From d88f977b85d251f548add3d0a76fc186f99b1b21 Mon Sep 17 00:00:00 2001 From: Todd Poynor Date: Wed, 20 Jul 2005 22:01:17 +0100 Subject: [MTD] CHIPS: Recognize Spansion CFI 1.4 chips Modify Amd/Fujitsu CFI NOR flash primary vendor extension table revision check to recognize version 1.4. Verified the existing driver can handle version 1.4 chips without additional info from 1.4 extended table. Move the primary vendor extension table revision check from common file to the 3 CFI chip driver files, since the data structures and revisions handled by those data structures are specific to the chip driver. Modify the error message printed when the revision is unknown to be a KERN_ERR instead of WARNING since this will cause mtd to ignore the chip. Signed-off-by: Todd Poynor Signed-off-by: Thomas Gleixner --- drivers/mtd/chips/cfi_cmdset_0001.c | 11 ++++++++++- drivers/mtd/chips/cfi_cmdset_0002.c | 12 +++++++++++- drivers/mtd/chips/cfi_cmdset_0020.c | 11 ++++++++++- drivers/mtd/chips/cfi_util.c | 11 +---------- 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 0cfcd88468e..1e99dffcc6a 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -4,7 +4,7 @@ * * (C) 2000 Red Hat. GPL'd * - * $Id: cfi_cmdset_0001.c,v 1.178 2005/05/19 17:05:43 nico Exp $ + * $Id: cfi_cmdset_0001.c,v 1.180 2005/07/20 21:01:13 tpoynor Exp $ * * * 10/10/2000 Nicolas Pitre @@ -252,6 +252,15 @@ read_pri_intelext(struct map_info *map, __u16 adr) if (!extp) return NULL; + if (extp->MajorVersion != '1' || + (extp->MinorVersion < '0' || extp->MinorVersion > '3')) { + printk(KERN_ERR " Unknown Intel/Sharp Extended Query " + "version %c.%c.\n", extp->MajorVersion, + extp->MinorVersion); + kfree(extp); + return NULL; + } + /* Do some byteswapping if necessary */ extp->FeatureSupport = le32_to_cpu(extp->FeatureSupport); extp->BlkStatusRegMask = le16_to_cpu(extp->BlkStatusRegMask); diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 8505f118f2d..e3d31c74904 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -17,7 +17,7 @@ * * This code is GPL * - * $Id: cfi_cmdset_0002.c,v 1.118 2005/07/04 22:34:29 gleixner Exp $ + * $Id: cfi_cmdset_0002.c,v 1.120 2005/07/20 21:01:13 tpoynor Exp $ * */ @@ -253,6 +253,16 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) return NULL; } + if (extp->MajorVersion != '1' || + (extp->MinorVersion < '0' || extp->MinorVersion > '4')) { + printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query " + "version %c.%c.\n", extp->MajorVersion, + extp->MinorVersion); + kfree(extp); + kfree(mtd); + return NULL; + } + /* Install our own private info structure */ cfi->cmdset_priv = extp; diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index c894f880157..d22df2d9678 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c @@ -4,7 +4,7 @@ * * (C) 2000 Red Hat. GPL'd * - * $Id: cfi_cmdset_0020.c,v 1.19 2005/07/13 15:52:45 dwmw2 Exp $ + * $Id: cfi_cmdset_0020.c,v 1.20 2005/07/20 21:01:14 tpoynor Exp $ * * 10/10/2000 Nicolas Pitre * - completely revamped method functions so they are aware and @@ -133,6 +133,15 @@ struct mtd_info *cfi_cmdset_0020(struct map_info *map, int primary) if (!extp) return NULL; + if (extp->MajorVersion != '1' || + (extp->MinorVersion < '0' || extp->MinorVersion > '3')) { + printk(KERN_ERR " Unknown ST Microelectronics" + " Extended Query version %c.%c.\n", + extp->MajorVersion, extp->MinorVersion); + kfree(extp); + return NULL; + } + /* Do some byteswapping if necessary */ extp->FeatureSupport = cfi32_to_cpu(extp->FeatureSupport); extp->BlkStatusRegMask = cfi32_to_cpu(extp->BlkStatusRegMask); diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c index 2b2ede2bfcc..0cf183f01e4 100644 --- a/drivers/mtd/chips/cfi_util.c +++ b/drivers/mtd/chips/cfi_util.c @@ -7,7 +7,7 @@ * * This code is covered by the GPL. * - * $Id: cfi_util.c,v 1.8 2004/12/14 19:55:56 nico Exp $ + * $Id: cfi_util.c,v 1.9 2005/07/20 21:01:14 tpoynor Exp $ * */ @@ -70,15 +70,6 @@ __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* n local_irq_enable(); #endif - if (extp->MajorVersion != '1' || - (extp->MinorVersion < '0' || extp->MinorVersion > '3')) { - printk(KERN_WARNING " Unknown %s Extended Query " - "version %c.%c.\n", name, extp->MajorVersion, - extp->MinorVersion); - kfree(extp); - extp = NULL; - } - out: return extp; } -- cgit v1.2.3 From 7ad2b7f5955f117bfca99c6b7cd7483d25f6a8af Mon Sep 17 00:00:00 2001 From: Todd Poynor Date: Fri, 29 Jul 2005 02:57:58 +0100 Subject: [MTD] mtd_blkdevs.c: Remove DEVFS leftovers Remove mtd_blkdevs refs to the no longer functional DEVFS filesystem. Verified mtdblock continues to work fine via udev with these calls removed. Signed-off-by: Todd Poynor Signed-off-by: Thomas Gleixner --- drivers/mtd/mtd_blkdevs.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index f8d2185819e..5d0e13d9f24 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -1,5 +1,5 @@ /* - * $Id: mtd_blkdevs.c,v 1.24 2004/11/16 18:28:59 dwmw2 Exp $ + * $Id: mtd_blkdevs.c,v 1.25 2005/07/29 01:57:55 tpoynor Exp $ * * (C) 2003 David Woodhouse * @@ -21,7 +21,6 @@ #include #include #include -#include static LIST_HEAD(blktrans_majors); @@ -292,8 +291,6 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) snprintf(gd->disk_name, sizeof(gd->disk_name), "%s%c", tr->name, (tr->part_bits?'a':'0') + new->devnum); - snprintf(gd->devfs_name, sizeof(gd->devfs_name), - "%s/%c", tr->name, (tr->part_bits?'a':'0') + new->devnum); /* 2.5 has capacity in units of 512 bytes while still having BLOCK_SIZE_BITS set to 10. Just to keep us amused. */ @@ -411,8 +408,6 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) return ret; } - devfs_mk_dir(tr->name); - INIT_LIST_HEAD(&tr->devs); list_add(&tr->list, &blktrans_majors); @@ -445,7 +440,6 @@ int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr) tr->remove_dev(dev); } - devfs_remove(tr->name); blk_cleanup_queue(tr->blkcore_priv->rq); unregister_blkdev(tr->major, tr->name); -- cgit v1.2.3 From 65a8de36b48f1c1cd02940c4480bc8e290540d18 Mon Sep 17 00:00:00 2001 From: Todd Poynor Date: Fri, 29 Jul 2005 20:42:07 +0100 Subject: [MTD] mtd_blkdevs.c: Fix names when many devices/partitions are created mtdblock (and other mtd modules that use the mtd_blkdevs interface between the mtd translation layers and the linux block layer) handles incorrectly more than 10 devices or 26 partitions in the names passed to the generic disk layer. This causes the device file names and other info kept by the generic disk/block layers to have names such as "mtdblock<". Use integer formatting for device numbers; use "aa-az" for partitions 27-52, "ba-bz" for 53-78... Signed-off-by: Todd Poynor Signed-off-by: Thomas Gleixner --- drivers/mtd/mtd_blkdevs.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 5d0e13d9f24..d6cb3d194ef 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -1,5 +1,5 @@ /* - * $Id: mtd_blkdevs.c,v 1.25 2005/07/29 01:57:55 tpoynor Exp $ + * $Id: mtd_blkdevs.c,v 1.26 2005/07/29 19:42:04 tpoynor Exp $ * * (C) 2003 David Woodhouse * @@ -289,8 +289,18 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) gd->first_minor = (new->devnum) << tr->part_bits; gd->fops = &mtd_blktrans_ops; - snprintf(gd->disk_name, sizeof(gd->disk_name), - "%s%c", tr->name, (tr->part_bits?'a':'0') + new->devnum); + if (tr->part_bits) + if (new->devnum < 26) + snprintf(gd->disk_name, sizeof(gd->disk_name), + "%s%c", tr->name, 'a' + new->devnum); + else + snprintf(gd->disk_name, sizeof(gd->disk_name), + "%s%c%c", tr->name, + 'a' - 1 + new->devnum / 26, + 'a' + new->devnum % 26); + else + snprintf(gd->disk_name, sizeof(gd->disk_name), + "%s%d", tr->name, new->devnum); /* 2.5 has capacity in units of 512 bytes while still having BLOCK_SIZE_BITS set to 10. Just to keep us amused. */ -- cgit v1.2.3 From 1da2c9a638f8af7be3daf1fa8dbd087b3284d16e Mon Sep 17 00:00:00 2001 From: Todd Poynor Date: Tue, 2 Aug 2005 21:36:09 +0100 Subject: [MTD] Pre-CFI Sharp chip driver: Some speedups and cleanups Remove useless udelay(100) after status value already read. Poll for status OK with reduced udelay if not immediate OK status return. Fix read and compare of 32-bit status value using 16-bit variable. Include slab.h since kmalloc/kfree are called. Signed-off-by: Todd Poynor Signed-off-by: Thomas Gleixner --- drivers/mtd/chips/sharp.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/chips/sharp.c b/drivers/mtd/chips/sharp.c index c3cf0f63bc9..08376dbf5d6 100644 --- a/drivers/mtd/chips/sharp.c +++ b/drivers/mtd/chips/sharp.c @@ -4,7 +4,7 @@ * Copyright 2000,2001 David A. Schleef * 2000,2001 Lineo, Inc. * - * $Id: sharp.c,v 1.14 2004/08/09 13:19:43 dwmw2 Exp $ + * $Id: sharp.c,v 1.15 2005/08/02 20:36:05 tpoynor Exp $ * * Devices supported: * LH28F016SCT Symmetrical block flash memory, 2Mx8 @@ -31,6 +31,7 @@ #include #include #include +#include #define CMD_RESET 0xffffffff #define CMD_READ_ID 0x90909090 @@ -214,7 +215,7 @@ static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd) /* This function returns with the chip->mutex lock held. */ static int sharp_wait(struct map_info *map, struct flchip *chip) { - __u16 status; + int status, i; unsigned long timeo = jiffies + HZ; DECLARE_WAITQUEUE(wait, current); int adr = 0; @@ -227,13 +228,11 @@ retry: map_write32(map,CMD_READ_STATUS,adr); chip->state = FL_STATUS; case FL_STATUS: - status = map_read32(map,adr); -//printk("status=%08x\n",status); - - udelay(100); - if((status & SR_READY)!=SR_READY){ -//printk(".status=%08x\n",status); - udelay(100); + for(i=0;i<100;i++){ + status = map_read32(map,adr); + if((status & SR_READY)==SR_READY) + break; + udelay(1); } break; default: -- cgit v1.2.3 From 8b491d750885ebe8e7d385ce4186c85957d67123 Mon Sep 17 00:00:00 2001 From: Todd Poynor Date: Thu, 4 Aug 2005 02:05:51 +0100 Subject: [MTD] mtdchar: Return EINVAL for bad seeks instead of fixing up to valid byte mtdchar return -EINVAL for seek prior to offset 0 or to beyond the last byte in the device/partition, similar to various other seek methods, instead of fixing up to first or last byte. Signed-off-by: Todd Poynor Signed-off-by: Thomas Gleixner --- drivers/mtd/mtdchar.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 1ed602a0f24..4b3c6263e7f 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -1,5 +1,5 @@ /* - * $Id: mtdchar.c,v 1.73 2005/07/04 17:36:41 gleixner Exp $ + * $Id: mtdchar.c,v 1.74 2005/08/04 01:05:48 tpoynor Exp $ * * Character-device access to raw MTD devices. * @@ -69,26 +69,23 @@ static loff_t mtd_lseek (struct file *file, loff_t offset, int orig) switch (orig) { case 0: /* SEEK_SET */ - file->f_pos = offset; break; case 1: /* SEEK_CUR */ - file->f_pos += offset; + offset += file->f_pos; break; case 2: /* SEEK_END */ - file->f_pos =mtd->size + offset; + offset += mtd->size; break; default: return -EINVAL; } - if (file->f_pos < 0) - file->f_pos = 0; - else if (file->f_pos >= mtd->size) - file->f_pos = mtd->size - 1; + if (offset >= 0 && offset < mtd->size) + return file->f_pos = offset; - return file->f_pos; + return -EINVAL; } -- cgit v1.2.3 From df8b59be0976c56820453730078bef99a8d1dbda Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 20 Sep 2005 12:39:35 -0700 Subject: [CPUFREQ] Avoid the ondemand cpufreq governor to use a too high frequency for stats. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The problem is in the ondemand governor, there is a periodic measurement of the CPU usage. This CPU usage is updated by the scheduler after every tick (basically, by adding 1 either to "idle" or to "user" or to "system"). So if the frequency of the governor is too high, the stat will be meaningless (as mostly no number have changed). So this patch checks that the measurements are separated by at least 10 ticks. It means that by default, stats will have about 5% error (20 ticks). Of course those numbers can be argued but, IMHO, they look sane. The patch also includes a small clean-up to check more explictly the result of the conversion from ns to µs being null. Let's note that (on x86) this has never been really needed before 2.6.13 because HZ was always 1000. Now that HZ can be 100, some CPU might be affected by this problem. For instance when HZ=100, the centrino ,which has a 10µs transition latency, would lead to the governor allowing to read stats every tick (10ms)! Signed-off-by: Eric Piel Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_ondemand.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index c1fc9c62bb5..17741111246 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -48,7 +48,10 @@ * All times here are in uS. */ static unsigned int def_sampling_rate; -#define MIN_SAMPLING_RATE (def_sampling_rate / 2) +#define MIN_SAMPLING_RATE_RATIO (2) +/* for correct statistics, we need at least 10 ticks between each measure */ +#define MIN_STAT_SAMPLING_RATE (MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10)) +#define MIN_SAMPLING_RATE (def_sampling_rate / MIN_SAMPLING_RATE_RATIO) #define MAX_SAMPLING_RATE (500 * def_sampling_rate) #define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000) #define DEF_SAMPLING_DOWN_FACTOR (1) @@ -416,13 +419,16 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, if (dbs_enable == 1) { unsigned int latency; /* policy latency is in nS. Convert it to uS first */ + latency = policy->cpuinfo.transition_latency / 1000; + if (latency == 0) + latency = 1; - latency = policy->cpuinfo.transition_latency; - if (latency < 1000) - latency = 1000; - - def_sampling_rate = (latency / 1000) * + def_sampling_rate = latency * DEF_SAMPLING_RATE_LATENCY_MULTIPLIER; + + if (def_sampling_rate < MIN_STAT_SAMPLING_RATE) + def_sampling_rate = MIN_STAT_SAMPLING_RATE; + dbs_tuners_ins.sampling_rate = def_sampling_rate; dbs_tuners_ins.ignore_nice = 0; -- cgit v1.2.3 From b9111b7b7f46b0ec1ccb451d60ec439b92e4df65 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 23 Sep 2005 11:10:42 -0700 Subject: [CPUFREQ] Remove preempt_disable from powernow-k8 Via reading the code, my understanding is that powernow-k8 uses preempt_disable to ensure that driver->target doesn't migrate across cpus whilst it's accessing per processor registers, however set_cpus_allowed will provide this for us. Additionally, remove schedule() calls from set_cpus_allowed as set_cpus_allowed ensures that you're executing on the target processor on return. Signed-off-by: Zwane Mwaikambo Signed-off-by: Andrew Morton Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index ab6e0611303..e2e03eebedf 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -453,7 +453,6 @@ static int check_supported_cpu(unsigned int cpu) oldmask = current->cpus_allowed; set_cpus_allowed(current, cpumask_of_cpu(cpu)); - schedule(); if (smp_processor_id() != cpu) { printk(KERN_ERR "limiting to cpu %u failed\n", cpu); @@ -488,9 +487,7 @@ static int check_supported_cpu(unsigned int cpu) out: set_cpus_allowed(current, oldmask); - schedule(); return rc; - } static int check_pst_table(struct powernow_k8_data *data, struct pst_s *pst, u8 maxvid) @@ -904,7 +901,6 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi /* only run on specific CPU from here on */ oldmask = current->cpus_allowed; set_cpus_allowed(current, cpumask_of_cpu(pol->cpu)); - schedule(); if (smp_processor_id() != pol->cpu) { printk(KERN_ERR "limiting to cpu %u failed\n", pol->cpu); @@ -959,8 +955,6 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi err_out: set_cpus_allowed(current, oldmask); - schedule(); - return ret; } @@ -1017,7 +1011,6 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol) /* only run on specific CPU from here on */ oldmask = current->cpus_allowed; set_cpus_allowed(current, cpumask_of_cpu(pol->cpu)); - schedule(); if (smp_processor_id() != pol->cpu) { printk(KERN_ERR "limiting to cpu %u failed\n", pol->cpu); @@ -1036,7 +1029,6 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol) /* run on any CPU again */ set_cpus_allowed(current, oldmask); - schedule(); pol->governor = CPUFREQ_DEFAULT_GOVERNOR; pol->cpus = cpu_core_map[pol->cpu]; @@ -1071,7 +1063,6 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol) err_out: set_cpus_allowed(current, oldmask); - schedule(); powernow_k8_cpu_exit_acpi(data); kfree(data); @@ -1107,17 +1098,14 @@ static unsigned int powernowk8_get (unsigned int cpu) set_cpus_allowed(current, oldmask); return 0; } - preempt_disable(); - + if (query_current_values_with_pending_wait(data)) goto out; khz = find_khz_freq_from_fid(data->currfid); - out: - preempt_enable_no_resched(); +out: set_cpus_allowed(current, oldmask); - return khz; } -- cgit v1.2.3 From 0ff541dafdcb9bc8933e7e4881e5924a408b5335 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 23 Sep 2005 15:59:37 -0700 Subject: [AGPGART] Fix serverworks TLB flush. Go back to what 2.4 kernels used to do here, as if this hits, the kernel just hangs indefinitly. Actually an improvement over 2.4 - we now break; out of the loop instead of just printing messages on timeouts. Signed-off-by: Dave Jones --- drivers/char/agp/sworks-agp.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index a9fb12c20eb..53968973f89 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c @@ -242,13 +242,27 @@ static int serverworks_fetch_size(void) */ static void serverworks_tlbflush(struct agp_memory *temp) { + unsigned long timeout; + writeb(1, serverworks_private.registers+SVWRKS_POSTFLUSH); - while (readb(serverworks_private.registers+SVWRKS_POSTFLUSH) == 1) + timeout = jiffies + 3*HZ; + while (readb(serverworks_private.registers+SVWRKS_POSTFLUSH) == 1) { cpu_relax(); + if (time_after(jiffies, timeout)) { + printk(KERN_ERR PFX "TLB post flush took more than 3 seconds\n"); + break; + } + } writel(1, serverworks_private.registers+SVWRKS_DIRFLUSH); - while(readl(serverworks_private.registers+SVWRKS_DIRFLUSH) == 1) + timeout = jiffies + 3*HZ; + while (readl(serverworks_private.registers+SVWRKS_DIRFLUSH) == 1) { cpu_relax(); + if (time_after(jiffies, timeout)) { + printk(KERN_ERR PFX "TLB Dir flush took more than 3 seconds\n"); + break; + } + } } static int serverworks_configure(void) -- cgit v1.2.3 From 0ea27d9f2fb5b998063323bff47ab87891ced9e2 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 20 Oct 2005 15:12:16 -0700 Subject: [AGPGART] Replace kmalloc+memset's with kzalloc's Signed-off-by: Dave Jones --- drivers/char/agp/amd-k7-agp.c | 7 ++----- drivers/char/agp/ati-agp.c | 7 ++----- drivers/char/agp/backend.c | 6 +++--- drivers/char/agp/frontend.c | 15 ++++----------- drivers/char/agp/generic.c | 4 +--- drivers/char/agp/i460-agp.c | 6 ++---- drivers/char/agp/sworks-agp.c | 10 ++++------ 7 files changed, 18 insertions(+), 37 deletions(-) diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index 3a41672e4d6..1f776651ac6 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c @@ -94,19 +94,16 @@ static int amd_create_gatt_pages(int nr_tables) int retval = 0; int i; - tables = kmalloc((nr_tables + 1) * sizeof(struct amd_page_map *), - GFP_KERNEL); + tables = kzalloc((nr_tables + 1) * sizeof(struct amd_page_map *),GFP_KERNEL); if (tables == NULL) return -ENOMEM; - memset (tables, 0, sizeof(struct amd_page_map *) * (nr_tables + 1)); for (i = 0; i < nr_tables; i++) { - entry = kmalloc(sizeof(struct amd_page_map), GFP_KERNEL); + entry = kzalloc(sizeof(struct amd_page_map), GFP_KERNEL); if (entry == NULL) { retval = -ENOMEM; break; } - memset (entry, 0, sizeof(struct amd_page_map)); tables[i] = entry; retval = amd_create_page_map(entry); if (retval != 0) diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index e572ced9100..109582ab370 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c @@ -116,14 +116,12 @@ static int ati_create_gatt_pages(int nr_tables) int retval = 0; int i; - tables = kmalloc((nr_tables + 1) * sizeof(ati_page_map *), - GFP_KERNEL); + tables = kzalloc((nr_tables + 1) * sizeof(ati_page_map *),GFP_KERNEL); if (tables == NULL) return -ENOMEM; - memset(tables, 0, sizeof(ati_page_map *) * (nr_tables + 1)); for (i = 0; i < nr_tables; i++) { - entry = kmalloc(sizeof(ati_page_map), GFP_KERNEL); + entry = kzalloc(sizeof(ati_page_map), GFP_KERNEL); if (entry == NULL) { while (i>0) { kfree (tables[i-1]); @@ -134,7 +132,6 @@ static int ati_create_gatt_pages(int nr_tables) retval = -ENOMEM; break; } - memset(entry, 0, sizeof(ati_page_map)); tables[i] = entry; retval = ati_create_page_map(entry); if (retval != 0) break; diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index 82b43c541c8..73f333f491b 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c @@ -222,12 +222,12 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge) struct agp_bridge_data *agp_alloc_bridge(void) { - struct agp_bridge_data *bridge = kmalloc(sizeof(*bridge), GFP_KERNEL); - + struct agp_bridge_data *bridge; + + bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); if (!bridge) return NULL; - memset(bridge, 0, sizeof(*bridge)); atomic_set(&bridge->agp_in_use, 0); atomic_set(&bridge->current_memory_agp, 0); diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c index 3dfb6648547..17f520c9d47 100644 --- a/drivers/char/agp/frontend.c +++ b/drivers/char/agp/frontend.c @@ -189,13 +189,12 @@ static int agp_create_segment(struct agp_client *client, struct agp_region *regi struct agp_segment *user_seg; size_t i; - seg = kmalloc((sizeof(struct agp_segment_priv) * region->seg_count), GFP_KERNEL); + seg = kzalloc((sizeof(struct agp_segment_priv) * region->seg_count), GFP_KERNEL); if (seg == NULL) { kfree(region->seg_list); region->seg_list = NULL; return -ENOMEM; } - memset(seg, 0, (sizeof(struct agp_segment_priv) * region->seg_count)); user_seg = region->seg_list; for (i = 0; i < region->seg_count; i++) { @@ -332,14 +331,11 @@ static struct agp_controller *agp_create_controller(pid_t id) { struct agp_controller *controller; - controller = kmalloc(sizeof(struct agp_controller), GFP_KERNEL); - + controller = kzalloc(sizeof(struct agp_controller), GFP_KERNEL); if (controller == NULL) return NULL; - memset(controller, 0, sizeof(struct agp_controller)); controller->pid = id; - return controller; } @@ -540,12 +536,10 @@ static struct agp_client *agp_create_client(pid_t id) { struct agp_client *new_client; - new_client = kmalloc(sizeof(struct agp_client), GFP_KERNEL); - + new_client = kzalloc(sizeof(struct agp_client), GFP_KERNEL); if (new_client == NULL) return NULL; - memset(new_client, 0, sizeof(struct agp_client)); new_client->pid = id; agp_insert_client(new_client); return new_client; @@ -709,11 +703,10 @@ static int agp_open(struct inode *inode, struct file *file) if (minor != AGPGART_MINOR) goto err_out; - priv = kmalloc(sizeof(struct agp_file_private), GFP_KERNEL); + priv = kzalloc(sizeof(struct agp_file_private), GFP_KERNEL); if (priv == NULL) goto err_out_nomem; - memset(priv, 0, sizeof(struct agp_file_private)); set_bit(AGP_FF_ALLOW_CLIENT, &priv->access_flags); priv->my_pid = current->pid; diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index ac9da0ca36b..b0f2a6faf67 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -105,12 +105,10 @@ struct agp_memory *agp_create_memory(int scratch_pages) { struct agp_memory *new; - new = kmalloc(sizeof(struct agp_memory), GFP_KERNEL); - + new = kzalloc(sizeof(struct agp_memory), GFP_KERNEL); if (new == NULL) return NULL; - memset(new, 0, sizeof(struct agp_memory)); new->key = agp_get_key(); if (new->key < 0) { diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c index 94943298c03..75acb960558 100644 --- a/drivers/char/agp/i460-agp.c +++ b/drivers/char/agp/i460-agp.c @@ -225,10 +225,9 @@ static int i460_configure (void) */ if (I460_IO_PAGE_SHIFT > PAGE_SHIFT) { size = current_size->num_entries * sizeof(i460.lp_desc[0]); - i460.lp_desc = kmalloc(size, GFP_KERNEL); + i460.lp_desc = kzalloc(size, GFP_KERNEL); if (!i460.lp_desc) return -ENOMEM; - memset(i460.lp_desc, 0, size); } return 0; } @@ -364,13 +363,12 @@ static int i460_alloc_large_page (struct lp_desc *lp) } map_size = ((I460_KPAGES_PER_IOPAGE + BITS_PER_LONG - 1) & -BITS_PER_LONG)/8; - lp->alloced_map = kmalloc(map_size, GFP_KERNEL); + lp->alloced_map = kzalloc(map_size, GFP_KERNEL); if (!lp->alloced_map) { free_pages((unsigned long) lpage, order); printk(KERN_ERR PFX "Out of memory, we're in trouble...\n"); return -ENOMEM; } - memset(lp->alloced_map, 0, map_size); lp->paddr = virt_to_gart(lpage); lp->refcount = 0; diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index 53968973f89..161d22b67fa 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c @@ -100,19 +100,17 @@ static int serverworks_create_gatt_pages(int nr_tables) int retval = 0; int i; - tables = kmalloc((nr_tables + 1) * sizeof(struct serverworks_page_map *), + tables = kzalloc((nr_tables + 1) * sizeof(struct serverworks_page_map *), GFP_KERNEL); - if (tables == NULL) { + if (tables == NULL) return -ENOMEM; - } - memset(tables, 0, sizeof(struct serverworks_page_map *) * (nr_tables + 1)); + for (i = 0; i < nr_tables; i++) { - entry = kmalloc(sizeof(struct serverworks_page_map), GFP_KERNEL); + entry = kzalloc(sizeof(struct serverworks_page_map), GFP_KERNEL); if (entry == NULL) { retval = -ENOMEM; break; } - memset(entry, 0, sizeof(struct serverworks_page_map)); tables[i] = entry; retval = serverworks_create_page_map(entry); if (retval != 0) break; -- cgit v1.2.3 From bfdc708dc7d26fca66df0157b36356a2ba6166eb Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 20 Oct 2005 15:16:15 -0700 Subject: [CPUFREQ] kzalloc conversions for i386 drivers. Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c | 3 +-- arch/i386/kernel/cpu/cpufreq/powernow-k7.c | 12 +++--------- arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 3 +-- arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c | 3 +-- 4 files changed, 6 insertions(+), 15 deletions(-) diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c index 822c8ce9d1f..22b5622897f 100644 --- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -376,10 +376,9 @@ acpi_cpufreq_cpu_init ( arg0.buffer.length = 12; arg0.buffer.pointer = (u8 *) arg0_buf; - data = kmalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL); + data = kzalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL); if (!data) return (-ENOMEM); - memset(data, 0, sizeof(struct cpufreq_acpi_io)); acpi_io_data[cpu] = data; diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c index 73a5dc5b26b..edcd626001d 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c @@ -171,10 +171,9 @@ static int get_ranges (unsigned char *pst) unsigned int speed; u8 fid, vid; - powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table) * (number_scales + 1)), GFP_KERNEL); + powernow_table = kzalloc((sizeof(struct cpufreq_frequency_table) * (number_scales + 1)), GFP_KERNEL); if (!powernow_table) return -ENOMEM; - memset(powernow_table, 0, (sizeof(struct cpufreq_frequency_table) * (number_scales + 1))); for (j=0 ; j < number_scales; j++) { fid = *pst++; @@ -305,16 +304,13 @@ static int powernow_acpi_init(void) goto err0; } - acpi_processor_perf = kmalloc(sizeof(struct acpi_processor_performance), + acpi_processor_perf = kzalloc(sizeof(struct acpi_processor_performance), GFP_KERNEL); - if (!acpi_processor_perf) { retval = -ENOMEM; goto err0; } - memset(acpi_processor_perf, 0, sizeof(struct acpi_processor_performance)); - if (acpi_processor_register_performance(acpi_processor_perf, 0)) { retval = -EIO; goto err1; @@ -337,14 +333,12 @@ static int powernow_acpi_init(void) goto err2; } - powernow_table = kmalloc((number_scales + 1) * (sizeof(struct cpufreq_frequency_table)), GFP_KERNEL); + powernow_table = kzalloc((number_scales + 1) * (sizeof(struct cpufreq_frequency_table)), GFP_KERNEL); if (!powernow_table) { retval = -ENOMEM; goto err2; } - memset(powernow_table, 0, ((number_scales + 1) * sizeof(struct cpufreq_frequency_table))); - pc.val = (unsigned long) acpi_processor_perf->states[0].control; for (i = 0; i < number_scales; i++) { u8 fid, vid; diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index e2e03eebedf..beb101157bd 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -976,12 +976,11 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol) if (!check_supported_cpu(pol->cpu)) return -ENODEV; - data = kmalloc(sizeof(struct powernow_k8_data), GFP_KERNEL); + data = kzalloc(sizeof(struct powernow_k8_data), GFP_KERNEL); if (!data) { printk(KERN_ERR PFX "unable to alloc powernow_k8_data"); return -ENOMEM; } - memset(data,0,sizeof(struct powernow_k8_data)); data->cpu = pol->cpu; diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c index c397b622043..92936c1e173 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c @@ -422,12 +422,11 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy) } } - centrino_model[cpu] = kmalloc(sizeof(struct cpu_model), GFP_KERNEL); + centrino_model[cpu] = kzalloc(sizeof(struct cpu_model), GFP_KERNEL); if (!centrino_model[cpu]) { result = -ENOMEM; goto err_unreg; } - memset(centrino_model[cpu], 0, sizeof(struct cpu_model)); centrino_model[cpu]->model_name=NULL; centrino_model[cpu]->max_freq = p.states[0].core_frequency * 1000; -- cgit v1.2.3 From e98df50c5200ae3c748d69002a8827afc9d2eae2 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 20 Oct 2005 15:17:43 -0700 Subject: [CPUFREQ] kzalloc conversions for cpufreq core. Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq.c | 3 +-- drivers/cpufreq/cpufreq_stats.c | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 109d62ccf65..cfe1d0a2262 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -595,12 +595,11 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) goto module_out; } - policy = kmalloc(sizeof(struct cpufreq_policy), GFP_KERNEL); + policy = kzalloc(sizeof(struct cpufreq_policy), GFP_KERNEL); if (!policy) { ret = -ENOMEM; goto nomem_out; } - memset(policy, 0, sizeof(struct cpufreq_policy)); policy->cpu = cpu; policy->cpus = cpumask_of_cpu(cpu); diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 741b6b191e6..ff16a87125d 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -192,9 +192,8 @@ cpufreq_stats_create_table (struct cpufreq_policy *policy, unsigned int cpu = policy->cpu; if (cpufreq_stats_table[cpu]) return -EBUSY; - if ((stat = kmalloc(sizeof(struct cpufreq_stats), GFP_KERNEL)) == NULL) + if ((stat = kzalloc(sizeof(struct cpufreq_stats), GFP_KERNEL)) == NULL) return -ENOMEM; - memset(stat, 0, sizeof (struct cpufreq_stats)); data = cpufreq_cpu_get(cpu); if ((ret = sysfs_create_group(&data->kobj, &stats_attr_group))) @@ -216,12 +215,11 @@ cpufreq_stats_create_table (struct cpufreq_policy *policy, alloc_size += count * count * sizeof(int); #endif stat->max_state = count; - stat->time_in_state = kmalloc(alloc_size, GFP_KERNEL); + stat->time_in_state = kzalloc(alloc_size, GFP_KERNEL); if (!stat->time_in_state) { ret = -ENOMEM; goto error_out; } - memset(stat->time_in_state, 0, alloc_size); stat->freq_table = (unsigned int *)(stat->time_in_state + count); #ifdef CONFIG_CPU_FREQ_STAT_DETAILS -- cgit v1.2.3 From ea248bcaadd5bafe4217357e1e511ac55639bcf3 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 24 Oct 2005 20:20:11 -0700 Subject: [AGPGART] Set .owner field of struct pci_driver. From: Laurent Riffard This updates .owner field of struct pci_driver. This allows SYSFS to create the symlink from the driver to the module which provides it. $ tree /sys/bus/pci/drivers/agpgart-via/ /sys/bus/pci/drivers/agpgart-via/ |-- 0000:00:00.0 -> ../../../../devices/pci0000:00/0000:00:00.0 |-- bind |-- module -> ../../../../module/via_agp |-- new_id `-- unbind Signed-off-by: Laurent Riffard Signed-off-by: Dave Jones Signed-off-by: Andrew Morton --- drivers/char/agp/ali-agp.c | 1 + drivers/char/agp/amd-k7-agp.c | 1 + drivers/char/agp/amd64-agp.c | 1 + drivers/char/agp/ati-agp.c | 1 + drivers/char/agp/efficeon-agp.c | 1 + drivers/char/agp/i460-agp.c | 1 + drivers/char/agp/intel-agp.c | 1 + drivers/char/agp/nvidia-agp.c | 1 + drivers/char/agp/sis-agp.c | 1 + drivers/char/agp/sworks-agp.c | 1 + drivers/char/agp/uninorth-agp.c | 1 + drivers/char/agp/via-agp.c | 1 + 12 files changed, 12 insertions(+) diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c index 9c9c9c2247c..4de5dcb4251 100644 --- a/drivers/char/agp/ali-agp.c +++ b/drivers/char/agp/ali-agp.c @@ -388,6 +388,7 @@ static struct pci_device_id agp_ali_pci_table[] = { MODULE_DEVICE_TABLE(pci, agp_ali_pci_table); static struct pci_driver agp_ali_pci_driver = { + .owner = THIS_MODULE, .name = "agpgart-ali", .id_table = agp_ali_pci_table, .probe = agp_ali_probe, diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index 1f776651ac6..40fcd88b2ce 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c @@ -515,6 +515,7 @@ static struct pci_device_id agp_amdk7_pci_table[] = { MODULE_DEVICE_TABLE(pci, agp_amdk7_pci_table); static struct pci_driver agp_amdk7_pci_driver = { + .owner = THIS_MODULE, .name = "agpgart-amdk7", .id_table = agp_amdk7_pci_table, .probe = agp_amdk7_probe, diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 0a7624a9b1c..b954ddcecd3 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -701,6 +701,7 @@ static struct pci_device_id agp_amd64_pci_table[] = { MODULE_DEVICE_TABLE(pci, agp_amd64_pci_table); static struct pci_driver agp_amd64_pci_driver = { + .owner = THIS_MODULE, .name = "agpgart-amd64", .id_table = agp_amd64_pci_table, .probe = agp_amd64_probe, diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index 109582ab370..9e9ad8cbf29 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c @@ -519,6 +519,7 @@ static struct pci_device_id agp_ati_pci_table[] = { MODULE_DEVICE_TABLE(pci, agp_ati_pci_table); static struct pci_driver agp_ati_pci_driver = { + .owner = THIS_MODULE, .name = "agpgart-ati", .id_table = agp_ati_pci_table, .probe = agp_ati_probe, diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c index ac19fdcd21c..b64028abc1f 100644 --- a/drivers/char/agp/efficeon-agp.c +++ b/drivers/char/agp/efficeon-agp.c @@ -429,6 +429,7 @@ static struct pci_device_id agp_efficeon_pci_table[] = { MODULE_DEVICE_TABLE(pci, agp_efficeon_pci_table); static struct pci_driver agp_efficeon_pci_driver = { + .owner = THIS_MODULE, .name = "agpgart-efficeon", .id_table = agp_efficeon_pci_table, .probe = agp_efficeon_probe, diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c index 75acb960558..e2c616ba583 100644 --- a/drivers/char/agp/i460-agp.c +++ b/drivers/char/agp/i460-agp.c @@ -615,6 +615,7 @@ static struct pci_device_id agp_intel_i460_pci_table[] = { MODULE_DEVICE_TABLE(pci, agp_intel_i460_pci_table); static struct pci_driver agp_intel_i460_pci_driver = { + .owner = THIS_MODULE, .name = "agpgart-intel-i460", .id_table = agp_intel_i460_pci_table, .probe = agp_intel_i460_probe, diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 1f7d415f432..bf4cc9ffd5b 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -1824,6 +1824,7 @@ static struct pci_device_id agp_intel_pci_table[] = { MODULE_DEVICE_TABLE(pci, agp_intel_pci_table); static struct pci_driver agp_intel_pci_driver = { + .owner = THIS_MODULE, .name = "agpgart-intel", .id_table = agp_intel_pci_table, .probe = agp_intel_probe, diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c index 80dafa3030b..3aed0c5e2f9 100644 --- a/drivers/char/agp/nvidia-agp.c +++ b/drivers/char/agp/nvidia-agp.c @@ -398,6 +398,7 @@ static struct pci_device_id agp_nvidia_pci_table[] = { MODULE_DEVICE_TABLE(pci, agp_nvidia_pci_table); static struct pci_driver agp_nvidia_pci_driver = { + .owner = THIS_MODULE, .name = "agpgart-nvidia", .id_table = agp_nvidia_pci_table, .probe = agp_nvidia_probe, diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c index ebc05554045..a701361a889 100644 --- a/drivers/char/agp/sis-agp.c +++ b/drivers/char/agp/sis-agp.c @@ -332,6 +332,7 @@ static struct pci_device_id agp_sis_pci_table[] = { MODULE_DEVICE_TABLE(pci, agp_sis_pci_table); static struct pci_driver agp_sis_pci_driver = { + .owner = THIS_MODULE, .name = "agpgart-sis", .id_table = agp_sis_pci_table, .probe = agp_sis_probe, diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index 161d22b67fa..94a855e1c0b 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c @@ -543,6 +543,7 @@ static struct pci_device_id agp_serverworks_pci_table[] = { MODULE_DEVICE_TABLE(pci, agp_serverworks_pci_table); static struct pci_driver agp_serverworks_pci_driver = { + .owner = THIS_MODULE, .name = "agpgart-serverworks", .id_table = agp_serverworks_pci_table, .probe = agp_serverworks_probe, diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index c8255312b8c..183c50acab2 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c @@ -658,6 +658,7 @@ static struct pci_device_id agp_uninorth_pci_table[] = { MODULE_DEVICE_TABLE(pci, agp_uninorth_pci_table); static struct pci_driver agp_uninorth_pci_driver = { + .owner = THIS_MODULE, .name = "agpgart-uninorth", .id_table = agp_uninorth_pci_table, .probe = agp_uninorth_probe, diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c index c847df575cf..5d9a1370007 100644 --- a/drivers/char/agp/via-agp.c +++ b/drivers/char/agp/via-agp.c @@ -518,6 +518,7 @@ MODULE_DEVICE_TABLE(pci, agp_via_pci_table); static struct pci_driver agp_via_pci_driver = { + .owner = THIS_MODULE, .name = "agpgart-via", .id_table = agp_via_pci_table, .probe = agp_via_probe, -- cgit v1.2.3 From bc7b26fd7ca5e0c6e769d3886c022f0a98fd88ec Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 27 Oct 2005 16:02:06 -0700 Subject: [CPUFREQ] Check return value of cpufreq_cpu_get in cpufreq_stats This fixes an issue found in drivers/cpufreq/cpufreq_stats.c by Coverity. Error reported: CID: 2642 Checker: NULL_RETURNS (help) File: /export2/p4-coverity/mc2/linux26/drivers/cpufreq/cpufreq_stats.c Function: cpufreq_stats_create_table Description: Dereferencing NULL value "data" Patch description: The return of cpufreq_cpu_get can be NULL, check return code and return -EINVAL if it is NULL. Signed-off-by: Jayachandran C. Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_stats.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index ff16a87125d..19b4c3e7c39 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -196,6 +196,11 @@ cpufreq_stats_create_table (struct cpufreq_policy *policy, return -ENOMEM; data = cpufreq_cpu_get(cpu); + if (data == NULL) { + ret = -EINVAL; + goto error_get_fail; + } + if ((ret = sysfs_create_group(&data->kobj, &stats_attr_group))) goto error_out; -- cgit v1.2.3 From 631bb0e74e811e0d9ad23e7462a02d4767b4dd9d Mon Sep 17 00:00:00 2001 From: Bob Picco Date: Mon, 31 Oct 2005 13:25:25 -0500 Subject: [IA64] Recent SPARSEMEM and DISCONTIG changes break some builds My only objection to pfn_to_kaddr, which was introduced for HotPlug memory, is that all arches have an identical implementation. I haven't had a chance to pursue why yet. There is probably some arch issue I'm unaware of. Signed-off-by: Bob Picco Signed-off-by: Tony Luck --- include/asm-ia64/page.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h index ef436b9d06a..9d41548b7fe 100644 --- a/include/asm-ia64/page.h +++ b/include/asm-ia64/page.h @@ -120,6 +120,7 @@ extern unsigned long max_low_pfn; #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) +#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) typedef union ia64_va { struct { -- cgit v1.2.3 From dcc17d1baef3721d1574e5b2f4f2d4607514bcff Mon Sep 17 00:00:00 2001 From: Peter Keilty Date: Mon, 31 Oct 2005 16:44:47 -0500 Subject: [IA64] Use bitmaps for efficient context allocation/free Corrects the very inefficent method of finding free context_ids in get_mmu_context(). Instead of walking the task_list of all processes, 2 bitmaps are used to efficently store and lookup state, inuse and needs flushing. The entire rid address space is now used before calling wrap_mmu_context and global tlb flushing. Special thanks to Ken and Rohit for their review and modifications in using a bit flushmap. Signed-off-by: Peter Keilty Signed-off-by: Tony Luck --- arch/ia64/kernel/setup.c | 1 + arch/ia64/mm/tlb.c | 56 ++++++++++++++++++++---------------------- include/asm-ia64/mmu_context.h | 19 +++++++++++--- include/asm-ia64/tlbflush.h | 1 + 4 files changed, 44 insertions(+), 33 deletions(-) diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index fc56ca2da35..c9388a92cf4 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -454,6 +454,7 @@ setup_arch (char **cmdline_p) #endif cpu_init(); /* initialize the bootstrap CPU */ + mmu_context_init(); /* initialize context_id bitmap */ #ifdef CONFIG_ACPI acpi_boot_init(); diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c index c79a9b96d02..39628fca274 100644 --- a/arch/ia64/mm/tlb.c +++ b/arch/ia64/mm/tlb.c @@ -8,6 +8,8 @@ * Modified RID allocation for SMP * Goutham Rao * IPI based ptc implementation and A-step IPI implementation. + * Rohit Seth + * Ken Chen */ #include #include @@ -16,12 +18,14 @@ #include #include #include +#include #include #include #include #include #include +#include static struct { unsigned long mask; /* mask of supported purge page-sizes */ @@ -31,49 +35,43 @@ static struct { struct ia64_ctx ia64_ctx = { .lock = SPIN_LOCK_UNLOCKED, .next = 1, - .limit = (1 << 15) - 1, /* start out with the safe (architected) limit */ .max_ctx = ~0U }; DEFINE_PER_CPU(u8, ia64_need_tlb_flush); +/* + * Initializes the ia64_ctx.bitmap array based on max_ctx+1. + * Called after cpu_init() has setup ia64_ctx.max_ctx based on + * maximum RID that is supported by boot CPU. + */ +void __init +mmu_context_init (void) +{ + ia64_ctx.bitmap = alloc_bootmem((ia64_ctx.max_ctx+1)>>3); + ia64_ctx.flushmap = alloc_bootmem((ia64_ctx.max_ctx+1)>>3); +} + /* * Acquire the ia64_ctx.lock before calling this function! */ void wrap_mmu_context (struct mm_struct *mm) { - unsigned long tsk_context, max_ctx = ia64_ctx.max_ctx; - struct task_struct *tsk; int i; + unsigned long flush_bit; - if (ia64_ctx.next > max_ctx) - ia64_ctx.next = 300; /* skip daemons */ - ia64_ctx.limit = max_ctx + 1; - - /* - * Scan all the task's mm->context and set proper safe range - */ - - read_lock(&tasklist_lock); - repeat: - for_each_process(tsk) { - if (!tsk->mm) - continue; - tsk_context = tsk->mm->context; - if (tsk_context == ia64_ctx.next) { - if (++ia64_ctx.next >= ia64_ctx.limit) { - /* empty range: reset the range limit and start over */ - if (ia64_ctx.next > max_ctx) - ia64_ctx.next = 300; - ia64_ctx.limit = max_ctx + 1; - goto repeat; - } - } - if ((tsk_context > ia64_ctx.next) && (tsk_context < ia64_ctx.limit)) - ia64_ctx.limit = tsk_context; + for (i=0; i <= ia64_ctx.max_ctx / BITS_PER_LONG; i++) { + flush_bit = xchg(&ia64_ctx.flushmap[i], 0); + ia64_ctx.bitmap[i] ^= flush_bit; } - read_unlock(&tasklist_lock); + + /* use offset at 300 to skip daemons */ + ia64_ctx.next = find_next_zero_bit(ia64_ctx.bitmap, + ia64_ctx.max_ctx, 300); + ia64_ctx.limit = find_next_bit(ia64_ctx.bitmap, + ia64_ctx.max_ctx, ia64_ctx.next); + /* can't call flush_tlb_all() here because of race condition with O(1) scheduler [EF] */ { int cpu = get_cpu(); /* prevent preemption/migration */ diff --git a/include/asm-ia64/mmu_context.h b/include/asm-ia64/mmu_context.h index 8d6e72f7b08..8d9b30b5f7d 100644 --- a/include/asm-ia64/mmu_context.h +++ b/include/asm-ia64/mmu_context.h @@ -32,13 +32,17 @@ struct ia64_ctx { spinlock_t lock; unsigned int next; /* next context number to use */ - unsigned int limit; /* next >= limit => must call wrap_mmu_context() */ - unsigned int max_ctx; /* max. context value supported by all CPUs */ + unsigned int limit; /* available free range */ + unsigned int max_ctx; /* max. context value supported by all CPUs */ + /* call wrap_mmu_context when next >= max */ + unsigned long *bitmap; /* bitmap size is max_ctx+1 */ + unsigned long *flushmap;/* pending rid to be flushed */ }; extern struct ia64_ctx ia64_ctx; DECLARE_PER_CPU(u8, ia64_need_tlb_flush); +extern void mmu_context_init (void); extern void wrap_mmu_context (struct mm_struct *mm); static inline void @@ -83,9 +87,16 @@ get_mmu_context (struct mm_struct *mm) context = mm->context; if (context == 0) { cpus_clear(mm->cpu_vm_mask); - if (ia64_ctx.next >= ia64_ctx.limit) - wrap_mmu_context(mm); + if (ia64_ctx.next >= ia64_ctx.limit) { + ia64_ctx.next = find_next_zero_bit(ia64_ctx.bitmap, + ia64_ctx.max_ctx, ia64_ctx.next); + ia64_ctx.limit = find_next_bit(ia64_ctx.bitmap, + ia64_ctx.max_ctx, ia64_ctx.next); + if (ia64_ctx.next >= ia64_ctx.max_ctx) + wrap_mmu_context(mm); + } mm->context = context = ia64_ctx.next++; + __set_bit(context, ia64_ctx.bitmap); } } spin_unlock_irqrestore(&ia64_ctx.lock, flags); diff --git a/include/asm-ia64/tlbflush.h b/include/asm-ia64/tlbflush.h index b65c6270272..a35b323bae4 100644 --- a/include/asm-ia64/tlbflush.h +++ b/include/asm-ia64/tlbflush.h @@ -51,6 +51,7 @@ flush_tlb_mm (struct mm_struct *mm) if (!mm) return; + set_bit(mm->context, ia64_ctx.flushmap); mm->context = 0; if (atomic_read(&mm->mm_users) == 0) -- cgit v1.2.3 From 988a6490a793b73ff23aa3baf87b337152178e4d Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Mon, 31 Oct 2005 16:53:04 -0600 Subject: JFS: set i_ctime & i_mtime on target directory when creating links jfs has never been setting i_ctime or i_mtime when creating either hard or symbolic links. I'm surprised nobody had noticed until now. Thanks to Chris Spiegel for reporting the problem. Signed-off-by: Dave Kleikamp --- fs/jfs/namei.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 1abe7343f92..4abbe860430 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -827,6 +827,7 @@ static int jfs_link(struct dentry *old_dentry, /* update object inode */ ip->i_nlink++; /* for new link */ ip->i_ctime = CURRENT_TIME; + dir->i_ctime = dir->i_mtime = CURRENT_TIME; mark_inode_dirty(dir); atomic_inc(&ip->i_count); @@ -1024,6 +1025,8 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, insert_inode_hash(ip); mark_inode_dirty(ip); + dip->i_ctime = dip->i_mtime = CURRENT_TIME; + mark_inode_dirty(dip); /* * commit update of parent directory and link object */ -- cgit v1.2.3 From b7fb358c7c36a14927d5523ea674e69f90c51d1d Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 1 Nov 2005 23:13:45 -0800 Subject: [CPUFREQ] Fix up compile of cpufreq_stats Whoops, I lost a hunk of the last patch somehow. Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_stats.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 19b4c3e7c39..7ddf714c4d4 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -247,6 +247,7 @@ cpufreq_stats_create_table (struct cpufreq_policy *policy, return 0; error_out: cpufreq_cpu_put(data); +error_get_fail: kfree(stat); cpufreq_stats_table[cpu] = NULL; return ret; -- cgit v1.2.3 From cb9dbff92e4bd61851dd32864e78024e9f0a77d2 Mon Sep 17 00:00:00 2001 From: Steve French Date: Wed, 2 Nov 2005 11:37:15 -0800 Subject: [CIFS] Make CONFIG_CIFS_EXPERIMENTAL depend on CONFIG_EXPERIMENTAL It seems logical. Note that CONFIG_EXPERIMENTAL itself doesn't enable any code. Signed-off-by: Adrian Bunk Signed-off-by: Steve French --- fs/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/Kconfig b/fs/Kconfig index 01a295232f7..c9c4108469c 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -1639,7 +1639,7 @@ config CIFS_POSIX config CIFS_EXPERIMENTAL bool "CIFS Experimental Features (EXPERIMENTAL)" - depends on CIFS + depends on CIFS && EXPERIMENTAL help Enables cifs features under testing. These features are highly experimental. If unsure, say N. -- cgit v1.2.3 From 7afada45da2727fd96402b1244168e0420ca496a Mon Sep 17 00:00:00 2001 From: Ian Wienand Date: Wed, 2 Nov 2005 22:49:10 -0500 Subject: Input: convert dmasound_awacs (OSS) to dynamic input allocation Signed-off-by: Ian Wienand Signed-off-by: Dmitry Torokhov --- sound/oss/dmasound/dmasound_awacs.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c index b2bf8bac842..cebd881b91a 100644 --- a/sound/oss/dmasound/dmasound_awacs.c +++ b/sound/oss/dmasound/dmasound_awacs.c @@ -2805,16 +2805,7 @@ __init setup_beep(void) return 0 ; } -static struct input_dev awacs_beep_dev = { - .evbit = { BIT(EV_SND) }, - .sndbit = { BIT(SND_BELL) | BIT(SND_TONE) }, - .event = awacs_beep_event, - .name = "dmasound beeper", - .phys = "macio/input0", /* what the heck is this?? */ - .id = { - .bustype = BUS_HOST, - }, -}; +static struct input_dev *awacs_beep_dev; int __init dmasound_awacs_init(void) { @@ -2907,6 +2898,22 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n"); return -ENODEV; } + awacs_beep_dev = input_allocate_device(); + if (!awacs_beep_dev) { + release_OF_resource(io, 0); + release_OF_resource(io, 1); + release_OF_resource(io, 2); + printk(KERN_ERR "dmasound: can't allocate input device !\n"); + return -ENOMEM; + } + + awacs_beep_dev->name = "dmasound beeper"; + awacs_beep_dev->phys = "macio/input0"; + awacs_beep_dev->id.bustype = BUS_HOST; + awacs_beep_dev->event = awacs_beep_event; + awacs_beep_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); + awacs_beep_dev->evbit[0] = BIT(EV_SND); + /* all OF versions I've seen use this value */ if (i2s_node) i2s = ioremap(io->addrs[0].address, 0x1000); @@ -3140,14 +3147,14 @@ printk("dmasound_pmac: Awacs/Screamer Codec Mfct: %d Rev %d\n", mfg, rev); * XXX: we should handle errors here, but that would mean * rewriting the whole init code. later.. */ - input_register_device(&awacs_beep_dev); + input_register_device(awacs_beep_dev); return dmasound_init(); } static void __exit dmasound_awacs_cleanup(void) { - input_unregister_device(&awacs_beep_dev); + input_unregister_device(awacs_beep_dev); switch (awacs_revision) { case AWACS_TUMBLER: -- cgit v1.2.3 From 438c9da5143c6a563c5c684b91eb7848a7b2d83d Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 2 Nov 2005 22:49:53 -0500 Subject: Input: locomokbd - convert to dynamic input allocation Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/locomokbd.c | 63 +++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c index 8935290256b..a6ddd947260 100644 --- a/drivers/input/keyboard/locomokbd.c +++ b/drivers/input/keyboard/locomokbd.c @@ -76,7 +76,7 @@ static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = { struct locomokbd { unsigned char keycode[LOCOMOKBD_NUMKEYS]; - struct input_dev input; + struct input_dev *input; char phys[32]; struct locomo_dev *ldev; @@ -136,8 +136,7 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs * spin_lock_irqsave(&locomokbd->lock, flags); - if (regs) - input_regs(&locomokbd->input, regs); + input_regs(locomokbd->input, regs); locomokbd_charge_all(membase); @@ -152,16 +151,16 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs * scancode = SCANCODE(col, row); if (rowd & KB_ROWMASK(row)) { num_pressed += 1; - input_report_key(&locomokbd->input, locomokbd->keycode[scancode], 1); + input_report_key(locomokbd->input, locomokbd->keycode[scancode], 1); } else { - input_report_key(&locomokbd->input, locomokbd->keycode[scancode], 0); + input_report_key(locomokbd->input, locomokbd->keycode[scancode], 0); } } locomokbd_reset_col(membase, col); } locomokbd_activate_all(membase); - input_sync(&locomokbd->input); + input_sync(locomokbd->input); /* if any keys are pressed, enable the timer */ if (num_pressed) @@ -196,13 +195,15 @@ static void locomokbd_timer_callback(unsigned long data) static int locomokbd_probe(struct locomo_dev *dev) { struct locomokbd *locomokbd; + struct input_dev *input_dev; int i, ret; - locomokbd = kmalloc(sizeof(struct locomokbd), GFP_KERNEL); - if (!locomokbd) - return -ENOMEM; - - memset(locomokbd, 0, sizeof(struct locomokbd)); + locomokbd = kzalloc(sizeof(struct locomokbd), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!locomokbd || !input_dev) { + ret = -ENOMEM; + goto free; + } /* try and claim memory region */ if (!request_mem_region((unsigned long) dev->mapbase, @@ -224,27 +225,26 @@ static int locomokbd_probe(struct locomo_dev *dev) locomokbd->timer.function = locomokbd_timer_callback; locomokbd->timer.data = (unsigned long) locomokbd; - locomokbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); + locomokbd->input = input_dev; + strcpy(locomokbd->phys, "locomokbd/input0"); + + input_dev->name = "LoCoMo keyboard"; + input_dev->phys = locomokbd->phys; + input_dev->id.bustype = BUS_XTKBD; + input_dev->id.vendor = 0x0001; + input_dev->id.product = 0x0001; + input_dev->id.version = 0x0100; + input_dev->private = locomokbd; - init_input_dev(&locomokbd->input); - locomokbd->input.keycode = locomokbd->keycode; - locomokbd->input.keycodesize = sizeof(unsigned char); - locomokbd->input.keycodemax = ARRAY_SIZE(locomokbd_keycode); - locomokbd->input.private = locomokbd; + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); + input_dev->keycode = locomokbd->keycode; + input_dev->keycodesize = sizeof(unsigned char); + input_dev->keycodemax = ARRAY_SIZE(locomokbd_keycode); memcpy(locomokbd->keycode, locomokbd_keycode, sizeof(locomokbd->keycode)); for (i = 0; i < LOCOMOKBD_NUMKEYS; i++) - set_bit(locomokbd->keycode[i], locomokbd->input.keybit); - clear_bit(0, locomokbd->input.keybit); - - strcpy(locomokbd->phys, "locomokbd/input0"); - - locomokbd->input.name = "LoCoMo keyboard"; - locomokbd->input.phys = locomokbd->phys; - locomokbd->input.id.bustype = BUS_XTKBD; - locomokbd->input.id.vendor = 0x0001; - locomokbd->input.id.product = 0x0001; - locomokbd->input.id.version = 0x0100; + set_bit(locomokbd->keycode[i], input_dev->keybit); + clear_bit(0, input_dev->keybit); /* attempt to get the interrupt */ ret = request_irq(dev->irq[0], locomokbd_interrupt, 0, "locomokbd", locomokbd); @@ -253,9 +253,7 @@ static int locomokbd_probe(struct locomo_dev *dev) goto out; } - input_register_device(&locomokbd->input); - - printk(KERN_INFO "input: LoCoMo keyboard on locomokbd\n"); + input_register_device(locomokbd->input); return 0; @@ -263,6 +261,7 @@ out: release_mem_region((unsigned long) dev->mapbase, dev->length); locomo_set_drvdata(dev, NULL); free: + input_free_device(input_dev); kfree(locomokbd); return ret; @@ -276,7 +275,7 @@ static int locomokbd_remove(struct locomo_dev *dev) del_timer_sync(&locomokbd->timer); - input_unregister_device(&locomokbd->input); + input_unregister_device(locomokbd->input); locomo_set_drvdata(dev, NULL); release_mem_region((unsigned long) dev->mapbase, dev->length); -- cgit v1.2.3 From 5f94548982ad8cb9867297e9e18e50ec7b8accea Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 2 Nov 2005 22:51:46 -0500 Subject: Input: do not register statically allocated devices Do not register statically allocated input devices to prevent OOPS when attaching input interfaces since it requires class device to be properly initialized. Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 26 +++++++++++++++----------- include/linux/input.h | 2 +- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/input/input.c b/drivers/input/input.c index 1a1654caedd..d543c0ce522 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -377,7 +377,7 @@ static int input_devices_read(char *buf, char **start, off_t pos, int count, int list_for_each_entry(dev, &input_dev_list, node) { - path = dev->dynalloc ? kobject_get_path(&dev->cdev.kobj, GFP_KERNEL) : NULL; + path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL); len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n", dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version); @@ -741,15 +741,21 @@ static void input_register_classdevice(struct input_dev *dev) sysfs_create_group(&dev->cdev.kobj, &input_dev_caps_attr_group); } -void input_register_device(struct input_dev *dev) +int input_register_device(struct input_dev *dev) { struct input_handle *handle; struct input_handler *handler; struct input_device_id *id; - set_bit(EV_SYN, dev->evbit); + if (!dev->dynalloc) { + printk(KERN_WARNING "input: device %s is statically allocated, will not register\n" + "Please convert to input_allocate_device() or contact dtor_core@ameritech.net\n", + dev->name ? dev->name : ""); + return -EINVAL; + } init_MUTEX(&dev->sem); + set_bit(EV_SYN, dev->evbit); /* * If delay and period are pre-set by the driver, then autorepeating @@ -767,8 +773,7 @@ void input_register_device(struct input_dev *dev) INIT_LIST_HEAD(&dev->h_list); list_add_tail(&dev->node, &input_dev_list); - if (dev->dynalloc) - input_register_classdevice(dev); + input_register_classdevice(dev); list_for_each_entry(handler, &input_handler_list, node) if (!handler->blacklist || !input_match_device(handler->blacklist, dev)) @@ -776,8 +781,9 @@ void input_register_device(struct input_dev *dev) if ((handle = handler->connect(handler, dev, id))) input_link_handle(handle); - input_wakeup_procfs_readers(); + + return 0; } void input_unregister_device(struct input_dev *dev) @@ -797,11 +803,9 @@ void input_unregister_device(struct input_dev *dev) list_del_init(&dev->node); - if (dev->dynalloc) { - sysfs_remove_group(&dev->cdev.kobj, &input_dev_caps_attr_group); - sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group); - class_device_unregister(&dev->cdev); - } + sysfs_remove_group(&dev->cdev.kobj, &input_dev_caps_attr_group); + sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group); + class_device_unregister(&dev->cdev); input_wakeup_procfs_readers(); } diff --git a/include/linux/input.h b/include/linux/input.h index f623c745c21..3c5823368dd 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -1007,7 +1007,7 @@ static inline void input_put_device(struct input_dev *dev) class_device_put(&dev->cdev); } -void input_register_device(struct input_dev *); +int input_register_device(struct input_dev *); void input_unregister_device(struct input_dev *); void input_register_handler(struct input_handler *); -- cgit v1.2.3 From 47610602c2ebe16ec99063b06bc019f18c8923a9 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 2 Nov 2005 22:52:16 -0500 Subject: Input: fix input device deregistration Remove main attribute group (name, phys, uniq) when unregistering input devices. Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/input.c b/drivers/input/input.c index d543c0ce522..0879915b14d 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -805,6 +805,7 @@ void input_unregister_device(struct input_dev *dev) sysfs_remove_group(&dev->cdev.kobj, &input_dev_caps_attr_group); sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group); + sysfs_remove_group(&dev->cdev.kobj, &input_dev_group); class_device_unregister(&dev->cdev); input_wakeup_procfs_readers(); -- cgit v1.2.3 From d7a767dddcbd690a6c0e2b3b395858dc116db2e6 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Wed, 2 Nov 2005 22:52:33 -0500 Subject: Input: locomokbd - fix wrong bustype Signed-off-by: Pavel Machek Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/locomokbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c index a6ddd947260..2c510881874 100644 --- a/drivers/input/keyboard/locomokbd.c +++ b/drivers/input/keyboard/locomokbd.c @@ -230,7 +230,7 @@ static int locomokbd_probe(struct locomo_dev *dev) input_dev->name = "LoCoMo keyboard"; input_dev->phys = locomokbd->phys; - input_dev->id.bustype = BUS_XTKBD; + input_dev->id.bustype = BUS_HOST; input_dev->id.vendor = 0x0001; input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; -- cgit v1.2.3 From 14a48b444420908cf8f87be12f5c94fb9ab16673 Mon Sep 17 00:00:00 2001 From: Mirco Macrelli Date: Wed, 2 Nov 2005 22:52:45 -0500 Subject: Input: logips2pp - add support for MX3100 Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/logips2pp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index 0f69ff46c1a..31a59f7abfa 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c @@ -217,6 +217,9 @@ static struct ps2pp_info *get_model_info(unsigned char model) { 61, PS2PP_KIND_MX, /* MX700 */ PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN | PS2PP_EXTRA_BTN | PS2PP_NAV_BTN }, + { 66, PS2PP_KIND_MX, /* MX3100 reciver */ + PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN | + PS2PP_EXTRA_BTN | PS2PP_NAV_BTN | PS2PP_HWHEEL }, { 73, 0, PS2PP_SIDE_BTN }, { 75, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, { 76, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, -- cgit v1.2.3 From 0aeafa77558fc1b44b0f39a4d9e5bd9316420788 Mon Sep 17 00:00:00 2001 From: Jan-Benedict Glaw Date: Wed, 2 Nov 2005 22:53:11 -0500 Subject: Input: lkkbd - miscellaneous fixes * Hide debugging code into #ifdef, which allows to simplify the large switch statement * Update macros to not reference variables not given as arguments Signed-off-by: Jan-Benedict Glaw Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/lkkbd.c | 101 ++++++++++++++++++++++++----------------- 1 file changed, 59 insertions(+), 42 deletions(-) diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index 9481132532d..77c4d9669ad 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c @@ -273,11 +273,11 @@ static lk_keycode_t lkkbd_keycode[LK_NUM_KEYCODES] = { [0xfb] = KEY_APOSTROPHE, }; -#define CHECK_LED(LED, BITS) do { \ - if (test_bit (LED, lk->dev->led)) \ - leds_on |= BITS; \ - else \ - leds_off |= BITS; \ +#define CHECK_LED(LK, VAR_ON, VAR_OFF, LED, BITS) do { \ + if (test_bit (LED, (LK)->dev->led)) \ + VAR_ON |= BITS; \ + else \ + VAR_OFF |= BITS; \ } while (0) /* @@ -298,6 +298,42 @@ struct lkkbd { int ctrlclick_volume; }; +#ifdef LKKBD_DEBUG +/* + * Responses from the keyboard and mapping back to their names. + */ +static struct { + unsigned char value; + unsigned char *name; +} lk_response[] = { +#define RESPONSE(x) { .value = (x), .name = #x, } + RESPONSE (LK_STUCK_KEY), + RESPONSE (LK_SELFTEST_FAILED), + RESPONSE (LK_ALL_KEYS_UP), + RESPONSE (LK_METRONOME), + RESPONSE (LK_OUTPUT_ERROR), + RESPONSE (LK_INPUT_ERROR), + RESPONSE (LK_KBD_LOCKED), + RESPONSE (LK_KBD_TEST_MODE_ACK), + RESPONSE (LK_PREFIX_KEY_DOWN), + RESPONSE (LK_MODE_CHANGE_ACK), + RESPONSE (LK_RESPONSE_RESERVED), +#undef RESPONSE +}; + +static unsigned char * +response_name (unsigned char value) +{ + int i; + + for (i = 0; i < ARRAY_SIZE (lk_response); i++) + if (lk_response[i].value == value) + return lk_response[i].name; + + return ""; +} +#endif /* LKKBD_DEBUG */ + /* * Calculate volume parameter byte for a given volume. */ @@ -440,43 +476,24 @@ lkkbd_interrupt (struct serio *serio, unsigned char data, unsigned int flags, input_report_key (lk->dev, lk->keycode[i], 0); input_sync (lk->dev); break; - case LK_METRONOME: - DBG (KERN_INFO "Got LK_METRONOME and don't " - "know how to handle...\n"); + + case 0x01: + DBG (KERN_INFO "Got 0x01, scheduling re-initialization\n"); + lk->ignore_bytes = LK_NUM_IGNORE_BYTES; + lk->id[LK_NUM_IGNORE_BYTES - lk->ignore_bytes--] = data; + schedule_work (&lk->tq); break; + + case LK_METRONOME: case LK_OUTPUT_ERROR: - DBG (KERN_INFO "Got LK_OUTPUT_ERROR and don't " - "know how to handle...\n"); - break; case LK_INPUT_ERROR: - DBG (KERN_INFO "Got LK_INPUT_ERROR and don't " - "know how to handle...\n"); - break; case LK_KBD_LOCKED: - DBG (KERN_INFO "Got LK_KBD_LOCKED and don't " - "know how to handle...\n"); - break; case LK_KBD_TEST_MODE_ACK: - DBG (KERN_INFO "Got LK_KBD_TEST_MODE_ACK and don't " - "know how to handle...\n"); - break; case LK_PREFIX_KEY_DOWN: - DBG (KERN_INFO "Got LK_PREFIX_KEY_DOWN and don't " - "know how to handle...\n"); - break; case LK_MODE_CHANGE_ACK: - DBG (KERN_INFO "Got LK_MODE_CHANGE_ACK and ignored " - "it properly...\n"); - break; case LK_RESPONSE_RESERVED: - DBG (KERN_INFO "Got LK_RESPONSE_RESERVED and don't " - "know how to handle...\n"); - break; - case 0x01: - DBG (KERN_INFO "Got 0x01, scheduling re-initialization\n"); - lk->ignore_bytes = LK_NUM_IGNORE_BYTES; - lk->id[LK_NUM_IGNORE_BYTES - lk->ignore_bytes--] = data; - schedule_work (&lk->tq); + DBG (KERN_INFO "Got %s and don't know how to handle...\n", + response_name (data)); break; default: @@ -509,10 +526,10 @@ lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code, switch (type) { case EV_LED: - CHECK_LED (LED_CAPSL, LK_LED_SHIFTLOCK); - CHECK_LED (LED_COMPOSE, LK_LED_COMPOSE); - CHECK_LED (LED_SCROLLL, LK_LED_SCROLLLOCK); - CHECK_LED (LED_SLEEP, LK_LED_WAIT); + CHECK_LED (lk, leds_on, leds_off, LED_CAPSL, LK_LED_SHIFTLOCK); + CHECK_LED (lk, leds_on, leds_off, LED_COMPOSE, LK_LED_COMPOSE); + CHECK_LED (lk, leds_on, leds_off, LED_SCROLLL, LK_LED_SCROLLLOCK); + CHECK_LED (lk, leds_on, leds_off, LED_SLEEP, LK_LED_WAIT); if (leds_on != 0) { lk->serio->write (lk->serio, LK_CMD_LED_ON); lk->serio->write (lk->serio, leds_on); @@ -574,10 +591,10 @@ lkkbd_reinit (void *data) lk->serio->write (lk->serio, LK_CMD_SET_DEFAULTS); /* Set LEDs */ - CHECK_LED (LED_CAPSL, LK_LED_SHIFTLOCK); - CHECK_LED (LED_COMPOSE, LK_LED_COMPOSE); - CHECK_LED (LED_SCROLLL, LK_LED_SCROLLLOCK); - CHECK_LED (LED_SLEEP, LK_LED_WAIT); + CHECK_LED (lk, leds_on, leds_off, LED_CAPSL, LK_LED_SHIFTLOCK); + CHECK_LED (lk, leds_on, leds_off, LED_COMPOSE, LK_LED_COMPOSE); + CHECK_LED (lk, leds_on, leds_off, LED_SCROLLL, LK_LED_SCROLLLOCK); + CHECK_LED (lk, leds_on, leds_off, LED_SLEEP, LK_LED_WAIT); if (leds_on != 0) { lk->serio->write (lk->serio, LK_CMD_LED_ON); lk->serio->write (lk->serio, leds_on); -- cgit v1.2.3 From 58cd90829918dabbd81a453de676d41fb7b628ad Mon Sep 17 00:00:00 2001 From: "Chen, Kenneth W" Date: Sat, 29 Oct 2005 18:47:04 -0700 Subject: [IA64] make mmu_context.h and tlb.c 80-column friendly wrap_mmu_context(), delayed_tlb_flush(), get_mmu_context() all have an extra { } block which cause one extra indentation. get_mmu_context() is particularly bad with 5 indentations to the most inner "if". It finally gets on my nerve that I can't keep the code within 80 columns. Remove the extra { } block and while I'm at it, reformat all the comments to 80-column friendly. No functional change at all with this patch. Signed-off-by: Ken Chen Signed-off-by: Tony Luck --- arch/ia64/mm/tlb.c | 33 +++++++++-------- include/asm-ia64/mmu_context.h | 80 ++++++++++++++++++++++-------------------- 2 files changed, 59 insertions(+), 54 deletions(-) diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c index 39628fca274..41105d45442 100644 --- a/arch/ia64/mm/tlb.c +++ b/arch/ia64/mm/tlb.c @@ -29,7 +29,7 @@ static struct { unsigned long mask; /* mask of supported purge page-sizes */ - unsigned long max_bits; /* log2() of largest supported purge page-size */ + unsigned long max_bits; /* log2 of largest supported purge page-size */ } purge; struct ia64_ctx ia64_ctx = { @@ -58,7 +58,7 @@ mmu_context_init (void) void wrap_mmu_context (struct mm_struct *mm) { - int i; + int i, cpu; unsigned long flush_bit; for (i=0; i <= ia64_ctx.max_ctx / BITS_PER_LONG; i++) { @@ -72,20 +72,21 @@ wrap_mmu_context (struct mm_struct *mm) ia64_ctx.limit = find_next_bit(ia64_ctx.bitmap, ia64_ctx.max_ctx, ia64_ctx.next); - /* can't call flush_tlb_all() here because of race condition with O(1) scheduler [EF] */ - { - int cpu = get_cpu(); /* prevent preemption/migration */ - for_each_online_cpu(i) { - if (i != cpu) - per_cpu(ia64_need_tlb_flush, i) = 1; - } - put_cpu(); - } + /* + * can't call flush_tlb_all() here because of race condition + * with O(1) scheduler [EF] + */ + cpu = get_cpu(); /* prevent preemption/migration */ + for_each_online_cpu(i) + if (i != cpu) + per_cpu(ia64_need_tlb_flush, i) = 1; + put_cpu(); local_flush_tlb_all(); } void -ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long nbits) +ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start, + unsigned long end, unsigned long nbits) { static DEFINE_SPINLOCK(ptcg_lock); @@ -133,7 +134,8 @@ local_flush_tlb_all (void) } void -flush_tlb_range (struct vm_area_struct *vma, unsigned long start, unsigned long end) +flush_tlb_range (struct vm_area_struct *vma, unsigned long start, + unsigned long end) { struct mm_struct *mm = vma->vm_mm; unsigned long size = end - start; @@ -147,7 +149,8 @@ flush_tlb_range (struct vm_area_struct *vma, unsigned long start, unsigned long #endif nbits = ia64_fls(size + 0xfff); - while (unlikely (((1UL << nbits) & purge.mask) == 0) && (nbits < purge.max_bits)) + while (unlikely (((1UL << nbits) & purge.mask) == 0) && + (nbits < purge.max_bits)) ++nbits; if (nbits > purge.max_bits) nbits = purge.max_bits; @@ -189,5 +192,5 @@ ia64_tlb_init (void) local_cpu_data->ptce_stride[0] = ptce_info.stride[0]; local_cpu_data->ptce_stride[1] = ptce_info.stride[1]; - local_flush_tlb_all(); /* nuke left overs from bootstrapping... */ + local_flush_tlb_all(); /* nuke left overs from bootstrapping... */ } diff --git a/include/asm-ia64/mmu_context.h b/include/asm-ia64/mmu_context.h index 8d9b30b5f7d..b5c65081a3a 100644 --- a/include/asm-ia64/mmu_context.h +++ b/include/asm-ia64/mmu_context.h @@ -7,12 +7,13 @@ */ /* - * Routines to manage the allocation of task context numbers. Task context numbers are - * used to reduce or eliminate the need to perform TLB flushes due to context switches. - * Context numbers are implemented using ia-64 region ids. Since the IA-64 TLB does not - * consider the region number when performing a TLB lookup, we need to assign a unique - * region id to each region in a process. We use the least significant three bits in a - * region id for this purpose. + * Routines to manage the allocation of task context numbers. Task context + * numbers are used to reduce or eliminate the need to perform TLB flushes + * due to context switches. Context numbers are implemented using ia-64 + * region ids. Since the IA-64 TLB does not consider the region number when + * performing a TLB lookup, we need to assign a unique region id to each + * region in a process. We use the least significant three bits in aregion + * id for this purpose. */ #define IA64_REGION_ID_KERNEL 0 /* the kernel's region id (tlb.c depends on this being 0) */ @@ -51,10 +52,10 @@ enter_lazy_tlb (struct mm_struct *mm, struct task_struct *tsk) } /* - * When the context counter wraps around all TLBs need to be flushed because an old - * context number might have been reused. This is signalled by the ia64_need_tlb_flush - * per-CPU variable, which is checked in the routine below. Called by activate_mm(). - * + * When the context counter wraps around all TLBs need to be flushed because + * an old context number might have been reused. This is signalled by the + * ia64_need_tlb_flush per-CPU variable, which is checked in the routine + * below. Called by activate_mm(). */ static inline void delayed_tlb_flush (void) @@ -64,11 +65,9 @@ delayed_tlb_flush (void) if (unlikely(__ia64_per_cpu_var(ia64_need_tlb_flush))) { spin_lock_irqsave(&ia64_ctx.lock, flags); - { - if (__ia64_per_cpu_var(ia64_need_tlb_flush)) { - local_flush_tlb_all(); - __ia64_per_cpu_var(ia64_need_tlb_flush) = 0; - } + if (__ia64_per_cpu_var(ia64_need_tlb_flush)) { + local_flush_tlb_all(); + __ia64_per_cpu_var(ia64_need_tlb_flush) = 0; } spin_unlock_irqrestore(&ia64_ctx.lock, flags); } @@ -80,27 +79,27 @@ get_mmu_context (struct mm_struct *mm) unsigned long flags; nv_mm_context_t context = mm->context; - if (unlikely(!context)) { - spin_lock_irqsave(&ia64_ctx.lock, flags); - { - /* re-check, now that we've got the lock: */ - context = mm->context; - if (context == 0) { - cpus_clear(mm->cpu_vm_mask); - if (ia64_ctx.next >= ia64_ctx.limit) { - ia64_ctx.next = find_next_zero_bit(ia64_ctx.bitmap, - ia64_ctx.max_ctx, ia64_ctx.next); - ia64_ctx.limit = find_next_bit(ia64_ctx.bitmap, - ia64_ctx.max_ctx, ia64_ctx.next); - if (ia64_ctx.next >= ia64_ctx.max_ctx) - wrap_mmu_context(mm); - } - mm->context = context = ia64_ctx.next++; - __set_bit(context, ia64_ctx.bitmap); - } + if (likely(context)) + goto out; + + spin_lock_irqsave(&ia64_ctx.lock, flags); + /* re-check, now that we've got the lock: */ + context = mm->context; + if (context == 0) { + cpus_clear(mm->cpu_vm_mask); + if (ia64_ctx.next >= ia64_ctx.limit) { + ia64_ctx.next = find_next_zero_bit(ia64_ctx.bitmap, + ia64_ctx.max_ctx, ia64_ctx.next); + ia64_ctx.limit = find_next_bit(ia64_ctx.bitmap, + ia64_ctx.max_ctx, ia64_ctx.next); + if (ia64_ctx.next >= ia64_ctx.max_ctx) + wrap_mmu_context(mm); } - spin_unlock_irqrestore(&ia64_ctx.lock, flags); + mm->context = context = ia64_ctx.next++; + __set_bit(context, ia64_ctx.bitmap); } + spin_unlock_irqrestore(&ia64_ctx.lock, flags); +out: /* * Ensure we're not starting to use "context" before any old * uses of it are gone from our TLB. @@ -111,8 +110,8 @@ get_mmu_context (struct mm_struct *mm) } /* - * Initialize context number to some sane value. MM is guaranteed to be a brand-new - * address-space, so no TLB flushing is needed, ever. + * Initialize context number to some sane value. MM is guaranteed to be a + * brand-new address-space, so no TLB flushing is needed, ever. */ static inline int init_new_context (struct task_struct *p, struct mm_struct *mm) @@ -173,7 +172,10 @@ activate_context (struct mm_struct *mm) if (!cpu_isset(smp_processor_id(), mm->cpu_vm_mask)) cpu_set(smp_processor_id(), mm->cpu_vm_mask); reload_context(context); - /* in the unlikely event of a TLB-flush by another thread, redo the load: */ + /* + * in the unlikely event of a TLB-flush by another thread, + * redo the load. + */ } while (unlikely(context != mm->context)); } @@ -186,8 +188,8 @@ static inline void activate_mm (struct mm_struct *prev, struct mm_struct *next) { /* - * We may get interrupts here, but that's OK because interrupt handlers cannot - * touch user-space. + * We may get interrupts here, but that's OK because interrupt + * handlers cannot touch user-space. */ ia64_set_kr(IA64_KR_PT_BASE, __pa(next->pgd)); activate_context(next); -- cgit v1.2.3 From f79b348856fbaf77e4a0c5cb08a808e5879967a9 Mon Sep 17 00:00:00 2001 From: Dean Nelson Date: Tue, 1 Nov 2005 10:21:51 -0600 Subject: [IA64] restrict CONFIG_SGI_SN_XP to IA64_GENERIC or IA64_SGI_SN2 Restrict CONFIG_SGI_SN_XP to IA64_GENERIC or IA64_SGI_SN2 kernels. Signed-off-by: Dean Nelson Signed-off-by: Tony Luck --- arch/ia64/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 3b4248cff9a..eb784046130 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -191,6 +191,7 @@ config IOSAPIC config IA64_SGI_SN_XP tristate "Support communication between SGI SSIs" + depends on IA64_GENERIC || IA64_SGI_SN2 select IA64_UNCACHED_ALLOCATOR help An SGI machine can be divided into multiple Single System -- cgit v1.2.3 From 3a65dfe8c088143c7155cfd36a72f4b0ad2fc4b2 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 4 Nov 2005 08:43:35 +0100 Subject: [BLOCK] Move all core block layer code to new block/ directory drivers/block/ is right now a mix of core and driver parts. Lets move the core parts to a new top level directory. Al will move the fs/ related block parts to block/ next. Signed-off-by: Jens Axboe --- Makefile | 2 +- block/Kconfig | 14 + block/Kconfig.iosched | 69 + block/Makefile | 10 + block/as-iosched.c | 1985 +++++++++++++++++++++ block/cfq-iosched.c | 2428 +++++++++++++++++++++++++ block/deadline-iosched.c | 878 +++++++++ block/elevator.c | 802 +++++++++ block/genhd.c | 726 ++++++++ block/ioctl.c | 275 +++ block/ll_rw_blk.c | 3613 ++++++++++++++++++++++++++++++++++++++ block/noop-iosched.c | 46 + block/scsi_ioctl.c | 589 +++++++ drivers/block/Kconfig | 12 - drivers/block/Kconfig.iosched | 69 - drivers/block/Makefile | 14 - drivers/block/as-iosched.c | 1985 --------------------- drivers/block/cfq-iosched.c | 2428 ------------------------- drivers/block/deadline-iosched.c | 878 --------- drivers/block/elevator.c | 802 --------- drivers/block/genhd.c | 726 -------- drivers/block/ioctl.c | 275 --- drivers/block/ll_rw_blk.c | 3613 -------------------------------------- drivers/block/noop-iosched.c | 46 - drivers/block/scsi_ioctl.c | 589 ------- init/Kconfig | 4 + 26 files changed, 11440 insertions(+), 11438 deletions(-) create mode 100644 block/Kconfig create mode 100644 block/Kconfig.iosched create mode 100644 block/Makefile create mode 100644 block/as-iosched.c create mode 100644 block/cfq-iosched.c create mode 100644 block/deadline-iosched.c create mode 100644 block/elevator.c create mode 100644 block/genhd.c create mode 100644 block/ioctl.c create mode 100644 block/ll_rw_blk.c create mode 100644 block/noop-iosched.c create mode 100644 block/scsi_ioctl.c delete mode 100644 drivers/block/Kconfig.iosched delete mode 100644 drivers/block/as-iosched.c delete mode 100644 drivers/block/cfq-iosched.c delete mode 100644 drivers/block/deadline-iosched.c delete mode 100644 drivers/block/elevator.c delete mode 100644 drivers/block/genhd.c delete mode 100644 drivers/block/ioctl.c delete mode 100644 drivers/block/ll_rw_blk.c delete mode 100644 drivers/block/noop-iosched.c delete mode 100644 drivers/block/scsi_ioctl.c diff --git a/Makefile b/Makefile index 79601320ac3..a0270c5c3f3 100644 --- a/Makefile +++ b/Makefile @@ -582,7 +582,7 @@ export MODLIB ifeq ($(KBUILD_EXTMOD),) -core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ +core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \ $(core-y) $(core-m) $(drivers-y) $(drivers-m) \ diff --git a/block/Kconfig b/block/Kconfig new file mode 100644 index 00000000000..eb48edb80c1 --- /dev/null +++ b/block/Kconfig @@ -0,0 +1,14 @@ +# +# Block layer core configuration +# +#XXX - it makes sense to enable this only for 32-bit subarch's, not for x86_64 +#for instance. +config LBD + bool "Support for Large Block Devices" + depends on X86 || (MIPS && 32BIT) || PPC32 || ARCH_S390_31 || SUPERH || UML + help + Say Y here if you want to attach large (bigger than 2TB) discs to + your machine, or if you want to have a raid or loopback device + bigger than 2TB. Otherwise say N. + +source block/Kconfig.iosched diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched new file mode 100644 index 00000000000..5b90d2fa63b --- /dev/null +++ b/block/Kconfig.iosched @@ -0,0 +1,69 @@ + +menu "IO Schedulers" + +config IOSCHED_NOOP + bool + default y + ---help--- + The no-op I/O scheduler is a minimal scheduler that does basic merging + and sorting. Its main uses include non-disk based block devices like + memory devices, and specialised software or hardware environments + that do their own scheduling and require only minimal assistance from + the kernel. + +config IOSCHED_AS + tristate "Anticipatory I/O scheduler" + default y + ---help--- + The anticipatory I/O scheduler is the default disk scheduler. It is + generally a good choice for most environments, but is quite large and + complex when compared to the deadline I/O scheduler, it can also be + slower in some cases especially some database loads. + +config IOSCHED_DEADLINE + tristate "Deadline I/O scheduler" + default y + ---help--- + The deadline I/O scheduler is simple and compact, and is often as + good as the anticipatory I/O scheduler, and in some database + workloads, better. In the case of a single process performing I/O to + a disk at any one time, its behaviour is almost identical to the + anticipatory I/O scheduler and so is a good choice. + +config IOSCHED_CFQ + tristate "CFQ I/O scheduler" + default y + ---help--- + The CFQ I/O scheduler tries to distribute bandwidth equally + among all processes in the system. It should provide a fair + working environment, suitable for desktop systems. + +choice + prompt "Default I/O scheduler" + default DEFAULT_AS + help + Select the I/O scheduler which will be used by default for all + block devices. + + config DEFAULT_AS + bool "Anticipatory" if IOSCHED_AS + + config DEFAULT_DEADLINE + bool "Deadline" if IOSCHED_DEADLINE + + config DEFAULT_CFQ + bool "CFQ" if IOSCHED_CFQ + + config DEFAULT_NOOP + bool "No-op" + +endchoice + +config DEFAULT_IOSCHED + string + default "anticipatory" if DEFAULT_AS + default "deadline" if DEFAULT_DEADLINE + default "cfq" if DEFAULT_CFQ + default "noop" if DEFAULT_NOOP + +endmenu diff --git a/block/Makefile b/block/Makefile new file mode 100644 index 00000000000..7e4f93e2b44 --- /dev/null +++ b/block/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for the kernel block layer +# + +obj-y := elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o + +obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o +obj-$(CONFIG_IOSCHED_AS) += as-iosched.o +obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o +obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o diff --git a/block/as-iosched.c b/block/as-iosched.c new file mode 100644 index 00000000000..c6744ff3829 --- /dev/null +++ b/block/as-iosched.c @@ -0,0 +1,1985 @@ +/* + * linux/drivers/block/as-iosched.c + * + * Anticipatory & deadline i/o scheduler. + * + * Copyright (C) 2002 Jens Axboe + * Nick Piggin + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define REQ_SYNC 1 +#define REQ_ASYNC 0 + +/* + * See Documentation/block/as-iosched.txt + */ + +/* + * max time before a read is submitted. + */ +#define default_read_expire (HZ / 8) + +/* + * ditto for writes, these limits are not hard, even + * if the disk is capable of satisfying them. + */ +#define default_write_expire (HZ / 4) + +/* + * read_batch_expire describes how long we will allow a stream of reads to + * persist before looking to see whether it is time to switch over to writes. + */ +#define default_read_batch_expire (HZ / 2) + +/* + * write_batch_expire describes how long we want a stream of writes to run for. + * This is not a hard limit, but a target we set for the auto-tuning thingy. + * See, the problem is: we can send a lot of writes to disk cache / TCQ in + * a short amount of time... + */ +#define default_write_batch_expire (HZ / 8) + +/* + * max time we may wait to anticipate a read (default around 6ms) + */ +#define default_antic_expire ((HZ / 150) ? HZ / 150 : 1) + +/* + * Keep track of up to 20ms thinktimes. We can go as big as we like here, + * however huge values tend to interfere and not decay fast enough. A program + * might be in a non-io phase of operation. Waiting on user input for example, + * or doing a lengthy computation. A small penalty can be justified there, and + * will still catch out those processes that constantly have large thinktimes. + */ +#define MAX_THINKTIME (HZ/50UL) + +/* Bits in as_io_context.state */ +enum as_io_states { + AS_TASK_RUNNING=0, /* Process has not exitted */ + AS_TASK_IOSTARTED, /* Process has started some IO */ + AS_TASK_IORUNNING, /* Process has completed some IO */ +}; + +enum anticipation_status { + ANTIC_OFF=0, /* Not anticipating (normal operation) */ + ANTIC_WAIT_REQ, /* The last read has not yet completed */ + ANTIC_WAIT_NEXT, /* Currently anticipating a request vs + last read (which has completed) */ + ANTIC_FINISHED, /* Anticipating but have found a candidate + * or timed out */ +}; + +struct as_data { + /* + * run time data + */ + + struct request_queue *q; /* the "owner" queue */ + + /* + * requests (as_rq s) are present on both sort_list and fifo_list + */ + struct rb_root sort_list[2]; + struct list_head fifo_list[2]; + + struct as_rq *next_arq[2]; /* next in sort order */ + sector_t last_sector[2]; /* last REQ_SYNC & REQ_ASYNC sectors */ + struct list_head *hash; /* request hash */ + + unsigned long exit_prob; /* probability a task will exit while + being waited on */ + unsigned long new_ttime_total; /* mean thinktime on new proc */ + unsigned long new_ttime_mean; + u64 new_seek_total; /* mean seek on new proc */ + sector_t new_seek_mean; + + unsigned long current_batch_expires; + unsigned long last_check_fifo[2]; + int changed_batch; /* 1: waiting for old batch to end */ + int new_batch; /* 1: waiting on first read complete */ + int batch_data_dir; /* current batch REQ_SYNC / REQ_ASYNC */ + int write_batch_count; /* max # of reqs in a write batch */ + int current_write_count; /* how many requests left this batch */ + int write_batch_idled; /* has the write batch gone idle? */ + mempool_t *arq_pool; + + enum anticipation_status antic_status; + unsigned long antic_start; /* jiffies: when it started */ + struct timer_list antic_timer; /* anticipatory scheduling timer */ + struct work_struct antic_work; /* Deferred unplugging */ + struct io_context *io_context; /* Identify the expected process */ + int ioc_finished; /* IO associated with io_context is finished */ + int nr_dispatched; + + /* + * settings that change how the i/o scheduler behaves + */ + unsigned long fifo_expire[2]; + unsigned long batch_expire[2]; + unsigned long antic_expire; +}; + +#define list_entry_fifo(ptr) list_entry((ptr), struct as_rq, fifo) + +/* + * per-request data. + */ +enum arq_state { + AS_RQ_NEW=0, /* New - not referenced and not on any lists */ + AS_RQ_QUEUED, /* In the request queue. It belongs to the + scheduler */ + AS_RQ_DISPATCHED, /* On the dispatch list. It belongs to the + driver now */ + AS_RQ_PRESCHED, /* Debug poisoning for requests being used */ + AS_RQ_REMOVED, + AS_RQ_MERGED, + AS_RQ_POSTSCHED, /* when they shouldn't be */ +}; + +struct as_rq { + /* + * rbtree index, key is the starting offset + */ + struct rb_node rb_node; + sector_t rb_key; + + struct request *request; + + struct io_context *io_context; /* The submitting task */ + + /* + * request hash, key is the ending offset (for back merge lookup) + */ + struct list_head hash; + unsigned int on_hash; + + /* + * expire fifo + */ + struct list_head fifo; + unsigned long expires; + + unsigned int is_sync; + enum arq_state state; +}; + +#define RQ_DATA(rq) ((struct as_rq *) (rq)->elevator_private) + +static kmem_cache_t *arq_pool; + +/* + * IO Context helper functions + */ + +/* Called to deallocate the as_io_context */ +static void free_as_io_context(struct as_io_context *aic) +{ + kfree(aic); +} + +/* Called when the task exits */ +static void exit_as_io_context(struct as_io_context *aic) +{ + WARN_ON(!test_bit(AS_TASK_RUNNING, &aic->state)); + clear_bit(AS_TASK_RUNNING, &aic->state); +} + +static struct as_io_context *alloc_as_io_context(void) +{ + struct as_io_context *ret; + + ret = kmalloc(sizeof(*ret), GFP_ATOMIC); + if (ret) { + ret->dtor = free_as_io_context; + ret->exit = exit_as_io_context; + ret->state = 1 << AS_TASK_RUNNING; + atomic_set(&ret->nr_queued, 0); + atomic_set(&ret->nr_dispatched, 0); + spin_lock_init(&ret->lock); + ret->ttime_total = 0; + ret->ttime_samples = 0; + ret->ttime_mean = 0; + ret->seek_total = 0; + ret->seek_samples = 0; + ret->seek_mean = 0; + } + + return ret; +} + +/* + * If the current task has no AS IO context then create one and initialise it. + * Then take a ref on the task's io context and return it. + */ +static struct io_context *as_get_io_context(void) +{ + struct io_context *ioc = get_io_context(GFP_ATOMIC); + if (ioc && !ioc->aic) { + ioc->aic = alloc_as_io_context(); + if (!ioc->aic) { + put_io_context(ioc); + ioc = NULL; + } + } + return ioc; +} + +static void as_put_io_context(struct as_rq *arq) +{ + struct as_io_context *aic; + + if (unlikely(!arq->io_context)) + return; + + aic = arq->io_context->aic; + + if (arq->is_sync == REQ_SYNC && aic) { + spin_lock(&aic->lock); + set_bit(AS_TASK_IORUNNING, &aic->state); + aic->last_end_request = jiffies; + spin_unlock(&aic->lock); + } + + put_io_context(arq->io_context); +} + +/* + * the back merge hash support functions + */ +static const int as_hash_shift = 6; +#define AS_HASH_BLOCK(sec) ((sec) >> 3) +#define AS_HASH_FN(sec) (hash_long(AS_HASH_BLOCK((sec)), as_hash_shift)) +#define AS_HASH_ENTRIES (1 << as_hash_shift) +#define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors) +#define list_entry_hash(ptr) list_entry((ptr), struct as_rq, hash) + +static inline void __as_del_arq_hash(struct as_rq *arq) +{ + arq->on_hash = 0; + list_del_init(&arq->hash); +} + +static inline void as_del_arq_hash(struct as_rq *arq) +{ + if (arq->on_hash) + __as_del_arq_hash(arq); +} + +static void as_add_arq_hash(struct as_data *ad, struct as_rq *arq) +{ + struct request *rq = arq->request; + + BUG_ON(arq->on_hash); + + arq->on_hash = 1; + list_add(&arq->hash, &ad->hash[AS_HASH_FN(rq_hash_key(rq))]); +} + +/* + * move hot entry to front of chain + */ +static inline void as_hot_arq_hash(struct as_data *ad, struct as_rq *arq) +{ + struct request *rq = arq->request; + struct list_head *head = &ad->hash[AS_HASH_FN(rq_hash_key(rq))]; + + if (!arq->on_hash) { + WARN_ON(1); + return; + } + + if (arq->hash.prev != head) { + list_del(&arq->hash); + list_add(&arq->hash, head); + } +} + +static struct request *as_find_arq_hash(struct as_data *ad, sector_t offset) +{ + struct list_head *hash_list = &ad->hash[AS_HASH_FN(offset)]; + struct list_head *entry, *next = hash_list->next; + + while ((entry = next) != hash_list) { + struct as_rq *arq = list_entry_hash(entry); + struct request *__rq = arq->request; + + next = entry->next; + + BUG_ON(!arq->on_hash); + + if (!rq_mergeable(__rq)) { + as_del_arq_hash(arq); + continue; + } + + if (rq_hash_key(__rq) == offset) + return __rq; + } + + return NULL; +} + +/* + * rb tree support functions + */ +#define RB_NONE (2) +#define RB_EMPTY(root) ((root)->rb_node == NULL) +#define ON_RB(node) ((node)->rb_color != RB_NONE) +#define RB_CLEAR(node) ((node)->rb_color = RB_NONE) +#define rb_entry_arq(node) rb_entry((node), struct as_rq, rb_node) +#define ARQ_RB_ROOT(ad, arq) (&(ad)->sort_list[(arq)->is_sync]) +#define rq_rb_key(rq) (rq)->sector + +/* + * as_find_first_arq finds the first (lowest sector numbered) request + * for the specified data_dir. Used to sweep back to the start of the disk + * (1-way elevator) after we process the last (highest sector) request. + */ +static struct as_rq *as_find_first_arq(struct as_data *ad, int data_dir) +{ + struct rb_node *n = ad->sort_list[data_dir].rb_node; + + if (n == NULL) + return NULL; + + for (;;) { + if (n->rb_left == NULL) + return rb_entry_arq(n); + + n = n->rb_left; + } +} + +/* + * Add the request to the rb tree if it is unique. If there is an alias (an + * existing request against the same sector), which can happen when using + * direct IO, then return the alias. + */ +static struct as_rq *as_add_arq_rb(struct as_data *ad, struct as_rq *arq) +{ + struct rb_node **p = &ARQ_RB_ROOT(ad, arq)->rb_node; + struct rb_node *parent = NULL; + struct as_rq *__arq; + struct request *rq = arq->request; + + arq->rb_key = rq_rb_key(rq); + + while (*p) { + parent = *p; + __arq = rb_entry_arq(parent); + + if (arq->rb_key < __arq->rb_key) + p = &(*p)->rb_left; + else if (arq->rb_key > __arq->rb_key) + p = &(*p)->rb_right; + else + return __arq; + } + + rb_link_node(&arq->rb_node, parent, p); + rb_insert_color(&arq->rb_node, ARQ_RB_ROOT(ad, arq)); + + return NULL; +} + +static inline void as_del_arq_rb(struct as_data *ad, struct as_rq *arq) +{ + if (!ON_RB(&arq->rb_node)) { + WARN_ON(1); + return; + } + + rb_erase(&arq->rb_node, ARQ_RB_ROOT(ad, arq)); + RB_CLEAR(&arq->rb_node); +} + +static struct request * +as_find_arq_rb(struct as_data *ad, sector_t sector, int data_dir) +{ + struct rb_node *n = ad->sort_list[data_dir].rb_node; + struct as_rq *arq; + + while (n) { + arq = rb_entry_arq(n); + + if (sector < arq->rb_key) + n = n->rb_left; + else if (sector > arq->rb_key) + n = n->rb_right; + else + return arq->request; + } + + return NULL; +} + +/* + * IO Scheduler proper + */ + +#define MAXBACK (1024 * 1024) /* + * Maximum distance the disk will go backward + * for a request. + */ + +#define BACK_PENALTY 2 + +/* + * as_choose_req selects the preferred one of two requests of the same data_dir + * ignoring time - eg. timeouts, which is the job of as_dispatch_request + */ +static struct as_rq * +as_choose_req(struct as_data *ad, struct as_rq *arq1, struct as_rq *arq2) +{ + int data_dir; + sector_t last, s1, s2, d1, d2; + int r1_wrap=0, r2_wrap=0; /* requests are behind the disk head */ + const sector_t maxback = MAXBACK; + + if (arq1 == NULL || arq1 == arq2) + return arq2; + if (arq2 == NULL) + return arq1; + + data_dir = arq1->is_sync; + + last = ad->last_sector[data_dir]; + s1 = arq1->request->sector; + s2 = arq2->request->sector; + + BUG_ON(data_dir != arq2->is_sync); + + /* + * Strict one way elevator _except_ in the case where we allow + * short backward seeks which are biased as twice the cost of a + * similar forward seek. + */ + if (s1 >= last) + d1 = s1 - last; + else if (s1+maxback >= last) + d1 = (last - s1)*BACK_PENALTY; + else { + r1_wrap = 1; + d1 = 0; /* shut up, gcc */ + } + + if (s2 >= last) + d2 = s2 - last; + else if (s2+maxback >= last) + d2 = (last - s2)*BACK_PENALTY; + else { + r2_wrap = 1; + d2 = 0; + } + + /* Found required data */ + if (!r1_wrap && r2_wrap) + return arq1; + else if (!r2_wrap && r1_wrap) + return arq2; + else if (r1_wrap && r2_wrap) { + /* both behind the head */ + if (s1 <= s2) + return arq1; + else + return arq2; + } + + /* Both requests in front of the head */ + if (d1 < d2) + return arq1; + else if (d2 < d1) + return arq2; + else { + if (s1 >= s2) + return arq1; + else + return arq2; + } +} + +/* + * as_find_next_arq finds the next request after @prev in elevator order. + * this with as_choose_req form the basis for how the scheduler chooses + * what request to process next. Anticipation works on top of this. + */ +static struct as_rq *as_find_next_arq(struct as_data *ad, struct as_rq *last) +{ + const int data_dir = last->is_sync; + struct as_rq *ret; + struct rb_node *rbnext = rb_next(&last->rb_node); + struct rb_node *rbprev = rb_prev(&last->rb_node); + struct as_rq *arq_next, *arq_prev; + + BUG_ON(!ON_RB(&last->rb_node)); + + if (rbprev) + arq_prev = rb_entry_arq(rbprev); + else + arq_prev = NULL; + + if (rbnext) + arq_next = rb_entry_arq(rbnext); + else { + arq_next = as_find_first_arq(ad, data_dir); + if (arq_next == last) + arq_next = NULL; + } + + ret = as_choose_req(ad, arq_next, arq_prev); + + return ret; +} + +/* + * anticipatory scheduling functions follow + */ + +/* + * as_antic_expired tells us when we have anticipated too long. + * The funny "absolute difference" math on the elapsed time is to handle + * jiffy wraps, and disks which have been idle for 0x80000000 jiffies. + */ +static int as_antic_expired(struct as_data *ad) +{ + long delta_jif; + + delta_jif = jiffies - ad->antic_start; + if (unlikely(delta_jif < 0)) + delta_jif = -delta_jif; + if (delta_jif < ad->antic_expire) + return 0; + + return 1; +} + +/* + * as_antic_waitnext starts anticipating that a nice request will soon be + * submitted. See also as_antic_waitreq + */ +static void as_antic_waitnext(struct as_data *ad) +{ + unsigned long timeout; + + BUG_ON(ad->antic_status != ANTIC_OFF + && ad->antic_status != ANTIC_WAIT_REQ); + + timeout = ad->antic_start + ad->antic_expire; + + mod_timer(&ad->antic_timer, timeout); + + ad->antic_status = ANTIC_WAIT_NEXT; +} + +/* + * as_antic_waitreq starts anticipating. We don't start timing the anticipation + * until the request that we're anticipating on has finished. This means we + * are timing from when the candidate process wakes up hopefully. + */ +static void as_antic_waitreq(struct as_data *ad) +{ + BUG_ON(ad->antic_status == ANTIC_FINISHED); + if (ad->antic_status == ANTIC_OFF) { + if (!ad->io_context || ad->ioc_finished) + as_antic_waitnext(ad); + else + ad->antic_status = ANTIC_WAIT_REQ; + } +} + +/* + * This is called directly by the functions in this file to stop anticipation. + * We kill the timer and schedule a call to the request_fn asap. + */ +static void as_antic_stop(struct as_data *ad) +{ + int status = ad->antic_status; + + if (status == ANTIC_WAIT_REQ || status == ANTIC_WAIT_NEXT) { + if (status == ANTIC_WAIT_NEXT) + del_timer(&ad->antic_timer); + ad->antic_status = ANTIC_FINISHED; + /* see as_work_handler */ + kblockd_schedule_work(&ad->antic_work); + } +} + +/* + * as_antic_timeout is the timer function set by as_antic_waitnext. + */ +static void as_antic_timeout(unsigned long data) +{ + struct request_queue *q = (struct request_queue *)data; + struct as_data *ad = q->elevator->elevator_data; + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); + if (ad->antic_status == ANTIC_WAIT_REQ + || ad->antic_status == ANTIC_WAIT_NEXT) { + struct as_io_context *aic = ad->io_context->aic; + + ad->antic_status = ANTIC_FINISHED; + kblockd_schedule_work(&ad->antic_work); + + if (aic->ttime_samples == 0) { + /* process anticipated on has exitted or timed out*/ + ad->exit_prob = (7*ad->exit_prob + 256)/8; + } + } + spin_unlock_irqrestore(q->queue_lock, flags); +} + +/* + * as_close_req decides if one request is considered "close" to the + * previous one issued. + */ +static int as_close_req(struct as_data *ad, struct as_rq *arq) +{ + unsigned long delay; /* milliseconds */ + sector_t last = ad->last_sector[ad->batch_data_dir]; + sector_t next = arq->request->sector; + sector_t delta; /* acceptable close offset (in sectors) */ + + if (ad->antic_status == ANTIC_OFF || !ad->ioc_finished) + delay = 0; + else + delay = ((jiffies - ad->antic_start) * 1000) / HZ; + + if (delay <= 1) + delta = 64; + else if (delay <= 20 && delay <= ad->antic_expire) + delta = 64 << (delay-1); + else + return 1; + + return (last - (delta>>1) <= next) && (next <= last + delta); +} + +/* + * as_can_break_anticipation returns true if we have been anticipating this + * request. + * + * It also returns true if the process against which we are anticipating + * submits a write - that's presumably an fsync, O_SYNC write, etc. We want to + * dispatch it ASAP, because we know that application will not be submitting + * any new reads. + * + * If the task which has submitted the request has exitted, break anticipation. + * + * If this task has queued some other IO, do not enter enticipation. + */ +static int as_can_break_anticipation(struct as_data *ad, struct as_rq *arq) +{ + struct io_context *ioc; + struct as_io_context *aic; + sector_t s; + + ioc = ad->io_context; + BUG_ON(!ioc); + + if (arq && ioc == arq->io_context) { + /* request from same process */ + return 1; + } + + if (ad->ioc_finished && as_antic_expired(ad)) { + /* + * In this situation status should really be FINISHED, + * however the timer hasn't had the chance to run yet. + */ + return 1; + } + + aic = ioc->aic; + if (!aic) + return 0; + + if (!test_bit(AS_TASK_RUNNING, &aic->state)) { + /* process anticipated on has exitted */ + if (aic->ttime_samples == 0) + ad->exit_prob = (7*ad->exit_prob + 256)/8; + return 1; + } + + if (atomic_read(&aic->nr_queued) > 0) { + /* process has more requests queued */ + return 1; + } + + if (atomic_read(&aic->nr_dispatched) > 0) { + /* process has more requests dispatched */ + return 1; + } + + if (arq && arq->is_sync == REQ_SYNC && as_close_req(ad, arq)) { + /* + * Found a close request that is not one of ours. + * + * This makes close requests from another process reset + * our thinktime delay. Is generally useful when there are + * two or more cooperating processes working in the same + * area. + */ + spin_lock(&aic->lock); + aic->last_end_request = jiffies; + spin_unlock(&aic->lock); + return 1; + } + + + if (aic->ttime_samples == 0) { + if (ad->new_ttime_mean > ad->antic_expire) + return 1; + if (ad->exit_prob > 128) + return 1; + } else if (aic->ttime_mean > ad->antic_expire) { + /* the process thinks too much between requests */ + return 1; + } + + if (!arq) + return 0; + + if (ad->last_sector[REQ_SYNC] < arq->request->sector) + s = arq->request->sector - ad->last_sector[REQ_SYNC]; + else + s = ad->last_sector[REQ_SYNC] - arq->request->sector; + + if (aic->seek_samples == 0) { + /* + * Process has just started IO. Use past statistics to + * guage success possibility + */ + if (ad->new_seek_mean > s) { + /* this request is better than what we're expecting */ + return 1; + } + + } else { + if (aic->seek_mean > s) { + /* this request is better than what we're expecting */ + return 1; + } + } + + return 0; +} + +/* + * as_can_anticipate indicates weather we should either run arq + * or keep anticipating a better request. + */ +static int as_can_anticipate(struct as_data *ad, struct as_rq *arq) +{ + if (!ad->io_context) + /* + * Last request submitted was a write + */ + return 0; + + if (ad->antic_status == ANTIC_FINISHED) + /* + * Don't restart if we have just finished. Run the next request + */ + return 0; + + if (as_can_break_anticipation(ad, arq)) + /* + * This request is a good candidate. Don't keep anticipating, + * run it. + */ + return 0; + + /* + * OK from here, we haven't finished, and don't have a decent request! + * Status is either ANTIC_OFF so start waiting, + * ANTIC_WAIT_REQ so continue waiting for request to finish + * or ANTIC_WAIT_NEXT so continue waiting for an acceptable request. + * + */ + + return 1; +} + +static void as_update_thinktime(struct as_data *ad, struct as_io_context *aic, unsigned long ttime) +{ + /* fixed point: 1.0 == 1<<8 */ + if (aic->ttime_samples == 0) { + ad->new_ttime_total = (7*ad->new_ttime_total + 256*ttime) / 8; + ad->new_ttime_mean = ad->new_ttime_total / 256; + + ad->exit_prob = (7*ad->exit_prob)/8; + } + aic->ttime_samples = (7*aic->ttime_samples + 256) / 8; + aic->ttime_total = (7*aic->ttime_total + 256*ttime) / 8; + aic->ttime_mean = (aic->ttime_total + 128) / aic->ttime_samples; +} + +static void as_update_seekdist(struct as_data *ad, struct as_io_context *aic, sector_t sdist) +{ + u64 total; + + if (aic->seek_samples == 0) { + ad->new_seek_total = (7*ad->new_seek_total + 256*(u64)sdist)/8; + ad->new_seek_mean = ad->new_seek_total / 256; + } + + /* + * Don't allow the seek distance to get too large from the + * odd fragment, pagein, etc + */ + if (aic->seek_samples <= 60) /* second&third seek */ + sdist = min(sdist, (aic->seek_mean * 4) + 2*1024*1024); + else + sdist = min(sdist, (aic->seek_mean * 4) + 2*1024*64); + + aic->seek_samples = (7*aic->seek_samples + 256) / 8; + aic->seek_total = (7*aic->seek_total + (u64)256*sdist) / 8; + total = aic->seek_total + (aic->seek_samples/2); + do_div(total, aic->seek_samples); + aic->seek_mean = (sector_t)total; +} + +/* + * as_update_iohist keeps a decaying histogram of IO thinktimes, and + * updates @aic->ttime_mean based on that. It is called when a new + * request is queued. + */ +static void as_update_iohist(struct as_data *ad, struct as_io_context *aic, struct request *rq) +{ + struct as_rq *arq = RQ_DATA(rq); + int data_dir = arq->is_sync; + unsigned long thinktime; + sector_t seek_dist; + + if (aic == NULL) + return; + + if (data_dir == REQ_SYNC) { + unsigned long in_flight = atomic_read(&aic->nr_queued) + + atomic_read(&aic->nr_dispatched); + spin_lock(&aic->lock); + if (test_bit(AS_TASK_IORUNNING, &aic->state) || + test_bit(AS_TASK_IOSTARTED, &aic->state)) { + /* Calculate read -> read thinktime */ + if (test_bit(AS_TASK_IORUNNING, &aic->state) + && in_flight == 0) { + thinktime = jiffies - aic->last_end_request; + thinktime = min(thinktime, MAX_THINKTIME-1); + } else + thinktime = 0; + as_update_thinktime(ad, aic, thinktime); + + /* Calculate read -> read seek distance */ + if (aic->last_request_pos < rq->sector) + seek_dist = rq->sector - aic->last_request_pos; + else + seek_dist = aic->last_request_pos - rq->sector; + as_update_seekdist(ad, aic, seek_dist); + } + aic->last_request_pos = rq->sector + rq->nr_sectors; + set_bit(AS_TASK_IOSTARTED, &aic->state); + spin_unlock(&aic->lock); + } +} + +/* + * as_update_arq must be called whenever a request (arq) is added to + * the sort_list. This function keeps caches up to date, and checks if the + * request might be one we are "anticipating" + */ +static void as_update_arq(struct as_data *ad, struct as_rq *arq) +{ + const int data_dir = arq->is_sync; + + /* keep the next_arq cache up to date */ + ad->next_arq[data_dir] = as_choose_req(ad, arq, ad->next_arq[data_dir]); + + /* + * have we been anticipating this request? + * or does it come from the same process as the one we are anticipating + * for? + */ + if (ad->antic_status == ANTIC_WAIT_REQ + || ad->antic_status == ANTIC_WAIT_NEXT) { + if (as_can_break_anticipation(ad, arq)) + as_antic_stop(ad); + } +} + +/* + * Gathers timings and resizes the write batch automatically + */ +static void update_write_batch(struct as_data *ad) +{ + unsigned long batch = ad->batch_expire[REQ_ASYNC]; + long write_time; + + write_time = (jiffies - ad->current_batch_expires) + batch; + if (write_time < 0) + write_time = 0; + + if (write_time > batch && !ad->write_batch_idled) { + if (write_time > batch * 3) + ad->write_batch_count /= 2; + else + ad->write_batch_count--; + } else if (write_time < batch && ad->current_write_count == 0) { + if (batch > write_time * 3) + ad->write_batch_count *= 2; + else + ad->write_batch_count++; + } + + if (ad->write_batch_count < 1) + ad->write_batch_count = 1; +} + +/* + * as_completed_request is to be called when a request has completed and + * returned something to the requesting process, be it an error or data. + */ +static void as_completed_request(request_queue_t *q, struct request *rq) +{ + struct as_data *ad = q->elevator->elevator_data; + struct as_rq *arq = RQ_DATA(rq); + + WARN_ON(!list_empty(&rq->queuelist)); + + if (arq->state != AS_RQ_REMOVED) { + printk("arq->state %d\n", arq->state); + WARN_ON(1); + goto out; + } + + if (ad->changed_batch && ad->nr_dispatched == 1) { + kblockd_schedule_work(&ad->antic_work); + ad->changed_batch = 0; + + if (ad->batch_data_dir == REQ_SYNC) + ad->new_batch = 1; + } + WARN_ON(ad->nr_dispatched == 0); + ad->nr_dispatched--; + + /* + * Start counting the batch from when a request of that direction is + * actually serviced. This should help devices with big TCQ windows + * and writeback caches + */ + if (ad->new_batch && ad->batch_data_dir == arq->is_sync) { + update_write_batch(ad); + ad->current_batch_expires = jiffies + + ad->batch_expire[REQ_SYNC]; + ad->new_batch = 0; + } + + if (ad->io_context == arq->io_context && ad->io_context) { + ad->antic_start = jiffies; + ad->ioc_finished = 1; + if (ad->antic_status == ANTIC_WAIT_REQ) { + /* + * We were waiting on this request, now anticipate + * the next one + */ + as_antic_waitnext(ad); + } + } + + as_put_io_context(arq); +out: + arq->state = AS_RQ_POSTSCHED; +} + +/* + * as_remove_queued_request removes a request from the pre dispatch queue + * without updating refcounts. It is expected the caller will drop the + * reference unless it replaces the request at somepart of the elevator + * (ie. the dispatch queue) + */ +static void as_remove_queued_request(request_queue_t *q, struct request *rq) +{ + struct as_rq *arq = RQ_DATA(rq); + const int data_dir = arq->is_sync; + struct as_data *ad = q->elevator->elevator_data; + + WARN_ON(arq->state != AS_RQ_QUEUED); + + if (arq->io_context && arq->io_context->aic) { + BUG_ON(!atomic_read(&arq->io_context->aic->nr_queued)); + atomic_dec(&arq->io_context->aic->nr_queued); + } + + /* + * Update the "next_arq" cache if we are about to remove its + * entry + */ + if (ad->next_arq[data_dir] == arq) + ad->next_arq[data_dir] = as_find_next_arq(ad, arq); + + list_del_init(&arq->fifo); + as_del_arq_hash(arq); + as_del_arq_rb(ad, arq); +} + +/* + * as_fifo_expired returns 0 if there are no expired reads on the fifo, + * 1 otherwise. It is ratelimited so that we only perform the check once per + * `fifo_expire' interval. Otherwise a large number of expired requests + * would create a hopeless seekstorm. + * + * See as_antic_expired comment. + */ +static int as_fifo_expired(struct as_data *ad, int adir) +{ + struct as_rq *arq; + long delta_jif; + + delta_jif = jiffies - ad->last_check_fifo[adir]; + if (unlikely(delta_jif < 0)) + delta_jif = -delta_jif; + if (delta_jif < ad->fifo_expire[adir]) + return 0; + + ad->last_check_fifo[adir] = jiffies; + + if (list_empty(&ad->fifo_list[adir])) + return 0; + + arq = list_entry_fifo(ad->fifo_list[adir].next); + + return time_after(jiffies, arq->expires); +} + +/* + * as_batch_expired returns true if the current batch has expired. A batch + * is a set of reads or a set of writes. + */ +static inline int as_batch_expired(struct as_data *ad) +{ + if (ad->changed_batch || ad->new_batch) + return 0; + + if (ad->batch_data_dir == REQ_SYNC) + /* TODO! add a check so a complete fifo gets written? */ + return time_after(jiffies, ad->current_batch_expires); + + return time_after(jiffies, ad->current_batch_expires) + || ad->current_write_count == 0; +} + +/* + * move an entry to dispatch queue + */ +static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq) +{ + struct request *rq = arq->request; + const int data_dir = arq->is_sync; + + BUG_ON(!ON_RB(&arq->rb_node)); + + as_antic_stop(ad); + ad->antic_status = ANTIC_OFF; + + /* + * This has to be set in order to be correctly updated by + * as_find_next_arq + */ + ad->last_sector[data_dir] = rq->sector + rq->nr_sectors; + + if (data_dir == REQ_SYNC) { + /* In case we have to anticipate after this */ + copy_io_context(&ad->io_context, &arq->io_context); + } else { + if (ad->io_context) { + put_io_context(ad->io_context); + ad->io_context = NULL; + } + + if (ad->current_write_count != 0) + ad->current_write_count--; + } + ad->ioc_finished = 0; + + ad->next_arq[data_dir] = as_find_next_arq(ad, arq); + + /* + * take it off the sort and fifo list, add to dispatch queue + */ + while (!list_empty(&rq->queuelist)) { + struct request *__rq = list_entry_rq(rq->queuelist.next); + struct as_rq *__arq = RQ_DATA(__rq); + + list_del(&__rq->queuelist); + + elv_dispatch_add_tail(ad->q, __rq); + + if (__arq->io_context && __arq->io_context->aic) + atomic_inc(&__arq->io_context->aic->nr_dispatched); + + WARN_ON(__arq->state != AS_RQ_QUEUED); + __arq->state = AS_RQ_DISPATCHED; + + ad->nr_dispatched++; + } + + as_remove_queued_request(ad->q, rq); + WARN_ON(arq->state != AS_RQ_QUEUED); + + elv_dispatch_sort(ad->q, rq); + + arq->state = AS_RQ_DISPATCHED; + if (arq->io_context && arq->io_context->aic) + atomic_inc(&arq->io_context->aic->nr_dispatched); + ad->nr_dispatched++; +} + +/* + * as_dispatch_request selects the best request according to + * read/write expire, batch expire, etc, and moves it to the dispatch + * queue. Returns 1 if a request was found, 0 otherwise. + */ +static int as_dispatch_request(request_queue_t *q, int force) +{ + struct as_data *ad = q->elevator->elevator_data; + struct as_rq *arq; + const int reads = !list_empty(&ad->fifo_list[REQ_SYNC]); + const int writes = !list_empty(&ad->fifo_list[REQ_ASYNC]); + + if (unlikely(force)) { + /* + * Forced dispatch, accounting is useless. Reset + * accounting states and dump fifo_lists. Note that + * batch_data_dir is reset to REQ_SYNC to avoid + * screwing write batch accounting as write batch + * accounting occurs on W->R transition. + */ + int dispatched = 0; + + ad->batch_data_dir = REQ_SYNC; + ad->changed_batch = 0; + ad->new_batch = 0; + + while (ad->next_arq[REQ_SYNC]) { + as_move_to_dispatch(ad, ad->next_arq[REQ_SYNC]); + dispatched++; + } + ad->last_check_fifo[REQ_SYNC] = jiffies; + + while (ad->next_arq[REQ_ASYNC]) { + as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]); + dispatched++; + } + ad->last_check_fifo[REQ_ASYNC] = jiffies; + + return dispatched; + } + + /* Signal that the write batch was uncontended, so we can't time it */ + if (ad->batch_data_dir == REQ_ASYNC && !reads) { + if (ad->current_write_count == 0 || !writes) + ad->write_batch_idled = 1; + } + + if (!(reads || writes) + || ad->antic_status == ANTIC_WAIT_REQ + || ad->antic_status == ANTIC_WAIT_NEXT + || ad->changed_batch) + return 0; + + if (!(reads && writes && as_batch_expired(ad)) ) { + /* + * batch is still running or no reads or no writes + */ + arq = ad->next_arq[ad->batch_data_dir]; + + if (ad->batch_data_dir == REQ_SYNC && ad->antic_expire) { + if (as_fifo_expired(ad, REQ_SYNC)) + goto fifo_expired; + + if (as_can_anticipate(ad, arq)) { + as_antic_waitreq(ad); + return 0; + } + } + + if (arq) { + /* we have a "next request" */ + if (reads && !writes) + ad->current_batch_expires = + jiffies + ad->batch_expire[REQ_SYNC]; + goto dispatch_request; + } + } + + /* + * at this point we are not running a batch. select the appropriate + * data direction (read / write) + */ + + if (reads) { + BUG_ON(RB_EMPTY(&ad->sort_list[REQ_SYNC])); + + if (writes && ad->batch_data_dir == REQ_SYNC) + /* + * Last batch was a read, switch to writes + */ + goto dispatch_writes; + + if (ad->batch_data_dir == REQ_ASYNC) { + WARN_ON(ad->new_batch); + ad->changed_batch = 1; + } + ad->batch_data_dir = REQ_SYNC; + arq = list_entry_fifo(ad->fifo_list[ad->batch_data_dir].next); + ad->last_check_fifo[ad->batch_data_dir] = jiffies; + goto dispatch_request; + } + + /* + * the last batch was a read + */ + + if (writes) { +dispatch_writes: + BUG_ON(RB_EMPTY(&ad->sort_list[REQ_ASYNC])); + + if (ad->batch_data_dir == REQ_SYNC) { + ad->changed_batch = 1; + + /* + * new_batch might be 1 when the queue runs out of + * reads. A subsequent submission of a write might + * cause a change of batch before the read is finished. + */ + ad->new_batch = 0; + } + ad->batch_data_dir = REQ_ASYNC; + ad->current_write_count = ad->write_batch_count; + ad->write_batch_idled = 0; + arq = ad->next_arq[ad->batch_data_dir]; + goto dispatch_request; + } + + BUG(); + return 0; + +dispatch_request: + /* + * If a request has expired, service it. + */ + + if (as_fifo_expired(ad, ad->batch_data_dir)) { +fifo_expired: + arq = list_entry_fifo(ad->fifo_list[ad->batch_data_dir].next); + BUG_ON(arq == NULL); + } + + if (ad->changed_batch) { + WARN_ON(ad->new_batch); + + if (ad->nr_dispatched) + return 0; + + if (ad->batch_data_dir == REQ_ASYNC) + ad->current_batch_expires = jiffies + + ad->batch_expire[REQ_ASYNC]; + else + ad->new_batch = 1; + + ad->changed_batch = 0; + } + + /* + * arq is the selected appropriate request. + */ + as_move_to_dispatch(ad, arq); + + return 1; +} + +/* + * Add arq to a list behind alias + */ +static inline void +as_add_aliased_request(struct as_data *ad, struct as_rq *arq, struct as_rq *alias) +{ + struct request *req = arq->request; + struct list_head *insert = alias->request->queuelist.prev; + + /* + * Transfer list of aliases + */ + while (!list_empty(&req->queuelist)) { + struct request *__rq = list_entry_rq(req->queuelist.next); + struct as_rq *__arq = RQ_DATA(__rq); + + list_move_tail(&__rq->queuelist, &alias->request->queuelist); + + WARN_ON(__arq->state != AS_RQ_QUEUED); + } + + /* + * Another request with the same start sector on the rbtree. + * Link this request to that sector. They are untangled in + * as_move_to_dispatch + */ + list_add(&arq->request->queuelist, insert); + + /* + * Don't want to have to handle merges. + */ + as_del_arq_hash(arq); + arq->request->flags |= REQ_NOMERGE; +} + +/* + * add arq to rbtree and fifo + */ +static void as_add_request(request_queue_t *q, struct request *rq) +{ + struct as_data *ad = q->elevator->elevator_data; + struct as_rq *arq = RQ_DATA(rq); + struct as_rq *alias; + int data_dir; + + if (arq->state != AS_RQ_PRESCHED) { + printk("arq->state: %d\n", arq->state); + WARN_ON(1); + } + arq->state = AS_RQ_NEW; + + if (rq_data_dir(arq->request) == READ + || current->flags&PF_SYNCWRITE) + arq->is_sync = 1; + else + arq->is_sync = 0; + data_dir = arq->is_sync; + + arq->io_context = as_get_io_context(); + + if (arq->io_context) { + as_update_iohist(ad, arq->io_context->aic, arq->request); + atomic_inc(&arq->io_context->aic->nr_queued); + } + + alias = as_add_arq_rb(ad, arq); + if (!alias) { + /* + * set expire time (only used for reads) and add to fifo list + */ + arq->expires = jiffies + ad->fifo_expire[data_dir]; + list_add_tail(&arq->fifo, &ad->fifo_list[data_dir]); + + if (rq_mergeable(arq->request)) + as_add_arq_hash(ad, arq); + as_update_arq(ad, arq); /* keep state machine up to date */ + + } else { + as_add_aliased_request(ad, arq, alias); + + /* + * have we been anticipating this request? + * or does it come from the same process as the one we are + * anticipating for? + */ + if (ad->antic_status == ANTIC_WAIT_REQ + || ad->antic_status == ANTIC_WAIT_NEXT) { + if (as_can_break_anticipation(ad, arq)) + as_antic_stop(ad); + } + } + + arq->state = AS_RQ_QUEUED; +} + +static void as_activate_request(request_queue_t *q, struct request *rq) +{ + struct as_rq *arq = RQ_DATA(rq); + + WARN_ON(arq->state != AS_RQ_DISPATCHED); + arq->state = AS_RQ_REMOVED; + if (arq->io_context && arq->io_context->aic) + atomic_dec(&arq->io_context->aic->nr_dispatched); +} + +static void as_deactivate_request(request_queue_t *q, struct request *rq) +{ + struct as_rq *arq = RQ_DATA(rq); + + WARN_ON(arq->state != AS_RQ_REMOVED); + arq->state = AS_RQ_DISPATCHED; + if (arq->io_context && arq->io_context->aic) + atomic_inc(&arq->io_context->aic->nr_dispatched); +} + +/* + * as_queue_empty tells us if there are requests left in the device. It may + * not be the case that a driver can get the next request even if the queue + * is not empty - it is used in the block layer to check for plugging and + * merging opportunities + */ +static int as_queue_empty(request_queue_t *q) +{ + struct as_data *ad = q->elevator->elevator_data; + + return list_empty(&ad->fifo_list[REQ_ASYNC]) + && list_empty(&ad->fifo_list[REQ_SYNC]); +} + +static struct request * +as_former_request(request_queue_t *q, struct request *rq) +{ + struct as_rq *arq = RQ_DATA(rq); + struct rb_node *rbprev = rb_prev(&arq->rb_node); + struct request *ret = NULL; + + if (rbprev) + ret = rb_entry_arq(rbprev)->request; + + return ret; +} + +static struct request * +as_latter_request(request_queue_t *q, struct request *rq) +{ + struct as_rq *arq = RQ_DATA(rq); + struct rb_node *rbnext = rb_next(&arq->rb_node); + struct request *ret = NULL; + + if (rbnext) + ret = rb_entry_arq(rbnext)->request; + + return ret; +} + +static int +as_merge(request_queue_t *q, struct request **req, struct bio *bio) +{ + struct as_data *ad = q->elevator->elevator_data; + sector_t rb_key = bio->bi_sector + bio_sectors(bio); + struct request *__rq; + int ret; + + /* + * see if the merge hash can satisfy a back merge + */ + __rq = as_find_arq_hash(ad, bio->bi_sector); + if (__rq) { + BUG_ON(__rq->sector + __rq->nr_sectors != bio->bi_sector); + + if (elv_rq_merge_ok(__rq, bio)) { + ret = ELEVATOR_BACK_MERGE; + goto out; + } + } + + /* + * check for front merge + */ + __rq = as_find_arq_rb(ad, rb_key, bio_data_dir(bio)); + if (__rq) { + BUG_ON(rb_key != rq_rb_key(__rq)); + + if (elv_rq_merge_ok(__rq, bio)) { + ret = ELEVATOR_FRONT_MERGE; + goto out; + } + } + + return ELEVATOR_NO_MERGE; +out: + if (ret) { + if (rq_mergeable(__rq)) + as_hot_arq_hash(ad, RQ_DATA(__rq)); + } + *req = __rq; + return ret; +} + +static void as_merged_request(request_queue_t *q, struct request *req) +{ + struct as_data *ad = q->elevator->elevator_data; + struct as_rq *arq = RQ_DATA(req); + + /* + * hash always needs to be repositioned, key is end sector + */ + as_del_arq_hash(arq); + as_add_arq_hash(ad, arq); + + /* + * if the merge was a front merge, we need to reposition request + */ + if (rq_rb_key(req) != arq->rb_key) { + struct as_rq *alias, *next_arq = NULL; + + if (ad->next_arq[arq->is_sync] == arq) + next_arq = as_find_next_arq(ad, arq); + + /* + * Note! We should really be moving any old aliased requests + * off this request and try to insert them into the rbtree. We + * currently don't bother. Ditto the next function. + */ + as_del_arq_rb(ad, arq); + if ((alias = as_add_arq_rb(ad, arq)) ) { + list_del_init(&arq->fifo); + as_add_aliased_request(ad, arq, alias); + if (next_arq) + ad->next_arq[arq->is_sync] = next_arq; + } + /* + * Note! At this stage of this and the next function, our next + * request may not be optimal - eg the request may have "grown" + * behind the disk head. We currently don't bother adjusting. + */ + } +} + +static void +as_merged_requests(request_queue_t *q, struct request *req, + struct request *next) +{ + struct as_data *ad = q->elevator->elevator_data; + struct as_rq *arq = RQ_DATA(req); + struct as_rq *anext = RQ_DATA(next); + + BUG_ON(!arq); + BUG_ON(!anext); + + /* + * reposition arq (this is the merged request) in hash, and in rbtree + * in case of a front merge + */ + as_del_arq_hash(arq); + as_add_arq_hash(ad, arq); + + if (rq_rb_key(req) != arq->rb_key) { + struct as_rq *alias, *next_arq = NULL; + + if (ad->next_arq[arq->is_sync] == arq) + next_arq = as_find_next_arq(ad, arq); + + as_del_arq_rb(ad, arq); + if ((alias = as_add_arq_rb(ad, arq)) ) { + list_del_init(&arq->fifo); + as_add_aliased_request(ad, arq, alias); + if (next_arq) + ad->next_arq[arq->is_sync] = next_arq; + } + } + + /* + * if anext expires before arq, assign its expire time to arq + * and move into anext position (anext will be deleted) in fifo + */ + if (!list_empty(&arq->fifo) && !list_empty(&anext->fifo)) { + if (time_before(anext->expires, arq->expires)) { + list_move(&arq->fifo, &anext->fifo); + arq->expires = anext->expires; + /* + * Don't copy here but swap, because when anext is + * removed below, it must contain the unused context + */ + swap_io_context(&arq->io_context, &anext->io_context); + } + } + + /* + * Transfer list of aliases + */ + while (!list_empty(&next->queuelist)) { + struct request *__rq = list_entry_rq(next->queuelist.next); + struct as_rq *__arq = RQ_DATA(__rq); + + list_move_tail(&__rq->queuelist, &req->queuelist); + + WARN_ON(__arq->state != AS_RQ_QUEUED); + } + + /* + * kill knowledge of next, this one is a goner + */ + as_remove_queued_request(q, next); + as_put_io_context(anext); + + anext->state = AS_RQ_MERGED; +} + +/* + * This is executed in a "deferred" process context, by kblockd. It calls the + * driver's request_fn so the driver can submit that request. + * + * IMPORTANT! This guy will reenter the elevator, so set up all queue global + * state before calling, and don't rely on any state over calls. + * + * FIXME! dispatch queue is not a queue at all! + */ +static void as_work_handler(void *data) +{ + struct request_queue *q = data; + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); + if (!as_queue_empty(q)) + q->request_fn(q); + spin_unlock_irqrestore(q->queue_lock, flags); +} + +static void as_put_request(request_queue_t *q, struct request *rq) +{ + struct as_data *ad = q->elevator->elevator_data; + struct as_rq *arq = RQ_DATA(rq); + + if (!arq) { + WARN_ON(1); + return; + } + + if (unlikely(arq->state != AS_RQ_POSTSCHED && + arq->state != AS_RQ_PRESCHED && + arq->state != AS_RQ_MERGED)) { + printk("arq->state %d\n", arq->state); + WARN_ON(1); + } + + mempool_free(arq, ad->arq_pool); + rq->elevator_private = NULL; +} + +static int as_set_request(request_queue_t *q, struct request *rq, + struct bio *bio, gfp_t gfp_mask) +{ + struct as_data *ad = q->elevator->elevator_data; + struct as_rq *arq = mempool_alloc(ad->arq_pool, gfp_mask); + + if (arq) { + memset(arq, 0, sizeof(*arq)); + RB_CLEAR(&arq->rb_node); + arq->request = rq; + arq->state = AS_RQ_PRESCHED; + arq->io_context = NULL; + INIT_LIST_HEAD(&arq->hash); + arq->on_hash = 0; + INIT_LIST_HEAD(&arq->fifo); + rq->elevator_private = arq; + return 0; + } + + return 1; +} + +static int as_may_queue(request_queue_t *q, int rw, struct bio *bio) +{ + int ret = ELV_MQUEUE_MAY; + struct as_data *ad = q->elevator->elevator_data; + struct io_context *ioc; + if (ad->antic_status == ANTIC_WAIT_REQ || + ad->antic_status == ANTIC_WAIT_NEXT) { + ioc = as_get_io_context(); + if (ad->io_context == ioc) + ret = ELV_MQUEUE_MUST; + put_io_context(ioc); + } + + return ret; +} + +static void as_exit_queue(elevator_t *e) +{ + struct as_data *ad = e->elevator_data; + + del_timer_sync(&ad->antic_timer); + kblockd_flush(); + + BUG_ON(!list_empty(&ad->fifo_list[REQ_SYNC])); + BUG_ON(!list_empty(&ad->fifo_list[REQ_ASYNC])); + + mempool_destroy(ad->arq_pool); + put_io_context(ad->io_context); + kfree(ad->hash); + kfree(ad); +} + +/* + * initialize elevator private data (as_data), and alloc a arq for + * each request on the free lists + */ +static int as_init_queue(request_queue_t *q, elevator_t *e) +{ + struct as_data *ad; + int i; + + if (!arq_pool) + return -ENOMEM; + + ad = kmalloc_node(sizeof(*ad), GFP_KERNEL, q->node); + if (!ad) + return -ENOMEM; + memset(ad, 0, sizeof(*ad)); + + ad->q = q; /* Identify what queue the data belongs to */ + + ad->hash = kmalloc_node(sizeof(struct list_head)*AS_HASH_ENTRIES, + GFP_KERNEL, q->node); + if (!ad->hash) { + kfree(ad); + return -ENOMEM; + } + + ad->arq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab, + mempool_free_slab, arq_pool, q->node); + if (!ad->arq_pool) { + kfree(ad->hash); + kfree(ad); + return -ENOMEM; + } + + /* anticipatory scheduling helpers */ + ad->antic_timer.function = as_antic_timeout; + ad->antic_timer.data = (unsigned long)q; + init_timer(&ad->antic_timer); + INIT_WORK(&ad->antic_work, as_work_handler, q); + + for (i = 0; i < AS_HASH_ENTRIES; i++) + INIT_LIST_HEAD(&ad->hash[i]); + + INIT_LIST_HEAD(&ad->fifo_list[REQ_SYNC]); + INIT_LIST_HEAD(&ad->fifo_list[REQ_ASYNC]); + ad->sort_list[REQ_SYNC] = RB_ROOT; + ad->sort_list[REQ_ASYNC] = RB_ROOT; + ad->fifo_expire[REQ_SYNC] = default_read_expire; + ad->fifo_expire[REQ_ASYNC] = default_write_expire; + ad->antic_expire = default_antic_expire; + ad->batch_expire[REQ_SYNC] = default_read_batch_expire; + ad->batch_expire[REQ_ASYNC] = default_write_batch_expire; + e->elevator_data = ad; + + ad->current_batch_expires = jiffies + ad->batch_expire[REQ_SYNC]; + ad->write_batch_count = ad->batch_expire[REQ_ASYNC] / 10; + if (ad->write_batch_count < 2) + ad->write_batch_count = 2; + + return 0; +} + +/* + * sysfs parts below + */ +struct as_fs_entry { + struct attribute attr; + ssize_t (*show)(struct as_data *, char *); + ssize_t (*store)(struct as_data *, const char *, size_t); +}; + +static ssize_t +as_var_show(unsigned int var, char *page) +{ + return sprintf(page, "%d\n", var); +} + +static ssize_t +as_var_store(unsigned long *var, const char *page, size_t count) +{ + char *p = (char *) page; + + *var = simple_strtoul(p, &p, 10); + return count; +} + +static ssize_t as_est_show(struct as_data *ad, char *page) +{ + int pos = 0; + + pos += sprintf(page+pos, "%lu %% exit probability\n", 100*ad->exit_prob/256); + pos += sprintf(page+pos, "%lu ms new thinktime\n", ad->new_ttime_mean); + pos += sprintf(page+pos, "%llu sectors new seek distance\n", (unsigned long long)ad->new_seek_mean); + + return pos; +} + +#define SHOW_FUNCTION(__FUNC, __VAR) \ +static ssize_t __FUNC(struct as_data *ad, char *page) \ +{ \ + return as_var_show(jiffies_to_msecs((__VAR)), (page)); \ +} +SHOW_FUNCTION(as_readexpire_show, ad->fifo_expire[REQ_SYNC]); +SHOW_FUNCTION(as_writeexpire_show, ad->fifo_expire[REQ_ASYNC]); +SHOW_FUNCTION(as_anticexpire_show, ad->antic_expire); +SHOW_FUNCTION(as_read_batchexpire_show, ad->batch_expire[REQ_SYNC]); +SHOW_FUNCTION(as_write_batchexpire_show, ad->batch_expire[REQ_ASYNC]); +#undef SHOW_FUNCTION + +#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX) \ +static ssize_t __FUNC(struct as_data *ad, const char *page, size_t count) \ +{ \ + int ret = as_var_store(__PTR, (page), count); \ + if (*(__PTR) < (MIN)) \ + *(__PTR) = (MIN); \ + else if (*(__PTR) > (MAX)) \ + *(__PTR) = (MAX); \ + *(__PTR) = msecs_to_jiffies(*(__PTR)); \ + return ret; \ +} +STORE_FUNCTION(as_readexpire_store, &ad->fifo_expire[REQ_SYNC], 0, INT_MAX); +STORE_FUNCTION(as_writeexpire_store, &ad->fifo_expire[REQ_ASYNC], 0, INT_MAX); +STORE_FUNCTION(as_anticexpire_store, &ad->antic_expire, 0, INT_MAX); +STORE_FUNCTION(as_read_batchexpire_store, + &ad->batch_expire[REQ_SYNC], 0, INT_MAX); +STORE_FUNCTION(as_write_batchexpire_store, + &ad->batch_expire[REQ_ASYNC], 0, INT_MAX); +#undef STORE_FUNCTION + +static struct as_fs_entry as_est_entry = { + .attr = {.name = "est_time", .mode = S_IRUGO }, + .show = as_est_show, +}; +static struct as_fs_entry as_readexpire_entry = { + .attr = {.name = "read_expire", .mode = S_IRUGO | S_IWUSR }, + .show = as_readexpire_show, + .store = as_readexpire_store, +}; +static struct as_fs_entry as_writeexpire_entry = { + .attr = {.name = "write_expire", .mode = S_IRUGO | S_IWUSR }, + .show = as_writeexpire_show, + .store = as_writeexpire_store, +}; +static struct as_fs_entry as_anticexpire_entry = { + .attr = {.name = "antic_expire", .mode = S_IRUGO | S_IWUSR }, + .show = as_anticexpire_show, + .store = as_anticexpire_store, +}; +static struct as_fs_entry as_read_batchexpire_entry = { + .attr = {.name = "read_batch_expire", .mode = S_IRUGO | S_IWUSR }, + .show = as_read_batchexpire_show, + .store = as_read_batchexpire_store, +}; +static struct as_fs_entry as_write_batchexpire_entry = { + .attr = {.name = "write_batch_expire", .mode = S_IRUGO | S_IWUSR }, + .show = as_write_batchexpire_show, + .store = as_write_batchexpire_store, +}; + +static struct attribute *default_attrs[] = { + &as_est_entry.attr, + &as_readexpire_entry.attr, + &as_writeexpire_entry.attr, + &as_anticexpire_entry.attr, + &as_read_batchexpire_entry.attr, + &as_write_batchexpire_entry.attr, + NULL, +}; + +#define to_as(atr) container_of((atr), struct as_fs_entry, attr) + +static ssize_t +as_attr_show(struct kobject *kobj, struct attribute *attr, char *page) +{ + elevator_t *e = container_of(kobj, elevator_t, kobj); + struct as_fs_entry *entry = to_as(attr); + + if (!entry->show) + return -EIO; + + return entry->show(e->elevator_data, page); +} + +static ssize_t +as_attr_store(struct kobject *kobj, struct attribute *attr, + const char *page, size_t length) +{ + elevator_t *e = container_of(kobj, elevator_t, kobj); + struct as_fs_entry *entry = to_as(attr); + + if (!entry->store) + return -EIO; + + return entry->store(e->elevator_data, page, length); +} + +static struct sysfs_ops as_sysfs_ops = { + .show = as_attr_show, + .store = as_attr_store, +}; + +static struct kobj_type as_ktype = { + .sysfs_ops = &as_sysfs_ops, + .default_attrs = default_attrs, +}; + +static struct elevator_type iosched_as = { + .ops = { + .elevator_merge_fn = as_merge, + .elevator_merged_fn = as_merged_request, + .elevator_merge_req_fn = as_merged_requests, + .elevator_dispatch_fn = as_dispatch_request, + .elevator_add_req_fn = as_add_request, + .elevator_activate_req_fn = as_activate_request, + .elevator_deactivate_req_fn = as_deactivate_request, + .elevator_queue_empty_fn = as_queue_empty, + .elevator_completed_req_fn = as_completed_request, + .elevator_former_req_fn = as_former_request, + .elevator_latter_req_fn = as_latter_request, + .elevator_set_req_fn = as_set_request, + .elevator_put_req_fn = as_put_request, + .elevator_may_queue_fn = as_may_queue, + .elevator_init_fn = as_init_queue, + .elevator_exit_fn = as_exit_queue, + }, + + .elevator_ktype = &as_ktype, + .elevator_name = "anticipatory", + .elevator_owner = THIS_MODULE, +}; + +static int __init as_init(void) +{ + int ret; + + arq_pool = kmem_cache_create("as_arq", sizeof(struct as_rq), + 0, 0, NULL, NULL); + if (!arq_pool) + return -ENOMEM; + + ret = elv_register(&iosched_as); + if (!ret) { + /* + * don't allow AS to get unregistered, since we would have + * to browse all tasks in the system and release their + * as_io_context first + */ + __module_get(THIS_MODULE); + return 0; + } + + kmem_cache_destroy(arq_pool); + return ret; +} + +static void __exit as_exit(void) +{ + elv_unregister(&iosched_as); + kmem_cache_destroy(arq_pool); +} + +module_init(as_init); +module_exit(as_exit); + +MODULE_AUTHOR("Nick Piggin"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("anticipatory IO scheduler"); diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c new file mode 100644 index 00000000000..ecacca9c877 --- /dev/null +++ b/block/cfq-iosched.c @@ -0,0 +1,2428 @@ +/* + * linux/drivers/block/cfq-iosched.c + * + * CFQ, or complete fairness queueing, disk scheduler. + * + * Based on ideas from a previously unfinished io + * scheduler (round robin per-process disk scheduling) and Andrea Arcangeli. + * + * Copyright (C) 2003 Jens Axboe + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * tunables + */ +static int cfq_quantum = 4; /* max queue in one round of service */ +static int cfq_queued = 8; /* minimum rq allocate limit per-queue*/ +static int cfq_fifo_expire[2] = { HZ / 4, HZ / 8 }; +static int cfq_back_max = 16 * 1024; /* maximum backwards seek, in KiB */ +static int cfq_back_penalty = 2; /* penalty of a backwards seek */ + +static int cfq_slice_sync = HZ / 10; +static int cfq_slice_async = HZ / 25; +static int cfq_slice_async_rq = 2; +static int cfq_slice_idle = HZ / 100; + +#define CFQ_IDLE_GRACE (HZ / 10) +#define CFQ_SLICE_SCALE (5) + +#define CFQ_KEY_ASYNC (0) +#define CFQ_KEY_ANY (0xffff) + +/* + * disable queueing at the driver/hardware level + */ +static int cfq_max_depth = 2; + +/* + * for the hash of cfqq inside the cfqd + */ +#define CFQ_QHASH_SHIFT 6 +#define CFQ_QHASH_ENTRIES (1 << CFQ_QHASH_SHIFT) +#define list_entry_qhash(entry) hlist_entry((entry), struct cfq_queue, cfq_hash) + +/* + * for the hash of crq inside the cfqq + */ +#define CFQ_MHASH_SHIFT 6 +#define CFQ_MHASH_BLOCK(sec) ((sec) >> 3) +#define CFQ_MHASH_ENTRIES (1 << CFQ_MHASH_SHIFT) +#define CFQ_MHASH_FN(sec) hash_long(CFQ_MHASH_BLOCK(sec), CFQ_MHASH_SHIFT) +#define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors) +#define list_entry_hash(ptr) hlist_entry((ptr), struct cfq_rq, hash) + +#define list_entry_cfqq(ptr) list_entry((ptr), struct cfq_queue, cfq_list) +#define list_entry_fifo(ptr) list_entry((ptr), struct request, queuelist) + +#define RQ_DATA(rq) (rq)->elevator_private + +/* + * rb-tree defines + */ +#define RB_NONE (2) +#define RB_EMPTY(node) ((node)->rb_node == NULL) +#define RB_CLEAR_COLOR(node) (node)->rb_color = RB_NONE +#define RB_CLEAR(node) do { \ + (node)->rb_parent = NULL; \ + RB_CLEAR_COLOR((node)); \ + (node)->rb_right = NULL; \ + (node)->rb_left = NULL; \ +} while (0) +#define RB_CLEAR_ROOT(root) ((root)->rb_node = NULL) +#define rb_entry_crq(node) rb_entry((node), struct cfq_rq, rb_node) +#define rq_rb_key(rq) (rq)->sector + +static kmem_cache_t *crq_pool; +static kmem_cache_t *cfq_pool; +static kmem_cache_t *cfq_ioc_pool; + +#define CFQ_PRIO_LISTS IOPRIO_BE_NR +#define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE) +#define cfq_class_be(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_BE) +#define cfq_class_rt(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_RT) + +#define ASYNC (0) +#define SYNC (1) + +#define cfq_cfqq_dispatched(cfqq) \ + ((cfqq)->on_dispatch[ASYNC] + (cfqq)->on_dispatch[SYNC]) + +#define cfq_cfqq_class_sync(cfqq) ((cfqq)->key != CFQ_KEY_ASYNC) + +#define cfq_cfqq_sync(cfqq) \ + (cfq_cfqq_class_sync(cfqq) || (cfqq)->on_dispatch[SYNC]) + +/* + * Per block device queue structure + */ +struct cfq_data { + atomic_t ref; + request_queue_t *queue; + + /* + * rr list of queues with requests and the count of them + */ + struct list_head rr_list[CFQ_PRIO_LISTS]; + struct list_head busy_rr; + struct list_head cur_rr; + struct list_head idle_rr; + unsigned int busy_queues; + + /* + * non-ordered list of empty cfqq's + */ + struct list_head empty_list; + + /* + * cfqq lookup hash + */ + struct hlist_head *cfq_hash; + + /* + * global crq hash for all queues + */ + struct hlist_head *crq_hash; + + unsigned int max_queued; + + mempool_t *crq_pool; + + int rq_in_driver; + + /* + * schedule slice state info + */ + /* + * idle window management + */ + struct timer_list idle_slice_timer; + struct work_struct unplug_work; + + struct cfq_queue *active_queue; + struct cfq_io_context *active_cic; + int cur_prio, cur_end_prio; + unsigned int dispatch_slice; + + struct timer_list idle_class_timer; + + sector_t last_sector; + unsigned long last_end_request; + + unsigned int rq_starved; + + /* + * tunables, see top of file + */ + unsigned int cfq_quantum; + unsigned int cfq_queued; + unsigned int cfq_fifo_expire[2]; + unsigned int cfq_back_penalty; + unsigned int cfq_back_max; + unsigned int cfq_slice[2]; + unsigned int cfq_slice_async_rq; + unsigned int cfq_slice_idle; + unsigned int cfq_max_depth; +}; + +/* + * Per process-grouping structure + */ +struct cfq_queue { + /* reference count */ + atomic_t ref; + /* parent cfq_data */ + struct cfq_data *cfqd; + /* cfqq lookup hash */ + struct hlist_node cfq_hash; + /* hash key */ + unsigned int key; + /* on either rr or empty list of cfqd */ + struct list_head cfq_list; + /* sorted list of pending requests */ + struct rb_root sort_list; + /* if fifo isn't expired, next request to serve */ + struct cfq_rq *next_crq; + /* requests queued in sort_list */ + int queued[2]; + /* currently allocated requests */ + int allocated[2]; + /* fifo list of requests in sort_list */ + struct list_head fifo; + + unsigned long slice_start; + unsigned long slice_end; + unsigned long slice_left; + unsigned long service_last; + + /* number of requests that are on the dispatch list */ + int on_dispatch[2]; + + /* io prio of this group */ + unsigned short ioprio, org_ioprio; + unsigned short ioprio_class, org_ioprio_class; + + /* various state flags, see below */ + unsigned int flags; +}; + +struct cfq_rq { + struct rb_node rb_node; + sector_t rb_key; + struct request *request; + struct hlist_node hash; + + struct cfq_queue *cfq_queue; + struct cfq_io_context *io_context; + + unsigned int crq_flags; +}; + +enum cfqq_state_flags { + CFQ_CFQQ_FLAG_on_rr = 0, + CFQ_CFQQ_FLAG_wait_request, + CFQ_CFQQ_FLAG_must_alloc, + CFQ_CFQQ_FLAG_must_alloc_slice, + CFQ_CFQQ_FLAG_must_dispatch, + CFQ_CFQQ_FLAG_fifo_expire, + CFQ_CFQQ_FLAG_idle_window, + CFQ_CFQQ_FLAG_prio_changed, + CFQ_CFQQ_FLAG_expired, +}; + +#define CFQ_CFQQ_FNS(name) \ +static inline void cfq_mark_cfqq_##name(struct cfq_queue *cfqq) \ +{ \ + cfqq->flags |= (1 << CFQ_CFQQ_FLAG_##name); \ +} \ +static inline void cfq_clear_cfqq_##name(struct cfq_queue *cfqq) \ +{ \ + cfqq->flags &= ~(1 << CFQ_CFQQ_FLAG_##name); \ +} \ +static inline int cfq_cfqq_##name(const struct cfq_queue *cfqq) \ +{ \ + return (cfqq->flags & (1 << CFQ_CFQQ_FLAG_##name)) != 0; \ +} + +CFQ_CFQQ_FNS(on_rr); +CFQ_CFQQ_FNS(wait_request); +CFQ_CFQQ_FNS(must_alloc); +CFQ_CFQQ_FNS(must_alloc_slice); +CFQ_CFQQ_FNS(must_dispatch); +CFQ_CFQQ_FNS(fifo_expire); +CFQ_CFQQ_FNS(idle_window); +CFQ_CFQQ_FNS(prio_changed); +CFQ_CFQQ_FNS(expired); +#undef CFQ_CFQQ_FNS + +enum cfq_rq_state_flags { + CFQ_CRQ_FLAG_is_sync = 0, +}; + +#define CFQ_CRQ_FNS(name) \ +static inline void cfq_mark_crq_##name(struct cfq_rq *crq) \ +{ \ + crq->crq_flags |= (1 << CFQ_CRQ_FLAG_##name); \ +} \ +static inline void cfq_clear_crq_##name(struct cfq_rq *crq) \ +{ \ + crq->crq_flags &= ~(1 << CFQ_CRQ_FLAG_##name); \ +} \ +static inline int cfq_crq_##name(const struct cfq_rq *crq) \ +{ \ + return (crq->crq_flags & (1 << CFQ_CRQ_FLAG_##name)) != 0; \ +} + +CFQ_CRQ_FNS(is_sync); +#undef CFQ_CRQ_FNS + +static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short); +static void cfq_dispatch_insert(request_queue_t *, struct cfq_rq *); +static void cfq_put_cfqd(struct cfq_data *cfqd); + +#define process_sync(tsk) ((tsk)->flags & PF_SYNCWRITE) + +/* + * lots of deadline iosched dupes, can be abstracted later... + */ +static inline void cfq_del_crq_hash(struct cfq_rq *crq) +{ + hlist_del_init(&crq->hash); +} + +static inline void cfq_add_crq_hash(struct cfq_data *cfqd, struct cfq_rq *crq) +{ + const int hash_idx = CFQ_MHASH_FN(rq_hash_key(crq->request)); + + hlist_add_head(&crq->hash, &cfqd->crq_hash[hash_idx]); +} + +static struct request *cfq_find_rq_hash(struct cfq_data *cfqd, sector_t offset) +{ + struct hlist_head *hash_list = &cfqd->crq_hash[CFQ_MHASH_FN(offset)]; + struct hlist_node *entry, *next; + + hlist_for_each_safe(entry, next, hash_list) { + struct cfq_rq *crq = list_entry_hash(entry); + struct request *__rq = crq->request; + + if (!rq_mergeable(__rq)) { + cfq_del_crq_hash(crq); + continue; + } + + if (rq_hash_key(__rq) == offset) + return __rq; + } + + return NULL; +} + +/* + * scheduler run of queue, if there are requests pending and no one in the + * driver that will restart queueing + */ +static inline void cfq_schedule_dispatch(struct cfq_data *cfqd) +{ + if (!cfqd->rq_in_driver && cfqd->busy_queues) + kblockd_schedule_work(&cfqd->unplug_work); +} + +static int cfq_queue_empty(request_queue_t *q) +{ + struct cfq_data *cfqd = q->elevator->elevator_data; + + return !cfqd->busy_queues; +} + +/* + * Lifted from AS - choose which of crq1 and crq2 that is best served now. + * We choose the request that is closest to the head right now. Distance + * behind the head are penalized and only allowed to a certain extent. + */ +static struct cfq_rq * +cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2) +{ + sector_t last, s1, s2, d1 = 0, d2 = 0; + int r1_wrap = 0, r2_wrap = 0; /* requests are behind the disk head */ + unsigned long back_max; + + if (crq1 == NULL || crq1 == crq2) + return crq2; + if (crq2 == NULL) + return crq1; + + if (cfq_crq_is_sync(crq1) && !cfq_crq_is_sync(crq2)) + return crq1; + else if (cfq_crq_is_sync(crq2) && !cfq_crq_is_sync(crq1)) + return crq2; + + s1 = crq1->request->sector; + s2 = crq2->request->sector; + + last = cfqd->last_sector; + + /* + * by definition, 1KiB is 2 sectors + */ + back_max = cfqd->cfq_back_max * 2; + + /* + * Strict one way elevator _except_ in the case where we allow + * short backward seeks which are biased as twice the cost of a + * similar forward seek. + */ + if (s1 >= last) + d1 = s1 - last; + else if (s1 + back_max >= last) + d1 = (last - s1) * cfqd->cfq_back_penalty; + else + r1_wrap = 1; + + if (s2 >= last) + d2 = s2 - last; + else if (s2 + back_max >= last) + d2 = (last - s2) * cfqd->cfq_back_penalty; + else + r2_wrap = 1; + + /* Found required data */ + if (!r1_wrap && r2_wrap) + return crq1; + else if (!r2_wrap && r1_wrap) + return crq2; + else if (r1_wrap && r2_wrap) { + /* both behind the head */ + if (s1 <= s2) + return crq1; + else + return crq2; + } + + /* Both requests in front of the head */ + if (d1 < d2) + return crq1; + else if (d2 < d1) + return crq2; + else { + if (s1 >= s2) + return crq1; + else + return crq2; + } +} + +/* + * would be nice to take fifo expire time into account as well + */ +static struct cfq_rq * +cfq_find_next_crq(struct cfq_data *cfqd, struct cfq_queue *cfqq, + struct cfq_rq *last) +{ + struct cfq_rq *crq_next = NULL, *crq_prev = NULL; + struct rb_node *rbnext, *rbprev; + + if (!(rbnext = rb_next(&last->rb_node))) { + rbnext = rb_first(&cfqq->sort_list); + if (rbnext == &last->rb_node) + rbnext = NULL; + } + + rbprev = rb_prev(&last->rb_node); + + if (rbprev) + crq_prev = rb_entry_crq(rbprev); + if (rbnext) + crq_next = rb_entry_crq(rbnext); + + return cfq_choose_req(cfqd, crq_next, crq_prev); +} + +static void cfq_update_next_crq(struct cfq_rq *crq) +{ + struct cfq_queue *cfqq = crq->cfq_queue; + + if (cfqq->next_crq == crq) + cfqq->next_crq = cfq_find_next_crq(cfqq->cfqd, cfqq, crq); +} + +static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted) +{ + struct cfq_data *cfqd = cfqq->cfqd; + struct list_head *list, *entry; + + BUG_ON(!cfq_cfqq_on_rr(cfqq)); + + list_del(&cfqq->cfq_list); + + if (cfq_class_rt(cfqq)) + list = &cfqd->cur_rr; + else if (cfq_class_idle(cfqq)) + list = &cfqd->idle_rr; + else { + /* + * if cfqq has requests in flight, don't allow it to be + * found in cfq_set_active_queue before it has finished them. + * this is done to increase fairness between a process that + * has lots of io pending vs one that only generates one + * sporadically or synchronously + */ + if (cfq_cfqq_dispatched(cfqq)) + list = &cfqd->busy_rr; + else + list = &cfqd->rr_list[cfqq->ioprio]; + } + + /* + * if queue was preempted, just add to front to be fair. busy_rr + * isn't sorted. + */ + if (preempted || list == &cfqd->busy_rr) { + list_add(&cfqq->cfq_list, list); + return; + } + + /* + * sort by when queue was last serviced + */ + entry = list; + while ((entry = entry->prev) != list) { + struct cfq_queue *__cfqq = list_entry_cfqq(entry); + + if (!__cfqq->service_last) + break; + if (time_before(__cfqq->service_last, cfqq->service_last)) + break; + } + + list_add(&cfqq->cfq_list, entry); +} + +/* + * add to busy list of queues for service, trying to be fair in ordering + * the pending list according to last request service + */ +static inline void +cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) +{ + BUG_ON(cfq_cfqq_on_rr(cfqq)); + cfq_mark_cfqq_on_rr(cfqq); + cfqd->busy_queues++; + + cfq_resort_rr_list(cfqq, 0); +} + +static inline void +cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) +{ + BUG_ON(!cfq_cfqq_on_rr(cfqq)); + cfq_clear_cfqq_on_rr(cfqq); + list_move(&cfqq->cfq_list, &cfqd->empty_list); + + BUG_ON(!cfqd->busy_queues); + cfqd->busy_queues--; +} + +/* + * rb tree support functions + */ +static inline void cfq_del_crq_rb(struct cfq_rq *crq) +{ + struct cfq_queue *cfqq = crq->cfq_queue; + struct cfq_data *cfqd = cfqq->cfqd; + const int sync = cfq_crq_is_sync(crq); + + BUG_ON(!cfqq->queued[sync]); + cfqq->queued[sync]--; + + cfq_update_next_crq(crq); + + rb_erase(&crq->rb_node, &cfqq->sort_list); + RB_CLEAR_COLOR(&crq->rb_node); + + if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY(&cfqq->sort_list)) + cfq_del_cfqq_rr(cfqd, cfqq); +} + +static struct cfq_rq * +__cfq_add_crq_rb(struct cfq_rq *crq) +{ + struct rb_node **p = &crq->cfq_queue->sort_list.rb_node; + struct rb_node *parent = NULL; + struct cfq_rq *__crq; + + while (*p) { + parent = *p; + __crq = rb_entry_crq(parent); + + if (crq->rb_key < __crq->rb_key) + p = &(*p)->rb_left; + else if (crq->rb_key > __crq->rb_key) + p = &(*p)->rb_right; + else + return __crq; + } + + rb_link_node(&crq->rb_node, parent, p); + return NULL; +} + +static void cfq_add_crq_rb(struct cfq_rq *crq) +{ + struct cfq_queue *cfqq = crq->cfq_queue; + struct cfq_data *cfqd = cfqq->cfqd; + struct request *rq = crq->request; + struct cfq_rq *__alias; + + crq->rb_key = rq_rb_key(rq); + cfqq->queued[cfq_crq_is_sync(crq)]++; + + /* + * looks a little odd, but the first insert might return an alias. + * if that happens, put the alias on the dispatch list + */ + while ((__alias = __cfq_add_crq_rb(crq)) != NULL) + cfq_dispatch_insert(cfqd->queue, __alias); + + rb_insert_color(&crq->rb_node, &cfqq->sort_list); + + if (!cfq_cfqq_on_rr(cfqq)) + cfq_add_cfqq_rr(cfqd, cfqq); + + /* + * check if this request is a better next-serve candidate + */ + cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq); +} + +static inline void +cfq_reposition_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq) +{ + rb_erase(&crq->rb_node, &cfqq->sort_list); + cfqq->queued[cfq_crq_is_sync(crq)]--; + + cfq_add_crq_rb(crq); +} + +static struct request *cfq_find_rq_rb(struct cfq_data *cfqd, sector_t sector) + +{ + struct cfq_queue *cfqq = cfq_find_cfq_hash(cfqd, current->pid, CFQ_KEY_ANY); + struct rb_node *n; + + if (!cfqq) + goto out; + + n = cfqq->sort_list.rb_node; + while (n) { + struct cfq_rq *crq = rb_entry_crq(n); + + if (sector < crq->rb_key) + n = n->rb_left; + else if (sector > crq->rb_key) + n = n->rb_right; + else + return crq->request; + } + +out: + return NULL; +} + +static void cfq_activate_request(request_queue_t *q, struct request *rq) +{ + struct cfq_data *cfqd = q->elevator->elevator_data; + + cfqd->rq_in_driver++; +} + +static void cfq_deactivate_request(request_queue_t *q, struct request *rq) +{ + struct cfq_data *cfqd = q->elevator->elevator_data; + + WARN_ON(!cfqd->rq_in_driver); + cfqd->rq_in_driver--; +} + +static void cfq_remove_request(struct request *rq) +{ + struct cfq_rq *crq = RQ_DATA(rq); + + list_del_init(&rq->queuelist); + cfq_del_crq_rb(crq); + cfq_del_crq_hash(crq); +} + +static int +cfq_merge(request_queue_t *q, struct request **req, struct bio *bio) +{ + struct cfq_data *cfqd = q->elevator->elevator_data; + struct request *__rq; + int ret; + + __rq = cfq_find_rq_hash(cfqd, bio->bi_sector); + if (__rq && elv_rq_merge_ok(__rq, bio)) { + ret = ELEVATOR_BACK_MERGE; + goto out; + } + + __rq = cfq_find_rq_rb(cfqd, bio->bi_sector + bio_sectors(bio)); + if (__rq && elv_rq_merge_ok(__rq, bio)) { + ret = ELEVATOR_FRONT_MERGE; + goto out; + } + + return ELEVATOR_NO_MERGE; +out: + *req = __rq; + return ret; +} + +static void cfq_merged_request(request_queue_t *q, struct request *req) +{ + struct cfq_data *cfqd = q->elevator->elevator_data; + struct cfq_rq *crq = RQ_DATA(req); + + cfq_del_crq_hash(crq); + cfq_add_crq_hash(cfqd, crq); + + if (rq_rb_key(req) != crq->rb_key) { + struct cfq_queue *cfqq = crq->cfq_queue; + + cfq_update_next_crq(crq); + cfq_reposition_crq_rb(cfqq, crq); + } +} + +static void +cfq_merged_requests(request_queue_t *q, struct request *rq, + struct request *next) +{ + cfq_merged_request(q, rq); + + /* + * reposition in fifo if next is older than rq + */ + if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist) && + time_before(next->start_time, rq->start_time)) + list_move(&rq->queuelist, &next->queuelist); + + cfq_remove_request(next); +} + +static inline void +__cfq_set_active_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) +{ + if (cfqq) { + /* + * stop potential idle class queues waiting service + */ + del_timer(&cfqd->idle_class_timer); + + cfqq->slice_start = jiffies; + cfqq->slice_end = 0; + cfqq->slice_left = 0; + cfq_clear_cfqq_must_alloc_slice(cfqq); + cfq_clear_cfqq_fifo_expire(cfqq); + cfq_clear_cfqq_expired(cfqq); + } + + cfqd->active_queue = cfqq; +} + +/* + * 0 + * 0,1 + * 0,1,2 + * 0,1,2,3 + * 0,1,2,3,4 + * 0,1,2,3,4,5 + * 0,1,2,3,4,5,6 + * 0,1,2,3,4,5,6,7 + */ +static int cfq_get_next_prio_level(struct cfq_data *cfqd) +{ + int prio, wrap; + + prio = -1; + wrap = 0; + do { + int p; + + for (p = cfqd->cur_prio; p <= cfqd->cur_end_prio; p++) { + if (!list_empty(&cfqd->rr_list[p])) { + prio = p; + break; + } + } + + if (prio != -1) + break; + cfqd->cur_prio = 0; + if (++cfqd->cur_end_prio == CFQ_PRIO_LISTS) { + cfqd->cur_end_prio = 0; + if (wrap) + break; + wrap = 1; + } + } while (1); + + if (unlikely(prio == -1)) + return -1; + + BUG_ON(prio >= CFQ_PRIO_LISTS); + + list_splice_init(&cfqd->rr_list[prio], &cfqd->cur_rr); + + cfqd->cur_prio = prio + 1; + if (cfqd->cur_prio > cfqd->cur_end_prio) { + cfqd->cur_end_prio = cfqd->cur_prio; + cfqd->cur_prio = 0; + } + if (cfqd->cur_end_prio == CFQ_PRIO_LISTS) { + cfqd->cur_prio = 0; + cfqd->cur_end_prio = 0; + } + + return prio; +} + +static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd) +{ + struct cfq_queue *cfqq; + + /* + * if current queue is expired but not done with its requests yet, + * wait for that to happen + */ + if ((cfqq = cfqd->active_queue) != NULL) { + if (cfq_cfqq_expired(cfqq) && cfq_cfqq_dispatched(cfqq)) + return NULL; + } + + /* + * if current list is non-empty, grab first entry. if it is empty, + * get next prio level and grab first entry then if any are spliced + */ + if (!list_empty(&cfqd->cur_rr) || cfq_get_next_prio_level(cfqd) != -1) + cfqq = list_entry_cfqq(cfqd->cur_rr.next); + + /* + * if we have idle queues and no rt or be queues had pending + * requests, either allow immediate service if the grace period + * has passed or arm the idle grace timer + */ + if (!cfqq && !list_empty(&cfqd->idle_rr)) { + unsigned long end = cfqd->last_end_request + CFQ_IDLE_GRACE; + + if (time_after_eq(jiffies, end)) + cfqq = list_entry_cfqq(cfqd->idle_rr.next); + else + mod_timer(&cfqd->idle_class_timer, end); + } + + __cfq_set_active_queue(cfqd, cfqq); + return cfqq; +} + +/* + * current cfqq expired its slice (or was too idle), select new one + */ +static void +__cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq, + int preempted) +{ + unsigned long now = jiffies; + + if (cfq_cfqq_wait_request(cfqq)) + del_timer(&cfqd->idle_slice_timer); + + if (!preempted && !cfq_cfqq_dispatched(cfqq)) + cfqq->service_last = now; + + cfq_clear_cfqq_must_dispatch(cfqq); + cfq_clear_cfqq_wait_request(cfqq); + + /* + * store what was left of this slice, if the queue idled out + * or was preempted + */ + if (time_after(now, cfqq->slice_end)) + cfqq->slice_left = now - cfqq->slice_end; + else + cfqq->slice_left = 0; + + if (cfq_cfqq_on_rr(cfqq)) + cfq_resort_rr_list(cfqq, preempted); + + if (cfqq == cfqd->active_queue) + cfqd->active_queue = NULL; + + if (cfqd->active_cic) { + put_io_context(cfqd->active_cic->ioc); + cfqd->active_cic = NULL; + } + + cfqd->dispatch_slice = 0; +} + +static inline void cfq_slice_expired(struct cfq_data *cfqd, int preempted) +{ + struct cfq_queue *cfqq = cfqd->active_queue; + + if (cfqq) { + /* + * use deferred expiry, if there are requests in progress as + * not to disturb the slice of the next queue + */ + if (cfq_cfqq_dispatched(cfqq)) + cfq_mark_cfqq_expired(cfqq); + else + __cfq_slice_expired(cfqd, cfqq, preempted); + } +} + +static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq) + +{ + WARN_ON(!RB_EMPTY(&cfqq->sort_list)); + WARN_ON(cfqq != cfqd->active_queue); + + /* + * idle is disabled, either manually or by past process history + */ + if (!cfqd->cfq_slice_idle) + return 0; + if (!cfq_cfqq_idle_window(cfqq)) + return 0; + /* + * task has exited, don't wait + */ + if (cfqd->active_cic && !cfqd->active_cic->ioc->task) + return 0; + + cfq_mark_cfqq_must_dispatch(cfqq); + cfq_mark_cfqq_wait_request(cfqq); + + if (!timer_pending(&cfqd->idle_slice_timer)) { + unsigned long slice_left = min(cfqq->slice_end - 1, (unsigned long) cfqd->cfq_slice_idle); + + cfqd->idle_slice_timer.expires = jiffies + slice_left; + add_timer(&cfqd->idle_slice_timer); + } + + return 1; +} + +static void cfq_dispatch_insert(request_queue_t *q, struct cfq_rq *crq) +{ + struct cfq_data *cfqd = q->elevator->elevator_data; + struct cfq_queue *cfqq = crq->cfq_queue; + + cfqq->next_crq = cfq_find_next_crq(cfqd, cfqq, crq); + cfq_remove_request(crq->request); + cfqq->on_dispatch[cfq_crq_is_sync(crq)]++; + elv_dispatch_sort(q, crq->request); +} + +/* + * return expired entry, or NULL to just start from scratch in rbtree + */ +static inline struct cfq_rq *cfq_check_fifo(struct cfq_queue *cfqq) +{ + struct cfq_data *cfqd = cfqq->cfqd; + struct request *rq; + struct cfq_rq *crq; + + if (cfq_cfqq_fifo_expire(cfqq)) + return NULL; + + if (!list_empty(&cfqq->fifo)) { + int fifo = cfq_cfqq_class_sync(cfqq); + + crq = RQ_DATA(list_entry_fifo(cfqq->fifo.next)); + rq = crq->request; + if (time_after(jiffies, rq->start_time + cfqd->cfq_fifo_expire[fifo])) { + cfq_mark_cfqq_fifo_expire(cfqq); + return crq; + } + } + + return NULL; +} + +/* + * Scale schedule slice based on io priority. Use the sync time slice only + * if a queue is marked sync and has sync io queued. A sync queue with async + * io only, should not get full sync slice length. + */ +static inline int +cfq_prio_to_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq) +{ + const int base_slice = cfqd->cfq_slice[cfq_cfqq_sync(cfqq)]; + + WARN_ON(cfqq->ioprio >= IOPRIO_BE_NR); + + return base_slice + (base_slice/CFQ_SLICE_SCALE * (4 - cfqq->ioprio)); +} + +static inline void +cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq) +{ + cfqq->slice_end = cfq_prio_to_slice(cfqd, cfqq) + jiffies; +} + +static inline int +cfq_prio_to_maxrq(struct cfq_data *cfqd, struct cfq_queue *cfqq) +{ + const int base_rq = cfqd->cfq_slice_async_rq; + + WARN_ON(cfqq->ioprio >= IOPRIO_BE_NR); + + return 2 * (base_rq + base_rq * (CFQ_PRIO_LISTS - 1 - cfqq->ioprio)); +} + +/* + * get next queue for service + */ +static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd, int force) +{ + unsigned long now = jiffies; + struct cfq_queue *cfqq; + + cfqq = cfqd->active_queue; + if (!cfqq) + goto new_queue; + + if (cfq_cfqq_expired(cfqq)) + goto new_queue; + + /* + * slice has expired + */ + if (!cfq_cfqq_must_dispatch(cfqq) && time_after(now, cfqq->slice_end)) + goto expire; + + /* + * if queue has requests, dispatch one. if not, check if + * enough slice is left to wait for one + */ + if (!RB_EMPTY(&cfqq->sort_list)) + goto keep_queue; + else if (!force && cfq_cfqq_class_sync(cfqq) && + time_before(now, cfqq->slice_end)) { + if (cfq_arm_slice_timer(cfqd, cfqq)) + return NULL; + } + +expire: + cfq_slice_expired(cfqd, 0); +new_queue: + cfqq = cfq_set_active_queue(cfqd); +keep_queue: + return cfqq; +} + +static int +__cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq, + int max_dispatch) +{ + int dispatched = 0; + + BUG_ON(RB_EMPTY(&cfqq->sort_list)); + + do { + struct cfq_rq *crq; + + /* + * follow expired path, else get first next available + */ + if ((crq = cfq_check_fifo(cfqq)) == NULL) + crq = cfqq->next_crq; + + /* + * finally, insert request into driver dispatch list + */ + cfq_dispatch_insert(cfqd->queue, crq); + + cfqd->dispatch_slice++; + dispatched++; + + if (!cfqd->active_cic) { + atomic_inc(&crq->io_context->ioc->refcount); + cfqd->active_cic = crq->io_context; + } + + if (RB_EMPTY(&cfqq->sort_list)) + break; + + } while (dispatched < max_dispatch); + + /* + * if slice end isn't set yet, set it. if at least one request was + * sync, use the sync time slice value + */ + if (!cfqq->slice_end) + cfq_set_prio_slice(cfqd, cfqq); + + /* + * expire an async queue immediately if it has used up its slice. idle + * queue always expire after 1 dispatch round. + */ + if ((!cfq_cfqq_sync(cfqq) && + cfqd->dispatch_slice >= cfq_prio_to_maxrq(cfqd, cfqq)) || + cfq_class_idle(cfqq)) + cfq_slice_expired(cfqd, 0); + + return dispatched; +} + +static int +cfq_dispatch_requests(request_queue_t *q, int force) +{ + struct cfq_data *cfqd = q->elevator->elevator_data; + struct cfq_queue *cfqq; + + if (!cfqd->busy_queues) + return 0; + + cfqq = cfq_select_queue(cfqd, force); + if (cfqq) { + int max_dispatch; + + /* + * if idle window is disabled, allow queue buildup + */ + if (!cfq_cfqq_idle_window(cfqq) && + cfqd->rq_in_driver >= cfqd->cfq_max_depth) + return 0; + + cfq_clear_cfqq_must_dispatch(cfqq); + cfq_clear_cfqq_wait_request(cfqq); + del_timer(&cfqd->idle_slice_timer); + + if (!force) { + max_dispatch = cfqd->cfq_quantum; + if (cfq_class_idle(cfqq)) + max_dispatch = 1; + } else + max_dispatch = INT_MAX; + + return __cfq_dispatch_requests(cfqd, cfqq, max_dispatch); + } + + return 0; +} + +/* + * task holds one reference to the queue, dropped when task exits. each crq + * in-flight on this queue also holds a reference, dropped when crq is freed. + * + * queue lock must be held here. + */ +static void cfq_put_queue(struct cfq_queue *cfqq) +{ + struct cfq_data *cfqd = cfqq->cfqd; + + BUG_ON(atomic_read(&cfqq->ref) <= 0); + + if (!atomic_dec_and_test(&cfqq->ref)) + return; + + BUG_ON(rb_first(&cfqq->sort_list)); + BUG_ON(cfqq->allocated[READ] + cfqq->allocated[WRITE]); + BUG_ON(cfq_cfqq_on_rr(cfqq)); + + if (unlikely(cfqd->active_queue == cfqq)) { + __cfq_slice_expired(cfqd, cfqq, 0); + cfq_schedule_dispatch(cfqd); + } + + cfq_put_cfqd(cfqq->cfqd); + + /* + * it's on the empty list and still hashed + */ + list_del(&cfqq->cfq_list); + hlist_del(&cfqq->cfq_hash); + kmem_cache_free(cfq_pool, cfqq); +} + +static inline struct cfq_queue * +__cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned int prio, + const int hashval) +{ + struct hlist_head *hash_list = &cfqd->cfq_hash[hashval]; + struct hlist_node *entry, *next; + + hlist_for_each_safe(entry, next, hash_list) { + struct cfq_queue *__cfqq = list_entry_qhash(entry); + const unsigned short __p = IOPRIO_PRIO_VALUE(__cfqq->ioprio_class, __cfqq->ioprio); + + if (__cfqq->key == key && (__p == prio || prio == CFQ_KEY_ANY)) + return __cfqq; + } + + return NULL; +} + +static struct cfq_queue * +cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned short prio) +{ + return __cfq_find_cfq_hash(cfqd, key, prio, hash_long(key, CFQ_QHASH_SHIFT)); +} + +static void cfq_free_io_context(struct cfq_io_context *cic) +{ + struct cfq_io_context *__cic; + struct list_head *entry, *next; + + list_for_each_safe(entry, next, &cic->list) { + __cic = list_entry(entry, struct cfq_io_context, list); + kmem_cache_free(cfq_ioc_pool, __cic); + } + + kmem_cache_free(cfq_ioc_pool, cic); +} + +/* + * Called with interrupts disabled + */ +static void cfq_exit_single_io_context(struct cfq_io_context *cic) +{ + struct cfq_data *cfqd = cic->cfqq->cfqd; + request_queue_t *q = cfqd->queue; + + WARN_ON(!irqs_disabled()); + + spin_lock(q->queue_lock); + + if (unlikely(cic->cfqq == cfqd->active_queue)) { + __cfq_slice_expired(cfqd, cic->cfqq, 0); + cfq_schedule_dispatch(cfqd); + } + + cfq_put_queue(cic->cfqq); + cic->cfqq = NULL; + spin_unlock(q->queue_lock); +} + +/* + * Another task may update the task cic list, if it is doing a queue lookup + * on its behalf. cfq_cic_lock excludes such concurrent updates + */ +static void cfq_exit_io_context(struct cfq_io_context *cic) +{ + struct cfq_io_context *__cic; + struct list_head *entry; + unsigned long flags; + + local_irq_save(flags); + + /* + * put the reference this task is holding to the various queues + */ + list_for_each(entry, &cic->list) { + __cic = list_entry(entry, struct cfq_io_context, list); + cfq_exit_single_io_context(__cic); + } + + cfq_exit_single_io_context(cic); + local_irq_restore(flags); +} + +static struct cfq_io_context * +cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask) +{ + struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_mask); + + if (cic) { + INIT_LIST_HEAD(&cic->list); + cic->cfqq = NULL; + cic->key = NULL; + cic->last_end_request = jiffies; + cic->ttime_total = 0; + cic->ttime_samples = 0; + cic->ttime_mean = 0; + cic->dtor = cfq_free_io_context; + cic->exit = cfq_exit_io_context; + } + + return cic; +} + +static void cfq_init_prio_data(struct cfq_queue *cfqq) +{ + struct task_struct *tsk = current; + int ioprio_class; + + if (!cfq_cfqq_prio_changed(cfqq)) + return; + + ioprio_class = IOPRIO_PRIO_CLASS(tsk->ioprio); + switch (ioprio_class) { + default: + printk(KERN_ERR "cfq: bad prio %x\n", ioprio_class); + case IOPRIO_CLASS_NONE: + /* + * no prio set, place us in the middle of the BE classes + */ + cfqq->ioprio = task_nice_ioprio(tsk); + cfqq->ioprio_class = IOPRIO_CLASS_BE; + break; + case IOPRIO_CLASS_RT: + cfqq->ioprio = task_ioprio(tsk); + cfqq->ioprio_class = IOPRIO_CLASS_RT; + break; + case IOPRIO_CLASS_BE: + cfqq->ioprio = task_ioprio(tsk); + cfqq->ioprio_class = IOPRIO_CLASS_BE; + break; + case IOPRIO_CLASS_IDLE: + cfqq->ioprio_class = IOPRIO_CLASS_IDLE; + cfqq->ioprio = 7; + cfq_clear_cfqq_idle_window(cfqq); + break; + } + + /* + * keep track of original prio settings in case we have to temporarily + * elevate the priority of this queue + */ + cfqq->org_ioprio = cfqq->ioprio; + cfqq->org_ioprio_class = cfqq->ioprio_class; + + if (cfq_cfqq_on_rr(cfqq)) + cfq_resort_rr_list(cfqq, 0); + + cfq_clear_cfqq_prio_changed(cfqq); +} + +static inline void changed_ioprio(struct cfq_queue *cfqq) +{ + if (cfqq) { + struct cfq_data *cfqd = cfqq->cfqd; + + spin_lock(cfqd->queue->queue_lock); + cfq_mark_cfqq_prio_changed(cfqq); + cfq_init_prio_data(cfqq); + spin_unlock(cfqd->queue->queue_lock); + } +} + +/* + * callback from sys_ioprio_set, irqs are disabled + */ +static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio) +{ + struct cfq_io_context *cic = ioc->cic; + + changed_ioprio(cic->cfqq); + + list_for_each_entry(cic, &cic->list, list) + changed_ioprio(cic->cfqq); + + return 0; +} + +static struct cfq_queue * +cfq_get_queue(struct cfq_data *cfqd, unsigned int key, unsigned short ioprio, + gfp_t gfp_mask) +{ + const int hashval = hash_long(key, CFQ_QHASH_SHIFT); + struct cfq_queue *cfqq, *new_cfqq = NULL; + +retry: + cfqq = __cfq_find_cfq_hash(cfqd, key, ioprio, hashval); + + if (!cfqq) { + if (new_cfqq) { + cfqq = new_cfqq; + new_cfqq = NULL; + } else if (gfp_mask & __GFP_WAIT) { + spin_unlock_irq(cfqd->queue->queue_lock); + new_cfqq = kmem_cache_alloc(cfq_pool, gfp_mask); + spin_lock_irq(cfqd->queue->queue_lock); + goto retry; + } else { + cfqq = kmem_cache_alloc(cfq_pool, gfp_mask); + if (!cfqq) + goto out; + } + + memset(cfqq, 0, sizeof(*cfqq)); + + INIT_HLIST_NODE(&cfqq->cfq_hash); + INIT_LIST_HEAD(&cfqq->cfq_list); + RB_CLEAR_ROOT(&cfqq->sort_list); + INIT_LIST_HEAD(&cfqq->fifo); + + cfqq->key = key; + hlist_add_head(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]); + atomic_set(&cfqq->ref, 0); + cfqq->cfqd = cfqd; + atomic_inc(&cfqd->ref); + cfqq->service_last = 0; + /* + * set ->slice_left to allow preemption for a new process + */ + cfqq->slice_left = 2 * cfqd->cfq_slice_idle; + cfq_mark_cfqq_idle_window(cfqq); + cfq_mark_cfqq_prio_changed(cfqq); + cfq_init_prio_data(cfqq); + } + + if (new_cfqq) + kmem_cache_free(cfq_pool, new_cfqq); + + atomic_inc(&cfqq->ref); +out: + WARN_ON((gfp_mask & __GFP_WAIT) && !cfqq); + return cfqq; +} + +/* + * Setup general io context and cfq io context. There can be several cfq + * io contexts per general io context, if this process is doing io to more + * than one device managed by cfq. Note that caller is holding a reference to + * cfqq, so we don't need to worry about it disappearing + */ +static struct cfq_io_context * +cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask) +{ + struct io_context *ioc = NULL; + struct cfq_io_context *cic; + + might_sleep_if(gfp_mask & __GFP_WAIT); + + ioc = get_io_context(gfp_mask); + if (!ioc) + return NULL; + + if ((cic = ioc->cic) == NULL) { + cic = cfq_alloc_io_context(cfqd, gfp_mask); + + if (cic == NULL) + goto err; + + /* + * manually increment generic io_context usage count, it + * cannot go away since we are already holding one ref to it + */ + ioc->cic = cic; + ioc->set_ioprio = cfq_ioc_set_ioprio; + cic->ioc = ioc; + cic->key = cfqd; + atomic_inc(&cfqd->ref); + } else { + struct cfq_io_context *__cic; + + /* + * the first cic on the list is actually the head itself + */ + if (cic->key == cfqd) + goto out; + + /* + * cic exists, check if we already are there. linear search + * should be ok here, the list will usually not be more than + * 1 or a few entries long + */ + list_for_each_entry(__cic, &cic->list, list) { + /* + * this process is already holding a reference to + * this queue, so no need to get one more + */ + if (__cic->key == cfqd) { + cic = __cic; + goto out; + } + } + + /* + * nope, process doesn't have a cic assoicated with this + * cfqq yet. get a new one and add to list + */ + __cic = cfq_alloc_io_context(cfqd, gfp_mask); + if (__cic == NULL) + goto err; + + __cic->ioc = ioc; + __cic->key = cfqd; + atomic_inc(&cfqd->ref); + list_add(&__cic->list, &cic->list); + cic = __cic; + } + +out: + return cic; +err: + put_io_context(ioc); + return NULL; +} + +static void +cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic) +{ + unsigned long elapsed, ttime; + + /* + * if this context already has stuff queued, thinktime is from + * last queue not last end + */ +#if 0 + if (time_after(cic->last_end_request, cic->last_queue)) + elapsed = jiffies - cic->last_end_request; + else + elapsed = jiffies - cic->last_queue; +#else + elapsed = jiffies - cic->last_end_request; +#endif + + ttime = min(elapsed, 2UL * cfqd->cfq_slice_idle); + + cic->ttime_samples = (7*cic->ttime_samples + 256) / 8; + cic->ttime_total = (7*cic->ttime_total + 256*ttime) / 8; + cic->ttime_mean = (cic->ttime_total + 128) / cic->ttime_samples; +} + +#define sample_valid(samples) ((samples) > 80) + +/* + * Disable idle window if the process thinks too long or seeks so much that + * it doesn't matter + */ +static void +cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq, + struct cfq_io_context *cic) +{ + int enable_idle = cfq_cfqq_idle_window(cfqq); + + if (!cic->ioc->task || !cfqd->cfq_slice_idle) + enable_idle = 0; + else if (sample_valid(cic->ttime_samples)) { + if (cic->ttime_mean > cfqd->cfq_slice_idle) + enable_idle = 0; + else + enable_idle = 1; + } + + if (enable_idle) + cfq_mark_cfqq_idle_window(cfqq); + else + cfq_clear_cfqq_idle_window(cfqq); +} + + +/* + * Check if new_cfqq should preempt the currently active queue. Return 0 for + * no or if we aren't sure, a 1 will cause a preempt. + */ +static int +cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, + struct cfq_rq *crq) +{ + struct cfq_queue *cfqq = cfqd->active_queue; + + if (cfq_class_idle(new_cfqq)) + return 0; + + if (!cfqq) + return 1; + + if (cfq_class_idle(cfqq)) + return 1; + if (!cfq_cfqq_wait_request(new_cfqq)) + return 0; + /* + * if it doesn't have slice left, forget it + */ + if (new_cfqq->slice_left < cfqd->cfq_slice_idle) + return 0; + if (cfq_crq_is_sync(crq) && !cfq_cfqq_sync(cfqq)) + return 1; + + return 0; +} + +/* + * cfqq preempts the active queue. if we allowed preempt with no slice left, + * let it have half of its nominal slice. + */ +static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) +{ + struct cfq_queue *__cfqq, *next; + + list_for_each_entry_safe(__cfqq, next, &cfqd->cur_rr, cfq_list) + cfq_resort_rr_list(__cfqq, 1); + + if (!cfqq->slice_left) + cfqq->slice_left = cfq_prio_to_slice(cfqd, cfqq) / 2; + + cfqq->slice_end = cfqq->slice_left + jiffies; + __cfq_slice_expired(cfqd, cfqq, 1); + __cfq_set_active_queue(cfqd, cfqq); +} + +/* + * should really be a ll_rw_blk.c helper + */ +static void cfq_start_queueing(struct cfq_data *cfqd, struct cfq_queue *cfqq) +{ + request_queue_t *q = cfqd->queue; + + if (!blk_queue_plugged(q)) + q->request_fn(q); + else + __generic_unplug_device(q); +} + +/* + * Called when a new fs request (crq) is added (to cfqq). Check if there's + * something we should do about it + */ +static void +cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, + struct cfq_rq *crq) +{ + struct cfq_io_context *cic; + + cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq); + + /* + * we never wait for an async request and we don't allow preemption + * of an async request. so just return early + */ + if (!cfq_crq_is_sync(crq)) + return; + + cic = crq->io_context; + + cfq_update_io_thinktime(cfqd, cic); + cfq_update_idle_window(cfqd, cfqq, cic); + + cic->last_queue = jiffies; + + if (cfqq == cfqd->active_queue) { + /* + * if we are waiting for a request for this queue, let it rip + * immediately and flag that we must not expire this queue + * just now + */ + if (cfq_cfqq_wait_request(cfqq)) { + cfq_mark_cfqq_must_dispatch(cfqq); + del_timer(&cfqd->idle_slice_timer); + cfq_start_queueing(cfqd, cfqq); + } + } else if (cfq_should_preempt(cfqd, cfqq, crq)) { + /* + * not the active queue - expire current slice if it is + * idle and has expired it's mean thinktime or this new queue + * has some old slice time left and is of higher priority + */ + cfq_preempt_queue(cfqd, cfqq); + cfq_mark_cfqq_must_dispatch(cfqq); + cfq_start_queueing(cfqd, cfqq); + } +} + +static void cfq_insert_request(request_queue_t *q, struct request *rq) +{ + struct cfq_data *cfqd = q->elevator->elevator_data; + struct cfq_rq *crq = RQ_DATA(rq); + struct cfq_queue *cfqq = crq->cfq_queue; + + cfq_init_prio_data(cfqq); + + cfq_add_crq_rb(crq); + + list_add_tail(&rq->queuelist, &cfqq->fifo); + + if (rq_mergeable(rq)) + cfq_add_crq_hash(cfqd, crq); + + cfq_crq_enqueued(cfqd, cfqq, crq); +} + +static void cfq_completed_request(request_queue_t *q, struct request *rq) +{ + struct cfq_rq *crq = RQ_DATA(rq); + struct cfq_queue *cfqq = crq->cfq_queue; + struct cfq_data *cfqd = cfqq->cfqd; + const int sync = cfq_crq_is_sync(crq); + unsigned long now; + + now = jiffies; + + WARN_ON(!cfqd->rq_in_driver); + WARN_ON(!cfqq->on_dispatch[sync]); + cfqd->rq_in_driver--; + cfqq->on_dispatch[sync]--; + + if (!cfq_class_idle(cfqq)) + cfqd->last_end_request = now; + + if (!cfq_cfqq_dispatched(cfqq)) { + if (cfq_cfqq_on_rr(cfqq)) { + cfqq->service_last = now; + cfq_resort_rr_list(cfqq, 0); + } + if (cfq_cfqq_expired(cfqq)) { + __cfq_slice_expired(cfqd, cfqq, 0); + cfq_schedule_dispatch(cfqd); + } + } + + if (cfq_crq_is_sync(crq)) + crq->io_context->last_end_request = now; +} + +static struct request * +cfq_former_request(request_queue_t *q, struct request *rq) +{ + struct cfq_rq *crq = RQ_DATA(rq); + struct rb_node *rbprev = rb_prev(&crq->rb_node); + + if (rbprev) + return rb_entry_crq(rbprev)->request; + + return NULL; +} + +static struct request * +cfq_latter_request(request_queue_t *q, struct request *rq) +{ + struct cfq_rq *crq = RQ_DATA(rq); + struct rb_node *rbnext = rb_next(&crq->rb_node); + + if (rbnext) + return rb_entry_crq(rbnext)->request; + + return NULL; +} + +/* + * we temporarily boost lower priority queues if they are holding fs exclusive + * resources. they are boosted to normal prio (CLASS_BE/4) + */ +static void cfq_prio_boost(struct cfq_queue *cfqq) +{ + const int ioprio_class = cfqq->ioprio_class; + const int ioprio = cfqq->ioprio; + + if (has_fs_excl()) { + /* + * boost idle prio on transactions that would lock out other + * users of the filesystem + */ + if (cfq_class_idle(cfqq)) + cfqq->ioprio_class = IOPRIO_CLASS_BE; + if (cfqq->ioprio > IOPRIO_NORM) + cfqq->ioprio = IOPRIO_NORM; + } else { + /* + * check if we need to unboost the queue + */ + if (cfqq->ioprio_class != cfqq->org_ioprio_class) + cfqq->ioprio_class = cfqq->org_ioprio_class; + if (cfqq->ioprio != cfqq->org_ioprio) + cfqq->ioprio = cfqq->org_ioprio; + } + + /* + * refile between round-robin lists if we moved the priority class + */ + if ((ioprio_class != cfqq->ioprio_class || ioprio != cfqq->ioprio) && + cfq_cfqq_on_rr(cfqq)) + cfq_resort_rr_list(cfqq, 0); +} + +static inline pid_t cfq_queue_pid(struct task_struct *task, int rw) +{ + if (rw == READ || process_sync(task)) + return task->pid; + + return CFQ_KEY_ASYNC; +} + +static inline int +__cfq_may_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq, + struct task_struct *task, int rw) +{ +#if 1 + if ((cfq_cfqq_wait_request(cfqq) || cfq_cfqq_must_alloc(cfqq)) && + !cfq_cfqq_must_alloc_slice(cfqq)) { + cfq_mark_cfqq_must_alloc_slice(cfqq); + return ELV_MQUEUE_MUST; + } + + return ELV_MQUEUE_MAY; +#else + if (!cfqq || task->flags & PF_MEMALLOC) + return ELV_MQUEUE_MAY; + if (!cfqq->allocated[rw] || cfq_cfqq_must_alloc(cfqq)) { + if (cfq_cfqq_wait_request(cfqq)) + return ELV_MQUEUE_MUST; + + /* + * only allow 1 ELV_MQUEUE_MUST per slice, otherwise we + * can quickly flood the queue with writes from a single task + */ + if (rw == READ || !cfq_cfqq_must_alloc_slice(cfqq)) { + cfq_mark_cfqq_must_alloc_slice(cfqq); + return ELV_MQUEUE_MUST; + } + + return ELV_MQUEUE_MAY; + } + if (cfq_class_idle(cfqq)) + return ELV_MQUEUE_NO; + if (cfqq->allocated[rw] >= cfqd->max_queued) { + struct io_context *ioc = get_io_context(GFP_ATOMIC); + int ret = ELV_MQUEUE_NO; + + if (ioc && ioc->nr_batch_requests) + ret = ELV_MQUEUE_MAY; + + put_io_context(ioc); + return ret; + } + + return ELV_MQUEUE_MAY; +#endif +} + +static int cfq_may_queue(request_queue_t *q, int rw, struct bio *bio) +{ + struct cfq_data *cfqd = q->elevator->elevator_data; + struct task_struct *tsk = current; + struct cfq_queue *cfqq; + + /* + * don't force setup of a queue from here, as a call to may_queue + * does not necessarily imply that a request actually will be queued. + * so just lookup a possibly existing queue, or return 'may queue' + * if that fails + */ + cfqq = cfq_find_cfq_hash(cfqd, cfq_queue_pid(tsk, rw), tsk->ioprio); + if (cfqq) { + cfq_init_prio_data(cfqq); + cfq_prio_boost(cfqq); + + return __cfq_may_queue(cfqd, cfqq, tsk, rw); + } + + return ELV_MQUEUE_MAY; +} + +static void cfq_check_waiters(request_queue_t *q, struct cfq_queue *cfqq) +{ + struct cfq_data *cfqd = q->elevator->elevator_data; + struct request_list *rl = &q->rq; + + if (cfqq->allocated[READ] <= cfqd->max_queued || cfqd->rq_starved) { + smp_mb(); + if (waitqueue_active(&rl->wait[READ])) + wake_up(&rl->wait[READ]); + } + + if (cfqq->allocated[WRITE] <= cfqd->max_queued || cfqd->rq_starved) { + smp_mb(); + if (waitqueue_active(&rl->wait[WRITE])) + wake_up(&rl->wait[WRITE]); + } +} + +/* + * queue lock held here + */ +static void cfq_put_request(request_queue_t *q, struct request *rq) +{ + struct cfq_data *cfqd = q->elevator->elevator_data; + struct cfq_rq *crq = RQ_DATA(rq); + + if (crq) { + struct cfq_queue *cfqq = crq->cfq_queue; + const int rw = rq_data_dir(rq); + + BUG_ON(!cfqq->allocated[rw]); + cfqq->allocated[rw]--; + + put_io_context(crq->io_context->ioc); + + mempool_free(crq, cfqd->crq_pool); + rq->elevator_private = NULL; + + cfq_check_waiters(q, cfqq); + cfq_put_queue(cfqq); + } +} + +/* + * Allocate cfq data structures associated with this request. + */ +static int +cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio, + gfp_t gfp_mask) +{ + struct cfq_data *cfqd = q->elevator->elevator_data; + struct task_struct *tsk = current; + struct cfq_io_context *cic; + const int rw = rq_data_dir(rq); + pid_t key = cfq_queue_pid(tsk, rw); + struct cfq_queue *cfqq; + struct cfq_rq *crq; + unsigned long flags; + + might_sleep_if(gfp_mask & __GFP_WAIT); + + cic = cfq_get_io_context(cfqd, key, gfp_mask); + + spin_lock_irqsave(q->queue_lock, flags); + + if (!cic) + goto queue_fail; + + if (!cic->cfqq) { + cfqq = cfq_get_queue(cfqd, key, tsk->ioprio, gfp_mask); + if (!cfqq) + goto queue_fail; + + cic->cfqq = cfqq; + } else + cfqq = cic->cfqq; + + cfqq->allocated[rw]++; + cfq_clear_cfqq_must_alloc(cfqq); + cfqd->rq_starved = 0; + atomic_inc(&cfqq->ref); + spin_unlock_irqrestore(q->queue_lock, flags); + + crq = mempool_alloc(cfqd->crq_pool, gfp_mask); + if (crq) { + RB_CLEAR(&crq->rb_node); + crq->rb_key = 0; + crq->request = rq; + INIT_HLIST_NODE(&crq->hash); + crq->cfq_queue = cfqq; + crq->io_context = cic; + + if (rw == READ || process_sync(tsk)) + cfq_mark_crq_is_sync(crq); + else + cfq_clear_crq_is_sync(crq); + + rq->elevator_private = crq; + return 0; + } + + spin_lock_irqsave(q->queue_lock, flags); + cfqq->allocated[rw]--; + if (!(cfqq->allocated[0] + cfqq->allocated[1])) + cfq_mark_cfqq_must_alloc(cfqq); + cfq_put_queue(cfqq); +queue_fail: + if (cic) + put_io_context(cic->ioc); + /* + * mark us rq allocation starved. we need to kickstart the process + * ourselves if there are no pending requests that can do it for us. + * that would be an extremely rare OOM situation + */ + cfqd->rq_starved = 1; + cfq_schedule_dispatch(cfqd); + spin_unlock_irqrestore(q->queue_lock, flags); + return 1; +} + +static void cfq_kick_queue(void *data) +{ + request_queue_t *q = data; + struct cfq_data *cfqd = q->elevator->elevator_data; + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); + + if (cfqd->rq_starved) { + struct request_list *rl = &q->rq; + + /* + * we aren't guaranteed to get a request after this, but we + * have to be opportunistic + */ + smp_mb(); + if (waitqueue_active(&rl->wait[READ])) + wake_up(&rl->wait[READ]); + if (waitqueue_active(&rl->wait[WRITE])) + wake_up(&rl->wait[WRITE]); + } + + blk_remove_plug(q); + q->request_fn(q); + spin_unlock_irqrestore(q->queue_lock, flags); +} + +/* + * Timer running if the active_queue is currently idling inside its time slice + */ +static void cfq_idle_slice_timer(unsigned long data) +{ + struct cfq_data *cfqd = (struct cfq_data *) data; + struct cfq_queue *cfqq; + unsigned long flags; + + spin_lock_irqsave(cfqd->queue->queue_lock, flags); + + if ((cfqq = cfqd->active_queue) != NULL) { + unsigned long now = jiffies; + + /* + * expired + */ + if (time_after(now, cfqq->slice_end)) + goto expire; + + /* + * only expire and reinvoke request handler, if there are + * other queues with pending requests + */ + if (!cfqd->busy_queues) { + cfqd->idle_slice_timer.expires = min(now + cfqd->cfq_slice_idle, cfqq->slice_end); + add_timer(&cfqd->idle_slice_timer); + goto out_cont; + } + + /* + * not expired and it has a request pending, let it dispatch + */ + if (!RB_EMPTY(&cfqq->sort_list)) { + cfq_mark_cfqq_must_dispatch(cfqq); + goto out_kick; + } + } +expire: + cfq_slice_expired(cfqd, 0); +out_kick: + cfq_schedule_dispatch(cfqd); +out_cont: + spin_unlock_irqrestore(cfqd->queue->queue_lock, flags); +} + +/* + * Timer running if an idle class queue is waiting for service + */ +static void cfq_idle_class_timer(unsigned long data) +{ + struct cfq_data *cfqd = (struct cfq_data *) data; + unsigned long flags, end; + + spin_lock_irqsave(cfqd->queue->queue_lock, flags); + + /* + * race with a non-idle queue, reset timer + */ + end = cfqd->last_end_request + CFQ_IDLE_GRACE; + if (!time_after_eq(jiffies, end)) { + cfqd->idle_class_timer.expires = end; + add_timer(&cfqd->idle_class_timer); + } else + cfq_schedule_dispatch(cfqd); + + spin_unlock_irqrestore(cfqd->queue->queue_lock, flags); +} + +static void cfq_shutdown_timer_wq(struct cfq_data *cfqd) +{ + del_timer_sync(&cfqd->idle_slice_timer); + del_timer_sync(&cfqd->idle_class_timer); + blk_sync_queue(cfqd->queue); +} + +static void cfq_put_cfqd(struct cfq_data *cfqd) +{ + request_queue_t *q = cfqd->queue; + + if (!atomic_dec_and_test(&cfqd->ref)) + return; + + cfq_shutdown_timer_wq(cfqd); + blk_put_queue(q); + + mempool_destroy(cfqd->crq_pool); + kfree(cfqd->crq_hash); + kfree(cfqd->cfq_hash); + kfree(cfqd); +} + +static void cfq_exit_queue(elevator_t *e) +{ + struct cfq_data *cfqd = e->elevator_data; + + cfq_shutdown_timer_wq(cfqd); + cfq_put_cfqd(cfqd); +} + +static int cfq_init_queue(request_queue_t *q, elevator_t *e) +{ + struct cfq_data *cfqd; + int i; + + cfqd = kmalloc(sizeof(*cfqd), GFP_KERNEL); + if (!cfqd) + return -ENOMEM; + + memset(cfqd, 0, sizeof(*cfqd)); + + for (i = 0; i < CFQ_PRIO_LISTS; i++) + INIT_LIST_HEAD(&cfqd->rr_list[i]); + + INIT_LIST_HEAD(&cfqd->busy_rr); + INIT_LIST_HEAD(&cfqd->cur_rr); + INIT_LIST_HEAD(&cfqd->idle_rr); + INIT_LIST_HEAD(&cfqd->empty_list); + + cfqd->crq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_MHASH_ENTRIES, GFP_KERNEL); + if (!cfqd->crq_hash) + goto out_crqhash; + + cfqd->cfq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_QHASH_ENTRIES, GFP_KERNEL); + if (!cfqd->cfq_hash) + goto out_cfqhash; + + cfqd->crq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, crq_pool); + if (!cfqd->crq_pool) + goto out_crqpool; + + for (i = 0; i < CFQ_MHASH_ENTRIES; i++) + INIT_HLIST_HEAD(&cfqd->crq_hash[i]); + for (i = 0; i < CFQ_QHASH_ENTRIES; i++) + INIT_HLIST_HEAD(&cfqd->cfq_hash[i]); + + e->elevator_data = cfqd; + + cfqd->queue = q; + atomic_inc(&q->refcnt); + + cfqd->max_queued = q->nr_requests / 4; + q->nr_batching = cfq_queued; + + init_timer(&cfqd->idle_slice_timer); + cfqd->idle_slice_timer.function = cfq_idle_slice_timer; + cfqd->idle_slice_timer.data = (unsigned long) cfqd; + + init_timer(&cfqd->idle_class_timer); + cfqd->idle_class_timer.function = cfq_idle_class_timer; + cfqd->idle_class_timer.data = (unsigned long) cfqd; + + INIT_WORK(&cfqd->unplug_work, cfq_kick_queue, q); + + atomic_set(&cfqd->ref, 1); + + cfqd->cfq_queued = cfq_queued; + cfqd->cfq_quantum = cfq_quantum; + cfqd->cfq_fifo_expire[0] = cfq_fifo_expire[0]; + cfqd->cfq_fifo_expire[1] = cfq_fifo_expire[1]; + cfqd->cfq_back_max = cfq_back_max; + cfqd->cfq_back_penalty = cfq_back_penalty; + cfqd->cfq_slice[0] = cfq_slice_async; + cfqd->cfq_slice[1] = cfq_slice_sync; + cfqd->cfq_slice_async_rq = cfq_slice_async_rq; + cfqd->cfq_slice_idle = cfq_slice_idle; + cfqd->cfq_max_depth = cfq_max_depth; + + return 0; +out_crqpool: + kfree(cfqd->cfq_hash); +out_cfqhash: + kfree(cfqd->crq_hash); +out_crqhash: + kfree(cfqd); + return -ENOMEM; +} + +static void cfq_slab_kill(void) +{ + if (crq_pool) + kmem_cache_destroy(crq_pool); + if (cfq_pool) + kmem_cache_destroy(cfq_pool); + if (cfq_ioc_pool) + kmem_cache_destroy(cfq_ioc_pool); +} + +static int __init cfq_slab_setup(void) +{ + crq_pool = kmem_cache_create("crq_pool", sizeof(struct cfq_rq), 0, 0, + NULL, NULL); + if (!crq_pool) + goto fail; + + cfq_pool = kmem_cache_create("cfq_pool", sizeof(struct cfq_queue), 0, 0, + NULL, NULL); + if (!cfq_pool) + goto fail; + + cfq_ioc_pool = kmem_cache_create("cfq_ioc_pool", + sizeof(struct cfq_io_context), 0, 0, NULL, NULL); + if (!cfq_ioc_pool) + goto fail; + + return 0; +fail: + cfq_slab_kill(); + return -ENOMEM; +} + +/* + * sysfs parts below --> + */ +struct cfq_fs_entry { + struct attribute attr; + ssize_t (*show)(struct cfq_data *, char *); + ssize_t (*store)(struct cfq_data *, const char *, size_t); +}; + +static ssize_t +cfq_var_show(unsigned int var, char *page) +{ + return sprintf(page, "%d\n", var); +} + +static ssize_t +cfq_var_store(unsigned int *var, const char *page, size_t count) +{ + char *p = (char *) page; + + *var = simple_strtoul(p, &p, 10); + return count; +} + +#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ +static ssize_t __FUNC(struct cfq_data *cfqd, char *page) \ +{ \ + unsigned int __data = __VAR; \ + if (__CONV) \ + __data = jiffies_to_msecs(__data); \ + return cfq_var_show(__data, (page)); \ +} +SHOW_FUNCTION(cfq_quantum_show, cfqd->cfq_quantum, 0); +SHOW_FUNCTION(cfq_queued_show, cfqd->cfq_queued, 0); +SHOW_FUNCTION(cfq_fifo_expire_sync_show, cfqd->cfq_fifo_expire[1], 1); +SHOW_FUNCTION(cfq_fifo_expire_async_show, cfqd->cfq_fifo_expire[0], 1); +SHOW_FUNCTION(cfq_back_max_show, cfqd->cfq_back_max, 0); +SHOW_FUNCTION(cfq_back_penalty_show, cfqd->cfq_back_penalty, 0); +SHOW_FUNCTION(cfq_slice_idle_show, cfqd->cfq_slice_idle, 1); +SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1); +SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1); +SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0); +SHOW_FUNCTION(cfq_max_depth_show, cfqd->cfq_max_depth, 0); +#undef SHOW_FUNCTION + +#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ +static ssize_t __FUNC(struct cfq_data *cfqd, const char *page, size_t count) \ +{ \ + unsigned int __data; \ + int ret = cfq_var_store(&__data, (page), count); \ + if (__data < (MIN)) \ + __data = (MIN); \ + else if (__data > (MAX)) \ + __data = (MAX); \ + if (__CONV) \ + *(__PTR) = msecs_to_jiffies(__data); \ + else \ + *(__PTR) = __data; \ + return ret; \ +} +STORE_FUNCTION(cfq_quantum_store, &cfqd->cfq_quantum, 1, UINT_MAX, 0); +STORE_FUNCTION(cfq_queued_store, &cfqd->cfq_queued, 1, UINT_MAX, 0); +STORE_FUNCTION(cfq_fifo_expire_sync_store, &cfqd->cfq_fifo_expire[1], 1, UINT_MAX, 1); +STORE_FUNCTION(cfq_fifo_expire_async_store, &cfqd->cfq_fifo_expire[0], 1, UINT_MAX, 1); +STORE_FUNCTION(cfq_back_max_store, &cfqd->cfq_back_max, 0, UINT_MAX, 0); +STORE_FUNCTION(cfq_back_penalty_store, &cfqd->cfq_back_penalty, 1, UINT_MAX, 0); +STORE_FUNCTION(cfq_slice_idle_store, &cfqd->cfq_slice_idle, 0, UINT_MAX, 1); +STORE_FUNCTION(cfq_slice_sync_store, &cfqd->cfq_slice[1], 1, UINT_MAX, 1); +STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1); +STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, UINT_MAX, 0); +STORE_FUNCTION(cfq_max_depth_store, &cfqd->cfq_max_depth, 1, UINT_MAX, 0); +#undef STORE_FUNCTION + +static struct cfq_fs_entry cfq_quantum_entry = { + .attr = {.name = "quantum", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_quantum_show, + .store = cfq_quantum_store, +}; +static struct cfq_fs_entry cfq_queued_entry = { + .attr = {.name = "queued", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_queued_show, + .store = cfq_queued_store, +}; +static struct cfq_fs_entry cfq_fifo_expire_sync_entry = { + .attr = {.name = "fifo_expire_sync", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_fifo_expire_sync_show, + .store = cfq_fifo_expire_sync_store, +}; +static struct cfq_fs_entry cfq_fifo_expire_async_entry = { + .attr = {.name = "fifo_expire_async", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_fifo_expire_async_show, + .store = cfq_fifo_expire_async_store, +}; +static struct cfq_fs_entry cfq_back_max_entry = { + .attr = {.name = "back_seek_max", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_back_max_show, + .store = cfq_back_max_store, +}; +static struct cfq_fs_entry cfq_back_penalty_entry = { + .attr = {.name = "back_seek_penalty", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_back_penalty_show, + .store = cfq_back_penalty_store, +}; +static struct cfq_fs_entry cfq_slice_sync_entry = { + .attr = {.name = "slice_sync", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_slice_sync_show, + .store = cfq_slice_sync_store, +}; +static struct cfq_fs_entry cfq_slice_async_entry = { + .attr = {.name = "slice_async", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_slice_async_show, + .store = cfq_slice_async_store, +}; +static struct cfq_fs_entry cfq_slice_async_rq_entry = { + .attr = {.name = "slice_async_rq", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_slice_async_rq_show, + .store = cfq_slice_async_rq_store, +}; +static struct cfq_fs_entry cfq_slice_idle_entry = { + .attr = {.name = "slice_idle", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_slice_idle_show, + .store = cfq_slice_idle_store, +}; +static struct cfq_fs_entry cfq_max_depth_entry = { + .attr = {.name = "max_depth", .mode = S_IRUGO | S_IWUSR }, + .show = cfq_max_depth_show, + .store = cfq_max_depth_store, +}; + +static struct attribute *default_attrs[] = { + &cfq_quantum_entry.attr, + &cfq_queued_entry.attr, + &cfq_fifo_expire_sync_entry.attr, + &cfq_fifo_expire_async_entry.attr, + &cfq_back_max_entry.attr, + &cfq_back_penalty_entry.attr, + &cfq_slice_sync_entry.attr, + &cfq_slice_async_entry.attr, + &cfq_slice_async_rq_entry.attr, + &cfq_slice_idle_entry.attr, + &cfq_max_depth_entry.attr, + NULL, +}; + +#define to_cfq(atr) container_of((atr), struct cfq_fs_entry, attr) + +static ssize_t +cfq_attr_show(struct kobject *kobj, struct attribute *attr, char *page) +{ + elevator_t *e = container_of(kobj, elevator_t, kobj); + struct cfq_fs_entry *entry = to_cfq(attr); + + if (!entry->show) + return -EIO; + + return entry->show(e->elevator_data, page); +} + +static ssize_t +cfq_attr_store(struct kobject *kobj, struct attribute *attr, + const char *page, size_t length) +{ + elevator_t *e = container_of(kobj, elevator_t, kobj); + struct cfq_fs_entry *entry = to_cfq(attr); + + if (!entry->store) + return -EIO; + + return entry->store(e->elevator_data, page, length); +} + +static struct sysfs_ops cfq_sysfs_ops = { + .show = cfq_attr_show, + .store = cfq_attr_store, +}; + +static struct kobj_type cfq_ktype = { + .sysfs_ops = &cfq_sysfs_ops, + .default_attrs = default_attrs, +}; + +static struct elevator_type iosched_cfq = { + .ops = { + .elevator_merge_fn = cfq_merge, + .elevator_merged_fn = cfq_merged_request, + .elevator_merge_req_fn = cfq_merged_requests, + .elevator_dispatch_fn = cfq_dispatch_requests, + .elevator_add_req_fn = cfq_insert_request, + .elevator_activate_req_fn = cfq_activate_request, + .elevator_deactivate_req_fn = cfq_deactivate_request, + .elevator_queue_empty_fn = cfq_queue_empty, + .elevator_completed_req_fn = cfq_completed_request, + .elevator_former_req_fn = cfq_former_request, + .elevator_latter_req_fn = cfq_latter_request, + .elevator_set_req_fn = cfq_set_request, + .elevator_put_req_fn = cfq_put_request, + .elevator_may_queue_fn = cfq_may_queue, + .elevator_init_fn = cfq_init_queue, + .elevator_exit_fn = cfq_exit_queue, + }, + .elevator_ktype = &cfq_ktype, + .elevator_name = "cfq", + .elevator_owner = THIS_MODULE, +}; + +static int __init cfq_init(void) +{ + int ret; + + /* + * could be 0 on HZ < 1000 setups + */ + if (!cfq_slice_async) + cfq_slice_async = 1; + if (!cfq_slice_idle) + cfq_slice_idle = 1; + + if (cfq_slab_setup()) + return -ENOMEM; + + ret = elv_register(&iosched_cfq); + if (ret) + cfq_slab_kill(); + + return ret; +} + +static void __exit cfq_exit(void) +{ + elv_unregister(&iosched_cfq); + cfq_slab_kill(); +} + +module_init(cfq_init); +module_exit(cfq_exit); + +MODULE_AUTHOR("Jens Axboe"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Completely Fair Queueing IO scheduler"); diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c new file mode 100644 index 00000000000..7929471d7df --- /dev/null +++ b/block/deadline-iosched.c @@ -0,0 +1,878 @@ +/* + * linux/drivers/block/deadline-iosched.c + * + * Deadline i/o scheduler. + * + * Copyright (C) 2002 Jens Axboe + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * See Documentation/block/deadline-iosched.txt + */ +static int read_expire = HZ / 2; /* max time before a read is submitted. */ +static int write_expire = 5 * HZ; /* ditto for writes, these limits are SOFT! */ +static int writes_starved = 2; /* max times reads can starve a write */ +static int fifo_batch = 16; /* # of sequential requests treated as one + by the above parameters. For throughput. */ + +static const int deadline_hash_shift = 5; +#define DL_HASH_BLOCK(sec) ((sec) >> 3) +#define DL_HASH_FN(sec) (hash_long(DL_HASH_BLOCK((sec)), deadline_hash_shift)) +#define DL_HASH_ENTRIES (1 << deadline_hash_shift) +#define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors) +#define list_entry_hash(ptr) list_entry((ptr), struct deadline_rq, hash) +#define ON_HASH(drq) (drq)->on_hash + +struct deadline_data { + /* + * run time data + */ + + /* + * requests (deadline_rq s) are present on both sort_list and fifo_list + */ + struct rb_root sort_list[2]; + struct list_head fifo_list[2]; + + /* + * next in sort order. read, write or both are NULL + */ + struct deadline_rq *next_drq[2]; + struct list_head *hash; /* request hash */ + unsigned int batching; /* number of sequential requests made */ + sector_t last_sector; /* head position */ + unsigned int starved; /* times reads have starved writes */ + + /* + * settings that change how the i/o scheduler behaves + */ + int fifo_expire[2]; + int fifo_batch; + int writes_starved; + int front_merges; + + mempool_t *drq_pool; +}; + +/* + * pre-request data. + */ +struct deadline_rq { + /* + * rbtree index, key is the starting offset + */ + struct rb_node rb_node; + sector_t rb_key; + + struct request *request; + + /* + * request hash, key is the ending offset (for back merge lookup) + */ + struct list_head hash; + char on_hash; + + /* + * expire fifo + */ + struct list_head fifo; + unsigned long expires; +}; + +static void deadline_move_request(struct deadline_data *dd, struct deadline_rq *drq); + +static kmem_cache_t *drq_pool; + +#define RQ_DATA(rq) ((struct deadline_rq *) (rq)->elevator_private) + +/* + * the back merge hash support functions + */ +static inline void __deadline_del_drq_hash(struct deadline_rq *drq) +{ + drq->on_hash = 0; + list_del_init(&drq->hash); +} + +static inline void deadline_del_drq_hash(struct deadline_rq *drq) +{ + if (ON_HASH(drq)) + __deadline_del_drq_hash(drq); +} + +static inline void +deadline_add_drq_hash(struct deadline_data *dd, struct deadline_rq *drq) +{ + struct request *rq = drq->request; + + BUG_ON(ON_HASH(drq)); + + drq->on_hash = 1; + list_add(&drq->hash, &dd->hash[DL_HASH_FN(rq_hash_key(rq))]); +} + +/* + * move hot entry to front of chain + */ +static inline void +deadline_hot_drq_hash(struct deadline_data *dd, struct deadline_rq *drq) +{ + struct request *rq = drq->request; + struct list_head *head = &dd->hash[DL_HASH_FN(rq_hash_key(rq))]; + + if (ON_HASH(drq) && drq->hash.prev != head) { + list_del(&drq->hash); + list_add(&drq->hash, head); + } +} + +static struct request * +deadline_find_drq_hash(struct deadline_data *dd, sector_t offset) +{ + struct list_head *hash_list = &dd->hash[DL_HASH_FN(offset)]; + struct list_head *entry, *next = hash_list->next; + + while ((entry = next) != hash_list) { + struct deadline_rq *drq = list_entry_hash(entry); + struct request *__rq = drq->request; + + next = entry->next; + + BUG_ON(!ON_HASH(drq)); + + if (!rq_mergeable(__rq)) { + __deadline_del_drq_hash(drq); + continue; + } + + if (rq_hash_key(__rq) == offset) + return __rq; + } + + return NULL; +} + +/* + * rb tree support functions + */ +#define RB_NONE (2) +#define RB_EMPTY(root) ((root)->rb_node == NULL) +#define ON_RB(node) ((node)->rb_color != RB_NONE) +#define RB_CLEAR(node) ((node)->rb_color = RB_NONE) +#define rb_entry_drq(node) rb_entry((node), struct deadline_rq, rb_node) +#define DRQ_RB_ROOT(dd, drq) (&(dd)->sort_list[rq_data_dir((drq)->request)]) +#define rq_rb_key(rq) (rq)->sector + +static struct deadline_rq * +__deadline_add_drq_rb(struct deadline_data *dd, struct deadline_rq *drq) +{ + struct rb_node **p = &DRQ_RB_ROOT(dd, drq)->rb_node; + struct rb_node *parent = NULL; + struct deadline_rq *__drq; + + while (*p) { + parent = *p; + __drq = rb_entry_drq(parent); + + if (drq->rb_key < __drq->rb_key) + p = &(*p)->rb_left; + else if (drq->rb_key > __drq->rb_key) + p = &(*p)->rb_right; + else + return __drq; + } + + rb_link_node(&drq->rb_node, parent, p); + return NULL; +} + +static void +deadline_add_drq_rb(struct deadline_data *dd, struct deadline_rq *drq) +{ + struct deadline_rq *__alias; + + drq->rb_key = rq_rb_key(drq->request); + +retry: + __alias = __deadline_add_drq_rb(dd, drq); + if (!__alias) { + rb_insert_color(&drq->rb_node, DRQ_RB_ROOT(dd, drq)); + return; + } + + deadline_move_request(dd, __alias); + goto retry; +} + +static inline void +deadline_del_drq_rb(struct deadline_data *dd, struct deadline_rq *drq) +{ + const int data_dir = rq_data_dir(drq->request); + + if (dd->next_drq[data_dir] == drq) { + struct rb_node *rbnext = rb_next(&drq->rb_node); + + dd->next_drq[data_dir] = NULL; + if (rbnext) + dd->next_drq[data_dir] = rb_entry_drq(rbnext); + } + + BUG_ON(!ON_RB(&drq->rb_node)); + rb_erase(&drq->rb_node, DRQ_RB_ROOT(dd, drq)); + RB_CLEAR(&drq->rb_node); +} + +static struct request * +deadline_find_drq_rb(struct deadline_data *dd, sector_t sector, int data_dir) +{ + struct rb_node *n = dd->sort_list[data_dir].rb_node; + struct deadline_rq *drq; + + while (n) { + drq = rb_entry_drq(n); + + if (sector < drq->rb_key) + n = n->rb_left; + else if (sector > drq->rb_key) + n = n->rb_right; + else + return drq->request; + } + + return NULL; +} + +/* + * deadline_find_first_drq finds the first (lowest sector numbered) request + * for the specified data_dir. Used to sweep back to the start of the disk + * (1-way elevator) after we process the last (highest sector) request. + */ +static struct deadline_rq * +deadline_find_first_drq(struct deadline_data *dd, int data_dir) +{ + struct rb_node *n = dd->sort_list[data_dir].rb_node; + + for (;;) { + if (n->rb_left == NULL) + return rb_entry_drq(n); + + n = n->rb_left; + } +} + +/* + * add drq to rbtree and fifo + */ +static void +deadline_add_request(struct request_queue *q, struct request *rq) +{ + struct deadline_data *dd = q->elevator->elevator_data; + struct deadline_rq *drq = RQ_DATA(rq); + + const int data_dir = rq_data_dir(drq->request); + + deadline_add_drq_rb(dd, drq); + /* + * set expire time (only used for reads) and add to fifo list + */ + drq->expires = jiffies + dd->fifo_expire[data_dir]; + list_add_tail(&drq->fifo, &dd->fifo_list[data_dir]); + + if (rq_mergeable(rq)) + deadline_add_drq_hash(dd, drq); +} + +/* + * remove rq from rbtree, fifo, and hash + */ +static void deadline_remove_request(request_queue_t *q, struct request *rq) +{ + struct deadline_rq *drq = RQ_DATA(rq); + struct deadline_data *dd = q->elevator->elevator_data; + + list_del_init(&drq->fifo); + deadline_del_drq_rb(dd, drq); + deadline_del_drq_hash(drq); +} + +static int +deadline_merge(request_queue_t *q, struct request **req, struct bio *bio) +{ + struct deadline_data *dd = q->elevator->elevator_data; + struct request *__rq; + int ret; + + /* + * see if the merge hash can satisfy a back merge + */ + __rq = deadline_find_drq_hash(dd, bio->bi_sector); + if (__rq) { + BUG_ON(__rq->sector + __rq->nr_sectors != bio->bi_sector); + + if (elv_rq_merge_ok(__rq, bio)) { + ret = ELEVATOR_BACK_MERGE; + goto out; + } + } + + /* + * check for front merge + */ + if (dd->front_merges) { + sector_t rb_key = bio->bi_sector + bio_sectors(bio); + + __rq = deadline_find_drq_rb(dd, rb_key, bio_data_dir(bio)); + if (__rq) { + BUG_ON(rb_key != rq_rb_key(__rq)); + + if (elv_rq_merge_ok(__rq, bio)) { + ret = ELEVATOR_FRONT_MERGE; + goto out; + } + } + } + + return ELEVATOR_NO_MERGE; +out: + if (ret) + deadline_hot_drq_hash(dd, RQ_DATA(__rq)); + *req = __rq; + return ret; +} + +static void deadline_merged_request(request_queue_t *q, struct request *req) +{ + struct deadline_data *dd = q->elevator->elevator_data; + struct deadline_rq *drq = RQ_DATA(req); + + /* + * hash always needs to be repositioned, key is end sector + */ + deadline_del_drq_hash(drq); + deadline_add_drq_hash(dd, drq); + + /* + * if the merge was a front merge, we need to reposition request + */ + if (rq_rb_key(req) != drq->rb_key) { + deadline_del_drq_rb(dd, drq); + deadline_add_drq_rb(dd, drq); + } +} + +static void +deadline_merged_requests(request_queue_t *q, struct request *req, + struct request *next) +{ + struct deadline_data *dd = q->elevator->elevator_data; + struct deadline_rq *drq = RQ_DATA(req); + struct deadline_rq *dnext = RQ_DATA(next); + + BUG_ON(!drq); + BUG_ON(!dnext); + + /* + * reposition drq (this is the merged request) in hash, and in rbtree + * in case of a front merge + */ + deadline_del_drq_hash(drq); + deadline_add_drq_hash(dd, drq); + + if (rq_rb_key(req) != drq->rb_key) { + deadline_del_drq_rb(dd, drq); + deadline_add_drq_rb(dd, drq); + } + + /* + * if dnext expires before drq, assign its expire time to drq + * and move into dnext position (dnext will be deleted) in fifo + */ + if (!list_empty(&drq->fifo) && !list_empty(&dnext->fifo)) { + if (time_before(dnext->expires, drq->expires)) { + list_move(&drq->fifo, &dnext->fifo); + drq->expires = dnext->expires; + } + } + + /* + * kill knowledge of next, this one is a goner + */ + deadline_remove_request(q, next); +} + +/* + * move request from sort list to dispatch queue. + */ +static inline void +deadline_move_to_dispatch(struct deadline_data *dd, struct deadline_rq *drq) +{ + request_queue_t *q = drq->request->q; + + deadline_remove_request(q, drq->request); + elv_dispatch_add_tail(q, drq->request); +} + +/* + * move an entry to dispatch queue + */ +static void +deadline_move_request(struct deadline_data *dd, struct deadline_rq *drq) +{ + const int data_dir = rq_data_dir(drq->request); + struct rb_node *rbnext = rb_next(&drq->rb_node); + + dd->next_drq[READ] = NULL; + dd->next_drq[WRITE] = NULL; + + if (rbnext) + dd->next_drq[data_dir] = rb_entry_drq(rbnext); + + dd->last_sector = drq->request->sector + drq->request->nr_sectors; + + /* + * take it off the sort and fifo list, move + * to dispatch queue + */ + deadline_move_to_dispatch(dd, drq); +} + +#define list_entry_fifo(ptr) list_entry((ptr), struct deadline_rq, fifo) + +/* + * deadline_check_fifo returns 0 if there are no expired reads on the fifo, + * 1 otherwise. Requires !list_empty(&dd->fifo_list[data_dir]) + */ +static inline int deadline_check_fifo(struct deadline_data *dd, int ddir) +{ + struct deadline_rq *drq = list_entry_fifo(dd->fifo_list[ddir].next); + + /* + * drq is expired! + */ + if (time_after(jiffies, drq->expires)) + return 1; + + return 0; +} + +/* + * deadline_dispatch_requests selects the best request according to + * read/write expire, fifo_batch, etc + */ +static int deadline_dispatch_requests(request_queue_t *q, int force) +{ + struct deadline_data *dd = q->elevator->elevator_data; + const int reads = !list_empty(&dd->fifo_list[READ]); + const int writes = !list_empty(&dd->fifo_list[WRITE]); + struct deadline_rq *drq; + int data_dir; + + /* + * batches are currently reads XOR writes + */ + if (dd->next_drq[WRITE]) + drq = dd->next_drq[WRITE]; + else + drq = dd->next_drq[READ]; + + if (drq) { + /* we have a "next request" */ + + if (dd->last_sector != drq->request->sector) + /* end the batch on a non sequential request */ + dd->batching += dd->fifo_batch; + + if (dd->batching < dd->fifo_batch) + /* we are still entitled to batch */ + goto dispatch_request; + } + + /* + * at this point we are not running a batch. select the appropriate + * data direction (read / write) + */ + + if (reads) { + BUG_ON(RB_EMPTY(&dd->sort_list[READ])); + + if (writes && (dd->starved++ >= dd->writes_starved)) + goto dispatch_writes; + + data_dir = READ; + + goto dispatch_find_request; + } + + /* + * there are either no reads or writes have been starved + */ + + if (writes) { +dispatch_writes: + BUG_ON(RB_EMPTY(&dd->sort_list[WRITE])); + + dd->starved = 0; + + data_dir = WRITE; + + goto dispatch_find_request; + } + + return 0; + +dispatch_find_request: + /* + * we are not running a batch, find best request for selected data_dir + */ + if (deadline_check_fifo(dd, data_dir)) { + /* An expired request exists - satisfy it */ + dd->batching = 0; + drq = list_entry_fifo(dd->fifo_list[data_dir].next); + + } else if (dd->next_drq[data_dir]) { + /* + * The last req was the same dir and we have a next request in + * sort order. No expired requests so continue on from here. + */ + drq = dd->next_drq[data_dir]; + } else { + /* + * The last req was the other direction or we have run out of + * higher-sectored requests. Go back to the lowest sectored + * request (1 way elevator) and start a new batch. + */ + dd->batching = 0; + drq = deadline_find_first_drq(dd, data_dir); + } + +dispatch_request: + /* + * drq is the selected appropriate request. + */ + dd->batching++; + deadline_move_request(dd, drq); + + return 1; +} + +static int deadline_queue_empty(request_queue_t *q) +{ + struct deadline_data *dd = q->elevator->elevator_data; + + return list_empty(&dd->fifo_list[WRITE]) + && list_empty(&dd->fifo_list[READ]); +} + +static struct request * +deadline_former_request(request_queue_t *q, struct request *rq) +{ + struct deadline_rq *drq = RQ_DATA(rq); + struct rb_node *rbprev = rb_prev(&drq->rb_node); + + if (rbprev) + return rb_entry_drq(rbprev)->request; + + return NULL; +} + +static struct request * +deadline_latter_request(request_queue_t *q, struct request *rq) +{ + struct deadline_rq *drq = RQ_DATA(rq); + struct rb_node *rbnext = rb_next(&drq->rb_node); + + if (rbnext) + return rb_entry_drq(rbnext)->request; + + return NULL; +} + +static void deadline_exit_queue(elevator_t *e) +{ + struct deadline_data *dd = e->elevator_data; + + BUG_ON(!list_empty(&dd->fifo_list[READ])); + BUG_ON(!list_empty(&dd->fifo_list[WRITE])); + + mempool_destroy(dd->drq_pool); + kfree(dd->hash); + kfree(dd); +} + +/* + * initialize elevator private data (deadline_data), and alloc a drq for + * each request on the free lists + */ +static int deadline_init_queue(request_queue_t *q, elevator_t *e) +{ + struct deadline_data *dd; + int i; + + if (!drq_pool) + return -ENOMEM; + + dd = kmalloc_node(sizeof(*dd), GFP_KERNEL, q->node); + if (!dd) + return -ENOMEM; + memset(dd, 0, sizeof(*dd)); + + dd->hash = kmalloc_node(sizeof(struct list_head)*DL_HASH_ENTRIES, + GFP_KERNEL, q->node); + if (!dd->hash) { + kfree(dd); + return -ENOMEM; + } + + dd->drq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab, + mempool_free_slab, drq_pool, q->node); + if (!dd->drq_pool) { + kfree(dd->hash); + kfree(dd); + return -ENOMEM; + } + + for (i = 0; i < DL_HASH_ENTRIES; i++) + INIT_LIST_HEAD(&dd->hash[i]); + + INIT_LIST_HEAD(&dd->fifo_list[READ]); + INIT_LIST_HEAD(&dd->fifo_list[WRITE]); + dd->sort_list[READ] = RB_ROOT; + dd->sort_list[WRITE] = RB_ROOT; + dd->fifo_expire[READ] = read_expire; + dd->fifo_expire[WRITE] = write_expire; + dd->writes_starved = writes_starved; + dd->front_merges = 1; + dd->fifo_batch = fifo_batch; + e->elevator_data = dd; + return 0; +} + +static void deadline_put_request(request_queue_t *q, struct request *rq) +{ + struct deadline_data *dd = q->elevator->elevator_data; + struct deadline_rq *drq = RQ_DATA(rq); + + mempool_free(drq, dd->drq_pool); + rq->elevator_private = NULL; +} + +static int +deadline_set_request(request_queue_t *q, struct request *rq, struct bio *bio, + gfp_t gfp_mask) +{ + struct deadline_data *dd = q->elevator->elevator_data; + struct deadline_rq *drq; + + drq = mempool_alloc(dd->drq_pool, gfp_mask); + if (drq) { + memset(drq, 0, sizeof(*drq)); + RB_CLEAR(&drq->rb_node); + drq->request = rq; + + INIT_LIST_HEAD(&drq->hash); + drq->on_hash = 0; + + INIT_LIST_HEAD(&drq->fifo); + + rq->elevator_private = drq; + return 0; + } + + return 1; +} + +/* + * sysfs parts below + */ +struct deadline_fs_entry { + struct attribute attr; + ssize_t (*show)(struct deadline_data *, char *); + ssize_t (*store)(struct deadline_data *, const char *, size_t); +}; + +static ssize_t +deadline_var_show(int var, char *page) +{ + return sprintf(page, "%d\n", var); +} + +static ssize_t +deadline_var_store(int *var, const char *page, size_t count) +{ + char *p = (char *) page; + + *var = simple_strtol(p, &p, 10); + return count; +} + +#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ +static ssize_t __FUNC(struct deadline_data *dd, char *page) \ +{ \ + int __data = __VAR; \ + if (__CONV) \ + __data = jiffies_to_msecs(__data); \ + return deadline_var_show(__data, (page)); \ +} +SHOW_FUNCTION(deadline_readexpire_show, dd->fifo_expire[READ], 1); +SHOW_FUNCTION(deadline_writeexpire_show, dd->fifo_expire[WRITE], 1); +SHOW_FUNCTION(deadline_writesstarved_show, dd->writes_starved, 0); +SHOW_FUNCTION(deadline_frontmerges_show, dd->front_merges, 0); +SHOW_FUNCTION(deadline_fifobatch_show, dd->fifo_batch, 0); +#undef SHOW_FUNCTION + +#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ +static ssize_t __FUNC(struct deadline_data *dd, const char *page, size_t count) \ +{ \ + int __data; \ + int ret = deadline_var_store(&__data, (page), count); \ + if (__data < (MIN)) \ + __data = (MIN); \ + else if (__data > (MAX)) \ + __data = (MAX); \ + if (__CONV) \ + *(__PTR) = msecs_to_jiffies(__data); \ + else \ + *(__PTR) = __data; \ + return ret; \ +} +STORE_FUNCTION(deadline_readexpire_store, &dd->fifo_expire[READ], 0, INT_MAX, 1); +STORE_FUNCTION(deadline_writeexpire_store, &dd->fifo_expire[WRITE], 0, INT_MAX, 1); +STORE_FUNCTION(deadline_writesstarved_store, &dd->writes_starved, INT_MIN, INT_MAX, 0); +STORE_FUNCTION(deadline_frontmerges_store, &dd->front_merges, 0, 1, 0); +STORE_FUNCTION(deadline_fifobatch_store, &dd->fifo_batch, 0, INT_MAX, 0); +#undef STORE_FUNCTION + +static struct deadline_fs_entry deadline_readexpire_entry = { + .attr = {.name = "read_expire", .mode = S_IRUGO | S_IWUSR }, + .show = deadline_readexpire_show, + .store = deadline_readexpire_store, +}; +static struct deadline_fs_entry deadline_writeexpire_entry = { + .attr = {.name = "write_expire", .mode = S_IRUGO | S_IWUSR }, + .show = deadline_writeexpire_show, + .store = deadline_writeexpire_store, +}; +static struct deadline_fs_entry deadline_writesstarved_entry = { + .attr = {.name = "writes_starved", .mode = S_IRUGO | S_IWUSR }, + .show = deadline_writesstarved_show, + .store = deadline_writesstarved_store, +}; +static struct deadline_fs_entry deadline_frontmerges_entry = { + .attr = {.name = "front_merges", .mode = S_IRUGO | S_IWUSR }, + .show = deadline_frontmerges_show, + .store = deadline_frontmerges_store, +}; +static struct deadline_fs_entry deadline_fifobatch_entry = { + .attr = {.name = "fifo_batch", .mode = S_IRUGO | S_IWUSR }, + .show = deadline_fifobatch_show, + .store = deadline_fifobatch_store, +}; + +static struct attribute *default_attrs[] = { + &deadline_readexpire_entry.attr, + &deadline_writeexpire_entry.attr, + &deadline_writesstarved_entry.attr, + &deadline_frontmerges_entry.attr, + &deadline_fifobatch_entry.attr, + NULL, +}; + +#define to_deadline(atr) container_of((atr), struct deadline_fs_entry, attr) + +static ssize_t +deadline_attr_show(struct kobject *kobj, struct attribute *attr, char *page) +{ + elevator_t *e = container_of(kobj, elevator_t, kobj); + struct deadline_fs_entry *entry = to_deadline(attr); + + if (!entry->show) + return -EIO; + + return entry->show(e->elevator_data, page); +} + +static ssize_t +deadline_attr_store(struct kobject *kobj, struct attribute *attr, + const char *page, size_t length) +{ + elevator_t *e = container_of(kobj, elevator_t, kobj); + struct deadline_fs_entry *entry = to_deadline(attr); + + if (!entry->store) + return -EIO; + + return entry->store(e->elevator_data, page, length); +} + +static struct sysfs_ops deadline_sysfs_ops = { + .show = deadline_attr_show, + .store = deadline_attr_store, +}; + +static struct kobj_type deadline_ktype = { + .sysfs_ops = &deadline_sysfs_ops, + .default_attrs = default_attrs, +}; + +static struct elevator_type iosched_deadline = { + .ops = { + .elevator_merge_fn = deadline_merge, + .elevator_merged_fn = deadline_merged_request, + .elevator_merge_req_fn = deadline_merged_requests, + .elevator_dispatch_fn = deadline_dispatch_requests, + .elevator_add_req_fn = deadline_add_request, + .elevator_queue_empty_fn = deadline_queue_empty, + .elevator_former_req_fn = deadline_former_request, + .elevator_latter_req_fn = deadline_latter_request, + .elevator_set_req_fn = deadline_set_request, + .elevator_put_req_fn = deadline_put_request, + .elevator_init_fn = deadline_init_queue, + .elevator_exit_fn = deadline_exit_queue, + }, + + .elevator_ktype = &deadline_ktype, + .elevator_name = "deadline", + .elevator_owner = THIS_MODULE, +}; + +static int __init deadline_init(void) +{ + int ret; + + drq_pool = kmem_cache_create("deadline_drq", sizeof(struct deadline_rq), + 0, 0, NULL, NULL); + + if (!drq_pool) + return -ENOMEM; + + ret = elv_register(&iosched_deadline); + if (ret) + kmem_cache_destroy(drq_pool); + + return ret; +} + +static void __exit deadline_exit(void) +{ + kmem_cache_destroy(drq_pool); + elv_unregister(&iosched_deadline); +} + +module_init(deadline_init); +module_exit(deadline_exit); + +MODULE_AUTHOR("Jens Axboe"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("deadline IO scheduler"); diff --git a/block/elevator.c b/block/elevator.c new file mode 100644 index 00000000000..d4a49a3df82 --- /dev/null +++ b/block/elevator.c @@ -0,0 +1,802 @@ +/* + * linux/drivers/block/elevator.c + * + * Block device elevator/IO-scheduler. + * + * Copyright (C) 2000 Andrea Arcangeli SuSE + * + * 30042000 Jens Axboe : + * + * Split the elevator a bit so that it is possible to choose a different + * one or even write a new "plug in". There are three pieces: + * - elevator_fn, inserts a new request in the queue list + * - elevator_merge_fn, decides whether a new buffer can be merged with + * an existing request + * - elevator_dequeue_fn, called when a request is taken off the active list + * + * 20082000 Dave Jones : + * Removed tests for max-bomb-segments, which was breaking elvtune + * when run without -bN + * + * Jens: + * - Rework again to work with bio instead of buffer_heads + * - loose bi_dev comparisons, partition handling is right now + * - completely modularize elevator setup and teardown + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static DEFINE_SPINLOCK(elv_list_lock); +static LIST_HEAD(elv_list); + +/* + * can we safely merge with this request? + */ +inline int elv_rq_merge_ok(struct request *rq, struct bio *bio) +{ + if (!rq_mergeable(rq)) + return 0; + + /* + * different data direction or already started, don't merge + */ + if (bio_data_dir(bio) != rq_data_dir(rq)) + return 0; + + /* + * same device and no special stuff set, merge is ok + */ + if (rq->rq_disk == bio->bi_bdev->bd_disk && + !rq->waiting && !rq->special) + return 1; + + return 0; +} +EXPORT_SYMBOL(elv_rq_merge_ok); + +inline int elv_try_merge(struct request *__rq, struct bio *bio) +{ + int ret = ELEVATOR_NO_MERGE; + + /* + * we can merge and sequence is ok, check if it's possible + */ + if (elv_rq_merge_ok(__rq, bio)) { + if (__rq->sector + __rq->nr_sectors == bio->bi_sector) + ret = ELEVATOR_BACK_MERGE; + else if (__rq->sector - bio_sectors(bio) == bio->bi_sector) + ret = ELEVATOR_FRONT_MERGE; + } + + return ret; +} +EXPORT_SYMBOL(elv_try_merge); + +static struct elevator_type *elevator_find(const char *name) +{ + struct elevator_type *e = NULL; + struct list_head *entry; + + list_for_each(entry, &elv_list) { + struct elevator_type *__e; + + __e = list_entry(entry, struct elevator_type, list); + + if (!strcmp(__e->elevator_name, name)) { + e = __e; + break; + } + } + + return e; +} + +static void elevator_put(struct elevator_type *e) +{ + module_put(e->elevator_owner); +} + +static struct elevator_type *elevator_get(const char *name) +{ + struct elevator_type *e; + + spin_lock_irq(&elv_list_lock); + + e = elevator_find(name); + if (e && !try_module_get(e->elevator_owner)) + e = NULL; + + spin_unlock_irq(&elv_list_lock); + + return e; +} + +static int elevator_attach(request_queue_t *q, struct elevator_type *e, + struct elevator_queue *eq) +{ + int ret = 0; + + memset(eq, 0, sizeof(*eq)); + eq->ops = &e->ops; + eq->elevator_type = e; + + q->elevator = eq; + + if (eq->ops->elevator_init_fn) + ret = eq->ops->elevator_init_fn(q, eq); + + return ret; +} + +static char chosen_elevator[16]; + +static void elevator_setup_default(void) +{ + struct elevator_type *e; + + /* + * If default has not been set, use the compiled-in selection. + */ + if (!chosen_elevator[0]) + strcpy(chosen_elevator, CONFIG_DEFAULT_IOSCHED); + + /* + * If the given scheduler is not available, fall back to no-op. + */ + if (!(e = elevator_find(chosen_elevator))) + strcpy(chosen_elevator, "noop"); + elevator_put(e); +} + +static int __init elevator_setup(char *str) +{ + strncpy(chosen_elevator, str, sizeof(chosen_elevator) - 1); + return 0; +} + +__setup("elevator=", elevator_setup); + +int elevator_init(request_queue_t *q, char *name) +{ + struct elevator_type *e = NULL; + struct elevator_queue *eq; + int ret = 0; + + INIT_LIST_HEAD(&q->queue_head); + q->last_merge = NULL; + q->end_sector = 0; + q->boundary_rq = NULL; + + elevator_setup_default(); + + if (!name) + name = chosen_elevator; + + e = elevator_get(name); + if (!e) + return -EINVAL; + + eq = kmalloc(sizeof(struct elevator_queue), GFP_KERNEL); + if (!eq) { + elevator_put(e->elevator_type); + return -ENOMEM; + } + + ret = elevator_attach(q, e, eq); + if (ret) { + kfree(eq); + elevator_put(e->elevator_type); + } + + return ret; +} + +void elevator_exit(elevator_t *e) +{ + if (e->ops->elevator_exit_fn) + e->ops->elevator_exit_fn(e); + + elevator_put(e->elevator_type); + e->elevator_type = NULL; + kfree(e); +} + +/* + * Insert rq into dispatch queue of q. Queue lock must be held on + * entry. If sort != 0, rq is sort-inserted; otherwise, rq will be + * appended to the dispatch queue. To be used by specific elevators. + */ +void elv_dispatch_sort(request_queue_t *q, struct request *rq) +{ + sector_t boundary; + struct list_head *entry; + + if (q->last_merge == rq) + q->last_merge = NULL; + + boundary = q->end_sector; + + list_for_each_prev(entry, &q->queue_head) { + struct request *pos = list_entry_rq(entry); + + if (pos->flags & (REQ_SOFTBARRIER|REQ_HARDBARRIER|REQ_STARTED)) + break; + if (rq->sector >= boundary) { + if (pos->sector < boundary) + continue; + } else { + if (pos->sector >= boundary) + break; + } + if (rq->sector >= pos->sector) + break; + } + + list_add(&rq->queuelist, entry); +} + +int elv_merge(request_queue_t *q, struct request **req, struct bio *bio) +{ + elevator_t *e = q->elevator; + int ret; + + if (q->last_merge) { + ret = elv_try_merge(q->last_merge, bio); + if (ret != ELEVATOR_NO_MERGE) { + *req = q->last_merge; + return ret; + } + } + + if (e->ops->elevator_merge_fn) + return e->ops->elevator_merge_fn(q, req, bio); + + return ELEVATOR_NO_MERGE; +} + +void elv_merged_request(request_queue_t *q, struct request *rq) +{ + elevator_t *e = q->elevator; + + if (e->ops->elevator_merged_fn) + e->ops->elevator_merged_fn(q, rq); + + q->last_merge = rq; +} + +void elv_merge_requests(request_queue_t *q, struct request *rq, + struct request *next) +{ + elevator_t *e = q->elevator; + + if (e->ops->elevator_merge_req_fn) + e->ops->elevator_merge_req_fn(q, rq, next); + + q->last_merge = rq; +} + +void elv_requeue_request(request_queue_t *q, struct request *rq) +{ + elevator_t *e = q->elevator; + + /* + * it already went through dequeue, we need to decrement the + * in_flight count again + */ + if (blk_account_rq(rq)) { + q->in_flight--; + if (blk_sorted_rq(rq) && e->ops->elevator_deactivate_req_fn) + e->ops->elevator_deactivate_req_fn(q, rq); + } + + rq->flags &= ~REQ_STARTED; + + /* + * if this is the flush, requeue the original instead and drop the flush + */ + if (rq->flags & REQ_BAR_FLUSH) { + clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags); + rq = rq->end_io_data; + } + + __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0); +} + +void __elv_add_request(request_queue_t *q, struct request *rq, int where, + int plug) +{ + if (rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) { + /* + * barriers implicitly indicate back insertion + */ + if (where == ELEVATOR_INSERT_SORT) + where = ELEVATOR_INSERT_BACK; + + /* + * this request is scheduling boundary, update end_sector + */ + if (blk_fs_request(rq)) { + q->end_sector = rq_end_sector(rq); + q->boundary_rq = rq; + } + } else if (!(rq->flags & REQ_ELVPRIV) && where == ELEVATOR_INSERT_SORT) + where = ELEVATOR_INSERT_BACK; + + if (plug) + blk_plug_device(q); + + rq->q = q; + + switch (where) { + case ELEVATOR_INSERT_FRONT: + rq->flags |= REQ_SOFTBARRIER; + + list_add(&rq->queuelist, &q->queue_head); + break; + + case ELEVATOR_INSERT_BACK: + rq->flags |= REQ_SOFTBARRIER; + + while (q->elevator->ops->elevator_dispatch_fn(q, 1)) + ; + list_add_tail(&rq->queuelist, &q->queue_head); + /* + * We kick the queue here for the following reasons. + * - The elevator might have returned NULL previously + * to delay requests and returned them now. As the + * queue wasn't empty before this request, ll_rw_blk + * won't run the queue on return, resulting in hang. + * - Usually, back inserted requests won't be merged + * with anything. There's no point in delaying queue + * processing. + */ + blk_remove_plug(q); + q->request_fn(q); + break; + + case ELEVATOR_INSERT_SORT: + BUG_ON(!blk_fs_request(rq)); + rq->flags |= REQ_SORTED; + if (q->last_merge == NULL && rq_mergeable(rq)) + q->last_merge = rq; + /* + * Some ioscheds (cfq) run q->request_fn directly, so + * rq cannot be accessed after calling + * elevator_add_req_fn. + */ + q->elevator->ops->elevator_add_req_fn(q, rq); + break; + + default: + printk(KERN_ERR "%s: bad insertion point %d\n", + __FUNCTION__, where); + BUG(); + } + + if (blk_queue_plugged(q)) { + int nrq = q->rq.count[READ] + q->rq.count[WRITE] + - q->in_flight; + + if (nrq >= q->unplug_thresh) + __generic_unplug_device(q); + } +} + +void elv_add_request(request_queue_t *q, struct request *rq, int where, + int plug) +{ + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); + __elv_add_request(q, rq, where, plug); + spin_unlock_irqrestore(q->queue_lock, flags); +} + +static inline struct request *__elv_next_request(request_queue_t *q) +{ + struct request *rq; + + if (unlikely(list_empty(&q->queue_head) && + !q->elevator->ops->elevator_dispatch_fn(q, 0))) + return NULL; + + rq = list_entry_rq(q->queue_head.next); + + /* + * if this is a barrier write and the device has to issue a + * flush sequence to support it, check how far we are + */ + if (blk_fs_request(rq) && blk_barrier_rq(rq)) { + BUG_ON(q->ordered == QUEUE_ORDERED_NONE); + + if (q->ordered == QUEUE_ORDERED_FLUSH && + !blk_barrier_preflush(rq)) + rq = blk_start_pre_flush(q, rq); + } + + return rq; +} + +struct request *elv_next_request(request_queue_t *q) +{ + struct request *rq; + int ret; + + while ((rq = __elv_next_request(q)) != NULL) { + if (!(rq->flags & REQ_STARTED)) { + elevator_t *e = q->elevator; + + /* + * This is the first time the device driver + * sees this request (possibly after + * requeueing). Notify IO scheduler. + */ + if (blk_sorted_rq(rq) && + e->ops->elevator_activate_req_fn) + e->ops->elevator_activate_req_fn(q, rq); + + /* + * just mark as started even if we don't start + * it, a request that has been delayed should + * not be passed by new incoming requests + */ + rq->flags |= REQ_STARTED; + } + + if (!q->boundary_rq || q->boundary_rq == rq) { + q->end_sector = rq_end_sector(rq); + q->boundary_rq = NULL; + } + + if ((rq->flags & REQ_DONTPREP) || !q->prep_rq_fn) + break; + + ret = q->prep_rq_fn(q, rq); + if (ret == BLKPREP_OK) { + break; + } else if (ret == BLKPREP_DEFER) { + /* + * the request may have been (partially) prepped. + * we need to keep this request in the front to + * avoid resource deadlock. REQ_STARTED will + * prevent other fs requests from passing this one. + */ + rq = NULL; + break; + } else if (ret == BLKPREP_KILL) { + int nr_bytes = rq->hard_nr_sectors << 9; + + if (!nr_bytes) + nr_bytes = rq->data_len; + + blkdev_dequeue_request(rq); + rq->flags |= REQ_QUIET; + end_that_request_chunk(rq, 0, nr_bytes); + end_that_request_last(rq); + } else { + printk(KERN_ERR "%s: bad return=%d\n", __FUNCTION__, + ret); + break; + } + } + + return rq; +} + +void elv_dequeue_request(request_queue_t *q, struct request *rq) +{ + BUG_ON(list_empty(&rq->queuelist)); + + list_del_init(&rq->queuelist); + + /* + * the time frame between a request being removed from the lists + * and to it is freed is accounted as io that is in progress at + * the driver side. + */ + if (blk_account_rq(rq)) + q->in_flight++; +} + +int elv_queue_empty(request_queue_t *q) +{ + elevator_t *e = q->elevator; + + if (!list_empty(&q->queue_head)) + return 0; + + if (e->ops->elevator_queue_empty_fn) + return e->ops->elevator_queue_empty_fn(q); + + return 1; +} + +struct request *elv_latter_request(request_queue_t *q, struct request *rq) +{ + struct list_head *next; + + elevator_t *e = q->elevator; + + if (e->ops->elevator_latter_req_fn) + return e->ops->elevator_latter_req_fn(q, rq); + + next = rq->queuelist.next; + if (next != &q->queue_head && next != &rq->queuelist) + return list_entry_rq(next); + + return NULL; +} + +struct request *elv_former_request(request_queue_t *q, struct request *rq) +{ + struct list_head *prev; + + elevator_t *e = q->elevator; + + if (e->ops->elevator_former_req_fn) + return e->ops->elevator_former_req_fn(q, rq); + + prev = rq->queuelist.prev; + if (prev != &q->queue_head && prev != &rq->queuelist) + return list_entry_rq(prev); + + return NULL; +} + +int elv_set_request(request_queue_t *q, struct request *rq, struct bio *bio, + gfp_t gfp_mask) +{ + elevator_t *e = q->elevator; + + if (e->ops->elevator_set_req_fn) + return e->ops->elevator_set_req_fn(q, rq, bio, gfp_mask); + + rq->elevator_private = NULL; + return 0; +} + +void elv_put_request(request_queue_t *q, struct request *rq) +{ + elevator_t *e = q->elevator; + + if (e->ops->elevator_put_req_fn) + e->ops->elevator_put_req_fn(q, rq); +} + +int elv_may_queue(request_queue_t *q, int rw, struct bio *bio) +{ + elevator_t *e = q->elevator; + + if (e->ops->elevator_may_queue_fn) + return e->ops->elevator_may_queue_fn(q, rw, bio); + + return ELV_MQUEUE_MAY; +} + +void elv_completed_request(request_queue_t *q, struct request *rq) +{ + elevator_t *e = q->elevator; + + /* + * request is released from the driver, io must be done + */ + if (blk_account_rq(rq)) { + q->in_flight--; + if (blk_sorted_rq(rq) && e->ops->elevator_completed_req_fn) + e->ops->elevator_completed_req_fn(q, rq); + } +} + +int elv_register_queue(struct request_queue *q) +{ + elevator_t *e = q->elevator; + + e->kobj.parent = kobject_get(&q->kobj); + if (!e->kobj.parent) + return -EBUSY; + + snprintf(e->kobj.name, KOBJ_NAME_LEN, "%s", "iosched"); + e->kobj.ktype = e->elevator_type->elevator_ktype; + + return kobject_register(&e->kobj); +} + +void elv_unregister_queue(struct request_queue *q) +{ + if (q) { + elevator_t *e = q->elevator; + kobject_unregister(&e->kobj); + kobject_put(&q->kobj); + } +} + +int elv_register(struct elevator_type *e) +{ + spin_lock_irq(&elv_list_lock); + if (elevator_find(e->elevator_name)) + BUG(); + list_add_tail(&e->list, &elv_list); + spin_unlock_irq(&elv_list_lock); + + printk(KERN_INFO "io scheduler %s registered", e->elevator_name); + if (!strcmp(e->elevator_name, chosen_elevator)) + printk(" (default)"); + printk("\n"); + return 0; +} +EXPORT_SYMBOL_GPL(elv_register); + +void elv_unregister(struct elevator_type *e) +{ + struct task_struct *g, *p; + + /* + * Iterate every thread in the process to remove the io contexts. + */ + read_lock(&tasklist_lock); + do_each_thread(g, p) { + struct io_context *ioc = p->io_context; + if (ioc && ioc->cic) { + ioc->cic->exit(ioc->cic); + ioc->cic->dtor(ioc->cic); + ioc->cic = NULL; + } + if (ioc && ioc->aic) { + ioc->aic->exit(ioc->aic); + ioc->aic->dtor(ioc->aic); + ioc->aic = NULL; + } + } while_each_thread(g, p); + read_unlock(&tasklist_lock); + + spin_lock_irq(&elv_list_lock); + list_del_init(&e->list); + spin_unlock_irq(&elv_list_lock); +} +EXPORT_SYMBOL_GPL(elv_unregister); + +/* + * switch to new_e io scheduler. be careful not to introduce deadlocks - + * we don't free the old io scheduler, before we have allocated what we + * need for the new one. this way we have a chance of going back to the old + * one, if the new one fails init for some reason. + */ +static void elevator_switch(request_queue_t *q, struct elevator_type *new_e) +{ + elevator_t *old_elevator, *e; + + /* + * Allocate new elevator + */ + e = kmalloc(sizeof(elevator_t), GFP_KERNEL); + if (!e) + goto error; + + /* + * Turn on BYPASS and drain all requests w/ elevator private data + */ + spin_lock_irq(q->queue_lock); + + set_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); + + while (q->elevator->ops->elevator_dispatch_fn(q, 1)) + ; + + while (q->rq.elvpriv) { + spin_unlock_irq(q->queue_lock); + msleep(10); + spin_lock_irq(q->queue_lock); + } + + spin_unlock_irq(q->queue_lock); + + /* + * unregister old elevator data + */ + elv_unregister_queue(q); + old_elevator = q->elevator; + + /* + * attach and start new elevator + */ + if (elevator_attach(q, new_e, e)) + goto fail; + + if (elv_register_queue(q)) + goto fail_register; + + /* + * finally exit old elevator and turn off BYPASS. + */ + elevator_exit(old_elevator); + clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); + return; + +fail_register: + /* + * switch failed, exit the new io scheduler and reattach the old + * one again (along with re-adding the sysfs dir) + */ + elevator_exit(e); + e = NULL; +fail: + q->elevator = old_elevator; + elv_register_queue(q); + clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); + kfree(e); +error: + elevator_put(new_e); + printk(KERN_ERR "elevator: switch to %s failed\n",new_e->elevator_name); +} + +ssize_t elv_iosched_store(request_queue_t *q, const char *name, size_t count) +{ + char elevator_name[ELV_NAME_MAX]; + struct elevator_type *e; + + memset(elevator_name, 0, sizeof(elevator_name)); + strncpy(elevator_name, name, sizeof(elevator_name)); + + if (elevator_name[strlen(elevator_name) - 1] == '\n') + elevator_name[strlen(elevator_name) - 1] = '\0'; + + e = elevator_get(elevator_name); + if (!e) { + printk(KERN_ERR "elevator: type %s not found\n", elevator_name); + return -EINVAL; + } + + if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name)) { + elevator_put(e); + return count; + } + + elevator_switch(q, e); + return count; +} + +ssize_t elv_iosched_show(request_queue_t *q, char *name) +{ + elevator_t *e = q->elevator; + struct elevator_type *elv = e->elevator_type; + struct list_head *entry; + int len = 0; + + spin_lock_irq(q->queue_lock); + list_for_each(entry, &elv_list) { + struct elevator_type *__e; + + __e = list_entry(entry, struct elevator_type, list); + if (!strcmp(elv->elevator_name, __e->elevator_name)) + len += sprintf(name+len, "[%s] ", elv->elevator_name); + else + len += sprintf(name+len, "%s ", __e->elevator_name); + } + spin_unlock_irq(q->queue_lock); + + len += sprintf(len+name, "\n"); + return len; +} + +EXPORT_SYMBOL(elv_dispatch_sort); +EXPORT_SYMBOL(elv_add_request); +EXPORT_SYMBOL(__elv_add_request); +EXPORT_SYMBOL(elv_requeue_request); +EXPORT_SYMBOL(elv_next_request); +EXPORT_SYMBOL(elv_dequeue_request); +EXPORT_SYMBOL(elv_queue_empty); +EXPORT_SYMBOL(elv_completed_request); +EXPORT_SYMBOL(elevator_exit); +EXPORT_SYMBOL(elevator_init); diff --git a/block/genhd.c b/block/genhd.c new file mode 100644 index 00000000000..54aec4a1ae1 --- /dev/null +++ b/block/genhd.c @@ -0,0 +1,726 @@ +/* + * gendisk handling + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_PROBE_HASH 255 /* random */ + +static struct subsystem block_subsys; + +static DECLARE_MUTEX(block_subsys_sem); + +/* + * Can be deleted altogether. Later. + * + */ +static struct blk_major_name { + struct blk_major_name *next; + int major; + char name[16]; +} *major_names[MAX_PROBE_HASH]; + +/* index in the above - for now: assume no multimajor ranges */ +static inline int major_to_index(int major) +{ + return major % MAX_PROBE_HASH; +} + +#ifdef CONFIG_PROC_FS +/* get block device names in somewhat random order */ +int get_blkdev_list(char *p, int used) +{ + struct blk_major_name *n; + int i, len; + + len = snprintf(p, (PAGE_SIZE-used), "\nBlock devices:\n"); + + down(&block_subsys_sem); + for (i = 0; i < ARRAY_SIZE(major_names); i++) { + for (n = major_names[i]; n; n = n->next) { + /* + * If the curent string plus the 5 extra characters + * in the line would run us off the page, then we're done + */ + if ((len + used + strlen(n->name) + 5) >= PAGE_SIZE) + goto page_full; + len += sprintf(p+len, "%3d %s\n", + n->major, n->name); + } + } +page_full: + up(&block_subsys_sem); + + return len; +} +#endif + +int register_blkdev(unsigned int major, const char *name) +{ + struct blk_major_name **n, *p; + int index, ret = 0; + + down(&block_subsys_sem); + + /* temporary */ + if (major == 0) { + for (index = ARRAY_SIZE(major_names)-1; index > 0; index--) { + if (major_names[index] == NULL) + break; + } + + if (index == 0) { + printk("register_blkdev: failed to get major for %s\n", + name); + ret = -EBUSY; + goto out; + } + major = index; + ret = major; + } + + p = kmalloc(sizeof(struct blk_major_name), GFP_KERNEL); + if (p == NULL) { + ret = -ENOMEM; + goto out; + } + + p->major = major; + strlcpy(p->name, name, sizeof(p->name)); + p->next = NULL; + index = major_to_index(major); + + for (n = &major_names[index]; *n; n = &(*n)->next) { + if ((*n)->major == major) + break; + } + if (!*n) + *n = p; + else + ret = -EBUSY; + + if (ret < 0) { + printk("register_blkdev: cannot get major %d for %s\n", + major, name); + kfree(p); + } +out: + up(&block_subsys_sem); + return ret; +} + +EXPORT_SYMBOL(register_blkdev); + +/* todo: make void - error printk here */ +int unregister_blkdev(unsigned int major, const char *name) +{ + struct blk_major_name **n; + struct blk_major_name *p = NULL; + int index = major_to_index(major); + int ret = 0; + + down(&block_subsys_sem); + for (n = &major_names[index]; *n; n = &(*n)->next) + if ((*n)->major == major) + break; + if (!*n || strcmp((*n)->name, name)) + ret = -EINVAL; + else { + p = *n; + *n = p->next; + } + up(&block_subsys_sem); + kfree(p); + + return ret; +} + +EXPORT_SYMBOL(unregister_blkdev); + +static struct kobj_map *bdev_map; + +/* + * Register device numbers dev..(dev+range-1) + * range must be nonzero + * The hash chain is sorted on range, so that subranges can override. + */ +void blk_register_region(dev_t dev, unsigned long range, struct module *module, + struct kobject *(*probe)(dev_t, int *, void *), + int (*lock)(dev_t, void *), void *data) +{ + kobj_map(bdev_map, dev, range, module, probe, lock, data); +} + +EXPORT_SYMBOL(blk_register_region); + +void blk_unregister_region(dev_t dev, unsigned long range) +{ + kobj_unmap(bdev_map, dev, range); +} + +EXPORT_SYMBOL(blk_unregister_region); + +static struct kobject *exact_match(dev_t dev, int *part, void *data) +{ + struct gendisk *p = data; + return &p->kobj; +} + +static int exact_lock(dev_t dev, void *data) +{ + struct gendisk *p = data; + + if (!get_disk(p)) + return -1; + return 0; +} + +/** + * add_disk - add partitioning information to kernel list + * @disk: per-device partitioning information + * + * This function registers the partitioning information in @disk + * with the kernel. + */ +void add_disk(struct gendisk *disk) +{ + disk->flags |= GENHD_FL_UP; + blk_register_region(MKDEV(disk->major, disk->first_minor), + disk->minors, NULL, exact_match, exact_lock, disk); + register_disk(disk); + blk_register_queue(disk); +} + +EXPORT_SYMBOL(add_disk); +EXPORT_SYMBOL(del_gendisk); /* in partitions/check.c */ + +void unlink_gendisk(struct gendisk *disk) +{ + blk_unregister_queue(disk); + blk_unregister_region(MKDEV(disk->major, disk->first_minor), + disk->minors); +} + +#define to_disk(obj) container_of(obj,struct gendisk,kobj) + +/** + * get_gendisk - get partitioning information for a given device + * @dev: device to get partitioning information for + * + * This function gets the structure containing partitioning + * information for the given device @dev. + */ +struct gendisk *get_gendisk(dev_t dev, int *part) +{ + struct kobject *kobj = kobj_lookup(bdev_map, dev, part); + return kobj ? to_disk(kobj) : NULL; +} + +#ifdef CONFIG_PROC_FS +/* iterator */ +static void *part_start(struct seq_file *part, loff_t *pos) +{ + struct list_head *p; + loff_t l = *pos; + + down(&block_subsys_sem); + list_for_each(p, &block_subsys.kset.list) + if (!l--) + return list_entry(p, struct gendisk, kobj.entry); + return NULL; +} + +static void *part_next(struct seq_file *part, void *v, loff_t *pos) +{ + struct list_head *p = ((struct gendisk *)v)->kobj.entry.next; + ++*pos; + return p==&block_subsys.kset.list ? NULL : + list_entry(p, struct gendisk, kobj.entry); +} + +static void part_stop(struct seq_file *part, void *v) +{ + up(&block_subsys_sem); +} + +static int show_partition(struct seq_file *part, void *v) +{ + struct gendisk *sgp = v; + int n; + char buf[BDEVNAME_SIZE]; + + if (&sgp->kobj.entry == block_subsys.kset.list.next) + seq_puts(part, "major minor #blocks name\n\n"); + + /* Don't show non-partitionable removeable devices or empty devices */ + if (!get_capacity(sgp) || + (sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE))) + return 0; + if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO) + return 0; + + /* show the full disk and all non-0 size partitions of it */ + seq_printf(part, "%4d %4d %10llu %s\n", + sgp->major, sgp->first_minor, + (unsigned long long)get_capacity(sgp) >> 1, + disk_name(sgp, 0, buf)); + for (n = 0; n < sgp->minors - 1; n++) { + if (!sgp->part[n]) + continue; + if (sgp->part[n]->nr_sects == 0) + continue; + seq_printf(part, "%4d %4d %10llu %s\n", + sgp->major, n + 1 + sgp->first_minor, + (unsigned long long)sgp->part[n]->nr_sects >> 1 , + disk_name(sgp, n + 1, buf)); + } + + return 0; +} + +struct seq_operations partitions_op = { + .start =part_start, + .next = part_next, + .stop = part_stop, + .show = show_partition +}; +#endif + + +extern int blk_dev_init(void); + +static struct kobject *base_probe(dev_t dev, int *part, void *data) +{ + if (request_module("block-major-%d-%d", MAJOR(dev), MINOR(dev)) > 0) + /* Make old-style 2.4 aliases work */ + request_module("block-major-%d", MAJOR(dev)); + return NULL; +} + +static int __init genhd_device_init(void) +{ + bdev_map = kobj_map_init(base_probe, &block_subsys_sem); + blk_dev_init(); + subsystem_register(&block_subsys); + return 0; +} + +subsys_initcall(genhd_device_init); + + + +/* + * kobject & sysfs bindings for block devices + */ +static ssize_t disk_attr_show(struct kobject *kobj, struct attribute *attr, + char *page) +{ + struct gendisk *disk = to_disk(kobj); + struct disk_attribute *disk_attr = + container_of(attr,struct disk_attribute,attr); + ssize_t ret = -EIO; + + if (disk_attr->show) + ret = disk_attr->show(disk,page); + return ret; +} + +static ssize_t disk_attr_store(struct kobject * kobj, struct attribute * attr, + const char *page, size_t count) +{ + struct gendisk *disk = to_disk(kobj); + struct disk_attribute *disk_attr = + container_of(attr,struct disk_attribute,attr); + ssize_t ret = 0; + + if (disk_attr->store) + ret = disk_attr->store(disk, page, count); + return ret; +} + +static struct sysfs_ops disk_sysfs_ops = { + .show = &disk_attr_show, + .store = &disk_attr_store, +}; + +static ssize_t disk_uevent_store(struct gendisk * disk, + const char *buf, size_t count) +{ + kobject_hotplug(&disk->kobj, KOBJ_ADD); + return count; +} +static ssize_t disk_dev_read(struct gendisk * disk, char *page) +{ + dev_t base = MKDEV(disk->major, disk->first_minor); + return print_dev_t(page, base); +} +static ssize_t disk_range_read(struct gendisk * disk, char *page) +{ + return sprintf(page, "%d\n", disk->minors); +} +static ssize_t disk_removable_read(struct gendisk * disk, char *page) +{ + return sprintf(page, "%d\n", + (disk->flags & GENHD_FL_REMOVABLE ? 1 : 0)); + +} +static ssize_t disk_size_read(struct gendisk * disk, char *page) +{ + return sprintf(page, "%llu\n", (unsigned long long)get_capacity(disk)); +} + +static ssize_t disk_stats_read(struct gendisk * disk, char *page) +{ + preempt_disable(); + disk_round_stats(disk); + preempt_enable(); + return sprintf(page, + "%8u %8u %8llu %8u " + "%8u %8u %8llu %8u " + "%8u %8u %8u" + "\n", + disk_stat_read(disk, ios[0]), disk_stat_read(disk, merges[0]), + (unsigned long long)disk_stat_read(disk, sectors[0]), + jiffies_to_msecs(disk_stat_read(disk, ticks[0])), + disk_stat_read(disk, ios[1]), disk_stat_read(disk, merges[1]), + (unsigned long long)disk_stat_read(disk, sectors[1]), + jiffies_to_msecs(disk_stat_read(disk, ticks[1])), + disk->in_flight, + jiffies_to_msecs(disk_stat_read(disk, io_ticks)), + jiffies_to_msecs(disk_stat_read(disk, time_in_queue))); +} +static struct disk_attribute disk_attr_uevent = { + .attr = {.name = "uevent", .mode = S_IWUSR }, + .store = disk_uevent_store +}; +static struct disk_attribute disk_attr_dev = { + .attr = {.name = "dev", .mode = S_IRUGO }, + .show = disk_dev_read +}; +static struct disk_attribute disk_attr_range = { + .attr = {.name = "range", .mode = S_IRUGO }, + .show = disk_range_read +}; +static struct disk_attribute disk_attr_removable = { + .attr = {.name = "removable", .mode = S_IRUGO }, + .show = disk_removable_read +}; +static struct disk_attribute disk_attr_size = { + .attr = {.name = "size", .mode = S_IRUGO }, + .show = disk_size_read +}; +static struct disk_attribute disk_attr_stat = { + .attr = {.name = "stat", .mode = S_IRUGO }, + .show = disk_stats_read +}; + +static struct attribute * default_attrs[] = { + &disk_attr_uevent.attr, + &disk_attr_dev.attr, + &disk_attr_range.attr, + &disk_attr_removable.attr, + &disk_attr_size.attr, + &disk_attr_stat.attr, + NULL, +}; + +static void disk_release(struct kobject * kobj) +{ + struct gendisk *disk = to_disk(kobj); + kfree(disk->random); + kfree(disk->part); + free_disk_stats(disk); + kfree(disk); +} + +static struct kobj_type ktype_block = { + .release = disk_release, + .sysfs_ops = &disk_sysfs_ops, + .default_attrs = default_attrs, +}; + +extern struct kobj_type ktype_part; + +static int block_hotplug_filter(struct kset *kset, struct kobject *kobj) +{ + struct kobj_type *ktype = get_ktype(kobj); + + return ((ktype == &ktype_block) || (ktype == &ktype_part)); +} + +static int block_hotplug(struct kset *kset, struct kobject *kobj, char **envp, + int num_envp, char *buffer, int buffer_size) +{ + struct kobj_type *ktype = get_ktype(kobj); + struct device *physdev; + struct gendisk *disk; + struct hd_struct *part; + int length = 0; + int i = 0; + + if (ktype == &ktype_block) { + disk = container_of(kobj, struct gendisk, kobj); + add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, + &length, "MINOR=%u", disk->first_minor); + } else if (ktype == &ktype_part) { + disk = container_of(kobj->parent, struct gendisk, kobj); + part = container_of(kobj, struct hd_struct, kobj); + add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, + &length, "MINOR=%u", + disk->first_minor + part->partno); + } else + return 0; + + add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &length, + "MAJOR=%u", disk->major); + + /* add physical device, backing this device */ + physdev = disk->driverfs_dev; + if (physdev) { + char *path = kobject_get_path(&physdev->kobj, GFP_KERNEL); + + add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, + &length, "PHYSDEVPATH=%s", path); + kfree(path); + + if (physdev->bus) + add_hotplug_env_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "PHYSDEVBUS=%s", + physdev->bus->name); + + if (physdev->driver) + add_hotplug_env_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "PHYSDEVDRIVER=%s", + physdev->driver->name); + } + + /* terminate, set to next free slot, shrink available space */ + envp[i] = NULL; + envp = &envp[i]; + num_envp -= i; + buffer = &buffer[length]; + buffer_size -= length; + + return 0; +} + +static struct kset_hotplug_ops block_hotplug_ops = { + .filter = block_hotplug_filter, + .hotplug = block_hotplug, +}; + +/* declare block_subsys. */ +static decl_subsys(block, &ktype_block, &block_hotplug_ops); + + +/* + * aggregate disk stat collector. Uses the same stats that the sysfs + * entries do, above, but makes them available through one seq_file. + * Watching a few disks may be efficient through sysfs, but watching + * all of them will be more efficient through this interface. + * + * The output looks suspiciously like /proc/partitions with a bunch of + * extra fields. + */ + +/* iterator */ +static void *diskstats_start(struct seq_file *part, loff_t *pos) +{ + loff_t k = *pos; + struct list_head *p; + + down(&block_subsys_sem); + list_for_each(p, &block_subsys.kset.list) + if (!k--) + return list_entry(p, struct gendisk, kobj.entry); + return NULL; +} + +static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos) +{ + struct list_head *p = ((struct gendisk *)v)->kobj.entry.next; + ++*pos; + return p==&block_subsys.kset.list ? NULL : + list_entry(p, struct gendisk, kobj.entry); +} + +static void diskstats_stop(struct seq_file *part, void *v) +{ + up(&block_subsys_sem); +} + +static int diskstats_show(struct seq_file *s, void *v) +{ + struct gendisk *gp = v; + char buf[BDEVNAME_SIZE]; + int n = 0; + + /* + if (&sgp->kobj.entry == block_subsys.kset.list.next) + seq_puts(s, "major minor name" + " rio rmerge rsect ruse wio wmerge " + "wsect wuse running use aveq" + "\n\n"); + */ + + preempt_disable(); + disk_round_stats(gp); + preempt_enable(); + seq_printf(s, "%4d %4d %s %u %u %llu %u %u %u %llu %u %u %u %u\n", + gp->major, n + gp->first_minor, disk_name(gp, n, buf), + disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]), + (unsigned long long)disk_stat_read(gp, sectors[0]), + jiffies_to_msecs(disk_stat_read(gp, ticks[0])), + disk_stat_read(gp, ios[1]), disk_stat_read(gp, merges[1]), + (unsigned long long)disk_stat_read(gp, sectors[1]), + jiffies_to_msecs(disk_stat_read(gp, ticks[1])), + gp->in_flight, + jiffies_to_msecs(disk_stat_read(gp, io_ticks)), + jiffies_to_msecs(disk_stat_read(gp, time_in_queue))); + + /* now show all non-0 size partitions of it */ + for (n = 0; n < gp->minors - 1; n++) { + struct hd_struct *hd = gp->part[n]; + + if (hd && hd->nr_sects) + seq_printf(s, "%4d %4d %s %u %u %u %u\n", + gp->major, n + gp->first_minor + 1, + disk_name(gp, n + 1, buf), + hd->ios[0], hd->sectors[0], + hd->ios[1], hd->sectors[1]); + } + + return 0; +} + +struct seq_operations diskstats_op = { + .start = diskstats_start, + .next = diskstats_next, + .stop = diskstats_stop, + .show = diskstats_show +}; + +struct gendisk *alloc_disk(int minors) +{ + return alloc_disk_node(minors, -1); +} + +struct gendisk *alloc_disk_node(int minors, int node_id) +{ + struct gendisk *disk; + + disk = kmalloc_node(sizeof(struct gendisk), GFP_KERNEL, node_id); + if (disk) { + memset(disk, 0, sizeof(struct gendisk)); + if (!init_disk_stats(disk)) { + kfree(disk); + return NULL; + } + if (minors > 1) { + int size = (minors - 1) * sizeof(struct hd_struct *); + disk->part = kmalloc_node(size, GFP_KERNEL, node_id); + if (!disk->part) { + kfree(disk); + return NULL; + } + memset(disk->part, 0, size); + } + disk->minors = minors; + kobj_set_kset_s(disk,block_subsys); + kobject_init(&disk->kobj); + rand_initialize_disk(disk); + } + return disk; +} + +EXPORT_SYMBOL(alloc_disk); +EXPORT_SYMBOL(alloc_disk_node); + +struct kobject *get_disk(struct gendisk *disk) +{ + struct module *owner; + struct kobject *kobj; + + if (!disk->fops) + return NULL; + owner = disk->fops->owner; + if (owner && !try_module_get(owner)) + return NULL; + kobj = kobject_get(&disk->kobj); + if (kobj == NULL) { + module_put(owner); + return NULL; + } + return kobj; + +} + +EXPORT_SYMBOL(get_disk); + +void put_disk(struct gendisk *disk) +{ + if (disk) + kobject_put(&disk->kobj); +} + +EXPORT_SYMBOL(put_disk); + +void set_device_ro(struct block_device *bdev, int flag) +{ + if (bdev->bd_contains != bdev) + bdev->bd_part->policy = flag; + else + bdev->bd_disk->policy = flag; +} + +EXPORT_SYMBOL(set_device_ro); + +void set_disk_ro(struct gendisk *disk, int flag) +{ + int i; + disk->policy = flag; + for (i = 0; i < disk->minors - 1; i++) + if (disk->part[i]) disk->part[i]->policy = flag; +} + +EXPORT_SYMBOL(set_disk_ro); + +int bdev_read_only(struct block_device *bdev) +{ + if (!bdev) + return 0; + else if (bdev->bd_contains != bdev) + return bdev->bd_part->policy; + else + return bdev->bd_disk->policy; +} + +EXPORT_SYMBOL(bdev_read_only); + +int invalidate_partition(struct gendisk *disk, int index) +{ + int res = 0; + struct block_device *bdev = bdget_disk(disk, index); + if (bdev) { + fsync_bdev(bdev); + res = __invalidate_device(bdev); + bdput(bdev); + } + return res; +} + +EXPORT_SYMBOL(invalidate_partition); diff --git a/block/ioctl.c b/block/ioctl.c new file mode 100644 index 00000000000..6e278474f9a --- /dev/null +++ b/block/ioctl.c @@ -0,0 +1,275 @@ +#include /* for capable() */ +#include +#include +#include +#include +#include +#include + +static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user *arg) +{ + struct block_device *bdevp; + struct gendisk *disk; + struct blkpg_ioctl_arg a; + struct blkpg_partition p; + long long start, length; + int part; + int i; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg))) + return -EFAULT; + if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition))) + return -EFAULT; + disk = bdev->bd_disk; + if (bdev != bdev->bd_contains) + return -EINVAL; + part = p.pno; + if (part <= 0 || part >= disk->minors) + return -EINVAL; + switch (a.op) { + case BLKPG_ADD_PARTITION: + start = p.start >> 9; + length = p.length >> 9; + /* check for fit in a hd_struct */ + if (sizeof(sector_t) == sizeof(long) && + sizeof(long long) > sizeof(long)) { + long pstart = start, plength = length; + if (pstart != start || plength != length + || pstart < 0 || plength < 0) + return -EINVAL; + } + /* partition number in use? */ + down(&bdev->bd_sem); + if (disk->part[part - 1]) { + up(&bdev->bd_sem); + return -EBUSY; + } + /* overlap? */ + for (i = 0; i < disk->minors - 1; i++) { + struct hd_struct *s = disk->part[i]; + + if (!s) + continue; + if (!(start+length <= s->start_sect || + start >= s->start_sect + s->nr_sects)) { + up(&bdev->bd_sem); + return -EBUSY; + } + } + /* all seems OK */ + add_partition(disk, part, start, length); + up(&bdev->bd_sem); + return 0; + case BLKPG_DEL_PARTITION: + if (!disk->part[part-1]) + return -ENXIO; + if (disk->part[part - 1]->nr_sects == 0) + return -ENXIO; + bdevp = bdget_disk(disk, part); + if (!bdevp) + return -ENOMEM; + down(&bdevp->bd_sem); + if (bdevp->bd_openers) { + up(&bdevp->bd_sem); + bdput(bdevp); + return -EBUSY; + } + /* all seems OK */ + fsync_bdev(bdevp); + invalidate_bdev(bdevp, 0); + + down(&bdev->bd_sem); + delete_partition(disk, part); + up(&bdev->bd_sem); + up(&bdevp->bd_sem); + bdput(bdevp); + + return 0; + default: + return -EINVAL; + } +} + +static int blkdev_reread_part(struct block_device *bdev) +{ + struct gendisk *disk = bdev->bd_disk; + int res; + + if (disk->minors == 1 || bdev != bdev->bd_contains) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + if (down_trylock(&bdev->bd_sem)) + return -EBUSY; + res = rescan_partitions(disk, bdev); + up(&bdev->bd_sem); + return res; +} + +static int put_ushort(unsigned long arg, unsigned short val) +{ + return put_user(val, (unsigned short __user *)arg); +} + +static int put_int(unsigned long arg, int val) +{ + return put_user(val, (int __user *)arg); +} + +static int put_long(unsigned long arg, long val) +{ + return put_user(val, (long __user *)arg); +} + +static int put_ulong(unsigned long arg, unsigned long val) +{ + return put_user(val, (unsigned long __user *)arg); +} + +static int put_u64(unsigned long arg, u64 val) +{ + return put_user(val, (u64 __user *)arg); +} + +static int blkdev_locked_ioctl(struct file *file, struct block_device *bdev, + unsigned cmd, unsigned long arg) +{ + struct backing_dev_info *bdi; + int ret, n; + + switch (cmd) { + case BLKRAGET: + case BLKFRAGET: + if (!arg) + return -EINVAL; + bdi = blk_get_backing_dev_info(bdev); + if (bdi == NULL) + return -ENOTTY; + return put_long(arg, (bdi->ra_pages * PAGE_CACHE_SIZE) / 512); + case BLKROGET: + return put_int(arg, bdev_read_only(bdev) != 0); + case BLKBSZGET: /* get the logical block size (cf. BLKSSZGET) */ + return put_int(arg, block_size(bdev)); + case BLKSSZGET: /* get block device hardware sector size */ + return put_int(arg, bdev_hardsect_size(bdev)); + case BLKSECTGET: + return put_ushort(arg, bdev_get_queue(bdev)->max_sectors); + case BLKRASET: + case BLKFRASET: + if(!capable(CAP_SYS_ADMIN)) + return -EACCES; + bdi = blk_get_backing_dev_info(bdev); + if (bdi == NULL) + return -ENOTTY; + bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE; + return 0; + case BLKBSZSET: + /* set the logical block size */ + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + if (!arg) + return -EINVAL; + if (get_user(n, (int __user *) arg)) + return -EFAULT; + if (bd_claim(bdev, file) < 0) + return -EBUSY; + ret = set_blocksize(bdev, n); + bd_release(bdev); + return ret; + case BLKPG: + return blkpg_ioctl(bdev, (struct blkpg_ioctl_arg __user *) arg); + case BLKRRPART: + return blkdev_reread_part(bdev); + case BLKGETSIZE: + if ((bdev->bd_inode->i_size >> 9) > ~0UL) + return -EFBIG; + return put_ulong(arg, bdev->bd_inode->i_size >> 9); + case BLKGETSIZE64: + return put_u64(arg, bdev->bd_inode->i_size); + } + return -ENOIOCTLCMD; +} + +static int blkdev_driver_ioctl(struct inode *inode, struct file *file, + struct gendisk *disk, unsigned cmd, unsigned long arg) +{ + int ret; + if (disk->fops->unlocked_ioctl) + return disk->fops->unlocked_ioctl(file, cmd, arg); + + if (disk->fops->ioctl) { + lock_kernel(); + ret = disk->fops->ioctl(inode, file, cmd, arg); + unlock_kernel(); + return ret; + } + + return -ENOTTY; +} + +int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, + unsigned long arg) +{ + struct block_device *bdev = inode->i_bdev; + struct gendisk *disk = bdev->bd_disk; + int ret, n; + + switch(cmd) { + case BLKFLSBUF: + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg); + /* -EINVAL to handle old uncorrected drivers */ + if (ret != -EINVAL && ret != -ENOTTY) + return ret; + + lock_kernel(); + fsync_bdev(bdev); + invalidate_bdev(bdev, 0); + unlock_kernel(); + return 0; + + case BLKROSET: + ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg); + /* -EINVAL to handle old uncorrected drivers */ + if (ret != -EINVAL && ret != -ENOTTY) + return ret; + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + if (get_user(n, (int __user *)(arg))) + return -EFAULT; + lock_kernel(); + set_device_ro(bdev, n); + unlock_kernel(); + return 0; + } + + lock_kernel(); + ret = blkdev_locked_ioctl(file, bdev, cmd, arg); + unlock_kernel(); + if (ret != -ENOIOCTLCMD) + return ret; + + return blkdev_driver_ioctl(inode, file, disk, cmd, arg); +} + +/* Most of the generic ioctls are handled in the normal fallback path. + This assumes the blkdev's low level compat_ioctl always returns + ENOIOCTLCMD for unknown ioctls. */ +long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) +{ + struct block_device *bdev = file->f_dentry->d_inode->i_bdev; + struct gendisk *disk = bdev->bd_disk; + int ret = -ENOIOCTLCMD; + if (disk->fops->compat_ioctl) { + lock_kernel(); + ret = disk->fops->compat_ioctl(file, cmd, arg); + unlock_kernel(); + } + return ret; +} + +EXPORT_SYMBOL_GPL(blkdev_ioctl); diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c new file mode 100644 index 00000000000..2747741677f --- /dev/null +++ b/block/ll_rw_blk.c @@ -0,0 +1,3613 @@ +/* + * linux/drivers/block/ll_rw_blk.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright (C) 1994, Karl Keyte: Added support for disk statistics + * Elevator latency, (C) 2000 Andrea Arcangeli SuSE + * Queue request tables / lock, selectable elevator, Jens Axboe + * kernel-doc documentation started by NeilBrown - July2000 + * bio rewrite, highmem i/o, etc, Jens Axboe - may 2001 + */ + +/* + * This handles all read/write requests to block devices + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for max_pfn/max_low_pfn */ +#include +#include +#include +#include +#include + +/* + * for max sense size + */ +#include + +static void blk_unplug_work(void *data); +static void blk_unplug_timeout(unsigned long data); +static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io); + +/* + * For the allocated request tables + */ +static kmem_cache_t *request_cachep; + +/* + * For queue allocation + */ +static kmem_cache_t *requestq_cachep; + +/* + * For io context allocations + */ +static kmem_cache_t *iocontext_cachep; + +static wait_queue_head_t congestion_wqh[2] = { + __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[0]), + __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1]) + }; + +/* + * Controlling structure to kblockd + */ +static struct workqueue_struct *kblockd_workqueue; + +unsigned long blk_max_low_pfn, blk_max_pfn; + +EXPORT_SYMBOL(blk_max_low_pfn); +EXPORT_SYMBOL(blk_max_pfn); + +/* Amount of time in which a process may batch requests */ +#define BLK_BATCH_TIME (HZ/50UL) + +/* Number of requests a "batching" process may submit */ +#define BLK_BATCH_REQ 32 + +/* + * Return the threshold (number of used requests) at which the queue is + * considered to be congested. It include a little hysteresis to keep the + * context switch rate down. + */ +static inline int queue_congestion_on_threshold(struct request_queue *q) +{ + return q->nr_congestion_on; +} + +/* + * The threshold at which a queue is considered to be uncongested + */ +static inline int queue_congestion_off_threshold(struct request_queue *q) +{ + return q->nr_congestion_off; +} + +static void blk_queue_congestion_threshold(struct request_queue *q) +{ + int nr; + + nr = q->nr_requests - (q->nr_requests / 8) + 1; + if (nr > q->nr_requests) + nr = q->nr_requests; + q->nr_congestion_on = nr; + + nr = q->nr_requests - (q->nr_requests / 8) - (q->nr_requests / 16) - 1; + if (nr < 1) + nr = 1; + q->nr_congestion_off = nr; +} + +/* + * A queue has just exitted congestion. Note this in the global counter of + * congested queues, and wake up anyone who was waiting for requests to be + * put back. + */ +static void clear_queue_congested(request_queue_t *q, int rw) +{ + enum bdi_state bit; + wait_queue_head_t *wqh = &congestion_wqh[rw]; + + bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested; + clear_bit(bit, &q->backing_dev_info.state); + smp_mb__after_clear_bit(); + if (waitqueue_active(wqh)) + wake_up(wqh); +} + +/* + * A queue has just entered congestion. Flag that in the queue's VM-visible + * state flags and increment the global gounter of congested queues. + */ +static void set_queue_congested(request_queue_t *q, int rw) +{ + enum bdi_state bit; + + bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested; + set_bit(bit, &q->backing_dev_info.state); +} + +/** + * blk_get_backing_dev_info - get the address of a queue's backing_dev_info + * @bdev: device + * + * Locates the passed device's request queue and returns the address of its + * backing_dev_info + * + * Will return NULL if the request queue cannot be located. + */ +struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev) +{ + struct backing_dev_info *ret = NULL; + request_queue_t *q = bdev_get_queue(bdev); + + if (q) + ret = &q->backing_dev_info; + return ret; +} + +EXPORT_SYMBOL(blk_get_backing_dev_info); + +void blk_queue_activity_fn(request_queue_t *q, activity_fn *fn, void *data) +{ + q->activity_fn = fn; + q->activity_data = data; +} + +EXPORT_SYMBOL(blk_queue_activity_fn); + +/** + * blk_queue_prep_rq - set a prepare_request function for queue + * @q: queue + * @pfn: prepare_request function + * + * It's possible for a queue to register a prepare_request callback which + * is invoked before the request is handed to the request_fn. The goal of + * the function is to prepare a request for I/O, it can be used to build a + * cdb from the request data for instance. + * + */ +void blk_queue_prep_rq(request_queue_t *q, prep_rq_fn *pfn) +{ + q->prep_rq_fn = pfn; +} + +EXPORT_SYMBOL(blk_queue_prep_rq); + +/** + * blk_queue_merge_bvec - set a merge_bvec function for queue + * @q: queue + * @mbfn: merge_bvec_fn + * + * Usually queues have static limitations on the max sectors or segments that + * we can put in a request. Stacking drivers may have some settings that + * are dynamic, and thus we have to query the queue whether it is ok to + * add a new bio_vec to a bio at a given offset or not. If the block device + * has such limitations, it needs to register a merge_bvec_fn to control + * the size of bio's sent to it. Note that a block device *must* allow a + * single page to be added to an empty bio. The block device driver may want + * to use the bio_split() function to deal with these bio's. By default + * no merge_bvec_fn is defined for a queue, and only the fixed limits are + * honored. + */ +void blk_queue_merge_bvec(request_queue_t *q, merge_bvec_fn *mbfn) +{ + q->merge_bvec_fn = mbfn; +} + +EXPORT_SYMBOL(blk_queue_merge_bvec); + +/** + * blk_queue_make_request - define an alternate make_request function for a device + * @q: the request queue for the device to be affected + * @mfn: the alternate make_request function + * + * Description: + * The normal way for &struct bios to be passed to a device + * driver is for them to be collected into requests on a request + * queue, and then to allow the device driver to select requests + * off that queue when it is ready. This works well for many block + * devices. However some block devices (typically virtual devices + * such as md or lvm) do not benefit from the processing on the + * request queue, and are served best by having the requests passed + * directly to them. This can be achieved by providing a function + * to blk_queue_make_request(). + * + * Caveat: + * The driver that does this *must* be able to deal appropriately + * with buffers in "highmemory". This can be accomplished by either calling + * __bio_kmap_atomic() to get a temporary kernel mapping, or by calling + * blk_queue_bounce() to create a buffer in normal memory. + **/ +void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn) +{ + /* + * set defaults + */ + q->nr_requests = BLKDEV_MAX_RQ; + blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS); + blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS); + q->make_request_fn = mfn; + q->backing_dev_info.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; + q->backing_dev_info.state = 0; + q->backing_dev_info.capabilities = BDI_CAP_MAP_COPY; + blk_queue_max_sectors(q, MAX_SECTORS); + blk_queue_hardsect_size(q, 512); + blk_queue_dma_alignment(q, 511); + blk_queue_congestion_threshold(q); + q->nr_batching = BLK_BATCH_REQ; + + q->unplug_thresh = 4; /* hmm */ + q->unplug_delay = (3 * HZ) / 1000; /* 3 milliseconds */ + if (q->unplug_delay == 0) + q->unplug_delay = 1; + + INIT_WORK(&q->unplug_work, blk_unplug_work, q); + + q->unplug_timer.function = blk_unplug_timeout; + q->unplug_timer.data = (unsigned long)q; + + /* + * by default assume old behaviour and bounce for any highmem page + */ + blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH); + + blk_queue_activity_fn(q, NULL, NULL); +} + +EXPORT_SYMBOL(blk_queue_make_request); + +static inline void rq_init(request_queue_t *q, struct request *rq) +{ + INIT_LIST_HEAD(&rq->queuelist); + + rq->errors = 0; + rq->rq_status = RQ_ACTIVE; + rq->bio = rq->biotail = NULL; + rq->ioprio = 0; + rq->buffer = NULL; + rq->ref_count = 1; + rq->q = q; + rq->waiting = NULL; + rq->special = NULL; + rq->data_len = 0; + rq->data = NULL; + rq->nr_phys_segments = 0; + rq->sense = NULL; + rq->end_io = NULL; + rq->end_io_data = NULL; +} + +/** + * blk_queue_ordered - does this queue support ordered writes + * @q: the request queue + * @flag: see below + * + * Description: + * For journalled file systems, doing ordered writes on a commit + * block instead of explicitly doing wait_on_buffer (which is bad + * for performance) can be a big win. Block drivers supporting this + * feature should call this function and indicate so. + * + **/ +void blk_queue_ordered(request_queue_t *q, int flag) +{ + switch (flag) { + case QUEUE_ORDERED_NONE: + if (q->flush_rq) + kmem_cache_free(request_cachep, q->flush_rq); + q->flush_rq = NULL; + q->ordered = flag; + break; + case QUEUE_ORDERED_TAG: + q->ordered = flag; + break; + case QUEUE_ORDERED_FLUSH: + q->ordered = flag; + if (!q->flush_rq) + q->flush_rq = kmem_cache_alloc(request_cachep, + GFP_KERNEL); + break; + default: + printk("blk_queue_ordered: bad value %d\n", flag); + break; + } +} + +EXPORT_SYMBOL(blk_queue_ordered); + +/** + * blk_queue_issue_flush_fn - set function for issuing a flush + * @q: the request queue + * @iff: the function to be called issuing the flush + * + * Description: + * If a driver supports issuing a flush command, the support is notified + * to the block layer by defining it through this call. + * + **/ +void blk_queue_issue_flush_fn(request_queue_t *q, issue_flush_fn *iff) +{ + q->issue_flush_fn = iff; +} + +EXPORT_SYMBOL(blk_queue_issue_flush_fn); + +/* + * Cache flushing for ordered writes handling + */ +static void blk_pre_flush_end_io(struct request *flush_rq) +{ + struct request *rq = flush_rq->end_io_data; + request_queue_t *q = rq->q; + + elv_completed_request(q, flush_rq); + + rq->flags |= REQ_BAR_PREFLUSH; + + if (!flush_rq->errors) + elv_requeue_request(q, rq); + else { + q->end_flush_fn(q, flush_rq); + clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags); + q->request_fn(q); + } +} + +static void blk_post_flush_end_io(struct request *flush_rq) +{ + struct request *rq = flush_rq->end_io_data; + request_queue_t *q = rq->q; + + elv_completed_request(q, flush_rq); + + rq->flags |= REQ_BAR_POSTFLUSH; + + q->end_flush_fn(q, flush_rq); + clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags); + q->request_fn(q); +} + +struct request *blk_start_pre_flush(request_queue_t *q, struct request *rq) +{ + struct request *flush_rq = q->flush_rq; + + BUG_ON(!blk_barrier_rq(rq)); + + if (test_and_set_bit(QUEUE_FLAG_FLUSH, &q->queue_flags)) + return NULL; + + rq_init(q, flush_rq); + flush_rq->elevator_private = NULL; + flush_rq->flags = REQ_BAR_FLUSH; + flush_rq->rq_disk = rq->rq_disk; + flush_rq->rl = NULL; + + /* + * prepare_flush returns 0 if no flush is needed, just mark both + * pre and post flush as done in that case + */ + if (!q->prepare_flush_fn(q, flush_rq)) { + rq->flags |= REQ_BAR_PREFLUSH | REQ_BAR_POSTFLUSH; + clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags); + return rq; + } + + /* + * some drivers dequeue requests right away, some only after io + * completion. make sure the request is dequeued. + */ + if (!list_empty(&rq->queuelist)) + blkdev_dequeue_request(rq); + + flush_rq->end_io_data = rq; + flush_rq->end_io = blk_pre_flush_end_io; + + __elv_add_request(q, flush_rq, ELEVATOR_INSERT_FRONT, 0); + return flush_rq; +} + +static void blk_start_post_flush(request_queue_t *q, struct request *rq) +{ + struct request *flush_rq = q->flush_rq; + + BUG_ON(!blk_barrier_rq(rq)); + + rq_init(q, flush_rq); + flush_rq->elevator_private = NULL; + flush_rq->flags = REQ_BAR_FLUSH; + flush_rq->rq_disk = rq->rq_disk; + flush_rq->rl = NULL; + + if (q->prepare_flush_fn(q, flush_rq)) { + flush_rq->end_io_data = rq; + flush_rq->end_io = blk_post_flush_end_io; + + __elv_add_request(q, flush_rq, ELEVATOR_INSERT_FRONT, 0); + q->request_fn(q); + } +} + +static inline int blk_check_end_barrier(request_queue_t *q, struct request *rq, + int sectors) +{ + if (sectors > rq->nr_sectors) + sectors = rq->nr_sectors; + + rq->nr_sectors -= sectors; + return rq->nr_sectors; +} + +static int __blk_complete_barrier_rq(request_queue_t *q, struct request *rq, + int sectors, int queue_locked) +{ + if (q->ordered != QUEUE_ORDERED_FLUSH) + return 0; + if (!blk_fs_request(rq) || !blk_barrier_rq(rq)) + return 0; + if (blk_barrier_postflush(rq)) + return 0; + + if (!blk_check_end_barrier(q, rq, sectors)) { + unsigned long flags = 0; + + if (!queue_locked) + spin_lock_irqsave(q->queue_lock, flags); + + blk_start_post_flush(q, rq); + + if (!queue_locked) + spin_unlock_irqrestore(q->queue_lock, flags); + } + + return 1; +} + +/** + * blk_complete_barrier_rq - complete possible barrier request + * @q: the request queue for the device + * @rq: the request + * @sectors: number of sectors to complete + * + * Description: + * Used in driver end_io handling to determine whether to postpone + * completion of a barrier request until a post flush has been done. This + * is the unlocked variant, used if the caller doesn't already hold the + * queue lock. + **/ +int blk_complete_barrier_rq(request_queue_t *q, struct request *rq, int sectors) +{ + return __blk_complete_barrier_rq(q, rq, sectors, 0); +} +EXPORT_SYMBOL(blk_complete_barrier_rq); + +/** + * blk_complete_barrier_rq_locked - complete possible barrier request + * @q: the request queue for the device + * @rq: the request + * @sectors: number of sectors to complete + * + * Description: + * See blk_complete_barrier_rq(). This variant must be used if the caller + * holds the queue lock. + **/ +int blk_complete_barrier_rq_locked(request_queue_t *q, struct request *rq, + int sectors) +{ + return __blk_complete_barrier_rq(q, rq, sectors, 1); +} +EXPORT_SYMBOL(blk_complete_barrier_rq_locked); + +/** + * blk_queue_bounce_limit - set bounce buffer limit for queue + * @q: the request queue for the device + * @dma_addr: bus address limit + * + * Description: + * Different hardware can have different requirements as to what pages + * it can do I/O directly to. A low level driver can call + * blk_queue_bounce_limit to have lower memory pages allocated as bounce + * buffers for doing I/O to pages residing above @page. By default + * the block layer sets this to the highest numbered "low" memory page. + **/ +void blk_queue_bounce_limit(request_queue_t *q, u64 dma_addr) +{ + unsigned long bounce_pfn = dma_addr >> PAGE_SHIFT; + + /* + * set appropriate bounce gfp mask -- unfortunately we don't have a + * full 4GB zone, so we have to resort to low memory for any bounces. + * ISA has its own < 16MB zone. + */ + if (bounce_pfn < blk_max_low_pfn) { + BUG_ON(dma_addr < BLK_BOUNCE_ISA); + init_emergency_isa_pool(); + q->bounce_gfp = GFP_NOIO | GFP_DMA; + } else + q->bounce_gfp = GFP_NOIO; + + q->bounce_pfn = bounce_pfn; +} + +EXPORT_SYMBOL(blk_queue_bounce_limit); + +/** + * blk_queue_max_sectors - set max sectors for a request for this queue + * @q: the request queue for the device + * @max_sectors: max sectors in the usual 512b unit + * + * Description: + * Enables a low level driver to set an upper limit on the size of + * received requests. + **/ +void blk_queue_max_sectors(request_queue_t *q, unsigned short max_sectors) +{ + if ((max_sectors << 9) < PAGE_CACHE_SIZE) { + max_sectors = 1 << (PAGE_CACHE_SHIFT - 9); + printk("%s: set to minimum %d\n", __FUNCTION__, max_sectors); + } + + q->max_sectors = q->max_hw_sectors = max_sectors; +} + +EXPORT_SYMBOL(blk_queue_max_sectors); + +/** + * blk_queue_max_phys_segments - set max phys segments for a request for this queue + * @q: the request queue for the device + * @max_segments: max number of segments + * + * Description: + * Enables a low level driver to set an upper limit on the number of + * physical data segments in a request. This would be the largest sized + * scatter list the driver could handle. + **/ +void blk_queue_max_phys_segments(request_queue_t *q, unsigned short max_segments) +{ + if (!max_segments) { + max_segments = 1; + printk("%s: set to minimum %d\n", __FUNCTION__, max_segments); + } + + q->max_phys_segments = max_segments; +} + +EXPORT_SYMBOL(blk_queue_max_phys_segments); + +/** + * blk_queue_max_hw_segments - set max hw segments for a request for this queue + * @q: the request queue for the device + * @max_segments: max number of segments + * + * Description: + * Enables a low level driver to set an upper limit on the number of + * hw data segments in a request. This would be the largest number of + * address/length pairs the host adapter can actually give as once + * to the device. + **/ +void blk_queue_max_hw_segments(request_queue_t *q, unsigned short max_segments) +{ + if (!max_segments) { + max_segments = 1; + printk("%s: set to minimum %d\n", __FUNCTION__, max_segments); + } + + q->max_hw_segments = max_segments; +} + +EXPORT_SYMBOL(blk_queue_max_hw_segments); + +/** + * blk_queue_max_segment_size - set max segment size for blk_rq_map_sg + * @q: the request queue for the device + * @max_size: max size of segment in bytes + * + * Description: + * Enables a low level driver to set an upper limit on the size of a + * coalesced segment + **/ +void blk_queue_max_segment_size(request_queue_t *q, unsigned int max_size) +{ + if (max_size < PAGE_CACHE_SIZE) { + max_size = PAGE_CACHE_SIZE; + printk("%s: set to minimum %d\n", __FUNCTION__, max_size); + } + + q->max_segment_size = max_size; +} + +EXPORT_SYMBOL(blk_queue_max_segment_size); + +/** + * blk_queue_hardsect_size - set hardware sector size for the queue + * @q: the request queue for the device + * @size: the hardware sector size, in bytes + * + * Description: + * This should typically be set to the lowest possible sector size + * that the hardware can operate on (possible without reverting to + * even internal read-modify-write operations). Usually the default + * of 512 covers most hardware. + **/ +void blk_queue_hardsect_size(request_queue_t *q, unsigned short size) +{ + q->hardsect_size = size; +} + +EXPORT_SYMBOL(blk_queue_hardsect_size); + +/* + * Returns the minimum that is _not_ zero, unless both are zero. + */ +#define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r)) + +/** + * blk_queue_stack_limits - inherit underlying queue limits for stacked drivers + * @t: the stacking driver (top) + * @b: the underlying device (bottom) + **/ +void blk_queue_stack_limits(request_queue_t *t, request_queue_t *b) +{ + /* zero is "infinity" */ + t->max_sectors = t->max_hw_sectors = + min_not_zero(t->max_sectors,b->max_sectors); + + t->max_phys_segments = min(t->max_phys_segments,b->max_phys_segments); + t->max_hw_segments = min(t->max_hw_segments,b->max_hw_segments); + t->max_segment_size = min(t->max_segment_size,b->max_segment_size); + t->hardsect_size = max(t->hardsect_size,b->hardsect_size); +} + +EXPORT_SYMBOL(blk_queue_stack_limits); + +/** + * blk_queue_segment_boundary - set boundary rules for segment merging + * @q: the request queue for the device + * @mask: the memory boundary mask + **/ +void blk_queue_segment_boundary(request_queue_t *q, unsigned long mask) +{ + if (mask < PAGE_CACHE_SIZE - 1) { + mask = PAGE_CACHE_SIZE - 1; + printk("%s: set to minimum %lx\n", __FUNCTION__, mask); + } + + q->seg_boundary_mask = mask; +} + +EXPORT_SYMBOL(blk_queue_segment_boundary); + +/** + * blk_queue_dma_alignment - set dma length and memory alignment + * @q: the request queue for the device + * @mask: alignment mask + * + * description: + * set required memory and length aligment for direct dma transactions. + * this is used when buiding direct io requests for the queue. + * + **/ +void blk_queue_dma_alignment(request_queue_t *q, int mask) +{ + q->dma_alignment = mask; +} + +EXPORT_SYMBOL(blk_queue_dma_alignment); + +/** + * blk_queue_find_tag - find a request by its tag and queue + * + * @q: The request queue for the device + * @tag: The tag of the request + * + * Notes: + * Should be used when a device returns a tag and you want to match + * it with a request. + * + * no locks need be held. + **/ +struct request *blk_queue_find_tag(request_queue_t *q, int tag) +{ + struct blk_queue_tag *bqt = q->queue_tags; + + if (unlikely(bqt == NULL || tag >= bqt->real_max_depth)) + return NULL; + + return bqt->tag_index[tag]; +} + +EXPORT_SYMBOL(blk_queue_find_tag); + +/** + * __blk_queue_free_tags - release tag maintenance info + * @q: the request queue for the device + * + * Notes: + * blk_cleanup_queue() will take care of calling this function, if tagging + * has been used. So there's no need to call this directly. + **/ +static void __blk_queue_free_tags(request_queue_t *q) +{ + struct blk_queue_tag *bqt = q->queue_tags; + + if (!bqt) + return; + + if (atomic_dec_and_test(&bqt->refcnt)) { + BUG_ON(bqt->busy); + BUG_ON(!list_empty(&bqt->busy_list)); + + kfree(bqt->tag_index); + bqt->tag_index = NULL; + + kfree(bqt->tag_map); + bqt->tag_map = NULL; + + kfree(bqt); + } + + q->queue_tags = NULL; + q->queue_flags &= ~(1 << QUEUE_FLAG_QUEUED); +} + +/** + * blk_queue_free_tags - release tag maintenance info + * @q: the request queue for the device + * + * Notes: + * This is used to disabled tagged queuing to a device, yet leave + * queue in function. + **/ +void blk_queue_free_tags(request_queue_t *q) +{ + clear_bit(QUEUE_FLAG_QUEUED, &q->queue_flags); +} + +EXPORT_SYMBOL(blk_queue_free_tags); + +static int +init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth) +{ + struct request **tag_index; + unsigned long *tag_map; + int nr_ulongs; + + if (depth > q->nr_requests * 2) { + depth = q->nr_requests * 2; + printk(KERN_ERR "%s: adjusted depth to %d\n", + __FUNCTION__, depth); + } + + tag_index = kmalloc(depth * sizeof(struct request *), GFP_ATOMIC); + if (!tag_index) + goto fail; + + nr_ulongs = ALIGN(depth, BITS_PER_LONG) / BITS_PER_LONG; + tag_map = kmalloc(nr_ulongs * sizeof(unsigned long), GFP_ATOMIC); + if (!tag_map) + goto fail; + + memset(tag_index, 0, depth * sizeof(struct request *)); + memset(tag_map, 0, nr_ulongs * sizeof(unsigned long)); + tags->real_max_depth = depth; + tags->max_depth = depth; + tags->tag_index = tag_index; + tags->tag_map = tag_map; + + return 0; +fail: + kfree(tag_index); + return -ENOMEM; +} + +/** + * blk_queue_init_tags - initialize the queue tag info + * @q: the request queue for the device + * @depth: the maximum queue depth supported + * @tags: the tag to use + **/ +int blk_queue_init_tags(request_queue_t *q, int depth, + struct blk_queue_tag *tags) +{ + int rc; + + BUG_ON(tags && q->queue_tags && tags != q->queue_tags); + + if (!tags && !q->queue_tags) { + tags = kmalloc(sizeof(struct blk_queue_tag), GFP_ATOMIC); + if (!tags) + goto fail; + + if (init_tag_map(q, tags, depth)) + goto fail; + + INIT_LIST_HEAD(&tags->busy_list); + tags->busy = 0; + atomic_set(&tags->refcnt, 1); + } else if (q->queue_tags) { + if ((rc = blk_queue_resize_tags(q, depth))) + return rc; + set_bit(QUEUE_FLAG_QUEUED, &q->queue_flags); + return 0; + } else + atomic_inc(&tags->refcnt); + + /* + * assign it, all done + */ + q->queue_tags = tags; + q->queue_flags |= (1 << QUEUE_FLAG_QUEUED); + return 0; +fail: + kfree(tags); + return -ENOMEM; +} + +EXPORT_SYMBOL(blk_queue_init_tags); + +/** + * blk_queue_resize_tags - change the queueing depth + * @q: the request queue for the device + * @new_depth: the new max command queueing depth + * + * Notes: + * Must be called with the queue lock held. + **/ +int blk_queue_resize_tags(request_queue_t *q, int new_depth) +{ + struct blk_queue_tag *bqt = q->queue_tags; + struct request **tag_index; + unsigned long *tag_map; + int max_depth, nr_ulongs; + + if (!bqt) + return -ENXIO; + + /* + * if we already have large enough real_max_depth. just + * adjust max_depth. *NOTE* as requests with tag value + * between new_depth and real_max_depth can be in-flight, tag + * map can not be shrunk blindly here. + */ + if (new_depth <= bqt->real_max_depth) { + bqt->max_depth = new_depth; + return 0; + } + + /* + * save the old state info, so we can copy it back + */ + tag_index = bqt->tag_index; + tag_map = bqt->tag_map; + max_depth = bqt->real_max_depth; + + if (init_tag_map(q, bqt, new_depth)) + return -ENOMEM; + + memcpy(bqt->tag_index, tag_index, max_depth * sizeof(struct request *)); + nr_ulongs = ALIGN(max_depth, BITS_PER_LONG) / BITS_PER_LONG; + memcpy(bqt->tag_map, tag_map, nr_ulongs * sizeof(unsigned long)); + + kfree(tag_index); + kfree(tag_map); + return 0; +} + +EXPORT_SYMBOL(blk_queue_resize_tags); + +/** + * blk_queue_end_tag - end tag operations for a request + * @q: the request queue for the device + * @rq: the request that has completed + * + * Description: + * Typically called when end_that_request_first() returns 0, meaning + * all transfers have been done for a request. It's important to call + * this function before end_that_request_last(), as that will put the + * request back on the free list thus corrupting the internal tag list. + * + * Notes: + * queue lock must be held. + **/ +void blk_queue_end_tag(request_queue_t *q, struct request *rq) +{ + struct blk_queue_tag *bqt = q->queue_tags; + int tag = rq->tag; + + BUG_ON(tag == -1); + + if (unlikely(tag >= bqt->real_max_depth)) + /* + * This can happen after tag depth has been reduced. + * FIXME: how about a warning or info message here? + */ + return; + + if (unlikely(!__test_and_clear_bit(tag, bqt->tag_map))) { + printk(KERN_ERR "%s: attempt to clear non-busy tag (%d)\n", + __FUNCTION__, tag); + return; + } + + list_del_init(&rq->queuelist); + rq->flags &= ~REQ_QUEUED; + rq->tag = -1; + + if (unlikely(bqt->tag_index[tag] == NULL)) + printk(KERN_ERR "%s: tag %d is missing\n", + __FUNCTION__, tag); + + bqt->tag_index[tag] = NULL; + bqt->busy--; +} + +EXPORT_SYMBOL(blk_queue_end_tag); + +/** + * blk_queue_start_tag - find a free tag and assign it + * @q: the request queue for the device + * @rq: the block request that needs tagging + * + * Description: + * This can either be used as a stand-alone helper, or possibly be + * assigned as the queue &prep_rq_fn (in which case &struct request + * automagically gets a tag assigned). Note that this function + * assumes that any type of request can be queued! if this is not + * true for your device, you must check the request type before + * calling this function. The request will also be removed from + * the request queue, so it's the drivers responsibility to readd + * it if it should need to be restarted for some reason. + * + * Notes: + * queue lock must be held. + **/ +int blk_queue_start_tag(request_queue_t *q, struct request *rq) +{ + struct blk_queue_tag *bqt = q->queue_tags; + int tag; + + if (unlikely((rq->flags & REQ_QUEUED))) { + printk(KERN_ERR + "%s: request %p for device [%s] already tagged %d", + __FUNCTION__, rq, + rq->rq_disk ? rq->rq_disk->disk_name : "?", rq->tag); + BUG(); + } + + tag = find_first_zero_bit(bqt->tag_map, bqt->max_depth); + if (tag >= bqt->max_depth) + return 1; + + __set_bit(tag, bqt->tag_map); + + rq->flags |= REQ_QUEUED; + rq->tag = tag; + bqt->tag_index[tag] = rq; + blkdev_dequeue_request(rq); + list_add(&rq->queuelist, &bqt->busy_list); + bqt->busy++; + return 0; +} + +EXPORT_SYMBOL(blk_queue_start_tag); + +/** + * blk_queue_invalidate_tags - invalidate all pending tags + * @q: the request queue for the device + * + * Description: + * Hardware conditions may dictate a need to stop all pending requests. + * In this case, we will safely clear the block side of the tag queue and + * readd all requests to the request queue in the right order. + * + * Notes: + * queue lock must be held. + **/ +void blk_queue_invalidate_tags(request_queue_t *q) +{ + struct blk_queue_tag *bqt = q->queue_tags; + struct list_head *tmp, *n; + struct request *rq; + + list_for_each_safe(tmp, n, &bqt->busy_list) { + rq = list_entry_rq(tmp); + + if (rq->tag == -1) { + printk(KERN_ERR + "%s: bad tag found on list\n", __FUNCTION__); + list_del_init(&rq->queuelist); + rq->flags &= ~REQ_QUEUED; + } else + blk_queue_end_tag(q, rq); + + rq->flags &= ~REQ_STARTED; + __elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 0); + } +} + +EXPORT_SYMBOL(blk_queue_invalidate_tags); + +static char *rq_flags[] = { + "REQ_RW", + "REQ_FAILFAST", + "REQ_SORTED", + "REQ_SOFTBARRIER", + "REQ_HARDBARRIER", + "REQ_CMD", + "REQ_NOMERGE", + "REQ_STARTED", + "REQ_DONTPREP", + "REQ_QUEUED", + "REQ_ELVPRIV", + "REQ_PC", + "REQ_BLOCK_PC", + "REQ_SENSE", + "REQ_FAILED", + "REQ_QUIET", + "REQ_SPECIAL", + "REQ_DRIVE_CMD", + "REQ_DRIVE_TASK", + "REQ_DRIVE_TASKFILE", + "REQ_PREEMPT", + "REQ_PM_SUSPEND", + "REQ_PM_RESUME", + "REQ_PM_SHUTDOWN", +}; + +void blk_dump_rq_flags(struct request *rq, char *msg) +{ + int bit; + + printk("%s: dev %s: flags = ", msg, + rq->rq_disk ? rq->rq_disk->disk_name : "?"); + bit = 0; + do { + if (rq->flags & (1 << bit)) + printk("%s ", rq_flags[bit]); + bit++; + } while (bit < __REQ_NR_BITS); + + printk("\nsector %llu, nr/cnr %lu/%u\n", (unsigned long long)rq->sector, + rq->nr_sectors, + rq->current_nr_sectors); + printk("bio %p, biotail %p, buffer %p, data %p, len %u\n", rq->bio, rq->biotail, rq->buffer, rq->data, rq->data_len); + + if (rq->flags & (REQ_BLOCK_PC | REQ_PC)) { + printk("cdb: "); + for (bit = 0; bit < sizeof(rq->cmd); bit++) + printk("%02x ", rq->cmd[bit]); + printk("\n"); + } +} + +EXPORT_SYMBOL(blk_dump_rq_flags); + +void blk_recount_segments(request_queue_t *q, struct bio *bio) +{ + struct bio_vec *bv, *bvprv = NULL; + int i, nr_phys_segs, nr_hw_segs, seg_size, hw_seg_size, cluster; + int high, highprv = 1; + + if (unlikely(!bio->bi_io_vec)) + return; + + cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER); + hw_seg_size = seg_size = nr_phys_segs = nr_hw_segs = 0; + bio_for_each_segment(bv, bio, i) { + /* + * the trick here is making sure that a high page is never + * considered part of another segment, since that might + * change with the bounce page. + */ + high = page_to_pfn(bv->bv_page) >= q->bounce_pfn; + if (high || highprv) + goto new_hw_segment; + if (cluster) { + if (seg_size + bv->bv_len > q->max_segment_size) + goto new_segment; + if (!BIOVEC_PHYS_MERGEABLE(bvprv, bv)) + goto new_segment; + if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bv)) + goto new_segment; + if (BIOVEC_VIRT_OVERSIZE(hw_seg_size + bv->bv_len)) + goto new_hw_segment; + + seg_size += bv->bv_len; + hw_seg_size += bv->bv_len; + bvprv = bv; + continue; + } +new_segment: + if (BIOVEC_VIRT_MERGEABLE(bvprv, bv) && + !BIOVEC_VIRT_OVERSIZE(hw_seg_size + bv->bv_len)) { + hw_seg_size += bv->bv_len; + } else { +new_hw_segment: + if (hw_seg_size > bio->bi_hw_front_size) + bio->bi_hw_front_size = hw_seg_size; + hw_seg_size = BIOVEC_VIRT_START_SIZE(bv) + bv->bv_len; + nr_hw_segs++; + } + + nr_phys_segs++; + bvprv = bv; + seg_size = bv->bv_len; + highprv = high; + } + if (hw_seg_size > bio->bi_hw_back_size) + bio->bi_hw_back_size = hw_seg_size; + if (nr_hw_segs == 1 && hw_seg_size > bio->bi_hw_front_size) + bio->bi_hw_front_size = hw_seg_size; + bio->bi_phys_segments = nr_phys_segs; + bio->bi_hw_segments = nr_hw_segs; + bio->bi_flags |= (1 << BIO_SEG_VALID); +} + + +static int blk_phys_contig_segment(request_queue_t *q, struct bio *bio, + struct bio *nxt) +{ + if (!(q->queue_flags & (1 << QUEUE_FLAG_CLUSTER))) + return 0; + + if (!BIOVEC_PHYS_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt))) + return 0; + if (bio->bi_size + nxt->bi_size > q->max_segment_size) + return 0; + + /* + * bio and nxt are contigous in memory, check if the queue allows + * these two to be merged into one + */ + if (BIO_SEG_BOUNDARY(q, bio, nxt)) + return 1; + + return 0; +} + +static int blk_hw_contig_segment(request_queue_t *q, struct bio *bio, + struct bio *nxt) +{ + if (unlikely(!bio_flagged(bio, BIO_SEG_VALID))) + blk_recount_segments(q, bio); + if (unlikely(!bio_flagged(nxt, BIO_SEG_VALID))) + blk_recount_segments(q, nxt); + if (!BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt)) || + BIOVEC_VIRT_OVERSIZE(bio->bi_hw_front_size + bio->bi_hw_back_size)) + return 0; + if (bio->bi_size + nxt->bi_size > q->max_segment_size) + return 0; + + return 1; +} + +/* + * map a request to scatterlist, return number of sg entries setup. Caller + * must make sure sg can hold rq->nr_phys_segments entries + */ +int blk_rq_map_sg(request_queue_t *q, struct request *rq, struct scatterlist *sg) +{ + struct bio_vec *bvec, *bvprv; + struct bio *bio; + int nsegs, i, cluster; + + nsegs = 0; + cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER); + + /* + * for each bio in rq + */ + bvprv = NULL; + rq_for_each_bio(bio, rq) { + /* + * for each segment in bio + */ + bio_for_each_segment(bvec, bio, i) { + int nbytes = bvec->bv_len; + + if (bvprv && cluster) { + if (sg[nsegs - 1].length + nbytes > q->max_segment_size) + goto new_segment; + + if (!BIOVEC_PHYS_MERGEABLE(bvprv, bvec)) + goto new_segment; + if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bvec)) + goto new_segment; + + sg[nsegs - 1].length += nbytes; + } else { +new_segment: + memset(&sg[nsegs],0,sizeof(struct scatterlist)); + sg[nsegs].page = bvec->bv_page; + sg[nsegs].length = nbytes; + sg[nsegs].offset = bvec->bv_offset; + + nsegs++; + } + bvprv = bvec; + } /* segments in bio */ + } /* bios in rq */ + + return nsegs; +} + +EXPORT_SYMBOL(blk_rq_map_sg); + +/* + * the standard queue merge functions, can be overridden with device + * specific ones if so desired + */ + +static inline int ll_new_mergeable(request_queue_t *q, + struct request *req, + struct bio *bio) +{ + int nr_phys_segs = bio_phys_segments(q, bio); + + if (req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) { + req->flags |= REQ_NOMERGE; + if (req == q->last_merge) + q->last_merge = NULL; + return 0; + } + + /* + * A hw segment is just getting larger, bump just the phys + * counter. + */ + req->nr_phys_segments += nr_phys_segs; + return 1; +} + +static inline int ll_new_hw_segment(request_queue_t *q, + struct request *req, + struct bio *bio) +{ + int nr_hw_segs = bio_hw_segments(q, bio); + int nr_phys_segs = bio_phys_segments(q, bio); + + if (req->nr_hw_segments + nr_hw_segs > q->max_hw_segments + || req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) { + req->flags |= REQ_NOMERGE; + if (req == q->last_merge) + q->last_merge = NULL; + return 0; + } + + /* + * This will form the start of a new hw segment. Bump both + * counters. + */ + req->nr_hw_segments += nr_hw_segs; + req->nr_phys_segments += nr_phys_segs; + return 1; +} + +static int ll_back_merge_fn(request_queue_t *q, struct request *req, + struct bio *bio) +{ + int len; + + if (req->nr_sectors + bio_sectors(bio) > q->max_sectors) { + req->flags |= REQ_NOMERGE; + if (req == q->last_merge) + q->last_merge = NULL; + return 0; + } + if (unlikely(!bio_flagged(req->biotail, BIO_SEG_VALID))) + blk_recount_segments(q, req->biotail); + if (unlikely(!bio_flagged(bio, BIO_SEG_VALID))) + blk_recount_segments(q, bio); + len = req->biotail->bi_hw_back_size + bio->bi_hw_front_size; + if (BIOVEC_VIRT_MERGEABLE(__BVEC_END(req->biotail), __BVEC_START(bio)) && + !BIOVEC_VIRT_OVERSIZE(len)) { + int mergeable = ll_new_mergeable(q, req, bio); + + if (mergeable) { + if (req->nr_hw_segments == 1) + req->bio->bi_hw_front_size = len; + if (bio->bi_hw_segments == 1) + bio->bi_hw_back_size = len; + } + return mergeable; + } + + return ll_new_hw_segment(q, req, bio); +} + +static int ll_front_merge_fn(request_queue_t *q, struct request *req, + struct bio *bio) +{ + int len; + + if (req->nr_sectors + bio_sectors(bio) > q->max_sectors) { + req->flags |= REQ_NOMERGE; + if (req == q->last_merge) + q->last_merge = NULL; + return 0; + } + len = bio->bi_hw_back_size + req->bio->bi_hw_front_size; + if (unlikely(!bio_flagged(bio, BIO_SEG_VALID))) + blk_recount_segments(q, bio); + if (unlikely(!bio_flagged(req->bio, BIO_SEG_VALID))) + blk_recount_segments(q, req->bio); + if (BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(req->bio)) && + !BIOVEC_VIRT_OVERSIZE(len)) { + int mergeable = ll_new_mergeable(q, req, bio); + + if (mergeable) { + if (bio->bi_hw_segments == 1) + bio->bi_hw_front_size = len; + if (req->nr_hw_segments == 1) + req->biotail->bi_hw_back_size = len; + } + return mergeable; + } + + return ll_new_hw_segment(q, req, bio); +} + +static int ll_merge_requests_fn(request_queue_t *q, struct request *req, + struct request *next) +{ + int total_phys_segments; + int total_hw_segments; + + /* + * First check if the either of the requests are re-queued + * requests. Can't merge them if they are. + */ + if (req->special || next->special) + return 0; + + /* + * Will it become too large? + */ + if ((req->nr_sectors + next->nr_sectors) > q->max_sectors) + return 0; + + total_phys_segments = req->nr_phys_segments + next->nr_phys_segments; + if (blk_phys_contig_segment(q, req->biotail, next->bio)) + total_phys_segments--; + + if (total_phys_segments > q->max_phys_segments) + return 0; + + total_hw_segments = req->nr_hw_segments + next->nr_hw_segments; + if (blk_hw_contig_segment(q, req->biotail, next->bio)) { + int len = req->biotail->bi_hw_back_size + next->bio->bi_hw_front_size; + /* + * propagate the combined length to the end of the requests + */ + if (req->nr_hw_segments == 1) + req->bio->bi_hw_front_size = len; + if (next->nr_hw_segments == 1) + next->biotail->bi_hw_back_size = len; + total_hw_segments--; + } + + if (total_hw_segments > q->max_hw_segments) + return 0; + + /* Merge is OK... */ + req->nr_phys_segments = total_phys_segments; + req->nr_hw_segments = total_hw_segments; + return 1; +} + +/* + * "plug" the device if there are no outstanding requests: this will + * force the transfer to start only after we have put all the requests + * on the list. + * + * This is called with interrupts off and no requests on the queue and + * with the queue lock held. + */ +void blk_plug_device(request_queue_t *q) +{ + WARN_ON(!irqs_disabled()); + + /* + * don't plug a stopped queue, it must be paired with blk_start_queue() + * which will restart the queueing + */ + if (test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags)) + return; + + if (!test_and_set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) + mod_timer(&q->unplug_timer, jiffies + q->unplug_delay); +} + +EXPORT_SYMBOL(blk_plug_device); + +/* + * remove the queue from the plugged list, if present. called with + * queue lock held and interrupts disabled. + */ +int blk_remove_plug(request_queue_t *q) +{ + WARN_ON(!irqs_disabled()); + + if (!test_and_clear_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) + return 0; + + del_timer(&q->unplug_timer); + return 1; +} + +EXPORT_SYMBOL(blk_remove_plug); + +/* + * remove the plug and let it rip.. + */ +void __generic_unplug_device(request_queue_t *q) +{ + if (unlikely(test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags))) + return; + + if (!blk_remove_plug(q)) + return; + + q->request_fn(q); +} +EXPORT_SYMBOL(__generic_unplug_device); + +/** + * generic_unplug_device - fire a request queue + * @q: The &request_queue_t in question + * + * Description: + * Linux uses plugging to build bigger requests queues before letting + * the device have at them. If a queue is plugged, the I/O scheduler + * is still adding and merging requests on the queue. Once the queue + * gets unplugged, the request_fn defined for the queue is invoked and + * transfers started. + **/ +void generic_unplug_device(request_queue_t *q) +{ + spin_lock_irq(q->queue_lock); + __generic_unplug_device(q); + spin_unlock_irq(q->queue_lock); +} +EXPORT_SYMBOL(generic_unplug_device); + +static void blk_backing_dev_unplug(struct backing_dev_info *bdi, + struct page *page) +{ + request_queue_t *q = bdi->unplug_io_data; + + /* + * devices don't necessarily have an ->unplug_fn defined + */ + if (q->unplug_fn) + q->unplug_fn(q); +} + +static void blk_unplug_work(void *data) +{ + request_queue_t *q = data; + + q->unplug_fn(q); +} + +static void blk_unplug_timeout(unsigned long data) +{ + request_queue_t *q = (request_queue_t *)data; + + kblockd_schedule_work(&q->unplug_work); +} + +/** + * blk_start_queue - restart a previously stopped queue + * @q: The &request_queue_t in question + * + * Description: + * blk_start_queue() will clear the stop flag on the queue, and call + * the request_fn for the queue if it was in a stopped state when + * entered. Also see blk_stop_queue(). Queue lock must be held. + **/ +void blk_start_queue(request_queue_t *q) +{ + clear_bit(QUEUE_FLAG_STOPPED, &q->queue_flags); + + /* + * one level of recursion is ok and is much faster than kicking + * the unplug handling + */ + if (!test_and_set_bit(QUEUE_FLAG_REENTER, &q->queue_flags)) { + q->request_fn(q); + clear_bit(QUEUE_FLAG_REENTER, &q->queue_flags); + } else { + blk_plug_device(q); + kblockd_schedule_work(&q->unplug_work); + } +} + +EXPORT_SYMBOL(blk_start_queue); + +/** + * blk_stop_queue - stop a queue + * @q: The &request_queue_t in question + * + * Description: + * The Linux block layer assumes that a block driver will consume all + * entries on the request queue when the request_fn strategy is called. + * Often this will not happen, because of hardware limitations (queue + * depth settings). If a device driver gets a 'queue full' response, + * or if it simply chooses not to queue more I/O at one point, it can + * call this function to prevent the request_fn from being called until + * the driver has signalled it's ready to go again. This happens by calling + * blk_start_queue() to restart queue operations. Queue lock must be held. + **/ +void blk_stop_queue(request_queue_t *q) +{ + blk_remove_plug(q); + set_bit(QUEUE_FLAG_STOPPED, &q->queue_flags); +} +EXPORT_SYMBOL(blk_stop_queue); + +/** + * blk_sync_queue - cancel any pending callbacks on a queue + * @q: the queue + * + * Description: + * The block layer may perform asynchronous callback activity + * on a queue, such as calling the unplug function after a timeout. + * A block device may call blk_sync_queue to ensure that any + * such activity is cancelled, thus allowing it to release resources + * the the callbacks might use. The caller must already have made sure + * that its ->make_request_fn will not re-add plugging prior to calling + * this function. + * + */ +void blk_sync_queue(struct request_queue *q) +{ + del_timer_sync(&q->unplug_timer); + kblockd_flush(); +} +EXPORT_SYMBOL(blk_sync_queue); + +/** + * blk_run_queue - run a single device queue + * @q: The queue to run + */ +void blk_run_queue(struct request_queue *q) +{ + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); + blk_remove_plug(q); + if (!elv_queue_empty(q)) + q->request_fn(q); + spin_unlock_irqrestore(q->queue_lock, flags); +} +EXPORT_SYMBOL(blk_run_queue); + +/** + * blk_cleanup_queue: - release a &request_queue_t when it is no longer needed + * @q: the request queue to be released + * + * Description: + * blk_cleanup_queue is the pair to blk_init_queue() or + * blk_queue_make_request(). It should be called when a request queue is + * being released; typically when a block device is being de-registered. + * Currently, its primary task it to free all the &struct request + * structures that were allocated to the queue and the queue itself. + * + * Caveat: + * Hopefully the low level driver will have finished any + * outstanding requests first... + **/ +void blk_cleanup_queue(request_queue_t * q) +{ + struct request_list *rl = &q->rq; + + if (!atomic_dec_and_test(&q->refcnt)) + return; + + if (q->elevator) + elevator_exit(q->elevator); + + blk_sync_queue(q); + + if (rl->rq_pool) + mempool_destroy(rl->rq_pool); + + if (q->queue_tags) + __blk_queue_free_tags(q); + + blk_queue_ordered(q, QUEUE_ORDERED_NONE); + + kmem_cache_free(requestq_cachep, q); +} + +EXPORT_SYMBOL(blk_cleanup_queue); + +static int blk_init_free_list(request_queue_t *q) +{ + struct request_list *rl = &q->rq; + + rl->count[READ] = rl->count[WRITE] = 0; + rl->starved[READ] = rl->starved[WRITE] = 0; + rl->elvpriv = 0; + init_waitqueue_head(&rl->wait[READ]); + init_waitqueue_head(&rl->wait[WRITE]); + + rl->rq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab, + mempool_free_slab, request_cachep, q->node); + + if (!rl->rq_pool) + return -ENOMEM; + + return 0; +} + +static int __make_request(request_queue_t *, struct bio *); + +request_queue_t *blk_alloc_queue(gfp_t gfp_mask) +{ + return blk_alloc_queue_node(gfp_mask, -1); +} +EXPORT_SYMBOL(blk_alloc_queue); + +request_queue_t *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) +{ + request_queue_t *q; + + q = kmem_cache_alloc_node(requestq_cachep, gfp_mask, node_id); + if (!q) + return NULL; + + memset(q, 0, sizeof(*q)); + init_timer(&q->unplug_timer); + atomic_set(&q->refcnt, 1); + + q->backing_dev_info.unplug_io_fn = blk_backing_dev_unplug; + q->backing_dev_info.unplug_io_data = q; + + return q; +} +EXPORT_SYMBOL(blk_alloc_queue_node); + +/** + * blk_init_queue - prepare a request queue for use with a block device + * @rfn: The function to be called to process requests that have been + * placed on the queue. + * @lock: Request queue spin lock + * + * Description: + * If a block device wishes to use the standard request handling procedures, + * which sorts requests and coalesces adjacent requests, then it must + * call blk_init_queue(). The function @rfn will be called when there + * are requests on the queue that need to be processed. If the device + * supports plugging, then @rfn may not be called immediately when requests + * are available on the queue, but may be called at some time later instead. + * Plugged queues are generally unplugged when a buffer belonging to one + * of the requests on the queue is needed, or due to memory pressure. + * + * @rfn is not required, or even expected, to remove all requests off the + * queue, but only as many as it can handle at a time. If it does leave + * requests on the queue, it is responsible for arranging that the requests + * get dealt with eventually. + * + * The queue spin lock must be held while manipulating the requests on the + * request queue. + * + * Function returns a pointer to the initialized request queue, or NULL if + * it didn't succeed. + * + * Note: + * blk_init_queue() must be paired with a blk_cleanup_queue() call + * when the block device is deactivated (such as at module unload). + **/ + +request_queue_t *blk_init_queue(request_fn_proc *rfn, spinlock_t *lock) +{ + return blk_init_queue_node(rfn, lock, -1); +} +EXPORT_SYMBOL(blk_init_queue); + +request_queue_t * +blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id) +{ + request_queue_t *q = blk_alloc_queue_node(GFP_KERNEL, node_id); + + if (!q) + return NULL; + + q->node = node_id; + if (blk_init_free_list(q)) + goto out_init; + + /* + * if caller didn't supply a lock, they get per-queue locking with + * our embedded lock + */ + if (!lock) { + spin_lock_init(&q->__queue_lock); + lock = &q->__queue_lock; + } + + q->request_fn = rfn; + q->back_merge_fn = ll_back_merge_fn; + q->front_merge_fn = ll_front_merge_fn; + q->merge_requests_fn = ll_merge_requests_fn; + q->prep_rq_fn = NULL; + q->unplug_fn = generic_unplug_device; + q->queue_flags = (1 << QUEUE_FLAG_CLUSTER); + q->queue_lock = lock; + + blk_queue_segment_boundary(q, 0xffffffff); + + blk_queue_make_request(q, __make_request); + blk_queue_max_segment_size(q, MAX_SEGMENT_SIZE); + + blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS); + blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS); + + /* + * all done + */ + if (!elevator_init(q, NULL)) { + blk_queue_congestion_threshold(q); + return q; + } + + blk_cleanup_queue(q); +out_init: + kmem_cache_free(requestq_cachep, q); + return NULL; +} +EXPORT_SYMBOL(blk_init_queue_node); + +int blk_get_queue(request_queue_t *q) +{ + if (likely(!test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) { + atomic_inc(&q->refcnt); + return 0; + } + + return 1; +} + +EXPORT_SYMBOL(blk_get_queue); + +static inline void blk_free_request(request_queue_t *q, struct request *rq) +{ + if (rq->flags & REQ_ELVPRIV) + elv_put_request(q, rq); + mempool_free(rq, q->rq.rq_pool); +} + +static inline struct request * +blk_alloc_request(request_queue_t *q, int rw, struct bio *bio, + int priv, gfp_t gfp_mask) +{ + struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask); + + if (!rq) + return NULL; + + /* + * first three bits are identical in rq->flags and bio->bi_rw, + * see bio.h and blkdev.h + */ + rq->flags = rw; + + if (priv) { + if (unlikely(elv_set_request(q, rq, bio, gfp_mask))) { + mempool_free(rq, q->rq.rq_pool); + return NULL; + } + rq->flags |= REQ_ELVPRIV; + } + + return rq; +} + +/* + * ioc_batching returns true if the ioc is a valid batching request and + * should be given priority access to a request. + */ +static inline int ioc_batching(request_queue_t *q, struct io_context *ioc) +{ + if (!ioc) + return 0; + + /* + * Make sure the process is able to allocate at least 1 request + * even if the batch times out, otherwise we could theoretically + * lose wakeups. + */ + return ioc->nr_batch_requests == q->nr_batching || + (ioc->nr_batch_requests > 0 + && time_before(jiffies, ioc->last_waited + BLK_BATCH_TIME)); +} + +/* + * ioc_set_batching sets ioc to be a new "batcher" if it is not one. This + * will cause the process to be a "batcher" on all queues in the system. This + * is the behaviour we want though - once it gets a wakeup it should be given + * a nice run. + */ +static void ioc_set_batching(request_queue_t *q, struct io_context *ioc) +{ + if (!ioc || ioc_batching(q, ioc)) + return; + + ioc->nr_batch_requests = q->nr_batching; + ioc->last_waited = jiffies; +} + +static void __freed_request(request_queue_t *q, int rw) +{ + struct request_list *rl = &q->rq; + + if (rl->count[rw] < queue_congestion_off_threshold(q)) + clear_queue_congested(q, rw); + + if (rl->count[rw] + 1 <= q->nr_requests) { + if (waitqueue_active(&rl->wait[rw])) + wake_up(&rl->wait[rw]); + + blk_clear_queue_full(q, rw); + } +} + +/* + * A request has just been released. Account for it, update the full and + * congestion status, wake up any waiters. Called under q->queue_lock. + */ +static void freed_request(request_queue_t *q, int rw, int priv) +{ + struct request_list *rl = &q->rq; + + rl->count[rw]--; + if (priv) + rl->elvpriv--; + + __freed_request(q, rw); + + if (unlikely(rl->starved[rw ^ 1])) + __freed_request(q, rw ^ 1); +} + +#define blkdev_free_rq(list) list_entry((list)->next, struct request, queuelist) +/* + * Get a free request, queue_lock must be held. + * Returns NULL on failure, with queue_lock held. + * Returns !NULL on success, with queue_lock *not held*. + */ +static struct request *get_request(request_queue_t *q, int rw, struct bio *bio, + gfp_t gfp_mask) +{ + struct request *rq = NULL; + struct request_list *rl = &q->rq; + struct io_context *ioc = current_io_context(GFP_ATOMIC); + int priv; + + if (rl->count[rw]+1 >= q->nr_requests) { + /* + * The queue will fill after this allocation, so set it as + * full, and mark this process as "batching". This process + * will be allowed to complete a batch of requests, others + * will be blocked. + */ + if (!blk_queue_full(q, rw)) { + ioc_set_batching(q, ioc); + blk_set_queue_full(q, rw); + } + } + + switch (elv_may_queue(q, rw, bio)) { + case ELV_MQUEUE_NO: + goto rq_starved; + case ELV_MQUEUE_MAY: + break; + case ELV_MQUEUE_MUST: + goto get_rq; + } + + if (blk_queue_full(q, rw) && !ioc_batching(q, ioc)) { + /* + * The queue is full and the allocating process is not a + * "batcher", and not exempted by the IO scheduler + */ + goto out; + } + +get_rq: + /* + * Only allow batching queuers to allocate up to 50% over the defined + * limit of requests, otherwise we could have thousands of requests + * allocated with any setting of ->nr_requests + */ + if (rl->count[rw] >= (3 * q->nr_requests / 2)) + goto out; + + rl->count[rw]++; + rl->starved[rw] = 0; + if (rl->count[rw] >= queue_congestion_on_threshold(q)) + set_queue_congested(q, rw); + + priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); + if (priv) + rl->elvpriv++; + + spin_unlock_irq(q->queue_lock); + + rq = blk_alloc_request(q, rw, bio, priv, gfp_mask); + if (!rq) { + /* + * Allocation failed presumably due to memory. Undo anything + * we might have messed up. + * + * Allocating task should really be put onto the front of the + * wait queue, but this is pretty rare. + */ + spin_lock_irq(q->queue_lock); + freed_request(q, rw, priv); + + /* + * in the very unlikely event that allocation failed and no + * requests for this direction was pending, mark us starved + * so that freeing of a request in the other direction will + * notice us. another possible fix would be to split the + * rq mempool into READ and WRITE + */ +rq_starved: + if (unlikely(rl->count[rw] == 0)) + rl->starved[rw] = 1; + + goto out; + } + + if (ioc_batching(q, ioc)) + ioc->nr_batch_requests--; + + rq_init(q, rq); + rq->rl = rl; +out: + return rq; +} + +/* + * No available requests for this queue, unplug the device and wait for some + * requests to become available. + * + * Called with q->queue_lock held, and returns with it unlocked. + */ +static struct request *get_request_wait(request_queue_t *q, int rw, + struct bio *bio) +{ + struct request *rq; + + rq = get_request(q, rw, bio, GFP_NOIO); + while (!rq) { + DEFINE_WAIT(wait); + struct request_list *rl = &q->rq; + + prepare_to_wait_exclusive(&rl->wait[rw], &wait, + TASK_UNINTERRUPTIBLE); + + rq = get_request(q, rw, bio, GFP_NOIO); + + if (!rq) { + struct io_context *ioc; + + __generic_unplug_device(q); + spin_unlock_irq(q->queue_lock); + io_schedule(); + + /* + * After sleeping, we become a "batching" process and + * will be able to allocate at least one request, and + * up to a big batch of them for a small period time. + * See ioc_batching, ioc_set_batching + */ + ioc = current_io_context(GFP_NOIO); + ioc_set_batching(q, ioc); + + spin_lock_irq(q->queue_lock); + } + finish_wait(&rl->wait[rw], &wait); + } + + return rq; +} + +struct request *blk_get_request(request_queue_t *q, int rw, gfp_t gfp_mask) +{ + struct request *rq; + + BUG_ON(rw != READ && rw != WRITE); + + spin_lock_irq(q->queue_lock); + if (gfp_mask & __GFP_WAIT) { + rq = get_request_wait(q, rw, NULL); + } else { + rq = get_request(q, rw, NULL, gfp_mask); + if (!rq) + spin_unlock_irq(q->queue_lock); + } + /* q->queue_lock is unlocked at this point */ + + return rq; +} +EXPORT_SYMBOL(blk_get_request); + +/** + * blk_requeue_request - put a request back on queue + * @q: request queue where request should be inserted + * @rq: request to be inserted + * + * Description: + * Drivers often keep queueing requests until the hardware cannot accept + * more, when that condition happens we need to put the request back + * on the queue. Must be called with queue lock held. + */ +void blk_requeue_request(request_queue_t *q, struct request *rq) +{ + if (blk_rq_tagged(rq)) + blk_queue_end_tag(q, rq); + + elv_requeue_request(q, rq); +} + +EXPORT_SYMBOL(blk_requeue_request); + +/** + * blk_insert_request - insert a special request in to a request queue + * @q: request queue where request should be inserted + * @rq: request to be inserted + * @at_head: insert request at head or tail of queue + * @data: private data + * + * Description: + * Many block devices need to execute commands asynchronously, so they don't + * block the whole kernel from preemption during request execution. This is + * accomplished normally by inserting aritficial requests tagged as + * REQ_SPECIAL in to the corresponding request queue, and letting them be + * scheduled for actual execution by the request queue. + * + * We have the option of inserting the head or the tail of the queue. + * Typically we use the tail for new ioctls and so forth. We use the head + * of the queue for things like a QUEUE_FULL message from a device, or a + * host that is unable to accept a particular command. + */ +void blk_insert_request(request_queue_t *q, struct request *rq, + int at_head, void *data) +{ + int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK; + unsigned long flags; + + /* + * tell I/O scheduler that this isn't a regular read/write (ie it + * must not attempt merges on this) and that it acts as a soft + * barrier + */ + rq->flags |= REQ_SPECIAL | REQ_SOFTBARRIER; + + rq->special = data; + + spin_lock_irqsave(q->queue_lock, flags); + + /* + * If command is tagged, release the tag + */ + if (blk_rq_tagged(rq)) + blk_queue_end_tag(q, rq); + + drive_stat_acct(rq, rq->nr_sectors, 1); + __elv_add_request(q, rq, where, 0); + + if (blk_queue_plugged(q)) + __generic_unplug_device(q); + else + q->request_fn(q); + spin_unlock_irqrestore(q->queue_lock, flags); +} + +EXPORT_SYMBOL(blk_insert_request); + +/** + * blk_rq_map_user - map user data to a request, for REQ_BLOCK_PC usage + * @q: request queue where request should be inserted + * @rq: request structure to fill + * @ubuf: the user buffer + * @len: length of user data + * + * Description: + * Data will be mapped directly for zero copy io, if possible. Otherwise + * a kernel bounce buffer is used. + * + * A matching blk_rq_unmap_user() must be issued at the end of io, while + * still in process context. + * + * Note: The mapped bio may need to be bounced through blk_queue_bounce() + * before being submitted to the device, as pages mapped may be out of + * reach. It's the callers responsibility to make sure this happens. The + * original bio must be passed back in to blk_rq_unmap_user() for proper + * unmapping. + */ +int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf, + unsigned int len) +{ + unsigned long uaddr; + struct bio *bio; + int reading; + + if (len > (q->max_sectors << 9)) + return -EINVAL; + if (!len || !ubuf) + return -EINVAL; + + reading = rq_data_dir(rq) == READ; + + /* + * if alignment requirement is satisfied, map in user pages for + * direct dma. else, set up kernel bounce buffers + */ + uaddr = (unsigned long) ubuf; + if (!(uaddr & queue_dma_alignment(q)) && !(len & queue_dma_alignment(q))) + bio = bio_map_user(q, NULL, uaddr, len, reading); + else + bio = bio_copy_user(q, uaddr, len, reading); + + if (!IS_ERR(bio)) { + rq->bio = rq->biotail = bio; + blk_rq_bio_prep(q, rq, bio); + + rq->buffer = rq->data = NULL; + rq->data_len = len; + return 0; + } + + /* + * bio is the err-ptr + */ + return PTR_ERR(bio); +} + +EXPORT_SYMBOL(blk_rq_map_user); + +/** + * blk_rq_map_user_iov - map user data to a request, for REQ_BLOCK_PC usage + * @q: request queue where request should be inserted + * @rq: request to map data to + * @iov: pointer to the iovec + * @iov_count: number of elements in the iovec + * + * Description: + * Data will be mapped directly for zero copy io, if possible. Otherwise + * a kernel bounce buffer is used. + * + * A matching blk_rq_unmap_user() must be issued at the end of io, while + * still in process context. + * + * Note: The mapped bio may need to be bounced through blk_queue_bounce() + * before being submitted to the device, as pages mapped may be out of + * reach. It's the callers responsibility to make sure this happens. The + * original bio must be passed back in to blk_rq_unmap_user() for proper + * unmapping. + */ +int blk_rq_map_user_iov(request_queue_t *q, struct request *rq, + struct sg_iovec *iov, int iov_count) +{ + struct bio *bio; + + if (!iov || iov_count <= 0) + return -EINVAL; + + /* we don't allow misaligned data like bio_map_user() does. If the + * user is using sg, they're expected to know the alignment constraints + * and respect them accordingly */ + bio = bio_map_user_iov(q, NULL, iov, iov_count, rq_data_dir(rq)== READ); + if (IS_ERR(bio)) + return PTR_ERR(bio); + + rq->bio = rq->biotail = bio; + blk_rq_bio_prep(q, rq, bio); + rq->buffer = rq->data = NULL; + rq->data_len = bio->bi_size; + return 0; +} + +EXPORT_SYMBOL(blk_rq_map_user_iov); + +/** + * blk_rq_unmap_user - unmap a request with user data + * @bio: bio to be unmapped + * @ulen: length of user buffer + * + * Description: + * Unmap a bio previously mapped by blk_rq_map_user(). + */ +int blk_rq_unmap_user(struct bio *bio, unsigned int ulen) +{ + int ret = 0; + + if (bio) { + if (bio_flagged(bio, BIO_USER_MAPPED)) + bio_unmap_user(bio); + else + ret = bio_uncopy_user(bio); + } + + return 0; +} + +EXPORT_SYMBOL(blk_rq_unmap_user); + +/** + * blk_rq_map_kern - map kernel data to a request, for REQ_BLOCK_PC usage + * @q: request queue where request should be inserted + * @rq: request to fill + * @kbuf: the kernel buffer + * @len: length of user data + * @gfp_mask: memory allocation flags + */ +int blk_rq_map_kern(request_queue_t *q, struct request *rq, void *kbuf, + unsigned int len, gfp_t gfp_mask) +{ + struct bio *bio; + + if (len > (q->max_sectors << 9)) + return -EINVAL; + if (!len || !kbuf) + return -EINVAL; + + bio = bio_map_kern(q, kbuf, len, gfp_mask); + if (IS_ERR(bio)) + return PTR_ERR(bio); + + if (rq_data_dir(rq) == WRITE) + bio->bi_rw |= (1 << BIO_RW); + + rq->bio = rq->biotail = bio; + blk_rq_bio_prep(q, rq, bio); + + rq->buffer = rq->data = NULL; + rq->data_len = len; + return 0; +} + +EXPORT_SYMBOL(blk_rq_map_kern); + +/** + * blk_execute_rq_nowait - insert a request into queue for execution + * @q: queue to insert the request in + * @bd_disk: matching gendisk + * @rq: request to insert + * @at_head: insert request at head or tail of queue + * @done: I/O completion handler + * + * Description: + * Insert a fully prepared request at the back of the io scheduler queue + * for execution. Don't wait for completion. + */ +void blk_execute_rq_nowait(request_queue_t *q, struct gendisk *bd_disk, + struct request *rq, int at_head, + void (*done)(struct request *)) +{ + int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK; + + rq->rq_disk = bd_disk; + rq->flags |= REQ_NOMERGE; + rq->end_io = done; + elv_add_request(q, rq, where, 1); + generic_unplug_device(q); +} + +/** + * blk_execute_rq - insert a request into queue for execution + * @q: queue to insert the request in + * @bd_disk: matching gendisk + * @rq: request to insert + * @at_head: insert request at head or tail of queue + * + * Description: + * Insert a fully prepared request at the back of the io scheduler queue + * for execution and wait for completion. + */ +int blk_execute_rq(request_queue_t *q, struct gendisk *bd_disk, + struct request *rq, int at_head) +{ + DECLARE_COMPLETION(wait); + char sense[SCSI_SENSE_BUFFERSIZE]; + int err = 0; + + /* + * we need an extra reference to the request, so we can look at + * it after io completion + */ + rq->ref_count++; + + if (!rq->sense) { + memset(sense, 0, sizeof(sense)); + rq->sense = sense; + rq->sense_len = 0; + } + + rq->waiting = &wait; + blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq); + wait_for_completion(&wait); + rq->waiting = NULL; + + if (rq->errors) + err = -EIO; + + return err; +} + +EXPORT_SYMBOL(blk_execute_rq); + +/** + * blkdev_issue_flush - queue a flush + * @bdev: blockdev to issue flush for + * @error_sector: error sector + * + * Description: + * Issue a flush for the block device in question. Caller can supply + * room for storing the error offset in case of a flush error, if they + * wish to. Caller must run wait_for_completion() on its own. + */ +int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector) +{ + request_queue_t *q; + + if (bdev->bd_disk == NULL) + return -ENXIO; + + q = bdev_get_queue(bdev); + if (!q) + return -ENXIO; + if (!q->issue_flush_fn) + return -EOPNOTSUPP; + + return q->issue_flush_fn(q, bdev->bd_disk, error_sector); +} + +EXPORT_SYMBOL(blkdev_issue_flush); + +static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io) +{ + int rw = rq_data_dir(rq); + + if (!blk_fs_request(rq) || !rq->rq_disk) + return; + + if (!new_io) { + __disk_stat_inc(rq->rq_disk, merges[rw]); + } else { + disk_round_stats(rq->rq_disk); + rq->rq_disk->in_flight++; + } +} + +/* + * add-request adds a request to the linked list. + * queue lock is held and interrupts disabled, as we muck with the + * request queue list. + */ +static inline void add_request(request_queue_t * q, struct request * req) +{ + drive_stat_acct(req, req->nr_sectors, 1); + + if (q->activity_fn) + q->activity_fn(q->activity_data, rq_data_dir(req)); + + /* + * elevator indicated where it wants this request to be + * inserted at elevator_merge time + */ + __elv_add_request(q, req, ELEVATOR_INSERT_SORT, 0); +} + +/* + * disk_round_stats() - Round off the performance stats on a struct + * disk_stats. + * + * The average IO queue length and utilisation statistics are maintained + * by observing the current state of the queue length and the amount of + * time it has been in this state for. + * + * Normally, that accounting is done on IO completion, but that can result + * in more than a second's worth of IO being accounted for within any one + * second, leading to >100% utilisation. To deal with that, we call this + * function to do a round-off before returning the results when reading + * /proc/diskstats. This accounts immediately for all queue usage up to + * the current jiffies and restarts the counters again. + */ +void disk_round_stats(struct gendisk *disk) +{ + unsigned long now = jiffies; + + if (now == disk->stamp) + return; + + if (disk->in_flight) { + __disk_stat_add(disk, time_in_queue, + disk->in_flight * (now - disk->stamp)); + __disk_stat_add(disk, io_ticks, (now - disk->stamp)); + } + disk->stamp = now; +} + +/* + * queue lock must be held + */ +static void __blk_put_request(request_queue_t *q, struct request *req) +{ + struct request_list *rl = req->rl; + + if (unlikely(!q)) + return; + if (unlikely(--req->ref_count)) + return; + + elv_completed_request(q, req); + + req->rq_status = RQ_INACTIVE; + req->rl = NULL; + + /* + * Request may not have originated from ll_rw_blk. if not, + * it didn't come out of our reserved rq pools + */ + if (rl) { + int rw = rq_data_dir(req); + int priv = req->flags & REQ_ELVPRIV; + + BUG_ON(!list_empty(&req->queuelist)); + + blk_free_request(q, req); + freed_request(q, rw, priv); + } +} + +void blk_put_request(struct request *req) +{ + unsigned long flags; + request_queue_t *q = req->q; + + /* + * Gee, IDE calls in w/ NULL q. Fix IDE and remove the + * following if (q) test. + */ + if (q) { + spin_lock_irqsave(q->queue_lock, flags); + __blk_put_request(q, req); + spin_unlock_irqrestore(q->queue_lock, flags); + } +} + +EXPORT_SYMBOL(blk_put_request); + +/** + * blk_end_sync_rq - executes a completion event on a request + * @rq: request to complete + */ +void blk_end_sync_rq(struct request *rq) +{ + struct completion *waiting = rq->waiting; + + rq->waiting = NULL; + __blk_put_request(rq->q, rq); + + /* + * complete last, if this is a stack request the process (and thus + * the rq pointer) could be invalid right after this complete() + */ + complete(waiting); +} +EXPORT_SYMBOL(blk_end_sync_rq); + +/** + * blk_congestion_wait - wait for a queue to become uncongested + * @rw: READ or WRITE + * @timeout: timeout in jiffies + * + * Waits for up to @timeout jiffies for a queue (any queue) to exit congestion. + * If no queues are congested then just wait for the next request to be + * returned. + */ +long blk_congestion_wait(int rw, long timeout) +{ + long ret; + DEFINE_WAIT(wait); + wait_queue_head_t *wqh = &congestion_wqh[rw]; + + prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE); + ret = io_schedule_timeout(timeout); + finish_wait(wqh, &wait); + return ret; +} + +EXPORT_SYMBOL(blk_congestion_wait); + +/* + * Has to be called with the request spinlock acquired + */ +static int attempt_merge(request_queue_t *q, struct request *req, + struct request *next) +{ + if (!rq_mergeable(req) || !rq_mergeable(next)) + return 0; + + /* + * not contigious + */ + if (req->sector + req->nr_sectors != next->sector) + return 0; + + if (rq_data_dir(req) != rq_data_dir(next) + || req->rq_disk != next->rq_disk + || next->waiting || next->special) + return 0; + + /* + * If we are allowed to merge, then append bio list + * from next to rq and release next. merge_requests_fn + * will have updated segment counts, update sector + * counts here. + */ + if (!q->merge_requests_fn(q, req, next)) + return 0; + + /* + * At this point we have either done a back merge + * or front merge. We need the smaller start_time of + * the merged requests to be the current request + * for accounting purposes. + */ + if (time_after(req->start_time, next->start_time)) + req->start_time = next->start_time; + + req->biotail->bi_next = next->bio; + req->biotail = next->biotail; + + req->nr_sectors = req->hard_nr_sectors += next->hard_nr_sectors; + + elv_merge_requests(q, req, next); + + if (req->rq_disk) { + disk_round_stats(req->rq_disk); + req->rq_disk->in_flight--; + } + + req->ioprio = ioprio_best(req->ioprio, next->ioprio); + + __blk_put_request(q, next); + return 1; +} + +static inline int attempt_back_merge(request_queue_t *q, struct request *rq) +{ + struct request *next = elv_latter_request(q, rq); + + if (next) + return attempt_merge(q, rq, next); + + return 0; +} + +static inline int attempt_front_merge(request_queue_t *q, struct request *rq) +{ + struct request *prev = elv_former_request(q, rq); + + if (prev) + return attempt_merge(q, prev, rq); + + return 0; +} + +/** + * blk_attempt_remerge - attempt to remerge active head with next request + * @q: The &request_queue_t belonging to the device + * @rq: The head request (usually) + * + * Description: + * For head-active devices, the queue can easily be unplugged so quickly + * that proper merging is not done on the front request. This may hurt + * performance greatly for some devices. The block layer cannot safely + * do merging on that first request for these queues, but the driver can + * call this function and make it happen any way. Only the driver knows + * when it is safe to do so. + **/ +void blk_attempt_remerge(request_queue_t *q, struct request *rq) +{ + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); + attempt_back_merge(q, rq); + spin_unlock_irqrestore(q->queue_lock, flags); +} + +EXPORT_SYMBOL(blk_attempt_remerge); + +static int __make_request(request_queue_t *q, struct bio *bio) +{ + struct request *req; + int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, err, sync; + unsigned short prio; + sector_t sector; + + sector = bio->bi_sector; + nr_sectors = bio_sectors(bio); + cur_nr_sectors = bio_cur_sectors(bio); + prio = bio_prio(bio); + + rw = bio_data_dir(bio); + sync = bio_sync(bio); + + /* + * low level driver can indicate that it wants pages above a + * certain limit bounced to low memory (ie for highmem, or even + * ISA dma in theory) + */ + blk_queue_bounce(q, &bio); + + spin_lock_prefetch(q->queue_lock); + + barrier = bio_barrier(bio); + if (unlikely(barrier) && (q->ordered == QUEUE_ORDERED_NONE)) { + err = -EOPNOTSUPP; + goto end_io; + } + + spin_lock_irq(q->queue_lock); + + if (unlikely(barrier) || elv_queue_empty(q)) + goto get_rq; + + el_ret = elv_merge(q, &req, bio); + switch (el_ret) { + case ELEVATOR_BACK_MERGE: + BUG_ON(!rq_mergeable(req)); + + if (!q->back_merge_fn(q, req, bio)) + break; + + req->biotail->bi_next = bio; + req->biotail = bio; + req->nr_sectors = req->hard_nr_sectors += nr_sectors; + req->ioprio = ioprio_best(req->ioprio, prio); + drive_stat_acct(req, nr_sectors, 0); + if (!attempt_back_merge(q, req)) + elv_merged_request(q, req); + goto out; + + case ELEVATOR_FRONT_MERGE: + BUG_ON(!rq_mergeable(req)); + + if (!q->front_merge_fn(q, req, bio)) + break; + + bio->bi_next = req->bio; + req->bio = bio; + + /* + * may not be valid. if the low level driver said + * it didn't need a bounce buffer then it better + * not touch req->buffer either... + */ + req->buffer = bio_data(bio); + req->current_nr_sectors = cur_nr_sectors; + req->hard_cur_sectors = cur_nr_sectors; + req->sector = req->hard_sector = sector; + req->nr_sectors = req->hard_nr_sectors += nr_sectors; + req->ioprio = ioprio_best(req->ioprio, prio); + drive_stat_acct(req, nr_sectors, 0); + if (!attempt_front_merge(q, req)) + elv_merged_request(q, req); + goto out; + + /* ELV_NO_MERGE: elevator says don't/can't merge. */ + default: + ; + } + +get_rq: + /* + * Grab a free request. This is might sleep but can not fail. + * Returns with the queue unlocked. + */ + req = get_request_wait(q, rw, bio); + + /* + * After dropping the lock and possibly sleeping here, our request + * may now be mergeable after it had proven unmergeable (above). + * We don't worry about that case for efficiency. It won't happen + * often, and the elevators are able to handle it. + */ + + req->flags |= REQ_CMD; + + /* + * inherit FAILFAST from bio (for read-ahead, and explicit FAILFAST) + */ + if (bio_rw_ahead(bio) || bio_failfast(bio)) + req->flags |= REQ_FAILFAST; + + /* + * REQ_BARRIER implies no merging, but lets make it explicit + */ + if (unlikely(barrier)) + req->flags |= (REQ_HARDBARRIER | REQ_NOMERGE); + + req->errors = 0; + req->hard_sector = req->sector = sector; + req->hard_nr_sectors = req->nr_sectors = nr_sectors; + req->current_nr_sectors = req->hard_cur_sectors = cur_nr_sectors; + req->nr_phys_segments = bio_phys_segments(q, bio); + req->nr_hw_segments = bio_hw_segments(q, bio); + req->buffer = bio_data(bio); /* see ->buffer comment above */ + req->waiting = NULL; + req->bio = req->biotail = bio; + req->ioprio = prio; + req->rq_disk = bio->bi_bdev->bd_disk; + req->start_time = jiffies; + + spin_lock_irq(q->queue_lock); + if (elv_queue_empty(q)) + blk_plug_device(q); + add_request(q, req); +out: + if (sync) + __generic_unplug_device(q); + + spin_unlock_irq(q->queue_lock); + return 0; + +end_io: + bio_endio(bio, nr_sectors << 9, err); + return 0; +} + +/* + * If bio->bi_dev is a partition, remap the location + */ +static inline void blk_partition_remap(struct bio *bio) +{ + struct block_device *bdev = bio->bi_bdev; + + if (bdev != bdev->bd_contains) { + struct hd_struct *p = bdev->bd_part; + const int rw = bio_data_dir(bio); + + p->sectors[rw] += bio_sectors(bio); + p->ios[rw]++; + + bio->bi_sector += p->start_sect; + bio->bi_bdev = bdev->bd_contains; + } +} + +static void handle_bad_sector(struct bio *bio) +{ + char b[BDEVNAME_SIZE]; + + printk(KERN_INFO "attempt to access beyond end of device\n"); + printk(KERN_INFO "%s: rw=%ld, want=%Lu, limit=%Lu\n", + bdevname(bio->bi_bdev, b), + bio->bi_rw, + (unsigned long long)bio->bi_sector + bio_sectors(bio), + (long long)(bio->bi_bdev->bd_inode->i_size >> 9)); + + set_bit(BIO_EOF, &bio->bi_flags); +} + +/** + * generic_make_request: hand a buffer to its device driver for I/O + * @bio: The bio describing the location in memory and on the device. + * + * generic_make_request() is used to make I/O requests of block + * devices. It is passed a &struct bio, which describes the I/O that needs + * to be done. + * + * generic_make_request() does not return any status. The + * success/failure status of the request, along with notification of + * completion, is delivered asynchronously through the bio->bi_end_io + * function described (one day) else where. + * + * The caller of generic_make_request must make sure that bi_io_vec + * are set to describe the memory buffer, and that bi_dev and bi_sector are + * set to describe the device address, and the + * bi_end_io and optionally bi_private are set to describe how + * completion notification should be signaled. + * + * generic_make_request and the drivers it calls may use bi_next if this + * bio happens to be merged with someone else, and may change bi_dev and + * bi_sector for remaps as it sees fit. So the values of these fields + * should NOT be depended on after the call to generic_make_request. + */ +void generic_make_request(struct bio *bio) +{ + request_queue_t *q; + sector_t maxsector; + int ret, nr_sectors = bio_sectors(bio); + + might_sleep(); + /* Test device or partition size, when known. */ + maxsector = bio->bi_bdev->bd_inode->i_size >> 9; + if (maxsector) { + sector_t sector = bio->bi_sector; + + if (maxsector < nr_sectors || maxsector - nr_sectors < sector) { + /* + * This may well happen - the kernel calls bread() + * without checking the size of the device, e.g., when + * mounting a device. + */ + handle_bad_sector(bio); + goto end_io; + } + } + + /* + * Resolve the mapping until finished. (drivers are + * still free to implement/resolve their own stacking + * by explicitly returning 0) + * + * NOTE: we don't repeat the blk_size check for each new device. + * Stacking drivers are expected to know what they are doing. + */ + do { + char b[BDEVNAME_SIZE]; + + q = bdev_get_queue(bio->bi_bdev); + if (!q) { + printk(KERN_ERR + "generic_make_request: Trying to access " + "nonexistent block-device %s (%Lu)\n", + bdevname(bio->bi_bdev, b), + (long long) bio->bi_sector); +end_io: + bio_endio(bio, bio->bi_size, -EIO); + break; + } + + if (unlikely(bio_sectors(bio) > q->max_hw_sectors)) { + printk("bio too big device %s (%u > %u)\n", + bdevname(bio->bi_bdev, b), + bio_sectors(bio), + q->max_hw_sectors); + goto end_io; + } + + if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) + goto end_io; + + /* + * If this device has partitions, remap block n + * of partition p to block n+start(p) of the disk. + */ + blk_partition_remap(bio); + + ret = q->make_request_fn(q, bio); + } while (ret); +} + +EXPORT_SYMBOL(generic_make_request); + +/** + * submit_bio: submit a bio to the block device layer for I/O + * @rw: whether to %READ or %WRITE, or maybe to %READA (read ahead) + * @bio: The &struct bio which describes the I/O + * + * submit_bio() is very similar in purpose to generic_make_request(), and + * uses that function to do most of the work. Both are fairly rough + * interfaces, @bio must be presetup and ready for I/O. + * + */ +void submit_bio(int rw, struct bio *bio) +{ + int count = bio_sectors(bio); + + BIO_BUG_ON(!bio->bi_size); + BIO_BUG_ON(!bio->bi_io_vec); + bio->bi_rw |= rw; + if (rw & WRITE) + mod_page_state(pgpgout, count); + else + mod_page_state(pgpgin, count); + + if (unlikely(block_dump)) { + char b[BDEVNAME_SIZE]; + printk(KERN_DEBUG "%s(%d): %s block %Lu on %s\n", + current->comm, current->pid, + (rw & WRITE) ? "WRITE" : "READ", + (unsigned long long)bio->bi_sector, + bdevname(bio->bi_bdev,b)); + } + + generic_make_request(bio); +} + +EXPORT_SYMBOL(submit_bio); + +static void blk_recalc_rq_segments(struct request *rq) +{ + struct bio *bio, *prevbio = NULL; + int nr_phys_segs, nr_hw_segs; + unsigned int phys_size, hw_size; + request_queue_t *q = rq->q; + + if (!rq->bio) + return; + + phys_size = hw_size = nr_phys_segs = nr_hw_segs = 0; + rq_for_each_bio(bio, rq) { + /* Force bio hw/phys segs to be recalculated. */ + bio->bi_flags &= ~(1 << BIO_SEG_VALID); + + nr_phys_segs += bio_phys_segments(q, bio); + nr_hw_segs += bio_hw_segments(q, bio); + if (prevbio) { + int pseg = phys_size + prevbio->bi_size + bio->bi_size; + int hseg = hw_size + prevbio->bi_size + bio->bi_size; + + if (blk_phys_contig_segment(q, prevbio, bio) && + pseg <= q->max_segment_size) { + nr_phys_segs--; + phys_size += prevbio->bi_size + bio->bi_size; + } else + phys_size = 0; + + if (blk_hw_contig_segment(q, prevbio, bio) && + hseg <= q->max_segment_size) { + nr_hw_segs--; + hw_size += prevbio->bi_size + bio->bi_size; + } else + hw_size = 0; + } + prevbio = bio; + } + + rq->nr_phys_segments = nr_phys_segs; + rq->nr_hw_segments = nr_hw_segs; +} + +static void blk_recalc_rq_sectors(struct request *rq, int nsect) +{ + if (blk_fs_request(rq)) { + rq->hard_sector += nsect; + rq->hard_nr_sectors -= nsect; + + /* + * Move the I/O submission pointers ahead if required. + */ + if ((rq->nr_sectors >= rq->hard_nr_sectors) && + (rq->sector <= rq->hard_sector)) { + rq->sector = rq->hard_sector; + rq->nr_sectors = rq->hard_nr_sectors; + rq->hard_cur_sectors = bio_cur_sectors(rq->bio); + rq->current_nr_sectors = rq->hard_cur_sectors; + rq->buffer = bio_data(rq->bio); + } + + /* + * if total number of sectors is less than the first segment + * size, something has gone terribly wrong + */ + if (rq->nr_sectors < rq->current_nr_sectors) { + printk("blk: request botched\n"); + rq->nr_sectors = rq->current_nr_sectors; + } + } +} + +static int __end_that_request_first(struct request *req, int uptodate, + int nr_bytes) +{ + int total_bytes, bio_nbytes, error, next_idx = 0; + struct bio *bio; + + /* + * extend uptodate bool to allow < 0 value to be direct io error + */ + error = 0; + if (end_io_error(uptodate)) + error = !uptodate ? -EIO : uptodate; + + /* + * for a REQ_BLOCK_PC request, we want to carry any eventual + * sense key with us all the way through + */ + if (!blk_pc_request(req)) + req->errors = 0; + + if (!uptodate) { + if (blk_fs_request(req) && !(req->flags & REQ_QUIET)) + printk("end_request: I/O error, dev %s, sector %llu\n", + req->rq_disk ? req->rq_disk->disk_name : "?", + (unsigned long long)req->sector); + } + + if (blk_fs_request(req) && req->rq_disk) { + const int rw = rq_data_dir(req); + + __disk_stat_add(req->rq_disk, sectors[rw], nr_bytes >> 9); + } + + total_bytes = bio_nbytes = 0; + while ((bio = req->bio) != NULL) { + int nbytes; + + if (nr_bytes >= bio->bi_size) { + req->bio = bio->bi_next; + nbytes = bio->bi_size; + bio_endio(bio, nbytes, error); + next_idx = 0; + bio_nbytes = 0; + } else { + int idx = bio->bi_idx + next_idx; + + if (unlikely(bio->bi_idx >= bio->bi_vcnt)) { + blk_dump_rq_flags(req, "__end_that"); + printk("%s: bio idx %d >= vcnt %d\n", + __FUNCTION__, + bio->bi_idx, bio->bi_vcnt); + break; + } + + nbytes = bio_iovec_idx(bio, idx)->bv_len; + BIO_BUG_ON(nbytes > bio->bi_size); + + /* + * not a complete bvec done + */ + if (unlikely(nbytes > nr_bytes)) { + bio_nbytes += nr_bytes; + total_bytes += nr_bytes; + break; + } + + /* + * advance to the next vector + */ + next_idx++; + bio_nbytes += nbytes; + } + + total_bytes += nbytes; + nr_bytes -= nbytes; + + if ((bio = req->bio)) { + /* + * end more in this run, or just return 'not-done' + */ + if (unlikely(nr_bytes <= 0)) + break; + } + } + + /* + * completely done + */ + if (!req->bio) + return 0; + + /* + * if the request wasn't completed, update state + */ + if (bio_nbytes) { + bio_endio(bio, bio_nbytes, error); + bio->bi_idx += next_idx; + bio_iovec(bio)->bv_offset += nr_bytes; + bio_iovec(bio)->bv_len -= nr_bytes; + } + + blk_recalc_rq_sectors(req, total_bytes >> 9); + blk_recalc_rq_segments(req); + return 1; +} + +/** + * end_that_request_first - end I/O on a request + * @req: the request being processed + * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error + * @nr_sectors: number of sectors to end I/O on + * + * Description: + * Ends I/O on a number of sectors attached to @req, and sets it up + * for the next range of segments (if any) in the cluster. + * + * Return: + * 0 - we are done with this request, call end_that_request_last() + * 1 - still buffers pending for this request + **/ +int end_that_request_first(struct request *req, int uptodate, int nr_sectors) +{ + return __end_that_request_first(req, uptodate, nr_sectors << 9); +} + +EXPORT_SYMBOL(end_that_request_first); + +/** + * end_that_request_chunk - end I/O on a request + * @req: the request being processed + * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error + * @nr_bytes: number of bytes to complete + * + * Description: + * Ends I/O on a number of bytes attached to @req, and sets it up + * for the next range of segments (if any). Like end_that_request_first(), + * but deals with bytes instead of sectors. + * + * Return: + * 0 - we are done with this request, call end_that_request_last() + * 1 - still buffers pending for this request + **/ +int end_that_request_chunk(struct request *req, int uptodate, int nr_bytes) +{ + return __end_that_request_first(req, uptodate, nr_bytes); +} + +EXPORT_SYMBOL(end_that_request_chunk); + +/* + * queue lock must be held + */ +void end_that_request_last(struct request *req) +{ + struct gendisk *disk = req->rq_disk; + + if (unlikely(laptop_mode) && blk_fs_request(req)) + laptop_io_completion(); + + if (disk && blk_fs_request(req)) { + unsigned long duration = jiffies - req->start_time; + const int rw = rq_data_dir(req); + + __disk_stat_inc(disk, ios[rw]); + __disk_stat_add(disk, ticks[rw], duration); + disk_round_stats(disk); + disk->in_flight--; + } + if (req->end_io) + req->end_io(req); + else + __blk_put_request(req->q, req); +} + +EXPORT_SYMBOL(end_that_request_last); + +void end_request(struct request *req, int uptodate) +{ + if (!end_that_request_first(req, uptodate, req->hard_cur_sectors)) { + add_disk_randomness(req->rq_disk); + blkdev_dequeue_request(req); + end_that_request_last(req); + } +} + +EXPORT_SYMBOL(end_request); + +void blk_rq_bio_prep(request_queue_t *q, struct request *rq, struct bio *bio) +{ + /* first three bits are identical in rq->flags and bio->bi_rw */ + rq->flags |= (bio->bi_rw & 7); + + rq->nr_phys_segments = bio_phys_segments(q, bio); + rq->nr_hw_segments = bio_hw_segments(q, bio); + rq->current_nr_sectors = bio_cur_sectors(bio); + rq->hard_cur_sectors = rq->current_nr_sectors; + rq->hard_nr_sectors = rq->nr_sectors = bio_sectors(bio); + rq->buffer = bio_data(bio); + + rq->bio = rq->biotail = bio; +} + +EXPORT_SYMBOL(blk_rq_bio_prep); + +int kblockd_schedule_work(struct work_struct *work) +{ + return queue_work(kblockd_workqueue, work); +} + +EXPORT_SYMBOL(kblockd_schedule_work); + +void kblockd_flush(void) +{ + flush_workqueue(kblockd_workqueue); +} +EXPORT_SYMBOL(kblockd_flush); + +int __init blk_dev_init(void) +{ + kblockd_workqueue = create_workqueue("kblockd"); + if (!kblockd_workqueue) + panic("Failed to create kblockd\n"); + + request_cachep = kmem_cache_create("blkdev_requests", + sizeof(struct request), 0, SLAB_PANIC, NULL, NULL); + + requestq_cachep = kmem_cache_create("blkdev_queue", + sizeof(request_queue_t), 0, SLAB_PANIC, NULL, NULL); + + iocontext_cachep = kmem_cache_create("blkdev_ioc", + sizeof(struct io_context), 0, SLAB_PANIC, NULL, NULL); + + blk_max_low_pfn = max_low_pfn; + blk_max_pfn = max_pfn; + + return 0; +} + +/* + * IO Context helper functions + */ +void put_io_context(struct io_context *ioc) +{ + if (ioc == NULL) + return; + + BUG_ON(atomic_read(&ioc->refcount) == 0); + + if (atomic_dec_and_test(&ioc->refcount)) { + if (ioc->aic && ioc->aic->dtor) + ioc->aic->dtor(ioc->aic); + if (ioc->cic && ioc->cic->dtor) + ioc->cic->dtor(ioc->cic); + + kmem_cache_free(iocontext_cachep, ioc); + } +} +EXPORT_SYMBOL(put_io_context); + +/* Called by the exitting task */ +void exit_io_context(void) +{ + unsigned long flags; + struct io_context *ioc; + + local_irq_save(flags); + task_lock(current); + ioc = current->io_context; + current->io_context = NULL; + ioc->task = NULL; + task_unlock(current); + local_irq_restore(flags); + + if (ioc->aic && ioc->aic->exit) + ioc->aic->exit(ioc->aic); + if (ioc->cic && ioc->cic->exit) + ioc->cic->exit(ioc->cic); + + put_io_context(ioc); +} + +/* + * If the current task has no IO context then create one and initialise it. + * Otherwise, return its existing IO context. + * + * This returned IO context doesn't have a specifically elevated refcount, + * but since the current task itself holds a reference, the context can be + * used in general code, so long as it stays within `current` context. + */ +struct io_context *current_io_context(gfp_t gfp_flags) +{ + struct task_struct *tsk = current; + struct io_context *ret; + + ret = tsk->io_context; + if (likely(ret)) + return ret; + + ret = kmem_cache_alloc(iocontext_cachep, gfp_flags); + if (ret) { + atomic_set(&ret->refcount, 1); + ret->task = current; + ret->set_ioprio = NULL; + ret->last_waited = jiffies; /* doesn't matter... */ + ret->nr_batch_requests = 0; /* because this is 0 */ + ret->aic = NULL; + ret->cic = NULL; + tsk->io_context = ret; + } + + return ret; +} +EXPORT_SYMBOL(current_io_context); + +/* + * If the current task has no IO context then create one and initialise it. + * If it does have a context, take a ref on it. + * + * This is always called in the context of the task which submitted the I/O. + */ +struct io_context *get_io_context(gfp_t gfp_flags) +{ + struct io_context *ret; + ret = current_io_context(gfp_flags); + if (likely(ret)) + atomic_inc(&ret->refcount); + return ret; +} +EXPORT_SYMBOL(get_io_context); + +void copy_io_context(struct io_context **pdst, struct io_context **psrc) +{ + struct io_context *src = *psrc; + struct io_context *dst = *pdst; + + if (src) { + BUG_ON(atomic_read(&src->refcount) == 0); + atomic_inc(&src->refcount); + put_io_context(dst); + *pdst = src; + } +} +EXPORT_SYMBOL(copy_io_context); + +void swap_io_context(struct io_context **ioc1, struct io_context **ioc2) +{ + struct io_context *temp; + temp = *ioc1; + *ioc1 = *ioc2; + *ioc2 = temp; +} +EXPORT_SYMBOL(swap_io_context); + +/* + * sysfs parts below + */ +struct queue_sysfs_entry { + struct attribute attr; + ssize_t (*show)(struct request_queue *, char *); + ssize_t (*store)(struct request_queue *, const char *, size_t); +}; + +static ssize_t +queue_var_show(unsigned int var, char *page) +{ + return sprintf(page, "%d\n", var); +} + +static ssize_t +queue_var_store(unsigned long *var, const char *page, size_t count) +{ + char *p = (char *) page; + + *var = simple_strtoul(p, &p, 10); + return count; +} + +static ssize_t queue_requests_show(struct request_queue *q, char *page) +{ + return queue_var_show(q->nr_requests, (page)); +} + +static ssize_t +queue_requests_store(struct request_queue *q, const char *page, size_t count) +{ + struct request_list *rl = &q->rq; + + int ret = queue_var_store(&q->nr_requests, page, count); + if (q->nr_requests < BLKDEV_MIN_RQ) + q->nr_requests = BLKDEV_MIN_RQ; + blk_queue_congestion_threshold(q); + + if (rl->count[READ] >= queue_congestion_on_threshold(q)) + set_queue_congested(q, READ); + else if (rl->count[READ] < queue_congestion_off_threshold(q)) + clear_queue_congested(q, READ); + + if (rl->count[WRITE] >= queue_congestion_on_threshold(q)) + set_queue_congested(q, WRITE); + else if (rl->count[WRITE] < queue_congestion_off_threshold(q)) + clear_queue_congested(q, WRITE); + + if (rl->count[READ] >= q->nr_requests) { + blk_set_queue_full(q, READ); + } else if (rl->count[READ]+1 <= q->nr_requests) { + blk_clear_queue_full(q, READ); + wake_up(&rl->wait[READ]); + } + + if (rl->count[WRITE] >= q->nr_requests) { + blk_set_queue_full(q, WRITE); + } else if (rl->count[WRITE]+1 <= q->nr_requests) { + blk_clear_queue_full(q, WRITE); + wake_up(&rl->wait[WRITE]); + } + return ret; +} + +static ssize_t queue_ra_show(struct request_queue *q, char *page) +{ + int ra_kb = q->backing_dev_info.ra_pages << (PAGE_CACHE_SHIFT - 10); + + return queue_var_show(ra_kb, (page)); +} + +static ssize_t +queue_ra_store(struct request_queue *q, const char *page, size_t count) +{ + unsigned long ra_kb; + ssize_t ret = queue_var_store(&ra_kb, page, count); + + spin_lock_irq(q->queue_lock); + if (ra_kb > (q->max_sectors >> 1)) + ra_kb = (q->max_sectors >> 1); + + q->backing_dev_info.ra_pages = ra_kb >> (PAGE_CACHE_SHIFT - 10); + spin_unlock_irq(q->queue_lock); + + return ret; +} + +static ssize_t queue_max_sectors_show(struct request_queue *q, char *page) +{ + int max_sectors_kb = q->max_sectors >> 1; + + return queue_var_show(max_sectors_kb, (page)); +} + +static ssize_t +queue_max_sectors_store(struct request_queue *q, const char *page, size_t count) +{ + unsigned long max_sectors_kb, + max_hw_sectors_kb = q->max_hw_sectors >> 1, + page_kb = 1 << (PAGE_CACHE_SHIFT - 10); + ssize_t ret = queue_var_store(&max_sectors_kb, page, count); + int ra_kb; + + if (max_sectors_kb > max_hw_sectors_kb || max_sectors_kb < page_kb) + return -EINVAL; + /* + * Take the queue lock to update the readahead and max_sectors + * values synchronously: + */ + spin_lock_irq(q->queue_lock); + /* + * Trim readahead window as well, if necessary: + */ + ra_kb = q->backing_dev_info.ra_pages << (PAGE_CACHE_SHIFT - 10); + if (ra_kb > max_sectors_kb) + q->backing_dev_info.ra_pages = + max_sectors_kb >> (PAGE_CACHE_SHIFT - 10); + + q->max_sectors = max_sectors_kb << 1; + spin_unlock_irq(q->queue_lock); + + return ret; +} + +static ssize_t queue_max_hw_sectors_show(struct request_queue *q, char *page) +{ + int max_hw_sectors_kb = q->max_hw_sectors >> 1; + + return queue_var_show(max_hw_sectors_kb, (page)); +} + + +static struct queue_sysfs_entry queue_requests_entry = { + .attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR }, + .show = queue_requests_show, + .store = queue_requests_store, +}; + +static struct queue_sysfs_entry queue_ra_entry = { + .attr = {.name = "read_ahead_kb", .mode = S_IRUGO | S_IWUSR }, + .show = queue_ra_show, + .store = queue_ra_store, +}; + +static struct queue_sysfs_entry queue_max_sectors_entry = { + .attr = {.name = "max_sectors_kb", .mode = S_IRUGO | S_IWUSR }, + .show = queue_max_sectors_show, + .store = queue_max_sectors_store, +}; + +static struct queue_sysfs_entry queue_max_hw_sectors_entry = { + .attr = {.name = "max_hw_sectors_kb", .mode = S_IRUGO }, + .show = queue_max_hw_sectors_show, +}; + +static struct queue_sysfs_entry queue_iosched_entry = { + .attr = {.name = "scheduler", .mode = S_IRUGO | S_IWUSR }, + .show = elv_iosched_show, + .store = elv_iosched_store, +}; + +static struct attribute *default_attrs[] = { + &queue_requests_entry.attr, + &queue_ra_entry.attr, + &queue_max_hw_sectors_entry.attr, + &queue_max_sectors_entry.attr, + &queue_iosched_entry.attr, + NULL, +}; + +#define to_queue(atr) container_of((atr), struct queue_sysfs_entry, attr) + +static ssize_t +queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page) +{ + struct queue_sysfs_entry *entry = to_queue(attr); + struct request_queue *q; + + q = container_of(kobj, struct request_queue, kobj); + if (!entry->show) + return -EIO; + + return entry->show(q, page); +} + +static ssize_t +queue_attr_store(struct kobject *kobj, struct attribute *attr, + const char *page, size_t length) +{ + struct queue_sysfs_entry *entry = to_queue(attr); + struct request_queue *q; + + q = container_of(kobj, struct request_queue, kobj); + if (!entry->store) + return -EIO; + + return entry->store(q, page, length); +} + +static struct sysfs_ops queue_sysfs_ops = { + .show = queue_attr_show, + .store = queue_attr_store, +}; + +static struct kobj_type queue_ktype = { + .sysfs_ops = &queue_sysfs_ops, + .default_attrs = default_attrs, +}; + +int blk_register_queue(struct gendisk *disk) +{ + int ret; + + request_queue_t *q = disk->queue; + + if (!q || !q->request_fn) + return -ENXIO; + + q->kobj.parent = kobject_get(&disk->kobj); + if (!q->kobj.parent) + return -EBUSY; + + snprintf(q->kobj.name, KOBJ_NAME_LEN, "%s", "queue"); + q->kobj.ktype = &queue_ktype; + + ret = kobject_register(&q->kobj); + if (ret < 0) + return ret; + + ret = elv_register_queue(q); + if (ret) { + kobject_unregister(&q->kobj); + return ret; + } + + return 0; +} + +void blk_unregister_queue(struct gendisk *disk) +{ + request_queue_t *q = disk->queue; + + if (q && q->request_fn) { + elv_unregister_queue(q); + + kobject_unregister(&q->kobj); + kobject_put(&disk->kobj); + } +} diff --git a/block/noop-iosched.c b/block/noop-iosched.c new file mode 100644 index 00000000000..e54f006e7e6 --- /dev/null +++ b/block/noop-iosched.c @@ -0,0 +1,46 @@ +/* + * elevator noop + */ +#include +#include +#include +#include +#include + +static void elevator_noop_add_request(request_queue_t *q, struct request *rq) +{ + rq->flags |= REQ_NOMERGE; + elv_dispatch_add_tail(q, rq); +} + +static int elevator_noop_dispatch(request_queue_t *q, int force) +{ + return 0; +} + +static struct elevator_type elevator_noop = { + .ops = { + .elevator_dispatch_fn = elevator_noop_dispatch, + .elevator_add_req_fn = elevator_noop_add_request, + }, + .elevator_name = "noop", + .elevator_owner = THIS_MODULE, +}; + +static int __init noop_init(void) +{ + return elv_register(&elevator_noop); +} + +static void __exit noop_exit(void) +{ + elv_unregister(&elevator_noop); +} + +module_init(noop_init); +module_exit(noop_exit); + + +MODULE_AUTHOR("Jens Axboe"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("No-op IO scheduler"); diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c new file mode 100644 index 00000000000..382dea7b224 --- /dev/null +++ b/block/scsi_ioctl.c @@ -0,0 +1,589 @@ +/* + * Copyright (C) 2001 Jens Axboe + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public Licens + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111- + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* Command group 3 is reserved and should never be used. */ +const unsigned char scsi_command_size[8] = +{ + 6, 10, 10, 12, + 16, 12, 10, 10 +}; + +EXPORT_SYMBOL(scsi_command_size); + +#define BLK_DEFAULT_TIMEOUT (60 * HZ) + +#include + +static int sg_get_version(int __user *p) +{ + static int sg_version_num = 30527; + return put_user(sg_version_num, p); +} + +static int scsi_get_idlun(request_queue_t *q, int __user *p) +{ + return put_user(0, p); +} + +static int scsi_get_bus(request_queue_t *q, int __user *p) +{ + return put_user(0, p); +} + +static int sg_get_timeout(request_queue_t *q) +{ + return q->sg_timeout / (HZ / USER_HZ); +} + +static int sg_set_timeout(request_queue_t *q, int __user *p) +{ + int timeout, err = get_user(timeout, p); + + if (!err) + q->sg_timeout = timeout * (HZ / USER_HZ); + + return err; +} + +static int sg_get_reserved_size(request_queue_t *q, int __user *p) +{ + return put_user(q->sg_reserved_size, p); +} + +static int sg_set_reserved_size(request_queue_t *q, int __user *p) +{ + int size, err = get_user(size, p); + + if (err) + return err; + + if (size < 0) + return -EINVAL; + if (size > (q->max_sectors << 9)) + size = q->max_sectors << 9; + + q->sg_reserved_size = size; + return 0; +} + +/* + * will always return that we are ATAPI even for a real SCSI drive, I'm not + * so sure this is worth doing anything about (why would you care??) + */ +static int sg_emulated_host(request_queue_t *q, int __user *p) +{ + return put_user(1, p); +} + +#define CMD_READ_SAFE 0x01 +#define CMD_WRITE_SAFE 0x02 +#define CMD_WARNED 0x04 +#define safe_for_read(cmd) [cmd] = CMD_READ_SAFE +#define safe_for_write(cmd) [cmd] = CMD_WRITE_SAFE + +static int verify_command(struct file *file, unsigned char *cmd) +{ + static unsigned char cmd_type[256] = { + + /* Basic read-only commands */ + safe_for_read(TEST_UNIT_READY), + safe_for_read(REQUEST_SENSE), + safe_for_read(READ_6), + safe_for_read(READ_10), + safe_for_read(READ_12), + safe_for_read(READ_16), + safe_for_read(READ_BUFFER), + safe_for_read(READ_DEFECT_DATA), + safe_for_read(READ_LONG), + safe_for_read(INQUIRY), + safe_for_read(MODE_SENSE), + safe_for_read(MODE_SENSE_10), + safe_for_read(LOG_SENSE), + safe_for_read(START_STOP), + safe_for_read(GPCMD_VERIFY_10), + safe_for_read(VERIFY_16), + + /* Audio CD commands */ + safe_for_read(GPCMD_PLAY_CD), + safe_for_read(GPCMD_PLAY_AUDIO_10), + safe_for_read(GPCMD_PLAY_AUDIO_MSF), + safe_for_read(GPCMD_PLAY_AUDIO_TI), + safe_for_read(GPCMD_PAUSE_RESUME), + + /* CD/DVD data reading */ + safe_for_read(GPCMD_READ_BUFFER_CAPACITY), + safe_for_read(GPCMD_READ_CD), + safe_for_read(GPCMD_READ_CD_MSF), + safe_for_read(GPCMD_READ_DISC_INFO), + safe_for_read(GPCMD_READ_CDVD_CAPACITY), + safe_for_read(GPCMD_READ_DVD_STRUCTURE), + safe_for_read(GPCMD_READ_HEADER), + safe_for_read(GPCMD_READ_TRACK_RZONE_INFO), + safe_for_read(GPCMD_READ_SUBCHANNEL), + safe_for_read(GPCMD_READ_TOC_PMA_ATIP), + safe_for_read(GPCMD_REPORT_KEY), + safe_for_read(GPCMD_SCAN), + safe_for_read(GPCMD_GET_CONFIGURATION), + safe_for_read(GPCMD_READ_FORMAT_CAPACITIES), + safe_for_read(GPCMD_GET_EVENT_STATUS_NOTIFICATION), + safe_for_read(GPCMD_GET_PERFORMANCE), + safe_for_read(GPCMD_SEEK), + safe_for_read(GPCMD_STOP_PLAY_SCAN), + + /* Basic writing commands */ + safe_for_write(WRITE_6), + safe_for_write(WRITE_10), + safe_for_write(WRITE_VERIFY), + safe_for_write(WRITE_12), + safe_for_write(WRITE_VERIFY_12), + safe_for_write(WRITE_16), + safe_for_write(WRITE_LONG), + safe_for_write(WRITE_LONG_2), + safe_for_write(ERASE), + safe_for_write(GPCMD_MODE_SELECT_10), + safe_for_write(MODE_SELECT), + safe_for_write(LOG_SELECT), + safe_for_write(GPCMD_BLANK), + safe_for_write(GPCMD_CLOSE_TRACK), + safe_for_write(GPCMD_FLUSH_CACHE), + safe_for_write(GPCMD_FORMAT_UNIT), + safe_for_write(GPCMD_REPAIR_RZONE_TRACK), + safe_for_write(GPCMD_RESERVE_RZONE_TRACK), + safe_for_write(GPCMD_SEND_DVD_STRUCTURE), + safe_for_write(GPCMD_SEND_EVENT), + safe_for_write(GPCMD_SEND_KEY), + safe_for_write(GPCMD_SEND_OPC), + safe_for_write(GPCMD_SEND_CUE_SHEET), + safe_for_write(GPCMD_SET_SPEED), + safe_for_write(GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL), + safe_for_write(GPCMD_LOAD_UNLOAD), + safe_for_write(GPCMD_SET_STREAMING), + }; + unsigned char type = cmd_type[cmd[0]]; + + /* Anybody who can open the device can do a read-safe command */ + if (type & CMD_READ_SAFE) + return 0; + + /* Write-safe commands just require a writable open.. */ + if (type & CMD_WRITE_SAFE) { + if (file->f_mode & FMODE_WRITE) + return 0; + } + + /* And root can do any command.. */ + if (capable(CAP_SYS_RAWIO)) + return 0; + + if (!type) { + cmd_type[cmd[0]] = CMD_WARNED; + printk(KERN_WARNING "scsi: unknown opcode 0x%02x\n", cmd[0]); + } + + /* Otherwise fail it with an "Operation not permitted" */ + return -EPERM; +} + +static int sg_io(struct file *file, request_queue_t *q, + struct gendisk *bd_disk, struct sg_io_hdr *hdr) +{ + unsigned long start_time; + int writing = 0, ret = 0; + struct request *rq; + struct bio *bio; + char sense[SCSI_SENSE_BUFFERSIZE]; + unsigned char cmd[BLK_MAX_CDB]; + + if (hdr->interface_id != 'S') + return -EINVAL; + if (hdr->cmd_len > BLK_MAX_CDB) + return -EINVAL; + if (copy_from_user(cmd, hdr->cmdp, hdr->cmd_len)) + return -EFAULT; + if (verify_command(file, cmd)) + return -EPERM; + + if (hdr->dxfer_len > (q->max_sectors << 9)) + return -EIO; + + if (hdr->dxfer_len) + switch (hdr->dxfer_direction) { + default: + return -EINVAL; + case SG_DXFER_TO_FROM_DEV: + case SG_DXFER_TO_DEV: + writing = 1; + break; + case SG_DXFER_FROM_DEV: + break; + } + + rq = blk_get_request(q, writing ? WRITE : READ, GFP_KERNEL); + if (!rq) + return -ENOMEM; + + if (hdr->iovec_count) { + const int size = sizeof(struct sg_iovec) * hdr->iovec_count; + struct sg_iovec *iov; + + iov = kmalloc(size, GFP_KERNEL); + if (!iov) { + ret = -ENOMEM; + goto out; + } + + if (copy_from_user(iov, hdr->dxferp, size)) { + kfree(iov); + ret = -EFAULT; + goto out; + } + + ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count); + kfree(iov); + } else if (hdr->dxfer_len) + ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len); + + if (ret) + goto out; + + /* + * fill in request structure + */ + rq->cmd_len = hdr->cmd_len; + memcpy(rq->cmd, cmd, hdr->cmd_len); + if (sizeof(rq->cmd) != hdr->cmd_len) + memset(rq->cmd + hdr->cmd_len, 0, sizeof(rq->cmd) - hdr->cmd_len); + + memset(sense, 0, sizeof(sense)); + rq->sense = sense; + rq->sense_len = 0; + + rq->flags |= REQ_BLOCK_PC; + bio = rq->bio; + + /* + * bounce this after holding a reference to the original bio, it's + * needed for proper unmapping + */ + if (rq->bio) + blk_queue_bounce(q, &rq->bio); + + rq->timeout = (hdr->timeout * HZ) / 1000; + if (!rq->timeout) + rq->timeout = q->sg_timeout; + if (!rq->timeout) + rq->timeout = BLK_DEFAULT_TIMEOUT; + + start_time = jiffies; + + /* ignore return value. All information is passed back to caller + * (if he doesn't check that is his problem). + * N.B. a non-zero SCSI status is _not_ necessarily an error. + */ + blk_execute_rq(q, bd_disk, rq, 0); + + /* write to all output members */ + hdr->status = 0xff & rq->errors; + hdr->masked_status = status_byte(rq->errors); + hdr->msg_status = msg_byte(rq->errors); + hdr->host_status = host_byte(rq->errors); + hdr->driver_status = driver_byte(rq->errors); + hdr->info = 0; + if (hdr->masked_status || hdr->host_status || hdr->driver_status) + hdr->info |= SG_INFO_CHECK; + hdr->resid = rq->data_len; + hdr->duration = ((jiffies - start_time) * 1000) / HZ; + hdr->sb_len_wr = 0; + + if (rq->sense_len && hdr->sbp) { + int len = min((unsigned int) hdr->mx_sb_len, rq->sense_len); + + if (!copy_to_user(hdr->sbp, rq->sense, len)) + hdr->sb_len_wr = len; + } + + if (blk_rq_unmap_user(bio, hdr->dxfer_len)) + ret = -EFAULT; + + /* may not have succeeded, but output values written to control + * structure (struct sg_io_hdr). */ +out: + blk_put_request(rq); + return ret; +} + +#define OMAX_SB_LEN 16 /* For backward compatibility */ + +static int sg_scsi_ioctl(struct file *file, request_queue_t *q, + struct gendisk *bd_disk, Scsi_Ioctl_Command __user *sic) +{ + struct request *rq; + int err; + unsigned int in_len, out_len, bytes, opcode, cmdlen; + char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE]; + + /* + * get in an out lengths, verify they don't exceed a page worth of data + */ + if (get_user(in_len, &sic->inlen)) + return -EFAULT; + if (get_user(out_len, &sic->outlen)) + return -EFAULT; + if (in_len > PAGE_SIZE || out_len > PAGE_SIZE) + return -EINVAL; + if (get_user(opcode, sic->data)) + return -EFAULT; + + bytes = max(in_len, out_len); + if (bytes) { + buffer = kmalloc(bytes, q->bounce_gfp | GFP_USER| __GFP_NOWARN); + if (!buffer) + return -ENOMEM; + + memset(buffer, 0, bytes); + } + + rq = blk_get_request(q, in_len ? WRITE : READ, __GFP_WAIT); + + cmdlen = COMMAND_SIZE(opcode); + + /* + * get command and data to send to device, if any + */ + err = -EFAULT; + rq->cmd_len = cmdlen; + if (copy_from_user(rq->cmd, sic->data, cmdlen)) + goto error; + + if (copy_from_user(buffer, sic->data + cmdlen, in_len)) + goto error; + + err = verify_command(file, rq->cmd); + if (err) + goto error; + + switch (opcode) { + case SEND_DIAGNOSTIC: + case FORMAT_UNIT: + rq->timeout = FORMAT_UNIT_TIMEOUT; + break; + case START_STOP: + rq->timeout = START_STOP_TIMEOUT; + break; + case MOVE_MEDIUM: + rq->timeout = MOVE_MEDIUM_TIMEOUT; + break; + case READ_ELEMENT_STATUS: + rq->timeout = READ_ELEMENT_STATUS_TIMEOUT; + break; + case READ_DEFECT_DATA: + rq->timeout = READ_DEFECT_DATA_TIMEOUT; + break; + default: + rq->timeout = BLK_DEFAULT_TIMEOUT; + break; + } + + memset(sense, 0, sizeof(sense)); + rq->sense = sense; + rq->sense_len = 0; + + rq->data = buffer; + rq->data_len = bytes; + rq->flags |= REQ_BLOCK_PC; + + blk_execute_rq(q, bd_disk, rq, 0); + err = rq->errors & 0xff; /* only 8 bit SCSI status */ + if (err) { + if (rq->sense_len && rq->sense) { + bytes = (OMAX_SB_LEN > rq->sense_len) ? + rq->sense_len : OMAX_SB_LEN; + if (copy_to_user(sic->data, rq->sense, bytes)) + err = -EFAULT; + } + } else { + if (copy_to_user(sic->data, buffer, out_len)) + err = -EFAULT; + } + +error: + kfree(buffer); + blk_put_request(rq); + return err; +} + +int scsi_cmd_ioctl(struct file *file, struct gendisk *bd_disk, unsigned int cmd, void __user *arg) +{ + request_queue_t *q; + struct request *rq; + int close = 0, err; + + q = bd_disk->queue; + if (!q) + return -ENXIO; + + if (blk_get_queue(q)) + return -ENXIO; + + switch (cmd) { + /* + * new sgv3 interface + */ + case SG_GET_VERSION_NUM: + err = sg_get_version(arg); + break; + case SCSI_IOCTL_GET_IDLUN: + err = scsi_get_idlun(q, arg); + break; + case SCSI_IOCTL_GET_BUS_NUMBER: + err = scsi_get_bus(q, arg); + break; + case SG_SET_TIMEOUT: + err = sg_set_timeout(q, arg); + break; + case SG_GET_TIMEOUT: + err = sg_get_timeout(q); + break; + case SG_GET_RESERVED_SIZE: + err = sg_get_reserved_size(q, arg); + break; + case SG_SET_RESERVED_SIZE: + err = sg_set_reserved_size(q, arg); + break; + case SG_EMULATED_HOST: + err = sg_emulated_host(q, arg); + break; + case SG_IO: { + struct sg_io_hdr hdr; + + err = -EFAULT; + if (copy_from_user(&hdr, arg, sizeof(hdr))) + break; + err = sg_io(file, q, bd_disk, &hdr); + if (err == -EFAULT) + break; + + if (copy_to_user(arg, &hdr, sizeof(hdr))) + err = -EFAULT; + break; + } + case CDROM_SEND_PACKET: { + struct cdrom_generic_command cgc; + struct sg_io_hdr hdr; + + err = -EFAULT; + if (copy_from_user(&cgc, arg, sizeof(cgc))) + break; + cgc.timeout = clock_t_to_jiffies(cgc.timeout); + memset(&hdr, 0, sizeof(hdr)); + hdr.interface_id = 'S'; + hdr.cmd_len = sizeof(cgc.cmd); + hdr.dxfer_len = cgc.buflen; + err = 0; + switch (cgc.data_direction) { + case CGC_DATA_UNKNOWN: + hdr.dxfer_direction = SG_DXFER_UNKNOWN; + break; + case CGC_DATA_WRITE: + hdr.dxfer_direction = SG_DXFER_TO_DEV; + break; + case CGC_DATA_READ: + hdr.dxfer_direction = SG_DXFER_FROM_DEV; + break; + case CGC_DATA_NONE: + hdr.dxfer_direction = SG_DXFER_NONE; + break; + default: + err = -EINVAL; + } + if (err) + break; + + hdr.dxferp = cgc.buffer; + hdr.sbp = cgc.sense; + if (hdr.sbp) + hdr.mx_sb_len = sizeof(struct request_sense); + hdr.timeout = cgc.timeout; + hdr.cmdp = ((struct cdrom_generic_command __user*) arg)->cmd; + hdr.cmd_len = sizeof(cgc.cmd); + + err = sg_io(file, q, bd_disk, &hdr); + if (err == -EFAULT) + break; + + if (hdr.status) + err = -EIO; + + cgc.stat = err; + cgc.buflen = hdr.resid; + if (copy_to_user(arg, &cgc, sizeof(cgc))) + err = -EFAULT; + + break; + } + + /* + * old junk scsi send command ioctl + */ + case SCSI_IOCTL_SEND_COMMAND: + printk(KERN_WARNING "program %s is using a deprecated SCSI ioctl, please convert it to SG_IO\n", current->comm); + err = -EINVAL; + if (!arg) + break; + + err = sg_scsi_ioctl(file, q, bd_disk, arg); + break; + case CDROMCLOSETRAY: + close = 1; + case CDROMEJECT: + rq = blk_get_request(q, WRITE, __GFP_WAIT); + rq->flags |= REQ_BLOCK_PC; + rq->data = NULL; + rq->data_len = 0; + rq->timeout = BLK_DEFAULT_TIMEOUT; + memset(rq->cmd, 0, sizeof(rq->cmd)); + rq->cmd[0] = GPCMD_START_STOP_UNIT; + rq->cmd[4] = 0x02 + (close != 0); + rq->cmd_len = 6; + err = blk_execute_rq(q, bd_disk, rq, 0); + blk_put_request(rq); + break; + default: + err = -ENOTTY; + } + + blk_put_queue(q); + return err; +} + +EXPORT_SYMBOL(scsi_cmd_ioctl); diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 51b0af1cebe..7b1cd93892b 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -409,16 +409,6 @@ config BLK_DEV_INITRD for details. -#XXX - it makes sense to enable this only for 32-bit subarch's, not for x86_64 -#for instance. -config LBD - bool "Support for Large Block Devices" - depends on X86 || (MIPS && 32BIT) || PPC32 || ARCH_S390_31 || SUPERH || UML - help - Say Y here if you want to attach large (bigger than 2TB) discs to - your machine, or if you want to have a raid or loopback device - bigger than 2TB. Otherwise say N. - config CDROM_PKTCDVD tristate "Packet writing on CD/DVD media" depends on !UML @@ -455,8 +445,6 @@ config CDROM_PKTCDVD_WCACHE source "drivers/s390/block/Kconfig" -source "drivers/block/Kconfig.iosched" - config ATA_OVER_ETH tristate "ATA over Ethernet support" depends on NET diff --git a/drivers/block/Kconfig.iosched b/drivers/block/Kconfig.iosched deleted file mode 100644 index 5b90d2fa63b..00000000000 --- a/drivers/block/Kconfig.iosched +++ /dev/null @@ -1,69 +0,0 @@ - -menu "IO Schedulers" - -config IOSCHED_NOOP - bool - default y - ---help--- - The no-op I/O scheduler is a minimal scheduler that does basic merging - and sorting. Its main uses include non-disk based block devices like - memory devices, and specialised software or hardware environments - that do their own scheduling and require only minimal assistance from - the kernel. - -config IOSCHED_AS - tristate "Anticipatory I/O scheduler" - default y - ---help--- - The anticipatory I/O scheduler is the default disk scheduler. It is - generally a good choice for most environments, but is quite large and - complex when compared to the deadline I/O scheduler, it can also be - slower in some cases especially some database loads. - -config IOSCHED_DEADLINE - tristate "Deadline I/O scheduler" - default y - ---help--- - The deadline I/O scheduler is simple and compact, and is often as - good as the anticipatory I/O scheduler, and in some database - workloads, better. In the case of a single process performing I/O to - a disk at any one time, its behaviour is almost identical to the - anticipatory I/O scheduler and so is a good choice. - -config IOSCHED_CFQ - tristate "CFQ I/O scheduler" - default y - ---help--- - The CFQ I/O scheduler tries to distribute bandwidth equally - among all processes in the system. It should provide a fair - working environment, suitable for desktop systems. - -choice - prompt "Default I/O scheduler" - default DEFAULT_AS - help - Select the I/O scheduler which will be used by default for all - block devices. - - config DEFAULT_AS - bool "Anticipatory" if IOSCHED_AS - - config DEFAULT_DEADLINE - bool "Deadline" if IOSCHED_DEADLINE - - config DEFAULT_CFQ - bool "CFQ" if IOSCHED_CFQ - - config DEFAULT_NOOP - bool "No-op" - -endchoice - -config DEFAULT_IOSCHED - string - default "anticipatory" if DEFAULT_AS - default "deadline" if DEFAULT_DEADLINE - default "cfq" if DEFAULT_CFQ - default "noop" if DEFAULT_NOOP - -endmenu diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 1cf09a1c065..3ec1f8df87b 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -4,21 +4,7 @@ # 12 June 2000, Christoph Hellwig # Rewritten to use lists instead of if-statements. # -# Note : at this point, these files are compiled on all systems. -# In the future, some of these should be built conditionally. -# - -# -# NOTE that ll_rw_blk.c must come early in linkage order - it starts the -# kblockd threads -# - -obj-y := elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o -obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o -obj-$(CONFIG_IOSCHED_AS) += as-iosched.o -obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o -obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o obj-$(CONFIG_MAC_FLOPPY) += swim3.o obj-$(CONFIG_BLK_DEV_FD) += floppy.o obj-$(CONFIG_BLK_DEV_FD98) += floppy98.o diff --git a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c deleted file mode 100644 index c6744ff3829..00000000000 --- a/drivers/block/as-iosched.c +++ /dev/null @@ -1,1985 +0,0 @@ -/* - * linux/drivers/block/as-iosched.c - * - * Anticipatory & deadline i/o scheduler. - * - * Copyright (C) 2002 Jens Axboe - * Nick Piggin - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define REQ_SYNC 1 -#define REQ_ASYNC 0 - -/* - * See Documentation/block/as-iosched.txt - */ - -/* - * max time before a read is submitted. - */ -#define default_read_expire (HZ / 8) - -/* - * ditto for writes, these limits are not hard, even - * if the disk is capable of satisfying them. - */ -#define default_write_expire (HZ / 4) - -/* - * read_batch_expire describes how long we will allow a stream of reads to - * persist before looking to see whether it is time to switch over to writes. - */ -#define default_read_batch_expire (HZ / 2) - -/* - * write_batch_expire describes how long we want a stream of writes to run for. - * This is not a hard limit, but a target we set for the auto-tuning thingy. - * See, the problem is: we can send a lot of writes to disk cache / TCQ in - * a short amount of time... - */ -#define default_write_batch_expire (HZ / 8) - -/* - * max time we may wait to anticipate a read (default around 6ms) - */ -#define default_antic_expire ((HZ / 150) ? HZ / 150 : 1) - -/* - * Keep track of up to 20ms thinktimes. We can go as big as we like here, - * however huge values tend to interfere and not decay fast enough. A program - * might be in a non-io phase of operation. Waiting on user input for example, - * or doing a lengthy computation. A small penalty can be justified there, and - * will still catch out those processes that constantly have large thinktimes. - */ -#define MAX_THINKTIME (HZ/50UL) - -/* Bits in as_io_context.state */ -enum as_io_states { - AS_TASK_RUNNING=0, /* Process has not exitted */ - AS_TASK_IOSTARTED, /* Process has started some IO */ - AS_TASK_IORUNNING, /* Process has completed some IO */ -}; - -enum anticipation_status { - ANTIC_OFF=0, /* Not anticipating (normal operation) */ - ANTIC_WAIT_REQ, /* The last read has not yet completed */ - ANTIC_WAIT_NEXT, /* Currently anticipating a request vs - last read (which has completed) */ - ANTIC_FINISHED, /* Anticipating but have found a candidate - * or timed out */ -}; - -struct as_data { - /* - * run time data - */ - - struct request_queue *q; /* the "owner" queue */ - - /* - * requests (as_rq s) are present on both sort_list and fifo_list - */ - struct rb_root sort_list[2]; - struct list_head fifo_list[2]; - - struct as_rq *next_arq[2]; /* next in sort order */ - sector_t last_sector[2]; /* last REQ_SYNC & REQ_ASYNC sectors */ - struct list_head *hash; /* request hash */ - - unsigned long exit_prob; /* probability a task will exit while - being waited on */ - unsigned long new_ttime_total; /* mean thinktime on new proc */ - unsigned long new_ttime_mean; - u64 new_seek_total; /* mean seek on new proc */ - sector_t new_seek_mean; - - unsigned long current_batch_expires; - unsigned long last_check_fifo[2]; - int changed_batch; /* 1: waiting for old batch to end */ - int new_batch; /* 1: waiting on first read complete */ - int batch_data_dir; /* current batch REQ_SYNC / REQ_ASYNC */ - int write_batch_count; /* max # of reqs in a write batch */ - int current_write_count; /* how many requests left this batch */ - int write_batch_idled; /* has the write batch gone idle? */ - mempool_t *arq_pool; - - enum anticipation_status antic_status; - unsigned long antic_start; /* jiffies: when it started */ - struct timer_list antic_timer; /* anticipatory scheduling timer */ - struct work_struct antic_work; /* Deferred unplugging */ - struct io_context *io_context; /* Identify the expected process */ - int ioc_finished; /* IO associated with io_context is finished */ - int nr_dispatched; - - /* - * settings that change how the i/o scheduler behaves - */ - unsigned long fifo_expire[2]; - unsigned long batch_expire[2]; - unsigned long antic_expire; -}; - -#define list_entry_fifo(ptr) list_entry((ptr), struct as_rq, fifo) - -/* - * per-request data. - */ -enum arq_state { - AS_RQ_NEW=0, /* New - not referenced and not on any lists */ - AS_RQ_QUEUED, /* In the request queue. It belongs to the - scheduler */ - AS_RQ_DISPATCHED, /* On the dispatch list. It belongs to the - driver now */ - AS_RQ_PRESCHED, /* Debug poisoning for requests being used */ - AS_RQ_REMOVED, - AS_RQ_MERGED, - AS_RQ_POSTSCHED, /* when they shouldn't be */ -}; - -struct as_rq { - /* - * rbtree index, key is the starting offset - */ - struct rb_node rb_node; - sector_t rb_key; - - struct request *request; - - struct io_context *io_context; /* The submitting task */ - - /* - * request hash, key is the ending offset (for back merge lookup) - */ - struct list_head hash; - unsigned int on_hash; - - /* - * expire fifo - */ - struct list_head fifo; - unsigned long expires; - - unsigned int is_sync; - enum arq_state state; -}; - -#define RQ_DATA(rq) ((struct as_rq *) (rq)->elevator_private) - -static kmem_cache_t *arq_pool; - -/* - * IO Context helper functions - */ - -/* Called to deallocate the as_io_context */ -static void free_as_io_context(struct as_io_context *aic) -{ - kfree(aic); -} - -/* Called when the task exits */ -static void exit_as_io_context(struct as_io_context *aic) -{ - WARN_ON(!test_bit(AS_TASK_RUNNING, &aic->state)); - clear_bit(AS_TASK_RUNNING, &aic->state); -} - -static struct as_io_context *alloc_as_io_context(void) -{ - struct as_io_context *ret; - - ret = kmalloc(sizeof(*ret), GFP_ATOMIC); - if (ret) { - ret->dtor = free_as_io_context; - ret->exit = exit_as_io_context; - ret->state = 1 << AS_TASK_RUNNING; - atomic_set(&ret->nr_queued, 0); - atomic_set(&ret->nr_dispatched, 0); - spin_lock_init(&ret->lock); - ret->ttime_total = 0; - ret->ttime_samples = 0; - ret->ttime_mean = 0; - ret->seek_total = 0; - ret->seek_samples = 0; - ret->seek_mean = 0; - } - - return ret; -} - -/* - * If the current task has no AS IO context then create one and initialise it. - * Then take a ref on the task's io context and return it. - */ -static struct io_context *as_get_io_context(void) -{ - struct io_context *ioc = get_io_context(GFP_ATOMIC); - if (ioc && !ioc->aic) { - ioc->aic = alloc_as_io_context(); - if (!ioc->aic) { - put_io_context(ioc); - ioc = NULL; - } - } - return ioc; -} - -static void as_put_io_context(struct as_rq *arq) -{ - struct as_io_context *aic; - - if (unlikely(!arq->io_context)) - return; - - aic = arq->io_context->aic; - - if (arq->is_sync == REQ_SYNC && aic) { - spin_lock(&aic->lock); - set_bit(AS_TASK_IORUNNING, &aic->state); - aic->last_end_request = jiffies; - spin_unlock(&aic->lock); - } - - put_io_context(arq->io_context); -} - -/* - * the back merge hash support functions - */ -static const int as_hash_shift = 6; -#define AS_HASH_BLOCK(sec) ((sec) >> 3) -#define AS_HASH_FN(sec) (hash_long(AS_HASH_BLOCK((sec)), as_hash_shift)) -#define AS_HASH_ENTRIES (1 << as_hash_shift) -#define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors) -#define list_entry_hash(ptr) list_entry((ptr), struct as_rq, hash) - -static inline void __as_del_arq_hash(struct as_rq *arq) -{ - arq->on_hash = 0; - list_del_init(&arq->hash); -} - -static inline void as_del_arq_hash(struct as_rq *arq) -{ - if (arq->on_hash) - __as_del_arq_hash(arq); -} - -static void as_add_arq_hash(struct as_data *ad, struct as_rq *arq) -{ - struct request *rq = arq->request; - - BUG_ON(arq->on_hash); - - arq->on_hash = 1; - list_add(&arq->hash, &ad->hash[AS_HASH_FN(rq_hash_key(rq))]); -} - -/* - * move hot entry to front of chain - */ -static inline void as_hot_arq_hash(struct as_data *ad, struct as_rq *arq) -{ - struct request *rq = arq->request; - struct list_head *head = &ad->hash[AS_HASH_FN(rq_hash_key(rq))]; - - if (!arq->on_hash) { - WARN_ON(1); - return; - } - - if (arq->hash.prev != head) { - list_del(&arq->hash); - list_add(&arq->hash, head); - } -} - -static struct request *as_find_arq_hash(struct as_data *ad, sector_t offset) -{ - struct list_head *hash_list = &ad->hash[AS_HASH_FN(offset)]; - struct list_head *entry, *next = hash_list->next; - - while ((entry = next) != hash_list) { - struct as_rq *arq = list_entry_hash(entry); - struct request *__rq = arq->request; - - next = entry->next; - - BUG_ON(!arq->on_hash); - - if (!rq_mergeable(__rq)) { - as_del_arq_hash(arq); - continue; - } - - if (rq_hash_key(__rq) == offset) - return __rq; - } - - return NULL; -} - -/* - * rb tree support functions - */ -#define RB_NONE (2) -#define RB_EMPTY(root) ((root)->rb_node == NULL) -#define ON_RB(node) ((node)->rb_color != RB_NONE) -#define RB_CLEAR(node) ((node)->rb_color = RB_NONE) -#define rb_entry_arq(node) rb_entry((node), struct as_rq, rb_node) -#define ARQ_RB_ROOT(ad, arq) (&(ad)->sort_list[(arq)->is_sync]) -#define rq_rb_key(rq) (rq)->sector - -/* - * as_find_first_arq finds the first (lowest sector numbered) request - * for the specified data_dir. Used to sweep back to the start of the disk - * (1-way elevator) after we process the last (highest sector) request. - */ -static struct as_rq *as_find_first_arq(struct as_data *ad, int data_dir) -{ - struct rb_node *n = ad->sort_list[data_dir].rb_node; - - if (n == NULL) - return NULL; - - for (;;) { - if (n->rb_left == NULL) - return rb_entry_arq(n); - - n = n->rb_left; - } -} - -/* - * Add the request to the rb tree if it is unique. If there is an alias (an - * existing request against the same sector), which can happen when using - * direct IO, then return the alias. - */ -static struct as_rq *as_add_arq_rb(struct as_data *ad, struct as_rq *arq) -{ - struct rb_node **p = &ARQ_RB_ROOT(ad, arq)->rb_node; - struct rb_node *parent = NULL; - struct as_rq *__arq; - struct request *rq = arq->request; - - arq->rb_key = rq_rb_key(rq); - - while (*p) { - parent = *p; - __arq = rb_entry_arq(parent); - - if (arq->rb_key < __arq->rb_key) - p = &(*p)->rb_left; - else if (arq->rb_key > __arq->rb_key) - p = &(*p)->rb_right; - else - return __arq; - } - - rb_link_node(&arq->rb_node, parent, p); - rb_insert_color(&arq->rb_node, ARQ_RB_ROOT(ad, arq)); - - return NULL; -} - -static inline void as_del_arq_rb(struct as_data *ad, struct as_rq *arq) -{ - if (!ON_RB(&arq->rb_node)) { - WARN_ON(1); - return; - } - - rb_erase(&arq->rb_node, ARQ_RB_ROOT(ad, arq)); - RB_CLEAR(&arq->rb_node); -} - -static struct request * -as_find_arq_rb(struct as_data *ad, sector_t sector, int data_dir) -{ - struct rb_node *n = ad->sort_list[data_dir].rb_node; - struct as_rq *arq; - - while (n) { - arq = rb_entry_arq(n); - - if (sector < arq->rb_key) - n = n->rb_left; - else if (sector > arq->rb_key) - n = n->rb_right; - else - return arq->request; - } - - return NULL; -} - -/* - * IO Scheduler proper - */ - -#define MAXBACK (1024 * 1024) /* - * Maximum distance the disk will go backward - * for a request. - */ - -#define BACK_PENALTY 2 - -/* - * as_choose_req selects the preferred one of two requests of the same data_dir - * ignoring time - eg. timeouts, which is the job of as_dispatch_request - */ -static struct as_rq * -as_choose_req(struct as_data *ad, struct as_rq *arq1, struct as_rq *arq2) -{ - int data_dir; - sector_t last, s1, s2, d1, d2; - int r1_wrap=0, r2_wrap=0; /* requests are behind the disk head */ - const sector_t maxback = MAXBACK; - - if (arq1 == NULL || arq1 == arq2) - return arq2; - if (arq2 == NULL) - return arq1; - - data_dir = arq1->is_sync; - - last = ad->last_sector[data_dir]; - s1 = arq1->request->sector; - s2 = arq2->request->sector; - - BUG_ON(data_dir != arq2->is_sync); - - /* - * Strict one way elevator _except_ in the case where we allow - * short backward seeks which are biased as twice the cost of a - * similar forward seek. - */ - if (s1 >= last) - d1 = s1 - last; - else if (s1+maxback >= last) - d1 = (last - s1)*BACK_PENALTY; - else { - r1_wrap = 1; - d1 = 0; /* shut up, gcc */ - } - - if (s2 >= last) - d2 = s2 - last; - else if (s2+maxback >= last) - d2 = (last - s2)*BACK_PENALTY; - else { - r2_wrap = 1; - d2 = 0; - } - - /* Found required data */ - if (!r1_wrap && r2_wrap) - return arq1; - else if (!r2_wrap && r1_wrap) - return arq2; - else if (r1_wrap && r2_wrap) { - /* both behind the head */ - if (s1 <= s2) - return arq1; - else - return arq2; - } - - /* Both requests in front of the head */ - if (d1 < d2) - return arq1; - else if (d2 < d1) - return arq2; - else { - if (s1 >= s2) - return arq1; - else - return arq2; - } -} - -/* - * as_find_next_arq finds the next request after @prev in elevator order. - * this with as_choose_req form the basis for how the scheduler chooses - * what request to process next. Anticipation works on top of this. - */ -static struct as_rq *as_find_next_arq(struct as_data *ad, struct as_rq *last) -{ - const int data_dir = last->is_sync; - struct as_rq *ret; - struct rb_node *rbnext = rb_next(&last->rb_node); - struct rb_node *rbprev = rb_prev(&last->rb_node); - struct as_rq *arq_next, *arq_prev; - - BUG_ON(!ON_RB(&last->rb_node)); - - if (rbprev) - arq_prev = rb_entry_arq(rbprev); - else - arq_prev = NULL; - - if (rbnext) - arq_next = rb_entry_arq(rbnext); - else { - arq_next = as_find_first_arq(ad, data_dir); - if (arq_next == last) - arq_next = NULL; - } - - ret = as_choose_req(ad, arq_next, arq_prev); - - return ret; -} - -/* - * anticipatory scheduling functions follow - */ - -/* - * as_antic_expired tells us when we have anticipated too long. - * The funny "absolute difference" math on the elapsed time is to handle - * jiffy wraps, and disks which have been idle for 0x80000000 jiffies. - */ -static int as_antic_expired(struct as_data *ad) -{ - long delta_jif; - - delta_jif = jiffies - ad->antic_start; - if (unlikely(delta_jif < 0)) - delta_jif = -delta_jif; - if (delta_jif < ad->antic_expire) - return 0; - - return 1; -} - -/* - * as_antic_waitnext starts anticipating that a nice request will soon be - * submitted. See also as_antic_waitreq - */ -static void as_antic_waitnext(struct as_data *ad) -{ - unsigned long timeout; - - BUG_ON(ad->antic_status != ANTIC_OFF - && ad->antic_status != ANTIC_WAIT_REQ); - - timeout = ad->antic_start + ad->antic_expire; - - mod_timer(&ad->antic_timer, timeout); - - ad->antic_status = ANTIC_WAIT_NEXT; -} - -/* - * as_antic_waitreq starts anticipating. We don't start timing the anticipation - * until the request that we're anticipating on has finished. This means we - * are timing from when the candidate process wakes up hopefully. - */ -static void as_antic_waitreq(struct as_data *ad) -{ - BUG_ON(ad->antic_status == ANTIC_FINISHED); - if (ad->antic_status == ANTIC_OFF) { - if (!ad->io_context || ad->ioc_finished) - as_antic_waitnext(ad); - else - ad->antic_status = ANTIC_WAIT_REQ; - } -} - -/* - * This is called directly by the functions in this file to stop anticipation. - * We kill the timer and schedule a call to the request_fn asap. - */ -static void as_antic_stop(struct as_data *ad) -{ - int status = ad->antic_status; - - if (status == ANTIC_WAIT_REQ || status == ANTIC_WAIT_NEXT) { - if (status == ANTIC_WAIT_NEXT) - del_timer(&ad->antic_timer); - ad->antic_status = ANTIC_FINISHED; - /* see as_work_handler */ - kblockd_schedule_work(&ad->antic_work); - } -} - -/* - * as_antic_timeout is the timer function set by as_antic_waitnext. - */ -static void as_antic_timeout(unsigned long data) -{ - struct request_queue *q = (struct request_queue *)data; - struct as_data *ad = q->elevator->elevator_data; - unsigned long flags; - - spin_lock_irqsave(q->queue_lock, flags); - if (ad->antic_status == ANTIC_WAIT_REQ - || ad->antic_status == ANTIC_WAIT_NEXT) { - struct as_io_context *aic = ad->io_context->aic; - - ad->antic_status = ANTIC_FINISHED; - kblockd_schedule_work(&ad->antic_work); - - if (aic->ttime_samples == 0) { - /* process anticipated on has exitted or timed out*/ - ad->exit_prob = (7*ad->exit_prob + 256)/8; - } - } - spin_unlock_irqrestore(q->queue_lock, flags); -} - -/* - * as_close_req decides if one request is considered "close" to the - * previous one issued. - */ -static int as_close_req(struct as_data *ad, struct as_rq *arq) -{ - unsigned long delay; /* milliseconds */ - sector_t last = ad->last_sector[ad->batch_data_dir]; - sector_t next = arq->request->sector; - sector_t delta; /* acceptable close offset (in sectors) */ - - if (ad->antic_status == ANTIC_OFF || !ad->ioc_finished) - delay = 0; - else - delay = ((jiffies - ad->antic_start) * 1000) / HZ; - - if (delay <= 1) - delta = 64; - else if (delay <= 20 && delay <= ad->antic_expire) - delta = 64 << (delay-1); - else - return 1; - - return (last - (delta>>1) <= next) && (next <= last + delta); -} - -/* - * as_can_break_anticipation returns true if we have been anticipating this - * request. - * - * It also returns true if the process against which we are anticipating - * submits a write - that's presumably an fsync, O_SYNC write, etc. We want to - * dispatch it ASAP, because we know that application will not be submitting - * any new reads. - * - * If the task which has submitted the request has exitted, break anticipation. - * - * If this task has queued some other IO, do not enter enticipation. - */ -static int as_can_break_anticipation(struct as_data *ad, struct as_rq *arq) -{ - struct io_context *ioc; - struct as_io_context *aic; - sector_t s; - - ioc = ad->io_context; - BUG_ON(!ioc); - - if (arq && ioc == arq->io_context) { - /* request from same process */ - return 1; - } - - if (ad->ioc_finished && as_antic_expired(ad)) { - /* - * In this situation status should really be FINISHED, - * however the timer hasn't had the chance to run yet. - */ - return 1; - } - - aic = ioc->aic; - if (!aic) - return 0; - - if (!test_bit(AS_TASK_RUNNING, &aic->state)) { - /* process anticipated on has exitted */ - if (aic->ttime_samples == 0) - ad->exit_prob = (7*ad->exit_prob + 256)/8; - return 1; - } - - if (atomic_read(&aic->nr_queued) > 0) { - /* process has more requests queued */ - return 1; - } - - if (atomic_read(&aic->nr_dispatched) > 0) { - /* process has more requests dispatched */ - return 1; - } - - if (arq && arq->is_sync == REQ_SYNC && as_close_req(ad, arq)) { - /* - * Found a close request that is not one of ours. - * - * This makes close requests from another process reset - * our thinktime delay. Is generally useful when there are - * two or more cooperating processes working in the same - * area. - */ - spin_lock(&aic->lock); - aic->last_end_request = jiffies; - spin_unlock(&aic->lock); - return 1; - } - - - if (aic->ttime_samples == 0) { - if (ad->new_ttime_mean > ad->antic_expire) - return 1; - if (ad->exit_prob > 128) - return 1; - } else if (aic->ttime_mean > ad->antic_expire) { - /* the process thinks too much between requests */ - return 1; - } - - if (!arq) - return 0; - - if (ad->last_sector[REQ_SYNC] < arq->request->sector) - s = arq->request->sector - ad->last_sector[REQ_SYNC]; - else - s = ad->last_sector[REQ_SYNC] - arq->request->sector; - - if (aic->seek_samples == 0) { - /* - * Process has just started IO. Use past statistics to - * guage success possibility - */ - if (ad->new_seek_mean > s) { - /* this request is better than what we're expecting */ - return 1; - } - - } else { - if (aic->seek_mean > s) { - /* this request is better than what we're expecting */ - return 1; - } - } - - return 0; -} - -/* - * as_can_anticipate indicates weather we should either run arq - * or keep anticipating a better request. - */ -static int as_can_anticipate(struct as_data *ad, struct as_rq *arq) -{ - if (!ad->io_context) - /* - * Last request submitted was a write - */ - return 0; - - if (ad->antic_status == ANTIC_FINISHED) - /* - * Don't restart if we have just finished. Run the next request - */ - return 0; - - if (as_can_break_anticipation(ad, arq)) - /* - * This request is a good candidate. Don't keep anticipating, - * run it. - */ - return 0; - - /* - * OK from here, we haven't finished, and don't have a decent request! - * Status is either ANTIC_OFF so start waiting, - * ANTIC_WAIT_REQ so continue waiting for request to finish - * or ANTIC_WAIT_NEXT so continue waiting for an acceptable request. - * - */ - - return 1; -} - -static void as_update_thinktime(struct as_data *ad, struct as_io_context *aic, unsigned long ttime) -{ - /* fixed point: 1.0 == 1<<8 */ - if (aic->ttime_samples == 0) { - ad->new_ttime_total = (7*ad->new_ttime_total + 256*ttime) / 8; - ad->new_ttime_mean = ad->new_ttime_total / 256; - - ad->exit_prob = (7*ad->exit_prob)/8; - } - aic->ttime_samples = (7*aic->ttime_samples + 256) / 8; - aic->ttime_total = (7*aic->ttime_total + 256*ttime) / 8; - aic->ttime_mean = (aic->ttime_total + 128) / aic->ttime_samples; -} - -static void as_update_seekdist(struct as_data *ad, struct as_io_context *aic, sector_t sdist) -{ - u64 total; - - if (aic->seek_samples == 0) { - ad->new_seek_total = (7*ad->new_seek_total + 256*(u64)sdist)/8; - ad->new_seek_mean = ad->new_seek_total / 256; - } - - /* - * Don't allow the seek distance to get too large from the - * odd fragment, pagein, etc - */ - if (aic->seek_samples <= 60) /* second&third seek */ - sdist = min(sdist, (aic->seek_mean * 4) + 2*1024*1024); - else - sdist = min(sdist, (aic->seek_mean * 4) + 2*1024*64); - - aic->seek_samples = (7*aic->seek_samples + 256) / 8; - aic->seek_total = (7*aic->seek_total + (u64)256*sdist) / 8; - total = aic->seek_total + (aic->seek_samples/2); - do_div(total, aic->seek_samples); - aic->seek_mean = (sector_t)total; -} - -/* - * as_update_iohist keeps a decaying histogram of IO thinktimes, and - * updates @aic->ttime_mean based on that. It is called when a new - * request is queued. - */ -static void as_update_iohist(struct as_data *ad, struct as_io_context *aic, struct request *rq) -{ - struct as_rq *arq = RQ_DATA(rq); - int data_dir = arq->is_sync; - unsigned long thinktime; - sector_t seek_dist; - - if (aic == NULL) - return; - - if (data_dir == REQ_SYNC) { - unsigned long in_flight = atomic_read(&aic->nr_queued) - + atomic_read(&aic->nr_dispatched); - spin_lock(&aic->lock); - if (test_bit(AS_TASK_IORUNNING, &aic->state) || - test_bit(AS_TASK_IOSTARTED, &aic->state)) { - /* Calculate read -> read thinktime */ - if (test_bit(AS_TASK_IORUNNING, &aic->state) - && in_flight == 0) { - thinktime = jiffies - aic->last_end_request; - thinktime = min(thinktime, MAX_THINKTIME-1); - } else - thinktime = 0; - as_update_thinktime(ad, aic, thinktime); - - /* Calculate read -> read seek distance */ - if (aic->last_request_pos < rq->sector) - seek_dist = rq->sector - aic->last_request_pos; - else - seek_dist = aic->last_request_pos - rq->sector; - as_update_seekdist(ad, aic, seek_dist); - } - aic->last_request_pos = rq->sector + rq->nr_sectors; - set_bit(AS_TASK_IOSTARTED, &aic->state); - spin_unlock(&aic->lock); - } -} - -/* - * as_update_arq must be called whenever a request (arq) is added to - * the sort_list. This function keeps caches up to date, and checks if the - * request might be one we are "anticipating" - */ -static void as_update_arq(struct as_data *ad, struct as_rq *arq) -{ - const int data_dir = arq->is_sync; - - /* keep the next_arq cache up to date */ - ad->next_arq[data_dir] = as_choose_req(ad, arq, ad->next_arq[data_dir]); - - /* - * have we been anticipating this request? - * or does it come from the same process as the one we are anticipating - * for? - */ - if (ad->antic_status == ANTIC_WAIT_REQ - || ad->antic_status == ANTIC_WAIT_NEXT) { - if (as_can_break_anticipation(ad, arq)) - as_antic_stop(ad); - } -} - -/* - * Gathers timings and resizes the write batch automatically - */ -static void update_write_batch(struct as_data *ad) -{ - unsigned long batch = ad->batch_expire[REQ_ASYNC]; - long write_time; - - write_time = (jiffies - ad->current_batch_expires) + batch; - if (write_time < 0) - write_time = 0; - - if (write_time > batch && !ad->write_batch_idled) { - if (write_time > batch * 3) - ad->write_batch_count /= 2; - else - ad->write_batch_count--; - } else if (write_time < batch && ad->current_write_count == 0) { - if (batch > write_time * 3) - ad->write_batch_count *= 2; - else - ad->write_batch_count++; - } - - if (ad->write_batch_count < 1) - ad->write_batch_count = 1; -} - -/* - * as_completed_request is to be called when a request has completed and - * returned something to the requesting process, be it an error or data. - */ -static void as_completed_request(request_queue_t *q, struct request *rq) -{ - struct as_data *ad = q->elevator->elevator_data; - struct as_rq *arq = RQ_DATA(rq); - - WARN_ON(!list_empty(&rq->queuelist)); - - if (arq->state != AS_RQ_REMOVED) { - printk("arq->state %d\n", arq->state); - WARN_ON(1); - goto out; - } - - if (ad->changed_batch && ad->nr_dispatched == 1) { - kblockd_schedule_work(&ad->antic_work); - ad->changed_batch = 0; - - if (ad->batch_data_dir == REQ_SYNC) - ad->new_batch = 1; - } - WARN_ON(ad->nr_dispatched == 0); - ad->nr_dispatched--; - - /* - * Start counting the batch from when a request of that direction is - * actually serviced. This should help devices with big TCQ windows - * and writeback caches - */ - if (ad->new_batch && ad->batch_data_dir == arq->is_sync) { - update_write_batch(ad); - ad->current_batch_expires = jiffies + - ad->batch_expire[REQ_SYNC]; - ad->new_batch = 0; - } - - if (ad->io_context == arq->io_context && ad->io_context) { - ad->antic_start = jiffies; - ad->ioc_finished = 1; - if (ad->antic_status == ANTIC_WAIT_REQ) { - /* - * We were waiting on this request, now anticipate - * the next one - */ - as_antic_waitnext(ad); - } - } - - as_put_io_context(arq); -out: - arq->state = AS_RQ_POSTSCHED; -} - -/* - * as_remove_queued_request removes a request from the pre dispatch queue - * without updating refcounts. It is expected the caller will drop the - * reference unless it replaces the request at somepart of the elevator - * (ie. the dispatch queue) - */ -static void as_remove_queued_request(request_queue_t *q, struct request *rq) -{ - struct as_rq *arq = RQ_DATA(rq); - const int data_dir = arq->is_sync; - struct as_data *ad = q->elevator->elevator_data; - - WARN_ON(arq->state != AS_RQ_QUEUED); - - if (arq->io_context && arq->io_context->aic) { - BUG_ON(!atomic_read(&arq->io_context->aic->nr_queued)); - atomic_dec(&arq->io_context->aic->nr_queued); - } - - /* - * Update the "next_arq" cache if we are about to remove its - * entry - */ - if (ad->next_arq[data_dir] == arq) - ad->next_arq[data_dir] = as_find_next_arq(ad, arq); - - list_del_init(&arq->fifo); - as_del_arq_hash(arq); - as_del_arq_rb(ad, arq); -} - -/* - * as_fifo_expired returns 0 if there are no expired reads on the fifo, - * 1 otherwise. It is ratelimited so that we only perform the check once per - * `fifo_expire' interval. Otherwise a large number of expired requests - * would create a hopeless seekstorm. - * - * See as_antic_expired comment. - */ -static int as_fifo_expired(struct as_data *ad, int adir) -{ - struct as_rq *arq; - long delta_jif; - - delta_jif = jiffies - ad->last_check_fifo[adir]; - if (unlikely(delta_jif < 0)) - delta_jif = -delta_jif; - if (delta_jif < ad->fifo_expire[adir]) - return 0; - - ad->last_check_fifo[adir] = jiffies; - - if (list_empty(&ad->fifo_list[adir])) - return 0; - - arq = list_entry_fifo(ad->fifo_list[adir].next); - - return time_after(jiffies, arq->expires); -} - -/* - * as_batch_expired returns true if the current batch has expired. A batch - * is a set of reads or a set of writes. - */ -static inline int as_batch_expired(struct as_data *ad) -{ - if (ad->changed_batch || ad->new_batch) - return 0; - - if (ad->batch_data_dir == REQ_SYNC) - /* TODO! add a check so a complete fifo gets written? */ - return time_after(jiffies, ad->current_batch_expires); - - return time_after(jiffies, ad->current_batch_expires) - || ad->current_write_count == 0; -} - -/* - * move an entry to dispatch queue - */ -static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq) -{ - struct request *rq = arq->request; - const int data_dir = arq->is_sync; - - BUG_ON(!ON_RB(&arq->rb_node)); - - as_antic_stop(ad); - ad->antic_status = ANTIC_OFF; - - /* - * This has to be set in order to be correctly updated by - * as_find_next_arq - */ - ad->last_sector[data_dir] = rq->sector + rq->nr_sectors; - - if (data_dir == REQ_SYNC) { - /* In case we have to anticipate after this */ - copy_io_context(&ad->io_context, &arq->io_context); - } else { - if (ad->io_context) { - put_io_context(ad->io_context); - ad->io_context = NULL; - } - - if (ad->current_write_count != 0) - ad->current_write_count--; - } - ad->ioc_finished = 0; - - ad->next_arq[data_dir] = as_find_next_arq(ad, arq); - - /* - * take it off the sort and fifo list, add to dispatch queue - */ - while (!list_empty(&rq->queuelist)) { - struct request *__rq = list_entry_rq(rq->queuelist.next); - struct as_rq *__arq = RQ_DATA(__rq); - - list_del(&__rq->queuelist); - - elv_dispatch_add_tail(ad->q, __rq); - - if (__arq->io_context && __arq->io_context->aic) - atomic_inc(&__arq->io_context->aic->nr_dispatched); - - WARN_ON(__arq->state != AS_RQ_QUEUED); - __arq->state = AS_RQ_DISPATCHED; - - ad->nr_dispatched++; - } - - as_remove_queued_request(ad->q, rq); - WARN_ON(arq->state != AS_RQ_QUEUED); - - elv_dispatch_sort(ad->q, rq); - - arq->state = AS_RQ_DISPATCHED; - if (arq->io_context && arq->io_context->aic) - atomic_inc(&arq->io_context->aic->nr_dispatched); - ad->nr_dispatched++; -} - -/* - * as_dispatch_request selects the best request according to - * read/write expire, batch expire, etc, and moves it to the dispatch - * queue. Returns 1 if a request was found, 0 otherwise. - */ -static int as_dispatch_request(request_queue_t *q, int force) -{ - struct as_data *ad = q->elevator->elevator_data; - struct as_rq *arq; - const int reads = !list_empty(&ad->fifo_list[REQ_SYNC]); - const int writes = !list_empty(&ad->fifo_list[REQ_ASYNC]); - - if (unlikely(force)) { - /* - * Forced dispatch, accounting is useless. Reset - * accounting states and dump fifo_lists. Note that - * batch_data_dir is reset to REQ_SYNC to avoid - * screwing write batch accounting as write batch - * accounting occurs on W->R transition. - */ - int dispatched = 0; - - ad->batch_data_dir = REQ_SYNC; - ad->changed_batch = 0; - ad->new_batch = 0; - - while (ad->next_arq[REQ_SYNC]) { - as_move_to_dispatch(ad, ad->next_arq[REQ_SYNC]); - dispatched++; - } - ad->last_check_fifo[REQ_SYNC] = jiffies; - - while (ad->next_arq[REQ_ASYNC]) { - as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]); - dispatched++; - } - ad->last_check_fifo[REQ_ASYNC] = jiffies; - - return dispatched; - } - - /* Signal that the write batch was uncontended, so we can't time it */ - if (ad->batch_data_dir == REQ_ASYNC && !reads) { - if (ad->current_write_count == 0 || !writes) - ad->write_batch_idled = 1; - } - - if (!(reads || writes) - || ad->antic_status == ANTIC_WAIT_REQ - || ad->antic_status == ANTIC_WAIT_NEXT - || ad->changed_batch) - return 0; - - if (!(reads && writes && as_batch_expired(ad)) ) { - /* - * batch is still running or no reads or no writes - */ - arq = ad->next_arq[ad->batch_data_dir]; - - if (ad->batch_data_dir == REQ_SYNC && ad->antic_expire) { - if (as_fifo_expired(ad, REQ_SYNC)) - goto fifo_expired; - - if (as_can_anticipate(ad, arq)) { - as_antic_waitreq(ad); - return 0; - } - } - - if (arq) { - /* we have a "next request" */ - if (reads && !writes) - ad->current_batch_expires = - jiffies + ad->batch_expire[REQ_SYNC]; - goto dispatch_request; - } - } - - /* - * at this point we are not running a batch. select the appropriate - * data direction (read / write) - */ - - if (reads) { - BUG_ON(RB_EMPTY(&ad->sort_list[REQ_SYNC])); - - if (writes && ad->batch_data_dir == REQ_SYNC) - /* - * Last batch was a read, switch to writes - */ - goto dispatch_writes; - - if (ad->batch_data_dir == REQ_ASYNC) { - WARN_ON(ad->new_batch); - ad->changed_batch = 1; - } - ad->batch_data_dir = REQ_SYNC; - arq = list_entry_fifo(ad->fifo_list[ad->batch_data_dir].next); - ad->last_check_fifo[ad->batch_data_dir] = jiffies; - goto dispatch_request; - } - - /* - * the last batch was a read - */ - - if (writes) { -dispatch_writes: - BUG_ON(RB_EMPTY(&ad->sort_list[REQ_ASYNC])); - - if (ad->batch_data_dir == REQ_SYNC) { - ad->changed_batch = 1; - - /* - * new_batch might be 1 when the queue runs out of - * reads. A subsequent submission of a write might - * cause a change of batch before the read is finished. - */ - ad->new_batch = 0; - } - ad->batch_data_dir = REQ_ASYNC; - ad->current_write_count = ad->write_batch_count; - ad->write_batch_idled = 0; - arq = ad->next_arq[ad->batch_data_dir]; - goto dispatch_request; - } - - BUG(); - return 0; - -dispatch_request: - /* - * If a request has expired, service it. - */ - - if (as_fifo_expired(ad, ad->batch_data_dir)) { -fifo_expired: - arq = list_entry_fifo(ad->fifo_list[ad->batch_data_dir].next); - BUG_ON(arq == NULL); - } - - if (ad->changed_batch) { - WARN_ON(ad->new_batch); - - if (ad->nr_dispatched) - return 0; - - if (ad->batch_data_dir == REQ_ASYNC) - ad->current_batch_expires = jiffies + - ad->batch_expire[REQ_ASYNC]; - else - ad->new_batch = 1; - - ad->changed_batch = 0; - } - - /* - * arq is the selected appropriate request. - */ - as_move_to_dispatch(ad, arq); - - return 1; -} - -/* - * Add arq to a list behind alias - */ -static inline void -as_add_aliased_request(struct as_data *ad, struct as_rq *arq, struct as_rq *alias) -{ - struct request *req = arq->request; - struct list_head *insert = alias->request->queuelist.prev; - - /* - * Transfer list of aliases - */ - while (!list_empty(&req->queuelist)) { - struct request *__rq = list_entry_rq(req->queuelist.next); - struct as_rq *__arq = RQ_DATA(__rq); - - list_move_tail(&__rq->queuelist, &alias->request->queuelist); - - WARN_ON(__arq->state != AS_RQ_QUEUED); - } - - /* - * Another request with the same start sector on the rbtree. - * Link this request to that sector. They are untangled in - * as_move_to_dispatch - */ - list_add(&arq->request->queuelist, insert); - - /* - * Don't want to have to handle merges. - */ - as_del_arq_hash(arq); - arq->request->flags |= REQ_NOMERGE; -} - -/* - * add arq to rbtree and fifo - */ -static void as_add_request(request_queue_t *q, struct request *rq) -{ - struct as_data *ad = q->elevator->elevator_data; - struct as_rq *arq = RQ_DATA(rq); - struct as_rq *alias; - int data_dir; - - if (arq->state != AS_RQ_PRESCHED) { - printk("arq->state: %d\n", arq->state); - WARN_ON(1); - } - arq->state = AS_RQ_NEW; - - if (rq_data_dir(arq->request) == READ - || current->flags&PF_SYNCWRITE) - arq->is_sync = 1; - else - arq->is_sync = 0; - data_dir = arq->is_sync; - - arq->io_context = as_get_io_context(); - - if (arq->io_context) { - as_update_iohist(ad, arq->io_context->aic, arq->request); - atomic_inc(&arq->io_context->aic->nr_queued); - } - - alias = as_add_arq_rb(ad, arq); - if (!alias) { - /* - * set expire time (only used for reads) and add to fifo list - */ - arq->expires = jiffies + ad->fifo_expire[data_dir]; - list_add_tail(&arq->fifo, &ad->fifo_list[data_dir]); - - if (rq_mergeable(arq->request)) - as_add_arq_hash(ad, arq); - as_update_arq(ad, arq); /* keep state machine up to date */ - - } else { - as_add_aliased_request(ad, arq, alias); - - /* - * have we been anticipating this request? - * or does it come from the same process as the one we are - * anticipating for? - */ - if (ad->antic_status == ANTIC_WAIT_REQ - || ad->antic_status == ANTIC_WAIT_NEXT) { - if (as_can_break_anticipation(ad, arq)) - as_antic_stop(ad); - } - } - - arq->state = AS_RQ_QUEUED; -} - -static void as_activate_request(request_queue_t *q, struct request *rq) -{ - struct as_rq *arq = RQ_DATA(rq); - - WARN_ON(arq->state != AS_RQ_DISPATCHED); - arq->state = AS_RQ_REMOVED; - if (arq->io_context && arq->io_context->aic) - atomic_dec(&arq->io_context->aic->nr_dispatched); -} - -static void as_deactivate_request(request_queue_t *q, struct request *rq) -{ - struct as_rq *arq = RQ_DATA(rq); - - WARN_ON(arq->state != AS_RQ_REMOVED); - arq->state = AS_RQ_DISPATCHED; - if (arq->io_context && arq->io_context->aic) - atomic_inc(&arq->io_context->aic->nr_dispatched); -} - -/* - * as_queue_empty tells us if there are requests left in the device. It may - * not be the case that a driver can get the next request even if the queue - * is not empty - it is used in the block layer to check for plugging and - * merging opportunities - */ -static int as_queue_empty(request_queue_t *q) -{ - struct as_data *ad = q->elevator->elevator_data; - - return list_empty(&ad->fifo_list[REQ_ASYNC]) - && list_empty(&ad->fifo_list[REQ_SYNC]); -} - -static struct request * -as_former_request(request_queue_t *q, struct request *rq) -{ - struct as_rq *arq = RQ_DATA(rq); - struct rb_node *rbprev = rb_prev(&arq->rb_node); - struct request *ret = NULL; - - if (rbprev) - ret = rb_entry_arq(rbprev)->request; - - return ret; -} - -static struct request * -as_latter_request(request_queue_t *q, struct request *rq) -{ - struct as_rq *arq = RQ_DATA(rq); - struct rb_node *rbnext = rb_next(&arq->rb_node); - struct request *ret = NULL; - - if (rbnext) - ret = rb_entry_arq(rbnext)->request; - - return ret; -} - -static int -as_merge(request_queue_t *q, struct request **req, struct bio *bio) -{ - struct as_data *ad = q->elevator->elevator_data; - sector_t rb_key = bio->bi_sector + bio_sectors(bio); - struct request *__rq; - int ret; - - /* - * see if the merge hash can satisfy a back merge - */ - __rq = as_find_arq_hash(ad, bio->bi_sector); - if (__rq) { - BUG_ON(__rq->sector + __rq->nr_sectors != bio->bi_sector); - - if (elv_rq_merge_ok(__rq, bio)) { - ret = ELEVATOR_BACK_MERGE; - goto out; - } - } - - /* - * check for front merge - */ - __rq = as_find_arq_rb(ad, rb_key, bio_data_dir(bio)); - if (__rq) { - BUG_ON(rb_key != rq_rb_key(__rq)); - - if (elv_rq_merge_ok(__rq, bio)) { - ret = ELEVATOR_FRONT_MERGE; - goto out; - } - } - - return ELEVATOR_NO_MERGE; -out: - if (ret) { - if (rq_mergeable(__rq)) - as_hot_arq_hash(ad, RQ_DATA(__rq)); - } - *req = __rq; - return ret; -} - -static void as_merged_request(request_queue_t *q, struct request *req) -{ - struct as_data *ad = q->elevator->elevator_data; - struct as_rq *arq = RQ_DATA(req); - - /* - * hash always needs to be repositioned, key is end sector - */ - as_del_arq_hash(arq); - as_add_arq_hash(ad, arq); - - /* - * if the merge was a front merge, we need to reposition request - */ - if (rq_rb_key(req) != arq->rb_key) { - struct as_rq *alias, *next_arq = NULL; - - if (ad->next_arq[arq->is_sync] == arq) - next_arq = as_find_next_arq(ad, arq); - - /* - * Note! We should really be moving any old aliased requests - * off this request and try to insert them into the rbtree. We - * currently don't bother. Ditto the next function. - */ - as_del_arq_rb(ad, arq); - if ((alias = as_add_arq_rb(ad, arq)) ) { - list_del_init(&arq->fifo); - as_add_aliased_request(ad, arq, alias); - if (next_arq) - ad->next_arq[arq->is_sync] = next_arq; - } - /* - * Note! At this stage of this and the next function, our next - * request may not be optimal - eg the request may have "grown" - * behind the disk head. We currently don't bother adjusting. - */ - } -} - -static void -as_merged_requests(request_queue_t *q, struct request *req, - struct request *next) -{ - struct as_data *ad = q->elevator->elevator_data; - struct as_rq *arq = RQ_DATA(req); - struct as_rq *anext = RQ_DATA(next); - - BUG_ON(!arq); - BUG_ON(!anext); - - /* - * reposition arq (this is the merged request) in hash, and in rbtree - * in case of a front merge - */ - as_del_arq_hash(arq); - as_add_arq_hash(ad, arq); - - if (rq_rb_key(req) != arq->rb_key) { - struct as_rq *alias, *next_arq = NULL; - - if (ad->next_arq[arq->is_sync] == arq) - next_arq = as_find_next_arq(ad, arq); - - as_del_arq_rb(ad, arq); - if ((alias = as_add_arq_rb(ad, arq)) ) { - list_del_init(&arq->fifo); - as_add_aliased_request(ad, arq, alias); - if (next_arq) - ad->next_arq[arq->is_sync] = next_arq; - } - } - - /* - * if anext expires before arq, assign its expire time to arq - * and move into anext position (anext will be deleted) in fifo - */ - if (!list_empty(&arq->fifo) && !list_empty(&anext->fifo)) { - if (time_before(anext->expires, arq->expires)) { - list_move(&arq->fifo, &anext->fifo); - arq->expires = anext->expires; - /* - * Don't copy here but swap, because when anext is - * removed below, it must contain the unused context - */ - swap_io_context(&arq->io_context, &anext->io_context); - } - } - - /* - * Transfer list of aliases - */ - while (!list_empty(&next->queuelist)) { - struct request *__rq = list_entry_rq(next->queuelist.next); - struct as_rq *__arq = RQ_DATA(__rq); - - list_move_tail(&__rq->queuelist, &req->queuelist); - - WARN_ON(__arq->state != AS_RQ_QUEUED); - } - - /* - * kill knowledge of next, this one is a goner - */ - as_remove_queued_request(q, next); - as_put_io_context(anext); - - anext->state = AS_RQ_MERGED; -} - -/* - * This is executed in a "deferred" process context, by kblockd. It calls the - * driver's request_fn so the driver can submit that request. - * - * IMPORTANT! This guy will reenter the elevator, so set up all queue global - * state before calling, and don't rely on any state over calls. - * - * FIXME! dispatch queue is not a queue at all! - */ -static void as_work_handler(void *data) -{ - struct request_queue *q = data; - unsigned long flags; - - spin_lock_irqsave(q->queue_lock, flags); - if (!as_queue_empty(q)) - q->request_fn(q); - spin_unlock_irqrestore(q->queue_lock, flags); -} - -static void as_put_request(request_queue_t *q, struct request *rq) -{ - struct as_data *ad = q->elevator->elevator_data; - struct as_rq *arq = RQ_DATA(rq); - - if (!arq) { - WARN_ON(1); - return; - } - - if (unlikely(arq->state != AS_RQ_POSTSCHED && - arq->state != AS_RQ_PRESCHED && - arq->state != AS_RQ_MERGED)) { - printk("arq->state %d\n", arq->state); - WARN_ON(1); - } - - mempool_free(arq, ad->arq_pool); - rq->elevator_private = NULL; -} - -static int as_set_request(request_queue_t *q, struct request *rq, - struct bio *bio, gfp_t gfp_mask) -{ - struct as_data *ad = q->elevator->elevator_data; - struct as_rq *arq = mempool_alloc(ad->arq_pool, gfp_mask); - - if (arq) { - memset(arq, 0, sizeof(*arq)); - RB_CLEAR(&arq->rb_node); - arq->request = rq; - arq->state = AS_RQ_PRESCHED; - arq->io_context = NULL; - INIT_LIST_HEAD(&arq->hash); - arq->on_hash = 0; - INIT_LIST_HEAD(&arq->fifo); - rq->elevator_private = arq; - return 0; - } - - return 1; -} - -static int as_may_queue(request_queue_t *q, int rw, struct bio *bio) -{ - int ret = ELV_MQUEUE_MAY; - struct as_data *ad = q->elevator->elevator_data; - struct io_context *ioc; - if (ad->antic_status == ANTIC_WAIT_REQ || - ad->antic_status == ANTIC_WAIT_NEXT) { - ioc = as_get_io_context(); - if (ad->io_context == ioc) - ret = ELV_MQUEUE_MUST; - put_io_context(ioc); - } - - return ret; -} - -static void as_exit_queue(elevator_t *e) -{ - struct as_data *ad = e->elevator_data; - - del_timer_sync(&ad->antic_timer); - kblockd_flush(); - - BUG_ON(!list_empty(&ad->fifo_list[REQ_SYNC])); - BUG_ON(!list_empty(&ad->fifo_list[REQ_ASYNC])); - - mempool_destroy(ad->arq_pool); - put_io_context(ad->io_context); - kfree(ad->hash); - kfree(ad); -} - -/* - * initialize elevator private data (as_data), and alloc a arq for - * each request on the free lists - */ -static int as_init_queue(request_queue_t *q, elevator_t *e) -{ - struct as_data *ad; - int i; - - if (!arq_pool) - return -ENOMEM; - - ad = kmalloc_node(sizeof(*ad), GFP_KERNEL, q->node); - if (!ad) - return -ENOMEM; - memset(ad, 0, sizeof(*ad)); - - ad->q = q; /* Identify what queue the data belongs to */ - - ad->hash = kmalloc_node(sizeof(struct list_head)*AS_HASH_ENTRIES, - GFP_KERNEL, q->node); - if (!ad->hash) { - kfree(ad); - return -ENOMEM; - } - - ad->arq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab, - mempool_free_slab, arq_pool, q->node); - if (!ad->arq_pool) { - kfree(ad->hash); - kfree(ad); - return -ENOMEM; - } - - /* anticipatory scheduling helpers */ - ad->antic_timer.function = as_antic_timeout; - ad->antic_timer.data = (unsigned long)q; - init_timer(&ad->antic_timer); - INIT_WORK(&ad->antic_work, as_work_handler, q); - - for (i = 0; i < AS_HASH_ENTRIES; i++) - INIT_LIST_HEAD(&ad->hash[i]); - - INIT_LIST_HEAD(&ad->fifo_list[REQ_SYNC]); - INIT_LIST_HEAD(&ad->fifo_list[REQ_ASYNC]); - ad->sort_list[REQ_SYNC] = RB_ROOT; - ad->sort_list[REQ_ASYNC] = RB_ROOT; - ad->fifo_expire[REQ_SYNC] = default_read_expire; - ad->fifo_expire[REQ_ASYNC] = default_write_expire; - ad->antic_expire = default_antic_expire; - ad->batch_expire[REQ_SYNC] = default_read_batch_expire; - ad->batch_expire[REQ_ASYNC] = default_write_batch_expire; - e->elevator_data = ad; - - ad->current_batch_expires = jiffies + ad->batch_expire[REQ_SYNC]; - ad->write_batch_count = ad->batch_expire[REQ_ASYNC] / 10; - if (ad->write_batch_count < 2) - ad->write_batch_count = 2; - - return 0; -} - -/* - * sysfs parts below - */ -struct as_fs_entry { - struct attribute attr; - ssize_t (*show)(struct as_data *, char *); - ssize_t (*store)(struct as_data *, const char *, size_t); -}; - -static ssize_t -as_var_show(unsigned int var, char *page) -{ - return sprintf(page, "%d\n", var); -} - -static ssize_t -as_var_store(unsigned long *var, const char *page, size_t count) -{ - char *p = (char *) page; - - *var = simple_strtoul(p, &p, 10); - return count; -} - -static ssize_t as_est_show(struct as_data *ad, char *page) -{ - int pos = 0; - - pos += sprintf(page+pos, "%lu %% exit probability\n", 100*ad->exit_prob/256); - pos += sprintf(page+pos, "%lu ms new thinktime\n", ad->new_ttime_mean); - pos += sprintf(page+pos, "%llu sectors new seek distance\n", (unsigned long long)ad->new_seek_mean); - - return pos; -} - -#define SHOW_FUNCTION(__FUNC, __VAR) \ -static ssize_t __FUNC(struct as_data *ad, char *page) \ -{ \ - return as_var_show(jiffies_to_msecs((__VAR)), (page)); \ -} -SHOW_FUNCTION(as_readexpire_show, ad->fifo_expire[REQ_SYNC]); -SHOW_FUNCTION(as_writeexpire_show, ad->fifo_expire[REQ_ASYNC]); -SHOW_FUNCTION(as_anticexpire_show, ad->antic_expire); -SHOW_FUNCTION(as_read_batchexpire_show, ad->batch_expire[REQ_SYNC]); -SHOW_FUNCTION(as_write_batchexpire_show, ad->batch_expire[REQ_ASYNC]); -#undef SHOW_FUNCTION - -#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX) \ -static ssize_t __FUNC(struct as_data *ad, const char *page, size_t count) \ -{ \ - int ret = as_var_store(__PTR, (page), count); \ - if (*(__PTR) < (MIN)) \ - *(__PTR) = (MIN); \ - else if (*(__PTR) > (MAX)) \ - *(__PTR) = (MAX); \ - *(__PTR) = msecs_to_jiffies(*(__PTR)); \ - return ret; \ -} -STORE_FUNCTION(as_readexpire_store, &ad->fifo_expire[REQ_SYNC], 0, INT_MAX); -STORE_FUNCTION(as_writeexpire_store, &ad->fifo_expire[REQ_ASYNC], 0, INT_MAX); -STORE_FUNCTION(as_anticexpire_store, &ad->antic_expire, 0, INT_MAX); -STORE_FUNCTION(as_read_batchexpire_store, - &ad->batch_expire[REQ_SYNC], 0, INT_MAX); -STORE_FUNCTION(as_write_batchexpire_store, - &ad->batch_expire[REQ_ASYNC], 0, INT_MAX); -#undef STORE_FUNCTION - -static struct as_fs_entry as_est_entry = { - .attr = {.name = "est_time", .mode = S_IRUGO }, - .show = as_est_show, -}; -static struct as_fs_entry as_readexpire_entry = { - .attr = {.name = "read_expire", .mode = S_IRUGO | S_IWUSR }, - .show = as_readexpire_show, - .store = as_readexpire_store, -}; -static struct as_fs_entry as_writeexpire_entry = { - .attr = {.name = "write_expire", .mode = S_IRUGO | S_IWUSR }, - .show = as_writeexpire_show, - .store = as_writeexpire_store, -}; -static struct as_fs_entry as_anticexpire_entry = { - .attr = {.name = "antic_expire", .mode = S_IRUGO | S_IWUSR }, - .show = as_anticexpire_show, - .store = as_anticexpire_store, -}; -static struct as_fs_entry as_read_batchexpire_entry = { - .attr = {.name = "read_batch_expire", .mode = S_IRUGO | S_IWUSR }, - .show = as_read_batchexpire_show, - .store = as_read_batchexpire_store, -}; -static struct as_fs_entry as_write_batchexpire_entry = { - .attr = {.name = "write_batch_expire", .mode = S_IRUGO | S_IWUSR }, - .show = as_write_batchexpire_show, - .store = as_write_batchexpire_store, -}; - -static struct attribute *default_attrs[] = { - &as_est_entry.attr, - &as_readexpire_entry.attr, - &as_writeexpire_entry.attr, - &as_anticexpire_entry.attr, - &as_read_batchexpire_entry.attr, - &as_write_batchexpire_entry.attr, - NULL, -}; - -#define to_as(atr) container_of((atr), struct as_fs_entry, attr) - -static ssize_t -as_attr_show(struct kobject *kobj, struct attribute *attr, char *page) -{ - elevator_t *e = container_of(kobj, elevator_t, kobj); - struct as_fs_entry *entry = to_as(attr); - - if (!entry->show) - return -EIO; - - return entry->show(e->elevator_data, page); -} - -static ssize_t -as_attr_store(struct kobject *kobj, struct attribute *attr, - const char *page, size_t length) -{ - elevator_t *e = container_of(kobj, elevator_t, kobj); - struct as_fs_entry *entry = to_as(attr); - - if (!entry->store) - return -EIO; - - return entry->store(e->elevator_data, page, length); -} - -static struct sysfs_ops as_sysfs_ops = { - .show = as_attr_show, - .store = as_attr_store, -}; - -static struct kobj_type as_ktype = { - .sysfs_ops = &as_sysfs_ops, - .default_attrs = default_attrs, -}; - -static struct elevator_type iosched_as = { - .ops = { - .elevator_merge_fn = as_merge, - .elevator_merged_fn = as_merged_request, - .elevator_merge_req_fn = as_merged_requests, - .elevator_dispatch_fn = as_dispatch_request, - .elevator_add_req_fn = as_add_request, - .elevator_activate_req_fn = as_activate_request, - .elevator_deactivate_req_fn = as_deactivate_request, - .elevator_queue_empty_fn = as_queue_empty, - .elevator_completed_req_fn = as_completed_request, - .elevator_former_req_fn = as_former_request, - .elevator_latter_req_fn = as_latter_request, - .elevator_set_req_fn = as_set_request, - .elevator_put_req_fn = as_put_request, - .elevator_may_queue_fn = as_may_queue, - .elevator_init_fn = as_init_queue, - .elevator_exit_fn = as_exit_queue, - }, - - .elevator_ktype = &as_ktype, - .elevator_name = "anticipatory", - .elevator_owner = THIS_MODULE, -}; - -static int __init as_init(void) -{ - int ret; - - arq_pool = kmem_cache_create("as_arq", sizeof(struct as_rq), - 0, 0, NULL, NULL); - if (!arq_pool) - return -ENOMEM; - - ret = elv_register(&iosched_as); - if (!ret) { - /* - * don't allow AS to get unregistered, since we would have - * to browse all tasks in the system and release their - * as_io_context first - */ - __module_get(THIS_MODULE); - return 0; - } - - kmem_cache_destroy(arq_pool); - return ret; -} - -static void __exit as_exit(void) -{ - elv_unregister(&iosched_as); - kmem_cache_destroy(arq_pool); -} - -module_init(as_init); -module_exit(as_exit); - -MODULE_AUTHOR("Nick Piggin"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("anticipatory IO scheduler"); diff --git a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c deleted file mode 100644 index ecacca9c877..00000000000 --- a/drivers/block/cfq-iosched.c +++ /dev/null @@ -1,2428 +0,0 @@ -/* - * linux/drivers/block/cfq-iosched.c - * - * CFQ, or complete fairness queueing, disk scheduler. - * - * Based on ideas from a previously unfinished io - * scheduler (round robin per-process disk scheduling) and Andrea Arcangeli. - * - * Copyright (C) 2003 Jens Axboe - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * tunables - */ -static int cfq_quantum = 4; /* max queue in one round of service */ -static int cfq_queued = 8; /* minimum rq allocate limit per-queue*/ -static int cfq_fifo_expire[2] = { HZ / 4, HZ / 8 }; -static int cfq_back_max = 16 * 1024; /* maximum backwards seek, in KiB */ -static int cfq_back_penalty = 2; /* penalty of a backwards seek */ - -static int cfq_slice_sync = HZ / 10; -static int cfq_slice_async = HZ / 25; -static int cfq_slice_async_rq = 2; -static int cfq_slice_idle = HZ / 100; - -#define CFQ_IDLE_GRACE (HZ / 10) -#define CFQ_SLICE_SCALE (5) - -#define CFQ_KEY_ASYNC (0) -#define CFQ_KEY_ANY (0xffff) - -/* - * disable queueing at the driver/hardware level - */ -static int cfq_max_depth = 2; - -/* - * for the hash of cfqq inside the cfqd - */ -#define CFQ_QHASH_SHIFT 6 -#define CFQ_QHASH_ENTRIES (1 << CFQ_QHASH_SHIFT) -#define list_entry_qhash(entry) hlist_entry((entry), struct cfq_queue, cfq_hash) - -/* - * for the hash of crq inside the cfqq - */ -#define CFQ_MHASH_SHIFT 6 -#define CFQ_MHASH_BLOCK(sec) ((sec) >> 3) -#define CFQ_MHASH_ENTRIES (1 << CFQ_MHASH_SHIFT) -#define CFQ_MHASH_FN(sec) hash_long(CFQ_MHASH_BLOCK(sec), CFQ_MHASH_SHIFT) -#define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors) -#define list_entry_hash(ptr) hlist_entry((ptr), struct cfq_rq, hash) - -#define list_entry_cfqq(ptr) list_entry((ptr), struct cfq_queue, cfq_list) -#define list_entry_fifo(ptr) list_entry((ptr), struct request, queuelist) - -#define RQ_DATA(rq) (rq)->elevator_private - -/* - * rb-tree defines - */ -#define RB_NONE (2) -#define RB_EMPTY(node) ((node)->rb_node == NULL) -#define RB_CLEAR_COLOR(node) (node)->rb_color = RB_NONE -#define RB_CLEAR(node) do { \ - (node)->rb_parent = NULL; \ - RB_CLEAR_COLOR((node)); \ - (node)->rb_right = NULL; \ - (node)->rb_left = NULL; \ -} while (0) -#define RB_CLEAR_ROOT(root) ((root)->rb_node = NULL) -#define rb_entry_crq(node) rb_entry((node), struct cfq_rq, rb_node) -#define rq_rb_key(rq) (rq)->sector - -static kmem_cache_t *crq_pool; -static kmem_cache_t *cfq_pool; -static kmem_cache_t *cfq_ioc_pool; - -#define CFQ_PRIO_LISTS IOPRIO_BE_NR -#define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE) -#define cfq_class_be(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_BE) -#define cfq_class_rt(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_RT) - -#define ASYNC (0) -#define SYNC (1) - -#define cfq_cfqq_dispatched(cfqq) \ - ((cfqq)->on_dispatch[ASYNC] + (cfqq)->on_dispatch[SYNC]) - -#define cfq_cfqq_class_sync(cfqq) ((cfqq)->key != CFQ_KEY_ASYNC) - -#define cfq_cfqq_sync(cfqq) \ - (cfq_cfqq_class_sync(cfqq) || (cfqq)->on_dispatch[SYNC]) - -/* - * Per block device queue structure - */ -struct cfq_data { - atomic_t ref; - request_queue_t *queue; - - /* - * rr list of queues with requests and the count of them - */ - struct list_head rr_list[CFQ_PRIO_LISTS]; - struct list_head busy_rr; - struct list_head cur_rr; - struct list_head idle_rr; - unsigned int busy_queues; - - /* - * non-ordered list of empty cfqq's - */ - struct list_head empty_list; - - /* - * cfqq lookup hash - */ - struct hlist_head *cfq_hash; - - /* - * global crq hash for all queues - */ - struct hlist_head *crq_hash; - - unsigned int max_queued; - - mempool_t *crq_pool; - - int rq_in_driver; - - /* - * schedule slice state info - */ - /* - * idle window management - */ - struct timer_list idle_slice_timer; - struct work_struct unplug_work; - - struct cfq_queue *active_queue; - struct cfq_io_context *active_cic; - int cur_prio, cur_end_prio; - unsigned int dispatch_slice; - - struct timer_list idle_class_timer; - - sector_t last_sector; - unsigned long last_end_request; - - unsigned int rq_starved; - - /* - * tunables, see top of file - */ - unsigned int cfq_quantum; - unsigned int cfq_queued; - unsigned int cfq_fifo_expire[2]; - unsigned int cfq_back_penalty; - unsigned int cfq_back_max; - unsigned int cfq_slice[2]; - unsigned int cfq_slice_async_rq; - unsigned int cfq_slice_idle; - unsigned int cfq_max_depth; -}; - -/* - * Per process-grouping structure - */ -struct cfq_queue { - /* reference count */ - atomic_t ref; - /* parent cfq_data */ - struct cfq_data *cfqd; - /* cfqq lookup hash */ - struct hlist_node cfq_hash; - /* hash key */ - unsigned int key; - /* on either rr or empty list of cfqd */ - struct list_head cfq_list; - /* sorted list of pending requests */ - struct rb_root sort_list; - /* if fifo isn't expired, next request to serve */ - struct cfq_rq *next_crq; - /* requests queued in sort_list */ - int queued[2]; - /* currently allocated requests */ - int allocated[2]; - /* fifo list of requests in sort_list */ - struct list_head fifo; - - unsigned long slice_start; - unsigned long slice_end; - unsigned long slice_left; - unsigned long service_last; - - /* number of requests that are on the dispatch list */ - int on_dispatch[2]; - - /* io prio of this group */ - unsigned short ioprio, org_ioprio; - unsigned short ioprio_class, org_ioprio_class; - - /* various state flags, see below */ - unsigned int flags; -}; - -struct cfq_rq { - struct rb_node rb_node; - sector_t rb_key; - struct request *request; - struct hlist_node hash; - - struct cfq_queue *cfq_queue; - struct cfq_io_context *io_context; - - unsigned int crq_flags; -}; - -enum cfqq_state_flags { - CFQ_CFQQ_FLAG_on_rr = 0, - CFQ_CFQQ_FLAG_wait_request, - CFQ_CFQQ_FLAG_must_alloc, - CFQ_CFQQ_FLAG_must_alloc_slice, - CFQ_CFQQ_FLAG_must_dispatch, - CFQ_CFQQ_FLAG_fifo_expire, - CFQ_CFQQ_FLAG_idle_window, - CFQ_CFQQ_FLAG_prio_changed, - CFQ_CFQQ_FLAG_expired, -}; - -#define CFQ_CFQQ_FNS(name) \ -static inline void cfq_mark_cfqq_##name(struct cfq_queue *cfqq) \ -{ \ - cfqq->flags |= (1 << CFQ_CFQQ_FLAG_##name); \ -} \ -static inline void cfq_clear_cfqq_##name(struct cfq_queue *cfqq) \ -{ \ - cfqq->flags &= ~(1 << CFQ_CFQQ_FLAG_##name); \ -} \ -static inline int cfq_cfqq_##name(const struct cfq_queue *cfqq) \ -{ \ - return (cfqq->flags & (1 << CFQ_CFQQ_FLAG_##name)) != 0; \ -} - -CFQ_CFQQ_FNS(on_rr); -CFQ_CFQQ_FNS(wait_request); -CFQ_CFQQ_FNS(must_alloc); -CFQ_CFQQ_FNS(must_alloc_slice); -CFQ_CFQQ_FNS(must_dispatch); -CFQ_CFQQ_FNS(fifo_expire); -CFQ_CFQQ_FNS(idle_window); -CFQ_CFQQ_FNS(prio_changed); -CFQ_CFQQ_FNS(expired); -#undef CFQ_CFQQ_FNS - -enum cfq_rq_state_flags { - CFQ_CRQ_FLAG_is_sync = 0, -}; - -#define CFQ_CRQ_FNS(name) \ -static inline void cfq_mark_crq_##name(struct cfq_rq *crq) \ -{ \ - crq->crq_flags |= (1 << CFQ_CRQ_FLAG_##name); \ -} \ -static inline void cfq_clear_crq_##name(struct cfq_rq *crq) \ -{ \ - crq->crq_flags &= ~(1 << CFQ_CRQ_FLAG_##name); \ -} \ -static inline int cfq_crq_##name(const struct cfq_rq *crq) \ -{ \ - return (crq->crq_flags & (1 << CFQ_CRQ_FLAG_##name)) != 0; \ -} - -CFQ_CRQ_FNS(is_sync); -#undef CFQ_CRQ_FNS - -static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short); -static void cfq_dispatch_insert(request_queue_t *, struct cfq_rq *); -static void cfq_put_cfqd(struct cfq_data *cfqd); - -#define process_sync(tsk) ((tsk)->flags & PF_SYNCWRITE) - -/* - * lots of deadline iosched dupes, can be abstracted later... - */ -static inline void cfq_del_crq_hash(struct cfq_rq *crq) -{ - hlist_del_init(&crq->hash); -} - -static inline void cfq_add_crq_hash(struct cfq_data *cfqd, struct cfq_rq *crq) -{ - const int hash_idx = CFQ_MHASH_FN(rq_hash_key(crq->request)); - - hlist_add_head(&crq->hash, &cfqd->crq_hash[hash_idx]); -} - -static struct request *cfq_find_rq_hash(struct cfq_data *cfqd, sector_t offset) -{ - struct hlist_head *hash_list = &cfqd->crq_hash[CFQ_MHASH_FN(offset)]; - struct hlist_node *entry, *next; - - hlist_for_each_safe(entry, next, hash_list) { - struct cfq_rq *crq = list_entry_hash(entry); - struct request *__rq = crq->request; - - if (!rq_mergeable(__rq)) { - cfq_del_crq_hash(crq); - continue; - } - - if (rq_hash_key(__rq) == offset) - return __rq; - } - - return NULL; -} - -/* - * scheduler run of queue, if there are requests pending and no one in the - * driver that will restart queueing - */ -static inline void cfq_schedule_dispatch(struct cfq_data *cfqd) -{ - if (!cfqd->rq_in_driver && cfqd->busy_queues) - kblockd_schedule_work(&cfqd->unplug_work); -} - -static int cfq_queue_empty(request_queue_t *q) -{ - struct cfq_data *cfqd = q->elevator->elevator_data; - - return !cfqd->busy_queues; -} - -/* - * Lifted from AS - choose which of crq1 and crq2 that is best served now. - * We choose the request that is closest to the head right now. Distance - * behind the head are penalized and only allowed to a certain extent. - */ -static struct cfq_rq * -cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2) -{ - sector_t last, s1, s2, d1 = 0, d2 = 0; - int r1_wrap = 0, r2_wrap = 0; /* requests are behind the disk head */ - unsigned long back_max; - - if (crq1 == NULL || crq1 == crq2) - return crq2; - if (crq2 == NULL) - return crq1; - - if (cfq_crq_is_sync(crq1) && !cfq_crq_is_sync(crq2)) - return crq1; - else if (cfq_crq_is_sync(crq2) && !cfq_crq_is_sync(crq1)) - return crq2; - - s1 = crq1->request->sector; - s2 = crq2->request->sector; - - last = cfqd->last_sector; - - /* - * by definition, 1KiB is 2 sectors - */ - back_max = cfqd->cfq_back_max * 2; - - /* - * Strict one way elevator _except_ in the case where we allow - * short backward seeks which are biased as twice the cost of a - * similar forward seek. - */ - if (s1 >= last) - d1 = s1 - last; - else if (s1 + back_max >= last) - d1 = (last - s1) * cfqd->cfq_back_penalty; - else - r1_wrap = 1; - - if (s2 >= last) - d2 = s2 - last; - else if (s2 + back_max >= last) - d2 = (last - s2) * cfqd->cfq_back_penalty; - else - r2_wrap = 1; - - /* Found required data */ - if (!r1_wrap && r2_wrap) - return crq1; - else if (!r2_wrap && r1_wrap) - return crq2; - else if (r1_wrap && r2_wrap) { - /* both behind the head */ - if (s1 <= s2) - return crq1; - else - return crq2; - } - - /* Both requests in front of the head */ - if (d1 < d2) - return crq1; - else if (d2 < d1) - return crq2; - else { - if (s1 >= s2) - return crq1; - else - return crq2; - } -} - -/* - * would be nice to take fifo expire time into account as well - */ -static struct cfq_rq * -cfq_find_next_crq(struct cfq_data *cfqd, struct cfq_queue *cfqq, - struct cfq_rq *last) -{ - struct cfq_rq *crq_next = NULL, *crq_prev = NULL; - struct rb_node *rbnext, *rbprev; - - if (!(rbnext = rb_next(&last->rb_node))) { - rbnext = rb_first(&cfqq->sort_list); - if (rbnext == &last->rb_node) - rbnext = NULL; - } - - rbprev = rb_prev(&last->rb_node); - - if (rbprev) - crq_prev = rb_entry_crq(rbprev); - if (rbnext) - crq_next = rb_entry_crq(rbnext); - - return cfq_choose_req(cfqd, crq_next, crq_prev); -} - -static void cfq_update_next_crq(struct cfq_rq *crq) -{ - struct cfq_queue *cfqq = crq->cfq_queue; - - if (cfqq->next_crq == crq) - cfqq->next_crq = cfq_find_next_crq(cfqq->cfqd, cfqq, crq); -} - -static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted) -{ - struct cfq_data *cfqd = cfqq->cfqd; - struct list_head *list, *entry; - - BUG_ON(!cfq_cfqq_on_rr(cfqq)); - - list_del(&cfqq->cfq_list); - - if (cfq_class_rt(cfqq)) - list = &cfqd->cur_rr; - else if (cfq_class_idle(cfqq)) - list = &cfqd->idle_rr; - else { - /* - * if cfqq has requests in flight, don't allow it to be - * found in cfq_set_active_queue before it has finished them. - * this is done to increase fairness between a process that - * has lots of io pending vs one that only generates one - * sporadically or synchronously - */ - if (cfq_cfqq_dispatched(cfqq)) - list = &cfqd->busy_rr; - else - list = &cfqd->rr_list[cfqq->ioprio]; - } - - /* - * if queue was preempted, just add to front to be fair. busy_rr - * isn't sorted. - */ - if (preempted || list == &cfqd->busy_rr) { - list_add(&cfqq->cfq_list, list); - return; - } - - /* - * sort by when queue was last serviced - */ - entry = list; - while ((entry = entry->prev) != list) { - struct cfq_queue *__cfqq = list_entry_cfqq(entry); - - if (!__cfqq->service_last) - break; - if (time_before(__cfqq->service_last, cfqq->service_last)) - break; - } - - list_add(&cfqq->cfq_list, entry); -} - -/* - * add to busy list of queues for service, trying to be fair in ordering - * the pending list according to last request service - */ -static inline void -cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) -{ - BUG_ON(cfq_cfqq_on_rr(cfqq)); - cfq_mark_cfqq_on_rr(cfqq); - cfqd->busy_queues++; - - cfq_resort_rr_list(cfqq, 0); -} - -static inline void -cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) -{ - BUG_ON(!cfq_cfqq_on_rr(cfqq)); - cfq_clear_cfqq_on_rr(cfqq); - list_move(&cfqq->cfq_list, &cfqd->empty_list); - - BUG_ON(!cfqd->busy_queues); - cfqd->busy_queues--; -} - -/* - * rb tree support functions - */ -static inline void cfq_del_crq_rb(struct cfq_rq *crq) -{ - struct cfq_queue *cfqq = crq->cfq_queue; - struct cfq_data *cfqd = cfqq->cfqd; - const int sync = cfq_crq_is_sync(crq); - - BUG_ON(!cfqq->queued[sync]); - cfqq->queued[sync]--; - - cfq_update_next_crq(crq); - - rb_erase(&crq->rb_node, &cfqq->sort_list); - RB_CLEAR_COLOR(&crq->rb_node); - - if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY(&cfqq->sort_list)) - cfq_del_cfqq_rr(cfqd, cfqq); -} - -static struct cfq_rq * -__cfq_add_crq_rb(struct cfq_rq *crq) -{ - struct rb_node **p = &crq->cfq_queue->sort_list.rb_node; - struct rb_node *parent = NULL; - struct cfq_rq *__crq; - - while (*p) { - parent = *p; - __crq = rb_entry_crq(parent); - - if (crq->rb_key < __crq->rb_key) - p = &(*p)->rb_left; - else if (crq->rb_key > __crq->rb_key) - p = &(*p)->rb_right; - else - return __crq; - } - - rb_link_node(&crq->rb_node, parent, p); - return NULL; -} - -static void cfq_add_crq_rb(struct cfq_rq *crq) -{ - struct cfq_queue *cfqq = crq->cfq_queue; - struct cfq_data *cfqd = cfqq->cfqd; - struct request *rq = crq->request; - struct cfq_rq *__alias; - - crq->rb_key = rq_rb_key(rq); - cfqq->queued[cfq_crq_is_sync(crq)]++; - - /* - * looks a little odd, but the first insert might return an alias. - * if that happens, put the alias on the dispatch list - */ - while ((__alias = __cfq_add_crq_rb(crq)) != NULL) - cfq_dispatch_insert(cfqd->queue, __alias); - - rb_insert_color(&crq->rb_node, &cfqq->sort_list); - - if (!cfq_cfqq_on_rr(cfqq)) - cfq_add_cfqq_rr(cfqd, cfqq); - - /* - * check if this request is a better next-serve candidate - */ - cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq); -} - -static inline void -cfq_reposition_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq) -{ - rb_erase(&crq->rb_node, &cfqq->sort_list); - cfqq->queued[cfq_crq_is_sync(crq)]--; - - cfq_add_crq_rb(crq); -} - -static struct request *cfq_find_rq_rb(struct cfq_data *cfqd, sector_t sector) - -{ - struct cfq_queue *cfqq = cfq_find_cfq_hash(cfqd, current->pid, CFQ_KEY_ANY); - struct rb_node *n; - - if (!cfqq) - goto out; - - n = cfqq->sort_list.rb_node; - while (n) { - struct cfq_rq *crq = rb_entry_crq(n); - - if (sector < crq->rb_key) - n = n->rb_left; - else if (sector > crq->rb_key) - n = n->rb_right; - else - return crq->request; - } - -out: - return NULL; -} - -static void cfq_activate_request(request_queue_t *q, struct request *rq) -{ - struct cfq_data *cfqd = q->elevator->elevator_data; - - cfqd->rq_in_driver++; -} - -static void cfq_deactivate_request(request_queue_t *q, struct request *rq) -{ - struct cfq_data *cfqd = q->elevator->elevator_data; - - WARN_ON(!cfqd->rq_in_driver); - cfqd->rq_in_driver--; -} - -static void cfq_remove_request(struct request *rq) -{ - struct cfq_rq *crq = RQ_DATA(rq); - - list_del_init(&rq->queuelist); - cfq_del_crq_rb(crq); - cfq_del_crq_hash(crq); -} - -static int -cfq_merge(request_queue_t *q, struct request **req, struct bio *bio) -{ - struct cfq_data *cfqd = q->elevator->elevator_data; - struct request *__rq; - int ret; - - __rq = cfq_find_rq_hash(cfqd, bio->bi_sector); - if (__rq && elv_rq_merge_ok(__rq, bio)) { - ret = ELEVATOR_BACK_MERGE; - goto out; - } - - __rq = cfq_find_rq_rb(cfqd, bio->bi_sector + bio_sectors(bio)); - if (__rq && elv_rq_merge_ok(__rq, bio)) { - ret = ELEVATOR_FRONT_MERGE; - goto out; - } - - return ELEVATOR_NO_MERGE; -out: - *req = __rq; - return ret; -} - -static void cfq_merged_request(request_queue_t *q, struct request *req) -{ - struct cfq_data *cfqd = q->elevator->elevator_data; - struct cfq_rq *crq = RQ_DATA(req); - - cfq_del_crq_hash(crq); - cfq_add_crq_hash(cfqd, crq); - - if (rq_rb_key(req) != crq->rb_key) { - struct cfq_queue *cfqq = crq->cfq_queue; - - cfq_update_next_crq(crq); - cfq_reposition_crq_rb(cfqq, crq); - } -} - -static void -cfq_merged_requests(request_queue_t *q, struct request *rq, - struct request *next) -{ - cfq_merged_request(q, rq); - - /* - * reposition in fifo if next is older than rq - */ - if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist) && - time_before(next->start_time, rq->start_time)) - list_move(&rq->queuelist, &next->queuelist); - - cfq_remove_request(next); -} - -static inline void -__cfq_set_active_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) -{ - if (cfqq) { - /* - * stop potential idle class queues waiting service - */ - del_timer(&cfqd->idle_class_timer); - - cfqq->slice_start = jiffies; - cfqq->slice_end = 0; - cfqq->slice_left = 0; - cfq_clear_cfqq_must_alloc_slice(cfqq); - cfq_clear_cfqq_fifo_expire(cfqq); - cfq_clear_cfqq_expired(cfqq); - } - - cfqd->active_queue = cfqq; -} - -/* - * 0 - * 0,1 - * 0,1,2 - * 0,1,2,3 - * 0,1,2,3,4 - * 0,1,2,3,4,5 - * 0,1,2,3,4,5,6 - * 0,1,2,3,4,5,6,7 - */ -static int cfq_get_next_prio_level(struct cfq_data *cfqd) -{ - int prio, wrap; - - prio = -1; - wrap = 0; - do { - int p; - - for (p = cfqd->cur_prio; p <= cfqd->cur_end_prio; p++) { - if (!list_empty(&cfqd->rr_list[p])) { - prio = p; - break; - } - } - - if (prio != -1) - break; - cfqd->cur_prio = 0; - if (++cfqd->cur_end_prio == CFQ_PRIO_LISTS) { - cfqd->cur_end_prio = 0; - if (wrap) - break; - wrap = 1; - } - } while (1); - - if (unlikely(prio == -1)) - return -1; - - BUG_ON(prio >= CFQ_PRIO_LISTS); - - list_splice_init(&cfqd->rr_list[prio], &cfqd->cur_rr); - - cfqd->cur_prio = prio + 1; - if (cfqd->cur_prio > cfqd->cur_end_prio) { - cfqd->cur_end_prio = cfqd->cur_prio; - cfqd->cur_prio = 0; - } - if (cfqd->cur_end_prio == CFQ_PRIO_LISTS) { - cfqd->cur_prio = 0; - cfqd->cur_end_prio = 0; - } - - return prio; -} - -static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd) -{ - struct cfq_queue *cfqq; - - /* - * if current queue is expired but not done with its requests yet, - * wait for that to happen - */ - if ((cfqq = cfqd->active_queue) != NULL) { - if (cfq_cfqq_expired(cfqq) && cfq_cfqq_dispatched(cfqq)) - return NULL; - } - - /* - * if current list is non-empty, grab first entry. if it is empty, - * get next prio level and grab first entry then if any are spliced - */ - if (!list_empty(&cfqd->cur_rr) || cfq_get_next_prio_level(cfqd) != -1) - cfqq = list_entry_cfqq(cfqd->cur_rr.next); - - /* - * if we have idle queues and no rt or be queues had pending - * requests, either allow immediate service if the grace period - * has passed or arm the idle grace timer - */ - if (!cfqq && !list_empty(&cfqd->idle_rr)) { - unsigned long end = cfqd->last_end_request + CFQ_IDLE_GRACE; - - if (time_after_eq(jiffies, end)) - cfqq = list_entry_cfqq(cfqd->idle_rr.next); - else - mod_timer(&cfqd->idle_class_timer, end); - } - - __cfq_set_active_queue(cfqd, cfqq); - return cfqq; -} - -/* - * current cfqq expired its slice (or was too idle), select new one - */ -static void -__cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq, - int preempted) -{ - unsigned long now = jiffies; - - if (cfq_cfqq_wait_request(cfqq)) - del_timer(&cfqd->idle_slice_timer); - - if (!preempted && !cfq_cfqq_dispatched(cfqq)) - cfqq->service_last = now; - - cfq_clear_cfqq_must_dispatch(cfqq); - cfq_clear_cfqq_wait_request(cfqq); - - /* - * store what was left of this slice, if the queue idled out - * or was preempted - */ - if (time_after(now, cfqq->slice_end)) - cfqq->slice_left = now - cfqq->slice_end; - else - cfqq->slice_left = 0; - - if (cfq_cfqq_on_rr(cfqq)) - cfq_resort_rr_list(cfqq, preempted); - - if (cfqq == cfqd->active_queue) - cfqd->active_queue = NULL; - - if (cfqd->active_cic) { - put_io_context(cfqd->active_cic->ioc); - cfqd->active_cic = NULL; - } - - cfqd->dispatch_slice = 0; -} - -static inline void cfq_slice_expired(struct cfq_data *cfqd, int preempted) -{ - struct cfq_queue *cfqq = cfqd->active_queue; - - if (cfqq) { - /* - * use deferred expiry, if there are requests in progress as - * not to disturb the slice of the next queue - */ - if (cfq_cfqq_dispatched(cfqq)) - cfq_mark_cfqq_expired(cfqq); - else - __cfq_slice_expired(cfqd, cfqq, preempted); - } -} - -static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq) - -{ - WARN_ON(!RB_EMPTY(&cfqq->sort_list)); - WARN_ON(cfqq != cfqd->active_queue); - - /* - * idle is disabled, either manually or by past process history - */ - if (!cfqd->cfq_slice_idle) - return 0; - if (!cfq_cfqq_idle_window(cfqq)) - return 0; - /* - * task has exited, don't wait - */ - if (cfqd->active_cic && !cfqd->active_cic->ioc->task) - return 0; - - cfq_mark_cfqq_must_dispatch(cfqq); - cfq_mark_cfqq_wait_request(cfqq); - - if (!timer_pending(&cfqd->idle_slice_timer)) { - unsigned long slice_left = min(cfqq->slice_end - 1, (unsigned long) cfqd->cfq_slice_idle); - - cfqd->idle_slice_timer.expires = jiffies + slice_left; - add_timer(&cfqd->idle_slice_timer); - } - - return 1; -} - -static void cfq_dispatch_insert(request_queue_t *q, struct cfq_rq *crq) -{ - struct cfq_data *cfqd = q->elevator->elevator_data; - struct cfq_queue *cfqq = crq->cfq_queue; - - cfqq->next_crq = cfq_find_next_crq(cfqd, cfqq, crq); - cfq_remove_request(crq->request); - cfqq->on_dispatch[cfq_crq_is_sync(crq)]++; - elv_dispatch_sort(q, crq->request); -} - -/* - * return expired entry, or NULL to just start from scratch in rbtree - */ -static inline struct cfq_rq *cfq_check_fifo(struct cfq_queue *cfqq) -{ - struct cfq_data *cfqd = cfqq->cfqd; - struct request *rq; - struct cfq_rq *crq; - - if (cfq_cfqq_fifo_expire(cfqq)) - return NULL; - - if (!list_empty(&cfqq->fifo)) { - int fifo = cfq_cfqq_class_sync(cfqq); - - crq = RQ_DATA(list_entry_fifo(cfqq->fifo.next)); - rq = crq->request; - if (time_after(jiffies, rq->start_time + cfqd->cfq_fifo_expire[fifo])) { - cfq_mark_cfqq_fifo_expire(cfqq); - return crq; - } - } - - return NULL; -} - -/* - * Scale schedule slice based on io priority. Use the sync time slice only - * if a queue is marked sync and has sync io queued. A sync queue with async - * io only, should not get full sync slice length. - */ -static inline int -cfq_prio_to_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq) -{ - const int base_slice = cfqd->cfq_slice[cfq_cfqq_sync(cfqq)]; - - WARN_ON(cfqq->ioprio >= IOPRIO_BE_NR); - - return base_slice + (base_slice/CFQ_SLICE_SCALE * (4 - cfqq->ioprio)); -} - -static inline void -cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq) -{ - cfqq->slice_end = cfq_prio_to_slice(cfqd, cfqq) + jiffies; -} - -static inline int -cfq_prio_to_maxrq(struct cfq_data *cfqd, struct cfq_queue *cfqq) -{ - const int base_rq = cfqd->cfq_slice_async_rq; - - WARN_ON(cfqq->ioprio >= IOPRIO_BE_NR); - - return 2 * (base_rq + base_rq * (CFQ_PRIO_LISTS - 1 - cfqq->ioprio)); -} - -/* - * get next queue for service - */ -static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd, int force) -{ - unsigned long now = jiffies; - struct cfq_queue *cfqq; - - cfqq = cfqd->active_queue; - if (!cfqq) - goto new_queue; - - if (cfq_cfqq_expired(cfqq)) - goto new_queue; - - /* - * slice has expired - */ - if (!cfq_cfqq_must_dispatch(cfqq) && time_after(now, cfqq->slice_end)) - goto expire; - - /* - * if queue has requests, dispatch one. if not, check if - * enough slice is left to wait for one - */ - if (!RB_EMPTY(&cfqq->sort_list)) - goto keep_queue; - else if (!force && cfq_cfqq_class_sync(cfqq) && - time_before(now, cfqq->slice_end)) { - if (cfq_arm_slice_timer(cfqd, cfqq)) - return NULL; - } - -expire: - cfq_slice_expired(cfqd, 0); -new_queue: - cfqq = cfq_set_active_queue(cfqd); -keep_queue: - return cfqq; -} - -static int -__cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq, - int max_dispatch) -{ - int dispatched = 0; - - BUG_ON(RB_EMPTY(&cfqq->sort_list)); - - do { - struct cfq_rq *crq; - - /* - * follow expired path, else get first next available - */ - if ((crq = cfq_check_fifo(cfqq)) == NULL) - crq = cfqq->next_crq; - - /* - * finally, insert request into driver dispatch list - */ - cfq_dispatch_insert(cfqd->queue, crq); - - cfqd->dispatch_slice++; - dispatched++; - - if (!cfqd->active_cic) { - atomic_inc(&crq->io_context->ioc->refcount); - cfqd->active_cic = crq->io_context; - } - - if (RB_EMPTY(&cfqq->sort_list)) - break; - - } while (dispatched < max_dispatch); - - /* - * if slice end isn't set yet, set it. if at least one request was - * sync, use the sync time slice value - */ - if (!cfqq->slice_end) - cfq_set_prio_slice(cfqd, cfqq); - - /* - * expire an async queue immediately if it has used up its slice. idle - * queue always expire after 1 dispatch round. - */ - if ((!cfq_cfqq_sync(cfqq) && - cfqd->dispatch_slice >= cfq_prio_to_maxrq(cfqd, cfqq)) || - cfq_class_idle(cfqq)) - cfq_slice_expired(cfqd, 0); - - return dispatched; -} - -static int -cfq_dispatch_requests(request_queue_t *q, int force) -{ - struct cfq_data *cfqd = q->elevator->elevator_data; - struct cfq_queue *cfqq; - - if (!cfqd->busy_queues) - return 0; - - cfqq = cfq_select_queue(cfqd, force); - if (cfqq) { - int max_dispatch; - - /* - * if idle window is disabled, allow queue buildup - */ - if (!cfq_cfqq_idle_window(cfqq) && - cfqd->rq_in_driver >= cfqd->cfq_max_depth) - return 0; - - cfq_clear_cfqq_must_dispatch(cfqq); - cfq_clear_cfqq_wait_request(cfqq); - del_timer(&cfqd->idle_slice_timer); - - if (!force) { - max_dispatch = cfqd->cfq_quantum; - if (cfq_class_idle(cfqq)) - max_dispatch = 1; - } else - max_dispatch = INT_MAX; - - return __cfq_dispatch_requests(cfqd, cfqq, max_dispatch); - } - - return 0; -} - -/* - * task holds one reference to the queue, dropped when task exits. each crq - * in-flight on this queue also holds a reference, dropped when crq is freed. - * - * queue lock must be held here. - */ -static void cfq_put_queue(struct cfq_queue *cfqq) -{ - struct cfq_data *cfqd = cfqq->cfqd; - - BUG_ON(atomic_read(&cfqq->ref) <= 0); - - if (!atomic_dec_and_test(&cfqq->ref)) - return; - - BUG_ON(rb_first(&cfqq->sort_list)); - BUG_ON(cfqq->allocated[READ] + cfqq->allocated[WRITE]); - BUG_ON(cfq_cfqq_on_rr(cfqq)); - - if (unlikely(cfqd->active_queue == cfqq)) { - __cfq_slice_expired(cfqd, cfqq, 0); - cfq_schedule_dispatch(cfqd); - } - - cfq_put_cfqd(cfqq->cfqd); - - /* - * it's on the empty list and still hashed - */ - list_del(&cfqq->cfq_list); - hlist_del(&cfqq->cfq_hash); - kmem_cache_free(cfq_pool, cfqq); -} - -static inline struct cfq_queue * -__cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned int prio, - const int hashval) -{ - struct hlist_head *hash_list = &cfqd->cfq_hash[hashval]; - struct hlist_node *entry, *next; - - hlist_for_each_safe(entry, next, hash_list) { - struct cfq_queue *__cfqq = list_entry_qhash(entry); - const unsigned short __p = IOPRIO_PRIO_VALUE(__cfqq->ioprio_class, __cfqq->ioprio); - - if (__cfqq->key == key && (__p == prio || prio == CFQ_KEY_ANY)) - return __cfqq; - } - - return NULL; -} - -static struct cfq_queue * -cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned short prio) -{ - return __cfq_find_cfq_hash(cfqd, key, prio, hash_long(key, CFQ_QHASH_SHIFT)); -} - -static void cfq_free_io_context(struct cfq_io_context *cic) -{ - struct cfq_io_context *__cic; - struct list_head *entry, *next; - - list_for_each_safe(entry, next, &cic->list) { - __cic = list_entry(entry, struct cfq_io_context, list); - kmem_cache_free(cfq_ioc_pool, __cic); - } - - kmem_cache_free(cfq_ioc_pool, cic); -} - -/* - * Called with interrupts disabled - */ -static void cfq_exit_single_io_context(struct cfq_io_context *cic) -{ - struct cfq_data *cfqd = cic->cfqq->cfqd; - request_queue_t *q = cfqd->queue; - - WARN_ON(!irqs_disabled()); - - spin_lock(q->queue_lock); - - if (unlikely(cic->cfqq == cfqd->active_queue)) { - __cfq_slice_expired(cfqd, cic->cfqq, 0); - cfq_schedule_dispatch(cfqd); - } - - cfq_put_queue(cic->cfqq); - cic->cfqq = NULL; - spin_unlock(q->queue_lock); -} - -/* - * Another task may update the task cic list, if it is doing a queue lookup - * on its behalf. cfq_cic_lock excludes such concurrent updates - */ -static void cfq_exit_io_context(struct cfq_io_context *cic) -{ - struct cfq_io_context *__cic; - struct list_head *entry; - unsigned long flags; - - local_irq_save(flags); - - /* - * put the reference this task is holding to the various queues - */ - list_for_each(entry, &cic->list) { - __cic = list_entry(entry, struct cfq_io_context, list); - cfq_exit_single_io_context(__cic); - } - - cfq_exit_single_io_context(cic); - local_irq_restore(flags); -} - -static struct cfq_io_context * -cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask) -{ - struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_mask); - - if (cic) { - INIT_LIST_HEAD(&cic->list); - cic->cfqq = NULL; - cic->key = NULL; - cic->last_end_request = jiffies; - cic->ttime_total = 0; - cic->ttime_samples = 0; - cic->ttime_mean = 0; - cic->dtor = cfq_free_io_context; - cic->exit = cfq_exit_io_context; - } - - return cic; -} - -static void cfq_init_prio_data(struct cfq_queue *cfqq) -{ - struct task_struct *tsk = current; - int ioprio_class; - - if (!cfq_cfqq_prio_changed(cfqq)) - return; - - ioprio_class = IOPRIO_PRIO_CLASS(tsk->ioprio); - switch (ioprio_class) { - default: - printk(KERN_ERR "cfq: bad prio %x\n", ioprio_class); - case IOPRIO_CLASS_NONE: - /* - * no prio set, place us in the middle of the BE classes - */ - cfqq->ioprio = task_nice_ioprio(tsk); - cfqq->ioprio_class = IOPRIO_CLASS_BE; - break; - case IOPRIO_CLASS_RT: - cfqq->ioprio = task_ioprio(tsk); - cfqq->ioprio_class = IOPRIO_CLASS_RT; - break; - case IOPRIO_CLASS_BE: - cfqq->ioprio = task_ioprio(tsk); - cfqq->ioprio_class = IOPRIO_CLASS_BE; - break; - case IOPRIO_CLASS_IDLE: - cfqq->ioprio_class = IOPRIO_CLASS_IDLE; - cfqq->ioprio = 7; - cfq_clear_cfqq_idle_window(cfqq); - break; - } - - /* - * keep track of original prio settings in case we have to temporarily - * elevate the priority of this queue - */ - cfqq->org_ioprio = cfqq->ioprio; - cfqq->org_ioprio_class = cfqq->ioprio_class; - - if (cfq_cfqq_on_rr(cfqq)) - cfq_resort_rr_list(cfqq, 0); - - cfq_clear_cfqq_prio_changed(cfqq); -} - -static inline void changed_ioprio(struct cfq_queue *cfqq) -{ - if (cfqq) { - struct cfq_data *cfqd = cfqq->cfqd; - - spin_lock(cfqd->queue->queue_lock); - cfq_mark_cfqq_prio_changed(cfqq); - cfq_init_prio_data(cfqq); - spin_unlock(cfqd->queue->queue_lock); - } -} - -/* - * callback from sys_ioprio_set, irqs are disabled - */ -static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio) -{ - struct cfq_io_context *cic = ioc->cic; - - changed_ioprio(cic->cfqq); - - list_for_each_entry(cic, &cic->list, list) - changed_ioprio(cic->cfqq); - - return 0; -} - -static struct cfq_queue * -cfq_get_queue(struct cfq_data *cfqd, unsigned int key, unsigned short ioprio, - gfp_t gfp_mask) -{ - const int hashval = hash_long(key, CFQ_QHASH_SHIFT); - struct cfq_queue *cfqq, *new_cfqq = NULL; - -retry: - cfqq = __cfq_find_cfq_hash(cfqd, key, ioprio, hashval); - - if (!cfqq) { - if (new_cfqq) { - cfqq = new_cfqq; - new_cfqq = NULL; - } else if (gfp_mask & __GFP_WAIT) { - spin_unlock_irq(cfqd->queue->queue_lock); - new_cfqq = kmem_cache_alloc(cfq_pool, gfp_mask); - spin_lock_irq(cfqd->queue->queue_lock); - goto retry; - } else { - cfqq = kmem_cache_alloc(cfq_pool, gfp_mask); - if (!cfqq) - goto out; - } - - memset(cfqq, 0, sizeof(*cfqq)); - - INIT_HLIST_NODE(&cfqq->cfq_hash); - INIT_LIST_HEAD(&cfqq->cfq_list); - RB_CLEAR_ROOT(&cfqq->sort_list); - INIT_LIST_HEAD(&cfqq->fifo); - - cfqq->key = key; - hlist_add_head(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]); - atomic_set(&cfqq->ref, 0); - cfqq->cfqd = cfqd; - atomic_inc(&cfqd->ref); - cfqq->service_last = 0; - /* - * set ->slice_left to allow preemption for a new process - */ - cfqq->slice_left = 2 * cfqd->cfq_slice_idle; - cfq_mark_cfqq_idle_window(cfqq); - cfq_mark_cfqq_prio_changed(cfqq); - cfq_init_prio_data(cfqq); - } - - if (new_cfqq) - kmem_cache_free(cfq_pool, new_cfqq); - - atomic_inc(&cfqq->ref); -out: - WARN_ON((gfp_mask & __GFP_WAIT) && !cfqq); - return cfqq; -} - -/* - * Setup general io context and cfq io context. There can be several cfq - * io contexts per general io context, if this process is doing io to more - * than one device managed by cfq. Note that caller is holding a reference to - * cfqq, so we don't need to worry about it disappearing - */ -static struct cfq_io_context * -cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask) -{ - struct io_context *ioc = NULL; - struct cfq_io_context *cic; - - might_sleep_if(gfp_mask & __GFP_WAIT); - - ioc = get_io_context(gfp_mask); - if (!ioc) - return NULL; - - if ((cic = ioc->cic) == NULL) { - cic = cfq_alloc_io_context(cfqd, gfp_mask); - - if (cic == NULL) - goto err; - - /* - * manually increment generic io_context usage count, it - * cannot go away since we are already holding one ref to it - */ - ioc->cic = cic; - ioc->set_ioprio = cfq_ioc_set_ioprio; - cic->ioc = ioc; - cic->key = cfqd; - atomic_inc(&cfqd->ref); - } else { - struct cfq_io_context *__cic; - - /* - * the first cic on the list is actually the head itself - */ - if (cic->key == cfqd) - goto out; - - /* - * cic exists, check if we already are there. linear search - * should be ok here, the list will usually not be more than - * 1 or a few entries long - */ - list_for_each_entry(__cic, &cic->list, list) { - /* - * this process is already holding a reference to - * this queue, so no need to get one more - */ - if (__cic->key == cfqd) { - cic = __cic; - goto out; - } - } - - /* - * nope, process doesn't have a cic assoicated with this - * cfqq yet. get a new one and add to list - */ - __cic = cfq_alloc_io_context(cfqd, gfp_mask); - if (__cic == NULL) - goto err; - - __cic->ioc = ioc; - __cic->key = cfqd; - atomic_inc(&cfqd->ref); - list_add(&__cic->list, &cic->list); - cic = __cic; - } - -out: - return cic; -err: - put_io_context(ioc); - return NULL; -} - -static void -cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic) -{ - unsigned long elapsed, ttime; - - /* - * if this context already has stuff queued, thinktime is from - * last queue not last end - */ -#if 0 - if (time_after(cic->last_end_request, cic->last_queue)) - elapsed = jiffies - cic->last_end_request; - else - elapsed = jiffies - cic->last_queue; -#else - elapsed = jiffies - cic->last_end_request; -#endif - - ttime = min(elapsed, 2UL * cfqd->cfq_slice_idle); - - cic->ttime_samples = (7*cic->ttime_samples + 256) / 8; - cic->ttime_total = (7*cic->ttime_total + 256*ttime) / 8; - cic->ttime_mean = (cic->ttime_total + 128) / cic->ttime_samples; -} - -#define sample_valid(samples) ((samples) > 80) - -/* - * Disable idle window if the process thinks too long or seeks so much that - * it doesn't matter - */ -static void -cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq, - struct cfq_io_context *cic) -{ - int enable_idle = cfq_cfqq_idle_window(cfqq); - - if (!cic->ioc->task || !cfqd->cfq_slice_idle) - enable_idle = 0; - else if (sample_valid(cic->ttime_samples)) { - if (cic->ttime_mean > cfqd->cfq_slice_idle) - enable_idle = 0; - else - enable_idle = 1; - } - - if (enable_idle) - cfq_mark_cfqq_idle_window(cfqq); - else - cfq_clear_cfqq_idle_window(cfqq); -} - - -/* - * Check if new_cfqq should preempt the currently active queue. Return 0 for - * no or if we aren't sure, a 1 will cause a preempt. - */ -static int -cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, - struct cfq_rq *crq) -{ - struct cfq_queue *cfqq = cfqd->active_queue; - - if (cfq_class_idle(new_cfqq)) - return 0; - - if (!cfqq) - return 1; - - if (cfq_class_idle(cfqq)) - return 1; - if (!cfq_cfqq_wait_request(new_cfqq)) - return 0; - /* - * if it doesn't have slice left, forget it - */ - if (new_cfqq->slice_left < cfqd->cfq_slice_idle) - return 0; - if (cfq_crq_is_sync(crq) && !cfq_cfqq_sync(cfqq)) - return 1; - - return 0; -} - -/* - * cfqq preempts the active queue. if we allowed preempt with no slice left, - * let it have half of its nominal slice. - */ -static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) -{ - struct cfq_queue *__cfqq, *next; - - list_for_each_entry_safe(__cfqq, next, &cfqd->cur_rr, cfq_list) - cfq_resort_rr_list(__cfqq, 1); - - if (!cfqq->slice_left) - cfqq->slice_left = cfq_prio_to_slice(cfqd, cfqq) / 2; - - cfqq->slice_end = cfqq->slice_left + jiffies; - __cfq_slice_expired(cfqd, cfqq, 1); - __cfq_set_active_queue(cfqd, cfqq); -} - -/* - * should really be a ll_rw_blk.c helper - */ -static void cfq_start_queueing(struct cfq_data *cfqd, struct cfq_queue *cfqq) -{ - request_queue_t *q = cfqd->queue; - - if (!blk_queue_plugged(q)) - q->request_fn(q); - else - __generic_unplug_device(q); -} - -/* - * Called when a new fs request (crq) is added (to cfqq). Check if there's - * something we should do about it - */ -static void -cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, - struct cfq_rq *crq) -{ - struct cfq_io_context *cic; - - cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq); - - /* - * we never wait for an async request and we don't allow preemption - * of an async request. so just return early - */ - if (!cfq_crq_is_sync(crq)) - return; - - cic = crq->io_context; - - cfq_update_io_thinktime(cfqd, cic); - cfq_update_idle_window(cfqd, cfqq, cic); - - cic->last_queue = jiffies; - - if (cfqq == cfqd->active_queue) { - /* - * if we are waiting for a request for this queue, let it rip - * immediately and flag that we must not expire this queue - * just now - */ - if (cfq_cfqq_wait_request(cfqq)) { - cfq_mark_cfqq_must_dispatch(cfqq); - del_timer(&cfqd->idle_slice_timer); - cfq_start_queueing(cfqd, cfqq); - } - } else if (cfq_should_preempt(cfqd, cfqq, crq)) { - /* - * not the active queue - expire current slice if it is - * idle and has expired it's mean thinktime or this new queue - * has some old slice time left and is of higher priority - */ - cfq_preempt_queue(cfqd, cfqq); - cfq_mark_cfqq_must_dispatch(cfqq); - cfq_start_queueing(cfqd, cfqq); - } -} - -static void cfq_insert_request(request_queue_t *q, struct request *rq) -{ - struct cfq_data *cfqd = q->elevator->elevator_data; - struct cfq_rq *crq = RQ_DATA(rq); - struct cfq_queue *cfqq = crq->cfq_queue; - - cfq_init_prio_data(cfqq); - - cfq_add_crq_rb(crq); - - list_add_tail(&rq->queuelist, &cfqq->fifo); - - if (rq_mergeable(rq)) - cfq_add_crq_hash(cfqd, crq); - - cfq_crq_enqueued(cfqd, cfqq, crq); -} - -static void cfq_completed_request(request_queue_t *q, struct request *rq) -{ - struct cfq_rq *crq = RQ_DATA(rq); - struct cfq_queue *cfqq = crq->cfq_queue; - struct cfq_data *cfqd = cfqq->cfqd; - const int sync = cfq_crq_is_sync(crq); - unsigned long now; - - now = jiffies; - - WARN_ON(!cfqd->rq_in_driver); - WARN_ON(!cfqq->on_dispatch[sync]); - cfqd->rq_in_driver--; - cfqq->on_dispatch[sync]--; - - if (!cfq_class_idle(cfqq)) - cfqd->last_end_request = now; - - if (!cfq_cfqq_dispatched(cfqq)) { - if (cfq_cfqq_on_rr(cfqq)) { - cfqq->service_last = now; - cfq_resort_rr_list(cfqq, 0); - } - if (cfq_cfqq_expired(cfqq)) { - __cfq_slice_expired(cfqd, cfqq, 0); - cfq_schedule_dispatch(cfqd); - } - } - - if (cfq_crq_is_sync(crq)) - crq->io_context->last_end_request = now; -} - -static struct request * -cfq_former_request(request_queue_t *q, struct request *rq) -{ - struct cfq_rq *crq = RQ_DATA(rq); - struct rb_node *rbprev = rb_prev(&crq->rb_node); - - if (rbprev) - return rb_entry_crq(rbprev)->request; - - return NULL; -} - -static struct request * -cfq_latter_request(request_queue_t *q, struct request *rq) -{ - struct cfq_rq *crq = RQ_DATA(rq); - struct rb_node *rbnext = rb_next(&crq->rb_node); - - if (rbnext) - return rb_entry_crq(rbnext)->request; - - return NULL; -} - -/* - * we temporarily boost lower priority queues if they are holding fs exclusive - * resources. they are boosted to normal prio (CLASS_BE/4) - */ -static void cfq_prio_boost(struct cfq_queue *cfqq) -{ - const int ioprio_class = cfqq->ioprio_class; - const int ioprio = cfqq->ioprio; - - if (has_fs_excl()) { - /* - * boost idle prio on transactions that would lock out other - * users of the filesystem - */ - if (cfq_class_idle(cfqq)) - cfqq->ioprio_class = IOPRIO_CLASS_BE; - if (cfqq->ioprio > IOPRIO_NORM) - cfqq->ioprio = IOPRIO_NORM; - } else { - /* - * check if we need to unboost the queue - */ - if (cfqq->ioprio_class != cfqq->org_ioprio_class) - cfqq->ioprio_class = cfqq->org_ioprio_class; - if (cfqq->ioprio != cfqq->org_ioprio) - cfqq->ioprio = cfqq->org_ioprio; - } - - /* - * refile between round-robin lists if we moved the priority class - */ - if ((ioprio_class != cfqq->ioprio_class || ioprio != cfqq->ioprio) && - cfq_cfqq_on_rr(cfqq)) - cfq_resort_rr_list(cfqq, 0); -} - -static inline pid_t cfq_queue_pid(struct task_struct *task, int rw) -{ - if (rw == READ || process_sync(task)) - return task->pid; - - return CFQ_KEY_ASYNC; -} - -static inline int -__cfq_may_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq, - struct task_struct *task, int rw) -{ -#if 1 - if ((cfq_cfqq_wait_request(cfqq) || cfq_cfqq_must_alloc(cfqq)) && - !cfq_cfqq_must_alloc_slice(cfqq)) { - cfq_mark_cfqq_must_alloc_slice(cfqq); - return ELV_MQUEUE_MUST; - } - - return ELV_MQUEUE_MAY; -#else - if (!cfqq || task->flags & PF_MEMALLOC) - return ELV_MQUEUE_MAY; - if (!cfqq->allocated[rw] || cfq_cfqq_must_alloc(cfqq)) { - if (cfq_cfqq_wait_request(cfqq)) - return ELV_MQUEUE_MUST; - - /* - * only allow 1 ELV_MQUEUE_MUST per slice, otherwise we - * can quickly flood the queue with writes from a single task - */ - if (rw == READ || !cfq_cfqq_must_alloc_slice(cfqq)) { - cfq_mark_cfqq_must_alloc_slice(cfqq); - return ELV_MQUEUE_MUST; - } - - return ELV_MQUEUE_MAY; - } - if (cfq_class_idle(cfqq)) - return ELV_MQUEUE_NO; - if (cfqq->allocated[rw] >= cfqd->max_queued) { - struct io_context *ioc = get_io_context(GFP_ATOMIC); - int ret = ELV_MQUEUE_NO; - - if (ioc && ioc->nr_batch_requests) - ret = ELV_MQUEUE_MAY; - - put_io_context(ioc); - return ret; - } - - return ELV_MQUEUE_MAY; -#endif -} - -static int cfq_may_queue(request_queue_t *q, int rw, struct bio *bio) -{ - struct cfq_data *cfqd = q->elevator->elevator_data; - struct task_struct *tsk = current; - struct cfq_queue *cfqq; - - /* - * don't force setup of a queue from here, as a call to may_queue - * does not necessarily imply that a request actually will be queued. - * so just lookup a possibly existing queue, or return 'may queue' - * if that fails - */ - cfqq = cfq_find_cfq_hash(cfqd, cfq_queue_pid(tsk, rw), tsk->ioprio); - if (cfqq) { - cfq_init_prio_data(cfqq); - cfq_prio_boost(cfqq); - - return __cfq_may_queue(cfqd, cfqq, tsk, rw); - } - - return ELV_MQUEUE_MAY; -} - -static void cfq_check_waiters(request_queue_t *q, struct cfq_queue *cfqq) -{ - struct cfq_data *cfqd = q->elevator->elevator_data; - struct request_list *rl = &q->rq; - - if (cfqq->allocated[READ] <= cfqd->max_queued || cfqd->rq_starved) { - smp_mb(); - if (waitqueue_active(&rl->wait[READ])) - wake_up(&rl->wait[READ]); - } - - if (cfqq->allocated[WRITE] <= cfqd->max_queued || cfqd->rq_starved) { - smp_mb(); - if (waitqueue_active(&rl->wait[WRITE])) - wake_up(&rl->wait[WRITE]); - } -} - -/* - * queue lock held here - */ -static void cfq_put_request(request_queue_t *q, struct request *rq) -{ - struct cfq_data *cfqd = q->elevator->elevator_data; - struct cfq_rq *crq = RQ_DATA(rq); - - if (crq) { - struct cfq_queue *cfqq = crq->cfq_queue; - const int rw = rq_data_dir(rq); - - BUG_ON(!cfqq->allocated[rw]); - cfqq->allocated[rw]--; - - put_io_context(crq->io_context->ioc); - - mempool_free(crq, cfqd->crq_pool); - rq->elevator_private = NULL; - - cfq_check_waiters(q, cfqq); - cfq_put_queue(cfqq); - } -} - -/* - * Allocate cfq data structures associated with this request. - */ -static int -cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio, - gfp_t gfp_mask) -{ - struct cfq_data *cfqd = q->elevator->elevator_data; - struct task_struct *tsk = current; - struct cfq_io_context *cic; - const int rw = rq_data_dir(rq); - pid_t key = cfq_queue_pid(tsk, rw); - struct cfq_queue *cfqq; - struct cfq_rq *crq; - unsigned long flags; - - might_sleep_if(gfp_mask & __GFP_WAIT); - - cic = cfq_get_io_context(cfqd, key, gfp_mask); - - spin_lock_irqsave(q->queue_lock, flags); - - if (!cic) - goto queue_fail; - - if (!cic->cfqq) { - cfqq = cfq_get_queue(cfqd, key, tsk->ioprio, gfp_mask); - if (!cfqq) - goto queue_fail; - - cic->cfqq = cfqq; - } else - cfqq = cic->cfqq; - - cfqq->allocated[rw]++; - cfq_clear_cfqq_must_alloc(cfqq); - cfqd->rq_starved = 0; - atomic_inc(&cfqq->ref); - spin_unlock_irqrestore(q->queue_lock, flags); - - crq = mempool_alloc(cfqd->crq_pool, gfp_mask); - if (crq) { - RB_CLEAR(&crq->rb_node); - crq->rb_key = 0; - crq->request = rq; - INIT_HLIST_NODE(&crq->hash); - crq->cfq_queue = cfqq; - crq->io_context = cic; - - if (rw == READ || process_sync(tsk)) - cfq_mark_crq_is_sync(crq); - else - cfq_clear_crq_is_sync(crq); - - rq->elevator_private = crq; - return 0; - } - - spin_lock_irqsave(q->queue_lock, flags); - cfqq->allocated[rw]--; - if (!(cfqq->allocated[0] + cfqq->allocated[1])) - cfq_mark_cfqq_must_alloc(cfqq); - cfq_put_queue(cfqq); -queue_fail: - if (cic) - put_io_context(cic->ioc); - /* - * mark us rq allocation starved. we need to kickstart the process - * ourselves if there are no pending requests that can do it for us. - * that would be an extremely rare OOM situation - */ - cfqd->rq_starved = 1; - cfq_schedule_dispatch(cfqd); - spin_unlock_irqrestore(q->queue_lock, flags); - return 1; -} - -static void cfq_kick_queue(void *data) -{ - request_queue_t *q = data; - struct cfq_data *cfqd = q->elevator->elevator_data; - unsigned long flags; - - spin_lock_irqsave(q->queue_lock, flags); - - if (cfqd->rq_starved) { - struct request_list *rl = &q->rq; - - /* - * we aren't guaranteed to get a request after this, but we - * have to be opportunistic - */ - smp_mb(); - if (waitqueue_active(&rl->wait[READ])) - wake_up(&rl->wait[READ]); - if (waitqueue_active(&rl->wait[WRITE])) - wake_up(&rl->wait[WRITE]); - } - - blk_remove_plug(q); - q->request_fn(q); - spin_unlock_irqrestore(q->queue_lock, flags); -} - -/* - * Timer running if the active_queue is currently idling inside its time slice - */ -static void cfq_idle_slice_timer(unsigned long data) -{ - struct cfq_data *cfqd = (struct cfq_data *) data; - struct cfq_queue *cfqq; - unsigned long flags; - - spin_lock_irqsave(cfqd->queue->queue_lock, flags); - - if ((cfqq = cfqd->active_queue) != NULL) { - unsigned long now = jiffies; - - /* - * expired - */ - if (time_after(now, cfqq->slice_end)) - goto expire; - - /* - * only expire and reinvoke request handler, if there are - * other queues with pending requests - */ - if (!cfqd->busy_queues) { - cfqd->idle_slice_timer.expires = min(now + cfqd->cfq_slice_idle, cfqq->slice_end); - add_timer(&cfqd->idle_slice_timer); - goto out_cont; - } - - /* - * not expired and it has a request pending, let it dispatch - */ - if (!RB_EMPTY(&cfqq->sort_list)) { - cfq_mark_cfqq_must_dispatch(cfqq); - goto out_kick; - } - } -expire: - cfq_slice_expired(cfqd, 0); -out_kick: - cfq_schedule_dispatch(cfqd); -out_cont: - spin_unlock_irqrestore(cfqd->queue->queue_lock, flags); -} - -/* - * Timer running if an idle class queue is waiting for service - */ -static void cfq_idle_class_timer(unsigned long data) -{ - struct cfq_data *cfqd = (struct cfq_data *) data; - unsigned long flags, end; - - spin_lock_irqsave(cfqd->queue->queue_lock, flags); - - /* - * race with a non-idle queue, reset timer - */ - end = cfqd->last_end_request + CFQ_IDLE_GRACE; - if (!time_after_eq(jiffies, end)) { - cfqd->idle_class_timer.expires = end; - add_timer(&cfqd->idle_class_timer); - } else - cfq_schedule_dispatch(cfqd); - - spin_unlock_irqrestore(cfqd->queue->queue_lock, flags); -} - -static void cfq_shutdown_timer_wq(struct cfq_data *cfqd) -{ - del_timer_sync(&cfqd->idle_slice_timer); - del_timer_sync(&cfqd->idle_class_timer); - blk_sync_queue(cfqd->queue); -} - -static void cfq_put_cfqd(struct cfq_data *cfqd) -{ - request_queue_t *q = cfqd->queue; - - if (!atomic_dec_and_test(&cfqd->ref)) - return; - - cfq_shutdown_timer_wq(cfqd); - blk_put_queue(q); - - mempool_destroy(cfqd->crq_pool); - kfree(cfqd->crq_hash); - kfree(cfqd->cfq_hash); - kfree(cfqd); -} - -static void cfq_exit_queue(elevator_t *e) -{ - struct cfq_data *cfqd = e->elevator_data; - - cfq_shutdown_timer_wq(cfqd); - cfq_put_cfqd(cfqd); -} - -static int cfq_init_queue(request_queue_t *q, elevator_t *e) -{ - struct cfq_data *cfqd; - int i; - - cfqd = kmalloc(sizeof(*cfqd), GFP_KERNEL); - if (!cfqd) - return -ENOMEM; - - memset(cfqd, 0, sizeof(*cfqd)); - - for (i = 0; i < CFQ_PRIO_LISTS; i++) - INIT_LIST_HEAD(&cfqd->rr_list[i]); - - INIT_LIST_HEAD(&cfqd->busy_rr); - INIT_LIST_HEAD(&cfqd->cur_rr); - INIT_LIST_HEAD(&cfqd->idle_rr); - INIT_LIST_HEAD(&cfqd->empty_list); - - cfqd->crq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_MHASH_ENTRIES, GFP_KERNEL); - if (!cfqd->crq_hash) - goto out_crqhash; - - cfqd->cfq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_QHASH_ENTRIES, GFP_KERNEL); - if (!cfqd->cfq_hash) - goto out_cfqhash; - - cfqd->crq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, crq_pool); - if (!cfqd->crq_pool) - goto out_crqpool; - - for (i = 0; i < CFQ_MHASH_ENTRIES; i++) - INIT_HLIST_HEAD(&cfqd->crq_hash[i]); - for (i = 0; i < CFQ_QHASH_ENTRIES; i++) - INIT_HLIST_HEAD(&cfqd->cfq_hash[i]); - - e->elevator_data = cfqd; - - cfqd->queue = q; - atomic_inc(&q->refcnt); - - cfqd->max_queued = q->nr_requests / 4; - q->nr_batching = cfq_queued; - - init_timer(&cfqd->idle_slice_timer); - cfqd->idle_slice_timer.function = cfq_idle_slice_timer; - cfqd->idle_slice_timer.data = (unsigned long) cfqd; - - init_timer(&cfqd->idle_class_timer); - cfqd->idle_class_timer.function = cfq_idle_class_timer; - cfqd->idle_class_timer.data = (unsigned long) cfqd; - - INIT_WORK(&cfqd->unplug_work, cfq_kick_queue, q); - - atomic_set(&cfqd->ref, 1); - - cfqd->cfq_queued = cfq_queued; - cfqd->cfq_quantum = cfq_quantum; - cfqd->cfq_fifo_expire[0] = cfq_fifo_expire[0]; - cfqd->cfq_fifo_expire[1] = cfq_fifo_expire[1]; - cfqd->cfq_back_max = cfq_back_max; - cfqd->cfq_back_penalty = cfq_back_penalty; - cfqd->cfq_slice[0] = cfq_slice_async; - cfqd->cfq_slice[1] = cfq_slice_sync; - cfqd->cfq_slice_async_rq = cfq_slice_async_rq; - cfqd->cfq_slice_idle = cfq_slice_idle; - cfqd->cfq_max_depth = cfq_max_depth; - - return 0; -out_crqpool: - kfree(cfqd->cfq_hash); -out_cfqhash: - kfree(cfqd->crq_hash); -out_crqhash: - kfree(cfqd); - return -ENOMEM; -} - -static void cfq_slab_kill(void) -{ - if (crq_pool) - kmem_cache_destroy(crq_pool); - if (cfq_pool) - kmem_cache_destroy(cfq_pool); - if (cfq_ioc_pool) - kmem_cache_destroy(cfq_ioc_pool); -} - -static int __init cfq_slab_setup(void) -{ - crq_pool = kmem_cache_create("crq_pool", sizeof(struct cfq_rq), 0, 0, - NULL, NULL); - if (!crq_pool) - goto fail; - - cfq_pool = kmem_cache_create("cfq_pool", sizeof(struct cfq_queue), 0, 0, - NULL, NULL); - if (!cfq_pool) - goto fail; - - cfq_ioc_pool = kmem_cache_create("cfq_ioc_pool", - sizeof(struct cfq_io_context), 0, 0, NULL, NULL); - if (!cfq_ioc_pool) - goto fail; - - return 0; -fail: - cfq_slab_kill(); - return -ENOMEM; -} - -/* - * sysfs parts below --> - */ -struct cfq_fs_entry { - struct attribute attr; - ssize_t (*show)(struct cfq_data *, char *); - ssize_t (*store)(struct cfq_data *, const char *, size_t); -}; - -static ssize_t -cfq_var_show(unsigned int var, char *page) -{ - return sprintf(page, "%d\n", var); -} - -static ssize_t -cfq_var_store(unsigned int *var, const char *page, size_t count) -{ - char *p = (char *) page; - - *var = simple_strtoul(p, &p, 10); - return count; -} - -#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ -static ssize_t __FUNC(struct cfq_data *cfqd, char *page) \ -{ \ - unsigned int __data = __VAR; \ - if (__CONV) \ - __data = jiffies_to_msecs(__data); \ - return cfq_var_show(__data, (page)); \ -} -SHOW_FUNCTION(cfq_quantum_show, cfqd->cfq_quantum, 0); -SHOW_FUNCTION(cfq_queued_show, cfqd->cfq_queued, 0); -SHOW_FUNCTION(cfq_fifo_expire_sync_show, cfqd->cfq_fifo_expire[1], 1); -SHOW_FUNCTION(cfq_fifo_expire_async_show, cfqd->cfq_fifo_expire[0], 1); -SHOW_FUNCTION(cfq_back_max_show, cfqd->cfq_back_max, 0); -SHOW_FUNCTION(cfq_back_penalty_show, cfqd->cfq_back_penalty, 0); -SHOW_FUNCTION(cfq_slice_idle_show, cfqd->cfq_slice_idle, 1); -SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1); -SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1); -SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0); -SHOW_FUNCTION(cfq_max_depth_show, cfqd->cfq_max_depth, 0); -#undef SHOW_FUNCTION - -#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ -static ssize_t __FUNC(struct cfq_data *cfqd, const char *page, size_t count) \ -{ \ - unsigned int __data; \ - int ret = cfq_var_store(&__data, (page), count); \ - if (__data < (MIN)) \ - __data = (MIN); \ - else if (__data > (MAX)) \ - __data = (MAX); \ - if (__CONV) \ - *(__PTR) = msecs_to_jiffies(__data); \ - else \ - *(__PTR) = __data; \ - return ret; \ -} -STORE_FUNCTION(cfq_quantum_store, &cfqd->cfq_quantum, 1, UINT_MAX, 0); -STORE_FUNCTION(cfq_queued_store, &cfqd->cfq_queued, 1, UINT_MAX, 0); -STORE_FUNCTION(cfq_fifo_expire_sync_store, &cfqd->cfq_fifo_expire[1], 1, UINT_MAX, 1); -STORE_FUNCTION(cfq_fifo_expire_async_store, &cfqd->cfq_fifo_expire[0], 1, UINT_MAX, 1); -STORE_FUNCTION(cfq_back_max_store, &cfqd->cfq_back_max, 0, UINT_MAX, 0); -STORE_FUNCTION(cfq_back_penalty_store, &cfqd->cfq_back_penalty, 1, UINT_MAX, 0); -STORE_FUNCTION(cfq_slice_idle_store, &cfqd->cfq_slice_idle, 0, UINT_MAX, 1); -STORE_FUNCTION(cfq_slice_sync_store, &cfqd->cfq_slice[1], 1, UINT_MAX, 1); -STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1); -STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, UINT_MAX, 0); -STORE_FUNCTION(cfq_max_depth_store, &cfqd->cfq_max_depth, 1, UINT_MAX, 0); -#undef STORE_FUNCTION - -static struct cfq_fs_entry cfq_quantum_entry = { - .attr = {.name = "quantum", .mode = S_IRUGO | S_IWUSR }, - .show = cfq_quantum_show, - .store = cfq_quantum_store, -}; -static struct cfq_fs_entry cfq_queued_entry = { - .attr = {.name = "queued", .mode = S_IRUGO | S_IWUSR }, - .show = cfq_queued_show, - .store = cfq_queued_store, -}; -static struct cfq_fs_entry cfq_fifo_expire_sync_entry = { - .attr = {.name = "fifo_expire_sync", .mode = S_IRUGO | S_IWUSR }, - .show = cfq_fifo_expire_sync_show, - .store = cfq_fifo_expire_sync_store, -}; -static struct cfq_fs_entry cfq_fifo_expire_async_entry = { - .attr = {.name = "fifo_expire_async", .mode = S_IRUGO | S_IWUSR }, - .show = cfq_fifo_expire_async_show, - .store = cfq_fifo_expire_async_store, -}; -static struct cfq_fs_entry cfq_back_max_entry = { - .attr = {.name = "back_seek_max", .mode = S_IRUGO | S_IWUSR }, - .show = cfq_back_max_show, - .store = cfq_back_max_store, -}; -static struct cfq_fs_entry cfq_back_penalty_entry = { - .attr = {.name = "back_seek_penalty", .mode = S_IRUGO | S_IWUSR }, - .show = cfq_back_penalty_show, - .store = cfq_back_penalty_store, -}; -static struct cfq_fs_entry cfq_slice_sync_entry = { - .attr = {.name = "slice_sync", .mode = S_IRUGO | S_IWUSR }, - .show = cfq_slice_sync_show, - .store = cfq_slice_sync_store, -}; -static struct cfq_fs_entry cfq_slice_async_entry = { - .attr = {.name = "slice_async", .mode = S_IRUGO | S_IWUSR }, - .show = cfq_slice_async_show, - .store = cfq_slice_async_store, -}; -static struct cfq_fs_entry cfq_slice_async_rq_entry = { - .attr = {.name = "slice_async_rq", .mode = S_IRUGO | S_IWUSR }, - .show = cfq_slice_async_rq_show, - .store = cfq_slice_async_rq_store, -}; -static struct cfq_fs_entry cfq_slice_idle_entry = { - .attr = {.name = "slice_idle", .mode = S_IRUGO | S_IWUSR }, - .show = cfq_slice_idle_show, - .store = cfq_slice_idle_store, -}; -static struct cfq_fs_entry cfq_max_depth_entry = { - .attr = {.name = "max_depth", .mode = S_IRUGO | S_IWUSR }, - .show = cfq_max_depth_show, - .store = cfq_max_depth_store, -}; - -static struct attribute *default_attrs[] = { - &cfq_quantum_entry.attr, - &cfq_queued_entry.attr, - &cfq_fifo_expire_sync_entry.attr, - &cfq_fifo_expire_async_entry.attr, - &cfq_back_max_entry.attr, - &cfq_back_penalty_entry.attr, - &cfq_slice_sync_entry.attr, - &cfq_slice_async_entry.attr, - &cfq_slice_async_rq_entry.attr, - &cfq_slice_idle_entry.attr, - &cfq_max_depth_entry.attr, - NULL, -}; - -#define to_cfq(atr) container_of((atr), struct cfq_fs_entry, attr) - -static ssize_t -cfq_attr_show(struct kobject *kobj, struct attribute *attr, char *page) -{ - elevator_t *e = container_of(kobj, elevator_t, kobj); - struct cfq_fs_entry *entry = to_cfq(attr); - - if (!entry->show) - return -EIO; - - return entry->show(e->elevator_data, page); -} - -static ssize_t -cfq_attr_store(struct kobject *kobj, struct attribute *attr, - const char *page, size_t length) -{ - elevator_t *e = container_of(kobj, elevator_t, kobj); - struct cfq_fs_entry *entry = to_cfq(attr); - - if (!entry->store) - return -EIO; - - return entry->store(e->elevator_data, page, length); -} - -static struct sysfs_ops cfq_sysfs_ops = { - .show = cfq_attr_show, - .store = cfq_attr_store, -}; - -static struct kobj_type cfq_ktype = { - .sysfs_ops = &cfq_sysfs_ops, - .default_attrs = default_attrs, -}; - -static struct elevator_type iosched_cfq = { - .ops = { - .elevator_merge_fn = cfq_merge, - .elevator_merged_fn = cfq_merged_request, - .elevator_merge_req_fn = cfq_merged_requests, - .elevator_dispatch_fn = cfq_dispatch_requests, - .elevator_add_req_fn = cfq_insert_request, - .elevator_activate_req_fn = cfq_activate_request, - .elevator_deactivate_req_fn = cfq_deactivate_request, - .elevator_queue_empty_fn = cfq_queue_empty, - .elevator_completed_req_fn = cfq_completed_request, - .elevator_former_req_fn = cfq_former_request, - .elevator_latter_req_fn = cfq_latter_request, - .elevator_set_req_fn = cfq_set_request, - .elevator_put_req_fn = cfq_put_request, - .elevator_may_queue_fn = cfq_may_queue, - .elevator_init_fn = cfq_init_queue, - .elevator_exit_fn = cfq_exit_queue, - }, - .elevator_ktype = &cfq_ktype, - .elevator_name = "cfq", - .elevator_owner = THIS_MODULE, -}; - -static int __init cfq_init(void) -{ - int ret; - - /* - * could be 0 on HZ < 1000 setups - */ - if (!cfq_slice_async) - cfq_slice_async = 1; - if (!cfq_slice_idle) - cfq_slice_idle = 1; - - if (cfq_slab_setup()) - return -ENOMEM; - - ret = elv_register(&iosched_cfq); - if (ret) - cfq_slab_kill(); - - return ret; -} - -static void __exit cfq_exit(void) -{ - elv_unregister(&iosched_cfq); - cfq_slab_kill(); -} - -module_init(cfq_init); -module_exit(cfq_exit); - -MODULE_AUTHOR("Jens Axboe"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Completely Fair Queueing IO scheduler"); diff --git a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c deleted file mode 100644 index 7929471d7df..00000000000 --- a/drivers/block/deadline-iosched.c +++ /dev/null @@ -1,878 +0,0 @@ -/* - * linux/drivers/block/deadline-iosched.c - * - * Deadline i/o scheduler. - * - * Copyright (C) 2002 Jens Axboe - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * See Documentation/block/deadline-iosched.txt - */ -static int read_expire = HZ / 2; /* max time before a read is submitted. */ -static int write_expire = 5 * HZ; /* ditto for writes, these limits are SOFT! */ -static int writes_starved = 2; /* max times reads can starve a write */ -static int fifo_batch = 16; /* # of sequential requests treated as one - by the above parameters. For throughput. */ - -static const int deadline_hash_shift = 5; -#define DL_HASH_BLOCK(sec) ((sec) >> 3) -#define DL_HASH_FN(sec) (hash_long(DL_HASH_BLOCK((sec)), deadline_hash_shift)) -#define DL_HASH_ENTRIES (1 << deadline_hash_shift) -#define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors) -#define list_entry_hash(ptr) list_entry((ptr), struct deadline_rq, hash) -#define ON_HASH(drq) (drq)->on_hash - -struct deadline_data { - /* - * run time data - */ - - /* - * requests (deadline_rq s) are present on both sort_list and fifo_list - */ - struct rb_root sort_list[2]; - struct list_head fifo_list[2]; - - /* - * next in sort order. read, write or both are NULL - */ - struct deadline_rq *next_drq[2]; - struct list_head *hash; /* request hash */ - unsigned int batching; /* number of sequential requests made */ - sector_t last_sector; /* head position */ - unsigned int starved; /* times reads have starved writes */ - - /* - * settings that change how the i/o scheduler behaves - */ - int fifo_expire[2]; - int fifo_batch; - int writes_starved; - int front_merges; - - mempool_t *drq_pool; -}; - -/* - * pre-request data. - */ -struct deadline_rq { - /* - * rbtree index, key is the starting offset - */ - struct rb_node rb_node; - sector_t rb_key; - - struct request *request; - - /* - * request hash, key is the ending offset (for back merge lookup) - */ - struct list_head hash; - char on_hash; - - /* - * expire fifo - */ - struct list_head fifo; - unsigned long expires; -}; - -static void deadline_move_request(struct deadline_data *dd, struct deadline_rq *drq); - -static kmem_cache_t *drq_pool; - -#define RQ_DATA(rq) ((struct deadline_rq *) (rq)->elevator_private) - -/* - * the back merge hash support functions - */ -static inline void __deadline_del_drq_hash(struct deadline_rq *drq) -{ - drq->on_hash = 0; - list_del_init(&drq->hash); -} - -static inline void deadline_del_drq_hash(struct deadline_rq *drq) -{ - if (ON_HASH(drq)) - __deadline_del_drq_hash(drq); -} - -static inline void -deadline_add_drq_hash(struct deadline_data *dd, struct deadline_rq *drq) -{ - struct request *rq = drq->request; - - BUG_ON(ON_HASH(drq)); - - drq->on_hash = 1; - list_add(&drq->hash, &dd->hash[DL_HASH_FN(rq_hash_key(rq))]); -} - -/* - * move hot entry to front of chain - */ -static inline void -deadline_hot_drq_hash(struct deadline_data *dd, struct deadline_rq *drq) -{ - struct request *rq = drq->request; - struct list_head *head = &dd->hash[DL_HASH_FN(rq_hash_key(rq))]; - - if (ON_HASH(drq) && drq->hash.prev != head) { - list_del(&drq->hash); - list_add(&drq->hash, head); - } -} - -static struct request * -deadline_find_drq_hash(struct deadline_data *dd, sector_t offset) -{ - struct list_head *hash_list = &dd->hash[DL_HASH_FN(offset)]; - struct list_head *entry, *next = hash_list->next; - - while ((entry = next) != hash_list) { - struct deadline_rq *drq = list_entry_hash(entry); - struct request *__rq = drq->request; - - next = entry->next; - - BUG_ON(!ON_HASH(drq)); - - if (!rq_mergeable(__rq)) { - __deadline_del_drq_hash(drq); - continue; - } - - if (rq_hash_key(__rq) == offset) - return __rq; - } - - return NULL; -} - -/* - * rb tree support functions - */ -#define RB_NONE (2) -#define RB_EMPTY(root) ((root)->rb_node == NULL) -#define ON_RB(node) ((node)->rb_color != RB_NONE) -#define RB_CLEAR(node) ((node)->rb_color = RB_NONE) -#define rb_entry_drq(node) rb_entry((node), struct deadline_rq, rb_node) -#define DRQ_RB_ROOT(dd, drq) (&(dd)->sort_list[rq_data_dir((drq)->request)]) -#define rq_rb_key(rq) (rq)->sector - -static struct deadline_rq * -__deadline_add_drq_rb(struct deadline_data *dd, struct deadline_rq *drq) -{ - struct rb_node **p = &DRQ_RB_ROOT(dd, drq)->rb_node; - struct rb_node *parent = NULL; - struct deadline_rq *__drq; - - while (*p) { - parent = *p; - __drq = rb_entry_drq(parent); - - if (drq->rb_key < __drq->rb_key) - p = &(*p)->rb_left; - else if (drq->rb_key > __drq->rb_key) - p = &(*p)->rb_right; - else - return __drq; - } - - rb_link_node(&drq->rb_node, parent, p); - return NULL; -} - -static void -deadline_add_drq_rb(struct deadline_data *dd, struct deadline_rq *drq) -{ - struct deadline_rq *__alias; - - drq->rb_key = rq_rb_key(drq->request); - -retry: - __alias = __deadline_add_drq_rb(dd, drq); - if (!__alias) { - rb_insert_color(&drq->rb_node, DRQ_RB_ROOT(dd, drq)); - return; - } - - deadline_move_request(dd, __alias); - goto retry; -} - -static inline void -deadline_del_drq_rb(struct deadline_data *dd, struct deadline_rq *drq) -{ - const int data_dir = rq_data_dir(drq->request); - - if (dd->next_drq[data_dir] == drq) { - struct rb_node *rbnext = rb_next(&drq->rb_node); - - dd->next_drq[data_dir] = NULL; - if (rbnext) - dd->next_drq[data_dir] = rb_entry_drq(rbnext); - } - - BUG_ON(!ON_RB(&drq->rb_node)); - rb_erase(&drq->rb_node, DRQ_RB_ROOT(dd, drq)); - RB_CLEAR(&drq->rb_node); -} - -static struct request * -deadline_find_drq_rb(struct deadline_data *dd, sector_t sector, int data_dir) -{ - struct rb_node *n = dd->sort_list[data_dir].rb_node; - struct deadline_rq *drq; - - while (n) { - drq = rb_entry_drq(n); - - if (sector < drq->rb_key) - n = n->rb_left; - else if (sector > drq->rb_key) - n = n->rb_right; - else - return drq->request; - } - - return NULL; -} - -/* - * deadline_find_first_drq finds the first (lowest sector numbered) request - * for the specified data_dir. Used to sweep back to the start of the disk - * (1-way elevator) after we process the last (highest sector) request. - */ -static struct deadline_rq * -deadline_find_first_drq(struct deadline_data *dd, int data_dir) -{ - struct rb_node *n = dd->sort_list[data_dir].rb_node; - - for (;;) { - if (n->rb_left == NULL) - return rb_entry_drq(n); - - n = n->rb_left; - } -} - -/* - * add drq to rbtree and fifo - */ -static void -deadline_add_request(struct request_queue *q, struct request *rq) -{ - struct deadline_data *dd = q->elevator->elevator_data; - struct deadline_rq *drq = RQ_DATA(rq); - - const int data_dir = rq_data_dir(drq->request); - - deadline_add_drq_rb(dd, drq); - /* - * set expire time (only used for reads) and add to fifo list - */ - drq->expires = jiffies + dd->fifo_expire[data_dir]; - list_add_tail(&drq->fifo, &dd->fifo_list[data_dir]); - - if (rq_mergeable(rq)) - deadline_add_drq_hash(dd, drq); -} - -/* - * remove rq from rbtree, fifo, and hash - */ -static void deadline_remove_request(request_queue_t *q, struct request *rq) -{ - struct deadline_rq *drq = RQ_DATA(rq); - struct deadline_data *dd = q->elevator->elevator_data; - - list_del_init(&drq->fifo); - deadline_del_drq_rb(dd, drq); - deadline_del_drq_hash(drq); -} - -static int -deadline_merge(request_queue_t *q, struct request **req, struct bio *bio) -{ - struct deadline_data *dd = q->elevator->elevator_data; - struct request *__rq; - int ret; - - /* - * see if the merge hash can satisfy a back merge - */ - __rq = deadline_find_drq_hash(dd, bio->bi_sector); - if (__rq) { - BUG_ON(__rq->sector + __rq->nr_sectors != bio->bi_sector); - - if (elv_rq_merge_ok(__rq, bio)) { - ret = ELEVATOR_BACK_MERGE; - goto out; - } - } - - /* - * check for front merge - */ - if (dd->front_merges) { - sector_t rb_key = bio->bi_sector + bio_sectors(bio); - - __rq = deadline_find_drq_rb(dd, rb_key, bio_data_dir(bio)); - if (__rq) { - BUG_ON(rb_key != rq_rb_key(__rq)); - - if (elv_rq_merge_ok(__rq, bio)) { - ret = ELEVATOR_FRONT_MERGE; - goto out; - } - } - } - - return ELEVATOR_NO_MERGE; -out: - if (ret) - deadline_hot_drq_hash(dd, RQ_DATA(__rq)); - *req = __rq; - return ret; -} - -static void deadline_merged_request(request_queue_t *q, struct request *req) -{ - struct deadline_data *dd = q->elevator->elevator_data; - struct deadline_rq *drq = RQ_DATA(req); - - /* - * hash always needs to be repositioned, key is end sector - */ - deadline_del_drq_hash(drq); - deadline_add_drq_hash(dd, drq); - - /* - * if the merge was a front merge, we need to reposition request - */ - if (rq_rb_key(req) != drq->rb_key) { - deadline_del_drq_rb(dd, drq); - deadline_add_drq_rb(dd, drq); - } -} - -static void -deadline_merged_requests(request_queue_t *q, struct request *req, - struct request *next) -{ - struct deadline_data *dd = q->elevator->elevator_data; - struct deadline_rq *drq = RQ_DATA(req); - struct deadline_rq *dnext = RQ_DATA(next); - - BUG_ON(!drq); - BUG_ON(!dnext); - - /* - * reposition drq (this is the merged request) in hash, and in rbtree - * in case of a front merge - */ - deadline_del_drq_hash(drq); - deadline_add_drq_hash(dd, drq); - - if (rq_rb_key(req) != drq->rb_key) { - deadline_del_drq_rb(dd, drq); - deadline_add_drq_rb(dd, drq); - } - - /* - * if dnext expires before drq, assign its expire time to drq - * and move into dnext position (dnext will be deleted) in fifo - */ - if (!list_empty(&drq->fifo) && !list_empty(&dnext->fifo)) { - if (time_before(dnext->expires, drq->expires)) { - list_move(&drq->fifo, &dnext->fifo); - drq->expires = dnext->expires; - } - } - - /* - * kill knowledge of next, this one is a goner - */ - deadline_remove_request(q, next); -} - -/* - * move request from sort list to dispatch queue. - */ -static inline void -deadline_move_to_dispatch(struct deadline_data *dd, struct deadline_rq *drq) -{ - request_queue_t *q = drq->request->q; - - deadline_remove_request(q, drq->request); - elv_dispatch_add_tail(q, drq->request); -} - -/* - * move an entry to dispatch queue - */ -static void -deadline_move_request(struct deadline_data *dd, struct deadline_rq *drq) -{ - const int data_dir = rq_data_dir(drq->request); - struct rb_node *rbnext = rb_next(&drq->rb_node); - - dd->next_drq[READ] = NULL; - dd->next_drq[WRITE] = NULL; - - if (rbnext) - dd->next_drq[data_dir] = rb_entry_drq(rbnext); - - dd->last_sector = drq->request->sector + drq->request->nr_sectors; - - /* - * take it off the sort and fifo list, move - * to dispatch queue - */ - deadline_move_to_dispatch(dd, drq); -} - -#define list_entry_fifo(ptr) list_entry((ptr), struct deadline_rq, fifo) - -/* - * deadline_check_fifo returns 0 if there are no expired reads on the fifo, - * 1 otherwise. Requires !list_empty(&dd->fifo_list[data_dir]) - */ -static inline int deadline_check_fifo(struct deadline_data *dd, int ddir) -{ - struct deadline_rq *drq = list_entry_fifo(dd->fifo_list[ddir].next); - - /* - * drq is expired! - */ - if (time_after(jiffies, drq->expires)) - return 1; - - return 0; -} - -/* - * deadline_dispatch_requests selects the best request according to - * read/write expire, fifo_batch, etc - */ -static int deadline_dispatch_requests(request_queue_t *q, int force) -{ - struct deadline_data *dd = q->elevator->elevator_data; - const int reads = !list_empty(&dd->fifo_list[READ]); - const int writes = !list_empty(&dd->fifo_list[WRITE]); - struct deadline_rq *drq; - int data_dir; - - /* - * batches are currently reads XOR writes - */ - if (dd->next_drq[WRITE]) - drq = dd->next_drq[WRITE]; - else - drq = dd->next_drq[READ]; - - if (drq) { - /* we have a "next request" */ - - if (dd->last_sector != drq->request->sector) - /* end the batch on a non sequential request */ - dd->batching += dd->fifo_batch; - - if (dd->batching < dd->fifo_batch) - /* we are still entitled to batch */ - goto dispatch_request; - } - - /* - * at this point we are not running a batch. select the appropriate - * data direction (read / write) - */ - - if (reads) { - BUG_ON(RB_EMPTY(&dd->sort_list[READ])); - - if (writes && (dd->starved++ >= dd->writes_starved)) - goto dispatch_writes; - - data_dir = READ; - - goto dispatch_find_request; - } - - /* - * there are either no reads or writes have been starved - */ - - if (writes) { -dispatch_writes: - BUG_ON(RB_EMPTY(&dd->sort_list[WRITE])); - - dd->starved = 0; - - data_dir = WRITE; - - goto dispatch_find_request; - } - - return 0; - -dispatch_find_request: - /* - * we are not running a batch, find best request for selected data_dir - */ - if (deadline_check_fifo(dd, data_dir)) { - /* An expired request exists - satisfy it */ - dd->batching = 0; - drq = list_entry_fifo(dd->fifo_list[data_dir].next); - - } else if (dd->next_drq[data_dir]) { - /* - * The last req was the same dir and we have a next request in - * sort order. No expired requests so continue on from here. - */ - drq = dd->next_drq[data_dir]; - } else { - /* - * The last req was the other direction or we have run out of - * higher-sectored requests. Go back to the lowest sectored - * request (1 way elevator) and start a new batch. - */ - dd->batching = 0; - drq = deadline_find_first_drq(dd, data_dir); - } - -dispatch_request: - /* - * drq is the selected appropriate request. - */ - dd->batching++; - deadline_move_request(dd, drq); - - return 1; -} - -static int deadline_queue_empty(request_queue_t *q) -{ - struct deadline_data *dd = q->elevator->elevator_data; - - return list_empty(&dd->fifo_list[WRITE]) - && list_empty(&dd->fifo_list[READ]); -} - -static struct request * -deadline_former_request(request_queue_t *q, struct request *rq) -{ - struct deadline_rq *drq = RQ_DATA(rq); - struct rb_node *rbprev = rb_prev(&drq->rb_node); - - if (rbprev) - return rb_entry_drq(rbprev)->request; - - return NULL; -} - -static struct request * -deadline_latter_request(request_queue_t *q, struct request *rq) -{ - struct deadline_rq *drq = RQ_DATA(rq); - struct rb_node *rbnext = rb_next(&drq->rb_node); - - if (rbnext) - return rb_entry_drq(rbnext)->request; - - return NULL; -} - -static void deadline_exit_queue(elevator_t *e) -{ - struct deadline_data *dd = e->elevator_data; - - BUG_ON(!list_empty(&dd->fifo_list[READ])); - BUG_ON(!list_empty(&dd->fifo_list[WRITE])); - - mempool_destroy(dd->drq_pool); - kfree(dd->hash); - kfree(dd); -} - -/* - * initialize elevator private data (deadline_data), and alloc a drq for - * each request on the free lists - */ -static int deadline_init_queue(request_queue_t *q, elevator_t *e) -{ - struct deadline_data *dd; - int i; - - if (!drq_pool) - return -ENOMEM; - - dd = kmalloc_node(sizeof(*dd), GFP_KERNEL, q->node); - if (!dd) - return -ENOMEM; - memset(dd, 0, sizeof(*dd)); - - dd->hash = kmalloc_node(sizeof(struct list_head)*DL_HASH_ENTRIES, - GFP_KERNEL, q->node); - if (!dd->hash) { - kfree(dd); - return -ENOMEM; - } - - dd->drq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab, - mempool_free_slab, drq_pool, q->node); - if (!dd->drq_pool) { - kfree(dd->hash); - kfree(dd); - return -ENOMEM; - } - - for (i = 0; i < DL_HASH_ENTRIES; i++) - INIT_LIST_HEAD(&dd->hash[i]); - - INIT_LIST_HEAD(&dd->fifo_list[READ]); - INIT_LIST_HEAD(&dd->fifo_list[WRITE]); - dd->sort_list[READ] = RB_ROOT; - dd->sort_list[WRITE] = RB_ROOT; - dd->fifo_expire[READ] = read_expire; - dd->fifo_expire[WRITE] = write_expire; - dd->writes_starved = writes_starved; - dd->front_merges = 1; - dd->fifo_batch = fifo_batch; - e->elevator_data = dd; - return 0; -} - -static void deadline_put_request(request_queue_t *q, struct request *rq) -{ - struct deadline_data *dd = q->elevator->elevator_data; - struct deadline_rq *drq = RQ_DATA(rq); - - mempool_free(drq, dd->drq_pool); - rq->elevator_private = NULL; -} - -static int -deadline_set_request(request_queue_t *q, struct request *rq, struct bio *bio, - gfp_t gfp_mask) -{ - struct deadline_data *dd = q->elevator->elevator_data; - struct deadline_rq *drq; - - drq = mempool_alloc(dd->drq_pool, gfp_mask); - if (drq) { - memset(drq, 0, sizeof(*drq)); - RB_CLEAR(&drq->rb_node); - drq->request = rq; - - INIT_LIST_HEAD(&drq->hash); - drq->on_hash = 0; - - INIT_LIST_HEAD(&drq->fifo); - - rq->elevator_private = drq; - return 0; - } - - return 1; -} - -/* - * sysfs parts below - */ -struct deadline_fs_entry { - struct attribute attr; - ssize_t (*show)(struct deadline_data *, char *); - ssize_t (*store)(struct deadline_data *, const char *, size_t); -}; - -static ssize_t -deadline_var_show(int var, char *page) -{ - return sprintf(page, "%d\n", var); -} - -static ssize_t -deadline_var_store(int *var, const char *page, size_t count) -{ - char *p = (char *) page; - - *var = simple_strtol(p, &p, 10); - return count; -} - -#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ -static ssize_t __FUNC(struct deadline_data *dd, char *page) \ -{ \ - int __data = __VAR; \ - if (__CONV) \ - __data = jiffies_to_msecs(__data); \ - return deadline_var_show(__data, (page)); \ -} -SHOW_FUNCTION(deadline_readexpire_show, dd->fifo_expire[READ], 1); -SHOW_FUNCTION(deadline_writeexpire_show, dd->fifo_expire[WRITE], 1); -SHOW_FUNCTION(deadline_writesstarved_show, dd->writes_starved, 0); -SHOW_FUNCTION(deadline_frontmerges_show, dd->front_merges, 0); -SHOW_FUNCTION(deadline_fifobatch_show, dd->fifo_batch, 0); -#undef SHOW_FUNCTION - -#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ -static ssize_t __FUNC(struct deadline_data *dd, const char *page, size_t count) \ -{ \ - int __data; \ - int ret = deadline_var_store(&__data, (page), count); \ - if (__data < (MIN)) \ - __data = (MIN); \ - else if (__data > (MAX)) \ - __data = (MAX); \ - if (__CONV) \ - *(__PTR) = msecs_to_jiffies(__data); \ - else \ - *(__PTR) = __data; \ - return ret; \ -} -STORE_FUNCTION(deadline_readexpire_store, &dd->fifo_expire[READ], 0, INT_MAX, 1); -STORE_FUNCTION(deadline_writeexpire_store, &dd->fifo_expire[WRITE], 0, INT_MAX, 1); -STORE_FUNCTION(deadline_writesstarved_store, &dd->writes_starved, INT_MIN, INT_MAX, 0); -STORE_FUNCTION(deadline_frontmerges_store, &dd->front_merges, 0, 1, 0); -STORE_FUNCTION(deadline_fifobatch_store, &dd->fifo_batch, 0, INT_MAX, 0); -#undef STORE_FUNCTION - -static struct deadline_fs_entry deadline_readexpire_entry = { - .attr = {.name = "read_expire", .mode = S_IRUGO | S_IWUSR }, - .show = deadline_readexpire_show, - .store = deadline_readexpire_store, -}; -static struct deadline_fs_entry deadline_writeexpire_entry = { - .attr = {.name = "write_expire", .mode = S_IRUGO | S_IWUSR }, - .show = deadline_writeexpire_show, - .store = deadline_writeexpire_store, -}; -static struct deadline_fs_entry deadline_writesstarved_entry = { - .attr = {.name = "writes_starved", .mode = S_IRUGO | S_IWUSR }, - .show = deadline_writesstarved_show, - .store = deadline_writesstarved_store, -}; -static struct deadline_fs_entry deadline_frontmerges_entry = { - .attr = {.name = "front_merges", .mode = S_IRUGO | S_IWUSR }, - .show = deadline_frontmerges_show, - .store = deadline_frontmerges_store, -}; -static struct deadline_fs_entry deadline_fifobatch_entry = { - .attr = {.name = "fifo_batch", .mode = S_IRUGO | S_IWUSR }, - .show = deadline_fifobatch_show, - .store = deadline_fifobatch_store, -}; - -static struct attribute *default_attrs[] = { - &deadline_readexpire_entry.attr, - &deadline_writeexpire_entry.attr, - &deadline_writesstarved_entry.attr, - &deadline_frontmerges_entry.attr, - &deadline_fifobatch_entry.attr, - NULL, -}; - -#define to_deadline(atr) container_of((atr), struct deadline_fs_entry, attr) - -static ssize_t -deadline_attr_show(struct kobject *kobj, struct attribute *attr, char *page) -{ - elevator_t *e = container_of(kobj, elevator_t, kobj); - struct deadline_fs_entry *entry = to_deadline(attr); - - if (!entry->show) - return -EIO; - - return entry->show(e->elevator_data, page); -} - -static ssize_t -deadline_attr_store(struct kobject *kobj, struct attribute *attr, - const char *page, size_t length) -{ - elevator_t *e = container_of(kobj, elevator_t, kobj); - struct deadline_fs_entry *entry = to_deadline(attr); - - if (!entry->store) - return -EIO; - - return entry->store(e->elevator_data, page, length); -} - -static struct sysfs_ops deadline_sysfs_ops = { - .show = deadline_attr_show, - .store = deadline_attr_store, -}; - -static struct kobj_type deadline_ktype = { - .sysfs_ops = &deadline_sysfs_ops, - .default_attrs = default_attrs, -}; - -static struct elevator_type iosched_deadline = { - .ops = { - .elevator_merge_fn = deadline_merge, - .elevator_merged_fn = deadline_merged_request, - .elevator_merge_req_fn = deadline_merged_requests, - .elevator_dispatch_fn = deadline_dispatch_requests, - .elevator_add_req_fn = deadline_add_request, - .elevator_queue_empty_fn = deadline_queue_empty, - .elevator_former_req_fn = deadline_former_request, - .elevator_latter_req_fn = deadline_latter_request, - .elevator_set_req_fn = deadline_set_request, - .elevator_put_req_fn = deadline_put_request, - .elevator_init_fn = deadline_init_queue, - .elevator_exit_fn = deadline_exit_queue, - }, - - .elevator_ktype = &deadline_ktype, - .elevator_name = "deadline", - .elevator_owner = THIS_MODULE, -}; - -static int __init deadline_init(void) -{ - int ret; - - drq_pool = kmem_cache_create("deadline_drq", sizeof(struct deadline_rq), - 0, 0, NULL, NULL); - - if (!drq_pool) - return -ENOMEM; - - ret = elv_register(&iosched_deadline); - if (ret) - kmem_cache_destroy(drq_pool); - - return ret; -} - -static void __exit deadline_exit(void) -{ - kmem_cache_destroy(drq_pool); - elv_unregister(&iosched_deadline); -} - -module_init(deadline_init); -module_exit(deadline_exit); - -MODULE_AUTHOR("Jens Axboe"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("deadline IO scheduler"); diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c deleted file mode 100644 index d4a49a3df82..00000000000 --- a/drivers/block/elevator.c +++ /dev/null @@ -1,802 +0,0 @@ -/* - * linux/drivers/block/elevator.c - * - * Block device elevator/IO-scheduler. - * - * Copyright (C) 2000 Andrea Arcangeli SuSE - * - * 30042000 Jens Axboe : - * - * Split the elevator a bit so that it is possible to choose a different - * one or even write a new "plug in". There are three pieces: - * - elevator_fn, inserts a new request in the queue list - * - elevator_merge_fn, decides whether a new buffer can be merged with - * an existing request - * - elevator_dequeue_fn, called when a request is taken off the active list - * - * 20082000 Dave Jones : - * Removed tests for max-bomb-segments, which was breaking elvtune - * when run without -bN - * - * Jens: - * - Rework again to work with bio instead of buffer_heads - * - loose bi_dev comparisons, partition handling is right now - * - completely modularize elevator setup and teardown - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -static DEFINE_SPINLOCK(elv_list_lock); -static LIST_HEAD(elv_list); - -/* - * can we safely merge with this request? - */ -inline int elv_rq_merge_ok(struct request *rq, struct bio *bio) -{ - if (!rq_mergeable(rq)) - return 0; - - /* - * different data direction or already started, don't merge - */ - if (bio_data_dir(bio) != rq_data_dir(rq)) - return 0; - - /* - * same device and no special stuff set, merge is ok - */ - if (rq->rq_disk == bio->bi_bdev->bd_disk && - !rq->waiting && !rq->special) - return 1; - - return 0; -} -EXPORT_SYMBOL(elv_rq_merge_ok); - -inline int elv_try_merge(struct request *__rq, struct bio *bio) -{ - int ret = ELEVATOR_NO_MERGE; - - /* - * we can merge and sequence is ok, check if it's possible - */ - if (elv_rq_merge_ok(__rq, bio)) { - if (__rq->sector + __rq->nr_sectors == bio->bi_sector) - ret = ELEVATOR_BACK_MERGE; - else if (__rq->sector - bio_sectors(bio) == bio->bi_sector) - ret = ELEVATOR_FRONT_MERGE; - } - - return ret; -} -EXPORT_SYMBOL(elv_try_merge); - -static struct elevator_type *elevator_find(const char *name) -{ - struct elevator_type *e = NULL; - struct list_head *entry; - - list_for_each(entry, &elv_list) { - struct elevator_type *__e; - - __e = list_entry(entry, struct elevator_type, list); - - if (!strcmp(__e->elevator_name, name)) { - e = __e; - break; - } - } - - return e; -} - -static void elevator_put(struct elevator_type *e) -{ - module_put(e->elevator_owner); -} - -static struct elevator_type *elevator_get(const char *name) -{ - struct elevator_type *e; - - spin_lock_irq(&elv_list_lock); - - e = elevator_find(name); - if (e && !try_module_get(e->elevator_owner)) - e = NULL; - - spin_unlock_irq(&elv_list_lock); - - return e; -} - -static int elevator_attach(request_queue_t *q, struct elevator_type *e, - struct elevator_queue *eq) -{ - int ret = 0; - - memset(eq, 0, sizeof(*eq)); - eq->ops = &e->ops; - eq->elevator_type = e; - - q->elevator = eq; - - if (eq->ops->elevator_init_fn) - ret = eq->ops->elevator_init_fn(q, eq); - - return ret; -} - -static char chosen_elevator[16]; - -static void elevator_setup_default(void) -{ - struct elevator_type *e; - - /* - * If default has not been set, use the compiled-in selection. - */ - if (!chosen_elevator[0]) - strcpy(chosen_elevator, CONFIG_DEFAULT_IOSCHED); - - /* - * If the given scheduler is not available, fall back to no-op. - */ - if (!(e = elevator_find(chosen_elevator))) - strcpy(chosen_elevator, "noop"); - elevator_put(e); -} - -static int __init elevator_setup(char *str) -{ - strncpy(chosen_elevator, str, sizeof(chosen_elevator) - 1); - return 0; -} - -__setup("elevator=", elevator_setup); - -int elevator_init(request_queue_t *q, char *name) -{ - struct elevator_type *e = NULL; - struct elevator_queue *eq; - int ret = 0; - - INIT_LIST_HEAD(&q->queue_head); - q->last_merge = NULL; - q->end_sector = 0; - q->boundary_rq = NULL; - - elevator_setup_default(); - - if (!name) - name = chosen_elevator; - - e = elevator_get(name); - if (!e) - return -EINVAL; - - eq = kmalloc(sizeof(struct elevator_queue), GFP_KERNEL); - if (!eq) { - elevator_put(e->elevator_type); - return -ENOMEM; - } - - ret = elevator_attach(q, e, eq); - if (ret) { - kfree(eq); - elevator_put(e->elevator_type); - } - - return ret; -} - -void elevator_exit(elevator_t *e) -{ - if (e->ops->elevator_exit_fn) - e->ops->elevator_exit_fn(e); - - elevator_put(e->elevator_type); - e->elevator_type = NULL; - kfree(e); -} - -/* - * Insert rq into dispatch queue of q. Queue lock must be held on - * entry. If sort != 0, rq is sort-inserted; otherwise, rq will be - * appended to the dispatch queue. To be used by specific elevators. - */ -void elv_dispatch_sort(request_queue_t *q, struct request *rq) -{ - sector_t boundary; - struct list_head *entry; - - if (q->last_merge == rq) - q->last_merge = NULL; - - boundary = q->end_sector; - - list_for_each_prev(entry, &q->queue_head) { - struct request *pos = list_entry_rq(entry); - - if (pos->flags & (REQ_SOFTBARRIER|REQ_HARDBARRIER|REQ_STARTED)) - break; - if (rq->sector >= boundary) { - if (pos->sector < boundary) - continue; - } else { - if (pos->sector >= boundary) - break; - } - if (rq->sector >= pos->sector) - break; - } - - list_add(&rq->queuelist, entry); -} - -int elv_merge(request_queue_t *q, struct request **req, struct bio *bio) -{ - elevator_t *e = q->elevator; - int ret; - - if (q->last_merge) { - ret = elv_try_merge(q->last_merge, bio); - if (ret != ELEVATOR_NO_MERGE) { - *req = q->last_merge; - return ret; - } - } - - if (e->ops->elevator_merge_fn) - return e->ops->elevator_merge_fn(q, req, bio); - - return ELEVATOR_NO_MERGE; -} - -void elv_merged_request(request_queue_t *q, struct request *rq) -{ - elevator_t *e = q->elevator; - - if (e->ops->elevator_merged_fn) - e->ops->elevator_merged_fn(q, rq); - - q->last_merge = rq; -} - -void elv_merge_requests(request_queue_t *q, struct request *rq, - struct request *next) -{ - elevator_t *e = q->elevator; - - if (e->ops->elevator_merge_req_fn) - e->ops->elevator_merge_req_fn(q, rq, next); - - q->last_merge = rq; -} - -void elv_requeue_request(request_queue_t *q, struct request *rq) -{ - elevator_t *e = q->elevator; - - /* - * it already went through dequeue, we need to decrement the - * in_flight count again - */ - if (blk_account_rq(rq)) { - q->in_flight--; - if (blk_sorted_rq(rq) && e->ops->elevator_deactivate_req_fn) - e->ops->elevator_deactivate_req_fn(q, rq); - } - - rq->flags &= ~REQ_STARTED; - - /* - * if this is the flush, requeue the original instead and drop the flush - */ - if (rq->flags & REQ_BAR_FLUSH) { - clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags); - rq = rq->end_io_data; - } - - __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0); -} - -void __elv_add_request(request_queue_t *q, struct request *rq, int where, - int plug) -{ - if (rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) { - /* - * barriers implicitly indicate back insertion - */ - if (where == ELEVATOR_INSERT_SORT) - where = ELEVATOR_INSERT_BACK; - - /* - * this request is scheduling boundary, update end_sector - */ - if (blk_fs_request(rq)) { - q->end_sector = rq_end_sector(rq); - q->boundary_rq = rq; - } - } else if (!(rq->flags & REQ_ELVPRIV) && where == ELEVATOR_INSERT_SORT) - where = ELEVATOR_INSERT_BACK; - - if (plug) - blk_plug_device(q); - - rq->q = q; - - switch (where) { - case ELEVATOR_INSERT_FRONT: - rq->flags |= REQ_SOFTBARRIER; - - list_add(&rq->queuelist, &q->queue_head); - break; - - case ELEVATOR_INSERT_BACK: - rq->flags |= REQ_SOFTBARRIER; - - while (q->elevator->ops->elevator_dispatch_fn(q, 1)) - ; - list_add_tail(&rq->queuelist, &q->queue_head); - /* - * We kick the queue here for the following reasons. - * - The elevator might have returned NULL previously - * to delay requests and returned them now. As the - * queue wasn't empty before this request, ll_rw_blk - * won't run the queue on return, resulting in hang. - * - Usually, back inserted requests won't be merged - * with anything. There's no point in delaying queue - * processing. - */ - blk_remove_plug(q); - q->request_fn(q); - break; - - case ELEVATOR_INSERT_SORT: - BUG_ON(!blk_fs_request(rq)); - rq->flags |= REQ_SORTED; - if (q->last_merge == NULL && rq_mergeable(rq)) - q->last_merge = rq; - /* - * Some ioscheds (cfq) run q->request_fn directly, so - * rq cannot be accessed after calling - * elevator_add_req_fn. - */ - q->elevator->ops->elevator_add_req_fn(q, rq); - break; - - default: - printk(KERN_ERR "%s: bad insertion point %d\n", - __FUNCTION__, where); - BUG(); - } - - if (blk_queue_plugged(q)) { - int nrq = q->rq.count[READ] + q->rq.count[WRITE] - - q->in_flight; - - if (nrq >= q->unplug_thresh) - __generic_unplug_device(q); - } -} - -void elv_add_request(request_queue_t *q, struct request *rq, int where, - int plug) -{ - unsigned long flags; - - spin_lock_irqsave(q->queue_lock, flags); - __elv_add_request(q, rq, where, plug); - spin_unlock_irqrestore(q->queue_lock, flags); -} - -static inline struct request *__elv_next_request(request_queue_t *q) -{ - struct request *rq; - - if (unlikely(list_empty(&q->queue_head) && - !q->elevator->ops->elevator_dispatch_fn(q, 0))) - return NULL; - - rq = list_entry_rq(q->queue_head.next); - - /* - * if this is a barrier write and the device has to issue a - * flush sequence to support it, check how far we are - */ - if (blk_fs_request(rq) && blk_barrier_rq(rq)) { - BUG_ON(q->ordered == QUEUE_ORDERED_NONE); - - if (q->ordered == QUEUE_ORDERED_FLUSH && - !blk_barrier_preflush(rq)) - rq = blk_start_pre_flush(q, rq); - } - - return rq; -} - -struct request *elv_next_request(request_queue_t *q) -{ - struct request *rq; - int ret; - - while ((rq = __elv_next_request(q)) != NULL) { - if (!(rq->flags & REQ_STARTED)) { - elevator_t *e = q->elevator; - - /* - * This is the first time the device driver - * sees this request (possibly after - * requeueing). Notify IO scheduler. - */ - if (blk_sorted_rq(rq) && - e->ops->elevator_activate_req_fn) - e->ops->elevator_activate_req_fn(q, rq); - - /* - * just mark as started even if we don't start - * it, a request that has been delayed should - * not be passed by new incoming requests - */ - rq->flags |= REQ_STARTED; - } - - if (!q->boundary_rq || q->boundary_rq == rq) { - q->end_sector = rq_end_sector(rq); - q->boundary_rq = NULL; - } - - if ((rq->flags & REQ_DONTPREP) || !q->prep_rq_fn) - break; - - ret = q->prep_rq_fn(q, rq); - if (ret == BLKPREP_OK) { - break; - } else if (ret == BLKPREP_DEFER) { - /* - * the request may have been (partially) prepped. - * we need to keep this request in the front to - * avoid resource deadlock. REQ_STARTED will - * prevent other fs requests from passing this one. - */ - rq = NULL; - break; - } else if (ret == BLKPREP_KILL) { - int nr_bytes = rq->hard_nr_sectors << 9; - - if (!nr_bytes) - nr_bytes = rq->data_len; - - blkdev_dequeue_request(rq); - rq->flags |= REQ_QUIET; - end_that_request_chunk(rq, 0, nr_bytes); - end_that_request_last(rq); - } else { - printk(KERN_ERR "%s: bad return=%d\n", __FUNCTION__, - ret); - break; - } - } - - return rq; -} - -void elv_dequeue_request(request_queue_t *q, struct request *rq) -{ - BUG_ON(list_empty(&rq->queuelist)); - - list_del_init(&rq->queuelist); - - /* - * the time frame between a request being removed from the lists - * and to it is freed is accounted as io that is in progress at - * the driver side. - */ - if (blk_account_rq(rq)) - q->in_flight++; -} - -int elv_queue_empty(request_queue_t *q) -{ - elevator_t *e = q->elevator; - - if (!list_empty(&q->queue_head)) - return 0; - - if (e->ops->elevator_queue_empty_fn) - return e->ops->elevator_queue_empty_fn(q); - - return 1; -} - -struct request *elv_latter_request(request_queue_t *q, struct request *rq) -{ - struct list_head *next; - - elevator_t *e = q->elevator; - - if (e->ops->elevator_latter_req_fn) - return e->ops->elevator_latter_req_fn(q, rq); - - next = rq->queuelist.next; - if (next != &q->queue_head && next != &rq->queuelist) - return list_entry_rq(next); - - return NULL; -} - -struct request *elv_former_request(request_queue_t *q, struct request *rq) -{ - struct list_head *prev; - - elevator_t *e = q->elevator; - - if (e->ops->elevator_former_req_fn) - return e->ops->elevator_former_req_fn(q, rq); - - prev = rq->queuelist.prev; - if (prev != &q->queue_head && prev != &rq->queuelist) - return list_entry_rq(prev); - - return NULL; -} - -int elv_set_request(request_queue_t *q, struct request *rq, struct bio *bio, - gfp_t gfp_mask) -{ - elevator_t *e = q->elevator; - - if (e->ops->elevator_set_req_fn) - return e->ops->elevator_set_req_fn(q, rq, bio, gfp_mask); - - rq->elevator_private = NULL; - return 0; -} - -void elv_put_request(request_queue_t *q, struct request *rq) -{ - elevator_t *e = q->elevator; - - if (e->ops->elevator_put_req_fn) - e->ops->elevator_put_req_fn(q, rq); -} - -int elv_may_queue(request_queue_t *q, int rw, struct bio *bio) -{ - elevator_t *e = q->elevator; - - if (e->ops->elevator_may_queue_fn) - return e->ops->elevator_may_queue_fn(q, rw, bio); - - return ELV_MQUEUE_MAY; -} - -void elv_completed_request(request_queue_t *q, struct request *rq) -{ - elevator_t *e = q->elevator; - - /* - * request is released from the driver, io must be done - */ - if (blk_account_rq(rq)) { - q->in_flight--; - if (blk_sorted_rq(rq) && e->ops->elevator_completed_req_fn) - e->ops->elevator_completed_req_fn(q, rq); - } -} - -int elv_register_queue(struct request_queue *q) -{ - elevator_t *e = q->elevator; - - e->kobj.parent = kobject_get(&q->kobj); - if (!e->kobj.parent) - return -EBUSY; - - snprintf(e->kobj.name, KOBJ_NAME_LEN, "%s", "iosched"); - e->kobj.ktype = e->elevator_type->elevator_ktype; - - return kobject_register(&e->kobj); -} - -void elv_unregister_queue(struct request_queue *q) -{ - if (q) { - elevator_t *e = q->elevator; - kobject_unregister(&e->kobj); - kobject_put(&q->kobj); - } -} - -int elv_register(struct elevator_type *e) -{ - spin_lock_irq(&elv_list_lock); - if (elevator_find(e->elevator_name)) - BUG(); - list_add_tail(&e->list, &elv_list); - spin_unlock_irq(&elv_list_lock); - - printk(KERN_INFO "io scheduler %s registered", e->elevator_name); - if (!strcmp(e->elevator_name, chosen_elevator)) - printk(" (default)"); - printk("\n"); - return 0; -} -EXPORT_SYMBOL_GPL(elv_register); - -void elv_unregister(struct elevator_type *e) -{ - struct task_struct *g, *p; - - /* - * Iterate every thread in the process to remove the io contexts. - */ - read_lock(&tasklist_lock); - do_each_thread(g, p) { - struct io_context *ioc = p->io_context; - if (ioc && ioc->cic) { - ioc->cic->exit(ioc->cic); - ioc->cic->dtor(ioc->cic); - ioc->cic = NULL; - } - if (ioc && ioc->aic) { - ioc->aic->exit(ioc->aic); - ioc->aic->dtor(ioc->aic); - ioc->aic = NULL; - } - } while_each_thread(g, p); - read_unlock(&tasklist_lock); - - spin_lock_irq(&elv_list_lock); - list_del_init(&e->list); - spin_unlock_irq(&elv_list_lock); -} -EXPORT_SYMBOL_GPL(elv_unregister); - -/* - * switch to new_e io scheduler. be careful not to introduce deadlocks - - * we don't free the old io scheduler, before we have allocated what we - * need for the new one. this way we have a chance of going back to the old - * one, if the new one fails init for some reason. - */ -static void elevator_switch(request_queue_t *q, struct elevator_type *new_e) -{ - elevator_t *old_elevator, *e; - - /* - * Allocate new elevator - */ - e = kmalloc(sizeof(elevator_t), GFP_KERNEL); - if (!e) - goto error; - - /* - * Turn on BYPASS and drain all requests w/ elevator private data - */ - spin_lock_irq(q->queue_lock); - - set_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); - - while (q->elevator->ops->elevator_dispatch_fn(q, 1)) - ; - - while (q->rq.elvpriv) { - spin_unlock_irq(q->queue_lock); - msleep(10); - spin_lock_irq(q->queue_lock); - } - - spin_unlock_irq(q->queue_lock); - - /* - * unregister old elevator data - */ - elv_unregister_queue(q); - old_elevator = q->elevator; - - /* - * attach and start new elevator - */ - if (elevator_attach(q, new_e, e)) - goto fail; - - if (elv_register_queue(q)) - goto fail_register; - - /* - * finally exit old elevator and turn off BYPASS. - */ - elevator_exit(old_elevator); - clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); - return; - -fail_register: - /* - * switch failed, exit the new io scheduler and reattach the old - * one again (along with re-adding the sysfs dir) - */ - elevator_exit(e); - e = NULL; -fail: - q->elevator = old_elevator; - elv_register_queue(q); - clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); - kfree(e); -error: - elevator_put(new_e); - printk(KERN_ERR "elevator: switch to %s failed\n",new_e->elevator_name); -} - -ssize_t elv_iosched_store(request_queue_t *q, const char *name, size_t count) -{ - char elevator_name[ELV_NAME_MAX]; - struct elevator_type *e; - - memset(elevator_name, 0, sizeof(elevator_name)); - strncpy(elevator_name, name, sizeof(elevator_name)); - - if (elevator_name[strlen(elevator_name) - 1] == '\n') - elevator_name[strlen(elevator_name) - 1] = '\0'; - - e = elevator_get(elevator_name); - if (!e) { - printk(KERN_ERR "elevator: type %s not found\n", elevator_name); - return -EINVAL; - } - - if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name)) { - elevator_put(e); - return count; - } - - elevator_switch(q, e); - return count; -} - -ssize_t elv_iosched_show(request_queue_t *q, char *name) -{ - elevator_t *e = q->elevator; - struct elevator_type *elv = e->elevator_type; - struct list_head *entry; - int len = 0; - - spin_lock_irq(q->queue_lock); - list_for_each(entry, &elv_list) { - struct elevator_type *__e; - - __e = list_entry(entry, struct elevator_type, list); - if (!strcmp(elv->elevator_name, __e->elevator_name)) - len += sprintf(name+len, "[%s] ", elv->elevator_name); - else - len += sprintf(name+len, "%s ", __e->elevator_name); - } - spin_unlock_irq(q->queue_lock); - - len += sprintf(len+name, "\n"); - return len; -} - -EXPORT_SYMBOL(elv_dispatch_sort); -EXPORT_SYMBOL(elv_add_request); -EXPORT_SYMBOL(__elv_add_request); -EXPORT_SYMBOL(elv_requeue_request); -EXPORT_SYMBOL(elv_next_request); -EXPORT_SYMBOL(elv_dequeue_request); -EXPORT_SYMBOL(elv_queue_empty); -EXPORT_SYMBOL(elv_completed_request); -EXPORT_SYMBOL(elevator_exit); -EXPORT_SYMBOL(elevator_init); diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c deleted file mode 100644 index 54aec4a1ae1..00000000000 --- a/drivers/block/genhd.c +++ /dev/null @@ -1,726 +0,0 @@ -/* - * gendisk handling - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAX_PROBE_HASH 255 /* random */ - -static struct subsystem block_subsys; - -static DECLARE_MUTEX(block_subsys_sem); - -/* - * Can be deleted altogether. Later. - * - */ -static struct blk_major_name { - struct blk_major_name *next; - int major; - char name[16]; -} *major_names[MAX_PROBE_HASH]; - -/* index in the above - for now: assume no multimajor ranges */ -static inline int major_to_index(int major) -{ - return major % MAX_PROBE_HASH; -} - -#ifdef CONFIG_PROC_FS -/* get block device names in somewhat random order */ -int get_blkdev_list(char *p, int used) -{ - struct blk_major_name *n; - int i, len; - - len = snprintf(p, (PAGE_SIZE-used), "\nBlock devices:\n"); - - down(&block_subsys_sem); - for (i = 0; i < ARRAY_SIZE(major_names); i++) { - for (n = major_names[i]; n; n = n->next) { - /* - * If the curent string plus the 5 extra characters - * in the line would run us off the page, then we're done - */ - if ((len + used + strlen(n->name) + 5) >= PAGE_SIZE) - goto page_full; - len += sprintf(p+len, "%3d %s\n", - n->major, n->name); - } - } -page_full: - up(&block_subsys_sem); - - return len; -} -#endif - -int register_blkdev(unsigned int major, const char *name) -{ - struct blk_major_name **n, *p; - int index, ret = 0; - - down(&block_subsys_sem); - - /* temporary */ - if (major == 0) { - for (index = ARRAY_SIZE(major_names)-1; index > 0; index--) { - if (major_names[index] == NULL) - break; - } - - if (index == 0) { - printk("register_blkdev: failed to get major for %s\n", - name); - ret = -EBUSY; - goto out; - } - major = index; - ret = major; - } - - p = kmalloc(sizeof(struct blk_major_name), GFP_KERNEL); - if (p == NULL) { - ret = -ENOMEM; - goto out; - } - - p->major = major; - strlcpy(p->name, name, sizeof(p->name)); - p->next = NULL; - index = major_to_index(major); - - for (n = &major_names[index]; *n; n = &(*n)->next) { - if ((*n)->major == major) - break; - } - if (!*n) - *n = p; - else - ret = -EBUSY; - - if (ret < 0) { - printk("register_blkdev: cannot get major %d for %s\n", - major, name); - kfree(p); - } -out: - up(&block_subsys_sem); - return ret; -} - -EXPORT_SYMBOL(register_blkdev); - -/* todo: make void - error printk here */ -int unregister_blkdev(unsigned int major, const char *name) -{ - struct blk_major_name **n; - struct blk_major_name *p = NULL; - int index = major_to_index(major); - int ret = 0; - - down(&block_subsys_sem); - for (n = &major_names[index]; *n; n = &(*n)->next) - if ((*n)->major == major) - break; - if (!*n || strcmp((*n)->name, name)) - ret = -EINVAL; - else { - p = *n; - *n = p->next; - } - up(&block_subsys_sem); - kfree(p); - - return ret; -} - -EXPORT_SYMBOL(unregister_blkdev); - -static struct kobj_map *bdev_map; - -/* - * Register device numbers dev..(dev+range-1) - * range must be nonzero - * The hash chain is sorted on range, so that subranges can override. - */ -void blk_register_region(dev_t dev, unsigned long range, struct module *module, - struct kobject *(*probe)(dev_t, int *, void *), - int (*lock)(dev_t, void *), void *data) -{ - kobj_map(bdev_map, dev, range, module, probe, lock, data); -} - -EXPORT_SYMBOL(blk_register_region); - -void blk_unregister_region(dev_t dev, unsigned long range) -{ - kobj_unmap(bdev_map, dev, range); -} - -EXPORT_SYMBOL(blk_unregister_region); - -static struct kobject *exact_match(dev_t dev, int *part, void *data) -{ - struct gendisk *p = data; - return &p->kobj; -} - -static int exact_lock(dev_t dev, void *data) -{ - struct gendisk *p = data; - - if (!get_disk(p)) - return -1; - return 0; -} - -/** - * add_disk - add partitioning information to kernel list - * @disk: per-device partitioning information - * - * This function registers the partitioning information in @disk - * with the kernel. - */ -void add_disk(struct gendisk *disk) -{ - disk->flags |= GENHD_FL_UP; - blk_register_region(MKDEV(disk->major, disk->first_minor), - disk->minors, NULL, exact_match, exact_lock, disk); - register_disk(disk); - blk_register_queue(disk); -} - -EXPORT_SYMBOL(add_disk); -EXPORT_SYMBOL(del_gendisk); /* in partitions/check.c */ - -void unlink_gendisk(struct gendisk *disk) -{ - blk_unregister_queue(disk); - blk_unregister_region(MKDEV(disk->major, disk->first_minor), - disk->minors); -} - -#define to_disk(obj) container_of(obj,struct gendisk,kobj) - -/** - * get_gendisk - get partitioning information for a given device - * @dev: device to get partitioning information for - * - * This function gets the structure containing partitioning - * information for the given device @dev. - */ -struct gendisk *get_gendisk(dev_t dev, int *part) -{ - struct kobject *kobj = kobj_lookup(bdev_map, dev, part); - return kobj ? to_disk(kobj) : NULL; -} - -#ifdef CONFIG_PROC_FS -/* iterator */ -static void *part_start(struct seq_file *part, loff_t *pos) -{ - struct list_head *p; - loff_t l = *pos; - - down(&block_subsys_sem); - list_for_each(p, &block_subsys.kset.list) - if (!l--) - return list_entry(p, struct gendisk, kobj.entry); - return NULL; -} - -static void *part_next(struct seq_file *part, void *v, loff_t *pos) -{ - struct list_head *p = ((struct gendisk *)v)->kobj.entry.next; - ++*pos; - return p==&block_subsys.kset.list ? NULL : - list_entry(p, struct gendisk, kobj.entry); -} - -static void part_stop(struct seq_file *part, void *v) -{ - up(&block_subsys_sem); -} - -static int show_partition(struct seq_file *part, void *v) -{ - struct gendisk *sgp = v; - int n; - char buf[BDEVNAME_SIZE]; - - if (&sgp->kobj.entry == block_subsys.kset.list.next) - seq_puts(part, "major minor #blocks name\n\n"); - - /* Don't show non-partitionable removeable devices or empty devices */ - if (!get_capacity(sgp) || - (sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE))) - return 0; - if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO) - return 0; - - /* show the full disk and all non-0 size partitions of it */ - seq_printf(part, "%4d %4d %10llu %s\n", - sgp->major, sgp->first_minor, - (unsigned long long)get_capacity(sgp) >> 1, - disk_name(sgp, 0, buf)); - for (n = 0; n < sgp->minors - 1; n++) { - if (!sgp->part[n]) - continue; - if (sgp->part[n]->nr_sects == 0) - continue; - seq_printf(part, "%4d %4d %10llu %s\n", - sgp->major, n + 1 + sgp->first_minor, - (unsigned long long)sgp->part[n]->nr_sects >> 1 , - disk_name(sgp, n + 1, buf)); - } - - return 0; -} - -struct seq_operations partitions_op = { - .start =part_start, - .next = part_next, - .stop = part_stop, - .show = show_partition -}; -#endif - - -extern int blk_dev_init(void); - -static struct kobject *base_probe(dev_t dev, int *part, void *data) -{ - if (request_module("block-major-%d-%d", MAJOR(dev), MINOR(dev)) > 0) - /* Make old-style 2.4 aliases work */ - request_module("block-major-%d", MAJOR(dev)); - return NULL; -} - -static int __init genhd_device_init(void) -{ - bdev_map = kobj_map_init(base_probe, &block_subsys_sem); - blk_dev_init(); - subsystem_register(&block_subsys); - return 0; -} - -subsys_initcall(genhd_device_init); - - - -/* - * kobject & sysfs bindings for block devices - */ -static ssize_t disk_attr_show(struct kobject *kobj, struct attribute *attr, - char *page) -{ - struct gendisk *disk = to_disk(kobj); - struct disk_attribute *disk_attr = - container_of(attr,struct disk_attribute,attr); - ssize_t ret = -EIO; - - if (disk_attr->show) - ret = disk_attr->show(disk,page); - return ret; -} - -static ssize_t disk_attr_store(struct kobject * kobj, struct attribute * attr, - const char *page, size_t count) -{ - struct gendisk *disk = to_disk(kobj); - struct disk_attribute *disk_attr = - container_of(attr,struct disk_attribute,attr); - ssize_t ret = 0; - - if (disk_attr->store) - ret = disk_attr->store(disk, page, count); - return ret; -} - -static struct sysfs_ops disk_sysfs_ops = { - .show = &disk_attr_show, - .store = &disk_attr_store, -}; - -static ssize_t disk_uevent_store(struct gendisk * disk, - const char *buf, size_t count) -{ - kobject_hotplug(&disk->kobj, KOBJ_ADD); - return count; -} -static ssize_t disk_dev_read(struct gendisk * disk, char *page) -{ - dev_t base = MKDEV(disk->major, disk->first_minor); - return print_dev_t(page, base); -} -static ssize_t disk_range_read(struct gendisk * disk, char *page) -{ - return sprintf(page, "%d\n", disk->minors); -} -static ssize_t disk_removable_read(struct gendisk * disk, char *page) -{ - return sprintf(page, "%d\n", - (disk->flags & GENHD_FL_REMOVABLE ? 1 : 0)); - -} -static ssize_t disk_size_read(struct gendisk * disk, char *page) -{ - return sprintf(page, "%llu\n", (unsigned long long)get_capacity(disk)); -} - -static ssize_t disk_stats_read(struct gendisk * disk, char *page) -{ - preempt_disable(); - disk_round_stats(disk); - preempt_enable(); - return sprintf(page, - "%8u %8u %8llu %8u " - "%8u %8u %8llu %8u " - "%8u %8u %8u" - "\n", - disk_stat_read(disk, ios[0]), disk_stat_read(disk, merges[0]), - (unsigned long long)disk_stat_read(disk, sectors[0]), - jiffies_to_msecs(disk_stat_read(disk, ticks[0])), - disk_stat_read(disk, ios[1]), disk_stat_read(disk, merges[1]), - (unsigned long long)disk_stat_read(disk, sectors[1]), - jiffies_to_msecs(disk_stat_read(disk, ticks[1])), - disk->in_flight, - jiffies_to_msecs(disk_stat_read(disk, io_ticks)), - jiffies_to_msecs(disk_stat_read(disk, time_in_queue))); -} -static struct disk_attribute disk_attr_uevent = { - .attr = {.name = "uevent", .mode = S_IWUSR }, - .store = disk_uevent_store -}; -static struct disk_attribute disk_attr_dev = { - .attr = {.name = "dev", .mode = S_IRUGO }, - .show = disk_dev_read -}; -static struct disk_attribute disk_attr_range = { - .attr = {.name = "range", .mode = S_IRUGO }, - .show = disk_range_read -}; -static struct disk_attribute disk_attr_removable = { - .attr = {.name = "removable", .mode = S_IRUGO }, - .show = disk_removable_read -}; -static struct disk_attribute disk_attr_size = { - .attr = {.name = "size", .mode = S_IRUGO }, - .show = disk_size_read -}; -static struct disk_attribute disk_attr_stat = { - .attr = {.name = "stat", .mode = S_IRUGO }, - .show = disk_stats_read -}; - -static struct attribute * default_attrs[] = { - &disk_attr_uevent.attr, - &disk_attr_dev.attr, - &disk_attr_range.attr, - &disk_attr_removable.attr, - &disk_attr_size.attr, - &disk_attr_stat.attr, - NULL, -}; - -static void disk_release(struct kobject * kobj) -{ - struct gendisk *disk = to_disk(kobj); - kfree(disk->random); - kfree(disk->part); - free_disk_stats(disk); - kfree(disk); -} - -static struct kobj_type ktype_block = { - .release = disk_release, - .sysfs_ops = &disk_sysfs_ops, - .default_attrs = default_attrs, -}; - -extern struct kobj_type ktype_part; - -static int block_hotplug_filter(struct kset *kset, struct kobject *kobj) -{ - struct kobj_type *ktype = get_ktype(kobj); - - return ((ktype == &ktype_block) || (ktype == &ktype_part)); -} - -static int block_hotplug(struct kset *kset, struct kobject *kobj, char **envp, - int num_envp, char *buffer, int buffer_size) -{ - struct kobj_type *ktype = get_ktype(kobj); - struct device *physdev; - struct gendisk *disk; - struct hd_struct *part; - int length = 0; - int i = 0; - - if (ktype == &ktype_block) { - disk = container_of(kobj, struct gendisk, kobj); - add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, - &length, "MINOR=%u", disk->first_minor); - } else if (ktype == &ktype_part) { - disk = container_of(kobj->parent, struct gendisk, kobj); - part = container_of(kobj, struct hd_struct, kobj); - add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, - &length, "MINOR=%u", - disk->first_minor + part->partno); - } else - return 0; - - add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &length, - "MAJOR=%u", disk->major); - - /* add physical device, backing this device */ - physdev = disk->driverfs_dev; - if (physdev) { - char *path = kobject_get_path(&physdev->kobj, GFP_KERNEL); - - add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, - &length, "PHYSDEVPATH=%s", path); - kfree(path); - - if (physdev->bus) - add_hotplug_env_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVBUS=%s", - physdev->bus->name); - - if (physdev->driver) - add_hotplug_env_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVDRIVER=%s", - physdev->driver->name); - } - - /* terminate, set to next free slot, shrink available space */ - envp[i] = NULL; - envp = &envp[i]; - num_envp -= i; - buffer = &buffer[length]; - buffer_size -= length; - - return 0; -} - -static struct kset_hotplug_ops block_hotplug_ops = { - .filter = block_hotplug_filter, - .hotplug = block_hotplug, -}; - -/* declare block_subsys. */ -static decl_subsys(block, &ktype_block, &block_hotplug_ops); - - -/* - * aggregate disk stat collector. Uses the same stats that the sysfs - * entries do, above, but makes them available through one seq_file. - * Watching a few disks may be efficient through sysfs, but watching - * all of them will be more efficient through this interface. - * - * The output looks suspiciously like /proc/partitions with a bunch of - * extra fields. - */ - -/* iterator */ -static void *diskstats_start(struct seq_file *part, loff_t *pos) -{ - loff_t k = *pos; - struct list_head *p; - - down(&block_subsys_sem); - list_for_each(p, &block_subsys.kset.list) - if (!k--) - return list_entry(p, struct gendisk, kobj.entry); - return NULL; -} - -static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos) -{ - struct list_head *p = ((struct gendisk *)v)->kobj.entry.next; - ++*pos; - return p==&block_subsys.kset.list ? NULL : - list_entry(p, struct gendisk, kobj.entry); -} - -static void diskstats_stop(struct seq_file *part, void *v) -{ - up(&block_subsys_sem); -} - -static int diskstats_show(struct seq_file *s, void *v) -{ - struct gendisk *gp = v; - char buf[BDEVNAME_SIZE]; - int n = 0; - - /* - if (&sgp->kobj.entry == block_subsys.kset.list.next) - seq_puts(s, "major minor name" - " rio rmerge rsect ruse wio wmerge " - "wsect wuse running use aveq" - "\n\n"); - */ - - preempt_disable(); - disk_round_stats(gp); - preempt_enable(); - seq_printf(s, "%4d %4d %s %u %u %llu %u %u %u %llu %u %u %u %u\n", - gp->major, n + gp->first_minor, disk_name(gp, n, buf), - disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]), - (unsigned long long)disk_stat_read(gp, sectors[0]), - jiffies_to_msecs(disk_stat_read(gp, ticks[0])), - disk_stat_read(gp, ios[1]), disk_stat_read(gp, merges[1]), - (unsigned long long)disk_stat_read(gp, sectors[1]), - jiffies_to_msecs(disk_stat_read(gp, ticks[1])), - gp->in_flight, - jiffies_to_msecs(disk_stat_read(gp, io_ticks)), - jiffies_to_msecs(disk_stat_read(gp, time_in_queue))); - - /* now show all non-0 size partitions of it */ - for (n = 0; n < gp->minors - 1; n++) { - struct hd_struct *hd = gp->part[n]; - - if (hd && hd->nr_sects) - seq_printf(s, "%4d %4d %s %u %u %u %u\n", - gp->major, n + gp->first_minor + 1, - disk_name(gp, n + 1, buf), - hd->ios[0], hd->sectors[0], - hd->ios[1], hd->sectors[1]); - } - - return 0; -} - -struct seq_operations diskstats_op = { - .start = diskstats_start, - .next = diskstats_next, - .stop = diskstats_stop, - .show = diskstats_show -}; - -struct gendisk *alloc_disk(int minors) -{ - return alloc_disk_node(minors, -1); -} - -struct gendisk *alloc_disk_node(int minors, int node_id) -{ - struct gendisk *disk; - - disk = kmalloc_node(sizeof(struct gendisk), GFP_KERNEL, node_id); - if (disk) { - memset(disk, 0, sizeof(struct gendisk)); - if (!init_disk_stats(disk)) { - kfree(disk); - return NULL; - } - if (minors > 1) { - int size = (minors - 1) * sizeof(struct hd_struct *); - disk->part = kmalloc_node(size, GFP_KERNEL, node_id); - if (!disk->part) { - kfree(disk); - return NULL; - } - memset(disk->part, 0, size); - } - disk->minors = minors; - kobj_set_kset_s(disk,block_subsys); - kobject_init(&disk->kobj); - rand_initialize_disk(disk); - } - return disk; -} - -EXPORT_SYMBOL(alloc_disk); -EXPORT_SYMBOL(alloc_disk_node); - -struct kobject *get_disk(struct gendisk *disk) -{ - struct module *owner; - struct kobject *kobj; - - if (!disk->fops) - return NULL; - owner = disk->fops->owner; - if (owner && !try_module_get(owner)) - return NULL; - kobj = kobject_get(&disk->kobj); - if (kobj == NULL) { - module_put(owner); - return NULL; - } - return kobj; - -} - -EXPORT_SYMBOL(get_disk); - -void put_disk(struct gendisk *disk) -{ - if (disk) - kobject_put(&disk->kobj); -} - -EXPORT_SYMBOL(put_disk); - -void set_device_ro(struct block_device *bdev, int flag) -{ - if (bdev->bd_contains != bdev) - bdev->bd_part->policy = flag; - else - bdev->bd_disk->policy = flag; -} - -EXPORT_SYMBOL(set_device_ro); - -void set_disk_ro(struct gendisk *disk, int flag) -{ - int i; - disk->policy = flag; - for (i = 0; i < disk->minors - 1; i++) - if (disk->part[i]) disk->part[i]->policy = flag; -} - -EXPORT_SYMBOL(set_disk_ro); - -int bdev_read_only(struct block_device *bdev) -{ - if (!bdev) - return 0; - else if (bdev->bd_contains != bdev) - return bdev->bd_part->policy; - else - return bdev->bd_disk->policy; -} - -EXPORT_SYMBOL(bdev_read_only); - -int invalidate_partition(struct gendisk *disk, int index) -{ - int res = 0; - struct block_device *bdev = bdget_disk(disk, index); - if (bdev) { - fsync_bdev(bdev); - res = __invalidate_device(bdev); - bdput(bdev); - } - return res; -} - -EXPORT_SYMBOL(invalidate_partition); diff --git a/drivers/block/ioctl.c b/drivers/block/ioctl.c deleted file mode 100644 index 6e278474f9a..00000000000 --- a/drivers/block/ioctl.c +++ /dev/null @@ -1,275 +0,0 @@ -#include /* for capable() */ -#include -#include -#include -#include -#include -#include - -static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user *arg) -{ - struct block_device *bdevp; - struct gendisk *disk; - struct blkpg_ioctl_arg a; - struct blkpg_partition p; - long long start, length; - int part; - int i; - - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg))) - return -EFAULT; - if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition))) - return -EFAULT; - disk = bdev->bd_disk; - if (bdev != bdev->bd_contains) - return -EINVAL; - part = p.pno; - if (part <= 0 || part >= disk->minors) - return -EINVAL; - switch (a.op) { - case BLKPG_ADD_PARTITION: - start = p.start >> 9; - length = p.length >> 9; - /* check for fit in a hd_struct */ - if (sizeof(sector_t) == sizeof(long) && - sizeof(long long) > sizeof(long)) { - long pstart = start, plength = length; - if (pstart != start || plength != length - || pstart < 0 || plength < 0) - return -EINVAL; - } - /* partition number in use? */ - down(&bdev->bd_sem); - if (disk->part[part - 1]) { - up(&bdev->bd_sem); - return -EBUSY; - } - /* overlap? */ - for (i = 0; i < disk->minors - 1; i++) { - struct hd_struct *s = disk->part[i]; - - if (!s) - continue; - if (!(start+length <= s->start_sect || - start >= s->start_sect + s->nr_sects)) { - up(&bdev->bd_sem); - return -EBUSY; - } - } - /* all seems OK */ - add_partition(disk, part, start, length); - up(&bdev->bd_sem); - return 0; - case BLKPG_DEL_PARTITION: - if (!disk->part[part-1]) - return -ENXIO; - if (disk->part[part - 1]->nr_sects == 0) - return -ENXIO; - bdevp = bdget_disk(disk, part); - if (!bdevp) - return -ENOMEM; - down(&bdevp->bd_sem); - if (bdevp->bd_openers) { - up(&bdevp->bd_sem); - bdput(bdevp); - return -EBUSY; - } - /* all seems OK */ - fsync_bdev(bdevp); - invalidate_bdev(bdevp, 0); - - down(&bdev->bd_sem); - delete_partition(disk, part); - up(&bdev->bd_sem); - up(&bdevp->bd_sem); - bdput(bdevp); - - return 0; - default: - return -EINVAL; - } -} - -static int blkdev_reread_part(struct block_device *bdev) -{ - struct gendisk *disk = bdev->bd_disk; - int res; - - if (disk->minors == 1 || bdev != bdev->bd_contains) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (down_trylock(&bdev->bd_sem)) - return -EBUSY; - res = rescan_partitions(disk, bdev); - up(&bdev->bd_sem); - return res; -} - -static int put_ushort(unsigned long arg, unsigned short val) -{ - return put_user(val, (unsigned short __user *)arg); -} - -static int put_int(unsigned long arg, int val) -{ - return put_user(val, (int __user *)arg); -} - -static int put_long(unsigned long arg, long val) -{ - return put_user(val, (long __user *)arg); -} - -static int put_ulong(unsigned long arg, unsigned long val) -{ - return put_user(val, (unsigned long __user *)arg); -} - -static int put_u64(unsigned long arg, u64 val) -{ - return put_user(val, (u64 __user *)arg); -} - -static int blkdev_locked_ioctl(struct file *file, struct block_device *bdev, - unsigned cmd, unsigned long arg) -{ - struct backing_dev_info *bdi; - int ret, n; - - switch (cmd) { - case BLKRAGET: - case BLKFRAGET: - if (!arg) - return -EINVAL; - bdi = blk_get_backing_dev_info(bdev); - if (bdi == NULL) - return -ENOTTY; - return put_long(arg, (bdi->ra_pages * PAGE_CACHE_SIZE) / 512); - case BLKROGET: - return put_int(arg, bdev_read_only(bdev) != 0); - case BLKBSZGET: /* get the logical block size (cf. BLKSSZGET) */ - return put_int(arg, block_size(bdev)); - case BLKSSZGET: /* get block device hardware sector size */ - return put_int(arg, bdev_hardsect_size(bdev)); - case BLKSECTGET: - return put_ushort(arg, bdev_get_queue(bdev)->max_sectors); - case BLKRASET: - case BLKFRASET: - if(!capable(CAP_SYS_ADMIN)) - return -EACCES; - bdi = blk_get_backing_dev_info(bdev); - if (bdi == NULL) - return -ENOTTY; - bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE; - return 0; - case BLKBSZSET: - /* set the logical block size */ - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (!arg) - return -EINVAL; - if (get_user(n, (int __user *) arg)) - return -EFAULT; - if (bd_claim(bdev, file) < 0) - return -EBUSY; - ret = set_blocksize(bdev, n); - bd_release(bdev); - return ret; - case BLKPG: - return blkpg_ioctl(bdev, (struct blkpg_ioctl_arg __user *) arg); - case BLKRRPART: - return blkdev_reread_part(bdev); - case BLKGETSIZE: - if ((bdev->bd_inode->i_size >> 9) > ~0UL) - return -EFBIG; - return put_ulong(arg, bdev->bd_inode->i_size >> 9); - case BLKGETSIZE64: - return put_u64(arg, bdev->bd_inode->i_size); - } - return -ENOIOCTLCMD; -} - -static int blkdev_driver_ioctl(struct inode *inode, struct file *file, - struct gendisk *disk, unsigned cmd, unsigned long arg) -{ - int ret; - if (disk->fops->unlocked_ioctl) - return disk->fops->unlocked_ioctl(file, cmd, arg); - - if (disk->fops->ioctl) { - lock_kernel(); - ret = disk->fops->ioctl(inode, file, cmd, arg); - unlock_kernel(); - return ret; - } - - return -ENOTTY; -} - -int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, - unsigned long arg) -{ - struct block_device *bdev = inode->i_bdev; - struct gendisk *disk = bdev->bd_disk; - int ret, n; - - switch(cmd) { - case BLKFLSBUF: - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - - ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg); - /* -EINVAL to handle old uncorrected drivers */ - if (ret != -EINVAL && ret != -ENOTTY) - return ret; - - lock_kernel(); - fsync_bdev(bdev); - invalidate_bdev(bdev, 0); - unlock_kernel(); - return 0; - - case BLKROSET: - ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg); - /* -EINVAL to handle old uncorrected drivers */ - if (ret != -EINVAL && ret != -ENOTTY) - return ret; - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (get_user(n, (int __user *)(arg))) - return -EFAULT; - lock_kernel(); - set_device_ro(bdev, n); - unlock_kernel(); - return 0; - } - - lock_kernel(); - ret = blkdev_locked_ioctl(file, bdev, cmd, arg); - unlock_kernel(); - if (ret != -ENOIOCTLCMD) - return ret; - - return blkdev_driver_ioctl(inode, file, disk, cmd, arg); -} - -/* Most of the generic ioctls are handled in the normal fallback path. - This assumes the blkdev's low level compat_ioctl always returns - ENOIOCTLCMD for unknown ioctls. */ -long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) -{ - struct block_device *bdev = file->f_dentry->d_inode->i_bdev; - struct gendisk *disk = bdev->bd_disk; - int ret = -ENOIOCTLCMD; - if (disk->fops->compat_ioctl) { - lock_kernel(); - ret = disk->fops->compat_ioctl(file, cmd, arg); - unlock_kernel(); - } - return ret; -} - -EXPORT_SYMBOL_GPL(blkdev_ioctl); diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c deleted file mode 100644 index 2747741677f..00000000000 --- a/drivers/block/ll_rw_blk.c +++ /dev/null @@ -1,3613 +0,0 @@ -/* - * linux/drivers/block/ll_rw_blk.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright (C) 1994, Karl Keyte: Added support for disk statistics - * Elevator latency, (C) 2000 Andrea Arcangeli SuSE - * Queue request tables / lock, selectable elevator, Jens Axboe - * kernel-doc documentation started by NeilBrown - July2000 - * bio rewrite, highmem i/o, etc, Jens Axboe - may 2001 - */ - -/* - * This handles all read/write requests to block devices - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for max_pfn/max_low_pfn */ -#include -#include -#include -#include -#include - -/* - * for max sense size - */ -#include - -static void blk_unplug_work(void *data); -static void blk_unplug_timeout(unsigned long data); -static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io); - -/* - * For the allocated request tables - */ -static kmem_cache_t *request_cachep; - -/* - * For queue allocation - */ -static kmem_cache_t *requestq_cachep; - -/* - * For io context allocations - */ -static kmem_cache_t *iocontext_cachep; - -static wait_queue_head_t congestion_wqh[2] = { - __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[0]), - __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1]) - }; - -/* - * Controlling structure to kblockd - */ -static struct workqueue_struct *kblockd_workqueue; - -unsigned long blk_max_low_pfn, blk_max_pfn; - -EXPORT_SYMBOL(blk_max_low_pfn); -EXPORT_SYMBOL(blk_max_pfn); - -/* Amount of time in which a process may batch requests */ -#define BLK_BATCH_TIME (HZ/50UL) - -/* Number of requests a "batching" process may submit */ -#define BLK_BATCH_REQ 32 - -/* - * Return the threshold (number of used requests) at which the queue is - * considered to be congested. It include a little hysteresis to keep the - * context switch rate down. - */ -static inline int queue_congestion_on_threshold(struct request_queue *q) -{ - return q->nr_congestion_on; -} - -/* - * The threshold at which a queue is considered to be uncongested - */ -static inline int queue_congestion_off_threshold(struct request_queue *q) -{ - return q->nr_congestion_off; -} - -static void blk_queue_congestion_threshold(struct request_queue *q) -{ - int nr; - - nr = q->nr_requests - (q->nr_requests / 8) + 1; - if (nr > q->nr_requests) - nr = q->nr_requests; - q->nr_congestion_on = nr; - - nr = q->nr_requests - (q->nr_requests / 8) - (q->nr_requests / 16) - 1; - if (nr < 1) - nr = 1; - q->nr_congestion_off = nr; -} - -/* - * A queue has just exitted congestion. Note this in the global counter of - * congested queues, and wake up anyone who was waiting for requests to be - * put back. - */ -static void clear_queue_congested(request_queue_t *q, int rw) -{ - enum bdi_state bit; - wait_queue_head_t *wqh = &congestion_wqh[rw]; - - bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested; - clear_bit(bit, &q->backing_dev_info.state); - smp_mb__after_clear_bit(); - if (waitqueue_active(wqh)) - wake_up(wqh); -} - -/* - * A queue has just entered congestion. Flag that in the queue's VM-visible - * state flags and increment the global gounter of congested queues. - */ -static void set_queue_congested(request_queue_t *q, int rw) -{ - enum bdi_state bit; - - bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested; - set_bit(bit, &q->backing_dev_info.state); -} - -/** - * blk_get_backing_dev_info - get the address of a queue's backing_dev_info - * @bdev: device - * - * Locates the passed device's request queue and returns the address of its - * backing_dev_info - * - * Will return NULL if the request queue cannot be located. - */ -struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev) -{ - struct backing_dev_info *ret = NULL; - request_queue_t *q = bdev_get_queue(bdev); - - if (q) - ret = &q->backing_dev_info; - return ret; -} - -EXPORT_SYMBOL(blk_get_backing_dev_info); - -void blk_queue_activity_fn(request_queue_t *q, activity_fn *fn, void *data) -{ - q->activity_fn = fn; - q->activity_data = data; -} - -EXPORT_SYMBOL(blk_queue_activity_fn); - -/** - * blk_queue_prep_rq - set a prepare_request function for queue - * @q: queue - * @pfn: prepare_request function - * - * It's possible for a queue to register a prepare_request callback which - * is invoked before the request is handed to the request_fn. The goal of - * the function is to prepare a request for I/O, it can be used to build a - * cdb from the request data for instance. - * - */ -void blk_queue_prep_rq(request_queue_t *q, prep_rq_fn *pfn) -{ - q->prep_rq_fn = pfn; -} - -EXPORT_SYMBOL(blk_queue_prep_rq); - -/** - * blk_queue_merge_bvec - set a merge_bvec function for queue - * @q: queue - * @mbfn: merge_bvec_fn - * - * Usually queues have static limitations on the max sectors or segments that - * we can put in a request. Stacking drivers may have some settings that - * are dynamic, and thus we have to query the queue whether it is ok to - * add a new bio_vec to a bio at a given offset or not. If the block device - * has such limitations, it needs to register a merge_bvec_fn to control - * the size of bio's sent to it. Note that a block device *must* allow a - * single page to be added to an empty bio. The block device driver may want - * to use the bio_split() function to deal with these bio's. By default - * no merge_bvec_fn is defined for a queue, and only the fixed limits are - * honored. - */ -void blk_queue_merge_bvec(request_queue_t *q, merge_bvec_fn *mbfn) -{ - q->merge_bvec_fn = mbfn; -} - -EXPORT_SYMBOL(blk_queue_merge_bvec); - -/** - * blk_queue_make_request - define an alternate make_request function for a device - * @q: the request queue for the device to be affected - * @mfn: the alternate make_request function - * - * Description: - * The normal way for &struct bios to be passed to a device - * driver is for them to be collected into requests on a request - * queue, and then to allow the device driver to select requests - * off that queue when it is ready. This works well for many block - * devices. However some block devices (typically virtual devices - * such as md or lvm) do not benefit from the processing on the - * request queue, and are served best by having the requests passed - * directly to them. This can be achieved by providing a function - * to blk_queue_make_request(). - * - * Caveat: - * The driver that does this *must* be able to deal appropriately - * with buffers in "highmemory". This can be accomplished by either calling - * __bio_kmap_atomic() to get a temporary kernel mapping, or by calling - * blk_queue_bounce() to create a buffer in normal memory. - **/ -void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn) -{ - /* - * set defaults - */ - q->nr_requests = BLKDEV_MAX_RQ; - blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS); - blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS); - q->make_request_fn = mfn; - q->backing_dev_info.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; - q->backing_dev_info.state = 0; - q->backing_dev_info.capabilities = BDI_CAP_MAP_COPY; - blk_queue_max_sectors(q, MAX_SECTORS); - blk_queue_hardsect_size(q, 512); - blk_queue_dma_alignment(q, 511); - blk_queue_congestion_threshold(q); - q->nr_batching = BLK_BATCH_REQ; - - q->unplug_thresh = 4; /* hmm */ - q->unplug_delay = (3 * HZ) / 1000; /* 3 milliseconds */ - if (q->unplug_delay == 0) - q->unplug_delay = 1; - - INIT_WORK(&q->unplug_work, blk_unplug_work, q); - - q->unplug_timer.function = blk_unplug_timeout; - q->unplug_timer.data = (unsigned long)q; - - /* - * by default assume old behaviour and bounce for any highmem page - */ - blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH); - - blk_queue_activity_fn(q, NULL, NULL); -} - -EXPORT_SYMBOL(blk_queue_make_request); - -static inline void rq_init(request_queue_t *q, struct request *rq) -{ - INIT_LIST_HEAD(&rq->queuelist); - - rq->errors = 0; - rq->rq_status = RQ_ACTIVE; - rq->bio = rq->biotail = NULL; - rq->ioprio = 0; - rq->buffer = NULL; - rq->ref_count = 1; - rq->q = q; - rq->waiting = NULL; - rq->special = NULL; - rq->data_len = 0; - rq->data = NULL; - rq->nr_phys_segments = 0; - rq->sense = NULL; - rq->end_io = NULL; - rq->end_io_data = NULL; -} - -/** - * blk_queue_ordered - does this queue support ordered writes - * @q: the request queue - * @flag: see below - * - * Description: - * For journalled file systems, doing ordered writes on a commit - * block instead of explicitly doing wait_on_buffer (which is bad - * for performance) can be a big win. Block drivers supporting this - * feature should call this function and indicate so. - * - **/ -void blk_queue_ordered(request_queue_t *q, int flag) -{ - switch (flag) { - case QUEUE_ORDERED_NONE: - if (q->flush_rq) - kmem_cache_free(request_cachep, q->flush_rq); - q->flush_rq = NULL; - q->ordered = flag; - break; - case QUEUE_ORDERED_TAG: - q->ordered = flag; - break; - case QUEUE_ORDERED_FLUSH: - q->ordered = flag; - if (!q->flush_rq) - q->flush_rq = kmem_cache_alloc(request_cachep, - GFP_KERNEL); - break; - default: - printk("blk_queue_ordered: bad value %d\n", flag); - break; - } -} - -EXPORT_SYMBOL(blk_queue_ordered); - -/** - * blk_queue_issue_flush_fn - set function for issuing a flush - * @q: the request queue - * @iff: the function to be called issuing the flush - * - * Description: - * If a driver supports issuing a flush command, the support is notified - * to the block layer by defining it through this call. - * - **/ -void blk_queue_issue_flush_fn(request_queue_t *q, issue_flush_fn *iff) -{ - q->issue_flush_fn = iff; -} - -EXPORT_SYMBOL(blk_queue_issue_flush_fn); - -/* - * Cache flushing for ordered writes handling - */ -static void blk_pre_flush_end_io(struct request *flush_rq) -{ - struct request *rq = flush_rq->end_io_data; - request_queue_t *q = rq->q; - - elv_completed_request(q, flush_rq); - - rq->flags |= REQ_BAR_PREFLUSH; - - if (!flush_rq->errors) - elv_requeue_request(q, rq); - else { - q->end_flush_fn(q, flush_rq); - clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags); - q->request_fn(q); - } -} - -static void blk_post_flush_end_io(struct request *flush_rq) -{ - struct request *rq = flush_rq->end_io_data; - request_queue_t *q = rq->q; - - elv_completed_request(q, flush_rq); - - rq->flags |= REQ_BAR_POSTFLUSH; - - q->end_flush_fn(q, flush_rq); - clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags); - q->request_fn(q); -} - -struct request *blk_start_pre_flush(request_queue_t *q, struct request *rq) -{ - struct request *flush_rq = q->flush_rq; - - BUG_ON(!blk_barrier_rq(rq)); - - if (test_and_set_bit(QUEUE_FLAG_FLUSH, &q->queue_flags)) - return NULL; - - rq_init(q, flush_rq); - flush_rq->elevator_private = NULL; - flush_rq->flags = REQ_BAR_FLUSH; - flush_rq->rq_disk = rq->rq_disk; - flush_rq->rl = NULL; - - /* - * prepare_flush returns 0 if no flush is needed, just mark both - * pre and post flush as done in that case - */ - if (!q->prepare_flush_fn(q, flush_rq)) { - rq->flags |= REQ_BAR_PREFLUSH | REQ_BAR_POSTFLUSH; - clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags); - return rq; - } - - /* - * some drivers dequeue requests right away, some only after io - * completion. make sure the request is dequeued. - */ - if (!list_empty(&rq->queuelist)) - blkdev_dequeue_request(rq); - - flush_rq->end_io_data = rq; - flush_rq->end_io = blk_pre_flush_end_io; - - __elv_add_request(q, flush_rq, ELEVATOR_INSERT_FRONT, 0); - return flush_rq; -} - -static void blk_start_post_flush(request_queue_t *q, struct request *rq) -{ - struct request *flush_rq = q->flush_rq; - - BUG_ON(!blk_barrier_rq(rq)); - - rq_init(q, flush_rq); - flush_rq->elevator_private = NULL; - flush_rq->flags = REQ_BAR_FLUSH; - flush_rq->rq_disk = rq->rq_disk; - flush_rq->rl = NULL; - - if (q->prepare_flush_fn(q, flush_rq)) { - flush_rq->end_io_data = rq; - flush_rq->end_io = blk_post_flush_end_io; - - __elv_add_request(q, flush_rq, ELEVATOR_INSERT_FRONT, 0); - q->request_fn(q); - } -} - -static inline int blk_check_end_barrier(request_queue_t *q, struct request *rq, - int sectors) -{ - if (sectors > rq->nr_sectors) - sectors = rq->nr_sectors; - - rq->nr_sectors -= sectors; - return rq->nr_sectors; -} - -static int __blk_complete_barrier_rq(request_queue_t *q, struct request *rq, - int sectors, int queue_locked) -{ - if (q->ordered != QUEUE_ORDERED_FLUSH) - return 0; - if (!blk_fs_request(rq) || !blk_barrier_rq(rq)) - return 0; - if (blk_barrier_postflush(rq)) - return 0; - - if (!blk_check_end_barrier(q, rq, sectors)) { - unsigned long flags = 0; - - if (!queue_locked) - spin_lock_irqsave(q->queue_lock, flags); - - blk_start_post_flush(q, rq); - - if (!queue_locked) - spin_unlock_irqrestore(q->queue_lock, flags); - } - - return 1; -} - -/** - * blk_complete_barrier_rq - complete possible barrier request - * @q: the request queue for the device - * @rq: the request - * @sectors: number of sectors to complete - * - * Description: - * Used in driver end_io handling to determine whether to postpone - * completion of a barrier request until a post flush has been done. This - * is the unlocked variant, used if the caller doesn't already hold the - * queue lock. - **/ -int blk_complete_barrier_rq(request_queue_t *q, struct request *rq, int sectors) -{ - return __blk_complete_barrier_rq(q, rq, sectors, 0); -} -EXPORT_SYMBOL(blk_complete_barrier_rq); - -/** - * blk_complete_barrier_rq_locked - complete possible barrier request - * @q: the request queue for the device - * @rq: the request - * @sectors: number of sectors to complete - * - * Description: - * See blk_complete_barrier_rq(). This variant must be used if the caller - * holds the queue lock. - **/ -int blk_complete_barrier_rq_locked(request_queue_t *q, struct request *rq, - int sectors) -{ - return __blk_complete_barrier_rq(q, rq, sectors, 1); -} -EXPORT_SYMBOL(blk_complete_barrier_rq_locked); - -/** - * blk_queue_bounce_limit - set bounce buffer limit for queue - * @q: the request queue for the device - * @dma_addr: bus address limit - * - * Description: - * Different hardware can have different requirements as to what pages - * it can do I/O directly to. A low level driver can call - * blk_queue_bounce_limit to have lower memory pages allocated as bounce - * buffers for doing I/O to pages residing above @page. By default - * the block layer sets this to the highest numbered "low" memory page. - **/ -void blk_queue_bounce_limit(request_queue_t *q, u64 dma_addr) -{ - unsigned long bounce_pfn = dma_addr >> PAGE_SHIFT; - - /* - * set appropriate bounce gfp mask -- unfortunately we don't have a - * full 4GB zone, so we have to resort to low memory for any bounces. - * ISA has its own < 16MB zone. - */ - if (bounce_pfn < blk_max_low_pfn) { - BUG_ON(dma_addr < BLK_BOUNCE_ISA); - init_emergency_isa_pool(); - q->bounce_gfp = GFP_NOIO | GFP_DMA; - } else - q->bounce_gfp = GFP_NOIO; - - q->bounce_pfn = bounce_pfn; -} - -EXPORT_SYMBOL(blk_queue_bounce_limit); - -/** - * blk_queue_max_sectors - set max sectors for a request for this queue - * @q: the request queue for the device - * @max_sectors: max sectors in the usual 512b unit - * - * Description: - * Enables a low level driver to set an upper limit on the size of - * received requests. - **/ -void blk_queue_max_sectors(request_queue_t *q, unsigned short max_sectors) -{ - if ((max_sectors << 9) < PAGE_CACHE_SIZE) { - max_sectors = 1 << (PAGE_CACHE_SHIFT - 9); - printk("%s: set to minimum %d\n", __FUNCTION__, max_sectors); - } - - q->max_sectors = q->max_hw_sectors = max_sectors; -} - -EXPORT_SYMBOL(blk_queue_max_sectors); - -/** - * blk_queue_max_phys_segments - set max phys segments for a request for this queue - * @q: the request queue for the device - * @max_segments: max number of segments - * - * Description: - * Enables a low level driver to set an upper limit on the number of - * physical data segments in a request. This would be the largest sized - * scatter list the driver could handle. - **/ -void blk_queue_max_phys_segments(request_queue_t *q, unsigned short max_segments) -{ - if (!max_segments) { - max_segments = 1; - printk("%s: set to minimum %d\n", __FUNCTION__, max_segments); - } - - q->max_phys_segments = max_segments; -} - -EXPORT_SYMBOL(blk_queue_max_phys_segments); - -/** - * blk_queue_max_hw_segments - set max hw segments for a request for this queue - * @q: the request queue for the device - * @max_segments: max number of segments - * - * Description: - * Enables a low level driver to set an upper limit on the number of - * hw data segments in a request. This would be the largest number of - * address/length pairs the host adapter can actually give as once - * to the device. - **/ -void blk_queue_max_hw_segments(request_queue_t *q, unsigned short max_segments) -{ - if (!max_segments) { - max_segments = 1; - printk("%s: set to minimum %d\n", __FUNCTION__, max_segments); - } - - q->max_hw_segments = max_segments; -} - -EXPORT_SYMBOL(blk_queue_max_hw_segments); - -/** - * blk_queue_max_segment_size - set max segment size for blk_rq_map_sg - * @q: the request queue for the device - * @max_size: max size of segment in bytes - * - * Description: - * Enables a low level driver to set an upper limit on the size of a - * coalesced segment - **/ -void blk_queue_max_segment_size(request_queue_t *q, unsigned int max_size) -{ - if (max_size < PAGE_CACHE_SIZE) { - max_size = PAGE_CACHE_SIZE; - printk("%s: set to minimum %d\n", __FUNCTION__, max_size); - } - - q->max_segment_size = max_size; -} - -EXPORT_SYMBOL(blk_queue_max_segment_size); - -/** - * blk_queue_hardsect_size - set hardware sector size for the queue - * @q: the request queue for the device - * @size: the hardware sector size, in bytes - * - * Description: - * This should typically be set to the lowest possible sector size - * that the hardware can operate on (possible without reverting to - * even internal read-modify-write operations). Usually the default - * of 512 covers most hardware. - **/ -void blk_queue_hardsect_size(request_queue_t *q, unsigned short size) -{ - q->hardsect_size = size; -} - -EXPORT_SYMBOL(blk_queue_hardsect_size); - -/* - * Returns the minimum that is _not_ zero, unless both are zero. - */ -#define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r)) - -/** - * blk_queue_stack_limits - inherit underlying queue limits for stacked drivers - * @t: the stacking driver (top) - * @b: the underlying device (bottom) - **/ -void blk_queue_stack_limits(request_queue_t *t, request_queue_t *b) -{ - /* zero is "infinity" */ - t->max_sectors = t->max_hw_sectors = - min_not_zero(t->max_sectors,b->max_sectors); - - t->max_phys_segments = min(t->max_phys_segments,b->max_phys_segments); - t->max_hw_segments = min(t->max_hw_segments,b->max_hw_segments); - t->max_segment_size = min(t->max_segment_size,b->max_segment_size); - t->hardsect_size = max(t->hardsect_size,b->hardsect_size); -} - -EXPORT_SYMBOL(blk_queue_stack_limits); - -/** - * blk_queue_segment_boundary - set boundary rules for segment merging - * @q: the request queue for the device - * @mask: the memory boundary mask - **/ -void blk_queue_segment_boundary(request_queue_t *q, unsigned long mask) -{ - if (mask < PAGE_CACHE_SIZE - 1) { - mask = PAGE_CACHE_SIZE - 1; - printk("%s: set to minimum %lx\n", __FUNCTION__, mask); - } - - q->seg_boundary_mask = mask; -} - -EXPORT_SYMBOL(blk_queue_segment_boundary); - -/** - * blk_queue_dma_alignment - set dma length and memory alignment - * @q: the request queue for the device - * @mask: alignment mask - * - * description: - * set required memory and length aligment for direct dma transactions. - * this is used when buiding direct io requests for the queue. - * - **/ -void blk_queue_dma_alignment(request_queue_t *q, int mask) -{ - q->dma_alignment = mask; -} - -EXPORT_SYMBOL(blk_queue_dma_alignment); - -/** - * blk_queue_find_tag - find a request by its tag and queue - * - * @q: The request queue for the device - * @tag: The tag of the request - * - * Notes: - * Should be used when a device returns a tag and you want to match - * it with a request. - * - * no locks need be held. - **/ -struct request *blk_queue_find_tag(request_queue_t *q, int tag) -{ - struct blk_queue_tag *bqt = q->queue_tags; - - if (unlikely(bqt == NULL || tag >= bqt->real_max_depth)) - return NULL; - - return bqt->tag_index[tag]; -} - -EXPORT_SYMBOL(blk_queue_find_tag); - -/** - * __blk_queue_free_tags - release tag maintenance info - * @q: the request queue for the device - * - * Notes: - * blk_cleanup_queue() will take care of calling this function, if tagging - * has been used. So there's no need to call this directly. - **/ -static void __blk_queue_free_tags(request_queue_t *q) -{ - struct blk_queue_tag *bqt = q->queue_tags; - - if (!bqt) - return; - - if (atomic_dec_and_test(&bqt->refcnt)) { - BUG_ON(bqt->busy); - BUG_ON(!list_empty(&bqt->busy_list)); - - kfree(bqt->tag_index); - bqt->tag_index = NULL; - - kfree(bqt->tag_map); - bqt->tag_map = NULL; - - kfree(bqt); - } - - q->queue_tags = NULL; - q->queue_flags &= ~(1 << QUEUE_FLAG_QUEUED); -} - -/** - * blk_queue_free_tags - release tag maintenance info - * @q: the request queue for the device - * - * Notes: - * This is used to disabled tagged queuing to a device, yet leave - * queue in function. - **/ -void blk_queue_free_tags(request_queue_t *q) -{ - clear_bit(QUEUE_FLAG_QUEUED, &q->queue_flags); -} - -EXPORT_SYMBOL(blk_queue_free_tags); - -static int -init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth) -{ - struct request **tag_index; - unsigned long *tag_map; - int nr_ulongs; - - if (depth > q->nr_requests * 2) { - depth = q->nr_requests * 2; - printk(KERN_ERR "%s: adjusted depth to %d\n", - __FUNCTION__, depth); - } - - tag_index = kmalloc(depth * sizeof(struct request *), GFP_ATOMIC); - if (!tag_index) - goto fail; - - nr_ulongs = ALIGN(depth, BITS_PER_LONG) / BITS_PER_LONG; - tag_map = kmalloc(nr_ulongs * sizeof(unsigned long), GFP_ATOMIC); - if (!tag_map) - goto fail; - - memset(tag_index, 0, depth * sizeof(struct request *)); - memset(tag_map, 0, nr_ulongs * sizeof(unsigned long)); - tags->real_max_depth = depth; - tags->max_depth = depth; - tags->tag_index = tag_index; - tags->tag_map = tag_map; - - return 0; -fail: - kfree(tag_index); - return -ENOMEM; -} - -/** - * blk_queue_init_tags - initialize the queue tag info - * @q: the request queue for the device - * @depth: the maximum queue depth supported - * @tags: the tag to use - **/ -int blk_queue_init_tags(request_queue_t *q, int depth, - struct blk_queue_tag *tags) -{ - int rc; - - BUG_ON(tags && q->queue_tags && tags != q->queue_tags); - - if (!tags && !q->queue_tags) { - tags = kmalloc(sizeof(struct blk_queue_tag), GFP_ATOMIC); - if (!tags) - goto fail; - - if (init_tag_map(q, tags, depth)) - goto fail; - - INIT_LIST_HEAD(&tags->busy_list); - tags->busy = 0; - atomic_set(&tags->refcnt, 1); - } else if (q->queue_tags) { - if ((rc = blk_queue_resize_tags(q, depth))) - return rc; - set_bit(QUEUE_FLAG_QUEUED, &q->queue_flags); - return 0; - } else - atomic_inc(&tags->refcnt); - - /* - * assign it, all done - */ - q->queue_tags = tags; - q->queue_flags |= (1 << QUEUE_FLAG_QUEUED); - return 0; -fail: - kfree(tags); - return -ENOMEM; -} - -EXPORT_SYMBOL(blk_queue_init_tags); - -/** - * blk_queue_resize_tags - change the queueing depth - * @q: the request queue for the device - * @new_depth: the new max command queueing depth - * - * Notes: - * Must be called with the queue lock held. - **/ -int blk_queue_resize_tags(request_queue_t *q, int new_depth) -{ - struct blk_queue_tag *bqt = q->queue_tags; - struct request **tag_index; - unsigned long *tag_map; - int max_depth, nr_ulongs; - - if (!bqt) - return -ENXIO; - - /* - * if we already have large enough real_max_depth. just - * adjust max_depth. *NOTE* as requests with tag value - * between new_depth and real_max_depth can be in-flight, tag - * map can not be shrunk blindly here. - */ - if (new_depth <= bqt->real_max_depth) { - bqt->max_depth = new_depth; - return 0; - } - - /* - * save the old state info, so we can copy it back - */ - tag_index = bqt->tag_index; - tag_map = bqt->tag_map; - max_depth = bqt->real_max_depth; - - if (init_tag_map(q, bqt, new_depth)) - return -ENOMEM; - - memcpy(bqt->tag_index, tag_index, max_depth * sizeof(struct request *)); - nr_ulongs = ALIGN(max_depth, BITS_PER_LONG) / BITS_PER_LONG; - memcpy(bqt->tag_map, tag_map, nr_ulongs * sizeof(unsigned long)); - - kfree(tag_index); - kfree(tag_map); - return 0; -} - -EXPORT_SYMBOL(blk_queue_resize_tags); - -/** - * blk_queue_end_tag - end tag operations for a request - * @q: the request queue for the device - * @rq: the request that has completed - * - * Description: - * Typically called when end_that_request_first() returns 0, meaning - * all transfers have been done for a request. It's important to call - * this function before end_that_request_last(), as that will put the - * request back on the free list thus corrupting the internal tag list. - * - * Notes: - * queue lock must be held. - **/ -void blk_queue_end_tag(request_queue_t *q, struct request *rq) -{ - struct blk_queue_tag *bqt = q->queue_tags; - int tag = rq->tag; - - BUG_ON(tag == -1); - - if (unlikely(tag >= bqt->real_max_depth)) - /* - * This can happen after tag depth has been reduced. - * FIXME: how about a warning or info message here? - */ - return; - - if (unlikely(!__test_and_clear_bit(tag, bqt->tag_map))) { - printk(KERN_ERR "%s: attempt to clear non-busy tag (%d)\n", - __FUNCTION__, tag); - return; - } - - list_del_init(&rq->queuelist); - rq->flags &= ~REQ_QUEUED; - rq->tag = -1; - - if (unlikely(bqt->tag_index[tag] == NULL)) - printk(KERN_ERR "%s: tag %d is missing\n", - __FUNCTION__, tag); - - bqt->tag_index[tag] = NULL; - bqt->busy--; -} - -EXPORT_SYMBOL(blk_queue_end_tag); - -/** - * blk_queue_start_tag - find a free tag and assign it - * @q: the request queue for the device - * @rq: the block request that needs tagging - * - * Description: - * This can either be used as a stand-alone helper, or possibly be - * assigned as the queue &prep_rq_fn (in which case &struct request - * automagically gets a tag assigned). Note that this function - * assumes that any type of request can be queued! if this is not - * true for your device, you must check the request type before - * calling this function. The request will also be removed from - * the request queue, so it's the drivers responsibility to readd - * it if it should need to be restarted for some reason. - * - * Notes: - * queue lock must be held. - **/ -int blk_queue_start_tag(request_queue_t *q, struct request *rq) -{ - struct blk_queue_tag *bqt = q->queue_tags; - int tag; - - if (unlikely((rq->flags & REQ_QUEUED))) { - printk(KERN_ERR - "%s: request %p for device [%s] already tagged %d", - __FUNCTION__, rq, - rq->rq_disk ? rq->rq_disk->disk_name : "?", rq->tag); - BUG(); - } - - tag = find_first_zero_bit(bqt->tag_map, bqt->max_depth); - if (tag >= bqt->max_depth) - return 1; - - __set_bit(tag, bqt->tag_map); - - rq->flags |= REQ_QUEUED; - rq->tag = tag; - bqt->tag_index[tag] = rq; - blkdev_dequeue_request(rq); - list_add(&rq->queuelist, &bqt->busy_list); - bqt->busy++; - return 0; -} - -EXPORT_SYMBOL(blk_queue_start_tag); - -/** - * blk_queue_invalidate_tags - invalidate all pending tags - * @q: the request queue for the device - * - * Description: - * Hardware conditions may dictate a need to stop all pending requests. - * In this case, we will safely clear the block side of the tag queue and - * readd all requests to the request queue in the right order. - * - * Notes: - * queue lock must be held. - **/ -void blk_queue_invalidate_tags(request_queue_t *q) -{ - struct blk_queue_tag *bqt = q->queue_tags; - struct list_head *tmp, *n; - struct request *rq; - - list_for_each_safe(tmp, n, &bqt->busy_list) { - rq = list_entry_rq(tmp); - - if (rq->tag == -1) { - printk(KERN_ERR - "%s: bad tag found on list\n", __FUNCTION__); - list_del_init(&rq->queuelist); - rq->flags &= ~REQ_QUEUED; - } else - blk_queue_end_tag(q, rq); - - rq->flags &= ~REQ_STARTED; - __elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 0); - } -} - -EXPORT_SYMBOL(blk_queue_invalidate_tags); - -static char *rq_flags[] = { - "REQ_RW", - "REQ_FAILFAST", - "REQ_SORTED", - "REQ_SOFTBARRIER", - "REQ_HARDBARRIER", - "REQ_CMD", - "REQ_NOMERGE", - "REQ_STARTED", - "REQ_DONTPREP", - "REQ_QUEUED", - "REQ_ELVPRIV", - "REQ_PC", - "REQ_BLOCK_PC", - "REQ_SENSE", - "REQ_FAILED", - "REQ_QUIET", - "REQ_SPECIAL", - "REQ_DRIVE_CMD", - "REQ_DRIVE_TASK", - "REQ_DRIVE_TASKFILE", - "REQ_PREEMPT", - "REQ_PM_SUSPEND", - "REQ_PM_RESUME", - "REQ_PM_SHUTDOWN", -}; - -void blk_dump_rq_flags(struct request *rq, char *msg) -{ - int bit; - - printk("%s: dev %s: flags = ", msg, - rq->rq_disk ? rq->rq_disk->disk_name : "?"); - bit = 0; - do { - if (rq->flags & (1 << bit)) - printk("%s ", rq_flags[bit]); - bit++; - } while (bit < __REQ_NR_BITS); - - printk("\nsector %llu, nr/cnr %lu/%u\n", (unsigned long long)rq->sector, - rq->nr_sectors, - rq->current_nr_sectors); - printk("bio %p, biotail %p, buffer %p, data %p, len %u\n", rq->bio, rq->biotail, rq->buffer, rq->data, rq->data_len); - - if (rq->flags & (REQ_BLOCK_PC | REQ_PC)) { - printk("cdb: "); - for (bit = 0; bit < sizeof(rq->cmd); bit++) - printk("%02x ", rq->cmd[bit]); - printk("\n"); - } -} - -EXPORT_SYMBOL(blk_dump_rq_flags); - -void blk_recount_segments(request_queue_t *q, struct bio *bio) -{ - struct bio_vec *bv, *bvprv = NULL; - int i, nr_phys_segs, nr_hw_segs, seg_size, hw_seg_size, cluster; - int high, highprv = 1; - - if (unlikely(!bio->bi_io_vec)) - return; - - cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER); - hw_seg_size = seg_size = nr_phys_segs = nr_hw_segs = 0; - bio_for_each_segment(bv, bio, i) { - /* - * the trick here is making sure that a high page is never - * considered part of another segment, since that might - * change with the bounce page. - */ - high = page_to_pfn(bv->bv_page) >= q->bounce_pfn; - if (high || highprv) - goto new_hw_segment; - if (cluster) { - if (seg_size + bv->bv_len > q->max_segment_size) - goto new_segment; - if (!BIOVEC_PHYS_MERGEABLE(bvprv, bv)) - goto new_segment; - if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bv)) - goto new_segment; - if (BIOVEC_VIRT_OVERSIZE(hw_seg_size + bv->bv_len)) - goto new_hw_segment; - - seg_size += bv->bv_len; - hw_seg_size += bv->bv_len; - bvprv = bv; - continue; - } -new_segment: - if (BIOVEC_VIRT_MERGEABLE(bvprv, bv) && - !BIOVEC_VIRT_OVERSIZE(hw_seg_size + bv->bv_len)) { - hw_seg_size += bv->bv_len; - } else { -new_hw_segment: - if (hw_seg_size > bio->bi_hw_front_size) - bio->bi_hw_front_size = hw_seg_size; - hw_seg_size = BIOVEC_VIRT_START_SIZE(bv) + bv->bv_len; - nr_hw_segs++; - } - - nr_phys_segs++; - bvprv = bv; - seg_size = bv->bv_len; - highprv = high; - } - if (hw_seg_size > bio->bi_hw_back_size) - bio->bi_hw_back_size = hw_seg_size; - if (nr_hw_segs == 1 && hw_seg_size > bio->bi_hw_front_size) - bio->bi_hw_front_size = hw_seg_size; - bio->bi_phys_segments = nr_phys_segs; - bio->bi_hw_segments = nr_hw_segs; - bio->bi_flags |= (1 << BIO_SEG_VALID); -} - - -static int blk_phys_contig_segment(request_queue_t *q, struct bio *bio, - struct bio *nxt) -{ - if (!(q->queue_flags & (1 << QUEUE_FLAG_CLUSTER))) - return 0; - - if (!BIOVEC_PHYS_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt))) - return 0; - if (bio->bi_size + nxt->bi_size > q->max_segment_size) - return 0; - - /* - * bio and nxt are contigous in memory, check if the queue allows - * these two to be merged into one - */ - if (BIO_SEG_BOUNDARY(q, bio, nxt)) - return 1; - - return 0; -} - -static int blk_hw_contig_segment(request_queue_t *q, struct bio *bio, - struct bio *nxt) -{ - if (unlikely(!bio_flagged(bio, BIO_SEG_VALID))) - blk_recount_segments(q, bio); - if (unlikely(!bio_flagged(nxt, BIO_SEG_VALID))) - blk_recount_segments(q, nxt); - if (!BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt)) || - BIOVEC_VIRT_OVERSIZE(bio->bi_hw_front_size + bio->bi_hw_back_size)) - return 0; - if (bio->bi_size + nxt->bi_size > q->max_segment_size) - return 0; - - return 1; -} - -/* - * map a request to scatterlist, return number of sg entries setup. Caller - * must make sure sg can hold rq->nr_phys_segments entries - */ -int blk_rq_map_sg(request_queue_t *q, struct request *rq, struct scatterlist *sg) -{ - struct bio_vec *bvec, *bvprv; - struct bio *bio; - int nsegs, i, cluster; - - nsegs = 0; - cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER); - - /* - * for each bio in rq - */ - bvprv = NULL; - rq_for_each_bio(bio, rq) { - /* - * for each segment in bio - */ - bio_for_each_segment(bvec, bio, i) { - int nbytes = bvec->bv_len; - - if (bvprv && cluster) { - if (sg[nsegs - 1].length + nbytes > q->max_segment_size) - goto new_segment; - - if (!BIOVEC_PHYS_MERGEABLE(bvprv, bvec)) - goto new_segment; - if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bvec)) - goto new_segment; - - sg[nsegs - 1].length += nbytes; - } else { -new_segment: - memset(&sg[nsegs],0,sizeof(struct scatterlist)); - sg[nsegs].page = bvec->bv_page; - sg[nsegs].length = nbytes; - sg[nsegs].offset = bvec->bv_offset; - - nsegs++; - } - bvprv = bvec; - } /* segments in bio */ - } /* bios in rq */ - - return nsegs; -} - -EXPORT_SYMBOL(blk_rq_map_sg); - -/* - * the standard queue merge functions, can be overridden with device - * specific ones if so desired - */ - -static inline int ll_new_mergeable(request_queue_t *q, - struct request *req, - struct bio *bio) -{ - int nr_phys_segs = bio_phys_segments(q, bio); - - if (req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) { - req->flags |= REQ_NOMERGE; - if (req == q->last_merge) - q->last_merge = NULL; - return 0; - } - - /* - * A hw segment is just getting larger, bump just the phys - * counter. - */ - req->nr_phys_segments += nr_phys_segs; - return 1; -} - -static inline int ll_new_hw_segment(request_queue_t *q, - struct request *req, - struct bio *bio) -{ - int nr_hw_segs = bio_hw_segments(q, bio); - int nr_phys_segs = bio_phys_segments(q, bio); - - if (req->nr_hw_segments + nr_hw_segs > q->max_hw_segments - || req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) { - req->flags |= REQ_NOMERGE; - if (req == q->last_merge) - q->last_merge = NULL; - return 0; - } - - /* - * This will form the start of a new hw segment. Bump both - * counters. - */ - req->nr_hw_segments += nr_hw_segs; - req->nr_phys_segments += nr_phys_segs; - return 1; -} - -static int ll_back_merge_fn(request_queue_t *q, struct request *req, - struct bio *bio) -{ - int len; - - if (req->nr_sectors + bio_sectors(bio) > q->max_sectors) { - req->flags |= REQ_NOMERGE; - if (req == q->last_merge) - q->last_merge = NULL; - return 0; - } - if (unlikely(!bio_flagged(req->biotail, BIO_SEG_VALID))) - blk_recount_segments(q, req->biotail); - if (unlikely(!bio_flagged(bio, BIO_SEG_VALID))) - blk_recount_segments(q, bio); - len = req->biotail->bi_hw_back_size + bio->bi_hw_front_size; - if (BIOVEC_VIRT_MERGEABLE(__BVEC_END(req->biotail), __BVEC_START(bio)) && - !BIOVEC_VIRT_OVERSIZE(len)) { - int mergeable = ll_new_mergeable(q, req, bio); - - if (mergeable) { - if (req->nr_hw_segments == 1) - req->bio->bi_hw_front_size = len; - if (bio->bi_hw_segments == 1) - bio->bi_hw_back_size = len; - } - return mergeable; - } - - return ll_new_hw_segment(q, req, bio); -} - -static int ll_front_merge_fn(request_queue_t *q, struct request *req, - struct bio *bio) -{ - int len; - - if (req->nr_sectors + bio_sectors(bio) > q->max_sectors) { - req->flags |= REQ_NOMERGE; - if (req == q->last_merge) - q->last_merge = NULL; - return 0; - } - len = bio->bi_hw_back_size + req->bio->bi_hw_front_size; - if (unlikely(!bio_flagged(bio, BIO_SEG_VALID))) - blk_recount_segments(q, bio); - if (unlikely(!bio_flagged(req->bio, BIO_SEG_VALID))) - blk_recount_segments(q, req->bio); - if (BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(req->bio)) && - !BIOVEC_VIRT_OVERSIZE(len)) { - int mergeable = ll_new_mergeable(q, req, bio); - - if (mergeable) { - if (bio->bi_hw_segments == 1) - bio->bi_hw_front_size = len; - if (req->nr_hw_segments == 1) - req->biotail->bi_hw_back_size = len; - } - return mergeable; - } - - return ll_new_hw_segment(q, req, bio); -} - -static int ll_merge_requests_fn(request_queue_t *q, struct request *req, - struct request *next) -{ - int total_phys_segments; - int total_hw_segments; - - /* - * First check if the either of the requests are re-queued - * requests. Can't merge them if they are. - */ - if (req->special || next->special) - return 0; - - /* - * Will it become too large? - */ - if ((req->nr_sectors + next->nr_sectors) > q->max_sectors) - return 0; - - total_phys_segments = req->nr_phys_segments + next->nr_phys_segments; - if (blk_phys_contig_segment(q, req->biotail, next->bio)) - total_phys_segments--; - - if (total_phys_segments > q->max_phys_segments) - return 0; - - total_hw_segments = req->nr_hw_segments + next->nr_hw_segments; - if (blk_hw_contig_segment(q, req->biotail, next->bio)) { - int len = req->biotail->bi_hw_back_size + next->bio->bi_hw_front_size; - /* - * propagate the combined length to the end of the requests - */ - if (req->nr_hw_segments == 1) - req->bio->bi_hw_front_size = len; - if (next->nr_hw_segments == 1) - next->biotail->bi_hw_back_size = len; - total_hw_segments--; - } - - if (total_hw_segments > q->max_hw_segments) - return 0; - - /* Merge is OK... */ - req->nr_phys_segments = total_phys_segments; - req->nr_hw_segments = total_hw_segments; - return 1; -} - -/* - * "plug" the device if there are no outstanding requests: this will - * force the transfer to start only after we have put all the requests - * on the list. - * - * This is called with interrupts off and no requests on the queue and - * with the queue lock held. - */ -void blk_plug_device(request_queue_t *q) -{ - WARN_ON(!irqs_disabled()); - - /* - * don't plug a stopped queue, it must be paired with blk_start_queue() - * which will restart the queueing - */ - if (test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags)) - return; - - if (!test_and_set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) - mod_timer(&q->unplug_timer, jiffies + q->unplug_delay); -} - -EXPORT_SYMBOL(blk_plug_device); - -/* - * remove the queue from the plugged list, if present. called with - * queue lock held and interrupts disabled. - */ -int blk_remove_plug(request_queue_t *q) -{ - WARN_ON(!irqs_disabled()); - - if (!test_and_clear_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) - return 0; - - del_timer(&q->unplug_timer); - return 1; -} - -EXPORT_SYMBOL(blk_remove_plug); - -/* - * remove the plug and let it rip.. - */ -void __generic_unplug_device(request_queue_t *q) -{ - if (unlikely(test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags))) - return; - - if (!blk_remove_plug(q)) - return; - - q->request_fn(q); -} -EXPORT_SYMBOL(__generic_unplug_device); - -/** - * generic_unplug_device - fire a request queue - * @q: The &request_queue_t in question - * - * Description: - * Linux uses plugging to build bigger requests queues before letting - * the device have at them. If a queue is plugged, the I/O scheduler - * is still adding and merging requests on the queue. Once the queue - * gets unplugged, the request_fn defined for the queue is invoked and - * transfers started. - **/ -void generic_unplug_device(request_queue_t *q) -{ - spin_lock_irq(q->queue_lock); - __generic_unplug_device(q); - spin_unlock_irq(q->queue_lock); -} -EXPORT_SYMBOL(generic_unplug_device); - -static void blk_backing_dev_unplug(struct backing_dev_info *bdi, - struct page *page) -{ - request_queue_t *q = bdi->unplug_io_data; - - /* - * devices don't necessarily have an ->unplug_fn defined - */ - if (q->unplug_fn) - q->unplug_fn(q); -} - -static void blk_unplug_work(void *data) -{ - request_queue_t *q = data; - - q->unplug_fn(q); -} - -static void blk_unplug_timeout(unsigned long data) -{ - request_queue_t *q = (request_queue_t *)data; - - kblockd_schedule_work(&q->unplug_work); -} - -/** - * blk_start_queue - restart a previously stopped queue - * @q: The &request_queue_t in question - * - * Description: - * blk_start_queue() will clear the stop flag on the queue, and call - * the request_fn for the queue if it was in a stopped state when - * entered. Also see blk_stop_queue(). Queue lock must be held. - **/ -void blk_start_queue(request_queue_t *q) -{ - clear_bit(QUEUE_FLAG_STOPPED, &q->queue_flags); - - /* - * one level of recursion is ok and is much faster than kicking - * the unplug handling - */ - if (!test_and_set_bit(QUEUE_FLAG_REENTER, &q->queue_flags)) { - q->request_fn(q); - clear_bit(QUEUE_FLAG_REENTER, &q->queue_flags); - } else { - blk_plug_device(q); - kblockd_schedule_work(&q->unplug_work); - } -} - -EXPORT_SYMBOL(blk_start_queue); - -/** - * blk_stop_queue - stop a queue - * @q: The &request_queue_t in question - * - * Description: - * The Linux block layer assumes that a block driver will consume all - * entries on the request queue when the request_fn strategy is called. - * Often this will not happen, because of hardware limitations (queue - * depth settings). If a device driver gets a 'queue full' response, - * or if it simply chooses not to queue more I/O at one point, it can - * call this function to prevent the request_fn from being called until - * the driver has signalled it's ready to go again. This happens by calling - * blk_start_queue() to restart queue operations. Queue lock must be held. - **/ -void blk_stop_queue(request_queue_t *q) -{ - blk_remove_plug(q); - set_bit(QUEUE_FLAG_STOPPED, &q->queue_flags); -} -EXPORT_SYMBOL(blk_stop_queue); - -/** - * blk_sync_queue - cancel any pending callbacks on a queue - * @q: the queue - * - * Description: - * The block layer may perform asynchronous callback activity - * on a queue, such as calling the unplug function after a timeout. - * A block device may call blk_sync_queue to ensure that any - * such activity is cancelled, thus allowing it to release resources - * the the callbacks might use. The caller must already have made sure - * that its ->make_request_fn will not re-add plugging prior to calling - * this function. - * - */ -void blk_sync_queue(struct request_queue *q) -{ - del_timer_sync(&q->unplug_timer); - kblockd_flush(); -} -EXPORT_SYMBOL(blk_sync_queue); - -/** - * blk_run_queue - run a single device queue - * @q: The queue to run - */ -void blk_run_queue(struct request_queue *q) -{ - unsigned long flags; - - spin_lock_irqsave(q->queue_lock, flags); - blk_remove_plug(q); - if (!elv_queue_empty(q)) - q->request_fn(q); - spin_unlock_irqrestore(q->queue_lock, flags); -} -EXPORT_SYMBOL(blk_run_queue); - -/** - * blk_cleanup_queue: - release a &request_queue_t when it is no longer needed - * @q: the request queue to be released - * - * Description: - * blk_cleanup_queue is the pair to blk_init_queue() or - * blk_queue_make_request(). It should be called when a request queue is - * being released; typically when a block device is being de-registered. - * Currently, its primary task it to free all the &struct request - * structures that were allocated to the queue and the queue itself. - * - * Caveat: - * Hopefully the low level driver will have finished any - * outstanding requests first... - **/ -void blk_cleanup_queue(request_queue_t * q) -{ - struct request_list *rl = &q->rq; - - if (!atomic_dec_and_test(&q->refcnt)) - return; - - if (q->elevator) - elevator_exit(q->elevator); - - blk_sync_queue(q); - - if (rl->rq_pool) - mempool_destroy(rl->rq_pool); - - if (q->queue_tags) - __blk_queue_free_tags(q); - - blk_queue_ordered(q, QUEUE_ORDERED_NONE); - - kmem_cache_free(requestq_cachep, q); -} - -EXPORT_SYMBOL(blk_cleanup_queue); - -static int blk_init_free_list(request_queue_t *q) -{ - struct request_list *rl = &q->rq; - - rl->count[READ] = rl->count[WRITE] = 0; - rl->starved[READ] = rl->starved[WRITE] = 0; - rl->elvpriv = 0; - init_waitqueue_head(&rl->wait[READ]); - init_waitqueue_head(&rl->wait[WRITE]); - - rl->rq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab, - mempool_free_slab, request_cachep, q->node); - - if (!rl->rq_pool) - return -ENOMEM; - - return 0; -} - -static int __make_request(request_queue_t *, struct bio *); - -request_queue_t *blk_alloc_queue(gfp_t gfp_mask) -{ - return blk_alloc_queue_node(gfp_mask, -1); -} -EXPORT_SYMBOL(blk_alloc_queue); - -request_queue_t *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) -{ - request_queue_t *q; - - q = kmem_cache_alloc_node(requestq_cachep, gfp_mask, node_id); - if (!q) - return NULL; - - memset(q, 0, sizeof(*q)); - init_timer(&q->unplug_timer); - atomic_set(&q->refcnt, 1); - - q->backing_dev_info.unplug_io_fn = blk_backing_dev_unplug; - q->backing_dev_info.unplug_io_data = q; - - return q; -} -EXPORT_SYMBOL(blk_alloc_queue_node); - -/** - * blk_init_queue - prepare a request queue for use with a block device - * @rfn: The function to be called to process requests that have been - * placed on the queue. - * @lock: Request queue spin lock - * - * Description: - * If a block device wishes to use the standard request handling procedures, - * which sorts requests and coalesces adjacent requests, then it must - * call blk_init_queue(). The function @rfn will be called when there - * are requests on the queue that need to be processed. If the device - * supports plugging, then @rfn may not be called immediately when requests - * are available on the queue, but may be called at some time later instead. - * Plugged queues are generally unplugged when a buffer belonging to one - * of the requests on the queue is needed, or due to memory pressure. - * - * @rfn is not required, or even expected, to remove all requests off the - * queue, but only as many as it can handle at a time. If it does leave - * requests on the queue, it is responsible for arranging that the requests - * get dealt with eventually. - * - * The queue spin lock must be held while manipulating the requests on the - * request queue. - * - * Function returns a pointer to the initialized request queue, or NULL if - * it didn't succeed. - * - * Note: - * blk_init_queue() must be paired with a blk_cleanup_queue() call - * when the block device is deactivated (such as at module unload). - **/ - -request_queue_t *blk_init_queue(request_fn_proc *rfn, spinlock_t *lock) -{ - return blk_init_queue_node(rfn, lock, -1); -} -EXPORT_SYMBOL(blk_init_queue); - -request_queue_t * -blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id) -{ - request_queue_t *q = blk_alloc_queue_node(GFP_KERNEL, node_id); - - if (!q) - return NULL; - - q->node = node_id; - if (blk_init_free_list(q)) - goto out_init; - - /* - * if caller didn't supply a lock, they get per-queue locking with - * our embedded lock - */ - if (!lock) { - spin_lock_init(&q->__queue_lock); - lock = &q->__queue_lock; - } - - q->request_fn = rfn; - q->back_merge_fn = ll_back_merge_fn; - q->front_merge_fn = ll_front_merge_fn; - q->merge_requests_fn = ll_merge_requests_fn; - q->prep_rq_fn = NULL; - q->unplug_fn = generic_unplug_device; - q->queue_flags = (1 << QUEUE_FLAG_CLUSTER); - q->queue_lock = lock; - - blk_queue_segment_boundary(q, 0xffffffff); - - blk_queue_make_request(q, __make_request); - blk_queue_max_segment_size(q, MAX_SEGMENT_SIZE); - - blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS); - blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS); - - /* - * all done - */ - if (!elevator_init(q, NULL)) { - blk_queue_congestion_threshold(q); - return q; - } - - blk_cleanup_queue(q); -out_init: - kmem_cache_free(requestq_cachep, q); - return NULL; -} -EXPORT_SYMBOL(blk_init_queue_node); - -int blk_get_queue(request_queue_t *q) -{ - if (likely(!test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) { - atomic_inc(&q->refcnt); - return 0; - } - - return 1; -} - -EXPORT_SYMBOL(blk_get_queue); - -static inline void blk_free_request(request_queue_t *q, struct request *rq) -{ - if (rq->flags & REQ_ELVPRIV) - elv_put_request(q, rq); - mempool_free(rq, q->rq.rq_pool); -} - -static inline struct request * -blk_alloc_request(request_queue_t *q, int rw, struct bio *bio, - int priv, gfp_t gfp_mask) -{ - struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask); - - if (!rq) - return NULL; - - /* - * first three bits are identical in rq->flags and bio->bi_rw, - * see bio.h and blkdev.h - */ - rq->flags = rw; - - if (priv) { - if (unlikely(elv_set_request(q, rq, bio, gfp_mask))) { - mempool_free(rq, q->rq.rq_pool); - return NULL; - } - rq->flags |= REQ_ELVPRIV; - } - - return rq; -} - -/* - * ioc_batching returns true if the ioc is a valid batching request and - * should be given priority access to a request. - */ -static inline int ioc_batching(request_queue_t *q, struct io_context *ioc) -{ - if (!ioc) - return 0; - - /* - * Make sure the process is able to allocate at least 1 request - * even if the batch times out, otherwise we could theoretically - * lose wakeups. - */ - return ioc->nr_batch_requests == q->nr_batching || - (ioc->nr_batch_requests > 0 - && time_before(jiffies, ioc->last_waited + BLK_BATCH_TIME)); -} - -/* - * ioc_set_batching sets ioc to be a new "batcher" if it is not one. This - * will cause the process to be a "batcher" on all queues in the system. This - * is the behaviour we want though - once it gets a wakeup it should be given - * a nice run. - */ -static void ioc_set_batching(request_queue_t *q, struct io_context *ioc) -{ - if (!ioc || ioc_batching(q, ioc)) - return; - - ioc->nr_batch_requests = q->nr_batching; - ioc->last_waited = jiffies; -} - -static void __freed_request(request_queue_t *q, int rw) -{ - struct request_list *rl = &q->rq; - - if (rl->count[rw] < queue_congestion_off_threshold(q)) - clear_queue_congested(q, rw); - - if (rl->count[rw] + 1 <= q->nr_requests) { - if (waitqueue_active(&rl->wait[rw])) - wake_up(&rl->wait[rw]); - - blk_clear_queue_full(q, rw); - } -} - -/* - * A request has just been released. Account for it, update the full and - * congestion status, wake up any waiters. Called under q->queue_lock. - */ -static void freed_request(request_queue_t *q, int rw, int priv) -{ - struct request_list *rl = &q->rq; - - rl->count[rw]--; - if (priv) - rl->elvpriv--; - - __freed_request(q, rw); - - if (unlikely(rl->starved[rw ^ 1])) - __freed_request(q, rw ^ 1); -} - -#define blkdev_free_rq(list) list_entry((list)->next, struct request, queuelist) -/* - * Get a free request, queue_lock must be held. - * Returns NULL on failure, with queue_lock held. - * Returns !NULL on success, with queue_lock *not held*. - */ -static struct request *get_request(request_queue_t *q, int rw, struct bio *bio, - gfp_t gfp_mask) -{ - struct request *rq = NULL; - struct request_list *rl = &q->rq; - struct io_context *ioc = current_io_context(GFP_ATOMIC); - int priv; - - if (rl->count[rw]+1 >= q->nr_requests) { - /* - * The queue will fill after this allocation, so set it as - * full, and mark this process as "batching". This process - * will be allowed to complete a batch of requests, others - * will be blocked. - */ - if (!blk_queue_full(q, rw)) { - ioc_set_batching(q, ioc); - blk_set_queue_full(q, rw); - } - } - - switch (elv_may_queue(q, rw, bio)) { - case ELV_MQUEUE_NO: - goto rq_starved; - case ELV_MQUEUE_MAY: - break; - case ELV_MQUEUE_MUST: - goto get_rq; - } - - if (blk_queue_full(q, rw) && !ioc_batching(q, ioc)) { - /* - * The queue is full and the allocating process is not a - * "batcher", and not exempted by the IO scheduler - */ - goto out; - } - -get_rq: - /* - * Only allow batching queuers to allocate up to 50% over the defined - * limit of requests, otherwise we could have thousands of requests - * allocated with any setting of ->nr_requests - */ - if (rl->count[rw] >= (3 * q->nr_requests / 2)) - goto out; - - rl->count[rw]++; - rl->starved[rw] = 0; - if (rl->count[rw] >= queue_congestion_on_threshold(q)) - set_queue_congested(q, rw); - - priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); - if (priv) - rl->elvpriv++; - - spin_unlock_irq(q->queue_lock); - - rq = blk_alloc_request(q, rw, bio, priv, gfp_mask); - if (!rq) { - /* - * Allocation failed presumably due to memory. Undo anything - * we might have messed up. - * - * Allocating task should really be put onto the front of the - * wait queue, but this is pretty rare. - */ - spin_lock_irq(q->queue_lock); - freed_request(q, rw, priv); - - /* - * in the very unlikely event that allocation failed and no - * requests for this direction was pending, mark us starved - * so that freeing of a request in the other direction will - * notice us. another possible fix would be to split the - * rq mempool into READ and WRITE - */ -rq_starved: - if (unlikely(rl->count[rw] == 0)) - rl->starved[rw] = 1; - - goto out; - } - - if (ioc_batching(q, ioc)) - ioc->nr_batch_requests--; - - rq_init(q, rq); - rq->rl = rl; -out: - return rq; -} - -/* - * No available requests for this queue, unplug the device and wait for some - * requests to become available. - * - * Called with q->queue_lock held, and returns with it unlocked. - */ -static struct request *get_request_wait(request_queue_t *q, int rw, - struct bio *bio) -{ - struct request *rq; - - rq = get_request(q, rw, bio, GFP_NOIO); - while (!rq) { - DEFINE_WAIT(wait); - struct request_list *rl = &q->rq; - - prepare_to_wait_exclusive(&rl->wait[rw], &wait, - TASK_UNINTERRUPTIBLE); - - rq = get_request(q, rw, bio, GFP_NOIO); - - if (!rq) { - struct io_context *ioc; - - __generic_unplug_device(q); - spin_unlock_irq(q->queue_lock); - io_schedule(); - - /* - * After sleeping, we become a "batching" process and - * will be able to allocate at least one request, and - * up to a big batch of them for a small period time. - * See ioc_batching, ioc_set_batching - */ - ioc = current_io_context(GFP_NOIO); - ioc_set_batching(q, ioc); - - spin_lock_irq(q->queue_lock); - } - finish_wait(&rl->wait[rw], &wait); - } - - return rq; -} - -struct request *blk_get_request(request_queue_t *q, int rw, gfp_t gfp_mask) -{ - struct request *rq; - - BUG_ON(rw != READ && rw != WRITE); - - spin_lock_irq(q->queue_lock); - if (gfp_mask & __GFP_WAIT) { - rq = get_request_wait(q, rw, NULL); - } else { - rq = get_request(q, rw, NULL, gfp_mask); - if (!rq) - spin_unlock_irq(q->queue_lock); - } - /* q->queue_lock is unlocked at this point */ - - return rq; -} -EXPORT_SYMBOL(blk_get_request); - -/** - * blk_requeue_request - put a request back on queue - * @q: request queue where request should be inserted - * @rq: request to be inserted - * - * Description: - * Drivers often keep queueing requests until the hardware cannot accept - * more, when that condition happens we need to put the request back - * on the queue. Must be called with queue lock held. - */ -void blk_requeue_request(request_queue_t *q, struct request *rq) -{ - if (blk_rq_tagged(rq)) - blk_queue_end_tag(q, rq); - - elv_requeue_request(q, rq); -} - -EXPORT_SYMBOL(blk_requeue_request); - -/** - * blk_insert_request - insert a special request in to a request queue - * @q: request queue where request should be inserted - * @rq: request to be inserted - * @at_head: insert request at head or tail of queue - * @data: private data - * - * Description: - * Many block devices need to execute commands asynchronously, so they don't - * block the whole kernel from preemption during request execution. This is - * accomplished normally by inserting aritficial requests tagged as - * REQ_SPECIAL in to the corresponding request queue, and letting them be - * scheduled for actual execution by the request queue. - * - * We have the option of inserting the head or the tail of the queue. - * Typically we use the tail for new ioctls and so forth. We use the head - * of the queue for things like a QUEUE_FULL message from a device, or a - * host that is unable to accept a particular command. - */ -void blk_insert_request(request_queue_t *q, struct request *rq, - int at_head, void *data) -{ - int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK; - unsigned long flags; - - /* - * tell I/O scheduler that this isn't a regular read/write (ie it - * must not attempt merges on this) and that it acts as a soft - * barrier - */ - rq->flags |= REQ_SPECIAL | REQ_SOFTBARRIER; - - rq->special = data; - - spin_lock_irqsave(q->queue_lock, flags); - - /* - * If command is tagged, release the tag - */ - if (blk_rq_tagged(rq)) - blk_queue_end_tag(q, rq); - - drive_stat_acct(rq, rq->nr_sectors, 1); - __elv_add_request(q, rq, where, 0); - - if (blk_queue_plugged(q)) - __generic_unplug_device(q); - else - q->request_fn(q); - spin_unlock_irqrestore(q->queue_lock, flags); -} - -EXPORT_SYMBOL(blk_insert_request); - -/** - * blk_rq_map_user - map user data to a request, for REQ_BLOCK_PC usage - * @q: request queue where request should be inserted - * @rq: request structure to fill - * @ubuf: the user buffer - * @len: length of user data - * - * Description: - * Data will be mapped directly for zero copy io, if possible. Otherwise - * a kernel bounce buffer is used. - * - * A matching blk_rq_unmap_user() must be issued at the end of io, while - * still in process context. - * - * Note: The mapped bio may need to be bounced through blk_queue_bounce() - * before being submitted to the device, as pages mapped may be out of - * reach. It's the callers responsibility to make sure this happens. The - * original bio must be passed back in to blk_rq_unmap_user() for proper - * unmapping. - */ -int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf, - unsigned int len) -{ - unsigned long uaddr; - struct bio *bio; - int reading; - - if (len > (q->max_sectors << 9)) - return -EINVAL; - if (!len || !ubuf) - return -EINVAL; - - reading = rq_data_dir(rq) == READ; - - /* - * if alignment requirement is satisfied, map in user pages for - * direct dma. else, set up kernel bounce buffers - */ - uaddr = (unsigned long) ubuf; - if (!(uaddr & queue_dma_alignment(q)) && !(len & queue_dma_alignment(q))) - bio = bio_map_user(q, NULL, uaddr, len, reading); - else - bio = bio_copy_user(q, uaddr, len, reading); - - if (!IS_ERR(bio)) { - rq->bio = rq->biotail = bio; - blk_rq_bio_prep(q, rq, bio); - - rq->buffer = rq->data = NULL; - rq->data_len = len; - return 0; - } - - /* - * bio is the err-ptr - */ - return PTR_ERR(bio); -} - -EXPORT_SYMBOL(blk_rq_map_user); - -/** - * blk_rq_map_user_iov - map user data to a request, for REQ_BLOCK_PC usage - * @q: request queue where request should be inserted - * @rq: request to map data to - * @iov: pointer to the iovec - * @iov_count: number of elements in the iovec - * - * Description: - * Data will be mapped directly for zero copy io, if possible. Otherwise - * a kernel bounce buffer is used. - * - * A matching blk_rq_unmap_user() must be issued at the end of io, while - * still in process context. - * - * Note: The mapped bio may need to be bounced through blk_queue_bounce() - * before being submitted to the device, as pages mapped may be out of - * reach. It's the callers responsibility to make sure this happens. The - * original bio must be passed back in to blk_rq_unmap_user() for proper - * unmapping. - */ -int blk_rq_map_user_iov(request_queue_t *q, struct request *rq, - struct sg_iovec *iov, int iov_count) -{ - struct bio *bio; - - if (!iov || iov_count <= 0) - return -EINVAL; - - /* we don't allow misaligned data like bio_map_user() does. If the - * user is using sg, they're expected to know the alignment constraints - * and respect them accordingly */ - bio = bio_map_user_iov(q, NULL, iov, iov_count, rq_data_dir(rq)== READ); - if (IS_ERR(bio)) - return PTR_ERR(bio); - - rq->bio = rq->biotail = bio; - blk_rq_bio_prep(q, rq, bio); - rq->buffer = rq->data = NULL; - rq->data_len = bio->bi_size; - return 0; -} - -EXPORT_SYMBOL(blk_rq_map_user_iov); - -/** - * blk_rq_unmap_user - unmap a request with user data - * @bio: bio to be unmapped - * @ulen: length of user buffer - * - * Description: - * Unmap a bio previously mapped by blk_rq_map_user(). - */ -int blk_rq_unmap_user(struct bio *bio, unsigned int ulen) -{ - int ret = 0; - - if (bio) { - if (bio_flagged(bio, BIO_USER_MAPPED)) - bio_unmap_user(bio); - else - ret = bio_uncopy_user(bio); - } - - return 0; -} - -EXPORT_SYMBOL(blk_rq_unmap_user); - -/** - * blk_rq_map_kern - map kernel data to a request, for REQ_BLOCK_PC usage - * @q: request queue where request should be inserted - * @rq: request to fill - * @kbuf: the kernel buffer - * @len: length of user data - * @gfp_mask: memory allocation flags - */ -int blk_rq_map_kern(request_queue_t *q, struct request *rq, void *kbuf, - unsigned int len, gfp_t gfp_mask) -{ - struct bio *bio; - - if (len > (q->max_sectors << 9)) - return -EINVAL; - if (!len || !kbuf) - return -EINVAL; - - bio = bio_map_kern(q, kbuf, len, gfp_mask); - if (IS_ERR(bio)) - return PTR_ERR(bio); - - if (rq_data_dir(rq) == WRITE) - bio->bi_rw |= (1 << BIO_RW); - - rq->bio = rq->biotail = bio; - blk_rq_bio_prep(q, rq, bio); - - rq->buffer = rq->data = NULL; - rq->data_len = len; - return 0; -} - -EXPORT_SYMBOL(blk_rq_map_kern); - -/** - * blk_execute_rq_nowait - insert a request into queue for execution - * @q: queue to insert the request in - * @bd_disk: matching gendisk - * @rq: request to insert - * @at_head: insert request at head or tail of queue - * @done: I/O completion handler - * - * Description: - * Insert a fully prepared request at the back of the io scheduler queue - * for execution. Don't wait for completion. - */ -void blk_execute_rq_nowait(request_queue_t *q, struct gendisk *bd_disk, - struct request *rq, int at_head, - void (*done)(struct request *)) -{ - int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK; - - rq->rq_disk = bd_disk; - rq->flags |= REQ_NOMERGE; - rq->end_io = done; - elv_add_request(q, rq, where, 1); - generic_unplug_device(q); -} - -/** - * blk_execute_rq - insert a request into queue for execution - * @q: queue to insert the request in - * @bd_disk: matching gendisk - * @rq: request to insert - * @at_head: insert request at head or tail of queue - * - * Description: - * Insert a fully prepared request at the back of the io scheduler queue - * for execution and wait for completion. - */ -int blk_execute_rq(request_queue_t *q, struct gendisk *bd_disk, - struct request *rq, int at_head) -{ - DECLARE_COMPLETION(wait); - char sense[SCSI_SENSE_BUFFERSIZE]; - int err = 0; - - /* - * we need an extra reference to the request, so we can look at - * it after io completion - */ - rq->ref_count++; - - if (!rq->sense) { - memset(sense, 0, sizeof(sense)); - rq->sense = sense; - rq->sense_len = 0; - } - - rq->waiting = &wait; - blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq); - wait_for_completion(&wait); - rq->waiting = NULL; - - if (rq->errors) - err = -EIO; - - return err; -} - -EXPORT_SYMBOL(blk_execute_rq); - -/** - * blkdev_issue_flush - queue a flush - * @bdev: blockdev to issue flush for - * @error_sector: error sector - * - * Description: - * Issue a flush for the block device in question. Caller can supply - * room for storing the error offset in case of a flush error, if they - * wish to. Caller must run wait_for_completion() on its own. - */ -int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector) -{ - request_queue_t *q; - - if (bdev->bd_disk == NULL) - return -ENXIO; - - q = bdev_get_queue(bdev); - if (!q) - return -ENXIO; - if (!q->issue_flush_fn) - return -EOPNOTSUPP; - - return q->issue_flush_fn(q, bdev->bd_disk, error_sector); -} - -EXPORT_SYMBOL(blkdev_issue_flush); - -static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io) -{ - int rw = rq_data_dir(rq); - - if (!blk_fs_request(rq) || !rq->rq_disk) - return; - - if (!new_io) { - __disk_stat_inc(rq->rq_disk, merges[rw]); - } else { - disk_round_stats(rq->rq_disk); - rq->rq_disk->in_flight++; - } -} - -/* - * add-request adds a request to the linked list. - * queue lock is held and interrupts disabled, as we muck with the - * request queue list. - */ -static inline void add_request(request_queue_t * q, struct request * req) -{ - drive_stat_acct(req, req->nr_sectors, 1); - - if (q->activity_fn) - q->activity_fn(q->activity_data, rq_data_dir(req)); - - /* - * elevator indicated where it wants this request to be - * inserted at elevator_merge time - */ - __elv_add_request(q, req, ELEVATOR_INSERT_SORT, 0); -} - -/* - * disk_round_stats() - Round off the performance stats on a struct - * disk_stats. - * - * The average IO queue length and utilisation statistics are maintained - * by observing the current state of the queue length and the amount of - * time it has been in this state for. - * - * Normally, that accounting is done on IO completion, but that can result - * in more than a second's worth of IO being accounted for within any one - * second, leading to >100% utilisation. To deal with that, we call this - * function to do a round-off before returning the results when reading - * /proc/diskstats. This accounts immediately for all queue usage up to - * the current jiffies and restarts the counters again. - */ -void disk_round_stats(struct gendisk *disk) -{ - unsigned long now = jiffies; - - if (now == disk->stamp) - return; - - if (disk->in_flight) { - __disk_stat_add(disk, time_in_queue, - disk->in_flight * (now - disk->stamp)); - __disk_stat_add(disk, io_ticks, (now - disk->stamp)); - } - disk->stamp = now; -} - -/* - * queue lock must be held - */ -static void __blk_put_request(request_queue_t *q, struct request *req) -{ - struct request_list *rl = req->rl; - - if (unlikely(!q)) - return; - if (unlikely(--req->ref_count)) - return; - - elv_completed_request(q, req); - - req->rq_status = RQ_INACTIVE; - req->rl = NULL; - - /* - * Request may not have originated from ll_rw_blk. if not, - * it didn't come out of our reserved rq pools - */ - if (rl) { - int rw = rq_data_dir(req); - int priv = req->flags & REQ_ELVPRIV; - - BUG_ON(!list_empty(&req->queuelist)); - - blk_free_request(q, req); - freed_request(q, rw, priv); - } -} - -void blk_put_request(struct request *req) -{ - unsigned long flags; - request_queue_t *q = req->q; - - /* - * Gee, IDE calls in w/ NULL q. Fix IDE and remove the - * following if (q) test. - */ - if (q) { - spin_lock_irqsave(q->queue_lock, flags); - __blk_put_request(q, req); - spin_unlock_irqrestore(q->queue_lock, flags); - } -} - -EXPORT_SYMBOL(blk_put_request); - -/** - * blk_end_sync_rq - executes a completion event on a request - * @rq: request to complete - */ -void blk_end_sync_rq(struct request *rq) -{ - struct completion *waiting = rq->waiting; - - rq->waiting = NULL; - __blk_put_request(rq->q, rq); - - /* - * complete last, if this is a stack request the process (and thus - * the rq pointer) could be invalid right after this complete() - */ - complete(waiting); -} -EXPORT_SYMBOL(blk_end_sync_rq); - -/** - * blk_congestion_wait - wait for a queue to become uncongested - * @rw: READ or WRITE - * @timeout: timeout in jiffies - * - * Waits for up to @timeout jiffies for a queue (any queue) to exit congestion. - * If no queues are congested then just wait for the next request to be - * returned. - */ -long blk_congestion_wait(int rw, long timeout) -{ - long ret; - DEFINE_WAIT(wait); - wait_queue_head_t *wqh = &congestion_wqh[rw]; - - prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE); - ret = io_schedule_timeout(timeout); - finish_wait(wqh, &wait); - return ret; -} - -EXPORT_SYMBOL(blk_congestion_wait); - -/* - * Has to be called with the request spinlock acquired - */ -static int attempt_merge(request_queue_t *q, struct request *req, - struct request *next) -{ - if (!rq_mergeable(req) || !rq_mergeable(next)) - return 0; - - /* - * not contigious - */ - if (req->sector + req->nr_sectors != next->sector) - return 0; - - if (rq_data_dir(req) != rq_data_dir(next) - || req->rq_disk != next->rq_disk - || next->waiting || next->special) - return 0; - - /* - * If we are allowed to merge, then append bio list - * from next to rq and release next. merge_requests_fn - * will have updated segment counts, update sector - * counts here. - */ - if (!q->merge_requests_fn(q, req, next)) - return 0; - - /* - * At this point we have either done a back merge - * or front merge. We need the smaller start_time of - * the merged requests to be the current request - * for accounting purposes. - */ - if (time_after(req->start_time, next->start_time)) - req->start_time = next->start_time; - - req->biotail->bi_next = next->bio; - req->biotail = next->biotail; - - req->nr_sectors = req->hard_nr_sectors += next->hard_nr_sectors; - - elv_merge_requests(q, req, next); - - if (req->rq_disk) { - disk_round_stats(req->rq_disk); - req->rq_disk->in_flight--; - } - - req->ioprio = ioprio_best(req->ioprio, next->ioprio); - - __blk_put_request(q, next); - return 1; -} - -static inline int attempt_back_merge(request_queue_t *q, struct request *rq) -{ - struct request *next = elv_latter_request(q, rq); - - if (next) - return attempt_merge(q, rq, next); - - return 0; -} - -static inline int attempt_front_merge(request_queue_t *q, struct request *rq) -{ - struct request *prev = elv_former_request(q, rq); - - if (prev) - return attempt_merge(q, prev, rq); - - return 0; -} - -/** - * blk_attempt_remerge - attempt to remerge active head with next request - * @q: The &request_queue_t belonging to the device - * @rq: The head request (usually) - * - * Description: - * For head-active devices, the queue can easily be unplugged so quickly - * that proper merging is not done on the front request. This may hurt - * performance greatly for some devices. The block layer cannot safely - * do merging on that first request for these queues, but the driver can - * call this function and make it happen any way. Only the driver knows - * when it is safe to do so. - **/ -void blk_attempt_remerge(request_queue_t *q, struct request *rq) -{ - unsigned long flags; - - spin_lock_irqsave(q->queue_lock, flags); - attempt_back_merge(q, rq); - spin_unlock_irqrestore(q->queue_lock, flags); -} - -EXPORT_SYMBOL(blk_attempt_remerge); - -static int __make_request(request_queue_t *q, struct bio *bio) -{ - struct request *req; - int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, err, sync; - unsigned short prio; - sector_t sector; - - sector = bio->bi_sector; - nr_sectors = bio_sectors(bio); - cur_nr_sectors = bio_cur_sectors(bio); - prio = bio_prio(bio); - - rw = bio_data_dir(bio); - sync = bio_sync(bio); - - /* - * low level driver can indicate that it wants pages above a - * certain limit bounced to low memory (ie for highmem, or even - * ISA dma in theory) - */ - blk_queue_bounce(q, &bio); - - spin_lock_prefetch(q->queue_lock); - - barrier = bio_barrier(bio); - if (unlikely(barrier) && (q->ordered == QUEUE_ORDERED_NONE)) { - err = -EOPNOTSUPP; - goto end_io; - } - - spin_lock_irq(q->queue_lock); - - if (unlikely(barrier) || elv_queue_empty(q)) - goto get_rq; - - el_ret = elv_merge(q, &req, bio); - switch (el_ret) { - case ELEVATOR_BACK_MERGE: - BUG_ON(!rq_mergeable(req)); - - if (!q->back_merge_fn(q, req, bio)) - break; - - req->biotail->bi_next = bio; - req->biotail = bio; - req->nr_sectors = req->hard_nr_sectors += nr_sectors; - req->ioprio = ioprio_best(req->ioprio, prio); - drive_stat_acct(req, nr_sectors, 0); - if (!attempt_back_merge(q, req)) - elv_merged_request(q, req); - goto out; - - case ELEVATOR_FRONT_MERGE: - BUG_ON(!rq_mergeable(req)); - - if (!q->front_merge_fn(q, req, bio)) - break; - - bio->bi_next = req->bio; - req->bio = bio; - - /* - * may not be valid. if the low level driver said - * it didn't need a bounce buffer then it better - * not touch req->buffer either... - */ - req->buffer = bio_data(bio); - req->current_nr_sectors = cur_nr_sectors; - req->hard_cur_sectors = cur_nr_sectors; - req->sector = req->hard_sector = sector; - req->nr_sectors = req->hard_nr_sectors += nr_sectors; - req->ioprio = ioprio_best(req->ioprio, prio); - drive_stat_acct(req, nr_sectors, 0); - if (!attempt_front_merge(q, req)) - elv_merged_request(q, req); - goto out; - - /* ELV_NO_MERGE: elevator says don't/can't merge. */ - default: - ; - } - -get_rq: - /* - * Grab a free request. This is might sleep but can not fail. - * Returns with the queue unlocked. - */ - req = get_request_wait(q, rw, bio); - - /* - * After dropping the lock and possibly sleeping here, our request - * may now be mergeable after it had proven unmergeable (above). - * We don't worry about that case for efficiency. It won't happen - * often, and the elevators are able to handle it. - */ - - req->flags |= REQ_CMD; - - /* - * inherit FAILFAST from bio (for read-ahead, and explicit FAILFAST) - */ - if (bio_rw_ahead(bio) || bio_failfast(bio)) - req->flags |= REQ_FAILFAST; - - /* - * REQ_BARRIER implies no merging, but lets make it explicit - */ - if (unlikely(barrier)) - req->flags |= (REQ_HARDBARRIER | REQ_NOMERGE); - - req->errors = 0; - req->hard_sector = req->sector = sector; - req->hard_nr_sectors = req->nr_sectors = nr_sectors; - req->current_nr_sectors = req->hard_cur_sectors = cur_nr_sectors; - req->nr_phys_segments = bio_phys_segments(q, bio); - req->nr_hw_segments = bio_hw_segments(q, bio); - req->buffer = bio_data(bio); /* see ->buffer comment above */ - req->waiting = NULL; - req->bio = req->biotail = bio; - req->ioprio = prio; - req->rq_disk = bio->bi_bdev->bd_disk; - req->start_time = jiffies; - - spin_lock_irq(q->queue_lock); - if (elv_queue_empty(q)) - blk_plug_device(q); - add_request(q, req); -out: - if (sync) - __generic_unplug_device(q); - - spin_unlock_irq(q->queue_lock); - return 0; - -end_io: - bio_endio(bio, nr_sectors << 9, err); - return 0; -} - -/* - * If bio->bi_dev is a partition, remap the location - */ -static inline void blk_partition_remap(struct bio *bio) -{ - struct block_device *bdev = bio->bi_bdev; - - if (bdev != bdev->bd_contains) { - struct hd_struct *p = bdev->bd_part; - const int rw = bio_data_dir(bio); - - p->sectors[rw] += bio_sectors(bio); - p->ios[rw]++; - - bio->bi_sector += p->start_sect; - bio->bi_bdev = bdev->bd_contains; - } -} - -static void handle_bad_sector(struct bio *bio) -{ - char b[BDEVNAME_SIZE]; - - printk(KERN_INFO "attempt to access beyond end of device\n"); - printk(KERN_INFO "%s: rw=%ld, want=%Lu, limit=%Lu\n", - bdevname(bio->bi_bdev, b), - bio->bi_rw, - (unsigned long long)bio->bi_sector + bio_sectors(bio), - (long long)(bio->bi_bdev->bd_inode->i_size >> 9)); - - set_bit(BIO_EOF, &bio->bi_flags); -} - -/** - * generic_make_request: hand a buffer to its device driver for I/O - * @bio: The bio describing the location in memory and on the device. - * - * generic_make_request() is used to make I/O requests of block - * devices. It is passed a &struct bio, which describes the I/O that needs - * to be done. - * - * generic_make_request() does not return any status. The - * success/failure status of the request, along with notification of - * completion, is delivered asynchronously through the bio->bi_end_io - * function described (one day) else where. - * - * The caller of generic_make_request must make sure that bi_io_vec - * are set to describe the memory buffer, and that bi_dev and bi_sector are - * set to describe the device address, and the - * bi_end_io and optionally bi_private are set to describe how - * completion notification should be signaled. - * - * generic_make_request and the drivers it calls may use bi_next if this - * bio happens to be merged with someone else, and may change bi_dev and - * bi_sector for remaps as it sees fit. So the values of these fields - * should NOT be depended on after the call to generic_make_request. - */ -void generic_make_request(struct bio *bio) -{ - request_queue_t *q; - sector_t maxsector; - int ret, nr_sectors = bio_sectors(bio); - - might_sleep(); - /* Test device or partition size, when known. */ - maxsector = bio->bi_bdev->bd_inode->i_size >> 9; - if (maxsector) { - sector_t sector = bio->bi_sector; - - if (maxsector < nr_sectors || maxsector - nr_sectors < sector) { - /* - * This may well happen - the kernel calls bread() - * without checking the size of the device, e.g., when - * mounting a device. - */ - handle_bad_sector(bio); - goto end_io; - } - } - - /* - * Resolve the mapping until finished. (drivers are - * still free to implement/resolve their own stacking - * by explicitly returning 0) - * - * NOTE: we don't repeat the blk_size check for each new device. - * Stacking drivers are expected to know what they are doing. - */ - do { - char b[BDEVNAME_SIZE]; - - q = bdev_get_queue(bio->bi_bdev); - if (!q) { - printk(KERN_ERR - "generic_make_request: Trying to access " - "nonexistent block-device %s (%Lu)\n", - bdevname(bio->bi_bdev, b), - (long long) bio->bi_sector); -end_io: - bio_endio(bio, bio->bi_size, -EIO); - break; - } - - if (unlikely(bio_sectors(bio) > q->max_hw_sectors)) { - printk("bio too big device %s (%u > %u)\n", - bdevname(bio->bi_bdev, b), - bio_sectors(bio), - q->max_hw_sectors); - goto end_io; - } - - if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) - goto end_io; - - /* - * If this device has partitions, remap block n - * of partition p to block n+start(p) of the disk. - */ - blk_partition_remap(bio); - - ret = q->make_request_fn(q, bio); - } while (ret); -} - -EXPORT_SYMBOL(generic_make_request); - -/** - * submit_bio: submit a bio to the block device layer for I/O - * @rw: whether to %READ or %WRITE, or maybe to %READA (read ahead) - * @bio: The &struct bio which describes the I/O - * - * submit_bio() is very similar in purpose to generic_make_request(), and - * uses that function to do most of the work. Both are fairly rough - * interfaces, @bio must be presetup and ready for I/O. - * - */ -void submit_bio(int rw, struct bio *bio) -{ - int count = bio_sectors(bio); - - BIO_BUG_ON(!bio->bi_size); - BIO_BUG_ON(!bio->bi_io_vec); - bio->bi_rw |= rw; - if (rw & WRITE) - mod_page_state(pgpgout, count); - else - mod_page_state(pgpgin, count); - - if (unlikely(block_dump)) { - char b[BDEVNAME_SIZE]; - printk(KERN_DEBUG "%s(%d): %s block %Lu on %s\n", - current->comm, current->pid, - (rw & WRITE) ? "WRITE" : "READ", - (unsigned long long)bio->bi_sector, - bdevname(bio->bi_bdev,b)); - } - - generic_make_request(bio); -} - -EXPORT_SYMBOL(submit_bio); - -static void blk_recalc_rq_segments(struct request *rq) -{ - struct bio *bio, *prevbio = NULL; - int nr_phys_segs, nr_hw_segs; - unsigned int phys_size, hw_size; - request_queue_t *q = rq->q; - - if (!rq->bio) - return; - - phys_size = hw_size = nr_phys_segs = nr_hw_segs = 0; - rq_for_each_bio(bio, rq) { - /* Force bio hw/phys segs to be recalculated. */ - bio->bi_flags &= ~(1 << BIO_SEG_VALID); - - nr_phys_segs += bio_phys_segments(q, bio); - nr_hw_segs += bio_hw_segments(q, bio); - if (prevbio) { - int pseg = phys_size + prevbio->bi_size + bio->bi_size; - int hseg = hw_size + prevbio->bi_size + bio->bi_size; - - if (blk_phys_contig_segment(q, prevbio, bio) && - pseg <= q->max_segment_size) { - nr_phys_segs--; - phys_size += prevbio->bi_size + bio->bi_size; - } else - phys_size = 0; - - if (blk_hw_contig_segment(q, prevbio, bio) && - hseg <= q->max_segment_size) { - nr_hw_segs--; - hw_size += prevbio->bi_size + bio->bi_size; - } else - hw_size = 0; - } - prevbio = bio; - } - - rq->nr_phys_segments = nr_phys_segs; - rq->nr_hw_segments = nr_hw_segs; -} - -static void blk_recalc_rq_sectors(struct request *rq, int nsect) -{ - if (blk_fs_request(rq)) { - rq->hard_sector += nsect; - rq->hard_nr_sectors -= nsect; - - /* - * Move the I/O submission pointers ahead if required. - */ - if ((rq->nr_sectors >= rq->hard_nr_sectors) && - (rq->sector <= rq->hard_sector)) { - rq->sector = rq->hard_sector; - rq->nr_sectors = rq->hard_nr_sectors; - rq->hard_cur_sectors = bio_cur_sectors(rq->bio); - rq->current_nr_sectors = rq->hard_cur_sectors; - rq->buffer = bio_data(rq->bio); - } - - /* - * if total number of sectors is less than the first segment - * size, something has gone terribly wrong - */ - if (rq->nr_sectors < rq->current_nr_sectors) { - printk("blk: request botched\n"); - rq->nr_sectors = rq->current_nr_sectors; - } - } -} - -static int __end_that_request_first(struct request *req, int uptodate, - int nr_bytes) -{ - int total_bytes, bio_nbytes, error, next_idx = 0; - struct bio *bio; - - /* - * extend uptodate bool to allow < 0 value to be direct io error - */ - error = 0; - if (end_io_error(uptodate)) - error = !uptodate ? -EIO : uptodate; - - /* - * for a REQ_BLOCK_PC request, we want to carry any eventual - * sense key with us all the way through - */ - if (!blk_pc_request(req)) - req->errors = 0; - - if (!uptodate) { - if (blk_fs_request(req) && !(req->flags & REQ_QUIET)) - printk("end_request: I/O error, dev %s, sector %llu\n", - req->rq_disk ? req->rq_disk->disk_name : "?", - (unsigned long long)req->sector); - } - - if (blk_fs_request(req) && req->rq_disk) { - const int rw = rq_data_dir(req); - - __disk_stat_add(req->rq_disk, sectors[rw], nr_bytes >> 9); - } - - total_bytes = bio_nbytes = 0; - while ((bio = req->bio) != NULL) { - int nbytes; - - if (nr_bytes >= bio->bi_size) { - req->bio = bio->bi_next; - nbytes = bio->bi_size; - bio_endio(bio, nbytes, error); - next_idx = 0; - bio_nbytes = 0; - } else { - int idx = bio->bi_idx + next_idx; - - if (unlikely(bio->bi_idx >= bio->bi_vcnt)) { - blk_dump_rq_flags(req, "__end_that"); - printk("%s: bio idx %d >= vcnt %d\n", - __FUNCTION__, - bio->bi_idx, bio->bi_vcnt); - break; - } - - nbytes = bio_iovec_idx(bio, idx)->bv_len; - BIO_BUG_ON(nbytes > bio->bi_size); - - /* - * not a complete bvec done - */ - if (unlikely(nbytes > nr_bytes)) { - bio_nbytes += nr_bytes; - total_bytes += nr_bytes; - break; - } - - /* - * advance to the next vector - */ - next_idx++; - bio_nbytes += nbytes; - } - - total_bytes += nbytes; - nr_bytes -= nbytes; - - if ((bio = req->bio)) { - /* - * end more in this run, or just return 'not-done' - */ - if (unlikely(nr_bytes <= 0)) - break; - } - } - - /* - * completely done - */ - if (!req->bio) - return 0; - - /* - * if the request wasn't completed, update state - */ - if (bio_nbytes) { - bio_endio(bio, bio_nbytes, error); - bio->bi_idx += next_idx; - bio_iovec(bio)->bv_offset += nr_bytes; - bio_iovec(bio)->bv_len -= nr_bytes; - } - - blk_recalc_rq_sectors(req, total_bytes >> 9); - blk_recalc_rq_segments(req); - return 1; -} - -/** - * end_that_request_first - end I/O on a request - * @req: the request being processed - * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error - * @nr_sectors: number of sectors to end I/O on - * - * Description: - * Ends I/O on a number of sectors attached to @req, and sets it up - * for the next range of segments (if any) in the cluster. - * - * Return: - * 0 - we are done with this request, call end_that_request_last() - * 1 - still buffers pending for this request - **/ -int end_that_request_first(struct request *req, int uptodate, int nr_sectors) -{ - return __end_that_request_first(req, uptodate, nr_sectors << 9); -} - -EXPORT_SYMBOL(end_that_request_first); - -/** - * end_that_request_chunk - end I/O on a request - * @req: the request being processed - * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error - * @nr_bytes: number of bytes to complete - * - * Description: - * Ends I/O on a number of bytes attached to @req, and sets it up - * for the next range of segments (if any). Like end_that_request_first(), - * but deals with bytes instead of sectors. - * - * Return: - * 0 - we are done with this request, call end_that_request_last() - * 1 - still buffers pending for this request - **/ -int end_that_request_chunk(struct request *req, int uptodate, int nr_bytes) -{ - return __end_that_request_first(req, uptodate, nr_bytes); -} - -EXPORT_SYMBOL(end_that_request_chunk); - -/* - * queue lock must be held - */ -void end_that_request_last(struct request *req) -{ - struct gendisk *disk = req->rq_disk; - - if (unlikely(laptop_mode) && blk_fs_request(req)) - laptop_io_completion(); - - if (disk && blk_fs_request(req)) { - unsigned long duration = jiffies - req->start_time; - const int rw = rq_data_dir(req); - - __disk_stat_inc(disk, ios[rw]); - __disk_stat_add(disk, ticks[rw], duration); - disk_round_stats(disk); - disk->in_flight--; - } - if (req->end_io) - req->end_io(req); - else - __blk_put_request(req->q, req); -} - -EXPORT_SYMBOL(end_that_request_last); - -void end_request(struct request *req, int uptodate) -{ - if (!end_that_request_first(req, uptodate, req->hard_cur_sectors)) { - add_disk_randomness(req->rq_disk); - blkdev_dequeue_request(req); - end_that_request_last(req); - } -} - -EXPORT_SYMBOL(end_request); - -void blk_rq_bio_prep(request_queue_t *q, struct request *rq, struct bio *bio) -{ - /* first three bits are identical in rq->flags and bio->bi_rw */ - rq->flags |= (bio->bi_rw & 7); - - rq->nr_phys_segments = bio_phys_segments(q, bio); - rq->nr_hw_segments = bio_hw_segments(q, bio); - rq->current_nr_sectors = bio_cur_sectors(bio); - rq->hard_cur_sectors = rq->current_nr_sectors; - rq->hard_nr_sectors = rq->nr_sectors = bio_sectors(bio); - rq->buffer = bio_data(bio); - - rq->bio = rq->biotail = bio; -} - -EXPORT_SYMBOL(blk_rq_bio_prep); - -int kblockd_schedule_work(struct work_struct *work) -{ - return queue_work(kblockd_workqueue, work); -} - -EXPORT_SYMBOL(kblockd_schedule_work); - -void kblockd_flush(void) -{ - flush_workqueue(kblockd_workqueue); -} -EXPORT_SYMBOL(kblockd_flush); - -int __init blk_dev_init(void) -{ - kblockd_workqueue = create_workqueue("kblockd"); - if (!kblockd_workqueue) - panic("Failed to create kblockd\n"); - - request_cachep = kmem_cache_create("blkdev_requests", - sizeof(struct request), 0, SLAB_PANIC, NULL, NULL); - - requestq_cachep = kmem_cache_create("blkdev_queue", - sizeof(request_queue_t), 0, SLAB_PANIC, NULL, NULL); - - iocontext_cachep = kmem_cache_create("blkdev_ioc", - sizeof(struct io_context), 0, SLAB_PANIC, NULL, NULL); - - blk_max_low_pfn = max_low_pfn; - blk_max_pfn = max_pfn; - - return 0; -} - -/* - * IO Context helper functions - */ -void put_io_context(struct io_context *ioc) -{ - if (ioc == NULL) - return; - - BUG_ON(atomic_read(&ioc->refcount) == 0); - - if (atomic_dec_and_test(&ioc->refcount)) { - if (ioc->aic && ioc->aic->dtor) - ioc->aic->dtor(ioc->aic); - if (ioc->cic && ioc->cic->dtor) - ioc->cic->dtor(ioc->cic); - - kmem_cache_free(iocontext_cachep, ioc); - } -} -EXPORT_SYMBOL(put_io_context); - -/* Called by the exitting task */ -void exit_io_context(void) -{ - unsigned long flags; - struct io_context *ioc; - - local_irq_save(flags); - task_lock(current); - ioc = current->io_context; - current->io_context = NULL; - ioc->task = NULL; - task_unlock(current); - local_irq_restore(flags); - - if (ioc->aic && ioc->aic->exit) - ioc->aic->exit(ioc->aic); - if (ioc->cic && ioc->cic->exit) - ioc->cic->exit(ioc->cic); - - put_io_context(ioc); -} - -/* - * If the current task has no IO context then create one and initialise it. - * Otherwise, return its existing IO context. - * - * This returned IO context doesn't have a specifically elevated refcount, - * but since the current task itself holds a reference, the context can be - * used in general code, so long as it stays within `current` context. - */ -struct io_context *current_io_context(gfp_t gfp_flags) -{ - struct task_struct *tsk = current; - struct io_context *ret; - - ret = tsk->io_context; - if (likely(ret)) - return ret; - - ret = kmem_cache_alloc(iocontext_cachep, gfp_flags); - if (ret) { - atomic_set(&ret->refcount, 1); - ret->task = current; - ret->set_ioprio = NULL; - ret->last_waited = jiffies; /* doesn't matter... */ - ret->nr_batch_requests = 0; /* because this is 0 */ - ret->aic = NULL; - ret->cic = NULL; - tsk->io_context = ret; - } - - return ret; -} -EXPORT_SYMBOL(current_io_context); - -/* - * If the current task has no IO context then create one and initialise it. - * If it does have a context, take a ref on it. - * - * This is always called in the context of the task which submitted the I/O. - */ -struct io_context *get_io_context(gfp_t gfp_flags) -{ - struct io_context *ret; - ret = current_io_context(gfp_flags); - if (likely(ret)) - atomic_inc(&ret->refcount); - return ret; -} -EXPORT_SYMBOL(get_io_context); - -void copy_io_context(struct io_context **pdst, struct io_context **psrc) -{ - struct io_context *src = *psrc; - struct io_context *dst = *pdst; - - if (src) { - BUG_ON(atomic_read(&src->refcount) == 0); - atomic_inc(&src->refcount); - put_io_context(dst); - *pdst = src; - } -} -EXPORT_SYMBOL(copy_io_context); - -void swap_io_context(struct io_context **ioc1, struct io_context **ioc2) -{ - struct io_context *temp; - temp = *ioc1; - *ioc1 = *ioc2; - *ioc2 = temp; -} -EXPORT_SYMBOL(swap_io_context); - -/* - * sysfs parts below - */ -struct queue_sysfs_entry { - struct attribute attr; - ssize_t (*show)(struct request_queue *, char *); - ssize_t (*store)(struct request_queue *, const char *, size_t); -}; - -static ssize_t -queue_var_show(unsigned int var, char *page) -{ - return sprintf(page, "%d\n", var); -} - -static ssize_t -queue_var_store(unsigned long *var, const char *page, size_t count) -{ - char *p = (char *) page; - - *var = simple_strtoul(p, &p, 10); - return count; -} - -static ssize_t queue_requests_show(struct request_queue *q, char *page) -{ - return queue_var_show(q->nr_requests, (page)); -} - -static ssize_t -queue_requests_store(struct request_queue *q, const char *page, size_t count) -{ - struct request_list *rl = &q->rq; - - int ret = queue_var_store(&q->nr_requests, page, count); - if (q->nr_requests < BLKDEV_MIN_RQ) - q->nr_requests = BLKDEV_MIN_RQ; - blk_queue_congestion_threshold(q); - - if (rl->count[READ] >= queue_congestion_on_threshold(q)) - set_queue_congested(q, READ); - else if (rl->count[READ] < queue_congestion_off_threshold(q)) - clear_queue_congested(q, READ); - - if (rl->count[WRITE] >= queue_congestion_on_threshold(q)) - set_queue_congested(q, WRITE); - else if (rl->count[WRITE] < queue_congestion_off_threshold(q)) - clear_queue_congested(q, WRITE); - - if (rl->count[READ] >= q->nr_requests) { - blk_set_queue_full(q, READ); - } else if (rl->count[READ]+1 <= q->nr_requests) { - blk_clear_queue_full(q, READ); - wake_up(&rl->wait[READ]); - } - - if (rl->count[WRITE] >= q->nr_requests) { - blk_set_queue_full(q, WRITE); - } else if (rl->count[WRITE]+1 <= q->nr_requests) { - blk_clear_queue_full(q, WRITE); - wake_up(&rl->wait[WRITE]); - } - return ret; -} - -static ssize_t queue_ra_show(struct request_queue *q, char *page) -{ - int ra_kb = q->backing_dev_info.ra_pages << (PAGE_CACHE_SHIFT - 10); - - return queue_var_show(ra_kb, (page)); -} - -static ssize_t -queue_ra_store(struct request_queue *q, const char *page, size_t count) -{ - unsigned long ra_kb; - ssize_t ret = queue_var_store(&ra_kb, page, count); - - spin_lock_irq(q->queue_lock); - if (ra_kb > (q->max_sectors >> 1)) - ra_kb = (q->max_sectors >> 1); - - q->backing_dev_info.ra_pages = ra_kb >> (PAGE_CACHE_SHIFT - 10); - spin_unlock_irq(q->queue_lock); - - return ret; -} - -static ssize_t queue_max_sectors_show(struct request_queue *q, char *page) -{ - int max_sectors_kb = q->max_sectors >> 1; - - return queue_var_show(max_sectors_kb, (page)); -} - -static ssize_t -queue_max_sectors_store(struct request_queue *q, const char *page, size_t count) -{ - unsigned long max_sectors_kb, - max_hw_sectors_kb = q->max_hw_sectors >> 1, - page_kb = 1 << (PAGE_CACHE_SHIFT - 10); - ssize_t ret = queue_var_store(&max_sectors_kb, page, count); - int ra_kb; - - if (max_sectors_kb > max_hw_sectors_kb || max_sectors_kb < page_kb) - return -EINVAL; - /* - * Take the queue lock to update the readahead and max_sectors - * values synchronously: - */ - spin_lock_irq(q->queue_lock); - /* - * Trim readahead window as well, if necessary: - */ - ra_kb = q->backing_dev_info.ra_pages << (PAGE_CACHE_SHIFT - 10); - if (ra_kb > max_sectors_kb) - q->backing_dev_info.ra_pages = - max_sectors_kb >> (PAGE_CACHE_SHIFT - 10); - - q->max_sectors = max_sectors_kb << 1; - spin_unlock_irq(q->queue_lock); - - return ret; -} - -static ssize_t queue_max_hw_sectors_show(struct request_queue *q, char *page) -{ - int max_hw_sectors_kb = q->max_hw_sectors >> 1; - - return queue_var_show(max_hw_sectors_kb, (page)); -} - - -static struct queue_sysfs_entry queue_requests_entry = { - .attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR }, - .show = queue_requests_show, - .store = queue_requests_store, -}; - -static struct queue_sysfs_entry queue_ra_entry = { - .attr = {.name = "read_ahead_kb", .mode = S_IRUGO | S_IWUSR }, - .show = queue_ra_show, - .store = queue_ra_store, -}; - -static struct queue_sysfs_entry queue_max_sectors_entry = { - .attr = {.name = "max_sectors_kb", .mode = S_IRUGO | S_IWUSR }, - .show = queue_max_sectors_show, - .store = queue_max_sectors_store, -}; - -static struct queue_sysfs_entry queue_max_hw_sectors_entry = { - .attr = {.name = "max_hw_sectors_kb", .mode = S_IRUGO }, - .show = queue_max_hw_sectors_show, -}; - -static struct queue_sysfs_entry queue_iosched_entry = { - .attr = {.name = "scheduler", .mode = S_IRUGO | S_IWUSR }, - .show = elv_iosched_show, - .store = elv_iosched_store, -}; - -static struct attribute *default_attrs[] = { - &queue_requests_entry.attr, - &queue_ra_entry.attr, - &queue_max_hw_sectors_entry.attr, - &queue_max_sectors_entry.attr, - &queue_iosched_entry.attr, - NULL, -}; - -#define to_queue(atr) container_of((atr), struct queue_sysfs_entry, attr) - -static ssize_t -queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page) -{ - struct queue_sysfs_entry *entry = to_queue(attr); - struct request_queue *q; - - q = container_of(kobj, struct request_queue, kobj); - if (!entry->show) - return -EIO; - - return entry->show(q, page); -} - -static ssize_t -queue_attr_store(struct kobject *kobj, struct attribute *attr, - const char *page, size_t length) -{ - struct queue_sysfs_entry *entry = to_queue(attr); - struct request_queue *q; - - q = container_of(kobj, struct request_queue, kobj); - if (!entry->store) - return -EIO; - - return entry->store(q, page, length); -} - -static struct sysfs_ops queue_sysfs_ops = { - .show = queue_attr_show, - .store = queue_attr_store, -}; - -static struct kobj_type queue_ktype = { - .sysfs_ops = &queue_sysfs_ops, - .default_attrs = default_attrs, -}; - -int blk_register_queue(struct gendisk *disk) -{ - int ret; - - request_queue_t *q = disk->queue; - - if (!q || !q->request_fn) - return -ENXIO; - - q->kobj.parent = kobject_get(&disk->kobj); - if (!q->kobj.parent) - return -EBUSY; - - snprintf(q->kobj.name, KOBJ_NAME_LEN, "%s", "queue"); - q->kobj.ktype = &queue_ktype; - - ret = kobject_register(&q->kobj); - if (ret < 0) - return ret; - - ret = elv_register_queue(q); - if (ret) { - kobject_unregister(&q->kobj); - return ret; - } - - return 0; -} - -void blk_unregister_queue(struct gendisk *disk) -{ - request_queue_t *q = disk->queue; - - if (q && q->request_fn) { - elv_unregister_queue(q); - - kobject_unregister(&q->kobj); - kobject_put(&disk->kobj); - } -} diff --git a/drivers/block/noop-iosched.c b/drivers/block/noop-iosched.c deleted file mode 100644 index e54f006e7e6..00000000000 --- a/drivers/block/noop-iosched.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * elevator noop - */ -#include -#include -#include -#include -#include - -static void elevator_noop_add_request(request_queue_t *q, struct request *rq) -{ - rq->flags |= REQ_NOMERGE; - elv_dispatch_add_tail(q, rq); -} - -static int elevator_noop_dispatch(request_queue_t *q, int force) -{ - return 0; -} - -static struct elevator_type elevator_noop = { - .ops = { - .elevator_dispatch_fn = elevator_noop_dispatch, - .elevator_add_req_fn = elevator_noop_add_request, - }, - .elevator_name = "noop", - .elevator_owner = THIS_MODULE, -}; - -static int __init noop_init(void) -{ - return elv_register(&elevator_noop); -} - -static void __exit noop_exit(void) -{ - elv_unregister(&elevator_noop); -} - -module_init(noop_init); -module_exit(noop_exit); - - -MODULE_AUTHOR("Jens Axboe"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("No-op IO scheduler"); diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c deleted file mode 100644 index 382dea7b224..00000000000 --- a/drivers/block/scsi_ioctl.c +++ /dev/null @@ -1,589 +0,0 @@ -/* - * Copyright (C) 2001 Jens Axboe - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public Licens - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111- - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* Command group 3 is reserved and should never be used. */ -const unsigned char scsi_command_size[8] = -{ - 6, 10, 10, 12, - 16, 12, 10, 10 -}; - -EXPORT_SYMBOL(scsi_command_size); - -#define BLK_DEFAULT_TIMEOUT (60 * HZ) - -#include - -static int sg_get_version(int __user *p) -{ - static int sg_version_num = 30527; - return put_user(sg_version_num, p); -} - -static int scsi_get_idlun(request_queue_t *q, int __user *p) -{ - return put_user(0, p); -} - -static int scsi_get_bus(request_queue_t *q, int __user *p) -{ - return put_user(0, p); -} - -static int sg_get_timeout(request_queue_t *q) -{ - return q->sg_timeout / (HZ / USER_HZ); -} - -static int sg_set_timeout(request_queue_t *q, int __user *p) -{ - int timeout, err = get_user(timeout, p); - - if (!err) - q->sg_timeout = timeout * (HZ / USER_HZ); - - return err; -} - -static int sg_get_reserved_size(request_queue_t *q, int __user *p) -{ - return put_user(q->sg_reserved_size, p); -} - -static int sg_set_reserved_size(request_queue_t *q, int __user *p) -{ - int size, err = get_user(size, p); - - if (err) - return err; - - if (size < 0) - return -EINVAL; - if (size > (q->max_sectors << 9)) - size = q->max_sectors << 9; - - q->sg_reserved_size = size; - return 0; -} - -/* - * will always return that we are ATAPI even for a real SCSI drive, I'm not - * so sure this is worth doing anything about (why would you care??) - */ -static int sg_emulated_host(request_queue_t *q, int __user *p) -{ - return put_user(1, p); -} - -#define CMD_READ_SAFE 0x01 -#define CMD_WRITE_SAFE 0x02 -#define CMD_WARNED 0x04 -#define safe_for_read(cmd) [cmd] = CMD_READ_SAFE -#define safe_for_write(cmd) [cmd] = CMD_WRITE_SAFE - -static int verify_command(struct file *file, unsigned char *cmd) -{ - static unsigned char cmd_type[256] = { - - /* Basic read-only commands */ - safe_for_read(TEST_UNIT_READY), - safe_for_read(REQUEST_SENSE), - safe_for_read(READ_6), - safe_for_read(READ_10), - safe_for_read(READ_12), - safe_for_read(READ_16), - safe_for_read(READ_BUFFER), - safe_for_read(READ_DEFECT_DATA), - safe_for_read(READ_LONG), - safe_for_read(INQUIRY), - safe_for_read(MODE_SENSE), - safe_for_read(MODE_SENSE_10), - safe_for_read(LOG_SENSE), - safe_for_read(START_STOP), - safe_for_read(GPCMD_VERIFY_10), - safe_for_read(VERIFY_16), - - /* Audio CD commands */ - safe_for_read(GPCMD_PLAY_CD), - safe_for_read(GPCMD_PLAY_AUDIO_10), - safe_for_read(GPCMD_PLAY_AUDIO_MSF), - safe_for_read(GPCMD_PLAY_AUDIO_TI), - safe_for_read(GPCMD_PAUSE_RESUME), - - /* CD/DVD data reading */ - safe_for_read(GPCMD_READ_BUFFER_CAPACITY), - safe_for_read(GPCMD_READ_CD), - safe_for_read(GPCMD_READ_CD_MSF), - safe_for_read(GPCMD_READ_DISC_INFO), - safe_for_read(GPCMD_READ_CDVD_CAPACITY), - safe_for_read(GPCMD_READ_DVD_STRUCTURE), - safe_for_read(GPCMD_READ_HEADER), - safe_for_read(GPCMD_READ_TRACK_RZONE_INFO), - safe_for_read(GPCMD_READ_SUBCHANNEL), - safe_for_read(GPCMD_READ_TOC_PMA_ATIP), - safe_for_read(GPCMD_REPORT_KEY), - safe_for_read(GPCMD_SCAN), - safe_for_read(GPCMD_GET_CONFIGURATION), - safe_for_read(GPCMD_READ_FORMAT_CAPACITIES), - safe_for_read(GPCMD_GET_EVENT_STATUS_NOTIFICATION), - safe_for_read(GPCMD_GET_PERFORMANCE), - safe_for_read(GPCMD_SEEK), - safe_for_read(GPCMD_STOP_PLAY_SCAN), - - /* Basic writing commands */ - safe_for_write(WRITE_6), - safe_for_write(WRITE_10), - safe_for_write(WRITE_VERIFY), - safe_for_write(WRITE_12), - safe_for_write(WRITE_VERIFY_12), - safe_for_write(WRITE_16), - safe_for_write(WRITE_LONG), - safe_for_write(WRITE_LONG_2), - safe_for_write(ERASE), - safe_for_write(GPCMD_MODE_SELECT_10), - safe_for_write(MODE_SELECT), - safe_for_write(LOG_SELECT), - safe_for_write(GPCMD_BLANK), - safe_for_write(GPCMD_CLOSE_TRACK), - safe_for_write(GPCMD_FLUSH_CACHE), - safe_for_write(GPCMD_FORMAT_UNIT), - safe_for_write(GPCMD_REPAIR_RZONE_TRACK), - safe_for_write(GPCMD_RESERVE_RZONE_TRACK), - safe_for_write(GPCMD_SEND_DVD_STRUCTURE), - safe_for_write(GPCMD_SEND_EVENT), - safe_for_write(GPCMD_SEND_KEY), - safe_for_write(GPCMD_SEND_OPC), - safe_for_write(GPCMD_SEND_CUE_SHEET), - safe_for_write(GPCMD_SET_SPEED), - safe_for_write(GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL), - safe_for_write(GPCMD_LOAD_UNLOAD), - safe_for_write(GPCMD_SET_STREAMING), - }; - unsigned char type = cmd_type[cmd[0]]; - - /* Anybody who can open the device can do a read-safe command */ - if (type & CMD_READ_SAFE) - return 0; - - /* Write-safe commands just require a writable open.. */ - if (type & CMD_WRITE_SAFE) { - if (file->f_mode & FMODE_WRITE) - return 0; - } - - /* And root can do any command.. */ - if (capable(CAP_SYS_RAWIO)) - return 0; - - if (!type) { - cmd_type[cmd[0]] = CMD_WARNED; - printk(KERN_WARNING "scsi: unknown opcode 0x%02x\n", cmd[0]); - } - - /* Otherwise fail it with an "Operation not permitted" */ - return -EPERM; -} - -static int sg_io(struct file *file, request_queue_t *q, - struct gendisk *bd_disk, struct sg_io_hdr *hdr) -{ - unsigned long start_time; - int writing = 0, ret = 0; - struct request *rq; - struct bio *bio; - char sense[SCSI_SENSE_BUFFERSIZE]; - unsigned char cmd[BLK_MAX_CDB]; - - if (hdr->interface_id != 'S') - return -EINVAL; - if (hdr->cmd_len > BLK_MAX_CDB) - return -EINVAL; - if (copy_from_user(cmd, hdr->cmdp, hdr->cmd_len)) - return -EFAULT; - if (verify_command(file, cmd)) - return -EPERM; - - if (hdr->dxfer_len > (q->max_sectors << 9)) - return -EIO; - - if (hdr->dxfer_len) - switch (hdr->dxfer_direction) { - default: - return -EINVAL; - case SG_DXFER_TO_FROM_DEV: - case SG_DXFER_TO_DEV: - writing = 1; - break; - case SG_DXFER_FROM_DEV: - break; - } - - rq = blk_get_request(q, writing ? WRITE : READ, GFP_KERNEL); - if (!rq) - return -ENOMEM; - - if (hdr->iovec_count) { - const int size = sizeof(struct sg_iovec) * hdr->iovec_count; - struct sg_iovec *iov; - - iov = kmalloc(size, GFP_KERNEL); - if (!iov) { - ret = -ENOMEM; - goto out; - } - - if (copy_from_user(iov, hdr->dxferp, size)) { - kfree(iov); - ret = -EFAULT; - goto out; - } - - ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count); - kfree(iov); - } else if (hdr->dxfer_len) - ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len); - - if (ret) - goto out; - - /* - * fill in request structure - */ - rq->cmd_len = hdr->cmd_len; - memcpy(rq->cmd, cmd, hdr->cmd_len); - if (sizeof(rq->cmd) != hdr->cmd_len) - memset(rq->cmd + hdr->cmd_len, 0, sizeof(rq->cmd) - hdr->cmd_len); - - memset(sense, 0, sizeof(sense)); - rq->sense = sense; - rq->sense_len = 0; - - rq->flags |= REQ_BLOCK_PC; - bio = rq->bio; - - /* - * bounce this after holding a reference to the original bio, it's - * needed for proper unmapping - */ - if (rq->bio) - blk_queue_bounce(q, &rq->bio); - - rq->timeout = (hdr->timeout * HZ) / 1000; - if (!rq->timeout) - rq->timeout = q->sg_timeout; - if (!rq->timeout) - rq->timeout = BLK_DEFAULT_TIMEOUT; - - start_time = jiffies; - - /* ignore return value. All information is passed back to caller - * (if he doesn't check that is his problem). - * N.B. a non-zero SCSI status is _not_ necessarily an error. - */ - blk_execute_rq(q, bd_disk, rq, 0); - - /* write to all output members */ - hdr->status = 0xff & rq->errors; - hdr->masked_status = status_byte(rq->errors); - hdr->msg_status = msg_byte(rq->errors); - hdr->host_status = host_byte(rq->errors); - hdr->driver_status = driver_byte(rq->errors); - hdr->info = 0; - if (hdr->masked_status || hdr->host_status || hdr->driver_status) - hdr->info |= SG_INFO_CHECK; - hdr->resid = rq->data_len; - hdr->duration = ((jiffies - start_time) * 1000) / HZ; - hdr->sb_len_wr = 0; - - if (rq->sense_len && hdr->sbp) { - int len = min((unsigned int) hdr->mx_sb_len, rq->sense_len); - - if (!copy_to_user(hdr->sbp, rq->sense, len)) - hdr->sb_len_wr = len; - } - - if (blk_rq_unmap_user(bio, hdr->dxfer_len)) - ret = -EFAULT; - - /* may not have succeeded, but output values written to control - * structure (struct sg_io_hdr). */ -out: - blk_put_request(rq); - return ret; -} - -#define OMAX_SB_LEN 16 /* For backward compatibility */ - -static int sg_scsi_ioctl(struct file *file, request_queue_t *q, - struct gendisk *bd_disk, Scsi_Ioctl_Command __user *sic) -{ - struct request *rq; - int err; - unsigned int in_len, out_len, bytes, opcode, cmdlen; - char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE]; - - /* - * get in an out lengths, verify they don't exceed a page worth of data - */ - if (get_user(in_len, &sic->inlen)) - return -EFAULT; - if (get_user(out_len, &sic->outlen)) - return -EFAULT; - if (in_len > PAGE_SIZE || out_len > PAGE_SIZE) - return -EINVAL; - if (get_user(opcode, sic->data)) - return -EFAULT; - - bytes = max(in_len, out_len); - if (bytes) { - buffer = kmalloc(bytes, q->bounce_gfp | GFP_USER| __GFP_NOWARN); - if (!buffer) - return -ENOMEM; - - memset(buffer, 0, bytes); - } - - rq = blk_get_request(q, in_len ? WRITE : READ, __GFP_WAIT); - - cmdlen = COMMAND_SIZE(opcode); - - /* - * get command and data to send to device, if any - */ - err = -EFAULT; - rq->cmd_len = cmdlen; - if (copy_from_user(rq->cmd, sic->data, cmdlen)) - goto error; - - if (copy_from_user(buffer, sic->data + cmdlen, in_len)) - goto error; - - err = verify_command(file, rq->cmd); - if (err) - goto error; - - switch (opcode) { - case SEND_DIAGNOSTIC: - case FORMAT_UNIT: - rq->timeout = FORMAT_UNIT_TIMEOUT; - break; - case START_STOP: - rq->timeout = START_STOP_TIMEOUT; - break; - case MOVE_MEDIUM: - rq->timeout = MOVE_MEDIUM_TIMEOUT; - break; - case READ_ELEMENT_STATUS: - rq->timeout = READ_ELEMENT_STATUS_TIMEOUT; - break; - case READ_DEFECT_DATA: - rq->timeout = READ_DEFECT_DATA_TIMEOUT; - break; - default: - rq->timeout = BLK_DEFAULT_TIMEOUT; - break; - } - - memset(sense, 0, sizeof(sense)); - rq->sense = sense; - rq->sense_len = 0; - - rq->data = buffer; - rq->data_len = bytes; - rq->flags |= REQ_BLOCK_PC; - - blk_execute_rq(q, bd_disk, rq, 0); - err = rq->errors & 0xff; /* only 8 bit SCSI status */ - if (err) { - if (rq->sense_len && rq->sense) { - bytes = (OMAX_SB_LEN > rq->sense_len) ? - rq->sense_len : OMAX_SB_LEN; - if (copy_to_user(sic->data, rq->sense, bytes)) - err = -EFAULT; - } - } else { - if (copy_to_user(sic->data, buffer, out_len)) - err = -EFAULT; - } - -error: - kfree(buffer); - blk_put_request(rq); - return err; -} - -int scsi_cmd_ioctl(struct file *file, struct gendisk *bd_disk, unsigned int cmd, void __user *arg) -{ - request_queue_t *q; - struct request *rq; - int close = 0, err; - - q = bd_disk->queue; - if (!q) - return -ENXIO; - - if (blk_get_queue(q)) - return -ENXIO; - - switch (cmd) { - /* - * new sgv3 interface - */ - case SG_GET_VERSION_NUM: - err = sg_get_version(arg); - break; - case SCSI_IOCTL_GET_IDLUN: - err = scsi_get_idlun(q, arg); - break; - case SCSI_IOCTL_GET_BUS_NUMBER: - err = scsi_get_bus(q, arg); - break; - case SG_SET_TIMEOUT: - err = sg_set_timeout(q, arg); - break; - case SG_GET_TIMEOUT: - err = sg_get_timeout(q); - break; - case SG_GET_RESERVED_SIZE: - err = sg_get_reserved_size(q, arg); - break; - case SG_SET_RESERVED_SIZE: - err = sg_set_reserved_size(q, arg); - break; - case SG_EMULATED_HOST: - err = sg_emulated_host(q, arg); - break; - case SG_IO: { - struct sg_io_hdr hdr; - - err = -EFAULT; - if (copy_from_user(&hdr, arg, sizeof(hdr))) - break; - err = sg_io(file, q, bd_disk, &hdr); - if (err == -EFAULT) - break; - - if (copy_to_user(arg, &hdr, sizeof(hdr))) - err = -EFAULT; - break; - } - case CDROM_SEND_PACKET: { - struct cdrom_generic_command cgc; - struct sg_io_hdr hdr; - - err = -EFAULT; - if (copy_from_user(&cgc, arg, sizeof(cgc))) - break; - cgc.timeout = clock_t_to_jiffies(cgc.timeout); - memset(&hdr, 0, sizeof(hdr)); - hdr.interface_id = 'S'; - hdr.cmd_len = sizeof(cgc.cmd); - hdr.dxfer_len = cgc.buflen; - err = 0; - switch (cgc.data_direction) { - case CGC_DATA_UNKNOWN: - hdr.dxfer_direction = SG_DXFER_UNKNOWN; - break; - case CGC_DATA_WRITE: - hdr.dxfer_direction = SG_DXFER_TO_DEV; - break; - case CGC_DATA_READ: - hdr.dxfer_direction = SG_DXFER_FROM_DEV; - break; - case CGC_DATA_NONE: - hdr.dxfer_direction = SG_DXFER_NONE; - break; - default: - err = -EINVAL; - } - if (err) - break; - - hdr.dxferp = cgc.buffer; - hdr.sbp = cgc.sense; - if (hdr.sbp) - hdr.mx_sb_len = sizeof(struct request_sense); - hdr.timeout = cgc.timeout; - hdr.cmdp = ((struct cdrom_generic_command __user*) arg)->cmd; - hdr.cmd_len = sizeof(cgc.cmd); - - err = sg_io(file, q, bd_disk, &hdr); - if (err == -EFAULT) - break; - - if (hdr.status) - err = -EIO; - - cgc.stat = err; - cgc.buflen = hdr.resid; - if (copy_to_user(arg, &cgc, sizeof(cgc))) - err = -EFAULT; - - break; - } - - /* - * old junk scsi send command ioctl - */ - case SCSI_IOCTL_SEND_COMMAND: - printk(KERN_WARNING "program %s is using a deprecated SCSI ioctl, please convert it to SG_IO\n", current->comm); - err = -EINVAL; - if (!arg) - break; - - err = sg_scsi_ioctl(file, q, bd_disk, arg); - break; - case CDROMCLOSETRAY: - close = 1; - case CDROMEJECT: - rq = blk_get_request(q, WRITE, __GFP_WAIT); - rq->flags |= REQ_BLOCK_PC; - rq->data = NULL; - rq->data_len = 0; - rq->timeout = BLK_DEFAULT_TIMEOUT; - memset(rq->cmd, 0, sizeof(rq->cmd)); - rq->cmd[0] = GPCMD_START_STOP_UNIT; - rq->cmd[4] = 0x02 + (close != 0); - rq->cmd_len = 6; - err = blk_execute_rq(q, bd_disk, rq, 0); - blk_put_request(rq); - break; - default: - err = -ENOTTY; - } - - blk_put_queue(q); - return err; -} - -EXPORT_SYMBOL(scsi_cmd_ioctl); diff --git a/init/Kconfig b/init/Kconfig index 3dcbd5bfd49..ea097e0a9c0 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -501,3 +501,7 @@ config STOP_MACHINE help Need stop_machine() primitive. endmenu + +menu "Block layer" +source "block/Kconfig" +endmenu -- cgit v1.2.3 From c6ea2ba7b8acdb6c4a883b2d38607c8078dff4ee Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 4 Nov 2005 08:44:58 +0100 Subject: [BLOCK] iosched: fix setting of default io scheduler With the recent reorg of the io scheduler selection, it unfortunately became possible to select an io scheduler to be the default even if it wasn't builtin. Fix this by requiring the default scheduler to be builtin. Signed-off-by: Jens Axboe --- block/Kconfig.iosched | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched index 5b90d2fa63b..f3b7753aac9 100644 --- a/block/Kconfig.iosched +++ b/block/Kconfig.iosched @@ -46,13 +46,13 @@ choice block devices. config DEFAULT_AS - bool "Anticipatory" if IOSCHED_AS + bool "Anticipatory" if IOSCHED_AS=y config DEFAULT_DEADLINE - bool "Deadline" if IOSCHED_DEADLINE + bool "Deadline" if IOSCHED_DEADLINE=y config DEFAULT_CFQ - bool "CFQ" if IOSCHED_CFQ + bool "CFQ" if IOSCHED_CFQ=y config DEFAULT_NOOP bool "No-op" -- cgit v1.2.3 From edf8e4565c44bffbb4d09e8984df941d0ae9e6e8 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Tue, 13 Sep 2005 11:32:58 +0200 Subject: [ALSA] emu10k1: Front channels via fxbus 8 and 9 Modules: EMU10K1/EMU10K2 driver Adds left and right front channel outputs using fxbus 8 and 9 and 'Front' playback and capture volume controls. Signed-off-by: Mikael Magnusson Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/emufx.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 646b5d972e6..20db3ac6cd6 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c @@ -964,8 +964,8 @@ static int snd_emu10k1_ipcm_peek(emu10k1_t *emu, emu10k1_fx8010_pcm_t *ipcm) return err; } -#define SND_EMU10K1_GPR_CONTROLS 41 -#define SND_EMU10K1_INPUTS 10 +#define SND_EMU10K1_GPR_CONTROLS 44 +#define SND_EMU10K1_INPUTS 12 #define SND_EMU10K1_PLAYBACK_CHANNELS 8 #define SND_EMU10K1_CAPTURE_CHANNELS 4 @@ -1527,7 +1527,7 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu) strcpy(icode->name, "SB Live! FX8010 code for ALSA v1.2 by Jaroslav Kysela"); ptr = 0; i = 0; - /* we have 10 inputs */ + /* we have 12 inputs */ playback = SND_EMU10K1_INPUTS; /* we have 6 playback channels and tone control doubles */ capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); @@ -1551,6 +1551,8 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu) OP(icode, &ptr, iMACINT0, GPR(7), C_00000000, FXBUS(FXBUS_PCM_LFE), C_00000004); OP(icode, &ptr, iMACINT0, GPR(8), C_00000000, C_00000000, C_00000000); /* S/PDIF left */ OP(icode, &ptr, iMACINT0, GPR(9), C_00000000, C_00000000, C_00000000); /* S/PDIF right */ + OP(icode, &ptr, iMACINT0, GPR(10), C_00000000, FXBUS(FXBUS_PCM_LEFT_FRONT), C_00000004); + OP(icode, &ptr, iMACINT0, GPR(11), C_00000000, FXBUS(FXBUS_PCM_RIGHT_FRONT), C_00000004); /* Raw S/PDIF PCM */ ipcm->substream = 0; @@ -1697,6 +1699,21 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu) VOLUME_ADD(icode, &ptr, playback + 5, 7, gpr); snd_emu10k1_init_mono_control(controls + i++, "LFE Digital Playback Volume", gpr++, 100); + /* Front Playback Volume */ + for (z = 0; z < 2; z++) + VOLUME_ADD(icode, &ptr, playback + z, 10 + z, gpr + z); + snd_emu10k1_init_stereo_control(controls + i++, "Front Playback Volume", gpr, 100); + gpr += 2; + + /* Front Capture Volume + Switch */ + for (z = 0; z < 2; z++) { + SWITCH(icode, &ptr, tmp + 0, 10 + z, gpr + 2); + VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z); + } + snd_emu10k1_init_stereo_control(controls + i++, "Front Capture Volume", gpr, 0); + snd_emu10k1_init_mono_onoff_control(controls + i++, "Front Capture Switch", gpr + 2, 0); + gpr += 3; + /* * Process inputs */ -- cgit v1.2.3 From 4525c9f31f4606881ed49d822b44c2c5d6080ef4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 13 Sep 2005 11:47:07 +0200 Subject: [ALSA] Fix surround control of CMI9761 Modules: AC97 Codec - Fixed surround controls of CMI9761 (model 83) in update_jacks callback. - Clean up ad1888 and ad1985 update_jacks callbacks. Signed-off-by: Takashi Iwai --- sound/pci/ac97/ac97_patch.c | 77 +++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 27 deletions(-) diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 0238cc65d32..ffc8d652107 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -163,14 +163,24 @@ static int ac97_channel_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t .private_value = 1, \ } +static inline int is_surround_on(ac97_t *ac97) +{ + return ac97->channel_mode >= 1; +} + +static inline int is_clfe_on(ac97_t *ac97) +{ + return a97->channel_mode >= 2; +} + static inline int is_shared_linein(ac97_t *ac97) { - return ! ac97->indep_surround && ac97->channel_mode >= 1; + return ! ac97->indep_surround && is_surround_on(ac97); } static inline int is_shared_micin(ac97_t *ac97) { - return ! ac97->indep_surround && ac97->channel_mode >= 2; + return ! ac97->indep_surround && is_clfe_on(ac97); } @@ -1753,12 +1763,13 @@ static int snd_ac97_ad1888_downmix_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_va static void ad1888_update_jacks(ac97_t *ac97) { + unsigned short val = 0; + if (! is_shared_linein(ac97)) + val |= (1 << 12); + if (! is_shared_micin(ac97)) + val |= (1 << 11); /* shared Line-In */ - snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 12, - is_shared_linein(ac97) ? 0 : 1 << 12); - /* shared Mic */ - snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 11, - is_shared_micin(ac97) ? 0 : 1 << 11); + snd_ac97_update_bits(ac97, AC97_AD_MISC, (1 << 11) | (1 << 12), val); } static const snd_kcontrol_new_t snd_ac97_ad1888_controls[] = { @@ -1852,12 +1863,7 @@ static const snd_kcontrol_new_t snd_ac97_ad1985_controls[] = { static void ad1985_update_jacks(ac97_t *ac97) { - /* shared Line-In */ - snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 12, - is_shared_linein(ac97) ? 0 : 1 << 12); - /* shared Mic */ - snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 11, - is_shared_micin(ac97) ? 0 : 1 << 11); + ad1888_update_jacks(ac97); snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 1 << 9, is_shared_micin(ac97) ? 0 : 1 << 9); } @@ -2442,21 +2448,37 @@ int patch_cm9739(ac97_t * ac97) static void cm9761_update_jacks(ac97_t *ac97) { - unsigned short surr_vals[2][2] = { - { 0x0008, 0x0400 }, /* off, on */ - { 0x0000, 0x0408 }, /* off, on (9761-82 rev.B) */ + /* FIXME: check the bits for each model + * model 83 is confirmed to work + */ + static unsigned short surr_on[3][2] = { + { 0x0008, 0x0000 }, /* 9761-78 & 82 */ + { 0x0000, 0x0008 }, /* 9761-82 rev.B */ + { 0x0000, 0x0008 }, /* 9761-83 */ + }; + static unsigned short clfe_on[3][2] = { + { 0x0000, 0x1000 }, /* 9761-78 & 82 */ + { 0x1000, 0x0000 }, /* 9761-82 rev.B */ + { 0x0000, 0x1000 }, /* 9761-83 */ + }; + static unsigned short surr_shared[3][2] = { + { 0x0000, 0x0400 }, /* 9761-78 & 82 */ + { 0x0000, 0x0400 }, /* 9761-82 rev.B */ + { 0x0000, 0x0400 }, /* 9761-83 */ }; - unsigned short clfe_vals[2][2] = { - { 0x2000, 0x1880 }, /* off, on */ - { 0x1000, 0x2880 }, /* off, on (9761-82 rev.B) */ + static unsigned short clfe_shared[3][2] = { + { 0x2000, 0x0880 }, /* 9761-78 & 82 */ + { 0x0000, 0x2880 }, /* 9761-82 rev.B */ + { 0x2000, 0x0800 }, /* 9761-83 */ }; + unsigned short val = 0; - /* shared Line-In */ - snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x0408, - surr_vals[ac97->spec.dev_flags][is_shared_linein(ac97)]); - /* shared Mic */ - snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3880, - clfe_vals[ac97->spec.dev_flags][is_shared_micin(ac97)]); + val |= surr_on[ac97->spec.dev_flags][is_surround_on(ac97)]; + val |= clfe_on[ac97->spec.dev_flags][is_clfe_on(ac97)]; + val |= surr_shared[ac97->spec.dev_flags][is_shared_linein(ac97)]; + val |= clfe_shared[ac97->spec.dev_flags][is_shared_micin(ac97)]; + + snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3c88, val); } static const snd_kcontrol_new_t snd_ac97_cm9761_controls[] = { @@ -2551,7 +2573,7 @@ int patch_cm9761(ac97_t *ac97) snd_ac97_write_cache(ac97, AC97_MASTER, 0x8808); snd_ac97_write_cache(ac97, AC97_PCM, 0x8808); - ac97->spec.dev_flags = 0; /* 1 = model 82 revision B */ + ac97->spec.dev_flags = 0; /* 1 = model 82 revision B, 2 = model 83 */ if (ac97->id == AC97_ID_CM9761_82) { unsigned short tmp; /* check page 1, reg 0x60 */ @@ -2560,7 +2582,8 @@ int patch_cm9761(ac97_t *ac97) tmp = snd_ac97_read(ac97, 0x60); ac97->spec.dev_flags = tmp & 1; /* revision B? */ snd_ac97_write_cache(ac97, AC97_INT_PAGING, val); - } + } else if (ac97->id == AC97_ID_CM9761_83) + ac97->spec.dev_flags = 2; ac97->build_ops = &patch_cm9761_ops; -- cgit v1.2.3 From eb9b4142b3af98d808012081c4dd6d36e2964d43 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 13 Sep 2005 18:39:21 +0200 Subject: [ALSA] Fix a typo Modules: AC97 Codec Fix a typo in the last patch. Signed-off-by: Takashi Iwai --- sound/pci/ac97/ac97_patch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index ffc8d652107..b24beb32961 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -170,7 +170,7 @@ static inline int is_surround_on(ac97_t *ac97) static inline int is_clfe_on(ac97_t *ac97) { - return a97->channel_mode >= 2; + return ac97->channel_mode >= 2; } static inline int is_shared_linein(ac97_t *ac97) -- cgit v1.2.3 From da3fca21996414a263d36804d9afb2e701abbfef Mon Sep 17 00:00:00 2001 From: Vinod G Date: Tue, 13 Sep 2005 18:49:12 +0200 Subject: [ALSA] hda-intel - Add NVidia support Modules: HDA Intel driver This patch is to make the Intel HDA code work for NVIDIA azalia controller. Modified by Takashi Iwai Signed-off-by: Vinod G. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 6fe696e53ea..2c5d4114771 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -223,6 +223,9 @@ enum { #define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42 #define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02 +/* Defines for Nvidia HDA support */ +#define NVIDIA_HDA_TRANSREG_ADDR 0x4e +#define NVIDIA_HDA_ENABLE_COHBITS 0x0f /* * Use CORB/RIRB for communication from/to codecs. @@ -328,6 +331,7 @@ enum { AZX_DRIVER_VIA, AZX_DRIVER_SIS, AZX_DRIVER_ULI, + AZX_DRIVER_NVIDIA, }; static char *driver_short_names[] __devinitdata = { @@ -335,7 +339,8 @@ static char *driver_short_names[] __devinitdata = { [AZX_DRIVER_ATI] = "HDA ATI SB", [AZX_DRIVER_VIA] = "HDA VIA VT82xx", [AZX_DRIVER_SIS] = "HDA SIS966", - [AZX_DRIVER_ULI] = "HDA ULI M5461" + [AZX_DRIVER_ULI] = "HDA ULI M5461", + [AZX_DRIVER_NVIDIA] = "HDA NVidia", }; /* @@ -710,14 +715,14 @@ static void azx_stream_stop(azx_t *chip, azx_dev_t *azx_dev) */ static void azx_init_chip(azx_t *chip) { - unsigned char tcsel_reg, ati_misc_cntl2; + unsigned char reg; /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44) * TCSEL == Traffic Class Select Register, which sets PCI express QOS * Ensuring these bits are 0 clears playback static on some HD Audio codecs */ - pci_read_config_byte (chip->pci, ICH6_PCIREG_TCSEL, &tcsel_reg); - pci_write_config_byte(chip->pci, ICH6_PCIREG_TCSEL, tcsel_reg & 0xf8); + pci_read_config_byte (chip->pci, ICH6_PCIREG_TCSEL, ®); + pci_write_config_byte(chip->pci, ICH6_PCIREG_TCSEL, reg & 0xf8); /* reset controller */ azx_reset(chip); @@ -733,13 +738,21 @@ static void azx_init_chip(azx_t *chip) azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr)); - /* For ATI SB450 azalia HD audio, we need to enable snoop */ - if (chip->driver_type == AZX_DRIVER_ATI) { + switch (chip->driver_type) { + case AZX_DRIVER_ATI: + /* For ATI SB450 azalia HD audio, we need to enable snoop */ pci_read_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, - &ati_misc_cntl2); + ®); pci_write_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, - (ati_misc_cntl2 & 0xf8) | ATI_SB450_HDAUDIO_ENABLE_SNOOP); - } + (reg & 0xf8) | ATI_SB450_HDAUDIO_ENABLE_SNOOP); + break; + case AZX_DRIVER_NVIDIA: + /* For NVIDIA HDA, enable snoop */ + pci_read_config_byte(chip->pci,NVIDIA_HDA_TRANSREG_ADDR, ®); + pci_write_config_byte(chip->pci,NVIDIA_HDA_TRANSREG_ADDR, + (reg & 0xf0) | NVIDIA_HDA_ENABLE_COHBITS); + break; + } } @@ -1601,6 +1614,8 @@ static struct pci_device_id azx_ids[] = { { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */ { 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */ { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */ + { 0x10de, 0x026c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA 026c */ + { 0x10de, 0x0371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA 0371 */ { 0, } }; MODULE_DEVICE_TABLE(pci, azx_ids); -- cgit v1.2.3 From 5747e54042c710272cefed74cc457531a01768c9 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 14 Sep 2005 08:33:46 +0200 Subject: [ALSA] cmipci: use FM/MIDI ports in PCI port space Modules: CMIPCI driver If possible, use ports in the card's PCI port address range instead of the legacy ports. Signed-off-by: Clemens Ladisch --- sound/pci/cmipci.c | 118 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 68 insertions(+), 50 deletions(-) diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 1eb3315d136..316afb78488 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -446,9 +446,6 @@ struct snd_stru_cmipci { snd_kcontrol_t *mixer_res_ctl[CM_SAVED_MIXERS]; int mixer_res_status[CM_SAVED_MIXERS]; - opl3_t *opl3; - snd_hwdep_t *opl3hwdep; - cmipci_pcm_t channel[2]; /* ch0 - DAC, ch1 - ADC or 2nd DAC */ /* external MIDI */ @@ -2753,6 +2750,51 @@ static int snd_cmipci_dev_free(snd_device_t *device) return snd_cmipci_free(cm); } +static int __devinit snd_cmipci_create_fm(cmipci_t *cm, long fm_port) +{ + long iosynth; + unsigned int val; + opl3_t *opl3; + int err; + + /* first try FM regs in PCI port range */ + iosynth = cm->iobase + CM_REG_FM_PCI; + err = snd_opl3_create(cm->card, iosynth, iosynth + 2, + OPL3_HW_OPL3, 1, &opl3); + if (err < 0) { + /* then try legacy ports */ + val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL) & ~CM_FMSEL_MASK; + iosynth = fm_port; + switch (iosynth) { + case 0x3E8: val |= CM_FMSEL_3E8; break; + case 0x3E0: val |= CM_FMSEL_3E0; break; + case 0x3C8: val |= CM_FMSEL_3C8; break; + case 0x388: val |= CM_FMSEL_388; break; + default: + return 0; + } + snd_cmipci_write(cm, CM_REG_LEGACY_CTRL, val); + /* enable FM */ + snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_FM_EN); + + if (snd_opl3_create(cm->card, iosynth, iosynth + 2, + OPL3_HW_OPL3, 0, &opl3) < 0) { + printk(KERN_ERR "cmipci: no OPL device at %#lx, " + "skipping...\n", iosynth); + /* disable FM */ + snd_cmipci_write(cm, CM_REG_LEGACY_CTRL, + val & ~CM_FMSEL_MASK); + snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_FM_EN); + return 0; + } + } + if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { + printk(KERN_ERR "cmipci: cannot create OPL3 hwdep\n"); + return err; + } + return 0; +} + static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci, int dev, cmipci_t **rcmipci) { @@ -2762,8 +2804,8 @@ static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci, .dev_free = snd_cmipci_dev_free, }; unsigned int val = 0; - long iomidi = mpu_port[dev]; - long iosynth = fm_port[dev]; + long iomidi; + int integrated_midi; int pcm_index, pcm_spdif_index; static struct pci_device_id intel_82437vx[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437VX) }, @@ -2867,52 +2909,28 @@ static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci, return err; } - /* set MPU address */ - switch (iomidi) { - case 0x320: val = CM_VMPU_320; break; - case 0x310: val = CM_VMPU_310; break; - case 0x300: val = CM_VMPU_300; break; - case 0x330: val = CM_VMPU_330; break; - default: - iomidi = 0; break; - } - if (iomidi > 0) { - snd_cmipci_write(cm, CM_REG_LEGACY_CTRL, val); - /* enable UART */ - snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_UART_EN); - } - - /* set FM address */ - val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL) & ~CM_FMSEL_MASK; - switch (iosynth) { - case 0x3E8: val |= CM_FMSEL_3E8; break; - case 0x3E0: val |= CM_FMSEL_3E0; break; - case 0x3C8: val |= CM_FMSEL_3C8; break; - case 0x388: val |= CM_FMSEL_388; break; - default: - iosynth = 0; break; - } - if (iosynth > 0) { - snd_cmipci_write(cm, CM_REG_LEGACY_CTRL, val); - /* enable FM */ - snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_FM_EN); - - if (snd_opl3_create(card, iosynth, iosynth + 2, - OPL3_HW_OPL3, 0, &cm->opl3) < 0) { - printk(KERN_ERR "cmipci: no OPL device at 0x%lx, skipping...\n", iosynth); - iosynth = 0; - } else { - if ((err = snd_opl3_hwdep_new(cm->opl3, 0, 1, &cm->opl3hwdep)) < 0) { - printk(KERN_ERR "cmipci: cannot create OPL3 hwdep\n"); - return err; - } + integrated_midi = snd_cmipci_read_b(cm, CM_REG_MPU_PCI) != 0xff; + if (integrated_midi) + iomidi = cm->iobase + CM_REG_MPU_PCI; + else { + iomidi = mpu_port[dev]; + switch (iomidi) { + case 0x320: val = CM_VMPU_320; break; + case 0x310: val = CM_VMPU_310; break; + case 0x300: val = CM_VMPU_300; break; + case 0x330: val = CM_VMPU_330; break; + default: + iomidi = 0; break; + } + if (iomidi > 0) { + snd_cmipci_write(cm, CM_REG_LEGACY_CTRL, val); + /* enable UART */ + snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_UART_EN); } } - if (! iosynth) { - /* disable FM */ - snd_cmipci_write(cm, CM_REG_LEGACY_CTRL, val & ~CM_FMSEL_MASK); - snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_FM_EN); - } + + if ((err = snd_cmipci_create_fm(cm, fm_port[dev])) < 0) + return err; /* reset mixer */ snd_cmipci_mixer_write(cm, 0, 0); @@ -2941,7 +2959,7 @@ static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci, if (iomidi > 0) { if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI, - iomidi, 0, + iomidi, integrated_midi, cm->irq, 0, &cm->rmidi)) < 0) { printk(KERN_ERR "cmipci: no UART401 device at 0x%lx\n", iomidi); } -- cgit v1.2.3 From d1bda0455478a9e2a13381044e9bb80a17ec92d2 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 14 Sep 2005 08:36:03 +0200 Subject: [ALSA] usb-audio: simplify MIDI quirk handling Modules: USB generic driver Simplify the handling of MIDI quirks by treating an interface without quirks as a QUIRK_MIDI_STANDARD_INTERFACE. This also fixes the bug where a MIDI_STANDARD quirk would not be recognized. Signed-off-by: Clemens Ladisch --- sound/usb/usbaudio.c | 24 +++++----------- sound/usb/usbmidi.c | 77 ++++++++++++++++++++++++++-------------------------- 2 files changed, 45 insertions(+), 56 deletions(-) diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 2ead878bcb8..ea1b1f87c1b 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -2755,9 +2755,9 @@ static int create_fixed_stream_quirk(snd_usb_audio_t *chip, /* * create a stream for an interface with proper descriptors */ -static int create_standard_interface_quirk(snd_usb_audio_t *chip, - struct usb_interface *iface, - const snd_usb_audio_quirk_t *quirk) +static int create_standard_audio_quirk(snd_usb_audio_t *chip, + struct usb_interface *iface, + const snd_usb_audio_quirk_t *quirk) { struct usb_host_interface *alts; struct usb_interface_descriptor *altsd; @@ -2765,24 +2765,14 @@ static int create_standard_interface_quirk(snd_usb_audio_t *chip, alts = &iface->altsetting[0]; altsd = get_iface_desc(alts); - switch (quirk->type) { - case QUIRK_AUDIO_STANDARD_INTERFACE: - err = parse_audio_endpoints(chip, altsd->bInterfaceNumber); - if (!err) - usb_set_interface(chip->dev, altsd->bInterfaceNumber, 0); /* reset the current interface */ - break; - case QUIRK_MIDI_STANDARD_INTERFACE: - err = snd_usb_create_midi_interface(chip, iface, NULL); - break; - default: - snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); - return -ENXIO; - } + err = parse_audio_endpoints(chip, altsd->bInterfaceNumber); if (err < 0) { snd_printk(KERN_ERR "cannot setup if %d: error %d\n", altsd->bInterfaceNumber, err); return err; } + /* reset the current interface */ + usb_set_interface(chip->dev, altsd->bInterfaceNumber, 0); return 0; } @@ -3044,7 +3034,7 @@ static int snd_usb_create_quirk(snd_usb_audio_t *chip, [QUIRK_MIDI_RAW] = snd_usb_create_midi_interface, [QUIRK_MIDI_EMAGIC] = snd_usb_create_midi_interface, [QUIRK_MIDI_MIDITECH] = snd_usb_create_midi_interface, - [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_interface_quirk, + [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, [QUIRK_AUDIO_EDIROL_UA700_UA25] = create_ua700_ua25_quirk, [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk, diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c index f1a2e2c2e02..32be9f99c02 100644 --- a/sound/usb/usbmidi.c +++ b/sound/usb/usbmidi.c @@ -1550,46 +1550,45 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip, /* detect the endpoint(s) to use */ memset(endpoints, 0, sizeof(endpoints)); - if (!quirk) { + switch (quirk ? quirk->type : QUIRK_MIDI_STANDARD_INTERFACE) { + case QUIRK_MIDI_STANDARD_INTERFACE: err = snd_usbmidi_get_ms_info(umidi, endpoints); - } else { - switch (quirk->type) { - case QUIRK_MIDI_FIXED_ENDPOINT: - memcpy(&endpoints[0], quirk->data, - sizeof(snd_usb_midi_endpoint_info_t)); - err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1); - break; - case QUIRK_MIDI_YAMAHA: - err = snd_usbmidi_detect_yamaha(umidi, &endpoints[0]); - break; - case QUIRK_MIDI_MIDIMAN: - umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops; - memcpy(&endpoints[0], quirk->data, - sizeof(snd_usb_midi_endpoint_info_t)); - err = 0; - break; - case QUIRK_MIDI_NOVATION: - umidi->usb_protocol_ops = &snd_usbmidi_novation_ops; - err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); - break; - case QUIRK_MIDI_RAW: - umidi->usb_protocol_ops = &snd_usbmidi_raw_ops; - err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); - break; - case QUIRK_MIDI_EMAGIC: - umidi->usb_protocol_ops = &snd_usbmidi_emagic_ops; - memcpy(&endpoints[0], quirk->data, - sizeof(snd_usb_midi_endpoint_info_t)); - err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1); - break; - case QUIRK_MIDI_MIDITECH: - err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); - break; - default: - snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); - err = -ENXIO; - break; - } + break; + case QUIRK_MIDI_FIXED_ENDPOINT: + memcpy(&endpoints[0], quirk->data, + sizeof(snd_usb_midi_endpoint_info_t)); + err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1); + break; + case QUIRK_MIDI_YAMAHA: + err = snd_usbmidi_detect_yamaha(umidi, &endpoints[0]); + break; + case QUIRK_MIDI_MIDIMAN: + umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops; + memcpy(&endpoints[0], quirk->data, + sizeof(snd_usb_midi_endpoint_info_t)); + err = 0; + break; + case QUIRK_MIDI_NOVATION: + umidi->usb_protocol_ops = &snd_usbmidi_novation_ops; + err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); + break; + case QUIRK_MIDI_RAW: + umidi->usb_protocol_ops = &snd_usbmidi_raw_ops; + err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); + break; + case QUIRK_MIDI_EMAGIC: + umidi->usb_protocol_ops = &snd_usbmidi_emagic_ops; + memcpy(&endpoints[0], quirk->data, + sizeof(snd_usb_midi_endpoint_info_t)); + err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1); + break; + case QUIRK_MIDI_MIDITECH: + err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); + break; + default: + snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); + err = -ENXIO; + break; } if (err < 0) { kfree(umidi); -- cgit v1.2.3 From dfedc5f47cfd672a57923506c71b2042b33ae306 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Fri, 16 Sep 2005 16:56:01 +0200 Subject: [ALSA] usb-audio: ignore Hercules DJ Console mixer errors Modules: USB generic driver Add a quirk entry for the Hercules DJ Console to ignore timeouts on some mixer control transfers. Signed-off-by: Clemens Ladisch --- sound/usb/usbmixer_maps.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/usb/usbmixer_maps.c b/sound/usb/usbmixer_maps.c index c1264434e50..9a8534b9eff 100644 --- a/sound/usb/usbmixer_maps.c +++ b/sound/usb/usbmixer_maps.c @@ -247,6 +247,11 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { .id = USB_ID(0x06f8, 0xd002), .ignore_ctl_error = 1, }, + { + /* Hercules DJ Console */ + .id = USB_ID(0x06f8, 0xd002), + .ignore_ctl_error = 1, + }, { .id = USB_ID(0x08bb, 0x2702), .map = linex_map, -- cgit v1.2.3 From a9430dd8fc232cfddcfaedde1a6a915e241366a8 Mon Sep 17 00:00:00 2001 From: Jonathan Woithe Date: Fri, 16 Sep 2005 19:12:48 +0200 Subject: [ALSA] hda-codec - A new model for Fujitsu S7020 Modules: HDA Codec driver Added a new model 'fujitsu' to ALC260 config for Fujitsu S7020. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 160 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 157 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 7327deb6df9..48356ab0457 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -57,6 +57,7 @@ enum { enum { ALC260_BASIC, ALC260_HP, + ALC260_FUJITSU_S702x, ALC260_MODEL_LAST /* last tag */ }; @@ -72,6 +73,7 @@ enum { #define PIN_VREF50 0x21 #define PIN_OUT 0x40 #define PIN_HP 0xc0 +#define PIN_HP_AMP 0x80 struct alc_spec { /* codec parameterization */ @@ -284,6 +286,54 @@ static int alc_bind_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u #define ALC_BIND_MUTE(xname,nid,indices,dir) ALC_BIND_MUTE_MONO(xname,nid,3,indices,dir) +/* + * Control of pin widget settings via the mixer. Only boolean settings are + * supported, so VrefEn can't be controlled using these functions as they + * stand. + */ +static int alc_pinctl_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +static int alc_pinctl_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + hda_nid_t nid = kcontrol->private_value & 0xffff; + long mask = (kcontrol->private_value >> 16) & 0xff; + long *valp = ucontrol->value.integer.value; + + *valp = 0; + if (snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00) & mask) + *valp = 1; + return 0; +} + +static int alc_pinctl_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + hda_nid_t nid = kcontrol->private_value & 0xffff; + long mask = (kcontrol->private_value >> 16) & 0xff; + long *valp = ucontrol->value.integer.value; + unsigned int pinctl = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00); + int change = ((pinctl & mask)!=0) != *valp; + + if (change) + snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL, + *valp?(pinctl|mask):(pinctl&~mask)); + return change; +} + +#define ALC_PINCTL_SWITCH(xname, nid, mask) \ + { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ + .info = alc_pinctl_switch_info, \ + .get = alc_pinctl_switch_get, \ + .put = alc_pinctl_switch_put, \ + .private_value = (nid) | (mask<<16) } /* * ALC880 3-stack model @@ -2205,6 +2255,17 @@ static struct hda_input_mux alc260_capture_source = { }, }; +/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack + * and the internal CD lines. + */ +static struct hda_input_mux alc260_fujitsu_capture_source = { + .num_items = 2, + .items = { + { "Mic/Line", 0x0 }, + { "CD", 0x4 }, + }, +}; + /* * This is just place-holder, so there's something for alc_build_pcms to look * at when it calculates the maximum number of channels. ALC260 has no mixer @@ -2271,6 +2332,30 @@ static snd_kcontrol_new_t alc260_hp_mixer[] = { { } /* end */ }; +static snd_kcontrol_new_t alc260_fujitsu_mixer[] = { + HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT), + ALC_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT), + ALC_PINCTL_SWITCH("Headphone Amp Switch", 0x14, PIN_HP_AMP), + HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), + HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), + HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), + HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), + HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT), + ALC_BIND_MUTE("Internal Speaker Playback Switch", 0x09, 2, HDA_INPUT), + HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Capture Source", + .info = alc_mux_enum_info, + .get = alc_mux_enum_get, + .put = alc_mux_enum_put, + }, + { } /* end */ +}; + static struct hda_verb alc260_init_verbs[] = { /* Line In pin widget for input */ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, @@ -2332,6 +2417,60 @@ static struct hda_verb alc260_init_verbs[] = { { } }; +/* Initialisation sequence for ALC260 as configured in Fujitsu S702x + * laptops. + */ +static struct hda_verb alc260_fujitsu_init_verbs[] = { + /* Disable all GPIOs */ + {0x01, AC_VERB_SET_GPIO_MASK, 0}, + /* Internal speaker is connected to headphone pin */ + {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + /* Headphone/Line-out jack connects to Line1 pin; make it an output */ + {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + /* Mic/Line-in jack is connected to mic1 pin, so make it an input */ + {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + /* Ensure all other unused pins are disabled and muted. + * Note: trying to set widget 0x15 to anything blocks all audio + * output for some reason, so just leave that at the default. + */ + {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, + {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, + {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, + {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + /* Disable digital (SPDIF) pins */ + {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0}, + {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0}, + + /* Start with mixer outputs muted */ + {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + + /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */ + {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + /* Unmute Line1 pin widget amp left and right (no equiv mixer ctrl) */ + {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + /* Unmute pin widget used for Line-in (no equiv mixer ctrl) */ + {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + + /* Mute capture amp left and right */ + {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + /* Set ADC connection select to line in (on mic1 pin) */ + {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, + + /* Mute all inputs to mixer widget (even unconnected ones) */ + {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ + {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ + {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ + {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ + {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ + {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ + {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ + {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ +}; + static struct hda_pcm_stream alc260_pcm_analog_playback = { .substreams = 1, .channels_min = 2, @@ -2347,6 +2486,8 @@ static struct hda_pcm_stream alc260_pcm_analog_capture = { static struct hda_board_config alc260_cfg_tbl[] = { { .modelname = "hp", .config = ALC260_HP }, { .pci_subvendor = 0x103c, .config = ALC260_HP }, + { .modelname = "fujitsu", .config = ALC260_FUJITSU_S702x }, + { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1326, .config = ALC260_FUJITSU_S702x }, {} }; @@ -2373,14 +2514,23 @@ static int patch_alc260(struct hda_codec *codec) spec->mixers[spec->num_mixers] = alc260_hp_mixer; spec->num_mixers++; break; + case ALC260_FUJITSU_S702x: + spec->mixers[spec->num_mixers] = alc260_fujitsu_mixer; + spec->num_mixers++; + break; default: spec->mixers[spec->num_mixers] = alc260_base_mixer; spec->num_mixers++; break; } - spec->init_verbs[0] = alc260_init_verbs; - spec->num_init_verbs = 1; + if (board_config != ALC260_FUJITSU_S702x) { + spec->init_verbs[0] = alc260_init_verbs; + spec->num_init_verbs = 1; + } else { + spec->init_verbs[0] = alc260_fujitsu_init_verbs; + spec->num_init_verbs = 1; + } spec->channel_mode = alc260_modes; spec->num_channel_mode = ARRAY_SIZE(alc260_modes); @@ -2393,7 +2543,11 @@ static int patch_alc260(struct hda_codec *codec) spec->multiout.num_dacs = ARRAY_SIZE(alc260_dac_nids); spec->multiout.dac_nids = alc260_dac_nids; - spec->input_mux = &alc260_capture_source; + if (board_config != ALC260_FUJITSU_S702x) { + spec->input_mux = &alc260_capture_source; + } else { + spec->input_mux = &alc260_fujitsu_capture_source; + } switch (board_config) { case ALC260_HP: spec->num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids); -- cgit v1.2.3 From 21be3d162651f11e422275aad62a4bb06292ef4f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 16 Sep 2005 19:18:56 +0200 Subject: [ALSA] Add description for ALC260 codec Modules: Documentation Added description for ALC260 codec models in hda-intel driver section. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 13cba955cb5..09340cb4e18 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -663,6 +663,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. adjusted. Appearing only when compiled with $CONFIG_SND_DEBUG=y + ALC260 + hp HP machines + fujitsu Fujitsu S7020 + CMI9880 minimal 3-jack in back min_fp 3-jack in back, 2-jack in front -- cgit v1.2.3 From f2b31737e509a70952421e7cca488a2001a3b087 Mon Sep 17 00:00:00 2001 From: Sasha Khapyorsky Date: Fri, 16 Sep 2005 19:22:44 +0200 Subject: [ALSA] au88x0: codec access procs for multiple AC97 codecs Modules: au88x0 driver This patch extends au88x0 AC97 codec access procedures to handle multiple codecs properly. Signed-off-by: Sasha Khapyorsky Signed-off-by: Takashi Iwai --- sound/pci/au88x0/au8810.h | 5 ----- sound/pci/au88x0/au8820.h | 5 ----- sound/pci/au88x0/au8830.h | 5 ----- sound/pci/au88x0/au88x0.h | 8 ++++++++ sound/pci/au88x0/au88x0_core.c | 6 ++++-- 5 files changed, 12 insertions(+), 17 deletions(-) diff --git a/sound/pci/au88x0/au8810.h b/sound/pci/au88x0/au8810.h index 3837d2ba5e6..5d69c31fe3f 100644 --- a/sound/pci/au88x0/au8810.h +++ b/sound/pci/au88x0/au8810.h @@ -178,11 +178,6 @@ #define EN_SPDIF 0x000c0000 #define VORTEX_CODEC_CHN 0x29080 -#define VORTEX_CODEC_WRITE 0x00800000 -#define VORTEX_CODEC_ADDSHIFT 16 -#define VORTEX_CODEC_ADDMASK 0x7f0000 /* 0x000f0000 */ -#define VORTEX_CODEC_DATSHIFT 0 -#define VORTEX_CODEC_DATMASK 0xffff #define VORTEX_CODEC_IO 0x29188 /* SPDIF */ diff --git a/sound/pci/au88x0/au8820.h b/sound/pci/au88x0/au8820.h index be8022e7871..abbe85e4f7a 100644 --- a/sound/pci/au88x0/au8820.h +++ b/sound/pci/au88x0/au8820.h @@ -162,11 +162,6 @@ #define EN_SPORT 0x00030000 #define EN_SPDIF 0x000c0000 #define VORTEX_CODEC_CHN 0x11880 -#define VORTEX_CODEC_WRITE 0x00800000 -#define VORTEX_CODEC_ADDSHIFT 16 -#define VORTEX_CODEC_ADDMASK 0x7f0000 /* 0x000f0000 */ -#define VORTEX_CODEC_DATSHIFT 0 -#define VORTEX_CODEC_DATMASK 0xffff #define VORTEX_CODEC_IO 0x11988 #define VORTEX_SPDIF_FLAGS 0x1005c /* FIXME */ diff --git a/sound/pci/au88x0/au8830.h b/sound/pci/au88x0/au8830.h index aa77826b5e5..04ece1b1c21 100644 --- a/sound/pci/au88x0/au8830.h +++ b/sound/pci/au88x0/au8830.h @@ -194,11 +194,6 @@ #define VORTEX_CODEC_CTRL 0x29184 #define VORTEX_CODEC_IO 0x29188 -#define VORTEX_CODEC_WRITE 0x00800000 -#define VORTEX_CODEC_ADDSHIFT 16 -#define VORTEX_CODEC_ADDMASK 0x7f0000 /* 0x000f0000 */ -#define VORTEX_CODEC_DATSHIFT 0 -#define VORTEX_CODEC_DATMASK 0xffff #define VORTEX_CODEC_SPORTCTRL 0x2918c diff --git a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h index ee1ede1979f..b1197cfab3f 100644 --- a/sound/pci/au88x0/au88x0.h +++ b/sound/pci/au88x0/au88x0.h @@ -79,6 +79,14 @@ #define VORTEX_RESOURCE_A3D 0x00000004 #define VORTEX_RESOURCE_LAST 0x00000005 +/* codec io: VORTEX_CODEC_IO bits */ +#define VORTEX_CODEC_ID_SHIFT 24 +#define VORTEX_CODEC_WRITE 0x00800000 +#define VORTEX_CODEC_ADDSHIFT 16 +#define VORTEX_CODEC_ADDMASK 0x7f0000 +#define VORTEX_CODEC_DATSHIFT 0 +#define VORTEX_CODEC_DATMASK 0xffff + /* Check for SDAC bit in "Extended audio ID" AC97 register */ //#define VORTEX_IS_QUAD(x) (((x)->codec == NULL) ? 0 : ((x)->codec->ext_id&0x80)) #define VORTEX_IS_QUAD(x) ((x)->isquad) diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c index f0eda4bbbb3..91ac4f3a2aa 100644 --- a/sound/pci/au88x0/au88x0_core.c +++ b/sound/pci/au88x0/au88x0_core.c @@ -2532,7 +2532,8 @@ vortex_codec_write(ac97_t * codec, unsigned short addr, unsigned short data) hwwrite(card->mmio, VORTEX_CODEC_IO, ((addr << VORTEX_CODEC_ADDSHIFT) & VORTEX_CODEC_ADDMASK) | ((data << VORTEX_CODEC_DATSHIFT) & VORTEX_CODEC_DATMASK) | - VORTEX_CODEC_WRITE); + VORTEX_CODEC_WRITE | + (codec->num << VORTEX_CODEC_ID_SHIFT) ); /* Flush Caches. */ hwread(card->mmio, VORTEX_CODEC_IO); @@ -2554,7 +2555,8 @@ static unsigned short vortex_codec_read(ac97_t * codec, unsigned short addr) } } /* set up read address */ - read_addr = ((addr << VORTEX_CODEC_ADDSHIFT) & VORTEX_CODEC_ADDMASK); + read_addr = ((addr << VORTEX_CODEC_ADDSHIFT) & VORTEX_CODEC_ADDMASK) | + (codec->num << VORTEX_CODEC_ID_SHIFT) ; hwwrite(card->mmio, VORTEX_CODEC_IO, read_addr); /* wait for address */ -- cgit v1.2.3 From d879f0ccf55a9ac5752b24dc210a446746e3c6da Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 21 Sep 2005 16:33:49 +0200 Subject: [ALSA] usb-audio: add quirk comments Modules: USB generic driver Add more comments about other device modes and unsupported devices to the Roland part of the quirks table. Signed-off-by: Clemens Ladisch --- sound/usb/usbquirks.h | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index 948759da656..ba506c3871f 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h @@ -294,6 +294,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + /* a later revision uses ID 0x0099 */ USB_DEVICE(0x0582, 0x0005), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", @@ -384,6 +385,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + /* a later revision uses ID 0x009d */ USB_DEVICE(0x0582, 0x0009), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", @@ -532,6 +534,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + /* has ID 0x0013 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0012), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", @@ -545,6 +548,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + /* has ID 0x0015 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0014), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", @@ -558,6 +562,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + /* has ID 0x0017 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0016), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", @@ -588,6 +593,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + /* has ID 0x001c when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x001b), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", @@ -618,6 +624,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + /* has ID 0x001e when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x001d), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", @@ -631,6 +638,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + /* has ID 0x0024 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0023), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", @@ -675,6 +683,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + /* has ID 0x0028 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0027), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", @@ -688,6 +697,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + /* has ID 0x002a when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0029), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", @@ -732,6 +742,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + /* has ID 0x002e when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x002d), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", @@ -745,6 +756,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + /* has ID 0x0030 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x002f), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", @@ -758,6 +770,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + /* has ID 0x0034 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0033), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", @@ -770,7 +783,12 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, + /* TODO: add Roland M-1000 support */ { + /* + * Has ID 0x0038 when not in "Advanced Driver" mode; + * later revisions use IDs 0x0054 and 0x00a2. + */ USB_DEVICE(0x0582, 0x0037), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", @@ -815,6 +833,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + /* has ID 0x0041 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0040), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", @@ -828,6 +847,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + /* has ID 0x0043 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0042), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", @@ -871,6 +891,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + /* has ID 0x004a when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0048), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", @@ -883,7 +904,9 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, + /* TODO: add Edirol M-100FX support */ { + /* has ID 0x004f when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x004d), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", @@ -931,7 +954,9 @@ YAMAHA_DEVICE(0x7010, "UB99"), .type = QUIRK_MIDI_STANDARD_INTERFACE } }, + /* TODO: add Roland EXR support */ { + /* has ID 0x0067 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0065), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", @@ -945,6 +970,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + /* has ID 0x006b when not in "Advanced Driver" mode */ USB_DEVICE_VENDOR_SPEC(0x0582, 0x006a), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", @@ -958,6 +984,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + /* has ID 0x006e when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x006d), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", @@ -1002,6 +1029,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + /* has ID 0x0076 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0075), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "BOSS", @@ -1015,10 +1043,11 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + /* has ID 0x007b when not in "Advanced Driver" mode */ USB_DEVICE_VENDOR_SPEC(0x0582, 0x007a), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", - /* RD-700SX, RD-300SX */ + /* "RD" or "RD-700SX"? */ .ifnum = 0, .type = QUIRK_MIDI_FIXED_ENDPOINT, .data = & (const snd_usb_midi_endpoint_info_t) { @@ -1048,6 +1077,15 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, + /* TODO: add Edirol UA-101 support */ + /* TODO: add Roland G-70 support */ + /* TODO: add Roland V-SYNTH XT support */ + /* TODO: add BOSS GT-PRO support */ + /* TODO: add Edirol PC-50 support */ + /* TODO: add Edirol PC-80 support */ + /* TODO: add Edirol UA-1EX support */ + /* TODO: add Edirol UM-3 support */ + /* TODO: add Edirol MD-P1 support */ /* Midiman/M-Audio devices */ { -- cgit v1.2.3 From 3cfc1eb181b49dfbfeaf20ebfeb5cd2af4c4c4b5 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 26 Sep 2005 10:01:12 +0200 Subject: [ALSA] usb-audio: remove old compatibility wrappers (1/2) Modules: USB generic driver Move the usb_pipe_needs_resubmit() compatibility wrapper out of the kernel tree. Signed-off-by: Clemens Ladisch --- sound/usb/usbaudio.h | 4 ---- sound/usb/usbmidi.c | 6 ++---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index ad9eab211d8..b58dc0ca7d3 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -249,10 +249,6 @@ void snd_usbmidi_disconnect(struct list_head *p); #define get_cfg_desc(cfg) (&(cfg)->desc) #endif -#ifndef usb_pipe_needs_resubmit -#define usb_pipe_needs_resubmit(pipe) 1 -#endif - #ifndef snd_usb_complete_callback #define snd_usb_complete_callback(x) (x) #endif diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c index 32be9f99c02..369319d672b 100644 --- a/sound/usb/usbmidi.c +++ b/sound/usb/usbmidi.c @@ -246,10 +246,8 @@ static void snd_usbmidi_in_urb_complete(struct urb* urb, struct pt_regs *regs) } } - if (usb_pipe_needs_resubmit(urb->pipe)) { - urb->dev = ep->umidi->chip->dev; - snd_usbmidi_submit_urb(urb, GFP_ATOMIC); - } + urb->dev = ep->umidi->chip->dev; + snd_usbmidi_submit_urb(urb, GFP_ATOMIC); } static void snd_usbmidi_out_urb_complete(struct urb* urb, struct pt_regs *regs) -- cgit v1.2.3 From 3527a008cbc51dd23a8bf4927e3ab29423b0d05b Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 26 Sep 2005 10:03:09 +0200 Subject: [ALSA] usb-audio: remove old compatibility wrappers (2/2) Modules: USB generic driver Move the usb_complete_callback() compatibility wrapper out of the kernel tree. Signed-off-by: Clemens Ladisch --- sound/usb/usbaudio.c | 4 ++-- sound/usb/usbaudio.h | 4 ---- sound/usb/usbmidi.c | 14 ++++++-------- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index ea1b1f87c1b..5429b169877 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -1044,7 +1044,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; u->urb->interval = 1 << subs->datainterval; u->urb->context = u; - u->urb->complete = snd_usb_complete_callback(snd_complete_urb); + u->urb->complete = snd_complete_urb; } if (subs->syncpipe) { @@ -1070,7 +1070,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by u->urb->number_of_packets = 1; u->urb->interval = 1 << subs->syncinterval; u->urb->context = u; - u->urb->complete = snd_usb_complete_callback(snd_complete_sync_urb); + u->urb->complete = snd_complete_sync_urb; } } return 0; diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index b58dc0ca7d3..b5802022bb1 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -249,10 +249,6 @@ void snd_usbmidi_disconnect(struct list_head *p); #define get_cfg_desc(cfg) (&(cfg)->desc) #endif -#ifndef snd_usb_complete_callback -#define snd_usb_complete_callback(x) (x) -#endif - #ifndef snd_usb_get_speed #define snd_usb_get_speed(dev) ((dev)->speed) #endif diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c index 369319d672b..2885b8974da 100644 --- a/sound/usb/usbmidi.c +++ b/sound/usb/usbmidi.c @@ -861,13 +861,12 @@ static int snd_usbmidi_in_endpoint_create(snd_usb_midi_t* umidi, return -ENOMEM; } if (ep_info->in_interval) - usb_fill_int_urb(ep->urb, umidi->chip->dev, pipe, buffer, length, - snd_usb_complete_callback(snd_usbmidi_in_urb_complete), - ep, ep_info->in_interval); + usb_fill_int_urb(ep->urb, umidi->chip->dev, pipe, buffer, + length, snd_usbmidi_in_urb_complete, ep, + ep_info->in_interval); else - usb_fill_bulk_urb(ep->urb, umidi->chip->dev, pipe, buffer, length, - snd_usb_complete_callback(snd_usbmidi_in_urb_complete), - ep); + usb_fill_bulk_urb(ep->urb, umidi->chip->dev, pipe, buffer, + length, snd_usbmidi_in_urb_complete, ep); ep->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; rep->in = ep; @@ -931,8 +930,7 @@ static int snd_usbmidi_out_endpoint_create(snd_usb_midi_t* umidi, return -ENOMEM; } usb_fill_bulk_urb(ep->urb, umidi->chip->dev, pipe, buffer, - ep->max_transfer, - snd_usb_complete_callback(snd_usbmidi_out_urb_complete), ep); + ep->max_transfer, snd_usbmidi_out_urb_complete, ep); ep->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; spin_lock_init(&ep->buffer_lock); -- cgit v1.2.3 From adf25df1be2e3843f786a2562202c7897bbd149d Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Tue, 27 Sep 2005 15:56:28 +0200 Subject: [ALSA] rtctimer: remove superfluous rtc_inc variable Modules: RTC timer driver The rtc_inc variable is never used outside the interrupt handler, and is always one where it matters, so we can just remove it. Signed-off-by: Clemens Ladisch --- sound/core/rtctimer.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/sound/core/rtctimer.c b/sound/core/rtctimer.c index bd5d584d284..85627dbe6a5 100644 --- a/sound/core/rtctimer.c +++ b/sound/core/rtctimer.c @@ -60,7 +60,6 @@ static struct _snd_timer_hardware rtc_hw = { static int rtctimer_freq = RTC_FREQ; /* frequency */ static snd_timer_t *rtctimer; -static atomic_t rtc_inc = ATOMIC_INIT(0); static rtc_task_t rtc_task; @@ -94,7 +93,6 @@ rtctimer_start(snd_timer_t *timer) snd_assert(rtc != NULL, return -EINVAL); rtc_control(rtc, RTC_IRQP_SET, rtctimer_freq); rtc_control(rtc, RTC_PIE_ON, 0); - atomic_set(&rtc_inc, 0); return 0; } @@ -112,12 +110,7 @@ rtctimer_stop(snd_timer_t *timer) */ static void rtctimer_interrupt(void *private_data) { - int ticks; - - atomic_inc(&rtc_inc); - ticks = atomic_read(&rtc_inc); - snd_timer_interrupt((snd_timer_t*)private_data, ticks); - atomic_sub(ticks, &rtc_inc); + snd_timer_interrupt(private_data, 1); } -- cgit v1.2.3 From d9ad1bdd6d72606a59cdc07e571fbe695e32f271 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Tue, 27 Sep 2005 15:57:24 +0200 Subject: [ALSA] rtctimer: optimize module parameter validation Modules: RTC timer driver The check whether rtctimer_freq is a power of two can be done easier with a simple bit operation. Signed-off-by: Clemens Ladisch --- sound/core/rtctimer.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/sound/core/rtctimer.c b/sound/core/rtctimer.c index 85627dbe6a5..8762ff8938c 100644 --- a/sound/core/rtctimer.c +++ b/sound/core/rtctimer.c @@ -119,16 +119,11 @@ static void rtctimer_interrupt(void *private_data) */ static int __init rtctimer_init(void) { - int order, err; + int err; snd_timer_t *timer; - if (rtctimer_freq < 2 || rtctimer_freq > 8192) { - snd_printk(KERN_ERR "rtctimer: invalid frequency %d\n", rtctimer_freq); - return -EINVAL; - } - for (order = 1; rtctimer_freq > order; order <<= 1) - ; - if (rtctimer_freq != order) { + if (rtctimer_freq < 2 || rtctimer_freq > 8192 || + (rtctimer_freq & (rtctimer_freq - 1)) != 0) { snd_printk(KERN_ERR "rtctimer: invalid frequency %d\n", rtctimer_freq); return -EINVAL; } -- cgit v1.2.3 From bf3b644039d6a99076f5a87c714d94dfea3a6814 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 28 Sep 2005 08:18:17 +0200 Subject: [ALSA] sequencer: remove superfluous function parameter Modules: ALSA sequencer Remove the last parameter of snd_seq_timer_set_tick_resolution() because it is always one. Signed-off-by: Clemens Ladisch --- sound/core/seq/seq_timer.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c index b57a3c07ff6..9c87d9f8ba9 100644 --- a/sound/core/seq/seq_timer.c +++ b/sound/core/seq/seq_timer.c @@ -37,7 +37,7 @@ extern int seq_default_timer_resolution; #define SKEW_BASE 0x10000 /* 16bit shift */ static void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick, - int tempo, int ppq, int nticks) + int tempo, int ppq) { if (tempo < 1000000) tick->resolution = (tempo * 1000) / ppq; @@ -51,7 +51,6 @@ static void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick, } if (tick->resolution <= 0) tick->resolution = 1; - tick->resolution *= nticks; snd_seq_timer_update_tick(tick, 0); } @@ -100,7 +99,7 @@ void snd_seq_timer_defaults(seq_timer_t * tmr) /* setup defaults */ tmr->ppq = 96; /* 96 PPQ */ tmr->tempo = 500000; /* 120 BPM */ - snd_seq_timer_set_tick_resolution(&tmr->tick, tmr->tempo, tmr->ppq, 1); + snd_seq_timer_set_tick_resolution(&tmr->tick, tmr->tempo, tmr->ppq); tmr->running = 0; tmr->type = SNDRV_SEQ_TIMER_ALSA; @@ -183,7 +182,7 @@ int snd_seq_timer_set_tempo(seq_timer_t * tmr, int tempo) spin_lock_irqsave(&tmr->lock, flags); if ((unsigned int)tempo != tmr->tempo) { tmr->tempo = tempo; - snd_seq_timer_set_tick_resolution(&tmr->tick, tmr->tempo, tmr->ppq, 1); + snd_seq_timer_set_tick_resolution(&tmr->tick, tmr->tempo, tmr->ppq); } spin_unlock_irqrestore(&tmr->lock, flags); return 0; @@ -207,7 +206,7 @@ int snd_seq_timer_set_ppq(seq_timer_t * tmr, int ppq) } tmr->ppq = ppq; - snd_seq_timer_set_tick_resolution(&tmr->tick, tmr->tempo, tmr->ppq, 1); + snd_seq_timer_set_tick_resolution(&tmr->tick, tmr->tempo, tmr->ppq); spin_unlock_irqrestore(&tmr->lock, flags); return 0; } -- cgit v1.2.3 From d602c885a6c30c78197b752c9241ce7e86cdf704 Mon Sep 17 00:00:00 2001 From: Glen Masgai Date: Wed, 28 Sep 2005 08:19:05 +0200 Subject: [ALSA] ymfpci: add S/PDIF-in > S/PDIF-out loop Modules: YMFPCI driver This patch adds a new mixer control called 'IEC958 Loop' which makes it possible to loop digital signals from S/PDIF-in to S/PDIF-out. Signed-off-by: Glen Masgai Signed-off-by: Clemens Ladisch --- sound/pci/ymfpci/ymfpci_main.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 27fa523639a..2e671ee438c 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -1421,15 +1421,18 @@ static snd_kcontrol_new_t snd_ymfpci_drec_source __devinitdata = { * Mixer controls */ -#define YMFPCI_SINGLE(xname, xindex, reg) \ +#define YMFPCI_SINGLE(xname, xindex, reg, shift) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ .info = snd_ymfpci_info_single, \ .get = snd_ymfpci_get_single, .put = snd_ymfpci_put_single, \ - .private_value = reg } + .private_value = ((reg) | ((shift) << 16)) } -static int snd_ymfpci_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) +static int snd_ymfpci_info_single(snd_kcontrol_t *kcontrol, + snd_ctl_elem_info_t *uinfo) { - switch (kcontrol->private_value) { + int reg = kcontrol->private_value & 0xffff; + + switch (reg) { case YDSXGR_SPDIFOUTCTRL: break; case YDSXGR_SPDIFINCTRL: break; default: return -EINVAL; @@ -1441,30 +1444,35 @@ static int snd_ymfpci_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t return 0; } -static int snd_ymfpci_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_ymfpci_get_single(snd_kcontrol_t *kcontrol, + snd_ctl_elem_value_t *ucontrol) { ymfpci_t *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value; - unsigned int shift = 0, mask = 1; + int reg = kcontrol->private_value & 0xffff; + unsigned int shift = (kcontrol->private_value >> 16) & 0xff; + unsigned int mask = 1; - switch (kcontrol->private_value) { + switch (reg) { case YDSXGR_SPDIFOUTCTRL: break; case YDSXGR_SPDIFINCTRL: break; default: return -EINVAL; } - ucontrol->value.integer.value[0] = (snd_ymfpci_readl(chip, reg) >> shift) & mask; + ucontrol->value.integer.value[0] = + (snd_ymfpci_readl(chip, reg) >> shift) & mask; return 0; } -static int snd_ymfpci_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_ymfpci_put_single(snd_kcontrol_t *kcontrol, + snd_ctl_elem_value_t *ucontrol) { ymfpci_t *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value; - unsigned int shift = 0, mask = 1; + int reg = kcontrol->private_value & 0xffff; + unsigned int shift = (kcontrol->private_value >> 16) & 0xff; + unsigned int mask = 1; int change; unsigned int val, oval; - switch (kcontrol->private_value) { + switch (reg) { case YDSXGR_SPDIFOUTCTRL: break; case YDSXGR_SPDIFINCTRL: break; default: return -EINVAL; @@ -1583,8 +1591,9 @@ YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("AC97 ", PLAYBACK,VOLUME), 0, YDSXGR_ZVOUTVO YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("", CAPTURE,VOLUME), 0, YDSXGR_ZVLOOPVOL), YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("AC97 ",PLAYBACK,VOLUME), 1, YDSXGR_SPDIFOUTVOL), YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,VOLUME), 1, YDSXGR_SPDIFLOOPVOL), -YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), 0, YDSXGR_SPDIFOUTCTRL), -YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0, YDSXGR_SPDIFINCTRL), +YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), 0, YDSXGR_SPDIFOUTCTRL, 0), +YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0, YDSXGR_SPDIFINCTRL, 0), +YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("Loop",NONE,NONE), 0, YDSXGR_SPDIFINCTRL, 4), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "4ch Duplication", -- cgit v1.2.3 From 6632d198c6643294319a4ca3f614539dc1ad37a8 Mon Sep 17 00:00:00 2001 From: Sasha Khapyorsky Date: Thu, 29 Sep 2005 11:48:17 +0200 Subject: [ALSA] dev_class=SNDRV_PCM_CLASS_MODEM for modem PCMs dev_class=SNDRV_PCM_CLASS_MODEM for all supported softmodem PCMs Signed-off-by: Sasha Khapyorsky Signed-off-by: Takashi Iwai --- sound/pci/ali5451/ali5451.c | 5 +++-- sound/pci/atiixp_modem.c | 1 + sound/pci/hda/hda_intel.c | 1 + sound/pci/intel8x0m.c | 1 + sound/pci/via82xx_modem.c | 1 + 5 files changed, 7 insertions(+), 2 deletions(-) diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index f35b558c29b..01d971c89e4 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -1795,6 +1795,7 @@ struct ali_pcm_description { unsigned int capture_num; snd_pcm_ops_t *playback_ops; snd_pcm_ops_t *capture_ops; + unsigned short class; }; @@ -1818,7 +1819,6 @@ static int __devinit snd_ali_pcm(ali_t * codec, int device, struct ali_pcm_descr } pcm->private_data = codec; pcm->private_free = snd_ali_pcm_free; - pcm->info_flags = 0; if (desc->playback_ops) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, desc->playback_ops); if (desc->capture_ops) @@ -1828,6 +1828,7 @@ static int __devinit snd_ali_pcm(ali_t * codec, int device, struct ali_pcm_descr snd_dma_pci_data(codec->pci), 64*1024, 128*1024); pcm->info_flags = 0; + pcm->dev_class = desc->class; pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; strcpy(pcm->name, desc->name); codec->pcm[0] = pcm; @@ -1836,7 +1837,7 @@ static int __devinit snd_ali_pcm(ali_t * codec, int device, struct ali_pcm_descr static struct ali_pcm_description ali_pcms[] = { { "ALI 5451", ALI_CHANNELS, 1, &snd_ali_playback_ops, &snd_ali_capture_ops }, - { "ALI 5451 modem", 1, 1, &snd_ali_modem_playback_ops, &snd_ali_modem_capture_ops } + { "ALI 5451 modem", 1, 1, &snd_ali_modem_playback_ops, &snd_ali_modem_capture_ops, SNDRV_PCM_CLASS_MODEM } }; static int __devinit snd_ali_build_pcms(ali_t *codec) diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index c1a239a4dac..c020c53a0cd 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -989,6 +989,7 @@ static int __devinit snd_atiixp_pcm_new(atiixp_t *chip) return err; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_atiixp_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_atiixp_capture_ops); + pcm->dev_class = SNDRV_PCM_CLASS_MODEM; pcm->private_data = chip; strcpy(pcm->name, "ATI IXP MC97"); chip->pcmdevs[ATI_PCMDEV_ANALOG] = pcm; diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 2c5d4114771..faf9dd00ba6 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1277,6 +1277,7 @@ static int __devinit azx_pcm_create(azx_t *chip) err = create_codec_pcm(chip, codec, &codec->pcm_info[c], pcm_dev); if (err < 0) return err; + chip->pcm[pcm_dev]->dev_class = SNDRV_PCM_CLASS_MODEM; pcm_dev++; } } diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 9e2060d56c2..2ac1fec5059 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -746,6 +746,7 @@ static int __devinit snd_intel8x0_pcm1(intel8x0_t *chip, int device, struct ich_ pcm->private_data = chip; pcm->info_flags = 0; + pcm->dev_class = SNDRV_PCM_CLASS_MODEM; if (rec->suffix) sprintf(pcm->name, "%s - %s", chip->card->shortname, rec->suffix); else diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 7eac6f6ac73..034dc1c6262 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -832,6 +832,7 @@ static int __devinit snd_via686_pcm_new(via82xx_t *chip) return err; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_via686_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_via686_capture_ops); + pcm->dev_class = SNDRV_PCM_CLASS_MODEM; pcm->private_data = chip; strcpy(pcm->name, chip->card->shortname); chip->pcms[0] = pcm; -- cgit v1.2.3 From 2ba71978c04d4dba983b4fc658f82eae164c2bca Mon Sep 17 00:00:00 2001 From: Sasha Khapyorsky Date: Thu, 29 Sep 2005 12:58:24 +0200 Subject: [ALSA] Removing obsolete AC97_SHARED_TYPES This patch cleans last ac97 audio/modem codec interception in initialization procedures (ac97_mixer_new()) and removes obsolete SHARED_TYPE 'locking' which prevents from AMC codecs to function correctly. Signed-off-by: Sasha Khapyorsky Signed-off-by: Takashi Iwai --- include/sound/ac97_codec.h | 10 ---------- sound/pci/ac97/ac97_codec.c | 38 ++------------------------------------ sound/pci/atiixp.c | 1 - sound/pci/atiixp_modem.c | 1 - sound/pci/intel8x0.c | 1 - sound/pci/intel8x0m.c | 1 - sound/pci/via82xx.c | 2 +- sound/pci/via82xx_modem.c | 1 - 8 files changed, 3 insertions(+), 52 deletions(-) diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h index d11f34832a9..7f0ca79d6c9 100644 --- a/include/sound/ac97_codec.h +++ b/include/sound/ac97_codec.h @@ -387,15 +387,6 @@ #define AC97_RATES_MIC_ADC 4 #define AC97_RATES_SPDIF 5 -/* shared controllers */ -enum { - AC97_SHARED_TYPE_NONE, - AC97_SHARED_TYPE_ICH, - AC97_SHARED_TYPE_ATIIXP, - AC97_SHARED_TYPE_VIA, - AC97_SHARED_TYPES -}; - /* * */ @@ -468,7 +459,6 @@ struct _snd_ac97_bus { unsigned short used_slots[2][4]; /* actually used PCM slots */ unsigned short pcms_count; /* count of PCMs */ struct ac97_pcm *pcms; - unsigned int shared_type; /* type of shared controller betwen audio and modem */ ac97_t *codec[4]; snd_info_entry_t *proc; }; diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 41fc290149e..56549add80a 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -220,12 +220,6 @@ const char *snd_ac97_stereo_enhancements[] = /* 31 */ "Reserved 31" }; -/* - * Shared AC97 controllers (ICH, ATIIXP...) - */ -static DECLARE_MUTEX(shared_codec_mutex); -static ac97_t *shared_codec[AC97_SHARED_TYPES][4]; - /* * I/O routines @@ -996,14 +990,8 @@ static int snd_ac97_free(ac97_t *ac97) { if (ac97) { snd_ac97_proc_done(ac97); - if (ac97->bus) { + if (ac97->bus) ac97->bus->codec[ac97->num] = NULL; - if (ac97->bus->shared_type) { - down(&shared_codec_mutex); - shared_codec[ac97->bus->shared_type-1][ac97->num] = NULL; - up(&shared_codec_mutex); - } - } if (ac97->private_free) ac97->private_free(ac97); kfree(ac97); @@ -1889,21 +1877,6 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) snd_assert(bus != NULL && template != NULL, return -EINVAL); snd_assert(template->num < 4 && bus->codec[template->num] == NULL, return -EINVAL); - snd_assert(bus->shared_type <= AC97_SHARED_TYPES, return -EINVAL); - if (bus->shared_type) { - /* already shared? */ - down(&shared_codec_mutex); - ac97 = shared_codec[bus->shared_type-1][template->num]; - if (ac97) { - if ((ac97_is_audio(ac97) && (template->scaps & AC97_SCAP_SKIP_AUDIO)) || - (ac97_is_modem(ac97) && (template->scaps & AC97_SCAP_SKIP_MODEM))) { - up(&shared_codec_mutex); - return -EACCES; /* skip this */ - } - } - up(&shared_codec_mutex); - } - card = bus->card; ac97 = kzalloc(sizeof(*ac97), GFP_KERNEL); if (ac97 == NULL) @@ -2153,7 +2126,7 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) } } /* make sure the proper powerdown bits are cleared */ - if (ac97->scaps) { + if (ac97->scaps && ac97_is_audio(ac97)) { reg = snd_ac97_read(ac97, AC97_EXTENDED_STATUS); if (ac97->scaps & AC97_SCAP_SURROUND_DAC) reg &= ~AC97_EA_PRJ; @@ -2167,13 +2140,6 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) return err; } *rac97 = ac97; - - if (bus->shared_type) { - down(&shared_codec_mutex); - shared_codec[bus->shared_type-1][ac97->num] = ac97; - up(&shared_codec_mutex); - } - return 0; } diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 241eacf1e65..cb1741102bb 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -1372,7 +1372,6 @@ static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock, const char if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0) return err; pbus->clock = clock; - pbus->shared_type = AC97_SHARED_TYPE_ATIIXP; /* shared with modem driver */ chip->ac97_bus = pbus; codec_count = 0; diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index c020c53a0cd..a88a6f37205 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -1068,7 +1068,6 @@ static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock) if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0) return err; pbus->clock = clock; - pbus->shared_type = AC97_SHARED_TYPE_ATIIXP; /* shared with audio driver */ chip->ac97_bus = pbus; codec_count = 0; diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 1a96198a17a..0d11cf7d569 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -2022,7 +2022,6 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock, const if ((err = snd_ac97_bus(chip->card, 0, ops, chip, &pbus)) < 0) goto __err; pbus->private_free = snd_intel8x0_mixer_free_ac97_bus; - pbus->shared_type = AC97_SHARED_TYPE_ICH; /* shared with modem driver */ if (ac97_clock >= 8000 && ac97_clock <= 48000) pbus->clock = ac97_clock; /* FIXME: my test board doesn't work well with VRA... */ diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 2ac1fec5059..15364d27804 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -855,7 +855,6 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock) if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0) goto __err; pbus->private_free = snd_intel8x0_mixer_free_ac97_bus; - pbus->shared_type = AC97_SHARED_TYPE_ICH; /* shared with audio driver */ if (ac97_clock >= 8000 && ac97_clock <= 48000) pbus->clock = ac97_clock; chip->ac97_bus = pbus; diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 3c0205b91e1..ecc4836ba8d 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -1616,12 +1616,12 @@ static int __devinit snd_via82xx_mixer_new(via82xx_t *chip, const char *quirk_ov return err; chip->ac97_bus->private_free = snd_via82xx_mixer_free_ac97_bus; chip->ac97_bus->clock = chip->ac97_clock; - chip->ac97_bus->shared_type = AC97_SHARED_TYPE_VIA; memset(&ac97, 0, sizeof(ac97)); ac97.private_data = chip; ac97.private_free = snd_via82xx_mixer_free_ac97; ac97.pci = chip->pci; + ac97.scaps = AC97_SCAP_SKIP_MODEM; if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0) return err; diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 034dc1c6262..c3ab8fbf582 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -879,7 +879,6 @@ static int __devinit snd_via82xx_mixer_new(via82xx_t *chip) return err; chip->ac97_bus->private_free = snd_via82xx_mixer_free_ac97_bus; chip->ac97_bus->clock = chip->ac97_clock; - chip->ac97_bus->shared_type = AC97_SHARED_TYPE_VIA; memset(&ac97, 0, sizeof(ac97)); ac97.private_data = chip; -- cgit v1.2.3 From 4b0940f8117b6cdf7e7c27bdecc29931f18c81ed Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 30 Sep 2005 16:55:14 +0200 Subject: [ALSA] sound: align device drivers menus Modules: Sound Core,PCI drivers AC97 Kconfig entries broke the ALSA device drivers menu, so move them to a location where that won't happen, enabling all device sub-menus to be presented together. Signed-off-by: Randy Dunlap Signed-off-by: Takashi Iwai --- sound/Kconfig | 8 ++++++++ sound/pci/Kconfig | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/Kconfig b/sound/Kconfig index b65ee4701f9..d8f11408ce2 100644 --- a/sound/Kconfig +++ b/sound/Kconfig @@ -48,6 +48,14 @@ config SND For more information, see +config SND_AC97_CODEC + tristate + select SND_PCM + select SND_AC97_BUS + +config SND_AC97_BUS + tristate + source "sound/core/Kconfig" source "sound/drivers/Kconfig" diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index a5d593c66f9..d140e93d37b 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig @@ -1,13 +1,5 @@ # ALSA PCI drivers -config SND_AC97_CODEC - tristate - select SND_PCM - select SND_AC97_BUS - -config SND_AC97_BUS - tristate - menu "PCI devices" depends on SND!=n && PCI -- cgit v1.2.3 From b7fe46220487f684abc858865cff817389af5c76 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Tue, 4 Oct 2005 08:46:51 +0200 Subject: [ALSA] highlanderize motherboard AC97/HDA drivers Remove the code for supporting eight cards from the integrated controller drivers because There Can Be Only One controller of each type per mainboard. Signed-off-by: Clemens Ladisch --- Documentation/sound/alsa/ALSA-Configuration.txt | 14 ++-- sound/pci/atiixp.c | 42 ++++------ sound/pci/atiixp_modem.c | 28 ++----- sound/pci/hda/hda_intel.c | 34 +++----- sound/pci/intel8x0.c | 58 +++++-------- sound/pci/intel8x0m.c | 28 ++----- sound/pci/via82xx.c | 103 +++++++++++------------- sound/pci/via82xx_modem.c | 29 +++---- 8 files changed, 126 insertions(+), 210 deletions(-) diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 09340cb4e18..46a125003b0 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -206,7 +206,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. See "AC97 Quirk Option" section below. spdif_aclink - S/PDIF transfer over AC-link (default = 1) - This module supports up to 8 cards and autoprobe. + This module supports one card and autoprobe. ATI IXP has two different methods to control SPDIF output. One is over AC-link and another is over the "direct" SPDIF output. The @@ -218,7 +218,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. Module for ATI IXP 150/200/250 AC97 modem controllers. - Module supports up to 8 cards. + This module supports one card and autoprobe. Note: The default index value of this module is -2, i.e. the first slot is excluded. @@ -637,7 +637,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. model - force the model name position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size) - Module supports up to 8 cards. + This module supports one card and autoprobe. Each codec may have a model table for different configurations. If your machine isn't listed there, the default (usually minimal) @@ -815,7 +815,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. semaphores (e.g. on some ASUS laptops) (default off) - Module supports autoprobe and multiple bus-master chips (max 8). + This module supports one chip and autoprobe. Note: the latest driver supports auto-detection of chip clock. if you still encounter too fast playback, specify the clock @@ -834,7 +834,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ac97_clock - AC'97 codec clock base (0 = auto-detect) - This module supports up to 8 cards and autoprobe. + This module supports one card and autoprobe. Note: The default index value of this module is -2, i.e. the first slot is excluded. @@ -1314,7 +1314,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ac97_quirk - AC'97 workaround for strange hardware See "AC97 Quirk Option" section below. - Module supports autoprobe and multiple bus-master chips (max 8). + This module supports one chip and autoprobe. Note: on some SMP motherboards like MSI 694D the interrupts might not be generated properly. In such a case, please try to @@ -1356,7 +1356,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ac97_clock - AC'97 codec clock base (default 48000Hz) - Module supports up to 8 cards. + This module supports one card and autoprobe. Note: The default index value of this module is -2, i.e. the first slot is excluded. diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index cb1741102bb..332a71de967 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -39,24 +39,21 @@ MODULE_DESCRIPTION("ATI IXP AC97 controller"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{ATI,IXP150/200/250/300/400}}"); -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 48000}; -static char *ac97_quirk[SNDRV_CARDS]; -static int spdif_aclink[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; - -module_param_array(index, int, NULL, 0444); +static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ +static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ +static int ac97_clock = 48000; +static char *ac97_quirk; +static int spdif_aclink = 1; + +module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for ATI IXP controller."); -module_param_array(id, charp, NULL, 0444); +module_param(id, charp, 0444); MODULE_PARM_DESC(id, "ID string for ATI IXP controller."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable audio part of ATI IXP controller."); -module_param_array(ac97_clock, int, NULL, 0444); +module_param(ac97_clock, int, 0444); MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz)."); -module_param_array(ac97_quirk, charp, NULL, 0444); +module_param(ac97_quirk, charp, 0444); MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); -module_param_array(spdif_aclink, bool, NULL, 0444); +module_param(spdif_aclink, bool, 0444); MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link."); @@ -1578,26 +1575,18 @@ static int __devinit snd_atiixp_create(snd_card_t *card, static int __devinit snd_atiixp_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { - static int dev; snd_card_t *card; atiixp_t *chip; unsigned char revision; int err; - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); + card = snd_card_new(index, id, THIS_MODULE, 0); if (card == NULL) return -ENOMEM; pci_read_config_byte(pci, PCI_REVISION_ID, &revision); - strcpy(card->driver, spdif_aclink[dev] ? "ATIIXP" : "ATIIXP-SPDMA"); + strcpy(card->driver, spdif_aclink ? "ATIIXP" : "ATIIXP-SPDMA"); strcpy(card->shortname, "ATI IXP"); if ((err = snd_atiixp_create(card, pci, &chip)) < 0) goto __error; @@ -1605,9 +1594,9 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci, if ((err = snd_atiixp_aclink_reset(chip)) < 0) goto __error; - chip->spdif_over_aclink = spdif_aclink[dev]; + chip->spdif_over_aclink = spdif_aclink; - if ((err = snd_atiixp_mixer_new(chip, ac97_clock[dev], ac97_quirk[dev])) < 0) + if ((err = snd_atiixp_mixer_new(chip, ac97_clock, ac97_quirk)) < 0) goto __error; if ((err = snd_atiixp_pcm_new(chip)) < 0) @@ -1628,7 +1617,6 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci, goto __error; pci_set_drvdata(pci, card); - dev++; return 0; __error: diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index a88a6f37205..a4778d373cd 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -39,18 +39,15 @@ MODULE_DESCRIPTION("ATI IXP MC97 controller"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{ATI,IXP150/200/250}}"); -static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 48000}; +static int index = -2; /* Exclude the first card */ +static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ +static int ac97_clock = 48000; -module_param_array(index, int, NULL, 0444); +module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for ATI IXP controller."); -module_param_array(id, charp, NULL, 0444); +module_param(id, charp, 0444); MODULE_PARM_DESC(id, "ID string for ATI IXP controller."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable audio part of ATI IXP controller."); -module_param_array(ac97_clock, int, NULL, 0444); +module_param(ac97_clock, int, 0444); MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz)."); @@ -1256,20 +1253,12 @@ static int __devinit snd_atiixp_create(snd_card_t *card, static int __devinit snd_atiixp_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { - static int dev; snd_card_t *card; atiixp_t *chip; unsigned char revision; int err; - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); + card = snd_card_new(index, id, THIS_MODULE, 0); if (card == NULL) return -ENOMEM; @@ -1283,7 +1272,7 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci, if ((err = snd_atiixp_aclink_reset(chip)) < 0) goto __error; - if ((err = snd_atiixp_mixer_new(chip, ac97_clock[dev])) < 0) + if ((err = snd_atiixp_mixer_new(chip, ac97_clock)) < 0) goto __error; if ((err = snd_atiixp_pcm_new(chip)) < 0) @@ -1302,7 +1291,6 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci, goto __error; pci_set_drvdata(pci, card); - dev++; return 0; __error: diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index faf9dd00ba6..d9e88dfe817 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -47,21 +47,18 @@ #include "hda_codec.h" -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static char *model[SNDRV_CARDS]; -static int position_fix[SNDRV_CARDS]; +static int index = SNDRV_DEFAULT_IDX1; +static char *id = SNDRV_DEFAULT_STR1; +static char *model; +static int position_fix; -module_param_array(index, int, NULL, 0444); +module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); -module_param_array(id, charp, NULL, 0444); +module_param(id, charp, 0444); MODULE_PARM_DESC(id, "ID string for Intel HD audio interface."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Intel HD audio interface."); -module_param_array(model, charp, NULL, 0444); +module_param(model, charp, 0444); MODULE_PARM_DESC(model, "Use the given board model."); -module_param_array(position_fix, int, NULL, 0444); +module_param(position_fix, int, 0444); MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)."); MODULE_LICENSE("GPL"); @@ -1544,32 +1541,24 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { - static int dev; snd_card_t *card; azx_t *chip; int err = 0; - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (! enable[dev]) { - dev++; - return -ENOENT; - } - - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); + card = snd_card_new(index, id, THIS_MODULE, 0); if (NULL == card) { snd_printk(KERN_ERR SFX "Error creating card!\n"); return -ENOMEM; } - if ((err = azx_create(card, pci, position_fix[dev], pci_id->driver_data, + if ((err = azx_create(card, pci, position_fix, pci_id->driver_data, &chip)) < 0) { snd_card_free(card); return err; } /* create codec instances */ - if ((err = azx_codec_create(chip, model[dev])) < 0) { + if ((err = azx_codec_create(chip, model)) < 0) { snd_card_free(card); return err; } @@ -1595,7 +1584,6 @@ static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id * } pci_set_drvdata(pci, card); - dev++; return err; } diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 0d11cf7d569..bd9563c8b11 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -64,34 +64,27 @@ MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH}," "{AMD,AMD8111}," "{ALI,M5455}}"); -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; -static char *ac97_quirk[SNDRV_CARDS]; -static int buggy_semaphore[SNDRV_CARDS]; -static int buggy_irq[SNDRV_CARDS]; -static int xbox[SNDRV_CARDS]; - -#ifdef SUPPORT_MIDI -static int mpu_port[SNDRV_CARDS]; /* disabled */ -#endif - -module_param_array(index, int, NULL, 0444); +static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ +static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ +static int ac97_clock = 0; +static char *ac97_quirk; +static int buggy_semaphore; +static int buggy_irq; +static int xbox; + +module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard."); -module_param_array(id, charp, NULL, 0444); +module_param(id, charp, 0444); MODULE_PARM_DESC(id, "ID string for Intel i8x0 soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Intel i8x0 soundcard."); -module_param_array(ac97_clock, int, NULL, 0444); +module_param(ac97_clock, int, 0444); MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect)."); -module_param_array(ac97_quirk, charp, NULL, 0444); +module_param(ac97_quirk, charp, 0444); MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); -module_param_array(buggy_semaphore, bool, NULL, 0444); +module_param(buggy_semaphore, bool, 0444); MODULE_PARM_DESC(buggy_semaphore, "Enable workaround for hardwares with problematic codec semaphores."); -module_param_array(buggy_irq, bool, NULL, 0444); +module_param(buggy_irq, bool, 0444); MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards."); -module_param_array(xbox, bool, NULL, 0444); +module_param(xbox, bool, 0444); MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 codec detection."); /* @@ -2781,20 +2774,12 @@ static struct shortname_table { static int __devinit snd_intel8x0_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { - static int dev; snd_card_t *card; intel8x0_t *chip; int err; struct shortname_table *name; - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); + card = snd_card_new(index, id, THIS_MODULE, 0); if (card == NULL) return -ENOMEM; @@ -2819,16 +2804,16 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci, } if ((err = snd_intel8x0_create(card, pci, pci_id->driver_data, - buggy_semaphore[dev], &chip)) < 0) { + buggy_semaphore, &chip)) < 0) { snd_card_free(card); return err; } - if (buggy_irq[dev]) + if (buggy_irq) chip->buggy_irq = 1; - if (xbox[dev]) + if (xbox) chip->xbox = 1; - if ((err = snd_intel8x0_mixer(chip, ac97_clock[dev], ac97_quirk[dev])) < 0) { + if ((err = snd_intel8x0_mixer(chip, ac97_clock, ac97_quirk)) < 0) { snd_card_free(card); return err; } @@ -2843,7 +2828,7 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci, "%s with %s at %#lx, irq %i", card->shortname, snd_ac97_get_short_name(chip->ac97[0]), chip->addr, chip->irq); - if (! ac97_clock[dev]) + if (! ac97_clock) intel8x0_measure_ac97_clock(chip); if ((err = snd_card_register(card)) < 0) { @@ -2851,7 +2836,6 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci, return err; } pci_set_drvdata(pci, card); - dev++; return 0; } diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 15364d27804..be604bb8445 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -56,18 +56,15 @@ MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH}," "{NVidia,NForce3 Modem}," "{AMD,AMD768}}"); -static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; +static int index = -2; /* Exclude the first card */ +static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ +static int ac97_clock = 0; -module_param_array(index, int, NULL, 0444); +module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for Intel i8x0 modemcard."); -module_param_array(id, charp, NULL, 0444); +module_param(id, charp, 0444); MODULE_PARM_DESC(id, "ID string for Intel i8x0 modemcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Intel i8x0 modemcard."); -module_param_array(ac97_clock, int, NULL, 0444); +module_param(ac97_clock, int, 0444); MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect)."); /* @@ -1263,20 +1260,12 @@ static struct shortname_table { static int __devinit snd_intel8x0m_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { - static int dev; snd_card_t *card; intel8x0_t *chip; int err; struct shortname_table *name; - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); + card = snd_card_new(index, id, THIS_MODULE, 0); if (card == NULL) return -ENOMEM; @@ -1295,7 +1284,7 @@ static int __devinit snd_intel8x0m_probe(struct pci_dev *pci, return err; } - if ((err = snd_intel8x0_mixer(chip, ac97_clock[dev])) < 0) { + if ((err = snd_intel8x0_mixer(chip, ac97_clock)) < 0) { snd_card_free(card); return err; } @@ -1314,7 +1303,6 @@ static int __devinit snd_intel8x0m_probe(struct pci_dev *pci, return err; } pci_set_drvdata(pci, card); - dev++; return 0; } diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index ecc4836ba8d..4545208ee46 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -73,34 +73,31 @@ MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C,pci},{VIA,VT8233A/C,8235}}"); #define SUPPORT_JOYSTICK 1 #endif -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static long mpu_port[SNDRV_CARDS]; +static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ +static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ +static long mpu_port; #ifdef SUPPORT_JOYSTICK -static int joystick[SNDRV_CARDS]; +static int joystick; #endif -static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 48000}; -static char *ac97_quirk[SNDRV_CARDS]; -static int dxs_support[SNDRV_CARDS]; +static int ac97_clock = 48000; +static char *ac97_quirk; +static int dxs_support; -module_param_array(index, int, NULL, 0444); +module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for VIA 82xx bridge."); -module_param_array(id, charp, NULL, 0444); +module_param(id, charp, 0444); MODULE_PARM_DESC(id, "ID string for VIA 82xx bridge."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable audio part of VIA 82xx bridge."); -module_param_array(mpu_port, long, NULL, 0444); +module_param(mpu_port, long, 0444); MODULE_PARM_DESC(mpu_port, "MPU-401 port. (VT82C686x only)"); #ifdef SUPPORT_JOYSTICK -module_param_array(joystick, bool, NULL, 0444); +module_param(joystick, bool, 0444); MODULE_PARM_DESC(joystick, "Enable joystick. (VT82C686x only)"); #endif -module_param_array(ac97_clock, int, NULL, 0444); +module_param(ac97_clock, int, 0444); MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz)."); -module_param_array(ac97_quirk, charp, NULL, 0444); +module_param(ac97_quirk, charp, 0444); MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); -module_param_array(dxs_support, int, NULL, 0444); +module_param(dxs_support, int, 0444); MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA, 5 = enable any sample rate)"); @@ -1637,12 +1634,12 @@ static int __devinit snd_via82xx_mixer_new(via82xx_t *chip, const char *quirk_ov #ifdef SUPPORT_JOYSTICK #define JOYSTICK_ADDR 0x200 -static int __devinit snd_via686_create_gameport(via82xx_t *chip, int dev, unsigned char *legacy) +static int __devinit snd_via686_create_gameport(via82xx_t *chip, unsigned char *legacy) { struct gameport *gp; struct resource *r; - if (!joystick[dev]) + if (!joystick) return -ENODEV; r = request_region(JOYSTICK_ADDR, 8, "VIA686 gameport"); @@ -1686,7 +1683,7 @@ static void snd_via686_free_gameport(via82xx_t *chip) } } #else -static inline int snd_via686_create_gameport(via82xx_t *chip, int dev, unsigned char *legacy) +static inline int snd_via686_create_gameport(via82xx_t *chip, unsigned char *legacy) { return -ENOSYS; } @@ -1698,7 +1695,7 @@ static inline void snd_via686_free_gameport(via82xx_t *chip) { } * */ -static int __devinit snd_via8233_init_misc(via82xx_t *chip, int dev) +static int __devinit snd_via8233_init_misc(via82xx_t *chip) { int i, err, caps; unsigned char val; @@ -1739,7 +1736,7 @@ static int __devinit snd_via8233_init_misc(via82xx_t *chip, int dev) return 0; } -static int __devinit snd_via686_init_misc(via82xx_t *chip, int dev) +static int __devinit snd_via686_init_misc(via82xx_t *chip) { unsigned char legacy, legacy_cfg; int rev_h = 0; @@ -1750,32 +1747,33 @@ static int __devinit snd_via686_init_misc(via82xx_t *chip, int dev) legacy &= ~VIA_FUNC_ENABLE_GAME; /* disable joystick */ if (chip->revision >= VIA_REV_686_H) { rev_h = 1; - if (mpu_port[dev] >= 0x200) { /* force MIDI */ - mpu_port[dev] &= 0xfffc; - pci_write_config_dword(chip->pci, 0x18, mpu_port[dev] | 0x01); + if (mpu_port >= 0x200) { /* force MIDI */ + mpu_port &= 0xfffc; + pci_write_config_dword(chip->pci, 0x18, mpu_port | 0x01); #ifdef CONFIG_PM - chip->mpu_port_saved = mpu_port[dev]; + chip->mpu_port_saved = mpu_port; #endif } else { - mpu_port[dev] = pci_resource_start(chip->pci, 2); + mpu_port = pci_resource_start(chip->pci, 2); } } else { - switch (mpu_port[dev]) { /* force MIDI */ + switch (mpu_port) { /* force MIDI */ case 0x300: case 0x310: case 0x320: case 0x330: legacy_cfg &= ~(3 << 2); - legacy_cfg |= (mpu_port[dev] & 0x0030) >> 2; + legacy_cfg |= (mpu_port & 0x0030) >> 2; break; default: /* no, use BIOS settings */ if (legacy & VIA_FUNC_ENABLE_MIDI) - mpu_port[dev] = 0x300 + ((legacy_cfg & 0x000c) << 2); + mpu_port = 0x300 + ((legacy_cfg & 0x000c) << 2); break; } } - if (mpu_port[dev] >= 0x200 && - (chip->mpu_res = request_region(mpu_port[dev], 2, "VIA82xx MPU401")) != NULL) { + if (mpu_port >= 0x200 && + (chip->mpu_res = request_region(mpu_port, 2, "VIA82xx MPU401")) + != NULL) { if (rev_h) legacy |= VIA_FUNC_MIDI_PNP; /* enable PCI I/O 2 */ legacy |= VIA_FUNC_ENABLE_MIDI; @@ -1783,16 +1781,17 @@ static int __devinit snd_via686_init_misc(via82xx_t *chip, int dev) if (rev_h) legacy &= ~VIA_FUNC_MIDI_PNP; /* disable PCI I/O 2 */ legacy &= ~VIA_FUNC_ENABLE_MIDI; - mpu_port[dev] = 0; + mpu_port = 0; } pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, legacy); pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, legacy_cfg); if (chip->mpu_res) { if (snd_mpu401_uart_new(chip->card, 0, MPU401_HW_VIA686A, - mpu_port[dev], 1, + mpu_port, 1, chip->irq, 0, &chip->rmidi) < 0) { - printk(KERN_WARNING "unable to initialize MPU-401 at 0x%lx, skipping\n", mpu_port[dev]); + printk(KERN_WARNING "unable to initialize MPU-401" + " at 0x%lx, skipping\n", mpu_port); legacy &= ~VIA_FUNC_ENABLE_MIDI; } else { legacy &= ~VIA_FUNC_MIDI_IRQMASK; /* enable MIDI interrupt */ @@ -1800,7 +1799,7 @@ static int __devinit snd_via686_init_misc(via82xx_t *chip, int dev) pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, legacy); } - snd_via686_create_gameport(chip, dev, &legacy); + snd_via686_create_gameport(chip, &legacy); #ifdef CONFIG_PM chip->legacy_saved = legacy; @@ -2221,7 +2220,6 @@ static int __devinit check_dxs_list(struct pci_dev *pci) static int __devinit snd_via82xx_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { - static int dev; snd_card_t *card; via82xx_t *chip; unsigned char revision; @@ -2229,14 +2227,7 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, unsigned int i; int err; - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); + card = snd_card_new(index, id, THIS_MODULE, 0); if (card == NULL) return -ENOMEM; @@ -2259,12 +2250,12 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, } } if (chip_type != TYPE_VIA8233A) { - if (dxs_support[dev] == VIA_DXS_AUTO) - dxs_support[dev] = check_dxs_list(pci); + if (dxs_support == VIA_DXS_AUTO) + dxs_support = check_dxs_list(pci); /* force to use VIA8233 or 8233A model according to * dxs_support module option */ - if (dxs_support[dev] == VIA_DXS_DISABLE) + if (dxs_support == VIA_DXS_DISABLE) chip_type = TYPE_VIA8233A; else chip_type = TYPE_VIA8233; @@ -2282,14 +2273,15 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, goto __error; } - if ((err = snd_via82xx_create(card, pci, chip_type, revision, ac97_clock[dev], &chip)) < 0) + if ((err = snd_via82xx_create(card, pci, chip_type, revision, + ac97_clock, &chip)) < 0) goto __error; - if ((err = snd_via82xx_mixer_new(chip, ac97_quirk[dev])) < 0) + if ((err = snd_via82xx_mixer_new(chip, ac97_quirk)) < 0) goto __error; if (chip_type == TYPE_VIA686) { if ((err = snd_via686_pcm_new(chip)) < 0 || - (err = snd_via686_init_misc(chip, dev)) < 0) + (err = snd_via686_init_misc(chip)) < 0) goto __error; } else { if (chip_type == TYPE_VIA8233A) { @@ -2299,16 +2291,16 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, } else { if ((err = snd_via8233_pcm_new(chip)) < 0) goto __error; - if (dxs_support[dev] == VIA_DXS_48K) + if (dxs_support == VIA_DXS_48K) chip->dxs_fixed = 1; - else if (dxs_support[dev] == VIA_DXS_NO_VRA) + else if (dxs_support == VIA_DXS_NO_VRA) chip->no_vra = 1; - else if (dxs_support[dev] == VIA_DXS_SRC) { + else if (dxs_support == VIA_DXS_SRC) { chip->no_vra = 1; chip->dxs_src = 1; } } - if ((err = snd_via8233_init_misc(chip, dev)) < 0) + if ((err = snd_via8233_init_misc(chip)) < 0) goto __error; } @@ -2329,7 +2321,6 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, return err; } pci_set_drvdata(pci, card); - dev++; return 0; __error: diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index c3ab8fbf582..a7a60d837c8 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -55,18 +55,15 @@ MODULE_DESCRIPTION("VIA VT82xx modem"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C modem,pci}}"); -static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 48000}; +static int index = -2; /* Exclude the first card */ +static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ +static int ac97_clock = 48000; -module_param_array(index, int, NULL, 0444); +module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for VIA 82xx bridge."); -module_param_array(id, charp, NULL, 0444); +module_param(id, charp, 0444); MODULE_PARM_DESC(id, "ID string for VIA 82xx bridge."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable modem part of VIA 82xx bridge."); -module_param_array(ac97_clock, int, NULL, 0444); +module_param(ac97_clock, int, 0444); MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz)."); @@ -1135,7 +1132,6 @@ static int __devinit snd_via82xx_create(snd_card_t * card, static int __devinit snd_via82xx_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { - static int dev; snd_card_t *card; via82xx_t *chip; unsigned char revision; @@ -1143,14 +1139,7 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, unsigned int i; int err; - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); + card = snd_card_new(index, id, THIS_MODULE, 0); if (card == NULL) return -ENOMEM; @@ -1167,7 +1156,8 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, goto __error; } - if ((err = snd_via82xx_create(card, pci, chip_type, revision, ac97_clock[dev], &chip)) < 0) + if ((err = snd_via82xx_create(card, pci, chip_type, revision, + ac97_clock, &chip)) < 0) goto __error; if ((err = snd_via82xx_mixer_new(chip)) < 0) goto __error; @@ -1191,7 +1181,6 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, return err; } pci_set_drvdata(pci, card); - dev++; return 0; __error: -- cgit v1.2.3 From 79ba34b94170eb517f0dcf634aab7fb1f5708d4b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 5 Oct 2005 19:47:41 +0200 Subject: [ALSA] intel8x0 - Suppress the codec warnings during probing Modules: Intel8x0 driver Suppress the codec warnings during probing of codecs. Signed-off-by: Takashi Iwai --- sound/pci/intel8x0.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index bd9563c8b11..a82f3b62364 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -600,16 +600,19 @@ static int snd_intel8x0_ali_codec_ready(intel8x0_t *chip, int mask) if (val & mask) return 0; } - snd_printd(KERN_WARNING "intel8x0: AC97 codec ready timeout.\n"); + if (! chip->in_ac97_init) + snd_printd(KERN_WARNING "intel8x0: AC97 codec ready timeout.\n"); return -EBUSY; } static int snd_intel8x0_ali_codec_semaphore(intel8x0_t *chip) { int time = 100; + if (chip->buggy_semaphore) + return 0; /* just ignore ... */ while (time-- && (igetdword(chip, ICHREG(ALI_CAS)) & ALI_CAS_SEM_BUSY)) udelay(1); - if (! time) + if (! time && ! chip->in_ac97_init) snd_printk(KERN_WARNING "ali_codec_semaphore timeout\n"); return snd_intel8x0_ali_codec_ready(chip, ALI_CSPSR_CODEC_READY); } -- cgit v1.2.3 From 2b3e584b9235b302efa769acb172258513400065 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 6 Oct 2005 13:47:23 +0200 Subject: [ALSA] Add dummy obsoleted module options for backward compatibility Added dummay obsoleted module options for backward compatibility (to reduce possible bugzilla entries :) Signed-off-by: Takashi Iwai --- sound/pci/atiixp.c | 4 ++++ sound/pci/atiixp_modem.c | 4 ++++ sound/pci/hda/hda_intel.c | 4 ++++ sound/pci/intel8x0.c | 6 ++++++ sound/pci/intel8x0m.c | 4 ++++ sound/pci/via82xx.c | 4 ++++ sound/pci/via82xx_modem.c | 4 ++++ 7 files changed, 30 insertions(+) diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 332a71de967..14f912ae40d 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -56,6 +56,10 @@ MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); module_param(spdif_aclink, bool, 0444); MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link."); +/* just for backward compatibility */ +static int enable; +module_param(enable, int, 0444); + /* */ diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index a4778d373cd..ab39c0b7cce 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -50,6 +50,10 @@ MODULE_PARM_DESC(id, "ID string for ATI IXP controller."); module_param(ac97_clock, int, 0444); MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz)."); +/* just for backward compatibility */ +static int enable; +module_param(enable, int, 0444); + /* */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index d9e88dfe817..1426fa0ac6d 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -61,6 +61,10 @@ MODULE_PARM_DESC(model, "Use the given board model."); module_param(position_fix, int, 0444); MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)."); +/* just for backward compatibility */ +static int enable; +module_param(enable, int, 0444); + MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," "{Intel, ICH6M}," diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index a82f3b62364..352c2cc650a 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -87,6 +87,12 @@ MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some moth module_param(xbox, bool, 0444); MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 codec detection."); +/* just for backward compatibility */ +static int enable; +module_param(enable, int, 0444); +static int joystick; +module_param(joystick, int, 0444); + /* * Direct registers */ diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index be604bb8445..2295335981f 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -67,6 +67,10 @@ MODULE_PARM_DESC(id, "ID string for Intel i8x0 modemcard."); module_param(ac97_clock, int, 0444); MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect)."); +/* just for backward compatibility */ +static int enable; +module_param(enable, int, 0444); + /* * Direct registers */ diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 4545208ee46..b2779fb7d1a 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -100,6 +100,10 @@ MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); module_param(dxs_support, int, 0444); MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA, 5 = enable any sample rate)"); +/* just for backward compatibility */ +static int enable; +module_param(enable, int, 0444); + /* revision numbers for via686 */ #define VIA_REV_686_A 0x10 diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index a7a60d837c8..9462ebf590d 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -66,6 +66,10 @@ MODULE_PARM_DESC(id, "ID string for VIA 82xx bridge."); module_param(ac97_clock, int, 0444); MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz)."); +/* just for backward compatibility */ +static int enable; +module_param(enable, int, 0444); + /* * Direct registers -- cgit v1.2.3 From c168143c450d93887590078087a57e1e6b1189f7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 6 Oct 2005 13:48:54 +0200 Subject: [ALSA] Allow 8-44khz sample rates on Revolution 7.1 Modules: ICE1724 driver Remove the restcition of sample rates on Revolution 7.1 board. This enables the low 8-44kHz sample rates. Signed-off-by: Takashi Iwai --- sound/pci/ice1712/revo.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c index d48d42524ac..1fe21009ca8 100644 --- a/sound/pci/ice1712/revo.c +++ b/sound/pci/ice1712/revo.c @@ -128,17 +128,6 @@ static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = { .mask_flags = 0, }; -static unsigned int rates[] = { - 32000, 44100, 48000, 64000, 88200, 96000, - 176400, 192000, -}; - -static snd_pcm_hw_constraint_list_t revo_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - static int __devinit revo_init(ice1712_t *ice) { akm4xxx_t *ak; @@ -173,8 +162,6 @@ static int __devinit revo_init(ice1712_t *ice) break; } - ice->hw_rates = &revo_rates; /* AK codecs don't support lower than 32k */ - return 0; } -- cgit v1.2.3 From 72c8986cafd20d93f331dc74fb175c304a37fbdb Mon Sep 17 00:00:00 2001 From: Dick Streefland Date: Fri, 7 Oct 2005 12:02:23 +0200 Subject: [ALSA] intel8x0 - enable ac97_quirk hp_only for Acer Aspire 3003LCi Modules: Intel8x0 driver On my Acer Aspire 3003LCi laptop, the speaker volume is not controlled by the master control, but by the headphone control. Enabling the 'hp_only' quirk corrects this. The patch below adds this device to the list of known quirks. Signed-off-by: Dick Streefland Signed-off-by: Takashi Iwai --- sound/pci/intel8x0.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 352c2cc650a..fc2fba8129e 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -1717,6 +1717,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { .name = "IBM NetVista A30p", /* AD1981B */ .type = AC97_TUNE_HP_ONLY }, + { + .subvendor = 0x1025, + .subdevice = 0x0083, + .name = "Acer Aspire 3003LCi", + .type = AC97_TUNE_HP_ONLY + }, { .subvendor = 0x1028, .subdevice = 0x00d8, -- cgit v1.2.3 From f01cc521a2abef5dba24fb0873b9626ba6b0a0a5 Mon Sep 17 00:00:00 2001 From: Sasha Khapyorsky Date: Mon, 10 Oct 2005 11:45:31 +0200 Subject: [ALSA] Sasha Khapyorsky: My email address is changed, there is update. Modules: Intel8x0-modem driver,VIA82xx-modem driver,HDA Codec driver Signed-off-by: Sasha Khapyorsky Signed-off-by: Jaroslav Kysela --- sound/pci/hda/patch_si3054.c | 2 +- sound/pci/intel8x0m.c | 2 +- sound/pci/via82xx_modem.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c index d014b7bb70d..9c7fe0b3200 100644 --- a/sound/pci/hda/patch_si3054.c +++ b/sound/pci/hda/patch_si3054.c @@ -3,7 +3,7 @@ * * HD audio interface patch for Silicon Labs 3054/5 modem codec * - * Copyright (c) 2005 Sasha Khapyorsky + * Copyright (c) 2005 Sasha Khapyorsky * Takashi Iwai * * diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 2295335981f..314f3d8caea 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -3,7 +3,7 @@ * * Copyright (c) 2000 Jaroslav Kysela * - * This is modified (by Sasha Khapyorsky ) version + * This is modified (by Sasha Khapyorsky ) version * of ALSA ICH sound driver intel8x0.c . * * diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 9462ebf590d..db7768124f5 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -26,7 +26,7 @@ /* * Changes: * - * Sep. 2, 2004 Sasha Khapyorsky + * Sep. 2, 2004 Sasha Khapyorsky * Modified from original audio driver 'via82xx.c' to support AC97 * modems. */ -- cgit v1.2.3 From 7c22f1aaa23370bf9ba2dd3abbccbed70dced216 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 10 Oct 2005 11:46:31 +0200 Subject: [ALSA] Remove snd_runtime_check() macro Remove snd_runtime_check() macro. This macro worsens the readability of codes. They should be either normal if() or removable asserts. Also, the assert displays stack-dump, instead of only the last caller pointer. Signed-off-by: Takashi Iwai --- .../sound/alsa/DocBook/writing-an-alsa-driver.tmpl | 33 +++++------- include/sound/core.h | 34 ++++--------- sound/core/control.c | 18 +++---- sound/core/init.c | 5 +- sound/core/oss/mixer_oss.c | 59 +++++++++++++++------- sound/core/pcm.c | 3 +- sound/core/pcm_lib.c | 3 +- sound/core/pcm_native.c | 3 +- sound/core/seq/seq_midi.c | 2 - sound/core/timer.c | 3 +- sound/isa/cs423x/cs4236_lib.c | 5 +- sound/pci/ac97/ac97_codec.c | 1 - sound/pci/ac97/ac97_patch.c | 3 +- sound/pci/emu10k1/emufx.c | 34 +++++++++---- sound/pci/emu10k1/emupcm.c | 3 +- sound/pci/trident/trident_main.c | 3 +- sound/ppc/pmac.c | 16 +++--- 17 files changed, 126 insertions(+), 102 deletions(-) diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index 24e85520890..f3a2fdca9ad 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -18,8 +18,8 @@ - March 6, 2005 - 0.3.4 + October 6, 2005 + 0.3.5 @@ -30,7 +30,7 @@ - Copyright (c) 2002-2004 Takashi Iwai tiwai@suse.de + Copyright (c) 2002-2005 Takashi Iwai tiwai@suse.de @@ -5998,32 +5998,23 @@ struct _snd_pcm_runtime { The first argument is the expression to evaluate, and the second argument is the action if it fails. When CONFIG_SND_DEBUG, is set, it will show an - error message such as BUG? (xxx) (called from - yyy). When no debug flag is set, this is - ignored. + error message such as BUG? (xxx) + together with stack trace. - - -
- <function>snd_runtime_check()</function> - This macro is quite similar with - snd_assert(). Unlike - snd_assert(), the expression is always - evaluated regardless of - CONFIG_SND_DEBUG. When - CONFIG_SND_DEBUG is set, the macro will - show a message like ERROR (xx) (called from - yyy). + When no debug flag is set, this macro is ignored.
<function>snd_BUG()</function> - It calls snd_assert(0,) -- that is, just - prints the error message at the point. It's useful to show that - a fatal error happens there. + It shows BUG? message and + stack trace as well as snd_assert at the point. + It's useful to show that a fatal error happens there. + + + When no debug flag is set, this macro is ignored.
diff --git a/include/sound/core.h b/include/sound/core.h index 6d971a4c4ca..f0f54407fe5 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -429,34 +429,24 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...) * When CONFIG_SND_DEBUG is not set, the expression is executed but * not checked. */ -#define snd_assert(expr, args...) do {\ - if (unlikely(!(expr))) { \ - snd_printk(KERN_ERR "BUG? (%s) (called from %p)\n", __ASTRING__(expr), __builtin_return_address(0));\ - args;\ - }\ +#define snd_assert(expr, args...) do { \ + if (unlikely(!(expr))) { \ + snd_printk(KERN_ERR "BUG? (%s)\n", __ASTRING__(expr)); \ + dump_stack(); \ + args; \ + } \ } while (0) -/** - * snd_runtime_check - run-time assertion macro - * @expr: expression - * @args...: the action - * - * This macro checks the expression in run-time and invokes the commands - * given in the rest arguments if the assertion is failed. - * Unlike snd_assert(), the action commands are executed even if - * CONFIG_SND_DEBUG is not set but without any error messages. - */ -#define snd_runtime_check(expr, args...) do {\ - if (unlikely(!(expr))) { \ - snd_printk(KERN_ERR "ERROR (%s) (called from %p)\n", __ASTRING__(expr), __builtin_return_address(0));\ - args;\ - }\ + +#define snd_BUG() do { \ + snd_printk(KERN_ERR "BUG?\n"); \ + dump_stack(); \ } while (0) #else /* !CONFIG_SND_DEBUG */ #define snd_printd(fmt, args...) /* nothing */ #define snd_assert(expr, args...) (void)(expr) -#define snd_runtime_check(expr, args...) do { if (!(expr)) { args; } } while (0) +#define snd_BUG() /* nothing */ #endif /* CONFIG_SND_DEBUG */ @@ -473,8 +463,6 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...) #define snd_printdd(format, args...) /* nothing */ #endif -#define snd_BUG() snd_assert(0, ) - static inline void snd_timestamp_now(struct timespec *tstamp, int timespec) { diff --git a/sound/core/control.c b/sound/core/control.c index 736edf358e0..212c46a9437 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -144,7 +144,7 @@ void snd_ctl_notify(snd_card_t *card, unsigned int mask, snd_ctl_elem_id_t *id) snd_ctl_file_t *ctl; snd_kctl_event_t *ev; - snd_runtime_check(card != NULL && id != NULL, return); + snd_assert(card != NULL && id != NULL, return); read_lock(&card->ctl_files_rwlock); #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) card->mixer_oss_change_count++; @@ -193,8 +193,8 @@ snd_kcontrol_t *snd_ctl_new(snd_kcontrol_t * control, unsigned int access) snd_kcontrol_t *kctl; unsigned int idx; - snd_runtime_check(control != NULL, return NULL); - snd_runtime_check(control->count > 0, return NULL); + snd_assert(control != NULL, return NULL); + snd_assert(control->count > 0, return NULL); kctl = kzalloc(sizeof(*kctl) + sizeof(snd_kcontrol_volatile_t) * control->count, GFP_KERNEL); if (kctl == NULL) return NULL; @@ -220,7 +220,7 @@ snd_kcontrol_t *snd_ctl_new1(const snd_kcontrol_new_t * ncontrol, void *private_ snd_kcontrol_t kctl; unsigned int access; - snd_runtime_check(ncontrol != NULL, return NULL); + snd_assert(ncontrol != NULL, return NULL); snd_assert(ncontrol->info != NULL, return NULL); memset(&kctl, 0, sizeof(kctl)); kctl.id.iface = ncontrol->iface; @@ -309,7 +309,7 @@ int snd_ctl_add(snd_card_t * card, snd_kcontrol_t * kcontrol) snd_ctl_elem_id_t id; unsigned int idx; - snd_runtime_check(card != NULL && kcontrol != NULL, return -EINVAL); + snd_assert(card != NULL && kcontrol != NULL, return -EINVAL); snd_assert(kcontrol->info != NULL, return -EINVAL); id = kcontrol->id; down_write(&card->controls_rwsem); @@ -355,7 +355,7 @@ int snd_ctl_remove(snd_card_t * card, snd_kcontrol_t * kcontrol) snd_ctl_elem_id_t id; unsigned int idx; - snd_runtime_check(card != NULL && kcontrol != NULL, return -EINVAL); + snd_assert(card != NULL && kcontrol != NULL, return -EINVAL); list_del(&kcontrol->list); card->controls_count -= kcontrol->count; id = kcontrol->id; @@ -468,7 +468,7 @@ snd_kcontrol_t *snd_ctl_find_numid(snd_card_t * card, unsigned int numid) struct list_head *list; snd_kcontrol_t *kctl; - snd_runtime_check(card != NULL && numid != 0, return NULL); + snd_assert(card != NULL && numid != 0, return NULL); list_for_each(list, &card->controls) { kctl = snd_kcontrol(list); if (kctl->id.numid <= numid && kctl->id.numid + kctl->count > numid) @@ -494,7 +494,7 @@ snd_kcontrol_t *snd_ctl_find_id(snd_card_t * card, snd_ctl_elem_id_t *id) struct list_head *list; snd_kcontrol_t *kctl; - snd_runtime_check(card != NULL && id != NULL, return NULL); + snd_assert(card != NULL && id != NULL, return NULL); if (id->numid != 0) return snd_ctl_find_numid(card, id->numid); list_for_each(list, &card->controls) { @@ -1215,7 +1215,7 @@ static int _snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn, struct list_head struct list_head *list; snd_kctl_ioctl_t *p; - snd_runtime_check(fcn != NULL, return -EINVAL); + snd_assert(fcn != NULL, return -EINVAL); down_write(&snd_ioctl_rwsem); list_for_each(list, lists) { p = list_entry(list, snd_kctl_ioctl_t, list); diff --git a/sound/core/init.c b/sound/core/init.c index 41e224986f3..b98f7c6310c 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -420,7 +420,7 @@ int snd_card_register(snd_card_t * card) int err; snd_info_entry_t *entry; - snd_runtime_check(card != NULL, return -EINVAL); + snd_assert(card != NULL, return -EINVAL); if ((err = snd_device_register_all(card)) < 0) return err; write_lock(&snd_card_rwlock); @@ -524,7 +524,8 @@ int __init snd_card_info_init(void) snd_info_entry_t *entry; entry = snd_info_create_module_entry(THIS_MODULE, "cards", NULL); - snd_runtime_check(entry != NULL, return -ENOMEM); + if (! entry) + return -ENOMEM; entry->c.text.read_size = PAGE_SIZE; entry->c.text.read = snd_card_info_read; if (snd_info_register(entry) < 0) { diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 69e1059112d..b2497cec207 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -521,9 +521,13 @@ static void snd_mixer_oss_get_volume1_vol(snd_mixer_oss_file_t *fmixer, uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); if (uinfo == NULL || uctl == NULL) goto __unalloc; - snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc); - snd_runtime_check(!kctl->get(kctl, uctl), goto __unalloc); - snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, goto __unalloc); + if (kctl->info(kctl, uinfo)) + goto __unalloc; + if (kctl->get(kctl, uctl)) + goto __unalloc; + if (uinfo->type == SNDRV_CTL_ELEM_TYPE_BOOLEAN && + uinfo->value.integer.min == 0 && uinfo->value.integer.max == 1) + goto __unalloc; *left = snd_mixer_oss_conv1(uctl->value.integer.value[0], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[0]); if (uinfo->count > 1) *right = snd_mixer_oss_conv1(uctl->value.integer.value[1], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[1]); @@ -555,8 +559,10 @@ static void snd_mixer_oss_get_volume1_sw(snd_mixer_oss_file_t *fmixer, uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); if (uinfo == NULL || uctl == NULL) goto __unalloc; - snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc); - snd_runtime_check(!kctl->get(kctl, uctl), goto __unalloc); + if (kctl->info(kctl, uinfo)) + goto __unalloc; + if (kctl->get(kctl, uctl)) + goto __unalloc; if (!uctl->value.integer.value[0]) { *left = 0; if (uinfo->count == 1) @@ -616,12 +622,16 @@ static void snd_mixer_oss_put_volume1_vol(snd_mixer_oss_file_t *fmixer, uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); if (uinfo == NULL || uctl == NULL) goto __unalloc; - snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc); - snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, goto __unalloc); + if (kctl->info(kctl, uinfo)) + goto __unalloc; + if (uinfo->type == SNDRV_CTL_ELEM_TYPE_BOOLEAN && + uinfo->value.integer.min == 0 && uinfo->value.integer.max == 1) + goto __unalloc; uctl->value.integer.value[0] = snd_mixer_oss_conv2(left, uinfo->value.integer.min, uinfo->value.integer.max); if (uinfo->count > 1) uctl->value.integer.value[1] = snd_mixer_oss_conv2(right, uinfo->value.integer.min, uinfo->value.integer.max); - snd_runtime_check((res = kctl->put(kctl, uctl)) >= 0, goto __unalloc); + if ((res = kctl->put(kctl, uctl)) < 0) + goto __unalloc; if (res > 0) snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); __unalloc: @@ -653,7 +663,8 @@ static void snd_mixer_oss_put_volume1_sw(snd_mixer_oss_file_t *fmixer, uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); if (uinfo == NULL || uctl == NULL) goto __unalloc; - snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc); + if (kctl->info(kctl, uinfo)) + goto __unalloc; if (uinfo->count > 1) { uctl->value.integer.value[0] = left > 0 ? 1 : 0; uctl->value.integer.value[route ? 3 : 1] = right > 0 ? 1 : 0; @@ -664,7 +675,8 @@ static void snd_mixer_oss_put_volume1_sw(snd_mixer_oss_file_t *fmixer, } else { uctl->value.integer.value[0] = (left > 0 || right > 0) ? 1 : 0; } - snd_runtime_check((res = kctl->put(kctl, uctl)) >= 0, goto __unalloc); + if ((res = kctl->put(kctl, uctl)) < 0) + goto __unalloc; if (res > 0) snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); __unalloc: @@ -776,9 +788,14 @@ static int snd_mixer_oss_get_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int } down_read(&card->controls_rwsem); kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0); - snd_runtime_check(kctl != NULL, err = -ENOENT; goto __unlock); - snd_runtime_check(!(err = kctl->info(kctl, uinfo)), goto __unlock); - snd_runtime_check(!(err = kctl->get(kctl, uctl)), goto __unlock); + if (! kctl) { + err = -ENOENT; + goto __unlock; + } + if ((err = kctl->info(kctl, uinfo)) < 0) + goto __unlock; + if ((err = kctl->get(kctl, uctl)) < 0) + goto __unlock; for (idx = 0; idx < 32; idx++) { if (!(mixer->mask_recsrc & (1 << idx))) continue; @@ -821,8 +838,12 @@ static int snd_mixer_oss_put_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int } down_read(&card->controls_rwsem); kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0); - snd_runtime_check(kctl != NULL, err = -ENOENT; goto __unlock); - snd_runtime_check(!(err = kctl->info(kctl, uinfo)), goto __unlock); + if (! kctl) { + err = -ENOENT; + goto __unlock; + } + if ((err = kctl->info(kctl, uinfo)) < 0) + goto __unlock; for (idx = 0; idx < 32; idx++) { if (!(mixer->mask_recsrc & (1 << idx))) continue; @@ -836,10 +857,11 @@ static int snd_mixer_oss_put_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int break; slot = NULL; } - snd_runtime_check(slot != NULL, goto __unlock); + if (! slot) + goto __unlock; for (idx = 0; idx < uinfo->count; idx++) uctl->value.enumerated.item[idx] = slot->capture_item; - snd_runtime_check((err = kctl->put(kctl, uctl)) >= 0, ); + err = kctl->put(kctl, uctl); if (err > 0) snd_ctl_notify(fmixer->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); err = 0; @@ -1008,7 +1030,8 @@ static int snd_mixer_oss_build_input(snd_mixer_oss_t *mixer, struct snd_mixer_os up_read(&mixer->card->controls_rwsem); if (slot.present != 0) { pslot = (struct slot *)kmalloc(sizeof(slot), GFP_KERNEL); - snd_runtime_check(pslot != NULL, return -ENOMEM); + if (! pslot) + return -ENOMEM; *pslot = slot; pslot->signature = SNDRV_MIXER_OSS_SIGNATURE; pslot->assigned = ptr; diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 1be470e942e..184e74b75ba 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -273,7 +273,8 @@ static void snd_pcm_proc_info_read(snd_pcm_substream_t *substream, snd_info_buff snd_pcm_info_t *info; int err; - snd_runtime_check(substream, return); + if (! substream) + return; info = kmalloc(sizeof(*info), GFP_KERNEL); if (! info) { diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 0503980c23d..dfc5f45f274 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -156,9 +156,8 @@ static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(snd_pcm_substream_t *s #ifdef CONFIG_SND_DEBUG if (pos >= runtime->buffer_size) { snd_printk(KERN_ERR "BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size); - } else + } #endif - snd_runtime_check(pos < runtime->buffer_size, return 0); pos -= pos % runtime->min_align; return pos; } diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index e97b2d162cc..e6e2b70314c 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -2053,7 +2053,8 @@ static int snd_pcm_open(struct inode *inode, struct file *file) snd_pcm_file_t *pcm_file; wait_queue_t wait; - snd_runtime_check(device >= SNDRV_MINOR_PCM_PLAYBACK && device < SNDRV_MINOR_DEVICES, return -ENXIO); + if (device < SNDRV_MINOR_PCM_PLAYBACK || device >= SNDRV_MINOR_DEVICES) + return -ENXIO; pcm = snd_pcm_devices[(cardnum * SNDRV_PCM_DEVICES) + (device % SNDRV_MINOR_PCMS)]; if (pcm == NULL) { err = -ENODEV; diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c index b4674ae3bc3..f89f40f4487 100644 --- a/sound/core/seq/seq_midi.c +++ b/sound/core/seq/seq_midi.c @@ -449,11 +449,9 @@ snd_seq_midisynth_unregister_port(snd_seq_device_t *dev) client->ports_per_device[device] = 0; msynth = client->ports[device]; client->ports[device] = NULL; - snd_runtime_check(msynth != NULL || ports <= 0, goto __skip); for (p = 0; p < ports; p++) snd_seq_midisynth_delete(&msynth[p]); kfree(msynth); - __skip: client->num_ports--; if (client->num_ports <= 0) { snd_seq_delete_kernel_client(client->seq_client); diff --git a/sound/core/timer.c b/sound/core/timer.c index 22b10462408..128916c6608 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -879,7 +879,8 @@ void snd_timer_notify(snd_timer_t *timer, enum sndrv_timer_event event, struct t snd_timer_instance_t *ti, *ts; struct list_head *p, *n; - snd_runtime_check(timer->hw.flags & SNDRV_TIMER_HW_SLAVE, return); + if (! (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)) + return; snd_assert(event >= SNDRV_TIMER_EVENT_MSTART && event <= SNDRV_TIMER_EVENT_MRESUME, return); spin_lock_irqsave(&timer->lock, flags); if (event == SNDRV_TIMER_EVENT_MSTART || diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c index 2128d4bdef4..1adb88d5f8f 100644 --- a/sound/isa/cs423x/cs4236_lib.c +++ b/sound/isa/cs423x/cs4236_lib.c @@ -173,7 +173,10 @@ static unsigned char divisor_to_rate_register(unsigned int divisor) case 2117: return 6; case 2558: return 7; default: - snd_runtime_check(divisor >= 21 && divisor <= 192, return 192); + if (divisor < 21 || divisor > 192) { + snd_BUG(); + return 192; + } return divisor; } } diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 56549add80a..bbc409ae7ee 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1127,7 +1127,6 @@ snd_kcontrol_t *snd_ac97_cnew(const snd_kcontrol_new_t *_template, ac97_t * ac97 { snd_kcontrol_new_t template; memcpy(&template, _template, sizeof(template)); - snd_runtime_check(!template.index, return NULL); template.index = ac97->num; return snd_ctl_new1(&template, ac97); } diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index b24beb32961..de1c72ad2c6 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -1460,7 +1460,8 @@ int patch_ad1881(ac97_t * ac97) codecs[1] = patch_ad1881_unchained(ac97, 1, (1<<14)); codecs[2] = patch_ad1881_unchained(ac97, 2, (1<<13)); - snd_runtime_check(codecs[0] | codecs[1] | codecs[2], goto __end); + if (! (codecs[0] || codecs[1] || codecs[2])) + goto __end; for (idx = 0; idx < 3; idx++) if (ac97->spec.ad18xx.unchained[idx]) diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 20db3ac6cd6..177c4ad0f77 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c @@ -364,12 +364,18 @@ static int snd_emu10k1_gpr_ctl_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, db_table[val]); break; case EMU10K1_GPR_TRANSLATION_BASS: - snd_runtime_check((ctl->count % 5) == 0 && (ctl->count / 5) == ctl->vcount, change = -EIO; goto __error); + if ((ctl->count % 5) != 0 || (ctl->count / 5) != ctl->vcount) { + change = -EIO; + goto __error; + } for (j = 0; j < 5; j++) snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[j * ctl->vcount + i], 0, bass_table[val][j]); break; case EMU10K1_GPR_TRANSLATION_TREBLE: - snd_runtime_check((ctl->count % 5) == 0 && (ctl->count / 5) == ctl->vcount, change = -EIO; goto __error); + if ((ctl->count % 5) != 0 || (ctl->count / 5) != ctl->vcount) { + change = -EIO; + goto __error; + } for (j = 0; j < 5; j++) snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[j * ctl->vcount + i], 0, treble_table[val][j]); break; @@ -412,8 +418,6 @@ int snd_emu10k1_fx8010_register_irq_handler(emu10k1_t *emu, snd_emu10k1_fx8010_irq_t *irq; unsigned long flags; - snd_runtime_check(emu, return -EINVAL); - snd_runtime_check(handler, return -EINVAL); irq = kmalloc(sizeof(*irq), GFP_ATOMIC); if (irq == NULL) return -ENOMEM; @@ -442,7 +446,6 @@ int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu, snd_emu10k1_fx8010_irq_t *tmp; unsigned long flags; - snd_runtime_check(irq, return -EINVAL); spin_lock_irqsave(&emu->fx8010.irq_lock, flags); if ((tmp = emu->fx8010.irq_handlers) == irq) { emu->fx8010.irq_handlers = tmp->next; @@ -717,9 +720,15 @@ static int snd_emu10k1_add_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode err = -EFAULT; goto __error; } - snd_runtime_check(gctl->id.iface == SNDRV_CTL_ELEM_IFACE_MIXER || - gctl->id.iface == SNDRV_CTL_ELEM_IFACE_PCM, err = -EINVAL; goto __error); - snd_runtime_check(gctl->id.name[0] != '\0', err = -EINVAL; goto __error); + if (gctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER && + gctl->id.iface != SNDRV_CTL_ELEM_IFACE_PCM) { + err = -EINVAL; + goto __error; + } + if (! gctl->id.name[0]) { + err = -EINVAL; + goto __error; + } ctl = snd_emu10k1_look_for_ctl(emu, &gctl->id); memset(&knew, 0, sizeof(knew)); knew.iface = gctl->id.iface; @@ -783,7 +792,8 @@ static int snd_emu10k1_del_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode for (i = 0, _id = icode->gpr_del_controls; i < icode->gpr_del_control_count; i++, _id++) { - snd_runtime_check(copy_from_user(&id, _id, sizeof(id)) == 0, return -EFAULT); + if (copy_from_user(&id, _id, sizeof(id))) + return -EFAULT; down_write(&card->controls_rwsem); ctl = snd_emu10k1_look_for_ctl(emu, &id); if (ctl) @@ -2075,14 +2085,16 @@ void snd_emu10k1_free_efx(emu10k1_t *emu) #if 0 // FIXME: who use them? int snd_emu10k1_fx8010_tone_control_activate(emu10k1_t *emu, int output) { - snd_runtime_check(output >= 0 && output < 6, return -EINVAL); + if (output < 0 || output >= 6) + return -EINVAL; snd_emu10k1_ptr_write(emu, emu->gpr_base + 0x94 + output, 0, 1); return 0; } int snd_emu10k1_fx8010_tone_control_deactivate(emu10k1_t *emu, int output) { - snd_runtime_check(output >= 0 && output < 6, return -EINVAL); + if (output < 0 || output >= 6) + return -EINVAL; snd_emu10k1_ptr_write(emu, emu->gpr_base + 0x94 + output, 0, 0); return 0; } diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index 66ba27afe96..bf7490dae09 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c @@ -965,7 +965,8 @@ static void snd_emu10k1_pcm_mixer_notify1(emu10k1_t *emu, snd_kcontrol_t *kctl, { snd_ctl_elem_id_t id; - snd_runtime_check(kctl != NULL, return); + if (! kctl) + return; if (activate) kctl->vd[idx].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; else diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 777da9a7298..dda62955b4f 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -2893,7 +2893,8 @@ static void snd_trident_notify_pcm_change1(snd_card_t * card, snd_kcontrol_t *kc { snd_ctl_elem_id_t id; - snd_runtime_check(kctl != NULL, return); + if (! kctl) + return; if (activate) kctl->vd[num].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; else diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index 392b2abd9f1..db2f1815fc3 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c @@ -220,7 +220,8 @@ static int snd_pmac_pcm_prepare(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substr /* set up constraints */ astr = snd_pmac_get_stream(chip, another_stream(rec->stream)); - snd_runtime_check(astr, return -EINVAL); + if (! astr) + return -EINVAL; astr->cur_freqs = 1 << rate_index; astr->cur_formats = 1 << runtime->format; chip->rate_index = rate_index; @@ -467,7 +468,8 @@ static int snd_pmac_hw_rule_rate(snd_pcm_hw_params_t *params, pmac_stream_t *rec = snd_pmac_get_stream(chip, rule->deps[0]); int i, freq_table[8], num_freqs; - snd_runtime_check(rec, return -EINVAL); + if (! rec) + return -EINVAL; num_freqs = 0; for (i = chip->num_freqs - 1; i >= 0; i--) { if (rec->cur_freqs & (1 << i)) @@ -484,7 +486,8 @@ static int snd_pmac_hw_rule_format(snd_pcm_hw_params_t *params, pmac_t *chip = rule->private; pmac_stream_t *rec = snd_pmac_get_stream(chip, rule->deps[0]); - snd_runtime_check(rec, return -EINVAL); + if (! rec) + return -EINVAL; return snd_mask_refine_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), rec->cur_formats); } @@ -569,7 +572,8 @@ static int snd_pmac_pcm_close(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substrea snd_pmac_dma_stop(rec); astr = snd_pmac_get_stream(chip, another_stream(rec->stream)); - snd_runtime_check(astr, return -EINVAL); + if (! astr) + return -EINVAL; /* reset constraints */ astr->cur_freqs = chip->freqs_ok; @@ -1158,7 +1162,6 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return) .dev_free = snd_pmac_dev_free, }; - snd_runtime_check(chip_return, return -EINVAL); *chip_return = NULL; chip = kzalloc(sizeof(*chip), GFP_KERNEL); @@ -1382,7 +1385,8 @@ static int snd_pmac_sleep_notify(struct pmu_sleep_notifier *self, int when) pmac_t *chip; chip = sleeping_pmac; - snd_runtime_check(chip, return 0); + if (! chip) + return 0; switch (when) { case PBOOK_SLEEP_NOW: -- cgit v1.2.3 From 07799e756c76ecd52cb01a812ba48b7d8ac67633 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 10 Oct 2005 11:49:49 +0200 Subject: [ALSA] Use getnstimeofday() Modules: Documentation,PCM Midlevel,Timer Midlevel,ALSA Core Use the standard getnstimeofday() function instead of ALSA's own one. Signed-off-by: Takashi Iwai --- .../sound/alsa/DocBook/writing-an-alsa-driver.tmpl | 3 +-- include/sound/core.h | 23 ---------------------- include/sound/pcm.h | 3 +-- sound/core/pcm_lib.c | 2 +- sound/core/pcm_native.c | 14 ++++--------- sound/core/timer.c | 6 +++--- 6 files changed, 10 insertions(+), 41 deletions(-) diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index f3a2fdca9ad..ab3dfe074fb 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -2190,8 +2190,7 @@ struct _snd_pcm_runtime { unsigned int rate_den; /* -- SW params -- */ - int tstamp_timespec; /* use timeval (0) or timespec (1) */ - snd_pcm_tstamp_t tstamp_mode; /* mmap timestamp is updated */ + struct timespec tstamp_mode; /* mmap timestamp is updated */ unsigned int period_step; unsigned int sleep_min; /* min ticks to sleep */ snd_pcm_uframes_t xfer_align; /* xfer size need to be a multiple */ diff --git a/include/sound/core.h b/include/sound/core.h index f0f54407fe5..fa8f4c9492c 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -29,7 +29,6 @@ #include /* pm_message_t */ /* Typedef's */ -typedef struct timespec snd_timestamp_t; typedef struct sndrv_interval snd_interval_t; typedef enum sndrv_card_type snd_card_type; typedef struct sndrv_xferi snd_xferi_t; @@ -464,28 +463,6 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...) #endif -static inline void snd_timestamp_now(struct timespec *tstamp, int timespec) -{ - struct timeval val; - /* FIXME: use a linear time source */ - do_gettimeofday(&val); - tstamp->tv_sec = val.tv_sec; - tstamp->tv_nsec = val.tv_usec; - if (timespec) - tstamp->tv_nsec *= 1000L; -} - -static inline void snd_timestamp_zero(struct timespec *tstamp) -{ - tstamp->tv_sec = 0; - tstamp->tv_nsec = 0; -} - -static inline int snd_timestamp_null(struct timespec *tstamp) -{ - return tstamp->tv_sec == 0 && tstamp->tv_nsec == 0; -} - #define SNDRV_OSS_VERSION ((3<<16)|(8<<8)|(1<<4)|(0)) /* 3.8.1a */ /* for easier backward-porting */ diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 2b23a596707..acc4fa9d5ab 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -281,7 +281,7 @@ typedef struct { struct _snd_pcm_runtime { /* -- Status -- */ snd_pcm_substream_t *trigger_master; - snd_timestamp_t trigger_tstamp; /* trigger timestamp */ + struct timespec trigger_tstamp; /* trigger timestamp */ int overrange; snd_pcm_uframes_t avail_max; snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */ @@ -306,7 +306,6 @@ struct _snd_pcm_runtime { unsigned int rate_den; /* -- SW params -- */ - int tstamp_timespec; /* use timeval (0) or timespec (1) */ snd_pcm_tstamp_t tstamp_mode; /* mmap timestamp is updated */ unsigned int period_step; unsigned int sleep_min; /* min ticks to sleep */ diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index dfc5f45f274..3dbf9bf2ac1 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -152,7 +152,7 @@ static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(snd_pcm_substream_t *s if (pos == SNDRV_PCM_POS_XRUN) return pos; /* XRUN */ if (runtime->tstamp_mode & SNDRV_PCM_TSTAMP_MMAP) - snd_timestamp_now((snd_timestamp_t*)&runtime->status->tstamp, runtime->tstamp_timespec); + getnstimeofday((struct timespec *)&runtime->status->tstamp); #ifdef CONFIG_SND_DEBUG if (pos >= runtime->buffer_size) { snd_printk(KERN_ERR "BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size); diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index e6e2b70314c..a1924f12d8f 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -565,9 +565,9 @@ int snd_pcm_status(snd_pcm_substream_t *substream, if (runtime->tstamp_mode & SNDRV_PCM_TSTAMP_MMAP) status->tstamp = runtime->status->tstamp; else - snd_timestamp_now(&status->tstamp, runtime->tstamp_timespec); + getnstimeofday(&status->tstamp); } else - snd_timestamp_now(&status->tstamp, runtime->tstamp_timespec); + getnstimeofday(&status->tstamp); status->appl_ptr = runtime->control->appl_ptr; status->hw_ptr = runtime->status->hw_ptr; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { @@ -652,7 +652,7 @@ static void snd_pcm_trigger_tstamp(snd_pcm_substream_t *substream) if (runtime->trigger_master == NULL) return; if (runtime->trigger_master == substream) { - snd_timestamp_now(&runtime->trigger_tstamp, runtime->tstamp_timespec); + getnstimeofday(&runtime->trigger_tstamp); } else { snd_pcm_trigger_tstamp(runtime->trigger_master); runtime->trigger_tstamp = runtime->trigger_master->runtime->trigger_tstamp; @@ -2446,14 +2446,8 @@ static int snd_pcm_common_ioctl1(snd_pcm_substream_t *substream, return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0; case SNDRV_PCM_IOCTL_INFO: return snd_pcm_info_user(substream, arg); - case SNDRV_PCM_IOCTL_TSTAMP: - { - int xarg; - if (get_user(xarg, (int __user *)arg)) - return -EFAULT; - substream->runtime->tstamp_timespec = xarg ? 1 : 0; + case SNDRV_PCM_IOCTL_TSTAMP: /* just for compatibility */ return 0; - } case SNDRV_PCM_IOCTL_HW_REFINE: return snd_pcm_hw_refine_user(substream, arg); case SNDRV_PCM_IOCTL_HW_PARAMS: diff --git a/sound/core/timer.c b/sound/core/timer.c index 128916c6608..8ecec9134ac 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -385,7 +385,7 @@ static void snd_timer_notify1(snd_timer_instance_t *ti, enum sndrv_timer_event e struct list_head *n; struct timespec tstamp; - snd_timestamp_now(&tstamp, 1); + getnstimeofday(&tstamp); snd_assert(event >= SNDRV_TIMER_EVENT_START && event <= SNDRV_TIMER_EVENT_PAUSE, return); if (event == SNDRV_TIMER_EVENT_START || event == SNDRV_TIMER_EVENT_CONTINUE) resolution = snd_timer_resolution(ti); @@ -1156,14 +1156,14 @@ static void snd_timer_user_tinterrupt(snd_timer_instance_t *timeri, struct timespec tstamp; int prev, append = 0; - snd_timestamp_zero(&tstamp); + memset(&tstamp, 0, sizeof(tstamp)); spin_lock(&tu->qlock); if ((tu->filter & ((1 << SNDRV_TIMER_EVENT_RESOLUTION)|(1 << SNDRV_TIMER_EVENT_TICK))) == 0) { spin_unlock(&tu->qlock); return; } if (tu->last_resolution != resolution || ticks > 0) - snd_timestamp_now(&tstamp, 1); + getnstimeofday(&tstamp); if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) && tu->last_resolution != resolution) { r1.event = SNDRV_TIMER_EVENT_RESOLUTION; r1.tstamp = tstamp; -- cgit v1.2.3 From 93f2e37840a9a7c3693ca6961fe6ad46b250f3b9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 10 Oct 2005 11:51:55 +0200 Subject: [ALSA] Make snd_task_name() module local Modules: ALSA Core,ALSA<-OSS emulation Remove a global function snd_task_name(), and move it local to snd-pcm-oss module. Signed-off-by: Takashi Iwai --- include/sound/core.h | 1 - sound/core/misc.c | 11 ----------- sound/core/oss/pcm_oss.c | 11 +++++++++++ sound/core/sound.c | 1 - 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/include/sound/core.h b/include/sound/core.h index fa8f4c9492c..af314205635 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -373,7 +373,6 @@ unsigned int snd_dma_pointer(unsigned long dma, unsigned int size); /* misc.c */ -int snd_task_name(struct task_struct *task, char *name, size_t size); #ifdef CONFIG_SND_VERBOSE_PRINTK void snd_verbose_printk(const char *file, int line, const char *format, ...) __attribute__ ((format (printf, 3, 4))); diff --git a/sound/core/misc.c b/sound/core/misc.c index 1a81fe4df21..11a7675b719 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c @@ -25,17 +25,6 @@ #include #include -int snd_task_name(struct task_struct *task, char *name, size_t size) -{ - unsigned int idx; - - snd_assert(task != NULL && name != NULL && size >= 2, return -EINVAL); - for (idx = 0; idx < sizeof(task->comm) && idx + 1 < size; idx++) - name[idx] = task->comm[idx]; - name[idx] = '\0'; - return 0; -} - #ifdef CONFIG_SND_VERBOSE_PRINTK void snd_verbose_printk(const char *file, int line, const char *format, ...) { diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 842c28b2ed5..c57f702d31a 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -1821,6 +1821,17 @@ static int snd_pcm_oss_open_file(struct file *file, } +static int snd_task_name(struct task_struct *task, char *name, size_t size) +{ + unsigned int idx; + + snd_assert(task != NULL && name != NULL && size >= 2, return -EINVAL); + for (idx = 0; idx < sizeof(task->comm) && idx + 1 < size; idx++) + name[idx] = task->comm[idx]; + name[idx] = '\0'; + return 0; +} + static int snd_pcm_oss_open(struct inode *inode, struct file *file) { int minor = iminor(inode); diff --git a/sound/core/sound.c b/sound/core/sound.c index b57519a3e3d..bc8ad001798 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -487,7 +487,6 @@ EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat); EXPORT_SYMBOL(snd_ctl_elem_read); EXPORT_SYMBOL(snd_ctl_elem_write); /* misc.c */ -EXPORT_SYMBOL(snd_task_name); #ifdef CONFIG_SND_VERBOSE_PRINTK EXPORT_SYMBOL(snd_verbose_printk); #endif -- cgit v1.2.3 From b1d5776d865951c213a1caaab5d8bf5de7615dbd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 10 Oct 2005 11:56:31 +0200 Subject: [ALSA] Remove vmalloc wrapper, kfree_nocheck() - Remove vmalloc wrapper - Add release_and_free_resource() to remove kfree_nocheck() from each driver and simplify the code Signed-off-by: Takashi Iwai --- .../sound/alsa/DocBook/writing-an-alsa-driver.tmpl | 17 +------ include/sound/core.h | 9 +--- include/sound/driver.h | 4 -- sound/core/memory.c | 53 ---------------------- sound/core/misc.c | 9 ++++ sound/core/sound.c | 5 +- sound/core/wrappers.c | 10 ---- sound/drivers/mpu401/mpu401_uart.c | 5 +- sound/drivers/mtpav.c | 5 +- sound/drivers/opl3/opl3_lib.c | 10 +--- sound/drivers/opl4/opl4_lib.c | 10 +--- sound/drivers/serial-u16550.c | 5 +- sound/drivers/vx/vx_pcm.c | 4 +- sound/isa/ad1816a/ad1816a_lib.c | 5 +- sound/isa/ad1848/ad1848_lib.c | 5 +- sound/isa/cs423x/cs4231_lib.c | 10 +--- sound/isa/cs423x/cs4236.c | 8 +--- sound/isa/es1688/es1688_lib.c | 3 +- sound/isa/es18xx.c | 15 ++---- sound/isa/gus/gus_main.c | 10 +--- sound/isa/gus/interwave.c | 5 +- sound/isa/opl3sa2.c | 5 +- sound/isa/opti9xx/opti92x-ad1848.c | 25 +++------- sound/isa/sb/emu8000.c | 15 ++---- sound/isa/sb/sb16.c | 5 +- sound/isa/sb/sb8.c | 5 +- sound/isa/sb/sb_common.c | 6 +-- sound/isa/sscape.c | 6 +-- sound/isa/wavefront/wavefront.c | 5 +- sound/mips/au1x00.c | 3 +- sound/pci/als4000.c | 6 +-- sound/pci/azt3328.c | 6 +-- sound/pci/ca0106/ca0106_main.c | 6 +-- sound/pci/cmipci.c | 6 +-- sound/pci/cs46xx/cs46xx_lib.c | 5 +- sound/pci/emu10k1/emu10k1x.c | 6 +-- sound/pci/es1968.c | 6 +-- sound/pci/nm256/nm256.c | 10 +--- sound/pci/sonicvibes.c | 10 +--- sound/pci/via82xx.c | 11 ++--- sound/pci/ymfpci/ymfpci.c | 16 ++----- sound/pci/ymfpci/ymfpci_main.c | 15 ++---- sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c | 6 +-- sound/usb/usbaudio.c | 6 +-- 44 files changed, 86 insertions(+), 311 deletions(-) diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index ab3dfe074fb..05ae29ac898 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -1433,25 +1433,10 @@ res_port) { - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); - } + release_and_free_resource(chip->res_port); ]]> - - As you can see, the resource pointer is also to be freed - via kfree_nocheck() after - release_resource() is called. You - cannot use kfree() here, because on ALSA, - kfree() may be a wrapper to its own - allocator with the memory debugging. Since the resource pointer - is allocated externally outside the ALSA, it must be released - via the native - kfree(). - kfree_nocheck() is used for that; it calls - the native kfree() without wrapper.
diff --git a/include/sound/core.h b/include/sound/core.h index af314205635..0a14885fb1d 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -293,19 +293,13 @@ void *snd_hidden_kmalloc(size_t size, gfp_t flags); void *snd_hidden_kzalloc(size_t size, gfp_t flags); void *snd_hidden_kcalloc(size_t n, size_t size, gfp_t flags); void snd_hidden_kfree(const void *obj); -void *snd_hidden_vmalloc(unsigned long size); -void snd_hidden_vfree(void *obj); char *snd_hidden_kstrdup(const char *s, gfp_t flags); #define kmalloc(size, flags) snd_hidden_kmalloc(size, flags) #define kzalloc(size, flags) snd_hidden_kzalloc(size, flags) #define kcalloc(n, size, flags) snd_hidden_kcalloc(n, size, flags) #define kfree(obj) snd_hidden_kfree(obj) -#define vmalloc(size) snd_hidden_vmalloc(size) -#define vfree(obj) snd_hidden_vfree(obj) #define kmalloc_nocheck(size, flags) snd_wrapper_kmalloc(size, flags) -#define vmalloc_nocheck(size) snd_wrapper_vmalloc(size) #define kfree_nocheck(obj) snd_wrapper_kfree(obj) -#define vfree_nocheck(obj) snd_wrapper_vfree(obj) #define kstrdup(s, flags) snd_hidden_kstrdup(s, flags) #else #define snd_memory_init() /*NOP*/ @@ -313,9 +307,7 @@ char *snd_hidden_kstrdup(const char *s, gfp_t flags); #define snd_memory_info_init() /*NOP*/ #define snd_memory_info_done() /*NOP*/ #define kmalloc_nocheck(size, flags) kmalloc(size, flags) -#define vmalloc_nocheck(size) vmalloc(size) #define kfree_nocheck(obj) kfree(obj) -#define vfree_nocheck(obj) vfree(obj) #endif int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count); int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count); @@ -372,6 +364,7 @@ unsigned int snd_dma_pointer(unsigned long dma, unsigned int size); #endif /* misc.c */ +void release_and_free_resource(struct resource *res); #ifdef CONFIG_SND_VERBOSE_PRINTK void snd_verbose_printk(const char *file, int line, const char *format, ...) diff --git a/include/sound/driver.h b/include/sound/driver.h index 1ec2fae050a..7973e0c05ae 100644 --- a/include/sound/driver.h +++ b/include/sound/driver.h @@ -55,10 +55,6 @@ void *snd_wrapper_kmalloc(size_t, gfp_t); #undef kmalloc void snd_wrapper_kfree(const void *); #undef kfree -void *snd_wrapper_vmalloc(size_t); -#undef vmalloc -void snd_wrapper_vfree(void *); -#undef vfree #endif #endif /* __SOUND_DRIVER_H */ diff --git a/sound/core/memory.c b/sound/core/memory.c index 7d8e2eebba5..b99343616f8 100644 --- a/sound/core/memory.c +++ b/sound/core/memory.c @@ -47,19 +47,14 @@ struct snd_alloc_track { #define snd_alloc_track_entry(obj) (struct snd_alloc_track *)((char*)obj - (unsigned long)((struct snd_alloc_track *)0)->data) static long snd_alloc_kmalloc; -static long snd_alloc_vmalloc; static LIST_HEAD(snd_alloc_kmalloc_list); -static LIST_HEAD(snd_alloc_vmalloc_list); static DEFINE_SPINLOCK(snd_alloc_kmalloc_lock); -static DEFINE_SPINLOCK(snd_alloc_vmalloc_lock); #define KMALLOC_MAGIC 0x87654321 -#define VMALLOC_MAGIC 0x87654320 static snd_info_entry_t *snd_memory_info_entry; void __init snd_memory_init(void) { snd_alloc_kmalloc = 0; - snd_alloc_vmalloc = 0; } void snd_memory_done(void) @@ -69,8 +64,6 @@ void snd_memory_done(void) if (snd_alloc_kmalloc > 0) snd_printk(KERN_ERR "Not freed snd_alloc_kmalloc = %li\n", snd_alloc_kmalloc); - if (snd_alloc_vmalloc > 0) - snd_printk(KERN_ERR "Not freed snd_alloc_vmalloc = %li\n", snd_alloc_vmalloc); list_for_each_prev(head, &snd_alloc_kmalloc_list) { t = list_entry(head, struct snd_alloc_track, list); if (t->magic != KMALLOC_MAGIC) { @@ -79,14 +72,6 @@ void snd_memory_done(void) } snd_printk(KERN_ERR "kmalloc(%ld) from %p not freed\n", (long) t->size, t->caller); } - list_for_each_prev(head, &snd_alloc_vmalloc_list) { - t = list_entry(head, struct snd_alloc_track, list); - if (t->magic != VMALLOC_MAGIC) { - snd_printk(KERN_ERR "Corrupted vmalloc\n"); - break; - } - snd_printk(KERN_ERR "vmalloc(%ld) from %p not freed\n", (long) t->size, t->caller); - } } static void *__snd_kmalloc(size_t size, gfp_t flags, void *caller) @@ -153,43 +138,6 @@ void snd_hidden_kfree(const void *obj) snd_wrapper_kfree(obj); } -void *snd_hidden_vmalloc(unsigned long size) -{ - void *ptr; - ptr = snd_wrapper_vmalloc(size + sizeof(struct snd_alloc_track)); - if (ptr) { - struct snd_alloc_track *t = (struct snd_alloc_track *)ptr; - t->magic = VMALLOC_MAGIC; - t->caller = __builtin_return_address(0); - spin_lock(&snd_alloc_vmalloc_lock); - list_add_tail(&t->list, &snd_alloc_vmalloc_list); - spin_unlock(&snd_alloc_vmalloc_lock); - t->size = size; - snd_alloc_vmalloc += size; - ptr = t->data; - } - return ptr; -} - -void snd_hidden_vfree(void *obj) -{ - struct snd_alloc_track *t; - if (obj == NULL) - return; - t = snd_alloc_track_entry(obj); - if (t->magic != VMALLOC_MAGIC) { - snd_printk(KERN_ERR "bad vfree (called from %p)\n", __builtin_return_address(0)); - return; - } - spin_lock(&snd_alloc_vmalloc_lock); - list_del(&t->list); - spin_unlock(&snd_alloc_vmalloc_lock); - t->magic = 0; - snd_alloc_vmalloc -= t->size; - obj = t; - snd_wrapper_vfree(obj); -} - char *snd_hidden_kstrdup(const char *s, gfp_t flags) { int len; @@ -207,7 +155,6 @@ char *snd_hidden_kstrdup(const char *s, gfp_t flags) static void snd_memory_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer) { snd_iprintf(buffer, "kmalloc: %li bytes\n", snd_alloc_kmalloc); - snd_iprintf(buffer, "vmalloc: %li bytes\n", snd_alloc_vmalloc); } int __init snd_memory_info_init(void) diff --git a/sound/core/misc.c b/sound/core/misc.c index 11a7675b719..3eddfdede9f 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c @@ -23,8 +23,17 @@ #include #include #include +#include #include +void release_and_free_resource(struct resource *res) +{ + if (res) { + release_resource(res); + kfree_nocheck(res); + } +} + #ifdef CONFIG_SND_VERBOSE_PRINTK void snd_verbose_printk(const char *file, int line, const char *format, ...) { diff --git a/sound/core/sound.c b/sound/core/sound.c index bc8ad001798..e94eebd8ad6 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -407,8 +407,6 @@ EXPORT_SYMBOL(snd_unregister_oss_device); EXPORT_SYMBOL(snd_hidden_kmalloc); EXPORT_SYMBOL(snd_hidden_kcalloc); EXPORT_SYMBOL(snd_hidden_kfree); -EXPORT_SYMBOL(snd_hidden_vmalloc); -EXPORT_SYMBOL(snd_hidden_vfree); EXPORT_SYMBOL(snd_hidden_kstrdup); #endif EXPORT_SYMBOL(copy_to_user_fromio); @@ -487,6 +485,7 @@ EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat); EXPORT_SYMBOL(snd_ctl_elem_read); EXPORT_SYMBOL(snd_ctl_elem_write); /* misc.c */ +EXPORT_SYMBOL(release_and_free_resource); #ifdef CONFIG_SND_VERBOSE_PRINTK EXPORT_SYMBOL(snd_verbose_printk); #endif @@ -497,6 +496,4 @@ EXPORT_SYMBOL(snd_verbose_printd); #ifdef CONFIG_SND_DEBUG_MEMORY EXPORT_SYMBOL(snd_wrapper_kmalloc); EXPORT_SYMBOL(snd_wrapper_kfree); -EXPORT_SYMBOL(snd_wrapper_vmalloc); -EXPORT_SYMBOL(snd_wrapper_vfree); #endif diff --git a/sound/core/wrappers.c b/sound/core/wrappers.c index 296b716f137..19e899089cb 100644 --- a/sound/core/wrappers.c +++ b/sound/core/wrappers.c @@ -36,15 +36,5 @@ void snd_wrapper_kfree(const void *obj) { kfree(obj); } - -void *snd_wrapper_vmalloc(unsigned long size) -{ - return vmalloc(size); -} - -void snd_wrapper_vfree(void *obj) -{ - vfree(obj); -} #endif diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c index fe3f921ffbe..bdeb2c00dac 100644 --- a/sound/drivers/mpu401/mpu401_uart.c +++ b/sound/drivers/mpu401/mpu401_uart.c @@ -423,10 +423,7 @@ static void snd_mpu401_uart_free(snd_rawmidi_t *rmidi) mpu401_t *mpu = rmidi->private_data; if (mpu->irq_flags && mpu->irq >= 0) free_irq(mpu->irq, (void *) mpu); - if (mpu->res) { - release_resource(mpu->res); - kfree_nocheck(mpu->res); - } + release_and_free_resource(mpu->res); kfree(mpu); } diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c index 3a25c89d298..e9d52c668ed 100644 --- a/sound/drivers/mtpav.c +++ b/sound/drivers/mtpav.c @@ -717,10 +717,7 @@ static void free_mtpav(mtpav_t * crd) spin_unlock_irqrestore(&crd->spinlock, flags); if (crd->irq >= 0) free_irq(crd->irq, (void *)crd); - if (crd->res_port) { - release_resource(crd->res_port); - kfree_nocheck(crd->res_port); - } + release_and_free_resource(crd->res_port); kfree(crd); } diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c index 1f84d78260d..06246503083 100644 --- a/sound/drivers/opl3/opl3_lib.c +++ b/sound/drivers/opl3/opl3_lib.c @@ -325,14 +325,8 @@ static int snd_opl3_free(opl3_t *opl3) snd_assert(opl3 != NULL, return -ENXIO); if (opl3->private_free) opl3->private_free(opl3); - if (opl3->res_l_port) { - release_resource(opl3->res_l_port); - kfree_nocheck(opl3->res_l_port); - } - if (opl3->res_r_port) { - release_resource(opl3->res_r_port); - kfree_nocheck(opl3->res_r_port); - } + release_and_free_resource(opl3->res_l_port); + release_and_free_resource(opl3->res_r_port); kfree(opl3); return 0; } diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c index 380c2c704c5..4ae5dd8f011 100644 --- a/sound/drivers/opl4/opl4_lib.c +++ b/sound/drivers/opl4/opl4_lib.c @@ -169,14 +169,8 @@ static void snd_opl4_free(opl4_t *opl4) #ifdef CONFIG_PROC_FS snd_opl4_free_proc(opl4); #endif - if (opl4->res_fm_port) { - release_resource(opl4->res_fm_port); - kfree_nocheck(opl4->res_fm_port); - } - if (opl4->res_pcm_port) { - release_resource(opl4->res_pcm_port); - kfree_nocheck(opl4->res_pcm_port); - } + release_and_free_resource(opl4->res_fm_port); + release_and_free_resource(opl4->res_pcm_port); kfree(opl4); } diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index 416172ea1f4..1ed58df4267 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c @@ -749,10 +749,7 @@ static int snd_uart16550_free(snd_uart16550_t *uart) { if (uart->irq >= 0) free_irq(uart->irq, (void *)uart); - if (uart->res_base) { - release_resource(uart->res_base); - kfree_nocheck(uart->res_base); - } + release_and_free_resource(uart->res_base); kfree(uart); return 0; }; diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c index c2312d912fc..2b46758fe86 100644 --- a/sound/drivers/vx/vx_pcm.c +++ b/sound/drivers/vx/vx_pcm.c @@ -79,7 +79,7 @@ static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t *subs, size_t size) /* already allocated */ if (runtime->dma_bytes >= size) return 0; /* already enough large */ - vfree_nocheck(runtime->dma_area); /* bypass the memory wrapper */ + vfree(runtime->dma_area); } runtime->dma_area = vmalloc_32(size); if (! runtime->dma_area) @@ -98,7 +98,7 @@ static int snd_pcm_free_vmalloc_buffer(snd_pcm_substream_t *subs) { snd_pcm_runtime_t *runtime = subs->runtime; if (runtime->dma_area) { - vfree_nocheck(runtime->dma_area); /* bypass the memory wrapper */ + vfree(runtime->dma_area); runtime->dma_area = NULL; } return 0; diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c index 27a9dcfbba0..7ae02396cae 100644 --- a/sound/isa/ad1816a/ad1816a_lib.c +++ b/sound/isa/ad1816a/ad1816a_lib.c @@ -542,10 +542,7 @@ static int snd_ad1816a_probe(ad1816a_t *chip) static int snd_ad1816a_free(ad1816a_t *chip) { - if (chip->res_port) { - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); - } + release_and_free_resource(chip->res_port); if (chip->irq >= 0) free_irq(chip->irq, (void *) chip); if (chip->dma1 >= 0) { diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c index 303861cd03c..0c2924dfefa 100644 --- a/sound/isa/ad1848/ad1848_lib.c +++ b/sound/isa/ad1848/ad1848_lib.c @@ -846,10 +846,7 @@ static int snd_ad1848_capture_close(snd_pcm_substream_t * substream) static int snd_ad1848_free(ad1848_t *chip) { - if (chip->res_port) { - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); - } + release_and_free_resource(chip->res_port); if (chip->irq >= 0) free_irq(chip->irq, (void *) chip); if (chip->dma >= 0) { diff --git a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c index 32318258cd8..4af769030be 100644 --- a/sound/isa/cs423x/cs4231_lib.c +++ b/sound/isa/cs423x/cs4231_lib.c @@ -1417,14 +1417,8 @@ static int snd_cs4231_pm_resume(snd_card_t *card) static int snd_cs4231_free(cs4231_t *chip) { - if (chip->res_port) { - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); - } - if (chip->res_cport) { - release_resource(chip->res_cport); - kfree_nocheck(chip->res_cport); - } + release_and_free_resource(chip->res_port); + release_and_free_resource(chip->res_cport); if (chip->irq >= 0) { disable_irq(chip->irq); if (!(chip->hwshare & CS4231_HWSHARE_IRQ)) diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index d28315dc72f..d60a55e6a0b 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c @@ -379,12 +379,8 @@ static void snd_card_cs4236_free(snd_card_t *card) { struct snd_card_cs4236 *acard = (struct snd_card_cs4236 *)card->private_data; - if (acard) { - if (acard->res_sb_port) { - release_resource(acard->res_sb_port); - kfree_nocheck(acard->res_sb_port); - } - } + if (acard) + release_and_free_resource(acard->res_sb_port); } #ifdef CONFIG_PNP diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c index aac898765c0..2edc9c9f044 100644 --- a/sound/isa/es1688/es1688_lib.c +++ b/sound/isa/es1688/es1688_lib.c @@ -606,8 +606,7 @@ static int snd_es1688_free(es1688_t *chip) { if (chip->res_port) { snd_es1688_init(chip, 0); - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); + release_and_free_resource(chip->res_port); } if (chip->irq >= 0) free_irq(chip->irq, (void *) chip); diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index d0ea19f4270..f0f8505cd1a 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -1640,18 +1640,9 @@ static int snd_es18xx_resume(snd_card_t *card) static int snd_es18xx_free(es18xx_t *chip) { - if (chip->res_port) { - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); - } - if (chip->res_ctrl_port) { - release_resource(chip->res_ctrl_port); - kfree_nocheck(chip->res_ctrl_port); - } - if (chip->res_mpu_port) { - release_resource(chip->res_mpu_port); - kfree_nocheck(chip->res_mpu_port); - } + release_and_free_resource(chip->res_port); + release_and_free_resource(chip->res_ctrl_port); + release_and_free_resource(chip->res_mpu_port); if (chip->irq >= 0) free_irq(chip->irq, (void *) chip); if (chip->dma1 >= 0) { diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c index 8f2872f8e8f..5fd374f052e 100644 --- a/sound/isa/gus/gus_main.c +++ b/sound/isa/gus/gus_main.c @@ -113,14 +113,8 @@ static int snd_gus_free(snd_gus_card_t *gus) snd_gf1_stop(gus); snd_gus_init_dma_irq(gus, 0); __hw_end: - if (gus->gf1.res_port1) { - release_resource(gus->gf1.res_port1); - kfree_nocheck(gus->gf1.res_port1); - } - if (gus->gf1.res_port2) { - release_resource(gus->gf1.res_port2); - kfree_nocheck(gus->gf1.res_port2); - } + release_and_free_resource(gus->gf1.res_port1); + release_and_free_resource(gus->gf1.res_port2); if (gus->gf1.irq >= 0) free_irq(gus->gf1.irq, (void *) gus); if (gus->gf1.dma1 >= 0) { diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index 358cba9d738..b101ab0a0db 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c @@ -638,10 +638,7 @@ static void snd_interwave_free(snd_card_t *card) if (iwcard == NULL) return; #ifdef SNDRV_STB - if (iwcard->i2c_res) { - release_resource(iwcard->i2c_res); - kfree_nocheck(iwcard->i2c_res); - } + release_and_free_resource(iwcard->i2c_res); #endif if (iwcard->irq >= 0) free_irq(iwcard->irq, (void *)iwcard); diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index 4ba268f251e..47cabda792b 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -656,10 +656,7 @@ static int snd_opl3sa2_free(opl3sa2_t *chip) { if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); - if (chip->res_port) { - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); - } + release_and_free_resource(chip->res_port); kfree(chip); return 0; } diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 73573cb1db6..b94339f8306 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -299,10 +299,8 @@ static char * snd_opti9xx_names[] = { static long snd_legacy_find_free_ioport(long *port_table, long size) { while (*port_table != -1) { - struct resource *res; - if ((res = request_region(*port_table, size, "ALSA test")) != NULL) { - release_resource(res); - kfree_nocheck(res); + if (request_region(*port_table, size, "ALSA test")) { + release_region(*port_table, size); return *port_table; } port_table++; @@ -1227,10 +1225,7 @@ static int snd_opti93x_probe(opti93x_t *chip) static int snd_opti93x_free(opti93x_t *chip) { - if (chip->res_port) { - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); - } + release_and_free_resource(chip->res_port); if (chip->dma1 >= 0) { disable_dma(chip->dma1); free_dma(chip->dma1); @@ -1656,8 +1651,7 @@ static int __devinit snd_card_opti9xx_detect(snd_card_t *card, opti9xx_t *chip) if (value == snd_opti9xx_read(chip, OPTi9XX_MC_REG(1))) return 1; - release_resource(chip->res_mc_base); - kfree_nocheck(chip->res_mc_base); + release_and_free_resource(chip->res_mc_base); chip->res_mc_base = NULL; } @@ -1683,8 +1677,7 @@ static int __devinit snd_card_opti9xx_detect(snd_card_t *card, opti9xx_t *chip) if (snd_opti9xx_read(chip, OPTi9XX_MC_REG(7)) == 0xff - value) return 1; - release_resource(chip->res_mc_base); - kfree_nocheck(chip->res_mc_base); + release_and_free_resource(chip->res_mc_base); chip->res_mc_base = NULL; } #endif /* OPTi93X */ @@ -1886,12 +1879,8 @@ static void snd_card_opti9xx_free(snd_card_t *card) { opti9xx_t *chip = (opti9xx_t *)card->private_data; - if (chip) { - if (chip->res_mc_base) { - release_resource(chip->res_mc_base); - kfree_nocheck(chip->res_mc_base); - } - } + if (chip) + release_and_free_resource(chip->res_mc_base); } static int snd_card_opti9xx_probe(struct pnp_card_link *pcard, diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c index 5375705c054..95540f13319 100644 --- a/sound/isa/sb/emu8000.c +++ b/sound/isa/sb/emu8000.c @@ -1054,18 +1054,9 @@ __error: */ static int snd_emu8000_free(emu8000_t *hw) { - if (hw->res_port1) { - release_resource(hw->res_port1); - kfree_nocheck(hw->res_port1); - } - if (hw->res_port2) { - release_resource(hw->res_port2); - kfree_nocheck(hw->res_port2); - } - if (hw->res_port3) { - release_resource(hw->res_port3); - kfree_nocheck(hw->res_port3); - } + release_and_free_resource(hw->res_port1); + release_and_free_resource(hw->res_port2); + release_and_free_resource(hw->res_port3); kfree(hw); return 0; } diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index 7888783d68f..c2fa451bc8f 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c @@ -345,10 +345,7 @@ static void snd_sb16_free(snd_card_t *card) if (acard == NULL) return; - if (acard->fm_res) { - release_resource(acard->fm_res); - kfree_nocheck(acard->fm_res); - } + release_and_free_resource(acard->fm_res); } #ifdef CONFIG_PNP diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c index c41ac25e85c..0bc0a3afdab 100644 --- a/sound/isa/sb/sb8.c +++ b/sound/isa/sb/sb8.c @@ -78,10 +78,7 @@ static void snd_sb8_free(snd_card_t *card) if (acard == NULL) return; - if (acard->fm_res) { - release_resource(acard->fm_res); - kfree_nocheck(acard->fm_res); - } + release_and_free_resource(acard->fm_res); } static int __init snd_sb8_probe(int dev) diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c index f0f205ae425..46b9480669f 100644 --- a/sound/isa/sb/sb_common.c +++ b/sound/isa/sb/sb_common.c @@ -178,10 +178,8 @@ static int snd_sbdsp_probe(sb_t * chip) static int snd_sbdsp_free(sb_t *chip) { - if (chip->res_port) { - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); - } + if (chip->res_port) + release_and_free_resource(chip->res_port); if (chip->irq >= 0) free_irq(chip->irq, (void *) chip); #ifdef CONFIG_ISA diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 9f6b58c7920..1036876146c 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -338,8 +338,7 @@ static inline void activate_ad1845_unsafe(unsigned io_base) static void soundscape_free(snd_card_t * c) { register struct soundscape *sscape = get_card_soundscape(c); - release_resource(sscape->io_res); - kfree_nocheck(sscape->io_res); + release_and_free_resource(sscape->io_res); free_dma(sscape->chip->dma1); } @@ -1288,8 +1287,7 @@ static int __devinit create_sscape(const struct params *params, snd_card_t **rca free_dma(params->dma1); _release_region: - release_resource(io_res); - kfree_nocheck(io_res); + release_and_free_resource(io_res); return err; } diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index 0a572e0a47e..1818f1013c3 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c @@ -379,10 +379,7 @@ snd_wavefront_free(snd_card_t *card) snd_wavefront_card_t *acard = (snd_wavefront_card_t *)card->private_data; if (acard) { - if (acard->wavefront.res_base != NULL) { - release_resource(acard->wavefront.res_base); - kfree_nocheck(acard->wavefront.res_base); - } + release_and_free_resource(acard->wavefront.res_base); if (acard->wavefront.irq > 0) free_irq(acard->wavefront.irq, (void *)acard); } diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c index 3f9684f1d1d..b7af85f5bfb 100644 --- a/sound/mips/au1x00.c +++ b/sound/mips/au1x00.c @@ -606,8 +606,7 @@ snd_au1000_free(snd_card_t *card) /* put internal AC97 block into reset */ au1000->ac97_ioport->cntrl = AC97C_RS; au1000->ac97_ioport = NULL; - release_resource(au1000->ac97_res_port); - kfree_nocheck(au1000->ac97_res_port); + release_and_free_resource(au1000->ac97_res_port); } if (au1000->stream[PLAYBACK]->dma >= 0) diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 196ec1c61bb..8a32cd92f62 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -594,8 +594,7 @@ static int __devinit snd_als4000_create_gameport(snd_card_als4000_t *acard, int acard->gameport = gp = gameport_allocate_port(); if (!gp) { printk(KERN_ERR "als4000: cannot allocate memory for gameport\n"); - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); return -ENOMEM; } @@ -622,8 +621,7 @@ static void snd_als4000_free_gameport(snd_card_als4000_t *acard) acard->gameport = NULL; snd_als4000_set_addr(acard->gcr, 0, 0, 0, 0); /* disable joystick */ - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); } } #else diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index d5261bdec58..dc638f395c0 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -1238,8 +1238,7 @@ static int __devinit snd_azf3328_config_joystick(azf3328_t *chip, int dev) chip->gameport = gp = gameport_allocate_port(); if (!gp) { printk(KERN_ERR "azt3328: cannot allocate memory for gameport\n"); - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); return -ENOMEM; } @@ -1267,8 +1266,7 @@ static void snd_azf3328_free_joystick(azf3328_t *chip) /* disable gameport */ snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR, snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY); - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); } } #else diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index ba07960921d..0d9d8923fbb 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -969,10 +969,8 @@ static int snd_ca0106_free(ca0106_t *chip) #endif // release the i/o port - if (chip->res_port) { - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); - } + release_and_free_resource(chip->res_port); + // release the irq if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 316afb78488..db093bca2cd 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -2683,8 +2683,7 @@ static int __devinit snd_cmipci_create_gameport(cmipci_t *cm, int dev) cm->gameport = gp = gameport_allocate_port(); if (!gp) { printk(KERN_ERR "cmipci: cannot allocate memory for gameport\n"); - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); return -ENOMEM; } gameport_set_name(gp, "C-Media Gameport"); @@ -2709,8 +2708,7 @@ static void snd_cmipci_free_gameport(cmipci_t *cm) cm->gameport = NULL; snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN); - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); } } #else diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 6e3855b8b33..147836f09dc 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -2906,10 +2906,7 @@ static int snd_cs46xx_free(cs46xx_t *chip) snd_cs46xx_region_t *region = &chip->region.idx[idx]; if (region->remap_addr) iounmap(region->remap_addr); - if (region->resource) { - release_resource(region->resource); - kfree_nocheck(region->resource); - } + release_and_free_resource(region->resource); } if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index ad15755a63c..cbb689474e7 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c @@ -759,10 +759,8 @@ static int snd_emu10k1x_free(emu10k1x_t *chip) outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG); // release the i/o port - if (chip->res_port) { - release_resource(chip->res_port); - kfree_nocheck(chip->res_port); - } + release_and_free_resource(chip->res_port); + // release the irq if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index ecdcada90ca..1bf094b6746 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -2461,8 +2461,7 @@ static int __devinit snd_es1968_create_gameport(es1968_t *chip, int dev) chip->gameport = gp = gameport_allocate_port(); if (!gp) { printk(KERN_ERR "es1968: cannot allocate memory for gameport\n"); - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); return -ENOMEM; } @@ -2488,8 +2487,7 @@ static void snd_es1968_free_gameport(es1968_t *chip) gameport_unregister_port(chip->gameport); chip->gameport = NULL; - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); } } #else diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 5c55a3b1d12..ebfa38b5112 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -1347,14 +1347,8 @@ static int snd_nm256_free(nm256_t *chip) iounmap(chip->cport); if (chip->buffer) iounmap(chip->buffer); - if (chip->res_cport) { - release_resource(chip->res_cport); - kfree_nocheck(chip->res_cport); - } - if (chip->res_buffer) { - release_resource(chip->res_buffer); - kfree_nocheck(chip->res_buffer); - } + release_and_free_resource(chip->res_cport); + release_and_free_resource(chip->res_buffer); if (chip->irq >= 0) free_irq(chip->irq, (void*)chip); diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 1f6c2bfd43f..4f64814dfef 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -1205,14 +1205,8 @@ static int snd_sonicvibes_free(sonicvibes_t *sonic) pci_write_config_dword(sonic->pci, 0x48, sonic->dmac_port); if (sonic->irq >= 0) free_irq(sonic->irq, (void *)sonic); - if (sonic->res_dmaa) { - release_resource(sonic->res_dmaa); - kfree_nocheck(sonic->res_dmaa); - } - if (sonic->res_dmac) { - release_resource(sonic->res_dmac); - kfree_nocheck(sonic->res_dmac); - } + release_and_free_resource(sonic->res_dmaa); + release_and_free_resource(sonic->res_dmac); pci_release_regions(sonic->pci); pci_disable_device(sonic->pci); kfree(sonic); diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index b2779fb7d1a..b0302c369c3 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -1655,8 +1655,7 @@ static int __devinit snd_via686_create_gameport(via82xx_t *chip, unsigned char * chip->gameport = gp = gameport_allocate_port(); if (!gp) { printk(KERN_ERR "via82xx: cannot allocate memory for gameport\n"); - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); return -ENOMEM; } @@ -1682,8 +1681,7 @@ static void snd_via686_free_gameport(via82xx_t *chip) gameport_unregister_port(chip->gameport); chip->gameport = NULL; - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); } } #else @@ -2023,10 +2021,7 @@ static int snd_via82xx_free(via82xx_t *chip) __end_hw: if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); - if (chip->mpu_res) { - release_resource(chip->mpu_res); - kfree_nocheck(chip->mpu_res); - } + release_and_free_resource(chip->mpu_res); pci_release_regions(chip->pci); if (chip->chip_type == TYPE_VIA686) { diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 2e69abe51aa..e50d744ae70 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c @@ -130,8 +130,7 @@ static int __devinit snd_ymfpci_create_gameport(ymfpci_t *chip, int dev, chip->gameport = gp = gameport_allocate_port(); if (!gp) { printk(KERN_ERR "ymfpci: cannot allocate memory for gameport\n"); - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); return -ENOMEM; } @@ -161,8 +160,7 @@ void snd_ymfpci_free_gameport(ymfpci_t *chip) gameport_unregister_port(chip->gameport); chip->gameport = NULL; - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); } } #else @@ -267,14 +265,8 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci, old_legacy_ctrl, &chip)) < 0) { snd_card_free(card); - if (mpu_res) { - release_resource(mpu_res); - kfree_nocheck(mpu_res); - } - if (fm_res) { - release_resource(fm_res); - kfree_nocheck(fm_res); - } + release_and_free_resource(mpu_res); + release_and_free_resource(fm_res); return err; } chip->fm_res = fm_res; diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 2e671ee438c..c0aaade772d 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -2151,14 +2151,8 @@ static int snd_ymfpci_free(ymfpci_t *chip) #ifdef CONFIG_PM vfree(chip->saved_regs); #endif - if (chip->mpu_res) { - release_resource(chip->mpu_res); - kfree_nocheck(chip->mpu_res); - } - if (chip->fm_res) { - release_resource(chip->fm_res); - kfree_nocheck(chip->fm_res); - } + release_and_free_resource(chip->mpu_res); + release_and_free_resource(chip->fm_res); snd_ymfpci_free_gameport(chip); if (chip->reg_area_virt) iounmap(chip->reg_area_virt); @@ -2167,10 +2161,7 @@ static int snd_ymfpci_free(ymfpci_t *chip) if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); - if (chip->res_reg_area) { - release_resource(chip->res_reg_area); - kfree_nocheck(chip->res_reg_area); - } + release_and_free_resource(chip->res_reg_area); pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl); diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c index 0a954dc11b7..20b86d8df7a 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c @@ -50,9 +50,9 @@ static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t *subs, size_t size) if (runtime->dma_area) { if (runtime->dma_bytes >= size) return 0; /* already enough large */ - vfree_nocheck(runtime->dma_area); + vfree(runtime->dma_area); } - runtime->dma_area = vmalloc_nocheck(size); + runtime->dma_area = vmalloc_32(size); if (! runtime->dma_area) return -ENOMEM; runtime->dma_bytes = size; @@ -67,7 +67,7 @@ static int snd_pcm_free_vmalloc_buffer(snd_pcm_substream_t *subs) { snd_pcm_runtime_t *runtime = subs->runtime; if (runtime->dma_area) { - vfree_nocheck(runtime->dma_area); + vfree(runtime->dma_area); runtime->dma_area = NULL; } return 0; diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 5429b169877..4589c637a25 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -692,9 +692,9 @@ static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t *subs, size_t size) if (runtime->dma_area) { if (runtime->dma_bytes >= size) return 0; /* already large enough */ - vfree_nocheck(runtime->dma_area); + vfree(runtime->dma_area); } - runtime->dma_area = vmalloc_nocheck(size); + runtime->dma_area = vmalloc(size); if (! runtime->dma_area) return -ENOMEM; runtime->dma_bytes = size; @@ -706,7 +706,7 @@ static int snd_pcm_free_vmalloc_buffer(snd_pcm_substream_t *subs) { snd_pcm_runtime_t *runtime = subs->runtime; if (runtime->dma_area) { - vfree_nocheck(runtime->dma_area); + vfree(runtime->dma_area); runtime->dma_area = NULL; } return 0; -- cgit v1.2.3 From e38e0cfa48ac38f4fe24453d2523852467c95b21 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 10 Oct 2005 11:59:52 +0200 Subject: [ALSA] Remove kmalloc wrappers Modules: ALSA Core Remove kmalloc wrappers. Signed-off-by: Takashi Iwai --- include/sound/core.h | 25 -------- include/sound/driver.h | 13 ---- sound/core/Kconfig | 6 -- sound/core/Makefile | 3 +- sound/core/info.c | 2 - sound/core/memory.c | 163 +------------------------------------------------ sound/core/misc.c | 2 +- sound/core/sound.c | 14 ----- 8 files changed, 4 insertions(+), 224 deletions(-) diff --git a/include/sound/core.h b/include/sound/core.h index 0a14885fb1d..ed56a356ab7 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -284,31 +284,6 @@ int snd_oss_init_module(void); /* memory.c */ -#ifdef CONFIG_SND_DEBUG_MEMORY -void snd_memory_init(void); -void snd_memory_done(void); -int snd_memory_info_init(void); -int snd_memory_info_done(void); -void *snd_hidden_kmalloc(size_t size, gfp_t flags); -void *snd_hidden_kzalloc(size_t size, gfp_t flags); -void *snd_hidden_kcalloc(size_t n, size_t size, gfp_t flags); -void snd_hidden_kfree(const void *obj); -char *snd_hidden_kstrdup(const char *s, gfp_t flags); -#define kmalloc(size, flags) snd_hidden_kmalloc(size, flags) -#define kzalloc(size, flags) snd_hidden_kzalloc(size, flags) -#define kcalloc(n, size, flags) snd_hidden_kcalloc(n, size, flags) -#define kfree(obj) snd_hidden_kfree(obj) -#define kmalloc_nocheck(size, flags) snd_wrapper_kmalloc(size, flags) -#define kfree_nocheck(obj) snd_wrapper_kfree(obj) -#define kstrdup(s, flags) snd_hidden_kstrdup(s, flags) -#else -#define snd_memory_init() /*NOP*/ -#define snd_memory_done() /*NOP*/ -#define snd_memory_info_init() /*NOP*/ -#define snd_memory_info_done() /*NOP*/ -#define kmalloc_nocheck(size, flags) kmalloc(size, flags) -#define kfree_nocheck(obj) kfree(obj) -#endif int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count); int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count); diff --git a/include/sound/driver.h b/include/sound/driver.h index 7973e0c05ae..3f0416ac24d 100644 --- a/include/sound/driver.h +++ b/include/sound/driver.h @@ -44,17 +44,4 @@ #include -/* - * ========================================================================== - */ - -#ifdef CONFIG_SND_DEBUG_MEMORY -#include -#include -void *snd_wrapper_kmalloc(size_t, gfp_t); -#undef kmalloc -void snd_wrapper_kfree(const void *); -#undef kfree -#endif - #endif /* __SOUND_DRIVER_H */ diff --git a/sound/core/Kconfig b/sound/core/Kconfig index 48cf45cfd0b..82718836f93 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig @@ -127,12 +127,6 @@ config SND_DEBUG help Say Y here to enable ALSA debug code. -config SND_DEBUG_MEMORY - bool "Debug memory" - depends on SND_DEBUG - help - Say Y here to enable debugging of memory allocations. - config SND_DEBUG_DETECT bool "Debug detection" depends on SND_DEBUG diff --git a/sound/core/Makefile b/sound/core/Makefile index 969d75528bd..5a01c76d02e 100644 --- a/sound/core/Makefile +++ b/sound/core/Makefile @@ -3,8 +3,7 @@ # Copyright (c) 1999,2001 by Jaroslav Kysela # -snd-objs := sound.o init.o memory.o info.o control.o misc.o \ - device.o wrappers.o +snd-objs := sound.o init.o memory.o info.o control.o misc.o device.o ifeq ($(CONFIG_ISA_DMA_API),y) snd-objs += isadma.o endif diff --git a/sound/core/info.c b/sound/core/info.c index 37024d68a26..39f9b97d921 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -566,7 +566,6 @@ int __init snd_info_init(void) } #endif snd_info_version_init(); - snd_memory_info_init(); snd_minor_info_init(); snd_minor_info_oss_init(); snd_card_info_init(); @@ -578,7 +577,6 @@ int __exit snd_info_done(void) snd_card_info_done(); snd_minor_info_oss_done(); snd_minor_info_done(); - snd_memory_info_done(); snd_info_version_done(); if (snd_proc_root) { #if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) diff --git a/sound/core/memory.c b/sound/core/memory.c index b99343616f8..862d62d2e14 100644 --- a/sound/core/memory.c +++ b/sound/core/memory.c @@ -1,7 +1,7 @@ /* * Copyright (c) by Jaroslav Kysela * - * Memory allocation helpers. + * Misc memory accessors * * * This program is free software; you can redistribute it and/or modify @@ -20,168 +20,9 @@ * */ -#include +#include #include #include -#include -#include -#include -#include -#include -#include - -/* - * memory allocation helpers and debug routines - */ - -#ifdef CONFIG_SND_DEBUG_MEMORY - -struct snd_alloc_track { - unsigned long magic; - void *caller; - size_t size; - struct list_head list; - long data[0]; -}; - -#define snd_alloc_track_entry(obj) (struct snd_alloc_track *)((char*)obj - (unsigned long)((struct snd_alloc_track *)0)->data) - -static long snd_alloc_kmalloc; -static LIST_HEAD(snd_alloc_kmalloc_list); -static DEFINE_SPINLOCK(snd_alloc_kmalloc_lock); -#define KMALLOC_MAGIC 0x87654321 -static snd_info_entry_t *snd_memory_info_entry; - -void __init snd_memory_init(void) -{ - snd_alloc_kmalloc = 0; -} - -void snd_memory_done(void) -{ - struct list_head *head; - struct snd_alloc_track *t; - - if (snd_alloc_kmalloc > 0) - snd_printk(KERN_ERR "Not freed snd_alloc_kmalloc = %li\n", snd_alloc_kmalloc); - list_for_each_prev(head, &snd_alloc_kmalloc_list) { - t = list_entry(head, struct snd_alloc_track, list); - if (t->magic != KMALLOC_MAGIC) { - snd_printk(KERN_ERR "Corrupted kmalloc\n"); - break; - } - snd_printk(KERN_ERR "kmalloc(%ld) from %p not freed\n", (long) t->size, t->caller); - } -} - -static void *__snd_kmalloc(size_t size, gfp_t flags, void *caller) -{ - unsigned long cpu_flags; - struct snd_alloc_track *t; - void *ptr; - - ptr = snd_wrapper_kmalloc(size + sizeof(struct snd_alloc_track), flags); - if (ptr != NULL) { - t = (struct snd_alloc_track *)ptr; - t->magic = KMALLOC_MAGIC; - t->caller = caller; - spin_lock_irqsave(&snd_alloc_kmalloc_lock, cpu_flags); - list_add_tail(&t->list, &snd_alloc_kmalloc_list); - spin_unlock_irqrestore(&snd_alloc_kmalloc_lock, cpu_flags); - t->size = size; - snd_alloc_kmalloc += size; - ptr = t->data; - } - return ptr; -} - -#define _snd_kmalloc(size, flags) __snd_kmalloc((size), (flags), __builtin_return_address(0)); -void *snd_hidden_kmalloc(size_t size, gfp_t flags) -{ - return _snd_kmalloc(size, flags); -} - -void *snd_hidden_kzalloc(size_t size, gfp_t flags) -{ - void *ret = _snd_kmalloc(size, flags); - if (ret) - memset(ret, 0, size); - return ret; -} -EXPORT_SYMBOL(snd_hidden_kzalloc); - -void *snd_hidden_kcalloc(size_t n, size_t size, gfp_t flags) -{ - void *ret = NULL; - if (n != 0 && size > INT_MAX / n) - return ret; - return snd_hidden_kzalloc(n * size, flags); -} - -void snd_hidden_kfree(const void *obj) -{ - unsigned long flags; - struct snd_alloc_track *t; - if (obj == NULL) - return; - t = snd_alloc_track_entry(obj); - if (t->magic != KMALLOC_MAGIC) { - snd_printk(KERN_WARNING "bad kfree (called from %p)\n", __builtin_return_address(0)); - return; - } - spin_lock_irqsave(&snd_alloc_kmalloc_lock, flags); - list_del(&t->list); - spin_unlock_irqrestore(&snd_alloc_kmalloc_lock, flags); - t->magic = 0; - snd_alloc_kmalloc -= t->size; - obj = t; - snd_wrapper_kfree(obj); -} - -char *snd_hidden_kstrdup(const char *s, gfp_t flags) -{ - int len; - char *buf; - - if (!s) return NULL; - - len = strlen(s) + 1; - buf = _snd_kmalloc(len, flags); - if (buf) - memcpy(buf, s, len); - return buf; -} - -static void snd_memory_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer) -{ - snd_iprintf(buffer, "kmalloc: %li bytes\n", snd_alloc_kmalloc); -} - -int __init snd_memory_info_init(void) -{ - snd_info_entry_t *entry; - - entry = snd_info_create_module_entry(THIS_MODULE, "meminfo", NULL); - if (entry) { - entry->c.text.read_size = 256; - entry->c.text.read = snd_memory_info_read; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - snd_memory_info_entry = entry; - return 0; -} - -int __exit snd_memory_info_done(void) -{ - if (snd_memory_info_entry) - snd_info_unregister(snd_memory_info_entry); - return 0; -} - -#endif /* CONFIG_SND_DEBUG_MEMORY */ /** * copy_to_user_fromio - copy data from mmio-space to user-space diff --git a/sound/core/misc.c b/sound/core/misc.c index 3eddfdede9f..b53e563c09e 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c @@ -30,7 +30,7 @@ void release_and_free_resource(struct resource *res) { if (res) { release_resource(res); - kfree_nocheck(res); + kfree(res); } } diff --git a/sound/core/sound.c b/sound/core/sound.c index e94eebd8ad6..dee602245fe 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -350,9 +350,7 @@ static int __init alsa_sound_init(void) devfs_remove("snd"); return -EIO; } - snd_memory_init(); if (snd_info_init() < 0) { - snd_memory_done(); unregister_chrdev(major, "alsa"); devfs_remove("snd"); return -ENOMEM; @@ -381,7 +379,6 @@ static void __exit alsa_sound_exit(void) #endif snd_info_minor_unregister(); snd_info_done(); - snd_memory_done(); if (unregister_chrdev(major, "alsa") != 0) snd_printk(KERN_ERR "unable to unregister major device number %d\n", major); devfs_remove("snd"); @@ -403,12 +400,6 @@ EXPORT_SYMBOL(snd_register_oss_device); EXPORT_SYMBOL(snd_unregister_oss_device); #endif /* memory.c */ -#ifdef CONFIG_SND_DEBUG_MEMORY -EXPORT_SYMBOL(snd_hidden_kmalloc); -EXPORT_SYMBOL(snd_hidden_kcalloc); -EXPORT_SYMBOL(snd_hidden_kfree); -EXPORT_SYMBOL(snd_hidden_kstrdup); -#endif EXPORT_SYMBOL(copy_to_user_fromio); EXPORT_SYMBOL(copy_from_user_toio); /* init.c */ @@ -491,9 +482,4 @@ EXPORT_SYMBOL(snd_verbose_printk); #endif #if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_VERBOSE_PRINTK) EXPORT_SYMBOL(snd_verbose_printd); -#endif - /* wrappers */ -#ifdef CONFIG_SND_DEBUG_MEMORY -EXPORT_SYMBOL(snd_wrapper_kmalloc); -EXPORT_SYMBOL(snd_wrapper_kfree); #endif -- cgit v1.2.3 From 94651a5bf5143053d34ea9f957dba4f33c1afb15 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 10 Oct 2005 12:08:01 +0200 Subject: [ALSA] via82xx - Add DXS entry for Clevo D470 Modules: VIA82xx driver Added the DXS entry for Clevo D470 laptop. Signed-off-by: Takashi Iwai --- sound/pci/via82xx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index b0302c369c3..78a5dfb6679 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -2176,6 +2176,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci) { .subvendor = 0x147b, .subdevice = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */ { .subvendor = 0x14ff, .subdevice = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */ { .subvendor = 0x14ff, .subdevice = 0x0408, .action = VIA_DXS_SRC }, /* Twinhead laptop */ + { .subvendor = 0x1558, .subdevice = 0x4701, .action = VIA_DXS_SRC }, /* Clevo D470 */ { .subvendor = 0x1584, .subdevice = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */ { .subvendor = 0x1584, .subdevice = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */ { .subvendor = 0x161f, .subdevice = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */ -- cgit v1.2.3 From c913f69b0d1b9f3f3aa39f49a240cb0fb9d7c6dd Mon Sep 17 00:00:00 2001 From: Rudolf Marek Date: Mon, 10 Oct 2005 12:11:23 +0200 Subject: [ALSA] es1938 - Fix resume Modules: ES1938 driver This patch fixes the suspend/resume issue I'm having with ESS-Solo1 soundcard. Without this patch I might get after resume message that kernel is disabling the IRQ5 (soundcard). If there was something playing it wont continue after resume without this patch. Signed-off-by: Rudolf Marek Signed-off-by: Takashi Iwai --- sound/pci/es1938.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 17fa80c2387..e8b8ebf9963 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -1390,7 +1390,8 @@ static int es1938_suspend(snd_card_t *card, pm_message_t state) *d = snd_es1938_reg_read(chip, *s); outb(0x00, SLIO_REG(chip, IRQCONTROL)); /* disable irqs */ - + if (chip->irq >= 0) + free_irq(chip->irq, (void *)chip); pci_disable_device(chip->pci); return 0; } @@ -1401,6 +1402,7 @@ static int es1938_resume(snd_card_t *card) unsigned char *s, *d; pci_enable_device(chip->pci); + request_irq(chip->pci->irq, snd_es1938_interrupt, SA_INTERRUPT|SA_SHIRQ, "ES1938", (void *)chip); snd_es1938_chip_init(chip); /* restore mixer-related registers */ -- cgit v1.2.3 From 93b9f426374a07d46f582fdf284e4e26d8fe9756 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 10 Oct 2005 13:42:24 +0200 Subject: [ALSA] es1938 - Clean up and fix trigger in PM Modules: ES1938 driver - Clean up the last PM fix - Add TRIGGER_SUSPEND/RESUME to disable/enable DMA properly during PM Signed-off-by: Takashi Iwai --- sound/pci/es1938.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index e8b8ebf9963..7bfbdfc2f8b 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -543,10 +543,12 @@ static int snd_es1938_capture_trigger(snd_pcm_substream_t * substream, int val; switch (cmd) { case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: val = 0x0f; chip->active |= ADC1; break; case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: val = 0x00; chip->active &= ~ADC1; break; @@ -563,6 +565,7 @@ static int snd_es1938_playback1_trigger(snd_pcm_substream_t * substream, es1938_t *chip = snd_pcm_substream_chip(substream); switch (cmd) { case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: /* According to the documentation this should be: 0x13 but that value may randomly swap stereo channels */ snd_es1938_mixer_write(chip, ESSSB_IREG_AUDIO2CONTROL1, 0x92); @@ -575,6 +578,7 @@ static int snd_es1938_playback1_trigger(snd_pcm_substream_t * substream, chip->active |= DAC2; break; case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: outb(0, SLIO_REG(chip, AUDIO2MODE)); snd_es1938_mixer_write(chip, ESSSB_IREG_AUDIO2CONTROL1, 0); chip->active &= ~DAC2; @@ -592,10 +596,12 @@ static int snd_es1938_playback2_trigger(snd_pcm_substream_t * substream, int val; switch (cmd) { case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: val = 5; chip->active |= DAC1; break; case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: val = 0; chip->active &= ~DAC1; break; @@ -1390,7 +1396,7 @@ static int es1938_suspend(snd_card_t *card, pm_message_t state) *d = snd_es1938_reg_read(chip, *s); outb(0x00, SLIO_REG(chip, IRQCONTROL)); /* disable irqs */ - if (chip->irq >= 0) + if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); pci_disable_device(chip->pci); return 0; @@ -1402,7 +1408,9 @@ static int es1938_resume(snd_card_t *card) unsigned char *s, *d; pci_enable_device(chip->pci); - request_irq(chip->pci->irq, snd_es1938_interrupt, SA_INTERRUPT|SA_SHIRQ, "ES1938", (void *)chip); + request_irq(chip->pci->irq, snd_es1938_interrupt, + SA_INTERRUPT|SA_SHIRQ, "ES1938", (void *)chip); + chip->irq = chip->pci->irq; snd_es1938_chip_init(chip); /* restore mixer-related registers */ -- cgit v1.2.3 From 86284e458b48ffb6f9849673880f8342dee5b76a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 11 Oct 2005 15:05:54 +0200 Subject: [ALSA] hda-codec - Get subsystem ID from AFG/MFG Modules: HDA Codec driver Get subsytem ID from AFG/MFG if not obtained from the root node. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 7 +++++++ sound/pci/hda/hda_codec.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 3815403ed09..57b5a0a83c8 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -518,6 +518,13 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, return -ENODEV; } + if (! codec->subsystem_id) { + hda_nid_t nid = codec->afg ? codec->afg : codec->mfg; + codec->subsystem_id = snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_SUBSYSTEM_ID, + 0); + } + codec->preset = find_codec_preset(codec); if (! *bus->card->mixername) snd_hda_get_codec_name(codec, bus->card->mixername, diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index bb53bcf7674..1179d6cfa82 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -79,6 +79,8 @@ enum { #define AC_VERB_GET_GPIO_MASK 0x0f16 #define AC_VERB_GET_GPIO_DIRECTION 0x0f17 #define AC_VERB_GET_CONFIG_DEFAULT 0x0f1c +/* f20: AFG/MFG */ +#define AC_VERB_GET_SUBSYSTEM_ID 0x0f20 /* * SET verbs -- cgit v1.2.3 From b709e57440b9d5f38b8c73e1310127d51777bba0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 11 Oct 2005 17:28:58 +0200 Subject: [ALSA] Add the missing forward declration Modules: ALSA Core Added the missing forward declaration before function prototypes. Signed-off-by: Takashi Iwai --- include/sound/core.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/sound/core.h b/include/sound/core.h index ed56a356ab7..642ddfbc632 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -339,6 +339,7 @@ unsigned int snd_dma_pointer(unsigned long dma, unsigned int size); #endif /* misc.c */ +struct resource; void release_and_free_resource(struct resource *res); #ifdef CONFIG_SND_VERBOSE_PRINTK -- cgit v1.2.3 From 2dfbeca9e9b3857e005afc9b933e2e1be07a9ea0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 12 Oct 2005 10:04:42 +0200 Subject: [ALSA] Add support of high-rate SPDIF output Modules: ICE1724 driver Add support of SPDIF output with sample rates higher than 48kHz. Signed-off-by: Takashi Iwai --- sound/pci/ice1712/ice1724.c | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index c3ce8f93740..a1133c53412 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -675,9 +675,12 @@ static snd_pcm_hardware_t snd_vt1724_spdif = SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_SYNC_START), .formats = SNDRV_PCM_FMTBIT_S32_LE, - .rates = SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000, + .rates = (SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_44100| + SNDRV_PCM_RATE_48000|SNDRV_PCM_RATE_88200| + SNDRV_PCM_RATE_96000|SNDRV_PCM_RATE_176400| + SNDRV_PCM_RATE_192000), .rate_min = 32000, - .rate_max = 48000, + .rate_max = 192000, .channels_min = 2, .channels_max = 2, .buffer_bytes_max = (1UL << 18), /* 16bits dword */ @@ -905,6 +908,10 @@ static void update_spdif_rate(ice1712_t *ice, unsigned int rate) case 44100: break; case 48000: nval |= 2 << 12; break; case 32000: nval |= 3 << 12; break; + case 88200: nval |= 4 << 12; break; + case 96000: nval |= 5 << 12; break; + case 192000: nval |= 6 << 12; break; + case 176400: nval |= 7 << 12; break; } if (val != nval) update_spdif_bits(ice, nval); @@ -1292,22 +1299,32 @@ static int snd_vt1724_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * static unsigned int encode_spdif_bits(snd_aes_iec958_t *diga) { - unsigned int val; + unsigned int val, rbits; val = diga->status[0] & 0x03; /* professional, non-audio */ if (val & 0x01) { /* professional */ if ((diga->status[0] & IEC958_AES0_PRO_EMPHASIS) == IEC958_AES0_PRO_EMPHASIS_5015) val |= 1U << 3; - switch (diga->status[0] & IEC958_AES0_PRO_FS) { - case IEC958_AES0_PRO_FS_44100: - break; - case IEC958_AES0_PRO_FS_32000: - val |= 3U << 12; - break; - default: - val |= 2U << 12; - break; + rbits = (diga->status[4] >> 3) & 0x0f; + if (rbits) { + switch (rbits) { + case 2: val |= 5 << 12; break; /* 96k */ + case 3: val |= 6 << 12; break; /* 192k */ + case 10: val |= 4 << 12; break; /* 88.2k */ + case 11: val |= 7 << 12; break; /* 176.4k */ + } + } else { + switch (diga->status[0] & IEC958_AES0_PRO_FS) { + case IEC958_AES0_PRO_FS_44100: + break; + case IEC958_AES0_PRO_FS_32000: + val |= 3U << 12; + break; + default: + val |= 2U << 12; + break; + } } } else { /* consumer */ -- cgit v1.2.3 From 2fd43d1159d22395aae01836c4b13ee5265a9b6b Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 12 Oct 2005 17:10:35 +0200 Subject: [ALSA] timer: fix timer instance memory allocation checks Modules: Timer Midlevel Add checks to return -ENOMEM in case snd_timer_instance_new() fails. Signed-off-by: Clemens Ladisch --- sound/core/timer.c | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/sound/core/timer.c b/sound/core/timer.c index 8ecec9134ac..b02681eaea7 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -251,6 +251,10 @@ int snd_timer_open(snd_timer_instance_t **ti, } down(®ister_mutex); timeri = snd_timer_instance_new(owner, NULL); + if (!timeri) { + up(®ister_mutex); + return -ENOMEM; + } timeri->slave_class = tid->dev_sclass; timeri->slave_id = tid->device; timeri->flags |= SNDRV_TIMER_IFLG_SLAVE; @@ -272,27 +276,29 @@ int snd_timer_open(snd_timer_instance_t **ti, timer = snd_timer_find(tid); } #endif - if (timer) { - if (!list_empty(&timer->open_list_head)) { - timeri = (snd_timer_instance_t *)list_entry(timer->open_list_head.next, snd_timer_instance_t, open_list); - if (timeri->flags & SNDRV_TIMER_IFLG_EXCLUSIVE) { - up(®ister_mutex); - return -EBUSY; - } - } - timeri = snd_timer_instance_new(owner, timer); - if (timeri) { - timeri->slave_class = tid->dev_sclass; - timeri->slave_id = slave_id; - if (list_empty(&timer->open_list_head) && timer->hw.open) - timer->hw.open(timer); - list_add_tail(&timeri->open_list, &timer->open_list_head); - snd_timer_check_master(timeri); - } - } else { + if (!timer) { up(®ister_mutex); return -ENODEV; } + if (!list_empty(&timer->open_list_head)) { + timeri = list_entry(timer->open_list_head.next, + snd_timer_instance_t, open_list); + if (timeri->flags & SNDRV_TIMER_IFLG_EXCLUSIVE) { + up(®ister_mutex); + return -EBUSY; + } + } + timeri = snd_timer_instance_new(owner, timer); + if (!timeri) { + up(®ister_mutex); + return -ENOMEM; + } + timeri->slave_class = tid->dev_sclass; + timeri->slave_id = slave_id; + if (list_empty(&timer->open_list_head) && timer->hw.open) + timer->hw.open(timer); + list_add_tail(&timeri->open_list, &timer->open_list_head); + snd_timer_check_master(timeri); up(®ister_mutex); *ti = timeri; return 0; -- cgit v1.2.3 From de24214d0c8e78134875752619f99b9e5824c196 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 12 Oct 2005 17:12:31 +0200 Subject: [ALSA] timers: add module refcounting for global timers Modules: RTC timer driver,Timer Midlevel Add a module pointer to the timer structure and use it for refcounting instead of the card's module pointer to prevent the global timer modules (rtctimer and hpetimer) from being removed while in use. Signed-off-by: Clemens Ladisch --- include/sound/timer.h | 1 + sound/core/rtctimer.c | 4 +++- sound/core/timer.c | 7 ++++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/sound/timer.h b/include/sound/timer.h index 1898511a0f3..b55f38ae56e 100644 --- a/include/sound/timer.h +++ b/include/sound/timer.h @@ -88,6 +88,7 @@ struct _snd_timer_hardware { struct _snd_timer { snd_timer_class_t tmr_class; snd_card_t *card; + struct module *module; int tmr_device; int tmr_subdevice; char id[64]; diff --git a/sound/core/rtctimer.c b/sound/core/rtctimer.c index 8762ff8938c..c3c18568207 100644 --- a/sound/core/rtctimer.c +++ b/sound/core/rtctimer.c @@ -124,7 +124,8 @@ static int __init rtctimer_init(void) if (rtctimer_freq < 2 || rtctimer_freq > 8192 || (rtctimer_freq & (rtctimer_freq - 1)) != 0) { - snd_printk(KERN_ERR "rtctimer: invalid frequency %d\n", rtctimer_freq); + snd_printk(KERN_ERR "rtctimer: invalid frequency %d\n", + rtctimer_freq); return -EINVAL; } @@ -133,6 +134,7 @@ static int __init rtctimer_init(void) if (err < 0) return err; + timer->module = THIS_MODULE; strcpy(timer->name, "RTC timer"); timer->hw = rtc_hw; timer->hw.resolution = NANO_SEC / rtctimer_freq; diff --git a/sound/core/timer.c b/sound/core/timer.c index b02681eaea7..c8496c7b8df 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -113,7 +113,7 @@ static snd_timer_instance_t *snd_timer_instance_new(char *owner, snd_timer_t *ti INIT_LIST_HEAD(&timeri->slave_active_head); timeri->timer = timer; - if (timer && timer->card && !try_module_get(timer->card->module)) { + if (timer && !try_module_get(timer->module)) { kfree(timeri->owner); kfree(timeri); return NULL; @@ -363,8 +363,8 @@ int snd_timer_close(snd_timer_instance_t * timeri) timeri->private_free(timeri); kfree(timeri->owner); kfree(timeri); - if (timer && timer->card) - module_put(timer->card->module); + if (timer) + module_put(timer->module); return 0; } @@ -787,6 +787,7 @@ int snd_timer_new(snd_card_t *card, char *id, snd_timer_id_t *tid, snd_timer_t * spin_lock_init(&timer->lock); tasklet_init(&timer->task_queue, snd_timer_tasklet, (unsigned long)timer); if (card != NULL) { + timer->module = card->module; if ((err = snd_device_new(card, SNDRV_DEV_TIMER, timer, &ops)) < 0) { snd_timer_free(timer); return err; -- cgit v1.2.3 From 9dfba38012196ecaf48cbb7ecad92e0729b4491f Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 12 Oct 2005 17:14:55 +0200 Subject: [ALSA] timer: remove list_entry() type casts Modules: Timer Midlevel The return value of list_entry() already has the type from the second argument, so we don't need to typecase it again. Signed-off-by: Clemens Ladisch --- sound/core/timer.c | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/sound/core/timer.c b/sound/core/timer.c index c8496c7b8df..488c28ac56c 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -131,7 +131,7 @@ static snd_timer_t *snd_timer_find(snd_timer_id_t *tid) struct list_head *p; list_for_each(p, &snd_timer_list) { - timer = (snd_timer_t *)list_entry(p, snd_timer_t, device_list); + timer = list_entry(p, snd_timer_t, device_list); if (timer->tmr_class != tid->dev_class) continue; @@ -186,9 +186,9 @@ static void snd_timer_check_slave(snd_timer_instance_t *slave) /* FIXME: it's really dumb to look up all entries.. */ list_for_each(p, &snd_timer_list) { - timer = (snd_timer_t *)list_entry(p, snd_timer_t, device_list); + timer = list_entry(p, snd_timer_t, device_list); list_for_each(q, &timer->open_list_head) { - master = (snd_timer_instance_t *)list_entry(q, snd_timer_instance_t, open_list); + master = list_entry(q, snd_timer_instance_t, open_list); if (slave->slave_class == master->slave_class && slave->slave_id == master->slave_id) { list_del(&slave->open_list); @@ -216,7 +216,7 @@ static void snd_timer_check_master(snd_timer_instance_t *master) /* check all pending slaves */ list_for_each_safe(p, n, &snd_timer_slave_list) { - slave = (snd_timer_instance_t *)list_entry(p, snd_timer_instance_t, open_list); + slave = list_entry(p, snd_timer_instance_t, open_list); if (slave->slave_class == master->slave_class && slave->slave_id == master->slave_id) { list_del(p); @@ -348,7 +348,7 @@ int snd_timer_close(snd_timer_instance_t * timeri) timer->hw.close(timer); /* remove slave links */ list_for_each_safe(p, n, &timeri->slave_list_head) { - slave = (snd_timer_instance_t *)list_entry(p, snd_timer_instance_t, open_list); + slave = list_entry(p, snd_timer_instance_t, open_list); spin_lock_irq(&slave_active_lock); _snd_timer_stop(slave, 1, SNDRV_TIMER_EVENT_RESOLUTION); list_del(p); @@ -406,7 +406,7 @@ static void snd_timer_notify1(snd_timer_instance_t *ti, enum sndrv_timer_event e return; spin_lock_irqsave(&timer->lock, flags); list_for_each(n, &ti->slave_active_head) { - ts = (snd_timer_instance_t *)list_entry(n, snd_timer_instance_t, active_list); + ts = list_entry(n, snd_timer_instance_t, active_list); if (ts->ccallback) ts->ccallback(ti, event + 100, &tstamp, resolution); } @@ -584,7 +584,7 @@ static void snd_timer_reschedule(snd_timer_t * timer, unsigned long ticks_left) struct list_head *p; list_for_each(p, &timer->active_list_head) { - ti = (snd_timer_instance_t *)list_entry(p, snd_timer_instance_t, active_list); + ti = list_entry(p, snd_timer_instance_t, active_list); if (ti->flags & SNDRV_TIMER_IFLG_START) { ti->flags &= ~SNDRV_TIMER_IFLG_START; ti->flags |= SNDRV_TIMER_IFLG_RUNNING; @@ -621,7 +621,7 @@ static void snd_timer_tasklet(unsigned long arg) /* now process all callbacks */ while (!list_empty(&timer->sack_list_head)) { p = timer->sack_list_head.next; /* get first item */ - ti = (snd_timer_instance_t *)list_entry(p, snd_timer_instance_t, ack_list); + ti = list_entry(p, snd_timer_instance_t, ack_list); /* remove from ack_list and make empty */ list_del_init(p); @@ -669,7 +669,7 @@ void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left) * instance is relinked to done_list_head before callback is called. */ list_for_each_safe(p, n, &timer->active_list_head) { - ti = (snd_timer_instance_t *)list_entry(p, snd_timer_instance_t, active_list); + ti = list_entry(p, snd_timer_instance_t, active_list); if (!(ti->flags & SNDRV_TIMER_IFLG_RUNNING)) continue; ti->pticks += ticks_left; @@ -696,7 +696,7 @@ void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left) } } list_for_each(q, &ti->slave_active_head) { - ts = (snd_timer_instance_t *)list_entry(q, snd_timer_instance_t, active_list); + ts = list_entry(q, snd_timer_instance_t, active_list); ts->pticks = ti->pticks; ts->resolution = resolution; if (list_empty(&ts->ack_list)) { @@ -729,7 +729,7 @@ void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left) /* now process all fast callbacks */ while (!list_empty(&timer->ack_list_head)) { p = timer->ack_list_head.next; /* get first item */ - ti = (snd_timer_instance_t *)list_entry(p, snd_timer_instance_t, ack_list); + ti = list_entry(p, snd_timer_instance_t, ack_list); /* remove from ack_list and make empty */ list_del_init(p); @@ -825,7 +825,7 @@ static int snd_timer_dev_register(snd_device_t *dev) down(®ister_mutex); list_for_each(p, &snd_timer_list) { - timer1 = (snd_timer_t *)list_entry(p, snd_timer_t, device_list); + timer1 = list_entry(p, snd_timer_t, device_list); if (timer1->tmr_class > timer->tmr_class) break; if (timer1->tmr_class < timer->tmr_class) @@ -864,7 +864,7 @@ static int snd_timer_unregister(snd_timer_t *timer) snd_printk(KERN_WARNING "timer 0x%lx is busy?\n", (long)timer); list_for_each_safe(p, n, &timer->open_list_head) { list_del_init(p); - ti = (snd_timer_instance_t *)list_entry(p, snd_timer_instance_t, open_list); + ti = list_entry(p, snd_timer_instance_t, open_list); ti->timer = NULL; } } @@ -899,11 +899,11 @@ void snd_timer_notify(snd_timer_t *timer, enum sndrv_timer_event event, struct t resolution = timer->hw.resolution; } list_for_each(p, &timer->active_list_head) { - ti = (snd_timer_instance_t *)list_entry(p, snd_timer_instance_t, active_list); + ti = list_entry(p, snd_timer_instance_t, active_list); if (ti->ccallback) ti->ccallback(ti, event, tstamp, resolution); list_for_each(n, &ti->slave_active_head) { - ts = (snd_timer_instance_t *)list_entry(n, snd_timer_instance_t, active_list); + ts = list_entry(n, snd_timer_instance_t, active_list); if (ts->ccallback) ts->ccallback(ts, event, tstamp, resolution); } @@ -1052,7 +1052,7 @@ static void snd_timer_proc_read(snd_info_entry_t *entry, down(®ister_mutex); list_for_each(p, &snd_timer_list) { - timer = (snd_timer_t *)list_entry(p, snd_timer_t, device_list); + timer = list_entry(p, snd_timer_t, device_list); switch (timer->tmr_class) { case SNDRV_TIMER_CLASS_GLOBAL: snd_iprintf(buffer, "G%i: ", timer->tmr_device); @@ -1074,7 +1074,7 @@ static void snd_timer_proc_read(snd_info_entry_t *entry, snd_iprintf(buffer, "\n"); spin_lock_irqsave(&timer->lock, flags); list_for_each(q, &timer->open_list_head) { - ti = (snd_timer_instance_t *)list_entry(q, snd_timer_instance_t, open_list); + ti = list_entry(q, snd_timer_instance_t, open_list); snd_iprintf(buffer, " Client %s : %s : lost interrupts %li\n", ti->owner ? ti->owner : "unknown", ti->flags & (SNDRV_TIMER_IFLG_START|SNDRV_TIMER_IFLG_RUNNING) ? "running" : "stopped", @@ -1275,7 +1275,8 @@ static int snd_timer_user_next_device(snd_timer_id_t __user *_tid) if (list_empty(&snd_timer_list)) snd_timer_user_zero_id(&id); else { - timer = (snd_timer_t *)list_entry(snd_timer_list.next, snd_timer_t, device_list); + timer = list_entry(snd_timer_list.next, + snd_timer_t, device_list); snd_timer_user_copy_id(&id, timer); } } else { @@ -1283,7 +1284,7 @@ static int snd_timer_user_next_device(snd_timer_id_t __user *_tid) case SNDRV_TIMER_CLASS_GLOBAL: id.device = id.device < 0 ? 0 : id.device + 1; list_for_each(p, &snd_timer_list) { - timer = (snd_timer_t *)list_entry(p, snd_timer_t, device_list); + timer = list_entry(p, snd_timer_t, device_list); if (timer->tmr_class > SNDRV_TIMER_CLASS_GLOBAL) { snd_timer_user_copy_id(&id, timer); break; @@ -1312,7 +1313,7 @@ static int snd_timer_user_next_device(snd_timer_id_t __user *_tid) } } list_for_each(p, &snd_timer_list) { - timer = (snd_timer_t *)list_entry(p, snd_timer_t, device_list); + timer = list_entry(p, snd_timer_t, device_list); if (timer->tmr_class > id.dev_class) { snd_timer_user_copy_id(&id, timer); break; @@ -1915,7 +1916,7 @@ static void __exit alsa_timer_exit(void) snd_unregister_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0); /* unregister the system timer */ list_for_each_safe(p, n, &snd_timer_list) { - snd_timer_t *timer = (snd_timer_t *)list_entry(p, snd_timer_t, device_list); + snd_timer_t *timer = list_entry(p, snd_timer_t, device_list); snd_timer_unregister(timer); } if (snd_timer_proc_entry) { -- cgit v1.2.3 From 6b172a853814fe52fb4d5942e660943cb9e6df37 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 12 Oct 2005 17:20:21 +0200 Subject: [ALSA] timer: formatting changes Modules: Timer Midlevel Split or rewrite lines that are longer than 80 characters, and remove whitespaces at the end of lines. Signed-off-by: Clemens Ladisch --- sound/core/timer.c | 279 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 167 insertions(+), 112 deletions(-) diff --git a/sound/core/timer.c b/sound/core/timer.c index 488c28ac56c..1b90a38d10f 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -55,7 +55,7 @@ MODULE_PARM_DESC(timer_limit, "Maximum global timers in system."); typedef struct { snd_timer_instance_t *timeri; - int tread; /* enhanced read with timestamps and events */ + int tread; /* enhanced read with timestamps and events */ unsigned long ticks; unsigned long overrun; int qhead; @@ -95,7 +95,8 @@ static void snd_timer_reschedule(snd_timer_t * timer, unsigned long ticks_left); * create a timer instance with the given owner string. * when timer is not NULL, increments the module counter */ -static snd_timer_instance_t *snd_timer_instance_new(char *owner, snd_timer_t *timer) +static snd_timer_instance_t *snd_timer_instance_new(char *owner, + snd_timer_t *timer) { snd_timer_instance_t *timeri; timeri = kzalloc(sizeof(*timeri), GFP_KERNEL); @@ -192,7 +193,8 @@ static void snd_timer_check_slave(snd_timer_instance_t *slave) if (slave->slave_class == master->slave_class && slave->slave_id == master->slave_id) { list_del(&slave->open_list); - list_add_tail(&slave->open_list, &master->slave_list_head); + list_add_tail(&slave->open_list, + &master->slave_list_head); spin_lock_irq(&slave_active_lock); slave->master = master; slave->timer = master->timer; @@ -225,7 +227,8 @@ static void snd_timer_check_master(snd_timer_instance_t *master) slave->master = master; slave->timer = master->timer; if (slave->flags & SNDRV_TIMER_IFLG_RUNNING) - list_add_tail(&slave->active_list, &master->slave_active_head); + list_add_tail(&slave->active_list, + &master->slave_active_head); spin_unlock_irq(&slave_active_lock); } } @@ -241,7 +244,7 @@ int snd_timer_open(snd_timer_instance_t **ti, { snd_timer_t *timer; snd_timer_instance_t *timeri = NULL; - + if (tid->dev_class == SNDRV_TIMER_CLASS_SLAVE) { /* open a slave instance */ if (tid->dev_sclass <= SNDRV_TIMER_SCLASS_NONE || @@ -304,7 +307,8 @@ int snd_timer_open(snd_timer_instance_t **ti, return 0; } -static int _snd_timer_stop(snd_timer_instance_t * timeri, int keep_flag, enum sndrv_timer_event event); +static int _snd_timer_stop(snd_timer_instance_t * timeri, + int keep_flag, enum sndrv_timer_event event); /* * close a timer instance @@ -344,7 +348,8 @@ int snd_timer_close(snd_timer_instance_t * timeri) spin_unlock_irq(&timer->lock); down(®ister_mutex); list_del(&timeri->open_list); - if (timer && list_empty(&timer->open_list_head) && timer->hw.close) + if (timer && list_empty(&timer->open_list_head) && + timer->hw.close) timer->hw.close(timer); /* remove slave links */ list_for_each_safe(p, n, &timeri->slave_list_head) { @@ -382,7 +387,8 @@ unsigned long snd_timer_resolution(snd_timer_instance_t * timeri) return 0; } -static void snd_timer_notify1(snd_timer_instance_t *ti, enum sndrv_timer_event event) +static void snd_timer_notify1(snd_timer_instance_t *ti, + enum sndrv_timer_event event) { snd_timer_t *timer; unsigned long flags; @@ -392,8 +398,10 @@ static void snd_timer_notify1(snd_timer_instance_t *ti, enum sndrv_timer_event e struct timespec tstamp; getnstimeofday(&tstamp); - snd_assert(event >= SNDRV_TIMER_EVENT_START && event <= SNDRV_TIMER_EVENT_PAUSE, return); - if (event == SNDRV_TIMER_EVENT_START || event == SNDRV_TIMER_EVENT_CONTINUE) + snd_assert(event >= SNDRV_TIMER_EVENT_START && + event <= SNDRV_TIMER_EVENT_PAUSE, return); + if (event == SNDRV_TIMER_EVENT_START || + event == SNDRV_TIMER_EVENT_CONTINUE) resolution = snd_timer_resolution(ti); if (ti->ccallback) ti->ccallback(ti, SNDRV_TIMER_EVENT_START, &tstamp, resolution); @@ -413,7 +421,8 @@ static void snd_timer_notify1(snd_timer_instance_t *ti, enum sndrv_timer_event e spin_unlock_irqrestore(&timer->lock, flags); } -static int snd_timer_start1(snd_timer_t *timer, snd_timer_instance_t *timeri, unsigned long sticks) +static int snd_timer_start1(snd_timer_t *timer, snd_timer_instance_t *timeri, + unsigned long sticks) { list_del(&timeri->active_list); list_add_tail(&timeri->active_list, &timer->active_list_head); @@ -440,14 +449,15 @@ static int snd_timer_start_slave(snd_timer_instance_t *timeri) spin_lock_irqsave(&slave_active_lock, flags); timeri->flags |= SNDRV_TIMER_IFLG_RUNNING; if (timeri->master) - list_add_tail(&timeri->active_list, &timeri->master->slave_active_head); + list_add_tail(&timeri->active_list, + &timeri->master->slave_active_head); spin_unlock_irqrestore(&slave_active_lock, flags); return 1; /* delayed start */ } /* * start the timer instance - */ + */ int snd_timer_start(snd_timer_instance_t * timeri, unsigned int ticks) { snd_timer_t *timer; @@ -473,7 +483,8 @@ int snd_timer_start(snd_timer_instance_t * timeri, unsigned int ticks) return result; } -static int _snd_timer_stop(snd_timer_instance_t * timeri, int keep_flag, enum sndrv_timer_event event) +static int _snd_timer_stop(snd_timer_instance_t * timeri, + int keep_flag, enum sndrv_timer_event event) { snd_timer_t *timer; unsigned long flags; @@ -507,7 +518,8 @@ static int _snd_timer_stop(snd_timer_instance_t * timeri, int keep_flag, enum sn } } if (!keep_flag) - timeri->flags &= ~(SNDRV_TIMER_IFLG_RUNNING|SNDRV_TIMER_IFLG_START); + timeri->flags &= + ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START); spin_unlock_irqrestore(&timer->lock, flags); __end: if (event != SNDRV_TIMER_EVENT_RESOLUTION) @@ -625,7 +637,7 @@ static void snd_timer_tasklet(unsigned long arg) /* remove from ack_list and make empty */ list_del_init(p); - + ticks = ti->pticks; ti->pticks = 0; resolution = ti->resolution; @@ -650,7 +662,7 @@ void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left) { snd_timer_instance_t *ti, *ts; unsigned long resolution, ticks; - struct list_head *p, *q, *n; + struct list_head *p, *q, *n, *ack_list_head; int use_tasklet = 0; if (timer == NULL) @@ -665,8 +677,9 @@ void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left) resolution = timer->hw.resolution; /* loop for all active instances - * here we cannot use list_for_each because the active_list of a processed - * instance is relinked to done_list_head before callback is called. + * Here we cannot use list_for_each because the active_list of a + * processed instance is relinked to done_list_head before the callback + * is called. */ list_for_each_safe(p, n, &timer->active_list_head) { ti = list_entry(p, snd_timer_instance_t, active_list); @@ -687,26 +700,19 @@ void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left) if (--timer->running) list_del(p); } - if (list_empty(&ti->ack_list)) { - if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) || - (ti->flags & SNDRV_TIMER_IFLG_FAST)) { - list_add_tail(&ti->ack_list, &timer->ack_list_head); - } else { - list_add_tail(&ti->ack_list, &timer->sack_list_head); - } - } + if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) || + (ti->flags & SNDRV_TIMER_IFLG_FAST)) + ack_list_head = &timer->ack_list_head; + else + ack_list_head = &timer->sack_list_head; + if (list_empty(&ti->ack_list)) + list_add_tail(&ti->ack_list, ack_list_head); list_for_each(q, &ti->slave_active_head) { ts = list_entry(q, snd_timer_instance_t, active_list); ts->pticks = ti->pticks; ts->resolution = resolution; - if (list_empty(&ts->ack_list)) { - if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) || - (ti->flags & SNDRV_TIMER_IFLG_FAST)) { - list_add_tail(&ts->ack_list, &timer->ack_list_head); - } else { - list_add_tail(&ts->ack_list, &timer->sack_list_head); - } - } + if (list_empty(&ts->ack_list)) + list_add_tail(&ts->ack_list, ack_list_head); } } if (timer->flags & SNDRV_TIMER_FLG_RESCHED) @@ -730,10 +736,10 @@ void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left) while (!list_empty(&timer->ack_list_head)) { p = timer->ack_list_head.next; /* get first item */ ti = list_entry(p, snd_timer_instance_t, ack_list); - + /* remove from ack_list and make empty */ list_del_init(p); - + ticks = ti->pticks; ti->pticks = 0; @@ -757,7 +763,8 @@ void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left) */ -int snd_timer_new(snd_card_t *card, char *id, snd_timer_id_t *tid, snd_timer_t ** rtimer) +int snd_timer_new(snd_card_t *card, char *id, snd_timer_id_t *tid, + snd_timer_t **rtimer) { snd_timer_t *timer; int err; @@ -785,10 +792,12 @@ int snd_timer_new(snd_card_t *card, char *id, snd_timer_id_t *tid, snd_timer_t * INIT_LIST_HEAD(&timer->ack_list_head); INIT_LIST_HEAD(&timer->sack_list_head); spin_lock_init(&timer->lock); - tasklet_init(&timer->task_queue, snd_timer_tasklet, (unsigned long)timer); + tasklet_init(&timer->task_queue, snd_timer_tasklet, + (unsigned long)timer); if (card != NULL) { timer->module = card->module; - if ((err = snd_device_new(card, SNDRV_DEV_TIMER, timer, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_TIMER, timer, &ops); + if (err < 0) { snd_timer_free(timer); return err; } @@ -818,7 +827,8 @@ static int snd_timer_dev_register(snd_device_t *dev) snd_timer_t *timer1; struct list_head *p; - snd_assert(timer != NULL && timer->hw.start != NULL && timer->hw.stop != NULL, return -ENXIO); + snd_assert(timer != NULL && timer->hw.start != NULL && + timer->hw.stop != NULL, return -ENXIO); if (!(timer->hw.flags & SNDRV_TIMER_HW_SLAVE) && !timer->hw.resolution && timer->hw.c_resolution == NULL) return -EINVAL; @@ -879,7 +889,8 @@ static int snd_timer_dev_unregister(snd_device_t *device) return snd_timer_unregister(timer); } -void snd_timer_notify(snd_timer_t *timer, enum sndrv_timer_event event, struct timespec *tstamp) +void snd_timer_notify(snd_timer_t *timer, enum sndrv_timer_event event, + struct timespec *tstamp) { unsigned long flags; unsigned long resolution = 0; @@ -888,7 +899,8 @@ void snd_timer_notify(snd_timer_t *timer, enum sndrv_timer_event event, struct t if (! (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)) return; - snd_assert(event >= SNDRV_TIMER_EVENT_MSTART && event <= SNDRV_TIMER_EVENT_MRESUME, return); + snd_assert(event >= SNDRV_TIMER_EVENT_MSTART && + event <= SNDRV_TIMER_EVENT_MRESUME, return); spin_lock_irqsave(&timer->lock, flags); if (event == SNDRV_TIMER_EVENT_MSTART || event == SNDRV_TIMER_EVENT_MCONTINUE || @@ -917,7 +929,7 @@ void snd_timer_notify(snd_timer_t *timer, enum sndrv_timer_event event, struct t int snd_timer_global_new(char *id, int device, snd_timer_t **rtimer) { snd_timer_id_t tid; - + tid.dev_class = SNDRV_TIMER_CLASS_GLOBAL; tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; tid.card = -1; @@ -945,7 +957,7 @@ int snd_timer_global_unregister(snd_timer_t *timer) return snd_timer_unregister(timer); } -/* +/* * System timer */ @@ -1021,7 +1033,8 @@ static int snd_timer_register_system(void) struct snd_timer_system_private *priv; int err; - if ((err = snd_timer_global_new("system", SNDRV_TIMER_GLOBAL_SYSTEM, &timer)) < 0) + err = snd_timer_global_new("system", SNDRV_TIMER_GLOBAL_SYSTEM, &timer); + if (err < 0) return err; strcpy(timer->name, "system timer"); timer->hw = snd_timer_system; @@ -1058,27 +1071,35 @@ static void snd_timer_proc_read(snd_info_entry_t *entry, snd_iprintf(buffer, "G%i: ", timer->tmr_device); break; case SNDRV_TIMER_CLASS_CARD: - snd_iprintf(buffer, "C%i-%i: ", timer->card->number, timer->tmr_device); + snd_iprintf(buffer, "C%i-%i: ", + timer->card->number, timer->tmr_device); break; case SNDRV_TIMER_CLASS_PCM: - snd_iprintf(buffer, "P%i-%i-%i: ", timer->card->number, timer->tmr_device, timer->tmr_subdevice); + snd_iprintf(buffer, "P%i-%i-%i: ", timer->card->number, + timer->tmr_device, timer->tmr_subdevice); break; default: - snd_iprintf(buffer, "?%i-%i-%i-%i: ", timer->tmr_class, timer->card ? timer->card->number : -1, timer->tmr_device, timer->tmr_subdevice); + snd_iprintf(buffer, "?%i-%i-%i-%i: ", timer->tmr_class, + timer->card ? timer->card->number : -1, + timer->tmr_device, timer->tmr_subdevice); } snd_iprintf(buffer, "%s :", timer->name); if (timer->hw.resolution) - snd_iprintf(buffer, " %lu.%03luus (%lu ticks)", timer->hw.resolution / 1000, timer->hw.resolution % 1000, timer->hw.ticks); + snd_iprintf(buffer, " %lu.%03luus (%lu ticks)", + timer->hw.resolution / 1000, + timer->hw.resolution % 1000, + timer->hw.ticks); if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) snd_iprintf(buffer, " SLAVE"); snd_iprintf(buffer, "\n"); spin_lock_irqsave(&timer->lock, flags); list_for_each(q, &timer->open_list_head) { ti = list_entry(q, snd_timer_instance_t, open_list); - snd_iprintf(buffer, " Client %s : %s : lost interrupts %li\n", - ti->owner ? ti->owner : "unknown", - ti->flags & (SNDRV_TIMER_IFLG_START|SNDRV_TIMER_IFLG_RUNNING) ? "running" : "stopped", - ti->lost); + snd_iprintf(buffer, " Client %s : %s\n", + ti->owner ? ti->owner : "unknown", + ti->flags & (SNDRV_TIMER_IFLG_START | + SNDRV_TIMER_IFLG_RUNNING) + ? "running" : "stopped"); } spin_unlock_irqrestore(&timer->lock, flags); } @@ -1096,7 +1117,7 @@ static void snd_timer_user_interrupt(snd_timer_instance_t *timeri, snd_timer_user_t *tu = timeri->callback_data; snd_timer_read_t *r; int prev; - + spin_lock(&tu->qlock); if (tu->qused > 0) { prev = tu->qtail == 0 ? tu->queue_size - 1 : tu->qtail - 1; @@ -1121,7 +1142,8 @@ static void snd_timer_user_interrupt(snd_timer_instance_t *timeri, wake_up(&tu->qchange_sleep); } -static void snd_timer_user_append_to_tqueue(snd_timer_user_t *tu, snd_timer_tread_t *tread) +static void snd_timer_user_append_to_tqueue(snd_timer_user_t *tu, + snd_timer_tread_t *tread) { if (tu->qused >= tu->queue_size) { tu->overrun++; @@ -1140,7 +1162,8 @@ static void snd_timer_user_ccallback(snd_timer_instance_t *timeri, snd_timer_user_t *tu = timeri->callback_data; snd_timer_tread_t r1; - if (event >= SNDRV_TIMER_EVENT_START && event <= SNDRV_TIMER_EVENT_PAUSE) + if (event >= SNDRV_TIMER_EVENT_START && + event <= SNDRV_TIMER_EVENT_PAUSE) tu->tstamp = *tstamp; if ((tu->filter & (1 << event)) == 0 || !tu->tread) return; @@ -1165,13 +1188,15 @@ static void snd_timer_user_tinterrupt(snd_timer_instance_t *timeri, memset(&tstamp, 0, sizeof(tstamp)); spin_lock(&tu->qlock); - if ((tu->filter & ((1 << SNDRV_TIMER_EVENT_RESOLUTION)|(1 << SNDRV_TIMER_EVENT_TICK))) == 0) { + if ((tu->filter & ((1 << SNDRV_TIMER_EVENT_RESOLUTION) | + (1 << SNDRV_TIMER_EVENT_TICK))) == 0) { spin_unlock(&tu->qlock); return; } if (tu->last_resolution != resolution || ticks > 0) getnstimeofday(&tstamp); - if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) && tu->last_resolution != resolution) { + if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) && + tu->last_resolution != resolution) { r1.event = SNDRV_TIMER_EVENT_RESOLUTION; r1.tstamp = tstamp; r1.val = resolution; @@ -1209,7 +1234,7 @@ static void snd_timer_user_tinterrupt(snd_timer_instance_t *timeri, static int snd_timer_user_open(struct inode *inode, struct file *file) { snd_timer_user_t *tu; - + tu = kzalloc(sizeof(*tu), GFP_KERNEL); if (tu == NULL) return -ENOMEM; @@ -1218,7 +1243,8 @@ static int snd_timer_user_open(struct inode *inode, struct file *file) init_MUTEX(&tu->tread_sem); tu->ticks = 1; tu->queue_size = 128; - tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); + tu->queue = kmalloc(tu->queue_size * sizeof(snd_timer_read_t), + GFP_KERNEL); if (tu->queue == NULL) { kfree(tu); return -ENOMEM; @@ -1267,7 +1293,7 @@ static int snd_timer_user_next_device(snd_timer_id_t __user *_tid) snd_timer_id_t id; snd_timer_t *timer; struct list_head *p; - + if (copy_from_user(&id, _tid, sizeof(id))) return -EFAULT; down(®ister_mutex); @@ -1308,7 +1334,11 @@ static int snd_timer_user_next_device(snd_timer_id_t __user *_tid) if (id.device < 0) { id.device = 0; } else { - id.subdevice = id.subdevice < 0 ? 0 : id.subdevice + 1; + if (id.subdevice < 0) { + id.subdevice = 0; + } else { + id.subdevice++; + } } } } @@ -1352,9 +1382,10 @@ static int snd_timer_user_next_device(snd_timer_id_t __user *_tid) if (copy_to_user(_tid, &id, sizeof(*_tid))) return -EFAULT; return 0; -} +} -static int snd_timer_user_ginfo(struct file *file, snd_timer_ginfo_t __user *_ginfo) +static int snd_timer_user_ginfo(struct file *file, + snd_timer_ginfo_t __user *_ginfo) { snd_timer_ginfo_t *ginfo; snd_timer_id_t tid; @@ -1398,7 +1429,8 @@ static int snd_timer_user_ginfo(struct file *file, snd_timer_ginfo_t __user *_gi return err; } -static int snd_timer_user_gparams(struct file *file, snd_timer_gparams_t __user *_gparams) +static int snd_timer_user_gparams(struct file *file, + snd_timer_gparams_t __user *_gparams) { snd_timer_gparams_t gparams; snd_timer_t *t; @@ -1408,23 +1440,26 @@ static int snd_timer_user_gparams(struct file *file, snd_timer_gparams_t __user return -EFAULT; down(®ister_mutex); t = snd_timer_find(&gparams.tid); - if (t != NULL) { - if (list_empty(&t->open_list_head)) { - if (t->hw.set_period) - err = t->hw.set_period(t, gparams.period_num, gparams.period_den); - else - err = -ENOSYS; - } else { - err = -EBUSY; - } - } else { + if (!t) { err = -ENODEV; + goto _error; + } + if (!list_empty(&t->open_list_head)) { + err = -EBUSY; + goto _error; + } + if (!t->hw.set_period) { + err = -ENOSYS; + goto _error; } + err = t->hw.set_period(t, gparams.period_num, gparams.period_den); +_error: up(®ister_mutex); return err; } -static int snd_timer_user_gstatus(struct file *file, snd_timer_gstatus_t __user *_gstatus) +static int snd_timer_user_gstatus(struct file *file, + snd_timer_gstatus_t __user *_gstatus) { snd_timer_gstatus_t gstatus; snd_timer_id_t tid; @@ -1444,7 +1479,8 @@ static int snd_timer_user_gstatus(struct file *file, snd_timer_gstatus_t __user else gstatus.resolution = t->hw.resolution; if (t->hw.precise_resolution) { - t->hw.precise_resolution(t, &gstatus.resolution_num, &gstatus.resolution_den); + t->hw.precise_resolution(t, &gstatus.resolution_num, + &gstatus.resolution_den); } else { gstatus.resolution_num = gstatus.resolution; gstatus.resolution_den = 1000000000uL; @@ -1458,13 +1494,14 @@ static int snd_timer_user_gstatus(struct file *file, snd_timer_gstatus_t __user return err; } -static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user *_tselect) +static int snd_timer_user_tselect(struct file *file, + snd_timer_select_t __user *_tselect) { snd_timer_user_t *tu; snd_timer_select_t tselect; char str[32]; int err = 0; - + tu = file->private_data; down(&tu->tread_sem); if (tu->timeri) { @@ -1478,7 +1515,8 @@ static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user * sprintf(str, "application %i", current->pid); if (tselect.id.dev_class != SNDRV_TIMER_CLASS_SLAVE) tselect.id.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION; - if ((err = snd_timer_open(&tu->timeri, str, &tselect.id, current->pid)) < 0) + err = snd_timer_open(&tu->timeri, str, &tselect.id, current->pid); + if (err < 0) goto __err; kfree(tu->queue); @@ -1486,21 +1524,24 @@ static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user * kfree(tu->tqueue); tu->tqueue = NULL; if (tu->tread) { - tu->tqueue = (snd_timer_tread_t *)kmalloc(tu->queue_size * sizeof(snd_timer_tread_t), GFP_KERNEL); + tu->tqueue = kmalloc(tu->queue_size * sizeof(snd_timer_tread_t), + GFP_KERNEL); if (tu->tqueue == NULL) err = -ENOMEM; } else { - tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); + tu->queue = kmalloc(tu->queue_size * sizeof(snd_timer_read_t), + GFP_KERNEL); if (tu->queue == NULL) err = -ENOMEM; } - + if (err < 0) { snd_timer_close(tu->timeri); tu->timeri = NULL; } else { tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST; - tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt; + tu->timeri->callback = tu->tread + ? snd_timer_user_tinterrupt : snd_timer_user_interrupt; tu->timeri->ccallback = snd_timer_user_ccallback; tu->timeri->callback_data = (void *)tu; } @@ -1510,7 +1551,8 @@ static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user * return err; } -static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info) +static int snd_timer_user_info(struct file *file, + snd_timer_info_t __user *_info) { snd_timer_user_t *tu; snd_timer_info_t *info; @@ -1537,7 +1579,8 @@ static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info return err; } -static int snd_timer_user_params(struct file *file, snd_timer_params_t __user *_params) +static int snd_timer_user_params(struct file *file, + snd_timer_params_t __user *_params) { snd_timer_user_t *tu; snd_timer_params_t params; @@ -1545,7 +1588,7 @@ static int snd_timer_user_params(struct file *file, snd_timer_params_t __user *_ snd_timer_read_t *tr; snd_timer_tread_t *ttr; int err; - + tu = file->private_data; snd_assert(tu->timeri != NULL, return -ENXIO); t = tu->timeri->timer; @@ -1556,7 +1599,8 @@ static int snd_timer_user_params(struct file *file, snd_timer_params_t __user *_ err = -EINVAL; goto _end; } - if (params.queue_size > 0 && (params.queue_size < 32 || params.queue_size > 1024)) { + if (params.queue_size > 0 && + (params.queue_size < 32 || params.queue_size > 1024)) { err = -EINVAL; goto _end; } @@ -1589,16 +1633,19 @@ static int snd_timer_user_params(struct file *file, snd_timer_params_t __user *_ if (params.flags & SNDRV_TIMER_PSFLG_EARLY_EVENT) tu->timeri->flags |= SNDRV_TIMER_IFLG_EARLY_EVENT; spin_unlock_irq(&t->lock); - if (params.queue_size > 0 && (unsigned int)tu->queue_size != params.queue_size) { + if (params.queue_size > 0 && + (unsigned int)tu->queue_size != params.queue_size) { if (tu->tread) { - ttr = (snd_timer_tread_t *)kmalloc(params.queue_size * sizeof(snd_timer_tread_t), GFP_KERNEL); + ttr = kmalloc(params.queue_size * sizeof(*ttr), + GFP_KERNEL); if (ttr) { kfree(tu->tqueue); tu->queue_size = params.queue_size; tu->tqueue = ttr; } } else { - tr = (snd_timer_read_t *)kmalloc(params.queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); + tr = kmalloc(params.queue_size * sizeof(*tr), + GFP_KERNEL); if (tr) { kfree(tu->queue); tu->queue_size = params.queue_size; @@ -1622,7 +1669,6 @@ static int snd_timer_user_params(struct file *file, snd_timer_params_t __user *_ tu->qused++; tu->qtail++; } - } tu->filter = params.filter; tu->ticks = params.ticks; @@ -1633,11 +1679,12 @@ static int snd_timer_user_params(struct file *file, snd_timer_params_t __user *_ return err; } -static int snd_timer_user_status(struct file *file, snd_timer_status_t __user *_status) +static int snd_timer_user_status(struct file *file, + snd_timer_status_t __user *_status) { snd_timer_user_t *tu; snd_timer_status_t status; - + tu = file->private_data; snd_assert(tu->timeri != NULL, return -ENXIO); memset(&status, 0, sizeof(status)); @@ -1657,7 +1704,7 @@ static int snd_timer_user_start(struct file *file) { int err; snd_timer_user_t *tu; - + tu = file->private_data; snd_assert(tu->timeri != NULL, return -ENXIO); snd_timer_stop(tu->timeri); @@ -1670,7 +1717,7 @@ static int snd_timer_user_stop(struct file *file) { int err; snd_timer_user_t *tu; - + tu = file->private_data; snd_assert(tu->timeri != NULL, return -ENXIO); return (err = snd_timer_stop(tu->timeri)) < 0 ? err : 0; @@ -1680,7 +1727,7 @@ static int snd_timer_user_continue(struct file *file) { int err; snd_timer_user_t *tu; - + tu = file->private_data; snd_assert(tu->timeri != NULL, return -ENXIO); tu->timeri->lost = 0; @@ -1691,7 +1738,7 @@ static int snd_timer_user_pause(struct file *file) { int err; snd_timer_user_t *tu; - + tu = file->private_data; snd_assert(tu->timeri != NULL, return -ENXIO); return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0; @@ -1704,12 +1751,13 @@ enum { SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23), }; -static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { snd_timer_user_t *tu; void __user *argp = (void __user *)arg; int __user *p = argp; - + tu = file->private_data; switch (cmd) { case SNDRV_TIMER_IOCTL_PVERSION: @@ -1719,7 +1767,7 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned l case SNDRV_TIMER_IOCTL_TREAD: { int xarg; - + down(&tu->tread_sem); if (tu->timeri) { /* too late */ up(&tu->tread_sem); @@ -1767,7 +1815,7 @@ static int snd_timer_user_fasync(int fd, struct file * file, int on) { snd_timer_user_t *tu; int err; - + tu = file->private_data; err = fasync_helper(fd, file, on, &tu->fasync); if (err < 0) @@ -1775,12 +1823,13 @@ static int snd_timer_user_fasync(int fd, struct file * file, int on) return 0; } -static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, size_t count, loff_t *offset) +static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, + size_t count, loff_t *offset) { snd_timer_user_t *tu; long result = 0, unit; int err = 0; - + tu = file->private_data; unit = tu->tread ? sizeof(snd_timer_tread_t) : sizeof(snd_timer_read_t); spin_lock_irq(&tu->qlock); @@ -1814,12 +1863,14 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, size_ goto _error; if (tu->tread) { - if (copy_to_user(buffer, &tu->tqueue[tu->qhead++], sizeof(snd_timer_tread_t))) { + if (copy_to_user(buffer, &tu->tqueue[tu->qhead++], + sizeof(snd_timer_tread_t))) { err = -EFAULT; goto _error; } } else { - if (copy_to_user(buffer, &tu->queue[tu->qhead++], sizeof(snd_timer_read_t))) { + if (copy_to_user(buffer, &tu->queue[tu->qhead++], + sizeof(snd_timer_read_t))) { err = -EFAULT; goto _error; } @@ -1846,7 +1897,7 @@ static unsigned int snd_timer_user_poll(struct file *file, poll_table * wait) tu = file->private_data; poll_wait(file, &tu->qchange_sleep, wait); - + mask = 0; if (tu->qused) mask |= POLLIN | POLLRDNORM; @@ -1890,9 +1941,11 @@ static int __init alsa_timer_init(void) snd_info_entry_t *entry; #ifdef SNDRV_OSS_INFO_DEV_TIMERS - snd_oss_info_register(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1, "system timer"); + snd_oss_info_register(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1, + "system timer"); #endif - if ((entry = snd_info_create_module_entry(THIS_MODULE, "timers", NULL)) != NULL) { + entry = snd_info_create_module_entry(THIS_MODULE, "timers", NULL); + if (entry != NULL) { entry->c.text.read_size = SNDRV_TIMER_DEVICES * 128; entry->c.text.read = snd_timer_proc_read; if (snd_info_register(entry) < 0) { @@ -1902,10 +1955,12 @@ static int __init alsa_timer_init(void) } snd_timer_proc_entry = entry; if ((err = snd_timer_register_system()) < 0) - snd_printk(KERN_ERR "unable to register system timer (%i)\n", err); + snd_printk(KERN_ERR "unable to register system timer (%i)\n", + err); if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0, &snd_timer_reg, "timer"))<0) - snd_printk(KERN_ERR "unable to register timer device (%i)\n", err); + snd_printk(KERN_ERR "unable to register timer device (%i)\n", + err); return 0; } -- cgit v1.2.3 From 063859c854fcb42a04eec4e20c71885dc121edce Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 14 Oct 2005 17:17:02 +0200 Subject: [ALSA] Remove obsolete chip_t Modules: Documentation,MIPS AU1x00 driver,PPC Beep,SPARC DBRI driver Removed the use of chip_t, which was obsoleted. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl | 3 +-- sound/mips/au1x00.c | 2 -- sound/ppc/beep.c | 2 -- sound/sparc/dbri.c | 5 +---- 4 files changed, 2 insertions(+), 10 deletions(-) diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index 05ae29ac898..260334c98d9 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -3693,8 +3693,7 @@ struct _snd_pcm_runtime { Here, the chip instance is retrieved via snd_kcontrol_chip() macro. This macro - converts from kcontrol->private_data to the type defined by - chip_t. The + just accesses to kcontrol->private_data. The kcontrol->private_data field is given as the argument of snd_ctl_new() (see the later subsection diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c index b7af85f5bfb..2df78a64c7f 100644 --- a/sound/mips/au1x00.c +++ b/sound/mips/au1x00.c @@ -57,8 +57,6 @@ MODULE_CLASSES("{sound}"); MODULE_DEVICES("{{AMD,Au1000 AC'97}}"); #endif -#define chip_t au1000_t - #define PLAYBACK 0 #define CAPTURE 1 #define AC97_SLOT_3 0x01 diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c index 1681ee13efb..d4ec6cc3f1c 100644 --- a/sound/ppc/beep.c +++ b/sound/ppc/beep.c @@ -171,8 +171,6 @@ static int snd_pmac_beep_event(struct input_dev *dev, unsigned int type, unsigne * beep volume mixer */ -#define chip_t pmac_t - static int snd_pmac_info_beep(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index b5c4c15ae7f..59a77129470 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -343,9 +343,6 @@ typedef struct snd_dbri { struct snd_dbri *next; } snd_dbri_t; -/* Needed for the ALSA macros to work */ -#define chip_t snd_dbri_t - #define DBRI_MAX_VOLUME 63 /* Output volume */ #define DBRI_MAX_GAIN 15 /* Input gain */ #define DBRI_RIGHT_BALANCE 255 @@ -1767,7 +1764,7 @@ play: spin_unlock_irqrestore(&dbri->lock, flags); } -DECLARE_TASKLET(xmit_descs_task, xmit_descs, 0); +static DECLARE_TASKLET(xmit_descs_task, xmit_descs, 0); /* transmission_complete_intr() * -- cgit v1.2.3 From 00f226d400d3a5868c4d798bb80491e22dd5b810 Mon Sep 17 00:00:00 2001 From: Honza Maly Date: Fri, 14 Oct 2005 18:18:01 +0200 Subject: [ALSA] Enable DXS controls for VIA VT82xx Modules: VIA82xx driver The patch enable separate DXS controls of sound function of VIA VT82xx controller in case DXS volume is not needed for PCM Playback volume control emulation. Signed-off-by: Honza Maly Signed-off-by: Takashi Iwai --- sound/pci/via82xx.c | 74 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 11 deletions(-) diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 78a5dfb6679..7d46bee828c 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -361,7 +361,8 @@ struct _snd_via82xx { unsigned int mpu_port_saved; #endif - unsigned char playback_volume[2]; /* for VIA8233/C/8235; default = 0 */ + unsigned char playback_volume[4][2]; /* for VIA8233/C/8235; default = 0 */ + unsigned char playback_volume_c[2]; /* for VIA8233/C/8235; default = 0 */ unsigned int intr_mask; /* SGD_SHADOW mask to check interrupts */ @@ -937,8 +938,8 @@ static int snd_via8233_playback_prepare(snd_pcm_substream_t *substream) snd_assert((rbits & ~0xfffff) == 0, return -EINVAL); snd_via82xx_channel_reset(chip, viadev); snd_via82xx_set_table_ptr(chip, viadev); - outb(chip->playback_volume[0], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_L)); - outb(chip->playback_volume[1], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_R)); + outb(chip->playback_volume[viadev->reg_offset / 0x10][0], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_L)); + outb(chip->playback_volume[viadev->reg_offset / 0x10][1], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_R)); outl((runtime->format == SNDRV_PCM_FORMAT_S16_LE ? VIA8233_REG_TYPE_16BIT : 0) | /* format */ (runtime->channels > 1 ? VIA8233_REG_TYPE_STEREO : 0) | /* stereo */ rbits | /* rate */ @@ -1498,12 +1499,44 @@ static int snd_via8233_dxs_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_in static int snd_via8233_dxs_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { via82xx_t *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume[0]; - ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume[1]; + unsigned int idx = snd_ctl_get_ioff(kcontrol, &ucontrol->id); + + ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume[idx][0]; + ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume[idx][1]; + return 0; +} + +static int snd_via8233_pcmdxs_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + via82xx_t *chip = snd_kcontrol_chip(kcontrol); + ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume_c[0]; + ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume_c[1]; return 0; } static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + via82xx_t *chip = snd_kcontrol_chip(kcontrol); + unsigned int idx = snd_ctl_get_ioff(kcontrol, &ucontrol->id); + unsigned long port = chip->port + 0x10 * idx; + unsigned char val; + int i, change = 0; + + for (i = 0; i < 2; i++) { + val = ucontrol->value.integer.value[i]; + if (val > VIA_DXS_MAX_VOLUME) + val = VIA_DXS_MAX_VOLUME; + val = VIA_DXS_MAX_VOLUME - val; + change |= val != chip->playback_volume[idx][i]; + if (change) { + chip->playback_volume[idx][i] = val; + outb(val, port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i); + } + } + return change; +} + +static int snd_via8233_pcmdxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { via82xx_t *chip = snd_kcontrol_chip(kcontrol); unsigned int idx; @@ -1515,11 +1548,12 @@ static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val if (val > VIA_DXS_MAX_VOLUME) val = VIA_DXS_MAX_VOLUME; val = VIA_DXS_MAX_VOLUME - val; - if (val != chip->playback_volume[i]) { + if (val != chip->playback_volume_c[i]) { change = 1; - chip->playback_volume[i] = val; + chip->playback_volume_c[i] = val; for (idx = 0; idx < 4; idx++) { unsigned long port = chip->port + 0x10 * idx; + chip->playback_volume[idx][i] = val; outb(val, port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i); } } @@ -1527,10 +1561,19 @@ static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val return change; } -static snd_kcontrol_new_t snd_via8233_dxs_volume_control __devinitdata = { +static snd_kcontrol_new_t snd_via8233_pcmdxs_volume_control __devinitdata = { .name = "PCM Playback Volume", .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .info = snd_via8233_dxs_volume_info, + .get = snd_via8233_pcmdxs_volume_get, + .put = snd_via8233_pcmdxs_volume_put, +}; + +static snd_kcontrol_new_t snd_via8233_dxs_volume_control __devinitdata = { + .name = "VIA DXS Playback Volume", + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .count = 4, + .info = snd_via8233_dxs_volume_info, .get = snd_via8233_dxs_volume_get, .put = snd_via8233_dxs_volume_put, }; @@ -1723,12 +1766,19 @@ static int __devinit snd_via8233_init_misc(via82xx_t *chip) strcpy(sid.name, "PCM Playback Volume"); sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; if (! snd_ctl_find_id(chip->card, &sid)) { + snd_printd(KERN_INFO "Using DXS as PCM Playback\n"); + err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_pcmdxs_volume_control, chip)); + if (err < 0) + return err; + } + else /* Using DXS when PCM emulation is enabled is really weird */ + { + /* Standalone DXS controls */ err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs_volume_control, chip)); if (err < 0) return err; } } - /* select spdif data slot 10/11 */ pci_read_config_byte(chip->pci, VIA8233_SPDIF_CTRL, &val); val = (val & ~VIA8233_SPDIF_SLOT_MASK) | VIA8233_SPDIF_SLOT_1011; @@ -1941,8 +1991,10 @@ static int snd_via82xx_chip_init(via82xx_t *chip) int i, idx; for (idx = 0; idx < 4; idx++) { unsigned long port = chip->port + 0x10 * idx; - for (i = 0; i < 2; i++) - outb(chip->playback_volume[i], port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i); + for (i = 0; i < 2; i++) { + chip->playback_volume[idx][i]=chip->playback_volume_c[i]; + outb(chip->playback_volume_c[i], port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i); + } } } -- cgit v1.2.3 From f0597a416dc44e3afe25090e9af9d42bad62547d Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 17 Oct 2005 17:15:46 +0200 Subject: [ALSA] usb-audio: don't call usb_reset_configuration() when probing Modules: USB generic driver Remove the usb_reset_configuration() call from the probe callback because it isn't needed and it may interfere with other drivers already loaded for the device. Signed-off-by: Clemens Ladisch --- sound/usb/usbaudio.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 4589c637a25..fce6ad62df6 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -3212,7 +3212,6 @@ static void *snd_usb_audio_probe(struct usb_device *dev, struct usb_interface *intf, const struct usb_device_id *usb_id) { - struct usb_host_config *config = dev->actconfig; const snd_usb_audio_quirk_t *quirk = (const snd_usb_audio_quirk_t *)usb_id->driver_info; int i, err; snd_usb_audio_t *chip; @@ -3233,7 +3232,6 @@ static void *snd_usb_audio_probe(struct usb_device *dev, if (id == USB_ID(0x041e, 0x3000)) { if (snd_usb_extigy_boot_quirk(dev, intf) < 0) goto __err_val; - config = dev->actconfig; } /* SB Audigy 2 NX needs its own boot-up magic, too */ if (id == USB_ID(0x041e, 0x3020)) { @@ -3262,11 +3260,6 @@ static void *snd_usb_audio_probe(struct usb_device *dev, /* it's a fresh one. * now look for an empty slot and create a new card instance */ - /* first, set the current configuration for this device */ - if (usb_reset_configuration(dev) < 0) { - snd_printk(KERN_ERR "cannot reset configuration (value 0x%x)\n", get_cfg_desc(config)->bConfigurationValue); - goto __error; - } for (i = 0; i < SNDRV_CARDS; i++) if (enable[i] && ! usb_chip[i] && (vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) && -- cgit v1.2.3 From 4f550df58f4758ea023704b409830ad9c3b47771 Mon Sep 17 00:00:00 2001 From: Karsten Wiese Date: Tue, 18 Oct 2005 14:31:07 +0200 Subject: [ALSA] Reduce interrupt latency in sound/pci/via82xx.c Modules: VIA82xx driver The change only affects the via823x kind of chips. Here the via8233_pcm_pointer_hw() function (named snd_via8233_pcm_pointer() before) needed to loop until a non zero position is red from the chip. Measurements have shown that more than 200 loops are typically needed on an Athlon64. As io-reads cost many cycles, those loops sum up huge. via8233_pcm_pointer_hw() runs either in interrupt or with interrupts disabled. So it introduces significant interrupt latency. The patch introduces a calculated position value hwptr_done, that is updated by the interrupt routine when a period is completed. It is only used, if the 823x chip returns a zero position, which can't be interpreted reliably. Further optimisation is applied on the 8233 chip's interrupt routine: Only the SGD_SHADOW is read, as it contains all infos needed. We ommit ~5 more register reads that way. Signed-off-by: Karsten Wiese Signed-off-by: Takashi Iwai --- sound/pci/via82xx.c | 170 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 131 insertions(+), 39 deletions(-) diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 7d46bee828c..eb35b446235 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -41,6 +41,9 @@ * device for applications. * - clean up the code, separate low-level initialization * routines for each chipset. + * + * Sep. 26, 2005 Karsten Wiese + * - Optimize position calculation for the 823x chips. */ #include @@ -131,6 +134,7 @@ module_param(enable, int, 0444); /* common offsets */ #define VIA_REG_OFFSET_STATUS 0x00 /* byte - channel status */ #define VIA_REG_STAT_ACTIVE 0x80 /* RO */ +#define VIA8233_SHADOW_STAT_ACTIVE 0x08 /* RO */ #define VIA_REG_STAT_PAUSED 0x40 /* RO */ #define VIA_REG_STAT_TRIGGER_QUEUED 0x08 /* RO */ #define VIA_REG_STAT_STOPPED 0x04 /* RWC */ @@ -329,6 +333,9 @@ struct via_dev { unsigned int fragsize; unsigned int bufsize; unsigned int bufsize2; + int hwptr_done; /* processed frame position in the buffer */ + int in_interrupt; + int shadow_shift; }; @@ -395,8 +402,10 @@ struct _snd_via82xx { }; static struct pci_device_id snd_via82xx_ids[] = { - { 0x1106, 0x3058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA686, }, /* 686A */ - { 0x1106, 0x3059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA8233, }, /* VT8233 */ + /* 0x1106, 0x3058 */ + { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA686, }, /* 686A */ + /* 0x1106, 0x3059 */ + { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA8233, }, /* VT8233 */ { 0, } }; @@ -550,7 +559,7 @@ static void snd_via82xx_codec_write(ac97_t *ac97, { via82xx_t *chip = ac97->private_data; unsigned int xval; - + xval = !ac97->num ? VIA_REG_AC97_CODEC_ID_PRIMARY : VIA_REG_AC97_CODEC_ID_SECONDARY; xval <<= VIA_REG_AC97_CODEC_ID_SHIFT; xval |= reg << VIA_REG_AC97_CMD_SHIFT; @@ -598,14 +607,15 @@ static void snd_via82xx_channel_reset(via82xx_t *chip, viadev_t *viadev) outb(0x00, VIADEV_REG(viadev, OFFSET_TYPE)); /* for via686 */ // outl(0, VIADEV_REG(viadev, OFFSET_CURR_PTR)); viadev->lastpos = 0; + viadev->hwptr_done = 0; } /* * Interrupt handler + * Used for 686 and 8233A */ - -static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t snd_via686_interrupt(int irq, void *dev_id, struct pt_regs *regs) { via82xx_t *chip = dev_id; unsigned int status; @@ -624,13 +634,23 @@ static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id, struct pt_regs * for (i = 0; i < chip->num_devs; i++) { viadev_t *viadev = &chip->devs[i]; unsigned char c_status = inb(VIADEV_REG(viadev, OFFSET_STATUS)); - c_status &= (VIA_REG_STAT_EOL|VIA_REG_STAT_FLAG|VIA_REG_STAT_STOPPED); - if (! c_status) + if (! (c_status & (VIA_REG_STAT_EOL|VIA_REG_STAT_FLAG|VIA_REG_STAT_STOPPED))) continue; if (viadev->substream && viadev->running) { + /* + * Update hwptr_done based on 'period elapsed' + * interrupts. We'll use it, when the chip returns 0 + * for OFFSET_CURR_COUNT. + */ + if (c_status & VIA_REG_STAT_EOL) + viadev->hwptr_done = 0; + else + viadev->hwptr_done += viadev->fragsize; + viadev->in_interrupt = c_status; spin_unlock(&chip->reg_lock); snd_pcm_period_elapsed(viadev->substream); spin_lock(&chip->reg_lock); + viadev->in_interrupt = 0; } outb(c_status, VIADEV_REG(viadev, OFFSET_STATUS)); /* ack */ } @@ -638,6 +658,60 @@ static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id, struct pt_regs * return IRQ_HANDLED; } +/* + * Interrupt handler + */ +static irqreturn_t snd_via8233_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + via82xx_t *chip = dev_id; + unsigned int status; + unsigned int i; + int irqreturn = 0; + + /* check status for each stream */ + spin_lock(&chip->reg_lock); + status = inl(VIAREG(chip, SGD_SHADOW)); + + for (i = 0; i < chip->num_devs; i++) { + viadev_t *viadev = &chip->devs[i]; + snd_pcm_substream_t *substream; + unsigned char c_status, shadow_status; + + shadow_status = (status >> viadev->shadow_shift) & + (VIA8233_SHADOW_STAT_ACTIVE|VIA_REG_STAT_EOL| + VIA_REG_STAT_FLAG); + c_status = shadow_status & (VIA_REG_STAT_EOL|VIA_REG_STAT_FLAG); + if (!c_status) + continue; + + substream = viadev->substream; + if (substream && viadev->running) { + /* + * Update hwptr_done based on 'period elapsed' + * interrupts. We'll use it, when the chip returns 0 + * for OFFSET_CURR_COUNT. + */ + if (c_status & VIA_REG_STAT_EOL) + viadev->hwptr_done = 0; + else + viadev->hwptr_done += viadev->fragsize; + viadev->in_interrupt = c_status; + if (shadow_status & VIA8233_SHADOW_STAT_ACTIVE) + viadev->in_interrupt |= VIA_REG_STAT_ACTIVE; + spin_unlock(&chip->reg_lock); + + snd_pcm_period_elapsed(substream); + + spin_lock(&chip->reg_lock); + viadev->in_interrupt = 0; + } + outb(c_status, VIADEV_REG(viadev, OFFSET_STATUS)); /* ack */ + irqreturn = 1; + } + spin_unlock(&chip->reg_lock); + return IRQ_RETVAL(irqreturn); +} + /* * PCM callbacks */ @@ -701,6 +775,8 @@ static inline unsigned int calc_linear_pos(viadev_t *viadev, unsigned int idx, u size = viadev->idx_table[idx].size; base = viadev->idx_table[idx].offset; res = base + size - count; + if (res >= viadev->bufsize) + res -= viadev->bufsize; /* check the validity of the calculated position */ if (size < count) { @@ -730,9 +806,6 @@ static inline unsigned int calc_linear_pos(viadev_t *viadev, unsigned int idx, u } } } - viadev->lastpos = res; /* remember the last position */ - if (res >= viadev->bufsize) - res -= viadev->bufsize; return res; } @@ -760,6 +833,7 @@ static snd_pcm_uframes_t snd_via686_pcm_pointer(snd_pcm_substream_t *substream) else /* CURR_PTR holds the address + 8 */ idx = ((ptr - (unsigned int)viadev->table.addr) / 8 - 1) % viadev->tbl_entries; res = calc_linear_pos(viadev, idx, count); + viadev->lastpos = res; /* remember the last position */ spin_unlock(&chip->reg_lock); return bytes_to_frames(substream->runtime, res); @@ -773,30 +847,44 @@ static snd_pcm_uframes_t snd_via8233_pcm_pointer(snd_pcm_substream_t *substream) via82xx_t *chip = snd_pcm_substream_chip(substream); viadev_t *viadev = (viadev_t *)substream->runtime->private_data; unsigned int idx, count, res; - int timeout = 5000; + int status; snd_assert(viadev->tbl_entries, return 0); - if (!(inb(VIADEV_REG(viadev, OFFSET_STATUS)) & VIA_REG_STAT_ACTIVE)) - return 0; + spin_lock(&chip->reg_lock); - do { - count = inl(VIADEV_REG(viadev, OFFSET_CURR_COUNT)); - /* some mobos read 0 count */ - if ((count & 0xffffff) || ! viadev->running) - break; - } while (--timeout); - if (! timeout) - snd_printd(KERN_ERR "zero position is read\n"); - idx = count >> 24; - if (idx >= viadev->tbl_entries) { + count = inl(VIADEV_REG(viadev, OFFSET_CURR_COUNT)); + status = viadev->in_interrupt; + if (!status) + status = inb(VIADEV_REG(viadev, OFFSET_STATUS)); + + if (!(status & VIA_REG_STAT_ACTIVE)) { + res = 0; + goto unlock; + } + if (count & 0xffffff) { + idx = count >> 24; + if (idx >= viadev->tbl_entries) { #ifdef POINTER_DEBUG - printk("fail: invalid idx = %i/%i\n", idx, viadev->tbl_entries); + printk("fail: invalid idx = %i/%i\n", idx, viadev->tbl_entries); #endif - res = viadev->lastpos; + res = viadev->lastpos; + } else { + count &= 0xffffff; + res = calc_linear_pos(viadev, idx, count); + } } else { - count &= 0xffffff; - res = calc_linear_pos(viadev, idx, count); - } + res = viadev->hwptr_done; + if (!viadev->in_interrupt) { + if (status & VIA_REG_STAT_EOL) { + res = 0; + } else + if (status & VIA_REG_STAT_FLAG) { + res += viadev->fragsize; + } + } + } +unlock: + viadev->lastpos = res; spin_unlock(&chip->reg_lock); return bytes_to_frames(substream->runtime, res); @@ -1241,9 +1329,10 @@ static snd_pcm_ops_t snd_via8233_capture_ops = { }; -static void init_viadev(via82xx_t *chip, int idx, unsigned int reg_offset, int direction) +static void init_viadev(via82xx_t *chip, int idx, unsigned int reg_offset, int shadow_pos, int direction) { chip->devs[idx].reg_offset = reg_offset; + chip->devs[idx].shadow_shift = shadow_pos * 4; chip->devs[idx].direction = direction; chip->devs[idx].port = chip->port + reg_offset; } @@ -1273,9 +1362,9 @@ static int __devinit snd_via8233_pcm_new(via82xx_t *chip) chip->pcms[0] = pcm; /* set up playbacks */ for (i = 0; i < 4; i++) - init_viadev(chip, i, 0x10 * i, 0); + init_viadev(chip, i, 0x10 * i, i, 0); /* capture */ - init_viadev(chip, chip->capture_devno, VIA_REG_CAPTURE_8233_STATUS, 1); + init_viadev(chip, chip->capture_devno, VIA_REG_CAPTURE_8233_STATUS, 6, 1); if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) @@ -1291,9 +1380,9 @@ static int __devinit snd_via8233_pcm_new(via82xx_t *chip) strcpy(pcm->name, chip->card->shortname); chip->pcms[1] = pcm; /* set up playback */ - init_viadev(chip, chip->multi_devno, VIA_REG_MULTPLAY_STATUS, 0); + init_viadev(chip, chip->multi_devno, VIA_REG_MULTPLAY_STATUS, 4, 0); /* set up capture */ - init_viadev(chip, chip->capture_devno + 1, VIA_REG_CAPTURE_8233_STATUS + 0x10, 1); + init_viadev(chip, chip->capture_devno + 1, VIA_REG_CAPTURE_8233_STATUS + 0x10, 7, 1); if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) @@ -1326,9 +1415,9 @@ static int __devinit snd_via8233a_pcm_new(via82xx_t *chip) strcpy(pcm->name, chip->card->shortname); chip->pcms[0] = pcm; /* set up playback */ - init_viadev(chip, chip->multi_devno, VIA_REG_MULTPLAY_STATUS, 0); + init_viadev(chip, chip->multi_devno, VIA_REG_MULTPLAY_STATUS, 4, 0); /* capture */ - init_viadev(chip, chip->capture_devno, VIA_REG_CAPTURE_8233_STATUS, 1); + init_viadev(chip, chip->capture_devno, VIA_REG_CAPTURE_8233_STATUS, 6, 1); if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) @@ -1347,7 +1436,7 @@ static int __devinit snd_via8233a_pcm_new(via82xx_t *chip) strcpy(pcm->name, chip->card->shortname); chip->pcms[1] = pcm; /* set up playback */ - init_viadev(chip, chip->playback_devno, 0x30, 0); + init_viadev(chip, chip->playback_devno, 0x30, 3, 0); if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) @@ -1377,8 +1466,8 @@ static int __devinit snd_via686_pcm_new(via82xx_t *chip) pcm->private_data = chip; strcpy(pcm->name, chip->card->shortname); chip->pcms[0] = pcm; - init_viadev(chip, 0, VIA_REG_PLAYBACK_STATUS, 0); - init_viadev(chip, 1, VIA_REG_CAPTURE_STATUS, 1); + init_viadev(chip, 0, VIA_REG_PLAYBACK_STATUS, 0, 0); + init_viadev(chip, 1, VIA_REG_CAPTURE_STATUS, 0, 1); if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0) @@ -2134,7 +2223,10 @@ static int __devinit snd_via82xx_create(snd_card_t * card, return err; } chip->port = pci_resource_start(pci, 0); - if (request_irq(pci->irq, snd_via82xx_interrupt, SA_INTERRUPT|SA_SHIRQ, + if (request_irq(pci->irq, + chip_type == TYPE_VIA8233 ? + snd_via8233_interrupt : snd_via686_interrupt, + SA_INTERRUPT|SA_SHIRQ, card->driver, (void *)chip)) { snd_printk("unable to grab IRQ %d\n", pci->irq); snd_via82xx_free(chip); -- cgit v1.2.3 From c829b052de189b3ca4fb76d2f61917b67e12b83d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Oct 2005 18:03:35 +0200 Subject: [ALSA] intel8x0 - Fix handling of module parameters Modules: Intel8x0 driver - Set buggy_irq parameter before registration of irq handler. - Clean up module parameter handling. Signed-off-by: Takashi Iwai --- sound/pci/intel8x0.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index fc2fba8129e..d16ef527716 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -2563,7 +2563,6 @@ struct ich_reg_info { static int __devinit snd_intel8x0_create(snd_card_t * card, struct pci_dev *pci, unsigned long device_type, - int buggy_sem, intel8x0_t ** r_intel8x0) { intel8x0_t *chip; @@ -2621,7 +2620,12 @@ static int __devinit snd_intel8x0_create(snd_card_t * card, chip->card = card; chip->pci = pci; chip->irq = -1; - chip->buggy_semaphore = buggy_sem; + + /* module parameters */ + chip->buggy_irq = buggy_irq; + chip->buggy_semaphore = buggy_semaphore; + if (xbox) + chip->xbox = 1; if (pci->vendor == PCI_VENDOR_ID_INTEL && pci->device == PCI_DEVICE_ID_INTEL_440MX) @@ -2819,14 +2823,10 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci, } if ((err = snd_intel8x0_create(card, pci, pci_id->driver_data, - buggy_semaphore, &chip)) < 0) { + &chip)) < 0) { snd_card_free(card); return err; } - if (buggy_irq) - chip->buggy_irq = 1; - if (xbox) - chip->xbox = 1; if ((err = snd_intel8x0_mixer(chip, ac97_clock, ac97_quirk)) < 0) { snd_card_free(card); -- cgit v1.2.3 From 051b51653309db976c9665f8d4b1774fa1f8124a Mon Sep 17 00:00:00 2001 From: "Charles R. Anderson" Date: Tue, 18 Oct 2005 18:04:36 +0200 Subject: [ALSA] Fix maestro3 hang after cold boot Modules: Maestro3 driver This patch fixes the maestro3 driver to call the snd_m3_assp_init function to write the DSP firmware into the ASSP chip before sending the RUN_ASSP command, thereby solving the hang after a cold boot. Signed-off-by: Charles R. Anderson Signed-off-by: Takashi Iwai --- sound/pci/maestro3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 2693b6f731f..7b1b82521cf 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -2476,6 +2476,7 @@ snd_m3_chip_init(m3_t *chip) t |= ASSP_0_WS_ENABLE; outb(t, chip->iobase + ASSP_CONTROL_A); + snd_m3_assp_init(chip); /* download DSP code before starting ASSP below */ outb(RUN_ASSP, chip->iobase + ASSP_CONTROL_B); outb(0x00, io + HARDWARE_VOL_CTRL); @@ -2734,7 +2735,6 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci, snd_m3_ac97_reset(chip); - snd_m3_assp_init(chip); snd_m3_amp_enable(chip, 1); tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip); -- cgit v1.2.3 From 87ef7779be825c187747b6b39a24d5326d610c53 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 19 Oct 2005 14:38:30 +0200 Subject: [ALSA] seq-timer: restrict timer frequencies Modules: ALSA sequencer When no default timer frequency has been set, initialize_timer() just uses the maximum frequency supported by the timer, which is ridiculously high on 96 kHz timers. This patch introduces a default frequency of 1000 Hz for this case, and makes sure that a frequency set by the user isn't too high. Signed-off-by: Clemens Ladisch --- sound/core/seq/seq_timer.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c index 9c87d9f8ba9..65b64a7c456 100644 --- a/sound/core/seq/seq_timer.c +++ b/sound/core/seq/seq_timer.c @@ -34,6 +34,11 @@ extern int seq_default_timer_device; extern int seq_default_timer_subdevice; extern int seq_default_timer_resolution; +/* allowed sequencer timer frequencies, in Hz */ +#define MIN_FREQUENCY 10 +#define MAX_FREQUENCY 6250 +#define DEFAULT_FREQUENCY 1000 + #define SKEW_BASE 0x10000 /* 16bit shift */ static void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick, @@ -325,17 +330,26 @@ int snd_seq_timer_stop(seq_timer_t * tmr) static int initialize_timer(seq_timer_t *tmr) { snd_timer_t *t; + unsigned long freq; + t = tmr->timeri->timer; snd_assert(t, return -EINVAL); + freq = tmr->preferred_resolution; + if (!freq) + freq = DEFAULT_FREQUENCY; + else if (freq < MIN_FREQUENCY) + freq = MIN_FREQUENCY; + else if (freq > MAX_FREQUENCY) + freq = MAX_FREQUENCY; + tmr->ticks = 1; - if (tmr->preferred_resolution && - ! (t->hw.flags & SNDRV_TIMER_HW_SLAVE)) { + if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE)) { unsigned long r = t->hw.resolution; if (! r && t->hw.c_resolution) r = t->hw.c_resolution(t); if (r) { - tmr->ticks = (unsigned int)(1000000000uL / (r * tmr->preferred_resolution)); + tmr->ticks = (unsigned int)(1000000000uL / (r * freq)); if (! tmr->ticks) tmr->ticks = 1; } -- cgit v1.2.3 From d44c39acafff98590b9bcdecb44dbbc3f7714b4a Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 19 Oct 2005 14:39:48 +0200 Subject: [ALSA] ymfpci: change timer resolution to 48 kHz Modules: YMFPCI driver We better pretend that the ymfpci timer runs at 48 kHz because the interrupt frequency cannot be higher, and clients that would try to use 96 kHz would run at half their desired speed. Signed-off-by: Clemens Ladisch --- sound/pci/ymfpci/ymfpci_main.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index c0aaade772d..d27f3b56b51 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -1851,9 +1851,7 @@ static int snd_ymfpci_timer_start(snd_timer_t *timer) unsigned int count; chip = snd_timer_chip(timer); - count = timer->sticks - 1; - if (count == 0) /* minimum time is 20.8 us */ - count = 1; + count = (timer->sticks << 1) - 1; spin_lock_irqsave(&chip->reg_lock, flags); snd_ymfpci_writew(chip, YDSXGR_TIMERCOUNT, count); snd_ymfpci_writeb(chip, YDSXGR_TIMERCTRL, 0x03); @@ -1877,14 +1875,14 @@ static int snd_ymfpci_timer_precise_resolution(snd_timer_t *timer, unsigned long *num, unsigned long *den) { *num = 1; - *den = 96000; + *den = 48000; return 0; } static struct _snd_timer_hardware snd_ymfpci_timer_hw = { .flags = SNDRV_TIMER_HW_AUTO, - .resolution = 10417, /* 1/2fs = 10.41666...us */ - .ticks = 65536, + .resolution = 20833, /* 1/fs = 20.8333...us */ + .ticks = 0x8000, .start = snd_ymfpci_timer_start, .stop = snd_ymfpci_timer_stop, .precise_resolution = snd_ymfpci_timer_precise_resolution, -- cgit v1.2.3 From 47530cf44cb5f3945ed04a5ae65d06bf423cd97b Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 19 Oct 2005 16:03:10 +0200 Subject: [ALSA] nm256: reset workaround for Latitude CSx Modules: NM256 driver The current snd-nm256 driver can cause Dell Latitude CSx laptops to lock-up during module (un)load. I have isolated this to the writes to the control port register at offset 0x6cc which were not already protected by the existing reset_workaround. I tried grouping these writes with the existing reset_workaround clause, but that caused the driver to have (un)load problems on the Dell Latitude LS laptops. So, I have implemented a reset_workaround_2 clause (please feel free to suggest a better name!) to cover this situation and added a quirk entry for the CSx laptops. Signed-off-by: John W. Linville Signed-off-by: Takashi Iwai --- sound/pci/nm256/nm256.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index ebfa38b5112..d0da9a53de0 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -62,6 +62,7 @@ static int buffer_top[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* not spe static int use_cache[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* disabled */ static int vaio_hack[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* disabled */ static int reset_workaround[SNDRV_CARDS]; +static int reset_workaround_2[SNDRV_CARDS]; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); @@ -83,6 +84,8 @@ module_param_array(vaio_hack, bool, NULL, 0444); MODULE_PARM_DESC(vaio_hack, "Enable workaround for Sony VAIO notebooks."); module_param_array(reset_workaround, bool, NULL, 0444); MODULE_PARM_DESC(reset_workaround, "Enable AC97 RESET workaround for some laptops."); +module_param_array(reset_workaround_2, bool, NULL, 0444); +MODULE_PARM_DESC(reset_workaround_2, "Enable extended AC97 RESET workaround for some other laptops."); /* * hw definitions @@ -226,6 +229,7 @@ struct snd_nm256 { unsigned int coeffs_current: 1; /* coeff. table is loaded? */ unsigned int use_cache: 1; /* use one big coef. table */ unsigned int reset_workaround: 1; /* Workaround for some laptops to avoid freeze */ + unsigned int reset_workaround_2: 1; /* Extended workaround for some other laptops to avoid freeze */ int mixer_base; /* register offset of ac97 mixer */ int mixer_status_offset; /* offset of mixer status reg. */ @@ -1199,8 +1203,11 @@ snd_nm256_ac97_reset(ac97_t *ac97) /* Dell latitude LS will lock up by this */ snd_nm256_writeb(chip, 0x6cc, 0x87); } - snd_nm256_writeb(chip, 0x6cc, 0x80); - snd_nm256_writeb(chip, 0x6cc, 0x0); + if (! chip->reset_workaround_2) { + /* Dell latitude CSx will lock up by this */ + snd_nm256_writeb(chip, 0x6cc, 0x80); + snd_nm256_writeb(chip, 0x6cc, 0x0); + } } /* create an ac97 mixer interface */ @@ -1536,7 +1543,7 @@ struct nm256_quirk { int type; }; -enum { NM_BLACKLISTED, NM_RESET_WORKAROUND }; +enum { NM_BLACKLISTED, NM_RESET_WORKAROUND, NM_RESET_WORKAROUND_2 }; static struct nm256_quirk nm256_quirks[] __devinitdata = { /* HP omnibook 4150 has cs4232 codec internally */ @@ -1545,6 +1552,8 @@ static struct nm256_quirk nm256_quirks[] __devinitdata = { { .vendor = 0x104d, .device = 0x8041, .type = NM_RESET_WORKAROUND }, /* Dell Latitude LS */ { .vendor = 0x1028, .device = 0x0080, .type = NM_RESET_WORKAROUND }, + /* Dell Latitude CSx */ + { .vendor = 0x1028, .device = 0x0091, .type = NM_RESET_WORKAROUND_2 }, { } /* terminator */ }; @@ -1576,6 +1585,9 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci, case NM_BLACKLISTED: printk(KERN_INFO "nm256: The device is blacklisted. Loading stopped\n"); return -ENODEV; + case NM_RESET_WORKAROUND_2: + reset_workaround_2[dev] = 1; + /* Fall-through */ case NM_RESET_WORKAROUND: reset_workaround[dev] = 1; break; @@ -1632,6 +1644,11 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci, chip->reset_workaround = 1; } + if (reset_workaround_2[dev]) { + snd_printdd(KERN_INFO "nm256: reset_workaround_2 activated\n"); + chip->reset_workaround_2 = 1; + } + if ((err = snd_nm256_pcm(chip, 0)) < 0 || (err = snd_nm256_mixer(chip)) < 0) { snd_card_free(card); -- cgit v1.2.3 From d1f38cf9f8fcb486a027bb5adc214558d7830f45 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 19 Oct 2005 16:04:27 +0200 Subject: [ALSA] Add description about a new option of nm256 driver Modules: Documentation Add description about a new option of nm256 driver. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 46a125003b0..9342846c7c4 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -954,6 +954,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. use_cache - 0 or 1 (disabled by default) vaio_hack - alias buffer_top=0x25a800 reset_workaround - enable AC97 RESET workaround for some laptops + reset_workaround2 - enable extended AC97 RESET workaround for some + other laptops Module supports autoprobe and multiple chips (max 8). @@ -984,6 +986,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. workaround is enabled automatically. For other laptops with a hard freeze, you can try reset_workaround=1 option. + Note: Dell Latitude CSx laptops have another problem regarding + AC97 RESET. On these laptops, reset_workaround2 option is + turned on as default. This option is worth to try if the + previous reset_workaround option doesn't help. + Note: This driver is really crappy. It's a porting from the OSS driver, which is a result of black-magic reverse engineering. The detection of codec will fail if the driver is loaded *after* -- cgit v1.2.3 From 698444f31788bd9992f7c31bcc4862d82f985890 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 20 Oct 2005 16:53:49 +0200 Subject: [ALSA] Fix the type of enable module option Fix the type of enable module option to bool. Signed-off-by: Takashi Iwai --- sound/pci/atiixp.c | 2 +- sound/pci/atiixp_modem.c | 2 +- sound/pci/hda/hda_intel.c | 2 +- sound/pci/intel8x0.c | 2 +- sound/pci/intel8x0m.c | 2 +- sound/pci/via82xx.c | 2 +- sound/pci/via82xx_modem.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 14f912ae40d..a9314363abd 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -58,7 +58,7 @@ MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link."); /* just for backward compatibility */ static int enable; -module_param(enable, int, 0444); +module_param(enable, bool, 0444); /* diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index ab39c0b7cce..210eb676945 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -52,7 +52,7 @@ MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz)."); /* just for backward compatibility */ static int enable; -module_param(enable, int, 0444); +module_param(enable, bool, 0444); /* diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 1426fa0ac6d..9d1412a9f2f 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -63,7 +63,7 @@ MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, /* just for backward compatibility */ static int enable; -module_param(enable, int, 0444); +module_param(enable, bool, 0444); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index d16ef527716..68d0ed033d3 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -89,7 +89,7 @@ MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 c /* just for backward compatibility */ static int enable; -module_param(enable, int, 0444); +module_param(enable, bool, 0444); static int joystick; module_param(joystick, int, 0444); diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 314f3d8caea..42601f0e6a5 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -69,7 +69,7 @@ MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect)."); /* just for backward compatibility */ static int enable; -module_param(enable, int, 0444); +module_param(enable, bool, 0444); /* * Direct registers diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index eb35b446235..3fdb3b1d4e8 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -105,7 +105,7 @@ MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 /* just for backward compatibility */ static int enable; -module_param(enable, int, 0444); +module_param(enable, bool, 0444); /* revision numbers for via686 */ diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index db7768124f5..ff56eb8552e 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -68,7 +68,7 @@ MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz)."); /* just for backward compatibility */ static int enable; -module_param(enable, int, 0444); +module_param(enable, bool, 0444); /* -- cgit v1.2.3 From 8a3fb4d0ce5cc37a765d59b65a3b3714e5806dc9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 20 Oct 2005 17:10:49 +0200 Subject: [ALSA] Remove multi-card support for ali5451 and nm256 Modules: Documentation,ALI5451 driver,NM256 driver Removed multi-card supports for ali5451 and nm256 drivers. They are supposed to be a single device. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 4 +- sound/pci/ali5451/ali5451.c | 37 ++++----- sound/pci/nm256/nm256.c | 100 +++++++++++------------- 3 files changed, 64 insertions(+), 77 deletions(-) diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 9342846c7c4..2f27f391c7c 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -167,7 +167,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. spdif - Support SPDIF I/O - Default: disabled - Module supports autoprobe and multiple chips (max 8). + This module supports one chip and autoprobe. The power-management is supported. @@ -957,7 +957,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. reset_workaround2 - enable extended AC97 RESET workaround for some other laptops - Module supports autoprobe and multiple chips (max 8). + This module supports one chip and autoprobe. The power-management is supported. diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 01d971c89e4..1f747c3034f 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -45,23 +45,25 @@ MODULE_DESCRIPTION("ALI M5451"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{ALI,M5451,pci},{ALI,M5451}}"); -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; -static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 32}; -static int spdif[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; +static int index = SNDRV_DEFAULT_IDX1; /* Index */ +static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ +static int pcm_channels = 32; +static int spdif = 0; -module_param_array(index, int, NULL, 0444); +module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for ALI M5451 PCI Audio."); -module_param_array(id, charp, NULL, 0444); +module_param(id, charp, 0444); MODULE_PARM_DESC(id, "ID string for ALI M5451 PCI Audio."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable ALI 5451 PCI Audio."); -module_param_array(pcm_channels, int, NULL, 0444); +module_param(pcm_channels, int, 0444); MODULE_PARM_DESC(pcm_channels, "PCM Channels"); -module_param_array(spdif, bool, NULL, 0444); +module_param(spdif, bool, 0444); MODULE_PARM_DESC(spdif, "Support SPDIF I/O"); +/* just for backward compatibility */ +static int enable; +module_param(enable, bool, 0444); + + /* * Debug part definitions */ @@ -2353,25 +2355,17 @@ static int __devinit snd_ali_create(snd_card_t * card, static int __devinit snd_ali_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { - static int dev; snd_card_t *card; ali_t *codec; int err; snd_ali_printk("probe ...\n"); - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); + card = snd_card_new(index, id, THIS_MODULE, 0); if (card == NULL) return -ENOMEM; - if ((err = snd_ali_create(card, pci, pcm_channels[dev], spdif[dev], &codec)) < 0) { + if ((err = snd_ali_create(card, pci, pcm_channels, spdif, &codec)) < 0) { snd_card_free(card); return err; } @@ -2402,7 +2396,6 @@ static int __devinit snd_ali_probe(struct pci_dev *pci, return err; } pci_set_drvdata(pci, card); - dev++; return 0; } diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index d0da9a53de0..cccdc576b8a 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -52,41 +52,44 @@ MODULE_SUPPORTED_DEVICE("{{NeoMagic,NM256AV}," * some compile conditions. */ -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; -static int playback_bufsize[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 16}; -static int capture_bufsize[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 16}; -static int force_ac97[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* disabled as default */ -static int buffer_top[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* not specified */ -static int use_cache[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* disabled */ -static int vaio_hack[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* disabled */ -static int reset_workaround[SNDRV_CARDS]; -static int reset_workaround_2[SNDRV_CARDS]; - -module_param_array(index, int, NULL, 0444); +static int index = SNDRV_DEFAULT_IDX1; /* Index */ +static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ +static int playback_bufsize = 16; +static int capture_bufsize = 16; +static int force_ac97; /* disabled as default */ +static int buffer_top; /* not specified */ +static int use_cache; /* disabled */ +static int vaio_hack; /* disabled */ +static int reset_workaround; +static int reset_workaround_2; + +module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); +module_param(id, charp, 0444); MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable this soundcard."); -module_param_array(playback_bufsize, int, NULL, 0444); +module_param(playback_bufsize, int, 0444); MODULE_PARM_DESC(playback_bufsize, "DAC frame size in kB for " CARD_NAME " soundcard."); -module_param_array(capture_bufsize, int, NULL, 0444); +module_param(capture_bufsize, int, 0444); MODULE_PARM_DESC(capture_bufsize, "ADC frame size in kB for " CARD_NAME " soundcard."); -module_param_array(force_ac97, bool, NULL, 0444); +module_param(force_ac97, bool, 0444); MODULE_PARM_DESC(force_ac97, "Force to use AC97 codec for " CARD_NAME " soundcard."); -module_param_array(buffer_top, int, NULL, 0444); +module_param(buffer_top, int, 0444); MODULE_PARM_DESC(buffer_top, "Set the top address of audio buffer for " CARD_NAME " soundcard."); -module_param_array(use_cache, bool, NULL, 0444); +module_param(use_cache, bool, 0444); MODULE_PARM_DESC(use_cache, "Enable the cache for coefficient table access."); -module_param_array(vaio_hack, bool, NULL, 0444); +module_param(vaio_hack, bool, 0444); MODULE_PARM_DESC(vaio_hack, "Enable workaround for Sony VAIO notebooks."); -module_param_array(reset_workaround, bool, NULL, 0444); +module_param(reset_workaround, bool, 0444); MODULE_PARM_DESC(reset_workaround, "Enable AC97 RESET workaround for some laptops."); -module_param_array(reset_workaround_2, bool, NULL, 0444); +module_param(reset_workaround_2, bool, 0444); MODULE_PARM_DESC(reset_workaround_2, "Enable extended AC97 RESET workaround for some other laptops."); +/* just for backward compatibility */ +static int enable; +module_param(enable, bool, 0444); + + + /* * hw definitions */ @@ -1561,7 +1564,6 @@ static struct nm256_quirk nm256_quirks[] __devinitdata = { static int __devinit snd_nm256_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { - static int dev; snd_card_t *card; nm256_t *chip; int err; @@ -1569,13 +1571,6 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci, struct nm256_quirk *q; u16 subsystem_vendor, subsystem_device; - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor); pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device); @@ -1586,16 +1581,16 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci, printk(KERN_INFO "nm256: The device is blacklisted. Loading stopped\n"); return -ENODEV; case NM_RESET_WORKAROUND_2: - reset_workaround_2[dev] = 1; + reset_workaround_2 = 1; /* Fall-through */ case NM_RESET_WORKAROUND: - reset_workaround[dev] = 1; + reset_workaround = 1; break; } } } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); + card = snd_card_new(index, id, THIS_MODULE, 0); if (card == NULL) return -ENOMEM; @@ -1615,36 +1610,36 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci, return -EINVAL; } - if (vaio_hack[dev]) + if (vaio_hack) xbuffer_top = 0x25a800; /* this avoids conflicts with XFree86 server */ else - xbuffer_top = buffer_top[dev]; - - if (playback_bufsize[dev] < 4) - playback_bufsize[dev] = 4; - if (playback_bufsize[dev] > 128) - playback_bufsize[dev] = 128; - if (capture_bufsize[dev] < 4) - capture_bufsize[dev] = 4; - if (capture_bufsize[dev] > 128) - capture_bufsize[dev] = 128; + xbuffer_top = buffer_top; + + if (playback_bufsize < 4) + playback_bufsize = 4; + if (playback_bufsize > 128) + playback_bufsize = 128; + if (capture_bufsize < 4) + capture_bufsize = 4; + if (capture_bufsize > 128) + capture_bufsize = 128; if ((err = snd_nm256_create(card, pci, - playback_bufsize[dev] * 1024, /* in bytes */ - capture_bufsize[dev] * 1024, /* in bytes */ - force_ac97[dev], + playback_bufsize * 1024, /* in bytes */ + capture_bufsize * 1024, /* in bytes */ + force_ac97, xbuffer_top, - use_cache[dev], + use_cache, &chip)) < 0) { snd_card_free(card); return err; } - if (reset_workaround[dev]) { + if (reset_workaround) { snd_printdd(KERN_INFO "nm256: reset_workaround activated\n"); chip->reset_workaround = 1; } - if (reset_workaround_2[dev]) { + if (reset_workaround_2) { snd_printdd(KERN_INFO "nm256: reset_workaround_2 activated\n"); chip->reset_workaround_2 = 1; } @@ -1666,7 +1661,6 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci, } pci_set_drvdata(pci, card); - dev++; return 0; } -- cgit v1.2.3 From 99b359ba10a582148c6725f428a33ba5356dd993 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 20 Oct 2005 18:26:44 +0200 Subject: [ALSA] Add missing KERN_* suffix to printk Add missing KERN_* suffix to printk. Signed-off-by: Takashi Iwai --- sound/i2c/cs8427.c | 14 +++--- sound/i2c/other/ak4114.c | 6 +-- sound/i2c/other/ak4117.c | 8 ++-- sound/i2c/tea6330t.c | 2 +- sound/isa/ad1848/ad1848_lib.c | 16 +++---- sound/isa/es18xx.c | 34 ++++++++------ sound/isa/gus/gus_dma.c | 2 +- sound/isa/gus/gus_io.c | 94 +++++++++++++++++++------------------- sound/isa/gus/gus_main.c | 15 +++--- sound/isa/gus/gus_mem.c | 2 +- sound/isa/gus/gus_pcm.c | 2 +- sound/isa/gus/gus_reset.c | 4 +- sound/isa/gus/gus_simple.c | 2 +- sound/isa/gus/gus_uart.c | 4 +- sound/isa/gus/gus_volume.c | 6 +-- sound/isa/gus/interwave.c | 4 +- sound/isa/sb/emu8000_synth.c | 2 +- sound/isa/sb/sb16_main.c | 8 ++-- sound/isa/sb/sb8_main.c | 3 -- sound/isa/sb/sb_common.c | 6 +-- sound/isa/sb/sb_mixer.c | 4 +- sound/pci/ali5451/ali5451.c | 38 +++++++-------- sound/pci/als4000.c | 2 +- sound/pci/au88x0/au88x0.c | 2 +- sound/pci/au88x0/au88x0_a3d.c | 2 +- sound/pci/au88x0/au88x0_core.c | 4 +- sound/pci/au88x0/au88x0_eq.c | 2 +- sound/pci/au88x0/au88x0_synth.c | 8 ++-- sound/pci/azt3328.c | 18 ++++---- sound/pci/ca0106/ca0106_main.c | 6 +-- sound/pci/cmipci.c | 2 +- sound/pci/cs46xx/cs46xx_lib.c | 38 +++++++-------- sound/pci/emu10k1/emu10k1.c | 2 +- sound/pci/emu10k1/emufx.c | 2 +- sound/pci/emu10k1/irq.c | 2 +- sound/pci/emu10k1/memory.c | 6 +-- sound/pci/emu10k1/p16v.c | 2 +- sound/pci/ens1370.c | 14 +++--- sound/pci/es1938.c | 26 ++++++----- sound/pci/es1968.c | 16 +++---- sound/pci/fm801.c | 16 +++---- sound/pci/ice1712/aureon.c | 4 +- sound/pci/ice1712/delta.c | 2 +- sound/pci/ice1712/ews.c | 6 +-- sound/pci/ice1712/ice1712.c | 10 ++-- sound/pci/ice1712/ice1724.c | 2 +- sound/pci/intel8x0.c | 18 ++++---- sound/pci/intel8x0m.c | 16 +++---- sound/pci/maestro3.c | 10 ++-- sound/pci/nm256/nm256.c | 20 ++++---- sound/pci/rme32.c | 4 +- sound/pci/rme96.c | 4 +- sound/pci/rme9652/rme9652.c | 6 +-- sound/pci/sonicvibes.c | 14 +++--- sound/pci/trident/trident_main.c | 12 ++--- sound/pci/trident/trident_memory.c | 4 +- sound/pci/via82xx.c | 6 +-- sound/pci/via82xx_modem.c | 6 +-- sound/pci/ymfpci/ymfpci.c | 2 +- sound/pci/ymfpci/ymfpci_main.c | 6 +-- 60 files changed, 299 insertions(+), 299 deletions(-) diff --git a/sound/i2c/cs8427.c b/sound/i2c/cs8427.c index a21f7d541f8..21133eb6e88 100644 --- a/sound/i2c/cs8427.c +++ b/sound/i2c/cs8427.c @@ -75,7 +75,7 @@ int snd_cs8427_reg_write(snd_i2c_device_t *device, unsigned char reg, unsigned c buf[0] = reg & 0x7f; buf[1] = val; if ((err = snd_i2c_sendbytes(device, buf, 2)) != 2) { - snd_printk("unable to send bytes 0x%02x:0x%02x to CS8427 (%i)\n", buf[0], buf[1], err); + snd_printk(KERN_ERR "unable to send bytes 0x%02x:0x%02x to CS8427 (%i)\n", buf[0], buf[1], err); return err < 0 ? err : -EIO; } return 0; @@ -87,11 +87,11 @@ static int snd_cs8427_reg_read(snd_i2c_device_t *device, unsigned char reg) unsigned char buf; if ((err = snd_i2c_sendbytes(device, ®, 1)) != 1) { - snd_printk("unable to send register 0x%x byte to CS8427\n", reg); + snd_printk(KERN_ERR "unable to send register 0x%x byte to CS8427\n", reg); return err < 0 ? err : -EIO; } if ((err = snd_i2c_readbytes(device, &buf, 1)) != 1) { - snd_printk("unable to read register 0x%x byte from CS8427\n", reg); + snd_printk(KERN_ERR "unable to read register 0x%x byte from CS8427\n", reg); return err < 0 ? err : -EIO; } return buf; @@ -210,7 +210,7 @@ int snd_cs8427_create(snd_i2c_bus_t *bus, snd_i2c_lock(bus); if ((err = snd_cs8427_reg_read(device, CS8427_REG_ID_AND_VER)) != CS8427_VER8427A) { snd_i2c_unlock(bus); - snd_printk("unable to find CS8427 signature (expected 0x%x, read 0x%x), initialization is not completed\n", CS8427_VER8427A, err); + snd_printk(KERN_ERR "unable to find CS8427 signature (expected 0x%x, read 0x%x), initialization is not completed\n", CS8427_VER8427A, err); return -EFAULT; } /* turn off run bit while making changes to configuration */ @@ -260,7 +260,7 @@ int snd_cs8427_create(snd_i2c_bus_t *bus, snd_i2c_sendbytes(device, buf, 1); snd_i2c_readbytes(device, buf, 127); for (xx = 0; xx < 127; xx++) - printk("reg[0x%x] = 0x%x\n", xx+1, buf[xx]); + printk(KERN_DEBUG "reg[0x%x] = 0x%x\n", xx+1, buf[xx]); } #endif @@ -354,12 +354,12 @@ static int snd_cs8427_qsubcode_get(snd_kcontrol_t *kcontrol, snd_i2c_lock(device->bus); if ((err = snd_i2c_sendbytes(device, ®, 1)) != 1) { - snd_printk("unable to send register 0x%x byte to CS8427\n", reg); + snd_printk(KERN_ERR "unable to send register 0x%x byte to CS8427\n", reg); snd_i2c_unlock(device->bus); return err < 0 ? err : -EIO; } if ((err = snd_i2c_readbytes(device, ucontrol->value.bytes.data, 10)) != 10) { - snd_printk("unable to read Q-subcode bytes from CS8427\n"); + snd_printk(KERN_ERR "unable to read Q-subcode bytes from CS8427\n"); snd_i2c_unlock(device->bus); return err < 0 ? err : -EIO; } diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c index af5eadcddd9..d351b3aa191 100644 --- a/sound/i2c/other/ak4114.c +++ b/sound/i2c/other/ak4114.c @@ -56,9 +56,9 @@ static void reg_dump(ak4114_t *ak4114) { int i; - printk("AK4114 REG DUMP:\n"); + printk(KERN_DEBUG "AK4114 REG DUMP:\n"); for (i = 0; i < 0x20; i++) - printk("reg[%02x] = %02x (%02x)\n", i, reg_read(ak4114, i), i < sizeof(ak4114->regmap) ? ak4114->regmap[i] : 0); + printk(KERN_DEBUG "reg[%02x] = %02x (%02x)\n", i, reg_read(ak4114, i), i < sizeof(ak4114->regmap) ? ak4114->regmap[i] : 0); } #endif @@ -552,7 +552,7 @@ int snd_ak4114_check_rate_and_errors(ak4114_t *ak4114, unsigned int flags) if (!(flags & AK4114_CHECK_NO_RATE) && runtime && runtime->rate != res) { snd_pcm_stream_lock_irqsave(ak4114->capture_substream, _flags); if (snd_pcm_running(ak4114->capture_substream)) { - // printk("rate changed (%i <- %i)\n", runtime->rate, res); + // printk(KERN_DEBUG "rate changed (%i <- %i)\n", runtime->rate, res); snd_pcm_stop(ak4114->capture_substream, SNDRV_PCM_STATE_DRAINING); res = 1; } diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c index d51b51dd86d..35b4584483a 100644 --- a/sound/i2c/other/ak4117.c +++ b/sound/i2c/other/ak4117.c @@ -54,9 +54,9 @@ static void reg_dump(ak4117_t *ak4117) { int i; - printk("AK4117 REG DUMP:\n"); + printk(KERN_DEBUG "AK4117 REG DUMP:\n"); for (i = 0; i < 0x1b; i++) - printk("reg[%02x] = %02x (%02x)\n", i, reg_read(ak4117, i), i < sizeof(ak4117->regmap) ? ak4117->regmap[i] : 0); + printk(KERN_DEBUG "reg[%02x] = %02x (%02x)\n", i, reg_read(ak4117, i), i < sizeof(ak4117->regmap) ? ak4117->regmap[i] : 0); } #endif @@ -477,7 +477,7 @@ int snd_ak4117_check_rate_and_errors(ak4117_t *ak4117, unsigned int flags) goto __rate; rcs0 = reg_read(ak4117, AK4117_REG_RCS0); rcs2 = reg_read(ak4117, AK4117_REG_RCS2); - // printk("AK IRQ: rcs0 = 0x%x, rcs1 = 0x%x, rcs2 = 0x%x\n", rcs0, rcs1, rcs2); + // printk(KERN_DEBUG "AK IRQ: rcs0 = 0x%x, rcs1 = 0x%x, rcs2 = 0x%x\n", rcs0, rcs1, rcs2); spin_lock_irqsave(&ak4117->lock, _flags); if (rcs0 & AK4117_PAR) ak4117->parity_errors++; @@ -530,7 +530,7 @@ int snd_ak4117_check_rate_and_errors(ak4117_t *ak4117, unsigned int flags) if (!(flags & AK4117_CHECK_NO_RATE) && runtime && runtime->rate != res) { snd_pcm_stream_lock_irqsave(ak4117->substream, _flags); if (snd_pcm_running(ak4117->substream)) { - // printk("rate changed (%i <- %i)\n", runtime->rate, res); + // printk(KERN_DEBUG "rate changed (%i <- %i)\n", runtime->rate, res); snd_pcm_stop(ak4117->substream, SNDRV_PCM_STATE_DRAINING); wake_up(&runtime->sleep); res = 1; diff --git a/sound/i2c/tea6330t.c b/sound/i2c/tea6330t.c index fd65da65426..4fdd1fb57df 100644 --- a/sound/i2c/tea6330t.c +++ b/sound/i2c/tea6330t.c @@ -58,7 +58,7 @@ static void snd_tea6330t_set(tea6330t_t *tea, unsigned char addr, unsigned char value) { #if 0 - printk("set - 0x%x/0x%x\n", addr, value); + printk(KERN_DEBUG "set - 0x%x/0x%x\n", addr, value); #endif snd_i2c_write(tea->bus, TEA6330T_ADDR, addr, value, 1); } diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c index 0c2924dfefa..744b65a35c9 100644 --- a/sound/isa/ad1848/ad1848_lib.c +++ b/sound/isa/ad1848/ad1848_lib.c @@ -109,7 +109,7 @@ void snd_ad1848_out(ad1848_t *chip, udelay(100); #ifdef CONFIG_SND_DEBUG if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) - snd_printk("auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); + snd_printk(KERN_WARNING "auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); #endif outb(chip->mce_bit | reg, AD1848P(chip, REGSEL)); outb(chip->image[reg] = value, AD1848P(chip, REG)); @@ -139,7 +139,7 @@ static unsigned char snd_ad1848_in(ad1848_t *chip, unsigned char reg) udelay(100); #ifdef CONFIG_SND_DEBUG if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) - snd_printk("auto calibration time out - reg = 0x%x\n", reg); + snd_printk(KERN_WARNING "auto calibration time out - reg = 0x%x\n", reg); #endif outb(chip->mce_bit | reg, AD1848P(chip, REGSEL)); mb(); @@ -185,13 +185,13 @@ static void snd_ad1848_mce_up(ad1848_t *chip) udelay(100); #ifdef CONFIG_SND_DEBUG if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) - snd_printk("mce_up - auto calibration time out (0)\n"); + snd_printk(KERN_WARNING "mce_up - auto calibration time out (0)\n"); #endif spin_lock_irqsave(&chip->reg_lock, flags); chip->mce_bit |= AD1848_MCE; timeout = inb(AD1848P(chip, REGSEL)); if (timeout == 0x80) - snd_printk("mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port); + snd_printk(KERN_WARNING "mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port); if (!(timeout & AD1848_MCE)) outb(chip->mce_bit | (timeout & 0x1f), AD1848P(chip, REGSEL)); spin_unlock_irqrestore(&chip->reg_lock, flags); @@ -214,13 +214,13 @@ static void snd_ad1848_mce_down(ad1848_t *chip) #endif #ifdef CONFIG_SND_DEBUG if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) - snd_printk("mce_down [0x%lx] - auto calibration time out (0)\n", AD1848P(chip, REGSEL)); + snd_printk(KERN_WARNING "mce_down [0x%lx] - auto calibration time out (0)\n", AD1848P(chip, REGSEL)); #endif chip->mce_bit &= ~AD1848_MCE; timeout = inb(AD1848P(chip, REGSEL)); outb(chip->mce_bit | (timeout & 0x1f), AD1848P(chip, REGSEL)); if (timeout == 0x80) - snd_printk("mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port); + snd_printk(KERN_WARNING "mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port); if ((timeout & AD1848_MCE) == 0) { spin_unlock_irqrestore(&chip->reg_lock, flags); return; @@ -240,7 +240,7 @@ static void snd_ad1848_mce_down(ad1848_t *chip) while (snd_ad1848_in(chip, AD1848_TEST_INIT) & AD1848_CALIB_IN_PROGRESS) { spin_unlock_irqrestore(&chip->reg_lock, flags); if (time <= 0) { - snd_printk("mce_down - auto calibration time out (2)\n"); + snd_printk(KERN_ERR "mce_down - auto calibration time out (2)\n"); return; } set_current_state(TASK_INTERRUPTIBLE); @@ -254,7 +254,7 @@ static void snd_ad1848_mce_down(ad1848_t *chip) while (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) { spin_unlock_irqrestore(&chip->reg_lock, flags); if (time <= 0) { - snd_printk("mce_down - auto calibration time out (3)\n"); + snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n"); return; } set_current_state(TASK_INTERRUPTIBLE); diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index f0f8505cd1a..970e2aaade2 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -173,7 +173,7 @@ static int snd_es18xx_dsp_command(es18xx_t *chip, unsigned char val) outb(val, chip->port + 0x0C); return 0; } - snd_printk("dsp_command: timeout (0x%x)\n", val); + snd_printk(KERN_ERR "dsp_command: timeout (0x%x)\n", val); return -EINVAL; } @@ -184,7 +184,8 @@ static int snd_es18xx_dsp_get_byte(es18xx_t *chip) for(i = MILLISECOND/10; i; i--) if (inb(chip->port + 0x0C) & 0x40) return inb(chip->port + 0x0A); - snd_printk("dsp_get_byte failed: 0x%lx = 0x%x!!!\n", chip->port + 0x0A, inb(chip->port + 0x0A)); + snd_printk(KERN_ERR "dsp_get_byte failed: 0x%lx = 0x%x!!!\n", + chip->port + 0x0A, inb(chip->port + 0x0A)); return -ENODEV; } @@ -204,7 +205,7 @@ static int snd_es18xx_write(es18xx_t *chip, end: spin_unlock_irqrestore(&chip->reg_lock, flags); #ifdef REG_DEBUG - snd_printk("Reg %02x set to %02x\n", reg, data); + snd_printk(KERN_DEBUG "Reg %02x set to %02x\n", reg, data); #endif return ret; } @@ -223,7 +224,7 @@ static int snd_es18xx_read(es18xx_t *chip, unsigned char reg) data = snd_es18xx_dsp_get_byte(chip); ret = data; #ifdef REG_DEBUG - snd_printk("Reg %02x now is %02x (%d)\n", reg, data, ret); + snd_printk(KERN_DEBUG "Reg %02x now is %02x (%d)\n", reg, data, ret); #endif end: spin_unlock_irqrestore(&chip->reg_lock, flags); @@ -259,7 +260,8 @@ static int snd_es18xx_bits(es18xx_t *chip, unsigned char reg, if (ret < 0) goto end; #ifdef REG_DEBUG - snd_printk("Reg %02x was %02x, set to %02x (%d)\n", reg, old, new, ret); + snd_printk(KERN_DEBUG "Reg %02x was %02x, set to %02x (%d)\n", + reg, old, new, ret); #endif } ret = oval; @@ -277,7 +279,7 @@ static inline void snd_es18xx_mixer_write(es18xx_t *chip, outb(data, chip->port + 0x05); spin_unlock_irqrestore(&chip->mixer_lock, flags); #ifdef REG_DEBUG - snd_printk("Mixer reg %02x set to %02x\n", reg, data); + snd_printk(KERN_DEBUG "Mixer reg %02x set to %02x\n", reg, data); #endif } @@ -290,7 +292,7 @@ static inline int snd_es18xx_mixer_read(es18xx_t *chip, unsigned char reg) data = inb(chip->port + 0x05); spin_unlock_irqrestore(&chip->mixer_lock, flags); #ifdef REG_DEBUG - snd_printk("Mixer reg %02x now is %02x\n", reg, data); + snd_printk(KERN_DEBUG "Mixer reg %02x now is %02x\n", reg, data); #endif return data; } @@ -309,7 +311,8 @@ static inline int snd_es18xx_mixer_bits(es18xx_t *chip, unsigned char reg, new = (old & ~mask) | (val & mask); outb(new, chip->port + 0x05); #ifdef REG_DEBUG - snd_printk("Mixer reg %02x was %02x, set to %02x\n", reg, old, new); + snd_printk(KERN_DEBUG "Mixer reg %02x was %02x, set to %02x\n", + reg, old, new); #endif } spin_unlock_irqrestore(&chip->mixer_lock, flags); @@ -329,7 +332,8 @@ static inline int snd_es18xx_mixer_writable(es18xx_t *chip, unsigned char reg, new = inb(chip->port + 0x05); spin_unlock_irqrestore(&chip->mixer_lock, flags); #ifdef REG_DEBUG - snd_printk("Mixer reg %02x was %02x, set to %02x, now is %02x\n", reg, old, expected, new); + snd_printk(KERN_DEBUG "Mixer reg %02x was %02x, set to %02x, now is %02x\n", + reg, old, expected, new); #endif return expected == new; } @@ -1281,7 +1285,7 @@ static void __devinit snd_es18xx_config_write(es18xx_t *chip, outb(reg, chip->ctrl_port); outb(data, chip->ctrl_port + 1); #ifdef REG_DEBUG - snd_printk("Config reg %02x set to %02x\n", reg, data); + snd_printk(KERN_DEBUG "Config reg %02x set to %02x\n", reg, data); #endif } @@ -1346,7 +1350,7 @@ static int __devinit snd_es18xx_initialize(es18xx_t *chip) irqmask = 3; break; default: - snd_printk("invalid irq %d\n", chip->irq); + snd_printk(KERN_ERR "invalid irq %d\n", chip->irq); return -ENODEV; } switch (chip->dma1) { @@ -1360,7 +1364,7 @@ static int __devinit snd_es18xx_initialize(es18xx_t *chip) dma1mask = 3; break; default: - snd_printk("invalid dma1 %d\n", chip->dma1); + snd_printk(KERN_ERR "invalid dma1 %d\n", chip->dma1); return -ENODEV; } switch (chip->dma2) { @@ -1377,7 +1381,7 @@ static int __devinit snd_es18xx_initialize(es18xx_t *chip) dma2mask = 3; break; default: - snd_printk("invalid dma2 %d\n", chip->dma2); + snd_printk(KERN_ERR "invalid dma2 %d\n", chip->dma2); return -ENODEV; } @@ -1440,7 +1444,7 @@ static int __devinit snd_es18xx_identify(es18xx_t *chip) /* reset */ if (snd_es18xx_reset(chip) < 0) { - snd_printk("reset at 0x%lx failed!!!\n", chip->port); + snd_printk(KERN_ERR "reset at 0x%lx failed!!!\n", chip->port); return -ENODEV; } @@ -1527,7 +1531,7 @@ static int __devinit snd_es18xx_probe(es18xx_t *chip) chip->caps = ES18XX_PCM2 | ES18XX_RECMIX | ES18XX_AUXB | ES18XX_DUPLEX_SAME | ES18XX_HWV; break; default: - snd_printk("[0x%lx] unsupported chip ES%x\n", + snd_printk(KERN_ERR "[0x%lx] unsupported chip ES%x\n", chip->port, chip->version); return -ENODEV; } diff --git a/sound/isa/gus/gus_dma.c b/sound/isa/gus/gus_dma.c index de4b56d80b3..ef1b2e9832e 100644 --- a/sound/isa/gus/gus_dma.c +++ b/sound/isa/gus/gus_dma.c @@ -199,7 +199,7 @@ int snd_gf1_dma_transfer_block(snd_gus_card_t * gus, block = kmalloc(sizeof(*block), atomic ? GFP_ATOMIC : GFP_KERNEL); if (block == NULL) { - snd_printk("gf1: DMA transfer failure; not enough memory\n"); + snd_printk(KERN_ERR "gf1: DMA transfer failure; not enough memory\n"); return -ENOMEM; } *block = *__block; diff --git a/sound/isa/gus/gus_io.c b/sound/isa/gus/gus_io.c index 23e1b5f19e1..8d5752b2378 100644 --- a/sound/isa/gus/gus_io.c +++ b/sound/isa/gus/gus_io.c @@ -343,7 +343,7 @@ void snd_gf1_pokew(snd_gus_card_t * gus, unsigned int addr, unsigned short data) #ifdef CONFIG_SND_DEBUG if (!gus->interwave) - snd_printk("snd_gf1_pokew - GF1!!!\n"); + snd_printk(KERN_DEBUG "snd_gf1_pokew - GF1!!!\n"); #endif spin_lock_irqsave(&gus->reg_lock, flags); outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); @@ -367,7 +367,7 @@ unsigned short snd_gf1_peekw(snd_gus_card_t * gus, unsigned int addr) #ifdef CONFIG_SND_DEBUG if (!gus->interwave) - snd_printk("snd_gf1_peekw - GF1!!!\n"); + snd_printk(KERN_DEBUG "snd_gf1_peekw - GF1!!!\n"); #endif spin_lock_irqsave(&gus->reg_lock, flags); outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); @@ -393,7 +393,7 @@ void snd_gf1_dram_setmem(snd_gus_card_t * gus, unsigned int addr, #ifdef CONFIG_SND_DEBUG if (!gus->interwave) - snd_printk("snd_gf1_dram_setmem - GF1!!!\n"); + snd_printk(KERN_DEBUG "snd_gf1_dram_setmem - GF1!!!\n"); #endif addr &= ~1; count >>= 1; @@ -449,30 +449,30 @@ void snd_gf1_print_voice_registers(snd_gus_card_t * gus) int voice, ctrl; voice = gus->gf1.active_voice; - printk(" -%i- GF1 voice ctrl, ramp ctrl = 0x%x, 0x%x\n", voice, ctrl = snd_gf1_i_read8(gus, 0), snd_gf1_i_read8(gus, 0x0d)); - printk(" -%i- GF1 frequency = 0x%x\n", voice, snd_gf1_i_read16(gus, 1)); - printk(" -%i- GF1 loop start, end = 0x%x (0x%x), 0x%x (0x%x)\n", voice, snd_gf1_i_read_addr(gus, 2, ctrl & 4), snd_gf1_i_read_addr(gus, 2, (ctrl & 4) ^ 4), snd_gf1_i_read_addr(gus, 4, ctrl & 4), snd_gf1_i_read_addr(gus, 4, (ctrl & 4) ^ 4)); - printk(" -%i- GF1 ramp start, end, rate = 0x%x, 0x%x, 0x%x\n", voice, snd_gf1_i_read8(gus, 7), snd_gf1_i_read8(gus, 8), snd_gf1_i_read8(gus, 6)); - printk(" -%i- GF1 volume = 0x%x\n", voice, snd_gf1_i_read16(gus, 9)); - printk(" -%i- GF1 position = 0x%x (0x%x)\n", voice, snd_gf1_i_read_addr(gus, 0x0a, ctrl & 4), snd_gf1_i_read_addr(gus, 0x0a, (ctrl & 4) ^ 4)); + printk(KERN_INFO " -%i- GF1 voice ctrl, ramp ctrl = 0x%x, 0x%x\n", voice, ctrl = snd_gf1_i_read8(gus, 0), snd_gf1_i_read8(gus, 0x0d)); + printk(KERN_INFO " -%i- GF1 frequency = 0x%x\n", voice, snd_gf1_i_read16(gus, 1)); + printk(KERN_INFO " -%i- GF1 loop start, end = 0x%x (0x%x), 0x%x (0x%x)\n", voice, snd_gf1_i_read_addr(gus, 2, ctrl & 4), snd_gf1_i_read_addr(gus, 2, (ctrl & 4) ^ 4), snd_gf1_i_read_addr(gus, 4, ctrl & 4), snd_gf1_i_read_addr(gus, 4, (ctrl & 4) ^ 4)); + printk(KERN_INFO " -%i- GF1 ramp start, end, rate = 0x%x, 0x%x, 0x%x\n", voice, snd_gf1_i_read8(gus, 7), snd_gf1_i_read8(gus, 8), snd_gf1_i_read8(gus, 6)); + printk(KERN_INFO" -%i- GF1 volume = 0x%x\n", voice, snd_gf1_i_read16(gus, 9)); + printk(KERN_INFO " -%i- GF1 position = 0x%x (0x%x)\n", voice, snd_gf1_i_read_addr(gus, 0x0a, ctrl & 4), snd_gf1_i_read_addr(gus, 0x0a, (ctrl & 4) ^ 4)); if (gus->interwave && snd_gf1_i_read8(gus, 0x19) & 0x01) { /* enhanced mode */ mode = snd_gf1_i_read8(gus, 0x15); - printk(" -%i- GFA1 mode = 0x%x\n", voice, mode); + printk(KERN_INFO " -%i- GFA1 mode = 0x%x\n", voice, mode); if (mode & 0x01) { /* Effect processor */ - printk(" -%i- GFA1 effect address = 0x%x\n", voice, snd_gf1_i_read_addr(gus, 0x11, ctrl & 4)); - printk(" -%i- GFA1 effect volume = 0x%x\n", voice, snd_gf1_i_read16(gus, 0x16)); - printk(" -%i- GFA1 effect volume final = 0x%x\n", voice, snd_gf1_i_read16(gus, 0x1d)); - printk(" -%i- GFA1 effect acumulator = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x14)); + printk(KERN_INFO " -%i- GFA1 effect address = 0x%x\n", voice, snd_gf1_i_read_addr(gus, 0x11, ctrl & 4)); + printk(KERN_INFO " -%i- GFA1 effect volume = 0x%x\n", voice, snd_gf1_i_read16(gus, 0x16)); + printk(KERN_INFO " -%i- GFA1 effect volume final = 0x%x\n", voice, snd_gf1_i_read16(gus, 0x1d)); + printk(KERN_INFO " -%i- GFA1 effect acumulator = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x14)); } if (mode & 0x20) { - printk(" -%i- GFA1 left offset = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x13), snd_gf1_i_read16(gus, 0x13) >> 4); - printk(" -%i- GFA1 left offset final = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x1c), snd_gf1_i_read16(gus, 0x1c) >> 4); - printk(" -%i- GFA1 right offset = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x0c), snd_gf1_i_read16(gus, 0x0c) >> 4); - printk(" -%i- GFA1 right offset final = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x1b), snd_gf1_i_read16(gus, 0x1b) >> 4); + printk(KERN_INFO " -%i- GFA1 left offset = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x13), snd_gf1_i_read16(gus, 0x13) >> 4); + printk(KERN_INFO " -%i- GFA1 left offset final = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x1c), snd_gf1_i_read16(gus, 0x1c) >> 4); + printk(KERN_INFO " -%i- GFA1 right offset = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x0c), snd_gf1_i_read16(gus, 0x0c) >> 4); + printk(KERN_INFO " -%i- GFA1 right offset final = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x1b), snd_gf1_i_read16(gus, 0x1b) >> 4); } else - printk(" -%i- GF1 pan = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x0c)); + printk(KERN_INFO " -%i- GF1 pan = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x0c)); } else - printk(" -%i- GF1 pan = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x0c)); + printk(KERN_INFO " -%i- GF1 pan = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x0c)); } #if 0 @@ -481,45 +481,45 @@ void snd_gf1_print_global_registers(snd_gus_card_t * gus) { unsigned char global_mode = 0x00; - printk(" -G- GF1 active voices = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_ACTIVE_VOICES)); + printk(KERN_INFO " -G- GF1 active voices = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_ACTIVE_VOICES)); if (gus->interwave) { global_mode = snd_gf1_i_read8(gus, SNDRV_GF1_GB_GLOBAL_MODE); - printk(" -G- GF1 global mode = 0x%x\n", global_mode); + printk(KERN_INFO " -G- GF1 global mode = 0x%x\n", global_mode); } if (global_mode & 0x02) /* LFO enabled? */ - printk(" -G- GF1 LFO base = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_LFO_BASE)); - printk(" -G- GF1 voices IRQ read = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_VOICES_IRQ_READ)); - printk(" -G- GF1 DRAM DMA control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL)); - printk(" -G- GF1 DRAM DMA high/low = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_HIGH), snd_gf1_i_read16(gus, SNDRV_GF1_GW_DRAM_DMA_LOW)); - printk(" -G- GF1 DRAM IO high/low = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_IO_HIGH), snd_gf1_i_read16(gus, SNDRV_GF1_GW_DRAM_IO_LOW)); + printk(KERN_INFO " -G- GF1 LFO base = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_LFO_BASE)); + printk(KERN_INFO " -G- GF1 voices IRQ read = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_VOICES_IRQ_READ)); + printk(KERN_INFO " -G- GF1 DRAM DMA control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL)); + printk(KERN_INFO " -G- GF1 DRAM DMA high/low = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_HIGH), snd_gf1_i_read16(gus, SNDRV_GF1_GW_DRAM_DMA_LOW)); + printk(KERN_INFO " -G- GF1 DRAM IO high/low = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_IO_HIGH), snd_gf1_i_read16(gus, SNDRV_GF1_GW_DRAM_IO_LOW)); if (!gus->interwave) - printk(" -G- GF1 record DMA control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL)); - printk(" -G- GF1 DRAM IO 16 = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_DRAM_IO16)); + printk(KERN_INFO " -G- GF1 record DMA control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL)); + printk(KERN_INFO " -G- GF1 DRAM IO 16 = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_DRAM_IO16)); if (gus->gf1.enh_mode) { - printk(" -G- GFA1 memory config = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG)); - printk(" -G- GFA1 memory control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_MEMORY_CONTROL)); - printk(" -G- GFA1 FIFO record base = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_FIFO_RECORD_BASE_ADDR)); - printk(" -G- GFA1 FIFO playback base = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_FIFO_PLAY_BASE_ADDR)); - printk(" -G- GFA1 interleave control = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_INTERLEAVE)); + printk(KERN_INFO " -G- GFA1 memory config = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG)); + printk(KERN_INFO " -G- GFA1 memory control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_MEMORY_CONTROL)); + printk(KERN_INFO " -G- GFA1 FIFO record base = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_FIFO_RECORD_BASE_ADDR)); + printk(KERN_INFO " -G- GFA1 FIFO playback base = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_FIFO_PLAY_BASE_ADDR)); + printk(KERN_INFO " -G- GFA1 interleave control = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_INTERLEAVE)); } } void snd_gf1_print_setup_registers(snd_gus_card_t * gus) { - printk(" -S- mix control = 0x%x\n", inb(GUSP(gus, MIXCNTRLREG))); - printk(" -S- IRQ status = 0x%x\n", inb(GUSP(gus, IRQSTAT))); - printk(" -S- timer control = 0x%x\n", inb(GUSP(gus, TIMERCNTRL))); - printk(" -S- timer data = 0x%x\n", inb(GUSP(gus, TIMERDATA))); - printk(" -S- status read = 0x%x\n", inb(GUSP(gus, REGCNTRLS))); - printk(" -S- Sound Blaster control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL)); - printk(" -S- AdLib timer 1/2 = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_ADLIB_TIMER_1), snd_gf1_i_look8(gus, SNDRV_GF1_GB_ADLIB_TIMER_2)); - printk(" -S- reset = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)); + printk(KERN_INFO " -S- mix control = 0x%x\n", inb(GUSP(gus, MIXCNTRLREG))); + printk(KERN_INFO " -S- IRQ status = 0x%x\n", inb(GUSP(gus, IRQSTAT))); + printk(KERN_INFO " -S- timer control = 0x%x\n", inb(GUSP(gus, TIMERCNTRL))); + printk(KERN_INFO " -S- timer data = 0x%x\n", inb(GUSP(gus, TIMERDATA))); + printk(KERN_INFO " -S- status read = 0x%x\n", inb(GUSP(gus, REGCNTRLS))); + printk(KERN_INFO " -S- Sound Blaster control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL)); + printk(KERN_INFO " -S- AdLib timer 1/2 = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_ADLIB_TIMER_1), snd_gf1_i_look8(gus, SNDRV_GF1_GB_ADLIB_TIMER_2)); + printk(KERN_INFO " -S- reset = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)); if (gus->interwave) { - printk(" -S- compatibility = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_COMPATIBILITY)); - printk(" -S- decode control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DECODE_CONTROL)); - printk(" -S- version number = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER)); - printk(" -S- MPU-401 emul. control A/B = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_MPU401_CONTROL_A), snd_gf1_i_look8(gus, SNDRV_GF1_GB_MPU401_CONTROL_B)); - printk(" -S- emulation IRQ = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_EMULATION_IRQ)); + printk(KERN_INFO " -S- compatibility = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_COMPATIBILITY)); + printk(KERN_INFO " -S- decode control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DECODE_CONTROL)); + printk(KERN_INFO " -S- version number = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER)); + printk(KERN_INFO " -S- MPU-401 emul. control A/B = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_MPU401_CONTROL_A), snd_gf1_i_look8(gus, SNDRV_GF1_GB_MPU401_CONTROL_B)); + printk(KERN_INFO " -S- emulation IRQ = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_EMULATION_IRQ)); } } diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c index 5fd374f052e..4f57ff4ab35 100644 --- a/sound/isa/gus/gus_main.c +++ b/sound/isa/gus/gus_main.c @@ -246,7 +246,7 @@ static int snd_gus_detect_memory(snd_gus_card_t * gus) snd_gf1_poke(gus, 0L, 0xaa); snd_gf1_poke(gus, 1L, 0x55); if (snd_gf1_peek(gus, 0L) != 0xaa || snd_gf1_peek(gus, 1L) != 0x55) { - snd_printk("plain GF1 card at 0x%lx without onboard DRAM?\n", gus->gf1.port); + snd_printk(KERN_ERR "plain GF1 card at 0x%lx without onboard DRAM?\n", gus->gf1.port); return -ENOMEM; } for (idx = 1, d = 0xab; idx < 4; idx++, d++) { @@ -299,20 +299,17 @@ static int snd_gus_init_dma_irq(snd_gus_card_t * gus, int latches) dma2 = gus->gf1.dma2; dma2 = dma2 < 0 ? -dma2 : dma2; dma2 = dmas[dma2 & 7]; -#if 0 - printk("dma1 = %i, dma2 = %i\n", gus->gf1.dma1, gus->gf1.dma2); -#endif dma1 |= gus->equal_dma ? 0x40 : (dma2 << 3); if ((dma1 & 7) == 0 || (dma2 & 7) == 0) { - snd_printk("Error! DMA isn't defined.\n"); + snd_printk(KERN_ERR "Error! DMA isn't defined.\n"); return -EINVAL; } irq = gus->gf1.irq; irq = irq < 0 ? -irq : irq; irq = irqs[irq & 0x0f]; if (irq == 0) { - snd_printk("Error! IRQ isn't defined.\n"); + snd_printk(KERN_ERR "Error! IRQ isn't defined.\n"); return -EINVAL; } irq |= 0x40; @@ -400,8 +397,8 @@ static int snd_gus_check_version(snd_gus_card_t * gus) strcpy(card->longname, "Gravis UltraSound Extreme"); gus->ess_flag = 1; } else { - snd_printk("unknown GF1 revision number at 0x%lx - 0x%x (0x%x)\n", gus->gf1.port, rev, val); - snd_printk(" please - report to \n"); + snd_printk(KERN_ERR "unknown GF1 revision number at 0x%lx - 0x%x (0x%x)\n", gus->gf1.port, rev, val); + snd_printk(KERN_ERR " please - report to \n"); } } } @@ -425,7 +422,7 @@ int snd_gus_initialize(snd_gus_card_t *gus) if (!gus->interwave) { if ((err = snd_gus_check_version(gus)) < 0) { - snd_printk("version check failed\n"); + snd_printk(KERN_ERR "version check failed\n"); return err; } if ((err = snd_gus_detect_memory(gus)) < 0) diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c index 5eb766dd564..2e23f2a8c62 100644 --- a/sound/isa/gus/gus_mem.c +++ b/sound/isa/gus/gus_mem.c @@ -198,7 +198,7 @@ snd_gf1_mem_block_t *snd_gf1_mem_alloc(snd_gf1_mem_t * alloc, int owner, if (nblock != NULL) { if (size != (int)nblock->size) { /* TODO: remove in the future */ - snd_printk("snd_gf1_mem_alloc - share: sizes differ\n"); + snd_printk(KERN_ERR "snd_gf1_mem_alloc - share: sizes differ\n"); goto __std; } nblock->share++; diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c index beb01365dc4..720c0739c3a 100644 --- a/sound/isa/gus/gus_pcm.c +++ b/sound/isa/gus/gus_pcm.c @@ -698,7 +698,7 @@ static int snd_gf1_pcm_playback_close(snd_pcm_substream_t * substream) gus_pcm_private_t *pcmp = runtime->private_data; if (!wait_event_timeout(pcmp->sleep, (atomic_read(&pcmp->dma_count) <= 0), 2*HZ)) - snd_printk("gf1 pcm - serious DMA problem\n"); + snd_printk(KERN_ERR "gf1 pcm - serious DMA problem\n"); snd_gf1_dma_done(gus); return 0; diff --git a/sound/isa/gus/gus_reset.c b/sound/isa/gus/gus_reset.c index ef687abc707..90710969ef7 100644 --- a/sound/isa/gus/gus_reset.c +++ b/sound/isa/gus/gus_reset.c @@ -134,7 +134,7 @@ void snd_gf1_smart_stop_voice(snd_gus_card_t * gus, unsigned short voice) spin_lock_irqsave(&gus->reg_lock, flags); snd_gf1_select_voice(gus, voice); #if 0 - printk(" -%i- smart stop voice - volume = 0x%x\n", voice, snd_gf1_i_read16(gus, SNDRV_GF1_VW_VOLUME)); + printk(KERN_DEBUG " -%i- smart stop voice - volume = 0x%x\n", voice, snd_gf1_i_read16(gus, SNDRV_GF1_VW_VOLUME)); #endif snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL); snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); @@ -148,7 +148,7 @@ void snd_gf1_stop_voice(snd_gus_card_t * gus, unsigned short voice) spin_lock_irqsave(&gus->reg_lock, flags); snd_gf1_select_voice(gus, voice); #if 0 - printk(" -%i- stop voice - volume = 0x%x\n", voice, snd_gf1_i_read16(gus, SNDRV_GF1_VW_VOLUME)); + printk(KERN_DEBUG " -%i- stop voice - volume = 0x%x\n", voice, snd_gf1_i_read16(gus, SNDRV_GF1_VW_VOLUME)); #endif snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL); snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); diff --git a/sound/isa/gus/gus_simple.c b/sound/isa/gus/gus_simple.c index c122e7be6ce..dfed85b58b3 100644 --- a/sound/isa/gus/gus_simple.c +++ b/sound/isa/gus/gus_simple.c @@ -136,7 +136,7 @@ static void do_volume_envelope(snd_gus_card_t *gus, snd_gus_voice_t *voice) snd_gf1_select_voice(gus, voice->number); snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, voice->gf1_volume); - printk("gf1_volume = 0x%x\n", voice->gf1_volume); + /* printk("gf1_volume = 0x%x\n", voice->gf1_volume); */ spin_unlock_irqrestore(&gus->reg_lock, flags); return; } diff --git a/sound/isa/gus/gus_uart.c b/sound/isa/gus/gus_uart.c index 1bc2da8784e..fbc95e99105 100644 --- a/sound/isa/gus/gus_uart.c +++ b/sound/isa/gus/gus_uart.c @@ -104,7 +104,7 @@ static int snd_gf1_uart_output_open(snd_rawmidi_substream_t * substream) gus->midi_substream_output = substream; spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); #if 0 - snd_printk("write init - cmd = 0x%x, stat = 0x%x\n", gus->gf1.uart_cmd, snd_gf1_uart_stat(gus)); + snd_printk(KERN_DEBUG "write init - cmd = 0x%x, stat = 0x%x\n", gus->gf1.uart_cmd, snd_gf1_uart_stat(gus)); #endif return 0; } @@ -126,7 +126,7 @@ static int snd_gf1_uart_input_open(snd_rawmidi_substream_t * substream) for (i = 0; i < 1000 && (snd_gf1_uart_stat(gus) & 0x01); i++) snd_gf1_uart_get(gus); /* clean Rx */ if (i >= 1000) - snd_printk("gus midi uart init read - cleanup error\n"); + snd_printk(KERN_ERR "gus midi uart init read - cleanup error\n"); } spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); #if 0 diff --git a/sound/isa/gus/gus_volume.c b/sound/isa/gus/gus_volume.c index 3d36f6c8ee6..b3382fec529 100644 --- a/sound/isa/gus/gus_volume.c +++ b/sound/isa/gus/gus_volume.c @@ -119,7 +119,7 @@ unsigned short snd_gf1_translate_freq(snd_gus_card_t * gus, unsigned int freq16) freq16 = 50; if (freq16 & 0xf8000000) { freq16 = ~0xf8000000; - snd_printk("snd_gf1_translate_freq: overflow - freq = 0x%x\n", freq16); + snd_printk(KERN_ERR "snd_gf1_translate_freq: overflow - freq = 0x%x\n", freq16); } return ((freq16 << 9) + (gus->gf1.playback_freq >> 1)) / gus->gf1.playback_freq; } @@ -203,14 +203,14 @@ unsigned short snd_gf1_compute_freq(unsigned int freq, fc = (freq << 10) / rate; if (fc > 97391L) { fc = 97391; - snd_printk("patch: (1) fc frequency overflow - %u\n", fc); + snd_printk(KERN_ERR "patch: (1) fc frequency overflow - %u\n", fc); } fc = (fc * 44100UL) / mix_rate; while (scale--) fc <<= 1; if (fc > 65535L) { fc = 65535; - snd_printk("patch: (2) fc frequency overflow - %u\n", fc); + snd_printk(KERN_ERR "patch: (2) fc frequency overflow - %u\n", fc); } return (unsigned short) fc; } diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index b101ab0a0db..f703a9f4257 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c @@ -437,7 +437,7 @@ static void __devinit snd_interwave_detect_memory(snd_gus_card_t * gus) for (i = 0; i < 8; ++i) iwave[i] = snd_gf1_peek(gus, bank_pos + i); #ifdef CONFIG_SND_DEBUG_ROM - printk("ROM at 0x%06x = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", bank_pos, + printk(KERN_DEBUG "ROM at 0x%06x = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", bank_pos, iwave[0], iwave[1], iwave[2], iwave[3], iwave[4], iwave[5], iwave[6], iwave[7]); #endif @@ -447,7 +447,7 @@ static void __devinit snd_interwave_detect_memory(snd_gus_card_t * gus) for (i = 0; i < sizeof(struct rom_hdr); i++) csum += snd_gf1_peek(gus, bank_pos + i); #ifdef CONFIG_SND_DEBUG_ROM - printk("ROM checksum = 0x%x (computed)\n", csum); + printk(KERN_DEBUG "ROM checksum = 0x%x (computed)\n", csum); #endif if (csum != 0) continue; /* not valid rom */ diff --git a/sound/isa/sb/emu8000_synth.c b/sound/isa/sb/emu8000_synth.c index 1f63aa52d59..f68e217416a 100644 --- a/sound/isa/sb/emu8000_synth.c +++ b/sound/isa/sb/emu8000_synth.c @@ -56,7 +56,7 @@ static int snd_emu8000_new_device(snd_seq_device_t *dev) emu->num_ports = hw->seq_ports; if (hw->memhdr) { - snd_printk("memhdr is already initialized!?\n"); + snd_printk(KERN_ERR "memhdr is already initialized!?\n"); snd_util_memhdr_free(hw->memhdr); } hw->memhdr = snd_util_memhdr_new(hw->mem_size); diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c index a99e642a68b..556b95e3e22 100644 --- a/sound/isa/sb/sb16_main.c +++ b/sound/isa/sb/sb16_main.c @@ -747,7 +747,7 @@ int snd_sb16dsp_configure(sb_t * chip) unsigned char realirq, realdma, realmpureg; /* note: mpu register should be present only on SB16 Vibra soundcards */ - // printk("codec->irq=%i, codec->dma8=%i, codec->dma16=%i\n", chip->irq, chip->dma8, chip->dma16); + // printk(KERN_DEBUG "codec->irq=%i, codec->dma8=%i, codec->dma16=%i\n", chip->irq, chip->dma8, chip->dma16); spin_lock_irqsave(&chip->mixer_lock, flags); mpureg = snd_sbmixer_read(chip, SB_DSP4_MPUSETUP) & ~0x06; spin_unlock_irqrestore(&chip->mixer_lock, flags); @@ -821,9 +821,9 @@ int snd_sb16dsp_configure(sb_t * chip) spin_unlock_irqrestore(&chip->mixer_lock, flags); if ((~realirq) & irqreg || (~realdma) & dmareg) { - snd_printk("SB16 [0x%lx]: unable to set DMA & IRQ (PnP device?)\n", chip->port); - snd_printk("SB16 [0x%lx]: wanted: irqreg=0x%x, dmareg=0x%x, mpureg = 0x%x\n", chip->port, realirq, realdma, realmpureg); - snd_printk("SB16 [0x%lx]: got: irqreg=0x%x, dmareg=0x%x, mpureg = 0x%x\n", chip->port, irqreg, dmareg, mpureg); + snd_printk(KERN_ERR "SB16 [0x%lx]: unable to set DMA & IRQ (PnP device?)\n", chip->port); + snd_printk(KERN_ERR "SB16 [0x%lx]: wanted: irqreg=0x%x, dmareg=0x%x, mpureg = 0x%x\n", chip->port, realirq, realdma, realmpureg); + snd_printk(KERN_ERR "SB16 [0x%lx]: got: irqreg=0x%x, dmareg=0x%x, mpureg = 0x%x\n", chip->port, irqreg, dmareg, mpureg); return -ENODEV; } return 0; diff --git a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c index 87c9b1ba06c..5ddc6e41d90 100644 --- a/sound/isa/sb/sb8_main.c +++ b/sound/isa/sb/sb8_main.c @@ -334,9 +334,6 @@ irqreturn_t snd_sb8dsp_interrupt(sb_t *chip) snd_pcm_substream_t *substream; snd_pcm_runtime_t *runtime; -#if 0 - snd_printk("sb8: interrupt\n"); -#endif snd_sb_ack_8bit(chip); switch (chip->mode) { case SB_MODE_PLAYBACK_8: /* ok.. playback is active */ diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c index 46b9480669f..603e923b5d2 100644 --- a/sound/isa/sb/sb_common.c +++ b/sound/isa/sb/sb_common.c @@ -45,7 +45,7 @@ int snd_sbdsp_command(sb_t *chip, unsigned char val) { int i; #ifdef IO_DEBUG - snd_printk("command 0x%x\n", val); + snd_printk(KERN_DEBUG "command 0x%x\n", val); #endif for (i = BUSY_LOOPS; i; i--) if ((inb(SBP(chip, STATUS)) & 0x80) == 0) { @@ -64,7 +64,7 @@ int snd_sbdsp_get_byte(sb_t *chip) if (inb(SBP(chip, DATA_AVAIL)) & 0x80) { val = inb(SBP(chip, READ)); #ifdef IO_DEBUG - snd_printk("get_byte 0x%x\n", val); + snd_printk(KERN_DEBUG "get_byte 0x%x\n", val); #endif return val; } @@ -154,7 +154,7 @@ static int snd_sbdsp_probe(sb_t * chip) str = "16"; break; default: - snd_printk("SB [0x%lx]: unknown DSP chip version %i.%i\n", + snd_printk(KERN_INFO "SB [0x%lx]: unknown DSP chip version %i.%i\n", chip->port, major, minor); return -ENODEV; } diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c index ff4b5996802..5a926a452d3 100644 --- a/sound/isa/sb/sb_mixer.c +++ b/sound/isa/sb/sb_mixer.c @@ -36,7 +36,7 @@ void snd_sbmixer_write(sb_t *chip, unsigned char reg, unsigned char data) outb(data, SBP(chip, MIXER_DATA)); udelay(10); #ifdef IO_DEBUG - snd_printk("mixer_write 0x%x 0x%x\n", reg, data); + snd_printk(KERN_DEBUG "mixer_write 0x%x 0x%x\n", reg, data); #endif } @@ -49,7 +49,7 @@ unsigned char snd_sbmixer_read(sb_t *chip, unsigned char reg) result = inb(SBP(chip, MIXER_DATA)); udelay(10); #ifdef IO_DEBUG - snd_printk("mixer_read 0x%x 0x%x\n", reg, result); + snd_printk(KERN_DEBUG "mixer_read 0x%x 0x%x\n", reg, result); #endif return result; } diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 1f747c3034f..e33653439cb 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -426,7 +426,7 @@ static int snd_ali_stimer_ready(ali_t *codec, int sched) schedule_timeout(1); } } while (time_after_eq(end_time, jiffies)); - snd_printk("ali_stimer_read: stimer is not ready.\n"); + snd_printk(KERN_ERR "ali_stimer_read: stimer is not ready.\n"); return -EIO; } @@ -438,7 +438,7 @@ static void snd_ali_codec_poke(ali_t *codec,int secondary, unsigned int port = 0; if (reg >= 0x80) { - snd_printk("ali_codec_poke: reg(%xh) invalid.\n", reg); + snd_printk(KERN_ERR "ali_codec_poke: reg(%xh) invalid.\n", reg); return; } @@ -467,7 +467,7 @@ static unsigned short snd_ali_codec_peek( ali_t *codec, unsigned int port = 0; if (reg >= 0x80) { - snd_printk("ali_codec_peek: reg(%xh) invalid.\n", reg); + snd_printk(KERN_ERR "ali_codec_peek: reg(%xh) invalid.\n", reg); return ~0; } @@ -671,7 +671,7 @@ static int snd_ali_alloc_pcm_channel(ali_t *codec, int channel) unsigned int idx = channel & 0x1f; if (codec->synth.chcnt >= ALI_CHANNELS){ - snd_printk("ali_alloc_pcm_channel: no free channels.\n"); + snd_printk(KERN_ERR "ali_alloc_pcm_channel: no free channels.\n"); return -1; } @@ -702,7 +702,7 @@ static int snd_ali_find_free_channel(ali_t * codec, int rec) if ((result = snd_ali_alloc_pcm_channel(codec,idx)) >= 0) { return result; } else { - snd_printk("ali_find_free_channel: record channel is busy now.\n"); + snd_printk(KERN_ERR "ali_find_free_channel: record channel is busy now.\n"); return -1; } } @@ -714,7 +714,7 @@ static int snd_ali_find_free_channel(ali_t * codec, int rec) if ((result = snd_ali_alloc_pcm_channel(codec,idx)) >= 0) { return result; } else { - snd_printk("ali_find_free_channel: S/PDIF out channel is in busy now.\n"); + snd_printk(KERN_ERR "ali_find_free_channel: S/PDIF out channel is in busy now.\n"); } } @@ -722,7 +722,7 @@ static int snd_ali_find_free_channel(ali_t * codec, int rec) if ((result = snd_ali_alloc_pcm_channel(codec,idx)) >= 0) return result; } - snd_printk("ali_find_free_channel: no free channels.\n"); + snd_printk(KERN_ERR "ali_find_free_channel: no free channels.\n"); return -1; } @@ -736,7 +736,7 @@ static void snd_ali_free_channel_pcm(ali_t *codec, int channel) return; if (!(codec->synth.chmap & (1 << idx))) { - snd_printk("ali_free_channel_pcm: channel %d is not in use.\n",channel); + snd_printk(KERN_ERR "ali_free_channel_pcm: channel %d is not in use.\n",channel); return; } else { codec->synth.chmap &= ~(1 << idx); @@ -798,7 +798,7 @@ static void snd_ali_detect_spdif_rate(ali_t *codec) } if (count > 50000) { - snd_printk("ali_detect_spdif_rate: timeout!\n"); + snd_printk(KERN_ERR "ali_detect_spdif_rate: timeout!\n"); return; } @@ -811,7 +811,7 @@ static void snd_ali_detect_spdif_rate(ali_t *codec) } if (count > 50000) { - snd_printk("ali_detect_spdif_rate: timeout!\n"); + snd_printk(KERN_ERR "ali_detect_spdif_rate: timeout!\n"); return; } @@ -1079,7 +1079,7 @@ static snd_ali_voice_t *snd_ali_alloc_voice(ali_t * codec, int type, int rec, in idx = channel > 0 ? snd_ali_alloc_pcm_channel(codec, channel) : snd_ali_find_free_channel(codec,rec); if(idx < 0) { - snd_printk("ali_alloc_voice: err.\n"); + snd_printk(KERN_ERR "ali_alloc_voice: err.\n"); spin_unlock_irqrestore(&codec->voice_alloc, flags); return NULL; } @@ -1481,13 +1481,13 @@ static int snd_ali_prepare(snd_pcm_substream_t * substream) } rate = snd_ali_get_spdif_in_rate(codec); if (rate == 0) { - snd_printk("ali_capture_preapre: spdif rate detect err!\n"); + snd_printk(KERN_WARNING "ali_capture_preapre: spdif rate detect err!\n"); rate = 48000; } bValue = inb(ALI_REG(codec,ALI_SPDIF_CTRL)); if (bValue & 0x10) { outb(bValue,ALI_REG(codec,ALI_SPDIF_CTRL)); - printk("clear SPDIF parity error flag.\n"); + printk(KERN_WARNING "clear SPDIF parity error flag.\n"); } if (rate != 48000) @@ -1816,7 +1816,7 @@ static int __devinit snd_ali_pcm(ali_t * codec, int device, struct ali_pcm_descr err = snd_pcm_new(codec->card, desc->name, device, desc->playback_num, desc->capture_num, &pcm); if (err < 0) { - snd_printk("snd_ali_pcm: err called snd_pcm_new.\n"); + snd_printk(KERN_ERR "snd_ali_pcm: err called snd_pcm_new.\n"); return err; } pcm->private_data = codec; @@ -1994,7 +1994,7 @@ static int __devinit snd_ali_mixer(ali_t * codec) for ( i = 0 ; i < codec->num_of_codecs ; i++) { ac97.num = i; if ((err = snd_ac97_mixer(codec->ac97_bus, &ac97, &codec->ac97[i])) < 0) { - snd_printk("ali mixer %d creating error.\n", i); + snd_printk(KERN_ERR "ali mixer %d creating error.\n", i); if(i == 0) return err; codec->num_of_codecs = 1; @@ -2128,7 +2128,7 @@ static int snd_ali_chip_init(ali_t *codec) snd_ali_printk("chip initializing ... \n"); if (snd_ali_reset_5451(codec)) { - snd_printk("ali_chip_init: reset 5451 error.\n"); + snd_printk(KERN_ERR "ali_chip_init: reset 5451 error.\n"); return -1; } @@ -2203,7 +2203,7 @@ static int __devinit snd_ali_resources(ali_t *codec) codec->port = pci_resource_start(codec->pci, 0); if (request_irq(codec->pci->irq, snd_ali_card_interrupt, SA_INTERRUPT|SA_SHIRQ, "ALI 5451", (void *)codec)) { - snd_printk("Unable to request irq.\n"); + snd_printk(KERN_ERR "Unable to request irq.\n"); return -EBUSY; } codec->irq = codec->pci->irq; @@ -2243,7 +2243,7 @@ static int __devinit snd_ali_create(snd_card_t * card, /* check, if we can restrict PCI DMA transfers to 31 bits */ if (pci_set_dma_mask(pci, 0x7fffffff) < 0 || pci_set_consistent_dma_mask(pci, 0x7fffffff) < 0) { - snd_printk("architecture does not support 31bit PCI busmaster DMA\n"); + snd_printk(KERN_ERR "architecture does not support 31bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; } @@ -2332,7 +2332,7 @@ static int __devinit snd_ali_create(snd_card_t * card, } if ((err = snd_ali_chip_init(codec)) < 0) { - snd_printk("ali create: chip init error.\n"); + snd_printk(KERN_ERR "ali create: chip init error.\n"); return err; } diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 8a32cd92f62..7c61561f297 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -667,7 +667,7 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci, /* check, if we can restrict PCI DMA transfers to 24 bits */ if (pci_set_dma_mask(pci, 0x00ffffff) < 0 || pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) { - snd_printk("architecture does not support 24bit PCI busmaster DMA\n"); + snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; } diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c index 04b695d6fd4..6af3b13f2fd 100644 --- a/sound/pci/au88x0/au88x0.c +++ b/sound/pci/au88x0/au88x0.c @@ -303,7 +303,7 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_VORTEX_SYNTH, sizeof(snd_vortex_synth_arg_t), &wave) < 0 || wave == NULL) { - snd_printk("Can't initialize Aureal wavetable synth\n"); + snd_printk(KERN_ERR "Can't initialize Aureal wavetable synth\n"); } else { snd_vortex_synth_arg_t *arg; diff --git a/sound/pci/au88x0/au88x0_a3d.c b/sound/pci/au88x0/au88x0_a3d.c index 9ea2ba7bc3c..d5755db5141 100644 --- a/sound/pci/au88x0/au88x0_a3d.c +++ b/sound/pci/au88x0/au88x0_a3d.c @@ -488,7 +488,7 @@ static void a3dsrc_ZeroStateA3D(a3dsrc_t * a) int i, var, var2; if ((a->vortex) == NULL) { - printk("vortex: ZeroStateA3D: ERROR: a->vortex is NULL\n"); + printk(KERN_ERR "vortex: ZeroStateA3D: ERROR: a->vortex is NULL\n"); return; } diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c index 91ac4f3a2aa..5905188d06b 100644 --- a/sound/pci/au88x0/au88x0_core.c +++ b/sound/pci/au88x0/au88x0_core.c @@ -2033,7 +2033,7 @@ vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, int restype) } } } - printk("vortex: FATAL: ResManager: resource type %d exhausted.\n", restype); + printk(KERN_ERR "vortex: FATAL: ResManager: resource type %d exhausted.\n", restype); return -ENOMEM; } @@ -2165,7 +2165,7 @@ vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type) memset(stream->resources, 0, sizeof(unsigned char) * VORTEX_RESOURCE_LAST); - printk("vortex: out of A3D sources. Sorry\n"); + printk(KERN_ERR "vortex: out of A3D sources. Sorry\n"); return -EBUSY; } /* (De)Initialize A3D hardware source. */ diff --git a/sound/pci/au88x0/au88x0_eq.c b/sound/pci/au88x0/au88x0_eq.c index 53b47a42c7d..9d933cc0ea0 100644 --- a/sound/pci/au88x0/au88x0_eq.c +++ b/sound/pci/au88x0/au88x0_eq.c @@ -854,7 +854,7 @@ snd_vortex_peaks_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) vortex_Eqlzr_GetAllPeaks(vortex, peaks, &count); if (count != 20) { - printk("vortex: peak count error 20 != %d \n", count); + printk(KERN_ERR "vortex: peak count error 20 != %d \n", count); return -1; } for (i = 0; i < 20; i++) diff --git a/sound/pci/au88x0/au88x0_synth.c b/sound/pci/au88x0/au88x0_synth.c index 400417d3460..65f375bad43 100644 --- a/sound/pci/au88x0/au88x0_synth.c +++ b/sound/pci/au88x0/au88x0_synth.c @@ -90,7 +90,7 @@ static int vortex_wt_allocroute(vortex_t * vortex, int wt, int nr_ch) hwwrite(vortex->mmio, WT_PARM(wt, 2), 0); temp = hwread(vortex->mmio, WT_PARM(wt, 3)); - printk("vortex: WT PARM3: %x\n", temp); + printk(KERN_DEBUG "vortex: WT PARM3: %x\n", temp); //hwwrite(vortex->mmio, WT_PARM(wt, 3), temp); hwwrite(vortex->mmio, WT_DELAY(wt, 0), 0); @@ -98,7 +98,7 @@ static int vortex_wt_allocroute(vortex_t * vortex, int wt, int nr_ch) hwwrite(vortex->mmio, WT_DELAY(wt, 2), 0); hwwrite(vortex->mmio, WT_DELAY(wt, 3), 0); - printk("vortex: WT GMODE: %x\n", hwread(vortex->mmio, WT_GMODE(wt))); + printk(KERN_DEBUG "vortex: WT GMODE: %x\n", hwread(vortex->mmio, WT_GMODE(wt))); hwwrite(vortex->mmio, WT_PARM(wt, 2), 0xffffffff); hwwrite(vortex->mmio, WT_PARM(wt, 3), 0xcff1c810); @@ -106,7 +106,7 @@ static int vortex_wt_allocroute(vortex_t * vortex, int wt, int nr_ch) voice->parm0 = voice->parm1 = 0xcfb23e2f; hwwrite(vortex->mmio, WT_PARM(wt, 0), voice->parm0); hwwrite(vortex->mmio, WT_PARM(wt, 1), voice->parm1); - printk("vortex: WT GMODE 2 : %x\n", hwread(vortex->mmio, WT_GMODE(wt))); + printk(KERN_DEBUG "vortex: WT GMODE 2 : %x\n", hwread(vortex->mmio, WT_GMODE(wt))); return 0; } @@ -203,7 +203,7 @@ vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt, } } else { if (wt >= NR_WT) { - printk("vortex: WT SetReg: voice out of range\n"); + printk(KERN_ERR "vortex: WT SetReg: voice out of range\n"); return 0; } } diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index dc638f395c0..8260079a25f 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -669,7 +669,7 @@ static void snd_azf3328_setfmt(azf3328_t *chip, case 48000: val |= 0x06; break; case 64000: val |= 0x07; break; default: - snd_printk("unknown bitrate %d, assuming 44.1kHz!\n", bitrate); + snd_printk(KERN_WARNING "unknown bitrate %d, assuming 44.1kHz!\n", bitrate); val |= 0x05; /* 44100 */ break; } @@ -854,10 +854,10 @@ static int snd_azf3328_playback_trigger(snd_pcm_substream_t * substream, int cmd chip->is_playing = 0; break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - snd_printk("FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); + snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - snd_printk("FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n"); + snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n"); break; default: return -EINVAL; @@ -935,10 +935,10 @@ static int snd_azf3328_capture_trigger(snd_pcm_substream_t * substream, int cmd) chip->is_playing = 0; break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - snd_printk("FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); + snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - snd_printk("FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n"); + snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n"); break; default: return -EINVAL; @@ -1356,7 +1356,7 @@ static int __devinit snd_azf3328_create(snd_card_t * card, /* check if we can restrict PCI DMA transfers to 24 bits */ if (pci_set_dma_mask(pci, 0x00ffffff) < 0 || pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) { - snd_printk("architecture does not support 24bit PCI busmaster DMA\n"); + snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; } @@ -1374,7 +1374,7 @@ static int __devinit snd_azf3328_create(snd_card_t * card, chip->mixer_port = pci_resource_start(pci, 4); if (request_irq(pci->irq, snd_azf3328_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip)) { - snd_printk("unable to grab IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_azf3328_free(chip); return -EBUSY; } @@ -1450,7 +1450,7 @@ static int __devinit snd_azf3328_probe(struct pci_dev *pci, if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_MPU401, chip->mpu_port, 1, pci->irq, 0, &chip->rmidi)) < 0) { - snd_printk("azf3328: no MPU-401 device at 0x%lx?\n", chip->mpu_port); + snd_printk(KERN_ERR "azf3328: no MPU-401 device at 0x%lx?\n", chip->mpu_port); snd_card_free(card); return err; } @@ -1462,7 +1462,7 @@ static int __devinit snd_azf3328_probe(struct pci_dev *pci, if (snd_opl3_create(card, chip->synth_port, chip->synth_port+2, OPL3_HW_AUTO, 1, &opl3) < 0) { - snd_printk("azf3328: no OPL3 device at 0x%lx-0x%lx?\n", + snd_printk(KERN_ERR "azf3328: no OPL3 device at 0x%lx-0x%lx?\n", chip->synth_port, chip->synth_port+2 ); } else { if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 0d9d8923fbb..f6920ef5b4e 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -281,7 +281,7 @@ int snd_ca0106_i2c_write(ca0106_t *emu, int retry; if ((reg > 0x7f) || (value > 0x1ff)) { - snd_printk("i2c_write: invalid values.\n"); + snd_printk(KERN_ERR "i2c_write: invalid values.\n"); return -EINVAL; } @@ -319,7 +319,7 @@ int snd_ca0106_i2c_write(ca0106_t *emu, if(retry==10) { - snd_printk("Writing to ADC failed!\n"); + snd_printk(KERN_ERR "Writing to ADC failed!\n"); return -EINVAL; } @@ -421,7 +421,7 @@ static int snd_ca0106_pcm_open_capture_channel(snd_pcm_substream_t *substream, i epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); if (epcm == NULL) { - snd_printk("open_capture_channel: failed epcm alloc\n"); + snd_printk(KERN_ERR "open_capture_channel: failed epcm alloc\n"); return -ENOMEM; } epcm->emu = chip; diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index db093bca2cd..57e8e433d56 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -2839,7 +2839,7 @@ static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci, cm->iobase = pci_resource_start(pci, 0); if (request_irq(pci->irq, snd_cmipci_interrupt, SA_INTERRUPT|SA_SHIRQ, card->driver, (void *)cm)) { - snd_printk("unable to grab IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_cmipci_free(cm); return -EBUSY; } diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 147836f09dc..9b8af5bcbb0 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -163,7 +163,7 @@ static unsigned short snd_cs46xx_codec_read(cs46xx_t *chip, goto ok1; } - snd_printk("AC'97 read problem (ACCTL_DCV), reg = 0x%x\n", reg); + snd_printk(KERN_ERR "AC'97 read problem (ACCTL_DCV), reg = 0x%x\n", reg); result = 0xffff; goto end; @@ -182,7 +182,7 @@ static unsigned short snd_cs46xx_codec_read(cs46xx_t *chip, udelay(10); } - snd_printk("AC'97 read problem (ACSTS_VSTS), codec_index %d, reg = 0x%x\n", codec_index, reg); + snd_printk(KERN_ERR "AC'97 read problem (ACSTS_VSTS), codec_index %d, reg = 0x%x\n", codec_index, reg); result = 0xffff; goto end; @@ -281,7 +281,7 @@ static void snd_cs46xx_codec_write(cs46xx_t *chip, goto end; } } - snd_printk("AC'97 write problem, codec_index = %d, reg = 0x%x, val = 0x%x\n", codec_index, reg, val); + snd_printk(KERN_ERR "AC'97 write problem, codec_index = %d, reg = 0x%x, val = 0x%x\n", codec_index, reg, val); end: chip->active_ctrl(chip, -1); } @@ -510,7 +510,7 @@ static void snd_cs46xx_proc_start(cs46xx_t *chip) } if (snd_cs46xx_peek(chip, BA1_SPCR) & SPCR_RUNFR) - snd_printk("SPCR_RUNFR never reset\n"); + snd_printk(KERN_ERR "SPCR_RUNFR never reset\n"); } static void snd_cs46xx_proc_stop(cs46xx_t *chip) @@ -2403,7 +2403,7 @@ static void snd_cs46xx_codec_reset (ac97_t * ac97) msleep(10); } while (time_after_eq(end_time, jiffies)); - snd_printk("CS46xx secondary codec dont respond!\n"); + snd_printk(KERN_ERR "CS46xx secondary codec doesn't respond!\n"); } #endif @@ -3072,8 +3072,8 @@ static int snd_cs46xx_chip_init(cs46xx_t *chip) } - snd_printk("create - never read codec ready from AC'97\n"); - snd_printk("it is not probably bug, try to use CS4236 driver\n"); + snd_printk(KERN_ERR "create - never read codec ready from AC'97\n"); + snd_printk(KERN_ERR "it is not probably bug, try to use CS4236 driver\n"); return -EIO; ok1: #ifdef CONFIG_SND_CS46XX_NEW_DSP @@ -3121,17 +3121,17 @@ static int snd_cs46xx_chip_init(cs46xx_t *chip) } #ifndef CONFIG_SND_CS46XX_NEW_DSP - snd_printk("create - never read ISV3 & ISV4 from AC'97\n"); + snd_printk(KERN_ERR "create - never read ISV3 & ISV4 from AC'97\n"); return -EIO; #else /* This may happen on a cold boot with a Terratec SiXPack 5.1. Reloading the driver may help, if there's other soundcards with the same problem I would like to know. (Benny) */ - snd_printk("ERROR: snd-cs46xx: never read ISV3 & ISV4 from AC'97\n"); - snd_printk(" Try reloading the ALSA driver, if you find something\n"); - snd_printk(" broken or not working on your soundcard upon\n"); - snd_printk(" this message please report to alsa-devel@lists.sourceforge.net\n"); + snd_printk(KERN_ERR "ERROR: snd-cs46xx: never read ISV3 & ISV4 from AC'97\n"); + snd_printk(KERN_ERR " Try reloading the ALSA driver, if you find something\n"); + snd_printk(KERN_ERR " broken or not working on your soundcard upon\n"); + snd_printk(KERN_ERR " this message please report to alsa-devel@lists.sourceforge.net\n"); return -EIO; #endif @@ -3212,7 +3212,7 @@ int __devinit snd_cs46xx_start_dsp(cs46xx_t *chip) #else /* old image */ if (snd_cs46xx_download_image(chip) < 0) { - snd_printk("image download error\n"); + snd_printk(KERN_ERR "image download error\n"); return -EIO; } @@ -3787,7 +3787,7 @@ int __devinit snd_cs46xx_create(snd_card_t * card, chip->ba1_addr = pci_resource_start(pci, 1); if (chip->ba0_addr == 0 || chip->ba0_addr == (unsigned long)~0 || chip->ba1_addr == 0 || chip->ba1_addr == (unsigned long)~0) { - snd_printk("wrong address(es) - ba0 = 0x%lx, ba1 = 0x%lx\n", chip->ba0_addr, chip->ba1_addr); + snd_printk(KERN_ERR "wrong address(es) - ba0 = 0x%lx, ba1 = 0x%lx\n", chip->ba0_addr, chip->ba1_addr); snd_cs46xx_free(chip); return -ENOMEM; } @@ -3836,12 +3836,12 @@ int __devinit snd_cs46xx_create(snd_card_t * card, } if (external_amp) { - snd_printk("Crystal EAPD support forced on.\n"); + snd_printk(KERN_INFO "Crystal EAPD support forced on.\n"); chip->amplifier_ctrl = amp_voyetra; } if (thinkpad) { - snd_printk("Activating CLKRUN hack for Thinkpad.\n"); + snd_printk(KERN_INFO "Activating CLKRUN hack for Thinkpad.\n"); chip->active_ctrl = clkrun_hack; clkrun_init(chip); } @@ -3858,20 +3858,20 @@ int __devinit snd_cs46xx_create(snd_card_t * card, for (idx = 0; idx < 5; idx++) { region = &chip->region.idx[idx]; if ((region->resource = request_mem_region(region->base, region->size, region->name)) == NULL) { - snd_printk("unable to request memory region 0x%lx-0x%lx\n", region->base, region->base + region->size - 1); + snd_printk(KERN_ERR "unable to request memory region 0x%lx-0x%lx\n", region->base, region->base + region->size - 1); snd_cs46xx_free(chip); return -EBUSY; } region->remap_addr = ioremap_nocache(region->base, region->size); if (region->remap_addr == NULL) { - snd_printk("%s ioremap problem\n", region->name); + snd_printk(KERN_ERR "%s ioremap problem\n", region->name); snd_cs46xx_free(chip); return -ENOMEM; } } if (request_irq(pci->irq, snd_cs46xx_interrupt, SA_INTERRUPT|SA_SHIRQ, "CS46XX", (void *) chip)) { - snd_printk("unable to grab IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_cs46xx_free(chip); return -EBUSY; } diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index b0e00f0a7c2..dd1ea9d3b81 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c @@ -188,7 +188,7 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci, if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH, sizeof(snd_emu10k1_synth_arg_t), &wave) < 0 || wave == NULL) { - snd_printk("can't initialize Emu10k1 wavetable synth\n"); + snd_printk(KERN_WARNING "can't initialize Emu10k1 wavetable synth\n"); } else { snd_emu10k1_synth_arg_t *arg; arg = SNDRV_SEQ_DEVICE_ARGPTR(wave); diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 177c4ad0f77..03e8c167895 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c @@ -1392,7 +1392,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) A_SWITCH(icode, &ptr, tmp + 1, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, tmp + 1); if ((z==1) && (emu->card_capabilities->spdif_bug)) { /* Due to a SPDIF output bug on some Audigy cards, this code delays the Right channel by 1 sample */ - snd_printk("Installing spdif_bug patch: %s\n", emu->card_capabilities->name); + snd_printk(KERN_INFO "Installing spdif_bug patch: %s\n", emu->card_capabilities->name); A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(gpr - 3), A_C_00000000, A_C_00000000); A_OP(icode, &ptr, iACC3, A_GPR(gpr - 3), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000); } else { diff --git a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c index cd8460d5675..594ea063b14 100644 --- a/sound/pci/emu10k1/irq.c +++ b/sound/pci/emu10k1/irq.c @@ -41,7 +41,7 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs) orig_status = status; handled = 1; if (status & IPR_PCIERROR) { - snd_printk("interrupt: PCI error\n"); + snd_printk(KERN_ERR "interrupt: PCI error\n"); snd_emu10k1_intr_disable(emu, INTE_PCIERRORENABLE); status &= ~IPR_PCIERROR; } diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index 6afeaeab3e1..d42e4aeaa73 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c @@ -232,11 +232,11 @@ __found_pages: static int is_valid_page(emu10k1_t *emu, dma_addr_t addr) { if (addr & ~emu->dma_mask) { - snd_printk("max memory size is 0x%lx (addr = 0x%lx)!!\n", emu->dma_mask, (unsigned long)addr); + snd_printk(KERN_ERR "max memory size is 0x%lx (addr = 0x%lx)!!\n", emu->dma_mask, (unsigned long)addr); return 0; } if (addr & (EMUPAGESIZE-1)) { - snd_printk("page is not aligned\n"); + snd_printk(KERN_ERR "page is not aligned\n"); return 0; } return 1; @@ -501,7 +501,7 @@ static inline void *offset_ptr(emu10k1_t *emu, int page, int offset) snd_assert(page >= 0 && page < emu->max_cache_pages, return NULL); ptr = emu->page_ptr_table[page]; if (! ptr) { - printk("emu10k1: access to NULL ptr: page = %d\n", page); + printk(KERN_ERR "emu10k1: access to NULL ptr: page = %d\n", page); return NULL; } ptr += offset & (PAGE_SIZE - 1); diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index d59c7f345ad..e27ebb9bb74 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c @@ -546,7 +546,7 @@ snd_p16v_pcm_pointer_capture(snd_pcm_substream_t *substream) ptr=ptr2; if (ptr >= runtime->buffer_size) { ptr -= runtime->buffer_size; - printk("buffer capture limited!\n"); + printk(KERN_WARNING "buffer capture limited!\n"); } //printk("ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, (int)runtime->rate); diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index bef9a59f46d..b4d0a9c2b0b 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -508,7 +508,7 @@ static unsigned int snd_es1371_wait_src_ready(ensoniq_t * ensoniq) return r; cond_resched(); } - snd_printk("wait source ready timeout 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_SMPRATE), r); + snd_printk(KERN_ERR "wait source ready timeout 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_SMPRATE), r); return 0; } @@ -579,7 +579,7 @@ static void snd_es1370_codec_write(ak4531_t *ak4531, set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); } while (time_after(end_time, jiffies)); - snd_printk("codec write timeout, status = 0x%x\n", inl(ES_REG(ensoniq, STATUS))); + snd_printk(KERN_ERR "codec write timeout, status = 0x%x\n", inl(ES_REG(ensoniq, STATUS))); } #endif /* CHIP1370 */ @@ -620,7 +620,7 @@ static void snd_es1371_codec_write(ac97_t *ac97, } } up(&ensoniq->src_mutex); - snd_printk("codec write timeout at 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC))); + snd_printk(KERN_ERR "codec write timeout at 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC))); } static unsigned short snd_es1371_codec_read(ac97_t *ac97, @@ -667,14 +667,14 @@ static unsigned short snd_es1371_codec_read(ac97_t *ac97, } up(&ensoniq->src_mutex); if (++fail > 10) { - snd_printk("codec read timeout (final) at 0x%lx, reg = 0x%x [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), reg, inl(ES_REG(ensoniq, 1371_CODEC))); + snd_printk(KERN_ERR "codec read timeout (final) at 0x%lx, reg = 0x%x [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), reg, inl(ES_REG(ensoniq, 1371_CODEC))); return 0; } goto __again; } } up(&ensoniq->src_mutex); - snd_printk("es1371: codec read timeout at 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC))); + snd_printk(KERN_ERR "es1371: codec read timeout at 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC))); return 0; } @@ -1960,7 +1960,7 @@ static int __devinit snd_ensoniq_create(snd_card_t * card, } ensoniq->port = pci_resource_start(pci, 0); if (request_irq(pci->irq, snd_audiopci_interrupt, SA_INTERRUPT|SA_SHIRQ, "Ensoniq AudioPCI", (void *)ensoniq)) { - snd_printk("unable to grab IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_ensoniq_free(ensoniq); return -EBUSY; } @@ -1968,7 +1968,7 @@ static int __devinit snd_ensoniq_create(snd_card_t * card, #ifdef CHIP1370 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 16, &ensoniq->dma_bug) < 0) { - snd_printk("unable to allocate space for phantom area - dma_bug\n"); + snd_printk(KERN_ERR "unable to allocate space for phantom area - dma_bug\n"); snd_ensoniq_free(ensoniq); return -EBUSY; } diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 7bfbdfc2f8b..78f90defcab 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -267,7 +267,7 @@ static void snd_es1938_mixer_write(es1938_t *chip, unsigned char reg, unsigned c outb(val, SLSB_REG(chip, MIXERDATA)); spin_unlock_irqrestore(&chip->mixer_lock, flags); #ifdef REG_DEBUG - snd_printk("Mixer reg %02x set to %02x\n", reg, val); + snd_printk(KERN_DEBUG "Mixer reg %02x set to %02x\n", reg, val); #endif } @@ -283,7 +283,7 @@ static int snd_es1938_mixer_read(es1938_t *chip, unsigned char reg) data = inb(SLSB_REG(chip, MIXERDATA)); spin_unlock_irqrestore(&chip->mixer_lock, flags); #ifdef REG_DEBUG - snd_printk("Mixer reg %02x now is %02x\n", reg, data); + snd_printk(KERN_DEBUG "Mixer reg %02x now is %02x\n", reg, data); #endif return data; } @@ -303,7 +303,8 @@ static int snd_es1938_mixer_bits(es1938_t *chip, unsigned char reg, unsigned cha new = (old & ~mask) | (val & mask); outb(new, SLSB_REG(chip, MIXERDATA)); #ifdef REG_DEBUG - snd_printk("Mixer reg %02x was %02x, set to %02x\n", reg, old, new); + snd_printk(KERN_DEBUG "Mixer reg %02x was %02x, set to %02x\n", + reg, old, new); #endif } spin_unlock_irqrestore(&chip->mixer_lock, flags); @@ -323,7 +324,7 @@ static void snd_es1938_write_cmd(es1938_t *chip, unsigned char cmd) return; } } - printk("snd_es1938_write_cmd timeout (0x02%x/0x02%x)\n", cmd, v); + printk(KERN_ERR "snd_es1938_write_cmd timeout (0x02%x/0x02%x)\n", cmd, v); } /* ----------------------------------------------------------------- @@ -336,7 +337,7 @@ static int snd_es1938_get_byte(es1938_t *chip) for (i = GET_LOOP_TIMEOUT; i; i--) if ((v = inb(SLSB_REG(chip, STATUS))) & 0x80) return inb(SLSB_REG(chip, READDATA)); - snd_printk("get_byte timeout: status 0x02%x\n", v); + snd_printk(KERN_ERR "get_byte timeout: status 0x02%x\n", v); return -ENODEV; } @@ -351,7 +352,7 @@ static void snd_es1938_write(es1938_t *chip, unsigned char reg, unsigned char va snd_es1938_write_cmd(chip, val); spin_unlock_irqrestore(&chip->reg_lock, flags); #ifdef REG_DEBUG - snd_printk("Reg %02x set to %02x\n", reg, val); + snd_printk(KERN_DEBUG "Reg %02x set to %02x\n", reg, val); #endif } @@ -368,7 +369,7 @@ static unsigned char snd_es1938_read(es1938_t *chip, unsigned char reg) val = snd_es1938_get_byte(chip); spin_unlock_irqrestore(&chip->reg_lock, flags); #ifdef REG_DEBUG - snd_printk("Reg %02x now is %02x\n", reg, val); + snd_printk(KERN_DEBUG "Reg %02x now is %02x\n", reg, val); #endif return val; } @@ -390,7 +391,8 @@ static int snd_es1938_bits(es1938_t *chip, unsigned char reg, unsigned char mask new = (old & ~mask) | (val & mask); snd_es1938_write_cmd(chip, new); #ifdef REG_DEBUG - snd_printk("Reg %02x was %02x, set to %02x\n", reg, old, new); + snd_printk(KERN_DEBUG "Reg %02x was %02x, set to %02x\n", + reg, old, new); #endif } spin_unlock_irqrestore(&chip->reg_lock, flags); @@ -413,7 +415,7 @@ static void snd_es1938_reset(es1938_t *chip) goto __next; } } - snd_printk("ESS Solo-1 reset failed\n"); + snd_printk(KERN_ERR "ESS Solo-1 reset failed\n"); __next: snd_es1938_write_cmd(chip, ESS_CMD_ENABLEEXT); @@ -1499,7 +1501,7 @@ static int __devinit snd_es1938_create(snd_card_t * card, /* check, if we can restrict PCI DMA transfers to 24 bits */ if (pci_set_dma_mask(pci, 0x00ffffff) < 0 || pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) { - snd_printk("architecture does not support 24bit PCI busmaster DMA\n"); + snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; } @@ -1524,13 +1526,13 @@ static int __devinit snd_es1938_create(snd_card_t * card, chip->mpu_port = pci_resource_start(pci, 3); chip->game_port = pci_resource_start(pci, 4); if (request_irq(pci->irq, snd_es1938_interrupt, SA_INTERRUPT|SA_SHIRQ, "ES1938", (void *)chip)) { - snd_printk("unable to grab IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_es1938_free(chip); return -EBUSY; } chip->irq = pci->irq; #ifdef ES1938_DDEBUG - snd_printk("create: io: 0x%lx, sb: 0x%lx, vc: 0x%lx, mpu: 0x%lx, game: 0x%lx\n", + snd_printk(KERN_DEBUG "create: io: 0x%lx, sb: 0x%lx, vc: 0x%lx, mpu: 0x%lx, game: 0x%lx\n", chip->io_port, chip->sb_port, chip->vc_port, chip->mpu_port, chip->game_port); #endif diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 1bf094b6746..ac8294e21cc 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -1462,13 +1462,13 @@ snd_es1968_init_dmabuf(es1968_t *chip) snd_dma_pci_data(chip->pci), chip->total_bufsize, &chip->dma); if (err < 0 || ! chip->dma.area) { - snd_printk("es1968: can't allocate dma pages for size %d\n", + snd_printk(KERN_ERR "es1968: can't allocate dma pages for size %d\n", chip->total_bufsize); return -ENOMEM; } if ((chip->dma.addr + chip->dma.bytes - 1) & ~((1 << 28) - 1)) { snd_dma_free_pages(&chip->dma); - snd_printk("es1968: DMA buffer beyond 256MB.\n"); + snd_printk(KERN_ERR "es1968: DMA buffer beyond 256MB.\n"); return -ENOMEM; } } @@ -1741,11 +1741,11 @@ static void __devinit es1968_measure_clock(es1968_t *chip) /* search 2 APUs (although one apu is enough) */ if ((apu = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_PLAY)) < 0) { - snd_printk("Hmm, cannot find empty APU pair!?\n"); + snd_printk(KERN_ERR "Hmm, cannot find empty APU pair!?\n"); return; } if ((memory = snd_es1968_new_memory(chip, CLOCK_MEASURE_BUFSIZE)) == NULL) { - snd_printk("cannot allocate dma buffer - using default clock %d\n", chip->clock); + snd_printk(KERN_ERR "cannot allocate dma buffer - using default clock %d\n", chip->clock); snd_es1968_free_apu_pair(chip, apu); return; } @@ -1806,7 +1806,7 @@ static void __devinit es1968_measure_clock(es1968_t *chip) else t += stop_time.tv_usec - start_time.tv_usec; if (t == 0) { - snd_printk("?? calculation error..\n"); + snd_printk(KERN_ERR "?? calculation error..\n"); } else { offset *= 1000; offset = (offset / t) * 1000 + ((offset % t) * 1000) / t; @@ -2090,7 +2090,7 @@ static void snd_es1968_ac97_reset(es1968_t *chip) outw(inw(ioaddr + 0x3c) & 0xfffc, ioaddr + 0x3c); #if 0 /* the loop here needs to be much better if we want it.. */ - snd_printk("trying software reset\n"); + snd_printk(KERN_INFO "trying software reset\n"); /* try and do a software reset */ outb(0x80 | 0x7c, ioaddr + 0x30); for (w = 0;; w++) { @@ -2562,7 +2562,7 @@ static int __devinit snd_es1968_create(snd_card_t * card, /* check, if we can restrict PCI DMA transfers to 28 bits */ if (pci_set_dma_mask(pci, 0x0fffffff) < 0 || pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) { - snd_printk("architecture does not support 28bit PCI busmaster DMA\n"); + snd_printk(KERN_ERR "architecture does not support 28bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; } @@ -2597,7 +2597,7 @@ static int __devinit snd_es1968_create(snd_card_t * card, chip->io_port = pci_resource_start(pci, 0); if (request_irq(pci->irq, snd_es1968_interrupt, SA_INTERRUPT|SA_SHIRQ, "ESS Maestro", (void*)chip)) { - snd_printk("unable to grab IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_es1968_free(chip); return -EBUSY; } diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index e5cfa2a0c24..47dbe317069 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -237,7 +237,7 @@ static void snd_fm801_codec_write(ac97_t *ac97, goto ok1; udelay(10); } - snd_printk("AC'97 interface is busy (1)\n"); + snd_printk(KERN_ERR "AC'97 interface is busy (1)\n"); return; ok1: @@ -252,7 +252,7 @@ static void snd_fm801_codec_write(ac97_t *ac97, return; udelay(10); } - snd_printk("AC'97 interface #%d is busy (2)\n", ac97->num); + snd_printk(KERN_ERR "AC'97 interface #%d is busy (2)\n", ac97->num); } static unsigned short snd_fm801_codec_read(ac97_t *ac97, unsigned short reg) @@ -268,7 +268,7 @@ static unsigned short snd_fm801_codec_read(ac97_t *ac97, unsigned short reg) goto ok1; udelay(10); } - snd_printk("AC'97 interface is busy (1)\n"); + snd_printk(KERN_ERR "AC'97 interface is busy (1)\n"); return 0; ok1: @@ -279,7 +279,7 @@ static unsigned short snd_fm801_codec_read(ac97_t *ac97, unsigned short reg) goto ok2; udelay(10); } - snd_printk("AC'97 interface #%d is busy (2)\n", ac97->num); + snd_printk(KERN_ERR "AC'97 interface #%d is busy (2)\n", ac97->num); return 0; ok2: @@ -288,7 +288,7 @@ static unsigned short snd_fm801_codec_read(ac97_t *ac97, unsigned short reg) goto ok3; udelay(10); } - snd_printk("AC'97 interface #%d is not valid (2)\n", ac97->num); + snd_printk(KERN_ERR "AC'97 interface #%d is not valid (2)\n", ac97->num); return 0; ok3: @@ -1279,7 +1279,7 @@ static int __devinit snd_fm801_create(snd_card_t * card, } chip->port = pci_resource_start(pci, 0); if (request_irq(pci->irq, snd_fm801_interrupt, SA_INTERRUPT|SA_SHIRQ, "FM801", (void *)chip)) { - snd_printk("unable to grab IRQ %d\n", chip->irq); + snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->irq); snd_fm801_free(chip); return -EBUSY; } @@ -1306,7 +1306,7 @@ static int __devinit snd_fm801_create(snd_card_t * card, set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); } while (time_after(timeout, jiffies)); - snd_printk("Primary AC'97 codec not found\n"); + snd_printk(KERN_ERR "Primary AC'97 codec not found\n"); snd_fm801_free(chip); return -EIO; @@ -1346,7 +1346,7 @@ static int __devinit snd_fm801_create(snd_card_t * card, set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); } while (time_after(timeout, jiffies)); - snd_printk("Primary AC'97 codec not responding\n"); + snd_printk(KERN_ERR "Primary AC'97 codec not responding\n"); snd_fm801_free(chip); return -EIO; diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c index 2e0a31613ee..40b48186767 100644 --- a/sound/pci/ice1712/aureon.c +++ b/sound/pci/ice1712/aureon.c @@ -1672,9 +1672,9 @@ static int __devinit aureon_add_controls(ice1712_t *ice) snd_ice1712_save_gpio_status(ice); id = aureon_cs8415_get(ice, CS8415_ID); if (id != 0x41) - snd_printk("No CS8415 chip. Skipping CS8415 controls.\n"); + snd_printk(KERN_INFO "No CS8415 chip. Skipping CS8415 controls.\n"); else if ((id & 0x0F) != 0x01) - snd_printk("Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1)); + snd_printk(KERN_INFO "Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1)); else { for (i = 0; i< ARRAY_SIZE(cs8415_controls); i++) { snd_kcontrol_t *kctl; diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c index 39fbe662965..576f69d482c 100644 --- a/sound/pci/ice1712/delta.c +++ b/sound/pci/ice1712/delta.c @@ -546,7 +546,7 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice) case ICE1712_SUBDEVICE_DELTA1010LT: case ICE1712_SUBDEVICE_VX442: if ((err = snd_i2c_bus_create(ice->card, "ICE1712 GPIO 1", NULL, &ice->i2c)) < 0) { - snd_printk("unable to create I2C bus\n"); + snd_printk(KERN_ERR "unable to create I2C bus\n"); return err; } ice->i2c->private_data = ice; diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c index e36efa1bdac..c8ec5cac3c1 100644 --- a/sound/pci/ice1712/ews.c +++ b/sound/pci/ice1712/ews.c @@ -438,7 +438,7 @@ static int __devinit snd_ice1712_ews_init(ice1712_t *ice) /* create i2c */ if ((err = snd_i2c_bus_create(ice->card, "ICE1712 GPIO 1", NULL, &ice->i2c)) < 0) { - snd_printk("unable to create I2C bus\n"); + snd_printk(KERN_ERR "unable to create I2C bus\n"); return err; } ice->i2c->private_data = ice; @@ -448,7 +448,7 @@ static int __devinit snd_ice1712_ews_init(ice1712_t *ice) switch (ice->eeprom.subvendor) { case ICE1712_SUBDEVICE_DMX6FIRE: if ((err = snd_i2c_device_create(ice->i2c, "PCF9554", ICE1712_6FIRE_PCF9554_ADDR, &ice->spec.i2cdevs[EWS_I2C_6FIRE])) < 0) { - snd_printk("PCF9554 initialization failed\n"); + snd_printk(KERN_ERR "PCF9554 initialization failed\n"); return err; } snd_ice1712_6fire_write_pca(ice, PCF9554_REG_CONFIG, 0x80); @@ -791,7 +791,7 @@ static int snd_ice1712_6fire_read_pca(ice1712_t *ice, unsigned char reg) byte = 0; if (snd_i2c_readbytes(ice->spec.i2cdevs[EWS_I2C_6FIRE], &byte, 1) != 1) { snd_i2c_unlock(ice->i2c); - printk("cannot read pca\n"); + printk(KERN_ERR "cannot read pca\n"); return -EIO; } snd_i2c_unlock(ice->i2c); diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index a6d98013c33..5aca37798c3 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -387,7 +387,7 @@ int __devinit snd_ice1712_init_cs8427(ice1712_t *ice, int addr) if ((err = snd_cs8427_create(ice->i2c, addr, (ice->cs8427_timeout * HZ) / 1000, &ice->cs8427)) < 0) { - snd_printk("CS8427 initialization failed\n"); + snd_printk(KERN_ERR "CS8427 initialization failed\n"); return err; } ice->spdif.ops.open = open_cs8427; @@ -2348,12 +2348,12 @@ static int __devinit snd_ice1712_read_eeprom(ice1712_t *ice, const char *modelna if (ice->eeprom.size < 6) ice->eeprom.size = 32; /* FIXME: any cards without the correct size? */ else if (ice->eeprom.size > 32) { - snd_printk("invalid EEPROM (size = %i)\n", ice->eeprom.size); + snd_printk(KERN_ERR "invalid EEPROM (size = %i)\n", ice->eeprom.size); return -EIO; } ice->eeprom.version = snd_ice1712_read_i2c(ice, dev, 0x05); if (ice->eeprom.version != 1) { - snd_printk("invalid EEPROM version %i\n", ice->eeprom.version); + snd_printk(KERN_ERR "invalid EEPROM version %i\n", ice->eeprom.version); /* return -EIO; */ } size = ice->eeprom.size - 6; @@ -2524,7 +2524,7 @@ static int __devinit snd_ice1712_create(snd_card_t * card, /* check, if we can restrict PCI DMA transfers to 28 bits */ if (pci_set_dma_mask(pci, 0x0fffffff) < 0 || pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) { - snd_printk("architecture does not support 28bit PCI busmaster DMA\n"); + snd_printk(KERN_ERR "architecture does not support 28bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; } @@ -2573,7 +2573,7 @@ static int __devinit snd_ice1712_create(snd_card_t * card, ice->profi_port = pci_resource_start(pci, 3); if (request_irq(pci->irq, snd_ice1712_interrupt, SA_INTERRUPT|SA_SHIRQ, "ICE1712", (void *) ice)) { - snd_printk("unable to grab IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_ice1712_free(ice); return -EIO; } diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index a1133c53412..5b4293f5a65 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -2171,7 +2171,7 @@ static int __devinit snd_vt1724_create(snd_card_t * card, ice->profi_port = pci_resource_start(pci, 1); if (request_irq(pci->irq, snd_vt1724_interrupt, SA_INTERRUPT|SA_SHIRQ, "ICE1724", (void *) ice)) { - snd_printk("unable to grab IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_vt1724_free(ice); return -EIO; } diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 68d0ed033d3..d71f5d1e716 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -538,7 +538,7 @@ static int snd_intel8x0_codec_semaphore(intel8x0_t *chip, unsigned int codec) /* access to some forbidden (non existant) ac97 registers will not * reset the semaphore. So even if you don't get the semaphore, still * continue the access. We don't need the semaphore anyway. */ - snd_printk("codec_semaphore: semaphore is not ready [0x%x][0x%x]\n", + snd_printk(KERN_ERR "codec_semaphore: semaphore is not ready [0x%x][0x%x]\n", igetbyte(chip, ICHREG(ACC_SEMA)), igetdword(chip, ICHREG(GLOB_STA))); iagetword(chip, 0); /* clear semaphore flag */ /* I don't care about the semaphore */ @@ -553,7 +553,7 @@ static void snd_intel8x0_codec_write(ac97_t *ac97, if (snd_intel8x0_codec_semaphore(chip, ac97->num) < 0) { if (! chip->in_ac97_init) - snd_printk("codec_write %d: semaphore is not ready for register 0x%x\n", ac97->num, reg); + snd_printk(KERN_ERR "codec_write %d: semaphore is not ready for register 0x%x\n", ac97->num, reg); } iaputword(chip, reg + ac97->num * 0x80, val); } @@ -567,7 +567,7 @@ static unsigned short snd_intel8x0_codec_read(ac97_t *ac97, if (snd_intel8x0_codec_semaphore(chip, ac97->num) < 0) { if (! chip->in_ac97_init) - snd_printk("codec_read %d: semaphore is not ready for register 0x%x\n", ac97->num, reg); + snd_printk(KERN_ERR "codec_read %d: semaphore is not ready for register 0x%x\n", ac97->num, reg); res = 0xffff; } else { res = iagetword(chip, reg + ac97->num * 0x80); @@ -575,7 +575,7 @@ static unsigned short snd_intel8x0_codec_read(ac97_t *ac97, /* reset RCS and preserve other R/WC bits */ iputdword(chip, ICHREG(GLOB_STA), tmp & ~(ICH_SRI|ICH_PRI|ICH_TRI|ICH_GSCI)); if (! chip->in_ac97_init) - snd_printk("codec_read %d: read timeout for register 0x%x\n", ac97->num, reg); + snd_printk(KERN_ERR "codec_read %d: read timeout for register 0x%x\n", ac97->num, reg); res = 0xffff; } } @@ -2173,7 +2173,7 @@ static int snd_intel8x0_ich_chip_init(intel8x0_t *chip, int probing) goto __ok; do_delay(chip); } while (time_after_eq(end_time, jiffies)); - snd_printk("AC'97 warm reset still in progress? [0x%x]\n", igetdword(chip, ICHREG(GLOB_CNT))); + snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n", igetdword(chip, ICHREG(GLOB_CNT))); return -EIO; __ok: @@ -2448,7 +2448,7 @@ static void __devinit intel8x0_measure_ac97_clock(intel8x0_t *chip) subs = chip->pcm[0]->streams[0].substream; if (! subs || subs->dma_buffer.bytes < INTEL8X0_TESTBUF_SIZE) { - snd_printk("no playback buffer allocated - aborting measure ac97 clock\n"); + snd_printk(KERN_WARNING "no playback buffer allocated - aborting measure ac97 clock\n"); return; } ichdev = &chip->ichd[ICHD_PCMOUT]; @@ -2655,7 +2655,7 @@ static int __devinit snd_intel8x0_create(snd_card_t * card, chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci, 2)); if (chip->remap_addr == NULL) { - snd_printk("AC'97 space ioremap problem\n"); + snd_printk(KERN_ERR "AC'97 space ioremap problem\n"); snd_intel8x0_free(chip); return -EIO; } @@ -2668,7 +2668,7 @@ static int __devinit snd_intel8x0_create(snd_card_t * card, chip->remap_bmaddr = ioremap_nocache(chip->bmaddr, pci_resource_len(pci, 3)); if (chip->remap_bmaddr == NULL) { - snd_printk("Controller space ioremap problem\n"); + snd_printk(KERN_ERR "Controller space ioremap problem\n"); snd_intel8x0_free(chip); return -EIO; } @@ -2678,7 +2678,7 @@ static int __devinit snd_intel8x0_create(snd_card_t * card, port_inited: if (request_irq(pci->irq, snd_intel8x0_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip)) { - snd_printk("unable to grab IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_intel8x0_free(chip); return -EBUSY; } diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 42601f0e6a5..49a9f4d0896 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -363,7 +363,7 @@ static int snd_intel8x0m_codec_semaphore(intel8x0_t *chip, unsigned int codec) /* access to some forbidden (non existant) ac97 registers will not * reset the semaphore. So even if you don't get the semaphore, still * continue the access. We don't need the semaphore anyway. */ - snd_printk("codec_semaphore: semaphore is not ready [0x%x][0x%x]\n", + snd_printk(KERN_ERR "codec_semaphore: semaphore is not ready [0x%x][0x%x]\n", igetbyte(chip, ICHREG(ACC_SEMA)), igetdword(chip, ICHREG(GLOB_STA))); iagetword(chip, 0); /* clear semaphore flag */ /* I don't care about the semaphore */ @@ -378,7 +378,7 @@ static void snd_intel8x0_codec_write(ac97_t *ac97, if (snd_intel8x0m_codec_semaphore(chip, ac97->num) < 0) { if (! chip->in_ac97_init) - snd_printk("codec_write %d: semaphore is not ready for register 0x%x\n", ac97->num, reg); + snd_printk(KERN_ERR "codec_write %d: semaphore is not ready for register 0x%x\n", ac97->num, reg); } iaputword(chip, reg + ac97->num * 0x80, val); } @@ -392,7 +392,7 @@ static unsigned short snd_intel8x0_codec_read(ac97_t *ac97, if (snd_intel8x0m_codec_semaphore(chip, ac97->num) < 0) { if (! chip->in_ac97_init) - snd_printk("codec_read %d: semaphore is not ready for register 0x%x\n", ac97->num, reg); + snd_printk(KERN_ERR "codec_read %d: semaphore is not ready for register 0x%x\n", ac97->num, reg); res = 0xffff; } else { res = iagetword(chip, reg + ac97->num * 0x80); @@ -400,7 +400,7 @@ static unsigned short snd_intel8x0_codec_read(ac97_t *ac97, /* reset RCS and preserve other R/WC bits */ iputdword(chip, ICHREG(GLOB_STA), tmp & ~(ICH_SRI|ICH_PRI|ICH_TRI|ICH_GSCI)); if (! chip->in_ac97_init) - snd_printk("codec_read %d: read timeout for register 0x%x\n", ac97->num, reg); + snd_printk(KERN_ERR "codec_read %d: read timeout for register 0x%x\n", ac97->num, reg); res = 0xffff; } } @@ -917,7 +917,7 @@ static int snd_intel8x0m_ich_chip_init(intel8x0_t *chip, int probing) goto __ok; do_delay(chip); } while (time_after_eq(end_time, jiffies)); - snd_printk("AC'97 warm reset still in progress? [0x%x]\n", igetdword(chip, ICHREG(GLOB_CNT))); + snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n", igetdword(chip, ICHREG(GLOB_CNT))); return -EIO; __ok: @@ -1143,7 +1143,7 @@ static int __devinit snd_intel8x0m_create(snd_card_t * card, chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci, 2)); if (chip->remap_addr == NULL) { - snd_printk("AC'97 space ioremap problem\n"); + snd_printk(KERN_ERR "AC'97 space ioremap problem\n"); snd_intel8x0_free(chip); return -EIO; } @@ -1156,7 +1156,7 @@ static int __devinit snd_intel8x0m_create(snd_card_t * card, chip->remap_bmaddr = ioremap_nocache(chip->bmaddr, pci_resource_len(pci, 3)); if (chip->remap_bmaddr == NULL) { - snd_printk("Controller space ioremap problem\n"); + snd_printk(KERN_ERR "Controller space ioremap problem\n"); snd_intel8x0_free(chip); return -EIO; } @@ -1166,7 +1166,7 @@ static int __devinit snd_intel8x0m_create(snd_card_t * card, port_inited: if (request_irq(pci->irq, snd_intel8x0_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip)) { - snd_printk("unable to grab IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_intel8x0_free(chip); return -EBUSY; } diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 7b1b82521cf..ad77b414582 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -1492,7 +1492,7 @@ static int snd_m3_pcm_hw_params(snd_pcm_substream_t * substream, /* set buffer address */ s->buffer_addr = substream->runtime->dma_addr; if (s->buffer_addr & 0x3) { - snd_printk("oh my, not aligned\n"); + snd_printk(KERN_ERR "oh my, not aligned\n"); s->buffer_addr = s->buffer_addr & ~0x3; } return 0; @@ -1942,7 +1942,7 @@ static int snd_m3_ac97_wait(m3_t *chip) return 0; } while (i-- > 0); - snd_printk("ac97 serial bus busy\n"); + snd_printk(KERN_ERR "ac97 serial bus busy\n"); return 1; } @@ -2367,7 +2367,7 @@ static int __devinit snd_m3_assp_client_init(m3_t *chip, m3_dma_t *s, int index) address = 0x1100 + ((data_bytes/2) * index); if ((address + (data_bytes/2)) >= 0x1c00) { - snd_printk("no memory for %d bytes at ind %d (addr 0x%x)\n", + snd_printk(KERN_ERR "no memory for %d bytes at ind %d (addr 0x%x)\n", data_bytes, index, address); return -ENOMEM; } @@ -2656,7 +2656,7 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci, /* check, if we can restrict PCI DMA transfers to 28 bits */ if (pci_set_dma_mask(pci, 0x0fffffff) < 0 || pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) { - snd_printk("architecture does not support 28bit PCI busmaster DMA\n"); + snd_printk(KERN_ERR "architecture does not support 28bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; } @@ -2741,7 +2741,7 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci, if (request_irq(pci->irq, snd_m3_interrupt, SA_INTERRUPT|SA_SHIRQ, card->driver, (void *)chip)) { - snd_printk("unable to grab IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_m3_free(chip); return -ENOMEM; } diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index cccdc576b8a..e7aa1517845 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -320,9 +320,9 @@ static inline void snd_nm256_write_buffer(nm256_t *chip, void *src, int offset, int size) { offset -= chip->buffer_start; -#ifdef SNDRV_CONFIG_DEBUG +#ifdef CONFIG_SND_DEBUG if (offset < 0 || offset >= chip->buffer_size) { - snd_printk("write_buffer invalid offset = %d size = %d\n", offset, size); + snd_printk(KERN_ERR "write_buffer invalid offset = %d size = %d\n", offset, size); return; } #endif @@ -466,7 +466,7 @@ static int snd_nm256_acquire_irq(nm256_t *chip) if (chip->irq < 0) { if (request_irq(chip->pci->irq, chip->interrupt, SA_INTERRUPT|SA_SHIRQ, chip->card->driver, (void*)chip)) { - snd_printk("unable to grab IRQ %d\n", chip->pci->irq); + snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->pci->irq); up(&chip->irq_mutex); return -EBUSY; } @@ -1273,7 +1273,7 @@ snd_nm256_peek_for_sig(nm256_t *chip) temp = ioremap_nocache(chip->buffer_addr + chip->buffer_end - 0x400, 16); if (temp == NULL) { - snd_printk("Unable to scan for card signature in video RAM\n"); + snd_printk(KERN_ERR "Unable to scan for card signature in video RAM\n"); return -EBUSY; } @@ -1287,7 +1287,7 @@ snd_nm256_peek_for_sig(nm256_t *chip) if (pointer == 0xffffffff || pointer < chip->buffer_size || pointer > chip->buffer_end) { - snd_printk("invalid signature found: 0x%x\n", pointer); + snd_printk(KERN_ERR "invalid signature found: 0x%x\n", pointer); iounmap(temp); return -ENODEV; } else { @@ -1424,14 +1424,14 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci, chip->res_cport = request_mem_region(chip->cport_addr, NM_PORT2_SIZE, card->driver); if (chip->res_cport == NULL) { - snd_printk("memory region 0x%lx (size 0x%x) busy\n", + snd_printk(KERN_ERR "memory region 0x%lx (size 0x%x) busy\n", chip->cport_addr, NM_PORT2_SIZE); err = -EBUSY; goto __error; } chip->cport = ioremap_nocache(chip->cport_addr, NM_PORT2_SIZE); if (chip->cport == NULL) { - snd_printk("unable to map control port %lx\n", chip->cport_addr); + snd_printk(KERN_ERR "unable to map control port %lx\n", chip->cport_addr); err = -ENOMEM; goto __error; } @@ -1489,7 +1489,7 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci, chip->buffer_size, card->driver); if (chip->res_buffer == NULL) { - snd_printk("nm256: buffer 0x%lx (size 0x%x) busy\n", + snd_printk(KERN_ERR "nm256: buffer 0x%lx (size 0x%x) busy\n", chip->buffer_addr, chip->buffer_size); err = -EBUSY; goto __error; @@ -1497,7 +1497,7 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci, chip->buffer = ioremap_nocache(chip->buffer_addr, chip->buffer_size); if (chip->buffer == NULL) { err = -ENOMEM; - snd_printk("unable to map ring buffer at %lx\n", chip->buffer_addr); + snd_printk(KERN_ERR "unable to map ring buffer at %lx\n", chip->buffer_addr); goto __error; } @@ -1605,7 +1605,7 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci, strcpy(card->driver, "NM256XL+"); break; default: - snd_printk("invalid device id 0x%x\n", pci->device); + snd_printk(KERN_ERR "invalid device id 0x%x\n", pci->device); snd_card_free(card); return -EINVAL; } diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index cd313af6ebc..e6627b0e38e 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -1369,13 +1369,13 @@ static int __devinit snd_rme32_create(rme32_t * rme32) rme32->port = pci_resource_start(rme32->pci, 0); if (request_irq(pci->irq, snd_rme32_interrupt, SA_INTERRUPT | SA_SHIRQ, "RME32", (void *) rme32)) { - snd_printk("unable to grab IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); return -EBUSY; } rme32->irq = pci->irq; if ((rme32->iobase = ioremap_nocache(rme32->port, RME32_IO_SIZE)) == 0) { - snd_printk("unable to remap memory region 0x%lx-0x%lx\n", + snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", rme32->port, rme32->port + RME32_IO_SIZE - 1); return -ENOMEM; } diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index c495cae78db..0eddeb16a10 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -1570,13 +1570,13 @@ snd_rme96_create(rme96_t *rme96) rme96->port = pci_resource_start(rme96->pci, 0); if (request_irq(pci->irq, snd_rme96_interrupt, SA_INTERRUPT|SA_SHIRQ, "RME96", (void *)rme96)) { - snd_printk("unable to grab IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); return -EBUSY; } rme96->irq = pci->irq; if ((rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE)) == 0) { - snd_printk("unable to remap memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1); + snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1); return -ENOMEM; } diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index b600f45e183..59fcef9b6b8 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -779,7 +779,7 @@ static inline int rme9652_spdif_sample_rate(rme9652_t *s) break; default: - snd_printk("%s: unknown S/PDIF input rate (bits = 0x%x)\n", + snd_printk(KERN_ERR "%s: unknown S/PDIF input rate (bits = 0x%x)\n", s->card_name, rate_bits); return 0; break; @@ -2496,12 +2496,12 @@ static int __devinit snd_rme9652_create(snd_card_t *card, rme9652->port = pci_resource_start(pci, 0); rme9652->iobase = ioremap_nocache(rme9652->port, RME9652_IO_EXTENT); if (rme9652->iobase == NULL) { - snd_printk("unable to remap region 0x%lx-0x%lx\n", rme9652->port, rme9652->port + RME9652_IO_EXTENT - 1); + snd_printk(KERN_ERR "unable to remap region 0x%lx-0x%lx\n", rme9652->port, rme9652->port + RME9652_IO_EXTENT - 1); return -EBUSY; } if (request_irq(pci->irq, snd_rme9652_interrupt, SA_INTERRUPT|SA_SHIRQ, "rme9652", (void *)rme9652)) { - snd_printk("unable to request IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "unable to request IRQ %d\n", pci->irq); return -EBUSY; } rme9652->irq = pci->irq; diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 4f64814dfef..9a35474aad0 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -591,7 +591,7 @@ static irqreturn_t snd_sonicvibes_interrupt(int irq, void *dev_id, struct pt_reg return IRQ_NONE; if (status == 0xff) { /* failure */ outb(sonic->irqmask = ~0, SV_REG(sonic, IRQMASK)); - snd_printk("IRQ failure - interrupts disabled!!\n"); + snd_printk(KERN_ERR "IRQ failure - interrupts disabled!!\n"); return IRQ_HANDLED; } if (sonic->pcm) { @@ -1239,7 +1239,7 @@ static int __devinit snd_sonicvibes_create(snd_card_t * card, /* check, if we can restrict PCI DMA transfers to 24 bits */ if (pci_set_dma_mask(pci, 0x00ffffff) < 0 || pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) { - snd_printk("architecture does not support 24bit PCI busmaster DMA\n"); + snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; } @@ -1267,7 +1267,7 @@ static int __devinit snd_sonicvibes_create(snd_card_t * card, sonic->game_port = pci_resource_start(pci, 4); if (request_irq(pci->irq, snd_sonicvibes_interrupt, SA_INTERRUPT|SA_SHIRQ, "S3 SonicVibes", (void *)sonic)) { - snd_printk("unable to grab IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_sonicvibes_free(sonic); return -EBUSY; } @@ -1281,24 +1281,24 @@ static int __devinit snd_sonicvibes_create(snd_card_t * card, if (!dmaa) { dmaa = dmaio; dmaio += 0x10; - snd_printk("BIOS did not allocate DDMA channel A i/o, allocated at 0x%x\n", dmaa); + snd_printk(KERN_INFO "BIOS did not allocate DDMA channel A i/o, allocated at 0x%x\n", dmaa); } if (!dmac) { dmac = dmaio; dmaio += 0x10; - snd_printk("BIOS did not allocate DDMA channel C i/o, allocated at 0x%x\n", dmac); + snd_printk(KERN_INFO "BIOS did not allocate DDMA channel C i/o, allocated at 0x%x\n", dmac); } pci_write_config_dword(pci, 0x40, dmaa); pci_write_config_dword(pci, 0x48, dmac); if ((sonic->res_dmaa = request_region(dmaa, 0x10, "S3 SonicVibes DDMA-A")) == NULL) { snd_sonicvibes_free(sonic); - snd_printk("unable to grab DDMA-A port at 0x%x-0x%x\n", dmaa, dmaa + 0x10 - 1); + snd_printk(KERN_ERR "unable to grab DDMA-A port at 0x%x-0x%x\n", dmaa, dmaa + 0x10 - 1); return -EBUSY; } if ((sonic->res_dmac = request_region(dmac, 0x10, "S3 SonicVibes DDMA-C")) == NULL) { snd_sonicvibes_free(sonic); - snd_printk("unable to grab DDMA-C port at 0x%x-0x%x\n", dmac, dmac + 0x10 - 1); + snd_printk(KERN_ERR "unable to grab DDMA-C port at 0x%x-0x%x\n", dmac, dmac + 0x10 - 1); return -EBUSY; } diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index dda62955b4f..08226f523eb 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -153,7 +153,7 @@ static unsigned short snd_trident_codec_read(ac97_t *ac97, unsigned short reg) } if (count == 0 && !trident->ac97_detect) { - snd_printk("ac97 codec read TIMEOUT [0x%x/0x%x]!!!\n", reg, data); + snd_printk(KERN_ERR "ac97 codec read TIMEOUT [0x%x/0x%x]!!!\n", reg, data); data = 0; } @@ -2990,13 +2990,13 @@ static int __devinit snd_trident_mixer(trident_t * trident, int pcm_spdif_device _ac97.num = 1; err = snd_ac97_mixer(trident->ac97_bus, &_ac97, &trident->ac97_sec); if (err < 0) - snd_printk("SI7018: the secondary codec - invalid access\n"); + snd_printk(KERN_ERR "SI7018: the secondary codec - invalid access\n"); #if 0 // only for my testing purpose --jk { ac97_t *mc97; err = snd_ac97_modem(trident->card, &_ac97, &mc97); if (err < 0) - snd_printk("snd_ac97_modem returned error %i\n", err); + snd_printk(KERN_ERR "snd_ac97_modem returned error %i\n", err); } #endif } @@ -3244,7 +3244,7 @@ static int snd_trident_sis_reset(trident_t *trident) goto __si7018_ok; do_delay(trident); } while (time_after_eq(end_time, jiffies)); - snd_printk("AC'97 codec ready error [0x%x]\n", inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL))); + snd_printk(KERN_ERR "AC'97 codec ready error [0x%x]\n", inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL))); if (r-- > 0) { end_time = jiffies + HZ; do { @@ -3542,7 +3542,7 @@ int __devinit snd_trident_create(snd_card_t * card, /* check, if we can restrict PCI DMA transfers to 30 bits */ if (pci_set_dma_mask(pci, 0x3fffffff) < 0 || pci_set_consistent_dma_mask(pci, 0x3fffffff) < 0) { - snd_printk("architecture does not support 30bit PCI busmaster DMA\n"); + snd_printk(KERN_ERR "architecture does not support 30bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; } @@ -3579,7 +3579,7 @@ int __devinit snd_trident_create(snd_card_t * card, trident->port = pci_resource_start(pci, 0); if (request_irq(pci->irq, snd_trident_interrupt, SA_INTERRUPT|SA_SHIRQ, "Trident Audio", (void *) trident)) { - snd_printk("unable to grab IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_trident_free(trident); return -EBUSY; } diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c index 333d3790692..f3e6c546af7 100644 --- a/sound/pci/trident/trident_memory.c +++ b/sound/pci/trident/trident_memory.c @@ -170,11 +170,11 @@ __found_pages: static int is_valid_page(unsigned long ptr) { if (ptr & ~0x3fffffffUL) { - snd_printk("max memory size is 1GB!!\n"); + snd_printk(KERN_ERR "max memory size is 1GB!!\n"); return 0; } if (ptr & (SNDRV_TRIDENT_PAGE_SIZE-1)) { - snd_printk("page is not aligned\n"); + snd_printk(KERN_ERR "page is not aligned\n"); return 0; } return 1; diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 3fdb3b1d4e8..9b2bea866d1 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -865,7 +865,7 @@ static snd_pcm_uframes_t snd_via8233_pcm_pointer(snd_pcm_substream_t *substream) idx = count >> 24; if (idx >= viadev->tbl_entries) { #ifdef POINTER_DEBUG - printk("fail: invalid idx = %i/%i\n", idx, viadev->tbl_entries); + printk(KERN_DEBUG "fail: invalid idx = %i/%i\n", idx, viadev->tbl_entries); #endif res = viadev->lastpos; } else { @@ -2032,7 +2032,7 @@ static int snd_via82xx_chip_init(via82xx_t *chip) } while (time_before(jiffies, end_time)); if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) - snd_printk("AC'97 codec is not ready [0x%x]\n", val); + snd_printk(KERN_ERR "AC'97 codec is not ready [0x%x]\n", val); #if 0 /* FIXME: we don't support the second codec yet so skip the detection now.. */ snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | @@ -2228,7 +2228,7 @@ static int __devinit snd_via82xx_create(snd_card_t * card, snd_via8233_interrupt : snd_via686_interrupt, SA_INTERRUPT|SA_SHIRQ, card->driver, (void *)chip)) { - snd_printk("unable to grab IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_via82xx_free(chip); return -EBUSY; } diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index ff56eb8552e..bc7330ace96 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -570,7 +570,7 @@ static inline unsigned int calc_linear_pos(viadev_t *viadev, unsigned int idx, u res = viadev->lastpos; } else if (check_invalid_pos(viadev, res)) { #ifdef POINTER_DEBUG - printk("fail: idx = %i/%i, lastpos = 0x%x, bufsize2 = 0x%x, offsize = 0x%x, size = 0x%x, count = 0x%x\n", idx, viadev->tbl_entries, viadev->lastpos, viadev->bufsize2, viadev->idx_table[idx].offset, viadev->idx_table[idx].size, count); + printk(KERN_DEBUG "fail: idx = %i/%i, lastpos = 0x%x, bufsize2 = 0x%x, offsize = 0x%x, size = 0x%x, count = 0x%x\n", idx, viadev->tbl_entries, viadev->lastpos, viadev->bufsize2, viadev->idx_table[idx].offset, viadev->idx_table[idx].size, count); #endif if (count && size < count) { snd_printd(KERN_ERR "invalid via82xx_cur_ptr, using last valid pointer\n"); @@ -973,7 +973,7 @@ static int snd_via82xx_chip_init(via82xx_t *chip) } while (time_before(jiffies, end_time)); if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) - snd_printk("AC'97 codec is not ready [0x%x]\n", val); + snd_printk(KERN_ERR "AC'97 codec is not ready [0x%x]\n", val); snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | VIA_REG_AC97_SECONDARY_VALID | @@ -1102,7 +1102,7 @@ static int __devinit snd_via82xx_create(snd_card_t * card, chip->port = pci_resource_start(pci, 0); if (request_irq(pci->irq, snd_via82xx_interrupt, SA_INTERRUPT|SA_SHIRQ, card->driver, (void *)chip)) { - snd_printk("unable to grab IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_via82xx_free(chip); return -EBUSY; } diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index e50d744ae70..1bbba32517f 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c @@ -320,7 +320,7 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci, pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl); } else if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { snd_card_free(card); - snd_printk("cannot create opl3 hwdep\n"); + snd_printk(KERN_ERR "cannot create opl3 hwdep\n"); return err; } } diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index d27f3b56b51..a53117733d5 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -94,7 +94,7 @@ static int snd_ymfpci_codec_ready(ymfpci_t *chip, int secondary) set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); } while (time_before(jiffies, end_time)); - snd_printk("codec_ready: codec %i is not ready [0x%x]\n", secondary, snd_ymfpci_readw(chip, reg)); + snd_printk(KERN_ERR "codec_ready: codec %i is not ready [0x%x]\n", secondary, snd_ymfpci_readw(chip, reg)); return -EBUSY; } @@ -2288,12 +2288,12 @@ int __devinit snd_ymfpci_create(snd_card_t * card, pci_set_master(pci); if ((chip->res_reg_area = request_mem_region(chip->reg_area_phys, 0x8000, "YMFPCI")) == NULL) { - snd_printk("unable to grab memory region 0x%lx-0x%lx\n", chip->reg_area_phys, chip->reg_area_phys + 0x8000 - 1); + snd_printk(KERN_ERR "unable to grab memory region 0x%lx-0x%lx\n", chip->reg_area_phys, chip->reg_area_phys + 0x8000 - 1); snd_ymfpci_free(chip); return -EBUSY; } if (request_irq(pci->irq, snd_ymfpci_interrupt, SA_INTERRUPT|SA_SHIRQ, "YMFPCI", (void *) chip)) { - snd_printk("unable to grab IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_ymfpci_free(chip); return -EBUSY; } -- cgit v1.2.3 From b0b9811956db489ca43596c37ef2f38582454e51 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 20 Oct 2005 18:29:58 +0200 Subject: [ALSA] hdsp - Code clean up Modules: RME HDSP driver - Add missing KERN_* suffix to printk. - Clean up parentheses. - clean up the firmware check code. Signed-off-by: Takashi Iwai --- sound/pci/rme9652/hdsp.c | 588 +++++++++++++++++------------------------------ 1 file changed, 217 insertions(+), 371 deletions(-) diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 52525eb198c..845158b01b0 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -671,11 +671,7 @@ static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) { } } - if ((1000 / HZ) < 3000) { - ssleep(3); - } else { - mdelay(3000); - } + ssleep(3); if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) { snd_printk ("Hammerfall-DSP: timeout at end of firmware loading\n"); @@ -692,7 +688,7 @@ static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) { } if (hdsp->state & HDSP_InitializationComplete) { - snd_printk("Hammerfall-DSP: firmware loaded from cache, restoring defaults\n"); + snd_printk(KERN_INFO "Hammerfall-DSP: firmware loaded from cache, restoring defaults\n"); spin_lock_irqsave(&hdsp->lock, flags); snd_hdsp_set_defaults(hdsp); spin_unlock_irqrestore(&hdsp->lock, flags); @@ -709,9 +705,8 @@ static int hdsp_get_iobox_version (hdsp_t *hdsp) hdsp_write (hdsp, HDSP_control2Reg, HDSP_PROGRAM); hdsp_write (hdsp, HDSP_fifoData, 0); - if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT) < 0) { + if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT) < 0) return -EIO; - } hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD); hdsp_write (hdsp, HDSP_fifoData, 0); @@ -726,22 +721,30 @@ static int hdsp_get_iobox_version (hdsp_t *hdsp) } } else { /* firmware was already loaded, get iobox type */ - if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) { + if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) hdsp->io_type = Multiface; - } else { + else hdsp->io_type = Digiface; - } } return 0; } -static int hdsp_check_for_firmware (hdsp_t *hdsp) +static int hdsp_check_for_firmware (hdsp_t *hdsp, int show_err) { if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0; if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { - snd_printk("Hammerfall-DSP: firmware not present.\n"); + snd_printk(KERN_ERR "Hammerfall-DSP: firmware not present.\n"); hdsp->state &= ~HDSP_FirmwareLoaded; + if (! show_err) + return -EIO; + /* try to load firmware */ + if (hdsp->state & HDSP_FirmwareCached) { + if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) + snd_printk(KERN_ERR "Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); + } else { + snd_printk(KERN_ERR "Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); + } return -EIO; } return 0; @@ -775,9 +778,9 @@ static int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout) static int hdsp_read_gain (hdsp_t *hdsp, unsigned int addr) { - if (addr >= HDSP_MATRIX_MIXER_SIZE) { + if (addr >= HDSP_MATRIX_MIXER_SIZE) return 0; - } + return hdsp->mixer_matrix[addr]; } @@ -802,13 +805,11 @@ static int hdsp_write_gain(hdsp_t *hdsp, unsigned int addr, unsigned short data) memory." */ - if (hdsp->io_type == H9632 && addr >= 512) { + if (hdsp->io_type == H9632 && addr >= 512) return 0; - } - if (hdsp->io_type == H9652 && addr >= 1352) { + if (hdsp->io_type == H9652 && addr >= 1352) return 0; - } hdsp->mixer_matrix[addr] = data; @@ -832,9 +833,8 @@ static int hdsp_write_gain(hdsp_t *hdsp, unsigned int addr, unsigned short data) ad = (addr << 16) + data; - if (hdsp_fifo_wait(hdsp, 127, HDSP_LONG_WAIT)) { + if (hdsp_fifo_wait(hdsp, 127, HDSP_LONG_WAIT)) return -1; - } hdsp_write (hdsp, HDSP_fifoData, ad); hdsp->mixer_matrix[addr] = data; @@ -851,9 +851,8 @@ static int snd_hdsp_use_is_exclusive(hdsp_t *hdsp) spin_lock_irqsave(&hdsp->lock, flags); if ((hdsp->playback_pid != hdsp->capture_pid) && - (hdsp->playback_pid >= 0) && (hdsp->capture_pid >= 0)) { + (hdsp->playback_pid >= 0) && (hdsp->capture_pid >= 0)) ret = 0; - } spin_unlock_irqrestore(&hdsp->lock, flags); return ret; } @@ -880,9 +879,8 @@ static int hdsp_spdif_sample_rate(hdsp_t *hdsp) unsigned int status = hdsp_read(hdsp, HDSP_statusRegister); unsigned int rate_bits = (status & HDSP_spdifFrequencyMask); - if (status & HDSP_SPDIFErrorFlag) { + if (status & HDSP_SPDIFErrorFlag) return 0; - } switch (rate_bits) { case HDSP_spdifFrequency32KHz: return 32000; @@ -918,9 +916,8 @@ static snd_pcm_uframes_t hdsp_hw_pointer(hdsp_t *hdsp) position = hdsp_read(hdsp, HDSP_statusRegister); - if (!hdsp->precise_ptr) { + if (!hdsp->precise_ptr) return (position & HDSP_BufferID) ? (hdsp->period_bytes / 4) : 0; - } position &= HDSP_BufferPositionMask; position /= 4; @@ -989,19 +986,19 @@ static int hdsp_set_rate(hdsp_t *hdsp, int rate, int called_internally) if (!(hdsp->control_register & HDSP_ClockModeMaster)) { if (called_internally) { /* request from ctl or card initialization */ - snd_printk("Hammerfall-DSP: device is not running as a clock master: cannot set sample rate.\n"); + snd_printk(KERN_ERR "Hammerfall-DSP: device is not running as a clock master: cannot set sample rate.\n"); return -1; } else { /* hw_param request while in AutoSync mode */ int external_freq = hdsp_external_sample_rate(hdsp); int spdif_freq = hdsp_spdif_sample_rate(hdsp); - if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) { - snd_printk("Hammerfall-DSP: Detected ADAT in double speed mode\n"); - } else if (hdsp->io_type == H9632 && (spdif_freq == external_freq*4) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) { - snd_printk("Hammerfall-DSP: Detected ADAT in quad speed mode\n"); - } else if (rate != external_freq) { - snd_printk("Hammerfall-DSP: No AutoSync source for requested rate\n"); + if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) + snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in double speed mode\n"); + else if (hdsp->io_type == H9632 && (spdif_freq == external_freq*4) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) + snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in quad speed mode\n"); + else if (rate != external_freq) { + snd_printk(KERN_INFO "Hammerfall-DSP: No AutoSync source for requested rate\n"); return -1; } } @@ -1019,63 +1016,53 @@ static int hdsp_set_rate(hdsp_t *hdsp, int rate, int called_internally) exists for externally-driven rate changes. All we can do is to flag rate changes in the read/write routines. */ - if (rate > 96000 && hdsp->io_type != H9632) { + if (rate > 96000 && hdsp->io_type != H9632) return -EINVAL; - } switch (rate) { case 32000: - if (current_rate > 48000) { + if (current_rate > 48000) reject_if_open = 1; - } rate_bits = HDSP_Frequency32KHz; break; case 44100: - if (current_rate > 48000) { + if (current_rate > 48000) reject_if_open = 1; - } rate_bits = HDSP_Frequency44_1KHz; break; case 48000: - if (current_rate > 48000) { + if (current_rate > 48000) reject_if_open = 1; - } rate_bits = HDSP_Frequency48KHz; break; case 64000: - if (current_rate <= 48000 || current_rate > 96000) { + if (current_rate <= 48000 || current_rate > 96000) reject_if_open = 1; - } rate_bits = HDSP_Frequency64KHz; break; case 88200: - if (current_rate <= 48000 || current_rate > 96000) { + if (current_rate <= 48000 || current_rate > 96000) reject_if_open = 1; - } rate_bits = HDSP_Frequency88_2KHz; break; case 96000: - if (current_rate <= 48000 || current_rate > 96000) { + if (current_rate <= 48000 || current_rate > 96000) reject_if_open = 1; - } rate_bits = HDSP_Frequency96KHz; break; case 128000: - if (current_rate < 128000) { + if (current_rate < 128000) reject_if_open = 1; - } rate_bits = HDSP_Frequency128KHz; break; case 176400: - if (current_rate < 128000) { + if (current_rate < 128000) reject_if_open = 1; - } rate_bits = HDSP_Frequency176_4KHz; break; case 192000: - if (current_rate < 128000) { + if (current_rate < 128000) reject_if_open = 1; - } rate_bits = HDSP_Frequency192KHz; break; default: @@ -1096,11 +1083,10 @@ static int hdsp_set_rate(hdsp_t *hdsp, int rate, int called_internally) if (rate >= 128000) { hdsp->channel_map = channel_map_H9632_qs; } else if (rate > 48000) { - if (hdsp->io_type == H9632) { + if (hdsp->io_type == H9632) hdsp->channel_map = channel_map_H9632_ds; - } else { + else hdsp->channel_map = channel_map_ds; - } } else { switch (hdsp->io_type) { case Multiface: @@ -1131,54 +1117,48 @@ static int hdsp_set_rate(hdsp_t *hdsp, int rate, int called_internally) static unsigned char snd_hdsp_midi_read_byte (hdsp_t *hdsp, int id) { /* the hardware already does the relevant bit-mask with 0xff */ - if (id) { + if (id) return hdsp_read(hdsp, HDSP_midiDataIn1); - } else { + else return hdsp_read(hdsp, HDSP_midiDataIn0); - } } static void snd_hdsp_midi_write_byte (hdsp_t *hdsp, int id, int val) { /* the hardware already does the relevant bit-mask with 0xff */ - if (id) { + if (id) hdsp_write(hdsp, HDSP_midiDataOut1, val); - } else { + else hdsp_write(hdsp, HDSP_midiDataOut0, val); - } } static int snd_hdsp_midi_input_available (hdsp_t *hdsp, int id) { - if (id) { + if (id) return (hdsp_read(hdsp, HDSP_midiStatusIn1) & 0xff); - } else { + else return (hdsp_read(hdsp, HDSP_midiStatusIn0) & 0xff); - } } static int snd_hdsp_midi_output_possible (hdsp_t *hdsp, int id) { int fifo_bytes_used; - if (id) { + if (id) fifo_bytes_used = hdsp_read(hdsp, HDSP_midiStatusOut1) & 0xff; - } else { + else fifo_bytes_used = hdsp_read(hdsp, HDSP_midiStatusOut0) & 0xff; - } - if (fifo_bytes_used < 128) { + if (fifo_bytes_used < 128) return 128 - fifo_bytes_used; - } else { + else return 0; - } } static void snd_hdsp_flush_midi_input (hdsp_t *hdsp, int id) { - while (snd_hdsp_midi_input_available (hdsp, id)) { + while (snd_hdsp_midi_input_available (hdsp, id)) snd_hdsp_midi_read_byte (hdsp, id); - } } static int snd_hdsp_midi_output_write (hdsp_midi_t *hmidi) @@ -1219,28 +1199,23 @@ static int snd_hdsp_midi_input_read (hdsp_midi_t *hmidi) spin_lock_irqsave (&hmidi->lock, flags); if ((n_pending = snd_hdsp_midi_input_available (hmidi->hdsp, hmidi->id)) > 0) { if (hmidi->input) { - if (n_pending > (int)sizeof (buf)) { + if (n_pending > (int)sizeof (buf)) n_pending = sizeof (buf); - } - for (i = 0; i < n_pending; ++i) { + for (i = 0; i < n_pending; ++i) buf[i] = snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id); - } - if (n_pending) { + if (n_pending) snd_rawmidi_receive (hmidi->input, buf, n_pending); - } } else { /* flush the MIDI input FIFO */ - while (--n_pending) { + while (--n_pending) snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id); - } } } hmidi->pending = 0; - if (hmidi->id) { + if (hmidi->id) hmidi->hdsp->control_register |= HDSP_Midi1InterruptEnable; - } else { + else hmidi->hdsp->control_register |= HDSP_Midi0InterruptEnable; - } hdsp_write(hmidi->hdsp, HDSP_controlRegister, hmidi->hdsp->control_register); spin_unlock_irqrestore (&hmidi->lock, flags); return snd_hdsp_midi_output_write (hmidi); @@ -1310,9 +1285,8 @@ static void snd_hdsp_midi_output_trigger(snd_rawmidi_substream_t * substream, in hmidi->istimer++; } } else { - if (hmidi->istimer && --hmidi->istimer <= 0) { + if (hmidi->istimer && --hmidi->istimer <= 0) del_timer (&hmidi->timer); - } } spin_unlock_irqrestore (&hmidi->lock, flags); if (up) @@ -1400,9 +1374,8 @@ static int __devinit snd_hdsp_create_midi (snd_card_t *card, hdsp_t *hdsp, int i spin_lock_init (&hdsp->midi[id].lock); sprintf (buf, "%s MIDI %d", card->shortname, id+1); - if (snd_rawmidi_new (card, buf, id, 1, 1, &hdsp->midi[id].rmidi) < 0) { + if (snd_rawmidi_new (card, buf, id, 1, 1, &hdsp->midi[id].rmidi) < 0) return -1; - } sprintf (hdsp->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1); hdsp->midi[id].rmidi->private_data = &hdsp->midi[id]; @@ -1588,11 +1561,10 @@ static int hdsp_spdif_out(hdsp_t *hdsp) static int hdsp_set_spdif_output(hdsp_t *hdsp, int out) { - if (out) { + if (out) hdsp->control_register |= HDSP_SPDIFOpticalOut; - } else { + else hdsp->control_register &= ~HDSP_SPDIFOpticalOut; - } hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); return 0; } @@ -1642,11 +1614,10 @@ static int hdsp_spdif_professional(hdsp_t *hdsp) static int hdsp_set_spdif_professional(hdsp_t *hdsp, int val) { - if (val) { + if (val) hdsp->control_register |= HDSP_SPDIFProfessional; - } else { + else hdsp->control_register &= ~HDSP_SPDIFProfessional; - } hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); return 0; } @@ -1687,11 +1658,10 @@ static int hdsp_spdif_emphasis(hdsp_t *hdsp) static int hdsp_set_spdif_emphasis(hdsp_t *hdsp, int val) { - if (val) { + if (val) hdsp->control_register |= HDSP_SPDIFEmphasis; - } else { + else hdsp->control_register &= ~HDSP_SPDIFEmphasis; - } hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); return 0; } @@ -1732,11 +1702,10 @@ static int hdsp_spdif_nonaudio(hdsp_t *hdsp) static int hdsp_set_spdif_nonaudio(hdsp_t *hdsp, int val) { - if (val) { + if (val) hdsp->control_register |= HDSP_SPDIFNonAudio; - } else { + else hdsp->control_register &= ~HDSP_SPDIFNonAudio; - } hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); return 0; } @@ -1921,11 +1890,10 @@ static int snd_hdsp_get_autosync_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_ static int hdsp_system_clock_mode(hdsp_t *hdsp) { - if (hdsp->control_register & HDSP_ClockModeMaster) { + if (hdsp->control_register & HDSP_ClockModeMaster) return 0; - } else if (hdsp_external_sample_rate(hdsp) != hdsp->system_sample_rate) { + else if (hdsp_external_sample_rate(hdsp) != hdsp->system_sample_rate) return 0; - } return 1; } @@ -2074,16 +2042,17 @@ static int snd_hdsp_put_clock_source(snd_kcontrol_t * kcontrol, snd_ctl_elem_val val = ucontrol->value.enumerated.item[0]; if (val < 0) val = 0; if (hdsp->io_type == H9632) { - if (val > 9) val = 9; + if (val > 9) + val = 9; } else { - if (val > 6) val = 6; + if (val > 6) + val = 6; } spin_lock_irq(&hdsp->lock); - if (val != hdsp_clock_source(hdsp)) { + if (val != hdsp_clock_source(hdsp)) change = (hdsp_set_clock_source(hdsp, val) == 0) ? 1 : 0; - } else { + else change = 0; - } spin_unlock_irq(&hdsp->lock); return change; } @@ -2193,11 +2162,10 @@ static int snd_hdsp_put_da_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t if (val < 0) val = 0; if (val > 2) val = 2; spin_lock_irq(&hdsp->lock); - if (val != hdsp_da_gain(hdsp)) { + if (val != hdsp_da_gain(hdsp)) change = (hdsp_set_da_gain(hdsp, val) == 0) ? 1 : 0; - } else { + else change = 0; - } spin_unlock_irq(&hdsp->lock); return change; } @@ -2279,11 +2247,10 @@ static int snd_hdsp_put_ad_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t if (val < 0) val = 0; if (val > 2) val = 2; spin_lock_irq(&hdsp->lock); - if (val != hdsp_ad_gain(hdsp)) { + if (val != hdsp_ad_gain(hdsp)) change = (hdsp_set_ad_gain(hdsp, val) == 0) ? 1 : 0; - } else { + else change = 0; - } spin_unlock_irq(&hdsp->lock); return change; } @@ -2365,11 +2332,10 @@ static int snd_hdsp_put_phone_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value if (val < 0) val = 0; if (val > 2) val = 2; spin_lock_irq(&hdsp->lock); - if (val != hdsp_phone_gain(hdsp)) { + if (val != hdsp_phone_gain(hdsp)) change = (hdsp_set_phone_gain(hdsp, val) == 0) ? 1 : 0; - } else { + else change = 0; - } spin_unlock_irq(&hdsp->lock); return change; } @@ -2385,19 +2351,17 @@ static int snd_hdsp_put_phone_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value static int hdsp_xlr_breakout_cable(hdsp_t *hdsp) { - if (hdsp->control_register & HDSP_XLRBreakoutCable) { + if (hdsp->control_register & HDSP_XLRBreakoutCable) return 1; - } return 0; } static int hdsp_set_xlr_breakout_cable(hdsp_t *hdsp, int mode) { - if (mode) { + if (mode) hdsp->control_register |= HDSP_XLRBreakoutCable; - } else { + else hdsp->control_register &= ~HDSP_XLRBreakoutCable; - } hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); return 0; } @@ -2450,19 +2414,17 @@ static int snd_hdsp_put_xlr_breakout_cable(snd_kcontrol_t * kcontrol, snd_ctl_el static int hdsp_aeb(hdsp_t *hdsp) { - if (hdsp->control_register & HDSP_AnalogExtensionBoard) { + if (hdsp->control_register & HDSP_AnalogExtensionBoard) return 1; - } return 0; } static int hdsp_set_aeb(hdsp_t *hdsp, int mode) { - if (mode) { + if (mode) hdsp->control_register |= HDSP_AnalogExtensionBoard; - } else { + else hdsp->control_register &= ~HDSP_AnalogExtensionBoard; - } hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); return 0; } @@ -2705,11 +2667,10 @@ static int hdsp_line_out(hdsp_t *hdsp) static int hdsp_set_line_output(hdsp_t *hdsp, int out) { - if (out) { + if (out) hdsp->control_register |= HDSP_LineOut; - } else { + else hdsp->control_register &= ~HDSP_LineOut; - } hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); return 0; } @@ -2760,11 +2721,10 @@ static int snd_hdsp_put_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t static int hdsp_set_precise_pointer(hdsp_t *hdsp, int precise) { - if (precise) { + if (precise) hdsp->precise_ptr = 1; - } else { + else hdsp->precise_ptr = 0; - } return 0; } @@ -2814,11 +2774,10 @@ static int snd_hdsp_put_precise_pointer(snd_kcontrol_t * kcontrol, snd_ctl_elem_ static int hdsp_set_use_midi_tasklet(hdsp_t *hdsp, int use_tasklet) { - if (use_tasklet) { + if (use_tasklet) hdsp->use_midi_tasklet = 1; - } else { + else hdsp->use_midi_tasklet = 0; - } return 0; } @@ -2889,11 +2848,10 @@ static int snd_hdsp_get_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * source = ucontrol->value.integer.value[0]; destination = ucontrol->value.integer.value[1]; - if (source >= hdsp->max_channels) { + if (source >= hdsp->max_channels) addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels,destination); - } else { + else addr = hdsp_input_to_output_key(hdsp,source, destination); - } spin_lock_irq(&hdsp->lock); ucontrol->value.integer.value[2] = hdsp_read_gain (hdsp, addr); @@ -2916,11 +2874,10 @@ static int snd_hdsp_put_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * source = ucontrol->value.integer.value[0]; destination = ucontrol->value.integer.value[1]; - if (source >= hdsp->max_channels) { + if (source >= hdsp->max_channels) addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels, destination); - } else { + else addr = hdsp_input_to_output_key(hdsp,source, destination); - } gain = ucontrol->value.integer.value[2]; @@ -2957,14 +2914,12 @@ static int hdsp_wc_sync_check(hdsp_t *hdsp) { int status2 = hdsp_read(hdsp, HDSP_status2Register); if (status2 & HDSP_wc_lock) { - if (status2 & HDSP_wc_sync) { + if (status2 & HDSP_wc_sync) return 2; - } else { + else return 1; - } - } else { + } else return 0; - } return 0; } @@ -2988,14 +2943,13 @@ static int snd_hdsp_get_wc_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_va static int hdsp_spdif_sync_check(hdsp_t *hdsp) { int status = hdsp_read(hdsp, HDSP_statusRegister); - if (status & HDSP_SPDIFErrorFlag) { + if (status & HDSP_SPDIFErrorFlag) return 0; - } else { - if (status & HDSP_SPDIFSync) { + else { + if (status & HDSP_SPDIFSync) return 2; - } else { + else return 1; - } } return 0; } @@ -3021,14 +2975,12 @@ static int hdsp_adatsync_sync_check(hdsp_t *hdsp) { int status = hdsp_read(hdsp, HDSP_statusRegister); if (status & HDSP_TimecodeLock) { - if (status & HDSP_TimecodeSync) { + if (status & HDSP_TimecodeSync) return 2; - } else { + else return 1; - } - } else { + } else return 0; - } } static int snd_hdsp_get_adatsync_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) @@ -3051,14 +3003,12 @@ static int hdsp_adat_sync_check(hdsp_t *hdsp, int idx) int status = hdsp_read(hdsp, HDSP_statusRegister); if (status & (HDSP_Lock0>>idx)) { - if (status & (HDSP_Sync0>>idx)) { + if (status & (HDSP_Sync0>>idx)) return 2; - } else { + else return 1; - } - } else { + } else return 0; - } } static int snd_hdsp_get_adat_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) @@ -3171,9 +3121,8 @@ static int snd_hdsp_create_controls(snd_card_t *card, hdsp_t *hdsp) snd_kcontrol_t *kctl; for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_controls); idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_controls[idx], hdsp))) < 0) { + if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_controls[idx], hdsp))) < 0) return err; - } if (idx == 1) /* IEC958 (S/PDIF) Stream */ hdsp->spdif_ctl = kctl; } @@ -3181,32 +3130,28 @@ static int snd_hdsp_create_controls(snd_card_t *card, hdsp_t *hdsp) /* ADAT SyncCheck status */ snd_hdsp_adat_sync_check.name = "ADAT Lock Status"; snd_hdsp_adat_sync_check.index = 1; - if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp)))) { + if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp)))) return err; - } if (hdsp->io_type == Digiface || hdsp->io_type == H9652) { for (idx = 1; idx < 3; ++idx) { snd_hdsp_adat_sync_check.index = idx+1; - if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp)))) { + if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp)))) return err; - } } } /* DA, AD and Phone gain and XLR breakout cable controls for H9632 cards */ if (hdsp->io_type == H9632) { for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_9632_controls); idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_9632_controls[idx], hdsp))) < 0) { + if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_9632_controls[idx], hdsp))) < 0) return err; - } } } /* AEB control for H96xx card */ if (hdsp->io_type == H9632 || hdsp->io_type == H9652) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_96xx_aeb, hdsp))) < 0) { + if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_96xx_aeb, hdsp))) < 0) return err; - } } return 0; @@ -3228,12 +3173,11 @@ snd_hdsp_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer) char *clock_source; int x; - if (hdsp_check_for_iobox (hdsp)) { + if (hdsp_check_for_iobox (hdsp)) snd_iprintf(buffer, "No I/O box connected.\nPlease connect one and upload firmware.\n"); return; - } - if (hdsp_check_for_firmware(hdsp)) { + if (hdsp_check_for_firmware(hdsp, 0)) { if (hdsp->state & HDSP_FirmwareCached) { if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { snd_iprintf(buffer, "Firmware loading from cache failed, please upload manually.\n"); @@ -3314,11 +3258,10 @@ snd_hdsp_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer) } snd_iprintf (buffer, "Sample Clock Source: %s\n", clock_source); - if (hdsp_system_clock_mode(hdsp)) { + if (hdsp_system_clock_mode(hdsp)) system_clock_mode = "Slave"; - } else { + else system_clock_mode = "Master"; - } switch (hdsp_pref_sync_ref (hdsp)) { case HDSP_SYNC_FROM_WORD: @@ -3400,85 +3343,75 @@ snd_hdsp_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer) break; } - if (hdsp->control_register & HDSP_SPDIFOpticalOut) { + if (hdsp->control_register & HDSP_SPDIFOpticalOut) snd_iprintf(buffer, "IEC958 output: Coaxial & ADAT1\n"); - } else { + else snd_iprintf(buffer, "IEC958 output: Coaxial only\n"); - } - if (hdsp->control_register & HDSP_SPDIFProfessional) { + if (hdsp->control_register & HDSP_SPDIFProfessional) snd_iprintf(buffer, "IEC958 quality: Professional\n"); - } else { + else snd_iprintf(buffer, "IEC958 quality: Consumer\n"); - } - if (hdsp->control_register & HDSP_SPDIFEmphasis) { + if (hdsp->control_register & HDSP_SPDIFEmphasis) snd_iprintf(buffer, "IEC958 emphasis: on\n"); - } else { + else snd_iprintf(buffer, "IEC958 emphasis: off\n"); - } - if (hdsp->control_register & HDSP_SPDIFNonAudio) { + if (hdsp->control_register & HDSP_SPDIFNonAudio) snd_iprintf(buffer, "IEC958 NonAudio: on\n"); - } else { + else snd_iprintf(buffer, "IEC958 NonAudio: off\n"); - } - if ((x = hdsp_spdif_sample_rate (hdsp)) != 0) { + if ((x = hdsp_spdif_sample_rate (hdsp)) != 0) snd_iprintf (buffer, "IEC958 sample rate: %d\n", x); - } else { + else snd_iprintf (buffer, "IEC958 sample rate: Error flag set\n"); - } snd_iprintf(buffer, "\n"); /* Sync Check */ x = status & HDSP_Sync0; - if (status & HDSP_Lock0) { + if (status & HDSP_Lock0) snd_iprintf(buffer, "ADAT1: %s\n", x ? "Sync" : "Lock"); - } else { + else snd_iprintf(buffer, "ADAT1: No Lock\n"); - } switch (hdsp->io_type) { case Digiface: case H9652: x = status & HDSP_Sync1; - if (status & HDSP_Lock1) { + if (status & HDSP_Lock1) snd_iprintf(buffer, "ADAT2: %s\n", x ? "Sync" : "Lock"); - } else { + else snd_iprintf(buffer, "ADAT2: No Lock\n"); - } x = status & HDSP_Sync2; - if (status & HDSP_Lock2) { + if (status & HDSP_Lock2) snd_iprintf(buffer, "ADAT3: %s\n", x ? "Sync" : "Lock"); - } else { + else snd_iprintf(buffer, "ADAT3: No Lock\n"); - } + break; default: /* relax */ break; } x = status & HDSP_SPDIFSync; - if (status & HDSP_SPDIFErrorFlag) { + if (status & HDSP_SPDIFErrorFlag) snd_iprintf (buffer, "SPDIF: No Lock\n"); - } else { + else snd_iprintf (buffer, "SPDIF: %s\n", x ? "Sync" : "Lock"); - } x = status2 & HDSP_wc_sync; - if (status2 & HDSP_wc_lock) { + if (status2 & HDSP_wc_lock) snd_iprintf (buffer, "Word Clock: %s\n", x ? "Sync" : "Lock"); - } else { + else snd_iprintf (buffer, "Word Clock: No Lock\n"); - } x = status & HDSP_TimecodeSync; - if (status & HDSP_TimecodeLock) { + if (status & HDSP_TimecodeLock) snd_iprintf(buffer, "ADAT Sync: %s\n", x ? "Sync" : "Lock"); - } else { + else snd_iprintf(buffer, "ADAT Sync: No Lock\n"); - } snd_iprintf(buffer, "\n"); @@ -3527,11 +3460,10 @@ snd_hdsp_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer) snd_iprintf(buffer, "XLR Breakout Cable : %s\n", hdsp_xlr_breakout_cable(hdsp) ? "yes" : "no"); - if (hdsp->control_register & HDSP_AnalogExtensionBoard) { + if (hdsp->control_register & HDSP_AnalogExtensionBoard) snd_iprintf(buffer, "AEB : on (ADAT1 internal)\n"); - } else { + else snd_iprintf(buffer, "AEB : off (ADAT1 external)\n"); - } snd_iprintf(buffer, "\n"); } @@ -3610,25 +3542,22 @@ static int snd_hdsp_set_defaults(hdsp_t *hdsp) #else hdsp->control2_register = 0; #endif - if (hdsp->io_type == H9652) { + if (hdsp->io_type == H9652) snd_hdsp_9652_enable_mixer (hdsp); - } else { - hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register); - } + else + hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register); hdsp_reset_hw_pointer(hdsp); hdsp_compute_period_size(hdsp); /* silence everything */ - for (i = 0; i < HDSP_MATRIX_MIXER_SIZE; ++i) { + for (i = 0; i < HDSP_MATRIX_MIXER_SIZE; ++i) hdsp->mixer_matrix[i] = MINUS_INFINITY_GAIN; - } for (i = 0; i < ((hdsp->io_type == H9652 || hdsp->io_type == H9632) ? 1352 : HDSP_MATRIX_MIXER_SIZE); ++i) { - if (hdsp_write_gain (hdsp, i, MINUS_INFINITY_GAIN)) { + if (hdsp_write_gain (hdsp, i, MINUS_INFINITY_GAIN)) return -EIO; - } } /* H9632 specific defaults */ @@ -3649,12 +3578,10 @@ static void hdsp_midi_tasklet(unsigned long arg) { hdsp_t *hdsp = (hdsp_t *)arg; - if (hdsp->midi[0].pending) { + if (hdsp->midi[0].pending) snd_hdsp_midi_input_read (&hdsp->midi[0]); - } - if (hdsp->midi[1].pending) { + if (hdsp->midi[1].pending) snd_hdsp_midi_input_read (&hdsp->midi[1]); - } } static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id, struct pt_regs *regs) @@ -3674,9 +3601,8 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id, struct pt_regs *reg midi0 = status & HDSP_midi0IRQPending; midi1 = status & HDSP_midi1IRQPending; - if (!audio && !midi0 && !midi1) { + if (!audio && !midi0 && !midi1) return IRQ_NONE; - } hdsp_write(hdsp, HDSP_interruptConfirmation, 0); @@ -3684,13 +3610,11 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id, struct pt_regs *reg midi1status = hdsp_read (hdsp, HDSP_midiStatusIn1) & 0xff; if (audio) { - if (hdsp->capture_substream) { + if (hdsp->capture_substream) snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); - } - if (hdsp->playback_substream) { + if (hdsp->playback_substream) snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream); - } } if (midi0 && midi0status) { @@ -3735,15 +3659,13 @@ static char *hdsp_channel_buffer_location(hdsp_t *hdsp, snd_assert(channel >= 0 && channel < hdsp->max_channels, return NULL); - if ((mapped_channel = hdsp->channel_map[channel]) < 0) { + if ((mapped_channel = hdsp->channel_map[channel]) < 0) return NULL; - } - if (stream == SNDRV_PCM_STREAM_CAPTURE) { + if (stream == SNDRV_PCM_STREAM_CAPTURE) return hdsp->capture_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES); - } else { + else return hdsp->playback_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES); - } } static int snd_hdsp_playback_copy(snd_pcm_substream_t *substream, int channel, @@ -3824,20 +3746,11 @@ static int snd_hdsp_hw_params(snd_pcm_substream_t *substream, pid_t this_pid; pid_t other_pid; - if (hdsp_check_for_iobox (hdsp)) { + if (hdsp_check_for_iobox (hdsp)) return -EIO; - } - if (hdsp_check_for_firmware(hdsp)) { - if (hdsp->state & HDSP_FirmwareCached) { - if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { - snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); - } - } else { - snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); - } + if (hdsp_check_for_firmware(hdsp, 1)) return -EIO; - } spin_lock_irq(&hdsp->lock); @@ -3908,9 +3821,8 @@ static int snd_hdsp_channel_info(snd_pcm_substream_t *substream, snd_assert(info->channel < hdsp->max_channels, return -EINVAL); - if ((mapped_channel = hdsp->channel_map[info->channel]) < 0) { + if ((mapped_channel = hdsp->channel_map[info->channel]) < 0) return -EINVAL; - } info->offset = mapped_channel * HDSP_CHANNEL_BUFFER_BYTES; info->first = 0; @@ -3923,14 +3835,9 @@ static int snd_hdsp_ioctl(snd_pcm_substream_t *substream, { switch (cmd) { case SNDRV_PCM_IOCTL1_RESET: - { return snd_hdsp_reset(substream); - } case SNDRV_PCM_IOCTL1_CHANNEL_INFO: - { - snd_pcm_channel_info_t *info = arg; - return snd_hdsp_channel_info(substream, info); - } + return snd_hdsp_channel_info(substream, arg); default: break; } @@ -3944,20 +3851,11 @@ static int snd_hdsp_trigger(snd_pcm_substream_t *substream, int cmd) snd_pcm_substream_t *other; int running; - if (hdsp_check_for_iobox (hdsp)) { + if (hdsp_check_for_iobox (hdsp)) return -EIO; - } - if (hdsp_check_for_firmware(hdsp)) { - if (hdsp->state & HDSP_FirmwareCached) { - if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { - snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); - } - } else { - snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); - } + if (hdsp_check_for_firmware(hdsp, 1)) return -EIO; - } spin_lock(&hdsp->lock); running = hdsp->running; @@ -4022,20 +3920,11 @@ static int snd_hdsp_prepare(snd_pcm_substream_t *substream) hdsp_t *hdsp = snd_pcm_substream_chip(substream); int result = 0; - if (hdsp_check_for_iobox (hdsp)) { + if (hdsp_check_for_iobox (hdsp)) return -EIO; - } - if (hdsp_check_for_firmware(hdsp)) { - if (hdsp->state & HDSP_FirmwareCached) { - if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { - snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); - } - } else { - snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); - } + if (hdsp_check_for_firmware(hdsp, 1)) return -EIO; - } spin_lock_irq(&hdsp->lock); if (!hdsp->running) @@ -4285,20 +4174,11 @@ static int snd_hdsp_playback_open(snd_pcm_substream_t *substream) hdsp_t *hdsp = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; - if (hdsp_check_for_iobox (hdsp)) { + if (hdsp_check_for_iobox (hdsp)) return -EIO; - } - if (hdsp_check_for_firmware(hdsp)) { - if (hdsp->state & HDSP_FirmwareCached) { - if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { - snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); - } - } else { - snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); - } + if (hdsp_check_for_firmware(hdsp, 1)) return -EIO; - } spin_lock_irq(&hdsp->lock); @@ -4367,20 +4247,11 @@ static int snd_hdsp_capture_open(snd_pcm_substream_t *substream) hdsp_t *hdsp = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; - if (hdsp_check_for_iobox (hdsp)) { + if (hdsp_check_for_iobox (hdsp)) return -EIO; - } - if (hdsp_check_for_firmware(hdsp)) { - if (hdsp->state & HDSP_FirmwareCached) { - if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { - snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); - } - } else { - snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); - } + if (hdsp_check_for_firmware(hdsp, 1)) return -EIO; - } spin_lock_irq(&hdsp->lock); @@ -4589,19 +4460,17 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int int i; if (!(hdsp->state & HDSP_FirmwareLoaded)) { - snd_printk("Hammerfall-DSP: Firmware needs to be uploaded to the card.\n"); + snd_printk(KERN_ERR "Hammerfall-DSP: Firmware needs to be uploaded to the card.\n"); return -EINVAL; } spin_lock_irqsave(&hdsp->lock, flags); info.pref_sync_ref = (unsigned char)hdsp_pref_sync_ref(hdsp); info.wordclock_sync_check = (unsigned char)hdsp_wc_sync_check(hdsp); - if (hdsp->io_type != H9632) { + if (hdsp->io_type != H9632) info.adatsync_sync_check = (unsigned char)hdsp_adatsync_sync_check(hdsp); - } info.spdif_sync_check = (unsigned char)hdsp_spdif_sync_check(hdsp); - for (i = 0; i < ((hdsp->io_type != Multiface && hdsp->io_type != H9632) ? 3 : 1); ++i) { + for (i = 0; i < ((hdsp->io_type != Multiface && hdsp->io_type != H9632) ? 3 : 1); ++i) info.adat_sync_check[i] = (unsigned char)hdsp_adat_sync_check(hdsp, i); - } info.spdif_in = (unsigned char)hdsp_spdif_in(hdsp); info.spdif_out = (unsigned char)hdsp_spdif_out(hdsp); info.spdif_professional = (unsigned char)hdsp_spdif_professional(hdsp); @@ -4621,9 +4490,8 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int info.xlr_breakout_cable = (unsigned char)hdsp_xlr_breakout_cable(hdsp); } - if (hdsp->io_type == H9632 || hdsp->io_type == H9652) { + if (hdsp->io_type == H9632 || hdsp->io_type == H9652) info.analog_extension_board = (unsigned char)hdsp_aeb(hdsp); - } spin_unlock_irqrestore(&hdsp->lock, flags); if (copy_to_user(argp, &info, sizeof(info))) return -EFAULT; @@ -4645,15 +4513,13 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL; if (hdsp->io_type == Undefined) { - if ((err = hdsp_get_iobox_version(hdsp)) < 0) { + if ((err = hdsp_get_iobox_version(hdsp)) < 0) return err; - } } hdsp_version.io_type = hdsp->io_type; hdsp_version.firmware_rev = hdsp->firmware_rev; - if ((err = copy_to_user(argp, &hdsp_version, sizeof(hdsp_version)))) { + if ((err = copy_to_user(argp, &hdsp_version, sizeof(hdsp_version)))) return -EFAULT; - } break; } case SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE: { @@ -4668,38 +4534,33 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int if (hdsp->state & (HDSP_FirmwareCached | HDSP_FirmwareLoaded)) return -EBUSY; - snd_printk("Hammerfall-DSP: initializing firmware upload\n"); + snd_printk(KERN_INFO "Hammerfall-DSP: initializing firmware upload\n"); firmware = (hdsp_firmware_t __user *)argp; - if (get_user(firmware_data, &firmware->firmware_data)) { + if (get_user(firmware_data, &firmware->firmware_data)) return -EFAULT; - } - if (hdsp_check_for_iobox (hdsp)) { + if (hdsp_check_for_iobox (hdsp)) return -EIO; - } - if (copy_from_user(hdsp->firmware_cache, firmware_data, sizeof(hdsp->firmware_cache)) != 0) { + if (copy_from_user(hdsp->firmware_cache, firmware_data, sizeof(hdsp->firmware_cache)) != 0) return -EFAULT; - } hdsp->state |= HDSP_FirmwareCached; - if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0) { + if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0) return err; - } if (!(hdsp->state & HDSP_InitializationComplete)) { - if ((err = snd_hdsp_enable_io(hdsp)) < 0) { + if ((err = snd_hdsp_enable_io(hdsp)) < 0) return err; - } snd_hdsp_initialize_channels(hdsp); snd_hdsp_initialize_midi_flush(hdsp); if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) { - snd_printk("Hammerfall-DSP: error creating alsa devices\n"); - return err; + snd_printk(KERN_ERR "Hammerfall-DSP: error creating alsa devices\n"); + return err; } } break; @@ -4790,7 +4651,7 @@ static int snd_hdsp_enable_io (hdsp_t *hdsp) int i; if (hdsp_fifo_wait (hdsp, 0, 100)) { - snd_printk("Hammerfall-DSP: enable_io fifo_wait failed\n"); + snd_printk(KERN_ERR "Hammerfall-DSP: enable_io fifo_wait failed\n"); return -EIO; } @@ -4856,25 +4717,25 @@ static int snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp) int err; if ((err = snd_hdsp_create_pcm(card, hdsp)) < 0) { - snd_printk("Hammerfall-DSP: Error creating pcm interface\n"); + snd_printk(KERN_ERR "Hammerfall-DSP: Error creating pcm interface\n"); return err; } if ((err = snd_hdsp_create_midi(card, hdsp, 0)) < 0) { - snd_printk("Hammerfall-DSP: Error creating first midi interface\n"); + snd_printk(KERN_ERR "Hammerfall-DSP: Error creating first midi interface\n"); return err; } if (hdsp->io_type == Digiface || hdsp->io_type == H9652) { if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) { - snd_printk("Hammerfall-DSP: Error creating second midi interface\n"); + snd_printk(KERN_ERR "Hammerfall-DSP: Error creating second midi interface\n"); return err; } } if ((err = snd_hdsp_create_controls(card, hdsp)) < 0) { - snd_printk("Hammerfall-DSP: Error creating ctl interface\n"); + snd_printk(KERN_ERR "Hammerfall-DSP: Error creating ctl interface\n"); return err; } @@ -4887,7 +4748,7 @@ static int snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp) hdsp->playback_substream = NULL; if ((err = snd_hdsp_set_defaults(hdsp)) < 0) { - snd_printk("Hammerfall-DSP: Error setting default values\n"); + snd_printk(KERN_ERR "Hammerfall-DSP: Error setting default values\n"); return err; } @@ -4897,7 +4758,7 @@ static int snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp) hdsp->port, hdsp->irq); if ((err = snd_card_register(card)) < 0) { - snd_printk("Hammerfall-DSP: error registering card\n"); + snd_printk(KERN_ERR "Hammerfall-DSP: error registering card\n"); return err; } hdsp->state |= HDSP_InitializationComplete; @@ -4963,18 +4824,17 @@ static int __devinit hdsp_request_fw_loader(hdsp_t *hdsp) return err; if (!(hdsp->state & HDSP_InitializationComplete)) { - if ((err = snd_hdsp_enable_io(hdsp)) < 0) { + if ((err = snd_hdsp_enable_io(hdsp)) < 0) return err; - } if ((err = snd_hdsp_create_hwdep(hdsp->card, hdsp)) < 0) { - snd_printk("Hammerfall-DSP: error creating hwdep device\n"); + snd_printk(KERN_ERR "Hammerfall-DSP: error creating hwdep device\n"); return err; } snd_hdsp_initialize_channels(hdsp); snd_hdsp_initialize_midi_flush(hdsp); if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) { - snd_printk("Hammerfall-DSP: error creating alsa devices\n"); + snd_printk(KERN_ERR "Hammerfall-DSP: error creating alsa devices\n"); return err; } } @@ -5029,11 +4889,11 @@ static int __devinit snd_hdsp_create(snd_card_t *card, strcpy(card->driver, "H-DSP"); strcpy(card->mixername, "Xilinx FPGA"); - if (hdsp->firmware_rev < 0xa) { + if (hdsp->firmware_rev < 0xa) return -ENODEV; - } else if (hdsp->firmware_rev < 0x64) { + else if (hdsp->firmware_rev < 0x64) hdsp->card_name = "RME Hammerfall DSP"; - } else if (hdsp->firmware_rev < 0x96) { + else if (hdsp->firmware_rev < 0x96) { hdsp->card_name = "RME HDSP 9652"; is_9652 = 1; } else { @@ -5042,9 +4902,8 @@ static int __devinit snd_hdsp_create(snd_card_t *card, is_9632 = 1; } - if ((err = pci_enable_device(pci)) < 0) { + if ((err = pci_enable_device(pci)) < 0) return err; - } pci_set_master(hdsp->pci); @@ -5052,12 +4911,12 @@ static int __devinit snd_hdsp_create(snd_card_t *card, return err; hdsp->port = pci_resource_start(pci, 0); if ((hdsp->iobase = ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == NULL) { - snd_printk("Hammerfall-DSP: unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1); + snd_printk(KERN_ERR "Hammerfall-DSP: unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1); return -EBUSY; } if (request_irq(pci->irq, snd_hdsp_interrupt, SA_INTERRUPT|SA_SHIRQ, "hdsp", (void *)hdsp)) { - snd_printk("Hammerfall-DSP: unable to use IRQ %d\n", pci->irq); + snd_printk(KERN_ERR "Hammerfall-DSP: unable to use IRQ %d\n", pci->irq); return -EBUSY; } @@ -5065,71 +4924,58 @@ static int __devinit snd_hdsp_create(snd_card_t *card, hdsp->precise_ptr = 1; hdsp->use_midi_tasklet = 1; - if ((err = snd_hdsp_initialize_memory(hdsp)) < 0) { + if ((err = snd_hdsp_initialize_memory(hdsp)) < 0) return err; - } if (!is_9652 && !is_9632) { /* we wait 2 seconds to let freshly inserted cardbus cards do their hardware init */ - if ((1000 / HZ) < 2000) { - ssleep(2); - } else { - mdelay(2000); - } + ssleep(2); if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { #ifdef HDSP_FW_LOADER - if ((err = hdsp_request_fw_loader(hdsp)) < 0) { + if ((err = hdsp_request_fw_loader(hdsp)) < 0) /* we don't fail as this can happen if userspace is not ready for firmware upload */ - snd_printk("Hammerfall-DSP: couldn't get firmware from userspace. try using hdsploader\n"); - } else { + snd_printk(KERN_ERR "Hammerfall-DSP: couldn't get firmware from userspace. try using hdsploader\n"); + else /* init is complete, we return */ return 0; - } #endif /* no iobox connected, we defer initialization */ - snd_printk("Hammerfall-DSP: card initialization pending : waiting for firmware\n"); - if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) { + snd_printk(KERN_INFO "Hammerfall-DSP: card initialization pending : waiting for firmware\n"); + if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) return err; - } return 0; } else { - snd_printk("Hammerfall-DSP: Firmware already present, initializing card.\n"); - if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) { + snd_printk(KERN_INFO "Hammerfall-DSP: Firmware already present, initializing card.\n"); + if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) hdsp->io_type = Multiface; - } else { + else hdsp->io_type = Digiface; - } } } - if ((err = snd_hdsp_enable_io(hdsp)) != 0) { + if ((err = snd_hdsp_enable_io(hdsp)) != 0) return err; - } - if (is_9652) { + if (is_9652) hdsp->io_type = H9652; - } - if (is_9632) { + if (is_9632) hdsp->io_type = H9632; - } - if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) { + if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) return err; - } snd_hdsp_initialize_channels(hdsp); snd_hdsp_initialize_midi_flush(hdsp); hdsp->state |= HDSP_FirmwareLoaded; - if ((err = snd_hdsp_create_alsa_devices(card, hdsp)) < 0) { + if ((err = snd_hdsp_create_alsa_devices(card, hdsp)) < 0) return err; - } return 0; } -- cgit v1.2.3 From 8a5afd29dc16a9e687f63195cb635ecd611482d0 Mon Sep 17 00:00:00 2001 From: James Courtier-Dutton Date: Thu, 20 Oct 2005 22:57:51 +0200 Subject: [ALSA] snd-ca0106: Add midi support. Modules: PCI drivers,CA0106 driver Author: Tilman Kranz Signed-off-by: James Courtier-Dutton --- sound/pci/Kconfig | 1 + sound/pci/ca0106/Makefile | 2 +- sound/pci/ca0106/ca0106.h | 27 +++- sound/pci/ca0106/ca0106_main.c | 111 +++++++++++++++ sound/pci/ca0106/ca_midi.c | 304 +++++++++++++++++++++++++++++++++++++++++ sound/pci/ca0106/ca_midi.h | 72 ++++++++++ 6 files changed, 512 insertions(+), 5 deletions(-) create mode 100644 sound/pci/ca0106/ca_midi.c create mode 100644 sound/pci/ca0106/ca_midi.h diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index d140e93d37b..0fb16cf335e 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig @@ -184,6 +184,7 @@ config SND_CA0106 tristate "SB Audigy LS / Live 24bit" depends on SND select SND_AC97_CODEC + select SND_RAWMIDI help Say Y here to include support for the Sound Blaster Audigy LS and Live 24bit. diff --git a/sound/pci/ca0106/Makefile b/sound/pci/ca0106/Makefile index 89c6ceee21f..dcbae7b3154 100644 --- a/sound/pci/ca0106/Makefile +++ b/sound/pci/ca0106/Makefile @@ -1,3 +1,3 @@ -snd-ca0106-objs := ca0106_main.o ca0106_proc.o ca0106_mixer.o +snd-ca0106-objs := ca0106_main.o ca0106_proc.o ca0106_mixer.o ca_midi.o obj-$(CONFIG_SND_CA0106) += snd-ca0106.o diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h index da09cab405a..9a4b6406f7a 100644 --- a/sound/pci/ca0106/ca0106.h +++ b/sound/pci/ca0106/ca0106.h @@ -399,10 +399,24 @@ #define PLAYBACK_VOLUME2 0x6a /* Playback Analog volume per channel. Does not effect AC3 output */ /* Similar to register 0x66, except that the destination is the I2S mixer instead of the SPDIF mixer. I.E. Outputs to the Analog outputs instead of SPDIF. */ #define UNKNOWN6b 0x6b /* Unknown. Readonly. Default 00400000 00400000 00400000 00400000 */ -#define UART_A_DATA 0x6c /* Uart, used in setting sample rates, bits per sample etc. */ -#define UART_A_CMD 0x6d /* Uart, used in setting sample rates, bits per sample etc. */ -#define UART_B_DATA 0x6e /* Uart, Unknown. */ -#define UART_B_CMD 0x6f /* Uart, Unknown. */ +#define MIDI_UART_A_DATA 0x6c /* Midi Uart A Data */ +#define MIDI_UART_A_CMD 0x6d /* Midi Uart A Command/Status */ +#define MIDI_UART_B_DATA 0x6e /* Midi Uart B Data (currently unused) */ +#define MIDI_UART_B_CMD 0x6f /* Midi Uart B Command/Status (currently unused) */ + +/* unique channel identifier for midi->channel */ + +#define CA0106_MIDI_CHAN_A 0x1 +#define CA0106_MIDI_CHAN_B 0x2 + +/* from mpu401 */ + +#define CA0106_MIDI_INPUT_AVAIL 0x80 +#define CA0106_MIDI_OUTPUT_READY 0x40 +#define CA0106_MPU401_RESET 0xff +#define CA0106_MPU401_ENTER_UART 0x3f +#define CA0106_MPU401_ACK 0xfe + #define SAMPLE_RATE_TRACKER_STATUS 0x70 /* Readonly. Default 00108000 00108000 00500000 00500000 */ /* Estimated sample rate [19:0] Relative to 48kHz. 0x8000 = 1.0 * Rate Locked [20] @@ -538,6 +552,8 @@ #define CONTROL_CENTER_LFE_CHANNEL 1 #define CONTROL_UNKNOWN_CHANNEL 2 +#include "ca_midi.h" + typedef struct snd_ca0106_channel ca0106_channel_t; typedef struct snd_ca0106 ca0106_t; typedef struct snd_ca0106_pcm ca0106_pcm_t; @@ -592,6 +608,9 @@ struct snd_ca0106 { int capture_mic_line_in; struct snd_dma_buffer buffer; + + ca_midi_t midi; + ca_midi_t midi2; }; int __devinit snd_ca0106_mixer(ca0106_t *emu); diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index f6920ef5b4e..aaaef9e66af 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -338,6 +338,18 @@ static void snd_ca0106_intr_enable(ca0106_t *emu, unsigned int intrenb) spin_unlock_irqrestore(&emu->emu_lock, flags); } +static void snd_ca0106_intr_disable(ca0106_t *emu, unsigned int intrenb) +{ + unsigned long flags; + unsigned int enable; + + spin_lock_irqsave(&emu->emu_lock, flags); + enable = inl(emu->port + INTE) & ~intrenb; + outl(enable, emu->port + INTE); + spin_unlock_irqrestore(&emu->emu_lock, flags); +} + + static void snd_ca0106_pcm_free_substream(snd_pcm_runtime_t *runtime) { kfree(runtime->private_data); @@ -1040,6 +1052,15 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id, snd_ca0106_ptr_write(chip, EXTENDED_INT, 0, stat76); spin_lock(&chip->emu_lock); + + if (chip->midi.dev_id && + (status & (chip->midi.ipr_tx|chip->midi.ipr_rx))) { + if (chip->midi.interrupt) + chip->midi.interrupt(&chip->midi, status); + else + chip->midi.interrupt_disable(&chip->midi, chip->midi.tx_enable | chip->midi.rx_enable); + } + // acknowledge the interrupt if necessary outl(status, chip->port+IPR); @@ -1309,6 +1330,82 @@ static int __devinit snd_ca0106_create(snd_card_t *card, return 0; } + +void ca0106_midi_interrupt_enable(ca_midi_t *midi, int intr){ + snd_ca0106_intr_enable((ca0106_t *)(midi->dev_id), intr); +} + +void ca0106_midi_interrupt_disable(ca_midi_t *midi, int intr){ + snd_ca0106_intr_disable((ca0106_t *)(midi->dev_id), intr); +} + +unsigned char ca0106_midi_read(ca_midi_t *midi, int idx){ + return (unsigned char)snd_ca0106_ptr_read((ca0106_t *)(midi->dev_id), midi->port + idx, 0); +} + +void ca0106_midi_write(ca_midi_t *midi, int data, int idx){ + snd_ca0106_ptr_write((ca0106_t *)(midi->dev_id), midi->port + idx, 0, data); +} + +snd_card_t *ca0106_dev_id_card(void *dev_id){ + return ((ca0106_t *)dev_id)->card; +} + +int ca0106_dev_id_port(void *dev_id){ + return ((ca0106_t *)dev_id)->port; +} + +static int __devinit snd_ca0106_midi(ca0106_t *chip, unsigned int channel) +{ + ca_midi_t *midi; + char *name; + int err; + + if(channel==CA0106_MIDI_CHAN_B) { + name = "CA0106 MPU-401 (UART) B"; + midi = &chip->midi2; + midi->tx_enable = INTE_MIDI_TX_B; + midi->rx_enable = INTE_MIDI_RX_B; + midi->ipr_tx = IPR_MIDI_TX_B; + midi->ipr_rx = IPR_MIDI_RX_B; + midi->port = MIDI_UART_B_DATA; + } else { + name = "CA0106 MPU-401 (UART)"; + midi = &chip->midi; + midi->tx_enable = INTE_MIDI_TX_A; + midi->rx_enable = INTE_MIDI_TX_B; + midi->ipr_tx = IPR_MIDI_TX_A; + midi->ipr_rx = IPR_MIDI_RX_A; + midi->port = MIDI_UART_A_DATA; + } + + midi->reset = CA0106_MPU401_RESET; + midi->enter_uart = CA0106_MPU401_ENTER_UART; + midi->ack = CA0106_MPU401_ACK; + + midi->input_avail = CA0106_MIDI_INPUT_AVAIL; + midi->output_ready = CA0106_MIDI_OUTPUT_READY; + + midi->channel = channel; + + midi->interrupt_enable = ca0106_midi_interrupt_enable; + midi->interrupt_disable = ca0106_midi_interrupt_disable; + + midi->read = ca0106_midi_read; + midi->write = ca0106_midi_write; + + midi->get_dev_id_card = ca0106_dev_id_card; + midi->get_dev_id_port = ca0106_dev_id_port; + + midi->dev_id = chip; + + if ((err = ca_midi_init(chip, midi, 0, name)) < 0) + return err; + + return 0; +} + + static int __devinit snd_ca0106_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { @@ -1360,6 +1457,20 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci, return err; } +#ifdef CONFIG_SND_DEBUG_DETECT + printk("ca0106: probe for MIDI channel A ..."); +#endif + if ((err = snd_ca0106_midi(chip,CA0106_MIDI_CHAN_A)) < 0) { + snd_card_free(card); +#ifdef CONFIG_SND_DEBUG_DETECT + printk(" failed, err=0x%x\n",err); +#endif + return err; + } +#ifdef CONFIG_SND_DEBUG_DETECT + printk(" done.\n"); +#endif + snd_ca0106_proc_init(chip); if ((err = snd_card_register(card)) < 0) { diff --git a/sound/pci/ca0106/ca_midi.c b/sound/pci/ca0106/ca_midi.c new file mode 100644 index 00000000000..f439d14876b --- /dev/null +++ b/sound/pci/ca0106/ca_midi.c @@ -0,0 +1,304 @@ +/* + * Copyright 10/16/2005 Tilman Kranz + * Creative Audio MIDI, for the CA0106 Driver + * Version: 0.0.1 + * + * Changelog: + * Implementation is based on mpu401 and emu10k1x and + * tested with ca0106. + * + * 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 option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + */ + +#include +#include +#include +#include + +#include "ca_midi.h" + +#define ca_midi_write_data(midi, data) midi->write(midi, data, 0) +#define ca_midi_write_cmd(midi, data) midi->write(midi, data, 1) +#define ca_midi_read_data(midi) midi->read(midi, 0) +#define ca_midi_read_stat(midi) midi->read(midi, 1) +#define ca_midi_input_avail(midi) (!(ca_midi_read_stat(midi) & midi->input_avail)) +#define ca_midi_output_ready(midi) (!(ca_midi_read_stat(midi) & midi->output_ready)) + +static void ca_midi_clear_rx(ca_midi_t *midi) +{ + int timeout = 100000; + for (; timeout > 0 && ca_midi_input_avail(midi); timeout--) + ca_midi_read_data(midi); +#ifdef CONFIG_SND_DEBUG + if (timeout <= 0) + snd_printk(KERN_ERR "ca_midi_clear_rx: timeout (status = 0x%x)\n", ca_midi_read_stat(midi)); +#endif +} + +void ca_midi_interrupt(ca_midi_t *midi, unsigned int status) { + unsigned char byte; + + if (midi->rmidi == NULL) { + midi->interrupt_disable(midi,midi->tx_enable | midi->rx_enable); + return; + } + + spin_lock(&midi->input_lock); + if ((status & midi->ipr_rx) && ca_midi_input_avail(midi)) { + if (!(midi->midi_mode & CA_MIDI_MODE_INPUT)) { + ca_midi_clear_rx(midi); + } else { + byte = ca_midi_read_data(midi); + if(midi->substream_input) + snd_rawmidi_receive(midi->substream_input, &byte, 1); + + + } + } + spin_unlock(&midi->input_lock); + + spin_lock(&midi->output_lock); + if ((status & midi->ipr_tx) && ca_midi_output_ready(midi)) { + if (midi->substream_output && + snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) { + ca_midi_write_data(midi, byte); + } else { + midi->interrupt_disable(midi,midi->tx_enable); + } + } + spin_unlock(&midi->output_lock); + +} + +static void ca_midi_cmd(ca_midi_t *midi, unsigned char cmd, int ack) +{ + unsigned long flags; + int timeout, ok; + + spin_lock_irqsave(&midi->input_lock, flags); + ca_midi_write_data(midi, 0x00); + /* ca_midi_clear_rx(midi); */ + + ca_midi_write_cmd(midi, cmd); + if (ack) { + ok = 0; + timeout = 10000; + while (!ok && timeout-- > 0) { + if (ca_midi_input_avail(midi)) { + if (ca_midi_read_data(midi) == midi->ack) + ok = 1; + } + } + if (!ok && ca_midi_read_data(midi) == midi->ack) + ok = 1; + } else { + ok = 1; + } + spin_unlock_irqrestore(&midi->input_lock, flags); + if (!ok) + snd_printk(KERN_ERR "ca_midi_cmd: 0x%x failed at 0x%x (status = 0x%x, data = 0x%x)!!!\n", + cmd, + midi->get_dev_id_port(midi->dev_id), + ca_midi_read_stat(midi), + ca_midi_read_data(midi)); +} + +static int ca_midi_input_open(snd_rawmidi_substream_t * substream) +{ + ca_midi_t *midi = (ca_midi_t *)substream->rmidi->private_data; + unsigned long flags; + + snd_assert(midi->dev_id, return -ENXIO); + spin_lock_irqsave(&midi->open_lock, flags); + midi->midi_mode |= CA_MIDI_MODE_INPUT; + midi->substream_input = substream; + if (!(midi->midi_mode & CA_MIDI_MODE_OUTPUT)) { + spin_unlock_irqrestore(&midi->open_lock, flags); + ca_midi_cmd(midi, midi->reset, 1); + ca_midi_cmd(midi, midi->enter_uart, 1); + } else { + spin_unlock_irqrestore(&midi->open_lock, flags); + } + return 0; +} + +static int ca_midi_output_open(snd_rawmidi_substream_t * substream) +{ + ca_midi_t *midi = (ca_midi_t *)substream->rmidi->private_data; + unsigned long flags; + + snd_assert(midi->dev_id, return -ENXIO); + spin_lock_irqsave(&midi->open_lock, flags); + midi->midi_mode |= CA_MIDI_MODE_OUTPUT; + midi->substream_output = substream; + if (!(midi->midi_mode & CA_MIDI_MODE_INPUT)) { + spin_unlock_irqrestore(&midi->open_lock, flags); + ca_midi_cmd(midi, midi->reset, 1); + ca_midi_cmd(midi, midi->enter_uart, 1); + } else { + spin_unlock_irqrestore(&midi->open_lock, flags); + } + return 0; +} + +static int ca_midi_input_close(snd_rawmidi_substream_t * substream) +{ + ca_midi_t *midi = (ca_midi_t *)substream->rmidi->private_data; + unsigned long flags; + + snd_assert(midi->dev_id, return -ENXIO); + spin_lock_irqsave(&midi->open_lock, flags); + midi->interrupt_disable(midi,midi->rx_enable); + midi->midi_mode &= ~CA_MIDI_MODE_INPUT; + midi->substream_input = NULL; + if (!(midi->midi_mode & CA_MIDI_MODE_OUTPUT)) { + spin_unlock_irqrestore(&midi->open_lock, flags); + ca_midi_cmd(midi, midi->reset, 0); + } else { + spin_unlock_irqrestore(&midi->open_lock, flags); + } + return 0; +} + +static int ca_midi_output_close(snd_rawmidi_substream_t * substream) +{ + ca_midi_t *midi = (ca_midi_t *)substream->rmidi->private_data; + unsigned long flags; + snd_assert(midi->dev_id, return -ENXIO); + + spin_lock_irqsave(&midi->open_lock, flags); + + midi->interrupt_disable(midi,midi->tx_enable); + midi->midi_mode &= ~CA_MIDI_MODE_OUTPUT; + midi->substream_output = NULL; + + if (!(midi->midi_mode & CA_MIDI_MODE_INPUT)) { + spin_unlock_irqrestore(&midi->open_lock, flags); + ca_midi_cmd(midi, midi->reset, 0); + } else { + spin_unlock_irqrestore(&midi->open_lock, flags); + } + return 0; +} + +static void ca_midi_input_trigger(snd_rawmidi_substream_t * substream, int up) +{ + ca_midi_t *midi = (ca_midi_t *)substream->rmidi->private_data; + snd_assert(midi->dev_id, return); + + if (up) { + midi->interrupt_enable(midi,midi->rx_enable); + } else { + midi->interrupt_disable(midi, midi->rx_enable); + } +} + +static void ca_midi_output_trigger(snd_rawmidi_substream_t * substream, int up) +{ + ca_midi_t *midi = (ca_midi_t *)substream->rmidi->private_data; + unsigned long flags; + + snd_assert(midi->dev_id, return); + + if (up) { + int max = 4; + unsigned char byte; + + spin_lock_irqsave(&midi->output_lock, flags); + + /* try to send some amount of bytes here before interrupts */ + while (max > 0) { + if (ca_midi_output_ready(midi)) { + if (!(midi->midi_mode & CA_MIDI_MODE_OUTPUT) || + snd_rawmidi_transmit(substream, &byte, 1) != 1) { + /* no more data */ + spin_unlock_irqrestore(&midi->output_lock, flags); + return; + } + ca_midi_write_data(midi, byte); + max--; + } else { + break; + } + } + + spin_unlock_irqrestore(&midi->output_lock, flags); + midi->interrupt_enable(midi,midi->tx_enable); + + } else { + midi->interrupt_disable(midi,midi->tx_enable); + } +} + +static snd_rawmidi_ops_t ca_midi_output = +{ + .open = ca_midi_output_open, + .close = ca_midi_output_close, + .trigger = ca_midi_output_trigger, +}; + +static snd_rawmidi_ops_t ca_midi_input = +{ + .open = ca_midi_input_open, + .close = ca_midi_input_close, + .trigger = ca_midi_input_trigger, +}; + +void ca_midi_free(ca_midi_t *midi) { + midi->interrupt = NULL; + midi->interrupt_enable = NULL; + midi->interrupt_disable = NULL; + midi->read = NULL; + midi->write = NULL; + midi->get_dev_id_card = NULL; + midi->get_dev_id_port = NULL; + midi->rmidi = NULL; +} + +static void ca_rmidi_free(snd_rawmidi_t *rmidi) +{ + ca_midi_free((ca_midi_t *)rmidi->private_data); +} + +int __devinit ca_midi_init(void *dev_id, ca_midi_t *midi, int device, char *name) +{ + snd_rawmidi_t *rmidi; + int err; + + if ((err = snd_rawmidi_new(midi->get_dev_id_card(midi->dev_id), name, device, 1, 1, &rmidi)) < 0) + return err; + + midi->dev_id = dev_id; + midi->interrupt = ca_midi_interrupt; + + spin_lock_init(&midi->open_lock); + spin_lock_init(&midi->input_lock); + spin_lock_init(&midi->output_lock); + + strcpy(rmidi->name, name); + snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &ca_midi_output); + snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &ca_midi_input); + rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | + SNDRV_RAWMIDI_INFO_INPUT | + SNDRV_RAWMIDI_INFO_DUPLEX; + rmidi->private_data = midi; + rmidi->private_free = ca_rmidi_free; + + midi->rmidi = rmidi; + return 0; +} + diff --git a/sound/pci/ca0106/ca_midi.h b/sound/pci/ca0106/ca_midi.h new file mode 100644 index 00000000000..95c8e1c170b --- /dev/null +++ b/sound/pci/ca0106/ca_midi.h @@ -0,0 +1,72 @@ +/* + * Copyright 10/16/2005 Tilman Kranz + * Creative Audio MIDI, for the CA0106 Driver + * Version: 0.0.1 + * + * Changelog: + * See ca_midi.c + * + * 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 option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include + +#define CA_MIDI_MODE_INPUT MPU401_MODE_INPUT +#define CA_MIDI_MODE_OUTPUT MPU401_MODE_OUTPUT + +typedef struct ca_midi ca_midi_t; +struct ca_midi { + + snd_rawmidi_t *rmidi; + snd_rawmidi_substream_t *substream_input; + snd_rawmidi_substream_t *substream_output; + + void *dev_id; + + spinlock_t input_lock; + spinlock_t output_lock; + spinlock_t open_lock; + + unsigned int channel; + + unsigned int midi_mode; + int port; + int tx_enable, rx_enable; + int ipr_tx, ipr_rx; + + int input_avail, output_ready; + int ack, reset, enter_uart; + + void (*interrupt)(ca_midi_t *midi, unsigned int status); + void (*interrupt_enable)(ca_midi_t *midi, int intr); + void (*interrupt_disable)(ca_midi_t *midi, int intr); + + unsigned char (*read)(ca_midi_t *midi, int idx); + void (*write)(ca_midi_t *midi, int data, int idx); + + /* get info from dev_id */ + snd_card_t *(*get_dev_id_card)(void *dev_id); + int (*get_dev_id_port)(void *dev_id); +}; + +void ca_midi_interrupt(ca_midi_t *midi, unsigned int status); + +int __devinit ca_midi_init(void *card, ca_midi_t *midi, int device, char *name); + +void ca_midi_free(ca_midi_t *midi); + -- cgit v1.2.3 From d3d579f84ebf701dedd22ba696d1738ed6759ef7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 21 Oct 2005 16:20:11 +0200 Subject: [ALSA] Add missing KERN_* prefix Modules: ALSA<-OSS emulation,USB generic driver,USB USX2Y Added missing KERN_* prefix to printk. Signed-off-by: Takashi Iwai --- sound/core/oss/mixer_oss.c | 3 ++- sound/core/oss/pcm_oss.c | 9 ++++++--- sound/usb/usbmixer.c | 2 +- sound/usb/usx2y/usX2Yhwdep.c | 10 +++++----- sound/usb/usx2y/usbusx2y.c | 5 ++--- sound/usb/usx2y/usbusx2yaudio.c | 23 +++++++++++------------ sound/usb/usx2y/usx2yhwdeppcm.c | 4 ++-- 7 files changed, 29 insertions(+), 27 deletions(-) diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index b2497cec207..214933cf5d4 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -1294,7 +1294,8 @@ static int snd_mixer_oss_notify_handler(snd_card_t * card, int cmd) card, 0, &snd_mixer_oss_reg, name)) < 0) { - snd_printk("unable to register OSS mixer device %i:%i\n", card->number, 0); + snd_printk(KERN_ERR "unable to register OSS mixer device %i:%i\n", + card->number, 0); kfree(mixer); return err; } diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index c57f702d31a..bcc97075913 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2457,7 +2457,8 @@ static void register_oss_dsp(snd_pcm_t *pcm, int index) if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, pcm->card, index, &snd_pcm_oss_reg, name) < 0) { - snd_printk("unable to register OSS PCM device %i:%i\n", pcm->card->number, pcm->device); + snd_printk(KERN_ERR "unable to register OSS PCM device %i:%i\n", + pcm->card->number, pcm->device); } } @@ -2539,11 +2540,13 @@ static int __init alsa_pcm_oss_init(void) /* check device map table */ for (i = 0; i < SNDRV_CARDS; i++) { if (dsp_map[i] < 0 || dsp_map[i] >= SNDRV_PCM_DEVICES) { - snd_printk("invalid dsp_map[%d] = %d\n", i, dsp_map[i]); + snd_printk(KERN_ERR "invalid dsp_map[%d] = %d\n", + i, dsp_map[i]); dsp_map[i] = 0; } if (adsp_map[i] < 0 || adsp_map[i] >= SNDRV_PCM_DEVICES) { - snd_printk("invalid adsp_map[%d] = %d\n", i, adsp_map[i]); + snd_printk(KERN_ERR "invalid adsp_map[%d] = %d\n", + i, adsp_map[i]); adsp_map[i] = 1; } } diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index c3c08c9cb46..e570d140258 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c @@ -911,7 +911,7 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc, case USB_ID(0x0672, 0x1041): if (!strcmp(kctl->id.name, "PCM Playback Volume") && cval->min == -15616) { - snd_printk("using volume control quirk for the UDA1321/N101 chip\n"); + snd_printk(KERN_INFO "using volume control quirk for the UDA1321/N101 chip\n"); cval->max = -256; } } diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c index 0281a362857..8abe08611df 100644 --- a/sound/usb/usx2y/usX2Yhwdep.c +++ b/sound/usb/usx2y/usX2Yhwdep.c @@ -193,7 +193,7 @@ static int usX2Y_create_alsa_devices(snd_card_t* card) do { if ((err = usX2Y_create_usbmidi(card)) < 0) { - snd_printk("usX2Y_create_alsa_devices: usX2Y_create_usbmidi error %i \n", err); + snd_printk(KERN_ERR "usX2Y_create_alsa_devices: usX2Y_create_usbmidi error %i \n", err); break; } if ((err = usX2Y_audio_create(card)) < 0) @@ -224,7 +224,7 @@ static int snd_usX2Y_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp) } err = usb_set_interface(dev, 0, 1); if (err) - snd_printk("usb_set_interface error \n"); + snd_printk(KERN_ERR "usb_set_interface error \n"); else err = usb_bulk_msg(dev, usb_sndbulkpipe(dev, 2), buf, dsp->length, &lret, 6000); kfree(buf); @@ -235,17 +235,17 @@ static int snd_usX2Y_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp) msleep(250); // give the device some time err = usX2Y_AsyncSeq04_init(priv); if (err) { - snd_printk("usX2Y_AsyncSeq04_init error \n"); + snd_printk(KERN_ERR "usX2Y_AsyncSeq04_init error \n"); return err; } err = usX2Y_In04_init(priv); if (err) { - snd_printk("usX2Y_In04_init error \n"); + snd_printk(KERN_ERR "usX2Y_In04_init error \n"); return err; } err = usX2Y_create_alsa_devices(hw->card); if (err) { - snd_printk("usX2Y_create_alsa_devices error %i \n", err); + snd_printk(KERN_ERR "usX2Y_create_alsa_devices error %i \n", err); snd_card_free(hw->card); return err; } diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index e6e6da15967..cf77313c609 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c @@ -251,9 +251,8 @@ static void i_usX2Y_In04Int(struct urb* urb, struct pt_regs *regs) } } - if (err) { - snd_printk("In04Int() usb_submit_urb err=%i\n", err); - } + if (err) + snd_printk(KERN_ERR "In04Int() usb_submit_urb err=%i\n", err); urb->dev = usX2Y->chip.dev; usb_submit_urb(urb, GFP_ATOMIC); diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index 0f09e0de52d..affda973cec 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c @@ -78,7 +78,7 @@ static int usX2Y_urb_capt_retire(snd_usX2Y_substream_t *subs) for (i = 0; i < nr_of_packs(); i++) { cp = (unsigned char*)urb->transfer_buffer + urb->iso_frame_desc[i].offset; if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */ - snd_printk("activ frame status %i. Most propably some hardware problem.\n", urb->iso_frame_desc[i].status); + snd_printk(KERN_ERR "activ frame status %i. Most propably some hardware problem.\n", urb->iso_frame_desc[i].status); return urb->iso_frame_desc[i].status; } len = urb->iso_frame_desc[i].actual_length / usX2Y->stride; @@ -134,7 +134,7 @@ static int usX2Y_urb_play_prepare(snd_usX2Y_substream_t *subs, counts = cap_urb->iso_frame_desc[pack].actual_length / usX2Y->stride; count += counts; if (counts < 43 || counts > 50) { - snd_printk("should not be here with counts=%i\n", counts); + snd_printk(KERN_ERR "should not be here with counts=%i\n", counts); return -EPIPE; } /* set up descriptor */ @@ -196,7 +196,7 @@ static int usX2Y_urb_submit(snd_usX2Y_substream_t *subs, struct urb *urb, int fr urb->hcpriv = NULL; urb->dev = subs->usX2Y->chip.dev; /* we need to set this at each time */ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { - snd_printk("usb_submit_urb() returned %i\n", err); + snd_printk(KERN_ERR "usb_submit_urb() returned %i\n", err); return err; } return 0; @@ -283,16 +283,16 @@ static void usX2Y_clients_stop(usX2Ydev_t *usX2Y) static void usX2Y_error_urb_status(usX2Ydev_t *usX2Y, snd_usX2Y_substream_t *subs, struct urb *urb) { - snd_printk("ep=%i stalled with status=%i\n", subs->endpoint, urb->status); + snd_printk(KERN_ERR "ep=%i stalled with status=%i\n", subs->endpoint, urb->status); urb->status = 0; usX2Y_clients_stop(usX2Y); } static void usX2Y_error_sequence(usX2Ydev_t *usX2Y, snd_usX2Y_substream_t *subs, struct urb *urb) { - snd_printk("Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n" - "Most propably some urb of usb-frame %i is still missing.\n" - "Cause could be too long delays in usb-hcd interrupt handling.\n", + snd_printk(KERN_ERR "Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n" + KERN_ERR "Most propably some urb of usb-frame %i is still missing.\n" + KERN_ERR "Cause could be too long delays in usb-hcd interrupt handling.\n", usb_get_current_frame_number(usX2Y->chip.dev), subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", usX2Y->wait_iso_frame, urb->start_frame, usX2Y->wait_iso_frame); usX2Y_clients_stop(usX2Y); @@ -653,9 +653,8 @@ static void i_usX2Y_04Int(struct urb* urb, struct pt_regs *regs) { usX2Ydev_t* usX2Y = urb->context; - if (urb->status) { - snd_printk("snd_usX2Y_04Int() urb->status=%i\n", urb->status); - } + if (urb->status) + snd_printk(KERN_ERR "snd_usX2Y_04Int() urb->status=%i\n", urb->status); if (0 == --usX2Y->US04->len) wake_up(&usX2Y->In04WaitQueue); } @@ -740,7 +739,7 @@ static int usX2Y_format_set(usX2Ydev_t *usX2Y, snd_pcm_format_t format) } usb_kill_urb(usX2Y->In04urb); if ((err = usb_set_interface(usX2Y->chip.dev, 0, alternate))) { - snd_printk("usb_set_interface error \n"); + snd_printk(KERN_ERR "usb_set_interface error \n"); return err; } usX2Y->In04urb->dev = usX2Y->chip.dev; @@ -787,7 +786,7 @@ static int snd_usX2Y_pcm_hw_params(snd_pcm_substream_t *substream, } } if (0 > (err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)))) { - snd_printk("snd_pcm_lib_malloc_pages(%p, %i) returned %i\n", substream, params_buffer_bytes(hw_params), err); + snd_printk(KERN_ERR "snd_pcm_lib_malloc_pages(%p, %i) returned %i\n", substream, params_buffer_bytes(hw_params), err); return err; } return 0; diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index d0199c4e555..0dc828ff9e9 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c @@ -73,7 +73,7 @@ static int usX2Y_usbpcm_urb_capt_retire(snd_usX2Y_substream_t *subs) } for (i = 0; i < nr_of_packs(); i++) { if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */ - snd_printk("activ frame status %i. Most propably some hardware problem.\n", urb->iso_frame_desc[i].status); + snd_printk(KERN_ERR "activ frame status %i. Most propably some hardware problem.\n", urb->iso_frame_desc[i].status); return urb->iso_frame_desc[i].status; } lens += urb->iso_frame_desc[i].actual_length / usX2Y->stride; @@ -126,7 +126,7 @@ static int usX2Y_hwdep_urb_play_prepare(snd_usX2Y_substream_t *subs, /* calculate the size of a packet */ counts = shm->captured_iso[shm->playback_iso_head].length / usX2Y->stride; if (counts < 43 || counts > 50) { - snd_printk("should not be here with counts=%i\n", counts); + snd_printk(KERN_ERR "should not be here with counts=%i\n", counts); return -EPIPE; } /* set up descriptor */ -- cgit v1.2.3 From 7cf4783b31607ad13b84bed14ea2ca446364985a Mon Sep 17 00:00:00 2001 From: James Courtier-Dutton Date: Sat, 22 Oct 2005 11:45:55 +0200 Subject: [ALSA] ca0106: Cosmetic changes. Modules: CA0106 driver Just tidying up the code. Making more functions static. Signed-off-by: James Courtier-Dutton --- sound/pci/ca0106/ca0106_main.c | 30 +++++++++++++++--------------- sound/pci/ca0106/ca_midi.c | 4 ++-- sound/pci/ca0106/ca_midi.h | 3 --- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index aaaef9e66af..ee58d16002e 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -1331,27 +1331,33 @@ static int __devinit snd_ca0106_create(snd_card_t *card, } -void ca0106_midi_interrupt_enable(ca_midi_t *midi, int intr){ +static void ca0106_midi_interrupt_enable(ca_midi_t *midi, int intr) +{ snd_ca0106_intr_enable((ca0106_t *)(midi->dev_id), intr); } -void ca0106_midi_interrupt_disable(ca_midi_t *midi, int intr){ +static void ca0106_midi_interrupt_disable(ca_midi_t *midi, int intr) +{ snd_ca0106_intr_disable((ca0106_t *)(midi->dev_id), intr); } -unsigned char ca0106_midi_read(ca_midi_t *midi, int idx){ +static unsigned char ca0106_midi_read(ca_midi_t *midi, int idx) +{ return (unsigned char)snd_ca0106_ptr_read((ca0106_t *)(midi->dev_id), midi->port + idx, 0); } -void ca0106_midi_write(ca_midi_t *midi, int data, int idx){ +static void ca0106_midi_write(ca_midi_t *midi, int data, int idx) +{ snd_ca0106_ptr_write((ca0106_t *)(midi->dev_id), midi->port + idx, 0, data); } -snd_card_t *ca0106_dev_id_card(void *dev_id){ +static snd_card_t *ca0106_dev_id_card(void *dev_id) +{ return ((ca0106_t *)dev_id)->card; } -int ca0106_dev_id_port(void *dev_id){ +static int ca0106_dev_id_port(void *dev_id) +{ return ((ca0106_t *)dev_id)->port; } @@ -1457,19 +1463,13 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci, return err; } -#ifdef CONFIG_SND_DEBUG_DETECT - printk("ca0106: probe for MIDI channel A ..."); -#endif + snd_printdd("ca0106: probe for MIDI channel A ..."); if ((err = snd_ca0106_midi(chip,CA0106_MIDI_CHAN_A)) < 0) { snd_card_free(card); -#ifdef CONFIG_SND_DEBUG_DETECT - printk(" failed, err=0x%x\n",err); -#endif + snd_printdd(" failed, err=0x%x\n",err); return err; } -#ifdef CONFIG_SND_DEBUG_DETECT - printk(" done.\n"); -#endif + snd_printdd(" done.\n"); snd_ca0106_proc_init(chip); diff --git a/sound/pci/ca0106/ca_midi.c b/sound/pci/ca0106/ca_midi.c index f439d14876b..9cc0c67ace9 100644 --- a/sound/pci/ca0106/ca_midi.c +++ b/sound/pci/ca0106/ca_midi.c @@ -49,7 +49,7 @@ static void ca_midi_clear_rx(ca_midi_t *midi) #endif } -void ca_midi_interrupt(ca_midi_t *midi, unsigned int status) { +static void ca_midi_interrupt(ca_midi_t *midi, unsigned int status) { unsigned char byte; if (midi->rmidi == NULL) { @@ -258,7 +258,7 @@ static snd_rawmidi_ops_t ca_midi_input = .trigger = ca_midi_input_trigger, }; -void ca_midi_free(ca_midi_t *midi) { +static void ca_midi_free(ca_midi_t *midi) { midi->interrupt = NULL; midi->interrupt_enable = NULL; midi->interrupt_disable = NULL; diff --git a/sound/pci/ca0106/ca_midi.h b/sound/pci/ca0106/ca_midi.h index 95c8e1c170b..b452cec2bf5 100644 --- a/sound/pci/ca0106/ca_midi.h +++ b/sound/pci/ca0106/ca_midi.h @@ -64,9 +64,6 @@ struct ca_midi { int (*get_dev_id_port)(void *dev_id); }; -void ca_midi_interrupt(ca_midi_t *midi, unsigned int status); - int __devinit ca_midi_init(void *card, ca_midi_t *midi, int device, char *name); -void ca_midi_free(ca_midi_t *midi); -- cgit v1.2.3 From 7b4260f2cc8a0da74a7842106cc87ab54bf17ec5 Mon Sep 17 00:00:00 2001 From: James Courtier-Dutton Date: Sat, 22 Oct 2005 11:49:51 +0200 Subject: [ALSA] ca0106: Added copyright messages. Modules: CA0106 driver Signed-off-by: James Courtier-Dutton --- sound/pci/ca0106/ca_midi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/ca0106/ca_midi.c b/sound/pci/ca0106/ca_midi.c index 9cc0c67ace9..2e08b27b834 100644 --- a/sound/pci/ca0106/ca_midi.c +++ b/sound/pci/ca0106/ca_midi.c @@ -6,6 +6,8 @@ * Changelog: * Implementation is based on mpu401 and emu10k1x and * tested with ca0106. + * mpu401: Copyright (c) by Jaroslav Kysela + * emu10k1x: Copyright (c) by Francisco Moraes * * 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 -- cgit v1.2.3 From d78bec210f07b06f406b877b9179e0cc281ae8e6 Mon Sep 17 00:00:00 2001 From: Wei Ni Date: Mon, 24 Oct 2005 11:04:51 +0200 Subject: [ALSA] intel8x0 - fix capture for M1563 Modules: Intel8x0 driver 1.In intel8x0_measure_ac97_clock routine, when stop DMA, there is not stop DMA corectly, but start another PCM In2 DMA engine. 2.In do_ali_reset routine, there is only need to enable PCM IN and PCM OUT. Signed-off-by: Jaroslav Kysela --- sound/pci/intel8x0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index d71f5d1e716..383a3ac5ecb 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -2138,7 +2138,7 @@ static void do_ali_reset(intel8x0_t *chip) iputdword(chip, ICHREG(ALI_FIFOCR2), 0x83838383); iputdword(chip, ICHREG(ALI_FIFOCR3), 0x83838383); iputdword(chip, ICHREG(ALI_INTERFACECR), - ICH_ALI_IF_MC|ICH_ALI_IF_PI|ICH_ALI_IF_PO); + ICH_ALI_IF_PI|ICH_ALI_IF_PO); iputdword(chip, ICHREG(ALI_INTERRUPTCR), 0x00000000); iputdword(chip, ICHREG(ALI_INTERRUPTSR), 0x00000000); } @@ -2484,7 +2484,7 @@ static void __devinit intel8x0_measure_ac97_clock(intel8x0_t *chip) do_gettimeofday(&stop_time); /* stop */ if (chip->device_type == DEVICE_ALI) { - iputdword(chip, ICHREG(ALI_DMACR), 1 << (ichdev->ali_slot + 8)); + iputdword(chip, ICHREG(ALI_DMACR), 1 << (ichdev->ali_slot + 16)); iputbyte(chip, port + ICH_REG_OFF_CR, 0); while (igetbyte(chip, port + ICH_REG_OFF_CR)) ; -- cgit v1.2.3 From 8433a509c0eb6bb1f33ce39c82c580b8901619ee Mon Sep 17 00:00:00 2001 From: Nishanth Aravamudan Date: Mon, 24 Oct 2005 15:02:37 +0200 Subject: [ALSA] Fix schedule_timeout usage Use schedule_timeout_{,un}interruptible() instead of set_current_state()/schedule_timeout() to reduce kernel size. Also use human-time conversion functions instead of hard-coded division to avoid rounding issues. Signed-off-by: Nishanth Aravamudan Signed-off-by: Andrew Morton Signed-off-by: Takashi Iwai --- sound/core/seq/seq_instr.c | 12 ++++-------- sound/core/seq/seq_lock.c | 3 +-- sound/core/seq/seq_memory.c | 3 +-- sound/i2c/cs8427.c | 3 +-- sound/isa/ad1848/ad1848_lib.c | 6 ++---- sound/isa/gus/gus_pcm.c | 3 +-- sound/isa/sb/emu8000.c | 9 +++------ sound/isa/sb/emu8000_patch.c | 3 +-- sound/isa/sb/emu8000_pcm.c | 3 +-- sound/isa/sscape.c | 17 ++--------------- sound/isa/wavefront/wavefront_synth.c | 6 ++---- sound/pci/ac97/ac97_codec.c | 15 +++++---------- sound/pci/ali5451/ali5451.c | 12 ++++-------- sound/pci/atiixp.c | 3 +-- sound/pci/atiixp_modem.c | 3 +-- sound/pci/cs4281.c | 6 ++---- sound/pci/ens1370.c | 3 +-- sound/pci/fm801.c | 9 +++------ sound/pci/ice1712/pontis.c | 3 +-- sound/pci/intel8x0.c | 3 +-- sound/pci/intel8x0m.c | 3 +-- sound/pci/maestro3.c | 9 +++------ sound/pci/mixart/mixart.c | 3 +-- sound/pci/trident/trident_main.c | 3 +-- sound/pci/via82xx.c | 6 ++---- sound/pci/via82xx_modem.c | 6 ++---- sound/pci/ymfpci/ymfpci_main.c | 5 ++--- sound/usb/usbaudio.c | 3 +-- 28 files changed, 51 insertions(+), 112 deletions(-) diff --git a/sound/core/seq/seq_instr.c b/sound/core/seq/seq_instr.c index 019d43a462d..1d525b13ebb 100644 --- a/sound/core/seq/seq_instr.c +++ b/sound/core/seq/seq_instr.c @@ -109,8 +109,7 @@ void snd_seq_instr_list_free(snd_seq_kinstr_list_t **list_ptr) spin_lock_irqsave(&list->lock, flags); while (instr->use) { spin_unlock_irqrestore(&list->lock, flags); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_interruptible(1); spin_lock_irqsave(&list->lock, flags); } spin_unlock_irqrestore(&list->lock, flags); @@ -199,10 +198,8 @@ int snd_seq_instr_list_free_cond(snd_seq_kinstr_list_t *list, while (flist) { instr = flist; flist = instr->next; - while (instr->use) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } + while (instr->use) + schedule_timeout_interruptible(1); if (snd_seq_instr_free(instr, atomic)<0) snd_printk(KERN_WARNING "instrument free problem\n"); instr = next; @@ -554,8 +551,7 @@ static int instr_free(snd_seq_kinstr_ops_t *ops, instr->ops->notify(instr->ops->private_data, instr, SNDRV_SEQ_INSTR_NOTIFY_REMOVE); while (instr->use) { spin_unlock_irqrestore(&list->lock, flags); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_interruptible(1); spin_lock_irqsave(&list->lock, flags); } spin_unlock_irqrestore(&list->lock, flags); diff --git a/sound/core/seq/seq_lock.c b/sound/core/seq/seq_lock.c index b09cee058fa..a837a94b2d2 100644 --- a/sound/core/seq/seq_lock.c +++ b/sound/core/seq/seq_lock.c @@ -39,8 +39,7 @@ void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line) snd_printk(KERN_WARNING "seq_lock: timeout [%d left] in %s:%d\n", atomic_read(lockp), file, line); break; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); max_count--; } } diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index d4d7d326c4b..8416bcffa09 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c @@ -423,8 +423,7 @@ int snd_seq_pool_done(pool_t *pool) snd_printk(KERN_WARNING "snd_seq_pool_done timeout: %d cells remain\n", atomic_read(&pool->counter)); break; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); max_count--; } diff --git a/sound/i2c/cs8427.c b/sound/i2c/cs8427.c index 21133eb6e88..1a05cfbdc7c 100644 --- a/sound/i2c/cs8427.c +++ b/sound/i2c/cs8427.c @@ -302,8 +302,7 @@ static void snd_cs8427_reset(snd_i2c_device_t *cs8427) snd_i2c_unlock(cs8427->bus); if (!(data & CS8427_UNLOCK)) break; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } snd_i2c_lock(cs8427->bus); chip->regmap[CS8427_REG_CLOCKSOURCE] &= ~CS8427_RXDMASK; diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c index 744b65a35c9..891bacc94f6 100644 --- a/sound/isa/ad1848/ad1848_lib.c +++ b/sound/isa/ad1848/ad1848_lib.c @@ -243,8 +243,7 @@ static void snd_ad1848_mce_down(ad1848_t *chip) snd_printk(KERN_ERR "mce_down - auto calibration time out (2)\n"); return; } - set_current_state(TASK_INTERRUPTIBLE); - time = schedule_timeout(time); + time = schedule_timeout_interruptible(time); spin_lock_irqsave(&chip->reg_lock, flags); } #if 0 @@ -257,8 +256,7 @@ static void snd_ad1848_mce_down(ad1848_t *chip) snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n"); return; } - set_current_state(TASK_INTERRUPTIBLE); - time = schedule_timeout(time); + time = schedule_timeout_interruptible(time); spin_lock_irqsave(&chip->reg_lock, flags); } spin_unlock_irqrestore(&chip->reg_lock, flags); diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c index 720c0739c3a..1cc89fb67bf 100644 --- a/sound/isa/gus/gus_pcm.c +++ b/sound/isa/gus/gus_pcm.c @@ -333,8 +333,7 @@ static int snd_gf1_pcm_poke_block(snd_gus_card_t *gus, unsigned char *buf, } } if (count > 0 && !in_interrupt()) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_interruptible(1); if (signal_pending(current)) return -EAGAIN; } diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c index 95540f13319..b09c6575e01 100644 --- a/sound/isa/sb/emu8000.c +++ b/sound/isa/sb/emu8000.c @@ -135,8 +135,7 @@ static void __init snd_emu8000_read_wait(emu8000_t *emu) { while ((EMU8000_SMALR_READ(emu) & 0x80000000) != 0) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_interruptible(1); if (signal_pending(current)) break; } @@ -148,8 +147,7 @@ static void __init snd_emu8000_write_wait(emu8000_t *emu) { while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_interruptible(1); if (signal_pending(current)) break; } @@ -437,8 +435,7 @@ size_dram(emu8000_t *emu) for (i = 0; i < 10000; i++) { if ((EMU8000_SMALW_READ(emu) & 0x80000000) == 0) break; - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_interruptible(1); if (signal_pending(current)) break; } diff --git a/sound/isa/sb/emu8000_patch.c b/sound/isa/sb/emu8000_patch.c index 26e693078cb..2fea67e71c7 100644 --- a/sound/isa/sb/emu8000_patch.c +++ b/sound/isa/sb/emu8000_patch.c @@ -109,8 +109,7 @@ static void snd_emu8000_write_wait(emu8000_t *emu) { while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_interruptible(1); if (signal_pending(current)) break; } diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c index 0209790dc4b..b323beeeda1 100644 --- a/sound/isa/sb/emu8000_pcm.c +++ b/sound/isa/sb/emu8000_pcm.c @@ -117,8 +117,7 @@ snd_emu8000_write_wait(emu8000_t *emu, int can_schedule) { while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) { if (can_schedule) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_interruptible(1); if (signal_pending(current)) break; } diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 1036876146c..11588067fa4 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -342,19 +342,6 @@ static void soundscape_free(snd_card_t * c) free_dma(sscape->chip->dma1); } -/* - * Put this process into an idle wait-state for a certain number - * of "jiffies". The process can almost certainly be rescheduled - * while we're waiting, and so we must NOT be holding any spinlocks - * when we call this function. If we are then we risk DEADLOCK in - * SMP (Ha!) or pre-emptible kernels. - */ -static inline void sleep(long jiffs, int state) -{ - set_current_state(state); - schedule_timeout(jiffs); -} - /* * Tell the SoundScape to begin a DMA tranfer using the given channel. * All locking issues are left to the caller. @@ -392,7 +379,7 @@ static int obp_startup_ack(struct soundscape *s, unsigned timeout) unsigned long flags; unsigned char x; - sleep(1, TASK_INTERRUPTIBLE); + schedule_timeout_interruptible(1); spin_lock_irqsave(&s->lock, flags); x = inb(HOST_DATA_IO(s->io_base)); @@ -419,7 +406,7 @@ static int host_startup_ack(struct soundscape *s, unsigned timeout) unsigned long flags; unsigned char x; - sleep(1, TASK_INTERRUPTIBLE); + schedule_timeout_interruptible(1); spin_lock_irqsave(&s->lock, flags); x = inb(HOST_DATA_IO(s->io_base)); diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index 0c3c951009d..abd79b78141 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c @@ -275,8 +275,7 @@ static int wavefront_sleep (int limit) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(limit); + schedule_timeout_interruptible(limit); return signal_pending(current); } @@ -1788,8 +1787,7 @@ wavefront_should_cause_interrupt (snd_wavefront_t *dev, outb (val,port); spin_unlock_irq(&dev->irq_lock); while (1) { - set_current_state(TASK_INTERRUPTIBLE); - if ((timeout = schedule_timeout(timeout)) == 0) + if ((timeout = schedule_timeout_interruptible(timeout)) == 0) return; if (dev->irq_ok) return; diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index bbc409ae7ee..3b589104510 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1745,8 +1745,7 @@ static int ac97_reset_wait(ac97_t *ac97, int timeout, int with_modem) if ((snd_ac97_read(ac97, AC97_REC_GAIN) & 0x7fff) == 0x0a05) return 0; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } while (time_after_eq(end_time, jiffies)); return -ENODEV; } @@ -1992,8 +1991,7 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) do { if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f) goto __ready_ok; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } while (time_after_eq(end_time, jiffies)); snd_printk(KERN_WARNING "AC'97 %d analog subsections not ready\n", ac97->num); } @@ -2025,8 +2023,7 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) do { if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp) goto __ready_ok; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } while (time_after_eq(end_time, jiffies)); snd_printk(KERN_WARNING "MC'97 %d converters and GPIO not ready (0x%x)\n", ac97->num, snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS)); } @@ -2260,8 +2257,7 @@ void snd_ac97_resume(ac97_t *ac97) do { if (snd_ac97_read(ac97, AC97_MASTER) == 0x8101) break; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } while (time_after_eq(end_time, jiffies)); /* FIXME: extra delay */ ac97->bus->ops->write(ac97, AC97_MASTER, 0x8000); @@ -2273,8 +2269,7 @@ void snd_ac97_resume(ac97_t *ac97) unsigned short val = snd_ac97_read(ac97, AC97_EXTENDED_MID); if (val != 0xffff && (val & 1) != 0) break; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } while (time_after_eq(end_time, jiffies)); } __reset_ready: diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index e33653439cb..4e76c4a636d 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -398,10 +398,8 @@ static int snd_ali_codec_ready( ali_t *codec, res = snd_ali_5451_peek(codec,port); if (! (res & 0x8000)) return 0; - if (sched) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); - } + if (sched) + schedule_timeout_uninterruptible(1); } while (time_after_eq(end_time, jiffies)); snd_ali_5451_poke(codec, port, res & ~0x8000); snd_printdd("ali_codec_ready: codec is not ready.\n "); @@ -421,10 +419,8 @@ static int snd_ali_stimer_ready(ali_t *codec, int sched) dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER); if (dwChk2 != dwChk1) return 0; - if (sched) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); - } + if (sched) + schedule_timeout_uninterruptible(1); } while (time_after_eq(end_time, jiffies)); snd_printk(KERN_ERR "ali_stimer_read: stimer is not ready.\n"); return -EIO; diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index a9314363abd..f5dad9248e3 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -330,8 +330,7 @@ static int snd_atiixp_update_bits(atiixp_t *chip, unsigned int reg, /* delay for one tick */ #define do_delay() do { \ - set_current_state(TASK_UNINTERRUPTIBLE); \ - schedule_timeout(1); \ + schedule_timeout_uninterruptible(1); \ } while (0) diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 210eb676945..0cf20207957 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -307,8 +307,7 @@ static int snd_atiixp_update_bits(atiixp_t *chip, unsigned int reg, /* delay for one tick */ #define do_delay() do { \ - set_current_state(TASK_UNINTERRUPTIBLE); \ - schedule_timeout(1); \ + schedule_timeout_uninterruptible(1); \ } while (0) diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index dc87e0144b5..aea2c47712f 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -523,8 +523,7 @@ static void snd_cs4281_delay(unsigned int delay) delay = 1; end_time = jiffies + delay; do { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } while (time_after_eq(end_time, jiffies)); } else { udelay(delay); @@ -533,8 +532,7 @@ static void snd_cs4281_delay(unsigned int delay) static inline void snd_cs4281_delay_long(void) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } static inline void snd_cs4281_pokeBA0(cs4281_t *chip, unsigned long offset, unsigned int val) diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index b4d0a9c2b0b..92ff7c510f2 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -576,8 +576,7 @@ static void snd_es1370_codec_write(ak4531_t *ak4531, outw(ES_1370_CODEC_WRITE(reg, val), ES_REG(ensoniq, 1370_CODEC)); return; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } while (time_after(end_time, jiffies)); snd_printk(KERN_ERR "codec write timeout, status = 0x%x\n", inl(ES_REG(ensoniq, STATUS))); } diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 47dbe317069..4c7c8d225c7 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -1303,8 +1303,7 @@ static int __devinit snd_fm801_create(snd_card_t * card, do { if ((inw(FM801_REG(chip, AC97_CMD)) & (3<<8)) == (1<<8)) goto __ac97_secondary; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } while (time_after(timeout, jiffies)); snd_printk(KERN_ERR "Primary AC'97 codec not found\n"); snd_fm801_free(chip); @@ -1329,8 +1328,7 @@ static int __devinit snd_fm801_create(snd_card_t * card, goto __ac97_ok; } } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } while (time_after(timeout, jiffies)); } @@ -1343,8 +1341,7 @@ static int __devinit snd_fm801_create(snd_card_t * card, do { if ((inw(FM801_REG(chip, AC97_CMD)) & (3<<8)) == (1<<8)) goto __ac97_ok; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } while (time_after(timeout, jiffies)); snd_printk(KERN_ERR "Primary AC'97 codec not responding\n"); snd_fm801_free(chip); diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c index a5f852b1f57..773a1ecb75c 100644 --- a/sound/pci/ice1712/pontis.c +++ b/sound/pci/ice1712/pontis.c @@ -794,8 +794,7 @@ static int __devinit pontis_init(ice1712_t *ice) /* initialize WM8776 codec */ for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2) wm_put(ice, wm_inits[i], wm_inits[i+1]); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); for (i = 0; i < ARRAY_SIZE(wm_inits2); i += 2) wm_put(ice, wm_inits2[i], wm_inits2[i+1]); diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 383a3ac5ecb..c2f05021532 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -2144,8 +2144,7 @@ static void do_ali_reset(intel8x0_t *chip) } #define do_delay(chip) do {\ - set_current_state(TASK_UNINTERRUPTIBLE);\ - schedule_timeout(1);\ + schedule_timeout_uninterruptible(1);\ } while (0) static int snd_intel8x0_ich_chip_init(intel8x0_t *chip, int probing) diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 49a9f4d0896..acfb197a833 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -890,8 +890,7 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock) */ #define do_delay(chip) do {\ - set_current_state(TASK_UNINTERRUPTIBLE);\ - schedule_timeout(1);\ + schedule_timeout_uninterruptible(1);\ } while (0) static int snd_intel8x0m_ich_chip_init(intel8x0_t *chip, int probing) diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index ad77b414582..99eb76c56f8 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -2046,8 +2046,7 @@ static void snd_m3_ac97_reset(m3_t *chip) outw(0, io + GPIO_DATA); outw(dir | GPO_PRIMARY_AC97, io + GPIO_DIRECTION); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((delay1 * HZ) / 1000); + schedule_timeout_uninterruptible(msecs_to_jiffies(delay1)); outw(GPO_PRIMARY_AC97, io + GPIO_DATA); udelay(5); @@ -2055,8 +2054,7 @@ static void snd_m3_ac97_reset(m3_t *chip) outw(IO_SRAM_ENABLE | SERIAL_AC_LINK_ENABLE, io + RING_BUS_CTRL_A); outw(~0, io + GPIO_MASK); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((delay2 * HZ) / 1000); + schedule_timeout_uninterruptible(msecs_to_jiffies(delay2)); if (! snd_m3_try_read_vendor(chip)) break; @@ -2101,8 +2099,7 @@ static int __devinit snd_m3_mixer(m3_t *chip) /* seems ac97 PCM needs initialization.. hack hack.. */ snd_ac97_write(chip->ac97, AC97_PCM, 0x8000 | (15 << 8) | 15); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ / 10); + schedule_timeout_uninterruptible(msecs_to_jiffies(100)); snd_ac97_write(chip->ac97, AC97_PCM, 0); memset(&id, 0, sizeof(id)); diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 1a62c7f6c52..c341c99ec78 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -451,8 +451,7 @@ static int mixart_sync_nonblock_events(mixart_mgr_t *mgr) snd_printk(KERN_ERR "mixart: cannot process nonblock events!\n"); return -EBUSY; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } return 0; } diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 08226f523eb..b9b93c7faaf 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -3207,8 +3207,7 @@ static inline void snd_trident_free_gameport(trident_t *chip) { } */ static inline void do_delay(trident_t *chip) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } /* diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 9b2bea866d1..523eace250f 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -2027,8 +2027,7 @@ static int snd_via82xx_chip_init(via82xx_t *chip) pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ break; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } while (time_before(jiffies, end_time)); if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) @@ -2047,8 +2046,7 @@ static int snd_via82xx_chip_init(via82xx_t *chip) chip->ac97_secondary = 1; goto __ac97_ok2; } - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_interruptible(1); } while (time_before(jiffies, end_time)); /* This is ok, the most of motherboards have only one codec */ diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index bc7330ace96..011f0fb63bf 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -968,8 +968,7 @@ static int snd_via82xx_chip_init(via82xx_t *chip) pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ break; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } while (time_before(jiffies, end_time)); if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) @@ -987,8 +986,7 @@ static int snd_via82xx_chip_init(via82xx_t *chip) chip->ac97_secondary = 1; goto __ac97_ok2; } - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_interruptible(1); } while (time_before(jiffies, end_time)); /* This is ok, the most of motherboards have only one codec */ diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index a53117733d5..88a43e091d7 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -92,7 +92,7 @@ static int snd_ymfpci_codec_ready(ymfpci_t *chip, int secondary) if ((snd_ymfpci_readw(chip, reg) & 0x8000) == 0) return 0; set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } while (time_before(jiffies, end_time)); snd_printk(KERN_ERR "codec_ready: codec %i is not ready [0x%x]\n", secondary, snd_ymfpci_readw(chip, reg)); return -EBUSY; @@ -728,8 +728,7 @@ static void snd_ymfpci_irq_wait(ymfpci_t *chip) init_waitqueue_entry(&wait, current); add_wait_queue(&chip->interrupt_sleep, &wait); atomic_inc(&chip->interrupt_sleep_count); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/20); + schedule_timeout_uninterruptible(msecs_to_jiffies(50)); remove_wait_queue(&chip->interrupt_sleep, &wait); } } diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index fce6ad62df6..8818918c423 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -838,8 +838,7 @@ static int wait_clear_urbs(snd_usb_substream_t *subs) } if (! alive) break; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } while (time_before(jiffies, end_time)); if (alive) snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive); -- cgit v1.2.3 From fc58422ad95a0f4936ead538e0b946aee5a4f98c Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 24 Oct 2005 15:11:28 +0200 Subject: [ALSA] Big kfree NULL check cleanup - sound Modules: AD1889 driver,RME9652 driver This is the sound/ part of the big kfree cleanup patch. Remove pointless checks for NULL prior to calling kfree() in sound/. Signed-off-by: Jesper Juhl Signed-off-by: Andrew Morton Signed-off-by: Takashi Iwai --- sound/pci/ad1889.c | 5 ++--- sound/pci/rme9652/hdspm.c | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index d7d99a25c5e..e72ccd1a004 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c @@ -50,7 +50,7 @@ #include "ad1889.h" #include "ac97/ac97_id.h" -#define AD1889_DRVVER "$Revision: 1.3 $" +#define AD1889_DRVVER "$Revision: 1.4 $" MODULE_AUTHOR("Kyle McMartin , Thibaut Varene "); MODULE_DESCRIPTION("Analog Devices AD1889 ALSA sound driver"); @@ -982,8 +982,7 @@ snd_ad1889_create(snd_card_t *card, return 0; free_and_ret: - if (chip) - kfree(chip); + kfree(chip); pci_disable_device(pci); return err; diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index fc3f3283ff3..60a1141f132 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -3563,8 +3563,7 @@ static int snd_hdspm_free(hdspm_t * hdspm) free_irq(hdspm->irq, (void *) hdspm); - if (hdspm->mixer) - kfree(hdspm->mixer); + kfree(hdspm->mixer); if (hdspm->iobase) iounmap(hdspm->iobase); -- cgit v1.2.3 From 3939e7142da722324ab07d244a9736b0fa59c362 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 24 Oct 2005 17:02:03 +0200 Subject: [ALSA] clean up device types symbols Modules: ALSA Core,ALSA Minor Numbers Remove the unused and undefined symbols SNDRV_DEVICE_TYPE_{MIXER, PCM_PLOOP,PCM_CLOOP}, and introduce a new symbol SNDRV_MINOR_GLOBAL for non-card-specific devices like the sequencer or the timer. Signed-off-by: Clemens Ladisch --- include/sound/minors.h | 8 +++----- sound/core/sound.c | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/include/sound/minors.h b/include/sound/minors.h index b7b0d830944..a17b5c9961b 100644 --- a/include/sound/minors.h +++ b/include/sound/minors.h @@ -27,8 +27,9 @@ #define SNDRV_MINOR(card, dev) (((card) << 5) | (dev)) #define SNDRV_MINOR_CONTROL 0 /* 0 - 0 */ -#define SNDRV_MINOR_SEQUENCER 1 -#define SNDRV_MINOR_TIMER (1+32) +#define SNDRV_MINOR_GLOBAL 1 /* 1 */ +#define SNDRV_MINOR_SEQUENCER (SNDRV_MINOR_GLOBAL + 0 * 32) +#define SNDRV_MINOR_TIMER (SNDRV_MINOR_GLOBAL + 1 * 32) #define SNDRV_MINOR_HWDEP 4 /* 4 - 7 */ #define SNDRV_MINOR_HWDEPS 4 #define SNDRV_MINOR_RAWMIDI 8 /* 8 - 15 */ @@ -39,12 +40,9 @@ #define SNDRV_DEVICE_TYPE_CONTROL SNDRV_MINOR_CONTROL #define SNDRV_DEVICE_TYPE_HWDEP SNDRV_MINOR_HWDEP -#define SNDRV_DEVICE_TYPE_MIXER SNDRV_MINOR_MIXER #define SNDRV_DEVICE_TYPE_RAWMIDI SNDRV_MINOR_RAWMIDI #define SNDRV_DEVICE_TYPE_PCM_PLAYBACK SNDRV_MINOR_PCM_PLAYBACK -#define SNDRV_DEVICE_TYPE_PCM_PLOOP SNDRV_MINOR_PCM_PLOOP #define SNDRV_DEVICE_TYPE_PCM_CAPTURE SNDRV_MINOR_PCM_CAPTURE -#define SNDRV_DEVICE_TYPE_PCM_CLOOP SNDRV_MINOR_PCM_CLOOP #define SNDRV_DEVICE_TYPE_SEQUENCER SNDRV_MINOR_SEQUENCER #define SNDRV_DEVICE_TYPE_TIMER SNDRV_MINOR_TIMER diff --git a/sound/core/sound.c b/sound/core/sound.c index dee602245fe..1139dd8ca8e 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -130,7 +130,7 @@ static int snd_open(struct inode *inode, struct file *file) struct file_operations *old_fops; int err = 0; - if (dev != SNDRV_MINOR_SEQUENCER && dev != SNDRV_MINOR_TIMER) { + if (dev != SNDRV_MINOR_GLOBAL) { if (snd_cards[card] == NULL) { #ifdef CONFIG_KMOD snd_request_card(card); @@ -287,7 +287,7 @@ static void snd_minor_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buf for (card = 0; card < SNDRV_CARDS; card++) { list_for_each(list, &snd_minors_hash[card]) { mptr = list_entry(list, snd_minor_t, list); - if (SNDRV_MINOR_DEVICE(mptr->number) != SNDRV_MINOR_SEQUENCER) { + if (SNDRV_MINOR_DEVICE(mptr->number) != SNDRV_MINOR_GLOBAL) { if ((device = mptr->device) >= 0) snd_iprintf(buffer, "%3i: [%i-%2i]: %s\n", mptr->number, card, device, mptr->comment); else -- cgit v1.2.3 From c8a7e5c40ddcf98f1026581e411b05ff86491907 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 24 Oct 2005 17:02:46 +0200 Subject: [ALSA] usb-audio: remove superfluous include Modules: USB generic driver Remove a superfluous include of the sound/minors.h header. Signed-off-by: Clemens Ladisch --- sound/usb/usbmidi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c index 2885b8974da..f8aa662562a 100644 --- a/sound/usb/usbmidi.c +++ b/sound/usb/usbmidi.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include "usbaudio.h" -- cgit v1.2.3 From f1902860161ff212c515e7ea629e880fec856a37 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 24 Oct 2005 17:05:03 +0200 Subject: [ALSA] fix improper CONFIG_SND_MAJOR usage Modules: HWDEP Midlevel,PCM Midlevel,RawMidi Midlevel,ALSA Core Replace usage of CONFIG_SND_MAJOR with snd_major, where appropriate. Signed-off-by: Clemens Ladisch --- include/sound/core.h | 1 + sound/core/hwdep.c | 10 +++------- sound/core/pcm_native.c | 1 - sound/core/rawmidi.c | 12 ++++-------- 4 files changed, 8 insertions(+), 16 deletions(-) diff --git a/include/sound/core.h b/include/sound/core.h index 642ddfbc632..2be65ad2fd8 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -255,6 +255,7 @@ typedef struct _snd_minor snd_minor_t; /* sound.c */ +extern int snd_major; extern int snd_ecards_limit; void snd_request_card(int card); diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 9383f1294fb..e91cee35a4b 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c @@ -81,20 +81,16 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) int err; wait_queue_t wait; - switch (major) { - case CONFIG_SND_MAJOR: + if (major == snd_major) { cardnum = SNDRV_MINOR_CARD(iminor(inode)); device = SNDRV_MINOR_DEVICE(iminor(inode)) - SNDRV_MINOR_HWDEP; - break; #ifdef CONFIG_SND_OSSEMUL - case SOUND_MAJOR: + } else if (major == SOUND_MAJOR) { cardnum = SNDRV_MINOR_OSS_CARD(iminor(inode)); device = 0; - break; #endif - default: + } else return -ENXIO; - } cardnum %= SNDRV_CARDS; device %= SNDRV_MINOR_HWDEPS; hw = snd_hwdep_devices[(cardnum * SNDRV_MINOR_HWDEPS) + device]; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index a1924f12d8f..16e252f5495 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1522,7 +1522,6 @@ static int snd_pcm_drop(snd_pcm_substream_t *substream) /* WARNING: Don't forget to fput back the file */ -extern int snd_major; static struct file *snd_pcm_file_fd(int fd) { struct file *file; diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 7c20eafecb8..d033e61c05c 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -378,24 +378,20 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) struct list_head *list; snd_ctl_file_t *kctl; - switch (maj) { - case CONFIG_SND_MAJOR: + if (maj == snd_major) { cardnum = SNDRV_MINOR_CARD(iminor(inode)); cardnum %= SNDRV_CARDS; device = SNDRV_MINOR_DEVICE(iminor(inode)) - SNDRV_MINOR_RAWMIDI; device %= SNDRV_MINOR_RAWMIDIS; - break; #ifdef CONFIG_SND_OSSEMUL - case SOUND_MAJOR: + } else if (maj == SOUND_MAJOR) { cardnum = SNDRV_MINOR_OSS_CARD(iminor(inode)); cardnum %= SNDRV_CARDS; device = SNDRV_MINOR_OSS_DEVICE(iminor(inode)) == SNDRV_MINOR_OSS_MIDI ? midi_map[cardnum] : amidi_map[cardnum]; - break; #endif - default: + } else return -ENXIO; - } rmidi = snd_rawmidi_devices[(cardnum * SNDRV_RAWMIDI_DEVICES) + device]; if (rmidi == NULL) @@ -411,7 +407,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) if (err < 0) return -ENODEV; fflags = snd_rawmidi_file_flags(file); - if ((file->f_flags & O_APPEND) || maj != CONFIG_SND_MAJOR) /* OSS emul? */ + if ((file->f_flags & O_APPEND) || maj == SOUND_MAJOR) /* OSS emul? */ fflags |= SNDRV_RAWMIDI_LFLG_APPEND; fflags |= SNDRV_RAWMIDI_LFLG_NOOPENLOCK; rawmidi_file = kmalloc(sizeof(*rawmidi_file), GFP_KERNEL); -- cgit v1.2.3 From aa92c4af15224d8a96343286cdcf7c73b2ad3809 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 25 Oct 2005 10:58:59 +0200 Subject: [ALSA] Fix a typo in the last fix Modules: ALSA Core Fix a typo (bogus check) in the last patch to fix Oops with suspend/resume. Signed-off-by: Takashi Iwai --- sound/core/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/core/init.c b/sound/core/init.c index b98f7c6310c..d9ee27ae9a5 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -841,7 +841,7 @@ static int snd_generic_resume(struct device *dev) card = get_snd_generic_card(dev); if (card->power_state == SNDRV_CTL_POWER_D0) return 0; - if (card->pm_suspend) + if (card->pm_resume) card->pm_resume(card); snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; -- cgit v1.2.3 From fc20773329c993ec7d1b2c65618351f057d9d679 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 25 Oct 2005 11:10:55 +0200 Subject: [ALSA] Fix emu10k1 synth problems. Modules: EMU10K1/EMU10K2 driver,Common EMU synth This patch fixes problems with voices cutting off or not sounding at all. Signed-off-by: Tim Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/emu10k1_callback.c | 4 ++-- sound/synth/emux/emux_synth.c | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c index 7cf2f908eed..6589bf24abc 100644 --- a/sound/pci/emu10k1/emu10k1_callback.c +++ b/sound/pci/emu10k1/emu10k1_callback.c @@ -241,7 +241,7 @@ lookup_voices(snd_emux_t *emu, emu10k1_t *hw, best_voice_t *best, int active_onl else if (state == SNDRV_EMUX_ST_RELEASED || state == SNDRV_EMUX_ST_PENDING) { bp = best + V_RELEASED; -#if 0 +#if 1 val = snd_emu10k1_ptr_read(hw, CVCF_CURRENTVOL, vp->ch); if (! val) bp = best + V_OFF; @@ -349,7 +349,7 @@ start_voice(snd_emux_voice_t *vp) } /* channel to be silent and idle */ - snd_emu10k1_ptr_write(hw, DCYSUSV, ch, 0x0080); + snd_emu10k1_ptr_write(hw, DCYSUSV, ch, 0x0000); snd_emu10k1_ptr_write(hw, VTFT, ch, 0x0000FFFF); snd_emu10k1_ptr_write(hw, CVCF, ch, 0x0000FFFF); snd_emu10k1_ptr_write(hw, PTRX, ch, 0); diff --git a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c index 751bf1272af..bd71b73be65 100644 --- a/sound/synth/emux/emux_synth.c +++ b/sound/synth/emux/emux_synth.c @@ -171,7 +171,6 @@ snd_emux_note_off(void *p, int note, int vel, snd_midi_channel_t *chan) vp = &emu->voices[ch]; if (STATE_IS_PLAYING(vp->state) && vp->chan == chan && vp->key == note) { - vp->time = emu->use_time++; vp->state = SNDRV_EMUX_ST_RELEASED; if (vp->ontime == jiffies) { /* if note-off is sent too shortly after -- cgit v1.2.3 From d91c64c8279501f439feae9042eccd0bbe484265 Mon Sep 17 00:00:00 2001 From: Andreas Mohr Date: Tue, 25 Oct 2005 11:17:45 +0200 Subject: [ALSA] AZT3328 driver update Modules: AZT3328 driver this is now an even much more reworked patch (#3) for my azt3328.c ALSA driver. IOW I spent another 4 evenings to get the sequencer timer to work properly (my head is still hurting) and do lots of other cleanups. Note that despite the extensive sequencer timer additions, the driver object is still only 2kB bigger than the previous version, due to those many optimizations... Changes in version #3: - fully working ALSA sequencer timer support for the card's 1024000Hz DirectX timer (downscaling adjustable via seqtimer_scaling module param) - an insane amount of code optimizations - many, many cleanups Changes in version #2: - FOUND the 1us DirectX timer area (yay!), made the code respect it properly - renamed some 'weird' mixer control names according to ControlNames.txt - cleanup unneeded debug messages, reformatting - improved I/O register documentation - constified many more structs Changes in version #1: - improves/fixes some fatal playback/recording interaction - improves IRQ handler performance (and actually fixes some weird code) - coalesces some I/O accesses - slightly improves I/O interface documentation - improves/fixes logging - defines out some less important debug code - constifies some data Signed-off-by: Andreas Mohr Signed-off-by: Takashi Iwai --- sound/pci/azt3328.c | 981 +++++++++++++++++++++++++++++++++++----------------- sound/pci/azt3328.h | 135 ++++---- 2 files changed, 728 insertions(+), 388 deletions(-) diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 8260079a25f..da99b1be2e8 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -1,6 +1,6 @@ /* * azt3328.c - driver for Aztech AZF3328 based soundcards (e.g. PCI168). - * Copyright (C) 2002 by Andreas Mohr + * Copyright (C) 2002, 2005 by Andreas Mohr * * Framework borrowed from Bart Hartgers's als4000.c. * Driver developed on PCI168 AP(W) version (PCI rev. 10, subsystem ID 1801), @@ -46,7 +46,7 @@ * - MPU401 (+ legacy address support) FIXME: how to enable legacy addr?? * - game port (legacy address support) * - built-in General DirectX timer having a 20 bits counter - * with 1us resolution (FIXME: where is it?) + * with 1us resolution (see below!) * - I2S serial port for external DAC * - supports 33MHz PCI spec 2.1, PCI power management 1.0, compliant with ACPI * - supports hardware volume control @@ -55,13 +55,23 @@ * required for Microsoft's logo compliance (FIXME: where?) * - PCI168 AP(W) card: power amplifier with 4 Watts/channel at 4 Ohms * + * Note that this driver now is actually *better* than the Windows driver, + * since it additionally supports the card's 1MHz DirectX timer - just try + * the following snd-seq module parameters etc.: + * - options snd-seq seq_default_timer_class=2 seq_default_timer_sclass=0 + * seq_default_timer_card=0 seq_client_load=1 seq_default_timer_device=0 + * seq_default_timer_subdevice=0 seq_default_timer_resolution=1000000 + * - "timidity -iAv -B2,8 -Os -EFreverb=0" + * - "pmidi -p 128:0 jazz.mid" + * * Certain PCI versions of this card are susceptible to DMA traffic underruns * in some systems (resulting in sound crackling/clicking/popping), * probably because they don't have a DMA FIFO buffer or so. * Overview (PCI ID/PCI subID/PCI rev.): * - no DMA crackling on SiS735: 0x50DC/0x1801/16 * - unknown performance: 0x50DC/0x1801/10 - * + * (well, it's not bad on an Athlon 1800 with now very optimized IRQ handler) + * * Crackling happens with VIA chipsets or, in my case, an SiS735, which is * supposed to be very fast and supposed to get rid of crackling much * better than a VIA, yet ironically I still get crackling, like many other @@ -76,18 +86,13 @@ * - Disable ACPI/power management/"Auto Detect RAM/PCI Clk" in BIOS * * BUGS - * - when Ctrl-C'ing mpg321, the playback loops a bit - * (premature DMA playback reset?) - * - full-duplex sometimes breaks (IRQ management issues?). - * Once even a spontaneous REBOOT happened!!! + * - full-duplex might *still* be problematic, not fully tested recently * * TODO * - test MPU401 MIDI playback etc. - * - power management (CONFIG_PM). See e.g. intel8x0 or cs4281. + * - power management. See e.g. intel8x0 or cs4281. * This would be nice since the chip runs a bit hot, and it's *required* - * anyway for proper ACPI power management. In other words: rest - * assured that I *will* implement this very soon; as soon as Linux 2.5.x - * has power management that's bugfree enough to work properly on my desktop. + * anyway for proper ACPI power management. * - figure out what all unknown port bits are responsible for */ @@ -108,7 +113,7 @@ #include #include "azt3328.h" -MODULE_AUTHOR("Andreas Mohr "); +MODULE_AUTHOR("Andreas Mohr "); MODULE_DESCRIPTION("Aztech AZF3328 (PCI168)"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}"); @@ -122,6 +127,7 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}"); #define DEBUG_MIXER 0 #define DEBUG_PLAY_REC 0 #define DEBUG_IO 0 +#define DEBUG_TIMER 0 #define MIXER_TESTING 0 #if DEBUG_MISC @@ -132,8 +138,8 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}"); #if DEBUG_CALLS #define snd_azf3328_dbgcalls(format, args...) printk(format, ##args) -#define snd_azf3328_dbgcallenter() printk(KERN_ERR "entering %s\n", __FUNCTION__) -#define snd_azf3328_dbgcallleave() printk(KERN_ERR "leaving %s\n", __FUNCTION__) +#define snd_azf3328_dbgcallenter() printk(KERN_ERR "--> %s\n", __FUNCTION__) +#define snd_azf3328_dbgcallleave() printk(KERN_ERR "<-- %s\n", __FUNCTION__) #else #define snd_azf3328_dbgcalls(format, args...) #define snd_azf3328_dbgcallenter() @@ -152,13 +158,12 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}"); #define snd_azf3328_dbgplay(format, args...) #endif -#if DEBUG_IO -#define snd_azf3328_dbgio(chip, where) \ - printk(KERN_ERR "%s: IDX_IO_PLAY_FLAGS %04x, IDX_IO_PLAY_IRQMASK %04x, IDX_IO_IRQSTATUS %04x\n", where, inw(chip->codec_port+IDX_IO_PLAY_FLAGS), inw(chip->codec_port+IDX_IO_PLAY_IRQMASK), inw(chip->codec_port+IDX_IO_IRQSTATUS)) +#if DEBUG_MISC +#define snd_azf3328_dbgtimer(format, args...) printk(KERN_ERR format, ##args) #else -#define snd_azf3328_dbgio(chip, where) -#endif - +#define snd_azf3328_dbgtimer(format, args...) +#endif + static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for AZF3328 soundcard."); @@ -177,35 +182,40 @@ module_param_array(joystick, bool, NULL, 0444); MODULE_PARM_DESC(joystick, "Enable joystick for AZF3328 soundcard."); #endif -typedef struct _snd_azf3328 azf3328_t; - -struct _snd_azf3328 { - int irq; +static int seqtimer_scaling = 128; +module_param(seqtimer_scaling, int, 0444); +MODULE_PARM_DESC(seqtimer_scaling, "Set 1024000Hz sequencer timer scale factor (lockup danger!). Default 128."); +typedef struct _snd_azf3328 { + /* often-used fields towards beginning, then grouped */ unsigned long codec_port; unsigned long io2_port; unsigned long mpu_port; unsigned long synth_port; unsigned long mixer_port; -#ifdef SUPPORT_JOYSTICK - struct gameport *gameport; -#endif - - struct pci_dev *pci; - snd_card_t *card; + spinlock_t reg_lock; + snd_timer_t *timer; + snd_pcm_t *pcm; - snd_rawmidi_t *rmidi; snd_pcm_substream_t *playback_substream; snd_pcm_substream_t *capture_substream; unsigned int is_playing; unsigned int is_recording; - spinlock_t reg_lock; -}; + snd_card_t *card; + snd_rawmidi_t *rmidi; + +#ifdef SUPPORT_JOYSTICK + struct gameport *gameport; +#endif -static struct pci_device_id snd_azf3328_ids[] = { + struct pci_dev *pci; + int irq; +} azf3328_t; + +static const struct pci_device_id snd_azf3328_ids[] = { { 0x122D, 0x50DC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* PCI168/3328 */ { 0x122D, 0x80DA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* 3328 */ { 0, } @@ -213,57 +223,90 @@ static struct pci_device_id snd_azf3328_ids[] = { MODULE_DEVICE_TABLE(pci, snd_azf3328_ids); -static inline void snd_azf3328_io2_write(azf3328_t *chip, int reg, unsigned char value) +static inline void +snd_azf3328_codec_outb(const azf3328_t *chip, int reg, u8 value) +{ + outb(value, chip->codec_port + reg); +} + +static inline u8 +snd_azf3328_codec_inb(const azf3328_t *chip, int reg) +{ + return inb(chip->codec_port + reg); +} + +static inline void +snd_azf3328_codec_outw(const azf3328_t *chip, int reg, u16 value) +{ + outw(value, chip->codec_port + reg); +} + +static inline u16 +snd_azf3328_codec_inw(const azf3328_t *chip, int reg) +{ + return inw(chip->codec_port + reg); +} + +static inline void +snd_azf3328_codec_outl(const azf3328_t *chip, int reg, u32 value) +{ + outl(value, chip->codec_port + reg); +} + +static inline void +snd_azf3328_io2_outb(const azf3328_t *chip, int reg, u8 value) { outb(value, chip->io2_port + reg); } -static inline unsigned char snd_azf3328_io2_read(azf3328_t *chip, int reg) +static inline u8 +snd_azf3328_io2_inb(const azf3328_t *chip, int reg) { return inb(chip->io2_port + reg); } -static void snd_azf3328_mixer_write(azf3328_t *chip, int reg, unsigned long value, int type) +static inline void +snd_azf3328_mixer_outw(const azf3328_t *chip, int reg, u16 value) { - switch(type) { - case WORD_VALUE: - outw(value, chip->mixer_port + reg); - break; - case DWORD_VALUE: - outl(value, chip->mixer_port + reg); - break; - case BYTE_VALUE: - outb(value, chip->mixer_port + reg); - break; - } + outw(value, chip->mixer_port + reg); +} + +static inline u16 +snd_azf3328_mixer_inw(const azf3328_t *chip, int reg) +{ + return inw(chip->mixer_port + reg); } -static void snd_azf3328_mixer_set_mute(azf3328_t *chip, int reg, int do_mute) +static void +snd_azf3328_mixer_set_mute(const azf3328_t *chip, int reg, int do_mute) { + unsigned long portbase = chip->mixer_port + reg + 1; unsigned char oldval; /* the mute bit is on the *second* (i.e. right) register of a * left/right channel setting */ - oldval = inb(chip->mixer_port + reg + 1); + oldval = inb(portbase); if (do_mute) oldval |= 0x80; else oldval &= ~0x80; - outb(oldval, chip->mixer_port + reg + 1); + outb(oldval, portbase); } -static void snd_azf3328_mixer_write_volume_gradually(azf3328_t *chip, int reg, unsigned char dst_vol_left, unsigned char dst_vol_right, int chan_sel, int delay) +static void +snd_azf3328_mixer_write_volume_gradually(const azf3328_t *chip, int reg, unsigned char dst_vol_left, unsigned char dst_vol_right, int chan_sel, int delay) { + unsigned long portbase = chip->mixer_port + reg; unsigned char curr_vol_left = 0, curr_vol_right = 0; int left_done = 0, right_done = 0; snd_azf3328_dbgcallenter(); if (chan_sel & SET_CHAN_LEFT) - curr_vol_left = inb(chip->mixer_port + reg + 1); + curr_vol_left = inb(portbase + 1); else left_done = 1; if (chan_sel & SET_CHAN_RIGHT) - curr_vol_right = inb(chip->mixer_port + reg + 0); + curr_vol_right = inb(portbase + 0); else right_done = 1; @@ -284,7 +327,7 @@ static void snd_azf3328_mixer_write_volume_gradually(azf3328_t *chip, int reg, u curr_vol_left++; else left_done = 1; - outb(curr_vol_left, chip->mixer_port + reg + 1); + outb(curr_vol_left, portbase + 1); } if (!right_done) { @@ -298,7 +341,7 @@ static void snd_azf3328_mixer_write_volume_gradually(azf3328_t *chip, int reg, u /* during volume change, the right channel is crackling * somewhat more than the left channel, unfortunately. * This seems to be a hardware issue. */ - outb(curr_vol_right, chip->mixer_port + reg + 0); + outb(curr_vol_right, portbase + 0); } if (delay) mdelay(delay); @@ -320,7 +363,11 @@ typedef struct azf3328_mixer_reg { } azf3328_mixer_reg_t; #define COMPOSE_MIXER_REG(reg,lchan_shift,rchan_shift,mask,invert,stereo,enum_c) \ - ((reg) | (lchan_shift << 8) | (rchan_shift << 12) | (mask << 16) | (invert << 24) | (stereo << 25) | (enum_c << 26)) + ((reg) | (lchan_shift << 8) | (rchan_shift << 12) | \ + (mask << 16) | \ + (invert << 24) | \ + (stereo << 25) | \ + (enum_c << 26)) static void snd_azf3328_mixer_reg_decode(azf3328_mixer_reg_t *r, unsigned long val) { @@ -372,13 +419,15 @@ static void snd_azf3328_mixer_reg_decode(azf3328_mixer_reg_t *r, unsigned long v .private_value = COMPOSE_MIXER_REG(reg, shift, 0, 0, 0, 0, enum_c), \ } -static int snd_azf3328_info_mixer(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +static int +snd_azf3328_info_mixer(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) { azf3328_mixer_reg_t reg; snd_azf3328_dbgcallenter(); snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); - uinfo->type = reg.mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->type = reg.mask == 1 ? + SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = reg.stereo + 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = reg.mask; @@ -386,7 +435,8 @@ static int snd_azf3328_info_mixer(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t return 0; } -static int snd_azf3328_get_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int +snd_azf3328_get_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { azf3328_t *chip = snd_kcontrol_chip(kcontrol); azf3328_mixer_reg_t reg; @@ -395,7 +445,7 @@ static int snd_azf3328_get_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t snd_azf3328_dbgcallenter(); snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); - oreg = inw(chip->mixer_port + reg.reg); + oreg = snd_azf3328_mixer_inw(chip, reg.reg); val = (oreg >> reg.lchan_shift) & reg.mask; if (reg.invert) val = reg.mask - val; @@ -406,12 +456,17 @@ static int snd_azf3328_get_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t val = reg.mask - val; ucontrol->value.integer.value[1] = val; } - snd_azf3328_dbgmixer("get: %02x is %04x -> vol %02lx|%02lx (shift %02d|%02d, mask %02x, inv. %d, stereo %d)\n", reg.reg, oreg, ucontrol->value.integer.value[0], ucontrol->value.integer.value[1], reg.lchan_shift, reg.rchan_shift, reg.mask, reg.invert, reg.stereo); + snd_azf3328_dbgmixer("get: %02x is %04x -> vol %02lx|%02lx " + "(shift %02d|%02d, mask %02x, inv. %d, stereo %d)\n", + reg.reg, oreg, + ucontrol->value.integer.value[0], ucontrol->value.integer.value[1], + reg.lchan_shift, reg.rchan_shift, reg.mask, reg.invert, reg.stereo); snd_azf3328_dbgcallleave(); return 0; } -static int snd_azf3328_put_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int +snd_azf3328_put_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { azf3328_t *chip = snd_kcontrol_chip(kcontrol); azf3328_mixer_reg_t reg; @@ -419,7 +474,7 @@ static int snd_azf3328_put_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t snd_azf3328_dbgcallenter(); snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); - oreg = inw(chip->mixer_port + reg.reg); + oreg = snd_azf3328_mixer_inw(chip, reg.reg); val = ucontrol->value.integer.value[0] & reg.mask; if (reg.invert) val = reg.mask - val; @@ -433,24 +488,37 @@ static int snd_azf3328_put_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t nreg |= (val << reg.rchan_shift); } if (reg.mask >= 0x07) /* it's a volume control, so better take care */ - snd_azf3328_mixer_write_volume_gradually(chip, reg.reg, nreg >> 8, nreg & 0xff, SET_CHAN_LEFT|SET_CHAN_RIGHT, 0); /* just set both channels, doesn't matter */ + snd_azf3328_mixer_write_volume_gradually( + chip, reg.reg, nreg >> 8, nreg & 0xff, + /* just set both channels, doesn't matter */ + SET_CHAN_LEFT|SET_CHAN_RIGHT, + 0); else - outw(nreg, chip->mixer_port + reg.reg); + snd_azf3328_mixer_outw(chip, reg.reg, nreg); - snd_azf3328_dbgmixer("put: %02x to %02lx|%02lx, oreg %04x; shift %02d|%02d -> nreg %04x; after: %04x\n", reg.reg, ucontrol->value.integer.value[0], ucontrol->value.integer.value[1], oreg, reg.lchan_shift, reg.rchan_shift, nreg, inw(chip->mixer_port + reg.reg)); + snd_azf3328_dbgmixer("put: %02x to %02lx|%02lx, " + "oreg %04x; shift %02d|%02d -> nreg %04x; after: %04x\n", + reg.reg, ucontrol->value.integer.value[0], ucontrol->value.integer.value[1], + oreg, reg.lchan_shift, reg.rchan_shift, + nreg, snd_azf3328_mixer_inw(chip, reg.reg)); snd_azf3328_dbgcallleave(); return (nreg != oreg); } -static int snd_azf3328_info_mixer_enum(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) +static int +snd_azf3328_info_mixer_enum(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) { - azf3328_mixer_reg_t reg; - static char *texts1[2] = { "ModemOut1", "ModemOut2" }; - static char *texts2[2] = { "MonoSelectSource1", "MonoSelectSource2" }; - static char *texts3[8] = { - "Mic", "CD", "Video", "Aux", "Line", - "Mix", "Mix Mono", "Phone" + static const char * const texts1[] = { + "ModemOut1", "ModemOut2" + }; + static const char * const texts2[] = { + "MonoSelectSource1", "MonoSelectSource2" + }; + static const char * const texts3[] = { + "Mic", "CD", "Video", "Aux", + "Line", "Mix", "Mix Mono", "Phone" }; + azf3328_mixer_reg_t reg; snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; @@ -471,14 +539,15 @@ static int snd_azf3328_info_mixer_enum(snd_kcontrol_t *kcontrol, snd_ctl_elem_in return 0; } -static int snd_azf3328_get_mixer_enum(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int +snd_azf3328_get_mixer_enum(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { - azf3328_mixer_reg_t reg; azf3328_t *chip = snd_kcontrol_chip(kcontrol); + azf3328_mixer_reg_t reg; unsigned short val; snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); - val = inw(chip->mixer_port + reg.reg); + val = snd_azf3328_mixer_inw(chip, reg.reg); if (reg.reg == IDX_MIXER_REC_SELECT) { ucontrol->value.enumerated.item[0] = (val >> 8) & (reg.enum_c - 1); @@ -486,18 +555,22 @@ static int snd_azf3328_get_mixer_enum(snd_kcontrol_t * kcontrol, snd_ctl_elem_va } else ucontrol->value.enumerated.item[0] = (val >> reg.lchan_shift) & (reg.enum_c - 1); - snd_azf3328_dbgmixer("get_enum: %02x is %04x -> %d|%d (shift %02d, enum_c %d)\n", reg.reg, val, ucontrol->value.enumerated.item[0], ucontrol->value.enumerated.item[1], reg.lchan_shift, reg.enum_c); + + snd_azf3328_dbgmixer("get_enum: %02x is %04x -> %d|%d (shift %02d, enum_c %d)\n", + reg.reg, val, ucontrol->value.enumerated.item[0], ucontrol->value.enumerated.item[1], + reg.lchan_shift, reg.enum_c); return 0; } -static int snd_azf3328_put_mixer_enum(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int +snd_azf3328_put_mixer_enum(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { - azf3328_mixer_reg_t reg; azf3328_t *chip = snd_kcontrol_chip(kcontrol); + azf3328_mixer_reg_t reg; unsigned int oreg, nreg, val; snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); - oreg = inw(chip->mixer_port + reg.reg); + oreg = snd_azf3328_mixer_inw(chip, reg.reg); val = oreg; if (reg.reg == IDX_MIXER_REC_SELECT) { @@ -514,19 +587,19 @@ static int snd_azf3328_put_mixer_enum(snd_kcontrol_t * kcontrol, snd_ctl_elem_va val &= ~((reg.enum_c - 1) << reg.lchan_shift); val |= (ucontrol->value.enumerated.item[0] << reg.lchan_shift); } - outw(val, chip->mixer_port + reg.reg); + snd_azf3328_mixer_outw(chip, reg.reg, val); nreg = val; snd_azf3328_dbgmixer("put_enum: %02x to %04x, oreg %04x\n", reg.reg, val, oreg); return (nreg != oreg); } -static snd_kcontrol_new_t snd_azf3328_mixer_controls[] __devinitdata = { +static const snd_kcontrol_new_t snd_azf3328_mixer_controls[] __devinitdata = { AZF3328_MIXER_SWITCH("Master Playback Switch", IDX_MIXER_PLAY_MASTER, 15, 1), AZF3328_MIXER_VOL_STEREO("Master Playback Volume", IDX_MIXER_PLAY_MASTER, 0x1f, 1), AZF3328_MIXER_SWITCH("Wave Playback Switch", IDX_MIXER_WAVEOUT, 15, 1), AZF3328_MIXER_VOL_STEREO("Wave Playback Volume", IDX_MIXER_WAVEOUT, 0x1f, 1), - AZF3328_MIXER_SWITCH("Wave Playback 3D Bypass", IDX_MIXER_ADVCTL2, 7, 1), + AZF3328_MIXER_SWITCH("Wave 3D Bypass Playback Switch", IDX_MIXER_ADVCTL2, 7, 1), AZF3328_MIXER_SWITCH("FM Playback Switch", IDX_MIXER_FMSYNTH, 15, 1), AZF3328_MIXER_VOL_STEREO("FM Playback Volume", IDX_MIXER_FMSYNTH, 0x1f, 1), AZF3328_MIXER_SWITCH("CD Playback Switch", IDX_MIXER_CDAUDIO, 15, 1), @@ -539,8 +612,8 @@ static snd_kcontrol_new_t snd_azf3328_mixer_controls[] __devinitdata = { AZF3328_MIXER_SWITCH("Mic Boost (+20dB)", IDX_MIXER_MIC, 6, 0), AZF3328_MIXER_SWITCH("Line Playback Switch", IDX_MIXER_LINEIN, 15, 1), AZF3328_MIXER_VOL_STEREO("Line Playback Volume", IDX_MIXER_LINEIN, 0x1f, 1), - AZF3328_MIXER_SWITCH("PCBeep Playback Switch", IDX_MIXER_PCBEEP, 15, 1), - AZF3328_MIXER_VOL_SPECIAL("PCBeep Playback Volume", IDX_MIXER_PCBEEP, 0x0f, 1, 1), + AZF3328_MIXER_SWITCH("PC Speaker Playback Switch", IDX_MIXER_PCBEEP, 15, 1), + AZF3328_MIXER_VOL_SPECIAL("PC Speaker Playback Volume", IDX_MIXER_PCBEEP, 0x0f, 1, 1), AZF3328_MIXER_SWITCH("Video Playback Switch", IDX_MIXER_VIDEO, 15, 1), AZF3328_MIXER_VOL_STEREO("Video Playback Volume", IDX_MIXER_VIDEO, 0x1f, 1), AZF3328_MIXER_SWITCH("Aux Playback Switch", IDX_MIXER_AUX, 15, 1), @@ -553,8 +626,8 @@ static snd_kcontrol_new_t snd_azf3328_mixer_controls[] __devinitdata = { AZF3328_MIXER_ENUM("Mono Select Source", IDX_MIXER_ADVCTL2, 2, 9), AZF3328_MIXER_VOL_SPECIAL("Tone Control - Treble", IDX_MIXER_BASSTREBLE, 0x07, 1, 0), AZF3328_MIXER_VOL_SPECIAL("Tone Control - Bass", IDX_MIXER_BASSTREBLE, 0x07, 9, 0), - AZF3328_MIXER_SWITCH("3D Control - Toggle", IDX_MIXER_ADVCTL2, 13, 0), - AZF3328_MIXER_VOL_SPECIAL("3D Control - Volume", IDX_MIXER_ADVCTL1, 0x07, 1, 0), /* "3D Width" */ + AZF3328_MIXER_SWITCH("3D Control - Switch", IDX_MIXER_ADVCTL2, 13, 0), + AZF3328_MIXER_VOL_SPECIAL("3D Control - Wide", IDX_MIXER_ADVCTL1, 0x07, 1, 0), /* "3D Width" */ AZF3328_MIXER_VOL_SPECIAL("3D Control - Space", IDX_MIXER_ADVCTL1, 0x03, 8, 0), /* "Hifi 3D" */ #if MIXER_TESTING AZF3328_MIXER_SWITCH("0", IDX_MIXER_ADVCTL2, 0, 0), @@ -576,9 +649,7 @@ static snd_kcontrol_new_t snd_azf3328_mixer_controls[] __devinitdata = { #endif }; -#define AZF3328_INIT_VALUES (sizeof(snd_azf3328_init_values)/sizeof(unsigned int)/2) - -static unsigned int snd_azf3328_init_values[][2] = { +static const u16 __devinitdata snd_azf3328_init_values[][2] = { { IDX_MIXER_PLAY_MASTER, MIXER_MUTE_MASK|0x1f1f }, { IDX_MIXER_MODEMOUT, MIXER_MUTE_MASK|0x1f1f }, { IDX_MIXER_BASSTREBLE, 0x0000 }, @@ -594,10 +665,11 @@ static unsigned int snd_azf3328_init_values[][2] = { { IDX_MIXER_REC_VOLUME, MIXER_MUTE_MASK|0x0707 }, }; -static int __devinit snd_azf3328_mixer_new(azf3328_t *chip) +static int __devinit +snd_azf3328_mixer_new(azf3328_t *chip) { snd_card_t *card; - snd_kcontrol_new_t *sw; + const snd_kcontrol_new_t *sw; unsigned int idx; int err; @@ -607,11 +679,13 @@ static int __devinit snd_azf3328_mixer_new(azf3328_t *chip) card = chip->card; /* mixer reset */ - snd_azf3328_mixer_write(chip, IDX_MIXER_RESET, 0x0, WORD_VALUE); + snd_azf3328_mixer_outw(chip, IDX_MIXER_RESET, 0x0000); /* mute and zero volume channels */ - for (idx = 0; idx < AZF3328_INIT_VALUES; idx++) { - snd_azf3328_mixer_write(chip, snd_azf3328_init_values[idx][0], snd_azf3328_init_values[idx][1], WORD_VALUE); + for (idx = 0; idx < ARRAY_SIZE(snd_azf3328_init_values); idx++) { + snd_azf3328_mixer_outw(chip, + snd_azf3328_init_values[idx][0], + snd_azf3328_init_values[idx][1]); } /* add mixer controls */ @@ -627,7 +701,8 @@ static int __devinit snd_azf3328_mixer_new(azf3328_t *chip) return 0; } -static int snd_azf3328_hw_params(snd_pcm_substream_t * substream, +static int +snd_azf3328_hw_params(snd_pcm_substream_t * substream, snd_pcm_hw_params_t * hw_params) { int res; @@ -637,7 +712,8 @@ static int snd_azf3328_hw_params(snd_pcm_substream_t * substream, return res; } -static int snd_azf3328_hw_free(snd_pcm_substream_t * substream) +static int +snd_azf3328_hw_free(snd_pcm_substream_t * substream) { snd_azf3328_dbgcallenter(); snd_pcm_lib_free_pages(substream); @@ -645,43 +721,48 @@ static int snd_azf3328_hw_free(snd_pcm_substream_t * substream) return 0; } -static void snd_azf3328_setfmt(azf3328_t *chip, +static void +snd_azf3328_setfmt(azf3328_t *chip, unsigned int reg, unsigned int bitrate, unsigned int format_width, unsigned int channels ) { - unsigned int val = 0xff00; + u16 val = 0xff00; unsigned long flags; snd_azf3328_dbgcallenter(); switch (bitrate) { - case 5512: val |= 0x0d; break; /* the AZF3328 names it "5510" for some strange reason */ - case 6620: val |= 0x0b; break; - case 8000: val |= 0x00; break; - case 9600: val |= 0x08; break; - case 11025: val |= 0x01; break; - case 16000: val |= 0x02; break; - case 22050: val |= 0x03; break; - case 32000: val |= 0x04; break; - case 44100: val |= 0x05; break; - case 48000: val |= 0x06; break; - case 64000: val |= 0x07; break; + case 4000: val |= SOUNDFORMAT_FREQ_SUSPECTED_4000; break; + case 4800: val |= SOUNDFORMAT_FREQ_SUSPECTED_4800; break; + case 5512: val |= SOUNDFORMAT_FREQ_5510; break; /* the AZF3328 names it "5510" for some strange reason */ + case 6620: val |= SOUNDFORMAT_FREQ_6620; break; + case 8000: val |= SOUNDFORMAT_FREQ_8000; break; + case 9600: val |= SOUNDFORMAT_FREQ_9600; break; + case 11025: val |= SOUNDFORMAT_FREQ_11025; break; + case 13240: val |= SOUNDFORMAT_FREQ_SUSPECTED_13240; break; + case 16000: val |= SOUNDFORMAT_FREQ_16000; break; + case 22050: val |= SOUNDFORMAT_FREQ_22050; break; + case 32000: val |= SOUNDFORMAT_FREQ_32000; break; + case 44100: val |= SOUNDFORMAT_FREQ_44100; break; + case 48000: val |= SOUNDFORMAT_FREQ_48000; break; + case 66200: val |= SOUNDFORMAT_FREQ_SUSPECTED_66200; break; default: snd_printk(KERN_WARNING "unknown bitrate %d, assuming 44.1kHz!\n", bitrate); - val |= 0x05; /* 44100 */ + val |= SOUNDFORMAT_FREQ_44100; break; } - /* val = 0xff07; 3m27.993s (65301Hz; -> 64000Hz???) */ - /* val = 0xff09; 17m15.098s (13123,478Hz; -> 12000Hz???) */ - /* val = 0xff0a; 47m30.599s (4764,891Hz; -> 4800Hz???) */ - /* val = 0xff0c; 57m0.510s (4010,263Hz; -> 4000Hz???) */ + /* val = 0xff07; 3m27.993s (65301Hz; -> 64000Hz???) hmm, 66120, 65967, 66123 */ + /* val = 0xff09; 17m15.098s (13123,478Hz; -> 12000Hz???) hmm, 13237.2Hz? */ + /* val = 0xff0a; 47m30.599s (4764,891Hz; -> 4800Hz???) yup, 4803Hz */ + /* val = 0xff0c; 57m0.510s (4010,263Hz; -> 4000Hz???) yup, 4003Hz */ /* val = 0xff05; 5m11.556s (... -> 44100Hz) */ /* val = 0xff03; 10m21.529s (21872,463Hz; -> 22050Hz???) */ /* val = 0xff0f; 20m41.883s (10937,993Hz; -> 11025Hz???) */ /* val = 0xff0d; 41m23.135s (5523,600Hz; -> 5512Hz???) */ /* val = 0xff0e; 28m30.777s (8017Hz; -> 8000Hz???) */ + if (channels == 2) val |= SOUNDFORMAT_FLAG_2CHANNELS; @@ -691,7 +772,7 @@ static void snd_azf3328_setfmt(azf3328_t *chip, spin_lock_irqsave(&chip->reg_lock, flags); /* set bitrate/format */ - outw(val, chip->codec_port+reg); + snd_azf3328_codec_outw(chip, reg, val); /* changing the bitrate/format settings switches off the * audio output with an annoying click in case of 8/16bit format change @@ -701,47 +782,67 @@ static void snd_azf3328_setfmt(azf3328_t *chip, * FIXME: does this have some side effects for full-duplex * or other dramatic side effects? */ if (reg == IDX_IO_PLAY_SOUNDFORMAT) /* only do it for playback */ - outw(inw(chip->codec_port + IDX_IO_PLAY_FLAGS)|DMA_PLAY_SOMETHING1|DMA_PLAY_SOMETHING2|SOMETHING_ALMOST_ALWAYS_SET|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port + IDX_IO_PLAY_FLAGS); + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, + snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) | + DMA_PLAY_SOMETHING1 | + DMA_PLAY_SOMETHING2 | + SOMETHING_ALMOST_ALWAYS_SET | + DMA_EPILOGUE_SOMETHING | + DMA_SOMETHING_ELSE + ); spin_unlock_irqrestore(&chip->reg_lock, flags); snd_azf3328_dbgcallleave(); } -static void snd_azf3328_setdmaa(azf3328_t *chip, +static void +snd_azf3328_setdmaa(azf3328_t *chip, long unsigned int addr, unsigned int count, unsigned int size, int do_recording) { - long unsigned int addr1; - long unsigned int addr2; - unsigned int count1; - unsigned int count2; - unsigned long flags; - int reg_offs = do_recording ? 0x20 : 0x00; + unsigned long flags, portbase; + unsigned int is_running; snd_azf3328_dbgcallenter(); + if (do_recording) + { + /* access capture registers, i.e. skip playback reg section */ + portbase = chip->codec_port + 0x20; + is_running = chip->is_recording; + } + else + { + /* access the playback register section */ + portbase = chip->codec_port + 0x00; + is_running = chip->is_playing; + } + /* AZF3328 uses a two buffer pointer DMA playback approach */ - if (!chip->is_playing) + if (!is_running) { - addr1 = addr; - addr2 = addr+(size/2); - count1 = (size/2)-1; - count2 = (size/2)-1; -#if DEBUG_PLAY_REC - snd_azf3328_dbgplay("setting dma: buf1 %08lx[%d], buf2 %08lx[%d]\n", addr1, count1, addr2, count2); -#endif + unsigned long addr_area2; + unsigned long count_areas, count_tmp; /* width 32bit -- overflow!! */ + count_areas = size/2; + addr_area2 = addr+count_areas; + count_areas--; /* max. index */ + snd_azf3328_dbgplay("set DMA: buf1 %08lx[%lu], buf2 %08lx[%lu]\n", addr, count_areas, addr_area2, count_areas); + + /* build combined I/O buffer length word */ + count_tmp = count_areas; + count_areas |= (count_tmp << 16); spin_lock_irqsave(&chip->reg_lock, flags); - outl(addr1, chip->codec_port+reg_offs+IDX_IO_PLAY_DMA_START_1); - outl(addr2, chip->codec_port+reg_offs+IDX_IO_PLAY_DMA_START_2); - outw(count1, chip->codec_port+reg_offs+IDX_IO_PLAY_DMA_LEN_1); - outw(count2, chip->codec_port+reg_offs+IDX_IO_PLAY_DMA_LEN_2); + outl(addr, portbase + IDX_IO_PLAY_DMA_START_1); + outl(addr_area2, portbase + IDX_IO_PLAY_DMA_START_2); + outl(count_areas, portbase + IDX_IO_PLAY_DMA_LEN_1); spin_unlock_irqrestore(&chip->reg_lock, flags); } snd_azf3328_dbgcallleave(); } -static int snd_azf3328_playback_prepare(snd_pcm_substream_t *substream) +static int +snd_azf3328_playback_prepare(snd_pcm_substream_t *substream) { #if 0 azf3328_t *chip = snd_pcm_substream_chip(substream); @@ -752,14 +853,18 @@ static int snd_azf3328_playback_prepare(snd_pcm_substream_t *substream) snd_azf3328_dbgcallenter(); #if 0 - snd_azf3328_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT, runtime->rate, snd_pcm_format_width(runtime->format), runtime->channels); + snd_azf3328_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT, + runtime->rate, + snd_pcm_format_width(runtime->format), + runtime->channels); snd_azf3328_setdmaa(chip, runtime->dma_addr, count, size, 0); #endif snd_azf3328_dbgcallleave(); return 0; } -static int snd_azf3328_capture_prepare(snd_pcm_substream_t * substream) +static int +snd_azf3328_capture_prepare(snd_pcm_substream_t * substream) { #if 0 azf3328_t *chip = snd_pcm_substream_chip(substream); @@ -770,14 +875,18 @@ static int snd_azf3328_capture_prepare(snd_pcm_substream_t * substream) snd_azf3328_dbgcallenter(); #if 0 - snd_azf3328_setfmt(chip, IDX_IO_REC_SOUNDFORMAT, runtime->rate, snd_pcm_format_width(runtime->format), runtime->channels); + snd_azf3328_setfmt(chip, IDX_IO_REC_SOUNDFORMAT, + runtime->rate, + snd_pcm_format_width(runtime->format), + runtime->channels); snd_azf3328_setdmaa(chip, runtime->dma_addr, count, size, 1); #endif snd_azf3328_dbgcallleave(); return 0; } -static int snd_azf3328_playback_trigger(snd_pcm_substream_t * substream, int cmd) +static int +snd_azf3328_playback_trigger(snd_pcm_substream_t * substream, int cmd) { azf3328_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; @@ -785,73 +894,92 @@ static int snd_azf3328_playback_trigger(snd_pcm_substream_t * substream, int cmd unsigned int status1; snd_azf3328_dbgcalls("snd_azf3328_playback_trigger cmd %d\n", cmd); + switch (cmd) { case SNDRV_PCM_TRIGGER_START: - - snd_azf3328_dbgio(chip, "trigger1"); + snd_azf3328_dbgplay("START PLAYBACK\n"); /* mute WaveOut */ snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1); - snd_azf3328_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT, runtime->rate, snd_pcm_format_width(runtime->format), runtime->channels); + snd_azf3328_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT, + runtime->rate, + snd_pcm_format_width(runtime->format), + runtime->channels); spin_lock(&chip->reg_lock); /* stop playback */ - status1 = inw(chip->codec_port+IDX_IO_PLAY_FLAGS); + status1 = snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS); status1 &= ~DMA_RESUME; - outw(status1, chip->codec_port+IDX_IO_PLAY_FLAGS); + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); /* FIXME: clear interrupts or what??? */ - outw(0xffff, chip->codec_port+IDX_IO_PLAY_IRQMASK); + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_IRQTYPE, 0xffff); spin_unlock(&chip->reg_lock); - snd_azf3328_setdmaa(chip, runtime->dma_addr, snd_pcm_lib_period_bytes(substream), snd_pcm_lib_buffer_bytes(substream), 0); + snd_azf3328_setdmaa(chip, runtime->dma_addr, + snd_pcm_lib_period_bytes(substream), + snd_pcm_lib_buffer_bytes(substream), + 0); spin_lock(&chip->reg_lock); #ifdef WIN9X /* FIXME: enable playback/recording??? */ status1 |= DMA_PLAY_SOMETHING1 | DMA_PLAY_SOMETHING2; - outw(status1, chip->codec_port+IDX_IO_PLAY_FLAGS); + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); /* start playback again */ /* FIXME: what is this value (0x0010)??? */ status1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING; - outw(status1, chip->codec_port+IDX_IO_PLAY_FLAGS); + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); #else /* NT4 */ - outw(0x00, chip->codec_port+IDX_IO_PLAY_FLAGS); - outw(DMA_PLAY_SOMETHING1, chip->codec_port+IDX_IO_PLAY_FLAGS); - outw(DMA_PLAY_SOMETHING1|DMA_PLAY_SOMETHING2, chip->codec_port+IDX_IO_PLAY_FLAGS); - outw(DMA_RESUME|SOMETHING_ALMOST_ALWAYS_SET|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port+IDX_IO_PLAY_FLAGS); + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, + 0x0000); + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, + DMA_PLAY_SOMETHING1); + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, + DMA_PLAY_SOMETHING1 | + DMA_PLAY_SOMETHING2); + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, + DMA_RESUME | + SOMETHING_ALMOST_ALWAYS_SET | + DMA_EPILOGUE_SOMETHING | + DMA_SOMETHING_ELSE); #endif spin_unlock(&chip->reg_lock); /* now unmute WaveOut */ snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0); - snd_azf3328_dbgio(chip, "trigger2"); chip->is_playing = 1; + snd_azf3328_dbgplay("STARTED PLAYBACK\n"); break; - case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_STOP: + snd_azf3328_dbgplay("STOP PLAYBACK\n"); + /* mute WaveOut */ snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1); spin_lock(&chip->reg_lock); /* stop playback */ - status1 = inw(chip->codec_port+IDX_IO_PLAY_FLAGS); + status1 = snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS); status1 &= ~DMA_RESUME; - outw(status1, chip->codec_port+IDX_IO_PLAY_FLAGS); + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); + /* hmm, is this really required? we're resetting the same bit + * immediately thereafter... */ status1 |= DMA_PLAY_SOMETHING1; - outw(status1, chip->codec_port+IDX_IO_PLAY_FLAGS); + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); status1 &= ~DMA_PLAY_SOMETHING1; - outw(status1, chip->codec_port+IDX_IO_PLAY_FLAGS); + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); spin_unlock(&chip->reg_lock); /* now unmute WaveOut */ snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0); chip->is_playing = 0; + snd_azf3328_dbgplay("STOPPED PLAYBACK\n"); break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); @@ -869,7 +997,8 @@ static int snd_azf3328_playback_trigger(snd_pcm_substream_t * substream, int cmd /* this is just analogous to playback; I'm not quite sure whether recording * should actually be triggered like that */ -static int snd_azf3328_capture_trigger(snd_pcm_substream_t * substream, int cmd) +static int +snd_azf3328_capture_trigger(snd_pcm_substream_t * substream, int cmd) { azf3328_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; @@ -877,62 +1006,80 @@ static int snd_azf3328_capture_trigger(snd_pcm_substream_t * substream, int cmd) unsigned int status1; snd_azf3328_dbgcalls("snd_azf3328_capture_trigger cmd %d\n", cmd); + switch (cmd) { case SNDRV_PCM_TRIGGER_START: - snd_azf3328_dbgio(chip, "trigger1"); + snd_azf3328_dbgplay("START CAPTURE\n"); - snd_azf3328_setfmt(chip, IDX_IO_REC_SOUNDFORMAT, runtime->rate, snd_pcm_format_width(runtime->format), runtime->channels); + snd_azf3328_setfmt(chip, IDX_IO_REC_SOUNDFORMAT, + runtime->rate, + snd_pcm_format_width(runtime->format), + runtime->channels); spin_lock(&chip->reg_lock); /* stop recording */ - status1 = inw(chip->codec_port+IDX_IO_REC_FLAGS); + status1 = snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS); status1 &= ~DMA_RESUME; - outw(status1, chip->codec_port+IDX_IO_REC_FLAGS); + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); /* FIXME: clear interrupts or what??? */ - outw(0xffff, chip->codec_port+IDX_IO_REC_IRQMASK); + snd_azf3328_codec_outw(chip, IDX_IO_REC_IRQTYPE, 0xffff); spin_unlock(&chip->reg_lock); - snd_azf3328_setdmaa(chip, runtime->dma_addr, snd_pcm_lib_period_bytes(substream), snd_pcm_lib_buffer_bytes(substream), 1); + snd_azf3328_setdmaa(chip, runtime->dma_addr, + snd_pcm_lib_period_bytes(substream), + snd_pcm_lib_buffer_bytes(substream), + 1); spin_lock(&chip->reg_lock); #ifdef WIN9X /* FIXME: enable playback/recording??? */ status1 |= DMA_PLAY_SOMETHING1 | DMA_PLAY_SOMETHING2; - outw(status1, chip->codec_port+IDX_IO_REC_FLAGS); + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); - /* start playback again */ + /* start capture again */ /* FIXME: what is this value (0x0010)??? */ status1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING; - outw(status1, chip->codec_port+IDX_IO_REC_FLAGS); + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); #else - outw(0x00, chip->codec_port+IDX_IO_REC_FLAGS); - outw(DMA_PLAY_SOMETHING1, chip->codec_port+IDX_IO_REC_FLAGS); - outw(DMA_PLAY_SOMETHING1|DMA_PLAY_SOMETHING2, chip->codec_port+IDX_IO_REC_FLAGS); - outw(DMA_RESUME|SOMETHING_ALMOST_ALWAYS_SET|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port+IDX_IO_REC_FLAGS); + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, + 0x0000); + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, + DMA_PLAY_SOMETHING1); + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, + DMA_PLAY_SOMETHING1 | + DMA_PLAY_SOMETHING2); + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, + DMA_RESUME | + SOMETHING_ALMOST_ALWAYS_SET | + DMA_EPILOGUE_SOMETHING | + DMA_SOMETHING_ELSE); #endif spin_unlock(&chip->reg_lock); - snd_azf3328_dbgio(chip, "trigger2"); - chip->is_playing = 1; + chip->is_recording = 1; + snd_azf3328_dbgplay("STARTED CAPTURE\n"); break; case SNDRV_PCM_TRIGGER_STOP: + snd_azf3328_dbgplay("STOP CAPTURE\n"); + spin_lock(&chip->reg_lock); /* stop recording */ - status1 = inw(chip->codec_port+IDX_IO_REC_FLAGS); + status1 = snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS); status1 &= ~DMA_RESUME; - outw(status1, chip->codec_port+IDX_IO_REC_FLAGS); + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); status1 |= DMA_PLAY_SOMETHING1; - outw(status1, chip->codec_port+IDX_IO_REC_FLAGS); + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); status1 &= ~DMA_PLAY_SOMETHING1; - outw(status1, chip->codec_port+IDX_IO_REC_FLAGS); + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); spin_unlock(&chip->reg_lock); - chip->is_playing = 0; + chip->is_recording = 0; + snd_azf3328_dbgplay("STOPPED CAPTURE\n"); break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); @@ -948,11 +1095,11 @@ static int snd_azf3328_capture_trigger(snd_pcm_substream_t * substream, int cmd) return result; } -static snd_pcm_uframes_t snd_azf3328_playback_pointer(snd_pcm_substream_t * substream) +static snd_pcm_uframes_t +snd_azf3328_playback_pointer(snd_pcm_substream_t * substream) { azf3328_t *chip = snd_pcm_substream_chip(substream); - unsigned long bufptr, playptr; - unsigned long result; + unsigned long bufptr, result; snd_pcm_uframes_t frmres; #ifdef QUERY_HARDWARE @@ -960,19 +1107,20 @@ static snd_pcm_uframes_t snd_azf3328_playback_pointer(snd_pcm_substream_t * subs #else bufptr = substream->runtime->dma_addr; #endif - playptr = inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS); + result = inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS); - result = playptr - bufptr; - frmres = bytes_to_frames( substream->runtime, result ); - snd_azf3328_dbgplay("result %lx, playptr %lx (base %x), frames %ld\n", result, playptr, substream->runtime->dma_addr, frmres); + /* calculate offset */ + result -= bufptr; + frmres = bytes_to_frames( substream->runtime, result); + snd_azf3328_dbgplay("PLAY @ 0x%8lx, frames %8ld\n", result, frmres); return frmres; } -static snd_pcm_uframes_t snd_azf3328_capture_pointer(snd_pcm_substream_t * substream) +static snd_pcm_uframes_t +snd_azf3328_capture_pointer(snd_pcm_substream_t * substream) { azf3328_t *chip = snd_pcm_substream_chip(substream); - unsigned long bufptr, recptr; - unsigned long result; + unsigned long bufptr, result; snd_pcm_uframes_t frmres; #ifdef QUERY_HARDWARE @@ -980,96 +1128,116 @@ static snd_pcm_uframes_t snd_azf3328_capture_pointer(snd_pcm_substream_t * subst #else bufptr = substream->runtime->dma_addr; #endif - recptr = inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS); + result = inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS); - result = recptr - bufptr; - frmres = bytes_to_frames( substream->runtime, result ); - snd_azf3328_dbgplay("result %lx, rec ptr %lx (base %x), frames %ld\n", result, recptr, substream->runtime->dma_addr, frmres); + /* calculate offset */ + result -= bufptr; + frmres = bytes_to_frames( substream->runtime, result); + snd_azf3328_dbgplay("REC @ 0x%8lx, frames %8ld\n", result, frmres); return frmres; } -static irqreturn_t snd_azf3328_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t +snd_azf3328_interrupt(int irq, void *dev_id, struct pt_regs *regs) { azf3328_t *chip = dev_id; - unsigned int status, which; - static unsigned long count; + u8 status, which; + static unsigned long irq_count; - status = inw(chip->codec_port+IDX_IO_IRQSTATUS); + status = snd_azf3328_codec_inb(chip, IDX_IO_IRQSTATUS); /* fast path out, to ease interrupt sharing */ - if (!(status & (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_MPU401|IRQ_SOMEIRQ))) + if (!(status & (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_MPU401|IRQ_TIMER))) return IRQ_NONE; /* must be interrupt for another device */ - snd_azf3328_dbgplay("Interrupt %ld!\nIDX_IO_PLAY_FLAGS %04x, IDX_IO_PLAY_IRQMASK %04x, IDX_IO_IRQSTATUS %04x\n", count, inw(chip->codec_port+IDX_IO_PLAY_FLAGS), inw(chip->codec_port+IDX_IO_PLAY_IRQMASK), inw(chip->codec_port+IDX_IO_IRQSTATUS)); + snd_azf3328_dbgplay("Interrupt %ld!\nIDX_IO_PLAY_FLAGS %04x, IDX_IO_PLAY_IRQTYPE %04x, IDX_IO_IRQSTATUS %04x\n", + irq_count, + snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS), + snd_azf3328_codec_inw(chip, IDX_IO_PLAY_IRQTYPE), + status); + if (status & IRQ_TIMER) + { + /* snd_azf3328_dbgplay("timer %ld\n", inl(chip->codec_port+IDX_IO_TIMER_VALUE) & TIMER_VALUE_MASK); */ + if (chip->timer) + snd_timer_interrupt(chip->timer, chip->timer->sticks); + /* ACK timer */ + spin_lock(&chip->reg_lock); + snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x07); + spin_unlock(&chip->reg_lock); + snd_azf3328_dbgplay("azt3328: timer IRQ\n"); + } if (status & IRQ_PLAYBACK) { spin_lock(&chip->reg_lock); - which = inw(chip->codec_port+IDX_IO_PLAY_IRQMASK); - if (which & IRQ_FINISHED_PLAYBUF_1) - /* ack IRQ */ - outw(which | IRQ_FINISHED_PLAYBUF_1, chip->codec_port+IDX_IO_PLAY_IRQMASK); - if (which & IRQ_FINISHED_PLAYBUF_2) - /* ack IRQ */ - outw(which | IRQ_FINISHED_PLAYBUF_2, chip->codec_port+IDX_IO_PLAY_IRQMASK); - if (which & IRQ_PLAY_SOMETHING) - { - snd_azf3328_dbgplay("azt3328: unknown play IRQ type occurred, please report!\n"); - } + which = snd_azf3328_codec_inb(chip, IDX_IO_PLAY_IRQTYPE); + /* ack all IRQ types immediately */ + snd_azf3328_codec_outb(chip, IDX_IO_PLAY_IRQTYPE, which); + spin_unlock(&chip->reg_lock); + if (chip->pcm && chip->playback_substream) { - snd_azf3328_dbgplay("which %x, playptr %lx\n", which, inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS)); snd_pcm_period_elapsed(chip->playback_substream); - snd_azf3328_dbgplay("period done, playptr %lx.\n", inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS)); + snd_azf3328_dbgplay("PLAY period done (#%x), @ %x\n", + which, + inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS)); } else snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n"); - spin_unlock(&chip->reg_lock); + if (which & IRQ_PLAY_SOMETHING) + snd_azf3328_dbgplay("azt3328: unknown play IRQ type occurred, please report!\n"); } if (status & IRQ_RECORDING) { spin_lock(&chip->reg_lock); - which = inw(chip->codec_port+IDX_IO_REC_IRQMASK); - if (which & IRQ_FINISHED_RECBUF_1) - /* ack interrupt */ - outw(which | IRQ_FINISHED_RECBUF_1, chip->codec_port+IDX_IO_REC_IRQMASK); - if (which & IRQ_FINISHED_RECBUF_2) - /* ack interrupt */ - outw(which | IRQ_FINISHED_RECBUF_2, chip->codec_port+IDX_IO_REC_IRQMASK); - if (which & IRQ_REC_SOMETHING) - { - snd_azf3328_dbgplay("azt3328: unknown rec IRQ type occurred, please report!\n"); - } + which = snd_azf3328_codec_inb(chip, IDX_IO_REC_IRQTYPE); + /* ack all IRQ types immediately */ + snd_azf3328_codec_outb(chip, IDX_IO_REC_IRQTYPE, which); + spin_unlock(&chip->reg_lock); + if (chip->pcm && chip->capture_substream) { - snd_azf3328_dbgplay("which %x, recptr %lx\n", which, inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS)); - spin_unlock(&chip->reg_lock); snd_pcm_period_elapsed(chip->capture_substream); - spin_lock(&chip->reg_lock); - snd_azf3328_dbgplay("period done, recptr %lx.\n", inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS)); + snd_azf3328_dbgplay("REC period done (#%x), @ %x\n", + which, + inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS)); } - spin_unlock(&chip->reg_lock); + else + snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n"); + if (which & IRQ_REC_SOMETHING) + snd_azf3328_dbgplay("azt3328: unknown rec IRQ type occurred, please report!\n"); } + /* MPU401 has less critical IRQ requirements + * than timer and playback/recording, right? */ if (status & IRQ_MPU401) + { snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs); - if (status & IRQ_SOMEIRQ) - snd_azf3328_dbgplay("azt3328: unknown IRQ type occurred, please report!\n"); - count++; + + /* hmm, do we have to ack the IRQ here somehow? + * If so, then I don't know how... */ + snd_azf3328_dbgplay("azt3328: MPU401 IRQ\n"); + } + irq_count++; return IRQ_HANDLED; } /*****************************************************************/ -static snd_pcm_hardware_t snd_azf3328_playback = +static const snd_pcm_hardware_t snd_azf3328_playback = { /* FIXME!! Correct? */ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE, - .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_KNOT, - .rate_min = 5512, - .rate_max = 64000, + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP_VALID, + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_U16_LE, + .rates = SNDRV_PCM_RATE_5512 | + SNDRV_PCM_RATE_8000_48000 | + SNDRV_PCM_RATE_KNOT, + .rate_min = 4000, + .rate_max = 66200, .channels_min = 1, .channels_max = 2, .buffer_bytes_max = 65536, @@ -1083,16 +1251,21 @@ static snd_pcm_hardware_t snd_azf3328_playback = .fifo_size = 0, }; -static snd_pcm_hardware_t snd_azf3328_capture = +static const snd_pcm_hardware_t snd_azf3328_capture = { /* FIXME */ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE, - .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_KNOT, - .rate_min = 5512, - .rate_max = 64000, + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP_VALID, + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_U16_LE, + .rates = SNDRV_PCM_RATE_5512 | + SNDRV_PCM_RATE_8000_48000 | + SNDRV_PCM_RATE_KNOT, + .rate_min = 4000, + .rate_max = 66200, .channels_min = 1, .channels_max = 2, .buffer_bytes_max = 65536, @@ -1105,8 +1278,8 @@ static snd_pcm_hardware_t snd_azf3328_capture = static unsigned int snd_azf3328_fixed_rates[] = { - 5512, 6620, 8000, 9600, 11025, 16000, 22050, 32000, 44100, 48000, 64000 -}; + 4000, 4800, 5512, 6620, 8000, 9600, 11025, 13240, 16000, 22050, 32000, + 44100, 48000, 66200 }; static snd_pcm_hw_constraint_list_t snd_azf3328_hw_constraints_rates = { .count = ARRAY_SIZE(snd_azf3328_fixed_rates), .list = snd_azf3328_fixed_rates, @@ -1115,7 +1288,8 @@ static snd_pcm_hw_constraint_list_t snd_azf3328_hw_constraints_rates = { /*****************************************************************/ -static int snd_azf3328_playback_open(snd_pcm_substream_t * substream) +static int +snd_azf3328_playback_open(snd_pcm_substream_t * substream) { azf3328_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; @@ -1129,7 +1303,8 @@ static int snd_azf3328_playback_open(snd_pcm_substream_t * substream) return 0; } -static int snd_azf3328_capture_open(snd_pcm_substream_t * substream) +static int +snd_azf3328_capture_open(snd_pcm_substream_t * substream) { azf3328_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; @@ -1143,7 +1318,8 @@ static int snd_azf3328_capture_open(snd_pcm_substream_t * substream) return 0; } -static int snd_azf3328_playback_close(snd_pcm_substream_t * substream) +static int +snd_azf3328_playback_close(snd_pcm_substream_t * substream) { azf3328_t *chip = snd_pcm_substream_chip(substream); @@ -1154,7 +1330,8 @@ static int snd_azf3328_playback_close(snd_pcm_substream_t * substream) return 0; } -static int snd_azf3328_capture_close(snd_pcm_substream_t * substream) +static int +snd_azf3328_capture_close(snd_pcm_substream_t * substream) { azf3328_t *chip = snd_pcm_substream_chip(substream); @@ -1188,14 +1365,16 @@ static snd_pcm_ops_t snd_azf3328_capture_ops = { .pointer = snd_azf3328_capture_pointer }; -static void snd_azf3328_pcm_free(snd_pcm_t *pcm) +static void +snd_azf3328_pcm_free(snd_pcm_t *pcm) { azf3328_t *chip = pcm->private_data; chip->pcm = NULL; snd_pcm_lib_preallocate_free_for_all(pcm); } -static int __devinit snd_azf3328_pcm(azf3328_t *chip, int device) +static int __devinit +snd_azf3328_pcm(azf3328_t *chip, int device) { snd_pcm_t *pcm; int err; @@ -1222,7 +1401,8 @@ static int __devinit snd_azf3328_pcm(azf3328_t *chip, int device) /******************************************************************/ #ifdef SUPPORT_JOYSTICK -static int __devinit snd_azf3328_config_joystick(azf3328_t *chip, int dev) +static int __devinit +snd_azf3328_config_joystick(azf3328_t *chip, int dev) { struct gameport *gp; struct resource *r; @@ -1248,15 +1428,16 @@ static int __devinit snd_azf3328_config_joystick(azf3328_t *chip, int dev) gp->io = 0x200; gameport_set_port_data(gp, r); - snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR, - snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) | LEGACY_JOY); + snd_azf3328_io2_outb(chip, IDX_IO2_LEGACY_ADDR, + snd_azf3328_io2_inb(chip, IDX_IO2_LEGACY_ADDR) | LEGACY_JOY); gameport_register_port(chip->gameport); return 0; } -static void snd_azf3328_free_joystick(azf3328_t *chip) +static void +snd_azf3328_free_joystick(azf3328_t *chip) { if (chip->gameport) { struct resource *r = gameport_get_port_data(chip->gameport); @@ -1264,32 +1445,36 @@ static void snd_azf3328_free_joystick(azf3328_t *chip) gameport_unregister_port(chip->gameport); chip->gameport = NULL; /* disable gameport */ - snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR, - snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY); + snd_azf3328_io2_outb(chip, IDX_IO2_LEGACY_ADDR, + snd_azf3328_io2_inb(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY); release_and_free_resource(r); } } #else -static inline int snd_azf3328_config_joystick(azf3328_t *chip, int dev) { return -ENOSYS; } -static inline void snd_azf3328_free_joystick(azf3328_t *chip) { } +static inline int +snd_azf3328_config_joystick(azf3328_t *chip, int dev) { return -ENOSYS; } +static inline void +snd_azf3328_free_joystick(azf3328_t *chip) { } #endif /******************************************************************/ -static int snd_azf3328_free(azf3328_t *chip) +static int +snd_azf3328_free(azf3328_t *chip) { if (chip->irq < 0) goto __end_hw; /* reset (close) mixer */ snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1); /* first mute master volume */ - snd_azf3328_mixer_write(chip, IDX_MIXER_RESET, 0x0, WORD_VALUE); + snd_azf3328_mixer_outw(chip, IDX_MIXER_RESET, 0x0000); - /* interrupt setup - mask everything */ - /* FIXME */ + /* interrupt setup - mask everything (FIXME!) */ + /* well, at least we know how to disable the timer IRQ */ + snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x00); synchronize_irq(chip->irq); - __end_hw: +__end_hw: snd_azf3328_free_joystick(chip); if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); @@ -1300,15 +1485,129 @@ static int snd_azf3328_free(azf3328_t *chip) return 0; } -static int snd_azf3328_dev_free(snd_device_t *device) +static int +snd_azf3328_dev_free(snd_device_t *device) { azf3328_t *chip = device->device_data; return snd_azf3328_free(chip); } +/******************************************************************/ + +/*** NOTE: the physical timer resolution actually is 1024000 ticks per second, + *** but announcing those attributes to user-space would make programs + *** configure the timer to a 1 tick value, resulting in an absolutely fatal + *** timer IRQ storm. + *** Thus I chose to announce a down-scaled virtual timer to the outside and + *** calculate real timer countdown values internally. + *** (the scale factor can be set via module parameter "seqtimer_scaling"). + ***/ + +static int +snd_azf3328_timer_start(snd_timer_t *timer) +{ + azf3328_t *chip; + unsigned long flags; + unsigned int delay; + + snd_azf3328_dbgcallenter(); + chip = snd_timer_chip(timer); + delay = ((timer->sticks * seqtimer_scaling) - 1) & TIMER_VALUE_MASK; + if (delay < 49) + { + /* uhoh, that's not good, since user-space won't know about + * this timing tweak + * (we need to do it to avoid a lockup, though) */ + + snd_azf3328_dbgtimer("delay was too low (%d)!\n", delay); + delay = 49; /* minimum time is 49 ticks */ + } + snd_azf3328_dbgtimer("setting timer countdown value %d, add COUNTDOWN|IRQ\n", delay); + delay |= TIMER_ENABLE_COUNTDOWN | TIMER_ENABLE_IRQ; + spin_lock_irqsave(&chip->reg_lock, flags); + snd_azf3328_codec_outl(chip, IDX_IO_TIMER_VALUE, delay); + spin_unlock_irqrestore(&chip->reg_lock, flags); + snd_azf3328_dbgcallleave(); + return 0; +} + +static int +snd_azf3328_timer_stop(snd_timer_t *timer) +{ + azf3328_t *chip; + unsigned long flags; + + snd_azf3328_dbgcallenter(); + chip = snd_timer_chip(timer); + spin_lock_irqsave(&chip->reg_lock, flags); + /* disable timer countdown and interrupt */ + /* FIXME: should we write TIMER_ACK_IRQ here? */ + snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0); + spin_unlock_irqrestore(&chip->reg_lock, flags); + snd_azf3328_dbgcallleave(); + return 0; +} + + +static int +snd_azf3328_timer_precise_resolution(snd_timer_t *timer, + unsigned long *num, unsigned long *den) +{ + snd_azf3328_dbgcallenter(); + *num = 1; + *den = 1024000 / seqtimer_scaling; + snd_azf3328_dbgcallleave(); + return 0; +} + +static struct _snd_timer_hardware snd_azf3328_timer_hw = { + .flags = SNDRV_TIMER_HW_AUTO, + .resolution = 977, /* 1000000/1024000 = 0.9765625us */ + .ticks = 1024000, /* max tick count, defined by the value register; actually it's not 1024000, but 1048576, but we don't care */ + .start = snd_azf3328_timer_start, + .stop = snd_azf3328_timer_stop, + .precise_resolution = snd_azf3328_timer_precise_resolution, +}; + +static int __devinit +snd_azf3328_timer(azf3328_t *chip, int device) +{ + snd_timer_t *timer = NULL; + snd_timer_id_t tid; + int err; + + snd_azf3328_dbgcallenter(); + tid.dev_class = SNDRV_TIMER_CLASS_CARD; + tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; + tid.card = chip->card->number; + tid.device = device; + tid.subdevice = 0; + + snd_azf3328_timer_hw.resolution *= seqtimer_scaling; + snd_azf3328_timer_hw.ticks /= seqtimer_scaling; + if ((err = snd_timer_new(chip->card, "AZF3328", &tid, &timer)) < 0) { + goto out; + } + + strcpy(timer->name, "AZF3328 timer"); + timer->private_data = chip; + timer->hw = snd_azf3328_timer_hw; + + chip->timer = timer; + + err = 0; + +out: + snd_azf3328_dbgcallleave(); + return err; +} + +/******************************************************************/ + #if 0 /* check whether a bit can be modified */ -static void snd_azf3328_test_bit(unsigned int reg, int bit) +static void +snd_azf3328_test_bit(unsigned int reg, int bit) { unsigned char val, valoff, valon; @@ -1326,7 +1625,26 @@ static void snd_azf3328_test_bit(unsigned int reg, int bit) } #endif -static int __devinit snd_azf3328_create(snd_card_t * card, +static void +snd_azf3328_debug_show_ports(const azf3328_t *chip) +{ +#if DEBUG_MISC + u16 tmp; + + snd_azf3328_dbgmisc("codec_port 0x%lx, io2_port 0x%lx, mpu_port 0x%lx, synth_port 0x%lx, mixer_port 0x%lx, irq %d\n", chip->codec_port, chip->io2_port, chip->mpu_port, chip->synth_port, chip->mixer_port, chip->irq); + + snd_azf3328_dbgmisc("io2 %02x %02x %02x %02x %02x %02x\n", snd_azf3328_io2_inb(chip, 0), snd_azf3328_io2_inb(chip, 1), snd_azf3328_io2_inb(chip, 2), snd_azf3328_io2_inb(chip, 3), snd_azf3328_io2_inb(chip, 4), snd_azf3328_io2_inb(chip, 5)); + + for (tmp=0; tmp <= 0x01; tmp += 1) + snd_azf3328_dbgmisc("0x%02x: opl 0x%04x, mpu300 0x%04x, mpu310 0x%04x, mpu320 0x%04x, mpu330 0x%04x\n", tmp, inb(0x388 + tmp), inb(0x300 + tmp), inb(0x310 + tmp), inb(0x320 + tmp), inb(0x330 + tmp)); + + for (tmp = 0; tmp <= 0x6E; tmp += 2) + snd_azf3328_dbgmisc("0x%02x: 0x%04x\n", tmp, snd_azf3328_codec_inb(chip, tmp)); +#endif +} + +static int __devinit +snd_azf3328_create(snd_card_t * card, struct pci_dev *pci, unsigned long device_type, azf3328_t ** rchip) @@ -1345,8 +1663,8 @@ static int __devinit snd_azf3328_create(snd_card_t * card, chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (chip == NULL) { - pci_disable_device(pci); - return -ENOMEM; + err = -ENOMEM; + goto out_err; } spin_lock_init(&chip->reg_lock); chip->card = card; @@ -1357,46 +1675,38 @@ static int __devinit snd_azf3328_create(snd_card_t * card, if (pci_set_dma_mask(pci, 0x00ffffff) < 0 || pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) { snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); - pci_disable_device(pci); - return -ENXIO; + err = -ENXIO; + goto out_err; } if ((err = pci_request_regions(pci, "Aztech AZF3328")) < 0) { - kfree(chip); - pci_disable_device(pci); - return err; + goto out_err; } chip->codec_port = pci_resource_start(pci, 0); - chip->io2_port = pci_resource_start(pci, 1); - chip->mpu_port = pci_resource_start(pci, 2); + chip->io2_port = pci_resource_start(pci, 1); + chip->mpu_port = pci_resource_start(pci, 2); chip->synth_port = pci_resource_start(pci, 3); chip->mixer_port = pci_resource_start(pci, 4); if (request_irq(pci->irq, snd_azf3328_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_azf3328_free(chip); - return -EBUSY; + err = -EBUSY; + goto out_err; } chip->irq = pci->irq; pci_set_master(pci); synchronize_irq(chip->irq); - snd_azf3328_dbgmisc("codec_port 0x%lx, io2_port 0x%lx, mpu_port 0x%lx, synth_port 0x%lx, mixer_port 0x%lx, irq %d\n", chip->codec_port, chip->io2_port, chip->mpu_port, chip->synth_port, chip->mixer_port, chip->irq); - - snd_azf3328_dbgmisc("io2 %02x %02x %02x %02x %02x %02x\n", snd_azf3328_io2_read(chip, 0), snd_azf3328_io2_read(chip, 1), snd_azf3328_io2_read(chip, 2), snd_azf3328_io2_read(chip, 3), snd_azf3328_io2_read(chip, 4), snd_azf3328_io2_read(chip, 5)); - - for (tmp=0; tmp <= 0x01; tmp += 1) - snd_azf3328_dbgmisc("0x%02x: opl 0x%04x, mpu300 0x%04x, mpu310 0x%04x, mpu320 0x%04x, mpu330 0x%04x\n", tmp, inb(0x388 + tmp), inb(0x300 + tmp), inb(0x310 + tmp), inb(0x320 + tmp), inb(0x330 + tmp)); - + snd_azf3328_debug_show_ports(chip); + if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_azf3328_free(chip); - return err; + goto out_err; } /* create mixer interface & switches */ if ((err = snd_azf3328_mixer_new(chip)) < 0) - return err; + goto out_err; #if 0 /* set very low bitrate to reduce noise and power consumption? */ @@ -1404,22 +1714,34 @@ static int __devinit snd_azf3328_create(snd_card_t * card, #endif /* standard chip init stuff */ - spin_lock_irq(&chip->reg_lock); - outb(DMA_PLAY_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port + IDX_IO_PLAY_FLAGS); - outb(DMA_PLAY_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port + IDX_IO_SOMETHING_FLAGS); - outb(DMA_PLAY_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port + IDX_IO_REC_FLAGS); - outb(0x0, chip->codec_port + IDX_IO_IRQ63H); + /* default IRQ init value */ + tmp = DMA_PLAY_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE; + spin_lock_irq(&chip->reg_lock); + snd_azf3328_codec_outb(chip, IDX_IO_PLAY_FLAGS, tmp); + snd_azf3328_codec_outb(chip, IDX_IO_REC_FLAGS, tmp); + snd_azf3328_codec_outb(chip, IDX_IO_SOMETHING_FLAGS, tmp); + snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x00); /* disable timer */ spin_unlock_irq(&chip->reg_lock); snd_card_set_dev(card, &pci->dev); *rchip = chip; - return 0; + + err = 0; + goto out; + +out_err: + if (chip) + snd_azf3328_free(chip); + pci_disable_device(pci); + +out: + return err; } -static int __devinit snd_azf3328_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) +static int __devinit +snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { static int dev; snd_card_t *card; @@ -1443,21 +1765,22 @@ static int __devinit snd_azf3328_probe(struct pci_dev *pci, strcpy(card->shortname, "Aztech AZF3328 (PCI168)"); if ((err = snd_azf3328_create(card, pci, pci_id->driver_data, &chip)) < 0) { - snd_card_free(card); - return err; + goto out_err; } if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_MPU401, chip->mpu_port, 1, pci->irq, 0, &chip->rmidi)) < 0) { snd_printk(KERN_ERR "azf3328: no MPU-401 device at 0x%lx?\n", chip->mpu_port); - snd_card_free(card); - return err; + goto out_err; + } + + if ((err = snd_azf3328_timer(chip, 0)) < 0) { + goto out_err; } if ((err = snd_azf3328_pcm(chip, 0)) < 0) { - snd_card_free(card); - return err; + goto out_err; } if (snd_opl3_create(card, chip->synth_port, chip->synth_port+2, @@ -1466,40 +1789,46 @@ static int __devinit snd_azf3328_probe(struct pci_dev *pci, chip->synth_port, chip->synth_port+2 ); } else { if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { - snd_card_free(card); - return err; + goto out_err; } } - snd_azf3328_dbgio(chip, "create"); - sprintf(card->longname, "%s at 0x%lx, irq %i", card->shortname, chip->codec_port, chip->irq); if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; + goto out_err; } #ifdef MODULE printk( -"azt3328: Experimental driver for Aztech AZF3328-based soundcards such as PCI168.\n" -"azt3328: ZERO support from Aztech: you might think hard about future purchase.\n" -"azt3328: Feel free to contact hw7oshyuv3001@sneakemail.com for bug reports etc.!\n"); +"azt3328: Sound driver for Aztech AZF3328-based soundcards such as PCI168\n" +"azt3328: (hardware was completely undocumented - ZERO support from Aztech).\n" +"azt3328: Feel free to contact andi AT lisas.de for bug reports etc.!\n" +"azt3328: User-scalable sequencer timer set to %dHz (1024000Hz / %d).\n", + 1024000 / seqtimer_scaling, seqtimer_scaling); #endif if (snd_azf3328_config_joystick(chip, dev) < 0) - snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR, - snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY); + snd_azf3328_io2_outb(chip, IDX_IO2_LEGACY_ADDR, + snd_azf3328_io2_inb(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY); pci_set_drvdata(pci, card); dev++; + err = 0; + goto out; + +out_err: + snd_card_free(card); + +out: snd_azf3328_dbgcallleave(); - return 0; + return err; } -static void __devexit snd_azf3328_remove(struct pci_dev *pci) +static void __devexit +snd_azf3328_remove(struct pci_dev *pci) { snd_azf3328_dbgcallenter(); snd_card_free(pci_get_drvdata(pci)); @@ -1515,7 +1844,8 @@ static struct pci_driver driver = { .remove = __devexit_p(snd_azf3328_remove), }; -static int __init alsa_card_azf3328_init(void) +static int __init +alsa_card_azf3328_init(void) { int err; snd_azf3328_dbgcallenter(); @@ -1524,7 +1854,8 @@ static int __init alsa_card_azf3328_init(void) return err; } -static void __exit alsa_card_azf3328_exit(void) +static void __exit +alsa_card_azf3328_exit(void) { snd_azf3328_dbgcallenter(); pci_unregister_driver(&driver); diff --git a/sound/pci/azt3328.h b/sound/pci/azt3328.h index 7e0e7918097..f489bdaf6d4 100644 --- a/sound/pci/azt3328.h +++ b/sound/pci/azt3328.h @@ -1,19 +1,17 @@ -#ifndef __SOUND_AZF3328_H -#define __SOUND_AZF3328_H +#ifndef __SOUND_AZT3328_H +#define __SOUND_AZT3328_H -/* type argument to use for the I/O functions */ -#define WORD_VALUE 0x1000 -#define DWORD_VALUE 0x2000 -#define BYTE_VALUE 0x4000 +/* "PU" == "power-up value", as tested on PCI168 PCI rev. 10 */ /*** main I/O area port indices ***/ /* (only 0x70 of 0x80 bytes saved/restored by Windows driver) */ -/* the driver initialisation suggests a layout of 3 main areas: - * from 0x00 (playback), from 0x20 (recording) and from 0x40 (maybe DirectX - * timer ???). and probably another area from 0x60 to 0x6f - * (IRQ management, power management etc. ???). */ -/* playback area */ -#define IDX_IO_PLAY_FLAGS 0x00 +/* the driver initialisation suggests a layout of 4 main areas: + * from 0x00 (playback), from 0x20 (recording) and from 0x40 (maybe MPU401??). + * And another area from 0x60 to 0x6f (DirectX timer, IRQ management, + * power management etc.???). */ + +/** playback area **/ +#define IDX_IO_PLAY_FLAGS 0x00 /* PU:0x0000 */ /* able to reactivate output after output muting due to 8/16bit * output change, just like 0x0002. * 0x0001 is the only bit that's able to start the DMA counter */ @@ -29,7 +27,7 @@ #define DMA_EPILOGUE_SOMETHING 0x0010 #define DMA_SOMETHING_ELSE 0x0020 /* ??? */ #define SOMETHING_UNMODIFIABLE 0xffc0 /* unused ? not modifiable */ -#define IDX_IO_PLAY_IRQMASK 0x02 +#define IDX_IO_PLAY_IRQTYPE 0x02 /* PU:0x0001 */ /* write back to flags in case flags are set, in order to ACK IRQ in handler * (bit 1 of port 0x64 indicates interrupt for one of these three types) * sometimes in this case it just writes 0xffff to globally ACK all IRQs @@ -41,36 +39,39 @@ #define IRQMASK_SOME_STATUS_1 0x0008 /* \ related bits */ #define IRQMASK_SOME_STATUS_2 0x0010 /* / (checked together in loop) */ #define IRQMASK_UNMODIFIABLE 0xffe0 /* unused ? not modifiable */ -#define IDX_IO_PLAY_DMA_START_1 0x04 /* start address of 1st DMA play area */ -#define IDX_IO_PLAY_DMA_START_2 0x08 /* start address of 2nd DMA play area */ -#define IDX_IO_PLAY_DMA_LEN_1 0x0c /* length of 1st DMA play area */ -#define IDX_IO_PLAY_DMA_LEN_2 0x0e /* length of 2nd DMA play area */ -#define IDX_IO_PLAY_DMA_CURRPOS 0x10 /* current DMA position */ -#define IDX_IO_PLAY_DMA_CURROFS 0x14 /* offset within current DMA play area */ -#define IDX_IO_PLAY_SOUNDFORMAT 0x16 +#define IDX_IO_PLAY_DMA_START_1 0x04 /* start address of 1st DMA play area, PU:0x00000000 */ +#define IDX_IO_PLAY_DMA_START_2 0x08 /* start address of 2nd DMA play area, PU:0x00000000 */ +#define IDX_IO_PLAY_DMA_LEN_1 0x0c /* length of 1st DMA play area, PU:0x0000 */ +#define IDX_IO_PLAY_DMA_LEN_2 0x0e /* length of 2nd DMA play area, PU:0x0000 */ +#define IDX_IO_PLAY_DMA_CURRPOS 0x10 /* current DMA position, PU:0x00000000 */ +#define IDX_IO_PLAY_DMA_CURROFS 0x14 /* offset within current DMA play area, PU:0x0000 */ +#define IDX_IO_PLAY_SOUNDFORMAT 0x16 /* PU:0x0010 */ /* all unspecified bits can't be modified */ #define SOUNDFORMAT_FREQUENCY_MASK 0x000f + #define SOUNDFORMAT_XTAL1 0x00 + #define SOUNDFORMAT_XTAL2 0x01 /* all _SUSPECTED_ values are not used by Windows drivers, so we don't * have any hard facts, only rough measurements */ - #define SOUNDFORMAT_FREQ_SUSPECTED_4000 0x0c - #define SOUNDFORMAT_FREQ_SUSPECTED_4800 0x0a - #define SOUNDFORMAT_FREQ_5510 0x0d - #define SOUNDFORMAT_FREQ_6620 0x0b - #define SOUNDFORMAT_FREQ_8000 0x00 /* also 0x0e ? */ - #define SOUNDFORMAT_FREQ_9600 0x08 - #define SOUNDFORMAT_FREQ_SUSPECTED_12000 0x09 - #define SOUNDFORMAT_FREQ_11025 0x01 /* also 0x0f ? */ - #define SOUNDFORMAT_FREQ_16000 0x02 - #define SOUNDFORMAT_FREQ_22050 0x03 - #define SOUNDFORMAT_FREQ_32000 0x04 - #define SOUNDFORMAT_FREQ_44100 0x05 - #define SOUNDFORMAT_FREQ_48000 0x06 - #define SOUNDFORMAT_FREQ_SUSPECTED_64000 0x07 + #define SOUNDFORMAT_FREQ_SUSPECTED_4000 0x0c | SOUNDFORMAT_XTAL1 + #define SOUNDFORMAT_FREQ_SUSPECTED_4800 0x0a | SOUNDFORMAT_XTAL1 + #define SOUNDFORMAT_FREQ_5510 0x0c | SOUNDFORMAT_XTAL2 + #define SOUNDFORMAT_FREQ_6620 0x0a | SOUNDFORMAT_XTAL2 + #define SOUNDFORMAT_FREQ_8000 0x00 | SOUNDFORMAT_XTAL1 /* also 0x0e | SOUNDFORMAT_XTAL1? */ + #define SOUNDFORMAT_FREQ_9600 0x08 | SOUNDFORMAT_XTAL1 + #define SOUNDFORMAT_FREQ_11025 0x00 | SOUNDFORMAT_XTAL2 /* also 0x0e | SOUNDFORMAT_XTAL2? */ + #define SOUNDFORMAT_FREQ_SUSPECTED_13240 0x08 | SOUNDFORMAT_XTAL2 /* seems to be 6620 *2 */ + #define SOUNDFORMAT_FREQ_16000 0x02 | SOUNDFORMAT_XTAL1 + #define SOUNDFORMAT_FREQ_22050 0x02 | SOUNDFORMAT_XTAL2 + #define SOUNDFORMAT_FREQ_32000 0x04 | SOUNDFORMAT_XTAL1 + #define SOUNDFORMAT_FREQ_44100 0x04 | SOUNDFORMAT_XTAL2 + #define SOUNDFORMAT_FREQ_48000 0x06 | SOUNDFORMAT_XTAL1 + #define SOUNDFORMAT_FREQ_SUSPECTED_66200 0x06 | SOUNDFORMAT_XTAL2 /* 66200 (13240 * 5); 64000 may have been nicer :-\ */ #define SOUNDFORMAT_FLAG_16BIT 0x0010 #define SOUNDFORMAT_FLAG_2CHANNELS 0x0020 -/* recording area (see also: playback bit flag definitions) */ -#define IDX_IO_REC_FLAGS 0x20 /* ?? */ -#define IDX_IO_REC_IRQMASK 0x22 /* ?? */ + +/** recording area (see also: playback bit flag definitions) **/ +#define IDX_IO_REC_FLAGS 0x20 /* ??, PU:0x0000 */ +#define IDX_IO_REC_IRQTYPE 0x22 /* ??, PU:0x0000 */ #define IRQ_REC_SOMETHING 0x0001 /* something & ACK */ #define IRQ_FINISHED_RECBUF_1 0x0002 /* 1st dmabuf finished & ACK */ #define IRQ_FINISHED_RECBUF_2 0x0004 /* 2nd dmabuf finished & ACK */ @@ -78,39 +79,47 @@ * but OTOH they are most likely at port 0x22 instead */ #define IRQMASK_SOME_STATUS_1 0x0008 /* \ related bits */ #define IRQMASK_SOME_STATUS_2 0x0010 /* / (checked together in loop) */ -#define IDX_IO_REC_DMA_START_1 0x24 -#define IDX_IO_REC_DMA_START_2 0x28 -#define IDX_IO_REC_DMA_LEN_1 0x2c -#define IDX_IO_REC_DMA_LEN_2 0x2e -#define IDX_IO_REC_DMA_CURRPOS 0x30 -#define IDX_IO_REC_DMA_CURROFS 0x34 -#define IDX_IO_REC_SOUNDFORMAT 0x36 -/* some third area ? (after playback and recording) */ -#define IDX_IO_SOMETHING_FLAGS 0x40 /* gets set to 0x34 just like port 0x0 and 0x20 on card init */ +#define IDX_IO_REC_DMA_START_1 0x24 /* PU:0x00000000 */ +#define IDX_IO_REC_DMA_START_2 0x28 /* PU:0x00000000 */ +#define IDX_IO_REC_DMA_LEN_1 0x2c /* PU:0x0000 */ +#define IDX_IO_REC_DMA_LEN_2 0x2e /* PU:0x0000 */ +#define IDX_IO_REC_DMA_CURRPOS 0x30 /* PU:0x00000000 */ +#define IDX_IO_REC_DMA_CURROFS 0x34 /* PU:0x00000000 */ +#define IDX_IO_REC_SOUNDFORMAT 0x36 /* PU:0x0000 */ + +/** hmm, what is this I/O area for? MPU401?? (after playback, recording, ???, timer) **/ +#define IDX_IO_SOMETHING_FLAGS 0x40 /* gets set to 0x34 just like port 0x0 and 0x20 on card init, PU:0x0000 */ /* general */ -#define IDX_IO_60H 0x60 /* writing 0xffff returns 0xffff */ -#define IDX_IO_62H 0x62 /* writing to WORD 0x0062 can hang the box ! --> responsible for IRQ management as a whole ?? */ -#define IDX_IO_IRQ63H 0x63 /* FIXME !! */ - #define IO_IRQ63H_SOMETHING 0x04 /* being set in IRQ handler in case port 0x00 had 0x0020 set upon IRQ handler */ +#define IDX_IO_42H 0x42 /* PU:0x0001 */ + +/** DirectX timer, main interrupt area (FIXME: and something else?) **/ +#define IDX_IO_TIMER_VALUE 0x60 /* found this timer area by pure luck :-) */ + #define TIMER_VALUE_MASK 0x000fffffUL /* timer countdown value; triggers IRQ when timer is finished */ + #define TIMER_ENABLE_COUNTDOWN 0x01000000UL /* activate the timer countdown */ + #define TIMER_ENABLE_IRQ 0x02000000UL /* trigger timer IRQ on zero transition */ + #define TIMER_ACK_IRQ 0x04000000UL /* being set in IRQ handler in case port 0x00 (hmm, not port 0x64!?!?) had 0x0020 set upon IRQ handler */ #define IDX_IO_IRQSTATUS 0x64 #define IRQ_PLAYBACK 0x0001 #define IRQ_RECORDING 0x0002 #define IRQ_MPU401 0x0010 - #define IRQ_SOMEIRQ 0x0020 /* ???? */ - #define IRQ_WHO_KNOWS_UNUSED 0x00e0 /* probably unused */ + #define IRQ_TIMER 0x0020 /* DirectX timer */ + #define IRQ_UNKNOWN1 0x0040 /* probably unused */ + #define IRQ_UNKNOWN2 0x0080 /* probably unused */ #define IDX_IO_66H 0x66 /* writing 0xffff returns 0x0000 */ -#define IDX_IO_SOME_VALUE 0x68 /* this is always set to 0x3ff, and writable; maybe some buffer limit, but I couldn't find out more */ -#define IDX_IO_6AH 0x6A /* this WORD can be set to have bits 0x0028 activated; actually inhibits PCM playback !!! maybe power management ?? */ -#define IDX_IO_6CH 0x6C /* this WORD can have all its bits activated ? */ +#define IDX_IO_SOME_VALUE 0x68 /* this is set to e.g. 0x3ff or 0x300, and writable; maybe some buffer limit, but I couldn't find out more, PU:0x00ff */ +#define IDX_IO_6AH 0x6A /* this WORD can be set to have bits 0x0028 activated; actually inhibits PCM playback!!! maybe power management?? */ +#define IDX_IO_6CH 0x6C #define IDX_IO_6EH 0x6E /* writing 0xffff returns 0x83fe */ /* further I/O indices not saved/restored, so probably not used */ + /*** I/O 2 area port indices ***/ /* (only 0x06 of 0x08 bytes saved/restored by Windows driver) */ #define IDX_IO2_LEGACY_ADDR 0x04 - #define LEGACY_SOMETHING 0x01 /* OPL3 ?? */ + #define LEGACY_SOMETHING 0x01 /* OPL3?? */ #define LEGACY_JOY 0x08 + /*** mixer I/O area port indices ***/ /* (only 0x22 of 0x40 bytes saved/restored by Windows driver) * generally spoken: AC97 register index = AZF3328 mixer reg index + 2 @@ -148,18 +157,18 @@ /* unlisted bits are unmodifiable */ #define MIXER_ADVCTL1_3DWIDTH_MASK 0x000e #define MIXER_ADVCTL1_HIFI3D_MASK 0x0300 -#define IDX_MIXER_ADVCTL2 0x20 /* resembles AC97_GENERAL_PURPOSE reg ! */ +#define IDX_MIXER_ADVCTL2 0x20 /* resembles AC97_GENERAL_PURPOSE reg! */ /* unlisted bits are unmodifiable */ - #define MIXER_ADVCTL2_BIT7 0x0080 /* WaveOut 3D Bypass ? mutes WaveOut at LineOut */ - #define MIXER_ADVCTL2_BIT8 0x0100 /* is this Modem Out Select ? */ - #define MIXER_ADVCTL2_BIT9 0x0200 /* Mono Select Source ? */ - #define MIXER_ADVCTL2_BIT13 0x2000 /* 3D enable ? */ + #define MIXER_ADVCTL2_BIT7 0x0080 /* WaveOut 3D Bypass? mutes WaveOut at LineOut */ + #define MIXER_ADVCTL2_BIT8 0x0100 /* is this Modem Out Select? */ + #define MIXER_ADVCTL2_BIT9 0x0200 /* Mono Select Source? */ + #define MIXER_ADVCTL2_BIT13 0x2000 /* 3D enable? */ #define MIXER_ADVCTL2_BIT15 0x8000 /* unknown */ -#define IDX_MIXER_SOMETHING30H 0x30 /* used, but unknown ??? */ +#define IDX_MIXER_SOMETHING30H 0x30 /* used, but unknown??? */ /* driver internal flags */ #define SET_CHAN_LEFT 1 #define SET_CHAN_RIGHT 2 -#endif /* __SOUND_AZF3328_H */ +#endif /* __SOUND_AZT3328_H */ -- cgit v1.2.3 From 9529a5bae10118fd08edfd667cac19f94fb7264a Mon Sep 17 00:00:00 2001 From: Lee Revell Date: Tue, 25 Oct 2005 11:25:29 +0200 Subject: [ALSA] emu10k1 - Use 31 bit DMA mask for Audigy Modules: EMU10K1/EMU10K2 driver It appears that either the Audigy DMA engine or the Linux kernel cannot handle 32 bit DMA with this device. Problem manifests as noise when using more than 2GB of RAM, possibly only on 64 bit machines. The OSS driver actually uses a 29 bit DMA mask for both devices, this seems like overkill for now. Signed-off-by: Lee Revell Signed-off-by: Takashi Iwai --- include/sound/emu10k1.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h index 46e3c0bf3c9..8411c7ef6f1 100644 --- a/include/sound/emu10k1.h +++ b/include/sound/emu10k1.h @@ -48,7 +48,8 @@ /* FIXME? - according to the OSS driver the EMU10K1 needs a 29 bit DMA mask */ #define EMU10K1_DMA_MASK 0x7fffffffUL /* 31bit */ -#define AUDIGY_DMA_MASK 0xffffffffUL /* 32bit */ +#define AUDIGY_DMA_MASK 0x7fffffffUL /* 31bit FIXME - 32 should work? */ + /* See ALSA bug #1276 - rlrevell */ #define TMEMSIZE 256*1024 #define TMEMSIZEREG 4 -- cgit v1.2.3 From 6d6f9156209892bc0cdc3354394ac947db5e32f1 Mon Sep 17 00:00:00 2001 From: Karoly Lorentey Date: Tue, 25 Oct 2005 11:50:25 +0200 Subject: [ALSA] intel8x0 - Add ac97_quirk for Dell Inspiron 8600 Modules: Intel8x0 driver Add AC97_TUNE_HP_ONLY quirk for Dell Inspiron 8600. Signed-off-by: Karoly Lorentey Signed-off-by: Takashi Iwai --- sound/pci/intel8x0.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index c2f05021532..8eb966505d2 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -1765,6 +1765,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { .name = "Dell Unknown", /* STAC9750/51 */ .type = AC97_TUNE_HP_ONLY }, + { + .subvendor = 0x1028, + .subdevice = 0x0191, + .name = "Dell Inspiron 8600", + .type = AC97_TUNE_HP_ONLY + }, { .subvendor = 0x103c, .subdevice = 0x006d, -- cgit v1.2.3 From 708f997169d5674177450f25ef3ac6b4f2562690 Mon Sep 17 00:00:00 2001 From: Konstantin Baydarov Date: Thu, 27 Oct 2005 17:25:02 +0200 Subject: [ALSA] AMD Au1x00 driver: buggy spinlocks Modules: MIPS AU1x00 driver AMD Au1x00 ALSA driver fails compilation with the alternate spinlock implementation because it doesn't do locking/unlocking correctly in some places (passes spinlock by value). Signed-off-by: Konstantin Baydarov Signed-off-by: Sergei Shtylyov Signed-off-by: Takashi Iwai --- sound/mips/au1x00.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c index 2df78a64c7f..d08a42b24b1 100644 --- a/sound/mips/au1x00.c +++ b/sound/mips/au1x00.c @@ -472,7 +472,7 @@ snd_au1000_ac97_read(ac97_t *ac97, unsigned short reg) u32 volatile cmd; u16 volatile data; int i; - spin_lock(au1000->ac97_lock); + spin_lock(&au1000->ac97_lock); /* would rather use the interupt than this polling but it works and I can't get the interupt driven case to work efficiently */ for (i = 0; i < 0x5000; i++) @@ -495,7 +495,7 @@ get the interupt driven case to work efficiently */ } data = au1000->ac97_ioport->cmd & 0xffff; - spin_unlock(au1000->ac97_lock); + spin_unlock(&au1000->ac97_lock); return data; @@ -507,7 +507,7 @@ snd_au1000_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val) { u32 cmd; int i; - spin_lock(au1000->ac97_lock); + spin_lock(&au1000->ac97_lock); /* would rather use the interupt than this polling but it works and I can't get the interupt driven case to work efficiently */ for (i = 0; i < 0x5000; i++) @@ -520,7 +520,7 @@ get the interupt driven case to work efficiently */ cmd &= ~AC97C_READ; cmd |= ((u32) val << AC97C_WD_BIT); au1000->ac97_ioport->cmd = cmd; - spin_unlock(au1000->ac97_lock); + spin_unlock(&au1000->ac97_lock); } static void snd_au1000_ac97_free(ac97_t *ac97) -- cgit v1.2.3 From beef08a54524e4a657bfb66b6b9758f8bc54fd17 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 27 Oct 2005 20:55:38 +0200 Subject: [ALSA] intel8x0 - Fix irq handler registration Modules: Intel8x0 driver - Request irq handler after proper initialization - Don't override always buggy_irq option for Nvidia Signed-off-by: Takashi Iwai --- sound/pci/intel8x0.c | 47 ++++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 8eb966505d2..0801083f32d 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -69,7 +69,7 @@ static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ static int ac97_clock = 0; static char *ac97_quirk; static int buggy_semaphore; -static int buggy_irq; +static int buggy_irq = -1; /* auto-check */ static int xbox; module_param(index, int, 0444); @@ -2636,12 +2636,6 @@ static int __devinit snd_intel8x0_create(snd_card_t * card, pci->device == PCI_DEVICE_ID_INTEL_440MX) chip->fix_nocache = 1; /* enable workaround */ - /* some Nforce[2] and ICH boards have problems with IRQ handling. - * Needs to return IRQ_HANDLED for unknown irqs. - */ - if (device_type == DEVICE_NFORCE) - chip->buggy_irq = 1; - if ((err = pci_request_regions(pci, card->shortname)) < 0) { kfree(chip); pci_disable_device(pci); @@ -2682,15 +2676,6 @@ static int __devinit snd_intel8x0_create(snd_card_t * card, } port_inited: - if (request_irq(pci->irq, snd_intel8x0_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_intel8x0_free(chip); - return -EBUSY; - } - chip->irq = pci->irq; - pci_set_master(pci); - synchronize_irq(chip->irq); - chip->bdbars_count = bdbars[device_type]; /* initialize offsets */ @@ -2741,13 +2726,27 @@ static int __devinit snd_intel8x0_create(snd_card_t * card, int_sta_masks = 0; for (i = 0; i < chip->bdbars_count; i++) { ichdev = &chip->ichd[i]; - ichdev->bdbar = ((u32 *)chip->bdbars.area) + (i * ICH_MAX_FRAGS * 2); - ichdev->bdbar_addr = chip->bdbars.addr + (i * sizeof(u32) * ICH_MAX_FRAGS * 2); + ichdev->bdbar = ((u32 *)chip->bdbars.area) + + (i * ICH_MAX_FRAGS * 2); + ichdev->bdbar_addr = chip->bdbars.addr + + (i * sizeof(u32) * ICH_MAX_FRAGS * 2); int_sta_masks |= ichdev->int_sta_mask; } - chip->int_sta_reg = device_type == DEVICE_ALI ? ICH_REG_ALI_INTERRUPTSR : ICH_REG_GLOB_STA; + chip->int_sta_reg = device_type == DEVICE_ALI ? + ICH_REG_ALI_INTERRUPTSR : ICH_REG_GLOB_STA; chip->int_sta_mask = int_sta_masks; + /* request irq after initializaing int_sta_mask, etc */ + if (request_irq(pci->irq, snd_intel8x0_interrupt, + SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip)) { + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + snd_intel8x0_free(chip); + return -EBUSY; + } + chip->irq = pci->irq; + pci_set_master(pci); + synchronize_irq(chip->irq); + if ((err = snd_intel8x0_chip_init(chip, 1)) < 0) { snd_intel8x0_free(chip); return err; @@ -2827,6 +2826,16 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci, } } + if (buggy_irq < 0) { + /* some Nforce[2] and ICH boards have problems with IRQ handling. + * Needs to return IRQ_HANDLED for unknown irqs. + */ + if (pci_id->driver_data == DEVICE_NFORCE) + buggy_irq = 1; + else + buggy_irq = 0; + } + if ((err = snd_intel8x0_create(card, pci, pci_id->driver_data, &chip)) < 0) { snd_card_free(card); -- cgit v1.2.3 From 091e95ee7febf894603475c44d51f8ec4fab4328 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 27 Oct 2005 20:56:35 +0200 Subject: [ALSA] ac97 - Fix confliction of DRA and surround slots Modules: AC97 Codec Fixed the confliction of DRA and surround slots 7/8. Signed-off-by: Takashi Iwai --- sound/pci/ac97/ac97_codec.c | 2 ++ sound/pci/ac97/ac97_pcm.c | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 3b589104510..9bde76c4c6a 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -2046,6 +2046,8 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) snd_ac97_update_bits(ac97, AC97_GENERAL_PURPOSE, AC97_GP_DRSS_MASK, AC97_GP_DRSS_78); if ((snd_ac97_read(ac97, AC97_GENERAL_PURPOSE) & AC97_GP_DRSS_MASK) == AC97_GP_DRSS_78) ac97->flags |= AC97_DOUBLE_RATE; + /* restore to slots 10/11 to avoid the confliction with surrounds */ + snd_ac97_update_bits(ac97, AC97_GENERAL_PURPOSE, AC97_GP_DRSS_MASK, 0); } if (ac97->ext_id & AC97_EI_VRA) { /* VRA support */ snd_ac97_determine_rates(ac97, AC97_PCM_FRONT_DAC_RATE, 0, &ac97->rates[AC97_RATES_FRONT_DAC]); diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c index dd289b9512e..ded13165d63 100644 --- a/sound/pci/ac97/ac97_pcm.c +++ b/sound/pci/ac97/ac97_pcm.c @@ -303,6 +303,15 @@ int snd_ac97_set_rate(ac97_t *ac97, int reg, unsigned int rate) AC97_EA_DRA, dbl ? AC97_EA_DRA : 0); snd_ac97_update(ac97, reg, tmp & 0xffff); snd_ac97_read(ac97, reg); + if ((ac97->ext_id & AC97_EI_DRA) && reg == AC97_PCM_FRONT_DAC_RATE) { + /* Intel controllers require double rate data to be put in + * slots 7+8 + */ + snd_ac97_update_bits(ac97, AC97_GENERAL_PURPOSE, + AC97_GP_DRSS_MASK, + dbl ? AC97_GP_DRSS_78 : 0); + snd_ac97_read(ac97, AC97_GENERAL_PURPOSE); + } return 0; } -- cgit v1.2.3 From b55bbf06e850d7561ad7bdded1f4d8c08b1e1f11 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 2 Nov 2005 11:32:52 +0100 Subject: [ALSA] usb-audio: start submitting URBs in the prepared state Modules: USB generic driver If we submit all our URBs when a playback stream is started, the first hwptr_done update for each URB happens at the same time. This results in an underrun when there isn't enough PCM data available at this point for all URBs. To avoid this, we begin submitting our URBs earlier (when the stream is prepared), with empy packets. When the stream is started, the prepare_playback_urb() call for each URB will be run only when the respective URB has completed previously, so the first hwptr_done updates will be done nicely staggered. Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/usb/usbaudio.c | 100 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 62 insertions(+), 38 deletions(-) diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 8818918c423..99dae024b64 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include @@ -185,7 +184,6 @@ struct snd_usb_substream { unsigned int num_formats; /* number of supported audio formats (list) */ struct list_head fmt_list; /* format list */ spinlock_t lock; - struct tasklet_struct start_period_elapsed; /* for start trigger */ struct snd_urb_ops ops; /* callbacks (must be filled at init) */ }; @@ -479,6 +477,28 @@ static int retire_playback_sync_urb_hs(snd_usb_substream_t *subs, return 0; } +/* + * Prepare urb for streaming before playback starts. + * + * We don't care about (or have) any data, so we just send a transfer delimiter. + */ +static int prepare_startup_playback_urb(snd_usb_substream_t *subs, + snd_pcm_runtime_t *runtime, + struct urb *urb) +{ + unsigned int i; + snd_urb_ctx_t *ctx = urb->context; + + urb->dev = ctx->subs->dev; + urb->number_of_packets = subs->packs_per_ms; + for (i = 0; i < subs->packs_per_ms; ++i) { + urb->iso_frame_desc[i].offset = 0; + urb->iso_frame_desc[i].length = 0; + } + urb->transfer_buffer_length = 0; + return 0; +} + /* * prepare urb for playback data pipe * @@ -568,12 +588,8 @@ static int prepare_playback_urb(snd_usb_substream_t *subs, subs->hwptr_done -= runtime->buffer_size; spin_unlock_irqrestore(&subs->lock, flags); urb->transfer_buffer_length = offs * stride; - if (period_elapsed) { - if (likely(subs->running)) - snd_pcm_period_elapsed(subs->pcm_substream); - else - tasklet_hi_schedule(&subs->start_period_elapsed); - } + if (period_elapsed) + snd_pcm_period_elapsed(subs->pcm_substream); return 0; } @@ -588,22 +604,12 @@ static int retire_playback_urb(snd_usb_substream_t *subs, return 0; } -/* - * Delay the snd_pcm_period_elapsed() call until after the start trigger - * callback so that we're not longer in the substream's lock. - */ -static void start_period_elapsed(unsigned long data) -{ - snd_usb_substream_t *subs = (snd_usb_substream_t *)data; - snd_pcm_period_elapsed(subs->pcm_substream); -} - /* */ static struct snd_urb_ops audio_urb_ops[2] = { { - .prepare = prepare_playback_urb, + .prepare = prepare_startup_playback_urb, .retire = retire_playback_urb, .prepare_sync = prepare_playback_sync_urb, .retire_sync = retire_playback_sync_urb, @@ -618,7 +624,7 @@ static struct snd_urb_ops audio_urb_ops[2] = { static struct snd_urb_ops audio_urb_ops_high_speed[2] = { { - .prepare = prepare_playback_urb, + .prepare = prepare_startup_playback_urb, .retire = retire_playback_urb, .prepare_sync = prepare_playback_sync_urb_hs, .retire_sync = retire_playback_sync_urb_hs, @@ -863,25 +869,40 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(snd_pcm_substream_t *substream) /* - * start/stop substream + * start/stop playback substream */ -static int snd_usb_pcm_trigger(snd_pcm_substream_t *substream, int cmd) +static int snd_usb_pcm_playback_trigger(snd_pcm_substream_t *substream, + int cmd) { - snd_usb_substream_t *subs = (snd_usb_substream_t *)substream->runtime->private_data; - int err; + snd_usb_substream_t *subs = substream->runtime->private_data; switch (cmd) { case SNDRV_PCM_TRIGGER_START: - err = start_urbs(subs, substream->runtime); - break; + subs->ops.prepare = prepare_playback_urb; + return 0; case SNDRV_PCM_TRIGGER_STOP: - err = deactivate_urbs(subs, 0, 0); - break; + return deactivate_urbs(subs, 0, 0); default: - err = -EINVAL; - break; + return -EINVAL; + } +} + +/* + * start/stop capture substream + */ +static int snd_usb_pcm_capture_trigger(snd_pcm_substream_t *substream, + int cmd) +{ + snd_usb_substream_t *subs = substream->runtime->private_data; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + return start_urbs(subs, substream->runtime); + case SNDRV_PCM_TRIGGER_STOP: + return deactivate_urbs(subs, 0, 0); + default: + return -EINVAL; } - return err < 0 ? err : 0; } @@ -1413,7 +1434,7 @@ static int snd_usb_hw_free(snd_pcm_substream_t *substream) static int snd_usb_pcm_prepare(snd_pcm_substream_t *substream) { snd_pcm_runtime_t *runtime = substream->runtime; - snd_usb_substream_t *subs = (snd_usb_substream_t *)runtime->private_data; + snd_usb_substream_t *subs = runtime->private_data; if (! subs->cur_audiofmt) { snd_printk(KERN_ERR "usbaudio: no format is specified!\n"); @@ -1433,7 +1454,13 @@ static int snd_usb_pcm_prepare(snd_pcm_substream_t *substream) deactivate_urbs(subs, 0, 1); wait_clear_urbs(subs); - return 0; + /* for playback, submit the URBs now; otherwise, the first hwptr_done + * updates for all URBs would happen at the same time when starting */ + if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) { + subs->ops.prepare = prepare_startup_playback_urb; + return start_urbs(subs, runtime); + } else + return 0; } static snd_pcm_hardware_t snd_usb_playback = @@ -1847,7 +1874,7 @@ static snd_pcm_ops_t snd_usb_playback_ops = { .hw_params = snd_usb_hw_params, .hw_free = snd_usb_hw_free, .prepare = snd_usb_pcm_prepare, - .trigger = snd_usb_pcm_trigger, + .trigger = snd_usb_pcm_playback_trigger, .pointer = snd_usb_pcm_pointer, .page = snd_pcm_get_vmalloc_page, }; @@ -1859,7 +1886,7 @@ static snd_pcm_ops_t snd_usb_capture_ops = { .hw_params = snd_usb_hw_params, .hw_free = snd_usb_hw_free, .prepare = snd_usb_pcm_prepare, - .trigger = snd_usb_pcm_trigger, + .trigger = snd_usb_pcm_capture_trigger, .pointer = snd_usb_pcm_pointer, .page = snd_pcm_get_vmalloc_page, }; @@ -2078,9 +2105,6 @@ static void init_substream(snd_usb_stream_t *as, int stream, struct audioformat INIT_LIST_HEAD(&subs->fmt_list); spin_lock_init(&subs->lock); - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - tasklet_init(&subs->start_period_elapsed, start_period_elapsed, - (unsigned long)subs); subs->stream = as; subs->direction = stream; -- cgit v1.2.3 From 09f9a891e9c8a3a5f75216c292a5420eb73a9c8b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 2 Nov 2005 11:54:36 +0100 Subject: [ALSA] ice1724 - Add SPDIF support to Shuttle SN25P Modules: ICE1712 driver Added the SPDIF support to Shuttle SN25P. Signed-off-by: Takashi Iwai --- sound/pci/ice1712/vt1720_mobo.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/sound/pci/ice1712/vt1720_mobo.c b/sound/pci/ice1712/vt1720_mobo.c index ab61e383024..90c85cd9547 100644 --- a/sound/pci/ice1712/vt1720_mobo.c +++ b/sound/pci/ice1712/vt1720_mobo.c @@ -71,6 +71,22 @@ static unsigned char k8x800_eeprom[] __devinitdata = { 0x00, /* - */ }; +static unsigned char sn25p_eeprom[] __devinitdata = { + 0x01, /* SYSCONF: clock 256, 1ADC, 2DACs */ + 0x02, /* ACLINK: ACLINK, packed */ + 0x00, /* I2S: - */ + 0x41, /* SPDIF: - */ + 0xff, /* GPIO_DIR */ + 0xff, /* GPIO_DIR1 */ + 0x00, /* - */ + 0xff, /* GPIO_MASK */ + 0xff, /* GPIO_MASK1 */ + 0x00, /* - */ + 0x00, /* GPIO_STATE */ + 0x00, /* GPIO_STATE1 */ + 0x00, /* - */ +}; + /* entry point */ struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = { @@ -113,11 +129,11 @@ struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = { { .subvendor = VT1720_SUBDEVICE_SN25P, .name = "Shuttle SN25P", - /* identical with k8x800 */ + .model = "sn25p", .chip_init = k8x800_init, .build_controls = k8x800_add_controls, .eeprom_size = sizeof(k8x800_eeprom), - .eeprom_data = k8x800_eeprom, + .eeprom_data = sn25p_eeprom, }, { } /* terminator */ }; -- cgit v1.2.3 From b7027cc29e158ec2d1c5e53c69f3e9e6a0d02a48 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 2 Nov 2005 18:13:41 +0100 Subject: [ALSA] hda-codec - Show power state in proc file Modules: HDA generic driver Show the power state of each widget in proc file. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_proc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 08f6a6efc5e..39ddf1cd901 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -281,6 +281,11 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer) print_pcm_caps(buffer, codec, nid); } + if (wid_caps & AC_WCAP_POWER) + snd_iprintf(buffer, " Power: 0x%x\n", + snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_POWER_STATE, 0)); + if (wid_caps & AC_WCAP_CONN_LIST) { int c, curr = -1; if (conn_len > 1 && wid_type != AC_WID_AUD_MIX) -- cgit v1.2.3 From 985be54ba8b042923f5a76276a1c0490aa8af7a1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 2 Nov 2005 18:26:49 +0100 Subject: [ALSA] hda-codec - Minor rewrites Modules: HDA Codec driver,HDA generic driver - Make bound controls global to all patches - Clean up analog patches (for the upcoming extension to AD1988) Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 45 +++++++++++++ sound/pci/hda/hda_local.h | 22 ++++++ sound/pci/hda/patch_analog.c | 133 +++++++++++++++++++++++++++--------- sound/pci/hda/patch_realtek.c | 152 +++++++++++------------------------------- 4 files changed, 208 insertions(+), 144 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 57b5a0a83c8..0dbeeaf6113 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -820,6 +820,51 @@ int snd_hda_mixer_amp_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t return change; } +/* + * bound volume controls + * + * bind multiple volumes (# indices, from 0) + */ + +#define AMP_VAL_IDX_SHIFT 19 +#define AMP_VAL_IDX_MASK (0x0f<<19) + +int snd_hda_mixer_bind_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + unsigned long pval; + int err; + + down(&codec->spdif_mutex); /* reuse spdif_mutex */ + pval = kcontrol->private_value; + kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ + err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); + kcontrol->private_value = pval; + up(&codec->spdif_mutex); + return err; +} + +int snd_hda_mixer_bind_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + unsigned long pval; + int i, indices, err = 0, change = 0; + + down(&codec->spdif_mutex); /* reuse spdif_mutex */ + pval = kcontrol->private_value; + indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; + for (i = 0; i < indices; i++) { + kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | (i << AMP_VAL_IDX_SHIFT); + err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); + if (err < 0) + break; + change |= err; + } + kcontrol->private_value = pval; + up(&codec->spdif_mutex); + return err < 0 ? err : change; +} + /* * SPDIF out controls */ diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 810cfd2d9bb..f51a56f813c 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -27,28 +27,36 @@ * for mixer controls */ #define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19)) +/* mono volume with index (index=0,1,...) (channel=1,2) */ #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ .info = snd_hda_mixer_amp_volume_info, \ .get = snd_hda_mixer_amp_volume_get, \ .put = snd_hda_mixer_amp_volume_put, \ .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } +/* stereo volume with index */ #define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \ HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, 3, xindex, direction) +/* mono volume */ #define HDA_CODEC_VOLUME_MONO(xname, nid, channel, xindex, direction) \ HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, channel, xindex, direction) +/* stereo volume */ #define HDA_CODEC_VOLUME(xname, nid, xindex, direction) \ HDA_CODEC_VOLUME_MONO(xname, nid, 3, xindex, direction) +/* mono mute switch with index (index=0,1,...) (channel=1,2) */ #define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ .info = snd_hda_mixer_amp_switch_info, \ .get = snd_hda_mixer_amp_switch_get, \ .put = snd_hda_mixer_amp_switch_put, \ .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } +/* stereo mute switch with index */ #define HDA_CODEC_MUTE_IDX(xname, xcidx, nid, xindex, direction) \ HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, 3, xindex, direction) +/* mono mute switch */ #define HDA_CODEC_MUTE_MONO(xname, nid, channel, xindex, direction) \ HDA_CODEC_MUTE_MONO_IDX(xname, 0, nid, channel, xindex, direction) +/* stereo mute switch */ #define HDA_CODEC_MUTE(xname, nid, xindex, direction) \ HDA_CODEC_MUTE_MONO(xname, nid, 3, xindex, direction) @@ -59,6 +67,20 @@ int snd_hda_mixer_amp_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t int snd_hda_mixer_amp_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol); int snd_hda_mixer_amp_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol); +/* mono switch binding multiple inputs */ +#define HDA_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \ + { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ + .info = snd_hda_mixer_amp_switch_info, \ + .get = snd_hda_mixer_bind_switch_get, \ + .put = snd_hda_mixer_bind_switch_put, \ + .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) } + +/* stereo switch binding multiple inputs */ +#define HDA_BIND_MUTE(xname,nid,indices,dir) HDA_BIND_MUTE_MONO(xname,nid,3,indices,dir) + +int snd_hda_mixer_bind_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol); +int snd_hda_mixer_bind_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol); + int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid); int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid); diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index da6874d3988..d7d636decef 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -28,15 +28,38 @@ #include "hda_local.h" struct ad198x_spec { - struct semaphore amp_mutex; /* PCM volume/mute control mutex */ - struct hda_multi_out multiout; /* playback */ - hda_nid_t adc_nid; + snd_kcontrol_new_t *mixers[5]; + int num_mixers; + + const struct hda_verb *init_verbs[3]; /* initialization verbs + * don't forget NULL termination! + */ + unsigned int num_init_verbs; + + /* playback */ + struct hda_multi_out multiout; /* playback set-up + * max_channels, dacs must be set + * dig_out_nid and hp_nid are optional + */ + + /* capture */ + unsigned int num_adc_nids; + hda_nid_t *adc_nids; + hda_nid_t dig_in_nid; /* digital-in NID; optional */ + + /* capture source */ const struct hda_input_mux *input_mux; - unsigned int cur_mux; /* capture source */ + unsigned int cur_mux[3]; + + /* channel model */ + const struct alc_channel_mode *channel_mode; + int num_channel_mode; + + /* PCM information */ + struct hda_pcm pcm_rec[2]; /* used in alc_build_pcms() */ + + struct semaphore amp_mutex; /* PCM volume/mute control mutex */ unsigned int spdif_route; - snd_kcontrol_new_t *mixers; - const struct hda_verb *init_verbs; - struct hda_pcm pcm_rec[2]; /* PCM information */ }; /* @@ -54,8 +77,9 @@ static int ad198x_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct ad198x_spec *spec = codec->spec; + unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - ucontrol->value.enumerated.item[0] = spec->cur_mux; + ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; return 0; } @@ -63,9 +87,10 @@ static int ad198x_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct ad198x_spec *spec = codec->spec; + unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, - spec->adc_nid, &spec->cur_mux); + spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]); } /* @@ -74,22 +99,34 @@ static int ad198x_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u static int ad198x_init(struct hda_codec *codec) { struct ad198x_spec *spec = codec->spec; - snd_hda_sequence_write(codec, spec->init_verbs); + int i; + + for (i = 0; i < spec->num_init_verbs; i++) + snd_hda_sequence_write(codec, spec->init_verbs[i]); return 0; } static int ad198x_build_controls(struct hda_codec *codec) { struct ad198x_spec *spec = codec->spec; + unsigned int i; int err; - err = snd_hda_add_new_ctls(codec, spec->mixers); - if (err < 0) - return err; - if (spec->multiout.dig_out_nid) + for (i = 0; i < spec->num_mixers; i++) { + err = snd_hda_add_new_ctls(codec, spec->mixers[i]); + if (err < 0) + return err; + } + if (spec->multiout.dig_out_nid) { err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); - if (err < 0) - return err; + if (err < 0) + return err; + } + if (spec->dig_in_nid) { + err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); + if (err < 0) + return err; + } return 0; } @@ -152,7 +189,8 @@ static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo, snd_pcm_substream_t *substream) { struct ad198x_spec *spec = codec->spec; - snd_hda_codec_setup_stream(codec, spec->adc_nid, stream_tag, 0, format); + snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], + stream_tag, 0, format); return 0; } @@ -161,7 +199,8 @@ static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, snd_pcm_substream_t *substream) { struct ad198x_spec *spec = codec->spec; - snd_hda_codec_setup_stream(codec, spec->adc_nid, 0, 0, 0); + snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], + 0, 0, 0); return 0; } @@ -171,7 +210,7 @@ static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, static struct hda_pcm_stream ad198x_pcm_analog_playback = { .substreams = 1, .channels_min = 2, - .channels_max = 6, + .channels_max = 6, /* changed later */ .nid = 0, /* fill later */ .ops = { .open = ad198x_playback_pcm_open, @@ -181,7 +220,7 @@ static struct hda_pcm_stream ad198x_pcm_analog_playback = { }; static struct hda_pcm_stream ad198x_pcm_analog_capture = { - .substreams = 2, + .substreams = 1, .channels_min = 2, .channels_max = 2, .nid = 0, /* fill later */ @@ -202,6 +241,13 @@ static struct hda_pcm_stream ad198x_pcm_digital_playback = { }, }; +static struct hda_pcm_stream ad198x_pcm_digital_capture = { + .substreams = 1, + .channels_min = 2, + .channels_max = 2, + /* NID is set in alc_build_pcms */ +}; + static int ad198x_build_pcms(struct hda_codec *codec) { struct ad198x_spec *spec = codec->spec; @@ -215,7 +261,8 @@ static int ad198x_build_pcms(struct hda_codec *codec) info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels; info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nid; + info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids; + info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; if (spec->multiout.dig_out_nid) { info++; @@ -223,6 +270,10 @@ static int ad198x_build_pcms(struct hda_codec *codec) info->name = "AD198x Digital"; info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback; info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; + if (spec->dig_in_nid) { + info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture; + info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; + } } return 0; @@ -237,10 +288,15 @@ static void ad198x_free(struct hda_codec *codec) static int ad198x_resume(struct hda_codec *codec) { struct ad198x_spec *spec = codec->spec; + int i; ad198x_init(codec); - snd_hda_resume_ctls(codec, spec->mixers); - snd_hda_resume_spdif_out(codec); + for (i = 0; i < spec->num_mixers; i++) + snd_hda_resume_ctls(codec, spec->mixers[i]); + if (spec->multiout.dig_out_nid) + snd_hda_resume_spdif_out(codec); + if (spec->dig_in_nid) + snd_hda_resume_spdif_in(codec); return 0; } #endif @@ -269,6 +325,7 @@ static struct hda_codec_ops ad198x_patch_ops = { static hda_nid_t ad1986a_dac_nids[3] = { AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC }; +static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC }; static struct hda_input_mux ad1986a_capture_source = { .num_items = 7, @@ -476,10 +533,13 @@ static int patch_ad1986a(struct hda_codec *codec) spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids); spec->multiout.dac_nids = ad1986a_dac_nids; spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT; - spec->adc_nid = AD1986A_ADC; + spec->num_adc_nids = 1; + spec->adc_nids = ad1986a_adc_nids; spec->input_mux = &ad1986a_capture_source; - spec->mixers = ad1986a_mixers; - spec->init_verbs = ad1986a_init_verbs; + spec->num_mixers = 1; + spec->mixers[0] = ad1986a_mixers; + spec->num_init_verbs = 1; + spec->init_verbs[0] = ad1986a_init_verbs; codec->patch_ops = ad198x_patch_ops; @@ -495,6 +555,7 @@ static int patch_ad1986a(struct hda_codec *codec) #define AD1983_ADC 0x04 static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC }; +static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC }; static struct hda_input_mux ad1983_capture_source = { .num_items = 4, @@ -619,6 +680,7 @@ static struct hda_verb ad1983_init_verbs[] = { { } /* end */ }; + static int patch_ad1983(struct hda_codec *codec) { struct ad198x_spec *spec; @@ -634,10 +696,13 @@ static int patch_ad1983(struct hda_codec *codec) spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids); spec->multiout.dac_nids = ad1983_dac_nids; spec->multiout.dig_out_nid = AD1983_SPDIF_OUT; - spec->adc_nid = AD1983_ADC; + spec->num_adc_nids = 1; + spec->adc_nids = ad1983_adc_nids; spec->input_mux = &ad1983_capture_source; - spec->mixers = ad1983_mixers; - spec->init_verbs = ad1983_init_verbs; + spec->num_mixers = 1; + spec->mixers[0] = ad1983_mixers; + spec->num_init_verbs = 1; + spec->init_verbs[0] = ad1983_init_verbs; spec->spdif_route = 0; codec->patch_ops = ad198x_patch_ops; @@ -655,6 +720,7 @@ static int patch_ad1983(struct hda_codec *codec) #define AD1981_ADC 0x04 static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC }; +static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC }; /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */ static struct hda_input_mux ad1981_capture_source = { @@ -775,10 +841,13 @@ static int patch_ad1981(struct hda_codec *codec) spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids); spec->multiout.dac_nids = ad1981_dac_nids; spec->multiout.dig_out_nid = AD1981_SPDIF_OUT; - spec->adc_nid = AD1981_ADC; + spec->num_adc_nids = 1; + spec->adc_nids = ad1981_adc_nids; spec->input_mux = &ad1981_capture_source; - spec->mixers = ad1981_mixers; - spec->init_verbs = ad1981_init_verbs; + spec->num_mixers = 1; + spec->mixers[0] = ad1981_mixers; + spec->num_init_verbs = 1; + spec->init_verbs[0] = ad1981_init_verbs; spec->spdif_route = 0; codec->patch_ops = ad198x_patch_ops; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 48356ab0457..cffb83fdcff 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -115,8 +115,6 @@ struct alc_spec { /* PCM information */ struct hda_pcm pcm_rec[2]; /* used in alc_build_pcms() */ - struct semaphore bind_mutex; /* for bound controls */ - /* dynamic controls, init_verbs and input_mux */ struct auto_pin_cfg autocfg; unsigned int num_kctl_alloc, num_kctl_used; @@ -219,73 +217,6 @@ static int alc880_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc } -/* - * bound volume controls - * - * bind multiple volumes (# indices, from 0) - */ - -#define AMP_VAL_IDX_SHIFT 19 -#define AMP_VAL_IDX_MASK (0x0f<<19) - -static int alc_bind_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct alc_spec *spec = codec->spec; - unsigned long pval; - - down(&spec->bind_mutex); - pval = kcontrol->private_value; - kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ - snd_hda_mixer_amp_switch_info(kcontrol, uinfo); - kcontrol->private_value = pval; - up(&spec->bind_mutex); - return 0; -} - -static int alc_bind_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct alc_spec *spec = codec->spec; - unsigned long pval; - - down(&spec->bind_mutex); - pval = kcontrol->private_value; - kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ - snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); - kcontrol->private_value = pval; - up(&spec->bind_mutex); - return 0; -} - -static int alc_bind_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct alc_spec *spec = codec->spec; - unsigned long pval; - int i, indices, change = 0; - - down(&spec->bind_mutex); - pval = kcontrol->private_value; - indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; - for (i = 0; i < indices; i++) { - kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | (i << AMP_VAL_IDX_SHIFT); - change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); - } - kcontrol->private_value = pval; - up(&spec->bind_mutex); - return change; -} - -#define ALC_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ - .info = alc_bind_switch_info, \ - .get = alc_bind_switch_get, \ - .put = alc_bind_switch_put, \ - .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) } - -#define ALC_BIND_MUTE(xname,nid,indices,dir) ALC_BIND_MUTE_MONO(xname,nid,3,indices,dir) - /* * Control of pin widget settings via the mixer. Only boolean settings are * supported, so VrefEn can't be controlled using these functions as they @@ -404,13 +335,13 @@ static struct alc_channel_mode alc880_threestack_modes[2] = { static snd_kcontrol_new_t alc880_three_stack_mixer[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), + HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT), + HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT), HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), - ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), + HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), + HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), @@ -491,7 +422,7 @@ static snd_kcontrol_new_t alc880_capture_alt_mixer[] = { /* additional mixers to alc880_three_stack_mixer */ static snd_kcontrol_new_t alc880_five_stack_mixer[] = { HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT), + HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT), { } /* end */ }; @@ -548,15 +479,15 @@ static struct alc_channel_mode alc880_sixstack_modes[1] = { static snd_kcontrol_new_t alc880_six_stack_mixer[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), + HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), + HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), - ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), + HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), + HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), + HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), @@ -616,13 +547,13 @@ static struct alc_channel_mode alc880_w810_modes[1] = { /* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */ static snd_kcontrol_new_t alc880_w810_base_mixer[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), + HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), + HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), - ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), + HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), + HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), { } /* end */ }; @@ -647,9 +578,9 @@ static struct alc_channel_mode alc880_2_jack_modes[1] = { static snd_kcontrol_new_t alc880_z71v_mixer[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), + HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT), + HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), @@ -673,9 +604,9 @@ static hda_nid_t alc880_f1734_dac_nids[1] = { static snd_kcontrol_new_t alc880_f1734_mixer[] = { HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), + HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT), + HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), @@ -698,13 +629,13 @@ static snd_kcontrol_new_t alc880_f1734_mixer[] = { static snd_kcontrol_new_t alc880_asus_mixer[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), + HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), + HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), - ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), + HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), + HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), @@ -1433,10 +1364,10 @@ static snd_kcontrol_new_t alc880_test_mixer[] = { HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), - ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), - ALC_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT), - ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), + HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), + HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), + HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT), + HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), PIN_CTL_TEST("Front Pin Mode", 0x14), PIN_CTL_TEST("Surround Pin Mode", 0x15), PIN_CTL_TEST("CLFE Pin Mode", 0x16), @@ -1819,7 +1750,7 @@ enum { static snd_kcontrol_new_t alc880_control_templates[] = { HDA_CODEC_VOLUME(NULL, 0, 0, 0), HDA_CODEC_MUTE(NULL, 0, 0, 0), - ALC_BIND_MUTE(NULL, 0, 0, 0), + HDA_BIND_MUTE(NULL, 0, 0, 0), }; /* add dynamic controls */ @@ -2137,7 +2068,6 @@ static int patch_alc880(struct hda_codec *codec) if (spec == NULL) return -ENOMEM; - init_MUTEX(&spec->bind_mutex); codec->spec = spec; board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl); @@ -2278,7 +2208,7 @@ static struct alc_channel_mode alc260_modes[1] = { static snd_kcontrol_new_t alc260_base_mixer[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT), + HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), @@ -2290,9 +2220,9 @@ static snd_kcontrol_new_t alc260_base_mixer[] = { HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT), HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT), HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), + HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), + HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT), { @@ -2307,7 +2237,7 @@ static snd_kcontrol_new_t alc260_base_mixer[] = { static snd_kcontrol_new_t alc260_hp_mixer[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT), + HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), @@ -2317,9 +2247,9 @@ static snd_kcontrol_new_t alc260_hp_mixer[] = { HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT), HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT), HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), + HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), + HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT), { @@ -2334,7 +2264,7 @@ static snd_kcontrol_new_t alc260_hp_mixer[] = { static snd_kcontrol_new_t alc260_fujitsu_mixer[] = { HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT), + HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT), ALC_PINCTL_SWITCH("Headphone Amp Switch", 0x14, PIN_HP_AMP), HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), @@ -2343,7 +2273,7 @@ static snd_kcontrol_new_t alc260_fujitsu_mixer[] = { HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT), HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Internal Speaker Playback Switch", 0x09, 2, HDA_INPUT), + HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x09, 2, HDA_INPUT), HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT), { @@ -2500,7 +2430,6 @@ static int patch_alc260(struct hda_codec *codec) if (spec == NULL) return -ENOMEM; - init_MUTEX(&spec->bind_mutex); codec->spec = spec; board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl); @@ -2637,15 +2566,15 @@ static int alc882_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u */ static snd_kcontrol_new_t alc882_base_mixer[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), + HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), + HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), - ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), + HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), + HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), + HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), @@ -2763,7 +2692,6 @@ static int patch_alc882(struct hda_codec *codec) if (spec == NULL) return -ENOMEM; - init_MUTEX(&spec->bind_mutex); codec->spec = spec; spec->mixers[spec->num_mixers] = alc882_base_mixer; -- cgit v1.2.3 From c2f2f0fa3829a8da1e029346c4f7e8da82f95d62 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 26 Oct 2005 11:50:25 +0200 Subject: [ALSA] usb-audio: remove duplicate fixup entry (Hercules DJ Console) Modules: USB generic driver Signed-off-by: Jaroslav Kysela --- sound/usb/usbmixer_maps.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sound/usb/usbmixer_maps.c b/sound/usb/usbmixer_maps.c index 9a8534b9eff..c1264434e50 100644 --- a/sound/usb/usbmixer_maps.c +++ b/sound/usb/usbmixer_maps.c @@ -247,11 +247,6 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { .id = USB_ID(0x06f8, 0xd002), .ignore_ctl_error = 1, }, - { - /* Hercules DJ Console */ - .id = USB_ID(0x06f8, 0xd002), - .ignore_ctl_error = 1, - }, { .id = USB_ID(0x08bb, 0x2702), .map = linex_map, -- cgit v1.2.3 From ec58ef03284f0bfa50a04982b74c8c2325a0758e Mon Sep 17 00:00:00 2001 From: Steve French Date: Fri, 4 Nov 2005 09:44:33 -0800 Subject: [CIFS] Update kconfig for cifs Add cifs extended stats configure option and reduce experimental code. Signed-off-by: Steve French --- fs/Kconfig | 40 +++++++++++++++++++++++++++++++--------- fs/cifs/cifsproto.h | 2 +- fs/cifs/cifssmb.c | 2 -- fs/cifs/inode.c | 2 -- 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/fs/Kconfig b/fs/Kconfig index c9c4108469c..8855fd41cfa 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -1587,9 +1587,10 @@ config CIFS PC operating systems. The CIFS protocol is fully supported by file servers such as Windows 2000 (including Windows 2003, NT 4 and Windows XP) as well by Samba (which provides excellent CIFS - server support for Linux and many other operating systems). Currently - you must use the smbfs client filesystem to access older SMB servers - such as Windows 9x and OS/2. + server support for Linux and many other operating systems). Limited + support for Windows ME and similar servers is provided as well. + You must use the smbfs client filesystem to access older SMB servers + such as OS/2 and DOS. The intent of the cifs module is to provide an advanced network file system client for mounting to CIFS compliant servers, @@ -1600,7 +1601,7 @@ config CIFS cifs if running only a (Samba) server. It is possible to enable both smbfs and cifs (e.g. if you are using CIFS for accessing Windows 2003 and Samba 3 servers, and smbfs for accessing old servers). If you need - to mount to Samba or Windows 2003 servers from this machine, say Y. + to mount to Samba or Windows from this machine, say Y. config CIFS_STATS bool "CIFS statistics" @@ -1609,8 +1610,22 @@ config CIFS_STATS Enabling this option will cause statistics for each server share mounted by the cifs client to be displayed in /proc/fs/cifs/Stats +config CIFS_STATS2 + bool "CIFS extended statistics" + depends on CIFS_STATS + help + Enabling this option will allow more detailed statistics on SMB + request timing to be displayed in /proc/fs/cifs/DebugData and also + allow optional logging of slow responses to dmesg (depending on the + value of /proc/fs/cifs/cifsFYI, see fs/cifs/README for more details). + These additional statistics may have a minor effect on performance + and memory utilization. + + Unless you are a developer or are doing network performance analysis + or tuning, say N. + config CIFS_XATTR - bool "CIFS extended attributes (EXPERIMENTAL)" + bool "CIFS extended attributes" depends on CIFS help Extended attributes are name:value pairs associated with inodes by @@ -1622,11 +1637,11 @@ config CIFS_XATTR prefaced by the user namespace prefix. The system namespace (used by some filesystems to store ACLs) is not supported at this time. - + If unsure, say N. config CIFS_POSIX - bool "CIFS POSIX Extensions (EXPERIMENTAL)" + bool "CIFS POSIX Extensions" depends on CIFS_XATTR help Enabling this option will cause the cifs client to attempt to @@ -1641,8 +1656,15 @@ config CIFS_EXPERIMENTAL bool "CIFS Experimental Features (EXPERIMENTAL)" depends on CIFS && EXPERIMENTAL help - Enables cifs features under testing. These features - are highly experimental. If unsure, say N. + Enables cifs features under testing. These features are + experimental and currently include support for writepages + (multipage writebehind performance improvements) and directory + change notification ie fcntl(F_DNOTIFY) as well as some security + improvements. Some also depend on setting at runtime the + pseudo-file /proc/fs/cifs/Experimental (which is disabled by + default). See the file fs/cifs/README for more details. + + If unsure, say N. config NCP_FS tristate "NCP file system support (to mount NetWare volumes)" diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index d301149b1bb..1b73f4f4c5c 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -242,11 +242,11 @@ extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, const int netfid, const unsigned int count, const __u64 offset, unsigned int *nbytes, struct kvec *iov, const int nvec, const int long_op); +#endif /* CONFIG_CIFS_EXPERIMENTAL */ extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, __u64 * inode_number, const struct nls_table *nls_codepage, int remap_special_chars); -#endif /* CONFIG_CIFS_EXPERIMENTAL */ extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen, const struct nls_table * codepage); extern int cifsConvertToUCS(__le16 * target, const char *source, int maxlen, diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 9312bfc5668..a53c596e108 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2959,7 +2959,6 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle return rc; } -#ifdef CONFIG_CIFS_EXPERIMENTAL int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, @@ -3053,7 +3052,6 @@ GetInodeNumOut: goto GetInodeNumberRetry; return rc; } -#endif /* CIFS_EXPERIMENTAL */ int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 912d401600f..923d071163b 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -283,7 +283,6 @@ int cifs_get_inode_info(struct inode **pinode, there Windows server or network appliances for which IndexNumber field is not guaranteed unique? */ -#ifdef CONFIG_CIFS_EXPERIMENTAL if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){ int rc1 = 0; __u64 inode_num; @@ -299,7 +298,6 @@ int cifs_get_inode_info(struct inode **pinode, } else /* do we need cast or hash to ino? */ (*pinode)->i_ino = inode_num; } /* else ino incremented to unique num in new_inode*/ -#endif /* CIFS_EXPERIMENTAL */ insert_inode_hash(*pinode); } inode = *pinode; -- cgit v1.2.3 From c4dd45823fbdaaa4748cd8c7704334f249914405 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 4 Nov 2005 15:18:56 -0800 Subject: [AGPGART] When we encounter reserved mode bits, print them out. Signed-off-by: Dave Jones --- drivers/char/agp/generic.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index b0f2a6faf67..c4a38715c6f 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -412,7 +412,8 @@ static void agp_v2_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_ u32 tmp; if (*requested_mode & AGP2_RESERVED_MASK) { - printk(KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode); + printk(KERN_INFO PFX "reserved bits set (%x) in mode 0x%x. Fixed.\n", + *requested_mode & AGP2_RESERVED_MASK, *requested_mode); *requested_mode &= ~AGP2_RESERVED_MASK; } @@ -490,7 +491,8 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_ u32 tmp; if (*requested_mode & AGP3_RESERVED_MASK) { - printk(KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode); + printk(KERN_INFO PFX "reserved bits set (%x) in mode 0x%x. Fixed.\n", + *requested_mode & AGP3_RESERVED_MASK, *requested_mode); *requested_mode &= ~AGP3_RESERVED_MASK; } -- cgit v1.2.3 From 146a209967886e57eb34b4cdb85ca52078a4f8cc Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 4 Nov 2005 15:32:08 -0800 Subject: [AGPGART] Fix up sgi-agp bug with no devices on bus. Signed-off-by: Eric Kunze Signed-off-by: Dave Jones --- drivers/char/agp/sgi-agp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c index d3aa159c9de..53eeb293d17 100644 --- a/drivers/char/agp/sgi-agp.c +++ b/drivers/char/agp/sgi-agp.c @@ -288,6 +288,8 @@ static int __devinit agp_sgi_init(void) j = 0; list_for_each_entry(info, &tioca_list, ca_list) { struct list_head *tmp; + if (list_empty(info->ca_devices)) + continue; list_for_each(tmp, info->ca_devices) { u8 cap_ptr; pdev = pci_dev_b(tmp); -- cgit v1.2.3 From 3428c209c6820bbbb7dfb323caef8d402b3deb4c Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 3 Nov 2005 14:27:07 +0100 Subject: [NETFILTER] PPTP helper: Fix compilation of conntrack helper without NAT This patch fixes compilation of the PPTP conntrack helper when NAT is configured off. Signed-off-by: Yasuyuki Kozakai Signed-off-by: Harald Welte Signed-off-by: Arnaldo Carvalho de Melo --- net/ipv4/netfilter/ip_conntrack_helper_pptp.c | 4 ---- net/ipv4/netfilter/ip_nat_helper_pptp.c | 2 ++ 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c index 926a6684643..4108a5e12b3 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c @@ -270,14 +270,10 @@ exp_gre(struct ip_conntrack *master, exp_orig->expectfn = pptp_expectfn; exp_orig->flags = 0; - exp_orig->dir = IP_CT_DIR_ORIGINAL; - /* both expectations are identical apart from tuple */ memcpy(exp_reply, exp_orig, sizeof(*exp_reply)); memcpy(&exp_reply->tuple, &exp_tuples[1], sizeof(exp_reply->tuple)); - exp_reply->dir = !exp_orig->dir; - if (ip_nat_pptp_hook_exp_gre) ret = ip_nat_pptp_hook_exp_gre(exp_orig, exp_reply); else { diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c index 3cdd0684d30..ee6ab74ad3a 100644 --- a/net/ipv4/netfilter/ip_nat_helper_pptp.c +++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c @@ -216,6 +216,7 @@ pptp_exp_gre(struct ip_conntrack_expect *expect_orig, expect_orig->saved_proto.gre.key = htons(nat_pptp_info->pac_call_id); expect_orig->tuple.src.u.gre.key = htons(nat_pptp_info->pns_call_id); expect_orig->tuple.dst.u.gre.key = htons(ct_pptp_info->pac_call_id); + expect_orig->dir = IP_CT_DIR_ORIGINAL; inv_t.src.ip = reply_t->src.ip; inv_t.dst.ip = reply_t->dst.ip; inv_t.src.u.gre.key = htons(nat_pptp_info->pac_call_id); @@ -233,6 +234,7 @@ pptp_exp_gre(struct ip_conntrack_expect *expect_orig, expect_reply->saved_proto.gre.key = htons(nat_pptp_info->pns_call_id); expect_reply->tuple.src.u.gre.key = htons(nat_pptp_info->pac_call_id); expect_reply->tuple.dst.u.gre.key = htons(ct_pptp_info->pns_call_id); + expect_reply->dir = IP_CT_DIR_REPLY; inv_t.src.ip = orig_t->src.ip; inv_t.dst.ip = orig_t->dst.ip; inv_t.src.u.gre.key = htons(nat_pptp_info->pns_call_id); -- cgit v1.2.3 From d811552eda2476215d69d485e437d2dcae1ab0b4 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 3 Nov 2005 13:05:20 +0100 Subject: [NETFILTER] PPTP helper: Fix endianness bug in GRE key / CallID NAT This endianness bug slipped through while changing the 'gre.key' field in the conntrack tuple from 32bit to 16bit. None of my tests caught the problem, since the linux pptp client always has '0' as call id / gre key. Only windows clients actually trigger the bug. Signed-off-by: Harald Welte Signed-off-by: Arnaldo Carvalho de Melo --- net/ipv4/netfilter/ip_nat_proto_gre.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/netfilter/ip_nat_proto_gre.c b/net/ipv4/netfilter/ip_nat_proto_gre.c index 7c128540167..f7cad7cf1ae 100644 --- a/net/ipv4/netfilter/ip_nat_proto_gre.c +++ b/net/ipv4/netfilter/ip_nat_proto_gre.c @@ -139,8 +139,8 @@ gre_manip_pkt(struct sk_buff **pskb, break; case GRE_VERSION_PPTP: DEBUGP("call_id -> 0x%04x\n", - ntohl(tuple->dst.u.gre.key)); - pgreh->call_id = htons(ntohl(tuple->dst.u.gre.key)); + ntohs(tuple->dst.u.gre.key)); + pgreh->call_id = tuple->dst.u.gre.key; break; default: DEBUGP("can't nat unknown GRE version\n"); -- cgit v1.2.3 From d2a7bb7141a1fac7b11523538b2d2407e928baeb Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 3 Nov 2005 20:17:51 +0100 Subject: [NETFILTER] NAT: Fix module refcount dropping too far The unknown protocol is used as a fallback when a protocol isn't known. Hence we cannot handle it failing, so don't set ".me". It's OK, since we only grab a reference from within the same module (iptable_nat.ko), so we never take the module refcount from 0 to 1. Also, remove the "protocol is NULL" test: it's never NULL. Signed-off-by: Rusty Rusty Signed-off-by: Harald Welte Signed-off-by: Arnaldo Carvalho de Melo --- net/ipv4/netfilter/ip_nat_core.c | 6 ++---- net/ipv4/netfilter/ip_nat_proto_unknown.c | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index c5e3abd2467..762f4d93936 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -66,10 +66,8 @@ ip_nat_proto_find_get(u_int8_t protonum) * removed until we've grabbed the reference */ preempt_disable(); p = __ip_nat_proto_find(protonum); - if (p) { - if (!try_module_get(p->me)) - p = &ip_nat_unknown_protocol; - } + if (!try_module_get(p->me)) + p = &ip_nat_unknown_protocol; preempt_enable(); return p; diff --git a/net/ipv4/netfilter/ip_nat_proto_unknown.c b/net/ipv4/netfilter/ip_nat_proto_unknown.c index 99bbef56f84..f0099a646a0 100644 --- a/net/ipv4/netfilter/ip_nat_proto_unknown.c +++ b/net/ipv4/netfilter/ip_nat_proto_unknown.c @@ -62,7 +62,7 @@ unknown_print_range(char *buffer, const struct ip_nat_range *range) struct ip_nat_protocol ip_nat_unknown_protocol = { .name = "unknown", - .me = THIS_MODULE, + /* .me isn't set: getting a ref to this cannot fail. */ .manip_pkt = unknown_manip_pkt, .in_range = unknown_in_range, .unique_tuple = unknown_unique_tuple, -- cgit v1.2.3 From 0f69ce1e4474e5d5e266457e8a1f4166cf71f6c7 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Fri, 4 Nov 2005 16:03:32 -0800 Subject: [IB] mthca: report page size capability Report the device's real page size capability in mthca_query_device(). Signed-off-by: Jack Morgenstein Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_dev.h | 1 + drivers/infiniband/hw/mthca/mthca_main.c | 1 + drivers/infiniband/hw/mthca/mthca_provider.c | 1 + 3 files changed, 3 insertions(+) diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index e7e5d3b4f00..808037f25c7 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h @@ -154,6 +154,7 @@ struct mthca_limits { int reserved_mcgs; int num_pds; int reserved_pds; + u32 page_size_cap; u32 flags; u8 port_width_cap; }; diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c index 45c6328e780..16594d1342d 100644 --- a/drivers/infiniband/hw/mthca/mthca_main.c +++ b/drivers/infiniband/hw/mthca/mthca_main.c @@ -181,6 +181,7 @@ static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim mdev->limits.reserved_uars = dev_lim->reserved_uars; mdev->limits.reserved_pds = dev_lim->reserved_pds; mdev->limits.port_width_cap = dev_lim->max_port_width; + mdev->limits.page_size_cap = ~(u32) (dev_lim->min_page_sz - 1); mdev->limits.flags = dev_lim->flags; /* IB_DEVICE_RESIZE_MAX_WR not supported by driver. diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 6b016666826..e78259b2664 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c @@ -90,6 +90,7 @@ static int mthca_query_device(struct ib_device *ibdev, memcpy(&props->node_guid, out_mad->data + 12, 8); props->max_mr_size = ~0ull; + props->page_size_cap = mdev->limits.page_size_cap; props->max_qp = mdev->limits.num_qps - mdev->limits.reserved_qps; props->max_qp_wr = mdev->limits.max_wqes; props->max_sge = mdev->limits.max_sg; -- cgit v1.2.3 From 0f81eb4db4f1cc560318b6e7762a7a1d7d8c7095 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 3 Nov 2005 19:05:37 +0100 Subject: [NETFILTER]: Fix double free after netlink_unicast() in ctnetlink It's not necessary to free skb if netlink_unicast() failed. Signed-off-by: Yasuyuki Kozakai Signed-off-by: Harald Welte Signed-off-by: Arnaldo Carvalho de Melo --- net/ipv4/netfilter/ip_conntrack_netlink.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index 166e6069f12..82a65043a8e 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -815,7 +815,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, IPCTNL_MSG_CT_NEW, 1, ct); ip_conntrack_put(ct); if (err <= 0) - goto out; + goto free; err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); if (err < 0) @@ -824,9 +824,9 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, DEBUGP("leaving\n"); return 0; +free: + kfree_skb(skb2); out: - if (skb2) - kfree_skb(skb2); return -1; } @@ -1322,21 +1322,16 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, 1, exp); if (err <= 0) - goto out; + goto free; ip_conntrack_expect_put(exp); - err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); - if (err < 0) - goto free; - - return err; + return netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); +free: + kfree_skb(skb2); out: ip_conntrack_expect_put(exp); -free: - if (skb2) - kfree_skb(skb2); return err; } -- cgit v1.2.3 From 20faa7c380c19c932d57be59bb2522bd9327a6c5 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 5 Nov 2005 10:20:56 +0000 Subject: [ARM] Documentation/arm/README: small update - egcs is not supported by kernel 2.6 - gcc 3.3 seems to be a good choice on ARM Signed-off-by: Adrian Bunk Signed-off-by: Russell King --- Documentation/arm/README | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Documentation/arm/README b/Documentation/arm/README index a6f718e90a8..5ed6f3530b8 100644 --- a/Documentation/arm/README +++ b/Documentation/arm/README @@ -8,10 +8,9 @@ Compilation of kernel --------------------- In order to compile ARM Linux, you will need a compiler capable of - generating ARM ELF code with GNU extensions. GCC 2.95.1, EGCS - 1.1.2, and GCC 3.3 are known to be good compilers. Fortunately, you - needn't guess. The kernel will report an error if your compiler is - a recognized offender. + generating ARM ELF code with GNU extensions. GCC 3.3 is known to be + a good compiler. Fortunately, you needn't guess. The kernel will report + an error if your compiler is a recognized offender. To build ARM Linux natively, you shouldn't have to alter the ARCH = line in the top level Makefile. However, if you don't have the ARM Linux ELF -- cgit v1.2.3 From 10dfdc69ea07d5a6c24406755f5e8de95a1b8901 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 3 Nov 2005 19:20:07 +0100 Subject: [NETFILTER] nfnetlink: Use kzalloc These is a cleanup patch, kzalloc can be used in a couple of cases Signed-off-by: Samir Bellabes Signed-off-by: Harald Welte Signed-off-by: Arnaldo Carvalho de Melo --- net/netfilter/nfnetlink_log.c | 6 ++---- net/netfilter/nfnetlink_queue.c | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index efcd10f996b..d194676f365 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -146,11 +146,10 @@ instance_create(u_int16_t group_num, int pid) goto out_unlock; } - inst = kmalloc(sizeof(*inst), GFP_ATOMIC); + inst = kzalloc(sizeof(*inst), GFP_ATOMIC); if (!inst) goto out_unlock; - memset(inst, 0, sizeof(*inst)); INIT_HLIST_NODE(&inst->hlist); inst->lock = SPIN_LOCK_UNLOCKED; /* needs to be two, since we _put() after creation */ @@ -962,10 +961,9 @@ static int nful_open(struct inode *inode, struct file *file) struct iter_state *is; int ret; - is = kmalloc(sizeof(*is), GFP_KERNEL); + is = kzalloc(sizeof(*is), GFP_KERNEL); if (!is) return -ENOMEM; - memset(is, 0, sizeof(*is)); ret = seq_open(file, &nful_seq_ops); if (ret < 0) goto out_free; diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index eaa44c49567..f065a6c9495 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -136,11 +136,10 @@ instance_create(u_int16_t queue_num, int pid) goto out_unlock; } - inst = kmalloc(sizeof(*inst), GFP_ATOMIC); + inst = kzalloc(sizeof(*inst), GFP_ATOMIC); if (!inst) goto out_unlock; - memset(inst, 0, sizeof(*inst)); inst->queue_num = queue_num; inst->peer_pid = pid; inst->queue_maxlen = NFQNL_QMAX_DEFAULT; @@ -1036,10 +1035,9 @@ static int nfqnl_open(struct inode *inode, struct file *file) struct iter_state *is; int ret; - is = kmalloc(sizeof(*is), GFP_KERNEL); + is = kzalloc(sizeof(*is), GFP_KERNEL); if (!is) return -ENOMEM; - memset(is, 0, sizeof(*is)); ret = seq_open(file, &nfqnl_seq_ops); if (ret < 0) goto out_free; -- cgit v1.2.3 From 433a4d3b5456dec5bcca5a0f236bf622da1267b3 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 3 Nov 2005 19:25:56 +0100 Subject: [NETFILTER]: CONNMARK target needs ip_conntrack There's a missing dependency from the CONNMARK target to ip_conntrack. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Harald Welte Signed-off-by: Arnaldo Carvalho de Melo --- net/ipv4/netfilter/ipt_CONNMARK.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/netfilter/ipt_CONNMARK.c b/net/ipv4/netfilter/ipt_CONNMARK.c index 13463802133..05d66ab5942 100644 --- a/net/ipv4/netfilter/ipt_CONNMARK.c +++ b/net/ipv4/netfilter/ipt_CONNMARK.c @@ -109,6 +109,7 @@ static struct ipt_target ipt_connmark_reg = { static int __init init(void) { + need_ip_conntrack(); return ipt_register_target(&ipt_connmark_reg); } -- cgit v1.2.3 From 1758ee0ea26561943813c5f5a7b27272f2cbc4cf Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 3 Nov 2005 20:03:24 +0100 Subject: [NETFILTER] nf_queue: Fix Ooops when no queue handler registered With the new nf_queue generalization in 2.6.14, we've introduced a bug that causes an oops as soon as a packet is queued but no queue handler registered. This patch fixes it. Signed-off-by: Harald Welte Signed-off-by: Arnaldo Carvalho de Melo --- net/netfilter/nf_queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index d10d552d9c4..d3a4f30a7f2 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -117,7 +117,7 @@ int nf_queue(struct sk_buff **skb, /* QUEUE == DROP if noone is waiting, to be safe. */ read_lock(&queue_handler_lock); - if (!queue_handler[pf]->outfn) { + if (!queue_handler[pf] || !queue_handler[pf]->outfn) { read_unlock(&queue_handler_lock); kfree_skb(*skb); return 1; -- cgit v1.2.3 From 07aaa11540828f4482c09e1a936a1f63cdb9fc9d Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 3 Nov 2005 13:43:07 -0800 Subject: [NETEM]: use PSCHED_LESS Convert netem to use PSCHED_LESS and warn if requeue fails. With some of the psched clock sources, the subtraction doesn't work always work right without wrapping. Signed-off-by: Stephen Hemminger Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_netem.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index bb9bf8d5003..d871fe7f81a 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -185,10 +185,13 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) || q->counter < q->gap /* inside last reordering gap */ || q->reorder < get_crandom(&q->reorder_cor)) { psched_time_t now; + psched_tdiff_t delay; + + delay = tabledist(q->latency, q->jitter, + &q->delay_cor, q->delay_dist); + PSCHED_GET_TIME(now); - PSCHED_TADD2(now, tabledist(q->latency, q->jitter, - &q->delay_cor, q->delay_dist), - cb->time_to_send); + PSCHED_TADD2(now, delay, cb->time_to_send); ++q->counter; ret = q->qdisc->enqueue(skb, q->qdisc); } else { @@ -248,24 +251,31 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch) const struct netem_skb_cb *cb = (const struct netem_skb_cb *)skb->cb; psched_time_t now; - long delay; /* if more time remaining? */ PSCHED_GET_TIME(now); - delay = PSCHED_US2JIFFIE(PSCHED_TDIFF(cb->time_to_send, now)); - pr_debug("netem_run: skb=%p delay=%ld\n", skb, delay); - if (delay <= 0) { + + if (PSCHED_TLESS(cb->time_to_send, now)) { pr_debug("netem_dequeue: return skb=%p\n", skb); sch->q.qlen--; sch->flags &= ~TCQ_F_THROTTLED; return skb; - } + } else { + psched_tdiff_t delay = PSCHED_TDIFF(cb->time_to_send, now); - mod_timer(&q->timer, jiffies + delay); - sch->flags |= TCQ_F_THROTTLED; + if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) { + sch->qstats.drops++; - if (q->qdisc->ops->requeue(skb, q->qdisc) != 0) - sch->qstats.drops++; + /* After this qlen is confused */ + printk(KERN_ERR "netem: queue discpline %s could not requeue\n", + q->qdisc->ops->id); + + sch->q.qlen--; + } + + mod_timer(&q->timer, jiffies + PSCHED_US2JIFFIE(delay)); + sch->flags |= TCQ_F_THROTTLED; + } } return NULL; -- cgit v1.2.3 From a783474591f2eed0348e08b15934fa9a25e23b3e Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:03 +0100 Subject: [PKT_SCHED]: Generic RED layer Extracts the RED algorithm from sch_red.c and puts it into include/net/red.h for use by other RED based modules. The statistics are extended to be more fine grained in order to differ between probability/forced marks/drops. We now reset the average queue length when setting new parameters, leaving it might result in an unreasonable qavg for a while depending on the value of W. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- include/net/red.h | 325 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 325 insertions(+) create mode 100644 include/net/red.h diff --git a/include/net/red.h b/include/net/red.h new file mode 100644 index 00000000000..2ed4358e329 --- /dev/null +++ b/include/net/red.h @@ -0,0 +1,325 @@ +#ifndef __NET_SCHED_RED_H +#define __NET_SCHED_RED_H + +#include +#include +#include +#include +#include + +/* Random Early Detection (RED) algorithm. + ======================================= + + Source: Sally Floyd and Van Jacobson, "Random Early Detection Gateways + for Congestion Avoidance", 1993, IEEE/ACM Transactions on Networking. + + This file codes a "divisionless" version of RED algorithm + as written down in Fig.17 of the paper. + + Short description. + ------------------ + + When a new packet arrives we calculate the average queue length: + + avg = (1-W)*avg + W*current_queue_len, + + W is the filter time constant (chosen as 2^(-Wlog)), it controls + the inertia of the algorithm. To allow larger bursts, W should be + decreased. + + if (avg > th_max) -> packet marked (dropped). + if (avg < th_min) -> packet passes. + if (th_min < avg < th_max) we calculate probability: + + Pb = max_P * (avg - th_min)/(th_max-th_min) + + and mark (drop) packet with this probability. + Pb changes from 0 (at avg==th_min) to max_P (avg==th_max). + max_P should be small (not 1), usually 0.01..0.02 is good value. + + max_P is chosen as a number, so that max_P/(th_max-th_min) + is a negative power of two in order arithmetics to contain + only shifts. + + + Parameters, settable by user: + ----------------------------- + + qth_min - bytes (should be < qth_max/2) + qth_max - bytes (should be at least 2*qth_min and less limit) + Wlog - bits (<32) log(1/W). + Plog - bits (<32) + + Plog is related to max_P by formula: + + max_P = (qth_max-qth_min)/2^Plog; + + F.e. if qth_max=128K and qth_min=32K, then Plog=22 + corresponds to max_P=0.02 + + Scell_log + Stab + + Lookup table for log((1-W)^(t/t_ave). + + + NOTES: + + Upper bound on W. + ----------------- + + If you want to allow bursts of L packets of size S, + you should choose W: + + L + 1 - th_min/S < (1-(1-W)^L)/W + + th_min/S = 32 th_min/S = 4 + + log(W) L + -1 33 + -2 35 + -3 39 + -4 46 + -5 57 + -6 75 + -7 101 + -8 135 + -9 190 + etc. + */ + +#define RED_STAB_SIZE 256 +#define RED_STAB_MASK (RED_STAB_SIZE - 1) + +struct red_stats +{ + u32 prob_drop; /* Early probability drops */ + u32 prob_mark; /* Early probability marks */ + u32 forced_drop; /* Forced drops, qavg > max_thresh */ + u32 forced_mark; /* Forced marks, qavg > max_thresh */ + u32 pdrop; /* Drops due to queue limits */ + u32 other; /* Drops due to drop() calls */ + u32 backlog; +}; + +struct red_parms +{ + /* Parameters */ + u32 qth_min; /* Min avg length threshold: A scaled */ + u32 qth_max; /* Max avg length threshold: A scaled */ + u32 Scell_max; + u32 Rmask; /* Cached random mask, see red_rmask */ + u8 Scell_log; + u8 Wlog; /* log(W) */ + u8 Plog; /* random number bits */ + u8 Stab[RED_STAB_SIZE]; + + /* Variables */ + int qcount; /* Number of packets since last random + number generation */ + u32 qR; /* Cached random number */ + + unsigned long qavg; /* Average queue length: A scaled */ + psched_time_t qidlestart; /* Start of current idle period */ +}; + +static inline u32 red_rmask(u8 Plog) +{ + return Plog < 32 ? ((1 << Plog) - 1) : ~0UL; +} + +static inline void red_set_parms(struct red_parms *p, + u32 qth_min, u32 qth_max, u8 Wlog, u8 Plog, + u8 Scell_log, u8 *stab) +{ + /* Reset average queue length, the value is strictly bound + * to the parameters below, reseting hurts a bit but leaving + * it might result in an unreasonable qavg for a while. --TGR + */ + p->qavg = 0; + + p->qcount = -1; + p->qth_min = qth_min << Wlog; + p->qth_max = qth_max << Wlog; + p->Wlog = Wlog; + p->Plog = Plog; + p->Rmask = red_rmask(Plog); + p->Scell_log = Scell_log; + p->Scell_max = (255 << Scell_log); + + memcpy(p->Stab, stab, sizeof(p->Stab)); +} + +static inline int red_is_idling(struct red_parms *p) +{ + return !PSCHED_IS_PASTPERFECT(p->qidlestart); +} + +static inline void red_start_of_idle_period(struct red_parms *p) +{ + PSCHED_GET_TIME(p->qidlestart); +} + +static inline void red_end_of_idle_period(struct red_parms *p) +{ + PSCHED_SET_PASTPERFECT(p->qidlestart); +} + +static inline void red_restart(struct red_parms *p) +{ + red_end_of_idle_period(p); + p->qavg = 0; + p->qcount = -1; +} + +static inline unsigned long red_calc_qavg_from_idle_time(struct red_parms *p) +{ + psched_time_t now; + long us_idle; + int shift; + + PSCHED_GET_TIME(now); + us_idle = PSCHED_TDIFF_SAFE(now, p->qidlestart, p->Scell_max); + + /* + * The problem: ideally, average length queue recalcultion should + * be done over constant clock intervals. This is too expensive, so + * that the calculation is driven by outgoing packets. + * When the queue is idle we have to model this clock by hand. + * + * SF+VJ proposed to "generate": + * + * m = idletime / (average_pkt_size / bandwidth) + * + * dummy packets as a burst after idle time, i.e. + * + * p->qavg *= (1-W)^m + * + * This is an apparently overcomplicated solution (f.e. we have to + * precompute a table to make this calculation in reasonable time) + * I believe that a simpler model may be used here, + * but it is field for experiments. + */ + + shift = p->Stab[(us_idle >> p->Scell_log) & RED_STAB_MASK]; + + if (shift) + return p->qavg >> shift; + else { + /* Approximate initial part of exponent with linear function: + * + * (1-W)^m ~= 1-mW + ... + * + * Seems, it is the best solution to + * problem of too coarse exponent tabulation. + */ + us_idle = (p->qavg * us_idle) >> p->Scell_log; + + if (us_idle < (p->qavg >> 1)) + return p->qavg - us_idle; + else + return p->qavg >> 1; + } +} + +static inline unsigned long red_calc_qavg_no_idle_time(struct red_parms *p, + unsigned int backlog) +{ + /* + * NOTE: p->qavg is fixed point number with point at Wlog. + * The formula below is equvalent to floating point + * version: + * + * qavg = qavg*(1-W) + backlog*W; + * + * --ANK (980924) + */ + return p->qavg + (backlog - (p->qavg >> p->Wlog)); +} + +static inline unsigned long red_calc_qavg(struct red_parms *p, + unsigned int backlog) +{ + if (!red_is_idling(p)) + return red_calc_qavg_no_idle_time(p, backlog); + else + return red_calc_qavg_from_idle_time(p); +} + +static inline u32 red_random(struct red_parms *p) +{ + return net_random() & p->Rmask; +} + +static inline int red_mark_probability(struct red_parms *p, unsigned long qavg) +{ + /* The formula used below causes questions. + + OK. qR is random number in the interval 0..Rmask + i.e. 0..(2^Plog). If we used floating point + arithmetics, it would be: (2^Plog)*rnd_num, + where rnd_num is less 1. + + Taking into account, that qavg have fixed + point at Wlog, and Plog is related to max_P by + max_P = (qth_max-qth_min)/2^Plog; two lines + below have the following floating point equivalent: + + max_P*(qavg - qth_min)/(qth_max-qth_min) < rnd/qcount + + Any questions? --ANK (980924) + */ + return !(((qavg - p->qth_min) >> p->Wlog) * p->qcount < p->qR); +} + +enum { + RED_BELOW_MIN_THRESH, + RED_BETWEEN_TRESH, + RED_ABOVE_MAX_TRESH, +}; + +static inline int red_cmp_thresh(struct red_parms *p, unsigned long qavg) +{ + if (qavg < p->qth_min) + return RED_BELOW_MIN_THRESH; + else if (qavg >= p->qth_max) + return RED_ABOVE_MAX_TRESH; + else + return RED_BETWEEN_TRESH; +} + +enum { + RED_DONT_MARK, + RED_PROB_MARK, + RED_HARD_MARK, +}; + +static inline int red_action(struct red_parms *p, unsigned long qavg) +{ + switch (red_cmp_thresh(p, qavg)) { + case RED_BELOW_MIN_THRESH: + p->qcount = -1; + return RED_DONT_MARK; + + case RED_BETWEEN_TRESH: + if (++p->qcount) { + if (red_mark_probability(p, qavg)) { + p->qcount = 0; + p->qR = red_random(p); + return RED_PROB_MARK; + } + } else + p->qR = red_random(p); + + return RED_DONT_MARK; + + case RED_ABOVE_MAX_TRESH: + p->qcount = -1; + return RED_HARD_MARK; + } + + BUG(); + return RED_DONT_MARK; +} + +#endif -- cgit v1.2.3 From 2566a509cacc8b8eaea2e5b54068816c9cfb41c2 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:04 +0100 Subject: [NET]: Introduce INET_ECN_set_ce() function Changes IP_ECN_set_ce() and IP6_ECN_set_ce() to return 0 if the CE bits could not bet set because none of the ECT bits are set or 1 if the CE bits are already set or have been successfully set. Introduces INET_ECN_set_ce(skb) to enable CE bits for all supported protocols. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- include/net/inet_ecn.h | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/include/net/inet_ecn.h b/include/net/inet_ecn.h index f87845e2e96..b0c47e2eccf 100644 --- a/include/net/inet_ecn.h +++ b/include/net/inet_ecn.h @@ -2,6 +2,7 @@ #define _INET_ECN_H_ #include +#include #include enum { @@ -48,7 +49,7 @@ static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner) (label) |= __constant_htons(INET_ECN_ECT_0 << 4); \ } while (0) -static inline void IP_ECN_set_ce(struct iphdr *iph) +static inline int IP_ECN_set_ce(struct iphdr *iph) { u32 check = iph->check; u32 ecn = (iph->tos + 1) & INET_ECN_MASK; @@ -61,7 +62,7 @@ static inline void IP_ECN_set_ce(struct iphdr *iph) * INET_ECN_CE => 00 */ if (!(ecn & 2)) - return; + return !ecn; /* * The following gives us: @@ -72,6 +73,7 @@ static inline void IP_ECN_set_ce(struct iphdr *iph) iph->check = check + (check>=0xFFFF); iph->tos |= INET_ECN_CE; + return 1; } static inline void IP_ECN_clear(struct iphdr *iph) @@ -87,11 +89,12 @@ static inline void ipv4_copy_dscp(struct iphdr *outer, struct iphdr *inner) struct ipv6hdr; -static inline void IP6_ECN_set_ce(struct ipv6hdr *iph) +static inline int IP6_ECN_set_ce(struct ipv6hdr *iph) { if (INET_ECN_is_not_ect(ipv6_get_dsfield(iph))) - return; + return 0; *(u32*)iph |= htonl(INET_ECN_CE << 20); + return 1; } static inline void IP6_ECN_clear(struct ipv6hdr *iph) @@ -105,4 +108,21 @@ static inline void ipv6_copy_dscp(struct ipv6hdr *outer, struct ipv6hdr *inner) ipv6_change_dsfield(inner, INET_ECN_MASK, dscp); } +static inline int INET_ECN_set_ce(struct sk_buff *skb) +{ + switch (skb->protocol) { + case __constant_htons(ETH_P_IP): + if (skb->nh.raw + sizeof(struct iphdr) <= skb->tail) + return IP_ECN_set_ce(skb->nh.iph); + break; + + case __constant_htons(ETH_P_IPV6): + if (skb->nh.raw + sizeof(struct ipv6hdr) <= skb->tail) + return IP6_ECN_set_ce(skb->nh.ipv6h); + break; + } + + return 0; +} + #endif -- cgit v1.2.3 From 6b31b28a441c9ba33889f88ac1d9451ed9532ada Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:05 +0100 Subject: [PKT_SCHED]: RED: Use new generic red interface Simplifies code a lot by separating the red algorithm and the queueing logic. We now differentiate between probability marks and forced marks but sum them together again to not break backwards compatibility. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_red.c | 321 ++++++++++++---------------------------------------- 1 file changed, 74 insertions(+), 247 deletions(-) diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 7845d045eec..0dabcc9091b 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c @@ -41,44 +41,10 @@ #include #include #include +#include -/* Random Early Detection (RED) algorithm. - ======================================= - - Source: Sally Floyd and Van Jacobson, "Random Early Detection Gateways - for Congestion Avoidance", 1993, IEEE/ACM Transactions on Networking. - - This file codes a "divisionless" version of RED algorithm - as written down in Fig.17 of the paper. - -Short description. ------------------- - - When a new packet arrives we calculate the average queue length: - - avg = (1-W)*avg + W*current_queue_len, - - W is the filter time constant (chosen as 2^(-Wlog)), it controls - the inertia of the algorithm. To allow larger bursts, W should be - decreased. - - if (avg > th_max) -> packet marked (dropped). - if (avg < th_min) -> packet passes. - if (th_min < avg < th_max) we calculate probability: - - Pb = max_P * (avg - th_min)/(th_max-th_min) - - and mark (drop) packet with this probability. - Pb changes from 0 (at avg==th_min) to max_P (avg==th_max). - max_P should be small (not 1), usually 0.01..0.02 is good value. - - max_P is chosen as a number, so that max_P/(th_max-th_min) - is a negative power of two in order arithmetics to contain - only shifts. - - - Parameters, settable by user: +/* Parameters, settable by user: ----------------------------- limit - bytes (must be > qth_max + burst) @@ -89,92 +55,19 @@ Short description. arbitrarily high (well, less than ram size) Really, this limit will never be reached if RED works correctly. - - qth_min - bytes (should be < qth_max/2) - qth_max - bytes (should be at least 2*qth_min and less limit) - Wlog - bits (<32) log(1/W). - Plog - bits (<32) - - Plog is related to max_P by formula: - - max_P = (qth_max-qth_min)/2^Plog; - - F.e. if qth_max=128K and qth_min=32K, then Plog=22 - corresponds to max_P=0.02 - - Scell_log - Stab - - Lookup table for log((1-W)^(t/t_ave). - - -NOTES: - -Upper bound on W. ------------------ - - If you want to allow bursts of L packets of size S, - you should choose W: - - L + 1 - th_min/S < (1-(1-W)^L)/W - - th_min/S = 32 th_min/S = 4 - - log(W) L - -1 33 - -2 35 - -3 39 - -4 46 - -5 57 - -6 75 - -7 101 - -8 135 - -9 190 - etc. */ struct red_sched_data { -/* Parameters */ - u32 limit; /* HARD maximal queue length */ - u32 qth_min; /* Min average length threshold: A scaled */ - u32 qth_max; /* Max average length threshold: A scaled */ - u32 Rmask; - u32 Scell_max; - unsigned char flags; - char Wlog; /* log(W) */ - char Plog; /* random number bits */ - char Scell_log; - u8 Stab[256]; - -/* Variables */ - unsigned long qave; /* Average queue length: A scaled */ - int qcount; /* Packets since last random number generation */ - u32 qR; /* Cached random number */ - - psched_time_t qidlestart; /* Start of idle period */ - struct tc_red_xstats st; + u32 limit; /* HARD maximal queue length */ + unsigned char flags; + struct red_parms parms; + struct red_stats stats; }; -static int red_ecn_mark(struct sk_buff *skb) +static inline int red_use_ecn(struct red_sched_data *q) { - if (skb->nh.raw + 20 > skb->tail) - return 0; - - switch (skb->protocol) { - case __constant_htons(ETH_P_IP): - if (INET_ECN_is_not_ect(skb->nh.iph->tos)) - return 0; - IP_ECN_set_ce(skb->nh.iph); - return 1; - case __constant_htons(ETH_P_IPV6): - if (INET_ECN_is_not_ect(ipv6_get_dsfield(skb->nh.ipv6h))) - return 0; - IP6_ECN_set_ce(skb->nh.ipv6h); - return 1; - default: - return 0; - } + return q->flags & TC_RED_ECN; } static int @@ -182,119 +75,50 @@ red_enqueue(struct sk_buff *skb, struct Qdisc* sch) { struct red_sched_data *q = qdisc_priv(sch); - psched_time_t now; + q->parms.qavg = red_calc_qavg(&q->parms, sch->qstats.backlog); - if (!PSCHED_IS_PASTPERFECT(q->qidlestart)) { - long us_idle; - int shift; + if (red_is_idling(&q->parms)) + red_end_of_idle_period(&q->parms); - PSCHED_GET_TIME(now); - us_idle = PSCHED_TDIFF_SAFE(now, q->qidlestart, q->Scell_max); - PSCHED_SET_PASTPERFECT(q->qidlestart); + switch (red_action(&q->parms, q->parms.qavg)) { + case RED_DONT_MARK: + break; -/* - The problem: ideally, average length queue recalcultion should - be done over constant clock intervals. This is too expensive, so that - the calculation is driven by outgoing packets. - When the queue is idle we have to model this clock by hand. - - SF+VJ proposed to "generate" m = idletime/(average_pkt_size/bandwidth) - dummy packets as a burst after idle time, i.e. - - q->qave *= (1-W)^m - - This is an apparently overcomplicated solution (f.e. we have to precompute - a table to make this calculation in reasonable time) - I believe that a simpler model may be used here, - but it is field for experiments. -*/ - shift = q->Stab[us_idle>>q->Scell_log]; - - if (shift) { - q->qave >>= shift; - } else { - /* Approximate initial part of exponent - with linear function: - (1-W)^m ~= 1-mW + ... - - Seems, it is the best solution to - problem of too coarce exponent tabulation. - */ - - us_idle = (q->qave * us_idle)>>q->Scell_log; - if (us_idle < q->qave/2) - q->qave -= us_idle; - else - q->qave >>= 1; - } - } else { - q->qave += sch->qstats.backlog - (q->qave >> q->Wlog); - /* NOTE: - q->qave is fixed point number with point at Wlog. - The formulae above is equvalent to floating point - version: - - qave = qave*(1-W) + sch->qstats.backlog*W; - --ANK (980924) - */ - } + case RED_PROB_MARK: + sch->qstats.overlimits++; + if (!red_use_ecn(q) || !INET_ECN_set_ce(skb)) { + q->stats.prob_drop++; + goto congestion_drop; + } - if (q->qave < q->qth_min) { - q->qcount = -1; -enqueue: - if (sch->qstats.backlog + skb->len <= q->limit) { - __skb_queue_tail(&sch->q, skb); - sch->qstats.backlog += skb->len; - sch->bstats.bytes += skb->len; - sch->bstats.packets++; - return NET_XMIT_SUCCESS; - } else { - q->st.pdrop++; - } - kfree_skb(skb); - sch->qstats.drops++; - return NET_XMIT_DROP; - } - if (q->qave >= q->qth_max) { - q->qcount = -1; - sch->qstats.overlimits++; -mark: - if (!(q->flags&TC_RED_ECN) || !red_ecn_mark(skb)) { - q->st.early++; - goto drop; - } - q->st.marked++; - goto enqueue; + q->stats.prob_mark++; + break; + + case RED_HARD_MARK: + sch->qstats.overlimits++; + if (!red_use_ecn(q) || !INET_ECN_set_ce(skb)) { + q->stats.forced_drop++; + goto congestion_drop; + } + + q->stats.forced_mark++; + break; } - if (++q->qcount) { - /* The formula used below causes questions. - - OK. qR is random number in the interval 0..Rmask - i.e. 0..(2^Plog). If we used floating point - arithmetics, it would be: (2^Plog)*rnd_num, - where rnd_num is less 1. - - Taking into account, that qave have fixed - point at Wlog, and Plog is related to max_P by - max_P = (qth_max-qth_min)/2^Plog; two lines - below have the following floating point equivalent: - - max_P*(qave - qth_min)/(qth_max-qth_min) < rnd/qcount - - Any questions? --ANK (980924) - */ - if (((q->qave - q->qth_min)>>q->Wlog)*q->qcount < q->qR) - goto enqueue; - q->qcount = 0; - q->qR = net_random()&q->Rmask; - sch->qstats.overlimits++; - goto mark; + if (sch->qstats.backlog + skb->len <= q->limit) { + __skb_queue_tail(&sch->q, skb); + sch->qstats.backlog += skb->len; + sch->bstats.bytes += skb->len; + sch->bstats.packets++; + return NET_XMIT_SUCCESS; } - q->qR = net_random()&q->Rmask; - goto enqueue; -drop: + q->stats.pdrop++; + kfree_skb(skb); + sch->qstats.drops++; + return NET_XMIT_DROP; + +congestion_drop: kfree_skb(skb); sch->qstats.drops++; return NET_XMIT_CN; @@ -305,7 +129,8 @@ red_requeue(struct sk_buff *skb, struct Qdisc* sch) { struct red_sched_data *q = qdisc_priv(sch); - PSCHED_SET_PASTPERFECT(q->qidlestart); + if (red_is_idling(&q->parms)) + red_end_of_idle_period(&q->parms); __skb_queue_head(&sch->q, skb); sch->qstats.backlog += skb->len; @@ -324,7 +149,8 @@ red_dequeue(struct Qdisc* sch) sch->qstats.backlog -= skb->len; return skb; } - PSCHED_GET_TIME(q->qidlestart); + + red_start_of_idle_period(&q->parms); return NULL; } @@ -338,11 +164,12 @@ static unsigned int red_drop(struct Qdisc* sch) unsigned int len = skb->len; sch->qstats.backlog -= len; sch->qstats.drops++; - q->st.other++; + q->stats.other++; kfree_skb(skb); return len; } - PSCHED_GET_TIME(q->qidlestart); + + red_start_of_idle_period(&q->parms); return 0; } @@ -352,9 +179,7 @@ static void red_reset(struct Qdisc* sch) __skb_queue_purge(&sch->q); sch->qstats.backlog = 0; - PSCHED_SET_PASTPERFECT(q->qidlestart); - q->qave = 0; - q->qcount = -1; + red_restart(&q->parms); } static int red_change(struct Qdisc *sch, struct rtattr *opt) @@ -374,19 +199,14 @@ static int red_change(struct Qdisc *sch, struct rtattr *opt) sch_tree_lock(sch); q->flags = ctl->flags; - q->Wlog = ctl->Wlog; - q->Plog = ctl->Plog; - q->Rmask = ctl->Plog < 32 ? ((1<Plog) - 1) : ~0UL; - q->Scell_log = ctl->Scell_log; - q->Scell_max = (255<Scell_log); - q->qth_min = ctl->qth_min<Wlog; - q->qth_max = ctl->qth_max<Wlog; q->limit = ctl->limit; - memcpy(q->Stab, RTA_DATA(tb[TCA_RED_STAB-1]), 256); - q->qcount = -1; + red_set_parms(&q->parms, ctl->qth_min, ctl->qth_max, ctl->Wlog, + ctl->Plog, ctl->Scell_log, + RTA_DATA(tb[TCA_RED_STAB-1])); + if (skb_queue_empty(&sch->q)) - PSCHED_SET_PASTPERFECT(q->qidlestart); + red_end_of_idle_period(&q->parms); sch_tree_unlock(sch); return 0; } @@ -401,17 +221,18 @@ static int red_dump(struct Qdisc *sch, struct sk_buff *skb) struct red_sched_data *q = qdisc_priv(sch); unsigned char *b = skb->tail; struct rtattr *rta; - struct tc_red_qopt opt; + struct tc_red_qopt opt = { + .limit = q->limit, + .flags = q->flags, + .qth_min = q->parms.qth_min >> q->parms.Wlog, + .qth_max = q->parms.qth_max >> q->parms.Wlog, + .Wlog = q->parms.Wlog, + .Plog = q->parms.Plog, + .Scell_log = q->parms.Scell_log, + }; rta = (struct rtattr*)b; RTA_PUT(skb, TCA_OPTIONS, 0, NULL); - opt.limit = q->limit; - opt.qth_min = q->qth_min>>q->Wlog; - opt.qth_max = q->qth_max>>q->Wlog; - opt.Wlog = q->Wlog; - opt.Plog = q->Plog; - opt.Scell_log = q->Scell_log; - opt.flags = q->flags; RTA_PUT(skb, TCA_RED_PARMS, sizeof(opt), &opt); rta->rta_len = skb->tail - b; @@ -425,8 +246,14 @@ rtattr_failure: static int red_dump_stats(struct Qdisc *sch, struct gnet_dump *d) { struct red_sched_data *q = qdisc_priv(sch); - - return gnet_stats_copy_app(d, &q->st, sizeof(q->st)); + struct tc_red_xstats st = { + .early = q->stats.prob_drop + q->stats.forced_drop, + .pdrop = q->stats.pdrop, + .other = q->stats.other, + .marked = q->stats.prob_mark + q->stats.forced_mark, + }; + + return gnet_stats_copy_app(d, &st, sizeof(st)); } static struct Qdisc_ops red_qdisc_ops = { -- cgit v1.2.3 From 9e178ff27cd9187babe86dc80ef766b722c88da6 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:06 +0100 Subject: [PKT_SCHED]: RED: Use generic queue management interface Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_red.c | 42 +++++++++++++----------------------------- 1 file changed, 13 insertions(+), 29 deletions(-) diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 0dabcc9091b..d5e934c33f9 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c @@ -105,22 +105,14 @@ red_enqueue(struct sk_buff *skb, struct Qdisc* sch) break; } - if (sch->qstats.backlog + skb->len <= q->limit) { - __skb_queue_tail(&sch->q, skb); - sch->qstats.backlog += skb->len; - sch->bstats.bytes += skb->len; - sch->bstats.packets++; - return NET_XMIT_SUCCESS; - } + if (sch->qstats.backlog + skb->len <= q->limit) + return qdisc_enqueue_tail(skb, sch); q->stats.pdrop++; - kfree_skb(skb); - sch->qstats.drops++; - return NET_XMIT_DROP; + return qdisc_drop(skb, sch); congestion_drop: - kfree_skb(skb); - sch->qstats.drops++; + qdisc_drop(skb, sch); return NET_XMIT_CN; } @@ -132,10 +124,7 @@ red_requeue(struct sk_buff *skb, struct Qdisc* sch) if (red_is_idling(&q->parms)) red_end_of_idle_period(&q->parms); - __skb_queue_head(&sch->q, skb); - sch->qstats.backlog += skb->len; - sch->qstats.requeues++; - return 0; + return qdisc_requeue(skb, sch); } static struct sk_buff * @@ -144,14 +133,12 @@ red_dequeue(struct Qdisc* sch) struct sk_buff *skb; struct red_sched_data *q = qdisc_priv(sch); - skb = __skb_dequeue(&sch->q); - if (skb) { - sch->qstats.backlog -= skb->len; - return skb; - } + skb = qdisc_dequeue_head(sch); - red_start_of_idle_period(&q->parms); - return NULL; + if (skb == NULL) + red_start_of_idle_period(&q->parms); + + return skb; } static unsigned int red_drop(struct Qdisc* sch) @@ -159,13 +146,11 @@ static unsigned int red_drop(struct Qdisc* sch) struct sk_buff *skb; struct red_sched_data *q = qdisc_priv(sch); - skb = __skb_dequeue_tail(&sch->q); + skb = qdisc_dequeue_tail(sch); if (skb) { unsigned int len = skb->len; - sch->qstats.backlog -= len; - sch->qstats.drops++; q->stats.other++; - kfree_skb(skb); + qdisc_drop(skb, sch); return len; } @@ -177,8 +162,7 @@ static void red_reset(struct Qdisc* sch) { struct red_sched_data *q = qdisc_priv(sch); - __skb_queue_purge(&sch->q); - sch->qstats.backlog = 0; + qdisc_reset_queue(sch); red_restart(&q->parms); } -- cgit v1.2.3 From 6a1b63d467281eb6bd64aafbbf6130a1b42c8c2e Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:07 +0100 Subject: [PKT_SCHED]: RED: Dont start idle periods while already idling We should not interrupt and restart an idle period while idling already. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_red.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index d5e934c33f9..76e8df8447d 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c @@ -135,7 +135,7 @@ red_dequeue(struct Qdisc* sch) skb = qdisc_dequeue_head(sch); - if (skb == NULL) + if (skb == NULL && !red_is_idling(&q->parms)) red_start_of_idle_period(&q->parms); return skb; @@ -154,7 +154,9 @@ static unsigned int red_drop(struct Qdisc* sch) return len; } - red_start_of_idle_period(&q->parms); + if (!red_is_idling(&q->parms)) + red_start_of_idle_period(&q->parms); + return 0; } -- cgit v1.2.3 From dba051f36a47989b20b248248ffef7984a2f6013 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:08 +0100 Subject: [PKT_SCHED]: RED: Cleanup and remove unnecessary code Removes the skb trimming code which is not needed since we never touch the skb upon failure. Removes unnecessary includes, initializers, and simplifies the code a bit. Removes Jamal's obsolete email addresses upon his own request. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_red.c | 65 +++++++++++++++++------------------------------------ 1 file changed, 21 insertions(+), 44 deletions(-) diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 76e8df8447d..0d89dee751a 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c @@ -9,38 +9,19 @@ * Authors: Alexey Kuznetsov, * * Changes: - * J Hadi Salim 980914: computation fixes + * J Hadi Salim 980914: computation fixes * Alexey Makarenko 990814: qave on idle link was calculated incorrectly. - * J Hadi Salim 980816: ECN support + * J Hadi Salim 980816: ECN support */ #include #include -#include -#include -#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include #include -#include #include #include -#include #include @@ -70,8 +51,7 @@ static inline int red_use_ecn(struct red_sched_data *q) return q->flags & TC_RED_ECN; } -static int -red_enqueue(struct sk_buff *skb, struct Qdisc* sch) +static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch) { struct red_sched_data *q = qdisc_priv(sch); @@ -116,8 +96,7 @@ congestion_drop: return NET_XMIT_CN; } -static int -red_requeue(struct sk_buff *skb, struct Qdisc* sch) +static int red_requeue(struct sk_buff *skb, struct Qdisc* sch) { struct red_sched_data *q = qdisc_priv(sch); @@ -127,8 +106,7 @@ red_requeue(struct sk_buff *skb, struct Qdisc* sch) return qdisc_requeue(skb, sch); } -static struct sk_buff * -red_dequeue(struct Qdisc* sch) +static struct sk_buff * red_dequeue(struct Qdisc* sch) { struct sk_buff *skb; struct red_sched_data *q = qdisc_priv(sch); @@ -171,14 +149,16 @@ static void red_reset(struct Qdisc* sch) static int red_change(struct Qdisc *sch, struct rtattr *opt) { struct red_sched_data *q = qdisc_priv(sch); - struct rtattr *tb[TCA_RED_STAB]; + struct rtattr *tb[TCA_RED_MAX]; struct tc_red_qopt *ctl; - if (opt == NULL || - rtattr_parse_nested(tb, TCA_RED_STAB, opt) || - tb[TCA_RED_PARMS-1] == 0 || tb[TCA_RED_STAB-1] == 0 || + if (opt == NULL || rtattr_parse_nested(tb, TCA_RED_MAX, opt)) + return -EINVAL; + + if (tb[TCA_RED_PARMS-1] == NULL || RTA_PAYLOAD(tb[TCA_RED_PARMS-1]) < sizeof(*ctl) || - RTA_PAYLOAD(tb[TCA_RED_STAB-1]) < 256) + tb[TCA_RED_STAB-1] == NULL || + RTA_PAYLOAD(tb[TCA_RED_STAB-1]) < RED_STAB_SIZE) return -EINVAL; ctl = RTA_DATA(tb[TCA_RED_PARMS-1]); @@ -193,6 +173,7 @@ static int red_change(struct Qdisc *sch, struct rtattr *opt) if (skb_queue_empty(&sch->q)) red_end_of_idle_period(&q->parms); + sch_tree_unlock(sch); return 0; } @@ -205,8 +186,7 @@ static int red_init(struct Qdisc* sch, struct rtattr *opt) static int red_dump(struct Qdisc *sch, struct sk_buff *skb) { struct red_sched_data *q = qdisc_priv(sch); - unsigned char *b = skb->tail; - struct rtattr *rta; + struct rtattr *opts = NULL; struct tc_red_qopt opt = { .limit = q->limit, .flags = q->flags, @@ -217,16 +197,12 @@ static int red_dump(struct Qdisc *sch, struct sk_buff *skb) .Scell_log = q->parms.Scell_log, }; - rta = (struct rtattr*)b; - RTA_PUT(skb, TCA_OPTIONS, 0, NULL); + opts = RTA_NEST(skb, TCA_OPTIONS); RTA_PUT(skb, TCA_RED_PARMS, sizeof(opt), &opt); - rta->rta_len = skb->tail - b; - - return skb->len; + return RTA_NEST_END(skb, opts); rtattr_failure: - skb_trim(skb, b - skb->data); - return -1; + return RTA_NEST_CANCEL(skb, opts); } static int red_dump_stats(struct Qdisc *sch, struct gnet_dump *d) @@ -243,8 +219,6 @@ static int red_dump_stats(struct Qdisc *sch, struct gnet_dump *d) } static struct Qdisc_ops red_qdisc_ops = { - .next = NULL, - .cl_ops = NULL, .id = "red", .priv_size = sizeof(struct red_sched_data), .enqueue = red_enqueue, @@ -263,10 +237,13 @@ static int __init red_module_init(void) { return register_qdisc(&red_qdisc_ops); } -static void __exit red_module_exit(void) + +static void __exit red_module_exit(void) { unregister_qdisc(&red_qdisc_ops); } + module_init(red_module_init) module_exit(red_module_exit) + MODULE_LICENSE("GPL"); -- cgit v1.2.3 From dea3f62852f98670b72ad355c67bd55c9af58530 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:09 +0100 Subject: [PKT_SCHED]: GRED: Cleanup equalize flag and add new WRED mode detection Introduces a flags variable using bitops and transforms eqp to use it. Converts the conditions of the form (wred && rio) to (wred) since wred can only be enabled in rio mode anyway. The patch also improves WRED mode detection. The current behaviour does not allow WRED mode to be turned off again without removing the whole qdisc first. The new algorithm checks each VQ against each other looking for equal priorities every time a VQ is changed or added. The performance is poor, O(n**2), but it's used only during administrative tasks and the number of VQs is strictly limited. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_gred.c | 87 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 65 insertions(+), 22 deletions(-) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 25c171c3271..4ced47bf608 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -91,16 +91,57 @@ struct gred_sched_data psched_time_t qidlestart; /* Start of idle period */ }; +enum { + GRED_WRED_MODE = 1, +}; + struct gred_sched { struct gred_sched_data *tab[MAX_DPs]; + unsigned long flags; u32 DPs; u32 def; u8 initd; u8 grio; - u8 eqp; }; +static inline int gred_wred_mode(struct gred_sched *table) +{ + return test_bit(GRED_WRED_MODE, &table->flags); +} + +static inline void gred_enable_wred_mode(struct gred_sched *table) +{ + __set_bit(GRED_WRED_MODE, &table->flags); +} + +static inline void gred_disable_wred_mode(struct gred_sched *table) +{ + __clear_bit(GRED_WRED_MODE, &table->flags); +} + +static inline int gred_wred_mode_check(struct Qdisc *sch) +{ + struct gred_sched *table = qdisc_priv(sch); + int i; + + /* Really ugly O(n^2) but shouldn't be necessary too frequent. */ + for (i = 0; i < table->DPs; i++) { + struct gred_sched_data *q = table->tab[i]; + int n; + + if (q == NULL) + continue; + + for (n = 0; n < table->DPs; n++) + if (table->tab[n] && table->tab[n] != q && + table->tab[n]->prio == q->prio) + return 1; + } + + return 0; +} + static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) { @@ -132,7 +173,7 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) "general backlog %d\n",skb->tc_index&0xf,sch->handle,q->backlog, sch->qstats.backlog); /* sum up all the qaves of prios <= to ours to get the new qave*/ - if (!t->eqp && t->grio) { + if (!gred_wred_mode(t) && t->grio) { for (i=0;iDPs;i++) { if ((!t->tab[i]) || (i==q->DP)) continue; @@ -146,7 +187,7 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) q->packetsin++; q->bytesin+=skb->len; - if (t->eqp && t->grio) { + if (gred_wred_mode(t)) { qave=0; q->qave=t->tab[t->def]->qave; q->qidlestart=t->tab[t->def]->qidlestart; @@ -160,7 +201,7 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) q->qave >>= q->Stab[(us_idle>>q->Scell_log)&0xFF]; } else { - if (t->eqp) { + if (gred_wred_mode(t)) { q->qave += sch->qstats.backlog - (q->qave >> q->Wlog); } else { q->qave += q->backlog - (q->qave >> q->Wlog); @@ -169,7 +210,7 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) } - if (t->eqp && t->grio) + if (gred_wred_mode(t)) t->tab[t->def]->qave=q->qave; if ((q->qave+qave) < q->qth_min) { @@ -240,7 +281,7 @@ gred_dequeue(struct Qdisc* sch) q= t->tab[(skb->tc_index&0xf)]; if (q) { q->backlog -= skb->len; - if (!q->backlog && !t->eqp) + if (!q->backlog && !gred_wred_mode(t)) PSCHED_GET_TIME(q->qidlestart); } else { D2PRINTK("gred_dequeue: skb has bad tcindex %x\n",skb->tc_index&0xf); @@ -248,7 +289,7 @@ gred_dequeue(struct Qdisc* sch) return skb; } - if (t->eqp) { + if (gred_wred_mode(t)) { q= t->tab[t->def]; if (!q) D2PRINTK("no default VQ set: Results will be " @@ -276,7 +317,7 @@ static unsigned int gred_drop(struct Qdisc* sch) if (q) { q->backlog -= len; q->other++; - if (!q->backlog && !t->eqp) + if (!q->backlog && !gred_wred_mode(t)) PSCHED_GET_TIME(q->qidlestart); } else { D2PRINTK("gred_dequeue: skb has bad tcindex %x\n",skb->tc_index&0xf); @@ -330,7 +371,6 @@ static int gred_change(struct Qdisc *sch, struct rtattr *opt) struct tc_gred_sopt *sopt; struct rtattr *tb[TCA_GRED_STAB]; struct rtattr *tb2[TCA_GRED_DPS]; - int i; if (opt == NULL || rtattr_parse_nested(tb, TCA_GRED_STAB, opt)) return -EINVAL; @@ -344,7 +384,17 @@ static int gred_change(struct Qdisc *sch, struct rtattr *opt) sopt = RTA_DATA(tb2[TCA_GRED_DPS-1]); table->DPs=sopt->DPs; table->def=sopt->def_DP; - table->grio=sopt->grio; + + if (sopt->grio) { + table->grio = 1; + gred_disable_wred_mode(table); + if (gred_wred_mode_check(sch)) + gred_enable_wred_mode(table); + } else { + table->grio = 0; + gred_disable_wred_mode(table); + } + table->initd=0; /* probably need to clear all the table DP entries as well */ return 0; @@ -413,17 +463,10 @@ static int gred_change(struct Qdisc *sch, struct rtattr *opt) PSCHED_SET_PASTPERFECT(q->qidlestart); memcpy(q->Stab, RTA_DATA(tb[TCA_GRED_STAB-1]), 256); - if ( table->initd && table->grio) { - /* this looks ugly but it's not in the fast path */ - for (i=0;iDPs;i++) { - if ((!table->tab[i]) || (i==q->DP) ) - continue; - if (table->tab[i]->prio == q->prio ){ - /* WRED mode detected */ - table->eqp=1; - break; - } - } + if (table->grio) { + gred_disable_wred_mode(table); + if (gred_wred_mode_check(sch)) + gred_enable_wred_mode(table); } if (!table->initd) { @@ -541,7 +584,7 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) dst->DP=q->DP; dst->backlog=q->backlog; if (q->qave) { - if (table->eqp && table->grio) { + if (gred_wred_mode(table)) { q->qidlestart=table->tab[table->def]->qidlestart; q->qave=table->tab[table->def]->qave; } -- cgit v1.2.3 From d6fd4e9667bf5e00b92e62f02d75bd6c97a7007a Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:10 +0100 Subject: [PKT_SCHED]: GRED: Transform grio to GRED_RIO_MODE Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_gred.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 4ced47bf608..db594b46a52 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -93,6 +93,7 @@ struct gred_sched_data enum { GRED_WRED_MODE = 1, + GRED_RIO_MODE, }; struct gred_sched @@ -102,7 +103,6 @@ struct gred_sched u32 DPs; u32 def; u8 initd; - u8 grio; }; static inline int gred_wred_mode(struct gred_sched *table) @@ -120,6 +120,21 @@ static inline void gred_disable_wred_mode(struct gred_sched *table) __clear_bit(GRED_WRED_MODE, &table->flags); } +static inline int gred_rio_mode(struct gred_sched *table) +{ + return test_bit(GRED_RIO_MODE, &table->flags); +} + +static inline void gred_enable_rio_mode(struct gred_sched *table) +{ + __set_bit(GRED_RIO_MODE, &table->flags); +} + +static inline void gred_disable_rio_mode(struct gred_sched *table) +{ + __clear_bit(GRED_RIO_MODE, &table->flags); +} + static inline int gred_wred_mode_check(struct Qdisc *sch) { struct gred_sched *table = qdisc_priv(sch); @@ -173,7 +188,7 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) "general backlog %d\n",skb->tc_index&0xf,sch->handle,q->backlog, sch->qstats.backlog); /* sum up all the qaves of prios <= to ours to get the new qave*/ - if (!gred_wred_mode(t) && t->grio) { + if (!gred_wred_mode(t) && gred_rio_mode(t)) { for (i=0;iDPs;i++) { if ((!t->tab[i]) || (i==q->DP)) continue; @@ -386,12 +401,12 @@ static int gred_change(struct Qdisc *sch, struct rtattr *opt) table->def=sopt->def_DP; if (sopt->grio) { - table->grio = 1; + gred_enable_rio_mode(table); gred_disable_wred_mode(table); if (gred_wred_mode_check(sch)) gred_enable_wred_mode(table); } else { - table->grio = 0; + gred_disable_rio_mode(table); gred_disable_wred_mode(table); } @@ -423,7 +438,7 @@ static int gred_change(struct Qdisc *sch, struct rtattr *opt) } q= table->tab[ctl->DP]; - if (table->grio) { + if (gred_rio_mode(table)) { if (ctl->prio <=0) { if (table->def && table->tab[table->def]) { DPRINTK("\nGRED: DP %u does not have a prio" @@ -463,7 +478,7 @@ static int gred_change(struct Qdisc *sch, struct rtattr *opt) PSCHED_SET_PASTPERFECT(q->qidlestart); memcpy(q->Stab, RTA_DATA(tb[TCA_GRED_STAB-1]), 256); - if (table->grio) { + if (gred_rio_mode(table)) { gred_disable_wred_mode(table); if (gred_wred_mode_check(sch)) gred_enable_wred_mode(table); @@ -496,7 +511,7 @@ static int gred_change(struct Qdisc *sch, struct rtattr *opt) q->qth_min = ctl->qth_min<Wlog; q->qth_max = ctl->qth_max<Wlog; - if (table->grio) + if (gred_rio_mode(table)) q->prio=table->tab[ctl->DP]->prio; else q->prio=8; @@ -528,7 +543,12 @@ static int gred_init(struct Qdisc *sch, struct rtattr *opt) sopt = RTA_DATA(tb2[TCA_GRED_DPS-1]); table->DPs=sopt->DPs; table->def=sopt->def_DP; - table->grio=sopt->grio; + + if (sopt->grio) + gred_enable_rio_mode(table); + else + gred_disable_rio_mode(table); + table->initd=0; return 0; } -- cgit v1.2.3 From 05f1cc01b4d24bc5432ae7044f8209d464f2b8ec Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:11 +0100 Subject: [PKT_SCHED]: GRED: Cleanup dumping Avoids the allocation of a buffer by appending the VQs directly to the skb and simplifies the code by using the appropriate message construction macros. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_gred.c | 92 +++++++++++++++++++--------------------------------- 1 file changed, 34 insertions(+), 58 deletions(-) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index db594b46a52..b3f5ad73fd8 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -559,50 +559,44 @@ static int gred_init(struct Qdisc *sch, struct rtattr *opt) static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) { - unsigned long qave; - struct rtattr *rta; - struct tc_gred_qopt *opt = NULL ; - struct tc_gred_qopt *dst; struct gred_sched *table = qdisc_priv(sch); - struct gred_sched_data *q; + struct rtattr *parms, *opts = NULL; int i; - unsigned char *b = skb->tail; - - rta = (struct rtattr*)b; - RTA_PUT(skb, TCA_OPTIONS, 0, NULL); - opt=kmalloc(sizeof(struct tc_gred_qopt)*MAX_DPs, GFP_KERNEL); - - if (opt == NULL) { - DPRINTK("gred_dump:failed to malloc for %Zd\n", - sizeof(struct tc_gred_qopt)*MAX_DPs); - goto rtattr_failure; - } + opts = RTA_NEST(skb, TCA_OPTIONS); + parms = RTA_NEST(skb, TCA_GRED_PARMS); - memset(opt, 0, (sizeof(struct tc_gred_qopt))*table->DPs); - - if (!table->initd) { - DPRINTK("NO GRED Queues setup!\n"); - } + for (i = 0; i < MAX_DPs; i++) { + struct gred_sched_data *q = table->tab[i]; + struct tc_gred_qopt opt; - for (i=0;itab[i]; + memset(&opt, 0, sizeof(opt)); if (!q) { /* hack -- fix at some point with proper message This is how we indicate to tc that there is no VQ at this DP */ - dst->DP=MAX_DPs+i; - continue; + opt.DP = MAX_DPs + i; + goto append_opt; } - dst->limit=q->limit; - dst->qth_min=q->qth_min>>q->Wlog; - dst->qth_max=q->qth_max>>q->Wlog; - dst->DP=q->DP; - dst->backlog=q->backlog; + opt.limit = q->limit; + opt.DP = q->DP; + opt.backlog = q->backlog; + opt.prio = q->prio; + opt.qth_min = q->qth_min >> q->Wlog; + opt.qth_max = q->qth_max >> q->Wlog; + opt.Wlog = q->Wlog; + opt.Plog = q->Plog; + opt.Scell_log = q->Scell_log; + opt.other = q->other; + opt.early = q->early; + opt.forced = q->forced; + opt.pdrop = q->pdrop; + opt.packets = q->packetsin; + opt.bytesin = q->bytesin; + if (q->qave) { if (gred_wred_mode(table)) { q->qidlestart=table->tab[table->def]->qidlestart; @@ -610,46 +604,28 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) } if (!PSCHED_IS_PASTPERFECT(q->qidlestart)) { long idle; + unsigned long qave; psched_time_t now; PSCHED_GET_TIME(now); idle = PSCHED_TDIFF_SAFE(now, q->qidlestart, q->Scell_max); qave = q->qave >> q->Stab[(idle>>q->Scell_log)&0xFF]; - dst->qave = qave >> q->Wlog; + opt.qave = qave >> q->Wlog; } else { - dst->qave = q->qave >> q->Wlog; + opt.qave = q->qave >> q->Wlog; } - } else { - dst->qave = 0; } - - - dst->Wlog = q->Wlog; - dst->Plog = q->Plog; - dst->Scell_log = q->Scell_log; - dst->other = q->other; - dst->forced = q->forced; - dst->early = q->early; - dst->pdrop = q->pdrop; - dst->prio = q->prio; - dst->packets=q->packetsin; - dst->bytesin=q->bytesin; + +append_opt: + RTA_APPEND(skb, sizeof(opt), &opt); } - RTA_PUT(skb, TCA_GRED_PARMS, sizeof(struct tc_gred_qopt)*MAX_DPs, opt); - rta->rta_len = skb->tail - b; + RTA_NEST_END(skb, parms); - kfree(opt); - return skb->len; + return RTA_NEST_END(skb, opts); rtattr_failure: - if (opt) - kfree(opt); - DPRINTK("gred_dump: FAILURE!!!!\n"); - -/* also free the opt struct here */ - skb_trim(skb, b - skb->data); - return -1; + return RTA_NEST_CANCEL(skb, opts); } static void gred_destroy(struct Qdisc *sch) -- cgit v1.2.3 From e06368221c204d7b5f1ba37d047170f9a0dd359d Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:12 +0100 Subject: [PKT_SCHED]: GRED: Dump table definition Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_gred.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index b3f5ad73fd8..a1369550ce7 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -562,8 +562,14 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) struct gred_sched *table = qdisc_priv(sch); struct rtattr *parms, *opts = NULL; int i; + struct tc_gred_sopt sopt = { + .DPs = table->DPs, + .def_DP = table->def, + .grio = gred_rio_mode(table), + }; opts = RTA_NEST(skb, TCA_OPTIONS); + RTA_PUT(skb, TCA_GRED_DPS, sizeof(sopt), &sopt); parms = RTA_NEST(skb, TCA_GRED_PARMS); for (i = 0; i < MAX_DPs; i++) { -- cgit v1.2.3 From 6639607ed9deaed9ab3a1cc588f0288891ece2ac Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:13 +0100 Subject: [PKT_SCHED]: GRED: Use a central table definition change procedure Introduces a function gred_change_table_def() acting as a central point to change the table definition. Adds missing validations for table definition: MAX_DPs > DPs > 0 and def_DP < DPs thus fixing possible invalid memory reference oopses. Only root could do it but having a typo crashing the machine is a bit hard. Adds missing locking while changing the table definition, the operation of changing the number of DPs and removing shadowed VQs may not be interrupted by a dequeue. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_gred.c | 113 +++++++++++++++++++++++++++------------------------ 1 file changed, 61 insertions(+), 52 deletions(-) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index a1369550ce7..fdc20ced52e 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -378,43 +378,72 @@ static void gred_reset(struct Qdisc* sch) } } -static int gred_change(struct Qdisc *sch, struct rtattr *opt) +static inline void gred_destroy_vq(struct gred_sched_data *q) +{ + kfree(q); +} + +static inline int gred_change_table_def(struct Qdisc *sch, struct rtattr *dps) { struct gred_sched *table = qdisc_priv(sch); - struct gred_sched_data *q; - struct tc_gred_qopt *ctl; struct tc_gred_sopt *sopt; - struct rtattr *tb[TCA_GRED_STAB]; - struct rtattr *tb2[TCA_GRED_DPS]; + int i; - if (opt == NULL || rtattr_parse_nested(tb, TCA_GRED_STAB, opt)) + if (dps == NULL || RTA_PAYLOAD(dps) < sizeof(*sopt)) return -EINVAL; - if (tb[TCA_GRED_PARMS-1] == 0 && tb[TCA_GRED_STAB-1] == 0) { - rtattr_parse_nested(tb2, TCA_GRED_DPS, opt); + sopt = RTA_DATA(dps); - if (tb2[TCA_GRED_DPS-1] == 0) - return -EINVAL; + if (sopt->DPs > MAX_DPs || sopt->DPs == 0 || sopt->def_DP >= sopt->DPs) + return -EINVAL; - sopt = RTA_DATA(tb2[TCA_GRED_DPS-1]); - table->DPs=sopt->DPs; - table->def=sopt->def_DP; + sch_tree_lock(sch); + table->DPs = sopt->DPs; + table->def = sopt->def_DP; - if (sopt->grio) { - gred_enable_rio_mode(table); - gred_disable_wred_mode(table); - if (gred_wred_mode_check(sch)) - gred_enable_wred_mode(table); - } else { - gred_disable_rio_mode(table); - gred_disable_wred_mode(table); - } + /* + * Every entry point to GRED is synchronized with the above code + * and the DP is checked against DPs, i.e. shadowed VQs can no + * longer be found so we can unlock right here. + */ + sch_tree_unlock(sch); - table->initd=0; - /* probably need to clear all the table DP entries as well */ - return 0; - } + if (sopt->grio) { + gred_enable_rio_mode(table); + gred_disable_wred_mode(table); + if (gred_wred_mode_check(sch)) + gred_enable_wred_mode(table); + } else { + gred_disable_rio_mode(table); + gred_disable_wred_mode(table); + } + + for (i = table->DPs; i < MAX_DPs; i++) { + if (table->tab[i]) { + printk(KERN_WARNING "GRED: Warning: Destroying " + "shadowed VQ 0x%x\n", i); + gred_destroy_vq(table->tab[i]); + table->tab[i] = NULL; + } + } + table->initd = 0; + + return 0; +} + +static int gred_change(struct Qdisc *sch, struct rtattr *opt) +{ + struct gred_sched *table = qdisc_priv(sch); + struct gred_sched_data *q; + struct tc_gred_qopt *ctl; + struct rtattr *tb[TCA_GRED_STAB]; + + if (opt == NULL || rtattr_parse_nested(tb, TCA_GRED_STAB, opt)) + return -EINVAL; + + if (tb[TCA_GRED_PARMS-1] == NULL && tb[TCA_GRED_STAB-1] == NULL) + return gred_change_table_def(sch, tb[TCA_GRED_DPS-1]); if (!table->DPs || tb[TCA_GRED_PARMS-1] == 0 || tb[TCA_GRED_STAB-1] == 0 || RTA_PAYLOAD(tb[TCA_GRED_PARMS-1]) < sizeof(*ctl) || @@ -526,35 +555,15 @@ static int gred_change(struct Qdisc *sch, struct rtattr *opt) static int gred_init(struct Qdisc *sch, struct rtattr *opt) { - struct gred_sched *table = qdisc_priv(sch); - struct tc_gred_sopt *sopt; - struct rtattr *tb[TCA_GRED_STAB]; - struct rtattr *tb2[TCA_GRED_DPS]; + struct rtattr *tb[TCA_GRED_MAX]; - if (opt == NULL || rtattr_parse_nested(tb, TCA_GRED_STAB, opt)) + if (opt == NULL || rtattr_parse_nested(tb, TCA_GRED_MAX, opt)) return -EINVAL; - if (tb[TCA_GRED_PARMS-1] == 0 && tb[TCA_GRED_STAB-1] == 0) { - rtattr_parse_nested(tb2, TCA_GRED_DPS, opt); - - if (tb2[TCA_GRED_DPS-1] == 0) - return -EINVAL; - - sopt = RTA_DATA(tb2[TCA_GRED_DPS-1]); - table->DPs=sopt->DPs; - table->def=sopt->def_DP; - - if (sopt->grio) - gred_enable_rio_mode(table); - else - gred_disable_rio_mode(table); - - table->initd=0; - return 0; - } + if (tb[TCA_GRED_PARMS-1] || tb[TCA_GRED_STAB-1]) + return -EINVAL; - DPRINTK("\n GRED_INIT error!\n"); - return -EINVAL; + return gred_change_table_def(sch, tb[TCA_GRED_DPS-1]); } static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) @@ -641,7 +650,7 @@ static void gred_destroy(struct Qdisc *sch) for (i = 0;i < table->DPs; i++) { if (table->tab[i]) - kfree(table->tab[i]); + gred_destroy_vq(table->tab[i]); } } -- cgit v1.2.3 From a8aaa9958eea2420e13d5a00c3fae934e0a3889e Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:14 +0100 Subject: [PKT_SCHED]: GRED: Report out-of-bound DPs as illegal Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_gred.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index fdc20ced52e..b04b07fcc2c 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -451,12 +451,9 @@ static int gred_change(struct Qdisc *sch, struct rtattr *opt) return -EINVAL; ctl = RTA_DATA(tb[TCA_GRED_PARMS-1]); - if (ctl->DP > MAX_DPs-1 ) { - /* misbehaving is punished! Put in the default drop probability */ - DPRINTK("\nGRED: DP %u not in the proper range fixed. New DP " - "set to default at %d\n",ctl->DP,table->def); - ctl->DP=table->def; - } + + if (ctl->DP >= table->DPs) + return -EINVAL; if (table->tab[ctl->DP] == NULL) { table->tab[ctl->DP]=kmalloc(sizeof(struct gred_sched_data), -- cgit v1.2.3 From f62d6b936df500247474c13360eb23e1b602bad0 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:15 +0100 Subject: [PKT_SCHED]: GRED: Use central VQ change procedure Introduces a function gred_change_vq() acting as a central point to change VQ parameters. Fixes priority inheritance in rio mode when the default DP equals 0. Adds proper locking during changes. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_gred.c | 173 +++++++++++++++++++++++++-------------------------- 1 file changed, 84 insertions(+), 89 deletions(-) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index b04b07fcc2c..ca6cb271493 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -58,6 +58,8 @@ #define D2PRINTK(format,args...) #endif +#define GRED_DEF_PRIO (MAX_DPs / 2) + struct gred_sched_data; struct gred_sched; @@ -432,77 +434,102 @@ static inline int gred_change_table_def(struct Qdisc *sch, struct rtattr *dps) return 0; } -static int gred_change(struct Qdisc *sch, struct rtattr *opt) +static inline int gred_change_vq(struct Qdisc *sch, int dp, + struct tc_gred_qopt *ctl, int prio, u8 *stab) { struct gred_sched *table = qdisc_priv(sch); struct gred_sched_data *q; + + if (table->tab[dp] == NULL) { + table->tab[dp] = kmalloc(sizeof(*q), GFP_KERNEL); + if (table->tab[dp] == NULL) + return -ENOMEM; + memset(table->tab[dp], 0, sizeof(*q)); + } + + q = table->tab[dp]; + q->DP = dp; + q->prio = prio; + + q->Wlog = ctl->Wlog; + q->Plog = ctl->Plog; + q->limit = ctl->limit; + q->Scell_log = ctl->Scell_log; + q->Rmask = ctl->Plog < 32 ? ((1<Plog) - 1) : ~0UL; + q->Scell_max = (255<Scell_log); + q->qth_min = ctl->qth_min<Wlog; + q->qth_max = ctl->qth_max<Wlog; + q->qave=0; + q->backlog=0; + q->qcount = -1; + q->other=0; + q->forced=0; + q->pdrop=0; + q->early=0; + + PSCHED_SET_PASTPERFECT(q->qidlestart); + memcpy(q->Stab, stab, 256); + + return 0; +} + +static int gred_change(struct Qdisc *sch, struct rtattr *opt) +{ + struct gred_sched *table = qdisc_priv(sch); struct tc_gred_qopt *ctl; - struct rtattr *tb[TCA_GRED_STAB]; + struct rtattr *tb[TCA_GRED_MAX]; + int err = -EINVAL, prio = GRED_DEF_PRIO; + u8 *stab; - if (opt == NULL || rtattr_parse_nested(tb, TCA_GRED_STAB, opt)) + if (opt == NULL || rtattr_parse_nested(tb, TCA_GRED_MAX, opt)) return -EINVAL; if (tb[TCA_GRED_PARMS-1] == NULL && tb[TCA_GRED_STAB-1] == NULL) - return gred_change_table_def(sch, tb[TCA_GRED_DPS-1]); + return gred_change_table_def(sch, opt); - if (!table->DPs || tb[TCA_GRED_PARMS-1] == 0 || tb[TCA_GRED_STAB-1] == 0 || - RTA_PAYLOAD(tb[TCA_GRED_PARMS-1]) < sizeof(*ctl) || - RTA_PAYLOAD(tb[TCA_GRED_STAB-1]) < 256) - return -EINVAL; + if (tb[TCA_GRED_PARMS-1] == NULL || + RTA_PAYLOAD(tb[TCA_GRED_PARMS-1]) < sizeof(*ctl) || + tb[TCA_GRED_STAB-1] == NULL || + RTA_PAYLOAD(tb[TCA_GRED_STAB-1]) < 256) + return -EINVAL; ctl = RTA_DATA(tb[TCA_GRED_PARMS-1]); + stab = RTA_DATA(tb[TCA_GRED_STAB-1]); if (ctl->DP >= table->DPs) - return -EINVAL; - - if (table->tab[ctl->DP] == NULL) { - table->tab[ctl->DP]=kmalloc(sizeof(struct gred_sched_data), - GFP_KERNEL); - if (NULL == table->tab[ctl->DP]) - return -ENOMEM; - memset(table->tab[ctl->DP], 0, (sizeof(struct gred_sched_data))); - } - q= table->tab[ctl->DP]; + goto errout; if (gred_rio_mode(table)) { - if (ctl->prio <=0) { - if (table->def && table->tab[table->def]) { - DPRINTK("\nGRED: DP %u does not have a prio" - "setting default to %d\n",ctl->DP, - table->tab[table->def]->prio); - q->prio=table->tab[table->def]->prio; - } else { - DPRINTK("\nGRED: DP %u does not have a prio" - " setting default to 8\n",ctl->DP); - q->prio=8; - } - } else { - q->prio=ctl->prio; - } - } else { - q->prio=8; + if (ctl->prio == 0) { + int def_prio = GRED_DEF_PRIO; + + if (table->tab[table->def]) + def_prio = table->tab[table->def]->prio; + + printk(KERN_DEBUG "GRED: DP %u does not have a prio " + "setting default to %d\n", ctl->DP, def_prio); + + prio = def_prio; + } else + prio = ctl->prio; } + sch_tree_lock(sch); - q->DP=ctl->DP; - q->Wlog = ctl->Wlog; - q->Plog = ctl->Plog; - q->limit = ctl->limit; - q->Scell_log = ctl->Scell_log; - q->Rmask = ctl->Plog < 32 ? ((1<Plog) - 1) : ~0UL; - q->Scell_max = (255<Scell_log); - q->qth_min = ctl->qth_min<Wlog; - q->qth_max = ctl->qth_max<Wlog; - q->qave=0; - q->backlog=0; - q->qcount = -1; - q->other=0; - q->forced=0; - q->pdrop=0; - q->early=0; + err = gred_change_vq(sch, ctl->DP, ctl, prio, stab); + if (err < 0) + goto errout_locked; - PSCHED_SET_PASTPERFECT(q->qidlestart); - memcpy(q->Stab, RTA_DATA(tb[TCA_GRED_STAB-1]), 256); + if (table->tab[table->def] == NULL) { + if (gred_rio_mode(table)) + prio = table->tab[ctl->DP]->prio; + + err = gred_change_vq(sch, table->def, ctl, prio, stab); + if (err < 0) + goto errout_locked; + } + + table->initd = 1; if (gred_rio_mode(table)) { gred_disable_wred_mode(table); @@ -510,44 +537,12 @@ static int gred_change(struct Qdisc *sch, struct rtattr *opt) gred_enable_wred_mode(table); } - if (!table->initd) { - table->initd=1; - /* - the first entry also goes into the default until - over-written - */ - - if (table->tab[table->def] == NULL) { - table->tab[table->def]= - kmalloc(sizeof(struct gred_sched_data), GFP_KERNEL); - if (NULL == table->tab[table->def]) - return -ENOMEM; - - memset(table->tab[table->def], 0, - (sizeof(struct gred_sched_data))); - } - q= table->tab[table->def]; - q->DP=table->def; - q->Wlog = ctl->Wlog; - q->Plog = ctl->Plog; - q->limit = ctl->limit; - q->Scell_log = ctl->Scell_log; - q->Rmask = ctl->Plog < 32 ? ((1<Plog) - 1) : ~0UL; - q->Scell_max = (255<Scell_log); - q->qth_min = ctl->qth_min<Wlog; - q->qth_max = ctl->qth_max<Wlog; - - if (gred_rio_mode(table)) - q->prio=table->tab[ctl->DP]->prio; - else - q->prio=8; - - q->qcount = -1; - PSCHED_SET_PASTPERFECT(q->qidlestart); - memcpy(q->Stab, RTA_DATA(tb[TCA_GRED_STAB-1]), 256); - } - return 0; + err = 0; +errout_locked: + sch_tree_unlock(sch); +errout: + return err; } static int gred_init(struct Qdisc *sch, struct rtattr *opt) -- cgit v1.2.3 From 22b33429ab93155895854e9518a253680a920493 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:16 +0100 Subject: [PKT_SCHED]: GRED: Use new generic red interface Simplifies code a lot by separating the red algorithm and the queueing logic. We now differentiate between probability marks and forced marks but sum them together again to not break backwards compatibility. This brings GRED back to the level of RED and improves the accuracy of the averge queue length calculations when stab suggests a zero shift. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_gred.c | 224 +++++++++++++++++++++------------------------------ 1 file changed, 91 insertions(+), 133 deletions(-) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index ca6cb271493..a52490c7af3 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -45,6 +45,7 @@ #include #include #include +#include #if 1 /* control */ #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) @@ -65,32 +66,15 @@ struct gred_sched; struct gred_sched_data { -/* Parameters */ u32 limit; /* HARD maximal queue length */ - u32 qth_min; /* Min average length threshold: A scaled */ - u32 qth_max; /* Max average length threshold: A scaled */ u32 DP; /* the drop pramaters */ - char Wlog; /* log(W) */ - char Plog; /* random number bits */ - u32 Scell_max; - u32 Rmask; u32 bytesin; /* bytes seen on virtualQ so far*/ u32 packetsin; /* packets seen on virtualQ so far*/ u32 backlog; /* bytes on the virtualQ */ - u32 forced; /* packets dropped for exceeding limits */ - u32 early; /* packets dropped as a warning */ - u32 other; /* packets dropped by invoking drop() */ - u32 pdrop; /* packets dropped because we exceeded physical queue limits */ - char Scell_log; - u8 Stab[256]; u8 prio; /* the prio of this vq */ -/* Variables */ - unsigned long qave; /* Average queue length: A scaled */ - int qcount; /* Packets since last random number generation */ - u32 qR; /* Cached random number */ - - psched_time_t qidlestart; /* Start of idle period */ + struct red_parms parms; + struct red_stats stats; }; enum { @@ -159,13 +143,22 @@ static inline int gred_wred_mode_check(struct Qdisc *sch) return 0; } +static inline unsigned int gred_backlog(struct gred_sched *table, + struct gred_sched_data *q, + struct Qdisc *sch) +{ + if (gred_wred_mode(table)) + return sch->qstats.backlog; + else + return q->backlog; +} + static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) { - psched_time_t now; struct gred_sched_data *q=NULL; struct gred_sched *t= qdisc_priv(sch); - unsigned long qave=0; + unsigned long qavg = 0; int i=0; if (!t->initd && skb_queue_len(&sch->q) < (sch->dev->tx_queue_len ? : 1)) { @@ -195,8 +188,9 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) if ((!t->tab[i]) || (i==q->DP)) continue; - if ((t->tab[i]->prio < q->prio) && (PSCHED_IS_PASTPERFECT(t->tab[i]->qidlestart))) - qave +=t->tab[i]->qave; + if (t->tab[i]->prio < q->prio && + !red_is_idling(&t->tab[i]->parms)) + qavg +=t->tab[i]->parms.qavg; } } @@ -205,68 +199,49 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) q->bytesin+=skb->len; if (gred_wred_mode(t)) { - qave=0; - q->qave=t->tab[t->def]->qave; - q->qidlestart=t->tab[t->def]->qidlestart; + qavg = 0; + q->parms.qavg = t->tab[t->def]->parms.qavg; + q->parms.qidlestart = t->tab[t->def]->parms.qidlestart; } - if (!PSCHED_IS_PASTPERFECT(q->qidlestart)) { - long us_idle; - PSCHED_GET_TIME(now); - us_idle = PSCHED_TDIFF_SAFE(now, q->qidlestart, q->Scell_max); - PSCHED_SET_PASTPERFECT(q->qidlestart); + q->parms.qavg = red_calc_qavg(&q->parms, gred_backlog(t, q, sch)); - q->qave >>= q->Stab[(us_idle>>q->Scell_log)&0xFF]; - } else { - if (gred_wred_mode(t)) { - q->qave += sch->qstats.backlog - (q->qave >> q->Wlog); - } else { - q->qave += q->backlog - (q->qave >> q->Wlog); - } - - } - + if (red_is_idling(&q->parms)) + red_end_of_idle_period(&q->parms); if (gred_wred_mode(t)) - t->tab[t->def]->qave=q->qave; + t->tab[t->def]->parms.qavg = q->parms.qavg; - if ((q->qave+qave) < q->qth_min) { - q->qcount = -1; -enqueue: - if (q->backlog + skb->len <= q->limit) { - q->backlog += skb->len; -do_enqueue: - __skb_queue_tail(&sch->q, skb); - sch->qstats.backlog += skb->len; - sch->bstats.bytes += skb->len; - sch->bstats.packets++; - return 0; - } else { - q->pdrop++; - } + switch (red_action(&q->parms, q->parms.qavg + qavg)) { + case RED_DONT_MARK: + break; -drop: - kfree_skb(skb); - sch->qstats.drops++; - return NET_XMIT_DROP; - } - if ((q->qave+qave) >= q->qth_max) { - q->qcount = -1; - sch->qstats.overlimits++; - q->forced++; - goto drop; + case RED_PROB_MARK: + sch->qstats.overlimits++; + q->stats.prob_drop++; + goto drop; + + case RED_HARD_MARK: + sch->qstats.overlimits++; + q->stats.forced_drop++; + goto drop; } - if (++q->qcount) { - if ((((qave+q->qave) - q->qth_min)>>q->Wlog)*q->qcount < q->qR) - goto enqueue; - q->qcount = 0; - q->qR = net_random()&q->Rmask; - sch->qstats.overlimits++; - q->early++; - goto drop; + + if (q->backlog + skb->len <= q->limit) { + q->backlog += skb->len; +do_enqueue: + __skb_queue_tail(&sch->q, skb); + sch->qstats.backlog += skb->len; + sch->bstats.bytes += skb->len; + sch->bstats.packets++; + return 0; } - q->qR = net_random()&q->Rmask; - goto enqueue; + + q->stats.pdrop++; +drop: + kfree_skb(skb); + sch->qstats.drops++; + return NET_XMIT_DROP; } static int @@ -276,7 +251,9 @@ gred_requeue(struct sk_buff *skb, struct Qdisc* sch) struct gred_sched *t= qdisc_priv(sch); q= t->tab[(skb->tc_index&0xf)]; /* error checking here -- probably unnecessary */ - PSCHED_SET_PASTPERFECT(q->qidlestart); + + if (red_is_idling(&q->parms)) + red_end_of_idle_period(&q->parms); __skb_queue_head(&sch->q, skb); sch->qstats.backlog += skb->len; @@ -299,7 +276,7 @@ gred_dequeue(struct Qdisc* sch) if (q) { q->backlog -= skb->len; if (!q->backlog && !gred_wred_mode(t)) - PSCHED_GET_TIME(q->qidlestart); + red_start_of_idle_period(&q->parms); } else { D2PRINTK("gred_dequeue: skb has bad tcindex %x\n",skb->tc_index&0xf); } @@ -312,7 +289,7 @@ gred_dequeue(struct Qdisc* sch) D2PRINTK("no default VQ set: Results will be " "screwed up\n"); else - PSCHED_GET_TIME(q->qidlestart); + red_start_of_idle_period(&q->parms); } return NULL; @@ -333,9 +310,9 @@ static unsigned int gred_drop(struct Qdisc* sch) q= t->tab[(skb->tc_index&0xf)]; if (q) { q->backlog -= len; - q->other++; + q->stats.other++; if (!q->backlog && !gred_wred_mode(t)) - PSCHED_GET_TIME(q->qidlestart); + red_start_of_idle_period(&q->parms); } else { D2PRINTK("gred_dequeue: skb has bad tcindex %x\n",skb->tc_index&0xf); } @@ -350,7 +327,7 @@ static unsigned int gred_drop(struct Qdisc* sch) return 0; } - PSCHED_GET_TIME(q->qidlestart); + red_start_of_idle_period(&q->parms); return 0; } @@ -369,14 +346,12 @@ static void gred_reset(struct Qdisc* sch) q= t->tab[i]; if (!q) continue; - PSCHED_SET_PASTPERFECT(q->qidlestart); - q->qave = 0; - q->qcount = -1; + red_restart(&q->parms); q->backlog = 0; - q->other=0; - q->forced=0; - q->pdrop=0; - q->early=0; + q->stats.other = 0; + q->stats.forced_drop = 0; + q->stats.prob_drop = 0; + q->stats.pdrop = 0; } } @@ -450,25 +425,19 @@ static inline int gred_change_vq(struct Qdisc *sch, int dp, q = table->tab[dp]; q->DP = dp; q->prio = prio; - - q->Wlog = ctl->Wlog; - q->Plog = ctl->Plog; q->limit = ctl->limit; - q->Scell_log = ctl->Scell_log; - q->Rmask = ctl->Plog < 32 ? ((1<Plog) - 1) : ~0UL; - q->Scell_max = (255<Scell_log); - q->qth_min = ctl->qth_min<Wlog; - q->qth_max = ctl->qth_max<Wlog; - q->qave=0; - q->backlog=0; - q->qcount = -1; - q->other=0; - q->forced=0; - q->pdrop=0; - q->early=0; - - PSCHED_SET_PASTPERFECT(q->qidlestart); - memcpy(q->Stab, stab, 256); + + if (q->backlog == 0) + red_end_of_idle_period(&q->parms); + + red_set_parms(&q->parms, + ctl->qth_min, ctl->qth_max, ctl->Wlog, ctl->Plog, + ctl->Scell_log, stab); + + q->stats.other = 0; + q->stats.forced_drop = 0; + q->stats.prob_drop = 0; + q->stats.pdrop = 0; return 0; } @@ -592,37 +561,26 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) opt.DP = q->DP; opt.backlog = q->backlog; opt.prio = q->prio; - opt.qth_min = q->qth_min >> q->Wlog; - opt.qth_max = q->qth_max >> q->Wlog; - opt.Wlog = q->Wlog; - opt.Plog = q->Plog; - opt.Scell_log = q->Scell_log; - opt.other = q->other; - opt.early = q->early; - opt.forced = q->forced; - opt.pdrop = q->pdrop; + opt.qth_min = q->parms.qth_min >> q->parms.Wlog; + opt.qth_max = q->parms.qth_max >> q->parms.Wlog; + opt.Wlog = q->parms.Wlog; + opt.Plog = q->parms.Plog; + opt.Scell_log = q->parms.Scell_log; + opt.other = q->stats.other; + opt.early = q->stats.prob_drop; + opt.forced = q->stats.forced_drop; + opt.pdrop = q->stats.pdrop; opt.packets = q->packetsin; opt.bytesin = q->bytesin; - if (q->qave) { - if (gred_wred_mode(table)) { - q->qidlestart=table->tab[table->def]->qidlestart; - q->qave=table->tab[table->def]->qave; - } - if (!PSCHED_IS_PASTPERFECT(q->qidlestart)) { - long idle; - unsigned long qave; - psched_time_t now; - PSCHED_GET_TIME(now); - idle = PSCHED_TDIFF_SAFE(now, q->qidlestart, q->Scell_max); - qave = q->qave >> q->Stab[(idle>>q->Scell_log)&0xFF]; - opt.qave = qave >> q->Wlog; - - } else { - opt.qave = q->qave >> q->Wlog; - } + if (gred_wred_mode(table)) { + q->parms.qidlestart = + table->tab[table->def]->parms.qidlestart; + q->parms.qavg = table->tab[table->def]->parms.qavg; } + opt.qave = red_calc_qavg(&q->parms, q->parms.qavg); + append_opt: RTA_APPEND(skb, sizeof(opt), &opt); } -- cgit v1.2.3 From 301d063c2915e8307e3d128245d8a393ad776539 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:17 +0100 Subject: [PKT_SCHED]: GRED: Do not reset statistics in gred_reset/gred_change Qdiscs are not supposed to reset statistics in reset() and while changing parameters. My argumentation is that if the user wants the counters to be reset he can simply remove and readd the qdiscs, that's what most users do anyway. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_gred.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index a52490c7af3..50f184cd7f1 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -348,10 +348,6 @@ static void gred_reset(struct Qdisc* sch) continue; red_restart(&q->parms); q->backlog = 0; - q->stats.other = 0; - q->stats.forced_drop = 0; - q->stats.prob_drop = 0; - q->stats.pdrop = 0; } } @@ -434,11 +430,6 @@ static inline int gred_change_vq(struct Qdisc *sch, int dp, ctl->qth_min, ctl->qth_max, ctl->Wlog, ctl->Plog, ctl->Scell_log, stab); - q->stats.other = 0; - q->stats.forced_drop = 0; - q->stats.prob_drop = 0; - q->stats.pdrop = 0; - return 0; } -- cgit v1.2.3 From c3b553cdaf50ce915bcd995fa8ec2905f227de64 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:18 +0100 Subject: [PKT_SCHED]: GRED: Report congestion related drops as NET_XMIT_CN Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_gred.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 50f184cd7f1..f7c6c0359ce 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -219,12 +219,12 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) case RED_PROB_MARK: sch->qstats.overlimits++; q->stats.prob_drop++; - goto drop; + goto congestion_drop; case RED_HARD_MARK: sch->qstats.overlimits++; q->stats.forced_drop++; - goto drop; + goto congestion_drop; } if (q->backlog + skb->len <= q->limit) { @@ -242,6 +242,11 @@ drop: kfree_skb(skb); sch->qstats.drops++; return NET_XMIT_DROP; + +congestion_drop: + kfree_skb(skb); + sch->qstats.drops++; + return NET_XMIT_CN; } static int -- cgit v1.2.3 From edf7a7b1f0bd31d96096e38cbf35b02a3a1352b4 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:19 +0100 Subject: [PKT_SCHED]: GRED: Use generic queue management interface Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_gred.c | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index f7c6c0359ce..95c5f2cf3fd 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -230,22 +230,15 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) if (q->backlog + skb->len <= q->limit) { q->backlog += skb->len; do_enqueue: - __skb_queue_tail(&sch->q, skb); - sch->qstats.backlog += skb->len; - sch->bstats.bytes += skb->len; - sch->bstats.packets++; - return 0; + return qdisc_enqueue_tail(skb, sch); } q->stats.pdrop++; drop: - kfree_skb(skb); - sch->qstats.drops++; - return NET_XMIT_DROP; + return qdisc_drop(skb, sch); congestion_drop: - kfree_skb(skb); - sch->qstats.drops++; + qdisc_drop(skb, sch); return NET_XMIT_CN; } @@ -260,11 +253,8 @@ gred_requeue(struct sk_buff *skb, struct Qdisc* sch) if (red_is_idling(&q->parms)) red_end_of_idle_period(&q->parms); - __skb_queue_head(&sch->q, skb); - sch->qstats.backlog += skb->len; - sch->qstats.requeues++; q->backlog += skb->len; - return 0; + return qdisc_requeue(skb, sch); } static struct sk_buff * @@ -274,9 +264,9 @@ gred_dequeue(struct Qdisc* sch) struct gred_sched_data *q; struct gred_sched *t= qdisc_priv(sch); - skb = __skb_dequeue(&sch->q); + skb = qdisc_dequeue_head(sch); + if (skb) { - sch->qstats.backlog -= skb->len; q= t->tab[(skb->tc_index&0xf)]; if (q) { q->backlog -= skb->len; @@ -307,11 +297,9 @@ static unsigned int gred_drop(struct Qdisc* sch) struct gred_sched_data *q; struct gred_sched *t= qdisc_priv(sch); - skb = __skb_dequeue_tail(&sch->q); + skb = qdisc_dequeue_tail(sch); if (skb) { unsigned int len = skb->len; - sch->qstats.backlog -= len; - sch->qstats.drops++; q= t->tab[(skb->tc_index&0xf)]; if (q) { q->backlog -= len; @@ -322,7 +310,7 @@ static unsigned int gred_drop(struct Qdisc* sch) D2PRINTK("gred_dequeue: skb has bad tcindex %x\n",skb->tc_index&0xf); } - kfree_skb(skb); + qdisc_drop(skb, sch); return len; } @@ -343,9 +331,7 @@ static void gred_reset(struct Qdisc* sch) struct gred_sched_data *q; struct gred_sched *t= qdisc_priv(sch); - __skb_queue_purge(&sch->q); - - sch->qstats.backlog = 0; + qdisc_reset_queue(sch); for (i=0;iDPs;i++) { q= t->tab[i]; -- cgit v1.2.3 From 716a1b40b0ed630570edd4e2bf9053c421e9770b Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:20 +0100 Subject: [PKT_SCHED]: GRED: Introduce tc_index_to_dp() Adds a transformation function returning the DP index for a given skb according to its tc_index. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_gred.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 95c5f2cf3fd..38dab959fee 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -60,6 +60,7 @@ #endif #define GRED_DEF_PRIO (MAX_DPs / 2) +#define GRED_VQ_MASK (MAX_DPs - 1) struct gred_sched_data; struct gred_sched; @@ -153,6 +154,11 @@ static inline unsigned int gred_backlog(struct gred_sched *table, return q->backlog; } +static inline u16 tc_index_to_dp(struct sk_buff *skb) +{ + return skb->tc_index & GRED_VQ_MASK; +} + static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) { @@ -160,14 +166,16 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) struct gred_sched *t= qdisc_priv(sch); unsigned long qavg = 0; int i=0; + u16 dp; if (!t->initd && skb_queue_len(&sch->q) < (sch->dev->tx_queue_len ? : 1)) { D2PRINTK("NO GRED Queues setup yet! Enqueued anyway\n"); goto do_enqueue; } + dp = tc_index_to_dp(skb); - if ( ((skb->tc_index&0xf) > (t->DPs -1)) || !(q=t->tab[skb->tc_index&0xf])) { + if (dp >= t->DPs || (q = t->tab[dp]) == NULL) { printk("GRED: setting to default (%d)\n ",t->def); if (!(q=t->tab[t->def])) { DPRINTK("GRED: setting to default FAILED! dropping!! " @@ -176,7 +184,7 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) } /* fix tc_index? --could be controvesial but needed for requeueing */ - skb->tc_index=(skb->tc_index&0xfffffff0) | t->def; + skb->tc_index=(skb->tc_index & ~GRED_VQ_MASK) | t->def; } D2PRINTK("gred_enqueue virtualQ 0x%x classid %x backlog %d " @@ -245,9 +253,8 @@ congestion_drop: static int gred_requeue(struct sk_buff *skb, struct Qdisc* sch) { - struct gred_sched_data *q; - struct gred_sched *t= qdisc_priv(sch); - q= t->tab[(skb->tc_index&0xf)]; + struct gred_sched *t = qdisc_priv(sch); + struct gred_sched_data *q = t->tab[tc_index_to_dp(skb)]; /* error checking here -- probably unnecessary */ if (red_is_idling(&q->parms)) @@ -267,13 +274,14 @@ gred_dequeue(struct Qdisc* sch) skb = qdisc_dequeue_head(sch); if (skb) { - q= t->tab[(skb->tc_index&0xf)]; + q = t->tab[tc_index_to_dp(skb)]; if (q) { q->backlog -= skb->len; if (!q->backlog && !gred_wred_mode(t)) red_start_of_idle_period(&q->parms); } else { - D2PRINTK("gred_dequeue: skb has bad tcindex %x\n",skb->tc_index&0xf); + D2PRINTK("gred_dequeue: skb has bad tcindex %x\n", + tc_index_to_dp(skb)); } return skb; } @@ -300,14 +308,15 @@ static unsigned int gred_drop(struct Qdisc* sch) skb = qdisc_dequeue_tail(sch); if (skb) { unsigned int len = skb->len; - q= t->tab[(skb->tc_index&0xf)]; + q = t->tab[tc_index_to_dp(skb)]; if (q) { q->backlog -= len; q->stats.other++; if (!q->backlog && !gred_wred_mode(t)) red_start_of_idle_period(&q->parms); } else { - D2PRINTK("gred_dequeue: skb has bad tcindex %x\n",skb->tc_index&0xf); + D2PRINTK("gred_dequeue: skb has bad tcindex %x\n", + tc_index_to_dp(skb)); } qdisc_drop(skb, sch); -- cgit v1.2.3 From 18e3fb84e698dcab1c5fa7b7c89921b826bb5620 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:21 +0100 Subject: [PKT_SCHED]: GRED: Improve error handling and messages Try to enqueue packets if we cannot associate it with a VQ, this basically means that the default VQ has not been set up yet. We must check if the VQ still exists while requeueing, the VQ might have been changed between dequeue and the requeue of the underlying qdisc. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_gred.c | 68 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 38dab959fee..646dbdc4ef2 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -176,20 +176,24 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) dp = tc_index_to_dp(skb); if (dp >= t->DPs || (q = t->tab[dp]) == NULL) { - printk("GRED: setting to default (%d)\n ",t->def); - if (!(q=t->tab[t->def])) { - DPRINTK("GRED: setting to default FAILED! dropping!! " - "(%d)\n ", t->def); - goto drop; + dp = t->def; + + if ((q = t->tab[dp]) == NULL) { + /* Pass through packets not assigned to a DP + * if no default DP has been configured. This + * allows for DP flows to be left untouched. + */ + if (skb_queue_len(&sch->q) < sch->dev->tx_queue_len) + return qdisc_enqueue_tail(skb, sch); + else + goto drop; } + /* fix tc_index? --could be controvesial but needed for requeueing */ - skb->tc_index=(skb->tc_index & ~GRED_VQ_MASK) | t->def; + skb->tc_index = (skb->tc_index & ~GRED_VQ_MASK) | dp; } - D2PRINTK("gred_enqueue virtualQ 0x%x classid %x backlog %d " - "general backlog %d\n",skb->tc_index&0xf,sch->handle,q->backlog, - sch->qstats.backlog); /* sum up all the qaves of prios <= to ours to get the new qave*/ if (!gred_wred_mode(t) && gred_rio_mode(t)) { for (i=0;iDPs;i++) { @@ -254,13 +258,20 @@ static int gred_requeue(struct sk_buff *skb, struct Qdisc* sch) { struct gred_sched *t = qdisc_priv(sch); - struct gred_sched_data *q = t->tab[tc_index_to_dp(skb)]; -/* error checking here -- probably unnecessary */ + struct gred_sched_data *q; + u16 dp = tc_index_to_dp(skb); - if (red_is_idling(&q->parms)) - red_end_of_idle_period(&q->parms); + if (dp >= t->DPs || (q = t->tab[dp]) == NULL) { + if (net_ratelimit()) + printk(KERN_WARNING "GRED: Unable to relocate VQ 0x%x " + "for requeue, screwing up backlog.\n", + tc_index_to_dp(skb)); + } else { + if (red_is_idling(&q->parms)) + red_end_of_idle_period(&q->parms); + q->backlog += skb->len; + } - q->backlog += skb->len; return qdisc_requeue(skb, sch); } @@ -274,15 +285,20 @@ gred_dequeue(struct Qdisc* sch) skb = qdisc_dequeue_head(sch); if (skb) { - q = t->tab[tc_index_to_dp(skb)]; - if (q) { + u16 dp = tc_index_to_dp(skb); + + if (dp >= t->DPs || (q = t->tab[dp]) == NULL) { + if (net_ratelimit()) + printk(KERN_WARNING "GRED: Unable to relocate " + "VQ 0x%x after dequeue, screwing up " + "backlog.\n", tc_index_to_dp(skb)); + } else { q->backlog -= skb->len; + if (!q->backlog && !gred_wred_mode(t)) red_start_of_idle_period(&q->parms); - } else { - D2PRINTK("gred_dequeue: skb has bad tcindex %x\n", - tc_index_to_dp(skb)); } + return skb; } @@ -308,15 +324,19 @@ static unsigned int gred_drop(struct Qdisc* sch) skb = qdisc_dequeue_tail(sch); if (skb) { unsigned int len = skb->len; - q = t->tab[tc_index_to_dp(skb)]; - if (q) { + u16 dp = tc_index_to_dp(skb); + + if (dp >= t->DPs || (q = t->tab[dp]) == NULL) { + if (net_ratelimit()) + printk(KERN_WARNING "GRED: Unable to relocate " + "VQ 0x%x while dropping, screwing up " + "backlog.\n", tc_index_to_dp(skb)); + } else { q->backlog -= len; q->stats.other++; + if (!q->backlog && !gred_wred_mode(t)) red_start_of_idle_period(&q->parms); - } else { - D2PRINTK("gred_dequeue: skb has bad tcindex %x\n", - tc_index_to_dp(skb)); } qdisc_drop(skb, sch); -- cgit v1.2.3 From 4a591834cfc79b2ff74457e976420361f8ae28b4 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:22 +0100 Subject: [PKT_SCHED]: GRED: Remove initd flag The case when the default VQ is not set up yet is already handled in a less error prone way. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_gred.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 646dbdc4ef2..29869a07748 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -89,7 +89,6 @@ struct gred_sched unsigned long flags; u32 DPs; u32 def; - u8 initd; }; static inline int gred_wred_mode(struct gred_sched *table) @@ -166,14 +165,7 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) struct gred_sched *t= qdisc_priv(sch); unsigned long qavg = 0; int i=0; - u16 dp; - - if (!t->initd && skb_queue_len(&sch->q) < (sch->dev->tx_queue_len ? : 1)) { - D2PRINTK("NO GRED Queues setup yet! Enqueued anyway\n"); - goto do_enqueue; - } - - dp = tc_index_to_dp(skb); + u16 dp = tc_index_to_dp(skb); if (dp >= t->DPs || (q = t->tab[dp]) == NULL) { dp = t->def; @@ -241,7 +233,6 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) if (q->backlog + skb->len <= q->limit) { q->backlog += skb->len; -do_enqueue: return qdisc_enqueue_tail(skb, sch); } @@ -420,8 +411,6 @@ static inline int gred_change_table_def(struct Qdisc *sch, struct rtattr *dps) } } - table->initd = 0; - return 0; } @@ -509,8 +498,6 @@ static int gred_change(struct Qdisc *sch, struct rtattr *opt) goto errout_locked; } - table->initd = 1; - if (gred_rio_mode(table)) { gred_disable_wred_mode(table); if (gred_wred_mode_check(sch)) -- cgit v1.2.3 From 7051703b990ec40bdf192ec7c87ffafd7011c640 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:23 +0100 Subject: [PKT_SCHED]: GRED: Dont abuse default VQ for equalizing Introduces a new red parameter set for use in equalize mode, although only the qavg variable and the idle period marker are being used for now this makes it possible to allow a separate parameter set to be used for equalize later on. The use of this separate parameter set fixes a bogus start of an idle period in gred_drop() which did start an idle period on the default VQ even if equalize mode was disabled. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_gred.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 29869a07748..a545532be2c 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -89,6 +89,7 @@ struct gred_sched unsigned long flags; u32 DPs; u32 def; + struct red_parms wred_set; }; static inline int gred_wred_mode(struct gred_sched *table) @@ -158,6 +159,19 @@ static inline u16 tc_index_to_dp(struct sk_buff *skb) return skb->tc_index & GRED_VQ_MASK; } +static inline void gred_load_wred_set(struct gred_sched *table, + struct gred_sched_data *q) +{ + q->parms.qavg = table->wred_set.qavg; + q->parms.qidlestart = table->wred_set.qidlestart; +} + +static inline void gred_store_wred_set(struct gred_sched *table, + struct gred_sched_data *q) +{ + table->wred_set.qavg = q->parms.qavg; +} + static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) { @@ -204,8 +218,7 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) if (gred_wred_mode(t)) { qavg = 0; - q->parms.qavg = t->tab[t->def]->parms.qavg; - q->parms.qidlestart = t->tab[t->def]->parms.qidlestart; + gred_load_wred_set(t, q); } q->parms.qavg = red_calc_qavg(&q->parms, gred_backlog(t, q, sch)); @@ -214,7 +227,7 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) red_end_of_idle_period(&q->parms); if (gred_wred_mode(t)) - t->tab[t->def]->parms.qavg = q->parms.qavg; + gred_store_wred_set(t, q); switch (red_action(&q->parms, q->parms.qavg + qavg)) { case RED_DONT_MARK: @@ -293,14 +306,8 @@ gred_dequeue(struct Qdisc* sch) return skb; } - if (gred_wred_mode(t)) { - q= t->tab[t->def]; - if (!q) - D2PRINTK("no default VQ set: Results will be " - "screwed up\n"); - else - red_start_of_idle_period(&q->parms); - } + if (gred_wred_mode(t)) + red_start_of_idle_period(&t->wred_set); return NULL; } @@ -334,13 +341,9 @@ static unsigned int gred_drop(struct Qdisc* sch) return len; } - q=t->tab[t->def]; - if (!q) { - D2PRINTK("no default VQ set: Results might be screwed up\n"); - return 0; - } + if (gred_wred_mode(t)) + red_start_of_idle_period(&t->wred_set); - red_start_of_idle_period(&q->parms); return 0; } -- cgit v1.2.3 From 6214e653cc578947bf83d6766339a18a41c5b923 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:24 +0100 Subject: [PKT_SCHED]: GRED: Remove auto-creation of default VQ Since we are no longer depending on the default VQ to be always allocated we can leave it up to the user to actually create it. This gives the user the ability to leave it out on purpose and enqueue packets directly to the device without applying the RED algorithm. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_gred.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index a545532be2c..897e6df81b1 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -492,15 +492,6 @@ static int gred_change(struct Qdisc *sch, struct rtattr *opt) if (err < 0) goto errout_locked; - if (table->tab[table->def] == NULL) { - if (gred_rio_mode(table)) - prio = table->tab[ctl->DP]->prio; - - err = gred_change_vq(sch, table->def, ctl, prio, stab); - if (err < 0) - goto errout_locked; - } - if (gred_rio_mode(table)) { gred_disable_wred_mode(table); if (gred_wred_mode_check(sch)) -- cgit v1.2.3 From 1e4dfaf9b99a8b652e8421936fd5fe2459da8265 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:25 +0100 Subject: [PKT_SCHED]: GRED: Cleanup and remove unnecessary code Removes unnecessary includes, initializers, and simplifies the code a bit. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/pkt_sched.h | 48 ++++++++++------------ net/sched/sch_gred.c | 100 ++++++++++++++-------------------------------- 2 files changed, 53 insertions(+), 95 deletions(-) diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index 60ffcb9c579..d053add3dca 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -194,38 +194,34 @@ enum #define TCA_GRED_MAX (__TCA_GRED_MAX - 1) -#define TCA_SET_OFF TCA_GRED_PARMS struct tc_gred_qopt { - __u32 limit; /* HARD maximal queue length (bytes) -*/ - __u32 qth_min; /* Min average length threshold (bytes) -*/ - __u32 qth_max; /* Max average length threshold (bytes) -*/ - __u32 DP; /* upto 2^32 DPs */ - __u32 backlog; - __u32 qave; - __u32 forced; - __u32 early; - __u32 other; - __u32 pdrop; - - unsigned char Wlog; /* log(W) */ - unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */ - unsigned char Scell_log; /* cell size for idle damping */ - __u8 prio; /* prio of this VQ */ - __u32 packets; - __u32 bytesin; + __u32 limit; /* HARD maximal queue length (bytes) */ + __u32 qth_min; /* Min average length threshold (bytes) */ + __u32 qth_max; /* Max average length threshold (bytes) */ + __u32 DP; /* upto 2^32 DPs */ + __u32 backlog; + __u32 qave; + __u32 forced; + __u32 early; + __u32 other; + __u32 pdrop; + __u8 Wlog; /* log(W) */ + __u8 Plog; /* log(P_max/(qth_max-qth_min)) */ + __u8 Scell_log; /* cell size for idle damping */ + __u8 prio; /* prio of this VQ */ + __u32 packets; + __u32 bytesin; }; + /* gred setup */ struct tc_gred_sopt { - __u32 DPs; - __u32 def_DP; - __u8 grio; - __u8 pad1; - __u16 pad2; + __u32 DPs; + __u32 def_DP; + __u8 grio; + __u8 pad1; + __u16 pad2; }; /* HTB section */ diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 897e6df81b1..1fb34be32f7 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -15,50 +15,18 @@ * from Ren Liu * - More error checks * - * - * - * For all the glorious comments look at Alexey's sch_red.c + * For all the glorious comments look at include/net/red.h */ #include #include -#include -#include -#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include #include -#include #include #include -#if 1 /* control */ -#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) -#else -#define DPRINTK(format,args...) -#endif - -#if 0 /* data */ -#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args) -#else -#define D2PRINTK(format,args...) -#endif - #define GRED_DEF_PRIO (MAX_DPs / 2) #define GRED_VQ_MASK (MAX_DPs - 1) @@ -72,7 +40,7 @@ struct gred_sched_data u32 bytesin; /* bytes seen on virtualQ so far*/ u32 packetsin; /* packets seen on virtualQ so far*/ u32 backlog; /* bytes on the virtualQ */ - u8 prio; /* the prio of this vq */ + u8 prio; /* the prio of this vq */ struct red_parms parms; struct red_stats stats; @@ -87,8 +55,8 @@ struct gred_sched { struct gred_sched_data *tab[MAX_DPs]; unsigned long flags; - u32 DPs; - u32 def; + u32 DPs; + u32 def; struct red_parms wred_set; }; @@ -172,13 +140,11 @@ static inline void gred_store_wred_set(struct gred_sched *table, table->wred_set.qavg = q->parms.qavg; } -static int -gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) +static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) { struct gred_sched_data *q=NULL; struct gred_sched *t= qdisc_priv(sch); unsigned long qavg = 0; - int i=0; u16 dp = tc_index_to_dp(skb); if (dp >= t->DPs || (q = t->tab[dp]) == NULL) { @@ -200,26 +166,23 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) skb->tc_index = (skb->tc_index & ~GRED_VQ_MASK) | dp; } - /* sum up all the qaves of prios <= to ours to get the new qave*/ + /* sum up all the qaves of prios <= to ours to get the new qave */ if (!gred_wred_mode(t) && gred_rio_mode(t)) { - for (i=0;iDPs;i++) { - if ((!t->tab[i]) || (i==q->DP)) - continue; - - if (t->tab[i]->prio < q->prio && + int i; + + for (i = 0; i < t->DPs; i++) { + if (t->tab[i] && t->tab[i]->prio < q->prio && !red_is_idling(&t->tab[i]->parms)) qavg +=t->tab[i]->parms.qavg; } - + } q->packetsin++; - q->bytesin+=skb->len; + q->bytesin += skb->len; - if (gred_wred_mode(t)) { - qavg = 0; + if (gred_wred_mode(t)) gred_load_wred_set(t, q); - } q->parms.qavg = red_calc_qavg(&q->parms, gred_backlog(t, q, sch)); @@ -258,8 +221,7 @@ congestion_drop: return NET_XMIT_CN; } -static int -gred_requeue(struct sk_buff *skb, struct Qdisc* sch) +static int gred_requeue(struct sk_buff *skb, struct Qdisc* sch) { struct gred_sched *t = qdisc_priv(sch); struct gred_sched_data *q; @@ -279,16 +241,15 @@ gred_requeue(struct sk_buff *skb, struct Qdisc* sch) return qdisc_requeue(skb, sch); } -static struct sk_buff * -gred_dequeue(struct Qdisc* sch) +static struct sk_buff *gred_dequeue(struct Qdisc* sch) { struct sk_buff *skb; - struct gred_sched_data *q; - struct gred_sched *t= qdisc_priv(sch); + struct gred_sched *t = qdisc_priv(sch); skb = qdisc_dequeue_head(sch); if (skb) { + struct gred_sched_data *q; u16 dp = tc_index_to_dp(skb); if (dp >= t->DPs || (q = t->tab[dp]) == NULL) { @@ -315,13 +276,12 @@ gred_dequeue(struct Qdisc* sch) static unsigned int gred_drop(struct Qdisc* sch) { struct sk_buff *skb; - - struct gred_sched_data *q; - struct gred_sched *t= qdisc_priv(sch); + struct gred_sched *t = qdisc_priv(sch); skb = qdisc_dequeue_tail(sch); if (skb) { unsigned int len = skb->len; + struct gred_sched_data *q; u16 dp = tc_index_to_dp(skb); if (dp >= t->DPs || (q = t->tab[dp]) == NULL) { @@ -351,15 +311,16 @@ static unsigned int gred_drop(struct Qdisc* sch) static void gred_reset(struct Qdisc* sch) { int i; - struct gred_sched_data *q; - struct gred_sched *t= qdisc_priv(sch); + struct gred_sched *t = qdisc_priv(sch); qdisc_reset_queue(sch); - for (i=0;iDPs;i++) { - q= t->tab[i]; - if (!q) - continue; + for (i = 0; i < t->DPs; i++) { + struct gred_sched_data *q = t->tab[i]; + + if (!q) + continue; + red_restart(&q->parms); q->backlog = 0; } @@ -590,15 +551,13 @@ static void gred_destroy(struct Qdisc *sch) struct gred_sched *table = qdisc_priv(sch); int i; - for (i = 0;i < table->DPs; i++) { + for (i = 0; i < table->DPs; i++) { if (table->tab[i]) gred_destroy_vq(table->tab[i]); } } static struct Qdisc_ops gred_qdisc_ops = { - .next = NULL, - .cl_ops = NULL, .id = "gred", .priv_size = sizeof(struct gred_sched), .enqueue = gred_enqueue, @@ -617,10 +576,13 @@ static int __init gred_module_init(void) { return register_qdisc(&gred_qdisc_ops); } -static void __exit gred_module_exit(void) + +static void __exit gred_module_exit(void) { unregister_qdisc(&gred_qdisc_ops); } + module_init(gred_module_init) module_exit(gred_module_exit) + MODULE_LICENSE("GPL"); -- cgit v1.2.3 From d8f64e19605d6ce40bc560e7bc919e2e02a79c1b Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:26 +0100 Subject: [PKT_SCHED]: GRED: Fix restart of idle period in WRED mode upon dequeue and drop Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_gred.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 1fb34be32f7..69f0fd45d4c 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -267,7 +267,7 @@ static struct sk_buff *gred_dequeue(struct Qdisc* sch) return skb; } - if (gred_wred_mode(t)) + if (gred_wred_mode(t) && !red_is_idling(&t->wred_set)) red_start_of_idle_period(&t->wred_set); return NULL; @@ -301,7 +301,7 @@ static unsigned int gred_drop(struct Qdisc* sch) return len; } - if (gred_wred_mode(t)) + if (gred_wred_mode(t) && !red_is_idling(&t->wred_set)) red_start_of_idle_period(&t->wred_set); return 0; -- cgit v1.2.3 From b38c7eef7e536d12051cc3d5864032f2f907cdfe Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:27 +0100 Subject: [PKT_SCHED]: GRED: Support ECN marking Adds a new u8 flags in a unused padding area of the netlink message. Adds ECN marking support to be used instead of dropping packets immediately. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/pkt_sched.h | 4 ++-- net/sched/sch_gred.c | 25 +++++++++++++++++++++---- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index d053add3dca..0ebe320223e 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -220,8 +220,8 @@ struct tc_gred_sopt __u32 DPs; __u32 def_DP; __u8 grio; - __u8 pad1; - __u16 pad2; + __u8 flags; + __u16 pad1; }; /* HTB section */ diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 69f0fd45d4c..079b0a4ea1c 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -55,6 +55,7 @@ struct gred_sched { struct gred_sched_data *tab[MAX_DPs]; unsigned long flags; + u32 red_flags; u32 DPs; u32 def; struct red_parms wred_set; @@ -140,6 +141,11 @@ static inline void gred_store_wred_set(struct gred_sched *table, table->wred_set.qavg = q->parms.qavg; } +static inline int gred_use_ecn(struct gred_sched *t) +{ + return t->red_flags & TC_RED_ECN; +} + static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) { struct gred_sched_data *q=NULL; @@ -198,13 +204,22 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) case RED_PROB_MARK: sch->qstats.overlimits++; - q->stats.prob_drop++; - goto congestion_drop; + if (!gred_use_ecn(t) || !INET_ECN_set_ce(skb)) { + q->stats.prob_drop++; + goto congestion_drop; + } + + q->stats.prob_mark++; + break; case RED_HARD_MARK: sch->qstats.overlimits++; - q->stats.forced_drop++; - goto congestion_drop; + if (!gred_use_ecn(t) || !INET_ECN_set_ce(skb)) { + q->stats.forced_drop++; + goto congestion_drop; + } + q->stats.forced_mark++; + break; } if (q->backlog + skb->len <= q->limit) { @@ -348,6 +363,7 @@ static inline int gred_change_table_def(struct Qdisc *sch, struct rtattr *dps) sch_tree_lock(sch); table->DPs = sopt->DPs; table->def = sopt->def_DP; + table->red_flags = sopt->flags; /* * Every entry point to GRED is synchronized with the above code @@ -489,6 +505,7 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) .DPs = table->DPs, .def_DP = table->def, .grio = gred_rio_mode(table), + .flags = table->red_flags, }; opts = RTA_NEST(skb, TCA_OPTIONS); -- cgit v1.2.3 From bdc450a0bb1d48144ced1f899cc8366ec8e85024 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:28 +0100 Subject: [PKT_SCHED]: (G)RED: Introduce hard dropping Introduces a new flag TC_RED_HARDDROP which specifies that if ECN marking is enabled packets should still be dropped once the average queue length exceeds the maximum threshold. This _may_ help to avoid global synchronisation during small bursts of peers advertising but not caring about ECN. Use this option very carefully, it does more harm than good if (qth_max - qth_min) does not cover at least two average burst cycles. The difference to the current behaviour, in which we'd run into the hard queue limit, is that due to the low pass filter of RED short bursts are less likely to cause a global synchronisation. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/pkt_sched.h | 2 ++ net/sched/sch_gred.c | 8 +++++++- net/sched/sch_red.c | 8 +++++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index 0ebe320223e..e87b233615b 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -93,6 +93,7 @@ struct tc_fifo_qopt /* PRIO section */ #define TCQ_PRIO_BANDS 16 +#define TCQ_MIN_PRIO_BANDS 2 struct tc_prio_qopt { @@ -169,6 +170,7 @@ struct tc_red_qopt unsigned char Scell_log; /* cell size for idle damping */ unsigned char flags; #define TC_RED_ECN 1 +#define TC_RED_HARDDROP 2 }; struct tc_red_xstats diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 079b0a4ea1c..29a2dd9f302 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -146,6 +146,11 @@ static inline int gred_use_ecn(struct gred_sched *t) return t->red_flags & TC_RED_ECN; } +static inline int gred_use_harddrop(struct gred_sched *t) +{ + return t->red_flags & TC_RED_HARDDROP; +} + static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) { struct gred_sched_data *q=NULL; @@ -214,7 +219,8 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) case RED_HARD_MARK: sch->qstats.overlimits++; - if (!gred_use_ecn(t) || !INET_ECN_set_ce(skb)) { + if (gred_use_harddrop(t) || !gred_use_ecn(t) || + !INET_ECN_set_ce(skb)) { q->stats.forced_drop++; goto congestion_drop; } diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 0d89dee751a..dccfa44c2d7 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c @@ -51,6 +51,11 @@ static inline int red_use_ecn(struct red_sched_data *q) return q->flags & TC_RED_ECN; } +static inline int red_use_harddrop(struct red_sched_data *q) +{ + return q->flags & TC_RED_HARDDROP; +} + static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch) { struct red_sched_data *q = qdisc_priv(sch); @@ -76,7 +81,8 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch) case RED_HARD_MARK: sch->qstats.overlimits++; - if (!red_use_ecn(q) || !INET_ECN_set_ce(skb)) { + if (red_use_harddrop(q) || !red_use_ecn(q) || + !INET_ECN_set_ce(skb)) { q->stats.forced_drop++; goto congestion_drop; } -- cgit v1.2.3 From 37c12e7497b6fe2b6a890814f0ff4edce696d862 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 5 Nov 2005 21:19:33 +0000 Subject: [DRIVER MODEL] Improved dynamically allocated platform_device interface Re-jig the simple platform device support to allow private data to be attached to a platform device, as well as allowing the parent device to be set. Example usage: pdev = platform_device_alloc("mydev", id); if (pdev) { err = platform_device_add_resources(pdev, &resources, ARRAY_SIZE(resources)); if (err == 0) err = platform_device_add_data(pdev, &platform_data, sizeof(platform_data)); if (err == 0) err = platform_device_add(pdev); } else { err = -ENOMEM; } if (err) platform_device_put(pdev); Signed-off-by: Russell King Acked-by: Greg Kroah-Hartman --- drivers/base/platform.c | 153 +++++++++++++++++++++++++++++++++------- include/linux/platform_device.h | 6 ++ 2 files changed, 132 insertions(+), 27 deletions(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index d597c922af1..6d4736e89f1 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -116,12 +116,115 @@ int platform_add_devices(struct platform_device **devs, int num) return ret; } +struct platform_object { + struct platform_device pdev; + char name[1]; +}; + /** - * platform_device_register - add a platform-level device + * platform_device_put + * @pdev: platform device to free + * + * Free all memory associated with a platform device. This function + * must _only_ be externally called in error cases. All other usage + * is a bug. + */ +void platform_device_put(struct platform_device *pdev) +{ + if (pdev) + put_device(&pdev->dev); +} +EXPORT_SYMBOL_GPL(platform_device_put); + +static void platform_device_release(struct device *dev) +{ + struct platform_object *pa = container_of(dev, struct platform_object, pdev.dev); + + kfree(pa->pdev.dev.platform_data); + kfree(pa->pdev.resource); + kfree(pa); +} + +/** + * platform_device_alloc + * @name: base name of the device we're adding + * @id: instance id + * + * Create a platform device object which can have other objects attached + * to it, and which will have attached objects freed when it is released. + */ +struct platform_device *platform_device_alloc(const char *name, unsigned int id) +{ + struct platform_object *pa; + + pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL); + if (pa) { + strcpy(pa->name, name); + pa->pdev.name = pa->name; + pa->pdev.id = id; + device_initialize(&pa->pdev.dev); + pa->pdev.dev.release = platform_device_release; + } + + return pa ? &pa->pdev : NULL; +} +EXPORT_SYMBOL_GPL(platform_device_alloc); + +/** + * platform_device_add_resources + * @pdev: platform device allocated by platform_device_alloc to add resources to + * @res: set of resources that needs to be allocated for the device + * @num: number of resources + * + * Add a copy of the resources to the platform device. The memory + * associated with the resources will be freed when the platform + * device is released. + */ +int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num) +{ + struct resource *r; + + r = kmalloc(sizeof(struct resource) * num, GFP_KERNEL); + if (r) { + memcpy(r, res, sizeof(struct resource) * num); + pdev->resource = r; + pdev->num_resources = num; + } + return r ? 0 : -ENOMEM; +} +EXPORT_SYMBOL_GPL(platform_device_add_resources); + +/** + * platform_device_add_data + * @pdev: platform device allocated by platform_device_alloc to add resources to + * @data: platform specific data for this platform device + * @size: size of platform specific data + * + * Add a copy of platform specific data to the platform device's platform_data + * pointer. The memory associated with the platform data will be freed + * when the platform device is released. + */ +int platform_device_add_data(struct platform_device *pdev, void *data, size_t size) +{ + void *d; + + d = kmalloc(size, GFP_KERNEL); + if (d) { + memcpy(d, data, size); + pdev->dev.platform_data = d; + } + return d ? 0 : -ENOMEM; +} +EXPORT_SYMBOL_GPL(platform_device_add_data); + +/** + * platform_device_add - add a platform device to device hierarchy * @pdev: platform device we're adding * + * This is part 2 of platform_device_register(), though may be called + * separately _iff_ pdev was allocated by platform_device_alloc(). */ -int platform_device_register(struct platform_device * pdev) +int platform_device_add(struct platform_device *pdev) { int i, ret = 0; @@ -174,6 +277,18 @@ int platform_device_register(struct platform_device * pdev) release_resource(&pdev->resource[i]); return ret; } +EXPORT_SYMBOL_GPL(platform_device_add); + +/** + * platform_device_register - add a platform-level device + * @pdev: platform device we're adding + * + */ +int platform_device_register(struct platform_device * pdev) +{ + device_initialize(&pdev->dev); + return platform_device_add(pdev); +} /** * platform_device_unregister - remove a platform-level device @@ -197,18 +312,6 @@ void platform_device_unregister(struct platform_device * pdev) } } -struct platform_object { - struct platform_device pdev; - struct resource resources[0]; -}; - -static void platform_device_release_simple(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - - kfree(container_of(pdev, struct platform_object, pdev)); -} - /** * platform_device_register_simple * @name: base name of the device we're adding @@ -225,33 +328,29 @@ static void platform_device_release_simple(struct device *dev) struct platform_device *platform_device_register_simple(char *name, unsigned int id, struct resource *res, unsigned int num) { - struct platform_object *pobj; + struct platform_device *pdev; int retval; - pobj = kzalloc(sizeof(*pobj) + sizeof(struct resource) * num, GFP_KERNEL); - if (!pobj) { + pdev = platform_device_alloc(name, id); + if (!pdev) { retval = -ENOMEM; goto error; } - pobj->pdev.name = name; - pobj->pdev.id = id; - pobj->pdev.dev.release = platform_device_release_simple; - if (num) { - memcpy(pobj->resources, res, sizeof(struct resource) * num); - pobj->pdev.resource = pobj->resources; - pobj->pdev.num_resources = num; + retval = platform_device_add_resources(pdev, res, num); + if (retval) + goto error; } - retval = platform_device_register(&pobj->pdev); + retval = platform_device_add(pdev); if (retval) goto error; - return &pobj->pdev; + return pdev; error: - kfree(pobj); + platform_device_put(pdev); return ERR_PTR(retval); } diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index a726225e0af..1a165b7ae01 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -37,4 +37,10 @@ extern int platform_add_devices(struct platform_device **, int); extern struct platform_device *platform_device_register_simple(char *, unsigned int, struct resource *, unsigned int); +extern struct platform_device *platform_device_alloc(const char *name, unsigned int id); +extern int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num); +extern int platform_device_add_data(struct platform_device *pdev, void *data, size_t size); +extern int platform_device_add(struct platform_device *pdev); +extern void platform_device_put(struct platform_device *pdev); + #endif /* _PLATFORM_DEVICE_H_ */ -- cgit v1.2.3 From 5d994b7f5d1c77acaa0b9b4c1b9f0f278605c309 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 5 Nov 2005 21:20:21 +0000 Subject: [DRIVER MODEL] Fix depca Release code in driver modules is a potential cause of oopsen. The device may be in use by a userspace process, which will keep a reference to the device. If the module is unloaded, the module text will be freed. Subsequently, when the last reference is dropped, the release code will be called, which no longer exists. Use generic platform device allocation/release code in modules. Signed-off-by: Russell King Acked-by: Greg Kroah-Hartman --- drivers/net/depca.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/drivers/net/depca.c b/drivers/net/depca.c index 4d26e5e7d18..0d33a93df96 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -1470,15 +1470,6 @@ static int __init depca_mca_probe(struct device *device) ** ISA bus I/O device probe */ -static void depca_platform_release (struct device *device) -{ - struct platform_device *pldev; - - /* free device */ - pldev = to_platform_device (device); - kfree (pldev); -} - static void __init depca_platform_probe (void) { int i; @@ -1491,19 +1482,16 @@ static void __init depca_platform_probe (void) * line, use it (if valid) */ if (io && io != depca_io_ports[i].iobase) continue; - - if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) + + pldev = platform_device_alloc(depca_string, i); + if (!pldev) continue; - memset (pldev, 0, sizeof (*pldev)); - pldev->name = depca_string; - pldev->id = i; pldev->dev.platform_data = (void *) depca_io_ports[i].iobase; - pldev->dev.release = depca_platform_release; depca_io_ports[i].device = pldev; - if (platform_device_register (pldev)) { - kfree (pldev); + if (platform_device_add(pldev)) { + platform_device_put(pldev); depca_io_ports[i].device = NULL; continue; } @@ -1515,6 +1503,7 @@ static void __init depca_platform_probe (void) * allocated structure */ depca_io_ports[i].device = NULL; + pldev->dev.platform_data = NULL; platform_device_unregister (pldev); } } @@ -2112,6 +2101,7 @@ static void __exit depca_module_exit (void) for (i = 0; depca_io_ports[i].iobase; i++) { if (depca_io_ports[i].device) { + depca_io_ports[i].device->dev.platform_data = NULL; platform_device_unregister (depca_io_ports[i].device); depca_io_ports[i].device = NULL; } -- cgit v1.2.3 From 95cb5d954ee656a0b048ea2298188569e0759336 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 5 Nov 2005 21:20:47 +0000 Subject: [DRIVER MODEL] Fix jazzsonic Release code in driver modules is a potential cause of oopsen. The device may be in use by a userspace process, which will keep a reference to the device. If the module is unloaded, the module text will be freed. Subsequently, when the last reference is dropped, the release code will be called, which no longer exists. Use generic platform device allocation/release code in modules. Signed-off-by: Russell King Acked-by: Greg Kroah-Hartman --- drivers/net/jazzsonic.c | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c index a74a5cfaf5b..2fb3101cb33 100644 --- a/drivers/net/jazzsonic.c +++ b/drivers/net/jazzsonic.c @@ -285,18 +285,8 @@ static struct device_driver jazz_sonic_driver = { .remove = __devexit_p(jazz_sonic_device_remove), }; -static void jazz_sonic_platform_release (struct device *device) -{ - struct platform_device *pldev; - - /* free device */ - pldev = to_platform_device (device); - kfree (pldev); -} - static int __init jazz_sonic_init_module(void) { - struct platform_device *pldev; int err; if ((err = driver_register(&jazz_sonic_driver))) { @@ -304,27 +294,19 @@ static int __init jazz_sonic_init_module(void) return err; } - jazz_sonic_device = NULL; - - if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) { + jazz_sonic_device = platform_device_alloc(jazz_sonic_string, 0); + if (!jazz_sonnic_device) goto out_unregister; - } - memset(pldev, 0, sizeof (*pldev)); - pldev->name = jazz_sonic_string; - pldev->id = 0; - pldev->dev.release = jazz_sonic_platform_release; - jazz_sonic_device = pldev; - - if (platform_device_register (pldev)) { - kfree(pldev); + if (platform_device_add(jazz_sonic_device)) { + platform_device_put(jazz_sonic_device); jazz_sonic_device = NULL; } return 0; out_unregister: - platform_device_unregister(pldev); + driver_unregister(&jazz_sonic_driver); return -ENOMEM; } -- cgit v1.2.3 From 09c6518ca0de24549a923891b2d335e8496d79a9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 5 Nov 2005 21:21:10 +0000 Subject: [DRIVER MODEL] Fix macsonic Release code in driver modules is a potential cause of oopsen. The device may be in use by a userspace process, which will keep a reference to the device. If the module is unloaded, the module text will be freed. Subsequently, when the last reference is dropped, the release code will be called, which no longer exists. Use generic platform device allocation/release code in modules. Signed-off-by: Russell King Acked-by: Greg Kroah-Hartman --- drivers/net/macsonic.c | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c index e9c999d7eb3..9ef4592aca0 100644 --- a/drivers/net/macsonic.c +++ b/drivers/net/macsonic.c @@ -599,18 +599,8 @@ static struct device_driver mac_sonic_driver = { .remove = __devexit_p(mac_sonic_device_remove), }; -static void mac_sonic_platform_release(struct device *device) -{ - struct platform_device *pldev; - - /* free device */ - pldev = to_platform_device (device); - kfree (pldev); -} - static int __init mac_sonic_init_module(void) { - struct platform_device *pldev; int err; if ((err = driver_register(&mac_sonic_driver))) { @@ -618,27 +608,20 @@ static int __init mac_sonic_init_module(void) return err; } - mac_sonic_device = NULL; - - if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) { + mac_sonic_device = platform_device_alloc(mac_sonic_string, 0); + if (!mac_sonic_device) { goto out_unregister; } - memset(pldev, 0, sizeof (*pldev)); - pldev->name = mac_sonic_string; - pldev->id = 0; - pldev->dev.release = mac_sonic_platform_release; - mac_sonic_device = pldev; - - if (platform_device_register (pldev)) { - kfree(pldev); + if (platform_device_add(mac_sonic_device)) { + platform_device_put(mac_sonic_device); mac_sonic_device = NULL; } return 0; out_unregister: - platform_device_unregister(pldev); + driver_unregister(&mac_sonic_driver); return -ENOMEM; } -- cgit v1.2.3 From 8d972a962177a261fc894f767fa3014f63d661e9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 5 Nov 2005 21:21:38 +0000 Subject: [DRIVER MODEL] Fix arcfb Release code in driver modules is a potential cause of oopsen. The device may be in use by a userspace process, which will keep a reference to the device. If the module is unloaded, the module text will be freed. Subsequently, when the last reference is dropped, the release code will be called, which no longer exists. Use generic platform device allocation/release code in modules. Signed-off-by: Russell King Acked-by: Greg Kroah-Hartman --- drivers/video/arcfb.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c index 126daff1c84..6aa9f824c18 100644 --- a/drivers/video/arcfb.c +++ b/drivers/video/arcfb.c @@ -502,10 +502,6 @@ static ssize_t arcfb_write(struct file *file, const char *buf, size_t count, return err; } -static void arcfb_platform_release(struct device *device) -{ -} - static struct fb_ops arcfb_ops = { .owner = THIS_MODULE, .fb_open = arcfb_open, @@ -624,13 +620,7 @@ static struct device_driver arcfb_driver = { .remove = arcfb_remove, }; -static struct platform_device arcfb_device = { - .name = "arcfb", - .id = 0, - .dev = { - .release = arcfb_platform_release, - } -}; +static struct platform_device *arcfb_device; static int __init arcfb_init(void) { @@ -641,9 +631,16 @@ static int __init arcfb_init(void) ret = driver_register(&arcfb_driver); if (!ret) { - ret = platform_device_register(&arcfb_device); - if (ret) + arcfb_device = platform_device_alloc("arcfb", 0); + if (arcfb_device) { + ret = platform_device_add(arcfb_device); + } else { + ret = -ENOMEM; + } + if (ret) { + platform_device_put(arcfb_device); driver_unregister(&arcfb_driver); + } } return ret; @@ -651,7 +648,7 @@ static int __init arcfb_init(void) static void __exit arcfb_exit(void) { - platform_device_unregister(&arcfb_device); + platform_device_unregister(arcfb_device); driver_unregister(&arcfb_driver); } -- cgit v1.2.3 From abbf268ae8f51e19779cdf3f5fbb8144f1a5fbc3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 5 Nov 2005 21:22:13 +0000 Subject: [DRIVER MODEL] Fix gbefb Statically allocated devices in module data is a potential cause of oopsen. The device may be in use by a userspace process, which will keep a reference to the device. If the module is unloaded, the module data will be freed. Subsequent use of the platform device will cause a kernel oops. Use generic platform device allocation/release code in modules. Signed-off-by: Russell King Acked-by: Greg Kroah-Hartman --- drivers/video/gbefb.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index 316bfe99481..ed853bef19e 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c @@ -1260,24 +1260,30 @@ static struct device_driver gbefb_driver = { .remove = __devexit_p(gbefb_remove), }; -static struct platform_device gbefb_device = { - .name = "gbefb", -}; +static struct platform_device *gbefb_device; int __init gbefb_init(void) { int ret = driver_register(&gbefb_driver); if (!ret) { - ret = platform_device_register(&gbefb_device); - if (ret) + gbefb_device = platform_device_alloc("gbefb", 0); + if (gbefb_device) { + ret = platform_device_add(gbefb_device); + } else { + ret = -ENOMEM; + } + if (ret) { + platform_device_put(gbefb_device); driver_unregister(&gbefb_driver); + } } return ret; } void __exit gbefb_exit(void) { - driver_unregister(&gbefb_driver); + platform_device_unregister(gbefb_device); + driver_unregister(&gbefb_driver); } module_init(gbefb_init); -- cgit v1.2.3 From 2c119aa8091a15a87920f09aa0f17e05960fe11b Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 5 Nov 2005 21:22:39 +0000 Subject: [DRIVER MODEL] Fix sgivwfb Statically allocated devices in module data is a potential cause of oopsen. The device may be in use by a userspace process, which will keep a reference to the device. If the module is unloaded, the module data will be freed. Subsequent use of the platform device will cause a kernel oops. Use generic platform device allocation/release code in modules. Signed-off-by: Russell King Acked-by: Greg Kroah-Hartman --- drivers/video/sgivwfb.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c index cf5106eab2d..5ce81f44c76 100644 --- a/drivers/video/sgivwfb.c +++ b/drivers/video/sgivwfb.c @@ -751,10 +751,6 @@ int __init sgivwfb_setup(char *options) /* * Initialisation */ -static void sgivwfb_release(struct device *device) -{ -} - static int __init sgivwfb_probe(struct device *device) { struct platform_device *dev = to_platform_device(device); @@ -859,13 +855,7 @@ static struct device_driver sgivwfb_driver = { .remove = sgivwfb_remove, }; -static struct platform_device sgivwfb_device = { - .name = "sgivwfb", - .id = 0, - .dev = { - .release = sgivwfb_release, - } -}; +static struct platform_device *sgivwfb_device; int __init sgivwfb_init(void) { @@ -880,9 +870,15 @@ int __init sgivwfb_init(void) #endif ret = driver_register(&sgivwfb_driver); if (!ret) { - ret = platform_device_register(&sgivwfb_device); - if (ret) + sgivwfb_device = platform_device_alloc("sgivwfb", 0); + if (sgivwfb_device) { + ret = platform_device_add(sgivwfb_device); + } else + ret = -ENOMEM; + if (ret) { driver_unregister(&sgivwfb_driver); + platform_device_put(sgivwfb_device); + } } return ret; } @@ -894,7 +890,7 @@ MODULE_LICENSE("GPL"); static void __exit sgivwfb_exit(void) { - platform_device_unregister(&sgivwfb_device); + platform_device_unregister(sgivwfb_device); driver_unregister(&sgivwfb_driver); } -- cgit v1.2.3 From 88dcb6c4113afe93a6c4891ec43bef6a17c83155 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 5 Nov 2005 22:19:50 +0100 Subject: [PATCH] Set the vga cursor even when hidden Some visually impaired people use hardware devices which directly read the vga screen. When newt for instance asks to hide the cursor for better visual aspect, the kernel puts the vga cursor out of the screen, so that the cursor position can't be read by the hardware device. This is a great loss for such people. Here is a patch which uses the same technique as CUR_NONE for hiding the cursor while still moving it. Mario, you should apply it to the speakup kernel for access floppies asap. I'll submit a 2.4 patch too. Signed-off-by: samuel.thibault@ens-lyon.org Signed-off-by: Linus Torvalds --- drivers/video/console/vgacon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 56cd199605f..274f90543e3 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -448,7 +448,8 @@ static void vgacon_cursor(struct vc_data *c, int mode) vgacon_scrolldelta(c, 0); switch (mode) { case CM_ERASE: - write_vga(14, (vga_vram_end - vga_vram_base - 1) / 2); + write_vga(14, (c->vc_pos - vga_vram_base) / 2); + vgacon_set_cursor_size(c->vc_x, 31, 30); break; case CM_MOVE: -- cgit v1.2.3 From 300ce174ebc2fcf2b5111a50fa42f79d891927dd Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 30 Oct 2005 13:47:34 -0800 Subject: [NETEM]: Support time based reordering Change netem to support packets getting reordered because of variations in delay. Introduce a special case version of FIFO that queues packets in order based on the netem delay. Since netem is classful, those users that don't want jitter based reordering can just insert a pfifo instead of the default. This required changes to generic skbuff code to allow finer grain manipulation of sk_buff_head. Insertion into the middle and reverse walk. Signed-off-by: Stephen Hemminger Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/skbuff.h | 38 +++++++++++++++++----- net/sched/sch_netem.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 114 insertions(+), 9 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 4286d832166..fdfb8fe8c38 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -603,29 +603,46 @@ static inline void skb_queue_head_init(struct sk_buff_head *list) */ /** - * __skb_queue_head - queue a buffer at the list head + * __skb_queue_after - queue a buffer at the list head * @list: list to use + * @prev: place after this buffer * @newsk: buffer to queue * - * Queue a buffer at the start of a list. This function takes no locks + * Queue a buffer int the middle of a list. This function takes no locks * and you must therefore hold required locks before calling it. * * A buffer cannot be placed on two lists at the same time. */ -extern void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk); -static inline void __skb_queue_head(struct sk_buff_head *list, - struct sk_buff *newsk) +static inline void __skb_queue_after(struct sk_buff_head *list, + struct sk_buff *prev, + struct sk_buff *newsk) { - struct sk_buff *prev, *next; - + struct sk_buff *next; list->qlen++; - prev = (struct sk_buff *)list; + next = prev->next; newsk->next = next; newsk->prev = prev; next->prev = prev->next = newsk; } +/** + * __skb_queue_head - queue a buffer at the list head + * @list: list to use + * @newsk: buffer to queue + * + * Queue a buffer at the start of a list. This function takes no locks + * and you must therefore hold required locks before calling it. + * + * A buffer cannot be placed on two lists at the same time. + */ +extern void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk); +static inline void __skb_queue_head(struct sk_buff_head *list, + struct sk_buff *newsk) +{ + __skb_queue_after(list, (struct sk_buff *)list, newsk); +} + /** * __skb_queue_tail - queue a buffer at the list tail * @list: list to use @@ -1203,6 +1220,11 @@ static inline void kunmap_skb_frag(void *vaddr) prefetch(skb->next), (skb != (struct sk_buff *)(queue)); \ skb = skb->next) +#define skb_queue_reverse_walk(queue, skb) \ + for (skb = (queue)->prev; \ + prefetch(skb->prev), (skb != (struct sk_buff *)(queue)); \ + skb = skb->prev) + extern struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock, int *err); diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index d871fe7f81a..7c10ef3457d 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -300,11 +300,16 @@ static void netem_reset(struct Qdisc *sch) del_timer_sync(&q->timer); } +/* Pass size change message down to embedded FIFO */ static int set_fifo_limit(struct Qdisc *q, int limit) { struct rtattr *rta; int ret = -ENOMEM; + /* Hack to avoid sending change message to non-FIFO */ + if (strncmp(q->ops->id + 1, "fifo", 4) != 0) + return 0; + rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL); if (rta) { rta->rta_type = RTM_NEWQDISC; @@ -436,6 +441,84 @@ static int netem_change(struct Qdisc *sch, struct rtattr *opt) return 0; } +/* + * Special case version of FIFO queue for use by netem. + * It queues in order based on timestamps in skb's + */ +struct fifo_sched_data { + u32 limit; +}; + +static int tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) +{ + struct fifo_sched_data *q = qdisc_priv(sch); + struct sk_buff_head *list = &sch->q; + const struct netem_skb_cb *ncb + = (const struct netem_skb_cb *)nskb->cb; + struct sk_buff *skb; + + if (likely(skb_queue_len(list) < q->limit)) { + skb_queue_reverse_walk(list, skb) { + const struct netem_skb_cb *cb + = (const struct netem_skb_cb *)skb->cb; + + if (PSCHED_TLESS(cb->time_to_send, ncb->time_to_send)) + break; + } + + __skb_queue_after(list, skb, nskb); + + sch->qstats.backlog += nskb->len; + sch->bstats.bytes += nskb->len; + sch->bstats.packets++; + + return NET_XMIT_SUCCESS; + } + + return qdisc_drop(nskb, sch); +} + +static int tfifo_init(struct Qdisc *sch, struct rtattr *opt) +{ + struct fifo_sched_data *q = qdisc_priv(sch); + + if (opt) { + struct tc_fifo_qopt *ctl = RTA_DATA(opt); + if (RTA_PAYLOAD(opt) < sizeof(*ctl)) + return -EINVAL; + + q->limit = ctl->limit; + } else + q->limit = max_t(u32, sch->dev->tx_queue_len, 1); + + return 0; +} + +static int tfifo_dump(struct Qdisc *sch, struct sk_buff *skb) +{ + struct fifo_sched_data *q = qdisc_priv(sch); + struct tc_fifo_qopt opt = { .limit = q->limit }; + + RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); + return skb->len; + +rtattr_failure: + return -1; +} + +static struct Qdisc_ops tfifo_qdisc_ops = { + .id = "tfifo", + .priv_size = sizeof(struct fifo_sched_data), + .enqueue = tfifo_enqueue, + .dequeue = qdisc_dequeue_head, + .requeue = qdisc_requeue, + .drop = qdisc_queue_drop, + .init = tfifo_init, + .reset = qdisc_reset_queue, + .change = tfifo_init, + .dump = tfifo_dump, +}; + static int netem_init(struct Qdisc *sch, struct rtattr *opt) { struct netem_sched_data *q = qdisc_priv(sch); @@ -448,7 +531,7 @@ static int netem_init(struct Qdisc *sch, struct rtattr *opt) q->timer.function = netem_watchdog; q->timer.data = (unsigned long) sch; - q->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); + q->qdisc = qdisc_create_dflt(sch->dev, &tfifo_qdisc_ops); if (!q->qdisc) { pr_debug("netem: qdisc create failed\n"); return -ENOMEM; -- cgit v1.2.3 From eb229c4cdc3389682cda20adb015ba767950a220 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 3 Nov 2005 13:49:01 -0800 Subject: [NETEM]: Add version string Add a version string to help support issues. Signed-off-by: Stephen Hemminger Signed-off-by: Arnaldo Carvalho de Melo --- net/sched/sch_netem.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 7c10ef3457d..cdc8d283791 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -25,6 +25,8 @@ #include +#define VERSION "1.1" + /* Network Emulation Queuing algorithm. ==================================== @@ -694,6 +696,7 @@ static struct Qdisc_ops netem_qdisc_ops = { static int __init netem_module_init(void) { + pr_info("netem: version " VERSION "\n"); return register_qdisc(&netem_qdisc_ops); } static void __exit netem_module_exit(void) -- cgit v1.2.3 From 6151b31c9616d71f714fc7ef8e2306f67f3b94c3 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 4 Nov 2005 09:56:56 +1100 Subject: [NET]: Fix race condition in sk_stream_wait_connect When sk_stream_wait_connect detects a state transition to ESTABLISHED or CLOSE_WAIT prior to it going to sleep, it will return without calling finish_wait and decrementing sk_write_pending. This may result in crashes and other unintended behaviour. The fix is to always call finish_wait and update sk_write_pending since it is safe to do so even if the wait entry is no longer on the queue. This bug was tracked down with the help of Alex Sidorenko and the fix is also based on his suggestion. Signed-off-by: Herbert Xu Signed-off-by: Arnaldo Carvalho de Melo --- net/core/stream.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/net/core/stream.c b/net/core/stream.c index ac9edfdf874..15bfd03e802 100644 --- a/net/core/stream.c +++ b/net/core/stream.c @@ -52,8 +52,9 @@ int sk_stream_wait_connect(struct sock *sk, long *timeo_p) { struct task_struct *tsk = current; DEFINE_WAIT(wait); + int done; - while (1) { + do { if (sk->sk_err) return sock_error(sk); if ((1 << sk->sk_state) & ~(TCPF_SYN_SENT | TCPF_SYN_RECV)) @@ -65,13 +66,12 @@ int sk_stream_wait_connect(struct sock *sk, long *timeo_p) prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); sk->sk_write_pending++; - if (sk_wait_event(sk, timeo_p, - !((1 << sk->sk_state) & - ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)))) - break; + done = sk_wait_event(sk, timeo_p, + !((1 << sk->sk_state) & + ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT))); finish_wait(sk->sk_sleep, &wait); sk->sk_write_pending--; - } + } while (!done); return 0; } -- cgit v1.2.3 From 6df716340da3a6fdd33d73d7ed4c6f7590ca1c42 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 3 Nov 2005 16:33:23 -0800 Subject: [TCP/DCCP]: Randomize port selection This patch randomizes the port selected on bind() for connections to help with possible security attacks. It should also be faster in most cases because there is no need for a global lock. Signed-off-by: Stephen Hemminger Signed-off-by: Arnaldo Carvalho de Melo --- include/net/inet_hashtables.h | 2 -- net/dccp/ipv4.c | 32 +++----------------------------- net/ipv4/inet_connection_sock.c | 14 +++----------- net/ipv4/tcp.c | 1 - net/ipv4/tcp_ipv4.c | 2 -- net/ipv6/tcp_ipv6.c | 15 ++++----------- 6 files changed, 10 insertions(+), 56 deletions(-) diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index f50f9596834..07840baa934 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h @@ -125,9 +125,7 @@ struct inet_hashinfo { rwlock_t lhash_lock ____cacheline_aligned; atomic_t lhash_users; wait_queue_head_t lhash_wait; - spinlock_t portalloc_lock; kmem_cache_t *bind_bucket_cachep; - int port_rover; }; static inline unsigned int inet_ehashfn(const __u32 laddr, const __u16 lport, diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 6298cf58ff9..4b9bc81ae1a 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -31,8 +31,6 @@ struct inet_hashinfo __cacheline_aligned dccp_hashinfo = { .lhash_lock = RW_LOCK_UNLOCKED, .lhash_users = ATOMIC_INIT(0), .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(dccp_hashinfo.lhash_wait), - .portalloc_lock = SPIN_LOCK_UNLOCKED, - .port_rover = 1024 - 1, }; EXPORT_SYMBOL_GPL(dccp_hashinfo); @@ -125,36 +123,15 @@ static int dccp_v4_hash_connect(struct sock *sk) int ret; if (snum == 0) { - int rover; int low = sysctl_local_port_range[0]; int high = sysctl_local_port_range[1]; int remaining = (high - low) + 1; + int rover = net_random() % (high - low) + low; struct hlist_node *node; struct inet_timewait_sock *tw = NULL; local_bh_disable(); - - /* TODO. Actually it is not so bad idea to remove - * dccp_hashinfo.portalloc_lock before next submission to - * Linus. - * As soon as we touch this place at all it is time to think. - * - * Now it protects single _advisory_ variable - * dccp_hashinfo.port_rover, hence it is mostly useless. - * Code will work nicely if we just delete it, but - * I am afraid in contented case it will work not better or - * even worse: another cpu just will hit the same bucket - * and spin there. - * So some cpu salt could remove both contention and - * memory pingpong. Any ideas how to do this in a nice way? - */ - spin_lock(&dccp_hashinfo.portalloc_lock); - rover = dccp_hashinfo.port_rover; - do { - rover++; - if ((rover < low) || (rover > high)) - rover = low; head = &dccp_hashinfo.bhash[inet_bhashfn(rover, dccp_hashinfo.bhash_size)]; spin_lock(&head->lock); @@ -187,9 +164,9 @@ static int dccp_v4_hash_connect(struct sock *sk) next_port: spin_unlock(&head->lock); + if (++rover > high) + rover = low; } while (--remaining > 0); - dccp_hashinfo.port_rover = rover; - spin_unlock(&dccp_hashinfo.portalloc_lock); local_bh_enable(); @@ -197,9 +174,6 @@ static int dccp_v4_hash_connect(struct sock *sk) ok: /* All locks still held and bhs disabled */ - dccp_hashinfo.port_rover = rover; - spin_unlock(&dccp_hashinfo.portalloc_lock); - inet_bind_hash(sk, tb, rover); if (sk_unhashed(sk)) { inet_sk(sk)->sport = htons(rover); diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 94468a76c5b..3fe021f1a56 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -78,17 +78,9 @@ int inet_csk_get_port(struct inet_hashinfo *hashinfo, int low = sysctl_local_port_range[0]; int high = sysctl_local_port_range[1]; int remaining = (high - low) + 1; - int rover; + int rover = net_random() % (high - low) + low; - spin_lock(&hashinfo->portalloc_lock); - if (hashinfo->port_rover < low) - rover = low; - else - rover = hashinfo->port_rover; do { - rover++; - if (rover > high) - rover = low; head = &hashinfo->bhash[inet_bhashfn(rover, hashinfo->bhash_size)]; spin_lock(&head->lock); inet_bind_bucket_for_each(tb, node, &head->chain) @@ -97,9 +89,9 @@ int inet_csk_get_port(struct inet_hashinfo *hashinfo, break; next: spin_unlock(&head->lock); + if (++rover > high) + rover = low; } while (--remaining > 0); - hashinfo->port_rover = rover; - spin_unlock(&hashinfo->portalloc_lock); /* Exhausted local port range during search? It is not * possible for us to be holding one of the bind hash diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index f3f0013a958..72b7c22e1ea 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2112,7 +2112,6 @@ void __init tcp_init(void) sysctl_tcp_max_orphans >>= (3 - order); sysctl_max_syn_backlog = 128; } - tcp_hashinfo.port_rover = sysctl_local_port_range[0] - 1; sysctl_tcp_mem[0] = 768 << order; sysctl_tcp_mem[1] = 1024 << order; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index c85819d8474..49d67cd75ed 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -93,8 +93,6 @@ struct inet_hashinfo __cacheline_aligned tcp_hashinfo = { .lhash_lock = RW_LOCK_UNLOCKED, .lhash_users = ATOMIC_INIT(0), .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait), - .portalloc_lock = SPIN_LOCK_UNLOCKED, - .port_rover = 1024 - 1, }; static int tcp_v4_get_port(struct sock *sk, unsigned short snum) diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index d693cb988b7..d746d3b27ef 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -114,16 +114,9 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum) int low = sysctl_local_port_range[0]; int high = sysctl_local_port_range[1]; int remaining = (high - low) + 1; - int rover; + int rover = net_random() % (high - low) + low; - spin_lock(&tcp_hashinfo.portalloc_lock); - if (tcp_hashinfo.port_rover < low) - rover = low; - else - rover = tcp_hashinfo.port_rover; - do { rover++; - if (rover > high) - rover = low; + do { head = &tcp_hashinfo.bhash[inet_bhashfn(rover, tcp_hashinfo.bhash_size)]; spin_lock(&head->lock); inet_bind_bucket_for_each(tb, node, &head->chain) @@ -132,9 +125,9 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum) break; next: spin_unlock(&head->lock); + if (++rover > high) + rover = low; } while (--remaining > 0); - tcp_hashinfo.port_rover = rover; - spin_unlock(&tcp_hashinfo.portalloc_lock); /* Exhausted local port range during search? It is not * possible for us to be holding one of the bind hash -- cgit v1.2.3 From f912696ab330bf539231d1f8032320f2a08b850f Mon Sep 17 00:00:00 2001 From: Bart Oldeman Date: Sun, 6 Nov 2005 12:54:07 +1300 Subject: [PATCH] reset tss->io_bitmap_owner in sys_ioperm() my patch "x86: initialise tss->io_bitmap_owner to something" (commit ID d5cd4aadd3d220afac8e3e6d922e333592551f7d) introduced a problem with a program (DOSEMU) that called ioperm after already doing some port i/o. The problem is that a process switch return causes tss->io_bitmap_base to be set to IO_BITMAP_OFFSET so that the fault (that *really* sets the io bitmap) never triggers. This fixes that regression. Signed-off-by: Bart Oldeman Signed-off-by: Linus Torvalds --- arch/i386/kernel/ioport.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/i386/kernel/ioport.c b/arch/i386/kernel/ioport.c index f2b37654777..b59a34dbe26 100644 --- a/arch/i386/kernel/ioport.c +++ b/arch/i386/kernel/ioport.c @@ -108,8 +108,11 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) /* * Sets the lazy trigger so that the next I/O operation will * reload the correct bitmap. + * Reset the owner so that a process switch will not set + * tss->io_bitmap_base to IO_BITMAP_OFFSET. */ tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY; + tss->io_bitmap_owner = NULL; put_cpu(); -- cgit v1.2.3 From e9ab1d145365a871858f402f3655cd4939fa38d5 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 30 Oct 2005 16:53:30 +0100 Subject: [PATCH] drivers/net/ixgb/: make some code static This patch makes some needlessly global code static. Signed-off-by: Adrian Bunk Signed-off-by: John W. Linville --- drivers/net/ixgb/ixgb_ethtool.c | 2 +- drivers/net/ixgb/ixgb_hw.c | 31 ++++++++++++++++++++++--------- drivers/net/ixgb/ixgb_hw.h | 17 ----------------- drivers/net/ixgb/ixgb_main.c | 2 +- 4 files changed, 24 insertions(+), 28 deletions(-) diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c index 04e47189d83..d38ade5f2f4 100644 --- a/drivers/net/ixgb/ixgb_ethtool.c +++ b/drivers/net/ixgb/ixgb_ethtool.c @@ -694,7 +694,7 @@ ixgb_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data) } } -struct ethtool_ops ixgb_ethtool_ops = { +static struct ethtool_ops ixgb_ethtool_ops = { .get_settings = ixgb_get_settings, .set_settings = ixgb_set_settings, .get_drvinfo = ixgb_get_drvinfo, diff --git a/drivers/net/ixgb/ixgb_hw.c b/drivers/net/ixgb/ixgb_hw.c index 69329c73095..620cad48bde 100644 --- a/drivers/net/ixgb/ixgb_hw.c +++ b/drivers/net/ixgb/ixgb_hw.c @@ -47,9 +47,22 @@ static void ixgb_optics_reset(struct ixgb_hw *hw); static ixgb_phy_type ixgb_identify_phy(struct ixgb_hw *hw); -uint32_t ixgb_mac_reset(struct ixgb_hw *hw); +static void ixgb_clear_hw_cntrs(struct ixgb_hw *hw); -uint32_t ixgb_mac_reset(struct ixgb_hw *hw) +static void ixgb_clear_vfta(struct ixgb_hw *hw); + +static void ixgb_init_rx_addrs(struct ixgb_hw *hw); + +static uint16_t ixgb_read_phy_reg(struct ixgb_hw *hw, + uint32_t reg_address, + uint32_t phy_address, + uint32_t device_type); + +static boolean_t ixgb_setup_fc(struct ixgb_hw *hw); + +static boolean_t mac_addr_valid(uint8_t *mac_addr); + +static uint32_t ixgb_mac_reset(struct ixgb_hw *hw) { uint32_t ctrl_reg; @@ -335,7 +348,7 @@ ixgb_init_hw(struct ixgb_hw *hw) * of the receive addresss registers. Clears the multicast table. Assumes * the receiver is in reset when the routine is called. *****************************************************************************/ -void +static void ixgb_init_rx_addrs(struct ixgb_hw *hw) { uint32_t i; @@ -604,7 +617,7 @@ ixgb_write_vfta(struct ixgb_hw *hw, * * hw - Struct containing variables accessed by shared code *****************************************************************************/ -void +static void ixgb_clear_vfta(struct ixgb_hw *hw) { uint32_t offset; @@ -620,7 +633,7 @@ ixgb_clear_vfta(struct ixgb_hw *hw) * hw - Struct containing variables accessed by shared code *****************************************************************************/ -boolean_t +static boolean_t ixgb_setup_fc(struct ixgb_hw *hw) { uint32_t ctrl_reg; @@ -722,7 +735,7 @@ ixgb_setup_fc(struct ixgb_hw *hw) * This requires that first an address cycle command is sent, followed by a * read command. *****************************************************************************/ -uint16_t +static uint16_t ixgb_read_phy_reg(struct ixgb_hw *hw, uint32_t reg_address, uint32_t phy_address, @@ -815,7 +828,7 @@ ixgb_read_phy_reg(struct ixgb_hw *hw, * This requires that first an address cycle command is sent, followed by a * write command. *****************************************************************************/ -void +static void ixgb_write_phy_reg(struct ixgb_hw *hw, uint32_t reg_address, uint32_t phy_address, @@ -959,7 +972,7 @@ boolean_t ixgb_check_for_bad_link(struct ixgb_hw *hw) * * hw - Struct containing variables accessed by shared code *****************************************************************************/ -void +static void ixgb_clear_hw_cntrs(struct ixgb_hw *hw) { volatile uint32_t temp_reg; @@ -1114,7 +1127,7 @@ ixgb_get_bus_info(struct ixgb_hw *hw) * mac_addr - pointer to MAC address. * *****************************************************************************/ -boolean_t +static boolean_t mac_addr_valid(uint8_t *mac_addr) { boolean_t is_valid = TRUE; diff --git a/drivers/net/ixgb/ixgb_hw.h b/drivers/net/ixgb/ixgb_hw.h index 8bcf31ed10c..382c6300ccc 100644 --- a/drivers/net/ixgb/ixgb_hw.h +++ b/drivers/net/ixgb/ixgb_hw.h @@ -784,23 +784,8 @@ struct ixgb_hw_stats { extern boolean_t ixgb_adapter_stop(struct ixgb_hw *hw); extern boolean_t ixgb_init_hw(struct ixgb_hw *hw); extern boolean_t ixgb_adapter_start(struct ixgb_hw *hw); -extern void ixgb_init_rx_addrs(struct ixgb_hw *hw); extern void ixgb_check_for_link(struct ixgb_hw *hw); extern boolean_t ixgb_check_for_bad_link(struct ixgb_hw *hw); -extern boolean_t ixgb_setup_fc(struct ixgb_hw *hw); -extern void ixgb_clear_hw_cntrs(struct ixgb_hw *hw); -extern boolean_t mac_addr_valid(uint8_t *mac_addr); - -extern uint16_t ixgb_read_phy_reg(struct ixgb_hw *hw, - uint32_t reg_addr, - uint32_t phy_addr, - uint32_t device_type); - -extern void ixgb_write_phy_reg(struct ixgb_hw *hw, - uint32_t reg_addr, - uint32_t phy_addr, - uint32_t device_type, - uint16_t data); extern void ixgb_rar_set(struct ixgb_hw *hw, uint8_t *addr, @@ -818,8 +803,6 @@ extern void ixgb_write_vfta(struct ixgb_hw *hw, uint32_t offset, uint32_t value); -extern void ixgb_clear_vfta(struct ixgb_hw *hw); - /* Access functions to eeprom data */ void ixgb_get_ee_mac_addr(struct ixgb_hw *hw, uint8_t *mac_addr); uint32_t ixgb_get_ee_pba_number(struct ixgb_hw *hw); diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 176680cb153..f9f77e4f596 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -45,7 +45,7 @@ */ char ixgb_driver_name[] = "ixgb"; -char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver"; +static char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver"; #ifndef CONFIG_IXGB_NAPI #define DRIVERNAPI -- cgit v1.2.3 From 3ad2cc6798be9388c9a3f1e6180e77690303eb01 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 30 Oct 2005 16:53:34 +0100 Subject: [PATCH] drivers/net/e1000/: possible cleanups This patch contains the following possible cleanups: - make needlessly global code static - #if 0 the following unused global functions: - e1000_hw.c: e1000_mc_addr_list_update - e1000_hw.c: e1000_read_reg_io - e1000_hw.c: e1000_enable_pciex_master Signed-off-by: Adrian Bunk Signed-off-by: John W. Linville --- drivers/net/e1000/e1000_ethtool.c | 2 +- drivers/net/e1000/e1000_hw.c | 101 ++++++++++++++++++++++++++------------ drivers/net/e1000/e1000_hw.h | 42 ---------------- drivers/net/e1000/e1000_main.c | 31 ++++++------ 4 files changed, 87 insertions(+), 89 deletions(-) diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 9c7feaeaa6a..8eae8ba27e8 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -1739,7 +1739,7 @@ e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data) } } -struct ethtool_ops e1000_ethtool_ops = { +static struct ethtool_ops e1000_ethtool_ops = { .get_settings = e1000_get_settings, .set_settings = e1000_set_settings, .get_drvinfo = e1000_get_drvinfo, diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 8fc876da43b..a267c5235fc 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -68,6 +68,38 @@ static int32_t e1000_polarity_reversal_workaround(struct e1000_hw *hw); static int32_t e1000_set_phy_mode(struct e1000_hw *hw); static int32_t e1000_host_if_read_cookie(struct e1000_hw *hw, uint8_t *buffer); static uint8_t e1000_calculate_mng_checksum(char *buffer, uint32_t length); +static uint8_t e1000_arc_subsystem_valid(struct e1000_hw *hw); +static int32_t e1000_check_downshift(struct e1000_hw *hw); +static int32_t e1000_check_polarity(struct e1000_hw *hw, uint16_t *polarity); +static void e1000_clear_hw_cntrs(struct e1000_hw *hw); +static void e1000_clear_vfta(struct e1000_hw *hw); +static int32_t e1000_commit_shadow_ram(struct e1000_hw *hw); +static int32_t e1000_config_dsp_after_link_change(struct e1000_hw *hw, + boolean_t link_up); +static int32_t e1000_config_fc_after_link_up(struct e1000_hw *hw); +static int32_t e1000_detect_gig_phy(struct e1000_hw *hw); +static int32_t e1000_get_auto_rd_done(struct e1000_hw *hw); +static int32_t e1000_get_cable_length(struct e1000_hw *hw, + uint16_t *min_length, + uint16_t *max_length); +static int32_t e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw); +static int32_t e1000_get_phy_cfg_done(struct e1000_hw *hw); +static int32_t e1000_id_led_init(struct e1000_hw * hw); +static void e1000_init_rx_addrs(struct e1000_hw *hw); +static boolean_t e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw); +static int32_t e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd); +static void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw); +static int32_t e1000_read_eeprom_eerd(struct e1000_hw *hw, uint16_t offset, + uint16_t words, uint16_t *data); +static int32_t e1000_set_d0_lplu_state(struct e1000_hw *hw, boolean_t active); +static int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active); +static int32_t e1000_wait_autoneg(struct e1000_hw *hw); + +static void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, + uint32_t value); + +#define E1000_WRITE_REG_IO(a, reg, val) \ + e1000_write_reg_io((a), E1000_##reg, val) /* IGP cable length table */ static const @@ -2035,7 +2067,7 @@ e1000_force_mac_fc(struct e1000_hw *hw) * based on the flow control negotiated by the PHY. In TBI mode, the TFCE * and RFCE bits will be automaticaly set to the negotiated flow control mode. *****************************************************************************/ -int32_t +static int32_t e1000_config_fc_after_link_up(struct e1000_hw *hw) { int32_t ret_val; @@ -2537,7 +2569,7 @@ e1000_get_speed_and_duplex(struct e1000_hw *hw, * * hw - Struct containing variables accessed by shared code ******************************************************************************/ -int32_t +static int32_t e1000_wait_autoneg(struct e1000_hw *hw) { int32_t ret_val; @@ -3021,7 +3053,7 @@ e1000_phy_reset(struct e1000_hw *hw) * * hw - Struct containing variables accessed by shared code ******************************************************************************/ -int32_t +static int32_t e1000_detect_gig_phy(struct e1000_hw *hw) { int32_t phy_init_status, ret_val; @@ -3121,7 +3153,7 @@ e1000_phy_reset_dsp(struct e1000_hw *hw) * hw - Struct containing variables accessed by shared code * phy_info - PHY information structure ******************************************************************************/ -int32_t +static int32_t e1000_phy_igp_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info) { @@ -3195,7 +3227,7 @@ e1000_phy_igp_get_info(struct e1000_hw *hw, * hw - Struct containing variables accessed by shared code * phy_info - PHY information structure ******************************************************************************/ -int32_t +static int32_t e1000_phy_m88_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info) { @@ -3905,7 +3937,7 @@ e1000_read_eeprom(struct e1000_hw *hw, * data - word read from the EEPROM * words - number of words to read *****************************************************************************/ -int32_t +static int32_t e1000_read_eeprom_eerd(struct e1000_hw *hw, uint16_t offset, uint16_t words, @@ -3939,7 +3971,7 @@ e1000_read_eeprom_eerd(struct e1000_hw *hw, * data - word read from the EEPROM * words - number of words to read *****************************************************************************/ -int32_t +static int32_t e1000_write_eeprom_eewr(struct e1000_hw *hw, uint16_t offset, uint16_t words, @@ -3976,7 +4008,7 @@ e1000_write_eeprom_eewr(struct e1000_hw *hw, * * hw - Struct containing variables accessed by shared code *****************************************************************************/ -int32_t +static int32_t e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd) { uint32_t attempts = 100000; @@ -4004,7 +4036,7 @@ e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd) * * hw - Struct containing variables accessed by shared code ****************************************************************************/ -boolean_t +static boolean_t e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw) { uint32_t eecd = 0; @@ -4322,7 +4354,7 @@ e1000_write_eeprom_microwire(struct e1000_hw *hw, * data - word read from the EEPROM * words - number of words to read *****************************************************************************/ -int32_t +static int32_t e1000_commit_shadow_ram(struct e1000_hw *hw) { uint32_t attempts = 100000; @@ -4453,7 +4485,7 @@ e1000_read_mac_addr(struct e1000_hw * hw) * of the receive addresss registers. Clears the multicast table. Assumes * the receiver is in reset when the routine is called. *****************************************************************************/ -void +static void e1000_init_rx_addrs(struct e1000_hw *hw) { uint32_t i; @@ -4481,6 +4513,7 @@ e1000_init_rx_addrs(struct e1000_hw *hw) } } +#if 0 /****************************************************************************** * Updates the MAC's list of multicast addresses. * @@ -4564,6 +4597,7 @@ e1000_mc_addr_list_update(struct e1000_hw *hw, } DEBUGOUT("MC Update Complete\n"); } +#endif /* 0 */ /****************************************************************************** * Hashes an address to determine its location in the multicast table @@ -4705,7 +4739,7 @@ e1000_write_vfta(struct e1000_hw *hw, * * hw - Struct containing variables accessed by shared code *****************************************************************************/ -void +static void e1000_clear_vfta(struct e1000_hw *hw) { uint32_t offset; @@ -4735,7 +4769,7 @@ e1000_clear_vfta(struct e1000_hw *hw) } } -int32_t +static int32_t e1000_id_led_init(struct e1000_hw * hw) { uint32_t ledctl; @@ -4997,7 +5031,7 @@ e1000_led_off(struct e1000_hw *hw) * * hw - Struct containing variables accessed by shared code *****************************************************************************/ -void +static void e1000_clear_hw_cntrs(struct e1000_hw *hw) { volatile uint32_t temp; @@ -5283,6 +5317,8 @@ e1000_get_bus_info(struct e1000_hw *hw) break; } } + +#if 0 /****************************************************************************** * Reads a value from one of the devices registers using port I/O (as opposed * memory mapped I/O). Only 82544 and newer devices support port I/O. @@ -5300,6 +5336,7 @@ e1000_read_reg_io(struct e1000_hw *hw, e1000_io_write(hw, io_addr, offset); return e1000_io_read(hw, io_data); } +#endif /* 0 */ /****************************************************************************** * Writes a value to one of the devices registers using port I/O (as opposed to @@ -5309,7 +5346,7 @@ e1000_read_reg_io(struct e1000_hw *hw, * offset - offset to write to * value - value to write *****************************************************************************/ -void +static void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value) @@ -5337,7 +5374,7 @@ e1000_write_reg_io(struct e1000_hw *hw, * register to the minimum and maximum range. * For IGP phy's, the function calculates the range by the AGC registers. *****************************************************************************/ -int32_t +static int32_t e1000_get_cable_length(struct e1000_hw *hw, uint16_t *min_length, uint16_t *max_length) @@ -5489,7 +5526,7 @@ e1000_get_cable_length(struct e1000_hw *hw, * return 0. If the link speed is 1000 Mbps the polarity status is in the * IGP01E1000_PHY_PCS_INIT_REG. *****************************************************************************/ -int32_t +static int32_t e1000_check_polarity(struct e1000_hw *hw, uint16_t *polarity) { @@ -5551,7 +5588,7 @@ e1000_check_polarity(struct e1000_hw *hw, * Link Health register. In IGP this bit is latched high, so the driver must * read it immediately after link is established. *****************************************************************************/ -int32_t +static int32_t e1000_check_downshift(struct e1000_hw *hw) { int32_t ret_val; @@ -5592,7 +5629,7 @@ e1000_check_downshift(struct e1000_hw *hw) * ****************************************************************************/ -int32_t +static int32_t e1000_config_dsp_after_link_change(struct e1000_hw *hw, boolean_t link_up) { @@ -5823,7 +5860,7 @@ e1000_set_phy_mode(struct e1000_hw *hw) * ****************************************************************************/ -int32_t +static int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active) { @@ -5936,7 +5973,7 @@ e1000_set_d3_lplu_state(struct e1000_hw *hw, * ****************************************************************************/ -int32_t +static int32_t e1000_set_d0_lplu_state(struct e1000_hw *hw, boolean_t active) { @@ -6103,7 +6140,7 @@ e1000_host_if_read_cookie(struct e1000_hw * hw, uint8_t *buffer) * timeout * - E1000_SUCCESS for success. ****************************************************************************/ -int32_t +static int32_t e1000_mng_enable_host_if(struct e1000_hw * hw) { uint32_t hicr; @@ -6137,7 +6174,7 @@ e1000_mng_enable_host_if(struct e1000_hw * hw) * * returns - E1000_SUCCESS for success. ****************************************************************************/ -int32_t +static int32_t e1000_mng_host_if_write(struct e1000_hw * hw, uint8_t *buffer, uint16_t length, uint16_t offset, uint8_t *sum) { @@ -6205,7 +6242,7 @@ e1000_mng_host_if_write(struct e1000_hw * hw, uint8_t *buffer, * * returns - E1000_SUCCESS for success. ****************************************************************************/ -int32_t +static int32_t e1000_mng_write_cmd_header(struct e1000_hw * hw, struct e1000_host_mng_command_header * hdr) { @@ -6243,7 +6280,7 @@ e1000_mng_write_cmd_header(struct e1000_hw * hw, * * returns - E1000_SUCCESS for success. ****************************************************************************/ -int32_t +static int32_t e1000_mng_write_commit( struct e1000_hw * hw) { @@ -6496,7 +6533,7 @@ e1000_polarity_reversal_workaround(struct e1000_hw *hw) * returns: - none. * ***************************************************************************/ -void +static void e1000_set_pci_express_master_disable(struct e1000_hw *hw) { uint32_t ctrl; @@ -6511,6 +6548,7 @@ e1000_set_pci_express_master_disable(struct e1000_hw *hw) E1000_WRITE_REG(hw, CTRL, ctrl); } +#if 0 /*************************************************************************** * * Enables PCI-Express master access. @@ -6534,6 +6572,7 @@ e1000_enable_pciex_master(struct e1000_hw *hw) ctrl &= ~E1000_CTRL_GIO_MASTER_DISABLE; E1000_WRITE_REG(hw, CTRL, ctrl); } +#endif /* 0 */ /******************************************************************************* * @@ -6584,7 +6623,7 @@ e1000_disable_pciex_master(struct e1000_hw *hw) * E1000_SUCCESS at any other case. * ******************************************************************************/ -int32_t +static int32_t e1000_get_auto_rd_done(struct e1000_hw *hw) { int32_t timeout = AUTO_READ_DONE_TIMEOUT; @@ -6623,7 +6662,7 @@ e1000_get_auto_rd_done(struct e1000_hw *hw) * E1000_SUCCESS at any other case. * ***************************************************************************/ -int32_t +static int32_t e1000_get_phy_cfg_done(struct e1000_hw *hw) { int32_t timeout = PHY_CFG_TIMEOUT; @@ -6666,7 +6705,7 @@ e1000_get_phy_cfg_done(struct e1000_hw *hw) * E1000_SUCCESS at any other case. * ***************************************************************************/ -int32_t +static int32_t e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw) { int32_t timeout; @@ -6711,7 +6750,7 @@ e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw) * returns: - None. * ***************************************************************************/ -void +static void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw) { uint32_t swsm; @@ -6747,7 +6786,7 @@ e1000_check_phy_reset_block(struct e1000_hw *hw) E1000_BLK_PHY_RESET : E1000_SUCCESS; } -uint8_t +static uint8_t e1000_arc_subsystem_valid(struct e1000_hw *hw) { uint32_t fwsm; diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index 4f2c196dc31..76ce12809a1 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -284,7 +284,6 @@ typedef enum { /* Initialization */ int32_t e1000_reset_hw(struct e1000_hw *hw); int32_t e1000_init_hw(struct e1000_hw *hw); -int32_t e1000_id_led_init(struct e1000_hw * hw); int32_t e1000_set_mac_type(struct e1000_hw *hw); void e1000_set_media_type(struct e1000_hw *hw); @@ -292,10 +291,8 @@ void e1000_set_media_type(struct e1000_hw *hw); int32_t e1000_setup_link(struct e1000_hw *hw); int32_t e1000_phy_setup_autoneg(struct e1000_hw *hw); void e1000_config_collision_dist(struct e1000_hw *hw); -int32_t e1000_config_fc_after_link_up(struct e1000_hw *hw); int32_t e1000_check_for_link(struct e1000_hw *hw); int32_t e1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t * speed, uint16_t * duplex); -int32_t e1000_wait_autoneg(struct e1000_hw *hw); int32_t e1000_force_mac_fc(struct e1000_hw *hw); /* PHY */ @@ -303,21 +300,11 @@ int32_t e1000_read_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *phy int32_t e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t data); int32_t e1000_phy_hw_reset(struct e1000_hw *hw); int32_t e1000_phy_reset(struct e1000_hw *hw); -int32_t e1000_detect_gig_phy(struct e1000_hw *hw); int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info); -int32_t e1000_phy_m88_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info); -int32_t e1000_phy_igp_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info); -int32_t e1000_get_cable_length(struct e1000_hw *hw, uint16_t *min_length, uint16_t *max_length); -int32_t e1000_check_polarity(struct e1000_hw *hw, uint16_t *polarity); -int32_t e1000_check_downshift(struct e1000_hw *hw); int32_t e1000_validate_mdi_setting(struct e1000_hw *hw); /* EEPROM Functions */ int32_t e1000_init_eeprom_params(struct e1000_hw *hw); -boolean_t e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw); -int32_t e1000_read_eeprom_eerd(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data); -int32_t e1000_write_eeprom_eewr(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data); -int32_t e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd); /* MNG HOST IF functions */ uint32_t e1000_enable_mng_pass_thru(struct e1000_hw *hw); @@ -377,13 +364,6 @@ int32_t e1000_mng_write_dhcp_info(struct e1000_hw *hw, uint8_t *buffer, uint16_t length); boolean_t e1000_check_mng_mode(struct e1000_hw *hw); boolean_t e1000_enable_tx_pkt_filtering(struct e1000_hw *hw); -int32_t e1000_mng_enable_host_if(struct e1000_hw *hw); -int32_t e1000_mng_host_if_write(struct e1000_hw *hw, uint8_t *buffer, - uint16_t length, uint16_t offset, uint8_t *sum); -int32_t e1000_mng_write_cmd_header(struct e1000_hw* hw, - struct e1000_host_mng_command_header* hdr); - -int32_t e1000_mng_write_commit(struct e1000_hw *hw); int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data); int32_t e1000_validate_eeprom_checksum(struct e1000_hw *hw); @@ -395,13 +375,10 @@ int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask); void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask); /* Filters (multicast, vlan, receive) */ -void e1000_init_rx_addrs(struct e1000_hw *hw); -void e1000_mc_addr_list_update(struct e1000_hw *hw, uint8_t * mc_addr_list, uint32_t mc_addr_count, uint32_t pad, uint32_t rar_used_count); uint32_t e1000_hash_mc_addr(struct e1000_hw *hw, uint8_t * mc_addr); void e1000_mta_set(struct e1000_hw *hw, uint32_t hash_value); void e1000_rar_set(struct e1000_hw *hw, uint8_t * mc_addr, uint32_t rar_index); void e1000_write_vfta(struct e1000_hw *hw, uint32_t offset, uint32_t value); -void e1000_clear_vfta(struct e1000_hw *hw); /* LED functions */ int32_t e1000_setup_led(struct e1000_hw *hw); @@ -412,7 +389,6 @@ int32_t e1000_led_off(struct e1000_hw *hw); /* Adaptive IFS Functions */ /* Everything else */ -void e1000_clear_hw_cntrs(struct e1000_hw *hw); void e1000_reset_adaptive(struct e1000_hw *hw); void e1000_update_adaptive(struct e1000_hw *hw); void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats, uint32_t frame_len, uint8_t * mac_addr); @@ -423,29 +399,11 @@ void e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value); void e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value); /* Port I/O is only supported on 82544 and newer */ uint32_t e1000_io_read(struct e1000_hw *hw, unsigned long port); -uint32_t e1000_read_reg_io(struct e1000_hw *hw, uint32_t offset); void e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value); -void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value); -int32_t e1000_config_dsp_after_link_change(struct e1000_hw *hw, boolean_t link_up); -int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active); -int32_t e1000_set_d0_lplu_state(struct e1000_hw *hw, boolean_t active); -void e1000_set_pci_express_master_disable(struct e1000_hw *hw); -void e1000_enable_pciex_master(struct e1000_hw *hw); int32_t e1000_disable_pciex_master(struct e1000_hw *hw); -int32_t e1000_get_auto_rd_done(struct e1000_hw *hw); -int32_t e1000_get_phy_cfg_done(struct e1000_hw *hw); int32_t e1000_get_software_semaphore(struct e1000_hw *hw); void e1000_release_software_semaphore(struct e1000_hw *hw); int32_t e1000_check_phy_reset_block(struct e1000_hw *hw); -int32_t e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw); -void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw); -int32_t e1000_commit_shadow_ram(struct e1000_hw *hw); -uint8_t e1000_arc_subsystem_valid(struct e1000_hw *hw); - -#define E1000_READ_REG_IO(a, reg) \ - e1000_read_reg_io((a), E1000_##reg) -#define E1000_WRITE_REG_IO(a, reg, val) \ - e1000_write_reg_io((a), E1000_##reg, val) /* PCI Device IDs */ #define E1000_DEV_ID_82542 0x1000 diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index efbbda7cbcb..8b207f0e139 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -37,7 +37,7 @@ */ char e1000_driver_name[] = "e1000"; -char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; +static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; #ifndef CONFIG_E1000_NAPI #define DRIVERNAPI #else @@ -45,7 +45,7 @@ char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; #endif #define DRV_VERSION "6.1.16-k2"DRIVERNAPI char e1000_driver_version[] = DRV_VERSION; -char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation."; +static char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation."; /* e1000_pci_tbl - PCI Device ID Table * @@ -112,14 +112,14 @@ int e1000_setup_all_tx_resources(struct e1000_adapter *adapter); int e1000_setup_all_rx_resources(struct e1000_adapter *adapter); void e1000_free_all_tx_resources(struct e1000_adapter *adapter); void e1000_free_all_rx_resources(struct e1000_adapter *adapter); -int e1000_setup_tx_resources(struct e1000_adapter *adapter, - struct e1000_tx_ring *txdr); -int e1000_setup_rx_resources(struct e1000_adapter *adapter, - struct e1000_rx_ring *rxdr); -void e1000_free_tx_resources(struct e1000_adapter *adapter, - struct e1000_tx_ring *tx_ring); -void e1000_free_rx_resources(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring); +static int e1000_setup_tx_resources(struct e1000_adapter *adapter, + struct e1000_tx_ring *txdr); +static int e1000_setup_rx_resources(struct e1000_adapter *adapter, + struct e1000_rx_ring *rxdr); +static void e1000_free_tx_resources(struct e1000_adapter *adapter, + struct e1000_tx_ring *tx_ring); +static void e1000_free_rx_resources(struct e1000_adapter *adapter, + struct e1000_rx_ring *rx_ring); void e1000_update_stats(struct e1000_adapter *adapter); /* Local Function Prototypes */ @@ -296,7 +296,8 @@ e1000_irq_enable(struct e1000_adapter *adapter) E1000_WRITE_FLUSH(&adapter->hw); } } -void + +static void e1000_update_mng_vlan(struct e1000_adapter *adapter) { struct net_device *netdev = adapter->netdev; @@ -1141,7 +1142,7 @@ e1000_check_64k_bound(struct e1000_adapter *adapter, * Return 0 on success, negative on failure **/ -int +static int e1000_setup_tx_resources(struct e1000_adapter *adapter, struct e1000_tx_ring *txdr) { @@ -1359,7 +1360,7 @@ e1000_configure_tx(struct e1000_adapter *adapter) * Returns 0 on success, negative on failure **/ -int +static int e1000_setup_rx_resources(struct e1000_adapter *adapter, struct e1000_rx_ring *rxdr) { @@ -1747,7 +1748,7 @@ e1000_configure_rx(struct e1000_adapter *adapter) * Free all transmit software resources **/ -void +static void e1000_free_tx_resources(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring) { @@ -1858,7 +1859,7 @@ e1000_clean_all_tx_rings(struct e1000_adapter *adapter) * Free all receive software resources **/ -void +static void e1000_free_rx_resources(struct e1000_adapter *adapter, struct e1000_rx_ring *rx_ring) { -- cgit v1.2.3 From e6b365f61e0bd6e8e5fd320bda78e92eafab79aa Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 31 Oct 2005 01:33:45 +0100 Subject: [PATCH] drivers/net/hamradio/dmascc.c: remove dmascc_setup() It seems dmascc_setup() is a leftover time before dmascc_init() was there. Signed-off-by: Adrian Bunk Signed-off-by: John W. Linville --- drivers/net/hamradio/dmascc.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c index 3be3f916643..c8dc40214a0 100644 --- a/drivers/net/hamradio/dmascc.c +++ b/drivers/net/hamradio/dmascc.c @@ -311,16 +311,6 @@ static void __exit dmascc_exit(void) } } -#ifndef MODULE -void __init dmascc_setup(char *str, int *ints) -{ - int i; - - for (i = 0; i < MAX_NUM_DEVS && i < ints[0]; i++) - io[i] = ints[i + 1]; -} -#endif - static int __init dmascc_init(void) { int h, i, j, n; -- cgit v1.2.3 From 17ecc1e63b675fb43d60e84f242c848f81c5a079 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Thu, 3 Nov 2005 22:45:02 +0000 Subject: [PATCH] prism54: Remove redundant assignment The last patch I sent in ("prism54: Free skb after disabling interrupts") included a redundant NULL assignment. Thanks to Herbert Xu for pointing it out. Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/prism54/islpci_eth.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index 3b49efa37ee..fc1eb356483 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c @@ -244,7 +244,6 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev) priv->statistics.tx_dropped++; spin_unlock_irqrestore(&priv->slock, flags); dev_kfree_skb(skb); - skb = NULL; return err; } -- cgit v1.2.3 From 5b0c76ad94faf95ca50fa0de9ab07460bea19568 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 4 Nov 2005 08:45:49 -0800 Subject: [PATCH] bnx2: add 5708 support Add 5708 copper and serdes basic support, including 2.5 Gbps support on 5708 serdes. SPEED_2500 is also added to ethtool.h Signed-off-by: Michael Chan Signed-off-by: John W. Linville --- drivers/net/bnx2.c | 217 ++++++++++++++++++++++++++++++++++++++++++------ drivers/net/bnx2.h | 63 +++++++++++++- include/linux/ethtool.h | 3 +- include/linux/pci_ids.h | 2 + 4 files changed, 256 insertions(+), 29 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 11d25231822..671393a1846 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -41,6 +41,8 @@ typedef enum { NC370I, BCM5706S, NC370F, + BCM5708, + BCM5708S, } board_t; /* indexed by board_t, above */ @@ -52,6 +54,8 @@ static struct { { "HP NC370i Multifunction Gigabit Server Adapter" }, { "Broadcom NetXtreme II BCM5706 1000Base-SX" }, { "HP NC370F Multifunction Gigabit Server Adapter" }, + { "Broadcom NetXtreme II BCM5708 1000Base-T" }, + { "Broadcom NetXtreme II BCM5708 1000Base-SX" }, }; static struct pci_device_id bnx2_pci_tbl[] = { @@ -61,10 +65,14 @@ static struct pci_device_id bnx2_pci_tbl[] = { PCI_VENDOR_ID_HP, 0x3106, 0, 0, NC370I }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5706 }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5708, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5708 }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706S, PCI_VENDOR_ID_HP, 0x3102, 0, 0, NC370F }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706S, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5706S }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5708S, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5708S }, { 0, } }; @@ -430,6 +438,18 @@ bnx2_resolve_flow_ctrl(struct bnx2 *bp) return; } + if ((bp->phy_flags & PHY_SERDES_FLAG) && + (CHIP_NUM(bp) == CHIP_NUM_5708)) { + u32 val; + + bnx2_read_phy(bp, BCM5708S_1000X_STAT1, &val); + if (val & BCM5708S_1000X_STAT1_TX_PAUSE) + bp->flow_ctrl |= FLOW_CTRL_TX; + if (val & BCM5708S_1000X_STAT1_RX_PAUSE) + bp->flow_ctrl |= FLOW_CTRL_RX; + return; + } + bnx2_read_phy(bp, MII_ADVERTISE, &local_adv); bnx2_read_phy(bp, MII_LPA, &remote_adv); @@ -476,7 +496,36 @@ bnx2_resolve_flow_ctrl(struct bnx2 *bp) } static int -bnx2_serdes_linkup(struct bnx2 *bp) +bnx2_5708s_linkup(struct bnx2 *bp) +{ + u32 val; + + bp->link_up = 1; + bnx2_read_phy(bp, BCM5708S_1000X_STAT1, &val); + switch (val & BCM5708S_1000X_STAT1_SPEED_MASK) { + case BCM5708S_1000X_STAT1_SPEED_10: + bp->line_speed = SPEED_10; + break; + case BCM5708S_1000X_STAT1_SPEED_100: + bp->line_speed = SPEED_100; + break; + case BCM5708S_1000X_STAT1_SPEED_1G: + bp->line_speed = SPEED_1000; + break; + case BCM5708S_1000X_STAT1_SPEED_2G5: + bp->line_speed = SPEED_2500; + break; + } + if (val & BCM5708S_1000X_STAT1_FD) + bp->duplex = DUPLEX_FULL; + else + bp->duplex = DUPLEX_HALF; + + return 0; +} + +static int +bnx2_5706s_linkup(struct bnx2 *bp) { u32 bmcr, local_adv, remote_adv, common; @@ -593,13 +642,27 @@ bnx2_set_mac_link(struct bnx2 *bp) val = REG_RD(bp, BNX2_EMAC_MODE); val &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX | - BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK); + BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK | + BNX2_EMAC_MODE_25G); if (bp->link_up) { - if (bp->line_speed != SPEED_1000) - val |= BNX2_EMAC_MODE_PORT_MII; - else - val |= BNX2_EMAC_MODE_PORT_GMII; + switch (bp->line_speed) { + case SPEED_10: + if (CHIP_NUM(bp) == CHIP_NUM_5708) { + val |= BNX2_EMAC_MODE_PORT_MII_10; + break; + } + /* fall through */ + case SPEED_100: + val |= BNX2_EMAC_MODE_PORT_MII; + break; + case SPEED_2500: + val |= BNX2_EMAC_MODE_25G; + /* fall through */ + case SPEED_1000: + val |= BNX2_EMAC_MODE_PORT_GMII; + break; + } } else { val |= BNX2_EMAC_MODE_PORT_GMII; @@ -662,7 +725,10 @@ bnx2_set_link(struct bnx2 *bp) bp->link_up = 1; if (bp->phy_flags & PHY_SERDES_FLAG) { - bnx2_serdes_linkup(bp); + if (CHIP_NUM(bp) == CHIP_NUM_5706) + bnx2_5706s_linkup(bp); + else if (CHIP_NUM(bp) == CHIP_NUM_5708) + bnx2_5708s_linkup(bp); } else { bnx2_copper_linkup(bp); @@ -755,39 +821,61 @@ bnx2_phy_get_pause_adv(struct bnx2 *bp) static int bnx2_setup_serdes_phy(struct bnx2 *bp) { - u32 adv, bmcr; + u32 adv, bmcr, up1; u32 new_adv = 0; if (!(bp->autoneg & AUTONEG_SPEED)) { u32 new_bmcr; + int force_link_down = 0; + + if (CHIP_NUM(bp) == CHIP_NUM_5708) { + bnx2_read_phy(bp, BCM5708S_UP1, &up1); + if (up1 & BCM5708S_UP1_2G5) { + up1 &= ~BCM5708S_UP1_2G5; + bnx2_write_phy(bp, BCM5708S_UP1, up1); + force_link_down = 1; + } + } + + bnx2_read_phy(bp, MII_ADVERTISE, &adv); + adv &= ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF); bnx2_read_phy(bp, MII_BMCR, &bmcr); new_bmcr = bmcr & ~BMCR_ANENABLE; new_bmcr |= BMCR_SPEED1000; if (bp->req_duplex == DUPLEX_FULL) { + adv |= ADVERTISE_1000XFULL; new_bmcr |= BMCR_FULLDPLX; } else { + adv |= ADVERTISE_1000XHALF; new_bmcr &= ~BMCR_FULLDPLX; } - if (new_bmcr != bmcr) { + if ((new_bmcr != bmcr) || (force_link_down)) { /* Force a link down visible on the other side */ if (bp->link_up) { - bnx2_read_phy(bp, MII_ADVERTISE, &adv); - adv &= ~(ADVERTISE_1000XFULL | - ADVERTISE_1000XHALF); - bnx2_write_phy(bp, MII_ADVERTISE, adv); + bnx2_write_phy(bp, MII_ADVERTISE, adv & + ~(ADVERTISE_1000XFULL | + ADVERTISE_1000XHALF)); bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART | BMCR_ANENABLE); bp->link_up = 0; netif_carrier_off(bp->dev); + bnx2_write_phy(bp, MII_BMCR, new_bmcr); } + bnx2_write_phy(bp, MII_ADVERTISE, adv); bnx2_write_phy(bp, MII_BMCR, new_bmcr); } return 0; } + if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) { + bnx2_read_phy(bp, BCM5708S_UP1, &up1); + up1 |= BCM5708S_UP1_2G5; + bnx2_write_phy(bp, BCM5708S_UP1, up1); + } + if (bp->advertising & ADVERTISED_1000baseT_Full) new_adv |= ADVERTISE_1000XFULL; @@ -952,7 +1040,60 @@ bnx2_setup_phy(struct bnx2 *bp) } static int -bnx2_init_serdes_phy(struct bnx2 *bp) +bnx2_init_5708s_phy(struct bnx2 *bp) +{ + u32 val; + + bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG3); + bnx2_write_phy(bp, BCM5708S_DIG_3_0, BCM5708S_DIG_3_0_USE_IEEE); + bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG); + + bnx2_read_phy(bp, BCM5708S_1000X_CTL1, &val); + val |= BCM5708S_1000X_CTL1_FIBER_MODE | BCM5708S_1000X_CTL1_AUTODET_EN; + bnx2_write_phy(bp, BCM5708S_1000X_CTL1, val); + + bnx2_read_phy(bp, BCM5708S_1000X_CTL2, &val); + val |= BCM5708S_1000X_CTL2_PLLEL_DET_EN; + bnx2_write_phy(bp, BCM5708S_1000X_CTL2, val); + + if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) { + bnx2_read_phy(bp, BCM5708S_UP1, &val); + val |= BCM5708S_UP1_2G5; + bnx2_write_phy(bp, BCM5708S_UP1, val); + } + + if ((CHIP_ID(bp) == CHIP_ID_5708_A0) || + (CHIP_ID(bp) == CHIP_ID_5708_B0)) { + /* increase tx signal amplitude */ + bnx2_write_phy(bp, BCM5708S_BLK_ADDR, + BCM5708S_BLK_ADDR_TX_MISC); + bnx2_read_phy(bp, BCM5708S_TX_ACTL1, &val); + val &= ~BCM5708S_TX_ACTL1_DRIVER_VCM; + bnx2_write_phy(bp, BCM5708S_TX_ACTL1, val); + bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG); + } + + val = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_PORT_HW_CFG_CONFIG) & + BNX2_PORT_HW_CFG_CFG_TXCTL3_MASK; + + if (val) { + u32 is_backplane; + + is_backplane = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + + BNX2_SHARED_HW_CFG_CONFIG); + if (is_backplane & BNX2_SHARED_HW_CFG_PHY_BACKPLANE) { + bnx2_write_phy(bp, BCM5708S_BLK_ADDR, + BCM5708S_BLK_ADDR_TX_MISC); + bnx2_write_phy(bp, BCM5708S_TX_ACTL3, val); + bnx2_write_phy(bp, BCM5708S_BLK_ADDR, + BCM5708S_BLK_ADDR_DIG); + } + } + return 0; +} + +static int +bnx2_init_5706s_phy(struct bnx2 *bp) { bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG; @@ -990,6 +1131,8 @@ bnx2_init_serdes_phy(struct bnx2 *bp) static int bnx2_init_copper_phy(struct bnx2 *bp) { + u32 val; + bp->phy_flags |= PHY_CRC_FIX_FLAG; if (bp->phy_flags & PHY_CRC_FIX_FLAG) { @@ -1004,8 +1147,6 @@ bnx2_init_copper_phy(struct bnx2 *bp) } if (bp->dev->mtu > 1500) { - u32 val; - /* Set extended packet length bit */ bnx2_write_phy(bp, 0x18, 0x7); bnx2_read_phy(bp, 0x18, &val); @@ -1015,8 +1156,6 @@ bnx2_init_copper_phy(struct bnx2 *bp) bnx2_write_phy(bp, 0x10, val | 0x1); } else { - u32 val; - bnx2_write_phy(bp, 0x18, 0x7); bnx2_read_phy(bp, 0x18, &val); bnx2_write_phy(bp, 0x18, val & ~0x4007); @@ -1025,6 +1164,10 @@ bnx2_init_copper_phy(struct bnx2 *bp) bnx2_write_phy(bp, 0x10, val & ~0x1); } + /* ethernet@wirespeed */ + bnx2_write_phy(bp, 0x18, 0x7007); + bnx2_read_phy(bp, 0x18, &val); + bnx2_write_phy(bp, 0x18, val | (1 << 15) | (1 << 4)); return 0; } @@ -1048,7 +1191,10 @@ bnx2_init_phy(struct bnx2 *bp) bp->phy_id |= val & 0xffff; if (bp->phy_flags & PHY_SERDES_FLAG) { - rc = bnx2_init_serdes_phy(bp); + if (CHIP_NUM(bp) == CHIP_NUM_5706) + rc = bnx2_init_5706s_phy(bp); + else if (CHIP_NUM(bp) == CHIP_NUM_5708) + rc = bnx2_init_5708s_phy(bp); } else { rc = bnx2_init_copper_phy(bp); @@ -3234,7 +3380,7 @@ bnx2_test_registers(struct bnx2 *bp) { 0x1408, 0, 0x01c00800, 0x00000000 }, { 0x149c, 0, 0x8000ffff, 0x00000000 }, { 0x14a8, 0, 0x00000000, 0x000001ff }, - { 0x14ac, 0, 0x4fffffff, 0x10000000 }, + { 0x14ac, 0, 0x0fffffff, 0x10000000 }, { 0x14b0, 0, 0x00000002, 0x00000001 }, { 0x14b8, 0, 0x00000000, 0x00000000 }, { 0x14c0, 0, 0x00000000, 0x00000009 }, @@ -3577,7 +3723,7 @@ bnx2_test_memory(struct bnx2 *bp) u32 len; } mem_tbl[] = { { 0x60000, 0x4000 }, - { 0xa0000, 0x4000 }, + { 0xa0000, 0x3000 }, { 0xe0000, 0x4000 }, { 0x120000, 0x4000 }, { 0x1a0000, 0x4000 }, @@ -4264,7 +4410,8 @@ bnx2_get_stats(struct net_device *dev) (unsigned long) (stats_blk->stat_Dot3StatsExcessiveCollisions + stats_blk->stat_Dot3StatsLateCollisions); - if (CHIP_NUM(bp) == CHIP_NUM_5706) + if ((CHIP_NUM(bp) == CHIP_NUM_5706) || + (CHIP_ID(bp) == CHIP_ID_5708_A0)) net_stats->tx_carrier_errors = 0; else { net_stats->tx_carrier_errors = @@ -4814,6 +4961,14 @@ static u8 bnx2_5706_stats_len_arr[BNX2_NUM_STATS] = { 4,4,4,4,4, }; +static u8 bnx2_5708_stats_len_arr[BNX2_NUM_STATS] = { + 8,0,8,8,8,8,8,8,8,8, + 4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4, +}; + #define BNX2_NUM_TESTS 6 static struct { @@ -4922,8 +5077,13 @@ bnx2_get_ethtool_stats(struct net_device *dev, return; } - if (CHIP_NUM(bp) == CHIP_NUM_5706) + if ((CHIP_ID(bp) == CHIP_ID_5706_A0) || + (CHIP_ID(bp) == CHIP_ID_5706_A1) || + (CHIP_ID(bp) == CHIP_ID_5706_A2) || + (CHIP_ID(bp) == CHIP_ID_5708_A0)) stats_len_arr = bnx2_5706_stats_len_arr; + else + stats_len_arr = bnx2_5708_stats_len_arr; for (i = 0; i < BNX2_NUM_STATS; i++) { if (stats_len_arr[i] == 0) { @@ -5205,8 +5365,6 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->chip_id = REG_RD(bp, BNX2_MISC_ID); - bp->phy_addr = 1; - /* Get bus information. */ reg = REG_RD(bp, BNX2_PCICFG_MISC_STATUS); if (reg & BNX2_PCICFG_MISC_STATUS_PCIX_DET) { @@ -5316,10 +5474,19 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->timer_interval = HZ; bp->current_interval = HZ; + bp->phy_addr = 1; + /* Disable WOL support if we are running on a SERDES chip. */ if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT) { bp->phy_flags |= PHY_SERDES_FLAG; bp->flags |= NO_WOL_FLAG; + if (CHIP_NUM(bp) == CHIP_NUM_5708) { + bp->phy_addr = 2; + reg = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + + BNX2_SHARED_HW_CFG_CONFIG); + if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G) + bp->phy_flags |= PHY_2_5G_CAPABLE_FLAG; + } } if (CHIP_ID(bp) == CHIP_ID_5706_A0) { diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 62857b6a6ee..c0e88f85049 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -1449,8 +1449,9 @@ struct l2_fhdr { #define BNX2_EMAC_MODE_PORT_NONE (0L<<2) #define BNX2_EMAC_MODE_PORT_MII (1L<<2) #define BNX2_EMAC_MODE_PORT_GMII (2L<<2) -#define BNX2_EMAC_MODE_PORT_UNDEF (3L<<2) +#define BNX2_EMAC_MODE_PORT_MII_10 (3L<<2) #define BNX2_EMAC_MODE_MAC_LOOP (1L<<4) +#define BNX2_EMAC_MODE_25G (1L<<5) #define BNX2_EMAC_MODE_TAGGED_MAC_CTL (1L<<7) #define BNX2_EMAC_MODE_TX_BURST (1L<<8) #define BNX2_EMAC_MODE_MAX_DEFER_DROP_ENA (1L<<9) @@ -3724,6 +3725,53 @@ struct l2_fhdr { #define PHY_ID(id) ((id) & 0xfffffff0) #define PHY_REV_ID(id) ((id) & 0xf) +/* 5708 Serdes PHY registers */ + +#define BCM5708S_UP1 0xb + +#define BCM5708S_UP1_2G5 0x1 + +#define BCM5708S_BLK_ADDR 0x1f + +#define BCM5708S_BLK_ADDR_DIG 0x0000 +#define BCM5708S_BLK_ADDR_DIG3 0x0002 +#define BCM5708S_BLK_ADDR_TX_MISC 0x0005 + +/* Digital Block */ +#define BCM5708S_1000X_CTL1 0x10 + +#define BCM5708S_1000X_CTL1_FIBER_MODE 0x0001 +#define BCM5708S_1000X_CTL1_AUTODET_EN 0x0010 + +#define BCM5708S_1000X_CTL2 0x11 + +#define BCM5708S_1000X_CTL2_PLLEL_DET_EN 0x0001 + +#define BCM5708S_1000X_STAT1 0x14 + +#define BCM5708S_1000X_STAT1_SGMII 0x0001 +#define BCM5708S_1000X_STAT1_LINK 0x0002 +#define BCM5708S_1000X_STAT1_FD 0x0004 +#define BCM5708S_1000X_STAT1_SPEED_MASK 0x0018 +#define BCM5708S_1000X_STAT1_SPEED_10 0x0000 +#define BCM5708S_1000X_STAT1_SPEED_100 0x0008 +#define BCM5708S_1000X_STAT1_SPEED_1G 0x0010 +#define BCM5708S_1000X_STAT1_SPEED_2G5 0x0018 +#define BCM5708S_1000X_STAT1_TX_PAUSE 0x0020 +#define BCM5708S_1000X_STAT1_RX_PAUSE 0x0040 + +/* Digital3 Block */ +#define BCM5708S_DIG_3_0 0x10 + +#define BCM5708S_DIG_3_0_USE_IEEE 0x0001 + +/* Tx/Misc Block */ +#define BCM5708S_TX_ACTL1 0x15 + +#define BCM5708S_TX_ACTL1_DRIVER_VCM 0x30 + +#define BCM5708S_TX_ACTL3 0x17 + #define MIN_ETHERNET_PACKET_SIZE 60 #define MAX_ETHERNET_PACKET_SIZE 1514 #define MAX_ETHERNET_JUMBO_PACKET_SIZE 9014 @@ -3893,6 +3941,7 @@ struct bnx2 { #define PHY_SERDES_FLAG 1 #define PHY_CRC_FIX_FLAG 2 #define PHY_PARALLEL_DETECT_FLAG 4 +#define PHY_2_5G_CAPABLE_FLAG 8 #define PHY_INT_MODE_MASK_FLAG 0x300 #define PHY_INT_MODE_AUTO_POLLING_FLAG 0x100 #define PHY_INT_MODE_LINK_READY_FLAG 0x200 @@ -3901,6 +3950,7 @@ struct bnx2 { /* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */ #define CHIP_NUM(bp) (((bp)->chip_id) & 0xffff0000) #define CHIP_NUM_5706 0x57060000 +#define CHIP_NUM_5708 0x57080000 #define CHIP_REV(bp) (((bp)->chip_id) & 0x0000f000) #define CHIP_REV_Ax 0x00000000 @@ -3913,6 +3963,9 @@ struct bnx2 { #define CHIP_ID(bp) (((bp)->chip_id) & 0xfffffff0) #define CHIP_ID_5706_A0 0x57060000 #define CHIP_ID_5706_A1 0x57060010 +#define CHIP_ID_5706_A2 0x57060020 +#define CHIP_ID_5708_A0 0x57080000 +#define CHIP_ID_5708_B0 0x57081000 #define CHIP_BOND_ID(bp) (((bp)->chip_id) & 0xf) @@ -4132,12 +4185,12 @@ struct fw_info { #define BNX2_LINK_STATUS 0x0000000c #define BNX2_DRV_PULSE_MB 0x00000010 -#define BNX2_DRV_PULSE_SEQ_MASK 0x0000ffff +#define BNX2_DRV_PULSE_SEQ_MASK 0x00007fff /* Indicate to the firmware not to go into the * OS absent when it is not getting driver pulse. * This is used for debugging. */ -#define BNX2_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE 0x00010000 +#define BNX2_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE 0x00080000 #define BNX2_DEV_INFO_SIGNATURE 0x00000020 #define BNX2_DEV_INFO_SIGNATURE_MAGIC 0x44564900 @@ -4160,6 +4213,8 @@ struct fw_info { #define BNX2_SHARED_HW_CFG_DESIGN_LOM 0x1 #define BNX2_SHARED_HW_CFG_PHY_COPPER 0 #define BNX2_SHARED_HW_CFG_PHY_FIBER 0x2 +#define BNX2_SHARED_HW_CFG_PHY_2_5G 0x20 +#define BNX2_SHARED_HW_CFG_PHY_BACKPLANE 0x40 #define BNX2_SHARED_HW_CFG_LED_MODE_SHIFT_BITS 8 #define BNX2_SHARED_HW_CFG_LED_MODE_MASK 0x300 #define BNX2_SHARED_HW_CFG_LED_MODE_MAC 0 @@ -4173,9 +4228,11 @@ struct fw_info { #define BNX2_PORT_HW_CFG_MAC_LOWER 0x00000054 #define BNX2_PORT_HW_CFG_CONFIG 0x00000058 +#define BNX2_PORT_HW_CFG_CFG_TXCTL3_MASK 0x0000ffff #define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK 0x001f0000 #define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_AN 0x00000000 #define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G 0x00030000 +#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_2_5G 0x00040000 #define BNX2_PORT_HW_CFG_IMD_MAC_A_UPPER 0x00000068 #define BNX2_PORT_HW_CFG_IMD_MAC_A_LOWER 0x0000006c diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index d2c390eff1b..93535f09321 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -453,10 +453,11 @@ struct ethtool_ops { * it was foced up into this mode or autonegotiated. */ -/* The forced speed, 10Mb, 100Mb, gigabit, 10GbE. */ +/* The forced speed, 10Mb, 100Mb, gigabit, 2.5Gb, 10GbE. */ #define SPEED_10 10 #define SPEED_100 100 #define SPEED_1000 1000 +#define SPEED_2500 2500 #define SPEED_10000 10000 /* Duplex, half or full. */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 88de3f8ce1a..8cadfdeef67 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1785,6 +1785,7 @@ #define PCI_DEVICE_ID_TIGON3_5704 0x1648 #define PCI_DEVICE_ID_TIGON3_5704S_2 0x1649 #define PCI_DEVICE_ID_NX2_5706 0x164a +#define PCI_DEVICE_ID_NX2_5708 0x164c #define PCI_DEVICE_ID_TIGON3_5702FE 0x164d #define PCI_DEVICE_ID_TIGON3_5705 0x1653 #define PCI_DEVICE_ID_TIGON3_5705_2 0x1654 @@ -1809,6 +1810,7 @@ #define PCI_DEVICE_ID_TIGON3_5703X 0x16a7 #define PCI_DEVICE_ID_TIGON3_5704S 0x16a8 #define PCI_DEVICE_ID_NX2_5706S 0x16aa +#define PCI_DEVICE_ID_NX2_5708S 0x16ac #define PCI_DEVICE_ID_TIGON3_5702A3 0x16c6 #define PCI_DEVICE_ID_TIGON3_5703A3 0x16c7 #define PCI_DEVICE_ID_TIGON3_5781 0x16dd -- cgit v1.2.3 From 12d30d89e57d467e4c134906a4682719813d40ad Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 4 Nov 2005 08:48:02 -0800 Subject: [PATCH] bnx2: update firmware for 5708 Update bnx2 firmware with support for 5708. Signed-off-by: Michael Chan Signed-off-by: John W. Linville --- drivers/net/bnx2_fw.h | 4055 ++++++++++++++++++++++++++++++------------------- 1 file changed, 2527 insertions(+), 1528 deletions(-) diff --git a/drivers/net/bnx2_fw.h b/drivers/net/bnx2_fw.h index 35f3a2ae5ef..ab07a4900e9 100644 --- a/drivers/net/bnx2_fw.h +++ b/drivers/net/bnx2_fw.h @@ -14,24 +14,23 @@ * accompanying it. */ - -static int bnx2_COM_b06FwReleaseMajor = 0x0; +static int bnx2_COM_b06FwReleaseMajor = 0x1; static int bnx2_COM_b06FwReleaseMinor = 0x0; static int bnx2_COM_b06FwReleaseFix = 0x0; -static u32 bnx2_COM_b06FwStartAddr = 0x080004a0; +static u32 bnx2_COM_b06FwStartAddr = 0x080008b4; static u32 bnx2_COM_b06FwTextAddr = 0x08000000; -static int bnx2_COM_b06FwTextLen = 0x4594; -static u32 bnx2_COM_b06FwDataAddr = 0x080045e0; +static int bnx2_COM_b06FwTextLen = 0x57bc; +static u32 bnx2_COM_b06FwDataAddr = 0x08005840; static int bnx2_COM_b06FwDataLen = 0x0; -static u32 bnx2_COM_b06FwRodataAddr = 0x08004598; -static int bnx2_COM_b06FwRodataLen = 0x18; -static u32 bnx2_COM_b06FwBssAddr = 0x08004600; +static u32 bnx2_COM_b06FwRodataAddr = 0x080057c0; +static int bnx2_COM_b06FwRodataLen = 0x58; +static u32 bnx2_COM_b06FwBssAddr = 0x08005860; static int bnx2_COM_b06FwBssLen = 0x88; -static u32 bnx2_COM_b06FwSbssAddr = 0x080045e0; +static u32 bnx2_COM_b06FwSbssAddr = 0x08005840; static int bnx2_COM_b06FwSbssLen = 0x1c; -static u32 bnx2_COM_b06FwText[(0x4594/4) + 1] = { - 0x0a000128, 0x00000000, 0x00000000, 0x0000000d, 0x636f6d20, 0x302e362e, - 0x39000000, 0x00060902, 0x00000000, 0x00000003, 0x00000014, 0x00000032, +static u32 bnx2_COM_b06FwText[(0x57bc/4) + 1] = { + 0x0a00022d, 0x00000000, 0x00000000, 0x0000000d, 0x636f6d20, 0x322e352e, + 0x38000000, 0x02050802, 0x00000000, 0x00000003, 0x00000014, 0x00000032, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000010, 0x000003e8, 0x0000ea60, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -79,70 +78,117 @@ static u32 bnx2_COM_b06FwText[(0x4594/4) + 1] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x10000003, 0x00000000, 0x0000000d, - 0x0000000d, 0x3c020800, 0x244245e0, 0x3c030800, 0x24634688, 0xac400000, - 0x0043202b, 0x1480fffd, 0x24420004, 0x3c1d0800, 0x37bd7ffc, 0x03a0f021, - 0x3c100800, 0x261004a0, 0x3c1c0800, 0x279c45e0, 0x0e0001f2, 0x00000000, - 0x0000000d, 0x27bdffe8, 0x3c1a8000, 0x3c020008, 0x0342d825, 0x3c036010, - 0xafbf0010, 0x8c655000, 0x3c020800, 0x24470ac8, 0x3c040800, 0x24864600, - 0x2402ff7f, 0x00a22824, 0x34a5380c, 0xac655000, 0x00002821, 0x24020037, - 0x24030c80, 0xaf420008, 0xaf430024, 0xacc70000, 0x24a50001, 0x2ca20016, - 0x1440fffc, 0x24c60004, 0x24844600, 0x3c020800, 0x24420ad4, 0x3c030800, - 0x246309d4, 0xac820004, 0x3c020800, 0x24420618, 0x3c050800, 0x24a50ca0, - 0xac82000c, 0x3c020800, 0x24423100, 0xac830008, 0x3c030800, 0x246325c8, - 0xac820014, 0x3c020800, 0x24422b0c, 0xac830018, 0xac83001c, 0x3c030800, - 0x24630adc, 0xac820024, 0x3c020800, 0x24423040, 0xac83002c, 0x3c030800, - 0x24633060, 0xac820030, 0x3c020800, 0x24422f6c, 0xac830034, 0x3c030800, - 0x24632c60, 0xac82003c, 0x3c020800, 0x24420b6c, 0xac850010, 0xac850020, - 0xac830040, 0x0e000bd6, 0xac820050, 0x8fbf0010, 0x03e00008, 0x27bd0018, - 0x27bdffe0, 0xafb00010, 0x27500100, 0xafbf0018, 0xafb10014, 0x9203000b, - 0x24020003, 0x1462005b, 0x96110008, 0x32220001, 0x10400009, 0x27430080, - 0x8e020000, 0x96040014, 0x000211c2, 0x00021040, 0x00621821, 0xa4640000, - 0x0a0001cb, 0x3c020800, 0x3c020800, 0x8c430020, 0x1060002a, 0x3c030800, - 0x0e001006, 0x00000000, 0x97420108, 0x8f850018, 0x9743010c, 0x3042003e, - 0x00021400, 0x00621825, 0xaca30000, 0x8f840018, 0x8f420100, 0xac820004, - 0x97430116, 0x9742010e, 0x8f840018, 0x00031c00, 0x00431025, 0xac820008, - 0x97430110, 0x97440112, 0x8f850018, 0x00031c00, 0x00832025, 0xaca4000c, - 0x97420114, 0x8f840018, 0x3042ffff, 0xac820010, 0x8f830018, 0xac600014, - 0x8f820018, 0x3c030800, 0xac400018, 0x9462466e, 0x8f840018, 0x3c032000, - 0x00431025, 0xac82001c, 0x0e001044, 0x24040001, 0x3c030800, 0x8c620040, - 0x24420001, 0xac620040, 0x3c020800, 0x8c430044, 0x32240004, 0x24630001, - 0x10800017, 0xac430044, 0x8f4202b8, 0x04430007, 0x8e020020, 0x3c040800, - 0x8c830060, 0x24020001, 0x24630001, 0x0a0001ed, 0xac830060, 0x3c060800, - 0x8cc4005c, 0xaf420280, 0x96030016, 0x00001021, 0xa7430284, 0x8e050004, - 0x24840001, 0x3c031000, 0xaf450288, 0xaf4302b8, 0x0a0001ed, 0xacc4005c, - 0x32220002, 0x0a0001ed, 0x0002102b, 0x3c026000, 0xac400808, 0x0000000d, - 0x00001021, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, - 0x27bdffc8, 0xafbf0034, 0xafbe0030, 0xafb7002c, 0xafb60028, 0xafb50024, - 0xafb40020, 0xafb3001c, 0xafb20018, 0xafb10014, 0x0e00013f, 0xafb00010, - 0x24110020, 0x24150030, 0x2794000c, 0x27930008, 0x3c124000, 0x3c1e0800, - 0x3c170800, 0x3c160800, 0x8f820004, 0x3c040800, 0x8c830020, 0x10430004, - 0x00000000, 0xaf830004, 0x0e00110b, 0x00000000, 0x8f500000, 0x32020007, - 0x1040fff5, 0x32020001, 0x1040002b, 0x32020002, 0x8f420100, 0xaf420020, - 0x8f430104, 0xaf4300a8, 0x9342010b, 0x93630000, 0x306300ff, 0x10710005, - 0x304400ff, 0x10750006, 0x2c820016, 0x0a000227, 0x00000000, 0xaf940000, - 0x0a000228, 0x2c820016, 0xaf930000, 0x0a000228, 0x00000000, 0xaf800000, - 0x14400005, 0x00041880, 0x0e0002b2, 0x00000000, 0x0a000234, 0x00000000, - 0x3c020800, 0x24424600, 0x00621821, 0x8c620000, 0x0040f809, 0x00000000, - 0x10400005, 0x8fc20034, 0x8f420104, 0x3c016020, 0xac220014, 0x8fc20034, - 0xaf520138, 0x24420001, 0xafc20034, 0x32020002, 0x10400019, 0x32020004, - 0x8f420140, 0xaf420020, 0x93630000, 0x306300ff, 0x10710005, 0x00000000, - 0x10750006, 0x00000000, 0x0a000250, 0x00000000, 0xaf940000, 0x0a000251, - 0x00000000, 0xaf930000, 0x0a000251, 0x00000000, 0xaf800000, 0x0e0008b9, - 0x00000000, 0x8ee20038, 0xaf520178, 0x24420001, 0xaee20038, 0x32020004, - 0x1040ffad, 0x00000000, 0x8f420180, 0xaf420020, 0x93630000, 0x306300ff, - 0x10710005, 0x00000000, 0x10750006, 0x00000000, 0x0a00026a, 0x00000000, - 0xaf940000, 0x0a00026b, 0x00000000, 0xaf930000, 0x0a00026b, 0x00000000, - 0xaf800000, 0x93620000, 0x14510004, 0x8ec2003c, 0x0e000835, 0x00000000, - 0x8ec2003c, 0xaf5201b8, 0x24420001, 0x0a000206, 0xaec2003c, 0x27bdffe8, - 0xafbf0010, 0x97420108, 0x24033000, 0x30447000, 0x10830012, 0x28823001, - 0x10400007, 0x24024000, 0x1080000b, 0x24022000, 0x1082001a, 0x24020001, - 0x0a000299, 0x00000000, 0x1082000c, 0x24025000, 0x1082000e, 0x00000000, - 0x0a000299, 0x00000000, 0x0000000d, 0x0a00029b, 0x00001021, 0x0e000300, - 0x00000000, 0x0a00029b, 0x00001021, 0x0e00048f, 0x00000000, 0x0a00029b, - 0x00001021, 0x0e000fdf, 0x00000000, 0x0a00029b, 0x00001021, 0x0000000d, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800, 0x24425840, + 0x3c030800, 0x246358e8, 0xac400000, 0x0043202b, 0x1480fffd, 0x24420004, + 0x3c1d0800, 0x37bd7ffc, 0x03a0f021, 0x3c100800, 0x261008b4, 0x3c1c0800, + 0x279c5840, 0x0e0002f7, 0x00000000, 0x0000000d, 0x27bdffe8, 0x3c1a8000, + 0x3c020008, 0x0342d825, 0x3c036010, 0xafbf0010, 0x8c655000, 0x3c020800, + 0x24470f30, 0x3c040800, 0x24865860, 0x2402ff7f, 0x00a22824, 0x34a5380c, + 0xac655000, 0x00002821, 0x24020037, 0x24030c80, 0xaf420008, 0xaf430024, + 0xacc70000, 0x24a50001, 0x2ca20016, 0x1440fffc, 0x24c60004, 0x24845860, + 0x3c020800, 0x24420f3c, 0x3c030800, 0x24630e2c, 0xac820004, 0x3c020800, + 0x24420a2c, 0x3c050800, 0x24a51268, 0xac82000c, 0x3c020800, 0x244243dc, + 0xac830008, 0x3c030800, 0x24633698, 0xac820014, 0x3c020800, 0x24423c24, + 0xac830018, 0xac83001c, 0x3c030800, 0x24630f44, 0xac820024, 0x3c020800, + 0x244243ac, 0xac83002c, 0x3c030800, 0x246343cc, 0xac820030, 0x3c020800, + 0x244242f0, 0xac830034, 0x3c030800, 0x24633d78, 0xac82003c, 0x3c020800, + 0x24420fd4, 0xac850010, 0xac850020, 0xac830040, 0x0e0010b7, 0xac820050, + 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe0, 0xafb00010, 0x27500100, + 0xafbf0018, 0xafb10014, 0x9203000b, 0x24020003, 0x1462005b, 0x96110008, + 0x32220001, 0x10400009, 0x27430080, 0x8e020000, 0x96040014, 0x000211c2, + 0x00021040, 0x00621821, 0xa4640000, 0x0a0002d0, 0x3c020800, 0x3c020800, + 0x8c430020, 0x1060002a, 0x3c030800, 0x0e00148e, 0x00000000, 0x97420108, + 0x8f850018, 0x9743010c, 0x3042003e, 0x00021400, 0x00621825, 0xaca30000, + 0x8f840018, 0x8f420100, 0xac820004, 0x97430116, 0x9742010e, 0x8f840018, + 0x00031c00, 0x00431025, 0xac820008, 0x97430110, 0x97440112, 0x8f850018, + 0x00031c00, 0x00832025, 0xaca4000c, 0x97420114, 0x8f840018, 0x3042ffff, + 0xac820010, 0x8f830018, 0xac600014, 0x8f820018, 0x3c030800, 0xac400018, + 0x946258ce, 0x8f840018, 0x3c032000, 0x00431025, 0xac82001c, 0x0e0014cc, + 0x24040001, 0x3c030800, 0x8c620040, 0x24420001, 0xac620040, 0x3c020800, + 0x8c430044, 0x32240004, 0x24630001, 0x10800017, 0xac430044, 0x8f4202b8, + 0x04430007, 0x8e020020, 0x3c040800, 0x8c830060, 0x24020001, 0x24630001, + 0x0a0002f2, 0xac830060, 0x3c060800, 0x8cc4005c, 0xaf420280, 0x96030016, + 0x00001021, 0xa7430284, 0x8e050004, 0x24840001, 0x3c031000, 0xaf450288, + 0xaf4302b8, 0x0a0002f2, 0xacc4005c, 0x32220002, 0x0a0002f2, 0x0002102b, + 0x3c026000, 0xac400808, 0x0000000d, 0x00001021, 0x8fbf0018, 0x8fb10014, + 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffc8, 0xafbf0034, 0xafbe0030, + 0xafb7002c, 0xafb60028, 0xafb50024, 0xafb40020, 0xafb3001c, 0xafb20018, + 0xafb10014, 0x0e000244, 0xafb00010, 0x3c170800, 0x3c160800, 0x24110020, + 0x24150030, 0x2794000c, 0x27930008, 0x3c124000, 0x3c1e0800, 0x8f820004, + 0x3c040800, 0x8c830020, 0x10430005, 0x8ee200a4, 0xaf830004, 0x0e001593, + 0x00000000, 0x8ee200a4, 0x8ec300a0, 0x10430004, 0x26c400a0, 0x94820002, + 0xa742009e, 0xaee300a4, 0x8f500000, 0x32020007, 0x1040ffee, 0x32020001, + 0x1040002c, 0x32020002, 0x8f420100, 0xaf420020, 0x8f430104, 0xaf4300a8, + 0x9342010b, 0x93630000, 0x306300ff, 0x10710005, 0x304400ff, 0x10750006, + 0x2c820016, 0x0a000333, 0x00000000, 0xaf940000, 0x0a000334, 0x2c820016, + 0xaf930000, 0x0a000334, 0x00000000, 0xaf800000, 0x14400005, 0x00041880, + 0x0e0003cc, 0x00000000, 0x0a000340, 0x00000000, 0x3c020800, 0x24425860, + 0x00621821, 0x8c620000, 0x0040f809, 0x00000000, 0x10400005, 0x3c030800, + 0x8f420104, 0x3c016020, 0xac220014, 0x3c030800, 0x8c620034, 0xaf520138, + 0x24420001, 0xac620034, 0x32020002, 0x1040001a, 0x32020004, 0x8f420140, + 0xaf420020, 0x93630000, 0x306300ff, 0x10710005, 0x00000000, 0x10750006, + 0x00000000, 0x0a00035d, 0x00000000, 0xaf940000, 0x0a00035e, 0x00000000, + 0xaf930000, 0x0a00035e, 0x00000000, 0xaf800000, 0x0e000c7b, 0x00000000, + 0x3c040800, 0x8c820038, 0xaf520178, 0x24420001, 0xac820038, 0x32020004, + 0x1040ffa4, 0x00000000, 0x8f420180, 0xaf420020, 0x93630000, 0x306300ff, + 0x10710005, 0x00000000, 0x10750006, 0x00000000, 0x0a000378, 0x00000000, + 0xaf940000, 0x0a000379, 0x00000000, 0xaf930000, 0x0a000379, 0x00000000, + 0xaf800000, 0x8f430180, 0x24020f00, 0x14620005, 0x00000000, 0x8f420188, + 0xa742009c, 0x0a000387, 0x8fc2003c, 0x93620000, 0x14510004, 0x8fc2003c, + 0x0e000bad, 0x00000000, 0x8fc2003c, 0xaf5201b8, 0x24420001, 0x0a00030b, + 0xafc2003c, 0x27bdffe8, 0xafbf0010, 0x97420108, 0x24033000, 0x30447000, + 0x10830016, 0x28823001, 0x10400007, 0x24024000, 0x1080000b, 0x24022000, + 0x1082000c, 0x00000000, 0x0a0003b3, 0x00000000, 0x10820010, 0x24025000, + 0x10820012, 0x00000000, 0x0a0003b3, 0x00000000, 0x0000000d, 0x0a0003b5, + 0x00001021, 0x0e000442, 0x00000000, 0x0a0003b6, 0x8fbf0010, 0x0e00041a, + 0x00000000, 0x0a0003b5, 0x00001021, 0x0e000669, 0x00000000, 0x0a0003b5, + 0x00001021, 0x0e001467, 0x00000000, 0x0a0003b5, 0x00001021, 0x0000000d, 0x00001021, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x93620000, 0x24030020, - 0x304400ff, 0x10830005, 0x24020030, 0x10820007, 0x00000000, 0x0a0002af, + 0x304400ff, 0x10830005, 0x24020030, 0x10820007, 0x00000000, 0x0a0003c9, 0x00000000, 0x2782000c, 0xaf820000, 0x03e00008, 0x00000000, 0x27820008, 0xaf820000, 0x03e00008, 0x00000000, 0xaf800000, 0x03e00008, 0x00000000, 0x0000000d, 0x03e00008, 0x00001021, 0x03e00008, 0x00001021, 0x27440100, @@ -159,1000 +205,1716 @@ static u32 bnx2_COM_b06FwText[(0x4594/4) + 1] = { 0x3c020006, 0x34420001, 0xaf420030, 0x00000000, 0x00000000, 0x00000000, 0x8f420000, 0x30420010, 0x1040fffd, 0x00001021, 0x03e00008, 0x00000000, 0x3c020800, 0x8c430020, 0x27bdffe8, 0xafb00010, 0x27500100, 0x1060001e, - 0xafbf0014, 0x0e001006, 0x00000000, 0x8f830018, 0x8e020018, 0xac620000, + 0xafbf0014, 0x0e00148e, 0x00000000, 0x8f830018, 0x8e020018, 0xac620000, 0x8f840018, 0x9602000c, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, 0xac400014, 0x8f840018, - 0x3c026000, 0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x9464466e, - 0x8f850018, 0x00021400, 0x00441025, 0x24040001, 0x0e001044, 0xaca2001c, - 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdffc8, 0xafb3001c, - 0x00009821, 0xafb7002c, 0x0000b821, 0xafbe0030, 0x0000f021, 0xafb50024, - 0x27550100, 0xafbf0034, 0xafb60028, 0xafb40020, 0xafb20018, 0xafb10014, - 0xafb00010, 0x96a20008, 0x8f540100, 0x8eb20018, 0x30420001, 0x10400037, - 0x02a0b021, 0x8f630054, 0x2642ffff, 0x00431023, 0x18400006, 0x00000000, - 0x0000000d, 0x00000000, 0x24000128, 0x0a000372, 0x00002021, 0x8f62004c, - 0x02421023, 0x18400028, 0x00002021, 0x93650120, 0x93640121, 0x3c030800, - 0x8c62008c, 0x308400ff, 0x24420001, 0x30a500ff, 0x00803821, 0x1485000b, - 0xac62008c, 0x3c040800, 0x8c830090, 0x24630001, 0xac830090, 0x93620122, - 0x30420001, 0x00021023, 0x30420005, 0x0a000372, 0x34440004, 0x27660100, - 0x00041080, 0x00c21021, 0x8c430000, 0x02431823, 0x04600004, 0x24820001, - 0x30440007, 0x1485fff9, 0x00041080, 0x10870007, 0x3c030800, 0xa3640121, - 0x8c620094, 0x24040005, 0x24420001, 0x0a000372, 0xac620094, 0x24040004, - 0x00809821, 0x9362003f, 0x304400ff, 0x38830016, 0x2c630001, 0x38820010, - 0x2c420001, 0x00621825, 0x1460000c, 0x24020001, 0x38830008, 0x2c630001, - 0x38820014, 0x2c420001, 0x00621825, 0x14600005, 0x24020001, 0x24020012, - 0x14820002, 0x00001021, 0x24020001, 0x50400007, 0x8eb10020, 0x8ea20020, - 0x8f630040, 0x00408821, 0x00431023, 0x5c400001, 0x8f710040, 0x9343010b, - 0x24020004, 0x54620005, 0x36730080, 0x96a20008, 0x36730002, 0x24170001, - 0x305e0020, 0x2402fffb, 0x02628024, 0x1200002a, 0x3c030800, 0x8c620030, - 0x02021024, 0x10400026, 0x3c020800, 0x8c430020, 0x10600024, 0x32620004, - 0x0e001006, 0x00000000, 0x8f830018, 0x8f420100, 0xac620000, 0x8f840018, - 0x02201821, 0x32620002, 0xac900004, 0x8f840018, 0x50400001, 0x8ec30014, - 0xac830008, 0x8f830018, 0x8ec20020, 0xac62000c, 0x8f840018, 0x8f620040, - 0xac820010, 0x8f830018, 0x8ec20018, 0xac620014, 0x8f840018, 0x3c026000, - 0x8c434448, 0x3c020800, 0xac830018, 0x9443466e, 0x8f840018, 0x3c024010, - 0x00621825, 0xac83001c, 0x0e001044, 0x24040001, 0x32620004, 0x10400076, - 0x00003821, 0x3c029000, 0x34420001, 0x3c038000, 0x02821025, 0xa360007c, - 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620023, - 0x30420080, 0x10400011, 0x00000000, 0x8f65005c, 0x8f63004c, 0x9764003c, - 0x8f620064, 0x00a32823, 0x00852821, 0x00a2102b, 0x54400006, 0x3c023fff, - 0x93620023, 0x3042007f, 0xa3620023, 0xaf720064, 0x3c023fff, 0x0a0003f1, - 0x3442ffff, 0x8f62005c, 0x02421023, 0x04400011, 0x00000000, 0x8f65005c, - 0x8f630064, 0x9764003c, 0x3c023fff, 0x3442ffff, 0xaf720064, 0x00a32823, - 0x00852821, 0x0045102b, 0x10400004, 0x02451021, 0x3c053fff, 0x34a5ffff, - 0x02451021, 0xaf62005c, 0x24070001, 0xaf72004c, 0x8f620054, 0x16420005, + 0x3c026000, 0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x946458ce, + 0x8f850018, 0x00021400, 0x00441025, 0x24040001, 0x0e0014cc, 0xaca2001c, + 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafb00010, + 0x27500100, 0xafbf0014, 0x92020009, 0x14400003, 0x3c020800, 0x0a00046c, + 0x24020001, 0x8c430020, 0x1060001f, 0x00001021, 0x0e00148e, 0x00000000, + 0x8f830018, 0x8e020018, 0xac620000, 0x8f840018, 0x9602000c, 0xac820004, + 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, + 0x8f820018, 0xac400014, 0x8f840018, 0x3c026000, 0x8c434448, 0xac830018, + 0x96020008, 0x3c030800, 0x946458ce, 0x8f850018, 0x00021400, 0x00441025, + 0x24040001, 0x0e0014cc, 0xaca2001c, 0x00001021, 0x8fbf0014, 0x8fb00010, + 0x03e00008, 0x27bd0018, 0x3c0b0800, 0x8d6808b0, 0x3c070800, 0x24e700b0, + 0x00084900, 0x01271821, 0xac640000, 0x93620005, 0x97660008, 0x00e95021, + 0x93630023, 0x9364003f, 0x25080001, 0x00021600, 0x00063400, 0x00461025, + 0x00031a00, 0x00431025, 0x00822025, 0xad440004, 0x9362007e, 0x9366007f, + 0x8f630178, 0x9364007a, 0x00021600, 0x00063400, 0x00461025, 0x00031a00, + 0x00431025, 0x00822025, 0xad440008, 0x93620080, 0x9363007d, 0x3108007f, + 0x01403821, 0xad6808b0, 0x00021600, 0x00031c00, 0x00431025, 0x00451025, + 0x03e00008, 0xace2000c, 0x27bdffb8, 0xafb3002c, 0x00009821, 0xafbe0040, + 0x0000f021, 0xafb50034, 0x27550100, 0xafbf0044, 0xafb7003c, 0xafb60038, + 0xafb40030, 0xafb20028, 0xafb10024, 0xafb00020, 0xafa00010, 0xafa00014, + 0x96a20008, 0x8f540100, 0x8eb10018, 0x30420001, 0x10400037, 0x02a0b821, + 0x8f630054, 0x2622ffff, 0x00431023, 0x18400006, 0x00000000, 0x0000000d, + 0x00000000, 0x2400015c, 0x0a0004e5, 0x00002021, 0x8f62004c, 0x02221023, + 0x18400028, 0x00002021, 0x93650120, 0x93640121, 0x3c030800, 0x8c62008c, + 0x308400ff, 0x24420001, 0x30a500ff, 0x00803821, 0x1485000b, 0xac62008c, + 0x3c040800, 0x8c830090, 0x24630001, 0xac830090, 0x93620122, 0x30420001, + 0x00021023, 0x30420005, 0x0a0004e5, 0x34440004, 0x27660100, 0x00041080, + 0x00c21021, 0x8c430000, 0x02231823, 0x04600004, 0x24820001, 0x30440007, + 0x1485fff9, 0x00041080, 0x10870007, 0x3c030800, 0xa3640121, 0x8c620094, + 0x24040005, 0x24420001, 0x0a0004e5, 0xac620094, 0x24040004, 0x00809821, + 0x9362003f, 0x304400ff, 0x38830016, 0x2c630001, 0x38820010, 0x2c420001, + 0x00621825, 0x1460000c, 0x24020001, 0x38830008, 0x2c630001, 0x38820014, + 0x2c420001, 0x00621825, 0x14600005, 0x24020001, 0x24020012, 0x14820002, + 0x00001021, 0x24020001, 0x10400009, 0x00000000, 0x8ea20020, 0x8f630040, + 0x0040b021, 0x00431023, 0x5c400010, 0x8f760040, 0x0a000511, 0x00000000, + 0x9343010b, 0x24020004, 0x1462000a, 0x8eb60020, 0x8f630040, 0x3c021000, + 0x00761823, 0x0043102a, 0x10400004, 0x00000000, 0x0000000d, 0x00000000, + 0x240002fa, 0x9343010b, 0x24020004, 0x5462000b, 0x96a20008, 0x24020001, + 0xafa20010, 0x96a20008, 0x24030001, 0xafa30018, 0x8eb2001c, 0x36730002, + 0x30420020, 0x0a000526, 0xafa20014, 0x36730080, 0x30420002, 0x10400003, + 0xafa00018, 0x0a000526, 0x8eb2001c, 0x8eb20014, 0x2402fffb, 0x02628024, + 0x1200002a, 0x3c030800, 0x8c620030, 0x02021024, 0x10400026, 0x3c020800, + 0x8c430020, 0x10600024, 0x32620004, 0x0e00148e, 0x00000000, 0x8f830018, + 0x8f420100, 0xac620000, 0x8f840018, 0x02401821, 0x32620002, 0xac900004, + 0x8f840018, 0x54400001, 0x02c01821, 0xac830008, 0x8f830018, 0x8ee20020, + 0xac62000c, 0x8f840018, 0x8f620040, 0xac820010, 0x8f830018, 0x8ee20018, + 0xac620014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, + 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024010, 0x00621825, 0x0e0014cc, + 0xaca3001c, 0x32620004, 0x10400063, 0x00003821, 0x3c029000, 0x34420001, + 0x3c038000, 0x02821025, 0xa360007c, 0xaf420020, 0x8f420020, 0x00431024, + 0x1440fffd, 0x00000000, 0x93620023, 0x30420080, 0x10400011, 0x00000000, + 0x8f65005c, 0x8f63004c, 0x9764003c, 0x8f620064, 0x00a32823, 0x00852821, + 0x00a2102b, 0x54400006, 0x3c023fff, 0x93620023, 0x3042007f, 0xa3620023, + 0xaf710064, 0x3c023fff, 0x0a000580, 0x3442ffff, 0x8f62005c, 0x02221023, + 0x04400011, 0x00000000, 0x8f65005c, 0x8f630064, 0x9764003c, 0x3c023fff, + 0x3442ffff, 0xaf710064, 0x00a32823, 0x00852821, 0x0045102b, 0x10400004, + 0x02251021, 0x3c053fff, 0x34a5ffff, 0x02251021, 0xaf62005c, 0x24070001, + 0xaf71004c, 0x8f620054, 0x16220005, 0x00000000, 0x93620023, 0x30420040, + 0x10400017, 0x24020001, 0x9762006a, 0x00022880, 0x50a00001, 0x24050001, + 0x97630068, 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804, + 0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b, + 0x54600001, 0x00c02021, 0x8f420074, 0x2403fffe, 0x00832824, 0x00a21021, + 0xaf62000c, 0x93620082, 0x30420080, 0x50400001, 0xa3600081, 0x3c028000, + 0x34420001, 0x02821025, 0xaf420020, 0x9363007e, 0x9362007a, 0x10620004, + 0x00000000, 0x0e0013c4, 0x00000000, 0x00403821, 0x54e00001, 0x241e0001, + 0x8f700040, 0x8f620040, 0x14520003, 0x00521023, 0x0a0005bf, 0x00001021, + 0x28420001, 0x10400041, 0x8fa20010, 0x0e000fae, 0x02402021, 0xaf720040, + 0x9362003e, 0x30420001, 0x1440000b, 0x3c029000, 0x93620022, 0x24420001, + 0xa3620022, 0x93630022, 0x3c020800, 0x8c440098, 0x0064182b, 0x14600027, + 0x3c020800, 0x3c029000, 0x34420001, 0x02821025, 0xaf420020, 0x3c038000, + 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, + 0x34420001, 0xa362007d, 0x8f640074, 0x34630001, 0x02831825, 0xaf430020, + 0x04810006, 0x3c038000, 0x02802021, 0x0e000470, 0x24050273, 0x0a0005f2, + 0x24050001, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, + 0xaf5401c0, 0xa34201c4, 0xaf4301f8, 0x24050001, 0x24020001, 0xa7620012, + 0xa3600022, 0x0a0005fe, 0x2ca20001, 0x9743007a, 0x9444002a, 0x00002821, + 0x00641821, 0x3063fffe, 0xa7630012, 0x2ca20001, 0x00021023, 0x03c2f024, + 0x8fa20010, 0x10400004, 0x8fa30014, 0x0e0013c1, 0x00000000, 0x8fa30014, + 0x10600003, 0x00000000, 0x0e0010eb, 0x00000000, 0x13c0001f, 0x3c029000, + 0x34420001, 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, + 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074, + 0x34630001, 0x02831825, 0xaf430020, 0x04810006, 0x3c038000, 0x02802021, + 0x0e000470, 0x2405036c, 0x0a00062b, 0x8fa20018, 0x8f4201f8, 0x00431024, + 0x1440fffd, 0x24020002, 0x3c031000, 0xaf5401c0, 0xa34201c4, 0xaf4301f8, + 0x8fa20018, 0x5040002f, 0x96a20008, 0x8f620048, 0x8f630024, 0x00761821, + 0xaf630048, 0x9764003c, 0x00501023, 0x0044102b, 0x10400025, 0x3c029000, + 0x34420001, 0x3c040800, 0x8c830080, 0x8f450100, 0x3c068000, 0x24630001, + 0x00a21025, 0xac830080, 0xaf420020, 0x8f420020, 0x00461024, 0x1440fffd, + 0x00000000, 0x9362007d, 0x3c038000, 0x34420004, 0xa362007d, 0x8f640074, + 0x34630001, 0x00a31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00a02021, + 0x0e000470, 0x2405038a, 0x0a00065b, 0x96a20008, 0x8f4201f8, 0x00431024, + 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4501c0, 0xa34201c4, 0xaf4301f8, + 0x96a20008, 0x8fbf0044, 0x8fbe0040, 0x8fb7003c, 0x8fb60038, 0x8fb50034, + 0x8fb40030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020, 0x00021042, + 0x30420001, 0x03e00008, 0x27bd0048, 0x27bdffe0, 0xafbf0018, 0x97420108, + 0x24030019, 0x304400ff, 0x10830065, 0x2882001a, 0x1040001a, 0x2882000a, + 0x1040000f, 0x28820008, 0x10400040, 0x24020001, 0x1082003a, 0x28820002, + 0x50400005, 0x24020006, 0x10800032, 0x3c026000, 0x0a0006fb, 0x00000000, + 0x1082003d, 0x00000000, 0x0a0006fb, 0x00000000, 0x2402000b, 0x10820044, + 0x2882000b, 0x1440004b, 0x2402000e, 0x10820045, 0x00000000, 0x0a0006fb, + 0x00000000, 0x24020020, 0x10820062, 0x28820021, 0x1040000e, 0x2402001c, + 0x1082004c, 0x2882001d, 0x10400005, 0x2402001b, 0x10820043, 0x00000000, + 0x0a0006fb, 0x00000000, 0x2402001f, 0x10820050, 0x00000000, 0x0a0006fb, + 0x00000000, 0x240200c1, 0x10820042, 0x288200c2, 0x10400005, 0x24020080, + 0x10820021, 0x00000000, 0x0a0006fb, 0x00000000, 0x240200c2, 0x1082003d, + 0x240200c9, 0x50820049, 0xafa00010, 0x0a0006fb, 0x00000000, 0x0e001163, + 0xac400808, 0x0a0006fd, 0x8fbf0018, 0x3c026000, 0x8c444448, 0x3c030800, + 0xac640064, 0x0e001163, 0x00000000, 0x3c026000, 0x8c444448, 0x3c030800, + 0x0a0006fc, 0xac640068, 0x8f440100, 0x0e0006ff, 0x00000000, 0x3c026000, + 0x8c444448, 0x3c030800, 0x0a0006fc, 0xac64006c, 0x0e001191, 0x00000000, + 0x0a0006fd, 0x8fbf0018, 0x8f440100, 0x0e0011bb, 0x00000000, 0x0a0006fd, + 0x8fbf0018, 0x0e001202, 0x00000000, 0x0a0006fd, 0x8fbf0018, 0x0000000d, + 0x0a0006fd, 0x8fbf0018, 0x0e000826, 0x00000000, 0x0a0006fd, 0x8fbf0018, + 0x8f440100, 0x0e001264, 0x00000000, 0x0a0006fd, 0x8fbf0018, 0x0e00134e, + 0x00000000, 0x0a0006fd, 0x8fbf0018, 0x0e00087c, 0x27440100, 0x0a0006fd, + 0x8fbf0018, 0x8f640040, 0x0e000fae, 0x00000000, 0x0a0006fd, 0x8fbf0018, + 0x8f440100, 0x0e001059, 0x00000000, 0x0a0006fd, 0x8fbf0018, 0x0e001417, + 0x00000000, 0x0a0006fd, 0x8fbf0018, 0xafa00014, 0x8f440100, 0x8f450118, + 0x8f46011c, 0x0e001439, 0x8f470120, 0x0a0006fd, 0x8fbf0018, 0x0000000d, + 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0010, 0x9742010c, + 0x1440005e, 0x00803821, 0x3c029000, 0x34420001, 0x00e21025, 0xaf420020, + 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620023, + 0x30420010, 0x14400026, 0x3c030800, 0x8f630074, 0x3c027fff, 0x3442ffff, + 0x00621824, 0xaf630074, 0x93620005, 0x34420001, 0xa3620005, 0x8f63004c, + 0x8f620054, 0x10620021, 0x24040001, 0x9762006a, 0x00022880, 0x50a00001, + 0x24050001, 0x97630068, 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821, + 0x00852804, 0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050, + 0x00c4182b, 0x54600001, 0x00c02021, 0x8f420074, 0x2403fffe, 0x00832824, + 0x00a21021, 0xaf62000c, 0x0a00073d, 0x24040001, 0x8c6200a8, 0x00002021, + 0x24420001, 0xac6200a8, 0x0000000d, 0x00000000, 0x2400044d, 0x3c028000, + 0x34420001, 0x00e21025, 0xaf420020, 0x1080001f, 0x3c029000, 0x34420001, + 0x00e21025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, + 0x00000000, 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074, 0x34630001, + 0x00e31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00e02021, 0x0e000470, + 0x24050455, 0x0a000761, 0x00000000, 0x8f4201f8, 0x00431024, 0x1440fffd, + 0x24020002, 0x3c031000, 0xaf4701c0, 0xa34201c4, 0xaf4301f8, 0x0e001163, + 0x00000000, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffd8, 0xafbf0024, + 0xafb40020, 0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, 0x93630005, + 0x00809821, 0x24020030, 0x30630030, 0x146200ac, 0x00a0a021, 0x3c020800, + 0x8c430020, 0x106000a6, 0x00000000, 0x0e00148e, 0x00000000, 0x8f830018, + 0xac730000, 0x936200c4, 0x30420002, 0x10400004, 0x24020001, 0x8f830018, + 0x0a000784, 0x00000000, 0x8f830018, 0x24020003, 0xac620004, 0x8f6200dc, + 0x8f630040, 0x00431023, 0x18400004, 0x00000000, 0x0000000d, 0x00000000, + 0x24000509, 0x8f840018, 0x8f6200dc, 0xac820008, 0x8f830018, 0xac60000c, + 0x8f820018, 0xac400010, 0x8f830018, 0x8f62004c, 0x3c100800, 0xac620014, + 0x8f850018, 0x3c026000, 0x8c434448, 0x261258c0, 0x00002021, 0xaca30018, + 0x9642000e, 0x8f850018, 0x3c034010, 0x00431025, 0x0e0014cc, 0xaca2001c, + 0x8f830018, 0xac730000, 0x9362003e, 0x9363003f, 0x8f840018, 0x00021200, + 0x00621825, 0xac830004, 0x93620081, 0x93630082, 0x8f840018, 0x00021600, + 0x00031c00, 0x00431025, 0xac820008, 0x8f830018, 0x8f620040, 0xac62000c, + 0x8f840018, 0x8f620048, 0xac820010, 0x8f71004c, 0x8f820018, 0xac510014, + 0x8f620050, 0x8f850018, 0x00401821, 0x02221023, 0x5c400001, 0x02201821, + 0x00002021, 0xaca30018, 0x9642000e, 0x8f850018, 0x3c03c00b, 0x00431025, + 0x0e0014cc, 0xaca2001c, 0x8f620054, 0x8f840018, 0x00401821, 0x02221023, + 0x5c400001, 0x02201821, 0xac830000, 0x8f840018, 0x8f630058, 0xac830004, + 0x93620023, 0x30420010, 0x10400004, 0x00000000, 0x8f830018, 0x0a0007dd, + 0x8f620148, 0x8f830018, 0x8f62005c, 0xac620008, 0x8f830018, 0x8f620060, + 0xac62000c, 0x8f840018, 0x8f620064, 0xac820010, 0x97630068, 0x9762006a, + 0x8f840018, 0x00031c00, 0x00431025, 0xac820014, 0x8f850018, 0x00002021, + 0x2402ffff, 0x260358c0, 0xaca20018, 0x9462000e, 0x8f850018, 0x3c03c00c, + 0x00431025, 0x0e0014cc, 0xaca2001c, 0x8f840018, 0x8f630018, 0xac830000, + 0x936200c4, 0x30420002, 0x10400006, 0x00000000, 0x976200c8, 0x8f830018, + 0x3042ffff, 0x0a000803, 0xac620004, 0x8f820018, 0xac400004, 0x8f830018, + 0x8f62006c, 0xac620008, 0x8f840018, 0x8f6200dc, 0xac82000c, 0x8f830018, + 0xac600010, 0x93620005, 0x8f830018, 0x00021600, 0x00541025, 0xac620014, + 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x260258c0, 0xaca30018, + 0x9443000e, 0x8f850018, 0x3c02400d, 0x00621825, 0x0e0014cc, 0xaca3001c, + 0x0e00122e, 0x02602021, 0x8fbf0024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, + 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0028, 0x27bdffe0, 0xafb00010, + 0x27500100, 0xafbf0018, 0xafb10014, 0x9603000c, 0x240200c1, 0x54620024, + 0x8e040000, 0x3c029000, 0x8f450100, 0x34420001, 0x3c038000, 0x00a21025, + 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x9362007d, + 0x3c038000, 0x34420004, 0xa362007d, 0x8f640074, 0x34630001, 0x00a31825, + 0xaf430020, 0x04810006, 0x3c038000, 0x00a02021, 0x0e000470, 0x240505b2, + 0x0a000878, 0x8fbf0018, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, + 0x3c031000, 0xaf4501c0, 0xa34201c4, 0xaf4301f8, 0x0a000878, 0x8fbf0018, + 0x8f65004c, 0x24060001, 0x0e0012a3, 0x240705be, 0x3c020800, 0x8c430020, + 0x9611000c, 0x1060001d, 0x8e100000, 0x0e00148e, 0x00000000, 0x8f820018, + 0xac500000, 0x8f840018, 0x00111400, 0xac820004, 0x8f830018, 0xac600008, + 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f840018, 0x240205c1, + 0xac820014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, + 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024019, 0x00621825, 0x0e0014cc, + 0xaca3001c, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, + 0x27bdffb0, 0xafb5003c, 0x0000a821, 0xafbe0048, 0x0000f021, 0xafb70044, + 0x0000b821, 0xafb30034, 0x00009821, 0xafb60040, 0x0080b021, 0xafbf004c, + 0xafb40038, 0xafb20030, 0xafb1002c, 0xafb00028, 0xafa00010, 0x8f620040, + 0x8ec30014, 0x96d1000c, 0x00431023, 0x04410025, 0x8ed40000, 0x32220401, + 0x1040030c, 0x3c029000, 0x34420001, 0x02821025, 0xaf420020, 0x3c038000, + 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, + 0x34420004, 0xa362007d, 0x8f640074, 0x34630001, 0x02831825, 0xaf430020, + 0x04810006, 0x3c038000, 0x02802021, 0x0e000470, 0x24050664, 0x0a000ba2, + 0x8fbf004c, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, + 0xaf5401c0, 0xa34201c4, 0xaf4301f8, 0x0a000ba2, 0x8fbf004c, 0x32220010, + 0x1040006b, 0x00003021, 0x9362003f, 0x92c6000f, 0x304500ff, 0x24c3fff8, + 0x2c62000f, 0x10400057, 0x3c020800, 0x244257c0, 0x00031880, 0x00621821, + 0x8c640000, 0x00800008, 0x00000000, 0x38a20012, 0x0a000924, 0x0002a82b, + 0x2402000e, 0x14a20004, 0x2402000c, 0x24150001, 0x0a000924, 0x24060010, + 0x10a20049, 0x38a30010, 0x2c630001, 0x38a20016, 0x2c420001, 0x00621825, + 0x1460004d, 0x0000a821, 0x24020014, 0x10a2004a, 0x00000000, 0x0000000d, + 0x00000000, 0x2400069c, 0x0a000924, 0x0000a821, 0x24020016, 0x14a20005, + 0x2402000c, 0x24150001, 0x24060010, 0x0a000924, 0x3231fffd, 0x10a20032, + 0x38a30010, 0x2c630001, 0x38a2000e, 0x2c420001, 0x00621825, 0x14600036, + 0x0000a821, 0x24020014, 0x14a20003, 0x24150001, 0x0a000924, 0x24060012, + 0x0000000d, 0x00000000, 0x240006bc, 0x0a000924, 0x0000a821, 0x2402000e, + 0x14a20004, 0x24020016, 0x24150001, 0x0a000924, 0x3231fffb, 0x14a20004, + 0x24020014, 0x24150001, 0x0a000924, 0x3231fffd, 0x54a20013, 0x92c2000e, + 0x24150001, 0x24060012, 0x0a000924, 0x3231fffd, 0x2402000c, 0x54a2000c, + 0x92c2000e, 0x92c3000e, 0x2402000a, 0x10620005, 0x24150001, 0x0000000d, + 0x00000000, 0x240006e8, 0x24150001, 0x0a000924, 0x24060014, 0x92c2000e, + 0x14a20003, 0x00000000, 0x0a000924, 0x24150001, 0x10a6ffc1, 0x24020012, + 0x10a20005, 0x0000a821, 0x0000000d, 0x00000000, 0x24000704, 0x0000a821, + 0x12a00022, 0x32220004, 0x10400002, 0x24020001, 0xafa20010, 0x32230102, + 0x24020002, 0x1462000f, 0x00000000, 0x92c2000a, 0x30420020, 0x1440000b, + 0x00000000, 0x8f630048, 0x8f620040, 0x14620004, 0x00000000, 0x8f620048, + 0x24420001, 0xaf620048, 0x8f620040, 0x24420001, 0xaf620040, 0xa366003f, + 0x38c30012, 0x2c630001, 0x38c20010, 0x2c420001, 0x00621825, 0x10600005, + 0x3c030800, 0x8c620074, 0x24420001, 0x0e00140d, 0xac620074, 0x32220040, + 0x32230020, 0xafa30020, 0x32230080, 0xafa30024, 0x32230001, 0xafa30018, + 0x32230008, 0xafa3001c, 0x32230100, 0x104000c4, 0xafa30014, 0x8ec60010, + 0x8f630054, 0x24c2ffff, 0x00431023, 0x18400006, 0x00000000, 0x0000000d, + 0x00000000, 0x2400015c, 0x0a000989, 0x00009021, 0x8f62004c, 0x00c21023, + 0x18400028, 0x00009021, 0x93650120, 0x93640121, 0x3c030800, 0x8c62008c, + 0x308400ff, 0x24420001, 0x30a500ff, 0x00804021, 0x1485000b, 0xac62008c, + 0x3c040800, 0x8c830090, 0x24630001, 0xac830090, 0x93620122, 0x30420001, + 0x00021023, 0x30420005, 0x0a000989, 0x34520004, 0x27670100, 0x00041080, + 0x00e21021, 0x8c430000, 0x00c31823, 0x04600004, 0x24820001, 0x30440007, + 0x1485fff9, 0x00041080, 0x10880007, 0x3c030800, 0xa3640121, 0x8c620094, + 0x24120005, 0x24420001, 0x0a000989, 0xac620094, 0x24120004, 0x32420001, + 0x10400021, 0x3c020800, 0x8c430020, 0x8ed00000, 0x1060001c, 0x8ed30010, + 0x0e00148e, 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x24020001, + 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, + 0xac600010, 0x8f820018, 0xac530014, 0x8f850018, 0x3c026000, 0x8c434448, + 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024010, + 0x00621825, 0x0e0014cc, 0xaca3001c, 0x24130001, 0x32420004, 0x10400068, + 0x00003821, 0x3c029000, 0x8ec60010, 0x34420001, 0x3c038000, 0x02821025, + 0xa360007c, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, + 0x93620023, 0x30420080, 0x10400011, 0x00000000, 0x8f65005c, 0x8f63004c, + 0x9764003c, 0x8f620064, 0x00a32823, 0x00852821, 0x00a2102b, 0x54400006, + 0x3c023fff, 0x93620023, 0x3042007f, 0xa3620023, 0xaf660064, 0x3c023fff, + 0x0a0009da, 0x3442ffff, 0x8f62005c, 0x00c21023, 0x04400011, 0x00000000, + 0x8f65005c, 0x8f630064, 0x9764003c, 0x3c023fff, 0x3442ffff, 0xaf660064, + 0x00a32823, 0x00852821, 0x0045102b, 0x10400004, 0x00c51021, 0x3c053fff, + 0x34a5ffff, 0x00c51021, 0xaf62005c, 0x24070001, 0xaf66004c, 0x8fa20010, + 0x10400003, 0x00000000, 0xaf660050, 0xaf660054, 0x8f620054, 0x14c20005, 0x00000000, 0x93620023, 0x30420040, 0x10400017, 0x24020001, 0x9762006a, 0x00022880, 0x50a00001, 0x24050001, 0x97630068, 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001, 0x00c02021, 0x8f420074, - 0x2403fffe, 0x00832824, 0x00a21021, 0xaf62000c, 0x3c028000, 0x34420001, - 0x02821025, 0xa3600081, 0xaf420020, 0x9363007e, 0x9362007a, 0x10620004, - 0x00000000, 0x0e000f2a, 0x00000000, 0x00403821, 0x10e00017, 0x3c029000, + 0x2403fffe, 0x00832824, 0x00a21021, 0xaf62000c, 0x93620082, 0x30420080, + 0x50400001, 0xa3600081, 0x3c028000, 0x34420001, 0x02821025, 0xaf420020, + 0x9363007e, 0x9362007a, 0x10620005, 0x00e0b821, 0x0e0013c4, 0x00000000, + 0x00403821, 0x00e0b821, 0x8fa30020, 0x10600009, 0x8fa20010, 0x8ec20018, + 0xaf620018, 0x8ec3001c, 0xaf63001c, 0x8ec20020, 0x24170001, 0xaf620058, + 0x8fa20010, 0x10400057, 0x8fa30024, 0x93620023, 0x30420040, 0x10400053, + 0x00000000, 0x16600021, 0x3c120800, 0x8e420020, 0x8f70004c, 0x1040001e, + 0x24130001, 0x0e00148e, 0x00000000, 0x8f820018, 0xac540000, 0x8f840018, + 0x24020001, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, + 0x8f830018, 0xac600010, 0x8f820018, 0xac500014, 0x8f850018, 0x3c026000, + 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, + 0x3c024010, 0x00621825, 0xaca3001c, 0x0e0014cc, 0x24130001, 0x8e420020, + 0x1040001c, 0x8ed00000, 0x0e00148e, 0x00000000, 0x8f820018, 0xac500000, + 0x8f830018, 0xac600004, 0x8f820018, 0xac400008, 0x8f830018, 0xac60000c, + 0x8f820018, 0xac400010, 0x8f830018, 0x24020798, 0xac620014, 0x8f850018, + 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, + 0x8f850018, 0x3c024019, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x3c029000, 0x34420001, 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, - 0x1440fffd, 0x3c028000, 0x9363007d, 0x34420001, 0x3c048000, 0x02821025, - 0xa363007d, 0xaf420020, 0x8f4201f8, 0x00441024, 0x1440fffd, 0x24020002, - 0x3c031000, 0xaf5401c0, 0xa34201c4, 0xaf4301f8, 0x8ea30014, 0x8f620040, - 0x14430003, 0x00431023, 0x0a000443, 0x00001021, 0x28420001, 0x10400034, - 0x00000000, 0x8f620040, 0xaf630040, 0x9362003e, 0x30420001, 0x1440000b, - 0x3c029000, 0x93620022, 0x24420001, 0xa3620022, 0x93630022, 0x3c020800, - 0x8c440098, 0x0064182b, 0x1460001e, 0x3c020800, 0x3c029000, 0x34420001, + 0x1440fffd, 0x24020001, 0xaf62000c, 0x93630023, 0x3c028000, 0x34420001, + 0x02821025, 0x306300bf, 0xa3630023, 0xaf420020, 0x8fa30024, 0x10600012, + 0x8fa30018, 0x9362007c, 0x24420001, 0xa362007c, 0x9363007e, 0x9362007a, + 0x1462000b, 0x8fa30018, 0x9362007c, 0x3c030800, 0x8c640024, 0x0044102b, + 0x14400005, 0x8fa30018, 0x0e0013c4, 0x00000000, 0x02e2b825, 0x8fa30018, + 0x3062ffff, 0x10400003, 0x32220200, 0x0a000a94, 0x241e0004, 0x10400003, + 0x00000000, 0x241e0040, 0x24170001, 0x12a000d0, 0x32220002, 0x104000cf, + 0x8fa2001c, 0x92c2000a, 0x30420002, 0x5040003b, 0x92c2000a, 0x93620023, + 0x30420008, 0x54400037, 0x92c2000a, 0x3c020800, 0x8c430020, 0x10600023, + 0x3c029000, 0x0e00148e, 0x00000000, 0x8f840018, 0x8ec30000, 0xac830000, + 0x92c2000a, 0x8f830018, 0x00021600, 0xac620004, 0x8f840018, 0x8f620040, + 0xac820008, 0x8f850018, 0x8f63004c, 0xaca3000c, 0x9362003f, 0x8f840018, + 0x304200ff, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f850018, + 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, + 0x3c02401a, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x3c029000, 0x34420001, 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, - 0x00000000, 0x3c038000, 0x9362007d, 0x34630001, 0x3c048000, 0x02831825, - 0x34420001, 0xa362007d, 0xaf430020, 0x8f4201f8, 0x00441024, 0x1440fffd, - 0x24020002, 0x3c031000, 0xaf5401c0, 0xa34201c4, 0x24020001, 0xaf4301f8, - 0xa7620012, 0x0a000476, 0xa3600022, 0x9743007a, 0x9444002a, 0x00641821, - 0x3063fffe, 0xa7630012, 0x0e000b68, 0x00000000, 0x12e00003, 0x00000000, - 0x0e000f27, 0x00000000, 0x53c00004, 0x96a20008, 0x0e000c10, 0x00000000, - 0x96a20008, 0x8fbf0034, 0x8fbe0030, 0x8fb7002c, 0x8fb60028, 0x8fb50024, - 0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x00021042, - 0x30420001, 0x03e00008, 0x27bd0038, 0x27bdffe8, 0xafbf0010, 0x97420108, - 0x2403000b, 0x304400ff, 0x1083004e, 0x2882000c, 0x10400011, 0x24020006, - 0x1082003e, 0x28820007, 0x10400007, 0x28820008, 0x1080002b, 0x24020001, - 0x1082002e, 0x3c026000, 0x0a000504, 0x00000000, 0x14400061, 0x2882000a, - 0x1440002b, 0x00000000, 0x0a0004ec, 0x00000000, 0x2402001c, 0x1082004e, - 0x2882001d, 0x1040000e, 0x24020019, 0x10820041, 0x2882001a, 0x10400005, - 0x2402000e, 0x10820036, 0x00000000, 0x0a000504, 0x00000000, 0x2402001b, - 0x1082003c, 0x00000000, 0x0a000504, 0x00000000, 0x240200c1, 0x10820040, - 0x288200c2, 0x10400005, 0x24020080, 0x1082001f, 0x00000000, 0x0a000504, - 0x00000000, 0x240200c2, 0x1082003b, 0x00000000, 0x0a000504, 0x00000000, - 0x3c026000, 0x0e000c7d, 0xac400808, 0x0a000506, 0x8fbf0010, 0x8c444448, - 0x3c030800, 0xac640064, 0x0e000c7d, 0x00000000, 0x3c026000, 0x8c444448, - 0x3c030800, 0x0a000505, 0xac640068, 0x8f440100, 0x0e000508, 0x00000000, - 0x3c026000, 0x8c444448, 0x3c030800, 0x0a000505, 0xac64006c, 0x0e000cab, - 0x00000000, 0x0a000506, 0x8fbf0010, 0x8f440100, 0x0e000cd5, 0x00000000, - 0x0a000506, 0x8fbf0010, 0x0e000d1c, 0x00000000, 0x0a000506, 0x8fbf0010, - 0x0000000d, 0x0a000506, 0x8fbf0010, 0x0e0005d7, 0x00000000, 0x0a000506, - 0x8fbf0010, 0x8f440100, 0x0e000d7e, 0x00000000, 0x0a000506, 0x8fbf0010, - 0x0e000e95, 0x00000000, 0x0a000506, 0x8fbf0010, 0x0e000626, 0x00000000, - 0x0a000506, 0x8fbf0010, 0x0e000b68, 0x00000000, 0x0a000506, 0x8fbf0010, - 0x0000000d, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0x3c029000, - 0x34420001, 0xafb00010, 0x00808021, 0x02021025, 0x3c038000, 0xafbf0014, - 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620005, - 0x34420001, 0xa3620005, 0x8f63004c, 0x8f620054, 0x10620019, 0x3c028000, - 0x9762006a, 0x00022880, 0x50a00001, 0x24050001, 0x97630068, 0x93640081, - 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b, 0x54400001, - 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001, 0x00c02021, - 0x8f420074, 0x2403fffe, 0x00832824, 0x00a21021, 0xaf62000c, 0x3c028000, - 0x34420001, 0x02021025, 0x0e000c7d, 0xaf420020, 0x3c029000, 0x34420001, - 0x3c038000, 0x02021025, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, - 0x3c028000, 0x9363007d, 0x34420001, 0x3c048000, 0x02021025, 0xa363007d, - 0xaf420020, 0x8f4201f8, 0x00441024, 0x1440fffd, 0x8fbf0014, 0xaf5001c0, - 0x8fb00010, 0x24020002, 0x3c031000, 0xa34201c4, 0xaf4301f8, 0x03e00008, - 0x27bd0018, 0x27bdffd8, 0xafbf0020, 0xafb3001c, 0xafb20018, 0xafb10014, - 0xafb00010, 0x93630005, 0x00809021, 0x24020030, 0x30630030, 0x14620072, - 0x00a09821, 0x3c020800, 0x8c430020, 0x1060006c, 0x00000000, 0x0e001006, - 0x00000000, 0x8f820018, 0xac520000, 0x9363003e, 0x9362003f, 0x8f840018, - 0x00031a00, 0x00431025, 0xac820004, 0x93630081, 0x93620082, 0x8f850018, - 0x00031e00, 0x00021400, 0x00621825, 0xaca30008, 0x8f840018, 0x8f620040, - 0xac82000c, 0x8f830018, 0x8f620048, 0xac620010, 0x8f840018, 0x8f62004c, - 0x3c110800, 0xac820014, 0x8f830018, 0x8f620050, 0x26304660, 0x00002021, - 0xac620018, 0x9602000e, 0x8f850018, 0x3c03c00b, 0x00431025, 0x0e001044, - 0xaca2001c, 0x8f830018, 0x8f620054, 0xac620000, 0x8f840018, 0x8f620058, - 0xac820004, 0x8f830018, 0x8f62005c, 0xac620008, 0x8f840018, 0x8f620060, - 0xac82000c, 0x8f850018, 0x8f620064, 0xaca20010, 0x97630068, 0x9762006a, - 0x8f840018, 0x00031c00, 0x00431025, 0xac820014, 0x8f830018, 0x00002021, - 0xac600018, 0x9602000e, 0x8f850018, 0x3c03c00c, 0x00431025, 0x0e001044, - 0xaca2001c, 0x8f840018, 0x8f630018, 0xac830000, 0x936200c4, 0x30420002, - 0x10400006, 0x00000000, 0x976200c8, 0x8f830018, 0x3042ffff, 0x0a0005b5, - 0xac620004, 0x8f820018, 0xac400004, 0x8f830018, 0x8f62006c, 0xac620008, - 0x8f840018, 0x8f6200dc, 0xac82000c, 0x8f830018, 0xac600010, 0x93620005, - 0x8f830018, 0x00021600, 0x00531025, 0xac620014, 0x8f850018, 0x3c026000, - 0x8c434448, 0x24040001, 0x26224660, 0xaca30018, 0x9443000e, 0x8f850018, - 0x3c02400d, 0x00621825, 0x0e001044, 0xaca3001c, 0x0e000d48, 0x02402021, - 0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, - 0x27bd0028, 0x27bdffe0, 0xafb00010, 0x27500100, 0xafbf0018, 0xafb10014, - 0x9603000c, 0x240200c1, 0x5462001d, 0x8e040000, 0x3c029000, 0x8f440100, - 0x34420001, 0x3c038000, 0x00821025, 0xaf420020, 0x8f420020, 0x00431024, - 0x1440fffd, 0x00000000, 0x3c038000, 0x9362007d, 0x34630001, 0x3c058000, - 0x00831825, 0x34420004, 0xa362007d, 0xaf430020, 0x8f4201f8, 0x00451024, - 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4401c0, 0xa34201c4, 0xaf4301f8, - 0x0a000622, 0x8fbf0018, 0x8f65004c, 0x24060001, 0x0e000db5, 0x2407049f, - 0x3c020800, 0x8c430020, 0x9611000c, 0x1060001d, 0x8e100000, 0x0e001006, - 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x00111400, 0xac820004, - 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, - 0x8f840018, 0x240204a2, 0xac820014, 0x8f850018, 0x3c026000, 0x8c434448, - 0x24040001, 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018, 0x3c024019, - 0x00621825, 0x0e001044, 0xaca3001c, 0x8fbf0018, 0x8fb10014, 0x8fb00010, - 0x03e00008, 0x27bd0020, 0x27bdffb0, 0xafb1002c, 0x27510100, 0xafbf004c, - 0xafbe0048, 0xafb70044, 0xafb60040, 0xafb5003c, 0xafb40038, 0xafb30034, - 0xafb20030, 0xafb00028, 0x8e350000, 0x9634000c, 0x3c026000, 0x8c434448, - 0x0000f021, 0xaf630170, 0x8f620040, 0x8e230014, 0x0000b821, 0x00431023, - 0x044001ec, 0x0000b021, 0x32820010, 0x1040002e, 0x3c026000, 0x9363003f, - 0x9222000e, 0x10430006, 0x2402000c, 0x9223000f, 0x10620003, 0x24020014, - 0x14620025, 0x3c026000, 0x32820004, 0x10400007, 0x241e0001, 0x8f620050, - 0x24420001, 0xaf620050, 0x8f630054, 0x24630001, 0xaf630054, 0x32830102, - 0x24020002, 0x5462000d, 0x9222000f, 0x8f620040, 0x24420001, 0xaf620040, - 0x8f630048, 0x8f620040, 0x24630001, 0x54620005, 0x9222000f, 0x8f620048, - 0x24420001, 0xaf620048, 0x9222000f, 0xa362003f, 0x9223000f, 0x24020012, - 0x14620007, 0x3c026000, 0x3c030800, 0x8c620074, 0x24420001, 0x0e000f6e, - 0xac620074, 0x3c026000, 0x8c434448, 0x32820040, 0xaf630174, 0x32830020, - 0xafa30010, 0x32830080, 0xafa30014, 0x32830001, 0xafa3001c, 0x32830008, - 0xafa30020, 0x32830100, 0x104000bb, 0xafa30018, 0x8e260010, 0x8f630054, - 0x24c2ffff, 0x00431023, 0x18400006, 0x00000000, 0x0000000d, 0x00000000, - 0x24000128, 0x0a0006b2, 0x00009021, 0x8f62004c, 0x00c21023, 0x18400028, - 0x00009021, 0x93650120, 0x93640121, 0x3c030800, 0x8c62008c, 0x308400ff, - 0x24420001, 0x30a500ff, 0x00804021, 0x1485000b, 0xac62008c, 0x3c040800, - 0x8c830090, 0x24630001, 0xac830090, 0x93620122, 0x30420001, 0x00021023, - 0x30420005, 0x0a0006b2, 0x34520004, 0x27670100, 0x00041080, 0x00e21021, - 0x8c430000, 0x00c31823, 0x04600004, 0x24820001, 0x30440007, 0x1485fff9, - 0x00041080, 0x10880007, 0x3c030800, 0xa3640121, 0x8c620094, 0x24120005, - 0x24420001, 0x0a0006b2, 0xac620094, 0x24120004, 0x32420001, 0x10400020, - 0x3c020800, 0x8c430020, 0x8e300000, 0x1060001c, 0x8e330010, 0x0e001006, - 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x24020001, 0xac820004, - 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, - 0x8f820018, 0xac530014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, - 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018, 0x3c024010, 0x00621825, - 0x0e001044, 0xaca3001c, 0x32420004, 0x10400060, 0x00003821, 0x3c029000, - 0x8e260010, 0x34420001, 0x3c038000, 0x02a21025, 0xa360007c, 0xaf420020, - 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620023, 0x30420080, - 0x10400011, 0x00000000, 0x8f65005c, 0x8f63004c, 0x9764003c, 0x8f620064, - 0x00a32823, 0x00852821, 0x00a2102b, 0x54400006, 0x3c023fff, 0x93620023, - 0x3042007f, 0xa3620023, 0xaf660064, 0x3c023fff, 0x0a000702, 0x3442ffff, - 0x8f62005c, 0x00c21023, 0x04400011, 0x00000000, 0x8f65005c, 0x8f630064, - 0x9764003c, 0x3c023fff, 0x3442ffff, 0xaf660064, 0x00a32823, 0x00852821, - 0x0045102b, 0x10400004, 0x00c51021, 0x3c053fff, 0x34a5ffff, 0x00c51021, - 0xaf62005c, 0x24070001, 0xaf66004c, 0x8f620054, 0x14c20005, 0x00000000, - 0x93620023, 0x30420040, 0x10400017, 0x24020001, 0x9762006a, 0x00022880, - 0x50a00001, 0x24050001, 0x97630068, 0x93640081, 0x3c020800, 0x8c46004c, - 0x00652821, 0x00852804, 0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800, - 0x8c440050, 0x00c4182b, 0x54600001, 0x00c02021, 0x8f420074, 0x2403fffe, - 0x00832824, 0x00a21021, 0xaf62000c, 0x3c028000, 0x34420001, 0x02a21025, - 0xa3600081, 0xaf420020, 0x9363007e, 0x9362007a, 0x10620005, 0x00e0b021, - 0x0e000f2a, 0x00000000, 0x00403821, 0x00e0b021, 0x8fa20010, 0x10400008, - 0x00000000, 0x8e220018, 0xaf620018, 0x8e23001c, 0xaf63001c, 0x8e220020, - 0x24160001, 0xaf620058, 0x13c00036, 0x32820004, 0x10400035, 0x8fa30014, - 0x93620023, 0x30420040, 0x10400031, 0x3c020800, 0x8c430020, 0x1060001c, - 0x8e300000, 0x0e001006, 0x00000000, 0x8f820018, 0xac500000, 0x8f830018, - 0xac600004, 0x8f820018, 0xac400008, 0x8f830018, 0xac60000c, 0x8f820018, - 0xac400010, 0x8f830018, 0x24020587, 0xac620014, 0x8f850018, 0x3c026000, - 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018, - 0x3c024019, 0x00621825, 0x0e001044, 0xaca3001c, 0x3c029000, 0x34420001, - 0x02a21025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, - 0x24020001, 0xaf62000c, 0x93630023, 0x3c028000, 0x34420001, 0x02a21025, - 0x306300bf, 0xa3630023, 0xaf420020, 0x8fa30014, 0x10600012, 0x8fa3001c, - 0x9362007c, 0x24420001, 0xa362007c, 0x9363007e, 0x9362007a, 0x1462000b, - 0x8fa3001c, 0x9362007c, 0x3c030800, 0x8c640024, 0x0044102b, 0x14400005, - 0x8fa3001c, 0x0e000f2a, 0x00000000, 0x02c2b025, 0x8fa3001c, 0x3062ffff, - 0x10400003, 0x32820200, 0x0a000793, 0x24170004, 0x10400003, 0x00000000, - 0x24170040, 0x24160001, 0x13c0005d, 0x32820002, 0x1040005c, 0x8fa20020, - 0x9222000a, 0x30420020, 0x10400033, 0x3c100800, 0x93620023, 0x30420040, - 0x1040002f, 0x8e020020, 0x1040001e, 0x3c029000, 0x0e001006, 0x00000000, - 0x8f820018, 0xac550000, 0x8f840018, 0x3c02008d, 0xac820004, 0x8f830018, - 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f840018, - 0x240205bf, 0xac820014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, - 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018, 0x3c024019, 0x00621825, - 0x0e001044, 0xaca3001c, 0x3c029000, 0x34420001, 0x02a21025, 0xaf420020, - 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93630023, - 0x3c028000, 0x34420001, 0x02a21025, 0x306300bf, 0xa3630023, 0xaf420020, - 0x8e020020, 0x10400023, 0x8fa20020, 0x0e001006, 0x00000000, 0x8f840018, - 0x8e230000, 0xac830000, 0x9222000a, 0x8f830018, 0x00021600, 0xac620004, - 0x8f840018, 0x8f620040, 0xac820008, 0x8f850018, 0x8f63004c, 0xaca3000c, - 0x9362003f, 0x8f840018, 0x304200ff, 0xac820010, 0x8f830018, 0x3c026000, - 0xac600014, 0x8f850018, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, - 0x9443466e, 0x8f850018, 0x3c02401a, 0x00621825, 0x0e001044, 0xaca3001c, - 0x8fa20020, 0x1040000e, 0x8fa20018, 0x9222000a, 0xa3620082, 0x56e00005, - 0x36f70008, 0x8fa30018, 0x10600004, 0x00000000, 0x36f70008, 0x0a000801, - 0x24160001, 0x0e000de1, 0x02a02021, 0x8fa20018, 0x10400003, 0x00000000, - 0x36f70010, 0x24160001, 0x12c00019, 0x3c029000, 0x34420001, 0x02a21025, - 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, - 0x3c038000, 0x9362007d, 0x34630001, 0x3c048000, 0x02a31825, 0x02e21025, - 0xa362007d, 0xaf430020, 0x8f4201f8, 0x00441024, 0x1440fffd, 0x24020002, - 0x3c031000, 0xaf5501c0, 0xa34201c4, 0xaf4301f8, 0x9363003f, 0x24020012, - 0x14620004, 0x3c026000, 0x0e000f6e, 0x00000000, 0x3c026000, 0x8c434448, - 0xaf630178, 0x8fbf004c, 0x8fbe0048, 0x8fb70044, 0x8fb60040, 0x8fb5003c, + 0x00000000, 0x93630023, 0x3c028000, 0x34420001, 0x02821025, 0x34630008, + 0xa3630023, 0xaf420020, 0x92c2000a, 0x30420020, 0x1040008e, 0x8fa2001c, + 0x93620023, 0x30420001, 0x14400035, 0x3c020800, 0x8c430020, 0x10600023, + 0x3c029000, 0x0e00148e, 0x00000000, 0x8f840018, 0x8ec30000, 0xac830000, + 0x92c2000a, 0x8f830018, 0x00021600, 0xac620004, 0x8f840018, 0x8f620040, + 0xac820008, 0x8f850018, 0x8f63004c, 0xaca3000c, 0x9362003f, 0x8f840018, + 0x304200ff, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f850018, + 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, + 0x3c02401a, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x3c029000, 0x34420001, + 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, + 0x00000000, 0x93630023, 0x3c028000, 0x34420001, 0x02821025, 0x34630001, + 0xa3630023, 0xaf420020, 0x93620023, 0x30420040, 0x10400052, 0x8fa2001c, + 0x16600020, 0x3c120800, 0x8e420020, 0x8f70004c, 0x1040003c, 0x3c029000, + 0x0e00148e, 0x00000000, 0x8f820018, 0xac540000, 0x8f840018, 0x24020001, + 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, + 0xac600010, 0x8f820018, 0xac500014, 0x8f850018, 0x3c026000, 0x8c434448, + 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024010, + 0x00621825, 0x0e0014cc, 0xaca3001c, 0x8e420020, 0x1040001e, 0x3c029000, + 0x0e00148e, 0x00000000, 0x8f820018, 0xac540000, 0x8f840018, 0x3c02008d, + 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, + 0xac600010, 0x8f840018, 0x240207ee, 0xac820014, 0x8f850018, 0x3c026000, + 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, + 0x3c024019, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x3c029000, 0x34420001, + 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, + 0x00000000, 0x93630023, 0x3c028000, 0x34420001, 0x02821025, 0x306300bf, + 0xa3630023, 0xaf420020, 0x8fa2001c, 0x1040000e, 0x8fa20014, 0x92c2000a, + 0xa3620082, 0x57c00005, 0x37de0008, 0x8fa30014, 0x10600004, 0x00000000, + 0x37de0008, 0x0a000b75, 0x24170001, 0x0e0012cf, 0x02802021, 0x8fa20014, + 0x10400003, 0x00000000, 0x37de0010, 0x24170001, 0x12e00020, 0x3c029000, + 0x34420001, 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, + 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0x03c21025, 0xa362007d, + 0x8f640074, 0x34630001, 0x02831825, 0xaf430020, 0x04810006, 0x3c038000, + 0x02802021, 0x0e000470, 0x2405082a, 0x0a000b9b, 0x00000000, 0x8f4201f8, + 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf5401c0, 0xa34201c4, + 0xaf4301f8, 0x9363003f, 0x24020012, 0x14620004, 0x8fbf004c, 0x0e00140d, + 0x00000000, 0x8fbf004c, 0x8fbe0048, 0x8fb70044, 0x8fb60040, 0x8fb5003c, 0x8fb40038, 0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028, 0x03e00008, 0x27bd0050, 0x27bdffe8, 0xafbf0014, 0xafb00010, 0x8f500180, 0x97420184, 0x30420200, 0x14400015, 0x00000000, 0x8f430188, 0x3c02ff00, 0x00621824, 0x3c020200, 0x10620031, 0x0043102b, 0x14400007, 0x3c020300, 0x1060000b, - 0x3c020100, 0x1062000d, 0x00000000, 0x0a0008b4, 0x00000000, 0x10620027, - 0x3c020400, 0x1062003e, 0x02002021, 0x0a0008b4, 0x00000000, 0x0e000e1e, - 0x02002021, 0x0a0008b6, 0x8fbf0014, 0x93620005, 0x30420020, 0x1440005e, + 0x3c020100, 0x1062000d, 0x00000000, 0x0a000c2c, 0x00000000, 0x10620027, + 0x3c020400, 0x1062003e, 0x02002021, 0x0a000c2c, 0x00000000, 0x0e000c31, + 0x02002021, 0x0a000c2e, 0x8fbf0014, 0x93620005, 0x30420020, 0x1440005e, 0x8fbf0014, 0x3c029000, 0x34420001, 0x02021025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620005, 0x3c038000, 0x34630001, 0x02031825, 0x34420020, 0xa3620005, 0xaf430020, 0x93620005, - 0x30420020, 0x14400003, 0x02002021, 0x0000000d, 0x02002021, 0x0e000553, - 0x24055854, 0x0a0008b6, 0x8fbf0014, 0x93620005, 0x30420001, 0x1040003f, + 0x30420020, 0x14400003, 0x02002021, 0x0000000d, 0x02002021, 0x0e000766, + 0x24055854, 0x0a000c2e, 0x8fbf0014, 0x93620005, 0x30420001, 0x1040003f, 0x3c029000, 0x34420001, 0x02021025, 0xaf420020, 0x3c038000, 0x8f420020, - 0x00431024, 0x1440fffd, 0x00000000, 0x93620005, 0x3c048000, 0x3c030800, - 0x304200fe, 0xa3620005, 0x8c620020, 0x34840001, 0x02042025, 0xaf440020, - 0x1040002d, 0x8fbf0014, 0x0a000894, 0x00000000, 0x00002821, 0x00003021, - 0x0e000f78, 0x240706a4, 0x3c020800, 0x8c430020, 0x10600023, 0x8fbf0014, - 0x0e001006, 0x00000000, 0x8f820018, 0xac500000, 0x93630082, 0x9362003f, + 0x00431024, 0x1440fffd, 0x00000000, 0x93620023, 0x34420004, 0xa3620023, + 0x93630005, 0x3c048000, 0x3c020800, 0x306300fe, 0xa3630005, 0x8c430020, + 0x34840001, 0x02042025, 0x0a000c0a, 0xaf440020, 0x00002821, 0x00003021, + 0x0e000fb1, 0x240708d9, 0x3c020800, 0x8c430020, 0x10600023, 0x8fbf0014, + 0x0e00148e, 0x00000000, 0x8f820018, 0xac500000, 0x93630082, 0x9362003f, 0x8f840018, 0x00031a00, 0x00431025, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, 0xac400014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, - 0x9443466e, 0x8f850018, 0x3c02400a, 0x00621825, 0x0e001044, 0xaca3001c, - 0x0a0008b6, 0x8fbf0014, 0x0000000d, 0x8fbf0014, 0x8fb00010, 0x03e00008, - 0x27bd0018, 0x27bdffe8, 0xafbf0010, 0x93420148, 0x2444ffff, 0x2c830005, - 0x10600047, 0x3c020800, 0x24424598, 0x00041880, 0x00621821, 0x8c640000, - 0x00800008, 0x00000000, 0x8f430144, 0x8f62000c, 0x14620006, 0x24020001, - 0xaf62000c, 0x0e000909, 0x00000000, 0x0a000907, 0x8fbf0010, 0x8f62000c, - 0x0a000900, 0x00000000, 0x97630010, 0x8f420144, 0x14430006, 0x24020001, - 0xa7620010, 0x0e000eeb, 0x00000000, 0x0a000907, 0x8fbf0010, 0x97620010, - 0x0a000900, 0x00000000, 0x97630012, 0x8f420144, 0x14430006, 0x24020001, - 0xa7620012, 0x0e000f06, 0x00000000, 0x0a000907, 0x8fbf0010, 0x97620012, - 0x0a000900, 0x00000000, 0x97630014, 0x8f420144, 0x14430006, 0x24020001, - 0xa7620014, 0x0e000f21, 0x00000000, 0x0a000907, 0x8fbf0010, 0x97620014, - 0x0a000900, 0x00000000, 0x97630016, 0x8f420144, 0x14430006, 0x24020001, - 0xa7620016, 0x0e000f24, 0x00000000, 0x0a000907, 0x8fbf0010, 0x97620016, - 0x14400006, 0x8fbf0010, 0x3c030800, 0x8c620070, 0x24420001, 0xac620070, - 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafbf0010, 0x93620081, - 0x3c030800, 0x8c640048, 0x0044102b, 0x14400028, 0x3c029000, 0x8f460140, - 0x34420001, 0x3c038000, 0x00c21025, 0xaf420020, 0x8f420020, 0x00431024, - 0x1440fffd, 0x3c048000, 0x34840001, 0x3c059000, 0x34a50001, 0x3c078000, - 0x24020012, 0x24030080, 0x00c42025, 0x00c52825, 0xa362003f, 0xa3630082, - 0xaf440020, 0xaf450020, 0x8f420020, 0x00471024, 0x1440fffd, 0x3c038000, - 0x9362007d, 0x34630001, 0x3c048000, 0x00c31825, 0x34420020, 0xa362007d, - 0xaf430020, 0x8f4201f8, 0x00441024, 0x1440fffd, 0x24020002, 0x3c031000, - 0x0a00096d, 0xaf4601c0, 0x93620081, 0x24420001, 0x0e000f2a, 0xa3620081, - 0x9763006a, 0x00032880, 0x14a00002, 0x00403821, 0x24050001, 0x97630068, + 0x944358ce, 0x8f850018, 0x3c02400a, 0x00621825, 0x0e0014cc, 0xaca3001c, + 0x0a000c2e, 0x8fbf0014, 0x0000000d, 0x8fbf0014, 0x8fb00010, 0x03e00008, + 0x27bd0018, 0x27bdffe8, 0xafbf0010, 0x8f420188, 0x00803021, 0x93640000, + 0x24030020, 0x00021402, 0x10830008, 0x304500ff, 0x3c036018, 0x8c625000, + 0x34420400, 0xac625000, 0x0000000d, 0x00000000, 0x24000955, 0x9363003f, + 0x24020012, 0x14620023, 0x3c029000, 0x34420001, 0x3c038000, 0x00c21025, + 0xaf650178, 0xa365007a, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, + 0x00000000, 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074, 0x34630001, + 0x00c31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00c02021, 0x0e000470, + 0x24050963, 0x0a000c79, 0x8fbf0010, 0x8f4201f8, 0x00431024, 0x1440fffd, + 0x24020002, 0x3c031000, 0xaf4601c0, 0xa34201c4, 0xaf4301f8, 0x0a000c79, + 0x8fbf0010, 0x9362007e, 0x1445000e, 0x00000000, 0x8f620178, 0x1045000b, + 0x00000000, 0x8f820000, 0xaf650178, 0x8f660178, 0x8f440180, 0x8f65004c, + 0x8c430000, 0x0060f809, 0x30c600ff, 0x0a000c79, 0x8fbf0010, 0xaf650178, + 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafbf0010, 0x93630000, + 0x24020020, 0x10620005, 0x00000000, 0x93630000, 0x24020030, 0x1462004d, + 0x8fbf0010, 0x93420148, 0x2444ffff, 0x2c830005, 0x10600047, 0x3c020800, + 0x24425800, 0x00041880, 0x00621821, 0x8c640000, 0x00800008, 0x00000000, + 0x8f430144, 0x8f62000c, 0x14620006, 0x24020001, 0xaf62000c, 0x0e000d59, + 0x00000000, 0x0a000cd1, 0x8fbf0010, 0x8f62000c, 0x0a000cca, 0x00000000, + 0x97630010, 0x8f420144, 0x14430006, 0x24020001, 0xa7620010, 0x0e00137a, + 0x00000000, 0x0a000cd1, 0x8fbf0010, 0x97620010, 0x0a000cca, 0x00000000, + 0x97630012, 0x8f420144, 0x14430006, 0x24020001, 0xa7620012, 0x0e001395, + 0x00000000, 0x0a000cd1, 0x8fbf0010, 0x97620012, 0x0a000cca, 0x00000000, + 0x97630014, 0x8f420144, 0x14430006, 0x24020001, 0xa7620014, 0x0e0013bb, + 0x00000000, 0x0a000cd1, 0x8fbf0010, 0x97620014, 0x0a000cca, 0x00000000, + 0x97630016, 0x8f420144, 0x14430006, 0x24020001, 0xa7620016, 0x0e0013be, + 0x00000000, 0x0a000cd1, 0x8fbf0010, 0x97620016, 0x14400006, 0x8fbf0010, + 0x3c030800, 0x8c620070, 0x24420001, 0xac620070, 0x8fbf0010, 0x03e00008, + 0x27bd0018, 0x27bdffe0, 0x3c029000, 0xafbf001c, 0xafb20018, 0xafb10014, + 0xafb00010, 0x8f500140, 0x34420001, 0x3c038000, 0x02021025, 0xaf420020, + 0x8f420020, 0x00431024, 0x1440fffd, 0x24020012, 0x24030080, 0xa362003f, + 0xa3630082, 0x93620023, 0x30420040, 0x10400007, 0x00008821, 0x93620023, + 0x24110001, 0x304200bf, 0xa3620023, 0x0a000cf0, 0x3c028000, 0x3c028000, + 0x34420001, 0x3c039000, 0x34630001, 0x3c048000, 0x02021025, 0x02031825, + 0xaf420020, 0xaf430020, 0x8f420020, 0x00441024, 0x1440fffd, 0x00000000, + 0x9362007d, 0x3c038000, 0x34420020, 0xa362007d, 0x8f640074, 0x34630001, + 0x02031825, 0xaf430020, 0x04810006, 0x3c038000, 0x02002021, 0x0e000470, + 0x24050a63, 0x0a000d13, 0x00000000, 0x8f4201f8, 0x00431024, 0x1440fffd, + 0x24020002, 0x3c031000, 0xaf5001c0, 0xa34201c4, 0xaf4301f8, 0x1220003f, + 0x3c120800, 0x8e420020, 0x8f71004c, 0x1040003c, 0x8fbf001c, 0x0e00148e, + 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x24020001, 0xac820004, + 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, + 0x8f820018, 0xac510014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, + 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024010, 0x00621825, + 0x0e0014cc, 0xaca3001c, 0x8e420020, 0x1040001e, 0x8fbf001c, 0x0e00148e, + 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x3c02008d, 0xac820004, + 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, + 0x8f840018, 0x24020a6a, 0xac820014, 0x8f850018, 0x3c026000, 0x8c434448, + 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024019, + 0x00621825, 0x0e0014cc, 0xaca3001c, 0x8fbf001c, 0x8fb20018, 0x8fb10014, + 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0010, 0x93620081, + 0x3c030800, 0x8c640048, 0x0044102b, 0x14400005, 0x00000000, 0x0e000cd3, + 0x00000000, 0x0a000da4, 0x8fbf0010, 0x93620081, 0x24420001, 0x0e0013c4, + 0xa3620081, 0x9763006a, 0x00032880, 0x14a00002, 0x00403821, 0x24050001, + 0x97630068, 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804, + 0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b, + 0x54600001, 0x00c02021, 0x8f420074, 0x2403fffe, 0x00832824, 0x00a21021, + 0xaf62000c, 0x10e00021, 0x3c029000, 0x8f450140, 0x34420001, 0x3c038000, + 0x00a21025, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, + 0x9362007d, 0x3c038000, 0x34420004, 0xa362007d, 0x8f640074, 0x34630001, + 0x00a31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00a02021, 0x0e000470, + 0x24050a92, 0x0a000da4, 0x8fbf0010, 0x8f4201f8, 0x00431024, 0x1440fffd, + 0x24020002, 0x3c031000, 0xaf4501c0, 0xa34201c4, 0xaf4301f8, 0x8fbf0010, + 0x03e00008, 0x27bd0018, 0x27bdffd8, 0xafb3001c, 0x27530100, 0xafbf0024, + 0xafb40020, 0xafb20018, 0xafb10014, 0xafb00010, 0x96620008, 0x3c140800, + 0x8f520100, 0x30420001, 0x104000da, 0x00000000, 0x8e700018, 0x8f630054, + 0x2602ffff, 0x00431023, 0x18400006, 0x00000000, 0x0000000d, 0x00000000, + 0x2400015c, 0x0a000dea, 0x00008821, 0x8f62004c, 0x02021023, 0x18400028, + 0x00008821, 0x93650120, 0x93640121, 0x3c030800, 0x8c62008c, 0x308400ff, + 0x24420001, 0x30a500ff, 0x00803821, 0x1485000b, 0xac62008c, 0x3c040800, + 0x8c830090, 0x24630001, 0xac830090, 0x93620122, 0x30420001, 0x00021023, + 0x30420005, 0x0a000dea, 0x34510004, 0x27660100, 0x00041080, 0x00c21021, + 0x8c430000, 0x02031823, 0x04600004, 0x24820001, 0x30440007, 0x1485fff9, + 0x00041080, 0x10870007, 0x3c030800, 0xa3640121, 0x8c620094, 0x24110005, + 0x24420001, 0x0a000dea, 0xac620094, 0x24110004, 0x32220001, 0x1040001e, + 0x8e820020, 0x1040001d, 0x32220004, 0x0e00148e, 0x00000000, 0x8f820018, + 0xac520000, 0x8f840018, 0x24020001, 0xac820004, 0x8f830018, 0xac600008, + 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, 0xac500014, + 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, + 0x944358ce, 0x8f850018, 0x3c024010, 0x00621825, 0x0e0014cc, 0xaca3001c, + 0x32220004, 0x10400081, 0x00003821, 0x3c029000, 0x34420001, 0x3c038000, + 0x02421025, 0xa360007c, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, + 0x00000000, 0x93620023, 0x30420080, 0x10400011, 0x00000000, 0x8f65005c, + 0x8f63004c, 0x9764003c, 0x8f620064, 0x00a32823, 0x00852821, 0x00a2102b, + 0x54400006, 0x3c023fff, 0x93620023, 0x3042007f, 0xa3620023, 0xaf700064, + 0x3c023fff, 0x0a000e37, 0x3442ffff, 0x8f62005c, 0x02021023, 0x04400011, + 0x00000000, 0x8f65005c, 0x8f630064, 0x9764003c, 0x3c023fff, 0x3442ffff, + 0xaf700064, 0x00a32823, 0x00852821, 0x0045102b, 0x10400004, 0x02051021, + 0x3c053fff, 0x34a5ffff, 0x02051021, 0xaf62005c, 0x24070001, 0xaf70004c, + 0x8f620054, 0x16020005, 0x00000000, 0x93620023, 0x30420040, 0x10400017, + 0x24020001, 0x9762006a, 0x00022880, 0x50a00001, 0x24050001, 0x97630068, 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001, 0x00c02021, 0x8f420074, 0x2403fffe, 0x00832824, 0x00a21021, 0xaf62000c, - 0x10e0001a, 0x3c029000, 0x8f440140, 0x34420001, 0x3c038000, 0x00821025, - 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x3c038000, - 0x9362007d, 0x34630001, 0x3c058000, 0x00831825, 0x34420004, 0xa362007d, - 0xaf430020, 0x8f4201f8, 0x00451024, 0x1440fffd, 0x24020002, 0x3c031000, - 0xaf4401c0, 0xa34201c4, 0xaf4301f8, 0x8fbf0010, 0x03e00008, 0x27bd0018, - 0x27bdffd8, 0xafb3001c, 0x27530100, 0xafbf0024, 0xafb40020, 0xafb20018, - 0xafb10014, 0xafb00010, 0x96620008, 0x3c140800, 0x8f520100, 0x30420001, - 0x104000cf, 0x00000000, 0x8e700018, 0x8f630054, 0x2602ffff, 0x00431023, - 0x18400006, 0x00000000, 0x0000000d, 0x00000000, 0x24000128, 0x0a0009b6, - 0x00008821, 0x8f62004c, 0x02021023, 0x18400028, 0x00008821, 0x93650120, - 0x93640121, 0x3c030800, 0x8c62008c, 0x308400ff, 0x24420001, 0x30a500ff, - 0x00803821, 0x1485000b, 0xac62008c, 0x3c040800, 0x8c830090, 0x24630001, - 0xac830090, 0x93620122, 0x30420001, 0x00021023, 0x30420005, 0x0a0009b6, - 0x34510004, 0x27660100, 0x00041080, 0x00c21021, 0x8c430000, 0x02031823, - 0x04600004, 0x24820001, 0x30440007, 0x1485fff9, 0x00041080, 0x10870007, - 0x3c030800, 0xa3640121, 0x8c620094, 0x24110005, 0x24420001, 0x0a0009b6, - 0xac620094, 0x24110004, 0x32220001, 0x1040001e, 0x8e820020, 0x1040001d, - 0x32220004, 0x0e001006, 0x00000000, 0x8f820018, 0xac520000, 0x8f840018, - 0x24020001, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, - 0x8f830018, 0xac600010, 0x8f820018, 0xac500014, 0x8f850018, 0x3c026000, - 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018, - 0x3c024010, 0x00621825, 0x0e001044, 0xaca3001c, 0x32220004, 0x10400076, - 0x00003821, 0x3c029000, 0x34420001, 0x3c038000, 0x02421025, 0xa360007c, - 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620023, - 0x30420080, 0x10400011, 0x00000000, 0x8f65005c, 0x8f63004c, 0x9764003c, - 0x8f620064, 0x00a32823, 0x00852821, 0x00a2102b, 0x54400006, 0x3c023fff, - 0x93620023, 0x3042007f, 0xa3620023, 0xaf700064, 0x3c023fff, 0x0a000a03, - 0x3442ffff, 0x8f62005c, 0x02021023, 0x04400011, 0x00000000, 0x8f65005c, - 0x8f630064, 0x9764003c, 0x3c023fff, 0x3442ffff, 0xaf700064, 0x00a32823, - 0x00852821, 0x0045102b, 0x10400004, 0x02051021, 0x3c053fff, 0x34a5ffff, - 0x02051021, 0xaf62005c, 0x24070001, 0xaf70004c, 0x8f620054, 0x16020005, - 0x00000000, 0x93620023, 0x30420040, 0x10400017, 0x24020001, 0x9762006a, - 0x00022880, 0x50a00001, 0x24050001, 0x97630068, 0x93640081, 0x3c020800, - 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b, 0x54400001, 0x00a03021, - 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001, 0x00c02021, 0x8f420074, - 0x2403fffe, 0x00832824, 0x00a21021, 0xaf62000c, 0x3c028000, 0x34420001, - 0x02421025, 0xa3600081, 0xaf420020, 0x9363007e, 0x9362007a, 0x10620004, - 0x00000000, 0x0e000f2a, 0x00000000, 0x00403821, 0x10e00017, 0x3c029000, + 0x93620082, 0x30420080, 0x50400001, 0xa3600081, 0x3c028000, 0x34420001, + 0x02421025, 0xaf420020, 0x9363007e, 0x9362007a, 0x10620004, 0x00000000, + 0x0e0013c4, 0x00000000, 0x00403821, 0x10e0001f, 0x3c029000, 0x34420001, + 0x02421025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, + 0x00000000, 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074, 0x34630001, + 0x02431825, 0xaf430020, 0x04810006, 0x3c038000, 0x02402021, 0x0e000470, + 0x24050b3d, 0x0a000e8d, 0x00000000, 0x8f4201f8, 0x00431024, 0x1440fffd, + 0x24020002, 0x3c031000, 0xaf5201c0, 0xa34201c4, 0xaf4301f8, 0x9342010b, + 0x9343010b, 0x8e820020, 0x27500100, 0x38630006, 0x10400029, 0x2c710001, + 0x0e00148e, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018, + 0x96020008, 0xac820004, 0x8f830018, 0x8e020014, 0xac620008, 0x8f850018, + 0x3c026000, 0x8c434448, 0xaca3000c, 0x8f840018, 0x96020012, 0xac820010, + 0x8f850018, 0x8e030020, 0xaca30014, 0x9602000c, 0x9603000e, 0x8f840018, + 0x00021400, 0x00431025, 0xac820018, 0x12200005, 0x3c020800, 0x944358ce, + 0x8f840018, 0x0a000eb8, 0x3c024013, 0x944358ce, 0x8f840018, 0x3c024014, + 0x00621825, 0xac83001c, 0x0e0014cc, 0x24040001, 0x8e700014, 0x8f620040, + 0x14500003, 0x00501023, 0x0a000ec3, 0x00001021, 0x28420001, 0x1040003a, + 0x00000000, 0x0e000fae, 0x02002021, 0xaf700040, 0x9362003e, 0x30420001, + 0x1440000b, 0x3c029000, 0x93620022, 0x24420001, 0xa3620022, 0x93630022, + 0x3c020800, 0x8c440098, 0x0064182b, 0x14600025, 0x3c020800, 0x3c029000, 0x34420001, 0x02421025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, - 0x1440fffd, 0x3c028000, 0x9363007d, 0x34420001, 0x3c048000, 0x02421025, - 0xa363007d, 0xaf420020, 0x8f4201f8, 0x00441024, 0x1440fffd, 0x24020002, - 0x3c031000, 0xaf5201c0, 0xa34201c4, 0xaf4301f8, 0x9342010b, 0x8e830020, - 0x27500100, 0x38420006, 0x10600029, 0x2c510001, 0x0e001006, 0x00000000, - 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018, 0x96020008, 0xac820004, - 0x8f830018, 0x8e020014, 0xac620008, 0x8f850018, 0x3c026000, 0x8c434448, - 0xaca3000c, 0x8f840018, 0x96020012, 0xac820010, 0x8f850018, 0x8e030020, - 0xaca30014, 0x9602000c, 0x9603000e, 0x8f840018, 0x00021400, 0x00431025, - 0xac820018, 0x12200005, 0x3c020800, 0x9443466e, 0x8f840018, 0x0a000a78, - 0x3c024013, 0x9443466e, 0x8f840018, 0x3c024014, 0x00621825, 0xac83001c, - 0x0e001044, 0x24040001, 0x8e630014, 0x8f620040, 0x14430003, 0x00431023, - 0x0a000a83, 0x00001021, 0x28420001, 0x10400034, 0x00000000, 0x8f620040, - 0xaf630040, 0x9362003e, 0x30420001, 0x1440000b, 0x3c029000, 0x93620022, - 0x24420001, 0xa3620022, 0x93630022, 0x3c020800, 0x8c440098, 0x0064182b, - 0x1460001e, 0x3c020800, 0x3c029000, 0x34420001, 0x02421025, 0xaf420020, - 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x3c038000, - 0x9362007d, 0x34630001, 0x3c048000, 0x02431825, 0x34420001, 0xa362007d, - 0xaf430020, 0x8f4201f8, 0x00441024, 0x1440fffd, 0x24020002, 0x3c031000, - 0xaf5201c0, 0xa34201c4, 0x24020001, 0xaf4301f8, 0xa7620012, 0x0a000ab6, - 0xa3600022, 0x9743007a, 0x9444002a, 0x00641821, 0x3063fffe, 0xa7630012, - 0x0e000b68, 0x00000000, 0x97420108, 0x8fbf0024, 0x8fb40020, 0x8fb3001c, - 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x00021042, 0x30420001, 0x03e00008, - 0x27bd0028, 0x27bdffe0, 0xafb20018, 0x3c120800, 0x8e420020, 0xafb00010, - 0x27500100, 0xafbf001c, 0x10400046, 0xafb10014, 0x0e001006, 0x00000000, - 0x8f840018, 0x8e020000, 0xac820000, 0x936300b1, 0x936200c5, 0x8f850018, - 0x00031e00, 0x00021400, 0x34420100, 0x00621825, 0xaca30004, 0x8f840018, - 0x8e02001c, 0xac820008, 0x8f830018, 0x8f620048, 0xac62000c, 0x8f840018, - 0x96020012, 0xac820010, 0x8f830018, 0x8f620040, 0x24040001, 0xac620014, - 0x8f850018, 0x3c026000, 0x8c434448, 0x3c020800, 0x24514660, 0xaca30018, - 0x9623000e, 0x8f850018, 0x3c024016, 0x00621825, 0x0e001044, 0xaca3001c, - 0x96030008, 0x30630010, 0x1060001c, 0x8e420020, 0x1040001a, 0x8e100000, - 0x0e001006, 0x00000000, 0x8f820018, 0xac500000, 0x8f830018, 0xac600004, - 0x8f820018, 0xac400008, 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010, - 0x8f830018, 0xac600014, 0x8f850018, 0x3c036000, 0x8c634448, 0x24040001, - 0xaca30018, 0x9622000e, 0x8f850018, 0x3c034015, 0x00431025, 0x0e001044, - 0xaca2001c, 0x00001021, 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, - 0x03e00008, 0x27bd0020, 0x27bdffe0, 0xafb20018, 0x3c120800, 0x8e420020, - 0xafb00010, 0x27500100, 0xafbf001c, 0x10400041, 0xafb10014, 0x0e001006, - 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018, 0x24020100, - 0xac820004, 0x8f830018, 0x8e02001c, 0xac620008, 0x8f840018, 0x8e020018, - 0xac82000c, 0x8f830018, 0x96020012, 0xac620010, 0x8f840018, 0x96020008, - 0xac820014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, - 0x24514660, 0xaca30018, 0x9623000e, 0x8f850018, 0x3c024017, 0x00621825, - 0x0e001044, 0xaca3001c, 0x96030008, 0x30630010, 0x1060001c, 0x8e420020, - 0x1040001a, 0x8e100000, 0x0e001006, 0x00000000, 0x8f820018, 0xac500000, + 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0x34420001, 0xa362007d, + 0x8f640074, 0x34630001, 0x02431825, 0xaf430020, 0x04810006, 0x3c038000, + 0x02402021, 0x0e000470, 0x24050273, 0x0a000ef6, 0x24020001, 0x8f4201f8, + 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf5201c0, 0xa34201c4, + 0xaf4301f8, 0x24020001, 0xa7620012, 0x0a000efe, 0xa3600022, 0x9743007a, + 0x9444002a, 0x00641821, 0x3063fffe, 0xa7630012, 0x97420108, 0x8fbf0024, + 0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x00021042, + 0x30420001, 0x03e00008, 0x27bd0028, 0x27bdffe0, 0xafb20018, 0x3c120800, + 0x8e420020, 0xafb00010, 0x27500100, 0xafbf001c, 0x10400046, 0xafb10014, + 0x0e00148e, 0x00000000, 0x8f840018, 0x8e020000, 0xac820000, 0x936300b1, + 0x936200c5, 0x8f850018, 0x00031e00, 0x00021400, 0x34420100, 0x00621825, + 0xaca30004, 0x8f840018, 0x8e02001c, 0xac820008, 0x8f830018, 0x8f620048, + 0xac62000c, 0x8f840018, 0x96020012, 0xac820010, 0x8f830018, 0x8f620040, + 0x24040001, 0xac620014, 0x8f850018, 0x3c026000, 0x8c434448, 0x3c020800, + 0x245158c0, 0xaca30018, 0x9623000e, 0x8f850018, 0x3c024016, 0x00621825, + 0x0e0014cc, 0xaca3001c, 0x96030008, 0x30630010, 0x1060001c, 0x8e420020, + 0x1040001a, 0x8e100000, 0x0e00148e, 0x00000000, 0x8f820018, 0xac500000, 0x8f830018, 0xac600004, 0x8f820018, 0xac400008, 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010, 0x8f830018, 0xac600014, 0x8f850018, 0x3c036000, 0x8c634448, 0x24040001, 0xaca30018, 0x9622000e, 0x8f850018, 0x3c034015, - 0x00431025, 0x0e001044, 0xaca2001c, 0x00001021, 0x8fbf001c, 0x8fb20018, - 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0010, - 0x936200c4, 0x30420002, 0x10400019, 0x00000000, 0x936200c5, 0x936300b1, - 0x00431023, 0x304400ff, 0x30830080, 0x10600004, 0x00000000, 0x0000000d, - 0x00000000, 0x24000a6a, 0x93620004, 0x00441023, 0x304400ff, 0x30830080, - 0x10600004, 0x2482ffff, 0x8f650024, 0x0a000b82, 0x00000000, 0x00022b00, - 0x8f620024, 0x0045102b, 0x10400002, 0x00000000, 0x8f650024, 0x8f620048, - 0x8f630040, 0x00431823, 0x0065202b, 0x10800004, 0x00000000, 0x8f620040, - 0x00451021, 0xaf620048, 0x9762003c, 0x0062102b, 0x10400041, 0x8fbf0010, - 0x10a0003f, 0x3c029000, 0x34420001, 0x3c040800, 0x8c830080, 0x8f450100, - 0x3c068000, 0x24630001, 0x00a21025, 0xac830080, 0xaf420020, 0x8f420020, - 0x00461024, 0x1440fffd, 0x3c038000, 0x9362007d, 0x34630001, 0x3c048000, - 0x00a31825, 0x34420004, 0xa362007d, 0xaf430020, 0x8f4201f8, 0x00441024, - 0x1440fffd, 0x24020002, 0x3c030800, 0xaf4501c0, 0xa34201c4, 0x8c640020, - 0x3c021000, 0xaf4201f8, 0x1080001f, 0x8fbf0010, 0x0e001006, 0x00000000, - 0x8f830018, 0x8f420100, 0xac620000, 0x8f840018, 0x8f620040, 0xac820004, - 0x8f850018, 0x8f620048, 0xaca20008, 0x8f830018, 0xac60000c, 0x8f820018, - 0xac400010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f840018, 0x8c434448, - 0x3c020800, 0xac830018, 0x9443466e, 0x8f840018, 0x3c0240c2, 0x00621825, - 0xac83001c, 0x0e001044, 0x24040001, 0x8fbf0010, 0x03e00008, 0x27bd0018, - 0x3c020800, 0x24423958, 0xaf82000c, 0x03e00008, 0x00000000, 0x27bdffe8, - 0xafb00010, 0x27500100, 0xafbf0014, 0x8e02001c, 0x14400003, 0x3c020800, - 0x0000000d, 0x3c020800, 0x8c430020, 0x10600026, 0x00001021, 0x0e001006, - 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018, 0x8e02001c, - 0xac820004, 0x8f830018, 0xac600008, 0x8f840018, 0x8e020018, 0xac82000c, - 0x8f850018, 0x96020012, 0xaca20010, 0x8f830018, 0x3c106000, 0xac600014, - 0x8f840018, 0x8e024448, 0x3c030800, 0xac820018, 0x9462466e, 0x8f840018, - 0x3c034012, 0x00431025, 0xac82001c, 0x0e001044, 0x24040001, 0x8e036800, - 0x00001021, 0x3c040001, 0x00641825, 0xae036800, 0x0a000c0d, 0x8fbf0014, - 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c020800, 0x97430078, - 0x9444002e, 0x00001021, 0x00641821, 0x3063fffe, 0x03e00008, 0xa7630010, - 0x27450100, 0x8f640048, 0x8ca30018, 0x00641023, 0x18400021, 0x00000000, - 0xaf630048, 0x8f620040, 0x9763003c, 0x00821023, 0x0043102a, 0x1040001a, - 0x3c029000, 0x8ca40000, 0x34420001, 0x3c038000, 0x00821025, 0xaf420020, - 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x3c038000, 0x9362007d, - 0x34630001, 0x3c058000, 0x00831825, 0x34420004, 0xa362007d, 0xaf430020, - 0x8f4201f8, 0x00451024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4401c0, - 0xa34201c4, 0xaf4301f8, 0x03e00008, 0x00001021, 0x8f420100, 0x34420001, - 0xaf4200a4, 0x03e00008, 0x00001021, 0x27bdffe0, 0xafbf0018, 0xafb10014, - 0xafb00010, 0x9362007e, 0x30d000ff, 0x16020029, 0x00808821, 0x93620080, - 0x16020026, 0x00000000, 0x9362007f, 0x16020023, 0x00000000, 0x9362007a, - 0x16020004, 0x00000000, 0x0000000d, 0x00000000, 0x24000771, 0x0e000f49, - 0x00000000, 0x3c039000, 0x34630001, 0x3c048000, 0x02231825, 0xa370007a, - 0xaf430020, 0x8f420020, 0x00441024, 0x1440fffd, 0x3c028000, 0x9363007d, - 0x34420001, 0x3c048000, 0x02221025, 0xa363007d, 0xaf420020, 0x8f4201f8, - 0x00441024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf5101c0, 0xa34201c4, - 0xaf4301f8, 0x0a000c79, 0x8fbf0018, 0x0000000d, 0x00000000, 0x24000781, - 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3c020800, + 0x00431025, 0x0e0014cc, 0xaca2001c, 0x00001021, 0x8fbf001c, 0x8fb20018, + 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe0, 0xafb20018, + 0x3c120800, 0x8e420020, 0xafb00010, 0x27500100, 0xafbf001c, 0x10400041, + 0xafb10014, 0x0e00148e, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, + 0x8f840018, 0x24020100, 0xac820004, 0x8f830018, 0x8e02001c, 0xac620008, + 0x8f840018, 0x8e020018, 0xac82000c, 0x8f830018, 0x96020012, 0xac620010, + 0x8f840018, 0x96020008, 0xac820014, 0x8f850018, 0x3c026000, 0x8c434448, + 0x24040001, 0x3c020800, 0x245158c0, 0xaca30018, 0x9623000e, 0x8f850018, + 0x3c024017, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x96030008, 0x30630010, + 0x1060001c, 0x8e420020, 0x1040001a, 0x8e100000, 0x0e00148e, 0x00000000, + 0x8f820018, 0xac500000, 0x8f830018, 0xac600004, 0x8f820018, 0xac400008, + 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010, 0x8f830018, 0xac600014, + 0x8f850018, 0x3c036000, 0x8c634448, 0x24040001, 0xaca30018, 0x9622000e, + 0x8f850018, 0x3c034015, 0x00431025, 0x0e0014cc, 0xaca2001c, 0x00001021, + 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, + 0x27bdfff0, 0x03e00008, 0x27bd0010, 0x27bdffd0, 0xafb10014, 0x00808821, + 0xafb40020, 0x00c0a021, 0xafbf0028, 0xafb50024, 0xafb3001c, 0xafb20018, + 0xafb00010, 0x93620023, 0x00e0a821, 0x30420040, 0x1040003e, 0x30b3ffff, + 0x3c120800, 0x8e420020, 0x1040003a, 0x8f70004c, 0x0e00148e, 0x00000000, + 0x8f820018, 0xac510000, 0x8f840018, 0x24020001, 0xac820004, 0x8f830018, + 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, + 0x24040001, 0xac500014, 0x8f850018, 0x3c026000, 0x8c434448, 0x3c020800, + 0x245058c0, 0xaca30018, 0x9603000e, 0x8f850018, 0x3c024010, 0x00621825, + 0x0e0014cc, 0xaca3001c, 0x8e430020, 0x1060001b, 0x00000000, 0x0e00148e, + 0x00000000, 0x8f820018, 0xac510000, 0x8f840018, 0x3c02008d, 0xac820004, + 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, + 0x8f820018, 0xac550014, 0x8f850018, 0x3c036000, 0x8c634448, 0x24040001, + 0xaca30018, 0x9602000e, 0x8f850018, 0x3c034019, 0x00431025, 0x0e0014cc, + 0xaca2001c, 0x93620023, 0x30420020, 0x14400003, 0x3c120800, 0x1280003f, + 0x3c029000, 0x8e420020, 0x8f70004c, 0x1040003b, 0x3c029000, 0x0e00148e, + 0x00000000, 0x8f820018, 0xac510000, 0x8f840018, 0x24020001, 0xac820004, + 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, + 0x8f820018, 0x24040001, 0xac500014, 0x8f850018, 0x3c026000, 0x8c434448, + 0x3c020800, 0x245058c0, 0xaca30018, 0x9603000e, 0x8f850018, 0x3c024010, + 0x00621825, 0x0e0014cc, 0xaca3001c, 0x8e430020, 0x1060001c, 0x3c029000, + 0x0e00148e, 0x00000000, 0x8f820018, 0xac510000, 0x8f840018, 0x00131400, + 0xac820004, 0x8f830018, 0xac750008, 0x8f820018, 0xac40000c, 0x8f830018, + 0xac600010, 0x8f820018, 0xac400014, 0x8f850018, 0x3c036000, 0x8c634448, + 0x24040001, 0xaca30018, 0x9602000e, 0x8f850018, 0x3c03401b, 0x00431025, + 0x0e0014cc, 0xaca2001c, 0x3c029000, 0x34420001, 0x02221025, 0xaf420020, + 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93630023, + 0x3c028000, 0x34420001, 0x02221025, 0x8fbf0028, 0x8fb50024, 0x8fb40020, + 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3063009f, 0xa3630023, + 0xaf420020, 0x03e00008, 0x27bd0030, 0x27bdffe0, 0xafb10014, 0x27510100, + 0x3c029000, 0x34420001, 0xafb00010, 0x00808021, 0x02021025, 0x3c038000, + 0xafbf0018, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, + 0xa7600008, 0x8f63005c, 0x3c028000, 0x34420001, 0xaf630148, 0x8f640050, + 0x02021025, 0x3c039000, 0xaf64017c, 0xaf420020, 0x8f450100, 0x34630001, + 0x3c048000, 0x00a31825, 0xaf430020, 0x8f420020, 0x00441024, 0x1440fffd, + 0x00000000, 0x9362007d, 0x3c038000, 0x34420001, 0xa362007d, 0x8f640074, + 0x34630001, 0x00a31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00a02021, + 0x0e000470, 0x24050de5, 0x0a001093, 0x3c020800, 0x8f4201f8, 0x00431024, + 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4501c0, 0xa34201c4, 0xaf4301f8, + 0x3c020800, 0x8c430020, 0x1060001e, 0x8fbf0018, 0x0e00148e, 0x00000000, + 0x8f830018, 0xac700000, 0x9622000c, 0x8f840018, 0x00021400, 0xac820004, + 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, + 0x8f820018, 0xac400014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, + 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c02401f, 0x00621825, + 0x0e0014cc, 0xaca3001c, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, + 0x27bd0020, 0x3c020800, 0x24424c3c, 0xaf82000c, 0x03e00008, 0x00000000, + 0x27bdffe8, 0xafb00010, 0x27500100, 0xafbf0014, 0x8e02001c, 0x14400003, + 0x3c020800, 0x0000000d, 0x3c020800, 0x8c430020, 0x10600020, 0x00001021, + 0x0e00148e, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018, + 0x8e02001c, 0xac820004, 0x8f830018, 0xac600008, 0x8f840018, 0x8e020018, + 0xac82000c, 0x8f850018, 0x96020012, 0xaca20010, 0x8f830018, 0x3c026000, + 0xac600014, 0x8f840018, 0x8c434448, 0x3c020800, 0xac830018, 0x944358ce, + 0x8f840018, 0x3c024012, 0x00621825, 0xac83001c, 0x0e0014cc, 0x24040001, + 0x00001021, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c020800, + 0x97430078, 0x9444002e, 0x00001021, 0x00641821, 0x3063fffe, 0x03e00008, + 0xa7630010, 0x27bdfff0, 0x00001021, 0x03e00008, 0x27bd0010, 0x8f420100, + 0x34420001, 0xaf4200a4, 0x03e00008, 0x00001021, 0x27bdffe0, 0xafbf0018, + 0xafb10014, 0xafb00010, 0x9362007e, 0x30d000ff, 0x16020031, 0x00808821, + 0x8f620178, 0x1602002e, 0x00000000, 0x9362007f, 0x1602002b, 0x00000000, + 0x9362007a, 0x16020004, 0x00000000, 0x0000000d, 0x00000000, 0x240009d2, + 0x0e0013e6, 0x00000000, 0x3c039000, 0x34630001, 0x3c048000, 0x02231825, + 0xa370007a, 0xaf430020, 0x8f420020, 0x00441024, 0x1440fffd, 0x00000000, + 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074, 0x34630001, 0x02231825, + 0xaf430020, 0x04810006, 0x3c038000, 0x02202021, 0x0e000470, 0x240509dd, + 0x0a001138, 0x8fbf0018, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, + 0x3c031000, 0xaf5101c0, 0xa34201c4, 0xaf4301f8, 0x0a001138, 0x8fbf0018, + 0x0000000d, 0x00000000, 0x240009e2, 0x8fbf0018, 0x8fb10014, 0x8fb00010, + 0x03e00008, 0x27bd0020, 0x27bdffe8, 0x30a500ff, 0x3c029000, 0x34420001, + 0x00803821, 0x00e21025, 0x3c038000, 0xafbf0010, 0xaf420020, 0x8f420020, + 0x00431024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0x00a21025, + 0xa362007d, 0x8f640074, 0x34630001, 0x00e31825, 0xaf430020, 0x04810006, + 0x3c038000, 0x00e02021, 0x0e000470, 0x00c02821, 0x0a001161, 0x8fbf0010, + 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4701c0, + 0xa34201c4, 0xaf4301f8, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe8, 0xafb00010, 0x27500100, 0x10600024, 0xafbf0014, - 0x0e001006, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018, + 0x0e00148e, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018, 0x8e020004, 0xac820004, 0x8f830018, 0x8e020018, 0xac620008, 0x8f840018, 0x8e03001c, 0xac83000c, 0x9602000c, 0x9203000a, 0x8f840018, 0x00021400, 0x00431025, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f840018, - 0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x9464466e, 0x8f850018, - 0x00021400, 0x00441025, 0x24040001, 0x0e001044, 0xaca2001c, 0x8fbf0014, + 0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x946458ce, 0x8f850018, + 0x00021400, 0x00441025, 0x24040001, 0x0e0014cc, 0xaca2001c, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe8, - 0xafb00010, 0x27500100, 0x10600020, 0xafbf0014, 0x0e001006, 0x00000000, + 0xafb00010, 0x27500100, 0x10600020, 0xafbf0014, 0x0e00148e, 0x00000000, 0x8f820018, 0xac400000, 0x8f830018, 0xac600004, 0x8f820018, 0xac400008, 0x8f830018, 0xac60000c, 0x9602000c, 0x9603000e, 0x8f840018, 0x00021400, 0x00431025, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f840018, - 0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x9464466e, 0x8f850018, - 0x00021400, 0x00441025, 0x24040001, 0x0e001044, 0xaca2001c, 0x8fbf0014, + 0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x946458ce, 0x8f850018, + 0x00021400, 0x00441025, 0x24040001, 0x0e0014cc, 0xaca2001c, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafb00010, 0x27500100, 0xafbf0014, 0x9602000c, 0x10400024, 0x00802821, 0x3c020800, 0x8c430020, - 0x1060003a, 0x8fbf0014, 0x0e001006, 0x00000000, 0x8f840018, 0x8e030000, + 0x1060003a, 0x8fbf0014, 0x0e00148e, 0x00000000, 0x8f840018, 0x8e030000, 0xac830000, 0x9602000c, 0x8f840018, 0x00021400, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, 0xac400014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, - 0xaca30018, 0x9443466e, 0x8f850018, 0x3c02400b, 0x00621825, 0x0e001044, - 0xaca3001c, 0x0a000d19, 0x8fbf0014, 0x93620005, 0x30420010, 0x14400015, + 0xaca30018, 0x944358ce, 0x8f850018, 0x3c02400b, 0x00621825, 0x0e0014cc, + 0xaca3001c, 0x0a0011ff, 0x8fbf0014, 0x93620005, 0x30420010, 0x14400015, 0x3c029000, 0x34420001, 0x00a21025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x3c038000, 0x93620005, 0x34630001, - 0x00a02021, 0x00a31825, 0x24055852, 0x34420010, 0xa3620005, 0x0e000553, - 0xaf430020, 0x0a000d19, 0x8fbf0014, 0x0000000d, 0x8fbf0014, 0x8fb00010, + 0x00a02021, 0x00a31825, 0x24055852, 0x34420010, 0xa3620005, 0x0e000766, + 0xaf430020, 0x0a0011ff, 0x8fbf0014, 0x0000000d, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe8, 0xafb00010, - 0x27500100, 0x10600022, 0xafbf0014, 0x0e001006, 0x00000000, 0x8f840018, + 0x27500100, 0x10600022, 0xafbf0014, 0x0e00148e, 0x00000000, 0x8f840018, 0x8e020004, 0xac820000, 0x9603000c, 0x9762002c, 0x8f840018, 0x00031c00, 0x00431025, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, 0xac400014, 0x8f850018, 0x3c026000, - 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018, - 0x3c02400e, 0x00621825, 0x0e001044, 0xaca3001c, 0x0e000d48, 0x8e040000, + 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, + 0x3c02400e, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x0e00122e, 0x8e040000, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c038000, 0x8f420278, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf440240, 0xa3420244, 0x03e00008, 0xaf430278, 0x3c020800, 0x8c430020, 0x27bdffe0, 0xafb10014, 0x00808821, 0xafb20018, 0x00c09021, 0xafb00010, 0x30b0ffff, 0x1060001c, - 0xafbf001c, 0x0e001006, 0x00000000, 0x8f820018, 0xac510000, 0x8f840018, + 0xafbf001c, 0x0e00148e, 0x00000000, 0x8f820018, 0xac510000, 0x8f840018, 0x00101400, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, 0xac520014, 0x8f840018, 0x3c026000, - 0x8c434448, 0x3c020800, 0xac830018, 0x9443466e, 0x8f840018, 0x3c024019, - 0x00621825, 0xac83001c, 0x0e001044, 0x24040001, 0x8fbf001c, 0x8fb20018, + 0x8c434448, 0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c024019, + 0x00621825, 0xac83001c, 0x0e0014cc, 0x24040001, 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0x27450100, - 0xafbf0010, 0x94a3000c, 0x240200c1, 0x14620029, 0x00803021, 0x3c029000, + 0xafbf0010, 0x94a3000c, 0x240200c1, 0x14620031, 0x00803021, 0x3c029000, 0x34420001, 0x00c21025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x3c028000, 0x34420001, 0x3c049000, 0x34840001, 0x3c058000, 0x24030012, 0x00c21025, 0x00c42025, 0xa363003f, 0xaf420020, 0xaf440020, - 0x8f420020, 0x00451024, 0x1440fffd, 0x3c038000, 0x9362007d, 0x34630001, - 0x3c048000, 0x00c31825, 0x34420020, 0xa362007d, 0xaf430020, 0x8f4201f8, - 0x00441024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4601c0, 0xa34201c4, - 0xaf4301f8, 0x0a000db3, 0x8fbf0010, 0x00c02021, 0x94a5000c, 0x24060001, - 0x0e000f78, 0x240706d8, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x3c020800, - 0x8c430020, 0x27bdffe0, 0xafb00010, 0x00808021, 0xafb20018, 0x00a09021, - 0xafb10014, 0x30d100ff, 0x1060001c, 0xafbf001c, 0x0e001006, 0x00000000, - 0x8f820018, 0xac500000, 0x8f840018, 0x24020001, 0xac820004, 0x8f830018, - 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, - 0xac520014, 0x8f840018, 0x3c026000, 0x8c434448, 0x3c020800, 0xac830018, - 0x9443466e, 0x8f840018, 0x3c024010, 0x00621825, 0xac83001c, 0x0e001044, - 0x02202021, 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, - 0x27bd0020, 0x27bdffe8, 0xafbf0014, 0xafb00010, 0x93620005, 0x30420001, - 0x10400033, 0x00808021, 0x3c029000, 0x34420001, 0x02021025, 0xaf420020, - 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620005, - 0x3c048000, 0x3c030800, 0x304200fe, 0xa3620005, 0x8c620020, 0x34840001, - 0x02042025, 0xaf440020, 0x10400020, 0x8fbf0014, 0x0e001006, 0x00000000, - 0x8f820018, 0xac500000, 0x93630082, 0x9362003f, 0x8f840018, 0x00031a00, - 0x00431025, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, - 0x8f830018, 0xac600010, 0x8f820018, 0xac400014, 0x8f840018, 0x3c026000, - 0x8c434448, 0x3c020800, 0xac830018, 0x9443466e, 0x8f840018, 0x3c02400a, - 0x00621825, 0xac83001c, 0x0e001044, 0x24040001, 0x8fbf0014, 0x8fb00010, - 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafbf0010, 0x8f420188, 0x00803021, - 0x9364003f, 0x24030012, 0x00021402, 0x1483001c, 0x304500ff, 0x3c029000, - 0x34420001, 0x3c038000, 0x00c21025, 0xa3650080, 0xa365007a, 0xaf420020, - 0x8f420020, 0x00431024, 0x1440fffd, 0x3c028000, 0x9363007d, 0x34420001, - 0x3c048000, 0x00c21025, 0xa363007d, 0xaf420020, 0x8f4201f8, 0x00441024, - 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4601c0, 0xa34201c4, 0xaf4301f8, - 0x0a000e54, 0x8fbf0010, 0x9362007e, 0x1445000e, 0x00000000, 0x93620080, - 0x1045000b, 0x00000000, 0xa3650080, 0x8f820000, 0x93660080, 0x8f440180, - 0x8f65004c, 0x8c430000, 0x0060f809, 0x00000000, 0x0a000e54, 0x8fbf0010, - 0xa3650080, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x3c020800, 0x8c430020, - 0x27bdffe0, 0xafb10014, 0x00808821, 0xafb20018, 0x00a09021, 0xafb00010, - 0x30d000ff, 0x1060002f, 0xafbf001c, 0x0e001006, 0x00000000, 0x8f820018, - 0xac510000, 0x8f830018, 0xac700004, 0x8f820018, 0xac520008, 0x8f830018, - 0xac60000c, 0x8f820018, 0xac400010, 0x9763006a, 0x00032880, 0x50a00001, - 0x24050001, 0x97630068, 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821, - 0x00852804, 0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050, - 0x00c4182b, 0x54600001, 0x00c02021, 0x8f830018, 0x2402fffe, 0x00822824, - 0x3c026000, 0xac650014, 0x8f840018, 0x8c434448, 0x3c020800, 0xac830018, - 0x9443466e, 0x8f840018, 0x3c024011, 0x00621825, 0xac83001c, 0x0e001044, - 0x24040001, 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, - 0x27bd0020, 0x27bdffe8, 0xafbf0014, 0xafb00010, 0x8f440100, 0x27500100, - 0x8f650050, 0x0e000c45, 0x9206001b, 0x3c020800, 0x8c430020, 0x1060001d, - 0x8e100018, 0x0e001006, 0x00000000, 0x8f840018, 0x8f420100, 0xac820000, - 0x8f830018, 0xac700004, 0x8f840018, 0x8f620050, 0xac820008, 0x8f830018, - 0xac60000c, 0x8f820018, 0xac400010, 0x8f830018, 0x3c026000, 0xac600014, - 0x8f850018, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x9443466e, - 0x8f850018, 0x3c02401c, 0x00621825, 0x0e001044, 0xaca3001c, 0x8fbf0014, - 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c029000, 0x8f460140, 0x34420001, - 0x3c038000, 0x00c21025, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, - 0x3c048000, 0x34840001, 0x3c059000, 0x34a50001, 0x3c078000, 0x24020012, - 0x24030080, 0x00c42025, 0x00c52825, 0xa362003f, 0xa3630082, 0xaf440020, - 0xaf450020, 0x8f420020, 0x00471024, 0x1440fffd, 0x3c038000, 0x9362007d, - 0x34630001, 0x3c048000, 0x00c31825, 0x34420020, 0xa362007d, 0xaf430020, - 0x8f4201f8, 0x00441024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4601c0, - 0xa34201c4, 0x03e00008, 0xaf4301f8, 0x8f430238, 0x3c020800, 0x04610013, - 0x8c44009c, 0x2406fffe, 0x3c050800, 0x3c038000, 0x2484ffff, 0x14800009, - 0x00000000, 0x97420078, 0x8ca3007c, 0x24420001, 0x00461024, 0x24630001, - 0xa7620010, 0x03e00008, 0xaca3007c, 0x8f420238, 0x00431024, 0x1440fff3, - 0x2484ffff, 0x8f420140, 0x3c031000, 0xaf420200, 0x03e00008, 0xaf430238, - 0x3c029000, 0x8f440140, 0x34420001, 0x3c038000, 0x00821025, 0xaf420020, - 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x3c038000, 0x9362007d, - 0x34630001, 0x3c058000, 0x00831825, 0x34420001, 0xa362007d, 0xaf430020, - 0x8f4201f8, 0x00451024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4401c0, - 0xa34201c4, 0x03e00008, 0xaf4301f8, 0x0000000d, 0x03e00008, 0x00000000, - 0x0000000d, 0x03e00008, 0x00000000, 0x24020001, 0x03e00008, 0xa7620010, - 0x9362003f, 0x304400ff, 0x3883000e, 0x2c630001, 0x38820010, 0x2c420001, - 0x00621825, 0x14600003, 0x24020012, 0x14820003, 0x00000000, 0x03e00008, - 0x00001021, 0x9363007e, 0x9362007a, 0x14620006, 0x00000000, 0x9363007e, - 0x24020001, 0x24630001, 0x03e00008, 0xa363007e, 0x9363007e, 0x93620080, - 0x14620004, 0x24020001, 0xa362000b, 0x03e00008, 0x24020001, 0x03e00008, - 0x00001021, 0x9362000b, 0x10400021, 0x00001021, 0xa360000b, 0x9362003f, - 0x304400ff, 0x3883000e, 0x2c630001, 0x38820010, 0x2c420001, 0x00621825, - 0x14600015, 0x00001821, 0x24020012, 0x10820012, 0x00000000, 0x9363007e, - 0x9362007a, 0x14620007, 0x00000000, 0x9362007e, 0x24030001, 0x24420001, - 0xa362007e, 0x03e00008, 0x00601021, 0x9363007e, 0x93620080, 0x14620004, - 0x00001821, 0x24020001, 0xa362000b, 0x24030001, 0x03e00008, 0x00601021, - 0x03e00008, 0x00000000, 0x24040001, 0xaf64000c, 0x8f6300dc, 0x8f6200cc, - 0x50620001, 0xa7640010, 0xa7640012, 0xa7640014, 0x03e00008, 0xa7640016, - 0x27bdffd8, 0xafb00010, 0x00808021, 0xafb3001c, 0x00c09821, 0xafbf0020, - 0xafb20018, 0xafb10014, 0x93620023, 0x00e09021, 0x30420040, 0x10400020, - 0x30b1ffff, 0x3c020800, 0x8c430020, 0x1060001c, 0x00000000, 0x0e001006, - 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x3c02008d, 0xac820004, - 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, - 0x8f820018, 0xac520014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, - 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018, 0x3c024019, 0x00621825, - 0x0e001044, 0xaca3001c, 0x93620023, 0x30420020, 0x14400003, 0x3c020800, - 0x52600020, 0x3c029000, 0x8c430020, 0x1060001d, 0x3c029000, 0x0e001006, - 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x00111400, 0xac820004, - 0x8f830018, 0xac720008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, - 0x8f820018, 0xac400014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, - 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018, 0x3c02401b, 0x00621825, - 0x0e001044, 0xaca3001c, 0x3c029000, 0x34420001, 0x02021025, 0xaf420020, - 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93630023, - 0x3c028000, 0x34420001, 0x02021025, 0x8fbf0020, 0x8fb3001c, 0x8fb20018, - 0x8fb10014, 0x8fb00010, 0x3063009f, 0xa3630023, 0xaf420020, 0x03e00008, - 0x27bd0028, 0x3c020800, 0x8c430020, 0x27bdffe8, 0xafb00010, 0x27500100, - 0x1060001d, 0xafbf0014, 0x0e001006, 0x00000000, 0x8f830018, 0x8e020004, - 0xac620000, 0x8f840018, 0x8e020018, 0xac820004, 0x8f850018, 0x8e020000, - 0xaca20008, 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010, 0x8f830018, - 0xac600014, 0x8f820018, 0xac400018, 0x96030008, 0x3c020800, 0x9444466e, - 0x8f850018, 0x00031c00, 0x00641825, 0x24040001, 0x0e001044, 0xaca3001c, - 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c060800, 0x24c54660, - 0x3c02000a, 0x03421821, 0x94640006, 0x94a2000a, 0x00441023, 0x00021400, - 0x00021c03, 0x04610006, 0xa4a40006, 0x0000000d, 0x00000000, 0x2400005a, - 0x0a00101b, 0x24020001, 0x8f820014, 0x0062102b, 0x14400002, 0x00001021, - 0x24020001, 0x304200ff, 0x1040001c, 0x274a0400, 0x3c07000a, 0x3c020800, - 0x24454660, 0x94a9000a, 0x8f880014, 0x03471021, 0x94430006, 0x00402021, - 0xa4a30006, 0x94820006, 0xa4a20006, 0x01221023, 0x00021400, 0x00021403, - 0x04410006, 0x0048102b, 0x0000000d, 0x00000000, 0x2400005a, 0x0a001036, - 0x24020001, 0x14400002, 0x00001021, 0x24020001, 0x304200ff, 0x1440ffec, - 0x03471021, 0x24c44660, 0x8c820010, 0xaf420038, 0x8c830014, 0x3c020005, - 0xaf43003c, 0xaf420030, 0xaf800010, 0xaf8a0018, 0x03e00008, 0x00000000, - 0x27bdffe0, 0x8f820010, 0x8f850018, 0x3c070800, 0x24e84660, 0xafbf001c, - 0xafb20018, 0xafb10014, 0xafb00010, 0x9503000a, 0x8d060014, 0x00009021, - 0x309000ff, 0x00e08821, 0x24420001, 0x24a50020, 0x24630001, 0xaf820010, - 0xaf850018, 0xa503000a, 0x24c30020, 0x3c028000, 0x04c10007, 0xad030014, - 0x00621024, 0x14400005, 0x26224660, 0x8d020010, 0x24420001, 0xad020010, - 0x26224660, 0x9444000a, 0x94450018, 0x0010102b, 0x00a41826, 0x2c630001, - 0x00621825, 0x1060001c, 0x3c030006, 0x8f820010, 0x24120001, 0x00021140, - 0x00431025, 0xaf420030, 0x00000000, 0x00000000, 0x00000000, 0x27450400, - 0x8f420000, 0x30420010, 0x1040fffd, 0x26224660, 0x9444000a, 0x94430018, - 0xaf800010, 0xaf850018, 0x14830012, 0x26274660, 0x0e0010d2, 0x00000000, - 0x1600000e, 0x26274660, 0x0e001006, 0x00000000, 0x0a00108f, 0x26274660, - 0x00041c00, 0x00031c03, 0x00051400, 0x00021403, 0x00621823, 0x18600002, - 0x3c026000, 0xac400808, 0x26274660, 0x94e2000e, 0x94e3000c, 0x24420001, - 0xa4e2000e, 0x3042ffff, 0x50430001, 0xa4e0000e, 0x12000005, 0x3c02000a, - 0x94e2000a, 0xa74200a2, 0x0a0010cc, 0x02401021, 0x03421821, 0x94640006, - 0x94e2000a, 0x00441023, 0x00021400, 0x00021c03, 0x04610006, 0xa4e40006, - 0x0000000d, 0x00000000, 0x2400005a, 0x0a0010ae, 0x24020001, 0x8f820014, - 0x0062102b, 0x14400002, 0x00001021, 0x24020001, 0x304200ff, 0x1040001b, - 0x3c020800, 0x3c06000a, 0x24454660, 0x94a8000a, 0x8f870014, 0x03461021, - 0x94430006, 0x00402021, 0xa4a30006, 0x94820006, 0xa4a20006, 0x01021023, - 0x00021400, 0x00021403, 0x04410006, 0x0047102b, 0x0000000d, 0x00000000, - 0x2400005a, 0x0a0010c8, 0x24020001, 0x14400002, 0x00001021, 0x24020001, - 0x304200ff, 0x1440ffec, 0x03461021, 0x02401021, 0x8fbf001c, 0x8fb20018, - 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3c020800, 0x24454660, - 0x94a3001a, 0x8ca40024, 0x00403021, 0x000318c0, 0x00832021, 0xaf44003c, - 0x8ca20020, 0xaf420038, 0x3c020050, 0x34420008, 0xaf420030, 0x00000000, - 0x00000000, 0x00000000, 0x8f420000, 0x30420020, 0x1040fffd, 0x00000000, - 0x8f430400, 0x24c64660, 0xacc30010, 0x8f420404, 0x3c030020, 0xacc20014, - 0xaf430030, 0x94c40018, 0x94c3001c, 0x94c2001a, 0x94c5001e, 0x00832021, - 0x24420001, 0xa4c2001a, 0x3042ffff, 0x14450002, 0xa4c40018, 0xa4c0001a, - 0x03e00008, 0x00000000, 0x8f820010, 0x3c030006, 0x00021140, 0x00431025, - 0xaf420030, 0x00000000, 0x00000000, 0x00000000, 0x27430400, 0x8f420000, - 0x30420010, 0x1040fffd, 0x00000000, 0xaf800010, 0xaf830018, 0x03e00008, - 0x00000000, 0x27bdffe8, 0xafb00010, 0x3c100800, 0x26104660, 0x3c05000a, - 0x02002021, 0x03452821, 0xafbf0014, 0x0e001128, 0x2406000a, 0x96020002, - 0x9603001e, 0x3042000f, 0x24420003, 0x00431804, 0x24027fff, 0x0043102b, - 0xaf830014, 0x10400004, 0x00000000, 0x0000000d, 0x00000000, 0x24000043, - 0x0e0010d2, 0x00000000, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, - 0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000, - 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, 0x0a001137, 0x00a01021, - 0xac860000, 0x24840004, 0x00a01021, 0x1440fffc, 0x24a5ffff, 0x03e00008, - 0x00000000, 0x3c036000, 0x8c642b7c, 0x3c036010, 0x8c6553fc, 0x00041582, - 0x00042302, 0x308403ff, 0x00052d82, 0x00441026, 0x0002102b, 0x0005282b, - 0x00451025, 0x1440000d, 0x3c020050, 0x34420004, 0xaf400038, 0xaf40003c, - 0xaf420030, 0x00000000, 0x00000000, 0x8f420000, 0x30420020, 0x1040fffd, - 0x3c020020, 0xaf420030, 0x0000000d, 0x03e00008, 0x00000000, 0x3c020050, - 0x34420004, 0xaf440038, 0xaf45003c, 0xaf420030, 0x00000000, 0x00000000, - 0x8f420000, 0x30420020, 0x1040fffd, 0x3c020020, 0xaf420030, 0x03e00008, - 0x00000000, 0x00000000 }; - -static u32 bnx2_COM_b06FwData[(0x0/4) + 1] = { 0x00000000 }; -static u32 bnx2_COM_b06FwRodata[(0x18/4) + 1] = { - 0x08002318, 0x08002348, 0x08002378, 0x080023a8, 0x080023d8, 0x00000000, - 0x00000000 }; + 0x8f420020, 0x00451024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, + 0x34420020, 0xa362007d, 0x8f640074, 0x34630001, 0x00c31825, 0xaf430020, + 0x04810006, 0x3c038000, 0x00c02021, 0x0e000470, 0x24050906, 0x0a0012a1, + 0x8fbf0010, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, + 0xaf4601c0, 0xa34201c4, 0xaf4301f8, 0x0a0012a1, 0x8fbf0010, 0x00c02021, + 0x94a5000c, 0x24060001, 0x0e000fb1, 0x2407090e, 0x8fbf0010, 0x03e00008, + 0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe0, 0xafb00010, 0x00808021, + 0xafb20018, 0x00a09021, 0xafb10014, 0x30d100ff, 0x1060001c, 0xafbf001c, + 0x0e00148e, 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x24020001, + 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, + 0xac600010, 0x8f820018, 0xac520014, 0x8f840018, 0x3c026000, 0x8c434448, + 0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c024010, 0x00621825, + 0xac83001c, 0x0e0014cc, 0x02202021, 0x8fbf001c, 0x8fb20018, 0x8fb10014, + 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0014, 0xafb00010, + 0x93620005, 0x30420001, 0x10400036, 0x00808021, 0x3c029000, 0x34420001, + 0x02021025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, + 0x00000000, 0x93620023, 0x34420004, 0xa3620023, 0x93630005, 0x3c048000, + 0x3c020800, 0x306300fe, 0xa3630005, 0x8c430020, 0x34840001, 0x02042025, + 0xaf440020, 0x10600020, 0x8fbf0014, 0x0e00148e, 0x00000000, 0x8f820018, + 0xac500000, 0x93630082, 0x9362003f, 0x8f840018, 0x00031a00, 0x00431025, + 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, + 0xac600010, 0x8f820018, 0xac400014, 0x8f840018, 0x3c026000, 0x8c434448, + 0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c02400a, 0x00621825, + 0xac83001c, 0x0e0014cc, 0x24040001, 0x8fbf0014, 0x8fb00010, 0x03e00008, + 0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe0, 0xafb10014, 0x00808821, + 0xafb20018, 0x00a09021, 0xafb00010, 0x30d000ff, 0x1060002f, 0xafbf001c, + 0x0e00148e, 0x00000000, 0x8f820018, 0xac510000, 0x8f830018, 0xac700004, + 0x8f820018, 0xac520008, 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010, + 0x9763006a, 0x00032880, 0x50a00001, 0x24050001, 0x97630068, 0x93640081, + 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b, 0x54400001, + 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001, 0x00c02021, + 0x8f830018, 0x2402fffe, 0x00822824, 0x3c026000, 0xac650014, 0x8f840018, + 0x8c434448, 0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c024011, + 0x00621825, 0xac83001c, 0x0e0014cc, 0x24040001, 0x8fbf001c, 0x8fb20018, + 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0014, + 0xafb00010, 0x8f440100, 0x27500100, 0x8f650050, 0x0e0010fc, 0x9206001b, + 0x3c020800, 0x8c430020, 0x1060001d, 0x8e100018, 0x0e00148e, 0x00000000, + 0x8f840018, 0x8f420100, 0xac820000, 0x8f830018, 0xac700004, 0x8f840018, + 0x8f620050, 0xac820008, 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010, + 0x8f830018, 0x3c026000, 0xac600014, 0x8f850018, 0x8c434448, 0x24040001, + 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c02401c, 0x00621825, + 0x0e0014cc, 0xaca3001c, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, + 0x8f430238, 0x3c020800, 0x04610013, 0x8c44009c, 0x2406fffe, 0x3c050800, + 0x3c038000, 0x2484ffff, 0x14800009, 0x00000000, 0x97420078, 0x8ca3007c, + 0x24420001, 0x00461024, 0x24630001, 0xa7620010, 0x03e00008, 0xaca3007c, + 0x8f420238, 0x00431024, 0x1440fff3, 0x2484ffff, 0x8f420140, 0x3c031000, + 0xaf420200, 0x03e00008, 0xaf430238, 0x27bdffe8, 0x3c029000, 0xafbf0010, + 0x8f450140, 0x34420001, 0x3c038000, 0x00a21025, 0xaf420020, 0x8f420020, + 0x00431024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0x34420001, + 0xa362007d, 0x8f640074, 0x34630001, 0x00a31825, 0xaf430020, 0x04810006, + 0x3c038000, 0x00a02021, 0x0e000470, 0x24050ac7, 0x0a0013b9, 0x8fbf0010, + 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4501c0, + 0xa34201c4, 0xaf4301f8, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x0000000d, + 0x03e00008, 0x00000000, 0x0000000d, 0x03e00008, 0x00000000, 0x24020001, + 0x03e00008, 0xa7620010, 0x9362003f, 0x304400ff, 0x3883000e, 0x2c630001, + 0x38820010, 0x2c420001, 0x00621825, 0x14600003, 0x24020012, 0x14820003, + 0x00000000, 0x03e00008, 0x00001021, 0x9363007e, 0x9362007a, 0x14620006, + 0x00000000, 0x9363007e, 0x24020001, 0x24630001, 0x03e00008, 0xa363007e, + 0x9362007e, 0x8f630178, 0x304200ff, 0x14430006, 0x00000000, 0x9363000b, + 0x24020001, 0x24630001, 0x03e00008, 0xa363000b, 0x03e00008, 0x00001021, + 0x9362000b, 0x10400023, 0x00001021, 0xa360000b, 0x9362003f, 0x304400ff, + 0x3883000e, 0x2c630001, 0x38820010, 0x2c420001, 0x00621825, 0x14600017, + 0x00001821, 0x24020012, 0x10820014, 0x00000000, 0x9363007e, 0x9362007a, + 0x14620007, 0x00000000, 0x9362007e, 0x24030001, 0x24420001, 0xa362007e, + 0x03e00008, 0x00601021, 0x9362007e, 0x8f630178, 0x304200ff, 0x14430005, + 0x00001821, 0x9362000b, 0x24030001, 0x24420001, 0xa362000b, 0x03e00008, + 0x00601021, 0x03e00008, 0x00000000, 0x24040001, 0xaf64000c, 0x8f6300dc, + 0x8f6200cc, 0x50620001, 0xa7640010, 0xa7640012, 0xa7640014, 0x03e00008, + 0xa7640016, 0x3c020800, 0x8c430020, 0x27bdffe8, 0x1060001b, 0xafbf0010, + 0x0e00148e, 0x00000000, 0x8f820018, 0xac400000, 0x8f830018, 0xac600004, + 0x8f820018, 0xac400008, 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010, + 0x8f830018, 0x3c026000, 0xac600014, 0x8f840018, 0x8c434448, 0x3c020800, + 0xac830018, 0x944358ce, 0x8f840018, 0x3c024020, 0x00621825, 0xac83001c, + 0x0e0014cc, 0x24040001, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x3c020800, + 0x8c430020, 0x27bdffe0, 0xafb00010, 0x00a08021, 0xafb10014, 0x00c08821, + 0xafb20018, 0x00e09021, 0x1060001e, 0xafbf001c, 0x0e00148e, 0x00000000, + 0x8f840018, 0x8f420100, 0xac820000, 0x8f830018, 0xac700004, 0x8f820018, + 0xac510008, 0x8f830018, 0xac72000c, 0x8f840018, 0x8fa20030, 0xac820010, + 0x8f830018, 0x8fa20034, 0xac620014, 0x8f840018, 0x3c026000, 0x8c434448, + 0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c0240c9, 0x00621825, + 0xac83001c, 0x0e0014cc, 0x24040001, 0x8fbf001c, 0x8fb20018, 0x8fb10014, + 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3c020800, 0x8c430020, 0x27bdffe8, + 0xafb00010, 0x27500100, 0x1060001d, 0xafbf0014, 0x0e00148e, 0x00000000, + 0x8f830018, 0x8e020004, 0xac620000, 0x8f840018, 0x8e020018, 0xac820004, + 0x8f850018, 0x8e020000, 0xaca20008, 0x8f830018, 0xac60000c, 0x8f820018, + 0xac400010, 0x8f830018, 0xac600014, 0x8f820018, 0xac400018, 0x96030008, + 0x3c020800, 0x944458ce, 0x8f850018, 0x00031c00, 0x00641825, 0x24040001, + 0x0e0014cc, 0xaca3001c, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, + 0x3c060800, 0x24c558c0, 0x3c02000a, 0x03421821, 0x94640006, 0x94a2000a, + 0x00441023, 0x00021400, 0x00021c03, 0x04610006, 0xa4a40006, 0x0000000d, + 0x00000000, 0x2400005a, 0x0a0014a3, 0x24020001, 0x8f820014, 0x0062102b, + 0x14400002, 0x00001021, 0x24020001, 0x304200ff, 0x1040001c, 0x274a0400, + 0x3c07000a, 0x3c020800, 0x244558c0, 0x94a9000a, 0x8f880014, 0x03471021, + 0x94430006, 0x00402021, 0xa4a30006, 0x94820006, 0xa4a20006, 0x01221023, + 0x00021400, 0x00021403, 0x04410006, 0x0048102b, 0x0000000d, 0x00000000, + 0x2400005a, 0x0a0014be, 0x24020001, 0x14400002, 0x00001021, 0x24020001, + 0x304200ff, 0x1440ffec, 0x03471021, 0x24c458c0, 0x8c820010, 0xaf420038, + 0x8c830014, 0x3c020005, 0xaf43003c, 0xaf420030, 0xaf800010, 0xaf8a0018, + 0x03e00008, 0x00000000, 0x27bdffe0, 0x8f820010, 0x8f850018, 0x3c070800, + 0x24e858c0, 0xafbf001c, 0xafb20018, 0xafb10014, 0xafb00010, 0x9503000a, + 0x8d060014, 0x00009021, 0x309000ff, 0x00e08821, 0x24420001, 0x24a50020, + 0x24630001, 0xaf820010, 0xaf850018, 0xa503000a, 0x24c30020, 0x3c028000, + 0x04c10007, 0xad030014, 0x00621024, 0x14400005, 0x262258c0, 0x8d020010, + 0x24420001, 0xad020010, 0x262258c0, 0x9444000a, 0x94450018, 0x0010102b, + 0x00a41826, 0x2c630001, 0x00621825, 0x1060001c, 0x3c030006, 0x8f820010, + 0x24120001, 0x00021140, 0x00431025, 0xaf420030, 0x00000000, 0x00000000, + 0x00000000, 0x27450400, 0x8f420000, 0x30420010, 0x1040fffd, 0x262258c0, + 0x9444000a, 0x94430018, 0xaf800010, 0xaf850018, 0x14830012, 0x262758c0, + 0x0e00155a, 0x00000000, 0x1600000e, 0x262758c0, 0x0e00148e, 0x00000000, + 0x0a001517, 0x262758c0, 0x00041c00, 0x00031c03, 0x00051400, 0x00021403, + 0x00621823, 0x18600002, 0x3c026000, 0xac400808, 0x262758c0, 0x94e2000e, + 0x94e3000c, 0x24420001, 0xa4e2000e, 0x3042ffff, 0x50430001, 0xa4e0000e, + 0x12000005, 0x3c02000a, 0x94e2000a, 0xa74200a2, 0x0a001554, 0x02401021, + 0x03421821, 0x94640006, 0x94e2000a, 0x00441023, 0x00021400, 0x00021c03, + 0x04610006, 0xa4e40006, 0x0000000d, 0x00000000, 0x2400005a, 0x0a001536, + 0x24020001, 0x8f820014, 0x0062102b, 0x14400002, 0x00001021, 0x24020001, + 0x304200ff, 0x1040001b, 0x3c020800, 0x3c06000a, 0x244558c0, 0x94a8000a, + 0x8f870014, 0x03461021, 0x94430006, 0x00402021, 0xa4a30006, 0x94820006, + 0xa4a20006, 0x01021023, 0x00021400, 0x00021403, 0x04410006, 0x0047102b, + 0x0000000d, 0x00000000, 0x2400005a, 0x0a001550, 0x24020001, 0x14400002, + 0x00001021, 0x24020001, 0x304200ff, 0x1440ffec, 0x03461021, 0x02401021, + 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, + 0x3c020800, 0x244558c0, 0x94a3001a, 0x8ca40024, 0x00403021, 0x000318c0, + 0x00832021, 0xaf44003c, 0x8ca20020, 0xaf420038, 0x3c020050, 0x34420008, + 0xaf420030, 0x00000000, 0x00000000, 0x00000000, 0x8f420000, 0x30420020, + 0x1040fffd, 0x00000000, 0x8f430400, 0x24c658c0, 0xacc30010, 0x8f420404, + 0x3c030020, 0xacc20014, 0xaf430030, 0x94c40018, 0x94c3001c, 0x94c2001a, + 0x94c5001e, 0x00832021, 0x24420001, 0xa4c2001a, 0x3042ffff, 0x14450002, + 0xa4c40018, 0xa4c0001a, 0x03e00008, 0x00000000, 0x8f820010, 0x3c030006, + 0x00021140, 0x00431025, 0xaf420030, 0x00000000, 0x00000000, 0x00000000, + 0x27430400, 0x8f420000, 0x30420010, 0x1040fffd, 0x00000000, 0xaf800010, + 0xaf830018, 0x03e00008, 0x00000000, 0x27bdffe8, 0xafb00010, 0x3c100800, + 0x261058c0, 0x3c05000a, 0x02002021, 0x03452821, 0xafbf0014, 0x0e0015b0, + 0x2406000a, 0x96020002, 0x9603001e, 0x3042000f, 0x24420003, 0x00431804, + 0x24027fff, 0x0043102b, 0xaf830014, 0x10400004, 0x00000000, 0x0000000d, + 0x00000000, 0x24000043, 0x0e00155a, 0x00000000, 0x8fbf0014, 0x8fb00010, + 0x03e00008, 0x27bd0018, 0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff, + 0x24a50004, 0xac820000, 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, + 0x0a0015c1, 0x00a01021, 0xac860000, 0x00000000, 0x00000000, 0x24840004, + 0x00a01021, 0x1440fffa, 0x24a5ffff, 0x03e00008, 0x00000000, 0x3c036000, + 0x8c642b7c, 0x3c036010, 0x8c6553fc, 0x00041582, 0x00042302, 0x308403ff, + 0x00052d82, 0x00441026, 0x0002102b, 0x0005282b, 0x00451025, 0x1440000d, + 0x3c020050, 0x34420004, 0xaf400038, 0xaf40003c, 0xaf420030, 0x00000000, + 0x00000000, 0x8f420000, 0x30420020, 0x1040fffd, 0x3c020020, 0xaf420030, + 0x0000000d, 0x03e00008, 0x00000000, 0x3c020050, 0x34420004, 0xaf440038, + 0xaf45003c, 0xaf420030, 0x00000000, 0x00000000, 0x8f420000, 0x30420020, + 0x1040fffd, 0x3c020020, 0xaf420030, 0x03e00008, 0x00000000, 0x00000000}; -static u32 bnx2_COM_b06FwBss[(0x88/4) + 1] = { 0x00000000 }; -static u32 bnx2_COM_b06FwSbss[(0x1c/4) + 1] = { 0x00000000 }; +static u32 bnx2_COM_b06FwData[(0x0/4) + 1] = { 0x0 }; +static u32 bnx2_COM_b06FwRodata[(0x58/4) + 1] = { + 0x08002428, 0x0800245c, 0x0800245c, 0x0800245c, 0x0800245c, 0x0800245c, + 0x08002380, 0x0800245c, 0x080023e4, 0x0800245c, 0x0800231c, 0x0800245c, + 0x0800245c, 0x0800245c, 0x08002328, 0x00000000, 0x08003240, 0x08003270, + 0x080032a0, 0x080032d0, 0x08003300, 0x00000000, 0x00000000 }; +static u32 bnx2_COM_b06FwBss[(0x88/4) + 1] = { 0x0 }; +static u32 bnx2_COM_b06FwSbss[(0x1c/4) + 1] = { 0x0 }; -static int bnx2_RXP_b06FwReleaseMajor = 0x0; +static int bnx2_RXP_b06FwReleaseMajor = 0x1; static int bnx2_RXP_b06FwReleaseMinor = 0x0; static int bnx2_RXP_b06FwReleaseFix = 0x0; -static u32 bnx2_RXP_b06FwStartAddr = 0x08000060; +static u32 bnx2_RXP_b06FwStartAddr = 0x08003104; static u32 bnx2_RXP_b06FwTextAddr = 0x08000000; -static int bnx2_RXP_b06FwTextLen = 0x20b8; -static u32 bnx2_RXP_b06FwDataAddr = 0x080020e0; +static int bnx2_RXP_b06FwTextLen = 0x562c; +static u32 bnx2_RXP_b06FwDataAddr = 0x08005660; static int bnx2_RXP_b06FwDataLen = 0x0; static u32 bnx2_RXP_b06FwRodataAddr = 0x00000000; static int bnx2_RXP_b06FwRodataLen = 0x0; -static u32 bnx2_RXP_b06FwBssAddr = 0x08002100; -static int bnx2_RXP_b06FwBssLen = 0x239c; -static u32 bnx2_RXP_b06FwSbssAddr = 0x080020e0; -static int bnx2_RXP_b06FwSbssLen = 0x14; - -static u32 bnx2_RXP_b06FwText[(0x20b8/4) + 1] = { - 0x0a000018, 0x00000000, 0x00000000, 0x0000000d, 0x72787020, 0x302e362e, - 0x39000000, 0x00060903, 0x00000000, 0x0000000d, 0x00000000, 0x00000000, +static u32 bnx2_RXP_b06FwBssAddr = 0x08005680; +static int bnx2_RXP_b06FwBssLen = 0x1394; +static u32 bnx2_RXP_b06FwSbssAddr = 0x08005660; +static int bnx2_RXP_b06FwSbssLen = 0x18; +static u32 bnx2_RXP_b06FwText[(0x562c/4) + 1] = { + 0x0a000c41, 0x00000000, 0x00000000, 0x0000000d, 0x72787020, 0x322e352e, + 0x38000000, 0x02050803, 0x00000000, 0x0000000d, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800, - 0x244220e0, 0x3c030800, 0x2463449c, 0xac400000, 0x0043202b, 0x1480fffd, - 0x24420004, 0x3c1d0800, 0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100060, - 0x3c1c0800, 0x279c20e0, 0x0e000329, 0x00000000, 0x0000000d, 0x8f870008, - 0x2ce20080, 0x10400018, 0x3c030800, 0x24633490, 0x8f460100, 0x00072140, - 0x00831021, 0xac460000, 0x8f450104, 0x00641021, 0xac450004, 0x8f460108, - 0xac460008, 0x8f45010c, 0xac45000c, 0x8f460114, 0xac460010, 0x8f450118, - 0xac450014, 0x8f460124, 0xac460018, 0x8f450128, 0x00641821, 0x24e20001, - 0xaf820008, 0xac65001c, 0x03e00008, 0x00000000, 0x00804021, 0x8f830000, - 0x24070001, 0x3c020001, 0x00621024, 0x10400037, 0x00603021, 0x9742010e, - 0x3c038000, 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, - 0xa342018b, 0x8f840004, 0x24020080, 0x24030002, 0xaf420180, 0xa743018c, - 0x10800005, 0xa745018e, 0x9743011c, 0x9742011e, 0x0a000069, 0x00021400, - 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c, - 0x24020003, 0x30838000, 0x1060000d, 0xa7420188, 0x93420116, 0x304200fc, - 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600005, 0x00000000, - 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c, - 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, - 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, 0x30c21000, - 0x1040000f, 0x00000000, 0x9742010c, 0x3042fc00, 0x5440000b, 0x24070005, - 0x3c021000, 0x00c21024, 0x10400007, 0x3c030dff, 0x3463ffff, 0x3c020e00, - 0x00c21024, 0x0062182b, 0x54600001, 0x24070005, 0x8f82000c, 0x30434000, - 0x10600016, 0x00404821, 0x3c020f00, 0x00c21024, 0x14400012, 0x00000000, - 0x93420116, 0x34424000, 0x03421821, 0x94650002, 0x2ca21389, 0x1040000b, - 0x3c020800, 0x24422100, 0x00051942, 0x00031880, 0x00621821, 0x30a5001f, - 0x8c640000, 0x24020001, 0x00a21004, 0x00822024, 0x01044025, 0x11000037, - 0x3c021000, 0x9742010e, 0x34e60002, 0x3c038000, 0x24420004, 0x3045ffff, - 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x8f840004, - 0x24020180, 0x24030002, 0xaf420180, 0xa743018c, 0x10800005, 0xa745018e, - 0x9743011c, 0x9742011e, 0x0a0000cd, 0x00021400, 0x9743011e, 0x9742011c, - 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c, 0x30828000, 0x1040000c, - 0xa7460188, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, - 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf82000c, - 0x9782000e, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, - 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x03e00008, - 0x00001021, 0x00c21024, 0x104000ba, 0x3c020800, 0x8c430030, 0x1060003e, - 0x31224000, 0x1040003c, 0x3c030f00, 0x00c31824, 0x3c020100, 0x0043102b, - 0x14400038, 0x3c030800, 0x9742010e, 0x34e60002, 0x3c038000, 0x24420004, - 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, - 0x8f840004, 0x24020080, 0x24030002, 0xaf420180, 0xa743018c, 0x10800005, - 0xa745018e, 0x9743011c, 0x9742011e, 0x0a000110, 0x00021400, 0x9743011e, - 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c, 0x30828000, - 0x1040000c, 0xa7460188, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, - 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024, - 0xaf82000c, 0x9782000e, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, - 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, - 0x03e00008, 0x00001021, 0x3c030800, 0x8c620024, 0x30420008, 0x1040003d, - 0x34e80002, 0x3c020f00, 0x00c21024, 0x5440003a, 0x3107ffff, 0x9742010c, - 0x30420200, 0x50400036, 0x3107ffff, 0x9742010e, 0x30e6fffb, 0x3c038000, - 0x24420004, 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, - 0xa342018b, 0x8f840004, 0x24020180, 0x24030002, 0xaf420180, 0xa743018c, - 0x10800005, 0xa745018e, 0x9743011c, 0x9742011e, 0x0a000153, 0x00021400, - 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c, - 0x30828000, 0x1040000c, 0xa7460188, 0x93420116, 0x304200fc, 0x005a1021, - 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, - 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c, 0x8f440104, 0x3042bfff, - 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, - 0xaf4201b8, 0x3107ffff, 0x8f820000, 0x3c068000, 0x9743010e, 0x00021442, - 0x30440780, 0x24630004, 0x3065ffff, 0x8f4201b8, 0x00461024, 0x1440fffd, - 0x24020003, 0xa342018b, 0x8f830004, 0x24020002, 0xaf440180, 0xa742018c, - 0x10600005, 0xa745018e, 0x9743011c, 0x9742011e, 0x0a000189, 0x00021400, - 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800, 0x24425660, + 0x3c030800, 0x24636a14, 0xac400000, 0x0043202b, 0x1480fffd, 0x24420004, + 0x3c1d0800, 0x37bd7ffc, 0x03a0f021, 0x3c100800, 0x26103104, 0x3c1c0800, + 0x279c5660, 0x0e001035, 0x00000000, 0x0000000d, 0x3c080800, 0x8d023100, + 0x2c420080, 0x50400001, 0xad003100, 0x8d073100, 0x3c040800, 0x24840100, + 0x8f460100, 0x00071840, 0x00671821, 0x00031940, 0x00641021, 0xac460000, + 0x8f450104, 0x00831021, 0xac450004, 0x8f460108, 0xac460008, 0x8f45010c, + 0xac45000c, 0x8f460114, 0xac460010, 0x8f450118, 0xac450014, 0x8f460124, + 0xac460018, 0x8f450128, 0xac45001c, 0x8f464010, 0xac460020, 0x8f454014, + 0xac450024, 0x8f464018, 0xac460028, 0x8f45401c, 0xac45002c, 0x8f464020, + 0xac460030, 0x8f454024, 0xac450034, 0x8f464028, 0xac460038, 0x8f45402c, + 0xac45003c, 0x8f464030, 0xac460040, 0x8f454034, 0xac450044, 0x8f464038, + 0xac460048, 0x8f45403c, 0xac45004c, 0x8f464040, 0xac460050, 0x8f454044, + 0xac450054, 0x8f464048, 0xac460058, 0x8f45404c, 0x24e70001, 0x00402021, + 0xad073100, 0x03e00008, 0xac85005c, 0x8f820004, 0x9743010c, 0x00804821, + 0x00403021, 0x30421000, 0x10400010, 0x306affff, 0x30c20020, 0x1440000e, + 0x24070005, 0x3c021000, 0x00c21024, 0x10400009, 0x3c030dff, 0x3463ffff, + 0x3c020e00, 0x00c21024, 0x0062182b, 0x50600004, 0x24070001, 0x0a000cb1, + 0x3c020800, 0x24070001, 0x3c020800, 0x8c430034, 0x1460001d, 0x00405821, + 0x8f820010, 0x30424000, 0x1440001a, 0x3c020001, 0x3c021f01, 0x00c24024, + 0x3c031000, 0x15030015, 0x3c020001, 0x31420200, 0x54400012, 0x3c020001, + 0x9744010e, 0x24020003, 0xa342018b, 0x97850012, 0x24020002, 0x34e30002, + 0xaf400180, 0xa742018c, 0xa7430188, 0x24840004, 0x30a5bfff, 0xa744018e, + 0xa74501a6, 0xaf4801b8, 0x03e00008, 0x00001021, 0x3c020001, 0x00c21024, + 0x10400039, 0x00000000, 0x9742010e, 0x3c038000, 0x3046ffff, 0x8f4201b8, + 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x97840006, 0x8f85000c, + 0x24020080, 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0x10a00005, + 0xa7440190, 0x9743011c, 0x9742011e, 0x0a000cec, 0x00021400, 0x9743011e, + 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010, 0x24020003, + 0x30838000, 0x1060000d, 0xa7420188, 0x93420116, 0x304200fc, 0x005a1021, + 0x24424004, 0x8c430000, 0x3063ffff, 0x14600005, 0x00000000, 0x3c02ffff, + 0x34427fff, 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, + 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, + 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, 0x8f820010, 0x30434000, + 0x10600016, 0x00404021, 0x3c020f00, 0x00c21024, 0x14400012, 0x00000000, + 0x93420116, 0x34424000, 0x03421821, 0x94650002, 0x2ca21389, 0x1040000b, + 0x3c020800, 0x24425680, 0x00051942, 0x00031880, 0x00621821, 0x30a5001f, + 0x8c640000, 0x24020001, 0x00a21004, 0x00822024, 0x01244825, 0x11200039, + 0x3c021000, 0x9742010e, 0x34e70002, 0x3c038000, 0x24420004, 0x3046ffff, + 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x97840006, + 0x8f85000c, 0x24020180, 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, + 0x10a00005, 0xa7440190, 0x9743011c, 0x9742011e, 0x0a000d41, 0x00021400, + 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010, 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, - 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c, 0x8f440104, 0x3042bfff, + 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, - 0xaf4201b8, 0x03e00008, 0x00001021, 0x8f424000, 0x30420100, 0x104000ef, - 0x3c020800, 0x8c440024, 0x24030001, 0x14830036, 0x00404021, 0x9742010e, - 0x34e50002, 0x3c038000, 0x24420004, 0x3044ffff, 0x8f4201b8, 0x00431024, - 0x1440fffd, 0x24020003, 0xa342018b, 0x8f830004, 0x24020002, 0xaf400180, - 0xa742018c, 0x10600005, 0xa744018e, 0x9743011c, 0x9742011e, 0x0a0001c6, + 0xaf4201b8, 0x03e00008, 0x00001021, 0x00c21024, 0x104000e3, 0x3c020800, + 0x8c430030, 0x10600040, 0x31024000, 0x1040003e, 0x3c030f00, 0x00c31824, + 0x3c020100, 0x0043102b, 0x1440003a, 0x3c030800, 0x9742010e, 0x34e70002, + 0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, + 0x24020003, 0xa342018b, 0x97840006, 0x8f85000c, 0x24020080, 0x24030002, + 0xaf420180, 0xa743018c, 0xa746018e, 0x10a00005, 0xa7440190, 0x9743011c, + 0x9742011e, 0x0a000d86, 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, + 0x00621825, 0xaf4301a8, 0x8f840010, 0x30828000, 0x1040000c, 0xa7470188, + 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, + 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf820010, 0x97820012, + 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, + 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, + 0x3c030800, 0x8c620024, 0x30420008, 0x1040003e, 0x34e80002, 0x3c020f00, + 0x00c21024, 0x1440003b, 0x8d620034, 0x31420200, 0x10400038, 0x8d620034, + 0x9742010e, 0x30e7fffb, 0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, + 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x97840006, 0x8f85000c, + 0x24020180, 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0x10a00005, + 0xa7440190, 0x9743011c, 0x9742011e, 0x0a000dca, 0x00021400, 0x9743011e, + 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010, 0x30828000, + 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, + 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024, + 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, + 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, + 0x8d620034, 0x8f860004, 0x1040001a, 0x30c20100, 0x10400018, 0x3c020f00, + 0x00c21024, 0x3c030200, 0x10430014, 0x00000000, 0x8f82000c, 0x10400004, + 0x00000000, 0x9742011c, 0x0a000df8, 0x3044ffff, 0x9742011e, 0x3044ffff, + 0x3c030800, 0x8c620038, 0x3c030800, 0x2463003c, 0x2442ffff, 0x00822024, + 0x00831821, 0x90620000, 0x24420004, 0x0a000e0d, 0x000229c0, 0x00000000, + 0x00061602, 0x3042000f, 0x000229c0, 0x3c04fc00, 0x00441021, 0x3c030300, + 0x0062182b, 0x50600001, 0x24050800, 0x9742010e, 0x3107ffff, 0x3c038000, + 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, + 0xa342018b, 0x97830006, 0x8f84000c, 0x24020002, 0xaf450180, 0xa742018c, + 0xa746018e, 0x10800005, 0xa7430190, 0x9743011c, 0x9742011e, 0x0a000e26, 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, - 0x8f84000c, 0x30828000, 0x1040000c, 0xa7450188, 0x93420116, 0x304200fc, + 0x8f840010, 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, - 0x34427fff, 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c, 0x8f440104, + 0x34427fff, 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, - 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, 0x30820001, 0x10400035, - 0x30e90004, 0x9742010e, 0x30e6fffb, 0x3c038000, 0x24420004, 0x3044ffff, - 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x8f830004, - 0x24020002, 0xaf400180, 0xa742018c, 0x10600005, 0xa744018e, 0x9743011c, - 0x9742011e, 0x0a0001fe, 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, - 0x00621825, 0xaf4301a8, 0x8f84000c, 0x30828000, 0x1040000c, 0xa7470188, - 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, - 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf82000c, 0x9782000e, - 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, - 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x30c7ffff, 0x8d020024, - 0x30420004, 0x10400037, 0x8d020024, 0x9742010e, 0x30e6fffb, 0x3c038000, - 0x24420004, 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, - 0xa342018b, 0x8f840004, 0x24020100, 0x24030002, 0xaf420180, 0xa743018c, - 0x10800005, 0xa745018e, 0x9743011c, 0x9742011e, 0x0a000237, 0x00021400, - 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c, - 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021, - 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, - 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c, 0x8f440104, 0x3042bfff, - 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, - 0xaf4201b8, 0x30c7ffff, 0x8d020024, 0x30420008, 0x10400034, 0x00000000, - 0x9742010e, 0x3c038000, 0x24420004, 0x3045ffff, 0x8f4201b8, 0x00431024, - 0x1440fffd, 0x24020003, 0xa342018b, 0x8f840004, 0x24020180, 0x24030002, - 0xaf420180, 0xa743018c, 0x10800005, 0xa745018e, 0x9743011c, 0x9742011e, - 0x0a00026f, 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, - 0xaf4301a8, 0x8f84000c, 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, + 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, 0x8f424000, 0x30420100, + 0x104000f9, 0x3c020800, 0x8c440024, 0x24030001, 0x14830038, 0x00404821, + 0x9742010e, 0x34e60002, 0x3c038000, 0x24420004, 0x3045ffff, 0x8f4201b8, + 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x97830006, 0x8f84000c, + 0x24020002, 0xaf400180, 0xa742018c, 0xa745018e, 0x10800005, 0xa7430190, + 0x9743011c, 0x9742011e, 0x0a000e65, 0x00021400, 0x9743011e, 0x9742011c, + 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010, 0x30828000, 0x1040000c, + 0xa7460188, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, + 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf820010, + 0x97820012, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, + 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x03e00008, + 0x00001021, 0x30820001, 0x10400037, 0x30ea0004, 0x9742010e, 0x30e8fffb, + 0x3c038000, 0x24420004, 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, + 0x24020003, 0xa342018b, 0x97830006, 0x8f84000c, 0x24020002, 0xaf400180, + 0xa742018c, 0xa745018e, 0x10800005, 0xa7430190, 0x9743011c, 0x9742011e, + 0x0a000e9f, 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, + 0xaf4301a8, 0x8f840010, 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, - 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c, + 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, - 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x15200046, 0x00001021, 0x3c038000, - 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0x24032000, 0xa342018b, - 0xa7430188, 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, 0x3c030800, - 0x8c620024, 0x30420001, 0x10400035, 0x00001021, 0x9742010e, 0x34e50002, - 0x3c038000, 0x24420004, 0x3044ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, - 0x24020003, 0xa342018b, 0x8f830004, 0x24020002, 0xaf400180, 0xa742018c, - 0x10600005, 0xa744018e, 0x9743011c, 0x9742011e, 0x0a0002b5, 0x00021400, - 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c, - 0x30828000, 0x1040000c, 0xa7450188, 0x93420116, 0x304200fc, 0x005a1021, - 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, - 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c, 0x8f440104, 0x3042bfff, - 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, - 0xaf4201b8, 0x00001021, 0x03e00008, 0x00000000, 0x27bdffe0, 0xafbf0018, - 0xafb10014, 0xafb00010, 0x8f420140, 0xaf420020, 0x8f430148, 0x3c027000, - 0x00621824, 0x3c024000, 0x1062000c, 0x0043102b, 0x14400006, 0x3c025000, - 0x3c023000, 0x1062000b, 0x3c024000, 0x0a00031f, 0x00000000, 0x10620034, - 0x3c024000, 0x0a00031f, 0x00000000, 0x0e00067c, 0x00000000, 0x0a00031f, + 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x3107ffff, 0x8d220024, 0x30420004, + 0x10400039, 0x8d220024, 0x9742010e, 0x30e8fffb, 0x3c038000, 0x24420004, + 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, + 0x97840006, 0x8f85000c, 0x24020100, 0x24030002, 0xaf420180, 0xa743018c, + 0xa746018e, 0x10a00005, 0xa7440190, 0x9743011c, 0x9742011e, 0x0a000eda, + 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, + 0x8f840010, 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, + 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, + 0x34427fff, 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, + 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, + 0x3c021000, 0xaf4201b8, 0x3107ffff, 0x8d220024, 0x30420008, 0x10400036, + 0x00000000, 0x9742010e, 0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, + 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x97840006, 0x8f85000c, + 0x24020180, 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0x10a00005, + 0xa7440190, 0x9743011c, 0x9742011e, 0x0a000f14, 0x00021400, 0x9743011e, + 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010, 0x30828000, + 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, + 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024, + 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, + 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, + 0x1540004a, 0x00001021, 0x27440180, 0x3c038000, 0x8f4201b8, 0x00431024, + 0x1440fffd, 0x24022000, 0x24030002, 0xa4820008, 0xa083000b, 0xa4800010, + 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, 0x3c030800, 0x8c620024, + 0x30420001, 0x10400037, 0x00001021, 0x9742010e, 0x34e60002, 0x3c038000, + 0x24420004, 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, + 0xa342018b, 0x97830006, 0x8f84000c, 0x24020002, 0xaf400180, 0xa742018c, + 0xa745018e, 0x10800005, 0xa7430190, 0x9743011c, 0x9742011e, 0x0a000f5e, + 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, + 0x8f840010, 0x30828000, 0x1040000c, 0xa7460188, 0x93420116, 0x304200fc, + 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, + 0x34427fff, 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, + 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, + 0x3c021000, 0xaf4201b8, 0x00001021, 0x03e00008, 0x00000000, 0x27bdffe8, + 0xafbf0010, 0x8f460128, 0x8f84000c, 0xaf460020, 0x8f450104, 0x8f420100, + 0x24030800, 0xaf850004, 0xaf820010, 0xaf4301b8, 0x1080000a, 0x3c020800, + 0x8c430034, 0x10600007, 0x30a22000, 0x10400005, 0x34a30100, 0x8f820008, + 0xaf830004, 0x24420001, 0xaf820008, 0x3c020800, 0x8c4300c0, 0x10600006, + 0x3c030800, 0x8c6200c4, 0x24040001, 0x24420001, 0x0a000fc0, 0xac6200c4, + 0x8f820004, 0x3c030010, 0x00431024, 0x14400009, 0x3c02001f, 0x3c030800, + 0x8c620020, 0x00002021, 0x24420001, 0x0e000c99, 0xac620020, 0x0a000fc0, + 0x00402021, 0x3442ff00, 0x14c20009, 0x2403bfff, 0x3c030800, 0x8c620020, + 0x24040001, 0x24420001, 0x0e000c99, 0xac620020, 0x0a000fc0, 0x00402021, + 0x8f820010, 0x00431024, 0x14400006, 0x00000000, 0xaf400048, 0x0e001144, + 0xaf400040, 0x0a000fc0, 0x00402021, 0x0e0014c9, 0x00000000, 0x00402021, + 0x10800005, 0x3c024000, 0x8f430124, 0x3c026020, 0xac430014, 0x3c024000, + 0xaf420138, 0x00000000, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe0, + 0xafbf0018, 0xafb10014, 0xafb00010, 0x8f420140, 0xaf420020, 0x8f430148, + 0x3c027000, 0x00621824, 0x3c023000, 0x10620021, 0x0043102b, 0x14400006, + 0x3c024000, 0x3c022000, 0x10620009, 0x3c024000, 0x0a00102b, 0x00000000, + 0x10620045, 0x3c025000, 0x10620047, 0x3c024000, 0x0a00102b, 0x00000000, + 0x27440180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, + 0x8f420148, 0x24030002, 0xa083000b, 0x00021402, 0xa4820008, 0x8f430148, + 0xa4830010, 0x8f420144, 0x3c031000, 0xac820024, 0xaf4301b8, 0x0a00102b, 0x3c024000, 0x8f420148, 0x24030002, 0x3044ffff, 0x00021402, 0x305000ff, 0x1203000c, 0x27510180, 0x2a020003, 0x10400005, 0x24020003, 0x0600001d, - 0x36053000, 0x0a00030a, 0x3c038000, 0x12020007, 0x00000000, 0x0a000317, - 0x00000000, 0x0e000423, 0x00000000, 0x0a000308, 0x00402021, 0x0e000435, + 0x36053000, 0x0a001012, 0x3c038000, 0x12020007, 0x00000000, 0x0a00101f, + 0x00000000, 0x0e00111f, 0x00000000, 0x0a001010, 0x00402021, 0x0e001131, 0x00000000, 0x00402021, 0x36053000, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0xa6250008, 0xa222000b, 0xa6240010, 0x8f420144, - 0x3c031000, 0xae220024, 0xaf4301b8, 0x0a00031f, 0x3c024000, 0x0000000d, - 0x00000000, 0x240001c3, 0x0a00031f, 0x3c024000, 0x0e0007f7, 0x00000000, - 0x3c024000, 0xaf420178, 0x00000000, 0x8fbf0018, 0x8fb10014, 0x8fb00010, - 0x03e00008, 0x27bd0020, 0x24020800, 0x03e00008, 0xaf4201b8, 0x27bdffe8, - 0x3c04600c, 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000, 0x2403ff7f, - 0x3c106000, 0x00431024, 0x3442380c, 0x24030003, 0xac825000, 0x3c040008, - 0xaf430008, 0x8e020808, 0x3c030800, 0xac600020, 0x3042fff0, 0x2c420001, - 0xaf820004, 0x0e000819, 0x0344d825, 0x0e000781, 0x00000000, 0x3c020400, - 0x3442000c, 0x3c03ffff, 0x34630806, 0xae021948, 0xae03194c, 0x8e021980, - 0x34420200, 0xae021980, 0x8f500000, 0x32020003, 0x1040fffd, 0x32020001, - 0x10400004, 0x32020002, 0x0e0003bd, 0x00000000, 0x32020002, 0x1040fff6, - 0x00000000, 0x0e0002d4, 0x00000000, 0x0a00034a, 0x00000000, 0x27bdffe8, - 0x3c04600c, 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000, 0x2403ff7f, - 0x3c106000, 0x00431024, 0x3442380c, 0x24030003, 0xac825000, 0x3c040008, - 0xaf430008, 0x8e020808, 0x3c030800, 0xac600020, 0x3042fff0, 0x2c420001, - 0xaf820004, 0x0e000819, 0x0344d825, 0x0e000781, 0x00000000, 0x3c020400, - 0x3442000c, 0x3c03ffff, 0x34630806, 0xae021948, 0xae03194c, 0x8e021980, - 0x8fbf0014, 0x34420200, 0xae021980, 0x8fb00010, 0x03e00008, 0x27bd0018, - 0x30a5ffff, 0x30c6ffff, 0x30e7ffff, 0x3c038000, 0x8f4201b8, 0x00431024, - 0x1440fffd, 0x24020003, 0xa342018b, 0x8f830004, 0xaf440180, 0xa745018c, - 0x10600005, 0xa746018e, 0x9743011c, 0x9742011e, 0x0a000393, 0x00021400, - 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c, + 0x3c031000, 0xae220024, 0xaf4301b8, 0x0a00102b, 0x3c024000, 0x0000000d, + 0x00000000, 0x24000295, 0x0a00102b, 0x3c024000, 0x0e0013a7, 0x00000000, + 0x0a00102b, 0x3c024000, 0x0e001552, 0x00000000, 0x3c024000, 0xaf420178, + 0x00000000, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, + 0x24020800, 0x03e00008, 0xaf4201b8, 0x27bdffe8, 0x3c04600c, 0xafbf0014, + 0xafb00010, 0x8c825000, 0x3c1a8000, 0x2403ff7f, 0x3c106000, 0x00431024, + 0x3442380c, 0x24030003, 0xac825000, 0x3c020008, 0xaf430008, 0x8e040808, + 0x0342d825, 0x8e020808, 0x3c030800, 0xac600020, 0x3084fff0, 0x2c840001, + 0x3042fff0, 0x38420010, 0x2c420001, 0xaf84000c, 0xaf820000, 0x0e001574, + 0x00000000, 0x0e0014c7, 0x00000000, 0x3c020400, 0x3442000c, 0x3c03ffff, + 0x34630806, 0xae021948, 0xae03194c, 0x8e021980, 0x34420200, 0xae021980, + 0x8f500000, 0x32020003, 0x1040fffd, 0x32020001, 0x10400004, 0x32020002, + 0x0e000f7d, 0x00000000, 0x32020002, 0x1040fff6, 0x00000000, 0x0e000fcb, + 0x00000000, 0x0a00105c, 0x00000000, 0x27bdffe8, 0x3c04600c, 0xafbf0014, + 0xafb00010, 0x8c825000, 0x3c1a8000, 0x2403ff7f, 0x3c106000, 0x00431024, + 0x3442380c, 0x24030003, 0xac825000, 0x3c020008, 0xaf430008, 0x8e040808, + 0x0342d825, 0x8e020808, 0x3c030800, 0xac600020, 0x3084fff0, 0x2c840001, + 0x3042fff0, 0x38420010, 0x2c420001, 0xaf84000c, 0xaf820000, 0x0e001574, + 0x00000000, 0x0e0014c7, 0x00000000, 0x3c020400, 0x3442000c, 0x3c03ffff, + 0x34630806, 0xae021948, 0xae03194c, 0x8e021980, 0x8fbf0014, 0x34420200, + 0xae021980, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x30a5ffff, 0x30c6ffff, + 0x30e7ffff, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, + 0xa342018b, 0x97830006, 0x8f82000c, 0xaf440180, 0xa745018c, 0xa746018e, + 0x10400005, 0xa7430190, 0x9743011c, 0x9742011e, 0x0a0010ad, 0x00021400, + 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f840010, 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, - 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c, 0x8f440104, 0x3042bfff, + 0x00821024, 0xaf820010, 0x97820012, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, - 0xaf4201b8, 0x03e00008, 0x00000000, 0x3c038000, 0x8f4201b8, 0x00431024, - 0x1440fffd, 0x24020002, 0x24032000, 0xa342018b, 0xa7430188, 0x3c021000, - 0xaf4201b8, 0x03e00008, 0x00000000, 0x27bdffe8, 0xafbf0010, 0x8f460128, - 0xaf460020, 0x8f420104, 0x8f450100, 0x24030800, 0x3c040010, 0xaf820000, - 0x00441024, 0xaf85000c, 0xaf4301b8, 0x14400005, 0x3c02001f, 0x3c030800, - 0x8c620020, 0x0a0003d5, 0x00002021, 0x3442ff00, 0x14c20009, 0x2402bfff, - 0x3c030800, 0x8c620020, 0x24040001, 0x24420001, 0x0e00004c, 0xac620020, - 0x0a0003e4, 0x00000000, 0x00a21024, 0x14400006, 0x00000000, 0xaf400048, - 0x0e000448, 0xaf400040, 0x0a0003e4, 0x00000000, 0x0e000783, 0x00000000, - 0x10400005, 0x3c024000, 0x8f430124, 0x3c026020, 0xac430014, 0x3c024000, - 0xaf420138, 0x00000000, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe0, + 0xaf4201b8, 0x03e00008, 0x00000000, 0x27440180, 0x3c038000, 0x8f4201b8, + 0x00431024, 0x1440fffd, 0x24022000, 0x24030002, 0xa4820008, 0xa083000b, + 0xa4800010, 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00000000, 0x27440180, + 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420148, + 0x24030002, 0xa083000b, 0x00021402, 0xa4820008, 0x8f430148, 0xa4830010, + 0x8f420144, 0x3c031000, 0xac820024, 0x03e00008, 0xaf4301b8, 0x27bdffe0, 0xafbf0018, 0xafb10014, 0xafb00010, 0x8f420148, 0x24030002, 0x3044ffff, 0x00021402, 0x305000ff, 0x1203000c, 0x27510180, 0x2a020003, 0x10400005, - 0x24020003, 0x0600001d, 0x36053000, 0x0a00040e, 0x3c038000, 0x12020007, - 0x00000000, 0x0a00041b, 0x00000000, 0x0e000423, 0x00000000, 0x0a00040c, - 0x00402021, 0x0e000435, 0x00000000, 0x00402021, 0x36053000, 0x3c038000, + 0x24020003, 0x0600001d, 0x36053000, 0x0a00110a, 0x3c038000, 0x12020007, + 0x00000000, 0x0a001117, 0x00000000, 0x0e00111f, 0x00000000, 0x0a001108, + 0x00402021, 0x0e001131, 0x00000000, 0x00402021, 0x36053000, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0xa6250008, 0xa222000b, - 0xa6240010, 0x8f420144, 0x3c031000, 0xae220024, 0xaf4301b8, 0x0a00041f, - 0x8fbf0018, 0x0000000d, 0x00000000, 0x240001c3, 0x8fbf0018, 0x8fb10014, + 0xa6240010, 0x8f420144, 0x3c031000, 0xae220024, 0xaf4301b8, 0x0a00111b, + 0x8fbf0018, 0x0000000d, 0x00000000, 0x24000295, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3084ffff, 0x2c821389, 0x1040000d, - 0x00001021, 0x3c030800, 0x24632100, 0x00042942, 0x00052880, 0x00a32821, + 0x00001021, 0x3c030800, 0x24635680, 0x00042942, 0x00052880, 0x00a32821, 0x3086001f, 0x8ca40000, 0x24030001, 0x00c31804, 0x00832025, 0x03e00008, 0xaca40000, 0x03e00008, 0x24020091, 0x3084ffff, 0x2c821389, 0x1040000e, - 0x00001021, 0x3c030800, 0x24632100, 0x00042942, 0x00052880, 0x00a32821, + 0x00001021, 0x3c030800, 0x24635680, 0x00042942, 0x00052880, 0x00a32821, 0x3086001f, 0x24030001, 0x8ca40000, 0x00c31804, 0x00031827, 0x00832024, - 0x03e00008, 0xaca40000, 0x03e00008, 0x24020091, 0x27bdffb0, 0x3c026000, - 0xafbf0048, 0x8c434448, 0xaf630140, 0x93620005, 0x30420001, 0x14400005, - 0x00000000, 0x0e0007ed, 0x00000000, 0x0a00067a, 0x8fbf0048, 0x93420116, - 0x93430112, 0x8f430104, 0x3c040020, 0x34424000, 0x00641824, 0x1060000d, - 0x03426021, 0x8f430128, 0x27420180, 0xac430000, 0x8f650040, 0x24040008, - 0x240340c1, 0xa4430008, 0x24030002, 0xa043000b, 0x3c031000, 0x0a000563, - 0xa044000a, 0x8f420104, 0x3c030040, 0x00431024, 0x10400007, 0x00000000, - 0x8f430128, 0x27420180, 0xac430000, 0x8f650040, 0x0a00055c, 0x24040010, - 0xaf400048, 0xaf400054, 0xaf400040, 0x8f630048, 0x8f620040, 0x00624823, - 0x05210004, 0x00000000, 0x0000000d, 0x00000000, 0x24000132, 0x9742011a, - 0x3046ffff, 0x10c00004, 0x8d880004, 0x01061021, 0x0a000487, 0x2445ffff, - 0x01002821, 0x918a000d, 0xa7a00020, 0xafa00028, 0x9364003f, 0x3c026000, - 0x8c434448, 0x308700ff, 0x31420004, 0x10400033, 0xaf630144, 0x24090012, - 0x14e90006, 0x3c040800, 0x8c830028, 0x24020001, 0x24630001, 0x0a00054e, - 0xac830028, 0x8f620044, 0x15020012, 0x97a20020, 0x27a60010, 0x27450180, - 0x3442001a, 0xa7a20020, 0x8f630040, 0x3c048000, 0x24020020, 0xa3a70022, - 0xa3a90023, 0xa3a2001a, 0xafa30028, 0x8f4201b8, 0x00441024, 0x1440fffd, - 0x00000000, 0x0a000533, 0x00000000, 0x8f620044, 0x01021023, 0x0440009e, - 0x24020001, 0x8f620048, 0x01021023, 0x0441009a, 0x24020001, 0x97a20020, - 0x27a60010, 0x34420001, 0xa7a20020, 0x8f630040, 0x27450180, 0x3c048000, - 0xafa30028, 0x8f4201b8, 0x00441024, 0x1440fffd, 0x00000000, 0x0a000533, - 0x00000000, 0x3c026000, 0x8c424448, 0xaf620148, 0x8f630040, 0x00685823, - 0x19600013, 0x00cb102a, 0x54400007, 0x314a00fe, 0x5566000c, 0x010b4021, - 0x31420001, 0x54400009, 0x010b4021, 0x314a00fe, 0x24020001, 0xa7a20020, - 0x8f630040, 0x00c05821, 0x00003021, 0x0a0004dd, 0xafa30028, 0x00cb1023, - 0x0a0004dd, 0x3046ffff, 0x00005821, 0x8f620048, 0x2442ffff, 0x00a21823, - 0x18600019, 0x0066102a, 0x14400013, 0x24020001, 0xa7a20020, 0x8f630040, - 0xafa30028, 0x8f620040, 0x55020005, 0x27a60010, 0x55200003, 0x27a60010, - 0x0a0004f6, 0x00c01821, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, - 0x1440fffd, 0x00000000, 0x0a000533, 0x00000000, 0x8f650048, 0x00c31023, - 0x3046ffff, 0x314a00f6, 0x3c046000, 0x8c824448, 0x31430002, 0x1060001e, - 0xaf62014c, 0x8f620044, 0x1502000e, 0x97a20020, 0x27a60010, 0x34420200, - 0xa7a20020, 0x8f630040, 0x27450180, 0x3c048000, 0xafa30028, 0x8f4201b8, - 0x00441024, 0x1440fffd, 0x00000000, 0x0a000533, 0x00000000, 0x27a60010, - 0x34420001, 0xa7a20020, 0x8f630040, 0x27450180, 0x3c048000, 0xafa30028, - 0x8f4201b8, 0x00441024, 0x1440fffd, 0x00000000, 0x0a000533, 0x00000000, - 0x3c026000, 0x8c424448, 0x31430010, 0xaf620150, 0x54600003, 0x8d890008, - 0x0a00054e, 0x24020001, 0x8f630054, 0x2522ffff, 0x00431023, 0x1840002a, - 0x24020001, 0x27a60010, 0xa7a20020, 0x8f630040, 0x27450180, 0x3c048000, - 0xafa30028, 0x8f4201b8, 0x00441024, 0x1440fffd, 0x00000000, 0x8f420128, - 0xaca20000, 0x8cc30018, 0x240240c1, 0xa4a20008, 0xaca30018, 0x90c4000a, - 0x24020002, 0xa0a2000b, 0xa0a4000a, 0x94c20010, 0xa4a20010, 0x90c30012, - 0xa0a30012, 0x90c20013, 0xa0a20013, 0x8cc30014, 0xaca30014, 0x8cc20024, - 0xaca20024, 0x8cc30028, 0xaca30028, 0x8cc4002c, 0x24020001, 0x3c031000, - 0xaca4002c, 0xaf4301b8, 0xaf400044, 0xaf400050, 0x0a00067a, 0x8fbf0048, - 0x3c026000, 0x8c424448, 0x31430020, 0x10600019, 0xaf620154, 0x8f430128, - 0x27420180, 0xac430000, 0x8f650040, 0x24040004, 0x240340c1, 0xa4430008, - 0x24030002, 0xa044000a, 0x24040008, 0xa043000b, 0x3c031000, 0xa4440010, - 0xa0400012, 0xa0400013, 0xac400014, 0xac400024, 0xac400028, 0xac40002c, - 0xac450018, 0x0e0007ed, 0xaf4301b8, 0x0a00067a, 0x8fbf0048, 0x8f430104, - 0x8c824448, 0x38e3000a, 0x2c630001, 0xaf620158, 0x38e2000c, 0x2c420001, - 0x00621825, 0x14600003, 0x2402000e, 0x14e2002a, 0x00000000, 0x50c00008, - 0x9584000e, 0x10c00004, 0xa7a60040, 0x01061021, 0x0a000583, 0x2445ffff, - 0x01002821, 0x9584000e, 0x93630035, 0x8f62004c, 0x00642004, 0x00892021, - 0x00821023, 0x1840001f, 0x3c026000, 0x8f620018, 0x01021023, 0x1c40000f, - 0x97a20020, 0x8f620018, 0x15020018, 0x3c026000, 0x8f62001c, 0x01221023, - 0x1c400008, 0x97a20020, 0x8f62001c, 0x15220011, 0x3c026000, 0x8f620058, - 0x00821023, 0x1840000c, 0x97a20020, 0xafa50028, 0xafa80034, 0xafa90038, - 0xafa4003c, 0x34420020, 0x0a0005a8, 0xa7a20020, 0x8f680040, 0x00003021, - 0x8f640058, 0x01002821, 0x3c026000, 0x8c434448, 0xaf63015c, 0x8f62004c, - 0x01221023, 0x18400009, 0x00000000, 0x8f620054, 0x01221023, 0x1c400005, - 0x97a20020, 0xafa50028, 0xafa90024, 0x0a0005c3, 0x34420040, 0x9742011a, - 0x1440000c, 0x24020014, 0x8f620058, 0x14820009, 0x24020014, 0x8f63004c, - 0x8f620054, 0x10620004, 0x97a20020, 0xafa50028, 0x34420080, 0xa7a20020, - 0x24020014, 0x10e2000a, 0x28e20015, 0x10400005, 0x2402000c, 0x10e20006, - 0x3c026000, 0x0a000600, 0x00000000, 0x24020016, 0x14e20031, 0x3c026000, - 0x8f620054, 0x24420001, 0x1522002d, 0x3c026000, 0x24020014, 0x10e2001e, - 0x28e20015, 0x10400005, 0x2402000c, 0x10e20008, 0x3c026000, 0x0a000600, - 0x00000000, 0x24020016, 0x10e2000c, 0x97a20020, 0x0a000600, 0x3c026000, - 0x97a30020, 0x2402000e, 0xafa50028, 0xa3a70022, 0xa3a20023, 0xafa90024, - 0x34630054, 0x0a0005ff, 0xa7a30020, 0x24030010, 0x24040002, 0xafa50028, - 0xa3a70022, 0xa3a30023, 0xa3a4001a, 0xafa90024, 0x0a0005fe, 0x3442005d, - 0x97a20020, 0x24030012, 0x24040002, 0xafa50028, 0xa3a70022, 0xa3a30023, - 0xa3a4001a, 0xafa90024, 0x3042fffe, 0x3442005c, 0xa7a20020, 0x3c026000, - 0x8c434448, 0x31420001, 0xaf630160, 0x1040002c, 0x2402000c, 0x10e20014, - 0x28e2000d, 0x10400005, 0x2402000a, 0x10e20008, 0x97a20020, 0x0a000631, - 0x3c026000, 0x2402000e, 0x10e20018, 0x3c026000, 0x0a000631, 0x00000000, - 0x24030008, 0x24040002, 0xafa50028, 0xa3a70022, 0xa3a30023, 0xa3a4001a, - 0x0a00062f, 0x34420013, 0x97a30020, 0x30620004, 0x1440000b, 0x97a20020, - 0x3462001b, 0xa7a20020, 0x24020016, 0x24030002, 0xafa50028, 0xa3a70022, - 0xa3a20023, 0x0a000630, 0xa3a3001a, 0x97a20020, 0x24030010, 0x24040002, - 0xafa50028, 0xa3a70022, 0xa3a30023, 0xa3a4001a, 0x3442001b, 0xa7a20020, - 0x3c026000, 0x8c434448, 0x31420009, 0x0002102b, 0x00021023, 0x30420007, - 0x34440003, 0xaf630164, 0x10c00016, 0x24030800, 0x8f820010, 0x27450180, - 0x24420001, 0xaf820010, 0x24020004, 0xaf4301b8, 0xa4a40008, 0xa0a2000b, - 0x93440120, 0x3c031000, 0xa4a6000e, 0xaca90024, 0xaca80028, 0x008b2021, - 0xa4a4000c, 0xaf4301b8, 0x97a20020, 0x00003021, 0x3042ffbf, 0x0a000650, - 0xa7a20020, 0x24060001, 0x3c026000, 0x8c434448, 0xaf630168, 0x97a20020, - 0x10400020, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, - 0x00000000, 0x8f420128, 0xaca20000, 0x8fa30028, 0x240240c1, 0xa4a20008, - 0xaca30018, 0x93a4001a, 0x24020002, 0xa0a2000b, 0xa0a4000a, 0x97a20020, - 0xa4a20010, 0x93a30022, 0xa0a30012, 0x93a20023, 0xa0a20013, 0x8fa30024, - 0xaca30014, 0x8fa20034, 0xaca20024, 0x8fa30038, 0xaca30028, 0x8fa2003c, - 0x3c031000, 0xaca2002c, 0xaf4301b8, 0x3c026000, 0x8c434448, 0x00c01021, - 0xaf63016c, 0x8fbf0048, 0x03e00008, 0x27bd0050, 0x8f460140, 0x8f470148, - 0x3c028000, 0x00e24024, 0x00072c02, 0x30a300ff, 0x2402000b, 0x1062008f, - 0x27440180, 0x2862000c, 0x10400011, 0x24020006, 0x1062005a, 0x28620007, - 0x10400007, 0x24020008, 0x10600024, 0x24020001, 0x10620037, 0x00000000, - 0x0a00077e, 0x00000000, 0x106200a9, 0x24020009, 0x106200bb, 0x00071c02, - 0x0a00077e, 0x00000000, 0x2402001b, 0x106200c7, 0x2862001c, 0x10400007, - 0x2402000e, 0x106200b1, 0x24020019, 0x106200c2, 0x00071c02, 0x0a00077e, - 0x00000000, 0x24020080, 0x10620060, 0x28620081, 0x10400005, 0x2402001c, - 0x10620094, 0x00071c02, 0x0a00077e, 0x00000000, 0x240200c2, 0x106200c5, - 0x00a01821, 0x0a00077e, 0x00000000, 0x00a01821, 0x3c058000, 0x8f4201b8, - 0x00451024, 0x1440fffd, 0x24020001, 0xa4830008, 0x24030002, 0xac860000, - 0xac800004, 0xa082000a, 0xa083000b, 0xa4870010, 0x8f430144, 0x3c021000, + 0x03e00008, 0xaca40000, 0x03e00008, 0x24020091, 0x27bdffb0, 0xafbf0048, + 0x93620023, 0x30420010, 0x1440025b, 0x24020001, 0x93420116, 0x93630005, + 0x34424000, 0x30630001, 0x14600005, 0x03425821, 0x0e001548, 0x00000000, + 0x0a0013a5, 0x8fbf0048, 0x93420112, 0x8f430104, 0x3c040020, 0x34424000, + 0x00641824, 0x10600012, 0x03422821, 0x27450180, 0x3c038000, 0x8f4201b8, + 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, 0x8f640040, + 0x24030008, 0x240240c1, 0xa4a20008, 0x24020002, 0xa0a2000b, 0x3c021000, + 0x0a001181, 0xa0a3000a, 0x8f420104, 0x3c030040, 0x00431024, 0x1040001d, + 0x3c038000, 0x27450180, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, + 0x8f420128, 0xaca20000, 0x8f640040, 0x24030010, 0x240240c1, 0xa4a20008, + 0x24020002, 0xa0a3000a, 0x24030008, 0xa0a2000b, 0x3c021000, 0xa4a30010, + 0xa0a00012, 0xa0a00013, 0xaca00014, 0xaca00024, 0xaca00028, 0xaca0002c, + 0xaca40018, 0x0e001548, 0xaf4201b8, 0x0a0013a5, 0x8fbf0048, 0x8f820000, + 0x10400016, 0x00000000, 0x8f420104, 0x3c030001, 0x00431024, 0x10400011, + 0x00000000, 0x8ca3000c, 0x8f620030, 0x1462020c, 0x24020001, 0x8ca30010, + 0x8f62002c, 0x14620208, 0x24020001, 0x9763003a, 0x95620000, 0x14430204, + 0x24020001, 0x97630038, 0x95620002, 0x14430200, 0x24020001, 0xaf400048, + 0xaf400054, 0xaf400040, 0x8f690040, 0x8f6a0048, 0x01497023, 0x05c10004, + 0x00000000, 0x0000000d, 0x00000000, 0x24000169, 0x9742011a, 0x3046ffff, + 0x10c00004, 0x8d680004, 0x01061021, 0x0a0011b8, 0x2445ffff, 0x01002821, + 0x916c000d, 0xa7a00020, 0xa3a0001a, 0xafa00028, 0x9362003f, 0x31830004, + 0x1060003a, 0x304700ff, 0x24040012, 0x14e40006, 0x24020001, 0x3c040800, + 0x8c830028, 0x24630001, 0x0a00128d, 0xac830028, 0x8f620044, 0x15020010, + 0x27a60010, 0x27450180, 0x3c038000, 0x2402001a, 0xa7a20020, 0x24020020, + 0xafa90028, 0xa3a70022, 0xa3a40023, 0xa3a2001a, 0x8f4201b8, 0x00431024, + 0x1440fffd, 0x00000000, 0x0a001272, 0x00000000, 0x8f620044, 0x01021023, + 0x0440001a, 0x010a1023, 0x044100ae, 0x24020001, 0x3c020800, 0x8c4300d8, + 0x10600004, 0x24020001, 0xa7a20020, 0x0a0011ee, 0xafa90028, 0x2402001a, + 0xa7a20020, 0x24020020, 0xafa90028, 0xa3a70022, 0xa3a40023, 0xa3a2001a, + 0x27a60010, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, + 0x00000000, 0x0a001272, 0x00000000, 0x0a00128d, 0x24020001, 0x01286823, + 0x19a00016, 0x00cd102a, 0x54400007, 0x318c00fe, 0x55a6000f, 0x010d4021, + 0x31820001, 0x5440000c, 0x010d4021, 0x318c00fe, 0x00c06821, 0x3c040800, + 0x8c8300c8, 0x00003021, 0x24020001, 0xa7a20020, 0xafa90028, 0x24630001, + 0x0a001212, 0xac8300c8, 0x00cd1023, 0x0a001212, 0x3046ffff, 0x00006821, + 0x2542ffff, 0x00a21823, 0x1860001e, 0x0066102a, 0x14400018, 0x01402821, + 0x97a20020, 0x3c040800, 0x8c8300cc, 0xafa90028, 0x34420001, 0x24630001, + 0xa7a20020, 0x01091026, 0x2c420001, 0xac8300cc, 0x2dc30001, 0x00431024, + 0x1440000a, 0x00c01821, 0x27a60010, 0x27450180, 0x3c038000, 0x8f4201b8, + 0x00431024, 0x1440fffd, 0x00000000, 0x0a001272, 0x00000000, 0x00c31023, + 0x3046ffff, 0x0a00123d, 0x318c00f6, 0x01091023, 0x18400008, 0x97a20020, + 0x3c040800, 0x8c8300d4, 0xafa80028, 0x34420400, 0x24630001, 0xa7a20020, + 0xac8300d4, 0x31820002, 0x1040001c, 0x31820010, 0x8f620044, 0x1502000d, + 0x27a60010, 0x97a20020, 0x27450180, 0x3c038000, 0xafa90028, 0x34420001, + 0xa7a20020, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a001272, + 0x00000000, 0x97a20020, 0x27450180, 0x3c038000, 0xafa90028, 0x34420001, + 0xa7a20020, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a001272, + 0x00000000, 0x54400003, 0x8d6a0008, 0x0a00128d, 0x24020001, 0x8f630054, + 0x2542ffff, 0x00431023, 0x1840002e, 0x97a20020, 0x27a60010, 0x3c040800, + 0x8c8300d0, 0x27450180, 0x3c078000, 0xafa90028, 0x34420001, 0x24630001, + 0xa7a20020, 0xac8300d0, 0x8f4201b8, 0x00471024, 0x1440fffd, 0x00000000, + 0x8f420128, 0xaca20000, 0x8cc30018, 0x240240c1, 0xa4a20008, 0xaca30018, + 0x90c4000a, 0x24020002, 0xa0a2000b, 0xa0a4000a, 0x94c20010, 0xa4a20010, + 0x90c30012, 0xa0a30012, 0x90c20013, 0xa0a20013, 0x8cc30014, 0xaca30014, + 0x8cc20024, 0xaca20024, 0x8cc30028, 0xaca30028, 0x8cc4002c, 0x24020001, + 0x3c031000, 0xaca4002c, 0xaf4301b8, 0xaf400044, 0xaf400050, 0x0a0013a5, + 0x8fbf0048, 0x31820020, 0x10400011, 0x00000000, 0x95620012, 0x0046102b, + 0x10400008, 0x97a20020, 0x95660012, 0x10c00003, 0x01061021, 0x0a00129e, + 0x2445ffff, 0x01002821, 0x97a20020, 0x93a3001a, 0x34420008, 0x34630004, + 0xa7a20020, 0xa3a3001a, 0x8f420104, 0x38e3000a, 0x2c630001, 0x38e2000c, + 0x2c420001, 0x00621825, 0x14600003, 0x2402000e, 0x54e2002a, 0x00003021, + 0x50c00008, 0x9564000e, 0x10c00004, 0xa7a60040, 0x01061021, 0x0a0012b6, + 0x2445ffff, 0x01002821, 0x9564000e, 0x93630035, 0x8f62004c, 0x00642004, + 0x008a2021, 0x00821023, 0x1840001d, 0x00000000, 0x8f620018, 0x01021023, + 0x1c40000f, 0x97a20020, 0x8f620018, 0x15020016, 0x00000000, 0x8f62001c, + 0x01421023, 0x1c400008, 0x97a20020, 0x8f62001c, 0x1542000f, 0x00000000, + 0x8f620058, 0x00821023, 0x1840000b, 0x97a20020, 0xafa50028, 0xafa80034, + 0xafaa0038, 0xafa4003c, 0x34420020, 0x0a0012da, 0xa7a20020, 0x01204021, + 0x01002821, 0x8f640058, 0x8f62004c, 0x01421023, 0x18400009, 0x00000000, + 0x8f620054, 0x01421023, 0x1c400005, 0x97a20020, 0xafa50028, 0xafaa0024, + 0x0a0012f2, 0x34420040, 0x9742011a, 0x1440000c, 0x24020014, 0x8f620058, + 0x14820009, 0x24020014, 0x8f63004c, 0x8f620054, 0x10620004, 0x97a20020, + 0xafa50028, 0x34420080, 0xa7a20020, 0x24020014, 0x10e2000a, 0x28e20015, + 0x10400005, 0x2402000c, 0x10e20006, 0x31820001, 0x0a001333, 0x00000000, + 0x24020016, 0x14e20035, 0x31820001, 0x8f620084, 0x24420001, 0x15420031, + 0x31820001, 0x24020014, 0x10e20021, 0x28e20015, 0x10400005, 0x2402000c, + 0x10e20008, 0x31820001, 0x0a001333, 0x00000000, 0x24020016, 0x10e2000c, + 0x31820001, 0x0a001333, 0x00000000, 0x97a30020, 0x2402000e, 0xafa50028, + 0xa3a70022, 0xa3a20023, 0xafaa0024, 0x34630054, 0x0a001332, 0xa7a30020, + 0x97a20020, 0x93a4001a, 0x24030010, 0xafa50028, 0xa3a70022, 0xa3a30023, + 0xafaa0024, 0x3442005d, 0x34840002, 0xa7a20020, 0x0a001332, 0xa3a4001a, + 0x97a20020, 0x24030012, 0xa3a30023, 0x93a3001a, 0xafa50028, 0xa3a70022, + 0xafaa0024, 0x3042fffe, 0x3442005c, 0x34630002, 0xa7a20020, 0xa3a3001a, + 0x31820001, 0x10400030, 0x2402000c, 0x10e20013, 0x28e2000d, 0x10400005, + 0x2402000a, 0x10e20008, 0x97a20020, 0x0a001365, 0x31820009, 0x2402000e, + 0x10e2001b, 0x31820009, 0x0a001366, 0x0002102b, 0x93a4001a, 0x24030008, + 0xafa50028, 0xa3a70022, 0xa3a30023, 0x0a001361, 0x34420013, 0x97a30020, + 0x30620004, 0x14400005, 0x93a2001a, 0x3463001b, 0xa7a30020, 0x0a001354, + 0x24030016, 0x3463001b, 0xa7a30020, 0x24030010, 0xafa50028, 0xa3a70022, + 0xa3a30023, 0x34420002, 0x0a001364, 0xa3a2001a, 0x97a20020, 0x93a4001a, + 0x24030010, 0xafa50028, 0xa3a70022, 0xa3a30023, 0x3442001b, 0x34840002, + 0xa7a20020, 0xa3a4001a, 0x31820009, 0x0002102b, 0x00021023, 0x30420007, + 0x10c00017, 0x34440003, 0x8f820014, 0x24030800, 0x27450180, 0x24420001, + 0xaf820014, 0x24020004, 0xaf4301b8, 0xa4a40008, 0xa0a2000b, 0x93440120, + 0x3c031000, 0xa4a6000e, 0xacaa0024, 0xaca80028, 0x008d2021, 0xa4a4000c, + 0xaf4301b8, 0x97a20020, 0x00003021, 0x3042ffbf, 0x0a001381, 0xa7a20020, + 0x24060001, 0x97a20020, 0x10400020, 0x27450180, 0x3c038000, 0x8f4201b8, + 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, 0x8fa30028, + 0x240240c1, 0xa4a20008, 0xaca30018, 0x93a4001a, 0x24020002, 0xa0a2000b, + 0xa0a4000a, 0x97a20020, 0xa4a20010, 0x93a30022, 0xa0a30012, 0x93a20023, + 0xa0a20013, 0x8fa30024, 0xaca30014, 0x8fa20034, 0xaca20024, 0x8fa30038, + 0xaca30028, 0x8fa2003c, 0x3c031000, 0xaca2002c, 0xaf4301b8, 0x00c01021, + 0x8fbf0048, 0x03e00008, 0x27bd0050, 0x8f470140, 0x8f460148, 0x3c028000, + 0x00c24024, 0x00062c02, 0x30a300ff, 0x24020019, 0x106200e7, 0x27440180, + 0x2862001a, 0x1040001f, 0x24020008, 0x106200be, 0x28620009, 0x1040000d, + 0x24020001, 0x10620046, 0x28620002, 0x50400005, 0x24020006, 0x1060002e, + 0x00a01821, 0x0a0014c4, 0x00000000, 0x1062005b, 0x00a01821, 0x0a0014c4, + 0x00000000, 0x2402000b, 0x10620084, 0x2862000c, 0x10400005, 0x24020009, + 0x106200bc, 0x00061c02, 0x0a0014c4, 0x00000000, 0x2402000e, 0x106200b7, + 0x00061c02, 0x0a0014c4, 0x00000000, 0x28620021, 0x10400009, 0x2862001f, + 0x104000c1, 0x2402001b, 0x106200bf, 0x2402001c, 0x1062009a, 0x00061c02, + 0x0a0014c4, 0x00000000, 0x240200c2, 0x106200ca, 0x286200c3, 0x10400005, + 0x24020080, 0x1062005a, 0x00a01821, 0x0a0014c4, 0x00000000, 0x240200c9, + 0x106200cd, 0x30c5ffff, 0x0a0014c4, 0x00000000, 0x3c058000, 0x8f4201b8, + 0x00451024, 0x1440fffd, 0x24020001, 0xa4830008, 0x24030002, 0xac870000, + 0xac800004, 0xa082000a, 0xa083000b, 0xa4860010, 0x8f430144, 0x3c021000, 0xac800028, 0xac830024, 0x3c036000, 0xaf4201b8, 0x03e00008, 0xac600808, - 0x11000009, 0x00a01821, 0x3c020800, 0x24030002, 0xa0434490, 0x24424490, - 0xac460008, 0x8f430144, 0x03e00008, 0xac430004, 0x3c058000, 0x8f4201b8, - 0x00451024, 0x1440fffd, 0x24020002, 0xac800000, 0xac860004, 0xa4830008, - 0xa082000a, 0xa082000b, 0xa4870010, 0xac800024, 0x8f420144, 0x3c031000, - 0xac820028, 0x3c026000, 0xaf4301b8, 0x03e00008, 0xac400808, 0x00a01821, - 0x3c080800, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x00000000, - 0xac860000, 0x91024490, 0x00002821, 0x10400002, 0x25064490, 0x8cc50008, - 0xac850004, 0xa4830008, 0x91034490, 0x24020002, 0xa082000b, 0xa4870010, - 0x34630001, 0xa083000a, 0x8f420144, 0xac820024, 0x91034490, 0x10600002, - 0x00001021, 0x8cc20004, 0xac820028, 0x3c021000, 0xaf4201b8, 0x3c026000, - 0xa1004490, 0x03e00008, 0xac400808, 0x00a01821, 0x3c058000, 0x8f4201b8, - 0x00451024, 0x1440fffd, 0x24020002, 0xa082000b, 0xa4830008, 0xa4870010, - 0x8f420144, 0x3c031000, 0xa4820012, 0x03e00008, 0xaf4301b8, 0x30e2ffff, - 0x14400028, 0x00071c02, 0x93620005, 0x30420004, 0x14400020, 0x3c029000, - 0x34420001, 0x00c21025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, - 0x1440fffd, 0x00000000, 0x93620005, 0x3c038000, 0x34630001, 0x00c31825, - 0x34420004, 0xa3620005, 0xaf430020, 0x93620005, 0x30420004, 0x14400003, - 0x3c038000, 0x0000000d, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, - 0x24020005, 0x3c031000, 0xac860000, 0xa082000b, 0xaf4301b8, 0x0a00073d, - 0x00071c02, 0x0000000d, 0x03e00008, 0x00000000, 0x00071c02, 0x3c058000, - 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020001, 0xa4830008, 0x24030002, - 0xac860000, 0xac800004, 0xa082000a, 0xa083000b, 0xa4870010, 0x8f430144, - 0x3c021000, 0xac800028, 0xac830024, 0x03e00008, 0xaf4201b8, 0x00071c02, - 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002, 0xac800000, - 0xac860004, 0xa4830008, 0xa082000a, 0xa082000b, 0xa4870010, 0xac800024, - 0x8f420144, 0x3c031000, 0xac820028, 0x03e00008, 0xaf4301b8, 0x00071c02, - 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020001, 0xa4830008, - 0x24030002, 0xa082000a, 0x3c021000, 0xac860000, 0xac800004, 0xa083000b, - 0xa4870010, 0xac800024, 0xac800028, 0x03e00008, 0xaf4201b8, 0x3c058000, - 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002, 0xac860000, 0xac800004, - 0xa4830008, 0xa080000a, 0x0a000748, 0xa082000b, 0x0000000d, 0x03e00008, - 0x00000000, 0x03e00008, 0x00000000, 0x8f420100, 0x3042003e, 0x14400011, - 0x24020001, 0xaf400048, 0x8f420100, 0x304207c0, 0x10400005, 0x00000000, - 0xaf40004c, 0xaf400050, 0x03e00008, 0x24020001, 0xaf400054, 0xaf400040, - 0x8f420100, 0x30423800, 0x54400001, 0xaf400044, 0x24020001, 0x03e00008, - 0x00000000, 0x3c029000, 0x34420001, 0x00822025, 0xaf440020, 0x3c038000, - 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x03e00008, 0x00000000, - 0x3c028000, 0x34420001, 0x00822025, 0x03e00008, 0xaf440020, 0x8f430128, - 0x27420180, 0xac430000, 0x8f650040, 0x240340c1, 0xa4430008, 0x24030002, - 0xa044000a, 0x24040008, 0xa043000b, 0x3c031000, 0xa4440010, 0xa0400012, - 0xa0400013, 0xac400014, 0xac400024, 0xac400028, 0xac40002c, 0xac450018, - 0x03e00008, 0xaf4301b8, 0x24020001, 0xacc40000, 0x03e00008, 0xa4e50000, - 0x03e00008, 0x24020001, 0x24020001, 0xaf400044, 0x03e00008, 0xaf400050, - 0x00803021, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, - 0x00000000, 0x8f420128, 0xaca20000, 0x8cc30018, 0x240240c1, 0xa4a20008, - 0xaca30018, 0x90c4000a, 0x24020002, 0xa0a2000b, 0xa0a4000a, 0x94c20010, - 0xa4a20010, 0x90c30012, 0xa0a30012, 0x90c20013, 0xa0a20013, 0x8cc30014, - 0xaca30014, 0x8cc20024, 0xaca20024, 0x8cc30028, 0xaca30028, 0x8cc2002c, - 0x3c031000, 0xaca2002c, 0x24020001, 0xaf4301b8, 0xaf400044, 0x03e00008, - 0xaf400050, 0x27bdffe8, 0xafbf0010, 0x0e000326, 0x00000000, 0x00002021, - 0x0e00004c, 0xaf400180, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x8f460148, - 0x27450180, 0x3c038000, 0x00061402, 0x304700ff, 0x8f4201b8, 0x00431024, - 0x1440fffd, 0x00000000, 0x8f440140, 0x00061202, 0x304200ff, 0x00061c02, - 0xaca20004, 0x24020002, 0xa4a30008, 0x30c300ff, 0xa0a2000b, 0xaca30024, - 0x10e0000a, 0xaca40000, 0x28e20004, 0x14400005, 0x24020001, 0x24020005, - 0x54e20005, 0xa0a0000a, 0x24020001, 0x0a000816, 0xa0a2000a, 0xa0a0000a, - 0x3c021000, 0x03e00008, 0xaf4201b8, 0x03e00008, 0x00001021, 0x10c00007, - 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000, 0x14c0fffb, - 0x24840004, 0x03e00008, 0x00000000, 0x0a00082a, 0x00a01021, 0xac860000, - 0x24840004, 0x00a01021, 0x1440fffc, 0x24a5ffff, 0x03e00008, 0x00000000, - 0x00000000 }; + 0x11000009, 0x00a01821, 0x3c020800, 0x24030002, 0xa0436a08, 0x24426a08, + 0xac470008, 0x8f430144, 0x03e00008, 0xac430004, 0x3c058000, 0x8f4201b8, + 0x00451024, 0x1440fffd, 0x24020002, 0xac800000, 0xac870004, 0xa4830008, + 0xa082000a, 0xa082000b, 0xa4860010, 0xac800024, 0x8f420144, 0x3c031000, + 0xac820028, 0x3c026000, 0xaf4301b8, 0x03e00008, 0xac400808, 0x3c080800, + 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x00000000, 0xac870000, + 0x91026a08, 0x00002821, 0x10400002, 0x25076a08, 0x8ce50008, 0xac850004, + 0xa4830008, 0x91036a08, 0x24020002, 0xa082000b, 0xa4860010, 0x34630001, + 0xa083000a, 0x8f420144, 0xac820024, 0x91036a08, 0x10600002, 0x00001021, + 0x8ce20004, 0xac820028, 0x3c021000, 0xaf4201b8, 0x3c026000, 0xa1006a08, + 0x03e00008, 0xac400808, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, + 0x24020002, 0xa082000b, 0xa4830008, 0xa4860010, 0x8f420144, 0x3c031000, + 0xa4820012, 0x03e00008, 0xaf4301b8, 0x30c2ffff, 0x14400028, 0x00061c02, + 0x93620005, 0x30420004, 0x14400020, 0x3c029000, 0x34420001, 0x00e21025, + 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, + 0x93620005, 0x3c038000, 0x34630001, 0x00e31825, 0x34420004, 0xa3620005, + 0xaf430020, 0x93620005, 0x30420004, 0x14400003, 0x3c038000, 0x0000000d, + 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020005, 0x3c031000, + 0xac870000, 0xa082000b, 0xaf4301b8, 0x0a001473, 0x00061c02, 0x0000000d, + 0x03e00008, 0x00000000, 0x00061c02, 0x3c058000, 0x8f4201b8, 0x00451024, + 0x1440fffd, 0x24020001, 0xa4830008, 0x24030002, 0xac870000, 0xac800004, + 0xa082000a, 0xa083000b, 0xa4860010, 0x8f430144, 0x3c021000, 0xac800028, + 0xac830024, 0x03e00008, 0xaf4201b8, 0x3c058000, 0x8f4201b8, 0x00451024, + 0x1440fffd, 0x24020002, 0xac800000, 0xac870004, 0xa4830008, 0xa082000a, + 0xa082000b, 0xa4860010, 0xac800024, 0x8f420144, 0x3c031000, 0xac820028, + 0x03e00008, 0xaf4301b8, 0x00061c02, 0x3c058000, 0x8f4201b8, 0x00451024, + 0x1440fffd, 0x24020001, 0xa4830008, 0x24030002, 0xa082000a, 0x3c021000, + 0xac870000, 0xac800004, 0xa083000b, 0xa4860010, 0xac800024, 0xac800028, + 0x03e00008, 0xaf4201b8, 0x00a01821, 0x3c058000, 0x8f4201b8, 0x00451024, + 0x1440fffd, 0x24020002, 0xac870000, 0xac800004, 0xa4830008, 0xa080000a, + 0x0a00147e, 0xa082000b, 0x8f440144, 0x3c038000, 0x8f4201b8, 0x00431024, + 0x1440fffd, 0x24020002, 0x240340c9, 0xaf470180, 0xa342018b, 0x3c021000, + 0xa7430188, 0xaf4401a4, 0xaf4501a8, 0xaf4001ac, 0x03e00008, 0xaf4201b8, + 0x0000000d, 0x03e00008, 0x00000000, 0x03e00008, 0x00000000, 0x8f420100, + 0x3042003e, 0x14400011, 0x24020001, 0xaf400048, 0x8f420100, 0x304207c0, + 0x10400005, 0x00000000, 0xaf40004c, 0xaf400050, 0x03e00008, 0x24020001, + 0xaf400054, 0xaf400040, 0x8f420100, 0x30423800, 0x54400001, 0xaf400044, + 0x24020001, 0x03e00008, 0x00000000, 0x3c038000, 0x8f4201b8, 0x00431024, + 0x1440fffd, 0x24020002, 0x240340c9, 0xaf440180, 0xa342018b, 0x3c021000, + 0xa7430188, 0xaf4501a4, 0xaf4601a8, 0xaf4701ac, 0x03e00008, 0xaf4201b8, + 0x3c029000, 0x34420001, 0x00822025, 0xaf440020, 0x3c038000, 0x8f420020, + 0x00431024, 0x1440fffd, 0x00000000, 0x03e00008, 0x00000000, 0x3c028000, + 0x34420001, 0x00822025, 0x03e00008, 0xaf440020, 0x308600ff, 0x27450180, + 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, + 0xaca20000, 0x8f640040, 0x24030008, 0x240240c1, 0xa4a20008, 0x24020002, + 0xa0a2000b, 0x3c021000, 0xa0a6000a, 0xa4a30010, 0xa0a00012, 0xa0a00013, + 0xaca00014, 0xaca00024, 0xaca00028, 0xaca0002c, 0xaca40018, 0x03e00008, + 0xaf4201b8, 0x24020001, 0xacc40000, 0x03e00008, 0xa4e50000, 0x03e00008, + 0x24020001, 0x24020001, 0xaf400044, 0x03e00008, 0xaf400050, 0x00803021, + 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, + 0x8f420128, 0xaca20000, 0x8cc30018, 0x240240c1, 0xa4a20008, 0xaca30018, + 0x90c4000a, 0x24020002, 0xa0a2000b, 0xa0a4000a, 0x94c20010, 0xa4a20010, + 0x90c30012, 0xa0a30012, 0x90c20013, 0xa0a20013, 0x8cc30014, 0xaca30014, + 0x8cc20024, 0xaca20024, 0x8cc30028, 0xaca30028, 0x8cc2002c, 0x3c031000, + 0xaca2002c, 0x24020001, 0xaf4301b8, 0xaf400044, 0x03e00008, 0xaf400050, + 0x27bdffe8, 0xafbf0010, 0x0e001032, 0x00000000, 0x00002021, 0x0e000c99, + 0xaf400180, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x8f460148, 0x27450180, + 0x3c038000, 0x00061402, 0x304700ff, 0x8f4201b8, 0x00431024, 0x1440fffd, + 0x00000000, 0x8f440140, 0x00061202, 0x304200ff, 0x00061c02, 0xaca20004, + 0x24020002, 0xa4a30008, 0x30c300ff, 0xa0a2000b, 0xaca30024, 0x10e0000a, + 0xaca40000, 0x28e20004, 0x14400005, 0x24020001, 0x24020005, 0x54e20005, + 0xa0a0000a, 0x24020001, 0x0a001571, 0xa0a2000a, 0xa0a0000a, 0x3c021000, + 0x03e00008, 0xaf4201b8, 0x03e00008, 0x00001021, 0x10c00007, 0x00000000, + 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000, 0x14c0fffb, 0x24840004, + 0x03e00008, 0x00000000, 0x0a001587, 0x00a01021, 0xac860000, 0x00000000, + 0x00000000, 0x24840004, 0x00a01021, 0x1440fffa, 0x24a5ffff, 0x03e00008, + 0x00000000, 0x00000000 }; -static u32 bnx2_RXP_b06FwData[(0x0/4) + 1] = { 0x00000000 }; -static u32 bnx2_RXP_b06FwRodata[(0x0/4) + 1] = { 0x00000000 }; -static u32 bnx2_RXP_b06FwBss[(0x239c/4) + 1] = { 0x00000000 }; -static u32 bnx2_RXP_b06FwSbss[(0x14/4) + 1] = { 0x00000000 }; +static u32 bnx2_RXP_b06FwData[(0x0/4) + 1] = { 0x0 }; +static u32 bnx2_RXP_b06FwRodata[(0x0/4) + 1] = { 0x0 }; +static u32 bnx2_RXP_b06FwBss[(0x1394/4) + 1] = { 0x0 }; +static u32 bnx2_RXP_b06FwSbss[(0x18/4) + 1] = { 0x0 }; static u32 bnx2_rv2p_proc1[] = { 0x00000008, 0xac000001, 0x0000000c, 0x2f800001, 0x00000010, 0x213f0004, @@ -1536,249 +2298,328 @@ static u32 bnx2_rv2p_proc2[] = { 0x0000000c, 0x29520000, 0x00000018, 0x80000002, 0x0000000c, 0x29800000, 0x00000018, 0x00570000 }; -static int bnx2_TPAT_b06FwReleaseMajor = 0x0; +static int bnx2_TPAT_b06FwReleaseMajor = 0x1; static int bnx2_TPAT_b06FwReleaseMinor = 0x0; static int bnx2_TPAT_b06FwReleaseFix = 0x0; -static u32 bnx2_TPAT_b06FwStartAddr = 0x08000858; +static u32 bnx2_TPAT_b06FwStartAddr = 0x08000860; static u32 bnx2_TPAT_b06FwTextAddr = 0x08000800; -static int bnx2_TPAT_b06FwTextLen = 0x1314; -static u32 bnx2_TPAT_b06FwDataAddr = 0x08001b40; +static int bnx2_TPAT_b06FwTextLen = 0x122c; +static u32 bnx2_TPAT_b06FwDataAddr = 0x08001a60; static int bnx2_TPAT_b06FwDataLen = 0x0; static u32 bnx2_TPAT_b06FwRodataAddr = 0x00000000; static int bnx2_TPAT_b06FwRodataLen = 0x0; -static u32 bnx2_TPAT_b06FwBssAddr = 0x08001b90; -static int bnx2_TPAT_b06FwBssLen = 0x80; -static u32 bnx2_TPAT_b06FwSbssAddr = 0x08001b40; -static int bnx2_TPAT_b06FwSbssLen = 0x48; - -static u32 bnx2_TPAT_b06FwText[(0x1314/4) + 1] = { - 0x0a000216, 0x00000000, 0x00000000, 0x0000000d, 0x74706174, 0x20302e36, - 0x2e390000, 0x00060901, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x10000003, - 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800, 0x24421b40, 0x3c030800, - 0x24631c10, 0xac400000, 0x0043202b, 0x1480fffd, 0x24420004, 0x3c1d0800, - 0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100858, 0x3c1c0800, 0x279c1b40, - 0x0e00051f, 0x00000000, 0x0000000d, 0x8f820024, 0x27bdffe8, 0xafbf0014, - 0x10400004, 0xafb00010, 0x0000000d, 0x00000000, 0x2400015f, 0x8f82001c, +static u32 bnx2_TPAT_b06FwBssAddr = 0x08001aa0; +static int bnx2_TPAT_b06FwBssLen = 0x250; +static u32 bnx2_TPAT_b06FwSbssAddr = 0x08001a60; +static int bnx2_TPAT_b06FwSbssLen = 0x34; +static u32 bnx2_TPAT_b06FwText[(0x122c/4) + 1] = { + 0x0a000218, 0x00000000, 0x00000000, 0x0000000d, 0x74706174, 0x20322e35, + 0x2e313100, 0x02050b01, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800, + 0x24421a60, 0x3c030800, 0x24631cf0, 0xac400000, 0x0043202b, 0x1480fffd, + 0x24420004, 0x3c1d0800, 0x37bd2ffc, 0x03a0f021, 0x3c100800, 0x26100860, + 0x3c1c0800, 0x279c1a60, 0x0e000546, 0x00000000, 0x0000000d, 0x8f820010, 0x8c450008, 0x24030800, 0xaf430178, 0x97430104, 0x3c020008, 0xaf420140, - 0x8f820034, 0x30420001, 0x10400006, 0x3070ffff, 0x24020002, 0x2603fffe, - 0xa7420146, 0x0a000246, 0xa7430148, 0xa7400146, 0x8f850034, 0x30a20020, - 0x0002102b, 0x00021023, 0x30460009, 0x30a30c00, 0x24020400, 0x14620002, - 0x34c40001, 0x34c40005, 0xa744014a, 0x3c020800, 0x8c440820, 0x3c030048, - 0x24020002, 0x00832025, 0x30a30006, 0x1062000d, 0x2c620003, 0x50400005, - 0x24020004, 0x10600012, 0x3c020001, 0x0a000271, 0x00000000, 0x10620007, - 0x24020006, 0x1462000f, 0x3c020111, 0x0a000269, 0x00821025, 0x0a000268, - 0x3c020101, 0x3c020011, 0x00821025, 0x24030001, 0xaf421000, 0xaf830030, - 0x0a000271, 0x00000000, 0x00821025, 0xaf421000, 0xaf800030, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x8f830030, 0x1060003f, 0x3c048000, - 0x8f421000, 0x00441024, 0x1040fffd, 0x00000000, 0x10600039, 0x00000000, - 0x8f421000, 0x3c030020, 0x00431024, 0x10400034, 0x00000000, 0x97421014, - 0x14400031, 0x00000000, 0x97421008, 0x8f84001c, 0x24420006, 0x00024082, - 0x00081880, 0x00643821, 0x8ce50000, 0x30430003, 0x30420001, 0x10400004, - 0x00000000, 0x0000000d, 0x0a0002b0, 0x00081080, 0x5460000f, 0x30a5ffff, - 0x3c06ffff, 0x00a62824, 0x0005182b, 0x00a61026, 0x0002102b, 0x00621824, - 0x10600004, 0x00000000, 0x0000000d, 0x00000000, 0x240001fc, 0x8ce20000, - 0x0a0002af, 0x00462825, 0x0005182b, 0x38a2ffff, 0x0002102b, 0x00621824, - 0x10600004, 0x00000000, 0x0000000d, 0x00000000, 0x24000206, 0x8ce20000, - 0x3445ffff, 0x00081080, 0x00441021, 0x3c030800, 0xac450000, 0x8c620840, - 0x24420001, 0xac620840, 0x8f820008, 0x10400003, 0x00000000, 0x0e000660, - 0x00000000, 0x8f840028, 0x02002821, 0x24820008, 0x30421fff, 0x24434000, - 0x0343d821, 0x30a30007, 0xaf840018, 0xaf820028, 0xaf420084, 0x10600002, - 0x24a20007, 0x3045fff8, 0x8f820044, 0x8f840004, 0x00451821, 0xaf82002c, - 0x0064102b, 0xaf830044, 0x14400002, 0x00641023, 0xaf820044, 0x8f840044, - 0x34028000, 0x8fbf0014, 0x8fb00010, 0x00821021, 0x03421821, 0x3c021000, - 0xaf83001c, 0xaf440080, 0xaf420178, 0x03e00008, 0x27bd0018, 0x8f820024, - 0x27bdffe8, 0xafbf0014, 0x10400004, 0xafb00010, 0x0000000d, 0x00000000, - 0x24000249, 0x8f85001c, 0x24020001, 0xaf820024, 0x8ca70008, 0xa3800023, - 0x8f620004, 0x3c100800, 0x26041b90, 0x00021402, 0xa3820010, 0x304600ff, - 0x24c60005, 0x0e00064a, 0x00063082, 0x8f640004, 0x8f430108, 0x3c021000, - 0x00621824, 0xa7840020, 0x10600008, 0x00000000, 0x97420104, 0x93830023, - 0x2442ffec, 0x34630002, 0xa3830023, 0x0a000304, 0x3045ffff, 0x97420104, - 0x2442fff0, 0x3045ffff, 0x8f620004, 0x3042ffff, 0x2c420013, 0x14400004, - 0x00000000, 0x93820023, 0x34420001, 0xa3820023, 0x93830023, 0x24020001, - 0x10620009, 0x28620002, 0x14400014, 0x24020002, 0x10620012, 0x24020003, - 0x1062000a, 0x00000000, 0x0a000325, 0x00000000, 0x8f82001c, 0x8c43000c, - 0x3c04ffff, 0x00641824, 0x00651825, 0x0a000325, 0xac43000c, 0x8f82001c, - 0x8c430010, 0x3c04ffff, 0x00641824, 0x00651825, 0xac430010, 0x8f620004, - 0x3042ffff, 0x24420002, 0x00021083, 0xa3820038, 0x304500ff, 0x8f82001c, - 0x3c04ffff, 0x00052880, 0x00a22821, 0x8ca70000, 0x97820020, 0x97430104, - 0x00e42024, 0x24420002, 0x00621823, 0x00833825, 0xaca70000, 0x93840038, - 0x26061b90, 0x00041080, 0x00461021, 0x90430000, 0x3063000f, 0x00832021, - 0xa3840022, 0x308200ff, 0x3c04fff6, 0x24420003, 0x00021080, 0x00461021, - 0x8c450000, 0x93830022, 0x8f82001c, 0x3484ffff, 0x00a43824, 0x00031880, - 0x00621821, 0xaf850000, 0xac67000c, 0x93820022, 0x93830022, 0x8f84001c, - 0x24420003, 0x00021080, 0x00461021, 0x24630004, 0x00031880, 0xac470000, - 0x93820022, 0x00661821, 0x94670002, 0x00021080, 0x00441021, 0xac670000, - 0x24030010, 0xac470010, 0xa7430140, 0x24030002, 0xa7400142, 0xa7400144, - 0xa7430146, 0x97420104, 0x8f840034, 0x24030001, 0x2442fffe, 0x30840006, - 0xa7420148, 0x24020002, 0xa743014a, 0x1082000d, 0x2c820003, 0x10400005, - 0x24020004, 0x10800011, 0x3c020009, 0x0a000383, 0x00000000, 0x10820007, - 0x24020006, 0x1482000d, 0x3c020119, 0x0a00037d, 0x24030001, 0x0a00037c, - 0x3c020109, 0x3c020019, 0x24030001, 0xaf421000, 0xaf830030, 0x0a000383, - 0x00000000, 0xaf421000, 0xaf800030, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x93820010, 0x24030008, 0x8f840030, 0x24420002, 0x30420007, - 0x00621823, 0x30630007, 0xaf83000c, 0x10800005, 0x3c038000, 0x8f421000, - 0x00431024, 0x1040fffd, 0x00000000, 0x8f820028, 0xaf820018, 0x24420010, - 0x30421fff, 0xaf820028, 0xaf420084, 0x97430104, 0x24424000, 0x0342d821, - 0x3063ffff, 0x30620007, 0x10400002, 0x24620007, 0x3043fff8, 0x8f820044, - 0x8f840004, 0x00431821, 0xaf82002c, 0x0064102b, 0xaf830044, 0x14400002, - 0x00641023, 0xaf820044, 0x8f840044, 0x34028000, 0x8fbf0014, 0x8fb00010, - 0x00821021, 0x03421821, 0x3c021000, 0xaf83001c, 0xaf440080, 0xaf420178, - 0x03e00008, 0x27bd0018, 0x8f820024, 0x27bdffe8, 0xafbf0014, 0x14400004, - 0xafb00010, 0x0000000d, 0x00000000, 0x240002db, 0x8f620004, 0x04410009, - 0x3c050800, 0x93820022, 0x8f830000, 0x24a41b90, 0xaf800024, 0x24420003, - 0x00021080, 0x00441021, 0xac430000, 0x93820038, 0x24a51b90, 0x93860010, - 0x3c040001, 0x27700008, 0x24420001, 0x00021080, 0x00451021, 0x8c430000, - 0x24c60005, 0x00063082, 0x00641821, 0x02002021, 0x0e00064a, 0xac430000, - 0x93840022, 0x3c057fff, 0x8f620004, 0x00042080, 0x00902021, 0x8c830004, - 0x34a5ffff, 0x00451024, 0x00621821, 0xac830004, 0x93850038, 0x3c07ffff, - 0x93840010, 0x00052880, 0x00b02821, 0x8ca30000, 0x97420104, 0x97860020, - 0x00671824, 0x00441021, 0x00461023, 0x3042ffff, 0x00621825, 0xaca30000, - 0x93830023, 0x24020001, 0x10620009, 0x28620002, 0x1440001a, 0x24020002, - 0x10620018, 0x24020003, 0x1062000d, 0x00000000, 0x0a000411, 0x00000000, - 0x93820010, 0x97430104, 0x8e04000c, 0x00621821, 0x2463fff2, 0x3063ffff, - 0x00872024, 0x00832025, 0x0a000411, 0xae04000c, 0x93820010, 0x97430104, - 0x8e040010, 0x00621821, 0x2463ffee, 0x3063ffff, 0x00872024, 0x00832025, - 0xae040010, 0x9783000e, 0x8f840034, 0x2402000a, 0xa7420140, 0xa7430142, - 0x93820010, 0xa7420144, 0xa7400146, 0x97430104, 0x30840006, 0x24020001, - 0xa7430148, 0xa742014a, 0x24020002, 0x1082000d, 0x2c820003, 0x10400005, - 0x24020004, 0x10800011, 0x3c020041, 0x0a000437, 0x00000000, 0x10820007, - 0x24020006, 0x1482000d, 0x3c020151, 0x0a000431, 0x24030001, 0x0a000430, - 0x3c020141, 0x3c020051, 0x24030001, 0xaf421000, 0xaf830030, 0x0a000437, - 0x00000000, 0xaf421000, 0xaf800030, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x8f820030, 0x93840010, 0x8f850028, 0x10400005, 0x3c038000, - 0x8f421000, 0x00431024, 0x1040fffd, 0x00000000, 0x2483000a, 0x30620007, - 0x10400002, 0x24620007, 0x304303f8, 0x00a31021, 0x30421fff, 0xaf850018, - 0xaf820028, 0xaf420084, 0x97430104, 0x24424000, 0x0342d821, 0x3063ffff, - 0x30620007, 0x10400002, 0x24620007, 0x3043fff8, 0x8f820044, 0x8f840004, - 0x00431821, 0xaf82002c, 0x0064102b, 0xaf830044, 0x14400002, 0x00641023, - 0xaf820044, 0x8f840044, 0x34028000, 0x8fbf0014, 0x8fb00010, 0x00821021, - 0x03421821, 0x3c021000, 0xaf83001c, 0xaf440080, 0xaf420178, 0x03e00008, - 0x27bd0018, 0x3c026000, 0x8c444448, 0x3c030800, 0xac64082c, 0x8f620000, - 0x97430104, 0x3c048000, 0x3046ffff, 0x3067ffff, 0x8f420178, 0x00441024, - 0x1440fffd, 0x2402000a, 0x30c30007, 0xa7420140, 0x24020008, 0x00431023, - 0x30420007, 0x24c3fffe, 0xa7420142, 0xa7430144, 0xa7400146, 0xa7470148, - 0x8f420108, 0x3c036000, 0x8f850034, 0x30420020, 0x0002102b, 0x00021023, - 0x30420009, 0x34420001, 0xa742014a, 0x8c644448, 0x3c020800, 0x30a50006, - 0xac440830, 0x24020002, 0x10a2000d, 0x2ca20003, 0x10400005, 0x24020004, - 0x10a00011, 0x3c020041, 0x0a0004a8, 0x00000000, 0x10a20007, 0x24020006, - 0x14a2000d, 0x3c020151, 0x0a0004a2, 0x24030001, 0x0a0004a1, 0x3c020141, - 0x3c020051, 0x24030001, 0xaf421000, 0xaf830030, 0x0a0004a8, 0x00000000, - 0xaf421000, 0xaf800030, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x8f820030, 0x24c30008, 0x10400006, 0x30e6ffff, 0x3c048000, 0x8f421000, - 0x00441024, 0x1040fffd, 0x00000000, 0x3c026000, 0x8c444448, 0x3065ffff, - 0x3c020800, 0x30a30007, 0x10600003, 0xac440834, 0x24a20007, 0x3045fff8, - 0x8f840028, 0x00851021, 0x30421fff, 0x24434000, 0x0343d821, 0x30c30007, - 0xaf840018, 0xaf820028, 0xaf420084, 0x10600002, 0x24c20007, 0x3046fff8, - 0x8f820044, 0x8f840004, 0x00461821, 0xaf82002c, 0x0064102b, 0xaf830044, - 0x14400002, 0x00641023, 0xaf820044, 0x8f840044, 0x34028000, 0x3c030800, - 0x8c650844, 0x00821021, 0x03421821, 0xaf83001c, 0xaf440080, 0x10a00006, - 0x2402000e, 0x93830043, 0x14620004, 0x3c021000, 0x2402043f, 0xa7420148, - 0x3c021000, 0x3c036000, 0xaf420178, 0x8c644448, 0x3c020800, 0x03e00008, - 0xac440838, 0x8f820034, 0x30424000, 0x10400005, 0x24020800, 0x0000000d, - 0x00000000, 0x24000405, 0x24020800, 0xaf420178, 0x97440104, 0x3c030008, - 0xaf430140, 0x8f820034, 0x30420001, 0x10400006, 0x3085ffff, 0x24020002, - 0x24a3fffe, 0xa7420146, 0x0a0004ff, 0xa7430148, 0xa7400146, 0x8f840028, - 0x2402000d, 0xa742014a, 0x24830008, 0x30631fff, 0x24624000, 0x0342d821, - 0x30a20007, 0xaf840018, 0xaf830028, 0xaf430084, 0x10400002, 0x24a20007, - 0x3045fff8, 0x8f820044, 0x8f840004, 0x00451821, 0xaf82002c, 0x0064102b, - 0xaf830044, 0x14400002, 0x00641023, 0xaf820044, 0x8f840044, 0x34028000, - 0x00821021, 0x03421821, 0x3c021000, 0xaf83001c, 0xaf440080, 0x03e00008, - 0xaf420178, 0x27bdffe8, 0x3c046008, 0xafbf0014, 0xafb00010, 0x8c825000, - 0x3c1a8000, 0x2403ff7f, 0x375b4000, 0x00431024, 0x3442380c, 0xac825000, - 0x8f430008, 0x3c100800, 0x37428000, 0x34630001, 0xaf430008, 0xaf82001c, - 0x3c02601c, 0xaf800028, 0xaf400080, 0xaf400084, 0x8c450008, 0x3c036000, - 0x8c620808, 0x3c040800, 0x3c030080, 0xac830820, 0x3042fff0, 0x38420010, - 0x2c420001, 0xaf850004, 0xaf820008, 0x0e00062f, 0x00000000, 0x8f420000, - 0x30420001, 0x1040fffb, 0x00000000, 0x8f440108, 0x30822000, 0xaf840034, - 0x10400004, 0x8e02083c, 0x24420001, 0x0a00059d, 0xae02083c, 0x30820200, - 0x10400027, 0x00000000, 0x97420104, 0x1040001c, 0x30824000, 0x14400005, - 0x00000000, 0x0e00022d, 0x00000000, 0x0a000592, 0x00000000, 0x8f620008, - 0x8f630000, 0x24020030, 0x00031e02, 0x306300f0, 0x10620007, 0x28620031, - 0x14400031, 0x24020040, 0x10620007, 0x00000000, 0x0a000592, 0x00000000, - 0x0e0002dd, 0x00000000, 0x0a000592, 0x00000000, 0x0e0003b8, 0x00000000, - 0x0a000592, 0x00000000, 0x30820040, 0x1440002d, 0x00000000, 0x0000000d, - 0x00000000, 0x240004a6, 0x0a00059d, 0x00000000, 0x8f430100, 0x24020d00, - 0x1462000f, 0x30820006, 0x97420104, 0x10400005, 0x30820040, 0x0e0004e9, - 0x00000000, 0x0a000592, 0x00000000, 0x1440001b, 0x00000000, 0x0000000d, - 0x00000000, 0x240004b8, 0x0a00059d, 0x00000000, 0x1040000e, 0x30821000, - 0x10400005, 0x00000000, 0x0e00065d, 0x00000000, 0x0a000592, 0x00000000, - 0x0e00046b, 0x00000000, 0x8f820040, 0x24420001, 0xaf820040, 0x0a00059d, - 0x00000000, 0x30820040, 0x14400004, 0x00000000, 0x0000000d, 0x00000000, - 0x240004cf, 0x8f420138, 0x3c034000, 0x00431025, 0xaf420138, 0x0a00053f, - 0x00000000, 0x3c046008, 0x8c835000, 0x3c1a8000, 0x2402ff7f, 0x375b4000, - 0x00621824, 0x3463380c, 0xac835000, 0x8f420008, 0x3c056000, 0x3c03601c, - 0x34420001, 0xaf420008, 0x37428000, 0xaf800028, 0xaf82001c, 0xaf400080, - 0xaf400084, 0x8c660008, 0x8ca20808, 0x3c040800, 0x3c030080, 0xac830820, - 0x3042fff0, 0x38420010, 0x2c420001, 0xaf860004, 0xaf820008, 0x03e00008, - 0x00000000, 0x3084ffff, 0x30820007, 0x10400002, 0x24820007, 0x3044fff8, - 0x8f820028, 0x00441821, 0x30631fff, 0x24644000, 0x0344d821, 0xaf820018, - 0xaf830028, 0x03e00008, 0xaf430084, 0x3084ffff, 0x30820007, 0x10400002, - 0x24820007, 0x3044fff8, 0x8f820044, 0x8f830004, 0x00442021, 0xaf82002c, - 0x0083102b, 0xaf840044, 0x14400002, 0x00831023, 0xaf820044, 0x8f820044, - 0x34038000, 0x00431821, 0x03432021, 0xaf84001c, 0x03e00008, 0xaf420080, - 0x8f830034, 0x24020002, 0x30630006, 0x1062000d, 0x2c620003, 0x50400005, - 0x24020004, 0x10600012, 0x3c020001, 0x0a000601, 0x00000000, 0x10620007, - 0x24020006, 0x1462000f, 0x3c020111, 0x0a0005f9, 0x00821025, 0x0a0005f8, - 0x3c020101, 0x3c020011, 0x00821025, 0x24030001, 0xaf421000, 0xaf830030, - 0x0a000601, 0x00000000, 0x00821025, 0xaf421000, 0xaf800030, 0x00000000, - 0x00000000, 0x00000000, 0x03e00008, 0x00000000, 0x8f820030, 0x10400005, - 0x3c038000, 0x8f421000, 0x00431024, 0x1040fffd, 0x00000000, 0x03e00008, - 0x00000000, 0x8f820034, 0x27bdffe8, 0x30424000, 0x14400005, 0xafbf0010, - 0x0e00022d, 0x00000000, 0x0a00062d, 0x8fbf0010, 0x8f620008, 0x8f630000, - 0x24020030, 0x00031e02, 0x306300f0, 0x10620008, 0x28620031, 0x1440000d, - 0x8fbf0010, 0x24020040, 0x10620007, 0x00000000, 0x0a00062d, 0x00000000, - 0x0e0002dd, 0x00000000, 0x0a00062d, 0x8fbf0010, 0x0e0003b8, 0x00000000, - 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x8f84003c, 0x1080000f, 0x3c026000, - 0x8c430c3c, 0x30630fff, 0xaf830014, 0x14600011, 0x3082000f, 0x10400005, - 0x308200f0, 0x10400003, 0x30820f00, 0x14400006, 0x00000000, 0x0000000d, - 0x00000000, 0x2400050e, 0x03e00008, 0x00000000, 0x0000000d, 0x00000000, - 0x24000513, 0x03e00008, 0x00000000, 0xaf83003c, 0x03e00008, 0x00000000, - 0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000, - 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, 0x0a000659, 0x00a01021, - 0xac860000, 0x24840004, 0x00a01021, 0x1440fffc, 0x24a5ffff, 0x03e00008, - 0x00000000, 0x0000000d, 0x03e00008, 0x00000000, 0x3c040800, 0x8c82084c, - 0x54400007, 0xac80084c, 0x8f820034, 0x24030400, 0x30420c00, 0x1443005b, - 0x00000000, 0xac80084c, 0x0000000d, 0x00000000, 0x2400003c, 0x3c026000, - 0x8c444448, 0x3c030800, 0xac640850, 0x24000043, 0x97420104, 0x3045ffff, - 0x000530c2, 0x24a2007f, 0x000239c2, 0x2400004e, 0x3c046020, 0x24030020, - 0xac830000, 0x8c820000, 0x30420020, 0x10400005, 0x3c036020, 0x8c620000, - 0x30420020, 0x1440fffd, 0x00000000, 0x3c026020, 0x8c430010, 0x24040001, - 0x0087102b, 0x30ea007f, 0x24abfffe, 0x10400010, 0x00034240, 0x3c056020, - 0x24090020, 0xaca90000, 0x8ca20000, 0x30420020, 0x10400006, 0x24840001, - 0x3c036020, 0x8c620000, 0x30420020, 0x1440fffd, 0x00000000, 0x0087102b, - 0x1440fff4, 0x00000000, 0x8f85001c, 0x3c026020, 0x8c430010, 0x3c046020, - 0x34848000, 0x006a1825, 0x01034025, 0x2400006b, 0x10c0000b, 0x00000000, - 0x8ca30000, 0x24a50004, 0x8ca20000, 0x24a50004, 0x24c6ffff, 0xac820000, - 0x24840004, 0xac830000, 0x14c0fff7, 0x24840004, 0x24000077, 0x3c020007, - 0x34427700, 0x3c036000, 0xac6223c8, 0xac6b23cc, 0xac6823e4, 0x24000086, - 0x3c046000, 0x3c038000, 0x8c8223f8, 0x00431024, 0x1440fffd, 0x3c021000, - 0x3c056000, 0x24030019, 0xaca223f8, 0xa743014a, 0x8ca44448, 0x3c020800, - 0xac440854, 0x03e00008, 0x00000000, 0x00000000 }; + 0x8f820024, 0x30420001, 0x10400007, 0x3069ffff, 0x24020002, 0x2523fffe, + 0xa7420146, 0xa7430148, 0x0a000242, 0x3c020800, 0xa7400146, 0x3c020800, + 0x8c43083c, 0x1460000e, 0x24020f00, 0x8f820024, 0x30430020, 0x0003182b, + 0x00031823, 0x30650009, 0x30420c00, 0x24030400, 0x14430002, 0x34a40001, + 0x34a40005, 0xa744014a, 0x0a000264, 0x3c020800, 0x8f830014, 0x14620008, + 0x00000000, 0x8f820024, 0x30420020, 0x0002102b, 0x00021023, 0x3042000d, + 0x0a000262, 0x34420005, 0x8f820024, 0x30420020, 0x0002102b, 0x00021023, + 0x30420009, 0x34420001, 0xa742014a, 0x3c020800, 0x8c430820, 0x8f840024, + 0x3c020048, 0x00621825, 0x30840006, 0x24020002, 0x1082000d, 0x2c820003, + 0x50400005, 0x24020004, 0x10800012, 0x3c020001, 0x0a000284, 0x00000000, + 0x10820007, 0x24020006, 0x1482000f, 0x3c020111, 0x0a00027c, 0x00621025, + 0x0a00027b, 0x3c020101, 0x3c020011, 0x00621025, 0x24030001, 0xaf421000, + 0xaf830020, 0x0a000284, 0x00000000, 0x00621025, 0xaf421000, 0xaf800020, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8f830020, 0x1060003f, + 0x3c048000, 0x8f421000, 0x00441024, 0x1040fffd, 0x00000000, 0x10600039, + 0x00000000, 0x8f421000, 0x3c030020, 0x00431024, 0x10400034, 0x00000000, + 0x97421014, 0x14400031, 0x00000000, 0x97421008, 0x8f840010, 0x24420006, + 0x00024082, 0x00081880, 0x00643821, 0x8ce50000, 0x30430003, 0x30420001, + 0x10400004, 0x00000000, 0x0000000d, 0x0a0002c3, 0x00081080, 0x5460000f, + 0x30a5ffff, 0x3c06ffff, 0x00a62824, 0x0005182b, 0x00a61026, 0x0002102b, + 0x00621824, 0x10600004, 0x00000000, 0x0000000d, 0x00000000, 0x240001fb, + 0x8ce20000, 0x0a0002c2, 0x00462825, 0x0005182b, 0x38a2ffff, 0x0002102b, + 0x00621824, 0x10600004, 0x00000000, 0x0000000d, 0x00000000, 0x24000205, + 0x8ce20000, 0x3445ffff, 0x00081080, 0x00441021, 0x3c030800, 0xac450000, + 0x8c620830, 0x24420001, 0xac620830, 0x8f840018, 0x01202821, 0x24820008, + 0x30421fff, 0x24434000, 0x0343d821, 0x30a30007, 0xaf84000c, 0xaf820018, + 0xaf420084, 0x10600002, 0x24a20007, 0x3045fff8, 0x8f820030, 0x8f840000, + 0x00451821, 0xaf82001c, 0x0064102b, 0xaf830030, 0x14400002, 0x00641023, + 0xaf820030, 0x8f840030, 0x34028000, 0x00821021, 0x03421821, 0x3c021000, + 0xaf830010, 0xaf440080, 0x03e00008, 0xaf420178, 0x8f830024, 0x27bdffe0, + 0xafbf0018, 0xafb10014, 0x30620200, 0x14400004, 0xafb00010, 0x0000000d, + 0x00000000, 0x24000242, 0x00031a82, 0x30630003, 0x000310c0, 0x00431021, + 0x00021080, 0x00431021, 0x00021080, 0x3c030800, 0x24631aa0, 0x00438821, + 0x8e240000, 0x10800004, 0x00000000, 0x0000000d, 0x00000000, 0x2400024d, + 0x8f850010, 0x24020001, 0xae220000, 0x8ca70008, 0xa2200007, 0x8f620004, + 0x26300014, 0x02002021, 0x00021402, 0xa2220004, 0x304600ff, 0x24c60005, + 0x0e000673, 0x00063082, 0x8f620004, 0xa6220008, 0x8f430108, 0x3c021000, + 0x00621824, 0x10600008, 0x00000000, 0x97420104, 0x92230007, 0x2442ffec, + 0x3045ffff, 0x34630002, 0x0a000321, 0xa2230007, 0x97420104, 0x2442fff0, + 0x3045ffff, 0x8f620004, 0x3042ffff, 0x2c420013, 0x54400005, 0x92230007, + 0x92220007, 0x34420001, 0xa2220007, 0x92230007, 0x24020001, 0x10620009, + 0x28620002, 0x14400014, 0x24020002, 0x10620012, 0x24020003, 0x1062000a, + 0x00000000, 0x0a000342, 0x00000000, 0x8f820010, 0x8c43000c, 0x3c04ffff, + 0x00641824, 0x00651825, 0x0a000342, 0xac43000c, 0x8f820010, 0x8c430010, + 0x3c04ffff, 0x00641824, 0x00651825, 0xac430010, 0x8f620004, 0x3042ffff, + 0x24420002, 0x00021083, 0xa2220005, 0x304500ff, 0x8f820010, 0x3c04ffff, + 0x00052880, 0x00a22821, 0x8ca70000, 0x96220008, 0x97430104, 0x00e42024, + 0x24420002, 0x00621823, 0x00833825, 0xaca70000, 0x92240005, 0x00041080, + 0x02021021, 0x90430000, 0x3c05fff6, 0x34a5ffff, 0x3063000f, 0x00832021, + 0xa2240006, 0x308200ff, 0x24420003, 0x00021080, 0x02021021, 0x8c460000, + 0x308300ff, 0x8f820010, 0x3c04ff3f, 0x00031880, 0x00c53824, 0x00621821, + 0xae26000c, 0xac67000c, 0x8e22000c, 0x92230006, 0x3484ffff, 0x00441024, + 0x24630003, 0x00031880, 0x02031821, 0x00e42024, 0xae22000c, 0xac640000, + 0x92220006, 0x24420004, 0x00021080, 0x02021021, 0x94470002, 0xac470000, + 0x92230006, 0x8f820010, 0x00031880, 0x00621821, 0x24020010, 0xac670010, + 0x24030002, 0xa7420140, 0xa7400142, 0xa7400144, 0xa7430146, 0x97420104, + 0x24030001, 0x2442fffe, 0xa7420148, 0xa743014a, 0x8f820024, 0x24030002, + 0x30440006, 0x1083000d, 0x2c820003, 0x10400005, 0x24020004, 0x10800011, + 0x3c020009, 0x0a0003a5, 0x00000000, 0x10820007, 0x24020006, 0x1482000d, + 0x3c020119, 0x0a00039f, 0x24030001, 0x0a00039e, 0x3c020109, 0x3c020019, + 0x24030001, 0xaf421000, 0xaf830020, 0x0a0003a5, 0x00000000, 0xaf421000, + 0xaf800020, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x92220004, + 0x24030008, 0x8f840020, 0x24420002, 0x30420007, 0x00621823, 0x30630007, + 0x10800006, 0xae230010, 0x3c038000, 0x8f421000, 0x00431024, 0x1040fffd, + 0x00000000, 0x8f820018, 0xaf82000c, 0x24420010, 0x30421fff, 0xaf820018, + 0xaf420084, 0x97430104, 0x24424000, 0x0342d821, 0x3063ffff, 0x30620007, + 0x10400002, 0x24620007, 0x3043fff8, 0x8f820030, 0x8f840000, 0x00431821, + 0xaf82001c, 0x0064102b, 0xaf830030, 0x14400002, 0x00641023, 0xaf820030, + 0x8f840030, 0x34028000, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x00821021, + 0x03421821, 0x3c021000, 0xaf830010, 0xaf440080, 0xaf420178, 0x03e00008, + 0x27bd0020, 0x8f830024, 0x27bdffe0, 0xafbf0018, 0xafb10014, 0x30620200, + 0x14400004, 0xafb00010, 0x0000000d, 0x00000000, 0x240002e4, 0x00031a82, + 0x30630003, 0x000310c0, 0x00431021, 0x00021080, 0x00431021, 0x00021080, + 0x3c030800, 0x24631aa0, 0x00438021, 0x8e040000, 0x14800004, 0x00000000, + 0x0000000d, 0x00000000, 0x240002e9, 0x8f620004, 0x04410008, 0x26050014, + 0x92020006, 0x8e03000c, 0x24420003, 0x00021080, 0x00a21021, 0xac430000, + 0xae000000, 0x92020005, 0x24420001, 0x00021080, 0x00a21021, 0x8c430000, + 0x3c040001, 0x00641821, 0xac430000, 0x92060004, 0x27710008, 0x02202021, + 0x24c60005, 0x0e000673, 0x00063082, 0x92040006, 0x3c057fff, 0x8f620004, + 0x00042080, 0x00912021, 0x8c830004, 0x34a5ffff, 0x00451024, 0x00621821, + 0xac830004, 0x92050005, 0x3c07ffff, 0x92040004, 0x00052880, 0x00b12821, + 0x8ca30000, 0x97420104, 0x96060008, 0x00671824, 0x00441021, 0x00461023, + 0x3042ffff, 0x00621825, 0xaca30000, 0x92030007, 0x24020001, 0x1062000a, + 0x28620002, 0x1440001d, 0x2402000a, 0x24020002, 0x10620019, 0x24020003, + 0x1062000e, 0x2402000a, 0x0a000447, 0x00000000, 0x92020004, 0x97430104, + 0x8e24000c, 0x00621821, 0x2463fff2, 0x3063ffff, 0x00872024, 0x00832025, + 0xae24000c, 0x0a000447, 0x2402000a, 0x92020004, 0x97430104, 0x8e240010, + 0x00621821, 0x2463ffee, 0x3063ffff, 0x00872024, 0x00832025, 0xae240010, + 0x2402000a, 0xa7420140, 0x96030012, 0x8f840024, 0xa7430142, 0x92020004, + 0xa7420144, 0xa7400146, 0x97430104, 0x30840006, 0x24020001, 0xa7430148, + 0xa742014a, 0x24020002, 0x1082000d, 0x2c820003, 0x10400005, 0x24020004, + 0x10800011, 0x3c020041, 0x0a00046c, 0x00000000, 0x10820007, 0x24020006, + 0x1482000d, 0x3c020151, 0x0a000466, 0x24030001, 0x0a000465, 0x3c020141, + 0x3c020051, 0x24030001, 0xaf421000, 0xaf830020, 0x0a00046c, 0x00000000, + 0xaf421000, 0xaf800020, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x8f820020, 0x8f840018, 0x10400006, 0x92030004, 0x3c058000, 0x8f421000, + 0x00451024, 0x1040fffd, 0x00000000, 0x2463000a, 0x30620007, 0x10400002, + 0x24620007, 0x304303f8, 0x00831021, 0x30421fff, 0xaf84000c, 0xaf820018, + 0xaf420084, 0x97430104, 0x24424000, 0x0342d821, 0x3063ffff, 0x30620007, + 0x10400002, 0x24620007, 0x3043fff8, 0x8f820030, 0x8f840000, 0x00431821, + 0xaf82001c, 0x0064102b, 0xaf830030, 0x14400002, 0x00641023, 0xaf820030, + 0x8f840030, 0x34028000, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x00821021, + 0x03421821, 0x3c021000, 0xaf830010, 0xaf440080, 0xaf420178, 0x03e00008, + 0x27bd0020, 0x8f620000, 0x97430104, 0x3c048000, 0x3045ffff, 0x3066ffff, + 0x8f420178, 0x00441024, 0x1440fffd, 0x2402000a, 0x30a30007, 0xa7420140, + 0x24020008, 0x00431023, 0x30420007, 0x24a3fffe, 0xa7420142, 0xa7430144, + 0xa7400146, 0xa7460148, 0x8f420108, 0x8f830024, 0x30420020, 0x0002102b, + 0x00021023, 0x30420009, 0x34420001, 0x30630006, 0xa742014a, 0x24020002, + 0x1062000d, 0x2c620003, 0x10400005, 0x24020004, 0x10600011, 0x3c020041, + 0x0a0004d6, 0x00000000, 0x10620007, 0x24020006, 0x1462000d, 0x3c020151, + 0x0a0004d0, 0x24030001, 0x0a0004cf, 0x3c020141, 0x3c020051, 0x24030001, + 0xaf421000, 0xaf830020, 0x0a0004d6, 0x00000000, 0xaf421000, 0xaf800020, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8f820020, 0x24a30008, + 0x8f850018, 0x10400006, 0x30c6ffff, 0x3c048000, 0x8f421000, 0x00441024, + 0x1040fffd, 0x00000000, 0x3063ffff, 0x30620007, 0x10400002, 0x24620007, + 0x3043fff8, 0x00a31021, 0x30421fff, 0x24434000, 0x0343d821, 0x00c02021, + 0x30830007, 0xaf85000c, 0xaf820018, 0xaf420084, 0x10600002, 0x24820007, + 0x3044fff8, 0x8f820030, 0x8f850000, 0x00441821, 0xaf82001c, 0x0065102b, + 0xaf830030, 0x14400002, 0x00651023, 0xaf820030, 0x8f840030, 0x34028000, + 0x3c030800, 0x8c650834, 0x00821021, 0x03421821, 0xaf830010, 0xaf440080, + 0x10a00006, 0x2402000e, 0x9383002f, 0x14620004, 0x3c021000, 0x2402043f, + 0xa7420148, 0x3c021000, 0x03e00008, 0xaf420178, 0x8f820024, 0x30424000, + 0x10400005, 0x24020800, 0x0000000d, 0x00000000, 0x2400040e, 0x24020800, + 0xaf420178, 0x97440104, 0x3c030008, 0xaf430140, 0x8f820024, 0x30420001, + 0x10400006, 0x3085ffff, 0x24020002, 0x24a3fffe, 0xa7420146, 0x0a000526, + 0xa7430148, 0xa7400146, 0x8f840018, 0x2402000d, 0xa742014a, 0x24830008, + 0x30631fff, 0x24624000, 0x0342d821, 0x30a20007, 0xaf84000c, 0xaf830018, + 0xaf430084, 0x10400002, 0x24a20007, 0x3045fff8, 0x8f820030, 0x8f840000, + 0x00451821, 0xaf82001c, 0x0064102b, 0xaf830030, 0x14400002, 0x00641023, + 0xaf820030, 0x8f840030, 0x34028000, 0x00821021, 0x03421821, 0x3c021000, + 0xaf830010, 0xaf440080, 0x03e00008, 0xaf420178, 0x27bdffe8, 0x3c046008, + 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000, 0x2403ff7f, 0x375b4000, + 0x00431024, 0x3442380c, 0xac825000, 0x8f430008, 0x3c100800, 0x37428000, + 0x34630001, 0xaf430008, 0xaf820010, 0x3c02601c, 0xaf800018, 0xaf400080, + 0xaf400084, 0x8c450008, 0x3c036000, 0x8c620808, 0x3c040800, 0x3c030080, + 0xac830820, 0x3042fff0, 0x38420010, 0x2c420001, 0xaf850000, 0xaf820004, + 0x0e000658, 0x00000000, 0x8f420000, 0x30420001, 0x1040fffb, 0x00000000, + 0x8f430108, 0x8f440100, 0x30622000, 0xaf830024, 0xaf840014, 0x10400004, + 0x8e02082c, 0x24420001, 0x0a0005c6, 0xae02082c, 0x30620200, 0x14400003, + 0x24020f00, 0x14820027, 0x24020d00, 0x97420104, 0x1040001c, 0x30624000, + 0x14400005, 0x00000000, 0x0e00022f, 0x00000000, 0x0a0005bb, 0x00000000, + 0x8f620008, 0x8f630000, 0x24020030, 0x00031e02, 0x306300f0, 0x10620007, + 0x28620031, 0x1440002f, 0x24020040, 0x10620007, 0x00000000, 0x0a0005bb, + 0x00000000, 0x0e0002e8, 0x00000000, 0x0a0005bb, 0x00000000, 0x0e0003db, + 0x00000000, 0x0a0005bb, 0x00000000, 0x30620040, 0x1440002b, 0x00000000, + 0x0000000d, 0x00000000, 0x240004b2, 0x0a0005c6, 0x00000000, 0x1482000f, + 0x30620006, 0x97420104, 0x10400005, 0x30620040, 0x0e000510, 0x00000000, + 0x0a0005bb, 0x00000000, 0x1440001b, 0x00000000, 0x0000000d, 0x00000000, + 0x240004c4, 0x0a0005c6, 0x00000000, 0x1040000e, 0x30621000, 0x10400005, + 0x00000000, 0x0e000688, 0x00000000, 0x0a0005bb, 0x00000000, 0x0e0004a1, + 0x00000000, 0x8f82002c, 0x24420001, 0xaf82002c, 0x0a0005c6, 0x00000000, + 0x30620040, 0x14400004, 0x00000000, 0x0000000d, 0x00000000, 0x240004db, + 0x8f420138, 0x3c034000, 0x00431025, 0xaf420138, 0x0a000566, 0x00000000, + 0x3c046008, 0x8c835000, 0x3c1a8000, 0x2402ff7f, 0x375b4000, 0x00621824, + 0x3463380c, 0xac835000, 0x8f420008, 0x3c056000, 0x3c03601c, 0x34420001, + 0xaf420008, 0x37428000, 0xaf800018, 0xaf820010, 0xaf400080, 0xaf400084, + 0x8c660008, 0x8ca20808, 0x3c040800, 0x3c030080, 0xac830820, 0x3042fff0, + 0x38420010, 0x2c420001, 0xaf860000, 0xaf820004, 0x03e00008, 0x00000000, + 0x3084ffff, 0x30820007, 0x10400002, 0x24820007, 0x3044fff8, 0x8f820018, + 0x00441821, 0x30631fff, 0x24644000, 0x0344d821, 0xaf82000c, 0xaf830018, + 0x03e00008, 0xaf430084, 0x3084ffff, 0x30820007, 0x10400002, 0x24820007, + 0x3044fff8, 0x8f820030, 0x8f830000, 0x00442021, 0xaf82001c, 0x0083102b, + 0xaf840030, 0x14400002, 0x00831023, 0xaf820030, 0x8f820030, 0x34038000, + 0x00431821, 0x03432021, 0xaf840010, 0x03e00008, 0xaf420080, 0x8f830024, + 0x24020002, 0x30630006, 0x1062000d, 0x2c620003, 0x50400005, 0x24020004, + 0x10600012, 0x3c020001, 0x0a00062a, 0x00000000, 0x10620007, 0x24020006, + 0x1462000f, 0x3c020111, 0x0a000622, 0x00821025, 0x0a000621, 0x3c020101, + 0x3c020011, 0x00821025, 0x24030001, 0xaf421000, 0xaf830020, 0x0a00062a, + 0x00000000, 0x00821025, 0xaf421000, 0xaf800020, 0x00000000, 0x00000000, + 0x00000000, 0x03e00008, 0x00000000, 0x8f820020, 0x10400005, 0x3c038000, + 0x8f421000, 0x00431024, 0x1040fffd, 0x00000000, 0x03e00008, 0x00000000, + 0x8f820024, 0x27bdffe8, 0x30424000, 0x14400005, 0xafbf0010, 0x0e00022f, + 0x00000000, 0x0a000656, 0x8fbf0010, 0x8f620008, 0x8f630000, 0x24020030, + 0x00031e02, 0x306300f0, 0x10620008, 0x28620031, 0x1440000d, 0x8fbf0010, + 0x24020040, 0x10620007, 0x00000000, 0x0a000656, 0x00000000, 0x0e0002e8, + 0x00000000, 0x0a000656, 0x8fbf0010, 0x0e0003db, 0x00000000, 0x8fbf0010, + 0x03e00008, 0x27bd0018, 0x8f840028, 0x1080000f, 0x3c026000, 0x8c430c3c, + 0x30630fff, 0xaf830008, 0x14600011, 0x3082000f, 0x10400005, 0x308200f0, + 0x10400003, 0x30820f00, 0x14400006, 0x00000000, 0x0000000d, 0x00000000, + 0x2400051a, 0x03e00008, 0x00000000, 0x0000000d, 0x00000000, 0x2400051f, + 0x03e00008, 0x00000000, 0xaf830028, 0x03e00008, 0x00000000, 0x10c00007, + 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000, 0x14c0fffb, + 0x24840004, 0x03e00008, 0x00000000, 0x0a000684, 0x00a01021, 0xac860000, + 0x00000000, 0x00000000, 0x24840004, 0x00a01021, 0x1440fffa, 0x24a5ffff, + 0x03e00008, 0x00000000, 0x0000000d, 0x03e00008, 0x00000000, 0x00000000}; -static u32 bnx2_TPAT_b06FwData[(0x0/4) + 1] = { 0x00000000 }; -static u32 bnx2_TPAT_b06FwRodata[(0x0/4) + 1] = { 0x00000000 }; -static u32 bnx2_TPAT_b06FwBss[(0x80/4) + 1] = { 0x00000000 }; -static u32 bnx2_TPAT_b06FwSbss[(0x48/4) + 1] = { 0x00000000 }; +static u32 bnx2_TPAT_b06FwData[(0x0/4) + 1] = { 0x0 }; +static u32 bnx2_TPAT_b06FwRodata[(0x0/4) + 1] = { 0x0 }; +static u32 bnx2_TPAT_b06FwBss[(0x250/4) + 1] = { 0x0 }; +static u32 bnx2_TPAT_b06FwSbss[(0x34/4) + 1] = { 0x0 }; -static int bnx2_TXP_b06FwReleaseMajor = 0x0; +static int bnx2_TXP_b06FwReleaseMajor = 0x1; static int bnx2_TXP_b06FwReleaseMinor = 0x0; static int bnx2_TXP_b06FwReleaseFix = 0x0; -static u32 bnx2_TXP_b06FwStartAddr = 0x08002090; +static u32 bnx2_TXP_b06FwStartAddr = 0x080034b0; static u32 bnx2_TXP_b06FwTextAddr = 0x08000000; -static int bnx2_TXP_b06FwTextLen = 0x3ffc; -static u32 bnx2_TXP_b06FwDataAddr = 0x08004020; +static int bnx2_TXP_b06FwTextLen = 0x5748; +static u32 bnx2_TXP_b06FwDataAddr = 0x08005760; static int bnx2_TXP_b06FwDataLen = 0x0; static u32 bnx2_TXP_b06FwRodataAddr = 0x00000000; static int bnx2_TXP_b06FwRodataLen = 0x0; -static u32 bnx2_TXP_b06FwBssAddr = 0x08004060; -static int bnx2_TXP_b06FwBssLen = 0x194; -static u32 bnx2_TXP_b06FwSbssAddr = 0x08004020; -static int bnx2_TXP_b06FwSbssLen = 0x34; -static u32 bnx2_TXP_b06FwText[(0x3ffc/4) + 1] = { - 0x0a000824, 0x00000000, 0x00000000, 0x0000000d, 0x74787020, 0x302e362e, - 0x39000000, 0x00060900, 0x0000000a, 0x000003e8, 0x0000ea60, 0x00000000, +static u32 bnx2_TXP_b06FwBssAddr = 0x080057a0; +static int bnx2_TXP_b06FwBssLen = 0x1c4; +static u32 bnx2_TXP_b06FwSbssAddr = 0x08005760; +static int bnx2_TXP_b06FwSbssLen = 0x38; +static u32 bnx2_TXP_b06FwText[(0x5748/4) + 1] = { + 0x0a000d2c, 0x00000000, 0x00000000, 0x0000000d, 0x74787020, 0x322e352e, + 0x38000000, 0x02050800, 0x0000000a, 0x000003e8, 0x0000ea60, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -2124,55 +2965,182 @@ static u32 bnx2_TXP_b06FwText[(0x3ffc/4) + 1] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x10000003, 0x00000000, 0x0000000d, - 0x0000000d, 0x3c020800, 0x24424020, 0x3c030800, 0x246341f4, 0xac400000, - 0x0043202b, 0x1480fffd, 0x24420004, 0x3c1d0800, 0x37bd7ffc, 0x03a0f021, - 0x3c100800, 0x26102090, 0x3c1c0800, 0x279c4020, 0x0e000a0e, 0x00000000, - 0x0000000d, 0x8f840014, 0x27bdffe8, 0xafb00010, 0x8f460104, 0x8f830008, - 0x8c8500ac, 0xaf430080, 0x948200a8, 0xa7420e10, 0x948300aa, 0xa7430e12, - 0x8c8200ac, 0xaf420e18, 0x97430e10, 0xa7430e14, 0x97420e12, 0xa7420e16, - 0x8f430e18, 0x00005021, 0x00c53023, 0x10c001a3, 0xaf430e1c, 0x240f0800, - 0x3c0e1000, 0x2419fff8, 0x24100010, 0x3c188100, 0x93620008, 0x10400009, - 0x00000000, 0x97620010, 0x00c2102b, 0x14400005, 0x00000000, 0x97620010, - 0x3042ffff, 0x0a000862, 0xaf420e00, 0xaf460e00, 0x8f420000, 0x30420008, - 0x1040fffd, 0x00000000, 0x97420e08, 0x8f450e04, 0x3044ffff, 0x30820001, - 0x14400005, 0x00000000, 0x14a00005, 0x3083a040, 0x0a0009e6, 0x00000000, - 0x0000000d, 0x3083a040, 0x24020040, 0x14620049, 0x3082a000, 0x8f87000c, - 0x30880036, 0x30890008, 0xaf4f0178, 0x00e01821, 0x9742008a, 0x00431023, - 0x2442ffff, 0x30421fff, 0x2c420008, 0x1440fffa, 0x00000000, 0x8f830018, - 0x00a05021, 0x00c53023, 0x24e24000, 0x03422821, 0x306b00ff, 0x24630001, - 0xaf830018, 0x93840012, 0x000b1400, 0x3c030100, 0x00431025, 0xaca20000, - 0x8f820018, 0x30840007, 0x00042240, 0x34870001, 0x00e83825, 0x1120000f, - 0xaca20004, 0x97430e0a, 0x8f84000c, 0x00ee3825, 0x2402000e, 0x00781825, - 0xaf430160, 0x25430006, 0x24840008, 0x30841fff, 0xa742015a, 0xa7430158, - 0xaf84000c, 0x0a0008a9, 0x00000000, 0x8f83000c, 0x25420002, 0xa7420158, - 0x24630008, 0x30631fff, 0xaf83000c, 0x54c0000c, 0x8f420e14, 0x97420e10, - 0x97430e12, 0x8f840014, 0x00021400, 0x00621825, 0xac8300a8, 0x8f850014, - 0x8f420e18, 0x34e70040, 0xaca200ac, 0x8f420e14, 0x8f430e1c, 0xaf420144, - 0xaf430148, 0xa34b0152, 0xaf470154, 0x0a0009f1, 0xaf4e0178, 0x10400128, - 0x00000000, 0x97620010, 0x00a2102b, 0x10400003, 0x30820040, 0x10400122, - 0x00000000, 0xafa60008, 0xa7840010, 0xaf850004, 0x93620008, 0x1440005e, - 0x27ac0008, 0xaf60000c, 0x97820010, 0x30424000, 0x10400002, 0x2403000e, - 0x24030016, 0xa363000a, 0x24034007, 0xaf630014, 0x93820012, 0x8f630014, - 0x30420007, 0x00021240, 0x00621825, 0xaf630014, 0x97820010, 0x8f630014, - 0x30420010, 0x00621825, 0xaf630014, 0x97820010, 0x30420008, 0x5040000e, - 0x00002821, 0x8f620014, 0x004e1025, 0xaf620014, 0x97430e0a, 0x2402000e, - 0x00781825, 0xaf630004, 0xa3620002, 0x9363000a, 0x3405fffc, 0x24630004, - 0x0a0008f2, 0xa363000a, 0xaf600004, 0xa3600002, 0x97820010, 0x9363000a, - 0x30421f00, 0x00021182, 0x24420028, 0x00621821, 0xa3630009, 0x97420e0c, - 0xa7620010, 0x93630009, 0x24020008, 0x24630002, 0x30630007, 0x00431023, - 0x30420007, 0xa362000b, 0x93640009, 0x97620010, 0x8f890004, 0x97830010, - 0x00441021, 0x00a21021, 0x30630040, 0x10600006, 0x3045ffff, 0x15250005, - 0x0125102b, 0x3c068000, 0x0a000925, 0x00005821, 0x0125102b, 0x144000c8, - 0x00005021, 0x97420e14, 0xa7420e10, 0x97430e16, 0xa7430e12, 0x8f420e1c, - 0xaf420e18, 0xaf450e00, 0x8f420000, 0x30420008, 0x1040fffd, 0x00000000, - 0x97420e08, 0x00a04821, 0xa7820010, 0x8f430e04, 0x00003021, 0x240b0001, - 0xaf830004, 0x97620010, 0x0a000936, 0x304dffff, 0x8f890004, 0x97820010, - 0x30420040, 0x10400004, 0x01206821, 0x3c068000, 0x0a000936, 0x00005821, - 0x97630010, 0x8f820004, 0x144300a7, 0x00005021, 0x00003021, 0x240b0001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800, + 0x24425760, 0x3c030800, 0x24635964, 0xac400000, 0x0043202b, 0x1480fffd, + 0x24420004, 0x3c1d0800, 0x37bd7ffc, 0x03a0f021, 0x3c100800, 0x261034b0, + 0x3c1c0800, 0x279c5760, 0x0e000f5b, 0x00000000, 0x0000000d, 0x8f840014, + 0x27bdffe8, 0xafb10014, 0xafb00010, 0x8f460104, 0x8f830008, 0x8c8500ac, + 0xaf430080, 0x948200a8, 0xa7420e10, 0x948300aa, 0xa7430e12, 0x8c8200ac, + 0xaf420e18, 0x97430e10, 0xa7430e14, 0x97420e12, 0x00008021, 0xa7420e16, + 0x8f430e18, 0x00006021, 0x00c53023, 0xaf430e1c, 0x10c001a2, 0x2d820001, + 0x3c0e1000, 0x2419fff8, 0x24110010, 0x240f0f00, 0x3c188100, 0x93620008, + 0x10400009, 0x00000000, 0x97620010, 0x00c2102b, 0x14400005, 0x00000000, + 0x97620010, 0x3042ffff, 0x0a000d6d, 0xaf420e00, 0xaf460e00, 0x8f420000, + 0x30420008, 0x1040fffd, 0x00000000, 0x97420e08, 0x8f450e04, 0x3044ffff, + 0x30820001, 0x14400005, 0x00000000, 0x14a00005, 0x3083a040, 0x0a000f34, + 0x00000000, 0x0000000d, 0x3083a040, 0x24020040, 0x1462004f, 0x3082a000, + 0x308a0036, 0x8f88000c, 0x30890008, 0x24020800, 0xaf420178, 0x01001821, + 0x9742008a, 0x00431023, 0x2442ffff, 0x30421fff, 0x2c420008, 0x1440fffa, + 0x00a06021, 0x8f820018, 0x00cc3023, 0x24070001, 0x8f830008, 0x304b00ff, + 0x24420001, 0xaf820018, 0x25024000, 0x106f0005, 0x03422021, 0x93820012, + 0x30420007, 0x00021240, 0x34470001, 0x000b1400, 0x3c030100, 0x00431025, + 0xac820000, 0x8f830018, 0x00ea3825, 0x1120000f, 0xac830004, 0x97430e0a, + 0x8f84000c, 0x00ee3825, 0x2402000e, 0x00781825, 0xaf430160, 0x25830006, + 0x24840008, 0x30841fff, 0xa742015a, 0xa7430158, 0xaf84000c, 0x0a000db7, + 0x00000000, 0x8f83000c, 0x25820002, 0xa7420158, 0x24630008, 0x30631fff, + 0xaf83000c, 0x54c0000f, 0x8f420e14, 0x8f820008, 0x504f0002, 0x24100001, + 0x34e70040, 0x97420e10, 0x97430e12, 0x8f850014, 0x00021400, 0x00621825, + 0xaca300a8, 0x8f840014, 0x8f420e18, 0xac8200ac, 0x8f420e14, 0x8f430e1c, + 0xaf420144, 0xaf430148, 0xa34b0152, 0xaf470154, 0x0a000efb, 0xaf4e0178, + 0x10400165, 0x00000000, 0x93620008, 0x50400008, 0xafa60008, 0x97620010, + 0x00a2102b, 0x10400003, 0x30820040, 0x1040015c, 0x00000000, 0xafa60008, + 0xa7840010, 0xaf850004, 0x93620008, 0x1440005f, 0x27ac0008, 0xaf60000c, + 0x97820010, 0x30424000, 0x10400002, 0x2403000e, 0x24030016, 0xa363000a, + 0x24034007, 0xaf630014, 0x93820012, 0x8f630014, 0x30420007, 0x00021240, + 0x00621825, 0xaf630014, 0x97820010, 0x8f630014, 0x30420010, 0x00621825, + 0xaf630014, 0x97820010, 0x30420008, 0x5040000e, 0x00002821, 0x8f620014, + 0x004e1025, 0xaf620014, 0x97430e0a, 0x2402000e, 0x00781825, 0xaf630004, + 0xa3620002, 0x9363000a, 0x3405fffc, 0x24630004, 0x0a000e06, 0xa363000a, + 0xaf600004, 0xa3600002, 0x97820010, 0x9363000a, 0x30421f00, 0x00021182, + 0x24420028, 0x00621821, 0xa3630009, 0x97420e0c, 0xa7620010, 0x93630009, + 0x24020008, 0x24630002, 0x30630007, 0x00431023, 0x30420007, 0xa362000b, + 0x93640009, 0x97620010, 0x8f890004, 0x97830010, 0x00441021, 0x00a21021, + 0x30630040, 0x10600007, 0x3045ffff, 0x00a9102b, 0x14400005, 0x0125102b, + 0x3c068000, 0x0a000e3a, 0x00005821, 0x0125102b, 0x544000c7, 0x00006021, + 0x97420e14, 0xa7420e10, 0x97430e16, 0xa7430e12, 0x8f420e1c, 0xaf420e18, + 0xaf450e00, 0x8f420000, 0x30420008, 0x1040fffd, 0x00000000, 0x97420e08, + 0x00a04821, 0xa7820010, 0x8f430e04, 0x00003021, 0x240b0001, 0xaf830004, + 0x97620010, 0x0a000e4c, 0x304dffff, 0x8f890004, 0x97820010, 0x30420040, + 0x10400004, 0x01206821, 0x3c068000, 0x0a000e4c, 0x00005821, 0x97630010, + 0x8f820004, 0x10430003, 0x00003021, 0x0a000eee, 0x00006021, 0x240b0001, 0x8d820000, 0x00491023, 0x1440000d, 0xad820000, 0x8f620014, 0x34420040, 0xaf620014, 0x97430e10, 0x97420e12, 0x8f840014, 0x00031c00, 0x00431025, - 0xac8200a8, 0x8f830014, 0x8f420e18, 0xac6200ac, 0x93620008, 0x1440003f, + 0xac8200a8, 0x8f830014, 0x8f420e18, 0xac6200ac, 0x93620008, 0x1440003e, 0x00000000, 0x25260002, 0x8f84000c, 0x9743008a, 0x3063ffff, 0xafa30000, 0x8fa20000, 0x00441023, 0x2442ffff, 0x30421fff, 0x2c420010, 0x1440fff7, 0x00000000, 0x8f82000c, 0x8f830018, 0x00021082, 0x00021080, 0x24424000, @@ -2180,289 +3148,320 @@ static u32 bnx2_TXP_b06FwText[(0x3ffc/4) + 1] = { 0x3c033200, 0x00431025, 0xaca20000, 0x93630009, 0x9362000a, 0x00031c00, 0x00431025, 0xaca20004, 0x8f830018, 0xaca30008, 0x97820010, 0x30420008, 0x10400002, 0x00c04021, 0x25280006, 0x97430e14, 0x93640002, 0x8f450e1c, - 0x8f660004, 0x8f670014, 0xaf4f0178, 0x3063ffff, 0xa7430144, 0x97420e16, - 0xa7420146, 0xaf450148, 0xa34a0152, 0x8f82000c, 0x308400ff, 0xa744015a, - 0xaf460160, 0xa7480158, 0xaf470154, 0xaf4e0178, 0x00501021, 0x30421fff, - 0xaf82000c, 0x0a0009c5, 0x8d820000, 0x93620009, 0x9363000b, 0x8f85000c, - 0x2463000a, 0x00435021, 0x25440007, 0x00992024, 0x9743008a, 0x3063ffff, - 0xafa30000, 0x8fa20000, 0x00451023, 0x2442ffff, 0x30421fff, 0x0044102b, - 0x1440fff7, 0x00000000, 0x8f82000c, 0x8f840018, 0x00021082, 0x00021080, - 0x24424000, 0x03422821, 0x00804021, 0x24840001, 0xaf840018, 0x93630009, - 0x310200ff, 0x00022400, 0x3c024100, 0x24630002, 0x00621825, 0x00832025, - 0xaca40000, 0x8f62000c, 0x00461025, 0xaca20004, 0x97430e14, 0x93640002, - 0x8f450e1c, 0x8f660004, 0x8f670014, 0xaf4f0178, 0x3063ffff, 0xa7430144, - 0x97420e16, 0x308400ff, 0xa7420146, 0xaf450148, 0xa3480152, 0x8f83000c, - 0x25420007, 0x00591024, 0xa744015a, 0xaf460160, 0xa7490158, 0xaf470154, - 0xaf4e0178, 0x00621821, 0x30631fff, 0xaf83000c, 0x8d820000, 0x14400005, - 0x00000000, 0x8f620014, 0x2403ffbf, 0x00431024, 0xaf620014, 0x8f62000c, - 0x004d1021, 0xaf62000c, 0x93630008, 0x14600008, 0x00000000, 0x11600006, - 0x00000000, 0x8f630014, 0x3c02efff, 0x3442fffe, 0x00621824, 0xaf630014, - 0xa36b0008, 0x01205021, 0x15400016, 0x8fa60008, 0x97420e14, 0x97430e16, - 0x8f850014, 0x00021400, 0x00621825, 0xaca300a8, 0x8f840014, 0x8f420e1c, - 0x0a0009f3, 0xac8200ac, 0x97420e14, 0x97430e16, 0x8f840014, 0x00021400, - 0x00621825, 0xac8300a8, 0x8f850014, 0x8f420e1c, 0x00005021, 0x0a0009f3, - 0xaca200ac, 0x14c0fe64, 0x00000000, 0x55400018, 0x8fb00010, 0x3c038000, - 0x8f420178, 0x00431024, 0x1440fffd, 0x00000000, 0x97430e14, 0x8f440e1c, - 0x24020800, 0xaf420178, 0x3063ffff, 0xa7430144, 0x97420e16, 0x3c031000, - 0xa7420146, 0x24020240, 0xaf440148, 0xa3400152, 0xa740015a, 0xaf400160, - 0xa7400158, 0xaf420154, 0xaf430178, 0x8fb00010, 0x03e00008, 0x27bd0018, - 0x27bdffd8, 0x3c1a8000, 0x3c0420ff, 0x3484fffd, 0x3c020008, 0x03421821, - 0xafbf0020, 0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, 0xaf830014, - 0xaf440e00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x3c0200ff, 0x3442fffd, 0x3c046004, 0xaf420e00, 0x8c835000, 0x24130d00, - 0x3c120800, 0x3c114000, 0x2402ff7f, 0x00621824, 0x3463380c, 0x24020009, - 0xac835000, 0xaf420008, 0xaf800018, 0xaf80000c, 0x0e000fa1, 0x00000000, - 0x0e000a96, 0x00000000, 0x3c020800, 0x24504080, 0x8f420000, 0x30420001, - 0x1040fffd, 0x00000000, 0x8f440100, 0xaf840008, 0xaf440020, 0x93430108, - 0xa3830012, 0x93820012, 0x30420001, 0x10400008, 0x00000000, 0x93820012, - 0x30420006, 0x00021100, 0x0e00083b, 0x0050d821, 0x0a000a52, 0x00000000, - 0x14930005, 0x00000000, 0x0e00083b, 0x265b4100, 0x0a000a52, 0x00000000, - 0x0e000ba3, 0x00000000, 0xaf510138, 0x0a000a36, 0x00000000, 0x27bdfff8, - 0x3084ffff, 0x24820007, 0x3044fff8, 0x8f85000c, 0x9743008a, 0x3063ffff, - 0xafa30000, 0x8fa20000, 0x00451023, 0x2442ffff, 0x30421fff, 0x0044102b, - 0x1440fff7, 0x00000000, 0x8f82000c, 0x00021082, 0x00021080, 0x24424000, - 0x03421021, 0x03e00008, 0x27bd0008, 0x3084ffff, 0x8f82000c, 0x24840007, - 0x3084fff8, 0x00441021, 0x30421fff, 0xaf82000c, 0x03e00008, 0x00000000, - 0x27bdffe8, 0x3c1a8000, 0x3c0420ff, 0x3484fffd, 0x3c020008, 0x03421821, - 0xafbf0010, 0xaf830014, 0xaf440e00, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x3c0200ff, 0x3442fffd, 0x3c046004, 0xaf420e00, - 0x8c825000, 0x2403ff7f, 0x00431024, 0x3442380c, 0x24030009, 0xac825000, - 0xaf430008, 0xaf800018, 0xaf80000c, 0x0e000fa1, 0x00000000, 0x0e000a96, - 0x00000000, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0x3c02000a, - 0x03421821, 0x3c040800, 0x24844120, 0x24050018, 0xafbf0010, 0xaf830024, - 0x0e000fad, 0x00003021, 0x3c050800, 0x3c020800, 0x24423d60, 0xaca24180, - 0x24a54180, 0x3c020800, 0x24423e18, 0x3c030800, 0x24633e2c, 0x3c040800, - 0xaca20004, 0x3c020800, 0x24423d68, 0xaca30008, 0xac824190, 0x24844190, - 0x3c020800, 0x24423da4, 0x3c070800, 0x24e73de4, 0x3c060800, 0x24c63e40, - 0x3c050800, 0x24a52b28, 0x3c030800, 0xac820004, 0x3c020800, 0x24423e48, - 0xac870008, 0xac86000c, 0xac850010, 0xac6241b0, 0x246341b0, 0x8fbf0010, - 0x3c020800, 0x24423e60, 0xac620004, 0xac670008, 0xac66000c, 0xac650010, - 0x03e00008, 0x27bd0018, 0x27bdffc8, 0x3c020800, 0x24424120, 0xafbf0030, - 0xafb3002c, 0xafb20028, 0xafb10024, 0xafb00020, 0x90470021, 0x8c510008, - 0x8c45001c, 0x8f900020, 0x3c060800, 0x3c038000, 0x8f420178, 0x00431024, - 0x1440fffd, 0x8cc2414c, 0x24c3414c, 0x2473ffd4, 0xaf420144, 0x8e620030, - 0x30b22000, 0xaf420148, 0x3c021000, 0xaf50014c, 0xa3470152, 0xa7510158, - 0xaf450154, 0xaf420178, 0x12400004, 0x3c030800, 0x8c620030, 0x24420001, - 0xac620030, 0x93420109, 0x9344010a, 0x00111c00, 0xafa30018, 0x00071a00, - 0xafa50014, 0x8cc5414c, 0x00021600, 0x00042400, 0x00441025, 0x00431025, - 0xafa20010, 0x8f440100, 0x8e660030, 0x0e000fe1, 0x02003821, 0x1640000e, - 0x8fbf0030, 0x8f820000, 0x8e630030, 0x8c44017c, 0x02031823, 0x00711823, - 0x00641823, 0x2c630002, 0x14600006, 0x8fb3002c, 0x0000000d, 0x00000000, - 0x240000ca, 0x8fbf0030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020, - 0x03e00008, 0x27bd0038, 0x974309da, 0x00804021, 0xad030000, 0x8f4209dc, - 0xad020004, 0x8f4309e0, 0xad030008, 0x934409d9, 0x24020001, 0x30840003, - 0x1082001f, 0x30a900ff, 0x28820002, 0x10400005, 0x24020002, 0x10800009, - 0x3c0a0800, 0x0a000b64, 0x93420934, 0x1082000b, 0x24020003, 0x10820026, - 0x3c0a0800, 0x0a000b64, 0x93420934, 0x974209e4, 0x00021400, 0x34420800, - 0xad02000c, 0x0a000b63, 0x25080010, 0x974209e4, 0x00021400, 0x34428100, - 0xad02000c, 0x974309e8, 0x3c0a0800, 0x00031c00, 0x34630800, 0xad030010, - 0x0a000b63, 0x25080014, 0x974409e4, 0x3c050800, 0x24a24120, 0x94430018, - 0x94460010, 0x9447000c, 0x00a05021, 0x24020800, 0xad000010, 0xad020014, - 0x00042400, 0x00661821, 0x00671823, 0x2463fff2, 0x00832025, 0xad04000c, - 0x0a000b63, 0x25080018, 0x974209e4, 0x3c050800, 0x00021400, 0x34428100, - 0xad02000c, 0x974409e8, 0x24a24120, 0x94430018, 0x94460010, 0x9447000c, - 0x00a05021, 0x24020800, 0xad000014, 0xad020018, 0x00042400, 0x00661821, - 0x00671823, 0x2463ffee, 0x00832025, 0xad040010, 0x2508001c, 0x93420934, - 0x93450921, 0x3c074000, 0x25444120, 0x94830014, 0x94860010, 0x00021082, - 0x00021600, 0x00052c00, 0x00a72825, 0x00451025, 0x00661821, 0x00431025, - 0xad020000, 0x97830028, 0x974209ea, 0x00621821, 0x00031c00, 0xad030004, - 0x97820028, 0x24420001, 0x30427fff, 0xa7820028, 0x93430920, 0x3c020006, - 0x00031e00, 0x00621825, 0xad030008, 0x8f42092c, 0xad02000c, 0x8f430930, - 0xad030010, 0x8f440938, 0x25080014, 0xad040000, 0x8f820020, 0x11200004, - 0xad020004, 0x8f420940, 0x0a000b8d, 0x2442ffff, 0x8f420940, 0xad020008, - 0x8f440948, 0x8f420940, 0x93430936, 0x00822823, 0x00652806, 0x3402ffff, - 0x0045102b, 0x54400001, 0x3405ffff, 0x93420937, 0x25444120, 0x90830020, - 0xad000010, 0x00021700, 0x34630010, 0x00031c00, 0x00431025, 0x00451025, - 0xad02000c, 0x03e00008, 0x25020014, 0x27bdffb0, 0x3c020008, 0x03421821, - 0xafbf004c, 0xafbe0048, 0xafb70044, 0xafb60040, 0xafb5003c, 0xafb40038, - 0xafb30034, 0xafb20030, 0xafb1002c, 0xafb00028, 0xaf830000, 0x24020040, - 0xaf420814, 0xaf400810, 0x8f420944, 0x8f430950, 0x8f440954, 0x8f45095c, - 0xaf820030, 0xaf830020, 0xaf84001c, 0xaf85002c, 0x93430900, 0x24020020, - 0x10620005, 0x24020030, 0x10620022, 0x3c030800, 0x0a000bf1, 0x8c62002c, - 0x24020088, 0xaf420818, 0x3c020800, 0x24424180, 0xafa20020, 0x93430109, - 0x3c020800, 0x10600009, 0x24574190, 0x3c026000, 0x24030100, 0xac43081c, - 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000, 0x2400031d, 0x9342010a, - 0x30420080, 0x1440001c, 0x00000000, 0x3c026000, 0x24030100, 0xac43081c, - 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000, 0x24000324, 0x0a000bf4, - 0x00000000, 0x93430109, 0x3063007f, 0x00031140, 0x000318c0, 0x00431021, - 0x24430088, 0xaf430818, 0x0000000d, 0x3c020800, 0x244241d0, 0x3c030800, - 0x247741e0, 0x0a000bf4, 0xafa20020, 0x24420001, 0x0a000f4c, 0xac62002c, - 0x8f840000, 0x8f850020, 0x24020800, 0xaf420178, 0x8f4209a4, 0x8c83017c, - 0x00a21023, 0x00431023, 0x2c420002, 0x14400004, 0x00000000, 0x0000000d, - 0x00000000, 0x24000349, 0x8f420104, 0x8f430988, 0x00431023, 0x58400005, - 0x8f4209a0, 0x0000000d, 0x00000000, 0x2400034d, 0x8f4209a0, 0x3c100800, - 0xae02414c, 0x8f4309a4, 0x2604414c, 0x2491ffd4, 0xae230030, 0x8f420104, - 0xae250024, 0x00431023, 0xac82ffd4, 0x8fa30020, 0x8c620000, 0x0040f809, + 0x8f660004, 0x8f670014, 0x3063ffff, 0xa7430144, 0x97420e16, 0xa7420146, + 0xaf450148, 0xa34a0152, 0x8f82000c, 0x308400ff, 0xa744015a, 0xaf460160, + 0xa7480158, 0xaf470154, 0xaf4e0178, 0x00511021, 0x30421fff, 0xaf82000c, + 0x0a000ed9, 0x8d820000, 0x93620009, 0x9363000b, 0x8f85000c, 0x2463000a, + 0x00435021, 0x25440007, 0x00992024, 0x9743008a, 0x3063ffff, 0xafa30000, + 0x8fa20000, 0x00451023, 0x2442ffff, 0x30421fff, 0x0044102b, 0x1440fff7, + 0x00000000, 0x8f82000c, 0x8f840018, 0x00021082, 0x00021080, 0x24424000, + 0x03422821, 0x00804021, 0x24840001, 0xaf840018, 0x93630009, 0x310200ff, + 0x00022400, 0x3c024100, 0x24630002, 0x00621825, 0x00832025, 0xaca40000, + 0x8f62000c, 0x00461025, 0xaca20004, 0x97430e14, 0x93640002, 0x8f450e1c, + 0x8f660004, 0x8f670014, 0x3063ffff, 0xa7430144, 0x97420e16, 0x308400ff, + 0xa7420146, 0xaf450148, 0xa3480152, 0x8f83000c, 0x25420007, 0x00591024, + 0xa744015a, 0xaf460160, 0xa7490158, 0xaf470154, 0xaf4e0178, 0x00621821, + 0x30631fff, 0xaf83000c, 0x8d820000, 0x14400005, 0x00000000, 0x8f620014, + 0x2403ffbf, 0x00431024, 0xaf620014, 0x8f62000c, 0x004d1021, 0xaf62000c, + 0x93630008, 0x14600008, 0x00000000, 0x11600006, 0x00000000, 0x8f630014, + 0x3c02efff, 0x3442fffe, 0x00621824, 0xaf630014, 0xa36b0008, 0x01206021, + 0x1580000c, 0x8fa60008, 0x97420e14, 0x97430e16, 0x8f850014, 0x00021400, + 0x00621825, 0xaca300a8, 0x8f840014, 0x8f420e1c, 0xac8200ac, 0x0a000efd, + 0x2d820001, 0x14c0fe65, 0x2d820001, 0x00501025, 0x10400058, 0x24020f00, + 0x8f830008, 0x14620023, 0x3c048000, 0x11800009, 0x3c038000, 0x97420e08, + 0x30420040, 0x14400005, 0x00000000, 0x0000000d, 0x00000000, 0x2400032c, + 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x00000000, 0x97420e10, + 0x3c030500, 0x00431025, 0xaf42014c, 0x97430e14, 0xa7430144, 0x97420e16, + 0xa7420146, 0x8f430e1c, 0x24022000, 0xaf430148, 0x3c031000, 0xa3400152, + 0xa740015a, 0xaf400160, 0xa7400158, 0xaf420154, 0xaf430178, 0x8f830008, + 0x3c048000, 0x8f420178, 0x00441024, 0x1440fffd, 0x24020f00, 0x10620016, + 0x00000000, 0x97420e14, 0xa7420144, 0x97430e16, 0xa7430146, 0x8f420e1c, + 0x3c031000, 0xaf420148, 0x0a000f51, 0x24020240, 0x97420e14, 0x97430e16, + 0x8f840014, 0x00021400, 0x00621825, 0xac8300a8, 0x8f850014, 0x8f420e1c, + 0x00006021, 0xaca200ac, 0x0a000efd, 0x2d820001, 0xaf40014c, 0x11800007, + 0x00000000, 0x97420e10, 0xa7420144, 0x97430e12, 0xa7430146, 0x0a000f4e, + 0x8f420e18, 0x97420e14, 0xa7420144, 0x97430e16, 0xa7430146, 0x8f420e1c, + 0xaf420148, 0x24020040, 0x3c031000, 0xa3400152, 0xa740015a, 0xaf400160, + 0xa7400158, 0xaf420154, 0xaf430178, 0x8fb10014, 0x8fb00010, 0x03e00008, + 0x27bd0018, 0x27bdffd0, 0x3c1a8000, 0x3c0420ff, 0x3484fffd, 0x3c020008, + 0x03421821, 0xafbf002c, 0xafb60028, 0xafb50024, 0xafb40020, 0xafb3001c, + 0xafb20018, 0xafb10014, 0xafb00010, 0xaf830014, 0xaf440e00, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3c0200ff, 0x3442fffd, + 0x3c046004, 0xaf420e00, 0x8c835000, 0x24160800, 0x24150d00, 0x3c140800, + 0x24130f00, 0x3c120800, 0x3c114000, 0x2402ff7f, 0x00621824, 0x3463380c, + 0x24020009, 0xac835000, 0xaf420008, 0xaf800018, 0xaf80000c, 0x0e001559, + 0x00000000, 0x0e000ff0, 0x00000000, 0x3c020800, 0x245057c0, 0x8f420000, + 0x30420001, 0x1040fffd, 0x00000000, 0x8f440100, 0xaf840008, 0xaf440020, + 0xaf560178, 0x93430108, 0xa3830012, 0x93820012, 0x30420001, 0x10400008, + 0x00000000, 0x93820012, 0x30420006, 0x00021100, 0x0e000d43, 0x0050d821, + 0x0a000fac, 0x00000000, 0x14950005, 0x00000000, 0x0e000d43, 0x269b5840, + 0x0a000fac, 0x00000000, 0x14930005, 0x00000000, 0x0e000d43, 0x265b5860, + 0x0a000fac, 0x00000000, 0x0e0010ea, 0x00000000, 0xaf510138, 0x0a000f89, + 0x00000000, 0x27bdfff8, 0x3084ffff, 0x24820007, 0x3044fff8, 0x8f85000c, + 0x9743008a, 0x3063ffff, 0xafa30000, 0x8fa20000, 0x00451023, 0x2442ffff, + 0x30421fff, 0x0044102b, 0x1440fff7, 0x00000000, 0x8f82000c, 0x00021082, + 0x00021080, 0x24424000, 0x03421021, 0x03e00008, 0x27bd0008, 0x3084ffff, + 0x8f82000c, 0x24840007, 0x3084fff8, 0x00441021, 0x30421fff, 0xaf82000c, + 0x03e00008, 0x00000000, 0x27bdffe8, 0x3c1a8000, 0x3c0420ff, 0x3484fffd, + 0x3c020008, 0x03421821, 0xafbf0010, 0xaf830014, 0xaf440e00, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3c0200ff, 0x3442fffd, + 0x3c046004, 0xaf420e00, 0x8c825000, 0x2403ff7f, 0x00431024, 0x3442380c, + 0x24030009, 0xac825000, 0xaf430008, 0xaf800018, 0xaf80000c, 0x0e001559, + 0x00000000, 0x0e000ff0, 0x00000000, 0x8fbf0010, 0x03e00008, 0x27bd0018, + 0x27bdffe8, 0x3c02000a, 0x03421821, 0x3c040800, 0x24845880, 0x24050019, + 0xafbf0010, 0xaf830024, 0x0e001565, 0x00003021, 0x3c050800, 0x3c020800, + 0x24425330, 0xaca258e8, 0x24a558e8, 0x3c020800, 0x244254f8, 0x3c030800, + 0x2463550c, 0x3c040800, 0xaca20004, 0x3c020800, 0x24425338, 0xaca30008, + 0xac825900, 0x24845900, 0x3c020800, 0x244253c4, 0x3c070800, 0x24e75404, + 0x3c060800, 0x24c65520, 0x3c050800, 0x24a55438, 0x3c030800, 0xac820004, + 0x3c020800, 0x24425528, 0xac870008, 0xac86000c, 0xac850010, 0xac625920, + 0x24635920, 0x8fbf0010, 0x3c020800, 0x24425540, 0xac620004, 0x3c020800, + 0xac670008, 0xac66000c, 0xac650010, 0xac400048, 0x03e00008, 0x27bd0018, + 0x974309da, 0x00804021, 0xad030000, 0x8f4209dc, 0xad020004, 0x8f4309e0, + 0xad030008, 0x934409d9, 0x24020001, 0x30840003, 0x1082001f, 0x30a900ff, + 0x28820002, 0x10400005, 0x24020002, 0x10800009, 0x3c0a0800, 0x0a001078, + 0x93420934, 0x1082000b, 0x24020003, 0x10820026, 0x3c0a0800, 0x0a001078, + 0x93420934, 0x974209e4, 0x00021400, 0x34420800, 0xad02000c, 0x0a001077, + 0x25080010, 0x974209e4, 0x00021400, 0x34428100, 0xad02000c, 0x974309e8, + 0x3c0a0800, 0x00031c00, 0x34630800, 0xad030010, 0x0a001077, 0x25080014, + 0x974409e4, 0x3c050800, 0x24a25880, 0x9443001c, 0x94460014, 0x94470010, + 0x00a05021, 0x24020800, 0xad000010, 0xad020014, 0x00042400, 0x00661821, + 0x00671823, 0x2463fff2, 0x00832025, 0xad04000c, 0x0a001077, 0x25080018, + 0x974209e4, 0x3c050800, 0x00021400, 0x34428100, 0xad02000c, 0x974409e8, + 0x24a25880, 0x9443001c, 0x94460014, 0x94470010, 0x00a05021, 0x24020800, + 0xad000014, 0xad020018, 0x00042400, 0x00661821, 0x00671823, 0x2463ffee, + 0x00832025, 0xad040010, 0x2508001c, 0x93420934, 0x93450921, 0x3c074000, + 0x25445880, 0x94830018, 0x94860014, 0x00021082, 0x00021600, 0x00052c00, + 0x00a72825, 0x00451025, 0x00661821, 0x00431025, 0xad020000, 0x9783002c, + 0x974209ea, 0x00621821, 0x00031c00, 0xad030004, 0x9782002c, 0x24420001, + 0x30427fff, 0xa782002c, 0x93430920, 0x3c020006, 0x00031e00, 0x00621825, + 0xad030008, 0x8f42092c, 0xad02000c, 0x8f430930, 0xad030010, 0x8f440938, + 0x25080014, 0xad040000, 0x8f820020, 0x11200004, 0xad020004, 0x8f420940, + 0x0a0010a1, 0x2442ffff, 0x8f420940, 0xad020008, 0x8f440948, 0x8f420940, + 0x93430936, 0x00823023, 0x00663006, 0x3402ffff, 0x0046102b, 0x54400001, + 0x3406ffff, 0x93420937, 0x25445880, 0x90830024, 0xad000010, 0x00021700, + 0x34630010, 0x00031c00, 0x00431025, 0x00461025, 0xad02000c, 0x8c830008, + 0x14600031, 0x25080014, 0x3c020800, 0x8c430048, 0x1060002d, 0x00000000, + 0x9342010b, 0xad020000, 0x8f830000, 0x8c6200b0, 0xad020004, 0x8f830000, + 0x8c6200b4, 0xad020008, 0x8f830000, 0x8c6200c0, 0xad02000c, 0x8f830000, + 0x8c6200c4, 0xad020010, 0x8f830000, 0x8c6200c8, 0xad020014, 0x8f830000, + 0x8c6200cc, 0xad020018, 0x8f830000, 0x8c6200e0, 0xad02001c, 0x8f830000, + 0x8c6200e8, 0xad020020, 0x8f830000, 0x8c6200f0, 0x3c04600e, 0xad020024, + 0x8c8200d0, 0xad020028, 0x8c8300d4, 0xad03002c, 0x8f820028, 0x3c046012, + 0xad020030, 0x8c8200a8, 0xad020034, 0x8c8300ac, 0x3c026000, 0xad030038, + 0x8c434448, 0xad03003c, 0x03e00008, 0x01001021, 0x27bdffa8, 0x3c020008, + 0x03423021, 0xafbf0054, 0xafbe0050, 0xafb7004c, 0xafb60048, 0xafb50044, + 0xafb40040, 0xafb3003c, 0xafb20038, 0xafb10034, 0xafb00030, 0xaf860000, + 0x24020040, 0xaf420814, 0xaf400810, 0x8f420944, 0x8f430950, 0x8f440954, + 0x8f45095c, 0xaf820034, 0xaf830020, 0xaf84001c, 0xaf850030, 0x90c20000, + 0x24030020, 0x304400ff, 0x10830005, 0x24020030, 0x10820022, 0x3c030800, + 0x0a001139, 0x8c62002c, 0x24020088, 0xaf420818, 0x3c020800, 0x244258e8, + 0xafa20020, 0x93430109, 0x3c020800, 0x10600009, 0x24575900, 0x3c026000, + 0x24030100, 0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000, + 0x24000376, 0x9342010a, 0x30420080, 0x14400021, 0x24020800, 0x3c026000, + 0x24030100, 0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000, + 0x2400037d, 0x0a001141, 0x24020800, 0x93430109, 0x3063007f, 0x00031140, + 0x000318c0, 0x00431021, 0x24430088, 0xaf430818, 0x0000000d, 0x3c020800, + 0x24425940, 0x3c030800, 0x24775950, 0x0a001140, 0xafa20020, 0x24420001, + 0xac62002c, 0x0000000d, 0x00000000, 0x24000395, 0x0a0014c1, 0x8fbf0054, + 0x24020800, 0xaf420178, 0x8f450104, 0x8f420988, 0x00a21023, 0x58400005, + 0x8f4309a0, 0x0000000d, 0x00000000, 0x240003b1, 0x8f4309a0, 0x3c100800, + 0xae0358b0, 0x8f4209a4, 0x8f830020, 0x260458b0, 0x2491ffd0, 0xae220034, + 0x00a21023, 0xae230028, 0xac82ffd0, 0x8fa30020, 0x8c620000, 0x0040f809, 0x0200b021, 0x00409021, 0x32440010, 0x32420002, 0x10400007, 0xafa40024, - 0x8e22001c, 0x32500040, 0x2403ffbf, 0x00431024, 0x0a000f13, 0xae22001c, - 0x32420020, 0x10400002, 0x3c020800, 0x245741b0, 0x32420001, 0x14400007, - 0x00000000, 0x8f820008, 0xaf420080, 0x8ec3414c, 0xaf430e10, 0x8e220030, + 0x8e220020, 0x32530040, 0x2403ffbf, 0x00431024, 0x0a001493, 0xae220020, + 0x32420020, 0x10400002, 0x3c020800, 0x24575920, 0x32420001, 0x14400007, + 0x00000000, 0x8f820008, 0xaf420080, 0x8ec358b0, 0xaf430e10, 0x8e220034, 0xaf420e18, 0x9343010b, 0x93420905, 0x30420008, 0x1040003c, 0x307400ff, 0x8f820000, 0x8c430074, 0x0460000a, 0x00000000, 0x3c026000, 0x24030100, - 0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000, 0x24000384, - 0x8f820000, 0x9044007b, 0x9343010a, 0x14830027, 0x32500040, 0x24072000, - 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x8ec2414c, - 0x26c4414c, 0x2484ffd4, 0xaf420144, 0x8c820030, 0x3c030100, 0xaf420148, - 0x24020047, 0xaf43014c, 0x00001821, 0xa3420152, 0x3c021000, 0xa7430158, - 0xaf470154, 0xaf420178, 0x8ec5414c, 0x8d230030, 0x8c860030, 0x24630001, - 0xad230030, 0x93420109, 0x9343010a, 0xafa70014, 0xafa00018, 0x00021600, - 0x00031c00, 0x00431025, 0x34424700, 0xafa20010, 0x8f440100, 0x0e000fe1, - 0x3c070100, 0x3c030800, 0x24624120, 0x0a000d01, 0x8c43001c, 0x32820002, - 0x10400047, 0x3c039000, 0x34630001, 0x8f820008, 0x32500040, 0x3c048000, - 0x00431025, 0xaf420020, 0x8f420020, 0x00441024, 0x1440fffd, 0x00000000, - 0x8f830000, 0x90620005, 0x3c058000, 0x34420008, 0xa0620005, 0x8f860000, - 0x34a50001, 0x8f840008, 0x8cc20074, 0x3c038000, 0x00852025, 0x00431025, - 0xacc20074, 0xaf440020, 0x90c3007b, 0x9342010a, 0x14620028, 0x3c040800, - 0x24072000, 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, - 0x8ec2414c, 0x26c4414c, 0x2484ffd4, 0xaf420144, 0x8c820030, 0x3c030100, - 0xaf420148, 0x24020046, 0xaf43014c, 0x00001821, 0xa3420152, 0x3c021000, - 0xa7430158, 0xaf470154, 0xaf420178, 0x8ec5414c, 0x8d230030, 0x8c860030, - 0x24630001, 0xad230030, 0x93420109, 0x9343010a, 0xafa70014, 0xafa00018, - 0x00021600, 0x00031c00, 0x00431025, 0x34424600, 0xafa20010, 0x8f440100, - 0x0e000fe1, 0x3c070100, 0x3c040800, 0x24824120, 0x0a000d01, 0x8c43001c, - 0x93420108, 0x30420010, 0x50400050, 0x9343093f, 0x8f860000, 0x90c3007f, - 0x90c2007e, 0x90c40080, 0x306800ff, 0x00021600, 0x00081c00, 0x00431025, - 0x00042200, 0x90c3007a, 0x90c5000a, 0x00441025, 0x11050028, 0x00623825, - 0xa0c8000a, 0x24086000, 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, - 0x1440fffd, 0x8ec2414c, 0x26c4414c, 0x2484ffd4, 0xaf420144, 0x8c820030, - 0x00001821, 0xaf420148, 0x24020052, 0xaf47014c, 0xa3420152, 0x3c021000, - 0xa7430158, 0xaf480154, 0xaf420178, 0x8ec5414c, 0x8d230030, 0x8c860030, - 0x24630001, 0xad230030, 0x93420109, 0x9343010a, 0xafa80014, 0xafa00018, - 0x00021600, 0x00031c00, 0x00431025, 0x34425200, 0xafa20010, 0x0e000fe1, - 0x8f440100, 0x0a000cfb, 0x00000000, 0x3c026000, 0x24030100, 0xac43081c, - 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000, 0x240003cd, 0x16800009, - 0x3c040800, 0x3c030800, 0x24624120, 0x8c43001c, 0x32500040, 0x2404ffbf, - 0x00641824, 0x0a000f13, 0xac43001c, 0x8c824120, 0x10400005, 0x3c030800, - 0x8c620034, 0xac804120, 0x24420001, 0xac620034, 0x9343093f, 0x24020012, - 0x1462000f, 0x329e0038, 0x17c0000c, 0x3c030800, 0x8f830000, 0x8c62004c, - 0xac62005c, 0x3c020800, 0x24444120, 0x8c82001c, 0x32500040, 0x2403ffbf, - 0x00431024, 0x0a000f13, 0xac82001c, 0xac604120, 0x97420908, 0x000211c0, + 0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000, 0x240003ed, + 0x8f820000, 0x9044007b, 0x9343010a, 0x14830027, 0x32530040, 0x00003821, + 0x24052000, 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, + 0x8ec258b0, 0x26c458b0, 0x2484ffd0, 0xaf420144, 0x8c820034, 0x3c030100, + 0xaf420148, 0x24020047, 0xaf43014c, 0xa3420152, 0x8d230030, 0x3c021000, + 0xa7470158, 0xaf450154, 0xaf420178, 0x8c860034, 0x24630001, 0xad230030, + 0x9342010a, 0x3c030047, 0xafa50014, 0x00021600, 0x00431025, 0x00471025, + 0xafa20010, 0x9343010b, 0xafa30018, 0x8f440100, 0x8f450104, 0x0e00159b, + 0x3c070100, 0x3c050800, 0x24a25880, 0x0a001250, 0x8c430020, 0x32820002, + 0x10400050, 0x00000000, 0x0e0015b9, 0x32530040, 0x3c039000, 0x34630001, + 0x8f820008, 0x3c048000, 0x00431025, 0xaf420020, 0x8f420020, 0x00441024, + 0x1440fffd, 0x00000000, 0x8f830000, 0x90620005, 0x34420008, 0xa0620005, + 0x8f840000, 0x8c820074, 0x3c038000, 0x00431025, 0xac820074, 0x90830000, + 0x24020020, 0x10620004, 0x00000000, 0x0000000d, 0x00000000, 0x2400040b, + 0x8f830008, 0x3c028000, 0x34420001, 0x00621825, 0xaf430020, 0x9084007b, + 0x9342010a, 0x14820028, 0x3c030800, 0x00003821, 0x24052000, 0x3c090800, + 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x8ec258b0, 0x26c458b0, + 0x2484ffd0, 0xaf420144, 0x8c820034, 0x3c030100, 0xaf420148, 0x24020046, + 0xaf43014c, 0xa3420152, 0x8d230030, 0x3c021000, 0xa7470158, 0xaf450154, + 0xaf420178, 0x8c860034, 0x24630001, 0xad230030, 0x9342010a, 0x3c030046, + 0xafa50014, 0x00021600, 0x00431025, 0x00471025, 0xafa20010, 0x9343010b, + 0xafa30018, 0x8f440100, 0x8f450104, 0x0e00159b, 0x3c070100, 0x3c030800, + 0x24625880, 0x0a001250, 0x8c430020, 0x93420108, 0x30420010, 0x50400056, + 0x9343093f, 0x8f860000, 0x90c2007f, 0x8cc30178, 0x304800ff, 0x15030004, + 0x00000000, 0x0000000d, 0x00000000, 0x24000425, 0x90c2007e, 0x90c40080, + 0x00081c00, 0x00021600, 0x00431025, 0x00042200, 0x90c3007a, 0x90c5000a, + 0x00441025, 0x11050028, 0x00623825, 0xa0c8000a, 0x00004021, 0x24056000, + 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x8ec258b0, + 0x26c458b0, 0x2484ffd0, 0xaf420144, 0x8c820034, 0xaf420148, 0x24020052, + 0xaf47014c, 0xa3420152, 0x8d230030, 0x3c021000, 0xa7480158, 0xaf450154, + 0xaf420178, 0x8c860034, 0x24630001, 0xad230030, 0x9342010a, 0x3c030052, + 0xafa50014, 0x00021600, 0x00431025, 0x00481025, 0xafa20010, 0x9343010b, + 0xafa30018, 0x8f440100, 0x0e00159b, 0x8f450104, 0x0a00124a, 0x00000000, + 0x3c026000, 0x24030100, 0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d, + 0x00000000, 0x2400043e, 0x16800009, 0x3c050800, 0x3c040800, 0x24825880, + 0x8c430020, 0x32530040, 0x2404ffbf, 0x00641824, 0x0a001493, 0xac430020, + 0x8ca25880, 0x10400005, 0x3c030800, 0x8c620034, 0xaca05880, 0x24420001, + 0xac620034, 0x9343093f, 0x24020012, 0x5462000e, 0x97420908, 0x32820038, + 0x14400009, 0x3c030800, 0x8f830000, 0x8c62004c, 0xac62005c, 0x3c020800, + 0x24445880, 0x8c820020, 0x0a001285, 0x32530040, 0xac605880, 0x97420908, + 0x5440001c, 0x97420908, 0x3c039000, 0x34630001, 0x8f820008, 0x32530040, + 0x3c048000, 0x00431025, 0xaf420020, 0x8f420020, 0x00441024, 0x1440fffd, + 0x3c028000, 0x8f840000, 0x8f850008, 0x8c830050, 0x34420001, 0x00a22825, + 0xaf830020, 0xac830070, 0xac83005c, 0xaf450020, 0x3c050800, 0x24a45880, + 0x8c820020, 0x2403ffbf, 0x00431024, 0x0a001493, 0xac820020, 0x000211c0, 0xaf420024, 0x97420908, 0x3c030080, 0x34630003, 0x000211c0, 0xaf42080c, - 0xaf43081c, 0x974209ec, 0x8f4309a4, 0xa7820028, 0x3c020800, 0x24444120, - 0xac830028, 0x93420937, 0x93430934, 0x00021080, 0x00621821, 0xa4830014, - 0x934209d8, 0x00621821, 0xa4830016, 0x934209d8, 0x93430934, 0x00809821, - 0x00431021, 0x24420010, 0xa4820012, 0x0000a821, 0x24020006, 0x13c00003, - 0xae62001c, 0x0a000d82, 0x24120008, 0x8f420958, 0x8f830020, 0x8f84002c, - 0x00431023, 0x00832023, 0x04800003, 0xae620004, 0x04410003, 0x0082102b, - 0x0a000d4e, 0xae600004, 0x54400001, 0xae640004, 0x8ee20000, 0x0040f809, - 0x00000000, 0x00409021, 0x32420001, 0x5440001e, 0x8ee20004, 0x8e630008, - 0x1060002b, 0x3c02c000, 0x00621025, 0xaf420e00, 0x8f420000, 0x30420008, - 0x1040fffd, 0x00000000, 0x97420e08, 0xa7820010, 0x8f430e04, 0x8e620008, - 0xaf830004, 0x8f840004, 0x0044102b, 0x1040000b, 0x24150001, 0x24020100, - 0x3c016000, 0xac22081c, 0x3c020001, 0x3c016000, 0xac22081c, 0x0000000d, - 0x00000000, 0x24000449, 0x24150001, 0x8ee20004, 0x0040f809, 0x00000000, - 0x02429025, 0x32420002, 0x5040001d, 0x8f470940, 0x12a00006, 0x8ec2414c, - 0x8f830000, 0xac6200a8, 0x8f840000, 0x8e620030, 0xac8200ac, 0x32420004, - 0x50400013, 0x8f470940, 0x3c020800, 0x3283007d, 0x106000fe, 0x245741b0, - 0x32820001, 0x50400006, 0x36520002, 0x8f830030, 0x8f420940, 0x106200f7, - 0x00000000, 0x36520002, 0x24020008, 0xa660000c, 0xa662000e, 0xae600008, - 0xa2600020, 0x8f470940, 0x3c030800, 0x24684120, 0x8d020028, 0x8d050008, - 0x9504000c, 0x9506000a, 0x95030022, 0x00451021, 0x00862021, 0x00641821, - 0xaf870030, 0xad020028, 0x32820030, 0x10400006, 0xa5030010, 0x91020020, - 0x32910040, 0x34420004, 0x0a000dd4, 0xa1020020, 0x93420923, 0x30420040, + 0xaf43081c, 0x974209ec, 0x8f4309a4, 0xa782002c, 0x3c020800, 0x24445880, + 0xac83002c, 0x93420937, 0x93430934, 0x00021080, 0x00621821, 0xa4830018, + 0x934209d8, 0x32850038, 0xafa50028, 0x00621821, 0xa483001a, 0x934209d8, + 0x93430934, 0x3c1e0800, 0x00809821, 0x00431021, 0x24420010, 0xa4820016, + 0x24020006, 0xae620020, 0x8fa20028, 0x10400003, 0x0000a821, 0x0a0012f0, + 0x24120008, 0x8f420958, 0x8f830020, 0x8f840030, 0x00431023, 0x00832023, + 0x04800003, 0xae620004, 0x04410003, 0x0082102b, 0x0a0012bc, 0xae600004, + 0x54400001, 0xae640004, 0x8ee20000, 0x0040f809, 0x00000000, 0x00409021, + 0x32420001, 0x5440001e, 0x8ee20004, 0x8e630008, 0x1060002b, 0x3c02c000, + 0x00621025, 0xaf420e00, 0x8f420000, 0x30420008, 0x1040fffd, 0x00000000, + 0x97420e08, 0xa7820010, 0x8f430e04, 0x8e620008, 0xaf830004, 0x8f840004, + 0x0044102b, 0x1040000b, 0x24150001, 0x24020100, 0x3c016000, 0xac22081c, + 0x3c020001, 0x3c016000, 0xac22081c, 0x0000000d, 0x00000000, 0x240004cd, + 0x24150001, 0x8ee20004, 0x0040f809, 0x00000000, 0x02429025, 0x32420002, + 0x5040001d, 0x8f470940, 0x12a00006, 0x8ec258b0, 0x8f830000, 0xac6200a8, + 0x8f840000, 0x8e620034, 0xac8200ac, 0x32420004, 0x50400013, 0x8f470940, + 0x3c020800, 0x3283007d, 0x10600110, 0x24575920, 0x32820001, 0x50400006, + 0x36520002, 0x8f830034, 0x8f420940, 0x10620109, 0x00000000, 0x36520002, + 0x24020008, 0xa6600010, 0xa6620012, 0xae600008, 0xa2600024, 0x8f470940, + 0x3c030800, 0x24685880, 0x8d02002c, 0x8d050008, 0x95040010, 0x9506000a, + 0x95030026, 0x00451021, 0x00862021, 0x00641821, 0xaf870034, 0xad02002c, + 0x32820030, 0x10400008, 0xa5030014, 0x91020024, 0x32910040, 0x34420004, + 0xa1020024, 0xaf400048, 0x0a001345, 0x3c040800, 0x93420923, 0x30420002, 0x10400029, 0x32910040, 0x8f830000, 0x8f840020, 0x8c620084, 0x00441023, - 0x0442000a, 0x3c039000, 0x95020010, 0x8c630084, 0x00821021, 0x00621823, - 0x1c600004, 0x3c039000, 0x91020020, 0x34420001, 0xa1020020, 0x34630001, + 0x0442000a, 0x3c039000, 0x95020014, 0x8c630084, 0x00821021, 0x00621823, + 0x1c600004, 0x3c039000, 0x91020024, 0x34420001, 0xa1020024, 0x34630001, 0x8f820008, 0x32910040, 0x3c048000, 0x00431025, 0xaf420020, 0x8f420020, 0x00441024, 0x1440fffd, 0x00000000, 0x8f840000, 0x9083003f, 0x2402000a, 0x10620005, 0x2402000c, 0x9083003f, 0x24020008, 0x14620002, 0x24020014, 0xa082003f, 0x8f830008, 0x3c028000, 0x34420001, 0x00621825, 0xaf430020, - 0x3c040800, 0x24904120, 0x9602000c, 0x96030016, 0x9604000e, 0x00431021, - 0x00442021, 0x24840002, 0x3084ffff, 0x0e000a55, 0xa6020018, 0x8f850018, - 0x00a01821, 0xa2030021, 0x8ee60008, 0x00402021, 0x24a50001, 0xaf850018, - 0x00c0f809, 0x00000000, 0x00402021, 0x0e000b12, 0x02202821, 0x8ee3000c, - 0x0060f809, 0x00402021, 0x96040018, 0x9602000e, 0x00822021, 0x24840002, - 0x0e000a6b, 0x3084ffff, 0x3c030800, 0x8c624120, 0x8e030008, 0x3c040800, - 0x00431023, 0x14400012, 0xac824120, 0x54600006, 0x8e02001c, 0x3243004a, - 0x24020002, 0x14620005, 0x00000000, 0x8e02001c, 0x34420040, 0x0a000e0b, - 0xae02001c, 0x52a00006, 0x36520002, 0x8e02002c, 0xaf420e10, 0x8e030030, - 0xaf430e18, 0x36520002, 0x52a00008, 0x96670010, 0x8f830000, 0x8f420e10, - 0xac6200a8, 0x8f840000, 0x8f420e18, 0xac8200ac, 0x96670010, 0x92680020, - 0x24020040, 0xaf420814, 0x8f830020, 0x8f82001c, 0x00671821, 0x00621023, - 0xaf830020, 0x58400005, 0x8f42095c, 0x8f820000, 0xaf83001c, 0xac430054, - 0x8f42095c, 0x31030008, 0xaf82002c, 0x1060001a, 0x00000000, 0x8f840000, - 0x90820120, 0x90830121, 0x304600ff, 0x00c31823, 0x30630007, 0x24020007, - 0x1062000e, 0x00000000, 0x90820122, 0x304200fe, 0xa0820122, 0x8f850000, - 0x00061880, 0x8f840020, 0x24a20100, 0x00431021, 0x24c30001, 0x30630007, - 0xac440000, 0x0a000e40, 0xa0a30120, 0x90820122, 0x34420001, 0xa0820122, - 0x14e00003, 0x31020001, 0x10400031, 0x32510002, 0x8f820000, 0x8c43000c, - 0x30630001, 0x1060002c, 0x32510002, 0x3c029000, 0x8f830008, 0x34420001, - 0x3c048000, 0x00621825, 0xaf430020, 0x8f420020, 0x00441024, 0x1440fffd, - 0x00000000, 0x8f870000, 0x8ce2000c, 0x30420001, 0x10400018, 0x00000000, - 0x94e2006a, 0x00022880, 0x50a00001, 0x24050001, 0x94e30068, 0x90e40081, - 0x3c020800, 0x8c460024, 0x00652821, 0x00852804, 0x00c5102b, 0x54400001, - 0x00a03021, 0x3c020800, 0x8c440028, 0x00c4182b, 0x54600001, 0x00c02021, - 0x8f430074, 0x2402fffe, 0x00822824, 0x00a31821, 0xace3000c, 0x8f830008, - 0x3c028000, 0x34420001, 0x00621825, 0xaf430020, 0x8f830020, 0x3c020800, - 0x24504120, 0xae030024, 0x8ee20010, 0x0040f809, 0x00000000, 0x12a00005, - 0x00000000, 0x8f420e10, 0xae02002c, 0x8f430e18, 0xae030030, 0x1220feba, - 0x0000a821, 0x8f870024, 0x97860028, 0x8f830000, 0x8f820030, 0x8f840020, - 0x8f85001c, 0x32500040, 0xa4e6002c, 0xac620044, 0x32420008, 0xac640050, - 0xac650054, 0x1040007a, 0x32820020, 0x10400027, 0x32910010, 0x24072000, - 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x8ec2414c, - 0x26c4414c, 0x2484ffd4, 0xaf420144, 0x8c820030, 0x3c030400, 0xaf420148, - 0x24020041, 0xaf43014c, 0x00001821, 0xa3420152, 0x3c021000, 0xa7430158, - 0xaf470154, 0xaf420178, 0x8ec5414c, 0x8d230030, 0x8c860030, 0x24630001, - 0xad230030, 0x93420109, 0x9343010a, 0xafa70014, 0xafa00018, 0x00021600, - 0x00031c00, 0x00431025, 0x34424100, 0xafa20010, 0x8f440100, 0x0e000fe1, - 0x3c070400, 0x12200028, 0x24072000, 0x3c090800, 0x3c038000, 0x8f420178, - 0x00431024, 0x1440fffd, 0x8ec2414c, 0x26c4414c, 0x2484ffd4, 0xaf420144, - 0x8c820030, 0x3c030300, 0xaf420148, 0x2402004e, 0xaf43014c, 0x00001821, - 0xa3420152, 0x3c021000, 0xa7430158, 0xaf470154, 0xaf420178, 0x8ec5414c, - 0x8d230030, 0x8c860030, 0x24630001, 0xad230030, 0x93420109, 0x9343010a, - 0xafa70014, 0xafa00018, 0x00021600, 0x00031c00, 0x00431025, 0x34424e00, - 0xafa20010, 0x8f440100, 0x0e000fe1, 0x3c070300, 0x0a000f0b, 0x8fa30024, - 0x32820008, 0x10400026, 0x3c090800, 0x24072000, 0x3c038000, 0x8f420178, - 0x00431024, 0x1440fffd, 0x8ec2414c, 0x26c4414c, 0x2484ffd4, 0xaf420144, - 0x8c820030, 0x3c030200, 0xaf420148, 0x2402004b, 0xaf43014c, 0x00001821, - 0xa3420152, 0x3c021000, 0xa7430158, 0xaf470154, 0xaf420178, 0x8ec5414c, - 0x8d230030, 0x8c860030, 0x24630001, 0xad230030, 0x93420109, 0x9343010a, - 0xafa70014, 0xafa00018, 0x00021600, 0x00031c00, 0x00431025, 0x34424b00, - 0xafa20010, 0x8f440100, 0x0e000fe1, 0x3c070200, 0x8fa30024, 0x14600004, - 0x8fa40020, 0x32420010, 0x10400004, 0x00000000, 0x8c820004, 0x0040f809, - 0x00000000, 0x12000006, 0x8fa30020, 0x8c620008, 0x0040f809, 0x00000000, - 0x0a000f4d, 0x8fbf004c, 0x3c030800, 0x8c62413c, 0x30420040, 0x1440002f, - 0x8fbf004c, 0x24040040, 0x8f910020, 0x3c038000, 0x8f420178, 0x00431024, - 0x1440fffd, 0x8ec2414c, 0x26d0414c, 0x2610ffd4, 0xaf420144, 0x8e020030, - 0x00001821, 0xaf420148, 0x24020049, 0xaf51014c, 0xa3420152, 0x3c021000, - 0xa7430158, 0xaf440154, 0xaf420178, 0x8ec5414c, 0x8e060030, 0x93420109, - 0x9343010a, 0xafa40014, 0xafa00018, 0x00021600, 0x00031c00, 0x00431025, - 0x34424900, 0xafa20010, 0x8f440100, 0x0e000fe1, 0x02203821, 0x8f830000, - 0x8e020030, 0x8c64017c, 0x02221023, 0x00441023, 0x2c420002, 0x14400005, - 0x8fbf004c, 0x0000000d, 0x00000000, 0x240000ca, 0x8fbf004c, 0x8fbe0048, - 0x8fb70044, 0x8fb60040, 0x8fb5003c, 0x8fb40038, 0x8fb30034, 0x8fb20030, - 0x8fb1002c, 0x8fb00028, 0x03e00008, 0x27bd0050, 0x03e00008, 0x00001021, - 0x3c030800, 0x24654120, 0x8ca40004, 0x8c634120, 0x0064102b, 0x54400001, - 0x00602021, 0x9743093c, 0x0083102b, 0x54400001, 0x00801821, 0x00001021, - 0xaca30008, 0x03e00008, 0xa4a00022, 0x8f850004, 0x97840010, 0x3c030800, - 0x24634120, 0x24020008, 0xa462000e, 0x8f820004, 0xa460000c, 0x000420c2, + 0x3c040800, 0x24865880, 0x94c20010, 0x94c3001a, 0x8cc40008, 0x00432821, + 0x14800006, 0xa4c5001c, 0x3c020800, 0x8c430048, 0x10600002, 0x24a20040, + 0xa4c2001c, 0x27d05880, 0x9604001c, 0x96020012, 0x00822021, 0x24840002, + 0x0e000faf, 0x3084ffff, 0x8f850018, 0x00a01821, 0xa2030025, 0x8ee60008, + 0x00402021, 0x24a50001, 0xaf850018, 0x00c0f809, 0x00000000, 0x00402021, + 0x0e001026, 0x02202821, 0x8ee3000c, 0x0060f809, 0x00402021, 0x9604001c, + 0x96020012, 0x00822021, 0x24840002, 0x0e000fc5, 0x3084ffff, 0x8fc25880, + 0x8e030008, 0x00431023, 0x14400012, 0xafc25880, 0x54600006, 0x8e020020, + 0x3243004a, 0x24020002, 0x14620005, 0x00000000, 0x8e020020, 0x34420040, + 0x0a001382, 0xae020020, 0x52a00006, 0x36520002, 0x8e020030, 0xaf420e10, + 0x8e030034, 0xaf430e18, 0x36520002, 0x52a00008, 0x96670014, 0x8f830000, + 0x8f420e10, 0xac6200a8, 0x8f840000, 0x8f420e18, 0xac8200ac, 0x96670014, + 0x92680024, 0x24020040, 0xaf420814, 0x8f830020, 0x8f82001c, 0x00671821, + 0x00621023, 0xaf830020, 0x18400008, 0x00000000, 0x8f820000, 0xaf83001c, + 0xac430054, 0x54e00005, 0xaf400040, 0x0a0013a0, 0x8f42095c, 0x54e00001, + 0xaf400044, 0x8f42095c, 0x31030008, 0xaf820030, 0x1060001a, 0x00000000, + 0x8f840000, 0x90820120, 0x90830121, 0x304600ff, 0x00c31823, 0x30630007, + 0x24020007, 0x1062000e, 0x00000000, 0x90820122, 0x304200fe, 0xa0820122, + 0x8f850000, 0x00061880, 0x8f840020, 0x24a20100, 0x00431021, 0x24c30001, + 0x30630007, 0xac440000, 0x0a0013bd, 0xa0a30120, 0x90820122, 0x34420001, + 0xa0820122, 0x14e00003, 0x31020001, 0x10400031, 0x32510002, 0x8f820000, + 0x8c43000c, 0x30630001, 0x1060002c, 0x32510002, 0x3c029000, 0x8f830008, + 0x34420001, 0x3c048000, 0x00621825, 0xaf430020, 0x8f420020, 0x00441024, + 0x1440fffd, 0x00000000, 0x8f870000, 0x8ce2000c, 0x30420001, 0x10400018, + 0x00000000, 0x94e2006a, 0x00022880, 0x50a00001, 0x24050001, 0x94e30068, + 0x90e40081, 0x3c020800, 0x8c460024, 0x00652821, 0x00852804, 0x00c5102b, + 0x54400001, 0x00a03021, 0x3c020800, 0x8c440028, 0x00c4182b, 0x54600001, + 0x00c02021, 0x8f430074, 0x2402fffe, 0x00822824, 0x00a31821, 0xace3000c, + 0x8f830008, 0x3c028000, 0x34420001, 0x00621825, 0xaf430020, 0x8f820020, + 0x3c050800, 0x24b05880, 0xae020028, 0x8ee30010, 0x0060f809, 0x00000000, + 0x8f820028, 0x24420001, 0xaf820028, 0x12a00005, 0xaf40004c, 0x8f420e10, + 0xae020030, 0x8f430e18, 0xae030034, 0x1220fea7, 0x24020006, 0x8f870024, + 0x9786002c, 0x8f830000, 0x8f820034, 0x8f840020, 0x8f85001c, 0x32530040, + 0xa4e6002c, 0xac620044, 0x32420008, 0xac640050, 0xac650054, 0x1040007a, + 0x32820020, 0x10400027, 0x32910010, 0x00003821, 0x24052000, 0x3c090800, + 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x8ec258b0, 0x26c458b0, + 0x2484ffd0, 0xaf420144, 0x8c820034, 0x3c030400, 0xaf420148, 0x24020041, + 0xaf43014c, 0xa3420152, 0x8d230030, 0x3c021000, 0xa7470158, 0xaf450154, + 0xaf420178, 0x8c860034, 0x24630001, 0xad230030, 0x9342010a, 0x3c030041, + 0xafa50014, 0x00021600, 0x00431025, 0x00471025, 0xafa20010, 0x9343010b, + 0xafa30018, 0x8f440100, 0x8f450104, 0x0e00159b, 0x3c070400, 0x12200028, + 0x00003821, 0x24052000, 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, + 0x1440fffd, 0x8ec258b0, 0x26c458b0, 0x2484ffd0, 0xaf420144, 0x8c820034, + 0x3c030300, 0xaf420148, 0x2402004e, 0xaf43014c, 0xa3420152, 0x8d230030, + 0x3c021000, 0xa7470158, 0xaf450154, 0xaf420178, 0x8c860034, 0x24630001, + 0xad230030, 0x9342010a, 0x3c03004e, 0xafa50014, 0x00021600, 0x00431025, + 0x00471025, 0xafa20010, 0x9343010b, 0xafa30018, 0x8f440100, 0x8f450104, + 0x0e00159b, 0x3c070300, 0x0a00148b, 0x8fa20024, 0x32820008, 0x10400026, + 0x24052000, 0x00003821, 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, + 0x1440fffd, 0x8ec258b0, 0x26c458b0, 0x2484ffd0, 0xaf420144, 0x8c820034, + 0x3c030200, 0xaf420148, 0x2402004b, 0xaf43014c, 0xa3420152, 0x8d230030, + 0x3c021000, 0xa7470158, 0xaf450154, 0xaf420178, 0x8c860034, 0x24630001, + 0xad230030, 0x9342010a, 0x3c03004b, 0xafa50014, 0x00021600, 0x00431025, + 0x00471025, 0xafa20010, 0x9343010b, 0xafa30018, 0x8f440100, 0x8f450104, + 0x0e00159b, 0x3c070200, 0x8fa20024, 0x14400004, 0x8fa30020, 0x32420010, + 0x10400004, 0x00000000, 0x8c620004, 0x0040f809, 0x00000000, 0x12600006, + 0x8fa40020, 0x8c820008, 0x0040f809, 0x00000000, 0x0a0014c1, 0x8fbf0054, + 0x3c030800, 0x8c6258a0, 0x30420040, 0x14400023, 0x8fbf0054, 0x00002821, + 0x24040040, 0x8f870020, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, + 0x8ec258b0, 0x26c358b0, 0x2463ffd0, 0xaf420144, 0x8c620034, 0xaf420148, + 0x24020049, 0xaf47014c, 0xa3420152, 0x3c021000, 0xa7450158, 0xaf440154, + 0xaf420178, 0x8c660034, 0x9342010a, 0x3c030049, 0xafa40014, 0x00021600, + 0x00431025, 0x00451025, 0xafa20010, 0x9343010b, 0xafa30018, 0x8f440100, + 0x0e00159b, 0x8f450104, 0x8fbf0054, 0x8fbe0050, 0x8fb7004c, 0x8fb60048, + 0x8fb50044, 0x8fb40040, 0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030, + 0x03e00008, 0x27bd0058, 0x03e00008, 0x00001021, 0x3c020800, 0x24435880, + 0x8c650004, 0x8c445880, 0x0085182b, 0x10600002, 0x00403021, 0x00802821, + 0x9744093c, 0x00a4102b, 0x54400001, 0x00a02021, 0x93420923, 0x0004182b, + 0x00021042, 0x30420001, 0x00431024, 0x1040000d, 0x24c25880, 0x8f850000, + 0x8f830020, 0x8ca20084, 0x00431023, 0x04420007, 0x24c25880, 0x8ca20084, + 0x00641821, 0x00431023, 0x28420001, 0x00822023, 0x24c25880, 0xac440008, + 0xa4400026, 0x03e00008, 0x00001021, 0x8f850004, 0x97840010, 0x3c030800, + 0x24635880, 0x24020008, 0xa4620012, 0x8f820004, 0xa4600010, 0x000420c2, 0x30840008, 0x2c420001, 0x00021023, 0x30420006, 0xac650008, 0x03e00008, - 0xa0640020, 0x3c020800, 0x24424120, 0x90450021, 0x94430018, 0x3c021100, + 0xa0640024, 0x3c020800, 0x24425880, 0x90450025, 0x9443001c, 0x3c021100, 0xac800004, 0x00052c00, 0x24630002, 0x00621825, 0x00a32825, 0x24820008, - 0x03e00008, 0xac850000, 0x0000000d, 0x00000000, 0x2400016f, 0x03e00008, - 0x00000000, 0x0000000d, 0x00000000, 0x2400017b, 0x03e00008, 0x00000000, - 0x03e00008, 0x00000000, 0x3c020800, 0x24424120, 0xac400008, 0xa4400022, - 0x03e00008, 0x24020001, 0x3c020800, 0x24424120, 0x24030008, 0xac400008, - 0xa440000c, 0xa443000e, 0xa0400020, 0x03e00008, 0x24020004, 0x03e00008, + 0x03e00008, 0xac850000, 0x27bdffd8, 0x3c020800, 0x24425880, 0xafbf0020, + 0x90480025, 0x8c440008, 0x8c460020, 0x8f870020, 0x3c030800, 0x3c058000, + 0x8f420178, 0x00451024, 0x1440fffd, 0x8c6258b0, 0x246358b0, 0x2469ffd0, + 0xaf420144, 0x8d220034, 0x30c32000, 0xaf420148, 0x3c021000, 0xaf47014c, + 0xa3480152, 0xa7440158, 0xaf460154, 0xaf420178, 0x10600004, 0x3c030800, + 0x8c620030, 0x24420001, 0xac620030, 0x9342010a, 0x00081c00, 0x3084ffff, + 0xafa60014, 0x00021600, 0x00431025, 0x00441025, 0xafa20010, 0x9343010b, + 0xafa30018, 0x8f440100, 0x8f450104, 0x0e00159b, 0x8d260034, 0x8fbf0020, + 0x03e00008, 0x27bd0028, 0x0000000d, 0x00000000, 0x2400019d, 0x03e00008, + 0x00000000, 0x0000000d, 0x00000000, 0x240001a9, 0x03e00008, 0x00000000, + 0x03e00008, 0x00000000, 0x3c020800, 0x24425880, 0xac400008, 0xa4400026, + 0x03e00008, 0x24020001, 0x3c020800, 0x24425880, 0x24030008, 0xac400008, + 0xa4400010, 0xa4430012, 0xa0400024, 0x03e00008, 0x24020004, 0x03e00008, 0x00001021, 0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, - 0xac820000, 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, 0x0a000fb2, - 0x00a01021, 0xac860000, 0x24840004, 0x00a01021, 0x1440fffc, 0x24a5ffff, - 0x03e00008, 0x00000000, 0x3c0a0800, 0x8d490068, 0x3c050800, 0x24a51090, - 0x00093140, 0x00c51021, 0xac440000, 0x8f440e04, 0x00a61021, 0xac440004, - 0x97430e08, 0x97420e0c, 0x00a62021, 0x00031c00, 0x00431025, 0xac820008, - 0x8f430e10, 0x00801021, 0xac43000c, 0x8f440e14, 0xac440010, 0x8f430e18, - 0x3c0800ff, 0xac430014, 0x8f470e1c, 0x3508ffff, 0x25290001, 0xac470018, - 0x3c070800, 0x8ce3006c, 0x9344010a, 0x3c026000, 0x24630001, 0xace3006c, - 0x8c434448, 0x3129007f, 0x00a62821, 0xad490068, 0x00042600, 0x00681824, - 0x00832025, 0x03e00008, 0xaca4001c, 0x8fac0010, 0x8fad0014, 0x8fae0018, - 0x3c0b0800, 0x8d6a0060, 0x3c080800, 0x25080078, 0x000a4940, 0x01281021, - 0x01091821, 0xac440000, 0x00601021, 0xac650004, 0xac460008, 0xac67000c, - 0xac4c0010, 0xac6d0014, 0x3c036000, 0xac4e0018, 0x8c654448, 0x3c040800, - 0x8c820064, 0x254a0001, 0x314a007f, 0x01094021, 0xad6a0060, 0x24420001, - 0xac820064, 0x03e00008, 0xad05001c, 0x00000000 }; - -static u32 bnx2_TXP_b06FwData[(0x0/4) + 1] = { 0x00000000 }; -static u32 bnx2_TXP_b06FwRodata[(0x0/4) + 1] = { 0x00000000 }; -static u32 bnx2_TXP_b06FwBss[(0x194/4) + 1] = { 0x00000000 }; -static u32 bnx2_TXP_b06FwSbss[(0x34/4) + 1] = { 0x00000000 }; + 0xac820000, 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, 0x0a00156c, + 0x00a01021, 0xac860000, 0x00000000, 0x00000000, 0x24840004, 0x00a01021, + 0x1440fffa, 0x24a5ffff, 0x03e00008, 0x00000000, 0x3c0a0800, 0x8d490068, + 0x3c050800, 0x24a52098, 0x00093140, 0x00c51021, 0xac440000, 0x8f440e04, + 0x00a61021, 0xac440004, 0x97430e08, 0x97420e0c, 0x00a62021, 0x00031c00, + 0x00431025, 0xac820008, 0x8f430e10, 0x00801021, 0xac43000c, 0x8f440e14, + 0xac440010, 0x8f430e18, 0x3c0800ff, 0xac430014, 0x8f470e1c, 0x3508ffff, + 0x25290001, 0xac470018, 0x3c070800, 0x8ce3006c, 0x9344010a, 0x3c026000, + 0x24630001, 0xace3006c, 0x8c434448, 0x3129007f, 0x00a62821, 0xad490068, + 0x00042600, 0x00681824, 0x00832025, 0x03e00008, 0xaca4001c, 0x8fac0010, + 0x8fad0014, 0x8fae0018, 0x3c0b0800, 0x8d6a0060, 0x3c080800, 0x25080080, + 0x000a4940, 0x01281021, 0x01091821, 0xac440000, 0x00601021, 0xac650004, + 0xac460008, 0xac67000c, 0xac4c0010, 0xac6d0014, 0x3c036000, 0xac4e0018, + 0x8c654448, 0x3c040800, 0x8c820064, 0x254a0001, 0x314a00ff, 0x01094021, + 0xad6a0060, 0x24420001, 0xac820064, 0x03e00008, 0xad05001c, 0x3c030800, + 0x3c090800, 0x8d250070, 0x246330b0, 0x8f460100, 0x00053900, 0x00e31021, + 0xac460000, 0x8f440104, 0x00671021, 0xac440004, 0x8f460108, 0x8f840014, + 0x24a50001, 0xac460008, 0x8c880074, 0x3c060800, 0x8cc20074, 0x30a5003f, + 0x00671821, 0xad250070, 0x24420001, 0xacc20074, 0x03e00008, 0xac68000c, + 0x00000000 }; +static u32 bnx2_TXP_b06FwData[(0x0/4) + 1] = { 0x0 }; +static u32 bnx2_TXP_b06FwRodata[(0x0/4) + 1] = { 0x0 }; +static u32 bnx2_TXP_b06FwBss[(0x1c4/4) + 1] = { 0x0 }; +static u32 bnx2_TXP_b06FwSbss[(0x38/4) + 1] = { 0x0 }; -- cgit v1.2.3 From 371377091dff14090cbe995d0a9291364f8583cb Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 4 Nov 2005 08:49:17 -0800 Subject: [PATCH] bnx2: update nvram code for 5708 Update bnx2 nvram code with support for 5708. Signed-off-by: Michael Chan Signed-off-by: John W. Linville --- drivers/net/bnx2.c | 100 +++++++++++++++++++++++++++++++++++++++++------------ drivers/net/bnx2.h | 10 +++++- 2 files changed, 87 insertions(+), 23 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 671393a1846..08086a9e541 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -79,38 +79,88 @@ static struct pci_device_id bnx2_pci_tbl[] = { static struct flash_spec flash_table[] = { /* Slow EEPROM */ - {0x00000000, 0x40030380, 0x009f0081, 0xa184a053, 0xaf000400, + {0x00000000, 0x40830380, 0x009f0081, 0xa184a053, 0xaf000400, 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE, SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE, "EEPROM - slow"}, - /* Fast EEPROM */ - {0x02000000, 0x62008380, 0x009f0081, 0xa184a053, 0xaf000400, - 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE, - SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE, - "EEPROM - fast"}, - /* ATMEL AT45DB011B (buffered flash) */ - {0x02000003, 0x6e008173, 0x00570081, 0x68848353, 0xaf000400, - 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, - BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE, - "Buffered flash"}, - /* Saifun SA25F005 (non-buffered flash) */ - /* strap, cfg1, & write1 need updates */ - {0x01000003, 0x5f008081, 0x00050081, 0x03840253, 0xaf020406, + /* Expansion entry 0001 */ + {0x08000002, 0x4b808201, 0x00050081, 0x03840253, 0xaf020406, 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, - SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE, - "Non-buffered flash (64kB)"}, + SAIFUN_FLASH_BYTE_ADDR_MASK, 0, + "Entry 0001"}, /* Saifun SA25F010 (non-buffered flash) */ /* strap, cfg1, & write1 need updates */ - {0x00000001, 0x47008081, 0x00050081, 0x03840253, 0xaf020406, + {0x04000001, 0x47808201, 0x00050081, 0x03840253, 0xaf020406, 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*2, "Non-buffered flash (128kB)"}, /* Saifun SA25F020 (non-buffered flash) */ /* strap, cfg1, & write1 need updates */ - {0x00000003, 0x4f008081, 0x00050081, 0x03840253, 0xaf020406, + {0x0c000003, 0x4f808201, 0x00050081, 0x03840253, 0xaf020406, 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*4, "Non-buffered flash (256kB)"}, + /* Expansion entry 0100 */ + {0x11000000, 0x53808201, 0x00050081, 0x03840253, 0xaf020406, + 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, + SAIFUN_FLASH_BYTE_ADDR_MASK, 0, + "Entry 0100"}, + /* Entry 0101: ST M45PE10 (non-buffered flash, TetonII B0) */ + {0x19000002, 0x5b808201, 0x000500db, 0x03840253, 0xaf020406, + 0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE, + ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*2, + "Entry 0101: ST M45PE10 (128kB non-bufferred)"}, + /* Entry 0110: ST M45PE20 (non-buffered flash)*/ + {0x15000001, 0x57808201, 0x000500db, 0x03840253, 0xaf020406, + 0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE, + ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*4, + "Entry 0110: ST M45PE20 (256kB non-bufferred)"}, + /* Saifun SA25F005 (non-buffered flash) */ + /* strap, cfg1, & write1 need updates */ + {0x1d000003, 0x5f808201, 0x00050081, 0x03840253, 0xaf020406, + 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, + SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE, + "Non-buffered flash (64kB)"}, + /* Fast EEPROM */ + {0x22000000, 0x62808380, 0x009f0081, 0xa184a053, 0xaf000400, + 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE, + SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE, + "EEPROM - fast"}, + /* Expansion entry 1001 */ + {0x2a000002, 0x6b808201, 0x00050081, 0x03840253, 0xaf020406, + 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, + SAIFUN_FLASH_BYTE_ADDR_MASK, 0, + "Entry 1001"}, + /* Expansion entry 1010 */ + {0x26000001, 0x67808201, 0x00050081, 0x03840253, 0xaf020406, + 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, + SAIFUN_FLASH_BYTE_ADDR_MASK, 0, + "Entry 1010"}, + /* ATMEL AT45DB011B (buffered flash) */ + {0x2e000003, 0x6e808273, 0x00570081, 0x68848353, 0xaf000400, + 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, + BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE, + "Buffered flash (128kB)"}, + /* Expansion entry 1100 */ + {0x33000000, 0x73808201, 0x00050081, 0x03840253, 0xaf020406, + 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, + SAIFUN_FLASH_BYTE_ADDR_MASK, 0, + "Entry 1100"}, + /* Expansion entry 1101 */ + {0x3b000002, 0x7b808201, 0x00050081, 0x03840253, 0xaf020406, + 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, + SAIFUN_FLASH_BYTE_ADDR_MASK, 0, + "Entry 1101"}, + /* Ateml Expansion entry 1110 */ + {0x37000001, 0x76808273, 0x00570081, 0x68848353, 0xaf000400, + 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, + BUFFERED_FLASH_BYTE_ADDR_MASK, 0, + "Entry 1110 (Atmel)"}, + /* ATMEL AT45DB021B (buffered flash) */ + {0x3f000003, 0x7e808273, 0x00570081, 0x68848353, 0xaf000400, + 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, + BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE*2, + "Buffered flash (256kB)"}, }; MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl); @@ -2529,21 +2579,27 @@ bnx2_init_nvram(struct bnx2 *bp) /* Flash interface has been reconfigured */ for (j = 0, flash = &flash_table[0]; j < entry_count; - j++, flash++) { - - if (val == flash->config1) { + j++, flash++) { + if ((val & FLASH_BACKUP_STRAP_MASK) == + (flash->config1 & FLASH_BACKUP_STRAP_MASK)) { bp->flash_info = flash; break; } } } else { + u32 mask; /* Not yet been reconfigured */ + if (val & (1 << 23)) + mask = FLASH_BACKUP_STRAP_MASK; + else + mask = FLASH_STRAP_MASK; + for (j = 0, flash = &flash_table[0]; j < entry_count; j++, flash++) { - if ((val & FLASH_STRAP_MASK) == flash->strapping) { + if ((val & mask) == (flash->strapping & mask)) { bp->flash_info = flash; /* Request access to the flash interface. */ diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index c0e88f85049..4a2e6ba7cd7 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -3847,7 +3847,7 @@ struct sw_bd { #define BUFFERED_FLASH_PHY_PAGE_SIZE (1 << BUFFERED_FLASH_PAGE_BITS) #define BUFFERED_FLASH_BYTE_ADDR_MASK (BUFFERED_FLASH_PHY_PAGE_SIZE-1) #define BUFFERED_FLASH_PAGE_SIZE 264 -#define BUFFERED_FLASH_TOTAL_SIZE 131072 +#define BUFFERED_FLASH_TOTAL_SIZE 0x21000 #define SAIFUN_FLASH_PAGE_BITS 8 #define SAIFUN_FLASH_PHY_PAGE_SIZE (1 << SAIFUN_FLASH_PAGE_BITS) @@ -3855,6 +3855,12 @@ struct sw_bd { #define SAIFUN_FLASH_PAGE_SIZE 256 #define SAIFUN_FLASH_BASE_TOTAL_SIZE 65536 +#define ST_MICRO_FLASH_PAGE_BITS 8 +#define ST_MICRO_FLASH_PHY_PAGE_SIZE (1 << ST_MICRO_FLASH_PAGE_BITS) +#define ST_MICRO_FLASH_BYTE_ADDR_MASK (ST_MICRO_FLASH_PHY_PAGE_SIZE-1) +#define ST_MICRO_FLASH_PAGE_SIZE 256 +#define ST_MICRO_FLASH_BASE_TOTAL_SIZE 65536 + #define NVRAM_TIMEOUT_COUNT 30000 @@ -3863,6 +3869,8 @@ struct sw_bd { BNX2_NVM_CFG1_PROTECT_MODE | \ BNX2_NVM_CFG1_FLASH_SIZE) +#define FLASH_BACKUP_STRAP_MASK (0xf << 26) + struct flash_spec { u32 strapping; u32 config1; -- cgit v1.2.3 From e3648b3d8de3b37fae7acbb57db1e001a19cd3b7 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 4 Nov 2005 08:51:21 -0800 Subject: [PATCH] bnx2: update firmware handshake for 5708 Dynamically determine the shared memory location where eeprom parameters are stored instead of using a fixed location. Add speed reporting to management firmware. This allows management firmware to know the current speed without contending for MII registers. Signed-off-by: Michael Chan Signed-off-by: John W. Linville --- drivers/net/bnx2.c | 94 +++++++++++++++++++++++++++++++++++++++++++++--------- drivers/net/bnx2.h | 43 +++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 15 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 08086a9e541..affb67372e0 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -436,6 +436,62 @@ alloc_mem_err: return -ENOMEM; } +static void +bnx2_report_fw_link(struct bnx2 *bp) +{ + u32 fw_link_status = 0; + + if (bp->link_up) { + u32 bmsr; + + switch (bp->line_speed) { + case SPEED_10: + if (bp->duplex == DUPLEX_HALF) + fw_link_status = BNX2_LINK_STATUS_10HALF; + else + fw_link_status = BNX2_LINK_STATUS_10FULL; + break; + case SPEED_100: + if (bp->duplex == DUPLEX_HALF) + fw_link_status = BNX2_LINK_STATUS_100HALF; + else + fw_link_status = BNX2_LINK_STATUS_100FULL; + break; + case SPEED_1000: + if (bp->duplex == DUPLEX_HALF) + fw_link_status = BNX2_LINK_STATUS_1000HALF; + else + fw_link_status = BNX2_LINK_STATUS_1000FULL; + break; + case SPEED_2500: + if (bp->duplex == DUPLEX_HALF) + fw_link_status = BNX2_LINK_STATUS_2500HALF; + else + fw_link_status = BNX2_LINK_STATUS_2500FULL; + break; + } + + fw_link_status |= BNX2_LINK_STATUS_LINK_UP; + + if (bp->autoneg) { + fw_link_status |= BNX2_LINK_STATUS_AN_ENABLED; + + bnx2_read_phy(bp, MII_BMSR, &bmsr); + bnx2_read_phy(bp, MII_BMSR, &bmsr); + + if (!(bmsr & BMSR_ANEGCOMPLETE) || + bp->phy_flags & PHY_PARALLEL_DETECT_FLAG) + fw_link_status |= BNX2_LINK_STATUS_PARALLEL_DET; + else + fw_link_status |= BNX2_LINK_STATUS_AN_COMPLETE; + } + } + else + fw_link_status = BNX2_LINK_STATUS_LINK_DOWN; + + REG_WR_IND(bp, bp->shmem_base + BNX2_LINK_STATUS, fw_link_status); +} + static void bnx2_report_link(struct bnx2 *bp) { @@ -467,6 +523,8 @@ bnx2_report_link(struct bnx2 *bp) netif_carrier_off(bp->dev); printk(KERN_ERR PFX "%s NIC Link is Down\n", bp->dev->name); } + + bnx2_report_fw_link(bp); } static void @@ -1123,13 +1181,13 @@ bnx2_init_5708s_phy(struct bnx2 *bp) bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG); } - val = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_PORT_HW_CFG_CONFIG) & + val = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG) & BNX2_PORT_HW_CFG_CFG_TXCTL3_MASK; if (val) { u32 is_backplane; - is_backplane = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + + is_backplane = REG_RD_IND(bp, bp->shmem_base + BNX2_SHARED_HW_CFG_CONFIG); if (is_backplane & BNX2_SHARED_HW_CFG_PHY_BACKPLANE) { bnx2_write_phy(bp, BCM5708S_BLK_ADDR, @@ -1280,13 +1338,13 @@ bnx2_fw_sync(struct bnx2 *bp, u32 msg_data) bp->fw_wr_seq++; msg_data |= bp->fw_wr_seq; - REG_WR_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_DRV_MB, msg_data); + REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB, msg_data); /* wait for an acknowledgement. */ for (i = 0; i < (FW_ACK_TIME_OUT_MS * 1000)/5; i++) { udelay(5); - val = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_FW_MB); + val = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_MB); if ((val & BNX2_FW_MSG_ACK) == (msg_data & BNX2_DRV_MSG_SEQ)) break; @@ -1299,7 +1357,7 @@ bnx2_fw_sync(struct bnx2 *bp, u32 msg_data) msg_data &= ~BNX2_DRV_MSG_CODE; msg_data |= BNX2_DRV_MSG_CODE_FW_TIMEOUT; - REG_WR_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_DRV_MB, msg_data); + REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB, msg_data); bp->fw_timed_out = 1; @@ -2935,7 +2993,7 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) /* Deposit a driver reset signature so the firmware knows that * this is a soft reset. */ - REG_WR_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_DRV_RESET_SIGNATURE, + REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_RESET_SIGNATURE, BNX2_DRV_RESET_SIGNATURE_MAGIC); bp->fw_timed_out = 0; @@ -4012,7 +4070,7 @@ bnx2_timer(unsigned long data) goto bnx2_restart_timer; msg = (u32) ++bp->fw_drv_pulse_wr_seq; - REG_WR_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_DRV_PULSE_MB, msg); + REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_PULSE_MB, msg); if ((bp->phy_flags & PHY_SERDES_FLAG) && (CHIP_NUM(bp) == CHIP_NUM_5706)) { @@ -5483,10 +5541,18 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bnx2_init_nvram(bp); + reg = REG_RD_IND(bp, BNX2_SHM_HDR_SIGNATURE); + + if ((reg & BNX2_SHM_HDR_SIGNATURE_SIG_MASK) == + BNX2_SHM_HDR_SIGNATURE_SIG) + bp->shmem_base = REG_RD_IND(bp, BNX2_SHM_HDR_ADDR_0); + else + bp->shmem_base = HOST_VIEW_SHMEM_BASE; + /* Get the permanent MAC address. First we need to make sure the * firmware is actually running. */ - reg = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_DEV_INFO_SIGNATURE); + reg = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_SIGNATURE); if ((reg & BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK) != BNX2_DEV_INFO_SIGNATURE_MAGIC) { @@ -5495,14 +5561,13 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) goto err_out_unmap; } - bp->fw_ver = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + - BNX2_DEV_INFO_BC_REV); + bp->fw_ver = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_BC_REV); - reg = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_PORT_HW_CFG_MAC_UPPER); + reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_MAC_UPPER); bp->mac_addr[0] = (u8) (reg >> 8); bp->mac_addr[1] = (u8) reg; - reg = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_PORT_HW_CFG_MAC_LOWER); + reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_MAC_LOWER); bp->mac_addr[2] = (u8) (reg >> 24); bp->mac_addr[3] = (u8) (reg >> 16); bp->mac_addr[4] = (u8) (reg >> 8); @@ -5538,7 +5603,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->flags |= NO_WOL_FLAG; if (CHIP_NUM(bp) == CHIP_NUM_5708) { bp->phy_addr = 2; - reg = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + + reg = REG_RD_IND(bp, bp->shmem_base + BNX2_SHARED_HW_CFG_CONFIG); if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G) bp->phy_flags |= PHY_2_5G_CAPABLE_FLAG; @@ -5562,8 +5627,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) if (bp->phy_flags & PHY_SERDES_FLAG) { bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg; - reg = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + - BNX2_PORT_HW_CFG_CONFIG); + reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG); reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK; if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) { bp->autoneg = 0; diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 4a2e6ba7cd7..012586e4ba0 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -3715,6 +3715,15 @@ struct l2_fhdr { #define BNX2_MCP_ROM 0x00150000 #define BNX2_MCP_SCRATCH 0x00160000 +#define BNX2_SHM_HDR_SIGNATURE BNX2_MCP_SCRATCH +#define BNX2_SHM_HDR_SIGNATURE_SIG_MASK 0xffff0000 +#define BNX2_SHM_HDR_SIGNATURE_SIG 0x53530000 +#define BNX2_SHM_HDR_SIGNATURE_VER_MASK 0x000000ff +#define BNX2_SHM_HDR_SIGNATURE_VER_ONE 0x00000001 + +#define BNX2_SHM_HDR_ADDR_0 BNX2_MCP_SCRATCH + 4 +#define BNX2_SHM_HDR_ADDR_1 BNX2_MCP_SCRATCH + 8 + #define NUM_MC_HASH_REGISTERS 8 @@ -4052,6 +4061,8 @@ struct bnx2 { u8 mac_addr[8]; + u32 shmem_base; + u32 fw_ver; int pm_cap; @@ -4191,6 +4202,38 @@ struct fw_info { #define BNX2_FW_MSG_STATUS_FAILURE 0x00ff0000 #define BNX2_LINK_STATUS 0x0000000c +#define BNX2_LINK_STATUS_INIT_VALUE 0xffffffff +#define BNX2_LINK_STATUS_LINK_UP 0x1 +#define BNX2_LINK_STATUS_LINK_DOWN 0x0 +#define BNX2_LINK_STATUS_SPEED_MASK 0x1e +#define BNX2_LINK_STATUS_AN_INCOMPLETE (0<<1) +#define BNX2_LINK_STATUS_10HALF (1<<1) +#define BNX2_LINK_STATUS_10FULL (2<<1) +#define BNX2_LINK_STATUS_100HALF (3<<1) +#define BNX2_LINK_STATUS_100BASE_T4 (4<<1) +#define BNX2_LINK_STATUS_100FULL (5<<1) +#define BNX2_LINK_STATUS_1000HALF (6<<1) +#define BNX2_LINK_STATUS_1000FULL (7<<1) +#define BNX2_LINK_STATUS_2500HALF (8<<1) +#define BNX2_LINK_STATUS_2500FULL (9<<1) +#define BNX2_LINK_STATUS_AN_ENABLED (1<<5) +#define BNX2_LINK_STATUS_AN_COMPLETE (1<<6) +#define BNX2_LINK_STATUS_PARALLEL_DET (1<<7) +#define BNX2_LINK_STATUS_RESERVED (1<<8) +#define BNX2_LINK_STATUS_PARTNER_AD_1000FULL (1<<9) +#define BNX2_LINK_STATUS_PARTNER_AD_1000HALF (1<<10) +#define BNX2_LINK_STATUS_PARTNER_AD_100BT4 (1<<11) +#define BNX2_LINK_STATUS_PARTNER_AD_100FULL (1<<12) +#define BNX2_LINK_STATUS_PARTNER_AD_100HALF (1<<13) +#define BNX2_LINK_STATUS_PARTNER_AD_10FULL (1<<14) +#define BNX2_LINK_STATUS_PARTNER_AD_10HALF (1<<15) +#define BNX2_LINK_STATUS_TX_FC_ENABLED (1<<16) +#define BNX2_LINK_STATUS_RX_FC_ENABLED (1<<17) +#define BNX2_LINK_STATUS_PARTNER_SYM_PAUSE_CAP (1<<18) +#define BNX2_LINK_STATUS_PARTNER_ASYM_PAUSE_CAP (1<<19) +#define BNX2_LINK_STATUS_SERDES_LINK (1<<20) +#define BNX2_LINK_STATUS_PARTNER_AD_2500FULL (1<<21) +#define BNX2_LINK_STATUS_PARTNER_AD_2500HALF (1<<22) #define BNX2_DRV_PULSE_MB 0x00000010 #define BNX2_DRV_PULSE_SEQ_MASK 0x00007fff -- cgit v1.2.3 From f4e418f7f3286f854883f9f7e3bbf7005340d2de Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 4 Nov 2005 08:53:48 -0800 Subject: [PATCH] bnx2: refine bnx2_poll Refine bnx2_poll() logic to write back the most up-to-date status tag when all work has been processed. This eliminates some occasional extra interrupts when a older status tag is written even though all work has been processed. The idea is to read the status tag just before exiting bnx2_poll() and then check again for any new work. If no new work is pending, the status tag written back will not generate any extra interrupt. This logic is similar to the changes David Miller did to tg3_poll(). Signed-off-by: Michael Chan Signed-off-by: John W. Linville --- drivers/net/bnx2.c | 55 +++++++++++++++++++++++++++++++++++++++--------------- drivers/net/bnx2.h | 3 +++ 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index affb67372e0..aa6d30e0d82 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -1533,10 +1533,11 @@ bnx2_phy_int(struct bnx2 *bp) static void bnx2_tx_int(struct bnx2 *bp) { + struct status_block *sblk = bp->status_blk; u16 hw_cons, sw_cons, sw_ring_cons; int tx_free_bd = 0; - hw_cons = bp->status_blk->status_tx_quick_consumer_index0; + hw_cons = bp->hw_tx_cons = sblk->status_tx_quick_consumer_index0; if ((hw_cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT) { hw_cons++; } @@ -1591,7 +1592,9 @@ bnx2_tx_int(struct bnx2 *bp) dev_kfree_skb_irq(skb); - hw_cons = bp->status_blk->status_tx_quick_consumer_index0; + hw_cons = bp->hw_tx_cons = + sblk->status_tx_quick_consumer_index0; + if ((hw_cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT) { hw_cons++; } @@ -1636,11 +1639,12 @@ bnx2_reuse_rx_skb(struct bnx2 *bp, struct sk_buff *skb, static int bnx2_rx_int(struct bnx2 *bp, int budget) { + struct status_block *sblk = bp->status_blk; u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod; struct l2_fhdr *rx_hdr; int rx_pkt = 0; - hw_cons = bp->status_blk->status_rx_quick_consumer_index0; + hw_cons = bp->hw_rx_cons = sblk->status_rx_quick_consumer_index0; if ((hw_cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT) { hw_cons++; } @@ -1760,6 +1764,15 @@ next_rx: if ((rx_pkt == budget)) break; + + /* Refresh hw_cons to see if there is new work */ + if (sw_cons == hw_cons) { + hw_cons = bp->hw_rx_cons = + sblk->status_rx_quick_consumer_index0; + if ((hw_cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT) + hw_cons++; + rmb(); + } } bp->rx_cons = sw_cons; bp->rx_prod = sw_prod; @@ -1827,15 +1840,27 @@ bnx2_interrupt(int irq, void *dev_instance, struct pt_regs *regs) return IRQ_HANDLED; } +static inline int +bnx2_has_work(struct bnx2 *bp) +{ + struct status_block *sblk = bp->status_blk; + + if ((sblk->status_rx_quick_consumer_index0 != bp->hw_rx_cons) || + (sblk->status_tx_quick_consumer_index0 != bp->hw_tx_cons)) + return 1; + + if (((sblk->status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) != 0) != + bp->link_up) + return 1; + + return 0; +} + static int bnx2_poll(struct net_device *dev, int *budget) { struct bnx2 *bp = dev->priv; - int rx_done = 1; - - bp->last_status_idx = bp->status_blk->status_idx; - rmb(); if ((bp->status_blk->status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) != (bp->status_blk->status_attn_bits_ack & @@ -1846,11 +1871,10 @@ bnx2_poll(struct net_device *dev, int *budget) spin_unlock(&bp->phy_lock); } - if (bp->status_blk->status_tx_quick_consumer_index0 != bp->tx_cons) { + if (bp->status_blk->status_tx_quick_consumer_index0 != bp->hw_tx_cons) bnx2_tx_int(bp); - } - if (bp->status_blk->status_rx_quick_consumer_index0 != bp->rx_cons) { + if (bp->status_blk->status_rx_quick_consumer_index0 != bp->hw_rx_cons) { int orig_budget = *budget; int work_done; @@ -1860,13 +1884,12 @@ bnx2_poll(struct net_device *dev, int *budget) work_done = bnx2_rx_int(bp, orig_budget); *budget -= work_done; dev->quota -= work_done; - - if (work_done >= orig_budget) { - rx_done = 0; - } } - if (rx_done) { + bp->last_status_idx = bp->status_blk->status_idx; + rmb(); + + if (!bnx2_has_work(bp)) { netif_rx_complete(dev); REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | @@ -3222,6 +3245,7 @@ bnx2_init_tx_ring(struct bnx2 *bp) bp->tx_prod = 0; bp->tx_cons = 0; + bp->hw_tx_cons = 0; bp->tx_prod_bseq = 0; val = BNX2_L2CTX_TYPE_TYPE_L2; @@ -3254,6 +3278,7 @@ bnx2_init_rx_ring(struct bnx2 *bp) ring_prod = prod = bp->rx_prod = 0; bp->rx_cons = 0; + bp->hw_rx_cons = 0; bp->rx_prod_bseq = 0; rxbd = &bp->rx_desc_ring[0]; diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 012586e4ba0..76bb5f1a250 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -3914,6 +3914,9 @@ struct bnx2 { u16 tx_cons; int tx_ring_size; + u16 hw_tx_cons; + u16 hw_rx_cons; + #ifdef BCM_VLAN struct vlan_group *vlgrp; #endif -- cgit v1.2.3 From 05d0f1cf69fd589634b38b6f6e4b8cfdaace9ca0 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 4 Nov 2005 08:53:48 -0800 Subject: [PATCH] bnx2: update version and minor fixes Some book keeping and a style fix. Signed-off-by: Michael Chan Signed-off-by: John W. Linville --- drivers/net/bnx2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index aa6d30e0d82..8f464271664 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -14,8 +14,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.2.21" -#define DRV_MODULE_RELDATE "September 7, 2005" +#define DRV_MODULE_VERSION "1.4.30" +#define DRV_MODULE_RELDATE "October 11, 2005" #define RUN_AT(x) (jiffies + (x)) @@ -26,7 +26,7 @@ static char version[] __devinitdata = "Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; MODULE_AUTHOR("Michael Chan "); -MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706 Driver"); +MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708 Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); @@ -3364,7 +3364,7 @@ bnx2_free_rx_skbs(struct bnx2 *bp) struct sw_bd *rx_buf = &bp->rx_buf_ring[i]; struct sk_buff *skb = rx_buf->skb; - if (skb == 0) + if (skb == NULL) continue; pci_unmap_single(bp->pdev, pci_unmap_addr(rx_buf, mapping), -- cgit v1.2.3 From d38087609aefdf0918960c9d941d46f884a4f4eb Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 5 Nov 2005 17:42:27 +0100 Subject: [PATCH] airo.c/airo_cs.c: correct prototypes This patch creates a file airo.h containing prototypes of the global functions in airo.c used by airo_cs.c . If you got strange problems with either airo_cs devices or in any other completely unrelated part of the kernel shortly or long after a airo_cs device was detected by the kernel, this might have been caused by the fact that caller and callee disagreed regarding the size of the first argument to init_airo_card()... Signed-off-by: Adrian Bunk Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 2 ++ drivers/net/wireless/airo.h | 9 +++++++++ drivers/net/wireless/airo_cs.c | 6 ++---- 3 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 drivers/net/wireless/airo.h diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 849ac88bccc..6afc6e5dee9 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -47,6 +47,8 @@ #include #include +#include "airo.h" + #ifdef CONFIG_PCI static struct pci_device_id card_ids[] = { { 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, }, diff --git a/drivers/net/wireless/airo.h b/drivers/net/wireless/airo.h new file mode 100644 index 00000000000..e480adf86be --- /dev/null +++ b/drivers/net/wireless/airo.h @@ -0,0 +1,9 @@ +#ifndef _AIRO_H_ +#define _AIRO_H_ + +struct net_device *init_airo_card(unsigned short irq, int port, int is_pcmcia, + struct device *dmdev); +int reset_airo_card(struct net_device *dev); +void stop_airo_card(struct net_device *dev, int freeres); + +#endif /* _AIRO_H_ */ diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index 784de910911..96ed8da8661 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c @@ -42,6 +42,8 @@ #include #include +#include "airo.h" + /* All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If you do not define PCMCIA_DEBUG at all, all the debug code will be @@ -78,10 +80,6 @@ MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards"); event handler. */ -struct net_device *init_airo_card( int, int, int, struct device * ); -void stop_airo_card( struct net_device *, int ); -int reset_airo_card( struct net_device * ); - static void airo_config(dev_link_t *link); static void airo_release(dev_link_t *link); static int airo_event(event_t event, int priority, -- cgit v1.2.3 From 0a1cc0b6a4abaed5f891d1be3e3d0d7b9b719287 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sat, 5 Nov 2005 20:32:26 -0800 Subject: [AGPGART] Fix up warning in efficeon driver. efficeon-agp.c:222: warning: passing arg 1 of `virt_to_phys' makes pointer from integer without a cast Signed-off-by: Dave Jones --- drivers/char/agp/efficeon-agp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c index b64028abc1f..d41e0a62e32 100644 --- a/drivers/char/agp/efficeon-agp.c +++ b/drivers/char/agp/efficeon-agp.c @@ -219,7 +219,7 @@ static int efficeon_create_gatt_table(struct agp_bridge_data *bridge) efficeon_private.l1_table[index] = page; - value = virt_to_gart(page) | pati | present | index; + value = virt_to_gart((unsigned long *)page) | pati | present | index; pci_write_config_dword(agp_bridge->dev, EFFICEON_ATTPAGE, value); -- cgit v1.2.3 From a10b5aacea01d59152b9d003a14476ee99d394d8 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sat, 5 Nov 2005 23:39:54 -0500 Subject: Remove linux/version.h include from drivers/net/phy/* and net/ieee80211/*. Unused, and causes the files to be needlessly rebuilt in some cases. --- drivers/net/phy/cicada.c | 1 - drivers/net/phy/davicom.c | 1 - drivers/net/phy/lxt.c | 1 - drivers/net/phy/marvell.c | 1 - drivers/net/phy/mdio_bus.c | 1 - drivers/net/phy/phy.c | 1 - drivers/net/phy/phy_device.c | 1 - drivers/net/phy/qsemi.c | 1 - net/ieee80211/ieee80211_crypt.c | 1 - net/ieee80211/ieee80211_crypt_ccmp.c | 1 - net/ieee80211/ieee80211_crypt_tkip.c | 1 - net/ieee80211/ieee80211_crypt_wep.c | 1 - net/ieee80211/ieee80211_geo.c | 1 - net/ieee80211/ieee80211_module.c | 1 - net/ieee80211/ieee80211_rx.c | 1 - net/ieee80211/ieee80211_tx.c | 1 - 16 files changed, 16 deletions(-) diff --git a/drivers/net/phy/cicada.c b/drivers/net/phy/cicada.c index c47fb2ecd14..7d8d534255c 100644 --- a/drivers/net/phy/cicada.c +++ b/drivers/net/phy/cicada.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c index 6caf499fae3..5e9002e444c 100644 --- a/drivers/net/phy/davicom.c +++ b/drivers/net/phy/davicom.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c index 4c840448ec8..bef79e454c3 100644 --- a/drivers/net/phy/lxt.c +++ b/drivers/net/phy/lxt.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 4a72b025006..a2d6386d13b 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 5eab9c42a11..02940c0fef6 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 9209da9dde0..b8686e47f89 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 6da1aa0706a..16bebe7a7ce 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/phy/qsemi.c b/drivers/net/phy/qsemi.c index d461ba45763..65d995b02b2 100644 --- a/drivers/net/phy/qsemi.c +++ b/drivers/net/phy/qsemi.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/net/ieee80211/ieee80211_crypt.c b/net/ieee80211/ieee80211_crypt.c index f3b6aa3be63..20cc580a07e 100644 --- a/net/ieee80211/ieee80211_crypt.c +++ b/net/ieee80211/ieee80211_crypt.c @@ -12,7 +12,6 @@ */ #include -#include #include #include #include diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c index 05a853c1301..47022172850 100644 --- a/net/ieee80211/ieee80211_crypt_ccmp.c +++ b/net/ieee80211/ieee80211_crypt_ccmp.c @@ -10,7 +10,6 @@ */ #include -#include #include #include #include diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c index 2e34f29b795..e0988320efb 100644 --- a/net/ieee80211/ieee80211_crypt_tkip.c +++ b/net/ieee80211/ieee80211_crypt_tkip.c @@ -10,7 +10,6 @@ */ #include -#include #include #include #include diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c index 7c08ed2f262..073aebdf0f6 100644 --- a/net/ieee80211/ieee80211_crypt_wep.c +++ b/net/ieee80211/ieee80211_crypt_wep.c @@ -10,7 +10,6 @@ */ #include -#include #include #include #include diff --git a/net/ieee80211/ieee80211_geo.c b/net/ieee80211/ieee80211_geo.c index c4b54ef8f6d..610cc5cbc25 100644 --- a/net/ieee80211/ieee80211_geo.c +++ b/net/ieee80211/ieee80211_geo.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c index f66d792cd20..321287bc887 100644 --- a/net/ieee80211/ieee80211_module.c +++ b/net/ieee80211/ieee80211_module.c @@ -45,7 +45,6 @@ #include #include #include -#include #include #include #include diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index ce694cf5c16..6ad88218f57 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c index 95ccbadbf55..445f206e65e 100644 --- a/net/ieee80211/ieee80211_tx.c +++ b/net/ieee80211/ieee80211_tx.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From ecf8b596cf636c14896841625d552e148585ad07 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sat, 5 Nov 2005 23:40:16 -0500 Subject: [netdrvr] fac_8xx build fix --- drivers/net/fec_8xx/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/fec_8xx/Kconfig b/drivers/net/fec_8xx/Kconfig index 4560026ed41..94e7a9af870 100644 --- a/drivers/net/fec_8xx/Kconfig +++ b/drivers/net/fec_8xx/Kconfig @@ -1,6 +1,6 @@ config FEC_8XX tristate "Motorola 8xx FEC driver" - depends on NET_ETHERNET + depends on NET_ETHERNET && FEC select MII config FEC_8XX_GENERIC_PHY -- cgit v1.2.3 From 50eb80068001871339d04b749fb9b198428b56d2 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sat, 5 Nov 2005 23:40:46 -0500 Subject: [netdrvr s2io] warning fixes From Andrew Morton. --- drivers/net/s2io.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 9c4935407f2..0745dd9d01f 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -2110,7 +2110,7 @@ int fill_rxd_3buf(nic_t *nic, RxD_t *rxdp, struct sk_buff *skb) { struct net_device *dev = nic->dev; struct sk_buff *frag_list; - u64 tmp; + void *tmp; /* Buffer-1 receives L3/L4 headers */ ((RxD3_t*)rxdp)->Buffer1_ptr = pci_map_single @@ -2125,11 +2125,9 @@ int fill_rxd_3buf(nic_t *nic, RxD_t *rxdp, struct sk_buff *skb) } frag_list = skb_shinfo(skb)->frag_list; frag_list->next = NULL; - tmp = (u64) frag_list->data; - tmp += ALIGN_SIZE; - tmp &= ~ALIGN_SIZE; - frag_list->data = (void *) tmp; - frag_list->tail = (void *) tmp; + tmp = (void *)ALIGN((long)frag_list->data, ALIGN_SIZE + 1); + frag_list->data = tmp; + frag_list->tail = tmp; /* Buffer-2 receives L4 data payload */ ((RxD3_t*)rxdp)->Buffer2_ptr = pci_map_single(nic->pdev, -- cgit v1.2.3 From 21c614a7899046ab108b3d327d76c33443a8ebf2 Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Sun, 6 Nov 2005 09:07:03 +0000 Subject: [SERIAL] Support Au1x00 8250 UARTs using the generic 8250 driver. The offsets of the registers are in a different place, and some parts cannot handle a full set of modem control signals. Signed-off-by: Pantelis Antoniou Signed-off-by: Russell King --- drivers/serial/8250.c | 73 +++++++++++++++++++++++++++++-- drivers/serial/8250.h | 1 + drivers/serial/8250_au1x00.c | 102 +++++++++++++++++++++++++++++++++++++++++++ drivers/serial/Kconfig | 8 ++++ drivers/serial/Makefile | 1 + drivers/serial/serial_core.c | 1 + include/linux/serial_8250.h | 1 + include/linux/serial_core.h | 1 + 8 files changed, 185 insertions(+), 3 deletions(-) create mode 100644 drivers/serial/8250_au1x00.c diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index f47d2c454e3..186e96c47b3 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -251,9 +251,53 @@ static const struct serial8250_config uart_config[] = { }, }; +#ifdef CONFIG_SERIAL_8250_AU1X00 + +/* Au1x00 UART hardware has a weird register layout */ +static const u8 au_io_in_map[] = { + [UART_RX] = 0, + [UART_IER] = 2, + [UART_IIR] = 3, + [UART_LCR] = 5, + [UART_MCR] = 6, + [UART_LSR] = 7, + [UART_MSR] = 8, +}; + +static const u8 au_io_out_map[] = { + [UART_TX] = 1, + [UART_IER] = 2, + [UART_FCR] = 4, + [UART_LCR] = 5, + [UART_MCR] = 6, +}; + +/* sane hardware needs no mapping */ +static inline int map_8250_in_reg(struct uart_8250_port *up, int offset) +{ + if (up->port.iotype != UPIO_AU) + return offset; + return au_io_in_map[offset]; +} + +static inline int map_8250_out_reg(struct uart_8250_port *up, int offset) +{ + if (up->port.iotype != UPIO_AU) + return offset; + return au_io_out_map[offset]; +} + +#else + +/* sane hardware needs no mapping */ +#define map_8250_in_reg(up, offset) (offset) +#define map_8250_out_reg(up, offset) (offset) + +#endif + static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) { - offset <<= up->port.regshift; + offset = map_8250_in_reg(up, offset) << up->port.regshift; switch (up->port.iotype) { case UPIO_HUB6: @@ -266,6 +310,11 @@ static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) case UPIO_MEM32: return readl(up->port.membase + offset); +#ifdef CONFIG_SERIAL_8250_AU1X00 + case UPIO_AU: + return __raw_readl(up->port.membase + offset); +#endif + default: return inb(up->port.iobase + offset); } @@ -274,7 +323,7 @@ static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) static _INLINE_ void serial_out(struct uart_8250_port *up, int offset, int value) { - offset <<= up->port.regshift; + offset = map_8250_out_reg(up, offset) << up->port.regshift; switch (up->port.iotype) { case UPIO_HUB6: @@ -290,6 +339,12 @@ serial_out(struct uart_8250_port *up, int offset, int value) writel(value, up->port.membase + offset); break; +#ifdef CONFIG_SERIAL_8250_AU1X00 + case UPIO_AU: + __raw_writel(value, up->port.membase + offset); + break; +#endif + default: outb(value, up->port.iobase + offset); } @@ -910,6 +965,13 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) } } #endif + +#ifdef CONFIG_SERIAL_8250_AU1X00 + /* if access method is AU, it is a 16550 with a quirk */ + if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU) + up->bugs |= UART_BUG_NOMSR; +#endif + serial_outp(up, UART_LCR, save_lcr); if (up->capabilities != uart_config[up->port.type].flags) { @@ -1057,6 +1119,10 @@ static void serial8250_enable_ms(struct uart_port *port) { struct uart_8250_port *up = (struct uart_8250_port *)port; + /* no MSR capabilities */ + if (up->bugs & UART_BUG_NOMSR) + return; + up->ier |= UART_IER_MSI; serial_out(up, UART_IER, up->ier); } @@ -1774,7 +1840,8 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios, * CTS flow control flag and modem status interrupts */ up->ier &= ~UART_IER_MSI; - if (UART_ENABLE_MS(&up->port, termios->c_cflag)) + if (!(up->bugs & UART_BUG_NOMSR) && + UART_ENABLE_MS(&up->port, termios->c_cflag)) up->ier |= UART_IER_MSI; if (up->capabilities & UART_CAP_UUE) up->ier |= UART_IER_UUE | UART_IER_RTOIE; diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h index b1b459efda5..a607b98016d 100644 --- a/drivers/serial/8250.h +++ b/drivers/serial/8250.h @@ -49,6 +49,7 @@ struct serial8250_config { #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ +#define UART_BUG_NOMSR (1 << 2) /* UART has buggy MSR status bits (Au1x00) */ #if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486)) #define _INLINE_ inline diff --git a/drivers/serial/8250_au1x00.c b/drivers/serial/8250_au1x00.c new file mode 100644 index 00000000000..06ae8fbcc94 --- /dev/null +++ b/drivers/serial/8250_au1x00.c @@ -0,0 +1,102 @@ +/* + * Serial Device Initialisation for Au1x00 + * + * (C) Copyright Embedded Alley Solutions, Inc 2005 + * Author: Pantelis Antoniou + * + * 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 option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "8250.h" + +#define PORT(_base, _irq) \ + { \ + .iobase = _base, \ + .membase = (void __iomem *)_base,\ + .mapbase = _base, \ + .irq = _irq, \ + .uartclk = 0, /* filled */ \ + .regshift = 2, \ + .iotype = UPIO_AU, \ + .flags = UPF_SKIP_TEST | \ + UPF_IOREMAP, \ + } + +static struct plat_serial8250_port au1x00_data[] = { +#if defined(CONFIG_SOC_AU1000) + PORT(UART0_ADDR, AU1000_UART0_INT), + PORT(UART1_ADDR, AU1000_UART1_INT), + PORT(UART2_ADDR, AU1000_UART2_INT), + PORT(UART3_ADDR, AU1000_UART3_INT), +#elif defined(CONFIG_SOC_AU1500) + PORT(UART0_ADDR, AU1500_UART0_INT), + PORT(UART3_ADDR, AU1500_UART3_INT), +#elif defined(CONFIG_SOC_AU1100) + PORT(UART0_ADDR, AU1100_UART0_INT), + PORT(UART1_ADDR, AU1100_UART1_INT), + PORT(UART2_ADDR, AU1100_UART2_INT), + PORT(UART3_ADDR, AU1100_UART3_INT), +#elif defined(CONFIG_SOC_AU1550) + PORT(UART0_ADDR, AU1550_UART0_INT), + PORT(UART1_ADDR, AU1550_UART1_INT), + PORT(UART2_ADDR, AU1550_UART2_INT), + PORT(UART3_ADDR, AU1550_UART3_INT), +#elif defined(CONFIG_SOC_AU1200) + PORT(UART0_ADDR, AU1200_UART0_INT), + PORT(UART1_ADDR, AU1200_UART1_INT), +#endif + { }, +}; + +static struct platform_device au1x00_device = { + .name = "serial8250", + .id = PLAT8250_DEV_AU1X00, + .dev = { + .platform_data = au1x00_data, + }, +}; + +static int __init au1x00_init(void) +{ + int i; + unsigned int uartclk; + + /* get uart clock */ + uartclk = get_au1x00_uart_baud_base() * 16; + + /* fill up uartclk */ + for (i = 0; au1x00_data[i].flags ; i++) + au1x00_data[i].uartclk = uartclk; + + return platform_device_register(&au1x00_device); +} + +/* XXX: Yes, I know this doesn't yet work. */ +static void __exit au1x00_exit(void) +{ + platform_device_unregister(&au1x00_device); +} + +module_init(au1x00_init); +module_exit(au1x00_exit); + +MODULE_AUTHOR("Pantelis Antoniou "); +MODULE_DESCRIPTION("8250 serial probe module for Au1x000 cards"); +MODULE_LICENSE("GPL"); diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index b745a1b9e83..ff36f0c9fda 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -207,6 +207,14 @@ config SERIAL_8250_ACORN system, say Y to this option. The driver can handle 1, 2, or 3 port cards. If unsure, say N. +config SERIAL_8250_AU1X00 + bool "AU1X00 serial port support" + depends on SERIAL_8250 != n && SOC_AU1X00 + help + If you have an Au1x00 board and want to use the serial port, say Y + to this option. The driver can handle 1 or 2 serial ports. + If unsure, say N. + comment "Non-8250 serial port support" config SERIAL_AMBA_PL010 diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 11c7dc483f9..d7c7c7180e3 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o +obj-$(CONFIG_SERIAL_8250_AU1X00) += 8250_au1x00.o obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 0745ce78297..427a2385807 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1959,6 +1959,7 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port) break; case UPIO_MEM: case UPIO_MEM32: + case UPIO_AU: snprintf(address, sizeof(address), "MMIO 0x%lx", port->mapbase); break; diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index 2b799d40d66..cee302aefdb 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -42,6 +42,7 @@ enum { PLAT8250_DEV_BOCA, PLAT8250_DEV_HUB6, PLAT8250_DEV_MCA, + PLAT8250_DEV_AU1X00, }; /* diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 9d257923068..a3ac92b19ac 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -211,6 +211,7 @@ struct uart_port { #define UPIO_HUB6 (1) #define UPIO_MEM (2) #define UPIO_MEM32 (3) +#define UPIO_AU (4) /* Au1x00 type IO */ unsigned int read_status_mask; /* driver specific */ unsigned int ignore_status_mask; /* driver specific */ -- cgit v1.2.3 From 2dd34b488a99135ad2a529e33087ddd6a09e992a Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 30 Oct 2005 22:42:11 +0100 Subject: [PATCH] kbuild: permanently fix kernel configuration include mess Include autoconf.h into every kernel compilation via the gcc command line using -imacros. This ensures that we have the kernel configuration included from the start, rather than relying on each file having #include as appropriate. History has shown that this is something which is difficult to get right. Since we now include the kernel configuration automatically, make configcheck becomes meaningless, so remove it. Signed-off-by: Russell King Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg --- Makefile | 8 ++------ include/linux/config.h | 4 +++- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 79601320ac3..2dac8010c14 100644 --- a/Makefile +++ b/Makefile @@ -346,7 +346,8 @@ AFLAGS_KERNEL = # Use LINUXINCLUDE when you must reference the include/ directory. # Needed to be compatible with the O= option LINUXINCLUDE := -Iinclude \ - $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) + $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \ + -imacros include/linux/autoconf.h CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE) @@ -1249,11 +1250,6 @@ tags: FORCE # Scripts to check various things for consistency # --------------------------------------------------------------------------- -configcheck: - find * $(RCS_FIND_IGNORE) \ - -name '*.[hcS]' -type f -print | sort \ - | xargs $(PERL) -w scripts/checkconfig.pl - includecheck: find * $(RCS_FIND_IGNORE) \ -name '*.[hcS]' -type f -print | sort \ diff --git a/include/linux/config.h b/include/linux/config.h index 9d1c14f7ad6..a91f5e55b52 100644 --- a/include/linux/config.h +++ b/include/linux/config.h @@ -1,6 +1,8 @@ #ifndef _LINUX_CONFIG_H #define _LINUX_CONFIG_H - +/* This file is no longer in use and kept only for backward compatibility. + * autoconf.h is now included via -imacros on the commandline + */ #include #endif -- cgit v1.2.3 From ab919c06144cfb11c05b5b5cd291daa96ac2e423 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 6 Nov 2005 11:05:21 +0100 Subject: kconfig: fix xconfig on fedora 2 & 3 (x86_64) From: Than Ngo qt as installed on fedora core (2 and 3) does not work with vanilla kernel. The linker fails to locate the qt lib: Actual Results: # make xconfig HOSTLD scripts/kconfig/qconf /usr/bin/ld: cannot find -lqt collect2: ld returned 1 exit status Than Ngo has provided following fix for the bug. Cc: Than Ngo Acked-by: Dave Jones Signed-off-by: Sam Ravnborg --- scripts/kconfig/Makefile | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index 0dd96919de3..455aeabd95d 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile @@ -129,7 +129,7 @@ endif HOSTCFLAGS_lex.zconf.o := -I$(src) HOSTCFLAGS_zconf.tab.o := -I$(src) -HOSTLOADLIBES_qconf = -L$(QTLIBPATH) -Wl,-rpath,$(QTLIBPATH) -l$(QTLIB) -ldl +HOSTLOADLIBES_qconf = -L$(QTLIBPATH) -Wl,-rpath,$(QTLIBPATH) -l$(LIBS_QT) -ldl HOSTCXXFLAGS_qconf.o = -I$(QTDIR)/include -D LKC_DIRECT_LINK HOSTLOADLIBES_gconf = `pkg-config gtk+-2.0 gmodule-2.0 libglade-2.0 --libs` @@ -163,11 +163,16 @@ $(obj)/.tmp_qtcheck: false; \ fi; \ LIBPATH=$$DIR/lib; LIB=qt; \ - $(HOSTCXX) -print-multi-os-directory > /dev/null 2>&1 && \ - LIBPATH=$$DIR/lib/$$($(HOSTCXX) -print-multi-os-directory); \ - if [ -f $$LIBPATH/libqt-mt.so ]; then LIB=qt-mt; fi; \ + if [ -f $$QTLIB/libqt-mt.so ] ; then \ + LIB=qt-mt; \ + LIBPATH=$$QTLIB; \ + else \ + $(HOSTCXX) -print-multi-os-directory > /dev/null 2>&1 && \ + LIBPATH=$$DIR/lib/$$($(HOSTCXX) -print-multi-os-directory); \ + if [ -f $$LIBPATH/libqt-mt.so ]; then LIB=qt-mt; fi; \ + fi; \ echo "QTDIR=$$DIR" > $@; echo "QTLIBPATH=$$LIBPATH" >> $@; \ - echo "QTLIB=$$LIB" >> $@; \ + echo "LIBS_QT=$$LIB" >> $@; \ if [ ! -x $$DIR/bin/moc -a -x /usr/bin/moc ]; then \ echo "*"; \ echo "* Unable to find $$DIR/bin/moc, using /usr/bin/moc instead."; \ -- cgit v1.2.3 From 8459c159f7de832eaf888398d2abf466c388dfa6 Mon Sep 17 00:00:00 2001 From: Dirk Opfer Date: Sun, 6 Nov 2005 14:27:52 +0000 Subject: [ARM] 3088/1: PXA: Add machine support for the Sharp SL-6000x series of PDAs Patch from Dirk Opfer This patch adds basic machine support for the Sharp SL-6000x (Tosa) PDAs. Signed-off-by: Dirk Opfer Signed-off-by: Richard Purdie Signed-off-by: Russell King --- MAINTAINERS | 5 ++ arch/arm/mach-pxa/Kconfig | 9 ++- arch/arm/mach-pxa/Makefile | 1 + arch/arm/mach-pxa/tosa.c | 162 +++++++++++++++++++++++++++++++++++++++ include/asm-arm/arch-pxa/tosa.h | 166 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 341 insertions(+), 2 deletions(-) create mode 100644 arch/arm/mach-pxa/tosa.c create mode 100644 include/asm-arm/arch-pxa/tosa.h diff --git a/MAINTAINERS b/MAINTAINERS index 983f9e9aed6..23337f88c50 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -297,6 +297,11 @@ P: Richard Purdie M: rpurdie@rpsys.net S: Maintained +ARM/TOSA MACHINE SUPPORT +P: Dirk Opfer +M: dirk@opfer-online.de +S: Maintained + ARM/PLEB SUPPORT P: Peter Chubb M: pleb@gelato.unsw.edu.au diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 3e5f69bb5ac..b380a438e68 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -27,7 +27,8 @@ config PXA_SHARPSL Say Y here if you intend to run this kernel on a Sharp Zaurus SL-5600 (Poodle), SL-C700 (Corgi), SL-C750 (Shepherd), SL-C760 (Husky), SL-C1000 (Akita), - SL-C3000 (Spitz) or SL-C3100 (Borzoi) handheld computer. + SL-C3000 (Spitz), SL-C3100 (Borzoi) or SL-C6000x (Tosa) + handheld computer. endchoice @@ -37,7 +38,7 @@ choice prompt "Select target Sharp Zaurus device range" config PXA_SHARPSL_25x - bool "Sharp PXA25x models (SL-5600 and SL-C7xx)" + bool "Sharp PXA25x models (SL-5600, SL-C7xx and SL-C6000x)" select PXA25x config PXA_SHARPSL_27x @@ -80,6 +81,10 @@ config MACH_BORZOI depends PXA_SHARPSL_27x select PXA_SHARP_Cxx00 +config MACH_TOSA + bool "Enable Sharp SL-6000x (Tosa) Support" + depends PXA_SHARPSL + config PXA25x bool help diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index f609a0f232c..8bc72d07cea 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_ARCH_PXA_IDP) += idp.o obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o ssp.o obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o ssp.o obj-$(CONFIG_MACH_POODLE) += poodle.o +obj-$(CONFIG_MACH_TOSA) += tosa.o # Support for blinky lights led-y := leds.o diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c new file mode 100644 index 00000000000..400609f8b6a --- /dev/null +++ b/arch/arm/mach-pxa/tosa.c @@ -0,0 +1,162 @@ +/* + * Support for Sharp SL-C6000x PDAs + * Model: (Tosa) + * + * Copyright (c) 2005 Dirk Opfer + * + * Based on code written by Sharp/Lineo for 2.4 kernels + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "generic.h" + + +/* + * SCOOP Device + */ +static struct resource tosa_scoop_resources[] = { + [0] = { + .start = TOSA_CF_PHYS, + .end = TOSA_CF_PHYS + 0xfff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct scoop_config tosa_scoop_setup = { + .io_dir = TOSA_SCOOP_IO_DIR, + .io_out = TOSA_SCOOP_IO_OUT, + +}; + +struct platform_device tosascoop_device = { + .name = "sharp-scoop", + .id = 0, + .dev = { + .platform_data = &tosa_scoop_setup, + }, + .num_resources = ARRAY_SIZE(tosa_scoop_resources), + .resource = tosa_scoop_resources, +}; + + +/* + * SCOOP Device Jacket + */ +static struct resource tosa_scoop_jc_resources[] = { + [0] = { + .start = TOSA_SCOOP_PHYS + 0x40, + .end = TOSA_SCOOP_PHYS + 0xfff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct scoop_config tosa_scoop_jc_setup = { + .io_dir = TOSA_SCOOP_JC_IO_DIR, + .io_out = TOSA_SCOOP_JC_IO_OUT, +}; + +struct platform_device tosascoop_jc_device = { + .name = "sharp-scoop", + .id = 1, + .dev = { + .platform_data = &tosa_scoop_jc_setup, + .parent = &tosascoop_device.dev, + }, + .num_resources = ARRAY_SIZE(tosa_scoop_jc_resources), + .resource = tosa_scoop_jc_resources, +}; + +static struct scoop_pcmcia_dev tosa_pcmcia_scoop[] = { +{ + .dev = &tosascoop_device.dev, + .irq = TOSA_IRQ_GPIO_CF_IRQ, + .cd_irq = TOSA_IRQ_GPIO_CF_CD, + .cd_irq_str = "PCMCIA0 CD", +},{ + .dev = &tosascoop_jc_device.dev, + .irq = TOSA_IRQ_GPIO_JC_CF_IRQ, + .cd_irq = -1, +}, +}; + + +static struct platform_device *devices[] __initdata = { + &tosascoop_device, + &tosascoop_jc_device, +}; + +static void __init tosa_init(void) +{ + pxa_gpio_mode(TOSA_GPIO_ON_RESET | GPIO_IN); + pxa_gpio_mode(TOSA_GPIO_TC6393_INT | GPIO_IN); + + /* setup sleep mode values */ + PWER = 0x00000002; + PFER = 0x00000000; + PRER = 0x00000002; + PGSR0 = 0x00000000; + PGSR1 = 0x00FF0002; + PGSR2 = 0x00014000; + PCFR |= PCFR_OPDE; + + // enable batt_fault + PMCR = 0x01; + + platform_add_devices(devices, ARRAY_SIZE(devices)); + + scoop_num = 2; + scoop_devs = &tosa_pcmcia_scoop[0]; +} + +static void __init fixup_tosa(struct machine_desc *desc, + struct tag *tags, char **cmdline, struct meminfo *mi) +{ + sharpsl_save_param(); + mi->nr_banks=1; + mi->bank[0].start = 0xa0000000; + mi->bank[0].node = 0; + mi->bank[0].size = (64*1024*1024); +} + +MACHINE_START(TOSA, "SHARP Tosa") + .phys_ram = 0xa0000000, + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .fixup = fixup_tosa, + .map_io = pxa_map_io, + .init_irq = pxa_init_irq, + .init_machine = tosa_init, + .timer = &pxa_timer, +MACHINE_END diff --git a/include/asm-arm/arch-pxa/tosa.h b/include/asm-arm/arch-pxa/tosa.h new file mode 100644 index 00000000000..c3364a2c475 --- /dev/null +++ b/include/asm-arm/arch-pxa/tosa.h @@ -0,0 +1,166 @@ +/* + * Hardware specific definitions for Sharp SL-C6000x series of PDAs + * + * Copyright (c) 2005 Dirk Opfer + * + * Based on Sharp's 2.4 kernel patches + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#ifndef _ASM_ARCH_TOSA_H_ +#define _ASM_ARCH_TOSA_H_ 1 + +/* TOSA Chip selects */ +#define TOSA_LCDC_PHYS PXA_CS4_PHYS +/* Internel Scoop */ +#define TOSA_CF_PHYS (PXA_CS2_PHYS + 0x00800000) +/* Jacket Scoop */ +#define TOSA_SCOOP_PHYS (PXA_CS5_PHYS + 0x00800000) + +/* + * SCOOP2 internal GPIOs + */ +#define TOSA_SCOOP_PXA_VCORE1 SCOOP_GPCR_PA11 +#define TOSA_SCOOP_TC6393_REST_IN SCOOP_GPCR_PA12 +#define TOSA_SCOOP_IR_POWERDWN SCOOP_GPCR_PA13 +#define TOSA_SCOOP_SD_WP SCOOP_GPCR_PA14 +#define TOSA_SCOOP_PWR_ON SCOOP_GPCR_PA15 +#define TOSA_SCOOP_AUD_PWR_ON SCOOP_GPCR_PA16 +#define TOSA_SCOOP_BT_RESET SCOOP_GPCR_PA17 +#define TOSA_SCOOP_BT_PWR_EN SCOOP_GPCR_PA18 +#define TOSA_SCOOP_AC_IN_OL SCOOP_GPCR_PA19 + +/* GPIO Direction 1 : output mode / 0:input mode */ +#define TOSA_SCOOP_IO_DIR ( TOSA_SCOOP_PXA_VCORE1 | TOSA_SCOOP_TC6393_REST_IN | \ + TOSA_SCOOP_IR_POWERDWN | TOSA_SCOOP_PWR_ON | TOSA_SCOOP_AUD_PWR_ON |\ + TOSA_SCOOP_BT_RESET | TOSA_SCOOP_BT_PWR_EN ) +/* GPIO out put level when init 1: Hi */ +#define TOSA_SCOOP_IO_OUT ( TOSA_SCOOP_TC6393_REST_IN ) + +/* + * SCOOP2 jacket GPIOs + */ +#define TOSA_SCOOP_JC_BT_LED SCOOP_GPCR_PA11 +#define TOSA_SCOOP_JC_NOTE_LED SCOOP_GPCR_PA12 +#define TOSA_SCOOP_JC_CHRG_ERR_LED SCOOP_GPCR_PA13 +#define TOSA_SCOOP_JC_USB_PULLUP SCOOP_GPCR_PA14 +#define TOSA_SCOOP_JC_TC6393_SUSPEND SCOOP_GPCR_PA15 +#define TOSA_SCOOP_JC_TC3693_L3V_ON SCOOP_GPCR_PA16 +#define TOSA_SCOOP_JC_WLAN_DETECT SCOOP_GPCR_PA17 +#define TOSA_SCOOP_JC_WLAN_LED SCOOP_GPCR_PA18 +#define TOSA_SCOOP_JC_CARD_LIMIT_SEL SCOOP_GPCR_PA19 + +/* GPIO Direction 1 : output mode / 0:input mode */ +#define TOSA_SCOOP_JC_IO_DIR ( TOSA_SCOOP_JC_BT_LED | TOSA_SCOOP_JC_NOTE_LED | \ + TOSA_SCOOP_JC_CHRG_ERR_LED | TOSA_SCOOP_JC_USB_PULLUP | \ + TOSA_SCOOP_JC_TC6393_SUSPEND | TOSA_SCOOP_JC_TC3693_L3V_ON | \ + TOSA_SCOOP_JC_WLAN_LED | TOSA_SCOOP_JC_CARD_LIMIT_SEL ) +/* GPIO out put level when init 1: Hi */ +#define TOSA_SCOOP_JC_IO_OUT ( 0 ) + +/* + * Timing Generator + */ +#define TG_PNLCTL 0x00 +#define TG_TPOSCTL 0x01 +#define TG_DUTYCTL 0x02 +#define TG_GPOSR 0x03 +#define TG_GPODR1 0x04 +#define TG_GPODR2 0x05 +#define TG_PINICTL 0x06 +#define TG_HPOSCTL 0x07 + +/* + * LED + */ +#define TOSA_SCOOP_LED_BLUE TOSA_SCOOP_GPCR_PA11 +#define TOSA_SCOOP_LED_GREEN TOSA_SCOOP_GPCR_PA12 +#define TOSA_SCOOP_LED_ORANGE TOSA_SCOOP_GPCR_PA13 +#define TOSA_SCOOP_LED_WLAN TOSA_SCOOP_GPCR_PA18 + + +/* + * PXA GPIOs + */ +#define TOSA_GPIO_POWERON (0) +#define TOSA_GPIO_RESET (1) +#define TOSA_GPIO_AC_IN (2) +#define TOSA_GPIO_RECORD_BTN (3) +#define TOSA_GPIO_SYNC (4) /* Cradle SYNC Button */ +#define TOSA_GPIO_USB_IN (5) +#define TOSA_GPIO_JACKET_DETECT (7) +#define TOSA_GPIO_nSD_DETECT (9) +#define TOSA_GPIO_nSD_INT (10) +#define TOSA_GPIO_TC6393_CLK (11) +#define TOSA_GPIO_BAT1_CRG (12) +#define TOSA_GPIO_CF_CD (13) +#define TOSA_GPIO_BAT0_CRG (14) +#define TOSA_GPIO_TC6393_INT (15) +#define TOSA_GPIO_BAT0_LOW (17) +#define TOSA_GPIO_TC6393_RDY (18) +#define TOSA_GPIO_ON_RESET (19) +#define TOSA_GPIO_EAR_IN (20) +#define TOSA_GPIO_CF_IRQ (21) /* CF slot0 Ready */ +#define TOSA_GPIO_ON_KEY (22) +#define TOSA_GPIO_VGA_LINE (27) +#define TOSA_GPIO_TP_INT (32) /* Touch Panel pen down interrupt */ +#define TOSA_GPIO_JC_CF_IRQ (36) /* CF slot1 Ready */ +#define TOSA_GPIO_BAT_LOCKED (38) /* Battery locked */ +#define TOSA_GPIO_TG_SPI_SCLK (81) +#define TOSA_GPIO_TG_SPI_CS (82) +#define TOSA_GPIO_TG_SPI_MOSI (83) +#define TOSA_GPIO_BAT1_LOW (84) + +#define TOSA_GPIO_HP_IN GPIO_EAR_IN + +#define TOSA_GPIO_MAIN_BAT_LOW GPIO_BAT0_LOW + +#define TOSA_KEY_STROBE_NUM (11) +#define TOSA_KEY_SENSE_NUM (7) + +#define TOSA_GPIO_HIGH_STROBE_BIT (0xfc000000) +#define TOSA_GPIO_LOW_STROBE_BIT (0x0000001f) +#define TOSA_GPIO_ALL_SENSE_BIT (0x00000fe0) +#define TOSA_GPIO_ALL_SENSE_RSHIFT (5) +#define TOSA_GPIO_STROBE_BIT(a) GPIO_bit(58+(a)) +#define TOSA_GPIO_SENSE_BIT(a) GPIO_bit(69+(a)) +#define TOSA_GAFR_HIGH_STROBE_BIT (0xfff00000) +#define TOSA_GAFR_LOW_STROBE_BIT (0x000003ff) +#define TOSA_GAFR_ALL_SENSE_BIT (0x00fffc00) +#define TOSA_GPIO_KEY_SENSE(a) (69+(a)) +#define TOSA_GPIO_KEY_STROBE(a) (58+(a)) + +/* + * Interrupts + */ +#define TOSA_IRQ_GPIO_WAKEUP IRQ_GPIO(TOSA_GPIO_WAKEUP) +#define TOSA_IRQ_GPIO_AC_IN IRQ_GPIO(TOSA_GPIO_AC_IN) +#define TOSA_IRQ_GPIO_RECORD_BTN IRQ_GPIO(TOSA_GPIO_RECORD_BTN) +#define TOSA_IRQ_GPIO_SYNC IRQ_GPIO(TOSA_GPIO_SYNC) +#define TOSA_IRQ_GPIO_USB_IN IRQ_GPIO(TOSA_GPIO_USB_IN) +#define TOSA_IRQ_GPIO_JACKET_DETECT IRQ_GPIO(TOSA_GPIO_JACKET_DETECT) +#define TOSA_IRQ_GPIO_nSD_INT IRQ_GPIO(TOSA_GPIO_nSD_INT) +#define TOSA_IRQ_GPIO_nSD_DETECT IRQ_GPIO(TOSA_GPIO_nSD_DETECT) +#define TOSA_IRQ_GPIO_BAT1_CRG IRQ_GPIO(TOSA_GPIO_BAT1_CRG) +#define TOSA_IRQ_GPIO_CF_CD IRQ_GPIO(TOSA_GPIO_CF_CD) +#define TOSA_IRQ_GPIO_BAT0_CRG IRQ_GPIO(TOSA_GPIO_BAT0_CRG) +#define TOSA_IRQ_GPIO_TC6393_INT IRQ_GPIO(TOSA_GPIO_TC6393_INT) +#define TOSA_IRQ_GPIO_BAT0_LOW IRQ_GPIO(TOSA_GPIO_BAT0_LOW) +#define TOSA_IRQ_GPIO_EAR_IN IRQ_GPIO(TOSA_GPIO_EAR_IN) +#define TOSA_IRQ_GPIO_CF_IRQ IRQ_GPIO(TOSA_GPIO_CF_IRQ) +#define TOSA_IRQ_GPIO_ON_KEY IRQ_GPIO(TOSA_GPIO_ON_KEY) +#define TOSA_IRQ_GPIO_VGA_LINE IRQ_GPIO(TOSA_GPIO_VGA_LINE) +#define TOSA_IRQ_GPIO_TP_INT IRQ_GPIO(TOSA_GPIO_TP_INT) +#define TOSA_IRQ_GPIO_JC_CF_IRQ IRQ_GPIO(TOSA_GPIO_JC_CF_IRQ) +#define TOSA_IRQ_GPIO_BAT_LOCKED IRQ_GPIO(TOSA_GPIO_BAT_LOCKED) +#define TOSA_IRQ_GPIO_BAT1_LOW IRQ_GPIO(TOSA_GPIO_BAT1_LOW) +#define TOSA_IRQ_GPIO_KEY_SENSE(a) IRQ_GPIO(69+(a)) + +#define TOSA_IRQ_GPIO_MAIN_BAT_LOW IRQ_GPIO(TOSA_GPIO_MAIN_BAT_LOW) + +extern struct platform_device tosascoop_jc_device; +extern struct platform_device tosascoop_device; +#endif /* _ASM_ARCH_TOSA_H_ */ -- cgit v1.2.3 From 84613387cb60bc760a4588822cd61fb88e1d7fad Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Sun, 6 Nov 2005 14:34:12 +0000 Subject: [ARM] 3089/1: ixp4xx AHB/PCI endianness fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch from Alessandro Zummo This patch fixes AHB/PCI endianness problems when the processor is in little-endian mode. The patch configures the CSR register closely following the directives in [1], paragraph 4.1, page 19. According to the considerations in [1], page 11, while the AHB bus supports both endian modes, on the IXP4XX it always uses big-endian. The PCI bus is connected to the South AHB. A wrong setting in the CSR register will thus cause a malfunctional PCI bus. A schematic diagram of the bus interconnections on the IXP4XX can be found in [1], page 18. The patch has been verified to work on the NSLU2 in both LE and BE modes. The author is Peter Korsgaard. [1] Intel® IXP4XX Product Line of Network Processors and IXC1100 Control Plane Processor: Understanding Big Endian and Little Endian Modes http://www.intel.com/design/network/applnots/25423701.pdf Signed-off-by: Alessandro Zummo Signed-off-by: Deepak Saxena Signed-off-by: Russell King --- arch/arm/mach-ixp4xx/common-pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c index 2b544363c07..9795da270e3 100644 --- a/arch/arm/mach-ixp4xx/common-pci.c +++ b/arch/arm/mach-ixp4xx/common-pci.c @@ -427,7 +427,7 @@ void __init ixp4xx_pci_preinit(void) #ifdef __ARMEB__ *PCI_CSR = PCI_CSR_IC | PCI_CSR_ABE | PCI_CSR_PDS | PCI_CSR_ADS; #else - *PCI_CSR = PCI_CSR_IC; + *PCI_CSR = PCI_CSR_IC | PCI_CSR_ABE; #endif pr_debug("DONE\n"); -- cgit v1.2.3 From 7240f1f183f085f6b7af44ec274b5b6123dfdead Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sun, 6 Nov 2005 14:34:13 +0000 Subject: [ARM] 3114/1: use ixp2000_reg_wrb in ixp2000 uengine loader Patch from Lennert Buytenhek Make the uengine loader use ixp2000_reg_wrb in the right places. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- arch/arm/mach-ixp2000/uengine.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-ixp2000/uengine.c b/arch/arm/mach-ixp2000/uengine.c index 43e234349d4..ec4e007a22e 100644 --- a/arch/arm/mach-ixp2000/uengine.c +++ b/arch/arm/mach-ixp2000/uengine.c @@ -91,8 +91,8 @@ EXPORT_SYMBOL(ixp2000_uengine_csr_write); void ixp2000_uengine_reset(u32 uengine_mask) { - ixp2000_reg_write(IXP2000_RESET1, uengine_mask & ixp2000_uengine_mask); - ixp2000_reg_write(IXP2000_RESET1, 0); + ixp2000_reg_wrb(IXP2000_RESET1, uengine_mask & ixp2000_uengine_mask); + ixp2000_reg_wrb(IXP2000_RESET1, 0); } EXPORT_SYMBOL(ixp2000_uengine_reset); @@ -452,21 +452,20 @@ static int __init ixp2000_uengine_init(void) /* * Reset microengines. */ - ixp2000_reg_write(IXP2000_RESET1, ixp2000_uengine_mask); - ixp2000_reg_write(IXP2000_RESET1, 0); + ixp2000_uengine_reset(ixp2000_uengine_mask); /* * Synchronise timestamp counters across all microengines. */ value = ixp2000_reg_read(IXP2000_MISC_CONTROL); - ixp2000_reg_write(IXP2000_MISC_CONTROL, value & ~0x80); + ixp2000_reg_wrb(IXP2000_MISC_CONTROL, value & ~0x80); for (uengine = 0; uengine < 32; uengine++) { if (ixp2000_uengine_mask & (1 << uengine)) { ixp2000_uengine_csr_write(uengine, TIMESTAMP_LOW, 0); ixp2000_uengine_csr_write(uengine, TIMESTAMP_HIGH, 0); } } - ixp2000_reg_write(IXP2000_MISC_CONTROL, value | 0x80); + ixp2000_reg_wrb(IXP2000_MISC_CONTROL, value | 0x80); return 0; } -- cgit v1.2.3 From dae6227f71fedb40b2478d3062397d3ab54e7556 Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Fri, 15 Jul 2005 11:13:57 +0100 Subject: [JFFS2] Split a large routine on several smaller. Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/nodelist.c | 597 +++++++++++++++++++++++++++++----------------------- 1 file changed, 336 insertions(+), 261 deletions(-) diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 4991c348f6e..a04111530f4 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.c,v 1.98 2005/07/10 15:15:32 dedekind Exp $ + * $Id: nodelist.c,v 1.99 2005/07/15 10:13:54 dedekind Exp $ * */ @@ -137,6 +137,307 @@ static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_r return NULL; } +/* + * Helper function for jffs2_get_inode_nodes(). + * It is called every time an directory entry node is found. + * + * Returns: 0 on succes; + * 1 if the node should be marked obsolete; + * negative error code on failure. + */ +static inline int +read_direntry(struct jffs2_sb_info *c, + struct jffs2_raw_node_ref *ref, + struct jffs2_raw_dirent *rd, + uint32_t read, + struct jffs2_full_dirent **fdp, + int32_t *latest_mctime, + uint32_t *mctime_ver) +{ + struct jffs2_full_dirent *fd; + + /* The direntry nodes are checked during the flash scanning */ + BUG_ON(ref_flags(ref) == REF_UNCHECKED); + /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ + BUG_ON(ref_obsolete(ref)); + + /* Sanity check */ + if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) { + printk(KERN_ERR "Error! Illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n", + ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen)); + return 1; + } + + fd = jffs2_alloc_full_dirent(rd->nsize + 1); + if (unlikely(!fd)) + return -ENOMEM; + + fd->raw = ref; + fd->version = je32_to_cpu(rd->version); + fd->ino = je32_to_cpu(rd->ino); + fd->type = rd->type; + + /* Pick out the mctime of the latest dirent */ + if(fd->version > *mctime_ver) { + *mctime_ver = fd->version; + *latest_mctime = je32_to_cpu(rd->mctime); + } + + /* + * Copy as much of the name as possible from the raw + * dirent we've already read from the flash. + */ + if (read > sizeof(*rd)) + memcpy(&fd->name[0], &rd->name[0], + min_t(uint32_t, rd->nsize, (read - sizeof(*rd)) )); + + /* Do we need to copy any more of the name directly from the flash? */ + if (rd->nsize + sizeof(*rd) > read) { + /* FIXME: point() */ + int err; + int already = read - sizeof(*rd); + + err = jffs2_flash_read(c, (ref_offset(ref)) + read, + rd->nsize - already, &read, &fd->name[already]); + if (unlikely(read != rd->nsize - already) && likely(!err)) + return -EIO; + + if (unlikely(err)) { + printk(KERN_WARNING "Read remainder of name in jffs2_get_inode_nodes(): error %d\n", err); + jffs2_free_full_dirent(fd); + return -EIO; + } + } + + fd->nhash = full_name_hash(fd->name, rd->nsize); + fd->next = NULL; + fd->name[rd->nsize] = '\0'; + + /* + * Wheee. We now have a complete jffs2_full_dirent structure, with + * the name in it and everything. Link it into the list + */ + D1(printk(KERN_DEBUG "Adding fd \"%s\", ino #%u\n", fd->name, fd->ino)); + + jffs2_add_fd_to_list(c, fd, fdp); + + return 0; +} + +/* + * Helper function for jffs2_get_inode_nodes(). + * It is called every time an inode node is found. + * + * Returns: 0 on succes; + * 1 if the node should be marked obsolete; + * negative error code on failure. + */ +static inline int +read_dnode(struct jffs2_sb_info *c, + struct jffs2_raw_node_ref *ref, + struct jffs2_raw_inode *rd, + uint32_t read, + struct rb_root *tnp, + int32_t *latest_mctime, + uint32_t *mctime_ver) +{ + struct jffs2_eraseblock *jeb; + struct jffs2_tmp_dnode_info *tn; + + /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ + BUG_ON(ref_obsolete(ref)); + + /* If we've never checked the CRCs on this node, check them now */ + if (ref_flags(ref) == REF_UNCHECKED) { + uint32_t crc, len; + + crc = crc32(0, rd, sizeof(*rd) - 8); + if (unlikely(crc != je32_to_cpu(rd->node_crc))) { + printk(KERN_WARNING "Header CRC failed on node at %#08x: read %#08x, calculated %#08x\n", + ref_offset(ref), je32_to_cpu(rd->node_crc), crc); + return 1; + } + + /* Sanity checks */ + if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) || + unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) { + printk(KERN_WARNING "Inode corrupted at %#08x, totlen %d, #ino %d, version %d, " + "isize %d, csize %d, dsize %d \n", + ref_offset(ref), je32_to_cpu(rd->totlen), je32_to_cpu(rd->ino), + je32_to_cpu(rd->version), je32_to_cpu(rd->isize), + je32_to_cpu(rd->csize), je32_to_cpu(rd->dsize)); + return 1; + } + + if (rd->compr != JFFS2_COMPR_ZERO && je32_to_cpu(rd->csize)) { + unsigned char *buf = NULL; + uint32_t pointed = 0; + int err; +#ifndef __ECOS + if (c->mtd->point) { + err = c->mtd->point (c->mtd, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize), + &read, &buf); + if (unlikely(read < je32_to_cpu(rd->csize)) && likely(!err)) { + D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", read)); + c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(*rd), + je32_to_cpu(rd->csize)); + } else if (unlikely(err)){ + D1(printk(KERN_DEBUG "MTD point failed %d\n", err)); + } else + pointed = 1; /* succefully pointed to device */ + } +#endif + if(!pointed){ + buf = kmalloc(je32_to_cpu(rd->csize), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + err = jffs2_flash_read(c, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize), + &read, buf); + if (unlikely(read != je32_to_cpu(rd->csize)) && likely(!err)) + err = -EIO; + if (err) { + kfree(buf); + return err; + } + } + crc = crc32(0, buf, je32_to_cpu(rd->csize)); + if(!pointed) + kfree(buf); +#ifndef __ECOS + else + c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize)); +#endif + + if (crc != je32_to_cpu(rd->data_crc)) { + printk(KERN_NOTICE "Data CRC failed on node at %#08x: read %#08x, calculated %#08x\n", + ref_offset(ref), je32_to_cpu(rd->data_crc), crc); + return 1; + } + + } + + /* Mark the node as having been checked and fix the accounting accordingly */ + jeb = &c->blocks[ref->flash_offset / c->sector_size]; + len = ref_totlen(c, jeb, ref); + + spin_lock(&c->erase_completion_lock); + jeb->used_size += len; + jeb->unchecked_size -= len; + c->used_size += len; + c->unchecked_size -= len; + + /* If node covers at least a whole page, or if it starts at the + beginning of a page and runs to the end of the file, or if + it's a hole node, mark it REF_PRISTINE, else REF_NORMAL. + + If it's actually overlapped, it'll get made NORMAL (or OBSOLETE) + when the overlapping node(s) get added to the tree anyway. + */ + if ((je32_to_cpu(rd->dsize) >= PAGE_CACHE_SIZE) || + ( ((je32_to_cpu(rd->offset) & (PAGE_CACHE_SIZE-1))==0) && + (je32_to_cpu(rd->dsize) + je32_to_cpu(rd->offset) == je32_to_cpu(rd->isize)))) { + D1(printk(KERN_DEBUG "Marking node at %#08x REF_PRISTINE\n", ref_offset(ref))); + ref->flash_offset = ref_offset(ref) | REF_PRISTINE; + } else { + D1(printk(KERN_DEBUG "Marking node at %#08x REF_NORMAL\n", ref_offset(ref))); + ref->flash_offset = ref_offset(ref) | REF_NORMAL; + } + spin_unlock(&c->erase_completion_lock); + } + + tn = jffs2_alloc_tmp_dnode_info(); + if (!tn) { + D1(printk(KERN_DEBUG "alloc tn failed\n")); + return -ENOMEM; + } + + tn->fn = jffs2_alloc_full_dnode(); + if (!tn->fn) { + D1(printk(KERN_DEBUG "alloc fn failed\n")); + jffs2_free_tmp_dnode_info(tn); + return -ENOMEM; + } + + tn->version = je32_to_cpu(rd->version); + tn->fn->ofs = je32_to_cpu(rd->offset); + tn->fn->raw = ref; + + /* There was a bug where we wrote hole nodes out with + csize/dsize swapped. Deal with it */ + if (rd->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(rd->dsize) && je32_to_cpu(rd->csize)) + tn->fn->size = je32_to_cpu(rd->csize); + else // normal case... + tn->fn->size = je32_to_cpu(rd->dsize); + + D1(printk(KERN_DEBUG "dnode @%08x: ver %u, offset %#04x, dsize %#04x\n", + ref_offset(ref), je32_to_cpu(rd->version), + je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize))); + + jffs2_add_tn_to_tree(tn, tnp); + + return 0; +} + +/* + * Helper function for jffs2_get_inode_nodes(). + * It is called every time an unknown node is found. + * + * Returns: 0 on succes; + * 1 if the node should be marked obsolete; + * negative error code on failure. + */ +static inline int +read_unknown(struct jffs2_sb_info *c, + struct jffs2_raw_node_ref *ref, + struct jffs2_unknown_node *un, + uint32_t read) +{ + /* We don't mark unknown nodes as REF_UNCHECKED */ + BUG_ON(ref_flags(ref) == REF_UNCHECKED); + + un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype)); + + if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) { + + /* Hmmm. This should have been caught at scan time. */ + printk(KERN_WARNING "Warning! Node header CRC failed at %#08x. " + "But it must have been OK earlier.\n", ref_offset(ref)); + D1(printk(KERN_DEBUG "Node was: { %#04x, %#04x, %#08x, %#08x }\n", + je16_to_cpu(un->magic), je16_to_cpu(un->nodetype), + je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc))); + return 1; + } else { + switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) { + + case JFFS2_FEATURE_INCOMPAT: + printk(KERN_NOTICE "Unknown INCOMPAT nodetype %#04X at %#08x\n", + je16_to_cpu(un->nodetype), ref_offset(ref)); + /* EEP */ + BUG(); + break; + + case JFFS2_FEATURE_ROCOMPAT: + printk(KERN_NOTICE "Unknown ROCOMPAT nodetype %#04X at %#08x\n", + je16_to_cpu(un->nodetype), ref_offset(ref)); + BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO)); + break; + + case JFFS2_FEATURE_RWCOMPAT_COPY: + printk(KERN_NOTICE "Unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n", + je16_to_cpu(un->nodetype), ref_offset(ref)); + break; + + case JFFS2_FEATURE_RWCOMPAT_DELETE: + printk(KERN_NOTICE "Unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n", + je16_to_cpu(un->nodetype), ref_offset(ref)); + return 1; + } + } + + return 0; +} + /* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated with this ino, returning the former in order of version */ @@ -146,9 +447,8 @@ int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t *mctime_ver) { struct jffs2_raw_node_ref *ref, *valid_ref; - struct jffs2_tmp_dnode_info *tn; struct rb_root ret_tn = RB_ROOT; - struct jffs2_full_dirent *fd, *ret_fd = NULL; + struct jffs2_full_dirent *ret_fd = NULL; union jffs2_node_union node; size_t retlen; int err; @@ -186,292 +486,67 @@ int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f, goto free_out; } - - /* Check we've managed to read at least the common node header */ - if (retlen < min_t(uint32_t, ref_totlen(c, NULL, ref), sizeof(node.u))) { - printk(KERN_WARNING "short read in get_inode_nodes()\n"); - err = -EIO; - goto free_out; - } - switch (je16_to_cpu(node.u.nodetype)) { + case JFFS2_NODETYPE_DIRENT: D1(printk(KERN_DEBUG "Node at %08x (%d) is a dirent node\n", ref_offset(ref), ref_flags(ref))); - if (ref_flags(ref) == REF_UNCHECKED) { - printk(KERN_WARNING "BUG: Dirent node at 0x%08x never got checked? How?\n", ref_offset(ref)); - BUG(); - } + if (retlen < sizeof(node.d)) { - printk(KERN_WARNING "short read in get_inode_nodes()\n"); + printk(KERN_WARNING "Warning! Short read dirent at %#08x\n", ref_offset(ref)); err = -EIO; goto free_out; } - /* sanity check */ - if (PAD((node.d.nsize + sizeof (node.d))) != PAD(je32_to_cpu (node.d.totlen))) { - printk(KERN_NOTICE "jffs2_get_inode_nodes(): Illegal nsize in node at 0x%08x: nsize 0x%02x, totlen %04x\n", - ref_offset(ref), node.d.nsize, je32_to_cpu(node.d.totlen)); + + err = read_direntry(c, ref, &node.d, retlen, &ret_fd, latest_mctime, mctime_ver); + if (err == 1) { jffs2_mark_node_obsolete(c, ref); - spin_lock(&c->erase_completion_lock); - continue; - } + break; + } else if (unlikely(err)) + goto free_out; + if (je32_to_cpu(node.d.version) > *highest_version) *highest_version = je32_to_cpu(node.d.version); - if (ref_obsolete(ref)) { - /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ - printk(KERN_ERR "Dirent node at 0x%08x became obsolete while we weren't looking\n", - ref_offset(ref)); - BUG(); - } - - fd = jffs2_alloc_full_dirent(node.d.nsize+1); - if (!fd) { - err = -ENOMEM; - goto free_out; - } - fd->raw = ref; - fd->version = je32_to_cpu(node.d.version); - fd->ino = je32_to_cpu(node.d.ino); - fd->type = node.d.type; - - /* Pick out the mctime of the latest dirent */ - if(fd->version > *mctime_ver) { - *mctime_ver = fd->version; - *latest_mctime = je32_to_cpu(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_t(uint32_t, node.d.nsize, (retlen-sizeof(struct jffs2_raw_dirent)))); - - /* Do we need to copy any more of the name directly - from the flash? - */ - if (node.d.nsize + sizeof(struct jffs2_raw_dirent) > retlen) { - /* FIXME: point() */ - int already = retlen - sizeof(struct jffs2_raw_dirent); - - err = jffs2_flash_read(c, (ref_offset(ref)) + retlen, - node.d.nsize - already, &retlen, &fd->name[already]); - if (!err && retlen != node.d.nsize - already) - err = -EIO; - - if (err) { - printk(KERN_WARNING "Read remainder of name in jffs2_get_inode_nodes(): error %d\n", err); - jffs2_free_full_dirent(fd); - goto free_out; - } - } - fd->nhash = full_name_hash(fd->name, node.d.nsize); - fd->next = NULL; - fd->name[node.d.nsize] = '\0'; - /* Wheee. We now have a complete jffs2_full_dirent structure, with - the name in it and everything. Link it into the list - */ - D1(printk(KERN_DEBUG "Adding fd \"%s\", ino #%u\n", fd->name, fd->ino)); - jffs2_add_fd_to_list(c, fd, &ret_fd); break; case JFFS2_NODETYPE_INODE: D1(printk(KERN_DEBUG "Node at %08x (%d) is a data node\n", ref_offset(ref), ref_flags(ref))); + if (retlen < sizeof(node.i)) { - printk(KERN_WARNING "read too short for dnode\n"); + printk(KERN_WARNING "Warning! Short read dnode at %#08x\n", ref_offset(ref)); err = -EIO; goto free_out; } - if (je32_to_cpu(node.i.version) > *highest_version) - *highest_version = je32_to_cpu(node.i.version); - D1(printk(KERN_DEBUG "version %d, highest_version now %d\n", je32_to_cpu(node.i.version), *highest_version)); - - if (ref_obsolete(ref)) { - /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ - printk(KERN_ERR "Inode node at 0x%08x became obsolete while we weren't looking\n", - ref_offset(ref)); - BUG(); - } - - /* If we've never checked the CRCs on this node, check them now. */ - if (ref_flags(ref) == REF_UNCHECKED) { - uint32_t crc, len; - struct jffs2_eraseblock *jeb; - - crc = crc32(0, &node, sizeof(node.i)-8); - if (crc != je32_to_cpu(node.i.node_crc)) { - printk(KERN_NOTICE "jffs2_get_inode_nodes(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", - ref_offset(ref), je32_to_cpu(node.i.node_crc), crc); - jffs2_mark_node_obsolete(c, ref); - spin_lock(&c->erase_completion_lock); - continue; - } - - /* sanity checks */ - if ( je32_to_cpu(node.i.offset) > je32_to_cpu(node.i.isize) || - PAD(je32_to_cpu(node.i.csize) + sizeof (node.i)) != PAD(je32_to_cpu(node.i.totlen))) { - printk(KERN_NOTICE "jffs2_get_inode_nodes(): Inode corrupted at 0x%08x, totlen %d, #ino %d, version %d, isize %d, csize %d, dsize %d \n", - ref_offset(ref), je32_to_cpu(node.i.totlen), je32_to_cpu(node.i.ino), - je32_to_cpu(node.i.version), je32_to_cpu(node.i.isize), - je32_to_cpu(node.i.csize), je32_to_cpu(node.i.dsize)); - jffs2_mark_node_obsolete(c, ref); - spin_lock(&c->erase_completion_lock); - continue; - } - if (node.i.compr != JFFS2_COMPR_ZERO && je32_to_cpu(node.i.csize)) { - unsigned char *buf=NULL; - uint32_t pointed = 0; -#ifndef __ECOS - if (c->mtd->point) { - err = c->mtd->point (c->mtd, ref_offset(ref) + sizeof(node.i), je32_to_cpu(node.i.csize), - &retlen, &buf); - if (!err && retlen < je32_to_cpu(node.i.csize)) { - D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", retlen)); - c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(node.i), je32_to_cpu(node.i.csize)); - } else if (err){ - D1(printk(KERN_DEBUG "MTD point failed %d\n", err)); - } else - pointed = 1; /* succefully pointed to device */ - } -#endif - if(!pointed){ - buf = kmalloc(je32_to_cpu(node.i.csize), GFP_KERNEL); - if (!buf) - return -ENOMEM; - - err = jffs2_flash_read(c, ref_offset(ref) + sizeof(node.i), je32_to_cpu(node.i.csize), - &retlen, buf); - if (!err && retlen != je32_to_cpu(node.i.csize)) - err = -EIO; - if (err) { - kfree(buf); - return err; - } - } - crc = crc32(0, buf, je32_to_cpu(node.i.csize)); - if(!pointed) - kfree(buf); -#ifndef __ECOS - else - c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(node.i), je32_to_cpu(node.i.csize)); -#endif - - if (crc != je32_to_cpu(node.i.data_crc)) { - printk(KERN_NOTICE "jffs2_get_inode_nodes(): Data CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", - ref_offset(ref), je32_to_cpu(node.i.data_crc), crc); - jffs2_mark_node_obsolete(c, ref); - spin_lock(&c->erase_completion_lock); - continue; - } - - } - - /* Mark the node as having been checked and fix the accounting accordingly */ - spin_lock(&c->erase_completion_lock); - jeb = &c->blocks[ref->flash_offset / c->sector_size]; - len = ref_totlen(c, jeb, ref); - - jeb->used_size += len; - jeb->unchecked_size -= len; - c->used_size += len; - c->unchecked_size -= len; - - /* If node covers at least a whole page, or if it starts at the - beginning of a page and runs to the end of the file, or if - it's a hole node, mark it REF_PRISTINE, else REF_NORMAL. - - If it's actually overlapped, it'll get made NORMAL (or OBSOLETE) - when the overlapping node(s) get added to the tree anyway. - */ - if ((je32_to_cpu(node.i.dsize) >= PAGE_CACHE_SIZE) || - ( ((je32_to_cpu(node.i.offset)&(PAGE_CACHE_SIZE-1))==0) && - (je32_to_cpu(node.i.dsize)+je32_to_cpu(node.i.offset) == je32_to_cpu(node.i.isize)))) { - D1(printk(KERN_DEBUG "Marking node at 0x%08x REF_PRISTINE\n", ref_offset(ref))); - ref->flash_offset = ref_offset(ref) | REF_PRISTINE; - } else { - D1(printk(KERN_DEBUG "Marking node at 0x%08x REF_NORMAL\n", ref_offset(ref))); - ref->flash_offset = ref_offset(ref) | REF_NORMAL; - } - spin_unlock(&c->erase_completion_lock); - } - - tn = jffs2_alloc_tmp_dnode_info(); - if (!tn) { - D1(printk(KERN_DEBUG "alloc tn failed\n")); - err = -ENOMEM; + err = read_dnode(c, ref, &node.i, retlen, &ret_tn, latest_mctime, mctime_ver); + if (err == 1) { + jffs2_mark_node_obsolete(c, ref); + break; + } else if (unlikely(err)) goto free_out; - } - tn->fn = jffs2_alloc_full_dnode(); - if (!tn->fn) { - D1(printk(KERN_DEBUG "alloc fn failed\n")); - err = -ENOMEM; - jffs2_free_tmp_dnode_info(tn); - goto free_out; - } - tn->version = je32_to_cpu(node.i.version); - tn->fn->ofs = je32_to_cpu(node.i.offset); - /* There was a bug where we wrote hole nodes out with - csize/dsize swapped. Deal with it */ - if (node.i.compr == JFFS2_COMPR_ZERO && !je32_to_cpu(node.i.dsize) && je32_to_cpu(node.i.csize)) - tn->fn->size = je32_to_cpu(node.i.csize); - else // normal case... - tn->fn->size = je32_to_cpu(node.i.dsize); - tn->fn->raw = ref; - D1(printk(KERN_DEBUG "dnode @%08x: ver %u, offset %04x, dsize %04x\n", - ref_offset(ref), je32_to_cpu(node.i.version), - je32_to_cpu(node.i.offset), je32_to_cpu(node.i.dsize))); - jffs2_add_tn_to_tree(tn, &ret_tn); + if (je32_to_cpu(node.i.version) > *highest_version) + *highest_version = je32_to_cpu(node.i.version); + + D1(printk(KERN_DEBUG "version %d, highest_version now %d\n", + je32_to_cpu(node.i.version), *highest_version)); + break; default: - if (ref_flags(ref) == REF_UNCHECKED) { - struct jffs2_eraseblock *jeb; - uint32_t len; - - printk(KERN_ERR "Eep. Unknown node type %04x at %08x was marked REF_UNCHECKED\n", - je16_to_cpu(node.u.nodetype), ref_offset(ref)); - - /* Mark the node as having been checked and fix the accounting accordingly */ - spin_lock(&c->erase_completion_lock); - jeb = &c->blocks[ref->flash_offset / c->sector_size]; - len = ref_totlen(c, jeb, ref); - - jeb->used_size += len; - jeb->unchecked_size -= len; - c->used_size += len; - c->unchecked_size -= len; - - mark_ref_normal(ref); - spin_unlock(&c->erase_completion_lock); + /* Check we've managed to read at least the common node header */ + if (retlen < sizeof(struct jffs2_unknown_node)) { + printk(KERN_WARNING "Warning! Short read unknown node at %#08x\n", + ref_offset(ref)); + return -EIO; } - node.u.nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(node.u.nodetype)); - if (crc32(0, &node, sizeof(struct jffs2_unknown_node)-4) != je32_to_cpu(node.u.hdr_crc)) { - /* Hmmm. This should have been caught at scan time. */ - printk(KERN_ERR "Node header CRC failed at %08x. But it must have been OK earlier.\n", - ref_offset(ref)); - printk(KERN_ERR "Node was: { %04x, %04x, %08x, %08x }\n", - je16_to_cpu(node.u.magic), je16_to_cpu(node.u.nodetype), je32_to_cpu(node.u.totlen), - je32_to_cpu(node.u.hdr_crc)); - jffs2_mark_node_obsolete(c, ref); - } else switch(je16_to_cpu(node.u.nodetype) & JFFS2_COMPAT_MASK) { - case JFFS2_FEATURE_INCOMPAT: - printk(KERN_NOTICE "Unknown INCOMPAT nodetype %04X at %08x\n", je16_to_cpu(node.u.nodetype), ref_offset(ref)); - /* EEP */ - BUG(); - break; - case JFFS2_FEATURE_ROCOMPAT: - printk(KERN_NOTICE "Unknown ROCOMPAT nodetype %04X at %08x\n", je16_to_cpu(node.u.nodetype), ref_offset(ref)); - if (!(c->flags & JFFS2_SB_FLAG_RO)) - BUG(); - break; - case JFFS2_FEATURE_RWCOMPAT_COPY: - printk(KERN_NOTICE "Unknown RWCOMPAT_COPY nodetype %04X at %08x\n", je16_to_cpu(node.u.nodetype), ref_offset(ref)); - break; - case JFFS2_FEATURE_RWCOMPAT_DELETE: - printk(KERN_NOTICE "Unknown RWCOMPAT_DELETE nodetype %04X at %08x\n", je16_to_cpu(node.u.nodetype), ref_offset(ref)); + + err = read_unknown(c, ref, &node.u, retlen); + if (err == 1) { jffs2_mark_node_obsolete(c, ref); break; - } + } else if (unlikely(err)) + goto free_out; } spin_lock(&c->erase_completion_lock); -- cgit v1.2.3 From b7ec479553b8755dd95ee988a957cbf2aef351dc Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 6 Nov 2005 14:42:37 +0000 Subject: [ARM] 3115/1: small optimizations to exception vector entry code Patch from Nicolas Pitre Since we know the value of cpsr on entry, we can replace the bic+orr with a single eor. Also remove a possible result delay (at least on XScale). Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/kernel/entry-armv.S | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index be439cab92c..a511ec5b11a 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -785,7 +785,7 @@ __kuser_helper_end: * SP points to a minimal amount of processor-private memory, the address * of which is copied into r0 for the mode specific abort handler. */ - .macro vector_stub, name, correction=0 + .macro vector_stub, name, mode, correction=0 .align 5 vector_\name: @@ -805,15 +805,14 @@ vector_\name: @ Prepare for SVC32 mode. IRQs remain disabled. @ mrs r0, cpsr - bic r0, r0, #MODE_MASK - orr r0, r0, #SVC_MODE + eor r0, r0, #(\mode ^ SVC_MODE) msr spsr_cxsf, r0 @ @ the branch table must immediately follow this code @ - mov r0, sp and lr, lr, #0x0f + mov r0, sp ldr lr, [pc, lr, lsl #2] movs pc, lr @ branch to handler in SVC mode .endm @@ -823,7 +822,7 @@ __stubs_start: /* * Interrupt dispatcher */ - vector_stub irq, 4 + vector_stub irq, IRQ_MODE, 4 .long __irq_usr @ 0 (USR_26 / USR_32) .long __irq_invalid @ 1 (FIQ_26 / FIQ_32) @@ -846,7 +845,7 @@ __stubs_start: * Data abort dispatcher * Enter in ABT mode, spsr = USR CPSR, lr = USR PC */ - vector_stub dabt, 8 + vector_stub dabt, ABT_MODE, 8 .long __dabt_usr @ 0 (USR_26 / USR_32) .long __dabt_invalid @ 1 (FIQ_26 / FIQ_32) @@ -869,7 +868,7 @@ __stubs_start: * Prefetch abort dispatcher * Enter in ABT mode, spsr = USR CPSR, lr = USR PC */ - vector_stub pabt, 4 + vector_stub pabt, ABT_MODE, 4 .long __pabt_usr @ 0 (USR_26 / USR_32) .long __pabt_invalid @ 1 (FIQ_26 / FIQ_32) @@ -892,7 +891,7 @@ __stubs_start: * Undef instr entry dispatcher * Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC */ - vector_stub und + vector_stub und, UND_MODE .long __und_usr @ 0 (USR_26 / USR_32) .long __und_invalid @ 1 (FIQ_26 / FIQ_32) -- cgit v1.2.3 From 756c7b748926b0baec6d2a921c3711679282c8fd Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Sun, 6 Nov 2005 15:03:23 +0000 Subject: [ARM] 3113/1: PXA: Allow machines to override (and also reuse) pxa pm functions Patch from Richard Purdie Update the PXA pm.c file to allow machines (such as the Sharp Zaurus) to override the standard pm functions but reuse/wrap them where needed. The init call is made slightly earlier to give machine code an init level to override them in removing any race. Signed-off-by: Richard Purdie Signed-off-by: Russell King --- arch/arm/mach-pxa/pm.c | 16 ++++++++++++---- include/asm-arm/arch-pxa/pm.h | 12 ++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 include/asm-arm/arch-pxa/pm.h diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c index ac4dd433616..f74b9af112d 100644 --- a/arch/arm/mach-pxa/pm.c +++ b/arch/arm/mach-pxa/pm.c @@ -12,6 +12,7 @@ */ #include #include +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -72,7 +74,7 @@ enum { SLEEP_SAVE_START = 0, }; -static int pxa_pm_enter(suspend_state_t state) +int pxa_pm_enter(suspend_state_t state) { unsigned long sleep_save[SLEEP_SAVE_SIZE]; unsigned long checksum = 0; @@ -191,6 +193,8 @@ static int pxa_pm_enter(suspend_state_t state) return 0; } +EXPORT_SYMBOL_GPL(pxa_pm_enter); + unsigned long sleep_phys_sp(void *sp) { return virt_to_phys(sp); @@ -199,21 +203,25 @@ unsigned long sleep_phys_sp(void *sp) /* * Called after processes are frozen, but before we shut down devices. */ -static int pxa_pm_prepare(suspend_state_t state) +int pxa_pm_prepare(suspend_state_t state) { extern int pxa_cpu_pm_prepare(suspend_state_t state); return pxa_cpu_pm_prepare(state); } +EXPORT_SYMBOL_GPL(pxa_pm_prepare); + /* * Called after devices are re-setup, but before processes are thawed. */ -static int pxa_pm_finish(suspend_state_t state) +int pxa_pm_finish(suspend_state_t state) { return 0; } +EXPORT_SYMBOL_GPL(pxa_pm_finish); + /* * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk. */ @@ -230,4 +238,4 @@ static int __init pxa_pm_init(void) return 0; } -late_initcall(pxa_pm_init); +device_initcall(pxa_pm_init); diff --git a/include/asm-arm/arch-pxa/pm.h b/include/asm-arm/arch-pxa/pm.h new file mode 100644 index 00000000000..7a8a1cdf430 --- /dev/null +++ b/include/asm-arm/arch-pxa/pm.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2005 Richard Purdie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +extern int pxa_pm_prepare(suspend_state_t state); +extern int pxa_pm_enter(suspend_state_t state); +extern int pxa_pm_finish(suspend_state_t state); -- cgit v1.2.3 From 730554d94607572ef8300c5c9848540b42394897 Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Sun, 17 Jul 2005 07:56:26 +0100 Subject: [JFFS2] Debug code clean up - step 1 Move debug functions into a seperate source file Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/Makefile | 4 +- fs/jffs2/build.c | 6 +- fs/jffs2/debug.c | 495 +++++++++++++++++++++++++++++++++++++++++++++++++++ fs/jffs2/debug.h | 104 +++++++++++ fs/jffs2/erase.c | 6 +- fs/jffs2/fs.c | 4 +- fs/jffs2/gc.c | 14 +- fs/jffs2/nodelist.h | 106 +---------- fs/jffs2/nodemgmt.c | 168 +---------------- fs/jffs2/read.c | 4 +- fs/jffs2/readinode.c | 110 +----------- fs/jffs2/scan.c | 6 +- fs/jffs2/wbuf.c | 20 +-- fs/jffs2/write.c | 55 ++---- 14 files changed, 663 insertions(+), 439 deletions(-) create mode 100644 fs/jffs2/debug.c create mode 100644 fs/jffs2/debug.h diff --git a/fs/jffs2/Makefile b/fs/jffs2/Makefile index f1afe681ecd..e6230f1bba7 100644 --- a/fs/jffs2/Makefile +++ b/fs/jffs2/Makefile @@ -1,7 +1,7 @@ # # Makefile for the Linux Journalling Flash File System v2 (JFFS2) # -# $Id: Makefile.common,v 1.9 2005/02/09 09:23:53 pavlov Exp $ +# $Id: Makefile.common,v 1.10 2005/07/17 06:56:20 dedekind Exp $ # obj-$(CONFIG_JFFS2_FS) += jffs2.o @@ -9,7 +9,7 @@ obj-$(CONFIG_JFFS2_FS) += jffs2.o jffs2-y := compr.o dir.o file.o ioctl.o nodelist.o malloc.o jffs2-y += read.o nodemgmt.o readinode.o write.o scan.o gc.o jffs2-y += symlink.o build.o erase.o background.o fs.o writev.o -jffs2-y += super.o +jffs2-y += super.o debug.o jffs2-$(CONFIG_JFFS2_FS_WRITEBUFFER) += wbuf.o jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index 97dc39796e2..3a0b003d73a 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: build.c,v 1.71 2005/07/12 16:37:08 dedekind Exp $ + * $Id: build.c,v 1.72 2005/07/17 06:56:20 dedekind Exp $ * */ @@ -104,7 +104,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) goto exit; D1(printk(KERN_DEBUG "Scanned flash completely\n")); - D2(jffs2_dump_block_lists(c)); + D2(jffs2_dbg_dump_block_lists(c)); c->flags |= JFFS2_SB_FLAG_BUILDING; /* Now scan the directory tree, increasing nlink according to every dirent found. */ @@ -168,7 +168,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) c->flags &= ~JFFS2_SB_FLAG_BUILDING; D1(printk(KERN_DEBUG "Pass 3 complete\n")); - D2(jffs2_dump_block_lists(c)); + D2(jffs2_dbg_dump_block_lists(c)); /* Rotate the lists by some number to ensure wear levelling */ jffs2_rotate_lists(c); diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c new file mode 100644 index 00000000000..9da524ca4e6 --- /dev/null +++ b/fs/jffs2/debug.c @@ -0,0 +1,495 @@ +/* + * JFFS2 -- Journalling Flash File System, Version 2. + * + * Copyright (C) 2001-2003 Red Hat, Inc. + * + * Created by David Woodhouse + * + * For licensing information, see the file 'LICENCE' in this directory. + * + * $Id: debug.c,v 1.1 2005/07/17 06:56:20 dedekind Exp $ + * + */ +#include +#include +#include "nodelist.h" +#include "debug.h" + +#ifdef JFFS2_DBG_PARANOIA_CHECKS + +void +jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f) +{ + struct jffs2_node_frag *frag; + int bitched = 0; + + for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) { + struct jffs2_full_dnode *fn = frag->node; + + if (!fn || !fn->raw) + continue; + + if (ref_flags(fn->raw) == REF_PRISTINE) { + if (fn->frags > 1) { + printk(KERN_ERR "REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2\n", + ref_offset(fn->raw), fn->frags); + bitched = 1; + } + + /* A hole node which isn't multi-page should be garbage-collected + and merged anyway, so we just check for the frag size here, + rather than mucking around with actually reading the node + and checking the compression type, which is the real way + to tell a hole node. */ + if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag) + && frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) { + printk(KERN_ERR "REF_PRISTINE node at 0x%08x had a previous non-hole frag " + "in the same page. Tell dwmw2\n", ref_offset(fn->raw)); + bitched = 1; + } + + if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag) + && frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) { + printk(KERN_ERR "REF_PRISTINE node at 0x%08x (%08x-%08x) had a following " + "non-hole frag in the same page. Tell dwmw2\n", + ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size); + bitched = 1; + } + } + } + + if (bitched) { + printk(KERN_ERR "Fragtree is corrupted. Fragtree dump:\n"); + jffs2_dbg_dump_fragtree(f); + BUG(); + } +} + +/* + * Check if the flash contains all 0xFF before we start writing. + */ +void +jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c, uint32_t ofs, int len) +{ + size_t retlen; + int ret, i; + unsigned char *buf; + + buf = kmalloc(len, GFP_KERNEL); + if (!buf) + return; + + ret = jffs2_flash_read(c, ofs, len, &retlen, buf); + if (ret || (retlen != len)) { + printk(KERN_WARNING "read %d bytes failed or short in %s(). ret %d, retlen %zd\n", + len, __FUNCTION__, ret, retlen); + kfree(buf); + return; + } + + ret = 0; + for (i = 0; i < len; i++) + if (buf[i] != 0xff) + ret = 1; + + if (ret) { + printk(KERN_ERR "ARGH. About to write node to %#08x on flash, but there are data " + "already there. The first corrupted byte is at %#08x.\n", ofs, ofs + i); + jffs2_dbg_dump_buffer(buf, len, ofs); + kfree(buf); + BUG(); + } + + kfree(buf); +} + +/* + * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'. + */ +void +jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) +{ + uint32_t my_used_size = 0; + uint32_t my_unchecked_size = 0; + uint32_t my_dirty_size = 0; + struct jffs2_raw_node_ref *ref2 = jeb->first_node; + + while (ref2) { + uint32_t totlen = ref_totlen(c, jeb, ref2); + + if (ref2->flash_offset < jeb->offset || + ref2->flash_offset > jeb->offset + c->sector_size) { + printk(KERN_ERR "node_ref %#08x shouldn't be in block at %#08x!\n", + ref_offset(ref2), jeb->offset); + jffs2_dbg_dump_node_refs(c, jeb); + jffs2_dbg_dump_block_lists(c); + BUG(); + + } + if (ref_flags(ref2) == REF_UNCHECKED) + my_unchecked_size += totlen; + else if (!ref_obsolete(ref2)) + my_used_size += totlen; + else + my_dirty_size += totlen; + + if ((!ref2->next_phys) != (ref2 == jeb->last_node)) { + printk(KERN_ERR "node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), " + "last_node is at %#08x (mem %p)\n", + ref_offset(ref2), ref2, ref_offset(ref2->next_phys), ref2->next_phys, + ref_offset(jeb->last_node), jeb->last_node); + jffs2_dbg_dump_node_refs(c, jeb); + jffs2_dbg_dump_block_lists(c); + BUG(); + } + ref2 = ref2->next_phys; + } + + if (my_used_size != jeb->used_size) { + printk(KERN_ERR "Calculated used size %#08x != stored used size %#08x\n", + my_used_size, jeb->used_size); + jffs2_dbg_dump_node_refs(c, jeb); + jffs2_dbg_dump_block_lists(c); + BUG(); + } + + if (my_unchecked_size != jeb->unchecked_size) { + printk(KERN_ERR "Calculated unchecked size %#08x != stored unchecked size %#08x\n", + my_unchecked_size, jeb->unchecked_size); + jffs2_dbg_dump_node_refs(c, jeb); + jffs2_dbg_dump_block_lists(c); + BUG(); + } + + if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) { + printk(KERN_ERR "Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n", + my_dirty_size, jeb->dirty_size + jeb->wasted_size); + jffs2_dbg_dump_node_refs(c, jeb); + jffs2_dbg_dump_block_lists(c); + BUG(); + } + + if (jeb->free_size == 0 + && my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) { + printk(KERN_ERR "The sum of all nodes in block (%#x) != size of block (%#x)\n", + my_used_size + my_unchecked_size + my_dirty_size, + c->sector_size); + jffs2_dbg_dump_node_refs(c, jeb); + jffs2_dbg_dump_block_lists(c); + BUG(); + } +} +#endif /* JFFS2_PARANOIA_CHECKS */ + +#if defined(JFFS2_PARANOIA_CHECKS) || (CONFIG_JFFS2_FS_DEBUG > 0) +/* + * Dump the node_refs of the 'jeb' JFFS2 eraseblock. + */ +void +jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) +{ + struct jffs2_raw_node_ref *ref; + int i = 0; + + if (!jeb->first_node) { + printk(KERN_DEBUG "no nodes in block %#08x\n", jeb->offset); + return; + } + + printk(KERN_DEBUG); + for (ref = jeb->first_node; ; ref = ref->next_phys) { + printk("%#08x(%#x)", ref_offset(ref), ref->__totlen); + if (ref->next_phys) + printk("->"); + else + break; + if (++i == 4) { + i = 0; + printk("\n" KERN_DEBUG); + } + } + printk("\n"); +} + +void +jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c) +{ + printk(KERN_DEBUG "flash_size: %#08x\n", c->flash_size); + printk(KERN_DEBUG "used_size: %#08x\n", c->used_size); + printk(KERN_DEBUG "dirty_size: %#08x\n", c->dirty_size); + printk(KERN_DEBUG "wasted_size: %#08x\n", c->wasted_size); + printk(KERN_DEBUG "unchecked_size: %#08x\n", c->unchecked_size); + printk(KERN_DEBUG "free_size: %#08x\n", c->free_size); + printk(KERN_DEBUG "erasing_size: %#08x\n", c->erasing_size); + printk(KERN_DEBUG "bad_size: %#08x\n", c->bad_size); + printk(KERN_DEBUG "sector_size: %#08x\n", c->sector_size); + printk(KERN_DEBUG "jffs2_reserved_blocks size: %#08x\n", + c->sector_size * c->resv_blocks_write); + + if (c->nextblock) + printk(KERN_DEBUG "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, " + "unchecked %#08x, free %#08x)\n", + c->nextblock->offset, c->nextblock->used_size, + c->nextblock->dirty_size, c->nextblock->wasted_size, + c->nextblock->unchecked_size, c->nextblock->free_size); + else + printk(KERN_DEBUG "nextblock: NULL\n"); + + if (c->gcblock) + printk(KERN_DEBUG "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, " + "unchecked %#08x, free %#08x)\n", + c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size, + c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size); + else + printk(KERN_DEBUG "gcblock: NULL\n"); + + if (list_empty(&c->clean_list)) { + printk(KERN_DEBUG "clean_list: empty\n"); + } else { + struct list_head *this; + int numblocks = 0; + uint32_t dirty = 0; + + list_for_each(this, &c->clean_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + numblocks ++; + dirty += jeb->wasted_size; + if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { + printk(KERN_DEBUG "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " + "unchecked %#08x, free %#08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, + jeb->unchecked_size, jeb->free_size); + } + } + + printk (KERN_DEBUG "Contains %d blocks with total wasted size %u, average wasted size: %u\n", + numblocks, dirty, dirty / numblocks); + } + + if (list_empty(&c->very_dirty_list)) { + printk(KERN_DEBUG "very_dirty_list: empty\n"); + } else { + struct list_head *this; + int numblocks = 0; + uint32_t dirty = 0; + + list_for_each(this, &c->very_dirty_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + + numblocks ++; + dirty += jeb->dirty_size; + if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { + printk(KERN_DEBUG "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " + "unchecked %#08x, free %#08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, + jeb->unchecked_size, jeb->free_size); + } + } + + printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n", + numblocks, dirty, dirty / numblocks); + } + + if (list_empty(&c->dirty_list)) { + printk(KERN_DEBUG "dirty_list: empty\n"); + } else { + struct list_head *this; + int numblocks = 0; + uint32_t dirty = 0; + + list_for_each(this, &c->dirty_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + + numblocks ++; + dirty += jeb->dirty_size; + if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { + printk(KERN_DEBUG "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " + "unchecked %#08x, free %#08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, + jeb->unchecked_size, jeb->free_size); + } + } + + printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n", + numblocks, dirty, dirty / numblocks); + } + + if (list_empty(&c->erasable_list)) { + printk(KERN_DEBUG "erasable_list: empty\n"); + } else { + struct list_head *this; + + list_for_each(this, &c->erasable_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + + if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { + printk(KERN_DEBUG "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " + "unchecked %#08x, free %#08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, + jeb->unchecked_size, jeb->free_size); + } + } + } + + if (list_empty(&c->erasing_list)) { + printk(KERN_DEBUG "erasing_list: empty\n"); + } else { + struct list_head *this; + + list_for_each(this, &c->erasing_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + + if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { + printk(KERN_DEBUG "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " + "unchecked %#08x, free %#08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, + jeb->unchecked_size, jeb->free_size); + } + } + } + + if (list_empty(&c->erase_pending_list)) { + printk(KERN_DEBUG "erase_pending_list: empty\n"); + } else { + struct list_head *this; + + list_for_each(this, &c->erase_pending_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + + if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { + printk(KERN_DEBUG "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " + "unchecked %#08x, free %#08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, + jeb->unchecked_size, jeb->free_size); + } + } + } + + if (list_empty(&c->erasable_pending_wbuf_list)) { + printk(KERN_DEBUG "erasable_pending_wbuf_list: empty\n"); + } else { + struct list_head *this; + + list_for_each(this, &c->erasable_pending_wbuf_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + + if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { + printk(KERN_DEBUG "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, " + "wasted %#08x, unchecked %#08x, free %#08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, + jeb->unchecked_size, jeb->free_size); + } + } + } + + if (list_empty(&c->free_list)) { + printk(KERN_DEBUG "free_list: empty\n"); + } else { + struct list_head *this; + + list_for_each(this, &c->free_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + + if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { + printk(KERN_DEBUG "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " + "unchecked %#08x, free %#08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, + jeb->unchecked_size, jeb->free_size); + } + } + } + + if (list_empty(&c->bad_list)) { + printk(KERN_DEBUG "bad_list: empty\n"); + } else { + struct list_head *this; + + list_for_each(this, &c->bad_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + + if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { + printk(KERN_DEBUG "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " + "unchecked %#08x, free %#08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, + jeb->unchecked_size, jeb->free_size); + } + } + } + + if (list_empty(&c->bad_used_list)) { + printk(KERN_DEBUG "bad_used_list: empty\n"); + } else { + struct list_head *this; + + list_for_each(this, &c->bad_used_list) { + struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); + + if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { + printk(KERN_DEBUG "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " + "unchecked %#08x, free %#08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, + jeb->unchecked_size, jeb->free_size); + } + } + } +} + +void +jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f) +{ + struct jffs2_node_frag *this = frag_first(&f->fragtree); + uint32_t lastofs = 0; + int buggy = 0; + + printk(KERN_DEBUG "inode is ino #%u\n", f->inocache->ino); + while(this) { + if (this->node) + printk(KERN_DEBUG "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), " + "right (%p), parent (%p)\n", + this->ofs, this->ofs+this->size, ref_offset(this->node->raw), + ref_flags(this->node->raw), this, frag_left(this), frag_right(this), + frag_parent(this)); + else + printk(KERN_DEBUG "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n", + this->ofs, this->ofs+this->size, this, frag_left(this), + frag_right(this), frag_parent(this)); + if (this->ofs != lastofs) + buggy = 1; + lastofs = this->ofs + this->size; + this = frag_next(this); + } + + if (f->metadata) + printk(KERN_DEBUG "metadata at 0x%08x\n", ref_offset(f->metadata->raw)); + + if (buggy) { + printk(KERN_ERR "Error! %s(): Frag tree got a hole in it\n", __FUNCTION__); + BUG(); + } +} + +#define JFFS3_BUFDUMP_BYTES_PER_LINE 8 +void +jffs2_dbg_dump_buffer(char *buf, int len, uint32_t offs) +{ + int i = 0; + int skip = offs & ~(JFFS3_BUFDUMP_BYTES_PER_LINE - 1); + + while (i < len) { + int j = 0; + + printk(KERN_DEBUG "0x#x: \n"); + while (skip) { + printk(" "); + skip -= 1; + } + + while (j < JFFS3_BUFDUMP_BYTES_PER_LINE) { + if (i + j < len) + printk(" %#02x", buf[i + j++]); + } + + i += JFFS3_BUFDUMP_BYTES_PER_LINE; + } +} +#endif /* JFFS2_PARANOIA_CHECKS || CONFIG_JFFS2_FS_DEBUG > 0 */ diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h new file mode 100644 index 00000000000..7d14f7b0139 --- /dev/null +++ b/fs/jffs2/debug.h @@ -0,0 +1,104 @@ +/* + * JFFS2 -- Journalling Flash File System, Version 2. + * + * Copyright (C) 2001-2003 Red Hat, Inc. + * + * Created by David Woodhouse + * + * For licensing information, see the file 'LICENCE' in this directory. + * + * $Id: debug.h,v 1.1 2005/07/17 06:56:20 dedekind Exp $ + * + */ +#ifndef _JFFS2_DEBUG_H_ +#define _JFFS2_DEBUG_H_ + +#include + +#ifndef CONFIG_JFFS2_FS_DEBUG +#define CONFIG_JFFS2_FS_DEBUG 1 +#endif + +#if CONFIG_JFFS2_FS_DEBUG > 0 +#define JFFS2_DBG_PARANOIA_CHECKS +#define D1(x) x +#else +#define D1(x) +#endif + +#if CONFIG_JFFS2_FS_DEBUG > 1 +#define D2(x) x +#else +#define D2(x) +#endif + +/* Enable JFFS2 sanity checks */ +#define JFFS2_DBG_SANITY_CHECKS + +#if CONFIG_JFFS2_FS_DEBUG > 0 +void +jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c); + +void +jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); + +void +jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f); + +void +jffs2_dbg_dump_buffer(char *buf, int len, uint32_t offs); +#endif + +#ifdef JFFS2_DBG_PARANOIA_CHECKS +void +jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f); + +void +jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c, + struct jffs2_eraseblock *jeb); + +void +jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c, + uint32_t ofs, int len); +#else +#define jffs2_dbg_fragtree_paranoia_check(f) +#define jffs2_dbg_acct_paranoia_check(c, jeb) +#define jffs2_dbg_prewrite_paranoia_check(c, ofs, len) +#endif /* !JFFS2_PARANOIA_CHECKS */ + +#ifdef JFFS2_DBG_SANITY_CHECKS +/* + * Check the space accounting of the file system and of + * the JFFS3 erasable block 'jeb'. + */ +static inline void +jffs2_dbg_acct_sanity_check(struct jffs2_sb_info *c, + struct jffs2_eraseblock *jeb) +{ + if (unlikely(jeb && jeb->used_size + jeb->dirty_size + + jeb->free_size + jeb->wasted_size + + jeb->unchecked_size != c->sector_size)) { + printk(KERN_ERR "Eeep. Space accounting for block at 0x%08x is screwed\n", jeb->offset); + printk(KERN_ERR "free %#08x + dirty %#08x + used %#08x + wasted %#08x + unchecked " + "%#08x != total %#08x\n", jeb->free_size, jeb->dirty_size, jeb->used_size, + jeb->wasted_size, jeb->unchecked_size, c->sector_size); + BUG(); + } + + if (unlikely(c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size + + c->wasted_size + c->unchecked_size != c->flash_size)) { + printk(KERN_ERR "Eeep. Space accounting superblock info is screwed\n"); + printk(KERN_ERR "free %#08x + dirty %#08x + used %#08x + erasing %#08x + bad %#08x + " + "wasted %#08x + unchecked %#08x != total %#08x\n", + c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, + c->wasted_size, c->unchecked_size, c->flash_size); + BUG(); + } +} +#else +static inline void +jffs2_dbg_acct_sanity_check(struct jffs2_sb_info *c, + struct jffs2_eraseblock *jeb); +#endif /* !JFFS2_DBG_SANITY_CHECKS */ + +#endif /* _JFFS2_DEBUG_H_ */ diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index 787d84ac2bc..af0c7d43188 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: erase.c,v 1.80 2005/07/14 19:46:24 joern Exp $ + * $Id: erase.c,v 1.81 2005/07/17 06:56:20 dedekind Exp $ * */ @@ -429,8 +429,8 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb c->free_size += jeb->free_size; c->used_size += jeb->used_size; - ACCT_SANITY_CHECK(c,jeb); - D1(ACCT_PARANOIA_CHECK(jeb)); + jffs2_dbg_acct_sanity_check(c,jeb); + jffs2_dbg_acct_paranoia_check(c, jeb); list_add_tail(&jeb->list, &c->free_list); c->nr_erasing_blocks--; diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 5687c3f4200..6c8a9d5d56a 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: fs.c,v 1.56 2005/07/06 12:13:09 dwmw2 Exp $ + * $Id: fs.c,v 1.57 2005/07/17 06:56:21 dedekind Exp $ * */ @@ -203,7 +203,7 @@ int jffs2_statfs(struct super_block *sb, struct kstatfs *buf) buf->f_bavail = buf->f_bfree = avail >> PAGE_SHIFT; - D2(jffs2_dump_block_lists(c)); + D2(jffs2_dbg_dump_block_lists(c)); spin_unlock(&c->erase_completion_lock); diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 7086cd63450..337ab49ab24 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: gc.c,v 1.148 2005/04/09 10:47:00 dedekind Exp $ + * $Id: gc.c,v 1.149 2005/07/17 06:56:21 dedekind Exp $ * */ @@ -111,7 +111,7 @@ again: ret->wasted_size = 0; } - D2(jffs2_dump_block_lists(c)); + D2(jffs2_dbg_dump_block_lists(c)); return ret; } @@ -142,7 +142,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) if (c->checked_ino > c->highest_ino) { printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n", c->unchecked_size); - D2(jffs2_dump_block_lists(c)); + D2(jffs2_dbg_dump_block_lists(c)); spin_unlock(&c->erase_completion_lock); BUG(); } @@ -619,16 +619,16 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, D1(printk(KERN_DEBUG "Retrying failed write of REF_PRISTINE node.\n")); - ACCT_SANITY_CHECK(c,jeb); - D1(ACCT_PARANOIA_CHECK(jeb)); + jffs2_dbg_acct_sanity_check(c,jeb); + jffs2_dbg_acct_paranoia_check(c, jeb); ret = jffs2_reserve_space_gc(c, rawlen, &phys_ofs, &dummy); if (!ret) { D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", phys_ofs)); - ACCT_SANITY_CHECK(c,jeb); - D1(ACCT_PARANOIA_CHECK(jeb)); + jffs2_dbg_acct_sanity_check(c,jeb); + jffs2_dbg_acct_paranoia_check(c, jeb); goto retry; } diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index b34c397909e..6802e0968d3 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.h,v 1.131 2005/07/05 21:03:07 dwmw2 Exp $ + * $Id: nodelist.h,v 1.132 2005/07/17 06:56:21 dedekind Exp $ * */ @@ -24,26 +24,10 @@ #ifdef __ECOS #include "os-ecos.h" #else -#include /* For min/max in older kernels */ +#include /* For compatibility with older kernels */ #include "os-linux.h" #endif -#ifndef CONFIG_JFFS2_FS_DEBUG -#define CONFIG_JFFS2_FS_DEBUG 1 -#endif - -#if CONFIG_JFFS2_FS_DEBUG > 0 -#define D1(x) x -#else -#define D1(x) -#endif - -#if CONFIG_JFFS2_FS_DEBUG > 1 -#define D2(x) x -#else -#define D2(x) -#endif - #define JFFS2_NATIVE_ENDIAN /* Note we handle mode bits conversion from JFFS2 (i.e. Linux) to/from @@ -207,79 +191,6 @@ struct jffs2_eraseblock struct jffs2_raw_node_ref *gc_node; /* Next node to be garbage collected */ }; -#define ACCT_SANITY_CHECK(c, jeb) do { \ - struct jffs2_eraseblock *___j = jeb; \ - if ((___j) && ___j->used_size + ___j->dirty_size + ___j->free_size + ___j->wasted_size + ___j->unchecked_size != c->sector_size) { \ - printk(KERN_NOTICE "Eeep. Space accounting for block at 0x%08x is screwed\n", ___j->offset); \ - printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x + wasted %08x + unchecked %08x != total %08x\n", \ - ___j->free_size, ___j->dirty_size, ___j->used_size, ___j->wasted_size, ___j->unchecked_size, c->sector_size); \ - BUG(); \ - } \ - if (c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size + c->wasted_size + c->unchecked_size != c->flash_size) { \ - printk(KERN_NOTICE "Eeep. Space accounting superblock info is screwed\n"); \ - printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x + erasing %08x + bad %08x + wasted %08x + unchecked %08x != total %08x\n", \ - c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, c->wasted_size, c->unchecked_size, c->flash_size); \ - BUG(); \ - } \ -} while(0) - -static inline void paranoia_failed_dump(struct jffs2_eraseblock *jeb) -{ - struct jffs2_raw_node_ref *ref; - int i=0; - - printk(KERN_NOTICE); - for (ref = jeb->first_node; ref; ref = ref->next_phys) { - printk("%08x->", ref_offset(ref)); - if (++i == 8) { - i = 0; - printk("\n" KERN_NOTICE); - } - } - printk("\n"); -} - - -#define ACCT_PARANOIA_CHECK(jeb) do { \ - uint32_t my_used_size = 0; \ - uint32_t my_unchecked_size = 0; \ - struct jffs2_raw_node_ref *ref2 = jeb->first_node; \ - while (ref2) { \ - if (unlikely(ref2->flash_offset < jeb->offset || \ - ref2->flash_offset > jeb->offset + c->sector_size)) { \ - printk(KERN_NOTICE "Node %08x shouldn't be in block at %08x!\n", \ - ref_offset(ref2), jeb->offset); \ - paranoia_failed_dump(jeb); \ - BUG(); \ - } \ - if (ref_flags(ref2) == REF_UNCHECKED) \ - my_unchecked_size += ref_totlen(c, jeb, ref2); \ - else if (!ref_obsolete(ref2)) \ - my_used_size += ref_totlen(c, jeb, ref2); \ - if (unlikely((!ref2->next_phys) != (ref2 == jeb->last_node))) { \ - if (!ref2->next_phys) \ - printk("ref for node at %p (phys %08x) has next_phys->%p (----), last_node->%p (phys %08x)\n", \ - ref2, ref_offset(ref2), ref2->next_phys, \ - jeb->last_node, ref_offset(jeb->last_node)); \ - else \ - printk("ref for node at %p (phys %08x) has next_phys->%p (%08x), last_node->%p (phys %08x)\n", \ - ref2, ref_offset(ref2), ref2->next_phys, ref_offset(ref2->next_phys), \ - jeb->last_node, ref_offset(jeb->last_node)); \ - paranoia_failed_dump(jeb); \ - BUG(); \ - } \ - ref2 = ref2->next_phys; \ - } \ - if (my_used_size != jeb->used_size) { \ - printk(KERN_NOTICE "Calculated used size %08x != stored used size %08x\n", my_used_size, jeb->used_size); \ - BUG(); \ - } \ - if (my_unchecked_size != jeb->unchecked_size) { \ - printk(KERN_NOTICE "Calculated unchecked size %08x != stored unchecked size %08x\n", my_unchecked_size, jeb->unchecked_size); \ - BUG(); \ - } \ - } while(0) - /* Calculate totlen from surrounding nodes or eraseblock */ static inline uint32_t __ref_totlen(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, @@ -306,11 +217,13 @@ static inline uint32_t ref_totlen(struct jffs2_sb_info *c, { uint32_t ret; - D1(if (jeb && jeb != &c->blocks[ref->flash_offset / c->sector_size]) { +#if CONFIG_JFFS2_FS_DEBUG > 0 + if (jeb && jeb != &c->blocks[ref->flash_offset / c->sector_size]) { printk(KERN_CRIT "ref_totlen called with wrong block -- at 0x%08x instead of 0x%08x; ref 0x%08x\n", jeb->offset, c->blocks[ref->flash_offset / c->sector_size].offset, ref_offset(ref)); BUG(); - }) + } +#endif #if 1 ret = ref->__totlen; @@ -323,14 +236,13 @@ static inline uint32_t ref_totlen(struct jffs2_sb_info *c, ret, ref->__totlen); if (!jeb) jeb = &c->blocks[ref->flash_offset / c->sector_size]; - paranoia_failed_dump(jeb); + jffs2_dbg_dump_node_refs(c, jeb); BUG(); } #endif return ret; } - #define ALLOC_NORMAL 0 /* Normal allocation */ #define ALLOC_DELETION 1 /* Deletion node. Best to allow it */ #define ALLOC_GC 2 /* Space requested for GC. Give it or die */ @@ -384,7 +296,6 @@ static inline struct jffs2_node_frag *frag_last(struct rb_root *root) #define frag_erase(frag, list) rb_erase(&frag->rb, list); /* nodelist.c */ -D2(void jffs2_print_frag_list(struct jffs2_inode_info *f)); void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list); int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct rb_root *tnp, struct jffs2_full_dirent **fdp, @@ -410,7 +321,6 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t * int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new); void jffs2_complete_reservation(struct jffs2_sb_info *c); void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw); -void jffs2_dump_block_lists(struct jffs2_sb_info *c); /* write.c */ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri); @@ -483,4 +393,6 @@ int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_erasebloc int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); #endif +#include "debug.h" + #endif /* __JFFS2_NODELIST_H__ */ diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index c1d8b5ed9ab..424be1e1ca9 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodemgmt.c,v 1.122 2005/05/06 09:30:27 dedekind Exp $ + * $Id: nodemgmt.c,v 1.123 2005/07/17 06:56:21 dedekind Exp $ * */ @@ -349,8 +349,8 @@ int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_r list_add_tail(&jeb->list, &c->clean_list); c->nextblock = NULL; } - ACCT_SANITY_CHECK(c,jeb); - D1(ACCT_PARANOIA_CHECK(jeb)); + jffs2_dbg_acct_sanity_check(c,jeb); + jffs2_dbg_acct_paranoia_check(c, jeb); spin_unlock(&c->erase_completion_lock); @@ -466,9 +466,9 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref } ref->flash_offset = ref_offset(ref) | REF_OBSOLETE; - ACCT_SANITY_CHECK(c, jeb); + jffs2_dbg_acct_sanity_check(c, jeb); - D1(ACCT_PARANOIA_CHECK(jeb)); + jffs2_dbg_acct_paranoia_check(c, jeb); if (c->flags & JFFS2_SB_FLAG_SCANNING) { /* Flash scanning is in progress. Don't muck about with the block @@ -649,164 +649,6 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref up(&c->erase_free_sem); } -#if CONFIG_JFFS2_FS_DEBUG >= 2 -void jffs2_dump_block_lists(struct jffs2_sb_info *c) -{ - - - printk(KERN_DEBUG "jffs2_dump_block_lists:\n"); - printk(KERN_DEBUG "flash_size: %08x\n", c->flash_size); - printk(KERN_DEBUG "used_size: %08x\n", c->used_size); - printk(KERN_DEBUG "dirty_size: %08x\n", c->dirty_size); - printk(KERN_DEBUG "wasted_size: %08x\n", c->wasted_size); - printk(KERN_DEBUG "unchecked_size: %08x\n", c->unchecked_size); - printk(KERN_DEBUG "free_size: %08x\n", c->free_size); - printk(KERN_DEBUG "erasing_size: %08x\n", c->erasing_size); - printk(KERN_DEBUG "bad_size: %08x\n", c->bad_size); - printk(KERN_DEBUG "sector_size: %08x\n", c->sector_size); - printk(KERN_DEBUG "jffs2_reserved_blocks size: %08x\n",c->sector_size * c->resv_blocks_write); - - if (c->nextblock) { - printk(KERN_DEBUG "nextblock: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", - c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->wasted_size, c->nextblock->unchecked_size, c->nextblock->free_size); - } else { - printk(KERN_DEBUG "nextblock: NULL\n"); - } - if (c->gcblock) { - printk(KERN_DEBUG "gcblock: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", - c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size, c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size); - } else { - printk(KERN_DEBUG "gcblock: NULL\n"); - } - if (list_empty(&c->clean_list)) { - printk(KERN_DEBUG "clean_list: empty\n"); - } else { - struct list_head *this; - int numblocks = 0; - uint32_t dirty = 0; - - list_for_each(this, &c->clean_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - numblocks ++; - dirty += jeb->wasted_size; - printk(KERN_DEBUG "clean_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); - } - printk (KERN_DEBUG "Contains %d blocks with total wasted size %u, average wasted size: %u\n", numblocks, dirty, dirty / numblocks); - } - if (list_empty(&c->very_dirty_list)) { - printk(KERN_DEBUG "very_dirty_list: empty\n"); - } else { - struct list_head *this; - int numblocks = 0; - uint32_t dirty = 0; - - list_for_each(this, &c->very_dirty_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - numblocks ++; - dirty += jeb->dirty_size; - printk(KERN_DEBUG "very_dirty_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); - } - printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n", - numblocks, dirty, dirty / numblocks); - } - if (list_empty(&c->dirty_list)) { - printk(KERN_DEBUG "dirty_list: empty\n"); - } else { - struct list_head *this; - int numblocks = 0; - uint32_t dirty = 0; - - list_for_each(this, &c->dirty_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - numblocks ++; - dirty += jeb->dirty_size; - printk(KERN_DEBUG "dirty_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); - } - printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n", - numblocks, dirty, dirty / numblocks); - } - if (list_empty(&c->erasable_list)) { - printk(KERN_DEBUG "erasable_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->erasable_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "erasable_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); - } - } - if (list_empty(&c->erasing_list)) { - printk(KERN_DEBUG "erasing_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->erasing_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "erasing_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); - } - } - if (list_empty(&c->erase_pending_list)) { - printk(KERN_DEBUG "erase_pending_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->erase_pending_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "erase_pending_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); - } - } - if (list_empty(&c->erasable_pending_wbuf_list)) { - printk(KERN_DEBUG "erasable_pending_wbuf_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->erasable_pending_wbuf_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "erasable_pending_wbuf_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); - } - } - if (list_empty(&c->free_list)) { - printk(KERN_DEBUG "free_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->free_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "free_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); - } - } - if (list_empty(&c->bad_list)) { - printk(KERN_DEBUG "bad_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->bad_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "bad_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); - } - } - if (list_empty(&c->bad_used_list)) { - printk(KERN_DEBUG "bad_used_list: empty\n"); - } else { - struct list_head *this; - - list_for_each(this, &c->bad_used_list) { - struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); - printk(KERN_DEBUG "bad_used_list: %08x (used %08x, dirty %08x, wasted %08x, unchecked %08x, free %08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); - } - } -} -#endif /* CONFIG_JFFS2_FS_DEBUG */ - int jffs2_thread_should_wake(struct jffs2_sb_info *c) { int ret = 0; diff --git a/fs/jffs2/read.c b/fs/jffs2/read.c index c7f9068907c..9706534786e 100644 --- a/fs/jffs2/read.c +++ b/fs/jffs2/read.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: read.c,v 1.39 2005/03/01 10:34:03 dedekind Exp $ + * $Id: read.c,v 1.40 2005/07/17 06:56:21 dedekind Exp $ * */ @@ -174,7 +174,7 @@ int jffs2_read_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, if (frag) { D1(printk(KERN_NOTICE "Eep. Hole in ino #%u fraglist. frag->ofs = 0x%08x, offset = 0x%08x\n", f->inocache->ino, frag->ofs, offset)); holesize = min(holesize, frag->ofs - offset); - D2(jffs2_print_frag_list(f)); + D2(jffs2_dbg_dump_fragtree(f)); } D1(printk(KERN_DEBUG "Filling non-frag hole from %d-%d\n", offset, offset+holesize)); memset(buf, 0, holesize); diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 5b2a83599d7..cf39bcf3e3c 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.125 2005/07/10 13:13:55 dedekind Exp $ + * $Id: readinode.c,v 1.126 2005/07/17 06:56:21 dedekind Exp $ * */ @@ -22,104 +22,6 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *list, struct jffs2_node_frag *newfrag); -#if CONFIG_JFFS2_FS_DEBUG >= 2 -static void jffs2_print_fragtree(struct rb_root *list, int permitbug) -{ - struct jffs2_node_frag *this = frag_first(list); - uint32_t lastofs = 0; - int buggy = 0; - - while(this) { - if (this->node) - printk(KERN_DEBUG "frag %04x-%04x: 0x%08x(%d) on flash (*%p). left (%p), right (%p), parent (%p)\n", - this->ofs, this->ofs+this->size, ref_offset(this->node->raw), ref_flags(this->node->raw), - this, frag_left(this), frag_right(this), frag_parent(this)); - else - printk(KERN_DEBUG "frag %04x-%04x: hole (*%p). left (%p} right (%p), parent (%p)\n", this->ofs, - this->ofs+this->size, this, frag_left(this), frag_right(this), frag_parent(this)); - if (this->ofs != lastofs) - buggy = 1; - lastofs = this->ofs+this->size; - this = frag_next(this); - } - if (buggy && !permitbug) { - printk(KERN_CRIT "Frag tree got a hole in it\n"); - BUG(); - } -} - -void jffs2_print_frag_list(struct jffs2_inode_info *f) -{ - jffs2_print_fragtree(&f->fragtree, 0); - - if (f->metadata) { - printk(KERN_DEBUG "metadata at 0x%08x\n", ref_offset(f->metadata->raw)); - } -} -#endif - -#if CONFIG_JFFS2_FS_DEBUG >= 1 -static int jffs2_sanitycheck_fragtree(struct jffs2_inode_info *f) -{ - struct jffs2_node_frag *frag; - int bitched = 0; - - for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) { - - struct jffs2_full_dnode *fn = frag->node; - if (!fn || !fn->raw) - continue; - - if (ref_flags(fn->raw) == REF_PRISTINE) { - - if (fn->frags > 1) { - printk(KERN_WARNING "REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2\n", ref_offset(fn->raw), fn->frags); - bitched = 1; - } - /* A hole node which isn't multi-page should be garbage-collected - and merged anyway, so we just check for the frag size here, - rather than mucking around with actually reading the node - and checking the compression type, which is the real way - to tell a hole node. */ - if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag) && frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) { - printk(KERN_WARNING "REF_PRISTINE node at 0x%08x had a previous non-hole frag in the same page. Tell dwmw2\n", - ref_offset(fn->raw)); - bitched = 1; - } - - if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag) && frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) { - printk(KERN_WARNING "REF_PRISTINE node at 0x%08x (%08x-%08x) had a following non-hole frag in the same page. Tell dwmw2\n", - ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size); - bitched = 1; - } - } - } - - if (bitched) { - struct jffs2_node_frag *thisfrag; - - printk(KERN_WARNING "Inode is #%u\n", f->inocache->ino); - thisfrag = frag_first(&f->fragtree); - while (thisfrag) { - if (!thisfrag->node) { - printk("Frag @0x%x-0x%x; node-less hole\n", - thisfrag->ofs, thisfrag->size + thisfrag->ofs); - } else if (!thisfrag->node->raw) { - printk("Frag @0x%x-0x%x; raw-less hole\n", - thisfrag->ofs, thisfrag->size + thisfrag->ofs); - } else { - printk("Frag @0x%x-0x%x; raw at 0x%08x(%d) (0x%x-0x%x)\n", - thisfrag->ofs, thisfrag->size + thisfrag->ofs, - ref_offset(thisfrag->node->raw), ref_flags(thisfrag->node->raw), - thisfrag->node->ofs, thisfrag->node->ofs+thisfrag->node->size); - } - thisfrag = frag_next(thisfrag); - } - } - return bitched; -} -#endif /* D1 */ - static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this) { if (this->node) { @@ -190,12 +92,8 @@ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_in mark_ref_normal(next->node->raw); } } - D2(if (jffs2_sanitycheck_fragtree(f)) { - printk(KERN_WARNING "Just added node %04x-%04x @0x%08x on flash, newfrag *%p\n", - fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag); - return 0; - }) - D2(jffs2_print_frag_list(f)); + D2(jffs2_dbg_fragtree_paranoia_check(f)); + D2(jffs2_dbg_dump_fragtree(f)); return 0; } @@ -582,7 +480,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, jffs2_free_tmp_dnode_info(tn); } - D1(jffs2_sanitycheck_fragtree(f)); + jffs2_dbg_fragtree_paranoia_check(f); if (!fn) { /* No data nodes for this inode. */ diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index b63160f83ba..a2a51b7c2fd 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: scan.c,v 1.119 2005/02/17 17:51:13 dedekind Exp $ + * $Id: scan.c,v 1.120 2005/07/17 06:56:21 dedekind Exp $ * */ #include @@ -130,7 +130,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) if (ret < 0) goto out; - ACCT_PARANOIA_CHECK(jeb); + jffs2_dbg_acct_paranoia_check(c, jeb); /* Now decide which list to put it on */ switch(ret) { @@ -370,7 +370,7 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo scan_more: while(ofs < jeb->offset + c->sector_size) { - D1(ACCT_PARANOIA_CHECK(jeb)); + jffs2_dbg_acct_paranoia_check(c, jeb); cond_resched(); diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 316133c626b..85ae51d2060 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -9,7 +9,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: wbuf.c,v 1.92 2005/04/05 12:51:54 dedekind Exp $ + * $Id: wbuf.c,v 1.93 2005/07/17 06:56:21 dedekind Exp $ * */ @@ -139,7 +139,7 @@ static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock { D1(printk("About to refile bad block at %08x\n", jeb->offset)); - D2(jffs2_dump_block_lists(c)); + D2(jffs2_dbg_dump_block_lists(c)); /* File the existing block on the bad_used_list.... */ if (c->nextblock == jeb) c->nextblock = NULL; @@ -156,7 +156,7 @@ static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock c->nr_erasing_blocks++; jffs2_erase_pending_trigger(c); } - D2(jffs2_dump_block_lists(c)); + D2(jffs2_dbg_dump_block_lists(c)); /* Adjust its size counts accordingly */ c->wasted_size += jeb->free_size; @@ -164,8 +164,8 @@ static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock jeb->wasted_size += jeb->free_size; jeb->free_size = 0; - ACCT_SANITY_CHECK(c,jeb); - D1(ACCT_PARANOIA_CHECK(jeb)); + jffs2_dbg_acct_sanity_check(c,jeb); + jffs2_dbg_acct_paranoia_check(c, jeb); } /* Recover from failure to write wbuf. Recover the nodes up to the @@ -392,11 +392,11 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) else jeb->last_node = container_of(first_raw, struct jffs2_raw_node_ref, next_phys); - ACCT_SANITY_CHECK(c,jeb); - D1(ACCT_PARANOIA_CHECK(jeb)); + jffs2_dbg_acct_sanity_check(c,jeb); + jffs2_dbg_acct_paranoia_check(c, jeb); - ACCT_SANITY_CHECK(c,new_jeb); - D1(ACCT_PARANOIA_CHECK(new_jeb)); + jffs2_dbg_acct_sanity_check(c,new_jeb); + jffs2_dbg_acct_paranoia_check(c, new_jeb); spin_unlock(&c->erase_completion_lock); @@ -973,7 +973,7 @@ int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb if (buf[i] != 0xFF) { D2(printk(KERN_DEBUG "Found %02x at %x in OOB for %08x\n", - buf[page+i], page+i, jeb->offset)); + buf[i], i, jeb->offset)); ret = 1; goto out; } diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index 69100615d9a..b6a53e5aaa0 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: write.c,v 1.92 2005/04/13 13:22:35 dwmw2 Exp $ + * $Id: write.c,v 1.93 2005/07/17 06:56:21 dedekind Exp $ * */ @@ -54,34 +54,6 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint return 0; } -#if CONFIG_JFFS2_FS_DEBUG > 0 -static void writecheck(struct jffs2_sb_info *c, uint32_t ofs) -{ - unsigned char buf[16]; - size_t retlen; - int ret, i; - - ret = jffs2_flash_read(c, ofs, 16, &retlen, buf); - if (ret || (retlen != 16)) { - D1(printk(KERN_DEBUG "read failed or short in writecheck(). ret %d, retlen %zd\n", ret, retlen)); - return; - } - ret = 0; - for (i=0; i<16; i++) { - if (buf[i] != 0xff) - ret = 1; - } - if (ret) { - printk(KERN_WARNING "ARGH. About to write node to 0x%08x on flash, but there are data already there:\n", ofs); - printk(KERN_WARNING "0x%08x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - ofs, - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], - buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]); - } -} -#endif - - /* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it, write it to the flash, link it into the existing inode/fragment list */ @@ -106,7 +78,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 vecs[1].iov_base = (unsigned char *)data; vecs[1].iov_len = datalen; - D1(writecheck(c, flash_ofs)); + jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) { printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen); @@ -177,8 +149,8 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 D1(printk(KERN_DEBUG "Retrying failed write.\n")); - ACCT_SANITY_CHECK(c,jeb); - D1(ACCT_PARANOIA_CHECK(jeb)); + jffs2_dbg_acct_sanity_check(c,jeb); + jffs2_dbg_acct_paranoia_check(c, jeb); if (alloc_mode == ALLOC_GC) { ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &flash_ofs, &dummy); @@ -194,8 +166,8 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 if (!ret) { D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs)); - ACCT_SANITY_CHECK(c,jeb); - D1(ACCT_PARANOIA_CHECK(jeb)); + jffs2_dbg_acct_sanity_check(c,jeb); + jffs2_dbg_acct_paranoia_check(c, jeb); goto retry; } @@ -232,7 +204,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen))); if (retried) { - ACCT_SANITY_CHECK(c,NULL); + jffs2_dbg_acct_sanity_check(c,NULL); } return fn; @@ -250,7 +222,8 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff D1(printk(KERN_DEBUG "jffs2_write_dirent(ino #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x)\n", je32_to_cpu(rd->pino), name, name, je32_to_cpu(rd->ino), je32_to_cpu(rd->name_crc))); - D1(writecheck(c, flash_ofs)); + + jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) { printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n"); @@ -322,8 +295,8 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff D1(printk(KERN_DEBUG "Retrying failed write.\n")); - ACCT_SANITY_CHECK(c,jeb); - D1(ACCT_PARANOIA_CHECK(jeb)); + jffs2_dbg_acct_sanity_check(c,jeb); + jffs2_dbg_acct_paranoia_check(c, jeb); if (alloc_mode == ALLOC_GC) { ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &flash_ofs, &dummy); @@ -338,8 +311,8 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff if (!ret) { D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs)); - ACCT_SANITY_CHECK(c,jeb); - D1(ACCT_PARANOIA_CHECK(jeb)); + jffs2_dbg_acct_sanity_check(c,jeb); + jffs2_dbg_acct_paranoia_check(c, jeb); goto retry; } D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); @@ -359,7 +332,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff spin_unlock(&c->erase_completion_lock); if (retried) { - ACCT_SANITY_CHECK(c,NULL); + jffs2_dbg_acct_sanity_check(c,NULL); } return fd; -- cgit v1.2.3 From 2b79adcca147c9f8fd1094ab4cb342d7e1790d70 Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Sun, 17 Jul 2005 12:13:51 +0100 Subject: [JFFS2] Use f->target instead of f->dents for symlink target JFFS2 uses f->dents to store the pointer to the symlink target string (in case the inode is symlink). This is somewhat ugly to use the same field for different reasons. Introduce distinct field f->target for this purpose. Note, f->fragtree, f->dents, f->target may probably be put in a union. Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/dir.c | 12 ++++++------ fs/jffs2/os-linux.h | 3 ++- fs/jffs2/readinode.c | 45 ++++++++++++++++++++------------------------- fs/jffs2/symlink.c | 26 ++++++++++++-------------- include/linux/jffs2_fs_i.h | 5 ++++- 5 files changed, 44 insertions(+), 47 deletions(-) diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 3ca0d25eef1..5738df22377 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: dir.c,v 1.86 2005/07/06 12:13:09 dwmw2 Exp $ + * $Id: dir.c,v 1.87 2005/07/17 11:13:46 dedekind Exp $ * */ @@ -344,9 +344,9 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char return PTR_ERR(fn); } - /* We use f->dents field to store the target path. */ - f->dents = kmalloc(targetlen + 1, GFP_KERNEL); - if (!f->dents) { + /* We use f->target field to store the target path. */ + f->target = kmalloc(targetlen + 1, GFP_KERNEL); + if (!f->target) { printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1); up(&f->sem); jffs2_complete_reservation(c); @@ -354,8 +354,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char return -ENOMEM; } - memcpy(f->dents, target, targetlen + 1); - D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached\n", (char *)f->dents)); + memcpy(f->target, target, targetlen + 1); + D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached\n", (char *)f->target)); /* No data here. Only a metadata node, which will be obsoleted by the first data write diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index d900c8929b0..0fc952eaf8c 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: os-linux.h,v 1.58 2005/07/12 02:34:35 tpoynor Exp $ + * $Id: os-linux.h,v 1.59 2005/07/17 11:13:46 dedekind Exp $ * */ @@ -57,6 +57,7 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) f->fragtree = RB_ROOT; f->metadata = NULL; f->dents = NULL; + f->target = NULL; f->flags = 0; f->usercompr = 0; } diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index cf39bcf3e3c..49da1a6cfc8 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.126 2005/07/17 06:56:21 dedekind Exp $ + * $Id: readinode.c,v 1.127 2005/07/17 11:13:46 dedekind Exp $ * */ @@ -547,11 +547,10 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, if (f->inocache->state != INO_STATE_CHECKING) { /* Symlink's inode data is the target path. Read it and - * keep in RAM to facilitate quick follow symlink operation. - * We use f->dents field to store the target path, which - * is somewhat ugly. */ - f->dents = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL); - if (!f->dents) { + * keep in RAM to facilitate quick follow symlink + * operation. */ + f->target = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL); + if (!f->target) { printk(KERN_WARNING "Can't allocate %d bytes of memory " "for the symlink target path cache\n", je32_to_cpu(latest_node->csize)); @@ -561,21 +560,21 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, } ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node), - je32_to_cpu(latest_node->csize), &retlen, (char *)f->dents); + je32_to_cpu(latest_node->csize), &retlen, (char *)f->target); if (ret || retlen != je32_to_cpu(latest_node->csize)) { if (retlen != je32_to_cpu(latest_node->csize)) ret = -EIO; - kfree(f->dents); - f->dents = NULL; + kfree(f->target); + f->target = NULL; up(&f->sem); jffs2_do_clear_inode(c, f); return -ret; } - ((char *)f->dents)[je32_to_cpu(latest_node->csize)] = '\0'; + f->target[je32_to_cpu(latest_node->csize)] = '\0'; D1(printk(KERN_DEBUG "jffs2_do_read_inode(): symlink's target '%s' cached\n", - (char *)f->dents)); + f->target)); } /* fall through... */ @@ -638,20 +637,16 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL); - /* For symlink inodes we us f->dents to store the target path name */ - if (S_ISLNK(OFNI_EDONI_2SFFJ(f)->i_mode)) { - if (f->dents) { - kfree(f->dents); - f->dents = NULL; - } - } else { - fds = f->dents; - - while(fds) { - fd = fds; - fds = fd->next; - jffs2_free_full_dirent(fd); - } + if (f->target) { + kfree(f->target); + f->target = NULL; + } + + fds = f->dents; + while(fds) { + fd = fds; + fds = fd->next; + jffs2_free_full_dirent(fd); } if (f->inocache && f->inocache->state != INO_STATE_CHECKING) { diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c index 82ef484f5e1..6fd5ee4f90b 100644 --- a/fs/jffs2/symlink.c +++ b/fs/jffs2/symlink.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: symlink.c,v 1.16 2005/03/01 10:50:48 dedekind Exp $ + * $Id: symlink.c,v 1.18 2005/11/06 11:03:27 gleixner Exp $ * */ @@ -30,35 +30,33 @@ struct inode_operations jffs2_symlink_inode_operations = static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) { struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode); - char *p = (char *)f->dents; - + char *p = (char *)f->target; + /* * We don't acquire the f->sem mutex here since the only data we - * use is f->dents which in case of the symlink inode points to the - * symlink's target path. + * use is f->target. * - * 1. If we are here the inode has already built and f->dents has + * 1. If we are here the inode has already built and f->target has * to point to the target path. - * 2. Nobody uses f->dents (if the inode is symlink's inode). The - * exception is inode freeing function which frees f->dents. But + * 2. Nobody uses f->target (if the inode is symlink's inode). The + * exception is inode freeing function which frees f->target. But * it can't be called while we are here and before VFS has - * stopped using our f->dents string which we provide by means of + * stopped using our f->target string which we provide by means of * nd_set_link() call. */ if (!p) { printk(KERN_ERR "jffs2_follow_link(): can't find symlink taerget\n"); p = ERR_PTR(-EIO); - } else { - D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->dents)); } + D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->target)); nd_set_link(nd, p); /* - * We unlock the f->sem mutex but VFS will use the f->dents string. This is safe - * since the only way that may cause f->dents to be changed is iput() operation. - * But VFS will not use f->dents after iput() has been called. + * We will unlock the f->sem mutex but VFS will use the f->target string. This is safe + * since the only way that may cause f->target to be changed is iput() operation. + * But VFS will not use f->target after iput() has been called. */ return NULL; } diff --git a/include/linux/jffs2_fs_i.h b/include/linux/jffs2_fs_i.h index 6dbb1cce664..a5db884ec60 100644 --- a/include/linux/jffs2_fs_i.h +++ b/include/linux/jffs2_fs_i.h @@ -1,4 +1,4 @@ -/* $Id: jffs2_fs_i.h,v 1.17 2004/11/11 23:51:27 dwmw2 Exp $ */ +/* $Id: jffs2_fs_i.h,v 1.18 2005/07/17 11:13:48 dedekind Exp $ */ #ifndef _JFFS2_FS_I #define _JFFS2_FS_I @@ -32,6 +32,9 @@ struct jffs2_inode_info { /* Directory entries */ struct jffs2_full_dirent *dents; + /* The target path if this is the inode of a symlink */ + unsigned char *target; + /* Some stuff we just have to keep in-core at all times, for each inode. */ struct jffs2_inode_cache *inocache; -- cgit v1.2.3 From 61a39b694137cef6059a0714c3b1847aabe53b90 Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Sun, 17 Jul 2005 13:01:46 +0100 Subject: [JFFS2] Debug code clean up - step 2 If debugging is disabled, define debugging functions as empty macros, instead of using Dx() explicitly. Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/build.c | 4 ++-- fs/jffs2/fs.c | 4 ++-- fs/jffs2/gc.c | 6 +++--- fs/jffs2/readinode.c | 6 +++--- fs/jffs2/wbuf.c | 6 +++--- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index 3a0b003d73a..b87d4010d36 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: build.c,v 1.72 2005/07/17 06:56:20 dedekind Exp $ + * $Id: build.c,v 1.74 2005/07/17 12:01:42 dedekind Exp $ * */ @@ -168,7 +168,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) c->flags &= ~JFFS2_SB_FLAG_BUILDING; D1(printk(KERN_DEBUG "Pass 3 complete\n")); - D2(jffs2_dbg_dump_block_lists(c)); + jffs2_dbg_dump_block_lists(c); /* Rotate the lists by some number to ensure wear levelling */ jffs2_rotate_lists(c); diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 6c8a9d5d56a..934c9f5090c 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: fs.c,v 1.57 2005/07/17 06:56:21 dedekind Exp $ + * $Id: fs.c,v 1.58 2005/07/17 12:01:42 dedekind Exp $ * */ @@ -203,7 +203,7 @@ int jffs2_statfs(struct super_block *sb, struct kstatfs *buf) buf->f_bavail = buf->f_bfree = avail >> PAGE_SHIFT; - D2(jffs2_dbg_dump_block_lists(c)); + jffs2_dbg_dump_block_lists(c); spin_unlock(&c->erase_completion_lock); diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 337ab49ab24..6b5da0a1d31 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: gc.c,v 1.149 2005/07/17 06:56:21 dedekind Exp $ + * $Id: gc.c,v 1.150 2005/07/17 12:01:43 dedekind Exp $ * */ @@ -111,7 +111,7 @@ again: ret->wasted_size = 0; } - D2(jffs2_dbg_dump_block_lists(c)); + jffs2_dbg_dump_block_lists(c); return ret; } @@ -142,7 +142,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) if (c->checked_ino > c->highest_ino) { printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n", c->unchecked_size); - D2(jffs2_dbg_dump_block_lists(c)); + jffs2_dbg_dump_block_lists(c); spin_unlock(&c->erase_completion_lock); BUG(); } diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 49da1a6cfc8..02a20d7b4d5 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.127 2005/07/17 11:13:46 dedekind Exp $ + * $Id: readinode.c,v 1.128 2005/07/17 12:01:43 dedekind Exp $ * */ @@ -92,8 +92,8 @@ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_in mark_ref_normal(next->node->raw); } } - D2(jffs2_dbg_fragtree_paranoia_check(f)); - D2(jffs2_dbg_dump_fragtree(f)); + jffs2_dbg_fragtree_paranoia_check(f); + jffs2_dbg_dump_fragtree(f); return 0; } diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 85ae51d2060..5a820f4ea35 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -9,7 +9,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: wbuf.c,v 1.93 2005/07/17 06:56:21 dedekind Exp $ + * $Id: wbuf.c,v 1.94 2005/07/17 12:01:43 dedekind Exp $ * */ @@ -139,7 +139,7 @@ static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock { D1(printk("About to refile bad block at %08x\n", jeb->offset)); - D2(jffs2_dbg_dump_block_lists(c)); + jffs2_dbg_dump_block_lists(c); /* File the existing block on the bad_used_list.... */ if (c->nextblock == jeb) c->nextblock = NULL; @@ -156,7 +156,7 @@ static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock c->nr_erasing_blocks++; jffs2_erase_pending_trigger(c); } - D2(jffs2_dbg_dump_block_lists(c)); + jffs2_dbg_dump_block_lists(c); /* Adjust its size counts accordingly */ c->wasted_size += jeb->free_size; -- cgit v1.2.3 From 6dac02a5e1bba0bb88ece50160fc4a64cccf30d1 Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Mon, 18 Jul 2005 12:21:23 +0100 Subject: [JFFS2] Fix slab panic When JFFS22 is unable to read the root inode, the bad root inode object is not freed and remains sticked in the jffs2_i slab cache. When we further try to free the slab cache (e.g., on rmmod jffs2), slab allocator subsystem panics. Fix this bug. Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/fs.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 934c9f5090c..a6661e8be25 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: fs.c,v 1.58 2005/07/17 12:01:42 dedekind Exp $ + * $Id: fs.c,v 1.59 2005/07/18 11:21:19 dedekind Exp $ * */ @@ -517,7 +517,7 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) root_i = iget(sb, 1); if (is_bad_inode(root_i)) { D1(printk(KERN_WARNING "get root inode failed\n")); - goto out_nodes; + goto out_root_i; } D1(printk(KERN_DEBUG "jffs2_do_fill_super(): d_alloc_root()\n")); @@ -535,7 +535,6 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) out_root_i: iput(root_i); - out_nodes: jffs2_free_ino_caches(c); jffs2_free_raw_node_refs(c); if (c->mtd->flags & MTD_NO_VIRTBLOCKS) -- cgit v1.2.3 From d3997abf699655d2ec012e944fb34668cc3ec6d7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 6 Nov 2005 15:45:00 +0000 Subject: [ARM] Fix another use of // as a comment // disagrees with ld's script parsing ability. Don't use it. Signed-off-by: Russell King --- include/asm-arm/arch-iop3xx/iop331.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-arm/arch-iop3xx/iop331.h b/include/asm-arm/arch-iop3xx/iop331.h index 96adffd8bad..fbf0cc11bdd 100644 --- a/include/asm-arm/arch-iop3xx/iop331.h +++ b/include/asm-arm/arch-iop3xx/iop331.h @@ -42,7 +42,7 @@ /* this can be 128M if OMWTVR1 is set */ #define IOP331_PCI_MEM_WINDOW_SIZE 0x04000000 /* 64M outbound window */ -//#define IOP331_PCI_MEM_WINDOW_SIZE (~*IOP331_IALR1 + 1) +/* #define IOP331_PCI_MEM_WINDOW_SIZE (~*IOP331_IALR1 + 1) */ #define IOP331_PCI_LOWER_MEM_PA 0x80000000 #define IOP331_PCI_LOWER_MEM_BA (*IOP331_OMWTVR0) #define IOP331_PCI_UPPER_MEM_PA (IOP331_PCI_LOWER_MEM_PA + IOP331_PCI_MEM_WINDOW_SIZE - 1) -- cgit v1.2.3 From 4299051ebe89ab1eeadeaf4cf06ce63421412232 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 6 Nov 2005 15:46:57 +0000 Subject: [ARM] Fix missing declaration of cache_is_vivt() Signed-off-by: Russell King --- arch/arm/kernel/ecard.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index dceb826bd21..c445b0a848b 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -41,6 +41,7 @@ #include #include +#include #include #include #include -- cgit v1.2.3 From e0c8e42f8f218063ff6838b25038ccef7ddf257e Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Sun, 24 Jul 2005 16:14:17 +0100 Subject: [JFFS2] Debug code clean up - step 3 Various simplifiactions. printk format corrections. Convert more code to use the new debug functions. Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/build.c | 6 +- fs/jffs2/debug.c | 526 ++++++++++++++++++++++++++++++++++++--------------- fs/jffs2/debug.h | 251 ++++++++++++++++++++---- fs/jffs2/erase.c | 9 +- fs/jffs2/fs.c | 8 +- fs/jffs2/gc.c | 8 +- fs/jffs2/nodelist.c | 4 +- fs/jffs2/nodelist.h | 4 +- fs/jffs2/nodemgmt.c | 13 +- fs/jffs2/read.c | 3 +- fs/jffs2/readinode.c | 8 +- fs/jffs2/scan.c | 6 +- fs/jffs2/wbuf.c | 17 +- fs/jffs2/write.c | 6 +- 14 files changed, 630 insertions(+), 239 deletions(-) diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index b87d4010d36..f08984a64a5 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: build.c,v 1.74 2005/07/17 12:01:42 dedekind Exp $ + * $Id: build.c,v 1.75 2005/07/22 10:32:07 dedekind Exp $ * */ @@ -104,7 +104,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) goto exit; D1(printk(KERN_DEBUG "Scanned flash completely\n")); - D2(jffs2_dbg_dump_block_lists(c)); + jffs2_dbg_dump_block_lists_nolock(c); c->flags |= JFFS2_SB_FLAG_BUILDING; /* Now scan the directory tree, increasing nlink according to every dirent found. */ @@ -168,7 +168,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) c->flags &= ~JFFS2_SB_FLAG_BUILDING; D1(printk(KERN_DEBUG "Pass 3 complete\n")); - jffs2_dbg_dump_block_lists(c); + jffs2_dbg_dump_block_lists_nolock(c); /* Rotate the lists by some number to ensure wear levelling */ jffs2_rotate_lists(c); diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c index 9da524ca4e6..fb88eb19711 100644 --- a/fs/jffs2/debug.c +++ b/fs/jffs2/debug.c @@ -7,18 +7,30 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.c,v 1.1 2005/07/17 06:56:20 dedekind Exp $ + * $Id: debug.c,v 1.7 2005/07/24 15:14:14 dedekind Exp $ * */ #include #include +#include +#include #include "nodelist.h" #include "debug.h" #ifdef JFFS2_DBG_PARANOIA_CHECKS - +/* + * Check the fragtree. + */ void -jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f) +__jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f) +{ + down(&f->sem); + __jffs2_dbg_fragtree_paranoia_check_nolock(f); + up(&f->sem); +} + +void +__jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f) { struct jffs2_node_frag *frag; int bitched = 0; @@ -31,7 +43,7 @@ jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f) if (ref_flags(fn->raw) == REF_PRISTINE) { if (fn->frags > 1) { - printk(KERN_ERR "REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2\n", + JFFS2_ERROR("REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2.\n", ref_offset(fn->raw), fn->frags); bitched = 1; } @@ -43,15 +55,15 @@ jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f) to tell a hole node. */ if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag) && frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) { - printk(KERN_ERR "REF_PRISTINE node at 0x%08x had a previous non-hole frag " - "in the same page. Tell dwmw2\n", ref_offset(fn->raw)); + JFFS2_ERROR("REF_PRISTINE node at 0x%08x had a previous non-hole frag " + "in the same page. Tell dwmw2.\n", ref_offset(fn->raw)); bitched = 1; } if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag) && frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) { - printk(KERN_ERR "REF_PRISTINE node at 0x%08x (%08x-%08x) had a following " - "non-hole frag in the same page. Tell dwmw2\n", + JFFS2_ERROR("REF_PRISTINE node at 0x%08x (%08x-%08x) had a following " + "non-hole frag in the same page. Tell dwmw2.\n", ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size); bitched = 1; } @@ -59,8 +71,8 @@ jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f) } if (bitched) { - printk(KERN_ERR "Fragtree is corrupted. Fragtree dump:\n"); - jffs2_dbg_dump_fragtree(f); + JFFS2_ERROR("fragtree is corrupted.\n"); + __jffs2_dbg_dump_fragtree_nolock(f); BUG(); } } @@ -69,7 +81,8 @@ jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f) * Check if the flash contains all 0xFF before we start writing. */ void -jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c, uint32_t ofs, int len) +__jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c, + uint32_t ofs, int len) { size_t retlen; int ret, i; @@ -81,8 +94,8 @@ jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c, uint32_t ofs, int len ret = jffs2_flash_read(c, ofs, len, &retlen, buf); if (ret || (retlen != len)) { - printk(KERN_WARNING "read %d bytes failed or short in %s(). ret %d, retlen %zd\n", - len, __FUNCTION__, ret, retlen); + JFFS2_WARNING("read %d bytes failed or short. ret %d, retlen %zd.\n", + len, ret, retlen); kfree(buf); return; } @@ -93,9 +106,9 @@ jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c, uint32_t ofs, int len ret = 1; if (ret) { - printk(KERN_ERR "ARGH. About to write node to %#08x on flash, but there are data " - "already there. The first corrupted byte is at %#08x.\n", ofs, ofs + i); - jffs2_dbg_dump_buffer(buf, len, ofs); + JFFS2_ERROR("argh, about to write node to %#08x on flash, but there are data " + "already there. The first corrupted byte is at %#08x offset.\n", ofs, ofs + i); + __jffs2_dbg_dump_buffer(buf, len, ofs); kfree(buf); BUG(); } @@ -107,7 +120,17 @@ jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c, uint32_t ofs, int len * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'. */ void -jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) +__jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c, + struct jffs2_eraseblock *jeb) +{ + spin_lock(&c->erase_completion_lock); + __jffs2_dbg_acct_paranoia_check_nolock(c, jeb); + spin_unlock(&c->erase_completion_lock); +} + +void +__jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c, + struct jffs2_eraseblock *jeb) { uint32_t my_used_size = 0; uint32_t my_unchecked_size = 0; @@ -119,11 +142,9 @@ jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c, struct jffs2_eraseblock * if (ref2->flash_offset < jeb->offset || ref2->flash_offset > jeb->offset + c->sector_size) { - printk(KERN_ERR "node_ref %#08x shouldn't be in block at %#08x!\n", + JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n", ref_offset(ref2), jeb->offset); - jffs2_dbg_dump_node_refs(c, jeb); - jffs2_dbg_dump_block_lists(c); - BUG(); + goto error; } if (ref_flags(ref2) == REF_UNCHECKED) @@ -134,69 +155,82 @@ jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c, struct jffs2_eraseblock * my_dirty_size += totlen; if ((!ref2->next_phys) != (ref2 == jeb->last_node)) { - printk(KERN_ERR "node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), " - "last_node is at %#08x (mem %p)\n", - ref_offset(ref2), ref2, ref_offset(ref2->next_phys), ref2->next_phys, - ref_offset(jeb->last_node), jeb->last_node); - jffs2_dbg_dump_node_refs(c, jeb); - jffs2_dbg_dump_block_lists(c); - BUG(); + JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), " + "last_node is at %#08x (mem %p).\n", + ref_offset(ref2), ref2, ref_offset(ref2->next_phys), ref2->next_phys, + ref_offset(jeb->last_node), jeb->last_node); + goto error; } ref2 = ref2->next_phys; } if (my_used_size != jeb->used_size) { - printk(KERN_ERR "Calculated used size %#08x != stored used size %#08x\n", - my_used_size, jeb->used_size); - jffs2_dbg_dump_node_refs(c, jeb); - jffs2_dbg_dump_block_lists(c); - BUG(); + JFFS2_ERROR("Calculated used size %#08x != stored used size %#08x.\n", + my_used_size, jeb->used_size); + goto error; } if (my_unchecked_size != jeb->unchecked_size) { - printk(KERN_ERR "Calculated unchecked size %#08x != stored unchecked size %#08x\n", - my_unchecked_size, jeb->unchecked_size); - jffs2_dbg_dump_node_refs(c, jeb); - jffs2_dbg_dump_block_lists(c); - BUG(); + JFFS2_ERROR("Calculated unchecked size %#08x != stored unchecked size %#08x.\n", + my_unchecked_size, jeb->unchecked_size); + goto error; } +#if 0 + /* This should work when we implement ref->__totlen elemination */ if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) { - printk(KERN_ERR "Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n", + JFFS2_ERROR("Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n", my_dirty_size, jeb->dirty_size + jeb->wasted_size); - jffs2_dbg_dump_node_refs(c, jeb); - jffs2_dbg_dump_block_lists(c); - BUG(); + goto error; } if (jeb->free_size == 0 && my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) { - printk(KERN_ERR "The sum of all nodes in block (%#x) != size of block (%#x)\n", + JFFS2_ERROR("The sum of all nodes in block (%#x) != size of block (%#x)\n", my_used_size + my_unchecked_size + my_dirty_size, c->sector_size); - jffs2_dbg_dump_node_refs(c, jeb); - jffs2_dbg_dump_block_lists(c); - BUG(); + goto error; } +#endif + + return; + +error: + __jffs2_dbg_dump_node_refs_nolock(c, jeb); + __jffs2_dbg_dump_jeb_nolock(jeb); + __jffs2_dbg_dump_block_lists_nolock(c); + BUG(); + } -#endif /* JFFS2_PARANOIA_CHECKS */ +#endif /* JFFS2_DBG_PARANOIA_CHECKS */ -#if defined(JFFS2_PARANOIA_CHECKS) || (CONFIG_JFFS2_FS_DEBUG > 0) +#if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS) /* * Dump the node_refs of the 'jeb' JFFS2 eraseblock. */ void -jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) +__jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c, + struct jffs2_eraseblock *jeb) +{ + spin_lock(&c->erase_completion_lock); + __jffs2_dbg_dump_node_refs_nolock(c, jeb); + spin_unlock(&c->erase_completion_lock); +} + +void +__jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c, + struct jffs2_eraseblock *jeb) { struct jffs2_raw_node_ref *ref; int i = 0; + JFFS2_DEBUG("Dump node_refs of the eraseblock %#08x\n", jeb->offset); if (!jeb->first_node) { - printk(KERN_DEBUG "no nodes in block %#08x\n", jeb->offset); + JFFS2_DEBUG("no nodes in the eraseblock %#08x\n", jeb->offset); return; } - printk(KERN_DEBUG); + printk(JFFS2_DBG_LVL); for (ref = jeb->first_node; ; ref = ref->next_phys) { printk("%#08x(%#x)", ref_offset(ref), ref->__totlen); if (ref->next_phys) @@ -205,46 +239,83 @@ jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) break; if (++i == 4) { i = 0; - printk("\n" KERN_DEBUG); + printk("\n" JFFS2_DBG_LVL); } } printk("\n"); } +/* + * Dump an eraseblock's space accounting. + */ +void +__jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) +{ + spin_lock(&c->erase_completion_lock); + __jffs2_dbg_dump_jeb_nolock(jeb); + spin_unlock(&c->erase_completion_lock); +} + void -jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c) +__jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb) { - printk(KERN_DEBUG "flash_size: %#08x\n", c->flash_size); - printk(KERN_DEBUG "used_size: %#08x\n", c->used_size); - printk(KERN_DEBUG "dirty_size: %#08x\n", c->dirty_size); - printk(KERN_DEBUG "wasted_size: %#08x\n", c->wasted_size); - printk(KERN_DEBUG "unchecked_size: %#08x\n", c->unchecked_size); - printk(KERN_DEBUG "free_size: %#08x\n", c->free_size); - printk(KERN_DEBUG "erasing_size: %#08x\n", c->erasing_size); - printk(KERN_DEBUG "bad_size: %#08x\n", c->bad_size); - printk(KERN_DEBUG "sector_size: %#08x\n", c->sector_size); - printk(KERN_DEBUG "jffs2_reserved_blocks size: %#08x\n", + if (!jeb) + return; + + JFFS2_DEBUG("dump space accounting for the eraseblock at %#08x:\n", + jeb->offset); + + printk(JFFS2_DBG_LVL "used_size: %#08x\n", jeb->used_size); + printk(JFFS2_DBG_LVL "dirty_size: %#08x\n", jeb->dirty_size); + printk(JFFS2_DBG_LVL "wasted_size: %#08x\n", jeb->wasted_size); + printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n", jeb->unchecked_size); + printk(JFFS2_DBG_LVL "free_size: %#08x\n", jeb->free_size); +} + +void +__jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c) +{ + spin_lock(&c->erase_completion_lock); + __jffs2_dbg_dump_block_lists_nolock(c); + spin_unlock(&c->erase_completion_lock); +} + +void +__jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) +{ + JFFS2_DEBUG("dump JFFS2 blocks lists:\n"); + + printk(JFFS2_DBG_LVL "flash_size: %#08x\n", c->flash_size); + printk(JFFS2_DBG_LVL "used_size: %#08x\n", c->used_size); + printk(JFFS2_DBG_LVL "dirty_size: %#08x\n", c->dirty_size); + printk(JFFS2_DBG_LVL "wasted_size: %#08x\n", c->wasted_size); + printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n", c->unchecked_size); + printk(JFFS2_DBG_LVL "free_size: %#08x\n", c->free_size); + printk(JFFS2_DBG_LVL "erasing_size: %#08x\n", c->erasing_size); + printk(JFFS2_DBG_LVL "bad_size: %#08x\n", c->bad_size); + printk(JFFS2_DBG_LVL "sector_size: %#08x\n", c->sector_size); + printk(JFFS2_DBG_LVL "jffs2_reserved_blocks size: %#08x\n", c->sector_size * c->resv_blocks_write); if (c->nextblock) - printk(KERN_DEBUG "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", - c->nextblock->offset, c->nextblock->used_size, - c->nextblock->dirty_size, c->nextblock->wasted_size, - c->nextblock->unchecked_size, c->nextblock->free_size); + printk(JFFS2_DBG_LVL "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, " + "unchecked %#08x, free %#08x)\n", + c->nextblock->offset, c->nextblock->used_size, + c->nextblock->dirty_size, c->nextblock->wasted_size, + c->nextblock->unchecked_size, c->nextblock->free_size); else - printk(KERN_DEBUG "nextblock: NULL\n"); + printk(JFFS2_DBG_LVL "nextblock: NULL\n"); if (c->gcblock) - printk(KERN_DEBUG "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", - c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size, - c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size); + printk(JFFS2_DBG_LVL "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, " + "unchecked %#08x, free %#08x)\n", + c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size, + c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size); else - printk(KERN_DEBUG "gcblock: NULL\n"); + printk(JFFS2_DBG_LVL "gcblock: NULL\n"); if (list_empty(&c->clean_list)) { - printk(KERN_DEBUG "clean_list: empty\n"); + printk(JFFS2_DBG_LVL "clean_list: empty\n"); } else { struct list_head *this; int numblocks = 0; @@ -255,19 +326,19 @@ jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c) numblocks ++; dirty += jeb->wasted_size; if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(KERN_DEBUG "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, - jeb->unchecked_size, jeb->free_size); + printk(JFFS2_DBG_LVL "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " + "unchecked %#08x, free %#08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, + jeb->unchecked_size, jeb->free_size); } } - printk (KERN_DEBUG "Contains %d blocks with total wasted size %u, average wasted size: %u\n", - numblocks, dirty, dirty / numblocks); + printk (JFFS2_DBG_LVL "Contains %d blocks with total wasted size %u, average wasted size: %u\n", + numblocks, dirty, dirty / numblocks); } if (list_empty(&c->very_dirty_list)) { - printk(KERN_DEBUG "very_dirty_list: empty\n"); + printk(JFFS2_DBG_LVL "very_dirty_list: empty\n"); } else { struct list_head *this; int numblocks = 0; @@ -279,19 +350,19 @@ jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c) numblocks ++; dirty += jeb->dirty_size; if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(KERN_DEBUG "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, - jeb->unchecked_size, jeb->free_size); + printk(JFFS2_DBG_LVL "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " + "unchecked %#08x, free %#08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, + jeb->unchecked_size, jeb->free_size); } } - printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n", - numblocks, dirty, dirty / numblocks); + printk (JFFS2_DBG_LVL "Contains %d blocks with total dirty size %u, average dirty size: %u\n", + numblocks, dirty, dirty / numblocks); } if (list_empty(&c->dirty_list)) { - printk(KERN_DEBUG "dirty_list: empty\n"); + printk(JFFS2_DBG_LVL "dirty_list: empty\n"); } else { struct list_head *this; int numblocks = 0; @@ -303,19 +374,19 @@ jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c) numblocks ++; dirty += jeb->dirty_size; if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(KERN_DEBUG "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, - jeb->unchecked_size, jeb->free_size); + printk(JFFS2_DBG_LVL "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " + "unchecked %#08x, free %#08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, + jeb->unchecked_size, jeb->free_size); } } - printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n", + printk (JFFS2_DBG_LVL "contains %d blocks with total dirty size %u, average dirty size: %u\n", numblocks, dirty, dirty / numblocks); } if (list_empty(&c->erasable_list)) { - printk(KERN_DEBUG "erasable_list: empty\n"); + printk(JFFS2_DBG_LVL "erasable_list: empty\n"); } else { struct list_head *this; @@ -323,16 +394,16 @@ jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c) struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(KERN_DEBUG "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, - jeb->unchecked_size, jeb->free_size); + printk(JFFS2_DBG_LVL "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " + "unchecked %#08x, free %#08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, + jeb->unchecked_size, jeb->free_size); } } } if (list_empty(&c->erasing_list)) { - printk(KERN_DEBUG "erasing_list: empty\n"); + printk(JFFS2_DBG_LVL "erasing_list: empty\n"); } else { struct list_head *this; @@ -340,16 +411,16 @@ jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c) struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(KERN_DEBUG "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, - jeb->unchecked_size, jeb->free_size); + printk(JFFS2_DBG_LVL "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " + "unchecked %#08x, free %#08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, + jeb->unchecked_size, jeb->free_size); } } } if (list_empty(&c->erase_pending_list)) { - printk(KERN_DEBUG "erase_pending_list: empty\n"); + printk(JFFS2_DBG_LVL "erase_pending_list: empty\n"); } else { struct list_head *this; @@ -357,16 +428,16 @@ jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c) struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(KERN_DEBUG "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, - jeb->unchecked_size, jeb->free_size); + printk(JFFS2_DBG_LVL "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " + "unchecked %#08x, free %#08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, + jeb->unchecked_size, jeb->free_size); } } } if (list_empty(&c->erasable_pending_wbuf_list)) { - printk(KERN_DEBUG "erasable_pending_wbuf_list: empty\n"); + printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: empty\n"); } else { struct list_head *this; @@ -374,16 +445,16 @@ jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c) struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(KERN_DEBUG "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, " - "wasted %#08x, unchecked %#08x, free %#08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, - jeb->unchecked_size, jeb->free_size); + printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, " + "wasted %#08x, unchecked %#08x, free %#08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, + jeb->unchecked_size, jeb->free_size); } } } if (list_empty(&c->free_list)) { - printk(KERN_DEBUG "free_list: empty\n"); + printk(JFFS2_DBG_LVL "free_list: empty\n"); } else { struct list_head *this; @@ -391,16 +462,16 @@ jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c) struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(KERN_DEBUG "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, - jeb->unchecked_size, jeb->free_size); + printk(JFFS2_DBG_LVL "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " + "unchecked %#08x, free %#08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, + jeb->unchecked_size, jeb->free_size); } } } if (list_empty(&c->bad_list)) { - printk(KERN_DEBUG "bad_list: empty\n"); + printk(JFFS2_DBG_LVL "bad_list: empty\n"); } else { struct list_head *this; @@ -408,16 +479,16 @@ jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c) struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(KERN_DEBUG "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, - jeb->unchecked_size, jeb->free_size); + printk(JFFS2_DBG_LVL "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " + "unchecked %#08x, free %#08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, + jeb->unchecked_size, jeb->free_size); } } } if (list_empty(&c->bad_used_list)) { - printk(KERN_DEBUG "bad_used_list: empty\n"); + printk(JFFS2_DBG_LVL "bad_used_list: empty\n"); } else { struct list_head *this; @@ -425,34 +496,42 @@ jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c) struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(KERN_DEBUG "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", - jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, - jeb->unchecked_size, jeb->free_size); + printk(JFFS2_DBG_LVL "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " + "unchecked %#08x, free %#08x)\n", + jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, + jeb->unchecked_size, jeb->free_size); } } } } void -jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f) +__jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f) +{ + down(&f->sem); + jffs2_dbg_dump_fragtree_nolock(f); + up(&f->sem); +} + +void +__jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f) { struct jffs2_node_frag *this = frag_first(&f->fragtree); uint32_t lastofs = 0; int buggy = 0; - printk(KERN_DEBUG "inode is ino #%u\n", f->inocache->ino); + JFFS2_DEBUG("dump fragtree of ino #%u\n", f->inocache->ino); while(this) { if (this->node) - printk(KERN_DEBUG "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), " - "right (%p), parent (%p)\n", - this->ofs, this->ofs+this->size, ref_offset(this->node->raw), - ref_flags(this->node->raw), this, frag_left(this), frag_right(this), - frag_parent(this)); + printk(JFFS2_DBG_LVL "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), " + "right (%p), parent (%p)\n", + this->ofs, this->ofs+this->size, ref_offset(this->node->raw), + ref_flags(this->node->raw), this, frag_left(this), frag_right(this), + frag_parent(this)); else - printk(KERN_DEBUG "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n", - this->ofs, this->ofs+this->size, this, frag_left(this), - frag_right(this), frag_parent(this)); + printk(JFFS2_DBG_LVL "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n", + this->ofs, this->ofs+this->size, this, frag_left(this), + frag_right(this), frag_parent(this)); if (this->ofs != lastofs) buggy = 1; lastofs = this->ofs + this->size; @@ -460,36 +539,171 @@ jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f) } if (f->metadata) - printk(KERN_DEBUG "metadata at 0x%08x\n", ref_offset(f->metadata->raw)); + printk(JFFS2_DBG_LVL "metadata at 0x%08x\n", ref_offset(f->metadata->raw)); if (buggy) { - printk(KERN_ERR "Error! %s(): Frag tree got a hole in it\n", __FUNCTION__); + JFFS2_ERROR("frag tree got a hole in it.\n"); BUG(); } } -#define JFFS3_BUFDUMP_BYTES_PER_LINE 8 +#define JFFS2_BUFDUMP_BYTES_PER_LINE 32 void -jffs2_dbg_dump_buffer(char *buf, int len, uint32_t offs) +__jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs) { - int i = 0; - int skip = offs & ~(JFFS3_BUFDUMP_BYTES_PER_LINE - 1); + int skip; + int i; + + JFFS2_DEBUG("dump from offset %#08x to offset %#08x (%x bytes).\n", + offs, offs + len, len); + i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE; + offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1); + + if (skip != 0) + printk(JFFS2_DBG_LVL "%#08x: ", offs); + + while (skip--) + printk(" "); while (i < len) { - int j = 0; - - printk(KERN_DEBUG "0x#x: \n"); - while (skip) { - printk(" "); - skip -= 1; + if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) { + if (i != 0) + printk("\n"); + offs += JFFS2_BUFDUMP_BYTES_PER_LINE; + printk(JFFS2_DBG_LVL "%0#8x: ", offs); } - while (j < JFFS3_BUFDUMP_BYTES_PER_LINE) { - if (i + j < len) - printk(" %#02x", buf[i + j++]); + printk("%02x ", buf[i]); + + i += 1; + } + + printk("\n"); +} + +/* + * Dump a JFFS2 node. + */ +void +__jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs) +{ + union jffs2_node_union node; + int len = sizeof(union jffs2_node_union); + size_t retlen; + uint32_t crc; + int ret; + + JFFS2_DEBUG("dump node at offset %#08x.\n", ofs); + + ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node); + if (ret || (retlen != len)) { + JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n", + len, ret, retlen); + return; + } + + printk(JFFS2_DBG_LVL "magic:\t%#04x\n", + je16_to_cpu(node.u.magic)); + printk(JFFS2_DBG_LVL "nodetype:\t%#04x\n", + je16_to_cpu(node.u.nodetype)); + printk(JFFS2_DBG_LVL "totlen:\t%#08x\n", + je32_to_cpu(node.u.totlen)); + printk(JFFS2_DBG_LVL "hdr_crc:\t%#08x\n", + je32_to_cpu(node.u.hdr_crc)); + + crc = crc32(0, &node.u, sizeof(node.u) - 4); + if (crc != je32_to_cpu(node.u.hdr_crc)) { + JFFS2_ERROR("wrong common header CRC.\n"); + return; + } + + if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK && + je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK) + { + JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n", + je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK); + return; + } + + switch(je16_to_cpu(node.u.nodetype)) { + + case JFFS2_NODETYPE_INODE: + + printk(JFFS2_DBG_LVL "the node is inode node\n"); + printk(JFFS2_DBG_LVL "ino:\t%#08x\n", + je32_to_cpu(node.i.ino)); + printk(JFFS2_DBG_LVL "version:\t%#08x\n", + je32_to_cpu(node.i.version)); + printk(JFFS2_DBG_LVL "mode:\t%#08x\n", + node.i.mode.m); + printk(JFFS2_DBG_LVL "uid:\t%#04x\n", + je16_to_cpu(node.i.uid)); + printk(JFFS2_DBG_LVL "gid:\t%#04x\n", + je16_to_cpu(node.i.gid)); + printk(JFFS2_DBG_LVL "isize:\t%#08x\n", + je32_to_cpu(node.i.isize)); + printk(JFFS2_DBG_LVL "atime:\t%#08x\n", + je32_to_cpu(node.i.atime)); + printk(JFFS2_DBG_LVL "mtime:\t%#08x\n", + je32_to_cpu(node.i.mtime)); + printk(JFFS2_DBG_LVL "ctime:\t%#08x\n", + je32_to_cpu(node.i.ctime)); + printk(JFFS2_DBG_LVL "offset:\t%#08x\n", + je32_to_cpu(node.i.offset)); + printk(JFFS2_DBG_LVL "csize:\t%#08x\n", + je32_to_cpu(node.i.csize)); + printk(JFFS2_DBG_LVL "dsize:\t%#08x\n", + je32_to_cpu(node.i.dsize)); + printk(JFFS2_DBG_LVL "compr:\t%#02x\n", + node.i.compr); + printk(JFFS2_DBG_LVL "usercompr:\t%#02x\n", + node.i.usercompr); + printk(JFFS2_DBG_LVL "flags:\t%#04x\n", + je16_to_cpu(node.i.flags)); + printk(JFFS2_DBG_LVL "data_crc:\t%#08x\n", + je32_to_cpu(node.i.data_crc)); + printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n", + je32_to_cpu(node.i.node_crc)); + crc = crc32(0, &node.i, sizeof(node.i) - 8); + if (crc != je32_to_cpu(node.i.node_crc)) { + JFFS2_ERROR("wrong node header CRC.\n"); + return; + } + break; + + case JFFS2_NODETYPE_DIRENT: + + printk(JFFS2_DBG_LVL "the node is dirent node\n"); + printk(JFFS2_DBG_LVL "pino:\t%#08x\n", + je32_to_cpu(node.d.pino)); + printk(JFFS2_DBG_LVL "version:\t%#08x\n", + je32_to_cpu(node.d.version)); + printk(JFFS2_DBG_LVL "ino:\t%#08x\n", + je32_to_cpu(node.d.ino)); + printk(JFFS2_DBG_LVL "mctime:\t%#08x\n", + je32_to_cpu(node.d.mctime)); + printk(JFFS2_DBG_LVL "nsize:\t%#02x\n", + node.d.nsize); + printk(JFFS2_DBG_LVL "type:\t%#02x\n", + node.d.type); + printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n", + je32_to_cpu(node.d.node_crc)); + printk(JFFS2_DBG_LVL "name_crc:\t%#08x\n", + je32_to_cpu(node.d.name_crc)); + + node.d.name[node.d.nsize] = '\0'; + printk(JFFS2_DBG_LVL "name:\t\"%s\"\n", node.d.name); + + crc = crc32(0, &node.d, sizeof(node.d) - 8); + if (crc != je32_to_cpu(node.d.node_crc)) { + JFFS2_ERROR("wrong node header CRC.\n"); + return; } + break; - i += JFFS3_BUFDUMP_BYTES_PER_LINE; + default: + printk(JFFS2_DBG_LVL "node type is unknown\n"); + break; } } -#endif /* JFFS2_PARANOIA_CHECKS || CONFIG_JFFS2_FS_DEBUG > 0 */ +#endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */ diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index 7d14f7b0139..51ff099a650 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.h,v 1.1 2005/07/17 06:56:20 dedekind Exp $ + * $Id: debug.h,v 1.5 2005/07/24 15:14:14 dedekind Exp $ * */ #ifndef _JFFS2_DEBUG_H_ @@ -15,12 +15,52 @@ #include +/* ------------------------------------------------ */ +/* TODO: remove */ +#undef CONFIG_JFFS2_FS_DEBUG +#define CONFIG_JFFS2_FS_DEBUG 0 +//#define JFFS2_DBG_PARANOIA_CHECKS +//#define JFFS2_DBG_DUMPS +#define JFFS2_DBG_READINODE_MESSAGES +//#define JFFS2_DBG_FRAGTREE_MESSAGES +//#define JFFS2_DBG_FRAGTREE2_MESSAGES +#undef KERN_DEBUG +#undef KERN_WARNING +#undef KERN_NOTICE +#undef KERN_ERR +#define KERN_DEBUG KERN_CRIT +#define KERN_WARNING KERN_CRIT +#define KERN_NOTICE KERN_CRIT +#define KERN_ERR KERN_CRIT +/* ------------------------------------------------ */ + #ifndef CONFIG_JFFS2_FS_DEBUG #define CONFIG_JFFS2_FS_DEBUG 1 #endif -#if CONFIG_JFFS2_FS_DEBUG > 0 +#if CONFIG_JFFS2_FS_DEBUG == 1 +/* Enable "paranoia" checks and dumps */ #define JFFS2_DBG_PARANOIA_CHECKS +#define JFFS2_DBG_DUMPS +#define JFFS2_DBG_READINODE_MESSAGES +#define JFFS2_DBG_FRAGTREE_MESSAGES +#define JFFS2_DBG_DENTLIST_MESSAGES +#define JFFS2_DBG_NODEREF_MESSAGES +#define JFFS2_DBG_INOCACHE_MESSAGES +#endif + +#if CONFIG_JFFS2_FS_DEBUG == 2 +#define JFFS2_DBG_FRAGTREE2_MESSAGES +#endif + +/* Enable JFFS2 sanity checks by default */ +#define JFFS2_DBG_SANITY_CHECKS + +/* + * Dx() are mainly used for debugging messages, they must go away and be + * superseded by nicer JFFS2_DBG_XXX() macros... + */ +#if CONFIG_JFFS2_FS_DEBUG > 0 #define D1(x) x #else #define D1(x) @@ -32,73 +72,216 @@ #define D2(x) #endif -/* Enable JFFS2 sanity checks */ -#define JFFS2_DBG_SANITY_CHECKS +/* The prefixes of JFFS2 messages */ +#define JFFS2_DBG_MSG_PREFIX "[JFFS2 DBG]" +#define JFFS2_ERR_MSG_PREFIX "JFFS2 error: " +#define JFFS2_WARN_MSG_PREFIX "JFFS2 warning: " +#define JFFS2_NOTICE_MSG_PREFIX "JFFS2 notice: " -#if CONFIG_JFFS2_FS_DEBUG > 0 -void -jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c); +#define JFFS2_ERR_LVL KERN_ERR +#define JFFS2_WARN_LVL KERN_WARNING +#define JFFS2_NOTICE_LVL KERN_NOTICE +#define JFFS2_DBG_LVL KERN_DEBUG -void -jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); +/* JFFS2 message macros */ +#define JFFS2_ERROR(fmt, ...) \ + do { \ + printk(JFFS2_ERR_LVL JFFS2_ERR_MSG_PREFIX " %s: " \ + fmt, __FUNCTION__, ##__VA_ARGS__); \ + } while(0) -void -jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f); +#define JFFS2_WARNING(fmt, ...) \ + do { \ + printk(JFFS2_WARN_LVL JFFS2_WARN_MSG_PREFIX " %s: " \ + fmt, __FUNCTION__, ##__VA_ARGS__); \ + } while(0) + +#define JFFS2_NOTICE(fmt, ...) \ + do { \ + printk(JFFS2_NOTICE_LVL JFFS2_NOTICE_MSG_PREFIX " %s: " \ + fmt, __FUNCTION__, ##__VA_ARGS__); \ + } while(0) -void -jffs2_dbg_dump_buffer(char *buf, int len, uint32_t offs); +#define JFFS2_DEBUG(fmt, ...) \ + do { \ + printk(JFFS2_DBG_LVL JFFS2_DBG_MSG_PREFIX " %s: " \ + fmt, __FUNCTION__, ##__VA_ARGS__); \ + } while(0) + +/* + * We split our debugging messages on several parts, depending on the JFFS2 + * subsystem the message belongs to. + */ +/* Read inode debugging messages */ +#ifdef JFFS2_DBG_READINODE_MESSAGES +#define JFFS2_DBG_READINODE(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#else +#define JFFS2_DBG_READINODE(fmt, ...) #endif -#ifdef JFFS2_DBG_PARANOIA_CHECKS -void -jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f); +/* Fragtree build debugging messages */ +#ifdef JFFS2_DBG_FRAGTREE_MESSAGES +#define JFFS2_DBG_FRAGTREE(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#else +#define JFFS2_DBG_FRAGTREE(fmt, ...) +#endif + +/* Directory entry list manilulation debugging messages */ +#ifdef JFFS2_DBG_DENTLIST_MESSAGES +#define JFFS2_DBG_DENTLIST(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#else +#define JFFS2_DBG_DENTLIST(fmt, ...) +#endif +#ifdef JFFS2_DBG_FRAGTREE2_MESSAGES +#define JFFS2_DBG_FRAGTREE2(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#else +#define JFFS2_DBG_FRAGTREE2(fmt, ...) +#endif + +/* Plays with node_refs */ +#ifdef JFFS2_DBG_NODEREF_MESSAGES +#define JFFS2_DBG_NODEREF(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#else +#define JFFS2_DBG_NODEREF(fmt, ...) +#endif +/* Plays with the list of inodes (JFFS2 inocache) */ +#ifdef JFFS2_DBG_INOCACHE_MESSAGES +#define JFFS2_DBG_INOCACHE(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#else +#define JFFS2_DBG_INOCACHE(fmt, ...) +#endif + +/* "Paranoia" checks */ +void +__jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f); void -jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c, - struct jffs2_eraseblock *jeb); +__jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f); +void +__jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c, + struct jffs2_eraseblock *jeb); +void +__jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c, + struct jffs2_eraseblock *jeb); +void +__jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c, + uint32_t ofs, int len); +/* "Dump" functions */ +void +__jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); +void +__jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb); +void +__jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c); +void +__jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c); +void +__jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c, + struct jffs2_eraseblock *jeb); +void +__jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c, + struct jffs2_eraseblock *jeb); +void +__jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f); +void +__jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f); void -jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c, - uint32_t ofs, int len); +__jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs); +void +__jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs); + +#ifdef JFFS2_DBG_PARANOIA_CHECKS +#define jffs2_dbg_fragtree_paranoia_check(f) \ + __jffs2_dbg_fragtree_paranoia_check(f) +#define jffs2_dbg_fragtree_paranoia_check_nolock(f) \ + __jffs2_dbg_fragtree_paranoia_check_nolock(f) +#define jffs2_dbg_acct_paranoia_check(c, jeb) \ + __jffs2_dbg_acct_paranoia_check(c,jeb) +#define jffs2_dbg_acct_paranoia_check_nolock(c, jeb) \ + __jffs2_dbg_acct_paranoia_check_nolock(c,jeb) +#define jffs2_dbg_prewrite_paranoia_check(c, ofs, len) \ + __jffs2_dbg_prewrite_paranoia_check(c, ofs, len) #else #define jffs2_dbg_fragtree_paranoia_check(f) +#define jffs2_dbg_fragtree_paranoia_check_nolock(f) #define jffs2_dbg_acct_paranoia_check(c, jeb) +#define jffs2_dbg_acct_paranoia_check_nolock(c, jeb) #define jffs2_dbg_prewrite_paranoia_check(c, ofs, len) #endif /* !JFFS2_PARANOIA_CHECKS */ +#ifdef JFFS2_DBG_DUMPS +#define jffs2_dbg_dump_jeb(c, jeb) \ + __jffs2_dbg_dump_jeb(c, jeb); +#define jffs2_dbg_dump_jeb_nolock(jeb) \ + __jffs2_dbg_dump_jeb_nolock(jeb); +#define jffs2_dbg_dump_block_lists(c) \ + __jffs2_dbg_dump_block_lists(c) +#define jffs2_dbg_dump_block_lists_nolock(c) \ + __jffs2_dbg_dump_block_lists_nolock(c) +#define jffs2_dbg_dump_fragtree(f) \ + __jffs2_dbg_dump_fragtree(f); +#define jffs2_dbg_dump_fragtree_nolock(f) \ + __jffs2_dbg_dump_fragtree_nolock(f); +#define jffs2_dbg_dump_buffer(buf, len, offs) \ + __jffs2_dbg_dump_buffer(*buf, len, offs); +#define jffs2_dbg_dump_node(c, ofs) \ + __jffs2_dbg_dump_node(c, ofs); +#else +#define jffs2_dbg_dump_jeb(c, jeb) +#define jffs2_dbg_dump_jeb_nolock(jeb) +#define jffs2_dbg_dump_block_lists(c) +#define jffs2_dbg_dump_block_lists_nolock(c) +#define jffs2_dbg_dump_fragtree(f) +#define jffs2_dbg_dump_fragtree_nolock(f) +#define jffs2_dbg_dump_buffer(buf, len, offs) +#define jffs2_dbg_dump_node(c, ofs) +#endif /* !JFFS2_DBG_DUMPS */ + +/* + * Sanity checks are supposed to be light-weight and enabled by default. + */ #ifdef JFFS2_DBG_SANITY_CHECKS /* * Check the space accounting of the file system and of - * the JFFS3 erasable block 'jeb'. + * the JFFS2 erasable block 'jeb'. */ static inline void -jffs2_dbg_acct_sanity_check(struct jffs2_sb_info *c, - struct jffs2_eraseblock *jeb) +jffs2_dbg_acct_sanity_check_nolock(struct jffs2_sb_info *c, + struct jffs2_eraseblock *jeb) { if (unlikely(jeb && jeb->used_size + jeb->dirty_size + jeb->free_size + jeb->wasted_size + jeb->unchecked_size != c->sector_size)) { - printk(KERN_ERR "Eeep. Space accounting for block at 0x%08x is screwed\n", jeb->offset); - printk(KERN_ERR "free %#08x + dirty %#08x + used %#08x + wasted %#08x + unchecked " - "%#08x != total %#08x\n", jeb->free_size, jeb->dirty_size, jeb->used_size, - jeb->wasted_size, jeb->unchecked_size, c->sector_size); + JFFS2_ERROR("eeep, space accounting for block at 0x%08x is screwed.\n", jeb->offset); + JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + wasted %#08x + unchecked " + "%#08x != total %#08x.\n", jeb->free_size, jeb->dirty_size, jeb->used_size, + jeb->wasted_size, jeb->unchecked_size, c->sector_size); BUG(); } if (unlikely(c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size + c->wasted_size + c->unchecked_size != c->flash_size)) { - printk(KERN_ERR "Eeep. Space accounting superblock info is screwed\n"); - printk(KERN_ERR "free %#08x + dirty %#08x + used %#08x + erasing %#08x + bad %#08x + " - "wasted %#08x + unchecked %#08x != total %#08x\n", - c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, - c->wasted_size, c->unchecked_size, c->flash_size); + JFFS2_ERROR("eeep, space accounting superblock info is screwed.\n"); + JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + erasing %#08x + bad %#08x + " + "wasted %#08x + unchecked %#08x != total %#08x.\n", + c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, + c->wasted_size, c->unchecked_size, c->flash_size); BUG(); } } -#else + static inline void jffs2_dbg_acct_sanity_check(struct jffs2_sb_info *c, - struct jffs2_eraseblock *jeb); + struct jffs2_eraseblock *jeb) +{ + spin_lock(&c->erase_completion_lock); + jffs2_dbg_acct_sanity_check_nolock(c, jeb); + spin_unlock(&c->erase_completion_lock); +} +#else +#define jffs2_dbg_acct_sanity_check(c, jeb) +#define jffs2_dbg_acct_sanity_check_nolock(c, jeb) #endif /* !JFFS2_DBG_SANITY_CHECKS */ #endif /* _JFFS2_DEBUG_H_ */ diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index af0c7d43188..a8a0908142d 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: erase.c,v 1.81 2005/07/17 06:56:20 dedekind Exp $ + * $Id: erase.c,v 1.83 2005/07/22 10:32:08 dedekind Exp $ * */ @@ -48,7 +48,8 @@ static void jffs2_erase_block(struct jffs2_sb_info *c, #else /* Linux */ struct erase_info *instr; - D1(printk(KERN_DEBUG "jffs2_erase_block(): erase block %#x (range %#x-%#x)\n", jeb->offset, jeb->offset, jeb->offset + c->sector_size)); + D1(printk(KERN_DEBUG "jffs2_erase_block(): erase block %#08x (range %#08x-%#08x)\n", + jeb->offset, jeb->offset, jeb->offset + c->sector_size)); instr = kmalloc(sizeof(struct erase_info) + sizeof(struct erase_priv_struct), GFP_KERNEL); if (!instr) { printk(KERN_WARNING "kmalloc for struct erase_info in jffs2_erase_block failed. Refiling block for later\n"); @@ -429,8 +430,8 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb c->free_size += jeb->free_size; c->used_size += jeb->used_size; - jffs2_dbg_acct_sanity_check(c,jeb); - jffs2_dbg_acct_paranoia_check(c, jeb); + jffs2_dbg_acct_sanity_check_nolock(c,jeb); + jffs2_dbg_acct_paranoia_check_nolock(c, jeb); list_add_tail(&jeb->list, &c->free_list); c->nr_erasing_blocks--; diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index a6661e8be25..34731614b57 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: fs.c,v 1.59 2005/07/18 11:21:19 dedekind Exp $ + * $Id: fs.c,v 1.60 2005/07/22 10:32:08 dedekind Exp $ * */ @@ -194,19 +194,15 @@ int jffs2_statfs(struct super_block *sb, struct kstatfs *buf) buf->f_namelen = JFFS2_MAX_NAME_LEN; spin_lock(&c->erase_completion_lock); - avail = c->dirty_size + c->free_size; if (avail > c->sector_size * c->resv_blocks_write) avail -= c->sector_size * c->resv_blocks_write; else avail = 0; + spin_unlock(&c->erase_completion_lock); buf->f_bavail = buf->f_bfree = avail >> PAGE_SHIFT; - jffs2_dbg_dump_block_lists(c); - - spin_unlock(&c->erase_completion_lock); - return 0; } diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 6b5da0a1d31..362cfeed732 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: gc.c,v 1.150 2005/07/17 12:01:43 dedekind Exp $ + * $Id: gc.c,v 1.152 2005/07/24 15:14:14 dedekind Exp $ * */ @@ -111,7 +111,6 @@ again: ret->wasted_size = 0; } - jffs2_dbg_dump_block_lists(c); return ret; } @@ -142,7 +141,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) if (c->checked_ino > c->highest_ino) { printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n", c->unchecked_size); - jffs2_dbg_dump_block_lists(c); + jffs2_dbg_dump_block_lists_nolock(c); spin_unlock(&c->erase_completion_lock); BUG(); } @@ -485,7 +484,8 @@ static int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_era if (ref_obsolete(raw)) { printk(KERN_WARNING "But it's obsolete so we don't mind too much\n"); } else { - ret = -EIO; + jffs2_dbg_dump_node(c, ref_offset(raw)); + BUG(); } } upnout: diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index a04111530f4..9d08d338818 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.c,v 1.99 2005/07/15 10:13:54 dedekind Exp $ + * $Id: nodelist.c,v 1.100 2005/07/22 10:32:08 dedekind Exp $ * */ @@ -203,7 +203,7 @@ read_direntry(struct jffs2_sb_info *c, return -EIO; if (unlikely(err)) { - printk(KERN_WARNING "Read remainder of name in jffs2_get_inode_nodes(): error %d\n", err); + printk(KERN_WARNING "Read remainder of name: error %d\n", err); jffs2_free_full_dirent(fd); return -EIO; } diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 6802e0968d3..dde9b86e43b 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.h,v 1.132 2005/07/17 06:56:21 dedekind Exp $ + * $Id: nodelist.h,v 1.133 2005/07/22 10:32:08 dedekind Exp $ * */ @@ -236,7 +236,7 @@ static inline uint32_t ref_totlen(struct jffs2_sb_info *c, ret, ref->__totlen); if (!jeb) jeb = &c->blocks[ref->flash_offset / c->sector_size]; - jffs2_dbg_dump_node_refs(c, jeb); + jffs2_dbg_dump_node_refs_nolock(c, jeb); BUG(); } #endif diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 424be1e1ca9..fe7e70a4055 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodemgmt.c,v 1.123 2005/07/17 06:56:21 dedekind Exp $ + * $Id: nodemgmt.c,v 1.124 2005/07/20 15:32:28 dedekind Exp $ * */ @@ -349,8 +349,8 @@ int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_r list_add_tail(&jeb->list, &c->clean_list); c->nextblock = NULL; } - jffs2_dbg_acct_sanity_check(c,jeb); - jffs2_dbg_acct_paranoia_check(c, jeb); + jffs2_dbg_acct_sanity_check_nolock(c,jeb); + jffs2_dbg_acct_paranoia_check_nolock(c, jeb); spin_unlock(&c->erase_completion_lock); @@ -430,7 +430,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref ref_totlen(c, jeb, ref), blocknr, ref->flash_offset, jeb->used_size); BUG(); }) - D1(printk(KERN_DEBUG "Obsoleting node at 0x%08x of len %x: ", ref_offset(ref), ref_totlen(c, jeb, ref))); + D1(printk(KERN_DEBUG "Obsoleting node at 0x%08x of len %#x: ", ref_offset(ref), ref_totlen(c, jeb, ref))); jeb->used_size -= ref_totlen(c, jeb, ref); c->used_size -= ref_totlen(c, jeb, ref); } @@ -466,9 +466,8 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref } ref->flash_offset = ref_offset(ref) | REF_OBSOLETE; - jffs2_dbg_acct_sanity_check(c, jeb); - - jffs2_dbg_acct_paranoia_check(c, jeb); + jffs2_dbg_acct_sanity_check_nolock(c, jeb); + jffs2_dbg_acct_paranoia_check_nolock(c, jeb); if (c->flags & JFFS2_SB_FLAG_SCANNING) { /* Flash scanning is in progress. Don't muck about with the block diff --git a/fs/jffs2/read.c b/fs/jffs2/read.c index 9706534786e..e38e6c5f143 100644 --- a/fs/jffs2/read.c +++ b/fs/jffs2/read.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: read.c,v 1.40 2005/07/17 06:56:21 dedekind Exp $ + * $Id: read.c,v 1.41 2005/07/22 10:32:08 dedekind Exp $ * */ @@ -174,7 +174,6 @@ int jffs2_read_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, if (frag) { D1(printk(KERN_NOTICE "Eep. Hole in ino #%u fraglist. frag->ofs = 0x%08x, offset = 0x%08x\n", f->inocache->ino, frag->ofs, offset)); holesize = min(holesize, frag->ofs - offset); - D2(jffs2_dbg_dump_fragtree(f)); } D1(printk(KERN_DEBUG "Filling non-frag hole from %d-%d\n", offset, offset+holesize)); memset(buf, 0, holesize); diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 02a20d7b4d5..02b02c1146b 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.128 2005/07/17 12:01:43 dedekind Exp $ + * $Id: readinode.c,v 1.129 2005/07/22 10:32:08 dedekind Exp $ * */ @@ -92,8 +92,8 @@ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_in mark_ref_normal(next->node->raw); } } - jffs2_dbg_fragtree_paranoia_check(f); - jffs2_dbg_dump_fragtree(f); + jffs2_dbg_fragtree_paranoia_check_nolock(f); + jffs2_dbg_dump_fragtree_nolock(f); return 0; } @@ -480,7 +480,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, jffs2_free_tmp_dnode_info(tn); } - jffs2_dbg_fragtree_paranoia_check(f); + jffs2_dbg_fragtree_paranoia_check_nolock(f); if (!fn) { /* No data nodes for this inode. */ diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index a2a51b7c2fd..fcd6314cf17 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: scan.c,v 1.120 2005/07/17 06:56:21 dedekind Exp $ + * $Id: scan.c,v 1.121 2005/07/20 15:32:28 dedekind Exp $ * */ #include @@ -130,7 +130,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) if (ret < 0) goto out; - jffs2_dbg_acct_paranoia_check(c, jeb); + jffs2_dbg_acct_paranoia_check_nolock(c, jeb); /* Now decide which list to put it on */ switch(ret) { @@ -370,7 +370,7 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo scan_more: while(ofs < jeb->offset + c->sector_size) { - jffs2_dbg_acct_paranoia_check(c, jeb); + jffs2_dbg_acct_paranoia_check_nolock(c, jeb); cond_resched(); diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 5a820f4ea35..251ac3d86f9 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -9,7 +9,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: wbuf.c,v 1.94 2005/07/17 12:01:43 dedekind Exp $ + * $Id: wbuf.c,v 1.96 2005/07/22 10:32:08 dedekind Exp $ * */ @@ -139,7 +139,6 @@ static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock { D1(printk("About to refile bad block at %08x\n", jeb->offset)); - jffs2_dbg_dump_block_lists(c); /* File the existing block on the bad_used_list.... */ if (c->nextblock == jeb) c->nextblock = NULL; @@ -156,7 +155,6 @@ static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock c->nr_erasing_blocks++; jffs2_erase_pending_trigger(c); } - jffs2_dbg_dump_block_lists(c); /* Adjust its size counts accordingly */ c->wasted_size += jeb->free_size; @@ -164,8 +162,9 @@ static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock jeb->wasted_size += jeb->free_size; jeb->free_size = 0; - jffs2_dbg_acct_sanity_check(c,jeb); - jffs2_dbg_acct_paranoia_check(c, jeb); + jffs2_dbg_dump_block_lists_nolock(c); + jffs2_dbg_acct_sanity_check_nolock(c,jeb); + jffs2_dbg_acct_paranoia_check_nolock(c, jeb); } /* Recover from failure to write wbuf. Recover the nodes up to the @@ -392,11 +391,11 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) else jeb->last_node = container_of(first_raw, struct jffs2_raw_node_ref, next_phys); - jffs2_dbg_acct_sanity_check(c,jeb); - jffs2_dbg_acct_paranoia_check(c, jeb); + jffs2_dbg_acct_sanity_check_nolock(c, jeb); + jffs2_dbg_acct_paranoia_check_nolock(c, jeb); - jffs2_dbg_acct_sanity_check(c,new_jeb); - jffs2_dbg_acct_paranoia_check(c, new_jeb); + jffs2_dbg_acct_sanity_check_nolock(c, new_jeb); + jffs2_dbg_acct_paranoia_check_nolock(c, new_jeb); spin_unlock(&c->erase_completion_lock); diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index b6a53e5aaa0..4c418e69cfc 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: write.c,v 1.93 2005/07/17 06:56:21 dedekind Exp $ + * $Id: write.c,v 1.94 2005/07/20 15:50:51 dedekind Exp $ * */ @@ -223,8 +223,6 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff je32_to_cpu(rd->pino), name, name, je32_to_cpu(rd->ino), je32_to_cpu(rd->name_crc))); - jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); - D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) { printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n"); BUG(); @@ -236,6 +234,8 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff vecs[1].iov_base = (unsigned char *)name; vecs[1].iov_len = namelen; + jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); + raw = jffs2_alloc_raw_node_ref(); if (!raw) -- cgit v1.2.3 From f302cd028c90ddbca20cb5388458ae0f0dd03d9b Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Sun, 24 Jul 2005 16:29:59 +0100 Subject: [JFFS2] Namespace clean up Rename functions to a name matching the functionality. Remove stall debug code Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/debug.h | 21 +-------------------- fs/jffs2/fs.c | 4 ++-- fs/jffs2/nodelist.h | 4 ++-- fs/jffs2/readinode.c | 6 +++--- include/linux/jffs2.h | 6 +++--- 5 files changed, 11 insertions(+), 30 deletions(-) diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index 51ff099a650..3c3c2940f27 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.h,v 1.5 2005/07/24 15:14:14 dedekind Exp $ + * $Id: debug.h,v 1.6 2005/07/24 15:18:26 dedekind Exp $ * */ #ifndef _JFFS2_DEBUG_H_ @@ -15,25 +15,6 @@ #include -/* ------------------------------------------------ */ -/* TODO: remove */ -#undef CONFIG_JFFS2_FS_DEBUG -#define CONFIG_JFFS2_FS_DEBUG 0 -//#define JFFS2_DBG_PARANOIA_CHECKS -//#define JFFS2_DBG_DUMPS -#define JFFS2_DBG_READINODE_MESSAGES -//#define JFFS2_DBG_FRAGTREE_MESSAGES -//#define JFFS2_DBG_FRAGTREE2_MESSAGES -#undef KERN_DEBUG -#undef KERN_WARNING -#undef KERN_NOTICE -#undef KERN_ERR -#define KERN_DEBUG KERN_CRIT -#define KERN_WARNING KERN_CRIT -#define KERN_NOTICE KERN_CRIT -#define KERN_ERR KERN_CRIT -/* ------------------------------------------------ */ - #ifndef CONFIG_JFFS2_FS_DEBUG #define CONFIG_JFFS2_FS_DEBUG 1 #endif diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 34731614b57..cc18b92234c 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: fs.c,v 1.60 2005/07/22 10:32:08 dedekind Exp $ + * $Id: fs.c,v 1.61 2005/07/24 15:29:56 dedekind Exp $ * */ @@ -147,7 +147,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) old_metadata = f->metadata; if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) - jffs2_truncate_fraglist (c, &f->fragtree, iattr->ia_size); + jffs2_truncate_fragtree (c, &f->fragtree, iattr->ia_size); if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) { jffs2_add_full_dnode_to_inode(c, f, new_metadata); diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index dde9b86e43b..0058e395641 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.h,v 1.133 2005/07/22 10:32:08 dedekind Exp $ + * $Id: nodelist.h,v 1.134 2005/07/24 15:29:56 dedekind Exp $ * */ @@ -336,7 +336,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint /* readinode.c */ -void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); +void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t ino, struct jffs2_raw_inode *latest_node); diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 02b02c1146b..339ba46320f 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.129 2005/07/22 10:32:08 dedekind Exp $ + * $Id: readinode.c,v 1.130 2005/07/24 15:29:56 dedekind Exp $ * */ @@ -273,7 +273,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *l return 0; } -void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size) +void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size) { struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size); @@ -534,7 +534,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, case S_IFREG: /* If it was a regular file, truncate it to the latest node's isize */ - jffs2_truncate_fraglist(c, &f->fragtree, je32_to_cpu(latest_node->isize)); + jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize)); break; case S_IFLNK: diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h index 419fc953ac1..7bc51add62f 100644 --- a/include/linux/jffs2.h +++ b/include/linux/jffs2.h @@ -8,7 +8,7 @@ * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * - * $Id: jffs2.h,v 1.34 2004/11/16 20:36:14 dwmw2 Exp $ + * $Id: jffs2.h,v 1.35 2005/07/24 15:15:51 dedekind Exp $ * */ @@ -101,7 +101,7 @@ struct jffs2_unknown_node struct jffs2_raw_dirent { jint16_t magic; - jint16_t nodetype; /* == JFFS_NODETYPE_DIRENT */ + jint16_t nodetype; /* == JFFS2_NODETYPE_DIRENT */ jint32_t totlen; jint32_t hdr_crc; jint32_t pino; @@ -125,7 +125,7 @@ struct jffs2_raw_dirent struct jffs2_raw_inode { jint16_t magic; /* A constant magic number. */ - jint16_t nodetype; /* == JFFS_NODETYPE_INODE */ + jint16_t nodetype; /* == JFFS2_NODETYPE_INODE */ jint32_t totlen; /* Total length of this node (inc data, etc.) */ jint32_t hdr_crc; jint32_t ino; /* Inode number. */ -- cgit v1.2.3 From 2227c0ba4bc177a014d95b380b4d888454a127a9 Mon Sep 17 00:00:00 2001 From: Ferenc Havasi Date: Tue, 26 Jul 2005 14:24:43 +0100 Subject: [jffs2] Remove compressor lzo and lzari Remove unused compressor code Signed-off-by: Ferenc Havasi Signed-off-by: Thomas Gleixner --- fs/jffs2/compr.c | 14 +------------- fs/jffs2/compr.h | 10 +--------- include/linux/jffs2.h | 4 +--- 3 files changed, 3 insertions(+), 25 deletions(-) diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c index af922a9618a..c9e54b97dba 100644 --- a/fs/jffs2/compr.c +++ b/fs/jffs2/compr.c @@ -9,7 +9,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: compr.c,v 1.42 2004/08/07 21:56:08 dwmw2 Exp $ + * $Id: compr.c,v 1.45 2005/07/26 13:24:40 havasi Exp $ * */ @@ -425,12 +425,6 @@ int jffs2_compressors_init(void) jffs2_rubinmips_init(); jffs2_dynrubin_init(); #endif -#ifdef CONFIG_JFFS2_LZARI - jffs2_lzari_init(); -#endif -#ifdef CONFIG_JFFS2_LZO - jffs2_lzo_init(); -#endif /* Setting default compression mode */ #ifdef CONFIG_JFFS2_CMODE_NONE jffs2_compression_mode = JFFS2_COMPR_MODE_NONE; @@ -449,12 +443,6 @@ int jffs2_compressors_init(void) int jffs2_compressors_exit(void) { /* Unregistering compressors */ -#ifdef CONFIG_JFFS2_LZO - jffs2_lzo_exit(); -#endif -#ifdef CONFIG_JFFS2_LZARI - jffs2_lzari_exit(); -#endif #ifdef CONFIG_JFFS2_RUBIN jffs2_dynrubin_exit(); jffs2_rubinmips_exit(); diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h index 89ceeed201e..9ec6e37d383 100644 --- a/fs/jffs2/compr.h +++ b/fs/jffs2/compr.h @@ -7,7 +7,7 @@ * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * - * $Id: compr.h,v 1.6 2004/07/16 15:17:57 dwmw2 Exp $ + * $Id: compr.h,v 1.8 2005/07/26 13:24:40 havasi Exp $ * */ @@ -103,13 +103,5 @@ void jffs2_rtime_exit(void); int jffs2_zlib_init(void); void jffs2_zlib_exit(void); #endif -#ifdef CONFIG_JFFS2_LZARI -int jffs2_lzari_init(void); -void jffs2_lzari_exit(void); -#endif -#ifdef CONFIG_JFFS2_LZO -int jffs2_lzo_init(void); -void jffs2_lzo_exit(void); -#endif #endif /* __JFFS2_COMPR_H__ */ diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h index 7bc51add62f..a66d0a8b70e 100644 --- a/include/linux/jffs2.h +++ b/include/linux/jffs2.h @@ -8,7 +8,7 @@ * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * - * $Id: jffs2.h,v 1.35 2005/07/24 15:15:51 dedekind Exp $ + * $Id: jffs2.h,v 1.36 2005/07/26 13:19:36 havasi Exp $ * */ @@ -43,8 +43,6 @@ #define JFFS2_COMPR_COPY 0x04 #define JFFS2_COMPR_DYNRUBIN 0x05 #define JFFS2_COMPR_ZLIB 0x06 -#define JFFS2_COMPR_LZO 0x07 -#define JFFS2_COMPR_LZARI 0x08 /* Compatibility flags. */ #define JFFS2_COMPAT_MASK 0xc000 /* What do to if an unknown nodetype is found */ #define JFFS2_NODE_ACCURATE 0x2000 -- cgit v1.2.3 From f538c96ba2a3fdf7744ecf9fdffac14b1ec4be32 Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Wed, 27 Jul 2005 15:16:57 +0100 Subject: [JFFS2] Debug code clean up - step 4 Small comment cleanups. Remove a unused macro Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/debug.h | 16 ++++++++--- fs/jffs2/malloc.c | 82 ++++++++++++++++++++++++++++--------------------------- 2 files changed, 54 insertions(+), 44 deletions(-) diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index 3c3c2940f27..4d785971201 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.h,v 1.6 2005/07/24 15:18:26 dedekind Exp $ + * $Id: debug.h,v 1.7 2005/07/27 13:06:56 dedekind Exp $ * */ #ifndef _JFFS2_DEBUG_H_ @@ -16,7 +16,7 @@ #include #ifndef CONFIG_JFFS2_FS_DEBUG -#define CONFIG_JFFS2_FS_DEBUG 1 +#define CONFIG_JFFS2_FS_DEBUG 0 #endif #if CONFIG_JFFS2_FS_DEBUG == 1 @@ -119,20 +119,28 @@ #define JFFS2_DBG_FRAGTREE2(fmt, ...) #endif -/* Plays with node_refs */ +/* Print the messages about manipulating node_refs */ #ifdef JFFS2_DBG_NODEREF_MESSAGES #define JFFS2_DBG_NODEREF(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else #define JFFS2_DBG_NODEREF(fmt, ...) #endif -/* Plays with the list of inodes (JFFS2 inocache) */ +/* Manipulations with the list of inodes (JFFS2 inocache) */ #ifdef JFFS2_DBG_INOCACHE_MESSAGES #define JFFS2_DBG_INOCACHE(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else #define JFFS2_DBG_INOCACHE(fmt, ...) #endif +/* Watch the object allocations */ +#ifdef JFFS2_DBG_MEMALLOC_MESSAGES +#define JFFS2_DBG_MEMALLOC(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#else +#define JFFS2_DBG_MEMALLOC(fmt, ...) +#endif + + /* "Paranoia" checks */ void __jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f); diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c index 5abb431c2a0..734801145bf 100644 --- a/fs/jffs2/malloc.c +++ b/fs/jffs2/malloc.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: malloc.c,v 1.28 2004/11/16 20:36:11 dwmw2 Exp $ + * $Id: malloc.c,v 1.29 2005/07/27 14:16:53 dedekind Exp $ * */ @@ -17,15 +17,6 @@ #include #include "nodelist.h" -#if 0 -#define JFFS2_SLAB_POISON SLAB_POISON -#else -#define JFFS2_SLAB_POISON 0 -#endif - -// replace this by #define D3 (x) x for cache debugging -#define D3(x) - /* These are initialised to NULL in the kernel startup code. If you're porting to other operating systems, beware */ static kmem_cache_t *full_dnode_slab; @@ -40,43 +31,43 @@ int __init jffs2_create_slab_caches(void) { full_dnode_slab = kmem_cache_create("jffs2_full_dnode", sizeof(struct jffs2_full_dnode), - 0, JFFS2_SLAB_POISON, NULL, NULL); + 0, 0, NULL, NULL); if (!full_dnode_slab) goto err; raw_dirent_slab = kmem_cache_create("jffs2_raw_dirent", sizeof(struct jffs2_raw_dirent), - 0, JFFS2_SLAB_POISON, NULL, NULL); + 0, 0, NULL, NULL); if (!raw_dirent_slab) goto err; raw_inode_slab = kmem_cache_create("jffs2_raw_inode", sizeof(struct jffs2_raw_inode), - 0, JFFS2_SLAB_POISON, NULL, NULL); + 0, 0, NULL, NULL); if (!raw_inode_slab) goto err; tmp_dnode_info_slab = kmem_cache_create("jffs2_tmp_dnode", sizeof(struct jffs2_tmp_dnode_info), - 0, JFFS2_SLAB_POISON, NULL, NULL); + 0, 0, NULL, NULL); if (!tmp_dnode_info_slab) goto err; raw_node_ref_slab = kmem_cache_create("jffs2_raw_node_ref", sizeof(struct jffs2_raw_node_ref), - 0, JFFS2_SLAB_POISON, NULL, NULL); + 0, 0, NULL, NULL); if (!raw_node_ref_slab) goto err; node_frag_slab = kmem_cache_create("jffs2_node_frag", sizeof(struct jffs2_node_frag), - 0, JFFS2_SLAB_POISON, NULL, NULL); + 0, 0, NULL, NULL); if (!node_frag_slab) goto err; inode_cache_slab = kmem_cache_create("jffs2_inode_cache", sizeof(struct jffs2_inode_cache), - 0, JFFS2_SLAB_POISON, NULL, NULL); + 0, 0, NULL, NULL); if (inode_cache_slab) return 0; err: @@ -104,102 +95,113 @@ void jffs2_destroy_slab_caches(void) struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize) { - return kmalloc(sizeof(struct jffs2_full_dirent) + namesize, GFP_KERNEL); + struct jffs2_full_dirent *ret; + ret = kmalloc(sizeof(struct jffs2_full_dirent) + namesize, GFP_KERNEL); + JFFS2_DBG_MEMALLOC("%p\n", ret); + return ret; } void jffs2_free_full_dirent(struct jffs2_full_dirent *x) { + JFFS2_DBG_MEMALLOC("%p\n", x); kfree(x); } struct jffs2_full_dnode *jffs2_alloc_full_dnode(void) { - struct jffs2_full_dnode *ret = kmem_cache_alloc(full_dnode_slab, GFP_KERNEL); - D3 (printk (KERN_DEBUG "alloc_full_dnode at %p\n", ret)); + struct jffs2_full_dnode *ret; + ret = kmem_cache_alloc(full_dnode_slab, GFP_KERNEL); + JFFS2_DBG_MEMALLOC("%p\n", ret); return ret; } void jffs2_free_full_dnode(struct jffs2_full_dnode *x) { - D3 (printk (KERN_DEBUG "free full_dnode at %p\n", x)); + JFFS2_DBG_MEMALLOC("%p\n", x); kmem_cache_free(full_dnode_slab, x); } struct jffs2_raw_dirent *jffs2_alloc_raw_dirent(void) { - struct jffs2_raw_dirent *ret = kmem_cache_alloc(raw_dirent_slab, GFP_KERNEL); - D3 (printk (KERN_DEBUG "alloc_raw_dirent\n", ret)); + struct jffs2_raw_dirent *ret; + ret = kmem_cache_alloc(raw_dirent_slab, GFP_KERNEL); + JFFS2_DBG_MEMALLOC("%p\n", ret); return ret; } void jffs2_free_raw_dirent(struct jffs2_raw_dirent *x) { - D3 (printk (KERN_DEBUG "free_raw_dirent at %p\n", x)); + JFFS2_DBG_MEMALLOC("%p\n", x); kmem_cache_free(raw_dirent_slab, x); } struct jffs2_raw_inode *jffs2_alloc_raw_inode(void) { - struct jffs2_raw_inode *ret = kmem_cache_alloc(raw_inode_slab, GFP_KERNEL); - D3 (printk (KERN_DEBUG "alloc_raw_inode at %p\n", ret)); + struct jffs2_raw_inode *ret; + ret = kmem_cache_alloc(raw_inode_slab, GFP_KERNEL); + JFFS2_DBG_MEMALLOC("%p\n", ret); return ret; } void jffs2_free_raw_inode(struct jffs2_raw_inode *x) { - D3 (printk (KERN_DEBUG "free_raw_inode at %p\n", x)); + JFFS2_DBG_MEMALLOC("%p\n", x); kmem_cache_free(raw_inode_slab, x); } struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void) { - struct jffs2_tmp_dnode_info *ret = kmem_cache_alloc(tmp_dnode_info_slab, GFP_KERNEL); - D3 (printk (KERN_DEBUG "alloc_tmp_dnode_info at %p\n", ret)); + struct jffs2_tmp_dnode_info *ret; + ret = kmem_cache_alloc(tmp_dnode_info_slab, GFP_KERNEL); + JFFS2_DBG_MEMALLOC("%p\n", + ret); return ret; } void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x) { - D3 (printk (KERN_DEBUG "free_tmp_dnode_info at %p\n", x)); + JFFS2_DBG_MEMALLOC("%p\n", x); kmem_cache_free(tmp_dnode_info_slab, x); } struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void) { - struct jffs2_raw_node_ref *ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL); - D3 (printk (KERN_DEBUG "alloc_raw_node_ref at %p\n", ret)); + struct jffs2_raw_node_ref *ret; + ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL); + JFFS2_DBG_MEMALLOC("%p\n", ret); return ret; } void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x) { - D3 (printk (KERN_DEBUG "free_raw_node_ref at %p\n", x)); + JFFS2_DBG_MEMALLOC("%p\n", x); kmem_cache_free(raw_node_ref_slab, x); } struct jffs2_node_frag *jffs2_alloc_node_frag(void) { - struct jffs2_node_frag *ret = kmem_cache_alloc(node_frag_slab, GFP_KERNEL); - D3 (printk (KERN_DEBUG "alloc_node_frag at %p\n", ret)); + struct jffs2_node_frag *ret; + ret = kmem_cache_alloc(node_frag_slab, GFP_KERNEL); + JFFS2_DBG_MEMALLOC("%p\n", ret); return ret; } void jffs2_free_node_frag(struct jffs2_node_frag *x) { - D3 (printk (KERN_DEBUG "free_node_frag at %p\n", x)); + JFFS2_DBG_MEMALLOC("%p\n", x); kmem_cache_free(node_frag_slab, x); } struct jffs2_inode_cache *jffs2_alloc_inode_cache(void) { - struct jffs2_inode_cache *ret = kmem_cache_alloc(inode_cache_slab, GFP_KERNEL); - D3 (printk(KERN_DEBUG "Allocated inocache at %p\n", ret)); + struct jffs2_inode_cache *ret; + ret = kmem_cache_alloc(inode_cache_slab, GFP_KERNEL); + JFFS2_DBG_MEMALLOC("%p\n", ret); return ret; } void jffs2_free_inode_cache(struct jffs2_inode_cache *x) { - D3 (printk(KERN_DEBUG "Freeing inocache at %p\n", x)); + JFFS2_DBG_MEMALLOC("%p\n", x); kmem_cache_free(inode_cache_slab, x); } - -- cgit v1.2.3 From f97117d15361b3a6aeaf9e347a287ef3f54b58f9 Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Wed, 27 Jul 2005 15:46:14 +0100 Subject: [JFFS2] Move scattered function into related files Move functions to read inodes into readinode.c Move functions to handle fragtree and dentry lists into nodelist.[ch] Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/nodelist.c | 717 ++++++++++++++---------------------------- fs/jffs2/nodelist.h | 10 +- fs/jffs2/readinode.c | 863 +++++++++++++++++++++++++++++++++------------------ 3 files changed, 790 insertions(+), 800 deletions(-) diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 9d08d338818..8373d312b19 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.c,v 1.100 2005/07/22 10:32:08 dedekind Exp $ + * $Id: nodelist.c,v 1.101 2005/07/27 14:46:11 dedekind Exp $ * */ @@ -55,515 +55,284 @@ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new }); } -/* - * Put a new tmp_dnode_info into the temporaty RB-tree, keeping the list in - * order of increasing version. - */ -static void jffs2_add_tn_to_tree(struct jffs2_tmp_dnode_info *tn, struct rb_root *list) +void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this) { - struct rb_node **p = &list->rb_node; - struct rb_node * parent = NULL; - struct jffs2_tmp_dnode_info *this; - - while (*p) { - parent = *p; - this = rb_entry(parent, struct jffs2_tmp_dnode_info, rb); - - /* There may actually be a collision here, but it doesn't - actually matter. As long as the two nodes with the same - version are together, it's all fine. */ - if (tn->version < this->version) - p = &(*p)->rb_left; - else - p = &(*p)->rb_right; - } - - rb_link_node(&tn->rb, parent, p); - rb_insert_color(&tn->rb, list); + if (this->node) { + this->node->frags--; + if (!this->node->frags) { + /* The node has no valid frags left. It's totally obsoleted */ + D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) obsolete\n", + ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size)); + jffs2_mark_node_obsolete(c, this->node->raw); + jffs2_free_full_dnode(this->node); + } else { + D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) REF_NORMAL. frags is %d\n", + ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size, + this->node->frags)); + mark_ref_normal(this->node->raw); + } + + } + jffs2_free_node_frag(this); } -static void jffs2_free_tmp_dnode_info_list(struct rb_root *list) +static void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_node_frag *base) { - struct rb_node *this; - struct jffs2_tmp_dnode_info *tn; + struct rb_node *parent = &base->rb; + struct rb_node **link = &parent; - this = list->rb_node; + D2(printk(KERN_DEBUG "jffs2_fragtree_insert(%p; %d-%d, %p)\n", newfrag, + newfrag->ofs, newfrag->ofs+newfrag->size, base)); - /* Now at bottom of tree */ - while (this) { - if (this->rb_left) - this = this->rb_left; - else if (this->rb_right) - this = this->rb_right; + while (*link) { + parent = *link; + base = rb_entry(parent, struct jffs2_node_frag, rb); + + D2(printk(KERN_DEBUG "fragtree_insert considering frag at 0x%x\n", base->ofs)); + if (newfrag->ofs > base->ofs) + link = &base->rb.rb_right; + else if (newfrag->ofs < base->ofs) + link = &base->rb.rb_left; else { - tn = rb_entry(this, struct jffs2_tmp_dnode_info, rb); - jffs2_free_full_dnode(tn->fn); - jffs2_free_tmp_dnode_info(tn); - - this = this->rb_parent; - if (!this) - break; - - if (this->rb_left == &tn->rb) - this->rb_left = NULL; - else if (this->rb_right == &tn->rb) - this->rb_right = NULL; - else BUG(); + printk(KERN_CRIT "Duplicate frag at %08x (%p,%p)\n", newfrag->ofs, newfrag, base); + BUG(); } } - list->rb_node = NULL; + + rb_link_node(&newfrag->rb, &base->rb, link); } -static void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd) +/* Doesn't set inode->i_size */ +static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *list, struct jffs2_node_frag *newfrag) { - struct jffs2_full_dirent *next; + struct jffs2_node_frag *this; + uint32_t lastend; - while (fd) { - next = fd->next; - jffs2_free_full_dirent(fd); - fd = next; - } -} + /* Skip all the nodes which are completed before this one starts */ + this = jffs2_lookup_node_frag(list, newfrag->node->ofs); -/* Returns first valid node after 'ref'. May return 'ref' */ -static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_ref *ref) -{ - while (ref && ref->next_in_ino) { - if (!ref_obsolete(ref)) - return ref; - D1(printk(KERN_DEBUG "node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref))); - ref = ref->next_in_ino; + if (this) { + D2(printk(KERN_DEBUG "j_a_f_d_t_f: Lookup gave frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", + this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this)); + lastend = this->ofs + this->size; + } else { + D2(printk(KERN_DEBUG "j_a_f_d_t_f: Lookup gave no frag\n")); + lastend = 0; } - return NULL; -} + + /* See if we ran off the end of the list */ + if (lastend <= newfrag->ofs) { + /* We did */ + + /* Check if 'this' node was on the same page as the new node. + If so, both 'this' and the new node get marked REF_NORMAL so + the GC can take a look. + */ + if (lastend && (lastend-1) >> PAGE_CACHE_SHIFT == newfrag->ofs >> PAGE_CACHE_SHIFT) { + if (this->node) + mark_ref_normal(this->node->raw); + mark_ref_normal(newfrag->node->raw); + } -/* - * Helper function for jffs2_get_inode_nodes(). - * It is called every time an directory entry node is found. - * - * Returns: 0 on succes; - * 1 if the node should be marked obsolete; - * negative error code on failure. - */ -static inline int -read_direntry(struct jffs2_sb_info *c, - struct jffs2_raw_node_ref *ref, - struct jffs2_raw_dirent *rd, - uint32_t read, - struct jffs2_full_dirent **fdp, - int32_t *latest_mctime, - uint32_t *mctime_ver) -{ - struct jffs2_full_dirent *fd; - - /* The direntry nodes are checked during the flash scanning */ - BUG_ON(ref_flags(ref) == REF_UNCHECKED); - /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ - BUG_ON(ref_obsolete(ref)); - - /* Sanity check */ - if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) { - printk(KERN_ERR "Error! Illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n", - ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen)); - return 1; + if (lastend < newfrag->node->ofs) { + /* ... and we need to put a hole in before the new node */ + struct jffs2_node_frag *holefrag = jffs2_alloc_node_frag(); + if (!holefrag) { + jffs2_free_node_frag(newfrag); + return -ENOMEM; + } + holefrag->ofs = lastend; + holefrag->size = newfrag->node->ofs - lastend; + holefrag->node = NULL; + if (this) { + /* By definition, the 'this' node has no right-hand child, + because there are no frags with offset greater than it. + So that's where we want to put the hole */ + D2(printk(KERN_DEBUG "Adding hole frag (%p) on right of node at (%p)\n", holefrag, this)); + rb_link_node(&holefrag->rb, &this->rb, &this->rb.rb_right); + } else { + D2(printk(KERN_DEBUG "Adding hole frag (%p) at root of tree\n", holefrag)); + rb_link_node(&holefrag->rb, NULL, &list->rb_node); + } + rb_insert_color(&holefrag->rb, list); + this = holefrag; + } + if (this) { + /* By definition, the 'this' node has no right-hand child, + because there are no frags with offset greater than it. + So that's where we want to put new fragment */ + D2(printk(KERN_DEBUG "Adding new frag (%p) on right of node at (%p)\n", newfrag, this)); + rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); + } else { + D2(printk(KERN_DEBUG "Adding new frag (%p) at root of tree\n", newfrag)); + rb_link_node(&newfrag->rb, NULL, &list->rb_node); + } + rb_insert_color(&newfrag->rb, list); + return 0; } - - fd = jffs2_alloc_full_dirent(rd->nsize + 1); - if (unlikely(!fd)) - return -ENOMEM; - - fd->raw = ref; - fd->version = je32_to_cpu(rd->version); - fd->ino = je32_to_cpu(rd->ino); - fd->type = rd->type; - /* Pick out the mctime of the latest dirent */ - if(fd->version > *mctime_ver) { - *mctime_ver = fd->version; - *latest_mctime = je32_to_cpu(rd->mctime); - } + D2(printk(KERN_DEBUG "j_a_f_d_t_f: dealing with frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", + this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this)); - /* - * Copy as much of the name as possible from the raw - * dirent we've already read from the flash. + /* OK. 'this' is pointing at the first frag that newfrag->ofs at least partially obsoletes, + * - i.e. newfrag->ofs < this->ofs+this->size && newfrag->ofs >= this->ofs */ - if (read > sizeof(*rd)) - memcpy(&fd->name[0], &rd->name[0], - min_t(uint32_t, rd->nsize, (read - sizeof(*rd)) )); - - /* Do we need to copy any more of the name directly from the flash? */ - if (rd->nsize + sizeof(*rd) > read) { - /* FIXME: point() */ - int err; - int already = read - sizeof(*rd); + if (newfrag->ofs > this->ofs) { + /* This node isn't completely obsoleted. The start of it remains valid */ + + /* Mark the new node and the partially covered node REF_NORMAL -- let + the GC take a look at them */ + mark_ref_normal(newfrag->node->raw); + if (this->node) + mark_ref_normal(this->node->raw); + + if (this->ofs + this->size > newfrag->ofs + newfrag->size) { + /* The new node splits 'this' frag into two */ + struct jffs2_node_frag *newfrag2 = jffs2_alloc_node_frag(); + if (!newfrag2) { + jffs2_free_node_frag(newfrag); + return -ENOMEM; + } + D2(printk(KERN_DEBUG "split old frag 0x%04x-0x%04x -->", this->ofs, this->ofs+this->size); + if (this->node) + printk("phys 0x%08x\n", ref_offset(this->node->raw)); + else + printk("hole\n"); + ) + + /* New second frag pointing to this's node */ + newfrag2->ofs = newfrag->ofs + newfrag->size; + newfrag2->size = (this->ofs+this->size) - newfrag2->ofs; + newfrag2->node = this->node; + if (this->node) + this->node->frags++; + + /* Adjust size of original 'this' */ + this->size = newfrag->ofs - this->ofs; + + /* Now, we know there's no node with offset + greater than this->ofs but smaller than + newfrag2->ofs or newfrag->ofs, for obvious + reasons. So we can do a tree insert from + 'this' to insert newfrag, and a tree insert + from newfrag to insert newfrag2. */ + jffs2_fragtree_insert(newfrag, this); + rb_insert_color(&newfrag->rb, list); - err = jffs2_flash_read(c, (ref_offset(ref)) + read, - rd->nsize - already, &read, &fd->name[already]); - if (unlikely(read != rd->nsize - already) && likely(!err)) - return -EIO; + jffs2_fragtree_insert(newfrag2, newfrag); + rb_insert_color(&newfrag2->rb, list); - if (unlikely(err)) { - printk(KERN_WARNING "Read remainder of name: error %d\n", err); - jffs2_free_full_dirent(fd); - return -EIO; + return 0; } - } - - fd->nhash = full_name_hash(fd->name, rd->nsize); - fd->next = NULL; - fd->name[rd->nsize] = '\0'; - - /* - * Wheee. We now have a complete jffs2_full_dirent structure, with - * the name in it and everything. Link it into the list - */ - D1(printk(KERN_DEBUG "Adding fd \"%s\", ino #%u\n", fd->name, fd->ino)); - - jffs2_add_fd_to_list(c, fd, fdp); + /* New node just reduces 'this' frag in size, doesn't split it */ + this->size = newfrag->ofs - this->ofs; - return 0; -} - -/* - * Helper function for jffs2_get_inode_nodes(). - * It is called every time an inode node is found. - * - * Returns: 0 on succes; - * 1 if the node should be marked obsolete; - * negative error code on failure. - */ -static inline int -read_dnode(struct jffs2_sb_info *c, - struct jffs2_raw_node_ref *ref, - struct jffs2_raw_inode *rd, - uint32_t read, - struct rb_root *tnp, - int32_t *latest_mctime, - uint32_t *mctime_ver) -{ - struct jffs2_eraseblock *jeb; - struct jffs2_tmp_dnode_info *tn; + /* Again, we know it lives down here in the tree */ + jffs2_fragtree_insert(newfrag, this); + rb_insert_color(&newfrag->rb, list); + } else { + /* New frag starts at the same point as 'this' used to. Replace + it in the tree without doing a delete and insertion */ + D2(printk(KERN_DEBUG "Inserting newfrag (*%p),%d-%d in before 'this' (*%p),%d-%d\n", + newfrag, newfrag->ofs, newfrag->ofs+newfrag->size, + this, this->ofs, this->ofs+this->size)); - /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ - BUG_ON(ref_obsolete(ref)); - - /* If we've never checked the CRCs on this node, check them now */ - if (ref_flags(ref) == REF_UNCHECKED) { - uint32_t crc, len; - - crc = crc32(0, rd, sizeof(*rd) - 8); - if (unlikely(crc != je32_to_cpu(rd->node_crc))) { - printk(KERN_WARNING "Header CRC failed on node at %#08x: read %#08x, calculated %#08x\n", - ref_offset(ref), je32_to_cpu(rd->node_crc), crc); - return 1; - } + rb_replace_node(&this->rb, &newfrag->rb, list); - /* Sanity checks */ - if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) || - unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) { - printk(KERN_WARNING "Inode corrupted at %#08x, totlen %d, #ino %d, version %d, " - "isize %d, csize %d, dsize %d \n", - ref_offset(ref), je32_to_cpu(rd->totlen), je32_to_cpu(rd->ino), - je32_to_cpu(rd->version), je32_to_cpu(rd->isize), - je32_to_cpu(rd->csize), je32_to_cpu(rd->dsize)); - return 1; - } - - if (rd->compr != JFFS2_COMPR_ZERO && je32_to_cpu(rd->csize)) { - unsigned char *buf = NULL; - uint32_t pointed = 0; - int err; -#ifndef __ECOS - if (c->mtd->point) { - err = c->mtd->point (c->mtd, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize), - &read, &buf); - if (unlikely(read < je32_to_cpu(rd->csize)) && likely(!err)) { - D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", read)); - c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(*rd), - je32_to_cpu(rd->csize)); - } else if (unlikely(err)){ - D1(printk(KERN_DEBUG "MTD point failed %d\n", err)); - } else - pointed = 1; /* succefully pointed to device */ - } -#endif - if(!pointed){ - buf = kmalloc(je32_to_cpu(rd->csize), GFP_KERNEL); - if (!buf) - return -ENOMEM; - - err = jffs2_flash_read(c, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize), - &read, buf); - if (unlikely(read != je32_to_cpu(rd->csize)) && likely(!err)) - err = -EIO; - if (err) { - kfree(buf); - return err; - } - } - crc = crc32(0, buf, je32_to_cpu(rd->csize)); - if(!pointed) - kfree(buf); -#ifndef __ECOS - else - c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize)); -#endif - - if (crc != je32_to_cpu(rd->data_crc)) { - printk(KERN_NOTICE "Data CRC failed on node at %#08x: read %#08x, calculated %#08x\n", - ref_offset(ref), je32_to_cpu(rd->data_crc), crc); - return 1; - } - - } - - /* Mark the node as having been checked and fix the accounting accordingly */ - jeb = &c->blocks[ref->flash_offset / c->sector_size]; - len = ref_totlen(c, jeb, ref); - - spin_lock(&c->erase_completion_lock); - jeb->used_size += len; - jeb->unchecked_size -= len; - c->used_size += len; - c->unchecked_size -= len; - - /* If node covers at least a whole page, or if it starts at the - beginning of a page and runs to the end of the file, or if - it's a hole node, mark it REF_PRISTINE, else REF_NORMAL. - - If it's actually overlapped, it'll get made NORMAL (or OBSOLETE) - when the overlapping node(s) get added to the tree anyway. - */ - if ((je32_to_cpu(rd->dsize) >= PAGE_CACHE_SIZE) || - ( ((je32_to_cpu(rd->offset) & (PAGE_CACHE_SIZE-1))==0) && - (je32_to_cpu(rd->dsize) + je32_to_cpu(rd->offset) == je32_to_cpu(rd->isize)))) { - D1(printk(KERN_DEBUG "Marking node at %#08x REF_PRISTINE\n", ref_offset(ref))); - ref->flash_offset = ref_offset(ref) | REF_PRISTINE; + if (newfrag->ofs + newfrag->size >= this->ofs+this->size) { + D2(printk(KERN_DEBUG "Obsoleting node frag %p (%x-%x)\n", this, this->ofs, this->ofs+this->size)); + jffs2_obsolete_node_frag(c, this); } else { - D1(printk(KERN_DEBUG "Marking node at %#08x REF_NORMAL\n", ref_offset(ref))); - ref->flash_offset = ref_offset(ref) | REF_NORMAL; + this->ofs += newfrag->size; + this->size -= newfrag->size; + + jffs2_fragtree_insert(this, newfrag); + rb_insert_color(&this->rb, list); + return 0; } - spin_unlock(&c->erase_completion_lock); } - - tn = jffs2_alloc_tmp_dnode_info(); - if (!tn) { - D1(printk(KERN_DEBUG "alloc tn failed\n")); - return -ENOMEM; + /* OK, now we have newfrag added in the correct place in the tree, but + frag_next(newfrag) may be a fragment which is overlapped by it + */ + while ((this = frag_next(newfrag)) && newfrag->ofs + newfrag->size >= this->ofs + this->size) { + /* 'this' frag is obsoleted completely. */ + D2(printk(KERN_DEBUG "Obsoleting node frag %p (%x-%x) and removing from tree\n", this, this->ofs, this->ofs+this->size)); + rb_erase(&this->rb, list); + jffs2_obsolete_node_frag(c, this); } + /* Now we're pointing at the first frag which isn't totally obsoleted by + the new frag */ - tn->fn = jffs2_alloc_full_dnode(); - if (!tn->fn) { - D1(printk(KERN_DEBUG "alloc fn failed\n")); - jffs2_free_tmp_dnode_info(tn); - return -ENOMEM; + if (!this || newfrag->ofs + newfrag->size == this->ofs) { + return 0; } - - tn->version = je32_to_cpu(rd->version); - tn->fn->ofs = je32_to_cpu(rd->offset); - tn->fn->raw = ref; - - /* There was a bug where we wrote hole nodes out with - csize/dsize swapped. Deal with it */ - if (rd->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(rd->dsize) && je32_to_cpu(rd->csize)) - tn->fn->size = je32_to_cpu(rd->csize); - else // normal case... - tn->fn->size = je32_to_cpu(rd->dsize); - - D1(printk(KERN_DEBUG "dnode @%08x: ver %u, offset %#04x, dsize %#04x\n", - ref_offset(ref), je32_to_cpu(rd->version), - je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize))); - - jffs2_add_tn_to_tree(tn, tnp); + /* Still some overlap but we don't need to move it in the tree */ + this->size = (this->ofs + this->size) - (newfrag->ofs + newfrag->size); + this->ofs = newfrag->ofs + newfrag->size; + + /* And mark them REF_NORMAL so the GC takes a look at them */ + if (this->node) + mark_ref_normal(this->node->raw); + mark_ref_normal(newfrag->node->raw); return 0; } -/* - * Helper function for jffs2_get_inode_nodes(). - * It is called every time an unknown node is found. - * - * Returns: 0 on succes; - * 1 if the node should be marked obsolete; - * negative error code on failure. +/* Given an inode, probably with existing list of fragments, add the new node + * to the fragment list. */ -static inline int -read_unknown(struct jffs2_sb_info *c, - struct jffs2_raw_node_ref *ref, - struct jffs2_unknown_node *un, - uint32_t read) +int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn) { - /* We don't mark unknown nodes as REF_UNCHECKED */ - BUG_ON(ref_flags(ref) == REF_UNCHECKED); - - un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype)); + int ret; + struct jffs2_node_frag *newfrag; - if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) { + D1(printk(KERN_DEBUG "jffs2_add_full_dnode_to_inode(ino #%u, f %p, fn %p)\n", f->inocache->ino, f, fn)); - /* Hmmm. This should have been caught at scan time. */ - printk(KERN_WARNING "Warning! Node header CRC failed at %#08x. " - "But it must have been OK earlier.\n", ref_offset(ref)); - D1(printk(KERN_DEBUG "Node was: { %#04x, %#04x, %#08x, %#08x }\n", - je16_to_cpu(un->magic), je16_to_cpu(un->nodetype), - je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc))); - return 1; - } else { - switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) { + if (unlikely(!fn->size)) + return 0; - case JFFS2_FEATURE_INCOMPAT: - printk(KERN_NOTICE "Unknown INCOMPAT nodetype %#04X at %#08x\n", - je16_to_cpu(un->nodetype), ref_offset(ref)); - /* EEP */ - BUG(); - break; - - case JFFS2_FEATURE_ROCOMPAT: - printk(KERN_NOTICE "Unknown ROCOMPAT nodetype %#04X at %#08x\n", - je16_to_cpu(un->nodetype), ref_offset(ref)); - BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO)); - break; - - case JFFS2_FEATURE_RWCOMPAT_COPY: - printk(KERN_NOTICE "Unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n", - je16_to_cpu(un->nodetype), ref_offset(ref)); - break; - - case JFFS2_FEATURE_RWCOMPAT_DELETE: - printk(KERN_NOTICE "Unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n", - je16_to_cpu(un->nodetype), ref_offset(ref)); - return 1; - } - } - - return 0; -} - -/* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated - with this ino, returning the former in order of version */ + newfrag = jffs2_alloc_node_frag(); + if (unlikely(!newfrag)) + return -ENOMEM; -int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - struct rb_root *tnp, struct jffs2_full_dirent **fdp, - uint32_t *highest_version, uint32_t *latest_mctime, - uint32_t *mctime_ver) -{ - struct jffs2_raw_node_ref *ref, *valid_ref; - struct rb_root ret_tn = RB_ROOT; - struct jffs2_full_dirent *ret_fd = NULL; - union jffs2_node_union node; - size_t retlen; - int err; - - *mctime_ver = 0; + D2(printk(KERN_DEBUG "adding node %04x-%04x @0x%08x on flash, newfrag *%p\n", + fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag)); - D1(printk(KERN_DEBUG "jffs2_get_inode_nodes(): ino #%u\n", f->inocache->ino)); - - spin_lock(&c->erase_completion_lock); - - valid_ref = jffs2_first_valid_node(f->inocache->nodes); - - if (!valid_ref && (f->inocache->ino != 1)) - printk(KERN_WARNING "Eep. No valid nodes for ino #%u\n", f->inocache->ino); - - while (valid_ref) { - /* We can hold a pointer to a non-obsolete node without the spinlock, - but _obsolete_ nodes may disappear at any time, if the block - they're in gets erased. So if we mark 'ref' obsolete while we're - not holding the lock, it can go away immediately. For that reason, - we find the next valid node first, before processing 'ref'. - */ - ref = valid_ref; - valid_ref = jffs2_first_valid_node(ref->next_in_ino); - spin_unlock(&c->erase_completion_lock); - - cond_resched(); - - /* FIXME: point() */ - err = jffs2_flash_read(c, (ref_offset(ref)), - min_t(uint32_t, ref_totlen(c, NULL, ref), sizeof(node)), - &retlen, (void *)&node); - if (err) { - printk(KERN_WARNING "error %d reading node at 0x%08x in get_inode_nodes()\n", err, ref_offset(ref)); - goto free_out; - } - - switch (je16_to_cpu(node.u.nodetype)) { - - case JFFS2_NODETYPE_DIRENT: - D1(printk(KERN_DEBUG "Node at %08x (%d) is a dirent node\n", ref_offset(ref), ref_flags(ref))); - - if (retlen < sizeof(node.d)) { - printk(KERN_WARNING "Warning! Short read dirent at %#08x\n", ref_offset(ref)); - err = -EIO; - goto free_out; - } - - err = read_direntry(c, ref, &node.d, retlen, &ret_fd, latest_mctime, mctime_ver); - if (err == 1) { - jffs2_mark_node_obsolete(c, ref); - break; - } else if (unlikely(err)) - goto free_out; - - if (je32_to_cpu(node.d.version) > *highest_version) - *highest_version = je32_to_cpu(node.d.version); - - break; - - case JFFS2_NODETYPE_INODE: - D1(printk(KERN_DEBUG "Node at %08x (%d) is a data node\n", ref_offset(ref), ref_flags(ref))); - - if (retlen < sizeof(node.i)) { - printk(KERN_WARNING "Warning! Short read dnode at %#08x\n", ref_offset(ref)); - err = -EIO; - goto free_out; - } - - err = read_dnode(c, ref, &node.i, retlen, &ret_tn, latest_mctime, mctime_ver); - if (err == 1) { - jffs2_mark_node_obsolete(c, ref); - break; - } else if (unlikely(err)) - goto free_out; - - if (je32_to_cpu(node.i.version) > *highest_version) - *highest_version = je32_to_cpu(node.i.version); - - D1(printk(KERN_DEBUG "version %d, highest_version now %d\n", - je32_to_cpu(node.i.version), *highest_version)); - - break; - - default: - /* Check we've managed to read at least the common node header */ - if (retlen < sizeof(struct jffs2_unknown_node)) { - printk(KERN_WARNING "Warning! Short read unknown node at %#08x\n", - ref_offset(ref)); - return -EIO; - } - - err = read_unknown(c, ref, &node.u, retlen); - if (err == 1) { - jffs2_mark_node_obsolete(c, ref); - break; - } else if (unlikely(err)) - goto free_out; + newfrag->ofs = fn->ofs; + newfrag->size = fn->size; + newfrag->node = fn; + newfrag->node->frags = 1; + + ret = jffs2_add_frag_to_fragtree(c, &f->fragtree, newfrag); + if (unlikely(ret)) + return ret; + + /* If we now share a page with other nodes, mark either previous + or next node REF_NORMAL, as appropriate. */ + if (newfrag->ofs & (PAGE_CACHE_SIZE-1)) { + struct jffs2_node_frag *prev = frag_prev(newfrag); + + mark_ref_normal(fn->raw); + /* If we don't start at zero there's _always_ a previous */ + if (prev->node) + mark_ref_normal(prev->node->raw); + } + if ((newfrag->ofs+newfrag->size) & (PAGE_CACHE_SIZE-1)) { + struct jffs2_node_frag *next = frag_next(newfrag); + + if (next) { + mark_ref_normal(fn->raw); + if (next->node) + mark_ref_normal(next->node->raw); } - spin_lock(&c->erase_completion_lock); - } - spin_unlock(&c->erase_completion_lock); - *tnp = ret_tn; - *fdp = ret_fd; - + jffs2_dbg_fragtree_paranoia_check_nolock(f); + jffs2_dbg_dump_fragtree_nolock(f); return 0; - - free_out: - jffs2_free_tmp_dnode_info_list(&ret_tn); - jffs2_free_full_dirent_list(ret_fd); - return err; } + void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state) { spin_lock(&c->inocache_lock); @@ -773,29 +542,3 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) cond_resched(); } } - -void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_node_frag *base) -{ - struct rb_node *parent = &base->rb; - struct rb_node **link = &parent; - - D2(printk(KERN_DEBUG "jffs2_fragtree_insert(%p; %d-%d, %p)\n", newfrag, - newfrag->ofs, newfrag->ofs+newfrag->size, base)); - - while (*link) { - parent = *link; - base = rb_entry(parent, struct jffs2_node_frag, rb); - - D2(printk(KERN_DEBUG "fragtree_insert considering frag at 0x%x\n", base->ofs)); - if (newfrag->ofs > base->ofs) - link = &base->rb.rb_right; - else if (newfrag->ofs < base->ofs) - link = &base->rb.rb_left; - else { - printk(KERN_CRIT "Duplicate frag at %08x (%p,%p)\n", newfrag->ofs, newfrag, base); - BUG(); - } - } - - rb_link_node(&newfrag->rb, &base->rb, link); -} diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 0058e395641..452fc81f391 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.h,v 1.134 2005/07/24 15:29:56 dedekind Exp $ + * $Id: nodelist.h,v 1.135 2005/07/27 14:46:11 dedekind Exp $ * */ @@ -297,10 +297,6 @@ static inline struct jffs2_node_frag *frag_last(struct rb_root *root) /* nodelist.c */ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list); -int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - struct rb_root *tnp, struct jffs2_full_dirent **fdp, - uint32_t *highest_version, uint32_t *latest_mctime, - uint32_t *mctime_ver); void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state); struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t ino); void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new); @@ -309,10 +305,11 @@ void jffs2_free_ino_caches(struct jffs2_sb_info *c); void jffs2_free_raw_node_refs(struct jffs2_sb_info *c); struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset); void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c_delete); -void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_node_frag *base); struct rb_node *rb_next(struct rb_node *); struct rb_node *rb_prev(struct rb_node *); void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root); +void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this); +int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); /* nodemgmt.c */ int jffs2_thread_should_wake(struct jffs2_sb_info *c); @@ -337,7 +334,6 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint /* readinode.c */ void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); -int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t ino, struct jffs2_raw_inode *latest_node); int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 339ba46320f..85a285b2a30 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.130 2005/07/24 15:29:56 dedekind Exp $ + * $Id: readinode.c,v 1.131 2005/07/27 14:46:11 dedekind Exp $ * */ @@ -20,376 +20,537 @@ #include #include "nodelist.h" -static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *list, struct jffs2_node_frag *newfrag); - -static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this) +void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size) { - if (this->node) { - this->node->frags--; - if (!this->node->frags) { - /* The node has no valid frags left. It's totally obsoleted */ - D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) obsolete\n", - ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size)); - jffs2_mark_node_obsolete(c, this->node->raw); - jffs2_free_full_dnode(this->node); - } else { - D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) REF_NORMAL. frags is %d\n", - ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size, - this->node->frags)); - mark_ref_normal(this->node->raw); + struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size); + + D1(printk(KERN_DEBUG "Truncating fraglist to 0x%08x bytes\n", size)); + + /* We know frag->ofs <= size. That's what lookup does for us */ + if (frag && frag->ofs != size) { + if (frag->ofs+frag->size >= size) { + D1(printk(KERN_DEBUG "Truncating frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size)); + frag->size = size - frag->ofs; } - + frag = frag_next(frag); + } + while (frag && frag->ofs >= size) { + struct jffs2_node_frag *next = frag_next(frag); + + D1(printk(KERN_DEBUG "Removing frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size)); + frag_erase(frag, list); + jffs2_obsolete_node_frag(c, frag); + frag = next; } - jffs2_free_node_frag(this); } -/* Given an inode, probably with existing list of fragments, add the new node - * to the fragment list. +/* + * Put a new tmp_dnode_info into the temporaty RB-tree, keeping the list in + * order of increasing version. */ -int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn) +static void jffs2_add_tn_to_tree(struct jffs2_tmp_dnode_info *tn, struct rb_root *list) { - int ret; - struct jffs2_node_frag *newfrag; + struct rb_node **p = &list->rb_node; + struct rb_node * parent = NULL; + struct jffs2_tmp_dnode_info *this; + + while (*p) { + parent = *p; + this = rb_entry(parent, struct jffs2_tmp_dnode_info, rb); + + /* There may actually be a collision here, but it doesn't + actually matter. As long as the two nodes with the same + version are together, it's all fine. */ + if (tn->version < this->version) + p = &(*p)->rb_left; + else + p = &(*p)->rb_right; + } + + rb_link_node(&tn->rb, parent, p); + rb_insert_color(&tn->rb, list); +} - D1(printk(KERN_DEBUG "jffs2_add_full_dnode_to_inode(ino #%u, f %p, fn %p)\n", f->inocache->ino, f, fn)); +static void jffs2_free_tmp_dnode_info_list(struct rb_root *list) +{ + struct rb_node *this; + struct jffs2_tmp_dnode_info *tn; + + this = list->rb_node; + + /* Now at bottom of tree */ + while (this) { + if (this->rb_left) + this = this->rb_left; + else if (this->rb_right) + this = this->rb_right; + else { + tn = rb_entry(this, struct jffs2_tmp_dnode_info, rb); + jffs2_free_full_dnode(tn->fn); + jffs2_free_tmp_dnode_info(tn); + + this = this->rb_parent; + if (!this) + break; + + if (this->rb_left == &tn->rb) + this->rb_left = NULL; + else if (this->rb_right == &tn->rb) + this->rb_right = NULL; + else BUG(); + } + } + list->rb_node = NULL; +} - if (unlikely(!fn->size)) - return 0; +static void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd) +{ + struct jffs2_full_dirent *next; - newfrag = jffs2_alloc_node_frag(); - if (unlikely(!newfrag)) - return -ENOMEM; + while (fd) { + next = fd->next; + jffs2_free_full_dirent(fd); + fd = next; + } +} - D2(printk(KERN_DEBUG "adding node %04x-%04x @0x%08x on flash, newfrag *%p\n", - fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag)); - - newfrag->ofs = fn->ofs; - newfrag->size = fn->size; - newfrag->node = fn; - newfrag->node->frags = 1; +/* Returns first valid node after 'ref'. May return 'ref' */ +static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_ref *ref) +{ + while (ref && ref->next_in_ino) { + if (!ref_obsolete(ref)) + return ref; + D1(printk(KERN_DEBUG "node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref))); + ref = ref->next_in_ino; + } + return NULL; +} - ret = jffs2_add_frag_to_fragtree(c, &f->fragtree, newfrag); - if (ret) - return ret; +/* + * Helper function for jffs2_get_inode_nodes(). + * It is called every time an directory entry node is found. + * + * Returns: 0 on succes; + * 1 if the node should be marked obsolete; + * negative error code on failure. + */ +static inline int +read_direntry(struct jffs2_sb_info *c, + struct jffs2_raw_node_ref *ref, + struct jffs2_raw_dirent *rd, + uint32_t read, + struct jffs2_full_dirent **fdp, + int32_t *latest_mctime, + uint32_t *mctime_ver) +{ + struct jffs2_full_dirent *fd; + + /* The direntry nodes are checked during the flash scanning */ + BUG_ON(ref_flags(ref) == REF_UNCHECKED); + /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ + BUG_ON(ref_obsolete(ref)); + + /* Sanity check */ + if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) { + printk(KERN_ERR "Error! Illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n", + ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen)); + return 1; + } + + fd = jffs2_alloc_full_dirent(rd->nsize + 1); + if (unlikely(!fd)) + return -ENOMEM; - /* If we now share a page with other nodes, mark either previous - or next node REF_NORMAL, as appropriate. */ - if (newfrag->ofs & (PAGE_CACHE_SIZE-1)) { - struct jffs2_node_frag *prev = frag_prev(newfrag); + fd->raw = ref; + fd->version = je32_to_cpu(rd->version); + fd->ino = je32_to_cpu(rd->ino); + fd->type = rd->type; - mark_ref_normal(fn->raw); - /* If we don't start at zero there's _always_ a previous */ - if (prev->node) - mark_ref_normal(prev->node->raw); + /* Pick out the mctime of the latest dirent */ + if(fd->version > *mctime_ver) { + *mctime_ver = fd->version; + *latest_mctime = je32_to_cpu(rd->mctime); } - if ((newfrag->ofs+newfrag->size) & (PAGE_CACHE_SIZE-1)) { - struct jffs2_node_frag *next = frag_next(newfrag); + /* + * Copy as much of the name as possible from the raw + * dirent we've already read from the flash. + */ + if (read > sizeof(*rd)) + memcpy(&fd->name[0], &rd->name[0], + min_t(uint32_t, rd->nsize, (read - sizeof(*rd)) )); - if (next) { - mark_ref_normal(fn->raw); - if (next->node) - mark_ref_normal(next->node->raw); + /* Do we need to copy any more of the name directly from the flash? */ + if (rd->nsize + sizeof(*rd) > read) { + /* FIXME: point() */ + int err; + int already = read - sizeof(*rd); + + err = jffs2_flash_read(c, (ref_offset(ref)) + read, + rd->nsize - already, &read, &fd->name[already]); + if (unlikely(read != rd->nsize - already) && likely(!err)) + return -EIO; + + if (unlikely(err)) { + printk(KERN_WARNING "Read remainder of name: error %d\n", err); + jffs2_free_full_dirent(fd); + return -EIO; } } - jffs2_dbg_fragtree_paranoia_check_nolock(f); - jffs2_dbg_dump_fragtree_nolock(f); + + fd->nhash = full_name_hash(fd->name, rd->nsize); + fd->next = NULL; + fd->name[rd->nsize] = '\0'; + + /* + * Wheee. We now have a complete jffs2_full_dirent structure, with + * the name in it and everything. Link it into the list + */ + D1(printk(KERN_DEBUG "Adding fd \"%s\", ino #%u\n", fd->name, fd->ino)); + + jffs2_add_fd_to_list(c, fd, fdp); + return 0; } -/* Doesn't set inode->i_size */ -static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *list, struct jffs2_node_frag *newfrag) +/* + * Helper function for jffs2_get_inode_nodes(). + * It is called every time an inode node is found. + * + * Returns: 0 on succes; + * 1 if the node should be marked obsolete; + * negative error code on failure. + */ +static inline int +read_dnode(struct jffs2_sb_info *c, + struct jffs2_raw_node_ref *ref, + struct jffs2_raw_inode *rd, + uint32_t read, + struct rb_root *tnp, + int32_t *latest_mctime, + uint32_t *mctime_ver) { - struct jffs2_node_frag *this; - uint32_t lastend; - - /* Skip all the nodes which are completed before this one starts */ - this = jffs2_lookup_node_frag(list, newfrag->node->ofs); - - if (this) { - D2(printk(KERN_DEBUG "j_a_f_d_t_f: Lookup gave frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", - this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this)); - lastend = this->ofs + this->size; - } else { - D2(printk(KERN_DEBUG "j_a_f_d_t_f: Lookup gave no frag\n")); - lastend = 0; - } - - /* See if we ran off the end of the list */ - if (lastend <= newfrag->ofs) { - /* We did */ - - /* Check if 'this' node was on the same page as the new node. - If so, both 'this' and the new node get marked REF_NORMAL so - the GC can take a look. - */ - if (lastend && (lastend-1) >> PAGE_CACHE_SHIFT == newfrag->ofs >> PAGE_CACHE_SHIFT) { - if (this->node) - mark_ref_normal(this->node->raw); - mark_ref_normal(newfrag->node->raw); + struct jffs2_eraseblock *jeb; + struct jffs2_tmp_dnode_info *tn; + + /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ + BUG_ON(ref_obsolete(ref)); + + /* If we've never checked the CRCs on this node, check them now */ + if (ref_flags(ref) == REF_UNCHECKED) { + uint32_t crc, len; + + crc = crc32(0, rd, sizeof(*rd) - 8); + if (unlikely(crc != je32_to_cpu(rd->node_crc))) { + printk(KERN_WARNING "Header CRC failed on node at %#08x: read %#08x, calculated %#08x\n", + ref_offset(ref), je32_to_cpu(rd->node_crc), crc); + return 1; + } + + /* Sanity checks */ + if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) || + unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) { + printk(KERN_WARNING "Inode corrupted at %#08x, totlen %d, #ino %d, version %d, " + "isize %d, csize %d, dsize %d \n", + ref_offset(ref), je32_to_cpu(rd->totlen), je32_to_cpu(rd->ino), + je32_to_cpu(rd->version), je32_to_cpu(rd->isize), + je32_to_cpu(rd->csize), je32_to_cpu(rd->dsize)); + return 1; } - if (lastend < newfrag->node->ofs) { - /* ... and we need to put a hole in before the new node */ - struct jffs2_node_frag *holefrag = jffs2_alloc_node_frag(); - if (!holefrag) { - jffs2_free_node_frag(newfrag); - return -ENOMEM; + if (rd->compr != JFFS2_COMPR_ZERO && je32_to_cpu(rd->csize)) { + unsigned char *buf = NULL; + uint32_t pointed = 0; + int err; +#ifndef __ECOS + if (c->mtd->point) { + err = c->mtd->point (c->mtd, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize), + &read, &buf); + if (unlikely(read < je32_to_cpu(rd->csize)) && likely(!err)) { + D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", read)); + c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(*rd), + je32_to_cpu(rd->csize)); + } else if (unlikely(err)){ + D1(printk(KERN_DEBUG "MTD point failed %d\n", err)); + } else + pointed = 1; /* succefully pointed to device */ } - holefrag->ofs = lastend; - holefrag->size = newfrag->node->ofs - lastend; - holefrag->node = NULL; - if (this) { - /* By definition, the 'this' node has no right-hand child, - because there are no frags with offset greater than it. - So that's where we want to put the hole */ - D2(printk(KERN_DEBUG "Adding hole frag (%p) on right of node at (%p)\n", holefrag, this)); - rb_link_node(&holefrag->rb, &this->rb, &this->rb.rb_right); - } else { - D2(printk(KERN_DEBUG "Adding hole frag (%p) at root of tree\n", holefrag)); - rb_link_node(&holefrag->rb, NULL, &list->rb_node); +#endif + if(!pointed){ + buf = kmalloc(je32_to_cpu(rd->csize), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + err = jffs2_flash_read(c, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize), + &read, buf); + if (unlikely(read != je32_to_cpu(rd->csize)) && likely(!err)) + err = -EIO; + if (err) { + kfree(buf); + return err; + } } - rb_insert_color(&holefrag->rb, list); - this = holefrag; - } - if (this) { - /* By definition, the 'this' node has no right-hand child, - because there are no frags with offset greater than it. - So that's where we want to put the hole */ - D2(printk(KERN_DEBUG "Adding new frag (%p) on right of node at (%p)\n", newfrag, this)); - rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); - } else { - D2(printk(KERN_DEBUG "Adding new frag (%p) at root of tree\n", newfrag)); - rb_link_node(&newfrag->rb, NULL, &list->rb_node); - } - rb_insert_color(&newfrag->rb, list); - return 0; - } - - D2(printk(KERN_DEBUG "j_a_f_d_t_f: dealing with frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", - this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this)); - - /* OK. 'this' is pointing at the first frag that newfrag->ofs at least partially obsoletes, - * - i.e. newfrag->ofs < this->ofs+this->size && newfrag->ofs >= this->ofs - */ - if (newfrag->ofs > this->ofs) { - /* This node isn't completely obsoleted. The start of it remains valid */ - - /* Mark the new node and the partially covered node REF_NORMAL -- let - the GC take a look at them */ - mark_ref_normal(newfrag->node->raw); - if (this->node) - mark_ref_normal(this->node->raw); - - if (this->ofs + this->size > newfrag->ofs + newfrag->size) { - /* The new node splits 'this' frag into two */ - struct jffs2_node_frag *newfrag2 = jffs2_alloc_node_frag(); - if (!newfrag2) { - jffs2_free_node_frag(newfrag); - return -ENOMEM; + crc = crc32(0, buf, je32_to_cpu(rd->csize)); + if(!pointed) + kfree(buf); +#ifndef __ECOS + else + c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize)); +#endif + + if (crc != je32_to_cpu(rd->data_crc)) { + printk(KERN_NOTICE "Data CRC failed on node at %#08x: read %#08x, calculated %#08x\n", + ref_offset(ref), je32_to_cpu(rd->data_crc), crc); + return 1; } - D2(printk(KERN_DEBUG "split old frag 0x%04x-0x%04x -->", this->ofs, this->ofs+this->size); - if (this->node) - printk("phys 0x%08x\n", ref_offset(this->node->raw)); - else - printk("hole\n"); - ) - - /* New second frag pointing to this's node */ - newfrag2->ofs = newfrag->ofs + newfrag->size; - newfrag2->size = (this->ofs+this->size) - newfrag2->ofs; - newfrag2->node = this->node; - if (this->node) - this->node->frags++; - - /* Adjust size of original 'this' */ - this->size = newfrag->ofs - this->ofs; - - /* Now, we know there's no node with offset - greater than this->ofs but smaller than - newfrag2->ofs or newfrag->ofs, for obvious - reasons. So we can do a tree insert from - 'this' to insert newfrag, and a tree insert - from newfrag to insert newfrag2. */ - jffs2_fragtree_insert(newfrag, this); - rb_insert_color(&newfrag->rb, list); - jffs2_fragtree_insert(newfrag2, newfrag); - rb_insert_color(&newfrag2->rb, list); - - return 0; } - /* New node just reduces 'this' frag in size, doesn't split it */ - this->size = newfrag->ofs - this->ofs; - /* Again, we know it lives down here in the tree */ - jffs2_fragtree_insert(newfrag, this); - rb_insert_color(&newfrag->rb, list); - } else { - /* New frag starts at the same point as 'this' used to. Replace - it in the tree without doing a delete and insertion */ - D2(printk(KERN_DEBUG "Inserting newfrag (*%p),%d-%d in before 'this' (*%p),%d-%d\n", - newfrag, newfrag->ofs, newfrag->ofs+newfrag->size, - this, this->ofs, this->ofs+this->size)); - - rb_replace_node(&this->rb, &newfrag->rb, list); - - if (newfrag->ofs + newfrag->size >= this->ofs+this->size) { - D2(printk(KERN_DEBUG "Obsoleting node frag %p (%x-%x)\n", this, this->ofs, this->ofs+this->size)); - jffs2_obsolete_node_frag(c, this); - } else { - this->ofs += newfrag->size; - this->size -= newfrag->size; + /* Mark the node as having been checked and fix the accounting accordingly */ + jeb = &c->blocks[ref->flash_offset / c->sector_size]; + len = ref_totlen(c, jeb, ref); + + spin_lock(&c->erase_completion_lock); + jeb->used_size += len; + jeb->unchecked_size -= len; + c->used_size += len; + c->unchecked_size -= len; + + /* If node covers at least a whole page, or if it starts at the + beginning of a page and runs to the end of the file, or if + it's a hole node, mark it REF_PRISTINE, else REF_NORMAL. - jffs2_fragtree_insert(this, newfrag); - rb_insert_color(&this->rb, list); - return 0; + If it's actually overlapped, it'll get made NORMAL (or OBSOLETE) + when the overlapping node(s) get added to the tree anyway. + */ + if ((je32_to_cpu(rd->dsize) >= PAGE_CACHE_SIZE) || + ( ((je32_to_cpu(rd->offset) & (PAGE_CACHE_SIZE-1))==0) && + (je32_to_cpu(rd->dsize) + je32_to_cpu(rd->offset) == je32_to_cpu(rd->isize)))) { + D1(printk(KERN_DEBUG "Marking node at %#08x REF_PRISTINE\n", ref_offset(ref))); + ref->flash_offset = ref_offset(ref) | REF_PRISTINE; + } else { + D1(printk(KERN_DEBUG "Marking node at %#08x REF_NORMAL\n", ref_offset(ref))); + ref->flash_offset = ref_offset(ref) | REF_NORMAL; } + spin_unlock(&c->erase_completion_lock); } - /* OK, now we have newfrag added in the correct place in the tree, but - frag_next(newfrag) may be a fragment which is overlapped by it - */ - while ((this = frag_next(newfrag)) && newfrag->ofs + newfrag->size >= this->ofs + this->size) { - /* 'this' frag is obsoleted completely. */ - D2(printk(KERN_DEBUG "Obsoleting node frag %p (%x-%x) and removing from tree\n", this, this->ofs, this->ofs+this->size)); - rb_erase(&this->rb, list); - jffs2_obsolete_node_frag(c, this); - } - /* Now we're pointing at the first frag which isn't totally obsoleted by - the new frag */ - if (!this || newfrag->ofs + newfrag->size == this->ofs) { - return 0; + tn = jffs2_alloc_tmp_dnode_info(); + if (!tn) { + D1(printk(KERN_DEBUG "alloc tn failed\n")); + return -ENOMEM; } - /* Still some overlap but we don't need to move it in the tree */ - this->size = (this->ofs + this->size) - (newfrag->ofs + newfrag->size); - this->ofs = newfrag->ofs + newfrag->size; - /* And mark them REF_NORMAL so the GC takes a look at them */ - if (this->node) - mark_ref_normal(this->node->raw); - mark_ref_normal(newfrag->node->raw); + tn->fn = jffs2_alloc_full_dnode(); + if (!tn->fn) { + D1(printk(KERN_DEBUG "alloc fn failed\n")); + jffs2_free_tmp_dnode_info(tn); + return -ENOMEM; + } + + tn->version = je32_to_cpu(rd->version); + tn->fn->ofs = je32_to_cpu(rd->offset); + tn->fn->raw = ref; + + /* There was a bug where we wrote hole nodes out with + csize/dsize swapped. Deal with it */ + if (rd->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(rd->dsize) && je32_to_cpu(rd->csize)) + tn->fn->size = je32_to_cpu(rd->csize); + else // normal case... + tn->fn->size = je32_to_cpu(rd->dsize); + + D1(printk(KERN_DEBUG "dnode @%08x: ver %u, offset %#04x, dsize %#04x\n", + ref_offset(ref), je32_to_cpu(rd->version), + je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize))); + + jffs2_add_tn_to_tree(tn, tnp); return 0; } -void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size) +/* + * Helper function for jffs2_get_inode_nodes(). + * It is called every time an unknown node is found. + * + * Returns: 0 on succes; + * 1 if the node should be marked obsolete; + * negative error code on failure. + */ +static inline int +read_unknown(struct jffs2_sb_info *c, + struct jffs2_raw_node_ref *ref, + struct jffs2_unknown_node *un, + uint32_t read) { - struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size); + /* We don't mark unknown nodes as REF_UNCHECKED */ + BUG_ON(ref_flags(ref) == REF_UNCHECKED); + + un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype)); - D1(printk(KERN_DEBUG "Truncating fraglist to 0x%08x bytes\n", size)); + if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) { - /* We know frag->ofs <= size. That's what lookup does for us */ - if (frag && frag->ofs != size) { - if (frag->ofs+frag->size >= size) { - D1(printk(KERN_DEBUG "Truncating frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size)); - frag->size = size - frag->ofs; + /* Hmmm. This should have been caught at scan time. */ + printk(KERN_WARNING "Warning! Node header CRC failed at %#08x. " + "But it must have been OK earlier.\n", ref_offset(ref)); + D1(printk(KERN_DEBUG "Node was: { %#04x, %#04x, %#08x, %#08x }\n", + je16_to_cpu(un->magic), je16_to_cpu(un->nodetype), + je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc))); + return 1; + } else { + switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) { + + case JFFS2_FEATURE_INCOMPAT: + printk(KERN_NOTICE "Unknown INCOMPAT nodetype %#04X at %#08x\n", + je16_to_cpu(un->nodetype), ref_offset(ref)); + /* EEP */ + BUG(); + break; + + case JFFS2_FEATURE_ROCOMPAT: + printk(KERN_NOTICE "Unknown ROCOMPAT nodetype %#04X at %#08x\n", + je16_to_cpu(un->nodetype), ref_offset(ref)); + BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO)); + break; + + case JFFS2_FEATURE_RWCOMPAT_COPY: + printk(KERN_NOTICE "Unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n", + je16_to_cpu(un->nodetype), ref_offset(ref)); + break; + + case JFFS2_FEATURE_RWCOMPAT_DELETE: + printk(KERN_NOTICE "Unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n", + je16_to_cpu(un->nodetype), ref_offset(ref)); + return 1; } - frag = frag_next(frag); } - while (frag && frag->ofs >= size) { - struct jffs2_node_frag *next = frag_next(frag); - D1(printk(KERN_DEBUG "Removing frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size)); - frag_erase(frag, list); - jffs2_obsolete_node_frag(c, frag); - frag = next; - } + return 0; } -/* Scan the list of all nodes present for this ino, build map of versions, etc. */ - -static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, - struct jffs2_inode_info *f, - struct jffs2_raw_inode *latest_node); +/* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated + with this ino, returning the former in order of version */ -int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - uint32_t ino, struct jffs2_raw_inode *latest_node) +static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f, + struct rb_root *tnp, struct jffs2_full_dirent **fdp, + uint32_t *highest_version, uint32_t *latest_mctime, + uint32_t *mctime_ver) { - D2(printk(KERN_DEBUG "jffs2_do_read_inode(): getting inocache\n")); + struct jffs2_raw_node_ref *ref, *valid_ref; + struct rb_root ret_tn = RB_ROOT; + struct jffs2_full_dirent *ret_fd = NULL; + union jffs2_node_union node; + size_t retlen; + int err; - retry_inocache: - spin_lock(&c->inocache_lock); - f->inocache = jffs2_get_ino_cache(c, ino); + *mctime_ver = 0; + + D1(printk(KERN_DEBUG "jffs2_get_inode_nodes(): ino #%u\n", f->inocache->ino)); - D2(printk(KERN_DEBUG "jffs2_do_read_inode(): Got inocache at %p\n", f->inocache)); + spin_lock(&c->erase_completion_lock); - if (f->inocache) { - /* Check its state. We may need to wait before we can use it */ - switch(f->inocache->state) { - case INO_STATE_UNCHECKED: - case INO_STATE_CHECKEDABSENT: - f->inocache->state = INO_STATE_READING; - break; + valid_ref = jffs2_first_valid_node(f->inocache->nodes); + + if (!valid_ref && (f->inocache->ino != 1)) + printk(KERN_WARNING "Eep. No valid nodes for ino #%u\n", f->inocache->ino); + + while (valid_ref) { + /* We can hold a pointer to a non-obsolete node without the spinlock, + but _obsolete_ nodes may disappear at any time, if the block + they're in gets erased. So if we mark 'ref' obsolete while we're + not holding the lock, it can go away immediately. For that reason, + we find the next valid node first, before processing 'ref'. + */ + ref = valid_ref; + valid_ref = jffs2_first_valid_node(ref->next_in_ino); + spin_unlock(&c->erase_completion_lock); + + cond_resched(); + + /* FIXME: point() */ + err = jffs2_flash_read(c, (ref_offset(ref)), + min_t(uint32_t, ref_totlen(c, NULL, ref), sizeof(node)), + &retlen, (void *)&node); + if (err) { + printk(KERN_WARNING "error %d reading node at 0x%08x in get_inode_nodes()\n", err, ref_offset(ref)); + goto free_out; + } - case INO_STATE_CHECKING: - case INO_STATE_GC: - /* If it's in either of these states, we need - to wait for whoever's got it to finish and - put it back. */ - D1(printk(KERN_DEBUG "jffs2_get_ino_cache_read waiting for ino #%u in state %d\n", - ino, f->inocache->state)); - sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); - goto retry_inocache; + switch (je16_to_cpu(node.u.nodetype)) { + + case JFFS2_NODETYPE_DIRENT: + D1(printk(KERN_DEBUG "Node at %08x (%d) is a dirent node\n", ref_offset(ref), ref_flags(ref))); + + if (retlen < sizeof(node.d)) { + printk(KERN_WARNING "Warning! Short read dirent at %#08x\n", ref_offset(ref)); + err = -EIO; + goto free_out; + } + + err = read_direntry(c, ref, &node.d, retlen, &ret_fd, latest_mctime, mctime_ver); + if (err == 1) { + jffs2_mark_node_obsolete(c, ref); + break; + } else if (unlikely(err)) + goto free_out; + + if (je32_to_cpu(node.d.version) > *highest_version) + *highest_version = je32_to_cpu(node.d.version); - case INO_STATE_READING: - case INO_STATE_PRESENT: - /* Eep. This should never happen. It can - happen if Linux calls read_inode() again - before clear_inode() has finished though. */ - printk(KERN_WARNING "Eep. Trying to read_inode #%u when it's already in state %d!\n", ino, f->inocache->state); - /* Fail. That's probably better than allowing it to succeed */ - f->inocache = NULL; break; - default: - BUG(); - } - } - spin_unlock(&c->inocache_lock); + case JFFS2_NODETYPE_INODE: + D1(printk(KERN_DEBUG "Node at %08x (%d) is a data node\n", ref_offset(ref), ref_flags(ref))); + + if (retlen < sizeof(node.i)) { + printk(KERN_WARNING "Warning! Short read dnode at %#08x\n", ref_offset(ref)); + err = -EIO; + goto free_out; + } - if (!f->inocache && ino == 1) { - /* Special case - no root inode on medium */ - f->inocache = jffs2_alloc_inode_cache(); - if (!f->inocache) { - printk(KERN_CRIT "jffs2_do_read_inode(): Cannot allocate inocache for root inode\n"); - return -ENOMEM; - } - D1(printk(KERN_DEBUG "jffs2_do_read_inode(): Creating inocache for root inode\n")); - memset(f->inocache, 0, sizeof(struct jffs2_inode_cache)); - f->inocache->ino = f->inocache->nlink = 1; - f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; - f->inocache->state = INO_STATE_READING; - jffs2_add_ino_cache(c, f->inocache); - } - if (!f->inocache) { - printk(KERN_WARNING "jffs2_do_read_inode() on nonexistent ino %u\n", ino); - return -ENOENT; - } + err = read_dnode(c, ref, &node.i, retlen, &ret_tn, latest_mctime, mctime_ver); + if (err == 1) { + jffs2_mark_node_obsolete(c, ref); + break; + } else if (unlikely(err)) + goto free_out; - return jffs2_do_read_inode_internal(c, f, latest_node); -} + if (je32_to_cpu(node.i.version) > *highest_version) + *highest_version = je32_to_cpu(node.i.version); + + D1(printk(KERN_DEBUG "version %d, highest_version now %d\n", + je32_to_cpu(node.i.version), *highest_version)); -int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) -{ - struct jffs2_raw_inode n; - struct jffs2_inode_info *f = kmalloc(sizeof(*f), GFP_KERNEL); - int ret; + break; - if (!f) - return -ENOMEM; + default: + /* Check we've managed to read at least the common node header */ + if (retlen < sizeof(struct jffs2_unknown_node)) { + printk(KERN_WARNING "Warning! Short read unknown node at %#08x\n", + ref_offset(ref)); + return -EIO; + } - memset(f, 0, sizeof(*f)); - init_MUTEX_LOCKED(&f->sem); - f->inocache = ic; + err = read_unknown(c, ref, &node.u, retlen); + if (err == 1) { + jffs2_mark_node_obsolete(c, ref); + break; + } else if (unlikely(err)) + goto free_out; + + } + spin_lock(&c->erase_completion_lock); - ret = jffs2_do_read_inode_internal(c, f, &n); - if (!ret) { - up(&f->sem); - jffs2_do_clear_inode(c, f); } - kfree (f); - return ret; + spin_unlock(&c->erase_completion_lock); + *tnp = ret_tn; + *fdp = ret_fd; + + return 0; + + free_out: + jffs2_free_tmp_dnode_info_list(&ret_tn); + jffs2_free_full_dirent_list(ret_fd); + return err; } static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, @@ -618,6 +779,96 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, return 0; } +/* Scan the list of all nodes present for this ino, build map of versions, etc. */ +int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, + uint32_t ino, struct jffs2_raw_inode *latest_node) +{ + D2(printk(KERN_DEBUG "jffs2_do_read_inode(): getting inocache\n")); + + retry_inocache: + spin_lock(&c->inocache_lock); + f->inocache = jffs2_get_ino_cache(c, ino); + + D2(printk(KERN_DEBUG "jffs2_do_read_inode(): Got inocache at %p\n", f->inocache)); + + if (f->inocache) { + /* Check its state. We may need to wait before we can use it */ + switch(f->inocache->state) { + case INO_STATE_UNCHECKED: + case INO_STATE_CHECKEDABSENT: + f->inocache->state = INO_STATE_READING; + break; + + case INO_STATE_CHECKING: + case INO_STATE_GC: + /* If it's in either of these states, we need + to wait for whoever's got it to finish and + put it back. */ + D1(printk(KERN_DEBUG "jffs2_get_ino_cache_read waiting for ino #%u in state %d\n", + ino, f->inocache->state)); + sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); + goto retry_inocache; + + case INO_STATE_READING: + case INO_STATE_PRESENT: + /* Eep. This should never happen. It can + happen if Linux calls read_inode() again + before clear_inode() has finished though. */ + printk(KERN_WARNING "Eep. Trying to read_inode #%u when it's already in state %d!\n", ino, f->inocache->state); + /* Fail. That's probably better than allowing it to succeed */ + f->inocache = NULL; + break; + + default: + BUG(); + } + } + spin_unlock(&c->inocache_lock); + + if (!f->inocache && ino == 1) { + /* Special case - no root inode on medium */ + f->inocache = jffs2_alloc_inode_cache(); + if (!f->inocache) { + printk(KERN_CRIT "jffs2_do_read_inode(): Cannot allocate inocache for root inode\n"); + return -ENOMEM; + } + D1(printk(KERN_DEBUG "jffs2_do_read_inode(): Creating inocache for root inode\n")); + memset(f->inocache, 0, sizeof(struct jffs2_inode_cache)); + f->inocache->ino = f->inocache->nlink = 1; + f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; + f->inocache->state = INO_STATE_READING; + jffs2_add_ino_cache(c, f->inocache); + } + if (!f->inocache) { + printk(KERN_WARNING "jffs2_do_read_inode() on nonexistent ino %u\n", ino); + return -ENOENT; + } + + return jffs2_do_read_inode_internal(c, f, latest_node); +} + +int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) +{ + struct jffs2_raw_inode n; + struct jffs2_inode_info *f = kmalloc(sizeof(*f), GFP_KERNEL); + int ret; + + if (!f) + return -ENOMEM; + + memset(f, 0, sizeof(*f)); + init_MUTEX_LOCKED(&f->sem); + f->inocache = ic; + + ret = jffs2_do_read_inode_internal(c, f, &n); + if (!ret) { + up(&f->sem); + jffs2_do_clear_inode(c, f); + } + kfree (f); + return ret; +} + void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) { struct jffs2_full_dirent *fd, *fds; -- cgit v1.2.3 From e0d601373b1123ea43b1fdec08d9e58a079ae35c Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Thu, 28 Jul 2005 15:46:43 +0100 Subject: [JFFS2] Debug code clean up - step 5 Replace the D1(printk()) style debugging with the new debug macros Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/nodelist.c | 126 ++++++++++++++++++++++-------------------------- fs/jffs2/readinode.c | 134 +++++++++++++++++++++++---------------------------- 2 files changed, 117 insertions(+), 143 deletions(-) diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 8373d312b19..7997f526c94 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.c,v 1.101 2005/07/27 14:46:11 dedekind Exp $ + * $Id: nodelist.c,v 1.102 2005/07/28 12:45:10 dedekind Exp $ * */ @@ -24,35 +24,31 @@ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list) { struct jffs2_full_dirent **prev = list; - D1(printk(KERN_DEBUG "jffs2_add_fd_to_list( %p, %p (->%p))\n", new, list, *list)); + + JFFS2_DBG_DENTLIST("add dirent \"%s\", ino #%u\n", new->name, new->ino); while ((*prev) && (*prev)->nhash <= new->nhash) { if ((*prev)->nhash == new->nhash && !strcmp((*prev)->name, new->name)) { /* Duplicate. Free one */ if (new->version < (*prev)->version) { - D1(printk(KERN_DEBUG "Eep! Marking new dirent node obsolete\n")); - D1(printk(KERN_DEBUG "New dirent is \"%s\"->ino #%u. Old is \"%s\"->ino #%u\n", new->name, new->ino, (*prev)->name, (*prev)->ino)); + JFFS2_DBG_DENTLIST("Eep! Marking new dirent node is obsolete, old is \"%s\", ino #%u\n", + (*prev)->name, (*prev)->ino); jffs2_mark_node_obsolete(c, new->raw); jffs2_free_full_dirent(new); } else { - D1(printk(KERN_DEBUG "Marking old dirent node (ino #%u) obsolete\n", (*prev)->ino)); + JFFS2_DBG_DENTLIST("marking old dirent \"%s\", ino #%u bsolete\n", + (*prev)->name, (*prev)->ino); new->next = (*prev)->next; jffs2_mark_node_obsolete(c, ((*prev)->raw)); jffs2_free_full_dirent(*prev); *prev = new; } - goto out; + return; } prev = &((*prev)->next); } new->next = *prev; *prev = new; - - out: - D2(while(*list) { - printk(KERN_DEBUG "Dirent \"%s\" (hash 0x%08x, ino #%u\n", (*list)->name, (*list)->nhash, (*list)->ino); - list = &(*list)->next; - }); } void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this) @@ -61,14 +57,13 @@ void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *t this->node->frags--; if (!this->node->frags) { /* The node has no valid frags left. It's totally obsoleted */ - D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) obsolete\n", - ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size)); + JFFS2_DBG_FRAGTREE2("marking old node @0x%08x (0x%04x-0x%04x) obsolete\n", + ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size); jffs2_mark_node_obsolete(c, this->node->raw); jffs2_free_full_dnode(this->node); } else { - D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) REF_NORMAL. frags is %d\n", - ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size, - this->node->frags)); + JFFS2_DBG_FRAGTREE2("marking old node @0x%08x (0x%04x-0x%04x) REF_NORMAL. frags is %d\n", + ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size, this->node->frags); mark_ref_normal(this->node->raw); } @@ -81,20 +76,19 @@ static void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_ struct rb_node *parent = &base->rb; struct rb_node **link = &parent; - D2(printk(KERN_DEBUG "jffs2_fragtree_insert(%p; %d-%d, %p)\n", newfrag, - newfrag->ofs, newfrag->ofs+newfrag->size, base)); + JFFS2_DBG_FRAGTREE2("insert frag (0x%04x-0x%04x)\n", newfrag->ofs, newfrag->ofs + newfrag->size); while (*link) { parent = *link; base = rb_entry(parent, struct jffs2_node_frag, rb); - D2(printk(KERN_DEBUG "fragtree_insert considering frag at 0x%x\n", base->ofs)); + JFFS2_DBG_FRAGTREE2("considering frag at 0x%08x\n", base->ofs); if (newfrag->ofs > base->ofs) link = &base->rb.rb_right; else if (newfrag->ofs < base->ofs) link = &base->rb.rb_left; else { - printk(KERN_CRIT "Duplicate frag at %08x (%p,%p)\n", newfrag->ofs, newfrag, base); + JFFS2_ERROR("duplicate frag at %08x (%p,%p)\n", newfrag->ofs, newfrag, base); BUG(); } } @@ -112,11 +106,11 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *l this = jffs2_lookup_node_frag(list, newfrag->node->ofs); if (this) { - D2(printk(KERN_DEBUG "j_a_f_d_t_f: Lookup gave frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", - this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this)); + JFFS2_DBG_FRAGTREE2("lookup gave frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", + this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this); lastend = this->ofs + this->size; } else { - D2(printk(KERN_DEBUG "j_a_f_d_t_f: Lookup gave no frag\n")); + JFFS2_DBG_FRAGTREE2("lookup gave no frag\n"); lastend = 0; } @@ -148,10 +142,10 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *l /* By definition, the 'this' node has no right-hand child, because there are no frags with offset greater than it. So that's where we want to put the hole */ - D2(printk(KERN_DEBUG "Adding hole frag (%p) on right of node at (%p)\n", holefrag, this)); + JFFS2_DBG_FRAGTREE2("adding hole frag (%p) on right of node at (%p)\n", holefrag, this); rb_link_node(&holefrag->rb, &this->rb, &this->rb.rb_right); } else { - D2(printk(KERN_DEBUG "Adding hole frag (%p) at root of tree\n", holefrag)); + JFFS2_DBG_FRAGTREE2("adding hole frag (%p) at root of tree\n", holefrag); rb_link_node(&holefrag->rb, NULL, &list->rb_node); } rb_insert_color(&holefrag->rb, list); @@ -161,18 +155,18 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *l /* By definition, the 'this' node has no right-hand child, because there are no frags with offset greater than it. So that's where we want to put new fragment */ - D2(printk(KERN_DEBUG "Adding new frag (%p) on right of node at (%p)\n", newfrag, this)); + JFFS2_DBG_FRAGTREE2("adding new frag (%p) on right of node at (%p)\n", newfrag, this); rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); } else { - D2(printk(KERN_DEBUG "Adding new frag (%p) at root of tree\n", newfrag)); + JFFS2_DBG_FRAGTREE2("adding new frag (%p) at root of tree\n", newfrag); rb_link_node(&newfrag->rb, NULL, &list->rb_node); } rb_insert_color(&newfrag->rb, list); return 0; } - D2(printk(KERN_DEBUG "j_a_f_d_t_f: dealing with frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", - this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this)); + JFFS2_DBG_FRAGTREE2("dealing with frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", + this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this); /* OK. 'this' is pointing at the first frag that newfrag->ofs at least partially obsoletes, * - i.e. newfrag->ofs < this->ofs+this->size && newfrag->ofs >= this->ofs @@ -193,12 +187,12 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *l jffs2_free_node_frag(newfrag); return -ENOMEM; } - D2(printk(KERN_DEBUG "split old frag 0x%04x-0x%04x -->", this->ofs, this->ofs+this->size); if (this->node) - printk("phys 0x%08x\n", ref_offset(this->node->raw)); + JFFS2_DBG_FRAGTREE2("split old frag 0x%04x-0x%04x, phys 0x%08x\n", + this->ofs, this->ofs+this->size, ref_offset(this->node->raw)); else - printk("hole\n"); - ) + JFFS2_DBG_FRAGTREE2("split old hole frag 0x%04x-0x%04x\n", + this->ofs, this->ofs+this->size, ref_offset(this->node->raw)); /* New second frag pointing to this's node */ newfrag2->ofs = newfrag->ofs + newfrag->size; @@ -233,14 +227,13 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *l } else { /* New frag starts at the same point as 'this' used to. Replace it in the tree without doing a delete and insertion */ - D2(printk(KERN_DEBUG "Inserting newfrag (*%p),%d-%d in before 'this' (*%p),%d-%d\n", - newfrag, newfrag->ofs, newfrag->ofs+newfrag->size, - this, this->ofs, this->ofs+this->size)); + JFFS2_DBG_FRAGTREE2("inserting newfrag (*%p),%d-%d in before 'this' (*%p),%d-%d\n", + newfrag, newfrag->ofs, newfrag->ofs+newfrag->size, this, this->ofs, this->ofs+this->size); rb_replace_node(&this->rb, &newfrag->rb, list); if (newfrag->ofs + newfrag->size >= this->ofs+this->size) { - D2(printk(KERN_DEBUG "Obsoleting node frag %p (%x-%x)\n", this, this->ofs, this->ofs+this->size)); + JFFS2_DBG_FRAGTREE2("obsoleting node frag %p (%x-%x)\n", this, this->ofs, this->ofs+this->size); jffs2_obsolete_node_frag(c, this); } else { this->ofs += newfrag->size; @@ -256,7 +249,8 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *l */ while ((this = frag_next(newfrag)) && newfrag->ofs + newfrag->size >= this->ofs + this->size) { /* 'this' frag is obsoleted completely. */ - D2(printk(KERN_DEBUG "Obsoleting node frag %p (%x-%x) and removing from tree\n", this, this->ofs, this->ofs+this->size)); + JFFS2_DBG_FRAGTREE2("obsoleting node frag %p (%x-%x) and removing from tree\n", + this, this->ofs, this->ofs+this->size); rb_erase(&this->rb, list); jffs2_obsolete_node_frag(c, this); } @@ -286,8 +280,6 @@ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_in int ret; struct jffs2_node_frag *newfrag; - D1(printk(KERN_DEBUG "jffs2_add_full_dnode_to_inode(ino #%u, f %p, fn %p)\n", f->inocache->ino, f, fn)); - if (unlikely(!fn->size)) return 0; @@ -295,8 +287,8 @@ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_in if (unlikely(!newfrag)) return -ENOMEM; - D2(printk(KERN_DEBUG "adding node %04x-%04x @0x%08x on flash, newfrag *%p\n", - fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag)); + JFFS2_DBG_FRAGTREE("adding node %#04x-%#04x @0x%08x on flash, newfrag *%p\n", + fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag); newfrag->ofs = fn->ofs; newfrag->size = fn->size; @@ -350,8 +342,6 @@ struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t { struct jffs2_inode_cache *ret; - D2(printk(KERN_DEBUG "jffs2_get_ino_cache(): ino %u\n", ino)); - ret = c->inocache_list[ino % INOCACHE_HASHSIZE]; while (ret && ret->ino < ino) { ret = ret->next; @@ -360,7 +350,6 @@ struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t if (ret && ret->ino != ino) ret = NULL; - D2(printk(KERN_DEBUG "jffs2_get_ino_cache found %p for ino %u\n", ret, ino)); return ret; } @@ -372,7 +361,7 @@ void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new if (!new->ino) new->ino = ++c->highest_ino; - D2(printk(KERN_DEBUG "jffs2_add_ino_cache: Add %p (ino #%u)\n", new, new->ino)); + JFFS2_DBG_INOCACHE("add %p (ino #%u)\n", new, new->ino); prev = &c->inocache_list[new->ino % INOCACHE_HASHSIZE]; @@ -388,7 +377,8 @@ 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) { struct jffs2_inode_cache **prev; - D1(printk(KERN_DEBUG "jffs2_del_ino_cache: Del %p (ino #%u)\n", old, old->ino)); + + JFFS2_DBG_INOCACHE("del %p (ino #%u)\n", old, old->ino); spin_lock(&c->inocache_lock); prev = &c->inocache_list[old->ino % INOCACHE_HASHSIZE]; @@ -451,29 +441,29 @@ struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_ struct jffs2_node_frag *prev = NULL; struct jffs2_node_frag *frag = NULL; - D2(printk(KERN_DEBUG "jffs2_lookup_node_frag(%p, %d)\n", fragtree, offset)); + JFFS2_DBG_FRAGTREE2("root %p, offset %d\n", fragtree, offset); next = fragtree->rb_node; while(next) { frag = rb_entry(next, struct jffs2_node_frag, rb); - D2(printk(KERN_DEBUG "Considering frag %d-%d (%p). left %p, right %p\n", - frag->ofs, frag->ofs+frag->size, frag, frag->rb.rb_left, frag->rb.rb_right)); + JFFS2_DBG_FRAGTREE2("considering frag %#04x-%#04x (%p). left %p, right %p\n", + frag->ofs, frag->ofs+frag->size, frag, frag->rb.rb_left, frag->rb.rb_right); if (frag->ofs + frag->size <= offset) { - D2(printk(KERN_DEBUG "Going right from frag %d-%d, before the region we care about\n", - frag->ofs, frag->ofs+frag->size)); + JFFS2_DBG_FRAGTREE2("going right from frag %#04x-%#04x, before the region we care about\n", + frag->ofs, frag->ofs+frag->size); /* Remember the closest smaller match on the way down */ if (!prev || frag->ofs > prev->ofs) prev = frag; next = frag->rb.rb_right; } else if (frag->ofs > offset) { - D2(printk(KERN_DEBUG "Going left from frag %d-%d, after the region we care about\n", - frag->ofs, frag->ofs+frag->size)); + JFFS2_DBG_FRAGTREE2("going left from frag %#04x-%#04x, after the region we care about\n", + frag->ofs, frag->ofs+frag->size); next = frag->rb.rb_left; } else { - D2(printk(KERN_DEBUG "Returning frag %d,%d, matched\n", - frag->ofs, frag->ofs+frag->size)); + JFFS2_DBG_FRAGTREE2("returning frag %#04x-%#04x, matched\n", + frag->ofs, frag->ofs+frag->size); return frag; } } @@ -482,10 +472,10 @@ struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_ and return the closest smaller one */ if (prev) - D2(printk(KERN_DEBUG "No match. Returning frag %d,%d, closest previous\n", - prev->ofs, prev->ofs+prev->size)); + JFFS2_DBG_FRAGTREE2("no match. Returning frag %#04x-%#04x, closest previous\n", + prev->ofs, prev->ofs+prev->size); else - D2(printk(KERN_DEBUG "Returning NULL, empty fragtree\n")); + JFFS2_DBG_FRAGTREE2("returning NULL, empty fragtree\n"); return prev; } @@ -500,25 +490,25 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) if (!root->rb_node) return; + JFFS2_DBG_FRAGTREE("killing\n"); + frag = (rb_entry(root->rb_node, struct jffs2_node_frag, rb)); - while(frag) { if (frag->rb.rb_left) { - D2(printk(KERN_DEBUG "Going left from frag (%p) %d-%d\n", - frag, frag->ofs, frag->ofs+frag->size)); + JFFS2_DBG_FRAGTREE2("going left from frag (%p) %#04x-%#04x\n", + frag, frag->ofs, frag->ofs+frag->size); frag = frag_left(frag); continue; } if (frag->rb.rb_right) { - D2(printk(KERN_DEBUG "Going right from frag (%p) %d-%d\n", - frag, frag->ofs, frag->ofs+frag->size)); + JFFS2_DBG_FRAGTREE2("going right from frag (%p) %#04x-%#04x\n", + frag, frag->ofs, frag->ofs+frag->size); frag = frag_right(frag); continue; } - D2(printk(KERN_DEBUG "jffs2_kill_fragtree: frag at 0x%x-0x%x: node %p, frags %d--\n", - frag->ofs, frag->ofs+frag->size, frag->node, - frag->node?frag->node->frags:0)); + JFFS2_DBG_FRAGTREE2("frag %#04x-%#04x: node %p, frags %d\n", + frag->ofs, frag->ofs+frag->size, frag->node, frag->node?frag->node->frags:0); if (frag->node && !(--frag->node->frags)) { /* Not a hole, and it's the final remaining frag diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 85a285b2a30..67732ba08c3 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.131 2005/07/27 14:46:11 dedekind Exp $ + * $Id: readinode.c,v 1.132 2005/07/28 14:46:40 dedekind Exp $ * */ @@ -24,12 +24,12 @@ void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uin { struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size); - D1(printk(KERN_DEBUG "Truncating fraglist to 0x%08x bytes\n", size)); + JFFS2_DBG_FRAGTREE("truncating fragtree to 0x%08x bytes\n", size); /* We know frag->ofs <= size. That's what lookup does for us */ if (frag && frag->ofs != size) { if (frag->ofs+frag->size >= size) { - D1(printk(KERN_DEBUG "Truncating frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size)); + JFFS2_DBG_FRAGTREE2("truncating frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size); frag->size = size - frag->ofs; } frag = frag_next(frag); @@ -37,7 +37,7 @@ void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uin while (frag && frag->ofs >= size) { struct jffs2_node_frag *next = frag_next(frag); - D1(printk(KERN_DEBUG "Removing frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size)); + JFFS2_DBG_FRAGTREE("removing frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size); frag_erase(frag, list); jffs2_obsolete_node_frag(c, frag); frag = next; @@ -120,7 +120,7 @@ static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_r while (ref && ref->next_in_ino) { if (!ref_obsolete(ref)) return ref; - D1(printk(KERN_DEBUG "node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref))); + JFFS2_DBG_NODEREF("node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref)); ref = ref->next_in_ino; } return NULL; @@ -152,7 +152,7 @@ read_direntry(struct jffs2_sb_info *c, /* Sanity check */ if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) { - printk(KERN_ERR "Error! Illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n", + JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n", ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen)); return 1; } @@ -192,7 +192,7 @@ read_direntry(struct jffs2_sb_info *c, return -EIO; if (unlikely(err)) { - printk(KERN_WARNING "Read remainder of name: error %d\n", err); + JFFS2_ERROR("read remainder of name: error %d\n", err); jffs2_free_full_dirent(fd); return -EIO; } @@ -206,8 +206,6 @@ read_direntry(struct jffs2_sb_info *c, * Wheee. We now have a complete jffs2_full_dirent structure, with * the name in it and everything. Link it into the list */ - D1(printk(KERN_DEBUG "Adding fd \"%s\", ino #%u\n", fd->name, fd->ino)); - jffs2_add_fd_to_list(c, fd, fdp); return 0; @@ -242,7 +240,7 @@ read_dnode(struct jffs2_sb_info *c, crc = crc32(0, rd, sizeof(*rd) - 8); if (unlikely(crc != je32_to_cpu(rd->node_crc))) { - printk(KERN_WARNING "Header CRC failed on node at %#08x: read %#08x, calculated %#08x\n", + JFFS2_NOTICE("header CRC failed on node at %#08x: read %#08x, calculated %#08x\n", ref_offset(ref), je32_to_cpu(rd->node_crc), crc); return 1; } @@ -250,11 +248,8 @@ read_dnode(struct jffs2_sb_info *c, /* Sanity checks */ if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) || unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) { - printk(KERN_WARNING "Inode corrupted at %#08x, totlen %d, #ino %d, version %d, " - "isize %d, csize %d, dsize %d \n", - ref_offset(ref), je32_to_cpu(rd->totlen), je32_to_cpu(rd->ino), - je32_to_cpu(rd->version), je32_to_cpu(rd->isize), - je32_to_cpu(rd->csize), je32_to_cpu(rd->dsize)); + JFFS2_WARNING("inode node header CRC is corrupted at %#08x\n", ref_offset(ref)); + __jffs2_dbg_dump_node(c, ref_offset(ref)); return 1; } @@ -267,11 +262,11 @@ read_dnode(struct jffs2_sb_info *c, err = c->mtd->point (c->mtd, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize), &read, &buf); if (unlikely(read < je32_to_cpu(rd->csize)) && likely(!err)) { - D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", read)); + JFFS2_ERROR("MTD point returned len too short: 0x%zx\n", read); c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize)); } else if (unlikely(err)){ - D1(printk(KERN_DEBUG "MTD point failed %d\n", err)); + JFFS2_ERROR("MTD point failed %d\n", err); } else pointed = 1; /* succefully pointed to device */ } @@ -299,8 +294,8 @@ read_dnode(struct jffs2_sb_info *c, #endif if (crc != je32_to_cpu(rd->data_crc)) { - printk(KERN_NOTICE "Data CRC failed on node at %#08x: read %#08x, calculated %#08x\n", - ref_offset(ref), je32_to_cpu(rd->data_crc), crc); + JFFS2_NOTICE("data CRC failed on node at %#08x: read %#08x, calculated %#08x\n", + ref_offset(ref), je32_to_cpu(rd->data_crc), crc); return 1; } @@ -326,10 +321,10 @@ read_dnode(struct jffs2_sb_info *c, if ((je32_to_cpu(rd->dsize) >= PAGE_CACHE_SIZE) || ( ((je32_to_cpu(rd->offset) & (PAGE_CACHE_SIZE-1))==0) && (je32_to_cpu(rd->dsize) + je32_to_cpu(rd->offset) == je32_to_cpu(rd->isize)))) { - D1(printk(KERN_DEBUG "Marking node at %#08x REF_PRISTINE\n", ref_offset(ref))); + JFFS2_DBG_READINODE("marking node at %#08x REF_PRISTINE\n", ref_offset(ref)); ref->flash_offset = ref_offset(ref) | REF_PRISTINE; } else { - D1(printk(KERN_DEBUG "Marking node at %#08x REF_NORMAL\n", ref_offset(ref))); + JFFS2_DBG_READINODE("marking node at %#08x REF_NORMAL\n", ref_offset(ref)); ref->flash_offset = ref_offset(ref) | REF_NORMAL; } spin_unlock(&c->erase_completion_lock); @@ -337,13 +332,13 @@ read_dnode(struct jffs2_sb_info *c, tn = jffs2_alloc_tmp_dnode_info(); if (!tn) { - D1(printk(KERN_DEBUG "alloc tn failed\n")); + JFFS2_ERROR("alloc tn failed\n"); return -ENOMEM; } tn->fn = jffs2_alloc_full_dnode(); if (!tn->fn) { - D1(printk(KERN_DEBUG "alloc fn failed\n")); + JFFS2_ERROR("alloc fn failed\n"); jffs2_free_tmp_dnode_info(tn); return -ENOMEM; } @@ -359,9 +354,8 @@ read_dnode(struct jffs2_sb_info *c, else // normal case... tn->fn->size = je32_to_cpu(rd->dsize); - D1(printk(KERN_DEBUG "dnode @%08x: ver %u, offset %#04x, dsize %#04x\n", - ref_offset(ref), je32_to_cpu(rd->version), - je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize))); + JFFS2_DBG_READINODE("dnode @%08x: ver %u, offset %#04x, dsize %#04x\n", + ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize)); jffs2_add_tn_to_tree(tn, tnp); @@ -388,37 +382,33 @@ read_unknown(struct jffs2_sb_info *c, un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype)); if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) { - /* Hmmm. This should have been caught at scan time. */ - printk(KERN_WARNING "Warning! Node header CRC failed at %#08x. " - "But it must have been OK earlier.\n", ref_offset(ref)); - D1(printk(KERN_DEBUG "Node was: { %#04x, %#04x, %#08x, %#08x }\n", - je16_to_cpu(un->magic), je16_to_cpu(un->nodetype), - je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc))); + JFFS2_NOTICE("node header CRC failed at %#08x. But it must have been OK earlier.\n", ref_offset(ref)); + __jffs2_dbg_dump_node(c, ref_offset(ref)); return 1; } else { switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) { case JFFS2_FEATURE_INCOMPAT: - printk(KERN_NOTICE "Unknown INCOMPAT nodetype %#04X at %#08x\n", - je16_to_cpu(un->nodetype), ref_offset(ref)); + JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n", + je16_to_cpu(un->nodetype), ref_offset(ref)); /* EEP */ BUG(); break; case JFFS2_FEATURE_ROCOMPAT: - printk(KERN_NOTICE "Unknown ROCOMPAT nodetype %#04X at %#08x\n", + JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n", je16_to_cpu(un->nodetype), ref_offset(ref)); BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO)); break; case JFFS2_FEATURE_RWCOMPAT_COPY: - printk(KERN_NOTICE "Unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n", + JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n", je16_to_cpu(un->nodetype), ref_offset(ref)); break; case JFFS2_FEATURE_RWCOMPAT_DELETE: - printk(KERN_NOTICE "Unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n", + JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n", je16_to_cpu(un->nodetype), ref_offset(ref)); return 1; } @@ -444,14 +434,14 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf *mctime_ver = 0; - D1(printk(KERN_DEBUG "jffs2_get_inode_nodes(): ino #%u\n", f->inocache->ino)); + JFFS2_DBG_READINODE("ino #%u\n", f->inocache->ino); spin_lock(&c->erase_completion_lock); valid_ref = jffs2_first_valid_node(f->inocache->nodes); if (!valid_ref && (f->inocache->ino != 1)) - printk(KERN_WARNING "Eep. No valid nodes for ino #%u\n", f->inocache->ino); + JFFS2_WARNING("no valid nodes for ino #%u\n", f->inocache->ino); while (valid_ref) { /* We can hold a pointer to a non-obsolete node without the spinlock, @@ -471,17 +461,17 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf min_t(uint32_t, ref_totlen(c, NULL, ref), sizeof(node)), &retlen, (void *)&node); if (err) { - printk(KERN_WARNING "error %d reading node at 0x%08x in get_inode_nodes()\n", err, ref_offset(ref)); + JFFS2_ERROR("error %d reading node at 0x%08x in get_inode_nodes()\n", err, ref_offset(ref)); goto free_out; } switch (je16_to_cpu(node.u.nodetype)) { case JFFS2_NODETYPE_DIRENT: - D1(printk(KERN_DEBUG "Node at %08x (%d) is a dirent node\n", ref_offset(ref), ref_flags(ref))); + JFFS2_DBG_READINODE("node at %08x (%d) is a dirent node\n", ref_offset(ref), ref_flags(ref)); if (retlen < sizeof(node.d)) { - printk(KERN_WARNING "Warning! Short read dirent at %#08x\n", ref_offset(ref)); + JFFS2_ERROR("short read dirent at %#08x\n", ref_offset(ref)); err = -EIO; goto free_out; } @@ -499,10 +489,10 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf break; case JFFS2_NODETYPE_INODE: - D1(printk(KERN_DEBUG "Node at %08x (%d) is a data node\n", ref_offset(ref), ref_flags(ref))); + JFFS2_DBG_READINODE("node at %08x (%d) is a data node\n", ref_offset(ref), ref_flags(ref)); if (retlen < sizeof(node.i)) { - printk(KERN_WARNING "Warning! Short read dnode at %#08x\n", ref_offset(ref)); + JFFS2_ERROR("short read dnode at %#08x\n", ref_offset(ref)); err = -EIO; goto free_out; } @@ -517,16 +507,15 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf if (je32_to_cpu(node.i.version) > *highest_version) *highest_version = je32_to_cpu(node.i.version); - D1(printk(KERN_DEBUG "version %d, highest_version now %d\n", - je32_to_cpu(node.i.version), *highest_version)); + JFFS2_DBG_READINODE("version %d, highest_version now %d\n", + je32_to_cpu(node.i.version), *highest_version); break; default: /* Check we've managed to read at least the common node header */ if (retlen < sizeof(struct jffs2_unknown_node)) { - printk(KERN_WARNING "Warning! Short read unknown node at %#08x\n", - ref_offset(ref)); + JFFS2_ERROR("short read unknown node at %#08x\n", ref_offset(ref)); return -EIO; } @@ -568,13 +557,13 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, size_t retlen; int ret; - D1(printk(KERN_DEBUG "jffs2_do_read_inode_internal(): ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink)); + JFFS2_DBG_READINODE("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink); /* Grab all nodes relevant to this ino */ ret = jffs2_get_inode_nodes(c, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver); if (ret) { - printk(KERN_CRIT "jffs2_get_inode_nodes() for ino %u returned %d\n", f->inocache->ino, ret); + JFFS2_ERROR("cannot read nodes for ino %u, returned error is %d\n", f->inocache->ino, ret); if (f->inocache->state == INO_STATE_READING) jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); return ret; @@ -589,7 +578,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, if (f->metadata) { if (likely(tn->version >= mdata_ver)) { - D1(printk(KERN_DEBUG "Obsoleting old metadata at 0x%08x\n", ref_offset(f->metadata->raw))); + JFFS2_DBG_READINODE("obsoleting old metadata at 0x%08x\n", ref_offset(f->metadata->raw)); jffs2_mark_node_obsolete(c, f->metadata->raw); jffs2_free_full_dnode(f->metadata); f->metadata = NULL; @@ -597,7 +586,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, mdata_ver = 0; } else { /* This should never happen. */ - printk(KERN_WARNING "Er. New metadata at 0x%08x with ver %d is actually older than previous ver %d at 0x%08x\n", + JFFS2_ERROR("Er. New metadata at 0x%08x with ver %d is actually older than previous ver %d at 0x%08x\n", ref_offset(fn->raw), tn->version, mdata_ver, ref_offset(f->metadata->raw)); jffs2_mark_node_obsolete(c, fn->raw); jffs2_free_full_dnode(fn); @@ -611,7 +600,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, jffs2_add_full_dnode_to_inode(c, f, fn); } else { /* Zero-sized node at end of version list. Just a metadata update */ - D1(printk(KERN_DEBUG "metadata @%08x: ver %d\n", ref_offset(fn->raw), tn->version)); + JFFS2_DBG_READINODE("metadata @%08x: ver %d\n", ref_offset(fn->raw), tn->version); f->metadata = fn; mdata_ver = tn->version; } @@ -646,13 +635,13 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, if (!fn) { /* No data nodes for this inode. */ if (f->inocache->ino != 1) { - printk(KERN_WARNING "jffs2_do_read_inode(): No data nodes found for ino #%u\n", f->inocache->ino); + JFFS2_WARNING("no data nodes found for ino #%u\n", f->inocache->ino); if (!fd_list) { if (f->inocache->state == INO_STATE_READING) jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); return -EIO; } - printk(KERN_WARNING "jffs2_do_read_inode(): But it has children so we fake some modes for it\n"); + JFFS2_NOTICE("but it has children so we fake some modes for it\n"); } latest_node->mode = cpu_to_jemode(S_IFDIR|S_IRUGO|S_IWUSR|S_IXUGO); latest_node->version = cpu_to_je32(0); @@ -667,8 +656,8 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(*latest_node), &retlen, (void *)latest_node); if (ret || retlen != sizeof(*latest_node)) { - printk(KERN_NOTICE "MTD read in jffs2_do_read_inode() failed: Returned %d, %zd of %zd bytes read\n", - ret, retlen, sizeof(*latest_node)); + JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n", + ret, retlen, sizeof(*latest_node)); /* FIXME: If this fails, there seems to be a memory leak. Find it. */ up(&f->sem); jffs2_do_clear_inode(c, f); @@ -677,7 +666,8 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, crc = crc32(0, latest_node, sizeof(*latest_node)-8); if (crc != je32_to_cpu(latest_node->node_crc)) { - printk(KERN_NOTICE "CRC failed for read_inode of inode %u at physical location 0x%x\n", f->inocache->ino, ref_offset(fn->raw)); + JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n", + f->inocache->ino, ref_offset(fn->raw)); up(&f->sem); jffs2_do_clear_inode(c, f); return -EIO; @@ -712,9 +702,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, * operation. */ f->target = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL); if (!f->target) { - printk(KERN_WARNING "Can't allocate %d bytes of memory " - "for the symlink target path cache\n", - je32_to_cpu(latest_node->csize)); + JFFS2_ERROR("can't allocate %d bytes of memory for the symlink target path cache\n", je32_to_cpu(latest_node->csize)); up(&f->sem); jffs2_do_clear_inode(c, f); return -ENOMEM; @@ -734,8 +722,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, } f->target[je32_to_cpu(latest_node->csize)] = '\0'; - D1(printk(KERN_DEBUG "jffs2_do_read_inode(): symlink's target '%s' cached\n", - f->target)); + JFFS2_DBG_READINODE("symlink's target '%s' cached\n", f->target); } /* fall through... */ @@ -745,14 +732,14 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, /* Certain inode types should have only one data node, and it's kept as the metadata node */ if (f->metadata) { - printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o had metadata node\n", + JFFS2_ERROR("Argh. Special inode #%u with mode 0%o had metadata node\n", f->inocache->ino, jemode_to_cpu(latest_node->mode)); up(&f->sem); jffs2_do_clear_inode(c, f); return -EIO; } if (!frag_first(&f->fragtree)) { - printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o has no fragments\n", + JFFS2_ERROR("Argh. Special inode #%u with mode 0%o has no fragments\n", f->inocache->ino, jemode_to_cpu(latest_node->mode)); up(&f->sem); jffs2_do_clear_inode(c, f); @@ -760,7 +747,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, } /* ASSERT: f->fraglist != NULL */ if (frag_next(frag_first(&f->fragtree))) { - printk(KERN_WARNING "Argh. Special inode #%u with mode 0x%x had more than one node\n", + JFFS2_ERROR("Argh. Special inode #%u with mode 0x%x had more than one node\n", f->inocache->ino, jemode_to_cpu(latest_node->mode)); /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */ up(&f->sem); @@ -783,14 +770,12 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t ino, struct jffs2_raw_inode *latest_node) { - D2(printk(KERN_DEBUG "jffs2_do_read_inode(): getting inocache\n")); + JFFS2_DBG_READINODE("read inode #%u\n", ino); retry_inocache: spin_lock(&c->inocache_lock); f->inocache = jffs2_get_ino_cache(c, ino); - D2(printk(KERN_DEBUG "jffs2_do_read_inode(): Got inocache at %p\n", f->inocache)); - if (f->inocache) { /* Check its state. We may need to wait before we can use it */ switch(f->inocache->state) { @@ -804,8 +789,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, /* If it's in either of these states, we need to wait for whoever's got it to finish and put it back. */ - D1(printk(KERN_DEBUG "jffs2_get_ino_cache_read waiting for ino #%u in state %d\n", - ino, f->inocache->state)); + JFFS2_DBG_READINODE("waiting for ino #%u in state %d\n", ino, f->inocache->state); sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); goto retry_inocache; @@ -814,7 +798,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, /* Eep. This should never happen. It can happen if Linux calls read_inode() again before clear_inode() has finished though. */ - printk(KERN_WARNING "Eep. Trying to read_inode #%u when it's already in state %d!\n", ino, f->inocache->state); + JFFS2_ERROR("Eep. Trying to read_inode #%u when it's already in state %d!\n", ino, f->inocache->state); /* Fail. That's probably better than allowing it to succeed */ f->inocache = NULL; break; @@ -829,10 +813,10 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, /* Special case - no root inode on medium */ f->inocache = jffs2_alloc_inode_cache(); if (!f->inocache) { - printk(KERN_CRIT "jffs2_do_read_inode(): Cannot allocate inocache for root inode\n"); + JFFS2_ERROR("cannot allocate inocache for root inode\n"); return -ENOMEM; } - D1(printk(KERN_DEBUG "jffs2_do_read_inode(): Creating inocache for root inode\n")); + JFFS2_DBG_READINODE("creating inocache for root inode\n"); memset(f->inocache, 0, sizeof(struct jffs2_inode_cache)); f->inocache->ino = f->inocache->nlink = 1; f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; @@ -840,7 +824,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, jffs2_add_ino_cache(c, f->inocache); } if (!f->inocache) { - printk(KERN_WARNING "jffs2_do_read_inode() on nonexistent ino %u\n", ino); + JFFS2_ERROR("requestied to read an nonexistent ino %u\n", ino); return -ENOENT; } -- cgit v1.2.3 From 737b7661e059680a68afb3df0a088fd976f666b7 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 30 Jul 2005 16:29:30 +0100 Subject: [JFFS2] Fix up new debug code for eCos build The debug code cleanup broke the eCos build. Signed-off-by: Andrew Lunn Signed-off-by: Thomas Gleixner --- fs/jffs2/build.c | 16 ++++++++++------ fs/jffs2/debug.c | 3 ++- fs/jffs2/readinode.c | 7 ++++--- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index f08984a64a5..8e2f1f4e8aa 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: build.c,v 1.75 2005/07/22 10:32:07 dedekind Exp $ + * $Id: build.c,v 1.76 2005/07/30 15:29:27 lunn Exp $ * */ @@ -317,9 +317,11 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) c->free_size = c->flash_size; c->nr_blocks = c->flash_size / c->sector_size; +#ifndef __ECOS if (c->mtd->flags & MTD_NO_VIRTBLOCKS) c->blocks = vmalloc(sizeof(struct jffs2_eraseblock) * c->nr_blocks); else +#endif c->blocks = kmalloc(sizeof(struct jffs2_eraseblock) * c->nr_blocks, GFP_KERNEL); if (!c->blocks) return -ENOMEM; @@ -353,11 +355,13 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) D1(printk(KERN_DEBUG "build_fs failed\n")); jffs2_free_ino_caches(c); jffs2_free_raw_node_refs(c); - if (c->mtd->flags & MTD_NO_VIRTBLOCKS) { - vfree(c->blocks); - } else { - kfree(c->blocks); - } +#ifndef __ECOS + if (c->mtd->flags & MTD_NO_VIRTBLOCKS) + vfree(c->blocks); + else +#endif + kfree(c->blocks); + return -EIO; } diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c index fb88eb19711..80ac9b6514b 100644 --- a/fs/jffs2/debug.c +++ b/fs/jffs2/debug.c @@ -7,10 +7,11 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.c,v 1.7 2005/07/24 15:14:14 dedekind Exp $ + * $Id: debug.c,v 1.8 2005/07/30 15:27:05 lunn Exp $ * */ #include +#include #include #include #include diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 67732ba08c3..8c6665d0e33 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,11 +7,12 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.132 2005/07/28 14:46:40 dedekind Exp $ + * $Id: readinode.c,v 1.133 2005/07/30 15:28:24 lunn Exp $ * */ #include +#include #include #include #include @@ -249,7 +250,7 @@ read_dnode(struct jffs2_sb_info *c, if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) || unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) { JFFS2_WARNING("inode node header CRC is corrupted at %#08x\n", ref_offset(ref)); - __jffs2_dbg_dump_node(c, ref_offset(ref)); + jffs2_dbg_dump_node(c, ref_offset(ref)); return 1; } @@ -384,7 +385,7 @@ read_unknown(struct jffs2_sb_info *c, if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) { /* Hmmm. This should have been caught at scan time. */ JFFS2_NOTICE("node header CRC failed at %#08x. But it must have been OK earlier.\n", ref_offset(ref)); - __jffs2_dbg_dump_node(c, ref_offset(ref)); + jffs2_dbg_dump_node(c, ref_offset(ref)); return 1; } else { switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) { -- cgit v1.2.3 From 1e900979a7e6c2abbfd1b86bffd226d2d6115f66 Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Sun, 31 Jul 2005 09:20:48 +0100 Subject: [JFFS2] Move another fragtree-related function to nodelist.c Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/nodelist.c | 26 +++++++++++++++++++++++++- fs/jffs2/nodelist.h | 4 ++-- fs/jffs2/readinode.c | 26 +------------------------- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 7997f526c94..0cf5e6f1198 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.c,v 1.102 2005/07/28 12:45:10 dedekind Exp $ + * $Id: nodelist.c,v 1.103 2005/07/31 08:20:44 dedekind Exp $ * */ @@ -51,6 +51,30 @@ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new *prev = new; } +void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint32_t size) +{ + struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size); + + JFFS2_DBG_FRAGTREE("truncating fragtree to 0x%08x bytes\n", size); + + /* We know frag->ofs <= size. That's what lookup does for us */ + if (frag && frag->ofs != size) { + if (frag->ofs+frag->size >= size) { + JFFS2_DBG_FRAGTREE2("truncating frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size); + frag->size = size - frag->ofs; + } + frag = frag_next(frag); + } + while (frag && frag->ofs >= size) { + struct jffs2_node_frag *next = frag_next(frag); + + JFFS2_DBG_FRAGTREE("removing frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size); + frag_erase(frag, list); + jffs2_obsolete_node_frag(c, frag); + frag = next; + } +} + void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this) { if (this->node) { diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 452fc81f391..53c12e4a337 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.h,v 1.135 2005/07/27 14:46:11 dedekind Exp $ + * $Id: nodelist.h,v 1.136 2005/07/31 08:20:44 dedekind Exp $ * */ @@ -310,6 +310,7 @@ struct rb_node *rb_prev(struct rb_node *); void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root); void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this); int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); +void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); /* nodemgmt.c */ int jffs2_thread_should_wake(struct jffs2_sb_info *c); @@ -333,7 +334,6 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint /* readinode.c */ -void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t ino, struct jffs2_raw_inode *latest_node); int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 8c6665d0e33..f3b12d7fe9a 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.133 2005/07/30 15:28:24 lunn Exp $ + * $Id: readinode.c,v 1.134 2005/07/31 08:20:44 dedekind Exp $ * */ @@ -21,30 +21,6 @@ #include #include "nodelist.h" -void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size) -{ - struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size); - - JFFS2_DBG_FRAGTREE("truncating fragtree to 0x%08x bytes\n", size); - - /* We know frag->ofs <= size. That's what lookup does for us */ - if (frag && frag->ofs != size) { - if (frag->ofs+frag->size >= size) { - JFFS2_DBG_FRAGTREE2("truncating frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size); - frag->size = size - frag->ofs; - } - frag = frag_next(frag); - } - while (frag && frag->ofs >= size) { - struct jffs2_node_frag *next = frag_next(frag); - - JFFS2_DBG_FRAGTREE("removing frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size); - frag_erase(frag, list); - jffs2_obsolete_node_frag(c, frag); - frag = next; - } -} - /* * Put a new tmp_dnode_info into the temporaty RB-tree, keeping the list in * order of increasing version. -- cgit v1.2.3 From e0e3006f79a6d995c9a7de7556f11a9b97536423 Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Sun, 31 Jul 2005 10:08:41 +0100 Subject: [JFFS2] Refine fragtree debug macros Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/debug.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index 4d785971201..2112bab514c 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.h,v 1.7 2005/07/27 13:06:56 dedekind Exp $ + * $Id: debug.h,v 1.8 2005/07/31 09:08:38 dedekind Exp $ * */ #ifndef _JFFS2_DEBUG_H_ @@ -106,6 +106,11 @@ #else #define JFFS2_DBG_FRAGTREE(fmt, ...) #endif +#ifdef JFFS2_DBG_FRAGTREE2_MESSAGES +#define JFFS2_DBG_FRAGTREE2(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#else +#define JFFS2_DBG_FRAGTREE2(fmt, ...) +#endif /* Directory entry list manilulation debugging messages */ #ifdef JFFS2_DBG_DENTLIST_MESSAGES @@ -113,11 +118,6 @@ #else #define JFFS2_DBG_DENTLIST(fmt, ...) #endif -#ifdef JFFS2_DBG_FRAGTREE2_MESSAGES -#define JFFS2_DBG_FRAGTREE2(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) -#else -#define JFFS2_DBG_FRAGTREE2(fmt, ...) -#endif /* Print the messages about manipulating node_refs */ #ifdef JFFS2_DBG_NODEREF_MESSAGES -- cgit v1.2.3 From 1e0da3cb6cd4a909c64c870344183185bd6815b1 Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Mon, 1 Aug 2005 13:05:22 +0100 Subject: [JFFS2] Build fragtree in reverse order Instead of building fragtree starting from node with the smallest version number, start from the highest. This helps to avoid reading and checking obsolete nodes. Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/nodelist.c | 637 +++++++++++++++++++++++++++++++++++++++++++++------ fs/jffs2/nodelist.h | 9 +- fs/jffs2/readinode.c | 475 +++++++++++++++++++++++--------------- 3 files changed, 868 insertions(+), 253 deletions(-) diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 0cf5e6f1198..390ce06ab1a 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.c,v 1.103 2005/07/31 08:20:44 dedekind Exp $ + * $Id: nodelist.c,v 1.104 2005/08/01 12:05:19 dedekind Exp $ * */ @@ -59,7 +59,7 @@ void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint /* We know frag->ofs <= size. That's what lookup does for us */ if (frag && frag->ofs != size) { - if (frag->ofs+frag->size >= size) { + if (frag->ofs+frag->size > size) { JFFS2_DBG_FRAGTREE2("truncating frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size); frag->size = size - frag->ofs; } @@ -73,6 +73,20 @@ void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint jffs2_obsolete_node_frag(c, frag); frag = next; } + + if (size == 0) + return; + + /* + * If the last fragment starts at the RAM page boundary, it is + * REF_PRISTINE irrespective of its size. + */ + frag = frag_last(list); + if ((frag->ofs & (PAGE_CACHE_SIZE - 1)) == 0) { + JFFS2_DBG_FRAGTREE2("marking the last fragment 0x%08x-0x%08x REF_PRISTINE.\n", + frag->ofs, frag->ofs + frag->size); + frag->node->raw->flash_offset = ref_offset(frag->node->raw) | REF_PRISTINE; + } } void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this) @@ -120,14 +134,82 @@ static void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_ rb_link_node(&newfrag->rb, &base->rb, link); } +/* + * Allocate and initializes a new fragment. + */ +static inline struct jffs2_node_frag * new_fragment(struct jffs2_full_dnode *fn, uint32_t ofs, uint32_t size) +{ + struct jffs2_node_frag *newfrag; + + newfrag = jffs2_alloc_node_frag(); + if (likely(newfrag)) { + newfrag->ofs = ofs; + newfrag->size = size; + newfrag->node = fn; + } else { + JFFS2_ERROR("cannot allocate a jffs2_node_frag object\n"); + } + + return newfrag; +} + +/* + * Called when there is no overlapping fragment exist. Inserts a hole before the new + * fragment and inserts the new fragment to the fragtree. + */ +static int no_overlapping_node(struct jffs2_sb_info *c, struct rb_root *root, + struct jffs2_node_frag *newfrag, + struct jffs2_node_frag *this, uint32_t lastend) +{ + if (lastend < newfrag->node->ofs) { + /* put a hole in before the new fragment */ + struct jffs2_node_frag *holefrag; + + holefrag= new_fragment(NULL, lastend, newfrag->node->ofs - lastend); + if (unlikely(!holefrag)) { + jffs2_free_node_frag(newfrag); + return -ENOMEM; + } + + if (this) { + /* By definition, the 'this' node has no right-hand child, + because there are no frags with offset greater than it. + So that's where we want to put the hole */ + JFFS2_DBG_FRAGTREE2("add hole frag %u-%u on the right of the new frag.\n", + holefrag->ofs, holefrag->ofs + holefrag->size); + rb_link_node(&holefrag->rb, &this->rb, &this->rb.rb_right); + } else { + JFFS2_DBG_FRAGTREE2("Add hole frag %u-%u to the root of the tree.\n", + holefrag->ofs, holefrag->ofs + holefrag->size); + rb_link_node(&holefrag->rb, NULL, &root->rb_node); + } + rb_insert_color(&holefrag->rb, root); + this = holefrag; + } + + if (this) { + /* By definition, the 'this' node has no right-hand child, + because there are no frags with offset greater than it. + So that's where we want to put new fragment */ + JFFS2_DBG_FRAGTREE2("add the new node at the right\n"); + rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); + } else { + JFFS2_DBG_FRAGTREE2("insert the new node at the root of the tree\n"); + rb_link_node(&newfrag->rb, NULL, &root->rb_node); + } + rb_insert_color(&newfrag->rb, root); + + return 0; +} + /* Doesn't set inode->i_size */ -static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *list, struct jffs2_node_frag *newfrag) +static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *root, struct jffs2_node_frag *newfrag) { struct jffs2_node_frag *this; uint32_t lastend; /* Skip all the nodes which are completed before this one starts */ - this = jffs2_lookup_node_frag(list, newfrag->node->ofs); + this = jffs2_lookup_node_frag(root, newfrag->node->ofs); if (this) { JFFS2_DBG_FRAGTREE2("lookup gave frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", @@ -138,7 +220,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *l lastend = 0; } - /* See if we ran off the end of the list */ + /* See if we ran off the end of the fragtree */ if (lastend <= newfrag->ofs) { /* We did */ @@ -152,45 +234,16 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *l mark_ref_normal(newfrag->node->raw); } - if (lastend < newfrag->node->ofs) { - /* ... and we need to put a hole in before the new node */ - struct jffs2_node_frag *holefrag = jffs2_alloc_node_frag(); - if (!holefrag) { - jffs2_free_node_frag(newfrag); - return -ENOMEM; - } - holefrag->ofs = lastend; - holefrag->size = newfrag->node->ofs - lastend; - holefrag->node = NULL; - if (this) { - /* By definition, the 'this' node has no right-hand child, - because there are no frags with offset greater than it. - So that's where we want to put the hole */ - JFFS2_DBG_FRAGTREE2("adding hole frag (%p) on right of node at (%p)\n", holefrag, this); - rb_link_node(&holefrag->rb, &this->rb, &this->rb.rb_right); - } else { - JFFS2_DBG_FRAGTREE2("adding hole frag (%p) at root of tree\n", holefrag); - rb_link_node(&holefrag->rb, NULL, &list->rb_node); - } - rb_insert_color(&holefrag->rb, list); - this = holefrag; - } - if (this) { - /* By definition, the 'this' node has no right-hand child, - because there are no frags with offset greater than it. - So that's where we want to put new fragment */ - JFFS2_DBG_FRAGTREE2("adding new frag (%p) on right of node at (%p)\n", newfrag, this); - rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); - } else { - JFFS2_DBG_FRAGTREE2("adding new frag (%p) at root of tree\n", newfrag); - rb_link_node(&newfrag->rb, NULL, &list->rb_node); - } - rb_insert_color(&newfrag->rb, list); - return 0; + return no_overlapping_node(c, root, newfrag, this, lastend); } - JFFS2_DBG_FRAGTREE2("dealing with frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", - this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this); + if (this->node) + JFFS2_DBG_FRAGTREE2("dealing with frag %u-%u, phys %#08x(%d).\n", + this->ofs, this->ofs + this->size, + ref_offset(this->node->raw), ref_flags(this->node->raw)); + else + JFFS2_DBG_FRAGTREE2("dealing with hole frag %u-%u.\n", + this->ofs, this->ofs + this->size); /* OK. 'this' is pointing at the first frag that newfrag->ofs at least partially obsoletes, * - i.e. newfrag->ofs < this->ofs+this->size && newfrag->ofs >= this->ofs @@ -206,11 +259,8 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *l if (this->ofs + this->size > newfrag->ofs + newfrag->size) { /* The new node splits 'this' frag into two */ - struct jffs2_node_frag *newfrag2 = jffs2_alloc_node_frag(); - if (!newfrag2) { - jffs2_free_node_frag(newfrag); - return -ENOMEM; - } + struct jffs2_node_frag *newfrag2; + if (this->node) JFFS2_DBG_FRAGTREE2("split old frag 0x%04x-0x%04x, phys 0x%08x\n", this->ofs, this->ofs+this->size, ref_offset(this->node->raw)); @@ -219,9 +269,10 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *l this->ofs, this->ofs+this->size, ref_offset(this->node->raw)); /* New second frag pointing to this's node */ - newfrag2->ofs = newfrag->ofs + newfrag->size; - newfrag2->size = (this->ofs+this->size) - newfrag2->ofs; - newfrag2->node = this->node; + newfrag2 = new_fragment(this->node, newfrag->ofs + newfrag->size, + this->ofs + this->size - newfrag->ofs - newfrag->size); + if (unlikely(!newfrag2)) + return -ENOMEM; if (this->node) this->node->frags++; @@ -235,10 +286,10 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *l 'this' to insert newfrag, and a tree insert from newfrag to insert newfrag2. */ jffs2_fragtree_insert(newfrag, this); - rb_insert_color(&newfrag->rb, list); + rb_insert_color(&newfrag->rb, root); jffs2_fragtree_insert(newfrag2, newfrag); - rb_insert_color(&newfrag2->rb, list); + rb_insert_color(&newfrag2->rb, root); return 0; } @@ -247,14 +298,14 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *l /* Again, we know it lives down here in the tree */ jffs2_fragtree_insert(newfrag, this); - rb_insert_color(&newfrag->rb, list); + rb_insert_color(&newfrag->rb, root); } else { /* New frag starts at the same point as 'this' used to. Replace it in the tree without doing a delete and insertion */ JFFS2_DBG_FRAGTREE2("inserting newfrag (*%p),%d-%d in before 'this' (*%p),%d-%d\n", newfrag, newfrag->ofs, newfrag->ofs+newfrag->size, this, this->ofs, this->ofs+this->size); - rb_replace_node(&this->rb, &newfrag->rb, list); + rb_replace_node(&this->rb, &newfrag->rb, root); if (newfrag->ofs + newfrag->size >= this->ofs+this->size) { JFFS2_DBG_FRAGTREE2("obsoleting node frag %p (%x-%x)\n", this, this->ofs, this->ofs+this->size); @@ -264,7 +315,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *l this->size -= newfrag->size; jffs2_fragtree_insert(this, newfrag); - rb_insert_color(&this->rb, list); + rb_insert_color(&this->rb, root); return 0; } } @@ -275,15 +326,15 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *l /* 'this' frag is obsoleted completely. */ JFFS2_DBG_FRAGTREE2("obsoleting node frag %p (%x-%x) and removing from tree\n", this, this->ofs, this->ofs+this->size); - rb_erase(&this->rb, list); + rb_erase(&this->rb, root); jffs2_obsolete_node_frag(c, this); } /* Now we're pointing at the first frag which isn't totally obsoleted by the new frag */ - if (!this || newfrag->ofs + newfrag->size == this->ofs) { + if (!this || newfrag->ofs + newfrag->size == this->ofs) return 0; - } + /* Still some overlap but we don't need to move it in the tree */ this->size = (this->ofs + this->size) - (newfrag->ofs + newfrag->size); this->ofs = newfrag->ofs + newfrag->size; @@ -296,8 +347,9 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *l return 0; } -/* Given an inode, probably with existing list of fragments, add the new node - * to the fragment list. +/* + * Given an inode, probably with existing tree of fragments, add the new node + * to the fragment tree. */ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn) { @@ -307,18 +359,14 @@ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_in if (unlikely(!fn->size)) return 0; - newfrag = jffs2_alloc_node_frag(); + newfrag = new_fragment(fn, fn->ofs, fn->size); if (unlikely(!newfrag)) return -ENOMEM; + newfrag->node->frags = 1; JFFS2_DBG_FRAGTREE("adding node %#04x-%#04x @0x%08x on flash, newfrag *%p\n", fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag); - newfrag->ofs = fn->ofs; - newfrag->size = fn->size; - newfrag->node = fn; - newfrag->node->frags = 1; - ret = jffs2_add_frag_to_fragtree(c, &f->fragtree, newfrag); if (unlikely(ret)) return ret; @@ -344,10 +392,465 @@ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_in } } jffs2_dbg_fragtree_paranoia_check_nolock(f); - jffs2_dbg_dump_fragtree_nolock(f); + + return 0; +} + +/* + * Check the data CRC of the node. + * + * Returns: 0 if the data CRC is correct; + * 1 - if incorrect; + * error code if an error occured. + */ +static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn) +{ + struct jffs2_raw_node_ref *ref = tn->fn->raw; + int err = 0, pointed = 0; + struct jffs2_eraseblock *jeb; + unsigned char *buffer; + uint32_t crc, ofs, retlen, len; + + BUG_ON(tn->csize == 0); + + /* Calculate how many bytes were already checked */ + ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode); + len = ofs - (ofs & (PAGE_CACHE_SIZE - 1)); + len = c->wbuf_pagesize - len; + + if (len >= tn->csize) { + JFFS2_DBG_READINODE("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n", + ref_offset(ref), tn->csize, ofs); + goto adj_acc; + } + + ofs += len; + len = tn->csize - len; + + JFFS2_DBG_READINODE("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.\n", + ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len); + +#ifndef __ECOS + /* TODO: instead, incapsulate point() stuff to jffs2_flash_read(), + * adding and jffs2_flash_read_end() interface. */ + if (c->mtd->point) { + err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer); + if (!err && retlen < tn->csize) { + JFFS2_WARNING("MTD point returned len too short: %u instead of %u.\n", retlen, tn->csize); + c->mtd->unpoint(c->mtd, buffer, ofs, len); + } else if (err) + JFFS2_WARNING("MTD point failed: error code %d.\n", err); + else + pointed = 1; /* succefully pointed to device */ + } +#endif + + if (!pointed) { + buffer = kmalloc(len, GFP_KERNEL); + if (unlikely(!buffer)) + return -ENOMEM; + + /* TODO: this is very frequent pattern, make it a separate + * routine */ + err = jffs2_flash_read(c, ofs, len, &retlen, buffer); + if (err) { + JFFS2_ERROR("can not read %d bytes from 0x%08x, error code: %d.\n", len, ofs, err); + goto free_out; + } + + if (retlen != len) { + JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", ofs, retlen, len); + err = -EIO; + goto free_out; + } + } + + /* Continue calculating CRC */ + crc = crc32(tn->partial_crc, buffer, len); + if(!pointed) + kfree(buffer); +#ifndef __ECOS + else + c->mtd->unpoint(c->mtd, buffer, ofs, len); +#endif + + if (crc != tn->data_crc) { + JFFS2_NOTICE("drong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n", + ofs, tn->data_crc, crc); + return 1; + } + +adj_acc: + jeb = &c->blocks[ref->flash_offset / c->sector_size]; + len = ref_totlen(c, jeb, ref); + + /* + * Mark the node as having been checked and fix the + * accounting accordingly. + */ + spin_lock(&c->erase_completion_lock); + jeb->used_size += len; + jeb->unchecked_size -= len; + c->used_size += len; + c->unchecked_size -= len; + spin_unlock(&c->erase_completion_lock); + return 0; + +free_out: + if(!pointed) + kfree(buffer); +#ifndef __ECOS + else + c->mtd->unpoint(c->mtd, buffer, ofs, len); +#endif + return err; } +/* + * Helper function for jffs2_add_older_frag_to_fragtree(). + * + * Checks the node if we are in the checking stage. + */ +static inline int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn) +{ + int ret; + + BUG_ON(ref_obsolete(tn->fn->raw)); + + /* We only check the data CRC of unchecked nodes */ + if (ref_flags(tn->fn->raw) != REF_UNCHECKED) + return 0; + + JFFS2_DBG_FRAGTREE2("check node %u-%u, phys offs %#08x.\n", + tn->fn->ofs, tn->fn->ofs + tn->fn->size, + ref_offset(tn->fn->raw)); + + ret = check_node_data(c, tn); + if (unlikely(ret < 0)) { + JFFS2_ERROR("check_node_data() returned error: %d.\n", + ret); + } else if (unlikely(ret > 0)) { + JFFS2_DBG_FRAGTREE2("CRC error, mark it obsolete.\n"); + jffs2_mark_node_obsolete(c, tn->fn->raw); + } + + return ret; +} + +/* + * Helper function for jffs2_add_older_frag_to_fragtree(). + * + * Called when the new fragment that is being inserted + * splits a hole fragment. + */ +static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, + struct jffs2_node_frag *newfrag, struct jffs2_node_frag *hole) +{ + JFFS2_DBG_FRAGTREE2("fragment %#04x-%#04x splits the hole %#04x-%#04x\n", + newfrag->ofs, newfrag->ofs + newfrag->size, hole->ofs, hole->ofs + hole->size); + + if (hole->ofs == newfrag->ofs) { + /* + * Well, the new fragment actually starts at the same offset as + * the hole. + */ + if (hole->ofs + hole->size > newfrag->ofs + newfrag->size) { + /* + * We replace the overlapped left part of the hole by + * the new node. + */ + + JFFS2_DBG_FRAGTREE2("insert fragment %#04x-%#04x and cut the left part of the hole\n", + newfrag->ofs, newfrag->ofs + newfrag->size); + rb_replace_node(&hole->rb, &newfrag->rb, root); + + hole->ofs += newfrag->size; + hole->size -= newfrag->size; + + /* + * We know that 'hole' should be the right hand + * fragment. + */ + jffs2_fragtree_insert(hole, newfrag); + rb_insert_color(&hole->rb, root); + } else { + /* + * Ah, the new fragment is of the same size as the hole. + * Relace the hole by it. + */ + JFFS2_DBG_FRAGTREE2("insert fragment %#04x-%#04x and overwrite hole\n", + newfrag->ofs, newfrag->ofs + newfrag->size); + rb_replace_node(&hole->rb, &newfrag->rb, root); + jffs2_free_node_frag(hole); + } + } else { + /* The new fragment lefts some hole space at the left */ + + struct jffs2_node_frag * newfrag2 = NULL; + + if (hole->ofs + hole->size > newfrag->ofs + newfrag->size) { + /* The new frag also lefts some space at the right */ + newfrag2 = new_fragment(NULL, newfrag->ofs + + newfrag->size, hole->ofs + hole->size + - newfrag->ofs - newfrag->size); + if (unlikely(!newfrag2)) { + jffs2_free_node_frag(newfrag); + return -ENOMEM; + } + } + + hole->size = newfrag->ofs - hole->ofs; + JFFS2_DBG_FRAGTREE2("left the hole %#04x-%#04x at the left and inserd fragment %#04x-%#04x\n", + hole->ofs, hole->ofs + hole->size, newfrag->ofs, newfrag->ofs + newfrag->size); + + jffs2_fragtree_insert(newfrag, hole); + rb_insert_color(&newfrag->rb, root); + + if (newfrag2) { + JFFS2_DBG_FRAGTREE2("left the hole %#04x-%#04x at the right\n", + newfrag2->ofs, newfrag2->ofs + newfrag2->size); + jffs2_fragtree_insert(newfrag2, newfrag); + rb_insert_color(&newfrag2->rb, root); + } + } + + return 0; +} + +/* + * This function is used when we build inode. It expects the nodes are passed + * in the decreasing version order. The whole point of this is to improve the + * inodes checking on NAND: we check the nodes' data CRC only when they are not + * obsoleted. Previously, add_frag_to_fragtree() function was used and + * nodes were passed to it in the increasing version ordes and CRCs of all + * nodes were checked. + * + * Note: tn->fn->size shouldn't be zero. + * + * Returns 0 if the node was inserted + * 1 if it wasn't inserted (since it is obsolete) + * < 0 an if error occured + */ +int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, + struct jffs2_tmp_dnode_info *tn) +{ + struct jffs2_node_frag *this, *newfrag; + uint32_t lastend; + struct jffs2_full_dnode *fn = tn->fn; + struct rb_root *root = &f->fragtree; + uint32_t fn_size = fn->size, fn_ofs = fn->ofs; + int err, checked = 0; + int ref_flag; + + JFFS2_DBG_FRAGTREE("insert fragment %#04x-%#04x\n", fn_ofs, fn_ofs + fn_size); + + /* Skip all the nodes which are completed before this one starts */ + this = jffs2_lookup_node_frag(root, fn_ofs); + if (this) + JFFS2_DBG_FRAGTREE2("'this' found %#04x-%#04x (%s)\n", this->ofs, this->ofs + this->size, this->node ? "data" : "hole"); + + if (this) + lastend = this->ofs + this->size; + else + lastend = 0; + + /* Detect the preliminary type of node */ + if (fn->size >= PAGE_CACHE_SIZE) + ref_flag = REF_PRISTINE; + else + ref_flag = REF_NORMAL; + + /* See if we ran off the end of the root */ + if (lastend <= fn_ofs) { + /* We did */ + + /* + * We are going to insert the new node into the + * fragment tree, so check it. + */ + err = check_node(c, f, tn); + if (err != 0) + return err; + + fn->frags = 1; + + newfrag = new_fragment(fn, fn_ofs, fn_size); + if (unlikely(!newfrag)) + return -ENOMEM; + + err = no_overlapping_node(c, root, newfrag, this, lastend); + if (unlikely(err != 0)) { + jffs2_free_node_frag(newfrag); + return err; + } + + goto out_ok; + } + + fn->frags = 0; + + while (1) { + /* + * Here we have: + * fn_ofs < this->ofs + this->size && fn_ofs >= this->ofs. + * + * Remember, 'this' has higher version, any non-hole node + * which is already in the fragtree is newer then the newly + * inserted. + */ + if (!this->node) { + /* + * 'this' is the hole fragment, so at least the + * beginning of the new fragment is valid. + */ + + /* + * We are going to insert the new node into the + * fragment tree, so check it. + */ + if (!checked) { + err = check_node(c, f, tn); + if (unlikely(err != 0)) + return err; + checked = 1; + } + + if (this->ofs + this->size >= fn_ofs + fn_size) { + /* We split the hole on two parts */ + + fn->frags += 1; + newfrag = new_fragment(fn, fn_ofs, fn_size); + if (unlikely(!newfrag)) + return -ENOMEM; + + err = split_hole(c, root, newfrag, this); + if (unlikely(err)) + return err; + goto out_ok; + } + + /* + * The beginning of the new fragment is valid since it + * overlaps the hole node. + */ + + ref_flag = REF_NORMAL; + + fn->frags += 1; + newfrag = new_fragment(fn, fn_ofs, + this->ofs + this->size - fn_ofs); + if (unlikely(!newfrag)) + return -ENOMEM; + + if (fn_ofs == this->ofs) { + /* + * The new node starts at the same offset as + * the hole and supersieds the hole. + */ + JFFS2_DBG_FRAGTREE2("add the new fragment instead of hole %#04x-%#04x, refcnt %d\n", + fn_ofs, fn_ofs + this->ofs + this->size - fn_ofs, fn->frags); + + rb_replace_node(&this->rb, &newfrag->rb, root); + jffs2_free_node_frag(this); + } else { + /* + * The hole becomes shorter as its right part + * is supersieded by the new fragment. + */ + JFFS2_DBG_FRAGTREE2("reduce size of hole %#04x-%#04x to %#04x-%#04x\n", + this->ofs, this->ofs + this->size, this->ofs, this->ofs + this->size - newfrag->size); + + JFFS2_DBG_FRAGTREE2("add new fragment %#04x-%#04x, refcnt %d\n", fn_ofs, + fn_ofs + this->ofs + this->size - fn_ofs, fn->frags); + + this->size -= newfrag->size; + jffs2_fragtree_insert(newfrag, this); + rb_insert_color(&newfrag->rb, root); + } + + fn_ofs += newfrag->size; + fn_size -= newfrag->size; + this = rb_entry(rb_next(&newfrag->rb), + struct jffs2_node_frag, rb); + + JFFS2_DBG_FRAGTREE2("switch to the next 'this' fragment: %#04x-%#04x %s\n", + this->ofs, this->ofs + this->size, this->node ? "(data)" : "(hole)"); + } + + /* + * 'This' node is not the hole so it obsoletes the new fragment + * either fully or partially. + */ + if (this->ofs + this->size >= fn_ofs + fn_size) { + /* The new node is obsolete, drop it */ + if (fn->frags == 0) { + JFFS2_DBG_FRAGTREE2("%#04x-%#04x is obsolete, mark it obsolete\n", fn_ofs, fn_ofs + fn_size); + ref_flag = REF_OBSOLETE; + } + goto out_ok; + } else { + struct jffs2_node_frag *new_this; + + /* 'This' node obsoletes the beginning of the new node */ + JFFS2_DBG_FRAGTREE2("the beginning %#04x-%#04x is obsolete\n", fn_ofs, this->ofs + this->size); + + ref_flag = REF_NORMAL; + + fn_size -= this->ofs + this->size - fn_ofs; + fn_ofs = this->ofs + this->size; + JFFS2_DBG_FRAGTREE2("now considering %#04x-%#04x\n", fn_ofs, fn_ofs + fn_size); + + new_this = rb_entry(rb_next(&this->rb), struct jffs2_node_frag, rb); + if (!new_this) { + /* + * There is no next fragment. Add the rest of + * the new node as the right-hand child. + */ + if (!checked) { + err = check_node(c, f, tn); + if (unlikely(err != 0)) + return err; + checked = 1; + } + + fn->frags += 1; + newfrag = new_fragment(fn, fn_ofs, fn_size); + if (unlikely(!newfrag)) + return -ENOMEM; + + JFFS2_DBG_FRAGTREE2("there are no more fragments, insert %#04x-%#04x\n", + newfrag->ofs, newfrag->ofs + newfrag->size); + rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); + rb_insert_color(&newfrag->rb, root); + goto out_ok; + } else { + this = new_this; + JFFS2_DBG_FRAGTREE2("switch to the next 'this' fragment: %#04x-%#04x %s\n", + this->ofs, this->ofs + this->size, this->node ? "(data)" : "(hole)"); + } + } + } + +out_ok: + BUG_ON(fn->size < PAGE_CACHE_SIZE && ref_flag == REF_PRISTINE); + + if (ref_flag == REF_OBSOLETE) { + JFFS2_DBG_FRAGTREE2("the node is obsolete now\n"); + /* jffs2_mark_node_obsolete() will adjust space accounting */ + jffs2_mark_node_obsolete(c, fn->raw); + return 1; + } + + JFFS2_DBG_FRAGTREE2("the node is \"%s\" now\n", ref_flag == REF_NORMAL ? "REF_NORMAL" : "REF_PRISTINE"); + + /* Space accounting was adjusted at check_node_data() */ + spin_lock(&c->erase_completion_lock); + fn->raw->flash_offset = ref_offset(fn->raw) | ref_flag; + spin_unlock(&c->erase_completion_lock); + + return 0; +} void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state) { diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 53c12e4a337..adee3c6eb44 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.h,v 1.136 2005/07/31 08:20:44 dedekind Exp $ + * $Id: nodelist.h,v 1.137 2005/08/01 12:05:19 dedekind Exp $ * */ @@ -61,6 +61,9 @@ #error wibble #endif +/* The minimal node header size */ +#define JFFS2_MIN_NODE_HEADER sizeof(struct jffs2_raw_dirent) + /* This is all we need to keep in-core for each raw node during normal operation. As and when we do read_inode on a particular inode, we can @@ -148,6 +151,9 @@ struct jffs2_tmp_dnode_info struct rb_node rb; struct jffs2_full_dnode *fn; uint32_t version; + uint32_t data_crc; + uint32_t partial_crc; + uint32_t csize; }; struct jffs2_full_dirent @@ -311,6 +317,7 @@ void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this); int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); +int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn); /* nodemgmt.c */ int jffs2_thread_should_wake(struct jffs2_sb_info *c); diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index f3b12d7fe9a..488787a823b 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.134 2005/07/31 08:20:44 dedekind Exp $ + * $Id: readinode.c,v 1.135 2005/08/01 12:05:19 dedekind Exp $ * */ @@ -21,8 +21,8 @@ #include #include "nodelist.h" -/* - * Put a new tmp_dnode_info into the temporaty RB-tree, keeping the list in +/* + * Put a new tmp_dnode_info into the temporaty RB-tree, keeping the list in * order of increasing version. */ static void jffs2_add_tn_to_tree(struct jffs2_tmp_dnode_info *tn, struct rb_root *list) @@ -38,11 +38,11 @@ static void jffs2_add_tn_to_tree(struct jffs2_tmp_dnode_info *tn, struct rb_root /* There may actually be a collision here, but it doesn't actually matter. As long as the two nodes with the same version are together, it's all fine. */ - if (tn->version < this->version) + if (tn->version > this->version) p = &(*p)->rb_left; else p = &(*p)->rb_right; - } + } rb_link_node(&tn->rb, parent, p); rb_insert_color(&tn->rb, list); @@ -111,14 +111,9 @@ static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_r * 1 if the node should be marked obsolete; * negative error code on failure. */ -static inline int -read_direntry(struct jffs2_sb_info *c, - struct jffs2_raw_node_ref *ref, - struct jffs2_raw_dirent *rd, - uint32_t read, - struct jffs2_full_dirent **fdp, - int32_t *latest_mctime, - uint32_t *mctime_ver) +static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, + struct jffs2_raw_dirent *rd, uint32_t read, struct jffs2_full_dirent **fdp, + uint32_t *latest_mctime, uint32_t *mctime_ver) { struct jffs2_full_dirent *fd; @@ -196,30 +191,35 @@ read_direntry(struct jffs2_sb_info *c, * 1 if the node should be marked obsolete; * negative error code on failure. */ -static inline int -read_dnode(struct jffs2_sb_info *c, - struct jffs2_raw_node_ref *ref, - struct jffs2_raw_inode *rd, - uint32_t read, - struct rb_root *tnp, - int32_t *latest_mctime, - uint32_t *mctime_ver) +static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, + struct jffs2_raw_inode *rd, struct rb_root *tnp, int rdlen, + uint32_t *latest_mctime, uint32_t *mctime_ver) { - struct jffs2_eraseblock *jeb; struct jffs2_tmp_dnode_info *tn; + uint32_t len, csize; + int ret = 1; /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ BUG_ON(ref_obsolete(ref)); + tn = jffs2_alloc_tmp_dnode_info(); + if (!tn) { + JFFS2_ERROR("failed to allocate tn (%d bytes).\n", sizeof(*tn)); + return -ENOMEM; + } + + tn->partial_crc = 0; + csize = je32_to_cpu(rd->csize); + /* If we've never checked the CRCs on this node, check them now */ if (ref_flags(ref) == REF_UNCHECKED) { - uint32_t crc, len; + uint32_t crc; crc = crc32(0, rd, sizeof(*rd) - 8); if (unlikely(crc != je32_to_cpu(rd->node_crc))) { JFFS2_NOTICE("header CRC failed on node at %#08x: read %#08x, calculated %#08x\n", ref_offset(ref), je32_to_cpu(rd->node_crc), crc); - return 1; + goto free_out; } /* Sanity checks */ @@ -227,107 +227,102 @@ read_dnode(struct jffs2_sb_info *c, unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) { JFFS2_WARNING("inode node header CRC is corrupted at %#08x\n", ref_offset(ref)); jffs2_dbg_dump_node(c, ref_offset(ref)); - return 1; + goto free_out; } - if (rd->compr != JFFS2_COMPR_ZERO && je32_to_cpu(rd->csize)) { - unsigned char *buf = NULL; - uint32_t pointed = 0; - int err; -#ifndef __ECOS - if (c->mtd->point) { - err = c->mtd->point (c->mtd, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize), - &read, &buf); - if (unlikely(read < je32_to_cpu(rd->csize)) && likely(!err)) { - JFFS2_ERROR("MTD point returned len too short: 0x%zx\n", read); - c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(*rd), - je32_to_cpu(rd->csize)); - } else if (unlikely(err)){ - JFFS2_ERROR("MTD point failed %d\n", err); - } else - pointed = 1; /* succefully pointed to device */ - } -#endif - if(!pointed){ - buf = kmalloc(je32_to_cpu(rd->csize), GFP_KERNEL); - if (!buf) - return -ENOMEM; - - err = jffs2_flash_read(c, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize), - &read, buf); - if (unlikely(read != je32_to_cpu(rd->csize)) && likely(!err)) - err = -EIO; - if (err) { - kfree(buf); - return err; - } - } - crc = crc32(0, buf, je32_to_cpu(rd->csize)); - if(!pointed) - kfree(buf); -#ifndef __ECOS - else - c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize)); -#endif - - if (crc != je32_to_cpu(rd->data_crc)) { - JFFS2_NOTICE("data CRC failed on node at %#08x: read %#08x, calculated %#08x\n", - ref_offset(ref), je32_to_cpu(rd->data_crc), crc); - return 1; - } + if (jffs2_is_writebuffered(c) && csize != 0) { + /* At this point we are supposed to check the data CRC + * of our unchecked node. But thus far, we do not + * know whether the node is valid or obsolete. To + * figure this out, we need to walk all the nodes of + * the inode and build the inode fragtree. We don't + * want to spend time checking data of nodes which may + * later be found to be obsolete. So we put off the full + * data CRC checking until we have read all the inode + * nodes and have started building the fragtree. + * + * The fragtree is being built starting with nodes + * having the highest version number, so we'll be able + * to detect whether a node is valid (i.e., it is not + * overlapped by a node with higher version) or not. + * And we'll be able to check only those nodes, which + * are not obsolete. + * + * Of course, this optimization only makes sense in case + * of NAND flashes (or other flashes whith + * !jffs2_can_mark_obsolete()), since on NOR flashes + * nodes are marked obsolete physically. + * + * Since NAND flashes (or other flashes with + * jffs2_is_writebuffered(c)) are anyway read by + * fractions of c->wbuf_pagesize, and we have just read + * the node header, it is likely that the starting part + * of the node data is also read when we read the + * header. So we don't mind to check the CRC of the + * starting part of the data of the node now, and check + * the second part later (in jffs2_check_node_data()). + * Of course, we will not need to re-read and re-check + * the NAND page which we have just read. This is why we + * read the whole NAND page at jffs2_get_inode_nodes(), + * while we needed only the node header. + */ + unsigned char *buf; + + /* 'buf' will point to the start of data */ + buf = (unsigned char *)rd + sizeof(*rd); + /* len will be the read data length */ + len = min_t(uint32_t, rdlen - sizeof(*rd), csize); - } - - /* Mark the node as having been checked and fix the accounting accordingly */ - jeb = &c->blocks[ref->flash_offset / c->sector_size]; - len = ref_totlen(c, jeb, ref); - - spin_lock(&c->erase_completion_lock); - jeb->used_size += len; - jeb->unchecked_size -= len; - c->used_size += len; - c->unchecked_size -= len; - - /* If node covers at least a whole page, or if it starts at the - beginning of a page and runs to the end of the file, or if - it's a hole node, mark it REF_PRISTINE, else REF_NORMAL. + if (len) + tn->partial_crc = crc = crc32(0, buf, len); + + /* If we actually calculated the whole data CRC + * and it is wrong, drop the node. */ + if (unlikely(tn->partial_crc + != je32_to_cpu(rd->data_crc)) && + len == csize) + goto free_out; - If it's actually overlapped, it'll get made NORMAL (or OBSOLETE) - when the overlapping node(s) get added to the tree anyway. - */ - if ((je32_to_cpu(rd->dsize) >= PAGE_CACHE_SIZE) || - ( ((je32_to_cpu(rd->offset) & (PAGE_CACHE_SIZE-1))==0) && - (je32_to_cpu(rd->dsize) + je32_to_cpu(rd->offset) == je32_to_cpu(rd->isize)))) { - JFFS2_DBG_READINODE("marking node at %#08x REF_PRISTINE\n", ref_offset(ref)); - ref->flash_offset = ref_offset(ref) | REF_PRISTINE; - } else { - JFFS2_DBG_READINODE("marking node at %#08x REF_NORMAL\n", ref_offset(ref)); + } else if (csize == 0) { + /* + * We checked the header CRC. If the node has no data, adjust + * the space accounting now. For other nodes this will be done + * later either when the node is marked obsolete or when its + * data is checked. + */ + struct jffs2_eraseblock *jeb; + + JFFS2_DBG_READINODE("the node has no data.\n"); + jeb = &c->blocks[ref->flash_offset / c->sector_size]; + len = ref_totlen(c, jeb, ref); + + spin_lock(&c->erase_completion_lock); + jeb->used_size += len; + jeb->unchecked_size -= len; + c->used_size += len; + c->unchecked_size -= len; ref->flash_offset = ref_offset(ref) | REF_NORMAL; + spin_unlock(&c->erase_completion_lock); } - spin_unlock(&c->erase_completion_lock); - } - - tn = jffs2_alloc_tmp_dnode_info(); - if (!tn) { - JFFS2_ERROR("alloc tn failed\n"); - return -ENOMEM; } tn->fn = jffs2_alloc_full_dnode(); if (!tn->fn) { JFFS2_ERROR("alloc fn failed\n"); - jffs2_free_tmp_dnode_info(tn); - return -ENOMEM; + ret = -ENOMEM; + goto free_out; } tn->version = je32_to_cpu(rd->version); tn->fn->ofs = je32_to_cpu(rd->offset); + tn->data_crc = je32_to_cpu(rd->data_crc); + tn->csize = csize; tn->fn->raw = ref; /* There was a bug where we wrote hole nodes out with csize/dsize swapped. Deal with it */ - if (rd->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(rd->dsize) && je32_to_cpu(rd->csize)) - tn->fn->size = je32_to_cpu(rd->csize); + if (rd->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(rd->dsize) && csize) + tn->fn->size = csize; else // normal case... tn->fn->size = je32_to_cpu(rd->dsize); @@ -337,6 +332,10 @@ read_dnode(struct jffs2_sb_info *c, jffs2_add_tn_to_tree(tn, tnp); return 0; + +free_out: + jffs2_free_tmp_dnode_info(tn); + return ret; } /* @@ -347,11 +346,7 @@ read_dnode(struct jffs2_sb_info *c, * 1 if the node should be marked obsolete; * negative error code on failure. */ -static inline int -read_unknown(struct jffs2_sb_info *c, - struct jffs2_raw_node_ref *ref, - struct jffs2_unknown_node *un, - uint32_t read) +static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, struct jffs2_unknown_node *un) { /* We don't mark unknown nodes as REF_UNCHECKED */ BUG_ON(ref_flags(ref) == REF_UNCHECKED); @@ -394,9 +389,62 @@ read_unknown(struct jffs2_sb_info *c, return 0; } +/* + * Helper function for jffs2_get_inode_nodes(). + * The function detects whether more data should be read and reads it if yes. + * + * Returns: 0 on succes; + * negative error code on failure. + */ +static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, + int right_size, int *rdlen, unsigned char *buf, unsigned char *bufstart) +{ + int right_len, err, len; + size_t retlen; + uint32_t offs; + + if (jffs2_is_writebuffered(c)) { + right_len = c->wbuf_pagesize - (bufstart - buf); + if (right_size + (int)(bufstart - buf) > c->wbuf_pagesize) + right_len += c->wbuf_pagesize; + } else + right_len = right_size; + + if (*rdlen == right_len) + return 0; + + /* We need to read more data */ + offs = ref_offset(ref) + *rdlen; + if (jffs2_is_writebuffered(c)) { + bufstart = buf + c->wbuf_pagesize; + len = c->wbuf_pagesize; + } else { + bufstart = buf + *rdlen; + len = right_size - *rdlen; + } + + JFFS2_DBG_READINODE("read more %d bytes.", len); + + err = jffs2_flash_read(c, offs, len, &retlen, bufstart); + if (err) { + JFFS2_ERROR("can not read %d bytes from 0x%08x, " + "error code: %d.\n", len, offs, err); + return err; + } + + if (retlen < len) { + JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", + offs, retlen, len); + return -EIO; + } + + *rdlen = right_len; + + return 0; +} + /* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated with this ino, returning the former in order of version */ - static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct rb_root *tnp, struct jffs2_full_dirent **fdp, uint32_t *highest_version, uint32_t *latest_mctime, @@ -405,22 +453,47 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf struct jffs2_raw_node_ref *ref, *valid_ref; struct rb_root ret_tn = RB_ROOT; struct jffs2_full_dirent *ret_fd = NULL; - union jffs2_node_union node; + unsigned char *buf = NULL; + union jffs2_node_union *node; size_t retlen; - int err; + int len, err; *mctime_ver = 0; JFFS2_DBG_READINODE("ino #%u\n", f->inocache->ino); - spin_lock(&c->erase_completion_lock); + if (jffs2_is_writebuffered(c)) { + /* + * If we have the write buffer, we assume the minimal I/O unit + * is c->wbuf_pagesize. We implement some optimizations which in + * this case and we need a temporary buffer of size = + * 2*c->wbuf_pagesize bytes (see comments in read_dnode()). + * Basically, we want to read not only the node header, but the + * whole wbuf (NAND page in case of NAND) or 2, if the node + * header overlaps the border between the 2 wbufs. + */ + len = 2*c->wbuf_pagesize; + } else { + /* + * When there is no write buffer, the size of the temporary + * buffer is the size of the larges node header. + */ + len = sizeof(union jffs2_node_union); + } + /* FIXME: in case of NOR and available ->point() this + * needs to be fixed. */ + buf = kmalloc(len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + spin_lock(&c->erase_completion_lock); valid_ref = jffs2_first_valid_node(f->inocache->nodes); - - if (!valid_ref && (f->inocache->ino != 1)) - JFFS2_WARNING("no valid nodes for ino #%u\n", f->inocache->ino); - + if (!valid_ref && f->inocache->ino != 1) + JFFS2_WARNING("Eep. No valid nodes for ino #%u.\n", f->inocache->ino); while (valid_ref) { + unsigned char *bufstart; + /* We can hold a pointer to a non-obsolete node without the spinlock, but _obsolete_ nodes may disappear at any time, if the block they're in gets erased. So if we mark 'ref' obsolete while we're @@ -433,70 +506,100 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf cond_resched(); + /* + * At this point we don't know the type of the node we're going + * to read, so we do not know the size of its header. In order + * to minimize the amount of flash IO we assume the node has + * size = JFFS2_MIN_NODE_HEADER. + */ + if (jffs2_is_writebuffered(c)) { + /* + * We treat 'buf' as 2 adjacent wbufs. We want to + * adjust bufstart such as it points to the + * beginning of the node within this wbuf. + */ + bufstart = buf + (ref_offset(ref) % c->wbuf_pagesize); + /* We will read either one wbuf or 2 wbufs. */ + len = c->wbuf_pagesize - (bufstart - buf); + if (JFFS2_MIN_NODE_HEADER + + (int)(bufstart - buf) > c->wbuf_pagesize) { + /* The header spans the border of the + * first wbuf */ + len += c->wbuf_pagesize; + } + } else { + bufstart = buf; + len = JFFS2_MIN_NODE_HEADER; + } + + JFFS2_DBG_READINODE("read %d bytes at %#08x(%d).\n", len, ref_offset(ref), ref_flags(ref)); + /* FIXME: point() */ - err = jffs2_flash_read(c, (ref_offset(ref)), - min_t(uint32_t, ref_totlen(c, NULL, ref), sizeof(node)), - &retlen, (void *)&node); + err = jffs2_flash_read(c, ref_offset(ref), len, + &retlen, bufstart); if (err) { - JFFS2_ERROR("error %d reading node at 0x%08x in get_inode_nodes()\n", err, ref_offset(ref)); + JFFS2_ERROR("can not read %d bytes from 0x%08x, " "error code: %d.\n", len, ref_offset(ref), err); + goto free_out; + } + + if (retlen < len) { + JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", ref_offset(ref), retlen, len); + err = -EIO; goto free_out; } + + node = (union jffs2_node_union *)bufstart; - switch (je16_to_cpu(node.u.nodetype)) { + switch (je16_to_cpu(node->u.nodetype)) { case JFFS2_NODETYPE_DIRENT: - JFFS2_DBG_READINODE("node at %08x (%d) is a dirent node\n", ref_offset(ref), ref_flags(ref)); - - if (retlen < sizeof(node.d)) { - JFFS2_ERROR("short read dirent at %#08x\n", ref_offset(ref)); - err = -EIO; - goto free_out; - } - err = read_direntry(c, ref, &node.d, retlen, &ret_fd, latest_mctime, mctime_ver); + if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent)) { + err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf, bufstart); + if (unlikely(err)) + goto free_out; + } + + err = read_direntry(c, ref, &node->d, retlen, &ret_fd, latest_mctime, mctime_ver); if (err == 1) { jffs2_mark_node_obsolete(c, ref); break; } else if (unlikely(err)) goto free_out; - if (je32_to_cpu(node.d.version) > *highest_version) - *highest_version = je32_to_cpu(node.d.version); + if (je32_to_cpu(node->d.version) > *highest_version) + *highest_version = je32_to_cpu(node->d.version); break; case JFFS2_NODETYPE_INODE: - JFFS2_DBG_READINODE("node at %08x (%d) is a data node\n", ref_offset(ref), ref_flags(ref)); - if (retlen < sizeof(node.i)) { - JFFS2_ERROR("short read dnode at %#08x\n", ref_offset(ref)); - err = -EIO; - goto free_out; + if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode)) { + err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf, bufstart); + if (unlikely(err)) + goto free_out; } - err = read_dnode(c, ref, &node.i, retlen, &ret_tn, latest_mctime, mctime_ver); + err = read_dnode(c, ref, &node->i, &ret_tn, len, latest_mctime, mctime_ver); if (err == 1) { jffs2_mark_node_obsolete(c, ref); break; } else if (unlikely(err)) goto free_out; - if (je32_to_cpu(node.i.version) > *highest_version) - *highest_version = je32_to_cpu(node.i.version); + if (je32_to_cpu(node->i.version) > *highest_version) + *highest_version = je32_to_cpu(node->i.version); - JFFS2_DBG_READINODE("version %d, highest_version now %d\n", - je32_to_cpu(node.i.version), *highest_version); - break; default: - /* Check we've managed to read at least the common node header */ - if (retlen < sizeof(struct jffs2_unknown_node)) { - JFFS2_ERROR("short read unknown node at %#08x\n", ref_offset(ref)); - return -EIO; + if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node)) { + err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf, bufstart); + if (unlikely(err)) + goto free_out; } - - err = read_unknown(c, ref, &node.u, retlen); + + err = read_unknown(c, ref, &node->u); if (err == 1) { jffs2_mark_node_obsolete(c, ref); break; @@ -505,17 +608,21 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf } spin_lock(&c->erase_completion_lock); - } + spin_unlock(&c->erase_completion_lock); *tnp = ret_tn; *fdp = ret_fd; + kfree(buf); + JFFS2_DBG_READINODE("nodes of inode #%u were read, the highest version is %u, latest_mctime %u, mctime_ver %u.\n", + f->inocache->ino, *highest_version, *latest_mctime, *mctime_ver); return 0; free_out: jffs2_free_tmp_dnode_info_list(&ret_tn); jffs2_free_full_dirent_list(ret_fd); + kfree(buf); return err; } @@ -523,14 +630,13 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *latest_node) { - struct jffs2_tmp_dnode_info *tn = NULL; + struct jffs2_tmp_dnode_info *tn; struct rb_root tn_list; struct rb_node *rb, *repl_rb; struct jffs2_full_dirent *fd_list; - struct jffs2_full_dnode *fn = NULL; + struct jffs2_full_dnode *fn, *first_fn = NULL; uint32_t crc; uint32_t latest_mctime, mctime_ver; - uint32_t mdata_ver = 0; size_t retlen; int ret; @@ -550,42 +656,33 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, rb = rb_first(&tn_list); while (rb) { + cond_resched(); tn = rb_entry(rb, struct jffs2_tmp_dnode_info, rb); fn = tn->fn; - - if (f->metadata) { - if (likely(tn->version >= mdata_ver)) { - JFFS2_DBG_READINODE("obsoleting old metadata at 0x%08x\n", ref_offset(f->metadata->raw)); - jffs2_mark_node_obsolete(c, f->metadata->raw); - jffs2_free_full_dnode(f->metadata); - f->metadata = NULL; - - mdata_ver = 0; - } else { - /* This should never happen. */ - JFFS2_ERROR("Er. New metadata at 0x%08x with ver %d is actually older than previous ver %d at 0x%08x\n", - ref_offset(fn->raw), tn->version, mdata_ver, ref_offset(f->metadata->raw)); - jffs2_mark_node_obsolete(c, fn->raw); - jffs2_free_full_dnode(fn); - /* Fill in latest_node from the metadata, not this one we're about to free... */ - fn = f->metadata; - goto next_tn; - } - } + ret = 1; + JFFS2_DBG_READINODE("consider node ver %u, phys offset " + "%#08x(%d), range %u-%u.\n", tn->version, + ref_offset(fn->raw), ref_flags(fn->raw), + fn->ofs, fn->ofs + fn->size); if (fn->size) { - jffs2_add_full_dnode_to_inode(c, f, fn); - } else { - /* Zero-sized node at end of version list. Just a metadata update */ - JFFS2_DBG_READINODE("metadata @%08x: ver %d\n", ref_offset(fn->raw), tn->version); + ret = jffs2_add_older_frag_to_fragtree(c, f, tn); + /* TODO: the error code isn't checked, check it */ + jffs2_dbg_fragtree_paranoia_check_nolock(f); + BUG_ON(ret < 0); + if (!first_fn && ret == 0) + first_fn = fn; + } else if (!first_fn) { + first_fn = fn; f->metadata = fn; - mdata_ver = tn->version; - } - next_tn: + ret = 0; /* Prevent freeing the metadata update node */ + } else + jffs2_mark_node_obsolete(c, fn->raw); + BUG_ON(rb->rb_left); if (rb->rb_parent && rb->rb_parent->rb_left == rb) { /* We were then left-hand child of our parent. We need - to move our own right-hand child into our place. */ + * to move our own right-hand child into our place. */ repl_rb = rb->rb_right; if (repl_rb) repl_rb->rb_parent = rb->rb_parent; @@ -595,7 +692,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, rb = rb_next(rb); /* Remove the spent tn from the tree; don't bother rebalancing - but put our right-hand child in our own place. */ + * but put our right-hand child in our own place. */ if (tn->rb.rb_parent) { if (tn->rb.rb_parent->rb_left == &tn->rb) tn->rb.rb_parent->rb_left = repl_rb; @@ -606,10 +703,18 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, tn->rb.rb_right->rb_parent = NULL; jffs2_free_tmp_dnode_info(tn); + if (ret) { + JFFS2_DBG_READINODE("delete dnode %u-%u.\n", + fn->ofs, fn->ofs + fn->size); + jffs2_free_full_dnode(fn); + } } jffs2_dbg_fragtree_paranoia_check_nolock(f); - if (!fn) { + BUG_ON(first_fn && ref_obsolete(first_fn->raw)); + + fn = first_fn; + if (unlikely(!first_fn)) { /* No data nodes for this inode. */ if (f->inocache->ino != 1) { JFFS2_WARNING("no data nodes found for ino #%u\n", f->inocache->ino); -- cgit v1.2.3 From 392435081e8cc6e02bdc4fa998050abb11d331b4 Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Wed, 3 Aug 2005 10:26:50 +0100 Subject: [JFFS2] Debug code clean up - step 6 Remove extra noisy debugs Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/debug.h | 2 +- fs/jffs2/nodelist.c | 26 +++++++------------------- fs/jffs2/readinode.c | 15 +++++++-------- 3 files changed, 15 insertions(+), 28 deletions(-) diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index 2112bab514c..11ee75922a5 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.h,v 1.8 2005/07/31 09:08:38 dedekind Exp $ + * $Id: debug.h,v 1.10 2005/08/02 10:03:51 dedekind Exp $ * */ #ifndef _JFFS2_DEBUG_H_ diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 390ce06ab1a..007d52f394d 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.c,v 1.104 2005/08/01 12:05:19 dedekind Exp $ + * $Id: nodelist.c,v 1.107 2005/08/03 09:26:46 dedekind Exp $ * */ @@ -60,7 +60,6 @@ void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint /* We know frag->ofs <= size. That's what lookup does for us */ if (frag && frag->ofs != size) { if (frag->ofs+frag->size > size) { - JFFS2_DBG_FRAGTREE2("truncating frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size); frag->size = size - frag->ofs; } frag = frag_next(frag); @@ -68,7 +67,6 @@ void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint while (frag && frag->ofs >= size) { struct jffs2_node_frag *next = frag_next(frag); - JFFS2_DBG_FRAGTREE("removing frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size); frag_erase(frag, list); jffs2_obsolete_node_frag(c, frag); frag = next; @@ -120,7 +118,6 @@ static void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_ parent = *link; base = rb_entry(parent, struct jffs2_node_frag, rb); - JFFS2_DBG_FRAGTREE2("considering frag at 0x%08x\n", base->ofs); if (newfrag->ofs > base->ofs) link = &base->rb.rb_right; else if (newfrag->ofs < base->ofs) @@ -175,11 +172,11 @@ static int no_overlapping_node(struct jffs2_sb_info *c, struct rb_root *root, /* By definition, the 'this' node has no right-hand child, because there are no frags with offset greater than it. So that's where we want to put the hole */ - JFFS2_DBG_FRAGTREE2("add hole frag %u-%u on the right of the new frag.\n", + JFFS2_DBG_FRAGTREE2("add hole frag %#04x-%#04x on the right of the new frag.\n", holefrag->ofs, holefrag->ofs + holefrag->size); rb_link_node(&holefrag->rb, &this->rb, &this->rb.rb_right); } else { - JFFS2_DBG_FRAGTREE2("Add hole frag %u-%u to the root of the tree.\n", + JFFS2_DBG_FRAGTREE2("Add hole frag %#04x-%#04x to the root of the tree.\n", holefrag->ofs, holefrag->ofs + holefrag->size); rb_link_node(&holefrag->rb, NULL, &root->rb_node); } @@ -475,7 +472,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info #endif if (crc != tn->data_crc) { - JFFS2_NOTICE("drong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n", + JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n", ofs, tn->data_crc, crc); return 1; } @@ -522,9 +519,8 @@ static inline int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f if (ref_flags(tn->fn->raw) != REF_UNCHECKED) return 0; - JFFS2_DBG_FRAGTREE2("check node %u-%u, phys offs %#08x.\n", - tn->fn->ofs, tn->fn->ofs + tn->fn->size, - ref_offset(tn->fn->raw)); + JFFS2_DBG_FRAGTREE2("check node %#04x-%#04x, phys offs %#08x.\n", + tn->fn->ofs, tn->fn->ofs + tn->fn->size, ref_offset(tn->fn->raw)); ret = check_node_data(c, tn); if (unlikely(ret < 0)) { @@ -643,7 +639,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode int err, checked = 0; int ref_flag; - JFFS2_DBG_FRAGTREE("insert fragment %#04x-%#04x\n", fn_ofs, fn_ofs + fn_size); + JFFS2_DBG_FRAGTREE("insert fragment %#04x-%#04x, ver %u\n", fn_ofs, fn_ofs + fn_size, tn->version); /* Skip all the nodes which are completed before this one starts */ this = jffs2_lookup_node_frag(root, fn_ofs); @@ -975,22 +971,14 @@ struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_ while(next) { frag = rb_entry(next, struct jffs2_node_frag, rb); - JFFS2_DBG_FRAGTREE2("considering frag %#04x-%#04x (%p). left %p, right %p\n", - frag->ofs, frag->ofs+frag->size, frag, frag->rb.rb_left, frag->rb.rb_right); if (frag->ofs + frag->size <= offset) { - JFFS2_DBG_FRAGTREE2("going right from frag %#04x-%#04x, before the region we care about\n", - frag->ofs, frag->ofs+frag->size); /* Remember the closest smaller match on the way down */ if (!prev || frag->ofs > prev->ofs) prev = frag; next = frag->rb.rb_right; } else if (frag->ofs > offset) { - JFFS2_DBG_FRAGTREE2("going left from frag %#04x-%#04x, after the region we care about\n", - frag->ofs, frag->ofs+frag->size); next = frag->rb.rb_left; } else { - JFFS2_DBG_FRAGTREE2("returning frag %#04x-%#04x, matched\n", - frag->ofs, frag->ofs+frag->size); return frag; } } diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 488787a823b..e6076fa5560 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.135 2005/08/01 12:05:19 dedekind Exp $ + * $Id: readinode.c,v 1.137 2005/08/03 09:26:46 dedekind Exp $ * */ @@ -278,10 +278,11 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref /* If we actually calculated the whole data CRC * and it is wrong, drop the node. */ - if (unlikely(tn->partial_crc - != je32_to_cpu(rd->data_crc)) && - len == csize) + if (len == csize && unlikely(tn->partial_crc != je32_to_cpu(rd->data_crc))) { + JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n", + ref_offset(ref), tn->partial_crc, je32_to_cpu(rd->data_crc)); goto free_out; + } } else if (csize == 0) { /* @@ -521,10 +522,8 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf bufstart = buf + (ref_offset(ref) % c->wbuf_pagesize); /* We will read either one wbuf or 2 wbufs. */ len = c->wbuf_pagesize - (bufstart - buf); - if (JFFS2_MIN_NODE_HEADER + - (int)(bufstart - buf) > c->wbuf_pagesize) { - /* The header spans the border of the - * first wbuf */ + if (JFFS2_MIN_NODE_HEADER + (int)(bufstart - buf) > c->wbuf_pagesize) { + /* The header spans the border of the first wbuf */ len += c->wbuf_pagesize; } } else { -- cgit v1.2.3 From 3c09133739beff0d5ad457dfcfc85c7c350d3661 Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Thu, 4 Aug 2005 12:40:02 +0100 Subject: [JFFS2] Correct buggy length checks The previous changes introduced wrong length calculations. Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/nodelist.c | 4 ++-- fs/jffs2/readinode.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 007d52f394d..b5f73ab6553 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.c,v 1.107 2005/08/03 09:26:46 dedekind Exp $ + * $Id: nodelist.c,v 1.108 2005/08/04 11:39:59 dedekind Exp $ * */ @@ -412,7 +412,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info /* Calculate how many bytes were already checked */ ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode); - len = ofs - (ofs & (PAGE_CACHE_SIZE - 1)); + len = ofs & (c->wbuf_pagesize - 1); len = c->wbuf_pagesize - len; if (len >= tn->csize) { diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index e6076fa5560..12a3aaeb2f7 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.137 2005/08/03 09:26:46 dedekind Exp $ + * $Id: readinode.c,v 1.138 2005/08/03 09:28:06 dedekind Exp $ * */ @@ -278,7 +278,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref /* If we actually calculated the whole data CRC * and it is wrong, drop the node. */ - if (len == csize && unlikely(tn->partial_crc != je32_to_cpu(rd->data_crc))) { + if (len >= csize && unlikely(tn->partial_crc != je32_to_cpu(rd->data_crc))) { JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n", ref_offset(ref), tn->partial_crc, je32_to_cpu(rd->data_crc)); goto free_out; -- cgit v1.2.3 From 45ca1b509ea156e87c99e529821fb3b548e14fe3 Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Fri, 5 Aug 2005 12:43:47 +0100 Subject: [JFFS2] Debug code clean up - step 7 Remove more noisy debugs. Add current->pid to debug messages. Remove bogus includes. Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/debug.c | 40 ++++++++++++++++++++++++- fs/jffs2/debug.h | 82 +++++++++++++++++++--------------------------------- fs/jffs2/nodelist.c | 9 +----- fs/jffs2/readinode.c | 4 +-- 4 files changed, 71 insertions(+), 64 deletions(-) diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c index 80ac9b6514b..9b776b5a760 100644 --- a/fs/jffs2/debug.c +++ b/fs/jffs2/debug.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.c,v 1.8 2005/07/30 15:27:05 lunn Exp $ + * $Id: debug.c,v 1.9 2005/08/05 10:42:24 dedekind Exp $ * */ #include @@ -18,6 +18,44 @@ #include "nodelist.h" #include "debug.h" +#ifdef JFFS2_DBG_SANITY_CHECKS + +void +__jffs2_dbg_acct_sanity_check_nolock(struct jffs2_sb_info *c, + struct jffs2_eraseblock *jeb) +{ + if (unlikely(jeb && jeb->used_size + jeb->dirty_size + + jeb->free_size + jeb->wasted_size + + jeb->unchecked_size != c->sector_size)) { + JFFS2_ERROR("eeep, space accounting for block at 0x%08x is screwed.\n", jeb->offset); + JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + wasted %#08x + unchecked " + "%#08x != total %#08x.\n", jeb->free_size, jeb->dirty_size, jeb->used_size, + jeb->wasted_size, jeb->unchecked_size, c->sector_size); + BUG(); + } + + if (unlikely(c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size + + c->wasted_size + c->unchecked_size != c->flash_size)) { + JFFS2_ERROR("eeep, space accounting superblock info is screwed.\n"); + JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + erasing %#08x + bad %#08x + " + "wasted %#08x + unchecked %#08x != total %#08x.\n", + c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, + c->wasted_size, c->unchecked_size, c->flash_size); + BUG(); + } +} + +void +__jffs2_dbg_acct_sanity_check(struct jffs2_sb_info *c, + struct jffs2_eraseblock *jeb) +{ + spin_lock(&c->erase_completion_lock); + jffs2_dbg_acct_sanity_check_nolock(c, jeb); + spin_unlock(&c->erase_completion_lock); +} + +#endif /* JFFS2_DBG_SANITY_CHECKS */ + #ifdef JFFS2_DBG_PARANOIA_CHECKS /* * Check the fragtree. diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index 11ee75922a5..3a7b11c2dd8 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.h,v 1.10 2005/08/02 10:03:51 dedekind Exp $ + * $Id: debug.h,v 1.12 2005/08/05 10:43:47 dedekind Exp $ * */ #ifndef _JFFS2_DEBUG_H_ @@ -34,7 +34,7 @@ #define JFFS2_DBG_FRAGTREE2_MESSAGES #endif -/* Enable JFFS2 sanity checks by default */ +/* Sanity checks are supposed to be light-weight and enabled by default */ #define JFFS2_DBG_SANITY_CHECKS /* @@ -55,9 +55,9 @@ /* The prefixes of JFFS2 messages */ #define JFFS2_DBG_MSG_PREFIX "[JFFS2 DBG]" -#define JFFS2_ERR_MSG_PREFIX "JFFS2 error: " -#define JFFS2_WARN_MSG_PREFIX "JFFS2 warning: " -#define JFFS2_NOTICE_MSG_PREFIX "JFFS2 notice: " +#define JFFS2_ERR_MSG_PREFIX "JFFS2 error:" +#define JFFS2_WARN_MSG_PREFIX "JFFS2 warning:" +#define JFFS2_NOTICE_MSG_PREFIX "JFFS2 notice:" #define JFFS2_ERR_LVL KERN_ERR #define JFFS2_WARN_LVL KERN_WARNING @@ -67,26 +67,30 @@ /* JFFS2 message macros */ #define JFFS2_ERROR(fmt, ...) \ do { \ - printk(JFFS2_ERR_LVL JFFS2_ERR_MSG_PREFIX " %s: " \ - fmt, __FUNCTION__, ##__VA_ARGS__); \ + printk(JFFS2_ERR_LVL JFFS2_ERR_MSG_PREFIX \ + " %d,%s: " fmt, current->pid, \ + __FUNCTION__, ##__VA_ARGS__); \ } while(0) #define JFFS2_WARNING(fmt, ...) \ do { \ - printk(JFFS2_WARN_LVL JFFS2_WARN_MSG_PREFIX " %s: " \ - fmt, __FUNCTION__, ##__VA_ARGS__); \ + printk(JFFS2_WARN_LVL JFFS2_WARN_MSG_PREFIX \ + " %d,%s: " fmt, current->pid, \ + __FUNCTION__, ##__VA_ARGS__); \ } while(0) #define JFFS2_NOTICE(fmt, ...) \ do { \ - printk(JFFS2_NOTICE_LVL JFFS2_NOTICE_MSG_PREFIX " %s: " \ - fmt, __FUNCTION__, ##__VA_ARGS__); \ + printk(JFFS2_NOTICE_LVL JFFS2_NOTICE_MSG_PREFIX \ + " %d,%s: " fmt, current->pid, \ + __FUNCTION__, ##__VA_ARGS__); \ } while(0) #define JFFS2_DEBUG(fmt, ...) \ do { \ - printk(JFFS2_DBG_LVL JFFS2_DBG_MSG_PREFIX " %s: " \ - fmt, __FUNCTION__, ##__VA_ARGS__); \ + printk(JFFS2_DBG_LVL JFFS2_DBG_MSG_PREFIX \ + " %d,%s: " fmt, current->pid, \ + __FUNCTION__, ##__VA_ARGS__); \ } while(0) /* @@ -141,6 +145,14 @@ #endif +/* "Sanity" checks */ +void +__jffs2_dbg_acct_sanity_check_nolock(struct jffs2_sb_info *c, + struct jffs2_eraseblock *jeb); +void +__jffs2_dbg_acct_sanity_check(struct jffs2_sb_info *c, + struct jffs2_eraseblock *jeb); + /* "Paranoia" checks */ void __jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f); @@ -227,47 +239,11 @@ __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs); #define jffs2_dbg_dump_node(c, ofs) #endif /* !JFFS2_DBG_DUMPS */ -/* - * Sanity checks are supposed to be light-weight and enabled by default. - */ #ifdef JFFS2_DBG_SANITY_CHECKS -/* - * Check the space accounting of the file system and of - * the JFFS2 erasable block 'jeb'. - */ -static inline void -jffs2_dbg_acct_sanity_check_nolock(struct jffs2_sb_info *c, - struct jffs2_eraseblock *jeb) -{ - if (unlikely(jeb && jeb->used_size + jeb->dirty_size + - jeb->free_size + jeb->wasted_size + - jeb->unchecked_size != c->sector_size)) { - JFFS2_ERROR("eeep, space accounting for block at 0x%08x is screwed.\n", jeb->offset); - JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + wasted %#08x + unchecked " - "%#08x != total %#08x.\n", jeb->free_size, jeb->dirty_size, jeb->used_size, - jeb->wasted_size, jeb->unchecked_size, c->sector_size); - BUG(); - } - - if (unlikely(c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size - + c->wasted_size + c->unchecked_size != c->flash_size)) { - JFFS2_ERROR("eeep, space accounting superblock info is screwed.\n"); - JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + erasing %#08x + bad %#08x + " - "wasted %#08x + unchecked %#08x != total %#08x.\n", - c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, - c->wasted_size, c->unchecked_size, c->flash_size); - BUG(); - } -} - -static inline void -jffs2_dbg_acct_sanity_check(struct jffs2_sb_info *c, - struct jffs2_eraseblock *jeb) -{ - spin_lock(&c->erase_completion_lock); - jffs2_dbg_acct_sanity_check_nolock(c, jeb); - spin_unlock(&c->erase_completion_lock); -} +#define jffs2_dbg_acct_sanity_check(c, jeb) \ + __jffs2_dbg_acct_sanity_check(c, jeb) +#define jffs2_dbg_acct_sanity_check_nolock(c, jeb) \ + __jffs2_dbg_acct_sanity_check_nolock(c, jeb) #else #define jffs2_dbg_acct_sanity_check(c, jeb) #define jffs2_dbg_acct_sanity_check_nolock(c, jeb) diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index b5f73ab6553..cd366ab1f02 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.c,v 1.108 2005/08/04 11:39:59 dedekind Exp $ + * $Id: nodelist.c,v 1.109 2005/08/04 11:41:30 dedekind Exp $ * */ @@ -1010,21 +1010,14 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) frag = (rb_entry(root->rb_node, struct jffs2_node_frag, rb)); while(frag) { if (frag->rb.rb_left) { - JFFS2_DBG_FRAGTREE2("going left from frag (%p) %#04x-%#04x\n", - frag, frag->ofs, frag->ofs+frag->size); frag = frag_left(frag); continue; } if (frag->rb.rb_right) { - JFFS2_DBG_FRAGTREE2("going right from frag (%p) %#04x-%#04x\n", - frag, frag->ofs, frag->ofs+frag->size); frag = frag_right(frag); continue; } - JFFS2_DBG_FRAGTREE2("frag %#04x-%#04x: node %p, frags %d\n", - frag->ofs, frag->ofs+frag->size, frag->node, frag->node?frag->node->frags:0); - if (frag->node && !(--frag->node->frags)) { /* Not a hole, and it's the final remaining frag of this node. Free the node */ diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 12a3aaeb2f7..50a62dd33e3 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.138 2005/08/03 09:28:06 dedekind Exp $ + * $Id: readinode.c,v 1.139 2005/08/04 11:41:31 dedekind Exp $ * */ @@ -424,7 +424,7 @@ static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, len = right_size - *rdlen; } - JFFS2_DBG_READINODE("read more %d bytes.", len); + JFFS2_DBG_READINODE("read more %d bytes\n", len); err = jffs2_flash_read(c, offs, len, &retlen, bufstart); if (err) { -- cgit v1.2.3 From e27a9960af0506d84b9ca9dd3874b7d88901f230 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Thu, 16 Jun 2005 09:49:33 +0100 Subject: [MTD] Add Resident Flash Disk (RFD) support This type of flash translation layer (FTL) is used by the Embedded BIOS by General Software. It is known as the Resident Flash Disk (RFD), see: http://www.gensw.com/pages/prod/bios/rfd.htm Signed-off-by: Sean Young Signed-off-by: Thomas Gleixner --- drivers/mtd/Kconfig | 12 +- drivers/mtd/Makefile | 3 +- drivers/mtd/maps/Kconfig | 9 +- drivers/mtd/maps/ts5500_flash.c | 6 +- drivers/mtd/rfd_ftl.c | 855 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 873 insertions(+), 12 deletions(-) create mode 100644 drivers/mtd/rfd_ftl.c diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 027054dea03..843a1cbe086 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -1,4 +1,4 @@ -# $Id: Kconfig,v 1.7 2004/11/22 11:33:56 ijc Exp $ +# $Id: Kconfig,v 1.9 2005/06/16 08:49:29 sean Exp $ menu "Memory Technology Devices (MTD)" @@ -253,6 +253,16 @@ config INFTL permitted to copy, modify and distribute the code as you wish. Just not use it. +config RFD_FTL + tristate "Resident Flash Disk (Flash Translation Layer) support" + depends on MTD + ---help--- + This provides support for the flash translation layer known + as the Resident Flash Disk (RFD), as used by the Embedded BIOS + of General Software. + See http://www.gensw.com/pages/prod/bios/rfd.htm for further + information. + source "drivers/mtd/chips/Kconfig" source "drivers/mtd/maps/Kconfig" diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index e4ad588327f..cb16b7d478c 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -1,7 +1,7 @@ # # Makefile for the memory technology device drivers. # -# $Id: Makefile.common,v 1.5 2004/08/10 20:51:49 dwmw2 Exp $ +# $Id: Makefile.common,v 1.6 2005/06/16 08:49:29 sean Exp $ # Core functionality. mtd-y := mtdcore.o @@ -20,6 +20,7 @@ obj-$(CONFIG_MTD_BLOCK_RO) += mtdblock_ro.o mtd_blkdevs.o obj-$(CONFIG_FTL) += ftl.o mtd_blkdevs.o obj-$(CONFIG_NFTL) += nftl.o mtd_blkdevs.o obj-$(CONFIG_INFTL) += inftl.o mtd_blkdevs.o +obj-$(CONFIG_RFD_FTL) += rfd_ftl.o mtd_blkdevs.o nftl-objs := nftlcore.o nftlmount.o inftl-objs := inftlcore.o inftlmount.o diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 44781a83b2e..aa5d71f8d81 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -97,14 +97,11 @@ config MTD_TS5500 depends on X86 && MTD_JEDECPROBE && MTD_PARTITIONS help This provides a driver for the on-board flash of the Technologic - System's TS-5500 board. The flash is split into 3 partitions + System's TS-5500 board. The 2MB flash is split into 3 partitions which are accessed as separate MTD devices. - mtd0 and mtd2 are the two BIOS drives. Unfortunately the BIOS - uses a proprietary flash translation layer from General Software, - which is not supported (the drives cannot be mounted). You can - create your own file system (jffs for example), but the BIOS - won't be able to boot from it. + mtd0 and mtd2 are the two BIOS drives, which use the resident + flash disk (RFD) flash translation layer. mtd1 allows you to reprogram your BIOS. BE VERY CAREFUL. diff --git a/drivers/mtd/maps/ts5500_flash.c b/drivers/mtd/maps/ts5500_flash.c index 3ebd90f5650..286dd82e8b8 100644 --- a/drivers/mtd/maps/ts5500_flash.c +++ b/drivers/mtd/maps/ts5500_flash.c @@ -19,13 +19,11 @@ * * Note: * - In order for detection to work, jumper 3 must be set. - * - Drive A and B use a proprietary FTL from General Software which isn't - * supported as of yet so standard drives can't be mounted; you can create - * your own (e.g. jffs) file system. + * - Drive A and B use the resident flash disk (RFD) flash translation layer. * - If you have created your own jffs file system and the bios overwrites * it during boot, try disabling Drive A: and B: in the boot order. * - * $Id: ts5500_flash.c,v 1.2 2004/11/28 09:40:40 dwmw2 Exp $ + * $Id: ts5500_flash.c,v 1.3 2005/06/16 08:49:30 sean Exp $ */ #include diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c new file mode 100644 index 00000000000..7b9f359f04b --- /dev/null +++ b/drivers/mtd/rfd_ftl.c @@ -0,0 +1,855 @@ +/* + * rfd_ftl.c -- resident flash disk (flash translation layer) + * + * Copyright (C) 2005 Sean Young + * + * $Id: rfd_ftl.c,v 1.4 2005/07/31 22:49:14 sean Exp $ + * + * This type of flash translation layer (FTL) is used by the Embedded BIOS + * by General Software. It is known as the Resident Flash Disk (RFD), see: + * + * http://www.gensw.com/pages/prod/bios/rfd.htm + * + * based on ftl.c + */ + +#include +#include +#include +#include +#include + +#include + +#define const_cpu_to_le16 __constant_cpu_to_le16 + +static int block_size = 0; +module_param(block_size, int, 0); +MODULE_PARM_DESC(block_size, "Block size to use by RFD, defaults to erase unit size"); + +#define PREFIX "rfd_ftl: " + +/* Major device # for FTL device */ + +/* A request for this major has been sent to device@lanana.org */ +#ifndef RFD_FTL_MAJOR +#define RFD_FTL_MAJOR 95 +#endif + +/* Maximum number of partitions in an FTL region */ +#define PART_BITS 4 + +/* An erase unit should start with this value */ +#define RFD_MAGIC 0x9193 + +/* the second value is 0xffff or 0xffc8; function unknown */ + +/* the third value is always 0xffff, ignored */ + +/* next is an array of mapping for each corresponding sector */ +#define HEADER_MAP_OFFSET 3 +#define SECTOR_DELETED 0x0000 +#define SECTOR_ZERO 0xfffe +#define SECTOR_FREE 0xffff + +#define SECTOR_SIZE 512 + +#define SECTORS_PER_TRACK 63 + +struct block { + enum { + BLOCK_OK, + BLOCK_ERASING, + BLOCK_ERASED, + BLOCK_FAILED + } state; + int free_sectors; + int used_sectors; + int erases; + u_long offset; +}; + +struct partition { + struct mtd_blktrans_dev mbd; + + u_int block_size; /* size of erase unit */ + u_int total_blocks; /* number of erase units */ + u_int header_sectors_per_block; /* header sectors in erase unit */ + u_int data_sectors_per_block; /* data sectors in erase unit */ + u_int sector_count; /* sectors in translated disk */ + u_int header_size; /* bytes in header sector */ + int reserved_block; /* block next up for reclaim */ + int current_block; /* block to write to */ + u16 *header_cache; /* cached header */ + + int is_reclaiming; + int cylinders; + int errors; + u_long *sector_map; + struct block *blocks; +}; + +static int rfd_ftl_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf); + +static int build_block_map(struct partition *part, int block_no) +{ + struct block *block = &part->blocks[block_no]; + int i; + + block->offset = part->block_size * block_no; + + if (le16_to_cpu(part->header_cache[0]) != RFD_MAGIC) { + block->state = BLOCK_ERASED; /* assumption */ + block->free_sectors = part->data_sectors_per_block; + part->reserved_block = block_no; + return 1; + } + + block->state = BLOCK_OK; + + for (i=0; idata_sectors_per_block; i++) { + u16 entry; + + entry = le16_to_cpu(part->header_cache[HEADER_MAP_OFFSET + i]); + + if (entry == SECTOR_DELETED) + continue; + + if (entry == SECTOR_FREE) { + block->free_sectors++; + continue; + } + + if (entry == SECTOR_ZERO) + entry = 0; + + if (entry >= part->sector_count) { + printk(KERN_NOTICE PREFIX + "'%s': unit #%d: entry %d corrupt, " + "sector %d out of range\n", + part->mbd.mtd->name, block_no, i, entry); + continue; + } + + if (part->sector_map[entry] != -1) { + printk(KERN_NOTICE PREFIX + "'%s': more than one entry for sector %d\n", + part->mbd.mtd->name, entry); + part->errors = 1; + continue; + } + + part->sector_map[entry] = block->offset + + (i + part->header_sectors_per_block) * SECTOR_SIZE; + + block->used_sectors++; + } + + if (block->free_sectors == part->data_sectors_per_block) + part->reserved_block = block_no; + + return 0; +} + +static int scan_header(struct partition *part) +{ + int sectors_per_block; + int i, rc = -ENOMEM; + int blocks_found; + size_t retlen; + + sectors_per_block = part->block_size / SECTOR_SIZE; + part->total_blocks = part->mbd.mtd->size / part->block_size; + + if (part->total_blocks < 2) + return -ENOENT; + + /* each erase block has three bytes header, followed by the map */ + part->header_sectors_per_block = + ((HEADER_MAP_OFFSET + sectors_per_block) * + sizeof(u16) + SECTOR_SIZE - 1) / SECTOR_SIZE; + + part->data_sectors_per_block = sectors_per_block - + part->header_sectors_per_block; + + part->header_size = (HEADER_MAP_OFFSET + + part->data_sectors_per_block) * sizeof(u16); + + part->cylinders = (part->data_sectors_per_block * + (part->total_blocks - 1) - 1) / SECTORS_PER_TRACK; + + part->sector_count = part->cylinders * SECTORS_PER_TRACK; + + part->current_block = -1; + part->reserved_block = -1; + part->is_reclaiming = 0; + + part->header_cache = kmalloc(part->header_size, GFP_KERNEL); + if (!part->header_cache) + goto err; + + part->blocks = kcalloc(part->total_blocks, sizeof(struct block), + GFP_KERNEL); + if (!part->blocks) + goto err; + + part->sector_map = vmalloc(part->sector_count * sizeof(u_long)); + if (!part->sector_map) { + printk(KERN_ERR PREFIX "'%s': unable to allocate memory for " + "sector map", part->mbd.mtd->name); + goto err; + } + + for (i=0; isector_count; i++) + part->sector_map[i] = -1; + + for (i=0, blocks_found=0; itotal_blocks; i++) { + rc = part->mbd.mtd->read(part->mbd.mtd, + i * part->block_size, part->header_size, + &retlen, (u_char*)part->header_cache); + + if (!rc && retlen != part->header_size) + rc = -EIO; + + if (rc) + goto err; + + if (!build_block_map(part, i)) + blocks_found++; + } + + if (blocks_found == 0) { + printk(KERN_NOTICE PREFIX "no RFD magic found in '%s'\n", + part->mbd.mtd->name); + rc = -ENOENT; + goto err; + } + + if (part->reserved_block == -1) { + printk(KERN_NOTICE PREFIX "'%s': no empty erase unit found\n", + part->mbd.mtd->name); + + part->errors = 1; + } + + return 0; + +err: + vfree(part->sector_map); + kfree(part->header_cache); + kfree(part->blocks); + + return rc; +} + +static int rfd_ftl_readsect(struct mtd_blktrans_dev *dev, u_long sector, char *buf) +{ + struct partition *part = (struct partition*)dev; + u_long addr; + size_t retlen; + int rc; + + if (sector >= part->sector_count) + return -EIO; + + addr = part->sector_map[sector]; + if (addr != -1) { + rc = part->mbd.mtd->read(part->mbd.mtd, addr, SECTOR_SIZE, + &retlen, (u_char*)buf); + if (!rc && retlen != SECTOR_SIZE) + rc = -EIO; + + if (rc) { + printk(KERN_WARNING PREFIX "error reading '%s' at " + "0x%lx\n", part->mbd.mtd->name, addr); + return rc; + } + } else + memset(buf, 0, SECTOR_SIZE); + + return 0; +} + +static void erase_callback(struct erase_info *erase) +{ + struct partition *part; + u16 magic; + int i, rc; + size_t retlen; + + part = (struct partition*)erase->priv; + + i = erase->addr / part->block_size; + if (i >= part->total_blocks || part->blocks[i].offset != erase->addr) { + printk(KERN_ERR PREFIX "erase callback for unknown offset %x " + "on '%s'\n", erase->addr, part->mbd.mtd->name); + return; + } + + if (erase->state != MTD_ERASE_DONE) { + printk(KERN_WARNING PREFIX "erase failed at 0x%x on '%s', " + "state %d\n", erase->addr, + part->mbd.mtd->name, erase->state); + + part->blocks[i].state = BLOCK_FAILED; + part->blocks[i].free_sectors = 0; + part->blocks[i].used_sectors = 0; + + kfree(erase); + + return; + } + + magic = const_cpu_to_le16(RFD_MAGIC); + + part->blocks[i].state = BLOCK_ERASED; + part->blocks[i].free_sectors = part->data_sectors_per_block; + part->blocks[i].used_sectors = 0; + part->blocks[i].erases++; + + rc = part->mbd.mtd->write(part->mbd.mtd, + part->blocks[i].offset, sizeof(magic), &retlen, + (u_char*)&magic); + + if (!rc && retlen != sizeof(magic)) + rc = -EIO; + + if (rc) { + printk(KERN_NOTICE PREFIX "'%s': unable to write RFD " + "header at 0x%lx\n", + part->mbd.mtd->name, + part->blocks[i].offset); + part->blocks[i].state = BLOCK_FAILED; + } + else + part->blocks[i].state = BLOCK_OK; + + kfree(erase); +} + +static int erase_block(struct partition *part, int block) +{ + struct erase_info *erase; + int rc = -ENOMEM; + + erase = kmalloc(sizeof(struct erase_info), GFP_KERNEL); + if (!erase) + goto err; + + erase->mtd = part->mbd.mtd; + erase->callback = erase_callback; + erase->addr = part->blocks[block].offset; + erase->len = part->block_size; + erase->priv = (u_long)part; + + part->blocks[block].state = BLOCK_ERASING; + part->blocks[block].free_sectors = 0; + + rc = part->mbd.mtd->erase(part->mbd.mtd, erase); + + if (rc) { + printk(KERN_WARNING PREFIX "erase of region %x,%x on '%s' " + "failed\n", erase->addr, erase->len, + part->mbd.mtd->name); + kfree(erase); + } + +err: + return rc; +} + +static int move_block_contents(struct partition *part, int block_no, u_long *old_sector) +{ + void *sector_data; + u16 *map; + size_t retlen; + int i, rc = -ENOMEM; + + part->is_reclaiming = 1; + + sector_data = kmalloc(SECTOR_SIZE, GFP_KERNEL); + if (!sector_data) + goto err3; + + map = kmalloc(part->header_size, GFP_KERNEL); + if (!map) + goto err2; + + rc = part->mbd.mtd->read(part->mbd.mtd, + part->blocks[block_no].offset, part->header_size, + &retlen, (u_char*)map); + + if (!rc && retlen != part->header_size) + rc = -EIO; + + if (rc) { + printk(KERN_NOTICE PREFIX "error reading '%s' at " + "0x%lx\n", part->mbd.mtd->name, + part->blocks[block_no].offset); + + goto err; + } + + for (i=0; idata_sectors_per_block; i++) { + u16 entry = le16_to_cpu(map[HEADER_MAP_OFFSET + i]); + u_long addr; + + + if (entry == SECTOR_FREE || entry == SECTOR_DELETED) + continue; + + if (entry == SECTOR_ZERO) + entry = 0; + + /* already warned about and ignored in build_block_map() */ + if (entry >= part->sector_count) + continue; + + addr = part->blocks[block_no].offset + + (i + part->header_sectors_per_block) * SECTOR_SIZE; + + if (*old_sector == addr) { + *old_sector = -1; + if (!part->blocks[block_no].used_sectors--) { + rc = erase_block(part, block_no); + break; + } + continue; + } + rc = part->mbd.mtd->read(part->mbd.mtd, addr, + SECTOR_SIZE, &retlen, sector_data); + + if (!rc && retlen != SECTOR_SIZE) + rc = -EIO; + + if (rc) { + printk(KERN_NOTICE PREFIX "'%s': Unable to " + "read sector for relocation\n", + part->mbd.mtd->name); + + goto err; + } + + rc = rfd_ftl_writesect((struct mtd_blktrans_dev*)part, + entry, sector_data); + + if (rc) + goto err; + } + +err: + kfree(map); +err2: + kfree(sector_data); +err3: + part->is_reclaiming = 0; + + return rc; +} + +static int reclaim_block(struct partition *part, u_long *old_sector) +{ + int block, best_block, score, old_sector_block; + int rc; + + /* we have a race if sync doesn't exist */ + if (part->mbd.mtd->sync) + part->mbd.mtd->sync(part->mbd.mtd); + + score = 0x7fffffff; /* MAX_INT */ + best_block = -1; + if (*old_sector != -1) + old_sector_block = *old_sector / part->block_size; + else + old_sector_block = -1; + + for (block=0; blocktotal_blocks; block++) { + int this_score; + + if (block == part->reserved_block) + continue; + + /* + * Postpone reclaiming if there is a free sector as + * more removed sectors is more efficient (have to move + * less). + */ + if (part->blocks[block].free_sectors) + return 0; + + this_score = part->blocks[block].used_sectors; + + if (block == old_sector_block) + this_score--; + else { + /* no point in moving a full block */ + if (part->blocks[block].used_sectors == + part->data_sectors_per_block) + continue; + } + + this_score += part->blocks[block].erases; + + if (this_score < score) { + best_block = block; + score = this_score; + } + } + + if (best_block == -1) + return -ENOSPC; + + part->current_block = -1; + part->reserved_block = best_block; + + pr_debug("reclaim_block: reclaiming block #%d with %d used " + "%d free sectors\n", best_block, + part->blocks[best_block].used_sectors, + part->blocks[best_block].free_sectors); + + if (part->blocks[best_block].used_sectors) + rc = move_block_contents(part, best_block, old_sector); + else + rc = erase_block(part, best_block); + + return rc; +} + +/* + * IMPROVE: It would be best to choose the block with the most deleted sectors, + * because if we fill that one up first it'll have the most chance of having + * the least live sectors at reclaim. + */ +static int find_free_block(const struct partition *part) +{ + int block, stop; + + block = part->current_block == -1 ? + jiffies % part->total_blocks : part->current_block; + stop = block; + + do { + if (part->blocks[block].free_sectors && + block != part->reserved_block) + return block; + + if (++block >= part->total_blocks) + block = 0; + + } while (block != stop); + + return -1; +} + +static int find_writeable_block(struct partition *part, u_long *old_sector) +{ + int rc, block; + size_t retlen; + + block = find_free_block(part); + + if (block == -1) { + if (!part->is_reclaiming) { + rc = reclaim_block(part, old_sector); + if (rc) + goto err; + + block = find_free_block(part); + } + + if (block == -1) { + rc = -ENOSPC; + goto err; + } + } + + rc = part->mbd.mtd->read(part->mbd.mtd, part->blocks[block].offset, + part->header_size, &retlen, (u_char*)part->header_cache); + + if (!rc && retlen != part->header_size) + rc = -EIO; + + if (rc) { + printk(KERN_NOTICE PREFIX "'%s': unable to read header at " + "0x%lx\n", part->mbd.mtd->name, + part->blocks[block].offset); + goto err; + } + + part->current_block = block; + +err: + return rc; +} + +static int mark_sector_deleted(struct partition *part, u_long old_addr) +{ + int block, offset, rc; + u_long addr; + size_t retlen; + u16 del = const_cpu_to_le16(SECTOR_DELETED); + + block = old_addr / part->block_size; + offset = (old_addr % part->block_size) / SECTOR_SIZE - + part->header_sectors_per_block; + + addr = part->blocks[block].offset + + (HEADER_MAP_OFFSET + offset) * sizeof(u16); + rc = part->mbd.mtd->write(part->mbd.mtd, addr, + sizeof(del), &retlen, (u_char*)&del); + + if (!rc && retlen != sizeof(del)) + rc = -EIO; + + if (rc) { + printk(KERN_WARNING PREFIX "error writing '%s' at " + "0x%lx\n", part->mbd.mtd->name, addr); + if (rc) + goto err; + } + if (block == part->current_block) + part->header_cache[offset + HEADER_MAP_OFFSET] = del; + + part->blocks[block].used_sectors--; + + if (!part->blocks[block].used_sectors && + !part->blocks[block].free_sectors) + rc = erase_block(part, block); + +err: + return rc; +} + +static int find_free_sector(const struct partition *part, const struct block *block) +{ + int i, stop; + + i = stop = part->data_sectors_per_block - block->free_sectors; + + do { + if (le16_to_cpu(part->header_cache[HEADER_MAP_OFFSET + i]) + == SECTOR_FREE) + return i; + + if (++i == part->data_sectors_per_block) + i = 0; + } + while(i != stop); + + return -1; +} + +static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf, ulong *old_addr) +{ + struct partition *part = (struct partition*)dev; + struct block *block; + u_long addr; + int i; + int rc; + size_t retlen; + u16 entry; + + if (part->current_block == -1 || + !part->blocks[part->current_block].free_sectors) { + + rc = find_writeable_block(part, old_addr); + if (rc) + goto err; + } + + block = &part->blocks[part->current_block]; + + i = find_free_sector(part, block); + + if (i < 0) { + rc = -ENOSPC; + goto err; + } + + addr = (i + part->header_sectors_per_block) * SECTOR_SIZE + + block->offset; + rc = part->mbd.mtd->write(part->mbd.mtd, + addr, SECTOR_SIZE, &retlen, (u_char*)buf); + + if (!rc && retlen != SECTOR_SIZE) + rc = -EIO; + + if (rc) { + printk(KERN_WARNING PREFIX "error writing '%s' at 0x%lx\n", + part->mbd.mtd->name, addr); + if (rc) + goto err; + } + + part->sector_map[sector] = addr; + + entry = cpu_to_le16(sector == 0 ? SECTOR_ZERO : sector); + + part->header_cache[i + HEADER_MAP_OFFSET] = entry; + + addr = block->offset + (HEADER_MAP_OFFSET + i) * sizeof(u16); + rc = part->mbd.mtd->write(part->mbd.mtd, addr, + sizeof(entry), &retlen, (u_char*)&entry); + + if (!rc && retlen != sizeof(entry)) + rc = -EIO; + + if (rc) { + printk(KERN_WARNING PREFIX "error writing '%s' at 0x%lx\n", + part->mbd.mtd->name, addr); + if (rc) + goto err; + } + block->used_sectors++; + block->free_sectors--; + +err: + return rc; +} + +static int rfd_ftl_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf) +{ + struct partition *part = (struct partition*)dev; + u_long old_addr; + int i; + int rc = 0; + + pr_debug("rfd_ftl_writesect(sector=0x%lx)\n", sector); + + if (part->reserved_block == -1) { + rc = -EACCES; + goto err; + } + + if (sector >= part->sector_count) { + rc = -EIO; + goto err; + } + + old_addr = part->sector_map[sector]; + + for (i=0; isector_map[sector] = -1; + + if (old_addr != -1) + rc = mark_sector_deleted(part, old_addr); + +err: + return rc; +} + +static int rfd_ftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo) +{ + struct partition *part = (struct partition*)dev; + + geo->heads = 1; + geo->sectors = SECTORS_PER_TRACK; + geo->cylinders = part->cylinders; + + return 0; +} + +static void rfd_ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) +{ + struct partition *part; + + if (mtd->type != MTD_NORFLASH) + return; + + part = kcalloc(1, sizeof(struct partition), GFP_KERNEL); + if (!part) + return; + + part->mbd.mtd = mtd; + + if (block_size) + part->block_size = block_size; + else { + if (!mtd->erasesize) { + printk(KERN_NOTICE PREFIX "please provide block_size"); + return; + } + else + part->block_size = mtd->erasesize; + } + + if (scan_header(part) == 0) { + part->mbd.size = part->sector_count; + part->mbd.blksize = SECTOR_SIZE; + part->mbd.tr = tr; + part->mbd.devnum = -1; + if (!(mtd->flags & MTD_WRITEABLE)) + part->mbd.readonly = 1; + else if (part->errors) { + printk(KERN_NOTICE PREFIX "'%s': errors found, " + "setting read-only", mtd->name); + part->mbd.readonly = 1; + } + + printk(KERN_INFO PREFIX "name: '%s' type: %d flags %x\n", + mtd->name, mtd->type, mtd->flags); + + if (!add_mtd_blktrans_dev((void*)part)) + return; + } + + kfree(part); +} + +static void rfd_ftl_remove_dev(struct mtd_blktrans_dev *dev) +{ + struct partition *part = (struct partition*)dev; + int i; + + for (i=0; itotal_blocks; i++) { + pr_debug("rfd_ftl_remove_dev:'%s': erase unit #%02d: %d erases\n", + part->mbd.mtd->name, i, part->blocks[i].erases); + } + + del_mtd_blktrans_dev(dev); + vfree(part->sector_map); + kfree(part->header_cache); + kfree(part->blocks); + kfree(part); +} + +struct mtd_blktrans_ops rfd_ftl_tr = { + .name = "rfd", + .major = RFD_FTL_MAJOR, + .part_bits = PART_BITS, + .readsect = rfd_ftl_readsect, + .writesect = rfd_ftl_writesect, + .getgeo = rfd_ftl_getgeo, + .add_mtd = rfd_ftl_add_mtd, + .remove_dev = rfd_ftl_remove_dev, + .owner = THIS_MODULE, +}; + +static int __init init_rfd_ftl(void) +{ + return register_mtd_blktrans(&rfd_ftl_tr); +} + +static void __exit cleanup_rfd_ftl(void) +{ + deregister_mtd_blktrans(&rfd_ftl_tr); +} + +module_init(init_rfd_ftl); +module_exit(cleanup_rfd_ftl); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Sean Young "); +MODULE_DESCRIPTION("Support code for RFD Flash Translation Layer, " + "used by General Software's Embedded BIOS"); + -- cgit v1.2.3 From 4843653cab0db036399f77d9355db31ce39cb8b9 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 6 Aug 2005 05:16:52 +0100 Subject: [MTD] cleanups to cfi_cmdset_0001 This includes improved error handling/reporting plus some other message cleanups. Signed-off-by: Nicolas Pitre Signed-off-by: Thomas Gleixner --- drivers/mtd/chips/cfi_cmdset_0001.c | 127 ++++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 56 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 1e99dffcc6a..308855e80f6 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -4,7 +4,7 @@ * * (C) 2000 Red Hat. GPL'd * - * $Id: cfi_cmdset_0001.c,v 1.180 2005/07/20 21:01:13 tpoynor Exp $ + * $Id: cfi_cmdset_0001.c,v 1.181 2005/08/06 04:16:48 nico Exp $ * * * 10/10/2000 Nicolas Pitre @@ -438,7 +438,7 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd) } for (i=0; inumeraseregions;i++){ - printk(KERN_DEBUG "%d: offset=0x%x,size=0x%x,blocks=%d\n", + printk(KERN_DEBUG "erase region %d: offset=0x%x,size=0x%x,blocks=%d\n", i,mtd->eraseregions[i].offset, mtd->eraseregions[i].erasesize, mtd->eraseregions[i].numblocks); @@ -663,8 +663,8 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr break; if (time_after(jiffies, timeo)) { - printk(KERN_ERR "Waiting for chip to be ready timed out. Status %lx\n", - status.x[0]); + printk(KERN_ERR "%s: Waiting for chip to be ready timed out. Status %lx\n", + map->name, status.x[0]); return -EIO; } spin_unlock(chip->mutex); @@ -711,8 +711,8 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr map_write(map, CMD(0x70), adr); chip->state = FL_ERASING; chip->oldstate = FL_READY; - printk(KERN_ERR "Chip not ready after erase " - "suspended: status = 0x%lx\n", status.x[0]); + printk(KERN_ERR "%s: Chip not ready after erase " + "suspended: status = 0x%lx\n", map->name, status.x[0]); return -EIO; } @@ -819,7 +819,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad DISABLE_VPP(map); break; default: - printk(KERN_ERR "put_chip() called with oldstate %d!!\n", chip->oldstate); + printk(KERN_ERR "%s: put_chip() called with oldstate %d!!\n", map->name, chip->oldstate); } wake_up(&chip->wq); } @@ -1130,7 +1130,7 @@ static void cfi_intelext_unpoint (struct mtd_info *mtd, u_char *addr, loff_t fro if(chip->ref_point_counter == 0) chip->state = FL_READY; } else - printk(KERN_ERR "Warning: unpoint called on non pointed region\n"); /* Should this give an error? */ + printk(KERN_ERR "%s: Warning: unpoint called on non pointed region\n", map->name); /* Should this give an error? */ put_chip(map, chip, chip->start); spin_unlock(chip->mutex); @@ -1271,9 +1271,10 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, /* OK Still waiting */ if (time_after(jiffies, timeo)) { + map_write(map, CMD(0x70), adr); chip->state = FL_STATUS; xip_enable(map, chip, adr); - printk(KERN_ERR "waiting for chip to be ready timed out in word write\n"); + printk(KERN_ERR "%s: word write error (status timeout)\n", map->name); ret = -EIO; goto out; } @@ -1285,7 +1286,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, if (!z) { chip->word_write_time--; if (!chip->word_write_time) - chip->word_write_time++; + chip->word_write_time = 1; } if (z > 1) chip->word_write_time++; @@ -1293,19 +1294,31 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, /* Done and happy. */ chip->state = FL_STATUS; - /* check for lock bit */ - if (map_word_bitsset(map, status, CMD(0x02))) { - /* clear status */ + /* check for errors */ + if (map_word_bitsset(map, status, CMD(0x1a))) { + unsigned long chipstatus = MERGESTATUS(status); + + /* reset status */ map_write(map, CMD(0x50), adr); - /* put back into read status register mode */ map_write(map, CMD(0x70), adr); - ret = -EROFS; + xip_enable(map, chip, adr); + + if (chipstatus & 0x02) { + ret = -EROFS; + } else if (chipstatus & 0x08) { + printk(KERN_ERR "%s: word write error (bad VPP)\n", map->name); + ret = -EIO; + } else { + printk(KERN_ERR "%s: word write error (status 0x%lx)\n", map->name, chipstatus); + ret = -EINVAL; + } + + goto out; } xip_enable(map, chip, adr); out: put_chip(map, chip, adr); spin_unlock(chip->mutex); - return ret; } @@ -1456,8 +1469,8 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, map_write(map, CMD(0x50), cmd_adr); map_write(map, CMD(0x70), cmd_adr); xip_enable(map, chip, cmd_adr); - printk(KERN_ERR "Chip not ready for buffer write. status = %lx, Xstatus = %lx\n", - status.x[0], Xstatus.x[0]); + printk(KERN_ERR "%s: Chip not ready for buffer write. status = %lx, Xstatus = %lx\n", + map->name, status.x[0], Xstatus.x[0]); ret = -EIO; goto out; } @@ -1516,9 +1529,10 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, /* OK Still waiting */ if (time_after(jiffies, timeo)) { + map_write(map, CMD(0x70), cmd_adr); chip->state = FL_STATUS; xip_enable(map, chip, cmd_adr); - printk(KERN_ERR "waiting for chip to be ready timed out in bufwrite\n"); + printk(KERN_ERR "%s: buffer write error (status timeout)\n", map->name); ret = -EIO; goto out; } @@ -1530,7 +1544,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, if (!z) { chip->buffer_write_time--; if (!chip->buffer_write_time) - chip->buffer_write_time++; + chip->buffer_write_time = 1; } if (z > 1) chip->buffer_write_time++; @@ -1538,13 +1552,26 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, /* Done and happy. */ chip->state = FL_STATUS; - /* check for lock bit */ - if (map_word_bitsset(map, status, CMD(0x02))) { - /* clear status */ + /* check for errors */ + if (map_word_bitsset(map, status, CMD(0x1a))) { + unsigned long chipstatus = MERGESTATUS(status); + + /* reset status */ map_write(map, CMD(0x50), cmd_adr); - /* put back into read status register mode */ - map_write(map, CMD(0x70), adr); - ret = -EROFS; + map_write(map, CMD(0x70), cmd_adr); + xip_enable(map, chip, cmd_adr); + + if (chipstatus & 0x02) { + ret = -EROFS; + } else if (chipstatus & 0x08) { + printk(KERN_ERR "%s: buffer write error (bad VPP)\n", map->name); + ret = -EIO; + } else { + printk(KERN_ERR "%s: buffer write error (status 0x%lx)\n", map->name, chipstatus); + ret = -EINVAL; + } + + goto out; } xip_enable(map, chip, cmd_adr); @@ -1685,16 +1712,10 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, /* OK Still waiting */ if (time_after(jiffies, timeo)) { - map_word Xstatus; map_write(map, CMD(0x70), adr); chip->state = FL_STATUS; - Xstatus = map_read(map, adr); - /* Clear status bits */ - map_write(map, CMD(0x50), adr); - map_write(map, CMD(0x70), adr); xip_enable(map, chip, adr); - printk(KERN_ERR "waiting for erase at %08lx to complete timed out. status = %lx, Xstatus = %lx.\n", - adr, status.x[0], Xstatus.x[0]); + printk(KERN_ERR "%s: block erase error: (status timeout)\n", map->name); ret = -EIO; goto out; } @@ -1708,43 +1729,40 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, chip->state = FL_STATUS; status = map_read(map, adr); - /* check for lock bit */ + /* check for errors */ if (map_word_bitsset(map, status, CMD(0x3a))) { - unsigned long chipstatus; + unsigned long chipstatus = MERGESTATUS(status); /* Reset the error bits */ map_write(map, CMD(0x50), adr); map_write(map, CMD(0x70), adr); xip_enable(map, chip, adr); - chipstatus = MERGESTATUS(status); - if ((chipstatus & 0x30) == 0x30) { - printk(KERN_NOTICE "Chip reports improper command sequence: status 0x%lx\n", chipstatus); - ret = -EIO; + printk(KERN_ERR "%s: block erase error: (bad command sequence, status 0x%lx)\n", map->name, chipstatus); + ret = -EINVAL; } else if (chipstatus & 0x02) { /* Protection bit set */ ret = -EROFS; } else if (chipstatus & 0x8) { /* Voltage */ - printk(KERN_WARNING "Chip reports voltage low on erase: status 0x%lx\n", chipstatus); + printk(KERN_ERR "%s: block erase error: (bad VPP)\n", map->name); ret = -EIO; - } else if (chipstatus & 0x20) { - if (retries--) { - printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%lx. Retrying...\n", adr, chipstatus); - timeo = jiffies + HZ; - put_chip(map, chip, adr); - spin_unlock(chip->mutex); - goto retry; - } - printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%lx\n", adr, chipstatus); + } else if (chipstatus & 0x20 && retries--) { + printk(KERN_DEBUG "block erase failed at 0x%08lx: status 0x%lx. Retrying...\n", adr, chipstatus); + timeo = jiffies + HZ; + put_chip(map, chip, adr); + spin_unlock(chip->mutex); + goto retry; + } else { + printk(KERN_ERR "%s: block erase failed at 0x%08lx (status 0x%lx)\n", map->name, adr, chipstatus); ret = -EIO; } - } else { - xip_enable(map, chip, adr); - ret = 0; + + goto out; } + xip_enable(map, chip, adr); out: put_chip(map, chip, adr); spin_unlock(chip->mutex); return ret; @@ -1887,13 +1905,10 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip /* OK Still waiting */ if (time_after(jiffies, timeo)) { - map_word Xstatus; map_write(map, CMD(0x70), adr); chip->state = FL_STATUS; - Xstatus = map_read(map, adr); xip_enable(map, chip, adr); - printk(KERN_ERR "waiting for unlock to complete timed out. status = %lx, Xstatus = %lx.\n", - status.x[0], Xstatus.x[0]); + printk(KERN_ERR "%s: block unlock error: (status timeout)\n", map->name); put_chip(map, chip, adr); spin_unlock(chip->mutex); return -EIO; -- cgit v1.2.3 From 638d983840bb64e02c29bdd6160bb9963f4090f7 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 6 Aug 2005 05:40:46 +0100 Subject: {MTD] add support for Intel's "Sibley" flash This updates the Primary Vendor-Specific Extended Query parsing to version 1.4 in order to get the information about the Configurable Programming Mode regions implemented in the Sibley flash, as well as selecting the appropriate write command code. This flash does not behave like traditional NOR flash when writing data. While mtdblock should just work, further changes are needed for JFFS2 use. Signed-off-by: Nicolas Pitre Signed-off-by: Thomas Gleixner --- drivers/mtd/chips/cfi_cmdset_0001.c | 88 +++++++++++++++++++++++++++---------- drivers/mtd/chips/gen_probe.c | 3 +- include/linux/mtd/cfi.h | 13 +++++- include/linux/mtd/mtd.h | 14 +++++- include/mtd/mtd-abi.h | 3 +- 5 files changed, 92 insertions(+), 29 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 308855e80f6..10c50604bcd 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -4,7 +4,7 @@ * * (C) 2000 Red Hat. GPL'd * - * $Id: cfi_cmdset_0001.c,v 1.181 2005/08/06 04:16:48 nico Exp $ + * $Id: cfi_cmdset_0001.c,v 1.182 2005/08/06 04:40:41 nico Exp $ * * * 10/10/2000 Nicolas Pitre @@ -105,6 +105,7 @@ static struct mtd_chip_driver cfi_intelext_chipdrv = { static void cfi_tell_features(struct cfi_pri_intelext *extp) { int i; + printk(" Extended Query version %c.%c\n", extp->MajorVersion, extp->MinorVersion); printk(" Feature/Command Support: %4.4X\n", extp->FeatureSupport); printk(" - Chip Erase: %s\n", extp->FeatureSupport&1?"supported":"unsupported"); printk(" - Suspend Erase: %s\n", extp->FeatureSupport&2?"supported":"unsupported"); @@ -116,7 +117,8 @@ static void cfi_tell_features(struct cfi_pri_intelext *extp) printk(" - Page-mode read: %s\n", extp->FeatureSupport&128?"supported":"unsupported"); printk(" - Synchronous read: %s\n", extp->FeatureSupport&256?"supported":"unsupported"); printk(" - Simultaneous operations: %s\n", extp->FeatureSupport&512?"supported":"unsupported"); - for (i=10; i<32; i++) { + printk(" - Extended Flash Array: %s\n", extp->FeatureSupport&1024?"supported":"unsupported"); + for (i=11; i<32; i++) { if (extp->FeatureSupport & (1<BlkStatusRegMask); printk(" - Lock Bit Active: %s\n", extp->BlkStatusRegMask&1?"yes":"no"); - printk(" - Valid Bit Active: %s\n", extp->BlkStatusRegMask&2?"yes":"no"); - for (i=2; i<16; i++) { + printk(" - Lock-Down Bit Active: %s\n", extp->BlkStatusRegMask&2?"yes":"no"); + for (i=2; i<3; i++) { if (extp->BlkStatusRegMask & (1<BlkStatusRegMask&16?"yes":"no"); + printk(" - EFA Lock-Down Bit: %s\n", extp->BlkStatusRegMask&32?"yes":"no"); + for (i=6; i<16; i++) { + if (extp->BlkStatusRegMask & (1<VccOptimal >> 4, extp->VccOptimal & 0xf); if (extp->VppOptimal) @@ -253,7 +261,7 @@ read_pri_intelext(struct map_info *map, __u16 adr) return NULL; if (extp->MajorVersion != '1' || - (extp->MinorVersion < '0' || extp->MinorVersion > '3')) { + (extp->MinorVersion < '0' || extp->MinorVersion > '4')) { printk(KERN_ERR " Unknown Intel/Sharp Extended Query " "version %c.%c.\n", extp->MajorVersion, extp->MinorVersion); @@ -266,7 +274,7 @@ read_pri_intelext(struct map_info *map, __u16 adr) extp->BlkStatusRegMask = le16_to_cpu(extp->BlkStatusRegMask); extp->ProtRegAddr = le16_to_cpu(extp->ProtRegAddr); - if (extp->MajorVersion == '1' && extp->MinorVersion == '3') { + if (extp->MajorVersion == '1' && extp->MinorVersion >= '3') { unsigned int extra_size = 0; int nb_parts, i; @@ -275,7 +283,7 @@ read_pri_intelext(struct map_info *map, __u16 adr) sizeof(struct cfi_intelext_otpinfo); /* Burst Read info */ - extra_size += 6; + extra_size += (extp->MinorVersion < '4') ? 6 : 5; /* Number of hardware-partitions */ extra_size += 1; @@ -283,6 +291,10 @@ read_pri_intelext(struct map_info *map, __u16 adr) goto need_more; nb_parts = extp->extra[extra_size - 1]; + /* skip the sizeof(partregion) field in CFI 1.4 */ + if (extp->MinorVersion >= '4') + extra_size += 2; + for (i = 0; i < nb_parts; i++) { struct cfi_intelext_regioninfo *rinfo; rinfo = (struct cfi_intelext_regioninfo *)&extp->extra[extra_size]; @@ -294,6 +306,9 @@ read_pri_intelext(struct map_info *map, __u16 adr) * sizeof(struct cfi_intelext_blockinfo); } + if (extp->MinorVersion >= '4') + extra_size += sizeof(struct cfi_intelext_programming_regioninfo); + if (extp_size < sizeof(*extp) + extra_size) { need_more: extp_size = sizeof(*extp) + extra_size; @@ -490,7 +505,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, * arrangement at this point. This can be rearranged in the future * if someone feels motivated enough. --nico */ - if (extp && extp->MajorVersion == '1' && extp->MinorVersion == '3' + if (extp && extp->MajorVersion == '1' && extp->MinorVersion >= '3' && extp->FeatureSupport & (1 << 9)) { struct cfi_private *newcfi; struct flchip *chip; @@ -502,12 +517,16 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, sizeof(struct cfi_intelext_otpinfo); /* Burst Read info */ - offs += 6; + offs += (extp->MinorVersion < '4') ? 6 : 5; /* Number of partition regions */ numregions = extp->extra[offs]; offs += 1; + /* skip the sizeof(partregion) field in CFI 1.4 */ + if (extp->MinorVersion >= '4') + offs += 2; + /* Number of hardware partitions */ numparts = 0; for (i = 0; i < numregions; i++) { @@ -519,6 +538,20 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, sizeof(struct cfi_intelext_blockinfo); } + /* Programming Region info */ + if (extp->MinorVersion >= '4') { + struct cfi_intelext_programming_regioninfo *prinfo; + prinfo = (struct cfi_intelext_programming_regioninfo *)&extp->extra[offs]; + MTD_PROGREGION_SIZE(mtd) = cfi->interleave << prinfo->ProgRegShift; + MTD_PROGREGION_CTRLMODE_VALID(mtd) = cfi->interleave * prinfo->ControlValid; + MTD_PROGREGION_CTRLMODE_INVALID(mtd) = cfi->interleave * prinfo->ControlInvalid; + mtd->flags |= MTD_PROGRAM_REGIONS; + printk(KERN_DEBUG "%s: program region size/ctrl_valid/ctrl_inval = %d/%d/%d\n", + map->name, MTD_PROGREGION_SIZE(mtd), + MTD_PROGREGION_CTRLMODE_VALID(mtd), + MTD_PROGREGION_CTRLMODE_INVALID(mtd)); + } + /* * All functions below currently rely on all chips having * the same geometry so we'll just assume that all hardware @@ -1222,12 +1255,17 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, adr += chip->start; - /* Let's determine this according to the interleave only once */ + /* Let's determine those according to the interleave only once */ status_OK = CMD(0x80); switch (mode) { - case FL_WRITING: write_cmd = CMD(0x40); break; - case FL_OTP_WRITE: write_cmd = CMD(0xc0); break; - default: return -EINVAL; + case FL_WRITING: + write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0x40) : CMD(0x41); + break; + case FL_OTP_WRITE: + write_cmd = CMD(0xc0); + break; + default: + return -EINVAL; } spin_lock(chip->mutex); @@ -1410,16 +1448,17 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, unsigned long adr, const u_char *buf, int len) { struct cfi_private *cfi = map->fldrv_priv; - map_word status, status_OK; + map_word status, status_OK, write_cmd; unsigned long cmd_adr, timeo; int wbufsize, z, ret=0, bytes, words; wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; adr += chip->start; cmd_adr = adr & ~(wbufsize-1); - + /* Let's determine this according to the interleave only once */ status_OK = CMD(0x80); + write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0xe8) : CMD(0xe9); spin_lock(chip->mutex); ret = get_chip(map, chip, cmd_adr, FL_WRITING); @@ -1451,7 +1490,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, z = 0; for (;;) { - map_write(map, CMD(0xe8), cmd_adr); + map_write(map, write_cmd, cmd_adr); status = map_read(map, cmd_adr); if (map_word_andequal(map, status, status_OK, status_OK)) @@ -2380,20 +2419,23 @@ static void cfi_intelext_destroy(struct mtd_info *mtd) kfree(mtd->eraseregions); } -static char im_name_1[]="cfi_cmdset_0001"; -static char im_name_3[]="cfi_cmdset_0003"; +static char im_name_0001[] = "cfi_cmdset_0001"; +static char im_name_0003[] = "cfi_cmdset_0003"; +static char im_name_0200[] = "cfi_cmdset_0200"; static int __init cfi_intelext_init(void) { - inter_module_register(im_name_1, THIS_MODULE, &cfi_cmdset_0001); - inter_module_register(im_name_3, THIS_MODULE, &cfi_cmdset_0001); + inter_module_register(im_name_0001, THIS_MODULE, &cfi_cmdset_0001); + inter_module_register(im_name_0003, THIS_MODULE, &cfi_cmdset_0001); + inter_module_register(im_name_0200, THIS_MODULE, &cfi_cmdset_0001); return 0; } static void __exit cfi_intelext_exit(void) { - inter_module_unregister(im_name_1); - inter_module_unregister(im_name_3); + inter_module_unregister(im_name_0001); + inter_module_unregister(im_name_0003); + inter_module_unregister(im_name_0200); } module_init(cfi_intelext_init); diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c index dc065b22f79..28807eb9fc8 100644 --- a/drivers/mtd/chips/gen_probe.c +++ b/drivers/mtd/chips/gen_probe.c @@ -2,7 +2,7 @@ * Routines common to all CFI-type probes. * (C) 2001-2003 Red Hat, Inc. * GPL'd - * $Id: gen_probe.c,v 1.22 2005/01/24 23:49:50 rmk Exp $ + * $Id: gen_probe.c,v 1.23 2005/08/06 04:40:41 nico Exp $ */ #include @@ -235,6 +235,7 @@ static struct mtd_info *check_cmd_set(struct map_info *map, int primary) #ifdef CONFIG_MTD_CFI_INTELEXT case 0x0001: case 0x0003: + case 0x0200: return cfi_cmdset_0001(map, primary); #endif #ifdef CONFIG_MTD_CFI_AMDSTD diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index e6b6a1c66bd..360cf626c28 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h @@ -1,7 +1,7 @@ /* Common Flash Interface structures * See http://support.intel.com/design/flash/technote/index.htm - * $Id: cfi.h,v 1.54 2005/06/06 23:04:36 tpoynor Exp $ + * $Id: cfi.h,v 1.55 2005/08/06 04:40:42 nico Exp $ */ #ifndef __MTD_CFI_H__ @@ -173,6 +173,15 @@ struct cfi_intelext_regioninfo { struct cfi_intelext_blockinfo BlockTypes[1]; } __attribute__((packed)); +struct cfi_intelext_programming_regioninfo { + uint8_t ProgRegShift; + uint8_t Reserved1; + uint8_t ControlValid; + uint8_t Reserved2; + uint8_t ControlInvalid; + uint8_t Reserved3; +} __attribute__((packed)); + /* Vendor-Specific PRI for AMD/Fujitsu Extended Command Set (0x0002) */ struct cfi_pri_amdstd { @@ -316,7 +325,7 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf #define CMD(x) cfi_build_cmd((x), map, cfi) -static inline unsigned char cfi_merge_status(map_word val, struct map_info *map, +static inline unsigned long cfi_merge_status(map_word val, struct map_info *map, struct cfi_private *cfi) { int wordwidth, words_per_bus, chip_mode, chips_per_word; diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index c50c3f3927d..ab580418391 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -1,5 +1,5 @@ /* - * $Id: mtd.h,v 1.59 2005/04/11 10:19:02 gleixner Exp $ + * $Id: mtd.h,v 1.60 2005/08/06 04:40:42 nico Exp $ * * Copyright (C) 1999-2003 David Woodhouse et al. * @@ -72,7 +72,17 @@ struct mtd_info { u_int32_t oobsize; // Amount of OOB data per block (e.g. 16) u_int32_t ecctype; u_int32_t eccsize; - + + /* + * Reuse some of the above unused fields in the case of NOR flash + * with configurable programming regions to avoid modifying the + * user visible structure layout/size. Only valid when the + * MTD_PROGRAM_REGIONS flag is set. + * (Maybe we should have an union for those?) + */ +#define MTD_PROGREGION_SIZE(mtd) (mtd)->oobblock +#define MTD_PROGREGION_CTRLMODE_VALID(mtd) (mtd)->oobsize +#define MTD_PROGREGION_CTRLMODE_INVALID(mtd) (mtd)->ecctype // Kernel-only stuff starts here. char *name; diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h index 428d9122940..16e74cafd0b 100644 --- a/include/mtd/mtd-abi.h +++ b/include/mtd/mtd-abi.h @@ -1,5 +1,5 @@ /* - * $Id: mtd-abi.h,v 1.11 2005/05/19 16:08:58 gleixner Exp $ + * $Id: mtd-abi.h,v 1.12 2005/08/06 04:40:43 nico Exp $ * * Portions of MTD ABI definition which are shared by kernel and user space */ @@ -42,6 +42,7 @@ struct mtd_oob_buf { #define MTD_OOB 64 // Out-of-band data (NAND flash) #define MTD_ECC 128 // Device capable of automatic ECC #define MTD_NO_VIRTBLOCKS 256 // Virtual blocks not allowed +#define MTD_PROGRAM_REGIONS 512 // Configurable Programming Regions // Some common devices / combinations of capabilities #define MTD_CAP_ROM 0 -- cgit v1.2.3 From e102d54abf6806b95c89142cd0b7e94d709ebcd7 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 6 Aug 2005 05:46:59 +0100 Subject: [MTD] writev support for cfi-cmdset-0001 While this might be useful for all supported flash types, it is mandatory for proper JFFS2 support with Sibley flash. Signed-off-by: Nicolas Pitre Signed-off-by: Thomas Gleixner --- drivers/mtd/chips/cfi_cmdset_0001.c | 125 +++++++++++++++++++++--------------- 1 file changed, 75 insertions(+), 50 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 10c50604bcd..adaad7c8fd4 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -4,7 +4,7 @@ * * (C) 2000 Red Hat. GPL'd * - * $Id: cfi_cmdset_0001.c,v 1.182 2005/08/06 04:40:41 nico Exp $ + * $Id: cfi_cmdset_0001.c,v 1.183 2005/08/06 04:46:56 nico Exp $ * * * 10/10/2000 Nicolas Pitre @@ -51,6 +51,7 @@ static int cfi_intelext_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); static int cfi_intelext_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); static int cfi_intelext_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); +static int cfi_intelext_writev(struct mtd_info *, const struct kvec *, unsigned long, loff_t, size_t *); static int cfi_intelext_erase_varsize(struct mtd_info *, struct erase_info *); static void cfi_intelext_sync (struct mtd_info *); static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len); @@ -215,6 +216,7 @@ static void fixup_use_write_buffers(struct mtd_info *mtd, void *param) if (cfi->cfiq->BufWriteTimeoutTyp) { printk(KERN_INFO "Using buffer write method\n" ); mtd->write = cfi_intelext_write_buffers; + mtd->writev = cfi_intelext_writev; } } @@ -1445,12 +1447,15 @@ static int cfi_intelext_write_words (struct mtd_info *mtd, loff_t to , size_t le static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, - unsigned long adr, const u_char *buf, int len) + unsigned long adr, const struct kvec **pvec, + unsigned long *pvec_seek, int len) { struct cfi_private *cfi = map->fldrv_priv; - map_word status, status_OK, write_cmd; + map_word status, status_OK, write_cmd, datum; unsigned long cmd_adr, timeo; - int wbufsize, z, ret=0, bytes, words; + int wbufsize, z, ret=0, word_gap, words; + const struct kvec *vec; + unsigned long vec_seek; wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; adr += chip->start; @@ -1515,28 +1520,53 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, } } + /* Figure out the number of words to write */ + word_gap = (-adr & (map_bankwidth(map)-1)); + words = (len - word_gap + map_bankwidth(map) - 1) / map_bankwidth(map); + if (!word_gap) { + words--; + } else { + word_gap = map_bankwidth(map) - word_gap; + adr -= word_gap; + datum = map_word_ff(map); + } + /* Write length of data to come */ - bytes = len & (map_bankwidth(map)-1); - words = len / map_bankwidth(map); - map_write(map, CMD(words - !bytes), cmd_adr ); + map_write(map, CMD(words), cmd_adr ); /* Write data */ - z = 0; - while(z < words * map_bankwidth(map)) { - map_word datum = map_word_load(map, buf); - map_write(map, datum, adr+z); - - z += map_bankwidth(map); - buf += map_bankwidth(map); - } + vec = *pvec; + vec_seek = *pvec_seek; + do { + int n = map_bankwidth(map) - word_gap; + if (n > vec->iov_len - vec_seek) + n = vec->iov_len - vec_seek; + if (n > len) + n = len; + + if (!word_gap && len < map_bankwidth(map)) + datum = map_word_ff(map); + + datum = map_word_load_partial(map, datum, + vec->iov_base + vec_seek, + word_gap, n); - if (bytes) { - map_word datum; + len -= n; + word_gap += n; + if (!len || word_gap == map_bankwidth(map)) { + map_write(map, datum, adr); + adr += map_bankwidth(map); + word_gap = 0; + } - datum = map_word_ff(map); - datum = map_word_load_partial(map, datum, buf, 0, bytes); - map_write(map, datum, adr+z); - } + vec_seek += n; + if (vec_seek == vec->iov_len) { + vec++; + vec_seek = 0; + } + } while (len); + *pvec = vec; + *pvec_seek = vec_seek; /* GO GO GO */ map_write(map, CMD(0xd0), cmd_adr); @@ -1619,57 +1649,40 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, return ret; } -static int cfi_intelext_write_buffers (struct mtd_info *mtd, loff_t to, - size_t len, size_t *retlen, const u_char *buf) +static int cfi_intelext_writev (struct mtd_info *mtd, const struct kvec *vecs, + unsigned long count, loff_t to, size_t *retlen) { struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; int wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; int ret = 0; int chipnum; - unsigned long ofs; + unsigned long ofs, vec_seek, i; + size_t len = 0; + + for (i = 0; i < count; i++) + len += vecs[i].iov_len; *retlen = 0; if (!len) return 0; chipnum = to >> cfi->chipshift; - ofs = to - (chipnum << cfi->chipshift); + ofs = to - (chipnum << cfi->chipshift); + vec_seek = 0; - /* If it's not bus-aligned, do the first word write */ - if (ofs & (map_bankwidth(map)-1)) { - size_t local_len = (-ofs)&(map_bankwidth(map)-1); - if (local_len > len) - local_len = len; - ret = cfi_intelext_write_words(mtd, to, local_len, - retlen, buf); - if (ret) - return ret; - ofs += local_len; - buf += local_len; - len -= local_len; - - if (ofs >> cfi->chipshift) { - chipnum ++; - ofs = 0; - if (chipnum == cfi->numchips) - return 0; - } - } - - while(len) { + do { /* We must not cross write block boundaries */ int size = wbufsize - (ofs & (wbufsize-1)); if (size > len) size = len; ret = do_write_buffer(map, &cfi->chips[chipnum], - ofs, buf, size); + ofs, &vecs, &vec_seek, size); if (ret) return ret; ofs += size; - buf += size; (*retlen) += size; len -= size; @@ -1679,10 +1692,22 @@ static int cfi_intelext_write_buffers (struct mtd_info *mtd, loff_t to, if (chipnum == cfi->numchips) return 0; } - } + } while (len); + return 0; } +static int cfi_intelext_write_buffers (struct mtd_info *mtd, loff_t to, + size_t len, size_t *retlen, const u_char *buf) +{ + struct kvec vec; + + vec.iov_base = (void *) buf; + vec.iov_len = len; + + return cfi_intelext_writev(mtd, &vec, 1, to, retlen); +} + static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, int len, void *thunk) { -- cgit v1.2.3 From 59da721a2288b8aec751a2716f7ab60f2ea0c925 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 6 Aug 2005 05:51:33 +0100 Subject: [JFFS2] Teach JFFS2 about Sibley flash Intels Sibley flash needs JFFS2 write buffer functionality Signed-off-by: Nicolas Pitre Signed-off-by: Thomas Gleixner --- fs/jffs2/fs.c | 16 ++++++++++++++-- fs/jffs2/os-linux.h | 13 +++++++++++-- fs/jffs2/wbuf.c | 22 +++++++++++++++++++++- 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index cc18b92234c..79b4bdc76f7 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: fs.c,v 1.61 2005/07/24 15:29:56 dedekind Exp $ + * $Id: fs.c,v 1.62 2005/08/06 04:51:30 nico Exp $ * */ @@ -664,7 +664,14 @@ static int jffs2_flash_setup(struct jffs2_sb_info *c) { if (ret) return ret; } - + + /* and Intel "Sibley" flash */ + if (jffs2_nor_wbuf_flash(c)) { + ret = jffs2_nor_wbuf_flash_setup(c); + if (ret) + return ret; + } + return ret; } @@ -683,4 +690,9 @@ void jffs2_flash_cleanup(struct jffs2_sb_info *c) { if (jffs2_dataflash(c)) { jffs2_dataflash_cleanup(c); } + + /* and Intel "Sibley" flash */ + if (jffs2_nor_wbuf_flash(c)) { + jffs2_nor_wbuf_flash_cleanup(c); + } } diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index 0fc952eaf8c..c3c1619fb13 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: os-linux.h,v 1.59 2005/07/17 11:13:46 dedekind Exp $ + * $Id: os-linux.h,v 1.60 2005/08/06 04:51:30 nico Exp $ * */ @@ -85,16 +85,21 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) #define jffs2_wbuf_process NULL #define jffs2_nor_ecc(c) (0) #define jffs2_dataflash(c) (0) +#define jffs2_nor_wbuf_flash(c) (0) #define jffs2_nor_ecc_flash_setup(c) (0) #define jffs2_nor_ecc_flash_cleanup(c) do {} while (0) #define jffs2_dataflash_setup(c) (0) #define jffs2_dataflash_cleanup(c) do {} while (0) +#define jffs2_nor_wbuf_flash_setup(c) (0) +#define jffs2_nor_wbuf_flash_cleanup(c) do {} while (0) #else /* NAND and/or ECC'd NOR support present */ #define jffs2_is_writebuffered(c) (c->wbuf != NULL) #define SECTOR_ADDR(x) ( ((unsigned long)(x) / (unsigned long)(c->sector_size)) * c->sector_size ) -#define jffs2_can_mark_obsolete(c) ((c->mtd->type == MTD_NORFLASH && !(c->mtd->flags & MTD_ECC)) || c->mtd->type == MTD_RAM) +#define jffs2_can_mark_obsolete(c) \ + ((c->mtd->type == MTD_NORFLASH && !(c->mtd->flags & (MTD_ECC|MTD_PROGRAM_REGIONS))) || \ + c->mtd->type == MTD_RAM) #define jffs2_cleanmarker_oob(c) (c->mtd->type == MTD_NANDFLASH) #define jffs2_flash_write_oob(c, ofs, len, retlen, buf) ((c)->mtd->write_oob((c)->mtd, ofs, len, retlen, buf)) @@ -124,6 +129,10 @@ void jffs2_nor_ecc_flash_cleanup(struct jffs2_sb_info *c); int jffs2_dataflash_setup(struct jffs2_sb_info *c); void jffs2_dataflash_cleanup(struct jffs2_sb_info *c); +#define jffs2_nor_wbuf_flash(c) (c->mtd->type == MTD_NORFLASH && (c->mtd->flags & MTD_PROGRAM_REGIONS)) +int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c); +void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c); + #endif /* WRITEBUFFER */ /* erase.c */ diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 251ac3d86f9..8c06d3a2b17 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -9,7 +9,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: wbuf.c,v 1.96 2005/07/22 10:32:08 dedekind Exp $ + * $Id: wbuf.c,v 1.97 2005/08/06 04:51:30 nico Exp $ * */ @@ -1235,3 +1235,23 @@ int jffs2_nor_ecc_flash_setup(struct jffs2_sb_info *c) { void jffs2_nor_ecc_flash_cleanup(struct jffs2_sb_info *c) { kfree(c->wbuf); } + +int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) { + /* Cleanmarker currently occupies a whole programming region */ + c->cleanmarker_size = MTD_PROGREGION_SIZE(c->mtd); + + /* Initialize write buffer */ + init_rwsem(&c->wbuf_sem); + c->wbuf_pagesize = MTD_PROGREGION_SIZE(c->mtd); + c->wbuf_ofs = 0xFFFFFFFF; + + c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); + if (!c->wbuf) + return -ENOMEM; + + return 0; +} + +void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c) { + kfree(c->wbuf); +} -- cgit v1.2.3 From e21f6c02f78351c4aae8510929ed794cd818d847 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 8 Aug 2005 09:56:22 +0100 Subject: [MTD] Missing check on kmalloc return in INFTL mount. Signed-off-by: Youssef Hmamouche Signed-off-by: David Woodhouse Signed-off-by: Thomas Gleixner --- drivers/mtd/inftlmount.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c index b5dda47395a..e066445320a 100644 --- a/drivers/mtd/inftlmount.c +++ b/drivers/mtd/inftlmount.c @@ -8,7 +8,7 @@ * Author: Fabrice Bellard (fabrice.bellard@netgem.com) * Copyright (C) 2000 Netgem S.A. * - * $Id: inftlmount.c,v 1.16 2004/11/22 13:50:53 kalev Exp $ + * $Id: inftlmount.c,v 1.17 2005/08/08 08:56:19 dwmw2 Exp $ * * 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 @@ -41,7 +41,7 @@ #include #include -char inftlmountrev[]="$Revision: 1.16 $"; +char inftlmountrev[]="$Revision: 1.17 $"; /* * find_boot_record: Find the INFTL Media Header and its Spare copy which @@ -563,7 +563,7 @@ int INFTL_mount(struct INFTLrecord *s) /* Search for INFTL MediaHeader and Spare INFTL Media Header */ if (find_boot_record(s) < 0) { printk(KERN_WARNING "INFTL: could not find valid boot record?\n"); - return -1; + return -ENXIO; } /* Init the logical to physical table */ @@ -574,6 +574,11 @@ int INFTL_mount(struct INFTLrecord *s) /* Temporary buffer to store ANAC numbers. */ ANACtable = kmalloc(s->nb_blocks * sizeof(u8), GFP_KERNEL); + if (!ANACtable) { + printk(KERN_ERR "INFTL: Out of memory.\n"); + return -ENOMEM; + } + memset(ANACtable, 0, s->nb_blocks); /* -- cgit v1.2.3 From 2c92d755323514a12c367f52027fb1f53328fcd6 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 11 Aug 2005 18:13:46 +0100 Subject: [MTD] Remove deprecated power management functions Signed-off-by: Thomas Gleixner --- drivers/mtd/mtdcore.c | 46 +--------------------------------------------- 1 file changed, 1 insertion(+), 45 deletions(-) diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index dc86df18e94..2c16e051c61 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -1,5 +1,5 @@ /* - * $Id: mtdcore.c,v 1.45 2005/02/18 14:34:50 dedekind Exp $ + * $Id: mtdcore.c,v 1.46 2005/08/11 17:13:43 gleixner Exp $ * * Core registration and callback routines for MTD * drivers and users. @@ -296,39 +296,6 @@ EXPORT_SYMBOL(unregister_mtd_user); EXPORT_SYMBOL(default_mtd_writev); EXPORT_SYMBOL(default_mtd_readv); -/*====================================================================*/ -/* Power management code */ - -#ifdef CONFIG_PM - -#include - -static struct pm_dev *mtd_pm_dev = NULL; - -static int mtd_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) -{ - int ret = 0, i; - - if (down_trylock(&mtd_table_mutex)) - return -EAGAIN; - if (rqst == PM_SUSPEND) { - for (i = 0; ret == 0 && i < MAX_MTD_DEVICES; i++) { - if (mtd_table[i] && mtd_table[i]->suspend) - ret = mtd_table[i]->suspend(mtd_table[i]); - } - } else i = MAX_MTD_DEVICES-1; - - if (rqst == PM_RESUME || ret) { - for ( ; i >= 0; i--) { - if (mtd_table[i] && mtd_table[i]->resume) - mtd_table[i]->resume(mtd_table[i]); - } - } - up(&mtd_table_mutex); - return ret; -} -#endif - /*====================================================================*/ /* Support for /proc/mtd */ @@ -388,22 +355,11 @@ static int __init init_mtd(void) if ((proc_mtd = create_proc_entry( "mtd", 0, NULL ))) proc_mtd->read_proc = mtd_read_proc; #endif - -#ifdef CONFIG_PM - mtd_pm_dev = pm_register(PM_UNKNOWN_DEV, 0, mtd_pm_callback); -#endif return 0; } static void __exit cleanup_mtd(void) { -#ifdef CONFIG_PM - if (mtd_pm_dev) { - pm_unregister(mtd_pm_dev); - mtd_pm_dev = NULL; - } -#endif - #ifdef CONFIG_PROC_FS if (proc_mtd) remove_proc_entry( "mtd", NULL); -- cgit v1.2.3 From d4094661545662982278900220729982372b0e9a Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 11 Aug 2005 18:13:46 +0100 Subject: [MTD] NAND: Use correct mask for OOB size calculation The bit mask used for oob size calculation was using 2 bits instead of one. Fortunately the next bit has been 0 all the time. Thanks to Nathan H. for pointing this out Signed-off-by: Thomas Gleixner --- drivers/mtd/nand/nand_base.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 04e54318bc6..cdf10861934 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -59,7 +59,7 @@ * The AG-AND chips have nice features for speed improvement, * which are not supported yet. Read / program 4 pages in one go. * - * $Id: nand_base.c,v 1.147 2005/07/15 07:18:06 gleixner Exp $ + * $Id: nand_base.c,v 1.148 2005/08/04 17:14:48 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -2369,7 +2369,7 @@ int nand_scan (struct mtd_info *mtd, int maxchips) mtd->oobblock = 1024 << (extid & 0x3); extid >>= 2; /* Calc oobsize */ - mtd->oobsize = (8 << (extid & 0x03)) * (mtd->oobblock / 512); + mtd->oobsize = (8 << (extid & 0x01)) * (mtd->oobblock >> 9); extid >>= 2; /* Calc blocksize. Blocksize is multiples of 64KiB */ mtd->erasesize = (64 * 1024) << (extid & 0x03); -- cgit v1.2.3 From 01d445f89d68187c9ada7b58ca939dbb987c9fbd Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Wed, 17 Aug 2005 14:42:09 +0100 Subject: [JFFS2] Make the JFFS2 messages a bit nicer Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/debug.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index 3a7b11c2dd8..676188ec730 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.h,v 1.12 2005/08/05 10:43:47 dedekind Exp $ + * $Id: debug.h,v 1.13 2005/08/17 13:42:06 dedekind Exp $ * */ #ifndef _JFFS2_DEBUG_H_ @@ -68,28 +68,28 @@ #define JFFS2_ERROR(fmt, ...) \ do { \ printk(JFFS2_ERR_LVL JFFS2_ERR_MSG_PREFIX \ - " %d,%s: " fmt, current->pid, \ + " %d (%s): " fmt, current->pid, \ __FUNCTION__, ##__VA_ARGS__); \ } while(0) #define JFFS2_WARNING(fmt, ...) \ do { \ printk(JFFS2_WARN_LVL JFFS2_WARN_MSG_PREFIX \ - " %d,%s: " fmt, current->pid, \ + " %d (%s): " fmt, current->pid, \ __FUNCTION__, ##__VA_ARGS__); \ } while(0) #define JFFS2_NOTICE(fmt, ...) \ do { \ printk(JFFS2_NOTICE_LVL JFFS2_NOTICE_MSG_PREFIX \ - " %d,%s: " fmt, current->pid, \ + " %d (%s): " fmt, current->pid, \ __FUNCTION__, ##__VA_ARGS__); \ } while(0) #define JFFS2_DEBUG(fmt, ...) \ do { \ printk(JFFS2_DBG_LVL JFFS2_DBG_MSG_PREFIX \ - " %d,%s: " fmt, current->pid, \ + " %d (%s): " fmt, current->pid, \ __FUNCTION__, ##__VA_ARGS__); \ } while(0) -- cgit v1.2.3 From 3a69e0cd22cf34920508a4032d53e41251925f53 Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Wed, 17 Aug 2005 14:46:26 +0100 Subject: [JFFS2] Fix JFFS2 [mc]time handling From: David Woodhouse Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/dir.c | 21 ++++++++++++++++----- fs/jffs2/gc.c | 12 ++++++++++-- fs/jffs2/nodelist.h | 6 +++--- fs/jffs2/readinode.c | 4 ++-- fs/jffs2/write.c | 11 ++++++----- 5 files changed, 37 insertions(+), 17 deletions(-) diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 5738df22377..0fd15aaf245 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: dir.c,v 1.87 2005/07/17 11:13:46 dedekind Exp $ + * $Id: dir.c,v 1.88 2005/08/17 13:46:22 dedekind Exp $ * */ @@ -232,11 +232,14 @@ static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry) struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); struct jffs2_inode_info *dead_f = JFFS2_INODE_INFO(dentry->d_inode); int ret; + uint32_t now = get_seconds(); ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, - dentry->d_name.len, dead_f); + dentry->d_name.len, dead_f, now); if (dead_f->inocache) dentry->d_inode->i_nlink = dead_f->inocache->nlink; + if (!ret) + dir_i->i_mtime = dir_i->i_ctime = ITIME(now); return ret; } /***********************************************************************/ @@ -249,6 +252,7 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); int ret; uint8_t type; + uint32_t now; /* Don't let people make hard links to bad inodes. */ if (!f->inocache) @@ -261,13 +265,15 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12; if (!type) type = DT_REG; - ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len); + now = get_seconds(); + ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len, now); if (!ret) { down(&f->sem); old_dentry->d_inode->i_nlink = ++f->inocache->nlink; up(&f->sem); d_instantiate(dentry, old_dentry->d_inode); + dir_i->i_mtime = dir_i->i_ctime = ITIME(now); atomic_inc(&old_dentry->d_inode->i_count); } return ret; @@ -716,6 +722,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb); struct jffs2_inode_info *victim_f = NULL; uint8_t type; + uint32_t now; /* The VFS will check for us and prevent trying to rename a * file over a directory and vice versa, but if it's a directory, @@ -749,9 +756,10 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12; if (!type) type = DT_REG; + now = get_seconds(); ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i), old_dentry->d_inode->i_ino, type, - new_dentry->d_name.name, new_dentry->d_name.len); + new_dentry->d_name.name, new_dentry->d_name.len, now); if (ret) return ret; @@ -775,7 +783,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, /* Unlink the original */ ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), - old_dentry->d_name.name, old_dentry->d_name.len, NULL); + old_dentry->d_name.name, old_dentry->d_name.len, NULL, now); /* We don't touch inode->i_nlink */ @@ -792,12 +800,15 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, /* Might as well let the VFS know */ d_instantiate(new_dentry, old_dentry->d_inode); atomic_inc(&old_dentry->d_inode->i_count); + new_dir_i->i_mtime = new_dir_i->i_ctime = ITIME(now); return ret; } if (S_ISDIR(old_dentry->d_inode->i_mode)) old_dir_i->i_nlink--; + new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = ITIME(now); + return 0; } diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 362cfeed732..def97157ecb 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: gc.c,v 1.152 2005/07/24 15:14:14 dedekind Exp $ + * $Id: gc.c,v 1.153 2005/08/17 13:46:22 dedekind Exp $ * */ @@ -771,7 +771,12 @@ static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_er rd.pino = cpu_to_je32(f->inocache->ino); rd.version = cpu_to_je32(++f->highest_version); rd.ino = cpu_to_je32(fd->ino); - rd.mctime = cpu_to_je32(max(JFFS2_F_I_MTIME(f), JFFS2_F_I_CTIME(f))); + /* If the times on this inode were set by explicit utime() they can be different, + so refrain from splatting them. */ + if (JFFS2_F_I_MTIME(f) == JFFS2_F_I_CTIME(f)) + rd.mctime = cpu_to_je32(JFFS2_F_I_MTIME(f)); + else + rd.mctime = cpu_to_je32(0); rd.type = fd->type; rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8)); rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize)); @@ -883,6 +888,9 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct kfree(rd); } + /* FIXME: If we're deleting a dirent which contains the current mtime and ctime, + we should update the metadata node with those times accordingly */ + /* No need for it any more. Just mark it obsolete and remove it from the list */ while (*fdp) { if ((*fdp) == fd) { diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index adee3c6eb44..ce47d5530a7 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.h,v 1.137 2005/08/01 12:05:19 dedekind Exp $ + * $Id: nodelist.h,v 1.138 2005/08/17 13:46:23 dedekind Exp $ * */ @@ -336,8 +336,8 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, unsigned char *buf, uint32_t offset, uint32_t writelen, uint32_t *retlen); int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen); -int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, int namelen, struct jffs2_inode_info *dead_f); -int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen); +int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, int namelen, struct jffs2_inode_info *dead_f, uint32_t time); +int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen, uint32_t time); /* readinode.c */ diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 50a62dd33e3..6d5adaba406 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.139 2005/08/04 11:41:31 dedekind Exp $ + * $Id: readinode.c,v 1.140 2005/08/17 13:46:23 dedekind Exp $ * */ @@ -139,7 +139,7 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r fd->type = rd->type; /* Pick out the mctime of the latest dirent */ - if(fd->version > *mctime_ver) { + if(fd->version > *mctime_ver && je32_to_cpu(rd->mctime)) { *mctime_ver = fd->version; *latest_mctime = je32_to_cpu(rd->mctime); } diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index 4c418e69cfc..0a194759bbb 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: write.c,v 1.94 2005/07/20 15:50:51 dedekind Exp $ + * $Id: write.c,v 1.95 2005/08/17 13:46:23 dedekind Exp $ * */ @@ -533,7 +533,8 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, - const char *name, int namelen, struct jffs2_inode_info *dead_f) + const char *name, int namelen, struct jffs2_inode_info *dead_f, + uint32_t time) { struct jffs2_raw_dirent *rd; struct jffs2_full_dirent *fd; @@ -565,7 +566,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, rd->pino = cpu_to_je32(dir_f->inocache->ino); rd->version = cpu_to_je32(++dir_f->highest_version); rd->ino = cpu_to_je32(0); - rd->mctime = cpu_to_je32(get_seconds()); + rd->mctime = cpu_to_je32(time); rd->nsize = namelen; rd->type = DT_UNKNOWN; rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); @@ -646,7 +647,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, } -int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen) +int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen, uint32_t time) { struct jffs2_raw_dirent *rd; struct jffs2_full_dirent *fd; @@ -674,7 +675,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint rd->pino = cpu_to_je32(dir_f->inocache->ino); rd->version = cpu_to_je32(++dir_f->highest_version); rd->ino = cpu_to_je32(ino); - rd->mctime = cpu_to_je32(get_seconds()); + rd->mctime = cpu_to_je32(time); rd->nsize = namelen; rd->type = type; -- cgit v1.2.3 From 8d5df40954281a8e0f788b311f9c08f96e530ffa Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Wed, 17 Aug 2005 15:13:48 +0100 Subject: [JFFS2] More message formatting cleanups Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/debug.h | 10 +++++----- fs/jffs2/nodelist.c | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index 676188ec730..03d9626ad1c 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.h,v 1.13 2005/08/17 13:42:06 dedekind Exp $ + * $Id: debug.h,v 1.14 2005/08/17 13:48:59 dedekind Exp $ * */ #ifndef _JFFS2_DEBUG_H_ @@ -68,28 +68,28 @@ #define JFFS2_ERROR(fmt, ...) \ do { \ printk(JFFS2_ERR_LVL JFFS2_ERR_MSG_PREFIX \ - " %d (%s): " fmt, current->pid, \ + " (%d) %s: " fmt, current->pid, \ __FUNCTION__, ##__VA_ARGS__); \ } while(0) #define JFFS2_WARNING(fmt, ...) \ do { \ printk(JFFS2_WARN_LVL JFFS2_WARN_MSG_PREFIX \ - " %d (%s): " fmt, current->pid, \ + " (%d) %s: " fmt, current->pid, \ __FUNCTION__, ##__VA_ARGS__); \ } while(0) #define JFFS2_NOTICE(fmt, ...) \ do { \ printk(JFFS2_NOTICE_LVL JFFS2_NOTICE_MSG_PREFIX \ - " %d (%s): " fmt, current->pid, \ + " (%d) %s: " fmt, current->pid, \ __FUNCTION__, ##__VA_ARGS__); \ } while(0) #define JFFS2_DEBUG(fmt, ...) \ do { \ printk(JFFS2_DBG_LVL JFFS2_DBG_MSG_PREFIX \ - " %d (%s): " fmt, current->pid, \ + " (%d) %s: " fmt, current->pid, \ __FUNCTION__, ##__VA_ARGS__); \ } while(0) diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index cd366ab1f02..0393d27eafc 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.c,v 1.109 2005/08/04 11:41:30 dedekind Exp $ + * $Id: nodelist.c,v 1.110 2005/08/17 14:13:45 dedekind Exp $ * */ @@ -263,7 +263,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r this->ofs, this->ofs+this->size, ref_offset(this->node->raw)); else JFFS2_DBG_FRAGTREE2("split old hole frag 0x%04x-0x%04x\n", - this->ofs, this->ofs+this->size, ref_offset(this->node->raw)); + this->ofs, this->ofs+this->size); /* New second frag pointing to this's node */ newfrag2 = new_fragment(this->node, newfrag->ofs + newfrag->size, -- cgit v1.2.3 From 280562b2104c9a0ca7efc5e716b6452a7ba820fa Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Wed, 17 Aug 2005 15:57:43 +0100 Subject: [JFFS2] Calculate CRC check starting point correctly When data starts from the beginning of NAND page, 'len' must be zero, not c->wbuf_page. Thanks to Zoltan Sogor for reporting this problem. Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/nodelist.c | 5 +++-- fs/jffs2/readinode.c | 12 ++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 0393d27eafc..fd21f109fbd 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.c,v 1.110 2005/08/17 14:13:45 dedekind Exp $ + * $Id: nodelist.c,v 1.111 2005/08/17 14:57:39 dedekind Exp $ * */ @@ -413,7 +413,8 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info /* Calculate how many bytes were already checked */ ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode); len = ofs & (c->wbuf_pagesize - 1); - len = c->wbuf_pagesize - len; + if (likely(len)) + len = c->wbuf_pagesize - len; if (len >= tn->csize) { JFFS2_DBG_READINODE("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n", diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 6d5adaba406..6f1e4a7ecd9 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.140 2005/08/17 13:46:23 dedekind Exp $ + * $Id: readinode.c,v 1.141 2005/08/17 14:57:39 dedekind Exp $ * */ @@ -272,9 +272,9 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref buf = (unsigned char *)rd + sizeof(*rd); /* len will be the read data length */ len = min_t(uint32_t, rdlen - sizeof(*rd), csize); - - if (len) - tn->partial_crc = crc = crc32(0, buf, len); + tn->partial_crc = crc32(0, buf, len); + + JFFS2_DBG_READINODE("Calculates CRC (%#08x) for %d bytes, csize %d\n", tn->partial_crc, len, csize); /* If we actually calculated the whole data CRC * and it is wrong, drop the node. */ @@ -327,8 +327,8 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref else // normal case... tn->fn->size = je32_to_cpu(rd->dsize); - JFFS2_DBG_READINODE("dnode @%08x: ver %u, offset %#04x, dsize %#04x\n", - ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize)); + JFFS2_DBG_READINODE("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n", + ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize); jffs2_add_tn_to_tree(tn, tnp); -- cgit v1.2.3 From f0507530cbedf37515e0d803c332cdb81b34e71a Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Mon, 22 Aug 2005 10:07:12 +0100 Subject: [JFFS2] Solve BUG caused by frag->node representing a hole in fragtree Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/nodelist.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index fd21f109fbd..9abb5f4cfd7 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.c,v 1.111 2005/08/17 14:57:39 dedekind Exp $ + * $Id: nodelist.c,v 1.112 2005/08/22 09:07:09 dedekind Exp $ * */ @@ -80,7 +80,7 @@ void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint * REF_PRISTINE irrespective of its size. */ frag = frag_last(list); - if ((frag->ofs & (PAGE_CACHE_SIZE - 1)) == 0) { + if (frag->node && (frag->ofs & (PAGE_CACHE_SIZE - 1)) == 0) { JFFS2_DBG_FRAGTREE2("marking the last fragment 0x%08x-0x%08x REF_PRISTINE.\n", frag->ofs, frag->ofs + frag->size); frag->node->raw->flash_offset = ref_offset(frag->node->raw) | REF_PRISTINE; -- cgit v1.2.3 From 4fe15ba08fdb280536bd7019e8505969c4ac6852 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 6 Nov 2005 19:47:04 +0000 Subject: [ARM] Fix second missing declaration of cache_is_vivt() Signed-off-by: Russell King --- arch/arm/kernel/ecard.c | 1 - include/asm-arm/mmu_context.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index c445b0a848b..dceb826bd21 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -41,7 +41,6 @@ #include #include -#include #include #include #include diff --git a/include/asm-arm/mmu_context.h b/include/asm-arm/mmu_context.h index 57b8def83d4..3d4b810d8c3 100644 --- a/include/asm-arm/mmu_context.h +++ b/include/asm-arm/mmu_context.h @@ -13,6 +13,7 @@ #ifndef __ASM_ARM_MMU_CONTEXT_H #define __ASM_ARM_MMU_CONTEXT_H +#include #include #if __LINUX_ARM_ARCH__ >= 6 -- cgit v1.2.3 From 32f8b97ca39421057d8adef05b7219127355d60c Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 6 Nov 2005 19:49:21 +0000 Subject: [ARM] Don't call dump_cpu_info unless we're booting We don't want to call dump_cpu_info() from cpu_init() after boot since it produces a lot of unnecessary noise - since cpu_init() gets called on resume and hotplug cpu insertion events. Signed-off-by: Russell King --- arch/arm/kernel/setup.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index c9b69771f92..a6d7fb81330 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -338,7 +338,8 @@ void cpu_init(void) BUG(); } - dump_cpu_info(cpu); + if (system_state == SYSTEM_BOOTING) + dump_cpu_info(cpu); /* * setup stacks for re-entrant exception handlers -- cgit v1.2.3 From 4ce1f562189696605a84813cf71847c0cc698414 Mon Sep 17 00:00:00 2001 From: Ferenc Havasi Date: Wed, 31 Aug 2005 14:51:04 +0100 Subject: [JFFS2] Remove support for virtual blocks Remove support for virtual blocks, which are build by concatenation of multiple physical erase blocks. For more information please read the MTD mailing list thread "[PATCH] remove support for virtual blocks" Signed-off-by: Ferenc Havasi Signed-off-by: Thomas Gleixner --- fs/jffs2/build.c | 6 +++--- fs/jffs2/fs.c | 19 ++----------------- fs/jffs2/nodelist.h | 7 ++++++- fs/jffs2/super.c | 4 ++-- 4 files changed, 13 insertions(+), 23 deletions(-) diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index 8e2f1f4e8aa..1522eace932 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: build.c,v 1.76 2005/07/30 15:29:27 lunn Exp $ + * $Id: build.c,v 1.77 2005/08/31 13:51:00 havasi Exp $ * */ @@ -318,7 +318,7 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) c->free_size = c->flash_size; c->nr_blocks = c->flash_size / c->sector_size; #ifndef __ECOS - if (c->mtd->flags & MTD_NO_VIRTBLOCKS) + if (jffs2_blocks_use_vmalloc(c)) c->blocks = vmalloc(sizeof(struct jffs2_eraseblock) * c->nr_blocks); else #endif @@ -356,7 +356,7 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) jffs2_free_ino_caches(c); jffs2_free_raw_node_refs(c); #ifndef __ECOS - if (c->mtd->flags & MTD_NO_VIRTBLOCKS) + if (jffs2_blocks_use_vmalloc(c)) vfree(c->blocks); else #endif diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 79b4bdc76f7..c99451ae4b7 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: fs.c,v 1.62 2005/08/06 04:51:30 nico Exp $ + * $Id: fs.c,v 1.64 2005/09/01 08:42:31 havasi Exp $ * */ @@ -457,19 +457,8 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) #endif c->flash_size = c->mtd->size; - - /* - * Check, if we have to concatenate physical blocks to larger virtual blocks - * to reduce the memorysize for c->blocks. (kmalloc allows max. 128K allocation) - */ c->sector_size = c->mtd->erasesize; blocks = c->flash_size / c->sector_size; - if (!(c->mtd->flags & MTD_NO_VIRTBLOCKS)) { - while ((blocks * sizeof (struct jffs2_eraseblock)) > (128 * 1024)) { - blocks >>= 1; - c->sector_size <<= 1; - } - } /* * Size alignment check @@ -480,10 +469,6 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) c->flash_size / 1024); } - if (c->sector_size != c->mtd->erasesize) - printk(KERN_INFO "jffs2: Erase block size too small (%dKiB). Using virtual blocks size (%dKiB) instead\n", - c->mtd->erasesize / 1024, c->sector_size / 1024); - if (c->flash_size < 5*c->sector_size) { printk(KERN_ERR "jffs2: Too few erase blocks (%d)\n", c->flash_size / c->sector_size); return -EINVAL; @@ -533,7 +518,7 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) iput(root_i); jffs2_free_ino_caches(c); jffs2_free_raw_node_refs(c); - if (c->mtd->flags & MTD_NO_VIRTBLOCKS) + if (jffs2_blocks_use_vmalloc(c)) vfree(c->blocks); else kfree(c->blocks); diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index ce47d5530a7..1533af8b395 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.h,v 1.138 2005/08/17 13:46:23 dedekind Exp $ + * $Id: nodelist.h,v 1.139 2005/08/31 13:51:00 havasi Exp $ * */ @@ -197,6 +197,11 @@ struct jffs2_eraseblock struct jffs2_raw_node_ref *gc_node; /* Next node to be garbage collected */ }; +static inline int jffs2_blocks_use_vmalloc(struct jffs2_sb_info *c) +{ + return ((c->flash_size / c->sector_size) * sizeof (struct jffs2_eraseblock)) > (128 * 1024); +} + /* Calculate totlen from surrounding nodes or eraseblock */ static inline uint32_t __ref_totlen(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index aaf9475cfb6..58496a03a1d 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: super.c,v 1.107 2005/07/12 16:37:08 dedekind Exp $ + * $Id: super.c,v 1.108 2005/08/31 13:51:00 havasi Exp $ * */ @@ -284,7 +284,7 @@ static void jffs2_put_super (struct super_block *sb) up(&c->alloc_sem); jffs2_free_ino_caches(c); jffs2_free_raw_node_refs(c); - if (c->mtd->flags & MTD_NO_VIRTBLOCKS) + if (jffs2_blocks_use_vmalloc(c)) vfree(c->blocks); else kfree(c->blocks); -- cgit v1.2.3 From cd5f6346bc28a41375412b49b290d22ee4e4bbe8 Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Mon, 11 Jul 2005 11:41:53 +0100 Subject: [MTD] Add initial support for OneNAND flash chips OneNAND is a new flash technology from Samsung with integrated SRAM buffers and logic interface. Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/Kconfig | 10 +- drivers/mtd/Makefile | 4 +- drivers/mtd/onenand/Kconfig | 32 + drivers/mtd/onenand/Makefile | 9 + drivers/mtd/onenand/omap-onenand.c | 178 +++++ drivers/mtd/onenand/onenand_base.c | 1462 ++++++++++++++++++++++++++++++++++++ include/linux/mtd/onenand.h | 134 ++++ include/linux/mtd/onenand_regs.h | 167 ++++ 8 files changed, 1990 insertions(+), 6 deletions(-) create mode 100644 drivers/mtd/onenand/Kconfig create mode 100644 drivers/mtd/onenand/Makefile create mode 100644 drivers/mtd/onenand/omap-onenand.c create mode 100644 drivers/mtd/onenand/onenand_base.c create mode 100644 include/linux/mtd/onenand.h create mode 100644 include/linux/mtd/onenand_regs.h diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 843a1cbe086..3dbfbafb348 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -1,4 +1,4 @@ -# $Id: Kconfig,v 1.9 2005/06/16 08:49:29 sean Exp $ +# $Id: Kconfig,v 1.10 2005/07/11 10:39:27 gleixner Exp $ menu "Memory Technology Devices (MTD)" @@ -259,9 +259,9 @@ config RFD_FTL ---help--- This provides support for the flash translation layer known as the Resident Flash Disk (RFD), as used by the Embedded BIOS - of General Software. - See http://www.gensw.com/pages/prod/bios/rfd.htm for further - information. + of General Software. There is a blurb at: + + http://www.gensw.com/pages/prod/bios/rfd.htm source "drivers/mtd/chips/Kconfig" @@ -271,5 +271,7 @@ source "drivers/mtd/devices/Kconfig" source "drivers/mtd/nand/Kconfig" +source "drivers/mtd/onenand/Kconfig" + endmenu diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index cb16b7d478c..fc9374407c2 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -1,7 +1,7 @@ # # Makefile for the memory technology device drivers. # -# $Id: Makefile.common,v 1.6 2005/06/16 08:49:29 sean Exp $ +# $Id: Makefile.common,v 1.7 2005/07/11 10:39:27 gleixner Exp $ # Core functionality. mtd-y := mtdcore.o @@ -25,4 +25,4 @@ obj-$(CONFIG_RFD_FTL) += rfd_ftl.o mtd_blkdevs.o nftl-objs := nftlcore.o nftlmount.o inftl-objs := inftlcore.o inftlmount.o -obj-y += chips/ maps/ devices/ nand/ +obj-y += chips/ maps/ devices/ nand/ onenand/ diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig new file mode 100644 index 00000000000..7d76ede984d --- /dev/null +++ b/drivers/mtd/onenand/Kconfig @@ -0,0 +1,32 @@ +# +# linux/drivers/mtd/onenand/Kconfig +# + +menu "OneNAND Flash Device Drivers (EXPERIMENTAL)" + depends on MTD != n && EXPERIMENTAL + +config MTD_ONENAND + tristate "OneNAND Device Support" + depends on MTD + help + This enables support for accessing all type of OneNAND flash + devices. For further information see + . + +config MTD_ONENAND_VERIFY_WRITE + bool "Verify OneNAND page writes" + depends on MTD_ONENAND + help + This adds an extra check when data is written to the flash. The + OneNAND flash device internally checks only bits transitioning + from 1 to 0. There is a rare possibility that even though the + device thinks the write was successful, a bit could have been + flipped accidentaly due to device wear or something else. + +config MTD_ONENAND_OMAP + tristate "OneNAND Flash device on OMAP board" + depends on ARCH_OMAP && MTD_ONENAND + help + Support for OneNAND flash on TI OMAP board. + +endmenu diff --git a/drivers/mtd/onenand/Makefile b/drivers/mtd/onenand/Makefile new file mode 100644 index 00000000000..f4e75864d8b --- /dev/null +++ b/drivers/mtd/onenand/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for the OneNAND MTD +# + +# Core functionality. +obj-$(CONFIG_MTD_ONENAND) += onenand_base.o + +# Board specific. +obj-$(CONFIG_MTD_ONENAND_OMAP) += omap-onenand.o diff --git a/drivers/mtd/onenand/omap-onenand.c b/drivers/mtd/onenand/omap-onenand.c new file mode 100644 index 00000000000..56e1aec6b83 --- /dev/null +++ b/drivers/mtd/onenand/omap-onenand.c @@ -0,0 +1,178 @@ +/* + * linux/drivers/mtd/onenand/omap-onenand.c + * + * Copyright (c) 2005 Samsung Electronics + * Kyungmin Park + * + * Derived from linux/drivers/mtd/nand/omap-nand-flash.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Overview: + * This is a device driver for the OneNAND flash device for TI OMAP boards. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define OMAP_ONENAND_FLASH_START1 OMAP_CS2A_PHYS +#define OMAP_ONENAND_FLASH_START2 OMAP_CS0_PHYS +/* + * MTD structure for OMAP board + */ +static struct mtd_info *omap_onenand_mtd = NULL; + +/* + * Define partitions for flash devices + */ + +#ifdef CONFIG_MTD_PARTITIONS +static struct mtd_partition static_partition[] = { + { + .name = "X-Loader + U-Boot", + .offset = 0, + .size = SZ_128K, + .mask_flags = MTD_WRITEABLE /* force read-only */ + }, + { + .name = "U-Boot Environment", + .offset = MTDPART_OFS_APPEND, + .size = SZ_128K, + .mask_flags = MTD_WRITEABLE /* force read-only */ + }, + { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = 2 * SZ_1M + }, + { + .name = "filesystem0", + .offset = MTDPART_OFS_APPEND, + .size = SZ_16M, + }, + { + .name = "filesystem1", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, +}; + +const char *part_probes[] = { "cmdlinepart", NULL, }; + +#endif + +/* Scan to find existance of the device at base. + This also allocates oob and data internal buffers */ +static char onenand_name[] = "onenand"; + +/* + * Main initialization routine + */ +static int __init omap_onenand_init (void) +{ + struct onenand_chip *this; + struct mtd_partition *dynamic_partition = 0; + int err = 0; + + /* Allocate memory for MTD device structure and private data */ + omap_onenand_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct onenand_chip), + GFP_KERNEL); + if (!omap_onenand_mtd) { + printk (KERN_WARNING "Unable to allocate OneNAND MTD device structure.\n"); + err = -ENOMEM; + goto out; + } + + /* Get pointer to private data */ + this = (struct onenand_chip *) (&omap_onenand_mtd[1]); + + /* Initialize structures */ + memset((char *) omap_onenand_mtd, 0, sizeof(struct mtd_info) + sizeof(struct onenand_chip)); + + /* Link the private data with the MTD structure */ + omap_onenand_mtd->priv = this; + + /* try the first address */ + this->base = ioremap(OMAP_ONENAND_FLASH_START1, SZ_128K); + omap_onenand_mtd->name = onenand_name; + if (onenand_scan(omap_onenand_mtd, 1)){ + /* try the second address */ + iounmap(this->base); + this->base = ioremap(OMAP_ONENAND_FLASH_START2, SZ_128K); + if (onenand_scan(omap_onenand_mtd, 1)) { + iounmap(this->base); + err = -ENXIO; + goto out_mtd; + } + } + + /* Register the partitions */ + switch (omap_onenand_mtd->size) { + case SZ_128M: + case SZ_64M: + case SZ_32M: +#ifdef CONFIG_MTD_PARTITIONS + err = parse_mtd_partitions(omap_onenand_mtd, part_probes, + &dynamic_partition, 0); + if (err > 0) + err = add_mtd_partitions(omap_onenand_mtd, + dynamic_partition, err); + else if (1) + err = add_mtd_partitions(omap_onenand_mtd, + static_partition, + ARRAY_SIZE(static_partition)); + else +#endif + err = add_mtd_device(omap_onenand_mtd); + if (err) + goto out_buf; + break; + + default: + printk(KERN_WARNING "Unsupported OneNAND device\n"); + err = -ENXIO; + goto out_buf; + } + + return 0; + +out_buf: + onenand_release(omap_onenand_mtd); + iounmap(this->base); +out_mtd: + kfree(omap_onenand_mtd); +out: + return err; +} + +/* + * Clean up routine + */ +static void __exit omap_onenand_cleanup (void) +{ + struct onenand_chip *this = omap_onenand_mtd->priv; + + /* onenand_release frees MTD partitions, MTD structure + and onenand internal buffers */ + onenand_release(omap_onenand_mtd); + iounmap(this->base); + kfree(omap_onenand_mtd); +} + +module_init(omap_onenand_init); +module_exit(omap_onenand_cleanup); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Kyungmin Park "); +MODULE_DESCRIPTION("Glue layer for OneNAND flash on OMAP boards"); diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c new file mode 100644 index 00000000000..bcce22ae3cb --- /dev/null +++ b/drivers/mtd/onenand/onenand_base.c @@ -0,0 +1,1462 @@ +/* + * linux/drivers/mtd/onenand/onenand_base.c + * + * Copyright (C) 2005 Samsung Electronics + * Kyungmin Park + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#include + +/** + * onenand_oob_64 - oob info for large (2KB) page + */ +static struct nand_oobinfo onenand_oob_64 = { + .useecc = MTD_NANDECC_AUTOPLACE, + .eccbytes = 20, + .eccpos = { + 8, 9, 10, 11, 12, + 24, 25, 26, 27, 28, + 40, 41, 42, 43, 44, + 56, 57, 58, 59, 60, + }, + .oobfree = { + {2, 3}, {14, 2}, {18, 3}, {30, 2}, + {24, 3}, {46, 2}, {40, 3}, {62, 2} } +}; + +/** + * onenand_oob_32 - oob info for middle (1KB) page + */ +static struct nand_oobinfo onenand_oob_32 = { + .useecc = MTD_NANDECC_AUTOPLACE, + .eccbytes = 10, + .eccpos = { + 8, 9, 10, 11, 12, + 24, 25, 26, 27, 28, + }, + .oobfree = { {2, 3}, {14, 2}, {18, 3}, {30, 2} } +}; + +static const unsigned char ffchars[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 32 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 48 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 64 */ +}; + +/** + * onenand_readw - [OneNAND Interface] Read OneNAND register + * @param addr address to read + * + * Read OneNAND register + */ +static unsigned short onenand_readw(void __iomem *addr) +{ + return readw(addr); +} + +/** + * onenand_writew - [OneNAND Interface] Write OneNAND register with value + * @param value value to write + * @param addr address to write + * + * Write OneNAND register with value + */ +static void onenand_writew(unsigned short value, void __iomem *addr) +{ + writew(value, addr); +} + +/** + * onenand_block_address - [DEFAULT] Get block address + * @param device the device id + * @param block the block + * @return translated block address if DDP, otherwise same + * + * Setup Start Address 1 Register (F100h) + */ +static int onenand_block_address(int device, int block) +{ + if (device & ONENAND_DEVICE_IS_DDP) { + /* Device Flash Core select, NAND Flash Block Address */ + int dfs = 0, density, mask; + + density = device >> ONENAND_DEVICE_DENSITY_SHIFT; + mask = (1 << (density + 6)); + + if (block & mask) + dfs = 1; + + return (dfs << ONENAND_DDP_SHIFT) | (block & (mask - 1)); + } + + return block; +} + +/** + * onenand_bufferram_address - [DEFAULT] Get bufferram address + * @param device the device id + * @param block the block + * @return set DBS value if DDP, otherwise 0 + * + * Setup Start Address 2 Register (F101h) for DDP + */ +static int onenand_bufferram_address(int device, int block) +{ + if (device & ONENAND_DEVICE_IS_DDP) { + /* Device BufferRAM Select */ + int dbs = 0, density, mask; + + density = device >> ONENAND_DEVICE_DENSITY_SHIFT; + mask = (1 << (density + 6)); + + if (block & mask) + dbs = 1; + + return (dbs << ONENAND_DDP_SHIFT); + } + + return 0; +} + +/** + * onenand_page_address - [DEFAULT] Get page address + * @param page the page address + * @param sector the sector address + * @return combined page and sector address + * + * Setup Start Address 8 Register (F107h) + */ +static int onenand_page_address(int page, int sector) +{ + /* Flash Page Address, Flash Sector Address */ + int fpa, fsa; + + fpa = page & ONENAND_FPA_MASK; + fsa = sector & ONENAND_FSA_MASK; + + return ((fpa << ONENAND_FPA_SHIFT) | fsa); +} + +/** + * onenand_buffer_address - [DEFAULT] Get buffer address + * @param dataram1 DataRAM index + * @param sectors the sector address + * @param count the number of sectors + * @return the start buffer value + * + * Setup Start Buffer Register (F200h) + */ +static int onenand_buffer_address(int dataram1, int sectors, int count) +{ + int bsa, bsc; + + /* BufferRAM Sector Address */ + bsa = sectors & ONENAND_BSA_MASK; + + if (dataram1) + bsa |= ONENAND_BSA_DATARAM1; /* DataRAM1 */ + else + bsa |= ONENAND_BSA_DATARAM0; /* DataRAM0 */ + + /* BufferRAM Sector Count */ + bsc = count & ONENAND_BSC_MASK; + + return ((bsa << ONENAND_BSA_SHIFT) | bsc); +} + +/** + * onenand_command - [DEFAULT] Send command to OneNAND device + * @param mtd MTD device structure + * @param cmd the command to be sent + * @param addr offset to read from or write to + * @param len number of bytes to read or write + * + * Send command to OneNAND device. This function is used for middle/large page + * devices (1KB/2KB Bytes per page) + */ +static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t len) +{ + struct onenand_chip *this = mtd->priv; + int value, readcmd = 0; + int block, page; + /* Now we use page size operation */ + int sectors = 4, count = 4; + + /* Address translation */ + switch (cmd) { + case ONENAND_CMD_UNLOCK: + case ONENAND_CMD_LOCK: + case ONENAND_CMD_LOCK_TIGHT: + block = -1; + page = -1; + break; + + case ONENAND_CMD_ERASE: + case ONENAND_CMD_BUFFERRAM: + block = (int) (addr >> this->erase_shift); + page = -1; + break; + + default: + block = (int) (addr >> this->erase_shift); + page = (int) (addr >> this->page_shift); + page &= this->page_mask; + break; + } + + /* NOTE: The setting order of the registers is very important! */ + if (cmd == ONENAND_CMD_BUFFERRAM) { + /* Select DataRAM for DDP */ + value = onenand_bufferram_address(this->device_id, block); + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); + + /* Switch to the next data buffer */ + ONENAND_SET_NEXT_BUFFERRAM(this); + + return 0; + } + + if (block != -1) { + /* Write 'DFS, FBA' of Flash */ + value = onenand_block_address(this->device_id, block); + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); + } + + if (page != -1) { + int dataram; + + switch (cmd) { + case ONENAND_CMD_READ: + case ONENAND_CMD_READOOB: + dataram = ONENAND_SET_NEXT_BUFFERRAM(this); + readcmd = 1; + break; + + default: + dataram = ONENAND_CURRENT_BUFFERRAM(this); + break; + } + + /* Write 'FPA, FSA' of Flash */ + value = onenand_page_address(page, sectors); + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS8); + + /* Write 'BSA, BSC' of DataRAM */ + value = onenand_buffer_address(dataram, sectors, count); + this->write_word(value, this->base + ONENAND_REG_START_BUFFER); + + if (readcmd) { + /* Select DataRAM for DDP */ + value = onenand_bufferram_address(this->device_id, block); + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); + } + } + + /* Interrupt clear */ + this->write_word(ONENAND_INT_CLEAR, this->base + ONENAND_REG_INTERRUPT); + + /* Write command */ + this->write_word(cmd, this->base + ONENAND_REG_COMMAND); + + return 0; +} + +/** + * onenand_wait - [DEFAULT] wait until the command is done + * @param mtd MTD device structure + * @param state state to select the max. timeout value + * + * Wait for command done. This applies to all OneNAND command + * Read can take up to 30us, erase up to 2ms and program up to 350us + * according to general OneNAND specs + */ +static int onenand_wait(struct mtd_info *mtd, int state) +{ + struct onenand_chip * this = mtd->priv; + unsigned long timeout; + unsigned int flags = ONENAND_INT_MASTER; + unsigned int interrupt = 0; + unsigned int ctrl, ecc; + + /* The 20 msec is enough */ + timeout = jiffies + msecs_to_jiffies(20); + while (time_before(jiffies, timeout)) { + interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); + + if (interrupt & flags) + break; + + if (state != FL_READING) + cond_resched(); + } + /* To get correct interrupt status in timeout case */ + interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); + + ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); + + if (ctrl & ONENAND_CTRL_ERROR) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x", ctrl); + return -EIO; + } + + if (ctrl & ONENAND_CTRL_LOCK) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error = 0x%04x", ctrl); + return -EIO; + } + + if (interrupt & ONENAND_INT_READ) { + ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS); + if (ecc & ONENAND_ECC_2BIT_ALL) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x", ecc); + return -EBADMSG; + } + } + + return 0; +} + +/** + * onenand_bufferram_offset - [DEFAULT] BufferRAM offset + * @param mtd MTD data structure + * @param area BufferRAM area + * @return offset given area + * + * Return BufferRAM offset given area + */ +static inline int onenand_bufferram_offset(struct mtd_info *mtd, int area) +{ + struct onenand_chip *this = mtd->priv; + + if (ONENAND_CURRENT_BUFFERRAM(this)) { + if (area == ONENAND_DATARAM) + return mtd->oobblock; + if (area == ONENAND_SPARERAM) + return mtd->oobsize; + } + + return 0; +} + +/** + * onenand_read_bufferram - [OneNAND Interface] Read the bufferram area + * @param mtd MTD data structure + * @param area BufferRAM area + * @param buffer the databuffer to put/get data + * @param offset offset to read from or write to + * @param count number of bytes to read/write + * + * Read the BufferRAM area + */ +static int onenand_read_bufferram(struct mtd_info *mtd, int area, + unsigned char *buffer, int offset, size_t count) +{ + struct onenand_chip *this = mtd->priv; + void __iomem *bufferram; + + bufferram = this->base + area; + + bufferram += onenand_bufferram_offset(mtd, area); + + memcpy(buffer, bufferram + offset, count); + + return 0; +} + +/** + * onenand_write_bufferram - [OneNAND Interface] Write the bufferram area + * @param mtd MTD data structure + * @param area BufferRAM area + * @param buffer the databuffer to put/get data + * @param offset offset to read from or write to + * @param count number of bytes to read/write + * + * Write the BufferRAM area + */ +static int onenand_write_bufferram(struct mtd_info *mtd, int area, + const unsigned char *buffer, int offset, size_t count) +{ + struct onenand_chip *this = mtd->priv; + void __iomem *bufferram; + + bufferram = this->base + area; + + bufferram += onenand_bufferram_offset(mtd, area); + + memcpy(bufferram + offset, buffer, count); + + return 0; +} + +/** + * onenand_check_bufferram - [GENERIC] Check BufferRAM information + * @param mtd MTD data structure + * @param addr address to check + * @return 1 if there are valid data, otherwise 0 + * + * Check bufferram if there is data we required + */ +static int onenand_check_bufferram(struct mtd_info *mtd, loff_t addr) +{ + struct onenand_chip *this = mtd->priv; + int block, page; + int i; + + block = (int) (addr >> this->erase_shift); + page = (int) (addr >> this->page_shift); + page &= this->page_mask; + + i = ONENAND_CURRENT_BUFFERRAM(this); + + /* Is there valid data? */ + if (this->bufferram[i].block == block && + this->bufferram[i].page == page && + this->bufferram[i].valid) + return 1; + + return 0; +} + +/** + * onenand_update_bufferram - [GENERIC] Update BufferRAM information + * @param mtd MTD data structure + * @param addr address to update + * @param valid valid flag + * + * Update BufferRAM information + */ +static int onenand_update_bufferram(struct mtd_info *mtd, loff_t addr, + int valid) +{ + struct onenand_chip *this = mtd->priv; + int block, page; + int i; + + block = (int) (addr >> this->erase_shift); + page = (int) (addr >> this->page_shift); + page &= this->page_mask; + + /* Invalidate BufferRAM */ + for (i = 0; i < MAX_BUFFERRAM; i++) { + if (this->bufferram[i].block == block && + this->bufferram[i].page == page) + this->bufferram[i].valid = 0; + } + + /* Update BufferRAM */ + i = ONENAND_CURRENT_BUFFERRAM(this); + this->bufferram[i].block = block; + this->bufferram[i].page = page; + this->bufferram[i].valid = valid; + + return 0; +} + +/** + * onenand_get_device - [GENERIC] Get chip for selected access + * @param mtd MTD device structure + * @param new_state the state which is requested + * + * Get the device and lock it for exclusive access + */ +static void onenand_get_device(struct mtd_info *mtd, int new_state) +{ + struct onenand_chip *this = mtd->priv; + DECLARE_WAITQUEUE(wait, current); + + /* + * Grab the lock and see if the device is available + */ + while (1) { + spin_lock(&this->chip_lock); + if (this->state == FL_READY) { + this->state = new_state; + spin_unlock(&this->chip_lock); + break; + } + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&this->wq, &wait); + spin_unlock(&this->chip_lock); + schedule(); + remove_wait_queue(&this->wq, &wait); + } +} + +/** + * onenand_release_device - [GENERIC] release chip + * @param mtd MTD device structure + * + * Deselect, release chip lock and wake up anyone waiting on the device + */ +static void onenand_release_device(struct mtd_info *mtd) +{ + struct onenand_chip *this = mtd->priv; + + /* Release the chip */ + spin_lock(&this->chip_lock); + this->state = FL_READY; + wake_up(&this->wq); + spin_unlock(&this->chip_lock); +} + +/** + * onenand_read_ecc - [MTD Interface] Read data with ECC + * @param mtd MTD device structure + * @param from offset to read from + * @param len number of bytes to read + * @param retlen pointer to variable to store the number of read bytes + * @param buf the databuffer to put data + * @param oob_buf filesystem supplied oob data buffer + * @param oobsel oob selection structure + * + * OneNAND read with ECC + */ +static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf, + u_char *oob_buf, struct nand_oobinfo *oobsel) +{ + struct onenand_chip *this = mtd->priv; + int read = 0, column; + int thislen; + int ret = 0; + + DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); + + /* Do not allow reads past end of device */ + if ((from + len) > mtd->size) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_ecc: Attempt read beyond end of device\n"); + *retlen = 0; + return -EINVAL; + } + + /* Grab the lock and see if the device is available */ + onenand_get_device(mtd, FL_READING); + + /* TODO handling oob */ + + while (read < len) { + thislen = min_t(int, mtd->oobblock, len - read); + + column = from & (mtd->oobblock - 1); + if (column + thislen > mtd->oobblock) + thislen = mtd->oobblock - column; + + if (!onenand_check_bufferram(mtd, from)) { + this->command(mtd, ONENAND_CMD_READ, from, mtd->oobblock); + + ret = this->wait(mtd, FL_READING); + /* First copy data and check return value for ECC handling */ + onenand_update_bufferram(mtd, from, 1); + } + + this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen); + + read += thislen; + + if (read == len) + break; + + if (ret) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_ecc: read failed = %d\n", ret); + goto out; + } + + from += thislen; + buf += thislen; + } + +out: + /* Deselect and wake up anyone waiting on the device */ + onenand_release_device(mtd); + + /* + * Return success, if no ECC failures, else -EBADMSG + * fs driver will take care of that, because + * retlen == desired len and result == -EBADMSG + */ + *retlen = read; + return ret; +} + +/** + * onenand_read - [MTD Interface] MTD compability function for onenand_read_ecc + * @param mtd MTD device structure + * @param from offset to read from + * @param len number of bytes to read + * @param retlen pointer to variable to store the number of read bytes + * @param buf the databuffer to put data + * + * This function simply calls onenand_read_ecc with oob buffer and oobsel = NULL +*/ +static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + return onenand_read_ecc(mtd, from, len, retlen, buf, NULL, NULL); +} + +/** + * onenand_read_oob - [MTD Interface] OneNAND read out-of-band + * @param mtd MTD device structure + * @param from offset to read from + * @param len number of bytes to read + * @param retlen pointer to variable to store the number of read bytes + * @param buf the databuffer to put data + * + * OneNAND read out-of-band data from the spare area + */ +static int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct onenand_chip *this = mtd->priv; + int read = 0, thislen, column; + int ret = 0; + + DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_oob: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); + + /* Initialize return length value */ + *retlen = 0; + + /* Do not allow reads past end of device */ + if (unlikely((from + len) > mtd->size)) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: Attempt read beyond end of device\n"); + return -EINVAL; + } + + /* Grab the lock and see if the device is available */ + onenand_get_device(mtd, FL_READING); + + column = from & (mtd->oobsize - 1); + + while (read < len) { + thislen = mtd->oobsize - column; + thislen = min_t(int, thislen, len); + + this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize); + + onenand_update_bufferram(mtd, from, 0); + + ret = this->wait(mtd, FL_READING); + /* First copy data and check return value for ECC handling */ + + this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); + + read += thislen; + + if (read == len) + break; + + if (ret) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: read failed = %d\n", ret); + goto out; + } + + buf += thislen; + + /* Read more? */ + if (read < len) { + /* Page size */ + from += mtd->oobblock; + column = 0; + } + } + +out: + /* Deselect and wake up anyone waiting on the device */ + onenand_release_device(mtd); + + *retlen = read; + return ret; +} + +#ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE +/** + * onenand_verify_page - [GENERIC] verify the chip contents after a write + * @param mtd MTD device structure + * @param buf the databuffer to verify + * @param block block address + * @param page page address + * + * Check DataRAM area directly + */ +static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, + loff_t addr, int block, int page) +{ + struct onenand_chip *this = mtd->priv; + void __iomem *dataram0, *dataram1; + int ret = 0; + + this->command(mtd, ONENAND_CMD_READ, addr, mtd->oobblock); + + ret = this->wait(mtd, FL_READING); + if (ret) + return ret; + + onenand_update_bufferram(mtd, addr, 1); + + /* Check, if the two dataram areas are same */ + dataram0 = this->base + ONENAND_DATARAM; + dataram1 = dataram0 + mtd->oobblock; + + if (memcmp(dataram0, dataram1, mtd->oobblock)) + return -EBADMSG; + + return 0; +} +#else +#define onenand_verify_page(...) (0) +#endif + +#define NOTALIGNED(x) ((x & (mtd->oobblock - 1)) != 0) + +/** + * onenand_write_ecc - [MTD Interface] OneNAND write with ECC + * @param mtd MTD device structure + * @param to offset to write to + * @param len number of bytes to write + * @param retlen pointer to variable to store the number of written bytes + * @param buf the data to write + * @param eccbuf filesystem supplied oob data buffer + * @param oobsel oob selection structure + * + * OneNAND write with ECC + */ +static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf, + u_char *eccbuf, struct nand_oobinfo *oobsel) +{ + struct onenand_chip *this = mtd->priv; + int written = 0; + int ret = 0; + + DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); + + /* Initialize retlen, in case of early exit */ + *retlen = 0; + + /* Do not allow writes past end of device */ + if (unlikely((to + len) > mtd->size)) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: Attempt write to past end of device\n"); + return -EINVAL; + } + + /* Reject writes, which are not page aligned */ + if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: Attempt to write not page aligned data\n"); + return -EINVAL; + } + + /* Grab the lock and see if the device is available */ + onenand_get_device(mtd, FL_WRITING); + + /* Loop until all data write */ + while (written < len) { + int thislen = min_t(int, mtd->oobblock, len - written); + + this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobblock); + + this->write_bufferram(mtd, ONENAND_DATARAM, buf, 0, thislen); + this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize); + + this->command(mtd, ONENAND_CMD_PROG, to, mtd->oobblock); + + onenand_update_bufferram(mtd, to, 1); + + ret = this->wait(mtd, FL_WRITING); + if (ret) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: write filaed %d\n", ret); + goto out; + } + + written += thislen; + + /* Only check verify write turn on */ + ret = onenand_verify_page(mtd, (u_char *) buf, to, block, page); + if (ret) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: verify failed %d\n", ret); + goto out; + } + + if (written == len) + break; + + to += thislen; + buf += thislen; + } + +out: + /* Deselect and wake up anyone waiting on the device */ + onenand_release_device(mtd); + + *retlen = written; + + return ret; +} + +/** + * onenand_write - [MTD Interface] compability function for onenand_write_ecc + * @param mtd MTD device structure + * @param to offset to write to + * @param len number of bytes to write + * @param retlen pointer to variable to store the number of written bytes + * @param buf the data to write + * + * This function simply calls onenand_write_ecc + * with oob buffer and oobsel = NULL + */ +static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + return onenand_write_ecc(mtd, to, len, retlen, buf, NULL, NULL); +} + +/** + * onenand_write_oob - [MTD Interface] OneNAND write out-of-band + * @param mtd MTD device structure + * @param to offset to write to + * @param len number of bytes to write + * @param retlen pointer to variable to store the number of written bytes + * @param buf the data to write + * + * OneNAND write out-of-band + */ +static int onenand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + struct onenand_chip *this = mtd->priv; + int column, status; + int written = 0; + + DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); + + /* Initialize retlen, in case of early exit */ + *retlen = 0; + + /* Do not allow writes past end of device */ + if (unlikely((to + len) > mtd->size)) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: Attempt write to past end of device\n"); + return -EINVAL; + } + + /* Grab the lock and see if the device is available */ + onenand_get_device(mtd, FL_WRITING); + + /* Loop until all data write */ + while (written < len) { + int thislen = min_t(int, mtd->oobsize, len - written); + + column = to & (mtd->oobsize - 1); + + this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobsize); + + this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize); + this->write_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); + + this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize); + + onenand_update_bufferram(mtd, to, 0); + + status = this->wait(mtd, FL_WRITING); + if (status) + goto out; + + written += thislen; + + if (written == len) + break; + + to += thislen; + buf += thislen; + } + +out: + /* Deselect and wake up anyone waiting on the device */ + onenand_release_device(mtd); + + *retlen = written; + + return 0; +} + +/** + * onenand_writev_ecc - [MTD Interface] write with iovec with ecc + * @param mtd MTD device structure + * @param vecs the iovectors to write + * @param count number of vectors + * @param to offset to write to + * @param retlen pointer to variable to store the number of written bytes + * @param eccbuf filesystem supplied oob data buffer + * @param oobsel oob selection structure + * + * OneNAND write with iovec with ecc + */ +static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, + unsigned long count, loff_t to, size_t *retlen, + u_char *eccbuf, struct nand_oobinfo *oobsel) +{ + struct onenand_chip *this = mtd->priv; + unsigned char buffer[mtd->oobblock], *pbuf; + size_t total_len, len; + int i, written = 0; + int ret = 0; + + /* Preset written len for early exit */ + *retlen = 0; + + /* Calculate total length of data */ + total_len = 0; + for (i = 0; i < count; i++) + total_len += vecs[i].iov_len; + + DEBUG(MTD_DEBUG_LEVEL3, "onenand_writev_ecc: to = 0x%08x, len = %i, count = %ld\n", (unsigned int) to, (unsigned int) total_len, count); + + /* Do not allow write past end of the device */ + if (unlikely((to + total_len) > mtd->size)) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: Attempted write past end of device\n"); + return -EINVAL; + } + + /* Reject writes, which are not page aligned */ + if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(total_len))) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: Attempt to write not page aligned data\n"); + return -EINVAL; + } + + /* Grab the lock and see if the device is available */ + onenand_get_device(mtd, FL_WRITING); + + /* TODO handling oob */ + + /* Loop until all keve's data has been written */ + len = 0; + while (count) { + pbuf = buffer; + /* + * If the given tuple is >= pagesize then + * write it out from the iov + */ + if ((vecs->iov_len - len) >= mtd->oobblock) { + pbuf = vecs->iov_base + len; + + len += mtd->oobblock; + + /* Check, if we have to switch to the next tuple */ + if (len >= (int) vecs->iov_len) { + vecs++; + len = 0; + count--; + } + } else { + int cnt = 0, thislen; + while (cnt < mtd->oobblock) { + thislen = min_t(int, mtd->oobblock - cnt, vecs->iov_len - len); + memcpy(buffer + cnt, vecs->iov_base + len, thislen); + cnt += thislen; + len += thislen; + + /* Check, if we have to switch to the next tuple */ + if (len >= (int) vecs->iov_len) { + vecs++; + len = 0; + count--; + } + } + } + + this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobblock); + + this->write_bufferram(mtd, ONENAND_DATARAM, pbuf, 0, mtd->oobblock); + this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize); + + this->command(mtd, ONENAND_CMD_PROG, to, mtd->oobblock); + + onenand_update_bufferram(mtd, to, 1); + + ret = this->wait(mtd, FL_WRITING); + if (ret) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: write failed %d\n", ret); + goto out; + } + + + /* Only check verify write turn on */ + ret = onenand_verify_page(mtd, (u_char *) pbuf, to, block, page); + if (ret) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: verify failed %d\n", ret); + goto out; + } + + written += mtd->oobblock; + + to += mtd->oobblock; + } + +out: + /* Deselect and wakt up anyone waiting on the device */ + onenand_release_device(mtd); + + *retlen = written; + + return 0; +} + +/** + * onenand_writev - [MTD Interface] compabilty function for onenand_writev_ecc + * @param mtd MTD device structure + * @param vecs the iovectors to write + * @param count number of vectors + * @param to offset to write to + * @param retlen pointer to variable to store the number of written bytes + * + * OneNAND write with kvec. This just calls the ecc function + */ +static int onenand_writev(struct mtd_info *mtd, const struct kvec *vecs, + unsigned long count, loff_t to, size_t *retlen) +{ + return onenand_writev_ecc(mtd, vecs, count, to, retlen, NULL, NULL); +} + +/** + * onenand_erase - [MTD Interface] erase block(s) + * @param mtd MTD device structure + * @param instr erase instruction + * + * Erase one ore more blocks + */ +static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + struct onenand_chip *this = mtd->priv; + unsigned int block_size; + loff_t addr; + int len; + int ret = 0; + + DEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%08x, len = %i\n", (unsigned int) instr->addr, (unsigned int) instr->len); + + block_size = (1 << this->erase_shift); + + /* Start address must align on block boundary */ + if (unlikely(instr->addr & (block_size - 1))) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Unaligned address\n"); + return -EINVAL; + } + + /* Length must align on block boundary */ + if (unlikely(instr->len & (block_size - 1))) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Length not block aligned\n"); + return -EINVAL; + } + + /* Do not allow erase past end of device */ + if (unlikely((instr->len + instr->addr) > mtd->size)) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Erase past end of device\n"); + return -EINVAL; + } + + instr->fail_addr = 0xffffffff; + + /* Grab the lock and see if the device is available */ + onenand_get_device(mtd, FL_ERASING); + + /* Loop throught the pages */ + len = instr->len; + addr = instr->addr; + + instr->state = MTD_ERASING; + + while (len) { + + /* TODO Check badblock */ + + this->command(mtd, ONENAND_CMD_ERASE, addr, block_size); + + ret = this->wait(mtd, FL_ERASING); + /* Check, if it is write protected */ + if (ret) { + if (ret == -EPERM) + DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Device is write protected!!!\n"); + else + DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift)); + instr->state = MTD_ERASE_FAILED; + instr->fail_addr = addr; + goto erase_exit; + } + + len -= block_size; + addr += block_size; + } + + instr->state = MTD_ERASE_DONE; + +erase_exit: + + ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO; + /* Do call back function */ + if (!ret) + mtd_erase_callback(instr); + + /* Deselect and wake up anyone waiting on the device */ + onenand_release_device(mtd); + + return ret; +} + +/** + * onenand_sync - [MTD Interface] sync + * @param mtd MTD device structure + * + * Sync is actually a wait for chip ready function + */ +static void onenand_sync(struct mtd_info *mtd) +{ + DEBUG(MTD_DEBUG_LEVEL3, "onenand_sync: called\n"); + + /* Grab the lock and see if the device is available */ + onenand_get_device(mtd, FL_SYNCING); + + /* Release it and go back */ + onenand_release_device(mtd); +} + +/** + * onenand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad + * @param mtd MTD device structure + * @param ofs offset relative to mtd start + */ +static int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs) +{ + /* + * TODO + * 1. Bad block table (BBT) + * -> using NAND BBT to support JFFS2 + * 2. Bad block management (BBM) + * -> bad block replace scheme + * + * Currently we do nothing + */ + return 0; +} + +/** + * onenand_block_markbad - [MTD Interface] Mark the block at the given offset as bad + * @param mtd MTD device structure + * @param ofs offset relative to mtd start + */ +static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs) +{ + /* see above */ + return 0; +} + +/** + * onenand_unlock - [MTD Interface] Unlock block(s) + * @param mtd MTD device structure + * @param ofs offset relative to mtd start + * @param len number of bytes to unlock + * + * Unlock one or more blocks + */ +static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) +{ + struct onenand_chip *this = mtd->priv; + int start, end, block, value, status; + + start = ofs >> this->erase_shift; + end = len >> this->erase_shift; + + /* Continuous lock scheme */ + if (this->options & ONENAND_CONT_LOCK) { + /* Set start block address */ + this->write_word(start, this->base + ONENAND_REG_START_BLOCK_ADDRESS); + /* Set end block address */ + this->write_word(end - 1, this->base + ONENAND_REG_END_BLOCK_ADDRESS); + /* Write unlock command */ + this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0); + + /* There's no return value */ + this->wait(mtd, FL_UNLOCKING); + + /* Sanity check */ + while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) + & ONENAND_CTRL_ONGO) + continue; + + /* Check lock status */ + status = this->read_word(this->base + ONENAND_REG_WP_STATUS); + if (!(status & ONENAND_WP_US)) + printk(KERN_ERR "wp status = 0x%x\n", status); + + return 0; + } + + /* Block lock scheme */ + for (block = start; block < end; block++) { + /* Set start block address */ + this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS); + /* Write unlock command */ + this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0); + + /* There's no return value */ + this->wait(mtd, FL_UNLOCKING); + + /* Sanity check */ + while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) + & ONENAND_CTRL_ONGO) + continue; + + /* Set block address for read block status */ + value = onenand_block_address(this->device_id, block); + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); + + /* Check lock status */ + status = this->read_word(this->base + ONENAND_REG_WP_STATUS); + if (!(status & ONENAND_WP_US)) + printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status); + } + + return 0; +} + +/** + * onenand_print_device_info - Print device ID + * @param device device ID + * + * Print device ID + */ +static void onenand_print_device_info(int device) +{ + int vcc, demuxed, ddp, density; + + vcc = device & ONENAND_DEVICE_VCC_MASK; + demuxed = device & ONENAND_DEVICE_IS_DEMUX; + ddp = device & ONENAND_DEVICE_IS_DDP; + density = device >> ONENAND_DEVICE_DENSITY_SHIFT; + printk(KERN_INFO "%sOneNAND%s %dMB %sV 16-bit (0x%02x)\n", + demuxed ? "" : "Muxed ", + ddp ? "(DDP)" : "", + (16 << density), + vcc ? "2.65/3.3" : "1.8", + device); +} + +static const struct onenand_manufacturers onenand_manuf_ids[] = { + {ONENAND_MFR_SAMSUNG, "Samsung"}, + {ONENAND_MFR_UNKNOWN, "Unknown"} +}; + +/** + * onenand_check_maf - Check manufacturer ID + * @param manuf manufacturer ID + * + * Check manufacturer ID + */ +static int onenand_check_maf(int manuf) +{ + int i; + + for (i = 0; onenand_manuf_ids[i].id; i++) { + if (manuf == onenand_manuf_ids[i].id) + break; + } + + printk(KERN_DEBUG "OneNAND Manufacturer: %s\n", + onenand_manuf_ids[i].name); + + return (i != ONENAND_MFR_UNKNOWN); +} + +/** + * onenand_probe - [OneNAND Interface] Probe the OneNAND device + * @param mtd MTD device structure + * + * OneNAND detection method: + * Compare the the values from command with ones from register + */ +static int onenand_probe(struct mtd_info *mtd) +{ + struct onenand_chip *this = mtd->priv; + int bram_maf_id, bram_dev_id, maf_id, dev_id; + int version_id; + int density; + + /* Send the command for reading device ID from BootRAM */ + this->write_word(ONENAND_CMD_READID, this->base + ONENAND_BOOTRAM); + + /* Read manufacturer and device IDs from BootRAM */ + bram_maf_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x0); + bram_dev_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x2); + + /* Check manufacturer ID */ + if (onenand_check_maf(bram_maf_id)) + return -ENXIO; + + /* Reset OneNAND to read default register values */ + this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM); + + /* Read manufacturer and device IDs from Register */ + maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); + dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); + + /* Check OneNAND device */ + if (maf_id != bram_maf_id || dev_id != bram_dev_id) + return -ENXIO; + + /* Flash device information */ + onenand_print_device_info(dev_id); + this->device_id = dev_id; + + density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT; + this->chipsize = (16 << density) << 20; + + /* OneNAND page size & block size */ + /* The data buffer size is equal to page size */ + mtd->oobblock = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE); + mtd->oobsize = mtd->oobblock >> 5; + /* Pagers per block is always 64 in OneNAND */ + mtd->erasesize = mtd->oobblock << 6; + + this->erase_shift = ffs(mtd->erasesize) - 1; + this->page_shift = ffs(mtd->oobblock) - 1; + this->ppb_shift = (this->erase_shift - this->page_shift); + this->page_mask = (mtd->erasesize / mtd->oobblock) - 1; + + /* REVIST: Multichip handling */ + + mtd->size = this->chipsize; + + /* Version ID */ + version_id = this->read_word(this->base + ONENAND_REG_VERSION_ID); + printk(KERN_DEBUG "OneNAND version = 0x%04x\n", version_id); + + /* Lock scheme */ + if (density <= ONENAND_DEVICE_DENSITY_512Mb && + !(version_id >> ONENAND_VERSION_PROCESS_SHIFT)) { + printk(KERN_INFO "Lock scheme is Continues Lock\n"); + this->options |= ONENAND_CONT_LOCK; + } + + return 0; +} + + +/** + * onenand_scan - [OneNAND Interface] Scan for the OneNAND device + * @param mtd MTD device structure + * @param maxchips Number of chips to scan for + * + * This fills out all the not initialized function pointers + * with the defaults. + * The flash ID is read and the mtd/chip structures are + * filled with the appropriate values. + */ +int onenand_scan(struct mtd_info *mtd, int maxchips) +{ + struct onenand_chip *this = mtd->priv; + + if (!this->read_word) + this->read_word = onenand_readw; + if (!this->write_word) + this->write_word = onenand_writew; + + if (!this->command) + this->command = onenand_command; + if (!this->wait) + this->wait = onenand_wait; + + if (!this->read_bufferram) + this->read_bufferram = onenand_read_bufferram; + if (!this->write_bufferram) + this->write_bufferram = onenand_write_bufferram; + + if (onenand_probe(mtd)) + return -ENXIO; + + this->state = FL_READY; + init_waitqueue_head(&this->wq); + spin_lock_init(&this->chip_lock); + + switch (mtd->oobsize) { + case 64: + this->autooob = &onenand_oob_64; + break; + + case 32: + this->autooob = &onenand_oob_32; + break; + + default: + printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n", + mtd->oobsize); + /* To prevent kernel oops */ + this->autooob = &onenand_oob_32; + break; + } + + memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo)); + + /* Fill in remaining MTD driver data */ + mtd->type = MTD_NANDFLASH; + mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC; + mtd->ecctype = MTD_ECC_SW; + mtd->erase = onenand_erase; + mtd->point = NULL; + mtd->unpoint = NULL; + mtd->read = onenand_read; + mtd->write = onenand_write; + mtd->read_ecc = onenand_read_ecc; + mtd->write_ecc = onenand_write_ecc; + mtd->read_oob = onenand_read_oob; + mtd->write_oob = onenand_write_oob; + mtd->readv = NULL; + mtd->readv_ecc = NULL; + mtd->writev = onenand_writev; + mtd->writev_ecc = onenand_writev_ecc; + mtd->sync = onenand_sync; + mtd->lock = NULL; + mtd->unlock = onenand_unlock; + mtd->suspend = NULL; + mtd->resume = NULL; + mtd->block_isbad = onenand_block_isbad; + mtd->block_markbad = onenand_block_markbad; + mtd->owner = THIS_MODULE; + + /* Unlock whole block */ + mtd->unlock(mtd, 0x0, this->chipsize); + + return 0; +} + +/** + * onenand_release - [OneNAND Interface] Free resources held by the OneNAND device + * @param mtd MTD device structure + */ +void onenand_release(struct mtd_info *mtd) +{ +#ifdef CONFIG_MTD_PARTITIONS + /* Deregister partitions */ + del_mtd_partitions (mtd); +#endif + /* Deregister the device */ + del_mtd_device (mtd); +} + +EXPORT_SYMBOL_GPL(onenand_scan); +EXPORT_SYMBOL_GPL(onenand_release); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Kyungmin Park "); +MODULE_DESCRIPTION("Generic OneNAND flash driver code"); diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h new file mode 100644 index 00000000000..b9a64117d64 --- /dev/null +++ b/include/linux/mtd/onenand.h @@ -0,0 +1,134 @@ +/* + * linux/include/linux/mtd/onenand.h + * + * Copyright (C) 2005 Samsung Electronics + * Kyungmin Park + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __LINUX_MTD_ONENAND_H +#define __LINUX_MTD_ONENAND_H + +#include +#include + +#define MAX_BUFFERRAM 2 + +/* Scan and identify a OneNAND device */ +extern int onenand_scan(struct mtd_info *mtd, int max_chips); +/* Free resources held by the OneNAND device */ +extern void onenand_release(struct mtd_info *mtd); + +/** + * onenand_state_t - chip states + * Enumeration for OneNAND flash chip state + */ +typedef enum { + FL_READY, + FL_READING, + FL_WRITING, + FL_ERASING, + FL_SYNCING, + FL_UNLOCKING, + FL_LOCKING, +} onenand_state_t; + +/** + * struct onenand_bufferram - OneNAND BufferRAM Data + * @param block block address in BufferRAM + * @param page page address in BufferRAM + * @param valid valid flag + */ +struct onenand_bufferram { + int block; + int page; + int valid; +}; + +/** + * struct onenand_chip - OneNAND Private Flash Chip Data + * @param base [BOARDSPECIFIC] address to access OneNAND + * @param chipsize [INTERN] the size of one chip for multichip arrays + * @param device_id [INTERN] device ID + * @param verstion_id [INTERN] version ID + * @param options [BOARDSPECIFIC] various chip options. They can partly be set to inform onenand_scan about + * @param erase_shift [INTERN] number of address bits in a block + * @param page_shift [INTERN] number of address bits in a page + * @param ppb_shift [INTERN] number of address bits in a pages per block + * @param page_mask [INTERN] a page per block mask + * @param bufferam_index [INTERN] BufferRAM index + * @param bufferam [INTERN] BufferRAM info + * @param readw [REPLACEABLE] hardware specific function for read short + * @param writew [REPLACEABLE] hardware specific function for write short + * @param command [REPLACEABLE] hardware specific function for writing commands to the chip + * @param wait [REPLACEABLE] hardware specific function for wait on ready + * @param read_bufferram [REPLACEABLE] hardware specific function for BufferRAM Area + * @param write_bufferram [REPLACEABLE] hardware specific function for BufferRAM Area + * @param chip_lock [INTERN] spinlock used to protect access to this structure and the chip + * @param wq [INTERN] wait queue to sleep on if a OneNAND operation is in progress + * @param state [INTERN] the current state of the OneNAND device + * @param autooob [REPLACEABLE] the default (auto)placement scheme + * @param priv [OPTIONAL] pointer to private chip date + */ +struct onenand_chip { + void __iomem *base; + unsigned int chipsize; + unsigned int device_id; + unsigned int options; + + unsigned int erase_shift; + unsigned int page_shift; + unsigned int ppb_shift; /* Pages per block shift */ + unsigned int page_mask; + + unsigned int bufferram_index; + struct onenand_bufferram bufferram[MAX_BUFFERRAM]; + + int (*command)(struct mtd_info *mtd, int cmd, loff_t address, size_t len); + int (*wait)(struct mtd_info *mtd, int state); + int (*read_bufferram)(struct mtd_info *mtd, int area, + unsigned char *buffer, int offset, size_t count); + int (*write_bufferram)(struct mtd_info *mtd, int area, + const unsigned char *buffer, int offset, size_t count); + unsigned short (*read_word)(void __iomem *addr); + void (*write_word)(unsigned short value, void __iomem *addr); + + spinlock_t chip_lock; + wait_queue_head_t wq; + onenand_state_t state; + + struct nand_oobinfo *autooob; + + void *priv; +}; + +#define ONENAND_CURRENT_BUFFERRAM(this) (this->bufferram_index) +#define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1) +#define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1) + +/* + * Options bits + */ +#define ONENAND_CONT_LOCK (0x0001) + + +/* + * OneNAND Flash Manufacturer ID Codes + */ +#define ONENAND_MFR_SAMSUNG 0xec +#define ONENAND_MFR_UNKNOWN 0x00 + +/** + * struct nand_manufacturers - NAND Flash Manufacturer ID Structure + * @param name: Manufacturer name + * @param id: manufacturer ID code of device. +*/ +struct onenand_manufacturers { + int id; + char *name; +}; + +#endif /* __LINUX_MTD_ONENAND_H */ diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h new file mode 100644 index 00000000000..4a2daad7d73 --- /dev/null +++ b/include/linux/mtd/onenand_regs.h @@ -0,0 +1,167 @@ +/* + * linux/include/linux/mtd/onenand_regs.h + * + * OneNAND Register header file + * + * Copyright (C) 2005 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ONENAND_REG_H +#define __ONENAND_REG_H + +/* Memory Address Map Translation (Word order) */ +#define ONENAND_MEMORY_MAP(x) ((x) << 1) + +/* + * External BufferRAM area + */ +#define ONENAND_BOOTRAM ONENAND_MEMORY_MAP(0x0000) +#define ONENAND_DATARAM ONENAND_MEMORY_MAP(0x0200) +#define ONENAND_SPARERAM ONENAND_MEMORY_MAP(0x8010) + +/* + * OneNAND Registers + */ +#define ONENAND_REG_MANUFACTURER_ID ONENAND_MEMORY_MAP(0xF000) +#define ONENAND_REG_DEVICE_ID ONENAND_MEMORY_MAP(0xF001) +#define ONENAND_REG_VERSION_ID ONENAND_MEMORY_MAP(0xF002) +#define ONENAND_REG_DATA_BUFFER_SIZE ONENAND_MEMORY_MAP(0xF003) +#define ONENAND_REG_BOOT_BUFFER_SIZE ONENAND_MEMORY_MAP(0xF004) +#define ONENAND_REG_NUM_BUFFERS ONENAND_MEMORY_MAP(0xF005) +#define ONENAND_REG_TECHNOLOGY ONENAND_MEMORY_MAP(0xF006) + +#define ONENAND_REG_START_ADDRESS1 ONENAND_MEMORY_MAP(0xF100) +#define ONENAND_REG_START_ADDRESS2 ONENAND_MEMORY_MAP(0xF101) +#define ONENAND_REG_START_ADDRESS3 ONENAND_MEMORY_MAP(0xF102) +#define ONENAND_REG_START_ADDRESS4 ONENAND_MEMORY_MAP(0xF103) +#define ONENAND_REG_START_ADDRESS5 ONENAND_MEMORY_MAP(0xF104) +#define ONENAND_REG_START_ADDRESS6 ONENAND_MEMORY_MAP(0xF105) +#define ONENAND_REG_START_ADDRESS7 ONENAND_MEMORY_MAP(0xF106) +#define ONENAND_REG_START_ADDRESS8 ONENAND_MEMORY_MAP(0xF107) + +#define ONENAND_REG_START_BUFFER ONENAND_MEMORY_MAP(0xF200) +#define ONENAND_REG_COMMAND ONENAND_MEMORY_MAP(0xF220) +#define ONENAND_REG_SYS_CFG1 ONENAND_MEMORY_MAP(0xF221) +#define ONENAND_REG_SYS_CFG2 ONENAND_MEMORY_MAP(0xF222) +#define ONENAND_REG_CTRL_STATUS ONENAND_MEMORY_MAP(0xF240) +#define ONENAND_REG_INTERRUPT ONENAND_MEMORY_MAP(0xF241) +#define ONENAND_REG_START_BLOCK_ADDRESS ONENAND_MEMORY_MAP(0xF24C) +#define ONENAND_REG_END_BLOCK_ADDRESS ONENAND_MEMORY_MAP(0xF24D) +#define ONENAND_REG_WP_STATUS ONENAND_MEMORY_MAP(0xF24E) + +#define ONENAND_REG_ECC_STATUS ONENAND_MEMORY_MAP(0xFF00) +#define ONENAND_REG_ECC_M0 ONENAND_MEMORY_MAP(0xFF01) +#define ONENAND_REG_ECC_S0 ONENAND_MEMORY_MAP(0xFF02) +#define ONENAND_REG_ECC_M1 ONENAND_MEMORY_MAP(0xFF03) +#define ONENAND_REG_ECC_S1 ONENAND_MEMORY_MAP(0xFF04) +#define ONENAND_REG_ECC_M2 ONENAND_MEMORY_MAP(0xFF05) +#define ONENAND_REG_ECC_S2 ONENAND_MEMORY_MAP(0xFF06) +#define ONENAND_REG_ECC_M3 ONENAND_MEMORY_MAP(0xFF07) +#define ONENAND_REG_ECC_S3 ONENAND_MEMORY_MAP(0xFF08) + +/* + * Device ID Register F001h (R) + */ +#define ONENAND_DEVICE_DENSITY_SHIFT (4) +#define ONENAND_DEVICE_IS_DDP (1 << 3) +#define ONENAND_DEVICE_IS_DEMUX (1 << 2) +#define ONENAND_DEVICE_VCC_MASK (0x3) + +#define ONENAND_DEVICE_DENSITY_512Mb (0x002) + +/* + * Version ID Register F002h (R) + */ +#define ONENAND_VERSION_PROCESS_SHIFT (8) + +/* + * Start Address 1 F100h (R/W) + */ +#define ONENAND_DDP_SHIFT (15) + +/* + * Start Address 8 F107h (R/W) + */ +#define ONENAND_FPA_MASK (0x3f) +#define ONENAND_FPA_SHIFT (2) +#define ONENAND_FSA_MASK (0x03) + +/* + * Start Buffer Register F200h (R/W) + */ +#define ONENAND_BSA_MASK (0x03) +#define ONENAND_BSA_SHIFT (8) +#define ONENAND_BSA_BOOTRAM (0 << 2) +#define ONENAND_BSA_DATARAM0 (2 << 2) +#define ONENAND_BSA_DATARAM1 (3 << 2) +#define ONENAND_BSC_MASK (0x03) + +/* + * Command Register F220h (R/W) + */ +#define ONENAND_CMD_READ (0x00) +#define ONENAND_CMD_READOOB (0x13) +#define ONENAND_CMD_PROG (0x80) +#define ONENAND_CMD_PROGOOB (0x1A) +#define ONENAND_CMD_UNLOCK (0x23) +#define ONENAND_CMD_LOCK (0x2A) +#define ONENAND_CMD_LOCK_TIGHT (0x2C) +#define ONENAND_CMD_ERASE (0x94) +#define ONENAND_CMD_RESET (0xF0) +#define ONENAND_CMD_READID (0x90) + +/* NOTE: Those are not *REAL* commands */ +#define ONENAND_CMD_BUFFERRAM (0x1978) + +/* + * System Configuration 1 Register F221h (R, R/W) + */ +#define ONENAND_SYS_CFG1_SYNC_READ (1 << 15) +#define ONENAND_SYS_CFG1_BRL (1 << 12) +#define ONENAND_SYS_CFG1_BL (1 << 9) +#define ONENAND_SYS_CFG1_NO_ECC (1 << 8) +#define ONENAND_SYS_CFG1_RDY (1 << 7) +#define ONENAND_SYS_CFG1_INT (1 << 6) +#define ONENAND_SYS_CFG1_IOBE (1 << 5) +#define ONENAND_SYS_CFG1_RDY_CONF (1 << 4) + +/* + * Controller Status Register F240h (R) + */ +#define ONENAND_CTRL_ONGO (1 << 15) +#define ONENAND_CTRL_LOCK (1 << 14) +#define ONENAND_CTRL_LOAD (1 << 13) +#define ONENAND_CTRL_PROGRAM (1 << 12) +#define ONENAND_CTRL_ERASE (1 << 11) +#define ONENAND_CTRL_ERROR (1 << 10) +#define ONENAND_CTRL_RSTB (1 << 7) + +/* + * Interrupt Status Register F241h (R) + */ +#define ONENAND_INT_MASTER (1 << 15) +#define ONENAND_INT_READ (1 << 7) +#define ONENAND_INT_WRITE (1 << 6) +#define ONENAND_INT_ERASE (1 << 5) +#define ONENAND_INT_RESET (1 << 4) +#define ONENAND_INT_CLEAR (0 << 0) + +/* + * NAND Flash Write Protection Status Register F24Eh (R) + */ +#define ONENAND_WP_US (1 << 2) +#define ONENAND_WP_LS (1 << 1) +#define ONENAND_WP_LTS (1 << 0) + +/* + * ECC Status Reigser FF00h (R) + */ +#define ONENAND_ECC_1BIT (1 << 0) +#define ONENAND_ECC_2BIT (1 << 1) +#define ONENAND_ECC_2BIT_ALL (0xAAAA) + +#endif /* __ONENAND_REG_H */ -- cgit v1.2.3 From 52b0eea73de05df33c51ca652e288a3ba1bba03b Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Sat, 3 Sep 2005 07:07:19 +0100 Subject: [PATCH] OneNAND: Sync. Burst Read support Add OneNAND Sync. Burst Read support Tested with OMAP platform Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/Kconfig | 6 ++++ drivers/mtd/onenand/omap-onenand.c | 66 ++++++++++++++++++++++++++++++++++++-- drivers/mtd/onenand/onenand_base.c | 39 ++++++++++++++++++++-- include/linux/mtd/onenand.h | 1 + include/linux/mtd/onenand_regs.h | 17 ++++++++-- 5 files changed, 123 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig index 7d76ede984d..186ea9dc094 100644 --- a/drivers/mtd/onenand/Kconfig +++ b/drivers/mtd/onenand/Kconfig @@ -29,4 +29,10 @@ config MTD_ONENAND_OMAP help Support for OneNAND flash on TI OMAP board. +config MTD_ONENAND_SYNC_READ + bool "OneNAND Sync. Burst Read Support" + depends on ARCH_OMAP + help + This enables support for Sync. Burst Read. + endmenu diff --git a/drivers/mtd/onenand/omap-onenand.c b/drivers/mtd/onenand/omap-onenand.c index 56e1aec6b83..7c89549f7f5 100644 --- a/drivers/mtd/onenand/omap-onenand.c +++ b/drivers/mtd/onenand/omap-onenand.c @@ -25,9 +25,10 @@ #include #include #include +#include #define OMAP_ONENAND_FLASH_START1 OMAP_CS2A_PHYS -#define OMAP_ONENAND_FLASH_START2 OMAP_CS0_PHYS +#define OMAP_ONENAND_FLASH_START2 omap_cs3_phys() /* * MTD structure for OMAP board */ @@ -68,10 +69,66 @@ static struct mtd_partition static_partition[] = { }, }; -const char *part_probes[] = { "cmdlinepart", NULL, }; +static const char *part_probes[] = { "cmdlinepart", NULL, }; #endif +#ifdef CONFIG_MTD_ONENAND_SYNC_READ +static unsigned int omap_emifs_cs; + +static void omap_find_emifs_cs(unsigned int addr) +{ + /* Check CS3 */ + if (OMAP_EMIFS_CONFIG_REG & OMAP_EMIFS_CONFIG_BM && addr == 0x0) { + omap_emifs_cs = 3; + } else { + omap_emifs_cs = (addr >> 26); + } +} + +/** + * omap_onenand_mmcontrol - Control OMAP EMIFS + */ +static void omap_onenand_mmcontrol(struct mtd_info *mtd, int sync_read) +{ + struct onenand_chip *this = mtd->priv; + static unsigned long omap_emifs_ccs, omap_emifs_acs; + static unsigned long onenand_sys_cfg1; + int config, emifs_ccs, emifs_acs; + + if (sync_read) { + /* + * Note: BRL and RDWST is equal + */ + omap_emifs_ccs = EMIFS_CCS(omap_emifs_cs); + omap_emifs_acs = EMIFS_ACS(omap_emifs_cs); + + emifs_ccs = 0x41141; + emifs_acs = 0x1; + + /* OneNAND System Configuration 1 */ + onenand_sys_cfg1 = this->read_word(this->base + ONENAND_REG_SYS_CFG1); + config = (onenand_sys_cfg1 + & ~(0x3f << ONENAND_SYS_CFG1_BL_SHIFT)) + | ONENAND_SYS_CFG1_SYNC_READ + | ONENAND_SYS_CFG1_BRL_4 + | ONENAND_SYS_CFG1_BL_8; + } else { + emifs_ccs = omap_emifs_ccs; + emifs_acs = omap_emifs_acs; + config = onenand_sys_cfg1; + } + + this->write_word(config, this->base + ONENAND_REG_SYS_CFG1); + EMIFS_CCS(omap_emifs_cs) = emifs_ccs; + EMIFS_ACS(omap_emifs_cs) = emifs_acs; +} +#else +#define omap_find_emifs_cs(x) do { } while (0) +#define omap_onenand_mmcontrol NULL +#endif + + /* Scan to find existance of the device at base. This also allocates oob and data internal buffers */ static char onenand_name[] = "onenand"; @@ -102,14 +159,19 @@ static int __init omap_onenand_init (void) /* Link the private data with the MTD structure */ omap_onenand_mtd->priv = this; + this->mmcontrol = omap_onenand_mmcontrol; /* try the first address */ this->base = ioremap(OMAP_ONENAND_FLASH_START1, SZ_128K); + omap_find_emifs_cs(OMAP_ONENAND_FLASH_START1); + omap_onenand_mtd->name = onenand_name; if (onenand_scan(omap_onenand_mtd, 1)){ /* try the second address */ iounmap(this->base); this->base = ioremap(OMAP_ONENAND_FLASH_START2, SZ_128K); + omap_find_emifs_cs(OMAP_ONENAND_FLASH_START2); + if (onenand_scan(omap_onenand_mtd, 1)) { iounmap(this->base); err = -ENXIO; diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index bcce22ae3cb..e8748950577 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -378,6 +378,35 @@ static int onenand_read_bufferram(struct mtd_info *mtd, int area, return 0; } +/** + * onenand_sync_read_bufferram - [OneNAND Interface] Read the bufferram area with Sync. Burst mode + * @param mtd MTD data structure + * @param area BufferRAM area + * @param buffer the databuffer to put/get data + * @param offset offset to read from or write to + * @param count number of bytes to read/write + * + * Read the BufferRAM area with Sync. Burst Mode + */ +static int onenand_sync_read_bufferram(struct mtd_info *mtd, int area, + unsigned char *buffer, int offset, size_t count) +{ + struct onenand_chip *this = mtd->priv; + void __iomem *bufferram; + + bufferram = this->base + area; + + bufferram += onenand_bufferram_offset(mtd, area); + + this->mmcontrol(mtd, ONENAND_SYS_CFG1_SYNC_READ); + + memcpy(buffer, bufferram + offset, count); + + this->mmcontrol(mtd, 0); + + return 0; +} + /** * onenand_write_bufferram - [OneNAND Interface] Write the bufferram area * @param mtd MTD data structure @@ -1273,8 +1302,8 @@ static int onenand_check_maf(int manuf) break; } - printk(KERN_DEBUG "OneNAND Manufacturer: %s\n", - onenand_manuf_ids[i].name); + printk(KERN_DEBUG "OneNAND Manufacturer: %s (0x%0x)\n", + onenand_manuf_ids[i].name, manuf); return (i != ONENAND_MFR_UNKNOWN); } @@ -1385,6 +1414,12 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) if (onenand_probe(mtd)) return -ENXIO; + /* Set Sync. Burst Read after probing */ + if (this->mmcontrol) { + printk(KERN_INFO "OneNAND Sync. Burst Read support\n"); + this->read_bufferram = onenand_sync_read_bufferram; + } + this->state = FL_READY; init_waitqueue_head(&this->wq); spin_lock_init(&this->chip_lock); diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index b9a64117d64..c557caa24a6 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -95,6 +95,7 @@ struct onenand_chip { const unsigned char *buffer, int offset, size_t count); unsigned short (*read_word)(void __iomem *addr); void (*write_word)(unsigned short value, void __iomem *addr); + void (*mmcontrol)(struct mtd_info *mtd, int sync_read); spinlock_t chip_lock; wait_queue_head_t wq; diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h index 4a2daad7d73..d7832ef8ed6 100644 --- a/include/linux/mtd/onenand_regs.h +++ b/include/linux/mtd/onenand_regs.h @@ -121,8 +121,21 @@ * System Configuration 1 Register F221h (R, R/W) */ #define ONENAND_SYS_CFG1_SYNC_READ (1 << 15) -#define ONENAND_SYS_CFG1_BRL (1 << 12) -#define ONENAND_SYS_CFG1_BL (1 << 9) +#define ONENAND_SYS_CFG1_BRL_7 (7 << 12) +#define ONENAND_SYS_CFG1_BRL_6 (6 << 12) +#define ONENAND_SYS_CFG1_BRL_5 (5 << 12) +#define ONENAND_SYS_CFG1_BRL_4 (4 << 12) +#define ONENAND_SYS_CFG1_BRL_3 (3 << 12) +#define ONENAND_SYS_CFG1_BRL_10 (2 << 12) +#define ONENAND_SYS_CFG1_BRL_9 (1 << 12) +#define ONENAND_SYS_CFG1_BRL_8 (0 << 12) +#define ONENAND_SYS_CFG1_BRL_SHIFT (12) +#define ONENAND_SYS_CFG1_BL_32 (4 << 9) +#define ONENAND_SYS_CFG1_BL_16 (3 << 9) +#define ONENAND_SYS_CFG1_BL_8 (2 << 9) +#define ONENAND_SYS_CFG1_BL_4 (1 << 9) +#define ONENAND_SYS_CFG1_BL_CONT (0 << 9) +#define ONENAND_SYS_CFG1_BL_SHIFT (9) #define ONENAND_SYS_CFG1_NO_ECC (1 << 8) #define ONENAND_SYS_CFG1_RDY (1 << 7) #define ONENAND_SYS_CFG1_INT (1 << 6) -- cgit v1.2.3 From cdc001305da4f057353911018e28f26f8f879061 Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Sat, 3 Sep 2005 07:15:48 +0100 Subject: [PATCH] OneNAND: Simple Bad Block handling support Based on NAND memory bad block table code Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/Makefile | 4 +- drivers/mtd/onenand/onenand_base.c | 105 ++++++++++++++++++++++++++++++------- include/linux/mtd/onenand.h | 9 ++++ 3 files changed, 98 insertions(+), 20 deletions(-) diff --git a/drivers/mtd/onenand/Makefile b/drivers/mtd/onenand/Makefile index f4e75864d8b..243c7592a11 100644 --- a/drivers/mtd/onenand/Makefile +++ b/drivers/mtd/onenand/Makefile @@ -3,7 +3,9 @@ # # Core functionality. -obj-$(CONFIG_MTD_ONENAND) += onenand_base.o +obj-$(CONFIG_MTD_ONENAND) += onenand.o # Board specific. obj-$(CONFIG_MTD_ONENAND_OMAP) += omap-onenand.o + +onenand-objs = onenand_base.o onenand_bbt.o diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index e8748950577..bdeac01e659 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -311,19 +311,21 @@ static int onenand_wait(struct mtd_info *mtd, int state) ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); if (ctrl & ONENAND_CTRL_ERROR) { - DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x", ctrl); - return -EIO; + /* It maybe occur at initial bad block */ + DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x\n", ctrl); + /* Clear other interrupt bits for preventing ECC error */ + interrupt &= ONENAND_INT_MASTER; } if (ctrl & ONENAND_CTRL_LOCK) { - DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error = 0x%04x", ctrl); - return -EIO; + DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error = 0x%04x\n", ctrl); + return -EACCES; } if (interrupt & ONENAND_INT_READ) { ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS); if (ecc & ONENAND_ECC_2BIT_ALL) { - DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x", ecc); + DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x\n", ecc); return -EBADMSG; } } @@ -1059,6 +1061,25 @@ static int onenand_writev(struct mtd_info *mtd, const struct kvec *vecs, return onenand_writev_ecc(mtd, vecs, count, to, retlen, NULL, NULL); } +/** + * onenand_block_checkbad - [GENERIC] Check if a block is marked bad + * @param mtd MTD device structure + * @param ofs offset from device start + * @param getchip 0, if the chip is already selected + * @param allowbbt 1, if its allowed to access the bbt area + * + * Check, if the block is bad. Either by reading the bad block table or + * calling of the scan function. + */ +static int onenand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt) +{ + struct onenand_chip *this = mtd->priv; + struct bbm_info *bbm = this->bbm; + + /* Return info from the table */ + return bbm->isbad_bbt(mtd, ofs, allowbbt); +} + /** * onenand_erase - [MTD Interface] erase block(s) * @param mtd MTD device structure @@ -1109,7 +1130,12 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr) while (len) { - /* TODO Check badblock */ + /* Check if we have a bad block, we do not erase bad blocks */ + if (onenand_block_checkbad(mtd, addr, 0, 0)) { + printk (KERN_WARNING "onenand_erase: attempt to erase a bad block at addr 0x%08x\n", (unsigned int) addr); + instr->state = MTD_ERASE_FAILED; + goto erase_exit; + } this->command(mtd, ONENAND_CMD_ERASE, addr, block_size); @@ -1161,34 +1187,70 @@ static void onenand_sync(struct mtd_info *mtd) onenand_release_device(mtd); } + /** * onenand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad * @param mtd MTD device structure * @param ofs offset relative to mtd start + * + * Check whether the block is bad */ static int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs) { - /* - * TODO - * 1. Bad block table (BBT) - * -> using NAND BBT to support JFFS2 - * 2. Bad block management (BBM) - * -> bad block replace scheme - * - * Currently we do nothing - */ - return 0; + /* Check for invalid offset */ + if (ofs > mtd->size) + return -EINVAL; + + return onenand_block_checkbad(mtd, ofs, 1, 0); +} + +/** + * onenand_default_block_markbad - [DEFAULT] mark a block bad + * @param mtd MTD device structure + * @param ofs offset from device start + * + * This is the default implementation, which can be overridden by + * a hardware specific driver. + */ +static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) +{ + struct onenand_chip *this = mtd->priv; + struct bbm_info *bbm = this->bbm; + u_char buf[2] = {0, 0}; + size_t retlen; + int block; + + /* Get block number */ + block = ((int) ofs) >> bbm->bbt_erase_shift; + if (bbm->bbt) + bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); + + /* We write two bytes, so we dont have to mess with 16 bit access */ + ofs += mtd->oobsize + (bbm->badblockpos & ~0x01); + return mtd->write_oob(mtd, ofs , 2, &retlen, buf); } /** * onenand_block_markbad - [MTD Interface] Mark the block at the given offset as bad * @param mtd MTD device structure * @param ofs offset relative to mtd start + * + * Mark the block as bad */ static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs) { - /* see above */ - return 0; + struct onenand_chip *this = mtd->priv; + int ret; + + ret = onenand_block_isbad(mtd, ofs); + if (ret) { + /* If it was bad already, return success and do nothing */ + if (ret > 0) + return 0; + return ret; + } + + return this->block_markbad(mtd, ofs); } /** @@ -1411,6 +1473,11 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) if (!this->write_bufferram) this->write_bufferram = onenand_write_bufferram; + if (!this->block_markbad) + this->block_markbad = onenand_default_block_markbad; + if (!this->scan_bbt) + this->scan_bbt = onenand_default_bbt; + if (onenand_probe(mtd)) return -ENXIO; @@ -1472,7 +1539,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) /* Unlock whole block */ mtd->unlock(mtd, 0x0, this->chipsize); - return 0; + return this->scan_bbt(mtd); } /** diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index c557caa24a6..89aaffbc957 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -14,6 +14,7 @@ #include #include +#include #define MAX_BUFFERRAM 2 @@ -67,10 +68,14 @@ struct onenand_bufferram { * @param wait [REPLACEABLE] hardware specific function for wait on ready * @param read_bufferram [REPLACEABLE] hardware specific function for BufferRAM Area * @param write_bufferram [REPLACEABLE] hardware specific function for BufferRAM Area + * @param read_word [REPLACEABLE] hardware specific function for read register of OneNAND + * @param write_word [REPLACEABLE] hardware specific function for write register of OneNAND + * @param scan_bbt [REPLACEALBE] hardware specific function for scaning Bad block Table * @param chip_lock [INTERN] spinlock used to protect access to this structure and the chip * @param wq [INTERN] wait queue to sleep on if a OneNAND operation is in progress * @param state [INTERN] the current state of the OneNAND device * @param autooob [REPLACEABLE] the default (auto)placement scheme + * @param bbm [REPLACEABLE] pointer to Bad Block Management * @param priv [OPTIONAL] pointer to private chip date */ struct onenand_chip { @@ -96,6 +101,8 @@ struct onenand_chip { unsigned short (*read_word)(void __iomem *addr); void (*write_word)(unsigned short value, void __iomem *addr); void (*mmcontrol)(struct mtd_info *mtd, int sync_read); + int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); + int (*scan_bbt)(struct mtd_info *mtd); spinlock_t chip_lock; wait_queue_head_t wq; @@ -103,6 +110,8 @@ struct onenand_chip { struct nand_oobinfo *autooob; + void *bbm; + void *priv; }; -- cgit v1.2.3 From fcc31470c49e224ed8115c70541f599fc7568fee Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Sat, 3 Sep 2005 07:20:08 +0100 Subject: [PATCH] OneNAND: Update OMAP OneNAND mapping using device driver model - Update OMAP OneNAND mapping file using device driver model - Remove board specific macro and values. Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/omap-onenand.c | 271 ++++++++++++------------------------- include/linux/mtd/onenand.h | 8 ++ 2 files changed, 97 insertions(+), 182 deletions(-) diff --git a/drivers/mtd/onenand/omap-onenand.c b/drivers/mtd/onenand/omap-onenand.c index 7c89549f7f5..57e69f184d3 100644 --- a/drivers/mtd/onenand/omap-onenand.c +++ b/drivers/mtd/onenand/omap-onenand.c @@ -4,236 +4,143 @@ * Copyright (c) 2005 Samsung Electronics * Kyungmin Park * - * Derived from linux/drivers/mtd/nand/omap-nand-flash.c - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Overview: - * This is a device driver for the OneNAND flash device for TI OMAP boards. + * This is a device driver for the OneNAND flash for OMAP boards. */ -#include -#include +#include #include +#include #include #include #include #include -#include -#include -#include -#include +#include -#define OMAP_ONENAND_FLASH_START1 OMAP_CS2A_PHYS -#define OMAP_ONENAND_FLASH_START2 omap_cs3_phys() -/* - * MTD structure for OMAP board - */ -static struct mtd_info *omap_onenand_mtd = NULL; +#define DRIVER_NAME "onenand" -/* - * Define partitions for flash devices - */ #ifdef CONFIG_MTD_PARTITIONS -static struct mtd_partition static_partition[] = { - { - .name = "X-Loader + U-Boot", - .offset = 0, - .size = SZ_128K, - .mask_flags = MTD_WRITEABLE /* force read-only */ - }, - { - .name = "U-Boot Environment", - .offset = MTDPART_OFS_APPEND, - .size = SZ_128K, - .mask_flags = MTD_WRITEABLE /* force read-only */ - }, - { - .name = "kernel", - .offset = MTDPART_OFS_APPEND, - .size = 2 * SZ_1M - }, - { - .name = "filesystem0", - .offset = MTDPART_OFS_APPEND, - .size = SZ_16M, - }, - { - .name = "filesystem1", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, - }, -}; - static const char *part_probes[] = { "cmdlinepart", NULL, }; - #endif -#ifdef CONFIG_MTD_ONENAND_SYNC_READ -static unsigned int omap_emifs_cs; +struct omap_onenand_info { + struct mtd_info mtd; + struct mtd_partition *parts; + struct onenand_chip onenand; +}; -static void omap_find_emifs_cs(unsigned int addr) +static int __devinit omap_onenand_probe(struct device *dev) { - /* Check CS3 */ - if (OMAP_EMIFS_CONFIG_REG & OMAP_EMIFS_CONFIG_BM && addr == 0x0) { - omap_emifs_cs = 3; - } else { - omap_emifs_cs = (addr >> 26); + struct omap_onenand_info *info; + struct platform_device *pdev = to_platform_device(dev); + struct onenand_platform_data *pdata = pdev->dev.platform_data; + struct resource *res = pdev->resource; + unsigned long size = res->end - res->start + 1; + int err; + + info = kmalloc(sizeof(struct omap_onenand_info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + memset(info, 0, sizeof(struct omap_onenand_info)); + + if (!request_mem_region(res->start, size, dev->driver->name)) { + err = -EBUSY; + goto out_free_info; } -} -/** - * omap_onenand_mmcontrol - Control OMAP EMIFS - */ -static void omap_onenand_mmcontrol(struct mtd_info *mtd, int sync_read) -{ - struct onenand_chip *this = mtd->priv; - static unsigned long omap_emifs_ccs, omap_emifs_acs; - static unsigned long onenand_sys_cfg1; - int config, emifs_ccs, emifs_acs; - - if (sync_read) { - /* - * Note: BRL and RDWST is equal - */ - omap_emifs_ccs = EMIFS_CCS(omap_emifs_cs); - omap_emifs_acs = EMIFS_ACS(omap_emifs_cs); - - emifs_ccs = 0x41141; - emifs_acs = 0x1; - - /* OneNAND System Configuration 1 */ - onenand_sys_cfg1 = this->read_word(this->base + ONENAND_REG_SYS_CFG1); - config = (onenand_sys_cfg1 - & ~(0x3f << ONENAND_SYS_CFG1_BL_SHIFT)) - | ONENAND_SYS_CFG1_SYNC_READ - | ONENAND_SYS_CFG1_BRL_4 - | ONENAND_SYS_CFG1_BL_8; - } else { - emifs_ccs = omap_emifs_ccs; - emifs_acs = omap_emifs_acs; - config = onenand_sys_cfg1; + info->onenand.base = ioremap(res->start, size); + if (!info->onenand.base) { + err = -ENOMEM; + goto out_release_mem_region; } - this->write_word(config, this->base + ONENAND_REG_SYS_CFG1); - EMIFS_CCS(omap_emifs_cs) = emifs_ccs; - EMIFS_ACS(omap_emifs_cs) = emifs_acs; -} -#else -#define omap_find_emifs_cs(x) do { } while (0) -#define omap_onenand_mmcontrol NULL -#endif + info->onenand.mmcontrol = pdata->mmcontrol; + info->mtd.name = pdev->dev.bus_id; + info->mtd.priv = &info->onenand; + info->mtd.owner = THIS_MODULE; -/* Scan to find existance of the device at base. - This also allocates oob and data internal buffers */ -static char onenand_name[] = "onenand"; - -/* - * Main initialization routine - */ -static int __init omap_onenand_init (void) -{ - struct onenand_chip *this; - struct mtd_partition *dynamic_partition = 0; - int err = 0; - - /* Allocate memory for MTD device structure and private data */ - omap_onenand_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct onenand_chip), - GFP_KERNEL); - if (!omap_onenand_mtd) { - printk (KERN_WARNING "Unable to allocate OneNAND MTD device structure.\n"); - err = -ENOMEM; - goto out; + if (onenand_scan(&info->mtd, 1)) { + err = -ENXIO; + goto out_iounmap; } - /* Get pointer to private data */ - this = (struct onenand_chip *) (&omap_onenand_mtd[1]); +#ifdef CONFIG_MTD_PARTITIONS + err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0); + if (err > 0) + add_mtd_partitions(&info->mtd, info->parts, err); + else if (err < 0 && pdata->parts) + add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts); + else +#endif + err = add_mtd_device(&info->mtd); - /* Initialize structures */ - memset((char *) omap_onenand_mtd, 0, sizeof(struct mtd_info) + sizeof(struct onenand_chip)); + dev_set_drvdata(&pdev->dev, info); - /* Link the private data with the MTD structure */ - omap_onenand_mtd->priv = this; - this->mmcontrol = omap_onenand_mmcontrol; + return 0; - /* try the first address */ - this->base = ioremap(OMAP_ONENAND_FLASH_START1, SZ_128K); - omap_find_emifs_cs(OMAP_ONENAND_FLASH_START1); +out_iounmap: + iounmap(info->onenand.base); +out_release_mem_region: + release_mem_region(res->start, size); +out_free_info: + kfree(info); - omap_onenand_mtd->name = onenand_name; - if (onenand_scan(omap_onenand_mtd, 1)){ - /* try the second address */ - iounmap(this->base); - this->base = ioremap(OMAP_ONENAND_FLASH_START2, SZ_128K); - omap_find_emifs_cs(OMAP_ONENAND_FLASH_START2); + return err; +} - if (onenand_scan(omap_onenand_mtd, 1)) { - iounmap(this->base); - err = -ENXIO; - goto out_mtd; - } - } +static int __devexit omap_onenand_remove(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct omap_onenand_info *info = dev_get_drvdata(&pdev->dev); + struct resource *res = pdev->resource; + unsigned long size = res->end - res->start + 1; - /* Register the partitions */ - switch (omap_onenand_mtd->size) { - case SZ_128M: - case SZ_64M: - case SZ_32M: -#ifdef CONFIG_MTD_PARTITIONS - err = parse_mtd_partitions(omap_onenand_mtd, part_probes, - &dynamic_partition, 0); - if (err > 0) - err = add_mtd_partitions(omap_onenand_mtd, - dynamic_partition, err); - else if (1) - err = add_mtd_partitions(omap_onenand_mtd, - static_partition, - ARRAY_SIZE(static_partition)); + dev_set_drvdata(&pdev->dev, NULL); + + if (info) { + if (info->parts) + del_mtd_partitions(&info->mtd); else -#endif - err = add_mtd_device(omap_onenand_mtd); - if (err) - goto out_buf; - break; + del_mtd_device(&info->mtd); - default: - printk(KERN_WARNING "Unsupported OneNAND device\n"); - err = -ENXIO; - goto out_buf; + onenand_release(&info->mtd); + release_mem_region(res->start, size); + iounmap(info->onenand.base); + kfree(info); } return 0; - -out_buf: - onenand_release(omap_onenand_mtd); - iounmap(this->base); -out_mtd: - kfree(omap_onenand_mtd); -out: - return err; } -/* - * Clean up routine - */ -static void __exit omap_onenand_cleanup (void) +static struct device_driver omap_onenand_driver = { + .name = DRIVER_NAME, + .bus = &platform_bus_type, + .probe = omap_onenand_probe, + .remove = __devexit_p(omap_onenand_remove), +}; + +MODULE_ALIAS(DRIVER_NAME); + +static int __init omap_onenand_init(void) { - struct onenand_chip *this = omap_onenand_mtd->priv; + return driver_register(&omap_onenand_driver); +} - /* onenand_release frees MTD partitions, MTD structure - and onenand internal buffers */ - onenand_release(omap_onenand_mtd); - iounmap(this->base); - kfree(omap_onenand_mtd); +static void __exit omap_onenand_exit(void) +{ + driver_unregister(&omap_onenand_driver); } module_init(omap_onenand_init); -module_exit(omap_onenand_cleanup); +module_exit(omap_onenand_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Kyungmin Park "); diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index 89aaffbc957..2c29a5ca2c9 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -115,10 +115,18 @@ struct onenand_chip { void *priv; }; +/* + * Helper macros + */ #define ONENAND_CURRENT_BUFFERRAM(this) (this->bufferram_index) #define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1) #define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1) +#define ONENAND_GET_SYS_CFG1(this) \ + (this->read_word(this->base + ONENAND_REG_SYS_CFG1)) +#define ONENAND_SET_SYS_CFG1(v, this) \ + (this->write_word(v, this->base + ONENAND_REG_SYS_CFG1)) + /* * Options bits */ -- cgit v1.2.3 From 405c829f98d216925de00af2ee52f969f2c2891c Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Sat, 3 Sep 2005 07:32:30 +0100 Subject: [PATCH] OneNAND: Add simulator Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/Kconfig | 7 + drivers/mtd/onenand/Makefile | 3 + drivers/mtd/onenand/onenand_sim.c | 464 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 474 insertions(+) create mode 100644 drivers/mtd/onenand/onenand_sim.c diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig index 186ea9dc094..e5ed081c42c 100644 --- a/drivers/mtd/onenand/Kconfig +++ b/drivers/mtd/onenand/Kconfig @@ -35,4 +35,11 @@ config MTD_ONENAND_SYNC_READ help This enables support for Sync. Burst Read. +config MTD_ONENAND_SIM + tristate "Support for OneNAND flash simulator" + depends on MTD_ONENAND + help + The simulator may simulate verious OneNAND flash chips for the + MTD onenand layer. + endmenu diff --git a/drivers/mtd/onenand/Makefile b/drivers/mtd/onenand/Makefile index 243c7592a11..932301a888e 100644 --- a/drivers/mtd/onenand/Makefile +++ b/drivers/mtd/onenand/Makefile @@ -8,4 +8,7 @@ obj-$(CONFIG_MTD_ONENAND) += onenand.o # Board specific. obj-$(CONFIG_MTD_ONENAND_OMAP) += omap-onenand.o +# Simulator +obj-$(CONFIG_MTD_ONENAND_SIM) += onenand_sim.o + onenand-objs = onenand_base.o onenand_bbt.o diff --git a/drivers/mtd/onenand/onenand_sim.c b/drivers/mtd/onenand/onenand_sim.c new file mode 100644 index 00000000000..cb376b20695 --- /dev/null +++ b/drivers/mtd/onenand/onenand_sim.c @@ -0,0 +1,464 @@ +/* + * linux/drivers/mtd/onenand/simulator.c + * + * The OneNAND simulator + * + * Copyright(c) 2005 Samsung Electronics + * Kyungmin Park + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifndef CONFIG_ONENAND_SIM_MANUFACTURER +#define CONFIG_ONENAND_SIM_MANUFACTURER 0xec +#endif +#ifndef CONFIG_ONENAND_SIM_DEVICE_ID +#define CONFIG_ONENAND_SIM_DEVICE_ID 0x04 +#endif +#ifndef CONFIG_ONENAND_SIM_VERSION_ID +#define CONFIG_ONENAND_SIM_VERSION_ID 0x1e +#endif + +static int manuf_id = CONFIG_ONENAND_SIM_MANUFACTURER; +static int device_id = CONFIG_ONENAND_SIM_DEVICE_ID; +static int version_id = CONFIG_ONENAND_SIM_VERSION_ID; + +struct onenand_flash { + void __iomem *base; + void __iomem *data; +}; + +#define ONENAND_CORE(flash) (flash->data) + +#define ONENAND_MAIN_AREA(this, offset) \ + (this->base + ONENAND_DATARAM + offset) + +#define ONENAND_SPARE_AREA(this, offset) \ + (this->base + ONENAND_SPARERAM + offset) + +#define ONENAND_GET_WP_STATUS(this) \ + (readw(this->base + ONENAND_REG_WP_STATUS)) + +#define ONENAND_SET_WP_STATUS(v, this) \ + (writew(v, this->base + ONENAND_REG_WP_STATUS)) + +/* It has all 0xff chars */ +static unsigned char *ffchars; + +/* + * OneNAND simulator mtd + */ +struct mtd_info *onenand_sim; + + +/** + * onenand_lock_handle - Handle Lock scheme + * @param this OneNAND device structure + * @param cmd The command to be sent + * + * Send lock command to OneNAND device. + * The lock scheme is depends on chip type. + */ +static void onenand_lock_handle(struct onenand_chip *this, int cmd) +{ + int block_lock_scheme; + int status; + + status = ONENAND_GET_WP_STATUS(this); + block_lock_scheme = !(this->options & ONENAND_CONT_LOCK); + + switch (cmd) { + case ONENAND_CMD_UNLOCK: + if (block_lock_scheme) + ONENAND_SET_WP_STATUS(ONENAND_WP_US, this); + else + ONENAND_SET_WP_STATUS(status | ONENAND_WP_US, this); + break; + + case ONENAND_CMD_LOCK: + if (block_lock_scheme) + ONENAND_SET_WP_STATUS(ONENAND_WP_LS, this); + else + ONENAND_SET_WP_STATUS(status | ONENAND_WP_LS, this); + break; + + case ONENAND_CMD_LOCK_TIGHT: + if (block_lock_scheme) + ONENAND_SET_WP_STATUS(ONENAND_WP_LTS, this); + else + ONENAND_SET_WP_STATUS(status | ONENAND_WP_LTS, this); + break; + + default: + break; + } +} + +/** + * onenand_bootram_handle - Handle BootRAM area + * @param this OneNAND device structure + * @param cmd The command to be sent + * + * Emulate BootRAM area. It is possible to do basic operation using BootRAM. + */ +static void onenand_bootram_handle(struct onenand_chip *this, int cmd) +{ + switch (cmd) { + case ONENAND_CMD_READID: + writew(manuf_id, this->base); + writew(device_id, this->base + 2); + writew(version_id, this->base + 4); + break; + + default: + /* REVIST: Handle other commands */ + break; + } +} + +/** + * onenand_update_interrupt - Set interrupt register + * @param this OneNAND device structure + * @param cmd The command to be sent + * + * Update interrupt register. The status is depends on command. + */ +static void onenand_update_interrupt(struct onenand_chip *this, int cmd) +{ + int interrupt = ONENAND_INT_MASTER; + + switch (cmd) { + case ONENAND_CMD_READ: + case ONENAND_CMD_READOOB: + interrupt |= ONENAND_INT_READ; + break; + + case ONENAND_CMD_PROG: + case ONENAND_CMD_PROGOOB: + interrupt |= ONENAND_INT_WRITE; + break; + + case ONENAND_CMD_ERASE: + interrupt |= ONENAND_INT_ERASE; + break; + + case ONENAND_CMD_RESET: + interrupt |= ONENAND_INT_RESET; + break; + + default: + break; + } + + writew(interrupt, this->base + ONENAND_REG_INTERRUPT); +} + +/** + * onenand_check_overwrite - Check over-write if happend + * @param dest The destination pointer + * @param src The source pointer + * @param count The length to be check + * @return 0 on same, otherwise 1 + * + * Compare the source with destination + */ +static int onenand_check_overwrite(void *dest, void *src, size_t count) +{ + unsigned int *s = (unsigned int *) src; + unsigned int *d = (unsigned int *) dest; + int i; + count >>= 2; + + for (i = 0; i < count; i++) + if ((*s++ ^ *d++) != 0) + return 1; + + return 0; +} + +/** + * onenand_data_handle - Handle OneNAND Core and DataRAM + * @param this OneNAND device structure + * @param cmd The command to be sent + * @param dataram Which dataram used + * @param offset The offset to OneNAND Core + * + * Copy data from OneNAND Core to DataRAM (read) + * Copy data from DataRAM to OneNAND Core (write) + * Erase the OneNAND Core (erase) + */ +static void onenand_data_handle(struct onenand_chip *this, int cmd, + int dataram, unsigned int offset) +{ + struct onenand_flash *flash = this->priv; + int main_offset, spare_offset; + void __iomem *src; + void __iomem *dest; + + if (dataram) { + main_offset = onenand_sim->oobblock; + spare_offset = onenand_sim->oobsize; + } else { + main_offset = 0; + spare_offset = 0; + } + + switch (cmd) { + case ONENAND_CMD_READ: + src = ONENAND_CORE(flash) + offset; + dest = ONENAND_MAIN_AREA(this, main_offset); + memcpy(dest, src, onenand_sim->oobblock); + /* Fall through */ + + case ONENAND_CMD_READOOB: + src = ONENAND_CORE(flash) + this->chipsize + (offset >> 5); + dest = ONENAND_SPARE_AREA(this, spare_offset); + memcpy(dest, src, onenand_sim->oobsize); + break; + + case ONENAND_CMD_PROG: + src = ONENAND_MAIN_AREA(this, main_offset); + dest = ONENAND_CORE(flash) + offset; + if (memcmp(dest, ffchars, onenand_sim->oobblock) && + onenand_check_overwrite(dest, src, onenand_sim->oobblock)) + printk(KERN_ERR "over-write happend at 0x%08x\n", offset); + memcpy(dest, src, onenand_sim->oobblock); + /* Fall through */ + + case ONENAND_CMD_PROGOOB: + src = ONENAND_SPARE_AREA(this, spare_offset); + /* Check all data is 0xff chars */ + if (!memcmp(src, ffchars, onenand_sim->oobsize)) + break; + + dest = ONENAND_CORE(flash) + this->chipsize + (offset >> 5); + if (memcmp(dest, ffchars, onenand_sim->oobsize) && + onenand_check_overwrite(dest, src, onenand_sim->oobsize)) + printk(KERN_ERR "OOB: over-write happend at 0x%08x\n", offset); + memcpy(dest, src, onenand_sim->oobsize); + break; + + case ONENAND_CMD_ERASE: + memset(ONENAND_CORE(flash) + offset, 0xff, (1 << this->erase_shift)); + break; + + default: + break; + } +} + +/** + * onenand_command_handle - Handle command + * @param this OneNAND device structure + * @param cmd The command to be sent + * + * Emulate OneNAND command. + */ +static void onenand_command_handle(struct onenand_chip *this, int cmd) +{ + unsigned long offset = 0; + int block = -1, page = -1, bufferram = -1; + int dataram = 0; + + switch (cmd) { + case ONENAND_CMD_UNLOCK: + case ONENAND_CMD_LOCK: + case ONENAND_CMD_LOCK_TIGHT: + onenand_lock_handle(this, cmd); + break; + + case ONENAND_CMD_BUFFERRAM: + /* Do nothing */ + return; + + default: + block = (int) readw(this->base + ONENAND_REG_START_ADDRESS1); + if (block & (1 << ONENAND_DDP_SHIFT)) { + block &= ~(1 << ONENAND_DDP_SHIFT); + /* The half of chip block */ + block += this->chipsize >> (this->erase_shift + 1); + } + if (cmd == ONENAND_CMD_ERASE) + break; + + page = (int) readw(this->base + ONENAND_REG_START_ADDRESS8); + page = (page >> ONENAND_FPA_SHIFT); + bufferram = (int) readw(this->base + ONENAND_REG_START_BUFFER); + bufferram >>= ONENAND_BSA_SHIFT; + bufferram &= ONENAND_BSA_DATARAM1; + dataram = (bufferram == ONENAND_BSA_DATARAM1) ? 1 : 0; + break; + } + + if (block != -1) + offset += block << this->erase_shift; + + if (page != -1) + offset += page << this->page_shift; + + onenand_data_handle(this, cmd, dataram, offset); + + onenand_update_interrupt(this, cmd); +} + +/** + * onenand_writew - [OneNAND Interface] Emulate write operation + * @param value value to write + * @param addr address to write + * + * Write OneNAND reigser with value + */ +static void onenand_writew(unsigned short value, void __iomem *addr) +{ + struct onenand_chip *this = onenand_sim->priv; + + /* BootRAM handling */ + if (addr < this->base + ONENAND_DATARAM) { + onenand_bootram_handle(this, value); + return; + } + /* Command handling */ + if (addr == this->base + ONENAND_REG_COMMAND) + onenand_command_handle(this, value); + + writew(value, addr); +} + +/** + * flash_init - Initialize OneNAND simulator + * @param flash OneNAND simulaotr data strucutres + * + * Initialize OneNAND simulator. + */ +static int __init flash_init(struct onenand_flash *flash) +{ + int density, size; + int buffer_size; + + flash->base = kmalloc(SZ_128K, GFP_KERNEL); + if (!flash->base) { + printk(KERN_ERR "Unalbe to allocate base address.\n"); + return -ENOMEM; + } + + memset(flash->base, 0, SZ_128K); + + density = device_id >> ONENAND_DEVICE_DENSITY_SHIFT; + size = ((16 << 20) << density); + + ONENAND_CORE(flash) = vmalloc(size + (size >> 5)); + if (!ONENAND_CORE(flash)) { + printk(KERN_ERR "Unalbe to allocate nand core address.\n"); + kfree(flash->base); + return -ENOMEM; + } + + memset(ONENAND_CORE(flash), 0xff, size + (size >> 5)); + + /* Setup registers */ + writew(manuf_id, flash->base + ONENAND_REG_MANUFACTURER_ID); + writew(device_id, flash->base + ONENAND_REG_DEVICE_ID); + writew(version_id, flash->base + ONENAND_REG_VERSION_ID); + + if (density < 2) + buffer_size = 0x0400; /* 1KB page */ + else + buffer_size = 0x0800; /* 2KB page */ + writew(buffer_size, flash->base + ONENAND_REG_DATA_BUFFER_SIZE); + + return 0; +} + +/** + * flash_exit - Clean up OneNAND simulator + * @param flash OneNAND simulaotr data strucutres + * + * Clean up OneNAND simulator. + */ +static void flash_exit(struct onenand_flash *flash) +{ + vfree(ONENAND_CORE(flash)); + kfree(flash->base); + kfree(flash); +} + +static int __init onenand_sim_init(void) +{ + struct onenand_chip *this; + struct onenand_flash *flash; + int len; + + /* Allocate all 0xff chars pointer */ + ffchars = kmalloc(MAX_ONENAND_PAGESIZE, GFP_KERNEL); + if (!ffchars) { + printk(KERN_ERR "Unable to allocate ff chars.\n"); + return -ENOMEM; + } + memset(ffchars, 0xff, MAX_ONENAND_PAGESIZE); + + len = sizeof(struct mtd_info) + sizeof(struct onenand_chip) + sizeof (struct onenand_flash); + + /* Allocate OneNAND simulator mtd pointer */ + onenand_sim = kmalloc(len, GFP_KERNEL); + if (!onenand_sim) { + printk(KERN_ERR "Unable to allocate core structures.\n"); + kfree(ffchars); + return -ENOMEM; + } + + memset(onenand_sim, 0, len); + + this = (struct onenand_chip *) (onenand_sim + 1); + /* Override write_word function */ + this->write_word = onenand_writew; + + flash = (struct onenand_flash *) (this + 1); + + if (flash_init(flash)) { + printk(KERN_ERR "Unable to allocat flash.\n"); + kfree(ffchars); + kfree(onenand_sim); + return -ENOMEM; + } + + this->base = flash->base; + this->priv = flash; + onenand_sim->priv = this; + + if (onenand_scan(onenand_sim, 1)) { + kfree(ffchars); + kfree(onenand_sim); + flash_exit(flash); + return -ENXIO; + } + + add_mtd_device(onenand_sim); + + return 0; +} + +static void __exit onenand_sim_exit(void) +{ + struct onenand_chip *this = onenand_sim->priv; + struct onenand_flash *flash = this->priv; + + kfree(ffchars); + onenand_release(onenand_sim); + flash_exit(flash); + kfree(onenand_sim); +} + +module_init(onenand_sim_init); +module_exit(onenand_sim_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Kyungmin Park "); +MODULE_DESCRIPTION("The OneNAND flash simulator"); -- cgit v1.2.3 From d36d63d404b75ddf231da0dbd3640e6d1722b4ab Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Sat, 3 Sep 2005 07:36:21 +0100 Subject: [PATCH] OneNAND: Fix bug in write verify - Remove unused block, page parameters - Add constant instead of runtime value Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/onenand_base.c | 11 ++++------- include/linux/mtd/onenand.h | 1 + 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index bdeac01e659..75d75788269 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -719,13 +719,10 @@ out: * onenand_verify_page - [GENERIC] verify the chip contents after a write * @param mtd MTD device structure * @param buf the databuffer to verify - * @param block block address - * @param page page address * * Check DataRAM area directly */ -static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, - loff_t addr, int block, int page) +static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, loff_t addr) { struct onenand_chip *this = mtd->priv; void __iomem *dataram0, *dataram1; @@ -816,7 +813,7 @@ static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, written += thislen; /* Only check verify write turn on */ - ret = onenand_verify_page(mtd, (u_char *) buf, to, block, page); + ret = onenand_verify_page(mtd, (u_char *) buf, to); if (ret) { DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: verify failed %d\n", ret); goto out; @@ -940,7 +937,7 @@ static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, u_char *eccbuf, struct nand_oobinfo *oobsel) { struct onenand_chip *this = mtd->priv; - unsigned char buffer[mtd->oobblock], *pbuf; + unsigned char buffer[MAX_ONENAND_PAGESIZE], *pbuf; size_t total_len, len; int i, written = 0; int ret = 0; @@ -1025,7 +1022,7 @@ static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, /* Only check verify write turn on */ - ret = onenand_verify_page(mtd, (u_char *) pbuf, to, block, page); + ret = onenand_verify_page(mtd, (u_char *) pbuf, to); if (ret) { DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: verify failed %d\n", ret); goto out; diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index 2c29a5ca2c9..58023082320 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -17,6 +17,7 @@ #include #define MAX_BUFFERRAM 2 +#define MAX_ONENAND_PAGESIZE (2048 + 64) /* Scan and identify a OneNAND device */ extern int onenand_scan(struct mtd_info *mtd, int max_chips); -- cgit v1.2.3 From 15017876751e4c2d786ba95920618359fe2b4f0a Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Sat, 3 Sep 2005 07:37:19 +0100 Subject: [MTD] OneNAND: Remove experimental Kconfig dependency Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig index e5ed081c42c..08a32a53a37 100644 --- a/drivers/mtd/onenand/Kconfig +++ b/drivers/mtd/onenand/Kconfig @@ -2,8 +2,8 @@ # linux/drivers/mtd/onenand/Kconfig # -menu "OneNAND Flash Device Drivers (EXPERIMENTAL)" - depends on MTD != n && EXPERIMENTAL +menu "OneNAND Flash Device Drivers" + depends on MTD != n config MTD_ONENAND tristate "OneNAND Device Support" -- cgit v1.2.3 From e631ddba588783edd521c5a89f7b2902772fb691 Mon Sep 17 00:00:00 2001 From: Ferenc Havasi Date: Wed, 7 Sep 2005 09:35:26 +0100 Subject: [JFFS2] Add erase block summary support (mount time improvement) The goal of summary is to speed up the mount time. Erase block summary (EBS) stores summary information at the end of every (closed) erase block. It is no longer necessary to scan all nodes separetly (and read all pages of them) just read this "small" summary, where every information is stored which is needed at mount time. This summary information is stored in a JFFS2_FEATURE_RWCOMPAT_DELETE. During the mount process if there is no summary info the orignal scan process will be executed. EBS works with NAND and NOR flashes, too. There is a user space tool called sumtool to generate this summary information for a JFFS2 image. Signed-off-by: Ferenc Havasi Signed-off-by: Thomas Gleixner --- fs/Kconfig | 13 + fs/jffs2/Makefile | 3 +- fs/jffs2/build.c | 12 +- fs/jffs2/debug.h | 10 +- fs/jffs2/dir.c | 20 +- fs/jffs2/file.c | 5 +- fs/jffs2/fs.c | 5 +- fs/jffs2/gc.c | 26 +- fs/jffs2/nodelist.h | 13 +- fs/jffs2/nodemgmt.c | 250 ++++++++++----- fs/jffs2/os-linux.h | 19 +- fs/jffs2/scan.c | 198 ++++++++---- fs/jffs2/summary.c | 729 ++++++++++++++++++++++++++++++++++++++++++++ fs/jffs2/summary.h | 183 +++++++++++ fs/jffs2/super.c | 8 +- fs/jffs2/wbuf.c | 12 +- fs/jffs2/write.c | 29 +- fs/jffs2/writev.c | 34 ++- include/linux/jffs2.h | 21 +- include/linux/jffs2_fs_sb.h | 4 +- 20 files changed, 1395 insertions(+), 199 deletions(-) create mode 100644 fs/jffs2/summary.c create mode 100644 fs/jffs2/summary.h diff --git a/fs/Kconfig b/fs/Kconfig index 01a295232f7..37d86c5072e 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -1050,6 +1050,19 @@ config JFFS2_FS_WRITEBUFFER - NOR flash with transparent ECC - DataFlash +config JFFS2_SUMMARY + bool "JFFS2 summary support (EXPERIMENTAL)" + depends on JFFS2_FS && EXPERIMENTAL + default n + help + This feature makes it possible to use summary information + for faster filesystem mount. + + The summary information can be inserted into a filesystem image + by the utility 'sumtool'. + + If unsure, say 'N'. + config JFFS2_COMPRESSION_OPTIONS bool "Advanced compression options for JFFS2" depends on JFFS2_FS diff --git a/fs/jffs2/Makefile b/fs/jffs2/Makefile index e6230f1bba7..77dc5561a04 100644 --- a/fs/jffs2/Makefile +++ b/fs/jffs2/Makefile @@ -1,7 +1,7 @@ # # Makefile for the Linux Journalling Flash File System v2 (JFFS2) # -# $Id: Makefile.common,v 1.10 2005/07/17 06:56:20 dedekind Exp $ +# $Id: Makefile.common,v 1.11 2005/09/07 08:34:53 havasi Exp $ # obj-$(CONFIG_JFFS2_FS) += jffs2.o @@ -15,3 +15,4 @@ jffs2-$(CONFIG_JFFS2_FS_WRITEBUFFER) += wbuf.o jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o +jffs2-$(CONFIG_JFFS2_SUMMARY) += summary.o diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index 1522eace932..f4a47a3b2a0 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: build.c,v 1.77 2005/08/31 13:51:00 havasi Exp $ + * $Id: build.c,v 1.78 2005/09/07 08:34:54 havasi Exp $ * */ @@ -350,6 +350,10 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) INIT_LIST_HEAD(&c->bad_list); INIT_LIST_HEAD(&c->bad_used_list); c->highest_ino = 1; + c->summary = NULL; + + if (jffs2_sum_init(c)) + return -ENOMEM; if (jffs2_build_filesystem(c)) { D1(printk(KERN_DEBUG "build_fs failed\n")); @@ -357,11 +361,11 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) jffs2_free_raw_node_refs(c); #ifndef __ECOS if (jffs2_blocks_use_vmalloc(c)) - vfree(c->blocks); + vfree(c->blocks); else #endif - kfree(c->blocks); - + kfree(c->blocks); + return -EIO; } diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index 03d9626ad1c..60e5dbb3946 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.h,v 1.14 2005/08/17 13:48:59 dedekind Exp $ + * $Id: debug.h,v 1.15 2005/09/07 08:34:54 havasi Exp $ * */ #ifndef _JFFS2_DEBUG_H_ @@ -28,6 +28,7 @@ #define JFFS2_DBG_DENTLIST_MESSAGES #define JFFS2_DBG_NODEREF_MESSAGES #define JFFS2_DBG_INOCACHE_MESSAGES +#define JFFS2_DBG_SUMMARY_MESSAGES #endif #if CONFIG_JFFS2_FS_DEBUG == 2 @@ -137,6 +138,13 @@ #define JFFS2_DBG_INOCACHE(fmt, ...) #endif +/* Summary debugging messages */ +#ifdef JFFS2_DBG_SUMMARY_MESSAGES +#define JFFS2_DBG_SUMMARY(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#else +#define JFFS2_DBG_SUMMARY(fmt, ...) +#endif + /* Watch the object allocations */ #ifdef JFFS2_DBG_MEMALLOC_MESSAGES #define JFFS2_DBG_MEMALLOC(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 0fd15aaf245..19bea0f95ac 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: dir.c,v 1.88 2005/08/17 13:46:22 dedekind Exp $ + * $Id: dir.c,v 1.89 2005/09/07 08:34:54 havasi Exp $ * */ @@ -310,7 +310,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char * Just the node will do for now, though */ namelen = dentry->d_name.len; - ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) { jffs2_free_raw_inode(ri); @@ -370,7 +371,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char up(&f->sem); jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { /* Eep. */ jffs2_clear_inode(inode); @@ -455,7 +457,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) * Just the node will do for now, though */ namelen = dentry->d_name.len; - ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL, + JFFS2_SUMMARY_INODE_SIZE); if (ret) { jffs2_free_raw_inode(ri); @@ -498,7 +501,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) up(&f->sem); jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { /* Eep. */ jffs2_clear_inode(inode); @@ -607,7 +611,8 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de * Just the node will do for now, though */ namelen = dentry->d_name.len; - ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) { jffs2_free_raw_inode(ri); @@ -652,7 +657,8 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de up(&f->sem); jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { /* Eep. */ jffs2_clear_inode(inode); diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index 8279bf0133f..231404a7472 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: file.c,v 1.102 2005/07/06 12:13:09 dwmw2 Exp $ + * $Id: file.c,v 1.103 2005/09/07 08:34:54 havasi Exp $ * */ @@ -134,7 +134,8 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg, D1(printk(KERN_DEBUG "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", (unsigned int)inode->i_size, pageofs)); - ret = jffs2_reserve_space(c, sizeof(ri), &phys_ofs, &alloc_len, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(ri), &phys_ofs, &alloc_len, + ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) return ret; diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index c99451ae4b7..c15c3022047 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: fs.c,v 1.64 2005/09/01 08:42:31 havasi Exp $ + * $Id: fs.c,v 1.65 2005/09/07 08:34:54 havasi Exp $ * */ @@ -74,7 +74,8 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) return -ENOMEM; } - ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) { jffs2_free_raw_inode(ri); if (S_ISLNK(inode->i_mode & S_IFMT)) diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index def97157ecb..ee54cdc59e0 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: gc.c,v 1.153 2005/08/17 13:46:22 dedekind Exp $ + * $Id: gc.c,v 1.154 2005/09/07 08:34:54 havasi Exp $ * */ @@ -513,8 +513,11 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, /* Ask for a small amount of space (or the totlen if smaller) because we don't want to force wastage of the end of a block if splitting would work. */ - ret = jffs2_reserve_space_gc(c, min_t(uint32_t, sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN, - rawlen), &phys_ofs, &alloclen); + ret = jffs2_reserve_space_gc(c, min_t(uint32_t, sizeof(struct jffs2_raw_inode) + + JFFS2_MIN_DATA_LEN, rawlen), &phys_ofs, &alloclen, rawlen); + /* this is not the exact summary size of it, + it is only an upper estimation */ + if (ret) return ret; @@ -622,7 +625,9 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, jffs2_dbg_acct_sanity_check(c,jeb); jffs2_dbg_acct_paranoia_check(c, jeb); - ret = jffs2_reserve_space_gc(c, rawlen, &phys_ofs, &dummy); + ret = jffs2_reserve_space_gc(c, rawlen, &phys_ofs, &dummy, rawlen); + /* this is not the exact summary size of it, + it is only an upper estimation */ if (!ret) { D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", phys_ofs)); @@ -701,7 +706,8 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ } - ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &phys_ofs, &alloclen); + ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &phys_ofs, &alloclen, + JFFS2_SUMMARY_INODE_SIZE); if (ret) { printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_metadata failed: %d\n", sizeof(ri)+ mdatalen, ret); @@ -781,7 +787,8 @@ static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_er rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8)); rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize)); - ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &phys_ofs, &alloclen); + ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &phys_ofs, &alloclen, + JFFS2_SUMMARY_DIRENT_SIZE(rd.nsize)); if (ret) { printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_dirent failed: %d\n", sizeof(rd)+rd.nsize, ret); @@ -994,7 +1001,8 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras ri.data_crc = cpu_to_je32(0); ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); - ret = jffs2_reserve_space_gc(c, sizeof(ri), &phys_ofs, &alloclen); + ret = jffs2_reserve_space_gc(c, sizeof(ri), &phys_ofs, &alloclen, + JFFS2_SUMMARY_INODE_SIZE); if (ret) { printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_hole failed: %d\n", sizeof(ri), ret); @@ -1219,7 +1227,8 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era uint32_t cdatalen; uint16_t comprtype = JFFS2_COMPR_NONE; - ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen); + ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, + &alloclen, JFFS2_SUMMARY_INODE_SIZE); if (ret) { printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_dnode failed: %d\n", @@ -1276,4 +1285,3 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era jffs2_gc_release_page(c, pg_ptr, &pg); return ret; } - diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 1533af8b395..1222372cb29 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.h,v 1.139 2005/08/31 13:51:00 havasi Exp $ + * $Id: nodelist.h,v 1.140 2005/09/07 08:34:54 havasi Exp $ * */ @@ -20,6 +20,7 @@ #include #include #include +#include "summary.h" #ifdef __ECOS #include "os-ecos.h" @@ -326,8 +327,10 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode /* nodemgmt.c */ int jffs2_thread_should_wake(struct jffs2_sb_info *c); -int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, int prio); -int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len); +int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, + uint32_t *len, int prio, uint32_t sumsize); +int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, + uint32_t *len, uint32_t sumsize); int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new); void jffs2_complete_reservation(struct jffs2_sb_info *c); void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw); @@ -386,6 +389,10 @@ char *jffs2_getlink(struct jffs2_sb_info *c, struct jffs2_inode_info *f); /* scan.c */ int jffs2_scan_medium(struct jffs2_sb_info *c); void jffs2_rotate_lists(struct jffs2_sb_info *c); +int jffs2_fill_scan_buf(struct jffs2_sb_info *c, void *buf, + uint32_t ofs, uint32_t len); +struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino); +int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); /* build.c */ int jffs2_do_mount_fs(struct jffs2_sb_info *c); diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index fe7e70a4055..208b2bdf01e 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodemgmt.c,v 1.124 2005/07/20 15:32:28 dedekind Exp $ + * $Id: nodemgmt.c,v 1.125 2005/09/07 08:34:54 havasi Exp $ * */ @@ -17,6 +17,7 @@ #include #include /* For cond_resched() */ #include "nodelist.h" +#include "debug.h" /** * jffs2_reserve_space - request physical space to write nodes to flash @@ -38,9 +39,11 @@ * for the requested allocation. */ -static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len); +static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, + uint32_t *ofs, uint32_t *len, uint32_t sumsize); -int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, int prio) +int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, + uint32_t *len, int prio, uint32_t sumsize) { int ret = -EAGAIN; int blocksneeded = c->resv_blocks_write; @@ -129,7 +132,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs spin_lock(&c->erase_completion_lock); } - ret = jffs2_do_reserve_space(c, minsize, ofs, len); + ret = jffs2_do_reserve_space(c, minsize, ofs, len, sumsize); if (ret) { D1(printk(KERN_DEBUG "jffs2_reserve_space: ret is %d\n", ret)); } @@ -140,7 +143,8 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs return ret; } -int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len) +int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, + uint32_t *len, uint32_t sumsize) { int ret = -EAGAIN; minsize = PAD(minsize); @@ -149,7 +153,7 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t * spin_lock(&c->erase_completion_lock); while(ret == -EAGAIN) { - ret = jffs2_do_reserve_space(c, minsize, ofs, len); + ret = jffs2_do_reserve_space(c, minsize, ofs, len, sumsize); if (ret) { D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret)); } @@ -158,105 +162,183 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t * return ret; } -/* Called with alloc sem _and_ erase_completion_lock */ -static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len) + +/* Classify nextblock (clean, dirty of verydirty) and force to select an other one */ + +static void jffs2_close_nextblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) { - struct jffs2_eraseblock *jeb = c->nextblock; + + /* Check, if we have a dirty block now, or if it was dirty already */ + if (ISDIRTY (jeb->wasted_size + jeb->dirty_size)) { + c->dirty_size += jeb->wasted_size; + c->wasted_size -= jeb->wasted_size; + jeb->dirty_size += jeb->wasted_size; + jeb->wasted_size = 0; + if (VERYDIRTY(c, jeb->dirty_size)) { + D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to very_dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", + jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); + list_add_tail(&jeb->list, &c->very_dirty_list); + } else { + D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", + jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); + list_add_tail(&jeb->list, &c->dirty_list); + } + } else { + D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", + jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); + list_add_tail(&jeb->list, &c->clean_list); + } + c->nextblock = NULL; + +} + +/* Select a new jeb for nextblock */ + +static int jffs2_find_nextblock(struct jffs2_sb_info *c) +{ + struct list_head *next; - restart: - if (jeb && minsize > jeb->free_size) { - /* Skip the end of this block and file it as having some dirty space */ - /* If there's a pending write to it, flush now */ - if (jffs2_wbuf_dirty(c)) { + /* Take the next block off the 'free' list */ + + if (list_empty(&c->free_list)) { + + if (!c->nr_erasing_blocks && + !list_empty(&c->erasable_list)) { + struct jffs2_eraseblock *ejeb; + + ejeb = list_entry(c->erasable_list.next, struct jffs2_eraseblock, list); + list_del(&ejeb->list); + list_add_tail(&ejeb->list, &c->erase_pending_list); + c->nr_erasing_blocks++; + jffs2_erase_pending_trigger(c); + D1(printk(KERN_DEBUG "jffs2_find_nextblock: Triggering erase of erasable block at 0x%08x\n", + ejeb->offset)); + } + + if (!c->nr_erasing_blocks && + !list_empty(&c->erasable_pending_wbuf_list)) { + D1(printk(KERN_DEBUG "jffs2_find_nextblock: Flushing write buffer\n")); + /* c->nextblock is NULL, no update to c->nextblock allowed */ spin_unlock(&c->erase_completion_lock); - D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Flushing write buffer\n")); jffs2_flush_wbuf_pad(c); spin_lock(&c->erase_completion_lock); - jeb = c->nextblock; - goto restart; + /* Have another go. It'll be on the erasable_list now */ + return -EAGAIN; } - c->wasted_size += jeb->free_size; - c->free_size -= jeb->free_size; - jeb->wasted_size += jeb->free_size; - jeb->free_size = 0; - - /* Check, if we have a dirty block now, or if it was dirty already */ - if (ISDIRTY (jeb->wasted_size + jeb->dirty_size)) { - c->dirty_size += jeb->wasted_size; - c->wasted_size -= jeb->wasted_size; - jeb->dirty_size += jeb->wasted_size; - jeb->wasted_size = 0; - if (VERYDIRTY(c, jeb->dirty_size)) { - D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to very_dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - list_add_tail(&jeb->list, &c->very_dirty_list); - } else { - D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - list_add_tail(&jeb->list, &c->dirty_list); - } - } else { - D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - list_add_tail(&jeb->list, &c->clean_list); + + if (!c->nr_erasing_blocks) { + /* Ouch. We're in GC, or we wouldn't have got here. + And there's no space left. At all. */ + printk(KERN_CRIT "Argh. No free space left for GC. nr_erasing_blocks is %d. nr_free_blocks is %d. (erasableempty: %s, erasingempty: %s, erasependingempty: %s)\n", + c->nr_erasing_blocks, c->nr_free_blocks, list_empty(&c->erasable_list)?"yes":"no", + list_empty(&c->erasing_list)?"yes":"no", list_empty(&c->erase_pending_list)?"yes":"no"); + return -ENOSPC; } - c->nextblock = jeb = NULL; + + spin_unlock(&c->erase_completion_lock); + /* Don't wait for it; just erase one right now */ + jffs2_erase_pending_blocks(c, 1); + spin_lock(&c->erase_completion_lock); + + /* An erase may have failed, decreasing the + amount of free space available. So we must + restart from the beginning */ + return -EAGAIN; } + + next = c->free_list.next; + list_del(next); + c->nextblock = list_entry(next, struct jffs2_eraseblock, list); + c->nr_free_blocks--; - if (!jeb) { - struct list_head *next; - /* Take the next block off the 'free' list */ + jffs2_sum_reset_collected(c->summary); /* reset collected summary */ - if (list_empty(&c->free_list)) { + D1(printk(KERN_DEBUG "jffs2_find_nextblock(): new nextblock = 0x%08x\n", c->nextblock->offset)); - if (!c->nr_erasing_blocks && - !list_empty(&c->erasable_list)) { - struct jffs2_eraseblock *ejeb; + return 0; +} - ejeb = list_entry(c->erasable_list.next, struct jffs2_eraseblock, list); - list_del(&ejeb->list); - list_add_tail(&ejeb->list, &c->erase_pending_list); - c->nr_erasing_blocks++; - jffs2_erase_pending_trigger(c); - D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Triggering erase of erasable block at 0x%08x\n", - ejeb->offset)); +/* Called with alloc sem _and_ erase_completion_lock */ +static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, uint32_t sumsize) +{ + struct jffs2_eraseblock *jeb = c->nextblock; + uint32_t reserved_size; /* for summary information at the end of the jeb */ + int ret; + + restart: + reserved_size = 0; + + if (jffs2_sum_active() && (sumsize != JFFS2_SUMMARY_NOSUM_SIZE)) { + /* NOSUM_SIZE means not to generate summary */ + + if (jeb) { + reserved_size = PAD(sumsize + c->summary->sum_size + JFFS2_SUMMARY_FRAME_SIZE); + JFFS2_DBG_SUMMARY("minsize=%d , jeb->free=%d ," + "summary->size=%d , sumsize=%d\n", + minsize, jeb->free_size, + c->summary->sum_size, sumsize); + } + + /* Is there enough space for writing out the current node, or we have to + write out summary information now, close this jeb and select new nextblock? */ + if (jeb && (PAD(minsize) + PAD(c->summary->sum_size + sumsize + + JFFS2_SUMMARY_FRAME_SIZE) > jeb->free_size)) { + + /* Has summary been disabled for this jeb? */ + if (jffs2_sum_is_disabled(c->summary)) { + sumsize = JFFS2_SUMMARY_NOSUM_SIZE; + goto restart; } - if (!c->nr_erasing_blocks && - !list_empty(&c->erasable_pending_wbuf_list)) { - D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Flushing write buffer\n")); - /* c->nextblock is NULL, no update to c->nextblock allowed */ + /* Writing out the collected summary information */ + JFFS2_DBG_SUMMARY("generating summary for 0x%08x.\n", jeb->offset); + ret = jffs2_sum_write_sumnode(c); + + if (ret) + return ret; + + if (jffs2_sum_is_disabled(c->summary)) { + /* jffs2_write_sumnode() couldn't write out the summary information + diabling summary for this jeb and free the collected information + */ + sumsize = JFFS2_SUMMARY_NOSUM_SIZE; + goto restart; + } + + jffs2_close_nextblock(c, jeb); + jeb = NULL; + } + } else { + if (jeb && minsize > jeb->free_size) { + /* Skip the end of this block and file it as having some dirty space */ + /* If there's a pending write to it, flush now */ + + if (jffs2_wbuf_dirty(c)) { spin_unlock(&c->erase_completion_lock); + D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Flushing write buffer\n")); jffs2_flush_wbuf_pad(c); spin_lock(&c->erase_completion_lock); - /* Have another go. It'll be on the erasable_list now */ - return -EAGAIN; - } - - if (!c->nr_erasing_blocks) { - /* Ouch. We're in GC, or we wouldn't have got here. - And there's no space left. At all. */ - printk(KERN_CRIT "Argh. No free space left for GC. nr_erasing_blocks is %d. nr_free_blocks is %d. (erasableempty: %s, erasingempty: %s, erasependingempty: %s)\n", - c->nr_erasing_blocks, c->nr_free_blocks, list_empty(&c->erasable_list)?"yes":"no", - list_empty(&c->erasing_list)?"yes":"no", list_empty(&c->erase_pending_list)?"yes":"no"); - return -ENOSPC; + jeb = c->nextblock; + goto restart; } - spin_unlock(&c->erase_completion_lock); - /* Don't wait for it; just erase one right now */ - jffs2_erase_pending_blocks(c, 1); - spin_lock(&c->erase_completion_lock); + c->wasted_size += jeb->free_size; + c->free_size -= jeb->free_size; + jeb->wasted_size += jeb->free_size; + jeb->free_size = 0; - /* An erase may have failed, decreasing the - amount of free space available. So we must - restart from the beginning */ - return -EAGAIN; + jffs2_close_nextblock(c, jeb); + jeb = NULL; } + } + + if (!jeb) { + + ret = jffs2_find_nextblock(c); + if (ret) + return ret; - next = c->free_list.next; - list_del(next); - c->nextblock = jeb = list_entry(next, struct jffs2_eraseblock, list); - c->nr_free_blocks--; + jeb = c->nextblock; if (jeb->free_size != c->sector_size - c->cleanmarker_size) { printk(KERN_WARNING "Eep. Block 0x%08x taken from free_list had free_size of 0x%08x!!\n", jeb->offset, jeb->free_size); @@ -266,7 +348,7 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, ui /* OK, jeb (==c->nextblock) is now pointing at a block which definitely has enough space */ *ofs = jeb->offset + (c->sector_size - jeb->free_size); - *len = jeb->free_size; + *len = jeb->free_size - reserved_size; if (c->cleanmarker_size && jeb->used_size == c->cleanmarker_size && !jeb->first_node->next_in_ino) { diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index c3c1619fb13..e026888cf1c 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: os-linux.h,v 1.60 2005/08/06 04:51:30 nico Exp $ + * $Id: os-linux.h,v 1.61 2005/09/07 08:34:54 havasi Exp $ * */ @@ -67,12 +67,18 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) #ifndef CONFIG_JFFS2_FS_WRITEBUFFER #define SECTOR_ADDR(x) ( ((unsigned long)(x) & ~(c->sector_size-1)) ) + +#ifdef CONFIG_JFFS2_SUMMARY +#define jffs2_can_mark_obsolete(c) (0) +#else #define jffs2_can_mark_obsolete(c) (1) +#endif + #define jffs2_is_writebuffered(c) (0) #define jffs2_cleanmarker_oob(c) (0) #define jffs2_write_nand_cleanmarker(c,jeb) (-EIO) -#define jffs2_flash_write(c, ofs, len, retlen, buf) ((c)->mtd->write((c)->mtd, ofs, len, retlen, buf)) +#define jffs2_flash_write(c, ofs, len, retlen, buf) jffs2_flash_direct_write(c, ofs, len, retlen, buf) #define jffs2_flash_read(c, ofs, len, retlen, buf) ((c)->mtd->read((c)->mtd, ofs, len, retlen, buf)) #define jffs2_flush_wbuf_pad(c) ({ (void)(c), 0; }) #define jffs2_flush_wbuf_gc(c, i) ({ (void)(c), (void) i, 0; }) @@ -97,9 +103,15 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) #define jffs2_is_writebuffered(c) (c->wbuf != NULL) #define SECTOR_ADDR(x) ( ((unsigned long)(x) / (unsigned long)(c->sector_size)) * c->sector_size ) + +#ifdef CONFIG_JFFS2_SUMMARY +#define jffs2_can_mark_obsolete(c) (0) +#else #define jffs2_can_mark_obsolete(c) \ ((c->mtd->type == MTD_NORFLASH && !(c->mtd->flags & (MTD_ECC|MTD_PROGRAM_REGIONS))) || \ c->mtd->type == MTD_RAM) +#endif + #define jffs2_cleanmarker_oob(c) (c->mtd->type == MTD_NANDFLASH) #define jffs2_flash_write_oob(c, ofs, len, retlen, buf) ((c)->mtd->write_oob((c)->mtd, ofs, len, retlen, buf)) @@ -192,7 +204,8 @@ void jffs2_flash_cleanup(struct jffs2_sb_info *c); /* writev.c */ int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); - +int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, + size_t *retlen, const u_char *buf); #endif /* __JFFS2_OS_LINUX_H__ */ diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index fcd6314cf17..4e60ba8da19 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: scan.c,v 1.121 2005/07/20 15:32:28 dedekind Exp $ + * $Id: scan.c,v 1.122 2005/09/07 08:34:54 havasi Exp $ * */ #include @@ -18,22 +18,11 @@ #include #include #include "nodelist.h" +#include "summary.h" +#include "debug.h" #define DEFAULT_EMPTY_SCAN_SIZE 1024 -#define DIRTY_SPACE(x) do { typeof(x) _x = (x); \ - c->free_size -= _x; c->dirty_size += _x; \ - jeb->free_size -= _x ; jeb->dirty_size += _x; \ - }while(0) -#define USED_SPACE(x) do { typeof(x) _x = (x); \ - c->free_size -= _x; c->used_size += _x; \ - jeb->free_size -= _x ; jeb->used_size += _x; \ - }while(0) -#define UNCHECKED_SPACE(x) do { typeof(x) _x = (x); \ - c->free_size -= _x; c->unchecked_size += _x; \ - jeb->free_size -= _x ; jeb->unchecked_size += _x; \ - }while(0) - #define noisy_printk(noise, args...) do { \ if (*(noise)) { \ printk(KERN_NOTICE args); \ @@ -47,23 +36,16 @@ static uint32_t pseudo_random; static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - unsigned char *buf, uint32_t buf_size); + unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s); /* These helper functions _must_ increase ofs and also do the dirty/used space accounting. * Returning an error will abort the mount - bad checksums etc. should just mark the space * as dirty. */ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_raw_inode *ri, uint32_t ofs); + struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s); static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_raw_dirent *rd, uint32_t ofs); - -#define BLK_STATE_ALLFF 0 -#define BLK_STATE_CLEAN 1 -#define BLK_STATE_PARTDIRTY 2 -#define BLK_STATE_CLEANMARKER 3 -#define BLK_STATE_ALLDIRTY 4 -#define BLK_STATE_BADBLOCK 5 + struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s); static inline int min_free(struct jffs2_sb_info *c) { @@ -89,6 +71,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) uint32_t empty_blocks = 0, bad_blocks = 0; unsigned char *flashbuf = NULL; uint32_t buf_size = 0; + struct jffs2_summary *s = NULL; /* summary info collected by the scan process */ #ifndef __ECOS size_t pointlen; @@ -122,10 +105,23 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) return -ENOMEM; } + if (jffs2_sum_active()) { + s = kmalloc(sizeof(struct jffs2_summary), GFP_KERNEL); + if (!s) { + JFFS2_WARNING("Can't allocate memory for summary\n"); + return -ENOMEM; + } + memset(s, 0, sizeof(struct jffs2_summary)); + } + for (i=0; inr_blocks; i++) { struct jffs2_eraseblock *jeb = &c->blocks[i]; - ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), buf_size); + /* reset summary info for next eraseblock scan */ + jffs2_sum_reset_collected(s); + + ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), + buf_size, s); if (ret < 0) goto out; @@ -162,18 +158,18 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) break; case BLK_STATE_CLEAN: - /* Full (or almost full) of clean data. Clean list */ - list_add(&jeb->list, &c->clean_list); + /* Full (or almost full) of clean data. Clean list */ + list_add(&jeb->list, &c->clean_list); break; case BLK_STATE_PARTDIRTY: - /* Some data, but not full. Dirty list. */ - /* We want to remember the block with most free space - and stick it in the 'nextblock' position to start writing to it. */ - if (jeb->free_size > min_free(c) && - (!c->nextblock || c->nextblock->free_size < jeb->free_size)) { - /* Better candidate for the next writes to go to */ - if (c->nextblock) { + /* Some data, but not full. Dirty list. */ + /* We want to remember the block with most free space + and stick it in the 'nextblock' position to start writing to it. */ + if (jeb->free_size > min_free(c) && + (!c->nextblock || c->nextblock->free_size < jeb->free_size)) { + /* Better candidate for the next writes to go to */ + if (c->nextblock) { c->nextblock->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size; c->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size; c->free_size -= c->nextblock->free_size; @@ -184,9 +180,14 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) } else { list_add(&c->nextblock->list, &c->dirty_list); } + /* deleting summary information of the old nextblock */ + jffs2_sum_reset_collected(c->summary); } - c->nextblock = jeb; - } else { + /* update collected summary infromation for the current nextblock */ + jffs2_sum_move_collected(c, s); + D1(printk(KERN_DEBUG "jffs2_scan_medium(): new nextblock = 0x%08x\n", jeb->offset)); + c->nextblock = jeb; + } else { jeb->dirty_size += jeb->free_size + jeb->wasted_size; c->dirty_size += jeb->free_size + jeb->wasted_size; c->free_size -= jeb->free_size; @@ -197,30 +198,33 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) } else { list_add(&jeb->list, &c->dirty_list); } - } + } break; case BLK_STATE_ALLDIRTY: /* Nothing valid - not even a clean marker. Needs erasing. */ - /* For now we just put it on the erasing list. We'll start the erases later */ + /* For now we just put it on the erasing list. We'll start the erases later */ D1(printk(KERN_NOTICE "JFFS2: Erase block at 0x%08x is not formatted. It will be erased\n", jeb->offset)); - list_add(&jeb->list, &c->erase_pending_list); + list_add(&jeb->list, &c->erase_pending_list); c->nr_erasing_blocks++; break; - + case BLK_STATE_BADBLOCK: D1(printk(KERN_NOTICE "JFFS2: Block at 0x%08x is bad\n", jeb->offset)); - list_add(&jeb->list, &c->bad_list); + list_add(&jeb->list, &c->bad_list); c->bad_size += c->sector_size; c->free_size -= c->sector_size; bad_blocks++; break; default: printk(KERN_WARNING "jffs2_scan_medium(): unknown block state\n"); - BUG(); + BUG(); } } - + + if (jffs2_sum_active() && s) + kfree(s); + /* Nextblock dirty is always seen as wasted, because we cannot recycle it now */ if (c->nextblock && (c->nextblock->dirty_size)) { c->nextblock->wasted_size += c->nextblock->dirty_size; @@ -265,7 +269,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) return ret; } -static int jffs2_fill_scan_buf (struct jffs2_sb_info *c, unsigned char *buf, +int jffs2_fill_scan_buf (struct jffs2_sb_info *c, void *buf, uint32_t ofs, uint32_t len) { int ret; @@ -286,14 +290,36 @@ static int jffs2_fill_scan_buf (struct jffs2_sb_info *c, unsigned char *buf, return 0; } +int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) +{ + if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->dirty_size + && (!jeb->first_node || !jeb->first_node->next_phys) ) + return BLK_STATE_CLEANMARKER; + + /* move blocks with max 4 byte dirty space to cleanlist */ + else if (!ISDIRTY(c->sector_size - (jeb->used_size + jeb->unchecked_size))) { + c->dirty_size -= jeb->dirty_size; + c->wasted_size += jeb->dirty_size; + jeb->wasted_size += jeb->dirty_size; + jeb->dirty_size = 0; + return BLK_STATE_CLEAN; + } else if (jeb->used_size || jeb->unchecked_size) + return BLK_STATE_PARTDIRTY; + else + return BLK_STATE_ALLDIRTY; +} + static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - unsigned char *buf, uint32_t buf_size) { + unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) { struct jffs2_unknown_node *node; struct jffs2_unknown_node crcnode; + struct jffs2_sum_marker *sm; uint32_t ofs, prevofs; uint32_t hdr_crc, buf_ofs, buf_len; int err; int noise = 0; + + #ifdef CONFIG_JFFS2_FS_WRITEBUFFER int cleanmarkerfound = 0; #endif @@ -319,10 +345,46 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo } } #endif + + if (jffs2_sum_active()) { + sm = kmalloc(sizeof(struct jffs2_sum_marker), GFP_KERNEL); + if (!sm) { + return -ENOMEM; + } + + err = jffs2_fill_scan_buf(c, (unsigned char *) sm, jeb->offset + c->sector_size - + sizeof(struct jffs2_sum_marker), sizeof(struct jffs2_sum_marker)); + if (err) { + kfree(sm); + return err; + } + + if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC ) { + err = jffs2_sum_scan_sumnode(c, jeb, je32_to_cpu(sm->offset), &pseudo_random); + if (err) { + kfree(sm); + return err; + } + } + + kfree(sm); + + ofs = jeb->offset; + prevofs = jeb->offset - 1; + } + buf_ofs = jeb->offset; if (!buf_size) { buf_len = c->sector_size; + + if (jffs2_sum_active()) { + /* must reread because of summary test */ + err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len); + if (err) + return err; + } + } else { buf_len = EMPTY_SCAN_SIZE(c->sector_size); err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len); @@ -367,6 +429,8 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo noise = 10; + JFFS2_DBG_SUMMARY("no summary found in jeb 0x%08x. Apply original scan.\n",jeb->offset); + scan_more: while(ofs < jeb->offset + c->sector_size) { @@ -532,7 +596,7 @@ scan_more: buf_ofs = ofs; node = (void *)buf; } - err = jffs2_scan_inode_node(c, jeb, (void *)node, ofs); + err = jffs2_scan_inode_node(c, jeb, (void *)node, ofs, s); if (err) return err; ofs += PAD(je32_to_cpu(node->totlen)); break; @@ -548,7 +612,7 @@ scan_more: buf_ofs = ofs; node = (void *)buf; } - err = jffs2_scan_dirent_node(c, jeb, (void *)node, ofs); + err = jffs2_scan_dirent_node(c, jeb, (void *)node, ofs, s); if (err) return err; ofs += PAD(je32_to_cpu(node->totlen)); break; @@ -582,6 +646,8 @@ scan_more: break; case JFFS2_NODETYPE_PADDING: + if (jffs2_sum_active()) + jffs2_sum_add_padding_mem(s, je32_to_cpu(node->totlen)); DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); ofs += PAD(je32_to_cpu(node->totlen)); break; @@ -616,6 +682,13 @@ scan_more: } } + if (jffs2_sum_active()) { + if (PAD(s->sum_size + JFFS2_SUMMARY_FRAME_SIZE) > jeb->free_size) { + JFFS2_DBG_SUMMARY("There is not enough space for " + "summary information, disabling for this jeb!\n"); + jffs2_sum_disable_collecting(s); + } + } D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x\n", jeb->offset, jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size)); @@ -628,24 +701,10 @@ scan_more: jeb->wasted_size = 0; } - if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->dirty_size - && (!jeb->first_node || !jeb->first_node->next_phys) ) - return BLK_STATE_CLEANMARKER; - - /* move blocks with max 4 byte dirty space to cleanlist */ - else if (!ISDIRTY(c->sector_size - (jeb->used_size + jeb->unchecked_size))) { - c->dirty_size -= jeb->dirty_size; - c->wasted_size += jeb->dirty_size; - jeb->wasted_size += jeb->dirty_size; - jeb->dirty_size = 0; - return BLK_STATE_CLEAN; - } else if (jeb->used_size || jeb->unchecked_size) - return BLK_STATE_PARTDIRTY; - else - return BLK_STATE_ALLDIRTY; + return jffs2_scan_classify_jeb(c, jeb); } -static struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino) +struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino) { struct jffs2_inode_cache *ic; @@ -672,7 +731,7 @@ static struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info } static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_raw_inode *ri, uint32_t ofs) + struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s) { struct jffs2_raw_node_ref *raw; struct jffs2_inode_cache *ic; @@ -739,11 +798,16 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc pseudo_random += je32_to_cpu(ri->version); UNCHECKED_SPACE(PAD(je32_to_cpu(ri->totlen))); + + if (jffs2_sum_active()) { + jffs2_sum_add_inode_mem(s, ri, ofs - jeb->offset); + } + return 0; } static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_raw_dirent *rd, uint32_t ofs) + struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s) { struct jffs2_raw_node_ref *raw; struct jffs2_full_dirent *fd; @@ -817,6 +881,10 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo USED_SPACE(PAD(je32_to_cpu(rd->totlen))); jffs2_add_fd_to_list(c, fd, &ic->scan_dents); + if (jffs2_sum_active()) { + jffs2_sum_add_dirent_mem(s, rd, ofs - jeb->offset); + } + return 0; } diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c new file mode 100644 index 00000000000..cb5dd8f11e7 --- /dev/null +++ b/fs/jffs2/summary.c @@ -0,0 +1,729 @@ +/* + * JFFS2 -- Journalling Flash File System, Version 2. + * + * Copyright (C) 2004 Ferenc Havasi , + * Zoltan Sogor , + * Patrik Kluba , + * University of Szeged, Hungary + * + * For licensing information, see the file 'LICENCE' in this directory. + * + * $Id: summary.c,v 1.1 2005/09/07 08:34:54 havasi Exp $ + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "nodelist.h" +#include "debug.h" + +int jffs2_sum_init(struct jffs2_sb_info *c) +{ + c->summary = kmalloc(sizeof(struct jffs2_summary), GFP_KERNEL); + + if (!c->summary) { + JFFS2_WARNING("Can't allocate memory for summary information!\n"); + return -ENOMEM; + } + + memset(c->summary, 0, sizeof(struct jffs2_summary)); + + c->summary->sum_buf = vmalloc(c->sector_size); + + if (!c->summary->sum_buf) { + JFFS2_WARNING("Can't allocate buffer for writing out summary information!\n"); + return -ENOMEM; + } + + JFFS2_DBG_SUMMARY("returned succesfully\n"); + + return 0; +} + +void jffs2_sum_exit(struct jffs2_sb_info *c) +{ + JFFS2_DBG_SUMMARY("called\n"); + + jffs2_sum_disable_collecting(c->summary); + + vfree(c->summary->sum_buf); + c->summary->sum_buf = NULL; + + kfree(c->summary); + c->summary = NULL; +} + +static int jffs2_sum_add_mem(struct jffs2_summary *s, union jffs2_sum_mem *item) +{ + if (!s->sum_list_head) + s->sum_list_head = (union jffs2_sum_mem *) item; + if (s->sum_list_tail) + s->sum_list_tail->u.next = (union jffs2_sum_mem *) item; + s->sum_list_tail = (union jffs2_sum_mem *) item; + + switch (je16_to_cpu(item->u.nodetype)) { + case JFFS2_NODETYPE_INODE: + s->sum_size += JFFS2_SUMMARY_INODE_SIZE; + s->sum_num++; + JFFS2_DBG_SUMMARY("inode (%u) added to summary\n", + je32_to_cpu(item->i.inode)); + break; + case JFFS2_NODETYPE_DIRENT: + s->sum_size += JFFS2_SUMMARY_DIRENT_SIZE(item->d.nsize); + s->sum_num++; + JFFS2_DBG_SUMMARY("dirent (%u) added to summary\n", + je32_to_cpu(item->d.ino)); + break; + default: + JFFS2_WARNING("UNKNOWN node type %u\n", + je16_to_cpu(item->u.nodetype)); + return 1; + } + return 0; +} + + +/* The following 3 functions are called from scan.c to collect summary info for not closed jeb */ + +int jffs2_sum_add_padding_mem(struct jffs2_summary *s, uint32_t size) +{ + JFFS2_DBG_SUMMARY("called with %u\n", size); + s->sum_padded += size; + return 0; +} + +int jffs2_sum_add_inode_mem(struct jffs2_summary *s, struct jffs2_raw_inode *ri, + uint32_t ofs) +{ + struct jffs2_sum_inode_mem *temp = kmalloc(sizeof(struct jffs2_sum_inode_mem), GFP_KERNEL); + + if (!temp) + return -ENOMEM; + + temp->nodetype = ri->nodetype; + temp->inode = ri->ino; + temp->version = ri->version; + temp->offset = cpu_to_je32(ofs); /* relative offset from the begining of the jeb */ + temp->totlen = ri->totlen; + temp->next = NULL; + + return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp); +} + +int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *rd, + uint32_t ofs) +{ + struct jffs2_sum_dirent_mem *temp = + kmalloc(sizeof(struct jffs2_sum_dirent_mem) + rd->nsize, GFP_KERNEL); + + if (!temp) + return -ENOMEM; + + temp->nodetype = rd->nodetype; + temp->totlen = rd->totlen; + temp->offset = cpu_to_je32(ofs); /* relative from the begining of the jeb */ + temp->pino = rd->pino; + temp->version = rd->version; + temp->ino = rd->ino; + temp->nsize = rd->nsize; + temp->type = rd->type; + temp->next = NULL; + + memcpy(temp->name, rd->name, rd->nsize); + + return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp); +} + +/* Cleanup every collected summary information */ + +static void jffs2_sum_clean_collected(struct jffs2_summary *s) +{ + union jffs2_sum_mem *temp; + + if (!s->sum_list_head) { + JFFS2_DBG_SUMMARY("already empty\n"); + } + while (s->sum_list_head) { + temp = s->sum_list_head; + s->sum_list_head = s->sum_list_head->u.next; + kfree(temp); + } + s->sum_list_tail = NULL; + s->sum_padded = 0; + s->sum_num = 0; +} + +void jffs2_sum_reset_collected(struct jffs2_summary *s) +{ + JFFS2_DBG_SUMMARY("called\n"); + jffs2_sum_clean_collected(s); + s->sum_size = 0; +} + +void jffs2_sum_disable_collecting(struct jffs2_summary *s) +{ + JFFS2_DBG_SUMMARY("called\n"); + jffs2_sum_clean_collected(s); + s->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; +} + +int jffs2_sum_is_disabled(struct jffs2_summary *s) +{ + return (s->sum_size == JFFS2_SUMMARY_NOSUM_SIZE); +} + +/* Move the collected summary information into sb (called from scan.c) */ + +void jffs2_sum_move_collected(struct jffs2_sb_info *c, struct jffs2_summary *s) +{ + JFFS2_DBG_SUMMARY("oldsize=0x%x oldnum=%u => newsize=0x%x newnum=%u\n", + c->summary->sum_size, c->summary->sum_num, + s->sum_size, s->sum_num); + + c->summary->sum_size = s->sum_size; + c->summary->sum_num = s->sum_num; + c->summary->sum_padded = s->sum_padded; + c->summary->sum_list_head = s->sum_list_head; + c->summary->sum_list_tail = s->sum_list_tail; + + s->sum_list_head = s->sum_list_tail = NULL; +} + +/* Called from wbuf.c to collect writed node info */ + +int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs, + unsigned long count, uint32_t ofs) +{ + union jffs2_node_union *node; + struct jffs2_eraseblock *jeb; + + node = invecs[0].iov_base; + jeb = &c->blocks[ofs / c->sector_size]; + ofs -= jeb->offset; + + switch (je16_to_cpu(node->u.nodetype)) { + case JFFS2_NODETYPE_INODE: { + struct jffs2_sum_inode_mem *temp = + kmalloc(sizeof(struct jffs2_sum_inode_mem), GFP_KERNEL); + + if (!temp) + goto no_mem; + + temp->nodetype = node->i.nodetype; + temp->inode = node->i.ino; + temp->version = node->i.version; + temp->offset = cpu_to_je32(ofs); + temp->totlen = node->i.totlen; + temp->next = NULL; + + return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp); + } + + case JFFS2_NODETYPE_DIRENT: { + struct jffs2_sum_dirent_mem *temp = + kmalloc(sizeof(struct jffs2_sum_dirent_mem) + node->d.nsize, GFP_KERNEL); + + if (!temp) + goto no_mem; + + temp->nodetype = node->d.nodetype; + temp->totlen = node->d.totlen; + temp->offset = cpu_to_je32(ofs); + temp->pino = node->d.pino; + temp->version = node->d.version; + temp->ino = node->d.ino; + temp->nsize = node->d.nsize; + temp->type = node->d.type; + temp->next = NULL; + + switch (count) { + case 1: + memcpy(temp->name,node->d.name,node->d.nsize); + break; + + case 2: + memcpy(temp->name,invecs[1].iov_base,node->d.nsize); + break; + + default: + BUG(); /* impossible count value */ + break; + } + + return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp); + } + + case JFFS2_NODETYPE_PADDING: + JFFS2_DBG_SUMMARY("node PADDING\n"); + c->summary->sum_padded += je32_to_cpu(node->u.totlen); + break; + + case JFFS2_NODETYPE_CLEANMARKER: + JFFS2_DBG_SUMMARY("node CLEANMARKER\n"); + break; + + case JFFS2_NODETYPE_SUMMARY: + JFFS2_DBG_SUMMARY("node SUMMARY\n"); + break; + + default: + /* If you implement a new node type you should also implement + summary support for it or disable summary. + */ + BUG(); + break; + } + + return 0; + +no_mem: + JFFS2_WARNING("MEMORY ALLOCATION ERROR!"); + return -ENOMEM; +} + + +/* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */ + +static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, + struct jffs2_summary_node *summary, uint32_t *pseudo_random) +{ + struct jffs2_raw_node_ref *raw; + struct jffs2_inode_cache *ic; + struct jffs2_full_dirent *fd; + void *sp; + int i, ino; + + sp = summary->sum; + + for (i=0; isum_num); i++) { + JFFS2_DBG_SUMMARY("processing summary index %d\n", i); + + switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) { + case JFFS2_NODETYPE_INODE: { + struct jffs2_sum_inode_flash *spi; + spi = sp; + + ino = je32_to_cpu(spi->inode); + + JFFS2_DBG_SUMMARY("Inode at 0x%08x\n", + jeb->offset + je32_to_cpu(spi->offset)); + + raw = jffs2_alloc_raw_node_ref(); + if (!raw) { + JFFS2_NOTICE("allocation of node reference failed\n"); + kfree(summary); + return -ENOMEM; + } + + ic = jffs2_scan_make_ino_cache(c, ino); + if (!ic) { + JFFS2_NOTICE("scan_make_ino_cache failed\n"); + jffs2_free_raw_node_ref(raw); + kfree(summary); + return -ENOMEM; + } + + raw->flash_offset = (jeb->offset + je32_to_cpu(spi->offset)) | REF_UNCHECKED; + raw->__totlen = PAD(je32_to_cpu(spi->totlen)); + raw->next_phys = NULL; + raw->next_in_ino = ic->nodes; + + ic->nodes = raw; + if (!jeb->first_node) + jeb->first_node = raw; + if (jeb->last_node) + jeb->last_node->next_phys = raw; + jeb->last_node = raw; + *pseudo_random += je32_to_cpu(spi->version); + + UNCHECKED_SPACE(PAD(je32_to_cpu(spi->totlen))); + + sp += JFFS2_SUMMARY_INODE_SIZE; + + break; + } + + case JFFS2_NODETYPE_DIRENT: { + struct jffs2_sum_dirent_flash *spd; + spd = sp; + + JFFS2_DBG_SUMMARY("Dirent at 0x%08x\n", + jeb->offset + je32_to_cpu(spd->offset)); + + fd = jffs2_alloc_full_dirent(spd->nsize+1); + if (!fd) { + kfree(summary); + return -ENOMEM; + } + + memcpy(&fd->name, spd->name, spd->nsize); + fd->name[spd->nsize] = 0; + + raw = jffs2_alloc_raw_node_ref(); + if (!raw) { + jffs2_free_full_dirent(fd); + JFFS2_NOTICE("allocation of node reference failed\n"); + kfree(summary); + return -ENOMEM; + } + + ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino)); + if (!ic) { + jffs2_free_full_dirent(fd); + jffs2_free_raw_node_ref(raw); + kfree(summary); + return -ENOMEM; + } + + raw->__totlen = PAD(je32_to_cpu(spd->totlen)); + raw->flash_offset = (jeb->offset + je32_to_cpu(spd->offset)) | REF_PRISTINE; + raw->next_phys = NULL; + raw->next_in_ino = ic->nodes; + ic->nodes = raw; + if (!jeb->first_node) + jeb->first_node = raw; + if (jeb->last_node) + jeb->last_node->next_phys = raw; + jeb->last_node = raw; + + fd->raw = raw; + fd->next = NULL; + fd->version = je32_to_cpu(spd->version); + fd->ino = je32_to_cpu(spd->ino); + fd->nhash = full_name_hash(fd->name, spd->nsize); + fd->type = spd->type; + USED_SPACE(PAD(je32_to_cpu(spd->totlen))); + jffs2_add_fd_to_list(c, fd, &ic->scan_dents); + + *pseudo_random += je32_to_cpu(spd->version); + + sp += JFFS2_SUMMARY_DIRENT_SIZE(spd->nsize); + + break; + } + + default : { + JFFS2_WARNING("Unsupported node type found in summary! Exiting..."); + kfree(summary); + return -EIO; + } + } + } + + kfree(summary); + return 0; +} + +/* Process the summary node - called from jffs2_scan_eraseblock() */ + +int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, + uint32_t ofs, uint32_t *pseudo_random) +{ + struct jffs2_unknown_node crcnode; + struct jffs2_raw_node_ref *cache_ref; + struct jffs2_summary_node *summary; + int ret, sumsize; + uint32_t crc; + + sumsize = c->sector_size - ofs; + ofs += jeb->offset; + + JFFS2_DBG_SUMMARY("summary found for 0x%08x at 0x%08x (0x%x bytes)\n", + jeb->offset, ofs, sumsize); + + summary = kmalloc(sumsize, GFP_KERNEL); + + if (!summary) { + return -ENOMEM; + } + + ret = jffs2_fill_scan_buf(c, (unsigned char *)summary, ofs, sumsize); + + if (ret) { + kfree(summary); + return ret; + } + + /* OK, now check for node validity and CRC */ + crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + crcnode.nodetype = cpu_to_je16(JFFS2_NODETYPE_SUMMARY); + crcnode.totlen = summary->totlen; + crc = crc32(0, &crcnode, sizeof(crcnode)-4); + + if (je32_to_cpu(summary->hdr_crc) != crc) { + JFFS2_DBG_SUMMARY("Summary node header is corrupt (bad CRC or " + "no summary at all)\n"); + goto crc_err; + } + + if (je32_to_cpu(summary->totlen) != sumsize) { + JFFS2_DBG_SUMMARY("Summary node is corrupt (wrong erasesize?)\n"); + goto crc_err; + } + + crc = crc32(0, summary, sizeof(struct jffs2_summary_node)-8); + + if (je32_to_cpu(summary->node_crc) != crc) { + JFFS2_DBG_SUMMARY("Summary node is corrupt (bad CRC)\n"); + goto crc_err; + } + + crc = crc32(0, summary->sum, sumsize - sizeof(struct jffs2_summary_node)); + + if (je32_to_cpu(summary->sum_crc) != crc) { + JFFS2_DBG_SUMMARY("Summary node data is corrupt (bad CRC)\n"); + goto crc_err; + } + + if ( je32_to_cpu(summary->cln_mkr) ) { + + JFFS2_DBG_SUMMARY("Summary : CLEANMARKER node \n"); + + if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) { + JFFS2_DBG_SUMMARY("CLEANMARKER node has totlen 0x%x != normal 0x%x\n", + je32_to_cpu(summary->cln_mkr), c->cleanmarker_size); + UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr))); + } else if (jeb->first_node) { + JFFS2_DBG_SUMMARY("CLEANMARKER node not first node in block " + "(0x%08x)\n", jeb->offset); + UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr))); + } else { + struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref(); + + if (!marker_ref) { + JFFS2_NOTICE("Failed to allocate node ref for clean marker\n"); + kfree(summary); + return -ENOMEM; + } + + marker_ref->next_in_ino = NULL; + marker_ref->next_phys = NULL; + marker_ref->flash_offset = jeb->offset | REF_NORMAL; + marker_ref->__totlen = je32_to_cpu(summary->cln_mkr); + jeb->first_node = jeb->last_node = marker_ref; + + USED_SPACE( PAD(je32_to_cpu(summary->cln_mkr)) ); + } + } + + if (je32_to_cpu(summary->padded)) { + DIRTY_SPACE(je32_to_cpu(summary->padded)); + } + + ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random); + if (ret) + return ret; + + /* for PARANOIA_CHECK */ + cache_ref = jffs2_alloc_raw_node_ref(); + + if (!cache_ref) { + JFFS2_NOTICE("Failed to allocate node ref for cache\n"); + return -ENOMEM; + } + + cache_ref->next_in_ino = NULL; + cache_ref->next_phys = NULL; + cache_ref->flash_offset = ofs | REF_NORMAL; + cache_ref->__totlen = sumsize; + + if (!jeb->first_node) + jeb->first_node = cache_ref; + if (jeb->last_node) + jeb->last_node->next_phys = cache_ref; + jeb->last_node = cache_ref; + + USED_SPACE(sumsize); + + jeb->wasted_size += jeb->free_size; + c->wasted_size += jeb->free_size; + c->free_size -= jeb->free_size; + jeb->free_size = 0; + + return jffs2_scan_classify_jeb(c, jeb); + +crc_err: + JFFS2_WARNING("Summary node crc error, skipping summary information.\n"); + + return 0; +} + +/* Write summary data to flash - helper function for jffs2_sum_write_sumnode() */ + +static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, + uint32_t infosize, uint32_t datasize, int padsize) +{ + struct jffs2_summary_node isum; + union jffs2_sum_mem *temp; + struct jffs2_sum_marker *sm; + struct kvec vecs[2]; + void *wpage; + int ret; + size_t retlen; + + memset(c->summary->sum_buf, 0xff, datasize); + memset(&isum, 0, sizeof(isum)); + + isum.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + isum.nodetype = cpu_to_je16(JFFS2_NODETYPE_SUMMARY); + isum.totlen = cpu_to_je32(infosize); + isum.hdr_crc = cpu_to_je32(crc32(0, &isum, sizeof(struct jffs2_unknown_node) - 4)); + isum.padded = cpu_to_je32(c->summary->sum_padded); + isum.cln_mkr = cpu_to_je32(c->cleanmarker_size); + isum.sum_num = cpu_to_je32(c->summary->sum_num); + wpage = c->summary->sum_buf; + + while (c->summary->sum_num) { + + switch (je16_to_cpu(c->summary->sum_list_head->u.nodetype)) { + case JFFS2_NODETYPE_INODE: { + struct jffs2_sum_inode_flash *sino_ptr = wpage; + + sino_ptr->nodetype = c->summary->sum_list_head->i.nodetype; + sino_ptr->inode = c->summary->sum_list_head->i.inode; + sino_ptr->version = c->summary->sum_list_head->i.version; + sino_ptr->offset = c->summary->sum_list_head->i.offset; + sino_ptr->totlen = c->summary->sum_list_head->i.totlen; + + wpage += JFFS2_SUMMARY_INODE_SIZE; + + break; + } + + case JFFS2_NODETYPE_DIRENT: { + struct jffs2_sum_dirent_flash *sdrnt_ptr = wpage; + + sdrnt_ptr->nodetype = c->summary->sum_list_head->d.nodetype; + sdrnt_ptr->totlen = c->summary->sum_list_head->d.totlen; + sdrnt_ptr->offset = c->summary->sum_list_head->d.offset; + sdrnt_ptr->pino = c->summary->sum_list_head->d.pino; + sdrnt_ptr->version = c->summary->sum_list_head->d.version; + sdrnt_ptr->ino = c->summary->sum_list_head->d.ino; + sdrnt_ptr->nsize = c->summary->sum_list_head->d.nsize; + sdrnt_ptr->type = c->summary->sum_list_head->d.type; + + memcpy(sdrnt_ptr->name, c->summary->sum_list_head->d.name, + c->summary->sum_list_head->d.nsize); + + wpage += JFFS2_SUMMARY_DIRENT_SIZE(c->summary->sum_list_head->d.nsize); + + break; + } + + default : { + BUG(); /* unknown node in summary information */ + } + } + + temp = c->summary->sum_list_head; + c->summary->sum_list_head = c->summary->sum_list_head->u.next; + kfree(temp); + + c->summary->sum_num--; + } + + jffs2_sum_reset_collected(c->summary); + + wpage += padsize; + + sm = wpage; + sm->offset = cpu_to_je32(c->sector_size - jeb->free_size); + sm->magic = cpu_to_je32(JFFS2_SUM_MAGIC); + + isum.sum_crc = cpu_to_je32(crc32(0, c->summary->sum_buf, datasize)); + isum.node_crc = cpu_to_je32(crc32(0, &isum, sizeof(isum) - 8)); + + vecs[0].iov_base = &isum; + vecs[0].iov_len = sizeof(isum); + vecs[1].iov_base = c->summary->sum_buf; + vecs[1].iov_len = datasize; + + JFFS2_DBG_SUMMARY("JFFS2: writing out data to flash to pos : 0x%08x\n", + jeb->offset + c->sector_size - jeb->free_size); + + spin_unlock(&c->erase_completion_lock); + ret = jffs2_flash_writev(c, vecs, 2, jeb->offset + c->sector_size - + jeb->free_size, &retlen, 0); + spin_lock(&c->erase_completion_lock); + + + if (ret || (retlen != infosize)) { + JFFS2_WARNING("Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", + infosize, jeb->offset + c->sector_size - jeb->free_size, ret, retlen); + + c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; + WASTED_SPACE(infosize); + + return 1; + } + + return 0; +} + +/* Write out summary information - called from jffs2_do_reserve_space */ + +int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) +{ + struct jffs2_raw_node_ref *summary_ref; + int datasize, infosize, padsize, ret; + struct jffs2_eraseblock *jeb; + + JFFS2_DBG_SUMMARY("called\n"); + + jeb = c->nextblock; + + if (!c->summary->sum_num || !c->summary->sum_list_head) { + JFFS2_WARNING("Empty summary info!!!\n"); + BUG(); + } + + datasize = c->summary->sum_size + sizeof(struct jffs2_sum_marker); + infosize = sizeof(struct jffs2_summary_node) + datasize; + padsize = jeb->free_size - infosize; + infosize += padsize; + datasize += padsize; + + /* Is there enough space for summary? */ + if (padsize < 0) { + /* don't try to write out summary for this jeb */ + jffs2_sum_disable_collecting(c->summary); + + JFFS2_WARNING("Not enough space for summary, padsize = %d\n", padsize); + return 0; + } + + ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize); + if (ret) + return 0; /* can't write out summary, block is marked as NOSUM_SIZE */ + + /* for ACCT_PARANOIA_CHECK */ + spin_unlock(&c->erase_completion_lock); + summary_ref = jffs2_alloc_raw_node_ref(); + spin_lock(&c->erase_completion_lock); + + if (!summary_ref) { + JFFS2_NOTICE("Failed to allocate node ref for summary\n"); + return -ENOMEM; + } + + summary_ref->next_in_ino = NULL; + summary_ref->next_phys = NULL; + summary_ref->flash_offset = (jeb->offset + c->sector_size - jeb->free_size) | REF_NORMAL; + summary_ref->__totlen = infosize; + + if (!jeb->first_node) + jeb->first_node = summary_ref; + if (jeb->last_node) + jeb->last_node->next_phys = summary_ref; + jeb->last_node = summary_ref; + + USED_SPACE(infosize); + + return 0; +} diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h new file mode 100644 index 00000000000..e6b0a69acbd --- /dev/null +++ b/fs/jffs2/summary.h @@ -0,0 +1,183 @@ +/* + * JFFS2 -- Journalling Flash File System, Version 2. + * + * Copyright (C) 2004 Ferenc Havasi , + * Zoltan Sogor , + * Patrik Kluba , + * University of Szeged, Hungary + * + * For licensing information, see the file 'LICENCE' in this directory. + * + * $Id: summary.h,v 1.1 2005/09/07 08:34:54 havasi Exp $ + * + */ + +#ifndef JFFS2_SUMMARY_H +#define JFFS2_SUMMARY_H + +#include +#include + +#define DIRTY_SPACE(x) do { typeof(x) _x = (x); \ + c->free_size -= _x; c->dirty_size += _x; \ + jeb->free_size -= _x ; jeb->dirty_size += _x; \ + }while(0) +#define USED_SPACE(x) do { typeof(x) _x = (x); \ + c->free_size -= _x; c->used_size += _x; \ + jeb->free_size -= _x ; jeb->used_size += _x; \ + }while(0) +#define WASTED_SPACE(x) do { typeof(x) _x = (x); \ + c->free_size -= _x; c->wasted_size += _x; \ + jeb->free_size -= _x ; jeb->wasted_size += _x; \ + }while(0) +#define UNCHECKED_SPACE(x) do { typeof(x) _x = (x); \ + c->free_size -= _x; c->unchecked_size += _x; \ + jeb->free_size -= _x ; jeb->unchecked_size += _x; \ + }while(0) + +#define BLK_STATE_ALLFF 0 +#define BLK_STATE_CLEAN 1 +#define BLK_STATE_PARTDIRTY 2 +#define BLK_STATE_CLEANMARKER 3 +#define BLK_STATE_ALLDIRTY 4 +#define BLK_STATE_BADBLOCK 5 + +#define JFFS2_SUMMARY_NOSUM_SIZE 0xffffffff +#define JFFS2_SUMMARY_INODE_SIZE (sizeof(struct jffs2_sum_inode_flash)) +#define JFFS2_SUMMARY_DIRENT_SIZE(x) (sizeof(struct jffs2_sum_dirent_flash) + (x)) + +/* Summary structures used on flash */ + +struct jffs2_sum_unknown_flash +{ + jint16_t nodetype; /* node type */ +}; + +struct jffs2_sum_inode_flash +{ + jint16_t nodetype; /* node type */ + jint32_t inode; /* inode number */ + jint32_t version; /* inode version */ + jint32_t offset; /* offset on jeb */ + jint32_t totlen; /* record length */ +} __attribute__((packed)); + +struct jffs2_sum_dirent_flash +{ + jint16_t nodetype; /* == JFFS_NODETYPE_DIRENT */ + jint32_t totlen; /* record length */ + jint32_t offset; /* offset on jeb */ + jint32_t pino; /* parent inode */ + jint32_t version; /* dirent version */ + jint32_t ino; /* == zero for unlink */ + uint8_t nsize; /* dirent name size */ + uint8_t type; /* dirent type */ + uint8_t name[0]; /* dirent name */ +} __attribute__((packed)); + +union jffs2_sum_flash +{ + struct jffs2_sum_unknown_flash u; + struct jffs2_sum_inode_flash i; + struct jffs2_sum_dirent_flash d; +}; + +/* Summary structures used in the memory */ + +struct jffs2_sum_unknown_mem +{ + union jffs2_sum_mem *next; + jint16_t nodetype; /* node type */ +}; + +struct jffs2_sum_inode_mem +{ + union jffs2_sum_mem *next; + jint16_t nodetype; /* node type */ + jint32_t inode; /* inode number */ + jint32_t version; /* inode version */ + jint32_t offset; /* offset on jeb */ + jint32_t totlen; /* record length */ +} __attribute__((packed)); + +struct jffs2_sum_dirent_mem +{ + union jffs2_sum_mem *next; + jint16_t nodetype; /* == JFFS_NODETYPE_DIRENT */ + jint32_t totlen; /* record length */ + jint32_t offset; /* ofset on jeb */ + jint32_t pino; /* parent inode */ + jint32_t version; /* dirent version */ + jint32_t ino; /* == zero for unlink */ + uint8_t nsize; /* dirent name size */ + uint8_t type; /* dirent type */ + uint8_t name[0]; /* dirent name */ +} __attribute__((packed)); + +union jffs2_sum_mem +{ + struct jffs2_sum_unknown_mem u; + struct jffs2_sum_inode_mem i; + struct jffs2_sum_dirent_mem d; +}; + +/* Summary related information stored in superblock */ + +struct jffs2_summary +{ + uint32_t sum_size; /* collected summary information for nextblock */ + uint32_t sum_num; + uint32_t sum_padded; + union jffs2_sum_mem *sum_list_head; + union jffs2_sum_mem *sum_list_tail; + + jint32_t *sum_buf; /* buffer for writing out summary */ +}; + +/* Summary marker is stored at the end of every sumarized erase block */ + +struct jffs2_sum_marker +{ + jint32_t offset; /* offset of the summary node in the jeb */ + jint32_t magic; /* == JFFS2_SUM_MAGIC */ +}; + +#define JFFS2_SUMMARY_FRAME_SIZE (sizeof(struct jffs2_summary_node) + sizeof(struct jffs2_sum_marker)) + +#ifdef CONFIG_JFFS2_SUMMARY /* SUMMARY SUPPORT ENABLED */ + +#define jffs2_sum_active() (1) +int jffs2_sum_init(struct jffs2_sb_info *c); +void jffs2_sum_exit(struct jffs2_sb_info *c); +void jffs2_sum_disable_collecting(struct jffs2_summary *s); +int jffs2_sum_is_disabled(struct jffs2_summary *s); +void jffs2_sum_reset_collected(struct jffs2_summary *s); +void jffs2_sum_move_collected(struct jffs2_sb_info *c, struct jffs2_summary *s); +int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs, + unsigned long count, uint32_t to); +int jffs2_sum_write_sumnode(struct jffs2_sb_info *c); +int jffs2_sum_add_padding_mem(struct jffs2_summary *s, uint32_t size); +int jffs2_sum_add_inode_mem(struct jffs2_summary *s, struct jffs2_raw_inode *ri, uint32_t ofs); +int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *rd, uint32_t ofs); +int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, + uint32_t ofs, uint32_t *pseudo_random); + +#else /* SUMMARY DISABLED */ + +#define jffs2_sum_active() (0) +#define jffs2_sum_init(a) (0) +#define jffs2_sum_exit(a) +#define jffs2_sum_disable_collecting(a) +#define jffs2_sum_is_disabled(a) (0) +#define jffs2_sum_reset_collected(a) +#define jffs2_sum_add_kvec(a,b,c,d) (0) +#define jffs2_sum_move_collected(a,b) +#define jffs2_sum_write_sumnode(a) (0) +#define jffs2_sum_add_padding_mem(a,b) +#define jffs2_sum_add_inode_mem(a,b,c) +#define jffs2_sum_add_dirent_mem(a,b,c) +#define jffs2_sum_scan_sumnode(a,b,c,d) (0) + +#endif /* CONFIG_JFFS2_SUMMARY */ + +#endif /* JFFS2_SUMMARY_H */ diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 58496a03a1d..99028af3f69 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: super.c,v 1.108 2005/08/31 13:51:00 havasi Exp $ + * $Id: super.c,v 1.109 2005/09/07 08:34:55 havasi Exp $ * */ @@ -282,6 +282,9 @@ static void jffs2_put_super (struct super_block *sb) down(&c->alloc_sem); jffs2_flush_wbuf_pad(c); up(&c->alloc_sem); + + jffs2_sum_exit(c); + jffs2_free_ino_caches(c); jffs2_free_raw_node_refs(c); if (jffs2_blocks_use_vmalloc(c)) @@ -320,6 +323,9 @@ static int __init init_jffs2_fs(void) printk(KERN_INFO "JFFS2 version 2.2." #ifdef CONFIG_JFFS2_FS_WRITEBUFFER " (NAND)" +#endif +#ifdef CONFIG_JFFS2_SUMMARY + " (SUMMARY) " #endif " (C) 2001-2003 Red Hat, Inc.\n"); diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 8c06d3a2b17..86860dbc670 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -9,7 +9,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: wbuf.c,v 1.97 2005/08/06 04:51:30 nico Exp $ + * $Id: wbuf.c,v 1.98 2005/09/07 08:34:55 havasi Exp $ * */ @@ -265,7 +265,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) /* ... and get an allocation of space from a shiny new block instead */ - ret = jffs2_reserve_space_gc(c, end-start, &ofs, &len); + ret = jffs2_reserve_space_gc(c, end-start, &ofs, &len, JFFS2_SUMMARY_NOSUM_SIZE); if (ret) { printk(KERN_WARNING "Failed to allocate space for wbuf recovery. Data loss ensues.\n"); kfree(buf); @@ -836,6 +836,12 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig alldone: *retlen = donelen; + if (jffs2_sum_active()) { + int res = jffs2_sum_add_kvec(c, invecs, count, (uint32_t) to); + if (res) + return res; + } + if (c->wbuf_len && ino) jffs2_wbuf_dirties_inode(c, ino); @@ -855,7 +861,7 @@ int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *r struct kvec vecs[1]; if (!jffs2_is_writebuffered(c)) - return c->mtd->write(c->mtd, ofs, len, retlen, buf); + return jffs2_flash_direct_write(c, ofs, len, retlen, buf); vecs[0].iov_base = (unsigned char *) buf; vecs[0].iov_len = len; diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index 0a194759bbb..ea411518d80 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: write.c,v 1.95 2005/08/17 13:46:23 dedekind Exp $ + * $Id: write.c,v 1.96 2005/09/07 08:34:55 havasi Exp $ * */ @@ -153,13 +153,15 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 jffs2_dbg_acct_paranoia_check(c, jeb); if (alloc_mode == ALLOC_GC) { - ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &flash_ofs, &dummy); + ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &flash_ofs, + &dummy, JFFS2_SUMMARY_INODE_SIZE); } else { /* Locking pain */ up(&f->sem); jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &flash_ofs, &dummy, alloc_mode); + ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &flash_ofs, + &dummy, alloc_mode, JFFS2_SUMMARY_INODE_SIZE); down(&f->sem); } @@ -299,13 +301,15 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff jffs2_dbg_acct_paranoia_check(c, jeb); if (alloc_mode == ALLOC_GC) { - ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &flash_ofs, &dummy); + ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &flash_ofs, + &dummy, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); } else { /* Locking pain */ up(&f->sem); jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &flash_ofs, &dummy, alloc_mode); + ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &flash_ofs, + &dummy, alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); down(&f->sem); } @@ -362,7 +366,8 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, retry: D2(printk(KERN_DEBUG "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", writelen, offset)); - ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, + &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) { D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret)); break; @@ -449,7 +454,8 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str /* Try to reserve enough space for both node and dirent. * Just the node will do for now, though */ - ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL, + JFFS2_SUMMARY_INODE_SIZE); D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen)); if (ret) { up(&f->sem); @@ -478,7 +484,8 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str up(&f->sem); jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { /* Eep. */ @@ -549,7 +556,8 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, if (!rd) return -ENOMEM; - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_DELETION); + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, + ALLOC_DELETION, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { jffs2_free_raw_dirent(rd); return ret; @@ -658,7 +666,8 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint if (!rd) return -ENOMEM; - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { jffs2_free_raw_dirent(rd); return ret; diff --git a/fs/jffs2/writev.c b/fs/jffs2/writev.c index f079f838856..6d8c27c5e72 100644 --- a/fs/jffs2/writev.c +++ b/fs/jffs2/writev.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: writev.c,v 1.6 2004/11/16 20:36:12 dwmw2 Exp $ + * $Id: writev.c,v 1.7 2005/09/07 08:34:55 havasi Exp $ * */ @@ -44,7 +44,37 @@ int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs, { if (c->mtd->writev) return c->mtd->writev(c->mtd, vecs, count, to, retlen); - else + else { + if (jffs2_sum_active()) { + int res; + + res = jffs2_sum_add_kvec(c, vecs, count, (uint32_t) to); + if (res) { + return res; + } + } + return mtd_fake_writev(c->mtd, vecs, count, to, retlen); + } } +int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, + size_t *retlen, const u_char *buf) +{ + int ret; + ret = c->mtd->write(c->mtd, ofs, len, retlen, buf); + + if (jffs2_sum_active()) { + struct kvec vecs[1]; + int res; + + vecs[0].iov_base = (unsigned char *) buf; + vecs[0].iov_len = len; + + res = jffs2_sum_add_kvec(c, vecs, 1, (uint32_t) ofs); + if (res) { + return res; + } + } + return ret; +} diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h index a66d0a8b70e..acb51a3669a 100644 --- a/include/linux/jffs2.h +++ b/include/linux/jffs2.h @@ -8,7 +8,7 @@ * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * - * $Id: jffs2.h,v 1.36 2005/07/26 13:19:36 havasi Exp $ + * $Id: jffs2.h,v 1.37 2005/09/07 08:34:55 havasi Exp $ * */ @@ -28,6 +28,9 @@ #define JFFS2_EMPTY_BITMASK 0xffff #define JFFS2_DIRTY_BITMASK 0x0000 +/* Summary node MAGIC marker */ +#define JFFS2_SUM_MAGIC 0x02851885 + /* We only allow a single char for length, and 0xFF is empty flash so we don't want it confused with a real length. Hence max 254. */ @@ -60,6 +63,8 @@ #define JFFS2_NODETYPE_CLEANMARKER (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3) #define JFFS2_NODETYPE_PADDING (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 4) +#define JFFS2_NODETYPE_SUMMARY (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 6) + // Maybe later... //#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3) //#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4) @@ -146,10 +151,24 @@ struct jffs2_raw_inode uint8_t data[0]; } __attribute__((packed)); +struct jffs2_summary_node{ + jint16_t magic; + jint16_t nodetype; /* = JFFS2_NODETYPE_INODE_SUM */ + jint32_t totlen; + jint32_t hdr_crc; + jint32_t sum_num; /* number of sum entries*/ + jint32_t cln_mkr; /* clean marker size, 0 = no cleanmarker */ + jint32_t padded; /* sum of the size of padding nodes */ + jint32_t sum_crc; /* summary information crc */ + jint32_t node_crc; /* node crc */ + jint32_t sum[0]; /* inode summary info */ +} __attribute__((packed)); + union jffs2_node_union { struct jffs2_raw_inode i; struct jffs2_raw_dirent d; struct jffs2_unknown_node u; + struct jffs2_summary_node s; }; #endif /* __LINUX_JFFS2_H__ */ diff --git a/include/linux/jffs2_fs_sb.h b/include/linux/jffs2_fs_sb.h index 1e21546622d..5087612ed9a 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.52 2005/05/19 16:12:17 gleixner Exp $ */ +/* $Id: jffs2_fs_sb.h,v 1.53 2005/09/07 08:34:56 havasi Exp $ */ #ifndef _JFFS2_FS_SB #define _JFFS2_FS_SB @@ -112,6 +112,8 @@ struct jffs2_sb_info { uint32_t fsdata_len; #endif + struct jffs2_summary *summary; /* Summary information */ + /* OS-private pointer for getting back to master superblock info */ void *os_priv; }; -- cgit v1.2.3 From 6dfca87806eb94c1033b01e4f7a48363b890ec79 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 6 Nov 2005 21:31:01 +0100 Subject: I am the new monkey. Signed-off-by: Adrian Bunk --- MAINTAINERS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index f08a1434b21..d5ed883c591 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2450,10 +2450,10 @@ L: linux-kernel@vger.kernel.org S: Maintained TRIVIAL PATCHES -P: Rusty Russell -M: trivial@rustcorp.com.au +P: Adrian Bunk +M: trivial@kernel.org L: linux-kernel@vger.kernel.org -W: http://www.kernel.org/pub/linux/kernel/people/rusty/trivial/ +W: http://www.kernel.org/pub/linux/kernel/people/bunk/trivial/ S: Maintained TMS380 TOKEN-RING NETWORK DRIVER -- cgit v1.2.3 From c617e842482eb513070cbf233766099cff2a1663 Mon Sep 17 00:00:00 2001 From: Ferenc Havasi Date: Wed, 7 Sep 2005 12:22:01 +0100 Subject: [JFFS2] Return real jffs2_sum_init() error code Signed-off-by: Ferenc Havasi Signed-off-by: Thomas Gleixner --- fs/jffs2/build.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index f4a47a3b2a0..f2cf562ebd2 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: build.c,v 1.78 2005/09/07 08:34:54 havasi Exp $ + * $Id: build.c,v 1.79 2005/09/07 11:21:57 havasi Exp $ * */ @@ -313,6 +313,7 @@ static void jffs2_calc_trigger_levels(struct jffs2_sb_info *c) int jffs2_do_mount_fs(struct jffs2_sb_info *c) { + int ret; int i; c->free_size = c->flash_size; @@ -352,8 +353,9 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) c->highest_ino = 1; c->summary = NULL; - if (jffs2_sum_init(c)) - return -ENOMEM; + ret = jffs2_sum_init(c); + if (ret) + return ret; if (jffs2_build_filesystem(c)) { D1(printk(KERN_DEBUG "build_fs failed\n")); -- cgit v1.2.3 From 65163fd73c65e4c61437c28ac4ef9f3c5ba16a80 Mon Sep 17 00:00:00 2001 From: Michal Wronski Date: Sun, 6 Nov 2005 21:31:54 +0100 Subject: Update Michal Wronski contact info --- CREDITS | 6 ++---- ipc/mqueue.c | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/CREDITS b/CREDITS index 5b1edf3a38a..7fb4c73e022 100644 --- a/CREDITS +++ b/CREDITS @@ -3642,11 +3642,9 @@ S: Beaverton, OR 97005 S: USA N: Michal Wronski -E: wrona@mat.uni.torun.pl -W: http://www.mat.uni.torun.pl/~wrona +E: Michal.Wronski@motorola.com D: POSIX message queues fs (with K. Benedyczak) -S: ul. Teczowa 23/12 -S: 80-680 Gdansk-Sobieszewo +S: Krakow S: Poland N: Frank Xia diff --git a/ipc/mqueue.c b/ipc/mqueue.c index a0f18c9cc89..c8943b53d8e 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -2,7 +2,7 @@ * POSIX message queues filesystem for Linux. * * Copyright (C) 2003,2004 Krzysztof Benedyczak (golbi@mat.uni.torun.pl) - * Michal Wronski (wrona@mat.uni.torun.pl) + * Michal Wronski (Michal.Wronski@motorola.com) * * Spinlocks: Mohamed Abbas (abbas.mohamed@intel.com) * Lockless receive & send, fd based notify: -- cgit v1.2.3 From e4c212efbdd4e286bc3defcddbab2c1e57ec75c3 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Thu, 8 Sep 2005 11:32:23 +0100 Subject: [MTD] maps/ixp4xx: remove platform specific bits - Intel chip driver has a reboot notifier so no need to reset the chip here. - Don't play with chip selects (platform code should do this if necessary). Signed-off-by: David Vrabel Signed-off-by: Thomas Gleixner --- drivers/mtd/maps/ixp4xx.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c index 733a9297a56..58b477043f2 100644 --- a/drivers/mtd/maps/ixp4xx.c +++ b/drivers/mtd/maps/ixp4xx.c @@ -1,5 +1,5 @@ /* - * $Id: ixp4xx.c,v 1.7 2004/11/04 13:24:15 gleixner Exp $ + * $Id: ixp4xx.c,v 1.8 2005/09/08 10:32:20 dvrabel Exp $ * * drivers/mtd/maps/ixp4xx.c * @@ -111,12 +111,6 @@ static int ixp4xx_flash_remove(struct device *_dev) if(!info) return 0; - /* - * This is required for a soft reboot to work. - */ - d.x[0] = 0xff; - ixp4xx_write16(&info->map, d, 0x55 * 0x2); - if (info->mtd) { del_mtd_partitions(info->mtd); map_destroy(info->mtd); @@ -135,9 +129,6 @@ static int ixp4xx_flash_remove(struct device *_dev) if (plat->exit) plat->exit(); - /* Disable flash write */ - *IXP4XX_EXP_CS0 &= ~IXP4XX_FLASH_WRITABLE; - return 0; } @@ -166,12 +157,6 @@ static int ixp4xx_flash_probe(struct device *_dev) dev_set_drvdata(&dev->dev, info); - /* - * Enable flash write - * TODO: Move this out to board specific code - */ - *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; - /* * Tell the MTD layer we're not 1:1 mapped so that it does * not attempt to do a direct access on us. -- cgit v1.2.3 From 68ee4b1c50847743393b01847a640ebf1002789b Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Fri, 9 Sep 2005 07:39:50 +0100 Subject: [MTD] OneNAND: Add generic platform driver Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/Kconfig | 7 ++ drivers/mtd/onenand/Makefile | 1 + drivers/mtd/onenand/generic.c | 147 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 155 insertions(+) create mode 100644 drivers/mtd/onenand/generic.c diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig index 08a32a53a37..666ad321773 100644 --- a/drivers/mtd/onenand/Kconfig +++ b/drivers/mtd/onenand/Kconfig @@ -23,6 +23,13 @@ config MTD_ONENAND_VERIFY_WRITE device thinks the write was successful, a bit could have been flipped accidentaly due to device wear or something else. +config MTD_ONENAND_GENERIC + tristate "OneNAND Flash device on generic board" + depends on MTD_ONENAND + help + Support for OneNAND flash on generic board. Using device driver + framework, now all most platfrom are support. + config MTD_ONENAND_OMAP tristate "OneNAND Flash device on OMAP board" depends on ARCH_OMAP && MTD_ONENAND diff --git a/drivers/mtd/onenand/Makefile b/drivers/mtd/onenand/Makefile index 932301a888e..e2a96549fcd 100644 --- a/drivers/mtd/onenand/Makefile +++ b/drivers/mtd/onenand/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_MTD_ONENAND) += onenand.o # Board specific. +obj-$(CONFIG_MTD_ONENAND_GENERIC) += generic.o obj-$(CONFIG_MTD_ONENAND_OMAP) += omap-onenand.o # Simulator diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c new file mode 100644 index 00000000000..48cce431f89 --- /dev/null +++ b/drivers/mtd/onenand/generic.c @@ -0,0 +1,147 @@ +/* + * linux/drivers/mtd/onenand/generic.c + * + * Copyright (c) 2005 Samsung Electronics + * Kyungmin Park + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Overview: + * This is a device driver for the OneNAND flash for generic boards. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define DRIVER_NAME "onenand" + + +#ifdef CONFIG_MTD_PARTITIONS +static const char *part_probes[] = { "cmdlinepart", NULL, }; +#endif + +struct onenand_info { + struct mtd_info mtd; + struct mtd_partition *parts; + struct onenand_chip onenand; +}; + +static int __devinit generic_onenand_probe(struct device *dev) +{ + struct onenand_info *info; + struct platform_device *pdev = to_platform_device(dev); + struct onenand_platform_data *pdata = pdev->dev.platform_data; + struct resource *res = pdev->resource; + unsigned long size = res->end - res->start + 1; + int err; + + info = kmalloc(sizeof(struct onenand_info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + memset(info, 0, sizeof(struct onenand_info)); + + if (!request_mem_region(res->start, size, dev->driver->name)) { + err = -EBUSY; + goto out_free_info; + } + + info->onenand.base = ioremap(res->start, size); + if (!info->onenand.base) { + err = -ENOMEM; + goto out_release_mem_region; + } + + info->onenand.mmcontrol = pdata->mmcontrol; + + info->mtd.name = pdev->dev.bus_id; + info->mtd.priv = &info->onenand; + info->mtd.owner = THIS_MODULE; + + if (onenand_scan(&info->mtd, 1)) { + err = -ENXIO; + goto out_iounmap; + } + +#ifdef CONFIG_MTD_PARTITIONS + err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0); + if (err > 0) + add_mtd_partitions(&info->mtd, info->parts, err); + else if (err < 0 && pdata->parts) + add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts); + else +#endif + err = add_mtd_device(&info->mtd); + + dev_set_drvdata(&pdev->dev, info); + + return 0; + +out_iounmap: + iounmap(info->onenand.base); +out_release_mem_region: + release_mem_region(res->start, size); +out_free_info: + kfree(info); + + return err; +} + +static int __devexit generic_onenand_remove(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct onenand_info *info = dev_get_drvdata(&pdev->dev); + struct resource *res = pdev->resource; + unsigned long size = res->end - res->start + 1; + + dev_set_drvdata(&pdev->dev, NULL); + + if (info) { + if (info->parts) + del_mtd_partitions(&info->mtd); + else + del_mtd_device(&info->mtd); + + onenand_release(&info->mtd); + release_mem_region(res->start, size); + iounmap(info->onenand.base); + kfree(info); + } + + return 0; +} + +static struct device_driver generic_onenand_driver = { + .name = DRIVER_NAME, + .bus = &platform_bus_type, + .probe = generic_onenand_probe, + .remove = __devexit_p(generic_onenand_remove), +}; + +MODULE_ALIAS(DRIVER_NAME); + +static int __init generic_onenand_init(void) +{ + return driver_register(&generic_onenand_driver); +} + +static void __exit generic_onenand_exit(void) +{ + driver_unregister(&generic_onenand_driver); +} + +module_init(generic_onenand_init); +module_exit(generic_onenand_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Kyungmin Park "); +MODULE_DESCRIPTION("Glue layer for OneNAND flash on generic boards"); -- cgit v1.2.3 From 1b01d9798d58bf28a40fede184482ebf39e63335 Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Fri, 9 Sep 2005 07:43:16 +0100 Subject: OneNAND: Remove OMAP platform driver Now we can use the generic platform driver Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/Kconfig | 6 -- drivers/mtd/onenand/Makefile | 1 - drivers/mtd/onenand/omap-onenand.c | 147 ------------------------------------- 3 files changed, 154 deletions(-) delete mode 100644 drivers/mtd/onenand/omap-onenand.c diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig index 666ad321773..fa5045c9d6e 100644 --- a/drivers/mtd/onenand/Kconfig +++ b/drivers/mtd/onenand/Kconfig @@ -30,12 +30,6 @@ config MTD_ONENAND_GENERIC Support for OneNAND flash on generic board. Using device driver framework, now all most platfrom are support. -config MTD_ONENAND_OMAP - tristate "OneNAND Flash device on OMAP board" - depends on ARCH_OMAP && MTD_ONENAND - help - Support for OneNAND flash on TI OMAP board. - config MTD_ONENAND_SYNC_READ bool "OneNAND Sync. Burst Read Support" depends on ARCH_OMAP diff --git a/drivers/mtd/onenand/Makefile b/drivers/mtd/onenand/Makefile index e2a96549fcd..4d2eacfd7e1 100644 --- a/drivers/mtd/onenand/Makefile +++ b/drivers/mtd/onenand/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_MTD_ONENAND) += onenand.o # Board specific. obj-$(CONFIG_MTD_ONENAND_GENERIC) += generic.o -obj-$(CONFIG_MTD_ONENAND_OMAP) += omap-onenand.o # Simulator obj-$(CONFIG_MTD_ONENAND_SIM) += onenand_sim.o diff --git a/drivers/mtd/onenand/omap-onenand.c b/drivers/mtd/onenand/omap-onenand.c deleted file mode 100644 index 57e69f184d3..00000000000 --- a/drivers/mtd/onenand/omap-onenand.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * linux/drivers/mtd/onenand/omap-onenand.c - * - * Copyright (c) 2005 Samsung Electronics - * Kyungmin Park - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Overview: - * This is a device driver for the OneNAND flash for OMAP boards. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#define DRIVER_NAME "onenand" - - -#ifdef CONFIG_MTD_PARTITIONS -static const char *part_probes[] = { "cmdlinepart", NULL, }; -#endif - -struct omap_onenand_info { - struct mtd_info mtd; - struct mtd_partition *parts; - struct onenand_chip onenand; -}; - -static int __devinit omap_onenand_probe(struct device *dev) -{ - struct omap_onenand_info *info; - struct platform_device *pdev = to_platform_device(dev); - struct onenand_platform_data *pdata = pdev->dev.platform_data; - struct resource *res = pdev->resource; - unsigned long size = res->end - res->start + 1; - int err; - - info = kmalloc(sizeof(struct omap_onenand_info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - memset(info, 0, sizeof(struct omap_onenand_info)); - - if (!request_mem_region(res->start, size, dev->driver->name)) { - err = -EBUSY; - goto out_free_info; - } - - info->onenand.base = ioremap(res->start, size); - if (!info->onenand.base) { - err = -ENOMEM; - goto out_release_mem_region; - } - - info->onenand.mmcontrol = pdata->mmcontrol; - - info->mtd.name = pdev->dev.bus_id; - info->mtd.priv = &info->onenand; - info->mtd.owner = THIS_MODULE; - - if (onenand_scan(&info->mtd, 1)) { - err = -ENXIO; - goto out_iounmap; - } - -#ifdef CONFIG_MTD_PARTITIONS - err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0); - if (err > 0) - add_mtd_partitions(&info->mtd, info->parts, err); - else if (err < 0 && pdata->parts) - add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts); - else -#endif - err = add_mtd_device(&info->mtd); - - dev_set_drvdata(&pdev->dev, info); - - return 0; - -out_iounmap: - iounmap(info->onenand.base); -out_release_mem_region: - release_mem_region(res->start, size); -out_free_info: - kfree(info); - - return err; -} - -static int __devexit omap_onenand_remove(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct omap_onenand_info *info = dev_get_drvdata(&pdev->dev); - struct resource *res = pdev->resource; - unsigned long size = res->end - res->start + 1; - - dev_set_drvdata(&pdev->dev, NULL); - - if (info) { - if (info->parts) - del_mtd_partitions(&info->mtd); - else - del_mtd_device(&info->mtd); - - onenand_release(&info->mtd); - release_mem_region(res->start, size); - iounmap(info->onenand.base); - kfree(info); - } - - return 0; -} - -static struct device_driver omap_onenand_driver = { - .name = DRIVER_NAME, - .bus = &platform_bus_type, - .probe = omap_onenand_probe, - .remove = __devexit_p(omap_onenand_remove), -}; - -MODULE_ALIAS(DRIVER_NAME); - -static int __init omap_onenand_init(void) -{ - return driver_register(&omap_onenand_driver); -} - -static void __exit omap_onenand_exit(void) -{ - driver_unregister(&omap_onenand_driver); -} - -module_init(omap_onenand_init); -module_exit(omap_onenand_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Kyungmin Park "); -MODULE_DESCRIPTION("Glue layer for OneNAND flash on OMAP boards"); -- cgit v1.2.3 From 8acff5e93488e4da653097bd5e50662ee0985867 Mon Sep 17 00:00:00 2001 From: Ferenc Havasi Date: Fri, 9 Sep 2005 16:12:01 +0100 Subject: [JFFS2] Call summary collector for all mtd devices with writev support Do the summary collection in the right place. If the device was not writebuffered but had c->mtd->writev function (e.g. blkmtd) the summary collector function was not called. Signed-off-by: Ferenc Havasi Signed-off-by: Thomas Gleixner --- fs/jffs2/writev.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/fs/jffs2/writev.c b/fs/jffs2/writev.c index 6d8c27c5e72..c638ae1008d 100644 --- a/fs/jffs2/writev.c +++ b/fs/jffs2/writev.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: writev.c,v 1.7 2005/09/07 08:34:55 havasi Exp $ + * $Id: writev.c,v 1.8 2005/09/09 15:11:58 havasi Exp $ * */ @@ -42,18 +42,19 @@ static inline int mtd_fake_writev(struct mtd_info *mtd, const struct kvec *vecs, int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen) { - if (c->mtd->writev) - return c->mtd->writev(c->mtd, vecs, count, to, retlen); - else { + if (!jffs2_is_writebuffered(c)) { if (jffs2_sum_active()) { int res; - res = jffs2_sum_add_kvec(c, vecs, count, (uint32_t) to); if (res) { return res; } } + } + if (c->mtd->writev) + return c->mtd->writev(c->mtd, vecs, count, to, retlen); + else { return mtd_fake_writev(c->mtd, vecs, count, to, retlen); } } -- cgit v1.2.3 From 81e39cf0297c7f32fb8869af9ae199130208ae6f Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Wed, 14 Sep 2005 17:57:35 +0100 Subject: [JFFS2] Debug message format clean up Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/debug.c | 248 +++++++++++++++++++++++-------------------------------- fs/jffs2/debug.h | 31 ++++--- 2 files changed, 120 insertions(+), 159 deletions(-) diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c index 9b776b5a760..28983501bce 100644 --- a/fs/jffs2/debug.c +++ b/fs/jffs2/debug.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.c,v 1.9 2005/08/05 10:42:24 dedekind Exp $ + * $Id: debug.c,v 1.10 2005/09/14 16:57:32 dedekind Exp $ * */ #include @@ -28,8 +28,8 @@ __jffs2_dbg_acct_sanity_check_nolock(struct jffs2_sb_info *c, jeb->free_size + jeb->wasted_size + jeb->unchecked_size != c->sector_size)) { JFFS2_ERROR("eeep, space accounting for block at 0x%08x is screwed.\n", jeb->offset); - JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + wasted %#08x + unchecked " - "%#08x != total %#08x.\n", jeb->free_size, jeb->dirty_size, jeb->used_size, + JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + wasted %#08x + unchecked %#08x != total %#08x.\n", + jeb->free_size, jeb->dirty_size, jeb->used_size, jeb->wasted_size, jeb->unchecked_size, c->sector_size); BUG(); } @@ -37,8 +37,7 @@ __jffs2_dbg_acct_sanity_check_nolock(struct jffs2_sb_info *c, if (unlikely(c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size + c->wasted_size + c->unchecked_size != c->flash_size)) { JFFS2_ERROR("eeep, space accounting superblock info is screwed.\n"); - JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + erasing %#08x + bad %#08x + " - "wasted %#08x + unchecked %#08x != total %#08x.\n", + JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + erasing %#08x + bad %#08x + wasted %#08x + unchecked %#08x != total %#08x.\n", c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, c->wasted_size, c->unchecked_size, c->flash_size); BUG(); @@ -83,7 +82,7 @@ __jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f) if (ref_flags(fn->raw) == REF_PRISTINE) { if (fn->frags > 1) { JFFS2_ERROR("REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2.\n", - ref_offset(fn->raw), fn->frags); + ref_offset(fn->raw), fn->frags); bitched = 1; } @@ -94,16 +93,15 @@ __jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f) to tell a hole node. */ if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag) && frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) { - JFFS2_ERROR("REF_PRISTINE node at 0x%08x had a previous non-hole frag " - "in the same page. Tell dwmw2.\n", ref_offset(fn->raw)); + JFFS2_ERROR("REF_PRISTINE node at 0x%08x had a previous non-hole frag in the same page. Tell dwmw2.\n", + ref_offset(fn->raw)); bitched = 1; } if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag) && frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) { - JFFS2_ERROR("REF_PRISTINE node at 0x%08x (%08x-%08x) had a following " - "non-hole frag in the same page. Tell dwmw2.\n", - ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size); + JFFS2_ERROR("REF_PRISTINE node at 0x%08x (%08x-%08x) had a following non-hole frag in the same page. Tell dwmw2.\n", + ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size); bitched = 1; } } @@ -145,8 +143,8 @@ __jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c, ret = 1; if (ret) { - JFFS2_ERROR("argh, about to write node to %#08x on flash, but there are data " - "already there. The first corrupted byte is at %#08x offset.\n", ofs, ofs + i); + JFFS2_ERROR("argh, about to write node to %#08x on flash, but there are data already there. The first corrupted byte is at %#08x offset.\n", + ofs, ofs + i); __jffs2_dbg_dump_buffer(buf, len, ofs); kfree(buf); BUG(); @@ -194,8 +192,7 @@ __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c, my_dirty_size += totlen; if ((!ref2->next_phys) != (ref2 == jeb->last_node)) { - JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), " - "last_node is at %#08x (mem %p).\n", + JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), last_node is at %#08x (mem %p).\n", ref_offset(ref2), ref2, ref_offset(ref2->next_phys), ref2->next_phys, ref_offset(jeb->last_node), jeb->last_node); goto error; @@ -263,13 +260,13 @@ __jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref; int i = 0; - JFFS2_DEBUG("Dump node_refs of the eraseblock %#08x\n", jeb->offset); + printk(JFFS2_DBG_MSG_PREFIX " Dump node_refs of the eraseblock %#08x\n", jeb->offset); if (!jeb->first_node) { - JFFS2_DEBUG("no nodes in the eraseblock %#08x\n", jeb->offset); + printk(JFFS2_DBG_MSG_PREFIX " no nodes in the eraseblock %#08x\n", jeb->offset); return; } - printk(JFFS2_DBG_LVL); + printk(JFFS2_DBG); for (ref = jeb->first_node; ; ref = ref->next_phys) { printk("%#08x(%#x)", ref_offset(ref), ref->__totlen); if (ref->next_phys) @@ -278,7 +275,7 @@ __jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c, break; if (++i == 4) { i = 0; - printk("\n" JFFS2_DBG_LVL); + printk("\n" JFFS2_DBG); } } printk("\n"); @@ -301,14 +298,14 @@ __jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb) if (!jeb) return; - JFFS2_DEBUG("dump space accounting for the eraseblock at %#08x:\n", + printk(JFFS2_DBG_MSG_PREFIX " dump space accounting for the eraseblock at %#08x:\n", jeb->offset); - printk(JFFS2_DBG_LVL "used_size: %#08x\n", jeb->used_size); - printk(JFFS2_DBG_LVL "dirty_size: %#08x\n", jeb->dirty_size); - printk(JFFS2_DBG_LVL "wasted_size: %#08x\n", jeb->wasted_size); - printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n", jeb->unchecked_size); - printk(JFFS2_DBG_LVL "free_size: %#08x\n", jeb->free_size); + printk(JFFS2_DBG "used_size: %#08x\n", jeb->used_size); + printk(JFFS2_DBG "dirty_size: %#08x\n", jeb->dirty_size); + printk(JFFS2_DBG "wasted_size: %#08x\n", jeb->wasted_size); + printk(JFFS2_DBG "unchecked_size: %#08x\n", jeb->unchecked_size); + printk(JFFS2_DBG "free_size: %#08x\n", jeb->free_size); } void @@ -322,39 +319,37 @@ __jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c) void __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) { - JFFS2_DEBUG("dump JFFS2 blocks lists:\n"); + printk(JFFS2_DBG_MSG_PREFIX " dump JFFS2 blocks lists:\n"); - printk(JFFS2_DBG_LVL "flash_size: %#08x\n", c->flash_size); - printk(JFFS2_DBG_LVL "used_size: %#08x\n", c->used_size); - printk(JFFS2_DBG_LVL "dirty_size: %#08x\n", c->dirty_size); - printk(JFFS2_DBG_LVL "wasted_size: %#08x\n", c->wasted_size); - printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n", c->unchecked_size); - printk(JFFS2_DBG_LVL "free_size: %#08x\n", c->free_size); - printk(JFFS2_DBG_LVL "erasing_size: %#08x\n", c->erasing_size); - printk(JFFS2_DBG_LVL "bad_size: %#08x\n", c->bad_size); - printk(JFFS2_DBG_LVL "sector_size: %#08x\n", c->sector_size); - printk(JFFS2_DBG_LVL "jffs2_reserved_blocks size: %#08x\n", + printk(JFFS2_DBG "flash_size: %#08x\n", c->flash_size); + printk(JFFS2_DBG "used_size: %#08x\n", c->used_size); + printk(JFFS2_DBG "dirty_size: %#08x\n", c->dirty_size); + printk(JFFS2_DBG "wasted_size: %#08x\n", c->wasted_size); + printk(JFFS2_DBG "unchecked_size: %#08x\n", c->unchecked_size); + printk(JFFS2_DBG "free_size: %#08x\n", c->free_size); + printk(JFFS2_DBG "erasing_size: %#08x\n", c->erasing_size); + printk(JFFS2_DBG "bad_size: %#08x\n", c->bad_size); + printk(JFFS2_DBG "sector_size: %#08x\n", c->sector_size); + printk(JFFS2_DBG "jffs2_reserved_blocks size: %#08x\n", c->sector_size * c->resv_blocks_write); if (c->nextblock) - printk(JFFS2_DBG_LVL "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", + printk(JFFS2_DBG "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->wasted_size, c->nextblock->unchecked_size, c->nextblock->free_size); else - printk(JFFS2_DBG_LVL "nextblock: NULL\n"); + printk(JFFS2_DBG "nextblock: NULL\n"); if (c->gcblock) - printk(JFFS2_DBG_LVL "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", + printk(JFFS2_DBG "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size, c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size); else - printk(JFFS2_DBG_LVL "gcblock: NULL\n"); + printk(JFFS2_DBG "gcblock: NULL\n"); if (list_empty(&c->clean_list)) { - printk(JFFS2_DBG_LVL "clean_list: empty\n"); + printk(JFFS2_DBG "clean_list: empty\n"); } else { struct list_head *this; int numblocks = 0; @@ -365,19 +360,18 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) numblocks ++; dirty += jeb->wasted_size; if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(JFFS2_DBG_LVL "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", + printk(JFFS2_DBG "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); } } - printk (JFFS2_DBG_LVL "Contains %d blocks with total wasted size %u, average wasted size: %u\n", + printk (JFFS2_DBG "Contains %d blocks with total wasted size %u, average wasted size: %u\n", numblocks, dirty, dirty / numblocks); } if (list_empty(&c->very_dirty_list)) { - printk(JFFS2_DBG_LVL "very_dirty_list: empty\n"); + printk(JFFS2_DBG "very_dirty_list: empty\n"); } else { struct list_head *this; int numblocks = 0; @@ -389,19 +383,18 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) numblocks ++; dirty += jeb->dirty_size; if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(JFFS2_DBG_LVL "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", + printk(JFFS2_DBG "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); } } - printk (JFFS2_DBG_LVL "Contains %d blocks with total dirty size %u, average dirty size: %u\n", + printk (JFFS2_DBG "Contains %d blocks with total dirty size %u, average dirty size: %u\n", numblocks, dirty, dirty / numblocks); } if (list_empty(&c->dirty_list)) { - printk(JFFS2_DBG_LVL "dirty_list: empty\n"); + printk(JFFS2_DBG "dirty_list: empty\n"); } else { struct list_head *this; int numblocks = 0; @@ -413,19 +406,18 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) numblocks ++; dirty += jeb->dirty_size; if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(JFFS2_DBG_LVL "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", + printk(JFFS2_DBG "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); } } - printk (JFFS2_DBG_LVL "contains %d blocks with total dirty size %u, average dirty size: %u\n", + printk (JFFS2_DBG "contains %d blocks with total dirty size %u, average dirty size: %u\n", numblocks, dirty, dirty / numblocks); } if (list_empty(&c->erasable_list)) { - printk(JFFS2_DBG_LVL "erasable_list: empty\n"); + printk(JFFS2_DBG "erasable_list: empty\n"); } else { struct list_head *this; @@ -433,8 +425,7 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(JFFS2_DBG_LVL "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", + printk(JFFS2_DBG "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); } @@ -442,7 +433,7 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) } if (list_empty(&c->erasing_list)) { - printk(JFFS2_DBG_LVL "erasing_list: empty\n"); + printk(JFFS2_DBG "erasing_list: empty\n"); } else { struct list_head *this; @@ -450,8 +441,7 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(JFFS2_DBG_LVL "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", + printk(JFFS2_DBG "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); } @@ -459,7 +449,7 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) } if (list_empty(&c->erase_pending_list)) { - printk(JFFS2_DBG_LVL "erase_pending_list: empty\n"); + printk(JFFS2_DBG "erase_pending_list: empty\n"); } else { struct list_head *this; @@ -467,8 +457,7 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(JFFS2_DBG_LVL "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", + printk(JFFS2_DBG "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); } @@ -476,7 +465,7 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) } if (list_empty(&c->erasable_pending_wbuf_list)) { - printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: empty\n"); + printk(JFFS2_DBG "erasable_pending_wbuf_list: empty\n"); } else { struct list_head *this; @@ -484,8 +473,7 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, " - "wasted %#08x, unchecked %#08x, free %#08x)\n", + printk(JFFS2_DBG "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); } @@ -493,7 +481,7 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) } if (list_empty(&c->free_list)) { - printk(JFFS2_DBG_LVL "free_list: empty\n"); + printk(JFFS2_DBG "free_list: empty\n"); } else { struct list_head *this; @@ -501,8 +489,7 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(JFFS2_DBG_LVL "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", + printk(JFFS2_DBG "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); } @@ -510,7 +497,7 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) } if (list_empty(&c->bad_list)) { - printk(JFFS2_DBG_LVL "bad_list: empty\n"); + printk(JFFS2_DBG "bad_list: empty\n"); } else { struct list_head *this; @@ -518,8 +505,7 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(JFFS2_DBG_LVL "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", + printk(JFFS2_DBG "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); } @@ -527,7 +513,7 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) } if (list_empty(&c->bad_used_list)) { - printk(JFFS2_DBG_LVL "bad_used_list: empty\n"); + printk(JFFS2_DBG "bad_used_list: empty\n"); } else { struct list_head *this; @@ -535,8 +521,7 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { - printk(JFFS2_DBG_LVL "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, " - "unchecked %#08x, free %#08x)\n", + printk(JFFS2_DBG "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, jeb->unchecked_size, jeb->free_size); } @@ -559,16 +544,15 @@ __jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f) uint32_t lastofs = 0; int buggy = 0; - JFFS2_DEBUG("dump fragtree of ino #%u\n", f->inocache->ino); + printk(JFFS2_DBG_MSG_PREFIX " dump fragtree of ino #%u\n", f->inocache->ino); while(this) { if (this->node) - printk(JFFS2_DBG_LVL "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), " - "right (%p), parent (%p)\n", + printk(JFFS2_DBG "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), right (%p), parent (%p)\n", this->ofs, this->ofs+this->size, ref_offset(this->node->raw), ref_flags(this->node->raw), this, frag_left(this), frag_right(this), frag_parent(this)); else - printk(JFFS2_DBG_LVL "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n", + printk(JFFS2_DBG "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n", this->ofs, this->ofs+this->size, this, frag_left(this), frag_right(this), frag_parent(this)); if (this->ofs != lastofs) @@ -578,7 +562,7 @@ __jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f) } if (f->metadata) - printk(JFFS2_DBG_LVL "metadata at 0x%08x\n", ref_offset(f->metadata->raw)); + printk(JFFS2_DBG "metadata at 0x%08x\n", ref_offset(f->metadata->raw)); if (buggy) { JFFS2_ERROR("frag tree got a hole in it.\n"); @@ -593,13 +577,13 @@ __jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs) int skip; int i; - JFFS2_DEBUG("dump from offset %#08x to offset %#08x (%x bytes).\n", + printk(JFFS2_DBG_MSG_PREFIX " dump from offset %#08x to offset %#08x (%x bytes).\n", offs, offs + len, len); i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE; offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1); if (skip != 0) - printk(JFFS2_DBG_LVL "%#08x: ", offs); + printk(JFFS2_DBG "%#08x: ", offs); while (skip--) printk(" "); @@ -609,7 +593,7 @@ __jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs) if (i != 0) printk("\n"); offs += JFFS2_BUFDUMP_BYTES_PER_LINE; - printk(JFFS2_DBG_LVL "%0#8x: ", offs); + printk(JFFS2_DBG "%0#8x: ", offs); } printk("%02x ", buf[i]); @@ -632,7 +616,7 @@ __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs) uint32_t crc; int ret; - JFFS2_DEBUG("dump node at offset %#08x.\n", ofs); + printk(JFFS2_DBG_MSG_PREFIX " dump node at offset %#08x.\n", ofs); ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node); if (ret || (retlen != len)) { @@ -641,14 +625,10 @@ __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs) return; } - printk(JFFS2_DBG_LVL "magic:\t%#04x\n", - je16_to_cpu(node.u.magic)); - printk(JFFS2_DBG_LVL "nodetype:\t%#04x\n", - je16_to_cpu(node.u.nodetype)); - printk(JFFS2_DBG_LVL "totlen:\t%#08x\n", - je32_to_cpu(node.u.totlen)); - printk(JFFS2_DBG_LVL "hdr_crc:\t%#08x\n", - je32_to_cpu(node.u.hdr_crc)); + printk(JFFS2_DBG "magic:\t%#04x\n", je16_to_cpu(node.u.magic)); + printk(JFFS2_DBG "nodetype:\t%#04x\n", je16_to_cpu(node.u.nodetype)); + printk(JFFS2_DBG "totlen:\t%#08x\n", je32_to_cpu(node.u.totlen)); + printk(JFFS2_DBG "hdr_crc:\t%#08x\n", je32_to_cpu(node.u.hdr_crc)); crc = crc32(0, &node.u, sizeof(node.u) - 4); if (crc != je32_to_cpu(node.u.hdr_crc)) { @@ -668,41 +648,25 @@ __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs) case JFFS2_NODETYPE_INODE: - printk(JFFS2_DBG_LVL "the node is inode node\n"); - printk(JFFS2_DBG_LVL "ino:\t%#08x\n", - je32_to_cpu(node.i.ino)); - printk(JFFS2_DBG_LVL "version:\t%#08x\n", - je32_to_cpu(node.i.version)); - printk(JFFS2_DBG_LVL "mode:\t%#08x\n", - node.i.mode.m); - printk(JFFS2_DBG_LVL "uid:\t%#04x\n", - je16_to_cpu(node.i.uid)); - printk(JFFS2_DBG_LVL "gid:\t%#04x\n", - je16_to_cpu(node.i.gid)); - printk(JFFS2_DBG_LVL "isize:\t%#08x\n", - je32_to_cpu(node.i.isize)); - printk(JFFS2_DBG_LVL "atime:\t%#08x\n", - je32_to_cpu(node.i.atime)); - printk(JFFS2_DBG_LVL "mtime:\t%#08x\n", - je32_to_cpu(node.i.mtime)); - printk(JFFS2_DBG_LVL "ctime:\t%#08x\n", - je32_to_cpu(node.i.ctime)); - printk(JFFS2_DBG_LVL "offset:\t%#08x\n", - je32_to_cpu(node.i.offset)); - printk(JFFS2_DBG_LVL "csize:\t%#08x\n", - je32_to_cpu(node.i.csize)); - printk(JFFS2_DBG_LVL "dsize:\t%#08x\n", - je32_to_cpu(node.i.dsize)); - printk(JFFS2_DBG_LVL "compr:\t%#02x\n", - node.i.compr); - printk(JFFS2_DBG_LVL "usercompr:\t%#02x\n", - node.i.usercompr); - printk(JFFS2_DBG_LVL "flags:\t%#04x\n", - je16_to_cpu(node.i.flags)); - printk(JFFS2_DBG_LVL "data_crc:\t%#08x\n", - je32_to_cpu(node.i.data_crc)); - printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n", - je32_to_cpu(node.i.node_crc)); + printk(JFFS2_DBG "the node is inode node\n"); + printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.i.ino)); + printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.i.version)); + printk(JFFS2_DBG "mode:\t%#08x\n", node.i.mode.m); + printk(JFFS2_DBG "uid:\t%#04x\n", je16_to_cpu(node.i.uid)); + printk(JFFS2_DBG "gid:\t%#04x\n", je16_to_cpu(node.i.gid)); + printk(JFFS2_DBG "isize:\t%#08x\n", je32_to_cpu(node.i.isize)); + printk(JFFS2_DBG "atime:\t%#08x\n", je32_to_cpu(node.i.atime)); + printk(JFFS2_DBG "mtime:\t%#08x\n", je32_to_cpu(node.i.mtime)); + printk(JFFS2_DBG "ctime:\t%#08x\n", je32_to_cpu(node.i.ctime)); + printk(JFFS2_DBG "offset:\t%#08x\n", je32_to_cpu(node.i.offset)); + printk(JFFS2_DBG "csize:\t%#08x\n", je32_to_cpu(node.i.csize)); + printk(JFFS2_DBG "dsize:\t%#08x\n", je32_to_cpu(node.i.dsize)); + printk(JFFS2_DBG "compr:\t%#02x\n", node.i.compr); + printk(JFFS2_DBG "usercompr:\t%#02x\n", node.i.usercompr); + printk(JFFS2_DBG "flags:\t%#04x\n", je16_to_cpu(node.i.flags)); + printk(JFFS2_DBG "data_crc:\t%#08x\n", je32_to_cpu(node.i.data_crc)); + printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.i.node_crc)); + crc = crc32(0, &node.i, sizeof(node.i) - 8); if (crc != je32_to_cpu(node.i.node_crc)) { JFFS2_ERROR("wrong node header CRC.\n"); @@ -712,26 +676,18 @@ __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs) case JFFS2_NODETYPE_DIRENT: - printk(JFFS2_DBG_LVL "the node is dirent node\n"); - printk(JFFS2_DBG_LVL "pino:\t%#08x\n", - je32_to_cpu(node.d.pino)); - printk(JFFS2_DBG_LVL "version:\t%#08x\n", - je32_to_cpu(node.d.version)); - printk(JFFS2_DBG_LVL "ino:\t%#08x\n", - je32_to_cpu(node.d.ino)); - printk(JFFS2_DBG_LVL "mctime:\t%#08x\n", - je32_to_cpu(node.d.mctime)); - printk(JFFS2_DBG_LVL "nsize:\t%#02x\n", - node.d.nsize); - printk(JFFS2_DBG_LVL "type:\t%#02x\n", - node.d.type); - printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n", - je32_to_cpu(node.d.node_crc)); - printk(JFFS2_DBG_LVL "name_crc:\t%#08x\n", - je32_to_cpu(node.d.name_crc)); + printk(JFFS2_DBG "the node is dirent node\n"); + printk(JFFS2_DBG "pino:\t%#08x\n", je32_to_cpu(node.d.pino)); + printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.d.version)); + printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.d.ino)); + printk(JFFS2_DBG "mctime:\t%#08x\n", je32_to_cpu(node.d.mctime)); + printk(JFFS2_DBG "nsize:\t%#02x\n", node.d.nsize); + printk(JFFS2_DBG "type:\t%#02x\n", node.d.type); + printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.d.node_crc)); + printk(JFFS2_DBG "name_crc:\t%#08x\n", je32_to_cpu(node.d.name_crc)); node.d.name[node.d.nsize] = '\0'; - printk(JFFS2_DBG_LVL "name:\t\"%s\"\n", node.d.name); + printk(JFFS2_DBG "name:\t\"%s\"\n", node.d.name); crc = crc32(0, &node.d, sizeof(node.d) - 8); if (crc != je32_to_cpu(node.d.node_crc)) { @@ -741,7 +697,7 @@ __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs) break; default: - printk(JFFS2_DBG_LVL "node type is unknown\n"); + printk(JFFS2_DBG "node type is unknown\n"); break; } } diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index 60e5dbb3946..7328e67bebb 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.h,v 1.15 2005/09/07 08:34:54 havasi Exp $ + * $Id: debug.h,v 1.16 2005/09/14 16:57:32 dedekind Exp $ * */ #ifndef _JFFS2_DEBUG_H_ @@ -55,41 +55,46 @@ #endif /* The prefixes of JFFS2 messages */ -#define JFFS2_DBG_MSG_PREFIX "[JFFS2 DBG]" -#define JFFS2_ERR_MSG_PREFIX "JFFS2 error:" -#define JFFS2_WARN_MSG_PREFIX "JFFS2 warning:" -#define JFFS2_NOTICE_MSG_PREFIX "JFFS2 notice:" +#define JFFS2_DBG_PREFIX "[JFFS2 DBG]" +#define JFFS2_ERR_PREFIX "JFFS2 error:" +#define JFFS2_WARN_PREFIX "JFFS2 warning:" +#define JFFS2_NOTICE_PREFIX "JFFS2 notice:" -#define JFFS2_ERR_LVL KERN_ERR -#define JFFS2_WARN_LVL KERN_WARNING -#define JFFS2_NOTICE_LVL KERN_NOTICE -#define JFFS2_DBG_LVL KERN_DEBUG +#define JFFS2_ERR KERN_ERR +#define JFFS2_WARN KERN_WARNING +#define JFFS2_NOT KERN_NOTICE +#define JFFS2_DBG KERN_DEBUG + +#define JFFS2_DBG_MSG_PREFIX JFFS2_DBG JFFS2_DBG_PREFIX +#define JFFS2_ERR_MSG_PREFIX JFFS2_ERR JFFS2_ERR_PREFIX +#define JFFS2_WARN_MSG_PREFIX JFFS2_WARN JFFS2_WARN_PREFIX +#define JFFS2_NOTICE_MSG_PREFIX JFFS2_NOT JFFS2_NOTICE_PREFIX /* JFFS2 message macros */ #define JFFS2_ERROR(fmt, ...) \ do { \ - printk(JFFS2_ERR_LVL JFFS2_ERR_MSG_PREFIX \ + printk(JFFS2_ERR_MSG_PREFIX \ " (%d) %s: " fmt, current->pid, \ __FUNCTION__, ##__VA_ARGS__); \ } while(0) #define JFFS2_WARNING(fmt, ...) \ do { \ - printk(JFFS2_WARN_LVL JFFS2_WARN_MSG_PREFIX \ + printk(JFFS2_WARN_MSG_PREFIX \ " (%d) %s: " fmt, current->pid, \ __FUNCTION__, ##__VA_ARGS__); \ } while(0) #define JFFS2_NOTICE(fmt, ...) \ do { \ - printk(JFFS2_NOTICE_LVL JFFS2_NOTICE_MSG_PREFIX \ + printk(JFFS2_NOTICE_MSG_PREFIX \ " (%d) %s: " fmt, current->pid, \ __FUNCTION__, ##__VA_ARGS__); \ } while(0) #define JFFS2_DEBUG(fmt, ...) \ do { \ - printk(JFFS2_DBG_LVL JFFS2_DBG_MSG_PREFIX \ + printk(JFFS2_DBG_MSG_PREFIX \ " (%d) %s: " fmt, current->pid, \ __FUNCTION__, ##__VA_ARGS__); \ } while(0) -- cgit v1.2.3 From 9c517e6c801aab0f8de8f9c67bfc16ea13d72971 Mon Sep 17 00:00:00 2001 From: Todd Poynor Date: Wed, 14 Sep 2005 20:14:17 +0100 Subject: [MTD] maps: Add mapping driver for PQ2FADS boards. From: Vitaly Bordug Signed-off-by: Todd Poynor Signed-off-by: Thomas Gleixner --- drivers/mtd/maps/Kconfig | 8 ++++- drivers/mtd/maps/Makefile | 3 +- drivers/mtd/maps/pq2fads.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 drivers/mtd/maps/pq2fads.c diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index aa5d71f8d81..8e3e93d6252 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -1,5 +1,5 @@ # drivers/mtd/maps/Kconfig -# $Id: Kconfig,v 1.55 2005/07/02 01:53:24 tpoynor Exp $ +# $Id: Kconfig,v 1.58 2005/09/14 19:14:13 tpoynor Exp $ menu "Mapping drivers for chip access" depends on MTD!=n @@ -520,6 +520,12 @@ config MTD_MPC1211 This enables access to the flash chips on the Interface MPC-1211(CTP/PCI/MPC-SH02). If you have such a board, say 'Y'. +config MTD_PQ2FADS + tristate "JEDEC flash SIMM mapped on PQ2FADS and 8272ADS boards" + depends on (ADS8272 || PQ2FADS) && MTD_PARTITIONS && MTD_JEDECPROBE && MTD_PHYSMAP && MTD_CFI_GEOMETRY && MTD_CFI_INTELEXT + help + This enables access to flash SIMM on PQ2FADS-like boards + config MTD_OMAP_NOR tristate "TI OMAP board mappings" depends on MTD_CFI && ARCH_OMAP diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index 7bcbc49e329..095517847c7 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -1,7 +1,7 @@ # # linux/drivers/maps/Makefile # -# $Id: Makefile.common,v 1.30 2005/07/02 01:53:24 tpoynor Exp $ +# $Id: Makefile.common,v 1.31 2005/09/14 19:14:13 tpoynor Exp $ ifeq ($(CONFIG_MTD_COMPLEX_MAPPINGS),y) obj-$(CONFIG_MTD) += map_funcs.o @@ -70,3 +70,4 @@ obj-$(CONFIG_MTD_DMV182) += dmv182.o obj-$(CONFIG_MTD_SHARP_SL) += sharpsl-flash.o obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o obj-$(CONFIG_MTD_OMAP_NOR) += omap_nor.o +obj-$(CONFIG_MTD_PQ2FADS) += pq2fads.o diff --git a/drivers/mtd/maps/pq2fads.c b/drivers/mtd/maps/pq2fads.c new file mode 100644 index 00000000000..e959076b1bf --- /dev/null +++ b/drivers/mtd/maps/pq2fads.c @@ -0,0 +1,88 @@ +/* + * drivers/mtd/maps/pq2fads.c + * + * Mapping for the flash SIMM on 8272ADS and PQ2FADS board + * + * Author: Vitaly Bordug + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + NOTE: bank width and interleave relative to the installed flash + should have been chosen within MTD_CFI_GEOMETRY options. + */ +#define PQ2FADS_BANK_WIDTH 4 + +static struct mtd_partition pq2fads_partitions[] = { + { +#ifdef CONFIG_ADS8272 + .name = "HRCW", + .size = 0x40000, + .offset = 0, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, { + .name = "User FS", + .size = 0x5c0000, + .offset = 0x40000, +#else + .name = "User FS", + .size = 0x600000, + .offset = 0, +#endif + }, { + .name = "uImage", + .size = 0x100000, + .offset = 0x600000, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, { + .name = "bootloader", + .size = 0x40000, + .offset = 0x700000, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, { + .name = "bootloader env", + .size = 0x40000, + .offset = 0x740000, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + } +}; + + +/* pointer to MPC885ADS board info data */ +extern unsigned char __res[]; + +static int __init init_pq2fads_mtd(void) +{ + bd_t *bd = (bd_t *)__res; + physmap_configure(bd->bi_flashstart, bd->bi_flashsize, PQ2FADS_BANK_WIDTH, NULL); + + physmap_set_partitions(pq2fads_partitions, + sizeof (pq2fads_partitions) / + sizeof (pq2fads_partitions[0])); + return 0; +} + +static void __exit cleanup_pq2fads_mtd(void) +{ +} + +module_init(init_pq2fads_mtd); +module_exit(cleanup_pq2fads_mtd); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MTD map and partitions for MPC8272ADS boards"); -- cgit v1.2.3 From 962034f43937d02a1c18e802a6641aed0a266ac5 Mon Sep 17 00:00:00 2001 From: Vitaly Wool Date: Thu, 15 Sep 2005 14:58:53 +0100 Subject: [MTD] NAND: Add suspend/resume functionality The changes introduced allow to suspend/resume NAND flash. A new state (FL_PM_SUSPENDED) is introduced, as well as routines for mtd->suspend and mtd->resume to put the flash in suspended state from software pov. Signed-off-by: Vitaly Wool Signed-off-by: Thomas Gleixner --- drivers/mtd/nand/nand_base.c | 46 ++++++++++++++++++++++++++++++++++++++------ include/linux/mtd/nand.h | 3 ++- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index cdf10861934..4e22317397e 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -46,6 +46,8 @@ * perform extra error status checks on erase and write failures. This required * adding a wrapper function for nand_read_ecc. * + * 08-20-2005 vwool: suspend/resume added + * * Credits: * David Woodhouse for adding multichip support * @@ -59,7 +61,7 @@ * The AG-AND chips have nice features for speed improvement, * which are not supported yet. Read / program 4 pages in one go. * - * $Id: nand_base.c,v 1.148 2005/08/04 17:14:48 gleixner Exp $ + * $Id: nand_base.c,v 1.150 2005/09/15 13:58:48 vwool Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -153,7 +155,7 @@ static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int #define nand_verify_pages(...) (0) #endif -static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state); +static int nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state); /** * nand_release_device - [GENERIC] release chip @@ -756,7 +758,7 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, * * Get the device and lock it for exclusive access */ -static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state) +static int nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state) { struct nand_chip *active; spinlock_t *lock; @@ -779,7 +781,11 @@ retry: if (active == this && this->state == FL_READY) { this->state = new_state; spin_unlock(lock); - return; + return 0; + } + if (new_state == FL_PM_SUSPENDED) { + spin_unlock(lock); + return (this->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN; } set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(wq, &wait); @@ -2284,6 +2290,34 @@ static int nand_block_markbad (struct mtd_info *mtd, loff_t ofs) return this->block_markbad(mtd, ofs); } +/** + * nand_suspend - [MTD Interface] Suspend the NAND flash + * @mtd: MTD device structure + */ +static int nand_suspend(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + + return nand_get_device (this, mtd, FL_PM_SUSPENDED); +} + +/** + * nand_resume - [MTD Interface] Resume the NAND flash + * @mtd: MTD device structure + */ +static void nand_resume(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + + if (this->state == FL_PM_SUSPENDED) + nand_release_device(mtd); + else + printk(KERN_ERR "resume() called for the chip which is not " + "in suspended state\n"); + +} + + /** * nand_scan - [NAND Interface] Scan for the NAND device * @mtd: MTD device structure @@ -2643,8 +2677,8 @@ int nand_scan (struct mtd_info *mtd, int maxchips) mtd->sync = nand_sync; mtd->lock = NULL; mtd->unlock = NULL; - mtd->suspend = NULL; - mtd->resume = NULL; + mtd->suspend = nand_suspend; + mtd->resume = nand_resume; mtd->block_isbad = nand_block_isbad; mtd->block_markbad = nand_block_markbad; diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 9b5b7621758..2d36413b2f9 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -5,7 +5,7 @@ * Steven J. Hill * Thomas Gleixner * - * $Id: nand.h,v 1.73 2005/05/31 19:39:17 gleixner Exp $ + * $Id: nand.h,v 1.74 2005/09/15 13:58:50 vwool Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -244,6 +244,7 @@ typedef enum { FL_ERASING, FL_SYNCING, FL_CACHEDPRG, + FL_PM_SUSPENDED, } nand_state_t; /* Keep gcc happy */ -- cgit v1.2.3 From 34c0e906718fa2f85b54b937f79bffdca48ee864 Mon Sep 17 00:00:00 2001 From: Ferenc Havasi Date: Fri, 16 Sep 2005 13:58:20 +0100 Subject: [JFFS2] Account summary space in reserved_size. Always keep valid data in reserved_size. It did not cause problems, but the reservation code was unoptimal when centralized summary was active or the size of the erase block was very small. Signed-off-by: Ferenc Havasi Signed-off-by: Thomas Gleixner --- fs/jffs2/nodemgmt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 208b2bdf01e..2cf576ae112 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodemgmt.c,v 1.125 2005/09/07 08:34:54 havasi Exp $ + * $Id: nodemgmt.c,v 1.126 2005/09/16 12:58:17 havasi Exp $ * */ @@ -307,6 +307,8 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin jffs2_close_nextblock(c, jeb); jeb = NULL; + /* keep always valid value in reserved_size */ + reserved_size = PAD(sumsize + c->summary->sum_size + JFFS2_SUMMARY_FRAME_SIZE); } } else { if (jeb && minsize > jeb->free_size) { -- cgit v1.2.3 From b523b3bac3a745fefd6f604082f2ffa09b808e5e Mon Sep 17 00:00:00 2001 From: Joern Engel Date: Sun, 18 Sep 2005 11:46:45 +0100 Subject: [MTD] maps: Add support for MTX-1 Flash device Add support for "4G Systems MTX-1 Flash device", better known as meshcube. From: Bruno Randolf Signed-off-by: Joern Engel Signed-off-by: Thomas Gleixner --- drivers/mtd/maps/Kconfig | 9 +++- drivers/mtd/maps/Makefile | 3 +- drivers/mtd/maps/mtx-1_flash.c | 96 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 drivers/mtd/maps/mtx-1_flash.c diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 8e3e93d6252..7f1ce08fb7b 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -1,5 +1,5 @@ # drivers/mtd/maps/Kconfig -# $Id: Kconfig,v 1.58 2005/09/14 19:14:13 tpoynor Exp $ +# $Id: Kconfig,v 1.59 2005/09/18 10:46:41 joern Exp $ menu "Mapping drivers for chip access" depends on MTD!=n @@ -214,6 +214,13 @@ config MTD_ALCHEMY help Flash memory access on AMD Alchemy Pb/Db/RDK Reference Boards +config MTD_MTX1 + tristate "4G Systems MTX-1 Flash device" + depends on MIPS && MIPS_MTX1 + help + Flash memory access on 4G Systems MTX-1 Board. If you have one of + these boards and would like to use the flash chips on it, say 'Y'. + config MTD_DILNETPC tristate "CFI Flash device mapped on DIL/Net PC" depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index 095517847c7..2afa80678d5 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -1,7 +1,7 @@ # # linux/drivers/maps/Makefile # -# $Id: Makefile.common,v 1.31 2005/09/14 19:14:13 tpoynor Exp $ +# $Id: Makefile.common,v 1.32 2005/09/18 10:46:41 joern Exp $ ifeq ($(CONFIG_MTD_COMPLEX_MAPPINGS),y) obj-$(CONFIG_MTD) += map_funcs.o @@ -71,3 +71,4 @@ obj-$(CONFIG_MTD_SHARP_SL) += sharpsl-flash.o obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o obj-$(CONFIG_MTD_OMAP_NOR) += omap_nor.o obj-$(CONFIG_MTD_PQ2FADS) += pq2fads.o +obj-$(CONFIG_MTD_MTX1) += mtx-1_flash.o diff --git a/drivers/mtd/maps/mtx-1_flash.c b/drivers/mtd/maps/mtx-1_flash.c new file mode 100644 index 00000000000..43f4416a611 --- /dev/null +++ b/drivers/mtd/maps/mtx-1_flash.c @@ -0,0 +1,96 @@ +/* + * Flash memory access on 4G Systems MTX-1 boards + * + * $Id: mtx-1_flash.c,v 1.1 2005/09/18 10:46:41 joern Exp $ + * + * (C) 2005 Bruno Randolf + * (C) 2005 Jörn Engel + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +static struct map_info mtx1_map = { + .name = "MTX-1 flash", + .bankwidth = 4, + .size = 0x2000000, + .phys = 0x1E000000, +}; + +static struct mtd_partition mtx1_partitions[] = { + { + .name = "filesystem", + .size = 0x01C00000, + .offset = 0, + },{ + .name = "yamon", + .size = 0x00100000, + .offset = MTDPART_OFS_APPEND, + .mask_flags = MTD_WRITEABLE, + },{ + .name = "kernel", + .size = 0x002c0000, + .offset = MTDPART_OFS_APPEND, + },{ + .name = "yamon env", + .size = 0x00040000, + .offset = MTDPART_OFS_APPEND, + } +}; + +static struct mtd_info *mtx1_mtd; + +int __init mtx1_mtd_init(void) +{ + int ret = -ENXIO; + + simple_map_init(&mtx1_map); + + mtx1_map.virt = ioremap(mtx1_map.phys, mtx1_map.size); + if (!mtx1_map.virt) + return -EIO; + + mtx1_mtd = do_map_probe("cfi_probe", &mtx1_map); + if (!mtx1_mtd) + goto err; + + mtx1_mtd->owner = THIS_MODULE; + + ret = add_mtd_partitions(mtx1_mtd, mtx1_partitions, + ARRAY_SIZE(mtx1_partitions)); + if (ret) + goto err; + + return 0; + +err: + iounmap(mtx1_map.virt); + return ret; +} + +static void __exit mtx1_mtd_cleanup(void) +{ + if (mtx1_mtd) { + del_mtd_partitions(mtx1_mtd); + map_destroy(mtx1_mtd); + } + if (mtx1_map.virt) + iounmap(mtx1_map.virt); +} + +module_init(mtx1_mtd_init); +module_exit(mtx1_mtd_cleanup); + +MODULE_AUTHOR("Bruno Randolf "); +MODULE_DESCRIPTION("MTX-1 flash map"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 733802d974e5af42acb7cd61b16c0ce6dd03b7ed Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Thu, 22 Sep 2005 12:25:00 +0100 Subject: [JFFS2] Debug code simplification, update TODO Simplify the debugging code further. Update the TODO list Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/TODO | 38 +++++++-------- fs/jffs2/build.c | 112 +++++++++++++++++++++----------------------- fs/jffs2/debug.c | 3 +- fs/jffs2/debug.h | 50 +++++++++++++------- fs/jffs2/erase.c | 2 +- fs/jffs2/malloc.c | 34 +++++++------- fs/jffs2/nodelist.c | 107 ++++++++++++++++++++++-------------------- fs/jffs2/nodemgmt.c | 6 +-- fs/jffs2/os-linux.h | 6 +-- fs/jffs2/readinode.c | 32 ++++++------- fs/jffs2/scan.c | 48 ++----------------- fs/jffs2/summary.c | 53 +++++++++++---------- fs/jffs2/wbuf.c | 5 +- include/linux/jffs2_fs_sb.h | 5 +- 14 files changed, 235 insertions(+), 266 deletions(-) diff --git a/fs/jffs2/TODO b/fs/jffs2/TODO index 2bff82fd221..d0e23b26fa5 100644 --- a/fs/jffs2/TODO +++ b/fs/jffs2/TODO @@ -1,5 +1,11 @@ -$Id: TODO,v 1.10 2002/09/09 16:31:21 dwmw2 Exp $ +$Id: TODO,v 1.18 2005/09/22 11:24:56 dedekind Exp $ + - support asynchronous operation -- add a per-fs 'reserved_space' count, + let each outstanding write reserve the _maximum_ amount of physical + space it could take. Let GC flush the outstanding writes because the + reservations will necessarily be pessimistic. With this we could even + do shared writable mmap, if we can have a fs hook for do_wp_page() to + make the reservation. - disable compression in commit_write()? - fine-tune the allocation / GC thresholds - chattr support - turning on/off and tuning compression per-inode @@ -11,26 +17,15 @@ $Id: TODO,v 1.10 2002/09/09 16:31:21 dwmw2 Exp $ - test, test, test - NAND flash support: - - flush_wbuf using GC to fill it, don't just pad. - - Deal with write errors. Data don't get lost - we just have to write - the affected node(s) out again somewhere else. - - make fsync flush only if actually required - - make sys_sync() work. - - reboot notifier - - timed flush of old wbuf - - fix magical second arg of jffs2_flush_wbuf(). Split into two or more functions instead. - + - almost done :) + - use bad block check instead of the hardwired byte check - Optimisations: - - Stop GC from decompressing and immediately recompressing nodes which could - just be copied intact. (We now keep track of REF_PRISTINE flag. Easy now.) - - Furthermore, in the case where it could be copied intact we don't even need - to call iget() for it -- if we use (raw_node_raw->flash_offset & 2) as a flag - to show a node can be copied intact and it's _not_ in icache, we could just do - it, fix up the next_in_ino list and move on. We would need a way to find out - _whether_ it's in icache though -- if it's in icache we also need to do the - fragment lists, etc. P'raps a flag or pointer in the jffs2_inode_cache could - help. (We have half of this now.) + - Split writes so they go to two separate blocks rather than just c->nextblock. + By writing _new_ nodes to one block, and garbage-collected REF_PRISTINE + nodes to a different one, we can separate clean nodes from those which + are likely to become dirty, and end up with blocks which are each far + closer to 100% or 0% clean, hence speeding up later GC progress dramatically. - Stop keeping name in-core with struct jffs2_full_dirent. If we keep the hash in the full dirent, we only need to go to the flash in lookup() when we think we've got a match, and in readdir(). @@ -38,3 +33,8 @@ $Id: TODO,v 1.10 2002/09/09 16:31:21 dwmw2 Exp $ - Remove totlen from jffs2_raw_node_ref? Need to have totlen passed into jffs2_mark_node_obsolete(). Can all callers work it out? - Remove size from jffs2_raw_node_frag. + +dedekind: +1. __jffs2_flush_wbuf() has a strange 'pad' parameter. Eliminate. +2. get_sb()->build_fs()->scan() path... Why get_sb() removes scan()'s crap in + case of failure? scan() does not clean everything. Fix. diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index f2cf562ebd2..ac393b3d6ea 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: build.c,v 1.79 2005/09/07 11:21:57 havasi Exp $ + * $Id: build.c,v 1.83 2005/09/21 15:52:33 dedekind Exp $ * */ @@ -18,7 +18,8 @@ #include #include "nodelist.h" -static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *, struct jffs2_inode_cache *, struct jffs2_full_dirent **); +static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *, + struct jffs2_inode_cache *, struct jffs2_full_dirent **); static inline struct jffs2_inode_cache * first_inode_chain(int *i, struct jffs2_sb_info *c) @@ -46,11 +47,12 @@ next_inode(int *i, struct jffs2_inode_cache *ic, struct jffs2_sb_info *c) ic = next_inode(&i, ic, (c))) -static inline void jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) +static inline void jffs2_build_inode_pass1(struct jffs2_sb_info *c, + struct jffs2_inode_cache *ic) { struct jffs2_full_dirent *fd; - D1(printk(KERN_DEBUG "jffs2_build_inode building directory inode #%u\n", ic->ino)); + dbg_fsbuild("building directory inode #%u\n", ic->ino); /* For each child, increase nlink */ for(fd = ic->scan_dents; fd; fd = fd->next) { @@ -58,26 +60,23 @@ static inline void jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2 if (!fd->ino) continue; - /* XXX: Can get high latency here with huge directories */ + /* we can get high latency here with huge directories */ child_ic = jffs2_get_ino_cache(c, fd->ino); if (!child_ic) { - printk(KERN_NOTICE "Eep. Child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n", + dbg_fsbuild("child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n", fd->name, fd->ino, ic->ino); jffs2_mark_node_obsolete(c, fd->raw); continue; } if (child_ic->nlink++ && fd->type == DT_DIR) { - printk(KERN_NOTICE "Child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n", fd->name, fd->ino, ic->ino); - if (fd->ino == 1 && ic->ino == 1) { - printk(KERN_NOTICE "This is mostly harmless, and probably caused by creating a JFFS2 image\n"); - printk(KERN_NOTICE "using a buggy version of mkfs.jffs2. Use at least v1.17.\n"); - } - /* What do we do about it? */ + JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n", + fd->name, fd->ino, ic->ino); + /* TODO: What do we do about it? */ } - D1(printk(KERN_DEBUG "Increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino)); - /* Can't free them. We might need them in pass 2 */ + dbg_fsbuild("increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino); + /* Can't free scan_dents so far. We might need them in pass 2 */ } } @@ -94,6 +93,8 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) struct jffs2_full_dirent *fd; struct jffs2_full_dirent *dead_fds = NULL; + dbg_fsbuild("build FS data structures\n"); + /* First, scan the medium and build all the inode caches with lists of physical nodes */ @@ -103,33 +104,29 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) if (ret) goto exit; - D1(printk(KERN_DEBUG "Scanned flash completely\n")); + dbg_fsbuild("scanned flash completely\n"); jffs2_dbg_dump_block_lists_nolock(c); + dbg_fsbuild("pass 1 starting\n"); c->flags |= JFFS2_SB_FLAG_BUILDING; /* Now scan the directory tree, increasing nlink according to every dirent found. */ for_each_inode(i, c, ic) { - D1(printk(KERN_DEBUG "Pass 1: ino #%u\n", ic->ino)); - - D1(BUG_ON(ic->ino > c->highest_ino)); - if (ic->scan_dents) { jffs2_build_inode_pass1(c, ic); cond_resched(); } } - D1(printk(KERN_DEBUG "Pass 1 complete\n")); + dbg_fsbuild("pass 1 complete\n"); /* Next, scan for inodes with nlink == 0 and remove them. If they were directories, then decrement the nlink of their children too, and repeat the scan. As that's going to be a fairly uncommon occurrence, it's not so evil to do it this way. Recursion bad. */ - D1(printk(KERN_DEBUG "Pass 2 starting\n")); + dbg_fsbuild("pass 2 starting\n"); for_each_inode(i, c, ic) { - D1(printk(KERN_DEBUG "Pass 2: ino #%u, nlink %d, ic %p, nodes %p\n", ic->ino, ic->nlink, ic, ic->nodes)); if (ic->nlink) continue; @@ -137,26 +134,24 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) cond_resched(); } - D1(printk(KERN_DEBUG "Pass 2a starting\n")); + dbg_fsbuild("pass 2a starting\n"); while (dead_fds) { fd = dead_fds; dead_fds = fd->next; ic = jffs2_get_ino_cache(c, fd->ino); - D1(printk(KERN_DEBUG "Removing dead_fd ino #%u (\"%s\"), ic at %p\n", fd->ino, fd->name, ic)); if (ic) jffs2_build_remove_unlinked_inode(c, ic, &dead_fds); jffs2_free_full_dirent(fd); } - D1(printk(KERN_DEBUG "Pass 2 complete\n")); + dbg_fsbuild("pass 2a complete\n"); + dbg_fsbuild("freeing temporary data structures\n"); /* Finally, we can scan again and free the dirent structs */ for_each_inode(i, c, ic) { - D1(printk(KERN_DEBUG "Pass 3: ino #%u, ic %p, nodes %p\n", ic->ino, ic, ic->nodes)); - while(ic->scan_dents) { fd = ic->scan_dents; ic->scan_dents = fd->next; @@ -167,8 +162,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) } c->flags &= ~JFFS2_SB_FLAG_BUILDING; - D1(printk(KERN_DEBUG "Pass 3 complete\n")); - jffs2_dbg_dump_block_lists_nolock(c); + dbg_fsbuild("FS build complete\n"); /* Rotate the lists by some number to ensure wear levelling */ jffs2_rotate_lists(c); @@ -189,24 +183,26 @@ exit: return ret; } -static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, struct jffs2_full_dirent **dead_fds) +static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, + struct jffs2_inode_cache *ic, + struct jffs2_full_dirent **dead_fds) { struct jffs2_raw_node_ref *raw; struct jffs2_full_dirent *fd; - D1(printk(KERN_DEBUG "JFFS2: Removing ino #%u with nlink == zero.\n", ic->ino)); + dbg_fsbuild("removing ino #%u with nlink == zero.\n", ic->ino); raw = ic->nodes; while (raw != (void *)ic) { struct jffs2_raw_node_ref *next = raw->next_in_ino; - D1(printk(KERN_DEBUG "obsoleting node at 0x%08x\n", ref_offset(raw))); + dbg_fsbuild("obsoleting node at 0x%08x\n", ref_offset(raw)); jffs2_mark_node_obsolete(c, raw); raw = next; } if (ic->scan_dents) { int whinged = 0; - D1(printk(KERN_DEBUG "Inode #%u was a directory which may have children...\n", ic->ino)); + dbg_fsbuild("inode #%u was a directory which may have children...\n", ic->ino); while(ic->scan_dents) { struct jffs2_inode_cache *child_ic; @@ -216,21 +212,19 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jf if (!fd->ino) { /* It's a deletion dirent. Ignore it */ - D1(printk(KERN_DEBUG "Child \"%s\" is a deletion dirent, skipping...\n", fd->name)); + dbg_fsbuild("child \"%s\" is a deletion dirent, skipping...\n", fd->name); jffs2_free_full_dirent(fd); continue; } - if (!whinged) { + if (!whinged) whinged = 1; - printk(KERN_NOTICE "Inode #%u was a directory with children - removing those too...\n", ic->ino); - } - D1(printk(KERN_DEBUG "Removing child \"%s\", ino #%u\n", - fd->name, fd->ino)); + dbg_fsbuild("removing child \"%s\", ino #%u\n", fd->name, fd->ino); child_ic = jffs2_get_ino_cache(c, fd->ino); if (!child_ic) { - printk(KERN_NOTICE "Cannot remove child \"%s\", ino #%u, because it doesn't exist\n", fd->name, fd->ino); + dbg_fsbuild("cannot remove child \"%s\", ino #%u, because it doesn't exist\n", + fd->name, fd->ino); jffs2_free_full_dirent(fd); continue; } @@ -241,13 +235,13 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jf child_ic->nlink--; if (!child_ic->nlink) { - D1(printk(KERN_DEBUG "Inode #%u (\"%s\") has now got zero nlink. Adding to dead_fds list.\n", - fd->ino, fd->name)); + dbg_fsbuild("inode #%u (\"%s\") has now got zero nlink, adding to dead_fds list.\n", + fd->ino, fd->name); fd->next = *dead_fds; *dead_fds = fd; } else { - D1(printk(KERN_DEBUG "Inode #%u (\"%s\") has now got nlink %d. Ignoring.\n", - fd->ino, fd->name, child_ic->nlink)); + dbg_fsbuild("inode #%u (\"%s\") has now got nlink %d. Ignoring.\n", + fd->ino, fd->name, child_ic->nlink); jffs2_free_full_dirent(fd); } } @@ -295,20 +289,20 @@ static void jffs2_calc_trigger_levels(struct jffs2_sb_info *c) trying to GC to make more space. It'll be a fruitless task */ c->nospc_dirty_size = c->sector_size + (c->flash_size / 100); - D1(printk(KERN_DEBUG "JFFS2 trigger levels (size %d KiB, block size %d KiB, %d blocks)\n", - c->flash_size / 1024, c->sector_size / 1024, c->nr_blocks)); - D1(printk(KERN_DEBUG "Blocks required to allow deletion: %d (%d KiB)\n", - c->resv_blocks_deletion, c->resv_blocks_deletion*c->sector_size/1024)); - D1(printk(KERN_DEBUG "Blocks required to allow writes: %d (%d KiB)\n", - c->resv_blocks_write, c->resv_blocks_write*c->sector_size/1024)); - D1(printk(KERN_DEBUG "Blocks required to quiesce GC thread: %d (%d KiB)\n", - c->resv_blocks_gctrigger, c->resv_blocks_gctrigger*c->sector_size/1024)); - D1(printk(KERN_DEBUG "Blocks required to allow GC merges: %d (%d KiB)\n", - c->resv_blocks_gcmerge, c->resv_blocks_gcmerge*c->sector_size/1024)); - D1(printk(KERN_DEBUG "Blocks required to GC bad blocks: %d (%d KiB)\n", - c->resv_blocks_gcbad, c->resv_blocks_gcbad*c->sector_size/1024)); - D1(printk(KERN_DEBUG "Amount of dirty space required to GC: %d bytes\n", - c->nospc_dirty_size)); + dbg_fsbuild("JFFS2 trigger levels (size %d KiB, block size %d KiB, %d blocks)\n", + c->flash_size / 1024, c->sector_size / 1024, c->nr_blocks); + dbg_fsbuild("Blocks required to allow deletion: %d (%d KiB)\n", + c->resv_blocks_deletion, c->resv_blocks_deletion*c->sector_size/1024); + dbg_fsbuild("Blocks required to allow writes: %d (%d KiB)\n", + c->resv_blocks_write, c->resv_blocks_write*c->sector_size/1024); + dbg_fsbuild("Blocks required to quiesce GC thread: %d (%d KiB)\n", + c->resv_blocks_gctrigger, c->resv_blocks_gctrigger*c->sector_size/1024); + dbg_fsbuild("Blocks required to allow GC merges: %d (%d KiB)\n", + c->resv_blocks_gcmerge, c->resv_blocks_gcmerge*c->sector_size/1024); + dbg_fsbuild("Blocks required to GC bad blocks: %d (%d KiB)\n", + c->resv_blocks_gcbad, c->resv_blocks_gcbad*c->sector_size/1024); + dbg_fsbuild("Amount of dirty space required to GC: %d bytes\n", + c->nospc_dirty_size); } int jffs2_do_mount_fs(struct jffs2_sb_info *c) @@ -358,7 +352,7 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) return ret; if (jffs2_build_filesystem(c)) { - D1(printk(KERN_DEBUG "build_fs failed\n")); + dbg_fsbuild("build_fs failed\n"); jffs2_free_ino_caches(c); jffs2_free_raw_node_refs(c); #ifndef __ECOS diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c index 28983501bce..0947284f45d 100644 --- a/fs/jffs2/debug.c +++ b/fs/jffs2/debug.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.c,v 1.10 2005/09/14 16:57:32 dedekind Exp $ + * $Id: debug.c,v 1.11 2005/09/21 13:28:35 dedekind Exp $ * */ #include @@ -15,6 +15,7 @@ #include #include #include +#include #include "nodelist.h" #include "debug.h" diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index 7328e67bebb..da1417d3891 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.h,v 1.16 2005/09/14 16:57:32 dedekind Exp $ + * $Id: debug.h,v 1.18 2005/09/21 10:26:26 dedekind Exp $ * */ #ifndef _JFFS2_DEBUG_H_ @@ -23,16 +23,23 @@ /* Enable "paranoia" checks and dumps */ #define JFFS2_DBG_PARANOIA_CHECKS #define JFFS2_DBG_DUMPS + +/* + * By defining/undefining the below macros one may select debugging messages + * fro specific JFFS2 subsystems. + */ #define JFFS2_DBG_READINODE_MESSAGES #define JFFS2_DBG_FRAGTREE_MESSAGES #define JFFS2_DBG_DENTLIST_MESSAGES #define JFFS2_DBG_NODEREF_MESSAGES #define JFFS2_DBG_INOCACHE_MESSAGES #define JFFS2_DBG_SUMMARY_MESSAGES +#define JFFS2_DBG_FSBUILD_MESSAGES #endif #if CONFIG_JFFS2_FS_DEBUG == 2 #define JFFS2_DBG_FRAGTREE2_MESSAGES +#define JFFS2_DBG_MEMALLOC_MESSAGES #endif /* Sanity checks are supposed to be light-weight and enabled by default */ @@ -40,7 +47,7 @@ /* * Dx() are mainly used for debugging messages, they must go away and be - * superseded by nicer JFFS2_DBG_XXX() macros... + * superseded by nicer dbg_xxx() macros... */ #if CONFIG_JFFS2_FS_DEBUG > 0 #define D1(x) x @@ -105,56 +112,63 @@ */ /* Read inode debugging messages */ #ifdef JFFS2_DBG_READINODE_MESSAGES -#define JFFS2_DBG_READINODE(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_readinode(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_READINODE(fmt, ...) +#define dbg_readinode(fmt, ...) #endif /* Fragtree build debugging messages */ #ifdef JFFS2_DBG_FRAGTREE_MESSAGES -#define JFFS2_DBG_FRAGTREE(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_fragtree(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_FRAGTREE(fmt, ...) +#define dbg_fragtree(fmt, ...) #endif #ifdef JFFS2_DBG_FRAGTREE2_MESSAGES -#define JFFS2_DBG_FRAGTREE2(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_fragtree2(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_FRAGTREE2(fmt, ...) +#define dbg_fragtree2(fmt, ...) #endif /* Directory entry list manilulation debugging messages */ #ifdef JFFS2_DBG_DENTLIST_MESSAGES -#define JFFS2_DBG_DENTLIST(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_dentlist(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_DENTLIST(fmt, ...) +#define dbg_dentlist(fmt, ...) #endif /* Print the messages about manipulating node_refs */ #ifdef JFFS2_DBG_NODEREF_MESSAGES -#define JFFS2_DBG_NODEREF(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_noderef(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_NODEREF(fmt, ...) +#define dbg_noderef(fmt, ...) #endif /* Manipulations with the list of inodes (JFFS2 inocache) */ #ifdef JFFS2_DBG_INOCACHE_MESSAGES -#define JFFS2_DBG_INOCACHE(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_inocache(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_INOCACHE(fmt, ...) +#define dbg_inocache(fmt, ...) #endif /* Summary debugging messages */ #ifdef JFFS2_DBG_SUMMARY_MESSAGES -#define JFFS2_DBG_SUMMARY(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_summary(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#else +#define dbg_summary(fmt, ...) +#endif + +/* File system build messages */ +#ifdef JFFS2_DBG_FSBUILD_MESSAGES +#define dbg_fsbuild(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_SUMMARY(fmt, ...) +#define dbg_fsbuild(fmt, ...) #endif /* Watch the object allocations */ #ifdef JFFS2_DBG_MEMALLOC_MESSAGES -#define JFFS2_DBG_MEMALLOC(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_memalloc(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_MEMALLOC(fmt, ...) +#define dbg_memalloc(fmt, ...) #endif diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index a8a0908142d..347de4efeee 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: erase.c,v 1.83 2005/07/22 10:32:08 dedekind Exp $ + * $Id: erase.c,v 1.85 2005/09/20 14:53:15 dedekind Exp $ * */ diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c index 734801145bf..f27df015f3e 100644 --- a/fs/jffs2/malloc.c +++ b/fs/jffs2/malloc.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: malloc.c,v 1.29 2005/07/27 14:16:53 dedekind Exp $ + * $Id: malloc.c,v 1.30 2005/09/20 14:27:34 dedekind Exp $ * */ @@ -97,13 +97,13 @@ struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize) { struct jffs2_full_dirent *ret; ret = kmalloc(sizeof(struct jffs2_full_dirent) + namesize, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", ret); + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_full_dirent(struct jffs2_full_dirent *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kfree(x); } @@ -111,13 +111,13 @@ struct jffs2_full_dnode *jffs2_alloc_full_dnode(void) { struct jffs2_full_dnode *ret; ret = kmem_cache_alloc(full_dnode_slab, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", ret); + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_full_dnode(struct jffs2_full_dnode *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kmem_cache_free(full_dnode_slab, x); } @@ -125,13 +125,13 @@ struct jffs2_raw_dirent *jffs2_alloc_raw_dirent(void) { struct jffs2_raw_dirent *ret; ret = kmem_cache_alloc(raw_dirent_slab, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", ret); + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_raw_dirent(struct jffs2_raw_dirent *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kmem_cache_free(raw_dirent_slab, x); } @@ -139,13 +139,13 @@ struct jffs2_raw_inode *jffs2_alloc_raw_inode(void) { struct jffs2_raw_inode *ret; ret = kmem_cache_alloc(raw_inode_slab, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", ret); + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_raw_inode(struct jffs2_raw_inode *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kmem_cache_free(raw_inode_slab, x); } @@ -153,14 +153,14 @@ struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void) { struct jffs2_tmp_dnode_info *ret; ret = kmem_cache_alloc(tmp_dnode_info_slab, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kmem_cache_free(tmp_dnode_info_slab, x); } @@ -168,13 +168,13 @@ struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void) { struct jffs2_raw_node_ref *ret; ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", ret); + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kmem_cache_free(raw_node_ref_slab, x); } @@ -182,13 +182,13 @@ struct jffs2_node_frag *jffs2_alloc_node_frag(void) { struct jffs2_node_frag *ret; ret = kmem_cache_alloc(node_frag_slab, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", ret); + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_node_frag(struct jffs2_node_frag *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kmem_cache_free(node_frag_slab, x); } @@ -196,12 +196,12 @@ struct jffs2_inode_cache *jffs2_alloc_inode_cache(void) { struct jffs2_inode_cache *ret; ret = kmem_cache_alloc(inode_cache_slab, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", ret); + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_inode_cache(struct jffs2_inode_cache *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kmem_cache_free(inode_cache_slab, x); } diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 9abb5f4cfd7..80fe8feffb4 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.c,v 1.112 2005/08/22 09:07:09 dedekind Exp $ + * $Id: nodelist.c,v 1.114 2005/09/21 13:28:35 dedekind Exp $ * */ @@ -25,18 +25,18 @@ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new { struct jffs2_full_dirent **prev = list; - JFFS2_DBG_DENTLIST("add dirent \"%s\", ino #%u\n", new->name, new->ino); + dbg_dentlist("add dirent \"%s\", ino #%u\n", new->name, new->ino); while ((*prev) && (*prev)->nhash <= new->nhash) { if ((*prev)->nhash == new->nhash && !strcmp((*prev)->name, new->name)) { /* Duplicate. Free one */ if (new->version < (*prev)->version) { - JFFS2_DBG_DENTLIST("Eep! Marking new dirent node is obsolete, old is \"%s\", ino #%u\n", + dbg_dentlist("Eep! Marking new dirent node is obsolete, old is \"%s\", ino #%u\n", (*prev)->name, (*prev)->ino); jffs2_mark_node_obsolete(c, new->raw); jffs2_free_full_dirent(new); } else { - JFFS2_DBG_DENTLIST("marking old dirent \"%s\", ino #%u bsolete\n", + dbg_dentlist("marking old dirent \"%s\", ino #%u bsolete\n", (*prev)->name, (*prev)->ino); new->next = (*prev)->next; jffs2_mark_node_obsolete(c, ((*prev)->raw)); @@ -55,7 +55,7 @@ void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint { struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size); - JFFS2_DBG_FRAGTREE("truncating fragtree to 0x%08x bytes\n", size); + dbg_fragtree("truncating fragtree to 0x%08x bytes\n", size); /* We know frag->ofs <= size. That's what lookup does for us */ if (frag && frag->ofs != size) { @@ -81,7 +81,7 @@ void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint */ frag = frag_last(list); if (frag->node && (frag->ofs & (PAGE_CACHE_SIZE - 1)) == 0) { - JFFS2_DBG_FRAGTREE2("marking the last fragment 0x%08x-0x%08x REF_PRISTINE.\n", + dbg_fragtree2("marking the last fragment 0x%08x-0x%08x REF_PRISTINE.\n", frag->ofs, frag->ofs + frag->size); frag->node->raw->flash_offset = ref_offset(frag->node->raw) | REF_PRISTINE; } @@ -93,12 +93,12 @@ void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *t this->node->frags--; if (!this->node->frags) { /* The node has no valid frags left. It's totally obsoleted */ - JFFS2_DBG_FRAGTREE2("marking old node @0x%08x (0x%04x-0x%04x) obsolete\n", + dbg_fragtree2("marking old node @0x%08x (0x%04x-0x%04x) obsolete\n", ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size); jffs2_mark_node_obsolete(c, this->node->raw); jffs2_free_full_dnode(this->node); } else { - JFFS2_DBG_FRAGTREE2("marking old node @0x%08x (0x%04x-0x%04x) REF_NORMAL. frags is %d\n", + dbg_fragtree2("marking old node @0x%08x (0x%04x-0x%04x) REF_NORMAL. frags is %d\n", ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size, this->node->frags); mark_ref_normal(this->node->raw); } @@ -112,7 +112,7 @@ static void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_ struct rb_node *parent = &base->rb; struct rb_node **link = &parent; - JFFS2_DBG_FRAGTREE2("insert frag (0x%04x-0x%04x)\n", newfrag->ofs, newfrag->ofs + newfrag->size); + dbg_fragtree2("insert frag (0x%04x-0x%04x)\n", newfrag->ofs, newfrag->ofs + newfrag->size); while (*link) { parent = *link; @@ -172,11 +172,11 @@ static int no_overlapping_node(struct jffs2_sb_info *c, struct rb_root *root, /* By definition, the 'this' node has no right-hand child, because there are no frags with offset greater than it. So that's where we want to put the hole */ - JFFS2_DBG_FRAGTREE2("add hole frag %#04x-%#04x on the right of the new frag.\n", + dbg_fragtree2("add hole frag %#04x-%#04x on the right of the new frag.\n", holefrag->ofs, holefrag->ofs + holefrag->size); rb_link_node(&holefrag->rb, &this->rb, &this->rb.rb_right); } else { - JFFS2_DBG_FRAGTREE2("Add hole frag %#04x-%#04x to the root of the tree.\n", + dbg_fragtree2("Add hole frag %#04x-%#04x to the root of the tree.\n", holefrag->ofs, holefrag->ofs + holefrag->size); rb_link_node(&holefrag->rb, NULL, &root->rb_node); } @@ -188,10 +188,10 @@ static int no_overlapping_node(struct jffs2_sb_info *c, struct rb_root *root, /* By definition, the 'this' node has no right-hand child, because there are no frags with offset greater than it. So that's where we want to put new fragment */ - JFFS2_DBG_FRAGTREE2("add the new node at the right\n"); + dbg_fragtree2("add the new node at the right\n"); rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); } else { - JFFS2_DBG_FRAGTREE2("insert the new node at the root of the tree\n"); + dbg_fragtree2("insert the new node at the root of the tree\n"); rb_link_node(&newfrag->rb, NULL, &root->rb_node); } rb_insert_color(&newfrag->rb, root); @@ -209,11 +209,11 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r this = jffs2_lookup_node_frag(root, newfrag->node->ofs); if (this) { - JFFS2_DBG_FRAGTREE2("lookup gave frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", + dbg_fragtree2("lookup gave frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this); lastend = this->ofs + this->size; } else { - JFFS2_DBG_FRAGTREE2("lookup gave no frag\n"); + dbg_fragtree2("lookup gave no frag\n"); lastend = 0; } @@ -235,11 +235,11 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r } if (this->node) - JFFS2_DBG_FRAGTREE2("dealing with frag %u-%u, phys %#08x(%d).\n", + dbg_fragtree2("dealing with frag %u-%u, phys %#08x(%d).\n", this->ofs, this->ofs + this->size, ref_offset(this->node->raw), ref_flags(this->node->raw)); else - JFFS2_DBG_FRAGTREE2("dealing with hole frag %u-%u.\n", + dbg_fragtree2("dealing with hole frag %u-%u.\n", this->ofs, this->ofs + this->size); /* OK. 'this' is pointing at the first frag that newfrag->ofs at least partially obsoletes, @@ -259,10 +259,10 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r struct jffs2_node_frag *newfrag2; if (this->node) - JFFS2_DBG_FRAGTREE2("split old frag 0x%04x-0x%04x, phys 0x%08x\n", + dbg_fragtree2("split old frag 0x%04x-0x%04x, phys 0x%08x\n", this->ofs, this->ofs+this->size, ref_offset(this->node->raw)); else - JFFS2_DBG_FRAGTREE2("split old hole frag 0x%04x-0x%04x\n", + dbg_fragtree2("split old hole frag 0x%04x-0x%04x\n", this->ofs, this->ofs+this->size); /* New second frag pointing to this's node */ @@ -299,13 +299,13 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r } else { /* New frag starts at the same point as 'this' used to. Replace it in the tree without doing a delete and insertion */ - JFFS2_DBG_FRAGTREE2("inserting newfrag (*%p),%d-%d in before 'this' (*%p),%d-%d\n", + dbg_fragtree2("inserting newfrag (*%p),%d-%d in before 'this' (*%p),%d-%d\n", newfrag, newfrag->ofs, newfrag->ofs+newfrag->size, this, this->ofs, this->ofs+this->size); rb_replace_node(&this->rb, &newfrag->rb, root); if (newfrag->ofs + newfrag->size >= this->ofs+this->size) { - JFFS2_DBG_FRAGTREE2("obsoleting node frag %p (%x-%x)\n", this, this->ofs, this->ofs+this->size); + dbg_fragtree2("obsoleting node frag %p (%x-%x)\n", this, this->ofs, this->ofs+this->size); jffs2_obsolete_node_frag(c, this); } else { this->ofs += newfrag->size; @@ -321,7 +321,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r */ while ((this = frag_next(newfrag)) && newfrag->ofs + newfrag->size >= this->ofs + this->size) { /* 'this' frag is obsoleted completely. */ - JFFS2_DBG_FRAGTREE2("obsoleting node frag %p (%x-%x) and removing from tree\n", + dbg_fragtree2("obsoleting node frag %p (%x-%x) and removing from tree\n", this, this->ofs, this->ofs+this->size); rb_erase(&this->rb, root); jffs2_obsolete_node_frag(c, this); @@ -361,7 +361,7 @@ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_in return -ENOMEM; newfrag->node->frags = 1; - JFFS2_DBG_FRAGTREE("adding node %#04x-%#04x @0x%08x on flash, newfrag *%p\n", + dbg_fragtree("adding node %#04x-%#04x @0x%08x on flash, newfrag *%p\n", fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag); ret = jffs2_add_frag_to_fragtree(c, &f->fragtree, newfrag); @@ -410,14 +410,17 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info BUG_ON(tn->csize == 0); + if (!jffs2_is_writebuffered(c)) + goto adj_acc; + /* Calculate how many bytes were already checked */ ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode); - len = ofs & (c->wbuf_pagesize - 1); + len = ofs % c->wbuf_pagesize; if (likely(len)) len = c->wbuf_pagesize - len; if (len >= tn->csize) { - JFFS2_DBG_READINODE("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n", + dbg_readinode("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n", ref_offset(ref), tn->csize, ofs); goto adj_acc; } @@ -425,7 +428,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info ofs += len; len = tn->csize - len; - JFFS2_DBG_READINODE("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.\n", + dbg_readinode("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.\n", ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len); #ifndef __ECOS @@ -520,7 +523,7 @@ static inline int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f if (ref_flags(tn->fn->raw) != REF_UNCHECKED) return 0; - JFFS2_DBG_FRAGTREE2("check node %#04x-%#04x, phys offs %#08x.\n", + dbg_fragtree2("check node %#04x-%#04x, phys offs %#08x.\n", tn->fn->ofs, tn->fn->ofs + tn->fn->size, ref_offset(tn->fn->raw)); ret = check_node_data(c, tn); @@ -528,7 +531,7 @@ static inline int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f JFFS2_ERROR("check_node_data() returned error: %d.\n", ret); } else if (unlikely(ret > 0)) { - JFFS2_DBG_FRAGTREE2("CRC error, mark it obsolete.\n"); + dbg_fragtree2("CRC error, mark it obsolete.\n"); jffs2_mark_node_obsolete(c, tn->fn->raw); } @@ -544,7 +547,7 @@ static inline int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, struct jffs2_node_frag *newfrag, struct jffs2_node_frag *hole) { - JFFS2_DBG_FRAGTREE2("fragment %#04x-%#04x splits the hole %#04x-%#04x\n", + dbg_fragtree2("fragment %#04x-%#04x splits the hole %#04x-%#04x\n", newfrag->ofs, newfrag->ofs + newfrag->size, hole->ofs, hole->ofs + hole->size); if (hole->ofs == newfrag->ofs) { @@ -558,7 +561,7 @@ static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, * the new node. */ - JFFS2_DBG_FRAGTREE2("insert fragment %#04x-%#04x and cut the left part of the hole\n", + dbg_fragtree2("insert fragment %#04x-%#04x and cut the left part of the hole\n", newfrag->ofs, newfrag->ofs + newfrag->size); rb_replace_node(&hole->rb, &newfrag->rb, root); @@ -576,7 +579,7 @@ static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, * Ah, the new fragment is of the same size as the hole. * Relace the hole by it. */ - JFFS2_DBG_FRAGTREE2("insert fragment %#04x-%#04x and overwrite hole\n", + dbg_fragtree2("insert fragment %#04x-%#04x and overwrite hole\n", newfrag->ofs, newfrag->ofs + newfrag->size); rb_replace_node(&hole->rb, &newfrag->rb, root); jffs2_free_node_frag(hole); @@ -598,14 +601,14 @@ static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, } hole->size = newfrag->ofs - hole->ofs; - JFFS2_DBG_FRAGTREE2("left the hole %#04x-%#04x at the left and inserd fragment %#04x-%#04x\n", + dbg_fragtree2("left the hole %#04x-%#04x at the left and inserd fragment %#04x-%#04x\n", hole->ofs, hole->ofs + hole->size, newfrag->ofs, newfrag->ofs + newfrag->size); jffs2_fragtree_insert(newfrag, hole); rb_insert_color(&newfrag->rb, root); if (newfrag2) { - JFFS2_DBG_FRAGTREE2("left the hole %#04x-%#04x at the right\n", + dbg_fragtree2("left the hole %#04x-%#04x at the right\n", newfrag2->ofs, newfrag2->ofs + newfrag2->size); jffs2_fragtree_insert(newfrag2, newfrag); rb_insert_color(&newfrag2->rb, root); @@ -640,12 +643,12 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode int err, checked = 0; int ref_flag; - JFFS2_DBG_FRAGTREE("insert fragment %#04x-%#04x, ver %u\n", fn_ofs, fn_ofs + fn_size, tn->version); + dbg_fragtree("insert fragment %#04x-%#04x, ver %u\n", fn_ofs, fn_ofs + fn_size, tn->version); /* Skip all the nodes which are completed before this one starts */ this = jffs2_lookup_node_frag(root, fn_ofs); if (this) - JFFS2_DBG_FRAGTREE2("'this' found %#04x-%#04x (%s)\n", this->ofs, this->ofs + this->size, this->node ? "data" : "hole"); + dbg_fragtree2("'this' found %#04x-%#04x (%s)\n", this->ofs, this->ofs + this->size, this->node ? "data" : "hole"); if (this) lastend = this->ofs + this->size; @@ -745,7 +748,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode * The new node starts at the same offset as * the hole and supersieds the hole. */ - JFFS2_DBG_FRAGTREE2("add the new fragment instead of hole %#04x-%#04x, refcnt %d\n", + dbg_fragtree2("add the new fragment instead of hole %#04x-%#04x, refcnt %d\n", fn_ofs, fn_ofs + this->ofs + this->size - fn_ofs, fn->frags); rb_replace_node(&this->rb, &newfrag->rb, root); @@ -755,10 +758,10 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode * The hole becomes shorter as its right part * is supersieded by the new fragment. */ - JFFS2_DBG_FRAGTREE2("reduce size of hole %#04x-%#04x to %#04x-%#04x\n", + dbg_fragtree2("reduce size of hole %#04x-%#04x to %#04x-%#04x\n", this->ofs, this->ofs + this->size, this->ofs, this->ofs + this->size - newfrag->size); - JFFS2_DBG_FRAGTREE2("add new fragment %#04x-%#04x, refcnt %d\n", fn_ofs, + dbg_fragtree2("add new fragment %#04x-%#04x, refcnt %d\n", fn_ofs, fn_ofs + this->ofs + this->size - fn_ofs, fn->frags); this->size -= newfrag->size; @@ -771,7 +774,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode this = rb_entry(rb_next(&newfrag->rb), struct jffs2_node_frag, rb); - JFFS2_DBG_FRAGTREE2("switch to the next 'this' fragment: %#04x-%#04x %s\n", + dbg_fragtree2("switch to the next 'this' fragment: %#04x-%#04x %s\n", this->ofs, this->ofs + this->size, this->node ? "(data)" : "(hole)"); } @@ -782,7 +785,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode if (this->ofs + this->size >= fn_ofs + fn_size) { /* The new node is obsolete, drop it */ if (fn->frags == 0) { - JFFS2_DBG_FRAGTREE2("%#04x-%#04x is obsolete, mark it obsolete\n", fn_ofs, fn_ofs + fn_size); + dbg_fragtree2("%#04x-%#04x is obsolete, mark it obsolete\n", fn_ofs, fn_ofs + fn_size); ref_flag = REF_OBSOLETE; } goto out_ok; @@ -790,13 +793,13 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode struct jffs2_node_frag *new_this; /* 'This' node obsoletes the beginning of the new node */ - JFFS2_DBG_FRAGTREE2("the beginning %#04x-%#04x is obsolete\n", fn_ofs, this->ofs + this->size); + dbg_fragtree2("the beginning %#04x-%#04x is obsolete\n", fn_ofs, this->ofs + this->size); ref_flag = REF_NORMAL; fn_size -= this->ofs + this->size - fn_ofs; fn_ofs = this->ofs + this->size; - JFFS2_DBG_FRAGTREE2("now considering %#04x-%#04x\n", fn_ofs, fn_ofs + fn_size); + dbg_fragtree2("now considering %#04x-%#04x\n", fn_ofs, fn_ofs + fn_size); new_this = rb_entry(rb_next(&this->rb), struct jffs2_node_frag, rb); if (!new_this) { @@ -816,14 +819,14 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode if (unlikely(!newfrag)) return -ENOMEM; - JFFS2_DBG_FRAGTREE2("there are no more fragments, insert %#04x-%#04x\n", + dbg_fragtree2("there are no more fragments, insert %#04x-%#04x\n", newfrag->ofs, newfrag->ofs + newfrag->size); rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); rb_insert_color(&newfrag->rb, root); goto out_ok; } else { this = new_this; - JFFS2_DBG_FRAGTREE2("switch to the next 'this' fragment: %#04x-%#04x %s\n", + dbg_fragtree2("switch to the next 'this' fragment: %#04x-%#04x %s\n", this->ofs, this->ofs + this->size, this->node ? "(data)" : "(hole)"); } } @@ -833,13 +836,13 @@ out_ok: BUG_ON(fn->size < PAGE_CACHE_SIZE && ref_flag == REF_PRISTINE); if (ref_flag == REF_OBSOLETE) { - JFFS2_DBG_FRAGTREE2("the node is obsolete now\n"); + dbg_fragtree2("the node is obsolete now\n"); /* jffs2_mark_node_obsolete() will adjust space accounting */ jffs2_mark_node_obsolete(c, fn->raw); return 1; } - JFFS2_DBG_FRAGTREE2("the node is \"%s\" now\n", ref_flag == REF_NORMAL ? "REF_NORMAL" : "REF_PRISTINE"); + dbg_fragtree2("the node is \"%s\" now\n", ref_flag == REF_NORMAL ? "REF_NORMAL" : "REF_PRISTINE"); /* Space accounting was adjusted at check_node_data() */ spin_lock(&c->erase_completion_lock); @@ -885,7 +888,7 @@ void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new if (!new->ino) new->ino = ++c->highest_ino; - JFFS2_DBG_INOCACHE("add %p (ino #%u)\n", new, new->ino); + dbg_inocache("add %p (ino #%u)\n", new, new->ino); prev = &c->inocache_list[new->ino % INOCACHE_HASHSIZE]; @@ -902,7 +905,7 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old) { struct jffs2_inode_cache **prev; - JFFS2_DBG_INOCACHE("del %p (ino #%u)\n", old, old->ino); + dbg_inocache("del %p (ino #%u)\n", old, old->ino); spin_lock(&c->inocache_lock); prev = &c->inocache_list[old->ino % INOCACHE_HASHSIZE]; @@ -965,7 +968,7 @@ struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_ struct jffs2_node_frag *prev = NULL; struct jffs2_node_frag *frag = NULL; - JFFS2_DBG_FRAGTREE2("root %p, offset %d\n", fragtree, offset); + dbg_fragtree2("root %p, offset %d\n", fragtree, offset); next = fragtree->rb_node; @@ -988,10 +991,10 @@ struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_ and return the closest smaller one */ if (prev) - JFFS2_DBG_FRAGTREE2("no match. Returning frag %#04x-%#04x, closest previous\n", + dbg_fragtree2("no match. Returning frag %#04x-%#04x, closest previous\n", prev->ofs, prev->ofs+prev->size); else - JFFS2_DBG_FRAGTREE2("returning NULL, empty fragtree\n"); + dbg_fragtree2("returning NULL, empty fragtree\n"); return prev; } @@ -1006,7 +1009,7 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) if (!root->rb_node) return; - JFFS2_DBG_FRAGTREE("killing\n"); + dbg_fragtree("killing\n"); frag = (rb_entry(root->rb_node, struct jffs2_node_frag, rb)); while(frag) { diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 2cf576ae112..2c938d1bffb 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodemgmt.c,v 1.126 2005/09/16 12:58:17 havasi Exp $ + * $Id: nodemgmt.c,v 1.127 2005/09/20 15:49:12 dedekind Exp $ * */ @@ -273,7 +273,7 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin if (jeb) { reserved_size = PAD(sumsize + c->summary->sum_size + JFFS2_SUMMARY_FRAME_SIZE); - JFFS2_DBG_SUMMARY("minsize=%d , jeb->free=%d ," + dbg_summary("minsize=%d , jeb->free=%d ," "summary->size=%d , sumsize=%d\n", minsize, jeb->free_size, c->summary->sum_size, sumsize); @@ -291,7 +291,7 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin } /* Writing out the collected summary information */ - JFFS2_DBG_SUMMARY("generating summary for 0x%08x.\n", jeb->offset); + dbg_summary("generating summary for 0x%08x.\n", jeb->offset); ret = jffs2_sum_write_sumnode(c); if (ret) diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index e026888cf1c..48ad4202fbb 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: os-linux.h,v 1.61 2005/09/07 08:34:54 havasi Exp $ + * $Id: os-linux.h,v 1.63 2005/09/21 11:55:21 dedekind Exp $ * */ @@ -80,8 +80,8 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) #define jffs2_flash_write(c, ofs, len, retlen, buf) jffs2_flash_direct_write(c, ofs, len, retlen, buf) #define jffs2_flash_read(c, ofs, len, retlen, buf) ((c)->mtd->read((c)->mtd, ofs, len, retlen, buf)) -#define jffs2_flush_wbuf_pad(c) ({ (void)(c), 0; }) -#define jffs2_flush_wbuf_gc(c, i) ({ (void)(c), (void) i, 0; }) +#define jffs2_flush_wbuf_pad(c) ({ do{} while(0); (void)(c), 0; }) +#define jffs2_flush_wbuf_gc(c, i) ({ do{} while(0); (void)(c), (void) i, 0; }) #define jffs2_write_nand_badblock(c,jeb,bad_offset) (1) #define jffs2_nand_flash_setup(c) (0) #define jffs2_nand_flash_cleanup(c) do {} while(0) diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 6f1e4a7ecd9..08f8c5ec611 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.141 2005/08/17 14:57:39 dedekind Exp $ + * $Id: readinode.c,v 1.142 2005/09/20 14:27:34 dedekind Exp $ * */ @@ -97,7 +97,7 @@ static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_r while (ref && ref->next_in_ino) { if (!ref_obsolete(ref)) return ref; - JFFS2_DBG_NODEREF("node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref)); + dbg_noderef("node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref)); ref = ref->next_in_ino; } return NULL; @@ -274,7 +274,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref len = min_t(uint32_t, rdlen - sizeof(*rd), csize); tn->partial_crc = crc32(0, buf, len); - JFFS2_DBG_READINODE("Calculates CRC (%#08x) for %d bytes, csize %d\n", tn->partial_crc, len, csize); + dbg_readinode("Calculates CRC (%#08x) for %d bytes, csize %d\n", tn->partial_crc, len, csize); /* If we actually calculated the whole data CRC * and it is wrong, drop the node. */ @@ -293,7 +293,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref */ struct jffs2_eraseblock *jeb; - JFFS2_DBG_READINODE("the node has no data.\n"); + dbg_readinode("the node has no data.\n"); jeb = &c->blocks[ref->flash_offset / c->sector_size]; len = ref_totlen(c, jeb, ref); @@ -327,7 +327,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref else // normal case... tn->fn->size = je32_to_cpu(rd->dsize); - JFFS2_DBG_READINODE("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n", + dbg_readinode("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n", ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize); jffs2_add_tn_to_tree(tn, tnp); @@ -424,7 +424,7 @@ static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, len = right_size - *rdlen; } - JFFS2_DBG_READINODE("read more %d bytes\n", len); + dbg_readinode("read more %d bytes\n", len); err = jffs2_flash_read(c, offs, len, &retlen, bufstart); if (err) { @@ -461,7 +461,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf *mctime_ver = 0; - JFFS2_DBG_READINODE("ino #%u\n", f->inocache->ino); + dbg_readinode("ino #%u\n", f->inocache->ino); if (jffs2_is_writebuffered(c)) { /* @@ -531,7 +531,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf len = JFFS2_MIN_NODE_HEADER; } - JFFS2_DBG_READINODE("read %d bytes at %#08x(%d).\n", len, ref_offset(ref), ref_flags(ref)); + dbg_readinode("read %d bytes at %#08x(%d).\n", len, ref_offset(ref), ref_flags(ref)); /* FIXME: point() */ err = jffs2_flash_read(c, ref_offset(ref), len, @@ -614,7 +614,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf *fdp = ret_fd; kfree(buf); - JFFS2_DBG_READINODE("nodes of inode #%u were read, the highest version is %u, latest_mctime %u, mctime_ver %u.\n", + dbg_readinode("nodes of inode #%u were read, the highest version is %u, latest_mctime %u, mctime_ver %u.\n", f->inocache->ino, *highest_version, *latest_mctime, *mctime_ver); return 0; @@ -639,7 +639,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, size_t retlen; int ret; - JFFS2_DBG_READINODE("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink); + dbg_readinode("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink); /* Grab all nodes relevant to this ino */ ret = jffs2_get_inode_nodes(c, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver); @@ -659,7 +659,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, tn = rb_entry(rb, struct jffs2_tmp_dnode_info, rb); fn = tn->fn; ret = 1; - JFFS2_DBG_READINODE("consider node ver %u, phys offset " + dbg_readinode("consider node ver %u, phys offset " "%#08x(%d), range %u-%u.\n", tn->version, ref_offset(fn->raw), ref_flags(fn->raw), fn->ofs, fn->ofs + fn->size); @@ -703,7 +703,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, jffs2_free_tmp_dnode_info(tn); if (ret) { - JFFS2_DBG_READINODE("delete dnode %u-%u.\n", + dbg_readinode("delete dnode %u-%u.\n", fn->ofs, fn->ofs + fn->size); jffs2_free_full_dnode(fn); } @@ -803,7 +803,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, } f->target[je32_to_cpu(latest_node->csize)] = '\0'; - JFFS2_DBG_READINODE("symlink's target '%s' cached\n", f->target); + dbg_readinode("symlink's target '%s' cached\n", f->target); } /* fall through... */ @@ -851,7 +851,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t ino, struct jffs2_raw_inode *latest_node) { - JFFS2_DBG_READINODE("read inode #%u\n", ino); + dbg_readinode("read inode #%u\n", ino); retry_inocache: spin_lock(&c->inocache_lock); @@ -870,7 +870,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, /* If it's in either of these states, we need to wait for whoever's got it to finish and put it back. */ - JFFS2_DBG_READINODE("waiting for ino #%u in state %d\n", ino, f->inocache->state); + dbg_readinode("waiting for ino #%u in state %d\n", ino, f->inocache->state); sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); goto retry_inocache; @@ -897,7 +897,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, JFFS2_ERROR("cannot allocate inocache for root inode\n"); return -ENOMEM; } - JFFS2_DBG_READINODE("creating inocache for root inode\n"); + dbg_readinode("creating inocache for root inode\n"); memset(f->inocache, 0, sizeof(struct jffs2_inode_cache)); f->inocache->ino = f->inocache->nlink = 1; f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 4e60ba8da19..8df7456472b 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: scan.c,v 1.122 2005/09/07 08:34:54 havasi Exp $ + * $Id: scan.c,v 1.124 2005/09/21 13:05:22 dedekind Exp $ * */ #include @@ -429,7 +429,7 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo noise = 10; - JFFS2_DBG_SUMMARY("no summary found in jeb 0x%08x. Apply original scan.\n",jeb->offset); + dbg_summary("no summary found in jeb 0x%08x. Apply original scan.\n",jeb->offset); scan_more: while(ofs < jeb->offset + c->sector_size) { @@ -684,7 +684,7 @@ scan_more: if (jffs2_sum_active()) { if (PAD(s->sum_size + JFFS2_SUMMARY_FRAME_SIZE) > jeb->free_size) { - JFFS2_DBG_SUMMARY("There is not enough space for " + dbg_summary("There is not enough space for " "summary information, disabling for this jeb!\n"); jffs2_sum_disable_collecting(s); } @@ -920,76 +920,34 @@ void jffs2_rotate_lists(struct jffs2_sb_info *c) x = count_list(&c->clean_list); if (x) { rotateby = pseudo_random % x; - D1(printk(KERN_DEBUG "Rotating clean_list by %d\n", rotateby)); - rotate_list((&c->clean_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of clean_list is at %08x\n", - list_entry(c->clean_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty clean_list\n")); } x = count_list(&c->very_dirty_list); if (x) { rotateby = pseudo_random % x; - D1(printk(KERN_DEBUG "Rotating very_dirty_list by %d\n", rotateby)); - rotate_list((&c->very_dirty_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of very_dirty_list is at %08x\n", - list_entry(c->very_dirty_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty very_dirty_list\n")); } x = count_list(&c->dirty_list); if (x) { rotateby = pseudo_random % x; - D1(printk(KERN_DEBUG "Rotating dirty_list by %d\n", rotateby)); - rotate_list((&c->dirty_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of dirty_list is at %08x\n", - list_entry(c->dirty_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty dirty_list\n")); } x = count_list(&c->erasable_list); if (x) { rotateby = pseudo_random % x; - D1(printk(KERN_DEBUG "Rotating erasable_list by %d\n", rotateby)); - rotate_list((&c->erasable_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of erasable_list is at %08x\n", - list_entry(c->erasable_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty erasable_list\n")); } if (c->nr_erasing_blocks) { rotateby = pseudo_random % c->nr_erasing_blocks; - D1(printk(KERN_DEBUG "Rotating erase_pending_list by %d\n", rotateby)); - rotate_list((&c->erase_pending_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of erase_pending_list is at %08x\n", - list_entry(c->erase_pending_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty erase_pending_list\n")); } if (c->nr_free_blocks) { rotateby = pseudo_random % c->nr_free_blocks; - D1(printk(KERN_DEBUG "Rotating free_list by %d\n", rotateby)); - rotate_list((&c->free_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of free_list is at %08x\n", - list_entry(c->free_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty free_list\n")); } } diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index cb5dd8f11e7..1ebc81e4477 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c @@ -8,7 +8,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: summary.c,v 1.1 2005/09/07 08:34:54 havasi Exp $ + * $Id: summary.c,v 1.3 2005/09/21 14:43:07 dedekind Exp $ * */ @@ -38,17 +38,18 @@ int jffs2_sum_init(struct jffs2_sb_info *c) if (!c->summary->sum_buf) { JFFS2_WARNING("Can't allocate buffer for writing out summary information!\n"); + kfree(c->summary); return -ENOMEM; } - JFFS2_DBG_SUMMARY("returned succesfully\n"); + dbg_summary("returned succesfully\n"); return 0; } void jffs2_sum_exit(struct jffs2_sb_info *c) { - JFFS2_DBG_SUMMARY("called\n"); + dbg_summary("called\n"); jffs2_sum_disable_collecting(c->summary); @@ -71,13 +72,13 @@ static int jffs2_sum_add_mem(struct jffs2_summary *s, union jffs2_sum_mem *item) case JFFS2_NODETYPE_INODE: s->sum_size += JFFS2_SUMMARY_INODE_SIZE; s->sum_num++; - JFFS2_DBG_SUMMARY("inode (%u) added to summary\n", + dbg_summary("inode (%u) added to summary\n", je32_to_cpu(item->i.inode)); break; case JFFS2_NODETYPE_DIRENT: s->sum_size += JFFS2_SUMMARY_DIRENT_SIZE(item->d.nsize); s->sum_num++; - JFFS2_DBG_SUMMARY("dirent (%u) added to summary\n", + dbg_summary("dirent (%u) added to summary\n", je32_to_cpu(item->d.ino)); break; default: @@ -93,7 +94,7 @@ static int jffs2_sum_add_mem(struct jffs2_summary *s, union jffs2_sum_mem *item) int jffs2_sum_add_padding_mem(struct jffs2_summary *s, uint32_t size) { - JFFS2_DBG_SUMMARY("called with %u\n", size); + dbg_summary("called with %u\n", size); s->sum_padded += size; return 0; } @@ -147,7 +148,7 @@ static void jffs2_sum_clean_collected(struct jffs2_summary *s) union jffs2_sum_mem *temp; if (!s->sum_list_head) { - JFFS2_DBG_SUMMARY("already empty\n"); + dbg_summary("already empty\n"); } while (s->sum_list_head) { temp = s->sum_list_head; @@ -161,14 +162,14 @@ static void jffs2_sum_clean_collected(struct jffs2_summary *s) void jffs2_sum_reset_collected(struct jffs2_summary *s) { - JFFS2_DBG_SUMMARY("called\n"); + dbg_summary("called\n"); jffs2_sum_clean_collected(s); s->sum_size = 0; } void jffs2_sum_disable_collecting(struct jffs2_summary *s) { - JFFS2_DBG_SUMMARY("called\n"); + dbg_summary("called\n"); jffs2_sum_clean_collected(s); s->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; } @@ -182,7 +183,7 @@ int jffs2_sum_is_disabled(struct jffs2_summary *s) void jffs2_sum_move_collected(struct jffs2_sb_info *c, struct jffs2_summary *s) { - JFFS2_DBG_SUMMARY("oldsize=0x%x oldnum=%u => newsize=0x%x newnum=%u\n", + dbg_summary("oldsize=0x%x oldnum=%u => newsize=0x%x newnum=%u\n", c->summary->sum_size, c->summary->sum_num, s->sum_size, s->sum_num); @@ -260,16 +261,16 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs, } case JFFS2_NODETYPE_PADDING: - JFFS2_DBG_SUMMARY("node PADDING\n"); + dbg_summary("node PADDING\n"); c->summary->sum_padded += je32_to_cpu(node->u.totlen); break; case JFFS2_NODETYPE_CLEANMARKER: - JFFS2_DBG_SUMMARY("node CLEANMARKER\n"); + dbg_summary("node CLEANMARKER\n"); break; case JFFS2_NODETYPE_SUMMARY: - JFFS2_DBG_SUMMARY("node SUMMARY\n"); + dbg_summary("node SUMMARY\n"); break; default: @@ -302,7 +303,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras sp = summary->sum; for (i=0; isum_num); i++) { - JFFS2_DBG_SUMMARY("processing summary index %d\n", i); + dbg_summary("processing summary index %d\n", i); switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) { case JFFS2_NODETYPE_INODE: { @@ -311,7 +312,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras ino = je32_to_cpu(spi->inode); - JFFS2_DBG_SUMMARY("Inode at 0x%08x\n", + dbg_summary("Inode at 0x%08x\n", jeb->offset + je32_to_cpu(spi->offset)); raw = jffs2_alloc_raw_node_ref(); @@ -353,7 +354,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras struct jffs2_sum_dirent_flash *spd; spd = sp; - JFFS2_DBG_SUMMARY("Dirent at 0x%08x\n", + dbg_summary("Dirent at 0x%08x\n", jeb->offset + je32_to_cpu(spd->offset)); fd = jffs2_alloc_full_dirent(spd->nsize+1); @@ -434,7 +435,7 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb sumsize = c->sector_size - ofs; ofs += jeb->offset; - JFFS2_DBG_SUMMARY("summary found for 0x%08x at 0x%08x (0x%x bytes)\n", + dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n", jeb->offset, ofs, sumsize); summary = kmalloc(sumsize, GFP_KERNEL); @@ -457,40 +458,40 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb crc = crc32(0, &crcnode, sizeof(crcnode)-4); if (je32_to_cpu(summary->hdr_crc) != crc) { - JFFS2_DBG_SUMMARY("Summary node header is corrupt (bad CRC or " + dbg_summary("Summary node header is corrupt (bad CRC or " "no summary at all)\n"); goto crc_err; } if (je32_to_cpu(summary->totlen) != sumsize) { - JFFS2_DBG_SUMMARY("Summary node is corrupt (wrong erasesize?)\n"); + dbg_summary("Summary node is corrupt (wrong erasesize?)\n"); goto crc_err; } crc = crc32(0, summary, sizeof(struct jffs2_summary_node)-8); if (je32_to_cpu(summary->node_crc) != crc) { - JFFS2_DBG_SUMMARY("Summary node is corrupt (bad CRC)\n"); + dbg_summary("Summary node is corrupt (bad CRC)\n"); goto crc_err; } crc = crc32(0, summary->sum, sumsize - sizeof(struct jffs2_summary_node)); if (je32_to_cpu(summary->sum_crc) != crc) { - JFFS2_DBG_SUMMARY("Summary node data is corrupt (bad CRC)\n"); + dbg_summary("Summary node data is corrupt (bad CRC)\n"); goto crc_err; } if ( je32_to_cpu(summary->cln_mkr) ) { - JFFS2_DBG_SUMMARY("Summary : CLEANMARKER node \n"); + dbg_summary("Summary : CLEANMARKER node \n"); if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) { - JFFS2_DBG_SUMMARY("CLEANMARKER node has totlen 0x%x != normal 0x%x\n", + dbg_summary("CLEANMARKER node has totlen 0x%x != normal 0x%x\n", je32_to_cpu(summary->cln_mkr), c->cleanmarker_size); UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr))); } else if (jeb->first_node) { - JFFS2_DBG_SUMMARY("CLEANMARKER node not first node in block " + dbg_summary("CLEANMARKER node not first node in block " "(0x%08x)\n", jeb->offset); UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr))); } else { @@ -644,7 +645,7 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock vecs[1].iov_base = c->summary->sum_buf; vecs[1].iov_len = datasize; - JFFS2_DBG_SUMMARY("JFFS2: writing out data to flash to pos : 0x%08x\n", + dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x\n", jeb->offset + c->sector_size - jeb->free_size); spin_unlock(&c->erase_completion_lock); @@ -674,7 +675,7 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) int datasize, infosize, padsize, ret; struct jffs2_eraseblock *jeb; - JFFS2_DBG_SUMMARY("called\n"); + dbg_summary("called\n"); jeb = c->nextblock; diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 86860dbc670..11e05bc014f 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -9,7 +9,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: wbuf.c,v 1.98 2005/09/07 08:34:55 havasi Exp $ + * $Id: wbuf.c,v 1.99 2005/09/21 16:11:04 dedekind Exp $ * */ @@ -33,9 +33,6 @@ static unsigned char *brokenbuf; /* max. erase failures before we mark a block bad */ #define MAX_ERASE_FAILURES 2 -/* two seconds timeout for timed wbuf-flushing */ -#define WBUF_FLUSH_TIMEOUT 2 * HZ - struct jffs2_inodirty { uint32_t ino; struct jffs2_inodirty *next; diff --git a/include/linux/jffs2_fs_sb.h b/include/linux/jffs2_fs_sb.h index 5087612ed9a..fdc445b49e1 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.53 2005/09/07 08:34:56 havasi Exp $ */ +/* $Id: jffs2_fs_sb.h,v 1.54 2005/09/21 13:37:34 dedekind Exp $ */ #ifndef _JFFS2_FS_SB #define _JFFS2_FS_SB @@ -95,12 +95,13 @@ struct jffs2_sb_info { to an obsoleted node. I don't like this. Alternatives welcomed. */ struct semaphore erase_free_sem; + uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */ + #ifdef CONFIG_JFFS2_FS_WRITEBUFFER /* Write-behind buffer for NAND flash */ unsigned char *wbuf; uint32_t wbuf_ofs; uint32_t wbuf_len; - uint32_t wbuf_pagesize; struct jffs2_inodirty *wbuf_inodes; struct rw_semaphore wbuf_sem; /* Protects the write buffer */ -- cgit v1.2.3 From ef6f0d1ffcd86484e01cec4fd2d2c5ca5887a43b Mon Sep 17 00:00:00 2001 From: Pete Popov Date: Fri, 23 Sep 2005 02:44:58 +0100 Subject: [MTD] NAND: Alchemy board driver cleanup - cleaned up the partitions and include files - added more flexible CS and address detection and setup Regression tested on db1200 and db1550. Signed-off-by: Pete Popov Signed-off-by: Thomas Gleixner --- drivers/mtd/nand/Kconfig | 6 +-- drivers/mtd/nand/au1550nd.c | 115 ++++++++++++++++++++++++++------------------ 2 files changed, 72 insertions(+), 49 deletions(-) diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 36d34e5e5a5..435739d4b29 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -1,5 +1,5 @@ # drivers/mtd/nand/Kconfig -# $Id: Kconfig,v 1.31 2005/06/20 12:03:21 bjd Exp $ +# $Id: Kconfig,v 1.34 2005/09/23 01:44:55 ppopov Exp $ menu "NAND Flash Device Drivers" depends on MTD!=n @@ -59,8 +59,8 @@ config MTD_NAND_IDS tristate config MTD_NAND_AU1550 - tristate "Au1550 NAND support" - depends on SOC_AU1550 && MTD_NAND + tristate "Au1550/1200 NAND support" + depends on (SOC_AU1200 || SOC_AU1550) && MTD_NAND help This enables the driver for the NAND flash controller on the AMD/Alchemy 1550 SOC. diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 4c7719ce3f4..953daf379b9 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c @@ -3,7 +3,7 @@ * * Copyright (C) 2004 Embedded Edge, LLC * - * $Id: au1550nd.c,v 1.11 2004/11/04 12:53:10 gleixner Exp $ + * $Id: au1550nd.c,v 1.12 2005/09/23 01:44:55 ppopov Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -21,13 +21,7 @@ /* fixme: this is ugly */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 0) -#include -#ifdef CONFIG_MIPS_PB1550 -#include -#endif -#ifdef CONFIG_MIPS_DB1550 -#include -#endif +#include #else #include #ifdef CONFIG_MIPS_PB1550 @@ -45,39 +39,22 @@ static struct mtd_info *au1550_mtd = NULL; static void __iomem *p_nand; static int nand_width = 1; /* default x8*/ -#define NAND_CS 1 - /* * Define partitions for flash device */ const static struct mtd_partition partition_info[] = { -#ifdef CONFIG_MIPS_PB1550 -#define NUM_PARTITIONS 2 - { - .name = "Pb1550 NAND FS 0", - .offset = 0, - .size = 8*1024*1024 - }, - { - .name = "Pb1550 NAND FS 1", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL - } -#endif -#ifdef CONFIG_MIPS_DB1550 -#define NUM_PARTITIONS 2 { - .name = "Db1550 NAND FS 0", + .name = "NAND FS 0", .offset = 0, - .size = 8*1024*1024 + .size = 8*1024*1024 }, { - .name = "Db1550 NAND FS 1", + .name = "NAND FS 1", .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL + .size = MTDPART_SIZ_FULL } -#endif }; +#define NB_OF(x) (sizeof(x)/sizeof(x[0])) /** @@ -339,11 +316,13 @@ int au1550_device_ready(struct mtd_info *mtd) /* * Main initialization routine */ -int __init au1550_init (void) +int __init au1xxx_nand_init (void) { struct nand_chip *this; u16 boot_swapboot = 0; /* default value */ int retval; + u32 mem_staddr; + u32 nand_phys; /* Allocate memory for MTD device structure and private data */ au1550_mtd = kmalloc (sizeof(struct mtd_info) + @@ -364,8 +343,11 @@ int __init au1550_init (void) au1550_mtd->priv = this; - /* MEM_STNDCTL: disable ints, disable nand boot */ - au_writel(0, MEM_STNDCTL); + /* disable interrupts */ + au_writel(au_readl(MEM_STNDCTL) & ~(1<<8), MEM_STNDCTL); + + /* disable NAND boot */ + au_writel(au_readl(MEM_STNDCTL) & ~(1<<0), MEM_STNDCTL); #ifdef CONFIG_MIPS_PB1550 /* set gpio206 high */ @@ -397,19 +379,60 @@ int __init au1550_init (void) } #endif - /* Configure RCE1 - should be done by YAMON */ - au_writel(0x5 | (nand_width << 22), 0xB4001010); /* MEM_STCFG1 */ - au_writel(NAND_TIMING, 0xB4001014); /* MEM_STTIME1 */ - au_sync(); + /* Configure chip-select; normally done by boot code, e.g. YAMON */ +#ifdef NAND_STCFG + if (NAND_CS == 0) { + au_writel(NAND_STCFG, MEM_STCFG0); + au_writel(NAND_STTIME, MEM_STTIME0); + au_writel(NAND_STADDR, MEM_STADDR0); + } + if (NAND_CS == 1) { + au_writel(NAND_STCFG, MEM_STCFG1); + au_writel(NAND_STTIME, MEM_STTIME1); + au_writel(NAND_STADDR, MEM_STADDR1); + } + if (NAND_CS == 2) { + au_writel(NAND_STCFG, MEM_STCFG2); + au_writel(NAND_STTIME, MEM_STTIME2); + au_writel(NAND_STADDR, MEM_STADDR2); + } + if (NAND_CS == 3) { + au_writel(NAND_STCFG, MEM_STCFG3); + au_writel(NAND_STTIME, MEM_STTIME3); + au_writel(NAND_STADDR, MEM_STADDR3); + } +#endif + + /* Locate NAND chip-select in order to determine NAND phys address */ + mem_staddr = 0x00000000; + if (((au_readl(MEM_STCFG0) & 0x7) == 0x5) && (NAND_CS == 0)) + mem_staddr = au_readl(MEM_STADDR0); + else if (((au_readl(MEM_STCFG1) & 0x7) == 0x5) && (NAND_CS == 1)) + mem_staddr = au_readl(MEM_STADDR1); + else if (((au_readl(MEM_STCFG2) & 0x7) == 0x5) && (NAND_CS == 2)) + mem_staddr = au_readl(MEM_STADDR2); + else if (((au_readl(MEM_STCFG3) & 0x7) == 0x5) && (NAND_CS == 3)) + mem_staddr = au_readl(MEM_STADDR3); + + if (mem_staddr == 0x00000000) { + printk("Au1xxx NAND: ERROR WITH NAND CHIP-SELECT\n"); + kfree(au1550_mtd); + return 1; + } + nand_phys = (mem_staddr << 4) & 0xFFFC0000; - /* setup and enable chip select, MEM_STADDR1 */ - /* we really need to decode offsets only up till 0x20 */ - au_writel((1<<28) | (NAND_PHYS_ADDR>>4) | - (((NAND_PHYS_ADDR + 0x1000)-1) & (0x3fff<<18)>>18), - MEM_STADDR1); - au_sync(); + p_nand = (void __iomem *)ioremap(nand_phys, 0x1000); + + /* make controller and MTD agree */ + if (NAND_CS == 0) + nand_width = au_readl(MEM_STCFG0) & (1<<22); + if (NAND_CS == 1) + nand_width = au_readl(MEM_STCFG1) & (1<<22); + if (NAND_CS == 2) + nand_width = au_readl(MEM_STCFG2) & (1<<22); + if (NAND_CS == 3) + nand_width = au_readl(MEM_STCFG3) & (1<<22); - p_nand = ioremap(NAND_PHYS_ADDR, 0x1000); /* Set address of hardware control function */ this->hwcontrol = au1550_hwcontrol; @@ -438,7 +461,7 @@ int __init au1550_init (void) } /* Register the partitions */ - add_mtd_partitions(au1550_mtd, partition_info, NUM_PARTITIONS); + add_mtd_partitions(au1550_mtd, partition_info, NB_OF(partition_info)); return 0; @@ -450,7 +473,7 @@ int __init au1550_init (void) return retval; } -module_init(au1550_init); +module_init(au1xxx_nand_init); /* * Clean up routine -- cgit v1.2.3 From 2bc9764c4837c6b7da540b7a2592ec02f9a14e47 Mon Sep 17 00:00:00 2001 From: Ferenc Havasi Date: Mon, 26 Sep 2005 12:37:25 +0100 Subject: [JFFS2] Rename jffs2_summary_node to jffs2_raw_summary Signed-off-by: Ferenc Havasi Signed-off-by: Thomas Gleixner --- fs/jffs2/summary.c | 14 +++++++------- fs/jffs2/summary.h | 4 ++-- include/linux/jffs2.h | 12 +++++++----- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index 1ebc81e4477..308251266c6 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c @@ -8,7 +8,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: summary.c,v 1.3 2005/09/21 14:43:07 dedekind Exp $ + * $Id: summary.c,v 1.4 2005/09/26 11:37:21 havasi Exp $ * */ @@ -292,7 +292,7 @@ no_mem: /* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_summary_node *summary, uint32_t *pseudo_random) + struct jffs2_raw_summary *summary, uint32_t *pseudo_random) { struct jffs2_raw_node_ref *raw; struct jffs2_inode_cache *ic; @@ -428,7 +428,7 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb { struct jffs2_unknown_node crcnode; struct jffs2_raw_node_ref *cache_ref; - struct jffs2_summary_node *summary; + struct jffs2_raw_summary *summary; int ret, sumsize; uint32_t crc; @@ -468,14 +468,14 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb goto crc_err; } - crc = crc32(0, summary, sizeof(struct jffs2_summary_node)-8); + crc = crc32(0, summary, sizeof(struct jffs2_raw_summary)-8); if (je32_to_cpu(summary->node_crc) != crc) { dbg_summary("Summary node is corrupt (bad CRC)\n"); goto crc_err; } - crc = crc32(0, summary->sum, sumsize - sizeof(struct jffs2_summary_node)); + crc = crc32(0, summary->sum, sumsize - sizeof(struct jffs2_raw_summary)); if (je32_to_cpu(summary->sum_crc) != crc) { dbg_summary("Summary node data is corrupt (bad CRC)\n"); @@ -560,7 +560,7 @@ crc_err: static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t infosize, uint32_t datasize, int padsize) { - struct jffs2_summary_node isum; + struct jffs2_raw_summary isum; union jffs2_sum_mem *temp; struct jffs2_sum_marker *sm; struct kvec vecs[2]; @@ -685,7 +685,7 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) } datasize = c->summary->sum_size + sizeof(struct jffs2_sum_marker); - infosize = sizeof(struct jffs2_summary_node) + datasize; + infosize = sizeof(struct jffs2_raw_summary) + datasize; padsize = jeb->free_size - infosize; infosize += padsize; datasize += padsize; diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h index e6b0a69acbd..b7a678be170 100644 --- a/fs/jffs2/summary.h +++ b/fs/jffs2/summary.h @@ -8,7 +8,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: summary.h,v 1.1 2005/09/07 08:34:54 havasi Exp $ + * $Id: summary.h,v 1.2 2005/09/26 11:37:21 havasi Exp $ * */ @@ -142,7 +142,7 @@ struct jffs2_sum_marker jint32_t magic; /* == JFFS2_SUM_MAGIC */ }; -#define JFFS2_SUMMARY_FRAME_SIZE (sizeof(struct jffs2_summary_node) + sizeof(struct jffs2_sum_marker)) +#define JFFS2_SUMMARY_FRAME_SIZE (sizeof(struct jffs2_raw_summary) + sizeof(struct jffs2_sum_marker)) #ifdef CONFIG_JFFS2_SUMMARY /* SUMMARY SUPPORT ENABLED */ diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h index acb51a3669a..2788880368c 100644 --- a/include/linux/jffs2.h +++ b/include/linux/jffs2.h @@ -8,7 +8,7 @@ * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * - * $Id: jffs2.h,v 1.37 2005/09/07 08:34:55 havasi Exp $ + * $Id: jffs2.h,v 1.38 2005/09/26 11:37:23 havasi Exp $ * */ @@ -151,9 +151,10 @@ struct jffs2_raw_inode uint8_t data[0]; } __attribute__((packed)); -struct jffs2_summary_node{ +struct jffs2_raw_summary +{ jint16_t magic; - jint16_t nodetype; /* = JFFS2_NODETYPE_INODE_SUM */ + jint16_t nodetype; /* = JFFS2_NODETYPE_SUMMARY */ jint32_t totlen; jint32_t hdr_crc; jint32_t sum_num; /* number of sum entries*/ @@ -164,11 +165,12 @@ struct jffs2_summary_node{ jint32_t sum[0]; /* inode summary info */ } __attribute__((packed)); -union jffs2_node_union { +union jffs2_node_union +{ struct jffs2_raw_inode i; struct jffs2_raw_dirent d; + struct jffs2_raw_summary s; struct jffs2_unknown_node u; - struct jffs2_summary_node s; }; #endif /* __LINUX_JFFS2_H__ */ -- cgit v1.2.3 From 0255fc1b081cf92b56dfe5e1f3a824d050326614 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 26 Sep 2005 22:42:57 +0100 Subject: [MTD] NAND: s3c2410 use dev_err() to report errors instead of printk() Signed-off-by: Ben Dooks Signed-off-by: Thomas Gleixner --- drivers/mtd/nand/s3c2410.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 2df5e47d1f5..44989c8b5f7 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -18,7 +18,7 @@ * 20-Jun-2005 BJD Updated s3c2440 support, fixed timing bug * 08-Jul-2005 BJD Fix OOPS when no platform data supplied * - * $Id: s3c2410.c,v 1.14 2005/07/06 20:05:06 bjd Exp $ + * $Id: s3c2410.c,v 1.15 2005/09/26 21:42:54 bjd Exp $ * * 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 @@ -576,7 +576,7 @@ static int s3c24xx_nand_probe(struct device *dev, int is_s3c2440) info = kmalloc(sizeof(*info), GFP_KERNEL); if (info == NULL) { - printk(KERN_ERR PFX "no memory for flash info\n"); + dev_err("no memory for flash info\n"); err = -ENOMEM; goto exit_error; } @@ -591,7 +591,7 @@ static int s3c24xx_nand_probe(struct device *dev, int is_s3c2440) info->clk = clk_get(dev, "nand"); if (IS_ERR(info->clk)) { - printk(KERN_ERR PFX "failed to get clock"); + dev_err(dev, "failed to get clock"); err = -ENOENT; goto exit_error; } @@ -608,7 +608,7 @@ static int s3c24xx_nand_probe(struct device *dev, int is_s3c2440) info->area = request_mem_region(res->start, size, pdev->name); if (info->area == NULL) { - printk(KERN_ERR PFX "cannot reserve register region\n"); + dev_err(dev, "cannot reserve register region\n"); err = -ENOENT; goto exit_error; } @@ -619,12 +619,12 @@ static int s3c24xx_nand_probe(struct device *dev, int is_s3c2440) info->is_s3c2440 = is_s3c2440; if (info->regs == NULL) { - printk(KERN_ERR PFX "cannot reserve register region\n"); + dev_err(dev, "cannot reserve register region\n"); err = -EIO; goto exit_error; } - printk(KERN_INFO PFX "mapped registers at %p\n", info->regs); + dev_dbg(dev, "mapped registers at %p\n", info->regs); /* initialise the hardware */ @@ -642,7 +642,7 @@ static int s3c24xx_nand_probe(struct device *dev, int is_s3c2440) size = nr_sets * sizeof(*info->mtds); info->mtds = kmalloc(size, GFP_KERNEL); if (info->mtds == NULL) { - printk(KERN_ERR PFX "failed to allocate mtd storage\n"); + dev_err(dev, "failed to allocate mtd storage\n"); err = -ENOMEM; goto exit_error; } -- cgit v1.2.3 From 87590e26ff4e7d57dfdaa81780b1b0d9e9970a4c Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Tue, 27 Sep 2005 11:26:39 +0100 Subject: [MTD] OneNAND: Add missing files Simple bad block table source and header files Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/onenand_bbt.c | 246 ++++++++++++++++++++++++++++++++++++++ include/linux/mtd/bbm.h | 122 +++++++++++++++++++ 2 files changed, 368 insertions(+) create mode 100644 drivers/mtd/onenand/onenand_bbt.c create mode 100644 include/linux/mtd/bbm.h diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c new file mode 100644 index 00000000000..f40190f499e --- /dev/null +++ b/drivers/mtd/onenand/onenand_bbt.c @@ -0,0 +1,246 @@ +/* + * linux/drivers/mtd/onenand/onenand_bbt.c + * + * Bad Block Table support for the OneNAND driver + * + * Copyright(c) 2005 Samsung Electronics + * Kyungmin Park + * + * Derived from nand_bbt.c + * + * TODO: + * Split BBT core and chip specific BBT. + */ + +#include +#include +#include +#include + +/** + * check_short_pattern - [GENERIC] check if a pattern is in the buffer + * @param buf the buffer to search + * @param len the length of buffer to search + * @param paglen the pagelength + * @param td search pattern descriptor + * + * Check for a pattern at the given place. Used to search bad block + * tables and good / bad block identifiers. Same as check_pattern, but + * no optional empty check and the pattern is expected to start + * at offset 0. + * + */ +static int check_short_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td) +{ + int i; + uint8_t *p = buf; + + /* Compare the pattern */ + for (i = 0; i < td->len; i++) { + if (p[i] != td->pattern[i]) + return -1; + } + return 0; +} + +/** + * create_bbt - [GENERIC] Create a bad block table by scanning the device + * @param mtd MTD device structure + * @param buf temporary buffer + * @param bd descriptor for the good/bad block search pattern + * @param chip create the table for a specific chip, -1 read all chips. + * Applies only if NAND_BBT_PERCHIP option is set + * + * Create a bad block table by scanning the device + * for the given good/bad block identify pattern + */ +static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip) +{ + struct onenand_chip *this = mtd->priv; + struct bbm_info *bbm = this->bbm; + int i, j, numblocks, len, scanlen; + int startblock; + loff_t from; + size_t readlen, ooblen; + + printk(KERN_INFO "Scanning device for bad blocks\n"); + + len = 1; + + /* We need only read few bytes from the OOB area */ + scanlen = ooblen = 0; + readlen = bd->len; + + /* chip == -1 case only */ + /* Note that numblocks is 2 * (real numblocks) here; + * see i += 2 below as it makses shifting and masking less painful + */ + numblocks = mtd->size >> (bbm->bbt_erase_shift - 1); + startblock = 0; + from = 0; + + for (i = startblock; i < numblocks; ) { + int ret; + + for (j = 0; j < len; j++) { + size_t retlen; + + /* No need to read pages fully, + * just read required OOB bytes */ + ret = mtd->read_oob(mtd, from + j * mtd->oobblock + bd->offs, + readlen, &retlen, &buf[0]); + + if (ret) + return ret; + + if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->oobblock, bd)) { + bbm->bbt[i >> 3] |= 0x03 << (i & 0x6); + printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n", + i >> 1, (unsigned int) from); + break; + } + } + i += 2; + from += (1 << bbm->bbt_erase_shift); + } + + return 0; +} + + +/** + * onenand_memory_bbt - [GENERIC] create a memory based bad block table + * @param mtd MTD device structure + * @param bd descriptor for the good/bad block search pattern + * + * The function creates a memory based bbt by scanning the device + * for manufacturer / software marked good / bad blocks + */ +static inline int onenand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) +{ + unsigned char data_buf[MAX_ONENAND_PAGESIZE]; + + bd->options &= ~NAND_BBT_SCANEMPTY; + return create_bbt(mtd, data_buf, bd, -1); +} + +/** + * onenand_isbad_bbt - [OneNAND Interface] Check if a block is bad + * @param mtd MTD device structure + * @param offs offset in the device + * @param allowbbt allow access to bad block table region + */ +static int onenand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) +{ + struct onenand_chip *this = mtd->priv; + struct bbm_info *bbm = this->bbm; + int block; + uint8_t res; + + /* Get block number * 2 */ + block = (int) (offs >> (bbm->bbt_erase_shift - 1)); + res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03; + + DEBUG(MTD_DEBUG_LEVEL2, "onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n", + (unsigned int) offs, block >> 1, res); + + switch ((int) res) { + case 0x00: return 0; + case 0x01: return 1; + case 0x02: return allowbbt ? 0 : 1; + } + + return 1; +} + +/** + * onenand_scan_bbt - [OneNAND Interface] scan, find, read and maybe create bad block table(s) + * @param mtd MTD device structure + * @param bd descriptor for the good/bad block search pattern + * + * The function checks, if a bad block table(s) is/are already + * available. If not it scans the device for manufacturer + * marked good / bad blocks and writes the bad block table(s) to + * the selected place. + * + * The bad block table memory is allocated here. It must be freed + * by calling the onenand_free_bbt function. + * + */ +int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) +{ + struct onenand_chip *this = mtd->priv; + struct bbm_info *bbm = this->bbm; + int len, ret = 0; + + len = mtd->size >> (this->erase_shift + 2); + /* Allocate memory (2bit per block) */ + bbm->bbt = kmalloc(len, GFP_KERNEL); + if (!bbm->bbt) { + printk(KERN_ERR "onenand_scan_bbt: Out of memory\n"); + return -ENOMEM; + } + /* Clear the memory bad block table */ + memset(bbm->bbt, 0x00, len); + + /* Set the bad block position */ + bbm->badblockpos = ONENAND_BADBLOCK_POS; + + /* Set erase shift */ + bbm->bbt_erase_shift = this->erase_shift; + + if (!bbm->isbad_bbt) + bbm->isbad_bbt = onenand_isbad_bbt; + + /* Scan the device to build a memory based bad block table */ + if ((ret = onenand_memory_bbt(mtd, bd))) { + printk(KERN_ERR "onenand_scan_bbt: Can't scan flash and build the RAM-based BBT\n"); + kfree(bbm->bbt); + bbm->bbt = NULL; + } + + return ret; +} + +/* + * Define some generic bad / good block scan pattern which are used + * while scanning a device for factory marked good / bad blocks. + */ +static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; + +static struct nand_bbt_descr largepage_memorybased = { + .options = 0, + .offs = 0, + .len = 2, + .pattern = scan_ff_pattern, +}; + +/** + * onenand_default_bbt - [OneNAND Interface] Select a default bad block table for the device + * @param mtd MTD device structure + * + * This function selects the default bad block table + * support for the device and calls the onenand_scan_bbt function + */ +int onenand_default_bbt(struct mtd_info *mtd) +{ + struct onenand_chip *this = mtd->priv; + struct bbm_info *bbm; + + this->bbm = kmalloc(sizeof(struct bbm_info), GFP_KERNEL); + if (!this->bbm) + return -ENOMEM; + + bbm = this->bbm; + + memset(bbm, 0, sizeof(struct bbm_info)); + + /* 1KB page has same configuration as 2KB page */ + if (!bbm->badblock_pattern) + bbm->badblock_pattern = &largepage_memorybased; + + return onenand_scan_bbt(mtd, bbm->badblock_pattern); +} + +EXPORT_SYMBOL(onenand_scan_bbt); +EXPORT_SYMBOL(onenand_default_bbt); diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h new file mode 100644 index 00000000000..92b42cb7ed2 --- /dev/null +++ b/include/linux/mtd/bbm.h @@ -0,0 +1,122 @@ +/* + * linux/include/linux/mtd/bbm.h + * + * NAND family Bad Block Management (BBM) header file + * - Bad Block Table (BBT) implementation + * + * Copyright (c) 2005 Samsung Electronics + * Kyungmin Park + * + * Copyright (c) 2000-2005 + * Thomas Gleixner + * + */ +#ifndef __LINUX_MTD_BBM_H +#define __LINUX_MTD_BBM_H + +/* The maximum number of NAND chips in an array */ +#define NAND_MAX_CHIPS 8 + +/** + * struct nand_bbt_descr - bad block table descriptor + * @param options options for this descriptor + * @param pages the page(s) where we find the bbt, used with + * option BBT_ABSPAGE when bbt is searched, + * then we store the found bbts pages here. + * Its an array and supports up to 8 chips now + * @param offs offset of the pattern in the oob area of the page + * @param veroffs offset of the bbt version counter in the oob are of the page + * @param version version read from the bbt page during scan + * @param len length of the pattern, if 0 no pattern check is performed + * @param maxblocks maximum number of blocks to search for a bbt. This number of + * blocks is reserved at the end of the device + * where the tables are written. + * @param reserved_block_code if non-0, this pattern denotes a reserved + * (rather than bad) block in the stored bbt + * @param pattern pattern to identify bad block table or factory marked + * good / bad blocks, can be NULL, if len = 0 + * + * Descriptor for the bad block table marker and the descriptor for the + * pattern which identifies good and bad blocks. The assumption is made + * that the pattern and the version count are always located in the oob area + * of the first block. + */ +struct nand_bbt_descr { + int options; + int pages[NAND_MAX_CHIPS]; + int offs; + int veroffs; + uint8_t version[NAND_MAX_CHIPS]; + int len; + int maxblocks; + int reserved_block_code; + uint8_t *pattern; +}; + +/* Options for the bad block table descriptors */ + +/* The number of bits used per block in the bbt on the device */ +#define NAND_BBT_NRBITS_MSK 0x0000000F +#define NAND_BBT_1BIT 0x00000001 +#define NAND_BBT_2BIT 0x00000002 +#define NAND_BBT_4BIT 0x00000004 +#define NAND_BBT_8BIT 0x00000008 +/* The bad block table is in the last good block of the device */ +#define NAND_BBT_LASTBLOCK 0x00000010 +/* The bbt is at the given page, else we must scan for the bbt */ +#define NAND_BBT_ABSPAGE 0x00000020 +/* The bbt is at the given page, else we must scan for the bbt */ +#define NAND_BBT_SEARCH 0x00000040 +/* bbt is stored per chip on multichip devices */ +#define NAND_BBT_PERCHIP 0x00000080 +/* bbt has a version counter at offset veroffs */ +#define NAND_BBT_VERSION 0x00000100 +/* Create a bbt if none axists */ +#define NAND_BBT_CREATE 0x00000200 +/* Search good / bad pattern through all pages of a block */ +#define NAND_BBT_SCANALLPAGES 0x00000400 +/* Scan block empty during good / bad block scan */ +#define NAND_BBT_SCANEMPTY 0x00000800 +/* Write bbt if neccecary */ +#define NAND_BBT_WRITE 0x00001000 +/* Read and write back block contents when writing bbt */ +#define NAND_BBT_SAVECONTENT 0x00002000 +/* Search good / bad pattern on the first and the second page */ +#define NAND_BBT_SCAN2NDPAGE 0x00004000 + +/* The maximum number of blocks to scan for a bbt */ +#define NAND_BBT_SCAN_MAXBLOCKS 4 + +/* + * Constants for oob configuration + */ +#define ONENAND_BADBLOCK_POS 0 + +/** + * struct bbt_info - [GENERIC] Bad Block Table data structure + * @param bbt_erase_shift [INTERN] number of address bits in a bbt entry + * @param badblockpos [INTERN] position of the bad block marker in the oob area + * @param bbt [INTERN] bad block table pointer + * @param badblock_pattern [REPLACEABLE] bad block scan pattern used for initial bad block scan + * @param priv [OPTIONAL] pointer to private bbm date + */ +struct bbm_info { + int bbt_erase_shift; + int badblockpos; + int options; + + uint8_t *bbt; + + int (*isbad_bbt)(struct mtd_info *mtd, loff_t ofs, int allowbbt); + + /* TODO Add more NAND specific fileds */ + struct nand_bbt_descr *badblock_pattern; + + void *priv; +}; + +/* OneNAND BBT interface */ +extern int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd); +extern int onenand_default_bbt(struct mtd_info *mtd); + +#endif /* __LINUX_MTD_BBM_H */ -- cgit v1.2.3 From 2f0077e01822424c4f73aa838a063a5b0193d533 Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Tue, 27 Sep 2005 14:17:32 +0100 Subject: [JFFS2] Remove stale comment Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/fs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index c15c3022047..b0b96d7272d 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: fs.c,v 1.65 2005/09/07 08:34:54 havasi Exp $ + * $Id: fs.c,v 1.66 2005/09/27 13:17:29 dedekind Exp $ * */ @@ -476,7 +476,6 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) } c->cleanmarker_size = sizeof(struct jffs2_unknown_node); - /* Joern -- stick alignment for weird 8-byte-page flash here */ /* NAND (or other bizarre) flash... do setup accordingly */ ret = jffs2_flash_setup(c); -- cgit v1.2.3 From 1555972231f3202f00e04f7c42d2db858e11b874 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 6 Nov 2005 21:41:08 +0000 Subject: [ARM] Fix /proc/cpuinfo format for ARM SMP glibc expects to count lines beginning with "processor" to determine the number of processors, not lines beginning with "Processor". So, give glibc the format it expects. Signed-off-by: Russell King --- arch/arm/kernel/setup.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index a6d7fb81330..85774165e9f 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -839,7 +839,12 @@ static int c_show(struct seq_file *m, void *v) #if defined(CONFIG_SMP) for_each_online_cpu(i) { - seq_printf(m, "Processor\t: %d\n", i); + /* + * glibc reads /proc/cpuinfo to determine the number of + * online processors, looking for lines beginning with + * "processor". Give glibc what it expects. + */ + seq_printf(m, "processor\t: %d\n", i); seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n", per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ), (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100); -- cgit v1.2.3 From d55849aa4d219b734795862692cc6981af848357 Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Tue, 27 Sep 2005 14:40:52 +0100 Subject: [JFFS2] Use memset(struct) instead of nulling struct members one by one Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/build.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index ac393b3d6ea..af6d2ec0136 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: build.c,v 1.83 2005/09/21 15:52:33 dedekind Exp $ + * $Id: build.c,v 1.84 2005/09/27 13:40:49 dedekind Exp $ * */ @@ -309,28 +309,25 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) { int ret; int i; + int size; c->free_size = c->flash_size; c->nr_blocks = c->flash_size / c->sector_size; + size = sizeof(struct jffs2_eraseblock) * c->nr_blocks; #ifndef __ECOS if (jffs2_blocks_use_vmalloc(c)) - c->blocks = vmalloc(sizeof(struct jffs2_eraseblock) * c->nr_blocks); + c->blocks = vmalloc(size); else #endif - c->blocks = kmalloc(sizeof(struct jffs2_eraseblock) * c->nr_blocks, GFP_KERNEL); + c->blocks = kmalloc(size, GFP_KERNEL); if (!c->blocks) return -ENOMEM; + + memset(c->blocks, 0, size); for (i=0; inr_blocks; i++) { INIT_LIST_HEAD(&c->blocks[i].list); c->blocks[i].offset = i * c->sector_size; c->blocks[i].free_size = c->sector_size; - c->blocks[i].dirty_size = 0; - c->blocks[i].wasted_size = 0; - c->blocks[i].unchecked_size = 0; - c->blocks[i].used_size = 0; - c->blocks[i].first_node = NULL; - c->blocks[i].last_node = NULL; - c->blocks[i].bad_count = 0; } INIT_LIST_HEAD(&c->clean_list); -- cgit v1.2.3 From a41371eb6d9b368e53867cd85156f07371e9f72f Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Thu, 29 Sep 2005 03:55:31 +0100 Subject: [MTD] OneNAND: Power Management (PM) support Add suspend/resume Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/onenand_base.c | 36 +++++++++++++++++++++++++++++++++--- include/linux/mtd/onenand.h | 1 + 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 75d75788269..a002d4025b2 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -505,7 +505,7 @@ static int onenand_update_bufferram(struct mtd_info *mtd, loff_t addr, * * Get the device and lock it for exclusive access */ -static void onenand_get_device(struct mtd_info *mtd, int new_state) +static int onenand_get_device(struct mtd_info *mtd, int new_state) { struct onenand_chip *this = mtd->priv; DECLARE_WAITQUEUE(wait, current); @@ -520,12 +520,18 @@ static void onenand_get_device(struct mtd_info *mtd, int new_state) spin_unlock(&this->chip_lock); break; } + if (new_state == FL_PM_SUSPENDED) { + spin_unlock(&this->chip_lock); + return (this->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN; + } set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&this->wq, &wait); spin_unlock(&this->chip_lock); schedule(); remove_wait_queue(&this->wq, &wait); } + + return 0; } /** @@ -1440,6 +1446,30 @@ static int onenand_probe(struct mtd_info *mtd) return 0; } +/** + * onenand_suspend - [MTD Interface] Suspend the OneNAND flash + * @param mtd MTD device structure + */ +static int onenand_suspend(struct mtd_info *mtd) +{ + return onenand_get_device(mtd, FL_PM_SUSPENDED); +} + +/** + * onenand_resume - [MTD Interface] Resume the OneNAND flash + * @param mtd MTD device structure + */ +static void onenand_resume(struct mtd_info *mtd) +{ + struct onenand_chip *this = mtd->priv; + + if (this->state == FL_PM_SUSPENDED) + onenand_release_device(mtd); + else + printk(KERN_ERR "resume() called for the chip which is not" + "in suspended state\n"); +} + /** * onenand_scan - [OneNAND Interface] Scan for the OneNAND device @@ -1527,8 +1557,8 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) mtd->sync = onenand_sync; mtd->lock = NULL; mtd->unlock = onenand_unlock; - mtd->suspend = NULL; - mtd->resume = NULL; + mtd->suspend = onenand_suspend; + mtd->resume = onenand_resume; mtd->block_isbad = onenand_block_isbad; mtd->block_markbad = onenand_block_markbad; mtd->owner = THIS_MODULE; diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index 58023082320..afaa6342aa7 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -36,6 +36,7 @@ typedef enum { FL_SYNCING, FL_UNLOCKING, FL_LOCKING, + FL_PM_SUSPENDED, } onenand_state_t; /** -- cgit v1.2.3 From 83a368380e172c1b2e9fd6ec2a62e457684adf0c Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Thu, 29 Sep 2005 04:53:16 +0100 Subject: [MTD] OneNAND: Enhanced support for DDP (Dual Densitiy Packages) Add density mask for better support of DDP chips. Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/onenand_base.c | 39 ++++++++++++++++++-------------------- include/linux/mtd/onenand.h | 1 + 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index a002d4025b2..99de2f055eb 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -84,25 +84,23 @@ static void onenand_writew(unsigned short value, void __iomem *addr) /** * onenand_block_address - [DEFAULT] Get block address - * @param device the device id + * @param this onenand chip data structure * @param block the block * @return translated block address if DDP, otherwise same * * Setup Start Address 1 Register (F100h) */ -static int onenand_block_address(int device, int block) +static int onenand_block_address(struct onenand_chip *this, int block) { - if (device & ONENAND_DEVICE_IS_DDP) { + if (this->device_id & ONENAND_DEVICE_IS_DDP) { /* Device Flash Core select, NAND Flash Block Address */ - int dfs = 0, density, mask; + int dfs = 0; - density = device >> ONENAND_DEVICE_DENSITY_SHIFT; - mask = (1 << (density + 6)); - - if (block & mask) + if (block & this->density_mask) dfs = 1; - return (dfs << ONENAND_DDP_SHIFT) | (block & (mask - 1)); + return (dfs << ONENAND_DDP_SHIFT) | + (block & (this->density_mask - 1)); } return block; @@ -110,22 +108,19 @@ static int onenand_block_address(int device, int block) /** * onenand_bufferram_address - [DEFAULT] Get bufferram address - * @param device the device id + * @param this onenand chip data structure * @param block the block * @return set DBS value if DDP, otherwise 0 * * Setup Start Address 2 Register (F101h) for DDP */ -static int onenand_bufferram_address(int device, int block) +static int onenand_bufferram_address(struct onenand_chip *this, int block) { - if (device & ONENAND_DEVICE_IS_DDP) { + if (this->device_id & ONENAND_DEVICE_IS_DDP) { /* Device BufferRAM Select */ - int dbs = 0, density, mask; - - density = device >> ONENAND_DEVICE_DENSITY_SHIFT; - mask = (1 << (density + 6)); + int dbs = 0; - if (block & mask) + if (block & this->density_mask) dbs = 1; return (dbs << ONENAND_DDP_SHIFT); @@ -223,7 +218,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le /* NOTE: The setting order of the registers is very important! */ if (cmd == ONENAND_CMD_BUFFERRAM) { /* Select DataRAM for DDP */ - value = onenand_bufferram_address(this->device_id, block); + value = onenand_bufferram_address(this, block); this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); /* Switch to the next data buffer */ @@ -234,7 +229,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le if (block != -1) { /* Write 'DFS, FBA' of Flash */ - value = onenand_block_address(this->device_id, block); + value = onenand_block_address(this, block); this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); } @@ -263,7 +258,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le if (readcmd) { /* Select DataRAM for DDP */ - value = onenand_bufferram_address(this->device_id, block); + value = onenand_bufferram_address(this, block); this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); } } @@ -1313,7 +1308,7 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) continue; /* Set block address for read block status */ - value = onenand_block_address(this->device_id, block); + value = onenand_block_address(this, block); this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); /* Check lock status */ @@ -1415,6 +1410,8 @@ static int onenand_probe(struct mtd_info *mtd) density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT; this->chipsize = (16 << density) << 20; + /* Set density mask. it is used for DDP */ + this->density_mask = (1 << (density + 6)); /* OneNAND page size & block size */ /* The data buffer size is equal to page size */ diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index afaa6342aa7..d27fd12d096 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -84,6 +84,7 @@ struct onenand_chip { void __iomem *base; unsigned int chipsize; unsigned int device_id; + unsigned int density_mask; unsigned int options; unsigned int erase_shift; -- cgit v1.2.3 From daba5cc4bcd025a9b4fd02a9117c71bfd400d811 Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Fri, 30 Sep 2005 14:59:17 +0100 Subject: [JFFS2] Fix dataflash support - assume wbuf may be of size which is not power of 2 - don't make strange assumption about not padding wbuf for DataFlash - use wbuf = DataFlash page and eraseblock >= 8 Dataflash pages From: Peter Menzebach Acked-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/os-linux.h | 6 +++--- fs/jffs2/scan.c | 6 +++--- fs/jffs2/wbuf.c | 50 ++++++++++++++++++++++++++++++++++---------------- 3 files changed, 40 insertions(+), 22 deletions(-) diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index 48ad4202fbb..04d4167ab25 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: os-linux.h,v 1.63 2005/09/21 11:55:21 dedekind Exp $ + * $Id: os-linux.h,v 1.64 2005/09/30 13:59:13 dedekind Exp $ * */ @@ -65,8 +65,9 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) #define jffs2_is_readonly(c) (OFNI_BS_2SFFJ(c)->s_flags & MS_RDONLY) +#define SECTOR_ADDR(x) ( (((unsigned long)(x) / c->sector_size) * c->sector_size) ) #ifndef CONFIG_JFFS2_FS_WRITEBUFFER -#define SECTOR_ADDR(x) ( ((unsigned long)(x) & ~(c->sector_size-1)) ) + #ifdef CONFIG_JFFS2_SUMMARY #define jffs2_can_mark_obsolete(c) (0) @@ -102,7 +103,6 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) #else /* NAND and/or ECC'd NOR support present */ #define jffs2_is_writebuffered(c) (c->wbuf != NULL) -#define SECTOR_ADDR(x) ( ((unsigned long)(x) / (unsigned long)(c->sector_size)) * c->sector_size ) #ifdef CONFIG_JFFS2_SUMMARY #define jffs2_can_mark_obsolete(c) (0) diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 8df7456472b..805a166469d 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: scan.c,v 1.124 2005/09/21 13:05:22 dedekind Exp $ + * $Id: scan.c,v 1.125 2005/09/30 13:59:13 dedekind Exp $ * */ #include @@ -233,12 +233,12 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) c->nextblock->dirty_size = 0; } #ifdef CONFIG_JFFS2_FS_WRITEBUFFER - if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size & (c->wbuf_pagesize-1))) { + if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size % c->wbuf_pagesize)) { /* If we're going to start writing into a block which already contains data, and the end of the data isn't page-aligned, skip a little and align it. */ - uint32_t skip = c->nextblock->free_size & (c->wbuf_pagesize-1); + uint32_t skip = c->nextblock->free_size % c->wbuf_pagesize; D1(printk(KERN_DEBUG "jffs2_scan_medium(): Skipping %d bytes in nextblock to ensure page alignment\n", skip)); diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 11e05bc014f..44d8a894a41 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -9,7 +9,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: wbuf.c,v 1.99 2005/09/21 16:11:04 dedekind Exp $ + * $Id: wbuf.c,v 1.100 2005/09/30 13:59:13 dedekind Exp $ * */ @@ -30,6 +30,9 @@ static unsigned char *brokenbuf; #endif +#define PAGE_DIV(x) ( ((unsigned long)(x) / (unsigned long)(c->wbuf_pagesize)) * (unsigned long)(c->wbuf_pagesize) ) +#define PAGE_MOD(x) ( (unsigned long)(x) % (unsigned long)(c->wbuf_pagesize) ) + /* max. erase failures before we mark a block bad */ #define MAX_ERASE_FAILURES 2 @@ -433,7 +436,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) if we have a switch to next page, we will not have enough remaining space for this. */ - if (pad && !jffs2_dataflash(c)) { + if (pad ) { c->wbuf_len = PAD(c->wbuf_len); /* Pad with JFFS2_DIRTY_BITMASK initially. this helps out ECC'd NOR @@ -482,9 +485,9 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) } spin_lock(&c->erase_completion_lock); - + /* Adjust free size of the block if we padded. */ - if (pad && !jffs2_dataflash(c)) { + if (pad) { struct jffs2_eraseblock *jeb; jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; @@ -601,15 +604,6 @@ int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c) return ret; } - -#ifdef CONFIG_JFFS2_FS_WRITEBUFFER -#define PAGE_DIV(x) ( ((unsigned long)(x) / (unsigned long)(c->wbuf_pagesize)) * (unsigned long)(c->wbuf_pagesize) ) -#define PAGE_MOD(x) ( (unsigned long)(x) % (unsigned long)(c->wbuf_pagesize) ) -#else -#define PAGE_DIV(x) ( (x) & (~(c->wbuf_pagesize - 1)) ) -#define PAGE_MOD(x) ( (x) & (c->wbuf_pagesize - 1) ) -#endif - int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino) { struct kvec outvecs[3]; @@ -1203,14 +1197,38 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) { /* Initialize write buffer */ init_rwsem(&c->wbuf_sem); - c->wbuf_pagesize = c->sector_size; - c->wbuf_ofs = 0xFFFFFFFF; + + + c->wbuf_pagesize = c->mtd->erasesize; + + /* Find a suitable c->sector_size + * - Not too much sectors + * - Sectors have to be at least 4 K + some bytes + * - All known dataflashes have erase sizes of 528 or 1056 + * - we take at least 8 eraseblocks and want to have at least 8K size + * - The concatenation should be a power of 2 + */ + + c->sector_size = 8 * c->mtd->erasesize; + + while (c->sector_size < 8192) { + c->sector_size *= 2; + } + + /* It may be necessary to adjust the flash size */ + c->flash_size = c->mtd->size; + if ((c->flash_size % c->sector_size) != 0) { + c->flash_size = (c->flash_size / c->sector_size) * c->sector_size; + printk(KERN_WARNING "JFFS2 flash size adjusted to %dKiB\n", c->flash_size); + }; + + c->wbuf_ofs = 0xFFFFFFFF; c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); if (!c->wbuf) return -ENOMEM; - printk(KERN_INFO "JFFS2 write-buffering enabled (%i)\n", c->wbuf_pagesize); + printk(KERN_INFO "JFFS2 write-buffering enabled buffer (%d) erasesize (%d)\n", c->wbuf_pagesize, c->sector_size); return 0; } -- cgit v1.2.3 From 5cea5dadfebdede8045fca118328860058129eb2 Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Fri, 30 Sep 2005 15:49:12 +0100 Subject: [MTD] mtdpart.c: Allow eraseblock size != power of 2 Don't assume eraseblock size is power of 2. Dataflash can have aligned eraseblock size. From: Peter Menzebach Acked-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- drivers/mtd/mtdpart.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index b92e6bfffaf..e9168b5cd51 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -5,7 +5,7 @@ * * This code is GPL * - * $Id: mtdpart.c,v 1.53 2005/02/08 17:11:13 nico Exp $ + * $Id: mtdpart.c,v 1.54 2005/09/30 14:49:08 dedekind Exp $ * * 02-21-2002 Thomas Gleixner * added support for read_oob, write_oob @@ -465,9 +465,10 @@ int add_mtd_partitions(struct mtd_info *master, if (slave->offset == MTDPART_OFS_APPEND) slave->offset = cur_offset; if (slave->offset == MTDPART_OFS_NXTBLK) { - u_int32_t emask = master->erasesize-1; - slave->offset = (cur_offset + emask) & ~emask; - if (slave->offset != cur_offset) { + slave->offset = cur_offset; + if ((cur_offset % master->erasesize) != 0) { + /* Round up to next erasesize */ + slave->offset = ((cur_offset / master->erasesize) + 1) * master->erasesize; printk(KERN_NOTICE "Moving partition %d: " "0x%08x -> 0x%08x\n", i, cur_offset, slave->offset); -- cgit v1.2.3 From 61a7275491ce3c2b0a243b1fbeda024e5faeb2c6 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 10 Oct 2005 01:09:19 +0100 Subject: [MTD] NAND: s3c2410.c Initialize owner in device_driver struct Added owner fields to the device_driver for tracking ownership when built as a module Signed-off-by: Ben Dooks Signed-off-by: Thomas Gleixner --- drivers/mtd/nand/s3c2410.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 44989c8b5f7..a44458fd422 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -18,7 +18,7 @@ * 20-Jun-2005 BJD Updated s3c2440 support, fixed timing bug * 08-Jul-2005 BJD Fix OOPS when no platform data supplied * - * $Id: s3c2410.c,v 1.15 2005/09/26 21:42:54 bjd Exp $ + * $Id: s3c2410.c,v 1.16 2005/10/10 00:09:16 bjd Exp $ * * 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 @@ -695,6 +695,7 @@ static int s3c2440_nand_probe(struct device *dev) static struct device_driver s3c2410_nand_driver = { .name = "s3c2410-nand", + .owner = THIS_MODULE, .bus = &platform_bus_type, .probe = s3c2410_nand_probe, .remove = s3c2410_nand_remove, @@ -702,6 +703,7 @@ static struct device_driver s3c2410_nand_driver = { static struct device_driver s3c2440_nand_driver = { .name = "s3c2440-nand", + .owner = THIS_MODULE, .bus = &platform_bus_type, .probe = s3c2440_nand_probe, .remove = s3c2410_nand_remove, -- cgit v1.2.3 From e0030b60ceeaea356e49187baf9702b5ce151be1 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 10 Oct 2005 01:13:41 +0100 Subject: [MTD] maps/bast-flash.c: Initialize owner in device_driver struct Added owner to device driver field for tracking when loaded as a module. Signed-off-by: Ben Dooks Signed-off-by: Thomas Gleixner --- drivers/mtd/maps/bast-flash.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/maps/bast-flash.c b/drivers/mtd/maps/bast-flash.c index bfe994e5926..5ec53c17e43 100644 --- a/drivers/mtd/maps/bast-flash.c +++ b/drivers/mtd/maps/bast-flash.c @@ -9,7 +9,7 @@ * 20-Sep-2004 BJD Initial version * 17-Jan-2005 BJD Add whole device if no partitions found * - * $Id: bast-flash.c,v 1.2 2005/01/18 11:13:47 bjd Exp $ + * $Id: bast-flash.c,v 1.3 2005/10/10 00:13:38 bjd Exp $ * * 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 @@ -206,6 +206,7 @@ static int bast_flash_probe(struct device *dev) static struct device_driver bast_flash_driver = { .name = "bast-nor", + .owner = THIS_MODULE, .bus = &platform_bus_type, .probe = bast_flash_probe, .remove = bast_flash_remove, -- cgit v1.2.3 From df2e162927b7af36d669f0ade81c17036c4001d4 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 10 Oct 2005 01:51:30 +0100 Subject: [MTD] maps/plat-ram.c: Initialize owner in device_driver struct Added .owner initialisation to allow the tracking of the device_driver owners when built as a module Signed-off-by: Ben Dooks Signed-off-by: Thomas Gleixner --- drivers/mtd/maps/plat-ram.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index 104576b5be3..acdf9f71577 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c @@ -6,7 +6,7 @@ * * Generic platfrom device based RAM map * - * $Id: plat-ram.c,v 1.3 2005/03/19 22:41:27 gleixner Exp $ + * $Id: plat-ram.c,v 1.4 2005/10/10 00:51:26 bjd Exp $ * * 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 @@ -254,6 +254,7 @@ static int platram_probe(struct device *dev) static struct device_driver platram_driver = { .name = "mtd-ram", + .owner = THIS_MODULE, .bus = &platform_bus_type, .probe = platram_probe, .remove = platram_remove, -- cgit v1.2.3 From d574504114753f52d8d2a8a0f186d2a5fcd80789 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 10 Oct 2005 11:27:05 +0100 Subject: [MTD] NAND s3c2410.c: Fix missing dev parameter to dev_err Signed-off-by: Ben Dooks Signed-off-by: Thomas Gleixner --- drivers/mtd/nand/s3c2410.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index a44458fd422..41f2078225a 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -18,7 +18,7 @@ * 20-Jun-2005 BJD Updated s3c2440 support, fixed timing bug * 08-Jul-2005 BJD Fix OOPS when no platform data supplied * - * $Id: s3c2410.c,v 1.16 2005/10/10 00:09:16 bjd Exp $ + * $Id: s3c2410.c,v 1.17 2005/10/10 10:27:02 bjd Exp $ * * 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 @@ -576,7 +576,7 @@ static int s3c24xx_nand_probe(struct device *dev, int is_s3c2440) info = kmalloc(sizeof(*info), GFP_KERNEL); if (info == NULL) { - dev_err("no memory for flash info\n"); + dev_err(dev, "no memory for flash info\n"); err = -ENOMEM; goto exit_error; } -- cgit v1.2.3 From fb0258730ad554db531f12fc1c3d5a5234fe52a4 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 17 Oct 2005 22:03:19 +0100 Subject: [MTD] Don't let gcc inline functions marked __xipram If they get inlined into non __xipram functions we're screwed. Signed-off-by: Nicolas Pitre Signed-off-by: Thomas Gleixner --- include/linux/mtd/xip.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/linux/mtd/xip.h b/include/linux/mtd/xip.h index 7b7deef6b18..863fa5a1d24 100644 --- a/include/linux/mtd/xip.h +++ b/include/linux/mtd/xip.h @@ -12,7 +12,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * $Id: xip.h,v 1.2 2004/12/01 15:49:10 nico Exp $ + * $Id: xip.h,v 1.4 2005/10/17 21:03:16 nico Exp $ */ #ifndef __LINUX_MTD_XIP_H__ @@ -22,19 +22,19 @@ #ifdef CONFIG_MTD_XIP -/* - * Function that are modifying the flash state away from array mode must - * obviously not be running from flash. The __xipram is therefore marking - * those functions so they get relocated to ram. - */ -#define __xipram __attribute__ ((__section__ (".data"))) - /* * We really don't want gcc to guess anything. * We absolutely _need_ proper inlining. */ #include +/* + * Function that are modifying the flash state away from array mode must + * obviously not be running from flash. The __xipram is therefore marking + * those functions so they get relocated to ram. + */ +#define __xipram noinline __attribute__ ((__section__ (".data"))) + /* * Each architecture has to provide the following macros. They must access * the hardware directly and not rely on any other (XIP) functions since they -- cgit v1.2.3 From 4fc67fbe52d7c34dfd3e03a1a79f3e078904bba2 Mon Sep 17 00:00:00 2001 From: Todd Poynor Date: Wed, 19 Oct 2005 00:29:38 +0100 Subject: [JFFS2] Return 0, not number of bytes written, for success at commit_write Some callers to block-layer commit_write function treat non-zero return as error, notably the loopback mount driver sometimes used in conjunction with JFFS2 on NAND flash for bad block avoidance, etc. Return zero for success as do various other commit_write functions. Signed-off-by: Todd Poynor Signed-off-by: Thomas Gleixner --- fs/jffs2/file.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index 231404a7472..605ea6b0b47 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: file.c,v 1.103 2005/09/07 08:34:54 havasi Exp $ + * $Id: file.c,v 1.104 2005/10/18 23:29:35 tpoynor Exp $ * */ @@ -279,6 +279,6 @@ static int jffs2_commit_write (struct file *filp, struct page *pg, ClearPageUptodate(pg); } - D1(printk(KERN_DEBUG "jffs2_commit_write() returning %d\n",writtenlen?writtenlen:ret)); - return writtenlen?writtenlen:ret; + D1(printk(KERN_DEBUG "jffs2_commit_write() returning %d\n",start+writtenlen==end?0:ret)); + return start+writtenlen==end?0:ret; } -- cgit v1.2.3 From cfd320fbfcf2ff0137d8e26f46ba4b66dae96083 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 20 Oct 2005 22:22:58 +0100 Subject: [MTD] NAND s3c2410.c: Fix timing calculation bugs Spotted by basprog@mail.ru Signed-off-by: Ben Dooks Signed-off-by: Thomas Gleixner --- drivers/mtd/nand/s3c2410.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 41f2078225a..24f4199eaee 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -17,8 +17,9 @@ * 02-May-2005 BJD Reduced hwcontrol decode * 20-Jun-2005 BJD Updated s3c2440 support, fixed timing bug * 08-Jul-2005 BJD Fix OOPS when no platform data supplied + * 20-Oct-2005 BJD Fix timing calculation bug * - * $Id: s3c2410.c,v 1.17 2005/10/10 10:27:02 bjd Exp $ + * $Id: s3c2410.c,v 1.18 2005/10/20 21:22:55 bjd Exp $ * * 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 @@ -136,13 +137,13 @@ static struct s3c2410_platform_nand *to_nand_plat(struct device *dev) /* timing calculations */ -#define NS_IN_KHZ 10000000 +#define NS_IN_KHZ 1000000 static int s3c2410_nand_calc_rate(int wanted, unsigned long clk, int max) { int result; - result = (wanted * NS_IN_KHZ) / clk; + result = (wanted * clk) / NS_IN_KHZ; result++; pr_debug("result %d from %ld, %d\n", result, clk, wanted); @@ -159,7 +160,7 @@ static int s3c2410_nand_calc_rate(int wanted, unsigned long clk, int max) return result; } -#define to_ns(ticks,clk) (((clk) * (ticks)) / NS_IN_KHZ) +#define to_ns(ticks,clk) (((ticks) * NS_IN_KHZ) / (unsigned int)(clk)) /* controller setup */ @@ -167,12 +168,14 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, struct device *dev) { struct s3c2410_platform_nand *plat = to_nand_plat(dev); - unsigned int tacls, twrph0, twrph1; unsigned long clkrate = clk_get_rate(info->clk); + int tacls, twrph0, twrph1; unsigned long cfg; /* calculate the timing information for the controller */ + clkrate /= 1000; /* turn clock into kHz for ease of use */ + if (plat != NULL) { tacls = s3c2410_nand_calc_rate(plat->tacls, clkrate, 4); twrph0 = s3c2410_nand_calc_rate(plat->twrph0, clkrate, 8); @@ -189,10 +192,10 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, return -EINVAL; } - printk(KERN_INFO PFX "timing: Tacls %ldns, Twrph0 %ldns, Twrph1 %ldns\n", - to_ns(tacls, clkrate), - to_ns(twrph0, clkrate), - to_ns(twrph1, clkrate)); + printk(KERN_INFO PFX "Tacls=%d, %dns Twrph0=%d %dns, Twrph1=%d %dns\n", + tacls, to_ns(tacls, clkrate), + twrph0, to_ns(twrph0, clkrate), + twrph1, to_ns(twrph1, clkrate)); if (!info->is_s3c2440) { cfg = S3C2410_NFCONF_EN; -- cgit v1.2.3 From 008531f4c30dce606094be8f78c766218edd6754 Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Mon, 24 Oct 2005 17:22:36 +0100 Subject: [JFFS2] Fix broken compile when debug level = 2 Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/debug.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index da1417d3891..b47ba9f1d60 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.h,v 1.18 2005/09/21 10:26:26 dedekind Exp $ + * $Id: debug.h,v 1.20 2005/10/24 16:22:34 dedekind Exp $ * */ #ifndef _JFFS2_DEBUG_H_ @@ -19,7 +19,7 @@ #define CONFIG_JFFS2_FS_DEBUG 0 #endif -#if CONFIG_JFFS2_FS_DEBUG == 1 +#if CONFIG_JFFS2_FS_DEBUG > 0 /* Enable "paranoia" checks and dumps */ #define JFFS2_DBG_PARANOIA_CHECKS #define JFFS2_DBG_DUMPS @@ -37,7 +37,7 @@ #define JFFS2_DBG_FSBUILD_MESSAGES #endif -#if CONFIG_JFFS2_FS_DEBUG == 2 +#if CONFIG_JFFS2_FS_DEBUG > 1 #define JFFS2_DBG_FRAGTREE2_MESSAGES #define JFFS2_DBG_MEMALLOC_MESSAGES #endif -- cgit v1.2.3 From 6f6ed056d2d5de7af9f0c14cf5bc73707eeb0a88 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 25 Oct 2005 21:28:43 +0100 Subject: [MTD] chips/cfi_cmdset_0001: fix for P30 cfi parsing Change to the extended cfi table parsing for Intel NOR flash that uses the info in the extended table to 'walk' the table rather than using hard coding for various primary extended query table version numbers. From: Jared Hulbert Signed-off-by: Nicolas Pitre Signed-off-by: Thomas Gleixner --- drivers/mtd/chips/cfi_cmdset_0001.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index adaad7c8fd4..61a2ec9901e 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -4,7 +4,7 @@ * * (C) 2000 Red Hat. GPL'd * - * $Id: cfi_cmdset_0001.c,v 1.183 2005/08/06 04:46:56 nico Exp $ + * $Id: cfi_cmdset_0001.c,v 1.184 2005/10/25 20:28:40 nico Exp $ * * * 10/10/2000 Nicolas Pitre @@ -285,7 +285,10 @@ read_pri_intelext(struct map_info *map, __u16 adr) sizeof(struct cfi_intelext_otpinfo); /* Burst Read info */ - extra_size += (extp->MinorVersion < '4') ? 6 : 5; + extra_size += 2; + if (extp_size < sizeof(*extp) + extra_size) + goto need_more; + extra_size += extp->extra[extra_size-1]; /* Number of hardware-partitions */ extra_size += 1; @@ -519,7 +522,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, sizeof(struct cfi_intelext_otpinfo); /* Burst Read info */ - offs += (extp->MinorVersion < '4') ? 6 : 5; + offs += extp->extra[offs+1]+2; /* Number of partition regions */ numregions = extp->extra[offs]; -- cgit v1.2.3 From 87c146dc1a8552d7ad431a41b37ba8168e51e50e Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Thu, 3 Nov 2005 11:36:45 +0000 Subject: [MTD] NAND sharpsl.c: Add support for akita and borzoi models The Sharp Zaurus akita and borzoi models are large page flash devices. This patch adds support for them to the sharpsl MTD NAND driver but keeps the oob layout and bad block positions compatible with the Sharp Zaurus 2.4 kernel and ROM bootloader. Signed-off-by: Richard Purdie Signed-off-by: Thomas Gleixner --- drivers/mtd/nand/sharpsl.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index 88b5b5b40b4..6def3d33b06 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c @@ -3,7 +3,7 @@ * * Copyright (C) 2004 Richard Purdie * - * $Id: sharpsl.c,v 1.4 2005/01/23 11:09:19 rpurdie Exp $ + * $Id: sharpsl.c,v 1.6 2005/11/03 11:36:42 rpurdie Exp $ * * Based on Sharp's NAND driver sharp_sl.c * @@ -115,6 +115,23 @@ static struct nand_bbt_descr sharpsl_bbt = { .pattern = scan_ff_pattern }; +static struct nand_bbt_descr sharpsl_akita_bbt = { + .options = 0, + .offs = 4, + .len = 1, + .pattern = scan_ff_pattern +}; + +static struct nand_oobinfo akita_oobinfo = { + .useecc = MTD_NANDECC_AUTOPLACE, + .eccbytes = 24, + .eccpos = { + 0x5, 0x1, 0x2, 0x3, 0x6, 0x7, 0x15, 0x11, + 0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23, + 0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37}, + .oobfree = { {0x08, 0x09} } +}; + static int sharpsl_nand_dev_ready(struct mtd_info* mtd) { @@ -194,10 +211,14 @@ sharpsl_nand_init(void) this->chip_delay = 15; /* set eccmode using hardware ECC */ this->eccmode = NAND_ECC_HW3_256; + this->badblock_pattern = &sharpsl_bbt; + if (machine_is_akita() || machine_is_borzoi()) { + this->badblock_pattern = &sharpsl_akita_bbt; + this->autooob = &akita_oobinfo; + } this->enable_hwecc = sharpsl_nand_enable_hwecc; this->calculate_ecc = sharpsl_nand_calculate_ecc; this->correct_data = nand_correct_data; - this->badblock_pattern = &sharpsl_bbt; /* Scan to find existence of the device */ err=nand_scan(sharpsl_mtd,1); @@ -230,7 +251,7 @@ sharpsl_nand_init(void) } } - if (machine_is_husky() || machine_is_borzoi()) { + if (machine_is_husky() || machine_is_borzoi() || machine_is_akita()) { /* Need to use small eraseblock size for backward compatibility */ sharpsl_mtd->flags |= MTD_NO_VIRTBLOCKS; } -- cgit v1.2.3 From 9090ed0b82f817bde471bdbb2e73278ab75f5fd3 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Tue, 1 Nov 2005 16:46:19 +0000 Subject: [MTD] maps/ixp4xx: kill some warnings - Use map.virt instead of map.map_priv_1 since it has the correct type. - Use readw/writew instead of dereferencing an ioremap'd cookie. - Remove an unused variable. Signed-off-by: David Vrabel Signed-off-by: Thomas Gleixner --- drivers/mtd/maps/ixp4xx.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c index 58b477043f2..c510c736ed9 100644 --- a/drivers/mtd/maps/ixp4xx.c +++ b/drivers/mtd/maps/ixp4xx.c @@ -1,5 +1,5 @@ /* - * $Id: ixp4xx.c,v 1.8 2005/09/08 10:32:20 dvrabel Exp $ + * $Id: ixp4xx.c,v 1.11 2005/11/06 11:15:51 gleixner Exp $ * * drivers/mtd/maps/ixp4xx.c * @@ -45,7 +45,7 @@ static map_word ixp4xx_read16(struct map_info *map, unsigned long ofs) { map_word val; - val.x[0] = *(__u16 *) (map->map_priv_1 + ofs); + val.x[0] = le16_to_cpu(readw(map->virt + ofs)); return val; } @@ -59,17 +59,17 @@ static void ixp4xx_copy_from(struct map_info *map, void *to, { int i; u8 *dest = (u8 *) to; - u16 *src = (u16 *) (map->map_priv_1 + from); + void __iomem *src = map->virt + from; u16 data; for (i = 0; i < (len / 2); i++) { - data = src[i]; + data = le16_to_cpu(readw(src + 2*i)); dest[i * 2] = BYTE0(data); dest[i * 2 + 1] = BYTE1(data); } if (len & 1) - dest[len - 1] = BYTE0(src[i]); + dest[len - 1] = BYTE0(le16_to_cpu(readw(src + 2*i))); } /* @@ -79,7 +79,7 @@ static void ixp4xx_copy_from(struct map_info *map, void *to, static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long adr) { if (!(adr & 1)) - *(__u16 *) (map->map_priv_1 + adr) = d.x[0]; + writew(cpu_to_le16(d.x[0]), map->virt + adr); } /* @@ -87,7 +87,7 @@ static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long */ static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr) { - *(__u16 *) (map->map_priv_1 + adr) = d.x[0]; + writew(cpu_to_le16(d.x[0]), map->virt + adr); } struct ixp4xx_flash_info { @@ -104,7 +104,6 @@ static int ixp4xx_flash_remove(struct device *_dev) struct platform_device *dev = to_platform_device(_dev); struct flash_platform_data *plat = dev->dev.platform_data; struct ixp4xx_flash_info *info = dev_get_drvdata(&dev->dev); - map_word d; dev_set_drvdata(&dev->dev, NULL); @@ -115,8 +114,8 @@ static int ixp4xx_flash_remove(struct device *_dev) del_mtd_partitions(info->mtd); map_destroy(info->mtd); } - if (info->map.map_priv_1) - iounmap((void *) info->map.map_priv_1); + if (info->map.virt) + iounmap(info->map.virt); if (info->partitions) kfree(info->partitions); @@ -184,9 +183,9 @@ static int ixp4xx_flash_probe(struct device *_dev) goto Error; } - info->map.map_priv_1 = ioremap(dev->resource->start, - dev->resource->end - dev->resource->start + 1); - if (!info->map.map_priv_1) { + info->map.virt = ioremap(dev->resource->start, + dev->resource->end - dev->resource->start + 1); + if (!info->map.virt) { printk(KERN_ERR "IXP4XXFlash: Failed to ioremap region\n"); err = -EIO; goto Error; @@ -244,4 +243,3 @@ module_exit(ixp4xx_flash_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems"); MODULE_AUTHOR("Deepak Saxena"); - -- cgit v1.2.3 From 15fdc52f35b853e3fa550087987b5ee4ffbd199b Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 00:14:42 +0100 Subject: [MTD] Tidy up Tims include cleanup While we are at it, reorder the includes and remove the silly /* TASK */ comment Signed-off-by: Thomas Gleixner --- drivers/mtd/mtdblock.c | 11 ++++++----- drivers/mtd/mtdchar.c | 15 ++++++++------- drivers/mtd/mtdconcat.c | 9 +++++---- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c index 400dd9c8988..bee8aba9e5b 100644 --- a/drivers/mtd/mtdblock.c +++ b/drivers/mtd/mtdblock.c @@ -1,21 +1,22 @@ /* * Direct MTD block device access * - * $Id: mtdblock.c,v 1.66 2004/11/25 13:52:52 joern Exp $ + * $Id: mtdblock.c,v 1.67 2005/11/06 10:04:37 gleixner Exp $ * * (C) 2000-2003 Nicolas Pitre * (C) 1999-2003 David Woodhouse */ #include -#include -#include -#include #include #include +#include +#include +#include #include +#include #include -#include /* TASK_* */ + #include #include diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 8c0d94b72b6..d1ffd246ad5 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -1,22 +1,23 @@ /* - * $Id: mtdchar.c,v 1.74 2005/08/04 01:05:48 tpoynor Exp $ + * $Id: mtdchar.c,v 1.75 2005/11/06 10:04:37 gleixner Exp $ * * Character-device access to raw MTD devices. * */ #include +#include +#include +#include #include #include +#include +#include + #include #include -#include -#include -#include -#include /* TASK_* */ -#include -#include +#include static struct class *mtd_class; diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index f3e65af33a9..eaaafb1de62 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c @@ -7,14 +7,15 @@ * * This code is GPL * - * $Id: mtdconcat.c,v 1.9 2004/06/30 15:17:41 dbrown Exp $ + * $Id: mtdconcat.c,v 1.10 2005/11/06 10:04:37 gleixner Exp $ */ -#include -#include #include +#include #include -#include /* TASK_* */ +#include +#include + #include #include -- cgit v1.2.3 From 28f462308e0fcd30dcab4c50862881dfb68a627c Mon Sep 17 00:00:00 2001 From: Sean Young Date: Wed, 29 Jun 2005 09:46:19 +0000 Subject: [MTD] maps/ts5500: Fix partition support. Code cleanup Signed-off-by: Sean Young Signed-off-by: Thomas Gleixner --- drivers/mtd/maps/ts5500_flash.c | 38 ++++++++++++-------------------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/drivers/mtd/maps/ts5500_flash.c b/drivers/mtd/maps/ts5500_flash.c index 286dd82e8b8..2762da95431 100644 --- a/drivers/mtd/maps/ts5500_flash.c +++ b/drivers/mtd/maps/ts5500_flash.c @@ -23,20 +23,18 @@ * - If you have created your own jffs file system and the bios overwrites * it during boot, try disabling Drive A: and B: in the boot order. * - * $Id: ts5500_flash.c,v 1.3 2005/06/16 08:49:30 sean Exp $ + * $Id: ts5500_flash.c,v 1.4 2005/06/29 09:29:43 sean Exp $ */ #include +#include #include -#include #include -#include -#include #include - -#ifdef CONFIG_MTD_PARTITIONS +#include #include -#endif +#include + #define WINDOW_ADDR 0x09400000 #define WINDOW_SIZE 0x00200000 @@ -48,7 +46,6 @@ static struct map_info ts5500_map = { .phys = WINDOW_ADDR }; -#ifdef CONFIG_MTD_PARTITIONS static struct mtd_partition ts5500_partitions[] = { { .name = "Drive A", @@ -69,8 +66,6 @@ static struct mtd_partition ts5500_partitions[] = { #define NUM_PARTITIONS (sizeof(ts5500_partitions)/sizeof(struct mtd_partition)) -#endif - static struct mtd_info *mymtd; static int __init init_ts5500_map(void) @@ -79,48 +74,39 @@ static int __init init_ts5500_map(void) ts5500_map.virt = ioremap_nocache(ts5500_map.phys, ts5500_map.size); - if(!ts5500_map.virt) { + if (!ts5500_map.virt) { printk(KERN_ERR "Failed to ioremap_nocache\n"); rc = -EIO; - goto err_out_ioremap; + goto err2; } simple_map_init(&ts5500_map); mymtd = do_map_probe("jedec_probe", &ts5500_map); - if(!mymtd) + if (!mymtd) mymtd = do_map_probe("map_rom", &ts5500_map); - if(!mymtd) { + if (!mymtd) { rc = -ENXIO; - goto err_out_map; + goto err1; } mymtd->owner = THIS_MODULE; -#ifdef CONFIG_MTD_PARTITIONS add_mtd_partitions(mymtd, ts5500_partitions, NUM_PARTITIONS); -#else - add_mtd_device(mymtd); -#endif return 0; -err_out_map: +err1: map_destroy(mymtd); -err_out_ioremap: iounmap(ts5500_map.virt); - +err2: return rc; } static void __exit cleanup_ts5500_map(void) { if (mymtd) { -#ifdef CONFIG_MTD_PARTITIONS del_mtd_partitions(mymtd); -#else - del_mtd_device(mymtd); -#endif map_destroy(mymtd); } -- cgit v1.2.3 From 01ac742db34fec11469724dc350a417790dbbbbe Mon Sep 17 00:00:00 2001 From: Sean Young Date: Wed, 29 Jun 2005 09:46:19 +0000 Subject: [MTD] maps/Kconfig: Simplify and update dependencies Signed-off-by: Thomas Gleixner --- drivers/mtd/maps/Kconfig | 61 +++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 7f1ce08fb7b..94a693f4bea 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -94,7 +94,10 @@ config MTD_NETSC520 config MTD_TS5500 tristate "JEDEC Flash device mapped on Technologic Systems TS-5500" - depends on X86 && MTD_JEDECPROBE && MTD_PARTITIONS + depends on ELAN + select MTD_PARTITIONS + select MTD_JEDECPROBE + select MTD_CFI_AMDSTD help This provides a driver for the on-board flash of the Technologic System's TS-5500 board. The 2MB flash is split into 3 partitions @@ -210,7 +213,7 @@ config MTD_NETtel config MTD_ALCHEMY tristate ' AMD Alchemy Pb1xxx/Db1xxx/RDK MTD support' - depends on MIPS && SOC_AU1X00 + depends on SOC_AU1X00 help Flash memory access on AMD Alchemy Pb/Db/RDK Reference Boards @@ -248,14 +251,14 @@ config MTD_L440GX config MTD_SBC8240 tristate "Flash device on SBC8240" - depends on PPC32 && MTD_JEDECPROBE && 6xx && 8260 + depends on MTD_JEDECPROBE && 8260 help Flash access on the SBC8240 board from Wind River. See config MTD_TQM8XXL tristate "CFI Flash device mapped on TQM8XXL" - depends on MTD_CFI && PPC32 && 8xx && TQM8xxL + depends on MTD_CFI && TQM8xxL help The TQM8xxL PowerPC board has up to two banks of CFI-compliant chips, currently uses AMD one. This 'mapping' driver supports @@ -265,7 +268,7 @@ config MTD_TQM8XXL config MTD_RPXLITE tristate "CFI Flash device mapped on RPX Lite or CLLF" - depends on MTD_CFI && PPC32 && 8xx && (RPXCLASSIC || RPXLITE) + depends on MTD_CFI && (RPXCLASSIC || RPXLITE) help The RPXLite PowerPC board has CFI-compliant chips mapped in a strange sparse mapping. This 'mapping' driver supports that @@ -275,7 +278,7 @@ config MTD_RPXLITE config MTD_MBX860 tristate "System flash on MBX860 board" - depends on MTD_CFI && PPC32 && 8xx && MBX + depends on MTD_CFI && MBX help This enables access routines for the flash chips on the Motorola MBX860 board. If you have one of these boards and would like @@ -283,7 +286,7 @@ config MTD_MBX860 config MTD_DBOX2 tristate "CFI Flash device mapped on D-Box2" - depends on PPC32 && 8xx && DBOX2 && MTD_CFI_INTELSTD && MTD_CFI_INTELEXT && MTD_CFI_AMDSTD + depends on DBOX2 && MTD_CFI_INTELSTD && MTD_CFI_INTELEXT && MTD_CFI_AMDSTD help This enables access routines for the flash chips on the Nokia/Sagem D-Box 2 board. If you have one of these boards and would like to use @@ -291,14 +294,14 @@ config MTD_DBOX2 config MTD_CFI_FLAGADM tristate "CFI Flash device mapping on FlagaDM" - depends on PPC32 && 8xx && MTD_CFI + depends on 8xx && MTD_CFI help Mapping for the Flaga digital module. If you don't have one, ignore this setting. config MTD_BEECH tristate "CFI Flash device mapped on IBM 405LP Beech" - depends on MTD_CFI && PPC32 && 40x && BEECH + depends on MTD_CFI && BEECH help This enables access routines for the flash chips on the IBM 405LP Beech board. If you have one of these boards and would like @@ -306,7 +309,7 @@ config MTD_BEECH config MTD_ARCTIC tristate "CFI Flash device mapped on IBM 405LP Arctic" - depends on MTD_CFI && PPC32 && 40x && ARCTIC2 + depends on MTD_CFI && ARCTIC2 help This enables access routines for the flash chips on the IBM 405LP Arctic board. If you have one of these boards and would like to @@ -314,7 +317,7 @@ config MTD_ARCTIC config MTD_WALNUT tristate "Flash device mapped on IBM 405GP Walnut" - depends on MTD_JEDECPROBE && PPC32 && 40x && WALNUT + depends on MTD_JEDECPROBE && WALNUT help This enables access routines for the flash chips on the IBM 405GP Walnut board. If you have one of these boards and would like to @@ -322,7 +325,7 @@ config MTD_WALNUT config MTD_EBONY tristate "Flash devices mapped on IBM 440GP Ebony" - depends on MTD_JEDECPROBE && PPC32 && 44x && EBONY + depends on MTD_JEDECPROBE && EBONY help This enables access routines for the flash chips on the IBM 440GP Ebony board. If you have one of these boards and would like to @@ -330,7 +333,7 @@ config MTD_EBONY config MTD_OCOTEA tristate "Flash devices mapped on IBM 440GX Ocotea" - depends on MTD_CFI && PPC32 && 44x && OCOTEA + depends on MTD_CFI && OCOTEA help This enables access routines for the flash chips on the IBM 440GX Ocotea board. If you have one of these boards and would like to @@ -338,7 +341,7 @@ config MTD_OCOTEA config MTD_REDWOOD tristate "CFI Flash devices mapped on IBM Redwood" - depends on MTD_CFI && PPC32 && 4xx && 40x && ( REDWOOD_4 || REDWOOD_5 || REDWOOD_6 ) + depends on MTD_CFI && ( REDWOOD_4 || REDWOOD_5 || REDWOOD_6 ) help This enables access routines for the flash chips on the IBM Redwood board. If you have one of these boards and would like to @@ -409,14 +412,14 @@ config MTD_ARM_INTEGRATOR config MTD_CDB89712 tristate "Cirrus CDB89712 evaluation board mappings" - depends on ARM && MTD_CFI && ARCH_CDB89712 + depends on MTD_CFI && ARCH_CDB89712 help This enables access to the flash or ROM chips on the CDB89712 board. If you have such a board, say 'Y'. config MTD_SA1100 tristate "CFI Flash device mapped on StrongARM SA11x0" - depends on ARM && MTD_CFI && ARCH_SA1100 && MTD_PARTITIONS + depends on MTD_CFI && ARCH_SA1100 && MTD_PARTITIONS help This enables access to the flash chips on most platforms based on the SA1100 and SA1110, including the Assabet and the Compaq iPAQ. @@ -424,13 +427,13 @@ config MTD_SA1100 config MTD_IPAQ tristate "CFI Flash device mapped on Compaq/HP iPAQ" - depends on ARM && IPAQ_HANDHELD && MTD_CFI + depends on IPAQ_HANDHELD && MTD_CFI help This provides a driver for the on-board flash of the iPAQ. config MTD_DC21285 tristate "CFI Flash device mapped on DC21285 Footbridge" - depends on ARM && MTD_CFI && ARCH_FOOTBRIDGE && MTD_COMPLEX_MAPPINGS + depends on MTD_CFI && ARCH_FOOTBRIDGE && MTD_COMPLEX_MAPPINGS help This provides a driver for the flash accessed using Intel's 21285 bridge used with Intel's StrongARM processors. More info at @@ -438,7 +441,7 @@ config MTD_DC21285 config MTD_IQ80310 tristate "CFI Flash device mapped on the XScale IQ80310 board" - depends on ARM && MTD_CFI && ARCH_IQ80310 + depends on MTD_CFI && ARCH_IQ80310 help This enables access routines for the flash chips on the Intel XScale IQ80310 evaluation board. If you have one of these boards and would @@ -446,7 +449,7 @@ config MTD_IQ80310 config MTD_IXP4XX tristate "CFI Flash device mapped on Intel IXP4xx based systems" - depends on ARM && MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP4XX + depends on MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP4XX help This enables MTD access to flash devices on platforms based on Intel's IXP4xx family of network processors such as the @@ -455,7 +458,7 @@ config MTD_IXP4XX config MTD_IXP2000 tristate "CFI Flash device mapped on Intel IXP2000 based systems" - depends on ARM && MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP2000 + depends on MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP2000 help This enables MTD access to flash devices on platforms based on Intel's IXP2000 family of network processors such as the @@ -464,7 +467,7 @@ config MTD_IXP2000 config MTD_EPXA10DB tristate "CFI Flash device mapped on Epxa10db" - depends on ARM && MTD_CFI && MTD_PARTITIONS && ARCH_CAMELOT + depends on MTD_CFI && MTD_PARTITIONS && ARCH_CAMELOT help This enables support for the flash devices on the Altera Excalibur XA10 Development Board. If you are building a kernel @@ -472,21 +475,21 @@ config MTD_EPXA10DB config MTD_FORTUNET tristate "CFI Flash device mapped on the FortuNet board" - depends on ARM && MTD_CFI && MTD_PARTITIONS && SA1100_FORTUNET + depends on MTD_CFI && MTD_PARTITIONS && SA1100_FORTUNET help This enables access to the Flash on the FortuNet board. If you have such a board, say 'Y'. config MTD_AUTCPU12 tristate "NV-RAM mapping AUTCPU12 board" - depends on ARM && ARCH_AUTCPU12 + depends on ARCH_AUTCPU12 help This enables access to the NV-RAM on autronix autcpu12 board. If you have such a board, say 'Y'. config MTD_EDB7312 tristate "CFI Flash device mapped on EDB7312" - depends on ARM && MTD_CFI + depends on ARCH_EDB7312 && MTD_CFI help This enables access to the CFI Flash on the Cogent EDB7312 board. If you have such a board, say 'Y' here. @@ -500,7 +503,7 @@ config MTD_IMPA7 config MTD_CEIVA tristate "JEDEC Flash device mapped on Ceiva/Polaroid PhotoMax Digital Picture Frame" - depends on ARM && MTD_JEDECPROBE && ARCH_CEIVA + depends on MTD_JEDECPROBE && ARCH_CEIVA help This enables access to the flash chips on the Ceiva/Polaroid PhotoMax Digital Picture Frame. @@ -508,21 +511,21 @@ config MTD_CEIVA config MTD_NOR_TOTO tristate "NOR Flash device on TOTO board" - depends on ARM && ARCH_OMAP && OMAP_TOTO + depends on ARCH_OMAP && OMAP_TOTO help This enables access to the NOR flash on the Texas Instruments TOTO board. config MTD_H720X tristate "Hynix evaluation board mappings" - depends on ARM && MTD_CFI && ( ARCH_H7201 || ARCH_H7202 ) + depends on MTD_CFI && ( ARCH_H7201 || ARCH_H7202 ) help This enables access to the flash chips on the Hynix evaluation boards. If you have such a board, say 'Y'. config MTD_MPC1211 tristate "CFI Flash device mapped on Interface MPC-1211" - depends on SUPERH && SH_MPC1211 && MTD_CFI + depends on SH_MPC1211 && MTD_CFI help This enables access to the flash chips on the Interface MPC-1211(CTP/PCI/MPC-SH02). If you have such a board, say 'Y'. -- cgit v1.2.3 From 8b37b94721533f2729c79bcb6fa0bb3e2bc2f400 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 6 Nov 2005 15:47:02 -0800 Subject: [IB] umad: two small fixes Two small fixes for the umad module: - set kobject name for issm device properly - in ib_umad_add_one(), s is subtracted from the index i when initializing ports, so s should be subtracted from the index when freeing ports in the error path as well. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/core/user_mad.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index aed5ca23fb2..6aefeed42ab 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -801,7 +801,7 @@ static int ib_umad_init_port(struct ib_device *device, int port_num, goto err_class; port->sm_dev->owner = THIS_MODULE; port->sm_dev->ops = &umad_sm_fops; - kobject_set_name(&port->dev->kobj, "issm%d", port->dev_num); + kobject_set_name(&port->sm_dev->kobj, "issm%d", port->dev_num); if (cdev_add(port->sm_dev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1)) goto err_sm_cdev; @@ -913,7 +913,7 @@ static void ib_umad_add_one(struct ib_device *device) err: while (--i >= s) - ib_umad_kill_port(&umad_dev->port[i]); + ib_umad_kill_port(&umad_dev->port[i - s]); kref_put(&umad_dev->ref, ib_umad_release_dev); } -- cgit v1.2.3 From f0250fd7c32d441be54e50f39eed6fbbe9bb100e Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 01:11:04 +0100 Subject: Revert "[PATCH] OneNAND: Add simulator" This reverts 405c829f98d216925de00af2ee52f969f2c2891c commit. --- drivers/mtd/onenand/Kconfig | 7 - drivers/mtd/onenand/Makefile | 3 - drivers/mtd/onenand/onenand_sim.c | 464 -------------------------------------- 3 files changed, 474 deletions(-) delete mode 100644 drivers/mtd/onenand/onenand_sim.c diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig index fa5045c9d6e..0b2b29320c0 100644 --- a/drivers/mtd/onenand/Kconfig +++ b/drivers/mtd/onenand/Kconfig @@ -36,11 +36,4 @@ config MTD_ONENAND_SYNC_READ help This enables support for Sync. Burst Read. -config MTD_ONENAND_SIM - tristate "Support for OneNAND flash simulator" - depends on MTD_ONENAND - help - The simulator may simulate verious OneNAND flash chips for the - MTD onenand layer. - endmenu diff --git a/drivers/mtd/onenand/Makefile b/drivers/mtd/onenand/Makefile index 4d2eacfd7e1..269cfe46734 100644 --- a/drivers/mtd/onenand/Makefile +++ b/drivers/mtd/onenand/Makefile @@ -8,7 +8,4 @@ obj-$(CONFIG_MTD_ONENAND) += onenand.o # Board specific. obj-$(CONFIG_MTD_ONENAND_GENERIC) += generic.o -# Simulator -obj-$(CONFIG_MTD_ONENAND_SIM) += onenand_sim.o - onenand-objs = onenand_base.o onenand_bbt.o diff --git a/drivers/mtd/onenand/onenand_sim.c b/drivers/mtd/onenand/onenand_sim.c deleted file mode 100644 index cb376b20695..00000000000 --- a/drivers/mtd/onenand/onenand_sim.c +++ /dev/null @@ -1,464 +0,0 @@ -/* - * linux/drivers/mtd/onenand/simulator.c - * - * The OneNAND simulator - * - * Copyright(c) 2005 Samsung Electronics - * Kyungmin Park - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifndef CONFIG_ONENAND_SIM_MANUFACTURER -#define CONFIG_ONENAND_SIM_MANUFACTURER 0xec -#endif -#ifndef CONFIG_ONENAND_SIM_DEVICE_ID -#define CONFIG_ONENAND_SIM_DEVICE_ID 0x04 -#endif -#ifndef CONFIG_ONENAND_SIM_VERSION_ID -#define CONFIG_ONENAND_SIM_VERSION_ID 0x1e -#endif - -static int manuf_id = CONFIG_ONENAND_SIM_MANUFACTURER; -static int device_id = CONFIG_ONENAND_SIM_DEVICE_ID; -static int version_id = CONFIG_ONENAND_SIM_VERSION_ID; - -struct onenand_flash { - void __iomem *base; - void __iomem *data; -}; - -#define ONENAND_CORE(flash) (flash->data) - -#define ONENAND_MAIN_AREA(this, offset) \ - (this->base + ONENAND_DATARAM + offset) - -#define ONENAND_SPARE_AREA(this, offset) \ - (this->base + ONENAND_SPARERAM + offset) - -#define ONENAND_GET_WP_STATUS(this) \ - (readw(this->base + ONENAND_REG_WP_STATUS)) - -#define ONENAND_SET_WP_STATUS(v, this) \ - (writew(v, this->base + ONENAND_REG_WP_STATUS)) - -/* It has all 0xff chars */ -static unsigned char *ffchars; - -/* - * OneNAND simulator mtd - */ -struct mtd_info *onenand_sim; - - -/** - * onenand_lock_handle - Handle Lock scheme - * @param this OneNAND device structure - * @param cmd The command to be sent - * - * Send lock command to OneNAND device. - * The lock scheme is depends on chip type. - */ -static void onenand_lock_handle(struct onenand_chip *this, int cmd) -{ - int block_lock_scheme; - int status; - - status = ONENAND_GET_WP_STATUS(this); - block_lock_scheme = !(this->options & ONENAND_CONT_LOCK); - - switch (cmd) { - case ONENAND_CMD_UNLOCK: - if (block_lock_scheme) - ONENAND_SET_WP_STATUS(ONENAND_WP_US, this); - else - ONENAND_SET_WP_STATUS(status | ONENAND_WP_US, this); - break; - - case ONENAND_CMD_LOCK: - if (block_lock_scheme) - ONENAND_SET_WP_STATUS(ONENAND_WP_LS, this); - else - ONENAND_SET_WP_STATUS(status | ONENAND_WP_LS, this); - break; - - case ONENAND_CMD_LOCK_TIGHT: - if (block_lock_scheme) - ONENAND_SET_WP_STATUS(ONENAND_WP_LTS, this); - else - ONENAND_SET_WP_STATUS(status | ONENAND_WP_LTS, this); - break; - - default: - break; - } -} - -/** - * onenand_bootram_handle - Handle BootRAM area - * @param this OneNAND device structure - * @param cmd The command to be sent - * - * Emulate BootRAM area. It is possible to do basic operation using BootRAM. - */ -static void onenand_bootram_handle(struct onenand_chip *this, int cmd) -{ - switch (cmd) { - case ONENAND_CMD_READID: - writew(manuf_id, this->base); - writew(device_id, this->base + 2); - writew(version_id, this->base + 4); - break; - - default: - /* REVIST: Handle other commands */ - break; - } -} - -/** - * onenand_update_interrupt - Set interrupt register - * @param this OneNAND device structure - * @param cmd The command to be sent - * - * Update interrupt register. The status is depends on command. - */ -static void onenand_update_interrupt(struct onenand_chip *this, int cmd) -{ - int interrupt = ONENAND_INT_MASTER; - - switch (cmd) { - case ONENAND_CMD_READ: - case ONENAND_CMD_READOOB: - interrupt |= ONENAND_INT_READ; - break; - - case ONENAND_CMD_PROG: - case ONENAND_CMD_PROGOOB: - interrupt |= ONENAND_INT_WRITE; - break; - - case ONENAND_CMD_ERASE: - interrupt |= ONENAND_INT_ERASE; - break; - - case ONENAND_CMD_RESET: - interrupt |= ONENAND_INT_RESET; - break; - - default: - break; - } - - writew(interrupt, this->base + ONENAND_REG_INTERRUPT); -} - -/** - * onenand_check_overwrite - Check over-write if happend - * @param dest The destination pointer - * @param src The source pointer - * @param count The length to be check - * @return 0 on same, otherwise 1 - * - * Compare the source with destination - */ -static int onenand_check_overwrite(void *dest, void *src, size_t count) -{ - unsigned int *s = (unsigned int *) src; - unsigned int *d = (unsigned int *) dest; - int i; - count >>= 2; - - for (i = 0; i < count; i++) - if ((*s++ ^ *d++) != 0) - return 1; - - return 0; -} - -/** - * onenand_data_handle - Handle OneNAND Core and DataRAM - * @param this OneNAND device structure - * @param cmd The command to be sent - * @param dataram Which dataram used - * @param offset The offset to OneNAND Core - * - * Copy data from OneNAND Core to DataRAM (read) - * Copy data from DataRAM to OneNAND Core (write) - * Erase the OneNAND Core (erase) - */ -static void onenand_data_handle(struct onenand_chip *this, int cmd, - int dataram, unsigned int offset) -{ - struct onenand_flash *flash = this->priv; - int main_offset, spare_offset; - void __iomem *src; - void __iomem *dest; - - if (dataram) { - main_offset = onenand_sim->oobblock; - spare_offset = onenand_sim->oobsize; - } else { - main_offset = 0; - spare_offset = 0; - } - - switch (cmd) { - case ONENAND_CMD_READ: - src = ONENAND_CORE(flash) + offset; - dest = ONENAND_MAIN_AREA(this, main_offset); - memcpy(dest, src, onenand_sim->oobblock); - /* Fall through */ - - case ONENAND_CMD_READOOB: - src = ONENAND_CORE(flash) + this->chipsize + (offset >> 5); - dest = ONENAND_SPARE_AREA(this, spare_offset); - memcpy(dest, src, onenand_sim->oobsize); - break; - - case ONENAND_CMD_PROG: - src = ONENAND_MAIN_AREA(this, main_offset); - dest = ONENAND_CORE(flash) + offset; - if (memcmp(dest, ffchars, onenand_sim->oobblock) && - onenand_check_overwrite(dest, src, onenand_sim->oobblock)) - printk(KERN_ERR "over-write happend at 0x%08x\n", offset); - memcpy(dest, src, onenand_sim->oobblock); - /* Fall through */ - - case ONENAND_CMD_PROGOOB: - src = ONENAND_SPARE_AREA(this, spare_offset); - /* Check all data is 0xff chars */ - if (!memcmp(src, ffchars, onenand_sim->oobsize)) - break; - - dest = ONENAND_CORE(flash) + this->chipsize + (offset >> 5); - if (memcmp(dest, ffchars, onenand_sim->oobsize) && - onenand_check_overwrite(dest, src, onenand_sim->oobsize)) - printk(KERN_ERR "OOB: over-write happend at 0x%08x\n", offset); - memcpy(dest, src, onenand_sim->oobsize); - break; - - case ONENAND_CMD_ERASE: - memset(ONENAND_CORE(flash) + offset, 0xff, (1 << this->erase_shift)); - break; - - default: - break; - } -} - -/** - * onenand_command_handle - Handle command - * @param this OneNAND device structure - * @param cmd The command to be sent - * - * Emulate OneNAND command. - */ -static void onenand_command_handle(struct onenand_chip *this, int cmd) -{ - unsigned long offset = 0; - int block = -1, page = -1, bufferram = -1; - int dataram = 0; - - switch (cmd) { - case ONENAND_CMD_UNLOCK: - case ONENAND_CMD_LOCK: - case ONENAND_CMD_LOCK_TIGHT: - onenand_lock_handle(this, cmd); - break; - - case ONENAND_CMD_BUFFERRAM: - /* Do nothing */ - return; - - default: - block = (int) readw(this->base + ONENAND_REG_START_ADDRESS1); - if (block & (1 << ONENAND_DDP_SHIFT)) { - block &= ~(1 << ONENAND_DDP_SHIFT); - /* The half of chip block */ - block += this->chipsize >> (this->erase_shift + 1); - } - if (cmd == ONENAND_CMD_ERASE) - break; - - page = (int) readw(this->base + ONENAND_REG_START_ADDRESS8); - page = (page >> ONENAND_FPA_SHIFT); - bufferram = (int) readw(this->base + ONENAND_REG_START_BUFFER); - bufferram >>= ONENAND_BSA_SHIFT; - bufferram &= ONENAND_BSA_DATARAM1; - dataram = (bufferram == ONENAND_BSA_DATARAM1) ? 1 : 0; - break; - } - - if (block != -1) - offset += block << this->erase_shift; - - if (page != -1) - offset += page << this->page_shift; - - onenand_data_handle(this, cmd, dataram, offset); - - onenand_update_interrupt(this, cmd); -} - -/** - * onenand_writew - [OneNAND Interface] Emulate write operation - * @param value value to write - * @param addr address to write - * - * Write OneNAND reigser with value - */ -static void onenand_writew(unsigned short value, void __iomem *addr) -{ - struct onenand_chip *this = onenand_sim->priv; - - /* BootRAM handling */ - if (addr < this->base + ONENAND_DATARAM) { - onenand_bootram_handle(this, value); - return; - } - /* Command handling */ - if (addr == this->base + ONENAND_REG_COMMAND) - onenand_command_handle(this, value); - - writew(value, addr); -} - -/** - * flash_init - Initialize OneNAND simulator - * @param flash OneNAND simulaotr data strucutres - * - * Initialize OneNAND simulator. - */ -static int __init flash_init(struct onenand_flash *flash) -{ - int density, size; - int buffer_size; - - flash->base = kmalloc(SZ_128K, GFP_KERNEL); - if (!flash->base) { - printk(KERN_ERR "Unalbe to allocate base address.\n"); - return -ENOMEM; - } - - memset(flash->base, 0, SZ_128K); - - density = device_id >> ONENAND_DEVICE_DENSITY_SHIFT; - size = ((16 << 20) << density); - - ONENAND_CORE(flash) = vmalloc(size + (size >> 5)); - if (!ONENAND_CORE(flash)) { - printk(KERN_ERR "Unalbe to allocate nand core address.\n"); - kfree(flash->base); - return -ENOMEM; - } - - memset(ONENAND_CORE(flash), 0xff, size + (size >> 5)); - - /* Setup registers */ - writew(manuf_id, flash->base + ONENAND_REG_MANUFACTURER_ID); - writew(device_id, flash->base + ONENAND_REG_DEVICE_ID); - writew(version_id, flash->base + ONENAND_REG_VERSION_ID); - - if (density < 2) - buffer_size = 0x0400; /* 1KB page */ - else - buffer_size = 0x0800; /* 2KB page */ - writew(buffer_size, flash->base + ONENAND_REG_DATA_BUFFER_SIZE); - - return 0; -} - -/** - * flash_exit - Clean up OneNAND simulator - * @param flash OneNAND simulaotr data strucutres - * - * Clean up OneNAND simulator. - */ -static void flash_exit(struct onenand_flash *flash) -{ - vfree(ONENAND_CORE(flash)); - kfree(flash->base); - kfree(flash); -} - -static int __init onenand_sim_init(void) -{ - struct onenand_chip *this; - struct onenand_flash *flash; - int len; - - /* Allocate all 0xff chars pointer */ - ffchars = kmalloc(MAX_ONENAND_PAGESIZE, GFP_KERNEL); - if (!ffchars) { - printk(KERN_ERR "Unable to allocate ff chars.\n"); - return -ENOMEM; - } - memset(ffchars, 0xff, MAX_ONENAND_PAGESIZE); - - len = sizeof(struct mtd_info) + sizeof(struct onenand_chip) + sizeof (struct onenand_flash); - - /* Allocate OneNAND simulator mtd pointer */ - onenand_sim = kmalloc(len, GFP_KERNEL); - if (!onenand_sim) { - printk(KERN_ERR "Unable to allocate core structures.\n"); - kfree(ffchars); - return -ENOMEM; - } - - memset(onenand_sim, 0, len); - - this = (struct onenand_chip *) (onenand_sim + 1); - /* Override write_word function */ - this->write_word = onenand_writew; - - flash = (struct onenand_flash *) (this + 1); - - if (flash_init(flash)) { - printk(KERN_ERR "Unable to allocat flash.\n"); - kfree(ffchars); - kfree(onenand_sim); - return -ENOMEM; - } - - this->base = flash->base; - this->priv = flash; - onenand_sim->priv = this; - - if (onenand_scan(onenand_sim, 1)) { - kfree(ffchars); - kfree(onenand_sim); - flash_exit(flash); - return -ENXIO; - } - - add_mtd_device(onenand_sim); - - return 0; -} - -static void __exit onenand_sim_exit(void) -{ - struct onenand_chip *this = onenand_sim->priv; - struct onenand_flash *flash = this->priv; - - kfree(ffchars); - onenand_release(onenand_sim); - flash_exit(flash); - kfree(onenand_sim); -} - -module_init(onenand_sim_init); -module_exit(onenand_sim_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Kyungmin Park "); -MODULE_DESCRIPTION("The OneNAND flash simulator"); -- cgit v1.2.3 From 46d0d0fb61ec6630dc2c844e3c5bf5ef44dedcbe Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 01:14:05 +0100 Subject: [MTD] OneNAND/Kconfig: Fix dependencies Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/Kconfig | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig index 0b2b29320c0..126ff6bf63d 100644 --- a/drivers/mtd/onenand/Kconfig +++ b/drivers/mtd/onenand/Kconfig @@ -24,11 +24,10 @@ config MTD_ONENAND_VERIFY_WRITE flipped accidentaly due to device wear or something else. config MTD_ONENAND_GENERIC - tristate "OneNAND Flash device on generic board" - depends on MTD_ONENAND + tristate "OneNAND Flash device via platform device driver" + depends on MTD_ONENAND && ARM help - Support for OneNAND flash on generic board. Using device driver - framework, now all most platfrom are support. + Support for OneNAND flash via platform device driver. config MTD_ONENAND_SYNC_READ bool "OneNAND Sync. Burst Read Support" -- cgit v1.2.3 From 3c726f8dee6f55e96475574e9f645327e461884c Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 7 Nov 2005 11:06:55 +1100 Subject: [PATCH] ppc64: support 64k pages Adds a new CONFIG_PPC_64K_PAGES which, when enabled, changes the kernel base page size to 64K. The resulting kernel still boots on any hardware. On current machines with 4K pages support only, the kernel will maintain 16 "subpages" for each 64K page transparently. Note that while real 64K capable HW has been tested, the current patch will not enable it yet as such hardware is not released yet, and I'm still verifying with the firmware architects the proper to get the information from the newer hypervisors. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Linus Torvalds --- arch/powerpc/Kconfig | 9 + arch/powerpc/kernel/asm-offsets.c | 3 + arch/powerpc/kernel/cputable.c | 4 +- arch/powerpc/kernel/head_64.S | 300 +++++++++++---- arch/powerpc/kernel/lparmap.c | 2 +- arch/powerpc/kernel/process.c | 6 +- arch/powerpc/kernel/prom.c | 76 ++-- arch/powerpc/kernel/setup_64.c | 31 +- arch/powerpc/lib/copypage_64.S | 2 +- arch/powerpc/lib/copyuser_64.S | 4 +- arch/powerpc/mm/hash_low_64.S | 613 +++++++++++++++++++++++++++++-- arch/powerpc/mm/hash_native_64.c | 377 +++++++++++-------- arch/powerpc/mm/hash_utils_64.c | 532 +++++++++++++++++++++------ arch/powerpc/mm/hugetlbpage.c | 134 ++++--- arch/powerpc/mm/init_64.c | 18 +- arch/powerpc/mm/mem.c | 56 ++- arch/powerpc/mm/pgtable_64.c | 22 +- arch/powerpc/mm/ppc_mmu_32.c | 15 + arch/powerpc/mm/slb.c | 102 ++++- arch/powerpc/mm/slb_low.S | 220 +++++++---- arch/powerpc/mm/stab.c | 30 +- arch/powerpc/mm/tlb_64.c | 32 +- arch/powerpc/platforms/iseries/htab.c | 65 ++-- arch/powerpc/platforms/iseries/hvlog.c | 4 +- arch/powerpc/platforms/iseries/iommu.c | 74 ++-- arch/powerpc/platforms/iseries/setup.c | 13 +- arch/powerpc/platforms/iseries/vio.c | 39 +- arch/powerpc/platforms/iseries/viopath.c | 16 +- arch/powerpc/platforms/pseries/lpar.c | 115 +++--- arch/ppc64/Kconfig | 13 + arch/ppc64/kernel/asm-offsets.c | 3 + arch/ppc64/kernel/head.S | 300 +++++++++++---- arch/ppc64/kernel/pacaData.c | 2 +- arch/ppc64/kernel/prom.c | 94 ++--- include/asm-powerpc/cputable.h | 3 + include/asm-powerpc/iommu.h | 5 + include/asm-powerpc/machdep.h | 10 +- include/asm-powerpc/prom.h | 8 + include/asm-powerpc/system.h | 2 +- include/asm-powerpc/thread_info.h | 20 +- include/asm-powerpc/tlbflush.h | 9 +- include/asm-ppc64/mmu.h | 208 ++++++----- include/asm-ppc64/mmu_context.h | 15 +- include/asm-ppc64/paca.h | 13 +- include/asm-ppc64/page.h | 147 ++++++-- include/asm-ppc64/pgalloc.h | 47 ++- include/asm-ppc64/pgtable-4k.h | 88 +++++ include/asm-ppc64/pgtable-64k.h | 87 +++++ include/asm-ppc64/pgtable.h | 160 +++----- include/asm-ppc64/prom.h | 8 + include/asm-ppc64/system.h | 2 +- mm/hugetlb.c | 3 + 52 files changed, 2949 insertions(+), 1212 deletions(-) create mode 100644 include/asm-ppc64/pgtable-4k.h create mode 100644 include/asm-ppc64/pgtable-64k.h diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index f4e25c648fb..ca7acb0c79f 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -603,6 +603,15 @@ config NODES_SPAN_OTHER_NODES def_bool y depends on NEED_MULTIPLE_NODES +config PPC_64K_PAGES + bool "64k page size" + help + This option changes the kernel logical page size to 64k. On machines + without processor support for 64k pages, the kernel will simulate + them by loading each individual 4k page on demand transparently, + while on hardware with such support, it will be used to map + normal application pages. + config SCHED_SMT bool "SMT (Hyperthreading) scheduler support" depends on PPC64 && SMP diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index bc5a3689cc0..b7575725199 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -125,6 +125,9 @@ int main(void) DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); +#ifdef CONFIG_PPC_64K_PAGES + DEFINE(PACAPGDIR, offsetof(struct paca_struct, pgdir)); +#endif #ifdef CONFIG_HUGETLB_PAGE DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas)); DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas)); diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index b91345fa080..33c63bcf69f 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -240,7 +240,7 @@ struct cpu_spec cpu_specs[] = { .oprofile_model = &op_model_power4, #endif }, - { /* Power5 */ + { /* Power5 GR */ .pvr_mask = 0xffff0000, .pvr_value = 0x003a0000, .cpu_name = "POWER5 (gr)", @@ -255,7 +255,7 @@ struct cpu_spec cpu_specs[] = { .oprofile_model = &op_model_power4, #endif }, - { /* Power5 */ + { /* Power5 GS */ .pvr_mask = 0xffff0000, .pvr_value = 0x003b0000, .cpu_name = "POWER5 (gs)", diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 45d81976987..16ab40daa73 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -195,11 +195,11 @@ exception_marker: #define EX_R12 24 #define EX_R13 32 #define EX_SRR0 40 -#define EX_R3 40 /* SLB miss saves R3, but not SRR0 */ #define EX_DAR 48 -#define EX_LR 48 /* SLB miss saves LR, but not DAR */ #define EX_DSISR 56 #define EX_CCR 60 +#define EX_R3 64 +#define EX_LR 72 #define EXCEPTION_PROLOG_PSERIES(area, label) \ mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ @@ -419,17 +419,22 @@ data_access_slb_pSeries: mtspr SPRN_SPRG1,r13 RUNLATCH_ON(r13) mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ + std r3,PACA_EXSLB+EX_R3(r13) + mfspr r3,SPRN_DAR std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ + mfcr r9 +#ifdef __DISABLED__ + /* Keep that around for when we re-implement dynamic VSIDs */ + cmpdi r3,0 + bge slb_miss_user_pseries +#endif /* __DISABLED__ */ std r10,PACA_EXSLB+EX_R10(r13) std r11,PACA_EXSLB+EX_R11(r13) std r12,PACA_EXSLB+EX_R12(r13) - std r3,PACA_EXSLB+EX_R3(r13) - mfspr r9,SPRN_SPRG1 - std r9,PACA_EXSLB+EX_R13(r13) - mfcr r9 + mfspr r10,SPRN_SPRG1 + std r10,PACA_EXSLB+EX_R13(r13) mfspr r12,SPRN_SRR1 /* and SRR1 */ - mfspr r3,SPRN_DAR - b .do_slb_miss /* Rel. branch works in real mode */ + b .slb_miss_realmode /* Rel. branch works in real mode */ STD_EXCEPTION_PSERIES(0x400, instruction_access) @@ -440,17 +445,22 @@ instruction_access_slb_pSeries: mtspr SPRN_SPRG1,r13 RUNLATCH_ON(r13) mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ + std r3,PACA_EXSLB+EX_R3(r13) + mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ + mfcr r9 +#ifdef __DISABLED__ + /* Keep that around for when we re-implement dynamic VSIDs */ + cmpdi r3,0 + bge slb_miss_user_pseries +#endif /* __DISABLED__ */ std r10,PACA_EXSLB+EX_R10(r13) std r11,PACA_EXSLB+EX_R11(r13) std r12,PACA_EXSLB+EX_R12(r13) - std r3,PACA_EXSLB+EX_R3(r13) - mfspr r9,SPRN_SPRG1 - std r9,PACA_EXSLB+EX_R13(r13) - mfcr r9 + mfspr r10,SPRN_SPRG1 + std r10,PACA_EXSLB+EX_R13(r13) mfspr r12,SPRN_SRR1 /* and SRR1 */ - mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ - b .do_slb_miss /* Rel. branch works in real mode */ + b .slb_miss_realmode /* Rel. branch works in real mode */ STD_EXCEPTION_PSERIES(0x500, hardware_interrupt) STD_EXCEPTION_PSERIES(0x600, alignment) @@ -508,6 +518,38 @@ _GLOBAL(do_stab_bolted_pSeries) mfspr r12,SPRN_SPRG2 EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted) +/* + * We have some room here we use that to put + * the peries slb miss user trampoline code so it's reasonably + * away from slb_miss_user_common to avoid problems with rfid + * + * This is used for when the SLB miss handler has to go virtual, + * which doesn't happen for now anymore but will once we re-implement + * dynamic VSIDs for shared page tables + */ +#ifdef __DISABLED__ +slb_miss_user_pseries: + std r10,PACA_EXGEN+EX_R10(r13) + std r11,PACA_EXGEN+EX_R11(r13) + std r12,PACA_EXGEN+EX_R12(r13) + mfspr r10,SPRG1 + ld r11,PACA_EXSLB+EX_R9(r13) + ld r12,PACA_EXSLB+EX_R3(r13) + std r10,PACA_EXGEN+EX_R13(r13) + std r11,PACA_EXGEN+EX_R9(r13) + std r12,PACA_EXGEN+EX_R3(r13) + clrrdi r12,r13,32 + mfmsr r10 + mfspr r11,SRR0 /* save SRR0 */ + ori r12,r12,slb_miss_user_common@l /* virt addr of handler */ + ori r10,r10,MSR_IR|MSR_DR|MSR_RI + mtspr SRR0,r12 + mfspr r12,SRR1 /* and SRR1 */ + mtspr SRR1,r10 + rfid + b . /* prevent spec. execution */ +#endif /* __DISABLED__ */ + /* * Vectors for the FWNMI option. Share common code. */ @@ -559,22 +601,59 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) .globl data_access_slb_iSeries data_access_slb_iSeries: mtspr SPRN_SPRG1,r13 /* save r13 */ - EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB) + mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ std r3,PACA_EXSLB+EX_R3(r13) - ld r12,PACALPPACA+LPPACASRR1(r13) mfspr r3,SPRN_DAR - b .do_slb_miss + std r9,PACA_EXSLB+EX_R9(r13) + mfcr r9 +#ifdef __DISABLED__ + cmpdi r3,0 + bge slb_miss_user_iseries +#endif + std r10,PACA_EXSLB+EX_R10(r13) + std r11,PACA_EXSLB+EX_R11(r13) + std r12,PACA_EXSLB+EX_R12(r13) + mfspr r10,SPRN_SPRG1 + std r10,PACA_EXSLB+EX_R13(r13) + ld r12,PACALPPACA+LPPACASRR1(r13); + b .slb_miss_realmode STD_EXCEPTION_ISERIES(0x400, instruction_access, PACA_EXGEN) .globl instruction_access_slb_iSeries instruction_access_slb_iSeries: mtspr SPRN_SPRG1,r13 /* save r13 */ - EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB) + mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ std r3,PACA_EXSLB+EX_R3(r13) - ld r12,PACALPPACA+LPPACASRR1(r13) - ld r3,PACALPPACA+LPPACASRR0(r13) - b .do_slb_miss + ld r3,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ + std r9,PACA_EXSLB+EX_R9(r13) + mfcr r9 +#ifdef __DISABLED__ + cmpdi r3,0 + bge .slb_miss_user_iseries +#endif + std r10,PACA_EXSLB+EX_R10(r13) + std r11,PACA_EXSLB+EX_R11(r13) + std r12,PACA_EXSLB+EX_R12(r13) + mfspr r10,SPRN_SPRG1 + std r10,PACA_EXSLB+EX_R13(r13) + ld r12,PACALPPACA+LPPACASRR1(r13); + b .slb_miss_realmode + +#ifdef __DISABLED__ +slb_miss_user_iseries: + std r10,PACA_EXGEN+EX_R10(r13) + std r11,PACA_EXGEN+EX_R11(r13) + std r12,PACA_EXGEN+EX_R12(r13) + mfspr r10,SPRG1 + ld r11,PACA_EXSLB+EX_R9(r13) + ld r12,PACA_EXSLB+EX_R3(r13) + std r10,PACA_EXGEN+EX_R13(r13) + std r11,PACA_EXGEN+EX_R9(r13) + std r12,PACA_EXGEN+EX_R3(r13) + EXCEPTION_PROLOG_ISERIES_2 + b slb_miss_user_common +#endif MASKABLE_EXCEPTION_ISERIES(0x500, hardware_interrupt) STD_EXCEPTION_ISERIES(0x600, alignment, PACA_EXGEN) @@ -809,6 +888,126 @@ instruction_access_common: li r5,0x400 b .do_hash_page /* Try to handle as hpte fault */ +/* + * Here is the common SLB miss user that is used when going to virtual + * mode for SLB misses, that is currently not used + */ +#ifdef __DISABLED__ + .align 7 + .globl slb_miss_user_common +slb_miss_user_common: + mflr r10 + std r3,PACA_EXGEN+EX_DAR(r13) + stw r9,PACA_EXGEN+EX_CCR(r13) + std r10,PACA_EXGEN+EX_LR(r13) + std r11,PACA_EXGEN+EX_SRR0(r13) + bl .slb_allocate_user + + ld r10,PACA_EXGEN+EX_LR(r13) + ld r3,PACA_EXGEN+EX_R3(r13) + lwz r9,PACA_EXGEN+EX_CCR(r13) + ld r11,PACA_EXGEN+EX_SRR0(r13) + mtlr r10 + beq- slb_miss_fault + + andi. r10,r12,MSR_RI /* check for unrecoverable exception */ + beq- unrecov_user_slb + mfmsr r10 + +.machine push +.machine "power4" + mtcrf 0x80,r9 +.machine pop + + clrrdi r10,r10,2 /* clear RI before setting SRR0/1 */ + mtmsrd r10,1 + + mtspr SRR0,r11 + mtspr SRR1,r12 + + ld r9,PACA_EXGEN+EX_R9(r13) + ld r10,PACA_EXGEN+EX_R10(r13) + ld r11,PACA_EXGEN+EX_R11(r13) + ld r12,PACA_EXGEN+EX_R12(r13) + ld r13,PACA_EXGEN+EX_R13(r13) + rfid + b . + +slb_miss_fault: + EXCEPTION_PROLOG_COMMON(0x380, PACA_EXGEN) + ld r4,PACA_EXGEN+EX_DAR(r13) + li r5,0 + std r4,_DAR(r1) + std r5,_DSISR(r1) + b .handle_page_fault + +unrecov_user_slb: + EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN) + DISABLE_INTS + bl .save_nvgprs +1: addi r3,r1,STACK_FRAME_OVERHEAD + bl .unrecoverable_exception + b 1b + +#endif /* __DISABLED__ */ + + +/* + * r13 points to the PACA, r9 contains the saved CR, + * r12 contain the saved SRR1, SRR0 is still ready for return + * r3 has the faulting address + * r9 - r13 are saved in paca->exslb. + * r3 is saved in paca->slb_r3 + * We assume we aren't going to take any exceptions during this procedure. + */ +_GLOBAL(slb_miss_realmode) + mflr r10 + + stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ + std r10,PACA_EXSLB+EX_LR(r13) /* save LR */ + + bl .slb_allocate_realmode + + /* All done -- return from exception. */ + + ld r10,PACA_EXSLB+EX_LR(r13) + ld r3,PACA_EXSLB+EX_R3(r13) + lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ +#ifdef CONFIG_PPC_ISERIES + ld r11,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ +#endif /* CONFIG_PPC_ISERIES */ + + mtlr r10 + + andi. r10,r12,MSR_RI /* check for unrecoverable exception */ + beq- unrecov_slb + +.machine push +.machine "power4" + mtcrf 0x80,r9 + mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */ +.machine pop + +#ifdef CONFIG_PPC_ISERIES + mtspr SPRN_SRR0,r11 + mtspr SPRN_SRR1,r12 +#endif /* CONFIG_PPC_ISERIES */ + ld r9,PACA_EXSLB+EX_R9(r13) + ld r10,PACA_EXSLB+EX_R10(r13) + ld r11,PACA_EXSLB+EX_R11(r13) + ld r12,PACA_EXSLB+EX_R12(r13) + ld r13,PACA_EXSLB+EX_R13(r13) + rfid + b . /* prevent speculative execution */ + +unrecov_slb: + EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) + DISABLE_INTS + bl .save_nvgprs +1: addi r3,r1,STACK_FRAME_OVERHEAD + bl .unrecoverable_exception + b 1b + .align 7 .globl hardware_interrupt_common .globl hardware_interrupt_entry @@ -1138,62 +1337,6 @@ _GLOBAL(do_stab_bolted) rfid b . /* prevent speculative execution */ -/* - * r13 points to the PACA, r9 contains the saved CR, - * r11 and r12 contain the saved SRR0 and SRR1. - * r3 has the faulting address - * r9 - r13 are saved in paca->exslb. - * r3 is saved in paca->slb_r3 - * We assume we aren't going to take any exceptions during this procedure. - */ -_GLOBAL(do_slb_miss) - mflr r10 - - stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ - std r10,PACA_EXSLB+EX_LR(r13) /* save LR */ - - bl .slb_allocate /* handle it */ - - /* All done -- return from exception. */ - - ld r10,PACA_EXSLB+EX_LR(r13) - ld r3,PACA_EXSLB+EX_R3(r13) - lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ -#ifdef CONFIG_PPC_ISERIES - ld r11,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ -#endif /* CONFIG_PPC_ISERIES */ - - mtlr r10 - - andi. r10,r12,MSR_RI /* check for unrecoverable exception */ - beq- unrecov_slb - -.machine push -.machine "power4" - mtcrf 0x80,r9 - mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */ -.machine pop - -#ifdef CONFIG_PPC_ISERIES - mtspr SPRN_SRR0,r11 - mtspr SPRN_SRR1,r12 -#endif /* CONFIG_PPC_ISERIES */ - ld r9,PACA_EXSLB+EX_R9(r13) - ld r10,PACA_EXSLB+EX_R10(r13) - ld r11,PACA_EXSLB+EX_R11(r13) - ld r12,PACA_EXSLB+EX_R12(r13) - ld r13,PACA_EXSLB+EX_R13(r13) - rfid - b . /* prevent speculative execution */ - -unrecov_slb: - EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) - DISABLE_INTS - bl .save_nvgprs -1: addi r3,r1,STACK_FRAME_OVERHEAD - bl .unrecoverable_exception - b 1b - /* * Space for CPU0's segment table. * @@ -1569,7 +1712,10 @@ _GLOBAL(__secondary_start) #endif /* Initialize the first segment table (or SLB) entry */ ld r3,PACASTABVIRT(r13) /* get addr of segment table */ +BEGIN_FTR_SECTION bl .stab_initialize +END_FTR_SECTION_IFCLR(CPU_FTR_SLB) + bl .slb_initialize /* Initialize the kernel stack. Just a repeat for iSeries. */ LOADADDR(r3,current_set) diff --git a/arch/powerpc/kernel/lparmap.c b/arch/powerpc/kernel/lparmap.c index eded971d1bf..5a05a797485 100644 --- a/arch/powerpc/kernel/lparmap.c +++ b/arch/powerpc/kernel/lparmap.c @@ -25,7 +25,7 @@ const struct LparMap __attribute__((__section__(".text"))) xLparMap = { .xRanges = { { .xPages = HvPagesToMap, .xOffset = 0, - .xVPN = KERNEL_VSID(KERNELBASE) << (SID_SHIFT - PAGE_SHIFT), + .xVPN = KERNEL_VSID(KERNELBASE) << (SID_SHIFT - HW_PAGE_SHIFT), }, }, }; diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 96843211cc5..7f64f0464d4 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -554,12 +554,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, #ifdef CONFIG_PPC64 if (cpu_has_feature(CPU_FTR_SLB)) { unsigned long sp_vsid = get_kernel_vsid(sp); + unsigned long llp = mmu_psize_defs[mmu_linear_psize].sllp; sp_vsid <<= SLB_VSID_SHIFT; - sp_vsid |= SLB_VSID_KERNEL; - if (cpu_has_feature(CPU_FTR_16M_PAGE)) - sp_vsid |= SLB_VSID_L; - + sp_vsid |= SLB_VSID_KERNEL | llp; p->thread.ksp_vsid = sp_vsid; } diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index eec2da69550..3675ef4bac9 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -724,10 +724,10 @@ static inline char *find_flat_dt_string(u32 offset) * used to extract the memory informations at boot before we can * unflatten the tree */ -static int __init scan_flat_dt(int (*it)(unsigned long node, - const char *uname, int depth, - void *data), - void *data) +int __init of_scan_flat_dt(int (*it)(unsigned long node, + const char *uname, int depth, + void *data), + void *data) { unsigned long p = ((unsigned long)initial_boot_params) + initial_boot_params->off_dt_struct; @@ -784,8 +784,8 @@ static int __init scan_flat_dt(int (*it)(unsigned long node, * This function can be used within scan_flattened_dt callback to get * access to properties */ -static void* __init get_flat_dt_prop(unsigned long node, const char *name, - unsigned long *size) +void* __init of_get_flat_dt_prop(unsigned long node, const char *name, + unsigned long *size) { unsigned long p = node; @@ -1087,7 +1087,7 @@ void __init unflatten_device_tree(void) static int __init early_init_dt_scan_cpus(unsigned long node, const char *uname, int depth, void *data) { - char *type = get_flat_dt_prop(node, "device_type", NULL); + char *type = of_get_flat_dt_prop(node, "device_type", NULL); u32 *prop; unsigned long size = 0; @@ -1095,19 +1095,6 @@ static int __init early_init_dt_scan_cpus(unsigned long node, if (type == NULL || strcmp(type, "cpu") != 0) return 0; -#ifdef CONFIG_PPC_PSERIES - /* On LPAR, look for the first ibm,pft-size property for the hash table size - */ - if (systemcfg->platform == PLATFORM_PSERIES_LPAR && ppc64_pft_size == 0) { - u32 *pft_size; - pft_size = get_flat_dt_prop(node, "ibm,pft-size", NULL); - if (pft_size != NULL) { - /* pft_size[0] is the NUMA CEC cookie */ - ppc64_pft_size = pft_size[1]; - } - } -#endif - boot_cpuid = 0; boot_cpuid_phys = 0; if (initial_boot_params && initial_boot_params->version >= 2) { @@ -1117,8 +1104,9 @@ static int __init early_init_dt_scan_cpus(unsigned long node, boot_cpuid_phys = initial_boot_params->boot_cpuid_phys; } else { /* Check if it's the boot-cpu, set it's hw index now */ - if (get_flat_dt_prop(node, "linux,boot-cpu", NULL) != NULL) { - prop = get_flat_dt_prop(node, "reg", NULL); + if (of_get_flat_dt_prop(node, + "linux,boot-cpu", NULL) != NULL) { + prop = of_get_flat_dt_prop(node, "reg", NULL); if (prop != NULL) boot_cpuid_phys = *prop; } @@ -1127,14 +1115,14 @@ static int __init early_init_dt_scan_cpus(unsigned long node, #ifdef CONFIG_ALTIVEC /* Check if we have a VMX and eventually update CPU features */ - prop = (u32 *)get_flat_dt_prop(node, "ibm,vmx", &size); + prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", &size); if (prop && (*prop) > 0) { cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; } /* Same goes for Apple's "altivec" property */ - prop = (u32 *)get_flat_dt_prop(node, "altivec", NULL); + prop = (u32 *)of_get_flat_dt_prop(node, "altivec", NULL); if (prop) { cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; @@ -1147,7 +1135,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node, * this by looking at the size of the ibm,ppc-interrupt-server#s * property */ - prop = (u32 *)get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", + prop = (u32 *)of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &size); cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT; if (prop && ((size / sizeof(u32)) > 1)) @@ -1170,7 +1158,7 @@ static int __init early_init_dt_scan_chosen(unsigned long node, return 0; /* get platform type */ - prop = (u32 *)get_flat_dt_prop(node, "linux,platform", NULL); + prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL); if (prop == NULL) return 0; #ifdef CONFIG_PPC64 @@ -1183,21 +1171,21 @@ static int __init early_init_dt_scan_chosen(unsigned long node, #ifdef CONFIG_PPC64 /* check if iommu is forced on or off */ - if (get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) + if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) iommu_is_off = 1; - if (get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL) + if (of_get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL) iommu_force_on = 1; #endif - lprop = get_flat_dt_prop(node, "linux,memory-limit", NULL); + lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL); if (lprop) memory_limit = *lprop; #ifdef CONFIG_PPC64 - lprop = get_flat_dt_prop(node, "linux,tce-alloc-start", NULL); + lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-start", NULL); if (lprop) tce_alloc_start = *lprop; - lprop = get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); + lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); if (lprop) tce_alloc_end = *lprop; #endif @@ -1209,9 +1197,9 @@ static int __init early_init_dt_scan_chosen(unsigned long node, { u64 *basep, *entryp; - basep = get_flat_dt_prop(node, "linux,rtas-base", NULL); - entryp = get_flat_dt_prop(node, "linux,rtas-entry", NULL); - prop = get_flat_dt_prop(node, "linux,rtas-size", NULL); + basep = of_get_flat_dt_prop(node, "linux,rtas-base", NULL); + entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL); + prop = of_get_flat_dt_prop(node, "linux,rtas-size", NULL); if (basep && entryp && prop) { rtas.base = *basep; rtas.entry = *entryp; @@ -1232,11 +1220,11 @@ static int __init early_init_dt_scan_root(unsigned long node, if (depth != 0) return 0; - prop = get_flat_dt_prop(node, "#size-cells", NULL); + prop = of_get_flat_dt_prop(node, "#size-cells", NULL); dt_root_size_cells = (prop == NULL) ? 1 : *prop; DBG("dt_root_size_cells = %x\n", dt_root_size_cells); - prop = get_flat_dt_prop(node, "#address-cells", NULL); + prop = of_get_flat_dt_prop(node, "#address-cells", NULL); dt_root_addr_cells = (prop == NULL) ? 2 : *prop; DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells); @@ -1271,7 +1259,7 @@ static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp) static int __init early_init_dt_scan_memory(unsigned long node, const char *uname, int depth, void *data) { - char *type = get_flat_dt_prop(node, "device_type", NULL); + char *type = of_get_flat_dt_prop(node, "device_type", NULL); cell_t *reg, *endp; unsigned long l; @@ -1279,7 +1267,7 @@ static int __init early_init_dt_scan_memory(unsigned long node, if (type == NULL || strcmp(type, "memory") != 0) return 0; - reg = (cell_t *)get_flat_dt_prop(node, "reg", &l); + reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); if (reg == NULL) return 0; @@ -1343,12 +1331,12 @@ void __init early_init_devtree(void *params) * device-tree, including the platform type, initrd location and * size, TCE reserve, and more ... */ - scan_flat_dt(early_init_dt_scan_chosen, NULL); + of_scan_flat_dt(early_init_dt_scan_chosen, NULL); /* Scan memory nodes and rebuild LMBs */ lmb_init(); - scan_flat_dt(early_init_dt_scan_root, NULL); - scan_flat_dt(early_init_dt_scan_memory, NULL); + of_scan_flat_dt(early_init_dt_scan_root, NULL); + of_scan_flat_dt(early_init_dt_scan_memory, NULL); lmb_enforce_memory_limit(memory_limit); lmb_analyze(); #ifdef CONFIG_PPC64 @@ -1363,10 +1351,10 @@ void __init early_init_devtree(void *params) DBG("Scanning CPUs ...\n"); - /* Retreive hash table size from flattened tree plus other - * CPU related informations (altivec support, boot CPU ID, ...) + /* Retreive CPU related informations from the flat tree + * (altivec support, boot CPU ID, ...) */ - scan_flat_dt(early_init_dt_scan_cpus, NULL); + of_scan_flat_dt(early_init_dt_scan_cpus, NULL); DBG(" <- early_init_devtree()\n"); } diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 6b52cce872b..b0994050024 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -277,16 +277,21 @@ void __init early_setup(unsigned long dt_ptr) DBG("Found, Initializing memory management...\n"); /* - * Initialize stab / SLB management + * Initialize the MMU Hash table and create the linear mapping + * of memory. Has to be done before stab/slb initialization as + * this is currently where the page size encoding is obtained */ - if (!firmware_has_feature(FW_FEATURE_ISERIES)) - stab_initialize(lpaca->stab_real); + htab_initialize(); /* - * Initialize the MMU Hash table and create the linear mapping - * of memory + * Initialize stab / SLB management except on iSeries */ - htab_initialize(); + if (!firmware_has_feature(FW_FEATURE_ISERIES)) { + if (cpu_has_feature(CPU_FTR_SLB)) + slb_initialize(); + else + stab_initialize(lpaca->stab_real); + } DBG(" <- early_setup()\n"); } @@ -552,10 +557,12 @@ static void __init irqstack_early_init(void) * SLB misses on them. */ for_each_cpu(i) { - softirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE, - THREAD_SIZE, 0x10000000)); - hardirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE, - THREAD_SIZE, 0x10000000)); + softirq_ctx[i] = (struct thread_info *) + __va(lmb_alloc_base(THREAD_SIZE, + THREAD_SIZE, 0x10000000)); + hardirq_ctx[i] = (struct thread_info *) + __va(lmb_alloc_base(THREAD_SIZE, + THREAD_SIZE, 0x10000000)); } } #else @@ -583,8 +590,8 @@ static void __init emergency_stack_init(void) limit = min(0x10000000UL, lmb.rmo_size); for_each_cpu(i) - paca[i].emergency_sp = __va(lmb_alloc_base(PAGE_SIZE, 128, - limit)) + PAGE_SIZE; + paca[i].emergency_sp = + __va(lmb_alloc_base(HW_PAGE_SIZE, 128, limit)) + HW_PAGE_SIZE; } /* diff --git a/arch/powerpc/lib/copypage_64.S b/arch/powerpc/lib/copypage_64.S index 733d61618bb..40523b14010 100644 --- a/arch/powerpc/lib/copypage_64.S +++ b/arch/powerpc/lib/copypage_64.S @@ -11,7 +11,7 @@ #include #include -_GLOBAL(copy_page) +_GLOBAL(copy_4K_page) std r31,-8(1) std r30,-16(1) std r29,-24(1) diff --git a/arch/powerpc/lib/copyuser_64.S b/arch/powerpc/lib/copyuser_64.S index a0b3fbbd6fb..6d69ef39b7d 100644 --- a/arch/powerpc/lib/copyuser_64.S +++ b/arch/powerpc/lib/copyuser_64.S @@ -24,7 +24,7 @@ _GLOBAL(__copy_tofrom_user) std r4,-16(r1) std r5,-8(r1) dcbt 0,r4 - beq .Lcopy_page + beq .Lcopy_page_4K andi. r6,r6,7 mtcrf 0x01,r5 blt cr1,.Lshort_copy @@ -366,7 +366,7 @@ _GLOBAL(__copy_tofrom_user) * above (following the .Ldst_aligned label) but it runs slightly * slower on POWER3. */ -.Lcopy_page: +.Lcopy_page_4K: std r31,-32(1) std r30,-40(1) std r29,-48(1) diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S index d6ed9102eee..e0d02c4a261 100644 --- a/arch/powerpc/mm/hash_low_64.S +++ b/arch/powerpc/mm/hash_low_64.S @@ -1,7 +1,7 @@ /* * ppc64 MMU hashtable management routines * - * (c) Copyright IBM Corp. 2003 + * (c) Copyright IBM Corp. 2003, 2005 * * Maintained by: Benjamin Herrenschmidt * @@ -10,6 +10,7 @@ * described in the kernel's COPYING file. */ +#include #include #include #include @@ -42,14 +43,24 @@ /* Save non-volatile offsets */ #define STK_REG(i) (112 + ((i)-14)*8) + +#ifndef CONFIG_PPC_64K_PAGES + +/***************************************************************************** + * * + * 4K SW & 4K HW pages implementation * + * * + *****************************************************************************/ + + /* - * _hash_page(unsigned long ea, unsigned long access, unsigned long vsid, - * pte_t *ptep, unsigned long trap, int local) + * _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid, + * pte_t *ptep, unsigned long trap, int local) * - * Adds a page to the hash table. This is the non-LPAR version for now + * Adds a 4K page to the hash table in a segment of 4K pages only */ -_GLOBAL(__hash_page) +_GLOBAL(__hash_page_4K) mflr r0 std r0,16(r1) stdu r1,-STACKFRAMESIZE(r1) @@ -88,7 +99,8 @@ _GLOBAL(__hash_page) /* If so, just bail out and refault if needed. Someone else * is changing this PTE anyway and might hash it. */ - bne- bail_ok + bne- htab_bail_ok + /* Prepare new PTE value (turn access RW into DIRTY, then * add BUSY,HASHPTE and ACCESSED) */ @@ -118,10 +130,10 @@ _GLOBAL(__hash_page) /* Convert linux PTE bits into HW equivalents */ andi. r3,r30,0x1fe /* Get basic set of flags */ - xori r3,r3,HW_NO_EXEC /* _PAGE_EXEC -> NOEXEC */ + xori r3,r3,HPTE_R_N /* _PAGE_EXEC -> NOEXEC */ rlwinm r0,r30,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */ rlwinm r4,r30,32-7+1,30,30 /* _PAGE_DIRTY -> _PAGE_USER (r4) */ - and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY -> r0 bit 30 */ + and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/ andc r0,r30,r0 /* r0 = pte & ~r0 */ rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */ @@ -158,19 +170,21 @@ htab_insert_pte: andc r30,r30,r0 ori r30,r30,_PAGE_HASHPTE - /* page number in r5 */ - rldicl r5,r31,64-PTE_SHIFT,PTE_SHIFT + /* physical address r5 */ + rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT + sldi r5,r5,PAGE_SHIFT /* Calculate primary group hash */ and r0,r28,r27 - rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */ + rldicr r3,r0,3,63-3 /* r3 = (hash & mask) << 3 */ /* Call ppc_md.hpte_insert */ - ld r7,STK_PARM(r4)(r1) /* Retreive new pp bits */ + ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */ mr r4,r29 /* Retreive va */ - li r6,0 /* no vflags */ + li r7,0 /* !bolted, !secondary */ + li r8,MMU_PAGE_4K /* page size */ _GLOBAL(htab_call_hpte_insert1) - bl . /* Will be patched by htab_finish_init() */ + bl . /* Patched by htab_finish_init() */ cmpdi 0,r3,0 bge htab_pte_insert_ok /* Insertion successful */ cmpdi 0,r3,-2 /* Critical failure */ @@ -178,19 +192,21 @@ _GLOBAL(htab_call_hpte_insert1) /* Now try secondary slot */ - /* page number in r5 */ - rldicl r5,r31,64-PTE_SHIFT,PTE_SHIFT + /* physical address r5 */ + rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT + sldi r5,r5,PAGE_SHIFT /* Calculate secondary group hash */ andc r0,r27,r28 rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */ /* Call ppc_md.hpte_insert */ - ld r7,STK_PARM(r4)(r1) /* Retreive new pp bits */ + ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */ mr r4,r29 /* Retreive va */ - li r6,HPTE_V_SECONDARY@l /* secondary slot */ + li r7,HPTE_V_SECONDARY /* !bolted, secondary */ + li r8,MMU_PAGE_4K /* page size */ _GLOBAL(htab_call_hpte_insert2) - bl . /* Will be patched by htab_finish_init() */ + bl . /* Patched by htab_finish_init() */ cmpdi 0,r3,0 bge+ htab_pte_insert_ok /* Insertion successful */ cmpdi 0,r3,-2 /* Critical failure */ @@ -207,14 +223,14 @@ _GLOBAL(htab_call_hpte_insert2) rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */ /* Call ppc_md.hpte_remove */ _GLOBAL(htab_call_hpte_remove) - bl . /* Will be patched by htab_finish_init() */ + bl . /* Patched by htab_finish_init() */ /* Try all again */ b htab_insert_pte -bail_ok: +htab_bail_ok: li r3,0 - b bail + b htab_bail htab_pte_insert_ok: /* Insert slot number & secondary bit in PTE */ @@ -227,7 +243,7 @@ htab_write_out_pte: ld r6,STK_PARM(r6)(r1) std r30,0(r6) li r3, 0 -bail: +htab_bail: ld r27,STK_REG(r27)(r1) ld r28,STK_REG(r28)(r1) ld r29,STK_REG(r29)(r1) @@ -256,10 +272,10 @@ htab_modify_pte: /* Call ppc_md.hpte_updatepp */ mr r5,r29 /* va */ - li r6,0 /* large is 0 */ + li r6,MMU_PAGE_4K /* page size */ ld r7,STK_PARM(r8)(r1) /* get "local" param */ _GLOBAL(htab_call_hpte_updatepp) - bl . /* Will be patched by htab_finish_init() */ + bl . /* Patched by htab_finish_init() */ /* if we failed because typically the HPTE wasn't really here * we try an insertion. @@ -276,13 +292,556 @@ htab_wrong_access: /* Bail out clearing reservation */ stdcx. r31,0,r6 li r3,1 - b bail + b htab_bail + +htab_pte_insert_failure: + /* Bail out restoring old PTE */ + ld r6,STK_PARM(r6)(r1) + std r31,0(r6) + li r3,-1 + b htab_bail + + +#else /* CONFIG_PPC_64K_PAGES */ + + +/***************************************************************************** + * * + * 64K SW & 4K or 64K HW in a 4K segment pages implementation * + * * + *****************************************************************************/ + +/* _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid, + * pte_t *ptep, unsigned long trap, int local) + */ + +/* + * For now, we do NOT implement Admixed pages + */ +_GLOBAL(__hash_page_4K) + mflr r0 + std r0,16(r1) + stdu r1,-STACKFRAMESIZE(r1) + /* Save all params that we need after a function call */ + std r6,STK_PARM(r6)(r1) + std r8,STK_PARM(r8)(r1) + + /* Add _PAGE_PRESENT to access */ + ori r4,r4,_PAGE_PRESENT + + /* Save non-volatile registers. + * r31 will hold "old PTE" + * r30 is "new PTE" + * r29 is "va" + * r28 is a hash value + * r27 is hashtab mask (maybe dynamic patched instead ?) + * r26 is the hidx mask + * r25 is the index in combo page + */ + std r25,STK_REG(r25)(r1) + std r26,STK_REG(r26)(r1) + std r27,STK_REG(r27)(r1) + std r28,STK_REG(r28)(r1) + std r29,STK_REG(r29)(r1) + std r30,STK_REG(r30)(r1) + std r31,STK_REG(r31)(r1) + + /* Step 1: + * + * Check permissions, atomically mark the linux PTE busy + * and hashed. + */ +1: + ldarx r31,0,r6 + /* Check access rights (access & ~(pte_val(*ptep))) */ + andc. r0,r4,r31 + bne- htab_wrong_access + /* Check if PTE is busy */ + andi. r0,r31,_PAGE_BUSY + /* If so, just bail out and refault if needed. Someone else + * is changing this PTE anyway and might hash it. + */ + bne- htab_bail_ok + /* Prepare new PTE value (turn access RW into DIRTY, then + * add BUSY and ACCESSED) + */ + rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */ + or r30,r30,r31 + ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE + /* Write the linux PTE atomically (setting busy) */ + stdcx. r30,0,r6 + bne- 1b + isync + + /* Step 2: + * + * Insert/Update the HPTE in the hash table. At this point, + * r4 (access) is re-useable, we use it for the new HPTE flags + */ + + /* Load the hidx index */ + rldicl r25,r3,64-12,60 + + /* Calc va and put it in r29 */ + rldicr r29,r5,28,63-28 /* r29 = (vsid << 28) */ + rldicl r3,r3,0,36 /* r3 = (ea & 0x0fffffff) */ + or r29,r3,r29 /* r29 = va + + /* Calculate hash value for primary slot and store it in r28 */ + rldicl r5,r5,0,25 /* vsid & 0x0000007fffffffff */ + rldicl r0,r3,64-12,48 /* (ea >> 12) & 0xffff */ + xor r28,r5,r0 + + /* Convert linux PTE bits into HW equivalents */ + andi. r3,r30,0x1fe /* Get basic set of flags */ + xori r3,r3,HPTE_R_N /* _PAGE_EXEC -> NOEXEC */ + rlwinm r0,r30,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */ + rlwinm r4,r30,32-7+1,30,30 /* _PAGE_DIRTY -> _PAGE_USER (r4) */ + and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/ + andc r0,r30,r0 /* r0 = pte & ~r0 */ + rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */ + + /* We eventually do the icache sync here (maybe inline that + * code rather than call a C function...) + */ +BEGIN_FTR_SECTION + mr r4,r30 + mr r5,r7 + bl .hash_page_do_lazy_icache +END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE) + + /* At this point, r3 contains new PP bits, save them in + * place of "access" in the param area (sic) + */ + std r3,STK_PARM(r4)(r1) + + /* Get htab_hash_mask */ + ld r4,htab_hash_mask@got(2) + ld r27,0(r4) /* htab_hash_mask -> r27 */ + + /* Check if we may already be in the hashtable, in this case, we + * go to out-of-line code to try to modify the HPTE. We look for + * the bit at (1 >> (index + 32)) + */ + andi. r0,r31,_PAGE_HASHPTE + li r26,0 /* Default hidx */ + beq htab_insert_pte + ld r6,STK_PARM(r6)(r1) + ori r26,r6,0x8000 /* Load the hidx mask */ + ld r26,0(r26) + addi r5,r25,36 /* Check actual HPTE_SUB bit, this */ + rldcr. r0,r31,r5,0 /* must match pgtable.h definition */ + bne htab_modify_pte + +htab_insert_pte: + /* real page number in r5, PTE RPN value + index */ + rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT + sldi r5,r5,PAGE_SHIFT-HW_PAGE_SHIFT + add r5,r5,r25 + sldi r5,r5,HW_PAGE_SHIFT + + /* Calculate primary group hash */ + and r0,r28,r27 + rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */ + + /* Call ppc_md.hpte_insert */ + ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */ + mr r4,r29 /* Retreive va */ + li r7,0 /* !bolted, !secondary */ + li r8,MMU_PAGE_4K /* page size */ +_GLOBAL(htab_call_hpte_insert1) + bl . /* patched by htab_finish_init() */ + cmpdi 0,r3,0 + bge htab_pte_insert_ok /* Insertion successful */ + cmpdi 0,r3,-2 /* Critical failure */ + beq- htab_pte_insert_failure + + /* Now try secondary slot */ + + /* real page number in r5, PTE RPN value + index */ + rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT + sldi r5,r5,PAGE_SHIFT-HW_PAGE_SHIFT + add r5,r5,r25 + sldi r5,r5,HW_PAGE_SHIFT + + /* Calculate secondary group hash */ + andc r0,r27,r28 + rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */ + + /* Call ppc_md.hpte_insert */ + ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */ + mr r4,r29 /* Retreive va */ + li r7,HPTE_V_SECONDARY /* !bolted, secondary */ + li r8,MMU_PAGE_4K /* page size */ +_GLOBAL(htab_call_hpte_insert2) + bl . /* patched by htab_finish_init() */ + cmpdi 0,r3,0 + bge+ htab_pte_insert_ok /* Insertion successful */ + cmpdi 0,r3,-2 /* Critical failure */ + beq- htab_pte_insert_failure + + /* Both are full, we need to evict something */ + mftb r0 + /* Pick a random group based on TB */ + andi. r0,r0,1 + mr r5,r28 + bne 2f + not r5,r5 +2: and r0,r5,r27 + rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */ + /* Call ppc_md.hpte_remove */ +_GLOBAL(htab_call_hpte_remove) + bl . /* patched by htab_finish_init() */ + + /* Try all again */ + b htab_insert_pte + +htab_bail_ok: + li r3,0 + b htab_bail + +htab_pte_insert_ok: + /* Insert slot number & secondary bit in PTE second half, + * clear _PAGE_BUSY and set approriate HPTE slot bit + */ + ld r6,STK_PARM(r6)(r1) + li r0,_PAGE_BUSY + andc r30,r30,r0 + /* HPTE SUB bit */ + li r0,1 + subfic r5,r25,27 /* Must match bit position in */ + sld r0,r0,r5 /* pgtable.h */ + or r30,r30,r0 + /* hindx */ + sldi r5,r25,2 + sld r3,r3,r5 + li r4,0xf + sld r4,r4,r5 + andc r26,r26,r4 + or r26,r26,r3 + ori r5,r6,0x8000 + std r26,0(r5) + lwsync + std r30,0(r6) + li r3, 0 +htab_bail: + ld r25,STK_REG(r25)(r1) + ld r26,STK_REG(r26)(r1) + ld r27,STK_REG(r27)(r1) + ld r28,STK_REG(r28)(r1) + ld r29,STK_REG(r29)(r1) + ld r30,STK_REG(r30)(r1) + ld r31,STK_REG(r31)(r1) + addi r1,r1,STACKFRAMESIZE + ld r0,16(r1) + mtlr r0 + blr + +htab_modify_pte: + /* Keep PP bits in r4 and slot idx from the PTE around in r3 */ + mr r4,r3 + sldi r5,r25,2 + srd r3,r26,r5 + + /* Secondary group ? if yes, get a inverted hash value */ + mr r5,r28 + andi. r0,r3,0x8 /* page secondary ? */ + beq 1f + not r5,r5 +1: andi. r3,r3,0x7 /* extract idx alone */ + + /* Calculate proper slot value for ppc_md.hpte_updatepp */ + and r0,r5,r27 + rldicr r0,r0,3,63-3 /* r0 = (hash & mask) << 3 */ + add r3,r0,r3 /* add slot idx */ + + /* Call ppc_md.hpte_updatepp */ + mr r5,r29 /* va */ + li r6,MMU_PAGE_4K /* page size */ + ld r7,STK_PARM(r8)(r1) /* get "local" param */ +_GLOBAL(htab_call_hpte_updatepp) + bl . /* patched by htab_finish_init() */ + + /* if we failed because typically the HPTE wasn't really here + * we try an insertion. + */ + cmpdi 0,r3,-1 + beq- htab_insert_pte + + /* Clear the BUSY bit and Write out the PTE */ + li r0,_PAGE_BUSY + andc r30,r30,r0 + ld r6,STK_PARM(r6)(r1) + std r30,0(r6) + li r3,0 + b htab_bail + +htab_wrong_access: + /* Bail out clearing reservation */ + stdcx. r31,0,r6 + li r3,1 + b htab_bail htab_pte_insert_failure: /* Bail out restoring old PTE */ ld r6,STK_PARM(r6)(r1) std r31,0(r6) li r3,-1 - b bail + b htab_bail + + +/***************************************************************************** + * * + * 64K SW & 64K HW in a 64K segment pages implementation * + * * + *****************************************************************************/ + +_GLOBAL(__hash_page_64K) + mflr r0 + std r0,16(r1) + stdu r1,-STACKFRAMESIZE(r1) + /* Save all params that we need after a function call */ + std r6,STK_PARM(r6)(r1) + std r8,STK_PARM(r8)(r1) + + /* Add _PAGE_PRESENT to access */ + ori r4,r4,_PAGE_PRESENT + + /* Save non-volatile registers. + * r31 will hold "old PTE" + * r30 is "new PTE" + * r29 is "va" + * r28 is a hash value + * r27 is hashtab mask (maybe dynamic patched instead ?) + */ + std r27,STK_REG(r27)(r1) + std r28,STK_REG(r28)(r1) + std r29,STK_REG(r29)(r1) + std r30,STK_REG(r30)(r1) + std r31,STK_REG(r31)(r1) + + /* Step 1: + * + * Check permissions, atomically mark the linux PTE busy + * and hashed. + */ +1: + ldarx r31,0,r6 + /* Check access rights (access & ~(pte_val(*ptep))) */ + andc. r0,r4,r31 + bne- ht64_wrong_access + /* Check if PTE is busy */ + andi. r0,r31,_PAGE_BUSY + /* If so, just bail out and refault if needed. Someone else + * is changing this PTE anyway and might hash it. + */ + bne- ht64_bail_ok + /* Prepare new PTE value (turn access RW into DIRTY, then + * add BUSY,HASHPTE and ACCESSED) + */ + rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */ + or r30,r30,r31 + ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE + /* Write the linux PTE atomically (setting busy) */ + stdcx. r30,0,r6 + bne- 1b + isync + + /* Step 2: + * + * Insert/Update the HPTE in the hash table. At this point, + * r4 (access) is re-useable, we use it for the new HPTE flags + */ + + /* Calc va and put it in r29 */ + rldicr r29,r5,28,63-28 + rldicl r3,r3,0,36 + or r29,r3,r29 + + /* Calculate hash value for primary slot and store it in r28 */ + rldicl r5,r5,0,25 /* vsid & 0x0000007fffffffff */ + rldicl r0,r3,64-16,52 /* (ea >> 16) & 0xfff */ + xor r28,r5,r0 + + /* Convert linux PTE bits into HW equivalents */ + andi. r3,r30,0x1fe /* Get basic set of flags */ + xori r3,r3,HPTE_R_N /* _PAGE_EXEC -> NOEXEC */ + rlwinm r0,r30,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */ + rlwinm r4,r30,32-7+1,30,30 /* _PAGE_DIRTY -> _PAGE_USER (r4) */ + and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/ + andc r0,r30,r0 /* r0 = pte & ~r0 */ + rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */ + + /* We eventually do the icache sync here (maybe inline that + * code rather than call a C function...) + */ +BEGIN_FTR_SECTION + mr r4,r30 + mr r5,r7 + bl .hash_page_do_lazy_icache +END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE) + + /* At this point, r3 contains new PP bits, save them in + * place of "access" in the param area (sic) + */ + std r3,STK_PARM(r4)(r1) + + /* Get htab_hash_mask */ + ld r4,htab_hash_mask@got(2) + ld r27,0(r4) /* htab_hash_mask -> r27 */ + + /* Check if we may already be in the hashtable, in this case, we + * go to out-of-line code to try to modify the HPTE + */ + andi. r0,r31,_PAGE_HASHPTE + bne ht64_modify_pte + +ht64_insert_pte: + /* Clear hpte bits in new pte (we also clear BUSY btw) and + * add _PAGE_HASHPTE + */ + lis r0,_PAGE_HPTEFLAGS@h + ori r0,r0,_PAGE_HPTEFLAGS@l + andc r30,r30,r0 + ori r30,r30,_PAGE_HASHPTE + + /* Phyical address in r5 */ + rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT + sldi r5,r5,PAGE_SHIFT + + /* Calculate primary group hash */ + and r0,r28,r27 + rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */ + + /* Call ppc_md.hpte_insert */ + ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */ + mr r4,r29 /* Retreive va */ + li r7,0 /* !bolted, !secondary */ + li r8,MMU_PAGE_64K +_GLOBAL(ht64_call_hpte_insert1) + bl . /* patched by htab_finish_init() */ + cmpdi 0,r3,0 + bge ht64_pte_insert_ok /* Insertion successful */ + cmpdi 0,r3,-2 /* Critical failure */ + beq- ht64_pte_insert_failure + + /* Now try secondary slot */ + + /* Phyical address in r5 */ + rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT + sldi r5,r5,PAGE_SHIFT + + /* Calculate secondary group hash */ + andc r0,r27,r28 + rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */ + + /* Call ppc_md.hpte_insert */ + ld r6,STK_PARM(r4)(r1) /* Retreive new pp bits */ + mr r4,r29 /* Retreive va */ + li r7,HPTE_V_SECONDARY /* !bolted, secondary */ + li r8,MMU_PAGE_64K +_GLOBAL(ht64_call_hpte_insert2) + bl . /* patched by htab_finish_init() */ + cmpdi 0,r3,0 + bge+ ht64_pte_insert_ok /* Insertion successful */ + cmpdi 0,r3,-2 /* Critical failure */ + beq- ht64_pte_insert_failure + + /* Both are full, we need to evict something */ + mftb r0 + /* Pick a random group based on TB */ + andi. r0,r0,1 + mr r5,r28 + bne 2f + not r5,r5 +2: and r0,r5,r27 + rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */ + /* Call ppc_md.hpte_remove */ +_GLOBAL(ht64_call_hpte_remove) + bl . /* patched by htab_finish_init() */ + + /* Try all again */ + b ht64_insert_pte + +ht64_bail_ok: + li r3,0 + b ht64_bail + +ht64_pte_insert_ok: + /* Insert slot number & secondary bit in PTE */ + rldimi r30,r3,12,63-15 + + /* Write out the PTE with a normal write + * (maybe add eieio may be good still ?) + */ +ht64_write_out_pte: + ld r6,STK_PARM(r6)(r1) + std r30,0(r6) + li r3, 0 +ht64_bail: + ld r27,STK_REG(r27)(r1) + ld r28,STK_REG(r28)(r1) + ld r29,STK_REG(r29)(r1) + ld r30,STK_REG(r30)(r1) + ld r31,STK_REG(r31)(r1) + addi r1,r1,STACKFRAMESIZE + ld r0,16(r1) + mtlr r0 + blr + +ht64_modify_pte: + /* Keep PP bits in r4 and slot idx from the PTE around in r3 */ + mr r4,r3 + rlwinm r3,r31,32-12,29,31 + + /* Secondary group ? if yes, get a inverted hash value */ + mr r5,r28 + andi. r0,r31,_PAGE_F_SECOND + beq 1f + not r5,r5 +1: + /* Calculate proper slot value for ppc_md.hpte_updatepp */ + and r0,r5,r27 + rldicr r0,r0,3,63-3 /* r0 = (hash & mask) << 3 */ + add r3,r0,r3 /* add slot idx */ + + /* Call ppc_md.hpte_updatepp */ + mr r5,r29 /* va */ + li r6,MMU_PAGE_64K + ld r7,STK_PARM(r8)(r1) /* get "local" param */ +_GLOBAL(ht64_call_hpte_updatepp) + bl . /* patched by htab_finish_init() */ + + /* if we failed because typically the HPTE wasn't really here + * we try an insertion. + */ + cmpdi 0,r3,-1 + beq- ht64_insert_pte + + /* Clear the BUSY bit and Write out the PTE */ + li r0,_PAGE_BUSY + andc r30,r30,r0 + b ht64_write_out_pte + +ht64_wrong_access: + /* Bail out clearing reservation */ + stdcx. r31,0,r6 + li r3,1 + b ht64_bail + +ht64_pte_insert_failure: + /* Bail out restoring old PTE */ + ld r6,STK_PARM(r6)(r1) + std r31,0(r6) + li r3,-1 + b ht64_bail + + +#endif /* CONFIG_PPC_64K_PAGES */ +/***************************************************************************** + * * + * Huge pages implementation is in hugetlbpage.c * + * * + *****************************************************************************/ diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index 174d14576c2..d96bcfe4c6f 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c @@ -9,6 +9,9 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ + +#undef DEBUG_LOW + #include #include #include @@ -22,11 +25,84 @@ #include #include #include +#include + +#ifdef DEBUG_LOW +#define DBG_LOW(fmt...) udbg_printf(fmt) +#else +#define DBG_LOW(fmt...) +#endif #define HPTE_LOCK_BIT 3 static DEFINE_SPINLOCK(native_tlbie_lock); +static inline void __tlbie(unsigned long va, unsigned int psize) +{ + unsigned int penc; + + /* clear top 16 bits, non SLS segment */ + va &= ~(0xffffULL << 48); + + switch (psize) { + case MMU_PAGE_4K: + va &= ~0xffful; + asm volatile("tlbie %0,0" : : "r" (va) : "memory"); + break; + default: + penc = mmu_psize_defs[psize].penc; + va &= ~((1ul << mmu_psize_defs[psize].shift) - 1); + va |= (0x7f >> (8 - penc)) << 12; + asm volatile("tlbie %0,1" : : "r" (va) : "memory"); + break; + } +} + +static inline void __tlbiel(unsigned long va, unsigned int psize) +{ + unsigned int penc; + + /* clear top 16 bits, non SLS segment */ + va &= ~(0xffffULL << 48); + + switch (psize) { + case MMU_PAGE_4K: + va &= ~0xffful; + asm volatile(".long 0x7c000224 | (%0 << 11) | (0 << 21)" + : : "r"(va) : "memory"); + break; + default: + penc = mmu_psize_defs[psize].penc; + va &= ~((1ul << mmu_psize_defs[psize].shift) - 1); + va |= (0x7f >> (8 - penc)) << 12; + asm volatile(".long 0x7c000224 | (%0 << 11) | (1 << 21)" + : : "r"(va) : "memory"); + break; + } + +} + +static inline void tlbie(unsigned long va, int psize, int local) +{ + unsigned int use_local = local && cpu_has_feature(CPU_FTR_TLBIEL); + int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE); + + if (use_local) + use_local = mmu_psize_defs[psize].tlbiel; + if (lock_tlbie && !use_local) + spin_lock(&native_tlbie_lock); + asm volatile("ptesync": : :"memory"); + if (use_local) { + __tlbiel(va, psize); + asm volatile("ptesync": : :"memory"); + } else { + __tlbie(va, psize); + asm volatile("eieio; tlbsync; ptesync": : :"memory"); + } + if (lock_tlbie && !use_local) + spin_unlock(&native_tlbie_lock); +} + static inline void native_lock_hpte(hpte_t *hptep) { unsigned long *word = &hptep->v; @@ -48,13 +124,19 @@ static inline void native_unlock_hpte(hpte_t *hptep) } long native_hpte_insert(unsigned long hpte_group, unsigned long va, - unsigned long prpn, unsigned long vflags, - unsigned long rflags) + unsigned long pa, unsigned long rflags, + unsigned long vflags, int psize) { hpte_t *hptep = htab_address + hpte_group; unsigned long hpte_v, hpte_r; int i; + if (!(vflags & HPTE_V_BOLTED)) { + DBG_LOW(" insert(group=%lx, va=%016lx, pa=%016lx," + " rflags=%lx, vflags=%lx, psize=%d)\n", + hpte_group, va, pa, rflags, vflags, psize); + } + for (i = 0; i < HPTES_PER_GROUP; i++) { if (! (hptep->v & HPTE_V_VALID)) { /* retry with lock held */ @@ -70,10 +152,13 @@ long native_hpte_insert(unsigned long hpte_group, unsigned long va, if (i == HPTES_PER_GROUP) return -1; - hpte_v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID; - if (vflags & HPTE_V_LARGE) - va &= ~(1UL << HPTE_V_AVPN_SHIFT); - hpte_r = (prpn << HPTE_R_RPN_SHIFT) | rflags; + hpte_v = hpte_encode_v(va, psize) | vflags | HPTE_V_VALID; + hpte_r = hpte_encode_r(pa, psize) | rflags; + + if (!(vflags & HPTE_V_BOLTED)) { + DBG_LOW(" i=%x hpte_v=%016lx, hpte_r=%016lx\n", + i, hpte_v, hpte_r); + } hptep->r = hpte_r; /* Guarantee the second dword is visible before the valid bit */ @@ -96,6 +181,8 @@ static long native_hpte_remove(unsigned long hpte_group) int slot_offset; unsigned long hpte_v; + DBG_LOW(" remove(group=%lx)\n", hpte_group); + /* pick a random entry to start at */ slot_offset = mftb() & 0x7; @@ -126,34 +213,51 @@ static long native_hpte_remove(unsigned long hpte_group) return i; } -static inline void set_pp_bit(unsigned long pp, hpte_t *addr) +static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, + unsigned long va, int psize, int local) { - unsigned long old; - unsigned long *p = &addr->r; - - __asm__ __volatile__( - "1: ldarx %0,0,%3\n\ - rldimi %0,%2,0,61\n\ - stdcx. %0,0,%3\n\ - bne 1b" - : "=&r" (old), "=m" (*p) - : "r" (pp), "r" (p), "m" (*p) - : "cc"); + hpte_t *hptep = htab_address + slot; + unsigned long hpte_v, want_v; + int ret = 0; + + want_v = hpte_encode_v(va, psize); + + DBG_LOW(" update(va=%016lx, avpnv=%016lx, hash=%016lx, newpp=%x)", + va, want_v & HPTE_V_AVPN, slot, newpp); + + native_lock_hpte(hptep); + + hpte_v = hptep->v; + + /* Even if we miss, we need to invalidate the TLB */ + if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) { + DBG_LOW(" -> miss\n"); + native_unlock_hpte(hptep); + ret = -1; + } else { + DBG_LOW(" -> hit\n"); + /* Update the HPTE */ + hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) | + (newpp & (HPTE_R_PP | HPTE_R_N)); + native_unlock_hpte(hptep); + } + + /* Ensure it is out of the tlb too. */ + tlbie(va, psize, local); + + return ret; } -/* - * Only works on small pages. Yes its ugly to have to check each slot in - * the group but we only use this during bootup. - */ -static long native_hpte_find(unsigned long vpn) +static long native_hpte_find(unsigned long va, int psize) { hpte_t *hptep; unsigned long hash; unsigned long i, j; long slot; - unsigned long hpte_v; + unsigned long want_v, hpte_v; - hash = hpt_hash(vpn, 0); + hash = hpt_hash(va, mmu_psize_defs[psize].shift); + want_v = hpte_encode_v(va, psize); for (j = 0; j < 2; j++) { slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; @@ -161,7 +265,7 @@ static long native_hpte_find(unsigned long vpn) hptep = htab_address + slot; hpte_v = hptep->v; - if ((HPTE_V_AVPN_VAL(hpte_v) == (vpn >> 11)) + if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID) && ( !!(hpte_v & HPTE_V_SECONDARY) == j)) { /* HPTE matches */ @@ -177,120 +281,92 @@ static long native_hpte_find(unsigned long vpn) return -1; } -static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, - unsigned long va, int large, int local) -{ - hpte_t *hptep = htab_address + slot; - unsigned long hpte_v; - unsigned long avpn = va >> 23; - int ret = 0; - - if (large) - avpn &= ~1; - - native_lock_hpte(hptep); - - hpte_v = hptep->v; - - /* Even if we miss, we need to invalidate the TLB */ - if ((HPTE_V_AVPN_VAL(hpte_v) != avpn) - || !(hpte_v & HPTE_V_VALID)) { - native_unlock_hpte(hptep); - ret = -1; - } else { - set_pp_bit(newpp, hptep); - native_unlock_hpte(hptep); - } - - /* Ensure it is out of the tlb too */ - if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) { - tlbiel(va); - } else { - int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE); - - if (lock_tlbie) - spin_lock(&native_tlbie_lock); - tlbie(va, large); - if (lock_tlbie) - spin_unlock(&native_tlbie_lock); - } - - return ret; -} - /* * Update the page protection bits. Intended to be used to create * guard pages for kernel data structures on pages which are bolted * in the HPT. Assumes pages being operated on will not be stolen. - * Does not work on large pages. * * No need to lock here because we should be the only user. */ -static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea) +static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, + int psize) { - unsigned long vsid, va, vpn, flags = 0; + unsigned long vsid, va; long slot; hpte_t *hptep; - int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE); vsid = get_kernel_vsid(ea); va = (vsid << 28) | (ea & 0x0fffffff); - vpn = va >> PAGE_SHIFT; - slot = native_hpte_find(vpn); + slot = native_hpte_find(va, psize); if (slot == -1) panic("could not find page to bolt\n"); hptep = htab_address + slot; - set_pp_bit(newpp, hptep); + /* Update the HPTE */ + hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) | + (newpp & (HPTE_R_PP | HPTE_R_N)); - /* Ensure it is out of the tlb too */ - if (lock_tlbie) - spin_lock_irqsave(&native_tlbie_lock, flags); - tlbie(va, 0); - if (lock_tlbie) - spin_unlock_irqrestore(&native_tlbie_lock, flags); + /* Ensure it is out of the tlb too. */ + tlbie(va, psize, 0); } static void native_hpte_invalidate(unsigned long slot, unsigned long va, - int large, int local) + int psize, int local) { hpte_t *hptep = htab_address + slot; unsigned long hpte_v; - unsigned long avpn = va >> 23; + unsigned long want_v; unsigned long flags; - int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE); - - if (large) - avpn &= ~1; local_irq_save(flags); - native_lock_hpte(hptep); + DBG_LOW(" invalidate(va=%016lx, hash: %x)\n", va, slot); + + want_v = hpte_encode_v(va, psize); + native_lock_hpte(hptep); hpte_v = hptep->v; /* Even if we miss, we need to invalidate the TLB */ - if ((HPTE_V_AVPN_VAL(hpte_v) != avpn) - || !(hpte_v & HPTE_V_VALID)) { + if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) native_unlock_hpte(hptep); - } else { + else /* Invalidate the hpte. NOTE: this also unlocks it */ hptep->v = 0; - } - /* Invalidate the tlb */ - if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) { - tlbiel(va); - } else { - if (lock_tlbie) - spin_lock(&native_tlbie_lock); - tlbie(va, large); - if (lock_tlbie) - spin_unlock(&native_tlbie_lock); - } + /* Invalidate the TLB */ + tlbie(va, psize, local); + local_irq_restore(flags); } +/* + * XXX This need fixing based on page size. It's only used by + * native_hpte_clear() for now which needs fixing too so they + * make a good pair... + */ +static unsigned long slot2va(unsigned long hpte_v, unsigned long slot) +{ + unsigned long avpn = HPTE_V_AVPN_VAL(hpte_v); + unsigned long va; + + va = avpn << 23; + + if (! (hpte_v & HPTE_V_LARGE)) { + unsigned long vpi, pteg; + + pteg = slot / HPTES_PER_GROUP; + if (hpte_v & HPTE_V_SECONDARY) + pteg = ~pteg; + + vpi = ((va >> 28) ^ pteg) & htab_hash_mask; + + va |= vpi << PAGE_SHIFT; + } + + return va; +} + /* * clear all mappings on kexec. All cpus are in real mode (or they will * be when they isi), and we are the only one left. We rely on our kernel @@ -298,6 +374,8 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va, * * TODO: add batching support when enabled. remember, no dynamic memory here, * athough there is the control page available... + * + * XXX FIXME: 4k only for now ! */ static void native_hpte_clear(void) { @@ -327,7 +405,7 @@ static void native_hpte_clear(void) if (hpte_v & HPTE_V_VALID) { hptep->v = 0; - tlbie(slot2va(hpte_v, slot), hpte_v & HPTE_V_LARGE); + tlbie(slot2va(hpte_v, slot), MMU_PAGE_4K, 0); } } @@ -335,59 +413,59 @@ static void native_hpte_clear(void) local_irq_restore(flags); } +/* + * Batched hash table flush, we batch the tlbie's to avoid taking/releasing + * the lock all the time + */ static void native_flush_hash_range(unsigned long number, int local) { - unsigned long va, vpn, hash, secondary, slot, flags, avpn; - int i, j; + unsigned long va, hash, index, hidx, shift, slot; hpte_t *hptep; unsigned long hpte_v; + unsigned long want_v; + unsigned long flags; + real_pte_t pte; struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); - unsigned long large = batch->large; + unsigned long psize = batch->psize; + int i; local_irq_save(flags); - j = 0; for (i = 0; i < number; i++) { - va = batch->vaddr[j]; - if (large) - vpn = va >> HPAGE_SHIFT; - else - vpn = va >> PAGE_SHIFT; - hash = hpt_hash(vpn, large); - secondary = (pte_val(batch->pte[i]) & _PAGE_SECONDARY) >> 15; - if (secondary) - hash = ~hash; - slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; - slot += (pte_val(batch->pte[i]) & _PAGE_GROUP_IX) >> 12; - - hptep = htab_address + slot; - - avpn = va >> 23; - if (large) - avpn &= ~0x1UL; - - native_lock_hpte(hptep); - - hpte_v = hptep->v; - - /* Even if we miss, we need to invalidate the TLB */ - if ((HPTE_V_AVPN_VAL(hpte_v) != avpn) - || !(hpte_v & HPTE_V_VALID)) { - native_unlock_hpte(hptep); - } else { - /* Invalidate the hpte. NOTE: this also unlocks it */ - hptep->v = 0; - } - - j++; + va = batch->vaddr[i]; + pte = batch->pte[i]; + + pte_iterate_hashed_subpages(pte, psize, va, index, shift) { + hash = hpt_hash(va, shift); + hidx = __rpte_to_hidx(pte, index); + if (hidx & _PTEIDX_SECONDARY) + hash = ~hash; + slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; + slot += hidx & _PTEIDX_GROUP_IX; + hptep = htab_address + slot; + want_v = hpte_encode_v(va, psize); + native_lock_hpte(hptep); + hpte_v = hptep->v; + if (!HPTE_V_COMPARE(hpte_v, want_v) || + !(hpte_v & HPTE_V_VALID)) + native_unlock_hpte(hptep); + else + hptep->v = 0; + } pte_iterate_hashed_end(); } - if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) { + if (cpu_has_feature(CPU_FTR_TLBIEL) && + mmu_psize_defs[psize].tlbiel && local) { asm volatile("ptesync":::"memory"); - - for (i = 0; i < j; i++) - __tlbiel(batch->vaddr[i]); - + for (i = 0; i < number; i++) { + va = batch->vaddr[i]; + pte = batch->pte[i]; + + pte_iterate_hashed_subpages(pte, psize, va, index, + shift) { + __tlbiel(va, psize); + } pte_iterate_hashed_end(); + } asm volatile("ptesync":::"memory"); } else { int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE); @@ -396,10 +474,15 @@ static void native_flush_hash_range(unsigned long number, int local) spin_lock(&native_tlbie_lock); asm volatile("ptesync":::"memory"); - - for (i = 0; i < j; i++) - __tlbie(batch->vaddr[i], large); - + for (i = 0; i < number; i++) { + va = batch->vaddr[i]; + pte = batch->pte[i]; + + pte_iterate_hashed_subpages(pte, psize, va, index, + shift) { + __tlbie(va, psize); + } pte_iterate_hashed_end(); + } asm volatile("eieio; tlbsync; ptesync":::"memory"); if (lock_tlbie) diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 6e9e05cce02..b2f3dbca695 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -19,6 +19,7 @@ */ #undef DEBUG +#undef DEBUG_LOW #include #include @@ -59,6 +60,15 @@ #define DBG(fmt...) #endif +#ifdef DEBUG_LOW +#define DBG_LOW(fmt...) udbg_printf(fmt) +#else +#define DBG_LOW(fmt...) +#endif + +#define KB (1024) +#define MB (1024*KB) + /* * Note: pte --> Linux PTE * HPTE --> PowerPC Hashed Page Table Entry @@ -77,91 +87,290 @@ extern unsigned long dart_tablebase; hpte_t *htab_address; unsigned long htab_hash_mask; - unsigned long _SDR1; +struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; +int mmu_linear_psize = MMU_PAGE_4K; +int mmu_virtual_psize = MMU_PAGE_4K; +#ifdef CONFIG_HUGETLB_PAGE +int mmu_huge_psize = MMU_PAGE_16M; +unsigned int HPAGE_SHIFT; +#endif -#define KB (1024) -#define MB (1024*KB) - -static inline void loop_forever(void) -{ - volatile unsigned long x = 1; - for(;x;x|=1) - ; -} +/* There are definitions of page sizes arrays to be used when none + * is provided by the firmware. + */ -static inline void create_pte_mapping(unsigned long start, unsigned long end, - unsigned long mode, int large) +/* Pre-POWER4 CPUs (4k pages only) + */ +struct mmu_psize_def mmu_psize_defaults_old[] = { + [MMU_PAGE_4K] = { + .shift = 12, + .sllp = 0, + .penc = 0, + .avpnm = 0, + .tlbiel = 0, + }, +}; + +/* POWER4, GPUL, POWER5 + * + * Support for 16Mb large pages + */ +struct mmu_psize_def mmu_psize_defaults_gp[] = { + [MMU_PAGE_4K] = { + .shift = 12, + .sllp = 0, + .penc = 0, + .avpnm = 0, + .tlbiel = 1, + }, + [MMU_PAGE_16M] = { + .shift = 24, + .sllp = SLB_VSID_L, + .penc = 0, + .avpnm = 0x1UL, + .tlbiel = 0, + }, +}; + + +int htab_bolt_mapping(unsigned long vstart, unsigned long vend, + unsigned long pstart, unsigned long mode, int psize) { - unsigned long addr; - unsigned int step; + unsigned long vaddr, paddr; + unsigned int step, shift; unsigned long tmp_mode; - unsigned long vflags; + int ret = 0; - if (large) { - step = 16*MB; - vflags = HPTE_V_BOLTED | HPTE_V_LARGE; - } else { - step = 4*KB; - vflags = HPTE_V_BOLTED; - } + shift = mmu_psize_defs[psize].shift; + step = 1 << shift; - for (addr = start; addr < end; addr += step) { + for (vaddr = vstart, paddr = pstart; vaddr < vend; + vaddr += step, paddr += step) { unsigned long vpn, hash, hpteg; - unsigned long vsid = get_kernel_vsid(addr); - unsigned long va = (vsid << 28) | (addr & 0xfffffff); - int ret = -1; - - if (large) - vpn = va >> HPAGE_SHIFT; - else - vpn = va >> PAGE_SHIFT; - + unsigned long vsid = get_kernel_vsid(vaddr); + unsigned long va = (vsid << 28) | (vaddr & 0x0fffffff); + vpn = va >> shift; tmp_mode = mode; /* Make non-kernel text non-executable */ - if (!in_kernel_text(addr)) - tmp_mode = mode | HW_NO_EXEC; - - hash = hpt_hash(vpn, large); + if (!in_kernel_text(vaddr)) + tmp_mode = mode | HPTE_R_N; + hash = hpt_hash(va, shift); hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); + /* The crap below can be cleaned once ppd_md.probe() can + * set up the hash callbacks, thus we can just used the + * normal insert callback here. + */ #ifdef CONFIG_PPC_ISERIES - if (systemcfg->platform & PLATFORM_ISERIES_LPAR) - ret = iSeries_hpte_bolt_or_insert(hpteg, va, - virt_to_abs(addr) >> PAGE_SHIFT, - vflags, tmp_mode); + if (systemcfg->platform == PLATFORM_ISERIES_LPAR) + ret = iSeries_hpte_insert(hpteg, va, + virt_to_abs(paddr), + tmp_mode, + HPTE_V_BOLTED, + psize); else #endif #ifdef CONFIG_PPC_PSERIES if (systemcfg->platform & PLATFORM_LPAR) ret = pSeries_lpar_hpte_insert(hpteg, va, - virt_to_abs(addr) >> PAGE_SHIFT, - vflags, tmp_mode); + virt_to_abs(paddr), + tmp_mode, + HPTE_V_BOLTED, + psize); else #endif #ifdef CONFIG_PPC_MULTIPLATFORM ret = native_hpte_insert(hpteg, va, - virt_to_abs(addr) >> PAGE_SHIFT, - vflags, tmp_mode); + virt_to_abs(paddr), + tmp_mode, HPTE_V_BOLTED, + psize); #endif + if (ret < 0) + break; + } + return ret < 0 ? ret : 0; +} - if (ret == -1) { - ppc64_terminate_msg(0x20, "create_pte_mapping"); - loop_forever(); +static int __init htab_dt_scan_page_sizes(unsigned long node, + const char *uname, int depth, + void *data) +{ + char *type = of_get_flat_dt_prop(node, "device_type", NULL); + u32 *prop; + unsigned long size = 0; + + /* We are scanning "cpu" nodes only */ + if (type == NULL || strcmp(type, "cpu") != 0) + return 0; + + prop = (u32 *)of_get_flat_dt_prop(node, + "ibm,segment-page-sizes", &size); + if (prop != NULL) { + DBG("Page sizes from device-tree:\n"); + size /= 4; + cur_cpu_spec->cpu_features &= ~(CPU_FTR_16M_PAGE); + while(size > 0) { + unsigned int shift = prop[0]; + unsigned int slbenc = prop[1]; + unsigned int lpnum = prop[2]; + unsigned int lpenc = 0; + struct mmu_psize_def *def; + int idx = -1; + + size -= 3; prop += 3; + while(size > 0 && lpnum) { + if (prop[0] == shift) + lpenc = prop[1]; + prop += 2; size -= 2; + lpnum--; + } + switch(shift) { + case 0xc: + idx = MMU_PAGE_4K; + break; + case 0x10: + idx = MMU_PAGE_64K; + break; + case 0x14: + idx = MMU_PAGE_1M; + break; + case 0x18: + idx = MMU_PAGE_16M; + cur_cpu_spec->cpu_features |= CPU_FTR_16M_PAGE; + break; + case 0x22: + idx = MMU_PAGE_16G; + break; + } + if (idx < 0) + continue; + def = &mmu_psize_defs[idx]; + def->shift = shift; + if (shift <= 23) + def->avpnm = 0; + else + def->avpnm = (1 << (shift - 23)) - 1; + def->sllp = slbenc; + def->penc = lpenc; + /* We don't know for sure what's up with tlbiel, so + * for now we only set it for 4K and 64K pages + */ + if (idx == MMU_PAGE_4K || idx == MMU_PAGE_64K) + def->tlbiel = 1; + else + def->tlbiel = 0; + + DBG(" %d: shift=%02x, sllp=%04x, avpnm=%08x, " + "tlbiel=%d, penc=%d\n", + idx, shift, def->sllp, def->avpnm, def->tlbiel, + def->penc); } + return 1; + } + return 0; +} + + +static void __init htab_init_page_sizes(void) +{ + int rc; + + /* Default to 4K pages only */ + memcpy(mmu_psize_defs, mmu_psize_defaults_old, + sizeof(mmu_psize_defaults_old)); + + /* + * Try to find the available page sizes in the device-tree + */ + rc = of_scan_flat_dt(htab_dt_scan_page_sizes, NULL); + if (rc != 0) /* Found */ + goto found; + + /* + * Not in the device-tree, let's fallback on known size + * list for 16M capable GP & GR + */ + if ((systemcfg->platform != PLATFORM_ISERIES_LPAR) && + cpu_has_feature(CPU_FTR_16M_PAGE)) + memcpy(mmu_psize_defs, mmu_psize_defaults_gp, + sizeof(mmu_psize_defaults_gp)); + found: + /* + * Pick a size for the linear mapping. Currently, we only support + * 16M, 1M and 4K which is the default + */ + if (mmu_psize_defs[MMU_PAGE_16M].shift) + mmu_linear_psize = MMU_PAGE_16M; + else if (mmu_psize_defs[MMU_PAGE_1M].shift) + mmu_linear_psize = MMU_PAGE_1M; + + /* + * Pick a size for the ordinary pages. Default is 4K, we support + * 64K if cache inhibited large pages are supported by the + * processor + */ +#ifdef CONFIG_PPC_64K_PAGES + if (mmu_psize_defs[MMU_PAGE_64K].shift && + cpu_has_feature(CPU_FTR_CI_LARGE_PAGE)) + mmu_virtual_psize = MMU_PAGE_64K; +#endif + + printk(KERN_INFO "Page orders: linear mapping = %d, others = %d\n", + mmu_psize_defs[mmu_linear_psize].shift, + mmu_psize_defs[mmu_virtual_psize].shift); + +#ifdef CONFIG_HUGETLB_PAGE + /* Init large page size. Currently, we pick 16M or 1M depending + * on what is available + */ + if (mmu_psize_defs[MMU_PAGE_16M].shift) + mmu_huge_psize = MMU_PAGE_16M; + else if (mmu_psize_defs[MMU_PAGE_1M].shift) + mmu_huge_psize = MMU_PAGE_1M; + + /* Calculate HPAGE_SHIFT and sanity check it */ + if (mmu_psize_defs[mmu_huge_psize].shift > 16 && + mmu_psize_defs[mmu_huge_psize].shift < 28) + HPAGE_SHIFT = mmu_psize_defs[mmu_huge_psize].shift; + else + HPAGE_SHIFT = 0; /* No huge pages dude ! */ +#endif /* CONFIG_HUGETLB_PAGE */ +} + +static int __init htab_dt_scan_pftsize(unsigned long node, + const char *uname, int depth, + void *data) +{ + char *type = of_get_flat_dt_prop(node, "device_type", NULL); + u32 *prop; + + /* We are scanning "cpu" nodes only */ + if (type == NULL || strcmp(type, "cpu") != 0) + return 0; + + prop = (u32 *)of_get_flat_dt_prop(node, "ibm,pft-size", NULL); + if (prop != NULL) { + /* pft_size[0] is the NUMA CEC cookie */ + ppc64_pft_size = prop[1]; + return 1; } + return 0; } -static unsigned long get_hashtable_size(void) +static unsigned long __init htab_get_table_size(void) { unsigned long rnd_mem_size, pteg_count; - /* If hash size wasn't obtained in prom.c, we calculate it now based on - * the total RAM size + /* If hash size isn't already provided by the platform, we try to + * retreive it from the device-tree. If it's not there neither, we + * calculate it now based on the total RAM size */ + if (ppc64_pft_size == 0) + of_scan_flat_dt(htab_dt_scan_pftsize, NULL); if (ppc64_pft_size) return 1UL << ppc64_pft_size; @@ -181,17 +390,21 @@ void __init htab_initialize(void) unsigned long table, htab_size_bytes; unsigned long pteg_count; unsigned long mode_rw; - int i, use_largepages = 0; unsigned long base = 0, size = 0; + int i; + extern unsigned long tce_alloc_start, tce_alloc_end; DBG(" -> htab_initialize()\n"); + /* Initialize page sizes */ + htab_init_page_sizes(); + /* * Calculate the required size of the htab. We want the number of * PTEGs to equal one half the number of real pages. */ - htab_size_bytes = get_hashtable_size(); + htab_size_bytes = htab_get_table_size(); pteg_count = htab_size_bytes >> 7; /* For debug, make the HTAB 1/8 as big as it normally would be. */ @@ -211,14 +424,11 @@ void __init htab_initialize(void) * the absolute address space. */ table = lmb_alloc(htab_size_bytes, htab_size_bytes); + BUG_ON(table == 0); DBG("Hash table allocated at %lx, size: %lx\n", table, htab_size_bytes); - if ( !table ) { - ppc64_terminate_msg(0x20, "hpt space"); - loop_forever(); - } htab_address = abs_to_virt(table); /* htab absolute addr + encoded htabsize */ @@ -234,8 +444,6 @@ void __init htab_initialize(void) * _NOT_ map it to avoid cache paradoxes as it's remapped non * cacheable later on */ - if (cpu_has_feature(CPU_FTR_16M_PAGE)) - use_largepages = 1; /* create bolted the linear mapping in the hash table */ for (i=0; i < lmb.memory.cnt; i++) { @@ -246,27 +454,32 @@ void __init htab_initialize(void) #ifdef CONFIG_U3_DART /* Do not map the DART space. Fortunately, it will be aligned - * in such a way that it will not cross two lmb regions and will - * fit within a single 16Mb page. - * The DART space is assumed to be a full 16Mb region even if we - * only use 2Mb of that space. We will use more of it later for - * AGP GART. We have to use a full 16Mb large page. + * in such a way that it will not cross two lmb regions and + * will fit within a single 16Mb page. + * The DART space is assumed to be a full 16Mb region even if + * we only use 2Mb of that space. We will use more of it later + * for AGP GART. We have to use a full 16Mb large page. */ DBG("DART base: %lx\n", dart_tablebase); if (dart_tablebase != 0 && dart_tablebase >= base && dart_tablebase < (base + size)) { if (base != dart_tablebase) - create_pte_mapping(base, dart_tablebase, mode_rw, - use_largepages); + BUG_ON(htab_bolt_mapping(base, dart_tablebase, + base, mode_rw, + mmu_linear_psize)); if ((base + size) > (dart_tablebase + 16*MB)) - create_pte_mapping(dart_tablebase + 16*MB, base + size, - mode_rw, use_largepages); + BUG_ON(htab_bolt_mapping(dart_tablebase+16*MB, + base + size, + dart_tablebase+16*MB, + mode_rw, + mmu_linear_psize)); continue; } #endif /* CONFIG_U3_DART */ - create_pte_mapping(base, base + size, mode_rw, use_largepages); - } + BUG_ON(htab_bolt_mapping(base, base + size, base, + mode_rw, mmu_linear_psize)); + } /* * If we have a memory_limit and we've allocated TCEs then we need to @@ -282,8 +495,9 @@ void __init htab_initialize(void) if (base + size >= tce_alloc_start) tce_alloc_start = base + size + 1; - create_pte_mapping(tce_alloc_start, tce_alloc_end, - mode_rw, use_largepages); + BUG_ON(htab_bolt_mapping(tce_alloc_start, tce_alloc_end, + tce_alloc_start, mode_rw, + mmu_linear_psize)); } DBG(" <- htab_initialize()\n"); @@ -298,9 +512,6 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap) { struct page *page; - if (!pfn_valid(pte_pfn(pte))) - return pp; - page = pte_page(pte); /* page is dirty */ @@ -309,7 +520,7 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap) __flush_dcache_icache(page_address(page)); set_bit(PG_arch_1, &page->flags); } else - pp |= HW_NO_EXEC; + pp |= HPTE_R_N; } return pp; } @@ -325,94 +536,169 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) unsigned long vsid; struct mm_struct *mm; pte_t *ptep; - int ret; - int user_region = 0; - int local = 0; cpumask_t tmp; + int rc, user_region = 0, local = 0; - if ((ea & ~REGION_MASK) >= PGTABLE_RANGE) - return 1; + DBG_LOW("hash_page(ea=%016lx, access=%lx, trap=%lx\n", + ea, access, trap); + if ((ea & ~REGION_MASK) >= PGTABLE_RANGE) { + DBG_LOW(" out of pgtable range !\n"); + return 1; + } + + /* Get region & vsid */ switch (REGION_ID(ea)) { case USER_REGION_ID: user_region = 1; mm = current->mm; - if (! mm) + if (! mm) { + DBG_LOW(" user region with no mm !\n"); return 1; - + } vsid = get_vsid(mm->context.id, ea); break; case VMALLOC_REGION_ID: mm = &init_mm; vsid = get_kernel_vsid(ea); break; -#if 0 - case KERNEL_REGION_ID: - /* - * Should never get here - entire 0xC0... region is bolted. - * Send the problem up to do_page_fault - */ -#endif default: /* Not a valid range * Send the problem up to do_page_fault */ return 1; - break; } + DBG_LOW(" mm=%p, mm->pgdir=%p, vsid=%016lx\n", mm, mm->pgd, vsid); + /* Get pgdir */ pgdir = mm->pgd; - if (pgdir == NULL) return 1; + /* Check CPU locality */ tmp = cpumask_of_cpu(smp_processor_id()); if (user_region && cpus_equal(mm->cpu_vm_mask, tmp)) local = 1; - /* Is this a huge page ? */ - if (unlikely(in_hugepage_area(mm->context, ea))) - ret = hash_huge_page(mm, access, ea, vsid, local); - else { - ptep = find_linux_pte(pgdir, ea); - if (ptep == NULL) - return 1; - ret = __hash_page(ea, access, vsid, ptep, trap, local); + /* Handle hugepage regions */ + if (unlikely(in_hugepage_area(mm->context, ea))) { + DBG_LOW(" -> huge page !\n"); + return hash_huge_page(mm, access, ea, vsid, local); + } + + /* Get PTE and page size from page tables */ + ptep = find_linux_pte(pgdir, ea); + if (ptep == NULL || !pte_present(*ptep)) { + DBG_LOW(" no PTE !\n"); + return 1; + } + +#ifndef CONFIG_PPC_64K_PAGES + DBG_LOW(" i-pte: %016lx\n", pte_val(*ptep)); +#else + DBG_LOW(" i-pte: %016lx %016lx\n", pte_val(*ptep), + pte_val(*(ptep + PTRS_PER_PTE))); +#endif + /* Pre-check access permissions (will be re-checked atomically + * in __hash_page_XX but this pre-check is a fast path + */ + if (access & ~pte_val(*ptep)) { + DBG_LOW(" no access !\n"); + return 1; } - return ret; + /* Do actual hashing */ +#ifndef CONFIG_PPC_64K_PAGES + rc = __hash_page_4K(ea, access, vsid, ptep, trap, local); +#else + if (mmu_virtual_psize == MMU_PAGE_64K) + rc = __hash_page_64K(ea, access, vsid, ptep, trap, local); + else + rc = __hash_page_4K(ea, access, vsid, ptep, trap, local); +#endif /* CONFIG_PPC_64K_PAGES */ + +#ifndef CONFIG_PPC_64K_PAGES + DBG_LOW(" o-pte: %016lx\n", pte_val(*ptep)); +#else + DBG_LOW(" o-pte: %016lx %016lx\n", pte_val(*ptep), + pte_val(*(ptep + PTRS_PER_PTE))); +#endif + DBG_LOW(" -> rc=%d\n", rc); + return rc; } -void flush_hash_page(unsigned long va, pte_t pte, int local) +void hash_preload(struct mm_struct *mm, unsigned long ea, + unsigned long access, unsigned long trap) { - unsigned long vpn, hash, secondary, slot; - unsigned long huge = pte_huge(pte); + unsigned long vsid; + void *pgdir; + pte_t *ptep; + cpumask_t mask; + unsigned long flags; + int local = 0; + + /* We don't want huge pages prefaulted for now + */ + if (unlikely(in_hugepage_area(mm->context, ea))) + return; + + DBG_LOW("hash_preload(mm=%p, mm->pgdir=%p, ea=%016lx, access=%lx," + " trap=%lx\n", mm, mm->pgd, ea, access, trap); - if (huge) - vpn = va >> HPAGE_SHIFT; + /* Get PTE, VSID, access mask */ + pgdir = mm->pgd; + if (pgdir == NULL) + return; + ptep = find_linux_pte(pgdir, ea); + if (!ptep) + return; + vsid = get_vsid(mm->context.id, ea); + + /* Hash it in */ + local_irq_save(flags); + mask = cpumask_of_cpu(smp_processor_id()); + if (cpus_equal(mm->cpu_vm_mask, mask)) + local = 1; +#ifndef CONFIG_PPC_64K_PAGES + __hash_page_4K(ea, access, vsid, ptep, trap, local); +#else + if (mmu_virtual_psize == MMU_PAGE_64K) + __hash_page_64K(ea, access, vsid, ptep, trap, local); else - vpn = va >> PAGE_SHIFT; - hash = hpt_hash(vpn, huge); - secondary = (pte_val(pte) & _PAGE_SECONDARY) >> 15; - if (secondary) - hash = ~hash; - slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; - slot += (pte_val(pte) & _PAGE_GROUP_IX) >> 12; - - ppc_md.hpte_invalidate(slot, va, huge, local); + __hash_page_4K(ea, access, vsid, ptep, trap, local); +#endif /* CONFIG_PPC_64K_PAGES */ + local_irq_restore(flags); +} + +void flush_hash_page(unsigned long va, real_pte_t pte, int psize, int local) +{ + unsigned long hash, index, shift, hidx, slot; + + DBG_LOW("flush_hash_page(va=%016x)\n", va); + pte_iterate_hashed_subpages(pte, psize, va, index, shift) { + hash = hpt_hash(va, shift); + hidx = __rpte_to_hidx(pte, index); + if (hidx & _PTEIDX_SECONDARY) + hash = ~hash; + slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; + slot += hidx & _PTEIDX_GROUP_IX; + DBG_LOW(" sub %d: hash=%x, hidx=%x\n", index, slot, hidx); + ppc_md.hpte_invalidate(slot, va, psize, local); + } pte_iterate_hashed_end(); } void flush_hash_range(unsigned long number, int local) { - if (ppc_md.flush_hash_range) { + if (ppc_md.flush_hash_range) ppc_md.flush_hash_range(number, local); - } else { + else { int i; struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); for (i = 0; i < number; i++) - flush_hash_page(batch->vaddr[i], batch->pte[i], local); + flush_hash_page(batch->vaddr[i], batch->pte[i], + batch->psize, local); } } @@ -452,6 +738,18 @@ void __init htab_finish_init(void) extern unsigned int *htab_call_hpte_remove; extern unsigned int *htab_call_hpte_updatepp; +#ifdef CONFIG_PPC_64K_PAGES + extern unsigned int *ht64_call_hpte_insert1; + extern unsigned int *ht64_call_hpte_insert2; + extern unsigned int *ht64_call_hpte_remove; + extern unsigned int *ht64_call_hpte_updatepp; + + make_bl(ht64_call_hpte_insert1, ppc_md.hpte_insert); + make_bl(ht64_call_hpte_insert2, ppc_md.hpte_insert); + make_bl(ht64_call_hpte_remove, ppc_md.hpte_remove); + make_bl(ht64_call_hpte_updatepp, ppc_md.hpte_updatepp); +#endif /* CONFIG_PPC_64K_PAGES */ + make_bl(htab_call_hpte_insert1, ppc_md.hpte_insert); make_bl(htab_call_hpte_insert2, ppc_md.hpte_insert); make_bl(htab_call_hpte_remove, ppc_md.hpte_remove); diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 0ea0994ed97..0073a04047e 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -47,10 +47,25 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) pu = pud_offset(pg, addr); if (!pud_none(*pu)) { pm = pmd_offset(pu, addr); +#ifdef CONFIG_PPC_64K_PAGES + /* Currently, we use the normal PTE offset within full + * size PTE pages, thus our huge PTEs are scattered in + * the PTE page and we do waste some. We may change + * that in the future, but the current mecanism keeps + * things much simpler + */ + if (!pmd_none(*pm)) { + /* Note: pte_offset_* are all equivalent on + * ppc64 as we don't have HIGHMEM + */ + pt = pte_offset_kernel(pm, addr); + return pt; + } +#else /* CONFIG_PPC_64K_PAGES */ + /* On 4k pages, we put huge PTEs in the PMD page */ pt = (pte_t *)pm; - BUG_ON(!pmd_none(*pm) - && !(pte_present(*pt) && pte_huge(*pt))); return pt; +#endif /* CONFIG_PPC_64K_PAGES */ } } @@ -74,9 +89,16 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr) if (pu) { pm = pmd_alloc(mm, pu, addr); if (pm) { +#ifdef CONFIG_PPC_64K_PAGES + /* See comment in huge_pte_offset. Note that if we ever + * want to put the page size in the PMD, we would have + * to open code our own pte_alloc* function in order + * to populate and set the size atomically + */ + pt = pte_alloc_map(mm, pm, addr); +#else /* CONFIG_PPC_64K_PAGES */ pt = (pte_t *)pm; - BUG_ON(!pmd_none(*pm) - && !(pte_present(*pt) && pte_huge(*pt))); +#endif /* CONFIG_PPC_64K_PAGES */ return pt; } } @@ -84,35 +106,29 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr) return NULL; } -#define HUGEPTE_BATCH_SIZE (HPAGE_SIZE / PMD_SIZE) - void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte) { - int i; - if (pte_present(*ptep)) { - pte_clear(mm, addr, ptep); + /* We open-code pte_clear because we need to pass the right + * argument to hpte_update (huge / !huge) + */ + unsigned long old = pte_update(ptep, ~0UL); + if (old & _PAGE_HASHPTE) + hpte_update(mm, addr & HPAGE_MASK, ptep, old, 1); flush_tlb_pending(); } - - for (i = 0; i < HUGEPTE_BATCH_SIZE; i++) { - *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); - ptep++; - } + *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); } pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { unsigned long old = pte_update(ptep, ~0UL); - int i; if (old & _PAGE_HASHPTE) - hpte_update(mm, addr, old, 0); - - for (i = 1; i < HUGEPTE_BATCH_SIZE; i++) - ptep[i] = __pte(0); + hpte_update(mm, addr & HPAGE_MASK, ptep, old, 1); + *ptep = __pte(0); return __pte(old); } @@ -563,6 +579,8 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, int lastshift; u16 areamask, curareas; + if (HPAGE_SHIFT == 0) + return -EINVAL; if (len & ~HPAGE_MASK) return -EINVAL; @@ -619,19 +637,15 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access, unsigned long ea, unsigned long vsid, int local) { pte_t *ptep; - unsigned long va, vpn; - pte_t old_pte, new_pte; - unsigned long rflags, prpn; + unsigned long old_pte, new_pte; + unsigned long va, rflags, pa; long slot; int err = 1; - spin_lock(&mm->page_table_lock); - ptep = huge_pte_offset(mm, ea); /* Search the Linux page table for a match with va */ va = (vsid << 28) | (ea & 0x0fffffff); - vpn = va >> HPAGE_SHIFT; /* * If no pte found or not present, send the problem up to @@ -640,8 +654,6 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access, if (unlikely(!ptep || pte_none(*ptep))) goto out; -/* BUG_ON(pte_bad(*ptep)); */ - /* * Check the user's access rights to the page. If access should be * prevented then send the problem up to do_page_fault. @@ -661,58 +673,64 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access, */ - old_pte = *ptep; - new_pte = old_pte; - - rflags = 0x2 | (! (pte_val(new_pte) & _PAGE_RW)); + do { + old_pte = pte_val(*ptep); + if (old_pte & _PAGE_BUSY) + goto out; + new_pte = old_pte | _PAGE_BUSY | + _PAGE_ACCESSED | _PAGE_HASHPTE; + } while(old_pte != __cmpxchg_u64((unsigned long *)ptep, + old_pte, new_pte)); + + rflags = 0x2 | (!(new_pte & _PAGE_RW)); /* _PAGE_EXEC -> HW_NO_EXEC since it's inverted */ - rflags |= ((pte_val(new_pte) & _PAGE_EXEC) ? 0 : HW_NO_EXEC); + rflags |= ((new_pte & _PAGE_EXEC) ? 0 : HPTE_R_N); /* Check if pte already has an hpte (case 2) */ - if (unlikely(pte_val(old_pte) & _PAGE_HASHPTE)) { + if (unlikely(old_pte & _PAGE_HASHPTE)) { /* There MIGHT be an HPTE for this pte */ unsigned long hash, slot; - hash = hpt_hash(vpn, 1); - if (pte_val(old_pte) & _PAGE_SECONDARY) + hash = hpt_hash(va, HPAGE_SHIFT); + if (old_pte & _PAGE_F_SECOND) hash = ~hash; slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; - slot += (pte_val(old_pte) & _PAGE_GROUP_IX) >> 12; + slot += (old_pte & _PAGE_F_GIX) >> 12; if (ppc_md.hpte_updatepp(slot, rflags, va, 1, local) == -1) - pte_val(old_pte) &= ~_PAGE_HPTEFLAGS; + old_pte &= ~_PAGE_HPTEFLAGS; } - if (likely(!(pte_val(old_pte) & _PAGE_HASHPTE))) { - unsigned long hash = hpt_hash(vpn, 1); + if (likely(!(old_pte & _PAGE_HASHPTE))) { + unsigned long hash = hpt_hash(va, HPAGE_SHIFT); unsigned long hpte_group; - prpn = pte_pfn(old_pte); + pa = pte_pfn(__pte(old_pte)) << PAGE_SHIFT; repeat: hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; - /* Update the linux pte with the HPTE slot */ - pte_val(new_pte) &= ~_PAGE_HPTEFLAGS; - pte_val(new_pte) |= _PAGE_HASHPTE; + /* clear HPTE slot informations in new PTE */ + new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE; /* Add in WIMG bits */ /* XXX We should store these in the pte */ + /* --BenH: I think they are ... */ rflags |= _PAGE_COHERENT; - slot = ppc_md.hpte_insert(hpte_group, va, prpn, - HPTE_V_LARGE, rflags); + /* Insert into the hash table, primary slot */ + slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags, 0, + mmu_huge_psize); /* Primary is full, try the secondary */ if (unlikely(slot == -1)) { - pte_val(new_pte) |= _PAGE_SECONDARY; + new_pte |= _PAGE_F_SECOND; hpte_group = ((~hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; - slot = ppc_md.hpte_insert(hpte_group, va, prpn, - HPTE_V_LARGE | + slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags, HPTE_V_SECONDARY, - rflags); + mmu_huge_psize); if (slot == -1) { if (mftb() & 0x1) hpte_group = ((hash & htab_hash_mask) * @@ -726,20 +744,18 @@ repeat: if (unlikely(slot == -2)) panic("hash_huge_page: pte_insert failed\n"); - pte_val(new_pte) |= (slot<<12) & _PAGE_GROUP_IX; - - /* - * No need to use ldarx/stdcx here because all who - * might be updating the pte will hold the - * page_table_lock - */ - *ptep = new_pte; + new_pte |= (slot << 12) & _PAGE_F_GIX; } + /* + * No need to use ldarx/stdcx here because all who + * might be updating the pte will hold the + * page_table_lock + */ + *ptep = __pte(new_pte & ~_PAGE_BUSY); + err = 0; out: - spin_unlock(&mm->page_table_lock); - return err; } diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index b0fc822ec29..dfe7fa37b41 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -188,12 +188,21 @@ static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags) memset(addr, 0, kmem_cache_size(cache)); } +#ifdef CONFIG_PPC_64K_PAGES +static const int pgtable_cache_size[2] = { + PTE_TABLE_SIZE, PGD_TABLE_SIZE +}; +static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { + "pte_pmd_cache", "pgd_cache", +}; +#else static const int pgtable_cache_size[2] = { PTE_TABLE_SIZE, PMD_TABLE_SIZE }; static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { "pgd_pte_cache", "pud_pmd_cache", }; +#endif /* CONFIG_PPC_64K_PAGES */ kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)]; @@ -201,19 +210,14 @@ void pgtable_cache_init(void) { int i; - BUILD_BUG_ON(PTE_TABLE_SIZE != pgtable_cache_size[PTE_CACHE_NUM]); - BUILD_BUG_ON(PMD_TABLE_SIZE != pgtable_cache_size[PMD_CACHE_NUM]); - BUILD_BUG_ON(PUD_TABLE_SIZE != pgtable_cache_size[PUD_CACHE_NUM]); - BUILD_BUG_ON(PGD_TABLE_SIZE != pgtable_cache_size[PGD_CACHE_NUM]); - for (i = 0; i < ARRAY_SIZE(pgtable_cache_size); i++) { int size = pgtable_cache_size[i]; const char *name = pgtable_cache_name[i]; pgtable_cache[i] = kmem_cache_create(name, size, size, - SLAB_HWCACHE_ALIGN - | SLAB_MUST_HWCACHE_ALIGN, + SLAB_HWCACHE_ALIGN | + SLAB_MUST_HWCACHE_ALIGN, zero_ctor, NULL); if (! pgtable_cache[i]) diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 117b00012e1..7faa46b71f2 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -61,6 +61,9 @@ int init_bootmem_done; int mem_init_done; unsigned long memory_limit; +extern void hash_preload(struct mm_struct *mm, unsigned long ea, + unsigned long access, unsigned long trap); + /* * This is called by /dev/mem to know if a given address has to * be mapped non-cacheable or not @@ -493,18 +496,10 @@ EXPORT_SYMBOL(flush_icache_user_range); void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) { - /* handle i-cache coherency */ - unsigned long pfn = pte_pfn(pte); -#ifdef CONFIG_PPC32 - pmd_t *pmd; -#else - unsigned long vsid; - void *pgdir; - pte_t *ptep; - int local = 0; - cpumask_t tmp; - unsigned long flags; +#ifdef CONFIG_PPC_STD_MMU + unsigned long access = 0, trap; #endif + unsigned long pfn = pte_pfn(pte); /* handle i-cache coherency */ if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE) && @@ -535,30 +530,21 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, /* We only want HPTEs for linux PTEs that have _PAGE_ACCESSED set */ if (!pte_young(pte) || address >= TASK_SIZE) return; -#ifdef CONFIG_PPC32 - if (Hash == 0) - return; - pmd = pmd_offset(pgd_offset(vma->vm_mm, address), address); - if (!pmd_none(*pmd)) - add_hash_page(vma->vm_mm->context, address, pmd_val(*pmd)); -#else - pgdir = vma->vm_mm->pgd; - if (pgdir == NULL) - return; - ptep = find_linux_pte(pgdir, address); - if (!ptep) + /* We try to figure out if we are coming from an instruction + * access fault and pass that down to __hash_page so we avoid + * double-faulting on execution of fresh text. We have to test + * for regs NULL since init will get here first thing at boot + * + * We also avoid filling the hash if not coming from a fault + */ + if (current->thread.regs == NULL) return; - - vsid = get_vsid(vma->vm_mm->context.id, address); - - local_irq_save(flags); - tmp = cpumask_of_cpu(smp_processor_id()); - if (cpus_equal(vma->vm_mm->cpu_vm_mask, tmp)) - local = 1; - - __hash_page(address, 0, vsid, ptep, 0x300, local); - local_irq_restore(flags); -#endif -#endif + trap = TRAP(current->thread.regs); + if (trap == 0x400) + access |= _PAGE_EXEC; + else if (trap != 0x300) + return; + hash_preload(vma->vm_mm, address, access, trap); +#endif /* CONFIG_PPC_STD_MMU */ } diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index b79a7820613..51b78694097 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c @@ -101,7 +101,6 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags) pud_t *pudp; pmd_t *pmdp; pte_t *ptep; - unsigned long vsid; if (mem_init_done) { pgdp = pgd_offset_k(ea); @@ -117,28 +116,15 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags) set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, __pgprot(flags))); } else { - unsigned long va, vpn, hash, hpteg; - /* * If the mm subsystem is not fully up, we cannot create a * linux page table entry for this mapping. Simply bolt an * entry in the hardware page table. + * */ - vsid = get_kernel_vsid(ea); - va = (vsid << 28) | (ea & 0xFFFFFFF); - vpn = va >> PAGE_SHIFT; - - hash = hpt_hash(vpn, 0); - - hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); - - /* Panic if a pte grpup is full */ - if (ppc_md.hpte_insert(hpteg, va, pa >> PAGE_SHIFT, - HPTE_V_BOLTED, - _PAGE_NO_CACHE|_PAGE_GUARDED|PP_RWXX) - == -1) { - panic("map_io_page: could not insert mapping"); - } + if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags, + mmu_virtual_psize)) + panic("Can't map bolted IO mapping"); } return 0; } diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c index cef9e83cc7e..d137abd241f 100644 --- a/arch/powerpc/mm/ppc_mmu_32.c +++ b/arch/powerpc/mm/ppc_mmu_32.c @@ -178,6 +178,21 @@ void __init setbat(int index, unsigned long virt, unsigned long phys, bat_addrs[index].phys = phys; } +/* + * Preload a translation in the hash table + */ +void hash_preload(struct mm_struct *mm, unsigned long ea, + unsigned long access, unsigned long trap) +{ + pmd_t *pmd; + + if (Hash == 0) + return; + pmd = pmd_offset(pgd_offset(vma->vm_mm, address), address); + if (!pmd_none(*pmd)) + add_hash_page(vma->vm_mm->context, address, pmd_val(*pmd)); +} + /* * Initialize the hash table and patch the instructions in hashtable.S. */ diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c index 0473953f6a3..60e852f2f8e 100644 --- a/arch/powerpc/mm/slb.c +++ b/arch/powerpc/mm/slb.c @@ -14,14 +14,32 @@ * 2 of the License, or (at your option) any later version. */ +#undef DEBUG + #include #include #include #include #include #include +#include + +#ifdef DEBUG +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) +#endif -extern void slb_allocate(unsigned long ea); +extern void slb_allocate_realmode(unsigned long ea); +extern void slb_allocate_user(unsigned long ea); + +static void slb_allocate(unsigned long ea) +{ + /* Currently, we do real mode for all SLBs including user, but + * that will change if we bring back dynamic VSIDs + */ + slb_allocate_realmode(ea); +} static inline unsigned long mk_esid_data(unsigned long ea, unsigned long slot) { @@ -46,13 +64,15 @@ static void slb_flush_and_rebolt(void) { /* If you change this make sure you change SLB_NUM_BOLTED * appropriately too. */ - unsigned long ksp_flags = SLB_VSID_KERNEL; + unsigned long linear_llp, virtual_llp, lflags, vflags; unsigned long ksp_esid_data; WARN_ON(!irqs_disabled()); - if (cpu_has_feature(CPU_FTR_16M_PAGE)) - ksp_flags |= SLB_VSID_L; + linear_llp = mmu_psize_defs[mmu_linear_psize].sllp; + virtual_llp = mmu_psize_defs[mmu_virtual_psize].sllp; + lflags = SLB_VSID_KERNEL | linear_llp; + vflags = SLB_VSID_KERNEL | virtual_llp; ksp_esid_data = mk_esid_data(get_paca()->kstack, 2); if ((ksp_esid_data & ESID_MASK) == KERNELBASE) @@ -67,9 +87,9 @@ static void slb_flush_and_rebolt(void) /* Slot 2 - kernel stack */ "slbmte %2,%3\n" "isync" - :: "r"(mk_vsid_data(VMALLOCBASE, SLB_VSID_KERNEL)), + :: "r"(mk_vsid_data(VMALLOCBASE, vflags)), "r"(mk_esid_data(VMALLOCBASE, 1)), - "r"(mk_vsid_data(ksp_esid_data, ksp_flags)), + "r"(mk_vsid_data(ksp_esid_data, lflags)), "r"(ksp_esid_data) : "memory"); } @@ -102,6 +122,9 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm) get_paca()->slb_cache_ptr = 0; get_paca()->context = mm->context; +#ifdef CONFIG_PPC_64K_PAGES + get_paca()->pgdir = mm->pgd; +#endif /* CONFIG_PPC_64K_PAGES */ /* * preload some userspace segments into the SLB. @@ -131,28 +154,77 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm) slb_allocate(unmapped_base); } +static inline void patch_slb_encoding(unsigned int *insn_addr, + unsigned int immed) +{ + /* Assume the instruction had a "0" immediate value, just + * "or" in the new value + */ + *insn_addr |= immed; + flush_icache_range((unsigned long)insn_addr, 4+ + (unsigned long)insn_addr); +} + void slb_initialize(void) { + unsigned long linear_llp, virtual_llp; + static int slb_encoding_inited; + extern unsigned int *slb_miss_kernel_load_linear; + extern unsigned int *slb_miss_kernel_load_virtual; + extern unsigned int *slb_miss_user_load_normal; +#ifdef CONFIG_HUGETLB_PAGE + extern unsigned int *slb_miss_user_load_huge; + unsigned long huge_llp; + + huge_llp = mmu_psize_defs[mmu_huge_psize].sllp; +#endif + + /* Prepare our SLB miss handler based on our page size */ + linear_llp = mmu_psize_defs[mmu_linear_psize].sllp; + virtual_llp = mmu_psize_defs[mmu_virtual_psize].sllp; + if (!slb_encoding_inited) { + slb_encoding_inited = 1; + patch_slb_encoding(slb_miss_kernel_load_linear, + SLB_VSID_KERNEL | linear_llp); + patch_slb_encoding(slb_miss_kernel_load_virtual, + SLB_VSID_KERNEL | virtual_llp); + patch_slb_encoding(slb_miss_user_load_normal, + SLB_VSID_USER | virtual_llp); + + DBG("SLB: linear LLP = %04x\n", linear_llp); + DBG("SLB: virtual LLP = %04x\n", virtual_llp); +#ifdef CONFIG_HUGETLB_PAGE + patch_slb_encoding(slb_miss_user_load_huge, + SLB_VSID_USER | huge_llp); + DBG("SLB: huge LLP = %04x\n", huge_llp); +#endif + } + /* On iSeries the bolted entries have already been set up by * the hypervisor from the lparMap data in head.S */ #ifndef CONFIG_PPC_ISERIES - unsigned long flags = SLB_VSID_KERNEL; + { + unsigned long lflags, vflags; - /* Invalidate the entire SLB (even slot 0) & all the ERATS */ - if (cpu_has_feature(CPU_FTR_16M_PAGE)) - flags |= SLB_VSID_L; + lflags = SLB_VSID_KERNEL | linear_llp; + vflags = SLB_VSID_KERNEL | virtual_llp; - asm volatile("isync":::"memory"); - asm volatile("slbmte %0,%0"::"r" (0) : "memory"); + /* Invalidate the entire SLB (even slot 0) & all the ERATS */ + asm volatile("isync":::"memory"); + asm volatile("slbmte %0,%0"::"r" (0) : "memory"); asm volatile("isync; slbia; isync":::"memory"); - create_slbe(KERNELBASE, flags, 0); - create_slbe(VMALLOCBASE, SLB_VSID_KERNEL, 1); + create_slbe(KERNELBASE, lflags, 0); + + /* VMALLOC space has 4K pages always for now */ + create_slbe(VMALLOCBASE, vflags, 1); + /* We don't bolt the stack for the time being - we're in boot, * so the stack is in the bolted segment. By the time it goes * elsewhere, we'll call _switch() which will bolt in the new * one. */ asm volatile("isync":::"memory"); -#endif + } +#endif /* CONFIG_PPC_ISERIES */ get_paca()->stab_rr = SLB_NUM_BOLTED; } diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S index a3a03da503b..3e18241b6f3 100644 --- a/arch/powerpc/mm/slb_low.S +++ b/arch/powerpc/mm/slb_low.S @@ -18,61 +18,28 @@ #include #include -#include -#include #include #include #include +#include +#include +#include -/* void slb_allocate(unsigned long ea); +/* void slb_allocate_realmode(unsigned long ea); * * Create an SLB entry for the given EA (user or kernel). * r3 = faulting address, r13 = PACA * r9, r10, r11 are clobbered by this function * No other registers are examined or changed. */ -_GLOBAL(slb_allocate) - /* - * First find a slot, round robin. Previously we tried to find - * a free slot first but that took too long. Unfortunately we - * dont have any LRU information to help us choose a slot. - */ -#ifdef CONFIG_PPC_ISERIES - /* - * On iSeries, the "bolted" stack segment can be cast out on - * shared processor switch so we need to check for a miss on - * it and restore it to the right slot. - */ - ld r9,PACAKSAVE(r13) - clrrdi r9,r9,28 - clrrdi r11,r3,28 - li r10,SLB_NUM_BOLTED-1 /* Stack goes in last bolted slot */ - cmpld r9,r11 - beq 3f -#endif /* CONFIG_PPC_ISERIES */ - - ld r10,PACASTABRR(r13) - addi r10,r10,1 - /* use a cpu feature mask if we ever change our slb size */ - cmpldi r10,SLB_NUM_ENTRIES - - blt+ 4f - li r10,SLB_NUM_BOLTED - -4: - std r10,PACASTABRR(r13) -3: - /* r3 = faulting address, r10 = entry */ +_GLOBAL(slb_allocate_realmode) + /* r3 = faulting address */ srdi r9,r3,60 /* get region */ - srdi r3,r3,28 /* get esid */ + srdi r10,r3,28 /* get esid */ cmpldi cr7,r9,0xc /* cmp KERNELBASE for later use */ - rldimi r10,r3,28,0 /* r10= ESID<<28 | entry */ - oris r10,r10,SLB_ESID_V@h /* r10 |= SLB_ESID_V */ - - /* r3 = esid, r10 = esid_data, cr7 = <>KERNELBASE */ - + /* r3 = address, r10 = esid, cr7 = <>KERNELBASE */ blt cr7,0f /* user or kernel? */ /* kernel address: proto-VSID = ESID */ @@ -81,43 +48,161 @@ _GLOBAL(slb_allocate) * top segment. That's ok, the scramble below will translate * it to VSID 0, which is reserved as a bad VSID - one which * will never have any pages in it. */ - li r11,SLB_VSID_KERNEL -BEGIN_FTR_SECTION - bne cr7,9f - li r11,(SLB_VSID_KERNEL|SLB_VSID_L) -END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE) - b 9f -0: /* user address: proto-VSID = context<<15 | ESID */ - srdi. r9,r3,USER_ESID_BITS + /* Check if hitting the linear mapping of the vmalloc/ioremap + * kernel space + */ + bne cr7,1f + + /* Linear mapping encoding bits, the "li" instruction below will + * be patched by the kernel at boot + */ +_GLOBAL(slb_miss_kernel_load_linear) + li r11,0 + b slb_finish_load + +1: /* vmalloc/ioremap mapping encoding bits, the "li" instruction below + * will be patched by the kernel at boot + */ +_GLOBAL(slb_miss_kernel_load_virtual) + li r11,0 + b slb_finish_load + + +0: /* user address: proto-VSID = context << 15 | ESID. First check + * if the address is within the boundaries of the user region + */ + srdi. r9,r10,USER_ESID_BITS bne- 8f /* invalid ea bits set */ + /* Figure out if the segment contains huge pages */ #ifdef CONFIG_HUGETLB_PAGE BEGIN_FTR_SECTION + b 1f +END_FTR_SECTION_IFCLR(CPU_FTR_16M_PAGE) lhz r9,PACAHIGHHTLBAREAS(r13) - srdi r11,r3,(HTLB_AREA_SHIFT-SID_SHIFT) + srdi r11,r10,(HTLB_AREA_SHIFT-SID_SHIFT) srd r9,r9,r11 lhz r11,PACALOWHTLBAREAS(r13) - srd r11,r11,r3 - or r9,r9,r11 -END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE) + srd r11,r11,r10 + or. r9,r9,r11 + beq 1f +_GLOBAL(slb_miss_user_load_huge) + li r11,0 + b 2f +1: #endif /* CONFIG_HUGETLB_PAGE */ - li r11,SLB_VSID_USER +_GLOBAL(slb_miss_user_load_normal) + li r11,0 -#ifdef CONFIG_HUGETLB_PAGE -BEGIN_FTR_SECTION - rldimi r11,r9,8,55 /* shift masked bit into SLB_VSID_L */ -END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE) -#endif /* CONFIG_HUGETLB_PAGE */ +2: + ld r9,PACACONTEXTID(r13) + rldimi r10,r9,USER_ESID_BITS,0 + b slb_finish_load + +8: /* invalid EA */ + li r10,0 /* BAD_VSID */ + li r11,SLB_VSID_USER /* flags don't much matter */ + b slb_finish_load + +#ifdef __DISABLED__ + +/* void slb_allocate_user(unsigned long ea); + * + * Create an SLB entry for the given EA (user or kernel). + * r3 = faulting address, r13 = PACA + * r9, r10, r11 are clobbered by this function + * No other registers are examined or changed. + * + * It is called with translation enabled in order to be able to walk the + * page tables. This is not currently used. + */ +_GLOBAL(slb_allocate_user) + /* r3 = faulting address */ + srdi r10,r3,28 /* get esid */ + + crset 4*cr7+lt /* set "user" flag for later */ + + /* check if we fit in the range covered by the pagetables*/ + srdi. r9,r3,PGTABLE_EADDR_SIZE + crnot 4*cr0+eq,4*cr0+eq + beqlr + /* now we need to get to the page tables in order to get the page + * size encoding from the PMD. In the future, we'll be able to deal + * with 1T segments too by getting the encoding from the PGD instead + */ + ld r9,PACAPGDIR(r13) + cmpldi cr0,r9,0 + beqlr + rlwinm r11,r10,8,25,28 + ldx r9,r9,r11 /* get pgd_t */ + cmpldi cr0,r9,0 + beqlr + rlwinm r11,r10,3,17,28 + ldx r9,r9,r11 /* get pmd_t */ + cmpldi cr0,r9,0 + beqlr + + /* build vsid flags */ + andi. r11,r9,SLB_VSID_LLP + ori r11,r11,SLB_VSID_USER + + /* get context to calculate proto-VSID */ ld r9,PACACONTEXTID(r13) - rldimi r3,r9,USER_ESID_BITS,0 + rldimi r10,r9,USER_ESID_BITS,0 + + /* fall through slb_finish_load */ + +#endif /* __DISABLED__ */ -9: /* r3 = protovsid, r11 = flags, r10 = esid_data, cr7 = <>KERNELBASE */ - ASM_VSID_SCRAMBLE(r3,r9) - rldimi r11,r3,SLB_VSID_SHIFT,16 /* combine VSID and flags */ +/* + * Finish loading of an SLB entry and return + * + * r3 = EA, r10 = proto-VSID, r11 = flags, clobbers r9, cr7 = <>KERNELBASE + */ +slb_finish_load: + ASM_VSID_SCRAMBLE(r10,r9) + rldimi r11,r10,SLB_VSID_SHIFT,16 /* combine VSID and flags */ + + /* r3 = EA, r11 = VSID data */ + /* + * Find a slot, round robin. Previously we tried to find a + * free slot first but that took too long. Unfortunately we + * dont have any LRU information to help us choose a slot. + */ +#ifdef CONFIG_PPC_ISERIES + /* + * On iSeries, the "bolted" stack segment can be cast out on + * shared processor switch so we need to check for a miss on + * it and restore it to the right slot. + */ + ld r9,PACAKSAVE(r13) + clrrdi r9,r9,28 + clrrdi r3,r3,28 + li r10,SLB_NUM_BOLTED-1 /* Stack goes in last bolted slot */ + cmpld r9,r3 + beq 3f +#endif /* CONFIG_PPC_ISERIES */ + + ld r10,PACASTABRR(r13) + addi r10,r10,1 + /* use a cpu feature mask if we ever change our slb size */ + cmpldi r10,SLB_NUM_ENTRIES + + blt+ 4f + li r10,SLB_NUM_BOLTED + +4: + std r10,PACASTABRR(r13) + +3: + rldimi r3,r10,0,36 /* r3= EA[0:35] | entry */ + oris r10,r3,SLB_ESID_V@h /* r3 |= SLB_ESID_V */ + + /* r3 = ESID data, r11 = VSID data */ /* * No need for an isync before or after this slbmte. The exception @@ -125,7 +210,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE) */ slbmte r11,r10 - bgelr cr7 /* we're done for kernel addresses */ + /* we're done for kernel addresses */ + crclr 4*cr0+eq /* set result to "success" */ + bgelr cr7 /* Update the slb cache */ lhz r3,PACASLBCACHEPTR(r13) /* offset = paca->slb_cache_ptr */ @@ -143,9 +230,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE) li r3,SLB_CACHE_ENTRIES+1 2: sth r3,PACASLBCACHEPTR(r13) /* paca->slb_cache_ptr = offset */ + crclr 4*cr0+eq /* set result to "success" */ blr -8: /* invalid EA */ - li r3,0 /* BAD_VSID */ - li r11,SLB_VSID_USER /* flags don't much matter */ - b 9b diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c index 1b83f002bf2..fa325dbf98f 100644 --- a/arch/powerpc/mm/stab.c +++ b/arch/powerpc/mm/stab.c @@ -26,7 +26,6 @@ struct stab_entry { unsigned long vsid_data; }; -/* Both the segment table and SLB code uses the following cache */ #define NR_STAB_CACHE_ENTRIES 8 DEFINE_PER_CPU(long, stab_cache_ptr); DEFINE_PER_CPU(long, stab_cache[NR_STAB_CACHE_ENTRIES]); @@ -186,7 +185,7 @@ void switch_stab(struct task_struct *tsk, struct mm_struct *mm) /* Never flush the first entry. */ ste += 1; for (entry = 1; - entry < (PAGE_SIZE / sizeof(struct stab_entry)); + entry < (HW_PAGE_SIZE / sizeof(struct stab_entry)); entry++, ste++) { unsigned long ea; ea = ste->esid_data & ESID_MASK; @@ -200,6 +199,10 @@ void switch_stab(struct task_struct *tsk, struct mm_struct *mm) __get_cpu_var(stab_cache_ptr) = 0; +#ifdef CONFIG_PPC_64K_PAGES + get_paca()->pgdir = mm->pgd; +#endif /* CONFIG_PPC_64K_PAGES */ + /* Now preload some entries for the new task */ if (test_tsk_thread_flag(tsk, TIF_32BIT)) unmapped_base = TASK_UNMAPPED_BASE_USER32; @@ -223,8 +226,6 @@ void switch_stab(struct task_struct *tsk, struct mm_struct *mm) asm volatile("sync" : : : "memory"); } -extern void slb_initialize(void); - /* * Allocate segment tables for secondary CPUs. These must all go in * the first (bolted) segment, so that do_stab_bolted won't get a @@ -243,18 +244,21 @@ void stabs_alloc(void) if (cpu == 0) continue; /* stab for CPU 0 is statically allocated */ - newstab = lmb_alloc_base(PAGE_SIZE, PAGE_SIZE, 1< #include #include @@ -30,7 +31,7 @@ #include #include #include -#include +#include DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); @@ -126,28 +127,46 @@ void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf) * (if we remove it we should clear the _PTE_HPTEFLAGS bits). */ void hpte_update(struct mm_struct *mm, unsigned long addr, - unsigned long pte, int wrprot) + pte_t *ptep, unsigned long pte, int huge) { struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); unsigned long vsid; + unsigned int psize = mmu_virtual_psize; int i; i = batch->index; + /* We mask the address for the base page size. Huge pages will + * have applied their own masking already + */ + addr &= PAGE_MASK; + + /* Get page size (maybe move back to caller) */ + if (huge) { +#ifdef CONFIG_HUGETLB_PAGE + psize = mmu_huge_psize; +#else + BUG(); +#endif + } + /* * This can happen when we are in the middle of a TLB batch and * we encounter memory pressure (eg copy_page_range when it tries * to allocate a new pte). If we have to reclaim memory and end * up scanning and resetting referenced bits then our batch context * will change mid stream. + * + * We also need to ensure only one page size is present in a given + * batch */ - if (i != 0 && (mm != batch->mm || batch->large != pte_huge(pte))) { + if (i != 0 && (mm != batch->mm || batch->psize != psize)) { flush_tlb_pending(); i = 0; } if (i == 0) { batch->mm = mm; - batch->large = pte_huge(pte); + batch->psize = psize; } if (addr < KERNELBASE) { vsid = get_vsid(mm->context.id, addr); @@ -155,7 +174,7 @@ void hpte_update(struct mm_struct *mm, unsigned long addr, } else vsid = get_kernel_vsid(addr); batch->vaddr[i] = (vsid << 28 ) | (addr & 0x0fffffff); - batch->pte[i] = __pte(pte); + batch->pte[i] = __real_pte(__pte(pte), ptep); batch->index = ++i; if (i >= PPC64_TLB_BATCH_NR) flush_tlb_pending(); @@ -177,7 +196,8 @@ void __flush_tlb_pending(struct ppc64_tlb_batch *batch) local = 1; if (i == 1) - flush_hash_page(batch->vaddr[0], batch->pte[0], local); + flush_hash_page(batch->vaddr[0], batch->pte[0], + batch->psize, local); else flush_hash_range(i, local); batch->index = 0; diff --git a/arch/powerpc/platforms/iseries/htab.c b/arch/powerpc/platforms/iseries/htab.c index b3c6c3374ca..30bdcf3925d 100644 --- a/arch/powerpc/platforms/iseries/htab.c +++ b/arch/powerpc/platforms/iseries/htab.c @@ -39,15 +39,16 @@ static inline void iSeries_hunlock(unsigned long slot) spin_unlock(&iSeries_hlocks[(slot >> 4) & 0x3f]); } -static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, - unsigned long prpn, unsigned long vflags, - unsigned long rflags) +long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, + unsigned long pa, unsigned long rflags, + unsigned long vflags, int psize) { - unsigned long arpn; long slot; hpte_t lhpte; int secondary = 0; + BUG_ON(psize != MMU_PAGE_4K); + /* * The hypervisor tries both primary and secondary. * If we are being called to insert in the secondary, @@ -59,8 +60,19 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, iSeries_hlock(hpte_group); - slot = HvCallHpt_findValid(&lhpte, va >> PAGE_SHIFT); - BUG_ON(lhpte.v & HPTE_V_VALID); + slot = HvCallHpt_findValid(&lhpte, va >> HW_PAGE_SHIFT); + if (unlikely(lhpte.v & HPTE_V_VALID)) { + if (vflags & HPTE_V_BOLTED) { + HvCallHpt_setSwBits(slot, 0x10, 0); + HvCallHpt_setPp(slot, PP_RWXX); + iSeries_hunlock(hpte_group); + if (slot < 0) + return 0x8 | (slot & 7); + else + return slot & 7; + } + BUG(); + } if (slot == -1) { /* No available entry found in either group */ iSeries_hunlock(hpte_group); @@ -73,10 +85,9 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, slot &= 0x7fffffffffffffff; } - arpn = phys_to_abs(prpn << PAGE_SHIFT) >> PAGE_SHIFT; - lhpte.v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID; - lhpte.r = (arpn << HPTE_R_RPN_SHIFT) | rflags; + lhpte.v = hpte_encode_v(va, MMU_PAGE_4K) | vflags | HPTE_V_VALID; + lhpte.r = hpte_encode_r(phys_to_abs(pa), MMU_PAGE_4K) | rflags; /* Now fill in the actual HPTE */ HvCallHpt_addValidate(slot, secondary, &lhpte); @@ -86,25 +97,6 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, return (secondary << 3) | (slot & 7); } -long iSeries_hpte_bolt_or_insert(unsigned long hpte_group, - unsigned long va, unsigned long prpn, unsigned long vflags, - unsigned long rflags) -{ - long slot; - hpte_t lhpte; - - slot = HvCallHpt_findValid(&lhpte, va >> PAGE_SHIFT); - - if (lhpte.v & HPTE_V_VALID) { - /* Bolt the existing HPTE */ - HvCallHpt_setSwBits(slot, 0x10, 0); - HvCallHpt_setPp(slot, PP_RWXX); - return 0; - } - - return iSeries_hpte_insert(hpte_group, va, prpn, vflags, rflags); -} - static unsigned long iSeries_hpte_getword0(unsigned long slot) { hpte_t hpte; @@ -150,15 +142,17 @@ static long iSeries_hpte_remove(unsigned long hpte_group) * bits 61..63 : PP2,PP1,PP0 */ static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp, - unsigned long va, int large, int local) + unsigned long va, int psize, int local) { hpte_t hpte; - unsigned long avpn = va >> 23; + unsigned long want_v; iSeries_hlock(slot); HvCallHpt_get(&hpte, slot); - if ((HPTE_V_AVPN_VAL(hpte.v) == avpn) && (hpte.v & HPTE_V_VALID)) { + want_v = hpte_encode_v(va, MMU_PAGE_4K); + + if (HPTE_V_COMPARE(hpte.v, want_v) && (hpte.v & HPTE_V_VALID)) { /* * Hypervisor expects bits as NPPP, which is * different from how they are mapped in our PP. @@ -210,14 +204,17 @@ static long iSeries_hpte_find(unsigned long vpn) * * No need to lock here because we should be the only user. */ -static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea) +static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, + int psize) { unsigned long vsid,va,vpn; long slot; + BUG_ON(psize != MMU_PAGE_4K); + vsid = get_kernel_vsid(ea); va = (vsid << 28) | (ea & 0x0fffffff); - vpn = va >> PAGE_SHIFT; + vpn = va >> HW_PAGE_SHIFT; slot = iSeries_hpte_find(vpn); if (slot == -1) panic("updateboltedpp: Could not find page to bolt\n"); @@ -225,7 +222,7 @@ static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea) } static void iSeries_hpte_invalidate(unsigned long slot, unsigned long va, - int large, int local) + int psize, int local) { unsigned long hpte_v; unsigned long avpn = va >> 23; diff --git a/arch/powerpc/platforms/iseries/hvlog.c b/arch/powerpc/platforms/iseries/hvlog.c index 62ec7347968..f476d71194f 100644 --- a/arch/powerpc/platforms/iseries/hvlog.c +++ b/arch/powerpc/platforms/iseries/hvlog.c @@ -22,7 +22,7 @@ void HvCall_writeLogBuffer(const void *buffer, u64 len) while (len) { hv_buf.addr = cur; - left_this_page = ((cur & PAGE_MASK) + PAGE_SIZE) - cur; + left_this_page = ((cur & HW_PAGE_MASK) + HW_PAGE_SIZE) - cur; if (left_this_page > len) left_this_page = len; hv_buf.len = left_this_page; @@ -30,6 +30,6 @@ void HvCall_writeLogBuffer(const void *buffer, u64 len) HvCall2(HvCallBaseWriteLogBuffer, virt_to_abs(&hv_buf), left_this_page); - cur = (cur & PAGE_MASK) + PAGE_SIZE; + cur = (cur & HW_PAGE_MASK) + HW_PAGE_SIZE; } } diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index 1a6845b5c5a..bf081b34582 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -43,9 +43,12 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, u64 rc; union tce_entry tce; + index <<= TCE_PAGE_FACTOR; + npages <<= TCE_PAGE_FACTOR; + while (npages--) { tce.te_word = 0; - tce.te_bits.tb_rpn = virt_to_abs(uaddr) >> PAGE_SHIFT; + tce.te_bits.tb_rpn = virt_to_abs(uaddr) >> TCE_SHIFT; if (tbl->it_type == TCE_VB) { /* Virtual Bus */ @@ -66,7 +69,7 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", rc); index++; - uaddr += PAGE_SIZE; + uaddr += TCE_PAGE_SIZE; } } @@ -74,6 +77,9 @@ static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages) { u64 rc; + npages <<= TCE_PAGE_FACTOR; + index <<= TCE_PAGE_FACTOR; + while (npages--) { rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, 0); if (rc) @@ -83,27 +89,6 @@ static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages) } } -#ifdef CONFIG_PCI -/* - * This function compares the known tables to find an iommu_table - * that has already been built for hardware TCEs. - */ -static struct iommu_table *iommu_table_find(struct iommu_table * tbl) -{ - struct pci_dn *pdn; - - list_for_each_entry(pdn, &iSeries_Global_Device_List, Device_List) { - struct iommu_table *it = pdn->iommu_table; - if ((it != NULL) && - (it->it_type == TCE_PCI) && - (it->it_offset == tbl->it_offset) && - (it->it_index == tbl->it_index) && - (it->it_size == tbl->it_size)) - return it; - } - return NULL; -} - /* * Call Hv with the architected data structure to get TCE table info. * info. Put the returned data into the Linux representation of the @@ -113,8 +98,10 @@ static struct iommu_table *iommu_table_find(struct iommu_table * tbl) * 2. TCE table per Bus. * 3. TCE Table per IOA. */ -static void iommu_table_getparms(struct pci_dn *pdn, - struct iommu_table* tbl) +void iommu_table_getparms_iSeries(unsigned long busno, + unsigned char slotno, + unsigned char virtbus, + struct iommu_table* tbl) { struct iommu_table_cb *parms; @@ -124,9 +111,9 @@ static void iommu_table_getparms(struct pci_dn *pdn, memset(parms, 0, sizeof(*parms)); - parms->itc_busno = pdn->busno; - parms->itc_slotno = pdn->LogicalSlot; - parms->itc_virtbus = 0; + parms->itc_busno = busno; + parms->itc_slotno = slotno; + parms->itc_virtbus = virtbus; HvCallXm_getTceTableParms(iseries_hv_addr(parms)); @@ -134,17 +121,40 @@ static void iommu_table_getparms(struct pci_dn *pdn, panic("PCI_DMA: parms->size is zero, parms is 0x%p", parms); /* itc_size is in pages worth of table, it_size is in # of entries */ - tbl->it_size = (parms->itc_size * PAGE_SIZE) / sizeof(union tce_entry); + tbl->it_size = ((parms->itc_size * TCE_PAGE_SIZE) / + sizeof(union tce_entry)) >> TCE_PAGE_FACTOR; tbl->it_busno = parms->itc_busno; - tbl->it_offset = parms->itc_offset; + tbl->it_offset = parms->itc_offset >> TCE_PAGE_FACTOR; tbl->it_index = parms->itc_index; tbl->it_blocksize = 1; - tbl->it_type = TCE_PCI; + tbl->it_type = virtbus ? TCE_VB : TCE_PCI; kfree(parms); } +#ifdef CONFIG_PCI +/* + * This function compares the known tables to find an iommu_table + * that has already been built for hardware TCEs. + */ +static struct iommu_table *iommu_table_find(struct iommu_table * tbl) +{ + struct pci_dn *pdn; + + list_for_each_entry(pdn, &iSeries_Global_Device_List, Device_List) { + struct iommu_table *it = pdn->iommu_table; + if ((it != NULL) && + (it->it_type == TCE_PCI) && + (it->it_offset == tbl->it_offset) && + (it->it_index == tbl->it_index) && + (it->it_size == tbl->it_size)) + return it; + } + return NULL; +} + + void iommu_devnode_init_iSeries(struct device_node *dn) { struct iommu_table *tbl; @@ -152,7 +162,7 @@ void iommu_devnode_init_iSeries(struct device_node *dn) tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); - iommu_table_getparms(pdn, tbl); + iommu_table_getparms_iSeries(pdn->busno, pdn->LogicalSlot, 0, tbl); /* Look for existing tce table */ pdn->iommu_table = iommu_table_find(tbl); diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index fda712b4216..c5207064977 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -320,11 +320,11 @@ static void __init iSeries_init_early(void) */ if (naca.xRamDisk) { initrd_start = (unsigned long)__va(naca.xRamDisk); - initrd_end = initrd_start + naca.xRamDiskSize * PAGE_SIZE; + initrd_end = initrd_start + naca.xRamDiskSize * HW_PAGE_SIZE; initrd_below_start_ok = 1; // ramdisk in kernel space ROOT_DEV = Root_RAM0; - if (((rd_size * 1024) / PAGE_SIZE) < naca.xRamDiskSize) - rd_size = (naca.xRamDiskSize * PAGE_SIZE) / 1024; + if (((rd_size * 1024) / HW_PAGE_SIZE) < naca.xRamDiskSize) + rd_size = (naca.xRamDiskSize * HW_PAGE_SIZE) / 1024; } else #endif /* CONFIG_BLK_DEV_INITRD */ { @@ -470,13 +470,14 @@ static void __init build_iSeries_Memory_Map(void) */ hptFirstChunk = (u32)addr_to_chunk(HvCallHpt_getHptAddress()); hptSizePages = (u32)HvCallHpt_getHptPages(); - hptSizeChunks = hptSizePages >> (MSCHUNKS_CHUNK_SHIFT - PAGE_SHIFT); + hptSizeChunks = hptSizePages >> + (MSCHUNKS_CHUNK_SHIFT - HW_PAGE_SHIFT); hptLastChunk = hptFirstChunk + hptSizeChunks - 1; printk("HPT absolute addr = %016lx, size = %dK\n", chunk_to_addr(hptFirstChunk), hptSizeChunks * 256); - ppc64_pft_size = __ilog2(hptSizePages * PAGE_SIZE); + ppc64_pft_size = __ilog2(hptSizePages * HW_PAGE_SIZE); /* * The actual hashed page table is in the hypervisor, @@ -629,7 +630,7 @@ static void __init iSeries_fixup_klimit(void) */ if (naca.xRamDisk) klimit = KERNELBASE + (u64)naca.xRamDisk + - (naca.xRamDiskSize * PAGE_SIZE); + (naca.xRamDiskSize * HW_PAGE_SIZE); else { /* * No ram disk was included - check and see if there diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c index c27a66876c2..384360ee06e 100644 --- a/arch/powerpc/platforms/iseries/vio.c +++ b/arch/powerpc/platforms/iseries/vio.c @@ -30,41 +30,14 @@ static struct iommu_table vio_iommu_table; static void __init iommu_vio_init(void) { - struct iommu_table *t; - struct iommu_table_cb cb; - unsigned long cbp; - unsigned long itc_entries; + iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table); + veth_iommu_table.it_size /= 2; + vio_iommu_table = veth_iommu_table; + vio_iommu_table.it_offset += veth_iommu_table.it_size; - cb.itc_busno = 255; /* Bus 255 is the virtual bus */ - cb.itc_virtbus = 0xff; /* Ask for virtual bus */ - - cbp = virt_to_abs(&cb); - HvCallXm_getTceTableParms(cbp); - - itc_entries = cb.itc_size * PAGE_SIZE / sizeof(union tce_entry); - veth_iommu_table.it_size = itc_entries / 2; - veth_iommu_table.it_busno = cb.itc_busno; - veth_iommu_table.it_offset = cb.itc_offset; - veth_iommu_table.it_index = cb.itc_index; - veth_iommu_table.it_type = TCE_VB; - veth_iommu_table.it_blocksize = 1; - - t = iommu_init_table(&veth_iommu_table); - - if (!t) + if (!iommu_init_table(&veth_iommu_table)) printk("Virtual Bus VETH TCE table failed.\n"); - - vio_iommu_table.it_size = itc_entries - veth_iommu_table.it_size; - vio_iommu_table.it_busno = cb.itc_busno; - vio_iommu_table.it_offset = cb.itc_offset + - veth_iommu_table.it_size; - vio_iommu_table.it_index = cb.itc_index; - vio_iommu_table.it_type = TCE_VB; - vio_iommu_table.it_blocksize = 1; - - t = iommu_init_table(&vio_iommu_table); - - if (!t) + if (!iommu_init_table(&vio_iommu_table)) printk("Virtual Bus VIO TCE table failed.\n"); } diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c index fe97bfbf746..84267269559 100644 --- a/arch/powerpc/platforms/iseries/viopath.c +++ b/arch/powerpc/platforms/iseries/viopath.c @@ -68,7 +68,8 @@ static DEFINE_SPINLOCK(statuslock); * For each kind of event we allocate a buffer that is * guaranteed not to cross a page boundary */ -static unsigned char event_buffer[VIO_MAX_SUBTYPES * 256] __page_aligned; +static unsigned char event_buffer[VIO_MAX_SUBTYPES * 256] + __attribute__((__aligned__(4096))); static atomic_t event_buffer_available[VIO_MAX_SUBTYPES]; static int event_buffer_initialised; @@ -116,12 +117,12 @@ static int proc_viopath_show(struct seq_file *m, void *v) HvLpEvent_Rc hvrc; DECLARE_MUTEX_LOCKED(Semaphore); - buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + buf = kmalloc(HW_PAGE_SIZE, GFP_KERNEL); if (!buf) return 0; - memset(buf, 0, PAGE_SIZE); + memset(buf, 0, HW_PAGE_SIZE); - handle = dma_map_single(iSeries_vio_dev, buf, PAGE_SIZE, + handle = dma_map_single(iSeries_vio_dev, buf, HW_PAGE_SIZE, DMA_FROM_DEVICE); hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, @@ -131,7 +132,7 @@ static int proc_viopath_show(struct seq_file *m, void *v) viopath_sourceinst(viopath_hostLp), viopath_targetinst(viopath_hostLp), (u64)(unsigned long)&Semaphore, VIOVERSION << 16, - ((u64)handle) << 32, PAGE_SIZE, 0, 0); + ((u64)handle) << 32, HW_PAGE_SIZE, 0, 0); if (hvrc != HvLpEvent_Rc_Good) printk(VIOPATH_KERN_WARN "hv error on op %d\n", (int)hvrc); @@ -140,7 +141,7 @@ static int proc_viopath_show(struct seq_file *m, void *v) vlanMap = HvLpConfig_getVirtualLanIndexMap(); - buf[PAGE_SIZE-1] = '\0'; + buf[HW_PAGE_SIZE-1] = '\0'; seq_printf(m, "%s", buf); seq_printf(m, "AVAILABLE_VETH=%x\n", vlanMap); seq_printf(m, "SRLNBR=%c%c%c%c%c%c%c\n", @@ -152,7 +153,8 @@ static int proc_viopath_show(struct seq_file *m, void *v) e2a(xItExtVpdPanel.systemSerial[4]), e2a(xItExtVpdPanel.systemSerial[5])); - dma_unmap_single(iSeries_vio_dev, handle, PAGE_SIZE, DMA_FROM_DEVICE); + dma_unmap_single(iSeries_vio_dev, handle, HW_PAGE_SIZE, + DMA_FROM_DEVICE); kfree(buf); return 0; diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index e384a5a9179..ab0c6dd6ec9 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define DEBUG +#undef DEBUG_LOW #include #include @@ -41,10 +41,10 @@ #include "plpar_wrappers.h" -#ifdef DEBUG -#define DBG(fmt...) udbg_printf(fmt) +#ifdef DEBUG_LOW +#define DBG_LOW(fmt...) do { udbg_printf(fmt); } while(0) #else -#define DBG(fmt...) +#define DBG_LOW(fmt...) do { } while(0) #endif /* in pSeries_hvCall.S */ @@ -276,8 +276,9 @@ void vpa_init(int cpu) } long pSeries_lpar_hpte_insert(unsigned long hpte_group, - unsigned long va, unsigned long prpn, - unsigned long vflags, unsigned long rflags) + unsigned long va, unsigned long pa, + unsigned long rflags, unsigned long vflags, + int psize) { unsigned long lpar_rc; unsigned long flags; @@ -285,11 +286,28 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group, unsigned long hpte_v, hpte_r; unsigned long dummy0, dummy1; - hpte_v = ((va >> 23) << HPTE_V_AVPN_SHIFT) | vflags | HPTE_V_VALID; - if (vflags & HPTE_V_LARGE) - hpte_v &= ~(1UL << HPTE_V_AVPN_SHIFT); - - hpte_r = (prpn << HPTE_R_RPN_SHIFT) | rflags; + if (!(vflags & HPTE_V_BOLTED)) + DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, " + "rflags=%lx, vflags=%lx, psize=%d)\n", + hpte_group, va, pa, rflags, vflags, psize); + + hpte_v = hpte_encode_v(va, psize) | vflags | HPTE_V_VALID; + hpte_r = hpte_encode_r(pa, psize) | rflags; + + if (!(vflags & HPTE_V_BOLTED)) + DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r); + +#if 1 + { + int i; + for (i=0;i<8;i++) { + unsigned long w0, w1; + plpar_pte_read(0, hpte_group, &w0, &w1); + BUG_ON (HPTE_V_COMPARE(hpte_v, w0) + && (w0 & HPTE_V_VALID)); + } + } +#endif /* Now fill in the actual HPTE */ /* Set CEC cookie to 0 */ @@ -299,23 +317,30 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group, /* Exact = 0 */ flags = 0; - /* XXX why is this here? - Anton */ + /* Make pHyp happy */ if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE)) hpte_r &= ~_PAGE_COHERENT; lpar_rc = plpar_hcall(H_ENTER, flags, hpte_group, hpte_v, hpte_r, &slot, &dummy0, &dummy1); - - if (unlikely(lpar_rc == H_PTEG_Full)) + if (unlikely(lpar_rc == H_PTEG_Full)) { + if (!(vflags & HPTE_V_BOLTED)) + DBG_LOW(" full\n"); return -1; + } /* * Since we try and ioremap PHBs we don't own, the pte insert * will fail. However we must catch the failure in hash_page * or we will loop forever, so return -2 in this case. */ - if (unlikely(lpar_rc != H_Success)) + if (unlikely(lpar_rc != H_Success)) { + if (!(vflags & HPTE_V_BOLTED)) + DBG_LOW(" lpar err %d\n", lpar_rc); return -2; + } + if (!(vflags & HPTE_V_BOLTED)) + DBG_LOW(" -> slot: %d\n", slot & 7); /* Because of iSeries, we have to pass down the secondary * bucket bit here as well @@ -340,10 +365,8 @@ static long pSeries_lpar_hpte_remove(unsigned long hpte_group) /* don't remove a bolted entry */ lpar_rc = plpar_pte_remove(H_ANDCOND, hpte_group + slot_offset, (0x1UL << 4), &dummy1, &dummy2); - if (lpar_rc == H_Success) return i; - BUG_ON(lpar_rc != H_Not_Found); slot_offset++; @@ -371,20 +394,28 @@ static void pSeries_lpar_hptab_clear(void) * We can probably optimize here and assume the high bits of newpp are * already zero. For now I am paranoid. */ -static long pSeries_lpar_hpte_updatepp(unsigned long slot, unsigned long newpp, - unsigned long va, int large, int local) +static long pSeries_lpar_hpte_updatepp(unsigned long slot, + unsigned long newpp, + unsigned long va, + int psize, int local) { unsigned long lpar_rc; unsigned long flags = (newpp & 7) | H_AVPN; - unsigned long avpn = va >> 23; + unsigned long want_v; - if (large) - avpn &= ~0x1UL; + want_v = hpte_encode_v(va, psize); - lpar_rc = plpar_pte_protect(flags, slot, (avpn << 7)); + DBG_LOW(" update: avpnv=%016lx, hash=%016lx, f=%x, psize: %d ... ", + want_v & HPTE_V_AVPN, slot, flags, psize); - if (lpar_rc == H_Not_Found) + lpar_rc = plpar_pte_protect(flags, slot, want_v & HPTE_V_AVPN); + + if (lpar_rc == H_Not_Found) { + DBG_LOW("not found !\n"); return -1; + } + + DBG_LOW("ok\n"); BUG_ON(lpar_rc != H_Success); @@ -410,21 +441,22 @@ static unsigned long pSeries_lpar_hpte_getword0(unsigned long slot) return dword0; } -static long pSeries_lpar_hpte_find(unsigned long vpn) +static long pSeries_lpar_hpte_find(unsigned long va, int psize) { unsigned long hash; unsigned long i, j; long slot; - unsigned long hpte_v; + unsigned long want_v, hpte_v; - hash = hpt_hash(vpn, 0); + hash = hpt_hash(va, mmu_psize_defs[psize].shift); + want_v = hpte_encode_v(va, psize); for (j = 0; j < 2; j++) { slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; for (i = 0; i < HPTES_PER_GROUP; i++) { hpte_v = pSeries_lpar_hpte_getword0(slot); - if ((HPTE_V_AVPN_VAL(hpte_v) == (vpn >> 11)) + if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID) && (!!(hpte_v & HPTE_V_SECONDARY) == j)) { /* HPTE matches */ @@ -441,17 +473,15 @@ static long pSeries_lpar_hpte_find(unsigned long vpn) } static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp, - unsigned long ea) + unsigned long ea, + int psize) { - unsigned long lpar_rc; - unsigned long vsid, va, vpn, flags; - long slot; + unsigned long lpar_rc, slot, vsid, va, flags; vsid = get_kernel_vsid(ea); va = (vsid << 28) | (ea & 0x0fffffff); - vpn = va >> PAGE_SHIFT; - slot = pSeries_lpar_hpte_find(vpn); + slot = pSeries_lpar_hpte_find(va, psize); BUG_ON(slot == -1); flags = newpp & 7; @@ -461,18 +491,18 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp, } static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, - int large, int local) + int psize, int local) { - unsigned long avpn = va >> 23; + unsigned long want_v; unsigned long lpar_rc; unsigned long dummy1, dummy2; - if (large) - avpn &= ~0x1UL; - - lpar_rc = plpar_pte_remove(H_AVPN, slot, (avpn << 7), &dummy1, - &dummy2); + DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d", + slot, va, psize, local); + want_v = hpte_encode_v(va, psize); + lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v & HPTE_V_AVPN, + &dummy1, &dummy2); if (lpar_rc == H_Not_Found) return; @@ -494,7 +524,8 @@ void pSeries_lpar_flush_hash_range(unsigned long number, int local) spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); for (i = 0; i < number; i++) - flush_hash_page(batch->vaddr[i], batch->pte[i], local); + flush_hash_page(batch->vaddr[i], batch->pte[i], + batch->psize, local); if (lock_tlbie) spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig index b987164fca4..2130cc31595 100644 --- a/arch/ppc64/Kconfig +++ b/arch/ppc64/Kconfig @@ -47,6 +47,10 @@ config ARCH_MAY_HAVE_PC_FDC bool default y +config PPC_STD_MMU + bool + default y + # We optimistically allocate largepages from the VM, so make the limit # large enough (16MB). This badly named config option is actually # max order + 1 @@ -294,6 +298,15 @@ config NODES_SPAN_OTHER_NODES def_bool y depends on NEED_MULTIPLE_NODES +config PPC_64K_PAGES + bool "64k page size" + help + This option changes the kernel logical page size to 64k. On machines + without processor support for 64k pages, the kernel will simulate + them by loading each individual 4k page on demand transparently, + while on hardware with such support, it will be used to map + normal application pages. + config SCHED_SMT bool "SMT (Hyperthreading) scheduler support" depends on SMP diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c index 504dee836d2..bce9065da6c 100644 --- a/arch/ppc64/kernel/asm-offsets.c +++ b/arch/ppc64/kernel/asm-offsets.c @@ -93,6 +93,9 @@ int main(void) DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); +#ifdef CONFIG_PPC_64K_PAGES + DEFINE(PACAPGDIR, offsetof(struct paca_struct, pgdir)); +#endif #ifdef CONFIG_HUGETLB_PAGE DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas)); DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas)); diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S index db1cf397be2..9e8050ea122 100644 --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S @@ -195,11 +195,11 @@ exception_marker: #define EX_R12 24 #define EX_R13 32 #define EX_SRR0 40 -#define EX_R3 40 /* SLB miss saves R3, but not SRR0 */ #define EX_DAR 48 -#define EX_LR 48 /* SLB miss saves LR, but not DAR */ #define EX_DSISR 56 #define EX_CCR 60 +#define EX_R3 64 +#define EX_LR 72 #define EXCEPTION_PROLOG_PSERIES(area, label) \ mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ @@ -419,17 +419,22 @@ data_access_slb_pSeries: mtspr SPRN_SPRG1,r13 RUNLATCH_ON(r13) mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ + std r3,PACA_EXSLB+EX_R3(r13) + mfspr r3,SPRN_DAR std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ + mfcr r9 +#ifdef __DISABLED__ + /* Keep that around for when we re-implement dynamic VSIDs */ + cmpdi r3,0 + bge slb_miss_user_pseries +#endif /* __DISABLED__ */ std r10,PACA_EXSLB+EX_R10(r13) std r11,PACA_EXSLB+EX_R11(r13) std r12,PACA_EXSLB+EX_R12(r13) - std r3,PACA_EXSLB+EX_R3(r13) - mfspr r9,SPRN_SPRG1 - std r9,PACA_EXSLB+EX_R13(r13) - mfcr r9 + mfspr r10,SPRN_SPRG1 + std r10,PACA_EXSLB+EX_R13(r13) mfspr r12,SPRN_SRR1 /* and SRR1 */ - mfspr r3,SPRN_DAR - b .do_slb_miss /* Rel. branch works in real mode */ + b .slb_miss_realmode /* Rel. branch works in real mode */ STD_EXCEPTION_PSERIES(0x400, instruction_access) @@ -440,17 +445,22 @@ instruction_access_slb_pSeries: mtspr SPRN_SPRG1,r13 RUNLATCH_ON(r13) mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ + std r3,PACA_EXSLB+EX_R3(r13) + mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ + mfcr r9 +#ifdef __DISABLED__ + /* Keep that around for when we re-implement dynamic VSIDs */ + cmpdi r3,0 + bge slb_miss_user_pseries +#endif /* __DISABLED__ */ std r10,PACA_EXSLB+EX_R10(r13) std r11,PACA_EXSLB+EX_R11(r13) std r12,PACA_EXSLB+EX_R12(r13) - std r3,PACA_EXSLB+EX_R3(r13) - mfspr r9,SPRN_SPRG1 - std r9,PACA_EXSLB+EX_R13(r13) - mfcr r9 + mfspr r10,SPRN_SPRG1 + std r10,PACA_EXSLB+EX_R13(r13) mfspr r12,SPRN_SRR1 /* and SRR1 */ - mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ - b .do_slb_miss /* Rel. branch works in real mode */ + b .slb_miss_realmode /* Rel. branch works in real mode */ STD_EXCEPTION_PSERIES(0x500, hardware_interrupt) STD_EXCEPTION_PSERIES(0x600, alignment) @@ -508,6 +518,38 @@ _GLOBAL(do_stab_bolted_pSeries) mfspr r12,SPRN_SPRG2 EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted) +/* + * We have some room here we use that to put + * the peries slb miss user trampoline code so it's reasonably + * away from slb_miss_user_common to avoid problems with rfid + * + * This is used for when the SLB miss handler has to go virtual, + * which doesn't happen for now anymore but will once we re-implement + * dynamic VSIDs for shared page tables + */ +#ifdef __DISABLED__ +slb_miss_user_pseries: + std r10,PACA_EXGEN+EX_R10(r13) + std r11,PACA_EXGEN+EX_R11(r13) + std r12,PACA_EXGEN+EX_R12(r13) + mfspr r10,SPRG1 + ld r11,PACA_EXSLB+EX_R9(r13) + ld r12,PACA_EXSLB+EX_R3(r13) + std r10,PACA_EXGEN+EX_R13(r13) + std r11,PACA_EXGEN+EX_R9(r13) + std r12,PACA_EXGEN+EX_R3(r13) + clrrdi r12,r13,32 + mfmsr r10 + mfspr r11,SRR0 /* save SRR0 */ + ori r12,r12,slb_miss_user_common@l /* virt addr of handler */ + ori r10,r10,MSR_IR|MSR_DR|MSR_RI + mtspr SRR0,r12 + mfspr r12,SRR1 /* and SRR1 */ + mtspr SRR1,r10 + rfid + b . /* prevent spec. execution */ +#endif /* __DISABLED__ */ + /* * Vectors for the FWNMI option. Share common code. */ @@ -559,22 +601,59 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) .globl data_access_slb_iSeries data_access_slb_iSeries: mtspr SPRN_SPRG1,r13 /* save r13 */ - EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB) + mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ std r3,PACA_EXSLB+EX_R3(r13) - ld r12,PACALPPACA+LPPACASRR1(r13) mfspr r3,SPRN_DAR - b .do_slb_miss + std r9,PACA_EXSLB+EX_R9(r13) + mfcr r9 +#ifdef __DISABLED__ + cmpdi r3,0 + bge slb_miss_user_iseries +#endif + std r10,PACA_EXSLB+EX_R10(r13) + std r11,PACA_EXSLB+EX_R11(r13) + std r12,PACA_EXSLB+EX_R12(r13) + mfspr r10,SPRN_SPRG1 + std r10,PACA_EXSLB+EX_R13(r13) + ld r12,PACALPPACA+LPPACASRR1(r13); + b .slb_miss_realmode STD_EXCEPTION_ISERIES(0x400, instruction_access, PACA_EXGEN) .globl instruction_access_slb_iSeries instruction_access_slb_iSeries: mtspr SPRN_SPRG1,r13 /* save r13 */ - EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB) + mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ std r3,PACA_EXSLB+EX_R3(r13) - ld r12,PACALPPACA+LPPACASRR1(r13) - ld r3,PACALPPACA+LPPACASRR0(r13) - b .do_slb_miss + ld r3,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ + std r9,PACA_EXSLB+EX_R9(r13) + mfcr r9 +#ifdef __DISABLED__ + cmpdi r3,0 + bge .slb_miss_user_iseries +#endif + std r10,PACA_EXSLB+EX_R10(r13) + std r11,PACA_EXSLB+EX_R11(r13) + std r12,PACA_EXSLB+EX_R12(r13) + mfspr r10,SPRN_SPRG1 + std r10,PACA_EXSLB+EX_R13(r13) + ld r12,PACALPPACA+LPPACASRR1(r13); + b .slb_miss_realmode + +#ifdef __DISABLED__ +slb_miss_user_iseries: + std r10,PACA_EXGEN+EX_R10(r13) + std r11,PACA_EXGEN+EX_R11(r13) + std r12,PACA_EXGEN+EX_R12(r13) + mfspr r10,SPRG1 + ld r11,PACA_EXSLB+EX_R9(r13) + ld r12,PACA_EXSLB+EX_R3(r13) + std r10,PACA_EXGEN+EX_R13(r13) + std r11,PACA_EXGEN+EX_R9(r13) + std r12,PACA_EXGEN+EX_R3(r13) + EXCEPTION_PROLOG_ISERIES_2 + b slb_miss_user_common +#endif MASKABLE_EXCEPTION_ISERIES(0x500, hardware_interrupt) STD_EXCEPTION_ISERIES(0x600, alignment, PACA_EXGEN) @@ -809,6 +888,126 @@ instruction_access_common: li r5,0x400 b .do_hash_page /* Try to handle as hpte fault */ +/* + * Here is the common SLB miss user that is used when going to virtual + * mode for SLB misses, that is currently not used + */ +#ifdef __DISABLED__ + .align 7 + .globl slb_miss_user_common +slb_miss_user_common: + mflr r10 + std r3,PACA_EXGEN+EX_DAR(r13) + stw r9,PACA_EXGEN+EX_CCR(r13) + std r10,PACA_EXGEN+EX_LR(r13) + std r11,PACA_EXGEN+EX_SRR0(r13) + bl .slb_allocate_user + + ld r10,PACA_EXGEN+EX_LR(r13) + ld r3,PACA_EXGEN+EX_R3(r13) + lwz r9,PACA_EXGEN+EX_CCR(r13) + ld r11,PACA_EXGEN+EX_SRR0(r13) + mtlr r10 + beq- slb_miss_fault + + andi. r10,r12,MSR_RI /* check for unrecoverable exception */ + beq- unrecov_user_slb + mfmsr r10 + +.machine push +.machine "power4" + mtcrf 0x80,r9 +.machine pop + + clrrdi r10,r10,2 /* clear RI before setting SRR0/1 */ + mtmsrd r10,1 + + mtspr SRR0,r11 + mtspr SRR1,r12 + + ld r9,PACA_EXGEN+EX_R9(r13) + ld r10,PACA_EXGEN+EX_R10(r13) + ld r11,PACA_EXGEN+EX_R11(r13) + ld r12,PACA_EXGEN+EX_R12(r13) + ld r13,PACA_EXGEN+EX_R13(r13) + rfid + b . + +slb_miss_fault: + EXCEPTION_PROLOG_COMMON(0x380, PACA_EXGEN) + ld r4,PACA_EXGEN+EX_DAR(r13) + li r5,0 + std r4,_DAR(r1) + std r5,_DSISR(r1) + b .handle_page_fault + +unrecov_user_slb: + EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN) + DISABLE_INTS + bl .save_nvgprs +1: addi r3,r1,STACK_FRAME_OVERHEAD + bl .unrecoverable_exception + b 1b + +#endif /* __DISABLED__ */ + + +/* + * r13 points to the PACA, r9 contains the saved CR, + * r12 contain the saved SRR1, SRR0 is still ready for return + * r3 has the faulting address + * r9 - r13 are saved in paca->exslb. + * r3 is saved in paca->slb_r3 + * We assume we aren't going to take any exceptions during this procedure. + */ +_GLOBAL(slb_miss_realmode) + mflr r10 + + stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ + std r10,PACA_EXSLB+EX_LR(r13) /* save LR */ + + bl .slb_allocate_realmode + + /* All done -- return from exception. */ + + ld r10,PACA_EXSLB+EX_LR(r13) + ld r3,PACA_EXSLB+EX_R3(r13) + lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ +#ifdef CONFIG_PPC_ISERIES + ld r11,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ +#endif /* CONFIG_PPC_ISERIES */ + + mtlr r10 + + andi. r10,r12,MSR_RI /* check for unrecoverable exception */ + beq- unrecov_slb + +.machine push +.machine "power4" + mtcrf 0x80,r9 + mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */ +.machine pop + +#ifdef CONFIG_PPC_ISERIES + mtspr SPRN_SRR0,r11 + mtspr SPRN_SRR1,r12 +#endif /* CONFIG_PPC_ISERIES */ + ld r9,PACA_EXSLB+EX_R9(r13) + ld r10,PACA_EXSLB+EX_R10(r13) + ld r11,PACA_EXSLB+EX_R11(r13) + ld r12,PACA_EXSLB+EX_R12(r13) + ld r13,PACA_EXSLB+EX_R13(r13) + rfid + b . /* prevent speculative execution */ + +unrecov_slb: + EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) + DISABLE_INTS + bl .save_nvgprs +1: addi r3,r1,STACK_FRAME_OVERHEAD + bl .unrecoverable_exception + b 1b + .align 7 .globl hardware_interrupt_common .globl hardware_interrupt_entry @@ -1138,62 +1337,6 @@ _GLOBAL(do_stab_bolted) rfid b . /* prevent speculative execution */ -/* - * r13 points to the PACA, r9 contains the saved CR, - * r11 and r12 contain the saved SRR0 and SRR1. - * r3 has the faulting address - * r9 - r13 are saved in paca->exslb. - * r3 is saved in paca->slb_r3 - * We assume we aren't going to take any exceptions during this procedure. - */ -_GLOBAL(do_slb_miss) - mflr r10 - - stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ - std r10,PACA_EXSLB+EX_LR(r13) /* save LR */ - - bl .slb_allocate /* handle it */ - - /* All done -- return from exception. */ - - ld r10,PACA_EXSLB+EX_LR(r13) - ld r3,PACA_EXSLB+EX_R3(r13) - lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ -#ifdef CONFIG_PPC_ISERIES - ld r11,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ -#endif /* CONFIG_PPC_ISERIES */ - - mtlr r10 - - andi. r10,r12,MSR_RI /* check for unrecoverable exception */ - beq- unrecov_slb - -.machine push -.machine "power4" - mtcrf 0x80,r9 - mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */ -.machine pop - -#ifdef CONFIG_PPC_ISERIES - mtspr SPRN_SRR0,r11 - mtspr SPRN_SRR1,r12 -#endif /* CONFIG_PPC_ISERIES */ - ld r9,PACA_EXSLB+EX_R9(r13) - ld r10,PACA_EXSLB+EX_R10(r13) - ld r11,PACA_EXSLB+EX_R11(r13) - ld r12,PACA_EXSLB+EX_R12(r13) - ld r13,PACA_EXSLB+EX_R13(r13) - rfid - b . /* prevent speculative execution */ - -unrecov_slb: - EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) - DISABLE_INTS - bl .save_nvgprs -1: addi r3,r1,STACK_FRAME_OVERHEAD - bl .unrecoverable_exception - b 1b - /* * Space for CPU0's segment table. * @@ -1569,7 +1712,10 @@ _GLOBAL(__secondary_start) #endif /* Initialize the first segment table (or SLB) entry */ ld r3,PACASTABVIRT(r13) /* get addr of segment table */ +BEGIN_FTR_SECTION bl .stab_initialize +END_FTR_SECTION_IFCLR(CPU_FTR_SLB) + bl .slb_initialize /* Initialize the kernel stack. Just a repeat for iSeries. */ LOADADDR(r3,current_set) diff --git a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c index 5e27e5a6a35..3133c72b28e 100644 --- a/arch/ppc64/kernel/pacaData.c +++ b/arch/ppc64/kernel/pacaData.c @@ -23,7 +23,7 @@ static union { struct systemcfg data; u8 page[PAGE_SIZE]; -} systemcfg_store __page_aligned; +} systemcfg_store __attribute__((__section__(".data.page.aligned"))); struct systemcfg *systemcfg = &systemcfg_store.data; EXPORT_SYMBOL(systemcfg); diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c index 97bfceb5353..dece31e58bc 100644 --- a/arch/ppc64/kernel/prom.c +++ b/arch/ppc64/kernel/prom.c @@ -635,10 +635,10 @@ static inline char *find_flat_dt_string(u32 offset) * used to extract the memory informations at boot before we can * unflatten the tree */ -static int __init scan_flat_dt(int (*it)(unsigned long node, - const char *uname, int depth, - void *data), - void *data) +int __init of_scan_flat_dt(int (*it)(unsigned long node, + const char *uname, int depth, + void *data), + void *data) { unsigned long p = ((unsigned long)initial_boot_params) + initial_boot_params->off_dt_struct; @@ -695,8 +695,8 @@ static int __init scan_flat_dt(int (*it)(unsigned long node, * This function can be used within scan_flattened_dt callback to get * access to properties */ -static void* __init get_flat_dt_prop(unsigned long node, const char *name, - unsigned long *size) +void* __init of_get_flat_dt_prop(unsigned long node, const char *name, + unsigned long *size) { unsigned long p = node; @@ -996,7 +996,7 @@ void __init unflatten_device_tree(void) static int __init early_init_dt_scan_cpus(unsigned long node, const char *uname, int depth, void *data) { - char *type = get_flat_dt_prop(node, "device_type", NULL); + char *type = of_get_flat_dt_prop(node, "device_type", NULL); u32 *prop; unsigned long size; @@ -1004,17 +1004,6 @@ static int __init early_init_dt_scan_cpus(unsigned long node, if (type == NULL || strcmp(type, "cpu") != 0) return 0; - /* On LPAR, look for the first ibm,pft-size property for the hash table size - */ - if (systemcfg->platform == PLATFORM_PSERIES_LPAR && ppc64_pft_size == 0) { - u32 *pft_size; - pft_size = (u32 *)get_flat_dt_prop(node, "ibm,pft-size", NULL); - if (pft_size != NULL) { - /* pft_size[0] is the NUMA CEC cookie */ - ppc64_pft_size = pft_size[1]; - } - } - if (initial_boot_params && initial_boot_params->version >= 2) { /* version 2 of the kexec param format adds the phys cpuid * of booted proc. @@ -1023,8 +1012,9 @@ static int __init early_init_dt_scan_cpus(unsigned long node, boot_cpuid = 0; } else { /* Check if it's the boot-cpu, set it's hw index in paca now */ - if (get_flat_dt_prop(node, "linux,boot-cpu", NULL) != NULL) { - u32 *prop = get_flat_dt_prop(node, "reg", NULL); + if (of_get_flat_dt_prop(node, "linux,boot-cpu", NULL) + != NULL) { + u32 *prop = of_get_flat_dt_prop(node, "reg", NULL); set_hard_smp_processor_id(0, prop == NULL ? 0 : *prop); boot_cpuid_phys = get_hard_smp_processor_id(0); } @@ -1032,14 +1022,14 @@ static int __init early_init_dt_scan_cpus(unsigned long node, #ifdef CONFIG_ALTIVEC /* Check if we have a VMX and eventually update CPU features */ - prop = (u32 *)get_flat_dt_prop(node, "ibm,vmx", NULL); + prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", NULL); if (prop && (*prop) > 0) { cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; } /* Same goes for Apple's "altivec" property */ - prop = (u32 *)get_flat_dt_prop(node, "altivec", NULL); + prop = (u32 *)of_get_flat_dt_prop(node, "altivec", NULL); if (prop) { cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; @@ -1051,7 +1041,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node, * this by looking at the size of the ibm,ppc-interrupt-server#s * property */ - prop = (u32 *)get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", + prop = (u32 *)of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &size); cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT; if (prop && ((size / sizeof(u32)) > 1)) @@ -1072,26 +1062,26 @@ static int __init early_init_dt_scan_chosen(unsigned long node, return 0; /* get platform type */ - prop = (u32 *)get_flat_dt_prop(node, "linux,platform", NULL); + prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL); if (prop == NULL) return 0; systemcfg->platform = *prop; /* check if iommu is forced on or off */ - if (get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) + if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) iommu_is_off = 1; - if (get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL) + if (of_get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL) iommu_force_on = 1; - prop64 = (u64*)get_flat_dt_prop(node, "linux,memory-limit", NULL); + prop64 = (u64*)of_get_flat_dt_prop(node, "linux,memory-limit", NULL); if (prop64) memory_limit = *prop64; - prop64 = (u64*)get_flat_dt_prop(node, "linux,tce-alloc-start", NULL); + prop64 = (u64*)of_get_flat_dt_prop(node, "linux,tce-alloc-start",NULL); if (prop64) tce_alloc_start = *prop64; - prop64 = (u64*)get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); + prop64 = (u64*)of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); if (prop64) tce_alloc_end = *prop64; @@ -1102,9 +1092,12 @@ static int __init early_init_dt_scan_chosen(unsigned long node, { u64 *basep, *entryp; - basep = (u64*)get_flat_dt_prop(node, "linux,rtas-base", NULL); - entryp = (u64*)get_flat_dt_prop(node, "linux,rtas-entry", NULL); - prop = (u32*)get_flat_dt_prop(node, "linux,rtas-size", NULL); + basep = (u64*)of_get_flat_dt_prop(node, + "linux,rtas-base", NULL); + entryp = (u64*)of_get_flat_dt_prop(node, + "linux,rtas-entry", NULL); + prop = (u32*)of_get_flat_dt_prop(node, + "linux,rtas-size", NULL); if (basep && entryp && prop) { rtas.base = *basep; rtas.entry = *entryp; @@ -1125,11 +1118,11 @@ static int __init early_init_dt_scan_root(unsigned long node, if (depth != 0) return 0; - prop = (u32 *)get_flat_dt_prop(node, "#size-cells", NULL); + prop = (u32 *)of_get_flat_dt_prop(node, "#size-cells", NULL); dt_root_size_cells = (prop == NULL) ? 1 : *prop; DBG("dt_root_size_cells = %x\n", dt_root_size_cells); - prop = (u32 *)get_flat_dt_prop(node, "#address-cells", NULL); + prop = (u32 *)of_get_flat_dt_prop(node, "#address-cells", NULL); dt_root_addr_cells = (prop == NULL) ? 2 : *prop; DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells); @@ -1161,7 +1154,7 @@ static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp) static int __init early_init_dt_scan_memory(unsigned long node, const char *uname, int depth, void *data) { - char *type = get_flat_dt_prop(node, "device_type", NULL); + char *type = of_get_flat_dt_prop(node, "device_type", NULL); cell_t *reg, *endp; unsigned long l; @@ -1169,7 +1162,7 @@ static int __init early_init_dt_scan_memory(unsigned long node, if (type == NULL || strcmp(type, "memory") != 0) return 0; - reg = (cell_t *)get_flat_dt_prop(node, "reg", &l); + reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); if (reg == NULL) return 0; @@ -1225,19 +1218,16 @@ void __init early_init_devtree(void *params) /* Setup flat device-tree pointer */ initial_boot_params = params; - /* By default, hash size is not set */ - ppc64_pft_size = 0; - /* Retreive various informations from the /chosen node of the * device-tree, including the platform type, initrd location and * size, TCE reserve, and more ... */ - scan_flat_dt(early_init_dt_scan_chosen, NULL); + of_scan_flat_dt(early_init_dt_scan_chosen, NULL); /* Scan memory nodes and rebuild LMBs */ lmb_init(); - scan_flat_dt(early_init_dt_scan_root, NULL); - scan_flat_dt(early_init_dt_scan_memory, NULL); + of_scan_flat_dt(early_init_dt_scan_root, NULL); + of_scan_flat_dt(early_init_dt_scan_memory, NULL); lmb_enforce_memory_limit(memory_limit); lmb_analyze(); systemcfg->physicalMemorySize = lmb_phys_mem_size(); @@ -1253,26 +1243,8 @@ void __init early_init_devtree(void *params) /* Retreive hash table size from flattened tree plus other * CPU related informations (altivec support, boot CPU ID, ...) */ - scan_flat_dt(early_init_dt_scan_cpus, NULL); - - /* If hash size wasn't obtained above, we calculate it now based on - * the total RAM size - */ - if (ppc64_pft_size == 0) { - unsigned long rnd_mem_size, pteg_count; - - /* round mem_size up to next power of 2 */ - rnd_mem_size = 1UL << __ilog2(systemcfg->physicalMemorySize); - if (rnd_mem_size < systemcfg->physicalMemorySize) - rnd_mem_size <<= 1; - - /* # pages / 2 */ - pteg_count = max(rnd_mem_size >> (12 + 1), 1UL << 11); - - ppc64_pft_size = __ilog2(pteg_count << 7); - } + of_scan_flat_dt(early_init_dt_scan_cpus, NULL); - DBG("Hash pftSize: %x\n", (int)ppc64_pft_size); DBG(" <- early_init_devtree()\n"); } diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index c019501dace..79a0556a0ab 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -101,6 +101,7 @@ extern void do_cpu_ftr_fixups(unsigned long offset); #define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000020000000000) #define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0000040000000000) #define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0000080000000000) +#define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0000100000000000) #else /* ensure on 32b processors the flags are available for compiling but * don't do anything */ @@ -116,6 +117,7 @@ extern void do_cpu_ftr_fixups(unsigned long offset); #define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0) #define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0) #define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0) +#define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0) #endif #ifndef __ASSEMBLY__ @@ -339,6 +341,7 @@ enum { #ifdef __powerpc64__ CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 | CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_CELL | + CPU_FTR_CI_LARGE_PAGE | #endif 0, diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h index 9d91bdd667a..6a35e6570cc 100644 --- a/include/asm-powerpc/iommu.h +++ b/include/asm-powerpc/iommu.h @@ -74,6 +74,11 @@ extern void iommu_devnode_init_pSeries(struct device_node *dn); /* Creates table for an individual device node */ extern void iommu_devnode_init_iSeries(struct device_node *dn); +/* Get table parameters from HV */ +extern void iommu_table_getparms_iSeries(unsigned long busno, + unsigned char slotno, + unsigned char virtbus, + struct iommu_table* tbl); #endif /* CONFIG_PPC_ISERIES */ diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index 629ca964b97..fa03864d06e 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h @@ -47,20 +47,22 @@ struct machdep_calls { #ifdef CONFIG_PPC64 void (*hpte_invalidate)(unsigned long slot, unsigned long va, - int large, + int psize, int local); long (*hpte_updatepp)(unsigned long slot, unsigned long newpp, unsigned long va, - int large, + int pize, int local); void (*hpte_updateboltedpp)(unsigned long newpp, - unsigned long ea); + unsigned long ea, + int psize); long (*hpte_insert)(unsigned long hpte_group, unsigned long va, unsigned long prpn, + unsigned long rflags, unsigned long vflags, - unsigned long rflags); + int psize); long (*hpte_remove)(unsigned long hpte_group); void (*flush_hash_range)(unsigned long number, int local); diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 3a0104fa046..7587bf5f38c 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -178,6 +178,14 @@ extern struct device_node *of_get_next_child(const struct device_node *node, extern struct device_node *of_node_get(struct device_node *node); extern void of_node_put(struct device_node *node); +/* For scanning the flat device-tree at boot time */ +int __init of_scan_flat_dt(int (*it)(unsigned long node, + const char *uname, int depth, + void *data), + void *data); +void* __init of_get_flat_dt_prop(unsigned long node, const char *name, + unsigned long *size); + /* For updating the device tree at runtime */ extern void of_attach_node(struct device_node *); extern void of_detach_node(const struct device_node *); diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h index b5da0b851e0..3536a5cd7a2 100644 --- a/include/asm-powerpc/system.h +++ b/include/asm-powerpc/system.h @@ -289,7 +289,7 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new) #ifdef CONFIG_PPC64 static __inline__ unsigned long -__cmpxchg_u64(volatile long *p, unsigned long old, unsigned long new) +__cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new) { unsigned long prev; diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h index ab17db79f69..e525f49bd17 100644 --- a/include/asm-powerpc/thread_info.h +++ b/include/asm-powerpc/thread_info.h @@ -65,23 +65,27 @@ struct thread_info { /* thread information allocation */ -#ifdef CONFIG_DEBUG_STACK_USAGE -#define THREAD_INFO_GFP GFP_KERNEL | __GFP_ZERO -#else -#define THREAD_INFO_GFP GFP_KERNEL -#endif - #if THREAD_SHIFT >= PAGE_SHIFT #define THREAD_ORDER (THREAD_SHIFT - PAGE_SHIFT) +#ifdef CONFIG_DEBUG_STACK_USAGE #define alloc_thread_info(tsk) \ - ((struct thread_info *)__get_free_pages(THREAD_INFO_GFP, THREAD_ORDER)) + ((struct thread_info *)__get_free_pages(GFP_KERNEL | \ + __GFP_ZERO, THREAD_ORDER)) +#else +#define alloc_thread_info(tsk) \ + ((struct thread_info *)__get_free_pages(GFP_KERNEL, THREAD_ORDER)) +#endif #define free_thread_info(ti) free_pages((unsigned long)ti, THREAD_ORDER) #else /* THREAD_SHIFT < PAGE_SHIFT */ -#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, THREAD_INFO_GFP) +#ifdef CONFIG_DEBUG_STACK_USAGE +#define alloc_thread_info(tsk) kzalloc(THREAD_SIZE, GFP_KERNEL) +#else +#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL) +#endif #define free_thread_info(ti) kfree(ti) #endif /* THREAD_SHIFT < PAGE_SHIFT */ diff --git a/include/asm-powerpc/tlbflush.h b/include/asm-powerpc/tlbflush.h index ca3655672bb..a2998eee37b 100644 --- a/include/asm-powerpc/tlbflush.h +++ b/include/asm-powerpc/tlbflush.h @@ -31,9 +31,9 @@ struct mm_struct; struct ppc64_tlb_batch { unsigned long index; struct mm_struct *mm; - pte_t pte[PPC64_TLB_BATCH_NR]; + real_pte_t pte[PPC64_TLB_BATCH_NR]; unsigned long vaddr[PPC64_TLB_BATCH_NR]; - unsigned int large; + unsigned int psize; }; DECLARE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); @@ -48,8 +48,9 @@ static inline void flush_tlb_pending(void) put_cpu_var(ppc64_tlb_batch); } -extern void flush_hash_page(unsigned long va, pte_t pte, int local); -void flush_hash_range(unsigned long number, int local); +extern void flush_hash_page(unsigned long va, real_pte_t pte, int psize, + int local); +extern void flush_hash_range(unsigned long number, int local); #else /* CONFIG_PPC64 */ diff --git a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h index e0505acb77d..4c18a5cb69f 100644 --- a/include/asm-ppc64/mmu.h +++ b/include/asm-ppc64/mmu.h @@ -48,13 +48,21 @@ extern char initial_stab[]; /* Bits in the SLB VSID word */ #define SLB_VSID_SHIFT 12 +#define SLB_VSID_B ASM_CONST(0xc000000000000000) +#define SLB_VSID_B_256M ASM_CONST(0x0000000000000000) +#define SLB_VSID_B_1T ASM_CONST(0x4000000000000000) #define SLB_VSID_KS ASM_CONST(0x0000000000000800) #define SLB_VSID_KP ASM_CONST(0x0000000000000400) #define SLB_VSID_N ASM_CONST(0x0000000000000200) /* no-execute */ -#define SLB_VSID_L ASM_CONST(0x0000000000000100) /* largepage */ +#define SLB_VSID_L ASM_CONST(0x0000000000000100) #define SLB_VSID_C ASM_CONST(0x0000000000000080) /* class */ -#define SLB_VSID_LS ASM_CONST(0x0000000000000070) /* size of largepage */ - +#define SLB_VSID_LP ASM_CONST(0x0000000000000030) +#define SLB_VSID_LP_00 ASM_CONST(0x0000000000000000) +#define SLB_VSID_LP_01 ASM_CONST(0x0000000000000010) +#define SLB_VSID_LP_10 ASM_CONST(0x0000000000000020) +#define SLB_VSID_LP_11 ASM_CONST(0x0000000000000030) +#define SLB_VSID_LLP (SLB_VSID_L|SLB_VSID_LP) + #define SLB_VSID_KERNEL (SLB_VSID_KP) #define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS|SLB_VSID_C) @@ -69,6 +77,7 @@ extern char initial_stab[]; #define HPTE_V_AVPN_SHIFT 7 #define HPTE_V_AVPN ASM_CONST(0xffffffffffffff80) #define HPTE_V_AVPN_VAL(x) (((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT) +#define HPTE_V_COMPARE(x,y) (!(((x) ^ (y)) & HPTE_V_AVPN)) #define HPTE_V_BOLTED ASM_CONST(0x0000000000000010) #define HPTE_V_LOCK ASM_CONST(0x0000000000000008) #define HPTE_V_LARGE ASM_CONST(0x0000000000000004) @@ -81,6 +90,7 @@ extern char initial_stab[]; #define HPTE_R_RPN ASM_CONST(0x3ffffffffffff000) #define HPTE_R_FLAGS ASM_CONST(0x00000000000003ff) #define HPTE_R_PP ASM_CONST(0x0000000000000003) +#define HPTE_R_N ASM_CONST(0x0000000000000004) /* Values for PP (assumes Ks=0, Kp=1) */ /* pp0 will always be 0 for linux */ @@ -99,100 +109,120 @@ typedef struct { extern hpte_t *htab_address; extern unsigned long htab_hash_mask; -static inline unsigned long hpt_hash(unsigned long vpn, int large) +/* + * Page size definition + * + * shift : is the "PAGE_SHIFT" value for that page size + * sllp : is a bit mask with the value of SLB L || LP to be or'ed + * directly to a slbmte "vsid" value + * penc : is the HPTE encoding mask for the "LP" field: + * + */ +struct mmu_psize_def { - unsigned long vsid; - unsigned long page; - - if (large) { - vsid = vpn >> 4; - page = vpn & 0xf; - } else { - vsid = vpn >> 16; - page = vpn & 0xffff; - } + unsigned int shift; /* number of bits */ + unsigned int penc; /* HPTE encoding */ + unsigned int tlbiel; /* tlbiel supported for that page size */ + unsigned long avpnm; /* bits to mask out in AVPN in the HPTE */ + unsigned long sllp; /* SLB L||LP (exact mask to use in slbmte) */ +}; - return (vsid & 0x7fffffffffUL) ^ page; -} - -static inline void __tlbie(unsigned long va, int large) -{ - /* clear top 16 bits, non SLS segment */ - va &= ~(0xffffULL << 48); - - if (large) { - va &= HPAGE_MASK; - asm volatile("tlbie %0,1" : : "r"(va) : "memory"); - } else { - va &= PAGE_MASK; - asm volatile("tlbie %0,0" : : "r"(va) : "memory"); - } -} +#endif /* __ASSEMBLY__ */ -static inline void tlbie(unsigned long va, int large) -{ - asm volatile("ptesync": : :"memory"); - __tlbie(va, large); - asm volatile("eieio; tlbsync; ptesync": : :"memory"); -} +/* + * The kernel use the constants below to index in the page sizes array. + * The use of fixed constants for this purpose is better for performances + * of the low level hash refill handlers. + * + * A non supported page size has a "shift" field set to 0 + * + * Any new page size being implemented can get a new entry in here. Whether + * the kernel will use it or not is a different matter though. The actual page + * size used by hugetlbfs is not defined here and may be made variable + */ -static inline void __tlbiel(unsigned long va) -{ - /* clear top 16 bits, non SLS segment */ - va &= ~(0xffffULL << 48); - va &= PAGE_MASK; - - /* - * Thanks to Alan Modra we are now able to use machine specific - * assembly instructions (like tlbiel) by using the gas -many flag. - * However we have to support older toolchains so for the moment - * we hardwire it. - */ -#if 0 - asm volatile("tlbiel %0" : : "r"(va) : "memory"); -#else - asm volatile(".long 0x7c000224 | (%0 << 11)" : : "r"(va) : "memory"); -#endif -} +#define MMU_PAGE_4K 0 /* 4K */ +#define MMU_PAGE_64K 1 /* 64K */ +#define MMU_PAGE_64K_AP 2 /* 64K Admixed (in a 4K segment) */ +#define MMU_PAGE_1M 3 /* 1M */ +#define MMU_PAGE_16M 4 /* 16M */ +#define MMU_PAGE_16G 5 /* 16G */ +#define MMU_PAGE_COUNT 6 -static inline void tlbiel(unsigned long va) -{ - asm volatile("ptesync": : :"memory"); - __tlbiel(va); - asm volatile("ptesync": : :"memory"); -} +#ifndef __ASSEMBLY__ -static inline unsigned long slot2va(unsigned long hpte_v, unsigned long slot) -{ - unsigned long avpn = HPTE_V_AVPN_VAL(hpte_v); - unsigned long va; +/* + * The current system page sizes + */ +extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; +extern int mmu_linear_psize; +extern int mmu_virtual_psize; - va = avpn << 23; +#ifdef CONFIG_HUGETLB_PAGE +/* + * The page size index of the huge pages for use by hugetlbfs + */ +extern int mmu_huge_psize; - if (! (hpte_v & HPTE_V_LARGE)) { - unsigned long vpi, pteg; +#endif /* CONFIG_HUGETLB_PAGE */ - pteg = slot / HPTES_PER_GROUP; - if (hpte_v & HPTE_V_SECONDARY) - pteg = ~pteg; +/* + * This function sets the AVPN and L fields of the HPTE appropriately + * for the page size + */ +static inline unsigned long hpte_encode_v(unsigned long va, int psize) +{ + unsigned long v = + v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm); + v <<= HPTE_V_AVPN_SHIFT; + if (psize != MMU_PAGE_4K) + v |= HPTE_V_LARGE; + return v; +} - vpi = ((va >> 28) ^ pteg) & htab_hash_mask; +/* + * This function sets the ARPN, and LP fields of the HPTE appropriately + * for the page size. We assume the pa is already "clean" that is properly + * aligned for the requested page size + */ +static inline unsigned long hpte_encode_r(unsigned long pa, int psize) +{ + unsigned long r; - va |= vpi << PAGE_SHIFT; + /* A 4K page needs no special encoding */ + if (psize == MMU_PAGE_4K) + return pa & HPTE_R_RPN; + else { + unsigned int penc = mmu_psize_defs[psize].penc; + unsigned int shift = mmu_psize_defs[psize].shift; + return (pa & ~((1ul << shift) - 1)) | (penc << 12); } - - return va; + return r; } /* - * Handle a fault by adding an HPTE. If the address can't be determined - * to be valid via Linux page tables, return 1. If handled return 0 + * This hashes a virtual address for a 256Mb segment only for now */ -extern int __hash_page(unsigned long ea, unsigned long access, - unsigned long vsid, pte_t *ptep, unsigned long trap, - int local); + +static inline unsigned long hpt_hash(unsigned long va, unsigned int shift) +{ + return ((va >> 28) & 0x7fffffffffUL) ^ ((va & 0x0fffffffUL) >> shift); +} + +extern int __hash_page_4K(unsigned long ea, unsigned long access, + unsigned long vsid, pte_t *ptep, unsigned long trap, + unsigned int local); +extern int __hash_page_64K(unsigned long ea, unsigned long access, + unsigned long vsid, pte_t *ptep, unsigned long trap, + unsigned int local); +struct mm_struct; +extern int hash_huge_page(struct mm_struct *mm, unsigned long access, + unsigned long ea, unsigned long vsid, int local); extern void htab_finish_init(void); +extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend, + unsigned long pstart, unsigned long mode, + int psize); extern void hpte_init_native(void); extern void hpte_init_lpar(void); @@ -200,17 +230,21 @@ extern void hpte_init_iSeries(void); extern long pSeries_lpar_hpte_insert(unsigned long hpte_group, unsigned long va, unsigned long prpn, - unsigned long vflags, - unsigned long rflags); -extern long native_hpte_insert(unsigned long hpte_group, unsigned long va, - unsigned long prpn, - unsigned long vflags, unsigned long rflags); + unsigned long rflags, + unsigned long vflags, int psize); + +extern long native_hpte_insert(unsigned long hpte_group, + unsigned long va, unsigned long prpn, + unsigned long rflags, + unsigned long vflags, int psize); -extern long iSeries_hpte_bolt_or_insert(unsigned long hpte_group, - unsigned long va, unsigned long prpn, - unsigned long vflags, unsigned long rflags); +extern long iSeries_hpte_insert(unsigned long hpte_group, + unsigned long va, unsigned long prpn, + unsigned long rflags, + unsigned long vflags, int psize); extern void stabs_alloc(void); +extern void slb_initialize(void); #endif /* __ASSEMBLY__ */ diff --git a/include/asm-ppc64/mmu_context.h b/include/asm-ppc64/mmu_context.h index 820dd729b89..4f512e9fa6b 100644 --- a/include/asm-ppc64/mmu_context.h +++ b/include/asm-ppc64/mmu_context.h @@ -16,8 +16,16 @@ * 2 of the License, or (at your option) any later version. */ -static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) +/* + * Getting into a kernel thread, there is no valid user segment, mark + * paca->pgdir NULL so that SLB miss on user addresses will fault + */ +static inline void enter_lazy_tlb(struct mm_struct *mm, + struct task_struct *tsk) { +#ifdef CONFIG_PPC_64K_PAGES + get_paca()->pgdir = NULL; +#endif /* CONFIG_PPC_64K_PAGES */ } #define NO_CONTEXT 0 @@ -40,8 +48,13 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, cpu_set(smp_processor_id(), next->cpu_vm_mask); /* No need to flush userspace segments if the mm doesnt change */ +#ifdef CONFIG_PPC_64K_PAGES + if (prev == next && get_paca()->pgdir == next->pgd) + return; +#else if (prev == next) return; +#endif /* CONFIG_PPC_64K_PAGES */ #ifdef CONFIG_ALTIVEC if (cpu_has_feature(CPU_FTR_ALTIVEC)) diff --git a/include/asm-ppc64/paca.h b/include/asm-ppc64/paca.h index f68fe91deba..bccacd6aa93 100644 --- a/include/asm-ppc64/paca.h +++ b/include/asm-ppc64/paca.h @@ -72,10 +72,15 @@ struct paca_struct { /* * Now, starting in cacheline 2, the exception save areas */ - u64 exgen[8] __attribute__((aligned(0x80))); /* used for most interrupts/exceptions */ - u64 exmc[8]; /* used for machine checks */ - u64 exslb[8]; /* used for SLB/segment table misses - * on the linear mapping */ + /* used for most interrupts/exceptions */ + u64 exgen[10] __attribute__((aligned(0x80))); + u64 exmc[10]; /* used for machine checks */ + u64 exslb[10]; /* used for SLB/segment table misses + * on the linear mapping */ +#ifdef CONFIG_PPC_64K_PAGES + pgd_t *pgdir; +#endif /* CONFIG_PPC_64K_PAGES */ + mm_context_t context; u16 slb_cache[SLB_CACHE_ENTRIES]; u16 slb_cache_ptr; diff --git a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h index d404431f0a9..82ce187e5be 100644 --- a/include/asm-ppc64/page.h +++ b/include/asm-ppc64/page.h @@ -13,32 +13,59 @@ #include #include /* for ASM_CONST */ -/* PAGE_SHIFT determines the page size */ -#define PAGE_SHIFT 12 -#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT) -#define PAGE_MASK (~(PAGE_SIZE-1)) +/* + * We support either 4k or 64k software page size. When using 64k pages + * however, wether we are really supporting 64k pages in HW or not is + * irrelevant to those definitions. We always define HW_PAGE_SHIFT to 12 + * as use of 64k pages remains a linux kernel specific, every notion of + * page number shared with the firmware, TCEs, iommu, etc... still assumes + * a page size of 4096. + */ +#ifdef CONFIG_PPC_64K_PAGES +#define PAGE_SHIFT 16 +#else +#define PAGE_SHIFT 12 +#endif -#define SID_SHIFT 28 -#define SID_MASK 0xfffffffffUL -#define ESID_MASK 0xfffffffff0000000UL -#define GET_ESID(x) (((x) >> SID_SHIFT) & SID_MASK) +#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) -#define HPAGE_SHIFT 24 -#define HPAGE_SIZE ((1UL) << HPAGE_SHIFT) -#define HPAGE_MASK (~(HPAGE_SIZE - 1)) +/* HW_PAGE_SHIFT is always 4k pages */ +#define HW_PAGE_SHIFT 12 +#define HW_PAGE_SIZE (ASM_CONST(1) << HW_PAGE_SHIFT) +#define HW_PAGE_MASK (~(HW_PAGE_SIZE-1)) -#ifdef CONFIG_HUGETLB_PAGE +/* PAGE_FACTOR is the number of bits factor between PAGE_SHIFT and + * HW_PAGE_SHIFT, that is 4k pages + */ +#define PAGE_FACTOR (PAGE_SHIFT - HW_PAGE_SHIFT) + +/* Segment size */ +#define SID_SHIFT 28 +#define SID_MASK 0xfffffffffUL +#define ESID_MASK 0xfffffffff0000000UL +#define GET_ESID(x) (((x) >> SID_SHIFT) & SID_MASK) +/* Large pages size */ + +#ifndef __ASSEMBLY__ +extern unsigned int HPAGE_SHIFT; +#define HPAGE_SIZE ((1UL) << HPAGE_SHIFT) +#define HPAGE_MASK (~(HPAGE_SIZE - 1)) #define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) +#endif /* __ASSEMBLY__ */ + +#ifdef CONFIG_HUGETLB_PAGE + #define HTLB_AREA_SHIFT 40 #define HTLB_AREA_SIZE (1UL << HTLB_AREA_SHIFT) #define GET_HTLB_AREA(x) ((x) >> HTLB_AREA_SHIFT) -#define LOW_ESID_MASK(addr, len) (((1U << (GET_ESID(addr+len-1)+1)) \ - - (1U << GET_ESID(addr))) & 0xffff) -#define HTLB_AREA_MASK(addr, len) (((1U << (GET_HTLB_AREA(addr+len-1)+1)) \ - - (1U << GET_HTLB_AREA(addr))) & 0xffff) +#define LOW_ESID_MASK(addr, len) (((1U << (GET_ESID(addr+len-1)+1)) \ + - (1U << GET_ESID(addr))) & 0xffff) +#define HTLB_AREA_MASK(addr, len) (((1U << (GET_HTLB_AREA(addr+len-1)+1)) \ + - (1U << GET_HTLB_AREA(addr))) & 0xffff) #define ARCH_HAS_HUGEPAGE_ONLY_RANGE #define ARCH_HAS_PREPARE_HUGEPAGE_RANGE @@ -114,7 +141,25 @@ static __inline__ void clear_page(void *addr) : "ctr", "memory"); } -extern void copy_page(void *to, void *from); +extern void copy_4K_page(void *to, void *from); + +#ifdef CONFIG_PPC_64K_PAGES +static inline void copy_page(void *to, void *from) +{ + unsigned int i; + for (i=0; i < (1 << (PAGE_SHIFT - 12)); i++) { + copy_4K_page(to, from); + to += 4096; + from += 4096; + } +} +#else /* CONFIG_PPC_64K_PAGES */ +static inline void copy_page(void *to, void *from) +{ + copy_4K_page(to, from); +} +#endif /* CONFIG_PPC_64K_PAGES */ + struct page; extern void clear_user_page(void *page, unsigned long vaddr, struct page *pg); extern void copy_user_page(void *to, void *from, unsigned long vaddr, struct page *p); @@ -124,43 +169,75 @@ extern void copy_user_page(void *to, void *from, unsigned long vaddr, struct pag * These are used to make use of C type-checking. * Entries in the pte table are 64b, while entries in the pgd & pmd are 32b. */ -typedef struct { unsigned long pte; } pte_t; -typedef struct { unsigned long pmd; } pmd_t; -typedef struct { unsigned long pud; } pud_t; -typedef struct { unsigned long pgd; } pgd_t; -typedef struct { unsigned long pgprot; } pgprot_t; +/* PTE level */ +typedef struct { unsigned long pte; } pte_t; #define pte_val(x) ((x).pte) -#define pmd_val(x) ((x).pmd) -#define pud_val(x) ((x).pud) -#define pgd_val(x) ((x).pgd) -#define pgprot_val(x) ((x).pgprot) - #define __pte(x) ((pte_t) { (x) }) + +/* 64k pages additionally define a bigger "real PTE" type that gathers + * the "second half" part of the PTE for pseudo 64k pages + */ +#ifdef CONFIG_PPC_64K_PAGES +typedef struct { pte_t pte; unsigned long hidx; } real_pte_t; +#else +typedef struct { pte_t pte; } real_pte_t; +#endif + +/* PMD level */ +typedef struct { unsigned long pmd; } pmd_t; +#define pmd_val(x) ((x).pmd) #define __pmd(x) ((pmd_t) { (x) }) + +/* PUD level exusts only on 4k pages */ +#ifndef CONFIG_PPC_64K_PAGES +typedef struct { unsigned long pud; } pud_t; +#define pud_val(x) ((x).pud) #define __pud(x) ((pud_t) { (x) }) +#endif + +/* PGD level */ +typedef struct { unsigned long pgd; } pgd_t; +#define pgd_val(x) ((x).pgd) #define __pgd(x) ((pgd_t) { (x) }) + +/* Page protection bits */ +typedef struct { unsigned long pgprot; } pgprot_t; +#define pgprot_val(x) ((x).pgprot) #define __pgprot(x) ((pgprot_t) { (x) }) #else + /* * .. while these make it easier on the compiler */ -typedef unsigned long pte_t; -typedef unsigned long pmd_t; -typedef unsigned long pud_t; -typedef unsigned long pgd_t; -typedef unsigned long pgprot_t; +typedef unsigned long pte_t; #define pte_val(x) (x) +#define __pte(x) (x) + +#ifdef CONFIG_PPC_64K_PAGES +typedef struct { pte_t pte; unsigned long hidx; } real_pte_t; +#else +typedef unsigned long real_pte_t; +#endif + + +typedef unsigned long pmd_t; #define pmd_val(x) (x) +#define __pmd(x) (x) + +#ifndef CONFIG_PPC_64K_PAGES +typedef unsigned long pud_t; #define pud_val(x) (x) +#define __pud(x) (x) +#endif + +typedef unsigned long pgd_t; #define pgd_val(x) (x) #define pgprot_val(x) (x) -#define __pte(x) (x) -#define __pmd(x) (x) -#define __pud(x) (x) +typedef unsigned long pgprot_t; #define __pgd(x) (x) #define __pgprot(x) (x) diff --git a/include/asm-ppc64/pgalloc.h b/include/asm-ppc64/pgalloc.h index 26bc49c1108..98da0e4262b 100644 --- a/include/asm-ppc64/pgalloc.h +++ b/include/asm-ppc64/pgalloc.h @@ -8,10 +8,16 @@ extern kmem_cache_t *pgtable_cache[]; +#ifdef CONFIG_PPC_64K_PAGES +#define PTE_CACHE_NUM 0 +#define PMD_CACHE_NUM 0 +#define PGD_CACHE_NUM 1 +#else #define PTE_CACHE_NUM 0 #define PMD_CACHE_NUM 1 #define PUD_CACHE_NUM 1 #define PGD_CACHE_NUM 0 +#endif /* * This program is free software; you can redistribute it and/or @@ -30,6 +36,8 @@ static inline void pgd_free(pgd_t *pgd) kmem_cache_free(pgtable_cache[PGD_CACHE_NUM], pgd); } +#ifndef CONFIG_PPC_64K_PAGES + #define pgd_populate(MM, PGD, PUD) pgd_set(PGD, PUD) static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) @@ -43,7 +51,30 @@ static inline void pud_free(pud_t *pud) kmem_cache_free(pgtable_cache[PUD_CACHE_NUM], pud); } -#define pud_populate(MM, PUD, PMD) pud_set(PUD, PMD) +static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) +{ + pud_set(pud, (unsigned long)pmd); +} + +#define pmd_populate(mm, pmd, pte_page) \ + pmd_populate_kernel(mm, pmd, page_address(pte_page)) +#define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, (unsigned long)(pte)) + + +#else /* CONFIG_PPC_64K_PAGES */ + +#define pud_populate(mm, pud, pmd) pud_set(pud, (unsigned long)pmd) + +static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, + pte_t *pte) +{ + pmd_set(pmd, (unsigned long)pte); +} + +#define pmd_populate(mm, pmd, pte_page) \ + pmd_populate_kernel(mm, pmd, page_address(pte_page)) + +#endif /* CONFIG_PPC_64K_PAGES */ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) { @@ -56,17 +87,15 @@ static inline void pmd_free(pmd_t *pmd) kmem_cache_free(pgtable_cache[PMD_CACHE_NUM], pmd); } -#define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, pte) -#define pmd_populate(mm, pmd, pte_page) \ - pmd_populate_kernel(mm, pmd, page_address(pte_page)) - -static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) +static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, + unsigned long address) { return kmem_cache_alloc(pgtable_cache[PTE_CACHE_NUM], GFP_KERNEL|__GFP_REPEAT); } -static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) +static inline struct page *pte_alloc_one(struct mm_struct *mm, + unsigned long address) { return virt_to_page(pte_alloc_one_kernel(mm, address)); } @@ -103,7 +132,7 @@ static inline void pgtable_free(pgtable_free_t pgf) kmem_cache_free(pgtable_cache[cachenum], p); } -void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf); +extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf); #define __pte_free_tlb(tlb, ptepage) \ pgtable_free_tlb(tlb, pgtable_free_cache(page_address(ptepage), \ @@ -111,9 +140,11 @@ void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf); #define __pmd_free_tlb(tlb, pmd) \ pgtable_free_tlb(tlb, pgtable_free_cache(pmd, \ PMD_CACHE_NUM, PMD_TABLE_SIZE-1)) +#ifndef CONFIG_PPC_64K_PAGES #define __pud_free_tlb(tlb, pmd) \ pgtable_free_tlb(tlb, pgtable_free_cache(pud, \ PUD_CACHE_NUM, PUD_TABLE_SIZE-1)) +#endif /* CONFIG_PPC_64K_PAGES */ #define check_pgt_cache() do { } while (0) diff --git a/include/asm-ppc64/pgtable-4k.h b/include/asm-ppc64/pgtable-4k.h new file mode 100644 index 00000000000..c883a274855 --- /dev/null +++ b/include/asm-ppc64/pgtable-4k.h @@ -0,0 +1,88 @@ +/* + * Entries per page directory level. The PTE level must use a 64b record + * for each page table entry. The PMD and PGD level use a 32b record for + * each entry by assuming that each entry is page aligned. + */ +#define PTE_INDEX_SIZE 9 +#define PMD_INDEX_SIZE 7 +#define PUD_INDEX_SIZE 7 +#define PGD_INDEX_SIZE 9 + +#define PTE_TABLE_SIZE (sizeof(pte_t) << PTE_INDEX_SIZE) +#define PMD_TABLE_SIZE (sizeof(pmd_t) << PMD_INDEX_SIZE) +#define PUD_TABLE_SIZE (sizeof(pud_t) << PUD_INDEX_SIZE) +#define PGD_TABLE_SIZE (sizeof(pgd_t) << PGD_INDEX_SIZE) + +#define PTRS_PER_PTE (1 << PTE_INDEX_SIZE) +#define PTRS_PER_PMD (1 << PMD_INDEX_SIZE) +#define PTRS_PER_PUD (1 << PMD_INDEX_SIZE) +#define PTRS_PER_PGD (1 << PGD_INDEX_SIZE) + +/* PMD_SHIFT determines what a second-level page table entry can map */ +#define PMD_SHIFT (PAGE_SHIFT + PTE_INDEX_SIZE) +#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE-1)) + +/* PUD_SHIFT determines what a third-level page table entry can map */ +#define PUD_SHIFT (PMD_SHIFT + PMD_INDEX_SIZE) +#define PUD_SIZE (1UL << PUD_SHIFT) +#define PUD_MASK (~(PUD_SIZE-1)) + +/* PGDIR_SHIFT determines what a fourth-level page table entry can map */ +#define PGDIR_SHIFT (PUD_SHIFT + PUD_INDEX_SIZE) +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) + +/* PTE bits */ +#define _PAGE_SECONDARY 0x8000 /* software: HPTE is in secondary group */ +#define _PAGE_GROUP_IX 0x7000 /* software: HPTE index within group */ +#define _PAGE_F_SECOND _PAGE_SECONDARY +#define _PAGE_F_GIX _PAGE_GROUP_IX + +/* PTE flags to conserve for HPTE identification */ +#define _PAGE_HPTEFLAGS (_PAGE_BUSY | _PAGE_HASHPTE | \ + _PAGE_SECONDARY | _PAGE_GROUP_IX) + +/* PAGE_MASK gives the right answer below, but only by accident */ +/* It should be preserving the high 48 bits and then specifically */ +/* preserving _PAGE_SECONDARY | _PAGE_GROUP_IX */ +#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | \ + _PAGE_HPTEFLAGS) + +/* Bits to mask out from a PMD to get to the PTE page */ +#define PMD_MASKED_BITS 0 +/* Bits to mask out from a PUD to get to the PMD page */ +#define PUD_MASKED_BITS 0 +/* Bits to mask out from a PGD to get to the PUD page */ +#define PGD_MASKED_BITS 0 + +/* shift to put page number into pte */ +#define PTE_RPN_SHIFT (17) + +#define __real_pte(e,p) ((real_pte_t)(e)) +#define __rpte_to_pte(r) (r) +#define __rpte_to_hidx(r,index) (pte_val((r)) >> 12) + +#define pte_iterate_hashed_subpages(rpte, psize, va, index, shift) \ + do { \ + index = 0; \ + shift = mmu_psize_defs[psize].shift; \ + +#define pte_iterate_hashed_end() } while(0) + +/* + * 4-level page tables related bits + */ + +#define pgd_none(pgd) (!pgd_val(pgd)) +#define pgd_bad(pgd) (pgd_val(pgd) == 0) +#define pgd_present(pgd) (pgd_val(pgd) != 0) +#define pgd_clear(pgdp) (pgd_val(*(pgdp)) = 0) +#define pgd_page(pgd) (pgd_val(pgd) & ~PGD_MASKED_BITS) + +#define pud_offset(pgdp, addr) \ + (((pud_t *) pgd_page(*(pgdp))) + \ + (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))) + +#define pud_ERROR(e) \ + printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pud_val(e)) diff --git a/include/asm-ppc64/pgtable-64k.h b/include/asm-ppc64/pgtable-64k.h new file mode 100644 index 00000000000..c5f437c86b3 --- /dev/null +++ b/include/asm-ppc64/pgtable-64k.h @@ -0,0 +1,87 @@ +#include + + +#define PTE_INDEX_SIZE 12 +#define PMD_INDEX_SIZE 12 +#define PUD_INDEX_SIZE 0 +#define PGD_INDEX_SIZE 4 + +#define PTE_TABLE_SIZE (sizeof(real_pte_t) << PTE_INDEX_SIZE) +#define PMD_TABLE_SIZE (sizeof(pmd_t) << PMD_INDEX_SIZE) +#define PGD_TABLE_SIZE (sizeof(pgd_t) << PGD_INDEX_SIZE) + +#define PTRS_PER_PTE (1 << PTE_INDEX_SIZE) +#define PTRS_PER_PMD (1 << PMD_INDEX_SIZE) +#define PTRS_PER_PGD (1 << PGD_INDEX_SIZE) + +/* PMD_SHIFT determines what a second-level page table entry can map */ +#define PMD_SHIFT (PAGE_SHIFT + PTE_INDEX_SIZE) +#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE-1)) + +/* PGDIR_SHIFT determines what a third-level page table entry can map */ +#define PGDIR_SHIFT (PMD_SHIFT + PMD_INDEX_SIZE) +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) + +/* Additional PTE bits (don't change without checking asm in hash_low.S) */ +#define _PAGE_HPTE_SUB 0x0ffff000 /* combo only: sub pages HPTE bits */ +#define _PAGE_HPTE_SUB0 0x08000000 /* combo only: first sub page */ +#define _PAGE_COMBO 0x10000000 /* this is a combo 4k page */ +#define _PAGE_F_SECOND 0x00008000 /* full page: hidx bits */ +#define _PAGE_F_GIX 0x00007000 /* full page: hidx bits */ + +/* PTE flags to conserve for HPTE identification */ +#define _PAGE_HPTEFLAGS (_PAGE_BUSY | _PAGE_HASHPTE | _PAGE_HPTE_SUB |\ + _PAGE_COMBO) + +/* Shift to put page number into pte. + * + * That gives us a max RPN of 32 bits, which means a max of 48 bits + * of addressable physical space. + * We could get 3 more bits here by setting PTE_RPN_SHIFT to 29 but + * 32 makes PTEs more readable for debugging for now :) + */ +#define PTE_RPN_SHIFT (32) +#define PTE_RPN_MAX (1UL << (64 - PTE_RPN_SHIFT)) +#define PTE_RPN_MASK (~((1UL<> ((index)<<2)) & 0xf) : ((pte_val((r).pte) >> 12) & 0xf)) +#define __rpte_to_pte(r) ((r).pte) +#define __rpte_sub_valid(rpte, index) \ + (pte_val(rpte.pte) & (_PAGE_HPTE_SUB0 >> (index))) + + +/* Trick: we set __end to va + 64k, which happens works for + * a 16M page as well as we want only one iteration + */ +#define pte_iterate_hashed_subpages(rpte, psize, va, index, shift) \ + do { \ + unsigned long __end = va + PAGE_SIZE; \ + unsigned __split = (psize == MMU_PAGE_4K || \ + psize == MMU_PAGE_64K_AP); \ + shift = mmu_psize_defs[psize].shift; \ + for (index = 0; va < __end; index++, va += (1 << shift)) { \ + if (!__split || __rpte_sub_valid(rpte, index)) do { \ + +#define pte_iterate_hashed_end() } while(0); } } while(0) + + +#endif /* __ASSEMBLY__ */ diff --git a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h index 8c3f574046b..fde93ec36ab 100644 --- a/include/asm-ppc64/pgtable.h +++ b/include/asm-ppc64/pgtable.h @@ -15,40 +15,11 @@ #include #endif /* __ASSEMBLY__ */ -/* - * Entries per page directory level. The PTE level must use a 64b record - * for each page table entry. The PMD and PGD level use a 32b record for - * each entry by assuming that each entry is page aligned. - */ -#define PTE_INDEX_SIZE 9 -#define PMD_INDEX_SIZE 7 -#define PUD_INDEX_SIZE 7 -#define PGD_INDEX_SIZE 9 - -#define PTE_TABLE_SIZE (sizeof(pte_t) << PTE_INDEX_SIZE) -#define PMD_TABLE_SIZE (sizeof(pmd_t) << PMD_INDEX_SIZE) -#define PUD_TABLE_SIZE (sizeof(pud_t) << PUD_INDEX_SIZE) -#define PGD_TABLE_SIZE (sizeof(pgd_t) << PGD_INDEX_SIZE) - -#define PTRS_PER_PTE (1 << PTE_INDEX_SIZE) -#define PTRS_PER_PMD (1 << PMD_INDEX_SIZE) -#define PTRS_PER_PUD (1 << PMD_INDEX_SIZE) -#define PTRS_PER_PGD (1 << PGD_INDEX_SIZE) - -/* PMD_SHIFT determines what a second-level page table entry can map */ -#define PMD_SHIFT (PAGE_SHIFT + PTE_INDEX_SIZE) -#define PMD_SIZE (1UL << PMD_SHIFT) -#define PMD_MASK (~(PMD_SIZE-1)) - -/* PUD_SHIFT determines what a third-level page table entry can map */ -#define PUD_SHIFT (PMD_SHIFT + PMD_INDEX_SIZE) -#define PUD_SIZE (1UL << PUD_SHIFT) -#define PUD_MASK (~(PUD_SIZE-1)) - -/* PGDIR_SHIFT determines what a fourth-level page table entry can map */ -#define PGDIR_SHIFT (PUD_SHIFT + PUD_INDEX_SIZE) -#define PGDIR_SIZE (1UL << PGDIR_SHIFT) -#define PGDIR_MASK (~(PGDIR_SIZE-1)) +#ifdef CONFIG_PPC_64K_PAGES +#include +#else +#include +#endif #define FIRST_USER_ADDRESS 0 @@ -75,8 +46,9 @@ #define VMALLOC_END (VMALLOC_START + VMALLOC_SIZE) /* - * Bits in a linux-style PTE. These match the bits in the - * (hardware-defined) PowerPC PTE as closely as possible. + * Common bits in a linux-style PTE. These match the bits in the + * (hardware-defined) PowerPC PTE as closely as possible. Additional + * bits may be defined in pgtable-*.h */ #define _PAGE_PRESENT 0x0001 /* software: pte contains a translation */ #define _PAGE_USER 0x0002 /* matches one of the PP bits */ @@ -91,15 +63,6 @@ #define _PAGE_RW 0x0200 /* software: user write access allowed */ #define _PAGE_HASHPTE 0x0400 /* software: pte has an associated HPTE */ #define _PAGE_BUSY 0x0800 /* software: PTE & hash are busy */ -#define _PAGE_SECONDARY 0x8000 /* software: HPTE is in secondary group */ -#define _PAGE_GROUP_IX 0x7000 /* software: HPTE index within group */ -#define _PAGE_HUGE 0x10000 /* 16MB page */ -/* Bits 0x7000 identify the index within an HPT Group */ -#define _PAGE_HPTEFLAGS (_PAGE_BUSY | _PAGE_HASHPTE | _PAGE_SECONDARY | _PAGE_GROUP_IX) -/* PAGE_MASK gives the right answer below, but only by accident */ -/* It should be preserving the high 48 bits and then specifically */ -/* preserving _PAGE_SECONDARY | _PAGE_GROUP_IX */ -#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HPTEFLAGS) #define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_COHERENT) @@ -122,10 +85,10 @@ #define PAGE_AGP __pgprot(_PAGE_BASE | _PAGE_WRENABLE | _PAGE_NO_CACHE) #define HAVE_PAGE_AGP -/* - * This bit in a hardware PTE indicates that the page is *not* executable. - */ -#define HW_NO_EXEC _PAGE_EXEC +/* PTEIDX nibble */ +#define _PTEIDX_SECONDARY 0x8 +#define _PTEIDX_GROUP_IX 0x7 + /* * POWER4 and newer have per page execute protection, older chips can only @@ -164,21 +127,10 @@ extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)]; #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) #endif /* __ASSEMBLY__ */ -/* shift to put page number into pte */ -#define PTE_SHIFT (17) - #ifdef CONFIG_HUGETLB_PAGE -#ifndef __ASSEMBLY__ -int hash_huge_page(struct mm_struct *mm, unsigned long access, - unsigned long ea, unsigned long vsid, int local); -#endif /* __ASSEMBLY__ */ - #define HAVE_ARCH_UNMAPPED_AREA #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN -#else - -#define hash_huge_page(mm,a,ea,vsid,local) -1 #endif @@ -197,7 +149,7 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot) pte_t pte; - pte_val(pte) = (pfn << PTE_SHIFT) | pgprot_val(pgprot); + pte_val(pte) = (pfn << PTE_RPN_SHIFT) | pgprot_val(pgprot); return pte; } @@ -209,30 +161,25 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot) /* pte_clear moved to later in this file */ -#define pte_pfn(x) ((unsigned long)((pte_val(x) >> PTE_SHIFT))) +#define pte_pfn(x) ((unsigned long)((pte_val(x)>>PTE_RPN_SHIFT))) #define pte_page(x) pfn_to_page(pte_pfn(x)) -#define pmd_set(pmdp, ptep) ({BUG_ON((u64)ptep < KERNELBASE); pmd_val(*(pmdp)) = (unsigned long)(ptep);}) +#define pmd_set(pmdp, pmdval) (pmd_val(*(pmdp)) = (pmdval)) #define pmd_none(pmd) (!pmd_val(pmd)) #define pmd_bad(pmd) (pmd_val(pmd) == 0) #define pmd_present(pmd) (pmd_val(pmd) != 0) #define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0) -#define pmd_page_kernel(pmd) (pmd_val(pmd)) +#define pmd_page_kernel(pmd) (pmd_val(pmd) & ~PMD_MASKED_BITS) #define pmd_page(pmd) virt_to_page(pmd_page_kernel(pmd)) -#define pud_set(pudp, pmdp) (pud_val(*(pudp)) = (unsigned long)(pmdp)) +#define pud_set(pudp, pudval) (pud_val(*(pudp)) = (pudval)) #define pud_none(pud) (!pud_val(pud)) #define pud_bad(pud) ((pud_val(pud)) == 0) #define pud_present(pud) (pud_val(pud) != 0) #define pud_clear(pudp) (pud_val(*(pudp)) = 0) -#define pud_page(pud) (pud_val(pud)) +#define pud_page(pud) (pud_val(pud) & ~PUD_MASKED_BITS) #define pgd_set(pgdp, pudp) ({pgd_val(*(pgdp)) = (unsigned long)(pudp);}) -#define pgd_none(pgd) (!pgd_val(pgd)) -#define pgd_bad(pgd) (pgd_val(pgd) == 0) -#define pgd_present(pgd) (pgd_val(pgd) != 0) -#define pgd_clear(pgdp) (pgd_val(*(pgdp)) = 0) -#define pgd_page(pgd) (pgd_val(pgd)) /* * Find an entry in a page-table-directory. We combine the address region @@ -243,9 +190,6 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot) #define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address)) -#define pud_offset(pgdp, addr) \ - (((pud_t *) pgd_page(*(pgdp))) + (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))) - #define pmd_offset(pudp,addr) \ (((pmd_t *) pud_page(*(pudp))) + (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))) @@ -271,7 +215,6 @@ static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXEC;} static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY;} static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED;} static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE;} -static inline int pte_huge(pte_t pte) { return pte_val(pte) & _PAGE_HUGE;} static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; } static inline void pte_cache(pte_t pte) { pte_val(pte) &= ~_PAGE_NO_CACHE; } @@ -286,7 +229,6 @@ static inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~(_PAGE_DIRTY); return pte; } static inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; } - static inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; } static inline pte_t pte_mkexec(pte_t pte) { @@ -298,7 +240,7 @@ static inline pte_t pte_mkdirty(pte_t pte) { static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; } static inline pte_t pte_mkhuge(pte_t pte) { - pte_val(pte) |= _PAGE_HUGE; return pte; } + return pte; } /* Atomic PTE updates */ static inline unsigned long pte_update(pte_t *p, unsigned long clr) @@ -321,11 +263,13 @@ static inline unsigned long pte_update(pte_t *p, unsigned long clr) /* PTE updating functions, this function puts the PTE in the * batch, doesn't actually triggers the hash flush immediately, * you need to call flush_tlb_pending() to do that. + * Pass -1 for "normal" size (4K or 64K) */ -extern void hpte_update(struct mm_struct *mm, unsigned long addr, unsigned long pte, - int wrprot); +extern void hpte_update(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, unsigned long pte, int huge); -static inline int __ptep_test_and_clear_young(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +static inline int __ptep_test_and_clear_young(struct mm_struct *mm, + unsigned long addr, pte_t *ptep) { unsigned long old; @@ -333,7 +277,7 @@ static inline int __ptep_test_and_clear_young(struct mm_struct *mm, unsigned lon return 0; old = pte_update(ptep, _PAGE_ACCESSED); if (old & _PAGE_HASHPTE) { - hpte_update(mm, addr, old, 0); + hpte_update(mm, addr, ptep, old, 0); flush_tlb_pending(); } return (old & _PAGE_ACCESSED) != 0; @@ -351,7 +295,8 @@ static inline int __ptep_test_and_clear_young(struct mm_struct *mm, unsigned lon * moment we always flush but we need to fix hpte_update and test if the * optimisation is worth it. */ -static inline int __ptep_test_and_clear_dirty(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +static inline int __ptep_test_and_clear_dirty(struct mm_struct *mm, + unsigned long addr, pte_t *ptep) { unsigned long old; @@ -359,7 +304,7 @@ static inline int __ptep_test_and_clear_dirty(struct mm_struct *mm, unsigned lon return 0; old = pte_update(ptep, _PAGE_DIRTY); if (old & _PAGE_HASHPTE) - hpte_update(mm, addr, old, 0); + hpte_update(mm, addr, ptep, old, 0); return (old & _PAGE_DIRTY) != 0; } #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY @@ -371,7 +316,8 @@ static inline int __ptep_test_and_clear_dirty(struct mm_struct *mm, unsigned lon }) #define __HAVE_ARCH_PTEP_SET_WRPROTECT -static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, + pte_t *ptep) { unsigned long old; @@ -379,7 +325,7 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, return; old = pte_update(ptep, _PAGE_RW); if (old & _PAGE_HASHPTE) - hpte_update(mm, addr, old, 0); + hpte_update(mm, addr, ptep, old, 0); } /* @@ -408,21 +354,23 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, }) #define __HAVE_ARCH_PTEP_GET_AND_CLEAR -static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +static inline pte_t ptep_get_and_clear(struct mm_struct *mm, + unsigned long addr, pte_t *ptep) { unsigned long old = pte_update(ptep, ~0UL); if (old & _PAGE_HASHPTE) - hpte_update(mm, addr, old, 0); + hpte_update(mm, addr, ptep, old, 0); return __pte(old); } -static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t * ptep) +static inline void pte_clear(struct mm_struct *mm, unsigned long addr, + pte_t * ptep) { unsigned long old = pte_update(ptep, ~0UL); if (old & _PAGE_HASHPTE) - hpte_update(mm, addr, old, 0); + hpte_update(mm, addr, ptep, old, 0); } /* @@ -435,7 +383,14 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_clear(mm, addr, ptep); flush_tlb_pending(); } - *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); + pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); + +#ifdef CONFIG_PPC_64K_PAGES + if (mmu_virtual_psize != MMU_PAGE_64K) + pte = __pte(pte_val(pte) | _PAGE_COMBO); +#endif /* CONFIG_PPC_64K_PAGES */ + + *ptep = pte; } /* Set the dirty and/or accessed bits atomically in a linux PTE, this @@ -482,8 +437,6 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) #define pmd_ERROR(e) \ printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e)) -#define pud_ERROR(e) \ - printk("%s:%d: bad pud %08lx.\n", __FILE__, __LINE__, pud_val(e)) #define pgd_ERROR(e) \ printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) @@ -509,12 +462,12 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); /* Encode and de-code a swap entry */ #define __swp_type(entry) (((entry).val >> 1) & 0x3f) #define __swp_offset(entry) ((entry).val >> 8) -#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) }) -#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> PTE_SHIFT }) -#define __swp_entry_to_pte(x) ((pte_t) { (x).val << PTE_SHIFT }) -#define pte_to_pgoff(pte) (pte_val(pte) >> PTE_SHIFT) -#define pgoff_to_pte(off) ((pte_t) {((off) << PTE_SHIFT)|_PAGE_FILE}) -#define PTE_FILE_MAX_BITS (BITS_PER_LONG - PTE_SHIFT) +#define __swp_entry(type, offset) ((swp_entry_t){((type)<< 1)|((offset)<<8)}) +#define __pte_to_swp_entry(pte) ((swp_entry_t){pte_val(pte) >> PTE_RPN_SHIFT}) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val << PTE_RPN_SHIFT }) +#define pte_to_pgoff(pte) (pte_val(pte) >> PTE_RPN_SHIFT) +#define pgoff_to_pte(off) ((pte_t) {((off) << PTE_RPN_SHIFT)|_PAGE_FILE}) +#define PTE_FILE_MAX_BITS (BITS_PER_LONG - PTE_RPN_SHIFT) /* * kern_addr_valid is intended to indicate whether an address is a valid @@ -532,29 +485,22 @@ void pgtable_cache_init(void); /* * find_linux_pte returns the address of a linux pte for a given * effective address and directory. If not found, it returns zero. - */ -static inline pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea) + */static inline pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea) { pgd_t *pg; pud_t *pu; pmd_t *pm; pte_t *pt = NULL; - pte_t pte; pg = pgdir + pgd_index(ea); if (!pgd_none(*pg)) { pu = pud_offset(pg, ea); if (!pud_none(*pu)) { pm = pmd_offset(pu, ea); - if (pmd_present(*pm)) { + if (pmd_present(*pm)) pt = pte_offset_kernel(pm, ea); - pte = *pt; - if (!pte_present(pte)) - pt = NULL; - } } } - return pt; } diff --git a/include/asm-ppc64/prom.h b/include/asm-ppc64/prom.h index e8d0d2ab4c0..bdb47174ff0 100644 --- a/include/asm-ppc64/prom.h +++ b/include/asm-ppc64/prom.h @@ -188,6 +188,14 @@ extern struct device_node *of_get_next_child(const struct device_node *node, extern struct device_node *of_node_get(struct device_node *node); extern void of_node_put(struct device_node *node); +/* For scanning the flat device-tree at boot time */ +int __init of_scan_flat_dt(int (*it)(unsigned long node, + const char *uname, int depth, + void *data), + void *data); +void* __init of_get_flat_dt_prop(unsigned long node, const char *name, + unsigned long *size); + /* For updating the device tree at runtime */ extern void of_attach_node(struct device_node *); extern void of_detach_node(const struct device_node *); diff --git a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h index 99b8ca52f10..0cdd66c9f4b 100644 --- a/include/asm-ppc64/system.h +++ b/include/asm-ppc64/system.h @@ -248,7 +248,7 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new) } static __inline__ unsigned long -__cmpxchg_u64(volatile long *p, unsigned long old, unsigned long new) +__cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new) { unsigned long prev; diff --git a/mm/hugetlb.c b/mm/hugetlb.c index c9b43360fd3..9a565808da3 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -103,6 +103,9 @@ static int __init hugetlb_init(void) unsigned long i; struct page *page; + if (HPAGE_SHIFT == 0) + return 0; + for (i = 0; i < MAX_NUMNODES; ++i) INIT_LIST_HEAD(&hugepage_freelists[i]); -- cgit v1.2.3 From ead837174d265b24334f0721a84cbdda8ccd89a7 Mon Sep 17 00:00:00 2001 From: John Rose Date: Fri, 4 Nov 2005 15:30:56 -0600 Subject: [PATCH] dlpar enable for OF pci probe This patch contains the arch/ppc64 bits for enabling DLPAR and PCI Hotplug for the new OF-based PCI probe mechanism. This code path is currently broken. Signed-off-by: John Rose Signed-off-by: Paul Mackerras --- arch/ppc64/kernel/pci.c | 17 +++++++++-------- arch/ppc64/kernel/rtas_pci.c | 6 +----- include/asm-powerpc/ppc-pci.h | 1 + include/asm-ppc64/pci.h | 8 ++++++++ 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c index 3d2106b022a..30247ff7497 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/ppc64/kernel/pci.c @@ -295,8 +295,8 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev) } } -static struct pci_dev *of_create_pci_dev(struct device_node *node, - struct pci_bus *bus, int devfn) +struct pci_dev *of_create_pci_dev(struct device_node *node, + struct pci_bus *bus, int devfn) { struct pci_dev *dev; const char *type; @@ -354,10 +354,9 @@ static struct pci_dev *of_create_pci_dev(struct device_node *node, return dev; } +EXPORT_SYMBOL(of_create_pci_dev); -static void of_scan_pci_bridge(struct device_node *node, struct pci_dev *dev); - -static void __devinit of_scan_bus(struct device_node *node, +void __devinit of_scan_bus(struct device_node *node, struct pci_bus *bus) { struct device_node *child = NULL; @@ -381,9 +380,10 @@ static void __devinit of_scan_bus(struct device_node *node, do_bus_setup(bus); } +EXPORT_SYMBOL(of_scan_bus); -static void __devinit of_scan_pci_bridge(struct device_node *node, - struct pci_dev *dev) +void __devinit of_scan_pci_bridge(struct device_node *node, + struct pci_dev *dev) { struct pci_bus *bus; u32 *busrange, *ranges; @@ -464,9 +464,10 @@ static void __devinit of_scan_pci_bridge(struct device_node *node, else if (mode == PCI_PROBE_NORMAL) pci_scan_child_bus(bus); } +EXPORT_SYMBOL(of_scan_pci_bridge); #endif /* CONFIG_PPC_MULTIPLATFORM */ -static void __devinit scan_phb(struct pci_controller *hose) +void __devinit scan_phb(struct pci_controller *hose) { struct pci_bus *bus; struct device_node *node = hose->arch_data; diff --git a/arch/ppc64/kernel/rtas_pci.c b/arch/ppc64/kernel/rtas_pci.c index 3ad15c90fbb..3c3f19192fc 100644 --- a/arch/ppc64/kernel/rtas_pci.c +++ b/arch/ppc64/kernel/rtas_pci.c @@ -440,7 +440,6 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) struct device_node *root = of_find_node_by_path("/"); unsigned int root_size_cells = 0; struct pci_controller *phb; - struct pci_bus *bus; int primary; root_size_cells = prom_n_size_cells(root); @@ -456,10 +455,7 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) of_node_put(root); pci_devs_phb_init_dynamic(phb); - phb->last_busno = 0xff; - bus = pci_scan_bus(phb->first_busno, phb->ops, phb->arch_data); - phb->bus = bus; - phb->last_busno = bus->subordinate; + scan_phb(phb); return phb; } diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h index a88728fba8f..13aacff755f 100644 --- a/include/asm-powerpc/ppc-pci.h +++ b/include/asm-powerpc/ppc-pci.h @@ -34,6 +34,7 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre, void pci_devs_phb_init(void); void pci_devs_phb_init_dynamic(struct pci_controller *phb); +void __devinit scan_phb(struct pci_controller *hose); /* PCI address cache management routines */ void pci_addr_cache_insert_device(struct pci_dev *dev); diff --git a/include/asm-ppc64/pci.h b/include/asm-ppc64/pci.h index 342e2d75555..fafdf885a3c 100644 --- a/include/asm-ppc64/pci.h +++ b/include/asm-ppc64/pci.h @@ -162,6 +162,14 @@ pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus); extern struct pci_controller *init_phb_dynamic(struct device_node *dn); +extern struct pci_dev *of_create_pci_dev(struct device_node *node, + struct pci_bus *bus, int devfn); + +extern void of_scan_pci_bridge(struct device_node *node, + struct pci_dev *dev); + +extern void of_scan_bus(struct device_node *node, struct pci_bus *bus); + extern int pci_read_irq_line(struct pci_dev *dev); extern void pcibios_add_platform_entries(struct pci_dev *dev); -- cgit v1.2.3 From 49196f3332e661ccc221734c3103115d8cd4ee49 Mon Sep 17 00:00:00 2001 From: Vitaly Wool Date: Wed, 2 Nov 2005 16:54:46 +0000 Subject: [MTD] NAND nand_base: Fix shift for bad block check (16bit devices only) In case of an odd offset, the result was shifted by 1 instead of 8 Signed-off-by: Vitaly Wool Signed-off-by: Thomas Gleixner --- drivers/mtd/nand/nand_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 4e22317397e..c7b1ce38c63 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -433,7 +433,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE, page & this->pagemask); bad = cpu_to_le16(this->read_word(mtd)); if (this->badblockpos & 0x1) - bad >>= 1; + bad >>= 8; if ((bad & 0xFF) != 0xff) res = 1; } else { -- cgit v1.2.3 From 868801e561d5d6df40a66197e2f803a109c19e7a Mon Sep 17 00:00:00 2001 From: Todd Poynor Date: Sat, 5 Nov 2005 03:21:15 +0000 Subject: [MTD] NAND: nand_write_ecc memory and OOB corruption Nathan Roberts noticed the nand_write_ecc index into oobbuf goes out of bounds when crossing an erase block boundary, causing incorrect OOB data to be written and corrupting memory. Reset the index to zero after re-preparing oobbuf for a new erase block. Signed-off-by: Todd Poynor Signed-off-by: Thomas Gleixner --- drivers/mtd/nand/nand_base.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index c7b1ce38c63..c18ea76ed40 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -1722,6 +1722,7 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, startpage = page; oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel, autoplace, numpages); + oob = 0; /* Check, if we cross a chip boundary */ if (!page) { chipnr++; -- cgit v1.2.3 From 3e17404918b119813dfe8d7649df049a451c9e24 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 00:52:27 +0000 Subject: [MTD] maps/plat-ram: Avoid gcc 4.0 warning The assignement of a "const char *" to a "char *" variable is emitting a warning with gcc 4.0. We cannot change mtd->name to "const char *" as we have dynamic assignements of the name. So casting is the correct solution here Signed-off-by: Thomas Gleixner --- drivers/mtd/maps/plat-ram.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index acdf9f71577..e35a1c428e5 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c @@ -6,7 +6,7 @@ * * Generic platfrom device based RAM map * - * $Id: plat-ram.c,v 1.4 2005/10/10 00:51:26 bjd Exp $ + * $Id: plat-ram.c,v 1.6 2005/11/07 00:52:24 gleixner Exp $ * * 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 @@ -177,7 +177,7 @@ static int platram_probe(struct device *dev) info->map.phys = res->start; info->map.size = (res->end - res->start) + 1; - info->map.name = pdata->mapname != NULL ? pdata->mapname : pd->name; + info->map.name = pdata->mapname != NULL ? pdata->mapname : (char *)pd->name; info->map.bankwidth = pdata->bankwidth; /* register our usage of the memory area */ -- cgit v1.2.3 From 9d2ba6faa1c2e10546a4bdf0f9687436d7681b2f Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sat, 5 Nov 2005 17:54:22 +0000 Subject: [PATCH] powerpc: Fix i8259 cascade IRQ setup_irq() aborts immediately if there's no handler for the IRQ in question. So i8259_init() should set up its handlers before trying to set up the cascade on IRQ 2. With this and the patch I sent a few days ago to fix initrd on ppc32, my Pegasos now runs the arch/powerpc kernel. Signed-off-by: David Woodhouse Signed-off-by: Paul Mackerras --- arch/powerpc/sysdev/i8259.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c index 90bce6e0c19..b7ac32fdd77 100644 --- a/arch/powerpc/sysdev/i8259.c +++ b/arch/powerpc/sysdev/i8259.c @@ -207,6 +207,9 @@ void __init i8259_init(unsigned long intack_addr, int offset) spin_unlock_irqrestore(&i8259_lock, flags); + for (i = 0; i < NUM_ISA_INTERRUPTS; ++i) + irq_desc[offset + i].handler = &i8259_pic; + /* reserve our resources */ setup_irq(offset + 2, &i8259_irqaction); request_resource(&ioport_resource, &pic1_iores); @@ -216,6 +219,4 @@ void __init i8259_init(unsigned long intack_addr, int offset) if (intack_addr != 0) pci_intack = ioremap(intack_addr, 1); - for (i = 0; i < NUM_ISA_INTERRUPTS; ++i) - irq_desc[offset + i].handler = &i8259_pic; } -- cgit v1.2.3 From c6d95044a2e124b606b78896a3a2d512e90ef65c Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Sat, 5 Nov 2005 13:01:16 -0200 Subject: [PATCH] ppc32 8xx: fix m8xx_wdt accessor macro update The following patch against m8xx_wdt.c adds (required for out,in_be32/16) and fixes syntatic problems introduced with the IO accessor macro update. Signed-off-by: Marcelo Tosatti Signed-off-by: Paul Mackerras --- arch/ppc/syslib/m8xx_wdt.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/arch/ppc/syslib/m8xx_wdt.c b/arch/ppc/syslib/m8xx_wdt.c index c5ac5ce5d7d..a21632d37e5 100644 --- a/arch/ppc/syslib/m8xx_wdt.c +++ b/arch/ppc/syslib/m8xx_wdt.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -29,8 +30,8 @@ void m8xx_wdt_reset(void) { volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR; - out_be16(imap->im_siu_conf.sc_swsr, 0x556c); /* write magic1 */ - out_be16(imap->im_siu_conf.sc_swsr, 0xaa39); /* write magic2 */ + out_be16(&imap->im_siu_conf.sc_swsr, 0x556c); /* write magic1 */ + out_be16(&imap->im_siu_conf.sc_swsr, 0xaa39); /* write magic2 */ } static irqreturn_t m8xx_wdt_interrupt(int irq, void *dev, struct pt_regs *regs) @@ -39,7 +40,7 @@ static irqreturn_t m8xx_wdt_interrupt(int irq, void *dev, struct pt_regs *regs) m8xx_wdt_reset(); - out_be16(imap->im_sit.sit_piscr, in_be16(imap->im_sit.sit_piscr | PISCR_PS)); /* clear irq */ + out_be16(&imap->im_sit.sit_piscr, in_be16(&imap->im_sit.sit_piscr) | PISCR_PS); /* clear irq */ return IRQ_HANDLED; } @@ -51,7 +52,7 @@ void __init m8xx_wdt_handler_install(bd_t * binfo) u32 sypcr; u32 pitrtclk; - sypcr = in_be32(imap->im_siu_conf.sc_sypcr); + sypcr = in_be32(&imap->im_siu_conf.sc_sypcr); if (!(sypcr & 0x04)) { printk(KERN_NOTICE "m8xx_wdt: wdt disabled (SYPCR: 0x%08X)\n", @@ -87,9 +88,9 @@ void __init m8xx_wdt_handler_install(bd_t * binfo) else pitc = pitrtclk * wdt_timeout / binfo->bi_intfreq / 2; - out_be32(imap->im_sit.sit_pitc, pitc << 16); + out_be32(&imap->im_sit.sit_pitc, pitc << 16); - out_be16(imap->im_sit.sit_piscr, (mk_int_int_mask(PIT_INTERRUPT) << 8) | PISCR_PIE | PISCR_PTE); + out_be16(&imap->im_sit.sit_piscr, (mk_int_int_mask(PIT_INTERRUPT) << 8) | PISCR_PIE | PISCR_PTE); if (setup_irq(PIT_INTERRUPT, &m8xx_wdt_irqaction)) panic("m8xx_wdt: error setting up the watchdog irq!"); -- cgit v1.2.3 From 55b6332ec89a5fc65d1287708cfd9f06f7a88b90 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Sat, 5 Nov 2005 14:06:24 -0200 Subject: [PATCH] ppc32: handle access to non-present IO ports on 8xx This adds exception table entries for I/O instructions on and changes MachineCheckException() slightly to cover 8xx specifics (on 8xx the MCE can be generated while executing the IO access instruction itself, which is not the case on PowerMac's, as the comment on traps.c details). Signed-off-by: Marcelo Tosatti Signed-off-by: Paul Mackerras --- arch/ppc/kernel/misc.S | 145 +++++++++++++++++++++++++++++++++++++++++------- arch/ppc/kernel/traps.c | 8 ++- include/asm-ppc/io.h | 12 ++-- 3 files changed, 138 insertions(+), 27 deletions(-) diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index 3056ede2424..ae6af29938a 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -25,6 +25,11 @@ #include #include +#ifdef CONFIG_8xx +#define ISYNC_8xx isync +#else +#define ISYNC_8xx +#endif .text .align 5 @@ -800,8 +805,18 @@ _GLOBAL(_insb) subi r4,r4,1 blelr- 00: lbz r5,0(r3) - eieio - stbu r5,1(r4) +01: eieio +02: stbu r5,1(r4) + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text bdnz 00b blr @@ -811,8 +826,18 @@ _GLOBAL(_outsb) subi r4,r4,1 blelr- 00: lbzu r5,1(r4) - stb r5,0(r3) - eieio +01: stb r5,0(r3) +02: eieio + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text bdnz 00b blr @@ -822,8 +847,18 @@ _GLOBAL(_insw) subi r4,r4,2 blelr- 00: lhbrx r5,0,r3 - eieio - sthu r5,2(r4) +01: eieio +02: sthu r5,2(r4) + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text bdnz 00b blr @@ -833,8 +868,18 @@ _GLOBAL(_outsw) subi r4,r4,2 blelr- 00: lhzu r5,2(r4) - eieio - sthbrx r5,0,r3 +01: eieio +02: sthbrx r5,0,r3 + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text bdnz 00b blr @@ -844,8 +889,18 @@ _GLOBAL(_insl) subi r4,r4,4 blelr- 00: lwbrx r5,0,r3 - eieio - stwu r5,4(r4) +01: eieio +02: stwu r5,4(r4) + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text bdnz 00b blr @@ -855,8 +910,18 @@ _GLOBAL(_outsl) subi r4,r4,4 blelr- 00: lwzu r5,4(r4) - stwbrx r5,0,r3 - eieio +01: stwbrx r5,0,r3 +02: eieio + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text bdnz 00b blr @@ -867,8 +932,18 @@ _GLOBAL(_insw_ns) subi r4,r4,2 blelr- 00: lhz r5,0(r3) - eieio - sthu r5,2(r4) +01: eieio +02: sthu r5,2(r4) + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text bdnz 00b blr @@ -879,8 +954,18 @@ _GLOBAL(_outsw_ns) subi r4,r4,2 blelr- 00: lhzu r5,2(r4) - sth r5,0(r3) - eieio +01: sth r5,0(r3) +02: eieio + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text bdnz 00b blr @@ -891,8 +976,18 @@ _GLOBAL(_insl_ns) subi r4,r4,4 blelr- 00: lwz r5,0(r3) - eieio - stwu r5,4(r4) +01: eieio +02: stwu r5,4(r4) + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text bdnz 00b blr @@ -903,8 +998,18 @@ _GLOBAL(_outsl_ns) subi r4,r4,4 blelr- 00: lwzu r5,4(r4) - stw r5,0(r3) - eieio +01: stw r5,0(r3) +02: eieio + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text bdnz 00b blr diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 16adde6b429..42d980e82bd 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -159,7 +159,7 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) */ static inline int check_io_access(struct pt_regs *regs) { -#ifdef CONFIG_PPC_PMAC +#if defined CONFIG_PPC_PMAC || defined CONFIG_8xx unsigned long msr = regs->msr; const struct exception_table_entry *entry; unsigned int *nip = (unsigned int *)regs->nip; @@ -178,7 +178,11 @@ static inline int check_io_access(struct pt_regs *regs) nip -= 2; else if (*nip == 0x4c00012c) /* isync */ --nip; - if (*nip == 0x7c0004ac || (*nip >> 26) == 3) { + /* eieio from I/O string functions */ + else if ((*nip) == 0x7c0006ac || *(nip+1) == 0x7c0006ac) + nip += 2; + if (*nip == 0x7c0004ac || (*nip >> 26) == 3 || + (*(nip+1) >> 26) == 3) { /* sync or twi */ unsigned int rb; diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h index f7f614dfc64..2bfdf9c9845 100644 --- a/include/asm-ppc/io.h +++ b/include/asm-ppc/io.h @@ -237,9 +237,9 @@ static inline void __raw_writel(__u32 b, volatile void __iomem *addr) #define outsl(port, buf, nl) _outsl_ns((port)+___IO_BASE, (buf), (nl)) /* - * On powermacs, we will get a machine check exception if we - * try to read data from a non-existent I/O port. Because the - * machine check is an asynchronous exception, it isn't + * On powermacs and 8xx we will get a machine check exception + * if we try to read data from a non-existent I/O port. Because + * the machine check is an asynchronous exception, it isn't * well-defined which instruction SRR0 will point to when the * exception occurs. * With the sequence below (twi; isync; nop), we have found that @@ -258,7 +258,7 @@ extern __inline__ unsigned int name(unsigned int port) \ { \ unsigned int x; \ __asm__ __volatile__( \ - op " %0,0,%1\n" \ + "0:" op " %0,0,%1\n" \ "1: twi 0,%0,0\n" \ "2: isync\n" \ "3: nop\n" \ @@ -269,6 +269,7 @@ extern __inline__ unsigned int name(unsigned int port) \ ".previous\n" \ ".section __ex_table,\"a\"\n" \ " .align 2\n" \ + " .long 0b,5b\n" \ " .long 1b,5b\n" \ " .long 2b,5b\n" \ " .long 3b,5b\n" \ @@ -282,11 +283,12 @@ extern __inline__ unsigned int name(unsigned int port) \ extern __inline__ void name(unsigned int val, unsigned int port) \ { \ __asm__ __volatile__( \ - op " %0,0,%1\n" \ + "0:" op " %0,0,%1\n" \ "1: sync\n" \ "2:\n" \ ".section __ex_table,\"a\"\n" \ " .align 2\n" \ + " .long 0b,2b\n" \ " .long 1b,2b\n" \ ".previous" \ : : "r" (val), "r" (port + ___IO_BASE)); \ -- cgit v1.2.3 From 723925b7b138cecb29d76169d20149255d354a7a Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Sun, 6 Nov 2005 14:54:36 -0800 Subject: [PATCH] powerpc: Nicer printing of address at oops Add nicer printing of faulting address on unresolvable kernel faults. Makes life a little easier for those who don't know how to decode our register contents at oops time. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/mm/fault.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 841d8b6323a..93d4fbfdb72 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -389,5 +389,22 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) } /* kernel has accessed a bad area */ + + printk(KERN_ALERT "Unable to handle kernel paging request for "); + switch (regs->trap) { + case 0x300: + case 0x380: + printk("data at address 0x%08lx\n", regs->dar); + break; + case 0x400: + case 0x480: + printk("instruction fetch\n"); + break; + default: + printk("unknown fault\n"); + } + printk(KERN_ALERT "Faulting instruction address: 0x%08lx\n", + regs->nip); + die("Kernel access of bad area", regs, sig); } -- cgit v1.2.3 From dcad47fc423ac9f4934579af814fa2dad5c8081b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 7 Nov 2005 09:49:43 +1100 Subject: [PATCH] powerpc: Kill ppcdebug The ancient ppcdebug/PPCDBG mechanism is now only used in two places. First, in the hash setup code, one of the bits allows the size of the hash table to be reduced by a factor of 8 - which would be better accomplished with a command line option for that purpose. The other was a bunch of bus walking related messages in the iSeries code, which would seem to be insufficient reason to keep the mechanism. This patch removes the last traces of this mechanism. Built and booted on iSeries and pSeries POWER5 LPAR (ARCH=powerpc). Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/setup_64.c | 9 +-- arch/powerpc/kernel/signal_32.c | 1 - arch/powerpc/kernel/signal_64.c | 1 - arch/powerpc/mm/hash_utils_64.c | 7 --- arch/powerpc/mm/init_64.c | 1 - arch/powerpc/mm/pgtable_64.c | 1 - arch/powerpc/platforms/iseries/irq.c | 5 -- arch/powerpc/platforms/iseries/pci.c | 37 ----------- arch/powerpc/platforms/iseries/setup.c | 4 -- arch/powerpc/platforms/iseries/smp.c | 1 - arch/powerpc/platforms/pseries/iommu.c | 1 - arch/powerpc/platforms/pseries/lpar.c | 2 +- arch/powerpc/platforms/pseries/ras.c | 2 +- arch/powerpc/sysdev/u3_iommu.c | 1 - arch/ppc64/Kconfig.debug | 4 -- arch/ppc64/kernel/prom.c | 1 - arch/ppc64/kernel/prom_init.c | 1 - arch/ppc64/kernel/udbg.c | 55 ----------------- include/asm-ppc64/ppcdebug.h | 108 --------------------------------- include/asm-ppc64/udbg.h | 3 - 20 files changed, 3 insertions(+), 242 deletions(-) delete mode 100644 include/asm-ppc64/ppcdebug.h diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 6b52cce872b..5f8154f95f9 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include @@ -60,6 +59,7 @@ #include #include #include +#include #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) @@ -243,12 +243,6 @@ void __init early_setup(unsigned long dt_ptr) DBG(" -> early_setup()\n"); - /* - * Fill the default DBG level (do we want to keep - * that old mecanism around forever ?) - */ - ppcdbg_initialize(); - /* * Do early initializations using the flattened device * tree, like retreiving the physical memory map or @@ -516,7 +510,6 @@ void __init setup_system(void) printk("-----------------------------------------------------\n"); printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size); - printk("ppc64_debug_switch = 0x%lx\n", ppc64_debug_switch); printk("ppc64_interrupt_controller = 0x%ld\n", ppc64_interrupt_controller); printk("systemcfg = 0x%p\n", systemcfg); printk("systemcfg->platform = 0x%x\n", systemcfg->platform); diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 876c57c1136..081d931eae4 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -44,7 +44,6 @@ #include #ifdef CONFIG_PPC64 #include "ppc32.h" -#include #include #include #else diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index ec9d0984b6a..58194e15071 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 6e9e05cce02..b6970c96d96 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -32,7 +32,6 @@ #include #include -#include #include #include #include @@ -194,12 +193,6 @@ void __init htab_initialize(void) htab_size_bytes = get_hashtable_size(); pteg_count = htab_size_bytes >> 7; - /* For debug, make the HTAB 1/8 as big as it normally would be. */ - ifppcdebug(PPCDBG_HTABSIZE) { - pteg_count >>= 3; - htab_size_bytes = pteg_count << 7; - } - htab_hash_mask = pteg_count - 1; if (systemcfg->platform & PLATFORM_LPAR) { diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index b0fc822ec29..aa98b79e734 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -57,7 +57,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index b79a7820613..d1fbd3fe684 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c @@ -59,7 +59,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index c1135912cc0..a06603d84a4 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c @@ -35,7 +35,6 @@ #include #include -#include #include #include #include @@ -227,8 +226,6 @@ static void iSeries_enable_IRQ(unsigned int irq) /* Unmask secondary INTA */ mask = 0x80000000; HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask); - PPCDBG(PPCDBG_BUSWALK, "iSeries_enable_IRQ 0x%02X.%02X.%02X 0x%04X\n", - bus, subBus, deviceId, irq); } /* This is called by iSeries_activate_IRQs */ @@ -310,8 +307,6 @@ static void iSeries_disable_IRQ(unsigned int irq) /* Mask secondary INTA */ mask = 0x80000000; HvCallPci_maskInterrupts(bus, subBus, deviceId, mask); - PPCDBG(PPCDBG_BUSWALK, "iSeries_disable_IRQ 0x%02X.%02X.%02X 0x%04X\n", - bus, subBus, deviceId, irq); } /* diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 7d7d5884343..4b75131773a 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include @@ -207,10 +206,6 @@ static struct device_node *build_device_node(HvBusNumber Bus, struct device_node *node; struct pci_dn *pdn; - PPCDBG(PPCDBG_BUSWALK, - "-build_device_node 0x%02X.%02X.%02X Function: %02X\n", - Bus, SubBus, AgentId, Function); - node = kmalloc(sizeof(struct device_node), GFP_KERNEL); if (node == NULL) return NULL; @@ -243,8 +238,6 @@ unsigned long __init find_and_init_phbs(void) struct pci_controller *phb; HvBusNumber bus; - PPCDBG(PPCDBG_BUSWALK, "find_and_init_phbs Entry\n"); - /* Check all possible buses. */ for (bus = 0; bus < 256; bus++) { int ret = HvCallXm_testBus(bus); @@ -261,9 +254,6 @@ unsigned long __init find_and_init_phbs(void) phb->last_busno = bus; phb->ops = &iSeries_pci_ops; - PPCDBG(PPCDBG_BUSWALK, "PCI:Create iSeries pci_controller(%p), Bus: %04X\n", - phb, bus); - /* Find and connect the devices. */ scan_PHB_slots(phb); } @@ -285,11 +275,9 @@ unsigned long __init find_and_init_phbs(void) */ void iSeries_pcibios_init(void) { - PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Entry.\n"); iomm_table_initialize(); find_and_init_phbs(); io_page_mask = -1; - PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Exit.\n"); } /* @@ -301,8 +289,6 @@ void __init iSeries_pci_final_fixup(void) struct device_node *node; int DeviceCount = 0; - PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup Entry.\n"); - /* Fix up at the device node and pci_dev relationship */ mf_display_src(0xC9000100); @@ -316,9 +302,6 @@ void __init iSeries_pci_final_fixup(void) ++DeviceCount; pdev->sysdata = (void *)node; PCI_DN(node)->pcidev = pdev; - PPCDBG(PPCDBG_BUSWALK, - "pdev 0x%p <==> DevNode 0x%p\n", - pdev, node); allocate_device_bars(pdev); iSeries_Device_Information(pdev, DeviceCount); iommu_devnode_init_iSeries(node); @@ -333,13 +316,10 @@ void __init iSeries_pci_final_fixup(void) void pcibios_fixup_bus(struct pci_bus *PciBus) { - PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup_bus(0x%04X) Entry.\n", - PciBus->number); } void pcibios_fixup_resources(struct pci_dev *pdev) { - PPCDBG(PPCDBG_BUSWALK, "fixup_resources pdev %p\n", pdev); } /* @@ -401,9 +381,6 @@ static void scan_EADS_bridge(HvBusNumber bus, HvSubBusNumber SubBus, printk("found device at bus %d idsel %d func %d (AgentId %x)\n", bus, IdSel, Function, AgentId); /* Connect EADs: 0x18.00.12 = 0x00 */ - PPCDBG(PPCDBG_BUSWALK, - "PCI:Connect EADs: 0x%02X.%02X.%02X\n", - bus, SubBus, AgentId); HvRc = HvCallPci_getBusUnitInfo(bus, SubBus, AgentId, iseries_hv_addr(BridgeInfo), sizeof(struct HvCallPci_BridgeInfo)); @@ -414,14 +391,6 @@ static void scan_EADS_bridge(HvBusNumber bus, HvSubBusNumber SubBus, BridgeInfo->maxAgents, BridgeInfo->maxSubBusNumber, BridgeInfo->logicalSlotNumber); - PPCDBG(PPCDBG_BUSWALK, - "PCI: BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X\n", - BridgeInfo->busUnitInfo.deviceType, - BridgeInfo->subBusNumber, - BridgeInfo->maxAgents, - BridgeInfo->maxSubBusNumber, - BridgeInfo->logicalSlotNumber); - if (BridgeInfo->busUnitInfo.deviceType == HvCallPci_BridgeDevice) { /* Scan_Bridge_Slot...: 0x18.00.12 */ @@ -454,9 +423,6 @@ static int scan_bridge_slot(HvBusNumber Bus, /* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */ Irq = iSeries_allocate_IRQ(Bus, 0, EADsIdSel); - PPCDBG(PPCDBG_BUSWALK, - "PCI:- allocate and assign IRQ 0x%02X.%02X.%02X = 0x%02X\n", - Bus, 0, EADsIdSel, Irq); /* * Connect all functions of any device found. @@ -482,9 +448,6 @@ static int scan_bridge_slot(HvBusNumber Bus, printk("read vendor ID: %x\n", VendorId); /* FoundDevice: 0x18.28.10 = 0x12AE */ - PPCDBG(PPCDBG_BUSWALK, - "PCI:- FoundDevice: 0x%02X.%02X.%02X = 0x%04X, irq %d\n", - Bus, SubBus, AgentId, VendorId, Irq); HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId, PCI_INTERRUPT_LINE, Irq); if (HvRc != 0) diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index fda712b4216..36f89e9ec7d 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -71,8 +71,6 @@ extern void hvlog(char *fmt, ...); #endif /* Function Prototypes */ -extern void ppcdbg_initialize(void); - static void build_iSeries_Memory_Map(void); static void iseries_shared_idle(void); static void iseries_dedicated_idle(void); @@ -309,8 +307,6 @@ static void __init iSeries_init_early(void) ppc64_firmware_features = FW_FEATURE_ISERIES; - ppcdbg_initialize(); - ppc64_interrupt_controller = IC_ISERIES; #if defined(CONFIG_BLK_DEV_INITRD) diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c index 3336bad6772..fcb094ec6ae 100644 --- a/arch/powerpc/platforms/iseries/smp.c +++ b/arch/powerpc/platforms/iseries/smp.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 513e2723149..8a99902c7ef 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index e384a5a9179..d84d76f0026 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -31,13 +31,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include "plpar_wrappers.h" diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index 6562ff4b0a8..fbd214d68b0 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c @@ -48,7 +48,7 @@ #include #include #include -#include +#include static unsigned char ras_log_buf[RTAS_ERROR_LOG_MAX]; static DEFINE_SPINLOCK(ras_log_buf_lock); diff --git a/arch/powerpc/sysdev/u3_iommu.c b/arch/powerpc/sysdev/u3_iommu.c index 607722178c1..543d6590981 100644 --- a/arch/powerpc/sysdev/u3_iommu.c +++ b/arch/powerpc/sysdev/u3_iommu.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc64/Kconfig.debug b/arch/ppc64/Kconfig.debug index f16a5030527..b258c9314a1 100644 --- a/arch/ppc64/Kconfig.debug +++ b/arch/ppc64/Kconfig.debug @@ -55,10 +55,6 @@ config XMON_DEFAULT xmon is normally disabled unless booted with 'xmon=on'. Use 'xmon=off' to disable xmon init during runtime. -config PPCDBG - bool "Include PPCDBG realtime debugging" - depends on DEBUG_KERNEL - config IRQSTACKS bool "Use separate kernel stacks when processing interrupts" help diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c index 97bfceb5353..a4cb97a2581 100644 --- a/arch/ppc64/kernel/prom.c +++ b/arch/ppc64/kernel/prom.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c index a4bbca6dbb8..e72b3f9061f 100644 --- a/arch/ppc64/kernel/prom_init.c +++ b/arch/ppc64/kernel/prom_init.c @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc64/kernel/udbg.c b/arch/ppc64/kernel/udbg.c index d49c3613c8e..0d878e72fc4 100644 --- a/arch/ppc64/kernel/udbg.c +++ b/arch/ppc64/kernel/udbg.c @@ -10,12 +10,10 @@ */ #include -#define WANT_PPCDBG_TAB /* Only defined here */ #include #include #include #include -#include #include void (*udbg_putc)(unsigned char c); @@ -89,59 +87,6 @@ void udbg_printf(const char *fmt, ...) va_end(args); } -/* PPCDBG stuff */ - -u64 ppc64_debug_switch; - -/* Special print used by PPCDBG() macro */ -void udbg_ppcdbg(unsigned long debug_flags, const char *fmt, ...) -{ - unsigned long active_debugs = debug_flags & ppc64_debug_switch; - - if (active_debugs) { - va_list ap; - unsigned char buf[UDBG_BUFSIZE]; - unsigned long i, len = 0; - - for (i=0; i < PPCDBG_NUM_FLAGS; i++) { - if (((1U << i) & active_debugs) && - trace_names[i]) { - len += strlen(trace_names[i]); - udbg_puts(trace_names[i]); - break; - } - } - - snprintf(buf, UDBG_BUFSIZE, " [%s]: ", current->comm); - len += strlen(buf); - udbg_puts(buf); - - while (len < 18) { - udbg_puts(" "); - len++; - } - - va_start(ap, fmt); - vsnprintf(buf, UDBG_BUFSIZE, fmt, ap); - udbg_puts(buf); - va_end(ap); - } -} - -unsigned long udbg_ifdebug(unsigned long flags) -{ - return (flags & ppc64_debug_switch); -} - -/* - * Initialize the PPCDBG state. Called before relocation has been enabled. - */ -void __init ppcdbg_initialize(void) -{ - ppc64_debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | */ - /* PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */; -} - /* * Early boot console based on udbg */ diff --git a/include/asm-ppc64/ppcdebug.h b/include/asm-ppc64/ppcdebug.h deleted file mode 100644 index fd7f696065c..00000000000 --- a/include/asm-ppc64/ppcdebug.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef __PPCDEBUG_H -#define __PPCDEBUG_H -/******************************************************************** - * Author: Adam Litke, IBM Corp - * (c) 2001 - * - * This file contains definitions and macros for a runtime debugging - * system for ppc64 (This should also work on 32 bit with a few - * adjustments. - * - * 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 option) any later version. - * - ********************************************************************/ - -#include -#include -#include -#include - -#define PPCDBG_BITVAL(X) ((1UL)<<((unsigned long)(X))) - -/* Defined below are the bit positions of various debug flags in the - * ppc64_debug_switch variable. - * -- When adding new values, please enter them into trace names below -- - * - * Values 62 & 63 can be used to stress the hardware page table management - * code. They must be set statically, any attempt to change them dynamically - * would be a very bad idea. - */ -#define PPCDBG_MMINIT PPCDBG_BITVAL(0) -#define PPCDBG_MM PPCDBG_BITVAL(1) -#define PPCDBG_SYS32 PPCDBG_BITVAL(2) -#define PPCDBG_SYS32NI PPCDBG_BITVAL(3) -#define PPCDBG_SYS32X PPCDBG_BITVAL(4) -#define PPCDBG_SYS32M PPCDBG_BITVAL(5) -#define PPCDBG_SYS64 PPCDBG_BITVAL(6) -#define PPCDBG_SYS64NI PPCDBG_BITVAL(7) -#define PPCDBG_SYS64X PPCDBG_BITVAL(8) -#define PPCDBG_SIGNAL PPCDBG_BITVAL(9) -#define PPCDBG_SIGNALXMON PPCDBG_BITVAL(10) -#define PPCDBG_BINFMT32 PPCDBG_BITVAL(11) -#define PPCDBG_BINFMT64 PPCDBG_BITVAL(12) -#define PPCDBG_BINFMTXMON PPCDBG_BITVAL(13) -#define PPCDBG_BINFMT_32ADDR PPCDBG_BITVAL(14) -#define PPCDBG_ALIGNFIXUP PPCDBG_BITVAL(15) -#define PPCDBG_TCEINIT PPCDBG_BITVAL(16) -#define PPCDBG_TCE PPCDBG_BITVAL(17) -#define PPCDBG_PHBINIT PPCDBG_BITVAL(18) -#define PPCDBG_SMP PPCDBG_BITVAL(19) -#define PPCDBG_BOOT PPCDBG_BITVAL(20) -#define PPCDBG_BUSWALK PPCDBG_BITVAL(21) -#define PPCDBG_PROM PPCDBG_BITVAL(22) -#define PPCDBG_RTAS PPCDBG_BITVAL(23) -#define PPCDBG_HTABSTRESS PPCDBG_BITVAL(62) -#define PPCDBG_HTABSIZE PPCDBG_BITVAL(63) -#define PPCDBG_NONE (0UL) -#define PPCDBG_ALL (0xffffffffUL) - -/* The default initial value for the debug switch */ -#define PPC_DEBUG_DEFAULT 0 -/* #define PPC_DEBUG_DEFAULT PPCDBG_ALL */ - -#define PPCDBG_NUM_FLAGS 64 - -extern u64 ppc64_debug_switch; - -#ifdef WANT_PPCDBG_TAB -/* A table of debug switch names to allow name lookup in xmon - * (and whoever else wants it. - */ -char *trace_names[PPCDBG_NUM_FLAGS] = { - /* Known debug names */ - "mminit", "mm", - "syscall32", "syscall32_ni", "syscall32x", "syscall32m", - "syscall64", "syscall64_ni", "syscall64x", - "signal", "signal_xmon", - "binfmt32", "binfmt64", "binfmt_xmon", "binfmt_32addr", - "alignfixup", "tceinit", "tce", "phb_init", - "smp", "boot", "buswalk", "prom", - "rtas" -}; -#else -extern char *trace_names[64]; -#endif /* WANT_PPCDBG_TAB */ - -#ifdef CONFIG_PPCDBG -/* Macro to conditionally print debug based on debug_switch */ -#define PPCDBG(...) udbg_ppcdbg(__VA_ARGS__) - -/* Macro to conditionally call a debug routine based on debug_switch */ -#define PPCDBGCALL(FLAGS,FUNCTION) ifppcdebug(FLAGS) FUNCTION - -/* Macros to test for debug states */ -#define ifppcdebug(FLAGS) if (udbg_ifdebug(FLAGS)) -#define ppcdebugset(FLAGS) (udbg_ifdebug(FLAGS)) -#define PPCDBG_BINFMT (test_thread_flag(TIF_32BIT) ? PPCDBG_BINFMT32 : PPCDBG_BINFMT64) - -#else -#define PPCDBG(...) do {;} while (0) -#define PPCDBGCALL(FLAGS,FUNCTION) do {;} while (0) -#define ifppcdebug(...) if (0) -#define ppcdebugset(FLAGS) (0) -#endif /* CONFIG_PPCDBG */ - -#endif /*__PPCDEBUG_H */ diff --git a/include/asm-ppc64/udbg.h b/include/asm-ppc64/udbg.h index 8192fb8541c..e3b92799185 100644 --- a/include/asm-ppc64/udbg.h +++ b/include/asm-ppc64/udbg.h @@ -23,9 +23,6 @@ extern int udbg_read(char *buf, int buflen); extern void register_early_udbg_console(void); extern void udbg_printf(const char *fmt, ...); -extern void udbg_ppcdbg(unsigned long flags, const char *fmt, ...); -extern unsigned long udbg_ifdebug(unsigned long flags); -extern void __init ppcdbg_initialize(void); extern void udbg_init_uart(void __iomem *comport, unsigned int speed); -- cgit v1.2.3 From 30966174341b3db58dfb77b82193eff7f5644a97 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 02:49:43 +0100 Subject: [MTD] NAND Kconfig: Simplify dependencies Signed-off-by: Thomas Gleixner --- drivers/mtd/nand/Kconfig | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 435739d4b29..f6f5ac80895 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -25,33 +25,33 @@ config MTD_NAND_VERIFY_WRITE config MTD_NAND_AUTCPU12 tristate "SmartMediaCard on autronix autcpu12 board" - depends on ARM && MTD_NAND && ARCH_AUTCPU12 + depends on MTD_NAND && ARCH_AUTCPU12 help This enables the driver for the autronix autcpu12 board to access the SmartMediaCard. config MTD_NAND_EDB7312 tristate "Support for Cirrus Logic EBD7312 evaluation board" - depends on ARM && MTD_NAND && ARCH_EDB7312 + depends on MTD_NAND && ARCH_EDB7312 help This enables the driver for the Cirrus Logic EBD7312 evaluation board to access the onboard NAND Flash. config MTD_NAND_H1900 tristate "iPAQ H1900 flash" - depends on ARM && MTD_NAND && ARCH_PXA && MTD_PARTITIONS + depends on MTD_NAND && ARCH_PXA && MTD_PARTITIONS help This enables the driver for the iPAQ h1900 flash. config MTD_NAND_SPIA tristate "NAND Flash device on SPIA board" - depends on ARM && ARCH_P720T && MTD_NAND + depends on ARCH_P720T && MTD_NAND help If you had to ask, you don't have one. Say 'N'. config MTD_NAND_TOTO tristate "NAND Flash device on TOTO board" - depends on ARM && ARCH_OMAP && MTD_NAND + depends on ARCH_OMAP && MTD_NAND help Support for NAND flash on Texas Instruments Toto platform. @@ -181,7 +181,7 @@ config MTD_NAND_DISKONCHIP_BBTWRITE config MTD_NAND_SHARPSL bool "Support for NAND Flash on Sharp SL Series (C7xx + others)" - depends on MTD_NAND && ARCH_PXA + depends on MTD_NAND && ARCH_PXA config MTD_NAND_NANDSIM bool "Support for NAND Flash Simulator" -- cgit v1.2.3 From 2249ca9d60d3a8a1f6f223f0f0a0283fcb7ce33e Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 7 Nov 2005 13:18:13 +1100 Subject: powerpc: Various UP build fixes Mostly this involves adding #include , since that defines things like boot_cpuid[_phys] and [gs]et_hard_smp_processor_id, which are SMP-related but still needed on UP. This incorporates fixes posted by Olof Johansson and Heikki Lindholm. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/rtas.c | 2 -- arch/powerpc/kernel/time.c | 5 +---- arch/powerpc/lib/locks.c | 1 + arch/powerpc/mm/numa.c | 1 + arch/powerpc/platforms/pseries/iommu.c | 1 + arch/powerpc/platforms/pseries/lpar.c | 1 + arch/powerpc/platforms/pseries/setup.c | 1 + arch/ppc64/kernel/idle.c | 1 + arch/ppc64/kernel/machine_kexec.c | 1 + arch/ppc64/kernel/sysfs.c | 1 + include/asm-powerpc/smp.h | 4 +++- 11 files changed, 12 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index b7fc2d88495..751f5ddea91 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -608,7 +608,6 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) return 0; } -#ifdef CONFIG_SMP /* This version can't take the spinlock, because it never returns */ struct rtas_args rtas_stop_self_args = { @@ -633,7 +632,6 @@ void rtas_stop_self(void) panic("Alas, I survived.\n"); } -#endif /* * Call early during boot, before mem init or bootmem, to retreive the RTAS diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 6996a593dcb..1c7ea5e0631 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -61,6 +61,7 @@ #include #include #include +#include #ifdef CONFIG_PPC64 #include #include @@ -118,10 +119,6 @@ static unsigned adjusting_time = 0; unsigned long ppc_proc_freq; unsigned long ppc_tb_freq; -#ifdef CONFIG_PPC32 /* XXX for now */ -#define boot_cpuid 0 -#endif - u64 tb_last_jiffy __cacheline_aligned_in_smp; unsigned long tb_last_stamp; diff --git a/arch/powerpc/lib/locks.c b/arch/powerpc/lib/locks.c index 2a912f411eb..35bd03c41dd 100644 --- a/arch/powerpc/lib/locks.c +++ b/arch/powerpc/lib/locks.c @@ -23,6 +23,7 @@ #if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES) #include #include +#include void __spin_yield(raw_spinlock_t *lock) { diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 4035cad8d7f..da09ba03c42 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -21,6 +21,7 @@ #include #include #include +#include static int numa_enabled = 1; diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 8a99902c7ef..fcc50bfd43f 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -46,6 +46,7 @@ #include #include #include +#include #include "plpar_wrappers.h" diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index d84d76f0026..8a42006370c 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "plpar_wrappers.h" diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 65bee939eec..934d7006353 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -65,6 +65,7 @@ #include #include #include +#include #include "plpar_wrappers.h" diff --git a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c index 8abd2ad9283..8fec2746980 100644 --- a/arch/ppc64/kernel/idle.c +++ b/arch/ppc64/kernel/idle.c @@ -28,6 +28,7 @@ #include #include #include +#include extern void power4_idle(void); diff --git a/arch/ppc64/kernel/machine_kexec.c b/arch/ppc64/kernel/machine_kexec.c index ff8679f260f..07ea03598c0 100644 --- a/arch/ppc64/kernel/machine_kexec.c +++ b/arch/ppc64/kernel/machine_kexec.c @@ -24,6 +24,7 @@ #include #include /* _end */ #include +#include #define HASH_GROUP_SIZE 0x80 /* size of each hash group, asm/mmu.h */ diff --git a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c index 6654b350979..e99ec62c2c5 100644 --- a/arch/ppc64/kernel/sysfs.c +++ b/arch/ppc64/kernel/sysfs.c @@ -20,6 +20,7 @@ #include #include #include +#include static DEFINE_PER_CPU(struct cpu, cpu_devices); diff --git a/include/asm-powerpc/smp.h b/include/asm-powerpc/smp.h index 8bcdd0faefe..98581e5a827 100644 --- a/include/asm-powerpc/smp.h +++ b/include/asm-powerpc/smp.h @@ -86,7 +86,6 @@ extern void __cpu_die(unsigned int cpu); #else /* for UP */ #define smp_setup_cpu_maps() -#define smp_release_cpus() #endif /* CONFIG_SMP */ @@ -94,6 +93,9 @@ extern void __cpu_die(unsigned int cpu); #define get_hard_smp_processor_id(CPU) (paca[(CPU)].hw_cpu_id) #define set_hard_smp_processor_id(CPU, VAL) \ do { (paca[(CPU)].hw_cpu_id = (VAL)); } while (0) + +extern void smp_release_cpus(void); + #else /* 32-bit */ #ifndef CONFIG_SMP -- cgit v1.2.3 From 76032de898f34db55b5048349db56557828a1390 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Mon, 7 Nov 2005 13:12:03 +1100 Subject: [PATCH] powerpc: Make ppc_md.set_dabr non 64-bit specific Define ppc_md.set_dabr for both 32 + 64 bit. Cleanup the implementation for pSeries also, it was needlessly complex. Now we just do two firmware tests at setup time, and use one of two functions, rather than using one function and testing on every call. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/process.c | 4 +--- arch/powerpc/platforms/pseries/plpar_wrappers.h | 10 ---------- arch/powerpc/platforms/pseries/setup.c | 17 ++++++++++------- include/asm-powerpc/machdep.h | 4 +++- 4 files changed, 14 insertions(+), 21 deletions(-) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 96843211cc5..29f6e875cf1 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -46,10 +46,10 @@ #include #include #include +#include #ifdef CONFIG_PPC64 #include #include -#include #endif extern unsigned long _get_SP(void); @@ -203,10 +203,8 @@ int dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs) int set_dabr(unsigned long dabr) { -#ifdef CONFIG_PPC64 if (ppc_md.set_dabr) return ppc_md.set_dabr(dabr); -#endif mtspr(SPRN_DABR, dabr); return 0; diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h index 382f8c5b0e7..3bd1b3e0600 100644 --- a/arch/powerpc/platforms/pseries/plpar_wrappers.h +++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h @@ -107,14 +107,4 @@ static inline long plpar_put_term_char(unsigned long termno, unsigned long len, lbuf[1]); } -static inline long plpar_set_xdabr(unsigned long address, unsigned long flags) -{ - return plpar_hcall_norets(H_SET_XDABR, address, flags); -} - -static inline long plpar_set_dabr(unsigned long val) -{ - return plpar_hcall_norets(H_SET_DABR, val); -} - #endif /* _PSERIES_PLPAR_WRAPPERS_H */ diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 934d7006353..e78c3936884 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -354,14 +354,15 @@ static void pSeries_mach_cpu_die(void) static int pseries_set_dabr(unsigned long dabr) { - if (firmware_has_feature(FW_FEATURE_XDABR)) { - /* We want to catch accesses from kernel and userspace */ - return plpar_set_xdabr(dabr, H_DABRX_KERNEL | H_DABRX_USER); - } - - return plpar_set_dabr(dabr); + return plpar_hcall_norets(H_SET_DABR, dabr); } +static int pseries_set_xdabr(unsigned long dabr) +{ + /* We want to catch accesses from kernel and userspace */ + return plpar_hcall_norets(H_SET_XDABR, dabr, + H_DABRX_KERNEL | H_DABRX_USER); +} /* * Early initialization. Relocation is on but do not reference unbolted pages @@ -397,8 +398,10 @@ static void __init pSeries_init_early(void) DBG("Hello World !\n"); } - if (firmware_has_feature(FW_FEATURE_XDABR | FW_FEATURE_DABR)) + if (firmware_has_feature(FW_FEATURE_DABR)) ppc_md.set_dabr = pseries_set_dabr; + else if (firmware_has_feature(FW_FEATURE_XDABR)) + ppc_md.set_dabr = pseries_set_xdabr; iommu_init_early_pSeries(); diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index 629ca964b97..b623bc4a155 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h @@ -80,7 +80,6 @@ struct machdep_calls { void (*iommu_dev_setup)(struct pci_dev *dev); void (*iommu_bus_setup)(struct pci_bus *bus); void (*irq_bus_setup)(struct pci_bus *bus); - int (*set_dabr)(unsigned long dabr); #endif int (*probe)(int platform); @@ -156,6 +155,9 @@ struct machdep_calls { platform, called once per cpu. */ void (*enable_pmcs)(void); + /* Set DABR for this platform, leave empty for default implemenation */ + int (*set_dabr)(unsigned long dabr); + #ifdef CONFIG_PPC32 /* XXX for now */ /* A general init function, called by ppc_init in init/main.c. May be NULL. */ -- cgit v1.2.3 From 193515d51ccb363165d6b09e9ba5c21089e34bad Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Mon, 7 Nov 2005 00:59:37 -0500 Subject: [libata] eliminate use of drivers/scsi/scsi.h compatibility header/defines --- drivers/scsi/ahci.c | 4 ++-- drivers/scsi/ata_piix.c | 3 +-- drivers/scsi/libata-core.c | 2 +- drivers/scsi/libata-scsi.c | 2 +- drivers/scsi/pdc_adma.c | 3 +-- drivers/scsi/sata_mv.c | 4 ++-- drivers/scsi/sata_nv.c | 3 +-- drivers/scsi/sata_promise.c | 4 ++-- drivers/scsi/sata_qstor.c | 3 +-- drivers/scsi/sata_sil.c | 3 +-- drivers/scsi/sata_sil24.c | 4 ++-- drivers/scsi/sata_sis.c | 3 +-- drivers/scsi/sata_svw.c | 3 +-- drivers/scsi/sata_sx4.c | 4 ++-- drivers/scsi/sata_uli.c | 3 +-- drivers/scsi/sata_via.c | 3 +-- drivers/scsi/sata_vsc.c | 3 +-- include/linux/libata.h | 6 +++--- 18 files changed, 25 insertions(+), 35 deletions(-) diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 4612312c0c2..10c470e7d31 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -42,8 +42,8 @@ #include #include #include -#include "scsi.h" #include +#include #include #include @@ -196,7 +196,7 @@ static u8 ahci_check_status(struct ata_port *ap); static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); static void ahci_remove_one (struct pci_dev *pdev); -static Scsi_Host_Template ahci_sht = { +static struct scsi_host_template ahci_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 7f8aa1b552c..a1bd8d95623 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -46,7 +46,6 @@ #include #include #include -#include "scsi.h" #include #include @@ -128,7 +127,7 @@ static struct pci_driver piix_pci_driver = { .remove = ata_pci_remove_one, }; -static Scsi_Host_Template piix_sht = { +static struct scsi_host_template piix_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 1c1a7caf785..98769a3d31a 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -51,8 +51,8 @@ #include #include #include -#include "scsi.h" #include "scsi_priv.h" +#include #include #include #include diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index eb604b0a899..38a895ebe82 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -37,9 +37,9 @@ #include #include #include -#include "scsi.h" #include #include +#include #include #include #include diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index a50588c60fa..78b4ff117af 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -41,7 +41,6 @@ #include #include #include -#include "scsi.h" #include #include #include @@ -139,7 +138,7 @@ static u8 adma_bmdma_status(struct ata_port *ap); static void adma_irq_clear(struct ata_port *ap); static void adma_eng_timeout(struct ata_port *ap); -static Scsi_Host_Template adma_ata_sht = { +static struct scsi_host_template adma_ata_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 0f469e3dabe..93d55233af7 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -30,8 +30,8 @@ #include #include #include -#include "scsi.h" #include +#include #include #include @@ -270,7 +270,7 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance, static void mv_eng_timeout(struct ata_port *ap); static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); -static Scsi_Host_Template mv_sht = { +static struct scsi_host_template mv_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index d573888eda7..37a4fae95ed 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -62,7 +62,6 @@ #include #include #include -#include "scsi.h" #include #include @@ -219,7 +218,7 @@ static struct pci_driver nv_pci_driver = { .remove = ata_pci_remove_one, }; -static Scsi_Host_Template nv_sht = { +static struct scsi_host_template nv_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index b41c977d6fa..9edc9d91efc 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -39,8 +39,8 @@ #include #include #include -#include "scsi.h" #include +#include #include #include #include "sata_promise.h" @@ -94,7 +94,7 @@ static void pdc_irq_clear(struct ata_port *ap); static int pdc_qc_issue_prot(struct ata_queued_cmd *qc); -static Scsi_Host_Template pdc_ata_sht = { +static struct scsi_host_template pdc_ata_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index 65502c157a5..d274ab23578 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -36,7 +36,6 @@ #include #include #include -#include "scsi.h" #include #include #include @@ -128,7 +127,7 @@ static u8 qs_bmdma_status(struct ata_port *ap); static void qs_irq_clear(struct ata_port *ap); static void qs_eng_timeout(struct ata_port *ap); -static Scsi_Host_Template qs_ata_sht = { +static struct scsi_host_template qs_ata_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 435f7e0085e..d0e3c3c6c25 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -42,7 +42,6 @@ #include #include #include -#include "scsi.h" #include #include @@ -131,7 +130,7 @@ static struct pci_driver sil_pci_driver = { .remove = ata_pci_remove_one, }; -static Scsi_Host_Template sil_sht = { +static struct scsi_host_template sil_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index e6c8e89c226..4682a50650b 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -37,7 +37,7 @@ #include #include #include -#include "scsi.h" +#include #include #include @@ -255,7 +255,7 @@ static struct pci_driver sil24_pci_driver = { .remove = ata_pci_remove_one, /* safe? */ }; -static Scsi_Host_Template sil24_sht = { +static struct scsi_host_template sil24_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index 42288be0e56..42d7c4e9250 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c @@ -39,7 +39,6 @@ #include #include #include -#include "scsi.h" #include #include @@ -83,7 +82,7 @@ static struct pci_driver sis_pci_driver = { .remove = ata_pci_remove_one, }; -static Scsi_Host_Template sis_sht = { +static struct scsi_host_template sis_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index db615ff794d..9895d1caefc 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -45,7 +45,6 @@ #include #include #include -#include "scsi.h" #include #include @@ -284,7 +283,7 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start, #endif /* CONFIG_PPC_OF */ -static Scsi_Host_Template k2_sata_sht = { +static struct scsi_host_template k2_sata_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index f859bbd681e..d5a38784352 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -39,8 +39,8 @@ #include #include #include -#include "scsi.h" #include +#include #include #include #include "sata_promise.h" @@ -177,7 +177,7 @@ static void pdc20621_irq_clear(struct ata_port *ap); static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc); -static Scsi_Host_Template pdc_sata_sht = { +static struct scsi_host_template pdc_sata_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c index a5e245c098e..cf0baaa4e04 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/scsi/sata_uli.c @@ -33,7 +33,6 @@ #include #include #include -#include "scsi.h" #include #include @@ -71,7 +70,7 @@ static struct pci_driver uli_pci_driver = { .remove = ata_pci_remove_one, }; -static Scsi_Host_Template uli_sht = { +static struct scsi_host_template uli_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c index b3ecdbe400e..ab19d2ba2a4 100644 --- a/drivers/scsi/sata_via.c +++ b/drivers/scsi/sata_via.c @@ -42,7 +42,6 @@ #include #include #include -#include "scsi.h" #include #include #include @@ -90,7 +89,7 @@ static struct pci_driver svia_pci_driver = { .remove = ata_pci_remove_one, }; -static Scsi_Host_Template svia_sht = { +static struct scsi_host_template svia_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index bb84ba0c7e8..ce8a2fd7da8 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -43,7 +43,6 @@ #include #include #include -#include "scsi.h" #include #include @@ -219,7 +218,7 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, } -static Scsi_Host_Template vsc_sata_sht = { +static struct scsi_host_template vsc_sata_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/include/linux/libata.h b/include/linux/libata.h index dcd17e7458a..6f0752219f6 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -214,7 +214,7 @@ struct ata_probe_ent { struct list_head node; struct device *dev; const struct ata_port_operations *port_ops; - Scsi_Host_Template *sht; + struct scsi_host_template *sht; struct ata_ioports port[ATA_MAX_PORTS]; unsigned int n_ports; unsigned int hard_port_no; @@ -398,7 +398,7 @@ struct ata_port_operations { }; struct ata_port_info { - Scsi_Host_Template *sht; + struct scsi_host_template *sht; unsigned long host_flags; unsigned long pio_mask; unsigned long mwdma_mask; @@ -433,7 +433,7 @@ extern void ata_pci_remove_one (struct pci_dev *pdev); #endif /* CONFIG_PCI */ extern int ata_device_add(const struct ata_probe_ent *ent); extern void ata_host_set_remove(struct ata_host_set *host_set); -extern int ata_scsi_detect(Scsi_Host_Template *sht); +extern int ata_scsi_detect(struct scsi_host_template *sht); extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); extern int ata_scsi_error(struct Scsi_Host *host); -- cgit v1.2.3 From c719369350bc566d2643067421fbf05f4b90e70b Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Mon, 7 Nov 2005 01:50:03 +0100 Subject: [PATCH] b44: b44_start_xmit returns with a lock held when it fails allocating The patch simply factors out the release of the lock. Signed-off-by: Francois Romieu Signed-off-by: Jeff Garzik --- drivers/net/b44.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 0ee3e27969c..b334cc310bc 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -948,6 +948,7 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct b44 *bp = netdev_priv(dev); struct sk_buff *bounce_skb; + int rc = NETDEV_TX_OK; dma_addr_t mapping; u32 len, entry, ctrl; @@ -957,10 +958,9 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) /* This is a hard error, log it. */ if (unlikely(TX_BUFFS_AVAIL(bp) < 1)) { netif_stop_queue(dev); - spin_unlock_irq(&bp->lock); printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n", dev->name); - return 1; + goto err_out; } mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE); @@ -971,7 +971,7 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) bounce_skb = __dev_alloc_skb(TX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA); if (!bounce_skb) - return NETDEV_TX_BUSY; + goto err_out; mapping = pci_map_single(bp->pdev, bounce_skb->data, len, PCI_DMA_TODEVICE); @@ -979,7 +979,7 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE); dev_kfree_skb_any(bounce_skb); - return NETDEV_TX_BUSY; + goto err_out; } memcpy(skb_put(bounce_skb, len), skb->data, skb->len); @@ -1019,11 +1019,16 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) if (TX_BUFFS_AVAIL(bp) < 1) netif_stop_queue(dev); + dev->trans_start = jiffies; + +out_unlock: spin_unlock_irq(&bp->lock); - dev->trans_start = jiffies; + return rc; - return 0; +err_out: + rc = NETDEV_TX_BUSY; + goto out_unlock; } static int b44_change_mtu(struct net_device *dev, int new_mtu) -- cgit v1.2.3 From 874a6214bc1477004a0dd6f881b078d0d6b1eae9 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Mon, 7 Nov 2005 01:50:46 +0100 Subject: [PATCH] b44: miscellaneous cleanup - remove unneeded forward declarations - s/kmalloc + memset/kzalloc/ - whitespace readjustement can't hurt - wrong comment: b44_init_rings _is_ called with a spinlock held in b44_{open/set_ringparam/set_pauseparam/etc}. Actually, it does not need to be able to sleep - b44_remove_one() can not be issued with a NULL device in its private member: remove the test. Signed-off-by: Francois Romieu Signed-off-by: Jeff Garzik --- drivers/net/b44.c | 67 +++++++++++++++++++++++-------------------------------- 1 file changed, 28 insertions(+), 39 deletions(-) diff --git a/drivers/net/b44.c b/drivers/net/b44.c index b334cc310bc..3b6428f004f 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -102,10 +102,6 @@ MODULE_DEVICE_TABLE(pci, b44_pci_tbl); static void b44_halt(struct b44 *); static void b44_init_rings(struct b44 *); static void b44_init_hw(struct b44 *); -static int b44_poll(struct net_device *dev, int *budget); -#ifdef CONFIG_NET_POLL_CONTROLLER -static void b44_poll_controller(struct net_device *dev); -#endif static int dma_desc_align_mask; static int dma_desc_sync_size; @@ -653,7 +649,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) /* Hardware bug work-around, the chip is unable to do PCI DMA to/from anything above 1GB :-( */ - if(mapping+RX_PKT_BUF_SZ > B44_DMA_MASK) { + if (mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) { /* Sigh... */ pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE); dev_kfree_skb_any(skb); @@ -663,7 +659,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) mapping = pci_map_single(bp->pdev, skb->data, RX_PKT_BUF_SZ, PCI_DMA_FROMDEVICE); - if(mapping+RX_PKT_BUF_SZ > B44_DMA_MASK) { + if (mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) { pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE); dev_kfree_skb_any(skb); return -ENOMEM; @@ -964,7 +960,7 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) } mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE); - if(mapping+len > B44_DMA_MASK) { + if (mapping + len > B44_DMA_MASK) { /* Chip can't handle DMA to/from >1GB, use bounce buffer */ pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE); @@ -975,7 +971,7 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) mapping = pci_map_single(bp->pdev, bounce_skb->data, len, PCI_DMA_TODEVICE); - if(mapping+len > B44_DMA_MASK) { + if (mapping + len > B44_DMA_MASK) { pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE); dev_kfree_skb_any(bounce_skb); @@ -1102,8 +1098,7 @@ static void b44_free_rings(struct b44 *bp) * * The chip has been shut down and the driver detached from * the networking, so no interrupts or new tx packets will - * end up in the driver. bp->lock is not held and we are not - * in an interrupt context and thus may sleep. + * end up in the driver. */ static void b44_init_rings(struct b44 *bp) { @@ -1175,16 +1170,14 @@ static int b44_alloc_consistent(struct b44 *bp) int size; size = B44_RX_RING_SIZE * sizeof(struct ring_info); - bp->rx_buffers = kmalloc(size, GFP_KERNEL); + bp->rx_buffers = kzalloc(size, GFP_KERNEL); if (!bp->rx_buffers) goto out_err; - memset(bp->rx_buffers, 0, size); size = B44_TX_RING_SIZE * sizeof(struct ring_info); - bp->tx_buffers = kmalloc(size, GFP_KERNEL); + bp->tx_buffers = kzalloc(size, GFP_KERNEL); if (!bp->tx_buffers) goto out_err; - memset(bp->tx_buffers, 0, size); size = DMA_TABLE_BYTES; bp->rx_ring = pci_alloc_consistent(bp->pdev, size, &bp->rx_ring_dma); @@ -1195,10 +1188,10 @@ static int b44_alloc_consistent(struct b44 *bp) struct dma_desc *rx_ring; dma_addr_t rx_ring_dma; - if (!(rx_ring = (struct dma_desc *)kmalloc(size, GFP_KERNEL))) + rx_ring = kzalloc(size, GFP_KERNEL); + if (!rx_ring) goto out_err; - memset(rx_ring, 0, size); rx_ring_dma = dma_map_single(&bp->pdev->dev, rx_ring, DMA_TABLE_BYTES, DMA_BIDIRECTIONAL); @@ -1221,10 +1214,10 @@ static int b44_alloc_consistent(struct b44 *bp) struct dma_desc *tx_ring; dma_addr_t tx_ring_dma; - if (!(tx_ring = (struct dma_desc *)kmalloc(size, GFP_KERNEL))) + tx_ring = kzalloc(size, GFP_KERNEL); + if (!tx_ring) goto out_err; - memset(tx_ring, 0, size); tx_ring_dma = dma_map_single(&bp->pdev->dev, tx_ring, DMA_TABLE_BYTES, DMA_TO_DEVICE); @@ -1530,8 +1523,6 @@ static void __b44_set_rx_mode(struct net_device *dev) { struct b44 *bp = netdev_priv(dev); u32 val; - int i=0; - unsigned char zero[6] = {0,0,0,0,0,0}; val = br32(bp, B44_RXCONFIG); val &= ~(RXCONFIG_PROMISC | RXCONFIG_ALLMULTI); @@ -1539,14 +1530,17 @@ static void __b44_set_rx_mode(struct net_device *dev) val |= RXCONFIG_PROMISC; bw32(bp, B44_RXCONFIG, val); } else { + unsigned char zero[6] = {0, 0, 0, 0, 0, 0}; + int i = 0; + __b44_set_mac_addr(bp); if (dev->flags & IFF_ALLMULTI) val |= RXCONFIG_ALLMULTI; else - i=__b44_load_mcast(bp, dev); + i = __b44_load_mcast(bp, dev); - for(;i<64;i++) { + for (; i < 64; i++) { __b44_cam_write(bp, zero, i); } bw32(bp, B44_RXCONFIG, val); @@ -1898,9 +1892,9 @@ static int __devinit b44_init_one(struct pci_dev *pdev, err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK); if (err) { - printk(KERN_ERR PFX "No usable DMA configuration, " - "aborting.\n"); - goto err_out_free_res; + printk(KERN_ERR PFX "No usable DMA configuration, " + "aborting.\n"); + goto err_out_free_res; } b44reg_base = pci_resource_start(pdev, 0); @@ -1922,10 +1916,8 @@ static int __devinit b44_init_one(struct pci_dev *pdev, bp = netdev_priv(dev); bp->pdev = pdev; bp->dev = dev; - if (b44_debug >= 0) - bp->msg_enable = (1 << b44_debug) - 1; - else - bp->msg_enable = B44_DEF_MSG_ENABLE; + + bp->msg_enable = netif_msg_init(b44_debug, B44_DEF_MSG_ENABLE); spin_lock_init(&bp->lock); @@ -2015,17 +2007,14 @@ err_out_disable_pdev: static void __devexit b44_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); + struct b44 *bp = netdev_priv(dev); - if (dev) { - struct b44 *bp = netdev_priv(dev); - - unregister_netdev(dev); - iounmap(bp->regs); - free_netdev(dev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } + unregister_netdev(dev); + iounmap(bp->regs); + free_netdev(dev); + pci_release_regions(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); } static int b44_suspend(struct pci_dev *pdev, pm_message_t state) -- cgit v1.2.3 From 3353930d9d026ca94747d0766f864b2a0a8c714b Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Mon, 7 Nov 2005 01:51:34 +0100 Subject: [PATCH] b44: expose counters through ethtool Signed-off-by: Francois Romieu Signed-off-by: Jeff Garzik --- drivers/net/b44.c | 45 ++++++++++++++++++++++++++++++++- drivers/net/b44.h | 74 ++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 98 insertions(+), 21 deletions(-) diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 3b6428f004f..ac223fcf986 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -106,6 +106,12 @@ static void b44_init_hw(struct b44 *); static int dma_desc_align_mask; static int dma_desc_sync_size; +static const char b44_gstrings[][ETH_GSTRING_LEN] = { +#define _B44(x...) # x, +B44_STAT_REG_DECLARE +#undef _B44 +}; + static inline void b44_sync_dma_desc_for_device(struct pci_dev *pdev, dma_addr_t dma_base, unsigned long offset, @@ -498,7 +504,10 @@ static void b44_stats_update(struct b44 *bp) for (reg = B44_TX_GOOD_O; reg <= B44_TX_PAUSE; reg += 4UL) { *val++ += br32(bp, reg); } - val = &bp->hw_stats.rx_good_octets; + + /* Pad */ + reg += 8*4UL; + for (reg = B44_RX_GOOD_O; reg <= B44_RX_NPAUSE; reg += 4UL) { *val++ += br32(bp, reg); } @@ -1772,6 +1781,37 @@ static int b44_set_pauseparam(struct net_device *dev, return 0; } +static void b44_get_strings(struct net_device *dev, u32 stringset, u8 *data) +{ + switch(stringset) { + case ETH_SS_STATS: + memcpy(data, *b44_gstrings, sizeof(b44_gstrings)); + break; + } +} + +static int b44_get_stats_count(struct net_device *dev) +{ + return ARRAY_SIZE(b44_gstrings); +} + +static void b44_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *data) +{ + struct b44 *bp = netdev_priv(dev); + u32 *val = &bp->hw_stats.tx_good_octets; + u32 i; + + spin_lock_irq(&bp->lock); + + b44_stats_update(bp); + + for (i = 0; i < ARRAY_SIZE(b44_gstrings); i++) + *data++ = *val++; + + spin_unlock_irq(&bp->lock); +} + static struct ethtool_ops b44_ethtool_ops = { .get_drvinfo = b44_get_drvinfo, .get_settings = b44_get_settings, @@ -1784,6 +1824,9 @@ static struct ethtool_ops b44_ethtool_ops = { .set_pauseparam = b44_set_pauseparam, .get_msglevel = b44_get_msglevel, .set_msglevel = b44_set_msglevel, + .get_strings = b44_get_strings, + .get_stats_count = b44_get_stats_count, + .get_ethtool_stats = b44_get_ethtool_stats, .get_perm_addr = ethtool_op_get_perm_addr, }; diff --git a/drivers/net/b44.h b/drivers/net/b44.h index 593cb0ad410..7afeaf60823 100644 --- a/drivers/net/b44.h +++ b/drivers/net/b44.h @@ -346,29 +346,63 @@ struct ring_info { #define B44_MCAST_TABLE_SIZE 32 +#define B44_STAT_REG_DECLARE \ + _B44(tx_good_octets) \ + _B44(tx_good_pkts) \ + _B44(tx_octets) \ + _B44(tx_pkts) \ + _B44(tx_broadcast_pkts) \ + _B44(tx_multicast_pkts) \ + _B44(tx_len_64) \ + _B44(tx_len_65_to_127) \ + _B44(tx_len_128_to_255) \ + _B44(tx_len_256_to_511) \ + _B44(tx_len_512_to_1023) \ + _B44(tx_len_1024_to_max) \ + _B44(tx_jabber_pkts) \ + _B44(tx_oversize_pkts) \ + _B44(tx_fragment_pkts) \ + _B44(tx_underruns) \ + _B44(tx_total_cols) \ + _B44(tx_single_cols) \ + _B44(tx_multiple_cols) \ + _B44(tx_excessive_cols) \ + _B44(tx_late_cols) \ + _B44(tx_defered) \ + _B44(tx_carrier_lost) \ + _B44(tx_pause_pkts) \ + _B44(rx_good_octets) \ + _B44(rx_good_pkts) \ + _B44(rx_octets) \ + _B44(rx_pkts) \ + _B44(rx_broadcast_pkts) \ + _B44(rx_multicast_pkts) \ + _B44(rx_len_64) \ + _B44(rx_len_65_to_127) \ + _B44(rx_len_128_to_255) \ + _B44(rx_len_256_to_511) \ + _B44(rx_len_512_to_1023) \ + _B44(rx_len_1024_to_max) \ + _B44(rx_jabber_pkts) \ + _B44(rx_oversize_pkts) \ + _B44(rx_fragment_pkts) \ + _B44(rx_missed_pkts) \ + _B44(rx_crc_align_errs) \ + _B44(rx_undersize) \ + _B44(rx_crc_errs) \ + _B44(rx_align_errs) \ + _B44(rx_symbol_errs) \ + _B44(rx_pause_pkts) \ + _B44(rx_nonpause_pkts) + /* SW copy of device statistics, kept up to date by periodic timer - * which probes HW values. Must have same relative layout as HW - * register above, because b44_stats_update depends upon this. + * which probes HW values. Check b44_stats_update if you mess with + * the layout */ struct b44_hw_stats { - u32 tx_good_octets, tx_good_pkts, tx_octets; - u32 tx_pkts, tx_broadcast_pkts, tx_multicast_pkts; - u32 tx_len_64, tx_len_65_to_127, tx_len_128_to_255; - u32 tx_len_256_to_511, tx_len_512_to_1023, tx_len_1024_to_max; - u32 tx_jabber_pkts, tx_oversize_pkts, tx_fragment_pkts; - u32 tx_underruns, tx_total_cols, tx_single_cols; - u32 tx_multiple_cols, tx_excessive_cols, tx_late_cols; - u32 tx_defered, tx_carrier_lost, tx_pause_pkts; - u32 __pad1[8]; - - u32 rx_good_octets, rx_good_pkts, rx_octets; - u32 rx_pkts, rx_broadcast_pkts, rx_multicast_pkts; - u32 rx_len_64, rx_len_65_to_127, rx_len_128_to_255; - u32 rx_len_256_to_511, rx_len_512_to_1023, rx_len_1024_to_max; - u32 rx_jabber_pkts, rx_oversize_pkts, rx_fragment_pkts; - u32 rx_missed_pkts, rx_crc_align_errs, rx_undersize; - u32 rx_crc_errs, rx_align_errs, rx_symbol_errs; - u32 rx_pause_pkts, rx_nonpause_pkts; +#define _B44(x) u32 x; +B44_STAT_REG_DECLARE +#undef _B44 }; struct b44 { -- cgit v1.2.3 From 65b984f26f16e97168ee29e53145055412f38a23 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Mon, 7 Nov 2005 01:52:06 +0100 Subject: [PATCH] b44: s/spin_lock_irqsave/spin_lock/ in b44_interrupt There is no need to save/restore the irq state as the irq are always locally disabled when b44_interrupt is issued. Signed-off-by: Francois Romieu Signed-off-by: Jeff Garzik --- drivers/net/b44.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/b44.c b/drivers/net/b44.c index ac223fcf986..09e1b4deae5 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -895,11 +895,10 @@ static irqreturn_t b44_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = dev_id; struct b44 *bp = netdev_priv(dev); - unsigned long flags; u32 istat, imask; int handled = 0; - spin_lock_irqsave(&bp->lock, flags); + spin_lock(&bp->lock); istat = br32(bp, B44_ISTAT); imask = br32(bp, B44_IMASK); @@ -925,7 +924,7 @@ static irqreturn_t b44_interrupt(int irq, void *dev_id, struct pt_regs *regs) bw32(bp, B44_ISTAT, istat); br32(bp, B44_ISTAT); } - spin_unlock_irqrestore(&bp->lock, flags); + spin_unlock(&bp->lock); return IRQ_RETVAL(handled); } -- cgit v1.2.3 From 6c2f4267833f453156f8f439cc32eb4c92f357b4 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Mon, 7 Nov 2005 01:52:57 +0100 Subject: [PATCH] b44: late request_irq in b44_open Don't request_irq before the registers are reset/init. Signed-off-by: Francois Romieu Signed-off-by: Jeff Garzik --- drivers/net/b44.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 09e1b4deae5..ecc2e32c38c 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1388,13 +1388,7 @@ static int b44_open(struct net_device *dev) err = b44_alloc_consistent(bp); if (err) - return err; - - err = request_irq(dev->irq, b44_interrupt, SA_SHIRQ, dev->name, dev); - if (err) - goto err_out_free; - - spin_lock_irq(&bp->lock); + goto out; b44_init_rings(bp); b44_init_hw(bp); @@ -1403,7 +1397,13 @@ static int b44_open(struct net_device *dev) netif_carrier_off(dev); b44_check_phy(bp); - spin_unlock_irq(&bp->lock); + err = request_irq(dev->irq, b44_interrupt, SA_SHIRQ, dev->name, dev); + if (unlikely(err < 0)) { + b44_chip_reset(bp); + b44_free_rings(bp); + b44_free_consistent(bp); + goto out; + } init_timer(&bp->timer); bp->timer.expires = jiffies + HZ; @@ -1412,11 +1412,7 @@ static int b44_open(struct net_device *dev) add_timer(&bp->timer); b44_enable_ints(bp); - - return 0; - -err_out_free: - b44_free_consistent(bp); +out: return err; } -- cgit v1.2.3 From ea17629f3e6f64591a98a9049a0d725d2672509c Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 7 Nov 2005 08:09:05 +0000 Subject: [MTD] maps ixp2000: fix compile warnings in ixp2000 map driver Fix two compile warnings that occur because of treating two 'unsigned long's as 'void *'s. Signed-off-by: Lennert Buytenhek Signed-off-by: Thomas Gleixner --- drivers/mtd/maps/ixp2000.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c index 00b9f67580f..78c68f49be8 100644 --- a/drivers/mtd/maps/ixp2000.c +++ b/drivers/mtd/maps/ixp2000.c @@ -1,5 +1,5 @@ /* - * $Id: ixp2000.c,v 1.6 2005/03/18 14:07:46 gleixner Exp $ + * $Id: ixp2000.c,v 1.8 2005/11/07 08:09:02 gleixner Exp $ * * drivers/mtd/maps/ixp2000.c * @@ -193,7 +193,7 @@ static int ixp2000_flash_probe(struct device *_dev) /* * map_priv_2 is used to store a ptr to to the bank_setup routine */ - info->map.map_priv_2 = (void __iomem *) ixp_data->bank_setup; + info->map.map_priv_2 = (unsigned long) ixp_data->bank_setup; info->map.name = dev->dev.bus_id; info->map.read = ixp2000_flash_read8; @@ -210,7 +210,7 @@ static int ixp2000_flash_probe(struct device *_dev) goto Error; } - info->map.map_priv_1 = ioremap(dev->resource->start, + info->map.map_priv_1 = (unsigned long) ioremap(dev->resource->start, dev->resource->end - dev->resource->start + 1); if (!info->map.map_priv_1) { dev_err(_dev, "Failed to ioremap flash region\n"); -- cgit v1.2.3 From be30c10fd8015a00c97c9b473263fe3c581389de Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Mon, 7 Nov 2005 08:33:38 +0000 Subject: [MTD] maps: Add support for the "TQM834x" Boards The following patch adds support for the TQ Systems TQM834x Boards. Verified on TQM8349L. This is a resubmit after integrating the suggested changes. Signed-off-by: Marian Balakowicz Signed-off-by: Wolfgang Denk Signed-off-by: Thomas Gleixner --- drivers/mtd/maps/Kconfig | 10 +- drivers/mtd/maps/Makefile | 3 +- drivers/mtd/maps/tqm834x.c | 291 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 302 insertions(+), 2 deletions(-) create mode 100644 drivers/mtd/maps/tqm834x.c diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 94a693f4bea..e12e36a003d 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -1,5 +1,5 @@ # drivers/mtd/maps/Kconfig -# $Id: Kconfig,v 1.59 2005/09/18 10:46:41 joern Exp $ +# $Id: Kconfig,v 1.60 2005/11/07 08:33:35 gleixner Exp $ menu "Mapping drivers for chip access" depends on MTD!=n @@ -347,6 +347,14 @@ config MTD_REDWOOD Redwood board. If you have one of these boards and would like to use the flash chips on it, say 'Y'. +config MTD_TQM834x + tristate "Flash device mapped on TQ Components TQM834x Boards" + depends on MTD_CFI && TQM834x + help + This enables access routines for the flash chips on the + TQ Components TQM834x boards. If you have one of these boards + and would like to use the flash chips on it, say 'Y'. + config MTD_CSTM_MIPS_IXX tristate "Flash chip mapping on ITE QED-4N-S01B, Globespan IVR or custom board" depends on MIPS && MTD_CFI && MTD_JEDECPROBE && MTD_PARTITIONS diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index 2afa80678d5..81f97c60e0c 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -1,7 +1,7 @@ # # linux/drivers/maps/Makefile # -# $Id: Makefile.common,v 1.32 2005/09/18 10:46:41 joern Exp $ +# $Id: Makefile.common,v 1.33 2005/11/07 08:33:35 gleixner Exp $ ifeq ($(CONFIG_MTD_COMPLEX_MAPPINGS),y) obj-$(CONFIG_MTD) += map_funcs.o @@ -72,3 +72,4 @@ obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o obj-$(CONFIG_MTD_OMAP_NOR) += omap_nor.o obj-$(CONFIG_MTD_PQ2FADS) += pq2fads.o obj-$(CONFIG_MTD_MTX1) += mtx-1_flash.o +obj-$(CONFIG_MTD_TQM834x) += tqm834x.o diff --git a/drivers/mtd/maps/tqm834x.c b/drivers/mtd/maps/tqm834x.c new file mode 100644 index 00000000000..d0bc9593cb4 --- /dev/null +++ b/drivers/mtd/maps/tqm834x.c @@ -0,0 +1,291 @@ +/* + * drivers/mtd/maps/tqm834x.c + * + * MTD mapping driver for TQM834x boards + * + * Copyright 2005 Wolfgang Denk, DENX Software Engineering, . + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define FLASH_BANK_MAX 2 + +extern unsigned char __res[]; + +/* trivial struct to describe partition information */ +struct mtd_part_def +{ + int nums; + unsigned char *type; + struct mtd_partition* mtd_part; +}; + +static struct mtd_info* mtd_banks[FLASH_BANK_MAX]; +static struct map_info* map_banks[FLASH_BANK_MAX]; +static struct mtd_part_def part_banks[FLASH_BANK_MAX]; + +static unsigned long num_banks; +static unsigned long start_scan_addr; + +#ifdef CONFIG_MTD_PARTITIONS +/* + * The following defines the partition layout of TQM834x boards. + * + * See include/linux/mtd/partitions.h for definition of the + * mtd_partition structure. + * + * Assume minimal initial size of 4 MiB per bank, will be updated + * later in init_tqm834x_mtd() routine. + */ + +/* Partition definition for the first flash bank which is always present. */ +static struct mtd_partition tqm834x_partitions_bank1[] = { + { + .name = "u-boot", /* u-boot firmware */ + .offset = 0x00000000, + .size = 0x00040000, /* 256 KiB */ + /*mask_flags: MTD_WRITEABLE, * force read-only */ + }, + { + .name = "env", /* u-boot environment */ + .offset = 0x00040000, + .size = 0x00020000, /* 128 KiB */ + /*mask_flags: MTD_WRITEABLE, * force read-only */ + }, + { + .name = "kernel", /* linux kernel image */ + .offset = 0x00060000, + .size = 0x00100000, /* 1 MiB */ + /*mask_flags: MTD_WRITEABLE, * force read-only */ + }, + { + .name = "initrd", /* ramdisk image */ + .offset = 0x00160000, + .size = 0x00200000, /* 2 MiB */ + }, + { + .name = "user", /* user data */ + .offset = 0x00360000, + .size = 0x000a0000, /* remaining space */ + /* NOTE: this parttion size is re-calcated in */ + /* init_tqm834x_mtd() to cover actual remaining space. */ + }, +}; + +/* Partition definition for the second flash bank which may be present on some + * TQM834x boards. + */ +static struct mtd_partition tqm834x_partitions_bank2[] = { + { + .name = "jffs2", /* jffs2 filesystem */ + .offset = 0x00000000, + .size = 0x00400000, /* whole device */ + /* NOTE: this parttion size is re-calcated in */ + /* init_tqm834x_mtd() to cover actual device size. */ + }, +}; + +#endif /* CONFIG_MTD_PARTITIONS */ + +static int __init init_tqm834x_mtd(void) +{ + int idx = 0, ret = 0; + unsigned long flash_addr, flash_size, mtd_size = 0; + + /* pointer to TQM834x board info data */ + bd_t *bd = (bd_t *)__res; +#ifdef CONFIG_MTD_CMDLINE_PARTS + int n; + char mtdid[4]; + const char *part_probes[] = { "cmdlinepart", NULL }; +#endif + + flash_addr = bd->bi_flashstart; + flash_size = bd->bi_flashsize; + + /* request maximum flash size address space */ + start_scan_addr = (unsigned long)ioremap(flash_addr, flash_size); + if (!start_scan_addr) { + printk("%s: Failed to ioremap address: 0x%lx\n", + __FUNCTION__, flash_addr); + return -EIO; + } + + for(idx = 0 ; idx < FLASH_BANK_MAX ; idx++) { + if (mtd_size >= flash_size) + break; + + pr_debug("%s: chip probing count %d\n", __FUNCTION__, idx); + + map_banks[idx] = + (struct map_info *)kmalloc(sizeof(struct map_info), + GFP_KERNEL); + if (map_banks[idx] == NULL) { + ret = -ENOMEM; + goto error_mem; + } + memset((void *)map_banks[idx], 0, sizeof(struct map_info)); + map_banks[idx]->name = (char *)kmalloc(16, GFP_KERNEL); + if (map_banks[idx]->name == NULL) { + ret = -ENOMEM; + goto error_mem; + } + memset((void *)map_banks[idx]->name, 0, 16); + + sprintf(map_banks[idx]->name, "TQM834x-%d", idx); + map_banks[idx]->size = flash_size; + map_banks[idx]->bankwidth = 4; + + simple_map_init(map_banks[idx]); + + map_banks[idx]->virt = (void __iomem *) + (start_scan_addr + ((idx > 0) ? + (mtd_banks[idx-1] ? mtd_banks[idx-1]->size : 0) : 0)); + map_banks[idx]->phys = + flash_addr + ((idx > 0) ? + (mtd_banks[idx-1] ? mtd_banks[idx-1]->size : 0) : 0); + + /* start to probe flash chips */ + mtd_banks[idx] = do_map_probe("cfi_probe", map_banks[idx]); + if (mtd_banks[idx]) { + mtd_banks[idx]->owner = THIS_MODULE; + mtd_size += mtd_banks[idx]->size; + num_banks++; + pr_debug("%s: bank %ld, name: %s, size: %d bytes \n", + __FUNCTION__, num_banks, + mtd_banks[idx]->name, mtd_banks[idx]->size); + } + } + + /* no supported flash chips found */ + if (!num_banks) { + printk("TQM834x: No supported flash chips found!\n"); + ret = -ENXIO; + goto error_mem; + } + +#ifdef CONFIG_MTD_PARTITIONS + /* + * Select static partition definitions + */ + n = ARRAY_SIZE(tqm834x_partitions_bank1); + part_banks[0].mtd_part = tqm834x_partitions_bank1; + part_banks[0].type = "static image bank1"; + part_banks[0].nums = n; + + /* update last partition size to cover actual remaining space */ + tqm834x_partitions_bank1[n - 1].size = + mtd_banks[0]->size - + tqm834x_partitions_bank1[n - 1].offset; + + /* check if we have second bank? */ + if (num_banks == 2) { + n = ARRAY_SIZE(tqm834x_partitions_bank2); + part_banks[1].mtd_part = tqm834x_partitions_bank2; + part_banks[1].type = "static image bank2"; + part_banks[1].nums = n; + + /* update last partition size to cover actual remaining space */ + tqm834x_partitions_bank2[n - 1].size = + mtd_banks[1]->size - + tqm834x_partitions_bank2[n - 1].offset; + } + + for(idx = 0; idx < num_banks ; idx++) { +#ifdef CONFIG_MTD_CMDLINE_PARTS + sprintf(mtdid, "%d", idx); + n = parse_mtd_partitions(mtd_banks[idx], + part_probes, + &part_banks[idx].mtd_part, + 0); + pr_debug("%s: %d command line partitions on bank %s\n", + __FUNCTION__, n, mtdid); + if (n > 0) { + part_banks[idx].type = "command line"; + part_banks[idx].nums = n; + } +#endif /* CONFIG_MTD_CMDLINE_PARTS */ + if (part_banks[idx].nums == 0) { + printk(KERN_NOTICE + "TQM834x flash bank %d: no partition info " + "available, registering whole device\n", idx); + add_mtd_device(mtd_banks[idx]); + } else { + printk(KERN_NOTICE + "TQM834x flash bank %d: Using %s partition " + "definition\n", idx, part_banks[idx].type); + add_mtd_partitions(mtd_banks[idx], + part_banks[idx].mtd_part, + part_banks[idx].nums); + } + } +#else /* ! CONFIG_MTD_PARTITIONS */ + printk(KERN_NOTICE "TQM834x flash: registering %d flash banks " + "at once\n", num_banks); + + for(idx = 0 ; idx < num_banks ; idx++) + add_mtd_device(mtd_banks[idx]); + +#endif /* CONFIG_MTD_PARTITIONS */ + + return 0; +error_mem: + for (idx = 0 ; idx < FLASH_BANK_MAX ; idx++) { + if (map_banks[idx] != NULL) { + if (map_banks[idx]->name != NULL) { + kfree(map_banks[idx]->name); + map_banks[idx]->name = NULL; + } + kfree(map_banks[idx]); + map_banks[idx] = NULL; + } + } + + iounmap((void *)start_scan_addr); + + return ret; +} + +static void __exit cleanup_tqm834x_mtd(void) +{ + unsigned int idx = 0; + for(idx = 0 ; idx < num_banks ; idx++) { + /* destroy mtd_info previously allocated */ + if (mtd_banks[idx]) { + del_mtd_partitions(mtd_banks[idx]); + map_destroy(mtd_banks[idx]); + } + + /* release map_info not used anymore */ + kfree(map_banks[idx]->name); + kfree(map_banks[idx]); + } + + if (start_scan_addr) { + iounmap((void *)start_scan_addr); + start_scan_addr = 0; + } +} + +module_init(init_tqm834x_mtd); +module_exit(cleanup_tqm834x_mtd); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Wolfgang Denk "); +MODULE_DESCRIPTION("MTD map driver for TQM834x boards"); -- cgit v1.2.3 From b95f9609c761a14d1e7be1a89f2a66399b5ae343 Mon Sep 17 00:00:00 2001 From: Konstantin Baidarov Date: Mon, 7 Nov 2005 09:00:05 +0000 Subject: [MTD] chips cfi_cmdset_0002: Prevent timeout race We've noticed that sometimes "MTD do_write_buffer(): software timeout" message was printed out when writing to a Fujitsu NOR flash. It turned out that this was because of a race in the timeout handling do_write_buffer(). A small timeout of (HZ / 1000) + 1 is used there, and sometimes if the timer interrupt handling takes more than one or even two jiffies (which is 1-2 ms with HZ == 1000) and that interrupt happens just after chip_ready() call, the driver bails out from a ready polling loop despite the chip has actually become ready while all those interrupts were handled. To deal with this issue, extra check for chip ready is neccessary on timeout expiration (and the checks should better be reordered). As do_write_oneword() uses the same approach, it needs to also be changed. Signed-off-by: Konstantin Baidarov Signed-off-by: Sergei Shtylyov Signed-off-by: Thomas Gleixner --- drivers/mtd/chips/cfi_cmdset_0002.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index e3d31c74904..50dd7d2f096 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -17,7 +17,7 @@ * * This code is GPL * - * $Id: cfi_cmdset_0002.c,v 1.120 2005/07/20 21:01:13 tpoynor Exp $ + * $Id: cfi_cmdset_0002.c,v 1.121 2005/11/07 09:00:01 gleixner Exp $ * */ @@ -1014,16 +1014,16 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, continue; } - if (chip_ready(map, adr)) - break; - - if (time_after(jiffies, timeo)) { + if (time_after(jiffies, timeo) && !chip_ready(map, adr)){ xip_enable(map, chip, adr); printk(KERN_WARNING "MTD %s(): software timeout\n", __func__); xip_disable(map, chip, adr); - break; + break; } + if (chip_ready(map, adr)) + break; + /* Latency issues. Drop the lock, wait a while and retry */ UDELAY(map, chip, adr, 1); } @@ -1275,13 +1275,13 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, continue; } + if (time_after(jiffies, timeo) && !chip_ready(map, adr)) + break; + if (chip_ready(map, adr)) { xip_enable(map, chip, adr); goto op_done; } - - if( time_after(jiffies, timeo)) - break; /* Latency issues. Drop the lock, wait a while and retry */ UDELAY(map, chip, adr, 1); -- cgit v1.2.3 From cd03adb0812fe0fb06cdb935e61ec9514254e951 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 7 Nov 2005 10:10:28 +0000 Subject: [ARM SMP] Add support for shared memory attribute We need to set the shared memory attribute in the page tables on SMP systems to allow the cache coherency to operate. Signed-off-by: Russell King --- arch/arm/mm/mm-armv.c | 48 ++++++++++++++++++++++++++++++++---------------- arch/arm/mm/proc-v6.S | 8 +++++++- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index fb5b40289de..9e50127be63 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c @@ -354,7 +354,7 @@ void __init build_mem_type_table(void) { struct cachepolicy *cp; unsigned int cr = get_cr(); - unsigned int user_pgprot; + unsigned int user_pgprot, kern_pgprot; int cpu_arch = cpu_architecture(); int i; @@ -381,7 +381,7 @@ void __init build_mem_type_table(void) } cp = &cache_policies[cachepolicy]; - user_pgprot = cp->pte; + kern_pgprot = user_pgprot = cp->pte; /* * ARMv6 and above have extended page tables. @@ -393,6 +393,7 @@ void __init build_mem_type_table(void) */ mem_types[MT_MEMORY].prot_sect &= ~PMD_BIT4; mem_types[MT_ROM].prot_sect &= ~PMD_BIT4; + /* * Mark cache clean areas and XIP ROM read only * from SVC mode and no access from userspace. @@ -412,32 +413,47 @@ void __init build_mem_type_table(void) * (iow, non-global) */ user_pgprot |= L_PTE_ASID; + +#ifdef CONFIG_SMP + /* + * Mark memory with the "shared" attribute for SMP systems + */ + user_pgprot |= L_PTE_SHARED; + kern_pgprot |= L_PTE_SHARED; + mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; +#endif } + for (i = 0; i < 16; i++) { + unsigned long v = pgprot_val(protection_map[i]); + v = (v & ~(L_PTE_BUFFERABLE|L_PTE_CACHEABLE)) | user_pgprot; + protection_map[i] = __pgprot(v); + } + + mem_types[MT_LOW_VECTORS].prot_pte |= kern_pgprot; + mem_types[MT_HIGH_VECTORS].prot_pte |= kern_pgprot; + if (cpu_arch >= CPU_ARCH_ARMv5) { - mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE; - mem_types[MT_HIGH_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE; +#ifndef CONFIG_SMP + /* + * Only use write-through for non-SMP systems + */ + mem_types[MT_LOW_VECTORS].prot_pte &= ~L_PTE_BUFFERABLE; + mem_types[MT_HIGH_VECTORS].prot_pte &= ~L_PTE_BUFFERABLE; +#endif } else { - mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte; - mem_types[MT_HIGH_VECTORS].prot_pte |= cp->pte; mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1); } + pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | + L_PTE_DIRTY | L_PTE_WRITE | + L_PTE_EXEC | kern_pgprot); + mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd; mem_types[MT_ROM].prot_sect |= cp->pmd; - for (i = 0; i < 16; i++) { - unsigned long v = pgprot_val(protection_map[i]); - v = (v & ~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot; - protection_map[i] = __pgprot(v); - } - - pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | - L_PTE_DIRTY | L_PTE_WRITE | - L_PTE_EXEC | cp->pte); - switch (cp->pmd) { case PMD_SECT_WT: mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WT; diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 9bb5fff406f..a39d8fa2ede 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -112,6 +112,9 @@ ENTRY(cpu_v6_dcache_clean_area) ENTRY(cpu_v6_switch_mm) mov r2, #0 ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id +#ifdef CONFIG_SMP + orr r0, r0, #2 @ set shared pgtable +#endif mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB mcr p15, 0, r2, c7, c10, 4 @ drain write buffer mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 @@ -140,7 +143,7 @@ ENTRY(cpu_v6_switch_mm) ENTRY(cpu_v6_set_pte) str r1, [r0], #-2048 @ linux version - bic r2, r1, #0x000007f0 + bic r2, r1, #0x000003f0 bic r2, r2, #0x00000003 orr r2, r2, #PTE_EXT_AP0 | 2 @@ -198,6 +201,9 @@ __v6_setup: mcr p15, 0, r0, c7, c10, 4 @ drain write buffer mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs mcr p15, 0, r0, c2, c0, 2 @ TTB control register +#ifdef CONFIG_SMP + orr r4, r4, #2 @ set shared pgtable +#endif mcr p15, 0, r4, c2, c0, 1 @ load TTB1 #ifdef CONFIG_VFP mrc p15, 0, r0, c1, c0, 2 -- cgit v1.2.3 From c3348760aaffd268f7e91b2185999025fdc5607f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 7 Nov 2005 11:14:57 +0100 Subject: [PATCH] Fix wrong irq enable via rtc_control() rtc_control() may be called in the interrupt context in ALSA rtc-timer driver. The patch fixes the wrong irq enable in rtc.c, and also fixes the possible race of bit flags. Signed-off-by: Takashi Iwai --- drivers/char/rtc.c | 65 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 27 deletions(-) diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 63fff7c1244..a7f099fb7df 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -149,8 +149,22 @@ static void get_rtc_alm_time (struct rtc_time *alm_tm); #ifdef RTC_IRQ static void rtc_dropped_irq(unsigned long data); -static void set_rtc_irq_bit(unsigned char bit); -static void mask_rtc_irq_bit(unsigned char bit); +static void set_rtc_irq_bit_locked(unsigned char bit); +static void mask_rtc_irq_bit_locked(unsigned char bit); + +static inline void set_rtc_irq_bit(unsigned char bit) +{ + spin_lock_irq(&rtc_lock); + set_rtc_irq_bit_locked(bit); + spin_unlock_irq(&rtc_lock); +} + +static void mask_rtc_irq_bit(unsigned char bit) +{ + spin_lock_irq(&rtc_lock); + mask_rtc_irq_bit_locked(bit); + spin_unlock_irq(&rtc_lock); +} #endif static int rtc_proc_open(struct inode *inode, struct file *file); @@ -401,18 +415,19 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) } case RTC_PIE_OFF: /* Mask periodic int. enab. bit */ { - mask_rtc_irq_bit(RTC_PIE); + unsigned long flags; /* can be called from isr via rtc_control() */ + spin_lock_irqsave (&rtc_lock, flags); + mask_rtc_irq_bit_locked(RTC_PIE); if (rtc_status & RTC_TIMER_ON) { - spin_lock_irq (&rtc_lock); rtc_status &= ~RTC_TIMER_ON; del_timer(&rtc_irq_timer); - spin_unlock_irq (&rtc_lock); } + spin_unlock_irqrestore (&rtc_lock, flags); return 0; } case RTC_PIE_ON: /* Allow periodic ints */ { - + unsigned long flags; /* can be called from isr via rtc_control() */ /* * We don't really want Joe User enabling more * than 64Hz of interrupts on a multi-user machine. @@ -421,14 +436,14 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) (!capable(CAP_SYS_RESOURCE))) return -EACCES; + spin_lock_irqsave (&rtc_lock, flags); if (!(rtc_status & RTC_TIMER_ON)) { - spin_lock_irq (&rtc_lock); rtc_irq_timer.expires = jiffies + HZ/rtc_freq + 2*HZ/100; add_timer(&rtc_irq_timer); rtc_status |= RTC_TIMER_ON; - spin_unlock_irq (&rtc_lock); } - set_rtc_irq_bit(RTC_PIE); + set_rtc_irq_bit_locked(RTC_PIE); + spin_unlock_irqrestore (&rtc_lock, flags); return 0; } case RTC_UIE_OFF: /* Mask ints from RTC updates. */ @@ -609,6 +624,7 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) { int tmp = 0; unsigned char val; + unsigned long flags; /* can be called from isr via rtc_control() */ /* * The max we can do is 8192Hz. @@ -631,9 +647,9 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) if (arg != (1< Date: Mon, 7 Nov 2005 11:22:04 +0100 Subject: [ALSA] Cleanup - remove sound/core/wrappers.c Signed-off-by: Jaroslav Kysela --- sound/core/wrappers.c | 40 ---------------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 sound/core/wrappers.c diff --git a/sound/core/wrappers.c b/sound/core/wrappers.c deleted file mode 100644 index 19e899089cb..00000000000 --- a/sound/core/wrappers.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Various wrappers - * Copyright (c) by Jaroslav Kysela - * - * - * 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 option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_SND_DEBUG_MEMORY -void *snd_wrapper_kmalloc(size_t size, gfp_t flags) -{ - return kmalloc(size, flags); -} - -void snd_wrapper_kfree(const void *obj) -{ - kfree(obj); -} -#endif - -- cgit v1.2.3 From 63786d064ca7dd7ccaf29d2a46ad269ad2df8041 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 4 Nov 2005 13:58:11 +0100 Subject: [ALSA] ice1724 - Fix ADC mux put callback in aureon.c Modules: ICE1712 driver Fix the return value of ADC mux put callback in aureon.c. Signed-off-by: Takashi Iwai --- sound/pci/ice1712/aureon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c index 40b48186767..db12b038286 100644 --- a/sound/pci/ice1712/aureon.c +++ b/sound/pci/ice1712/aureon.c @@ -960,7 +960,7 @@ static int wm_adc_mux_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucont if (change) wm_put(ice, WM_ADC_MUX, nval); snd_ice1712_restore_gpio_status(ice); - return 0; + return change; } /* -- cgit v1.2.3 From 01bbaf0b2b7b38e43139dce8bd64f8c7b2b83940 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 7 Nov 2005 10:30:16 +0000 Subject: [ARM] realview core.h uses leds_event_t, so include asm/leds.h Signed-off-by: Russell King --- arch/arm/mach-realview/core.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h index 575599db74d..d83e8bad203 100644 --- a/arch/arm/mach-realview/core.h +++ b/arch/arm/mach-realview/core.h @@ -23,6 +23,7 @@ #define __ASM_ARCH_REALVIEW_H #include +#include #include #define __io_address(n) __io(IO_ADDRESS(n)) -- cgit v1.2.3 From 97894cda5773e59bd13e87b72077751099419a9f Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 11:15:26 +0000 Subject: [MTD] core: Clean up trailing white spaces Signed-off-by: Thomas Gleixner --- drivers/mtd/Kconfig | 32 ++++++------ drivers/mtd/afs.c | 16 +++--- drivers/mtd/cmdlinepart.c | 56 ++++++++++---------- drivers/mtd/ftl.c | 128 +++++++++++++++++++++++----------------------- drivers/mtd/inftlcore.c | 48 ++++++++--------- drivers/mtd/inftlmount.c | 20 ++++---- drivers/mtd/mtd_blkdevs.c | 24 ++++----- drivers/mtd/mtdblock.c | 44 ++++++++-------- drivers/mtd/mtdchar.c | 60 +++++++++++----------- drivers/mtd/mtdconcat.c | 6 +-- drivers/mtd/mtdcore.c | 18 +++---- drivers/mtd/mtdpart.c | 92 ++++++++++++++++----------------- drivers/mtd/nftlcore.c | 80 ++++++++++++++--------------- drivers/mtd/nftlmount.c | 56 ++++++++++---------- drivers/mtd/redboot.c | 4 +- drivers/mtd/rfd_ftl.c | 114 ++++++++++++++++++++--------------------- 16 files changed, 399 insertions(+), 399 deletions(-) diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 3dbfbafb348..f6b775e63ac 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -1,4 +1,4 @@ -# $Id: Kconfig,v 1.10 2005/07/11 10:39:27 gleixner Exp $ +# $Id: Kconfig,v 1.11 2005/11/07 11:14:19 gleixner Exp $ menu "Memory Technology Devices (MTD)" @@ -10,7 +10,7 @@ config MTD will provide the generic support for MTD drivers to register themselves with the kernel and for potential users of MTD devices to enumerate the devices which are present and obtain a handle on - them. It will also allow you to select individual drivers for + them. It will also allow you to select individual drivers for particular hardware and users of MTD devices. If unsure, say N. config MTD_DEBUG @@ -61,11 +61,11 @@ config MTD_REDBOOT_PARTS If you need code which can detect and parse this table, and register MTD 'partitions' corresponding to each image in the table, enable - this option. + this option. You will still need the parsing functions to be called by the driver - for your particular device. It won't happen automatically. The - SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for + for your particular device. It won't happen automatically. The + SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for example. config MTD_REDBOOT_DIRECTORY_BLOCK @@ -81,10 +81,10 @@ config MTD_REDBOOT_DIRECTORY_BLOCK partition table. A zero or positive value gives an absolete erase block number. A negative value specifies a number of sectors before the end of the device. - + For example "2" means block number 2, "-1" means the last block and "-2" means the penultimate block. - + config MTD_REDBOOT_PARTS_UNALLOCATED bool " Include unallocated flash regions" depends on MTD_REDBOOT_PARTS @@ -105,11 +105,11 @@ config MTD_CMDLINE_PARTS ---help--- Allow generic configuration of the MTD paritition tables via the kernel command line. Multiple flash resources are supported for hardware where - different kinds of flash memory are available. + different kinds of flash memory are available. You will still need the parsing functions to be called by the driver - for your particular device. It won't happen automatically. The - SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for + for your particular device. It won't happen automatically. The + SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for example. The format for the command line is as follows: @@ -118,12 +118,12 @@ config MTD_CMDLINE_PARTS := :[,] := [@offset][][ro] := unique id used in mapping driver/device - := standard linux memsize OR "-" to denote all + := standard linux memsize OR "-" to denote all remaining space := (NAME) - Due to the way Linux handles the command line, no spaces are - allowed in the partition definition, including mtd id's and partition + Due to the way Linux handles the command line, no spaces are + allowed in the partition definition, including mtd id's and partition names. Examples: @@ -240,7 +240,7 @@ config INFTL tristate "INFTL (Inverse NAND Flash Translation Layer) support" depends on MTD ---help--- - This provides support for the Inverse NAND Flash Translation + This provides support for the Inverse NAND Flash Translation Layer which is used on M-Systems' newer DiskOnChip devices. It uses a kind of pseudo-file system on a flash device to emulate a block device with 512-byte sectors, on top of which you put @@ -257,8 +257,8 @@ config RFD_FTL tristate "Resident Flash Disk (Flash Translation Layer) support" depends on MTD ---help--- - This provides support for the flash translation layer known - as the Resident Flash Disk (RFD), as used by the Embedded BIOS + This provides support for the flash translation layer known + as the Resident Flash Disk (RFD), as used by the Embedded BIOS of General Software. There is a blurb at: http://www.gensw.com/pages/prod/bios/rfd.htm diff --git a/drivers/mtd/afs.c b/drivers/mtd/afs.c index 7363e101eb0..6a45be04564 100644 --- a/drivers/mtd/afs.c +++ b/drivers/mtd/afs.c @@ -1,27 +1,27 @@ /*====================================================================== drivers/mtd/afs.c: ARM Flash Layout/Partitioning - + Copyright (C) 2000 ARM Limited - + 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 option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - This is access code for flashes using ARM's flash partitioning + + This is access code for flashes using ARM's flash partitioning standards. - $Id: afs.c,v 1.13 2004/02/27 22:09:59 rmk Exp $ + $Id: afs.c,v 1.15 2005/11/07 11:14:19 gleixner Exp $ ======================================================================*/ @@ -163,7 +163,7 @@ afs_read_iis(struct mtd_info *mtd, struct image_info_struct *iis, u_int ptr) return ret; } -static int parse_afs_partitions(struct mtd_info *mtd, +static int parse_afs_partitions(struct mtd_info *mtd, struct mtd_partition **pparts, unsigned long origin) { diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c index ef24837019d..6b8bb2e4dcf 100644 --- a/drivers/mtd/cmdlinepart.c +++ b/drivers/mtd/cmdlinepart.c @@ -1,24 +1,24 @@ /* - * $Id: cmdlinepart.c,v 1.18 2005/06/07 15:04:26 joern Exp $ + * $Id: cmdlinepart.c,v 1.19 2005/11/07 11:14:19 gleixner Exp $ * * Read flash partition table from command line * * Copyright 2002 SYSGO Real-Time Solutions GmbH * * The format for the command line is as follows: - * + * * mtdparts=[; := :[,] * := [@offset][][ro] * := unique name used in mapping driver/device (mtd->name) * := standard linux memsize OR "-" to denote all remaining space * := '(' NAME ')' - * + * * Examples: - * + * * 1 NOR Flash, with 1 single writable partition: * edb7312-nor:- - * + * * 1 NOR Flash with 2 partitions, 1 NAND with one * edb7312-nor:256k(ARMboot)ro,-(root);edb7312-nand:-(home) */ @@ -60,17 +60,17 @@ static int cmdline_parsed = 0; /* * Parse one partition definition for an MTD. Since there can be many - * comma separated partition definitions, this function calls itself + * comma separated partition definitions, this function calls itself * recursively until no more partition definitions are found. Nice side * effect: the memory to keep the mtd_partition structs and the names * is allocated upon the last definition being found. At that point the * syntax has been verified ok. */ -static struct mtd_partition * newpart(char *s, +static struct mtd_partition * newpart(char *s, char **retptr, int *num_parts, - int this_part, - unsigned char **extra_mem_ptr, + int this_part, + unsigned char **extra_mem_ptr, int extra_mem_size) { struct mtd_partition *parts; @@ -102,7 +102,7 @@ static struct mtd_partition * newpart(char *s, mask_flags = 0; /* this is going to be a regular partition */ delim = 0; /* check for offset */ - if (*s == '@') + if (*s == '@') { s++; offset = memparse(s, &s); @@ -112,7 +112,7 @@ static struct mtd_partition * newpart(char *s, { delim = ')'; } - + if (delim) { char *p; @@ -131,12 +131,12 @@ static struct mtd_partition * newpart(char *s, name = NULL; name_len = 13; /* Partition_000 */ } - + /* record name length for memory allocation later */ extra_mem_size += name_len + 1; /* test for options */ - if (strncmp(s, "ro", 2) == 0) + if (strncmp(s, "ro", 2) == 0) { mask_flags |= MTD_WRITEABLE; s += 2; @@ -151,7 +151,7 @@ static struct mtd_partition * newpart(char *s, return NULL; } /* more partitions follow, parse them */ - if ((parts = newpart(s + 1, &s, num_parts, + if ((parts = newpart(s + 1, &s, num_parts, this_part + 1, &extra_mem, extra_mem_size)) == 0) return NULL; } @@ -187,7 +187,7 @@ static struct mtd_partition * newpart(char *s, extra_mem += name_len + 1; dbg(("partition %d: name <%s>, offset %x, size %x, mask flags %x\n", - this_part, + this_part, parts[this_part].name, parts[this_part].offset, parts[this_part].size, @@ -204,8 +204,8 @@ static struct mtd_partition * newpart(char *s, return parts; } -/* - * Parse the command line. +/* + * Parse the command line. */ static int mtdpart_setup_real(char *s) { @@ -230,7 +230,7 @@ static int mtdpart_setup_real(char *s) dbg(("parsing <%s>\n", p+1)); - /* + /* * parse one mtd. have it reserve memory for the * struct cmdline_mtd_partition and the mtd-id string. */ @@ -239,7 +239,7 @@ static int mtdpart_setup_real(char *s) &num_parts, /* out: number of parts */ 0, /* first partition */ (unsigned char**)&this_mtd, /* out: extra mem */ - mtd_id_len + 1 + sizeof(*this_mtd) + + mtd_id_len + 1 + sizeof(*this_mtd) + sizeof(void*)-1 /*alignment*/); if(!parts) { @@ -254,21 +254,21 @@ static int mtdpart_setup_real(char *s) } /* align this_mtd */ - this_mtd = (struct cmdline_mtd_partition *) + this_mtd = (struct cmdline_mtd_partition *) ALIGN((unsigned long)this_mtd, sizeof(void*)); - /* enter results */ + /* enter results */ this_mtd->parts = parts; this_mtd->num_parts = num_parts; this_mtd->mtd_id = (char*)(this_mtd + 1); strlcpy(this_mtd->mtd_id, mtd_id, mtd_id_len + 1); /* link into chain */ - this_mtd->next = partitions; + this_mtd->next = partitions; partitions = this_mtd; - dbg(("mtdid=<%s> num_parts=<%d>\n", + dbg(("mtdid=<%s> num_parts=<%d>\n", this_mtd->mtd_id, this_mtd->num_parts)); - + /* EOS - we're done */ if (*s == 0) @@ -292,7 +292,7 @@ static int mtdpart_setup_real(char *s) * information. It returns partitions for the requested mtd device, or * the first one in the chain if a NULL mtd_id is passed in. */ -static int parse_cmdline_partitions(struct mtd_info *master, +static int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, unsigned long origin) { @@ -322,7 +322,7 @@ static int parse_cmdline_partitions(struct mtd_info *master, part->parts[i].size = master->size - offset; if (offset + part->parts[i].size > master->size) { - printk(KERN_WARNING ERRP + printk(KERN_WARNING ERRP "%s: partitioning exceeds flash size, truncating\n", part->mtd_id); part->parts[i].size = master->size - offset; @@ -338,8 +338,8 @@ static int parse_cmdline_partitions(struct mtd_info *master, } -/* - * This is the handler for our kernel parameter, called from +/* + * This is the handler for our kernel parameter, called from * main.c::checksetup(). Note that we can not yet kmalloc() anything, * so we only save the commandline for later processing. * diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c index d32c1b3a8ce..de7e231d6d1 100644 --- a/drivers/mtd/ftl.c +++ b/drivers/mtd/ftl.c @@ -1,5 +1,5 @@ /* This version ported to the Linux-MTD system by dwmw2@infradead.org - * $Id: ftl.c,v 1.55 2005/01/17 13:47:21 hvr Exp $ + * $Id: ftl.c,v 1.58 2005/11/07 11:14:19 gleixner Exp $ * * Fixes: Arnaldo Carvalho de Melo * - fixes some leaks on failure in build_maps and ftl_notify_add, cleanups @@ -53,7 +53,7 @@ Use of the FTL format for non-PCMCIA applications may be an infringement of these patents. For additional information, contact M-Systems (http://www.m-sys.com) directly. - + ======================================================================*/ #include #include @@ -160,7 +160,7 @@ static void ftl_erase_callback(struct erase_info *done); Scan_header() checks to see if a memory region contains an FTL partition. build_maps() reads all the erase unit headers, builds the erase unit map, and then builds the virtual page map. - + ======================================================================*/ static int scan_header(partition_t *part) @@ -176,10 +176,10 @@ static int scan_header(partition_t *part) (offset + sizeof(header)) < max_offset; offset += part->mbd.mtd->erasesize ? : 0x2000) { - err = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &ret, + err = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &ret, (unsigned char *)&header); - - if (err) + + if (err) return err; if (strcmp(header.DataOrgTuple+3, "FTL100") == 0) break; @@ -232,10 +232,10 @@ static int build_maps(partition_t *part) for (i = 0; i < le16_to_cpu(part->header.NumEraseUnits); i++) { offset = ((i + le16_to_cpu(part->header.FirstPhysicalEUN)) << part->header.EraseUnitSize); - ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &retval, + ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &retval, (unsigned char *)&header); - - if (ret) + + if (ret) goto out_XferInfo; ret = -1; @@ -274,7 +274,7 @@ static int build_maps(partition_t *part) "don't add up!\n"); goto out_XferInfo; } - + /* Set up virtual page map */ blocks = le32_to_cpu(header.FormattedSize) >> header.BlockSize; part->VirtualBlockMap = vmalloc(blocks * sizeof(u_int32_t)); @@ -296,12 +296,12 @@ static int build_maps(partition_t *part) part->EUNInfo[i].Free = 0; part->EUNInfo[i].Deleted = 0; offset = part->EUNInfo[i].Offset + le32_to_cpu(header.BAMOffset); - - ret = part->mbd.mtd->read(part->mbd.mtd, offset, - part->BlocksPerUnit * sizeof(u_int32_t), &retval, + + ret = part->mbd.mtd->read(part->mbd.mtd, offset, + part->BlocksPerUnit * sizeof(u_int32_t), &retval, (unsigned char *)part->bam_cache); - - if (ret) + + if (ret) goto out_bam_cache; for (j = 0; j < part->BlocksPerUnit; j++) { @@ -316,7 +316,7 @@ static int build_maps(partition_t *part) part->EUNInfo[i].Deleted++; } } - + ret = 0; goto out; @@ -336,7 +336,7 @@ out: Erase_xfer() schedules an asynchronous erase operation for a transfer unit. - + ======================================================================*/ static int erase_xfer(partition_t *part, @@ -351,10 +351,10 @@ static int erase_xfer(partition_t *part, xfer->state = XFER_ERASING; /* Is there a free erase slot? Always in MTD. */ - - + + erase=kmalloc(sizeof(struct erase_info), GFP_KERNEL); - if (!erase) + if (!erase) return -ENOMEM; erase->mtd = part->mbd.mtd; @@ -362,7 +362,7 @@ static int erase_xfer(partition_t *part, erase->addr = xfer->Offset; erase->len = 1 << part->header.EraseUnitSize; erase->priv = (u_long)part; - + ret = part->mbd.mtd->erase(part->mbd.mtd, erase); if (!ret) @@ -377,7 +377,7 @@ static int erase_xfer(partition_t *part, Prepare_xfer() takes a freshly erased transfer unit and gives it an appropriate header. - + ======================================================================*/ static void ftl_erase_callback(struct erase_info *erase) @@ -385,7 +385,7 @@ static void ftl_erase_callback(struct erase_info *erase) partition_t *part; struct xfer_info_t *xfer; int i; - + /* Look up the transfer unit */ part = (partition_t *)(erase->priv); @@ -422,7 +422,7 @@ static int prepare_xfer(partition_t *part, int i) xfer = &part->XferInfo[i]; xfer->state = XFER_FAILED; - + DEBUG(1, "ftl_cs: preparing xfer unit at 0x%x\n", xfer->Offset); /* Write the transfer unit header */ @@ -446,7 +446,7 @@ static int prepare_xfer(partition_t *part, int i) for (i = 0; i < nbam; i++, offset += sizeof(u_int32_t)) { - ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int32_t), + ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int32_t), &retlen, (u_char *)&ctl); if (ret) @@ -454,7 +454,7 @@ static int prepare_xfer(partition_t *part, int i) } xfer->state = XFER_PREPARED; return 0; - + } /* prepare_xfer */ /*====================================================================== @@ -466,7 +466,7 @@ static int prepare_xfer(partition_t *part, int i) All data blocks are copied to the corresponding blocks in the target unit, so the virtual block map does not need to be updated. - + ======================================================================*/ static int copy_erase_unit(partition_t *part, u_int16_t srcunit, @@ -486,14 +486,14 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit, xfer = &part->XferInfo[xferunit]; DEBUG(2, "ftl_cs: copying block 0x%x to 0x%x\n", eun->Offset, xfer->Offset); - - + + /* Read current BAM */ if (part->bam_index != srcunit) { offset = eun->Offset + le32_to_cpu(part->header.BAMOffset); - ret = part->mbd.mtd->read(part->mbd.mtd, offset, + ret = part->mbd.mtd->read(part->mbd.mtd, offset, part->BlocksPerUnit * sizeof(u_int32_t), &retlen, (u_char *) (part->bam_cache)); @@ -501,11 +501,11 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit, part->bam_index = 0xffff; if (ret) { - printk( KERN_WARNING "ftl: Failed to read BAM cache in copy_erase_unit()!\n"); + printk( KERN_WARNING "ftl: Failed to read BAM cache in copy_erase_unit()!\n"); return ret; } } - + /* Write the LogicalEUN for the transfer unit */ xfer->state = XFER_UNKNOWN; offset = xfer->Offset + 20; /* Bad! */ @@ -513,12 +513,12 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit, ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int16_t), &retlen, (u_char *) &unit); - + if (ret) { printk( KERN_WARNING "ftl: Failed to write back to BAM cache in copy_erase_unit()!\n"); return ret; } - + /* Copy all data blocks from source unit to transfer unit */ src = eun->Offset; dest = xfer->Offset; @@ -558,15 +558,15 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit, } /* Write the BAM to the transfer unit */ - ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + le32_to_cpu(part->header.BAMOffset), - part->BlocksPerUnit * sizeof(int32_t), &retlen, + ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + le32_to_cpu(part->header.BAMOffset), + part->BlocksPerUnit * sizeof(int32_t), &retlen, (u_char *)part->bam_cache); if (ret) { printk( KERN_WARNING "ftl: Error writing BAM in copy_erase_unit\n"); return ret; } - + /* All clear? Then update the LogicalEUN again */ ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + 20, sizeof(u_int16_t), &retlen, (u_char *)&srcunitswap); @@ -574,9 +574,9 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit, if (ret) { printk(KERN_WARNING "ftl: Error writing new LogicalEUN in copy_erase_unit\n"); return ret; - } - - + } + + /* Update the maps and usage stats*/ i = xfer->EraseCount; xfer->EraseCount = eun->EraseCount; @@ -588,10 +588,10 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit, part->FreeTotal += free; eun->Free = free; eun->Deleted = 0; - + /* Now, the cache should be valid for the new block */ part->bam_index = srcunit; - + return 0; } /* copy_erase_unit */ @@ -608,7 +608,7 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit, oldest data unit instead. This means that we generally postpone the next reclaimation as long as possible, but shuffle static stuff around a bit for wear leveling. - + ======================================================================*/ static int reclaim_block(partition_t *part) @@ -666,7 +666,7 @@ static int reclaim_block(partition_t *part) else DEBUG(1, "ftl_cs: reclaim failed: no " "suitable transfer units!\n"); - + return -EIO; } } @@ -715,7 +715,7 @@ static int reclaim_block(partition_t *part) returns the block index -- the erase unit is just the currently cached unit. If there are no free blocks, it returns 0 -- this is never a valid data block because it contains the header. - + ======================================================================*/ #ifdef PSYCHO_DEBUG @@ -737,7 +737,7 @@ static u_int32_t find_free(partition_t *part) u_int32_t blk; size_t retlen; int ret; - + /* Find an erase unit with some free space */ stop = (part->bam_index == 0xffff) ? 0 : part->bam_index; eun = stop; @@ -749,17 +749,17 @@ static u_int32_t find_free(partition_t *part) if (part->EUNInfo[eun].Free == 0) return 0; - + /* Is this unit's BAM cached? */ if (eun != part->bam_index) { /* Invalidate cache */ part->bam_index = 0xffff; - ret = part->mbd.mtd->read(part->mbd.mtd, + ret = part->mbd.mtd->read(part->mbd.mtd, part->EUNInfo[eun].Offset + le32_to_cpu(part->header.BAMOffset), part->BlocksPerUnit * sizeof(u_int32_t), &retlen, (u_char *) (part->bam_cache)); - + if (ret) { printk(KERN_WARNING"ftl: Error reading BAM in find_free\n"); return 0; @@ -781,14 +781,14 @@ static u_int32_t find_free(partition_t *part) } DEBUG(2, "ftl_cs: found free block at %d in %d\n", blk, eun); return blk; - + } /* find_free */ /*====================================================================== Read a series of sectors from an FTL partition. - + ======================================================================*/ static int ftl_read(partition_t *part, caddr_t buffer, @@ -798,7 +798,7 @@ static int ftl_read(partition_t *part, caddr_t buffer, u_long i; int ret; size_t offset, retlen; - + DEBUG(2, "ftl_cs: ftl_read(0x%p, 0x%lx, %ld)\n", part, sector, nblocks); if (!(part->state & FTL_FORMATTED)) { @@ -834,7 +834,7 @@ static int ftl_read(partition_t *part, caddr_t buffer, /*====================================================================== Write a series of sectors to an FTL partition - + ======================================================================*/ static int set_bam_entry(partition_t *part, u_int32_t log_addr, @@ -855,7 +855,7 @@ static int set_bam_entry(partition_t *part, u_int32_t log_addr, blk = (log_addr % bsize) / SECTOR_SIZE; offset = (part->EUNInfo[eun].Offset + blk * sizeof(u_int32_t) + le32_to_cpu(part->header.BAMOffset)); - + #ifdef PSYCHO_DEBUG ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(u_int32_t), &retlen, (u_char *)&old_addr); @@ -925,7 +925,7 @@ static int ftl_write(partition_t *part, caddr_t buffer, if (ret) return ret; } - + bsize = 1 << part->header.EraseUnitSize; virt_addr = sector * SECTOR_SIZE | BLOCK_DATA; @@ -949,12 +949,12 @@ static int ftl_write(partition_t *part, caddr_t buffer, log_addr = part->bam_index * bsize + blk * SECTOR_SIZE; part->EUNInfo[part->bam_index].Free--; part->FreeTotal--; - if (set_bam_entry(part, log_addr, 0xfffffffe)) + if (set_bam_entry(part, log_addr, 0xfffffffe)) return -EIO; part->EUNInfo[part->bam_index].Deleted++; offset = (part->EUNInfo[part->bam_index].Offset + blk * SECTOR_SIZE); - ret = part->mbd.mtd->write(part->mbd.mtd, offset, SECTOR_SIZE, &retlen, + ret = part->mbd.mtd->write(part->mbd.mtd, offset, SECTOR_SIZE, &retlen, buffer); if (ret) { @@ -964,7 +964,7 @@ static int ftl_write(partition_t *part, caddr_t buffer, offset); return -EIO; } - + /* Only delete the old entry when the new entry is ready */ old_addr = part->VirtualBlockMap[sector+i]; if (old_addr != 0xffffffff) { @@ -979,7 +979,7 @@ static int ftl_write(partition_t *part, caddr_t buffer, return -EIO; part->VirtualBlockMap[sector+i] = log_addr; part->EUNInfo[part->bam_index].Deleted--; - + buffer += SECTOR_SIZE; virt_addr += SECTOR_SIZE; } @@ -1034,20 +1034,20 @@ static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) partition_t *partition; partition = kmalloc(sizeof(partition_t), GFP_KERNEL); - + if (!partition) { printk(KERN_WARNING "No memory to scan for FTL on %s\n", mtd->name); return; - } + } memset(partition, 0, sizeof(partition_t)); partition->mbd.mtd = mtd; - if ((scan_header(partition) == 0) && + if ((scan_header(partition) == 0) && (build_maps(partition) == 0)) { - + partition->state = FTL_FORMATTED; #ifdef PCMCIA_DEBUG printk(KERN_INFO "ftl_cs: opening %d KiB FTL partition\n", @@ -1086,7 +1086,7 @@ struct mtd_blktrans_ops ftl_tr = { int init_ftl(void) { - DEBUG(0, "$Id: ftl.c,v 1.55 2005/01/17 13:47:21 hvr Exp $\n"); + DEBUG(0, "$Id: ftl.c,v 1.58 2005/11/07 11:14:19 gleixner Exp $\n"); return register_mtd_blktrans(&ftl_tr); } diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c index 39eb53f6551..8db8618c18d 100644 --- a/drivers/mtd/inftlcore.c +++ b/drivers/mtd/inftlcore.c @@ -1,4 +1,4 @@ -/* +/* * inftlcore.c -- Linux driver for Inverse Flash Translation Layer (INFTL) * * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com) @@ -7,7 +7,7 @@ * (c) 1999 Machine Vision Holdings, Inc. * Author: David Woodhouse * - * $Id: inftlcore.c,v 1.18 2004/11/16 18:28:59 dwmw2 Exp $ + * $Id: inftlcore.c,v 1.19 2005/11/07 11:14:20 gleixner Exp $ * * 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 @@ -113,14 +113,14 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) if (inftl->mbd.size != inftl->heads * inftl->cylinders * inftl->sectors) { /* - Oh no we don't have + Oh no we don't have mbd.size == heads * cylinders * sectors */ printk(KERN_WARNING "INFTL: cannot calculate a geometry to " "match size of 0x%lx.\n", inftl->mbd.size); printk(KERN_WARNING "INFTL: using C:%d H:%d S:%d " "(== 0x%lx sects)\n", - inftl->cylinders, inftl->heads , inftl->sectors, + inftl->cylinders, inftl->heads , inftl->sectors, (long)inftl->cylinders * (long)inftl->heads * (long)inftl->sectors ); } @@ -223,7 +223,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned "Virtual Unit Chain %d!\n", thisVUC); return BLOCK_NIL; } - + /* * Scan to find the Erase Unit which holds the actual data for each * 512-byte block within the Chain. @@ -264,7 +264,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned "Unit Chain 0x%x\n", thisVUC); return BLOCK_NIL; } - + thisEUN = inftl->PUtable[thisEUN]; } @@ -295,15 +295,15 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned */ if (BlockMap[block] == BLOCK_NIL) continue; - + ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize * BlockMap[block]) + (block * SECTORSIZE), SECTORSIZE, - &retlen, movebuf); + &retlen, movebuf); if (ret < 0) { ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize * BlockMap[block]) + (block * SECTORSIZE), SECTORSIZE, &retlen, movebuf); - if (ret != -EIO) + if (ret != -EIO) DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went " "away on retry?\n"); } @@ -355,7 +355,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned static u16 INFTL_makefreeblock(struct INFTLrecord *inftl, unsigned pendingblock) { /* - * This is the part that needs some cleverness applied. + * This is the part that needs some cleverness applied. * For now, I'm doing the minimum applicable to actually * get the thing to work. * Wear-levelling and other clever stuff needs to be implemented @@ -414,7 +414,7 @@ static int nrbits(unsigned int val, int bitcount) } /* - * INFTL_findwriteunit: Return the unit number into which we can write + * INFTL_findwriteunit: Return the unit number into which we can write * for this block. Make it available if it isn't already. */ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block) @@ -463,10 +463,10 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block) * Invalid block. Don't use it any more. * Must implement. */ - break; + break; } - - if (!silly--) { + + if (!silly--) { printk(KERN_WARNING "INFTL: infinite loop in " "Virtual Unit Chain 0x%x\n", thisVUC); return 0xffff; @@ -482,7 +482,7 @@ hitused: /* - * OK. We didn't find one in the existing chain, or there + * OK. We didn't find one in the existing chain, or there * is no existing chain. Allocate a new one. */ writeEUN = INFTL_findfreeblock(inftl, 0); @@ -506,8 +506,8 @@ hitused: if (writeEUN == BLOCK_NIL) { /* * Ouch. This should never happen - we should - * always be able to make some room somehow. - * If we get here, we've allocated more storage + * always be able to make some room somehow. + * If we get here, we've allocated more storage * space than actual media, or our makefreeblock * routine is missing something. */ @@ -518,7 +518,7 @@ hitused: INFTL_dumpVUchains(inftl); #endif return BLOCK_NIL; - } + } } /* @@ -543,7 +543,7 @@ hitused: parity |= (nrbits(prev_block, 16) & 0x1) ? 0x2 : 0; parity |= (nrbits(anac, 8) & 0x1) ? 0x4 : 0; parity |= (nrbits(nacs, 8) & 0x1) ? 0x8 : 0; - + oob.u.a.virtualUnitNo = cpu_to_le16(thisVUC); oob.u.a.prevUnitNo = cpu_to_le16(prev_block); oob.u.a.ANAC = anac; @@ -562,7 +562,7 @@ hitused: oob.u.b.parityPerField = parity; oob.u.b.discarded = 0xaa; - MTD_WRITEOOB(inftl->mbd.mtd, writeEUN * inftl->EraseSize + + MTD_WRITEOOB(inftl->mbd.mtd, writeEUN * inftl->EraseSize + SECTORSIZE * 4 + 8, 8, &retlen, (char *)&oob.u); inftl->PUtable[writeEUN] = inftl->VUtable[thisVUC]; @@ -602,7 +602,7 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC) "Virtual Unit Chain %d!\n", thisVUC); return; } - + /* * Scan through the Erase Units to determine whether any data is in * each of the 512-byte blocks within the Chain. @@ -642,7 +642,7 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC) "Unit Chain 0x%x\n", thisVUC); return; } - + thisEUN = inftl->PUtable[thisEUN]; } @@ -758,7 +758,7 @@ foundit: return 0; } -static int inftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block, +static int inftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block, char *buffer) { struct INFTLrecord *inftl = (void *)mbd; @@ -893,7 +893,7 @@ extern char inftlmountrev[]; static int __init init_inftl(void) { - printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.18 $, " + printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.19 $, " "inftlmount.c %s\n", inftlmountrev); return register_mtd_blktrans(&inftl_tr); diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c index e066445320a..b26aea1f640 100644 --- a/drivers/mtd/inftlmount.c +++ b/drivers/mtd/inftlmount.c @@ -1,14 +1,14 @@ -/* +/* * inftlmount.c -- INFTL mount code with extensive checks. * * Author: Greg Ungerer (gerg@snapgear.com) * (C) Copyright 2002-2003, Greg Ungerer (gerg@snapgear.com) * * Based heavily on the nftlmount.c code which is: - * Author: Fabrice Bellard (fabrice.bellard@netgem.com) + * Author: Fabrice Bellard (fabrice.bellard@netgem.com) * Copyright (C) 2000 Netgem S.A. * - * $Id: inftlmount.c,v 1.17 2005/08/08 08:56:19 dwmw2 Exp $ + * $Id: inftlmount.c,v 1.18 2005/11/07 11:14:20 gleixner Exp $ * * 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 @@ -41,7 +41,7 @@ #include #include -char inftlmountrev[]="$Revision: 1.17 $"; +char inftlmountrev[]="$Revision: 1.18 $"; /* * find_boot_record: Find the INFTL Media Header and its Spare copy which @@ -273,7 +273,7 @@ static int find_boot_record(struct INFTLrecord *inftl) inftl->nb_boot_blocks); return -1; } - + inftl->mbd.size = inftl->numvunits * (inftl->EraseSize / SECTORSIZE); @@ -302,7 +302,7 @@ static int find_boot_record(struct INFTLrecord *inftl) inftl->nb_blocks * sizeof(u16)); return -ENOMEM; } - + /* Mark the blocks before INFTL MediaHeader as reserved */ for (i = 0; i < inftl->nb_boot_blocks; i++) inftl->PUtable[i] = BLOCK_RESERVED; @@ -380,7 +380,7 @@ static int check_free_sectors(struct INFTLrecord *inftl, unsigned int address, * * Return: 0 when succeed, -1 on error. * - * ToDo: 1. Is it neceressary to check_free_sector after erasing ?? + * ToDo: 1. Is it neceressary to check_free_sector after erasing ?? */ int INFTL_formatblock(struct INFTLrecord *inftl, int block) { @@ -578,7 +578,7 @@ int INFTL_mount(struct INFTLrecord *s) printk(KERN_ERR "INFTL: Out of memory.\n"); return -ENOMEM; } - + memset(ANACtable, 0, s->nb_blocks); /* @@ -600,7 +600,7 @@ int INFTL_mount(struct INFTLrecord *s) for (chain_length = 0; ; chain_length++) { - if ((chain_length == 0) && + if ((chain_length == 0) && (s->PUtable[block] != BLOCK_NOTEXPLORED)) { /* Nothing to do here, onto next block */ break; @@ -747,7 +747,7 @@ int INFTL_mount(struct INFTLrecord *s) "in virtual chain %d\n", s->PUtable[block], logical_block); s->PUtable[block] = BLOCK_NIL; - + } if (ANACtable[block] != ANAC) { /* diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index d6cb3d194ef..339cb1218ea 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -1,5 +1,5 @@ /* - * $Id: mtd_blkdevs.c,v 1.26 2005/07/29 19:42:04 tpoynor Exp $ + * $Id: mtd_blkdevs.c,v 1.27 2005/11/07 11:14:20 gleixner Exp $ * * (C) 2003 David Woodhouse * @@ -85,7 +85,7 @@ static int mtd_blktrans_thread(void *arg) daemonize("%sd", tr->name); /* daemonize() doesn't do this for us since some kernel threads - actually want to deal with signals. We can't just call + actually want to deal with signals. We can't just call exit_sighand() since that'll cause an oops when we finally do exit. */ spin_lock_irq(¤t->sighand->siglock); @@ -94,7 +94,7 @@ static int mtd_blktrans_thread(void *arg) spin_unlock_irq(¤t->sighand->siglock); spin_lock_irq(rq->queue_lock); - + while (!tr->blkcore_priv->exiting) { struct request *req; struct mtd_blktrans_dev *dev; @@ -157,7 +157,7 @@ static int blktrans_open(struct inode *i, struct file *f) if (!try_module_get(tr->owner)) goto out_tr; - /* FIXME: Locking. A hot pluggable device can go away + /* FIXME: Locking. A hot pluggable device can go away (del_mtd_device can be called for it) without its module being unloaded. */ dev->mtd->usecount++; @@ -195,7 +195,7 @@ static int blktrans_release(struct inode *i, struct file *f) } -static int blktrans_ioctl(struct inode *inode, struct file *file, +static int blktrans_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct mtd_blktrans_dev *dev = inode->i_bdev->bd_disk->private_data; @@ -264,7 +264,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) /* Required number was free */ list_add_tail(&new->list, &d->list); goto added; - } + } last_devnum = d->devnum; } if (new->devnum == -1) @@ -288,7 +288,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) gd->major = tr->major; gd->first_minor = (new->devnum) << tr->part_bits; gd->fops = &mtd_blktrans_ops; - + if (tr->part_bits) if (new->devnum < 26) snprintf(gd->disk_name, sizeof(gd->disk_name), @@ -314,7 +314,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) set_disk_ro(gd, 1); add_disk(gd); - + return 0; } @@ -329,7 +329,7 @@ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) del_gendisk(old->blkcore_priv); put_disk(old->blkcore_priv); - + return 0; } @@ -368,12 +368,12 @@ static struct mtd_notifier blktrans_notifier = { .add = blktrans_notify_add, .remove = blktrans_notify_remove, }; - + int register_mtd_blktrans(struct mtd_blktrans_ops *tr) { int ret, i; - /* Register the notifier if/when the first device type is + /* Register the notifier if/when the first device type is registered, to prevent the link/init ordering from fucking us over. */ if (!blktrans_notifier.list.next) @@ -416,7 +416,7 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) kfree(tr->blkcore_priv); up(&mtd_table_mutex); return ret; - } + } INIT_LIST_HEAD(&tr->devs); list_add(&tr->list, &blktrans_majors); diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c index bee8aba9e5b..e84756644fd 100644 --- a/drivers/mtd/mtdblock.c +++ b/drivers/mtd/mtdblock.c @@ -1,7 +1,7 @@ -/* +/* * Direct MTD block device access * - * $Id: mtdblock.c,v 1.67 2005/11/06 10:04:37 gleixner Exp $ + * $Id: mtdblock.c,v 1.68 2005/11/07 11:14:20 gleixner Exp $ * * (C) 2000-2003 Nicolas Pitre * (C) 1999-2003 David Woodhouse @@ -32,7 +32,7 @@ static struct mtdblk_dev { /* * Cache stuff... - * + * * Since typical flash erasable sectors are much larger than what Linux's * buffer cache can handle, we must implement read-modify-write on flash * sectors for each block write requests. To avoid over-erasing flash sectors @@ -46,7 +46,7 @@ static void erase_callback(struct erase_info *done) wake_up(wait_q); } -static int erase_write (struct mtd_info *mtd, unsigned long pos, +static int erase_write (struct mtd_info *mtd, unsigned long pos, int len, const char *buf) { struct erase_info erase; @@ -104,18 +104,18 @@ static int write_cached_data (struct mtdblk_dev *mtdblk) return 0; DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: writing cached data for \"%s\" " - "at 0x%lx, size 0x%x\n", mtd->name, + "at 0x%lx, size 0x%x\n", mtd->name, mtdblk->cache_offset, mtdblk->cache_size); - - ret = erase_write (mtd, mtdblk->cache_offset, + + ret = erase_write (mtd, mtdblk->cache_offset, mtdblk->cache_size, mtdblk->cache_data); if (ret) return ret; /* * Here we could argubly set the cache state to STATE_CLEAN. - * However this could lead to inconsistency since we will not - * be notified if this content is altered on the flash by other + * However this could lead to inconsistency since we will not + * be notified if this content is altered on the flash by other * means. Let's declare it empty and leave buffering tasks to * the buffer cache instead. */ @@ -124,7 +124,7 @@ static int write_cached_data (struct mtdblk_dev *mtdblk) } -static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, +static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, int len, const char *buf) { struct mtd_info *mtd = mtdblk->mtd; @@ -134,7 +134,7 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: write on \"%s\" at 0x%lx, size 0x%x\n", mtd->name, pos, len); - + if (!sect_size) return MTD_WRITE (mtd, pos, len, &retlen, buf); @@ -142,11 +142,11 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, unsigned long sect_start = (pos/sect_size)*sect_size; unsigned int offset = pos - sect_start; unsigned int size = sect_size - offset; - if( size > len ) + if( size > len ) size = len; if (size == sect_size) { - /* + /* * We are covering a whole sector. Thus there is no * need to bother with the cache while it may still be * useful for other partial writes. @@ -160,7 +160,7 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, if (mtdblk->cache_state == STATE_DIRTY && mtdblk->cache_offset != sect_start) { ret = write_cached_data(mtdblk); - if (ret) + if (ret) return ret; } @@ -193,7 +193,7 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, } -static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos, +static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos, int len, char *buf) { struct mtd_info *mtd = mtdblk->mtd; @@ -201,9 +201,9 @@ static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos, size_t retlen; int ret; - DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n", + DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n", mtd->name, pos, len); - + if (!sect_size) return MTD_READ (mtd, pos, len, &retlen, buf); @@ -211,7 +211,7 @@ static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos, unsigned long sect_start = (pos/sect_size)*sect_size; unsigned int offset = pos - sect_start; unsigned int size = sect_size - offset; - if (size > len) + if (size > len) size = len; /* @@ -269,12 +269,12 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd) int dev = mbd->devnum; DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n"); - + if (mtdblks[dev]) { mtdblks[dev]->count++; return 0; } - + /* OK, it's not open. Create cache info for it */ mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL); if (!mtdblk) @@ -293,7 +293,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd) } mtdblks[dev] = mtdblk; - + DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); return 0; @@ -321,7 +321,7 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd) DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); return 0; -} +} static int mtdblock_flush(struct mtd_blktrans_dev *dev) { diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index d1ffd246ad5..6f044584bdc 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -1,5 +1,5 @@ /* - * $Id: mtdchar.c,v 1.75 2005/11/06 10:04:37 gleixner Exp $ + * $Id: mtdchar.c,v 1.76 2005/11/07 11:14:20 gleixner Exp $ * * Character-device access to raw MTD devices. * @@ -28,7 +28,7 @@ static void mtd_notify_add(struct mtd_info* mtd) class_device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2), NULL, "mtd%d", mtd->index); - + class_device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1), NULL, "mtd%dro", mtd->index); @@ -108,23 +108,23 @@ static int mtd_open(struct inode *inode, struct file *file) return -EACCES; mtd = get_mtd_device(NULL, devnum); - + if (!mtd) return -ENODEV; - + if (MTD_ABSENT == mtd->type) { put_mtd_device(mtd); return -ENODEV; } file->private_data = mtd; - + /* You can't open it RW if it's not a writeable device */ if ((file->f_mode & 2) && !(mtd->flags & MTD_WRITEABLE)) { put_mtd_device(mtd); return -EACCES; } - + return 0; } /* mtd_open */ @@ -137,10 +137,10 @@ static int mtd_close(struct inode *inode, struct file *file) DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n"); mtd = TO_MTD(file); - + if (mtd->sync) mtd->sync(mtd); - + put_mtd_device(mtd); return 0; @@ -159,7 +159,7 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t int ret=0; int len; char *kbuf; - + DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n"); if (*ppos + count > mtd->size) @@ -167,11 +167,11 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t if (!count) return 0; - + /* FIXME: Use kiovec in 2.5 to lock down the user's buffers and pass them directly to the MTD functions */ while (count) { - if (count > MAX_KMALLOC_SIZE) + if (count > MAX_KMALLOC_SIZE) len = MAX_KMALLOC_SIZE; else len = count; @@ -179,7 +179,7 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t kbuf=kmalloc(len,GFP_KERNEL); if (!kbuf) return -ENOMEM; - + switch (MTD_MODE(file)) { case MTD_MODE_OTP_FACT: ret = mtd->read_fact_prot_reg(mtd, *ppos, len, &retlen, kbuf); @@ -192,7 +192,7 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t } /* Nand returns -EBADMSG on ecc errors, but it returns * the data. For our userspace tools it is important - * to dump areas with ecc errors ! + * to dump areas with ecc errors ! * Userspace software which accesses NAND this way * must be aware of the fact that it deals with NAND */ @@ -214,7 +214,7 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t kfree(kbuf); return ret; } - + kfree(kbuf); } @@ -231,10 +231,10 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count int len; DEBUG(MTD_DEBUG_LEVEL0,"MTD_write\n"); - + if (*ppos == mtd->size) return -ENOSPC; - + if (*ppos + count > mtd->size) count = mtd->size - *ppos; @@ -242,7 +242,7 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count return 0; while (count) { - if (count > MAX_KMALLOC_SIZE) + if (count > MAX_KMALLOC_SIZE) len = MAX_KMALLOC_SIZE; else len = count; @@ -257,7 +257,7 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count kfree(kbuf); return -EFAULT; } - + switch (MTD_MODE(file)) { case MTD_MODE_OTP_FACT: ret = -EROFS; @@ -282,7 +282,7 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count kfree(kbuf); return ret; } - + kfree(kbuf); } @@ -306,7 +306,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file, void __user *argp = (void __user *)arg; int ret = 0; u_long size; - + DEBUG(MTD_DEBUG_LEVEL0, "MTD_ioctl\n"); size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT; @@ -318,7 +318,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file, if (!access_ok(VERIFY_WRITE, argp, size)) return -EFAULT; } - + switch (cmd) { case MEMGETREGIONCOUNT: if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int))) @@ -370,11 +370,11 @@ static int mtd_ioctl(struct inode *inode, struct file *file, erase->mtd = mtd; erase->callback = mtdchar_erase_callback; erase->priv = (unsigned long)&waitq; - + /* FIXME: Allow INTERRUPTIBLE. Which means not having the wait_queue head on the stack. - + If the wq_head is on the stack, and we leave because we got interrupted, then the wq_head is no longer there when the @@ -402,13 +402,13 @@ static int mtd_ioctl(struct inode *inode, struct file *file, struct mtd_oob_buf buf; void *databuf; ssize_t retlen; - + if(!(file->f_mode & 2)) return -EPERM; if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf))) return -EFAULT; - + if (buf.length > 0x4096) return -EINVAL; @@ -424,7 +424,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file, databuf = kmalloc(buf.length, GFP_KERNEL); if (!databuf) return -ENOMEM; - + if (copy_from_user(databuf, buf.ptr, buf.length)) { kfree(databuf); return -EFAULT; @@ -448,7 +448,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file, if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf))) return -EFAULT; - + if (buf.length > 0x4096) return -EINVAL; @@ -464,14 +464,14 @@ static int mtd_ioctl(struct inode *inode, struct file *file, databuf = kmalloc(buf.length, GFP_KERNEL); if (!databuf) return -ENOMEM; - + ret = (mtd->read_oob)(mtd, buf.start, buf.length, &retlen, databuf); if (put_user(retlen, (uint32_t __user *)argp)) ret = -EFAULT; else if (retlen && copy_to_user(buf.ptr, databuf, retlen)) ret = -EFAULT; - + kfree(databuf); break; } @@ -521,7 +521,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file, case MEMGETBADBLOCK: { loff_t offs; - + if (copy_from_user(&offs, argp, sizeof(loff_t))) return -EFAULT; if (!mtd->block_isbad) diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index eaaafb1de62..b1bf8c411de 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c @@ -7,7 +7,7 @@ * * This code is GPL * - * $Id: mtdconcat.c,v 1.10 2005/11/06 10:04:37 gleixner Exp $ + * $Id: mtdconcat.c,v 1.11 2005/11/07 11:14:20 gleixner Exp $ */ #include @@ -44,7 +44,7 @@ struct mtd_concat { */ #define CONCAT(x) ((struct mtd_concat *)(x)) -/* +/* * MTD methods which look up the relevant subdevice, translate the * effective address and pass through to the subdevice. */ @@ -878,7 +878,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c return &concat->mtd; } -/* +/* * This function destroys an MTD object obtained from concat_mtd_devs() */ diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 2c16e051c61..dade02ab068 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -1,5 +1,5 @@ /* - * $Id: mtdcore.c,v 1.46 2005/08/11 17:13:43 gleixner Exp $ + * $Id: mtdcore.c,v 1.47 2005/11/07 11:14:20 gleixner Exp $ * * Core registration and callback routines for MTD * drivers and users. @@ -25,7 +25,7 @@ #include -/* These are exported solely for the purpose of mtd_blkdevs.c. You +/* These are exported solely for the purpose of mtd_blkdevs.c. You should not use them for _anything_ else */ DECLARE_MUTEX(mtd_table_mutex); struct mtd_info *mtd_table[MAX_MTD_DEVICES]; @@ -66,7 +66,7 @@ int add_mtd_device(struct mtd_info *mtd) struct mtd_notifier *not = list_entry(this, struct mtd_notifier, list); not->add(mtd); } - + up(&mtd_table_mutex); /* We _know_ we aren't being removed, because our caller is still holding us here. So none @@ -75,7 +75,7 @@ int add_mtd_device(struct mtd_info *mtd) __module_get(THIS_MODULE); return 0; } - + up(&mtd_table_mutex); return 1; } @@ -93,13 +93,13 @@ int add_mtd_device(struct mtd_info *mtd) int del_mtd_device (struct mtd_info *mtd) { int ret; - + down(&mtd_table_mutex); if (mtd_table[mtd->index] != mtd) { ret = -ENODEV; } else if (mtd->usecount) { - printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n", + printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n", mtd->index, mtd->name, mtd->usecount); ret = -EBUSY; } else { @@ -140,7 +140,7 @@ void register_mtd_user (struct mtd_notifier *new) list_add(&new->list, &mtd_notifiers); __module_get(THIS_MODULE); - + for (i=0; i< MAX_MTD_DEVICES; i++) if (mtd_table[i]) new->add(mtd_table[i]); @@ -169,7 +169,7 @@ int unregister_mtd_user (struct mtd_notifier *old) for (i=0; i< MAX_MTD_DEVICES; i++) if (mtd_table[i]) old->remove(mtd_table[i]); - + list_del(&old->list); up(&mtd_table_mutex); return 0; @@ -187,7 +187,7 @@ int unregister_mtd_user (struct mtd_notifier *old) * both, return the num'th driver only if its address matches. Return NULL * if not. */ - + struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) { struct mtd_info *ret = NULL; diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index e9168b5cd51..99395911d26 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -5,11 +5,11 @@ * * This code is GPL * - * $Id: mtdpart.c,v 1.54 2005/09/30 14:49:08 dedekind Exp $ + * $Id: mtdpart.c,v 1.55 2005/11/07 11:14:20 gleixner Exp $ * * 02-21-2002 Thomas Gleixner * added support for read_oob, write_oob - */ + */ #include #include @@ -41,13 +41,13 @@ struct mtd_part { */ #define PART(x) ((struct mtd_part *)(x)) - -/* + +/* * MTD methods which simply translate the effective address and pass through * to the _real_ device. */ -static int part_read (struct mtd_info *mtd, loff_t from, size_t len, +static int part_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { struct mtd_part *part = PART(mtd); @@ -55,15 +55,15 @@ static int part_read (struct mtd_info *mtd, loff_t from, size_t len, len = 0; else if (from + len > mtd->size) len = mtd->size - from; - if (part->master->read_ecc == NULL) - return part->master->read (part->master, from + part->offset, + if (part->master->read_ecc == NULL) + return part->master->read (part->master, from + part->offset, len, retlen, buf); else - return part->master->read_ecc (part->master, from + part->offset, + return part->master->read_ecc (part->master, from + part->offset, len, retlen, buf, NULL, &mtd->oobinfo); } -static int part_point (struct mtd_info *mtd, loff_t from, size_t len, +static int part_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **buf) { struct mtd_part *part = PART(mtd); @@ -71,7 +71,7 @@ static int part_point (struct mtd_info *mtd, loff_t from, size_t len, len = 0; else if (from + len > mtd->size) len = mtd->size - from; - return part->master->point (part->master, from + part->offset, + return part->master->point (part->master, from + part->offset, len, retlen, buf); } static void part_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) @@ -82,7 +82,7 @@ static void part_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_ } -static int part_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, +static int part_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel) { struct mtd_part *part = PART(mtd); @@ -92,11 +92,11 @@ static int part_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, len = 0; else if (from + len > mtd->size) len = mtd->size - from; - return part->master->read_ecc (part->master, from + part->offset, + return part->master->read_ecc (part->master, from + part->offset, len, retlen, buf, eccbuf, oobsel); } -static int part_read_oob (struct mtd_info *mtd, loff_t from, size_t len, +static int part_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { struct mtd_part *part = PART(mtd); @@ -104,15 +104,15 @@ static int part_read_oob (struct mtd_info *mtd, loff_t from, size_t len, len = 0; else if (from + len > mtd->size) len = mtd->size - from; - return part->master->read_oob (part->master, from + part->offset, + return part->master->read_oob (part->master, from + part->offset, len, retlen, buf); } -static int part_read_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, +static int part_read_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { struct mtd_part *part = PART(mtd); - return part->master->read_user_prot_reg (part->master, from, + return part->master->read_user_prot_reg (part->master, from, len, retlen, buf); } @@ -123,11 +123,11 @@ static int part_get_user_prot_info (struct mtd_info *mtd, return part->master->get_user_prot_info (part->master, buf, len); } -static int part_read_fact_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, +static int part_read_fact_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { struct mtd_part *part = PART(mtd); - return part->master->read_fact_prot_reg (part->master, from, + return part->master->read_fact_prot_reg (part->master, from, len, retlen, buf); } @@ -148,13 +148,13 @@ static int part_write (struct mtd_info *mtd, loff_t to, size_t len, len = 0; else if (to + len > mtd->size) len = mtd->size - to; - if (part->master->write_ecc == NULL) - return part->master->write (part->master, to + part->offset, + if (part->master->write_ecc == NULL) + return part->master->write (part->master, to + part->offset, len, retlen, buf); else - return part->master->write_ecc (part->master, to + part->offset, + return part->master->write_ecc (part->master, to + part->offset, len, retlen, buf, NULL, &mtd->oobinfo); - + } static int part_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, @@ -170,7 +170,7 @@ static int part_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, len = 0; else if (to + len > mtd->size) len = mtd->size - to; - return part->master->write_ecc (part->master, to + part->offset, + return part->master->write_ecc (part->master, to + part->offset, len, retlen, buf, eccbuf, oobsel); } @@ -184,19 +184,19 @@ static int part_write_oob (struct mtd_info *mtd, loff_t to, size_t len, len = 0; else if (to + len > mtd->size) len = mtd->size - to; - return part->master->write_oob (part->master, to + part->offset, + return part->master->write_oob (part->master, to + part->offset, len, retlen, buf); } -static int part_write_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, +static int part_write_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { struct mtd_part *part = PART(mtd); - return part->master->write_user_prot_reg (part->master, from, + return part->master->write_user_prot_reg (part->master, from, len, retlen, buf); } -static int part_lock_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len) +static int part_lock_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len) { struct mtd_part *part = PART(mtd); return part->master->lock_user_prot_reg (part->master, from, len); @@ -208,7 +208,7 @@ static int part_writev (struct mtd_info *mtd, const struct kvec *vecs, struct mtd_part *part = PART(mtd); if (!(mtd->flags & MTD_WRITEABLE)) return -EROFS; - if (part->master->writev_ecc == NULL) + if (part->master->writev_ecc == NULL) return part->master->writev (part->master, vecs, count, to + part->offset, retlen); else @@ -221,12 +221,12 @@ static int part_readv (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen) { struct mtd_part *part = PART(mtd); - if (part->master->readv_ecc == NULL) + if (part->master->readv_ecc == NULL) return part->master->readv (part->master, vecs, count, from + part->offset, retlen); else return part->master->readv_ecc (part->master, vecs, count, - from + part->offset, retlen, + from + part->offset, retlen, NULL, &mtd->oobinfo); } @@ -252,7 +252,7 @@ static int part_readv_ecc (struct mtd_info *mtd, struct kvec *vecs, if (oobsel == NULL) oobsel = &mtd->oobinfo; return part->master->readv_ecc (part->master, vecs, count, - from + part->offset, retlen, + from + part->offset, retlen, eccbuf, oobsel); } @@ -286,7 +286,7 @@ EXPORT_SYMBOL_GPL(mtd_erase_callback); static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len) { struct mtd_part *part = PART(mtd); - if ((len + ofs) > mtd->size) + if ((len + ofs) > mtd->size) return -EINVAL; return part->master->lock(part->master, ofs + part->offset, len); } @@ -294,7 +294,7 @@ static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len) static int part_unlock (struct mtd_info *mtd, loff_t ofs, size_t len) { struct mtd_part *part = PART(mtd); - if ((len + ofs) > mtd->size) + if ((len + ofs) > mtd->size) return -EINVAL; return part->master->unlock(part->master, ofs + part->offset, len); } @@ -337,8 +337,8 @@ static int part_block_markbad (struct mtd_info *mtd, loff_t ofs) return part->master->block_markbad(part->master, ofs); } -/* - * This function unregisters and destroy all slave MTD objects which are +/* + * This function unregisters and destroy all slave MTD objects which are * attached to the given master MTD object. */ @@ -371,7 +371,7 @@ int del_mtd_partitions(struct mtd_info *master) * (Q: should we register the master MTD object as well?) */ -int add_mtd_partitions(struct mtd_info *master, +int add_mtd_partitions(struct mtd_info *master, const struct mtd_partition *parts, int nbparts) { @@ -414,7 +414,7 @@ int add_mtd_partitions(struct mtd_info *master, slave->mtd.point = part_point; slave->mtd.unpoint = part_unpoint; } - + if (master->read_ecc) slave->mtd.read_ecc = part_read_ecc; if (master->write_ecc) @@ -477,8 +477,8 @@ int add_mtd_partitions(struct mtd_info *master, if (slave->mtd.size == MTDPART_SIZ_FULL) slave->mtd.size = master->size - slave->offset; cur_offset = slave->offset + slave->mtd.size; - - printk (KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset, + + printk (KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset, slave->offset + slave->mtd.size, slave->mtd.name); /* let's do some sanity checks */ @@ -498,7 +498,7 @@ int add_mtd_partitions(struct mtd_info *master, /* Deal with variable erase size stuff */ int i; struct mtd_erase_region_info *regions = master->eraseregions; - + /* Find the first erase regions which is part of this partition. */ for (i=0; i < master->numeraseregions && slave->offset >= regions[i].offset; i++) ; @@ -513,7 +513,7 @@ int add_mtd_partitions(struct mtd_info *master, slave->mtd.erasesize = master->erasesize; } - if ((slave->mtd.flags & MTD_WRITEABLE) && + if ((slave->mtd.flags & MTD_WRITEABLE) && (slave->offset % slave->mtd.erasesize)) { /* Doesn't start on a boundary of major erase size */ /* FIXME: Let it be writable if it is on a boundary of _minor_ erase size though */ @@ -521,14 +521,14 @@ int add_mtd_partitions(struct mtd_info *master, printk ("mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n", parts[i].name); } - if ((slave->mtd.flags & MTD_WRITEABLE) && + if ((slave->mtd.flags & MTD_WRITEABLE) && (slave->mtd.size % slave->mtd.erasesize)) { slave->mtd.flags &= ~MTD_WRITEABLE; printk ("mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n", parts[i].name); } - /* copy oobinfo from master */ + /* copy oobinfo from master */ memcpy(&slave->mtd.oobinfo, &master->oobinfo, sizeof(slave->mtd.oobinfo)); if(parts[i].mtdp) @@ -589,12 +589,12 @@ int deregister_mtd_parser(struct mtd_part_parser *p) return 0; } -int parse_mtd_partitions(struct mtd_info *master, const char **types, +int parse_mtd_partitions(struct mtd_info *master, const char **types, struct mtd_partition **pparts, unsigned long origin) { struct mtd_part_parser *parser; int ret = 0; - + for ( ; ret <= 0 && *types; types++) { parser = get_partition_parser(*types); #ifdef CONFIG_KMOD @@ -608,7 +608,7 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types, } ret = (*parser->parse_fn)(master, pparts, origin); if (ret > 0) { - printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n", + printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n", ret, parser->name, master->name); } put_partition_parser(parser); diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index b2014043634..89d662999e7 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c @@ -1,7 +1,7 @@ /* Linux driver for NAND Flash Translation Layer */ /* (c) 1999 Machine Vision Holdings, Inc. */ /* Author: David Woodhouse */ -/* $Id: nftlcore.c,v 1.97 2004/11/16 18:28:59 dwmw2 Exp $ */ +/* $Id: nftlcore.c,v 1.98 2005/11/07 11:14:21 gleixner Exp $ */ /* The contents of this file are distributed under the GNU General @@ -101,14 +101,14 @@ static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) if (nftl->mbd.size != nftl->heads * nftl->cylinders * nftl->sectors) { /* - Oh no we don't have + Oh no we don't have mbd.size == heads * cylinders * sectors */ printk(KERN_WARNING "NFTL: cannot calculate a geometry to " "match size of 0x%lx.\n", nftl->mbd.size); printk(KERN_WARNING "NFTL: using C:%d H:%d S:%d " "(== 0x%lx sects)\n", - nftl->cylinders, nftl->heads , nftl->sectors, + nftl->cylinders, nftl->heads , nftl->sectors, (long)nftl->cylinders * (long)nftl->heads * (long)nftl->sectors ); } @@ -178,7 +178,7 @@ static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate ) if (!silly--) { printk("Argh! No free blocks found! LastFreeEUN = %d, " - "FirstEUN = %d\n", nftl->LastFreeEUN, + "FirstEUN = %d\n", nftl->LastFreeEUN, le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN)); return 0xffff; } @@ -210,7 +210,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p "Virtual Unit Chain %d!\n", thisVUC); return BLOCK_NIL; } - + /* Scan to find the Erase Unit which holds the actual data for each 512-byte block within the Chain. */ @@ -227,7 +227,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p if (block == 2) { foldmark = oob.u.c.FoldMark | oob.u.c.FoldMark1; if (foldmark == FOLD_MARK_IN_PROGRESS) { - DEBUG(MTD_DEBUG_LEVEL1, + DEBUG(MTD_DEBUG_LEVEL1, "Write Inhibited on EUN %d\n", thisEUN); inplace = 0; } else { @@ -249,7 +249,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p if (!BlockFreeFound[block]) BlockMap[block] = thisEUN; else - printk(KERN_WARNING + printk(KERN_WARNING "SECTOR_USED found after SECTOR_FREE " "in Virtual Unit Chain %d for block %d\n", thisVUC, block); @@ -258,7 +258,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p if (!BlockFreeFound[block]) BlockMap[block] = BLOCK_NIL; else - printk(KERN_WARNING + printk(KERN_WARNING "SECTOR_DELETED found after SECTOR_FREE " "in Virtual Unit Chain %d for block %d\n", thisVUC, block); @@ -277,14 +277,14 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p thisVUC); return BLOCK_NIL; } - + thisEUN = nftl->ReplUnitTable[thisEUN]; } if (inplace) { /* We're being asked to be a fold-in-place. Check that all blocks which actually have data associated - with them (i.e. BlockMap[block] != BLOCK_NIL) are + with them (i.e. BlockMap[block] != BLOCK_NIL) are either already present or SECTOR_FREE in the target block. If not, we're going to have to fold out-of-place anyway. @@ -297,7 +297,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p "block %d was %x lastEUN, " "and is in EUN %d (%s) %d\n", thisVUC, block, BlockLastState[block], - BlockMap[block], + BlockMap[block], BlockMap[block]== targetEUN ? "==" : "!=", targetEUN); inplace = 0; @@ -314,17 +314,17 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p inplace = 0; } } - + if (!inplace) { DEBUG(MTD_DEBUG_LEVEL1, "Cannot fold Virtual Unit Chain %d in place. " "Trying out-of-place\n", thisVUC); /* We need to find a targetEUN to fold into. */ targetEUN = NFTL_findfreeblock(nftl, 1); if (targetEUN == BLOCK_NIL) { - /* Ouch. Now we're screwed. We need to do a + /* Ouch. Now we're screwed. We need to do a fold-in-place of another chain to make room for this one. We need a better way of selecting - which chain to fold, because makefreeblock will + which chain to fold, because makefreeblock will only ask us to fold the same one again. */ printk(KERN_WARNING @@ -338,7 +338,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p chain by selecting the longer one */ oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS); oob.u.c.unused = 0xffffffff; - MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8, + MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8, 8, &retlen, (char *)&oob.u); } @@ -361,14 +361,14 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p happen in case of media errors or deleted blocks) */ if (BlockMap[block] == BLOCK_NIL) continue; - + ret = MTD_READ(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512), - 512, &retlen, movebuf); + 512, &retlen, movebuf); if (ret < 0) { ret = MTD_READ(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512), 512, &retlen, - movebuf); - if (ret != -EIO) + movebuf); + if (ret != -EIO) printk("Error went away on retry.\n"); } memset(&oob, 0xff, sizeof(struct nftl_oob)); @@ -376,18 +376,18 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p MTD_WRITEECC(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + (block * 512), 512, &retlen, movebuf, (char *)&oob, &nftl->oobinfo); } - + /* add the header so that it is now a valid chain */ oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff; - - MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 8, + + MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 8, 8, &retlen, (char *)&oob.u); /* OK. We've moved the whole lot into the new block. Now we have to free the original blocks. */ - /* At this point, we have two different chains for this Virtual Unit, and no way to tell + /* At this point, we have two different chains for this Virtual Unit, and no way to tell them apart. If we crash now, we get confused. However, both contain the same data, so we shouldn't actually lose data in this case. It's just that when we load up on a medium which has duplicate chains, we need to free one of the chains because it's not necessary any more. @@ -395,7 +395,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p thisEUN = nftl->EUNtable[thisVUC]; DEBUG(MTD_DEBUG_LEVEL1,"Want to erase\n"); - /* For each block in the old chain (except the targetEUN of course), + /* For each block in the old chain (except the targetEUN of course), free it and make it available for future use */ while (thisEUN <= nftl->lastEUN && thisEUN != targetEUN) { unsigned int EUNtmp; @@ -413,7 +413,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p } thisEUN = EUNtmp; } - + /* Make this the new start of chain for thisVUC */ nftl->ReplUnitTable[targetEUN] = BLOCK_NIL; nftl->EUNtable[thisVUC] = targetEUN; @@ -423,7 +423,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p static u16 NFTL_makefreeblock( struct NFTLrecord *nftl , unsigned pendingblock) { - /* This is the part that needs some cleverness applied. + /* This is the part that needs some cleverness applied. For now, I'm doing the minimum applicable to actually get the thing to work. Wear-levelling and other clever stuff needs to be implemented @@ -470,7 +470,7 @@ static u16 NFTL_makefreeblock( struct NFTLrecord *nftl , unsigned pendingblock) return NFTL_foldchain (nftl, LongestChain, pendingblock); } -/* NFTL_findwriteunit: Return the unit number into which we can write +/* NFTL_findwriteunit: Return the unit number into which we can write for this block. Make it available if it isn't already */ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) @@ -488,7 +488,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) a free space for the block in question. */ - /* This condition catches the 0x[7f]fff cases, as well as + /* This condition catches the 0x[7f]fff cases, as well as being a sanity check for past-end-of-media access */ lastEUN = BLOCK_NIL; @@ -503,7 +503,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) MTD_READOOB(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs, 8, &retlen, (char *)&bci); - + DEBUG(MTD_DEBUG_LEVEL2, "Status of block %d in EUN %d is %x\n", block , writeEUN, le16_to_cpu(bci.Status)); @@ -518,10 +518,10 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) break; default: // Invalid block. Don't use it any more. Must implement. - break; + break; } - - if (!silly--) { + + if (!silly--) { printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n", thisVUC); @@ -532,7 +532,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) writeEUN = nftl->ReplUnitTable[writeEUN]; } - /* OK. We didn't find one in the existing chain, or there + /* OK. We didn't find one in the existing chain, or there is no existing chain. */ /* Try to find an already-free block */ @@ -546,12 +546,12 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) /* First remember the start of this chain */ //u16 startEUN = nftl->EUNtable[thisVUC]; - + //printk("Write to VirtualUnitChain %d, calling makefreeblock()\n", thisVUC); writeEUN = NFTL_makefreeblock(nftl, 0xffff); if (writeEUN == BLOCK_NIL) { - /* OK, we accept that the above comment is + /* OK, we accept that the above comment is lying - there may have been free blocks last time we called NFTL_findfreeblock(), but they are reserved for when we're @@ -562,21 +562,21 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) } if (writeEUN == BLOCK_NIL) { /* Ouch. This should never happen - we should - always be able to make some room somehow. - If we get here, we've allocated more storage + always be able to make some room somehow. + If we get here, we've allocated more storage space than actual media, or our makefreeblock routine is missing something. */ printk(KERN_WARNING "Cannot make free space.\n"); return BLOCK_NIL; - } + } //printk("Restarting scan\n"); lastEUN = BLOCK_NIL; continue; } /* We've found a free block. Insert it into the chain. */ - + if (lastEUN != BLOCK_NIL) { thisVUC |= 0x8000; /* It's a replacement block */ } else { @@ -749,7 +749,7 @@ extern char nftlmountrev[]; static int __init init_nftl(void) { - printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.97 $, nftlmount.c %s\n", nftlmountrev); + printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.98 $, nftlmount.c %s\n", nftlmountrev); return register_mtd_blktrans(&nftl_tr); } diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c index 84afd9029f5..3b104ebb219 100644 --- a/drivers/mtd/nftlmount.c +++ b/drivers/mtd/nftlmount.c @@ -1,10 +1,10 @@ -/* +/* * NFTL mount code with extensive checks * - * Author: Fabrice Bellard (fabrice.bellard@netgem.com) + * Author: Fabrice Bellard (fabrice.bellard@netgem.com) * Copyright (C) 2000 Netgem S.A. * - * $Id: nftlmount.c,v 1.40 2004/11/22 14:38:29 kalev Exp $ + * $Id: nftlmount.c,v 1.41 2005/11/07 11:14:21 gleixner Exp $ * * 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 @@ -31,7 +31,7 @@ #define SECTORSIZE 512 -char nftlmountrev[]="$Revision: 1.40 $"; +char nftlmountrev[]="$Revision: 1.41 $"; /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the * various device information of the NFTL partition and Bad Unit Table. Update @@ -47,7 +47,7 @@ static int find_boot_record(struct NFTLrecord *nftl) struct NFTLMediaHeader *mh = &nftl->MediaHdr; unsigned int i; - /* Assume logical EraseSize == physical erasesize for starting the scan. + /* Assume logical EraseSize == physical erasesize for starting the scan. We'll sort it out later if we find a MediaHeader which says otherwise */ /* Actually, we won't. The new DiskOnChip driver has already scanned the MediaHeader and adjusted the virtual erasesize it presents in @@ -83,9 +83,9 @@ static int find_boot_record(struct NFTLrecord *nftl) if (retlen < 6 || memcmp(buf, "ANAND", 6)) { /* ANAND\0 not found. Continue */ #if 0 - printk(KERN_DEBUG "ANAND header not found at 0x%x in mtd%d\n", + printk(KERN_DEBUG "ANAND header not found at 0x%x in mtd%d\n", block * nftl->EraseSize, nftl->mbd.mtd->index); -#endif +#endif continue; } @@ -103,7 +103,7 @@ static int find_boot_record(struct NFTLrecord *nftl) */ if (le16_to_cpu(h1.EraseMark | h1.EraseMark1) != ERASE_MARK) { printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but erase mark not present (0x%04x,0x%04x instead)\n", - block * nftl->EraseSize, nftl->mbd.mtd->index, + block * nftl->EraseSize, nftl->mbd.mtd->index, le16_to_cpu(h1.EraseMark), le16_to_cpu(h1.EraseMark1)); continue; } @@ -175,7 +175,7 @@ device is already correct. nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN); if ((nftl->nb_boot_blocks + 2) >= nftl->nb_blocks) { printk(KERN_NOTICE "NFTL Media Header sanity check failed:\n"); - printk(KERN_NOTICE "nb_boot_blocks (%d) + 2 > nb_blocks (%d)\n", + printk(KERN_NOTICE "nb_boot_blocks (%d) + 2 > nb_blocks (%d)\n", nftl->nb_boot_blocks, nftl->nb_blocks); return -1; } @@ -187,7 +187,7 @@ device is already correct. nftl->numvunits, nftl->nb_blocks, nftl->nb_boot_blocks); return -1; } - + nftl->mbd.size = nftl->numvunits * (nftl->EraseSize / SECTORSIZE); /* If we're not using the last sectors in the device for some reason, @@ -210,12 +210,12 @@ device is already correct. printk(KERN_NOTICE "NFTL: allocation of ReplUnitTable failed\n"); return -ENOMEM; } - + /* mark the bios blocks (blocks before NFTL MediaHeader) as reserved */ for (i = 0; i < nftl->nb_boot_blocks; i++) nftl->ReplUnitTable[i] = BLOCK_RESERVED; /* mark all remaining blocks as potentially containing data */ - for (; i < nftl->nb_blocks; i++) { + for (; i < nftl->nb_blocks; i++) { nftl->ReplUnitTable[i] = BLOCK_NOTEXPLORED; } @@ -245,12 +245,12 @@ The new DiskOnChip driver already scanned the bad block table. Just query it. if (nftl->mbd.mtd->block_isbad(nftl->mbd.mtd, i * nftl->EraseSize)) nftl->ReplUnitTable[i] = BLOCK_RESERVED; } - + nftl->MediaUnit = block; boot_record_count++; - + } /* foreach (block) */ - + return boot_record_count?0:-1; } @@ -265,7 +265,7 @@ static int memcmpb(void *a, int c, int n) } /* check_free_sector: check if a free sector is actually FREE, i.e. All 0xff in data and oob area */ -static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len, +static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len, int check_oob) { int i; @@ -293,7 +293,7 @@ static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int * * Return: 0 when succeed, -1 on error. * - * ToDo: 1. Is it neceressary to check_free_sector after erasing ?? + * ToDo: 1. Is it neceressary to check_free_sector after erasing ?? */ int NFTL_formatblock(struct NFTLrecord *nftl, int block) { @@ -385,7 +385,7 @@ static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_b /* verify that the sector is really free. If not, mark as ignore */ if (memcmpb(&bci, 0xff, 8) != 0 || - check_free_sectors(nftl, block * nftl->EraseSize + i * SECTORSIZE, + check_free_sectors(nftl, block * nftl->EraseSize + i * SECTORSIZE, SECTORSIZE, 0) != 0) { printk("Incorrect free sector %d in block %d: " "marking it as ignored\n", @@ -486,7 +486,7 @@ static int check_and_mark_free_block(struct NFTLrecord *nftl, int block) size_t retlen; /* check erase mark. */ - if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, + if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, &retlen, (char *)&h1) < 0) return -1; @@ -501,7 +501,7 @@ static int check_and_mark_free_block(struct NFTLrecord *nftl, int block) h1.EraseMark = cpu_to_le16(ERASE_MARK); h1.EraseMark1 = cpu_to_le16(ERASE_MARK); h1.WearInfo = cpu_to_le32(0); - if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, + if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, &retlen, (char *)&h1) < 0) return -1; } else { @@ -582,9 +582,9 @@ int NFTL_mount(struct NFTLrecord *s) for (;;) { /* read the block header. If error, we format the chain */ - if (MTD_READOOB(s->mbd.mtd, block * s->EraseSize + 8, 8, + if (MTD_READOOB(s->mbd.mtd, block * s->EraseSize + 8, 8, &retlen, (char *)&h0) < 0 || - MTD_READOOB(s->mbd.mtd, block * s->EraseSize + SECTORSIZE + 8, 8, + MTD_READOOB(s->mbd.mtd, block * s->EraseSize + SECTORSIZE + 8, 8, &retlen, (char *)&h1) < 0) { s->ReplUnitTable[block] = BLOCK_NIL; do_format_chain = 1; @@ -639,7 +639,7 @@ int NFTL_mount(struct NFTLrecord *s) first_logical_block = logical_block; } else { if (logical_block != first_logical_block) { - printk("Block %d: incorrect logical block: %d expected: %d\n", + printk("Block %d: incorrect logical block: %d expected: %d\n", block, logical_block, first_logical_block); /* the chain is incorrect : we must format it, but we need to read it completly */ @@ -668,7 +668,7 @@ int NFTL_mount(struct NFTLrecord *s) s->ReplUnitTable[block] = BLOCK_NIL; break; } else if (rep_block >= s->nb_blocks) { - printk("Block %d: referencing invalid block %d\n", + printk("Block %d: referencing invalid block %d\n", block, rep_block); do_format_chain = 1; s->ReplUnitTable[block] = BLOCK_NIL; @@ -688,7 +688,7 @@ int NFTL_mount(struct NFTLrecord *s) s->ReplUnitTable[block] = rep_block; s->EUNtable[first_logical_block] = BLOCK_NIL; } else { - printk("Block %d: referencing block %d already in another chain\n", + printk("Block %d: referencing block %d already in another chain\n", block, rep_block); /* XXX: should handle correctly fold in progress chains */ do_format_chain = 1; @@ -710,7 +710,7 @@ int NFTL_mount(struct NFTLrecord *s) } else { unsigned int first_block1, chain_to_format, chain_length1; int fold_mark; - + /* valid chain : get foldmark */ fold_mark = get_fold_mark(s, first_block); if (fold_mark == 0) { @@ -729,9 +729,9 @@ int NFTL_mount(struct NFTLrecord *s) if (first_block1 != BLOCK_NIL) { /* XXX: what to do if same length ? */ chain_length1 = calc_chain_length(s, first_block1); - printk("Two chains at blocks %d (len=%d) and %d (len=%d)\n", + printk("Two chains at blocks %d (len=%d) and %d (len=%d)\n", first_block1, chain_length1, first_block, chain_length); - + if (chain_length >= chain_length1) { chain_to_format = first_block1; s->EUNtable[first_logical_block] = first_block; diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c index 13f9e992bef..7b7ca5ab5ae 100644 --- a/drivers/mtd/redboot.c +++ b/drivers/mtd/redboot.c @@ -1,5 +1,5 @@ /* - * $Id: redboot.c,v 1.17 2004/11/22 11:33:56 ijc Exp $ + * $Id: redboot.c,v 1.18 2005/11/07 11:14:21 gleixner Exp $ * * Parse RedBoot-style Flash Image System (FIS) tables and * produce a Linux partition array to match. @@ -39,7 +39,7 @@ static inline int redboot_checksum(struct fis_image_desc *img) return 1; } -static int parse_redboot_partitions(struct mtd_info *master, +static int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts, unsigned long fis_origin) { diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c index 7b9f359f04b..041ee59ea77 100644 --- a/drivers/mtd/rfd_ftl.c +++ b/drivers/mtd/rfd_ftl.c @@ -3,7 +3,7 @@ * * Copyright (C) 2005 Sean Young * - * $Id: rfd_ftl.c,v 1.4 2005/07/31 22:49:14 sean Exp $ + * $Id: rfd_ftl.c,v 1.5 2005/11/07 11:14:21 gleixner Exp $ * * This type of flash translation layer (FTL) is used by the Embedded BIOS * by General Software. It is known as the Resident Flash Disk (RFD), see: @@ -95,7 +95,7 @@ static int build_block_map(struct partition *part, int block_no) { struct block *block = &part->blocks[block_no]; int i; - + block->offset = part->block_size * block_no; if (le16_to_cpu(part->header_cache[0]) != RFD_MAGIC) { @@ -109,12 +109,12 @@ static int build_block_map(struct partition *part, int block_no) for (i=0; idata_sectors_per_block; i++) { u16 entry; - + entry = le16_to_cpu(part->header_cache[HEADER_MAP_OFFSET + i]); if (entry == SECTOR_DELETED) continue; - + if (entry == SECTOR_FREE) { block->free_sectors++; continue; @@ -122,9 +122,9 @@ static int build_block_map(struct partition *part, int block_no) if (entry == SECTOR_ZERO) entry = 0; - + if (entry >= part->sector_count) { - printk(KERN_NOTICE PREFIX + printk(KERN_NOTICE PREFIX "'%s': unit #%d: entry %d corrupt, " "sector %d out of range\n", part->mbd.mtd->name, block_no, i, entry); @@ -132,14 +132,14 @@ static int build_block_map(struct partition *part, int block_no) } if (part->sector_map[entry] != -1) { - printk(KERN_NOTICE PREFIX + printk(KERN_NOTICE PREFIX "'%s': more than one entry for sector %d\n", part->mbd.mtd->name, entry); part->errors = 1; continue; } - part->sector_map[entry] = block->offset + + part->sector_map[entry] = block->offset + (i + part->header_sectors_per_block) * SECTOR_SIZE; block->used_sectors++; @@ -165,14 +165,14 @@ static int scan_header(struct partition *part) return -ENOENT; /* each erase block has three bytes header, followed by the map */ - part->header_sectors_per_block = - ((HEADER_MAP_OFFSET + sectors_per_block) * + part->header_sectors_per_block = + ((HEADER_MAP_OFFSET + sectors_per_block) * sizeof(u16) + SECTOR_SIZE - 1) / SECTOR_SIZE; - part->data_sectors_per_block = sectors_per_block - + part->data_sectors_per_block = sectors_per_block - part->header_sectors_per_block; - part->header_size = (HEADER_MAP_OFFSET + + part->header_size = (HEADER_MAP_OFFSET + part->data_sectors_per_block) * sizeof(u16); part->cylinders = (part->data_sectors_per_block * @@ -188,7 +188,7 @@ static int scan_header(struct partition *part) if (!part->header_cache) goto err; - part->blocks = kcalloc(part->total_blocks, sizeof(struct block), + part->blocks = kcalloc(part->total_blocks, sizeof(struct block), GFP_KERNEL); if (!part->blocks) goto err; @@ -200,18 +200,18 @@ static int scan_header(struct partition *part) goto err; } - for (i=0; isector_count; i++) + for (i=0; isector_count; i++) part->sector_map[i] = -1; for (i=0, blocks_found=0; itotal_blocks; i++) { - rc = part->mbd.mtd->read(part->mbd.mtd, + rc = part->mbd.mtd->read(part->mbd.mtd, i * part->block_size, part->header_size, &retlen, (u_char*)part->header_cache); if (!rc && retlen != part->header_size) rc = -EIO; - if (rc) + if (rc) goto err; if (!build_block_map(part, i)) @@ -226,7 +226,7 @@ static int scan_header(struct partition *part) } if (part->reserved_block == -1) { - printk(KERN_NOTICE PREFIX "'%s': no empty erase unit found\n", + printk(KERN_NOTICE PREFIX "'%s': no empty erase unit found\n", part->mbd.mtd->name); part->errors = 1; @@ -248,7 +248,7 @@ static int rfd_ftl_readsect(struct mtd_blktrans_dev *dev, u_long sector, char *b u_long addr; size_t retlen; int rc; - + if (sector >= part->sector_count) return -EIO; @@ -266,9 +266,9 @@ static int rfd_ftl_readsect(struct mtd_blktrans_dev *dev, u_long sector, char *b } } else memset(buf, 0, SECTOR_SIZE); - + return 0; -} +} static void erase_callback(struct erase_info *erase) { @@ -288,7 +288,7 @@ static void erase_callback(struct erase_info *erase) if (erase->state != MTD_ERASE_DONE) { printk(KERN_WARNING PREFIX "erase failed at 0x%x on '%s', " - "state %d\n", erase->addr, + "state %d\n", erase->addr, part->mbd.mtd->name, erase->state); part->blocks[i].state = BLOCK_FAILED; @@ -307,17 +307,17 @@ static void erase_callback(struct erase_info *erase) part->blocks[i].used_sectors = 0; part->blocks[i].erases++; - rc = part->mbd.mtd->write(part->mbd.mtd, - part->blocks[i].offset, sizeof(magic), &retlen, + rc = part->mbd.mtd->write(part->mbd.mtd, + part->blocks[i].offset, sizeof(magic), &retlen, (u_char*)&magic); - + if (!rc && retlen != sizeof(magic)) rc = -EIO; if (rc) { printk(KERN_NOTICE PREFIX "'%s': unable to write RFD " "header at 0x%lx\n", - part->mbd.mtd->name, + part->mbd.mtd->name, part->blocks[i].offset); part->blocks[i].state = BLOCK_FAILED; } @@ -374,17 +374,17 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old map = kmalloc(part->header_size, GFP_KERNEL); if (!map) goto err2; - - rc = part->mbd.mtd->read(part->mbd.mtd, - part->blocks[block_no].offset, part->header_size, + + rc = part->mbd.mtd->read(part->mbd.mtd, + part->blocks[block_no].offset, part->header_size, &retlen, (u_char*)map); - + if (!rc && retlen != part->header_size) rc = -EIO; if (rc) { printk(KERN_NOTICE PREFIX "error reading '%s' at " - "0x%lx\n", part->mbd.mtd->name, + "0x%lx\n", part->mbd.mtd->name, part->blocks[block_no].offset); goto err; @@ -398,11 +398,11 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old if (entry == SECTOR_FREE || entry == SECTOR_DELETED) continue; - if (entry == SECTOR_ZERO) + if (entry == SECTOR_ZERO) entry = 0; /* already warned about and ignored in build_block_map() */ - if (entry >= part->sector_count) + if (entry >= part->sector_count) continue; addr = part->blocks[block_no].offset + @@ -418,7 +418,7 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old } rc = part->mbd.mtd->read(part->mbd.mtd, addr, SECTOR_SIZE, &retlen, sector_data); - + if (!rc && retlen != SECTOR_SIZE) rc = -EIO; @@ -429,11 +429,11 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old goto err; } - + rc = rfd_ftl_writesect((struct mtd_blktrans_dev*)part, entry, sector_data); - - if (rc) + + if (rc) goto err; } @@ -447,11 +447,11 @@ err3: return rc; } -static int reclaim_block(struct partition *part, u_long *old_sector) +static int reclaim_block(struct partition *part, u_long *old_sector) { int block, best_block, score, old_sector_block; int rc; - + /* we have a race if sync doesn't exist */ if (part->mbd.mtd->sync) part->mbd.mtd->sync(part->mbd.mtd); @@ -474,16 +474,16 @@ static int reclaim_block(struct partition *part, u_long *old_sector) * more removed sectors is more efficient (have to move * less). */ - if (part->blocks[block].free_sectors) + if (part->blocks[block].free_sectors) return 0; this_score = part->blocks[block].used_sectors; - if (block == old_sector_block) + if (block == old_sector_block) this_score--; else { /* no point in moving a full block */ - if (part->blocks[block].used_sectors == + if (part->blocks[block].used_sectors == part->data_sectors_per_block) continue; } @@ -529,7 +529,7 @@ static int find_free_block(const struct partition *part) stop = block; do { - if (part->blocks[block].free_sectors && + if (part->blocks[block].free_sectors && block != part->reserved_block) return block; @@ -563,7 +563,7 @@ static int find_writeable_block(struct partition *part, u_long *old_sector) } } - rc = part->mbd.mtd->read(part->mbd.mtd, part->blocks[block].offset, + rc = part->mbd.mtd->read(part->mbd.mtd, part->blocks[block].offset, part->header_size, &retlen, (u_char*)part->header_cache); if (!rc && retlen != part->header_size) @@ -571,7 +571,7 @@ static int find_writeable_block(struct partition *part, u_long *old_sector) if (rc) { printk(KERN_NOTICE PREFIX "'%s': unable to read header at " - "0x%lx\n", part->mbd.mtd->name, + "0x%lx\n", part->mbd.mtd->name, part->blocks[block].offset); goto err; } @@ -580,7 +580,7 @@ static int find_writeable_block(struct partition *part, u_long *old_sector) err: return rc; -} +} static int mark_sector_deleted(struct partition *part, u_long old_addr) { @@ -590,7 +590,7 @@ static int mark_sector_deleted(struct partition *part, u_long old_addr) u16 del = const_cpu_to_le16(SECTOR_DELETED); block = old_addr / part->block_size; - offset = (old_addr % part->block_size) / SECTOR_SIZE - + offset = (old_addr % part->block_size) / SECTOR_SIZE - part->header_sectors_per_block; addr = part->blocks[block].offset + @@ -604,7 +604,7 @@ static int mark_sector_deleted(struct partition *part, u_long old_addr) if (rc) { printk(KERN_WARNING PREFIX "error writing '%s' at " "0x%lx\n", part->mbd.mtd->name, addr); - if (rc) + if (rc) goto err; } if (block == part->current_block) @@ -627,7 +627,7 @@ static int find_free_sector(const struct partition *part, const struct block *bl i = stop = part->data_sectors_per_block - block->free_sectors; do { - if (le16_to_cpu(part->header_cache[HEADER_MAP_OFFSET + i]) + if (le16_to_cpu(part->header_cache[HEADER_MAP_OFFSET + i]) == SECTOR_FREE) return i; @@ -653,7 +653,7 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf, !part->blocks[part->current_block].free_sectors) { rc = find_writeable_block(part, old_addr); - if (rc) + if (rc) goto err; } @@ -665,10 +665,10 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf, rc = -ENOSPC; goto err; } - - addr = (i + part->header_sectors_per_block) * SECTOR_SIZE + + + addr = (i + part->header_sectors_per_block) * SECTOR_SIZE + block->offset; - rc = part->mbd.mtd->write(part->mbd.mtd, + rc = part->mbd.mtd->write(part->mbd.mtd, addr, SECTOR_SIZE, &retlen, (u_char*)buf); if (!rc && retlen != SECTOR_SIZE) @@ -677,7 +677,7 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf, if (rc) { printk(KERN_WARNING PREFIX "error writing '%s' at 0x%lx\n", part->mbd.mtd->name, addr); - if (rc) + if (rc) goto err; } @@ -697,7 +697,7 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf, if (rc) { printk(KERN_WARNING PREFIX "error writing '%s' at 0x%lx\n", part->mbd.mtd->name, addr); - if (rc) + if (rc) goto err; } block->used_sectors++; @@ -738,7 +738,7 @@ static int rfd_ftl_writesect(struct mtd_blktrans_dev *dev, u_long sector, char * break; } - if (i == SECTOR_SIZE) + if (i == SECTOR_SIZE) part->sector_map[sector] = -1; if (old_addr != -1) @@ -801,7 +801,7 @@ static void rfd_ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) if (!add_mtd_blktrans_dev((void*)part)) return; - } + } kfree(part); } @@ -828,7 +828,7 @@ struct mtd_blktrans_ops rfd_ftl_tr = { .major = RFD_FTL_MAJOR, .part_bits = PART_BITS, .readsect = rfd_ftl_readsect, - .writesect = rfd_ftl_writesect, + .writesect = rfd_ftl_writesect, .getgeo = rfd_ftl_getgeo, .add_mtd = rfd_ftl_add_mtd, .remove_dev = rfd_ftl_remove_dev, -- cgit v1.2.3 From 182ec4eee397543101a6db8906ed88727d3f7e53 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 11:16:07 +0000 Subject: [JFFS2] Clean up trailing white spaces Signed-off-by: Thomas Gleixner --- fs/Kconfig | 10 +-- fs/jffs2/background.c | 4 +- fs/jffs2/build.c | 28 ++++---- fs/jffs2/compr.c | 28 ++++---- fs/jffs2/compr.h | 4 +- fs/jffs2/compr_rtime.c | 32 ++++----- fs/jffs2/compr_rubin.c | 37 +++++----- fs/jffs2/compr_rubin.h | 6 +- fs/jffs2/compr_zlib.c | 14 ++-- fs/jffs2/comprtest.c | 30 ++++---- fs/jffs2/debug.c | 30 ++++---- fs/jffs2/debug.h | 10 +-- fs/jffs2/dir.c | 74 +++++++++---------- fs/jffs2/erase.c | 28 ++++---- fs/jffs2/file.c | 20 +++--- fs/jffs2/fs.c | 56 +++++++-------- fs/jffs2/gc.c | 112 ++++++++++++++--------------- fs/jffs2/histo.h | 2 +- fs/jffs2/histo_mips.h | 2 +- fs/jffs2/ioctl.c | 6 +- fs/jffs2/malloc.c | 4 +- fs/jffs2/nodelist.c | 170 ++++++++++++++++++++++---------------------- fs/jffs2/nodelist.h | 26 +++---- fs/jffs2/nodemgmt.c | 58 +++++++-------- fs/jffs2/os-linux.h | 8 +-- fs/jffs2/read.c | 16 ++--- fs/jffs2/readinode.c | 84 +++++++++++----------- fs/jffs2/scan.c | 52 +++++++------- fs/jffs2/summary.c | 8 +-- fs/jffs2/super.c | 16 ++--- fs/jffs2/symlink.c | 8 +-- fs/jffs2/wbuf.c | 128 ++++++++++++++++----------------- fs/jffs2/write.c | 68 +++++++++--------- include/linux/jffs2.h | 12 ++-- include/linux/jffs2_fs_i.h | 4 +- include/linux/jffs2_fs_sb.h | 14 ++-- 36 files changed, 604 insertions(+), 605 deletions(-) diff --git a/fs/Kconfig b/fs/Kconfig index 37d86c5072e..660a0c04d6b 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -1084,10 +1084,10 @@ config JFFS2_ZLIB default y help Zlib is designed to be a free, general-purpose, legally unencumbered, - lossless data-compression library for use on virtually any computer + lossless data-compression library for use on virtually any computer hardware and operating system. See for further information. - + Say 'Y' if unsure. config JFFS2_RTIME @@ -1109,7 +1109,7 @@ choice default JFFS2_CMODE_PRIORITY depends on JFFS2_FS help - You can set here the default compression mode of JFFS2 from + You can set here the default compression mode of JFFS2 from the available compression modes. Don't touch if unsure. config JFFS2_CMODE_NONE @@ -1120,13 +1120,13 @@ config JFFS2_CMODE_NONE config JFFS2_CMODE_PRIORITY bool "priority" help - Tries the compressors in a predefinied order and chooses the first + Tries the compressors in a predefinied order and chooses the first successful one. config JFFS2_CMODE_SIZE bool "size (EXPERIMENTAL)" help - Tries all compressors and chooses the one which has the smallest + Tries all compressors and chooses the one which has the smallest result. endchoice diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c index 8210ac16a36..7b77a954112 100644 --- a/fs/jffs2/background.c +++ b/fs/jffs2/background.c @@ -51,7 +51,7 @@ int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c) D1(printk(KERN_DEBUG "JFFS2: Garbage collect thread is pid %d\n", pid)); wait_for_completion(&c->gc_thread_start); } - + return ret; } @@ -101,7 +101,7 @@ static int jffs2_garbage_collect_thread(void *_c) cond_resched(); - /* Put_super will send a SIGKILL and then wait on the sem. + /* Put_super will send a SIGKILL and then wait on the sem. */ while (signal_pending(current)) { siginfo_t info; diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index af6d2ec0136..fff108bb118 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: build.c,v 1.84 2005/09/27 13:40:49 dedekind Exp $ + * $Id: build.c,v 1.85 2005/11/07 11:14:38 gleixner Exp $ * */ @@ -129,10 +129,10 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) for_each_inode(i, c, ic) { if (ic->nlink) continue; - + jffs2_build_remove_unlinked_inode(c, ic, &dead_fds); cond_resched(); - } + } dbg_fsbuild("pass 2a starting\n"); @@ -149,7 +149,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) dbg_fsbuild("pass 2a complete\n"); dbg_fsbuild("freeing temporary data structures\n"); - + /* Finally, we can scan again and free the dirent structs */ for_each_inode(i, c, ic) { while(ic->scan_dents) { @@ -161,7 +161,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) cond_resched(); } c->flags &= ~JFFS2_SB_FLAG_BUILDING; - + dbg_fsbuild("FS build complete\n"); /* Rotate the lists by some number to ensure wear levelling */ @@ -191,7 +191,7 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_full_dirent *fd; dbg_fsbuild("removing ino #%u with nlink == zero.\n", ic->ino); - + raw = ic->nodes; while (raw != (void *)ic) { struct jffs2_raw_node_ref *next = raw->next_in_ino; @@ -220,7 +220,7 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, whinged = 1; dbg_fsbuild("removing child \"%s\", ino #%u\n", fd->name, fd->ino); - + child_ic = jffs2_get_ino_cache(c, fd->ino); if (!child_ic) { dbg_fsbuild("cannot remove child \"%s\", ino #%u, because it doesn't exist\n", @@ -229,11 +229,11 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, continue; } - /* Reduce nlink of the child. If it's now zero, stick it on the + /* Reduce nlink of the child. If it's now zero, stick it on the dead_fds list to be cleaned up later. Else just free the fd */ child_ic->nlink--; - + if (!child_ic->nlink) { dbg_fsbuild("inode #%u (\"%s\") has now got zero nlink, adding to dead_fds list.\n", fd->ino, fd->name); @@ -248,7 +248,7 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, } /* - We don't delete the inocache from the hash list and free it yet. + We don't delete the inocache from the hash list and free it yet. The erase code will do that, when all the nodes are completely gone. */ } @@ -262,7 +262,7 @@ static void jffs2_calc_trigger_levels(struct jffs2_sb_info *c) because there's not enough free space... */ c->resv_blocks_deletion = 2; - /* Be conservative about how much space we need before we allow writes. + /* Be conservative about how much space we need before we allow writes. On top of that which is required for deletia, require an extra 2% of the medium to be available, for overhead caused by nodes being split across blocks, etc. */ @@ -277,7 +277,7 @@ static void jffs2_calc_trigger_levels(struct jffs2_sb_info *c) c->resv_blocks_gctrigger = c->resv_blocks_write + 1; - /* When do we allow garbage collection to merge nodes to make + /* When do we allow garbage collection to merge nodes to make long-term progress at the expense of short-term space exhaustion? */ c->resv_blocks_gcmerge = c->resv_blocks_deletion + 1; @@ -303,7 +303,7 @@ static void jffs2_calc_trigger_levels(struct jffs2_sb_info *c) c->resv_blocks_gcbad, c->resv_blocks_gcbad*c->sector_size/1024); dbg_fsbuild("Amount of dirty space required to GC: %d bytes\n", c->nospc_dirty_size); -} +} int jffs2_do_mount_fs(struct jffs2_sb_info *c) { @@ -355,7 +355,7 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) #ifndef __ECOS if (jffs2_blocks_use_vmalloc(c)) vfree(c->blocks); - else + else #endif kfree(c->blocks); diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c index c9e54b97dba..e7944e665b9 100644 --- a/fs/jffs2/compr.c +++ b/fs/jffs2/compr.c @@ -9,7 +9,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: compr.c,v 1.45 2005/07/26 13:24:40 havasi Exp $ + * $Id: compr.c,v 1.46 2005/11/07 11:14:38 gleixner Exp $ * */ @@ -36,16 +36,16 @@ static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_co * data. * * Returns: Lower byte to be stored with data indicating compression type used. - * Zero is used to show that the data could not be compressed - the + * Zero is used to show that the data could not be compressed - the * compressed version was actually larger than the original. * Upper byte will be used later. (soon) * * If the cdata buffer isn't large enough to hold all the uncompressed data, - * jffs2_compress should compress as much as will fit, and should set + * jffs2_compress should compress as much as will fit, and should set * *datalen accordingly to show the amount of data which were compressed. */ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - unsigned char *data_in, unsigned char **cpage_out, + unsigned char *data_in, unsigned char **cpage_out, uint32_t *datalen, uint32_t *cdatalen) { int ret = JFFS2_COMPR_NONE; @@ -164,7 +164,7 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, } int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - uint16_t comprtype, unsigned char *cdata_in, + uint16_t comprtype, unsigned char *cdata_in, unsigned char *data_out, uint32_t cdatalen, uint32_t datalen) { struct jffs2_compressor *this; @@ -298,7 +298,7 @@ char *jffs2_stats(void) act_buf += sprintf(act_buf,"JFFS2 compressor statistics:\n"); act_buf += sprintf(act_buf,"%10s ","none"); - act_buf += sprintf(act_buf,"compr: %d blocks (%d) decompr: %d blocks\n", none_stat_compr_blocks, + act_buf += sprintf(act_buf,"compr: %d blocks (%d) decompr: %d blocks\n", none_stat_compr_blocks, none_stat_compr_size, none_stat_decompr_blocks); spin_lock(&jffs2_compressor_list_lock); list_for_each_entry(this, &jffs2_compressor_list, list) { @@ -307,8 +307,8 @@ char *jffs2_stats(void) act_buf += sprintf(act_buf,"- "); else act_buf += sprintf(act_buf,"+ "); - act_buf += sprintf(act_buf,"compr: %d blocks (%d/%d) decompr: %d blocks ", this->stat_compr_blocks, - this->stat_compr_new_size, this->stat_compr_orig_size, + act_buf += sprintf(act_buf,"compr: %d blocks (%d/%d) decompr: %d blocks ", this->stat_compr_blocks, + this->stat_compr_new_size, this->stat_compr_orig_size, this->stat_decompr_blocks); act_buf += sprintf(act_buf,"\n"); } @@ -317,7 +317,7 @@ char *jffs2_stats(void) return buf; } -char *jffs2_get_compression_mode_name(void) +char *jffs2_get_compression_mode_name(void) { switch (jffs2_compression_mode) { case JFFS2_COMPR_MODE_NONE: @@ -330,7 +330,7 @@ char *jffs2_get_compression_mode_name(void) return "unkown"; } -int jffs2_set_compression_mode_name(const char *name) +int jffs2_set_compression_mode_name(const char *name) { if (!strcmp("none",name)) { jffs2_compression_mode = JFFS2_COMPR_MODE_NONE; @@ -355,7 +355,7 @@ static int jffs2_compressor_Xable(const char *name, int disabled) if (!strcmp(this->name, name)) { this->disabled = disabled; spin_unlock(&jffs2_compressor_list_lock); - return 0; + return 0; } } spin_unlock(&jffs2_compressor_list_lock); @@ -385,7 +385,7 @@ int jffs2_set_compressor_priority(const char *name, int priority) } } spin_unlock(&jffs2_compressor_list_lock); - printk(KERN_WARNING "JFFS2: compressor %s not found.\n",name); + printk(KERN_WARNING "JFFS2: compressor %s not found.\n",name); return 1; reinsert: /* list is sorted in the order of priority, so if @@ -412,7 +412,7 @@ void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig) kfree(comprbuf); } -int jffs2_compressors_init(void) +int jffs2_compressors_init(void) { /* Registering compressors */ #ifdef CONFIG_JFFS2_ZLIB @@ -440,7 +440,7 @@ int jffs2_compressors_init(void) return 0; } -int jffs2_compressors_exit(void) +int jffs2_compressors_exit(void) { /* Unregistering compressors */ #ifdef CONFIG_JFFS2_RUBIN diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h index 9ec6e37d383..a77e830d85c 100644 --- a/fs/jffs2/compr.h +++ b/fs/jffs2/compr.h @@ -4,10 +4,10 @@ * Copyright (C) 2004 Ferenc Havasi , * University of Szeged, Hungary * - * For licensing information, see the file 'LICENCE' in the + * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * - * $Id: compr.h,v 1.8 2005/07/26 13:24:40 havasi Exp $ + * $Id: compr.h,v 1.9 2005/11/07 11:14:38 gleixner Exp $ * */ diff --git a/fs/jffs2/compr_rtime.c b/fs/jffs2/compr_rtime.c index 39312941866..2eb1b7428d1 100644 --- a/fs/jffs2/compr_rtime.c +++ b/fs/jffs2/compr_rtime.c @@ -24,8 +24,8 @@ #include #include #include -#include -#include +#include +#include #include "compr.h" /* _compress returns the compressed size, -1 if bigger */ @@ -38,19 +38,19 @@ static int jffs2_rtime_compress(unsigned char *data_in, int outpos = 0; int pos=0; - memset(positions,0,sizeof(positions)); - + memset(positions,0,sizeof(positions)); + while (pos < (*sourcelen) && outpos <= (*dstlen)-2) { int backpos, runlen=0; unsigned char value; - + value = data_in[pos]; cpage_out[outpos++] = data_in[pos++]; - + backpos = positions[value]; positions[value]=pos; - + while ((backpos < pos) && (pos < (*sourcelen)) && (data_in[pos]==data_in[backpos++]) && (runlen<255)) { pos++; @@ -63,12 +63,12 @@ static int jffs2_rtime_compress(unsigned char *data_in, /* We failed */ return -1; } - + /* Tell the caller how much we managed to compress, and how much space it took */ *sourcelen = pos; *dstlen = outpos; return 0; -} +} static int jffs2_rtime_decompress(unsigned char *data_in, @@ -79,19 +79,19 @@ static int jffs2_rtime_decompress(unsigned char *data_in, short positions[256]; int outpos = 0; int pos=0; - - memset(positions,0,sizeof(positions)); - + + memset(positions,0,sizeof(positions)); + while (outpos= outpos) { @@ -101,12 +101,12 @@ static int jffs2_rtime_decompress(unsigned char *data_in, } } else { memcpy(&cpage_out[outpos],&cpage_out[backoffs],repeat); - outpos+=repeat; + outpos+=repeat; } } } return 0; -} +} static struct jffs2_compressor jffs2_rtime_comp = { .priority = JFFS2_RTIME_PRIORITY, diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c index 09422388fb9..e792e675d62 100644 --- a/fs/jffs2/compr_rubin.c +++ b/fs/jffs2/compr_rubin.c @@ -11,7 +11,6 @@ * */ - #include #include #include @@ -20,7 +19,7 @@ #include "compr.h" static void init_rubin(struct rubin_state *rs, int div, int *bits) -{ +{ int c; rs->q = 0; @@ -40,7 +39,7 @@ static int encode(struct rubin_state *rs, long A, long B, int symbol) while ((rs->q >= UPPER_BIT_RUBIN) || ((rs->p + rs->q) <= UPPER_BIT_RUBIN)) { rs->bit_number++; - + ret = pushbit(&rs->pp, (rs->q & UPPER_BIT_RUBIN) ? 1 : 0, 0); if (ret) return ret; @@ -68,7 +67,7 @@ static int encode(struct rubin_state *rs, long A, long B, int symbol) static void end_rubin(struct rubin_state *rs) -{ +{ int i; @@ -82,7 +81,7 @@ static void end_rubin(struct rubin_state *rs) static void init_decode(struct rubin_state *rs, int div, int *bits) { - init_rubin(rs, div, bits); + init_rubin(rs, div, bits); /* behalve lower */ rs->rec_q = 0; @@ -188,7 +187,7 @@ static int in_byte(struct rubin_state *rs) -static int rubin_do_compress(int bit_divider, int *bits, unsigned char *data_in, +static int rubin_do_compress(int bit_divider, int *bits, unsigned char *data_in, unsigned char *cpage_out, uint32_t *sourcelen, uint32_t *dstlen) { int outpos = 0; @@ -198,31 +197,31 @@ static int rubin_do_compress(int bit_divider, int *bits, unsigned char *data_in, init_pushpull(&rs.pp, cpage_out, *dstlen * 8, 0, 32); init_rubin(&rs, bit_divider, bits); - + while (pos < (*sourcelen) && !out_byte(&rs, data_in[pos])) pos++; - + end_rubin(&rs); if (outpos > pos) { /* We failed */ return -1; } - - /* Tell the caller how much we managed to compress, + + /* Tell the caller how much we managed to compress, * and how much space it took */ - + outpos = (pushedbits(&rs.pp)+7)/8; - + if (outpos >= pos) return -1; /* We didn't actually compress */ *sourcelen = pos; *dstlen = outpos; return 0; -} +} #if 0 /* _compress returns the compressed size, -1 if bigger */ -int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, +int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, uint32_t *sourcelen, uint32_t *dstlen, void *model) { return rubin_do_compress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen); @@ -277,7 +276,7 @@ static int jffs2_dynrubin_compress(unsigned char *data_in, } ret = rubin_do_compress(256, bits, data_in, cpage_out+8, &mysrclen, &mydstlen); - if (ret) + if (ret) return ret; /* Add back the 8 bytes we took for the probabilities */ @@ -293,19 +292,19 @@ static int jffs2_dynrubin_compress(unsigned char *data_in, return 0; } -static void rubin_do_decompress(int bit_divider, int *bits, unsigned char *cdata_in, +static void rubin_do_decompress(int bit_divider, int *bits, unsigned char *cdata_in, unsigned char *page_out, uint32_t srclen, uint32_t destlen) { int outpos = 0; struct rubin_state rs; - + init_pushpull(&rs.pp, cdata_in, srclen, 0, 0); init_decode(&rs, bit_divider, bits); - + while (outpos < destlen) { page_out[outpos++] = in_byte(&rs); } -} +} static int jffs2_rubinmips_decompress(unsigned char *data_in, diff --git a/fs/jffs2/compr_rubin.h b/fs/jffs2/compr_rubin.h index cf51e34f657..bf1a9345162 100644 --- a/fs/jffs2/compr_rubin.h +++ b/fs/jffs2/compr_rubin.h @@ -1,7 +1,7 @@ /* Rubin encoder/decoder header */ /* work started at : aug 3, 1994 */ /* last modification : aug 15, 1994 */ -/* $Id: compr_rubin.h,v 1.6 2002/01/25 01:49:26 dwmw2 Exp $ */ +/* $Id: compr_rubin.h,v 1.7 2005/11/07 11:14:38 gleixner Exp $ */ #include "pushpull.h" @@ -11,8 +11,8 @@ struct rubin_state { - unsigned long p; - unsigned long q; + unsigned long p; + unsigned long q; unsigned long rec_q; long bit_number; struct pushpull pp; diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c index 83f7e0788fd..4db8be8e90c 100644 --- a/fs/jffs2/compr_zlib.c +++ b/fs/jffs2/compr_zlib.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: compr_zlib.c,v 1.31 2005/05/20 19:30:06 gleixner Exp $ + * $Id: compr_zlib.c,v 1.32 2005/11/07 11:14:38 gleixner Exp $ * */ @@ -24,11 +24,11 @@ #include "nodelist.h" #include "compr.h" - /* Plan: call deflate() with avail_in == *sourcelen, - avail_out = *dstlen - 12 and flush == Z_FINISH. + /* Plan: call deflate() with avail_in == *sourcelen, + avail_out = *dstlen - 12 and flush == Z_FINISH. If it doesn't manage to finish, call it again with avail_in == 0 and avail_out set to the remaining 12 - bytes for it to clean up. + bytes for it to clean up. Q: Is 12 bytes sufficient? */ #define STREAM_END_SPACE 12 @@ -89,7 +89,7 @@ static int jffs2_zlib_compress(unsigned char *data_in, def_strm.next_in = data_in; def_strm.total_in = 0; - + def_strm.next_out = cpage_out; def_strm.total_out = 0; @@ -99,7 +99,7 @@ static int jffs2_zlib_compress(unsigned char *data_in, D1(printk(KERN_DEBUG "calling deflate with avail_in %d, avail_out %d\n", def_strm.avail_in, def_strm.avail_out)); ret = zlib_deflate(&def_strm, Z_PARTIAL_FLUSH); - D1(printk(KERN_DEBUG "deflate returned with avail_in %d, avail_out %d, total_in %ld, total_out %ld\n", + D1(printk(KERN_DEBUG "deflate returned with avail_in %d, avail_out %d, total_in %ld, total_out %ld\n", def_strm.avail_in, def_strm.avail_out, def_strm.total_in, def_strm.total_out)); if (ret != Z_OK) { D1(printk(KERN_DEBUG "deflate in loop returned %d\n", ret)); @@ -150,7 +150,7 @@ static int jffs2_zlib_decompress(unsigned char *data_in, inf_strm.next_in = data_in; inf_strm.avail_in = srclen; inf_strm.total_in = 0; - + inf_strm.next_out = cpage_out; inf_strm.avail_out = destlen; inf_strm.total_out = 0; diff --git a/fs/jffs2/comprtest.c b/fs/jffs2/comprtest.c index cf51f091d0e..f0fb8be7740 100644 --- a/fs/jffs2/comprtest.c +++ b/fs/jffs2/comprtest.c @@ -1,4 +1,4 @@ -/* $Id: comprtest.c,v 1.5 2002/01/03 15:20:44 dwmw2 Exp $ */ +/* $Id: comprtest.c,v 1.6 2005/11/07 11:14:38 gleixner Exp $ */ #include #include @@ -265,9 +265,9 @@ static unsigned char testdata[TESTDATA_LEN] = { static unsigned char comprbuf[TESTDATA_LEN]; static unsigned char decomprbuf[TESTDATA_LEN]; -int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in, +int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in, unsigned char *data_out, uint32_t cdatalen, uint32_t datalen); -unsigned char jffs2_compress(unsigned char *data_in, unsigned char *cpage_out, +unsigned char jffs2_compress(unsigned char *data_in, unsigned char *cpage_out, uint32_t *datalen, uint32_t *cdatalen); int init_module(void ) { @@ -276,10 +276,10 @@ int init_module(void ) { int ret; printk("Original data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - testdata[0],testdata[1],testdata[2],testdata[3], - testdata[4],testdata[5],testdata[6],testdata[7], - testdata[8],testdata[9],testdata[10],testdata[11], - testdata[12],testdata[13],testdata[14],testdata[15]); + testdata[0],testdata[1],testdata[2],testdata[3], + testdata[4],testdata[5],testdata[6],testdata[7], + testdata[8],testdata[9],testdata[10],testdata[11], + testdata[12],testdata[13],testdata[14],testdata[15]); d = TESTDATA_LEN; c = TESTDATA_LEN; comprtype = jffs2_compress(testdata, comprbuf, &d, &c); @@ -287,18 +287,18 @@ int init_module(void ) { printk("jffs2_compress used compression type %d. Compressed size %d, uncompressed size %d\n", comprtype, c, d); printk("Compressed data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - comprbuf[0],comprbuf[1],comprbuf[2],comprbuf[3], - comprbuf[4],comprbuf[5],comprbuf[6],comprbuf[7], - comprbuf[8],comprbuf[9],comprbuf[10],comprbuf[11], - comprbuf[12],comprbuf[13],comprbuf[14],comprbuf[15]); + comprbuf[0],comprbuf[1],comprbuf[2],comprbuf[3], + comprbuf[4],comprbuf[5],comprbuf[6],comprbuf[7], + comprbuf[8],comprbuf[9],comprbuf[10],comprbuf[11], + comprbuf[12],comprbuf[13],comprbuf[14],comprbuf[15]); ret = jffs2_decompress(comprtype, comprbuf, decomprbuf, c, d); printk("jffs2_decompress returned %d\n", ret); printk("Decompressed data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - decomprbuf[0],decomprbuf[1],decomprbuf[2],decomprbuf[3], - decomprbuf[4],decomprbuf[5],decomprbuf[6],decomprbuf[7], - decomprbuf[8],decomprbuf[9],decomprbuf[10],decomprbuf[11], - decomprbuf[12],decomprbuf[13],decomprbuf[14],decomprbuf[15]); + decomprbuf[0],decomprbuf[1],decomprbuf[2],decomprbuf[3], + decomprbuf[4],decomprbuf[5],decomprbuf[6],decomprbuf[7], + decomprbuf[8],decomprbuf[9],decomprbuf[10],decomprbuf[11], + decomprbuf[12],decomprbuf[13],decomprbuf[14],decomprbuf[15]); if (memcmp(decomprbuf, testdata, d)) printk("Compression and decompression corrupted data\n"); else diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c index 0947284f45d..1fe17de713e 100644 --- a/fs/jffs2/debug.c +++ b/fs/jffs2/debug.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.c,v 1.11 2005/09/21 13:28:35 dedekind Exp $ + * $Id: debug.c,v 1.12 2005/11/07 11:14:39 gleixner Exp $ * */ #include @@ -67,7 +67,7 @@ __jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f) __jffs2_dbg_fragtree_paranoia_check_nolock(f); up(&f->sem); } - + void __jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f) { @@ -165,7 +165,7 @@ __jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c, __jffs2_dbg_acct_paranoia_check_nolock(c, jeb); spin_unlock(&c->erase_completion_lock); } - + void __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) @@ -237,7 +237,7 @@ error: __jffs2_dbg_dump_jeb_nolock(jeb); __jffs2_dbg_dump_block_lists_nolock(c); BUG(); - + } #endif /* JFFS2_DBG_PARANOIA_CHECKS */ @@ -321,7 +321,7 @@ void __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) { printk(JFFS2_DBG_MSG_PREFIX " dump JFFS2 blocks lists:\n"); - + printk(JFFS2_DBG "flash_size: %#08x\n", c->flash_size); printk(JFFS2_DBG "used_size: %#08x\n", c->used_size); printk(JFFS2_DBG "dirty_size: %#08x\n", c->dirty_size); @@ -577,15 +577,15 @@ __jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs) { int skip; int i; - + printk(JFFS2_DBG_MSG_PREFIX " dump from offset %#08x to offset %#08x (%x bytes).\n", offs, offs + len, len); i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE; offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1); - + if (skip != 0) printk(JFFS2_DBG "%#08x: ", offs); - + while (skip--) printk(" "); @@ -598,7 +598,7 @@ __jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs) } printk("%02x ", buf[i]); - + i += 1; } @@ -616,7 +616,7 @@ __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs) size_t retlen; uint32_t crc; int ret; - + printk(JFFS2_DBG_MSG_PREFIX " dump node at offset %#08x.\n", ofs); ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node); @@ -630,13 +630,13 @@ __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs) printk(JFFS2_DBG "nodetype:\t%#04x\n", je16_to_cpu(node.u.nodetype)); printk(JFFS2_DBG "totlen:\t%#08x\n", je32_to_cpu(node.u.totlen)); printk(JFFS2_DBG "hdr_crc:\t%#08x\n", je32_to_cpu(node.u.hdr_crc)); - + crc = crc32(0, &node.u, sizeof(node.u) - 4); if (crc != je32_to_cpu(node.u.hdr_crc)) { JFFS2_ERROR("wrong common header CRC.\n"); return; } - + if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK && je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK) { @@ -668,7 +668,7 @@ __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs) printk(JFFS2_DBG "data_crc:\t%#08x\n", je32_to_cpu(node.i.data_crc)); printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.i.node_crc)); - crc = crc32(0, &node.i, sizeof(node.i) - 8); + crc = crc32(0, &node.i, sizeof(node.i) - 8); if (crc != je32_to_cpu(node.i.node_crc)) { JFFS2_ERROR("wrong node header CRC.\n"); return; @@ -686,11 +686,11 @@ __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs) printk(JFFS2_DBG "type:\t%#02x\n", node.d.type); printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.d.node_crc)); printk(JFFS2_DBG "name_crc:\t%#08x\n", je32_to_cpu(node.d.name_crc)); - + node.d.name[node.d.nsize] = '\0'; printk(JFFS2_DBG "name:\t\"%s\"\n", node.d.name); - crc = crc32(0, &node.d, sizeof(node.d) - 8); + crc = crc32(0, &node.d, sizeof(node.d) - 8); if (crc != je32_to_cpu(node.d.node_crc)) { JFFS2_ERROR("wrong node header CRC.\n"); return; diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index b47ba9f1d60..f193d43a8a5 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.h,v 1.20 2005/10/24 16:22:34 dedekind Exp $ + * $Id: debug.h,v 1.21 2005/11/07 11:14:39 gleixner Exp $ * */ #ifndef _JFFS2_DEBUG_H_ @@ -24,7 +24,7 @@ #define JFFS2_DBG_PARANOIA_CHECKS #define JFFS2_DBG_DUMPS -/* +/* * By defining/undefining the below macros one may select debugging messages * fro specific JFFS2 subsystems. */ @@ -45,7 +45,7 @@ /* Sanity checks are supposed to be light-weight and enabled by default */ #define JFFS2_DBG_SANITY_CHECKS -/* +/* * Dx() are mainly used for debugging messages, they must go away and be * superseded by nicer dbg_xxx() macros... */ @@ -91,7 +91,7 @@ " (%d) %s: " fmt, current->pid, \ __FUNCTION__, ##__VA_ARGS__); \ } while(0) - + #define JFFS2_NOTICE(fmt, ...) \ do { \ printk(JFFS2_NOTICE_MSG_PREFIX \ @@ -106,7 +106,7 @@ __FUNCTION__, ##__VA_ARGS__); \ } while(0) -/* +/* * We split our debugging messages on several parts, depending on the JFFS2 * subsystem the message belongs to. */ diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 19bea0f95ac..a7bf9cb2567 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: dir.c,v 1.89 2005/09/07 08:34:54 havasi Exp $ + * $Id: dir.c,v 1.90 2005/11/07 11:14:39 gleixner Exp $ * */ @@ -64,7 +64,7 @@ struct inode_operations jffs2_dir_inode_operations = /* We keep the dirent list sorted in increasing order of name hash, - and we use the same hash function as the dentries. Makes this + and we use the same hash function as the dentries. Makes this nice and simple */ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target, @@ -85,7 +85,7 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target, /* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */ for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= target->d_name.hash; fd_list = fd_list->next) { - if (fd_list->nhash == target->d_name.hash && + if (fd_list->nhash == target->d_name.hash && (!fd || fd_list->version > fd->version) && strlen(fd_list->name) == target->d_name.len && !strncmp(fd_list->name, target->d_name.name, target->d_name.len)) { @@ -147,7 +147,7 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir) curofs++; /* First loop: curofs = 2; offset = 2 */ if (curofs < offset) { - D2(printk(KERN_DEBUG "Skipping dirent: \"%s\", ino #%u, type %d, because curofs %ld < offset %ld\n", + D2(printk(KERN_DEBUG "Skipping dirent: \"%s\", ino #%u, type %d, because curofs %ld < offset %ld\n", fd->name, fd->ino, fd->type, curofs, offset)); continue; } @@ -182,7 +182,7 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode, ri = jffs2_alloc_raw_inode(); if (!ri) return -ENOMEM; - + c = JFFS2_SB_INFO(dir_i->i_sb); D1(printk(KERN_DEBUG "jffs2_create()\n")); @@ -203,7 +203,7 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode, f = JFFS2_INODE_INFO(inode); dir_f = JFFS2_INODE_INFO(dir_i); - ret = jffs2_do_create(c, dir_f, f, ri, + ret = jffs2_do_create(c, dir_f, f, ri, dentry->d_name.name, dentry->d_name.len); if (ret) { @@ -234,7 +234,7 @@ static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry) int ret; uint32_t now = get_seconds(); - ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, + ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, dentry->d_name.len, dead_f, now); if (dead_f->inocache) dentry->d_inode->i_nlink = dead_f->inocache->nlink; @@ -303,11 +303,11 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char if (!ri) return -ENOMEM; - + c = JFFS2_SB_INFO(dir_i->i_sb); - - /* Try to reserve enough space for both node and dirent. - * Just the node will do for now, though + + /* Try to reserve enough space for both node and dirent. + * Just the node will do for now, though */ namelen = dentry->d_name.len; ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &phys_ofs, &alloclen, @@ -338,7 +338,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char ri->compr = JFFS2_COMPR_NONE; ri->data_crc = cpu_to_je32(crc32(0, target, targetlen)); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - + fn = jffs2_write_dnode(c, f, ri, target, targetlen, phys_ofs, ALLOC_NORMAL); jffs2_free_raw_inode(ri); @@ -364,7 +364,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char memcpy(f->target, target, targetlen + 1); D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached\n", (char *)f->target)); - /* No data here. Only a metadata node, which will be + /* No data here. Only a metadata node, which will be obsoleted by the first data write */ f->metadata = fn; @@ -407,7 +407,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); if (IS_ERR(fd)) { - /* dirent failed to write. Delete the inode normally + /* dirent failed to write. Delete the inode normally as if it were the final unlink() */ jffs2_complete_reservation(c); jffs2_free_raw_dirent(rd); @@ -450,11 +450,11 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) ri = jffs2_alloc_raw_inode(); if (!ri) return -ENOMEM; - + c = JFFS2_SB_INFO(dir_i->i_sb); - /* Try to reserve enough space for both node and dirent. - * Just the node will do for now, though + /* Try to reserve enough space for both node and dirent. + * Just the node will do for now, though */ namelen = dentry->d_name.len; ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL, @@ -482,7 +482,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) ri->data_crc = cpu_to_je32(0); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - + fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL); jffs2_free_raw_inode(ri); @@ -494,7 +494,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) jffs2_clear_inode(inode); return PTR_ERR(fn); } - /* No data here. Only a metadata node, which will be + /* No data here. Only a metadata node, which will be obsoleted by the first data write */ f->metadata = fn; @@ -508,7 +508,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) jffs2_clear_inode(inode); return ret; } - + rd = jffs2_alloc_raw_dirent(); if (!rd) { /* Argh. Now we treat it like a normal delete */ @@ -535,9 +535,9 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); - + if (IS_ERR(fd)) { - /* dirent failed to write. Delete the inode normally + /* dirent failed to write. Delete the inode normally as if it were the final unlink() */ jffs2_complete_reservation(c); jffs2_free_raw_dirent(rd); @@ -599,16 +599,16 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de ri = jffs2_alloc_raw_inode(); if (!ri) return -ENOMEM; - + c = JFFS2_SB_INFO(dir_i->i_sb); - + if (S_ISBLK(mode) || S_ISCHR(mode)) { dev = cpu_to_je16(old_encode_dev(rdev)); devlen = sizeof(dev); } - - /* Try to reserve enough space for both node and dirent. - * Just the node will do for now, though + + /* Try to reserve enough space for both node and dirent. + * Just the node will do for now, though */ namelen = dentry->d_name.len; ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &phys_ofs, &alloclen, @@ -638,7 +638,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de ri->compr = JFFS2_COMPR_NONE; ri->data_crc = cpu_to_je32(crc32(0, &dev, devlen)); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - + fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, phys_ofs, ALLOC_NORMAL); jffs2_free_raw_inode(ri); @@ -650,7 +650,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de jffs2_clear_inode(inode); return PTR_ERR(fn); } - /* No data here. Only a metadata node, which will be + /* No data here. Only a metadata node, which will be obsoleted by the first data write */ f->metadata = fn; @@ -694,9 +694,9 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); - + if (IS_ERR(fd)) { - /* dirent failed to write. Delete the inode normally + /* dirent failed to write. Delete the inode normally as if it were the final unlink() */ jffs2_complete_reservation(c); jffs2_free_raw_dirent(rd); @@ -730,7 +730,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, uint8_t type; uint32_t now; - /* The VFS will check for us and prevent trying to rename a + /* The VFS will check for us and prevent trying to rename a * file over a directory and vice versa, but if it's a directory, * the VFS can't check whether the victim is empty. The filesystem * needs to do that for itself. @@ -752,18 +752,18 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, } /* XXX: We probably ought to alloc enough space for - both nodes at the same time. Writing the new link, + both nodes at the same time. Writing the new link, then getting -ENOSPC, is quite bad :) */ /* Make a hard link */ - + /* XXX: This is ugly */ type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12; if (!type) type = DT_REG; now = get_seconds(); - ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i), + ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i), old_dentry->d_inode->i_ino, type, new_dentry->d_name.name, new_dentry->d_name.len, now); @@ -782,13 +782,13 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, } } - /* If it was a directory we moved, and there was no victim, + /* If it was a directory we moved, and there was no victim, increase i_nlink on its new parent */ if (S_ISDIR(old_dentry->d_inode->i_mode) && !victim_f) new_dir_i->i_nlink++; /* Unlink the original */ - ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), + ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), old_dentry->d_name.name, old_dentry->d_name.len, NULL, now); /* We don't touch inode->i_nlink */ diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index 347de4efeee..dad68fdffe9 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -24,7 +24,7 @@ struct erase_priv_struct { struct jffs2_eraseblock *jeb; struct jffs2_sb_info *c; }; - + #ifndef __ECOS static void jffs2_erase_callback(struct erase_info *); #endif @@ -71,7 +71,7 @@ static void jffs2_erase_block(struct jffs2_sb_info *c, instr->callback = jffs2_erase_callback; instr->priv = (unsigned long)(&instr[1]); instr->fail_addr = 0xffffffff; - + ((struct erase_priv_struct *)instr->priv)->jeb = jeb; ((struct erase_priv_struct *)instr->priv)->c = c; @@ -96,7 +96,7 @@ static void jffs2_erase_block(struct jffs2_sb_info *c, return; } - if (ret == -EROFS) + if (ret == -EROFS) printk(KERN_WARNING "Erase at 0x%08x failed immediately: -EROFS. Is the sector locked?\n", jeb->offset); else printk(KERN_WARNING "Erase at 0x%08x failed immediately: errno %d\n", jeb->offset, ret); @@ -197,7 +197,7 @@ static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock c->nr_erasing_blocks--; spin_unlock(&c->erase_completion_lock); wake_up(&c->erase_wait); -} +} #ifndef __ECOS static void jffs2_erase_callback(struct erase_info *instr) @@ -209,7 +209,7 @@ static void jffs2_erase_callback(struct erase_info *instr) jffs2_erase_failed(priv->c, priv->jeb, instr->fail_addr); } else { jffs2_erase_succeeded(priv->c, priv->jeb); - } + } kfree(instr); } #endif /* !__ECOS */ @@ -227,13 +227,13 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c, /* Walk the inode's list once, removing any nodes from this eraseblock */ while (1) { if (!(*prev)->next_in_ino) { - /* We're looking at the jffs2_inode_cache, which is + /* We're looking at the jffs2_inode_cache, which is at the end of the linked list. Stash it and continue from the beginning of the list */ ic = (struct jffs2_inode_cache *)(*prev); prev = &ic->nodes; continue; - } + } if (SECTOR_ADDR((*prev)->flash_offset) == jeb->offset) { /* It's in the block we're erasing */ @@ -267,7 +267,7 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c, printk(KERN_DEBUG "After remove_node_refs_from_ino_list: \n" KERN_DEBUG); this = ic->nodes; - + while(this) { printk( "0x%08x(%d)->", ref_offset(this), ref_flags(this)); if (++i == 5) { @@ -290,7 +290,7 @@ static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_erase while(jeb->first_node) { ref = jeb->first_node; jeb->first_node = ref->next_phys; - + /* Remove from the inode-list */ if (ref->next_in_ino) jffs2_remove_node_refs_from_ino_list(c, ref, jeb); @@ -307,7 +307,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl uint32_t ofs; size_t retlen; int ret = -EIO; - + ebuf = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!ebuf) { printk(KERN_WARNING "Failed to allocate page buffer for verifying erase at 0x%08x. Refiling\n", jeb->offset); @@ -361,7 +361,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb case -EIO: goto filebad; } - /* Write the erase complete marker */ + /* Write the erase complete marker */ D1(printk(KERN_DEBUG "Writing erased marker to block at 0x%08x\n", jeb->offset)); bad_offset = jeb->offset; @@ -399,7 +399,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb vecs[0].iov_base = (unsigned char *) ▮ vecs[0].iov_len = sizeof(marker); ret = jffs2_flash_direct_writev(c, vecs, 1, jeb->offset, &retlen); - + if (ret || retlen != sizeof(marker)) { if (ret) printk(KERN_WARNING "Write clean marker to block at 0x%08x failed: %d\n", @@ -416,9 +416,9 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb marker_ref->next_phys = NULL; marker_ref->flash_offset = jeb->offset | REF_NORMAL; marker_ref->__totlen = c->cleanmarker_size; - + jeb->first_node = jeb->last_node = marker_ref; - + jeb->free_size = c->sector_size - c->cleanmarker_size; jeb->used_size = c->cleanmarker_size; jeb->dirty_size = 0; diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index 605ea6b0b47..935f273dc57 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c @@ -34,8 +34,8 @@ int jffs2_fsync(struct file *filp, struct dentry *dentry, int datasync) /* Trigger GC to flush any pending writes for this inode */ jffs2_flush_wbuf_gc(c, inode->i_ino); - - return 0; + + return 0; } struct file_operations jffs2_file_operations = @@ -107,7 +107,7 @@ static int jffs2_readpage (struct file *filp, struct page *pg) { struct jffs2_inode_info *f = JFFS2_INODE_INFO(pg->mapping->host); int ret; - + down(&f->sem); ret = jffs2_do_readpage_unlock(pg->mapping->host, pg); up(&f->sem); @@ -130,7 +130,7 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg, struct jffs2_raw_inode ri; struct jffs2_full_dnode *fn; uint32_t phys_ofs, alloc_len; - + D1(printk(KERN_DEBUG "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", (unsigned int)inode->i_size, pageofs)); @@ -160,7 +160,7 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg, ri.compr = JFFS2_COMPR_ZERO; ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); ri.data_crc = cpu_to_je32(0); - + fn = jffs2_write_dnode(c, f, &ri, NULL, 0, phys_ofs, ALLOC_NORMAL); if (IS_ERR(fn)) { @@ -187,7 +187,7 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg, inode->i_size = pageofs; up(&f->sem); } - + /* Read in the page if it wasn't already present, unless it's a whole page */ if (!PageUptodate(pg) && (start || end < PAGE_CACHE_SIZE)) { down(&f->sem); @@ -218,7 +218,7 @@ static int jffs2_commit_write (struct file *filp, struct page *pg, if (!start && end == PAGE_CACHE_SIZE) { /* We need to avoid deadlock with page_cache_read() in jffs2_garbage_collect_pass(). So we have to mark the - page up to date, to prevent page_cache_read() from + page up to date, to prevent page_cache_read() from trying to re-lock it. */ SetPageUptodate(pg); } @@ -252,7 +252,7 @@ static int jffs2_commit_write (struct file *filp, struct page *pg, /* There was an error writing. */ SetPageError(pg); } - + /* Adjust writtenlen for the padding we did, so we don't confuse our caller */ if (writtenlen < (start&3)) writtenlen = 0; @@ -263,7 +263,7 @@ static int jffs2_commit_write (struct file *filp, struct page *pg, if (inode->i_size < (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen) { inode->i_size = (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen; inode->i_blocks = (inode->i_size + 511) >> 9; - + inode->i_ctime = inode->i_mtime = ITIME(je32_to_cpu(ri->ctime)); } } @@ -272,7 +272,7 @@ static int jffs2_commit_write (struct file *filp, struct page *pg, if (start+writtenlen < end) { /* generic_file_write has written more to the page cache than we've - actually written to the medium. Mark the page !Uptodate so that + actually written to the medium. Mark the page !Uptodate so that it gets reread */ D1(printk(KERN_DEBUG "jffs2_commit_write(): Not all bytes written. Marking page !uptodate\n")); SetPageError(pg); diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index b0b96d7272d..543420665c5 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -40,7 +40,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) int ret; D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino)); ret = inode_change_ok(inode, iattr); - if (ret) + if (ret) return ret; /* Special cases - we don't want more than one data node @@ -73,7 +73,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) kfree(mdata); return -ENOMEM; } - + ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) { @@ -84,7 +84,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) } down(&f->sem); ivalid = iattr->ia_valid; - + ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); ri->totlen = cpu_to_je32(sizeof(*ri) + mdatalen); @@ -100,7 +100,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) if (iattr->ia_mode & S_ISGID && !in_group_p(je16_to_cpu(ri->gid)) && !capable(CAP_FSETID)) ri->mode = cpu_to_jemode(iattr->ia_mode & ~S_ISGID); - else + else ri->mode = cpu_to_jemode(iattr->ia_mode); else ri->mode = cpu_to_jemode(inode->i_mode); @@ -129,7 +129,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, phys_ofs, ALLOC_NORMAL); if (S_ISLNK(inode->i_mode)) kfree(mdata); - + if (IS_ERR(new_metadata)) { jffs2_complete_reservation(c); jffs2_free_raw_inode(ri); @@ -167,7 +167,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) jffs2_complete_reservation(c); /* We have to do the vmtruncate() without f->sem held, since - some pages may be locked and waiting for it in readpage(). + some pages may be locked and waiting for it in readpage(). We are protected from a simultaneous write() extending i_size back past iattr->ia_size, because do_truncate() holds the generic inode semaphore. */ @@ -210,12 +210,12 @@ int jffs2_statfs(struct super_block *sb, struct kstatfs *buf) void jffs2_clear_inode (struct inode *inode) { - /* We can forget about this inode for now - drop all + /* We can forget about this inode for now - drop all * the nodelists associated with it, etc. */ struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - + D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode)); jffs2_do_clear_inode(c, f); @@ -234,7 +234,7 @@ void jffs2_read_inode (struct inode *inode) c = JFFS2_SB_INFO(inode->i_sb); jffs2_init_inode_info(f); - + ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node); if (ret) { @@ -254,14 +254,14 @@ void jffs2_read_inode (struct inode *inode) inode->i_blksize = PAGE_SIZE; inode->i_blocks = (inode->i_size + 511) >> 9; - + switch (inode->i_mode & S_IFMT) { jint16_t rdev; case S_IFLNK: inode->i_op = &jffs2_symlink_inode_operations; break; - + case S_IFDIR: { struct jffs2_full_dirent *fd; @@ -298,7 +298,7 @@ void jffs2_read_inode (struct inode *inode) jffs2_do_clear_inode(c, f); make_bad_inode(inode); return; - } + } case S_IFSOCK: case S_IFIFO: @@ -354,11 +354,11 @@ int jffs2_remount_fs (struct super_block *sb, int *flags, char *data) down(&c->alloc_sem); jffs2_flush_wbuf_pad(c); up(&c->alloc_sem); - } + } if (!(*flags & MS_RDONLY)) jffs2_start_garbage_collect_thread(c); - + *flags |= MS_NOATIME; return 0; @@ -392,9 +392,9 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i D1(printk(KERN_DEBUG "jffs2_new_inode(): dir_i %ld, mode 0x%x\n", dir_i->i_ino, mode)); c = JFFS2_SB_INFO(sb); - + inode = new_inode(sb); - + if (!inode) return ERR_PTR(-ENOMEM); @@ -458,14 +458,14 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) #endif c->flash_size = c->mtd->size; - c->sector_size = c->mtd->erasesize; + c->sector_size = c->mtd->erasesize; blocks = c->flash_size / c->sector_size; /* * Size alignment check */ if ((c->sector_size * blocks) != c->flash_size) { - c->flash_size = c->sector_size * blocks; + c->flash_size = c->sector_size * blocks; printk(KERN_INFO "jffs2: Flash size not aligned to erasesize, reducing to %dKiB\n", c->flash_size / 1024); } @@ -543,16 +543,16 @@ struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic; if (!nlink) { /* The inode has zero nlink but its nodes weren't yet marked - obsolete. This has to be because we're still waiting for + obsolete. This has to be because we're still waiting for the final (close() and) iput() to happen. - There's a possibility that the final iput() could have + There's a possibility that the final iput() could have happened while we were contemplating. In order to ensure that we don't cause a new read_inode() (which would fail) for the inode in question, we use ilookup() in this case instead of iget(). - The nlink can't _become_ zero at this point because we're + The nlink can't _become_ zero at this point because we're holding the alloc_sem, and jffs2_do_unlink() would also need that while decrementing nlink on any inode. */ @@ -599,19 +599,19 @@ struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, return JFFS2_INODE_INFO(inode); } -unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, - struct jffs2_inode_info *f, +unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, + struct jffs2_inode_info *f, unsigned long offset, unsigned long *priv) { struct inode *inode = OFNI_EDONI_2SFFJ(f); struct page *pg; - pg = read_cache_page(inode->i_mapping, offset >> PAGE_CACHE_SHIFT, + pg = read_cache_page(inode->i_mapping, offset >> PAGE_CACHE_SHIFT, (void *)jffs2_do_readpage_unlock, inode); if (IS_ERR(pg)) return (void *)pg; - + *priv = (unsigned long)pg; return kmap(pg); } @@ -628,7 +628,7 @@ void jffs2_gc_release_page(struct jffs2_sb_info *c, static int jffs2_flash_setup(struct jffs2_sb_info *c) { int ret = 0; - + if (jffs2_cleanmarker_oob(c)) { /* NAND flash... do setup accordingly */ ret = jffs2_nand_flash_setup(c); @@ -642,7 +642,7 @@ static int jffs2_flash_setup(struct jffs2_sb_info *c) { if (ret) return ret; } - + /* and Dataflash */ if (jffs2_dataflash(c)) { ret = jffs2_dataflash_setup(c); @@ -670,7 +670,7 @@ void jffs2_flash_cleanup(struct jffs2_sb_info *c) { if (jffs2_nor_ecc(c)) { jffs2_nor_ecc_flash_cleanup(c); } - + /* and DataFlash */ if (jffs2_dataflash(c)) { jffs2_dataflash_cleanup(c); diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index ee54cdc59e0..f9ffece453a 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: gc.c,v 1.154 2005/09/07 08:34:54 havasi Exp $ + * $Id: gc.c,v 1.155 2005/11/07 11:14:39 gleixner Exp $ * */ @@ -21,14 +21,14 @@ #include "nodelist.h" #include "compr.h" -static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, +static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, struct jffs2_raw_node_ref *raw); -static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_inode_info *f, struct jffs2_full_dnode *fd); -static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_inode_info *f, struct jffs2_full_dirent *fd); -static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_inode_info *f, struct jffs2_full_dirent *fd); static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, @@ -55,7 +55,7 @@ again: D1(printk(KERN_DEBUG "Picking block from bad_used_list to GC next\n")); nextlist = &c->bad_used_list; } else if (n < 50 && !list_empty(&c->erasable_list)) { - /* Note that most of them will have gone directly to be erased. + /* Note that most of them will have gone directly to be erased. So don't favour the erasable_list _too_ much. */ D1(printk(KERN_DEBUG "Picking block from erasable_list to GC next\n")); nextlist = &c->erasable_list; @@ -101,7 +101,7 @@ again: printk(KERN_WARNING "Eep. ret->gc_node for block at 0x%08x is NULL\n", ret->offset); BUG(); } - + /* Have we accidentally picked a clean block with wasted space ? */ if (ret->wasted_size) { D1(printk(KERN_DEBUG "Converting wasted_size %08x to dirty_size\n", ret->wasted_size)); @@ -136,7 +136,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) /* We can't start doing GC yet. We haven't finished checking the node CRCs etc. Do it now. */ - + /* checked_ino is protected by the alloc_sem */ if (c->checked_ino > c->highest_ino) { printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n", @@ -178,7 +178,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) case INO_STATE_READING: /* We need to wait for it to finish, lest we move on - and trigger the BUG() above while we haven't yet + and trigger the BUG() above while we haven't yet finished checking all its nodes */ D1(printk(KERN_DEBUG "Waiting for ino #%u to finish reading\n", ic->ino)); up(&c->alloc_sem); @@ -228,13 +228,13 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) } raw = jeb->gc_node; - + while(ref_obsolete(raw)) { D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", ref_offset(raw))); raw = raw->next_phys; if (unlikely(!raw)) { printk(KERN_WARNING "eep. End of raw list while still supposedly nodes to GC\n"); - printk(KERN_WARNING "erase block at 0x%08x. free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x\n", + printk(KERN_WARNING "erase block at 0x%08x. free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x\n", jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size); jeb->gc_node = raw; spin_unlock(&c->erase_completion_lock); @@ -259,7 +259,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) ic = jffs2_raw_ref_to_ic(raw); /* We need to hold the inocache. Either the erase_completion_lock or - the inocache_lock are sufficient; we trade down since the inocache_lock + the inocache_lock are sufficient; we trade down since the inocache_lock causes less contention. */ spin_lock(&c->inocache_lock); @@ -278,14 +278,14 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) switch(ic->state) { case INO_STATE_CHECKEDABSENT: - /* It's been checked, but it's not currently in-core. + /* It's been checked, but it's not currently in-core. We can just copy any pristine nodes, but have to prevent anyone else from doing read_inode() while we're at it, so we set the state accordingly */ if (ref_flags(raw) == REF_PRISTINE) ic->state = INO_STATE_GC; else { - D1(printk(KERN_DEBUG "Ino #%u is absent but node not REF_PRISTINE. Reading.\n", + D1(printk(KERN_DEBUG "Ino #%u is absent but node not REF_PRISTINE. Reading.\n", ic->ino)); } break; @@ -298,8 +298,8 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) case INO_STATE_CHECKING: case INO_STATE_GC: /* Should never happen. We should have finished checking - by the time we actually start doing any GC, and since - we're holding the alloc_sem, no other garbage collection + by the time we actually start doing any GC, and since + we're holding the alloc_sem, no other garbage collection can happen. */ printk(KERN_CRIT "Inode #%u already in state %d in jffs2_garbage_collect_pass()!\n", @@ -319,21 +319,21 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() waiting for ino #%u in state %d\n", ic->ino, ic->state)); sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); - /* And because we dropped the alloc_sem we must start again from the + /* And because we dropped the alloc_sem we must start again from the beginning. Ponder chance of livelock here -- we're returning success without actually making any progress. - Q: What are the chances that the inode is back in INO_STATE_READING + Q: What are the chances that the inode is back in INO_STATE_READING again by the time we next enter this function? And that this happens enough times to cause a real delay? - A: Small enough that I don't care :) + A: Small enough that I don't care :) */ return 0; } /* OK. Now if the inode is in state INO_STATE_GC, we are going to copy the - node intact, and we don't have to muck about with the fragtree etc. + node intact, and we don't have to muck about with the fragtree etc. because we know it's not in-core. If it _was_ in-core, we go through all the iget() crap anyway */ @@ -453,7 +453,7 @@ static int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_era if (!ret) { /* Urgh. Return it sensibly. */ frag->node->raw = f->inocache->nodes; - } + } if (ret != -EBADFD) goto upnout; } @@ -467,7 +467,7 @@ static int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_era } goto upnout; } - + /* Wasn't a dnode. Try dirent */ for (fd = f->dents; fd; fd=fd->next) { if (fd->raw == raw) @@ -494,7 +494,7 @@ static int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_era return ret; } -static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, +static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, struct jffs2_raw_node_ref *raw) { @@ -580,7 +580,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, } break; default: - printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n", + printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n", ref_offset(raw), je16_to_cpu(node->u.nodetype)); goto bail; } @@ -621,7 +621,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, retried = 1; D1(printk(KERN_DEBUG "Retrying failed write of REF_PRISTINE node.\n")); - + jffs2_dbg_acct_sanity_check(c,jeb); jffs2_dbg_acct_paranoia_check(c, jeb); @@ -669,7 +669,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, goto out_node; } -static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn) { struct jffs2_full_dnode *new_fn; @@ -684,7 +684,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ S_ISCHR(JFFS2_F_I_MODE(f)) ) { /* For these, we don't actually need to read the old node */ /* FIXME: for minor or major > 255. */ - dev = cpu_to_je16(((JFFS2_F_I_RDEV_MAJ(f) << 8) | + dev = cpu_to_je16(((JFFS2_F_I_RDEV_MAJ(f) << 8) | JFFS2_F_I_RDEV_MIN(f))); mdata = (char *)&dev; mdatalen = sizeof(dev); @@ -705,7 +705,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bites of symlink target\n", mdatalen)); } - + ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &phys_ofs, &alloclen, JFFS2_SUMMARY_INODE_SIZE); if (ret) { @@ -713,7 +713,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ sizeof(ri)+ mdatalen, ret); goto out; } - + last_frag = frag_last(&f->fragtree); if (last_frag) /* Fetch the inode length from the fragtree rather then @@ -721,7 +721,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ ilen = last_frag->ofs + last_frag->size; else ilen = JFFS2_F_I_SIZE(f); - + memset(&ri, 0, sizeof(ri)); ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); @@ -760,7 +760,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ return ret; } -static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_inode_info *f, struct jffs2_full_dirent *fd) { struct jffs2_full_dirent *new_fd; @@ -781,12 +781,12 @@ static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_er so refrain from splatting them. */ if (JFFS2_F_I_MTIME(f) == JFFS2_F_I_CTIME(f)) rd.mctime = cpu_to_je32(JFFS2_F_I_MTIME(f)); - else + else rd.mctime = cpu_to_je32(0); rd.type = fd->type; rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8)); rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize)); - + ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &phys_ofs, &alloclen, JFFS2_SUMMARY_DIRENT_SIZE(rd.nsize)); if (ret) { @@ -804,7 +804,7 @@ static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_er return 0; } -static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_inode_info *f, struct jffs2_full_dirent *fd) { struct jffs2_full_dirent **fdp = &f->dents; @@ -843,7 +843,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct if (ref_totlen(c, NULL, raw) != rawlen) continue; - /* Doesn't matter if there's one in the same erase block. We're going to + /* Doesn't matter if there's one in the same erase block. We're going to delete it too at the same time. */ if (SECTOR_ADDR(raw->flash_offset) == SECTOR_ADDR(fd->raw->flash_offset)) continue; @@ -895,7 +895,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct kfree(rd); } - /* FIXME: If we're deleting a dirent which contains the current mtime and ctime, + /* FIXME: If we're deleting a dirent which contains the current mtime and ctime, we should update the metadata node with those times accordingly */ /* No need for it any more. Just mark it obsolete and remove it from the list */ @@ -927,13 +927,13 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras D1(printk(KERN_DEBUG "Writing replacement hole node for ino #%u from offset 0x%x to 0x%x\n", f->inocache->ino, start, end)); - + memset(&ri, 0, sizeof(ri)); if(fn->frags > 1) { size_t readlen; uint32_t crc; - /* It's partially obsoleted by a later write. So we have to + /* It's partially obsoleted by a later write. So we have to write it out again with the _same_ version as before */ ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(ri), &readlen, (char *)&ri); if (readlen != sizeof(ri) || ret) { @@ -955,16 +955,16 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras crc = crc32(0, &ri, sizeof(ri)-8); if (crc != je32_to_cpu(ri.node_crc)) { printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had CRC 0x%08x which doesn't match calculated CRC 0x%08x\n", - ref_offset(fn->raw), + ref_offset(fn->raw), je32_to_cpu(ri.node_crc), crc); /* FIXME: We could possibly deal with this by writing new holes for each frag */ - printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n", + printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n", start, end, f->inocache->ino); goto fill; } if (ri.compr != JFFS2_COMPR_ZERO) { printk(KERN_WARNING "jffs2_garbage_collect_hole: Node 0x%08x wasn't a hole node!\n", ref_offset(fn->raw)); - printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n", + printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n", start, end, f->inocache->ino); goto fill; } @@ -982,7 +982,7 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras ri.csize = cpu_to_je32(0); ri.compr = JFFS2_COMPR_ZERO; } - + frag = frag_last(&f->fragtree); if (frag) /* Fetch the inode length from the fragtree rather then @@ -1024,10 +1024,10 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras return 0; } - /* + /* * We should only get here in the case where the node we are * replacing had more than one frag, so we kept the same version - * number as before. (Except in case of error -- see 'goto fill;' + * number as before. (Except in case of error -- see 'goto fill;' * above.) */ D1(if(unlikely(fn->frags <= 1)) { @@ -1039,7 +1039,7 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras /* This is a partially-overlapped hole node. Mark it REF_NORMAL not REF_PRISTINE */ mark_ref_normal(new_fn->raw); - for (frag = jffs2_lookup_node_frag(&f->fragtree, fn->ofs); + for (frag = jffs2_lookup_node_frag(&f->fragtree, fn->ofs); frag; frag = frag_next(frag)) { if (frag->ofs > fn->size + fn->ofs) break; @@ -1057,10 +1057,10 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras printk(KERN_WARNING "jffs2_garbage_collect_hole: New node has no frags!\n"); BUG(); } - + jffs2_mark_node_obsolete(c, fn->raw); jffs2_free_full_dnode(fn); - + return 0; } @@ -1070,12 +1070,12 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era { struct jffs2_full_dnode *new_fn; struct jffs2_raw_inode ri; - uint32_t alloclen, phys_ofs, offset, orig_end, orig_start; + uint32_t alloclen, phys_ofs, offset, orig_end, orig_start; int ret = 0; unsigned char *comprbuf = NULL, *writebuf; unsigned long pg; unsigned char *pg_ptr; - + memset(&ri, 0, sizeof(ri)); D1(printk(KERN_DEBUG "Writing replacement dnode for ino #%u from offset 0x%x to 0x%x\n", @@ -1087,8 +1087,8 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era if (c->nr_free_blocks + c->nr_erasing_blocks > c->resv_blocks_gcmerge) { /* Attempt to do some merging. But only expand to cover logically adjacent frags if the block containing them is already considered - to be dirty. Otherwise we end up with GC just going round in - circles dirtying the nodes it already wrote out, especially + to be dirty. Otherwise we end up with GC just going round in + circles dirtying the nodes it already wrote out, especially on NAND where we have small eraseblocks and hence a much higher chance of nodes having to be split to cross boundaries. */ @@ -1122,7 +1122,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era break; } else { - /* OK, it's a frag which extends to the beginning of the page. Does it live + /* OK, it's a frag which extends to the beginning of the page. Does it live in a block which is still considered clean? If so, don't obsolete it. If not, cover it anyway. */ @@ -1172,7 +1172,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era break; } else { - /* OK, it's a frag which extends to the beginning of the page. Does it live + /* OK, it's a frag which extends to the beginning of the page. Does it live in a block which is still considered clean? If so, don't obsolete it. If not, cover it anyway. */ @@ -1199,14 +1199,14 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era break; } } - D1(printk(KERN_DEBUG "Expanded dnode to write from (0x%x-0x%x) to (0x%x-0x%x)\n", + D1(printk(KERN_DEBUG "Expanded dnode to write from (0x%x-0x%x) to (0x%x-0x%x)\n", orig_start, orig_end, start, end)); D1(BUG_ON(end > frag_last(&f->fragtree)->ofs + frag_last(&f->fragtree)->size)); BUG_ON(end < orig_end); BUG_ON(start > orig_start); } - + /* First, use readpage() to read the appropriate page into the page cache */ /* Q: What happens if we actually try to GC the _same_ page for which commit_write() * triggered garbage collection in the first place? @@ -1263,7 +1263,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era ri.usercompr = (comprtype >> 8) & 0xff; ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); ri.data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen)); - + new_fn = jffs2_write_dnode(c, f, &ri, comprbuf, cdatalen, phys_ofs, ALLOC_GC); jffs2_free_comprbuf(comprbuf, writebuf); diff --git a/fs/jffs2/histo.h b/fs/jffs2/histo.h index 84f184f0836..22a93a08210 100644 --- a/fs/jffs2/histo.h +++ b/fs/jffs2/histo.h @@ -1,3 +1,3 @@ /* This file provides the bit-probabilities for the input file */ -#define BIT_DIVIDER 629 +#define BIT_DIVIDER 629 static int bits[9] = { 179,167,183,165,159,198,178,119,}; /* ia32 .so files */ diff --git a/fs/jffs2/histo_mips.h b/fs/jffs2/histo_mips.h index 9a443268d88..fa3dac19a10 100644 --- a/fs/jffs2/histo_mips.h +++ b/fs/jffs2/histo_mips.h @@ -1,2 +1,2 @@ -#define BIT_DIVIDER_MIPS 1043 +#define BIT_DIVIDER_MIPS 1043 static int bits_mips[8] = { 277,249,290,267,229,341,212,241}; /* mips32 */ diff --git a/fs/jffs2/ioctl.c b/fs/jffs2/ioctl.c index 238c7992064..69099835de1 100644 --- a/fs/jffs2/ioctl.c +++ b/fs/jffs2/ioctl.c @@ -7,17 +7,17 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: ioctl.c,v 1.9 2004/11/16 20:36:11 dwmw2 Exp $ + * $Id: ioctl.c,v 1.10 2005/11/07 11:14:40 gleixner Exp $ * */ #include -int jffs2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, +int jffs2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { /* Later, this will provide for lsattr.jffs2 and chattr.jffs2, which will include compression support etc. */ return -ENOTTY; } - + diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c index f27df015f3e..036cbd11c00 100644 --- a/fs/jffs2/malloc.c +++ b/fs/jffs2/malloc.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: malloc.c,v 1.30 2005/09/20 14:27:34 dedekind Exp $ + * $Id: malloc.c,v 1.31 2005/11/07 11:14:40 gleixner Exp $ * */ @@ -29,7 +29,7 @@ static kmem_cache_t *inode_cache_slab; int __init jffs2_create_slab_caches(void) { - full_dnode_slab = kmem_cache_create("jffs2_full_dnode", + full_dnode_slab = kmem_cache_create("jffs2_full_dnode", sizeof(struct jffs2_full_dnode), 0, 0, NULL, NULL); if (!full_dnode_slab) diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 80fe8feffb4..c79eebb8ab3 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.c,v 1.114 2005/09/21 13:28:35 dedekind Exp $ + * $Id: nodelist.c,v 1.115 2005/11/07 11:14:40 gleixner Exp $ * */ @@ -24,7 +24,7 @@ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list) { struct jffs2_full_dirent **prev = list; - + dbg_dentlist("add dirent \"%s\", ino #%u\n", new->name, new->ino); while ((*prev) && (*prev)->nhash <= new->nhash) { @@ -75,14 +75,14 @@ void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint if (size == 0) return; - /* + /* * If the last fragment starts at the RAM page boundary, it is * REF_PRISTINE irrespective of its size. */ frag = frag_last(list); if (frag->node && (frag->ofs & (PAGE_CACHE_SIZE - 1)) == 0) { dbg_fragtree2("marking the last fragment 0x%08x-0x%08x REF_PRISTINE.\n", - frag->ofs, frag->ofs + frag->size); + frag->ofs, frag->ofs + frag->size); frag->node->raw->flash_offset = ref_offset(frag->node->raw) | REF_PRISTINE; } } @@ -102,7 +102,7 @@ void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *t ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size, this->node->frags); mark_ref_normal(this->node->raw); } - + } jffs2_free_node_frag(this); } @@ -117,7 +117,7 @@ static void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_ while (*link) { parent = *link; base = rb_entry(parent, struct jffs2_node_frag, rb); - + if (newfrag->ofs > base->ofs) link = &base->rb.rb_right; else if (newfrag->ofs < base->ofs) @@ -137,7 +137,7 @@ static void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_ static inline struct jffs2_node_frag * new_fragment(struct jffs2_full_dnode *fn, uint32_t ofs, uint32_t size) { struct jffs2_node_frag *newfrag; - + newfrag = jffs2_alloc_node_frag(); if (likely(newfrag)) { newfrag->ofs = ofs; @@ -169,7 +169,7 @@ static int no_overlapping_node(struct jffs2_sb_info *c, struct rb_root *root, } if (this) { - /* By definition, the 'this' node has no right-hand child, + /* By definition, the 'this' node has no right-hand child, because there are no frags with offset greater than it. So that's where we want to put the hole */ dbg_fragtree2("add hole frag %#04x-%#04x on the right of the new frag.\n", @@ -183,13 +183,13 @@ static int no_overlapping_node(struct jffs2_sb_info *c, struct rb_root *root, rb_insert_color(&holefrag->rb, root); this = holefrag; } - + if (this) { - /* By definition, the 'this' node has no right-hand child, + /* By definition, the 'this' node has no right-hand child, because there are no frags with offset greater than it. So that's where we want to put new fragment */ dbg_fragtree2("add the new node at the right\n"); - rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); + rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); } else { dbg_fragtree2("insert the new node at the root of the tree\n"); rb_link_node(&newfrag->rb, NULL, &root->rb_node); @@ -216,7 +216,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r dbg_fragtree2("lookup gave no frag\n"); lastend = 0; } - + /* See if we ran off the end of the fragtree */ if (lastend <= newfrag->ofs) { /* We did */ @@ -243,7 +243,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r this->ofs, this->ofs + this->size); /* OK. 'this' is pointing at the first frag that newfrag->ofs at least partially obsoletes, - * - i.e. newfrag->ofs < this->ofs+this->size && newfrag->ofs >= this->ofs + * - i.e. newfrag->ofs < this->ofs+this->size && newfrag->ofs >= this->ofs */ if (newfrag->ofs > this->ofs) { /* This node isn't completely obsoleted. The start of it remains valid */ @@ -261,10 +261,10 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r if (this->node) dbg_fragtree2("split old frag 0x%04x-0x%04x, phys 0x%08x\n", this->ofs, this->ofs+this->size, ref_offset(this->node->raw)); - else + else dbg_fragtree2("split old hole frag 0x%04x-0x%04x\n", this->ofs, this->ofs+this->size); - + /* New second frag pointing to this's node */ newfrag2 = new_fragment(this->node, newfrag->ofs + newfrag->size, this->ofs + this->size - newfrag->ofs - newfrag->size); @@ -284,10 +284,10 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r from newfrag to insert newfrag2. */ jffs2_fragtree_insert(newfrag, this); rb_insert_color(&newfrag->rb, root); - + jffs2_fragtree_insert(newfrag2, newfrag); rb_insert_color(&newfrag2->rb, root); - + return 0; } /* New node just reduces 'this' frag in size, doesn't split it */ @@ -297,13 +297,13 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r jffs2_fragtree_insert(newfrag, this); rb_insert_color(&newfrag->rb, root); } else { - /* New frag starts at the same point as 'this' used to. Replace + /* New frag starts at the same point as 'this' used to. Replace it in the tree without doing a delete and insertion */ dbg_fragtree2("inserting newfrag (*%p),%d-%d in before 'this' (*%p),%d-%d\n", newfrag, newfrag->ofs, newfrag->ofs+newfrag->size, this, this->ofs, this->ofs+this->size); - + rb_replace_node(&this->rb, &newfrag->rb, root); - + if (newfrag->ofs + newfrag->size >= this->ofs+this->size) { dbg_fragtree2("obsoleting node frag %p (%x-%x)\n", this, this->ofs, this->ofs+this->size); jffs2_obsolete_node_frag(c, this); @@ -317,7 +317,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r } } /* OK, now we have newfrag added in the correct place in the tree, but - frag_next(newfrag) may be a fragment which is overlapped by it + frag_next(newfrag) may be a fragment which is overlapped by it */ while ((this = frag_next(newfrag)) && newfrag->ofs + newfrag->size >= this->ofs + this->size) { /* 'this' frag is obsoleted completely. */ @@ -326,7 +326,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r rb_erase(&this->rb, root); jffs2_obsolete_node_frag(c, this); } - /* Now we're pointing at the first frag which isn't totally obsoleted by + /* Now we're pointing at the first frag which isn't totally obsoleted by the new frag */ if (!this || newfrag->ofs + newfrag->size == this->ofs) @@ -344,7 +344,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r return 0; } -/* +/* * Given an inode, probably with existing tree of fragments, add the new node * to the fragment tree. */ @@ -363,7 +363,7 @@ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_in dbg_fragtree("adding node %#04x-%#04x @0x%08x on flash, newfrag *%p\n", fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag); - + ret = jffs2_add_frag_to_fragtree(c, &f->fragtree, newfrag); if (unlikely(ret)) return ret; @@ -374,14 +374,14 @@ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_in struct jffs2_node_frag *prev = frag_prev(newfrag); mark_ref_normal(fn->raw); - /* If we don't start at zero there's _always_ a previous */ + /* If we don't start at zero there's _always_ a previous */ if (prev->node) mark_ref_normal(prev->node->raw); } if ((newfrag->ofs+newfrag->size) & (PAGE_CACHE_SIZE-1)) { struct jffs2_node_frag *next = frag_next(newfrag); - + if (next) { mark_ref_normal(fn->raw); if (next->node) @@ -412,7 +412,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info if (!jffs2_is_writebuffered(c)) goto adj_acc; - + /* Calculate how many bytes were already checked */ ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode); len = ofs % c->wbuf_pagesize; @@ -424,13 +424,13 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info ref_offset(ref), tn->csize, ofs); goto adj_acc; } - + ofs += len; len = tn->csize - len; - + dbg_readinode("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.\n", ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len); - + #ifndef __ECOS /* TODO: instead, incapsulate point() stuff to jffs2_flash_read(), * adding and jffs2_flash_read_end() interface. */ @@ -445,12 +445,12 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info pointed = 1; /* succefully pointed to device */ } #endif - + if (!pointed) { buffer = kmalloc(len, GFP_KERNEL); if (unlikely(!buffer)) return -ENOMEM; - + /* TODO: this is very frequent pattern, make it a separate * routine */ err = jffs2_flash_read(c, ofs, len, &retlen, buffer); @@ -458,7 +458,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info JFFS2_ERROR("can not read %d bytes from 0x%08x, error code: %d.\n", len, ofs, err); goto free_out; } - + if (retlen != len) { JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", ofs, retlen, len); err = -EIO; @@ -485,7 +485,7 @@ adj_acc: jeb = &c->blocks[ref->flash_offset / c->sector_size]; len = ref_totlen(c, jeb, ref); - /* + /* * Mark the node as having been checked and fix the * accounting accordingly. */ @@ -516,13 +516,13 @@ free_out: static inline int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn) { int ret; - + BUG_ON(ref_obsolete(tn->fn->raw)); /* We only check the data CRC of unchecked nodes */ if (ref_flags(tn->fn->raw) != REF_UNCHECKED) return 0; - + dbg_fragtree2("check node %#04x-%#04x, phys offs %#08x.\n", tn->fn->ofs, tn->fn->ofs + tn->fn->size, ref_offset(tn->fn->raw)); @@ -538,7 +538,7 @@ static inline int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f return ret; } -/* +/* * Helper function for jffs2_add_older_frag_to_fragtree(). * * Called when the new fragment that is being inserted @@ -551,31 +551,31 @@ static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, newfrag->ofs, newfrag->ofs + newfrag->size, hole->ofs, hole->ofs + hole->size); if (hole->ofs == newfrag->ofs) { - /* + /* * Well, the new fragment actually starts at the same offset as * the hole. */ if (hole->ofs + hole->size > newfrag->ofs + newfrag->size) { - /* + /* * We replace the overlapped left part of the hole by * the new node. */ - + dbg_fragtree2("insert fragment %#04x-%#04x and cut the left part of the hole\n", newfrag->ofs, newfrag->ofs + newfrag->size); rb_replace_node(&hole->rb, &newfrag->rb, root); - + hole->ofs += newfrag->size; hole->size -= newfrag->size; - - /* + + /* * We know that 'hole' should be the right hand * fragment. */ jffs2_fragtree_insert(hole, newfrag); rb_insert_color(&hole->rb, root); } else { - /* + /* * Ah, the new fragment is of the same size as the hole. * Relace the hole by it. */ @@ -586,7 +586,7 @@ static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, } } else { /* The new fragment lefts some hole space at the left */ - + struct jffs2_node_frag * newfrag2 = NULL; if (hole->ofs + hole->size > newfrag->ofs + newfrag->size) { @@ -606,7 +606,7 @@ static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, jffs2_fragtree_insert(newfrag, hole); rb_insert_color(&newfrag->rb, root); - + if (newfrag2) { dbg_fragtree2("left the hole %#04x-%#04x at the right\n", newfrag2->ofs, newfrag2->ofs + newfrag2->size); @@ -654,18 +654,18 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode lastend = this->ofs + this->size; else lastend = 0; - + /* Detect the preliminary type of node */ if (fn->size >= PAGE_CACHE_SIZE) ref_flag = REF_PRISTINE; else ref_flag = REF_NORMAL; - + /* See if we ran off the end of the root */ if (lastend <= fn_ofs) { /* We did */ - - /* + + /* * We are going to insert the new node into the * fragment tree, so check it. */ @@ -691,21 +691,21 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode fn->frags = 0; while (1) { - /* + /* * Here we have: * fn_ofs < this->ofs + this->size && fn_ofs >= this->ofs. - * + * * Remember, 'this' has higher version, any non-hole node * which is already in the fragtree is newer then the newly * inserted. */ if (!this->node) { - /* + /* * 'this' is the hole fragment, so at least the * beginning of the new fragment is valid. */ - - /* + + /* * We are going to insert the new node into the * fragment tree, so check it. */ @@ -715,7 +715,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode return err; checked = 1; } - + if (this->ofs + this->size >= fn_ofs + fn_size) { /* We split the hole on two parts */ @@ -730,7 +730,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode goto out_ok; } - /* + /* * The beginning of the new fragment is valid since it * overlaps the hole node. */ @@ -742,9 +742,9 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode this->ofs + this->size - fn_ofs); if (unlikely(!newfrag)) return -ENOMEM; - + if (fn_ofs == this->ofs) { - /* + /* * The new node starts at the same offset as * the hole and supersieds the hole. */ @@ -754,21 +754,21 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode rb_replace_node(&this->rb, &newfrag->rb, root); jffs2_free_node_frag(this); } else { - /* + /* * The hole becomes shorter as its right part * is supersieded by the new fragment. */ dbg_fragtree2("reduce size of hole %#04x-%#04x to %#04x-%#04x\n", this->ofs, this->ofs + this->size, this->ofs, this->ofs + this->size - newfrag->size); - + dbg_fragtree2("add new fragment %#04x-%#04x, refcnt %d\n", fn_ofs, fn_ofs + this->ofs + this->size - fn_ofs, fn->frags); - + this->size -= newfrag->size; jffs2_fragtree_insert(newfrag, this); rb_insert_color(&newfrag->rb, root); } - + fn_ofs += newfrag->size; fn_size -= newfrag->size; this = rb_entry(rb_next(&newfrag->rb), @@ -778,7 +778,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode this->ofs, this->ofs + this->size, this->node ? "(data)" : "(hole)"); } - /* + /* * 'This' node is not the hole so it obsoletes the new fragment * either fully or partially. */ @@ -791,19 +791,19 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode goto out_ok; } else { struct jffs2_node_frag *new_this; - + /* 'This' node obsoletes the beginning of the new node */ dbg_fragtree2("the beginning %#04x-%#04x is obsolete\n", fn_ofs, this->ofs + this->size); ref_flag = REF_NORMAL; - + fn_size -= this->ofs + this->size - fn_ofs; fn_ofs = this->ofs + this->size; dbg_fragtree2("now considering %#04x-%#04x\n", fn_ofs, fn_ofs + fn_size); - + new_this = rb_entry(rb_next(&this->rb), struct jffs2_node_frag, rb); if (!new_this) { - /* + /* * There is no next fragment. Add the rest of * the new node as the right-hand child. */ @@ -813,7 +813,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode return err; checked = 1; } - + fn->frags += 1; newfrag = new_fragment(fn, fn_ofs, fn_size); if (unlikely(!newfrag)) @@ -821,7 +821,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode dbg_fragtree2("there are no more fragments, insert %#04x-%#04x\n", newfrag->ofs, newfrag->ofs + newfrag->size); - rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); + rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); rb_insert_color(&newfrag->rb, root); goto out_ok; } else { @@ -862,9 +862,9 @@ void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache /* During mount, this needs no locking. During normal operation, its callers want to do other stuff while still holding the inocache_lock. - Rather than introducing special case get_ino_cache functions or + Rather than introducing special case get_ino_cache functions or callbacks, we just let the caller do the locking itself. */ - + struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t ino) { struct jffs2_inode_cache *ret; @@ -873,7 +873,7 @@ struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t while (ret && ret->ino < ino) { ret = ret->next; } - + if (ret && ret->ino != ino) ret = NULL; @@ -907,9 +907,9 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old) dbg_inocache("del %p (ino #%u)\n", old, old->ino); spin_lock(&c->inocache_lock); - + prev = &c->inocache_list[old->ino % INOCACHE_HASHSIZE]; - + while ((*prev) && (*prev)->ino < old->ino) { prev = &(*prev)->next; } @@ -919,7 +919,7 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old) /* Free it now unless it's in READING or CLEARING state, which are the transitions upon read_inode() and clear_inode(). The - rest of the time we know nobody else is looking at it, and + rest of the time we know nobody else is looking at it, and if it's held by read_inode() or clear_inode() they'll free it for themselves. */ if (old->state != INO_STATE_READING && old->state != INO_STATE_CLEARING) @@ -932,7 +932,7 @@ void jffs2_free_ino_caches(struct jffs2_sb_info *c) { int i; struct jffs2_inode_cache *this, *next; - + for (i=0; iinocache_list[i]; while (this) { @@ -959,10 +959,10 @@ void jffs2_free_raw_node_refs(struct jffs2_sb_info *c) c->blocks[i].first_node = c->blocks[i].last_node = NULL; } } - + struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset) { - /* The common case in lookup is that there will be a node + /* The common case in lookup is that there will be a node which precisely matches. So we go looking for that first */ struct rb_node *next; struct jffs2_node_frag *prev = NULL; @@ -993,9 +993,9 @@ struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_ if (prev) dbg_fragtree2("no match. Returning frag %#04x-%#04x, closest previous\n", prev->ofs, prev->ofs+prev->size); - else + else dbg_fragtree2("returning NULL, empty fragtree\n"); - + return prev; } @@ -1010,7 +1010,7 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) return; dbg_fragtree("killing\n"); - + frag = (rb_entry(root->rb_node, struct jffs2_node_frag, rb)); while(frag) { if (frag->rb.rb_left) { @@ -1023,18 +1023,18 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) } if (frag->node && !(--frag->node->frags)) { - /* Not a hole, and it's the final remaining frag + /* Not a hole, and it's the final remaining frag of this node. Free the node */ if (c) jffs2_mark_node_obsolete(c, frag->node->raw); - + jffs2_free_full_dnode(frag->node); } parent = frag_parent(frag); if (parent) { if (frag_left(parent) == frag) parent->rb.rb_left = NULL; - else + else parent->rb.rb_right = NULL; } diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 1222372cb29..23a67bb3052 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -58,7 +58,7 @@ #define je16_to_cpu(x) (le16_to_cpu(x.v16)) #define je32_to_cpu(x) (le32_to_cpu(x.v32)) #define jemode_to_cpu(x) (le32_to_cpu(jffs2_to_os_mode((x).m))) -#else +#else #error wibble #endif @@ -68,7 +68,7 @@ /* This is all we need to keep in-core for each raw node during normal operation. As and when we do read_inode on a particular inode, we can - scan the nodes which are listed for it and build up a proper map of + scan the nodes which are listed for it and build up a proper map of which nodes are currently valid. JFFSv1 always used to keep that whole map in core for each inode. */ @@ -85,7 +85,7 @@ struct jffs2_raw_node_ref /* flash_offset & 3 always has to be zero, because nodes are always aligned at 4 bytes. So we have a couple of extra bits - to play with, which indicate the node's status; see below: */ + to play with, which indicate the node's status; see below: */ #define REF_UNCHECKED 0 /* We haven't yet checked the CRC or built its inode */ #define REF_OBSOLETE 1 /* Obsolete, can be completely ignored */ #define REF_PRISTINE 2 /* Completely clean. GC without looking */ @@ -98,7 +98,7 @@ struct jffs2_raw_node_ref /* For each inode in the filesystem, we need to keep a record of nlink, because it would be a PITA to scan the whole directory tree at read_inode() time to calculate it, and to keep sufficient information - in the raw_node_ref (basically both parent and child inode number for + in the raw_node_ref (basically both parent and child inode number for dirent nodes) would take more space than this does. We also keep a pointer to the first physical node which is part of this inode, too. */ @@ -128,7 +128,7 @@ struct jffs2_inode_cache { #define INOCACHE_HASHSIZE 128 /* - Larger representation of a raw node, kept in-core only when the + Larger representation of a raw node, kept in-core only when the struct inode for this particular ino is instantiated. */ @@ -138,11 +138,11 @@ struct jffs2_full_dnode uint32_t ofs; /* The offset to which the data of this node belongs */ uint32_t size; uint32_t frags; /* Number of fragments which currently refer - to this node. When this reaches zero, + to this node. When this reaches zero, the node is obsolete. */ }; -/* +/* Even larger representation of a raw node, kept in-core only while we're actually building up the original map of which nodes go where, in read_inode() @@ -155,7 +155,7 @@ struct jffs2_tmp_dnode_info uint32_t data_crc; uint32_t partial_crc; uint32_t csize; -}; +}; struct jffs2_full_dirent { @@ -169,7 +169,7 @@ struct jffs2_full_dirent }; /* - Fragments - used to build a map of which raw node to obtain + Fragments - used to build a map of which raw node to obtain data from for each part of the ino */ struct jffs2_node_frag @@ -209,7 +209,7 @@ static inline uint32_t __ref_totlen(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref) { uint32_t ref_end; - + if (ref->next_phys) ref_end = ref_offset(ref->next_phys); else { @@ -264,7 +264,7 @@ static inline uint32_t ref_totlen(struct jffs2_sb_info *c, #define VERYDIRTY(c, size) ((size) >= ((c)->sector_size / 2)) /* check if dirty space is more than 255 Byte */ -#define ISDIRTY(size) ((size) > sizeof (struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN) +#define ISDIRTY(size) ((size) > sizeof (struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN) #define PAD(x) (((x)+3)&~3) @@ -341,7 +341,7 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode); struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode); int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - struct jffs2_raw_inode *ri, unsigned char *buf, + struct jffs2_raw_inode *ri, unsigned char *buf, uint32_t offset, uint32_t writelen, uint32_t *retlen); int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen); int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, int namelen, struct jffs2_inode_info *dead_f, uint32_t time); @@ -349,7 +349,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint /* readinode.c */ -int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, +int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t ino, struct jffs2_raw_inode *latest_node); int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f); diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 2c938d1bffb..49127a1f045 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -88,12 +88,12 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs up(&c->alloc_sem); return -ENOSPC; } - + /* Calc possibly available space. Possibly available means that we * don't know, if unchecked size contains obsoleted nodes, which could give us some * more usable space. This will affect the sum only once, as gc first finishes checking * of nodes. - + Return -ENOSPC, if the maximum possibly available space is less or equal than + + Return -ENOSPC, if the maximum possibly available space is less or equal than * blocksneeded * sector_size. * This blocks endless gc looping on a filesystem, which is nearly full, even if * the check above passes. @@ -118,7 +118,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs c->nr_free_blocks, c->nr_erasing_blocks, c->free_size, c->dirty_size, c->wasted_size, c->used_size, c->erasing_size, c->bad_size, c->free_size + c->dirty_size + c->wasted_size + c->used_size + c->erasing_size + c->bad_size, c->flash_size)); spin_unlock(&c->erase_completion_lock); - + ret = jffs2_garbage_collect_pass(c); if (ret) return ret; @@ -183,7 +183,7 @@ static void jffs2_close_nextblock(struct jffs2_sb_info *c, struct jffs2_eraseblo jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); list_add_tail(&jeb->list, &c->dirty_list); } - } else { + } else { D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); list_add_tail(&jeb->list, &c->clean_list); @@ -197,7 +197,7 @@ static void jffs2_close_nextblock(struct jffs2_sb_info *c, struct jffs2_eraseblo static int jffs2_find_nextblock(struct jffs2_sb_info *c) { struct list_head *next; - + /* Take the next block off the 'free' list */ if (list_empty(&c->free_list)) { @@ -229,8 +229,8 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c) if (!c->nr_erasing_blocks) { /* Ouch. We're in GC, or we wouldn't have got here. And there's no space left. At all. */ - printk(KERN_CRIT "Argh. No free space left for GC. nr_erasing_blocks is %d. nr_free_blocks is %d. (erasableempty: %s, erasingempty: %s, erasependingempty: %s)\n", - c->nr_erasing_blocks, c->nr_free_blocks, list_empty(&c->erasable_list)?"yes":"no", + printk(KERN_CRIT "Argh. No free space left for GC. nr_erasing_blocks is %d. nr_free_blocks is %d. (erasableempty: %s, erasingempty: %s, erasependingempty: %s)\n", + c->nr_erasing_blocks, c->nr_free_blocks, list_empty(&c->erasable_list)?"yes":"no", list_empty(&c->erasing_list)?"yes":"no", list_empty(&c->erase_pending_list)?"yes":"no"); return -ENOSPC; } @@ -250,7 +250,7 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c) list_del(next); c->nextblock = list_entry(next, struct jffs2_eraseblock, list); c->nr_free_blocks--; - + jffs2_sum_reset_collected(c->summary); /* reset collected summary */ D1(printk(KERN_DEBUG "jffs2_find_nextblock(): new nextblock = 0x%08x\n", c->nextblock->offset)); @@ -354,9 +354,9 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin if (c->cleanmarker_size && jeb->used_size == c->cleanmarker_size && !jeb->first_node->next_in_ino) { - /* Only node in it beforehand was a CLEANMARKER node (we think). + /* Only node in it beforehand was a CLEANMARKER node (we think). So mark it obsolete now that there's going to be another node - in the block. This will reduce used_size to zero but We've + in the block. This will reduce used_size to zero but We've already set c->nextblock so that jffs2_mark_node_obsolete() won't try to refile it to the dirty_list. */ @@ -376,12 +376,12 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin * @len: length of this physical node * @dirty: dirty flag for new node * - * Should only be used to report nodes for which space has been allocated + * Should only be used to report nodes for which space has been allocated * by jffs2_reserve_space. * * Must be called with the alloc_sem held. */ - + int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new) { struct jffs2_eraseblock *jeb; @@ -488,8 +488,8 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref if (jffs2_can_mark_obsolete(c) && !jffs2_is_readonly(c) && !(c->flags & (JFFS2_SB_FLAG_SCANNING | JFFS2_SB_FLAG_BUILDING))) { - /* Hm. This may confuse static lock analysis. If any of the above - three conditions is false, we're going to return from this + /* Hm. This may confuse static lock analysis. If any of the above + three conditions is false, we're going to return from this function without actually obliterating any nodes or freeing any jffs2_raw_node_refs. So we don't need to stop erases from happening, or protect against people holding an obsolete @@ -546,17 +546,17 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref D1(printk(KERN_DEBUG "Wasting\n")); addedsize = 0; jeb->wasted_size += ref_totlen(c, jeb, ref); - c->wasted_size += ref_totlen(c, jeb, ref); + c->wasted_size += ref_totlen(c, jeb, ref); } ref->flash_offset = ref_offset(ref) | REF_OBSOLETE; - + jffs2_dbg_acct_sanity_check_nolock(c, jeb); jffs2_dbg_acct_paranoia_check_nolock(c, jeb); if (c->flags & JFFS2_SB_FLAG_SCANNING) { /* Flash scanning is in progress. Don't muck about with the block lists because they're not ready yet, and don't actually - obliterate nodes that look obsolete. If they weren't + obliterate nodes that look obsolete. If they weren't marked obsolete on the flash at the time they _became_ obsolete, there was probably a reason for that. */ spin_unlock(&c->erase_completion_lock); @@ -590,7 +590,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref immediately reused, and we spread the load a bit. */ D1(printk(KERN_DEBUG "...and adding to erasable_list\n")); list_add_tail(&jeb->list, &c->erasable_list); - } + } } D1(printk(KERN_DEBUG "Done OK\n")); } else if (jeb == c->gcblock) { @@ -608,8 +608,8 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref list_add_tail(&jeb->list, &c->very_dirty_list); } else { D1(printk(KERN_DEBUG "Eraseblock at 0x%08x not moved anywhere. (free 0x%08x, dirty 0x%08x, used 0x%08x)\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - } + jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); + } spin_unlock(&c->erase_completion_lock); @@ -656,11 +656,11 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref /* Nodes which have been marked obsolete no longer need to be associated with any inode. Remove them from the per-inode list. - - Note we can't do this for NAND at the moment because we need + + Note we can't do this for NAND at the moment because we need obsolete dirent nodes to stay on the lists, because of the horridness in jffs2_garbage_collect_deletion_dirent(). Also - because we delete the inocache, and on NAND we need that to + because we delete the inocache, and on NAND we need that to stay around until all the nodes are actually erased, in order to stop us from giving the same inode number to another newly created inode. */ @@ -689,7 +689,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref if (ref->next_phys && ref_obsolete(ref->next_phys) && !ref->next_phys->next_in_ino) { struct jffs2_raw_node_ref *n = ref->next_phys; - + spin_lock(&c->erase_completion_lock); ref->__totlen += n->__totlen; @@ -703,7 +703,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref jffs2_free_raw_node_ref(n); } - + /* Also merge with the previous node in the list, if there is one and that one is obsolete */ if (ref != jeb->first_node ) { @@ -713,7 +713,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref while (p->next_phys != ref) p = p->next_phys; - + if (ref_obsolete(p) && !ref->next_in_ino) { p->__totlen += ref->__totlen; if (jeb->last_node == ref) { @@ -753,11 +753,11 @@ int jffs2_thread_should_wake(struct jffs2_sb_info *c) */ dirty = c->dirty_size + c->erasing_size - c->nr_erasing_blocks * c->sector_size; - if (c->nr_free_blocks + c->nr_erasing_blocks < c->resv_blocks_gctrigger && - (dirty > c->nospc_dirty_size)) + if (c->nr_free_blocks + c->nr_erasing_blocks < c->resv_blocks_gctrigger && + (dirty > c->nospc_dirty_size)) ret = 1; - D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x: %s\n", + D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x: %s\n", c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size, ret?"yes":"no")); return ret; diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index 04d4167ab25..59e7a393200 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -191,18 +191,18 @@ void jffs2_gc_release_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, int inum, int nlink); -unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, - struct jffs2_inode_info *f, +unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, + struct jffs2_inode_info *f, unsigned long offset, unsigned long *priv); void jffs2_gc_release_page(struct jffs2_sb_info *c, unsigned char *pg, unsigned long *priv); void jffs2_flash_cleanup(struct jffs2_sb_info *c); - + /* writev.c */ -int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs, +int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, const u_char *buf); diff --git a/fs/jffs2/read.c b/fs/jffs2/read.c index e38e6c5f143..f3b86da833b 100644 --- a/fs/jffs2/read.c +++ b/fs/jffs2/read.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: read.c,v 1.41 2005/07/22 10:32:08 dedekind Exp $ + * $Id: read.c,v 1.42 2005/11/07 11:14:41 gleixner Exp $ * */ @@ -43,7 +43,7 @@ int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, } if (readlen != sizeof(*ri)) { jffs2_free_raw_inode(ri); - printk(KERN_WARNING "Short read from 0x%08x: wanted 0x%zx bytes, got 0x%zx\n", + printk(KERN_WARNING "Short read from 0x%08x: wanted 0x%zx bytes, got 0x%zx\n", ref_offset(fd->raw), sizeof(*ri), readlen); return -EIO; } @@ -61,7 +61,7 @@ int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, } /* There was a bug where we wrote hole nodes out with csize/dsize swapped. Deal with it */ - if (ri->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(ri->dsize) && + if (ri->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(ri->dsize) && je32_to_cpu(ri->csize)) { ri->dsize = ri->csize; ri->csize = cpu_to_je32(0); @@ -74,7 +74,7 @@ int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, goto out_ri; }); - + if (ri->compr == JFFS2_COMPR_ZERO) { memset(buf, 0, len); goto out_ri; @@ -82,8 +82,8 @@ int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, /* Cases: Reading whole node and it's uncompressed - read directly to buffer provided, check CRC. - Reading whole node and it's compressed - read into comprbuf, check CRC and decompress to buffer provided - Reading partial node and it's uncompressed - read into readbuf, check CRC, and copy + Reading whole node and it's compressed - read into comprbuf, check CRC and decompress to buffer provided + Reading partial node and it's uncompressed - read into readbuf, check CRC, and copy Reading partial node and it's compressed - read into readbuf, check checksum, decompress to decomprbuf and copy */ if (ri->compr == JFFS2_COMPR_NONE && len == je32_to_cpu(ri->dsize)) { @@ -129,7 +129,7 @@ int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, D2(printk(KERN_DEBUG "Data CRC matches calculated CRC %08x\n", crc)); if (ri->compr != JFFS2_COMPR_NONE) { D2(printk(KERN_DEBUG "Decompress %d bytes from %p to %d bytes at %p\n", - je32_to_cpu(ri->csize), readbuf, je32_to_cpu(ri->dsize), decomprbuf)); + je32_to_cpu(ri->csize), readbuf, je32_to_cpu(ri->dsize), decomprbuf)); ret = jffs2_decompress(c, f, ri->compr | (ri->usercompr << 8), readbuf, decomprbuf, je32_to_cpu(ri->csize), je32_to_cpu(ri->dsize)); if (ret) { printk(KERN_WARNING "Error: jffs2_decompress returned %d\n", ret); @@ -191,7 +191,7 @@ int jffs2_read_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, } else { uint32_t readlen; uint32_t fragofs; /* offset within the frag to start reading */ - + fragofs = offset - frag->ofs; readlen = min(frag->size - fragofs, end - offset); D1(printk(KERN_DEBUG "Reading %d-%d from node at 0x%08x (%d)\n", diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 08f8c5ec611..5f0652df5d4 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.142 2005/09/20 14:27:34 dedekind Exp $ + * $Id: readinode.c,v 1.143 2005/11/07 11:14:41 gleixner Exp $ * */ @@ -116,19 +116,19 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r uint32_t *latest_mctime, uint32_t *mctime_ver) { struct jffs2_full_dirent *fd; - + /* The direntry nodes are checked during the flash scanning */ BUG_ON(ref_flags(ref) == REF_UNCHECKED); /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ BUG_ON(ref_obsolete(ref)); - + /* Sanity check */ if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) { JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n", ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen)); return 1; } - + fd = jffs2_alloc_full_dirent(rd->nsize + 1); if (unlikely(!fd)) return -ENOMEM; @@ -144,39 +144,39 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r *latest_mctime = je32_to_cpu(rd->mctime); } - /* + /* * Copy as much of the name as possible from the raw * dirent we've already read from the flash. */ if (read > sizeof(*rd)) memcpy(&fd->name[0], &rd->name[0], min_t(uint32_t, rd->nsize, (read - sizeof(*rd)) )); - + /* Do we need to copy any more of the name directly from the flash? */ if (rd->nsize + sizeof(*rd) > read) { /* FIXME: point() */ int err; int already = read - sizeof(*rd); - - err = jffs2_flash_read(c, (ref_offset(ref)) + read, + + err = jffs2_flash_read(c, (ref_offset(ref)) + read, rd->nsize - already, &read, &fd->name[already]); if (unlikely(read != rd->nsize - already) && likely(!err)) return -EIO; - + if (unlikely(err)) { JFFS2_ERROR("read remainder of name: error %d\n", err); jffs2_free_full_dirent(fd); return -EIO; } } - + fd->nhash = full_name_hash(fd->name, rd->nsize); fd->next = NULL; fd->name[rd->nsize] = '\0'; - + /* * Wheee. We now have a complete jffs2_full_dirent structure, with - * the name in it and everything. Link it into the list + * the name in it and everything. Link it into the list */ jffs2_add_fd_to_list(c, fd, fdp); @@ -198,7 +198,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref struct jffs2_tmp_dnode_info *tn; uint32_t len, csize; int ret = 1; - + /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ BUG_ON(ref_obsolete(ref)); @@ -210,7 +210,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref tn->partial_crc = 0; csize = je32_to_cpu(rd->csize); - + /* If we've never checked the CRCs on this node, check them now */ if (ref_flags(ref) == REF_UNCHECKED) { uint32_t crc; @@ -221,7 +221,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref ref_offset(ref), je32_to_cpu(rd->node_crc), crc); goto free_out; } - + /* Sanity checks */ if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) || unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) { @@ -313,13 +313,13 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref ret = -ENOMEM; goto free_out; } - + tn->version = je32_to_cpu(rd->version); tn->fn->ofs = je32_to_cpu(rd->offset); tn->data_crc = je32_to_cpu(rd->data_crc); tn->csize = csize; tn->fn->raw = ref; - + /* There was a bug where we wrote hole nodes out with csize/dsize swapped. Deal with it */ if (rd->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(rd->dsize) && csize) @@ -329,7 +329,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref dbg_readinode("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n", ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize); - + jffs2_add_tn_to_tree(tn, tnp); return 0; @@ -351,7 +351,7 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re { /* We don't mark unknown nodes as REF_UNCHECKED */ BUG_ON(ref_flags(ref) == REF_UNCHECKED); - + un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype)); if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) { @@ -423,7 +423,7 @@ static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, bufstart = buf + *rdlen; len = right_size - *rdlen; } - + dbg_readinode("read more %d bytes\n", len); err = jffs2_flash_read(c, offs, len, &retlen, bufstart); @@ -432,7 +432,7 @@ static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, "error code: %d.\n", len, offs, err); return err; } - + if (retlen < len) { JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", offs, retlen, len); @@ -460,7 +460,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf int len, err; *mctime_ver = 0; - + dbg_readinode("ino #%u\n", f->inocache->ino); if (jffs2_is_writebuffered(c)) { @@ -487,7 +487,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf buf = kmalloc(len, GFP_KERNEL); if (!buf) return -ENOMEM; - + spin_lock(&c->erase_completion_lock); valid_ref = jffs2_first_valid_node(f->inocache->nodes); if (!valid_ref && f->inocache->ino != 1) @@ -514,7 +514,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf * size = JFFS2_MIN_NODE_HEADER. */ if (jffs2_is_writebuffered(c)) { - /* + /* * We treat 'buf' as 2 adjacent wbufs. We want to * adjust bufstart such as it points to the * beginning of the node within this wbuf. @@ -540,17 +540,17 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf JFFS2_ERROR("can not read %d bytes from 0x%08x, " "error code: %d.\n", len, ref_offset(ref), err); goto free_out; } - + if (retlen < len) { JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", ref_offset(ref), retlen, len); err = -EIO; goto free_out; } - + node = (union jffs2_node_union *)bufstart; - + switch (je16_to_cpu(node->u.nodetype)) { - + case JFFS2_NODETYPE_DIRENT: if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent)) { @@ -558,21 +558,21 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf if (unlikely(err)) goto free_out; } - + err = read_direntry(c, ref, &node->d, retlen, &ret_fd, latest_mctime, mctime_ver); if (err == 1) { jffs2_mark_node_obsolete(c, ref); break; } else if (unlikely(err)) goto free_out; - + if (je32_to_cpu(node->d.version) > *highest_version) *highest_version = je32_to_cpu(node->d.version); break; case JFFS2_NODETYPE_INODE: - + if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode)) { err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf, bufstart); if (unlikely(err)) @@ -588,7 +588,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf if (je32_to_cpu(node->i.version) > *highest_version) *highest_version = je32_to_cpu(node->i.version); - + break; default: @@ -597,7 +597,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf if (unlikely(err)) goto free_out; } - + err = read_unknown(c, ref, &node->u); if (err == 1) { jffs2_mark_node_obsolete(c, ref); @@ -625,7 +625,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf return err; } -static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, +static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *latest_node) { @@ -677,7 +677,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, ret = 0; /* Prevent freeing the metadata update node */ } else jffs2_mark_node_obsolete(c, fn->raw); - + BUG_ON(rb->rb_left); if (rb->rb_parent && rb->rb_parent->rb_left == rb) { /* We were then left-hand child of our parent. We need @@ -763,7 +763,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, } break; - + case S_IFREG: /* If it was a regular file, truncate it to the latest node's isize */ jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize)); @@ -788,10 +788,10 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, jffs2_do_clear_inode(c, f); return -ENOMEM; } - + ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node), je32_to_cpu(latest_node->csize), &retlen, (char *)f->target); - + if (ret || retlen != je32_to_cpu(latest_node->csize)) { if (retlen != je32_to_cpu(latest_node->csize)) ret = -EIO; @@ -805,7 +805,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, f->target[je32_to_cpu(latest_node->csize)] = '\0'; dbg_readinode("symlink's target '%s' cached\n", f->target); } - + /* fall through... */ case S_IFBLK: @@ -848,7 +848,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, } /* Scan the list of all nodes present for this ino, build map of versions, etc. */ -int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, +int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t ino, struct jffs2_raw_inode *latest_node) { dbg_readinode("read inode #%u\n", ino); @@ -864,7 +864,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, case INO_STATE_CHECKEDABSENT: f->inocache->state = INO_STATE_READING; break; - + case INO_STATE_CHECKING: case INO_STATE_GC: /* If it's in either of these states, we need @@ -957,7 +957,7 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) kfree(f->target); f->target = NULL; } - + fds = f->dents; while(fds) { fd = fds; diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 805a166469d..0e7456ec99f 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -38,11 +38,11 @@ static uint32_t pseudo_random; static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s); -/* These helper functions _must_ increase ofs and also do the dirty/used space accounting. +/* These helper functions _must_ increase ofs and also do the dirty/used space accounting. * Returning an error will abort the mount - bad checksums etc. should just mark the space * as dirty. */ -static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s); static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s); @@ -131,8 +131,8 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) /* Now decide which list to put it on */ switch(ret) { case BLK_STATE_ALLFF: - /* - * Empty block. Since we can't be sure it + /* + * Empty block. Since we can't be sure it * was entirely erased, we just queue it for erase * again. It will be marked as such when the erase * is complete. Meanwhile we still count it as empty @@ -234,7 +234,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) } #ifdef CONFIG_JFFS2_FS_WRITEBUFFER if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size % c->wbuf_pagesize)) { - /* If we're going to start writing into a block which already + /* If we're going to start writing into a block which already contains data, and the end of the data isn't page-aligned, skip a little and align it. */ @@ -250,7 +250,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) } #endif if (c->nr_erasing_blocks) { - if ( !c->used_size && ((c->nr_free_blocks+empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) { + if ( !c->used_size && ((c->nr_free_blocks+empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) { printk(KERN_NOTICE "Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n"); printk(KERN_NOTICE "empty_blocks %d, bad_blocks %d, c->nr_blocks %d\n",empty_blocks,bad_blocks,c->nr_blocks); ret = -EIO; @@ -263,7 +263,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) if (buf_size) kfree(flashbuf); #ifndef __ECOS - else + else c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size); #endif return ret; @@ -391,7 +391,7 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo if (err) return err; } - + /* We temporarily use 'ofs' as a pointer into the buffer/jeb */ ofs = 0; @@ -431,7 +431,7 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo dbg_summary("no summary found in jeb 0x%08x. Apply original scan.\n",jeb->offset); -scan_more: +scan_more: while(ofs < jeb->offset + c->sector_size) { jffs2_dbg_acct_paranoia_check_nolock(c, jeb); @@ -496,7 +496,7 @@ scan_more: /* If we're only checking the beginning of a block with a cleanmarker, bail now */ - if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) && + if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) && c->cleanmarker_size && !jeb->dirty_size && !jeb->first_node->next_phys) { D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE(c->sector_size))); return BLK_STATE_CLEANMARKER; @@ -505,7 +505,7 @@ scan_more: /* See how much more there is to read in this eraseblock... */ buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); if (!buf_len) { - /* No more to read. Break out of main loop without marking + /* No more to read. Break out of main loop without marking this range of empty space as dirty (because it's not) */ D1(printk(KERN_DEBUG "Empty flash at %08x runs to end of block. Treating as free_space\n", empty_start)); @@ -540,8 +540,8 @@ scan_more: } if (je16_to_cpu(node->magic) != JFFS2_MAGIC_BITMASK) { /* OK. We're out of possibilities. Whinge and move on */ - noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n", - JFFS2_MAGIC_BITMASK, ofs, + noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n", + JFFS2_MAGIC_BITMASK, ofs, je16_to_cpu(node->magic)); DIRTY_SPACE(4); ofs += 4; @@ -556,7 +556,7 @@ scan_more: if (hdr_crc != je32_to_cpu(node->hdr_crc)) { noisy_printk(&noise, "jffs2_scan_eraseblock(): Node at 0x%08x {0x%04x, 0x%04x, 0x%08x) has invalid CRC 0x%08x (calculated 0x%08x)\n", ofs, je16_to_cpu(node->magic), - je16_to_cpu(node->nodetype), + je16_to_cpu(node->nodetype), je32_to_cpu(node->totlen), je32_to_cpu(node->hdr_crc), hdr_crc); @@ -565,7 +565,7 @@ scan_more: continue; } - if (ofs + je32_to_cpu(node->totlen) > + if (ofs + je32_to_cpu(node->totlen) > jeb->offset + c->sector_size) { /* Eep. Node goes over the end of the erase block. */ printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n", @@ -600,7 +600,7 @@ scan_more: if (err) return err; ofs += PAD(je32_to_cpu(node->totlen)); break; - + case JFFS2_NODETYPE_DIRENT: if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) { buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); @@ -620,7 +620,7 @@ scan_more: case JFFS2_NODETYPE_CLEANMARKER: D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x\n", ofs)); if (je32_to_cpu(node->totlen) != c->cleanmarker_size) { - printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n", + printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n", ofs, je32_to_cpu(node->totlen), c->cleanmarker_size); DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node))); ofs += PAD(sizeof(struct jffs2_unknown_node)); @@ -639,7 +639,7 @@ scan_more: marker_ref->flash_offset = ofs | REF_NORMAL; marker_ref->__totlen = c->cleanmarker_size; jeb->first_node = jeb->last_node = marker_ref; - + USED_SPACE(PAD(c->cleanmarker_size)); ofs += PAD(c->cleanmarker_size); } @@ -690,7 +690,7 @@ scan_more: } } - D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x\n", jeb->offset, + D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x\n", jeb->offset, jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size)); /* mark_node_obsolete can add to wasted !! */ @@ -730,7 +730,7 @@ struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uin return ic; } -static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s) { struct jffs2_raw_node_ref *raw; @@ -740,11 +740,11 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs)); /* We do very little here now. Just check the ino# to which we should attribute - this node; we can do all the CRC checking etc. later. There's a tradeoff here -- + this node; we can do all the CRC checking etc. later. There's a tradeoff here -- we used to scan the flash once only, reading everything we want from it into memory, then building all our in-core data structures and freeing the extra information. Now we allow the first part of the mount to complete a lot quicker, - but we have to go _back_ to the flash in order to finish the CRC checking, etc. + but we have to go _back_ to the flash in order to finish the CRC checking, etc. Which means that the _full_ amount of time to get to proper write mode with GC operational may actually be _longer_ than before. Sucks to be me. */ @@ -790,7 +790,7 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc jeb->last_node->next_phys = raw; jeb->last_node = raw; - D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", + D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", je32_to_cpu(ri->ino), je32_to_cpu(ri->version), je32_to_cpu(ri->offset), je32_to_cpu(ri->offset)+je32_to_cpu(ri->dsize))); @@ -806,7 +806,7 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc return 0; } -static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s) { struct jffs2_raw_node_ref *raw; @@ -840,7 +840,7 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo crc = crc32(0, fd->name, rd->nsize); if (crc != je32_to_cpu(rd->name_crc)) { printk(KERN_NOTICE "jffs2_scan_dirent_node(): Name CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", - ofs, je32_to_cpu(rd->name_crc), crc); + ofs, je32_to_cpu(rd->name_crc), crc); D1(printk(KERN_NOTICE "Name for which CRC failed is (now) '%s', ino #%d\n", fd->name, je32_to_cpu(rd->ino))); jffs2_free_full_dirent(fd); /* FIXME: Why do we believe totlen? */ @@ -860,7 +860,7 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo jffs2_free_raw_node_ref(raw); return -ENOMEM; } - + raw->__totlen = PAD(je32_to_cpu(rd->totlen)); raw->flash_offset = ofs | REF_PRISTINE; raw->next_phys = NULL; diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index 308251266c6..fb9cec61fcf 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c @@ -82,7 +82,7 @@ static int jffs2_sum_add_mem(struct jffs2_summary *s, union jffs2_sum_mem *item) je32_to_cpu(item->d.ino)); break; default: - JFFS2_WARNING("UNKNOWN node type %u\n", + JFFS2_WARNING("UNKNOWN node type %u\n", je16_to_cpu(item->u.nodetype)); return 1; } @@ -174,7 +174,7 @@ void jffs2_sum_disable_collecting(struct jffs2_summary *s) s->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; } -int jffs2_sum_is_disabled(struct jffs2_summary *s) +int jffs2_sum_is_disabled(struct jffs2_summary *s) { return (s->sum_size == JFFS2_SUMMARY_NOSUM_SIZE); } @@ -609,7 +609,7 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock sdrnt_ptr->nsize = c->summary->sum_list_head->d.nsize; sdrnt_ptr->type = c->summary->sum_list_head->d.type; - memcpy(sdrnt_ptr->name, c->summary->sum_list_head->d.name, + memcpy(sdrnt_ptr->name, c->summary->sum_list_head->d.name, c->summary->sum_list_head->d.nsize); wpage += JFFS2_SUMMARY_DIRENT_SIZE(c->summary->sum_list_head->d.nsize); @@ -687,7 +687,7 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) datasize = c->summary->sum_size + sizeof(struct jffs2_sum_marker); infosize = sizeof(struct jffs2_raw_summary) + datasize; padsize = jeb->free_size - infosize; - infosize += padsize; + infosize += padsize; datasize += padsize; /* Is there enough space for summary? */ diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 99028af3f69..9e0b5458d9c 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: super.c,v 1.109 2005/09/07 08:34:55 havasi Exp $ + * $Id: super.c,v 1.110 2005/11/07 11:14:42 gleixner Exp $ * */ @@ -62,7 +62,7 @@ static int jffs2_sync_fs(struct super_block *sb, int wait) down(&c->alloc_sem); jffs2_flush_wbuf_pad(c); - up(&c->alloc_sem); + up(&c->alloc_sem); return 0; } @@ -112,7 +112,7 @@ static int jffs2_sb_set(struct super_block *sb, void *data) } static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type, - int flags, const char *dev_name, + int flags, const char *dev_name, void *data, struct mtd_info *mtd) { struct super_block *sb; @@ -172,7 +172,7 @@ static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type, } static struct super_block *jffs2_get_sb_mtdnr(struct file_system_type *fs_type, - int flags, const char *dev_name, + int flags, const char *dev_name, void *data, int mtdnr) { struct mtd_info *mtd; @@ -201,7 +201,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, /* The preferred way of mounting in future; especially when CONFIG_BLK_DEV is implemented - we specify the underlying - MTD device by number or by name, so that we don't require + MTD device by number or by name, so that we don't require block device support to be present in the kernel. */ /* FIXME: How to do the root fs this way? */ @@ -225,7 +225,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, } else if (isdigit(dev_name[3])) { /* Mount by MTD device number name */ char *endptr; - + mtdnr = simple_strtoul(dev_name+3, &endptr, 0); if (!*endptr) { /* It was a valid number */ @@ -235,7 +235,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, } } - /* Try the old way - the hack where we allowed users to mount + /* Try the old way - the hack where we allowed users to mount /dev/mtdblock$(n) but didn't actually _use_ the blkdev */ err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd); @@ -376,5 +376,5 @@ module_exit(exit_jffs2_fs); MODULE_DESCRIPTION("The Journalling Flash File System, v2"); MODULE_AUTHOR("Red Hat, Inc."); -MODULE_LICENSE("GPL"); // Actually dual-licensed, but it doesn't matter for +MODULE_LICENSE("GPL"); // Actually dual-licensed, but it doesn't matter for // the sake of this tag. It's Free Software. diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c index 6fd5ee4f90b..d55754fe892 100644 --- a/fs/jffs2/symlink.c +++ b/fs/jffs2/symlink.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: symlink.c,v 1.18 2005/11/06 11:03:27 gleixner Exp $ + * $Id: symlink.c,v 1.19 2005/11/07 11:14:42 gleixner Exp $ * */ @@ -21,7 +21,7 @@ static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd); struct inode_operations jffs2_symlink_inode_operations = -{ +{ .readlink = generic_readlink, .follow_link = jffs2_follow_link, .setattr = jffs2_setattr @@ -44,7 +44,7 @@ static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) * stopped using our f->target string which we provide by means of * nd_set_link() call. */ - + if (!p) { printk(KERN_ERR "jffs2_follow_link(): can't find symlink taerget\n"); p = ERR_PTR(-EIO); @@ -52,7 +52,7 @@ static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->target)); nd_set_link(nd, p); - + /* * We will unlock the f->sem mutex but VFS will use the f->target string. This is safe * since the only way that may cause f->target to be changed is iput() operation. diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 44d8a894a41..242cd53a970 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -188,7 +188,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) /* Find the first node to be recovered, by skipping over every node which ends before the wbuf starts, or which is obsolete. */ first_raw = &jeb->first_node; - while (*first_raw && + while (*first_raw && (ref_obsolete(*first_raw) || (ref_offset(*first_raw)+ref_totlen(c, jeb, *first_raw)) < c->wbuf_ofs)) { D1(printk(KERN_DEBUG "Skipping node at 0x%08x(%d)-0x%08x which is either before 0x%08x or obsolete\n", @@ -237,7 +237,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) ret = c->mtd->read_ecc(c->mtd, start, c->wbuf_ofs - start, &retlen, buf, NULL, c->oobinfo); else ret = c->mtd->read(c->mtd, start, c->wbuf_ofs - start, &retlen, buf); - + if (ret == -EBADMSG && retlen == c->wbuf_ofs - start) { /* ECC recovered */ ret = 0; @@ -274,15 +274,15 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) if (end-start >= c->wbuf_pagesize) { /* Need to do another write immediately, but it's possible that this is just because the wbuf itself is completely - full, and there's nothing earlier read back from the - flash. Hence 'buf' isn't necessarily what we're writing + full, and there's nothing earlier read back from the + flash. Hence 'buf' isn't necessarily what we're writing from. */ unsigned char *rewrite_buf = buf?:c->wbuf; uint32_t towrite = (end-start) - ((end-start)%c->wbuf_pagesize); D1(printk(KERN_DEBUG "Write 0x%x bytes at 0x%08x in wbuf recover\n", towrite, ofs)); - + #ifdef BREAKMEHEADER static int breakme; if (breakme++ == 20) { @@ -434,7 +434,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) this happens, if we have a change to a new block, or if fsync forces us to flush the writebuffer. if we have a switch to next page, we will not have - enough remaining space for this. + enough remaining space for this. */ if (pad ) { c->wbuf_len = PAD(c->wbuf_len); @@ -442,7 +442,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) /* Pad with JFFS2_DIRTY_BITMASK initially. this helps out ECC'd NOR with 8 byte page size */ memset(c->wbuf + c->wbuf_len, 0, c->wbuf_pagesize - c->wbuf_len); - + if ( c->wbuf_len + sizeof(struct jffs2_unknown_node) < c->wbuf_pagesize) { struct jffs2_unknown_node *padnode = (void *)(c->wbuf + c->wbuf_len); padnode->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); @@ -453,7 +453,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) } /* else jffs2_flash_writev has actually filled in the rest of the buffer for us, and will deal with the node refs etc. later. */ - + #ifdef BREAKME static int breakme; if (breakme++ == 20) { @@ -462,9 +462,9 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, brokenbuf, NULL, c->oobinfo); ret = -EIO; - } else + } else #endif - + if (jffs2_cleanmarker_oob(c)) ret = c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf, NULL, c->oobinfo); else @@ -485,7 +485,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) } spin_lock(&c->erase_completion_lock); - + /* Adjust free size of the block if we padded. */ if (pad) { struct jffs2_eraseblock *jeb; @@ -495,7 +495,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) D1(printk(KERN_DEBUG "jffs2_flush_wbuf() adjusting free_size of %sblock at %08x\n", (jeb==c->nextblock)?"next":"", jeb->offset)); - /* wbuf_pagesize - wbuf_len is the amount of space that's to be + /* wbuf_pagesize - wbuf_len is the amount of space that's to be padded. If there is less free space in the block than that, something screwed up */ if (jeb->free_size < (c->wbuf_pagesize - c->wbuf_len)) { @@ -523,9 +523,9 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) return 0; } -/* Trigger garbage collection to flush the write-buffer. +/* Trigger garbage collection to flush the write-buffer. If ino arg is zero, do it if _any_ real (i.e. not GC) writes are - outstanding. If ino arg non-zero, do it only if a write for the + outstanding. If ino arg non-zero, do it only if a write for the given inode is outstanding. */ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino) { @@ -620,13 +620,13 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig /* If not NAND flash, don't bother */ if (!jffs2_is_writebuffered(c)) return jffs2_flash_direct_writev(c, invecs, count, to, retlen); - + down_write(&c->wbuf_sem); /* If wbuf_ofs is not initialized, set it to target address */ if (c->wbuf_ofs == 0xFFFFFFFF) { c->wbuf_ofs = PAGE_DIV(to); - c->wbuf_len = PAGE_MOD(to); + c->wbuf_len = PAGE_MOD(to); memset(c->wbuf,0xff,c->wbuf_pagesize); } @@ -640,10 +640,10 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig memset(c->wbuf,0xff,c->wbuf_pagesize); } } - - /* Sanity checks on target address. - It's permitted to write at PAD(c->wbuf_len+c->wbuf_ofs), - and it's permitted to write at the beginning of a new + + /* Sanity checks on target address. + It's permitted to write at PAD(c->wbuf_len+c->wbuf_ofs), + and it's permitted to write at the beginning of a new erase block. Anything else, and you die. New block starts at xxx000c (0-b = block header) */ @@ -661,8 +661,8 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig } /* set pointer to new block */ c->wbuf_ofs = PAGE_DIV(to); - c->wbuf_len = PAGE_MOD(to); - } + c->wbuf_len = PAGE_MOD(to); + } if (to != PAD(c->wbuf_ofs + c->wbuf_len)) { /* We're not writing immediately after the writebuffer. Bad. */ @@ -682,21 +682,21 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig invec = 0; outvec = 0; - /* Fill writebuffer first, if already in use */ + /* Fill writebuffer first, if already in use */ if (c->wbuf_len) { uint32_t invec_ofs = 0; - /* adjust alignment offset */ + /* adjust alignment offset */ if (c->wbuf_len != PAGE_MOD(to)) { c->wbuf_len = PAGE_MOD(to); /* take care of alignment to next page */ if (!c->wbuf_len) c->wbuf_len = c->wbuf_pagesize; } - + while(c->wbuf_len < c->wbuf_pagesize) { uint32_t thislen; - + if (invec == count) goto alldone; @@ -704,17 +704,17 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig if (thislen >= invecs[invec].iov_len) thislen = invecs[invec].iov_len; - + invec_ofs = thislen; memcpy(c->wbuf + c->wbuf_len, invecs[invec].iov_base, thislen); c->wbuf_len += thislen; donelen += thislen; /* Get next invec, if actual did not fill the buffer */ - if (c->wbuf_len < c->wbuf_pagesize) + if (c->wbuf_len < c->wbuf_pagesize) invec++; - } - + } + /* write buffer is full, flush buffer */ ret = __jffs2_flush_wbuf(c, NOPAD); if (ret) { @@ -773,10 +773,10 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig /* We did cross a page boundary, so we write some now */ if (jffs2_cleanmarker_oob(c)) - ret = c->mtd->writev_ecc(c->mtd, outvecs, splitvec+1, outvec_to, &wbuf_retlen, NULL, c->oobinfo); + ret = c->mtd->writev_ecc(c->mtd, outvecs, splitvec+1, outvec_to, &wbuf_retlen, NULL, c->oobinfo); else ret = jffs2_flash_direct_writev(c, outvecs, splitvec+1, outvec_to, &wbuf_retlen); - + if (ret < 0 || wbuf_retlen != PAGE_DIV(totlen)) { /* At this point we have no problem, c->wbuf is empty. However refile nextblock to avoid @@ -793,7 +793,7 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig spin_unlock(&c->erase_completion_lock); goto exit; } - + donelen += wbuf_retlen; c->wbuf_ofs = PAGE_DIV(outvec_to) + PAGE_DIV(totlen); @@ -837,7 +837,7 @@ alldone: jffs2_wbuf_dirties_inode(c, ino); ret = 0; - + exit: up_write(&c->wbuf_sem); return ret; @@ -880,18 +880,18 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re if ( (ret == -EBADMSG) && (*retlen == len) ) { printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n", len, ofs); - /* - * We have the raw data without ECC correction in the buffer, maybe + /* + * We have the raw data without ECC correction in the buffer, maybe * we are lucky and all data or parts are correct. We check the node. * If data are corrupted node check will sort it out. * We keep this block, it will fail on write or erase and the we * mark it bad. Or should we do that now? But we should give him a chance. - * Maybe we had a system crash or power loss before the ecc write or + * Maybe we had a system crash or power loss before the ecc write or * a erase was completed. * So we return success. :) */ ret = 0; - } + } /* if no writebuffer available or write buffer empty, return */ if (!c->wbuf_pagesize || !c->wbuf_len) @@ -906,16 +906,16 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re if (owbf > c->wbuf_len) /* is read beyond write buffer ? */ goto exit; lwbf = c->wbuf_len - owbf; /* number of bytes to copy */ - if (lwbf > len) + if (lwbf > len) lwbf = len; - } else { + } else { orbf = (c->wbuf_ofs - ofs); /* offset in read buffer */ if (orbf > len) /* is write beyond write buffer ? */ goto exit; lwbf = len - orbf; /* number of bytes to copy */ - if (lwbf > c->wbuf_len) + if (lwbf > c->wbuf_len) lwbf = c->wbuf_len; - } + } if (lwbf > 0) memcpy(buf+orbf,c->wbuf+owbf,lwbf); @@ -943,7 +943,7 @@ int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb printk(KERN_NOTICE "jffs2_check_oob_empty(): allocation of temporary data buffer for oob check failed\n"); return -ENOMEM; } - /* + /* * if mode = 0, we scan for a total empty oob area, else we have * to take care of the cleanmarker in the first page of the block */ @@ -952,41 +952,41 @@ int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB failed %d for block at %08x\n", ret, jeb->offset)); goto out; } - + if (retlen < len) { D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB return short read " "(%zd bytes not %d) for block at %08x\n", retlen, len, jeb->offset)); ret = -EIO; goto out; } - + /* Special check for first page */ for(i = 0; i < oob_size ; i++) { /* Yeah, we know about the cleanmarker. */ - if (mode && i >= c->fsdata_pos && + if (mode && i >= c->fsdata_pos && i < c->fsdata_pos + c->fsdata_len) continue; if (buf[i] != 0xFF) { D2(printk(KERN_DEBUG "Found %02x at %x in OOB for %08x\n", buf[i], i, jeb->offset)); - ret = 1; + ret = 1; goto out; } } - /* we know, we are aligned :) */ + /* we know, we are aligned :) */ for (page = oob_size; page < len; page += sizeof(long)) { unsigned long dat = *(unsigned long *)(&buf[page]); if(dat != -1) { - ret = 1; + ret = 1; goto out; } } out: - kfree(buf); - + kfree(buf); + return ret; } @@ -1068,7 +1068,7 @@ int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_erasebloc n.totlen = cpu_to_je32(8); ret = jffs2_flash_write_oob(c, jeb->offset + c->fsdata_pos, c->fsdata_len, &retlen, (unsigned char *)&n); - + if (ret) { D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Write failed for block at %08x: error %d\n", jeb->offset, ret)); return ret; @@ -1080,7 +1080,7 @@ int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_erasebloc return 0; } -/* +/* * On NAND we try to mark this block bad. If the block was erased more * than MAX_ERASE_FAILURES we mark it finaly bad. * Don't care about failures. This block remains on the erase-pending @@ -1101,7 +1101,7 @@ int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock * D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Marking bad block at %08x\n", bad_offset)); ret = c->mtd->block_markbad(c->mtd, bad_offset); - + if (ret) { D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Write failed for block at %08x: error %d\n", jeb->offset, ret)); return ret; @@ -1125,7 +1125,7 @@ static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c) /* Do this only, if we have an oob buffer */ if (!c->mtd->oobsize) return 0; - + /* Cleanmarker is out-of-band, so inline size zero */ c->cleanmarker_size = 0; @@ -1151,7 +1151,7 @@ static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c) c->fsdata_len = NAND_JFFS2_OOB16_FSDALEN; c->badblock_pos = 15; break; - + default: D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n")); return -EINVAL; @@ -1168,7 +1168,7 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c) init_rwsem(&c->wbuf_sem); c->wbuf_pagesize = c->mtd->oobblock; c->wbuf_ofs = 0xFFFFFFFF; - + c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); if (!c->wbuf) return -ENOMEM; @@ -1194,13 +1194,13 @@ void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c) int jffs2_dataflash_setup(struct jffs2_sb_info *c) { c->cleanmarker_size = 0; /* No cleanmarkers needed */ - + /* Initialize write buffer */ init_rwsem(&c->wbuf_sem); - - + + c->wbuf_pagesize = c->mtd->erasesize; - + /* Find a suitable c->sector_size * - Not too much sectors * - Sectors have to be at least 4 K + some bytes @@ -1210,11 +1210,11 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) { */ c->sector_size = 8 * c->mtd->erasesize; - + while (c->sector_size < 8192) { c->sector_size *= 2; } - + /* It may be necessary to adjust the flash size */ c->flash_size = c->mtd->size; @@ -1222,7 +1222,7 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) { c->flash_size = (c->flash_size / c->sector_size) * c->sector_size; printk(KERN_WARNING "JFFS2 flash size adjusted to %dKiB\n", c->flash_size); }; - + c->wbuf_ofs = 0xFFFFFFFF; c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); if (!c->wbuf) diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index ea411518d80..1342f0158e9 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: write.c,v 1.96 2005/09/07 08:34:55 havasi Exp $ + * $Id: write.c,v 1.97 2005/11/07 11:14:42 gleixner Exp $ * */ @@ -54,7 +54,7 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint return 0; } -/* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it, +/* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it, write it to the flash, link it into the existing inode/fragment list */ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode) @@ -86,7 +86,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 raw = jffs2_alloc_raw_node_ref(); if (!raw) return ERR_PTR(-ENOMEM); - + fn = jffs2_alloc_full_dnode(); if (!fn) { jffs2_free_raw_node_ref(raw); @@ -110,7 +110,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(ri->version) < f->highest_version)) { BUG_ON(!retried); D1(printk(KERN_DEBUG "jffs2_write_dnode : dnode_version %d, " - "highest version %d -> updating dnode\n", + "highest version %d -> updating dnode\n", je32_to_cpu(ri->version), f->highest_version)); ri->version = cpu_to_je32(++f->highest_version); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); @@ -120,7 +120,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 (alloc_mode==ALLOC_GC)?0:f->inocache->ino); if (ret || (retlen != sizeof(*ri) + datalen)) { - printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", + printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", sizeof(*ri)+datalen, flash_ofs, ret, retlen); /* Mark the space as dirtied */ @@ -128,10 +128,10 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 /* Doesn't belong to any inode */ raw->next_in_ino = NULL; - /* Don't change raw->size to match retlen. We may have + /* Don't change raw->size to match retlen. We may have written the node header already, and only the data will seem corrupted, in which case the scan would skip over - any node we write before the original intended end of + any node we write before the original intended end of this node */ raw->flash_offset |= REF_OBSOLETE; jffs2_add_physical_node_ref(c, raw); @@ -148,7 +148,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 retried = 1; D1(printk(KERN_DEBUG "Retrying failed write.\n")); - + jffs2_dbg_acct_sanity_check(c,jeb); jffs2_dbg_acct_paranoia_check(c, jeb); @@ -159,7 +159,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 /* Locking pain */ up(&f->sem); jffs2_complete_reservation(c); - + ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &flash_ofs, &dummy, alloc_mode, JFFS2_SUMMARY_INODE_SIZE); down(&f->sem); @@ -181,9 +181,9 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 return ERR_PTR(ret?ret:-EIO); } /* Mark the space used */ - /* If node covers at least a whole page, or if it starts at the - beginning of a page and runs to the end of the file, or if - it's a hole node, mark it REF_PRISTINE, else REF_NORMAL. + /* If node covers at least a whole page, or if it starts at the + beginning of a page and runs to the end of the file, or if + it's a hole node, mark it REF_PRISTINE, else REF_NORMAL. */ if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) || ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) && @@ -201,7 +201,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 spin_unlock(&c->erase_completion_lock); D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", - flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize), + flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize), je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc), je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen))); @@ -221,7 +221,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff int retried = 0; int ret; - D1(printk(KERN_DEBUG "jffs2_write_dirent(ino #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x)\n", + D1(printk(KERN_DEBUG "jffs2_write_dirent(ino #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x)\n", je32_to_cpu(rd->pino), name, name, je32_to_cpu(rd->ino), je32_to_cpu(rd->name_crc))); @@ -235,7 +235,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff vecs[0].iov_len = sizeof(*rd); vecs[1].iov_base = (unsigned char *)name; vecs[1].iov_len = namelen; - + jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); raw = jffs2_alloc_raw_node_ref(); @@ -276,7 +276,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff ret = jffs2_flash_writev(c, vecs, 2, flash_ofs, &retlen, (alloc_mode==ALLOC_GC)?0:je32_to_cpu(rd->pino)); if (ret || (retlen != sizeof(*rd) + namelen)) { - printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", + printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", sizeof(*rd)+namelen, flash_ofs, ret, retlen); /* Mark the space as dirtied */ if (retlen) { @@ -307,7 +307,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff /* Locking pain */ up(&f->sem); jffs2_complete_reservation(c); - + ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &flash_ofs, &dummy, alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); down(&f->sem); @@ -346,7 +346,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff we don't have to go digging in struct inode or its equivalent. It should set: mode, uid, gid, (starting)isize, atime, ctime, mtime */ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - struct jffs2_raw_inode *ri, unsigned char *buf, + struct jffs2_raw_inode *ri, unsigned char *buf, uint32_t offset, uint32_t writelen, uint32_t *retlen) { int ret = 0; @@ -354,7 +354,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, D1(printk(KERN_DEBUG "jffs2_write_inode_range(): Ino #%u, ofs 0x%x, len 0x%x\n", f->inocache->ino, offset, writelen)); - + while(writelen) { struct jffs2_full_dnode *fn; unsigned char *comprbuf = NULL; @@ -451,8 +451,8 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str uint32_t alloclen, phys_ofs; int ret; - /* Try to reserve enough space for both node and dirent. - * Just the node will do for now, though + /* Try to reserve enough space for both node and dirent. + * Just the node will do for now, though */ ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); @@ -477,7 +477,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str jffs2_complete_reservation(c); return PTR_ERR(fn); } - /* No data here. Only a metadata node, which will be + /* No data here. Only a metadata node, which will be obsoleted by the first data write */ f->metadata = fn; @@ -486,7 +486,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str jffs2_complete_reservation(c); ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); - + if (ret) { /* Eep. */ D1(printk(KERN_DEBUG "jffs2_reserve_space() for dirent failed\n")); @@ -519,9 +519,9 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL); jffs2_free_raw_dirent(rd); - + if (IS_ERR(fd)) { - /* dirent failed to write. Delete the inode normally + /* dirent failed to write. Delete the inode normally as if it were the final unlink() */ jffs2_complete_reservation(c); up(&dir_f->sem); @@ -548,7 +548,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t alloclen, phys_ofs; int ret; - if (1 /* alternative branch needs testing */ || + if (1 /* alternative branch needs testing */ || !jffs2_can_mark_obsolete(c)) { /* We can't mark stuff obsolete on the medium. We need to write a deletion dirent */ @@ -570,7 +570,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); - + rd->pino = cpu_to_je32(dir_f->inocache->ino); rd->version = cpu_to_je32(++dir_f->highest_version); rd->ino = cpu_to_je32(0); @@ -581,7 +581,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_DELETION); - + jffs2_free_raw_dirent(rd); if (IS_ERR(fd)) { @@ -600,7 +600,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, down(&dir_f->sem); while ((*prev) && (*prev)->nhash <= nhash) { - if ((*prev)->nhash == nhash && + if ((*prev)->nhash == nhash && !memcmp((*prev)->name, name, namelen) && !(*prev)->name[namelen]) { struct jffs2_full_dirent *this = *prev; @@ -621,7 +621,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, /* dead_f is NULL if this was a rename not a real unlink */ /* Also catch the !f->inocache case, where there was a dirent pointing to an inode which didn't exist. */ - if (dead_f && dead_f->inocache) { + if (dead_f && dead_f->inocache) { down(&dead_f->sem); @@ -629,9 +629,9 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, while (dead_f->dents) { /* There can be only deleted ones */ fd = dead_f->dents; - + dead_f->dents = fd->next; - + if (fd->ino) { printk(KERN_WARNING "Deleting inode #%u with active dentry \"%s\"->ino #%u\n", dead_f->inocache->ino, fd->name, fd->ino); @@ -672,7 +672,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint jffs2_free_raw_dirent(rd); return ret; } - + down(&dir_f->sem); /* Build a deletion node */ @@ -693,7 +693,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL); - + jffs2_free_raw_dirent(rd); if (IS_ERR(fd)) { diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h index 2788880368c..cf792bb3c72 100644 --- a/include/linux/jffs2.h +++ b/include/linux/jffs2.h @@ -5,7 +5,7 @@ * * Created by David Woodhouse * - * For licensing information, see the file 'LICENCE' in the + * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * * $Id: jffs2.h,v 1.38 2005/09/26 11:37:23 havasi Exp $ @@ -70,10 +70,10 @@ //#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4) -#define JFFS2_INO_FLAG_PREREAD 1 /* Do read_inode() for this one at - mount time, don't wait for it to +#define JFFS2_INO_FLAG_PREREAD 1 /* Do read_inode() for this one at + mount time, don't wait for it to happen later */ -#define JFFS2_INO_FLAG_USERCOMPR 2 /* User has requested a specific +#define JFFS2_INO_FLAG_USERCOMPR 2 /* User has requested a specific compression type */ @@ -120,7 +120,7 @@ struct jffs2_raw_dirent } __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 +/* The uid, gid, atime, mtime and ctime members could be longer, but are left like this for space efficiency. If and when people decide they really need them extended, it's simple enough to add support for a new type of raw node. @@ -165,7 +165,7 @@ struct jffs2_raw_summary jint32_t sum[0]; /* inode summary info */ } __attribute__((packed)); -union jffs2_node_union +union jffs2_node_union { struct jffs2_raw_inode i; struct jffs2_raw_dirent d; diff --git a/include/linux/jffs2_fs_i.h b/include/linux/jffs2_fs_i.h index a5db884ec60..ef85ab56302 100644 --- a/include/linux/jffs2_fs_i.h +++ b/include/linux/jffs2_fs_i.h @@ -1,4 +1,4 @@ -/* $Id: jffs2_fs_i.h,v 1.18 2005/07/17 11:13:48 dedekind Exp $ */ +/* $Id: jffs2_fs_i.h,v 1.19 2005/11/07 11:14:52 gleixner Exp $ */ #ifndef _JFFS2_FS_I #define _JFFS2_FS_I @@ -25,7 +25,7 @@ struct jffs2_inode_info { /* There may be one datanode which isn't referenced by any of the above fragments, if it contains a metadata update but no actual data - or if this is a directory inode */ - /* This also holds the _only_ dnode for symlinks/device nodes, + /* This also holds the _only_ dnode for symlinks/device nodes, etc. */ struct jffs2_full_dnode *metadata; diff --git a/include/linux/jffs2_fs_sb.h b/include/linux/jffs2_fs_sb.h index fdc445b49e1..4bcfb557022 100644 --- a/include/linux/jffs2_fs_sb.h +++ b/include/linux/jffs2_fs_sb.h @@ -20,7 +20,7 @@ struct jffs2_inodirty; /* A struct for the overall file system control. Pointers to - jffs2_sb_info structs are named `c' in the source code. + jffs2_sb_info structs are named `c' in the source code. Nee jffs_control */ struct jffs2_sb_info { @@ -35,7 +35,7 @@ struct jffs2_sb_info { struct completion gc_thread_start; /* GC thread start completion */ struct completion gc_thread_exit; /* GC thread exit completion port */ - struct semaphore alloc_sem; /* Used to protect all the following + struct semaphore alloc_sem; /* Used to protect all the following fields, and also to protect against out-of-order writing of nodes. And GC. */ uint32_t cleanmarker_size; /* Size of an _inline_ CLEANMARKER @@ -64,7 +64,7 @@ struct jffs2_sb_info { uint32_t nospc_dirty_size; uint32_t nr_blocks; - struct jffs2_eraseblock *blocks; /* The whole array of blocks. Used for getting blocks + struct jffs2_eraseblock *blocks; /* The whole array of blocks. Used for getting blocks * from the offset (blocks[ofs / sector_size]) */ struct jffs2_eraseblock *nextblock; /* The block we're currently filling */ @@ -82,21 +82,21 @@ struct jffs2_sb_info { struct list_head bad_list; /* Bad blocks. */ struct list_head bad_used_list; /* Bad blocks with valid data in. */ - spinlock_t erase_completion_lock; /* Protect free_list and erasing_list + spinlock_t erase_completion_lock; /* Protect free_list and erasing_list against erase completion handler */ wait_queue_head_t erase_wait; /* For waiting for erases to complete */ wait_queue_head_t inocache_wq; struct jffs2_inode_cache **inocache_list; spinlock_t inocache_lock; - + /* Sem to allow jffs2_garbage_collect_deletion_dirent to - drop the erase_completion_lock while it's holding a pointer + drop the erase_completion_lock while it's holding a pointer to an obsoleted node. I don't like this. Alternatives welcomed. */ struct semaphore erase_free_sem; uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */ - + #ifdef CONFIG_JFFS2_FS_WRITEBUFFER /* Write-behind buffer for NAND flash */ unsigned char *wbuf; -- cgit v1.2.3 From 03ead8427d65f6986a8bf5fd3f29a879348780ad Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 11:15:37 +0000 Subject: [LIB] reed_solomon: Clean up trailing white spaces --- include/linux/rslib.h | 28 +++++++++--------- lib/reed_solomon/Makefile | 2 +- lib/reed_solomon/decode_rs.c | 36 +++++++++++------------ lib/reed_solomon/encode_rs.c | 14 ++++----- lib/reed_solomon/reed_solomon.c | 64 ++++++++++++++++++++--------------------- 5 files changed, 72 insertions(+), 72 deletions(-) diff --git a/include/linux/rslib.h b/include/linux/rslib.h index 980c8f74d8d..ace25acfdc9 100644 --- a/include/linux/rslib.h +++ b/include/linux/rslib.h @@ -1,15 +1,15 @@ -/* +/* * include/linux/rslib.h * * Overview: * Generic Reed Solomon encoder / decoder library - * + * * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) * * RS code lifted from reed solomon library written by Phil Karn * Copyright 2002 Phil Karn, KA9Q * - * $Id: rslib.h,v 1.3 2004/10/05 22:08:22 gleixner Exp $ + * $Id: rslib.h,v 1.4 2005/11/07 11:14:52 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -21,20 +21,20 @@ #include -/** +/** * struct rs_control - rs control structure - * + * * @mm: Bits per symbol * @nn: Symbols per block (= (1<mm = number of bits per symbol + * rs->mm = number of bits per symbol * rs->nn = (2^rs->mm) - 1 - * + * * Simple arithmetic modulo would return a wrong result for values * >= 3 * rs->nn */ diff --git a/lib/reed_solomon/Makefile b/lib/reed_solomon/Makefile index 747a2de2934..c3d7136827e 100644 --- a/lib/reed_solomon/Makefile +++ b/lib/reed_solomon/Makefile @@ -1,5 +1,5 @@ # -# This is a modified version of reed solomon lib, +# This is a modified version of reed solomon lib, # obj-$(CONFIG_REED_SOLOMON) += reed_solomon.o diff --git a/lib/reed_solomon/decode_rs.c b/lib/reed_solomon/decode_rs.c index d401decd628..a58df56f09b 100644 --- a/lib/reed_solomon/decode_rs.c +++ b/lib/reed_solomon/decode_rs.c @@ -1,22 +1,22 @@ -/* +/* * lib/reed_solomon/decode_rs.c * * Overview: * Generic Reed Solomon encoder / decoder library - * + * * Copyright 2002, Phil Karn, KA9Q * May be used under the terms of the GNU General Public License (GPL) * * Adaption to the kernel by Thomas Gleixner (tglx@linutronix.de) * - * $Id: decode_rs.c,v 1.6 2004/10/22 15:41:47 gleixner Exp $ + * $Id: decode_rs.c,v 1.7 2005/11/07 11:14:59 gleixner Exp $ * */ -/* Generic data width independent code which is included by the +/* Generic data width independent code which is included by the * wrappers. */ -{ +{ int deg_lambda, el, deg_omega; int i, j, r, k, pad; int nn = rs->nn; @@ -41,9 +41,9 @@ pad = nn - nroots - len; if (pad < 0 || pad >= nn) return -ERANGE; - + /* Does the caller provide the syndrome ? */ - if (s != NULL) + if (s != NULL) goto decode; /* form the syndromes; i.e., evaluate data(x) at roots of @@ -54,11 +54,11 @@ for (j = 1; j < len; j++) { for (i = 0; i < nroots; i++) { if (syn[i] == 0) { - syn[i] = (((uint16_t) data[j]) ^ + syn[i] = (((uint16_t) data[j]) ^ invmsk) & msk; } else { syn[i] = ((((uint16_t) data[j]) ^ - invmsk) & msk) ^ + invmsk) & msk) ^ alpha_to[rs_modnn(rs, index_of[syn[i]] + (fcr + i) * prim)]; } @@ -70,7 +70,7 @@ if (syn[i] == 0) { syn[i] = ((uint16_t) par[j]) & msk; } else { - syn[i] = (((uint16_t) par[j]) & msk) ^ + syn[i] = (((uint16_t) par[j]) & msk) ^ alpha_to[rs_modnn(rs, index_of[syn[i]] + (fcr+i)*prim)]; } @@ -99,14 +99,14 @@ if (no_eras > 0) { /* Init lambda to be the erasure locator polynomial */ - lambda[1] = alpha_to[rs_modnn(rs, + lambda[1] = alpha_to[rs_modnn(rs, prim * (nn - 1 - eras_pos[0]))]; for (i = 1; i < no_eras; i++) { u = rs_modnn(rs, prim * (nn - 1 - eras_pos[i])); for (j = i + 1; j > 0; j--) { tmp = index_of[lambda[j - 1]]; if (tmp != nn) { - lambda[j] ^= + lambda[j] ^= alpha_to[rs_modnn(rs, u + tmp)]; } } @@ -127,8 +127,8 @@ discr_r = 0; for (i = 0; i < r; i++) { if ((lambda[i] != 0) && (s[r - i - 1] != nn)) { - discr_r ^= - alpha_to[rs_modnn(rs, + discr_r ^= + alpha_to[rs_modnn(rs, index_of[lambda[i]] + s[r - i - 1])]; } @@ -143,7 +143,7 @@ t[0] = lambda[0]; for (i = 0; i < nroots; i++) { if (b[i] != nn) { - t[i + 1] = lambda[i + 1] ^ + t[i + 1] = lambda[i + 1] ^ alpha_to[rs_modnn(rs, discr_r + b[i])]; } else @@ -229,7 +229,7 @@ num1 = 0; for (i = deg_omega; i >= 0; i--) { if (omega[i] != nn) - num1 ^= alpha_to[rs_modnn(rs, omega[i] + + num1 ^= alpha_to[rs_modnn(rs, omega[i] + i * root[j])]; } num2 = alpha_to[rs_modnn(rs, root[j] * (fcr - 1) + nn)]; @@ -239,13 +239,13 @@ * lambda_pr of lambda[i] */ for (i = min(deg_lambda, nroots - 1) & ~1; i >= 0; i -= 2) { if (lambda[i + 1] != nn) { - den ^= alpha_to[rs_modnn(rs, lambda[i + 1] + + den ^= alpha_to[rs_modnn(rs, lambda[i + 1] + i * root[j])]; } } /* Apply error to data */ if (num1 != 0 && loc[j] >= pad) { - uint16_t cor = alpha_to[rs_modnn(rs,index_of[num1] + + uint16_t cor = alpha_to[rs_modnn(rs,index_of[num1] + index_of[num2] + nn - index_of[den])]; /* Store the error correction pattern, if a diff --git a/lib/reed_solomon/encode_rs.c b/lib/reed_solomon/encode_rs.c index 237bf65ae88..0b5b1a6728e 100644 --- a/lib/reed_solomon/encode_rs.c +++ b/lib/reed_solomon/encode_rs.c @@ -1,19 +1,19 @@ -/* +/* * lib/reed_solomon/encode_rs.c * * Overview: * Generic Reed Solomon encoder / decoder library - * + * * Copyright 2002, Phil Karn, KA9Q * May be used under the terms of the GNU General Public License (GPL) * * Adaption to the kernel by Thomas Gleixner (tglx@linutronix.de) * - * $Id: encode_rs.c,v 1.4 2004/10/22 15:41:47 gleixner Exp $ + * $Id: encode_rs.c,v 1.5 2005/11/07 11:14:59 gleixner Exp $ * */ -/* Generic data width independent code which is included by the +/* Generic data width independent code which is included by the * wrappers. * int encode_rsX (struct rs_control *rs, uintX_t *data, int len, uintY_t *par) */ @@ -35,16 +35,16 @@ for (i = 0; i < len; i++) { fb = index_of[((((uint16_t) data[i])^invmsk) & msk) ^ par[0]]; /* feedback term is non-zero */ - if (fb != nn) { + if (fb != nn) { for (j = 1; j < nroots; j++) { - par[j] ^= alpha_to[rs_modnn(rs, fb + + par[j] ^= alpha_to[rs_modnn(rs, fb + genpoly[nroots - j])]; } } /* Shift */ memmove(&par[0], &par[1], sizeof(uint16_t) * (nroots - 1)); if (fb != nn) { - par[nroots - 1] = alpha_to[rs_modnn(rs, + par[nroots - 1] = alpha_to[rs_modnn(rs, fb + genpoly[0])]; } else { par[nroots - 1] = 0; diff --git a/lib/reed_solomon/reed_solomon.c b/lib/reed_solomon/reed_solomon.c index 6604e3b1940..f5fef948a41 100644 --- a/lib/reed_solomon/reed_solomon.c +++ b/lib/reed_solomon/reed_solomon.c @@ -1,22 +1,22 @@ -/* +/* * lib/reed_solomon/rslib.c * * Overview: * Generic Reed Solomon encoder / decoder library - * + * * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) * * Reed Solomon code lifted from reed solomon library written by Phil Karn * Copyright 2002 Phil Karn, KA9Q * - * $Id: rslib.c,v 1.5 2004/10/22 15:41:47 gleixner Exp $ + * $Id: rslib.c,v 1.7 2005/11/07 11:14:59 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Description: - * + * * The generic Reed Solomon library provides runtime configurable * encoding / decoding of RS codes. * Each user must call init_rs to get a pointer to a rs_control @@ -25,11 +25,11 @@ * If a structure is generated then the polynomial arrays for * fast encoding / decoding are built. This can take some time so * make sure not to call this function from a time critical path. - * Usually a module / driver should initialize the necessary + * Usually a module / driver should initialize the necessary * rs_control structure on module / driver init and release it * on exit. - * The encoding puts the calculated syndrome into a given syndrome - * buffer. + * The encoding puts the calculated syndrome into a given syndrome + * buffer. * The decoding is a two step process. The first step calculates * the syndrome over the received (data + syndrome) and calls the * second stage, which does the decoding / error correction itself. @@ -51,7 +51,7 @@ static LIST_HEAD (rslist); /* Protection for the list */ static DECLARE_MUTEX(rslistlock); -/** +/** * rs_init - Initialize a Reed-Solomon codec * * @symsize: symbol size, bits (1-8) @@ -63,7 +63,7 @@ static DECLARE_MUTEX(rslistlock); * Allocate a control structure and the polynom arrays for faster * en/decoding. Fill the arrays according to the given parameters */ -static struct rs_control *rs_init(int symsize, int gfpoly, int fcr, +static struct rs_control *rs_init(int symsize, int gfpoly, int fcr, int prim, int nroots) { struct rs_control *rs; @@ -124,15 +124,15 @@ static struct rs_control *rs_init(int symsize, int gfpoly, int fcr, /* Multiply rs->genpoly[] by @**(root + x) */ for (j = i; j > 0; j--) { if (rs->genpoly[j] != 0) { - rs->genpoly[j] = rs->genpoly[j -1] ^ - rs->alpha_to[rs_modnn(rs, + rs->genpoly[j] = rs->genpoly[j -1] ^ + rs->alpha_to[rs_modnn(rs, rs->index_of[rs->genpoly[j]] + root)]; } else rs->genpoly[j] = rs->genpoly[j - 1]; } /* rs->genpoly[0] can never be zero */ - rs->genpoly[0] = - rs->alpha_to[rs_modnn(rs, + rs->genpoly[0] = + rs->alpha_to[rs_modnn(rs, rs->index_of[rs->genpoly[0]] + root)]; } /* convert rs->genpoly[] to index form for quicker encoding */ @@ -153,7 +153,7 @@ errrs: } -/** +/** * free_rs - Free the rs control structure, if its not longer used * * @rs: the control structure which is not longer used by the @@ -173,19 +173,19 @@ void free_rs(struct rs_control *rs) up(&rslistlock); } -/** +/** * init_rs - Find a matching or allocate a new rs control structure * * @symsize: the symbol size (number of bits) * @gfpoly: the extended Galois field generator polynomial coefficients, * with the 0th coefficient in the low order bit. The polynomial * must be primitive; - * @fcr: the first consecutive root of the rs code generator polynomial + * @fcr: the first consecutive root of the rs code generator polynomial * in index form * @prim: primitive element to generate polynomial roots * @nroots: RS code generator polynomial degree (number of roots) */ -struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim, +struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim, int nroots) { struct list_head *tmp; @@ -198,9 +198,9 @@ struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim, return NULL; if (prim <= 0 || prim >= (1<= (1< 8) + if (nroots < 0 || nroots >= (1<gfpoly) continue; if (fcr != rs->fcr) - continue; + continue; if (prim != rs->prim) - continue; + continue; if (nroots != rs->nroots) continue; /* We have a matching one already */ @@ -227,18 +227,18 @@ struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim, rs->users = 1; list_add(&rs->list, &rslist); } -out: +out: up(&rslistlock); return rs; } #ifdef CONFIG_REED_SOLOMON_ENC8 -/** +/** * encode_rs8 - Calculate the parity for data values (8bit data width) * * @rs: the rs control structure * @data: data field of a given type - * @len: data length + * @len: data length * @par: parity data, must be initialized by caller (usually all 0) * @invmsk: invert data mask (will be xored on data) * @@ -246,7 +246,7 @@ out: * symbol size > 8. The calling code must take care of encoding of the * syndrome result for storage itself. */ -int encode_rs8(struct rs_control *rs, uint8_t *data, int len, uint16_t *par, +int encode_rs8(struct rs_control *rs, uint8_t *data, int len, uint16_t *par, uint16_t invmsk) { #include "encode_rs.c" @@ -255,7 +255,7 @@ EXPORT_SYMBOL_GPL(encode_rs8); #endif #ifdef CONFIG_REED_SOLOMON_DEC8 -/** +/** * decode_rs8 - Decode codeword (8bit data width) * * @rs: the rs control structure @@ -273,7 +273,7 @@ EXPORT_SYMBOL_GPL(encode_rs8); * syndrome result and the received parity before calling this code. */ int decode_rs8(struct rs_control *rs, uint8_t *data, uint16_t *par, int len, - uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk, + uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk, uint16_t *corr) { #include "decode_rs.c" @@ -287,13 +287,13 @@ EXPORT_SYMBOL_GPL(decode_rs8); * * @rs: the rs control structure * @data: data field of a given type - * @len: data length + * @len: data length * @par: parity data, must be initialized by caller (usually all 0) * @invmsk: invert data mask (will be xored on data, not on parity!) * * Each field in the data array contains up to symbol size bits of valid data. */ -int encode_rs16(struct rs_control *rs, uint16_t *data, int len, uint16_t *par, +int encode_rs16(struct rs_control *rs, uint16_t *data, int len, uint16_t *par, uint16_t invmsk) { #include "encode_rs.c" @@ -302,7 +302,7 @@ EXPORT_SYMBOL_GPL(encode_rs16); #endif #ifdef CONFIG_REED_SOLOMON_DEC16 -/** +/** * decode_rs16 - Decode codeword (16bit data width) * * @rs: the rs control structure @@ -312,13 +312,13 @@ EXPORT_SYMBOL_GPL(encode_rs16); * @s: syndrome data field (if NULL, syndrome is calculated) * @no_eras: number of erasures * @eras_pos: position of erasures, can be NULL - * @invmsk: invert data mask (will be xored on data, not on parity!) + * @invmsk: invert data mask (will be xored on data, not on parity!) * @corr: buffer to store correction bitmask on eras_pos * * Each field in the data array contains up to symbol size bits of valid data. */ int decode_rs16(struct rs_control *rs, uint16_t *data, uint16_t *par, int len, - uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk, + uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk, uint16_t *corr) { #include "decode_rs.c" -- cgit v1.2.3 From 61ecfa8777d0bc8e33dc0e5c2cca9b3247da2d37 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 11:15:31 +0000 Subject: [MTD] includes: Clean up trailing white spaces Signed-off-by: Thomas Gleixner --- include/linux/mtd/bbm.h | 2 +- include/linux/mtd/blktrans.h | 4 ++-- include/linux/mtd/cfi.h | 24 +++++++++---------- include/linux/mtd/doc2000.h | 18 +++++++------- include/linux/mtd/flashchip.h | 14 +++++------ include/linux/mtd/ftl.h | 6 ++--- include/linux/mtd/gen_probe.h | 4 ++-- include/linux/mtd/jedec.h | 20 ++++++++-------- include/linux/mtd/map.h | 14 +++++------ include/linux/mtd/mtd.h | 24 +++++++++---------- include/linux/mtd/nand.h | 54 +++++++++++++++++++++--------------------- include/linux/mtd/onenand.h | 2 +- include/linux/mtd/partitions.h | 20 ++++++++-------- include/linux/mtd/physmap.h | 12 +++++----- include/linux/mtd/pmc551.h | 12 +++++----- include/linux/mtd/xip.h | 6 ++--- 16 files changed, 118 insertions(+), 118 deletions(-) diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h index 92b42cb7ed2..7a7fbe87fef 100644 --- a/include/linux/mtd/bbm.h +++ b/include/linux/mtd/bbm.h @@ -29,7 +29,7 @@ * @param version version read from the bbt page during scan * @param len length of the pattern, if 0 no pattern check is performed * @param maxblocks maximum number of blocks to search for a bbt. This number of - * blocks is reserved at the end of the device + * blocks is reserved at the end of the device * where the tables are written. * @param reserved_block_code if non-0, this pattern denotes a reserved * (rather than bad) block in the stored bbt diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h index 4ebc2e5a16e..f46afec6fbf 100644 --- a/include/linux/mtd/blktrans.h +++ b/include/linux/mtd/blktrans.h @@ -1,5 +1,5 @@ /* - * $Id: blktrans.h,v 1.5 2003/06/23 12:00:08 dwmw2 Exp $ + * $Id: blktrans.h,v 1.6 2005/11/07 11:14:54 gleixner Exp $ * * (C) 2003 David Woodhouse * @@ -67,6 +67,6 @@ extern int register_mtd_blktrans(struct mtd_blktrans_ops *tr); extern int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr); extern int add_mtd_blktrans_dev(struct mtd_blktrans_dev *dev); extern int del_mtd_blktrans_dev(struct mtd_blktrans_dev *dev); - + #endif /* __MTD_TRANS_H__ */ diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index 360cf626c28..39f1430bd6d 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h @@ -1,7 +1,7 @@ -/* Common Flash Interface structures +/* Common Flash Interface structures * See http://support.intel.com/design/flash/technote/index.htm - * $Id: cfi.h,v 1.55 2005/08/06 04:40:42 nico Exp $ + * $Id: cfi.h,v 1.56 2005/11/07 11:14:54 gleixner Exp $ */ #ifndef __MTD_CFI_H__ @@ -82,8 +82,8 @@ static inline int cfi_interleave_supported(int i) } -/* NB: these values must represents the number of bytes needed to meet the - * device type (x8, x16, x32). Eg. a 32 bit device is 4 x 8 bytes. +/* NB: these values must represents the number of bytes needed to meet the + * device type (x8, x16, x32). Eg. a 32 bit device is 4 x 8 bytes. * These numbers are used in calculations. */ #define CFI_DEVICETYPE_X8 (8 / 8) @@ -259,7 +259,7 @@ static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, int interleave, int /* * Transforms the CFI command for the given geometry (bus width & interleave). * It looks too long to be inline, but in the common case it should almost all - * get optimised away. + * get optimised away. */ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cfi_private *cfi) { @@ -268,7 +268,7 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf unsigned long onecmd; int i; - /* We do it this way to give the compiler a fighting chance + /* We do it this way to give the compiler a fighting chance of optimising away all the crap for 'bankwidth' larger than an unsigned long, in the common case where that support is disabled */ @@ -279,7 +279,7 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf wordwidth = map_bankwidth(map); words_per_bus = 1; } - + chip_mode = map_bankwidth(map) / cfi_interleave(cfi); chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map); @@ -298,7 +298,7 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf break; } - /* Now replicate it across the size of an unsigned long, or + /* Now replicate it across the size of an unsigned long, or just to the bus width as appropriate */ switch (chips_per_word) { default: BUG(); @@ -314,7 +314,7 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf ; } - /* And finally, for the multi-word case, replicate it + /* And finally, for the multi-word case, replicate it in all words in the structure */ for (i=0; i < words_per_bus; i++) { val.x[i] = onecmd; @@ -325,14 +325,14 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf #define CMD(x) cfi_build_cmd((x), map, cfi) -static inline unsigned long cfi_merge_status(map_word val, struct map_info *map, +static inline unsigned long cfi_merge_status(map_word val, struct map_info *map, struct cfi_private *cfi) { int wordwidth, words_per_bus, chip_mode, chips_per_word; unsigned long onestat, res = 0; int i; - /* We do it this way to give the compiler a fighting chance + /* We do it this way to give the compiler a fighting chance of optimising away all the crap for 'bankwidth' larger than an unsigned long, in the common case where that support is disabled */ @@ -343,7 +343,7 @@ static inline unsigned long cfi_merge_status(map_word val, struct map_info *map, wordwidth = map_bankwidth(map); words_per_bus = 1; } - + chip_mode = map_bankwidth(map) / cfi_interleave(cfi); chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map); diff --git a/include/linux/mtd/doc2000.h b/include/linux/mtd/doc2000.h index 953e64fb8ac..386a52cf8b1 100644 --- a/include/linux/mtd/doc2000.h +++ b/include/linux/mtd/doc2000.h @@ -1,12 +1,12 @@ -/* +/* * Linux driver for Disk-On-Chip devices * - * Copyright (C) 1999 Machine Vision Holdings, Inc. + * Copyright (C) 1999 Machine Vision Holdings, Inc. * Copyright (C) 2001-2003 David Woodhouse * Copyright (C) 2002-2003 Greg Ungerer * Copyright (C) 2002-2003 SnapGear Inc * - * $Id: doc2000.h,v 1.24 2005/01/05 12:40:38 dwmw2 Exp $ + * $Id: doc2000.h,v 1.25 2005/11/07 11:14:54 gleixner Exp $ * * Released under GPL */ @@ -75,10 +75,10 @@ #define DoC_Mplus_CtrlConfirm 0x1076 #define DoC_Mplus_Power 0x1fff -/* How to access the device? - * On ARM, it'll be mmap'd directly with 32-bit wide accesses. +/* How to access the device? + * On ARM, it'll be mmap'd directly with 32-bit wide accesses. * On PPC, it's mmap'd and 16-bit wide. - * Others use readb/writeb + * Others use readb/writeb */ #if defined(__arm__) #define ReadDOC_(adr, reg) ((unsigned char)(*(volatile __u32 *)(((unsigned long)adr)+((reg)<<2)))) @@ -172,7 +172,7 @@ struct DiskOnChip { unsigned long totlen; unsigned char ChipID; /* Type of DiskOnChip */ int ioreg; - + unsigned long mfr; /* Flash IDs - only one type of flash per device */ unsigned long id; int chipshift; @@ -180,10 +180,10 @@ struct DiskOnChip { char pageadrlen; char interleave; /* Internal interleaving - Millennium Plus style */ unsigned long erasesize; - + int curfloor; int curchip; - + int numchips; struct Nand *chips; struct mtd_info *nextdoc; diff --git a/include/linux/mtd/flashchip.h b/include/linux/mtd/flashchip.h index 675776fa3e2..a293a3b78e0 100644 --- a/include/linux/mtd/flashchip.h +++ b/include/linux/mtd/flashchip.h @@ -1,12 +1,12 @@ -/* +/* * struct flchip definition - * - * Contains information about the location and state of a given flash device + * + * Contains information about the location and state of a given flash device * * (C) 2000 Red Hat. GPLd. * - * $Id: flashchip.h,v 1.17 2005/03/14 18:27:15 bjd Exp $ + * $Id: flashchip.h,v 1.18 2005/11/07 11:14:54 gleixner Exp $ * */ @@ -15,11 +15,11 @@ /* For spinlocks. sched.h includes spinlock.h from whichever directory it * happens to be in - so we don't have to care whether we're on 2.2, which - * has asm/spinlock.h, or 2.4, which has linux/spinlock.h + * has asm/spinlock.h, or 2.4, which has linux/spinlock.h */ #include -typedef enum { +typedef enum { FL_READY, FL_STATUS, FL_CFI_QUERY, @@ -45,7 +45,7 @@ typedef enum { -/* NOTE: confusingly, this can be used to refer to more than one chip at a time, +/* NOTE: confusingly, this can be used to refer to more than one chip at a time, if they're interleaved. This can even refer to individual partitions on the same physical chip when present. */ diff --git a/include/linux/mtd/ftl.h b/include/linux/mtd/ftl.h index 3678459b453..d9960911330 100644 --- a/include/linux/mtd/ftl.h +++ b/include/linux/mtd/ftl.h @@ -1,6 +1,6 @@ /* - * $Id: ftl.h,v 1.6 2003/01/24 13:20:04 dwmw2 Exp $ - * + * $Id: ftl.h,v 1.7 2005/11/07 11:14:54 gleixner Exp $ + * * Derived from (and probably identical to): * ftl.h 1.7 1999/10/25 20:23:17 * @@ -12,7 +12,7 @@ * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and - * limitations under the License. + * limitations under the License. * * The initial developer of the original code is David A. Hinds * . Portions created by David A. Hinds diff --git a/include/linux/mtd/gen_probe.h b/include/linux/mtd/gen_probe.h index 3d7bdec14f9..256e7342ed1 100644 --- a/include/linux/mtd/gen_probe.h +++ b/include/linux/mtd/gen_probe.h @@ -1,14 +1,14 @@ /* * (C) 2001, 2001 Red Hat, Inc. * GPL'd - * $Id: gen_probe.h,v 1.3 2004/10/20 22:10:33 dwmw2 Exp $ + * $Id: gen_probe.h,v 1.4 2005/11/07 11:14:54 gleixner Exp $ */ #ifndef __LINUX_MTD_GEN_PROBE_H__ #define __LINUX_MTD_GEN_PROBE_H__ #include -#include +#include #include #include diff --git a/include/linux/mtd/jedec.h b/include/linux/mtd/jedec.h index 2ba0f700ddb..9006feb218b 100644 --- a/include/linux/mtd/jedec.h +++ b/include/linux/mtd/jedec.h @@ -1,13 +1,13 @@ /* JEDEC Flash Interface. - * This is an older type of interface for self programming flash. It is + * This is an older type of interface for self programming flash. It is * commonly use in older AMD chips and is obsolete compared with CFI. * It is called JEDEC because the JEDEC association distributes the ID codes * for the chips. * * See the AMD flash databook for information on how to operate the interface. * - * $Id: jedec.h,v 1.3 2003/05/21 11:51:01 dwmw2 Exp $ + * $Id: jedec.h,v 1.4 2005/11/07 11:14:54 gleixner Exp $ */ #ifndef __LINUX_MTD_JEDEC_H__ @@ -33,16 +33,16 @@ struct jedec_flash_chip __u16 jedec; unsigned long size; unsigned long sectorsize; - + // *(__u8*)(base + (adder << addrshift)) = data << datashift // Address size = size << addrshift unsigned long base; // Byte 0 of the flash, will be unaligned unsigned int datashift; // Useful for 32bit/16bit accesses unsigned int addrshift; unsigned long offset; // linerized start. base==offset for unbanked, uninterleaved flash - + __u32 capabilities; - + // These markers are filled in by the flash_chip_scan function unsigned long start; unsigned long length; @@ -51,16 +51,16 @@ struct jedec_flash_chip struct jedec_private { unsigned long size; // Total size of all the devices - + /* Bank handling. If sum(bank_fill) == size then this is linear flash. Otherwise the mapping has holes in it. bank_fill may be used to - find the holes, but in the common symetric case - bank_fill[0] == bank_fill[*], thus addresses may be computed + find the holes, but in the common symetric case + bank_fill[0] == bank_fill[*], thus addresses may be computed mathmatically. bank_fill must be powers of two */ unsigned is_banked; unsigned long bank_fill[MAX_JEDEC_CHIPS]; - - struct jedec_flash_chip chips[MAX_JEDEC_CHIPS]; + + struct jedec_flash_chip chips[MAX_JEDEC_CHIPS]; }; #endif diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h index fc28841f340..fedfbc8a287 100644 --- a/include/linux/mtd/map.h +++ b/include/linux/mtd/map.h @@ -1,6 +1,6 @@ /* Overhauled routines for dealing with different mmap regions of flash */ -/* $Id: map.h,v 1.52 2005/05/25 10:29:41 gleixner Exp $ */ +/* $Id: map.h,v 1.54 2005/11/07 11:14:54 gleixner Exp $ */ #ifndef __LINUX_MTD_MAP_H__ #define __LINUX_MTD_MAP_H__ @@ -170,14 +170,14 @@ typedef union { to a chip probe routine -- either JEDEC or CFI probe or both -- via do_map_probe(). If a chip is recognised, the probe code will invoke the appropriate chip driver (if present) and return a struct mtd_info. - At which point, you fill in the mtd->module with your own module + At which point, you fill in the mtd->module with your own module address, and register it with the MTD core code. Or you could partition it and register the partitions instead, or keep it for your own private use; whatever. - + The mtd->priv field will point to the struct map_info, and any further - private data required by the chip driver is linked from the - mtd->priv->fldrv_priv field. This allows the map driver to get at + private data required by the chip driver is linked from the + mtd->priv->fldrv_priv field. This allows the map driver to get at the destructor function map->fldrv_destroy() when it's tired of living. */ @@ -214,7 +214,7 @@ struct map_info { If there is no cache to care about this can be set to NULL. */ void (*inval_cache)(struct map_info *, unsigned long, ssize_t); - /* set_vpp() must handle being reentered -- enable, enable, disable + /* set_vpp() must handle being reentered -- enable, enable, disable must leave it enabled. */ void (*set_vpp)(struct map_info *, int); @@ -353,7 +353,7 @@ static inline map_word map_word_ff(struct map_info *map) { map_word r; int i; - + if (map_bankwidth(map) < MAP_FF_LIMIT) { int bw = 8 * map_bankwidth(map); r.x[0] = (1 << bw) - 1; diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index ab580418391..e95d0463a3e 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -1,5 +1,5 @@ -/* - * $Id: mtd.h,v 1.60 2005/08/06 04:40:42 nico Exp $ +/* + * $Id: mtd.h,v 1.61 2005/11/07 11:14:54 gleixner Exp $ * * Copyright (C) 1999-2003 David Woodhouse et al. * @@ -90,13 +90,13 @@ struct mtd_info { // oobinfo is a nand_oobinfo structure, which can be set by iotcl (MEMSETOOBINFO) struct nand_oobinfo oobinfo; - u_int32_t oobavail; // Number of bytes in OOB area available for fs + u_int32_t oobavail; // Number of bytes in OOB area available for fs /* Data for variable erase regions. If numeraseregions is zero, - * it means that the whole device has erasesize as given above. + * it means that the whole device has erasesize as given above. */ int numeraseregions; - struct mtd_erase_region_info *eraseregions; + struct mtd_erase_region_info *eraseregions; /* This really shouldn't be here. It can go away in 2.5 */ u_int32_t bank_size; @@ -119,10 +119,10 @@ struct mtd_info { int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); - /* - * Methods to access the protection register area, present in some + /* + * Methods to access the protection register area, present in some * flash devices. The user data is one time programmable but the - * factory data is read only. + * factory data is read only. */ int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len); int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); @@ -133,14 +133,14 @@ struct mtd_info { /* kvec-based read/write methods. We need these especially for NAND flash, with its limited number of write cycles per erase. - NB: The 'count' parameter is the number of _vectors_, each of + NB: The 'count' parameter is the number of _vectors_, each of which contains an (ofs, len) tuple. */ int (*readv) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen); - int (*readv_ecc) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, + int (*readv_ecc) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel); int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); - int (*writev_ecc) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, + int (*writev_ecc) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel); /* Sync */ @@ -204,7 +204,7 @@ int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs, #define MTD_WRITEECC(mtd, args...) (*(mtd->write_ecc))(mtd, args) #define MTD_READOOB(mtd, args...) (*(mtd->read_oob))(mtd, args) #define MTD_WRITEOOB(mtd, args...) (*(mtd->write_oob))(mtd, args) -#define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd); } while (0) +#define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd); } while (0) #ifdef CONFIG_MTD_PARTITIONS diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 2d36413b2f9..da5e67b3fc7 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -24,7 +24,7 @@ * bat later if I did something naughty. * 10-11-2000 SJH Added private NAND flash structure for driver * 10-24-2000 SJH Added prototype for 'nand_scan' function - * 10-29-2001 TG changed nand_chip structure to support + * 10-29-2001 TG changed nand_chip structure to support * hardwarespecific function for accessing control lines * 02-21-2002 TG added support for different read/write adress and * ready/busy line access function @@ -36,21 +36,21 @@ * CONFIG_MTD_NAND_ECC_JFFS2 is not set * 08-10-2002 TG extensions to nand_chip structure to support HW-ECC * - * 08-29-2002 tglx nand_chip structure: data_poi for selecting + * 08-29-2002 tglx nand_chip structure: data_poi for selecting * internal / fs-driver buffer * support for 6byte/512byte hardware ECC * read_ecc, write_ecc extended for different oob-layout * oob layout selections: NAND_NONE_OOB, NAND_JFFS2_OOB, * NAND_YAFFS_OOB * 11-25-2002 tglx Added Manufacturer code FUJITSU, NATIONAL - * Split manufacturer and device ID structures + * Split manufacturer and device ID structures * * 02-08-2004 tglx added option field to nand structure for chip anomalities * 05-25-2004 tglx added bad block table support, ST-MICRO manufacturer id * update of nand_chip structure description - * 01-17-2005 dmarlin added extended commands for AG-AND device and added option + * 01-17-2005 dmarlin added extended commands for AG-AND device and added option * for BBT_AUTO_REFRESH. - * 01-20-2005 dmarlin added optional pointer to hardware specific callback for + * 01-20-2005 dmarlin added optional pointer to hardware specific callback for * extra error status checks. */ #ifndef __LINUX_MTD_NAND_H @@ -120,8 +120,8 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_ #define NAND_CMD_CACHEDPROG 0x15 /* Extended commands for AG-AND device */ -/* - * Note: the command for NAND_CMD_DEPLETE1 is really 0x00 but +/* + * Note: the command for NAND_CMD_DEPLETE1 is really 0x00 but * there is no way to distinguish that from NAND_CMD_READ0 * until the remaining sequence of commands has been completed * so add a high order bit and mask it off in the command. @@ -145,7 +145,7 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_ #define NAND_STATUS_READY 0x40 #define NAND_STATUS_WP 0x80 -/* +/* * Constants for ECC_MODES */ @@ -191,12 +191,12 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_ #define NAND_CACHEPRG 0x00000008 /* Chip has copy back function */ #define NAND_COPYBACK 0x00000010 -/* AND Chip which has 4 banks and a confusing page / block +/* AND Chip which has 4 banks and a confusing page / block * assignment. See Renesas datasheet for further information */ #define NAND_IS_AND 0x00000020 /* Chip has a array of 4 pages which can be read without * additional ready /busy waits */ -#define NAND_4PAGE_ARRAY 0x00000040 +#define NAND_4PAGE_ARRAY 0x00000040 /* Chip requires that BBT is periodically rewritten to prevent * bits from adjacent blocks from 'leaking' in altering data. * This happens with the Renesas AG-AND chips, possibly others. */ @@ -219,8 +219,8 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_ /* Use a flash based bad block table. This option is passed to the * default bad block table function. */ #define NAND_USE_FLASH_BBT 0x00010000 -/* The hw ecc generator provides a syndrome instead a ecc value on read - * This can only work if we have the ecc bytes directly behind the +/* The hw ecc generator provides a syndrome instead a ecc value on read + * This can only work if we have the ecc bytes directly behind the * data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */ #define NAND_HWECC_SYNDROME 0x00020000 /* This option skips the bbt scan during initialization. */ @@ -252,7 +252,7 @@ struct nand_chip; /** * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independend devices - * @lock: protection lock + * @lock: protection lock * @active: the mtd device which holds the controller currently * @wq: wait queue to sleep on if a NAND operation is in progress * used instead of the per chip wait queue when a hw controller is available @@ -265,8 +265,8 @@ struct nand_hw_control { /** * struct nand_chip - NAND Private Flash Chip Data - * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device - * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device + * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device + * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device * @read_byte: [REPLACEABLE] read one byte from the chip * @write_byte: [REPLACEABLE] write one byte to the chip * @read_word: [REPLACEABLE] read one word from the chip @@ -289,7 +289,7 @@ struct nand_hw_control { * be provided if a hardware ECC is available * @erase_cmd: [INTERN] erase command write function, selectable due to AND support * @scan_bbt: [REPLACEABLE] function to scan bad block table - * @eccmode: [BOARDSPECIFIC] mode of ecc, see defines + * @eccmode: [BOARDSPECIFIC] mode of ecc, see defines * @eccsize: [INTERN] databytes used per ecc-calculation * @eccbytes: [INTERN] number of ecc bytes per ecc-calculation step * @eccsteps: [INTERN] number of ecc calculation steps per page @@ -301,7 +301,7 @@ struct nand_hw_control { * @phys_erase_shift: [INTERN] number of address bits in a physical eraseblock * @bbt_erase_shift: [INTERN] number of address bits in a bbt entry * @chip_shift: [INTERN] number of address bits in one chip - * @data_buf: [INTERN] internal buffer for one page + oob + * @data_buf: [INTERN] internal buffer for one page + oob * @oob_buf: [INTERN] oob buffer for one eraseblock * @oobdirty: [INTERN] indicates that oob_buf must be reinitialized * @data_poi: [INTERN] pointer to a data buffer @@ -316,22 +316,22 @@ struct nand_hw_control { * @bbt: [INTERN] bad block table pointer * @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup * @bbt_md: [REPLACEABLE] bad block table mirror descriptor - * @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial bad block scan + * @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial bad block scan * @controller: [OPTIONAL] a pointer to a hardware controller structure which is shared among multiple independend devices * @priv: [OPTIONAL] pointer to private chip date - * @errstat: [OPTIONAL] hardware specific function to perform additional error status checks + * @errstat: [OPTIONAL] hardware specific function to perform additional error status checks * (determine if errors are correctable) */ - + struct nand_chip { void __iomem *IO_ADDR_R; void __iomem *IO_ADDR_W; - + u_char (*read_byte)(struct mtd_info *mtd); void (*write_byte)(struct mtd_info *mtd, u_char byte); u16 (*read_word)(struct mtd_info *mtd); void (*write_word)(struct mtd_info *mtd, u16 word); - + void (*write_buf)(struct mtd_info *mtd, const u_char *buf, int len); void (*read_buf)(struct mtd_info *mtd, u_char *buf, int len); int (*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len); @@ -396,7 +396,7 @@ struct nand_chip { * @name: Identify the device type * @id: device ID code * @pagesize: Pagesize in bytes. Either 256 or 512 or 0 - * If the pagesize is 0, then the real pagesize + * If the pagesize is 0, then the real pagesize * and the eraseize are determined from the * extended id bytes in the chip * @erasesize: Size of an erase block in the flash device. @@ -425,7 +425,7 @@ struct nand_manufacturers { extern struct nand_flash_dev nand_flash_ids[]; extern struct nand_manufacturers nand_manuf_ids[]; -/** +/** * struct nand_bbt_descr - bad block table descriptor * @options: options for this descriptor * @pages: the page(s) where we find the bbt, used with option BBT_ABSPAGE @@ -436,14 +436,14 @@ extern struct nand_manufacturers nand_manuf_ids[]; * @version: version read from the bbt page during scan * @len: length of the pattern, if 0 no pattern check is performed * @maxblocks: maximum number of blocks to search for a bbt. This number of - * blocks is reserved at the end of the device where the tables are + * blocks is reserved at the end of the device where the tables are * written. * @reserved_block_code: if non-0, this pattern denotes a reserved (rather than * bad) block in the stored bbt - * @pattern: pattern to identify bad block table or factory marked good / + * @pattern: pattern to identify bad block table or factory marked good / * bad blocks, can be NULL, if len = 0 * - * Descriptor for the bad block table marker and the descriptor for the + * Descriptor for the bad block table marker and the descriptor for the * pattern which identifies good and bad blocks. The assumption is made * that the pattern and the version count are always located in the oob area * of the first block. diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index d27fd12d096..f1fd4215686 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -77,7 +77,7 @@ struct onenand_bufferram { * @param wq [INTERN] wait queue to sleep on if a OneNAND operation is in progress * @param state [INTERN] the current state of the OneNAND device * @param autooob [REPLACEABLE] the default (auto)placement scheme - * @param bbm [REPLACEABLE] pointer to Bad Block Management + * @param bbm [REPLACEABLE] pointer to Bad Block Management * @param priv [OPTIONAL] pointer to private chip date */ struct onenand_chip { diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h index 50b2edfc8f1..b03f512d51b 100644 --- a/include/linux/mtd/partitions.h +++ b/include/linux/mtd/partitions.h @@ -5,7 +5,7 @@ * * This code is GPL * - * $Id: partitions.h,v 1.16 2004/11/16 18:34:40 dwmw2 Exp $ + * $Id: partitions.h,v 1.17 2005/11/07 11:14:55 gleixner Exp $ */ #ifndef MTD_PARTITIONS_H @@ -16,25 +16,25 @@ /* * Partition definition structure: - * + * * An array of struct partition is passed along with a MTD object to * add_mtd_partitions() to create them. * * For each partition, these fields are available: * name: string that will be used to label the partition's MTD device. - * size: the partition size; if defined as MTDPART_SIZ_FULL, the partition + * size: the partition size; if defined as MTDPART_SIZ_FULL, the partition * will extend to the end of the master MTD device. - * offset: absolute starting position within the master MTD device; if - * defined as MTDPART_OFS_APPEND, the partition will start where the + * offset: absolute starting position within the master MTD device; if + * defined as MTDPART_OFS_APPEND, the partition will start where the * previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block. - * mask_flags: contains flags that have to be masked (removed) from the + * mask_flags: contains flags that have to be masked (removed) from the * master MTD flag set for the corresponding MTD partition. - * For example, to force a read-only partition, simply adding + * For example, to force a read-only partition, simply adding * MTD_WRITEABLE to the mask_flags will do the trick. * - * Note: writeable partitions require their size and offset be + * Note: writeable partitions require their size and offset be * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK). - */ + */ struct mtd_partition { char *name; /* identifier string */ @@ -66,7 +66,7 @@ struct mtd_part_parser { extern int register_mtd_parser(struct mtd_part_parser *parser); extern int deregister_mtd_parser(struct mtd_part_parser *parser); -extern int parse_mtd_partitions(struct mtd_info *master, const char **types, +extern int parse_mtd_partitions(struct mtd_info *master, const char **types, struct mtd_partition **pparts, unsigned long origin); #define put_partition_parser(p) do { module_put((p)->owner); } while(0) diff --git a/include/linux/mtd/physmap.h b/include/linux/mtd/physmap.h index 05aa4970677..c7b8bcdef01 100644 --- a/include/linux/mtd/physmap.h +++ b/include/linux/mtd/physmap.h @@ -1,8 +1,8 @@ /* - * For boards with physically mapped flash and using + * For boards with physically mapped flash and using * drivers/mtd/maps/physmap.c mapping driver. * - * $Id: physmap.h,v 1.3 2004/07/21 00:16:15 jwboyer Exp $ + * $Id: physmap.h,v 1.4 2005/11/07 11:14:55 gleixner Exp $ * * Copyright (C) 2003 MontaVista Software Inc. * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net @@ -18,7 +18,7 @@ #include -#if defined(CONFIG_MTD_PHYSMAP) +#if defined(CONFIG_MTD_PHYSMAP) #include #include @@ -44,12 +44,12 @@ static inline void physmap_configure(unsigned long addr, unsigned long size, int #if defined(CONFIG_MTD_PARTITIONS) /* - * Machines that wish to do flash partition may want to call this function in - * their setup routine. + * Machines that wish to do flash partition may want to call this function in + * their setup routine. * * physmap_set_partitions(mypartitions, num_parts); * - * Note that one can always override this hard-coded partition with + * Note that one can always override this hard-coded partition with * command line partition (you need to enable CONFIG_MTD_CMDLINE_PARTS). */ void physmap_set_partitions(struct mtd_partition *parts, int num_parts); diff --git a/include/linux/mtd/pmc551.h b/include/linux/mtd/pmc551.h index 113e3087f68..a7f6d20ad40 100644 --- a/include/linux/mtd/pmc551.h +++ b/include/linux/mtd/pmc551.h @@ -1,5 +1,5 @@ /* - * $Id: pmc551.h,v 1.5 2003/01/24 16:49:53 dwmw2 Exp $ + * $Id: pmc551.h,v 1.6 2005/11/07 11:14:55 gleixner Exp $ * * PMC551 PCI Mezzanine Ram Device * @@ -7,7 +7,7 @@ * Mark Ferrell * Copyright 1999,2000 Nortel Networks * - * License: + * License: * As part of this driver was derrived from the slram.c driver it falls * under the same license, which is GNU General Public License v2 */ @@ -17,7 +17,7 @@ #include -#define PMC551_VERSION "$Id: pmc551.h,v 1.5 2003/01/24 16:49:53 dwmw2 Exp $\n"\ +#define PMC551_VERSION "$Id: pmc551.h,v 1.6 2005/11/07 11:14:55 gleixner Exp $\n"\ "Ramix PMC551 PCI Mezzanine Ram Driver. (C) 1999,2000 Nortel Networks.\n" /* @@ -30,7 +30,7 @@ struct mypriv { u32 curr_map0; u32 asize; struct mtd_info *nextpmc551; -}; +}; /* * Function Prototypes @@ -39,7 +39,7 @@ static int pmc551_erase(struct mtd_info *, struct erase_info *); static void pmc551_unpoint(struct mtd_info *, u_char *, loff_t, size_t); static int pmc551_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf); static int pmc551_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *); -static int pmc551_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); +static int pmc551_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); /* @@ -50,7 +50,7 @@ static int pmc551_write(struct mtd_info *, loff_t, size_t, size_t *, const u_cha #endif #ifndef PCI_DEVICE_ID_V3_SEMI_V370PDC -#define PCI_DEVICE_ID_V3_SEMI_V370PDC 0x0200 +#define PCI_DEVICE_ID_V3_SEMI_V370PDC 0x0200 #endif diff --git a/include/linux/mtd/xip.h b/include/linux/mtd/xip.h index 863fa5a1d24..220d50bb71c 100644 --- a/include/linux/mtd/xip.h +++ b/include/linux/mtd/xip.h @@ -12,7 +12,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * $Id: xip.h,v 1.4 2005/10/17 21:03:16 nico Exp $ + * $Id: xip.h,v 1.5 2005/11/07 11:14:55 gleixner Exp $ */ #ifndef __LINUX_MTD_XIP_H__ @@ -60,9 +60,9 @@ * overflowing. * * xip_iprefetch() - * + * * Macro to fill instruction prefetch - * e.g. a series of nops: asm volatile (".rep 8; nop; .endr"); + * e.g. a series of nops: asm volatile (".rep 8; nop; .endr"); */ #include -- cgit v1.2.3 From b00e8443c3eece823052d06ae1c7cb797ab0ddf5 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 7 Nov 2005 14:35:14 +0100 Subject: [ALSA] version 1.0.10rc3 --- include/sound/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/sound/version.h b/include/sound/version.h index ee32af20dba..d1bd3b72396 100644 --- a/include/sound/version.h +++ b/include/sound/version.h @@ -1,3 +1,3 @@ /* include/version.h. Generated by configure. */ -#define CONFIG_SND_VERSION "1.0.10rc1" -#define CONFIG_SND_DATE " (Mon Sep 12 08:13:09 2005 UTC)" +#define CONFIG_SND_VERSION "1.0.10rc3" +#define CONFIG_SND_DATE " (Mon Nov 07 13:30:21 2005 UTC)" -- cgit v1.2.3 From e4f0648fb400a05adb7c640ce8766a7011d472d3 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 11:15:37 +0000 Subject: [MTD] user-abi: Clean up trailing white spaces Signed-off-by: Thomas Gleixner --- include/mtd/inftl-user.h | 4 ++-- include/mtd/mtd-abi.h | 6 +++--- include/mtd/nftl-user.h | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/mtd/inftl-user.h b/include/mtd/inftl-user.h index bda4f2c8f72..9b1e2526b45 100644 --- a/include/mtd/inftl-user.h +++ b/include/mtd/inftl-user.h @@ -1,7 +1,7 @@ /* - * $Id: inftl-user.h,v 1.1 2004/05/05 15:17:00 dwmw2 Exp $ + * $Id: inftl-user.h,v 1.2 2005/11/07 11:14:56 gleixner Exp $ * - * Parts of INFTL headers shared with userspace + * Parts of INFTL headers shared with userspace * */ diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h index 16e74cafd0b..b5994ea56a5 100644 --- a/include/mtd/mtd-abi.h +++ b/include/mtd/mtd-abi.h @@ -1,7 +1,7 @@ /* - * $Id: mtd-abi.h,v 1.12 2005/08/06 04:40:43 nico Exp $ + * $Id: mtd-abi.h,v 1.13 2005/11/07 11:14:56 gleixner Exp $ * - * Portions of MTD ABI definition which are shared by kernel and user space + * Portions of MTD ABI definition which are shared by kernel and user space */ #ifndef __MTD_ABI_H__ @@ -81,7 +81,7 @@ struct mtd_info_user { }; struct region_info_user { - uint32_t offset; /* At which this region starts, + uint32_t offset; /* At which this region starts, * from the beginning of the MTD */ uint32_t erasesize; /* For this region */ uint32_t numblocks; /* Number of blocks in this region */ diff --git a/include/mtd/nftl-user.h b/include/mtd/nftl-user.h index 924ec0459e9..b2bca18e731 100644 --- a/include/mtd/nftl-user.h +++ b/include/mtd/nftl-user.h @@ -1,7 +1,7 @@ /* - * $Id: nftl-user.h,v 1.1 2004/05/05 14:44:57 dwmw2 Exp $ + * $Id: nftl-user.h,v 1.2 2005/11/07 11:14:56 gleixner Exp $ * - * Parts of NFTL headers shared with userspace + * Parts of NFTL headers shared with userspace * */ -- cgit v1.2.3 From 1f948b43f7b5cf721cf0d03f507843efc1a9bfad Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 11:15:37 +0000 Subject: [MTD] chips: Clean up trailing white spaces Signed-off-by: Thomas Gleixner --- drivers/mtd/chips/Kconfig | 22 ++-- drivers/mtd/chips/Makefile | 4 +- drivers/mtd/chips/amd_flash.c | 80 +++++++------- drivers/mtd/chips/cfi_cmdset_0001.c | 150 +++++++++++++------------- drivers/mtd/chips/cfi_cmdset_0002.c | 130 +++++++++++------------ drivers/mtd/chips/cfi_cmdset_0020.c | 172 +++++++++++++++--------------- drivers/mtd/chips/cfi_probe.c | 98 ++++++++--------- drivers/mtd/chips/cfi_util.c | 16 +-- drivers/mtd/chips/chipreg.c | 6 +- drivers/mtd/chips/fwh_lock.h | 6 +- drivers/mtd/chips/gen_probe.c | 32 +++--- drivers/mtd/chips/jedec.c | 206 ++++++++++++++++++------------------ drivers/mtd/chips/jedec_probe.c | 48 ++++----- drivers/mtd/chips/map_absent.c | 8 +- drivers/mtd/chips/sharp.c | 8 +- 15 files changed, 493 insertions(+), 493 deletions(-) diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig index df95d2158b1..eafa23f5cbd 100644 --- a/drivers/mtd/chips/Kconfig +++ b/drivers/mtd/chips/Kconfig @@ -1,5 +1,5 @@ # drivers/mtd/chips/Kconfig -# $Id: Kconfig,v 1.15 2005/06/06 23:04:35 tpoynor Exp $ +# $Id: Kconfig,v 1.18 2005/11/07 11:14:22 gleixner Exp $ menu "RAM/ROM/Flash chip drivers" depends on MTD!=n @@ -39,7 +39,7 @@ config MTD_CFI_ADV_OPTIONS If you need to specify a specific endianness for access to flash chips, or if you wish to reduce the size of the kernel by including support for only specific arrangements of flash chips, say 'Y'. This - option does not directly affect the code, but will enable other + option does not directly affect the code, but will enable other configuration options which allow you to do so. If unsure, say 'N'. @@ -56,7 +56,7 @@ config MTD_CFI_NOSWAP data bits when writing the 'magic' commands to the chips. Saying 'NO', which is the default when CONFIG_MTD_CFI_ADV_OPTIONS isn't enabled, means that the CPU will not do any swapping; the chips - are expected to be wired to the CPU in 'host-endian' form. + are expected to be wired to the CPU in 'host-endian' form. Specific arrangements are possible with the BIG_ENDIAN_BYTE and LITTLE_ENDIAN_BYTE, if the bytes are reversed. @@ -79,10 +79,10 @@ config MTD_CFI_GEOMETRY bool "Specific CFI Flash geometry selection" depends on MTD_CFI_ADV_OPTIONS help - This option does not affect the code directly, but will enable + This option does not affect the code directly, but will enable some other configuration options which would allow you to reduce - the size of the kernel by including support for only certain - arrangements of CFI chips. If unsure, say 'N' and all options + the size of the kernel by including support for only certain + arrangements of CFI chips. If unsure, say 'N' and all options which are supported by the current code will be enabled. config MTD_MAP_BANK_WIDTH_1 @@ -197,7 +197,7 @@ config MTD_CFI_AMDSTD help The Common Flash Interface defines a number of different command sets which a CFI-compliant chip may claim to implement. This code - provides support for one of those command sets, used on chips + provides support for one of those command sets, used on chips including the AMD Am29LV320. config MTD_CFI_AMDSTD_RETRY @@ -237,14 +237,14 @@ config MTD_RAM tristate "Support for RAM chips in bus mapping" depends on MTD help - This option enables basic support for RAM chips accessed through + This option enables basic support for RAM chips accessed through a bus mapping driver. config MTD_ROM tristate "Support for ROM chips in bus mapping" depends on MTD help - This option enables basic support for ROM chips accessed through + This option enables basic support for ROM chips accessed through a bus mapping driver. config MTD_ABSENT @@ -275,7 +275,7 @@ config MTD_AMDSTD depends on MTD && MTD_OBSOLETE_CHIPS help This option enables support for flash chips using AMD-compatible - commands, including some which are not CFI-compatible and hence + commands, including some which are not CFI-compatible and hence cannot be used with the CONFIG_MTD_CFI_AMDSTD option. It also works on AMD compatible chips that do conform to CFI. @@ -285,7 +285,7 @@ config MTD_SHARP depends on MTD && MTD_OBSOLETE_CHIPS help This option enables support for flash chips using Sharp-compatible - commands, including some which are not CFI-compatible and hence + commands, including some which are not CFI-compatible and hence cannot be used with the CONFIG_MTD_CFI_INTELxxx options. config MTD_JEDEC diff --git a/drivers/mtd/chips/Makefile b/drivers/mtd/chips/Makefile index 6830489828c..8afe3092c4e 100644 --- a/drivers/mtd/chips/Makefile +++ b/drivers/mtd/chips/Makefile @@ -1,7 +1,7 @@ # # linux/drivers/chips/Makefile # -# $Id: Makefile.common,v 1.4 2004/07/12 16:07:30 dwmw2 Exp $ +# $Id: Makefile.common,v 1.5 2005/11/07 11:14:22 gleixner Exp $ # *** BIG UGLY NOTE *** # @@ -11,7 +11,7 @@ # the CFI command set drivers are linked before gen_probe.o obj-$(CONFIG_MTD) += chipreg.o -obj-$(CONFIG_MTD_AMDSTD) += amd_flash.o +obj-$(CONFIG_MTD_AMDSTD) += amd_flash.o obj-$(CONFIG_MTD_CFI) += cfi_probe.o obj-$(CONFIG_MTD_CFI_UTIL) += cfi_util.o obj-$(CONFIG_MTD_CFI_STAA) += cfi_cmdset_0020.o diff --git a/drivers/mtd/chips/amd_flash.c b/drivers/mtd/chips/amd_flash.c index 2dafeba3f3d..fdb91b6f1d9 100644 --- a/drivers/mtd/chips/amd_flash.c +++ b/drivers/mtd/chips/amd_flash.c @@ -3,7 +3,7 @@ * * Author: Jonas Holmberg * - * $Id: amd_flash.c,v 1.27 2005/02/04 07:43:09 jonashg Exp $ + * $Id: amd_flash.c,v 1.28 2005/11/07 11:14:22 gleixner Exp $ * * Copyright (c) 2001 Axis Communications AB * @@ -93,9 +93,9 @@ #define D6_MASK 0x40 struct amd_flash_private { - int device_type; - int interleave; - int numchips; + int device_type; + int interleave; + int numchips; unsigned long chipshift; // const char *im_name; struct flchip chips[0]; @@ -253,7 +253,7 @@ static int amd_flash_do_unlock(struct mtd_info *mtd, loff_t ofs, size_t len, int i; int retval = 0; int lock_status; - + map = mtd->priv; /* Pass the whole chip through sector by sector and check for each @@ -273,7 +273,7 @@ static int amd_flash_do_unlock(struct mtd_info *mtd, loff_t ofs, size_t len, unlock_sector(map, eraseoffset, is_unlock); lock_status = is_sector_locked(map, eraseoffset); - + if (is_unlock && lock_status) { printk("Cannot unlock sector at address %x length %xx\n", eraseoffset, merip->erasesize); @@ -305,7 +305,7 @@ static int amd_flash_lock(struct mtd_info *mtd, loff_t ofs, size_t len) /* * Reads JEDEC manufacturer ID and device ID and returns the index of the first * matching table entry (-1 if not found or alias for already found chip). - */ + */ static int probe_new_chip(struct mtd_info *mtd, __u32 base, struct flchip *chips, struct amd_flash_private *private, @@ -636,7 +636,7 @@ static struct mtd_info *amd_flash_probe(struct map_info *map) { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 }, { .offset = 0x1F0000, .erasesize = 0x02000, .numblocks = 8 } } - } + } }; struct mtd_info *mtd; @@ -701,7 +701,7 @@ static struct mtd_info *amd_flash_probe(struct map_info *map) mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) * mtd->numeraseregions, GFP_KERNEL); - if (!mtd->eraseregions) { + if (!mtd->eraseregions) { printk(KERN_WARNING "%s: Failed to allocate " "memory for MTD erase region info\n", map->name); kfree(mtd); @@ -739,12 +739,12 @@ static struct mtd_info *amd_flash_probe(struct map_info *map) mtd->type = MTD_NORFLASH; mtd->flags = MTD_CAP_NORFLASH; mtd->name = map->name; - mtd->erase = amd_flash_erase; - mtd->read = amd_flash_read; - mtd->write = amd_flash_write; - mtd->sync = amd_flash_sync; - mtd->suspend = amd_flash_suspend; - mtd->resume = amd_flash_resume; + mtd->erase = amd_flash_erase; + mtd->read = amd_flash_read; + mtd->write = amd_flash_write; + mtd->sync = amd_flash_sync; + mtd->suspend = amd_flash_suspend; + mtd->resume = amd_flash_resume; mtd->lock = amd_flash_lock; mtd->unlock = amd_flash_unlock; @@ -789,7 +789,7 @@ retry: map->name, chip->state); set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&chip->wq, &wait); - + spin_unlock_bh(chip->mutex); schedule(); @@ -802,7 +802,7 @@ retry: timeo = jiffies + HZ; goto retry; - } + } adr += chip->start; @@ -889,7 +889,7 @@ retry: map->name, chip->state); set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&chip->wq, &wait); - + spin_unlock_bh(chip->mutex); schedule(); @@ -901,7 +901,7 @@ retry: timeo = jiffies + HZ; goto retry; - } + } chip->state = FL_WRITING; @@ -911,7 +911,7 @@ retry: wide_write(map, datum, adr); times_left = 500000; - while (times_left-- && flash_is_busy(map, adr, private->interleave)) { + while (times_left-- && flash_is_busy(map, adr, private->interleave)) { if (need_resched()) { spin_unlock_bh(chip->mutex); schedule(); @@ -989,7 +989,7 @@ static int amd_flash_write(struct mtd_info *mtd, loff_t to , size_t len, if (ret) { return ret; } - + ofs += n; buf += n; (*retlen) += n; @@ -1002,7 +1002,7 @@ static int amd_flash_write(struct mtd_info *mtd, loff_t to , size_t len, } } } - + /* We are now aligned, write as much as possible. */ while(len >= map->buswidth) { __u32 datum; @@ -1063,7 +1063,7 @@ static int amd_flash_write(struct mtd_info *mtd, loff_t to , size_t len, if (ret) { return ret; } - + (*retlen) += n; } @@ -1085,7 +1085,7 @@ retry: if (chip->state != FL_READY){ set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&chip->wq, &wait); - + spin_unlock_bh(chip->mutex); schedule(); @@ -1098,7 +1098,7 @@ retry: timeo = jiffies + HZ; goto retry; - } + } chip->state = FL_ERASING; @@ -1106,30 +1106,30 @@ retry: ENABLE_VPP(map); send_cmd(map, chip->start, CMD_SECTOR_ERASE_UNLOCK_DATA); send_cmd_to_addr(map, chip->start, CMD_SECTOR_ERASE_UNLOCK_DATA_2, adr); - + timeo = jiffies + (HZ * 20); spin_unlock_bh(chip->mutex); msleep(1000); spin_lock_bh(chip->mutex); - + while (flash_is_busy(map, adr, private->interleave)) { if (chip->state != FL_ERASING) { /* Someone's suspended the erase. Sleep */ set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&chip->wq, &wait); - + spin_unlock_bh(chip->mutex); printk(KERN_INFO "%s: erase suspended. Sleeping\n", map->name); schedule(); remove_wait_queue(&chip->wq, &wait); - + if (signal_pending(current)) { return -EINTR; } - + timeo = jiffies + (HZ*2); /* FIXME */ spin_lock_bh(chip->mutex); continue; @@ -1145,7 +1145,7 @@ retry: return -EIO; } - + /* Latency issues. Drop the lock, wait a while and retry */ spin_unlock_bh(chip->mutex); @@ -1153,7 +1153,7 @@ retry: schedule(); else udelay(1); - + spin_lock_bh(chip->mutex); } @@ -1180,7 +1180,7 @@ retry: return -EIO; } } - + DISABLE_VPP(map); chip->state = FL_READY; wake_up(&chip->wq); @@ -1246,7 +1246,7 @@ static int amd_flash_erase(struct mtd_info *mtd, struct erase_info *instr) * with the erase region at that address. */ - while ((i < mtd->numeraseregions) && + while ((i < mtd->numeraseregions) && ((instr->addr + instr->len) >= regions[i].offset)) { i++; } @@ -1293,10 +1293,10 @@ static int amd_flash_erase(struct mtd_info *mtd, struct erase_info *instr) } } } - + instr->state = MTD_ERASE_DONE; mtd_erase_callback(instr); - + return 0; } @@ -1324,7 +1324,7 @@ static void amd_flash_sync(struct mtd_info *mtd) case FL_JEDEC_QUERY: chip->oldstate = chip->state; chip->state = FL_SYNCING; - /* No need to wake_up() on this state change - + /* No need to wake_up() on this state change - * as the whole point is that nobody can do anything * with the chip now anyway. */ @@ -1335,13 +1335,13 @@ static void amd_flash_sync(struct mtd_info *mtd) default: /* Not an idle state */ add_wait_queue(&chip->wq, &wait); - + spin_unlock_bh(chip->mutex); schedule(); remove_wait_queue(&chip->wq, &wait); - + goto retry; } } @@ -1351,7 +1351,7 @@ static void amd_flash_sync(struct mtd_info *mtd) chip = &private->chips[i]; spin_lock_bh(chip->mutex); - + if (chip->state == FL_SYNCING) { chip->state = chip->oldstate; wake_up(&chip->wq); diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 61a2ec9901e..e3a5c5d331b 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -4,9 +4,9 @@ * * (C) 2000 Red Hat. GPL'd * - * $Id: cfi_cmdset_0001.c,v 1.184 2005/10/25 20:28:40 nico Exp $ + * $Id: cfi_cmdset_0001.c,v 1.185 2005/11/07 11:14:22 gleixner Exp $ + * * - * * 10/10/2000 Nicolas Pitre * - completely revamped method functions so they are aware and * independent of the flash geometry (buswidth, interleave, etc.) @@ -120,17 +120,17 @@ static void cfi_tell_features(struct cfi_pri_intelext *extp) printk(" - Simultaneous operations: %s\n", extp->FeatureSupport&512?"supported":"unsupported"); printk(" - Extended Flash Array: %s\n", extp->FeatureSupport&1024?"supported":"unsupported"); for (i=11; i<32; i++) { - if (extp->FeatureSupport & (1<FeatureSupport & (1<SuspendCmdSupport); printk(" - Program after Erase Suspend: %s\n", extp->SuspendCmdSupport&1?"supported":"unsupported"); for (i=1; i<8; i++) { if (extp->SuspendCmdSupport & (1<BlkStatusRegMask); printk(" - Lock Bit Active: %s\n", extp->BlkStatusRegMask&1?"yes":"no"); printk(" - Lock-Down Bit Active: %s\n", extp->BlkStatusRegMask&2?"yes":"no"); @@ -145,16 +145,16 @@ static void cfi_tell_features(struct cfi_pri_intelext *extp) printk(" - Unknown Bit %X Active: yes\n",i); } - printk(" Vcc Logic Supply Optimum Program/Erase Voltage: %d.%d V\n", + printk(" Vcc Logic Supply Optimum Program/Erase Voltage: %d.%d V\n", extp->VccOptimal >> 4, extp->VccOptimal & 0xf); if (extp->VppOptimal) - printk(" Vpp Programming Supply Optimum Program/Erase Voltage: %d.%d V\n", + printk(" Vpp Programming Supply Optimum Program/Erase Voltage: %d.%d V\n", extp->VppOptimal >> 4, extp->VppOptimal & 0xf); } #endif #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE -/* Some Intel Strata Flash prior to FPO revision C has bugs in this area */ +/* Some Intel Strata Flash prior to FPO revision C has bugs in this area */ static void fixup_intel_strataflash(struct mtd_info *mtd, void* param) { struct map_info *map = mtd->priv; @@ -185,7 +185,7 @@ static void fixup_st_m28w320ct(struct mtd_info *mtd, void* param) { struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; - + cfi->cfiq->BufWriteTimeoutTyp = 0; /* Not supported */ cfi->cfiq->BufWriteTimeoutMax = 0; /* Not supported */ } @@ -194,7 +194,7 @@ static void fixup_st_m28w320cb(struct mtd_info *mtd, void* param) { struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; - + /* Note this is done after the region info is endian swapped */ cfi->cfiq->EraseRegionInfo[1] = (cfi->cfiq->EraseRegionInfo[1] & 0xffff0000) | 0x3e; @@ -222,7 +222,7 @@ static void fixup_use_write_buffers(struct mtd_info *mtd, void *param) static struct cfi_fixup cfi_fixup_table[] = { #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE - { CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL }, + { CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL }, #endif #ifdef CMDSET0001_DISABLE_WRITE_SUSPEND { CFI_MFR_ANY, CFI_ID_ANY, fixup_no_write_suspend, NULL }, @@ -327,7 +327,7 @@ read_pri_intelext(struct map_info *map, __u16 adr) goto again; } } - + return extp; } @@ -368,7 +368,7 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) mtd->reboot_notifier.notifier_call = cfi_intelext_reboot; if (cfi->cfi_mode == CFI_MODE_CFI) { - /* + /* * It's a real CFI chip, not one for which the probe * routine faked a CFI structure. So we read the feature * table from it. @@ -383,14 +383,14 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) } /* Install our own private info structure */ - cfi->cmdset_priv = extp; + cfi->cmdset_priv = extp; cfi_fixup(mtd, cfi_fixup_table); #ifdef DEBUG_CFI_FEATURES /* Tell the user about it in lots of lovely detail */ cfi_tell_features(extp); -#endif +#endif if(extp->SuspendCmdSupport & 1) { printk(KERN_NOTICE "cfi_cmdset_0001: Erase suspend on write enabled\n"); @@ -408,10 +408,10 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) cfi->chips[i].buffer_write_time = 1<cfiq->BufWriteTimeoutTyp; cfi->chips[i].erase_time = 1<cfiq->BlockEraseTimeoutTyp; cfi->chips[i].ref_point_counter = 0; - } + } map->fldrv = &cfi_intelext_chipdrv; - + return cfi_intelext_setup(mtd); } @@ -428,13 +428,13 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd) mtd->size = devsize * cfi->numchips; mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips; - mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) + mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) * mtd->numeraseregions, GFP_KERNEL); - if (!mtd->eraseregions) { + if (!mtd->eraseregions) { printk(KERN_ERR "Failed to allocate memory for MTD erase region info\n"); goto setup_err; } - + for (i=0; icfiq->NumEraseRegions; i++) { unsigned long ernum, ersize; ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave; @@ -701,7 +701,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr break; if (time_after(jiffies, timeo)) { - printk(KERN_ERR "%s: Waiting for chip to be ready timed out. Status %lx\n", + printk(KERN_ERR "%s: Waiting for chip to be ready timed out. Status %lx\n", map->name, status.x[0]); return -EIO; } @@ -711,7 +711,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr /* Someone else might have been playing with it. */ goto retry; } - + case FL_READY: case FL_CFI_QUERY: case FL_JEDEC_QUERY: @@ -830,14 +830,14 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad switch(chip->oldstate) { case FL_ERASING: chip->state = chip->oldstate; - /* What if one interleaved chip has finished and the + /* What if one interleaved chip has finished and the other hasn't? The old code would leave the finished - one in READY mode. That's bad, and caused -EROFS + one in READY mode. That's bad, and caused -EROFS errors to be returned from do_erase_oneblock because that's the only bit it checked for at the time. - As the state machine appears to explicitly allow + As the state machine appears to explicitly allow sending the 0x70 (Read Status) command to an erasing - chip and expecting it to be ignored, that's what we + chip and expecting it to be ignored, that's what we do. */ map_write(map, CMD(0xd0), adr); map_write(map, CMD(0x70), adr); @@ -1073,8 +1073,8 @@ static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t a adr += chip->start; - /* Ensure cmd read/writes are aligned. */ - cmd_addr = adr & ~(map_bankwidth(map)-1); + /* Ensure cmd read/writes are aligned. */ + cmd_addr = adr & ~(map_bankwidth(map)-1); spin_lock(chip->mutex); @@ -1102,7 +1102,7 @@ static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, si if (!map->virt || (from + len > mtd->size)) return -EINVAL; - + *mtdbuf = (void *)map->virt + from; *retlen = 0; @@ -1129,7 +1129,7 @@ static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, si *retlen += thislen; len -= thislen; - + ofs = 0; chipnum++; } @@ -1187,8 +1187,8 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof adr += chip->start; - /* Ensure cmd read/writes are aligned. */ - cmd_addr = adr & ~(map_bankwidth(map)-1); + /* Ensure cmd read/writes are aligned. */ + cmd_addr = adr & ~(map_bankwidth(map)-1); spin_lock(chip->mutex); ret = get_chip(map, chip, cmd_addr, FL_READY); @@ -1243,7 +1243,7 @@ static int cfi_intelext_read (struct mtd_info *mtd, loff_t from, size_t len, siz *retlen += thislen; len -= thislen; buf += thislen; - + ofs = 0; chipnum++; } @@ -1311,7 +1311,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, status = map_read(map, adr); if (map_word_andequal(map, status, status_OK, status_OK)) break; - + /* OK Still waiting */ if (time_after(jiffies, timeo)) { map_write(map, CMD(0x70), adr); @@ -1331,7 +1331,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, if (!chip->word_write_time) chip->word_write_time = 1; } - if (z > 1) + if (z > 1) chip->word_write_time++; /* Done and happy. */ @@ -1394,7 +1394,7 @@ static int cfi_intelext_write_words (struct mtd_info *mtd, loff_t to , size_t le ret = do_write_oneword(map, &cfi->chips[chipnum], bus_ofs, datum, FL_WRITING); - if (ret) + if (ret) return ret; len -= n; @@ -1403,13 +1403,13 @@ static int cfi_intelext_write_words (struct mtd_info *mtd, loff_t to , size_t le (*retlen) += n; if (ofs >> cfi->chipshift) { - chipnum ++; + chipnum ++; ofs = 0; if (chipnum == cfi->numchips) return 0; } } - + while(len >= map_bankwidth(map)) { map_word datum = map_word_load(map, buf); @@ -1424,7 +1424,7 @@ static int cfi_intelext_write_words (struct mtd_info *mtd, loff_t to , size_t le len -= map_bankwidth(map); if (ofs >> cfi->chipshift) { - chipnum ++; + chipnum ++; ofs = 0; if (chipnum == cfi->numchips) return 0; @@ -1439,9 +1439,9 @@ static int cfi_intelext_write_words (struct mtd_info *mtd, loff_t to , size_t le ret = do_write_oneword(map, &cfi->chips[chipnum], ofs, datum, FL_WRITING); - if (ret) + if (ret) return ret; - + (*retlen) += len; } @@ -1449,7 +1449,7 @@ static int cfi_intelext_write_words (struct mtd_info *mtd, loff_t to , size_t le } -static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, +static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, unsigned long adr, const struct kvec **pvec, unsigned long *pvec_seek, int len) { @@ -1480,7 +1480,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, xip_disable(map, chip, cmd_adr); /* §4.8 of the 28FxxxJ3A datasheet says "Any time SR.4 and/or SR.5 is set - [...], the device will not accept any more Write to Buffer commands". + [...], the device will not accept any more Write to Buffer commands". So we must check here and reset those bits if they're set. Otherwise we're just pissing in the wind */ if (chip->state != FL_STATUS) @@ -1549,9 +1549,9 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, if (!word_gap && len < map_bankwidth(map)) datum = map_word_ff(map); - + datum = map_word_load_partial(map, datum, - vec->iov_base + vec_seek, + vec->iov_base + vec_seek, word_gap, n); len -= n; @@ -1575,7 +1575,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, map_write(map, CMD(0xd0), cmd_adr); chip->state = FL_WRITING; - INVALIDATE_CACHE_UDELAY(map, chip, + INVALIDATE_CACHE_UDELAY(map, chip, cmd_adr, len, chip->buffer_write_time); @@ -1608,7 +1608,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, ret = -EIO; goto out; } - + /* Latency issues. Drop the lock, wait a while and retry */ z++; UDELAY(map, chip, cmd_adr, 1); @@ -1618,7 +1618,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, if (!chip->buffer_write_time) chip->buffer_write_time = 1; } - if (z > 1) + if (z > 1) chip->buffer_write_time++; /* Done and happy. */ @@ -1680,7 +1680,7 @@ static int cfi_intelext_writev (struct mtd_info *mtd, const struct kvec *vecs, if (size > len) size = len; - ret = do_write_buffer(map, &cfi->chips[chipnum], + ret = do_write_buffer(map, &cfi->chips[chipnum], ofs, &vecs, &vec_seek, size); if (ret) return ret; @@ -1690,7 +1690,7 @@ static int cfi_intelext_writev (struct mtd_info *mtd, const struct kvec *vecs, len -= size; if (ofs >> cfi->chipshift) { - chipnum ++; + chipnum ++; ofs = 0; if (chipnum == cfi->numchips) return 0; @@ -1776,7 +1776,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, status = map_read(map, adr); if (map_word_andequal(map, status, status_OK, status_OK)) break; - + /* OK Still waiting */ if (time_after(jiffies, timeo)) { map_write(map, CMD(0x70), adr); @@ -1786,7 +1786,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, ret = -EIO; goto out; } - + /* Latency issues. Drop the lock, wait a while and retry */ UDELAY(map, chip, adr, 1000000/HZ); } @@ -1849,7 +1849,7 @@ int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) instr->state = MTD_ERASE_DONE; mtd_erase_callback(instr); - + return 0; } @@ -1870,7 +1870,7 @@ static void cfi_intelext_sync (struct mtd_info *mtd) if (!ret) { chip->oldstate = chip->state; chip->state = FL_SYNCING; - /* No need to wake_up() on this state change - + /* No need to wake_up() on this state change - * as the whole point is that nobody can do anything * with the chip now anyway. */ @@ -1884,7 +1884,7 @@ static void cfi_intelext_sync (struct mtd_info *mtd) chip = &cfi->chips[i]; spin_lock(chip->mutex); - + if (chip->state == FL_SYNCING) { chip->state = chip->oldstate; chip->oldstate = FL_READY; @@ -1941,7 +1941,7 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip ENABLE_VPP(map); xip_disable(map, chip, adr); - + map_write(map, CMD(0x60), adr); if (thunk == DO_XXLOCK_ONEBLOCK_LOCK) { map_write(map, CMD(0x01), adr); @@ -1969,7 +1969,7 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip status = map_read(map, adr); if (map_word_andequal(map, status, status_OK, status_OK)) break; - + /* OK Still waiting */ if (time_after(jiffies, timeo)) { map_write(map, CMD(0x70), adr); @@ -1980,11 +1980,11 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip spin_unlock(chip->mutex); return -EIO; } - + /* Latency issues. Drop the lock, wait a while and retry */ UDELAY(map, chip, adr, 1); } - + /* Done and happy. */ chip->state = FL_STATUS; xip_enable(map, chip, adr); @@ -2004,9 +2004,9 @@ static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len) ofs, len, 0); #endif - ret = cfi_varsize_frob(mtd, do_xxlock_oneblock, + ret = cfi_varsize_frob(mtd, do_xxlock_oneblock, ofs, len, DO_XXLOCK_ONEBLOCK_LOCK); - + #ifdef DEBUG_LOCK_BITS printk(KERN_DEBUG "%s: lock status after, ret=%d\n", __FUNCTION__, ret); @@ -2030,20 +2030,20 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) ret = cfi_varsize_frob(mtd, do_xxlock_oneblock, ofs, len, DO_XXLOCK_ONEBLOCK_UNLOCK); - + #ifdef DEBUG_LOCK_BITS printk(KERN_DEBUG "%s: lock status after, ret=%d\n", __FUNCTION__, ret); - cfi_varsize_frob(mtd, do_printlockstatus_oneblock, + cfi_varsize_frob(mtd, do_printlockstatus_oneblock, ofs, len, 0); #endif - + return ret; } #ifdef CONFIG_MTD_OTP -typedef int (*otp_op_t)(struct map_info *map, struct flchip *chip, +typedef int (*otp_op_t)(struct map_info *map, struct flchip *chip, u_long data_offset, u_char *buf, u_int size, u_long prot_offset, u_int groupno, u_int groupsize); @@ -2094,7 +2094,7 @@ do_otp_write(struct map_info *map, struct flchip *chip, u_long offset, datum = map_word_load_partial(map, datum, buf, gap, n); ret = do_write_oneword(map, chip, bus_ofs, datum, FL_OTP_WRITE); - if (ret) + if (ret) return ret; offset += n; @@ -2287,7 +2287,7 @@ static int cfi_intelext_lock_user_prot_reg(struct mtd_info *mtd, NULL, do_otp_lock, 1); } -static int cfi_intelext_get_fact_prot_info(struct mtd_info *mtd, +static int cfi_intelext_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf, size_t len) { size_t retlen; @@ -2330,7 +2330,7 @@ static int cfi_intelext_suspend(struct mtd_info *mtd) if (chip->oldstate == FL_READY) { chip->oldstate = chip->state; chip->state = FL_PM_SUSPENDED; - /* No need to wake_up() on this state change - + /* No need to wake_up() on this state change - * as the whole point is that nobody can do anything * with the chip now anyway. */ @@ -2358,9 +2358,9 @@ static int cfi_intelext_suspend(struct mtd_info *mtd) if (ret) { for (i--; i >=0; i--) { chip = &cfi->chips[i]; - + spin_lock(chip->mutex); - + if (chip->state == FL_PM_SUSPENDED) { /* No need to force it into a known state here, because we're returning failure, and it didn't @@ -2371,8 +2371,8 @@ static int cfi_intelext_suspend(struct mtd_info *mtd) } spin_unlock(chip->mutex); } - } - + } + return ret; } @@ -2384,11 +2384,11 @@ static void cfi_intelext_resume(struct mtd_info *mtd) struct flchip *chip; for (i=0; inumchips; i++) { - + chip = &cfi->chips[i]; spin_lock(chip->mutex); - + /* Go to known state. Chip may have been power cycled */ if (chip->state == FL_PM_SUSPENDED) { map_write(map, CMD(0xFF), cfi->chips[i].start); @@ -2410,7 +2410,7 @@ static int cfi_intelext_reset(struct mtd_info *mtd) struct flchip *chip = &cfi->chips[i]; /* force the completion of any ongoing operation - and switch to array mode so any bootloader in + and switch to array mode so any bootloader in flash is accessible for soft reboot. */ spin_lock(chip->mutex); ret = get_chip(map, chip, chip->start, FL_SYNCING); diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 50dd7d2f096..88c5f5a34cb 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -10,14 +10,14 @@ * * 4_by_16 work by Carolyn J. Smith * - * XIP support hooks by Vitaly Wool (based on code for Intel flash + * XIP support hooks by Vitaly Wool (based on code for Intel flash * by Nicolas Pitre) - * + * * Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com * * This code is GPL * - * $Id: cfi_cmdset_0002.c,v 1.121 2005/11/07 09:00:01 gleixner Exp $ + * $Id: cfi_cmdset_0002.c,v 1.122 2005/11/07 11:14:22 gleixner Exp $ * */ @@ -93,7 +93,7 @@ static void cfi_tell_features(struct cfi_pri_amdstd *extp) }; printk(" Silicon revision: %d\n", extp->SiliconRevision >> 1); - printk(" Address sensitive unlock: %s\n", + printk(" Address sensitive unlock: %s\n", (extp->SiliconRevision & 1) ? "Not required" : "Required"); if (extp->EraseSuspend < ARRAY_SIZE(erase_suspend)) @@ -118,9 +118,9 @@ static void cfi_tell_features(struct cfi_pri_amdstd *extp) else printk(" Page mode: %d word page\n", extp->PageMode << 2); - printk(" Vpp Supply Minimum Program/Erase Voltage: %d.%d V\n", + printk(" Vpp Supply Minimum Program/Erase Voltage: %d.%d V\n", extp->VppMin >> 4, extp->VppMin & 0xf); - printk(" Vpp Supply Maximum Program/Erase Voltage: %d.%d V\n", + printk(" Vpp Supply Maximum Program/Erase Voltage: %d.%d V\n", extp->VppMax >> 4, extp->VppMax & 0xf); if (extp->TopBottom < ARRAY_SIZE(top_bottom)) @@ -177,7 +177,7 @@ static void fixup_use_erase_chip(struct mtd_info *mtd, void *param) ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0)) { mtd->erase = cfi_amdstd_erase_chip; } - + } static struct cfi_fixup cfi_fixup_table[] = { @@ -239,7 +239,7 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) if (cfi->cfi_mode==CFI_MODE_CFI){ unsigned char bootloc; - /* + /* * It's a real CFI chip, not one for which the probe * routine faked a CFI structure. So we read the feature * table from it. @@ -264,7 +264,7 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) } /* Install our own private info structure */ - cfi->cmdset_priv = extp; + cfi->cmdset_priv = extp; /* Apply cfi device specific fixups */ cfi_fixup(mtd, cfi_fixup_table); @@ -272,7 +272,7 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) #ifdef DEBUG_CFI_FEATURES /* Tell the user about it in lots of lovely detail */ cfi_tell_features(extp); -#endif +#endif bootloc = extp->TopBottom; if ((bootloc != 2) && (bootloc != 3)) { @@ -283,11 +283,11 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) if (bootloc == 3 && cfi->cfiq->NumEraseRegions > 1) { printk(KERN_WARNING "%s: Swapping erase regions for broken CFI table.\n", map->name); - + for (i=0; icfiq->NumEraseRegions / 2; i++) { int j = (cfi->cfiq->NumEraseRegions-1)-i; __u32 swap; - + swap = cfi->cfiq->EraseRegionInfo[i]; cfi->cfiq->EraseRegionInfo[i] = cfi->cfiq->EraseRegionInfo[j]; cfi->cfiq->EraseRegionInfo[j] = swap; @@ -298,11 +298,11 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) cfi->addr_unlock2 = 0x2aa; /* Modify the unlock address if we are in compatibility mode */ if ( /* x16 in x8 mode */ - ((cfi->device_type == CFI_DEVICETYPE_X8) && + ((cfi->device_type == CFI_DEVICETYPE_X8) && (cfi->cfiq->InterfaceDesc == 2)) || /* x32 in x16 mode */ ((cfi->device_type == CFI_DEVICETYPE_X16) && - (cfi->cfiq->InterfaceDesc == 4))) + (cfi->cfiq->InterfaceDesc == 4))) { cfi->addr_unlock1 = 0xaaa; cfi->addr_unlock2 = 0x555; @@ -320,10 +320,10 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) cfi->chips[i].word_write_time = 1<cfiq->WordWriteTimeoutTyp; cfi->chips[i].buffer_write_time = 1<cfiq->BufWriteTimeoutTyp; cfi->chips[i].erase_time = 1<cfiq->BlockEraseTimeoutTyp; - } - + } + map->fldrv = &cfi_amdstd_chipdrv; - + return cfi_amdstd_setup(mtd); } @@ -336,24 +336,24 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) unsigned long offset = 0; int i,j; - printk(KERN_NOTICE "number of %s chips: %d\n", + printk(KERN_NOTICE "number of %s chips: %d\n", (cfi->cfi_mode == CFI_MODE_CFI)?"CFI":"JEDEC",cfi->numchips); - /* Select the correct geometry setup */ + /* Select the correct geometry setup */ mtd->size = devsize * cfi->numchips; mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips; mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) * mtd->numeraseregions, GFP_KERNEL); - if (!mtd->eraseregions) { + if (!mtd->eraseregions) { printk(KERN_WARNING "Failed to allocate memory for MTD erase region info\n"); goto setup_err; } - + for (i=0; icfiq->NumEraseRegions; i++) { unsigned long ernum, ersize; ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave; ernum = (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1; - + if (mtd->erasesize < ersize) { mtd->erasesize = ersize; } @@ -440,7 +440,7 @@ static int __xipram chip_good(struct map_info *map, unsigned long addr, map_word oldd = map_read(map, addr); curd = map_read(map, addr); - return map_word_equal(map, oldd, curd) && + return map_word_equal(map, oldd, curd) && map_word_equal(map, curd, expected); } @@ -472,7 +472,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr /* Someone else might have been playing with it. */ goto retry; } - + case FL_READY: case FL_CFI_QUERY: case FL_JEDEC_QUERY: @@ -515,7 +515,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__); return -EIO; } - + spin_unlock(chip->mutex); cfi_udelay(1); spin_lock(chip->mutex); @@ -618,7 +618,7 @@ static void __xipram xip_enable(struct map_info *map, struct flchip *chip, * When a delay is required for the flash operation to complete, the * xip_udelay() function is polling for both the given timeout and pending * (but still masked) hardware interrupts. Whenever there is an interrupt - * pending then the flash erase operation is suspended, array mode restored + * pending then the flash erase operation is suspended, array mode restored * and interrupts unmasked. Task scheduling might also happen at that * point. The CPU eventually returns from the interrupt or the call to * schedule() and the suspended flash operation is resumed for the remaining @@ -642,9 +642,9 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip, ((chip->state == FL_ERASING && (extp->EraseSuspend & 2))) && (cfi_interleave_is_1(cfi) || chip->oldstate == FL_READY)) { /* - * Let's suspend the erase operation when supported. - * Note that we currently don't try to suspend - * interleaved chips if there is already another + * Let's suspend the erase operation when supported. + * Note that we currently don't try to suspend + * interleaved chips if there is already another * operation suspended (imagine what happens * when one chip was already done with the current * operation while another chip suspended it, then @@ -780,8 +780,8 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof adr += chip->start; - /* Ensure cmd read/writes are aligned. */ - cmd_addr = adr & ~(map_bankwidth(map)-1); + /* Ensure cmd read/writes are aligned. */ + cmd_addr = adr & ~(map_bankwidth(map)-1); spin_lock(chip->mutex); ret = get_chip(map, chip, cmd_addr, FL_READY); @@ -861,7 +861,7 @@ static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chi #endif set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&chip->wq, &wait); - + spin_unlock(chip->mutex); schedule(); @@ -873,7 +873,7 @@ static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chi timeo = jiffies + HZ; goto retry; - } + } adr += chip->start; @@ -882,14 +882,14 @@ static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chi cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x88, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); - + map_copy_from(map, buf, adr, len); cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x90, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x00, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); - + wake_up(&chip->wq); spin_unlock(chip->mutex); @@ -998,7 +998,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, chip->word_write_time); /* See comment above for timeout value. */ - timeo = jiffies + uWriteTimeout; + timeo = jiffies + uWriteTimeout; for (;;) { if (chip->state != FL_WRITING) { /* Someone's suspended the write. Sleep */ @@ -1033,7 +1033,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, map_write( map, CMD(0xF0), chip->start ); /* FIXME - should have reset delay before continuing */ - if (++retry_cnt <= MAX_WORD_RETRIES) + if (++retry_cnt <= MAX_WORD_RETRIES) goto retry; ret = -EIO; @@ -1101,27 +1101,27 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, /* Number of bytes to copy from buffer */ n = min_t(int, len, map_bankwidth(map)-i); - + tmp_buf = map_word_load_partial(map, tmp_buf, buf, i, n); - ret = do_write_oneword(map, &cfi->chips[chipnum], + ret = do_write_oneword(map, &cfi->chips[chipnum], bus_ofs, tmp_buf); - if (ret) + if (ret) return ret; - + ofs += n; buf += n; (*retlen) += n; len -= n; if (ofs >> cfi->chipshift) { - chipnum ++; + chipnum ++; ofs = 0; if (chipnum == cfi->numchips) return 0; } } - + /* We are now aligned, write as much as possible */ while(len >= map_bankwidth(map)) { map_word datum; @@ -1139,7 +1139,7 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, len -= map_bankwidth(map); if (ofs >> cfi->chipshift) { - chipnum ++; + chipnum ++; ofs = 0; if (chipnum == cfi->numchips) return 0; @@ -1177,12 +1177,12 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, spin_unlock(cfi->chips[chipnum].mutex); tmp_buf = map_word_load_partial(map, tmp_buf, buf, 0, len); - - ret = do_write_oneword(map, &cfi->chips[chipnum], + + ret = do_write_oneword(map, &cfi->chips[chipnum], ofs, tmp_buf); - if (ret) + if (ret) return ret; - + (*retlen) += len; } @@ -1194,7 +1194,7 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, * FIXME: interleaved mode not tested, and probably not supported! */ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, - unsigned long adr, const u_char *buf, + unsigned long adr, const u_char *buf, int len) { struct cfi_private *cfi = map->fldrv_priv; @@ -1224,7 +1224,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, XIP_INVAL_CACHED_RANGE(map, adr, len); ENABLE_VPP(map); xip_disable(map, chip, cmd_adr); - + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); //cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); @@ -1258,8 +1258,8 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, adr, map_bankwidth(map), chip->word_write_time); - timeo = jiffies + uWriteTimeout; - + timeo = jiffies + uWriteTimeout; + for (;;) { if (chip->state != FL_WRITING) { /* Someone's suspended the write. Sleep */ @@ -1353,7 +1353,7 @@ static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len, if (size % map_bankwidth(map)) size -= size % map_bankwidth(map); - ret = do_write_buffer(map, &cfi->chips[chipnum], + ret = do_write_buffer(map, &cfi->chips[chipnum], ofs, buf, size); if (ret) return ret; @@ -1364,7 +1364,7 @@ static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len, len -= size; if (ofs >> cfi->chipshift) { - chipnum ++; + chipnum ++; ofs = 0; if (chipnum == cfi->numchips) return 0; @@ -1581,7 +1581,7 @@ int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) instr->state = MTD_ERASE_DONE; mtd_erase_callback(instr); - + return 0; } @@ -1604,7 +1604,7 @@ static int cfi_amdstd_erase_chip(struct mtd_info *mtd, struct erase_info *instr) instr->state = MTD_ERASE_DONE; mtd_erase_callback(instr); - + return 0; } @@ -1631,7 +1631,7 @@ static void cfi_amdstd_sync (struct mtd_info *mtd) case FL_JEDEC_QUERY: chip->oldstate = chip->state; chip->state = FL_SYNCING; - /* No need to wake_up() on this state change - + /* No need to wake_up() on this state change - * as the whole point is that nobody can do anything * with the chip now anyway. */ @@ -1642,13 +1642,13 @@ static void cfi_amdstd_sync (struct mtd_info *mtd) default: /* Not an idle state */ add_wait_queue(&chip->wq, &wait); - + spin_unlock(chip->mutex); schedule(); remove_wait_queue(&chip->wq, &wait); - + goto retry; } } @@ -1659,7 +1659,7 @@ static void cfi_amdstd_sync (struct mtd_info *mtd) chip = &cfi->chips[i]; spin_lock(chip->mutex); - + if (chip->state == FL_SYNCING) { chip->state = chip->oldstate; wake_up(&chip->wq); @@ -1689,7 +1689,7 @@ static int cfi_amdstd_suspend(struct mtd_info *mtd) case FL_JEDEC_QUERY: chip->oldstate = chip->state; chip->state = FL_PM_SUSPENDED; - /* No need to wake_up() on this state change - + /* No need to wake_up() on this state change - * as the whole point is that nobody can do anything * with the chip now anyway. */ @@ -1710,7 +1710,7 @@ static int cfi_amdstd_suspend(struct mtd_info *mtd) chip = &cfi->chips[i]; spin_lock(chip->mutex); - + if (chip->state == FL_PM_SUSPENDED) { chip->state = chip->oldstate; wake_up(&chip->wq); @@ -1718,7 +1718,7 @@ static int cfi_amdstd_suspend(struct mtd_info *mtd) spin_unlock(chip->mutex); } } - + return ret; } @@ -1731,11 +1731,11 @@ static void cfi_amdstd_resume(struct mtd_info *mtd) struct flchip *chip; for (i=0; inumchips; i++) { - + chip = &cfi->chips[i]; spin_lock(chip->mutex); - + if (chip->state == FL_PM_SUSPENDED) { chip->state = FL_READY; map_write(map, CMD(0xF0), chip->start); diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index d22df2d9678..39e3c2d9441 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c @@ -4,7 +4,7 @@ * * (C) 2000 Red Hat. GPL'd * - * $Id: cfi_cmdset_0020.c,v 1.20 2005/07/20 21:01:14 tpoynor Exp $ + * $Id: cfi_cmdset_0020.c,v 1.22 2005/11/07 11:14:22 gleixner Exp $ * * 10/10/2000 Nicolas Pitre * - completely revamped method functions so they are aware and @@ -81,17 +81,17 @@ static void cfi_tell_features(struct cfi_pri_intelext *extp) printk(" - Page-mode read: %s\n", extp->FeatureSupport&128?"supported":"unsupported"); printk(" - Synchronous read: %s\n", extp->FeatureSupport&256?"supported":"unsupported"); for (i=9; i<32; i++) { - if (extp->FeatureSupport & (1<FeatureSupport & (1<SuspendCmdSupport); printk(" - Program after Erase Suspend: %s\n", extp->SuspendCmdSupport&1?"supported":"unsupported"); for (i=1; i<8; i++) { if (extp->SuspendCmdSupport & (1<BlkStatusRegMask); printk(" - Lock Bit Active: %s\n", extp->BlkStatusRegMask&1?"yes":"no"); printk(" - Valid Bit Active: %s\n", extp->BlkStatusRegMask&2?"yes":"no"); @@ -99,11 +99,11 @@ static void cfi_tell_features(struct cfi_pri_intelext *extp) if (extp->BlkStatusRegMask & (1<VccOptimal >> 8, extp->VccOptimal & 0xf); if (extp->VppOptimal) - printk(" Vpp Programming Supply Optimum Program/Erase Voltage: %d.%d V\n", + printk(" Vpp Programming Supply Optimum Program/Erase Voltage: %d.%d V\n", extp->VppOptimal >> 8, extp->VppOptimal & 0xf); } #endif @@ -121,7 +121,7 @@ struct mtd_info *cfi_cmdset_0020(struct map_info *map, int primary) int i; if (cfi->cfi_mode) { - /* + /* * It's a real CFI chip, not one for which the probe * routine faked a CFI structure. So we read the feature * table from it. @@ -145,21 +145,21 @@ struct mtd_info *cfi_cmdset_0020(struct map_info *map, int primary) /* Do some byteswapping if necessary */ extp->FeatureSupport = cfi32_to_cpu(extp->FeatureSupport); extp->BlkStatusRegMask = cfi32_to_cpu(extp->BlkStatusRegMask); - + #ifdef DEBUG_CFI_FEATURES /* Tell the user about it in lots of lovely detail */ cfi_tell_features(extp); -#endif +#endif /* Install our own private info structure */ cfi->cmdset_priv = extp; - } + } for (i=0; i< cfi->numchips; i++) { cfi->chips[i].word_write_time = 128; cfi->chips[i].buffer_write_time = 128; cfi->chips[i].erase_time = 1024; - } + } return cfi_staa_setup(map); } @@ -187,15 +187,15 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map) mtd->size = devsize * cfi->numchips; mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips; - mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) + mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) * mtd->numeraseregions, GFP_KERNEL); - if (!mtd->eraseregions) { + if (!mtd->eraseregions) { printk(KERN_ERR "Failed to allocate memory for MTD erase region info\n"); kfree(cfi->cmdset_priv); kfree(mtd); return NULL; } - + for (i=0; icfiq->NumEraseRegions; i++) { unsigned long ernum, ersize; ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave; @@ -228,7 +228,7 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map) mtd->eraseregions[i].numblocks); } - /* Also select the correct geometry setup too */ + /* Also select the correct geometry setup too */ mtd->erase = cfi_staa_erase_varsize; mtd->read = cfi_staa_read; mtd->write = cfi_staa_write_buffers; @@ -259,8 +259,8 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof adr += chip->start; - /* Ensure cmd read/writes are aligned. */ - cmd_addr = adr & ~(map_bankwidth(map)-1); + /* Ensure cmd read/writes are aligned. */ + cmd_addr = adr & ~(map_bankwidth(map)-1); /* Let's determine this according to the interleave only once */ status_OK = CMD(0x80); @@ -276,7 +276,7 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof case FL_ERASING: if (!(((struct cfi_pri_intelext *)cfi->cmdset_priv)->FeatureSupport & 2)) goto sleep; /* We don't support erase suspend */ - + map_write (map, CMD(0xb0), cmd_addr); /* If the flash has finished erasing, then 'erase suspend' * appears to make some (28F320) flash devices switch to @@ -291,7 +291,7 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof status = map_read(map, cmd_addr); if (map_word_andequal(map, status, status_OK, status_OK)) break; - + if (time_after(jiffies, timeo)) { /* Urgh */ map_write(map, CMD(0xd0), cmd_addr); @@ -303,17 +303,17 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof "suspended: status = 0x%lx\n", status.x[0]); return -EIO; } - + spin_unlock_bh(chip->mutex); cfi_udelay(1); spin_lock_bh(chip->mutex); } - + suspended = 1; map_write(map, CMD(0xff), cmd_addr); chip->state = FL_READY; break; - + #if 0 case FL_WRITING: /* Not quite yet */ @@ -334,7 +334,7 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof chip->state = FL_READY; break; } - + /* Urgh. Chip not yet ready to talk to us. */ if (time_after(jiffies, timeo)) { spin_unlock_bh(chip->mutex); @@ -364,17 +364,17 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof if (suspended) { chip->state = chip->oldstate; - /* What if one interleaved chip has finished and the + /* What if one interleaved chip has finished and the other hasn't? The old code would leave the finished - one in READY mode. That's bad, and caused -EROFS + one in READY mode. That's bad, and caused -EROFS errors to be returned from do_erase_oneblock because that's the only bit it checked for at the time. - As the state machine appears to explicitly allow + As the state machine appears to explicitly allow sending the 0x70 (Read Status) command to an erasing - chip and expecting it to be ignored, that's what we + chip and expecting it to be ignored, that's what we do. */ map_write(map, CMD(0xd0), cmd_addr); - map_write(map, CMD(0x70), cmd_addr); + map_write(map, CMD(0x70), cmd_addr); } wake_up(&chip->wq); @@ -414,14 +414,14 @@ static int cfi_staa_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen += thislen; len -= thislen; buf += thislen; - + ofs = 0; chipnum++; } return ret; } -static inline int do_write_buffer(struct map_info *map, struct flchip *chip, +static inline int do_write_buffer(struct map_info *map, struct flchip *chip, unsigned long adr, const u_char *buf, int len) { struct cfi_private *cfi = map->fldrv_priv; @@ -429,7 +429,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, unsigned long cmd_adr, timeo; DECLARE_WAITQUEUE(wait, current); int wbufsize, z; - + /* M58LW064A requires bus alignment for buffer wriets -- saw */ if (adr & (map_bankwidth(map)-1)) return -EINVAL; @@ -437,10 +437,10 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; adr += chip->start; cmd_adr = adr & ~(wbufsize-1); - + /* Let's determine this according to the interleave only once */ status_OK = CMD(0x80); - + timeo = jiffies + HZ; retry: @@ -448,7 +448,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, printk("%s: chip->state[%d]\n", __FUNCTION__, chip->state); #endif spin_lock_bh(chip->mutex); - + /* Check that the chip's ready to talk to us. * Later, we can actually think about interrupting it * if it's in FL_ERASING state. @@ -457,7 +457,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, switch (chip->state) { case FL_READY: break; - + case FL_CFI_QUERY: case FL_JEDEC_QUERY: map_write(map, CMD(0x70), cmd_adr); @@ -522,7 +522,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, /* Write length of data to come */ map_write(map, CMD(len/map_bankwidth(map)-1), cmd_adr ); - + /* Write data */ for (z = 0; z < len; z += map_bankwidth(map), buf += map_bankwidth(map)) { @@ -569,7 +569,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, printk(KERN_ERR "waiting for chip to be ready timed out in bufwrite\n"); return -EIO; } - + /* Latency issues. Drop the lock, wait a while and retry */ spin_unlock_bh(chip->mutex); cfi_udelay(1); @@ -581,9 +581,9 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, if (!chip->buffer_write_time) chip->buffer_write_time++; } - if (z > 1) + if (z > 1) chip->buffer_write_time++; - + /* Done and happy. */ DISABLE_VPP(map); chip->state = FL_STATUS; @@ -607,7 +607,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, return 0; } -static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to, +static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { struct map_info *map = mtd->priv; @@ -629,7 +629,7 @@ static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to, printk("%s: chipnum[%x] wbufsize[%x]\n", __FUNCTION__, chipnum, wbufsize); printk("%s: ofs[%x] len[%x]\n", __FUNCTION__, ofs, len); #endif - + /* Write buffer is worth it only if more than one word to write... */ while (len > 0) { /* We must not cross write block boundaries */ @@ -638,7 +638,7 @@ static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to, if (size > len) size = len; - ret = do_write_buffer(map, &cfi->chips[chipnum], + ret = do_write_buffer(map, &cfi->chips[chipnum], ofs, buf, size); if (ret) return ret; @@ -649,13 +649,13 @@ static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to, len -= size; if (ofs >> cfi->chipshift) { - chipnum ++; + chipnum ++; ofs = 0; if (chipnum == cfi->numchips) return 0; } } - + return 0; } @@ -765,7 +765,7 @@ retry: status = map_read(map, adr); if (map_word_andequal(map, status, status_OK, status_OK)) break; - + /* Urgh. Chip not yet ready to talk to us. */ if (time_after(jiffies, timeo)) { spin_unlock_bh(chip->mutex); @@ -798,7 +798,7 @@ retry: map_write(map, CMD(0x20), adr); map_write(map, CMD(0xD0), adr); chip->state = FL_ERASING; - + spin_unlock_bh(chip->mutex); msleep(1000); spin_lock_bh(chip->mutex); @@ -823,7 +823,7 @@ retry: status = map_read(map, adr); if (map_word_andequal(map, status, status_OK, status_OK)) break; - + /* OK Still waiting */ if (time_after(jiffies, timeo)) { map_write(map, CMD(0x70), adr); @@ -833,13 +833,13 @@ retry: spin_unlock_bh(chip->mutex); return -EIO; } - + /* Latency issues. Drop the lock, wait a while and retry */ spin_unlock_bh(chip->mutex); cfi_udelay(1); spin_lock_bh(chip->mutex); } - + DISABLE_VPP(map); ret = 0; @@ -864,7 +864,7 @@ retry: /* Reset the error bits */ map_write(map, CMD(0x50), adr); map_write(map, CMD(0x70), adr); - + if ((chipstatus & 0x30) == 0x30) { printk(KERN_NOTICE "Chip reports improper command sequence: status 0x%x\n", chipstatus); ret = -EIO; @@ -913,17 +913,17 @@ int cfi_staa_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) i = 0; - /* Skip all erase regions which are ended before the start of + /* Skip all erase regions which are ended before the start of the requested erase. Actually, to save on the calculations, we skip to the first erase region which starts after the start of the requested erase, and then go back one. */ - + while (i < mtd->numeraseregions && instr->addr >= regions[i].offset) i++; i--; - /* OK, now i is pointing at the erase region in which this + /* OK, now i is pointing at the erase region in which this erase request starts. Check the start of the requested erase range is aligned with the erase size which is in effect here. @@ -946,7 +946,7 @@ int cfi_staa_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) the address actually falls */ i--; - + if ((instr->addr + instr->len) & (regions[i].erasesize-1)) return -EINVAL; @@ -958,7 +958,7 @@ int cfi_staa_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) while(len) { ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr); - + if (ret) return ret; @@ -971,15 +971,15 @@ int cfi_staa_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) if (adr >> cfi->chipshift) { adr = 0; chipnum++; - + if (chipnum >= cfi->numchips) break; } } - + instr->state = MTD_ERASE_DONE; mtd_erase_callback(instr); - + return 0; } @@ -1005,7 +1005,7 @@ static void cfi_staa_sync (struct mtd_info *mtd) case FL_JEDEC_QUERY: chip->oldstate = chip->state; chip->state = FL_SYNCING; - /* No need to wake_up() on this state change - + /* No need to wake_up() on this state change - * as the whole point is that nobody can do anything * with the chip now anyway. */ @@ -1016,11 +1016,11 @@ static void cfi_staa_sync (struct mtd_info *mtd) default: /* Not an idle state */ add_wait_queue(&chip->wq, &wait); - + spin_unlock_bh(chip->mutex); schedule(); remove_wait_queue(&chip->wq, &wait); - + goto retry; } } @@ -1031,7 +1031,7 @@ static void cfi_staa_sync (struct mtd_info *mtd) chip = &cfi->chips[i]; spin_lock_bh(chip->mutex); - + if (chip->state == FL_SYNCING) { chip->state = chip->oldstate; wake_up(&chip->wq); @@ -1066,9 +1066,9 @@ retry: case FL_STATUS: status = map_read(map, adr); - if (map_word_andequal(map, status, status_OK, status_OK)) + if (map_word_andequal(map, status, status_OK, status_OK)) break; - + /* Urgh. Chip not yet ready to talk to us. */ if (time_after(jiffies, timeo)) { spin_unlock_bh(chip->mutex); @@ -1097,7 +1097,7 @@ retry: map_write(map, CMD(0x60), adr); map_write(map, CMD(0x01), adr); chip->state = FL_LOCKING; - + spin_unlock_bh(chip->mutex); msleep(1000); spin_lock_bh(chip->mutex); @@ -1111,7 +1111,7 @@ retry: status = map_read(map, adr); if (map_word_andequal(map, status, status_OK, status_OK)) break; - + /* OK Still waiting */ if (time_after(jiffies, timeo)) { map_write(map, CMD(0x70), adr); @@ -1121,13 +1121,13 @@ retry: spin_unlock_bh(chip->mutex); return -EIO; } - + /* Latency issues. Drop the lock, wait a while and retry */ spin_unlock_bh(chip->mutex); cfi_udelay(1); spin_lock_bh(chip->mutex); } - + /* Done and happy. */ chip->state = FL_STATUS; DISABLE_VPP(map); @@ -1171,8 +1171,8 @@ static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, size_t len) cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL); printk("after lock: block status register is %x\n",cfi_read_query(map, adr+(2*ofs_factor))); cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL); -#endif - +#endif + if (ret) return ret; @@ -1182,7 +1182,7 @@ static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, size_t len) if (adr >> cfi->chipshift) { adr = 0; chipnum++; - + if (chipnum >= cfi->numchips) break; } @@ -1217,7 +1217,7 @@ retry: status = map_read(map, adr); if (map_word_andequal(map, status, status_OK, status_OK)) break; - + /* Urgh. Chip not yet ready to talk to us. */ if (time_after(jiffies, timeo)) { spin_unlock_bh(chip->mutex); @@ -1246,7 +1246,7 @@ retry: map_write(map, CMD(0x60), adr); map_write(map, CMD(0xD0), adr); chip->state = FL_UNLOCKING; - + spin_unlock_bh(chip->mutex); msleep(1000); spin_lock_bh(chip->mutex); @@ -1260,7 +1260,7 @@ retry: status = map_read(map, adr); if (map_word_andequal(map, status, status_OK, status_OK)) break; - + /* OK Still waiting */ if (time_after(jiffies, timeo)) { map_write(map, CMD(0x70), adr); @@ -1270,13 +1270,13 @@ retry: spin_unlock_bh(chip->mutex); return -EIO; } - + /* Latency issues. Drop the unlock, wait a while and retry */ spin_unlock_bh(chip->mutex); cfi_udelay(1); spin_lock_bh(chip->mutex); } - + /* Done and happy. */ chip->state = FL_STATUS; DISABLE_VPP(map); @@ -1301,7 +1301,7 @@ static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) { unsigned long temp_adr = adr; unsigned long temp_len = len; - + cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL); while (temp_len) { printk("before unlock %x: block status register is %x\n",temp_adr,cfi_read_query(map, temp_adr+(2*ofs_factor))); @@ -1319,7 +1319,7 @@ static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) printk("after unlock: block status register is %x\n",cfi_read_query(map, adr+(2*ofs_factor))); cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL); #endif - + return ret; } @@ -1343,7 +1343,7 @@ static int cfi_staa_suspend(struct mtd_info *mtd) case FL_JEDEC_QUERY: chip->oldstate = chip->state; chip->state = FL_PM_SUSPENDED; - /* No need to wake_up() on this state change - + /* No need to wake_up() on this state change - * as the whole point is that nobody can do anything * with the chip now anyway. */ @@ -1362,9 +1362,9 @@ static int cfi_staa_suspend(struct mtd_info *mtd) if (ret) { for (i--; i >=0; i--) { chip = &cfi->chips[i]; - + spin_lock_bh(chip->mutex); - + if (chip->state == FL_PM_SUSPENDED) { /* No need to force it into a known state here, because we're returning failure, and it didn't @@ -1374,8 +1374,8 @@ static int cfi_staa_suspend(struct mtd_info *mtd) } spin_unlock_bh(chip->mutex); } - } - + } + return ret; } @@ -1387,11 +1387,11 @@ static void cfi_staa_resume(struct mtd_info *mtd) struct flchip *chip; for (i=0; inumchips; i++) { - + chip = &cfi->chips[i]; spin_lock_bh(chip->mutex); - + /* Go to known state. Chip may have been power cycled */ if (chip->state == FL_PM_SUSPENDED) { map_write(map, CMD(0xFF), 0); diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c index cf750038ce6..90eb30e06b7 100644 --- a/drivers/mtd/chips/cfi_probe.c +++ b/drivers/mtd/chips/cfi_probe.c @@ -1,7 +1,7 @@ -/* +/* Common Flash Interface probe code. (C) 2000 Red Hat. GPL'd. - $Id: cfi_probe.c,v 1.83 2004/11/16 18:19:02 nico Exp $ + $Id: cfi_probe.c,v 1.84 2005/11/07 11:14:23 gleixner Exp $ */ #include @@ -20,7 +20,7 @@ #include #include -//#define DEBUG_CFI +//#define DEBUG_CFI #ifdef DEBUG_CFI static void print_cfi_ident(struct cfi_ident *); @@ -103,7 +103,7 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base, unsigned long *chip_map, struct cfi_private *cfi) { int i; - + if ((base + 0) >= map->size) { printk(KERN_NOTICE "Probe at base[0x00](0x%08lx) past the end of the map(0x%08lx)\n", @@ -128,7 +128,7 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base, } if (!cfi->numchips) { - /* This is the first time we're called. Set up the CFI + /* This is the first time we're called. Set up the CFI stuff accordingly and return */ return cfi_chip_setup(map, cfi); } @@ -138,13 +138,13 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base, unsigned long start; if(!test_bit(i, chip_map)) { /* Skip location; no valid chip at this address */ - continue; + continue; } start = i << cfi->chipshift; /* This chip should be in read mode if it's one we've already touched. */ if (qry_present(map, start, cfi)) { - /* Eep. This chip also had the QRY marker. + /* Eep. This chip also had the QRY marker. * Is it an alias for the new one? */ cfi_send_gen_cmd(0xF0, 0, start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0xFF, 0, start, map, cfi, cfi->device_type, NULL); @@ -156,13 +156,13 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base, map->name, base, start); return 0; } - /* Yes, it's actually got QRY for data. Most + /* Yes, it's actually got QRY for data. Most * unfortunate. Stick the new chip in read mode * too and if it's the same, assume it's an alias. */ /* FIXME: Use other modes to do a proper check */ cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0xFF, 0, start, map, cfi, cfi->device_type, NULL); - + if (qry_present(map, base, cfi)) { xip_allowed(base, map); printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n", @@ -171,12 +171,12 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base, } } } - + /* OK, if we got to here, then none of the previous chips appear to be aliases for the current one. */ set_bit((base >> cfi->chipshift), chip_map); /* Update chip map */ cfi->numchips++; - + /* Put it back into Read Mode */ cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); @@ -185,11 +185,11 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base, printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n", map->name, cfi->interleave, cfi->device_type*8, base, map->bankwidth*8); - + return 1; } -static int __xipram cfi_chip_setup(struct map_info *map, +static int __xipram cfi_chip_setup(struct map_info *map, struct cfi_private *cfi) { int ofs_factor = cfi->interleave*cfi->device_type; @@ -209,11 +209,11 @@ static int __xipram cfi_chip_setup(struct map_info *map, printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name); return 0; } - - memset(cfi->cfiq,0,sizeof(struct cfi_ident)); - + + memset(cfi->cfiq,0,sizeof(struct cfi_ident)); + cfi->cfi_mode = CFI_MODE_CFI; - + /* Read the CFI info structure */ xip_disable_qry(base, map, cfi); for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++) @@ -231,7 +231,7 @@ static int __xipram cfi_chip_setup(struct map_info *map, cfi_send_gen_cmd(0x55, 0x2aa, base, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x90, 0x555, base, map, cfi, cfi->device_type, NULL); cfi->mfr = cfi_read_query(map, base); - cfi->id = cfi_read_query(map, base + ofs_factor); + cfi->id = cfi_read_query(map, base + ofs_factor); /* Put it back into Read Mode */ cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); @@ -255,10 +255,10 @@ static int __xipram cfi_chip_setup(struct map_info *map, for (i=0; icfiq->NumEraseRegions; i++) { cfi->cfiq->EraseRegionInfo[i] = le32_to_cpu(cfi->cfiq->EraseRegionInfo[i]); - -#ifdef DEBUG_CFI + +#ifdef DEBUG_CFI printk(" Erase Region #%d: BlockSize 0x%4.4X bytes, %d blocks\n", - i, (cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff, + i, (cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff, (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1); #endif } @@ -271,33 +271,33 @@ static int __xipram cfi_chip_setup(struct map_info *map, } #ifdef DEBUG_CFI -static char *vendorname(__u16 vendor) +static char *vendorname(__u16 vendor) { switch (vendor) { case P_ID_NONE: return "None"; - + case P_ID_INTEL_EXT: return "Intel/Sharp Extended"; - + case P_ID_AMD_STD: return "AMD/Fujitsu Standard"; - + case P_ID_INTEL_STD: return "Intel/Sharp Standard"; - + case P_ID_AMD_EXT: return "AMD/Fujitsu Extended"; case P_ID_WINBOND: return "Winbond Standard"; - + case P_ID_ST_ADV: return "ST Advanced"; case P_ID_MITSUBISHI_STD: return "Mitsubishi Standard"; - + case P_ID_MITSUBISHI_EXT: return "Mitsubishi Extended"; @@ -306,13 +306,13 @@ static char *vendorname(__u16 vendor) case P_ID_INTEL_PERFORMANCE: return "Intel Performance Code"; - + case P_ID_INTEL_DATA: return "Intel Data"; - + case P_ID_RESERVED: return "Not Allowed / Reserved for Future Use"; - + default: return "Unknown"; } @@ -325,21 +325,21 @@ static void print_cfi_ident(struct cfi_ident *cfip) if (cfip->qry[0] != 'Q' || cfip->qry[1] != 'R' || cfip->qry[2] != 'Y') { printk("Invalid CFI ident structure.\n"); return; - } -#endif + } +#endif printk("Primary Vendor Command Set: %4.4X (%s)\n", cfip->P_ID, vendorname(cfip->P_ID)); if (cfip->P_ADR) printk("Primary Algorithm Table at %4.4X\n", cfip->P_ADR); else printk("No Primary Algorithm Table\n"); - + printk("Alternative Vendor Command Set: %4.4X (%s)\n", cfip->A_ID, vendorname(cfip->A_ID)); if (cfip->A_ADR) printk("Alternate Algorithm Table at %4.4X\n", cfip->A_ADR); else printk("No Alternate Algorithm Table\n"); - - + + printk("Vcc Minimum: %2d.%d V\n", cfip->VccMin >> 4, cfip->VccMin & 0xf); printk("Vcc Maximum: %2d.%d V\n", cfip->VccMax >> 4, cfip->VccMax & 0xf); if (cfip->VppMin) { @@ -348,61 +348,61 @@ static void print_cfi_ident(struct cfi_ident *cfip) } else printk("No Vpp line\n"); - + printk("Typical byte/word write timeout: %d µs\n", 1<WordWriteTimeoutTyp); printk("Maximum byte/word write timeout: %d µs\n", (1<WordWriteTimeoutMax) * (1<WordWriteTimeoutTyp)); - + if (cfip->BufWriteTimeoutTyp || cfip->BufWriteTimeoutMax) { printk("Typical full buffer write timeout: %d µs\n", 1<BufWriteTimeoutTyp); printk("Maximum full buffer write timeout: %d µs\n", (1<BufWriteTimeoutMax) * (1<BufWriteTimeoutTyp)); } else printk("Full buffer write not supported\n"); - + printk("Typical block erase timeout: %d ms\n", 1<BlockEraseTimeoutTyp); printk("Maximum block erase timeout: %d ms\n", (1<BlockEraseTimeoutMax) * (1<BlockEraseTimeoutTyp)); if (cfip->ChipEraseTimeoutTyp || cfip->ChipEraseTimeoutMax) { - printk("Typical chip erase timeout: %d ms\n", 1<ChipEraseTimeoutTyp); + printk("Typical chip erase timeout: %d ms\n", 1<ChipEraseTimeoutTyp); printk("Maximum chip erase timeout: %d ms\n", (1<ChipEraseTimeoutMax) * (1<ChipEraseTimeoutTyp)); } else printk("Chip erase not supported\n"); - + printk("Device size: 0x%X bytes (%d MiB)\n", 1 << cfip->DevSize, 1<< (cfip->DevSize - 20)); printk("Flash Device Interface description: 0x%4.4X\n", cfip->InterfaceDesc); switch(cfip->InterfaceDesc) { case 0: printk(" - x8-only asynchronous interface\n"); break; - + case 1: printk(" - x16-only asynchronous interface\n"); break; - + case 2: printk(" - supports x8 and x16 via BYTE# with asynchronous interface\n"); break; - + case 3: printk(" - x32-only asynchronous interface\n"); break; - + case 4: printk(" - supports x16 and x32 via Word# with asynchronous interface\n"); break; - + case 65535: printk(" - Not Allowed / Reserved\n"); break; - + default: printk(" - Unknown\n"); break; } - + printk("Max. bytes in buffer write: 0x%x\n", 1<< cfip->MaxBufWriteSize); printk("Number of Erase Block Regions: %d\n", cfip->NumEraseRegions); - + } #endif /* DEBUG_CFI */ diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c index 0cf183f01e4..d8e7a026ba5 100644 --- a/drivers/mtd/chips/cfi_util.c +++ b/drivers/mtd/chips/cfi_util.c @@ -7,7 +7,7 @@ * * This code is covered by the GPL. * - * $Id: cfi_util.c,v 1.9 2005/07/20 21:01:14 tpoynor Exp $ + * $Id: cfi_util.c,v 1.10 2005/11/07 11:14:23 gleixner Exp $ * */ @@ -56,7 +56,7 @@ __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* n /* Read in the Extended Query Table */ for (i=0; inumeraseregions && ofs >= regions[i].offset) i++; i--; - /* OK, now i is pointing at the erase region in which this + /* OK, now i is pointing at the erase region in which this erase request starts. Check the start of the requested erase range is aligned with the erase size which is in effect here. @@ -146,7 +146,7 @@ int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob, the address actually falls */ i--; - + if ((ofs + len) & (regions[i].erasesize-1)) return -EINVAL; @@ -159,7 +159,7 @@ int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob, int size = regions[i].erasesize; ret = (*frob)(map, &cfi->chips[chipnum], adr, size, thunk); - + if (ret) return ret; @@ -173,7 +173,7 @@ int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob, if (adr >> cfi->chipshift) { adr = 0; chipnum++; - + if (chipnum >= cfi->numchips) break; } diff --git a/drivers/mtd/chips/chipreg.c b/drivers/mtd/chips/chipreg.c index d7d739a108a..c2127840a18 100644 --- a/drivers/mtd/chips/chipreg.c +++ b/drivers/mtd/chips/chipreg.c @@ -41,7 +41,7 @@ static struct mtd_chip_driver *get_mtd_chip_driver (const char *name) list_for_each(pos, &chip_drvs_list) { this = list_entry(pos, typeof(*this), list); - + if (!strcmp(this->name, name)) { ret = this; break; @@ -73,7 +73,7 @@ struct mtd_info *do_map_probe(const char *name, struct map_info *map) ret = drv->probe(map); - /* We decrease the use count here. It may have been a + /* We decrease the use count here. It may have been a probe-only module, which is no longer required from this point, having given us a handle on (and increased the use count of) the actual driver code. @@ -82,7 +82,7 @@ struct mtd_info *do_map_probe(const char *name, struct map_info *map) if (ret) return ret; - + return NULL; } /* diff --git a/drivers/mtd/chips/fwh_lock.h b/drivers/mtd/chips/fwh_lock.h index e1a5b76596c..77303ce5dcf 100644 --- a/drivers/mtd/chips/fwh_lock.h +++ b/drivers/mtd/chips/fwh_lock.h @@ -25,7 +25,7 @@ struct fwh_xxlock_thunk { * so this code has not been tested with interleaved chips, * and will likely fail in that context. */ -static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip, +static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, int len, void *thunk) { struct cfi_private *cfi = map->fldrv_priv; @@ -44,7 +44,7 @@ static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip, * - on 64k boundariesand * - bit 1 set high * - block lock registers are 4MiB lower - overflow subtract (danger) - * + * * The address manipulation is first done on the logical address * which is 0 at the start of the chip, and then the offset of * the individual chip is addted to it. Any other order a weird @@ -93,7 +93,7 @@ static int fwh_unlock_varsize(struct mtd_info *mtd, loff_t ofs, size_t len) ret = cfi_varsize_frob(mtd, fwh_xxlock_oneblock, ofs, len, (void *)&FWH_XXLOCK_ONEBLOCK_UNLOCK); - + return ret; } diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c index 28807eb9fc8..41bd59d20d8 100644 --- a/drivers/mtd/chips/gen_probe.c +++ b/drivers/mtd/chips/gen_probe.c @@ -2,7 +2,7 @@ * Routines common to all CFI-type probes. * (C) 2001-2003 Red Hat, Inc. * GPL'd - * $Id: gen_probe.c,v 1.23 2005/08/06 04:40:41 nico Exp $ + * $Id: gen_probe.c,v 1.24 2005/11/07 11:14:23 gleixner Exp $ */ #include @@ -26,7 +26,7 @@ struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp) /* First probe the map to see if we have CFI stuff there. */ cfi = genprobe_ident_chips(map, cp); - + if (!cfi) return NULL; @@ -36,12 +36,12 @@ struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp) mtd = check_cmd_set(map, 1); /* First the primary cmdset */ if (!mtd) mtd = check_cmd_set(map, 0); /* Then the secondary */ - + if (mtd) return mtd; printk(KERN_WARNING"gen_probe: No supported Vendor Command Set found\n"); - + kfree(cfi->cfiq); kfree(cfi); map->fldrv_priv = NULL; @@ -60,14 +60,14 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi memset(&cfi, 0, sizeof(cfi)); - /* Call the probetype-specific code with all permutations of + /* Call the probetype-specific code with all permutations of interleave and device type, etc. */ if (!genprobe_new_chip(map, cp, &cfi)) { /* The probe didn't like it */ printk(KERN_DEBUG "%s: Found no %s device at location zero\n", cp->name, map->name); return NULL; - } + } #if 0 /* Let the CFI probe routine do this sanity check. The Intel and AMD probe routines won't ever return a broken CFI structure anyway, @@ -92,13 +92,13 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi } else { BUG(); } - + cfi.numchips = 1; - /* - * Allocate memory for bitmap of valid chips. - * Align bitmap storage size to full byte. - */ + /* + * Allocate memory for bitmap of valid chips. + * Align bitmap storage size to full byte. + */ max_chips = map->size >> cfi.chipshift; mapsize = (max_chips / 8) + ((max_chips % 8) ? 1 : 0); chip_map = kmalloc(mapsize, GFP_KERNEL); @@ -122,7 +122,7 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi } /* - * Now allocate the space for the structures we need to return to + * Now allocate the space for the structures we need to return to * our caller, and copy the appropriate data into them. */ @@ -154,7 +154,7 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi return retcfi; } - + static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp, struct cfi_private *cfi) { @@ -189,7 +189,7 @@ extern cfi_cmdset_fn_t cfi_cmdset_0001; extern cfi_cmdset_fn_t cfi_cmdset_0002; extern cfi_cmdset_fn_t cfi_cmdset_0020; -static inline struct mtd_info *cfi_cmdset_unknown(struct map_info *map, +static inline struct mtd_info *cfi_cmdset_unknown(struct map_info *map, int primary) { struct cfi_private *cfi = map->fldrv_priv; @@ -199,7 +199,7 @@ static inline struct mtd_info *cfi_cmdset_unknown(struct map_info *map, cfi_cmdset_fn_t *probe_function; sprintf(probename, "cfi_cmdset_%4.4X", type); - + probe_function = inter_module_get_request(probename, probename); if (probe_function) { @@ -221,7 +221,7 @@ static struct mtd_info *check_cmd_set(struct map_info *map, int primary) { struct cfi_private *cfi = map->fldrv_priv; __u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID; - + if (type == P_ID_NONE || type == P_ID_RESERVED) return NULL; diff --git a/drivers/mtd/chips/jedec.c b/drivers/mtd/chips/jedec.c index 4f6778f3ee3..c40b48dabed 100644 --- a/drivers/mtd/chips/jedec.c +++ b/drivers/mtd/chips/jedec.c @@ -1,6 +1,6 @@ /* JEDEC Flash Interface. - * This is an older type of interface for self programming flash. It is + * This is an older type of interface for self programming flash. It is * commonly use in older AMD chips and is obsolete compared with CFI. * It is called JEDEC because the JEDEC association distributes the ID codes * for the chips. @@ -88,9 +88,9 @@ static const struct JEDECTable JEDEC_table[] = { static const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id); static void jedec_sync(struct mtd_info *mtd) {}; -static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len, +static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); -static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len, +static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); static struct mtd_info *jedec_probe(struct map_info *map); @@ -122,7 +122,7 @@ static struct mtd_info *jedec_probe(struct map_info *map) memset(MTD, 0, sizeof(struct mtd_info) + sizeof(struct jedec_private)); priv = (struct jedec_private *)&MTD[1]; - + my_bank_size = map->size; if (map->size/my_bank_size > MAX_JEDEC_CHIPS) @@ -131,13 +131,13 @@ static struct mtd_info *jedec_probe(struct map_info *map) kfree(MTD); return NULL; } - + for (Base = 0; Base < map->size; Base += my_bank_size) { // Perhaps zero could designate all tests? if (map->buswidth == 0) map->buswidth = 1; - + if (map->buswidth == 1){ if (jedec_probe8(map,Base,priv) == 0) { printk("did recognize jedec chip\n"); @@ -150,7 +150,7 @@ static struct mtd_info *jedec_probe(struct map_info *map) if (map->buswidth == 4) jedec_probe32(map,Base,priv); } - + // Get the biggest sector size SectorSize = 0; for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) @@ -160,7 +160,7 @@ static struct mtd_info *jedec_probe(struct map_info *map) if (priv->chips[I].sectorsize > SectorSize) SectorSize = priv->chips[I].sectorsize; } - + // Quickly ensure that the other sector sizes are factors of the largest for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) { @@ -169,9 +169,9 @@ static struct mtd_info *jedec_probe(struct map_info *map) printk("mtd: Failed. Device has incompatible mixed sector sizes\n"); kfree(MTD); return NULL; - } + } } - + /* Generate a part name that includes the number of different chips and other configuration information */ count = 1; @@ -181,13 +181,13 @@ static struct mtd_info *jedec_probe(struct map_info *map) for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) { const struct JEDECTable *JEDEC; - + if (priv->chips[I+1].jedec == priv->chips[I].jedec) { count++; continue; } - + // Locate the chip in the jedec table JEDEC = jedec_idtoinf(priv->chips[I].jedec >> 8,priv->chips[I].jedec); if (JEDEC == 0) @@ -196,11 +196,11 @@ static struct mtd_info *jedec_probe(struct map_info *map) kfree(MTD); return NULL; } - + if (Uniq != 0) strcat(Part,","); Uniq++; - + if (count != 1) sprintf(Part+strlen(Part),"%x*[%s]",count,JEDEC->name); else @@ -208,7 +208,7 @@ static struct mtd_info *jedec_probe(struct map_info *map) if (strlen(Part) > sizeof(Part)*2/3) break; count = 1; - } + } /* Determine if the chips are organized in a linear fashion, or if there are empty banks. Note, the last bank does not count here, only the @@ -233,7 +233,7 @@ static struct mtd_info *jedec_probe(struct map_info *map) { if (priv->bank_fill[I] != my_bank_size) priv->is_banked = 1; - + /* This even could be eliminated, but new de-optimized read/write functions have to be written */ printk("priv->bank_fill[%d] is %lx, priv->bank_fill[0] is %lx\n",I,priv->bank_fill[I],priv->bank_fill[0]); @@ -242,7 +242,7 @@ static struct mtd_info *jedec_probe(struct map_info *map) printk("mtd: Failed. Cannot handle unsymmetric banking\n"); kfree(MTD); return NULL; - } + } } } } @@ -250,7 +250,7 @@ static struct mtd_info *jedec_probe(struct map_info *map) strcat(Part,", banked"); // printk("Part: '%s'\n",Part); - + memset(MTD,0,sizeof(*MTD)); // strlcpy(MTD->name,Part,sizeof(MTD->name)); MTD->name = map->name; @@ -291,7 +291,7 @@ static int checkparity(u_char C) /* Take an array of JEDEC numbers that represent interleved flash chips and process them. Check to make sure they are good JEDEC numbers, look - them up and then add them to the chip list */ + them up and then add them to the chip list */ static int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count, unsigned long base,struct jedec_private *priv) { @@ -306,16 +306,16 @@ static int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count, if (checkparity(Mfg[I]) == 0 || checkparity(Id[I]) == 0) return 0; } - + // Finally, just make sure all the chip sizes are the same JEDEC = jedec_idtoinf(Mfg[0],Id[0]); - + if (JEDEC == 0) { printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]); return 0; } - + Size = JEDEC->size; SectorSize = JEDEC->sectorsize; for (I = 0; I != Count; I++) @@ -331,7 +331,7 @@ static int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count, { printk("mtd: Failed. Interleved flash does not have matching characteristics\n"); return 0; - } + } } // Load the Chips @@ -345,13 +345,13 @@ static int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count, { printk("mtd: Device has too many chips. Increase MAX_JEDEC_CHIPS\n"); return 0; - } - + } + // Add them to the table for (J = 0; J != Count; J++) { unsigned long Bank; - + JEDEC = jedec_idtoinf(Mfg[J],Id[J]); priv->chips[I].jedec = (Mfg[J] << 8) | Id[J]; priv->chips[I].size = JEDEC->size; @@ -364,17 +364,17 @@ static int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count, // log2 n :| priv->chips[I].addrshift = 0; for (Bank = Count; Bank != 1; Bank >>= 1, priv->chips[I].addrshift++); - + // Determine how filled this bank is. Bank = base & (~(my_bank_size-1)); - if (priv->bank_fill[Bank/my_bank_size] < base + + if (priv->bank_fill[Bank/my_bank_size] < base + (JEDEC->size << priv->chips[I].addrshift) - Bank) priv->bank_fill[Bank/my_bank_size] = base + (JEDEC->size << priv->chips[I].addrshift) - Bank; I++; } priv->size += priv->chips[I-1].size*Count; - + return priv->chips[I-1].size; } @@ -392,7 +392,7 @@ static const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id) // Look for flash using an 8 bit bus interface static int jedec_probe8(struct map_info *map,unsigned long base, struct jedec_private *priv) -{ +{ #define flread(x) map_read8(map,base+x) #define flwrite(v,x) map_write8(map,v,base+x) @@ -410,20 +410,20 @@ static int jedec_probe8(struct map_info *map,unsigned long base, OldVal = flread(base); for (I = 0; OldVal != flread(base) && I < 10000; I++) OldVal = flread(base); - + // Reset the chip - flwrite(Reset,0x555); - + flwrite(Reset,0x555); + // Send the sequence flwrite(AutoSel1,0x555); flwrite(AutoSel2,0x2AA); flwrite(AutoSel3,0x555); - + // Get the JEDEC numbers Mfg[0] = flread(0); Id[0] = flread(1); // printk("Mfg is %x, Id is %x\n",Mfg[0],Id[0]); - + Size = handle_jedecs(map,Mfg,Id,1,base,priv); // printk("handle_jedecs Size is %x\n",(unsigned int)Size); if (Size == 0) @@ -431,13 +431,13 @@ static int jedec_probe8(struct map_info *map,unsigned long base, flwrite(Reset,0x555); return 0; } - + // Reset. flwrite(Reset,0x555); - + return 1; - + #undef flread #undef flwrite } @@ -470,17 +470,17 @@ static int jedec_probe32(struct map_info *map,unsigned long base, OldVal = flread(base); for (I = 0; OldVal != flread(base) && I < 10000; I++) OldVal = flread(base); - + // Reset the chip - flwrite(Reset,0x555); - + flwrite(Reset,0x555); + // Send the sequence flwrite(AutoSel1,0x555); flwrite(AutoSel2,0x2AA); flwrite(AutoSel3,0x555); - + // Test #1, JEDEC numbers are readable from 0x??00/0x??01 - if (flread(0) != flread(0x100) || + if (flread(0) != flread(0x100) || flread(1) != flread(0x101)) { flwrite(Reset,0x555); @@ -494,14 +494,14 @@ static int jedec_probe32(struct map_info *map,unsigned long base, OldVal = flread(1); for (I = 0; I != 4; I++) Id[I] = (OldVal >> (I*8)); - + Size = handle_jedecs(map,Mfg,Id,4,base,priv); if (Size == 0) { flwrite(Reset,0x555); return 0; } - + /* Check if there is address wrap around within a single bank, if this returns JEDEC numbers then we assume that it is wrap around. Notice we call this routine with the JEDEC return still enabled, if two or @@ -519,27 +519,27 @@ static int jedec_probe32(struct map_info *map,unsigned long base, // Reset. flwrite(0xF0F0F0F0,0x555); - + return 1; - + #undef flread #undef flwrite } /* Linear read. */ -static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len, +static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { struct map_info *map = mtd->priv; - + map_copy_from(map, buf, from, len); *retlen = len; - return 0; + return 0; } /* Banked read. Take special care to jump past the holes in the bank mapping. This version assumes symetry in the holes.. */ -static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len, +static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { struct map_info *map = mtd->priv; @@ -555,17 +555,17 @@ static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len, if (priv->bank_fill[0] - offset < len) get = priv->bank_fill[0] - offset; - bank /= priv->bank_fill[0]; + bank /= priv->bank_fill[0]; map_copy_from(map,buf + *retlen,bank*my_bank_size + offset,get); - + len -= get; *retlen += get; from += get; - } - return 0; + } + return 0; } -/* Pass the flags value that the flash return before it re-entered read +/* Pass the flags value that the flash return before it re-entered read mode. */ static void jedec_flash_failed(unsigned char code) { @@ -579,17 +579,17 @@ static void jedec_flash_failed(unsigned char code) printk("mtd: Programming didn't take\n"); } -/* This uses the erasure function described in the AMD Flash Handbook, +/* This uses the erasure function described in the AMD Flash Handbook, it will work for flashes with a fixed sector size only. Flashes with a selection of sector sizes (ie the AMD Am29F800B) will need a different - routine. This routine tries to parallize erasing multiple chips/sectors + routine. This routine tries to parallize erasing multiple chips/sectors where possible */ static int flash_erase(struct mtd_info *mtd, struct erase_info *instr) { // Does IO to the currently selected chip #define flread(x) map_read8(map,chip->base+((x)<addrshift)) #define flwrite(v,x) map_write8(map,v,chip->base+((x)<addrshift)) - + unsigned long Time = 0; unsigned long NoTime = 0; unsigned long start = instr->addr, len = instr->len; @@ -603,7 +603,7 @@ static int flash_erase(struct mtd_info *mtd, struct erase_info *instr) (len % mtd->erasesize) != 0 || (len/mtd->erasesize) == 0) return -EINVAL; - + jedec_flash_chip_scan(priv,start,len); // Start the erase sequence on each chip @@ -611,16 +611,16 @@ static int flash_erase(struct mtd_info *mtd, struct erase_info *instr) { unsigned long off; struct jedec_flash_chip *chip = priv->chips + I; - + if (chip->length == 0) continue; - + if (chip->start + chip->length > chip->size) { printk("DIE\n"); return -EIO; - } - + } + flwrite(0xF0,chip->start + 0x555); flwrite(0xAA,chip->start + 0x555); flwrite(0x55,chip->start + 0x2AA); @@ -628,8 +628,8 @@ static int flash_erase(struct mtd_info *mtd, struct erase_info *instr) flwrite(0xAA,chip->start + 0x555); flwrite(0x55,chip->start + 0x2AA); - /* Once we start selecting the erase sectors the delay between each - command must not exceed 50us or it will immediately start erasing + /* Once we start selecting the erase sectors the delay between each + command must not exceed 50us or it will immediately start erasing and ignore the other sectors */ for (off = 0; off < len; off += chip->sectorsize) { @@ -641,19 +641,19 @@ static int flash_erase(struct mtd_info *mtd, struct erase_info *instr) { printk("mtd: Ack! We timed out the erase timer!\n"); return -EIO; - } + } } - } + } /* We could split this into a timer routine and return early, performing background erasure.. Maybe later if the need warrents */ /* Poll the flash for erasure completion, specs say this can take as long - as 480 seconds to do all the sectors (for a 2 meg flash). + as 480 seconds to do all the sectors (for a 2 meg flash). Erasure time is dependent on chip age, temp and wear.. */ - + /* This being a generic routine assumes a 32 bit bus. It does read32s - and bundles interleved chips into the same grouping. This will work + and bundles interleved chips into the same grouping. This will work for all bus widths */ Time = 0; NoTime = 0; @@ -664,20 +664,20 @@ static int flash_erase(struct mtd_info *mtd, struct erase_info *instr) unsigned todo[4] = {0,0,0,0}; unsigned todo_left = 0; unsigned J; - + if (chip->length == 0) continue; - /* Find all chips in this data line, realistically this is all + /* Find all chips in this data line, realistically this is all or nothing up to the interleve count */ for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++) { - if ((priv->chips[J].base & (~((1<addrshift)-1))) == + if ((priv->chips[J].base & (~((1<addrshift)-1))) == (chip->base & (~((1<addrshift)-1)))) { todo_left++; todo[priv->chips[J].base & ((1<addrshift)-1)] = 1; - } + } } /* printk("todo: %x %x %x %x\n",(short)todo[0],(short)todo[1], @@ -687,7 +687,7 @@ static int flash_erase(struct mtd_info *mtd, struct erase_info *instr) { __u32 Last[4]; unsigned long Count = 0; - + /* During erase bit 7 is held low and bit 6 toggles, we watch this, should it stop toggling or go high then the erase is completed, or this is not really flash ;> */ @@ -718,23 +718,23 @@ static int flash_erase(struct mtd_info *mtd, struct erase_info *instr) __u8 Byte3 = (Last[(Count-3)%4] >> (J*8)) & 0xFF; if (todo[J] == 0) continue; - + if ((Byte1 & (1 << 7)) == 0 && Byte1 != Byte2) { // printk("Check %x %x %x\n",(short)J,(short)Byte1,(short)Byte2); continue; } - + if (Byte1 == Byte2) { jedec_flash_failed(Byte3); return -EIO; } - + todo[J] = 0; todo_left--; } - + /* if (NoTime == 0) Time += HZ/10 - schedule_timeout(HZ/10);*/ NoTime = 0; @@ -751,7 +751,7 @@ static int flash_erase(struct mtd_info *mtd, struct erase_info *instr) break; } Count++; - + /* // Count time, max of 15s per sector (according to AMD) if (Time > 15*len/mtd->erasesize*HZ) { @@ -759,38 +759,38 @@ static int flash_erase(struct mtd_info *mtd, struct erase_info *instr) return -EIO; } */ } - + // Skip to the next chip if we used chip erase if (chip->length == chip->size) off = chip->size; else off += chip->sectorsize; - + if (off >= chip->length) break; NoTime = 1; } - + for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++) { if ((priv->chips[J].base & (~((1<addrshift)-1))) == (chip->base & (~((1<addrshift)-1)))) priv->chips[J].length = 0; - } + } } - + //printk("done\n"); instr->state = MTD_ERASE_DONE; mtd_erase_callback(instr); return 0; - + #undef flread #undef flwrite } /* This is the simple flash writing function. It writes to every byte, in sequence. It takes care of how to properly address the flash if - the flash is interleved. It can only be used if all the chips in the + the flash is interleved. It can only be used if all the chips in the array are identical!*/ static int flash_write(struct mtd_info *mtd, loff_t start, size_t len, size_t *retlen, const u_char *buf) @@ -800,25 +800,25 @@ static int flash_write(struct mtd_info *mtd, loff_t start, size_t len, of addrshift (interleave index) and then adds the control register index. */ #define flread(x) map_read8(map,base+(off&((1<addrshift)-1))+((x)<addrshift)) #define flwrite(v,x) map_write8(map,v,base+(off&((1<addrshift)-1))+((x)<addrshift)) - + struct map_info *map = mtd->priv; struct jedec_private *priv = map->fldrv_priv; unsigned long base; unsigned long off; size_t save_len = len; - + if (start + len > mtd->size) return -EIO; - + //printk("Here"); - + //printk("flash_write: start is %x, len is %x\n",start,(unsigned long)len); while (len != 0) { struct jedec_flash_chip *chip = priv->chips; unsigned long bank; unsigned long boffset; - + // Compute the base of the flash. off = ((unsigned long)start) % (chip->size << chip->addrshift); base = start - off; @@ -828,10 +828,10 @@ static int flash_write(struct mtd_info *mtd, loff_t start, size_t len, boffset = base & (priv->bank_fill[0]-1); bank = (bank/priv->bank_fill[0])*my_bank_size; base = bank + boffset; - + // printk("Flasing %X %X %X\n",base,chip->size,len); // printk("off is %x, compare with %x\n",off,chip->size << chip->addrshift); - + // Loop over this page for (; off != (chip->size << chip->addrshift) && len != 0; start++, len--, off++,buf++) { @@ -845,7 +845,7 @@ static int flash_write(struct mtd_info *mtd, loff_t start, size_t len, } if (((~oldbyte) & *buf) != 0) printk("mtd: warn: Trying to set a 0 to a 1\n"); - + // Write flwrite(0xAA,0x555); flwrite(0x55,0x2AA); @@ -854,10 +854,10 @@ static int flash_write(struct mtd_info *mtd, loff_t start, size_t len, Last[0] = map_read8(map,base + off); Last[1] = map_read8(map,base + off); Last[2] = map_read8(map,base + off); - + /* Wait for the flash to finish the operation. We store the last 4 status bytes that have been retrieved so we can determine why - it failed. The toggle bits keep toggling when there is a + it failed. The toggle bits keep toggling when there is a failure */ for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] && Count < 10000; Count++) @@ -866,7 +866,7 @@ static int flash_write(struct mtd_info *mtd, loff_t start, size_t len, { jedec_flash_failed(Last[(Count - 3) % 4]); return -EIO; - } + } } } *retlen = save_len; @@ -885,24 +885,24 @@ static void jedec_flash_chip_scan(struct jedec_private *priv,unsigned long start // Zero the records for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) priv->chips[I].start = priv->chips[I].length = 0; - + // Intersect the region with each chip for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) { struct jedec_flash_chip *chip = priv->chips + I; unsigned long ByteStart; unsigned long ChipEndByte = chip->offset + (chip->size << chip->addrshift); - + // End is before this chip or the start is after it if (start+len < chip->offset || ChipEndByte - (1 << chip->addrshift) < start) continue; - + if (start < chip->offset) { ByteStart = chip->offset; chip->start = 0; - } + } else { chip->start = (start - chip->offset + (1 << chip->addrshift)-1) >> chip->addrshift; diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index 30da428eb7b..edb306c03c0 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c @@ -1,7 +1,7 @@ -/* +/* Common Flash Interface probe code. (C) 2000 Red Hat. GPL'd. - $Id: jedec_probe.c,v 1.63 2005/02/14 16:30:32 bjd Exp $ + $Id: jedec_probe.c,v 1.66 2005/11/07 11:14:23 gleixner Exp $ See JEDEC (http://www.jedec.org/) standard JESD21C (section 3.5) for the standard this probe goes back to. @@ -1719,7 +1719,7 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, static struct mtd_info *jedec_probe(struct map_info *map); -static inline u32 jedec_read_mfr(struct map_info *map, __u32 base, +static inline u32 jedec_read_mfr(struct map_info *map, __u32 base, struct cfi_private *cfi) { map_word result; @@ -1730,7 +1730,7 @@ static inline u32 jedec_read_mfr(struct map_info *map, __u32 base, return result.x[0] & mask; } -static inline u32 jedec_read_id(struct map_info *map, __u32 base, +static inline u32 jedec_read_id(struct map_info *map, __u32 base, struct cfi_private *cfi) { map_word result; @@ -1741,7 +1741,7 @@ static inline u32 jedec_read_id(struct map_info *map, __u32 base, return result.x[0] & mask; } -static inline void jedec_reset(u32 base, struct map_info *map, +static inline void jedec_reset(u32 base, struct map_info *map, struct cfi_private *cfi) { /* Reset */ @@ -1765,7 +1765,7 @@ static inline void jedec_reset(u32 base, struct map_info *map, * so ensure we're in read mode. Send both the Intel and the AMD command * for this. Intel uses 0xff for this, AMD uses 0xff for NOP, so * this should be safe. - */ + */ cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); /* FIXME - should have reset delay before continuing */ } @@ -1807,14 +1807,14 @@ static int cfi_jedec_setup(struct cfi_private *p_cfi, int index) printk("Found: %s\n",jedec_table[index].name); num_erase_regions = jedec_table[index].NumEraseRegions; - + p_cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL); if (!p_cfi->cfiq) { //xx printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name); return 0; } - memset(p_cfi->cfiq,0,sizeof(struct cfi_ident)); + memset(p_cfi->cfiq,0,sizeof(struct cfi_ident)); p_cfi->cfiq->P_ID = jedec_table[index].CmdSet; p_cfi->cfiq->NumEraseRegions = jedec_table[index].NumEraseRegions; @@ -1969,7 +1969,7 @@ static inline int jedec_match( __u32 base, cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL); /* FIXME - should have a delay before continuing */ - match_done: + match_done: return rc; } @@ -1998,23 +1998,23 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, "Probe at base(0x%08x) past the end of the map(0x%08lx)\n", base, map->size -1); return 0; - + } /* Ensure the unlock addresses we try stay inside the map */ probe_offset1 = cfi_build_cmd_addr( - cfi->addr_unlock1, - cfi_interleave(cfi), + cfi->addr_unlock1, + cfi_interleave(cfi), cfi->device_type); probe_offset2 = cfi_build_cmd_addr( - cfi->addr_unlock1, - cfi_interleave(cfi), + cfi->addr_unlock1, + cfi_interleave(cfi), cfi->device_type); if ( ((base + probe_offset1 + map_bankwidth(map)) >= map->size) || ((base + probe_offset2 + map_bankwidth(map)) >= map->size)) { goto retry; } - + /* Reset */ jedec_reset(base, map, cfi); @@ -2027,13 +2027,13 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, /* FIXME - should have a delay before continuing */ if (!cfi->numchips) { - /* This is the first time we're called. Set up the CFI + /* This is the first time we're called. Set up the CFI stuff accordingly and return */ - + cfi->mfr = jedec_read_mfr(map, base, cfi); cfi->id = jedec_read_id(map, base, cfi); DEBUG(MTD_DEBUG_LEVEL3, - "Search for id:(%02x %02x) interleave(%d) type(%d)\n", + "Search for id:(%02x %02x) interleave(%d) type(%d)\n", cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type); for (i=0; i> cfi->chipshift); i++) { unsigned long start; @@ -2083,7 +2083,7 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, map->name, base, start); return 0; } - + /* Yes, it's actually got the device IDs as data. Most * unfortunate. Stick the new chip in read mode * too and if it's the same, assume it's an alias. */ @@ -2097,20 +2097,20 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, } } } - + /* OK, if we got to here, then none of the previous chips appear to be aliases for the current one. */ set_bit((base >> cfi->chipshift), chip_map); /* Update chip map */ cfi->numchips++; - + ok_out: /* Put it back into Read Mode */ jedec_reset(base, map, cfi); printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n", - map->name, cfi_interleave(cfi), cfi->device_type*8, base, + map->name, cfi_interleave(cfi), cfi->device_type*8, base, map->bankwidth*8); - + return 1; } diff --git a/drivers/mtd/chips/map_absent.c b/drivers/mtd/chips/map_absent.c index c6c83833cc3..a611de9b151 100644 --- a/drivers/mtd/chips/map_absent.c +++ b/drivers/mtd/chips/map_absent.c @@ -1,11 +1,11 @@ /* * Common code to handle absent "placeholder" devices * Copyright 2001 Resilience Corporation - * $Id: map_absent.c,v 1.5 2004/11/16 18:29:00 dwmw2 Exp $ + * $Id: map_absent.c,v 1.6 2005/11/07 11:14:23 gleixner Exp $ * * This map driver is used to allocate "placeholder" MTD - * devices on systems that have socketed/removable media. - * Use of this driver as a fallback preserves the expected + * devices on systems that have socketed/removable media. + * Use of this driver as a fallback preserves the expected * registration of MTD device nodes regardless of probe outcome. * A usage example is as follows: * @@ -80,7 +80,7 @@ static int map_absent_read(struct mtd_info *mtd, loff_t from, size_t len, size_t static int map_absent_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { *retlen = 0; - return -ENODEV; + return -ENODEV; } static int map_absent_erase(struct mtd_info *mtd, struct erase_info *instr) diff --git a/drivers/mtd/chips/sharp.c b/drivers/mtd/chips/sharp.c index 08376dbf5d6..2d26bdef82d 100644 --- a/drivers/mtd/chips/sharp.c +++ b/drivers/mtd/chips/sharp.c @@ -4,7 +4,7 @@ * Copyright 2000,2001 David A. Schleef * 2000,2001 Lineo, Inc. * - * $Id: sharp.c,v 1.15 2005/08/02 20:36:05 tpoynor Exp $ + * $Id: sharp.c,v 1.16 2005/11/07 11:14:23 gleixner Exp $ * * Devices supported: * LH28F016SCT Symmetrical block flash memory, 2Mx8 @@ -459,12 +459,12 @@ static int sharp_do_wait_for_ready(struct map_info *map, struct flchip *chip, remove_wait_queue(&chip->wq, &wait); //spin_lock_bh(chip->mutex); - + if (signal_pending(current)){ ret = -EINTR; goto out; } - + } ret = -ETIME; out: @@ -563,7 +563,7 @@ static int sharp_suspend(struct mtd_info *mtd) static void sharp_resume(struct mtd_info *mtd) { printk("sharp_resume()\n"); - + } static void sharp_destroy(struct mtd_info *mtd) -- cgit v1.2.3 From 69f34c98c1416eb74c55e38a21dbf3e294966514 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 11:15:40 +0000 Subject: [MTD] maps: Clean up trailing white spaces Signed-off-by: Thomas Gleixner --- drivers/mtd/maps/Kconfig | 24 +++++++++---------- drivers/mtd/maps/Makefile | 4 ++-- drivers/mtd/maps/alchemy-flash.c | 12 +++++----- drivers/mtd/maps/amd76xrom.c | 16 ++++++------- drivers/mtd/maps/arctic-mtd.c | 6 ++--- drivers/mtd/maps/autcpu12-nvram.c | 18 +++++++-------- drivers/mtd/maps/bast-flash.c | 18 +++++++-------- drivers/mtd/maps/beech-mtd.c | 6 ++--- drivers/mtd/maps/cdb89712.c | 34 +++++++++++++-------------- drivers/mtd/maps/cfi_flagadm.c | 12 +++++----- drivers/mtd/maps/cstm_mips_ixx.c | 24 +++++++++---------- drivers/mtd/maps/dbox2-flash.c | 38 +++++++++++++++--------------- drivers/mtd/maps/dc21285.c | 34 +++++++++++++-------------- drivers/mtd/maps/dilnetpc.c | 32 +++++++++++++------------- drivers/mtd/maps/dmv182.c | 8 +++---- drivers/mtd/maps/ebony.c | 6 ++--- drivers/mtd/maps/edb7312.c | 10 ++++---- drivers/mtd/maps/epxa10db-flash.c | 12 +++++----- drivers/mtd/maps/fortunet.c | 4 ++-- drivers/mtd/maps/h720x-flash.c | 16 ++++++------- drivers/mtd/maps/ichxrom.c | 16 ++++++------- drivers/mtd/maps/impa7.c | 16 ++++++------- drivers/mtd/maps/integrator-flash.c | 14 +++++------ drivers/mtd/maps/ipaq-flash.c | 34 +++++++++++++-------------- drivers/mtd/maps/iq80310.c | 4 ++-- drivers/mtd/maps/ixp2000.c | 30 ++++++++++++------------ drivers/mtd/maps/ixp4xx.c | 14 +++++------ drivers/mtd/maps/l440gx.c | 18 +++++++-------- drivers/mtd/maps/lubbock-flash.c | 14 +++++------ drivers/mtd/maps/mainstone-flash.c | 22 +++++++++--------- drivers/mtd/maps/mbx860.c | 6 ++--- drivers/mtd/maps/mtx-1_flash.c | 4 ++-- drivers/mtd/maps/netsc520.c | 32 +++++++++++++------------- drivers/mtd/maps/nettel.c | 8 +++---- drivers/mtd/maps/ocelot.c | 10 ++++---- drivers/mtd/maps/octagon-5066.c | 36 ++++++++++++++--------------- drivers/mtd/maps/omap-toto-flash.c | 20 ++++++++-------- drivers/mtd/maps/omap_nor.c | 2 +- drivers/mtd/maps/pci.c | 6 ++--- drivers/mtd/maps/pcmciamtd.c | 30 ++++++++++++------------ drivers/mtd/maps/physmap.c | 8 +++---- drivers/mtd/maps/plat-ram.c | 10 ++++---- drivers/mtd/maps/pnc2000.c | 8 +++---- drivers/mtd/maps/pq2fads.c | 14 +++++------ drivers/mtd/maps/redwood.c | 4 ++-- drivers/mtd/maps/sa1100-flash.c | 6 ++--- drivers/mtd/maps/sbc8240.c | 4 ++-- drivers/mtd/maps/sbc_gxx.c | 46 ++++++++++++++++++------------------- drivers/mtd/maps/sc520cdp.c | 6 ++--- drivers/mtd/maps/scx200_docflash.c | 46 ++++++++++++++++++------------------- drivers/mtd/maps/sharpsl-flash.c | 12 +++++----- drivers/mtd/maps/solutionengine.c | 4 ++-- drivers/mtd/maps/sun_uflash.c | 12 +++++----- drivers/mtd/maps/tqm834x.c | 8 +++---- drivers/mtd/maps/tqm8xxl.c | 20 ++++++++-------- drivers/mtd/maps/ts5500_flash.c | 6 ++--- drivers/mtd/maps/tsunami_flash.c | 6 ++--- drivers/mtd/maps/uclinux.c | 4 ++-- drivers/mtd/maps/vmax301.c | 24 +++++++++---------- drivers/mtd/maps/walnut.c | 16 ++++++------- drivers/mtd/maps/wr_sbc82xx_flash.c | 6 ++--- 61 files changed, 470 insertions(+), 470 deletions(-) diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index e12e36a003d..48638c8097a 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -1,5 +1,5 @@ # drivers/mtd/maps/Kconfig -# $Id: Kconfig,v 1.60 2005/11/07 08:33:35 gleixner Exp $ +# $Id: Kconfig,v 1.61 2005/11/07 11:14:26 gleixner Exp $ menu "Mapping drivers for chip access" depends on MTD!=n @@ -64,9 +64,9 @@ config MTD_SUN_UFLASH tristate "Sun Microsystems userflash support" depends on (SPARC32 || SPARC64) && MTD_CFI help - This provides a 'mapping' driver which supports the way in - which user-programmable flash chips are connected on various - Sun Microsystems boardsets. This driver will require CFI support + This provides a 'mapping' driver which supports the way in + which user-programmable flash chips are connected on various + Sun Microsystems boardsets. This driver will require CFI support in the kernel, so if you did not enable CFI previously, do that now. config MTD_PNC2000 @@ -89,7 +89,7 @@ config MTD_NETSC520 depends on X86 && MTD_CFI && MTD_PARTITIONS help This enables access routines for the flash chips on the AMD NetSc520 - demonstration board. If you have one of these boards and would like + demonstration board. If you have one of these boards and would like to use the flash chips on it, say 'Y'. config MTD_TS5500 @@ -212,7 +212,7 @@ config MTD_NETtel Support for flash chips on NETtel/SecureEdge/SnapGear boards. config MTD_ALCHEMY - tristate ' AMD Alchemy Pb1xxx/Db1xxx/RDK MTD support' + tristate ' AMD Alchemy Pb1xxx/Db1xxx/RDK MTD support' depends on SOC_AU1X00 help Flash memory access on AMD Alchemy Pb/Db/RDK Reference Boards @@ -377,8 +377,8 @@ config MTD_CSTM_MIPS_IXX_START default "0x8000000" help This is the physical memory location that the MTD driver will - use for the flash chips on your particular target board. - Refer to the memory map which should hopefully be in the + use for the flash chips on your particular target board. + Refer to the memory map which should hopefully be in the documentation for your board. config MTD_CSTM_MIPS_IXX_LEN @@ -386,7 +386,7 @@ config MTD_CSTM_MIPS_IXX_LEN depends on MTD_CSTM_MIPS_IXX default "0x4000000" help - This is the total length that the MTD driver will use for the + This is the total length that the MTD driver will use for the flash chips on your particular board. Refer to the memory map which should hopefully be in the documentation for your board. @@ -452,14 +452,14 @@ config MTD_IQ80310 depends on MTD_CFI && ARCH_IQ80310 help This enables access routines for the flash chips on the Intel XScale - IQ80310 evaluation board. If you have one of these boards and would + IQ80310 evaluation board. If you have one of these boards and would like to use the flash chips on it, say 'Y'. config MTD_IXP4XX tristate "CFI Flash device mapped on Intel IXP4xx based systems" depends on MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP4XX help - This enables MTD access to flash devices on platforms based + This enables MTD access to flash devices on platforms based on Intel's IXP4xx family of network processors such as the IXDP425 and Coyote. If you have an IXP4xx based board and would like to use the flash chips on it, say 'Y'. @@ -468,7 +468,7 @@ config MTD_IXP2000 tristate "CFI Flash device mapped on Intel IXP2000 based systems" depends on MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP2000 help - This enables MTD access to flash devices on platforms based + This enables MTD access to flash devices on platforms based on Intel's IXP2000 family of network processors such as the IXDP425 and Coyote. If you have an IXP2000 based board and would like to use the flash chips on it, say 'Y'. diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index 81f97c60e0c..7d9e940a1dc 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -1,7 +1,7 @@ # # linux/drivers/maps/Makefile # -# $Id: Makefile.common,v 1.33 2005/11/07 08:33:35 gleixner Exp $ +# $Id: Makefile.common,v 1.34 2005/11/07 11:14:26 gleixner Exp $ ifeq ($(CONFIG_MTD_COMPLEX_MAPPINGS),y) obj-$(CONFIG_MTD) += map_funcs.o @@ -26,7 +26,7 @@ obj-$(CONFIG_MTD_MAINSTONE) += mainstone-flash.o obj-$(CONFIG_MTD_MBX860) += mbx860.o obj-$(CONFIG_MTD_CEIVA) += ceiva.o obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o -obj-$(CONFIG_MTD_PHYSMAP) += physmap.o +obj-$(CONFIG_MTD_PHYSMAP) += physmap.o obj-$(CONFIG_MTD_PNC2000) += pnc2000.o obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o diff --git a/drivers/mtd/maps/alchemy-flash.c b/drivers/mtd/maps/alchemy-flash.c index 27fd2a3c3b6..a57791a6ce4 100644 --- a/drivers/mtd/maps/alchemy-flash.c +++ b/drivers/mtd/maps/alchemy-flash.c @@ -1,10 +1,10 @@ /* * Flash memory access on AMD Alchemy evaluation boards - * - * $Id: alchemy-flash.c,v 1.1 2005/02/27 21:50:21 ppopov Exp $ + * + * $Id: alchemy-flash.c,v 1.2 2005/11/07 11:14:26 gleixner Exp $ * * (C) 2003, 2004 Pete Popov - * + * */ #include @@ -22,7 +22,7 @@ #ifdef DEBUG_RW #define DBG(x...) printk(x) #else -#define DBG(x...) +#define DBG(x...) #endif #ifdef CONFIG_MIPS_PB1000 @@ -136,7 +136,7 @@ int __init alchemy_mtd_init(void) int nb_parts = 0; unsigned long window_addr; unsigned long window_size; - + /* Default flash buswidth */ alchemy_map.bankwidth = BOARD_FLASH_WIDTH; @@ -161,7 +161,7 @@ int __init alchemy_mtd_init(void) * Now let's probe for the actual flash. Do it here since * specific machine settings might have been set above. */ - printk(KERN_NOTICE BOARD_MAP_NAME ": probing %d-bit flash bus\n", + printk(KERN_NOTICE BOARD_MAP_NAME ": probing %d-bit flash bus\n", alchemy_map.bankwidth*8); alchemy_map.virt = ioremap(window_addr, window_size); mymtd = do_map_probe("cfi_probe", &alchemy_map); diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c index e8a900a7768..60ca3be5406 100644 --- a/drivers/mtd/maps/amd76xrom.c +++ b/drivers/mtd/maps/amd76xrom.c @@ -2,7 +2,7 @@ * amd76xrom.c * * Normal mappings of chips in physical memory - * $Id: amd76xrom.c,v 1.20 2005/03/18 14:04:35 gleixner Exp $ + * $Id: amd76xrom.c,v 1.21 2005/11/07 11:14:26 gleixner Exp $ */ #include @@ -70,7 +70,7 @@ static void amd76xrom_cleanup(struct amd76xrom_window *window) list_del(&map->list); kfree(map); } - if (window->rsrc.parent) + if (window->rsrc.parent) release_resource(&window->rsrc); if (window->virt) { @@ -107,7 +107,7 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev, window->phys = 0xffff0000; /* 64KiB */ } window->size = 0xffffffffUL - window->phys + 1UL; - + /* * Try to reserve the window mem region. If this fails then * it is likely due to a fragment of the window being @@ -138,7 +138,7 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev, /* Enable writes through the rom window */ pci_read_config_byte(pdev, 0x40, &byte); pci_write_config_byte(pdev, 0x40, byte | 1); - + /* FIXME handle registers 0x80 - 0x8C the bios region locks */ /* For write accesses caches are useless */ @@ -186,7 +186,7 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev, MOD_NAME, map->map.phys); /* There is no generic VPP support */ - for(map->map.bankwidth = 32; map->map.bankwidth; + for(map->map.bankwidth = 32; map->map.bankwidth; map->map.bankwidth >>= 1) { char **probe_type; @@ -239,7 +239,7 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev, for(i = 0; i < cfi->numchips; i++) { cfi->chips[i].start += offset; } - + /* Now that the mtd devices is complete claim and export it */ map->mtd->owner = THIS_MODULE; if (add_mtd_device(map->mtd)) { @@ -279,9 +279,9 @@ static void __devexit amd76xrom_remove_one (struct pci_dev *pdev) } static struct pci_device_id amd76xrom_pci_tbl[] = { - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7440, + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7440, PCI_ANY_ID, PCI_ANY_ID, }, { PCI_VENDOR_ID_AMD, 0x7468 }, /* amd8111 support */ { 0, } diff --git a/drivers/mtd/maps/arctic-mtd.c b/drivers/mtd/maps/arctic-mtd.c index 777276fd0e1..d95ae582fbe 100644 --- a/drivers/mtd/maps/arctic-mtd.c +++ b/drivers/mtd/maps/arctic-mtd.c @@ -1,7 +1,7 @@ /* - * $Id: arctic-mtd.c,v 1.13 2004/11/04 13:24:14 gleixner Exp $ - * - * drivers/mtd/maps/arctic-mtd.c MTD mappings and partition tables for + * $Id: arctic-mtd.c,v 1.14 2005/11/07 11:14:26 gleixner Exp $ + * + * drivers/mtd/maps/arctic-mtd.c MTD mappings and partition tables for * IBM 405LP Arctic boards. * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/mtd/maps/autcpu12-nvram.c b/drivers/mtd/maps/autcpu12-nvram.c index cf362ccc3c8..7ed3424dd95 100644 --- a/drivers/mtd/maps/autcpu12-nvram.c +++ b/drivers/mtd/maps/autcpu12-nvram.c @@ -1,8 +1,8 @@ /* - * NV-RAM memory access on autcpu12 + * NV-RAM memory access on autcpu12 * (C) 2002 Thomas Gleixner (gleixner@autronix.de) * - * $Id: autcpu12-nvram.c,v 1.8 2004/11/04 13:24:14 gleixner Exp $ + * $Id: autcpu12-nvram.c,v 1.9 2005/11/07 11:14:26 gleixner Exp $ * * 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 @@ -55,10 +55,10 @@ static int __init init_autcpu12_sram (void) } simple_map_init(&autcpu_sram_map); - /* - * Check for 32K/128K - * read ofs 0 - * read ofs 0x10000 + /* + * Check for 32K/128K + * read ofs 0 + * read ofs 0x10000 * Write complement to ofs 0x100000 * Read and check result on ofs 0x0 * Restore contents @@ -66,7 +66,7 @@ static int __init init_autcpu12_sram (void) save0 = map_read32(&autcpu12_sram_map,0); save1 = map_read32(&autcpu12_sram_map,0x10000); map_write32(&autcpu12_sram_map,~save0,0x10000); - /* if we find this pattern on 0x0, we have 32K size + /* if we find this pattern on 0x0, we have 32K size * restore contents and exit */ if ( map_read32(&autcpu12_sram_map,0) != save0) { @@ -89,7 +89,7 @@ map: sram_mtd->owner = THIS_MODULE; sram_mtd->erasesize = 16; - + if (add_mtd_device(sram_mtd)) { printk("NV-RAM device addition failed\n"); err = -ENOMEM; @@ -97,7 +97,7 @@ map: } printk("NV-RAM device size %ldKiB registered on AUTCPU12\n",autcpu12_sram_map.size/SZ_1K); - + return 0; out_probe: diff --git a/drivers/mtd/maps/bast-flash.c b/drivers/mtd/maps/bast-flash.c index 5ec53c17e43..610dfcaa2c8 100644 --- a/drivers/mtd/maps/bast-flash.c +++ b/drivers/mtd/maps/bast-flash.c @@ -9,7 +9,7 @@ * 20-Sep-2004 BJD Initial version * 17-Jan-2005 BJD Add whole device if no partitions found * - * $Id: bast-flash.c,v 1.3 2005/10/10 00:13:38 bjd Exp $ + * $Id: bast-flash.c,v 1.5 2005/11/07 11:14:26 gleixner Exp $ * * 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 @@ -75,7 +75,7 @@ static void bast_flash_setrw(int to) local_irq_save(flags); val = __raw_readb(BAST_VA_CTRL3); - + if (to) val |= BAST_CPLD_CTRL3_ROMWEN; else @@ -93,7 +93,7 @@ static int bast_flash_remove(struct device *dev) dev_set_drvdata(dev, NULL); - if (info == NULL) + if (info == NULL) return 0; if (info->map.virt != NULL) @@ -111,7 +111,7 @@ static int bast_flash_remove(struct device *dev) release_resource(info->area); kfree(info->area); } - + kfree(info); return 0; @@ -138,15 +138,15 @@ static int bast_flash_probe(struct device *dev) info->map.phys = res->start; info->map.size = res->end - res->start + 1; - info->map.name = dev->bus_id; + info->map.name = dev->bus_id; info->map.bankwidth = 2; - + if (info->map.size > AREA_MAXSIZE) info->map.size = AREA_MAXSIZE; pr_debug("%s: area %08lx, size %ld\n", __FUNCTION__, info->map.phys, info->map.size); - + info->area = request_mem_region(res->start, info->map.size, pdev->name); if (info->area == NULL) { @@ -163,7 +163,7 @@ static int bast_flash_probe(struct device *dev) err = -EIO; goto exit_error; } - + simple_map_init(&info->map); /* enable the write to the flash area */ @@ -188,7 +188,7 @@ static int bast_flash_probe(struct device *dev) err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0); if (err > 0) { err = add_mtd_partitions(info->mtd, info->partitions, err); - if (err) + if (err) printk(KERN_ERR PFX "cannot add/parse partitions\n"); } else { err = add_mtd_device(info->mtd); diff --git a/drivers/mtd/maps/beech-mtd.c b/drivers/mtd/maps/beech-mtd.c index 5e79c9d5da2..5df7361d140 100644 --- a/drivers/mtd/maps/beech-mtd.c +++ b/drivers/mtd/maps/beech-mtd.c @@ -1,7 +1,7 @@ /* - * $Id: beech-mtd.c,v 1.10 2004/11/04 13:24:14 gleixner Exp $ - * - * drivers/mtd/maps/beech-mtd.c MTD mappings and partition tables for + * $Id: beech-mtd.c,v 1.11 2005/11/07 11:14:26 gleixner Exp $ + * + * drivers/mtd/maps/beech-mtd.c MTD mappings and partition tables for * IBM 405LP Beech boards. * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/mtd/maps/cdb89712.c b/drivers/mtd/maps/cdb89712.c index ab15dac2f93..9f17bb6c5a9 100644 --- a/drivers/mtd/maps/cdb89712.c +++ b/drivers/mtd/maps/cdb89712.c @@ -1,7 +1,7 @@ /* * Flash on Cirrus CDB89712 * - * $Id: cdb89712.c,v 1.10 2004/11/04 13:24:14 gleixner Exp $ + * $Id: cdb89712.c,v 1.11 2005/11/07 11:14:26 gleixner Exp $ */ #include @@ -37,13 +37,13 @@ struct resource cdb89712_flash_resource = { static int __init init_cdb89712_flash (void) { int err; - + if (request_resource (&ioport_resource, &cdb89712_flash_resource)) { printk(KERN_NOTICE "Failed to reserve Cdb89712 FLASH space\n"); err = -EBUSY; goto out; } - + cdb89712_flash_map.virt = ioremap(FLASH_START, FLASH_SIZE); if (!cdb89712_flash_map.virt) { printk(KERN_NOTICE "Failed to ioremap Cdb89712 FLASH space\n"); @@ -64,13 +64,13 @@ static int __init init_cdb89712_flash (void) } flash_mtd->owner = THIS_MODULE; - + if (add_mtd_device(flash_mtd)) { printk("FLASH device addition failed\n"); err = -ENOMEM; goto out_probe; } - + return 0; out_probe: @@ -107,13 +107,13 @@ struct resource cdb89712_sram_resource = { static int __init init_cdb89712_sram (void) { int err; - + if (request_resource (&ioport_resource, &cdb89712_sram_resource)) { printk(KERN_NOTICE "Failed to reserve Cdb89712 SRAM space\n"); err = -EBUSY; goto out; } - + cdb89712_sram_map.virt = ioremap(SRAM_START, SRAM_SIZE); if (!cdb89712_sram_map.virt) { printk(KERN_NOTICE "Failed to ioremap Cdb89712 SRAM space\n"); @@ -130,13 +130,13 @@ static int __init init_cdb89712_sram (void) sram_mtd->owner = THIS_MODULE; sram_mtd->erasesize = 16; - + if (add_mtd_device(sram_mtd)) { printk("SRAM device addition failed\n"); err = -ENOMEM; goto out_probe; } - + return 0; out_probe: @@ -175,13 +175,13 @@ struct resource cdb89712_bootrom_resource = { static int __init init_cdb89712_bootrom (void) { int err; - + if (request_resource (&ioport_resource, &cdb89712_bootrom_resource)) { printk(KERN_NOTICE "Failed to reserve Cdb89712 BOOTROM space\n"); err = -EBUSY; goto out; } - + cdb89712_bootrom_map.virt = ioremap(BOOTROM_START, BOOTROM_SIZE); if (!cdb89712_bootrom_map.virt) { printk(KERN_NOTICE "Failed to ioremap Cdb89712 BootROM space\n"); @@ -198,13 +198,13 @@ static int __init init_cdb89712_bootrom (void) bootrom_mtd->owner = THIS_MODULE; bootrom_mtd->erasesize = 0x10000; - + if (add_mtd_device(bootrom_mtd)) { printk("BootROM device addition failed\n"); err = -ENOMEM; goto out_probe; } - + return 0; out_probe: @@ -225,16 +225,16 @@ out: static int __init init_cdb89712_maps(void) { - printk(KERN_INFO "Cirrus CDB89712 MTD mappings:\n Flash 0x%x at 0x%x\n SRAM 0x%x at 0x%x\n BootROM 0x%x at 0x%x\n", + printk(KERN_INFO "Cirrus CDB89712 MTD mappings:\n Flash 0x%x at 0x%x\n SRAM 0x%x at 0x%x\n BootROM 0x%x at 0x%x\n", FLASH_SIZE, FLASH_START, SRAM_SIZE, SRAM_START, BOOTROM_SIZE, BOOTROM_START); init_cdb89712_flash(); init_cdb89712_sram(); init_cdb89712_bootrom(); - + return 0; } - + static void __exit cleanup_cdb89712_maps(void) { @@ -244,7 +244,7 @@ static void __exit cleanup_cdb89712_maps(void) iounmap((void *)cdb89712_sram_map.virt); release_resource (&cdb89712_sram_resource); } - + if (flash_mtd) { del_mtd_device(flash_mtd); map_destroy(flash_mtd); diff --git a/drivers/mtd/maps/cfi_flagadm.c b/drivers/mtd/maps/cfi_flagadm.c index f72e4f894b3..6a8c0415bde 100644 --- a/drivers/mtd/maps/cfi_flagadm.c +++ b/drivers/mtd/maps/cfi_flagadm.c @@ -1,8 +1,8 @@ /* * Copyright © 2001 Flaga hf. Medical Devices, Kári Davíðsson * - * $Id: cfi_flagadm.c,v 1.14 2004/11/04 13:24:14 gleixner Exp $ - * + * $Id: cfi_flagadm.c,v 1.15 2005/11/07 11:14:26 gleixner Exp $ + * * 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 @@ -42,7 +42,7 @@ */ #define FLASH_PHYS_ADDR 0x40000000 -#define FLASH_SIZE 0x400000 +#define FLASH_SIZE 0x400000 #define FLASH_PARTITION0_ADDR 0x00000000 #define FLASH_PARTITION0_SIZE 0x00020000 @@ -79,7 +79,7 @@ struct mtd_partition flagadm_parts[] = { .offset = FLASH_PARTITION2_ADDR, .size = FLASH_PARTITION2_SIZE }, - { + { .name = "Persistant storage", .offset = FLASH_PARTITION3_ADDR, .size = FLASH_PARTITION3_SIZE @@ -91,10 +91,10 @@ struct mtd_partition flagadm_parts[] = { static struct mtd_info *mymtd; int __init init_flagadm(void) -{ +{ printk(KERN_NOTICE "FlagaDM flash device: %x at %x\n", FLASH_SIZE, FLASH_PHYS_ADDR); - + flagadm_map.phys = FLASH_PHYS_ADDR; flagadm_map.virt = ioremap(FLASH_PHYS_ADDR, FLASH_SIZE); diff --git a/drivers/mtd/maps/cstm_mips_ixx.c b/drivers/mtd/maps/cstm_mips_ixx.c index ae9252fbf17..a370953c151 100644 --- a/drivers/mtd/maps/cstm_mips_ixx.c +++ b/drivers/mtd/maps/cstm_mips_ixx.c @@ -1,10 +1,10 @@ /* - * $Id: cstm_mips_ixx.c,v 1.12 2004/11/04 13:24:14 gleixner Exp $ + * $Id: cstm_mips_ixx.c,v 1.14 2005/11/07 11:14:26 gleixner Exp $ * * Mapping of a custom board with both AMD CFI and JEDEC flash in partitions. * Config with both CFI and JEDEC device support. * - * Basically physmap.c with the addition of partitions and + * Basically physmap.c with the addition of partitions and * an array of mapping info to accomodate more than one flash type per board. * * Copyright 2000 MontaVista Software Inc. @@ -69,7 +69,7 @@ void cstm_mips_ixx_set_vpp(struct map_info *map,int vpp) __u16 data; __u8 data1; static u8 first = 1; - + // Set GPIO port B pin3 to high data = *(__u16 *)(CC_GPBCR); data = (data & 0xff0f) | 0x0040; @@ -85,7 +85,7 @@ void cstm_mips_ixx_set_vpp(struct map_info *map,int vpp) } else { if (!--vpp_count) { __u16 data; - + // Set GPIO port B pin3 to high data = *(__u16 *)(CC_GPBCR); data = (data & 0xff3f) | 0x0040; @@ -109,8 +109,8 @@ struct cstm_mips_ixx_info { }; #if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) -#define PHYSMAP_NUMBER 1 // number of board desc structs needed, one per contiguous flash type -const struct cstm_mips_ixx_info cstm_mips_ixx_board_desc[PHYSMAP_NUMBER] = +#define PHYSMAP_NUMBER 1 // number of board desc structs needed, one per contiguous flash type +const struct cstm_mips_ixx_info cstm_mips_ixx_board_desc[PHYSMAP_NUMBER] = { { // 28F128J3A in 2x16 configuration "big flash", // name @@ -131,10 +131,10 @@ static struct mtd_partition cstm_mips_ixx_partitions[PHYSMAP_NUMBER][MAX_PHYSMAP }, }; #else /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */ -#define PHYSMAP_NUMBER 1 // number of board desc structs needed, one per contiguous flash type -const struct cstm_mips_ixx_info cstm_mips_ixx_board_desc[PHYSMAP_NUMBER] = +#define PHYSMAP_NUMBER 1 // number of board desc structs needed, one per contiguous flash type +const struct cstm_mips_ixx_info cstm_mips_ixx_board_desc[PHYSMAP_NUMBER] = { - { + { "MTD flash", // name CONFIG_MTD_CSTM_MIPS_IXX_START, // window_addr CONFIG_MTD_CSTM_MIPS_IXX_LEN, // window_size @@ -144,7 +144,7 @@ const struct cstm_mips_ixx_info cstm_mips_ixx_board_desc[PHYSMAP_NUMBER] = }; static struct mtd_partition cstm_mips_ixx_partitions[PHYSMAP_NUMBER][MAX_PHYSMAP_PARTITIONS] = { -{ +{ { .name = "main partition", .size = CONFIG_MTD_CSTM_MIPS_IXX_LEN, @@ -165,7 +165,7 @@ int __init init_cstm_mips_ixx(void) /* Initialize mapping */ for (i=0;iowner = THIS_MODULE; /* Create MTD devices for each partition. */ add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS); - + return 0; } diff --git a/drivers/mtd/maps/dc21285.c b/drivers/mtd/maps/dc21285.c index e5b74169fde..701620b6bae 100644 --- a/drivers/mtd/maps/dc21285.c +++ b/drivers/mtd/maps/dc21285.c @@ -4,8 +4,8 @@ * (C) 2000 Nicolas Pitre * * This code is GPL - * - * $Id: dc21285.c,v 1.22 2004/11/01 13:39:21 rmk Exp $ + * + * $Id: dc21285.c,v 1.24 2005/11/07 11:14:26 gleixner Exp $ */ #include #include @@ -27,9 +27,9 @@ static struct mtd_info *dc21285_mtd; #ifdef CONFIG_ARCH_NETWINDER -/* +/* * This is really ugly, but it seams to be the only - * realiable way to do it, as the cpld state machine + * realiable way to do it, as the cpld state machine * is unpredictible. So we have a 25us penalty per * write access. */ @@ -150,7 +150,7 @@ static struct map_info dc21285_map = { static struct mtd_partition *dc21285_parts; static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; #endif - + static int __init init_dc21285(void) { @@ -160,20 +160,20 @@ static int __init init_dc21285(void) /* Determine bankwidth */ switch (*CSR_SA110_CNTL & (3<<14)) { - case SA110_CNTL_ROMWIDTH_8: + case SA110_CNTL_ROMWIDTH_8: dc21285_map.bankwidth = 1; dc21285_map.read = dc21285_read8; dc21285_map.write = dc21285_write8; dc21285_map.copy_to = dc21285_copy_to_8; break; - case SA110_CNTL_ROMWIDTH_16: - dc21285_map.bankwidth = 2; + case SA110_CNTL_ROMWIDTH_16: + dc21285_map.bankwidth = 2; dc21285_map.read = dc21285_read16; dc21285_map.write = dc21285_write16; dc21285_map.copy_to = dc21285_copy_to_16; break; - case SA110_CNTL_ROMWIDTH_32: - dc21285_map.bankwidth = 4; + case SA110_CNTL_ROMWIDTH_32: + dc21285_map.bankwidth = 4; dc21285_map.read = dc21285_read32; dc21285_map.write = dc21285_write32; dc21285_map.copy_to = dc21285_copy_to_32; @@ -201,20 +201,20 @@ static int __init init_dc21285(void) if (!dc21285_mtd) { iounmap(dc21285_map.virt); return -ENXIO; - } - + } + dc21285_mtd->owner = THIS_MODULE; #ifdef CONFIG_MTD_PARTITIONS nrparts = parse_mtd_partitions(dc21285_mtd, probes, &dc21285_parts, 0); if (nrparts > 0) add_mtd_partitions(dc21285_mtd, dc21285_parts, nrparts); - else -#endif + else +#endif add_mtd_device(dc21285_mtd); - + if(machine_is_ebsa285()) { - /* + /* * Flash timing is determined with bits 19-16 of the * CSR_SA110_CNTL. The value is the number of wait cycles, or * 0 for 16 cycles (the default). Cycles are 20 ns. @@ -227,7 +227,7 @@ static int __init init_dc21285(void) /* tristate time */ *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x0f000000) | (7 << 24)); } - + return 0; } diff --git a/drivers/mtd/maps/dilnetpc.c b/drivers/mtd/maps/dilnetpc.c index f99519692cb..b51c757817d 100644 --- a/drivers/mtd/maps/dilnetpc.c +++ b/drivers/mtd/maps/dilnetpc.c @@ -14,7 +14,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: dilnetpc.c,v 1.17 2004/11/28 09:40:39 dwmw2 Exp $ + * $Id: dilnetpc.c,v 1.20 2005/11/07 11:14:26 gleixner Exp $ * * The DIL/Net PC is a tiny embedded PC board made by SSV Embedded Systems * featuring the AMD Elan SC410 processor. There are two variants of this @@ -272,13 +272,13 @@ static struct map_info dnpc_map = { static struct mtd_partition partition_info[]= { - { - .name = "ADNP boot", - .offset = 0, + { + .name = "ADNP boot", + .offset = 0, .size = 0xf0000, }, - { - .name = "ADNP system BIOS", + { + .name = "ADNP system BIOS", .offset = MTDPART_OFS_NXTBLK, .size = 0x10000, #ifdef DNPC_BIOS_BLOCKS_WRITEPROTECTED @@ -291,7 +291,7 @@ static struct mtd_partition partition_info[]= .size = 0x2f0000, }, { - .name = "ADNP system BIOS entry", + .name = "ADNP system BIOS entry", .offset = MTDPART_OFS_NXTBLK, .size = MTDPART_SIZ_FULL, #ifdef DNPC_BIOS_BLOCKS_WRITEPROTECTED @@ -325,9 +325,9 @@ static struct mtd_info *merged_mtd; static struct mtd_partition higlvl_partition_info[]= { - { - .name = "ADNP boot block", - .offset = 0, + { + .name = "ADNP boot block", + .offset = 0, .size = CONFIG_MTD_DILNETPC_BOOTSIZE, }, { @@ -335,8 +335,8 @@ static struct mtd_partition higlvl_partition_info[]= .offset = MTDPART_OFS_NXTBLK, .size = ADNP_WINDOW_SIZE-CONFIG_MTD_DILNETPC_BOOTSIZE-0x20000, }, - { - .name = "ADNP system BIOS + BIOS Entry", + { + .name = "ADNP system BIOS + BIOS Entry", .offset = MTDPART_OFS_NXTBLK, .size = MTDPART_SIZ_FULL, #ifdef DNPC_BIOS_BLOCKS_WRITEPROTECTED @@ -371,7 +371,7 @@ static int __init init_dnpc(void) /* ** determine hardware (DNP/ADNP/invalid) - */ + */ if((is_dnp = dnp_adnp_probe()) < 0) return -ENXIO; @@ -397,13 +397,13 @@ static int __init init_dnpc(void) ++dnpc_map.name; for(i = 0; i < NUM_PARTITIONS; i++) ++partition_info[i].name; - higlvl_partition_info[1].size = DNP_WINDOW_SIZE - + higlvl_partition_info[1].size = DNP_WINDOW_SIZE - CONFIG_MTD_DILNETPC_BOOTSIZE - 0x20000; for(i = 0; i < NUM_HIGHLVL_PARTITIONS; i++) ++higlvl_partition_info[i].name; } - printk(KERN_NOTICE "DIL/Net %s flash: 0x%lx at 0x%lx\n", + printk(KERN_NOTICE "DIL/Net %s flash: 0x%lx at 0x%lx\n", is_dnp ? "DNPC" : "ADNP", dnpc_map.size, dnpc_map.phys); dnpc_map.virt = ioremap_nocache(dnpc_map.phys, dnpc_map.size); @@ -436,7 +436,7 @@ static int __init init_dnpc(void) iounmap(dnpc_map.virt); return -ENXIO; } - + mymtd->owner = THIS_MODULE; /* diff --git a/drivers/mtd/maps/dmv182.c b/drivers/mtd/maps/dmv182.c index b9bc63503e2..b993ac01a9a 100644 --- a/drivers/mtd/maps/dmv182.c +++ b/drivers/mtd/maps/dmv182.c @@ -1,10 +1,10 @@ /* * drivers/mtd/maps/svme182.c - * + * * Flash map driver for the Dy4 SVME182 board - * - * $Id: dmv182.c,v 1.5 2004/11/04 13:24:14 gleixner Exp $ + * + * $Id: dmv182.c,v 1.6 2005/11/07 11:14:26 gleixner Exp $ * * Copyright 2003-2004, TimeSys Corporation * @@ -104,7 +104,7 @@ static int __init init_svme182(void) partitions = svme182_partitions; svme182_map.virt = ioremap(FLASH_BASE_ADDR, svme182_map.size); - + if (svme182_map.virt == 0) { printk("Failed to ioremap FLASH memory area.\n"); return -EIO; diff --git a/drivers/mtd/maps/ebony.c b/drivers/mtd/maps/ebony.c index b9d9cf4854b..c0daf58357c 100644 --- a/drivers/mtd/maps/ebony.c +++ b/drivers/mtd/maps/ebony.c @@ -1,6 +1,6 @@ /* - * $Id: ebony.c,v 1.15 2004/12/09 18:39:54 holindho Exp $ - * + * $Id: ebony.c,v 1.16 2005/11/07 11:14:26 gleixner Exp $ + * * Mapping for Ebony user flash * * Matt Porter @@ -85,7 +85,7 @@ int __init init_ebony(void) small_flash_base = EBONY_SMALL_FLASH_LOW2; else small_flash_base = EBONY_SMALL_FLASH_LOW1; - + if (EBONY_BOOT_SMALL_FLASH(fpga0_reg) && !EBONY_ONBRD_FLASH_EN(fpga0_reg)) large_flash_base = EBONY_LARGE_FLASH_LOW; diff --git a/drivers/mtd/maps/edb7312.c b/drivers/mtd/maps/edb7312.c index 8b0da394f3f..b48a3473ffc 100644 --- a/drivers/mtd/maps/edb7312.c +++ b/drivers/mtd/maps/edb7312.c @@ -1,10 +1,10 @@ /* - * $Id: edb7312.c,v 1.13 2004/11/04 13:24:14 gleixner Exp $ + * $Id: edb7312.c,v 1.14 2005/11/07 11:14:27 gleixner Exp $ * * Handle mapping of the NOR flash on Cogent EDB7312 boards * * Copyright 2002 SYSGO Real-Time Solutions GmbH - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. @@ -46,7 +46,7 @@ struct map_info edb7312nor_map = { #ifdef CONFIG_MTD_PARTITIONS /* - * MTD partitioning stuff + * MTD partitioning stuff */ static struct mtd_partition static_partitions[3] = { @@ -80,7 +80,7 @@ int __init init_edb7312nor(void) const char **type; const char *part_type = 0; - printk(KERN_NOTICE MSG_PREFIX "0x%08x at 0x%08x\n", + printk(KERN_NOTICE MSG_PREFIX "0x%08x at 0x%08x\n", WINDOW_SIZE, WINDOW_ADDR); edb7312nor_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE); @@ -88,7 +88,7 @@ int __init init_edb7312nor(void) printk(MSG_PREFIX "failed to ioremap\n"); return -EIO; } - + simple_map_init(&edb7312nor_map); mymtd = 0; diff --git a/drivers/mtd/maps/epxa10db-flash.c b/drivers/mtd/maps/epxa10db-flash.c index 1df6188926b..265b079fe93 100644 --- a/drivers/mtd/maps/epxa10db-flash.c +++ b/drivers/mtd/maps/epxa10db-flash.c @@ -5,7 +5,7 @@ * Copyright (C) 2001 Altera Corporation * Copyright (C) 2001 Red Hat, Inc. * - * $Id: epxa10db-flash.c,v 1.13 2004/11/04 13:24:14 gleixner Exp $ + * $Id: epxa10db-flash.c,v 1.15 2005/11/07 11:14:27 gleixner Exp $ * * 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 @@ -62,7 +62,7 @@ static const char *probes[] = { "RedBoot", "afs", NULL }; static int __init epxa_mtd_init(void) { int i; - + printk(KERN_NOTICE "%s flash device: 0x%x at 0x%x\n", BOARD_NAME, FLASH_SIZE, FLASH_START); epxa_map.virt = ioremap(FLASH_START, FLASH_SIZE); @@ -126,8 +126,8 @@ static void __exit epxa_mtd_cleanup(void) } -/* - * This will do for now, once we decide which bootldr we're finally +/* + * This will do for now, once we decide which bootldr we're finally * going to use then we'll remove this function and do it properly * * Partions are currently (as offsets from base of flash): @@ -140,7 +140,7 @@ static int __init epxa_default_partitions(struct mtd_info *master, struct mtd_pa struct mtd_partition *parts; int ret, i; int npartitions = 0; - char *names; + char *names; const char *name = "jffs"; printk("Using default partitions for %s\n",BOARD_NAME); @@ -152,7 +152,7 @@ static int __init epxa_default_partitions(struct mtd_info *master, struct mtd_pa goto out; } i=0; - names = (char *)&parts[npartitions]; + names = (char *)&parts[npartitions]; parts[i].name = names; names += strlen(name) + 1; strcpy(parts[i].name, name); diff --git a/drivers/mtd/maps/fortunet.c b/drivers/mtd/maps/fortunet.c index 00f7bbe5479..c6bf4e1219e 100644 --- a/drivers/mtd/maps/fortunet.c +++ b/drivers/mtd/maps/fortunet.c @@ -1,6 +1,6 @@ /* fortunet.c memory map * - * $Id: fortunet.c,v 1.9 2004/11/04 13:24:14 gleixner Exp $ + * $Id: fortunet.c,v 1.11 2005/11/07 11:14:27 gleixner Exp $ */ #include @@ -212,7 +212,7 @@ int __init init_fortunet(void) map_regions[ix].map_info.phys = map_regions[ix].window_addr_physical, - map_regions[ix].map_info.virt = + map_regions[ix].map_info.virt = ioremap_nocache( map_regions[ix].window_addr_physical, map_regions[ix].map_info.size); diff --git a/drivers/mtd/maps/h720x-flash.c b/drivers/mtd/maps/h720x-flash.c index c73828171d9..31909482110 100644 --- a/drivers/mtd/maps/h720x-flash.c +++ b/drivers/mtd/maps/h720x-flash.c @@ -1,11 +1,11 @@ /* - * Flash memory access on Hynix GMS30C7201/HMS30C7202 based + * Flash memory access on Hynix GMS30C7201/HMS30C7202 based * evaluation boards - * - * $Id: h720x-flash.c,v 1.11 2004/11/04 13:24:14 gleixner Exp $ + * + * $Id: h720x-flash.c,v 1.12 2005/11/07 11:14:27 gleixner Exp $ * * (C) 2002 Jungjun Kim - * 2003 Thomas Gleixner + * 2003 Thomas Gleixner */ #include @@ -72,7 +72,7 @@ int __init h720x_mtd_init(void) { char *part_type = NULL; - + h720x_map.virt = ioremap(FLASH_PHYS, FLASH_SIZE); if (!h720x_map.virt) { @@ -91,7 +91,7 @@ int __init h720x_mtd_init(void) h720x_map.bankwidth = 2; mymtd = do_map_probe("cfi_probe", &h720x_map); } - + if (mymtd) { mymtd->owner = THIS_MODULE; @@ -124,11 +124,11 @@ static void __exit h720x_mtd_cleanup(void) del_mtd_partitions(mymtd); map_destroy(mymtd); } - + /* Free partition info, if commandline partition was used */ if (mtd_parts && (mtd_parts != h720x_partitions)) kfree (mtd_parts); - + if (h720x_map.virt) { iounmap((void *)h720x_map.virt); h720x_map.virt = 0; diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c index e505207cd48..aa9720ec4cd 100644 --- a/drivers/mtd/maps/ichxrom.c +++ b/drivers/mtd/maps/ichxrom.c @@ -2,7 +2,7 @@ * ichxrom.c * * Normal mappings of chips in physical memory - * $Id: ichxrom.c,v 1.18 2005/07/07 10:26:20 dwmw2 Exp $ + * $Id: ichxrom.c,v 1.19 2005/11/07 11:14:27 gleixner Exp $ */ #include @@ -101,7 +101,7 @@ static int __devinit ichxrom_init_one (struct pci_dev *pdev, * you can only really attach a FWH to an ICHX there * a number of simplifications you can make. * - * Also you can page firmware hubs if an 8MB window isn't enough + * Also you can page firmware hubs if an 8MB window isn't enough * but don't currently handle that case either. */ window->pdev = pdev; @@ -144,7 +144,7 @@ static int __devinit ichxrom_init_one (struct pci_dev *pdev, window->phys = 0xfff00000; } else if ((byte & 0x80) == 0x80) { - window->phys = 0xfff80000; + window->phys = 0xfff80000; } if (window->phys == 0) { @@ -233,7 +233,7 @@ static int __devinit ichxrom_init_one (struct pci_dev *pdev, * in a factory setting. So in-place programming * needs to use a different method. */ - for(map->map.bankwidth = 32; map->map.bankwidth; + for(map->map.bankwidth = 32; map->map.bankwidth; map->map.bankwidth >>= 1) { char **probe_type; @@ -286,7 +286,7 @@ static int __devinit ichxrom_init_one (struct pci_dev *pdev, for(i = 0; i < cfi->numchips; i++) { cfi->chips[i].start += offset; } - + /* Now that the mtd devices is complete claim and export it */ map->mtd->owner = THIS_MODULE; if (add_mtd_device(map->mtd)) { @@ -325,11 +325,11 @@ static void __devexit ichxrom_remove_one (struct pci_dev *pdev) } static struct pci_device_id ichxrom_pci_tbl[] __devinitdata = { - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, PCI_ANY_ID, PCI_ANY_ID, }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, PCI_ANY_ID, PCI_ANY_ID, }, diff --git a/drivers/mtd/maps/impa7.c b/drivers/mtd/maps/impa7.c index cb39172c81d..ba7f40311a7 100644 --- a/drivers/mtd/maps/impa7.c +++ b/drivers/mtd/maps/impa7.c @@ -1,10 +1,10 @@ /* - * $Id: impa7.c,v 1.13 2004/11/04 13:24:14 gleixner Exp $ + * $Id: impa7.c,v 1.14 2005/11/07 11:14:27 gleixner Exp $ * * Handle mapping of the NOR flash on implementa A7 boards * * Copyright 2002 SYSGO Real-Time Solutions GmbH - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. @@ -55,7 +55,7 @@ static struct map_info impa7_map[NUM_FLASHBANKS] = { #ifdef CONFIG_MTD_PARTITIONS /* - * MTD partitioning stuff + * MTD partitioning stuff */ static struct mtd_partition static_partitions[] = { @@ -108,9 +108,9 @@ int __init init_impa7(void) impa7_mtd[i]->owner = THIS_MODULE; devicesfound++; #ifdef CONFIG_MTD_PARTITIONS - mtd_parts_nb[i] = parse_mtd_partitions(impa7_mtd[i], + mtd_parts_nb[i] = parse_mtd_partitions(impa7_mtd[i], probes, - &mtd_parts[i], + &mtd_parts[i], 0); if (mtd_parts_nb[i] > 0) { part_type = "command line"; @@ -121,16 +121,16 @@ int __init init_impa7(void) } printk(KERN_NOTICE MSG_PREFIX - "using %s partition definition\n", + "using %s partition definition\n", part_type); - add_mtd_partitions(impa7_mtd[i], + add_mtd_partitions(impa7_mtd[i], mtd_parts[i], mtd_parts_nb[i]); #else add_mtd_device(impa7_mtd[i]); #endif } - else + else iounmap((void *)impa7_map[i].virt); } return devicesfound == 0 ? -ENXIO : 0; diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c index d14a0185b8f..549614693ac 100644 --- a/drivers/mtd/maps/integrator-flash.c +++ b/drivers/mtd/maps/integrator-flash.c @@ -1,28 +1,28 @@ /*====================================================================== drivers/mtd/maps/integrator-flash.c: ARM Integrator flash map driver - + Copyright (C) 2000 ARM Limited Copyright (C) 2003 Deep Blue Solutions Ltd. - + 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 option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - This is access code for flashes using ARM's flash partitioning + + This is access code for flashes using ARM's flash partitioning standards. - $Id: integrator-flash.c,v 1.18 2004/11/01 13:26:15 rmk Exp $ + $Id: integrator-flash.c,v 1.20 2005/11/07 11:14:27 gleixner Exp $ ======================================================================*/ diff --git a/drivers/mtd/maps/ipaq-flash.c b/drivers/mtd/maps/ipaq-flash.c index 71240181084..fbace127df3 100644 --- a/drivers/mtd/maps/ipaq-flash.c +++ b/drivers/mtd/maps/ipaq-flash.c @@ -1,11 +1,11 @@ /* * Flash memory access on iPAQ Handhelds (either SA1100 or PXA250 based) - * + * * (C) 2000 Nicolas Pitre * (C) 2002 Hewlett-Packard Company * (C) 2003 Christian Pellegrin , : concatenation of multiple flashes - * - * $Id: ipaq-flash.c,v 1.3 2004/11/04 13:24:15 gleixner Exp $ + * + * $Id: ipaq-flash.c,v 1.5 2005/11/07 11:14:27 gleixner Exp $ */ #include @@ -107,7 +107,7 @@ static struct mtd_partition h3xxx_partitions[] = { #ifndef CONFIG_LAB mask_flags: MTD_WRITEABLE, /* force read-only */ #endif - }, + }, { name: "H3XXX root jffs2", #ifndef CONFIG_LAB @@ -148,7 +148,7 @@ static DEFINE_SPINLOCK(ipaq_vpp_lock); static void h3xxx_set_vpp(struct map_info *map, int vpp) { static int nest = 0; - + spin_lock(&ipaq_vpp_lock); if (vpp) nest++; @@ -191,7 +191,7 @@ static unsigned long cs_phys[] = { SA1100_CS3_PHYS, SA1100_CS4_PHYS, SA1100_CS5_PHYS, -#else +#else PXA_CS0_PHYS, PXA_CS1_PHYS, PXA_CS2_PHYS, @@ -216,7 +216,7 @@ int __init ipaq_mtd_init(void) /* Default flash bankwidth */ // ipaq_map.bankwidth = (MSC0 & MSC_RBW) ? 2 : 4; - + if (machine_is_h1900()) { /* For our intents, the h1900 is not a real iPAQ, so we special-case it. */ @@ -229,7 +229,7 @@ int __init ipaq_mtd_init(void) else for(i=0; isize); - + /* do we really need this debugging? --joshua 20030703 */ // printk("my_sub_mtd[%d]=%p\n", i, my_sub_mtd[i]); my_sub_mtd[i]->owner = THIS_MODULE; @@ -333,11 +333,11 @@ int __init ipaq_mtd_init(void) #else mymtd = my_sub_mtd[0]; - /* + /* *In the very near future, command line partition parsing * will use the device name as 'mtd-id' instead of a value * passed to the parse_cmdline_partitions() routine. Since - * the bootldr says 'ipaq', make sure it continues to work. + * the bootldr says 'ipaq', make sure it continues to work. */ mymtd->name = "ipaq"; @@ -385,7 +385,7 @@ int __init ipaq_mtd_init(void) */ i = parse_mtd_partitions(mymtd, part_probes, &parsed_parts, 0); - + if (i > 0) { nb_parts = parsed_nr_parts = i; parts = parsed_parts; @@ -423,10 +423,10 @@ static void __exit ipaq_mtd_cleanup(void) #endif map_destroy(mymtd); #ifdef CONFIG_MTD_CONCAT - for(i=0; i @@ -46,8 +46,8 @@ struct ixp2000_flash_info { }; static inline unsigned long flash_bank_setup(struct map_info *map, unsigned long ofs) -{ - unsigned long (*set_bank)(unsigned long) = +{ + unsigned long (*set_bank)(unsigned long) = (unsigned long(*)(unsigned long))map->map_priv_2; return (set_bank ? set_bank(ofs) : ofs); @@ -55,8 +55,8 @@ static inline unsigned long flash_bank_setup(struct map_info *map, unsigned long #ifdef __ARMEB__ /* - * Rev A0 and A1 of IXP2400 silicon have a broken addressing unit which - * causes the lower address bits to be XORed with 0x11 on 8 bit accesses + * Rev A0 and A1 of IXP2400 silicon have a broken addressing unit which + * causes the lower address bits to be XORed with 0x11 on 8 bit accesses * and XORed with 0x10 on 16 bit accesses. See the spec update, erratum 44. */ static int erratum44_workaround = 0; @@ -90,7 +90,7 @@ static void ixp2000_flash_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) { from = flash_bank_setup(map, from); - while(len--) + while(len--) *(__u8 *) to++ = *(__u8 *)(map->map_priv_1 + from++); } @@ -149,11 +149,11 @@ static int ixp2000_flash_probe(struct device *_dev) static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; struct platform_device *dev = to_platform_device(_dev); struct ixp2000_flash_data *ixp_data = dev->dev.platform_data; - struct flash_platform_data *plat; + struct flash_platform_data *plat; struct ixp2000_flash_info *info; unsigned long window_size; int err = -1; - + if (!ixp_data) return -ENODEV; @@ -162,7 +162,7 @@ static int ixp2000_flash_probe(struct device *_dev) return -ENODEV; window_size = dev->resource->end - dev->resource->start + 1; - dev_info(_dev, "Probe of IXP2000 flash(%d banks x %dMiB)\n", + dev_info(_dev, "Probe of IXP2000 flash(%d banks x %dMiB)\n", ixp_data->nr_banks, ((u32)window_size >> 20)); if (plat->width != 1) { @@ -175,7 +175,7 @@ static int ixp2000_flash_probe(struct device *_dev) if(!info) { err = -ENOMEM; goto Error; - } + } memzero(info, sizeof(struct ixp2000_flash_info)); dev_set_drvdata(&dev->dev, info); @@ -185,7 +185,7 @@ static int ixp2000_flash_probe(struct device *_dev) * not attempt to do a direct access on us. */ info->map.phys = NO_XIP; - + info->nr_banks = ixp_data->nr_banks; info->map.size = ixp_data->nr_banks * window_size; info->map.bankwidth = 1; @@ -201,8 +201,8 @@ static int ixp2000_flash_probe(struct device *_dev) info->map.copy_from = ixp2000_flash_copy_from; info->map.copy_to = ixp2000_flash_copy_to; - info->res = request_mem_region(dev->resource->start, - dev->resource->end - dev->resource->start + 1, + info->res = request_mem_region(dev->resource->start, + dev->resource->end - dev->resource->start + 1, dev->dev.bus_id); if (!info->res) { dev_err(_dev, "Could not reserve memory region\n"); @@ -210,7 +210,7 @@ static int ixp2000_flash_probe(struct device *_dev) goto Error; } - info->map.map_priv_1 = (unsigned long) ioremap(dev->resource->start, + info->map.map_priv_1 = (unsigned long) ioremap(dev->resource->start, dev->resource->end - dev->resource->start + 1); if (!info->map.map_priv_1) { dev_err(_dev, "Failed to ioremap flash region\n"); diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c index c510c736ed9..471553a3da6 100644 --- a/drivers/mtd/maps/ixp4xx.c +++ b/drivers/mtd/maps/ixp4xx.c @@ -1,5 +1,5 @@ /* - * $Id: ixp4xx.c,v 1.11 2005/11/06 11:15:51 gleixner Exp $ + * $Id: ixp4xx.c,v 1.12 2005/11/07 11:14:27 gleixner Exp $ * * drivers/mtd/maps/ixp4xx.c * @@ -72,7 +72,7 @@ static void ixp4xx_copy_from(struct map_info *map, void *to, dest[len - 1] = BYTE0(le16_to_cpu(readw(src + 2*i))); } -/* +/* * Unaligned writes are ignored, causing the 8-bit * probe to fail and proceed to the 16-bit probe (which succeeds). */ @@ -82,7 +82,7 @@ static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long writew(cpu_to_le16(d.x[0]), map->virt + adr); } -/* +/* * Fast write16 function without the probing check above */ static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr) @@ -151,7 +151,7 @@ static int ixp4xx_flash_probe(struct device *_dev) if(!info) { err = -ENOMEM; goto Error; - } + } memzero(info, sizeof(struct ixp4xx_flash_info)); dev_set_drvdata(&dev->dev, info); @@ -174,8 +174,8 @@ static int ixp4xx_flash_probe(struct device *_dev) info->map.write = ixp4xx_probe_write16, info->map.copy_from = ixp4xx_copy_from, - info->res = request_mem_region(dev->resource->start, - dev->resource->end - dev->resource->start + 1, + info->res = request_mem_region(dev->resource->start, + dev->resource->end - dev->resource->start + 1, "IXP4XXFlash"); if (!info->res) { printk(KERN_ERR "IXP4XXFlash: Could not reserve memory region\n"); @@ -198,7 +198,7 @@ static int ixp4xx_flash_probe(struct device *_dev) goto Error; } info->mtd->owner = THIS_MODULE; - + /* Use the fast version */ info->map.write = ixp4xx_write16, diff --git a/drivers/mtd/maps/l440gx.c b/drivers/mtd/maps/l440gx.c index b08668212ab..851bf957605 100644 --- a/drivers/mtd/maps/l440gx.c +++ b/drivers/mtd/maps/l440gx.c @@ -1,5 +1,5 @@ /* - * $Id: l440gx.c,v 1.17 2004/11/28 09:40:39 dwmw2 Exp $ + * $Id: l440gx.c,v 1.18 2005/11/07 11:14:27 gleixner Exp $ * * BIOS Flash chip on Intel 440GX board. * @@ -49,7 +49,7 @@ static struct map_info l440gx_map = { .bankwidth = BUSWIDTH, .phys = WINDOW_ADDR, #if 0 - /* FIXME verify that this is the + /* FIXME verify that this is the * appripriate code for vpp enable/disable */ .set_vpp = l440gx_set_vpp @@ -62,10 +62,10 @@ static int __init init_l440gx(void) struct resource *pm_iobase; __u16 word; - dev = pci_find_device(PCI_VENDOR_ID_INTEL, + dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, NULL); - pm_dev = pci_find_device(PCI_VENDOR_ID_INTEL, + pm_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL); if (!dev || !pm_dev) { @@ -82,10 +82,10 @@ static int __init init_l440gx(void) simple_map_init(&l440gx_map); printk(KERN_NOTICE "window_addr = 0x%08lx\n", (unsigned long)l440gx_map.virt); - /* Setup the pm iobase resource + /* Setup the pm iobase resource * This code should move into some kind of generic bridge * driver but for the moment I'm content with getting the - * allocation correct. + * allocation correct. */ pm_iobase = &pm_dev->resource[PIIXE_IOBASE_RESOURCE]; if (!(pm_iobase->flags & IORESOURCE_IO)) { @@ -110,7 +110,7 @@ static int __init init_l440gx(void) /* Set the iobase */ iobase = pm_iobase->start; pci_write_config_dword(pm_dev, 0x40, iobase | 1); - + /* Set XBCS# */ pci_read_config_word(dev, 0x4e, &word); @@ -122,7 +122,7 @@ static int __init init_l440gx(void) /* Enable the gate on the WE line */ outb(inb(TRIBUF_PORT) & ~1, TRIBUF_PORT); - + printk(KERN_NOTICE "Enabled WE line to L440GX BIOS flash chip.\n"); mymtd = do_map_probe("jedec_probe", &l440gx_map); @@ -145,7 +145,7 @@ static void __exit cleanup_l440gx(void) { del_mtd_device(mymtd); map_destroy(mymtd); - + iounmap(l440gx_map.virt); } diff --git a/drivers/mtd/maps/lubbock-flash.c b/drivers/mtd/maps/lubbock-flash.c index 2337e0c4675..10f681f39c9 100644 --- a/drivers/mtd/maps/lubbock-flash.c +++ b/drivers/mtd/maps/lubbock-flash.c @@ -1,11 +1,11 @@ /* - * $Id: lubbock-flash.c,v 1.19 2004/11/04 13:24:15 gleixner Exp $ + * $Id: lubbock-flash.c,v 1.21 2005/11/07 11:14:27 gleixner Exp $ * * Map driver for the Lubbock developer platform. * * Author: Nicolas Pitre * Copyright: (C) 2001 MontaVista Software Inc. - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. @@ -76,7 +76,7 @@ static int __init init_lubbock(void) int flashboot = (LUB_CONF_SWITCHES & 1); int ret = 0, i; - lubbock_maps[0].bankwidth = lubbock_maps[1].bankwidth = + lubbock_maps[0].bankwidth = lubbock_maps[1].bankwidth = (BOOT_DEF & 1) ? 2 : 4; /* Compensate for the nROMBT switch which swaps the flash banks */ @@ -100,11 +100,11 @@ static int __init init_lubbock(void) simple_map_init(&lubbock_maps[i]); printk(KERN_NOTICE "Probing %s at physical address 0x%08lx (%d-bit bankwidth)\n", - lubbock_maps[i].name, lubbock_maps[i].phys, + lubbock_maps[i].name, lubbock_maps[i].phys, lubbock_maps[i].bankwidth * 8); mymtds[i] = do_map_probe("cfi_probe", &lubbock_maps[i]); - + if (!mymtds[i]) { iounmap((void *)lubbock_maps[i].virt); if (lubbock_maps[i].cached) @@ -124,7 +124,7 @@ static int __init init_lubbock(void) if (!mymtds[0] && !mymtds[1]) return ret; - + for (i = 0; i < 2; i++) { if (!mymtds[i]) { printk(KERN_WARNING "%s is absent. Skipping\n", lubbock_maps[i].name); @@ -151,7 +151,7 @@ static void __exit cleanup_lubbock(void) if (nr_parsed_parts[i] || !i) del_mtd_partitions(mymtds[i]); else - del_mtd_device(mymtds[i]); + del_mtd_device(mymtds[i]); map_destroy(mymtds[i]); iounmap((void *)lubbock_maps[i].virt); diff --git a/drivers/mtd/maps/mainstone-flash.c b/drivers/mtd/maps/mainstone-flash.c index da0f8a69262..eaa4bbb868a 100644 --- a/drivers/mtd/maps/mainstone-flash.c +++ b/drivers/mtd/maps/mainstone-flash.c @@ -5,7 +5,7 @@ * * Author: Nicolas Pitre * Copyright: (C) 2001 MontaVista Software Inc. - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. @@ -91,27 +91,27 @@ static int __init init_mainstone(void) mainstone_maps[i].virt = ioremap(mainstone_maps[i].phys, WINDOW_SIZE); if (!mainstone_maps[i].virt) { - printk(KERN_WARNING "Failed to ioremap %s\n", + printk(KERN_WARNING "Failed to ioremap %s\n", mainstone_maps[i].name); if (!ret) ret = -ENOMEM; continue; } - mainstone_maps[i].cached = + mainstone_maps[i].cached = ioremap_cached(mainstone_maps[i].phys, WINDOW_SIZE); if (!mainstone_maps[i].cached) printk(KERN_WARNING "Failed to ioremap cached %s\n", mainstone_maps[i].name); simple_map_init(&mainstone_maps[i]); - printk(KERN_NOTICE + printk(KERN_NOTICE "Probing %s at physical address 0x%08lx" " (%d-bit bankwidth)\n", - mainstone_maps[i].name, mainstone_maps[i].phys, + mainstone_maps[i].name, mainstone_maps[i].phys, mainstone_maps[i].bankwidth * 8); mymtds[i] = do_map_probe("cfi_probe", &mainstone_maps[i]); - + if (!mymtds[i]) { iounmap((void *)mainstone_maps[i].virt); if (mainstone_maps[i].cached) @@ -131,21 +131,21 @@ static int __init init_mainstone(void) if (!mymtds[0] && !mymtds[1]) return ret; - + for (i = 0; i < 2; i++) { if (!mymtds[i]) { - printk(KERN_WARNING "%s is absent. Skipping\n", + printk(KERN_WARNING "%s is absent. Skipping\n", mainstone_maps[i].name); } else if (nr_parsed_parts[i]) { - add_mtd_partitions(mymtds[i], parsed_parts[i], + add_mtd_partitions(mymtds[i], parsed_parts[i], nr_parsed_parts[i]); } else if (!i) { printk("Using static partitions on %s\n", mainstone_maps[i].name); - add_mtd_partitions(mymtds[i], mainstone_partitions, + add_mtd_partitions(mymtds[i], mainstone_partitions, ARRAY_SIZE(mainstone_partitions)); } else { - printk("Registering %s as whole device\n", + printk("Registering %s as whole device\n", mainstone_maps[i].name); add_mtd_device(mymtds[i]); } diff --git a/drivers/mtd/maps/mbx860.c b/drivers/mtd/maps/mbx860.c index c5c6901a476..06b11872784 100644 --- a/drivers/mtd/maps/mbx860.c +++ b/drivers/mtd/maps/mbx860.c @@ -1,11 +1,11 @@ /* - * $Id: mbx860.c,v 1.8 2004/11/04 13:24:15 gleixner Exp $ + * $Id: mbx860.c,v 1.9 2005/11/07 11:14:27 gleixner Exp $ * * Handle mapping of the flash on MBX860 boards * * Author: Anton Todorov * Copyright: (C) 2001 Emness Technology - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. @@ -46,7 +46,7 @@ static struct mtd_partition partition_info[]={ { .name = "MBX flash APPLICATION partition", .offset = (BOOT_PARTITION_SIZE_KiB+KERNEL_PARTITION_SIZE_KiB)*1024 } }; - + static struct mtd_info *mymtd; diff --git a/drivers/mtd/maps/mtx-1_flash.c b/drivers/mtd/maps/mtx-1_flash.c index 43f4416a611..d1e66e18674 100644 --- a/drivers/mtd/maps/mtx-1_flash.c +++ b/drivers/mtd/maps/mtx-1_flash.c @@ -1,7 +1,7 @@ /* * Flash memory access on 4G Systems MTX-1 boards * - * $Id: mtx-1_flash.c,v 1.1 2005/09/18 10:46:41 joern Exp $ + * $Id: mtx-1_flash.c,v 1.2 2005/11/07 11:14:27 gleixner Exp $ * * (C) 2005 Bruno Randolf * (C) 2005 Jörn Engel @@ -66,7 +66,7 @@ int __init mtx1_mtd_init(void) mtx1_mtd->owner = THIS_MODULE; - ret = add_mtd_partitions(mtx1_mtd, mtx1_partitions, + ret = add_mtd_partitions(mtx1_mtd, mtx1_partitions, ARRAY_SIZE(mtx1_partitions)); if (ret) goto err; diff --git a/drivers/mtd/maps/netsc520.c b/drivers/mtd/maps/netsc520.c index ab7e6358d28..33060a31572 100644 --- a/drivers/mtd/maps/netsc520.c +++ b/drivers/mtd/maps/netsc520.c @@ -3,7 +3,7 @@ * Copyright (C) 2001 Mark Langsdorf (mark.langsdorf@amd.com) * based on sc520cdp.c by Sysgo Real-Time Solutions GmbH * - * $Id: netsc520.c,v 1.13 2004/11/28 09:40:40 dwmw2 Exp $ + * $Id: netsc520.c,v 1.14 2005/11/07 11:14:27 gleixner Exp $ * * 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 @@ -38,7 +38,7 @@ ** The single, 16 megabyte flash bank is divided into four virtual ** partitions. The first partition is 768 KiB and is intended to ** store the kernel image loaded by the bootstrap loader. The second -** partition is 256 KiB and holds the BIOS image. The third +** partition is 256 KiB and holds the BIOS image. The third ** partition is 14.5 MiB and is intended for the flash file system ** image. The last partition is 512 KiB and contains another copy ** of the BIOS image and the reset vector. @@ -51,28 +51,28 @@ ** recoverable afterwards. */ -/* partition_info gives details on the logical partitions that the split the +/* partition_info gives details on the logical partitions that the split the * single flash device into. If the size if zero we use up to the end of the * device. */ static struct mtd_partition partition_info[]={ - { - .name = "NetSc520 boot kernel", - .offset = 0, + { + .name = "NetSc520 boot kernel", + .offset = 0, .size = 0xc0000 }, - { - .name = "NetSc520 Low BIOS", - .offset = 0xc0000, + { + .name = "NetSc520 Low BIOS", + .offset = 0xc0000, .size = 0x40000 }, - { - .name = "NetSc520 file system", - .offset = 0x100000, + { + .name = "NetSc520 file system", + .offset = 0x100000, .size = 0xe80000 }, - { - .name = "NetSc520 High BIOS", - .offset = 0xf80000, + { + .name = "NetSc520 High BIOS", + .offset = 0xf80000, .size = 0x80000 }, }; @@ -114,7 +114,7 @@ static int __init init_netsc520(void) iounmap(netsc520_map.virt); return -ENXIO; } - + mymtd->owner = THIS_MODULE; add_mtd_partitions( mymtd, partition_info, NUM_PARTITIONS ); return 0; diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c index 61be5a4148c..f00ee7e54db 100644 --- a/drivers/mtd/maps/nettel.c +++ b/drivers/mtd/maps/nettel.c @@ -6,7 +6,7 @@ * (C) Copyright 2000-2001, Greg Ungerer (gerg@snapgear.com) * (C) Copyright 2001-2002, SnapGear (www.snapgear.com) * - * $Id: nettel.c,v 1.10 2005/01/05 17:11:29 dwmw2 Exp $ + * $Id: nettel.c,v 1.11 2005/11/07 11:14:27 gleixner Exp $ */ /****************************************************************************/ @@ -143,7 +143,7 @@ static int nettel_reboot_notifier(struct notifier_block *nb, unsigned long val, { struct cfi_private *cfi = nettel_intel_map.fldrv_priv; unsigned long b; - + /* Make sure all FLASH chips are put back into read mode */ for (b = 0; (b < nettel_intel_partitions[3].size); b += 0x100000) { cfi_send_gen_cmd(0xff, 0x55, b, &nettel_intel_map, cfi, @@ -199,7 +199,7 @@ int nettel_eraseconfig(void) schedule(); /* Wait for erase to finish. */ remove_wait_queue(&wait_q, &wait); - + put_mtd_device(mtd); } @@ -430,7 +430,7 @@ int __init nettel_init(void) nettel_intel_partitions[1].size = (intel0size + intel1size) - (1024*1024 + intel_mtd->erasesize); nettel_intel_partitions[3].size = intel0size + intel1size; - nettel_intel_partitions[4].offset = + nettel_intel_partitions[4].offset = (intel0size + intel1size) - intel_mtd->erasesize; nettel_intel_partitions[4].size = intel_mtd->erasesize; nettel_intel_partitions[5].offset = diff --git a/drivers/mtd/maps/ocelot.c b/drivers/mtd/maps/ocelot.c index 82c3070678c..6977963d789 100644 --- a/drivers/mtd/maps/ocelot.c +++ b/drivers/mtd/maps/ocelot.c @@ -1,5 +1,5 @@ /* - * $Id: ocelot.c,v 1.16 2005/01/05 18:05:13 dwmw2 Exp $ + * $Id: ocelot.c,v 1.17 2005/11/07 11:14:27 gleixner Exp $ * * Flash on Momenco Ocelot */ @@ -31,7 +31,7 @@ static void ocelot_ram_write(struct mtd_info *mtd, loff_t to, size_t len, size_t struct map_info *map = mtd->priv; size_t done = 0; - /* If we use memcpy, it does word-wide writes. Even though we told the + /* If we use memcpy, it does word-wide writes. Even though we told the GT64120A that it's an 8-bit wide region, word-wide writes don't work. We end up just writing the first byte of the four to all four bytes. So we have this loop instead */ @@ -68,7 +68,7 @@ static int __init init_ocelot_maps(void) int nr_parts; unsigned char brd_status; - printk(KERN_INFO "Momenco Ocelot MTD mappings: Flash 0x%x at 0x%x, NVRAM 0x%x at 0x%x\n", + printk(KERN_INFO "Momenco Ocelot MTD mappings: Flash 0x%x at 0x%x, NVRAM 0x%x at 0x%x\n", FLASH_WINDOW_SIZE, FLASH_WINDOW_ADDR, NVRAM_WINDOW_SIZE, NVRAM_WINDOW_ADDR); /* First check whether the flash jumper is present */ @@ -138,8 +138,8 @@ static int __init init_ocelot_maps(void) add_mtd_device(flash_mtd); return 0; - - fail3: + + fail3: iounmap((void *)ocelot_flash_map.virt); if (ocelot_flash_map.cached) iounmap((void *)ocelot_flash_map.cached); diff --git a/drivers/mtd/maps/octagon-5066.c b/drivers/mtd/maps/octagon-5066.c index e5ff83de420..a6642db3d32 100644 --- a/drivers/mtd/maps/octagon-5066.c +++ b/drivers/mtd/maps/octagon-5066.c @@ -1,12 +1,12 @@ -// $Id: octagon-5066.c,v 1.26 2004/07/12 22:38:29 dwmw2 Exp $ +// $Id: octagon-5066.c,v 1.28 2005/11/07 11:14:27 gleixner Exp $ /* ###################################################################### - Octagon 5066 MTD Driver. - + Octagon 5066 MTD Driver. + The Octagon 5066 is a SBC based on AMD's 586-WB running at 133 MHZ. It comes with a builtin AMD 29F016 flash chip and a socketed EEPROM that is replacable by flash. Both units are mapped through a multiplexer - into a 32k memory window at 0xe8000. The control register for the + into a 32k memory window at 0xe8000. The control register for the multiplexing unit is located at IO 0x208 with a bit map of 0-5 Page Selection in 32k increments 6-7 Device selection: @@ -14,14 +14,14 @@ 01 SSD 0 (Socket) 10 SSD 1 (Flash chip) 11 undefined - + On each SSD, the first 128k is reserved for use by the bios - (actually it IS the bios..) This only matters if you are booting off the + (actually it IS the bios..) This only matters if you are booting off the flash, you must not put a file system starting there. - + The driver tries to do a detection algorithm to guess what sort of devices are plugged into the sockets. - + ##################################################################### */ #include @@ -56,7 +56,7 @@ static void __oct5066_page(struct map_info *map, __u8 byte) static inline void oct5066_page(struct map_info *map, unsigned long ofs) { __u8 byte = map->map_priv_1 | (ofs >> WINDOW_SHIFT); - + if (page_n_dev != byte) __oct5066_page(map, byte); } @@ -78,7 +78,7 @@ static void oct5066_copy_from(struct map_info *map, void *to, unsigned long from unsigned long thislen = len; if (len > (WINDOW_LENGTH - (from & WINDOW_MASK))) thislen = WINDOW_LENGTH-(from & WINDOW_MASK); - + spin_lock(&oct5066_spin); oct5066_page(map, from); memcpy_fromio(to, iomapadr + from, thislen); @@ -103,7 +103,7 @@ static void oct5066_copy_to(struct map_info *map, unsigned long to, const void * unsigned long thislen = len; if (len > (WINDOW_LENGTH - (to & WINDOW_MASK))) thislen = WINDOW_LENGTH-(to & WINDOW_MASK); - + spin_lock(&oct5066_spin); oct5066_page(map, to); memcpy_toio(iomapadr + to, from, thislen); @@ -144,7 +144,7 @@ static struct mtd_info *oct5066_mtd[2] = {NULL, NULL}; // OctProbe - Sense if this is an octagon card // --------------------------------------------------------------------- /* Perform a simple validity test, we map the window select SSD0 and - change pages while monitoring the window. A change in the window, + change pages while monitoring the window. A change in the window, controlled by the PAGE_IO port is a functioning 5066 board. This will fail if the thing in the socket is set to a uniform value. */ static int __init OctProbe(void) @@ -161,13 +161,13 @@ static int __init OctProbe(void) Values[I%10] = readl(iomapadr); if (I > 0 && Values[I%10] == Values[0]) return -EAGAIN; - } + } else { // Make sure we get the same values on the second pass if (Values[I%10] != readl(iomapadr)) return -EAGAIN; - } + } } return 0; } @@ -207,11 +207,11 @@ int __init init_oct5066(void) ret = -EAGAIN; goto out_unmap; } - + // Print out our little header.. printk("Octagon 5066 SSD IO:0x%x MEM:0x%x-0x%x\n",PAGE_IO,WINDOW_START, WINDOW_START+WINDOW_LENGTH); - + for (i=0; i<2; i++) { oct5066_mtd[i] = do_map_probe("cfi_probe", &oct5066_map[i]); if (!oct5066_mtd[i]) @@ -225,11 +225,11 @@ int __init init_oct5066(void) add_mtd_device(oct5066_mtd[i]); } } - + if (!oct5066_mtd[0] && !oct5066_mtd[1]) { cleanup_oct5066(); return -ENXIO; - } + } return 0; diff --git a/drivers/mtd/maps/omap-toto-flash.c b/drivers/mtd/maps/omap-toto-flash.c index da36e8dddd1..a88ed6691ca 100644 --- a/drivers/mtd/maps/omap-toto-flash.c +++ b/drivers/mtd/maps/omap-toto-flash.c @@ -5,7 +5,7 @@ * * (C) 2002 MontVista Software, Inc. * - * $Id: omap-toto-flash.c,v 1.3 2004/09/16 23:27:13 gleixner Exp $ + * $Id: omap-toto-flash.c,v 1.5 2005/11/07 11:14:27 gleixner Exp $ */ #include @@ -38,7 +38,7 @@ static struct map_info omap_toto_map_flash = { .virt = (void __iomem *)OMAP_TOTO_FLASH_BASE, }; - + static struct mtd_partition toto_flash_partitions[] = { { .name = "BootLoader", @@ -54,21 +54,21 @@ static struct mtd_partition toto_flash_partitions[] = { .name = "EnvArea", /* bottom 64KiB for env vars */ .size = MTDPART_SIZ_FULL, .offset = MTDPART_OFS_APPEND, - } + } }; static struct mtd_partition *parsed_parts; static struct mtd_info *flash_mtd; - -static int __init init_flash (void) + +static int __init init_flash (void) { struct mtd_partition *parts; int nb_parts = 0; int parsed_nr_parts = 0; const char *part_type; - + /* * Static partition definition selection */ @@ -89,7 +89,7 @@ static int __init init_flash (void) flash_mtd = do_map_probe("jedec_probe", &omap_toto_map_flash); if (!flash_mtd) return -ENXIO; - + if (parsed_nr_parts > 0) { parts = parsed_parts; nb_parts = parsed_nr_parts; @@ -108,8 +108,8 @@ static int __init init_flash (void) } return 0; } - -int __init omap_toto_mtd_init(void) + +int __init omap_toto_mtd_init(void) { int status; @@ -119,7 +119,7 @@ int __init omap_toto_mtd_init(void) return status; } -static void __exit omap_toto_mtd_cleanup(void) +static void __exit omap_toto_mtd_cleanup(void) { if (flash_mtd) { del_mtd_partitions(flash_mtd); diff --git a/drivers/mtd/maps/omap_nor.c b/drivers/mtd/maps/omap_nor.c index 7f370bb794f..fd3b4a5fc20 100644 --- a/drivers/mtd/maps/omap_nor.c +++ b/drivers/mtd/maps/omap_nor.c @@ -3,7 +3,7 @@ * * Copyright (C) 2001-2002 MontaVista Software Inc. * Copyright (C) 2003-2004 Texas Instruments - * Copyright (C) 2004 Nokia Corporation + * Copyright (C) 2004 Nokia Corporation * * Assembled using driver code copyright the companies above * and written by David Brownell, Jian Zhang , diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c index d9c64e99ee3..8b3570b0909 100644 --- a/drivers/mtd/maps/pci.c +++ b/drivers/mtd/maps/pci.c @@ -7,8 +7,8 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * $Id: pci.c,v 1.10 2005/03/18 14:04:35 gleixner Exp $ - * + * $Id: pci.c,v 1.13 2005/11/07 11:14:27 gleixner Exp $ + * * Generic PCI memory map driver. We support the following boards: * - Intel IQ80310 ATU. * - Intel EBSA285 (blank rom programming mode). Tested working 27/09/2001 @@ -38,7 +38,7 @@ struct map_pci_info { void (*exit)(struct pci_dev *dev, struct map_pci_info *map); unsigned long (*translate)(struct map_pci_info *map, unsigned long ofs); struct pci_dev *dev; -}; +}; static map_word mtd_pci_read8(struct map_info *_map, unsigned long ofs) { diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index ff7c50d1018..af24216a062 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -1,5 +1,5 @@ /* - * $Id: pcmciamtd.c,v 1.51 2004/07/12 22:38:29 dwmw2 Exp $ + * $Id: pcmciamtd.c,v 1.55 2005/11/07 11:14:28 gleixner Exp $ * * pcmciamtd.c - MTD driver for PCMCIA flash memory cards * @@ -48,7 +48,7 @@ static const int debug = 0; #define DRIVER_DESC "PCMCIA Flash memory card driver" -#define DRIVER_VERSION "$Revision: 1.51 $" +#define DRIVER_VERSION "$Revision: 1.55 $" /* Size of the PCMCIA address space: 26 bits = 64 MB */ #define MAX_PCMCIA_ADDR 0x4000000 @@ -176,7 +176,7 @@ static void pcmcia_copy_from_remap(struct map_info *map, void *to, unsigned long if(toread > len) toread = len; - + addr = remap_window(map, from); if(!addr) return; @@ -386,7 +386,7 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_ cs_error(link->handle, ParseTuple, rc); break; } - + switch(tuple.TupleCode) { case CISTPL_FORMAT: { cistpl_format_t *t = &parse.format; @@ -394,9 +394,9 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_ DEBUG(2, "Format type: %u, Error Detection: %u, offset = %u, length =%u", t->type, t->edc, t->offset, t->length); break; - + } - + case CISTPL_DEVICE: { cistpl_device_t *t = &parse.device; int i; @@ -410,7 +410,7 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_ } break; } - + case CISTPL_VERS_1: { cistpl_vers_1_t *t = &parse.version_1; int i; @@ -425,7 +425,7 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_ DEBUG(2, "Found name: %s", dev->mtd_name); break; } - + case CISTPL_JEDEC_C: { cistpl_jedec_t *t = &parse.jedec; int i; @@ -434,7 +434,7 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_ } break; } - + case CISTPL_DEVICE_GEO: { cistpl_device_geo_t *t = &parse.device_geo; int i; @@ -449,11 +449,11 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_ } break; } - + default: DEBUG(2, "Unknown tuple code %d", tuple.TupleCode); } - + rc = pcmcia_get_next_tuple(link->handle, &tuple); } if(!dev->pcmcia_map.size) @@ -470,7 +470,7 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_ if(bankwidth) { dev->pcmcia_map.bankwidth = bankwidth; DEBUG(2, "bankwidth forced to %d", bankwidth); - } + } dev->pcmcia_map.name = dev->mtd_name; if(!dev->mtd_name[0]) { @@ -568,7 +568,7 @@ static void pcmciamtd_config(dev_link_t *link) return; } DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10); - + /* Get write protect status */ CS_CHECK(GetStatus, pcmcia_get_status(link->handle, &status)); DEBUG(2, "status value: 0x%x window handle = 0x%8.8lx", @@ -624,11 +624,11 @@ static void pcmciamtd_config(dev_link_t *link) mtd = do_map_probe(probes[i], &dev->pcmcia_map); if(mtd) break; - + DEBUG(1, "FAILED: %s", probes[i]); } } - + if(!mtd) { DEBUG(1, "Cant find an MTD"); pcmciamtd_release(link); diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index b853670bfb8..9ee760f97bc 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c @@ -1,5 +1,5 @@ /* - * $Id: physmap.c,v 1.37 2004/11/28 09:40:40 dwmw2 Exp $ + * $Id: physmap.c,v 1.38 2005/11/07 11:14:28 gleixner Exp $ * * Normal mappings of chips in physical memory * @@ -69,7 +69,7 @@ static int __init init_physmap(void) mymtd->owner = THIS_MODULE; #ifdef CONFIG_MTD_PARTITIONS - mtd_parts_nb = parse_mtd_partitions(mymtd, part_probes, + mtd_parts_nb = parse_mtd_partitions(mymtd, part_probes, &mtd_parts, 0); if (mtd_parts_nb > 0) @@ -78,9 +78,9 @@ static int __init init_physmap(void) return 0; } - if (num_physmap_partitions != 0) + if (num_physmap_partitions != 0) { - printk(KERN_NOTICE + printk(KERN_NOTICE "Using physmap partition definition\n"); add_mtd_partitions (mymtd, physmap_partitions, num_physmap_partitions); return 0; diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index e35a1c428e5..a02eed94a23 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c @@ -6,7 +6,7 @@ * * Generic platfrom device based RAM map * - * $Id: plat-ram.c,v 1.6 2005/11/07 00:52:24 gleixner Exp $ + * $Id: plat-ram.c,v 1.7 2005/11/07 11:14:28 gleixner Exp $ * * 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 @@ -91,7 +91,7 @@ static int platram_remove(struct device *dev) dev_dbg(dev, "removing device\n"); - if (info == NULL) + if (info == NULL) return 0; if (info->mtd) { @@ -118,7 +118,7 @@ static int platram_remove(struct device *dev) if (info->map.virt != NULL) iounmap(info->map.virt); - + kfree(info); return 0; @@ -139,7 +139,7 @@ static int platram_probe(struct device *dev) int err = 0; dev_dbg(dev, "probe entered\n"); - + if (dev->platform_data == NULL) { dev_err(dev, "no platform data supplied\n"); err = -ENOENT; @@ -240,7 +240,7 @@ static int platram_probe(struct device *dev) dev_err(dev, "add_mtd_device() failed\n"); err = -ENOMEM; } - + dev_info(dev, "registered mtd device\n"); return err; diff --git a/drivers/mtd/maps/pnc2000.c b/drivers/mtd/maps/pnc2000.c index a0f43dad898..d7e16c2d5c4 100644 --- a/drivers/mtd/maps/pnc2000.c +++ b/drivers/mtd/maps/pnc2000.c @@ -5,7 +5,7 @@ * * This code is GPL * - * $Id: pnc2000.c,v 1.17 2004/11/16 18:29:02 dwmw2 Exp $ + * $Id: pnc2000.c,v 1.18 2005/11/07 11:14:28 gleixner Exp $ */ #include @@ -21,7 +21,7 @@ #define WINDOW_ADDR 0xbf000000 #define WINDOW_SIZE 0x00400000 -/* +/* * MAP DRIVER STUFF */ @@ -36,7 +36,7 @@ static struct map_info pnc_map = { /* - * MTD 'PARTITIONING' STUFF + * MTD 'PARTITIONING' STUFF */ static struct mtd_partition pnc_partitions[3] = { { @@ -56,7 +56,7 @@ static struct mtd_partition pnc_partitions[3] = { } }; -/* +/* * This is the master MTD device for which all the others are just * auto-relocating aliases. */ diff --git a/drivers/mtd/maps/pq2fads.c b/drivers/mtd/maps/pq2fads.c index e959076b1bf..fb78d87cc13 100644 --- a/drivers/mtd/maps/pq2fads.c +++ b/drivers/mtd/maps/pq2fads.c @@ -23,7 +23,7 @@ #include /* - NOTE: bank width and interleave relative to the installed flash + NOTE: bank width and interleave relative to the installed flash should have been chosen within MTD_CFI_GEOMETRY options. */ #define PQ2FADS_BANK_WIDTH 4 @@ -35,7 +35,7 @@ static struct mtd_partition pq2fads_partitions[] = { .size = 0x40000, .offset = 0, .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { + }, { .name = "User FS", .size = 0x5c0000, .offset = 0x40000, @@ -44,17 +44,17 @@ static struct mtd_partition pq2fads_partitions[] = { .size = 0x600000, .offset = 0, #endif - }, { + }, { .name = "uImage", .size = 0x100000, .offset = 0x600000, .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { + }, { .name = "bootloader", .size = 0x40000, .offset = 0x700000, .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, { + }, { .name = "bootloader env", .size = 0x40000, .offset = 0x740000, @@ -80,9 +80,9 @@ static int __init init_pq2fads_mtd(void) static void __exit cleanup_pq2fads_mtd(void) { } - + module_init(init_pq2fads_mtd); module_exit(cleanup_pq2fads_mtd); - + MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("MTD map and partitions for MPC8272ADS boards"); diff --git a/drivers/mtd/maps/redwood.c b/drivers/mtd/maps/redwood.c index edd01ee4f90..5b76ed88618 100644 --- a/drivers/mtd/maps/redwood.c +++ b/drivers/mtd/maps/redwood.c @@ -1,5 +1,5 @@ /* - * $Id: redwood.c,v 1.10 2004/11/04 13:24:15 gleixner Exp $ + * $Id: redwood.c,v 1.11 2005/11/07 11:14:28 gleixner Exp $ * * drivers/mtd/maps/redwood.c * @@ -79,7 +79,7 @@ static struct mtd_partition redwood_flash_partitions[] = { #define RW_PART0_OF 0 #define RW_PART0_SZ 0x400000 /* 4 MiB data */ -#define RW_PART1_OF RW_PART0_OF + RW_PART0_SZ +#define RW_PART1_OF RW_PART0_OF + RW_PART0_SZ #define RW_PART1_SZ 0x10000 /* 64K VPD */ #define RW_PART2_OF RW_PART1_OF + RW_PART1_SZ #define RW_PART2_SZ 0x400000 - (0x10000 + 0x20000) diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c index c8d0da19d89..92cf158abb1 100644 --- a/drivers/mtd/maps/sa1100-flash.c +++ b/drivers/mtd/maps/sa1100-flash.c @@ -1,9 +1,9 @@ /* * Flash memory access on SA11x0 based devices - * + * * (C) 2000 Nicolas Pitre - * - * $Id: sa1100-flash.c,v 1.47 2004/11/01 13:44:36 rmk Exp $ + * + * $Id: sa1100-flash.c,v 1.51 2005/11/07 11:14:28 gleixner Exp $ */ #include #include diff --git a/drivers/mtd/maps/sbc8240.c b/drivers/mtd/maps/sbc8240.c index da684d3384e..225cdd9ba5b 100644 --- a/drivers/mtd/maps/sbc8240.c +++ b/drivers/mtd/maps/sbc8240.c @@ -5,7 +5,7 @@ * * This code is GPLed * - * $Id: sbc8240.c,v 1.4 2004/07/12 22:38:29 dwmw2 Exp $ + * $Id: sbc8240.c,v 1.5 2005/11/07 11:14:28 gleixner Exp $ * */ @@ -205,7 +205,7 @@ int __init init_sbc8240_mtd (void) } else { printk (KERN_NOTICE MSG_PREFIX "Using %s partition definition\n", sbc8240_part_banks[i].mtd_part->name); - add_mtd_partitions (sbc8240_mtd[i], + add_mtd_partitions (sbc8240_mtd[i], sbc8240_part_banks[i].mtd_part, sbc8240_part_banks[i].nums); } diff --git a/drivers/mtd/maps/sbc_gxx.c b/drivers/mtd/maps/sbc_gxx.c index 65add28bde1..7cc4041d096 100644 --- a/drivers/mtd/maps/sbc_gxx.c +++ b/drivers/mtd/maps/sbc_gxx.c @@ -1,35 +1,35 @@ /* sbc_gxx.c -- MTD map driver for Arcom Control Systems SBC-MediaGX, SBC-GXm and SBC-GX1 series boards. - + Copyright (C) 2001 Arcom Control System Ltd - + 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 option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - $Id: sbc_gxx.c,v 1.33 2004/11/28 09:40:40 dwmw2 Exp $ + $Id: sbc_gxx.c,v 1.35 2005/11/07 11:14:28 gleixner Exp $ -The SBC-MediaGX / SBC-GXx has up to 16 MiB of -Intel StrataFlash (28F320/28F640) in x8 mode. +The SBC-MediaGX / SBC-GXx has up to 16 MiB of +Intel StrataFlash (28F320/28F640) in x8 mode. This driver uses the CFI probe and Intel Extended Command Set drivers. The flash is accessed as follows: 16 KiB memory window at 0xdc000-0xdffff - + Two IO address locations for paging - + 0x258 bit 0-7: address bit 14-21 0x259 @@ -37,7 +37,7 @@ The flash is accessed as follows: bit 7: 0 - reset/powered down 1 - device enabled -The single flash device is divided into 3 partition which appear as +The single flash device is divided into 3 partition which appear as separate MTD devices. 25/04/2001 AJL (Arcom) Modified signon strings and partition sizes @@ -87,17 +87,17 @@ static volatile int page_in_window = -1; // Current page in window. static void __iomem *iomapadr; static DEFINE_SPINLOCK(sbc_gxx_spin); -/* partition_info gives details on the logical partitions that the split the +/* partition_info gives details on the logical partitions that the split the * single flash device into. If the size if zero we use up to the end of the * device. */ static struct mtd_partition partition_info[]={ - { .name = "SBC-GXx flash boot partition", - .offset = 0, + { .name = "SBC-GXx flash boot partition", + .offset = 0, .size = BOOT_PARTITION_SIZE_KiB*1024 }, - { .name = "SBC-GXx flash data partition", - .offset = BOOT_PARTITION_SIZE_KiB*1024, + { .name = "SBC-GXx flash data partition", + .offset = BOOT_PARTITION_SIZE_KiB*1024, .size = (DATA_PARTITION_SIZE_KiB)*1024 }, - { .name = "SBC-GXx flash application partition", + { .name = "SBC-GXx flash application partition", .offset = (BOOT_PARTITION_SIZE_KiB+DATA_PARTITION_SIZE_KiB)*1024 } }; @@ -130,7 +130,7 @@ static void sbc_gxx_copy_from(struct map_info *map, void *to, unsigned long from unsigned long thislen = len; if (len > (WINDOW_LENGTH - (from & WINDOW_MASK))) thislen = WINDOW_LENGTH-(from & WINDOW_MASK); - + spin_lock(&sbc_gxx_spin); sbc_gxx_page(map, from); memcpy_fromio(to, iomapadr + (from & WINDOW_MASK), thislen); @@ -150,12 +150,12 @@ static void sbc_gxx_write8(struct map_info *map, map_word d, unsigned long adr) } static void sbc_gxx_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) -{ +{ while(len) { unsigned long thislen = len; if (len > (WINDOW_LENGTH - (to & WINDOW_MASK))) thislen = WINDOW_LENGTH-(to & WINDOW_MASK); - + spin_lock(&sbc_gxx_spin); sbc_gxx_page(map, to); memcpy_toio(iomapadr + (to & WINDOW_MASK), from, thislen); @@ -201,7 +201,7 @@ static int __init init_sbc_gxx(void) sbc_gxx_map.name ); return -EIO; } - + if (!request_region( PAGE_IO, PAGE_IO_SIZE, "SBC-GXx flash")) { printk( KERN_ERR"%s: IO ports 0x%x-0x%x in use\n", sbc_gxx_map.name, @@ -209,8 +209,8 @@ static int __init init_sbc_gxx(void) iounmap(iomapadr); return -EAGAIN; } - - + + printk( KERN_INFO"%s: IO:0x%x-0x%x MEM:0x%x-0x%x\n", sbc_gxx_map.name, PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1, @@ -222,7 +222,7 @@ static int __init init_sbc_gxx(void) cleanup_sbc_gxx(); return -ENXIO; } - + all_mtd->owner = THIS_MODULE; /* Create MTD devices for each partition. */ diff --git a/drivers/mtd/maps/sc520cdp.c b/drivers/mtd/maps/sc520cdp.c index a06ed21e7ed..6fb9f3c57aa 100644 --- a/drivers/mtd/maps/sc520cdp.c +++ b/drivers/mtd/maps/sc520cdp.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: sc520cdp.c,v 1.21 2004/12/13 10:27:08 dedekind Exp $ + * $Id: sc520cdp.c,v 1.22 2005/11/07 11:14:28 gleixner Exp $ * * * The SC520CDP is an evaluation board for the Elan SC520 processor available @@ -231,7 +231,7 @@ static void sc520cdp_setup_par(void) static int __init init_sc520cdp(void) { int i, devices_found = 0; - + #ifdef REPROGRAM_PAR /* reprogram PAR registers so flash appears at the desired addresses */ sc520cdp_setup_par(); @@ -278,7 +278,7 @@ static int __init init_sc520cdp(void) static void __exit cleanup_sc520cdp(void) { int i; - + if (merged_mtd) { del_mtd_device(merged_mtd); mtd_concat_destroy(merged_mtd); diff --git a/drivers/mtd/maps/scx200_docflash.c b/drivers/mtd/maps/scx200_docflash.c index 0ece3786d6e..2c91dff8bb6 100644 --- a/drivers/mtd/maps/scx200_docflash.c +++ b/drivers/mtd/maps/scx200_docflash.c @@ -1,8 +1,8 @@ -/* linux/drivers/mtd/maps/scx200_docflash.c +/* linux/drivers/mtd/maps/scx200_docflash.c Copyright (c) 2001,2002 Christer Weinigel - $Id: scx200_docflash.c,v 1.10 2004/11/28 09:40:40 dwmw2 Exp $ + $Id: scx200_docflash.c,v 1.12 2005/11/07 11:14:28 gleixner Exp $ National Semiconductor SCx200 flash mapped with DOCCS */ @@ -49,23 +49,23 @@ static struct mtd_info *mymtd; #ifdef CONFIG_MTD_PARTITIONS static struct mtd_partition partition_info[] = { - { - .name = "DOCCS Boot kernel", - .offset = 0, + { + .name = "DOCCS Boot kernel", + .offset = 0, .size = 0xc0000 }, - { - .name = "DOCCS Low BIOS", - .offset = 0xc0000, + { + .name = "DOCCS Low BIOS", + .offset = 0xc0000, .size = 0x40000 }, - { - .name = "DOCCS File system", - .offset = 0x100000, + { + .name = "DOCCS File system", + .offset = 0x100000, .size = ~0 /* calculate from flash size */ }, - { - .name = "DOCCS High BIOS", + { + .name = "DOCCS High BIOS", .offset = ~0, /* calculate from flash size */ .size = 0x80000 }, @@ -88,7 +88,7 @@ static int __init init_scx200_docflash(void) printk(KERN_DEBUG NAME ": NatSemi SCx200 DOCCS Flash Driver\n"); - if ((bridge = pci_find_device(PCI_VENDOR_ID_NS, + if ((bridge = pci_find_device(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE, NULL)) == NULL) return -ENODEV; @@ -134,28 +134,28 @@ static int __init init_scx200_docflash(void) printk(KERN_ERR NAME ": invalid size for flash mapping\n"); return -EINVAL; } - + if (width != 8 && width != 16) { printk(KERN_ERR NAME ": invalid bus width for flash mapping\n"); return -EINVAL; } - - if (allocate_resource(&iomem_resource, &docmem, + + if (allocate_resource(&iomem_resource, &docmem, size, - 0xc0000000, 0xffffffff, + 0xc0000000, 0xffffffff, size, NULL, NULL)) { printk(KERN_ERR NAME ": unable to allocate memory for flash mapping\n"); return -ENOMEM; } - + ctrl = 0x07000000 | ((size-1) >> 13); printk(KERN_INFO "DOCCS BASE=0x%08lx, CTRL=0x%08lx\n", (long)docmem.start, (long)ctrl); - + pci_write_config_dword(bridge, SCx200_DOCCS_BASE, docmem.start); pci_write_config_dword(bridge, SCx200_DOCCS_CTRL, ctrl); pmr = inl(scx200_cb_base + SCx200_PMR); - + if (width == 8) { pmr &= ~(1<<6); } else { @@ -163,8 +163,8 @@ static int __init init_scx200_docflash(void) } outl(pmr, scx200_cb_base + SCx200_PMR); } - - printk(KERN_INFO NAME ": DOCCS mapped at 0x%lx-0x%lx, width %d\n", + + printk(KERN_INFO NAME ": DOCCS mapped at 0x%lx-0x%lx, width %d\n", docmem.start, docmem.end, width); scx200_docflash_map.size = size; diff --git a/drivers/mtd/maps/sharpsl-flash.c b/drivers/mtd/maps/sharpsl-flash.c index b7f093fbf9b..999f4bb3d84 100644 --- a/drivers/mtd/maps/sharpsl-flash.c +++ b/drivers/mtd/maps/sharpsl-flash.c @@ -1,10 +1,10 @@ /* * sharpsl-flash.c - * + * * Copyright (C) 2001 Lineo Japan, Inc. * Copyright (C) 2002 SHARP * - * $Id: sharpsl-flash.c,v 1.5 2005/03/21 08:42:11 rpurdie Exp $ + * $Id: sharpsl-flash.c,v 1.7 2005/11/07 11:14:28 gleixner Exp $ * * based on rpxlite.c,v 1.15 2001/10/02 15:05:14 dwmw2 Exp * Handle mapping of the flash on the RPX Lite and CLLF boards @@ -57,7 +57,7 @@ int __init init_sharpsl(void) int nb_parts = 0; char *part_type = "static"; - printk(KERN_NOTICE "Sharp SL series flash device: %x at %x\n", + printk(KERN_NOTICE "Sharp SL series flash device: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); sharpsl_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE); if (!sharpsl_map.virt) { @@ -75,7 +75,7 @@ int __init init_sharpsl(void) mymtd->owner = THIS_MODULE; - if (machine_is_corgi() || machine_is_shepherd() || machine_is_husky() + if (machine_is_corgi() || machine_is_shepherd() || machine_is_husky() || machine_is_poodle()) { sharpsl_partitions[0].size=0x006d0000; sharpsl_partitions[0].offset=0x00120000; @@ -87,10 +87,10 @@ int __init init_sharpsl(void) sharpsl_partitions[0].offset=0x00140000; } else { map_destroy(mymtd); - iounmap(sharpsl_map.virt); + iounmap(sharpsl_map.virt); return -ENODEV; } - + parts = sharpsl_partitions; nb_parts = NB_OF(sharpsl_partitions); diff --git a/drivers/mtd/maps/solutionengine.c b/drivers/mtd/maps/solutionengine.c index 8ce5d897645..c53c2c369c9 100644 --- a/drivers/mtd/maps/solutionengine.c +++ b/drivers/mtd/maps/solutionengine.c @@ -1,5 +1,5 @@ /* - * $Id: solutionengine.c,v 1.14 2004/09/16 23:27:14 gleixner Exp $ + * $Id: solutionengine.c,v 1.15 2005/11/07 11:14:28 gleixner Exp $ * * Flash and EPROM on Hitachi Solution Engine and similar boards. * @@ -67,7 +67,7 @@ static int __init init_soleng_maps(void) soleng_eprom_map.virt = (void __iomem *)P1SEGADDR(0x01000000); simple_map_init(&soleng_eprom_map); simple_map_init(&soleng_flash_map); - + printk(KERN_NOTICE "Probing for flash chips at 0x00000000:\n"); flash_mtd = do_map_probe("cfi_probe", &soleng_flash_map); if (!flash_mtd) { diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c index 29091d10030..47941fbe74f 100644 --- a/drivers/mtd/maps/sun_uflash.c +++ b/drivers/mtd/maps/sun_uflash.c @@ -1,4 +1,4 @@ -/* $Id: sun_uflash.c,v 1.11 2004/11/04 13:24:15 gleixner Exp $ +/* $Id: sun_uflash.c,v 1.13 2005/11/07 11:14:28 gleixner Exp $ * * sun_uflash - Driver implementation for user-programmable flash * present on many Sun Microsystems SME boardsets. @@ -63,7 +63,7 @@ int uflash_devinit(struct linux_ebus_device* edev) iTmp = prom_getproperty( edev->prom_node, "reg", (void *)regs, sizeof(regs)); if ((iTmp % sizeof(regs[0])) != 0) { - printk("%s: Strange reg property size %d\n", + printk("%s: Strange reg property size %d\n", UFLASH_DEVNAME, iTmp); return -ENODEV; } @@ -75,7 +75,7 @@ int uflash_devinit(struct linux_ebus_device* edev) * can work on supporting it. */ printk("%s: unsupported device at 0x%lx (%d regs): " \ - "email ebrower@usa.net\n", + "email ebrower@usa.net\n", UFLASH_DEVNAME, edev->resource[0].start, nregs); return -ENODEV; } @@ -84,7 +84,7 @@ int uflash_devinit(struct linux_ebus_device* edev) printk("%s: unable to kmalloc new device\n", UFLASH_DEVNAME); return(-ENOMEM); } - + /* copy defaults and tweak parameters */ memcpy(&pdev->map, &uflash_map_templ, sizeof(uflash_map_templ)); pdev->map.size = regs[0].reg_size; @@ -155,7 +155,7 @@ static void __exit uflash_cleanup(void) list_for_each(udevlist, &device_list) { udev = list_entry(udevlist, struct uflash_dev, list); - DEBUG(2, "%s: removing device %s\n", + DEBUG(2, "%s: removing device %s\n", UFLASH_DEVNAME, udev->name); if(0 != udev->mtd) { @@ -170,7 +170,7 @@ static void __exit uflash_cleanup(void) kfree(udev->name); } kfree(udev); - } + } } module_init(uflash_init); diff --git a/drivers/mtd/maps/tqm834x.c b/drivers/mtd/maps/tqm834x.c index d0bc9593cb4..c7ae9a515c1 100644 --- a/drivers/mtd/maps/tqm834x.c +++ b/drivers/mtd/maps/tqm834x.c @@ -133,7 +133,7 @@ static int __init init_tqm834x_mtd(void) pr_debug("%s: chip probing count %d\n", __FUNCTION__, idx); - map_banks[idx] = + map_banks[idx] = (struct map_info *)kmalloc(sizeof(struct map_info), GFP_KERNEL); if (map_banks[idx] == NULL) { @@ -193,7 +193,7 @@ static int __init init_tqm834x_mtd(void) tqm834x_partitions_bank1[n - 1].size = mtd_banks[0]->size - tqm834x_partitions_bank1[n - 1].offset; - + /* check if we have second bank? */ if (num_banks == 2) { n = ARRAY_SIZE(tqm834x_partitions_bank2); @@ -227,11 +227,11 @@ static int __init init_tqm834x_mtd(void) "available, registering whole device\n", idx); add_mtd_device(mtd_banks[idx]); } else { - printk(KERN_NOTICE + printk(KERN_NOTICE "TQM834x flash bank %d: Using %s partition " "definition\n", idx, part_banks[idx].type); add_mtd_partitions(mtd_banks[idx], - part_banks[idx].mtd_part, + part_banks[idx].mtd_part, part_banks[idx].nums); } } diff --git a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c index 4e28b977f22..9cb5d679fe6 100644 --- a/drivers/mtd/maps/tqm8xxl.c +++ b/drivers/mtd/maps/tqm8xxl.c @@ -1,15 +1,15 @@ /* - * Handle mapping of the flash memory access routines + * Handle mapping of the flash memory access routines * on TQM8xxL based devices. * - * $Id: tqm8xxl.c,v 1.13 2004/10/20 22:21:53 dwmw2 Exp $ + * $Id: tqm8xxl.c,v 1.15 2005/11/07 11:14:28 gleixner Exp $ * * based on rpxlite.c * * Copyright(C) 2001 Kirk Lee * * This code is GPLed - * + * */ /* @@ -19,7 +19,7 @@ * 2MiB 512Kx16 2MiB 0 * 4MiB 1Mx16 4MiB 0 * 8MiB 1Mx16 4MiB 4MiB - * Thus, we choose CONFIG_MTD_CFI_I2 & CONFIG_MTD_CFI_B4 at + * Thus, we choose CONFIG_MTD_CFI_I2 & CONFIG_MTD_CFI_B4 at * kernel configuration. */ #include @@ -58,9 +58,9 @@ static void __iomem *start_scan_addr; * Here are partition information for all known TQM8xxL series devices. * See include/linux/mtd/partitions.h for definition of the mtd_partition * structure. - * + * * The *_max_flash_size is the maximum possible mapped flash size which - * is not necessarily the actual flash size. It must correspond to the + * is not necessarily the actual flash size. It must correspond to the * value specified in the mapping definition defined by the * "struct map_desc *_io_desc" for the corresponding machine. */ @@ -132,9 +132,9 @@ int __init init_tqm_mtd(void) for (idx = 0 ; idx < FLASH_BANK_MAX ; idx++) { if(mtd_size >= flash_size) break; - + printk(KERN_INFO "%s: chip probing count %d\n", __FUNCTION__, idx); - + map_banks[idx] = (struct map_info *)kmalloc(sizeof(struct map_info), GFP_KERNEL); if(map_banks[idx] == NULL) { ret = -ENOMEM; @@ -180,7 +180,7 @@ int __init init_tqm_mtd(void) mtd_size += mtd_banks[idx]->size; num_banks++; - printk(KERN_INFO "%s: bank%d, name:%s, size:%dbytes \n", __FUNCTION__, num_banks, + printk(KERN_INFO "%s: bank%d, name:%s, size:%dbytes \n", __FUNCTION__, num_banks, mtd_banks[idx]->name, mtd_banks[idx]->size); } } @@ -211,7 +211,7 @@ int __init init_tqm_mtd(void) } else { printk(KERN_NOTICE "TQM flash%d: Using %s partition definition\n", idx, part_banks[idx].type); - add_mtd_partitions(mtd_banks[idx], part_banks[idx].mtd_part, + add_mtd_partitions(mtd_banks[idx], part_banks[idx].mtd_part, part_banks[idx].nums); } } diff --git a/drivers/mtd/maps/ts5500_flash.c b/drivers/mtd/maps/ts5500_flash.c index 2762da95431..4b372bcb17f 100644 --- a/drivers/mtd/maps/ts5500_flash.c +++ b/drivers/mtd/maps/ts5500_flash.c @@ -19,11 +19,11 @@ * * Note: * - In order for detection to work, jumper 3 must be set. - * - Drive A and B use the resident flash disk (RFD) flash translation layer. - * - If you have created your own jffs file system and the bios overwrites + * - Drive A and B use the resident flash disk (RFD) flash translation layer. + * - If you have created your own jffs file system and the bios overwrites * it during boot, try disabling Drive A: and B: in the boot order. * - * $Id: ts5500_flash.c,v 1.4 2005/06/29 09:29:43 sean Exp $ + * $Id: ts5500_flash.c,v 1.5 2005/11/07 11:14:28 gleixner Exp $ */ #include diff --git a/drivers/mtd/maps/tsunami_flash.c b/drivers/mtd/maps/tsunami_flash.c index 170d71239e5..9e21e6c02f8 100644 --- a/drivers/mtd/maps/tsunami_flash.c +++ b/drivers/mtd/maps/tsunami_flash.c @@ -2,7 +2,7 @@ * tsunami_flash.c * * flash chip on alpha ds10... - * $Id: tsunami_flash.c,v 1.9 2004/07/14 09:52:55 dwmw2 Exp $ + * $Id: tsunami_flash.c,v 1.10 2005/11/07 11:14:29 gleixner Exp $ */ #include #include @@ -41,7 +41,7 @@ static void tsunami_flash_copy_from( } static void tsunami_flash_copy_to( - struct map_info *map, unsigned long offset, + struct map_info *map, unsigned long offset, const void *addr, ssize_t len) { const unsigned char *src; @@ -90,7 +90,7 @@ static int __init init_tsunami_flash(void) char **type; tsunami_tig_writeb(FLASH_ENABLE_BYTE, FLASH_ENABLE_PORT); - + tsunami_flash_mtd = 0; type = rom_probe_types; for(; !tsunami_flash_mtd && *type; type++) { diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c index cc372136e85..79d92808b76 100644 --- a/drivers/mtd/maps/uclinux.c +++ b/drivers/mtd/maps/uclinux.c @@ -5,7 +5,7 @@ * * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com) * - * $Id: uclinux.c,v 1.10 2005/01/05 18:05:13 dwmw2 Exp $ + * $Id: uclinux.c,v 1.12 2005/11/07 11:14:29 gleixner Exp $ */ /****************************************************************************/ @@ -82,7 +82,7 @@ int __init uclinux_mtd_init(void) iounmap(mapp->virt); return(-ENXIO); } - + mtd->owner = THIS_MODULE; mtd->point = uclinux_point; mtd->priv = mapp; diff --git a/drivers/mtd/maps/vmax301.c b/drivers/mtd/maps/vmax301.c index c8c74110ed1..e0063941c0d 100644 --- a/drivers/mtd/maps/vmax301.c +++ b/drivers/mtd/maps/vmax301.c @@ -1,19 +1,19 @@ -// $Id: vmax301.c,v 1.30 2004/07/12 22:38:29 dwmw2 Exp $ +// $Id: vmax301.c,v 1.32 2005/11/07 11:14:29 gleixner Exp $ /* ###################################################################### Tempustech VMAX SBC301 MTD Driver. - + The VMAx 301 is a SBC based on . It comes with three builtin AMD 29F016B flash chips and a socket for SRAM or - more flash. Each unit has it's own 8k mapping into a settable region + more flash. Each unit has it's own 8k mapping into a settable region (0xD8000). There are two 8k mappings for each MTD, the first is always set to the lower 8k of the device the second is paged. Writing a 16 bit page value to anywhere in the first 8k will cause the second 8k to page around. - To boot the device a bios extension must be installed into the first 8k - of flash that is smart enough to copy itself down, page in the rest of + To boot the device a bios extension must be installed into the first 8k + of flash that is smart enough to copy itself down, page in the rest of itself and begin executing. - + ##################################################################### */ #include @@ -35,7 +35,7 @@ /* Actually we could use two spinlocks, but we'd have to have more private space in the struct map_info. We lose a little performance like this, but we'd probably lose more by having - the extra indirection from having one of the map->map_priv + the extra indirection from having one of the map->map_priv fields pointing to yet another private struct. */ static DEFINE_SPINLOCK(vmax301_spin); @@ -98,7 +98,7 @@ static void vmax301_copy_to(struct map_info *map, unsigned long to, const void * spin_lock(&vmax301_spin); vmax301_page(map, to); memcpy_toio(map->map_priv_2 + to, from, thislen); - spin_unlock(&vmax301_spin); + spin_unlock(&vmax301_spin); to += thislen; from += thislen; len -= thislen; @@ -137,7 +137,7 @@ static struct mtd_info *vmax_mtd[2] = {NULL, NULL}; static void __exit cleanup_vmax301(void) { int i; - + for (i=0; i<2; i++) { if (vmax_mtd[i]) { del_mtd_device(vmax_mtd[i]); @@ -161,13 +161,13 @@ int __init init_vmax301(void) return -EIO; } /* Put the address in the map's private data area. - We store the actual MTD IO address rather than the + We store the actual MTD IO address rather than the address of the first half, because it's used more - often. + often. */ vmax_map[0].map_priv_2 = iomapadr + WINDOW_START; vmax_map[1].map_priv_2 = iomapadr + (3*WINDOW_START); - + for (i=0; i<2; i++) { vmax_mtd[i] = do_map_probe("cfi_probe", &vmax_map[i]); if (!vmax_mtd[i]) diff --git a/drivers/mtd/maps/walnut.c b/drivers/mtd/maps/walnut.c index d6137b1b567..5c17bca3a37 100644 --- a/drivers/mtd/maps/walnut.c +++ b/drivers/mtd/maps/walnut.c @@ -1,12 +1,12 @@ /* - * $Id: walnut.c,v 1.2 2004/12/10 12:07:42 holindho Exp $ - * + * $Id: walnut.c,v 1.3 2005/11/07 11:14:29 gleixner Exp $ + * * Mapping for Walnut flash * (used ebony.c as a "framework") - * + * * Heikki Lindholm - * - * + * + * * 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 @@ -48,7 +48,7 @@ static struct mtd_partition walnut_partitions[] = { .name = "OpenBIOS", .offset = 0x0, .size = WALNUT_FLASH_SIZE, - /*.mask_flags = MTD_WRITEABLE, */ /* force read-only */ + /*.mask_flags = MTD_WRITEABLE, */ /* force read-only */ } }; @@ -72,11 +72,11 @@ int __init init_walnut(void) printk("The on-board flash is disabled (U79 sw 5)!"); return -EIO; } - if (WALNUT_FLASH_SRAM_SEL(fpga_brds1)) + if (WALNUT_FLASH_SRAM_SEL(fpga_brds1)) flash_base = WALNUT_FLASH_LOW; else flash_base = WALNUT_FLASH_HIGH; - + walnut_map.phys = flash_base; walnut_map.virt = (void __iomem *)ioremap(flash_base, walnut_map.size); diff --git a/drivers/mtd/maps/wr_sbc82xx_flash.c b/drivers/mtd/maps/wr_sbc82xx_flash.c index 82b887b0570..60c197ec455 100644 --- a/drivers/mtd/maps/wr_sbc82xx_flash.c +++ b/drivers/mtd/maps/wr_sbc82xx_flash.c @@ -1,5 +1,5 @@ /* - * $Id: wr_sbc82xx_flash.c,v 1.7 2004/11/04 13:24:15 gleixner Exp $ + * $Id: wr_sbc82xx_flash.c,v 1.8 2005/11/07 11:14:29 gleixner Exp $ * * Map for flash chips on Wind River PowerQUICC II SBC82xx board. * @@ -163,10 +163,10 @@ static void __exit cleanup_sbc82xx_flash(void) del_mtd_partitions(sbcmtd[i]); else del_mtd_device(sbcmtd[i]); - + kfree(sbcmtd_parts[i]); map_destroy(sbcmtd[i]); - + iounmap((void *)sbc82xx_flash_map[i].virt); sbc82xx_flash_map[i].virt = 0; } -- cgit v1.2.3 From e5580fbe8a950131b9ccccce0f962811dfb9ef43 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 11:15:40 +0000 Subject: [MTD] devices: Clean up trailing white spaces Signed-off-by: Thomas Gleixner --- drivers/mtd/devices/Kconfig | 8 ++-- drivers/mtd/devices/blkmtd.c | 10 ++--- drivers/mtd/devices/block2mtd.c | 8 ++-- drivers/mtd/devices/doc2000.c | 42 ++++++++++---------- drivers/mtd/devices/doc2001.c | 24 +++++------ drivers/mtd/devices/doc2001plus.c | 20 +++++----- drivers/mtd/devices/docecc.c | 40 +++++++++---------- drivers/mtd/devices/docprobe.c | 84 +++++++++++++++++++-------------------- drivers/mtd/devices/lart.c | 8 ++-- drivers/mtd/devices/phram.c | 14 +++---- drivers/mtd/devices/pmc551.c | 24 +++++------ drivers/mtd/devices/slram.c | 30 +++++++------- 12 files changed, 156 insertions(+), 156 deletions(-) diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index c4a56a4ac5e..9a2aa4033c6 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig @@ -1,5 +1,5 @@ # drivers/mtd/maps/Kconfig -# $Id: Kconfig,v 1.15 2004/12/22 17:51:15 joern Exp $ +# $Id: Kconfig,v 1.18 2005/11/07 11:14:24 gleixner Exp $ menu "Self-contained MTD device drivers" depends on MTD!=n @@ -110,7 +110,7 @@ config MTDRAM_ABS_POS If you have system RAM accessible by the CPU but not used by Linux in normal operation, you can give the physical address at which the available RAM starts, and the MTDRAM driver will use it instead of - allocating space from Linux's available memory. Otherwise, leave + allocating space from Linux's available memory. Otherwise, leave this set to zero. Most people will want to leave this as zero. config MTD_BLKMTD @@ -165,7 +165,7 @@ config MTD_DOC2001 select MTD_DOCPROBE select MTD_NAND_IDS ---help--- - This provides an alternative MTD device driver for the M-Systems + This provides an alternative MTD device driver for the M-Systems DiskOnChip Millennium devices. Use this if you have problems with the combined DiskOnChip 2000 and Millennium driver above. To get the DiskOnChip probe code to load and use this driver instead of @@ -192,7 +192,7 @@ config MTD_DOC2001PLUS If you use this device, you probably also want to enable the INFTL 'Inverse NAND Flash Translation Layer' option below, which is used - to emulate a block device by using a kind of file system on the + to emulate a block device by using a kind of file system on the flash chips. NOTE: This driver will soon be replaced by the new DiskOnChip driver diff --git a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c index 662e807801e..ff585788880 100644 --- a/drivers/mtd/devices/blkmtd.c +++ b/drivers/mtd/devices/blkmtd.c @@ -1,5 +1,5 @@ /* - * $Id: blkmtd.c,v 1.24 2004/11/16 18:29:01 dwmw2 Exp $ + * $Id: blkmtd.c,v 1.27 2005/11/07 11:14:24 gleixner Exp $ * * blkmtd.c - use a block device as a fake MTD * @@ -39,7 +39,7 @@ /* Default erase size in K, always make it a multiple of PAGE_SIZE */ #define CONFIG_MTD_BLKDEV_ERASESIZE (128 << 10) /* 128KiB */ -#define VERSION "$Revision: 1.24 $" +#define VERSION "$Revision: 1.27 $" /* Info for the block device */ struct blkmtd_dev { @@ -117,7 +117,7 @@ static int bi_write_complete(struct bio *bio, unsigned int bytes_done, int error unlock_page(page); page_cache_release(page); } while (bvec >= bio->bi_io_vec); - + complete((struct completion*)bio->bi_private); return 0; } @@ -135,7 +135,7 @@ static int blkmtd_readpage(struct blkmtd_dev *dev, struct page *page) unlock_page(page); return 0; } - + ClearPageUptodate(page); ClearPageError(page); @@ -710,7 +710,7 @@ static struct blkmtd_dev *add_device(char *devname, int readonly, int erase_size dev->mtd_info.erasesize >> 10, readonly ? "(read-only)" : ""); } - + return dev; devinit_err: diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index 4a7a805e756..0aaa0ced9ab 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -1,5 +1,5 @@ /* - * $Id: block2mtd.c,v 1.28 2005/03/19 22:40:44 gleixner Exp $ + * $Id: block2mtd.c,v 1.29 2005/11/07 11:14:24 gleixner Exp $ * * block2mtd.c - create an mtd from a block device * @@ -19,7 +19,7 @@ #include #include -#define VERSION "$Revision: 1.28 $" +#define VERSION "$Revision: 1.29 $" #define ERROR(fmt, args...) printk(KERN_ERR "block2mtd: " fmt "\n" , ## args) @@ -111,7 +111,7 @@ static int _block2mtd_erase(struct block2mtd_dev *dev, loff_t to, size_t len) return PTR_ERR(page); max = (u_long*)page_address(page) + PAGE_SIZE; - for (p=(u_long*)page_address(page); p PAGE_SIZE) + if ((offset+len) > PAGE_SIZE) cpylen = PAGE_SIZE - offset; // multiple pages else cpylen = len; // this page diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c index 5fc532895a2..be5e88b3888 100644 --- a/drivers/mtd/devices/doc2000.c +++ b/drivers/mtd/devices/doc2000.c @@ -4,7 +4,7 @@ * (c) 1999 Machine Vision Holdings, Inc. * (c) 1999, 2000 David Woodhouse * - * $Id: doc2000.c,v 1.66 2005/01/05 18:05:12 dwmw2 Exp $ + * $Id: doc2000.c,v 1.67 2005/11/07 11:14:24 gleixner Exp $ */ #include @@ -58,7 +58,7 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); -static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, +static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel); static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, @@ -76,14 +76,14 @@ static void DoC_Delay(struct DiskOnChip *doc, unsigned short cycles) { volatile char dummy; int i; - + for (i = 0; i < cycles; i++) { if (DoC_is_Millennium(doc)) dummy = ReadDOC(doc->virtadr, NOP); else dummy = ReadDOC(doc->virtadr, DOCStatus); } - + } /* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ @@ -220,8 +220,8 @@ static int DoC_Address(struct DiskOnChip *doc, int numbytes, unsigned long ofs, WriteDOC(ofs & 0xff, docptr, WritePipeTerm); DoC_Delay(doc, 2); /* Needed for some slow flash chips. mf. */ - - /* FIXME: The SlowIO's for millennium could be replaced by + + /* FIXME: The SlowIO's for millennium could be replaced by a single WritePipeTerm here. mf. */ /* Lower the ALE line */ @@ -377,9 +377,9 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip) if (mfr == 0xff || mfr == 0) return 0; - /* Check it's the same as the first chip we identified. + /* Check it's the same as the first chip we identified. * M-Systems say that any given DiskOnChip device should only - * contain _one_ type of flash part, although that's not a + * contain _one_ type of flash part, although that's not a * hardware restriction. */ if (doc->mfr) { if (doc->mfr == mfr && doc->id == id) @@ -397,7 +397,7 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip) for (j = 0; nand_manuf_ids[j].id != 0x0; j++) { if (nand_manuf_ids[j].id == mfr) break; - } + } printk(KERN_INFO "Flash chip found: Manufacturer ID: %2.2X, " "Chip ID: %2.2X (%s:%s)\n", mfr, id, @@ -405,7 +405,7 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip) if (!doc->mfr) { doc->mfr = mfr; doc->id = id; - doc->chipshift = + doc->chipshift = ffs((nand_flash_ids[i].chipsize << 20)) - 1; doc->page256 = (nand_flash_ids[i].pagesize == 256) ? 1 : 0; doc->pageadrlen = doc->chipshift > 25 ? 3 : 2; @@ -467,7 +467,7 @@ static void DoC_ScanChips(struct DiskOnChip *this, int maxchips) ret = 0; - /* Fill out the chip array with {floor, chipno} for each + /* Fill out the chip array with {floor, chipno} for each * detected chip in the device. */ for (floor = 0; floor < MAX_FLOORS; floor++) { for (chip = 0; chip < numchips[floor]; chip++) { @@ -757,12 +757,12 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], eccbuf[4], eccbuf[5]); #endif - + /* disable the ECC engine */ WriteDOC(DOC_ECC_DIS, docptr , ECCConf); } - /* according to 11.4.1, we need to wait for the busy line + /* according to 11.4.1, we need to wait for the busy line * drop if we read to the end of the page. */ if(0 == ((from + len) & 0x1ff)) { @@ -941,7 +941,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, /* Let the caller know we completed it */ *retlen += len; - + if (eccbuf) { unsigned char x[8]; size_t dummy; @@ -950,10 +950,10 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, /* Write the ECC data to flash */ for (di=0; di<6; di++) x[di] = eccbuf[di]; - + x[6]=0x55; x[7]=0x55; - + ret = doc_write_oob_nolock(mtd, to, 8, &dummy, x); if (ret) { up(&this->lock); @@ -970,7 +970,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, return 0; } -static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, +static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel) { @@ -1022,7 +1022,7 @@ static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, break; to += thislen; - } + } up(&writev_buf_sem); *retlen = totretlen; @@ -1080,7 +1080,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, /* Reading the full OOB data drops us off of the end of the page, * causing the flash device to go into busy mode, so we need * to wait until ready 11.4.1 and Toshiba TC58256FT docs */ - + ret = DoC_WaitReady(this); up(&this->lock); @@ -1190,7 +1190,7 @@ static int doc_write_oob_nolock(struct mtd_info *mtd, loff_t ofs, size_t len, return 0; } - + static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t * retlen, const u_char * buf) { @@ -1222,7 +1222,7 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *instr) } instr->state = MTD_ERASING; - + /* FIXME: Do this in the background. Use timers or schedule_task() */ while(len) { mychip = &this->chips[ofs >> this->chipshift]; diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c index 1e704915ef0..fcb28a6fd89 100644 --- a/drivers/mtd/devices/doc2001.c +++ b/drivers/mtd/devices/doc2001.c @@ -4,7 +4,7 @@ * (c) 1999 Machine Vision Holdings, Inc. * (c) 1999, 2000 David Woodhouse * - * $Id: doc2001.c,v 1.48 2005/01/05 18:05:12 dwmw2 Exp $ + * $Id: doc2001.c,v 1.49 2005/11/07 11:14:24 gleixner Exp $ */ #include @@ -196,10 +196,10 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip) DoC_Command(doc->virtadr, NAND_CMD_RESET, CDSN_CTRL_WP); DoC_WaitReady(doc->virtadr); - /* Read the NAND chip ID: 1. Send ReadID command */ + /* Read the NAND chip ID: 1. Send ReadID command */ DoC_Command(doc->virtadr, NAND_CMD_READID, CDSN_CTRL_WP); - /* Read the NAND chip ID: 2. Send address byte zero */ + /* Read the NAND chip ID: 2. Send address byte zero */ DoC_Address(doc->virtadr, 1, 0x00, CDSN_CTRL_WP, 0x00); /* Read the manufacturer and device id codes of the flash device through @@ -223,7 +223,7 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip) for (j = 0; nand_manuf_ids[j].id != 0x0; j++) { if (nand_manuf_ids[j].id == mfr) break; - } + } printk(KERN_INFO "Flash chip found: Manufacturer ID: %2.2X, " "Chip ID: %2.2X (%s:%s)\n", mfr, id, nand_manuf_ids[j].name, nand_flash_ids[i].name); @@ -275,7 +275,7 @@ static void DoC_ScanChips(struct DiskOnChip *this) return; } - /* Fill out the chip array with {floor, chipno} for each + /* Fill out the chip array with {floor, chipno} for each * detected chip in the device. */ for (floor = 0, ret = 0; floor < MAX_FLOORS_MIL; floor++) { for (chip = 0 ; chip < numchips[floor] ; chip++) { @@ -309,7 +309,7 @@ static int DoCMil_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2) tmp2 = ReadDOC(doc2->virtadr, AliasResolution); if (tmp1 != tmp2) return 0; - + WriteDOC((tmp1+1) % 0xff, doc1->virtadr, AliasResolution); tmp2 = ReadDOC(doc2->virtadr, AliasResolution); if (tmp2 == (tmp1+1) % 0xff) @@ -425,7 +425,7 @@ static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, return -EINVAL; /* Don't allow a single read to cross a 512-byte block boundary */ - if (from + len > ((from | 0x1ff) + 1)) + if (from + len > ((from | 0x1ff) + 1)) len = ((from | 0x1ff) + 1) - from; /* Find the chip which is to be used and select it */ @@ -552,7 +552,7 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, #if 0 /* Don't allow a single write to cross a 512-byte block boundary */ - if (to + len > ( (to | 0x1ff) + 1)) + if (to + len > ( (to | 0x1ff) + 1)) len = ((to | 0x1ff) + 1) - to; #else /* Don't allow writes which aren't exactly one block */ @@ -632,7 +632,7 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, /* write the block status BLOCK_USED (0x5555) at the end of ECC data FIXME: this is only a hack for programming the IPL area for LinuxBIOS - and should be replace with proper codes in user space utilities */ + and should be replace with proper codes in user space utilities */ WriteDOC(0x55, docptr, Mil_CDSN_IO); WriteDOC(0x55, docptr, Mil_CDSN_IO + 1); @@ -802,7 +802,7 @@ int doc_erase (struct mtd_info *mtd, struct erase_info *instr) void __iomem *docptr = this->virtadr; struct Nand *mychip = &this->chips[ofs >> this->chipshift]; - if (len != mtd->erasesize) + if (len != mtd->erasesize) printk(KERN_WARNING "Erase not right size (%x != %x)n", len, mtd->erasesize); @@ -870,9 +870,9 @@ static void __exit cleanup_doc2001(void) while ((mtd=docmillist)) { this = mtd->priv; docmillist = this->nextdoc; - + del_mtd_device(mtd); - + iounmap(this->virtadr); kfree(this->chips); kfree(mtd); diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c index ed47bafb2ce..0595cc7324b 100644 --- a/drivers/mtd/devices/doc2001plus.c +++ b/drivers/mtd/devices/doc2001plus.c @@ -6,7 +6,7 @@ * (c) 1999 Machine Vision Holdings, Inc. * (c) 1999, 2000 David Woodhouse * - * $Id: doc2001plus.c,v 1.13 2005/01/05 18:05:12 dwmw2 Exp $ + * $Id: doc2001plus.c,v 1.14 2005/11/07 11:14:24 gleixner Exp $ * * Released under GPL */ @@ -293,10 +293,10 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip) DoC_Command(docptr, NAND_CMD_RESET, 0); DoC_WaitReady(docptr); - /* Read the NAND chip ID: 1. Send ReadID command */ + /* Read the NAND chip ID: 1. Send ReadID command */ DoC_Command(docptr, NAND_CMD_READID, 0); - /* Read the NAND chip ID: 2. Send address byte zero */ + /* Read the NAND chip ID: 2. Send address byte zero */ DoC_Address(doc, 1, 0x00, 0, 0x00); WriteDOC(0, docptr, Mplus_FlashControl); @@ -365,7 +365,7 @@ static void DoC_ScanChips(struct DiskOnChip *this) this->interleave = 1; /* Check the ASIC agrees */ - if ( (this->interleave << 2) != + if ( (this->interleave << 2) != (ReadDOC(this->virtadr, Mplus_Configuration) & 4)) { u_char conf = ReadDOC(this->virtadr, Mplus_Configuration); printk(KERN_NOTICE "Setting DiskOnChip Millennium Plus interleave to %s\n", @@ -398,7 +398,7 @@ static void DoC_ScanChips(struct DiskOnChip *this) return; } - /* Fill out the chip array with {floor, chipno} for each + /* Fill out the chip array with {floor, chipno} for each * detected chip in the device. */ for (floor = 0, ret = 0; floor < MAX_FLOORS_MPLUS; floor++) { for (chip = 0 ; chip < numchips[floor] ; chip++) { @@ -432,7 +432,7 @@ static int DoCMilPlus_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2) tmp2 = ReadDOC(doc2->virtadr, Mplus_AliasResolution); if (tmp1 != tmp2) return 0; - + WriteDOC((tmp1+1) % 0xff, doc1->virtadr, Mplus_AliasResolution); tmp2 = ReadDOC(doc2->virtadr, Mplus_AliasResolution); if (tmp2 == (tmp1+1) % 0xff) @@ -624,7 +624,7 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, return -EINVAL; /* Don't allow a single read to cross a 512-byte block boundary */ - if (from + len > ((from | 0x1ff) + 1)) + if (from + len > ((from | 0x1ff) + 1)) len = ((from | 0x1ff) + 1) - from; DoC_CheckASIC(docptr); @@ -1066,7 +1066,7 @@ int doc_erase(struct mtd_info *mtd, struct erase_info *instr) DoC_CheckASIC(docptr); - if (len != mtd->erasesize) + if (len != mtd->erasesize) printk(KERN_WARNING "MTD: Erase not right size (%x != %x)n", len, mtd->erasesize); @@ -1136,9 +1136,9 @@ static void __exit cleanup_doc2001plus(void) while ((mtd=docmilpluslist)) { this = mtd->priv; docmilpluslist = this->nextdoc; - + del_mtd_device(mtd); - + iounmap(this->virtadr); kfree(this->chips); kfree(mtd); diff --git a/drivers/mtd/devices/docecc.c b/drivers/mtd/devices/docecc.c index 24f670b5a4f..cd3db72bef9 100644 --- a/drivers/mtd/devices/docecc.c +++ b/drivers/mtd/devices/docecc.c @@ -4,10 +4,10 @@ * GNU GPL License. The rest is simply to convert the disk on chip * syndrom into a standard syndom. * - * Author: Fabrice Bellard (fabrice.bellard@netgem.com) + * Author: Fabrice Bellard (fabrice.bellard@netgem.com) * Copyright (C) 2000 Netgem S.A. * - * $Id: docecc.c,v 1.5 2003/05/21 15:15:06 dwmw2 Exp $ + * $Id: docecc.c,v 1.7 2005/11/07 11:14:25 gleixner Exp $ * * 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 @@ -122,7 +122,7 @@ for(ci=(n)-1;ci >=0;ci--)\ a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1) we consider the integer "i" whose binary representation with a(0) being LSB and a(m-1) MSB is (a(0),a(1),...,a(m-1)) and locate the entry - "index_of[i]". Now, @^index_of[i] is that element whose polynomial + "index_of[i]". Now, @^index_of[i] is that element whose polynomial representation is (a(0),a(1),a(2),...,a(m-1)). NOTE: The element alpha_to[2^m-1] = 0 always signifying that the @@ -130,7 +130,7 @@ for(ci=(n)-1;ci >=0;ci--)\ Similarily, the element index_of[0] = A0 always signifying that the power of alpha which has the polynomial representation (0,0,...,0) is "infinity". - + */ static void @@ -176,7 +176,7 @@ generate_gf(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1]) * are written back. NOTE! This array must be at least NN-KK elements long. * The corrected data are written in eras_val[]. They must be xor with the data * to retrieve the correct data : data[erase_pos[i]] ^= erase_val[i] . - * + * * First "no_eras" erasures are declared by the calling program. Then, the * maximum # of errors correctable is t_after_eras = floor((NN-KK-no_eras)/2). * If the number of channel errors is not greater than "t_after_eras" the @@ -189,7 +189,7 @@ generate_gf(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1]) * */ static int eras_dec_rs(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1], - gf bb[NN - KK + 1], gf eras_val[NN-KK], int eras_pos[NN-KK], + gf bb[NN - KK + 1], gf eras_val[NN-KK], int eras_pos[NN-KK], int no_eras) { int deg_lambda, el, deg_omega; @@ -212,7 +212,7 @@ eras_dec_rs(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1], count = 0; goto finish; } - + for(i=1;i<=NN-KK;i++){ s[i] = bb[0]; } @@ -220,7 +220,7 @@ eras_dec_rs(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1], if(bb[j] == 0) continue; tmp = Index_of[bb[j]]; - + for(i=1;i<=NN-KK;i++) s[i] ^= Alpha_to[modnn(tmp + (B0+i-1)*PRIM*j)]; } @@ -234,7 +234,7 @@ eras_dec_rs(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1], tmp = modnn(tmp + 2 * KK * (B0+i-1)*PRIM); s[i] = tmp; } - + CLEAR(&lambda[1],NN-KK); lambda[0] = 1; @@ -252,7 +252,7 @@ eras_dec_rs(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1], #if DEBUG_ECC >= 1 /* Test code that verifies the erasure locator polynomial just constructed Needed only for decoder debugging. */ - + /* find roots of the erasure location polynomial */ for(i=1;i<=no_eras;i++) reg[i] = Index_of[lambda[i]]; @@ -286,7 +286,7 @@ eras_dec_rs(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1], } for(i=0;i= 0; i -=2) { if(lambda[i+1] != A0) @@ -436,11 +436,11 @@ eras_dec_rs(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1], /* The sector bytes are packed into NB_DATA MM bits words */ #define NB_DATA (((SECTOR_SIZE + 1) * 8 + 6) / MM) -/* +/* * Correct the errors in 'sector[]' by using 'ecc1[]' which is the * content of the feedback shift register applyied to the sector and * the ECC. Return the number of errors corrected (and correct them in - * sector), or -1 if error + * sector), or -1 if error */ int doc_decode_ecc(unsigned char sector[SECTOR_SIZE], unsigned char ecc1[6]) { @@ -454,7 +454,7 @@ int doc_decode_ecc(unsigned char sector[SECTOR_SIZE], unsigned char ecc1[6]) Alpha_to = kmalloc((NN + 1) * sizeof(dtype), GFP_KERNEL); if (!Alpha_to) return -1; - + Index_of = kmalloc((NN + 1) * sizeof(dtype), GFP_KERNEL); if (!Index_of) { kfree(Alpha_to); @@ -470,7 +470,7 @@ int doc_decode_ecc(unsigned char sector[SECTOR_SIZE], unsigned char ecc1[6]) bb[2] = ((ecc1[2] & 0xf0) >> 4) | ((ecc1[3] & 0x3f) << 4); bb[3] = ((ecc1[3] & 0xc0) >> 6) | ((ecc1[0] & 0xff) << 2); - nb_errors = eras_dec_rs(Alpha_to, Index_of, bb, + nb_errors = eras_dec_rs(Alpha_to, Index_of, bb, error_val, error_pos, 0); if (nb_errors <= 0) goto the_end; @@ -489,7 +489,7 @@ int doc_decode_ecc(unsigned char sector[SECTOR_SIZE], unsigned char ecc1[6]) can be modified since pos is even */ index = (pos >> 3) ^ 1; bitpos = pos & 7; - if ((index >= 0 && index < SECTOR_SIZE) || + if ((index >= 0 && index < SECTOR_SIZE) || index == (SECTOR_SIZE + 1)) { val = error_val[i] >> (2 + bitpos); parity ^= val; @@ -500,7 +500,7 @@ int doc_decode_ecc(unsigned char sector[SECTOR_SIZE], unsigned char ecc1[6]) bitpos = (bitpos + 10) & 7; if (bitpos == 0) bitpos = 8; - if ((index >= 0 && index < SECTOR_SIZE) || + if ((index >= 0 && index < SECTOR_SIZE) || index == (SECTOR_SIZE + 1)) { val = error_val[i] << (8 - bitpos); parity ^= val; @@ -509,7 +509,7 @@ int doc_decode_ecc(unsigned char sector[SECTOR_SIZE], unsigned char ecc1[6]) } } } - + /* use parity to test extra errors */ if ((parity & 0xff) != 0) nb_errors = -1; diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c index 197d67045e1..13178b9dd00 100644 --- a/drivers/mtd/devices/docprobe.c +++ b/drivers/mtd/devices/docprobe.c @@ -4,22 +4,22 @@ /* (C) 1999 Machine Vision Holdings, Inc. */ /* (C) 1999-2003 David Woodhouse */ -/* $Id: docprobe.c,v 1.44 2005/01/05 12:40:36 dwmw2 Exp $ */ +/* $Id: docprobe.c,v 1.46 2005/11/07 11:14:25 gleixner Exp $ */ /* DOC_PASSIVE_PROBE: - In order to ensure that the BIOS checksum is correct at boot time, and - hence that the onboard BIOS extension gets executed, the DiskOnChip - goes into reset mode when it is read sequentially: all registers - return 0xff until the chip is woken up again by writing to the - DOCControl register. - - Unfortunately, this means that the probe for the DiskOnChip is unsafe, - because one of the first things it does is write to where it thinks - the DOCControl register should be - which may well be shared memory - for another device. I've had machines which lock up when this is - attempted. Hence the possibility to do a passive probe, which will fail + In order to ensure that the BIOS checksum is correct at boot time, and + hence that the onboard BIOS extension gets executed, the DiskOnChip + goes into reset mode when it is read sequentially: all registers + return 0xff until the chip is woken up again by writing to the + DOCControl register. + + Unfortunately, this means that the probe for the DiskOnChip is unsafe, + because one of the first things it does is write to where it thinks + the DOCControl register should be - which may well be shared memory + for another device. I've had machines which lock up when this is + attempted. Hence the possibility to do a passive probe, which will fail to detect a chip in reset mode, but is at least guaranteed not to lock the machine. @@ -33,9 +33,9 @@ The old Millennium-only driver has been retained just in case there are problems with the new code. If the combined driver doesn't work - for you, you can try the old one by undefining DOC_SINGLE_DRIVER + for you, you can try the old one by undefining DOC_SINGLE_DRIVER below and also enabling it in your configuration. If this fixes the - problems, please send a report to the MTD mailing list at + problems, please send a report to the MTD mailing list at . */ #define DOC_SINGLE_DRIVER @@ -68,16 +68,16 @@ MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe static unsigned long __initdata doc_locations[] = { #if defined (__alpha__) || defined(__i386__) || defined(__x86_64__) #ifdef CONFIG_MTD_DOCPROBE_HIGH - 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000, + 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000, 0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000, - 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000, - 0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000, + 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000, + 0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000, 0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000, #else /* CONFIG_MTD_DOCPROBE_HIGH */ - 0xc8000, 0xca000, 0xcc000, 0xce000, + 0xc8000, 0xca000, 0xcc000, 0xce000, 0xd0000, 0xd2000, 0xd4000, 0xd6000, - 0xd8000, 0xda000, 0xdc000, 0xde000, - 0xe0000, 0xe2000, 0xe4000, 0xe6000, + 0xd8000, 0xda000, 0xdc000, 0xde000, + 0xe0000, 0xe2000, 0xe4000, 0xe6000, 0xe8000, 0xea000, 0xec000, 0xee000, #endif /* CONFIG_MTD_DOCPROBE_HIGH */ #elif defined(__PPC__) @@ -111,35 +111,35 @@ static inline int __init doccheck(void __iomem *potential, unsigned long physadr return 0; #endif /* CONFIG_MTD_DOCPROBE_55AA */ -#ifndef DOC_PASSIVE_PROBE +#ifndef DOC_PASSIVE_PROBE /* It's not possible to cleanly detect the DiskOnChip - the * bootup procedure will put the device into reset mode, and * it's not possible to talk to it without actually writing * to the DOCControl register. So we store the current contents * of the DOCControl register's location, in case we later decide * that it's not a DiskOnChip, and want to put it back how we - * found it. + * found it. */ tmp2 = ReadDOC(window, DOCControl); - + /* Reset the DiskOnChip ASIC */ - WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, window, DOCControl); - WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, window, DOCControl); - + /* Enable the DiskOnChip ASIC */ - WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, window, DOCControl); - WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, window, DOCControl); -#endif /* !DOC_PASSIVE_PROBE */ +#endif /* !DOC_PASSIVE_PROBE */ /* We need to read the ChipID register four times. For some newer DiskOnChip 2000 units, the first three reads will return the DiskOnChip Millennium ident. Don't ask. */ ChipID = ReadDOC(window, ChipID); - + switch (ChipID) { case DOC_ChipID_Doc2k: /* Check the TOGGLE bit in the ECC register */ @@ -149,7 +149,7 @@ static inline int __init doccheck(void __iomem *potential, unsigned long physadr if (tmp != tmpb && tmp == tmpc) return ChipID; break; - + case DOC_ChipID_DocMil: /* Check for the new 2000 with Millennium ASIC */ ReadDOC(window, ChipID); @@ -164,7 +164,7 @@ static inline int __init doccheck(void __iomem *potential, unsigned long physadr if (tmp != tmpb && tmp == tmpc) return ChipID; break; - + case DOC_ChipID_DocMilPlus16: case DOC_ChipID_DocMilPlus32: case 0: @@ -179,7 +179,7 @@ static inline int __init doccheck(void __iomem *potential, unsigned long physadr DOC_MODE_BDECT; WriteDOC(tmp, window, Mplus_DOCControl); WriteDOC(~tmp, window, Mplus_CtrlConfirm); - + mdelay(1); /* Enable the DiskOnChip ASIC */ tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | @@ -187,7 +187,7 @@ static inline int __init doccheck(void __iomem *potential, unsigned long physadr WriteDOC(tmp, window, Mplus_DOCControl); WriteDOC(~tmp, window, Mplus_CtrlConfirm); mdelay(1); -#endif /* !DOC_PASSIVE_PROBE */ +#endif /* !DOC_PASSIVE_PROBE */ ChipID = ReadDOC(window, ChipID); @@ -227,7 +227,7 @@ static inline int __init doccheck(void __iomem *potential, unsigned long physadr WriteDOC(tmp2, window, DOCControl); #endif return 0; -} +} static int docfound; @@ -244,10 +244,10 @@ static void __init DoC_Probe(unsigned long physadr) void (*initroutine)(struct mtd_info *) = NULL; docptr = ioremap(physadr, DOC_IOREMAP_LEN); - + if (!docptr) return; - + if ((ChipID = doccheck(docptr, physadr))) { if (ChipID == DOC_ChipID_Doc2kTSOP) { /* Remove this at your own peril. The hardware driver works but nothing prevents you from erasing bad blocks */ @@ -263,9 +263,9 @@ static void __init DoC_Probe(unsigned long physadr) iounmap(docptr); return; } - + this = (struct DiskOnChip *)(&mtd[1]); - + memset((char *)mtd,0, sizeof(struct mtd_info)); memset((char *)this, 0, sizeof(struct DiskOnChip)); @@ -281,13 +281,13 @@ static void __init DoC_Probe(unsigned long physadr) im_funcname = "DoC2k_init"; im_modname = "doc2000"; break; - + case DOC_ChipID_Doc2k: name="2000"; im_funcname = "DoC2k_init"; im_modname = "doc2000"; break; - + case DOC_ChipID_DocMil: name="Millennium"; #ifdef DOC_SINGLE_DRIVER @@ -331,7 +331,7 @@ static void __init DoC_Probe(unsigned long physadr) static int __init init_doc(void) { int i; - + if (doc_config_location) { printk(KERN_INFO "Using configured DiskOnChip probe address 0x%lx\n", doc_config_location); DoC_Probe(doc_config_location); diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c index df987a53ed9..1e876fcb040 100644 --- a/drivers/mtd/devices/lart.c +++ b/drivers/mtd/devices/lart.c @@ -2,7 +2,7 @@ /* * MTD driver for the 28F160F3 Flash Memory (non-CFI) on LART. * - * $Id: lart.c,v 1.7 2004/08/09 13:19:44 dwmw2 Exp $ + * $Id: lart.c,v 1.9 2005/11/07 11:14:25 gleixner Exp $ * * Author: Abraham vd Merwe * @@ -122,7 +122,7 @@ static char module_name[] = "lart"; /* * The data line mapping on LART is as follows: - * + * * U2 CPU | U3 CPU * ------------------- * 0 20 | 0 12 @@ -181,7 +181,7 @@ static char module_name[] = "lart"; (((x) & 0x00004000) >> 13) \ ) -/* +/* * The address line mapping on LART is as follows: * * U3 CPU | U2 CPU @@ -204,7 +204,7 @@ static char module_name[] = "lart"; * 12 15 | 12 15 * 13 14 | 13 14 * 14 16 | 14 16 - * + * * MAIN BLOCK BOUNDARY * * 15 17 | 15 18 diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c index 765c0179c8d..e8685ee6c1e 100644 --- a/drivers/mtd/devices/phram.c +++ b/drivers/mtd/devices/phram.c @@ -1,5 +1,5 @@ /** - * $Id: phram.c,v 1.14 2005/03/07 21:43:38 joern Exp $ + * $Id: phram.c,v 1.16 2005/11/07 11:14:25 gleixner Exp $ * * Copyright (c) ???? Jochen Schäuble * Copyright (c) 2003-2004 Jörn Engel @@ -41,10 +41,10 @@ static int phram_erase(struct mtd_info *mtd, struct erase_info *instr) if (instr->addr + instr->len > mtd->size) return -EINVAL; - + memset(start + instr->addr, 0xff, instr->len); - /* This'll catch a few races. Free the thing before returning :) + /* This'll catch a few races. Free the thing before returning :) * I don't feel at all ashamed. This kind of thing is possible anyway * with flash, but unlikely. */ @@ -63,7 +63,7 @@ static int phram_point(struct mtd_info *mtd, loff_t from, size_t len, if (from + len > mtd->size) return -EINVAL; - + *mtdbuf = start + from; *retlen = len; return 0; @@ -84,7 +84,7 @@ static int phram_read(struct mtd_info *mtd, loff_t from, size_t len, if (len > mtd->size - from) len = mtd->size - from; - + memcpy(buf, start + from, len); *retlen = len; @@ -101,7 +101,7 @@ static int phram_write(struct mtd_info *mtd, loff_t to, size_t len, if (len > mtd->size - to) len = mtd->size - to; - + memcpy(start + to, buf, len); *retlen = len; @@ -159,7 +159,7 @@ static int register_device(char *name, unsigned long start, unsigned long len) } list_add_tail(&new->list, &phram_list); - return 0; + return 0; out2: iounmap(new->mtd.priv); diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c index 5b3defadf88..de48b35f560 100644 --- a/drivers/mtd/devices/pmc551.c +++ b/drivers/mtd/devices/pmc551.c @@ -1,5 +1,5 @@ /* - * $Id: pmc551.c,v 1.30 2005/01/05 18:05:13 dwmw2 Exp $ + * $Id: pmc551.c,v 1.32 2005/11/07 11:14:25 gleixner Exp $ * * PMC551 PCI Mezzanine Ram Device * @@ -27,7 +27,7 @@ * it as high speed swap or for a high speed disk device of some * sort. Which becomes very useful on diskless systems in the * embedded market I might add. - * + * * Notes: * Due to what I assume is more buggy SROM, the 64M PMC551 I * have available claims that all 4 of it's DRAM banks have 64M @@ -63,10 +63,10 @@ * Minyard set up the card to utilize a 1M sliding apature. * * Corey Minyard - * * Modified driver to utilize a sliding aperture instead of + * * Modified driver to utilize a sliding aperture instead of * mapping all memory into kernel space which turned out to * be very wasteful. - * * Located a bug in the SROM's initialization sequence that + * * Located a bug in the SROM's initialization sequence that * made the memory unusable, added a fix to code to touch up * the DRAM some. * @@ -390,7 +390,7 @@ static u32 fixup_pmc551 (struct pci_dev *dev) bcmd |= (0x40|0x20); pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); - /* + /* * Take care and turn off the memory on the device while we * tweak the configurations */ @@ -408,7 +408,7 @@ static u32 fixup_pmc551 (struct pci_dev *dev) * Grab old BAR0 config so that we can figure out memory size * This is another bit of kludge going on. The reason for the * redundancy is I am hoping to retain the original configuration - * previously assigned to the card by the BIOS or some previous + * previously assigned to the card by the BIOS or some previous * fixup routine in the kernel. So we read the old config into cfg, * then write all 1's to the memory space, read back the result into * "size", and then write back all the old config. @@ -480,7 +480,7 @@ static u32 fixup_pmc551 (struct pci_dev *dev) } while ( (PCI_COMMAND_IO) & cmd ); /* - * Turn on auto refresh + * Turn on auto refresh * The loop is taken directly from Ramix's example code. I assume that * this must be held high for some duration of time, but I can find no * documentation refrencing the reasons why. @@ -615,7 +615,7 @@ static u32 fixup_pmc551 (struct pci_dev *dev) pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd ); printk( KERN_DEBUG "pmc551: EEPROM is under %s control\n" "pmc551: System Control Register is %slocked to PCI access\n" - "pmc551: System Control Register is %slocked to EEPROM access\n", + "pmc551: System Control Register is %slocked to EEPROM access\n", (bcmd&0x1)?"software":"hardware", (bcmd&0x20)?"":"un", (bcmd&0x40)?"":"un"); #endif @@ -744,7 +744,7 @@ static int __init init_pmc551(void) priv->start = ioremap(((PCI_Device->resource[0].start) & PCI_BASE_ADDRESS_MEM_MASK), priv->asize); - + if (!priv->start) { printk(KERN_NOTICE "pmc551: Unable to map IO space\n"); kfree(mtd->priv); @@ -765,7 +765,7 @@ static int __init init_pmc551(void) priv->curr_map0 ); #ifdef CONFIG_MTD_PMC551_DEBUG - printk( KERN_DEBUG "pmc551: aperture set to %d\n", + printk( KERN_DEBUG "pmc551: aperture set to %d\n", (priv->base_map0 & 0xF0)>>4 ); #endif @@ -823,13 +823,13 @@ static void __exit cleanup_pmc551(void) while((mtd=pmc551list)) { priv = mtd->priv; pmc551list = priv->nextpmc551; - + if(priv->start) { printk (KERN_DEBUG "pmc551: unmapping %dM starting at 0x%p\n", priv->asize>>20, priv->start); iounmap (priv->start); } - + kfree (mtd->priv); del_mtd_device (mtd); kfree (mtd); diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c index 84fa91392a8..6faee6c6958 100644 --- a/drivers/mtd/devices/slram.c +++ b/drivers/mtd/devices/slram.c @@ -1,6 +1,6 @@ /*====================================================================== - $Id: slram.c,v 1.34 2005/01/06 21:16:42 jwboyer Exp $ + $Id: slram.c,v 1.36 2005/11/07 11:14:25 gleixner Exp $ This driver provides a method to access memory not used by the kernel itself (i.e. if the kernel commandline mem=xxx is used). To actually @@ -18,14 +18,14 @@ : start of the memory region, decimal or hex (0xabcdef) : end of the memory region. It's possible to use +0x1234 to specify the offset instead of the absolute address - + NOTE: With slram it's only possible to map a contigous memory region. Therfore if there's a device mapped somewhere in the region specified slram will fail to load (see kernel log if modprobe fails). - - + Jochen Schaeuble ======================================================================*/ @@ -89,10 +89,10 @@ static int slram_erase(struct mtd_info *mtd, struct erase_info *instr) if (instr->addr + instr->len > mtd->size) { return(-EINVAL); } - + memset(priv->start + instr->addr, 0xff, instr->len); - /* This'll catch a few races. Free the thing before returning :) + /* This'll catch a few races. Free the thing before returning :) * I don't feel at all ashamed. This kind of thing is possible anyway * with flash, but unlikely. */ @@ -170,12 +170,12 @@ static int register_device(char *name, unsigned long start, unsigned long length } (*curmtd)->mtdinfo = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); (*curmtd)->next = NULL; - + if ((*curmtd)->mtdinfo) { memset((char *)(*curmtd)->mtdinfo, 0, sizeof(struct mtd_info)); (*curmtd)->mtdinfo->priv = kmalloc(sizeof(slram_priv_t), GFP_KERNEL); - + if (!(*curmtd)->mtdinfo->priv) { kfree((*curmtd)->mtdinfo); (*curmtd)->mtdinfo = NULL; @@ -188,7 +188,7 @@ static int register_device(char *name, unsigned long start, unsigned long length E("slram: Cannot allocate new MTD device.\n"); return(-ENOMEM); } - + if (!(((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start = ioremap(start, length))) { E("slram: ioremap failed\n"); @@ -223,7 +223,7 @@ static int register_device(char *name, unsigned long start, unsigned long length T("slram: Mapped from 0x%p to 0x%p\n", ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start, ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->end); - return(0); + return(0); } static void unregister_devices(void) @@ -256,7 +256,7 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength) char *buffer; unsigned long devstart; unsigned long devlength; - + if ((!devname) || (!szstart) || (!szlength)) { unregister_devices(); return(-EINVAL); @@ -264,7 +264,7 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength) devstart = simple_strtoul(szstart, &buffer, 0); devstart = handle_unit(devstart, buffer); - + if (*(szlength) != '+') { devlength = simple_strtoul(szlength, &buffer, 0); devlength = handle_unit(devlength, buffer) - devstart; @@ -278,7 +278,7 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength) E("slram: Illegal start / length parameter.\n"); return(-EINVAL); } - + if ((devstart = register_device(devname, devstart, devlength))){ unregister_devices(); return((int)devstart); @@ -335,7 +335,7 @@ static int init_slram(void) } #else int count; - + for (count = 0; (map[count]) && (count < SLRAM_MAX_DEVICES_PARAMS); count++) { } @@ -350,10 +350,10 @@ static int init_slram(void) if (parse_cmdline(devname, map[i * 3 + 1], map[i * 3 + 2])!=0) { return(-EINVAL); } - + } #endif /* !MODULE */ - + return(0); } -- cgit v1.2.3 From 61b03bd7c3b55498c6180d43bf71b7bf49114b64 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 11:15:49 +0000 Subject: [MTD] NAND: Clean up trailing white spaces Signed-off-by: Thomas Gleixner --- drivers/mtd/nand/Kconfig | 10 +- drivers/mtd/nand/au1550nd.c | 58 ++--- drivers/mtd/nand/autcpu12.c | 22 +- drivers/mtd/nand/diskonchip.c | 100 ++++---- drivers/mtd/nand/edb7312.c | 48 ++-- drivers/mtd/nand/h1910.c | 48 ++-- drivers/mtd/nand/nand_base.c | 478 +++++++++++++++++++------------------- drivers/mtd/nand/nand_bbt.c | 248 ++++++++++---------- drivers/mtd/nand/nand_ecc.c | 44 ++-- drivers/mtd/nand/nand_ids.c | 30 +-- drivers/mtd/nand/nandsim.c | 162 ++++++------- drivers/mtd/nand/ppchameleonevb.c | 6 +- drivers/mtd/nand/rtc_from4.c | 58 ++--- drivers/mtd/nand/s3c2410.c | 30 +-- drivers/mtd/nand/sharpsl.c | 22 +- drivers/mtd/nand/spia.c | 6 +- drivers/mtd/nand/toto.c | 20 +- 17 files changed, 695 insertions(+), 695 deletions(-) diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index f6f5ac80895..1fc4c134d93 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -1,5 +1,5 @@ # drivers/mtd/nand/Kconfig -# $Id: Kconfig,v 1.34 2005/09/23 01:44:55 ppopov Exp $ +# $Id: Kconfig,v 1.35 2005/11/07 11:14:30 gleixner Exp $ menu "NAND Flash Device Drivers" depends on MTD!=n @@ -27,14 +27,14 @@ config MTD_NAND_AUTCPU12 tristate "SmartMediaCard on autronix autcpu12 board" depends on MTD_NAND && ARCH_AUTCPU12 help - This enables the driver for the autronix autcpu12 board to + This enables the driver for the autronix autcpu12 board to access the SmartMediaCard. config MTD_NAND_EDB7312 tristate "Support for Cirrus Logic EBD7312 evaluation board" depends on MTD_NAND && ARCH_EDB7312 help - This enables the driver for the Cirrus Logic EBD7312 evaluation + This enables the driver for the Cirrus Logic EBD7312 evaluation board to access the onboard NAND Flash. config MTD_NAND_H1900 @@ -71,7 +71,7 @@ config MTD_NAND_RTC_FROM4 select REED_SOLOMON select REED_SOLOMON_DEC8 help - This enables the driver for the Renesas Technology AG-AND + This enables the driver for the Renesas Technology AG-AND flash interface board (FROM_BOARD4) config MTD_NAND_PPCHAMELEONEVB @@ -88,7 +88,7 @@ config MTD_NAND_S3C2410 SoCs No board specfic support is done by this driver, each board - must advertise a platform_device for the driver to attach. + must advertise a platform_device for the driver to attach. config MTD_NAND_S3C2410_DEBUG bool "S3C2410 NAND driver debug" diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 953daf379b9..3cafcdf28ae 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c @@ -3,7 +3,7 @@ * * Copyright (C) 2004 Embedded Edge, LLC * - * $Id: au1550nd.c,v 1.12 2005/09/23 01:44:55 ppopov Exp $ + * $Id: au1550nd.c,v 1.13 2005/11/07 11:14:30 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -25,10 +25,10 @@ #else #include #ifdef CONFIG_MIPS_PB1550 -#include +#include #endif #ifdef CONFIG_MIPS_DB1550 -#include +#include #endif #endif @@ -43,12 +43,12 @@ static int nand_width = 1; /* default x8*/ * Define partitions for flash device */ const static struct mtd_partition partition_info[] = { - { + { .name = "NAND FS 0", .offset = 0, - .size = 8*1024*1024 + .size = 8*1024*1024 }, - { + { .name = "NAND FS 1", .offset = MTDPART_OFS_APPEND, .size = MTDPART_SIZ_FULL @@ -89,7 +89,7 @@ static void au_write_byte(struct mtd_info *mtd, u_char byte) * au_read_byte16 - read one byte endianess aware from the chip * @mtd: MTD device structure * - * read function for 16bit buswith with + * read function for 16bit buswith with * endianess conversion */ static u_char au_read_byte16(struct mtd_info *mtd) @@ -119,7 +119,7 @@ static void au_write_byte16(struct mtd_info *mtd, u_char byte) * au_read_word - read one word from the chip * @mtd: MTD device structure * - * read function for 16bit buswith without + * read function for 16bit buswith without * endianess conversion */ static u16 au_read_word(struct mtd_info *mtd) @@ -135,7 +135,7 @@ static u16 au_read_word(struct mtd_info *mtd) * @mtd: MTD device structure * @word: data word to write * - * write function for 16bit buswith without + * write function for 16bit buswith without * endianess conversion */ static void au_write_word(struct mtd_info *mtd, u16 word) @@ -165,7 +165,7 @@ static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len) } /** - * au_read_buf - read chip data into buffer + * au_read_buf - read chip data into buffer * @mtd: MTD device structure * @buf: buffer to store date * @len: number of bytes to read @@ -179,12 +179,12 @@ static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len) for (i=0; iIO_ADDR_R); - au_sync(); + au_sync(); } } /** - * au_verify_buf - Verify chip data against buffer + * au_verify_buf - Verify chip data against buffer * @mtd: MTD device structure * @buf: buffer containing the data to compare * @len: number of bytes to compare @@ -219,16 +219,16 @@ static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len) struct nand_chip *this = mtd->priv; u16 *p = (u16 *) buf; len >>= 1; - + for (i=0; iIO_ADDR_W); au_sync(); } - + } /** - * au_read_buf16 - read chip data into buffer + * au_read_buf16 - read chip data into buffer * @mtd: MTD device structure * @buf: buffer to store date * @len: number of bytes to read @@ -249,7 +249,7 @@ static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len) } /** - * au_verify_buf16 - Verify chip data against buffer + * au_verify_buf16 - Verify chip data against buffer * @mtd: MTD device structure * @buf: buffer containing the data to compare * @len: number of bytes to compare @@ -282,26 +282,26 @@ static void au1550_hwcontrol(struct mtd_info *mtd, int cmd) case NAND_CTL_CLRCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; break; case NAND_CTL_SETALE: this->IO_ADDR_W = p_nand + MEM_STNAND_ADDR; break; - case NAND_CTL_CLRALE: - this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; - /* FIXME: Nobody knows why this is neccecary, + case NAND_CTL_CLRALE: + this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; + /* FIXME: Nobody knows why this is neccecary, * but it works only that way */ - udelay(1); + udelay(1); break; - case NAND_CTL_SETNCE: + case NAND_CTL_SETNCE: /* assert (force assert) chip enable */ au_writel((1<<(4+NAND_CS)) , MEM_STNDCTL); break; break; - case NAND_CTL_CLRNCE: + case NAND_CTL_CLRNCE: /* deassert chip enable */ au_writel(0, MEM_STNDCTL); break; break; } this->IO_ADDR_R = this->IO_ADDR_W; - + /* Drain the writebuffer */ au_sync(); } @@ -325,7 +325,7 @@ int __init au1xxx_nand_init (void) u32 nand_phys; /* Allocate memory for MTD device structure and private data */ - au1550_mtd = kmalloc (sizeof(struct mtd_info) + + au1550_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), GFP_KERNEL); if (!au1550_mtd) { printk ("Unable to allocate NAND MTD dev structure.\n"); @@ -345,7 +345,7 @@ int __init au1xxx_nand_init (void) /* disable interrupts */ au_writel(au_readl(MEM_STNDCTL) & ~(1<<8), MEM_STNDCTL); - + /* disable NAND boot */ au_writel(au_readl(MEM_STNDCTL) & ~(1<<0), MEM_STNDCTL); @@ -353,7 +353,7 @@ int __init au1xxx_nand_init (void) /* set gpio206 high */ au_writel(au_readl(GPIO2_DIR) & ~(1<<6), GPIO2_DIR); - boot_swapboot = (au_readl(MEM_STSTAT) & (0x7<<1)) | + boot_swapboot = (au_readl(MEM_STSTAT) & (0x7<<1)) | ((bcsr->status >> 6) & 0x1); switch (boot_swapboot) { case 0: @@ -402,7 +402,7 @@ int __init au1xxx_nand_init (void) au_writel(NAND_STADDR, MEM_STADDR3); } #endif - + /* Locate NAND chip-select in order to determine NAND phys address */ mem_staddr = 0x00000000; if (((au_readl(MEM_STCFG0) & 0x7) == 0x5) && (NAND_CS == 0)) @@ -438,7 +438,7 @@ int __init au1xxx_nand_init (void) this->hwcontrol = au1550_hwcontrol; this->dev_ready = au1550_device_ready; /* 30 us command delay time */ - this->chip_delay = 30; + this->chip_delay = 30; this->eccmode = NAND_ECC_SOFT; this->options = NAND_NO_AUTOINCR; @@ -467,7 +467,7 @@ int __init au1xxx_nand_init (void) outio: iounmap ((void *)p_nand); - + outmem: kfree (au1550_mtd); return retval; diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c index 4afa8ced05a..056dfc17a07 100644 --- a/drivers/mtd/nand/autcpu12.c +++ b/drivers/mtd/nand/autcpu12.c @@ -5,8 +5,8 @@ * * Derived from drivers/mtd/spia.c * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) - * - * $Id: autcpu12.c,v 1.22 2004/11/04 12:53:10 gleixner Exp $ + * + * $Id: autcpu12.c,v 1.23 2005/11/07 11:14:30 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -14,7 +14,7 @@ * * Overview: * This is a device driver for the NAND flash device found on the - * autronix autcpu12 board, which is a SmartMediaCard. It supports + * autronix autcpu12 board, which is a SmartMediaCard. It supports * 16MiB, 32MiB and 64MiB cards. * * @@ -93,7 +93,7 @@ static struct mtd_partition partition_info128k[] = { #define NUM_PARTITIONS32K 2 #define NUM_PARTITIONS64K 2 #define NUM_PARTITIONS128K 2 -/* +/* * hardware specific access to control-lines */ static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd) @@ -163,7 +163,7 @@ int __init autcpu12_init (void) this->hwcontrol = autcpu12_hwcontrol; this->dev_ready = autcpu12_device_ready; /* 20 us command delay time */ - this->chip_delay = 20; + this->chip_delay = 20; this->eccmode = NAND_ECC_SOFT; /* Enable the following for a flash based bad block table */ @@ -171,21 +171,21 @@ int __init autcpu12_init (void) this->options = NAND_USE_FLASH_BBT; */ this->options = NAND_USE_FLASH_BBT; - + /* Scan to find existance of the device */ if (nand_scan (autcpu12_mtd, 1)) { err = -ENXIO; goto out_ior; } - + /* Register the partitions */ switch(autcpu12_mtd->size){ case SZ_16M: add_mtd_partitions(autcpu12_mtd, partition_info16k, NUM_PARTITIONS16K); break; case SZ_32M: add_mtd_partitions(autcpu12_mtd, partition_info32k, NUM_PARTITIONS32K); break; - case SZ_64M: add_mtd_partitions(autcpu12_mtd, partition_info64k, NUM_PARTITIONS64K); break; - case SZ_128M: add_mtd_partitions(autcpu12_mtd, partition_info128k, NUM_PARTITIONS128K); break; + case SZ_64M: add_mtd_partitions(autcpu12_mtd, partition_info64k, NUM_PARTITIONS64K); break; + case SZ_128M: add_mtd_partitions(autcpu12_mtd, partition_info128k, NUM_PARTITIONS128K); break; default: { - printk ("Unsupported SmartMedia device\n"); + printk ("Unsupported SmartMedia device\n"); err = -ENXIO; goto out_ior; } @@ -213,7 +213,7 @@ static void __exit autcpu12_cleanup (void) /* unmap physical adress */ iounmap((void *)autcpu12_fio_base); - + /* Free the MTD device structure */ kfree (autcpu12_mtd); } diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index fdb5d4ad3d5..21d4e8f4b7a 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -1,4 +1,4 @@ -/* +/* * drivers/mtd/nand/diskonchip.c * * (C) 2003 Red Hat, Inc. @@ -8,15 +8,15 @@ * Author: David Woodhouse * Additional Diskonchip 2000 and Millennium support by Dan Brown * Diskonchip Millennium Plus support by Kalev Lember - * + * * Error correction code lifted from the old docecc code - * Author: Fabrice Bellard (fabrice.bellard@netgem.com) + * Author: Fabrice Bellard (fabrice.bellard@netgem.com) * Copyright (C) 2000 Netgem S.A. * converted to the generic Reed-Solomon library by Thomas Gleixner - * + * * Interface to generic NAND code for M-Systems DiskOnChip devices * - * $Id: diskonchip.c,v 1.54 2005/04/07 14:22:55 dbrown Exp $ + * $Id: diskonchip.c,v 1.55 2005/11/07 11:14:30 gleixner Exp $ */ #include @@ -42,16 +42,16 @@ static unsigned long __initdata doc_locations[] = { #if defined (__alpha__) || defined(__i386__) || defined(__x86_64__) #ifdef CONFIG_MTD_NAND_DISKONCHIP_PROBE_HIGH - 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000, + 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000, 0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000, - 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000, - 0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000, + 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000, + 0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000, 0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000, #else /* CONFIG_MTD_DOCPROBE_HIGH */ - 0xc8000, 0xca000, 0xcc000, 0xce000, + 0xc8000, 0xca000, 0xcc000, 0xce000, 0xd0000, 0xd2000, 0xd4000, 0xd6000, - 0xd8000, 0xda000, 0xdc000, 0xde000, - 0xe0000, 0xe2000, 0xe4000, 0xe6000, + 0xd8000, 0xda000, 0xdc000, 0xde000, + 0xe0000, 0xe2000, 0xe4000, 0xe6000, 0xe8000, 0xea000, 0xec000, 0xee000, #endif /* CONFIG_MTD_DOCPROBE_HIGH */ #elif defined(__PPC__) @@ -138,7 +138,7 @@ MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe /* the Reed Solomon control structure */ static struct rs_control *rs_decoder; -/* +/* * The HW decoder in the DoC ASIC's provides us a error syndrome, * which we must convert to a standard syndrom usable by the generic * Reed-Solomon library code. @@ -163,8 +163,8 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) /* Initialize the syndrom buffer */ for (i = 0; i < NROOTS; i++) s[i] = ds[0]; - /* - * Evaluate + /* + * Evaluate * s[i] = ds[3]x^3 + ds[2]x^2 + ds[1]x^1 + ds[0] * where x = alpha^(FCR + i) */ @@ -188,7 +188,7 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) if (nerr < 0) return nerr; - /* + /* * Correct the errors. The bitpositions are a bit of magic, * but they are given by the design of the de/encoder circuit * in the DoC ASIC's. @@ -205,7 +205,7 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) can be modified since pos is even */ index = (pos >> 3) ^ 1; bitpos = pos & 7; - if ((index >= 0 && index < SECTOR_SIZE) || + if ((index >= 0 && index < SECTOR_SIZE) || index == (SECTOR_SIZE + 1)) { val = (uint8_t) (errval[i] >> (2 + bitpos)); parity ^= val; @@ -216,7 +216,7 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) bitpos = (bitpos + 10) & 7; if (bitpos == 0) bitpos = 8; - if ((index >= 0 && index < SECTOR_SIZE) || + if ((index >= 0 && index < SECTOR_SIZE) || index == (SECTOR_SIZE + 1)) { val = (uint8_t)(errval[i] << (8 - bitpos)); parity ^= val; @@ -233,7 +233,7 @@ static void DoC_Delay(struct doc_priv *doc, unsigned short cycles) { volatile char dummy; int i; - + for (i = 0; i < cycles; i++) { if (DoC_is_Millennium(doc)) dummy = ReadDOC(doc->virtadr, NOP); @@ -242,7 +242,7 @@ static void DoC_Delay(struct doc_priv *doc, unsigned short cycles) else dummy = ReadDOC(doc->virtadr, DOCStatus); } - + } #define CDSN_CTRL_FR_B_MASK (CDSN_CTRL_FR_B0 | CDSN_CTRL_FR_B1) @@ -327,7 +327,7 @@ static u_char doc2000_read_byte(struct mtd_info *mtd) return ret; } -static void doc2000_writebuf(struct mtd_info *mtd, +static void doc2000_writebuf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd->priv; @@ -343,7 +343,7 @@ static void doc2000_writebuf(struct mtd_info *mtd, if (debug) printk("\n"); } -static void doc2000_readbuf(struct mtd_info *mtd, +static void doc2000_readbuf(struct mtd_info *mtd, u_char *buf, int len) { struct nand_chip *this = mtd->priv; @@ -358,7 +358,7 @@ static void doc2000_readbuf(struct mtd_info *mtd, } } -static void doc2000_readbuf_dword(struct mtd_info *mtd, +static void doc2000_readbuf_dword(struct mtd_info *mtd, u_char *buf, int len) { struct nand_chip *this = mtd->priv; @@ -379,7 +379,7 @@ static void doc2000_readbuf_dword(struct mtd_info *mtd, } } -static int doc2000_verifybuf(struct mtd_info *mtd, +static int doc2000_verifybuf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd->priv; @@ -406,12 +406,12 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) doc200x_hwcontrol(mtd, NAND_CTL_SETALE); this->write_byte(mtd, 0); doc200x_hwcontrol(mtd, NAND_CTL_CLRALE); - + /* We cant' use dev_ready here, but at least we wait for the - * command to complete + * command to complete */ udelay(50); - + ret = this->read_byte(mtd) << 8; ret |= this->read_byte(mtd); @@ -438,7 +438,7 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) this->read_buf = &doc2000_readbuf_dword; } } - + return ret; } @@ -469,7 +469,7 @@ static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this, int state) struct doc_priv *doc = this->priv; int status; - + DoC_WaitReady(doc); this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); DoC_WaitReady(doc); @@ -503,7 +503,7 @@ static u_char doc2001_read_byte(struct mtd_info *mtd) return ReadDOC(docptr, LastDataRead); } -static void doc2001_writebuf(struct mtd_info *mtd, +static void doc2001_writebuf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd->priv; @@ -517,7 +517,7 @@ static void doc2001_writebuf(struct mtd_info *mtd, WriteDOC(0x00, docptr, WritePipeTerm); } -static void doc2001_readbuf(struct mtd_info *mtd, +static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len) { struct nand_chip *this = mtd->priv; @@ -535,7 +535,7 @@ static void doc2001_readbuf(struct mtd_info *mtd, buf[i] = ReadDOC(docptr, LastDataRead); } -static int doc2001_verifybuf(struct mtd_info *mtd, +static int doc2001_verifybuf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd->priv; @@ -570,7 +570,7 @@ static u_char doc2001plus_read_byte(struct mtd_info *mtd) return ret; } -static void doc2001plus_writebuf(struct mtd_info *mtd, +static void doc2001plus_writebuf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd->priv; @@ -587,7 +587,7 @@ static void doc2001plus_writebuf(struct mtd_info *mtd, if (debug) printk("\n"); } -static void doc2001plus_readbuf(struct mtd_info *mtd, +static void doc2001plus_readbuf(struct mtd_info *mtd, u_char *buf, int len) { struct nand_chip *this = mtd->priv; @@ -617,7 +617,7 @@ static void doc2001plus_readbuf(struct mtd_info *mtd, if (debug) printk("\n"); } -static int doc2001plus_verifybuf(struct mtd_info *mtd, +static int doc2001plus_verifybuf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd->priv; @@ -797,7 +797,7 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col WriteDOC(0, docptr, Mplus_FlashControl); } - /* + /* * program and erase have their own busy handlers * status and sequential in needs no delay */ @@ -822,7 +822,7 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col /* This applies to read commands */ default: - /* + /* * If we don't have access to the busy pin, we apply the given * command delay */ @@ -945,7 +945,7 @@ static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, for (i = 0; i < 6; i++) { if (DoC_is_MillenniumPlus(doc)) ecc_code[i] = ReadDOC_(docptr, DoC_Mplus_ECCSyndrome0 + i); - else + else ecc_code[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i); if (ecc_code[i] != empty_write_ecc[i]) emptymatch = 0; @@ -982,7 +982,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ void __iomem *docptr = doc->virtadr; volatile u_char dummy; int emptymatch = 1; - + /* flush the pipeline */ if (DoC_is_2000(doc)) { dummy = ReadDOC(docptr, 2k_ECCStatus); @@ -997,7 +997,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ dummy = ReadDOC(docptr, ECCConf); dummy = ReadDOC(docptr, ECCConf); } - + /* Error occured ? */ if (dummy & 0x80) { for (i = 0; i < 6; i++) { @@ -1035,7 +1035,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ if (!emptymatch) ret = doc_ecc_decode (rs_decoder, dat, calc_ecc); if (ret > 0) printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret); - } + } if (DoC_is_MillenniumPlus(doc)) WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf); else @@ -1046,7 +1046,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ } return ret; } - + //u_char mydatabuf[528]; /* The strange out-of-order .oobfree list below is a (possibly unneeded) @@ -1065,7 +1065,7 @@ static struct nand_oobinfo doc200x_oobinfo = { .eccpos = {0, 1, 2, 3, 4, 5}, .oobfree = { {8, 8}, {6, 2} } }; - + /* Find the (I)NFTL Media Header, and optionally also the mirror media header. On sucessful return, buf will contain a copy of the media header for further processing. id is the string to scan for, and will presumably be @@ -1251,7 +1251,7 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, mh->BlockMultiplierBits = le32_to_cpu(mh->BlockMultiplierBits); mh->FormatFlags = le32_to_cpu(mh->FormatFlags); mh->PercentUsed = le32_to_cpu(mh->PercentUsed); - + printk(KERN_INFO " bootRecordID = %s\n" " NoOfBootImageBlocks = %d\n" " NoOfBinaryPartitions = %d\n" @@ -1468,7 +1468,7 @@ static inline int __init doc2001_init(struct mtd_info *mtd) ReadDOC(doc->virtadr, ChipID); if (ReadDOC(doc->virtadr, ChipID) != DOC_ChipID_DocMil) { /* It's not a Millennium; it's one of the newer - DiskOnChip 2000 units with a similar ASIC. + DiskOnChip 2000 units with a similar ASIC. Treat it like a Millennium, except that it can have multiple chips. */ doc2000_count_chips(mtd); @@ -1530,20 +1530,20 @@ static inline int __init doc_probe(unsigned long physadr) * to the DOCControl register. So we store the current contents * of the DOCControl register's location, in case we later decide * that it's not a DiskOnChip, and want to put it back how we - * found it. + * found it. */ save_control = ReadDOC(virtadr, DOCControl); /* Reset the DiskOnChip ASIC */ - WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, virtadr, DOCControl); - WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, virtadr, DOCControl); /* Enable the DiskOnChip ASIC */ - WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, virtadr, DOCControl); - WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, virtadr, DOCControl); ChipID = ReadDOC(virtadr, ChipID); @@ -1738,7 +1738,7 @@ static int __init init_nanddoc(void) int i, ret = 0; /* We could create the decoder on demand, if memory is a concern. - * This way we have it handy, if an error happens + * This way we have it handy, if an error happens * * Symbolsize is 10 (bits) * Primitve polynomial is x^10+x^3+1 diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c index 5549681ccdc..9b1fd2f387f 100644 --- a/drivers/mtd/nand/edb7312.c +++ b/drivers/mtd/nand/edb7312.c @@ -6,7 +6,7 @@ * Derived from drivers/mtd/nand/autcpu12.c * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) * - * $Id: edb7312.c,v 1.11 2004/11/04 12:53:10 gleixner Exp $ + * $Id: edb7312.c,v 1.12 2005/11/07 11:14:30 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -71,27 +71,27 @@ static struct mtd_partition partition_info[] = { #endif -/* +/* * hardware specific access to control-lines */ -static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd) +static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd) { switch(cmd) { - - case NAND_CTL_SETCLE: - clps_writeb(clps_readb(ep7312_pxdr) | 0x10, ep7312_pxdr); + + case NAND_CTL_SETCLE: + clps_writeb(clps_readb(ep7312_pxdr) | 0x10, ep7312_pxdr); break; - case NAND_CTL_CLRCLE: + case NAND_CTL_CLRCLE: clps_writeb(clps_readb(ep7312_pxdr) & ~0x10, ep7312_pxdr); break; - + case NAND_CTL_SETALE: clps_writeb(clps_readb(ep7312_pxdr) | 0x20, ep7312_pxdr); break; case NAND_CTL_CLRALE: clps_writeb(clps_readb(ep7312_pxdr) & ~0x20, ep7312_pxdr); break; - + case NAND_CTL_SETNCE: clps_writeb((clps_readb(ep7312_pxdr) | 0x80) & ~0x40, ep7312_pxdr); break; @@ -122,16 +122,16 @@ static int __init ep7312_init (void) int mtd_parts_nb = 0; struct mtd_partition *mtd_parts = 0; void __iomem * ep7312_fio_base; - + /* Allocate memory for MTD device structure and private data */ - ep7312_mtd = kmalloc(sizeof(struct mtd_info) + + ep7312_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); if (!ep7312_mtd) { printk("Unable to allocate EDB7312 NAND MTD device structure.\n"); return -ENOMEM; } - + /* map physical adress */ ep7312_fio_base = ioremap(ep7312_fio_pbase, SZ_1K); if(!ep7312_fio_base) { @@ -139,23 +139,23 @@ static int __init ep7312_init (void) kfree(ep7312_mtd); return -EIO; } - + /* Get pointer to private data */ this = (struct nand_chip *) (&ep7312_mtd[1]); - + /* Initialize structures */ memset((char *) ep7312_mtd, 0, sizeof(struct mtd_info)); memset((char *) this, 0, sizeof(struct nand_chip)); - + /* Link the private data with the MTD structure */ ep7312_mtd->priv = this; - + /* * Set GPIO Port B control register so that the pins are configured * to be outputs for controlling the NAND flash. */ clps_writeb(0xf0, ep7312_pxddr); - + /* insert callbacks */ this->IO_ADDR_R = ep7312_fio_base; this->IO_ADDR_W = ep7312_fio_base; @@ -163,14 +163,14 @@ static int __init ep7312_init (void) this->dev_ready = ep7312_device_ready; /* 15 us command delay time */ this->chip_delay = 15; - + /* Scan to find existence of the device */ if (nand_scan (ep7312_mtd, 1)) { iounmap((void *)ep7312_fio_base); kfree (ep7312_mtd); return -ENXIO; } - + #ifdef CONFIG_MTD_PARTITIONS ep7312_mtd->name = "edb7312-nand"; mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, @@ -185,11 +185,11 @@ static int __init ep7312_init (void) mtd_parts_nb = NUM_PARTITIONS; part_type = "static"; } - + /* Register the partitions */ printk(KERN_NOTICE "Using %s partition definition\n", part_type); add_mtd_partitions(ep7312_mtd, mtd_parts, mtd_parts_nb); - + /* Return happy */ return 0; } @@ -201,13 +201,13 @@ module_init(ep7312_init); static void __exit ep7312_cleanup (void) { struct nand_chip *this = (struct nand_chip *) &ep7312_mtd[1]; - + /* Release resources, unregister device */ nand_release (ap7312_mtd); - + /* Free internal data buffer */ kfree (this->data_buf); - + /* Free the MTD device structure */ kfree (ep7312_mtd); } diff --git a/drivers/mtd/nand/h1910.c b/drivers/mtd/nand/h1910.c index 3825a7a0900..041e4b3358f 100644 --- a/drivers/mtd/nand/h1910.c +++ b/drivers/mtd/nand/h1910.c @@ -7,7 +7,7 @@ * Copyright (C) 2002 Marius Gröger (mag@sysgo.de) * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) * - * $Id: h1910.c,v 1.5 2004/11/04 12:53:10 gleixner Exp $ + * $Id: h1910.c,v 1.6 2005/11/07 11:14:30 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -54,24 +54,24 @@ static struct mtd_partition partition_info[] = { #endif -/* +/* * hardware specific access to control-lines */ -static void h1910_hwcontrol(struct mtd_info *mtd, int cmd) +static void h1910_hwcontrol(struct mtd_info *mtd, int cmd) { struct nand_chip* this = (struct nand_chip *) (mtd->priv); - + switch(cmd) { - - case NAND_CTL_SETCLE: + + case NAND_CTL_SETCLE: this->IO_ADDR_R |= (1 << 2); this->IO_ADDR_W |= (1 << 2); break; - case NAND_CTL_CLRCLE: + case NAND_CTL_CLRCLE: this->IO_ADDR_R &= ~(1 << 2); this->IO_ADDR_W &= ~(1 << 2); break; - + case NAND_CTL_SETALE: this->IO_ADDR_R |= (1 << 3); this->IO_ADDR_W |= (1 << 3); @@ -80,7 +80,7 @@ static void h1910_hwcontrol(struct mtd_info *mtd, int cmd) this->IO_ADDR_R &= ~(1 << 3); this->IO_ADDR_W &= ~(1 << 3); break; - + case NAND_CTL_SETNCE: break; case NAND_CTL_CLRNCE: @@ -108,18 +108,18 @@ static int __init h1910_init (void) int mtd_parts_nb = 0; struct mtd_partition *mtd_parts = 0; void __iomem *nandaddr; - + if (!machine_is_h1900()) return -ENODEV; - + nandaddr = __ioremap(0x08000000, 0x1000, 0, 1); if (!nandaddr) { printk("Failed to ioremap nand flash.\n"); return -ENOMEM; } - + /* Allocate memory for MTD device structure and private data */ - h1910_nand_mtd = kmalloc(sizeof(struct mtd_info) + + h1910_nand_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); if (!h1910_nand_mtd) { @@ -127,22 +127,22 @@ static int __init h1910_init (void) iounmap ((void *) nandaddr); return -ENOMEM; } - + /* Get pointer to private data */ this = (struct nand_chip *) (&h1910_nand_mtd[1]); - + /* Initialize structures */ memset((char *) h1910_nand_mtd, 0, sizeof(struct mtd_info)); memset((char *) this, 0, sizeof(struct nand_chip)); - + /* Link the private data with the MTD structure */ h1910_nand_mtd->priv = this; - + /* * Enable VPEN */ GPSR(37) = GPIO_bit(37); - + /* insert callbacks */ this->IO_ADDR_R = nandaddr; this->IO_ADDR_W = nandaddr; @@ -152,7 +152,7 @@ static int __init h1910_init (void) this->chip_delay = 50; this->eccmode = NAND_ECC_SOFT; this->options = NAND_NO_AUTOINCR; - + /* Scan to find existence of the device */ if (nand_scan (h1910_nand_mtd, 1)) { printk(KERN_NOTICE "No NAND device - returning -ENXIO\n"); @@ -160,9 +160,9 @@ static int __init h1910_init (void) iounmap ((void *) nandaddr); return -ENXIO; } - + #ifdef CONFIG_MTD_CMDLINE_PARTS - mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts, + mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts, "h1910-nand"); if (mtd_parts_nb > 0) part_type = "command line"; @@ -175,11 +175,11 @@ static int __init h1910_init (void) mtd_parts_nb = NUM_PARTITIONS; part_type = "static"; } - + /* Register the partitions */ printk(KERN_NOTICE "Using %s partition definition\n", part_type); add_mtd_partitions(h1910_nand_mtd, mtd_parts, mtd_parts_nb); - + /* Return happy */ return 0; } @@ -191,7 +191,7 @@ module_init(h1910_init); static void __exit h1910_cleanup (void) { struct nand_chip *this = (struct nand_chip *) &h1910_nand_mtd[1]; - + /* Release resources, unregister device */ nand_release (h1910_nand_mtd); diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index c18ea76ed40..4673ba79309 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -5,14 +5,14 @@ * This is the generic MTD driver for NAND flash devices. It should be * capable of working with almost all NAND chips currently available. * Basic support for AG-AND chips is provided. - * + * * Additional technical information is available on * http://www.linux-mtd.infradead.org/tech/nand.html - * + * * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) * 2002 Thomas Gleixner (tglx@linutronix.de) * - * 02-08-2004 tglx: support for strange chips, which cannot auto increment + * 02-08-2004 tglx: support for strange chips, which cannot auto increment * pages on read / read_oob * * 03-17-2004 tglx: Check ready before auto increment check. Simon Bayes @@ -21,7 +21,7 @@ * Make reads over block boundaries work too * * 04-14-2004 tglx: first working version for 2k page size chips - * + * * 05-19-2004 tglx: Basic support for Renesas AG-AND chips * * 09-24-2004 tglx: add support for hardware controllers (e.g. ECC) shared @@ -30,27 +30,27 @@ * * 12-05-2004 dmarlin: add workaround for Renesas AG-AND chips "disturb" issue. * Basically, any block not rewritten may lose data when surrounding blocks - * are rewritten many times. JFFS2 ensures this doesn't happen for blocks + * are rewritten many times. JFFS2 ensures this doesn't happen for blocks * it uses, but the Bad Block Table(s) may not be rewritten. To ensure they * do not lose data, force them to be rewritten when some of the surrounding - * blocks are erased. Rather than tracking a specific nearby block (which - * could itself go bad), use a page address 'mask' to select several blocks + * blocks are erased. Rather than tracking a specific nearby block (which + * could itself go bad), use a page address 'mask' to select several blocks * in the same area, and rewrite the BBT when any of them are erased. * - * 01-03-2005 dmarlin: added support for the device recovery command sequence for Renesas + * 01-03-2005 dmarlin: added support for the device recovery command sequence for Renesas * AG-AND chips. If there was a sudden loss of power during an erase operation, * a "device recovery" operation must be performed when power is restored * to ensure correct operation. * - * 01-20-2005 dmarlin: added support for optional hardware specific callback routine to + * 01-20-2005 dmarlin: added support for optional hardware specific callback routine to * perform extra error status checks on erase and write failures. This required * adding a wrapper function for nand_read_ecc. * * 08-20-2005 vwool: suspend/resume added * * Credits: - * David Woodhouse for adding multichip support - * + * David Woodhouse for adding multichip support + * * Aleph One Ltd. and Toby Churchill Ltd. for supporting the * rework for 2K page size chips * @@ -105,8 +105,8 @@ static struct nand_oobinfo nand_oob_64 = { .useecc = MTD_NANDECC_AUTOPLACE, .eccbytes = 24, .eccpos = { - 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63}, .oobfree = { {2, 38} } }; @@ -149,19 +149,19 @@ static void nand_sync (struct mtd_info *mtd); static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf, struct nand_oobinfo *oobsel, int mode); #ifdef CONFIG_MTD_NAND_VERIFY_WRITE -static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages, +static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages, u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode); #else #define nand_verify_pages(...) (0) #endif - + static int nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state); /** * nand_release_device - [GENERIC] release chip * @mtd: MTD device structure - * - * Deselect, release chip lock and wake up anyone waiting on the device + * + * Deselect, release chip lock and wake up anyone waiting on the device */ static void nand_release_device (struct mtd_info *mtd) { @@ -215,7 +215,7 @@ static void nand_write_byte(struct mtd_info *mtd, u_char byte) * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip * @mtd: MTD device structure * - * Default read function for 16bit buswith with + * Default read function for 16bit buswith with * endianess conversion */ static u_char nand_read_byte16(struct mtd_info *mtd) @@ -242,7 +242,7 @@ static void nand_write_byte16(struct mtd_info *mtd, u_char byte) * nand_read_word - [DEFAULT] read one word from the chip * @mtd: MTD device structure * - * Default read function for 16bit buswith without + * Default read function for 16bit buswith without * endianess conversion */ static u16 nand_read_word(struct mtd_info *mtd) @@ -256,7 +256,7 @@ static u16 nand_read_word(struct mtd_info *mtd) * @mtd: MTD device structure * @word: data word to write * - * Default write function for 16bit buswith without + * Default write function for 16bit buswith without * endianess conversion */ static void nand_write_word(struct mtd_info *mtd, u16 word) @@ -277,7 +277,7 @@ static void nand_select_chip(struct mtd_info *mtd, int chip) struct nand_chip *this = mtd->priv; switch(chip) { case -1: - this->hwcontrol(mtd, NAND_CTL_CLRNCE); + this->hwcontrol(mtd, NAND_CTL_CLRNCE); break; case 0: this->hwcontrol(mtd, NAND_CTL_SETNCE); @@ -306,7 +306,7 @@ static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) } /** - * nand_read_buf - [DEFAULT] read chip data into buffer + * nand_read_buf - [DEFAULT] read chip data into buffer * @mtd: MTD device structure * @buf: buffer to store date * @len: number of bytes to read @@ -323,7 +323,7 @@ static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) } /** - * nand_verify_buf - [DEFAULT] Verify chip data against buffer + * nand_verify_buf - [DEFAULT] Verify chip data against buffer * @mtd: MTD device structure * @buf: buffer containing the data to compare * @len: number of bytes to compare @@ -356,14 +356,14 @@ static void nand_write_buf16(struct mtd_info *mtd, const u_char *buf, int len) struct nand_chip *this = mtd->priv; u16 *p = (u16 *) buf; len >>= 1; - + for (i=0; iIO_ADDR_W); - + } /** - * nand_read_buf16 - [DEFAULT] read chip data into buffer + * nand_read_buf16 - [DEFAULT] read chip data into buffer * @mtd: MTD device structure * @buf: buffer to store date * @len: number of bytes to read @@ -382,7 +382,7 @@ static void nand_read_buf16(struct mtd_info *mtd, u_char *buf, int len) } /** - * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer + * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer * @mtd: MTD device structure * @buf: buffer containing the data to compare * @len: number of bytes to compare @@ -409,7 +409,7 @@ static int nand_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len) * @ofs: offset from device start * @getchip: 0, if the chip is already selected * - * Check, if the block is bad. + * Check, if the block is bad. */ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) { @@ -426,8 +426,8 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) /* Select the NAND device */ this->select_chip(mtd, chipnr); - } else - page = (int) ofs; + } else + page = (int) ofs; if (this->options & NAND_BUSWIDTH_16) { this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE, page & this->pagemask); @@ -441,12 +441,12 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) if (this->read_byte(mtd) != 0xff) res = 1; } - + if (getchip) { /* Deselect and wake up anyone waiting on the device */ nand_release_device(mtd); - } - + } + return res; } @@ -464,7 +464,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) u_char buf[2] = {0, 0}; size_t retlen; int block; - + /* Get block number */ block = ((int) ofs) >> this->bbt_erase_shift; if (this->bbt) @@ -473,25 +473,25 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) /* Do we have a flash based bad block table ? */ if (this->options & NAND_USE_FLASH_BBT) return nand_update_bbt (mtd, ofs); - + /* We write two bytes, so we dont have to mess with 16 bit access */ ofs += mtd->oobsize + (this->badblockpos & ~0x01); return nand_write_oob (mtd, ofs , 2, &retlen, buf); } -/** +/** * nand_check_wp - [GENERIC] check if the chip is write protected * @mtd: MTD device structure - * Check, if the device is write protected + * Check, if the device is write protected * - * The function expects, that the device is already selected + * The function expects, that the device is already selected */ static int nand_check_wp (struct mtd_info *mtd) { struct nand_chip *this = mtd->priv; /* Check the WP bit */ this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); - return (this->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1; + return (this->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1; } /** @@ -507,15 +507,15 @@ static int nand_check_wp (struct mtd_info *mtd) static int nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt) { struct nand_chip *this = mtd->priv; - + if (!this->bbt) return this->block_bad(mtd, ofs, getchip); - + /* Return info from the table */ return nand_isbad_bbt (mtd, ofs, allowbbt); } -/* +/* * Wait for the ready pin, after a command * The timeout is catched later. */ @@ -529,7 +529,7 @@ static void nand_wait_ready(struct mtd_info *mtd) if (this->dev_ready(mtd)) return; touch_softlockup_watchdog(); - } while (time_before(jiffies, timeo)); + } while (time_before(jiffies, timeo)); } /** @@ -592,13 +592,13 @@ static void nand_command (struct mtd_info *mtd, unsigned command, int column, in /* Latch in address */ this->hwcontrol(mtd, NAND_CTL_CLRALE); } - - /* - * program and erase have their own busy handlers + + /* + * program and erase have their own busy handlers * status and sequential in needs no delay */ switch (command) { - + case NAND_CMD_PAGEPROG: case NAND_CMD_ERASE1: case NAND_CMD_ERASE2: @@ -607,7 +607,7 @@ static void nand_command (struct mtd_info *mtd, unsigned command, int column, in return; case NAND_CMD_RESET: - if (this->dev_ready) + if (this->dev_ready) break; udelay(this->chip_delay); this->hwcontrol(mtd, NAND_CTL_SETCLE); @@ -616,16 +616,16 @@ static void nand_command (struct mtd_info *mtd, unsigned command, int column, in while ( !(this->read_byte(mtd) & NAND_STATUS_READY)); return; - /* This applies to read commands */ + /* This applies to read commands */ default: - /* + /* * If we don't have access to the busy pin, we apply the given * command delay */ if (!this->dev_ready) { udelay (this->chip_delay); return; - } + } } /* Apply this short delay always to ensure that we do wait tWB in * any case on any machine. */ @@ -655,8 +655,8 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, column += mtd->oobblock; command = NAND_CMD_READ0; } - - + + /* Begin command latch cycle */ this->hwcontrol(mtd, NAND_CTL_SETCLE); /* Write out the command to the device. */ @@ -674,7 +674,7 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, column >>= 1; this->write_byte(mtd, column & 0xff); this->write_byte(mtd, column >> 8); - } + } if (page_addr != -1) { this->write_byte(mtd, (unsigned char) (page_addr & 0xff)); this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff)); @@ -685,13 +685,13 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, /* Latch in address */ this->hwcontrol(mtd, NAND_CTL_CLRALE); } - - /* - * program and erase have their own busy handlers + + /* + * program and erase have their own busy handlers * status, sequential in, and deplete1 need no delay */ switch (command) { - + case NAND_CMD_CACHEDPROG: case NAND_CMD_PAGEPROG: case NAND_CMD_ERASE1: @@ -701,7 +701,7 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, case NAND_CMD_DEPLETE1: return; - /* + /* * read error status commands require only a short delay */ case NAND_CMD_STATUS_ERROR: @@ -713,7 +713,7 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, return; case NAND_CMD_RESET: - if (this->dev_ready) + if (this->dev_ready) break; udelay(this->chip_delay); this->hwcontrol(mtd, NAND_CTL_SETCLE); @@ -730,17 +730,17 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, /* End command latch cycle */ this->hwcontrol(mtd, NAND_CTL_CLRCLE); /* Fall through into ready check */ - - /* This applies to read commands */ + + /* This applies to read commands */ default: - /* + /* * If we don't have access to the busy pin, we apply the given * command delay */ if (!this->dev_ready) { udelay (this->chip_delay); return; - } + } } /* Apply this short delay always to ensure that we do wait tWB in @@ -754,7 +754,7 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, * nand_get_device - [GENERIC] Get chip for selected access * @this: the nand chip descriptor * @mtd: MTD device structure - * @new_state: the state which is requested + * @new_state: the state which is requested * * Get the device and lock it for exclusive access */ @@ -802,7 +802,7 @@ retry: * @state: state to select the max. timeout value * * Wait for command done. This applies to erase and program only - * Erase can take up to 400ms and program up to 20ms according to + * Erase can take up to 400ms and program up to 20ms according to * general NAND and SmartMedia specs * */ @@ -811,7 +811,7 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) unsigned long timeo = jiffies; int status; - + if (state == FL_ERASING) timeo += (HZ * 400) / 1000; else @@ -823,17 +823,17 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) if ((state == FL_ERASING) && (this->options & NAND_IS_AND)) this->cmdfunc (mtd, NAND_CMD_STATUS_MULTI, -1, -1); - else + else this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); - while (time_before(jiffies, timeo)) { + while (time_before(jiffies, timeo)) { /* Check, if we were interrupted */ if (this->state != state) return 0; if (this->dev_ready) { if (this->dev_ready(mtd)) - break; + break; } else { if (this->read_byte(mtd) & NAND_STATUS_READY) break; @@ -859,7 +859,7 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) * * Cached programming is not supported yet. */ -static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, +static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf, struct nand_oobinfo *oobsel, int cached) { int i, status; @@ -868,10 +868,10 @@ static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int pa int *oob_config = oobsel->eccpos; int datidx = 0, eccidx = 0, eccsteps = this->eccsteps; int eccbytes = 0; - + /* FIXME: Enable cached programming */ cached = 0; - + /* Send command to begin auto page programming */ this->cmdfunc (mtd, NAND_CMD_SEQIN, 0x00, page); @@ -882,7 +882,7 @@ static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int pa printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n"); this->write_buf(mtd, this->data_poi, mtd->oobblock); break; - + /* Software ecc 3/256, write all */ case NAND_ECC_SOFT: for (; eccsteps; eccsteps--) { @@ -911,11 +911,11 @@ static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int pa } break; } - + /* Write out OOB data */ if (this->options & NAND_HWECC_SYNDROME) this->write_buf(mtd, &oob_buf[oobsel->eccbytes], mtd->oobsize - oobsel->eccbytes); - else + else this->write_buf(mtd, oob_buf, mtd->oobsize); /* Send command to actually program the data */ @@ -940,7 +940,7 @@ static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int pa /* wait until cache is ready*/ // status = this->waitfunc (mtd, this, FL_CACHEDRPG); } - return 0; + return 0; } #ifdef CONFIG_MTD_NAND_VERIFY_WRITE @@ -956,19 +956,19 @@ static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int pa * @oobmode: 1 = full buffer verify, 0 = ecc only * * The NAND device assumes that it is always writing to a cleanly erased page. - * Hence, it performs its internal write verification only on bits that + * Hence, it performs its internal write verification only on bits that * transitioned from 1 to 0. The device does NOT verify the whole page on a - * byte by byte basis. It is possible that the page was not completely erased - * or the page is becoming unusable due to wear. The read with ECC would catch - * the error later when the ECC page check fails, but we would rather catch + * byte by byte basis. It is possible that the page was not completely erased + * or the page is becoming unusable due to wear. The read with ECC would catch + * the error later when the ECC page check fails, but we would rather catch * it early in the page write stage. Better to write no data than invalid data. */ -static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages, +static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages, u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode) { int i, j, datidx = 0, oobofs = 0, res = -EIO; int eccsteps = this->eccsteps; - int hweccbytes; + int hweccbytes; u_char oobdata[64]; hweccbytes = (this->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0; @@ -1008,7 +1008,7 @@ static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int if (oobsel->useecc != MTD_NANDECC_OFF && !hweccbytes) { int ecccnt = oobsel->eccbytes; - + for (i = 0; i < ecccnt; i++) { int idx = oobsel->eccpos[i]; if (oobdata[idx] != oob_buf[oobofs + idx] ) { @@ -1018,20 +1018,20 @@ static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int goto out; } } - } + } } oobofs += mtd->oobsize - hweccbytes * eccsteps; page++; numpages--; - /* Apply delay or wait for ready/busy pin + /* Apply delay or wait for ready/busy pin * Do this before the AUTOINCR check, so no problems * arise if a chip which does auto increment * is marked as NOAUTOINCR by the board driver. * Do this also before returning, so the chip is * ready for the next command. */ - if (!this->dev_ready) + if (!this->dev_ready) udelay (this->chip_delay); else nand_wait_ready(mtd); @@ -1039,17 +1039,17 @@ static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int /* All done, return happy */ if (!numpages) return 0; - - - /* Check, if the chip supports auto page increment */ + + + /* Check, if the chip supports auto page increment */ if (!NAND_CANAUTOINCR(this)) this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page); } - /* + /* * Terminate the read command. We come here in case of an error * So we must issue a reset command. */ -out: +out: this->cmdfunc (mtd, NAND_CMD_RESET, -1, -1); return res; } @@ -1111,7 +1111,7 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, * NAND read with ECC */ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, - size_t * retlen, u_char * buf, u_char * oob_buf, + size_t * retlen, u_char * buf, u_char * oob_buf, struct nand_oobinfo *oobsel, int flags) { @@ -1145,7 +1145,7 @@ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, /* Autoplace of oob data ? Use the default placement scheme */ if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) oobsel = this->autooob; - + eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE; oob_config = oobsel->eccpos; @@ -1163,28 +1163,28 @@ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, end = mtd->oobblock; ecc = this->eccsize; eccbytes = this->eccbytes; - + if ((eccmode == NAND_ECC_NONE) || (this->options & NAND_HWECC_SYNDROME)) compareecc = 0; oobreadlen = mtd->oobsize; - if (this->options & NAND_HWECC_SYNDROME) + if (this->options & NAND_HWECC_SYNDROME) oobreadlen -= oobsel->eccbytes; /* Loop until all data read */ while (read < len) { - + int aligned = (!col && (len - read) >= end); - /* + /* * If the read is not page aligned, we have to read into data buffer * due to ecc, else we read into return buffer direct */ if (aligned) data_poi = &buf[read]; - else + else data_poi = this->data_buf; - - /* Check, if we have this page in the buffer + + /* Check, if we have this page in the buffer * * FIXME: Make it work when we must provide oob data too, * check the usage of data_buf oob field @@ -1200,7 +1200,7 @@ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, if (sndcmd) { this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page); sndcmd = 0; - } + } /* get oob area, if we have no oob buffer from fs-driver */ if (!oob_buf || oobsel->useecc == MTD_NANDECC_AUTOPLACE || @@ -1208,7 +1208,7 @@ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, oob_data = &this->data_buf[end]; eccsteps = this->eccsteps; - + switch (eccmode) { case NAND_ECC_NONE: { /* No ECC, Read in a page */ static unsigned long lastwhinge = 0; @@ -1219,12 +1219,12 @@ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, this->read_buf(mtd, data_poi, end); break; } - + case NAND_ECC_SOFT: /* Software ECC 3/256: Read in a page + oob data */ this->read_buf(mtd, data_poi, end); - for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=3, datidx += ecc) + for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=3, datidx += ecc) this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]); - break; + break; default: for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=eccbytes, datidx += ecc) { @@ -1243,15 +1243,15 @@ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, * does the error correction on the fly */ ecc_status = this->correct_data(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]); if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " + DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr); ecc_failed++; } } else { this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]); - } + } } - break; + break; } /* read oobdata */ @@ -1259,8 +1259,8 @@ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, /* Skip ECC check, if not requested (ECC_NONE or HW_ECC with syndromes) */ if (!compareecc) - goto readoob; - + goto readoob; + /* Pick the ECC bytes out of the oob data */ for (j = 0; j < oobsel->eccbytes; j++) ecc_code[j] = oob_data[oob_config[j]]; @@ -1268,24 +1268,24 @@ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, /* correct data, if neccecary */ for (i = 0, j = 0, datidx = 0; i < this->eccsteps; i++, datidx += ecc) { ecc_status = this->correct_data(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]); - + /* Get next chunk of ecc bytes */ j += eccbytes; - - /* Check, if we have a fs supplied oob-buffer, + + /* Check, if we have a fs supplied oob-buffer, * This is the legacy mode. Used by YAFFS1 * Should go away some day */ - if (oob_buf && oobsel->useecc == MTD_NANDECC_PLACE) { + if (oob_buf && oobsel->useecc == MTD_NANDECC_PLACE) { int *p = (int *)(&oob_data[mtd->oobsize]); p[i] = ecc_status; } - - if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) { + + if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) { DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page); ecc_failed++; } - } + } readoob: /* check, if we have a fs supplied oob-buffer */ @@ -1311,25 +1311,25 @@ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, } readdata: /* Partial page read, transfer data into fs buffer */ - if (!aligned) { + if (!aligned) { for (j = col; j < end && read < len; j++) buf[read++] = data_poi[j]; - this->pagebuf = realpage; - } else + this->pagebuf = realpage; + } else read += mtd->oobblock; - /* Apply delay or wait for ready/busy pin + /* Apply delay or wait for ready/busy pin * Do this before the AUTOINCR check, so no problems * arise if a chip which does auto increment * is marked as NOAUTOINCR by the board driver. */ - if (!this->dev_ready) + if (!this->dev_ready) udelay (this->chip_delay); else nand_wait_ready(mtd); - + if (read == len) - break; + break; /* For subsequent reads align to page boundary. */ col = 0; @@ -1343,11 +1343,11 @@ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, this->select_chip(mtd, -1); this->select_chip(mtd, chipnr); } - /* Check, if the chip supports auto page increment - * or if we have hit a block boundary. - */ + /* Check, if the chip supports auto page increment + * or if we have hit a block boundary. + */ if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) - sndcmd = 1; + sndcmd = 1; } /* Deselect and wake up anyone waiting on the device */ @@ -1384,7 +1384,7 @@ static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t /* Shift to get page */ page = (int)(from >> this->page_shift); chipnr = (int)(from >> this->chip_shift); - + /* Mask to get column */ col = from & (mtd->oobsize - 1); @@ -1406,7 +1406,7 @@ static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t /* Send the read command */ this->cmdfunc (mtd, NAND_CMD_READOOB, col, page & this->pagemask); - /* + /* * Read the data, if we read more than one page * oob data, let the device transfer the data ! */ @@ -1428,20 +1428,20 @@ static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t this->select_chip(mtd, -1); this->select_chip(mtd, chipnr); } - - /* Apply delay or wait for ready/busy pin + + /* Apply delay or wait for ready/busy pin * Do this before the AUTOINCR check, so no problems * arise if a chip which does auto increment * is marked as NOAUTOINCR by the board driver. */ - if (!this->dev_ready) + if (!this->dev_ready) udelay (this->chip_delay); else nand_wait_ready(mtd); - /* Check, if the chip supports auto page increment - * or if we have hit a block boundary. - */ + /* Check, if the chip supports auto page increment + * or if we have hit a block boundary. + */ if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) { /* For subsequent page reads set offset to 0 */ this->cmdfunc (mtd, NAND_CMD_READOOB, 0x0, page & this->pagemask); @@ -1487,27 +1487,27 @@ int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, nand_get_device (this, mtd , FL_READING); this->select_chip (mtd, chip); - + /* Add requested oob length */ len += ooblen; - + while (len) { if (sndcmd) this->cmdfunc (mtd, NAND_CMD_READ0, 0, page & this->pagemask); - sndcmd = 0; + sndcmd = 0; this->read_buf (mtd, &buf[cnt], pagesize); len -= pagesize; cnt += pagesize; page++; - - if (!this->dev_ready) + + if (!this->dev_ready) udelay (this->chip_delay); else nand_wait_ready(mtd); - - /* Check, if the chip supports auto page increment */ + + /* Check, if the chip supports auto page increment */ if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) sndcmd = 1; } @@ -1518,8 +1518,8 @@ int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, } -/** - * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer +/** + * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer * @mtd: MTD device structure * @fsbuf: buffer given by fs driver * @oobsel: out of band selection structre @@ -1548,20 +1548,20 @@ static u_char * nand_prepare_oobbuf (struct mtd_info *mtd, u_char *fsbuf, struct int i, len, ofs; /* Zero copy fs supplied buffer */ - if (fsbuf && !autoplace) + if (fsbuf && !autoplace) return fsbuf; /* Check, if the buffer must be filled with ff again */ - if (this->oobdirty) { - memset (this->oob_buf, 0xff, + if (this->oobdirty) { + memset (this->oob_buf, 0xff, mtd->oobsize << (this->phys_erase_shift - this->page_shift)); this->oobdirty = 0; - } - + } + /* If we have no autoplacement or no fs buffer use the internal one */ if (!autoplace || !fsbuf) return this->oob_buf; - + /* Walk through the pages and place the data */ this->oobdirty = 1; ofs = 0; @@ -1595,7 +1595,7 @@ static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * ret { return (nand_write_ecc (mtd, to, len, retlen, buf, NULL, NULL)); } - + /** * nand_write_ecc - [MTD Interface] NAND write with ECC * @mtd: MTD device structure @@ -1628,7 +1628,7 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, return -EINVAL; } - /* reject writes, which are not page aligned */ + /* reject writes, which are not page aligned */ if (NOTALIGNED (to) || NOTALIGNED(len)) { printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n"); return -EINVAL; @@ -1647,14 +1647,14 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, goto out; /* if oobsel is NULL, use chip defaults */ - if (oobsel == NULL) - oobsel = &mtd->oobinfo; - + if (oobsel == NULL) + oobsel = &mtd->oobinfo; + /* Autoplace of oob data ? Use the default placement scheme */ if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) { oobsel = this->autooob; autoplace = 1; - } + } if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR) autoplace = 1; @@ -1662,9 +1662,9 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, totalpages = len >> this->page_shift; page = (int) (to >> this->page_shift); /* Invalidate the page cache, if we write to the cached page */ - if (page <= this->pagebuf && this->pagebuf < (page + totalpages)) + if (page <= this->pagebuf && this->pagebuf < (page + totalpages)) this->pagebuf = -1; - + /* Set it relative to chip */ page &= this->pagemask; startpage = page; @@ -1686,14 +1686,14 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, if (ret) { DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: write_page failed %d\n", ret); goto out; - } + } /* Next oob page */ oob += mtd->oobsize; /* Update written bytes count */ written += mtd->oobblock; - if (written == len) + if (written == len) goto cmp; - + /* Increment page address */ page++; @@ -1704,13 +1704,13 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, if (!(page & (ppblock - 1))){ int ofs; this->data_poi = bufstart; - ret = nand_verify_pages (mtd, this, startpage, + ret = nand_verify_pages (mtd, this, startpage, page - startpage, oobbuf, oobsel, chipnr, (eccbuf != NULL)); if (ret) { DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret); goto out; - } + } *retlen = written; ofs = autoplace ? mtd->oobavail : mtd->oobsize; @@ -1720,7 +1720,7 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, numpages = min (totalpages, ppblock); page &= this->pagemask; startpage = page; - oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel, + oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel, autoplace, numpages); oob = 0; /* Check, if we cross a chip boundary */ @@ -1738,7 +1738,7 @@ cmp: oobbuf, oobsel, chipnr, (eccbuf != NULL)); if (!ret) *retlen = written; - else + else DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret); out: @@ -1798,7 +1798,7 @@ static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * /* Check, if it is write protected */ if (nand_check_wp(mtd)) goto out; - + /* Invalidate the page cache, if we write to the cached page */ if (page == this->pagebuf) this->pagebuf = -1; @@ -1861,10 +1861,10 @@ out: * * NAND write with kvec. This just calls the ecc function */ -static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, +static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t * retlen) { - return (nand_writev_ecc (mtd, vecs, count, to, retlen, NULL, NULL)); + return (nand_writev_ecc (mtd, vecs, count, to, retlen, NULL, NULL)); } /** @@ -1879,7 +1879,7 @@ static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned * * NAND write with iovec with ecc */ -static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, +static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel) { int i, page, len, total_len, ret = -EIO, written = 0, chipnr; @@ -1905,7 +1905,7 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig return -EINVAL; } - /* reject writes, which are not page aligned */ + /* reject writes, which are not page aligned */ if (NOTALIGNED (to) || NOTALIGNED(total_len)) { printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n"); return -EINVAL; @@ -1924,21 +1924,21 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig goto out; /* if oobsel is NULL, use chip defaults */ - if (oobsel == NULL) - oobsel = &mtd->oobinfo; + if (oobsel == NULL) + oobsel = &mtd->oobinfo; /* Autoplace of oob data ? Use the default placement scheme */ if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) { oobsel = this->autooob; autoplace = 1; - } + } if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR) autoplace = 1; /* Setup start page */ page = (int) (to >> this->page_shift); /* Invalidate the page cache, if we write to the cached page */ - if (page <= this->pagebuf && this->pagebuf < ((to + total_len) >> this->page_shift)) + if (page <= this->pagebuf && this->pagebuf < ((to + total_len) >> this->page_shift)) this->pagebuf = -1; startpage = page & this->pagemask; @@ -1962,10 +1962,10 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig oob = 0; for (i = 1; i <= numpages; i++) { /* Write one page. If this is the last page to write - * then use the real pageprogram command, else select + * then use the real pageprogram command, else select * cached programming if supported by the chip. */ - ret = nand_write_page (mtd, this, page & this->pagemask, + ret = nand_write_page (mtd, this, page & this->pagemask, &oobbuf[oob], oobsel, i != numpages); if (ret) goto out; @@ -1981,12 +1981,12 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig count--; } } else { - /* We must use the internal buffer, read data out of each + /* We must use the internal buffer, read data out of each * tuple until we have a full page to write */ int cnt = 0; while (cnt < mtd->oobblock) { - if (vecs->iov_base != NULL && vecs->iov_len) + if (vecs->iov_base != NULL && vecs->iov_len) this->data_buf[cnt++] = ((u_char *) vecs->iov_base)[len++]; /* Check, if we have to switch to the next tuple */ if (len >= (int) vecs->iov_len) { @@ -1995,10 +1995,10 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig count--; } } - this->pagebuf = page; - this->data_poi = this->data_buf; + this->pagebuf = page; + this->data_poi = this->data_buf; bufstart = this->data_poi; - numpages = 1; + numpages = 1; oobbuf = nand_prepare_oobbuf (mtd, NULL, oobsel, autoplace, numpages); ret = nand_write_page (mtd, this, page & this->pagemask, oobbuf, oobsel, 0); @@ -2011,7 +2011,7 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig ret = nand_verify_pages (mtd, this, startpage, numpages, oobbuf, oobsel, chipnr, 0); if (ret) goto out; - + written += mtd->oobblock * numpages; /* All done ? */ if (!count) @@ -2079,7 +2079,7 @@ static int nand_erase (struct mtd_info *mtd, struct erase_info *instr) { return nand_erase_nand (mtd, instr, 0); } - + #define BBT_PAGE_MASK 0xffffff3f /** * nand_erase_intern - [NAND Interface] erase block(s) @@ -2161,14 +2161,14 @@ int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbb instr->state = MTD_ERASE_FAILED; goto erase_exit; } - - /* Invalidate the page cache, if we erase the block which contains + + /* Invalidate the page cache, if we erase the block which contains the current cached page */ if (page <= this->pagebuf && this->pagebuf < (page + pages_per_block)) this->pagebuf = -1; this->erase_cmd (mtd, page & this->pagemask); - + status = this->waitfunc (mtd, this, FL_ERASING); /* See if operation failed and additional status checks are available */ @@ -2186,12 +2186,12 @@ int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbb /* if BBT requires refresh, set the BBT rewrite flag to the page being erased */ if (this->options & BBT_AUTO_REFRESH) { - if (((page & BBT_PAGE_MASK) == bbt_masked_page) && + if (((page & BBT_PAGE_MASK) == bbt_masked_page) && (page != this->bbt_td->pages[chipnr])) { rewrite_bbt[chipnr] = (page << this->page_shift); } } - + /* Increment page address and decrement length */ len -= (1 << this->phys_erase_shift); page += pages_per_block; @@ -2202,7 +2202,7 @@ int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbb this->select_chip(mtd, -1); this->select_chip(mtd, chipnr); - /* if BBT requires refresh and BBT-PERCHIP, + /* if BBT requires refresh and BBT-PERCHIP, * set the BBT page mask to see if this BBT should be rewritten */ if ((this->options & BBT_AUTO_REFRESH) && (this->bbt_td->options & NAND_BBT_PERCHIP)) { bbt_masked_page = this->bbt_td->pages[chipnr] & BBT_PAGE_MASK; @@ -2227,7 +2227,7 @@ erase_exit: for (chipnr = 0; chipnr < this->numchips; chipnr++) { if (rewrite_bbt[chipnr]) { /* update the BBT for chip */ - DEBUG (MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt (%d:0x%0x 0x%0x)\n", + DEBUG (MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt (%d:0x%0x 0x%0x)\n", chipnr, rewrite_bbt[chipnr], this->bbt_td->pages[chipnr]); nand_update_bbt (mtd, rewrite_bbt[chipnr]); } @@ -2265,9 +2265,9 @@ static void nand_sync (struct mtd_info *mtd) static int nand_block_isbad (struct mtd_info *mtd, loff_t ofs) { /* Check for invalid offset */ - if (ofs > mtd->size) + if (ofs > mtd->size) return -EINVAL; - + return nand_block_checkbad (mtd, ofs, 1, 0); } @@ -2386,13 +2386,13 @@ int nand_scan (struct mtd_info *mtd, int maxchips) /* Print and store flash device information */ for (i = 0; nand_flash_ids[i].name != NULL; i++) { - - if (nand_dev_id != nand_flash_ids[i].id) + + if (nand_dev_id != nand_flash_ids[i].id) continue; if (!mtd->name) mtd->name = nand_flash_ids[i].name; this->chipsize = nand_flash_ids[i].chipsize << 20; - + /* New devices have all the information in additional id bytes */ if (!nand_flash_ids[i].pagesize) { int extid; @@ -2411,7 +2411,7 @@ int nand_scan (struct mtd_info *mtd, int maxchips) extid >>= 2; /* Get buswidth information */ busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; - + } else { /* Old devices have this data hardcoded in the * device id table */ @@ -2431,23 +2431,23 @@ int nand_scan (struct mtd_info *mtd, int maxchips) * this correct ! */ if (busw != (this->options & NAND_BUSWIDTH_16)) { printk (KERN_INFO "NAND device: Manufacturer ID:" - " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, + " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, nand_manuf_ids[maf_id].name , mtd->name); - printk (KERN_WARNING - "NAND bus width %d instead %d bit\n", + printk (KERN_WARNING + "NAND bus width %d instead %d bit\n", (this->options & NAND_BUSWIDTH_16) ? 16 : 8, busw ? 16 : 8); this->select_chip(mtd, -1); - return 1; + return 1; } - - /* Calculate the address shift from the page size */ + + /* Calculate the address shift from the page size */ this->page_shift = ffs(mtd->oobblock) - 1; this->bbt_erase_shift = this->phys_erase_shift = ffs(mtd->erasesize) - 1; this->chip_shift = ffs(this->chipsize) - 1; /* Set the bad block position */ - this->badblockpos = mtd->oobblock > 512 ? + this->badblockpos = mtd->oobblock > 512 ? NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS; /* Get chip options, preserve non chip based options */ @@ -2457,10 +2457,10 @@ int nand_scan (struct mtd_info *mtd, int maxchips) this->options |= NAND_NO_AUTOINCR; /* Check if this is a not a samsung device. Do not clear the options * for chips which are not having an extended id. - */ + */ if (nand_maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize) this->options &= ~NAND_SAMSUNG_LP_OPTIONS; - + /* Check for AND chips with 4 page planes */ if (this->options & NAND_4PAGE_ARRAY) this->erase_cmd = multi_erase_cmd; @@ -2470,9 +2470,9 @@ int nand_scan (struct mtd_info *mtd, int maxchips) /* Do not replace user supplied command function ! */ if (mtd->oobblock > 512 && this->cmdfunc == nand_command) this->cmdfunc = nand_command_lp; - + printk (KERN_INFO "NAND device: Manufacturer ID:" - " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, + " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, nand_manuf_ids[maf_id].name , nand_flash_ids[i].name); break; } @@ -2496,7 +2496,7 @@ int nand_scan (struct mtd_info *mtd, int maxchips) } if (i > 1) printk(KERN_INFO "%d NAND chips detected\n", i); - + /* Allocate buffers, if neccecary */ if (!this->oob_buf) { size_t len; @@ -2508,7 +2508,7 @@ int nand_scan (struct mtd_info *mtd, int maxchips) } this->options |= NAND_OOBBUF_ALLOC; } - + if (!this->data_buf) { size_t len; len = mtd->oobblock + mtd->oobsize; @@ -2535,7 +2535,7 @@ int nand_scan (struct mtd_info *mtd, int maxchips) if (!this->autooob) { /* Select the appropriate default oob placement scheme for * placement agnostic filesystems */ - switch (mtd->oobsize) { + switch (mtd->oobsize) { case 8: this->autooob = &nand_oob_8; break; @@ -2551,19 +2551,19 @@ int nand_scan (struct mtd_info *mtd, int maxchips) BUG(); } } - + /* The number of bytes available for the filesystem to place fs dependend * oob data */ mtd->oobavail = 0; for (i = 0; this->autooob->oobfree[i][1]; i++) mtd->oobavail += this->autooob->oobfree[i][1]; - /* + /* * check ECC mode, default to software * if 3byte/512byte hardware ECC is selected and we have 256 byte pagesize - * fallback to software ECC + * fallback to software ECC */ - this->eccsize = 256; /* set default eccsize */ + this->eccsize = 256; /* set default eccsize */ this->eccbytes = 3; switch (this->eccmode) { @@ -2578,56 +2578,56 @@ int nand_scan (struct mtd_info *mtd, int maxchips) this->eccsize = 2048; break; - case NAND_ECC_HW3_512: - case NAND_ECC_HW6_512: - case NAND_ECC_HW8_512: + case NAND_ECC_HW3_512: + case NAND_ECC_HW6_512: + case NAND_ECC_HW8_512: if (mtd->oobblock == 256) { printk (KERN_WARNING "512 byte HW ECC not possible on 256 Byte pagesize, fallback to SW ECC \n"); this->eccmode = NAND_ECC_SOFT; this->calculate_ecc = nand_calculate_ecc; this->correct_data = nand_correct_data; - } else + } else this->eccsize = 512; /* set eccsize to 512 */ break; - + case NAND_ECC_HW3_256: break; - - case NAND_ECC_NONE: + + case NAND_ECC_NONE: printk (KERN_WARNING "NAND_ECC_NONE selected by board driver. This is not recommended !!\n"); this->eccmode = NAND_ECC_NONE; break; - case NAND_ECC_SOFT: + case NAND_ECC_SOFT: this->calculate_ecc = nand_calculate_ecc; this->correct_data = nand_correct_data; break; default: printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode); - BUG(); - } + BUG(); + } - /* Check hardware ecc function availability and adjust number of ecc bytes per + /* Check hardware ecc function availability and adjust number of ecc bytes per * calculation step */ switch (this->eccmode) { case NAND_ECC_HW12_2048: this->eccbytes += 4; - case NAND_ECC_HW8_512: + case NAND_ECC_HW8_512: this->eccbytes += 2; - case NAND_ECC_HW6_512: + case NAND_ECC_HW6_512: this->eccbytes += 3; - case NAND_ECC_HW3_512: + case NAND_ECC_HW3_512: case NAND_ECC_HW3_256: if (this->calculate_ecc && this->correct_data && this->enable_hwecc) break; printk (KERN_WARNING "No ECC functions supplied, Hardware ECC not possible\n"); - BUG(); + BUG(); } - + mtd->eccsize = this->eccsize; - + /* Set the number of read / write steps for one page to ensure ECC generation */ switch (this->eccmode) { case NAND_ECC_HW12_2048: @@ -2639,15 +2639,15 @@ int nand_scan (struct mtd_info *mtd, int maxchips) this->eccsteps = mtd->oobblock / 512; break; case NAND_ECC_HW3_256: - case NAND_ECC_SOFT: + case NAND_ECC_SOFT: this->eccsteps = mtd->oobblock / 256; break; - - case NAND_ECC_NONE: + + case NAND_ECC_NONE: this->eccsteps = 1; break; } - + /* Initialize state, waitqueue and spinlock */ this->state = FL_READY; init_waitqueue_head (&this->wq); @@ -2687,7 +2687,7 @@ int nand_scan (struct mtd_info *mtd, int maxchips) memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo)); mtd->owner = THIS_MODULE; - + /* Check, if we should skip the bad block table scan */ if (this->options & NAND_SKIP_BBTSCAN) return 0; @@ -2697,7 +2697,7 @@ int nand_scan (struct mtd_info *mtd, int maxchips) } /** - * nand_release - [NAND Interface] Free resources held by the NAND device + * nand_release - [NAND Interface] Free resources held by the NAND device * @mtd: MTD device structure */ void nand_release (struct mtd_info *mtd) diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 7535ef53685..ca286999fe0 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -3,10 +3,10 @@ * * Overview: * Bad block table support for the NAND driver - * + * * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) * - * $Id: nand_bbt.c,v 1.35 2005/07/15 13:53:47 gleixner Exp $ + * $Id: nand_bbt.c,v 1.36 2005/11/07 11:14:30 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -14,23 +14,23 @@ * * Description: * - * When nand_scan_bbt is called, then it tries to find the bad block table - * depending on the options in the bbt descriptor(s). If a bbt is found - * then the contents are read and the memory based bbt is created. If a + * When nand_scan_bbt is called, then it tries to find the bad block table + * depending on the options in the bbt descriptor(s). If a bbt is found + * then the contents are read and the memory based bbt is created. If a * mirrored bbt is selected then the mirror is searched too and the - * versions are compared. If the mirror has a greater version number + * versions are compared. If the mirror has a greater version number * than the mirror bbt is used to build the memory based bbt. * If the tables are not versioned, then we "or" the bad block information. - * If one of the bbt's is out of date or does not exist it is (re)created. - * If no bbt exists at all then the device is scanned for factory marked - * good / bad blocks and the bad block tables are created. + * If one of the bbt's is out of date or does not exist it is (re)created. + * If no bbt exists at all then the device is scanned for factory marked + * good / bad blocks and the bad block tables are created. * - * For manufacturer created bbts like the one found on M-SYS DOC devices + * For manufacturer created bbts like the one found on M-SYS DOC devices * the bbt is searched and read but never created * - * The autogenerated bad block table is located in the last good blocks - * of the device. The table is mirrored, so it can be updated eventually. - * The table is marked in the oob area with an ident pattern and a version + * The autogenerated bad block table is located in the last good blocks + * of the device. The table is mirrored, so it can be updated eventually. + * The table is marked in the oob area with an ident pattern and a version * number which indicates which of both tables is more up to date. * * The table uses 2 bits per block @@ -43,13 +43,13 @@ * 01b: block is marked bad due to wear * 10b: block is reserved (to protect the bbt area) * 11b: block is factory marked bad - * + * * Multichip devices like DOC store the bad block info per floor. * * Following assumptions are made: * - bbts start at a page boundary, if autolocated on a block boundary * - the space neccecary for a bbt in FLASH does not exceed a block boundary - * + * */ #include @@ -62,7 +62,7 @@ #include -/** +/** * check_pattern - [GENERIC] check if a pattern is in the buffer * @buf: the buffer to search * @len: the length of buffer to search @@ -86,9 +86,9 @@ static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_des if (p[i] != 0xff) return -1; } - } + } p += end; - + /* Compare the pattern */ for (i = 0; i < td->len; i++) { if (p[i] != td->pattern[i]) @@ -106,13 +106,13 @@ static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_des return 0; } -/** +/** * check_short_pattern - [GENERIC] check if a pattern is in the buffer * @buf: the buffer to search * @td: search pattern descriptor * * Check for a pattern at the given place. Used to search bad block - * tables and good / bad block identifiers. Same as check_pattern, but + * tables and good / bad block identifiers. Same as check_pattern, but * no optional empty check * */ @@ -142,7 +142,7 @@ static int check_short_pattern (uint8_t *buf, struct nand_bbt_descr *td) * Read the bad block table starting from page. * */ -static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, +static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, int bits, int offs, int reserved_block_code) { int res, i, j, act = 0; @@ -153,7 +153,7 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, totlen = (num * bits) >> 3; from = ((loff_t)page) << this->page_shift; - + while (totlen) { len = min (totlen, (size_t) (1 << this->bbt_erase_shift)); res = mtd->read_ecc (mtd, from, len, &retlen, buf, NULL, this->autooob); @@ -163,7 +163,7 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, return res; } printk (KERN_WARNING "nand_bbt: ECC error while reading bad block table\n"); - } + } /* Analyse data */ for (i = 0; i < len; i++) { @@ -183,12 +183,12 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, * message to MTD_DEBUG_LEVEL0 */ printk (KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n", ((offs << 2) + (act >> 1)) << this->bbt_erase_shift); - /* Factory marked bad or worn out ? */ + /* Factory marked bad or worn out ? */ if (tmp == 0) this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06); else this->bbt[offs + (act >> 3)] |= 0x1 << (act & 0x06); - } + } } totlen -= len; from += len; @@ -200,7 +200,7 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, * read_abs_bbt - [GENERIC] Read the bad block table starting at a given page * @mtd: MTD device structure * @buf: temporary buffer - * @td: descriptor for the bad block table + * @td: descriptor for the bad block table * @chip: read the table for a specific chip, -1 read all chips. * Applies only if NAND_BBT_PERCHIP option is set * @@ -235,7 +235,7 @@ static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page * @mtd: MTD device structure * @buf: temporary buffer - * @td: descriptor for the bad block table + * @td: descriptor for the bad block table * @md: descriptor for the bad block table mirror * * Read the bad block table(s) for all chips starting at a given page @@ -247,16 +247,16 @@ static int read_abs_bbts (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_de { struct nand_chip *this = mtd->priv; - /* Read the primary version, if available */ + /* Read the primary version, if available */ if (td->options & NAND_BBT_VERSION) { - nand_read_raw (mtd, buf, td->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize); + nand_read_raw (mtd, buf, td->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize); td->version[0] = buf[mtd->oobblock + td->veroffs]; printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", td->pages[0], td->version[0]); } - /* Read the mirror version, if available */ + /* Read the mirror version, if available */ if (md && (md->options & NAND_BBT_VERSION)) { - nand_read_raw (mtd, buf, md->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize); + nand_read_raw (mtd, buf, md->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize); md->version[0] = buf[mtd->oobblock + md->veroffs]; printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]); } @@ -290,7 +290,7 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr else { if (bd->options & NAND_BBT_SCAN2NDPAGE) len = 2; - else + else len = 1; } @@ -322,10 +322,10 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr numblocks += startblock; from = startblock << (this->bbt_erase_shift - 1); } - + for (i = startblock; i < numblocks;) { int ret; - + if (bd->options & NAND_BBT_SCANEMPTY) if ((ret = nand_read_raw (mtd, buf, from, readlen, ooblen))) return ret; @@ -333,8 +333,8 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr for (j = 0; j < len; j++) { if (!(bd->options & NAND_BBT_SCANEMPTY)) { size_t retlen; - - /* Read the full oob until read_oob is fixed to + + /* Read the full oob until read_oob is fixed to * handle single byte reads for 16 bit buswidth */ ret = mtd->read_oob(mtd, from + j * mtd->oobblock, mtd->oobsize, &retlen, buf); @@ -343,14 +343,14 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr if (check_short_pattern (buf, bd)) { this->bbt[i >> 3] |= 0x03 << (i & 0x6); - printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", + printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", i >> 1, (unsigned int) from); break; } } else { if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) { this->bbt[i >> 3] |= 0x03 << (i & 0x6); - printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", + printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", i >> 1, (unsigned int) from); break; } @@ -369,15 +369,15 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr * @td: descriptor for the bad block table * * Read the bad block table by searching for a given ident pattern. - * Search is preformed either from the beginning up or from the end of + * Search is preformed either from the beginning up or from the end of * the device downwards. The search starts always at the start of a * block. - * If the option NAND_BBT_PERCHIP is given, each chip is searched + * If the option NAND_BBT_PERCHIP is given, each chip is searched * for a bbt, which contains the bad block information of this chip. * This is neccecary to provide support for certain DOC devices. * - * The bbt ident pattern resides in the oob area of the first page - * in a block. + * The bbt ident pattern resides in the oob area of the first page + * in a block. */ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td) { @@ -392,10 +392,10 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr startblock = (mtd->size >> this->bbt_erase_shift) -1; dir = -1; } else { - startblock = 0; + startblock = 0; dir = 1; - } - + } + /* Do we have a bbt per chip ? */ if (td->options & NAND_BBT_PERCHIP) { chips = this->numchips; @@ -405,19 +405,19 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr chips = 1; bbtblocks = mtd->size >> this->bbt_erase_shift; } - + /* Number of bits for each erase block in the bbt */ bits = td->options & NAND_BBT_NRBITS_MSK; - + for (i = 0; i < chips; i++) { /* Reset version information */ - td->version[i] = 0; + td->version[i] = 0; td->pages[i] = -1; /* Scan the maximum number of blocks */ for (block = 0; block < td->maxblocks; block++) { int actblock = startblock + dir * block; /* Read first page */ - nand_read_raw (mtd, buf, actblock << this->bbt_erase_shift, mtd->oobblock, mtd->oobsize); + nand_read_raw (mtd, buf, actblock << this->bbt_erase_shift, mtd->oobblock, mtd->oobsize); if (!check_pattern(buf, scanlen, mtd->oobblock, td)) { td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift); if (td->options & NAND_BBT_VERSION) { @@ -435,46 +435,46 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr else printk (KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i], td->version[i]); } - return 0; + return 0; } /** * search_read_bbts - [GENERIC] scan the device for bad block table(s) * @mtd: MTD device structure * @buf: temporary buffer - * @td: descriptor for the bad block table + * @td: descriptor for the bad block table * @md: descriptor for the bad block table mirror * * Search and read the bad block table(s) */ -static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf, +static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md) { /* Search the primary table */ search_bbt (mtd, buf, td); - + /* Search the mirror table */ if (md) search_bbt (mtd, buf, md); - + /* Force result check */ - return 1; + return 1; } - -/** + +/** * write_bbt - [GENERIC] (Re)write the bad block table * * @mtd: MTD device structure * @buf: temporary buffer - * @td: descriptor for the bad block table + * @td: descriptor for the bad block table * @md: descriptor for the bad block table mirror * @chipsel: selector for a specific chip, -1 for all * * (Re)write the bad block table * */ -static int write_bbt (struct mtd_info *mtd, uint8_t *buf, +static int write_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel) { struct nand_chip *this = mtd->priv; @@ -493,7 +493,7 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf, /* Write bad block table per chip rather than per device ? */ if (td->options & NAND_BBT_PERCHIP) { numblocks = (int) (this->chipsize >> this->bbt_erase_shift); - /* Full device write or specific chip ? */ + /* Full device write or specific chip ? */ if (chipsel == -1) { nrchips = this->numchips; } else { @@ -503,19 +503,19 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf, } else { numblocks = (int) (mtd->size >> this->bbt_erase_shift); nrchips = 1; - } - + } + /* Loop through the chips */ for (; chip < nrchips; chip++) { - - /* There was already a version of the table, reuse the page - * This applies for absolute placement too, as we have the + + /* There was already a version of the table, reuse the page + * This applies for absolute placement too, as we have the * page nr. in td->pages. */ if (td->pages[chip] != -1) { page = td->pages[chip]; goto write; - } + } /* Automatic placement of the bad block table */ /* Search direction top -> down ? */ @@ -525,7 +525,7 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf, } else { startblock = chip * numblocks; dir = 1; - } + } for (i = 0; i < td->maxblocks; i++) { int block = startblock + dir * i; @@ -542,7 +542,7 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf, } printk (KERN_ERR "No space left to write bad block table\n"); return -ENOSPC; -write: +write: /* Set up shift count and masks for the flash table */ bits = td->options & NAND_BBT_NRBITS_MSK; @@ -553,14 +553,14 @@ write: case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F; msk[2] = ~rcode; msk[3] = 0xff; break; default: return -EINVAL; } - + bbtoffs = chip * (numblocks >> 2); - + to = ((loff_t) page) << this->page_shift; memcpy (&oobinfo, this->autooob, sizeof(oobinfo)); oobinfo.useecc = MTD_NANDECC_PLACEONLY; - + /* Must we save the block contents ? */ if (td->options & NAND_BBT_SAVECONTENT) { /* Make it block aligned */ @@ -599,7 +599,7 @@ write: buf[len + td->veroffs] = td->version[chip]; } } - + /* walk through the memory table */ for (i = 0; i < numblocks; ) { uint8_t dat; @@ -611,7 +611,7 @@ write: dat >>= 2; } } - + memset (&einfo, 0, sizeof (einfo)); einfo.mtd = mtd; einfo.addr = (unsigned long) to; @@ -621,18 +621,18 @@ write: printk (KERN_WARNING "nand_bbt: Error during block erase: %d\n", res); return res; } - + res = mtd->write_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo); if (res < 0) { printk (KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", res); return res; } - printk (KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n", + printk (KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n", (unsigned int) to, td->version[chip]); - + /* Mark it as used */ td->pages[chip] = page; - } + } return 0; } @@ -641,7 +641,7 @@ write: * @mtd: MTD device structure * @bd: descriptor for the good/bad block search pattern * - * The function creates a memory based bbt by scanning the device + * The function creates a memory based bbt by scanning the device * for manufacturer / software marked good / bad blocks */ static inline int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) @@ -673,11 +673,11 @@ static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des struct nand_bbt_descr *rd, *rd2; /* Do we have a bbt per chip ? */ - if (td->options & NAND_BBT_PERCHIP) + if (td->options & NAND_BBT_PERCHIP) chips = this->numchips; - else + else chips = 1; - + for (i = 0; i < chips; i++) { writeops = 0; rd = NULL; @@ -692,7 +692,7 @@ static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des } if (td->pages[i] == -1) { - rd = md; + rd = md; td->version[i] = md->version[i]; writeops = 1; goto writecheck; @@ -710,7 +710,7 @@ static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des if (!(td->options & NAND_BBT_VERSION)) rd2 = md; goto writecheck; - } + } if (((int8_t) (td->version[i] - md->version[i])) > 0) { rd = td; @@ -735,15 +735,15 @@ static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des create: /* Create the bad block table by scanning the device ? */ if (!(td->options & NAND_BBT_CREATE)) - continue; - + continue; + /* Create the table in memory by scanning the chip(s) */ create_bbt (mtd, buf, bd, chipsel); - + td->version[i] = 1; if (md) - md->version[i] = 1; -writecheck: + md->version[i] = 1; +writecheck: /* read back first ? */ if (rd) read_abs_bbt (mtd, buf, rd, chipsel); @@ -757,7 +757,7 @@ writecheck: if (res < 0) return res; } - + /* Write the mirror bad block table to the device ? */ if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) { res = write_bbt (mtd, buf, md, td, chipsel); @@ -765,11 +765,11 @@ writecheck: return res; } } - return 0; + return 0; } /** - * mark_bbt_regions - [GENERIC] mark the bad block table regions + * mark_bbt_regions - [GENERIC] mark the bad block table regions * @mtd: MTD device structure * @td: bad block table descriptor * @@ -790,14 +790,14 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td) } else { chips = 1; nrblocks = (int)(mtd->size >> this->bbt_erase_shift); - } - + } + for (i = 0; i < chips; i++) { if ((td->options & NAND_BBT_ABSPAGE) || !(td->options & NAND_BBT_WRITE)) { if (td->pages[i] == -1) continue; block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift); - block <<= 1; + block <<= 1; oldval = this->bbt[(block >> 3)]; newval = oldval | (0x2 << (block & 0x06)); this->bbt[(block >> 3)] = newval; @@ -808,16 +808,16 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td) update = 0; if (td->options & NAND_BBT_LASTBLOCK) block = ((i + 1) * nrblocks) - td->maxblocks; - else + else block = i * nrblocks; - block <<= 1; + block <<= 1; for (j = 0; j < td->maxblocks; j++) { oldval = this->bbt[(block >> 3)]; newval = oldval | (0x2 << (block & 0x06)); this->bbt[(block >> 3)] = newval; if (oldval != newval) update = 1; block += 2; - } + } /* If we want reserved blocks to be recorded to flash, and some new ones have been marked, then we need to update the stored bbts. This should only happen once. */ @@ -831,7 +831,7 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td) * @mtd: MTD device structure * @bd: descriptor for the good/bad block search pattern * - * The function checks, if a bad block table(s) is/are already + * The function checks, if a bad block table(s) is/are already * available. If not it scans the device for manufacturer * marked good / bad blocks and writes the bad block table(s) to * the selected place. @@ -880,30 +880,30 @@ int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) this->bbt = NULL; return -ENOMEM; } - + /* Is the bbt at a given page ? */ if (td->options & NAND_BBT_ABSPAGE) { res = read_abs_bbts (mtd, buf, td, md); - } else { + } else { /* Search the bad block table using a pattern in oob */ res = search_read_bbts (mtd, buf, td, md); - } + } - if (res) + if (res) res = check_create (mtd, buf, bd); - + /* Prevent the bbt regions from erasing / writing */ mark_bbt_region (mtd, td); if (md) mark_bbt_region (mtd, md); - + kfree (buf); return res; } /** - * nand_update_bbt - [NAND Interface] update bad block table(s) + * nand_update_bbt - [NAND Interface] update bad block table(s) * @mtd: MTD device structure * @offs: the offset of the newly marked block * @@ -930,7 +930,7 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs) printk (KERN_ERR "nand_update_bbt: Out of memory\n"); return -ENOMEM; } - + writeops = md != NULL ? 0x03 : 0x01; /* Do we have a bbt per chip ? */ @@ -944,7 +944,7 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs) td->version[chip]++; if (md) - md->version[chip]++; + md->version[chip]++; /* Write the bad block table to the device ? */ if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) { @@ -957,12 +957,12 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs) res = write_bbt (mtd, buf, md, td, chipsel); } -out: +out: kfree (buf); return res; } -/* Define some generic bad / good block scan pattern which are used +/* Define some generic bad / good block scan pattern which are used * while scanning a device for factory marked good / bad blocks. */ static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; @@ -1009,7 +1009,7 @@ static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' }; static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' }; static struct nand_bbt_descr bbt_main_descr = { - .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, .offs = 8, .len = 4, @@ -1019,7 +1019,7 @@ static struct nand_bbt_descr bbt_main_descr = { }; static struct nand_bbt_descr bbt_mirror_descr = { - .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, .offs = 8, .len = 4, @@ -1029,7 +1029,7 @@ static struct nand_bbt_descr bbt_mirror_descr = { }; /** - * nand_default_bbt - [NAND Interface] Select a default bad block table for the device + * nand_default_bbt - [NAND Interface] Select a default bad block table for the device * @mtd: MTD device structure * * This function selects the default bad block table @@ -1039,29 +1039,29 @@ static struct nand_bbt_descr bbt_mirror_descr = { int nand_default_bbt (struct mtd_info *mtd) { struct nand_chip *this = mtd->priv; - - /* Default for AG-AND. We must use a flash based + + /* Default for AG-AND. We must use a flash based * bad block table as the devices have factory marked * _good_ blocks. Erasing those blocks leads to loss * of the good / bad information, so we _must_ store - * this information in a good / bad table during + * this information in a good / bad table during * startup */ if (this->options & NAND_IS_AND) { /* Use the default pattern descriptors */ - if (!this->bbt_td) { + if (!this->bbt_td) { this->bbt_td = &bbt_main_descr; this->bbt_md = &bbt_mirror_descr; - } + } this->options |= NAND_USE_FLASH_BBT; return nand_scan_bbt (mtd, &agand_flashbased); } - - + + /* Is a flash based bad block table requested ? */ if (this->options & NAND_USE_FLASH_BBT) { - /* Use the default pattern descriptors */ - if (!this->bbt_td) { + /* Use the default pattern descriptors */ + if (!this->bbt_td) { this->bbt_td = &bbt_main_descr; this->bbt_md = &bbt_mirror_descr; } @@ -1081,7 +1081,7 @@ int nand_default_bbt (struct mtd_info *mtd) } /** - * nand_isbad_bbt - [NAND Interface] Check if a block is bad + * nand_isbad_bbt - [NAND Interface] Check if a block is bad * @mtd: MTD device structure * @offs: offset in the device * @allowbbt: allow access to bad block table region @@ -1092,12 +1092,12 @@ int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt) struct nand_chip *this = mtd->priv; int block; uint8_t res; - + /* Get block number * 2 */ block = (int) (offs >> (this->bbt_erase_shift - 1)); res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03; - DEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n", + DEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n", (unsigned int)offs, block >> 1, res); switch ((int)res) { diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c index 2e341b75437..40ac909150a 100644 --- a/drivers/mtd/nand/nand_ecc.c +++ b/drivers/mtd/nand/nand_ecc.c @@ -7,22 +7,22 @@ * Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com) * Toshiba America Electronics Components, Inc. * - * $Id: nand_ecc.c,v 1.14 2004/06/16 15:34:37 gleixner Exp $ + * $Id: nand_ecc.c,v 1.15 2005/11/07 11:14:30 gleixner Exp $ * * This file 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 or (at your option) any * later version. - * + * * This file is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. - * + * * You should have received a copy of the GNU General Public License along * with this file; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * + * * As a special exception, if other files instantiate templates or use * macros or inline functions from these files, or you compile these * files and link them with other works to produce a work based on these @@ -30,7 +30,7 @@ * covered by the GNU General Public License. However the source code for * these files must still be made available in accordance with section (3) * of the GNU General Public License. - * + * * This exception does not invalidate any other reasons why a work based on * this file might be covered by the GNU General Public License. */ @@ -67,7 +67,7 @@ static const u_char nand_ecc_precalc_table[] = { * nand_trans_result - [GENERIC] create non-inverted ECC * @reg2: line parity reg 2 * @reg3: line parity reg 3 - * @ecc_code: ecc + * @ecc_code: ecc * * Creates non-inverted ECC code from line parity */ @@ -75,11 +75,11 @@ static void nand_trans_result(u_char reg2, u_char reg3, u_char *ecc_code) { u_char a, b, i, tmp1, tmp2; - + /* Initialize variables */ a = b = 0x80; tmp1 = tmp2 = 0; - + /* Calculate first ECC byte */ for (i = 0; i < 4; i++) { if (reg3 & a) /* LP15,13,11,9 --> ecc_code[0] */ @@ -90,7 +90,7 @@ static void nand_trans_result(u_char reg2, u_char reg3, b >>= 1; a >>= 1; } - + /* Calculate second ECC byte */ b = 0x80; for (i = 0; i < 4; i++) { @@ -102,7 +102,7 @@ static void nand_trans_result(u_char reg2, u_char reg3, b >>= 1; a >>= 1; } - + /* Store two of the ECC bytes */ ecc_code[0] = tmp1; ecc_code[1] = tmp2; @@ -118,28 +118,28 @@ int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code { u_char idx, reg1, reg2, reg3; int j; - + /* Initialize variables */ reg1 = reg2 = reg3 = 0; ecc_code[0] = ecc_code[1] = ecc_code[2] = 0; - - /* Build up column parity */ + + /* Build up column parity */ for(j = 0; j < 256; j++) { - + /* Get CP0 - CP5 from table */ idx = nand_ecc_precalc_table[dat[j]]; reg1 ^= (idx & 0x3f); - + /* All bit XOR = 1 ? */ if (idx & 0x40) { reg3 ^= (u_char) j; reg2 ^= ~((u_char) j); } } - + /* Create non-inverted ECC code from line parity */ nand_trans_result(reg2, reg3, ecc_code); - + /* Calculate final ECC code */ ecc_code[0] = ~ecc_code[0]; ecc_code[1] = ~ecc_code[1]; @@ -159,12 +159,12 @@ int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) { u_char a, b, c, d1, d2, d3, add, bit, i; - - /* Do error detection */ + + /* Do error detection */ d1 = calc_ecc[0] ^ read_ecc[0]; d2 = calc_ecc[1] ^ read_ecc[1]; d3 = calc_ecc[2] ^ read_ecc[2]; - + if ((d1 | d2 | d3) == 0) { /* No errors */ return 0; @@ -173,7 +173,7 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_cha a = (d1 ^ (d1 >> 1)) & 0x55; b = (d2 ^ (d2 >> 1)) & 0x55; c = (d3 ^ (d3 >> 1)) & 0x54; - + /* Found and will correct single bit error in the data */ if ((a == 0x55) && (b == 0x55) && (c == 0x54)) { c = 0x80; @@ -237,7 +237,7 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_cha } } } - + /* Should never happen */ return -1; } diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index efe246961b6..dbc7e55a424 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c @@ -3,7 +3,7 @@ * * Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de) * - * $Id: nand_ids.c,v 1.14 2005/06/23 09:38:50 gleixner Exp $ + * $Id: nand_ids.c,v 1.16 2005/11/07 11:14:31 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -14,14 +14,14 @@ #include /* * Chip ID list -* +* * Name. ID code, pagesize, chipsize in MegaByte, eraseblock size, * options -* +* * Pagesize; 0, 256, 512 * 0 get this information from the extended chip ID + 256 256 Byte page size -* 512 512 Byte page size +* 512 512 Byte page size */ struct nand_flash_dev nand_flash_ids[] = { {"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0}, @@ -34,27 +34,27 @@ struct nand_flash_dev nand_flash_ids[] = { {"NAND 4MiB 3,3V 8-bit", 0xe3, 512, 4, 0x2000, 0}, {"NAND 4MiB 3,3V 8-bit", 0xe5, 512, 4, 0x2000, 0}, {"NAND 8MiB 3,3V 8-bit", 0xd6, 512, 8, 0x2000, 0}, - + {"NAND 8MiB 1,8V 8-bit", 0x39, 512, 8, 0x2000, 0}, {"NAND 8MiB 3,3V 8-bit", 0xe6, 512, 8, 0x2000, 0}, {"NAND 8MiB 1,8V 16-bit", 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16}, {"NAND 8MiB 3,3V 16-bit", 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16}, - + {"NAND 16MiB 1,8V 8-bit", 0x33, 512, 16, 0x4000, 0}, {"NAND 16MiB 3,3V 8-bit", 0x73, 512, 16, 0x4000, 0}, {"NAND 16MiB 1,8V 16-bit", 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16}, {"NAND 16MiB 3,3V 16-bit", 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16}, - + {"NAND 32MiB 1,8V 8-bit", 0x35, 512, 32, 0x4000, 0}, {"NAND 32MiB 3,3V 8-bit", 0x75, 512, 32, 0x4000, 0}, {"NAND 32MiB 1,8V 16-bit", 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16}, {"NAND 32MiB 3,3V 16-bit", 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16}, - + {"NAND 64MiB 1,8V 8-bit", 0x36, 512, 64, 0x4000, 0}, {"NAND 64MiB 3,3V 8-bit", 0x76, 512, 64, 0x4000, 0}, {"NAND 64MiB 1,8V 16-bit", 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16}, {"NAND 64MiB 3,3V 16-bit", 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16}, - + {"NAND 128MiB 1,8V 8-bit", 0x78, 512, 128, 0x4000, 0}, {"NAND 128MiB 1,8V 8-bit", 0x39, 512, 128, 0x4000, 0}, {"NAND 128MiB 3,3V 8-bit", 0x79, 512, 128, 0x4000, 0}, @@ -62,7 +62,7 @@ struct nand_flash_dev nand_flash_ids[] = { {"NAND 128MiB 1,8V 16-bit", 0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16}, {"NAND 128MiB 3,3V 16-bit", 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16}, {"NAND 128MiB 3,3V 16-bit", 0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16}, - + {"NAND 256MiB 3,3V 8-bit", 0x71, 512, 256, 0x4000, 0}, /* These are the new chips with large page size. The pagesize @@ -73,7 +73,7 @@ struct nand_flash_dev nand_flash_ids[] = { {"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, {"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, {"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, - + /* 1 Gigabit */ {"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, {"NAND 128MiB 3,3V 8-bit", 0xF1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, @@ -85,13 +85,13 @@ struct nand_flash_dev nand_flash_ids[] = { {"NAND 256MiB 3,3V 8-bit", 0xDA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, {"NAND 256MiB 1,8V 16-bit", 0xBA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, {"NAND 256MiB 3,3V 16-bit", 0xCA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, - + /* 4 Gigabit */ {"NAND 512MiB 1,8V 8-bit", 0xAC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, {"NAND 512MiB 3,3V 8-bit", 0xDC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, {"NAND 512MiB 1,8V 16-bit", 0xBC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, {"NAND 512MiB 3,3V 16-bit", 0xCC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, - + /* 8 Gigabit */ {"NAND 1GiB 1,8V 8-bit", 0xA3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, {"NAND 1GiB 3,3V 8-bit", 0xD3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, @@ -104,11 +104,11 @@ struct nand_flash_dev nand_flash_ids[] = { {"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, - /* Renesas AND 1 Gigabit. Those chips do not support extended id and have a strange page/block layout ! + /* Renesas AND 1 Gigabit. Those chips do not support extended id and have a strange page/block layout ! * The chosen minimum erasesize is 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page planes * 1 block = 2 pages, but due to plane arrangement the blocks 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7 * Anyway JFFS2 would increase the eraseblock size so we chose a combined one which can be erased in one go - * There are more speed improvements for reads and writes possible, but not implemented now + * There are more speed improvements for reads and writes possible, but not implemented now */ {"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000, NAND_IS_AND | NAND_NO_AUTOINCR | NAND_4PAGE_ARRAY | BBT_AUTO_REFRESH}, diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 754b6ed7ce1..de450039530 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -3,7 +3,7 @@ * * Author: Artem B. Bityuckiy , * - * Copyright (C) 2004 Nokia Corporation + * Copyright (C) 2004 Nokia Corporation * * Note: NS means "NAND Simulator". * Note: Input means input TO flash chip, output means output FROM chip. @@ -126,7 +126,7 @@ MODULE_PARM_DESC(dbg, "Output debug information if not zero"); /* The largest possible page size */ #define NS_LARGEST_PAGE_SIZE 2048 - + /* The prefix for simulator output */ #define NS_OUTPUT_PREFIX "[nandsim]" @@ -145,7 +145,7 @@ MODULE_PARM_DESC(dbg, "Output debug information if not zero"); do { if (do_delays) udelay(us); } while(0) #define NS_MDELAY(us) \ do { if (do_delays) mdelay(us); } while(0) - + /* Is the nandsim structure initialized ? */ #define NS_IS_INITIALIZED(ns) ((ns)->geom.totsz != 0) @@ -153,12 +153,12 @@ MODULE_PARM_DESC(dbg, "Output debug information if not zero"); #define NS_STATUS_OK(ns) (NAND_STATUS_READY | (NAND_STATUS_WP * ((ns)->lines.wp == 0))) /* Operation failed completion status */ -#define NS_STATUS_FAILED(ns) (NAND_STATUS_FAIL | NS_STATUS_OK(ns)) +#define NS_STATUS_FAILED(ns) (NAND_STATUS_FAIL | NS_STATUS_OK(ns)) /* Calculate the page offset in flash RAM image by (row, column) address */ #define NS_RAW_OFFSET(ns) \ (((ns)->regs.row << (ns)->geom.pgshift) + ((ns)->regs.row * (ns)->geom.oobsz) + (ns)->regs.column) - + /* Calculate the OOB offset in flash RAM image by (row, column) address */ #define NS_RAW_OFFSET_OOB(ns) (NS_RAW_OFFSET(ns) + ns->geom.pgsz) @@ -223,15 +223,15 @@ MODULE_PARM_DESC(dbg, "Output debug information if not zero"); /* Remove action bits ftom state */ #define NS_STATE(x) ((x) & ~ACTION_MASK) - -/* + +/* * Maximum previous states which need to be saved. Currently saving is * only needed for page programm operation with preceeded read command * (which is only valid for 512-byte pages). */ #define NS_MAX_PREVSTATES 1 -/* +/* * The structure which describes all the internal simulator data. */ struct nandsim { @@ -242,7 +242,7 @@ struct nandsim { uint32_t options; /* chip's characteristic bits */ uint32_t state; /* current chip state */ uint32_t nxstate; /* next expected state */ - + uint32_t *op; /* current operation, NULL operations isn't known yet */ uint32_t pstates[NS_MAX_PREVSTATES]; /* previous states */ uint16_t npstates; /* number of previous states saved */ @@ -413,7 +413,7 @@ init_nandsim(struct mtd_info *mtd) ns->geom.secaddrbytes = 3; } } - + /* Detect how many ID bytes the NAND chip outputs */ for (i = 0; nand_flash_ids[i].name != NULL; i++) { if (second_id_byte != nand_flash_ids[i].id) @@ -444,7 +444,7 @@ init_nandsim(struct mtd_info *mtd) #ifdef CONFIG_NS_ABS_POS ns->mem.byte = ioremap(CONFIG_NS_ABS_POS, ns->geom.totszoob); if (!ns->mem.byte) { - NS_ERR("init_nandsim: failed to map the NAND flash image at address %p\n", + NS_ERR("init_nandsim: failed to map the NAND flash image at address %p\n", (void *)CONFIG_NS_ABS_POS); return -ENOMEM; } @@ -567,7 +567,7 @@ static int check_command(int cmd) { switch (cmd) { - + case NAND_CMD_READ0: case NAND_CMD_READSTART: case NAND_CMD_PAGEPROG: @@ -580,7 +580,7 @@ check_command(int cmd) case NAND_CMD_RESET: case NAND_CMD_READ1: return 0; - + case NAND_CMD_STATUS_MULTI: default: return 1; @@ -631,7 +631,7 @@ static inline void accept_addr_byte(struct nandsim *ns, u_char bt) { uint byte = (uint)bt; - + if (ns->regs.count < (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) ns->regs.column |= (byte << 8 * ns->regs.count); else { @@ -642,11 +642,11 @@ accept_addr_byte(struct nandsim *ns, u_char bt) return; } - + /* * Switch to STATE_READY state. */ -static inline void +static inline void switch_to_ready_state(struct nandsim *ns, u_char status) { NS_DBG("switch_to_ready_state: switch to %s state\n", get_state_name(STATE_READY)); @@ -675,7 +675,7 @@ switch_to_ready_state(struct nandsim *ns, u_char status) * (for example program from the second half and read from the * second half operations both begin with the READ1 command). In this * case the ns->pstates[] array contains previous states. - * + * * Thus, the function tries to find operation containing the following * states (if the 'flag' parameter is 0): * ns->pstates[0], ... ns->pstates[ns->npstates], ns->state @@ -683,7 +683,7 @@ switch_to_ready_state(struct nandsim *ns, u_char status) * If (one and only one) matching operation is found, it is accepted ( * ns->ops, ns->state, ns->nxstate are initialized, ns->npstate is * zeroed). - * + * * If there are several maches, the current state is pushed to the * ns->pstates. * @@ -692,7 +692,7 @@ switch_to_ready_state(struct nandsim *ns, u_char status) * In such situation the function is called with 'flag' != 0, and the * operation is searched using the following pattern: * ns->pstates[0], ... ns->pstates[ns->npstates],
- * + * * It is supposed that this pattern must either match one operation on * none. There can't be ambiguity in that case. * @@ -711,15 +711,15 @@ find_operation(struct nandsim *ns, uint32_t flag) { int opsfound = 0; int i, j, idx = 0; - + for (i = 0; i < NS_OPER_NUM; i++) { int found = 1; - + if (!(ns->options & ops[i].reqopts)) /* Ignore operations we can't perform */ continue; - + if (flag) { if (!(ops[i].states[ns->npstates] & STATE_ADDR_MASK)) continue; @@ -728,7 +728,7 @@ find_operation(struct nandsim *ns, uint32_t flag) continue; } - for (j = 0; j < ns->npstates; j++) + for (j = 0; j < ns->npstates; j++) if (NS_STATE(ops[i].states[j]) != NS_STATE(ns->pstates[j]) && (ns->options & ops[idx].reqopts)) { found = 0; @@ -745,7 +745,7 @@ find_operation(struct nandsim *ns, uint32_t flag) /* Exact match */ ns->op = &ops[idx].states[0]; if (flag) { - /* + /* * In this case the find_operation function was * called when address has just began input. But it isn't * yet fully input and the current state must @@ -763,7 +763,7 @@ find_operation(struct nandsim *ns, uint32_t flag) idx, get_state_name(ns->state), get_state_name(ns->nxstate)); return 0; } - + if (opsfound == 0) { /* Nothing was found. Try to ignore previous commands (if any) and search again */ if (ns->npstates != 0) { @@ -777,13 +777,13 @@ find_operation(struct nandsim *ns, uint32_t flag) switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); return -2; } - + if (flag) { /* This shouldn't happen */ NS_DBG("find_operation: BUG, operation must be known if address is input\n"); return -2; } - + NS_DBG("find_operation: there is still ambiguity\n"); ns->pstates[ns->npstates++] = ns->state; @@ -803,7 +803,7 @@ do_state_action(struct nandsim *ns, uint32_t action) int busdiv = ns->busw == 8 ? 1 : 2; action &= ACTION_MASK; - + /* Check that page address input is correct */ if (action != ACTION_SECERASE && ns->regs.row >= ns->geom.pgnum) { NS_WARN("do_state_action: wrong page number (%#x)\n", ns->regs.row); @@ -827,14 +827,14 @@ do_state_action(struct nandsim *ns, uint32_t action) NS_DBG("do_state_action: (ACTION_CPY:) copy %d bytes to int buf, raw offset %d\n", num, NS_RAW_OFFSET(ns) + ns->regs.off); - + if (ns->regs.off == 0) NS_LOG("read page %d\n", ns->regs.row); else if (ns->regs.off < ns->geom.pgsz) NS_LOG("read page %d (second half)\n", ns->regs.row); else NS_LOG("read OOB of page %d\n", ns->regs.row); - + NS_UDELAY(access_delay); NS_UDELAY(input_cycle * ns->geom.pgsz / 1000 / busdiv); @@ -844,30 +844,30 @@ do_state_action(struct nandsim *ns, uint32_t action) /* * Erase sector. */ - + if (ns->lines.wp) { NS_ERR("do_state_action: device is write-protected, ignore sector erase\n"); return -1; } - + if (ns->regs.row >= ns->geom.pgnum - ns->geom.pgsec || (ns->regs.row & ~(ns->geom.secsz - 1))) { NS_ERR("do_state_action: wrong sector address (%#x)\n", ns->regs.row); return -1; } - + ns->regs.row = (ns->regs.row << 8 * (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) | ns->regs.column; ns->regs.column = 0; - + NS_DBG("do_state_action: erase sector at address %#x, off = %d\n", ns->regs.row, NS_RAW_OFFSET(ns)); NS_LOG("erase sector %d\n", ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift)); memset(ns->mem.byte + NS_RAW_OFFSET(ns), 0xFF, ns->geom.secszoob); - + NS_MDELAY(erase_delay); - + break; case ACTION_PRGPAGE: @@ -893,12 +893,12 @@ do_state_action(struct nandsim *ns, uint32_t action) NS_DBG("do_state_action: copy %d bytes from int buf to (%#x, %#x), raw off = %d\n", num, ns->regs.row, ns->regs.column, NS_RAW_OFFSET(ns) + ns->regs.off); NS_LOG("programm page %d\n", ns->regs.row); - + NS_UDELAY(programm_delay); NS_UDELAY(output_cycle * ns->geom.pgsz / 1000 / busdiv); - + break; - + case ACTION_ZEROOFF: NS_DBG("do_state_action: set internal offset to 0\n"); ns->regs.off = 0; @@ -918,7 +918,7 @@ do_state_action(struct nandsim *ns, uint32_t action) NS_DBG("do_state_action: set internal offset to %d\n", ns->geom.pgsz); ns->regs.off = ns->geom.pgsz; break; - + default: NS_DBG("do_state_action: BUG! unknown action\n"); } @@ -937,7 +937,7 @@ switch_state(struct nandsim *ns) * The current operation have already been identified. * Just follow the states chain. */ - + ns->stateidx += 1; ns->state = ns->nxstate; ns->nxstate = ns->op[ns->stateidx + 1]; @@ -951,14 +951,14 @@ switch_state(struct nandsim *ns) switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); return; } - + } else { /* * We don't yet know which operation we perform. * Try to identify it. */ - /* + /* * The only event causing the switch_state function to * be called with yet unknown operation is new command. */ @@ -987,7 +987,7 @@ switch_state(struct nandsim *ns) */ u_char status = NS_STATUS_OK(ns); - + /* In case of data states, see if all bytes were input/output */ if ((ns->state & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK)) && ns->regs.count != ns->regs.num) { @@ -995,17 +995,17 @@ switch_state(struct nandsim *ns) ns->regs.num - ns->regs.count); status = NS_STATUS_FAILED(ns); } - + NS_DBG("switch_state: operation complete, switch to STATE_READY state\n"); switch_to_ready_state(ns, status); return; } else if (ns->nxstate & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK)) { - /* + /* * If the next state is data input/output, switch to it now */ - + ns->state = ns->nxstate; ns->nxstate = ns->op[++ns->stateidx + 1]; ns->regs.num = ns->regs.count = 0; @@ -1023,16 +1023,16 @@ switch_state(struct nandsim *ns) case STATE_DATAOUT: ns->regs.num = ns->geom.pgszoob - ns->regs.off - ns->regs.column; break; - + case STATE_DATAOUT_ID: ns->regs.num = ns->geom.idbytes; break; - + case STATE_DATAOUT_STATUS: case STATE_DATAOUT_STATUS_M: ns->regs.count = ns->regs.num = 0; break; - + default: NS_ERR("switch_state: BUG! unknown data state\n"); } @@ -1044,16 +1044,16 @@ switch_state(struct nandsim *ns) */ ns->regs.count = 0; - + switch (NS_STATE(ns->nxstate)) { case STATE_ADDR_PAGE: ns->regs.num = ns->geom.pgaddrbytes; - + break; case STATE_ADDR_SEC: ns->regs.num = ns->geom.secaddrbytes; break; - + case STATE_ADDR_ZERO: ns->regs.num = 1; break; @@ -1062,7 +1062,7 @@ switch_state(struct nandsim *ns) NS_ERR("switch_state: BUG! unknown address state\n"); } } else { - /* + /* * Just reset internal counters. */ @@ -1184,7 +1184,7 @@ ns_nand_read_byte(struct mtd_info *mtd) default: BUG(); } - + if (ns->regs.count == ns->regs.num) { NS_DBG("read_byte: all bytes were read\n"); @@ -1201,9 +1201,9 @@ ns_nand_read_byte(struct mtd_info *mtd) } else if (NS_STATE(ns->nxstate) == STATE_READY) switch_state(ns); - + } - + return outb; } @@ -1211,7 +1211,7 @@ static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte) { struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; - + /* Sanity and correctness checks */ if (!ns->lines.ce) { NS_ERR("write_byte: chip is disabled, ignore write\n"); @@ -1221,7 +1221,7 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte) NS_ERR("write_byte: ALE and CLE pins are high simultaneously, ignore write\n"); return; } - + if (ns->lines.cle == 1) { /* * The byte written is a command. @@ -1233,7 +1233,7 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte) return; } - /* + /* * Chip might still be in STATE_DATAOUT * (if OPT_AUTOINCR feature is supported), STATE_DATAOUT_STATUS or * STATE_DATAOUT_STATUS_M state. If so, switch state. @@ -1254,13 +1254,13 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte) "ignore previous states\n", (uint)byte, get_state_name(ns->nxstate)); switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); } - + /* Check that the command byte is correct */ if (check_command(byte)) { NS_ERR("write_byte: unknown command %#x\n", (uint)byte); return; } - + NS_DBG("command byte corresponding to %s state accepted\n", get_state_name(get_state_by_command(byte))); ns->regs.command = byte; @@ -1277,12 +1277,12 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte) if (find_operation(ns, 1) < 0) return; - + if ((ns->state & ACTION_MASK) && do_state_action(ns, ns->state) < 0) { switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); return; } - + ns->regs.count = 0; switch (NS_STATE(ns->nxstate)) { case STATE_ADDR_PAGE: @@ -1306,7 +1306,7 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte) switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); return; } - + /* Check if this is expected byte */ if (ns->regs.count == ns->regs.num) { NS_ERR("write_byte: no more address bytes expected\n"); @@ -1325,12 +1325,12 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte) NS_DBG("address (%#x, %#x) is accepted\n", ns->regs.row, ns->regs.column); switch_state(ns); } - + } else { /* * The byte written is an input data. */ - + /* Check that chip is expecting data input */ if (!(ns->state & STATE_DATAIN_MASK)) { NS_ERR("write_byte: data input (%#x) isn't expected, state is %s, " @@ -1372,7 +1372,7 @@ ns_nand_read_word(struct mtd_info *mtd) struct nand_chip *chip = (struct nand_chip *)mtd->priv; NS_DBG("read_word\n"); - + return chip->read_byte(mtd) | (chip->read_byte(mtd) << 8); } @@ -1380,14 +1380,14 @@ static void ns_nand_write_word(struct mtd_info *mtd, uint16_t word) { struct nand_chip *chip = (struct nand_chip *)mtd->priv; - + NS_DBG("write_word\n"); - + chip->write_byte(mtd, word & 0xFF); chip->write_byte(mtd, word >> 8); } -static void +static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) { struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; @@ -1409,13 +1409,13 @@ ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) memcpy(ns->buf.byte + ns->regs.count, buf, len); ns->regs.count += len; - + if (ns->regs.count == ns->regs.num) { NS_DBG("write_buf: %d bytes were written\n", ns->regs.count); } } -static void +static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) { struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; @@ -1453,7 +1453,7 @@ ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) memcpy(buf, ns->buf.byte + ns->regs.count, len); ns->regs.count += len; - + if (ns->regs.count == ns->regs.num) { if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) { ns->regs.count = 0; @@ -1465,11 +1465,11 @@ ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) else if (NS_STATE(ns->nxstate) == STATE_READY) switch_state(ns); } - + return; } -static int +static int ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) { ns_nand_read_buf(mtd, (u_char *)&ns_verify_buf[0], len); @@ -1496,7 +1496,7 @@ int __init ns_init_module(void) NS_ERR("wrong bus width (%d), use only 8 or 16\n", bus_width); return -EINVAL; } - + /* Allocate and initialize mtd_info, nand_chip and nandsim structures */ nsmtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip) + sizeof(struct nandsim), GFP_KERNEL); @@ -1509,7 +1509,7 @@ int __init ns_init_module(void) chip = (struct nand_chip *)(nsmtd + 1); nsmtd->priv = (void *)chip; nand = (struct nandsim *)(chip + 1); - chip->priv = (void *)nand; + chip->priv = (void *)nand; /* * Register simulator's callbacks. @@ -1526,9 +1526,9 @@ int __init ns_init_module(void) chip->eccmode = NAND_ECC_SOFT; chip->options |= NAND_SKIP_BBTSCAN; - /* + /* * Perform minimum nandsim structure initialization to handle - * the initial ID read command correctly + * the initial ID read command correctly */ if (third_id_byte != 0xFF || fourth_id_byte != 0xFF) nand->geom.idbytes = 4; @@ -1557,7 +1557,7 @@ int __init ns_init_module(void) NS_ERR("scan_bbt: can't initialize the nandsim structure\n"); goto error; } - + if ((retval = nand_default_bbt(nsmtd)) != 0) { free_nandsim(nand); goto error; diff --git a/drivers/mtd/nand/ppchameleonevb.c b/drivers/mtd/nand/ppchameleonevb.c index e510a83d7bd..91a95f34a6e 100644 --- a/drivers/mtd/nand/ppchameleonevb.c +++ b/drivers/mtd/nand/ppchameleonevb.c @@ -6,7 +6,7 @@ * Derived from drivers/mtd/nand/edb7312.c * * - * $Id: ppchameleonevb.c,v 1.6 2004/11/05 16:07:16 kalev Exp $ + * $Id: ppchameleonevb.c,v 1.7 2005/11/07 11:14:31 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -338,7 +338,7 @@ nand_evb_init: out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xFFFFFFF0); out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0x3FFFFFFF); /* enable output driver */ - out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN | + out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN | NAND_EVB_CLE_GPIO_PIN | NAND_EVB_ALE_GPIO_PIN); #ifdef USE_READY_BUSY_PIN /* three-state select */ @@ -402,7 +402,7 @@ static void __exit ppchameleonevb_cleanup (void) /* Release resources, unregister device(s) */ nand_release (ppchameleon_mtd); nand_release (ppchameleonevb_mtd); - + /* Release iomaps */ this = (struct nand_chip *) &ppchameleon_mtd[1]; iounmap((void *) this->IO_ADDR_R; diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c index 031051cbde7..3a5841c9d95 100644 --- a/drivers/mtd/nand/rtc_from4.c +++ b/drivers/mtd/nand/rtc_from4.c @@ -2,11 +2,11 @@ * drivers/mtd/nand/rtc_from4.c * * Copyright (C) 2004 Red Hat, Inc. - * + * * Derived from drivers/mtd/nand/spia.c * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) * - * $Id: rtc_from4.c,v 1.9 2005/01/24 20:40:11 dmarlin Exp $ + * $Id: rtc_from4.c,v 1.10 2005/11/07 11:14:31 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -14,8 +14,8 @@ * * Overview: * This is a device driver for the AG-AND flash device found on the - * Renesas Technology Corp. Flash ROM 4-slot interface board (FROM_BOARD4), - * which utilizes the Renesas HN29V1G91T-30 part. + * Renesas Technology Corp. Flash ROM 4-slot interface board (FROM_BOARD4), + * which utilizes the Renesas HN29V1G91T-30 part. * This chip is a 1 GBibit (128MiB x 8 bits) AG-AND flash device. */ @@ -105,9 +105,9 @@ const static struct mtd_partition partition_info[] = { }; #define NUM_PARTITIONS 1 -/* +/* * hardware specific flash bbt decriptors - * Note: this is to allow debugging by disabling + * Note: this is to allow debugging by disabling * NAND_BBT_CREATE and/or NAND_BBT_WRITE * */ @@ -141,7 +141,7 @@ static struct nand_bbt_descr rtc_from4_bbt_mirror_descr = { /* the Reed Solomon control structure */ static struct rs_control *rs_decoder; -/* +/* * hardware specific Out Of Band information */ static struct nand_oobinfo rtc_from4_nand_oobinfo = { @@ -200,38 +200,38 @@ static uint8_t revbits[256] = { -/* +/* * rtc_from4_hwcontrol - hardware specific access to control-lines * @mtd: MTD device structure * @cmd: hardware control command * - * Address lines (A5 and A4) are used to control Command and Address Latch + * Address lines (A5 and A4) are used to control Command and Address Latch * Enable on this board, so set the read/write address appropriately. * - * Chip Enable is also controlled by the Chip Select (CS5) and + * Chip Enable is also controlled by the Chip Select (CS5) and * Address lines (A24-A22), so no action is required here. * */ static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd) { struct nand_chip* this = (struct nand_chip *) (mtd->priv); - + switch(cmd) { - - case NAND_CTL_SETCLE: + + case NAND_CTL_SETCLE: this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_CLE); break; - case NAND_CTL_CLRCLE: + case NAND_CTL_CLRCLE: this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_CLE); break; - + case NAND_CTL_SETALE: this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_ALE); break; case NAND_CTL_CLRALE: this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_ALE); break; - + case NAND_CTL_SETNCE: break; case NAND_CTL_CLRNCE: @@ -296,7 +296,7 @@ static int rtc_from4_nand_device_ready(struct mtd_info *mtd) * @mtd: MTD device structure * @chip: Chip to select (0 == slot 3, 1 == slot 4) * - * If there was a sudden loss of power during an erase operation, a + * If there was a sudden loss of power during an erase operation, a * "device recovery" operation must be performed when power is restored * to ensure correct operation. This routine performs the required steps * for the requested chip. @@ -312,7 +312,7 @@ static void deplete(struct mtd_info *mtd, int chip) while (!this->dev_ready(mtd)); this->select_chip(mtd, chip); - + /* Send the commands for device recovery, phase 1 */ this->cmdfunc (mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0000); this->cmdfunc (mtd, NAND_CMD_DEPLETE2, -1, -1); @@ -330,7 +330,7 @@ static void deplete(struct mtd_info *mtd, int chip) * @mtd: MTD device structure * @mode: I/O mode; read or write * - * enable hardware ECC for data read or write + * enable hardware ECC for data read or write * */ static void rtc_from4_enable_hwecc(struct mtd_info *mtd, int mode) @@ -340,7 +340,7 @@ static void rtc_from4_enable_hwecc(struct mtd_info *mtd, int mode) switch (mode) { case NAND_ECC_READ : - status = RTC_FROM4_RS_ECC_CTL_CLR + status = RTC_FROM4_RS_ECC_CTL_CLR | RTC_FROM4_RS_ECC_CTL_FD_E; *rs_ecc_ctl = status; @@ -353,8 +353,8 @@ static void rtc_from4_enable_hwecc(struct mtd_info *mtd, int mode) break; case NAND_ECC_WRITE : - status = RTC_FROM4_RS_ECC_CTL_CLR - | RTC_FROM4_RS_ECC_CTL_GEN + status = RTC_FROM4_RS_ECC_CTL_CLR + | RTC_FROM4_RS_ECC_CTL_GEN | RTC_FROM4_RS_ECC_CTL_FD_E; *rs_ecc_ctl = status; @@ -411,7 +411,7 @@ static void rtc_from4_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_c static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_char *ecc1, u_char *ecc2) { int i, j, res; - unsigned short status; + unsigned short status; uint16_t par[6], syn[6]; uint8_t ecc[8]; volatile unsigned short *rs_ecc; @@ -430,7 +430,7 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha } /* convert into 6 10bit syndrome fields */ - par[5] = rs_decoder->index_of[(((uint16_t)ecc[0] >> 0) & 0x0ff) | + par[5] = rs_decoder->index_of[(((uint16_t)ecc[0] >> 0) & 0x0ff) | (((uint16_t)ecc[1] << 8) & 0x300)]; par[4] = rs_decoder->index_of[(((uint16_t)ecc[1] >> 2) & 0x03f) | (((uint16_t)ecc[2] << 6) & 0x3c0)]; @@ -456,7 +456,7 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha /* Let the library code do its magic.*/ res = decode_rs8(rs_decoder, (uint8_t *)buf, par, 512, syn, 0, NULL, 0xff, NULL); if (res > 0) { - DEBUG (MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: " + DEBUG (MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: " "ECC corrected %d errors on read\n", res); } return res; @@ -470,9 +470,9 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha * @state: state or the operation * @status: status code returned from read status * @page: startpage inside the chip, must be called with (page & this->pagemask) - * - * Perform additional error status checks on erase and write failures - * to determine if errors are correctable. For this device, correctable + * + * Perform additional error status checks on erase and write failures + * to determine if errors are correctable. For this device, correctable * 1-bit errors on erase and write are considered acceptable. * * note: see pages 34..37 of data sheet for details. @@ -633,7 +633,7 @@ int __init rtc_from4_init (void) #ifdef RTC_FROM4_HWECC /* We could create the decoder on demand, if memory is a concern. - * This way we have it handy, if an error happens + * This way we have it handy, if an error happens * * Symbolsize is 10 (bits) * Primitve polynomial is x^10+x^3+1 diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 24f4199eaee..97e9b7892d2 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -19,7 +19,7 @@ * 08-Jul-2005 BJD Fix OOPS when no platform data supplied * 20-Oct-2005 BJD Fix timing calculation bug * - * $Id: s3c2410.c,v 1.18 2005/10/20 21:22:55 bjd Exp $ + * $Id: s3c2410.c,v 1.20 2005/11/07 11:14:31 gleixner Exp $ * * 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 @@ -164,7 +164,7 @@ static int s3c2410_nand_calc_rate(int wanted, unsigned long clk, int max) /* controller setup */ -static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, +static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, struct device *dev) { struct s3c2410_platform_nand *plat = to_nand_plat(dev); @@ -186,7 +186,7 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, twrph0 = 8; twrph1 = 8; } - + if (tacls < 0 || twrph0 < 0 || twrph1 < 0) { printk(KERN_ERR PFX "cannot get timings suitable for board\n"); return -EINVAL; @@ -194,7 +194,7 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, printk(KERN_INFO PFX "Tacls=%d, %dns Twrph0=%d %dns, Twrph1=%d %dns\n", tacls, to_ns(tacls, clkrate), - twrph0, to_ns(twrph0, clkrate), + twrph0, to_ns(twrph0, clkrate), twrph1, to_ns(twrph1, clkrate)); if (!info->is_s3c2440) { @@ -219,7 +219,7 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip) { struct s3c2410_nand_info *info; - struct s3c2410_nand_mtd *nmtd; + struct s3c2410_nand_mtd *nmtd; struct nand_chip *this = mtd->priv; void __iomem *reg; unsigned long cur; @@ -252,7 +252,7 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip) writel(cur, reg); } -/* command and control functions +/* command and control functions * * Note, these all use tglx's method of changing the IO_ADDR_W field * to make the code simpler, and use the nand layer's code to issue the @@ -324,7 +324,7 @@ static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd) static int s3c2410_nand_devready(struct mtd_info *mtd) { struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); - + if (info->is_s3c2440) return readb(info->regs + S3C2440_NFSTAT) & S3C2440_NFSTAT_READY; return readb(info->regs + S3C2410_NFSTAT) & S3C2410_NFSTAT_BUSY; @@ -345,7 +345,7 @@ static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat, if (read_ecc[0] == calc_ecc[0] && read_ecc[1] == calc_ecc[1] && - read_ecc[2] == calc_ecc[2]) + read_ecc[2] == calc_ecc[2]) return 0; /* we curently have no method for correcting the error */ @@ -436,14 +436,14 @@ static int s3c2410_nand_remove(struct device *dev) dev_set_drvdata(dev, NULL); - if (info == NULL) + if (info == NULL) return 0; /* first thing we need to do is release all our mtds * and their partitions, then go through freeing the - * resources used + * resources used */ - + if (info->mtds != NULL) { struct s3c2410_nand_mtd *ptr = info->mtds; int mtdno; @@ -507,7 +507,7 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, /* s3c2410_nand_init_chip * - * init a single instance of an chip + * init a single instance of an chip */ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, @@ -625,7 +625,7 @@ static int s3c24xx_nand_probe(struct device *dev, int is_s3c2440) dev_err(dev, "cannot reserve register region\n"); err = -EIO; goto exit_error; - } + } dev_dbg(dev, "mapped registers at %p\n", info->regs); @@ -659,7 +659,7 @@ static int s3c24xx_nand_probe(struct device *dev, int is_s3c2440) for (setno = 0; setno < nr_sets; setno++, nmtd++) { pr_debug("initialising set %d (%p, info %p)\n", setno, nmtd, info); - + s3c2410_nand_init_chip(info, nmtd, sets); nmtd->scan_res = nand_scan(&nmtd->mtd, @@ -672,7 +672,7 @@ static int s3c24xx_nand_probe(struct device *dev, int is_s3c2440) if (sets != NULL) sets++; } - + pr_debug("initialised ok\n"); return 0; diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index 6def3d33b06..1924a4f137c 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c @@ -3,7 +3,7 @@ * * Copyright (C) 2004 Richard Purdie * - * $Id: sharpsl.c,v 1.6 2005/11/03 11:36:42 rpurdie Exp $ + * $Id: sharpsl.c,v 1.7 2005/11/07 11:14:31 gleixner Exp $ * * Based on Sharp's NAND driver sharp_sl.c * @@ -76,14 +76,14 @@ static struct mtd_partition sharpsl_nand_default_partition_info[] = { }, }; -/* +/* * hardware specific access to control-lines */ static void sharpsl_nand_hwcontrol(struct mtd_info* mtd, int cmd) { switch (cmd) { - case NAND_CTL_SETCLE: + case NAND_CTL_SETCLE: writeb(readb(FLASHCTL) | FLCLE, FLASHCTL); break; case NAND_CTL_CLRCLE: @@ -97,10 +97,10 @@ sharpsl_nand_hwcontrol(struct mtd_info* mtd, int cmd) writeb(readb(FLASHCTL) & ~FLALE, FLASHCTL); break; - case NAND_CTL_SETNCE: + case NAND_CTL_SETNCE: writeb(readb(FLASHCTL) & ~(FLCE0|FLCE1), FLASHCTL); break; - case NAND_CTL_CLRNCE: + case NAND_CTL_CLRNCE: writeb(readb(FLASHCTL) | (FLCE0|FLCE1), FLASHCTL); break; } @@ -126,8 +126,8 @@ static struct nand_oobinfo akita_oobinfo = { .useecc = MTD_NANDECC_AUTOPLACE, .eccbytes = 24, .eccpos = { - 0x5, 0x1, 0x2, 0x3, 0x6, 0x7, 0x15, 0x11, - 0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23, + 0x5, 0x1, 0x2, 0x3, 0x6, 0x7, 0x15, 0x11, + 0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23, 0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37}, .oobfree = { {0x08, 0x09} } }; @@ -177,7 +177,7 @@ sharpsl_nand_init(void) printk ("Unable to allocate SharpSL NAND MTD device structure.\n"); return -ENOMEM; } - + /* map physical adress */ sharpsl_io_base = ioremap(sharpsl_phys_base, 0x1000); if(!sharpsl_io_base){ @@ -185,7 +185,7 @@ sharpsl_nand_init(void) kfree(sharpsl_mtd); return -EIO; } - + /* Get pointer to private data */ this = (struct nand_chip *) (&sharpsl_mtd[1]); @@ -211,7 +211,7 @@ sharpsl_nand_init(void) this->chip_delay = 15; /* set eccmode using hardware ECC */ this->eccmode = NAND_ECC_HW3_256; - this->badblock_pattern = &sharpsl_bbt; + this->badblock_pattern = &sharpsl_bbt; if (machine_is_akita() || machine_is_borzoi()) { this->badblock_pattern = &sharpsl_akita_bbt; this->autooob = &akita_oobinfo; @@ -232,7 +232,7 @@ sharpsl_nand_init(void) sharpsl_mtd->name = "sharpsl-nand"; nr_partitions = parse_mtd_partitions(sharpsl_mtd, part_probes, &sharpsl_partition_info, 0); - + if (nr_partitions <= 0) { nr_partitions = DEFAULT_NUM_PARTITIONS; sharpsl_partition_info = sharpsl_nand_default_partition_info; diff --git a/drivers/mtd/nand/spia.c b/drivers/mtd/nand/spia.c index b777c412b75..32541cbb010 100644 --- a/drivers/mtd/nand/spia.c +++ b/drivers/mtd/nand/spia.c @@ -8,7 +8,7 @@ * to controllines (due to change in nand.c) * page_cache added * - * $Id: spia.c,v 1.24 2004/11/04 12:53:10 gleixner Exp $ + * $Id: spia.c,v 1.25 2005/11/07 11:14:31 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -82,7 +82,7 @@ const static struct mtd_partition partition_info[] = { #define NUM_PARTITIONS 2 -/* +/* * hardware specific access to control-lines */ static void spia_hwcontrol(struct mtd_info *mtd, int cmd){ @@ -137,7 +137,7 @@ int __init spia_init (void) /* Set address of hardware control function */ this->hwcontrol = spia_hwcontrol; /* 15 us command delay time */ - this->chip_delay = 15; + this->chip_delay = 15; /* Scan to find existence of the device */ if (nand_scan (spia_mtd, 1)) { diff --git a/drivers/mtd/nand/toto.c b/drivers/mtd/nand/toto.c index 52c808fb5fa..7609c43cb3e 100644 --- a/drivers/mtd/nand/toto.c +++ b/drivers/mtd/nand/toto.c @@ -15,7 +15,7 @@ * This is a device driver for the NAND flash device found on the * TI fido board. It supports 32MiB and 64MiB cards * - * $Id: toto.c,v 1.4 2004/10/05 13:50:20 gleixner Exp $ + * $Id: toto.c,v 1.5 2005/11/07 11:14:31 gleixner Exp $ */ #include @@ -57,7 +57,7 @@ static unsigned long toto_io_base = OMAP_FLASH_1_BASE; #endif #define T_NAND_CTL_SETNCE(iob) gpiosetout(NAND_NCE, 0) #define T_NAND_CTL_CLRNCE(iob) gpiosetout(NAND_NCE, NAND_NCE) - + /* * Define partitions for flash devices */ @@ -91,7 +91,7 @@ static struct mtd_partition partition_info32M[] = { #define NUM_PARTITIONS32M 3 #define NUM_PARTITIONS64M 4 -/* +/* * hardware specific access to control-lines */ @@ -146,7 +146,7 @@ int __init toto_init (void) this->hwcontrol = toto_hwcontrol; this->dev_ready = NULL; /* 25 us command delay time */ - this->chip_delay = 30; + this->chip_delay = 30; this->eccmode = NAND_ECC_SOFT; /* Scan to find existance of the device */ @@ -157,10 +157,10 @@ int __init toto_init (void) /* Register the partitions */ switch(toto_mtd->size){ - case SZ_64M: add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M); break; - case SZ_32M: add_mtd_partitions(toto_mtd, partition_info32M, NUM_PARTITIONS32M); break; + case SZ_64M: add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M); break; + case SZ_32M: add_mtd_partitions(toto_mtd, partition_info32M, NUM_PARTITIONS32M); break; default: { - printk (KERN_WARNING "Unsupported Nand device\n"); + printk (KERN_WARNING "Unsupported Nand device\n"); err = -ENXIO; goto out_buf; } @@ -170,9 +170,9 @@ int __init toto_init (void) archflashwp(0,0); /* open up flash for writing */ goto out; - + out_buf: - kfree (this->data_buf); + kfree (this->data_buf); out_mtd: kfree (toto_mtd); out: @@ -194,7 +194,7 @@ static void __exit toto_cleanup (void) /* stop flash writes */ archflashwp(0,1); - + /* release gpios to system */ gpiorelease(NAND_MASK); } -- cgit v1.2.3 From d5c5e78af5cbcaeb7cad5a3c0117de593e5f4824 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 11:15:51 +0000 Subject: [MTD] OneNAND: Clean up trailing white spaces Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/onenand_base.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 99de2f055eb..cc38fa0d45c 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -255,7 +255,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le /* Write 'BSA, BSC' of DataRAM */ value = onenand_buffer_address(dataram, sectors, count); this->write_word(value, this->base + ONENAND_REG_START_BUFFER); - + if (readcmd) { /* Select DataRAM for DDP */ value = onenand_bufferram_address(this, block); @@ -433,7 +433,7 @@ static int onenand_write_bufferram(struct mtd_info *mtd, int area, * onenand_check_bufferram - [GENERIC] Check BufferRAM information * @param mtd MTD data structure * @param addr address to check - * @return 1 if there are valid data, otherwise 0 + * @return 1 if there are valid data, otherwise 0 * * Check bufferram if there is data we required */ @@ -442,7 +442,7 @@ static int onenand_check_bufferram(struct mtd_info *mtd, loff_t addr) struct onenand_chip *this = mtd->priv; int block, page; int i; - + block = (int) (addr >> this->erase_shift); page = (int) (addr >> this->page_shift); page &= this->page_mask; @@ -472,7 +472,7 @@ static int onenand_update_bufferram(struct mtd_info *mtd, loff_t addr, struct onenand_chip *this = mtd->priv; int block, page; int i; - + block = (int) (addr >> this->erase_shift); page = (int) (addr >> this->page_shift); page &= this->page_mask; @@ -743,7 +743,7 @@ static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, loff_t addr) if (memcmp(dataram0, dataram1, mtd->oobblock)) return -EBADMSG; - + return 0; } #else @@ -832,7 +832,7 @@ out: onenand_release_device(mtd); *retlen = written; - + return ret; } @@ -917,7 +917,7 @@ out: onenand_release_device(mtd); *retlen = written; - + return 0; } @@ -969,12 +969,12 @@ static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, onenand_get_device(mtd, FL_WRITING); /* TODO handling oob */ - + /* Loop until all keve's data has been written */ len = 0; while (count) { pbuf = buffer; - /* + /* * If the given tuple is >= pagesize then * write it out from the iov */ @@ -1316,7 +1316,7 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) if (!(status & ONENAND_WP_US)) printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status); } - + return 0; } @@ -1439,7 +1439,7 @@ static int onenand_probe(struct mtd_info *mtd) printk(KERN_INFO "Lock scheme is Continues Lock\n"); this->options |= ONENAND_CONT_LOCK; } - + return 0; } @@ -1533,7 +1533,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) } memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo)); - + /* Fill in remaining MTD driver data */ mtd->type = MTD_NANDFLASH; mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC; -- cgit v1.2.3 From c2965f1129ee54afcc4ef293ff0f25fa3a7e7392 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 11:16:01 +0000 Subject: [MTD] chips: Clean up trailing white spaces Signed-off-by: Thomas Gleixner --- drivers/mtd/chips/cfi_cmdset_0020.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index 39e3c2d9441..c4a19d2dc67 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c @@ -5,7 +5,7 @@ * (C) 2000 Red Hat. GPL'd * * $Id: cfi_cmdset_0020.c,v 1.22 2005/11/07 11:14:22 gleixner Exp $ - * + * * 10/10/2000 Nicolas Pitre * - completely revamped method functions so they are aware and * independent of the flash geometry (buswidth, interleave, etc.) -- cgit v1.2.3 From 7d24f0b8a53261709938ffabe3e00f88f6498df9 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 7 Nov 2005 00:57:52 -0800 Subject: [PATCH] ppc64: Fix bug in SLB miss handler for hugepages This patch, however, should be applied on top of the 64k-page-size patch to fix some problems with hugepage (some pre-existing, another introduced by this patch). The patch fixes a bug in the SLB miss handler for hugepages on ppc64 introduced by the dynamic hugepage patch (commit id c594adad5653491813959277fb87a2fef54c4e05) due to a misunderstanding of the srd instruction's behaviour (mea culpa). The problem arises when a 64-bit process maps some hugepages in the low 4GB of the address space (unusual). In this case, as well as the 256M segment in question being marked for hugepages, other segments at 32G intervals will be incorrectly marked for hugepages. In the process, this patch tweaks the semantics of the hugepage bitmaps to be more sensible. Previously, an address below 4G was marked for hugepages if the appropriate segment bit in the "low areas" bitmask was set *or* if the low bit in the "high areas" bitmap was set (which would mark all addresses below 1TB for hugepage). With this patch, any given address is governed by a single bitmap. Addresses below 4GB are marked for hugepage if and only if their bit is set in the "low areas" bitmap (256M granularity). Addresses between 4GB and 1TB are marked for hugepage iff the low bit in the "high areas" bitmap is set. Higher addresses are marked for hugepage iff their bit in the "high areas" bitmap is set (1TB granularity). To avoid conflicts, this patch must be applied on top of BenH's pending patch for 64k base page size [0]. As such, this patch also addresses a hugepage problem introduced by that patch. That patch allows hugepages of 1MB in size on hardware which supports it, however, that won't work when using 4k pages (4 level pagetable), because in that case hugepage PTEs are stored at the PMD level, and each PMD entry maps 2MB. This patch simply disallows hugepages in that case (we can do something cleverer to re-enable them some other day). Built, booted, and a handful of hugepage related tests passed on POWER5 LPAR (both ARCH=powerpc and ARCH=ppc64). [0] http://gate.crashing.org/~benh/ppc64-64k-pages.diff Signed-off-by: David Gibson Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/mm/hash_utils_64.c | 6 ++++-- arch/powerpc/mm/hugetlbpage.c | 6 ++++++ arch/powerpc/mm/slb_low.S | 13 +++++++++---- include/asm-ppc64/pgtable-4k.h | 3 +++ include/asm-ppc64/pgtable-64k.h | 3 +++ 5 files changed, 25 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index b2f3dbca695..f15dfb92dec 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -329,12 +329,14 @@ static void __init htab_init_page_sizes(void) */ if (mmu_psize_defs[MMU_PAGE_16M].shift) mmu_huge_psize = MMU_PAGE_16M; + /* With 4k/4level pagetables, we can't (for now) cope with a + * huge page size < PMD_SIZE */ else if (mmu_psize_defs[MMU_PAGE_1M].shift) mmu_huge_psize = MMU_PAGE_1M; /* Calculate HPAGE_SHIFT and sanity check it */ - if (mmu_psize_defs[mmu_huge_psize].shift > 16 && - mmu_psize_defs[mmu_huge_psize].shift < 28) + if (mmu_psize_defs[mmu_huge_psize].shift > MIN_HUGEPTE_SHIFT && + mmu_psize_defs[mmu_huge_psize].shift < SID_SHIFT) HPAGE_SHIFT = mmu_psize_defs[mmu_huge_psize].shift; else HPAGE_SHIFT = 0; /* No huge pages dude ! */ diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 0073a04047e..426c269e552 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -212,6 +212,12 @@ static int prepare_high_area_for_htlb(struct mm_struct *mm, unsigned long area) BUG_ON(area >= NUM_HIGH_AREAS); + /* Hack, so that each addresses is controlled by exactly one + * of the high or low area bitmaps, the first high area starts + * at 4GB, not 0 */ + if (start == 0) + start = 0x100000000UL; + /* Check no VMAs are in the region */ vma = find_vma(mm, start); if (vma && (vma->vm_start < end)) diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S index 3e18241b6f3..950ffc5848c 100644 --- a/arch/powerpc/mm/slb_low.S +++ b/arch/powerpc/mm/slb_low.S @@ -80,12 +80,17 @@ _GLOBAL(slb_miss_kernel_load_virtual) BEGIN_FTR_SECTION b 1f END_FTR_SECTION_IFCLR(CPU_FTR_16M_PAGE) + cmpldi r10,16 + + lhz r9,PACALOWHTLBAREAS(r13) + mr r11,r10 + blt 5f + lhz r9,PACAHIGHHTLBAREAS(r13) srdi r11,r10,(HTLB_AREA_SHIFT-SID_SHIFT) - srd r9,r9,r11 - lhz r11,PACALOWHTLBAREAS(r13) - srd r11,r11,r10 - or. r9,r9,r11 + +5: srd r9,r9,r11 + andi. r9,r9,1 beq 1f _GLOBAL(slb_miss_user_load_huge) li r11,0 diff --git a/include/asm-ppc64/pgtable-4k.h b/include/asm-ppc64/pgtable-4k.h index c883a274855..e9590c06ad9 100644 --- a/include/asm-ppc64/pgtable-4k.h +++ b/include/asm-ppc64/pgtable-4k.h @@ -23,6 +23,9 @@ #define PMD_SIZE (1UL << PMD_SHIFT) #define PMD_MASK (~(PMD_SIZE-1)) +/* With 4k base page size, hugepage PTEs go at the PMD level */ +#define MIN_HUGEPTE_SHIFT PMD_SHIFT + /* PUD_SHIFT determines what a third-level page table entry can map */ #define PUD_SHIFT (PMD_SHIFT + PMD_INDEX_SIZE) #define PUD_SIZE (1UL << PUD_SHIFT) diff --git a/include/asm-ppc64/pgtable-64k.h b/include/asm-ppc64/pgtable-64k.h index c5f437c86b3..154f1840ece 100644 --- a/include/asm-ppc64/pgtable-64k.h +++ b/include/asm-ppc64/pgtable-64k.h @@ -14,6 +14,9 @@ #define PTRS_PER_PMD (1 << PMD_INDEX_SIZE) #define PTRS_PER_PGD (1 << PGD_INDEX_SIZE) +/* With 4k base page size, hugepage PTEs go at the PMD level */ +#define MIN_HUGEPTE_SHIFT PAGE_SHIFT + /* PMD_SHIFT determines what a second-level page table entry can map */ #define PMD_SHIFT (PAGE_SHIFT + PTE_INDEX_SIZE) #define PMD_SIZE (1UL << PMD_SHIFT) -- cgit v1.2.3 From 4ecc65e423ef10bdbec12362609b15fa8e8627c8 Mon Sep 17 00:00:00 2001 From: Yuri Vasilevski Date: Mon, 7 Nov 2005 00:57:53 -0800 Subject: [PATCH] typo correction for fix-build-on-nls-free-systems A typo fix for fix-build-on-nls-free-systems.patch that caused all systems to be detected as not having NLS. Signed-off-by: Yuri Vasilevski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/kconfig/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index 455aeabd95d..c65c435c492 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile @@ -118,7 +118,7 @@ clean-files := lkc_defs.h qconf.moc .tmp_qtcheck \ # Needed for systems without gettext KBUILD_HAVE_NLS := $(shell \ - if echo "\#include " | $(HOSTCC) $(HOSTCFLAGS) -E - > /dev/null 2>&1 ; \ + if echo "\#include " | $(HOSTCC) $(HOSTCFLAGS) -E - > /dev/null 2>&1 ; \ then echo yes ; \ else echo no ; fi) ifeq ($(KBUILD_HAVE_NLS),no) -- cgit v1.2.3 From e1531b4218a7ccfc1b2234b87105201e5ebe1bbf Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 7 Nov 2005 00:57:54 -0800 Subject: [PATCH] ia64: re-implement dma_get_cache_alignment to avoid EXPORT_SYMBOL The current ia64 implementation of dma_get_cache_alignment does not work for modules because it relies on a symbol which is not exported. Direct access to a global is a little ugly anyway, so this patch re-implements dma_get_cache_alignment in a manner similar to what is currently used for x86_64. Signed-off-by: John W. Linville Cc: "Luck, Tony" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ia64/kernel/setup.c | 7 +++++++ include/asm-ia64/dma-mapping.h | 7 +------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index fc56ca2da35..3af6de36a48 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -92,6 +92,13 @@ extern void efi_initialize_iomem_resources(struct resource *, extern char _text[], _end[], _etext[]; unsigned long ia64_max_cacheline_size; + +int dma_get_cache_alignment(void) +{ + return ia64_max_cacheline_size; +} +EXPORT_SYMBOL(dma_get_cache_alignment); + unsigned long ia64_iobase; /* virtual address for I/O accesses */ EXPORT_SYMBOL(ia64_iobase); struct io_space io_space[MAX_IO_SPACES]; diff --git a/include/asm-ia64/dma-mapping.h b/include/asm-ia64/dma-mapping.h index 6347c984564..df67d40801d 100644 --- a/include/asm-ia64/dma-mapping.h +++ b/include/asm-ia64/dma-mapping.h @@ -48,12 +48,7 @@ dma_set_mask (struct device *dev, u64 mask) return 0; } -static inline int -dma_get_cache_alignment (void) -{ - extern int ia64_max_cacheline_size; - return ia64_max_cacheline_size; -} +extern int dma_get_cache_alignment(void); static inline void dma_cache_sync (void *vaddr, size_t size, enum dma_data_direction dir) -- cgit v1.2.3 From 732ee21f2894819781766a0cd88e32bdd630d11e Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Mon, 7 Nov 2005 00:57:55 -0800 Subject: [PATCH] POWERPC/PPC64: Fix CONFIG_SMP=n build for ppc64 Two CONFIG_SMP=n build fixes due to missing includes. Signed-off-by: Olof Johansson Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/time.c | 1 + arch/ppc64/kernel/sysfs.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 6996a593dcb..b1c89bc4bf9 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -69,6 +69,7 @@ #include #include #endif +#include /* keep track of when we need to update the rtc */ time_t last_rtc_update; diff --git a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c index 6654b350979..e99ec62c2c5 100644 --- a/arch/ppc64/kernel/sysfs.c +++ b/arch/ppc64/kernel/sysfs.c @@ -20,6 +20,7 @@ #include #include #include +#include static DEFINE_PER_CPU(struct cpu, cpu_devices); -- cgit v1.2.3 From 2d4b95f06062d590aef8e44d42cec27b1828119f Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 7 Nov 2005 00:57:57 -0800 Subject: [PATCH] Suppress split ptlock on arches which may use one page for multiple page tables Suppress split ptlock on arches which may use one page for multiple page tables. Reconsider what better to do (particularly on ppc64) later on. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mm/Kconfig b/mm/Kconfig index 1a4473fcb2c..ae9ce6b73e8 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -126,9 +126,11 @@ comment "Memory hotplug is currently incompatible with Software Suspend" # Default to 4 for wider testing, though 8 might be more appropriate. # ARM's adjust_pte (unused if VIPT) depends on mm-wide page_table_lock. # PA-RISC's debug spinlock_t is too large for the 32-bit struct page. +# ARM26 and SPARC32 and PPC64 may use one page for multiple page tables. # config SPLIT_PTLOCK_CPUS int default "4096" if ARM && !CPU_CACHE_VIPT default "4096" if PARISC && DEBUG_SPINLOCK && !64BIT + default "4096" if ARM26 || SPARC32 || PPC64 default "4" -- cgit v1.2.3 From c8e3c8b21bd7a317d071ab8cf478880e7a4f92d6 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 7 Nov 2005 00:57:58 -0800 Subject: [PATCH] ppc64: Fix zImage boot The zImage wrapper has a bug where it doesn't claim() the memory for the kernel properly, it forgets to take into account the offset between the ELF header and the kernel itself. This results on some machines, like G5s, into a kernel that crashes at boot when clearing the BSS. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/boot/main.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c index c1dc876bcca..e0dde24a72c 100644 --- a/arch/ppc64/boot/main.c +++ b/arch/ppc64/boot/main.c @@ -203,8 +203,15 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) if (elf64ph->p_type == PT_LOAD && elf64ph->p_offset != 0) break; } - vmlinux.size = (unsigned long)elf64ph->p_filesz; - vmlinux.memsize = (unsigned long)elf64ph->p_memsz; + vmlinux.size = (unsigned long)elf64ph->p_filesz + + (unsigned long)elf64ph->p_offset; + /* We need to claim the memsize plus the file offset since gzip + * will expand the header (file offset), then the kernel, then + * possible rubbish we don't care about. But the kernel bss must + * be claimed (it will be zero'd by the kernel itself) + */ + vmlinux.memsize = (unsigned long)elf64ph->p_memsz + + (unsigned long)elf64ph->p_offset; printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux.memsize); vmlinux.addr = try_claim(vmlinux.memsize); if (vmlinux.addr == 0) { -- cgit v1.2.3 From 863c84b97cb660dbb949398e196c0b1bbe4ed39f Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 7 Nov 2005 00:57:58 -0800 Subject: [PATCH] ppc: Fix ppc32 build after 64K pages Oops, some last minute changes caused the 64K pages patch to break ppc32 build, this fixes it. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/Kconfig | 1 + arch/powerpc/mm/ppc_mmu_32.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index ca7acb0c79f..55ce4957052 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -605,6 +605,7 @@ config NODES_SPAN_OTHER_NODES config PPC_64K_PAGES bool "64k page size" + depends on PPC64 help This option changes the kernel logical page size to 64k. On machines without processor support for 64k pages, the kernel will simulate diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c index d137abd241f..ed7fcfe5fd3 100644 --- a/arch/powerpc/mm/ppc_mmu_32.c +++ b/arch/powerpc/mm/ppc_mmu_32.c @@ -188,9 +188,9 @@ void hash_preload(struct mm_struct *mm, unsigned long ea, if (Hash == 0) return; - pmd = pmd_offset(pgd_offset(vma->vm_mm, address), address); + pmd = pmd_offset(pgd_offset(mm, ea), ea); if (!pmd_none(*pmd)) - add_hash_page(vma->vm_mm->context, address, pmd_val(*pmd)); + add_hash_page(mm->context, ea, pmd_val(*pmd)); } /* -- cgit v1.2.3 From 7fd93cf30c531fd8b014e827e7a85fcfc010b2c6 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 7 Nov 2005 00:57:59 -0800 Subject: [PATCH] posix-timers `unlikely' rejig !unlikely(expr) hurts my brain. likely(!expr) is more straightforward. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/posix-cpu-timers.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index 91a89426494..84af54c39e1 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c @@ -497,7 +497,7 @@ static void process_timer_rebalance(struct task_struct *p, left = cputime_div(cputime_sub(expires.cpu, val.cpu), nthreads); do { - if (!unlikely(t->flags & PF_EXITING)) { + if (likely(!(t->flags & PF_EXITING))) { ticks = cputime_add(prof_ticks(t), left); if (cputime_eq(t->it_prof_expires, cputime_zero) || @@ -512,7 +512,7 @@ static void process_timer_rebalance(struct task_struct *p, left = cputime_div(cputime_sub(expires.cpu, val.cpu), nthreads); do { - if (!unlikely(t->flags & PF_EXITING)) { + if (likely(!(t->flags & PF_EXITING))) { ticks = cputime_add(virt_ticks(t), left); if (cputime_eq(t->it_virt_expires, cputime_zero) || @@ -527,7 +527,7 @@ static void process_timer_rebalance(struct task_struct *p, nsleft = expires.sched - val.sched; do_div(nsleft, nthreads); do { - if (!unlikely(t->flags & PF_EXITING)) { + if (likely(!(t->flags & PF_EXITING))) { ns = t->sched_time + nsleft; if (t->it_sched_expires == 0 || t->it_sched_expires > ns) { -- cgit v1.2.3 From 4f12bb4f7715f418a9c80f89447948790f476958 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 7 Nov 2005 00:58:00 -0800 Subject: [PATCH] slab: don't BUG on duplicated cache slab presently goes BUG if someone tries to register an already-registered cache. But this can happen if the user accidentally loads a module which is already statically linked into the kernel. Nuking the kernel is rather a harsh reaction. Change it into a warning, and just fail the kmem_cache_alloc() attempt. If the module is well-behaved, the modprobe will fail and all is well. Notes: - Swaps the ranking of cache_chain_sem and lock_cpu_hotplug(). Doesn't seem important. Acked-by: Manfred Spraul Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/slab.c | 67 ++++++++++++++++++++++++++++++++------------------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index 22bfb0b2ac8..41e91794aa5 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1502,6 +1502,7 @@ kmem_cache_create (const char *name, size_t size, size_t align, { size_t left_over, slab_size, ralign; kmem_cache_t *cachep = NULL; + struct list_head *p; /* * Sanity checks... these are all serious usage bugs. @@ -1516,6 +1517,35 @@ kmem_cache_create (const char *name, size_t size, size_t align, BUG(); } + down(&cache_chain_sem); + + list_for_each(p, &cache_chain) { + kmem_cache_t *pc = list_entry(p, kmem_cache_t, next); + mm_segment_t old_fs = get_fs(); + char tmp; + int res; + + /* + * This happens when the module gets unloaded and doesn't + * destroy its slab cache and no-one else reuses the vmalloc + * area of the module. Print a warning. + */ + set_fs(KERNEL_DS); + res = __get_user(tmp, pc->name); + set_fs(old_fs); + if (res) { + printk("SLAB: cache with size %d has lost its name\n", + pc->objsize); + continue; + } + + if (!strcmp(pc->name,name)) { + printk("kmem_cache_create: duplicate cache %s\n", name); + dump_stack(); + goto oops; + } + } + #if DEBUG WARN_ON(strchr(name, ' ')); /* It confuses parsers */ if ((flags & SLAB_DEBUG_INITIAL) && !ctor) { @@ -1592,7 +1622,7 @@ kmem_cache_create (const char *name, size_t size, size_t align, /* Get cache's description obj. */ cachep = (kmem_cache_t *) kmem_cache_alloc(&cache_cache, SLAB_KERNEL); if (!cachep) - goto opps; + goto oops; memset(cachep, 0, sizeof(kmem_cache_t)); #if DEBUG @@ -1686,7 +1716,7 @@ next: printk("kmem_cache_create: couldn't create cache %s.\n", name); kmem_cache_free(&cache_cache, cachep); cachep = NULL; - goto opps; + goto oops; } slab_size = ALIGN(cachep->num*sizeof(kmem_bufctl_t) + sizeof(struct slab), align); @@ -1781,43 +1811,14 @@ next: cachep->limit = BOOT_CPUCACHE_ENTRIES; } - /* Need the semaphore to access the chain. */ - down(&cache_chain_sem); - { - struct list_head *p; - mm_segment_t old_fs; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - list_for_each(p, &cache_chain) { - kmem_cache_t *pc = list_entry(p, kmem_cache_t, next); - char tmp; - /* This happens when the module gets unloaded and doesn't - destroy its slab cache and noone else reuses the vmalloc - area of the module. Print a warning. */ - if (__get_user(tmp,pc->name)) { - printk("SLAB: cache with size %d has lost its name\n", - pc->objsize); - continue; - } - if (!strcmp(pc->name,name)) { - printk("kmem_cache_create: duplicate cache %s\n",name); - up(&cache_chain_sem); - unlock_cpu_hotplug(); - BUG(); - } - } - set_fs(old_fs); - } - /* cache setup completed, link it into the list */ list_add(&cachep->next, &cache_chain); - up(&cache_chain_sem); unlock_cpu_hotplug(); -opps: +oops: if (!cachep && (flags & SLAB_PANIC)) panic("kmem_cache_create(): failed to create slab `%s'\n", name); + up(&cache_chain_sem); return cachep; } EXPORT_SYMBOL(kmem_cache_create); -- cgit v1.2.3 From 2109a2d1b175dfcffbfdac693bdbe4c4ab62f11f Mon Sep 17 00:00:00 2001 From: Pekka J Enberg Date: Mon, 7 Nov 2005 00:58:01 -0800 Subject: [PATCH] mm: rename kmem_cache_s to kmem_cache This patch renames struct kmem_cache_s to kmem_cache so we can start using it instead of kmem_cache_t typedef. Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/magic-number.txt | 2 +- fs/file_table.c | 4 ++-- fs/freevxfs/vxfs_extern.h | 4 ++-- fs/xfs/linux-2.6/kmem.h | 4 ++-- include/linux/file.h | 6 +++--- include/linux/slab.h | 2 +- mm/slab.c | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Documentation/magic-number.txt b/Documentation/magic-number.txt index bd8eefa1758..af67faccf4d 100644 --- a/Documentation/magic-number.txt +++ b/Documentation/magic-number.txt @@ -120,7 +120,7 @@ ISDN_NET_MAGIC 0x49344C02 isdn_net_local_s drivers/isdn/i4l/isdn_net_li SAVEKMSG_MAGIC2 0x4B4D5347 savekmsg arch/*/amiga/config.c STLI_BOARDMAGIC 0x4bc6c825 stlibrd include/linux/istallion.h CS_STATE_MAGIC 0x4c4f4749 cs_state sound/oss/cs46xx.c -SLAB_C_MAGIC 0x4f17a36d kmem_cache_s mm/slab.c +SLAB_C_MAGIC 0x4f17a36d kmem_cache mm/slab.c COW_MAGIC 0x4f4f4f4d cow_header_v1 arch/um/drivers/ubd_user.c I810_CARD_MAGIC 0x5072696E i810_card sound/oss/i810_audio.c TRIDENT_CARD_MAGIC 0x5072696E trident_card sound/oss/trident.c diff --git a/fs/file_table.c b/fs/file_table.c index 4dc20554654..c3a5e2fd663 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -35,7 +35,7 @@ static DEFINE_SPINLOCK(filp_count_lock); * context and must be fully threaded - use a local spinlock * to protect files_stat.nr_files */ -void filp_ctor(void * objp, struct kmem_cache_s *cachep, unsigned long cflags) +void filp_ctor(void *objp, struct kmem_cache *cachep, unsigned long cflags) { if ((cflags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) { @@ -46,7 +46,7 @@ void filp_ctor(void * objp, struct kmem_cache_s *cachep, unsigned long cflags) } } -void filp_dtor(void * objp, struct kmem_cache_s *cachep, unsigned long dflags) +void filp_dtor(void *objp, struct kmem_cache *cachep, unsigned long dflags) { unsigned long flags; spin_lock_irqsave(&filp_count_lock, flags); diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h index d8be917f979..927acf70c59 100644 --- a/fs/freevxfs/vxfs_extern.h +++ b/fs/freevxfs/vxfs_extern.h @@ -38,7 +38,7 @@ */ -struct kmem_cache_s; +struct kmem_cache; struct super_block; struct vxfs_inode_info; struct inode; @@ -51,7 +51,7 @@ extern daddr_t vxfs_bmap1(struct inode *, long); extern int vxfs_read_fshead(struct super_block *); /* vxfs_inode.c */ -extern struct kmem_cache_s *vxfs_inode_cachep; +extern struct kmem_cache *vxfs_inode_cachep; extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t); extern struct inode * vxfs_get_fake_inode(struct super_block *, struct vxfs_inode_info *); diff --git a/fs/xfs/linux-2.6/kmem.h b/fs/xfs/linux-2.6/kmem.h index 8f82c1a20dc..c64a29cdfff 100644 --- a/fs/xfs/linux-2.6/kmem.h +++ b/fs/xfs/linux-2.6/kmem.h @@ -30,8 +30,8 @@ #define KM_NOFS 0x0004u #define KM_MAYFAIL 0x0008u -#define kmem_zone kmem_cache_s -#define kmem_zone_t kmem_cache_t +#define kmem_zone kmem_cache +#define kmem_zone_t struct kmem_cache typedef unsigned long xfs_pflags_t; diff --git a/include/linux/file.h b/include/linux/file.h index f5bbd4c508b..d3b1a15d5f2 100644 --- a/include/linux/file.h +++ b/include/linux/file.h @@ -59,9 +59,9 @@ extern void FASTCALL(set_close_on_exec(unsigned int fd, int flag)); extern void put_filp(struct file *); extern int get_unused_fd(void); extern void FASTCALL(put_unused_fd(unsigned int fd)); -struct kmem_cache_s; -extern void filp_ctor(void * objp, struct kmem_cache_s *cachep, unsigned long cflags); -extern void filp_dtor(void * objp, struct kmem_cache_s *cachep, unsigned long dflags); +struct kmem_cache; +extern void filp_ctor(void * objp, struct kmem_cache *cachep, unsigned long cflags); +extern void filp_dtor(void * objp, struct kmem_cache *cachep, unsigned long dflags); extern struct file ** alloc_fd_array(int); extern void free_fd_array(struct file **, int); diff --git a/include/linux/slab.h b/include/linux/slab.h index 09b9aa60063..d1ea4051b99 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -9,7 +9,7 @@ #if defined(__KERNEL__) -typedef struct kmem_cache_s kmem_cache_t; +typedef struct kmem_cache kmem_cache_t; #include /* kmalloc_sizes.h needs CONFIG_ options */ #include diff --git a/mm/slab.c b/mm/slab.c index 41e91794aa5..d77e5f50fba 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -368,7 +368,7 @@ static inline void kmem_list3_init(struct kmem_list3 *parent) * manages a cache. */ -struct kmem_cache_s { +struct kmem_cache { /* 1) per-cpu data, touched during every alloc/free */ struct array_cache *array[NR_CPUS]; unsigned int batchcount; -- cgit v1.2.3 From cd61ef6268ac52d3dfa5626d1e0306a91b3b2608 Mon Sep 17 00:00:00 2001 From: Manfred Spraul Date: Mon, 7 Nov 2005 00:58:02 -0800 Subject: [PATCH] slab: Use same schedule timeout for all cpus in cache_reap Chen noticed that cache_reap uses REAPTIMEOUT_CPUC+smp_processor_id() as the timeout for rescheduling. The "+smp_processor_id()" part is wrong, the timeout should be identical for all cpus: start_cpu_timer already adds a cpu dependant offset to avoid any clustering. The attached patch removes smp_processor_id(). Signed-Off-By: Manfred Spraul Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/slab.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index d77e5f50fba..1db4d731385 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -3279,7 +3279,7 @@ static void cache_reap(void *unused) if (down_trylock(&cache_chain_sem)) { /* Give up. Setup the next iteration. */ - schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC + smp_processor_id()); + schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC); return; } @@ -3348,7 +3348,7 @@ next: up(&cache_chain_sem); drain_remote_pages(); /* Setup the next iteration */ - schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC + smp_processor_id()); + schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC); } #ifdef CONFIG_PROC_FS -- cgit v1.2.3 From 62afe595de7aaac6c140103a34dc8c208afa34e7 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 7 Nov 2005 00:58:02 -0800 Subject: [PATCH] 3c59x: convert to use of pci_iomap API Convert 3c59x driver to use pci_iomap API. This makes it easier to enable the use of memory-mapped PCI I/O resources. Signed-off-by: John W. Linville Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/3c59x.c | 507 +++++++++++++++++++++++++++------------------------- 1 file changed, 260 insertions(+), 247 deletions(-) diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 455ba915ede..2bad41bebd1 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -602,7 +602,7 @@ MODULE_DEVICE_TABLE(pci, vortex_pci_tbl); First the windows. There are eight register windows, with the command and status registers available in each. */ -#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD) +#define EL3WINDOW(win_num) iowrite16(SelectWindow + (win_num), ioaddr + EL3_CMD) #define EL3_CMD 0x0e #define EL3_STATUS 0x0e @@ -776,7 +776,8 @@ struct vortex_private { /* PCI configuration space information. */ struct device *gendev; - char __iomem *cb_fn_base; /* CardBus function status addr space. */ + void __iomem *ioaddr; /* IO address space */ + void __iomem *cb_fn_base; /* CardBus function status addr space. */ /* Some values here only for performance evaluation and path-coverage */ int rx_nocopy, rx_copy, queued_packet, rx_csumhits; @@ -869,12 +870,12 @@ static struct { /* number of ETHTOOL_GSTATS u64's */ #define VORTEX_NUM_STATS 3 -static int vortex_probe1(struct device *gendev, long ioaddr, int irq, +static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq, int chip_idx, int card_idx); static void vortex_up(struct net_device *dev); static void vortex_down(struct net_device *dev, int final); static int vortex_open(struct net_device *dev); -static void mdio_sync(long ioaddr, int bits); +static void mdio_sync(void __iomem *ioaddr, int bits); static int mdio_read(struct net_device *dev, int phy_id, int location); static void mdio_write(struct net_device *vp, int phy_id, int location, int value); static void vortex_timer(unsigned long arg); @@ -887,7 +888,7 @@ static irqreturn_t vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs); static int vortex_close(struct net_device *dev); static void dump_tx_ring(struct net_device *dev); -static void update_stats(long ioaddr, struct net_device *dev); +static void update_stats(void __iomem *ioaddr, struct net_device *dev); static struct net_device_stats *vortex_get_stats(struct net_device *dev); static void set_rx_mode(struct net_device *dev); #ifdef CONFIG_PCI @@ -1029,18 +1030,19 @@ static struct eisa_driver vortex_eisa_driver = { static int vortex_eisa_probe (struct device *device) { - long ioaddr; + void __iomem *ioaddr; struct eisa_device *edev; edev = to_eisa_device (device); - ioaddr = edev->base_addr; - if (!request_region(ioaddr, VORTEX_TOTAL_SIZE, DRV_NAME)) + if (!request_region(edev->base_addr, VORTEX_TOTAL_SIZE, DRV_NAME)) return -EBUSY; - if (vortex_probe1(device, ioaddr, inw(ioaddr + 0xC88) >> 12, + ioaddr = ioport_map(edev->base_addr, VORTEX_TOTAL_SIZE); + + if (vortex_probe1(device, ioaddr, ioread16(ioaddr + 0xC88) >> 12, edev->id.driver_data, vortex_cards_found)) { - release_region (ioaddr, VORTEX_TOTAL_SIZE); + release_region (edev->base_addr, VORTEX_TOTAL_SIZE); return -ENODEV; } @@ -1054,7 +1056,7 @@ static int vortex_eisa_remove (struct device *device) struct eisa_device *edev; struct net_device *dev; struct vortex_private *vp; - long ioaddr; + void __iomem *ioaddr; edev = to_eisa_device (device); dev = eisa_get_drvdata (edev); @@ -1065,11 +1067,11 @@ static int vortex_eisa_remove (struct device *device) } vp = netdev_priv(dev); - ioaddr = dev->base_addr; + ioaddr = vp->ioaddr; unregister_netdev (dev); - outw (TotalReset|0x14, ioaddr + EL3_CMD); - release_region (ioaddr, VORTEX_TOTAL_SIZE); + iowrite16 (TotalReset|0x14, ioaddr + EL3_CMD); + release_region (dev->base_addr, VORTEX_TOTAL_SIZE); free_netdev (dev); return 0; @@ -1096,8 +1098,8 @@ static int __init vortex_eisa_init (void) /* Special code to work-around the Compaq PCI BIOS32 problem. */ if (compaq_ioaddr) { - vortex_probe1(NULL, compaq_ioaddr, compaq_irq, - compaq_device_id, vortex_cards_found++); + vortex_probe1(NULL, ioport_map(compaq_ioaddr, VORTEX_TOTAL_SIZE), + compaq_irq, compaq_device_id, vortex_cards_found++); } return vortex_cards_found - orig_cards_found + eisa_found; @@ -1114,8 +1116,8 @@ static int __devinit vortex_init_one (struct pci_dev *pdev, if (rc < 0) goto out; - rc = vortex_probe1 (&pdev->dev, pci_resource_start (pdev, 0), - pdev->irq, ent->driver_data, vortex_cards_found); + rc = vortex_probe1 (&pdev->dev, pci_iomap(pdev, 0, 0), + pdev->irq, ent->driver_data, vortex_cards_found); if (rc < 0) { pci_disable_device (pdev); goto out; @@ -1134,7 +1136,7 @@ out: * NOTE: pdev can be NULL, for the case of a Compaq device */ static int __devinit vortex_probe1(struct device *gendev, - long ioaddr, int irq, + void __iomem *ioaddr, int irq, int chip_idx, int card_idx) { struct vortex_private *vp; @@ -1202,15 +1204,16 @@ static int __devinit vortex_probe1(struct device *gendev, if (print_info) printk (KERN_INFO "See Documentation/networking/vortex.txt\n"); - printk(KERN_INFO "%s: 3Com %s %s at 0x%lx. Vers " DRV_VERSION "\n", + printk(KERN_INFO "%s: 3Com %s %s at %p. Vers " DRV_VERSION "\n", print_name, pdev ? "PCI" : "EISA", vci->name, ioaddr); - dev->base_addr = ioaddr; + dev->base_addr = (unsigned long)ioaddr; dev->irq = irq; dev->mtu = mtu; + vp->ioaddr = ioaddr; vp->large_frames = mtu > 1500; vp->drv_flags = vci->drv_flags; vp->has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0; @@ -1226,7 +1229,7 @@ static int __devinit vortex_probe1(struct device *gendev, if (pdev) { /* EISA resources already marked, so only PCI needs to do this here */ /* Ignore return value, because Cardbus drivers already allocate for us */ - if (request_region(ioaddr, vci->io_size, print_name) != NULL) + if (request_region(dev->base_addr, vci->io_size, print_name) != NULL) vp->must_free_region = 1; /* enable bus-mastering if necessary */ @@ -1316,14 +1319,14 @@ static int __devinit vortex_probe1(struct device *gendev, for (i = 0; i < 0x40; i++) { int timer; - outw(base + i, ioaddr + Wn0EepromCmd); + iowrite16(base + i, ioaddr + Wn0EepromCmd); /* Pause for at least 162 us. for the read to take place. */ for (timer = 10; timer >= 0; timer--) { udelay(162); - if ((inw(ioaddr + Wn0EepromCmd) & 0x8000) == 0) + if ((ioread16(ioaddr + Wn0EepromCmd) & 0x8000) == 0) break; } - eeprom[i] = inw(ioaddr + Wn0EepromData); + eeprom[i] = ioread16(ioaddr + Wn0EepromData); } } for (i = 0; i < 0x18; i++) @@ -1351,7 +1354,7 @@ static int __devinit vortex_probe1(struct device *gendev, } EL3WINDOW(2); for (i = 0; i < 6; i++) - outb(dev->dev_addr[i], ioaddr + i); + iowrite8(dev->dev_addr[i], ioaddr + i); #ifdef __sparc__ if (print_info) @@ -1366,7 +1369,7 @@ static int __devinit vortex_probe1(struct device *gendev, #endif EL3WINDOW(4); - step = (inb(ioaddr + Wn4_NetDiag) & 0x1e) >> 1; + step = (ioread8(ioaddr + Wn4_NetDiag) & 0x1e) >> 1; if (print_info) { printk(KERN_INFO " product code %02x%02x rev %02x.%d date %02d-" "%02d-%02d\n", eeprom[6]&0xff, eeprom[6]>>8, eeprom[0x14], @@ -1375,31 +1378,30 @@ static int __devinit vortex_probe1(struct device *gendev, if (pdev && vci->drv_flags & HAS_CB_FNS) { - unsigned long fn_st_addr; /* Cardbus function status space */ unsigned short n; - fn_st_addr = pci_resource_start (pdev, 2); - if (fn_st_addr) { - vp->cb_fn_base = ioremap(fn_st_addr, 128); + vp->cb_fn_base = pci_iomap(pdev, 2, 0); + if (!vp->cb_fn_base) { retval = -ENOMEM; - if (!vp->cb_fn_base) - goto free_ring; + goto free_ring; } + if (print_info) { printk(KERN_INFO "%s: CardBus functions mapped %8.8lx->%p\n", - print_name, fn_st_addr, vp->cb_fn_base); + print_name, pci_resource_start(pdev, 2), + vp->cb_fn_base); } EL3WINDOW(2); - n = inw(ioaddr + Wn2_ResetOptions) & ~0x4010; + n = ioread16(ioaddr + Wn2_ResetOptions) & ~0x4010; if (vp->drv_flags & INVERT_LED_PWR) n |= 0x10; if (vp->drv_flags & INVERT_MII_PWR) n |= 0x4000; - outw(n, ioaddr + Wn2_ResetOptions); + iowrite16(n, ioaddr + Wn2_ResetOptions); if (vp->drv_flags & WNO_XCVR_PWR) { EL3WINDOW(0); - outw(0x0800, ioaddr); + iowrite16(0x0800, ioaddr); } } @@ -1418,13 +1420,13 @@ static int __devinit vortex_probe1(struct device *gendev, static const char * ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; unsigned int config; EL3WINDOW(3); - vp->available_media = inw(ioaddr + Wn3_Options); + vp->available_media = ioread16(ioaddr + Wn3_Options); if ((vp->available_media & 0xff) == 0) /* Broken 3c916 */ vp->available_media = 0x40; - config = inl(ioaddr + Wn3_Config); + config = ioread32(ioaddr + Wn3_Config); if (print_info) { printk(KERN_DEBUG " Internal config register is %4.4x, " - "transceivers %#x.\n", config, inw(ioaddr + Wn3_Options)); + "transceivers %#x.\n", config, ioread16(ioaddr + Wn3_Options)); printk(KERN_INFO " %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n", 8 << RAM_SIZE(config), RAM_WIDTH(config) ? "word" : "byte", @@ -1555,7 +1557,7 @@ free_ring: vp->rx_ring_dma); free_region: if (vp->must_free_region) - release_region(ioaddr, vci->io_size); + release_region(dev->base_addr, vci->io_size); free_netdev(dev); printk(KERN_ERR PFX "vortex_probe1 fails. Returns %d\n", retval); out: @@ -1565,17 +1567,19 @@ out: static void issue_and_wait(struct net_device *dev, int cmd) { + struct vortex_private *vp = netdev_priv(dev); + void __iomem *ioaddr = vp->ioaddr; int i; - outw(cmd, dev->base_addr + EL3_CMD); + iowrite16(cmd, ioaddr + EL3_CMD); for (i = 0; i < 2000; i++) { - if (!(inw(dev->base_addr + EL3_STATUS) & CmdInProgress)) + if (!(ioread16(ioaddr + EL3_STATUS) & CmdInProgress)) return; } /* OK, that didn't work. Do it the slow way. One second */ for (i = 0; i < 100000; i++) { - if (!(inw(dev->base_addr + EL3_STATUS) & CmdInProgress)) { + if (!(ioread16(ioaddr + EL3_STATUS) & CmdInProgress)) { if (vortex_debug > 1) printk(KERN_INFO "%s: command 0x%04x took %d usecs\n", dev->name, cmd, i * 10); @@ -1584,14 +1588,14 @@ issue_and_wait(struct net_device *dev, int cmd) udelay(10); } printk(KERN_ERR "%s: command 0x%04x did not complete! Status=0x%x\n", - dev->name, cmd, inw(dev->base_addr + EL3_STATUS)); + dev->name, cmd, ioread16(ioaddr + EL3_STATUS)); } static void vortex_up(struct net_device *dev) { - long ioaddr = dev->base_addr; struct vortex_private *vp = netdev_priv(dev); + void __iomem *ioaddr = vp->ioaddr; unsigned int config; int i; @@ -1604,7 +1608,7 @@ vortex_up(struct net_device *dev) /* Before initializing select the active media port. */ EL3WINDOW(3); - config = inl(ioaddr + Wn3_Config); + config = ioread32(ioaddr + Wn3_Config); if (vp->media_override != 7) { printk(KERN_INFO "%s: Media override to transceiver %d (%s).\n", @@ -1651,7 +1655,7 @@ vortex_up(struct net_device *dev) config = BFINS(config, dev->if_port, 20, 4); if (vortex_debug > 6) printk(KERN_DEBUG "vortex_up(): writing 0x%x to InternalConfig\n", config); - outl(config, ioaddr + Wn3_Config); + iowrite32(config, ioaddr + Wn3_Config); if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) { int mii_reg1, mii_reg5; @@ -1679,7 +1683,7 @@ vortex_up(struct net_device *dev) } /* Set the full-duplex bit. */ - outw( ((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) | + iowrite16( ((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) | (vp->large_frames ? 0x40 : 0) | ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0), ioaddr + Wn3_MAC_Ctrl); @@ -1695,51 +1699,51 @@ vortex_up(struct net_device *dev) */ issue_and_wait(dev, RxReset|0x04); - outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD); + iowrite16(SetStatusEnb | 0x00, ioaddr + EL3_CMD); if (vortex_debug > 1) { EL3WINDOW(4); printk(KERN_DEBUG "%s: vortex_up() irq %d media status %4.4x.\n", - dev->name, dev->irq, inw(ioaddr + Wn4_Media)); + dev->name, dev->irq, ioread16(ioaddr + Wn4_Media)); } /* Set the station address and mask in window 2 each time opened. */ EL3WINDOW(2); for (i = 0; i < 6; i++) - outb(dev->dev_addr[i], ioaddr + i); + iowrite8(dev->dev_addr[i], ioaddr + i); for (; i < 12; i+=2) - outw(0, ioaddr + i); + iowrite16(0, ioaddr + i); if (vp->cb_fn_base) { - unsigned short n = inw(ioaddr + Wn2_ResetOptions) & ~0x4010; + unsigned short n = ioread16(ioaddr + Wn2_ResetOptions) & ~0x4010; if (vp->drv_flags & INVERT_LED_PWR) n |= 0x10; if (vp->drv_flags & INVERT_MII_PWR) n |= 0x4000; - outw(n, ioaddr + Wn2_ResetOptions); + iowrite16(n, ioaddr + Wn2_ResetOptions); } if (dev->if_port == XCVR_10base2) /* Start the thinnet transceiver. We should really wait 50ms...*/ - outw(StartCoax, ioaddr + EL3_CMD); + iowrite16(StartCoax, ioaddr + EL3_CMD); if (dev->if_port != XCVR_NWAY) { EL3WINDOW(4); - outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) | + iowrite16((ioread16(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) | media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media); } /* Switch to the stats window, and clear all stats by reading. */ - outw(StatsDisable, ioaddr + EL3_CMD); + iowrite16(StatsDisable, ioaddr + EL3_CMD); EL3WINDOW(6); for (i = 0; i < 10; i++) - inb(ioaddr + i); - inw(ioaddr + 10); - inw(ioaddr + 12); + ioread8(ioaddr + i); + ioread16(ioaddr + 10); + ioread16(ioaddr + 12); /* New: On the Vortex we must also clear the BadSSD counter. */ EL3WINDOW(4); - inb(ioaddr + 12); + ioread8(ioaddr + 12); /* ..and on the Boomerang we enable the extra statistics bits. */ - outw(0x0040, ioaddr + Wn4_NetDiag); + iowrite16(0x0040, ioaddr + Wn4_NetDiag); /* Switch to register set 7 for normal use. */ EL3WINDOW(7); @@ -1747,30 +1751,30 @@ vortex_up(struct net_device *dev) if (vp->full_bus_master_rx) { /* Boomerang bus master. */ vp->cur_rx = vp->dirty_rx = 0; /* Initialize the RxEarly register as recommended. */ - outw(SetRxThreshold + (1536>>2), ioaddr + EL3_CMD); - outl(0x0020, ioaddr + PktStatus); - outl(vp->rx_ring_dma, ioaddr + UpListPtr); + iowrite16(SetRxThreshold + (1536>>2), ioaddr + EL3_CMD); + iowrite32(0x0020, ioaddr + PktStatus); + iowrite32(vp->rx_ring_dma, ioaddr + UpListPtr); } if (vp->full_bus_master_tx) { /* Boomerang bus master Tx. */ vp->cur_tx = vp->dirty_tx = 0; if (vp->drv_flags & IS_BOOMERANG) - outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */ + iowrite8(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */ /* Clear the Rx, Tx rings. */ for (i = 0; i < RX_RING_SIZE; i++) /* AKPM: this is done in vortex_open, too */ vp->rx_ring[i].status = 0; for (i = 0; i < TX_RING_SIZE; i++) vp->tx_skbuff[i] = NULL; - outl(0, ioaddr + DownListPtr); + iowrite32(0, ioaddr + DownListPtr); } /* Set receiver mode: presumably accept b-case and phys addr only. */ set_rx_mode(dev); /* enable 802.1q tagged frames */ set_8021q_mode(dev, 1); - outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ + iowrite16(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ // issue_and_wait(dev, SetTxStart|0x07ff); - outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ - outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ + iowrite16(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ + iowrite16(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ /* Allow status bits to be seen. */ vp->status_enable = SetStatusEnb | HostError|IntReq|StatsFull|TxComplete| (vp->full_bus_master_tx ? DownComplete : TxAvailable) | @@ -1780,13 +1784,13 @@ vortex_up(struct net_device *dev) (vp->full_bus_master_rx ? 0 : RxComplete) | StatsFull | HostError | TxComplete | IntReq | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete; - outw(vp->status_enable, ioaddr + EL3_CMD); + iowrite16(vp->status_enable, ioaddr + EL3_CMD); /* Ack all pending events, and set active indicator mask. */ - outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq, + iowrite16(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq, ioaddr + EL3_CMD); - outw(vp->intr_enable, ioaddr + EL3_CMD); + iowrite16(vp->intr_enable, ioaddr + EL3_CMD); if (vp->cb_fn_base) /* The PCMCIA people are idiots. */ - writel(0x8000, vp->cb_fn_base + 4); + iowrite32(0x8000, vp->cb_fn_base + 4); netif_start_queue (dev); } @@ -1852,7 +1856,7 @@ vortex_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct vortex_private *vp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = vp->ioaddr; int next_tick = 60*HZ; int ok = 0; int media_status, mii_status, old_window; @@ -1866,9 +1870,9 @@ vortex_timer(unsigned long data) if (vp->medialock) goto leave_media_alone; disable_irq(dev->irq); - old_window = inw(ioaddr + EL3_CMD) >> 13; + old_window = ioread16(ioaddr + EL3_CMD) >> 13; EL3WINDOW(4); - media_status = inw(ioaddr + Wn4_Media); + media_status = ioread16(ioaddr + Wn4_Media); switch (dev->if_port) { case XCVR_10baseT: case XCVR_100baseTx: case XCVR_100baseFx: if (media_status & Media_LnkBeat) { @@ -1909,7 +1913,7 @@ vortex_timer(unsigned long data) vp->phys[0], mii_reg5); /* Set the full-duplex bit. */ EL3WINDOW(3); - outw( (vp->full_duplex ? 0x20 : 0) | + iowrite16( (vp->full_duplex ? 0x20 : 0) | (vp->large_frames ? 0x40 : 0) | ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0), ioaddr + Wn3_MAC_Ctrl); @@ -1950,15 +1954,15 @@ vortex_timer(unsigned long data) dev->name, media_tbl[dev->if_port].name); next_tick = media_tbl[dev->if_port].wait; } - outw((media_status & ~(Media_10TP|Media_SQE)) | + iowrite16((media_status & ~(Media_10TP|Media_SQE)) | media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media); EL3WINDOW(3); - config = inl(ioaddr + Wn3_Config); + config = ioread32(ioaddr + Wn3_Config); config = BFINS(config, dev->if_port, 20, 4); - outl(config, ioaddr + Wn3_Config); + iowrite32(config, ioaddr + Wn3_Config); - outw(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax, + iowrite16(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax, ioaddr + EL3_CMD); if (vortex_debug > 1) printk(KERN_DEBUG "wrote 0x%08x to Wn3_Config\n", config); @@ -1974,29 +1978,29 @@ leave_media_alone: mod_timer(&vp->timer, RUN_AT(next_tick)); if (vp->deferred) - outw(FakeIntr, ioaddr + EL3_CMD); + iowrite16(FakeIntr, ioaddr + EL3_CMD); return; } static void vortex_tx_timeout(struct net_device *dev) { struct vortex_private *vp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = vp->ioaddr; printk(KERN_ERR "%s: transmit timed out, tx_status %2.2x status %4.4x.\n", - dev->name, inb(ioaddr + TxStatus), - inw(ioaddr + EL3_STATUS)); + dev->name, ioread8(ioaddr + TxStatus), + ioread16(ioaddr + EL3_STATUS)); EL3WINDOW(4); printk(KERN_ERR " diagnostics: net %04x media %04x dma %08x fifo %04x\n", - inw(ioaddr + Wn4_NetDiag), - inw(ioaddr + Wn4_Media), - inl(ioaddr + PktStatus), - inw(ioaddr + Wn4_FIFODiag)); + ioread16(ioaddr + Wn4_NetDiag), + ioread16(ioaddr + Wn4_Media), + ioread32(ioaddr + PktStatus), + ioread16(ioaddr + Wn4_FIFODiag)); /* Slight code bloat to be user friendly. */ - if ((inb(ioaddr + TxStatus) & 0x88) == 0x88) + if ((ioread8(ioaddr + TxStatus) & 0x88) == 0x88) printk(KERN_ERR "%s: Transmitter encountered 16 collisions --" " network cable problem?\n", dev->name); - if (inw(ioaddr + EL3_STATUS) & IntLatch) { + if (ioread16(ioaddr + EL3_STATUS) & IntLatch) { printk(KERN_ERR "%s: Interrupt posted but not delivered --" " IRQ blocked by another device?\n", dev->name); /* Bad idea here.. but we might as well handle a few events. */ @@ -2022,21 +2026,21 @@ static void vortex_tx_timeout(struct net_device *dev) vp->stats.tx_errors++; if (vp->full_bus_master_tx) { printk(KERN_DEBUG "%s: Resetting the Tx ring pointer.\n", dev->name); - if (vp->cur_tx - vp->dirty_tx > 0 && inl(ioaddr + DownListPtr) == 0) - outl(vp->tx_ring_dma + (vp->dirty_tx % TX_RING_SIZE) * sizeof(struct boom_tx_desc), + if (vp->cur_tx - vp->dirty_tx > 0 && ioread32(ioaddr + DownListPtr) == 0) + iowrite32(vp->tx_ring_dma + (vp->dirty_tx % TX_RING_SIZE) * sizeof(struct boom_tx_desc), ioaddr + DownListPtr); if (vp->cur_tx - vp->dirty_tx < TX_RING_SIZE) netif_wake_queue (dev); if (vp->drv_flags & IS_BOOMERANG) - outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); - outw(DownUnstall, ioaddr + EL3_CMD); + iowrite8(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); + iowrite16(DownUnstall, ioaddr + EL3_CMD); } else { vp->stats.tx_dropped++; netif_wake_queue(dev); } /* Issue Tx Enable */ - outw(TxEnable, ioaddr + EL3_CMD); + iowrite16(TxEnable, ioaddr + EL3_CMD); dev->trans_start = jiffies; /* Switch to register set 7 for normal use. */ @@ -2051,7 +2055,7 @@ static void vortex_error(struct net_device *dev, int status) { struct vortex_private *vp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = vp->ioaddr; int do_tx_reset = 0, reset_mask = 0; unsigned char tx_status = 0; @@ -2060,7 +2064,7 @@ vortex_error(struct net_device *dev, int status) } if (status & TxComplete) { /* Really "TxError" for us. */ - tx_status = inb(ioaddr + TxStatus); + tx_status = ioread8(ioaddr + TxStatus); /* Presumably a tx-timeout. We must merely re-enable. */ if (vortex_debug > 2 || (tx_status != 0x88 && vortex_debug > 0)) { @@ -2074,20 +2078,20 @@ vortex_error(struct net_device *dev, int status) } if (tx_status & 0x14) vp->stats.tx_fifo_errors++; if (tx_status & 0x38) vp->stats.tx_aborted_errors++; - outb(0, ioaddr + TxStatus); + iowrite8(0, ioaddr + TxStatus); if (tx_status & 0x30) { /* txJabber or txUnderrun */ do_tx_reset = 1; } else if ((tx_status & 0x08) && (vp->drv_flags & MAX_COLLISION_RESET)) { /* maxCollisions */ do_tx_reset = 1; reset_mask = 0x0108; /* Reset interface logic, but not download logic */ } else { /* Merely re-enable the transmitter. */ - outw(TxEnable, ioaddr + EL3_CMD); + iowrite16(TxEnable, ioaddr + EL3_CMD); } } if (status & RxEarly) { /* Rx early is unused. */ vortex_rx(dev); - outw(AckIntr | RxEarly, ioaddr + EL3_CMD); + iowrite16(AckIntr | RxEarly, ioaddr + EL3_CMD); } if (status & StatsFull) { /* Empty statistics. */ static int DoneDidThat; @@ -2097,29 +2101,29 @@ vortex_error(struct net_device *dev, int status) /* HACK: Disable statistics as an interrupt source. */ /* This occurs when we have the wrong media type! */ if (DoneDidThat == 0 && - inw(ioaddr + EL3_STATUS) & StatsFull) { + ioread16(ioaddr + EL3_STATUS) & StatsFull) { printk(KERN_WARNING "%s: Updating statistics failed, disabling " "stats as an interrupt source.\n", dev->name); EL3WINDOW(5); - outw(SetIntrEnb | (inw(ioaddr + 10) & ~StatsFull), ioaddr + EL3_CMD); + iowrite16(SetIntrEnb | (ioread16(ioaddr + 10) & ~StatsFull), ioaddr + EL3_CMD); vp->intr_enable &= ~StatsFull; EL3WINDOW(7); DoneDidThat++; } } if (status & IntReq) { /* Restore all interrupt sources. */ - outw(vp->status_enable, ioaddr + EL3_CMD); - outw(vp->intr_enable, ioaddr + EL3_CMD); + iowrite16(vp->status_enable, ioaddr + EL3_CMD); + iowrite16(vp->intr_enable, ioaddr + EL3_CMD); } if (status & HostError) { u16 fifo_diag; EL3WINDOW(4); - fifo_diag = inw(ioaddr + Wn4_FIFODiag); + fifo_diag = ioread16(ioaddr + Wn4_FIFODiag); printk(KERN_ERR "%s: Host error, FIFO diagnostic register %4.4x.\n", dev->name, fifo_diag); /* Adapter failure requires Tx/Rx reset and reinit. */ if (vp->full_bus_master_tx) { - int bus_status = inl(ioaddr + PktStatus); + int bus_status = ioread32(ioaddr + PktStatus); /* 0x80000000 PCI master abort. */ /* 0x40000000 PCI target abort. */ if (vortex_debug) @@ -2139,14 +2143,14 @@ vortex_error(struct net_device *dev, int status) set_rx_mode(dev); /* enable 802.1q VLAN tagged frames */ set_8021q_mode(dev, 1); - outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */ - outw(AckIntr | HostError, ioaddr + EL3_CMD); + iowrite16(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */ + iowrite16(AckIntr | HostError, ioaddr + EL3_CMD); } } if (do_tx_reset) { issue_and_wait(dev, TxReset|reset_mask); - outw(TxEnable, ioaddr + EL3_CMD); + iowrite16(TxEnable, ioaddr + EL3_CMD); if (!vp->full_bus_master_tx) netif_wake_queue(dev); } @@ -2156,29 +2160,29 @@ static int vortex_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct vortex_private *vp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = vp->ioaddr; /* Put out the doubleword header... */ - outl(skb->len, ioaddr + TX_FIFO); + iowrite32(skb->len, ioaddr + TX_FIFO); if (vp->bus_master) { /* Set the bus-master controller to transfer the packet. */ int len = (skb->len + 3) & ~3; - outl( vp->tx_skb_dma = pci_map_single(VORTEX_PCI(vp), skb->data, len, PCI_DMA_TODEVICE), + iowrite32( vp->tx_skb_dma = pci_map_single(VORTEX_PCI(vp), skb->data, len, PCI_DMA_TODEVICE), ioaddr + Wn7_MasterAddr); - outw(len, ioaddr + Wn7_MasterLen); + iowrite16(len, ioaddr + Wn7_MasterLen); vp->tx_skb = skb; - outw(StartDMADown, ioaddr + EL3_CMD); + iowrite16(StartDMADown, ioaddr + EL3_CMD); /* netif_wake_queue() will be called at the DMADone interrupt. */ } else { /* ... and the packet rounded to a doubleword. */ - outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); + iowrite32_rep(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); dev_kfree_skb (skb); - if (inw(ioaddr + TxFree) > 1536) { + if (ioread16(ioaddr + TxFree) > 1536) { netif_start_queue (dev); /* AKPM: redundant? */ } else { /* Interrupt us when the FIFO has room for max-sized packet. */ netif_stop_queue(dev); - outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD); + iowrite16(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD); } } @@ -2189,7 +2193,7 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev) int tx_status; int i = 32; - while (--i > 0 && (tx_status = inb(ioaddr + TxStatus)) > 0) { + while (--i > 0 && (tx_status = ioread8(ioaddr + TxStatus)) > 0) { if (tx_status & 0x3C) { /* A Tx-disabling error occurred. */ if (vortex_debug > 2) printk(KERN_DEBUG "%s: Tx error, status %2.2x.\n", @@ -2199,9 +2203,9 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev) if (tx_status & 0x30) { issue_and_wait(dev, TxReset); } - outw(TxEnable, ioaddr + EL3_CMD); + iowrite16(TxEnable, ioaddr + EL3_CMD); } - outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */ + iowrite8(0x00, ioaddr + TxStatus); /* Pop the status stack. */ } } return 0; @@ -2211,7 +2215,7 @@ static int boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct vortex_private *vp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = vp->ioaddr; /* Calculate the next Tx descriptor entry. */ int entry = vp->cur_tx % TX_RING_SIZE; struct boom_tx_desc *prev_entry = &vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE]; @@ -2275,8 +2279,8 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Wait for the stall to complete. */ issue_and_wait(dev, DownStall); prev_entry->next = cpu_to_le32(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc)); - if (inl(ioaddr + DownListPtr) == 0) { - outl(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc), ioaddr + DownListPtr); + if (ioread32(ioaddr + DownListPtr) == 0) { + iowrite32(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc), ioaddr + DownListPtr); vp->queued_packet++; } @@ -2291,7 +2295,7 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) prev_entry->status &= cpu_to_le32(~TxIntrUploaded); #endif } - outw(DownUnstall, ioaddr + EL3_CMD); + iowrite16(DownUnstall, ioaddr + EL3_CMD); spin_unlock_irqrestore(&vp->lock, flags); dev->trans_start = jiffies; return 0; @@ -2310,15 +2314,15 @@ vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = dev_id; struct vortex_private *vp = netdev_priv(dev); - long ioaddr; + void __iomem *ioaddr; int status; int work_done = max_interrupt_work; int handled = 0; - ioaddr = dev->base_addr; + ioaddr = vp->ioaddr; spin_lock(&vp->lock); - status = inw(ioaddr + EL3_STATUS); + status = ioread16(ioaddr + EL3_STATUS); if (vortex_debug > 6) printk("vortex_interrupt(). status=0x%4x\n", status); @@ -2337,7 +2341,7 @@ vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (vortex_debug > 4) printk(KERN_DEBUG "%s: interrupt, status %4.4x, latency %d ticks.\n", - dev->name, status, inb(ioaddr + Timer)); + dev->name, status, ioread8(ioaddr + Timer)); do { if (vortex_debug > 5) @@ -2350,16 +2354,16 @@ vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (vortex_debug > 5) printk(KERN_DEBUG " TX room bit was handled.\n"); /* There's room in the FIFO for a full-sized packet. */ - outw(AckIntr | TxAvailable, ioaddr + EL3_CMD); + iowrite16(AckIntr | TxAvailable, ioaddr + EL3_CMD); netif_wake_queue (dev); } if (status & DMADone) { - if (inw(ioaddr + Wn7_MasterStatus) & 0x1000) { - outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */ + if (ioread16(ioaddr + Wn7_MasterStatus) & 0x1000) { + iowrite16(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */ pci_unmap_single(VORTEX_PCI(vp), vp->tx_skb_dma, (vp->tx_skb->len + 3) & ~3, PCI_DMA_TODEVICE); dev_kfree_skb_irq(vp->tx_skb); /* Release the transferred buffer */ - if (inw(ioaddr + TxFree) > 1536) { + if (ioread16(ioaddr + TxFree) > 1536) { /* * AKPM: FIXME: I don't think we need this. If the queue was stopped due to * insufficient FIFO room, the TxAvailable test will succeed and call @@ -2367,7 +2371,7 @@ vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs) */ netif_wake_queue(dev); } else { /* Interrupt when FIFO has room for max-sized packet. */ - outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD); + iowrite16(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD); netif_stop_queue(dev); } } @@ -2385,17 +2389,17 @@ vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs) /* Disable all pending interrupts. */ do { vp->deferred |= status; - outw(SetStatusEnb | (~vp->deferred & vp->status_enable), + iowrite16(SetStatusEnb | (~vp->deferred & vp->status_enable), ioaddr + EL3_CMD); - outw(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD); - } while ((status = inw(ioaddr + EL3_CMD)) & IntLatch); + iowrite16(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD); + } while ((status = ioread16(ioaddr + EL3_CMD)) & IntLatch); /* The timer will reenable interrupts. */ mod_timer(&vp->timer, jiffies + 1*HZ); break; } /* Acknowledge the IRQ. */ - outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); - } while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete)); + iowrite16(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); + } while ((status = ioread16(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete)); if (vortex_debug > 4) printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n", @@ -2415,11 +2419,11 @@ boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = dev_id; struct vortex_private *vp = netdev_priv(dev); - long ioaddr; + void __iomem *ioaddr; int status; int work_done = max_interrupt_work; - ioaddr = dev->base_addr; + ioaddr = vp->ioaddr; /* * It seems dopey to put the spinlock this early, but we could race against vortex_tx_timeout @@ -2427,7 +2431,7 @@ boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs) */ spin_lock(&vp->lock); - status = inw(ioaddr + EL3_STATUS); + status = ioread16(ioaddr + EL3_STATUS); if (vortex_debug > 6) printk(KERN_DEBUG "boomerang_interrupt. status=0x%4x\n", status); @@ -2448,13 +2452,13 @@ boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (vortex_debug > 4) printk(KERN_DEBUG "%s: interrupt, status %4.4x, latency %d ticks.\n", - dev->name, status, inb(ioaddr + Timer)); + dev->name, status, ioread8(ioaddr + Timer)); do { if (vortex_debug > 5) printk(KERN_DEBUG "%s: In interrupt loop, status %4.4x.\n", dev->name, status); if (status & UpComplete) { - outw(AckIntr | UpComplete, ioaddr + EL3_CMD); + iowrite16(AckIntr | UpComplete, ioaddr + EL3_CMD); if (vortex_debug > 5) printk(KERN_DEBUG "boomerang_interrupt->boomerang_rx\n"); boomerang_rx(dev); @@ -2463,11 +2467,11 @@ boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (status & DownComplete) { unsigned int dirty_tx = vp->dirty_tx; - outw(AckIntr | DownComplete, ioaddr + EL3_CMD); + iowrite16(AckIntr | DownComplete, ioaddr + EL3_CMD); while (vp->cur_tx - dirty_tx > 0) { int entry = dirty_tx % TX_RING_SIZE; #if 1 /* AKPM: the latter is faster, but cyclone-only */ - if (inl(ioaddr + DownListPtr) == + if (ioread32(ioaddr + DownListPtr) == vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc)) break; /* It still hasn't been processed. */ #else @@ -2514,20 +2518,20 @@ boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs) /* Disable all pending interrupts. */ do { vp->deferred |= status; - outw(SetStatusEnb | (~vp->deferred & vp->status_enable), + iowrite16(SetStatusEnb | (~vp->deferred & vp->status_enable), ioaddr + EL3_CMD); - outw(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD); - } while ((status = inw(ioaddr + EL3_CMD)) & IntLatch); + iowrite16(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD); + } while ((status = ioread16(ioaddr + EL3_CMD)) & IntLatch); /* The timer will reenable interrupts. */ mod_timer(&vp->timer, jiffies + 1*HZ); break; } /* Acknowledge the IRQ. */ - outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); + iowrite16(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); if (vp->cb_fn_base) /* The PCMCIA people are idiots. */ - writel(0x8000, vp->cb_fn_base + 4); + iowrite32(0x8000, vp->cb_fn_base + 4); - } while ((status = inw(ioaddr + EL3_STATUS)) & IntLatch); + } while ((status = ioread16(ioaddr + EL3_STATUS)) & IntLatch); if (vortex_debug > 4) printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n", @@ -2540,16 +2544,16 @@ handler_exit: static int vortex_rx(struct net_device *dev) { struct vortex_private *vp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = vp->ioaddr; int i; short rx_status; if (vortex_debug > 5) printk(KERN_DEBUG "vortex_rx(): status %4.4x, rx_status %4.4x.\n", - inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus)); - while ((rx_status = inw(ioaddr + RxStatus)) > 0) { + ioread16(ioaddr+EL3_STATUS), ioread16(ioaddr+RxStatus)); + while ((rx_status = ioread16(ioaddr + RxStatus)) > 0) { if (rx_status & 0x4000) { /* Error, update stats. */ - unsigned char rx_error = inb(ioaddr + RxErrors); + unsigned char rx_error = ioread8(ioaddr + RxErrors); if (vortex_debug > 2) printk(KERN_DEBUG " Rx error: status %2.2x.\n", rx_error); vp->stats.rx_errors++; @@ -2572,27 +2576,28 @@ static int vortex_rx(struct net_device *dev) skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ /* 'skb_put()' points to the start of sk_buff data area. */ if (vp->bus_master && - ! (inw(ioaddr + Wn7_MasterStatus) & 0x8000)) { + ! (ioread16(ioaddr + Wn7_MasterStatus) & 0x8000)) { dma_addr_t dma = pci_map_single(VORTEX_PCI(vp), skb_put(skb, pkt_len), pkt_len, PCI_DMA_FROMDEVICE); - outl(dma, ioaddr + Wn7_MasterAddr); - outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen); - outw(StartDMAUp, ioaddr + EL3_CMD); - while (inw(ioaddr + Wn7_MasterStatus) & 0x8000) + iowrite32(dma, ioaddr + Wn7_MasterAddr); + iowrite16((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen); + iowrite16(StartDMAUp, ioaddr + EL3_CMD); + while (ioread16(ioaddr + Wn7_MasterStatus) & 0x8000) ; pci_unmap_single(VORTEX_PCI(vp), dma, pkt_len, PCI_DMA_FROMDEVICE); } else { - insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len), - (pkt_len + 3) >> 2); + ioread32_rep(ioaddr + RX_FIFO, + skb_put(skb, pkt_len), + (pkt_len + 3) >> 2); } - outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */ + iowrite16(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */ skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); dev->last_rx = jiffies; vp->stats.rx_packets++; /* Wait a limited time to go to next packet. */ for (i = 200; i >= 0; i--) - if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress)) + if ( ! (ioread16(ioaddr + EL3_STATUS) & CmdInProgress)) break; continue; } else if (vortex_debug > 0) @@ -2611,12 +2616,12 @@ boomerang_rx(struct net_device *dev) { struct vortex_private *vp = netdev_priv(dev); int entry = vp->cur_rx % RX_RING_SIZE; - long ioaddr = dev->base_addr; + void __iomem *ioaddr = vp->ioaddr; int rx_status; int rx_work_limit = vp->dirty_rx + RX_RING_SIZE - vp->cur_rx; if (vortex_debug > 5) - printk(KERN_DEBUG "boomerang_rx(): status %4.4x\n", inw(ioaddr+EL3_STATUS)); + printk(KERN_DEBUG "boomerang_rx(): status %4.4x\n", ioread16(ioaddr+EL3_STATUS)); while ((rx_status = le32_to_cpu(vp->rx_ring[entry].status)) & RxDComplete){ if (--rx_work_limit < 0) @@ -2699,7 +2704,7 @@ boomerang_rx(struct net_device *dev) vp->rx_skbuff[entry] = skb; } vp->rx_ring[entry].status = 0; /* Clear complete bit. */ - outw(UpUnstall, ioaddr + EL3_CMD); + iowrite16(UpUnstall, ioaddr + EL3_CMD); } return 0; } @@ -2728,7 +2733,7 @@ static void vortex_down(struct net_device *dev, int final_down) { struct vortex_private *vp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = vp->ioaddr; netif_stop_queue (dev); @@ -2736,26 +2741,26 @@ vortex_down(struct net_device *dev, int final_down) del_timer_sync(&vp->timer); /* Turn off statistics ASAP. We update vp->stats below. */ - outw(StatsDisable, ioaddr + EL3_CMD); + iowrite16(StatsDisable, ioaddr + EL3_CMD); /* Disable the receiver and transmitter. */ - outw(RxDisable, ioaddr + EL3_CMD); - outw(TxDisable, ioaddr + EL3_CMD); + iowrite16(RxDisable, ioaddr + EL3_CMD); + iowrite16(TxDisable, ioaddr + EL3_CMD); /* Disable receiving 802.1q tagged frames */ set_8021q_mode(dev, 0); if (dev->if_port == XCVR_10base2) /* Turn off thinnet power. Green! */ - outw(StopCoax, ioaddr + EL3_CMD); + iowrite16(StopCoax, ioaddr + EL3_CMD); - outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD); + iowrite16(SetIntrEnb | 0x0000, ioaddr + EL3_CMD); update_stats(ioaddr, dev); if (vp->full_bus_master_rx) - outl(0, ioaddr + UpListPtr); + iowrite32(0, ioaddr + UpListPtr); if (vp->full_bus_master_tx) - outl(0, ioaddr + DownListPtr); + iowrite32(0, ioaddr + DownListPtr); if (final_down && VORTEX_PCI(vp)) { vp->pm_state_valid = 1; @@ -2768,7 +2773,7 @@ static int vortex_close(struct net_device *dev) { struct vortex_private *vp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = vp->ioaddr; int i; if (netif_device_present(dev)) @@ -2776,7 +2781,7 @@ vortex_close(struct net_device *dev) if (vortex_debug > 1) { printk(KERN_DEBUG"%s: vortex_close() status %4.4x, Tx status %2.2x.\n", - dev->name, inw(ioaddr + EL3_STATUS), inb(ioaddr + TxStatus)); + dev->name, ioread16(ioaddr + EL3_STATUS), ioread8(ioaddr + TxStatus)); printk(KERN_DEBUG "%s: vortex close stats: rx_nocopy %d rx_copy %d" " tx_queued %d Rx pre-checksummed %d.\n", dev->name, vp->rx_nocopy, vp->rx_copy, vp->queued_packet, vp->rx_csumhits); @@ -2830,18 +2835,18 @@ dump_tx_ring(struct net_device *dev) { if (vortex_debug > 0) { struct vortex_private *vp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = vp->ioaddr; if (vp->full_bus_master_tx) { int i; - int stalled = inl(ioaddr + PktStatus) & 0x04; /* Possible racy. But it's only debug stuff */ + int stalled = ioread32(ioaddr + PktStatus) & 0x04; /* Possible racy. But it's only debug stuff */ printk(KERN_ERR " Flags; bus-master %d, dirty %d(%d) current %d(%d)\n", vp->full_bus_master_tx, vp->dirty_tx, vp->dirty_tx % TX_RING_SIZE, vp->cur_tx, vp->cur_tx % TX_RING_SIZE); printk(KERN_ERR " Transmit list %8.8x vs. %p.\n", - inl(ioaddr + DownListPtr), + ioread32(ioaddr + DownListPtr), &vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]); issue_and_wait(dev, DownStall); for (i = 0; i < TX_RING_SIZE; i++) { @@ -2855,7 +2860,7 @@ dump_tx_ring(struct net_device *dev) le32_to_cpu(vp->tx_ring[i].status)); } if (!stalled) - outw(DownUnstall, ioaddr + EL3_CMD); + iowrite16(DownUnstall, ioaddr + EL3_CMD); } } } @@ -2863,11 +2868,12 @@ dump_tx_ring(struct net_device *dev) static struct net_device_stats *vortex_get_stats(struct net_device *dev) { struct vortex_private *vp = netdev_priv(dev); + void __iomem *ioaddr = vp->ioaddr; unsigned long flags; if (netif_device_present(dev)) { /* AKPM: Used to be netif_running */ spin_lock_irqsave (&vp->lock, flags); - update_stats(dev->base_addr, dev); + update_stats(ioaddr, dev); spin_unlock_irqrestore (&vp->lock, flags); } return &vp->stats; @@ -2880,37 +2886,37 @@ static struct net_device_stats *vortex_get_stats(struct net_device *dev) table. This is done by checking that the ASM (!) code generated uses atomic updates with '+='. */ -static void update_stats(long ioaddr, struct net_device *dev) +static void update_stats(void __iomem *ioaddr, struct net_device *dev) { struct vortex_private *vp = netdev_priv(dev); - int old_window = inw(ioaddr + EL3_CMD); + int old_window = ioread16(ioaddr + EL3_CMD); if (old_window == 0xffff) /* Chip suspended or ejected. */ return; /* Unlike the 3c5x9 we need not turn off stats updates while reading. */ /* Switch to the stats window, and read everything. */ EL3WINDOW(6); - vp->stats.tx_carrier_errors += inb(ioaddr + 0); - vp->stats.tx_heartbeat_errors += inb(ioaddr + 1); - vp->stats.collisions += inb(ioaddr + 3); - vp->stats.tx_window_errors += inb(ioaddr + 4); - vp->stats.rx_fifo_errors += inb(ioaddr + 5); - vp->stats.tx_packets += inb(ioaddr + 6); - vp->stats.tx_packets += (inb(ioaddr + 9)&0x30) << 4; - /* Rx packets */ inb(ioaddr + 7); /* Must read to clear */ + vp->stats.tx_carrier_errors += ioread8(ioaddr + 0); + vp->stats.tx_heartbeat_errors += ioread8(ioaddr + 1); + vp->stats.collisions += ioread8(ioaddr + 3); + vp->stats.tx_window_errors += ioread8(ioaddr + 4); + vp->stats.rx_fifo_errors += ioread8(ioaddr + 5); + vp->stats.tx_packets += ioread8(ioaddr + 6); + vp->stats.tx_packets += (ioread8(ioaddr + 9)&0x30) << 4; + /* Rx packets */ ioread8(ioaddr + 7); /* Must read to clear */ /* Don't bother with register 9, an extension of registers 6&7. If we do use the 6&7 values the atomic update assumption above is invalid. */ - vp->stats.rx_bytes += inw(ioaddr + 10); - vp->stats.tx_bytes += inw(ioaddr + 12); + vp->stats.rx_bytes += ioread16(ioaddr + 10); + vp->stats.tx_bytes += ioread16(ioaddr + 12); /* Extra stats for get_ethtool_stats() */ - vp->xstats.tx_multiple_collisions += inb(ioaddr + 2); - vp->xstats.tx_deferred += inb(ioaddr + 8); + vp->xstats.tx_multiple_collisions += ioread8(ioaddr + 2); + vp->xstats.tx_deferred += ioread8(ioaddr + 8); EL3WINDOW(4); - vp->xstats.rx_bad_ssd += inb(ioaddr + 12); + vp->xstats.rx_bad_ssd += ioread8(ioaddr + 12); { - u8 up = inb(ioaddr + 13); + u8 up = ioread8(ioaddr + 13); vp->stats.rx_bytes += (up & 0x0f) << 16; vp->stats.tx_bytes += (up & 0xf0) << 12; } @@ -2922,7 +2928,7 @@ static void update_stats(long ioaddr, struct net_device *dev) static int vortex_nway_reset(struct net_device *dev) { struct vortex_private *vp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = vp->ioaddr; unsigned long flags; int rc; @@ -2936,7 +2942,7 @@ static int vortex_nway_reset(struct net_device *dev) static u32 vortex_get_link(struct net_device *dev) { struct vortex_private *vp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = vp->ioaddr; unsigned long flags; int rc; @@ -2950,7 +2956,7 @@ static u32 vortex_get_link(struct net_device *dev) static int vortex_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct vortex_private *vp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = vp->ioaddr; unsigned long flags; int rc; @@ -2964,7 +2970,7 @@ static int vortex_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) static int vortex_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct vortex_private *vp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = vp->ioaddr; unsigned long flags; int rc; @@ -2994,10 +3000,11 @@ static void vortex_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) { struct vortex_private *vp = netdev_priv(dev); + void __iomem *ioaddr = vp->ioaddr; unsigned long flags; spin_lock_irqsave(&vp->lock, flags); - update_stats(dev->base_addr, dev); + update_stats(ioaddr, dev); spin_unlock_irqrestore(&vp->lock, flags); data[0] = vp->xstats.tx_deferred; @@ -3057,7 +3064,7 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { int err; struct vortex_private *vp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = vp->ioaddr; unsigned long flags; int state = 0; @@ -3085,7 +3092,8 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) the chip has a very clean way to set the mode, unlike many others. */ static void set_rx_mode(struct net_device *dev) { - long ioaddr = dev->base_addr; + struct vortex_private *vp = netdev_priv(dev); + void __iomem *ioaddr = vp->ioaddr; int new_mode; if (dev->flags & IFF_PROMISC) { @@ -3097,7 +3105,7 @@ static void set_rx_mode(struct net_device *dev) } else new_mode = SetRxFilter | RxStation | RxBroadcast; - outw(new_mode, ioaddr + EL3_CMD); + iowrite16(new_mode, ioaddr + EL3_CMD); } #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) @@ -3111,8 +3119,8 @@ static void set_rx_mode(struct net_device *dev) static void set_8021q_mode(struct net_device *dev, int enable) { struct vortex_private *vp = netdev_priv(dev); - long ioaddr = dev->base_addr; - int old_window = inw(ioaddr + EL3_CMD); + void __iomem *ioaddr = vp->ioaddr; + int old_window = ioread16(ioaddr + EL3_CMD); int mac_ctrl; if ((vp->drv_flags&IS_CYCLONE) || (vp->drv_flags&IS_TORNADO)) { @@ -3124,24 +3132,24 @@ static void set_8021q_mode(struct net_device *dev, int enable) max_pkt_size += 4; /* 802.1Q VLAN tag */ EL3WINDOW(3); - outw(max_pkt_size, ioaddr+Wn3_MaxPktSize); + iowrite16(max_pkt_size, ioaddr+Wn3_MaxPktSize); /* set VlanEtherType to let the hardware checksumming treat tagged frames correctly */ EL3WINDOW(7); - outw(VLAN_ETHER_TYPE, ioaddr+Wn7_VlanEtherType); + iowrite16(VLAN_ETHER_TYPE, ioaddr+Wn7_VlanEtherType); } else { /* on older cards we have to enable large frames */ vp->large_frames = dev->mtu > 1500 || enable; EL3WINDOW(3); - mac_ctrl = inw(ioaddr+Wn3_MAC_Ctrl); + mac_ctrl = ioread16(ioaddr+Wn3_MAC_Ctrl); if (vp->large_frames) mac_ctrl |= 0x40; else mac_ctrl &= ~0x40; - outw(mac_ctrl, ioaddr+Wn3_MAC_Ctrl); + iowrite16(mac_ctrl, ioaddr+Wn3_MAC_Ctrl); } EL3WINDOW(old_window); @@ -3163,7 +3171,7 @@ static void set_8021q_mode(struct net_device *dev, int enable) /* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually met by back-to-back PCI I/O cycles, but we insert a delay to avoid "overclocking" issues. */ -#define mdio_delay() inl(mdio_addr) +#define mdio_delay() ioread32(mdio_addr) #define MDIO_SHIFT_CLK 0x01 #define MDIO_DIR_WRITE 0x04 @@ -3174,15 +3182,15 @@ static void set_8021q_mode(struct net_device *dev, int enable) /* Generate the preamble required for initial synchronization and a few older transceivers. */ -static void mdio_sync(long ioaddr, int bits) +static void mdio_sync(void __iomem *ioaddr, int bits) { - long mdio_addr = ioaddr + Wn4_PhysicalMgmt; + void __iomem *mdio_addr = ioaddr + Wn4_PhysicalMgmt; /* Establish sync by sending at least 32 logic ones. */ while (-- bits >= 0) { - outw(MDIO_DATA_WRITE1, mdio_addr); + iowrite16(MDIO_DATA_WRITE1, mdio_addr); mdio_delay(); - outw(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); + iowrite16(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); mdio_delay(); } } @@ -3190,10 +3198,11 @@ static void mdio_sync(long ioaddr, int bits) static int mdio_read(struct net_device *dev, int phy_id, int location) { int i; - long ioaddr = dev->base_addr; + struct vortex_private *vp = netdev_priv(dev); + void __iomem *ioaddr = vp->ioaddr; int read_cmd = (0xf6 << 10) | (phy_id << 5) | location; unsigned int retval = 0; - long mdio_addr = ioaddr + Wn4_PhysicalMgmt; + void __iomem *mdio_addr = ioaddr + Wn4_PhysicalMgmt; if (mii_preamble_required) mdio_sync(ioaddr, 32); @@ -3201,17 +3210,17 @@ static int mdio_read(struct net_device *dev, int phy_id, int location) /* Shift the read command bits out. */ for (i = 14; i >= 0; i--) { int dataval = (read_cmd&(1< 0; i--) { - outw(MDIO_ENB_IN, mdio_addr); + iowrite16(MDIO_ENB_IN, mdio_addr); mdio_delay(); - retval = (retval << 1) | ((inw(mdio_addr) & MDIO_DATA_READ) ? 1 : 0); - outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); + retval = (retval << 1) | ((ioread16(mdio_addr) & MDIO_DATA_READ) ? 1 : 0); + iowrite16(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); mdio_delay(); } return retval & 0x20000 ? 0xffff : retval>>1 & 0xffff; @@ -3219,9 +3228,10 @@ static int mdio_read(struct net_device *dev, int phy_id, int location) static void mdio_write(struct net_device *dev, int phy_id, int location, int value) { - long ioaddr = dev->base_addr; + struct vortex_private *vp = netdev_priv(dev); + void __iomem *ioaddr = vp->ioaddr; int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value; - long mdio_addr = ioaddr + Wn4_PhysicalMgmt; + void __iomem *mdio_addr = ioaddr + Wn4_PhysicalMgmt; int i; if (mii_preamble_required) @@ -3230,16 +3240,16 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val /* Shift the command bits out. */ for (i = 31; i >= 0; i--) { int dataval = (write_cmd&(1<= 0; i--) { - outw(MDIO_ENB_IN, mdio_addr); + iowrite16(MDIO_ENB_IN, mdio_addr); mdio_delay(); - outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); + iowrite16(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); mdio_delay(); } return; @@ -3250,15 +3260,15 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val static void acpi_set_WOL(struct net_device *dev) { struct vortex_private *vp = netdev_priv(dev); - long ioaddr = dev->base_addr; + void __iomem *ioaddr = vp->ioaddr; if (vp->enable_wol) { /* Power up on: 1==Downloaded Filter, 2==Magic Packets, 4==Link Status. */ EL3WINDOW(7); - outw(2, ioaddr + 0x0c); + iowrite16(2, ioaddr + 0x0c); /* The RxFilter must accept the WOL frames. */ - outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD); - outw(RxEnable, ioaddr + EL3_CMD); + iowrite16(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD); + iowrite16(RxEnable, ioaddr + EL3_CMD); pci_enable_wake(VORTEX_PCI(vp), 0, 1); @@ -3280,10 +3290,9 @@ static void __devexit vortex_remove_one (struct pci_dev *pdev) vp = netdev_priv(dev); - /* AKPM: FIXME: we should have - * if (vp->cb_fn_base) iounmap(vp->cb_fn_base); - * here - */ + if (vp->cb_fn_base) + pci_iounmap(VORTEX_PCI(vp), vp->cb_fn_base); + unregister_netdev(dev); if (VORTEX_PCI(vp)) { @@ -3293,8 +3302,10 @@ static void __devexit vortex_remove_one (struct pci_dev *pdev) pci_disable_device(VORTEX_PCI(vp)); } /* Should really use issue_and_wait() here */ - outw(TotalReset | ((vp->drv_flags & EEPROM_RESET) ? 0x04 : 0x14), - dev->base_addr + EL3_CMD); + iowrite16(TotalReset | ((vp->drv_flags & EEPROM_RESET) ? 0x04 : 0x14), + vp->ioaddr + EL3_CMD); + + pci_iounmap(VORTEX_PCI(vp), vp->ioaddr); pci_free_consistent(pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE @@ -3342,7 +3353,7 @@ static int __init vortex_init (void) static void __exit vortex_eisa_cleanup (void) { struct vortex_private *vp; - long ioaddr; + void __iomem *ioaddr; #ifdef CONFIG_EISA /* Take care of the EISA devices */ @@ -3351,11 +3362,13 @@ static void __exit vortex_eisa_cleanup (void) if (compaq_net_device) { vp = compaq_net_device->priv; - ioaddr = compaq_net_device->base_addr; + ioaddr = ioport_map(compaq_net_device->base_addr, + VORTEX_TOTAL_SIZE); unregister_netdev (compaq_net_device); - outw (TotalReset, ioaddr + EL3_CMD); - release_region (ioaddr, VORTEX_TOTAL_SIZE); + iowrite16 (TotalReset, ioaddr + EL3_CMD); + release_region(compaq_net_device->base_addr, + VORTEX_TOTAL_SIZE); free_netdev (compaq_net_device); } -- cgit v1.2.3 From 106427e65d2b6f3a519ab5d14a3586007e7e0f20 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Mon, 7 Nov 2005 00:58:03 -0800 Subject: [PATCH] 3c59x: cleanup of mdio_read routines to use MII_* macros Clean up mdio_read routines in 3c59x.c to use the MII_* macros defined in include/linux/mii.h Signed-off-by: Neil Horman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/3c59x.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 2bad41bebd1..88ce4c43fd4 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1457,7 +1457,7 @@ static int __devinit vortex_probe1(struct device *gendev, if (vp->drv_flags & EXTRA_PREAMBLE) mii_preamble_required++; mdio_sync(ioaddr, 32); - mdio_read(dev, 24, 1); + mdio_read(dev, 24, MII_BMSR); for (phy = 0; phy < 32 && phy_idx < 1; phy++) { int mii_status, phyx; @@ -1471,7 +1471,7 @@ static int __devinit vortex_probe1(struct device *gendev, phyx = phy - 1; else phyx = phy; - mii_status = mdio_read(dev, phyx, 1); + mii_status = mdio_read(dev, phyx, MII_BMSR); if (mii_status && mii_status != 0xffff) { vp->phys[phy_idx++] = phyx; if (print_info) { @@ -1487,7 +1487,7 @@ static int __devinit vortex_probe1(struct device *gendev, printk(KERN_WARNING" ***WARNING*** No MII transceivers found!\n"); vp->phys[0] = 24; } else { - vp->advertising = mdio_read(dev, vp->phys[0], 4); + vp->advertising = mdio_read(dev, vp->phys[0], MII_ADVERTISE); if (vp->full_duplex) { /* Only advertise the FD media types. */ vp->advertising &= ~0x02A0; @@ -1661,8 +1661,8 @@ vortex_up(struct net_device *dev) int mii_reg1, mii_reg5; EL3WINDOW(4); /* Read BMSR (reg1) only to clear old status. */ - mii_reg1 = mdio_read(dev, vp->phys[0], 1); - mii_reg5 = mdio_read(dev, vp->phys[0], 5); + mii_reg1 = mdio_read(dev, vp->phys[0], MII_BMSR); + mii_reg5 = mdio_read(dev, vp->phys[0], MII_LPA); if (mii_reg5 == 0xffff || mii_reg5 == 0x0000) { netif_carrier_off(dev); /* No MII device or no link partner report */ } else { @@ -1892,14 +1892,14 @@ vortex_timer(unsigned long data) case XCVR_MII: case XCVR_NWAY: { spin_lock_bh(&vp->lock); - mii_status = mdio_read(dev, vp->phys[0], 1); - mii_status = mdio_read(dev, vp->phys[0], 1); + mii_status = mdio_read(dev, vp->phys[0], MII_BMSR); + mii_status = mdio_read(dev, vp->phys[0], MII_BMSR); ok = 1; if (vortex_debug > 2) printk(KERN_DEBUG "%s: MII transceiver has status %4.4x.\n", dev->name, mii_status); if (mii_status & BMSR_LSTATUS) { - int mii_reg5 = mdio_read(dev, vp->phys[0], 5); + int mii_reg5 = mdio_read(dev, vp->phys[0], MII_LPA); if (! vp->force_fd && mii_reg5 != 0xffff) { int duplex; -- cgit v1.2.3 From d9e46de34e4212f472684b1561ba323aac54ea25 Mon Sep 17 00:00:00 2001 From: Tommy Christensen Date: Mon, 7 Nov 2005 00:58:04 -0800 Subject: [PATCH] 3c59x: avoid blindly reading link status twice In order to spare some I/O operations, be more intelligent about when to read from the PHY. Pointed out by Bogdan Costescu. Signed-off-by: Tommy S. Christensen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/3c59x.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 88ce4c43fd4..e1f773d07ed 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1893,7 +1893,10 @@ vortex_timer(unsigned long data) { spin_lock_bh(&vp->lock); mii_status = mdio_read(dev, vp->phys[0], MII_BMSR); - mii_status = mdio_read(dev, vp->phys[0], MII_BMSR); + if (!(mii_status & BMSR_LSTATUS)) { + /* Re-read to get actual link status */ + mii_status = mdio_read(dev, vp->phys[0], MII_BMSR); + } ok = 1; if (vortex_debug > 2) printk(KERN_DEBUG "%s: MII transceiver has status %4.4x.\n", -- cgit v1.2.3 From 32fb5f06dbb6ca007f7886eb210b7b15545e2e15 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 7 Nov 2005 00:58:05 -0800 Subject: [PATCH] 3c59x: bounds checking for hw_checksums Add bounds checking to usage of hw_checksums module parameter array. Signed-off-by: John W. Linville Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/3c59x.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index e1f773d07ed..78f90eb02b9 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1513,9 +1513,10 @@ static int __devinit vortex_probe1(struct device *gendev, dev->hard_start_xmit = boomerang_start_xmit; /* Actually, it still should work with iommu. */ dev->features |= NETIF_F_SG; - if (((hw_checksums[card_idx] == -1) && (vp->drv_flags & HAS_HWCKSM)) || - (hw_checksums[card_idx] == 1)) { - dev->features |= NETIF_F_IP_CSUM; + if (card_idx < MAX_UNITS && + ((hw_checksums[card_idx] == -1 && (vp->drv_flags & HAS_HWCKSM)) || + hw_checksums[card_idx] == 1)) { + dev->features |= NETIF_F_IP_CSUM; } } else { dev->hard_start_xmit = vortex_start_xmit; @@ -2791,10 +2792,11 @@ vortex_close(struct net_device *dev) } #if DO_ZEROCOPY - if ( vp->rx_csumhits && - ((vp->drv_flags & HAS_HWCKSM) == 0) && - (hw_checksums[vp->card_idx] == -1)) { - printk(KERN_WARNING "%s supports hardware checksums, and we're not using them!\n", dev->name); + if (vp->rx_csumhits && + (vp->drv_flags & HAS_HWCKSM) == 0 && + (vp->card_idx >= MAX_UNITS || hw_checksums[vp->card_idx] == -1)) { + printk(KERN_WARNING "%s supports hardware checksums, and we're " + "not using them!\n", dev->name); } #endif -- cgit v1.2.3 From 9954ab7fd52afedf0977893352bb3ddb07120214 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 7 Nov 2005 00:58:06 -0800 Subject: [PATCH] 3c59x: cleanup init of module parameter arrays Beautify the array initilizations for the module parameters. Signed-off-by: John W. Linville Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/3c59x.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 78f90eb02b9..0139d4b061e 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -903,11 +903,11 @@ static void set_8021q_mode(struct net_device *dev, int enable); /* This driver uses 'options' to pass the media type, full-duplex flag, etc. */ /* Option count limit only -- unlimited interfaces are supported. */ #define MAX_UNITS 8 -static int options[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1,}; -static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int hw_checksums[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int flow_ctrl[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int enable_wol[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; +static int options[MAX_UNITS] = { [0 ... MAX_UNITS-1] = -1 }; +static int full_duplex[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 }; +static int hw_checksums[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 }; +static int flow_ctrl[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 }; +static int enable_wol[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 }; static int global_options = -1; static int global_full_duplex = -1; static int global_enable_wol = -1; -- cgit v1.2.3 From 46e5e4a897ade416beb0bd8447fb0ff0bc1bb329 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 7 Nov 2005 00:58:06 -0800 Subject: [PATCH] 3c59x: fix some grammar in module parameter descriptions Correct several (apparently cut & paste) grammatical typos in module parameter descriptions. They seem to have originated as copies of the description for "global_options". Signed-off-by: John W. Linville Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/3c59x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 0139d4b061e..7dcc5545557 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -939,11 +939,11 @@ MODULE_PARM_DESC(debug, "3c59x debug level (0-6)"); MODULE_PARM_DESC(options, "3c59x: Bits 0-3: media type, bit 4: bus mastering, bit 9: full duplex"); MODULE_PARM_DESC(global_options, "3c59x: same as options, but applies to all NICs if options is unset"); MODULE_PARM_DESC(full_duplex, "3c59x full duplex setting(s) (1)"); -MODULE_PARM_DESC(global_full_duplex, "3c59x: same as full_duplex, but applies to all NICs if options is unset"); +MODULE_PARM_DESC(global_full_duplex, "3c59x: same as full_duplex, but applies to all NICs if full_duplex is unset"); MODULE_PARM_DESC(hw_checksums, "3c59x Hardware checksum checking by adapter(s) (0-1)"); MODULE_PARM_DESC(flow_ctrl, "3c59x 802.3x flow control usage (PAUSE only) (0-1)"); MODULE_PARM_DESC(enable_wol, "3c59x: Turn on Wake-on-LAN for adapter(s) (0-1)"); -MODULE_PARM_DESC(global_enable_wol, "3c59x: same as enable_wol, but applies to all NICs if options is unset"); +MODULE_PARM_DESC(global_enable_wol, "3c59x: same as enable_wol, but applies to all NICs if enable_wol is unset"); MODULE_PARM_DESC(rx_copybreak, "3c59x copy breakpoint for copy-only-tiny-frames"); MODULE_PARM_DESC(max_interrupt_work, "3c59x maximum events handled per interrupt"); MODULE_PARM_DESC(compaq_ioaddr, "3c59x PCI I/O base address (Compaq BIOS problem workaround)"); -- cgit v1.2.3 From bb531fc071f9017b4809c806f71e6a7f49b67289 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 7 Nov 2005 00:58:07 -0800 Subject: [PATCH] 3c59x: support ETHTOOL_GPERMADDR Add support for ETHTOOL_GPERMADDR to 3c59x. Signed-off-by: John W. Linville Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/3c59x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 7dcc5545557..be4f962d27b 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1341,6 +1341,7 @@ static int __devinit vortex_probe1(struct device *gendev, printk(" ***INVALID CHECKSUM %4.4x*** ", checksum); for (i = 0; i < 3; i++) ((u16 *)dev->dev_addr)[i] = htons(eeprom[i + 10]); + memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); if (print_info) { for (i = 0; i < 6; i++) printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]); @@ -3059,6 +3060,7 @@ static struct ethtool_ops vortex_ethtool_ops = { .set_settings = vortex_set_settings, .get_link = vortex_get_link, .nway_reset = vortex_nway_reset, + .get_perm_addr = ethtool_op_get_perm_addr, }; #ifdef CONFIG_PCI -- cgit v1.2.3 From 35b306743d17cdd31357e5de9ce6c549e5d6756e Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 7 Nov 2005 00:58:08 -0800 Subject: [PATCH] 3c59x: correct rx_dropped counting Only increment rx_dropped in case of lack of resources (i.e. not for frames with errors). Signed-off-by: John W. Linville Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/3c59x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index be4f962d27b..413b82c5994 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -2608,8 +2608,8 @@ static int vortex_rx(struct net_device *dev) } else if (vortex_debug > 0) printk(KERN_NOTICE "%s: No memory to allocate a sk_buff of " "size %d.\n", dev->name, pkt_len); + vp->stats.rx_dropped++; } - vp->stats.rx_dropped++; issue_and_wait(dev, RxDiscard); } -- cgit v1.2.3 From 900fd17dd01d2c99dfd1ec0b53a860894a2673ee Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 7 Nov 2005 00:58:08 -0800 Subject: [PATCH] 3c59x: enable use of memory-mapped PCI I/O Add capability for 3c59x driver to use memory-mapped PCI I/O resources. This may improve performance for those devices so equipped. This will be the default behaviour for IS_CYCLONE and IS_TORNADO devices. Additionally, it can be enabled/disabled individually for up to MAX_UNITS number of devices via the use_mmio module option or for all units via the global_use_mmio option. The use_mmio option overrides the global_use_mmio option for those devices specified. Signed-off-by: John W. Linville Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/3c59x.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 413b82c5994..c1ee8efc9d5 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -908,9 +908,11 @@ static int full_duplex[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 }; static int hw_checksums[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 }; static int flow_ctrl[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 }; static int enable_wol[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 }; +static int use_mmio[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 }; static int global_options = -1; static int global_full_duplex = -1; static int global_enable_wol = -1; +static int global_use_mmio = -1; /* #define dev_alloc_skb dev_alloc_skb_debug */ @@ -935,6 +937,8 @@ module_param(compaq_ioaddr, int, 0); module_param(compaq_irq, int, 0); module_param(compaq_device_id, int, 0); module_param(watchdog, int, 0); +module_param(global_use_mmio, int, 0); +module_param_array(use_mmio, int, NULL, 0); MODULE_PARM_DESC(debug, "3c59x debug level (0-6)"); MODULE_PARM_DESC(options, "3c59x: Bits 0-3: media type, bit 4: bus mastering, bit 9: full duplex"); MODULE_PARM_DESC(global_options, "3c59x: same as options, but applies to all NICs if options is unset"); @@ -950,6 +954,8 @@ MODULE_PARM_DESC(compaq_ioaddr, "3c59x PCI I/O base address (Compaq BIOS problem MODULE_PARM_DESC(compaq_irq, "3c59x PCI IRQ number (Compaq BIOS problem workaround)"); MODULE_PARM_DESC(compaq_device_id, "3c59x PCI device ID (Compaq BIOS problem workaround)"); MODULE_PARM_DESC(watchdog, "3c59x transmit timeout in milliseconds"); +MODULE_PARM_DESC(global_use_mmio, "3c59x: same as use_mmio, but applies to all NICs if options is unset"); +MODULE_PARM_DESC(use_mmio, "3c59x: use memory-mapped PCI I/O resource (0-1)"); #ifdef CONFIG_NET_POLL_CONTROLLER static void poll_vortex(struct net_device *dev) @@ -1109,15 +1115,32 @@ static int __init vortex_eisa_init (void) static int __devinit vortex_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { - int rc; + int rc, unit, pci_bar; + struct vortex_chip_info *vci; + void __iomem *ioaddr; /* wake up and enable device */ rc = pci_enable_device (pdev); if (rc < 0) goto out; - rc = vortex_probe1 (&pdev->dev, pci_iomap(pdev, 0, 0), - pdev->irq, ent->driver_data, vortex_cards_found); + unit = vortex_cards_found; + + if (global_use_mmio < 0 && (unit >= MAX_UNITS || use_mmio[unit] < 0)) { + /* Determine the default if the user didn't override us */ + vci = &vortex_info_tbl[ent->driver_data]; + pci_bar = vci->drv_flags & (IS_CYCLONE | IS_TORNADO) ? 1 : 0; + } else if (unit < MAX_UNITS && use_mmio[unit] >= 0) + pci_bar = use_mmio[unit] ? 1 : 0; + else + pci_bar = global_use_mmio ? 1 : 0; + + ioaddr = pci_iomap(pdev, pci_bar, 0); + if (!ioaddr) /* If mapping fails, fall-back to BAR 0... */ + ioaddr = pci_iomap(pdev, 0, 0); + + rc = vortex_probe1(&pdev->dev, ioaddr, pdev->irq, + ent->driver_data, unit); if (rc < 0) { pci_disable_device (pdev); goto out; -- cgit v1.2.3 From d311b0d3d8fcc279132f7251704b23ec264a194f Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 7 Nov 2005 00:58:09 -0800 Subject: [PATCH] 3c59x: don't enable scatter/gather w/o checksum support It is not valid to enable scatter/gather without hardware checksum support of some kind. (akpm: applies only to the old boomerang cards). Signed-off-by: Stephen Hemminger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/3c59x.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index c1ee8efc9d5..7488ee7f7ca 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1536,11 +1536,10 @@ static int __devinit vortex_probe1(struct device *gendev, if (vp->full_bus_master_tx) { dev->hard_start_xmit = boomerang_start_xmit; /* Actually, it still should work with iommu. */ - dev->features |= NETIF_F_SG; if (card_idx < MAX_UNITS && ((hw_checksums[card_idx] == -1 && (vp->drv_flags & HAS_HWCKSM)) || hw_checksums[card_idx] == 1)) { - dev->features |= NETIF_F_IP_CSUM; + dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; } } else { dev->hard_start_xmit = vortex_start_xmit; -- cgit v1.2.3 From 2104da90a9aeef31ff6441d171a7d0492088f1d0 Mon Sep 17 00:00:00 2001 From: Lee Nicks Date: Mon, 7 Nov 2005 00:58:10 -0800 Subject: [PATCH] ppc32: add watchdog & RTC support for Marvell EV64360BP board This patch adds watchdog, RTC support for Marvell EV64360BP board. Signed-off-by: Lee Nicks Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/configs/ev64360_defconfig | 73 +++++++++++++++++++++++++++----------- arch/ppc/platforms/ev64360.c | 12 +++++++ arch/ppc/syslib/Makefile | 1 + 3 files changed, 66 insertions(+), 20 deletions(-) diff --git a/arch/ppc/configs/ev64360_defconfig b/arch/ppc/configs/ev64360_defconfig index de9bbb791db..d471e578dcb 100644 --- a/arch/ppc/configs/ev64360_defconfig +++ b/arch/ppc/configs/ev64360_defconfig @@ -1,17 +1,17 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc5 -# Fri Aug 5 15:18:23 2005 +# Linux kernel version: 2.6.14 +# Fri Oct 28 19:15:34 2005 # CONFIG_MMU=y CONFIG_GENERIC_HARDIRQS=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_HAVE_DEC_LOCK=y CONFIG_PPC=y CONFIG_PPC32=y CONFIG_GENERIC_NVRAM=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y # # Code maturity level options @@ -26,6 +26,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32 # General setup # CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y @@ -35,6 +36,7 @@ CONFIG_SYSCTL=y CONFIG_HOTPLUG=y CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -74,7 +76,7 @@ CONFIG_TAU=y # CONFIG_TAU_AVERAGE is not set # CONFIG_KEXEC is not set # CONFIG_CPU_FREQ is not set -# CONFIG_PM is not set +# CONFIG_WANT_EARLY_SERIAL is not set CONFIG_PPC_STD_MMU=y CONFIG_NOT_COHERENT_CACHE=y @@ -86,22 +88,18 @@ CONFIG_NOT_COHERENT_CACHE=y # CONFIG_KATANA is not set # CONFIG_WILLOW is not set # CONFIG_CPCI690 is not set -# CONFIG_PCORE is not set # CONFIG_POWERPMC250 is not set # CONFIG_CHESTNUT is not set # CONFIG_SPRUCE is not set # CONFIG_HDPU is not set # CONFIG_EV64260 is not set # CONFIG_LOPEC is not set -# CONFIG_MCPN765 is not set # CONFIG_MVME5100 is not set # CONFIG_PPLUS is not set # CONFIG_PRPMC750 is not set # CONFIG_PRPMC800 is not set # CONFIG_SANDPOINT is not set # CONFIG_RADSTONE_PPC7D is not set -# CONFIG_ADIR is not set -# CONFIG_K2 is not set # CONFIG_PAL4 is not set # CONFIG_GEMINI is not set # CONFIG_EST8260 is not set @@ -138,10 +136,13 @@ CONFIG_FLATMEM_MANUAL=y # CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=y CONFIG_CMDLINE_BOOL=y CONFIG_CMDLINE="console=ttyMM0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2" +# CONFIG_PM is not set +# CONFIG_SOFTWARE_SUSPEND is not set CONFIG_SECCOMP=y CONFIG_ISA_DMA_API=y @@ -152,7 +153,6 @@ CONFIG_GENERIC_ISA_DMA=y CONFIG_PCI=y CONFIG_PCI_DOMAINS=y # CONFIG_PCI_LEGACY_PROC is not set -# CONFIG_PCI_NAMES is not set # # PCCARD (PCMCIA/CardBus) support @@ -206,13 +206,18 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_INET_TUNNEL is not set -CONFIG_IP_TCPDIAG=y -# CONFIG_IP_TCPDIAG_IPV6 is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_BIC=y # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + # # SCTP Configuration (EXPERIMENTAL) # @@ -239,6 +244,7 @@ CONFIG_TCP_CONG_BIC=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set +# CONFIG_IEEE80211 is not set # # Device Drivers @@ -251,6 +257,11 @@ CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + # # Memory Technology Devices (MTD) # @@ -358,7 +369,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=32768 CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set # CONFIG_CDROM_PKTCDVD is not set @@ -379,6 +389,7 @@ CONFIG_IOSCHED_CFQ=y # # SCSI device support # +# CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # @@ -419,6 +430,10 @@ CONFIG_NETDEVICES=y # # CONFIG_ARCNET is not set +# +# PHY device support +# + # # Ethernet (10 or 100Mbit) # @@ -434,6 +449,7 @@ CONFIG_NETDEVICES=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set +# CONFIG_SIS190 is not set # CONFIG_SKGE is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -446,6 +462,7 @@ CONFIG_MV643XX_ETH_0=y # # Ethernet (10000 Mbit) # +# CONFIG_CHELSIO_T1 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set @@ -547,7 +564,20 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Watchdog Cards # -# CONFIG_WATCHDOG is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_MV64X60_WDT=y + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set # CONFIG_NVRAM is not set CONFIG_GEN_RTC=y # CONFIG_GEN_RTC_X is not set @@ -571,7 +601,6 @@ CONFIG_GEN_RTC=y # I2C support # # CONFIG_I2C is not set -# CONFIG_I2C_SENSOR is not set # # Dallas's 1-wire bus @@ -582,12 +611,17 @@ CONFIG_GEN_RTC=y # Hardware Monitoring support # CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set # CONFIG_HWMON_DEBUG_CHIP is not set # # Misc devices # +# +# Multimedia Capabilities Port drivers +# + # # Multimedia devices # @@ -651,10 +685,6 @@ CONFIG_EXT2_FS=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set - -# -# XFS support -# # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set @@ -663,6 +693,7 @@ CONFIG_INOTIFY=y CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set # # CD-ROM/DVD Filesystems @@ -683,11 +714,10 @@ CONFIG_DNOTIFY=y CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_SYSFS=y -# CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y -# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set # # Miscellaneous filesystems @@ -735,6 +765,7 @@ CONFIG_SUNRPC=y # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set # # Partition Types @@ -751,6 +782,7 @@ CONFIG_MSDOS_PARTITION=y # Library routines # # CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y @@ -767,6 +799,7 @@ CONFIG_ZLIB_DEFLATE=y # CONFIG_PRINTK_TIME is not set # CONFIG_DEBUG_KERNEL is not set CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_SERIAL_TEXT_DEBUG is not set # # Security options diff --git a/arch/ppc/platforms/ev64360.c b/arch/ppc/platforms/ev64360.c index b1324564456..b9d844f88c2 100644 --- a/arch/ppc/platforms/ev64360.c +++ b/arch/ppc/platforms/ev64360.c @@ -52,6 +52,8 @@ static u32 ev64360_bus_frequency; unsigned char __res[sizeof(bd_t)]; +TODC_ALLOC(); + static int __init ev64360_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) { @@ -182,6 +184,9 @@ ev64360_setup_peripherals(void) EV64360_RTC_WINDOW_BASE, EV64360_RTC_WINDOW_SIZE, 0); bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN); + TODC_INIT(TODC_TYPE_DS1501, 0, 0, + ioremap(EV64360_RTC_WINDOW_BASE, EV64360_RTC_WINDOW_SIZE), 8); + mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN, EV64360_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, 0); bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN); @@ -496,6 +501,13 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, ppc_md.power_off = ev64360_power_off; ppc_md.halt = ev64360_halt; ppc_md.find_end_of_memory = ev64360_find_end_of_memory; + ppc_md.init = NULL; + + ppc_md.time_init = todc_time_init; + ppc_md.set_rtc_time = todc_set_rtc_time; + ppc_md.get_rtc_time = todc_get_rtc_time; + ppc_md.nvram_read_val = todc_direct_read_val; + ppc_md.nvram_write_val = todc_direct_write_val; ppc_md.calibrate_decr = ev64360_calibrate_decr; #if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE) diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index b4ef15b45c4..2e58c210522 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_BAMBOO) += pci_auto.o todc_time.o obj-$(CONFIG_CPCI690) += todc_time.o pci_auto.o obj-$(CONFIG_EBONY) += pci_auto.o todc_time.o obj-$(CONFIG_EV64260) += todc_time.o pci_auto.o +obj-$(CONFIG_EV64360) += todc_time.o obj-$(CONFIG_CHESTNUT) += mv64360_pic.o pci_auto.o obj-$(CONFIG_GEMINI) += open_pic.o obj-$(CONFIG_GT64260) += gt64260_pic.o -- cgit v1.2.3 From fcc188e7fdddd8b23f900e485e6b3db05e7375f4 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 7 Nov 2005 00:58:11 -0800 Subject: [PATCH] ppc32: Allow ERPN for early serial to depend on CPU type The PowerPC 440SPe supports up to 16 GB of RAM, and therefore its IO registers are at 0x4_xxxx_xxxx instead of being at 0x1_xxxx_xxxx like most other PPC 440 chips. To allow for this, this patch moves the definition of the ERPN used for mapping UART0 from being hard-coded in the head_44x.S assembly code to being defined in ibm44x.h. Signed-off-by: Roland Dreier Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/kernel/head_44x.S | 4 ++-- include/asm-ppc/ibm44x.h | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S index 8b49679fad5..677c571aa27 100644 --- a/arch/ppc/kernel/head_44x.S +++ b/arch/ppc/kernel/head_44x.S @@ -190,8 +190,8 @@ skpinv: addi r4,r4,1 /* Increment */ /* xlat fields */ lis r4,UART0_PHYS_IO_BASE@h /* RPN depends on SoC */ -#ifndef CONFIG_440EP - ori r4,r4,0x0001 /* ERPN is 1 for second 4GB page */ +#ifdef UART0_PHYS_ERPN + ori r4,r4,UART0_PHYS_ERPN /* Add ERPN if above 4GB */ #endif /* attrib fields */ diff --git a/include/asm-ppc/ibm44x.h b/include/asm-ppc/ibm44x.h index e5374be86ae..197a9ff23dd 100644 --- a/include/asm-ppc/ibm44x.h +++ b/include/asm-ppc/ibm44x.h @@ -34,12 +34,17 @@ /* Lowest TLB slot consumed by the default pinned TLBs */ #define PPC44x_LOW_SLOT 63 -/* LS 32-bits of UART0 physical address location for early serial text debug */ +/* + * Least significant 32-bits and extended real page number (ERPN) of + * UART0 physical address location for early serial text debug + */ #if defined(CONFIG_440SP) +#define UART0_PHYS_ERPN 1 #define UART0_PHYS_IO_BASE 0xf0000200 #elif defined(CONFIG_440EP) #define UART0_PHYS_IO_BASE 0xe0000000 #else +#define UART0_PHYS_ERPN 1 #define UART0_PHYS_IO_BASE 0x40000200 #endif -- cgit v1.2.3 From 41aace4fe81e3da52fa80b8380e5d2d084f77691 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 7 Nov 2005 00:58:12 -0800 Subject: [PATCH] ppc32: Dump error status for both PLB segments on 440SP The PowerPC 440SP SoC has two Processor Local Bus (PLB) segments (a high-throughput segment and a low-latency segment). Fix our PLB register definitions to cope with this, and add code to dump the status of both segments when a machine check occurs. Signed-off-by: Roland Dreier Cc: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/syslib/ibm44x_common.c | 11 +++++++++++ include/asm-ppc/ibm44x.h | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/arch/ppc/syslib/ibm44x_common.c b/arch/ppc/syslib/ibm44x_common.c index 5152c8e4134..ebae2e2fcea 100644 --- a/arch/ppc/syslib/ibm44x_common.c +++ b/arch/ppc/syslib/ibm44x_common.c @@ -214,9 +214,20 @@ void __init ibm44x_platform_init(unsigned long r3, unsigned long r4, unsigned lo /* Called from machine_check_exception */ void platform_machine_check(struct pt_regs *regs) { +#ifdef CONFIG_440SP + printk("PLB0: BEAR=0x%08x%08x ACR= 0x%08x BESR= 0x%08x%08x\n", + mfdcr(DCRN_PLB0_BEARH), mfdcr(DCRN_PLB0_BEARL), + mfdcr(DCRN_PLB0_ACR), mfdcr(DCRN_PLB0_BESRH), + mfdcr(DCRN_PLB0_BESRL)); + printk("PLB1: BEAR=0x%08x%08x ACR= 0x%08x BESR= 0x%08x%08x\n", + mfdcr(DCRN_PLB1_BEARH), mfdcr(DCRN_PLB1_BEARL), + mfdcr(DCRN_PLB1_ACR), mfdcr(DCRN_PLB1_BESRH), + mfdcr(DCRN_PLB1_BESRL)); +#else printk("PLB0: BEAR=0x%08x%08x ACR= 0x%08x BESR= 0x%08x\n", mfdcr(DCRN_PLB0_BEARH), mfdcr(DCRN_PLB0_BEARL), mfdcr(DCRN_PLB0_ACR), mfdcr(DCRN_PLB0_BESR)); +#endif printk("POB0: BEAR=0x%08x%08x BESR0=0x%08x BESR1=0x%08x\n", mfdcr(DCRN_POB0_BEARH), mfdcr(DCRN_POB0_BEARL), mfdcr(DCRN_POB0_BESR0), mfdcr(DCRN_POB0_BESR1)); diff --git a/include/asm-ppc/ibm44x.h b/include/asm-ppc/ibm44x.h index 197a9ff23dd..0c2ba03a1d4 100644 --- a/include/asm-ppc/ibm44x.h +++ b/include/asm-ppc/ibm44x.h @@ -302,6 +302,23 @@ #define MALOBISR_CH0 0x80000000 /* EOB channel 1 bit */ #define MALOBISR_CH2 0x40000000 /* EOB channel 2 bit */ +#if defined(CONFIG_440SP) +/* 440SP PLB Arbiter DCRs */ +#define DCRN_PLB_REVID 0x080 /* PLB Revision ID */ +#define DCRN_PLB_CCR 0x088 /* PLB Crossbar Control */ + +#define DCRN_PLB0_ACR 0x081 /* PLB Arbiter Control */ +#define DCRN_PLB0_BESRL 0x082 /* PLB Error Status */ +#define DCRN_PLB0_BESRH 0x083 /* PLB Error Status */ +#define DCRN_PLB0_BEARL 0x084 /* PLB Error Address Low */ +#define DCRN_PLB0_BEARH 0x085 /* PLB Error Address High */ + +#define DCRN_PLB1_ACR 0x089 /* PLB Arbiter Control */ +#define DCRN_PLB1_BESRL 0x08a /* PLB Error Status */ +#define DCRN_PLB1_BESRH 0x08b /* PLB Error Status */ +#define DCRN_PLB1_BEARL 0x08c /* PLB Error Address Low */ +#define DCRN_PLB1_BEARH 0x08d /* PLB Error Address High */ +#else /* 440GP/GX PLB Arbiter DCRs */ #define DCRN_PLB0_REVID 0x082 /* PLB Arbiter Revision ID */ #define DCRN_PLB0_ACR 0x083 /* PLB Arbiter Control */ @@ -309,6 +326,7 @@ #define DCRN_PLB0_BEARL 0x086 /* PLB Error Address Low */ #define DCRN_PLB0_BEAR DCRN_PLB0_BEARL /* 40x compatibility */ #define DCRN_PLB0_BEARH 0x087 /* PLB Error Address High */ +#endif /* 440GP/GX PLB to OPB bridge DCRs */ #define DCRN_POB0_BESR0 0x090 -- cgit v1.2.3 From b0f7b8bc57ee90138a7c429951457027a90c326f Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 7 Nov 2005 00:58:13 -0800 Subject: [PATCH] ppc32: Add 440SPe support Add support for the AMCC PowerPC 440SPe SoC, including PCI Express in root port mode. Signed-off-by: Roland Dreier Cc: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/cputable.c | 10 + arch/ppc/platforms/4xx/Kconfig | 8 +- arch/ppc/platforms/4xx/Makefile | 1 + arch/ppc/platforms/4xx/ppc440spe.c | 148 +++++++++++++ arch/ppc/platforms/4xx/ppc440spe.h | 66 ++++++ arch/ppc/syslib/Makefile | 1 + arch/ppc/syslib/ibm440sp_common.c | 4 +- arch/ppc/syslib/ibm44x_common.c | 2 +- arch/ppc/syslib/ppc440spe_pcie.c | 442 +++++++++++++++++++++++++++++++++++++ arch/ppc/syslib/ppc440spe_pcie.h | 149 +++++++++++++ arch/ppc/syslib/ppc4xx_pic.c | 37 +++- include/asm-ppc/ibm44x.h | 55 +++-- 12 files changed, 904 insertions(+), 19 deletions(-) create mode 100644 arch/ppc/platforms/4xx/ppc440spe.c create mode 100644 arch/ppc/platforms/4xx/ppc440spe.h create mode 100644 arch/ppc/syslib/ppc440spe_pcie.c create mode 100644 arch/ppc/syslib/ppc440spe_pcie.h diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 33c63bcf69f..cc4e9eb1c13 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -929,6 +929,16 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, }, + { /* 440SPe Rev. A */ + .pvr_mask = 0xff000fff, + .pvr_value = 0x53000890, + .cpu_name = "440SPe Rev. A", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .icache_bsize = 32, + .dcache_bsize = 32, + }, #endif /* CONFIG_44x */ #ifdef CONFIG_FSL_BOOKE { /* e200z5 */ diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig index 76f4476cab4..108d5a730f8 100644 --- a/arch/ppc/platforms/4xx/Kconfig +++ b/arch/ppc/platforms/4xx/Kconfig @@ -124,9 +124,13 @@ config 440SP depends on LUAN default y +config 440SPE + bool + default n + config 440 bool - depends on 440GP || 440SP || 440EP + depends on 440GP || 440SP || 440SPE || 440EP default y config 440A @@ -168,7 +172,7 @@ config XILINX_OCP config IBM_EMAC4 bool - depends on 440GX || 440SP + depends on 440GX || 440SP || 440SPE default y config BIOS_FIXUP diff --git a/arch/ppc/platforms/4xx/Makefile b/arch/ppc/platforms/4xx/Makefile index 1dd6d7fd6a9..694accdb59f 100644 --- a/arch/ppc/platforms/4xx/Makefile +++ b/arch/ppc/platforms/4xx/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_440EP) += ibm440ep.o obj-$(CONFIG_440GP) += ibm440gp.o obj-$(CONFIG_440GX) += ibm440gx.o obj-$(CONFIG_440SP) += ibm440sp.o +obj-$(CONFIG_440SPE) += ppc440spe.o obj-$(CONFIG_405EP) += ibm405ep.o obj-$(CONFIG_405GPR) += ibm405gpr.o obj-$(CONFIG_VIRTEX_II_PRO) += virtex-ii_pro.o diff --git a/arch/ppc/platforms/4xx/ppc440spe.c b/arch/ppc/platforms/4xx/ppc440spe.c new file mode 100644 index 00000000000..6139a0b3393 --- /dev/null +++ b/arch/ppc/platforms/4xx/ppc440spe.c @@ -0,0 +1,148 @@ +/* + * arch/ppc/platforms/4xx/ppc440spe.c + * + * PPC440SPe I/O descriptions + * + * Roland Dreier + * Copyright (c) 2005 Cisco Systems. All rights reserved. + * + * Matt Porter + * Copyright 2002-2005 MontaVista Software Inc. + * + * Eugene Surovegin or + * Copyright (c) 2003, 2004 Zultys Technologies + * + * 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 + * option) any later version. + * + */ +#include +#include +#include +#include +#include + +static struct ocp_func_emac_data ppc440spe_emac0_def = { + .rgmii_idx = -1, /* No RGMII */ + .rgmii_mux = -1, /* No RGMII */ + .zmii_idx = -1, /* No ZMII */ + .zmii_mux = -1, /* No ZMII */ + .mal_idx = 0, /* MAL device index */ + .mal_rx_chan = 0, /* MAL rx channel number */ + .mal_tx_chan = 0, /* MAL tx channel number */ + .wol_irq = 61, /* WOL interrupt number */ + .mdio_idx = -1, /* No shared MDIO */ + .tah_idx = -1, /* No TAH */ +}; +OCP_SYSFS_EMAC_DATA() + +static struct ocp_func_mal_data ppc440spe_mal0_def = { + .num_tx_chans = 1, /* Number of TX channels */ + .num_rx_chans = 1, /* Number of RX channels */ + .txeob_irq = 38, /* TX End Of Buffer IRQ */ + .rxeob_irq = 39, /* RX End Of Buffer IRQ */ + .txde_irq = 34, /* TX Descriptor Error IRQ */ + .rxde_irq = 35, /* RX Descriptor Error IRQ */ + .serr_irq = 33, /* MAL System Error IRQ */ + .dcr_base = DCRN_MAL_BASE /* MAL0_CFG DCR number */ +}; +OCP_SYSFS_MAL_DATA() + +static struct ocp_func_iic_data ppc440spe_iic0_def = { + .fast_mode = 0, /* Use standad mode (100Khz) */ +}; + +static struct ocp_func_iic_data ppc440spe_iic1_def = { + .fast_mode = 0, /* Use standad mode (100Khz) */ +}; +OCP_SYSFS_IIC_DATA() + +struct ocp_def core_ocp[] = { + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_16550, + .index = 0, + .paddr = PPC440SPE_UART0_ADDR, + .irq = UART0_INT, + .pm = IBM_CPM_UART0, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_16550, + .index = 1, + .paddr = PPC440SPE_UART1_ADDR, + .irq = UART1_INT, + .pm = IBM_CPM_UART1, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_16550, + .index = 2, + .paddr = PPC440SPE_UART2_ADDR, + .irq = UART2_INT, + .pm = IBM_CPM_UART2, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_IIC, + .index = 0, + .paddr = 0x00000004f0000400ULL, + .irq = 2, + .pm = IBM_CPM_IIC0, + .additions = &ppc440spe_iic0_def, + .show = &ocp_show_iic_data + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_IIC, + .index = 1, + .paddr = 0x00000004f0000500ULL, + .irq = 3, + .pm = IBM_CPM_IIC1, + .additions = &ppc440spe_iic1_def, + .show = &ocp_show_iic_data + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_GPIO, + .index = 0, + .paddr = 0x00000004f0000700ULL, + .irq = OCP_IRQ_NA, + .pm = IBM_CPM_GPIO0, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_MAL, + .paddr = OCP_PADDR_NA, + .irq = OCP_IRQ_NA, + .pm = OCP_CPM_NA, + .additions = &ppc440spe_mal0_def, + .show = &ocp_show_mal_data, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_EMAC, + .index = 0, + .paddr = 0x00000004f0000800ULL, + .irq = 60, + .pm = OCP_CPM_NA, + .additions = &ppc440spe_emac0_def, + .show = &ocp_show_emac_data, + }, + { .vendor = OCP_VENDOR_INVALID + } +}; + +/* Polarity and triggering settings for internal interrupt sources */ +struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = { + { .polarity = 0xffffffff, + .triggering = 0x010f0004, + .ext_irq_mask = 0x00000000, + }, + { .polarity = 0xffffffff, + .triggering = 0x001f8040, + .ext_irq_mask = 0x00007c30, /* IRQ6 - IRQ7, IRQ8 - IRQ12 */ + }, + { .polarity = 0xffffffff, + .triggering = 0x00000000, + .ext_irq_mask = 0x000000fc, /* IRQ0 - IRQ5 */ + }, + { .polarity = 0xffffffff, + .triggering = 0x00000000, + .ext_irq_mask = 0x00000000, + }, +}; diff --git a/arch/ppc/platforms/4xx/ppc440spe.h b/arch/ppc/platforms/4xx/ppc440spe.h new file mode 100644 index 00000000000..2216846973b --- /dev/null +++ b/arch/ppc/platforms/4xx/ppc440spe.h @@ -0,0 +1,66 @@ +/* + * arch/ppc/platforms/4xx/ibm440spe.h + * + * PPC440SPe definitions + * + * Roland Dreier + * Copyright (c) 2005 Cisco Systems. All rights reserved. + * + * Matt Porter + * Copyright 2004-2005 MontaVista Software, Inc. + * + * 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 + * option) any later version. + */ + +#ifdef __KERNEL__ +#ifndef __PPC_PLATFORMS_PPC440SPE_H +#define __PPC_PLATFORMS_PPC440SPE_H + +#include + +#include + +/* UART */ +#define PPC440SPE_UART0_ADDR 0x00000004f0000200ULL +#define PPC440SPE_UART1_ADDR 0x00000004f0000300ULL +#define PPC440SPE_UART2_ADDR 0x00000004f0000600ULL +#define UART0_INT 0 +#define UART1_INT 1 +#define UART2_INT 37 + +/* Clock and Power Management */ +#define IBM_CPM_IIC0 0x80000000 /* IIC interface */ +#define IBM_CPM_IIC1 0x40000000 /* IIC interface */ +#define IBM_CPM_PCI 0x20000000 /* PCI bridge */ +#define IBM_CPM_CPU 0x02000000 /* processor core */ +#define IBM_CPM_DMA 0x01000000 /* DMA controller */ +#define IBM_CPM_BGO 0x00800000 /* PLB to OPB bus arbiter */ +#define IBM_CPM_BGI 0x00400000 /* OPB to PLB bridge */ +#define IBM_CPM_EBC 0x00200000 /* External Bux Controller */ +#define IBM_CPM_EBM 0x00100000 /* Ext Bus Master Interface */ +#define IBM_CPM_DMC 0x00080000 /* SDRAM peripheral controller */ +#define IBM_CPM_PLB 0x00040000 /* PLB bus arbiter */ +#define IBM_CPM_SRAM 0x00020000 /* SRAM memory controller */ +#define IBM_CPM_PPM 0x00002000 /* PLB Performance Monitor */ +#define IBM_CPM_UIC1 0x00001000 /* Universal Interrupt Controller */ +#define IBM_CPM_GPIO0 0x00000800 /* General Purpose IO (??) */ +#define IBM_CPM_GPT 0x00000400 /* General Purpose Timers */ +#define IBM_CPM_UART0 0x00000200 /* serial port 0 */ +#define IBM_CPM_UART1 0x00000100 /* serial port 1 */ +#define IBM_CPM_UART2 0x00000100 /* serial port 1 */ +#define IBM_CPM_UIC0 0x00000080 /* Universal Interrupt Controller */ +#define IBM_CPM_TMRCLK 0x00000040 /* CPU timers */ +#define IBM_CPM_EMAC0 0x00000020 /* EMAC 0 */ + +#define DFLT_IBM4xx_PM ~(IBM_CPM_UIC | IBM_CPM_UIC1 | IBM_CPM_CPU \ + | IBM_CPM_EBC | IBM_CPM_SRAM | IBM_CPM_BGO \ + | IBM_CPM_EBM | IBM_CPM_PLB | IBM_CPM_OPB \ + | IBM_CPM_TMRCLK | IBM_CPM_DMA | IBM_CPM_PCI \ + | IBM_CPM_TAHOE0 | IBM_CPM_TAHOE1 \ + | IBM_CPM_EMAC0 | IBM_CPM_EMAC1 \ + | IBM_CPM_EMAC2 | IBM_CPM_EMAC3 ) +#endif /* __PPC_PLATFORMS_PPC440SP_H */ +#endif /* __KERNEL__ */ diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index 2e58c210522..13dff1e51f1 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_440EP) += ibm440gx_common.o obj-$(CONFIG_440GP) += ibm440gp_common.o obj-$(CONFIG_440GX) += ibm440gx_common.o obj-$(CONFIG_440SP) += ibm440gx_common.o ibm440sp_common.o +obj-$(CONFIG_440SPE) += ibm440gx_common.o ibm440sp_common.o ppc440spe_pcie.o ifeq ($(CONFIG_4xx),y) ifeq ($(CONFIG_VIRTEX_II_PRO),y) obj-$(CONFIG_40x) += xilinx_pic.o diff --git a/arch/ppc/syslib/ibm440sp_common.c b/arch/ppc/syslib/ibm440sp_common.c index 417d4cff77a..cdafda127d8 100644 --- a/arch/ppc/syslib/ibm440sp_common.c +++ b/arch/ppc/syslib/ibm440sp_common.c @@ -1,7 +1,7 @@ /* * arch/ppc/syslib/ibm440sp_common.c * - * PPC440SP system library + * PPC440SP/PPC440SPe system library * * Matt Porter * Copyright 2002-2005 MontaVista Software Inc. @@ -35,7 +35,7 @@ unsigned long __init ibm440sp_find_end_of_memory(void) u32 mem_size = 0; /* Read two bank sizes and sum */ - for (i=0; i<2; i++) + for (i=0; i< MQ0_NUM_BANKS; i++) switch (mfdcr(DCRN_MQ0_BS0BAS + i) & MQ0_CONFIG_SIZE_MASK) { case MQ0_CONFIG_SIZE_8M: mem_size += PPC44x_MEM_SIZE_8M; diff --git a/arch/ppc/syslib/ibm44x_common.c b/arch/ppc/syslib/ibm44x_common.c index ebae2e2fcea..a5bef9d163a 100644 --- a/arch/ppc/syslib/ibm44x_common.c +++ b/arch/ppc/syslib/ibm44x_common.c @@ -214,7 +214,7 @@ void __init ibm44x_platform_init(unsigned long r3, unsigned long r4, unsigned lo /* Called from machine_check_exception */ void platform_machine_check(struct pt_regs *regs) { -#ifdef CONFIG_440SP +#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) printk("PLB0: BEAR=0x%08x%08x ACR= 0x%08x BESR= 0x%08x%08x\n", mfdcr(DCRN_PLB0_BEARH), mfdcr(DCRN_PLB0_BEARL), mfdcr(DCRN_PLB0_ACR), mfdcr(DCRN_PLB0_BESRH), diff --git a/arch/ppc/syslib/ppc440spe_pcie.c b/arch/ppc/syslib/ppc440spe_pcie.c new file mode 100644 index 00000000000..1509fc1ddfb --- /dev/null +++ b/arch/ppc/syslib/ppc440spe_pcie.c @@ -0,0 +1,442 @@ +/* + * Copyright (c) 2005 Cisco Systems. All rights reserved. + * Roland Dreier + * + * 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 + * option) any later version. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ppc440spe_pcie.h" + +static int +pcie_read_config(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 *val) +{ + struct pci_controller *hose = bus->sysdata; + + if (PCI_SLOT(devfn) != 1) + return PCIBIOS_DEVICE_NOT_FOUND; + + offset += devfn << 12; + + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + switch (len) { + case 1: + *val = in_8(hose->cfg_data + offset); + break; + case 2: + *val = in_le16(hose->cfg_data + offset); + break; + default: + *val = in_le32(hose->cfg_data + offset); + break; + } + + if (0) printk("%s: read %x(%d) @ %x\n", __func__, *val, len, offset); + + return PCIBIOS_SUCCESSFUL; +} + +static int +pcie_write_config(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 val) +{ + struct pci_controller *hose = bus->sysdata; + + if (PCI_SLOT(devfn) != 1) + return PCIBIOS_DEVICE_NOT_FOUND; + + offset += devfn << 12; + + switch (len) { + case 1: + out_8(hose->cfg_data + offset, val); + break; + case 2: + out_le16(hose->cfg_data + offset, val); + break; + default: + out_le32(hose->cfg_data + offset, val); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops pcie_pci_ops = +{ + .read = pcie_read_config, + .write = pcie_write_config +}; + +enum { + PTYPE_ENDPOINT = 0x0, + PTYPE_LEGACY_ENDPOINT = 0x1, + PTYPE_ROOT_PORT = 0x4, + + LNKW_X1 = 0x1, + LNKW_X4 = 0x4, + LNKW_X8 = 0x8 +}; + +static void check_error(void) +{ + u32 valPE0, valPE1, valPE2; + + /* SDR0_PEGPLLLCT1 reset */ + if (!(valPE0 = SDR_READ(PESDR0_PLLLCT1) & 0x01000000)) { + printk(KERN_INFO "PCIE: SDR0_PEGPLLLCT1 reset error 0x%8x\n", valPE0); + } + + valPE0 = SDR_READ(PESDR0_RCSSET); + valPE1 = SDR_READ(PESDR1_RCSSET); + valPE2 = SDR_READ(PESDR2_RCSSET); + + /* SDR0_PExRCSSET rstgu */ + if ( !(valPE0 & 0x01000000) || + !(valPE1 & 0x01000000) || + !(valPE2 & 0x01000000)) { + printk(KERN_INFO "PCIE: SDR0_PExRCSSET rstgu error\n"); + } + + /* SDR0_PExRCSSET rstdl */ + if ( !(valPE0 & 0x00010000) || + !(valPE1 & 0x00010000) || + !(valPE2 & 0x00010000)) { + printk(KERN_INFO "PCIE: SDR0_PExRCSSET rstdl error\n"); + } + + /* SDR0_PExRCSSET rstpyn */ + if ( (valPE0 & 0x00001000) || + (valPE1 & 0x00001000) || + (valPE2 & 0x00001000)) { + printk(KERN_INFO "PCIE: SDR0_PExRCSSET rstpyn error\n"); + } + + /* SDR0_PExRCSSET hldplb */ + if ( (valPE0 & 0x10000000) || + (valPE1 & 0x10000000) || + (valPE2 & 0x10000000)) { + printk(KERN_INFO "PCIE: SDR0_PExRCSSET hldplb error\n"); + } + + /* SDR0_PExRCSSET rdy */ + if ( (valPE0 & 0x00100000) || + (valPE1 & 0x00100000) || + (valPE2 & 0x00100000)) { + printk(KERN_INFO "PCIE: SDR0_PExRCSSET rdy error\n"); + } + + /* SDR0_PExRCSSET shutdown */ + if ( (valPE0 & 0x00000100) || + (valPE1 & 0x00000100) || + (valPE2 & 0x00000100)) { + printk(KERN_INFO "PCIE: SDR0_PExRCSSET shutdown error\n"); + } +} + +/* + * Initialize PCI Express core as described in User Manual section 27.12.1 + */ +int ppc440spe_init_pcie(void) +{ + /* Set PLL clock receiver to LVPECL */ + SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) | 1 << 28); + + check_error(); + + printk(KERN_INFO "PCIE initialization OK\n"); + + if (!(SDR_READ(PESDR0_PLLLCT2) & 0x10000)) + printk(KERN_INFO "PESDR_PLLCT2 resistance calibration failed (0x%08x)\n", + SDR_READ(PESDR0_PLLLCT2)); + + /* De-assert reset of PCIe PLL, wait for lock */ + SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) & ~(1 << 24)); + udelay(3); + + return 0; +} + +int ppc440spe_init_pcie_rootport(int port) +{ + static int core_init; + void __iomem *utl_base; + u32 val = 0; + int i; + + if (!core_init) { + ++core_init; + i = ppc440spe_init_pcie(); + if (i) + return i; + } + + /* + * Initialize various parts of the PCI Express core for our port: + * + * - Set as a root port and enable max width + * (PXIE0 -> X8, PCIE1 and PCIE2 -> X4). + * - Set up UTL configuration. + * - Increase SERDES drive strength to levels suggested by AMCC. + * - De-assert RSTPYN, RSTDL and RSTGU. + */ + switch (port) { + case 0: + SDR_WRITE(PESDR0_DLPSET, PTYPE_ROOT_PORT << 20 | LNKW_X8 << 12); + + SDR_WRITE(PESDR0_UTLSET1, 0x21222222); + SDR_WRITE(PESDR0_UTLSET2, 0x11000000); + + SDR_WRITE(PESDR0_HSSL0SET1, 0x35000000); + SDR_WRITE(PESDR0_HSSL1SET1, 0x35000000); + SDR_WRITE(PESDR0_HSSL2SET1, 0x35000000); + SDR_WRITE(PESDR0_HSSL3SET1, 0x35000000); + SDR_WRITE(PESDR0_HSSL4SET1, 0x35000000); + SDR_WRITE(PESDR0_HSSL5SET1, 0x35000000); + SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000); + SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000); + + SDR_WRITE(PESDR0_RCSSET, + (SDR_READ(PESDR0_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); + break; + + case 1: + SDR_WRITE(PESDR1_DLPSET, PTYPE_ROOT_PORT << 20 | LNKW_X4 << 12); + + SDR_WRITE(PESDR1_UTLSET1, 0x21222222); + SDR_WRITE(PESDR1_UTLSET2, 0x11000000); + + SDR_WRITE(PESDR1_HSSL0SET1, 0x35000000); + SDR_WRITE(PESDR1_HSSL1SET1, 0x35000000); + SDR_WRITE(PESDR1_HSSL2SET1, 0x35000000); + SDR_WRITE(PESDR1_HSSL3SET1, 0x35000000); + + SDR_WRITE(PESDR1_RCSSET, + (SDR_READ(PESDR1_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); + break; + + case 2: + SDR_WRITE(PESDR2_DLPSET, PTYPE_ROOT_PORT << 20 | LNKW_X4 << 12); + + SDR_WRITE(PESDR2_UTLSET1, 0x21222222); + SDR_WRITE(PESDR2_UTLSET2, 0x11000000); + + SDR_WRITE(PESDR2_HSSL0SET1, 0x35000000); + SDR_WRITE(PESDR2_HSSL1SET1, 0x35000000); + SDR_WRITE(PESDR2_HSSL2SET1, 0x35000000); + SDR_WRITE(PESDR2_HSSL3SET1, 0x35000000); + + SDR_WRITE(PESDR2_RCSSET, + (SDR_READ(PESDR2_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); + break; + } + + mdelay(1000); + + switch (port) { + case 0: val = SDR_READ(PESDR0_RCSSTS); break; + case 1: val = SDR_READ(PESDR1_RCSSTS); break; + case 2: val = SDR_READ(PESDR2_RCSSTS); break; + } + + if (!(val & (1 << 20))) + printk(KERN_INFO "PCIE%d: PGRST inactive\n", port); + else + printk(KERN_WARNING "PGRST for PCIE%d failed %08x\n", port, val); + + switch (port) { + case 0: printk(KERN_INFO "PCIE0: LOOP %08x\n", SDR_READ(PESDR0_LOOP)); break; + case 1: printk(KERN_INFO "PCIE1: LOOP %08x\n", SDR_READ(PESDR1_LOOP)); break; + case 2: printk(KERN_INFO "PCIE2: LOOP %08x\n", SDR_READ(PESDR2_LOOP)); break; + } + + /* + * Map UTL registers at 0xc_1000_0n00 + */ + switch (port) { + case 0: + mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x0000000c); + mtdcr(DCRN_PEGPL_REGBAL(PCIE0), 0x10000000); + mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001); + mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0x68782800); + break; + + case 1: + mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x0000000c); + mtdcr(DCRN_PEGPL_REGBAL(PCIE1), 0x10001000); + mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001); + mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0x68782800); + break; + + case 2: + mtdcr(DCRN_PEGPL_REGBAH(PCIE2), 0x0000000c); + mtdcr(DCRN_PEGPL_REGBAL(PCIE2), 0x10002000); + mtdcr(DCRN_PEGPL_REGMSK(PCIE2), 0x00007001); + mtdcr(DCRN_PEGPL_SPECIAL(PCIE2), 0x68782800); + } + + utl_base = ioremap64(0xc10000000ull + 0x1000 * port, 0x100); + + /* + * Set buffer allocations and then assert VRB and TXE. + */ + out_be32(utl_base + PEUTL_OUTTR, 0x08000000); + out_be32(utl_base + PEUTL_INTR, 0x02000000); + out_be32(utl_base + PEUTL_OPDBSZ, 0x10000000); + out_be32(utl_base + PEUTL_PBBSZ, 0x53000000); + out_be32(utl_base + PEUTL_IPHBSZ, 0x08000000); + out_be32(utl_base + PEUTL_IPDBSZ, 0x10000000); + out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000); + out_be32(utl_base + PEUTL_PCTL, 0x80800066); + + iounmap(utl_base); + + /* + * We map PCI Express configuration access into the 512MB regions + * PCIE0: 0xc_4000_0000 + * PCIE1: 0xc_8000_0000 + * PCIE2: 0xc_c000_0000 + */ + switch (port) { + case 0: + mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000c); + mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x40000000); + mtdcr(DCRN_PEGPL_CFGMSK(PCIE0), 0xe0000001); /* 512MB region, valid */ + break; + + case 1: + mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000c); + mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x80000000); + mtdcr(DCRN_PEGPL_CFGMSK(PCIE1), 0xe0000001); /* 512MB region, valid */ + break; + + case 2: + mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000c); + mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0xc0000000); + mtdcr(DCRN_PEGPL_CFGMSK(PCIE2), 0xe0000001); /* 512MB region, valid */ + break; + } + + /* + * Check for VC0 active and assert RDY. + */ + switch (port) { + case 0: + if (!(SDR_READ(PESDR0_RCSSTS) & (1 << 16))) + printk(KERN_WARNING "PCIE0: VC0 not active\n"); + SDR_WRITE(PESDR0_RCSSET, SDR_READ(PESDR0_RCSSET) | 1 << 20); + break; + case 1: + if (!(SDR_READ(PESDR1_RCSSTS) & (1 << 16))) + printk(KERN_WARNING "PCIE0: VC0 not active\n"); + SDR_WRITE(PESDR1_RCSSET, SDR_READ(PESDR1_RCSSET) | 1 << 20); + break; + case 2: + if (!(SDR_READ(PESDR2_RCSSTS) & (1 << 16))) + printk(KERN_WARNING "PCIE0: VC0 not active\n"); + SDR_WRITE(PESDR2_RCSSET, SDR_READ(PESDR2_RCSSET) | 1 << 20); + break; + } + +#if 0 + /* Dump all config regs */ + for (i = 0x300; i <= 0x320; ++i) + printk("[%04x] 0x%08x\n", i, SDR_READ(i)); + for (i = 0x340; i <= 0x353; ++i) + printk("[%04x] 0x%08x\n", i, SDR_READ(i)); + for (i = 0x370; i <= 0x383; ++i) + printk("[%04x] 0x%08x\n", i, SDR_READ(i)); + for (i = 0x3a0; i <= 0x3a2; ++i) + printk("[%04x] 0x%08x\n", i, SDR_READ(i)); + for (i = 0x3c0; i <= 0x3c3; ++i) + printk("[%04x] 0x%08x\n", i, SDR_READ(i)); +#endif + + mdelay(100); + + return 0; +} + +void ppc440spe_setup_pcie(struct pci_controller *hose, int port) +{ + void __iomem *mbase; + + /* + * Map 16MB, which is enough for 4 bits of bus # + */ + hose->cfg_data = ioremap64(0xc40000000ull + port * 0x40000000, + 1 << 24); + hose->ops = &pcie_pci_ops; + + /* + * Set bus numbers on our root port + */ + mbase = ioremap64(0xc50000000ull + port * 0x40000000, 4096); + out_8(mbase + PCI_PRIMARY_BUS, 0); + out_8(mbase + PCI_SECONDARY_BUS, 0); + + /* + * Set up outbound translation to hose->mem_space from PLB + * addresses at an offset of 0xd_0000_0000. We set the low + * bits of the mask to 11 to turn off splitting into 8 + * subregions and to enable the outbound translation. + */ + out_le32(mbase + PECFG_POM0LAH, 0); + out_le32(mbase + PECFG_POM0LAL, hose->mem_space.start); + + switch (port) { + case 0: + mtdcr(DCRN_PEGPL_OMR1BAH(PCIE0), 0x0000000d); + mtdcr(DCRN_PEGPL_OMR1BAL(PCIE0), hose->mem_space.start); + mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE0), 0x7fffffff); + mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE0), + ~(hose->mem_space.end - hose->mem_space.start) | 3); + break; + case 1: + mtdcr(DCRN_PEGPL_OMR1BAH(PCIE1), 0x0000000d); + mtdcr(DCRN_PEGPL_OMR1BAL(PCIE1), hose->mem_space.start); + mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE1), 0x7fffffff); + mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1), + ~(hose->mem_space.end - hose->mem_space.start) | 3); + + break; + case 2: + mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2), 0x0000000d); + mtdcr(DCRN_PEGPL_OMR1BAL(PCIE2), hose->mem_space.start); + mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE2), 0x7fffffff); + mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE2), + ~(hose->mem_space.end - hose->mem_space.start) | 3); + break; + } + + /* Set up 16GB inbound memory window at 0 */ + out_le32(mbase + PCI_BASE_ADDRESS_0, 0); + out_le32(mbase + PCI_BASE_ADDRESS_1, 0); + out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffc); + out_le32(mbase + PECFG_BAR0LMPA, 0); + out_le32(mbase + PECFG_PIM0LAL, 0); + out_le32(mbase + PECFG_PIM0LAH, 0); + out_le32(mbase + PECFG_PIMEN, 0x1); + + /* Enable I/O, Mem, and Busmaster cycles */ + out_le16(mbase + PCI_COMMAND, + in_le16(mbase + PCI_COMMAND) | + PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + + iounmap(mbase); +} diff --git a/arch/ppc/syslib/ppc440spe_pcie.h b/arch/ppc/syslib/ppc440spe_pcie.h new file mode 100644 index 00000000000..55b765ad327 --- /dev/null +++ b/arch/ppc/syslib/ppc440spe_pcie.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2005 Cisco Systems. All rights reserved. + * Roland Dreier + * + * 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 + * option) any later version. + */ + +#ifndef __PPC_SYSLIB_PPC440SPE_PCIE_H +#define __PPC_SYSLIB_PPC440SPE_PCIE_H + +#define DCRN_SDR0_CFGADDR 0x00e +#define DCRN_SDR0_CFGDATA 0x00f + +#define DCRN_PCIE0_BASE 0x100 +#define DCRN_PCIE1_BASE 0x120 +#define DCRN_PCIE2_BASE 0x140 +#define PCIE0 DCRN_PCIE0_BASE +#define PCIE1 DCRN_PCIE1_BASE +#define PCIE2 DCRN_PCIE2_BASE + +#define DCRN_PEGPL_CFGBAH(base) (base + 0x00) +#define DCRN_PEGPL_CFGBAL(base) (base + 0x01) +#define DCRN_PEGPL_CFGMSK(base) (base + 0x02) +#define DCRN_PEGPL_MSGBAH(base) (base + 0x03) +#define DCRN_PEGPL_MSGBAL(base) (base + 0x04) +#define DCRN_PEGPL_MSGMSK(base) (base + 0x05) +#define DCRN_PEGPL_OMR1BAH(base) (base + 0x06) +#define DCRN_PEGPL_OMR1BAL(base) (base + 0x07) +#define DCRN_PEGPL_OMR1MSKH(base) (base + 0x08) +#define DCRN_PEGPL_OMR1MSKL(base) (base + 0x09) +#define DCRN_PEGPL_REGBAH(base) (base + 0x12) +#define DCRN_PEGPL_REGBAL(base) (base + 0x13) +#define DCRN_PEGPL_REGMSK(base) (base + 0x14) +#define DCRN_PEGPL_SPECIAL(base) (base + 0x15) + +/* + * System DCRs (SDRs) + */ +#define PESDR0_PLLLCT1 0x03a0 +#define PESDR0_PLLLCT2 0x03a1 +#define PESDR0_PLLLCT3 0x03a2 + +#define PESDR0_UTLSET1 0x0300 +#define PESDR0_UTLSET2 0x0301 +#define PESDR0_DLPSET 0x0302 +#define PESDR0_LOOP 0x0303 +#define PESDR0_RCSSET 0x0304 +#define PESDR0_RCSSTS 0x0305 +#define PESDR0_HSSL0SET1 0x0306 +#define PESDR0_HSSL0SET2 0x0307 +#define PESDR0_HSSL0STS 0x0308 +#define PESDR0_HSSL1SET1 0x0309 +#define PESDR0_HSSL1SET2 0x030a +#define PESDR0_HSSL1STS 0x030b +#define PESDR0_HSSL2SET1 0x030c +#define PESDR0_HSSL2SET2 0x030d +#define PESDR0_HSSL2STS 0x030e +#define PESDR0_HSSL3SET1 0x030f +#define PESDR0_HSSL3SET2 0x0310 +#define PESDR0_HSSL3STS 0x0311 +#define PESDR0_HSSL4SET1 0x0312 +#define PESDR0_HSSL4SET2 0x0313 +#define PESDR0_HSSL4STS 0x0314 +#define PESDR0_HSSL5SET1 0x0315 +#define PESDR0_HSSL5SET2 0x0316 +#define PESDR0_HSSL5STS 0x0317 +#define PESDR0_HSSL6SET1 0x0318 +#define PESDR0_HSSL6SET2 0x0319 +#define PESDR0_HSSL6STS 0x031a +#define PESDR0_HSSL7SET1 0x031b +#define PESDR0_HSSL7SET2 0x031c +#define PESDR0_HSSL7STS 0x031d +#define PESDR0_HSSCTLSET 0x031e +#define PESDR0_LANE_ABCD 0x031f +#define PESDR0_LANE_EFGH 0x0320 + +#define PESDR1_UTLSET1 0x0340 +#define PESDR1_UTLSET2 0x0341 +#define PESDR1_DLPSET 0x0342 +#define PESDR1_LOOP 0x0343 +#define PESDR1_RCSSET 0x0344 +#define PESDR1_RCSSTS 0x0345 +#define PESDR1_HSSL0SET1 0x0346 +#define PESDR1_HSSL0SET2 0x0347 +#define PESDR1_HSSL0STS 0x0348 +#define PESDR1_HSSL1SET1 0x0349 +#define PESDR1_HSSL1SET2 0x034a +#define PESDR1_HSSL1STS 0x034b +#define PESDR1_HSSL2SET1 0x034c +#define PESDR1_HSSL2SET2 0x034d +#define PESDR1_HSSL2STS 0x034e +#define PESDR1_HSSL3SET1 0x034f +#define PESDR1_HSSL3SET2 0x0350 +#define PESDR1_HSSL3STS 0x0351 +#define PESDR1_HSSCTLSET 0x0352 +#define PESDR1_LANE_ABCD 0x0353 + +#define PESDR2_UTLSET1 0x0370 +#define PESDR2_UTLSET2 0x0371 +#define PESDR2_DLPSET 0x0372 +#define PESDR2_LOOP 0x0373 +#define PESDR2_RCSSET 0x0374 +#define PESDR2_RCSSTS 0x0375 +#define PESDR2_HSSL0SET1 0x0376 +#define PESDR2_HSSL0SET2 0x0377 +#define PESDR2_HSSL0STS 0x0378 +#define PESDR2_HSSL1SET1 0x0379 +#define PESDR2_HSSL1SET2 0x037a +#define PESDR2_HSSL1STS 0x037b +#define PESDR2_HSSL2SET1 0x037c +#define PESDR2_HSSL2SET2 0x037d +#define PESDR2_HSSL2STS 0x037e +#define PESDR2_HSSL3SET1 0x037f +#define PESDR2_HSSL3SET2 0x0380 +#define PESDR2_HSSL3STS 0x0381 +#define PESDR2_HSSCTLSET 0x0382 +#define PESDR2_LANE_ABCD 0x0383 + +/* + * UTL register offsets + */ +#define PEUTL_PBBSZ 0x20 +#define PEUTL_OPDBSZ 0x68 +#define PEUTL_IPHBSZ 0x70 +#define PEUTL_IPDBSZ 0x78 +#define PEUTL_OUTTR 0x90 +#define PEUTL_INTR 0x98 +#define PEUTL_PCTL 0xa0 +#define PEUTL_RCIRQEN 0xb8 + +/* + * Config space register offsets + */ +#define PECFG_BAR0LMPA 0x210 +#define PECFG_BAR0HMPA 0x214 +#define PECFG_PIMEN 0x33c +#define PECFG_PIM0LAL 0x340 +#define PECFG_PIM0LAH 0x344 +#define PECFG_POM0LAL 0x380 +#define PECFG_POM0LAH 0x384 + +int ppc440spe_init_pcie(void); +int ppc440spe_init_pcie_rootport(int port); +void ppc440spe_setup_pcie(struct pci_controller *hose, int port); + +#endif /* __PPC_SYSLIB_PPC440SPE_PCIE_H */ diff --git a/arch/ppc/syslib/ppc4xx_pic.c b/arch/ppc/syslib/ppc4xx_pic.c index 0b435633a0d..aa4165144ec 100644 --- a/arch/ppc/syslib/ppc4xx_pic.c +++ b/arch/ppc/syslib/ppc4xx_pic.c @@ -38,6 +38,7 @@ extern unsigned char ppc4xx_uic_ext_irq_cfg[] __attribute__ ((weak)); #define IRQ_MASK_UICx(irq) (1 << (31 - ((irq) & 0x1f))) #define IRQ_MASK_UIC1(irq) IRQ_MASK_UICx(irq) #define IRQ_MASK_UIC2(irq) IRQ_MASK_UICx(irq) +#define IRQ_MASK_UIC3(irq) IRQ_MASK_UICx(irq) #define UIC_HANDLERS(n) \ static void ppc4xx_uic##n##_enable(unsigned int irq) \ @@ -88,7 +89,38 @@ static void ppc4xx_uic##n##_end(unsigned int irq) \ .end = ppc4xx_uic##n##_end, \ } \ -#if NR_UICS == 3 +#if NR_UICS == 4 +#define ACK_UIC0_PARENT +#define ACK_UIC1_PARENT mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC); +#define ACK_UIC2_PARENT mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC2NC); +#define ACK_UIC3_PARENT mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC3NC); +UIC_HANDLERS(0); +UIC_HANDLERS(1); +UIC_HANDLERS(2); +UIC_HANDLERS(3); + +static int ppc4xx_pic_get_irq(struct pt_regs *regs) +{ + u32 uic0 = mfdcr(DCRN_UIC_MSR(UIC0)); + if (uic0 & UIC0_UIC1NC) + return 64 - ffs(mfdcr(DCRN_UIC_MSR(UIC1))); + else if (uic0 & UIC0_UIC2NC) + return 96 - ffs(mfdcr(DCRN_UIC_MSR(UIC2))); + else if (uic0 & UIC0_UIC3NC) + return 128 - ffs(mfdcr(DCRN_UIC_MSR(UIC3))); + else + return uic0 ? 32 - ffs(uic0) : -1; +} + +static void __init ppc4xx_pic_impl_init(void) +{ + /* Enable cascade interrupts in UIC0 */ + ppc_cached_irq_mask[0] |= UIC0_UIC1NC | UIC0_UIC2NC | UIC0_UIC3NC; + mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC | UIC0_UIC2NC | UIC0_UIC3NC); + mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[0]); +} + +#elif NR_UICS == 3 #define ACK_UIC0_PARENT mtdcr(DCRN_UIC_SR(UICB), UICB_UIC0NC); #define ACK_UIC1_PARENT mtdcr(DCRN_UIC_SR(UICB), UICB_UIC1NC); #define ACK_UIC2_PARENT mtdcr(DCRN_UIC_SR(UICB), UICB_UIC2NC); @@ -170,6 +202,9 @@ static struct ppc4xx_uic_impl { { .decl = DECLARE_UIC(1), .base = UIC1 }, #if NR_UICS > 2 { .decl = DECLARE_UIC(2), .base = UIC2 }, +#if NR_UICS > 3 + { .decl = DECLARE_UIC(3), .base = UIC3 }, +#endif #endif #endif }; diff --git a/include/asm-ppc/ibm44x.h b/include/asm-ppc/ibm44x.h index 0c2ba03a1d4..f835066fb3c 100644 --- a/include/asm-ppc/ibm44x.h +++ b/include/asm-ppc/ibm44x.h @@ -41,6 +41,9 @@ #if defined(CONFIG_440SP) #define UART0_PHYS_ERPN 1 #define UART0_PHYS_IO_BASE 0xf0000200 +#elif defined(CONFIG_440SPE) +#define UART0_PHYS_ERPN 4 +#define UART0_PHYS_IO_BASE 0xf0000200 #elif defined(CONFIG_440EP) #define UART0_PHYS_IO_BASE 0xe0000000 #else @@ -61,6 +64,11 @@ #define PPC44x_PCICFG_PAGE 0x0000000900000000ULL #define PPC44x_PCIIO_PAGE PPC44x_PCICFG_PAGE #define PPC44x_PCIMEM_PAGE 0x0000000a00000000ULL +#elif defined(CONFIG_440SPE) +#define PPC44x_IO_PAGE 0x0000000400000000ULL +#define PPC44x_PCICFG_PAGE 0x0000000c00000000ULL +#define PPC44x_PCIIO_PAGE PPC44x_PCICFG_PAGE +#define PPC44x_PCIMEM_PAGE 0x0000000d00000000ULL #elif defined(CONFIG_440EP) #define PPC44x_IO_PAGE 0x0000000000000000ULL #define PPC44x_PCICFG_PAGE 0x0000000000000000ULL @@ -76,7 +84,7 @@ /* * 36-bit trap ranges */ -#if defined(CONFIG_440SP) +#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) #define PPC44x_IO_LO 0xf0000000UL #define PPC44x_IO_HI 0xf0000fffUL #define PPC44x_PCI0CFG_LO 0x0ec00000UL @@ -114,7 +122,7 @@ */ -/* CPRs (440GX and 440SP) */ +/* CPRs (440GX and 440SP/440SPe) */ #define DCRN_CPR_CONFIG_ADDR 0xc #define DCRN_CPR_CONFIG_DATA 0xd @@ -135,7 +143,7 @@ mtdcr(DCRN_CPR_CONFIG_ADDR, offset); \ mtdcr(DCRN_CPR_CONFIG_DATA, data);}) -/* SDRs (440GX and 440SP) */ +/* SDRs (440GX and 440SP/440SPe) */ #define DCRN_SDR_CONFIG_ADDR 0xe #define DCRN_SDR_CONFIG_DATA 0xf #define DCRN_SDR_PFC0 0x4100 @@ -185,7 +193,7 @@ mtdcr(DCRN_SDR_CONFIG_ADDR, offset); \ mtdcr(DCRN_SDR_CONFIG_DATA,data);}) -/* DMA (excluding 440SP) */ +/* DMA (excluding 440SP/440SPe) */ #define DCRN_DMA0_BASE 0x100 #define DCRN_DMA1_BASE 0x108 #define DCRN_DMA2_BASE 0x110 @@ -205,12 +213,20 @@ /* UIC */ #define DCRN_UIC0_BASE 0xc0 #define DCRN_UIC1_BASE 0xd0 -#define DCRN_UIC2_BASE 0x210 -#define DCRN_UICB_BASE 0x200 #define UIC0 DCRN_UIC0_BASE #define UIC1 DCRN_UIC1_BASE + +#ifdef CONFIG_440SPE +#define DCRN_UIC2_BASE 0xe0 +#define DCRN_UIC3_BASE 0xf0 +#define UIC2 DCRN_UIC2_BASE +#define UIC3 DCRN_UIC3_BASE +#else +#define DCRN_UIC2_BASE 0x210 +#define DCRN_UICB_BASE 0x200 #define UIC2 DCRN_UIC2_BASE #define UICB DCRN_UICB_BASE +#endif #define DCRN_UIC_SR(base) (base + 0x0) #define DCRN_UIC_ER(base) (base + 0x2) @@ -223,6 +239,12 @@ #define UIC0_UIC1NC 0x00000002 +#ifdef CONFIG_440SPE +#define UIC0_UIC1NC 0x00000002 +#define UIC0_UIC2NC 0x00200000 +#define UIC0_UIC3NC 0x00008000 +#endif + #define UICB_UIC0NC 0x40000000 #define UICB_UIC1NC 0x10000000 #define UICB_UIC2NC 0x04000000 @@ -302,8 +324,8 @@ #define MALOBISR_CH0 0x80000000 /* EOB channel 1 bit */ #define MALOBISR_CH2 0x40000000 /* EOB channel 2 bit */ -#if defined(CONFIG_440SP) -/* 440SP PLB Arbiter DCRs */ +#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) +/* 440SP/440SPe PLB Arbiter DCRs */ #define DCRN_PLB_REVID 0x080 /* PLB Revision ID */ #define DCRN_PLB_CCR 0x088 /* PLB Crossbar Control */ @@ -430,9 +452,13 @@ #define PPC44x_MEM_SIZE_1G 0x40000000 #define PPC44x_MEM_SIZE_2G 0x80000000 -/* 440SP memory controller DCRs */ +/* 440SP/440SPe memory controller DCRs */ #define DCRN_MQ0_BS0BAS 0x40 -#define DCRN_MQ0_BS1BAS 0x41 +#if defined(CONFIG_440SP) +#define MQ0_NUM_BANKS 2 +#elif defined(CONFIG_440SPE) +#define MQ0_NUM_BANKS 4 +#endif #define MQ0_CONFIG_SIZE_MASK 0x0000fff0 #define MQ0_CONFIG_SIZE_8M 0x0000ffc0 @@ -444,8 +470,9 @@ #define MQ0_CONFIG_SIZE_512M 0x0000f000 #define MQ0_CONFIG_SIZE_1G 0x0000e000 #define MQ0_CONFIG_SIZE_2G 0x0000c000 +#define MQ0_CONFIG_SIZE_4G 0x00008000 -/* Internal SRAM Controller 440GX/440SP */ +/* Internal SRAM Controller 440GX/440SP/440SPe */ #define DCRN_SRAM0_BASE 0x000 #define DCRN_SRAM0_SB0CR (DCRN_SRAM0_BASE + 0x020) @@ -469,7 +496,7 @@ #define DCRN_SRAM0_DPC (DCRN_SRAM0_BASE + 0x02a) #define SRAM_DPC_ENABLE 0x80000000 -/* L2 Cache Controller 440GX/440SP */ +/* L2 Cache Controller 440GX/440SP/440SPe */ #define DCRN_L2C0_CFG 0x030 #define L2C_CFG_L2M 0x80000000 #define L2C_CFG_ICU 0x40000000 @@ -633,8 +660,10 @@ #define IIC_CLOCK 50 #undef NR_UICS -#ifdef CONFIG_440GX +#if defined(CONFIG_440GX) #define NR_UICS 3 +#elif defined(CONFIG_440SPE) +#define NR_UICS 4 #else #define NR_UICS 2 #endif -- cgit v1.2.3 From 90eb2665841d7b444602736e2141a01c948f75b1 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 7 Nov 2005 00:58:14 -0800 Subject: [PATCH] ppc32: Add Yucca (440SPe eval board) platform Add support for AMCC PowerPC 440SPe "Yucca" eval board platform. Signed-off-by: Roland Dreier Cc: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/boot/simple/Makefile | 6 + arch/ppc/platforms/4xx/Kconfig | 11 +- arch/ppc/platforms/4xx/Makefile | 1 + arch/ppc/platforms/4xx/yucca.c | 395 ++++++++++++++++++++++++++++++++++++++++ arch/ppc/platforms/4xx/yucca.h | 111 +++++++++++ arch/ppc/syslib/Makefile | 1 + include/asm-ppc/ibm4xx.h | 4 + 7 files changed, 527 insertions(+), 2 deletions(-) create mode 100644 arch/ppc/platforms/4xx/yucca.c create mode 100644 arch/ppc/platforms/4xx/yucca.h diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile index b7bd8f61a4a..ff0904ee889 100644 --- a/arch/ppc/boot/simple/Makefile +++ b/arch/ppc/boot/simple/Makefile @@ -79,6 +79,12 @@ zimageinitrd-$(CONFIG_LUAN) := zImage.initrd-TREE entrypoint-$(CONFIG_LUAN) := 0x01000000 extra.o-$(CONFIG_LUAN) := pibs.o + zimage-$(CONFIG_YUCCA) := zImage-TREE +zimageinitrd-$(CONFIG_YUCCA) := zImage.initrd-TREE + end-$(CONFIG_YUCCA) := yucca + entrypoint-$(CONFIG_YUCCA) := 0x01000000 + extra.o-$(CONFIG_YUCCA) := pibs.o + zimage-$(CONFIG_OCOTEA) := zImage-TREE zimageinitrd-$(CONFIG_OCOTEA) := zImage.initrd-TREE end-$(CONFIG_OCOTEA) := ocotea diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig index 108d5a730f8..e70e4c6ec78 100644 --- a/arch/ppc/platforms/4xx/Kconfig +++ b/arch/ppc/platforms/4xx/Kconfig @@ -82,6 +82,12 @@ config LUAN help This option enables support for the IBM PPC440SP evaluation board. +config YUCCA + bool "Yucca" + select WANT_EARLY_SERIAL + help + This option enables support for the AMCC PPC440SPe evaluation board. + config OCOTEA bool "Ocotea" select WANT_EARLY_SERIAL @@ -126,7 +132,8 @@ config 440SP config 440SPE bool - default n + depends on YUCCA + default y config 440 bool @@ -162,7 +169,7 @@ config BOOKE config IBM_OCP bool - depends on ASH || BAMBOO || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT + depends on ASH || BAMBOO || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || YUCCA || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT default y config XILINX_OCP diff --git a/arch/ppc/platforms/4xx/Makefile b/arch/ppc/platforms/4xx/Makefile index 694accdb59f..c9bb6117095 100644 --- a/arch/ppc/platforms/4xx/Makefile +++ b/arch/ppc/platforms/4xx/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_EBONY) += ebony.o obj-$(CONFIG_EP405) += ep405.o obj-$(CONFIG_BUBINGA) += bubinga.o obj-$(CONFIG_LUAN) += luan.o +obj-$(CONFIG_YUCCA) += yucca.o obj-$(CONFIG_OCOTEA) += ocotea.o obj-$(CONFIG_REDWOOD_5) += redwood5.o obj-$(CONFIG_REDWOOD_6) += redwood6.o diff --git a/arch/ppc/platforms/4xx/yucca.c b/arch/ppc/platforms/4xx/yucca.c new file mode 100644 index 00000000000..e60f4bd437e --- /dev/null +++ b/arch/ppc/platforms/4xx/yucca.c @@ -0,0 +1,395 @@ +/* + * arch/ppc/platforms/4xx/yucca.c + * + * Yucca board specific routines + * + * Roland Dreier (based on luan.c by Matt Porter) + * + * Copyright 2004-2005 MontaVista Software Inc. + * Copyright (c) 2005 Cisco Systems. All rights reserved. + * + * 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 + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +extern bd_t __res; + +static struct ibm44x_clocks clocks __initdata; + +static void __init +yucca_calibrate_decr(void) +{ + unsigned int freq; + + if (mfspr(SPRN_CCR1) & CCR1_TCS) + freq = YUCCA_TMR_CLK; + else + freq = clocks.cpu; + + ibm44x_calibrate_decr(freq); +} + +static int +yucca_show_cpuinfo(struct seq_file *m) +{ + seq_printf(m, "vendor\t\t: AMCC\n"); + seq_printf(m, "machine\t\t: PPC440SPe EVB (Yucca)\n"); + + return 0; +} + +static enum { + HOSE_UNKNOWN, + HOSE_PCIX, + HOSE_PCIE0, + HOSE_PCIE1, + HOSE_PCIE2 +} hose_type[4]; + +static inline int +yucca_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); + + if (hose_type[hose->index] == HOSE_PCIX) { + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + { 81, -1, -1, -1 }, /* IDSEL 1 - PCIX0 Slot 0 */ + }; + const long min_idsel = 1, max_idsel = 1, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; + } else if (hose_type[hose->index] == HOSE_PCIE0) { + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + { 96, 97, 98, 99 }, + }; + const long min_idsel = 1, max_idsel = 1, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; + } else if (hose_type[hose->index] == HOSE_PCIE1) { + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + { 100, 101, 102, 103 }, + }; + const long min_idsel = 1, max_idsel = 1, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; + } else if (hose_type[hose->index] == HOSE_PCIE2) { + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + { 104, 105, 106, 107 }, + }; + const long min_idsel = 1, max_idsel = 1, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; + } + return -1; +} + +static void __init yucca_set_emacdata(void) +{ + struct ocp_def *def; + struct ocp_func_emac_data *emacdata; + + /* Set phy_map, phy_mode, and mac_addr for the EMAC */ + def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 0); + emacdata = def->additions; + emacdata->phy_map = 0x00000001; /* Skip 0x00 */ + emacdata->phy_mode = PHY_MODE_GMII; + memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6); +} + +static int __init yucca_pcie_card_present(int port) +{ + void __iomem *pcie_fpga_base; + u16 reg; + + pcie_fpga_base = ioremap64(YUCCA_FPGA_REG_BASE, YUCCA_FPGA_REG_SIZE); + reg = in_be16(pcie_fpga_base + FPGA_REG1C); + iounmap(pcie_fpga_base); + + switch(port) { + case 0: return !(reg & FPGA_REG1C_PE0_PRSNT); + case 1: return !(reg & FPGA_REG1C_PE1_PRSNT); + case 2: return !(reg & FPGA_REG1C_PE2_PRSNT); + default: return 0; + } +} + +/* + * For the given slot, set rootpoint mode, send power to the slot, + * turn on the green LED and turn off the yellow LED, enable the clock + * and turn off reset. + */ +static void __init yucca_setup_pcie_fpga_rootpoint(int port) +{ + void __iomem *pcie_reg_fpga_base; + u16 power, clock, green_led, yellow_led, reset_off, rootpoint, endpoint; + + pcie_reg_fpga_base = ioremap64(YUCCA_FPGA_REG_BASE, YUCCA_FPGA_REG_SIZE); + + switch(port) { + case 0: + rootpoint = FPGA_REG1C_PE0_ROOTPOINT; + endpoint = 0; + power = FPGA_REG1A_PE0_PWRON; + green_led = FPGA_REG1A_PE0_GLED; + clock = FPGA_REG1A_PE0_REFCLK_ENABLE; + yellow_led = FPGA_REG1A_PE0_YLED; + reset_off = FPGA_REG1C_PE0_PERST; + break; + case 1: + rootpoint = 0; + endpoint = FPGA_REG1C_PE1_ENDPOINT; + power = FPGA_REG1A_PE1_PWRON; + green_led = FPGA_REG1A_PE1_GLED; + clock = FPGA_REG1A_PE1_REFCLK_ENABLE; + yellow_led = FPGA_REG1A_PE1_YLED; + reset_off = FPGA_REG1C_PE1_PERST; + break; + case 2: + rootpoint = 0; + endpoint = FPGA_REG1C_PE2_ENDPOINT; + power = FPGA_REG1A_PE2_PWRON; + green_led = FPGA_REG1A_PE2_GLED; + clock = FPGA_REG1A_PE2_REFCLK_ENABLE; + yellow_led = FPGA_REG1A_PE2_YLED; + reset_off = FPGA_REG1C_PE2_PERST; + break; + + default: + return; + } + + out_be16(pcie_reg_fpga_base + FPGA_REG1A, + ~(power | clock | green_led) & + (yellow_led | in_be16(pcie_reg_fpga_base + FPGA_REG1A))); + out_be16(pcie_reg_fpga_base + FPGA_REG1C, + ~(endpoint | reset_off) & + (rootpoint | in_be16(pcie_reg_fpga_base + FPGA_REG1C))); + + /* + * Leave device in reset for a while after powering on the + * slot to give it a chance to initialize. + */ + mdelay(250); + + out_be16(pcie_reg_fpga_base + FPGA_REG1C, + reset_off | in_be16(pcie_reg_fpga_base + FPGA_REG1C)); + + iounmap(pcie_reg_fpga_base); +} + +static void __init +yucca_setup_hoses(void) +{ + struct pci_controller *hose; + char name[20]; + int i; + + if (0 && ppc440spe_init_pcie()) { + printk(KERN_WARNING "PPC440SPe PCI Express initialization failed\n"); + return; + } + + for (i = 0; i <= 2; ++i) { + if (!yucca_pcie_card_present(i)) + continue; + + printk(KERN_INFO "PCIE%d: card present\n", i); + yucca_setup_pcie_fpga_rootpoint(i); + if (ppc440spe_init_pcie_rootport(i)) { + printk(KERN_WARNING "PCIE%d: initialization failed\n", i); + continue; + } + + hose = pcibios_alloc_controller(); + if (!hose) + return; + + sprintf(name, "PCIE%d host bridge", i); + pci_init_resource(&hose->io_resource, + YUCCA_PCIX_LOWER_IO, + YUCCA_PCIX_UPPER_IO, + IORESOURCE_IO, + name); + + hose->mem_space.start = YUCCA_PCIE_LOWER_MEM + + i * YUCCA_PCIE_MEM_SIZE; + hose->mem_space.end = hose->mem_space.start + + YUCCA_PCIE_MEM_SIZE - 1; + + pci_init_resource(&hose->mem_resources[0], + hose->mem_space.start, + hose->mem_space.end, + IORESOURCE_MEM, + name); + + hose->first_busno = 0; + hose->last_busno = 15; + hose_type[hose->index] = HOSE_PCIE0 + i; + + ppc440spe_setup_pcie(hose, i); + hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); + } + + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = yucca_map_irq; +} + +TODC_ALLOC(); + +static void __init +yucca_early_serial_map(void) +{ + struct uart_port port; + + /* Setup ioremapped serial port access */ + memset(&port, 0, sizeof(port)); + port.membase = ioremap64(PPC440SPE_UART0_ADDR, 8); + port.irq = UART0_INT; + port.uartclk = clocks.uart0; + port.regshift = 0; + port.iotype = SERIAL_IO_MEM; + port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + port.line = 0; + + if (early_serial_setup(&port) != 0) { + printk("Early serial init of port 0 failed\n"); + } + + port.membase = ioremap64(PPC440SPE_UART1_ADDR, 8); + port.irq = UART1_INT; + port.uartclk = clocks.uart1; + port.line = 1; + + if (early_serial_setup(&port) != 0) { + printk("Early serial init of port 1 failed\n"); + } + + port.membase = ioremap64(PPC440SPE_UART2_ADDR, 8); + port.irq = UART2_INT; + port.uartclk = BASE_BAUD; + port.line = 2; + + if (early_serial_setup(&port) != 0) { + printk("Early serial init of port 2 failed\n"); + } +} + +static void __init +yucca_setup_arch(void) +{ + yucca_set_emacdata(); + +#if !defined(CONFIG_BDI_SWITCH) + /* + * The Abatron BDI JTAG debugger does not tolerate others + * mucking with the debug registers. + */ + mtspr(SPRN_DBCR0, (DBCR0_TDE | DBCR0_IDM)); +#endif + + /* + * Determine various clocks. + * To be completely correct we should get SysClk + * from FPGA, because it can be changed by on-board switches + * --ebs + */ + /* 440GX and 440SPe clocking is the same - rd */ + ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200); + ocp_sys_info.opb_bus_freq = clocks.opb; + + /* init to some ~sane value until calibrate_delay() runs */ + loops_per_jiffy = 50000000/HZ; + + /* Setup PCIXn host bridges */ + yucca_setup_hoses(); + +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start) + ROOT_DEV = Root_RAM0; + else +#endif +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif + + yucca_early_serial_map(); + + /* Identify the system */ + printk("Yucca port (Roland Dreier )\n"); +} + +void __init platform_init(unsigned long r3, unsigned long r4, + unsigned long r5, unsigned long r6, unsigned long r7) +{ + ibm44x_platform_init(r3, r4, r5, r6, r7); + + ppc_md.setup_arch = yucca_setup_arch; + ppc_md.show_cpuinfo = yucca_show_cpuinfo; + ppc_md.find_end_of_memory = ibm440sp_find_end_of_memory; + ppc_md.get_irq = NULL; /* Set in ppc4xx_pic_init() */ + + ppc_md.calibrate_decr = yucca_calibrate_decr; +#ifdef CONFIG_KGDB + ppc_md.early_serial_map = yucca_early_serial_map; +#endif +} diff --git a/arch/ppc/platforms/4xx/yucca.h b/arch/ppc/platforms/4xx/yucca.h new file mode 100644 index 00000000000..01a4afea151 --- /dev/null +++ b/arch/ppc/platforms/4xx/yucca.h @@ -0,0 +1,111 @@ +/* + * arch/ppc/platforms/4xx/yucca.h + * + * Yucca board definitions + * + * Roland Dreier (based on luan.h by Matt Porter) + * + * Copyright 2004-2005 MontaVista Software Inc. + * Copyright (c) 2005 Cisco Systems. All rights reserved. + * + * 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 + * option) any later version. + * + */ + +#ifdef __KERNEL__ +#ifndef __ASM_YUCCA_H__ +#define __ASM_YUCCA_H__ + +#include +#include + +/* F/W TLB mapping used in bootloader glue to reset EMAC */ +#define PPC44x_EMAC0_MR0 0xa0000800 + +/* Location of MAC addresses in PIBS image */ +#define PIBS_FLASH_BASE 0xffe00000 +#define PIBS_MAC_BASE (PIBS_FLASH_BASE+0x1b0400) + +/* External timer clock frequency */ +#define YUCCA_TMR_CLK 25000000 + +/* + * FPGA registers + */ +#define YUCCA_FPGA_REG_BASE 0x00000004e2000000ULL +#define YUCCA_FPGA_REG_SIZE 0x24 + +#define FPGA_REG1A 0x1a + +#define FPGA_REG1A_PE0_GLED 0x8000 +#define FPGA_REG1A_PE1_GLED 0x4000 +#define FPGA_REG1A_PE2_GLED 0x2000 +#define FPGA_REG1A_PE0_YLED 0x1000 +#define FPGA_REG1A_PE1_YLED 0x0800 +#define FPGA_REG1A_PE2_YLED 0x0400 +#define FPGA_REG1A_PE0_PWRON 0x0200 +#define FPGA_REG1A_PE1_PWRON 0x0100 +#define FPGA_REG1A_PE2_PWRON 0x0080 +#define FPGA_REG1A_PE0_REFCLK_ENABLE 0x0040 +#define FPGA_REG1A_PE1_REFCLK_ENABLE 0x0020 +#define FPGA_REG1A_PE2_REFCLK_ENABLE 0x0010 +#define FPGA_REG1A_PE_SPREAD0 0x0008 +#define FPGA_REG1A_PE_SPREAD1 0x0004 +#define FPGA_REG1A_PE_SELSOURCE_0 0x0002 +#define FPGA_REG1A_PE_SELSOURCE_1 0x0001 + +#define FPGA_REG1C 0x1c + +#define FPGA_REG1C_PE0_ROOTPOINT 0x8000 +#define FPGA_REG1C_PE1_ENDPOINT 0x4000 +#define FPGA_REG1C_PE2_ENDPOINT 0x2000 +#define FPGA_REG1C_PE0_PRSNT 0x1000 +#define FPGA_REG1C_PE1_PRSNT 0x0800 +#define FPGA_REG1C_PE2_PRSNT 0x0400 +#define FPGA_REG1C_PE0_WAKE 0x0080 +#define FPGA_REG1C_PE1_WAKE 0x0040 +#define FPGA_REG1C_PE2_WAKE 0x0020 +#define FPGA_REG1C_PE0_PERST 0x0010 +#define FPGA_REG1C_PE1_PERST 0x0008 +#define FPGA_REG1C_PE2_PERST 0x0004 + +/* + * Serial port defines + */ +#define RS_TABLE_SIZE 3 + +/* PIBS defined UART mappings, used before early_serial_setup */ +#define UART0_IO_BASE 0xa0000200 +#define UART1_IO_BASE 0xa0000300 +#define UART2_IO_BASE 0xa0000600 + +#define BASE_BAUD 11059200 +#define STD_UART_OP(num) \ + { 0, BASE_BAUD, 0, UART##num##_INT, \ + (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ + iomem_base: (void*)UART##num##_IO_BASE, \ + io_type: SERIAL_IO_MEM}, + +#define SERIAL_PORT_DFNS \ + STD_UART_OP(0) \ + STD_UART_OP(1) \ + STD_UART_OP(2) + +/* PCI support */ +#define YUCCA_PCIX_LOWER_IO 0x00000000 +#define YUCCA_PCIX_UPPER_IO 0x0000ffff +#define YUCCA_PCIX_LOWER_MEM 0x80000000 +#define YUCCA_PCIX_UPPER_MEM 0x8fffffff +#define YUCCA_PCIE_LOWER_MEM 0x90000000 +#define YUCCA_PCIE_MEM_SIZE 0x10000000 + +#define YUCCA_PCIX_MEM_SIZE 0x10000000 +#define YUCCA_PCIX_MEM_OFFSET 0x00000000 +#define YUCCA_PCIE_MEM_SIZE 0x10000000 +#define YUCCA_PCIE_MEM_OFFSET 0x00000000 + +#endif /* __ASM_YUCCA_H__ */ +#endif /* __KERNEL__ */ diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index 13dff1e51f1..dcd168f9a7a 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_GT64260) += gt64260_pic.o obj-$(CONFIG_LOPEC) += pci_auto.o todc_time.o obj-$(CONFIG_HDPU) += pci_auto.o obj-$(CONFIG_LUAN) += pci_auto.o todc_time.o +obj-$(CONFIG_YUCCA) += pci_auto.o todc_time.o obj-$(CONFIG_KATANA) += pci_auto.o obj-$(CONFIG_MV64360) += mv64360_pic.o obj-$(CONFIG_MV64X60) += mv64x60.o mv64x60_win.o diff --git a/include/asm-ppc/ibm4xx.h b/include/asm-ppc/ibm4xx.h index e992369cb8e..6c28ae7807f 100644 --- a/include/asm-ppc/ibm4xx.h +++ b/include/asm-ppc/ibm4xx.h @@ -97,6 +97,10 @@ void ppc4xx_init(unsigned long r3, unsigned long r4, unsigned long r5, #include #endif +#if defined(CONFIG_YUCCA) +#include +#endif + #if defined(CONFIG_OCOTEA) #include #endif -- cgit v1.2.3 From 3e9e7c1d0b7a36fb8affb973a054c5098e27baa8 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 7 Nov 2005 00:58:15 -0800 Subject: [PATCH] ppc32: cleanup AMCC PPC40x eval boards to support U-Boot Cleanup PPC40x eval boards (bubinga, walnut and sycamore) to support U-Boot as bootloader. The OpenBIOS bd_info struct is not used in the kernel anymore (only U-Boot now). uImage (U-Boot) tested on walnut, sycamore and bubinga zImage (OpenBIOS) tested on sycamore, bubinga and ebony Signed-off-by: Stefan Roese Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/boot/simple/Makefile | 21 +++++++- arch/ppc/boot/simple/misc.c | 16 ++++-- arch/ppc/boot/simple/openbios.c | 106 +++++++++++++++++++++++++++++++++++--- arch/ppc/platforms/4xx/Kconfig | 2 +- arch/ppc/platforms/4xx/bubinga.c | 2 +- arch/ppc/platforms/4xx/bubinga.h | 64 ++++++++++------------- arch/ppc/platforms/4xx/ebony.h | 4 +- arch/ppc/platforms/4xx/sycamore.c | 7 +-- arch/ppc/platforms/4xx/sycamore.h | 67 ++++++++++-------------- arch/ppc/platforms/4xx/walnut.c | 2 +- arch/ppc/platforms/4xx/walnut.h | 67 +++++++++--------------- include/asm-ppc/ibm_ocp.h | 19 +++++-- include/asm-ppc/ppcboot.h | 6 ++- 13 files changed, 237 insertions(+), 146 deletions(-) diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile index ff0904ee889..82df88b01bb 100644 --- a/arch/ppc/boot/simple/Makefile +++ b/arch/ppc/boot/simple/Makefile @@ -67,6 +67,12 @@ zimageinitrd-$(CONFIG_BAMBOO) := zImage.initrd-TREE entrypoint-$(CONFIG_BAMBOO) := 0x01000000 extra.o-$(CONFIG_BAMBOO) := pibs.o + zimage-$(CONFIG_BUBINGA) := zImage-TREE +zimageinitrd-$(CONFIG_BUBINGA) := zImage.initrd-TREE + end-$(CONFIG_BUBINGA) := bubinga + entrypoint-$(CONFIG_BUBINGA) := 0x01000000 + extra.o-$(CONFIG_BUBINGA) := openbios.o + zimage-$(CONFIG_EBONY) := zImage-TREE zimageinitrd-$(CONFIG_EBONY) := zImage.initrd-TREE end-$(CONFIG_EBONY) := ebony @@ -91,6 +97,18 @@ zimageinitrd-$(CONFIG_OCOTEA) := zImage.initrd-TREE entrypoint-$(CONFIG_OCOTEA) := 0x01000000 extra.o-$(CONFIG_OCOTEA) := pibs.o + zimage-$(CONFIG_SYCAMORE) := zImage-TREE +zimageinitrd-$(CONFIG_SYCAMORE) := zImage.initrd-TREE + end-$(CONFIG_SYCAMORE) := sycamore + entrypoint-$(CONFIG_SYCAMORE) := 0x01000000 + extra.o-$(CONFIG_SYCAMORE) := openbios.o + + zimage-$(CONFIG_WALNUT) := zImage-TREE +zimageinitrd-$(CONFIG_WALNUT) := zImage.initrd-TREE + end-$(CONFIG_WALNUT) := walnut + entrypoint-$(CONFIG_WALNUT) := 0x01000000 + extra.o-$(CONFIG_WALNUT) := openbios.o + extra.o-$(CONFIG_EV64260) := misc-ev64260.o end-$(CONFIG_EV64260) := ev64260 cacheflag-$(CONFIG_EV64260) := -include $(clear_L2_L3) @@ -168,7 +186,8 @@ OBJCOPY_ARGS := -O elf32-powerpc # head.o and relocate.o must be at the start. boot-y := head.o relocate.o $(extra.o-y) $(misc-y) -boot-$(CONFIG_40x) += embed_config.o +boot-$(CONFIG_REDWOOD_5) += embed_config.o +boot-$(CONFIG_REDWOOD_6) += embed_config.o boot-$(CONFIG_8xx) += embed_config.o boot-$(CONFIG_8260) += embed_config.o boot-$(CONFIG_BSEIP) += iic.o diff --git a/arch/ppc/boot/simple/misc.c b/arch/ppc/boot/simple/misc.c index e02de5b467a..f415d6c6236 100644 --- a/arch/ppc/boot/simple/misc.c +++ b/arch/ppc/boot/simple/misc.c @@ -23,7 +23,7 @@ #include #include #include -#ifdef CONFIG_44x +#ifdef CONFIG_4xx #include #endif #include @@ -88,6 +88,14 @@ get_mem_size(void) return 0; } +#if defined(CONFIG_40x) +#define PPC4xx_EMAC0_MR0 EMAC0_BASE +#endif + +#if defined(CONFIG_44x) && defined(PPC44x_EMAC0_MR0) +#define PPC4xx_EMAC0_MR0 PPC44x_EMAC0_MR0 +#endif + struct bi_record * decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum) { @@ -103,13 +111,13 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum) com_port = serial_init(0, NULL); #endif -#if defined(CONFIG_44x) && defined(PPC44x_EMAC0_MR0) +#if defined(PPC4xx_EMAC0_MR0) /* Reset MAL */ mtdcr(DCRN_MALCR(DCRN_MAL_BASE), MALCR_MMSR); /* Wait for reset */ while (mfdcr(DCRN_MALCR(DCRN_MAL_BASE)) & MALCR_MMSR) {}; /* Reset EMAC */ - *(volatile unsigned long *)PPC44x_EMAC0_MR0 = 0x20000000; + *(volatile unsigned long *)PPC4xx_EMAC0_MR0 = 0x20000000; __asm__ __volatile__("eieio"); #endif @@ -164,7 +172,9 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum) puts(" "); puthex((unsigned long)(&__ramdisk_end));puts("\n"); } +#ifndef CONFIG_40x /* don't overwrite the 40x image located at 0x00400000! */ avail_ram = (char *)0x00400000; +#endif end_avail = (char *)0x00800000; puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" "); puthex((unsigned long)end_avail); puts("\n"); diff --git a/arch/ppc/boot/simple/openbios.c b/arch/ppc/boot/simple/openbios.c index c732b6d70cf..81f11d8b30a 100644 --- a/arch/ppc/boot/simple/openbios.c +++ b/arch/ppc/boot/simple/openbios.c @@ -1,19 +1,43 @@ /* * arch/ppc/boot/simple/openbios.c * - * 2005 (c) SYSGO AG - g.jaeger@sysgo.com + * Copyright (c) 2005 DENX Software Engineering + * Stefan Roese + * + * Based on original work by + * 2005 (c) SYSGO AG - g.jaeger@sysgo.com + * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without * any warranty of any kind, whether express or implied. * - * Derived from arch/ppc/boot/simple/pibs.c (from MontaVista) */ #include #include #include #include -#include +#include +#include +#ifdef CONFIG_40x +#include +#endif + +#if defined(CONFIG_BUBINGA) +#define BOARD_INFO_VECTOR 0xFFF80B50 /* openbios 1.19 moved this vector down - armin */ +#else +#define BOARD_INFO_VECTOR 0xFFFE0B50 +#endif + +#ifdef CONFIG_40x +/* Supply a default Ethernet address for those eval boards that don't + * ship with one. This is an address from the MBX board I have, so + * it is unlikely you will find it on your network. + */ +static ushort def_enet_addr[] = { 0x0800, 0x3e26, 0x1559 }; + +extern unsigned long timebase_period_ns; +#endif /* CONFIG_40x */ extern unsigned long decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum); @@ -23,15 +47,85 @@ extern unsigned long decompress_kernel(unsigned long load_addr, int num_words, bd_t hold_resid_buf __attribute__ ((__section__ (".data.boot"))); bd_t *hold_residual = &hold_resid_buf; +typedef struct openbios_board_info { + unsigned char bi_s_version[4]; /* Version of this structure */ + unsigned char bi_r_version[30]; /* Version of the IBM ROM */ + unsigned int bi_memsize; /* DRAM installed, in bytes */ +#ifdef CONFIG_405EP + unsigned char bi_enetaddr[2][6]; /* Local Ethernet MAC address */ +#else /* CONFIG_405EP */ + unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */ +#endif /* CONFIG_405EP */ + unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */ + unsigned int bi_intfreq; /* Processor speed, in Hz */ + unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ + unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */ +#ifdef CONFIG_405EP + unsigned int bi_opb_busfreq; /* OPB Bus speed, in Hz */ + unsigned int bi_pllouta_freq; /* PLL OUTA speed, in Hz */ +#endif /* CONFIG_405EP */ +} openbios_bd_t; + void * load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, void *ign1, void *ign2) { - decompress_kernel(load_addr, num_words, cksum); +#ifdef CONFIG_40x + openbios_bd_t *openbios_bd = NULL; + openbios_bd_t *(*get_board_info)(void) = + (openbios_bd_t *(*)(void))(*(unsigned long *)BOARD_INFO_VECTOR); + + /* + * On 40x platforms we not only need the MAC-addresses, but also the + * clocks and memsize. Now try to get all values using the OpenBIOS + * "get_board_info()" callback. + */ + if ((openbios_bd = get_board_info()) != NULL) { + /* + * Copy bd_info from OpenBIOS struct into U-Boot struct + * used by kernel + */ + hold_residual->bi_memsize = openbios_bd->bi_memsize; + hold_residual->bi_intfreq = openbios_bd->bi_intfreq; + hold_residual->bi_busfreq = openbios_bd->bi_busfreq; + hold_residual->bi_pci_busfreq = openbios_bd->bi_pci_busfreq; + memcpy(hold_residual->bi_pci_enetaddr, openbios_bd->bi_pci_enetaddr, 6); +#ifdef CONFIG_405EP + memcpy(hold_residual->bi_enetaddr, openbios_bd->bi_enetaddr[0], 6); + memcpy(hold_residual->bi_enet1addr, openbios_bd->bi_enetaddr[1], 6); + hold_residual->bi_opbfreq = openbios_bd->bi_opb_busfreq; + hold_residual->bi_procfreq = openbios_bd->bi_pllouta_freq; +#else /* CONFIG_405EP */ + memcpy(hold_residual->bi_enetaddr, openbios_bd->bi_enetaddr, 6); +#endif /* CONFIG_405EP */ + } else { + /* Hmmm...better try to stuff some defaults. + */ + hold_residual->bi_memsize = 16 * 1024 * 1024; + hold_residual->bi_intfreq = 200000000; + hold_residual->bi_busfreq = 100000000; + hold_residual->bi_pci_busfreq = 66666666; + + /* + * Only supply one mac-address in this fallback + */ + memcpy(hold_residual->bi_enetaddr, (void *)def_enet_addr, 6); +#ifdef CONFIG_405EP + hold_residual->bi_opbfreq = 50000000; + hold_residual->bi_procfreq = 200000000; +#endif /* CONFIG_405EP */ + } + timebase_period_ns = 1000000000 / hold_residual->bi_intfreq; +#endif /* CONFIG_40x */ + +#ifdef CONFIG_440GP /* simply copy the MAC addresses */ - memcpy(hold_residual->bi_enetaddr, (char *)EBONY_OPENBIOS_MAC_BASE, 6); - memcpy(hold_residual->bi_enet1addr, (char *)(EBONY_OPENBIOS_MAC_BASE+EBONY_OPENBIOS_MAC_OFFSET), 6); + memcpy(hold_residual->bi_enetaddr, (char *)OPENBIOS_MAC_BASE, 6); + memcpy(hold_residual->bi_enet1addr, (char *)(OPENBIOS_MAC_BASE+OPENBIOS_MAC_OFFSET), 6); +#endif /* CONFIG_440GP */ + + decompress_kernel(load_addr, num_words, cksum); return (void *)hold_residual; } diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig index e70e4c6ec78..d8837911bbc 100644 --- a/arch/ppc/platforms/4xx/Kconfig +++ b/arch/ppc/platforms/4xx/Kconfig @@ -225,7 +225,7 @@ config EMBEDDEDBOOT config IBM_OPENBIOS bool - depends on ASH || BUBINGA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT + depends on ASH || REDWOOD_5 || REDWOOD_6 default y config PPC4xx_DMA diff --git a/arch/ppc/platforms/4xx/bubinga.c b/arch/ppc/platforms/4xx/bubinga.c index 3678abf8631..8110f55668c 100644 --- a/arch/ppc/platforms/4xx/bubinga.c +++ b/arch/ppc/platforms/4xx/bubinga.c @@ -89,7 +89,7 @@ bubinga_early_serial_map(void) * by 16. */ uart_div = (mfdcr(DCRN_CPC0_UCR_BASE) & DCRN_CPC0_UCR_U0DIV); - uart_clock = __res.bi_pllouta_freq / uart_div; + uart_clock = __res.bi_procfreq / uart_div; /* Setup serial port access */ memset(&port, 0, sizeof(port)); diff --git a/arch/ppc/platforms/4xx/bubinga.h b/arch/ppc/platforms/4xx/bubinga.h index b1df856f8e2..b5380cfaf5c 100644 --- a/arch/ppc/platforms/4xx/bubinga.h +++ b/arch/ppc/platforms/4xx/bubinga.h @@ -1,52 +1,34 @@ /* - * Support for IBM PPC 405EP evaluation board (Bubinga). + * arch/ppc/platforms/4xx/bubinga.h * - * Author: SAW (IBM), derived from walnut.h. - * Maintained by MontaVista Software + * Bubinga board definitions + * + * Copyright (c) 2005 DENX Software Engineering + * Stefan Roese + * + * Based on original work by + * SAW (IBM) + * 2003 (c) MontaVista Softare Inc. + * + * 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 + * option) any later version. * - * 2003 (c) MontaVista Softare Inc. This file is licensed under the - * terms of the GNU General Public License version 2. This program is - * licensed "as is" without any warranty of any kind, whether express - * or implied. */ #ifdef __KERNEL__ #ifndef __BUBINGA_H__ #define __BUBINGA_H__ -/* 405EP */ +#include #include - -#ifndef __ASSEMBLY__ -/* - * Data structure defining board information maintained by the boot - * ROM on IBM's evaluation board. An effort has been made to - * keep the field names consistent with the 8xx 'bd_t' board info - * structures. - */ - -typedef struct board_info { - unsigned char bi_s_version[4]; /* Version of this structure */ - unsigned char bi_r_version[30]; /* Version of the IBM ROM */ - unsigned int bi_memsize; /* DRAM installed, in bytes */ - unsigned char bi_enetaddr[2][6]; /* Local Ethernet MAC address */ unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */ - unsigned int bi_intfreq; /* Processor speed, in Hz */ - unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ - unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */ - unsigned int bi_opb_busfreq; /* OPB Bus speed, in Hz */ - unsigned int bi_pllouta_freq; /* PLL OUTA speed, in Hz */ -} bd_t; - -/* Some 4xx parts use a different timebase frequency from the internal clock. -*/ -#define bi_tbfreq bi_intfreq - +#include /* Memory map for the Bubinga board. * Generic 4xx plus RTC. */ -extern void *bubinga_rtc_base; #define BUBINGA_RTC_PADDR ((uint)0xf0000000) #define BUBINGA_RTC_VADDR BUBINGA_RTC_PADDR #define BUBINGA_RTC_SIZE ((uint)8*1024) @@ -58,12 +40,18 @@ extern void *bubinga_rtc_base; * for typical configurations at various CPU speeds. * The base baud is calculated as (FWDA / EXT UART DIV / 16) */ -#define BASE_BAUD 0 +#define BASE_BAUD 0 -#define BUBINGA_FPGA_BASE 0xF0300000 +/* Flash */ +#define PPC40x_FPGA_BASE 0xF0300000 +#define PPC40x_FPGA_REG_OFFS 1 /* offset to flash map reg */ +#define PPC40x_FLASH_ONBD_N(x) (x & 0x02) +#define PPC40x_FLASH_SRAM_SEL(x) (x & 0x01) +#define PPC40x_FLASH_LOW 0xFFF00000 +#define PPC40x_FLASH_HIGH 0xFFF80000 +#define PPC40x_FLASH_SIZE 0x80000 -#define PPC4xx_MACHINE_NAME "IBM Bubinga" +#define PPC4xx_MACHINE_NAME "IBM Bubinga" -#endif /* !__ASSEMBLY__ */ #endif /* __BUBINGA_H__ */ #endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/4xx/ebony.h b/arch/ppc/platforms/4xx/ebony.h index d08faa46a0a..b91ad4272df 100644 --- a/arch/ppc/platforms/4xx/ebony.h +++ b/arch/ppc/platforms/4xx/ebony.h @@ -24,8 +24,8 @@ #define PPC44x_EMAC0_MR0 0xE0000800 /* Where to find the MAC info */ -#define EBONY_OPENBIOS_MAC_BASE 0xfffffe0c -#define EBONY_OPENBIOS_MAC_OFFSET 0x0c +#define OPENBIOS_MAC_BASE 0xfffffe0c +#define OPENBIOS_MAC_OFFSET 0x0c /* Default clock rates for Rev. B and Rev. C silicon */ #define EBONY_440GP_RB_SYSCLK 33000000 diff --git a/arch/ppc/platforms/4xx/sycamore.c b/arch/ppc/platforms/4xx/sycamore.c index d8019eec470..281b4a2ffb9 100644 --- a/arch/ppc/platforms/4xx/sycamore.c +++ b/arch/ppc/platforms/4xx/sycamore.c @@ -88,9 +88,6 @@ ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) void __init sycamore_setup_arch(void) { -#define SYCAMORE_PS2_BASE 0xF0100000 -#define SYCAMORE_FPGA_BASE 0xF0300000 - void *fpga_brdc; unsigned char fpga_brdc_data; void *fpga_enable; @@ -100,7 +97,7 @@ sycamore_setup_arch(void) ppc4xx_setup_arch(); - ibm_ocp_set_emac(0, 1); + ibm_ocp_set_emac(0, 0); kb_data = ioremap(SYCAMORE_PS2_BASE, 8); if (!kb_data) { @@ -111,7 +108,7 @@ sycamore_setup_arch(void) kb_cs = kb_data + 1; - fpga_status = ioremap(SYCAMORE_FPGA_BASE, 8); + fpga_status = ioremap(PPC40x_FPGA_BASE, 8); if (!fpga_status) { printk(KERN_CRIT "sycamore_setup_arch() fpga_status ioremap failed\n"); diff --git a/arch/ppc/platforms/4xx/sycamore.h b/arch/ppc/platforms/4xx/sycamore.h index 3e7b4e2c8c5..1cd6c824fd6 100644 --- a/arch/ppc/platforms/4xx/sycamore.h +++ b/arch/ppc/platforms/4xx/sycamore.h @@ -1,67 +1,52 @@ /* * arch/ppc/platforms/4xx/sycamore.h * - * Macros, definitions, and data structures specific to the IBM PowerPC - * 405GPr "Sycamore" evaluation board. + * Sycamore board definitions * - * Author: Armin Kuster + * Copyright (c) 2005 DENX Software Engineering + * Stefan Roese + * + * Based on original work by + * Armin Kuster + * 2000 (c) MontaVista, Software, Inc. + * + * 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 + * option) any later version. * - * 2000 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. */ #ifdef __KERNEL__ #ifndef __ASM_SYCAMORE_H__ #define __ASM_SYCAMORE_H__ +#include #include +#include -#ifndef __ASSEMBLY__ -/* - * Data structure defining board information maintained by the boot - * ROM on IBM's "Sycamore" evaluation board. An effort has been made to - * keep the field names consistent with the 8xx 'bd_t' board info - * structures. - */ - -typedef struct board_info { - unsigned char bi_s_version[4]; /* Version of this structure */ - unsigned char bi_r_version[30]; /* Version of the IBM ROM */ - unsigned int bi_memsize; /* DRAM installed, in bytes */ - unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */ - unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */ - unsigned int bi_intfreq; /* Processor speed, in Hz */ - unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ - unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */ -} bd_t; - -/* Some 4xx parts use a different timebase frequency from the internal clock. -*/ -#define bi_tbfreq bi_intfreq - - -/* Memory map for the IBM "Sycamore" 405GP evaluation board. +/* Memory map for the IBM "Sycamore" 405GPr evaluation board. * Generic 4xx plus RTC. */ -extern void *sycamore_rtc_base; #define SYCAMORE_RTC_PADDR ((uint)0xf0000000) #define SYCAMORE_RTC_VADDR SYCAMORE_RTC_PADDR -#define SYCAMORE_RTC_SIZE ((uint)8*1024) +#define SYCAMORE_RTC_SIZE ((uint)8*1024) -#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK -#define BASE_BAUD 201600 -#else #define BASE_BAUD 691200 -#endif -#define SYCAMORE_PS2_BASE 0xF0100000 -#define SYCAMORE_FPGA_BASE 0xF0300000 +#define SYCAMORE_PS2_BASE 0xF0100000 + +/* Flash */ +#define PPC40x_FPGA_BASE 0xF0300000 +#define PPC40x_FPGA_REG_OFFS 5 /* offset to flash map reg */ +#define PPC40x_FLASH_ONBD_N(x) (x & 0x02) +#define PPC40x_FLASH_SRAM_SEL(x) (x & 0x01) +#define PPC40x_FLASH_LOW 0xFFF00000 +#define PPC40x_FLASH_HIGH 0xFFF80000 +#define PPC40x_FLASH_SIZE 0x80000 #define PPC4xx_MACHINE_NAME "IBM Sycamore" -#endif /* !__ASSEMBLY__ */ #endif /* __ASM_SYCAMORE_H__ */ #endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/4xx/walnut.c b/arch/ppc/platforms/4xx/walnut.c index a33eda4b748..74cb33182d9 100644 --- a/arch/ppc/platforms/4xx/walnut.c +++ b/arch/ppc/platforms/4xx/walnut.c @@ -90,7 +90,7 @@ walnut_setup_arch(void) kb_cs = kb_data + 1; - fpga_status = ioremap(WALNUT_FPGA_BASE, 8); + fpga_status = ioremap(PPC40x_FPGA_BASE, 8); if (!fpga_status) { printk(KERN_CRIT "walnut_setup_arch() fpga_status ioremap failed\n"); diff --git a/arch/ppc/platforms/4xx/walnut.h b/arch/ppc/platforms/4xx/walnut.h index 04cfbf3696b..dcf2691698c 100644 --- a/arch/ppc/platforms/4xx/walnut.h +++ b/arch/ppc/platforms/4xx/walnut.h @@ -1,72 +1,55 @@ /* * arch/ppc/platforms/4xx/walnut.h * - * Macros, definitions, and data structures specific to the IBM PowerPC - * 405GP "Walnut" evaluation board. + * Walnut board definitions * - * Authors: Grant Erickson , Frank Rowand - * , Debbie Chu or - * source@mvista.com + * Copyright (c) 2005 DENX Software Engineering + * Stefan Roese * - * Copyright (c) 1999 Grant Erickson + * Based on original work by + * Copyright (c) 1999 Grant Erickson + * Frank Rowand + * Debbie Chu + * 2000 (c) MontaVista, Software, Inc. + * + * 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 + * option) any later version. * - * 2000 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. */ #ifdef __KERNEL__ #ifndef __ASM_WALNUT_H__ #define __ASM_WALNUT_H__ -/* We have a 405GP core */ +#include #include - -#ifndef __ASSEMBLY__ -/* - * Data structure defining board information maintained by the boot - * ROM on IBM's "Walnut" evaluation board. An effort has been made to - * keep the field names consistent with the 8xx 'bd_t' board info - * structures. - */ - -typedef struct board_info { - unsigned char bi_s_version[4]; /* Version of this structure */ - unsigned char bi_r_version[30]; /* Version of the IBM ROM */ - unsigned int bi_memsize; /* DRAM installed, in bytes */ - unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */ - unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */ - unsigned int bi_intfreq; /* Processor speed, in Hz */ - unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ - unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */ -} bd_t; - -/* Some 4xx parts use a different timebase frequency from the internal clock. -*/ -#define bi_tbfreq bi_intfreq - +#include /* Memory map for the IBM "Walnut" 405GP evaluation board. * Generic 4xx plus RTC. */ -extern void *walnut_rtc_base; #define WALNUT_RTC_PADDR ((uint)0xf0000000) #define WALNUT_RTC_VADDR WALNUT_RTC_PADDR #define WALNUT_RTC_SIZE ((uint)8*1024) -#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK -#define BASE_BAUD 201600 -#else #define BASE_BAUD 691200 -#endif #define WALNUT_PS2_BASE 0xF0100000 -#define WALNUT_FPGA_BASE 0xF0300000 + +/* Flash */ +#define PPC40x_FPGA_BASE 0xF0300000 +#define PPC40x_FPGA_REG_OFFS 5 /* offset to flash map reg */ +#define PPC40x_FLASH_ONBD_N(x) (x & 0x02) +#define PPC40x_FLASH_SRAM_SEL(x) (x & 0x01) +#define PPC40x_FLASH_LOW 0xFFF00000 +#define PPC40x_FLASH_HIGH 0xFFF80000 +#define PPC40x_FLASH_SIZE 0x80000 +#define WALNUT_FPGA_BASE PPC40x_FPGA_BASE #define PPC4xx_MACHINE_NAME "IBM Walnut" -#endif /* !__ASSEMBLY__ */ #endif /* __ASM_WALNUT_H__ */ #endif /* __KERNEL__ */ diff --git a/include/asm-ppc/ibm_ocp.h b/include/asm-ppc/ibm_ocp.h index 6f10a25bd62..9c21de1ff4e 100644 --- a/include/asm-ppc/ibm_ocp.h +++ b/include/asm-ppc/ibm_ocp.h @@ -131,9 +131,22 @@ static inline void ibm_ocp_set_emac(int start, int end) /* Copy MAC addresses to EMAC additions */ for (i=start; i<=end; i++) { def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, i); - memcpy(((struct ocp_func_emac_data *)def->additions)->mac_addr, - &__res.bi_enetaddr[i], - 6); + if (i == 0) + memcpy(((struct ocp_func_emac_data *)def->additions)->mac_addr, + __res.bi_enetaddr, 6); +#if defined(CONFIG_405EP) || defined(CONFIG_44x) + else if (i == 1) + memcpy(((struct ocp_func_emac_data *)def->additions)->mac_addr, + __res.bi_enet1addr, 6); +#endif +#if defined(CONFIG_440GX) + else if (i == 2) + memcpy(((struct ocp_func_emac_data *)def->additions)->mac_addr, + __res.bi_enet2addr, 6); + else if (i == 3) + memcpy(((struct ocp_func_emac_data *)def->additions)->mac_addr, + __res.bi_enet3addr, 6); +#endif } } #endif diff --git a/include/asm-ppc/ppcboot.h b/include/asm-ppc/ppcboot.h index fe24e452020..6b7b63f71da 100644 --- a/include/asm-ppc/ppcboot.h +++ b/include/asm-ppc/ppcboot.h @@ -73,8 +73,8 @@ typedef struct bd_info { #if defined(CONFIG_HYMOD) hymod_conf_t bi_hymod_conf; /* hymod configuration information */ #endif -#if defined(CONFIG_EVB64260) || defined(CONFIG_44x) || defined(CONFIG_85xx) ||\ - defined(CONFIG_83xx) +#if defined(CONFIG_EVB64260) || defined(CONFIG_405EP) || defined(CONFIG_44x) || \ + defined(CONFIG_85xx) || defined(CONFIG_83xx) /* second onboard ethernet port */ unsigned char bi_enet1addr[6]; #endif @@ -96,5 +96,7 @@ typedef struct bd_info { #endif } bd_t; +#define bi_tbfreq bi_intfreq + #endif /* __ASSEMBLY__ */ #endif /* __ASM_PPCBOOT_H__ */ -- cgit v1.2.3 From 7869ec6d735e3802f0d442f585ae6bb7633222f6 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 7 Nov 2005 00:58:16 -0800 Subject: [PATCH] ppc32: Remove internal PCI arbiter check on PPC40x On PPC405GP/GPR it should be possible to enable PCI support, even when the internal PCI arbiter is disabled (e.g. when using an external PCI arbiter). The removed code didn't allow this, and also generated a warning on PPC405EP platforms. Signed-off-by: Stefan Roese Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/syslib/ppc405_pci.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/arch/ppc/syslib/ppc405_pci.c b/arch/ppc/syslib/ppc405_pci.c index 81c83bf98df..d6d838b16da 100644 --- a/arch/ppc/syslib/ppc405_pci.c +++ b/arch/ppc/syslib/ppc405_pci.c @@ -89,13 +89,6 @@ ppc4xx_find_bridges(void) isa_mem_base = 0; pci_dram_offset = 0; -#if (PSR_PCI_ARBIT_EN > 1) - /* Check if running in slave mode */ - if ((mfdcr(DCRN_CHPSR) & PSR_PCI_ARBIT_EN) == 0) { - printk("Running as PCI slave, kernel PCI disabled !\n"); - return; - } -#endif /* Setup PCI32 hose */ hose_a = pcibios_alloc_controller(); if (!hose_a) -- cgit v1.2.3 From 634e67ff917c079b102317d53556d758dc207969 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 7 Nov 2005 00:58:16 -0800 Subject: [PATCH] ppc32: Add missing initrd header on ppc440 This missing initrd header slipped though last time. Signed-off-by: Stefan Roese Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/syslib/ibm44x_common.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/ppc/syslib/ibm44x_common.c b/arch/ppc/syslib/ibm44x_common.c index a5bef9d163a..71db11d2215 100644 --- a/arch/ppc/syslib/ibm44x_common.c +++ b/arch/ppc/syslib/ibm44x_common.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From de672e4ade25502c28486da005be3eb79534017d Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Mon, 7 Nov 2005 00:58:17 -0800 Subject: [PATCH] ppc32: Add CPM1 config option Kconfig patch needed by fs_enet to work. Works like CONFIG_CPM2. Cc: Kumar Cc: Benjamin Herrenschmidt Cc: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/Kconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index 114b90fdea2..f8db33d5527 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -746,6 +746,16 @@ config MPC834x bool default y if MPC834x_SYS +config CPM1 + bool + depends on 8xx + default y + help + The CPM1 (Communications Processor Module) is a coprocessor on + embedded CPUs made by Motorola. Selecting this option means that + you wish to build a kernel for a machine with a CPM1 coprocessor + on it (8xx, 827x, 8560). + config CPM2 bool depends on 8260 || MPC8560 || MPC8555 -- cgit v1.2.3 From e87eaad107d3c0fa81bf9de84f0fe2b7eaaf1fb9 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 7 Nov 2005 00:58:19 -0800 Subject: [PATCH] sh: Re-add sh to drivers/Makefile drivers/sh/ got dropped from drivers/Makefile, so add it back in.. Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/Makefile b/drivers/Makefile index 65670be6ff1..61c64f76836 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -67,3 +67,4 @@ obj-$(CONFIG_INFINIBAND) += infiniband/ obj-$(CONFIG_SGI_IOC4) += sn/ obj-y += firmware/ obj-$(CONFIG_CRYPTO) += crypto/ +obj-$(CONFIG_SUPERH) += sh/ -- cgit v1.2.3 From 72777373b3a09c9132a787d5e1e03eaf64f30a64 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 7 Nov 2005 00:58:20 -0800 Subject: [PATCH] sh: Drop deprecated support for custom ramdisk embedding sh had its own support for embedding ramdisk images in to the kernel binary, but people are using initramfs for this now, so we drop the ramdisk embedding. Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sh/Kconfig | 18 ------------------ arch/sh/Makefile | 8 -------- arch/sh/ramdisk/Makefile | 20 -------------------- arch/sh/ramdisk/ld.script | 9 --------- 4 files changed, 55 deletions(-) delete mode 100644 arch/sh/ramdisk/Makefile delete mode 100644 arch/sh/ramdisk/ld.script diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 3e804c736e6..7d31d628cde 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -770,24 +770,6 @@ source "fs/Kconfig.binfmt" endmenu -menu "SH initrd options" - depends on BLK_DEV_INITRD - -config EMBEDDED_RAMDISK - bool "Embed root filesystem ramdisk into the kernel" - -config EMBEDDED_RAMDISK_IMAGE - string "Filename of gziped ramdisk image" - depends on EMBEDDED_RAMDISK - default "ramdisk.gz" - help - This is the filename of the ramdisk image to be built into the - kernel. Relative pathnames are relative to arch/sh/ramdisk/. - The ramdisk image is not part of the kernel distribution; you must - provide one yourself. - -endmenu - source "net/Kconfig" source "drivers/Kconfig" diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 4a3049080b4..67192d6b00d 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -60,14 +60,6 @@ LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) core-y += arch/sh/kernel/ arch/sh/mm/ -# -# ramdisk/initrd support -# You need a compressed ramdisk image, named -# CONFIG_EMBEDDED_RAMDISK_IMAGE. Relative pathnames -# are relative to arch/sh/ramdisk/. -# -core-$(CONFIG_EMBEDDED_RAMDISK) += arch/sh/ramdisk/ - # Boards machdir-$(CONFIG_SH_SOLUTION_ENGINE) := se/770x machdir-$(CONFIG_SH_7751_SOLUTION_ENGINE) := se/7751 diff --git a/arch/sh/ramdisk/Makefile b/arch/sh/ramdisk/Makefile deleted file mode 100644 index 99e1c68673c..00000000000 --- a/arch/sh/ramdisk/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# -# Makefile for a ramdisk image -# - -obj-y += ramdisk.o - - -O_FORMAT = $(shell $(OBJDUMP) -i | head -n 2 | grep elf32) -img := $(subst ",,$(CONFIG_EMBEDDED_RAMDISK_IMAGE)) -# add $(src) when $(img) is relative -img := $(subst $(src)//,/,$(src)/$(img)) - -quiet_cmd_ramdisk = LD $@ -define cmd_ramdisk - $(LD) -T $(srctree)/$(src)/ld.script -b binary --oformat $(O_FORMAT) \ - -o $@ $(img) -endef - -$(obj)/ramdisk.o: $(img) $(srctree)/$(src)/ld.script - $(call cmd,ramdisk) diff --git a/arch/sh/ramdisk/ld.script b/arch/sh/ramdisk/ld.script deleted file mode 100644 index 94beee248c0..00000000000 --- a/arch/sh/ramdisk/ld.script +++ /dev/null @@ -1,9 +0,0 @@ -OUTPUT_ARCH(sh) -SECTIONS -{ - .initrd : - { - *(.data) - } -} - -- cgit v1.2.3 From 055a2512144cd7e60dcaae7a13e460df43b98787 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 7 Nov 2005 00:58:21 -0800 Subject: [PATCH] superhyway: multiple block support and VCR rework This extends the API somewhat to allow for platform-specific VCR reading and writing. Some platforms (like SH4-202) implement the VCR in a split VCRL and VCRH, but end up being in reverse order or have other quirks that need to be dealt with, so we add a set of superhyway_ops per-bus to accomodate this. We also have to extend the per-device resources somewhat, as some devices now conveniently split control and data blocks. So we allow a platform to register its set of SuperHyway devices via superhyway_add_devices() with the control block always ordered as the first resource (as this is the one that userspace cares about). Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/sh/superhyway/superhyway-sysfs.c | 2 +- drivers/sh/superhyway/superhyway.c | 75 +++++++++++++++++++++++--------- include/linux/superhyway.h | 38 +++++++++++++--- 3 files changed, 89 insertions(+), 26 deletions(-) diff --git a/drivers/sh/superhyway/superhyway-sysfs.c b/drivers/sh/superhyway/superhyway-sysfs.c index dc119ce68e3..55434330867 100644 --- a/drivers/sh/superhyway/superhyway-sysfs.c +++ b/drivers/sh/superhyway/superhyway-sysfs.c @@ -30,7 +30,7 @@ superhyway_ro_attr(bot_mb, "0x%02x\n", vcr.bot_mb); superhyway_ro_attr(top_mb, "0x%02x\n", vcr.top_mb); /* Misc */ -superhyway_ro_attr(resource, "0x%08lx\n", resource.start); +superhyway_ro_attr(resource, "0x%08lx\n", resource[0].start); struct device_attribute superhyway_dev_attrs[] = { __ATTR_RO(perr_flags), diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c index 28757cb9d24..7bdab2a7f59 100644 --- a/drivers/sh/superhyway/superhyway.c +++ b/drivers/sh/superhyway/superhyway.c @@ -27,19 +27,20 @@ static struct device superhyway_bus_device = { static void superhyway_device_release(struct device *dev) { - kfree(to_superhyway_device(dev)); + struct superhyway_device *sdev = to_superhyway_device(dev); + + kfree(sdev->resource); + kfree(sdev); } /** * superhyway_add_device - Add a SuperHyway module - * @mod_id: Module ID (taken from MODULE.VCR.MOD_ID). * @base: Physical address where module is mapped. - * @vcr: VCR value. + * @sdev: SuperHyway device to add, or NULL to allocate a new one. + * @bus: Bus where SuperHyway module resides. * * This is responsible for adding a new SuperHyway module. This sets up a new - * struct superhyway_device for the module being added. Each one of @mod_id, - * @base, and @vcr are registered with the new device for further use - * elsewhere. + * struct superhyway_device for the module being added if @sdev == NULL. * * Devices are initially added in the order that they are scanned (from the * top-down of the memory map), and are assigned an ID based on the order that @@ -49,28 +50,40 @@ static void superhyway_device_release(struct device *dev) * Further work can and should be done in superhyway_scan_bus(), to be sure * that any new modules are properly discovered and subsequently registered. */ -int superhyway_add_device(unsigned int mod_id, unsigned long base, - unsigned long long vcr) +int superhyway_add_device(unsigned long base, struct superhyway_device *sdev, + struct superhyway_bus *bus) { - struct superhyway_device *dev; + struct superhyway_device *dev = sdev; + + if (!dev) { + dev = kmalloc(sizeof(struct superhyway_device), GFP_KERNEL); + if (!dev) + return -ENOMEM; - dev = kmalloc(sizeof(struct superhyway_device), GFP_KERNEL); - if (!dev) - return -ENOMEM; + memset(dev, 0, sizeof(struct superhyway_device)); + } - memset(dev, 0, sizeof(struct superhyway_device)); + dev->bus = bus; + superhyway_read_vcr(dev, base, &dev->vcr); - dev->id.id = mod_id; - sprintf(dev->name, "SuperHyway device %04x", dev->id.id); + if (!dev->resource) { + dev->resource = kmalloc(sizeof(struct resource), GFP_KERNEL); + if (!dev->resource) { + kfree(dev); + return -ENOMEM; + } + + dev->resource->name = dev->name; + dev->resource->start = base; + dev->resource->end = dev->resource->start + 0x01000000; + } - dev->vcr = *((struct vcr_info *)(&vcr)); - dev->resource.name = dev->name; - dev->resource.start = base; - dev->resource.end = dev->resource.start + 0x01000000; dev->dev.parent = &superhyway_bus_device; dev->dev.bus = &superhyway_bus_type; dev->dev.release = superhyway_device_release; + dev->id.id = dev->vcr.mod_id; + sprintf(dev->name, "SuperHyway device %04x", dev->id.id); sprintf(dev->dev.bus_id, "%02x", superhyway_devices); superhyway_devices++; @@ -78,10 +91,31 @@ int superhyway_add_device(unsigned int mod_id, unsigned long base, return device_register(&dev->dev); } +int superhyway_add_devices(struct superhyway_bus *bus, + struct superhyway_device **devices, + int nr_devices) +{ + int i, ret = 0; + + for (i = 0; i < nr_devices; i++) { + struct superhyway_device *dev = devices[i]; + ret |= superhyway_add_device(dev->resource[0].start, dev, bus); + } + + return ret; +} + static int __init superhyway_init(void) { + struct superhyway_bus *bus; + int ret = 0; + device_register(&superhyway_bus_device); - return superhyway_scan_bus(); + + for (bus = superhyway_channels; bus->ops; bus++) + ret |= superhyway_scan_bus(bus); + + return ret; } postcore_initcall(superhyway_init); @@ -197,6 +231,7 @@ module_exit(superhyway_bus_exit); EXPORT_SYMBOL(superhyway_bus_type); EXPORT_SYMBOL(superhyway_add_device); +EXPORT_SYMBOL(superhyway_add_devices); EXPORT_SYMBOL(superhyway_register_driver); EXPORT_SYMBOL(superhyway_unregister_driver); diff --git a/include/linux/superhyway.h b/include/linux/superhyway.h index c906c5a0aae..17ea468fa36 100644 --- a/include/linux/superhyway.h +++ b/include/linux/superhyway.h @@ -19,7 +19,7 @@ */ #define SUPERHYWAY_DEVICE_ID_SH5_DMAC 0x0183 -struct vcr_info { +struct superhyway_vcr_info { u8 perr_flags; /* P-port Error flags */ u8 merr_flags; /* Module Error flags */ u16 mod_vers; /* Module Version */ @@ -28,6 +28,17 @@ struct vcr_info { u8 top_mb; /* Top Memory block */ }; +struct superhyway_ops { + int (*read_vcr)(unsigned long base, struct superhyway_vcr_info *vcr); + int (*write_vcr)(unsigned long base, struct superhyway_vcr_info vcr); +}; + +struct superhyway_bus { + struct superhyway_ops *ops; +}; + +extern struct superhyway_bus superhyway_channels[]; + struct superhyway_device_id { unsigned int id; unsigned long driver_data; @@ -55,9 +66,11 @@ struct superhyway_device { struct superhyway_device_id id; struct superhyway_driver *drv; + struct superhyway_bus *bus; - struct resource resource; - struct vcr_info vcr; + int num_resources; + struct resource *resource; + struct superhyway_vcr_info vcr; }; #define to_superhyway_device(d) container_of((d), struct superhyway_device, dev) @@ -65,12 +78,27 @@ struct superhyway_device { #define superhyway_get_drvdata(d) dev_get_drvdata(&(d)->dev) #define superhyway_set_drvdata(d,p) dev_set_drvdata(&(d)->dev, (p)) -extern int superhyway_scan_bus(void); +static inline int +superhyway_read_vcr(struct superhyway_device *dev, unsigned long base, + struct superhyway_vcr_info *vcr) +{ + return dev->bus->ops->read_vcr(base, vcr); +} + +static inline int +superhyway_write_vcr(struct superhyway_device *dev, unsigned long base, + struct superhyway_vcr_info vcr) +{ + return dev->bus->ops->write_vcr(base, vcr); +} + +extern int superhyway_scan_bus(struct superhyway_bus *); /* drivers/sh/superhyway/superhyway.c */ int superhyway_register_driver(struct superhyway_driver *); void superhyway_unregister_driver(struct superhyway_driver *); -int superhyway_add_device(unsigned int, unsigned long, unsigned long long); +int superhyway_add_device(unsigned long base, struct superhyway_device *, struct superhyway_bus *); +int superhyway_add_devices(struct superhyway_bus *bus, struct superhyway_device **devices, int nr_devices); /* drivers/sh/superhyway/superhyway-sysfs.c */ extern struct device_attribute superhyway_dev_attrs[]; -- cgit v1.2.3 From d5cb9783536a41df9f9cba5b0a1d78047ed787f7 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 7 Nov 2005 00:58:22 -0800 Subject: [PATCH] sh: SuperHyway support for SH4-202 This adds support for the relatively quirky (ie, not in line with any known documentation, and amazed it works at all) SuperHyway implementation on SH4-202. This depends on the earlier SuperHyway patch for multiple block support and VCR refactoring. Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sh/drivers/Makefile | 5 +- arch/sh/drivers/superhyway/Makefile | 6 ++ arch/sh/drivers/superhyway/ops-sh4-202.c | 171 +++++++++++++++++++++++++++++++ 3 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 arch/sh/drivers/superhyway/Makefile create mode 100644 arch/sh/drivers/superhyway/ops-sh4-202.c diff --git a/arch/sh/drivers/Makefile b/arch/sh/drivers/Makefile index bd6726cde39..338c3729d27 100644 --- a/arch/sh/drivers/Makefile +++ b/arch/sh/drivers/Makefile @@ -2,6 +2,7 @@ # Makefile for the Linux SuperH-specific device drivers. # -obj-$(CONFIG_PCI) += pci/ -obj-$(CONFIG_SH_DMA) += dma/ +obj-$(CONFIG_PCI) += pci/ +obj-$(CONFIG_SH_DMA) += dma/ +obj-$(CONFIG_SUPERHYWAY) += superhyway/ diff --git a/arch/sh/drivers/superhyway/Makefile b/arch/sh/drivers/superhyway/Makefile new file mode 100644 index 00000000000..5b8e0c7ca3a --- /dev/null +++ b/arch/sh/drivers/superhyway/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for the SuperHyway specific kernel interface routines under Linux. +# + +obj-$(CONFIG_CPU_SUBTYPE_SH4_202) += ops-sh4-202.o + diff --git a/arch/sh/drivers/superhyway/ops-sh4-202.c b/arch/sh/drivers/superhyway/ops-sh4-202.c new file mode 100644 index 00000000000..a55c98a9052 --- /dev/null +++ b/arch/sh/drivers/superhyway/ops-sh4-202.c @@ -0,0 +1,171 @@ +/* + * arch/sh/drivers/superhyway/ops-sh4-202.c + * + * SuperHyway bus support for SH4-202 + * + * Copyright (C) 2005 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU + * General Public License. See the file "COPYING" in the main + * directory of this archive for more details. + */ +#include +#include +#include +#include +#include +#include + +#define PHYS_EMI_CBLOCK P4SEGADDR(0x1ec00000) +#define PHYS_EMI_DBLOCK P4SEGADDR(0x08000000) +#define PHYS_FEMI_CBLOCK P4SEGADDR(0x1f800000) +#define PHYS_FEMI_DBLOCK P4SEGADDR(0x00000000) + +#define PHYS_EPBR_BLOCK P4SEGADDR(0x1de00000) +#define PHYS_DMAC_BLOCK P4SEGADDR(0x1fa00000) +#define PHYS_PBR_BLOCK P4SEGADDR(0x1fc00000) + +static struct resource emi_resources[] = { + [0] = { + .start = PHYS_EMI_CBLOCK, + .end = PHYS_EMI_CBLOCK + 0x00300000 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PHYS_EMI_DBLOCK, + .end = PHYS_EMI_DBLOCK + 0x08000000 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct superhyway_device emi_device = { + .name = "emi", + .num_resources = ARRAY_SIZE(emi_resources), + .resource = emi_resources, +}; + +static struct resource femi_resources[] = { + [0] = { + .start = PHYS_FEMI_CBLOCK, + .end = PHYS_FEMI_CBLOCK + 0x00100000 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PHYS_FEMI_DBLOCK, + .end = PHYS_FEMI_DBLOCK + 0x08000000 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct superhyway_device femi_device = { + .name = "femi", + .num_resources = ARRAY_SIZE(femi_resources), + .resource = femi_resources, +}; + +static struct resource epbr_resources[] = { + [0] = { + .start = P4SEGADDR(0x1e7ffff8), + .end = P4SEGADDR(0x1e7ffff8 + (sizeof(u32) * 2) - 1), + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PHYS_EPBR_BLOCK, + .end = PHYS_EPBR_BLOCK + 0x00a00000 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct superhyway_device epbr_device = { + .name = "epbr", + .num_resources = ARRAY_SIZE(epbr_resources), + .resource = epbr_resources, +}; + +static struct resource dmac_resource = { + .start = PHYS_DMAC_BLOCK, + .end = PHYS_DMAC_BLOCK + 0x00100000 - 1, + .flags = IORESOURCE_MEM, +}; + +static struct superhyway_device dmac_device = { + .name = "dmac", + .num_resources = 1, + .resource = &dmac_resource, +}; + +static struct resource pbr_resources[] = { + [0] = { + .start = P4SEGADDR(0x1ffffff8), + .end = P4SEGADDR(0x1ffffff8 + (sizeof(u32) * 2) - 1), + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PHYS_PBR_BLOCK, + .end = PHYS_PBR_BLOCK + 0x00400000 - (sizeof(u32) * 2) - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct superhyway_device pbr_device = { + .name = "pbr", + .num_resources = ARRAY_SIZE(pbr_resources), + .resource = pbr_resources, +}; + +static struct superhyway_device *sh4202_devices[] __initdata = { + &emi_device, &femi_device, &epbr_device, &dmac_device, &pbr_device, +}; + +static int sh4202_read_vcr(unsigned long base, struct superhyway_vcr_info *vcr) +{ + u32 vcrh, vcrl; + u64 tmp; + + /* + * XXX: Even though the SH4-202 Evaluation Device documentation + * indicates that VCRL is mapped first with VCRH at a + 0x04 + * offset, the opposite seems to be true. + * + * Some modules (PBR and ePBR for instance) also appear to have + * VCRL/VCRH flipped in the documentation, but on the SH4-202 + * itself it appears that these are all consistently mapped with + * VCRH preceeding VCRL. + * + * Do not trust the documentation, for it is evil. + */ + vcrh = ctrl_inl(base); + vcrl = ctrl_inl(base + sizeof(u32)); + + tmp = ((u64)vcrh << 32) | vcrl; + memcpy(vcr, &tmp, sizeof(u64)); + + return 0; +} + +static int sh4202_write_vcr(unsigned long base, struct superhyway_vcr_info vcr) +{ + u64 tmp = *(u64 *)&vcr; + + ctrl_outl((tmp >> 32) & 0xffffffff, base); + ctrl_outl(tmp & 0xffffffff, base + sizeof(u32)); + + return 0; +} + +static struct superhyway_ops sh4202_superhyway_ops = { + .read_vcr = sh4202_read_vcr, + .write_vcr = sh4202_write_vcr, +}; + +struct superhyway_bus superhyway_channels[] = { + { &sh4202_superhyway_ops, }, + { 0, }, +}; + +int __init superhyway_scan_bus(struct superhyway_bus *bus) +{ + return superhyway_add_devices(bus, sh4202_devices, + ARRAY_SIZE(sh4202_devices)); +} + -- cgit v1.2.3 From d229401f130941583eb46a2e8886df61241c14eb Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 7 Nov 2005 00:58:23 -0800 Subject: [PATCH] sh: pte_mkhuge() compile fix for !CONFIG_HUGETLB_PAGE Presently it is bogus to call pte_mkhuge() outside of the CONFIG_HUGETLB_PAGE context, as the only processors that support _PAGE_SZHUGE do so in the hugetlbpage context only (and this is the only time that _PAGE_SZHUGE is even defined). SH-2 and SH-3 do not support huge pages at all, and so it is not possible to enable this. Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-sh/pgtable.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h index aef8ae43de1..dee36bcbcf9 100644 --- a/include/asm-sh/pgtable.h +++ b/include/asm-sh/pgtable.h @@ -196,7 +196,9 @@ static inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _ static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; } static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; } static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; } +#ifdef CONFIG_HUGETLB_PAGE static inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; } +#endif /* * Macro and implementation to make a page protection as uncachable. -- cgit v1.2.3 From 65463b73b14ed43368dc5961a6c3dcb0d98cfe1f Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 7 Nov 2005 00:58:24 -0800 Subject: [PATCH] sh: Drop hp690 discontig support There was only one board using this (hp690 specifically), and it just so happens that it's only physically discontiguous at the "normal" P1 offset. If we bump up the P1 offset, it's possible to hit a shadowed region of memory where we suddenly become magically contiguous. As people have been using this shadowed region workaround for quite some time (and without any adverse effects), it's time to drop the left over discontig bits that no longer have any practical use (it was always very much hp690-centric to begin with). Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sh/Kconfig | 10 -------- arch/sh/kernel/setup.c | 26 ++++++--------------- arch/sh/mm/init.c | 21 ++--------------- include/asm-sh/mmzone.h | 61 ------------------------------------------------- include/asm-sh/page.h | 7 ------ 5 files changed, 9 insertions(+), 116 deletions(-) delete mode 100644 include/asm-sh/mmzone.h diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 7d31d628cde..64f5ae0ff96 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -490,16 +490,6 @@ config CPU_SUBTYPE_ST40 depends on CPU_SUBTYPE_ST40STB1 || CPU_SUBTYPE_ST40GX1 default y -config ARCH_DISCONTIGMEM_ENABLE - bool - depends on SH_HP690 - default y - help - Say Y to upport efficient handling of discontiguous physical memory, - for architectures which are either NUMA (Non-Uniform Memory Access) - or have huge holes in the physical address space for other reasons. - See for more. - source "mm/Kconfig" config ZERO_PAGE_OFFSET diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 25b9d9ebe85..036050b377c 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -83,9 +83,9 @@ static struct sh_machine_vector* __init get_mv_byname(const char* name); /* ... */ #define COMMAND_LINE ((char *) (PARAM+0x100)) -#define RAMDISK_IMAGE_START_MASK 0x07FF +#define RAMDISK_IMAGE_START_MASK 0x07FF #define RAMDISK_PROMPT_FLAG 0x8000 -#define RAMDISK_LOAD_FLAG 0x4000 +#define RAMDISK_LOAD_FLAG 0x4000 static char command_line[COMMAND_LINE_SIZE] = { 0, }; @@ -284,18 +284,6 @@ void __init setup_arch(char **cmdline_p) #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) #define PFN_PHYS(x) ((x) << PAGE_SHIFT) -#ifdef CONFIG_DISCONTIGMEM - NODE_DATA(0)->bdata = &discontig_node_bdata[0]; - NODE_DATA(1)->bdata = &discontig_node_bdata[1]; - - bootmap_size = init_bootmem_node(NODE_DATA(1), - PFN_UP(__MEMORY_START_2ND), - PFN_UP(__MEMORY_START_2ND), - PFN_DOWN(__MEMORY_START_2ND+__MEMORY_SIZE_2ND)); - free_bootmem_node(NODE_DATA(1), __MEMORY_START_2ND, __MEMORY_SIZE_2ND); - reserve_bootmem_node(NODE_DATA(1), __MEMORY_START_2ND, bootmap_size); -#endif - /* * Find the highest page frame number we have available */ @@ -306,10 +294,10 @@ void __init setup_arch(char **cmdline_p) */ max_low_pfn = max_pfn; - /* + /* * Partially used pages are not usable - thus * we are rounding upwards: - */ + */ start_pfn = PFN_UP(__pa(_end)); /* @@ -360,12 +348,12 @@ void __init setup_arch(char **cmdline_p) reserve_bootmem_node(NODE_DATA(0), __MEMORY_START, PAGE_SIZE); #ifdef CONFIG_BLK_DEV_INITRD - ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); - if (&__rd_start != &__rd_end) { + ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); + if (&__rd_start != &__rd_end) { LOADER_TYPE = 1; INITRD_START = PHYSADDR((unsigned long)&__rd_start) - __MEMORY_START; INITRD_SIZE = (unsigned long)&__rd_end - (unsigned long)&__rd_start; - } + } if (LOADER_TYPE && INITRD_START) { if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) { diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index 4e9c854845a..e342565f75f 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -51,11 +51,6 @@ unsigned long mmu_context_cache = NO_CONTEXT; #define MAX_LOW_PFN (NODE_DATA(0)->bdata->node_low_pfn) #endif -#ifdef CONFIG_DISCONTIGMEM -pg_data_t discontig_page_data[MAX_NUMNODES]; -bootmem_data_t discontig_node_bdata[MAX_NUMNODES]; -#endif - void (*copy_page)(void *from, void *to); void (*clear_page)(void *to); @@ -216,15 +211,6 @@ void __init paging_init(void) #endif NODE_DATA(0)->node_mem_map = NULL; free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0); - -#ifdef CONFIG_DISCONTIGMEM - /* - * And for discontig, do some more fixups on the zone sizes.. - */ - zones_size[ZONE_DMA] = __MEMORY_SIZE_2ND >> PAGE_SHIFT; - zones_size[ZONE_NORMAL] = 0; - free_area_init_node(1, NODE_DATA(1), zones_size, __MEMORY_START_2ND >> PAGE_SHIFT, 0); -#endif } void __init mem_init(void) @@ -248,7 +234,7 @@ void __init mem_init(void) memset(empty_zero_page, 0, PAGE_SIZE); __flush_wback_region(empty_zero_page, PAGE_SIZE); - /* + /* * Setup wrappers for copy/clear_page(), these will get overridden * later in the boot process if a better method is available. */ @@ -257,9 +243,6 @@ void __init mem_init(void) /* this will put all low memory onto the freelists */ totalram_pages += free_all_bootmem_node(NODE_DATA(0)); -#ifdef CONFIG_DISCONTIGMEM - totalram_pages += free_all_bootmem_node(NODE_DATA(1)); -#endif reservedpages = 0; for (tmp = 0; tmp < num_physpages; tmp++) /* @@ -286,7 +269,7 @@ void __init mem_init(void) void free_initmem(void) { unsigned long addr; - + addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); diff --git a/include/asm-sh/mmzone.h b/include/asm-sh/mmzone.h deleted file mode 100644 index 0e7406601fd..00000000000 --- a/include/asm-sh/mmzone.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * linux/include/asm-sh/mmzone.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#ifndef __ASM_SH_MMZONE_H -#define __ASM_SH_MMZONE_H - -#include - -#ifdef CONFIG_DISCONTIGMEM - -/* Currently, just for HP690 */ -#define PHYSADDR_TO_NID(phys) ((((phys) - __MEMORY_START) >= 0x01000000)?1:0) - -extern pg_data_t discontig_page_data[MAX_NUMNODES]; -extern bootmem_data_t discontig_node_bdata[MAX_NUMNODES]; - -/* - * Following are macros that each numa implmentation must define. - */ - -/* - * Given a kernel address, find the home node of the underlying memory. - */ -#define KVADDR_TO_NID(kaddr) PHYSADDR_TO_NID(__pa(kaddr)) - -/* - * Return a pointer to the node data for node n. - */ -#define NODE_DATA(nid) (&discontig_page_data[nid]) - -/* - * NODE_MEM_MAP gives the kaddr for the mem_map of the node. - */ -#define NODE_MEM_MAP(nid) (NODE_DATA(nid)->node_mem_map) - -#define phys_to_page(phys) \ -({ unsigned int node = PHYSADDR_TO_NID(phys); \ - NODE_MEM_MAP(node) \ - + (((phys) - NODE_DATA(node)->node_start_paddr) >> PAGE_SHIFT); }) - -static inline int is_valid_page(struct page *page) -{ - unsigned int i; - - for (i = 0; i < MAX_NUMNODES; i++) { - if (page >= NODE_MEM_MAP(i) && - page < NODE_MEM_MAP(i) + NODE_DATA(i)->node_size) - return 1; - } - return 0; -} - -#define VALID_PAGE(page) is_valid_page(page) -#define page_to_phys(page) PHYSADDR(page_address(page)) - -#endif /* CONFIG_DISCONTIGMEM */ -#endif diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h index 324e6cc5ecf..972c3f655b2 100644 --- a/include/asm-sh/page.h +++ b/include/asm-sh/page.h @@ -93,11 +93,6 @@ typedef struct { unsigned long pgprot; } pgprot_t; #define __MEMORY_START CONFIG_MEMORY_START #define __MEMORY_SIZE CONFIG_MEMORY_SIZE -#ifdef CONFIG_DISCONTIGMEM -/* Just for HP690, for now.. */ -#define __MEMORY_START_2ND (__MEMORY_START+0x02000000) -#define __MEMORY_SIZE_2ND 0x001000000 /* 16MB */ -#endif #define PAGE_OFFSET (0x80000000UL) #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) @@ -105,10 +100,8 @@ typedef struct { unsigned long pgprot; } pgprot_t; #define MAP_NR(addr) (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT) -#ifndef CONFIG_DISCONTIGMEM #define phys_to_page(phys) (mem_map + (((phys)-__MEMORY_START) >> PAGE_SHIFT)) #define page_to_phys(page) (((page - mem_map) << PAGE_SHIFT) + __MEMORY_START) -#endif /* PFN start number, because of __MEMORY_START */ #define PFN_START (__MEMORY_START >> PAGE_SHIFT) -- cgit v1.2.3 From 0d6d82b6712c808e461090dd483f111f72b3b38b Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 7 Nov 2005 00:58:28 -0800 Subject: [PATCH] sh: Use pfn_valid() for lazy dcache write-back on SH7705 SH7705 in extended cache mode has some left-over VALID_PAGE() cruft that it checks when doing lazy dcache write-back. This has been gone for some time (the last bits were in the discontig code, which should now also be gone -- this also fixes up a build error in the non-discontig case). pfn_valid() gives the desired behaviour, so we switch to that. Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sh/mm/tlb-sh3.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/arch/sh/mm/tlb-sh3.c b/arch/sh/mm/tlb-sh3.c index 7a0d5c10bf2..46b09e26e08 100644 --- a/arch/sh/mm/tlb-sh3.c +++ b/arch/sh/mm/tlb-sh3.c @@ -40,12 +40,17 @@ void update_mmu_cache(struct vm_area_struct * vma, return; #if defined(CONFIG_SH7705_CACHE_32KB) - struct page *page; - page = pte_page(pte); - if (VALID_PAGE(page) && !test_bit(PG_mapped, &page->flags)) { - unsigned long phys = pte_val(pte) & PTE_PHYS_MASK; - __flush_wback_region((void *)P1SEGADDR(phys), PAGE_SIZE); - __set_bit(PG_mapped, &page->flags); + { + struct page *page = pte_page(pte); + unsigned long pfn = pte_pfn(pte); + + if (pfn_valid(pfn) && !test_bit(PG_mapped, &page->flags)) { + unsigned long phys = pte_val(pte) & PTE_PHYS_MASK; + + __flush_wback_region((void *)P1SEGADDR(phys), + PAGE_SIZE); + __set_bit(PG_mapped, &page->flags); + } } #endif @@ -80,7 +85,7 @@ void __flush_tlb_page(unsigned long asid, unsigned long page) */ addr = MMU_TLB_ADDRESS_ARRAY | (page & 0x1F000); data = (page & 0xfffe0000) | asid; /* VALID bit is off */ - + if ((cpu_data->flags & CPU_HAS_MMU_PAGE_ASSOC)) { addr |= MMU_PAGE_ASSOC_BIT; ways = 1; /* we already know the way .. */ -- cgit v1.2.3 From 38e548ee1a79c8da7b3d9e26f2adce9b61413f84 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 7 Nov 2005 00:58:31 -0800 Subject: [PATCH] arch/i386: Use ARRAY_SIZE macro Use ARRAY_SIZE macro instead of sizeof(x)/sizeof(x[0]) Signed-off-by: Tobias Klauser Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/apm.c | 5 ++--- arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c | 2 +- arch/i386/kernel/mca.c | 2 +- arch/i386/kernel/reboot_fixups.c | 2 +- arch/i386/kernel/smpboot.c | 2 +- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index d2ef0c2aa93..86e80c55147 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -447,8 +447,7 @@ static char * apm_event_name[] = { "system standby resume", "capabilities change" }; -#define NR_APM_EVENT_NAME \ - (sizeof(apm_event_name) / sizeof(apm_event_name[0])) +#define NR_APM_EVENT_NAME ARRAY_SIZE(apm_event_name) typedef struct lookup_t { int key; @@ -479,7 +478,7 @@ static const lookup_t error_table[] = { { APM_NO_ERROR, "BIOS did not set a return code" }, { APM_NOT_PRESENT, "No APM present" } }; -#define ERROR_COUNT (sizeof(error_table)/sizeof(lookup_t)) +#define ERROR_COUNT ARRAY_SIZE(error_table) /** * apm_error - display an APM error diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c index 1465974256c..0ea010a7afb 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c @@ -67,7 +67,7 @@ static const struct cpu_id cpu_ids[] = { [CPU_MP4HT_D0] = {15, 3, 4 }, [CPU_MP4HT_E0] = {15, 4, 1 }, }; -#define N_IDS (sizeof(cpu_ids)/sizeof(cpu_ids[0])) +#define N_IDS ARRAY_SIZE(cpu_ids) struct cpu_model { diff --git a/arch/i386/kernel/mca.c b/arch/i386/kernel/mca.c index 8600faeea29..558bb207720 100644 --- a/arch/i386/kernel/mca.c +++ b/arch/i386/kernel/mca.c @@ -132,7 +132,7 @@ static struct resource mca_standard_resources[] = { { .start = 0x100, .end = 0x107, .name = "POS (MCA)" } }; -#define MCA_STANDARD_RESOURCES (sizeof(mca_standard_resources)/sizeof(struct resource)) +#define MCA_STANDARD_RESOURCES ARRAY_SIZE(mca_standard_resources) /** * mca_read_and_store_pos - read the POS registers into a memory buffer diff --git a/arch/i386/kernel/reboot_fixups.c b/arch/i386/kernel/reboot_fixups.c index c9b87330aee..6f73c9ea4e3 100644 --- a/arch/i386/kernel/reboot_fixups.c +++ b/arch/i386/kernel/reboot_fixups.c @@ -42,7 +42,7 @@ void mach_reboot_fixups(void) struct pci_dev *dev; int i; - for (i=0; i < (sizeof(fixups_table)/sizeof(fixups_table[0])); i++) { + for (i=0; i < ARRAY_SIZE(fixups_table); i++) { cur = &(fixups_table[i]); dev = pci_get_device(cur->vendor, cur->device, NULL); if (!dev) diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 01b618e73ec..e6488ffc1f7 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -612,7 +612,7 @@ static inline void __inquire_remote_apic(int apicid) printk("Inquiring remote APIC #%d...\n", apicid); - for (i = 0; i < sizeof(regs) / sizeof(*regs); i++) { + for (i = 0; i < ARRAY_SIZE(regs); i++) { printk("... APIC #%d %s: ", apicid, names[i]); /* -- cgit v1.2.3 From 77f72b192fd4624ad639dbf60c48be787c8aea59 Mon Sep 17 00:00:00 2001 From: Zwane Mwaikambo Date: Mon, 7 Nov 2005 00:58:33 -0800 Subject: [PATCH] i386: LVT entries remaining unmasked on reboot Excerpt from bugzilla entry http://bugzilla.kernel.org/show_bug.cgi?id=5518 "i386 version of Reboot-through-BIOS is unsafe: it forgets to mask APIC LVT interrupts before jumping to a BIOS entry point. As a result, BIOS ends up bombarded with interrupts early on boot. The BIOS does not expect it since following a "normal" hardware cpu reset, all APIC LVT registers have the Mask bit (16) set and can't generate interrupts. For example, the version of Phoenix BIOS used by VMware enables interrupts for the first time before masking/clearing APIC LVT. The APIC Timer LVT register is still set up for a timer interrupt delivery with a high vector from the previous Linux incarnation (0xef in our case). The BIOS has not fully initialized its IDT at this point and the real mode gate for 0xef remains all zeros. Vector 0xef dispatches BIOS to address 0:0, BIOS takes a #GP and eventually hangs. machine_shutdown() does attempt to shut down APIC before jumping to BIOS, but it is ineffective" Signed-off-by: Zwane Mwaikambo Cc: "Seth, Rohit" Cc: Zachary Amsden Cc: "Eric W. Biederman" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/apic.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index 7c724ffa08b..496a2c9909f 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -559,14 +559,20 @@ void __devinit setup_local_APIC(void) * If Linux enabled the LAPIC against the BIOS default * disable it down before re-entering the BIOS on shutdown. * Otherwise the BIOS may get confused and not power-off. + * Additionally clear all LVT entries before disable_local_APIC + * for the case where Linux didn't enable the LAPIC. */ void lapic_shutdown(void) { - if (!cpu_has_apic || !enabled_via_apicbase) + if (!cpu_has_apic) return; local_irq_disable(); - disable_local_APIC(); + clear_local_APIC(); + + if (enabled_via_apicbase) + disable_local_APIC(); + local_irq_enable(); } -- cgit v1.2.3 From 8d1ed6366b9f3cb54eb5aef5dae79b39b8d5ce43 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 00:58:35 -0800 Subject: [PATCH] arch/i386/kernel/ldt.c should #include Every file should #include the header files containing the prototypes of its global functions Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/ldt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/i386/kernel/ldt.c b/arch/i386/kernel/ldt.c index fe1ffa55587..983f95707e1 100644 --- a/arch/i386/kernel/ldt.c +++ b/arch/i386/kernel/ldt.c @@ -18,6 +18,7 @@ #include #include #include +#include #ifdef CONFIG_SMP /* avoids "defined but not used" warnig */ static void flush_ldt(void *null) -- cgit v1.2.3 From 5cc6135af73ad0c7897d1d00ff361e510ac23ccb Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 00:58:36 -0800 Subject: [PATCH] arch/i386/kernel/reboot_fixups.c should #include Every file should #include the header files containing the prototypes of its global functions Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/reboot_fixups.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/i386/kernel/reboot_fixups.c b/arch/i386/kernel/reboot_fixups.c index 6f73c9ea4e3..10e21a4773d 100644 --- a/arch/i386/kernel/reboot_fixups.c +++ b/arch/i386/kernel/reboot_fixups.c @@ -10,6 +10,7 @@ #include #include +#include static void cs5530a_warm_reset(struct pci_dev *dev) { -- cgit v1.2.3 From cc658cfe3c66a6124b5a8db90cdcdd440201b1dc Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 00:58:37 -0800 Subject: [PATCH] arch/i386/kernel/scx200.c should #include Every file should #include the header files containing the prototypes of its global functions Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/scx200.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/i386/kernel/scx200.c b/arch/i386/kernel/scx200.c index 69e203a0d33..9c968ae67c4 100644 --- a/arch/i386/kernel/scx200.c +++ b/arch/i386/kernel/scx200.c @@ -12,6 +12,7 @@ #include #include +#include /* Verify that the configuration block really is there */ #define scx200_cb_probe(base) (inw((base) + SCx200_CBA) == (base)) -- cgit v1.2.3 From a4c4af7c8dc1eccdfb8c57e1684f08179b4407e6 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 7 Nov 2005 00:58:38 -0800 Subject: [PATCH] cpu hoptlug: avoid usage of smp_processor_id() in preemptible code Replace smp_processor_id() with any_online_cpu(cpu_online_map) in order to avoid lots of "BUG: using smp_processor_id() in preemptible [00000001] code:..." messages in case taking a cpu online fails. All the traces start at the last notifier_call_chain(...) in kernel/cpu.c. Since we hold the cpu_control semaphore it shouldn't be any problem to access cpu_online_map. The reason why cpu_up failed is simply that the cpu that was supposed to be taken online wasn't even there. That is because on s390 we never know when a new cpu comes and therefore cpu_possible_map consists of only ones and doesn't reflect reality. Signed-off-by: Heiko Carstens Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/sched.c | 3 ++- kernel/softirq.c | 3 ++- kernel/softlockup.c | 3 ++- kernel/workqueue.c | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index b4f4eb61353..013f1448006 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -4680,7 +4680,8 @@ static int migration_call(struct notifier_block *nfb, unsigned long action, #ifdef CONFIG_HOTPLUG_CPU case CPU_UP_CANCELED: /* Unbind it from offline cpu so it can run. Fall thru. */ - kthread_bind(cpu_rq(cpu)->migration_thread,smp_processor_id()); + kthread_bind(cpu_rq(cpu)->migration_thread, + any_online_cpu(cpu_online_map)); kthread_stop(cpu_rq(cpu)->migration_thread); cpu_rq(cpu)->migration_thread = NULL; break; diff --git a/kernel/softirq.c b/kernel/softirq.c index f766b2fc48b..ad3295cdded 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -470,7 +470,8 @@ static int __devinit cpu_callback(struct notifier_block *nfb, #ifdef CONFIG_HOTPLUG_CPU case CPU_UP_CANCELED: /* Unbind so it can run. Fall thru. */ - kthread_bind(per_cpu(ksoftirqd, hotcpu), smp_processor_id()); + kthread_bind(per_cpu(ksoftirqd, hotcpu), + any_online_cpu(cpu_online_map)); case CPU_DEAD: p = per_cpu(ksoftirqd, hotcpu); per_cpu(ksoftirqd, hotcpu) = NULL; diff --git a/kernel/softlockup.c b/kernel/softlockup.c index 75976209cea..a2dcceb9437 100644 --- a/kernel/softlockup.c +++ b/kernel/softlockup.c @@ -123,7 +123,8 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) #ifdef CONFIG_HOTPLUG_CPU case CPU_UP_CANCELED: /* Unbind so it can run. Fall thru. */ - kthread_bind(per_cpu(watchdog_task, hotcpu), smp_processor_id()); + kthread_bind(per_cpu(watchdog_task, hotcpu), + any_online_cpu(cpu_online_map)); case CPU_DEAD: p = per_cpu(watchdog_task, hotcpu); per_cpu(watchdog_task, hotcpu) = NULL; diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 7cee222231b..42df83d7fad 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -524,7 +524,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, list_for_each_entry(wq, &workqueues, list) { /* Unbind so it can run. */ kthread_bind(per_cpu_ptr(wq->cpu_wq, hotcpu)->thread, - smp_processor_id()); + any_online_cpu(cpu_online_map)); cleanup_workqueue_thread(wq, hotcpu); } break; -- cgit v1.2.3 From 36fabc248e5466e3f28897819b0400b5cdbb8dc6 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 7 Nov 2005 00:58:39 -0800 Subject: [PATCH] suspend-to-ram: update docs This adds few more working systems. Signed-off-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/power/video.txt | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/Documentation/power/video.txt b/Documentation/power/video.txt index 526d6dd267e..912bed87c75 100644 --- a/Documentation/power/video.txt +++ b/Documentation/power/video.txt @@ -11,9 +11,9 @@ boot video card. (Kernel usually does not even contain video card driver -- vesafb and vgacon are widely used). This is not problem for swsusp, because during swsusp resume, BIOS is -run normally so video card is normally initialized. S3 has absolutely -no chance of working with SMP/HT. Be sure it to turn it off before -testing (swsusp should work ok, OTOH). +run normally so video card is normally initialized. It should not be +problem for S1 standby, because hardware should retain its state over +that. There are a few types of systems where video works after S3 resume: @@ -64,7 +64,7 @@ your video card (good luck getting docs :-(). Maybe suspending from X (proper X, knowing your hardware, not XF68_FBcon) might have better chance of working. -Table of known working systems: +Table of known working notebooks: Model hack (or "how to do it") ------------------------------------------------------------------------------ @@ -73,7 +73,7 @@ Acer TM 242FX vbetool (6) Acer TM C110 video_post (8) Acer TM C300 vga=normal (only suspend on console, not in X), vbetool (6) or video_post (8) Acer TM 4052LCi s3_bios (2) -Acer TM 636Lci s3_bios vga=normal (2) +Acer TM 636Lci s3_bios,s3_mode (4) Acer TM 650 (Radeon M7) vga=normal plus boot-radeon (5) gets text console back Acer TM 660 ??? (*) Acer TM 800 vga=normal, X patches, see webpage (5) or vbetool (6) @@ -137,6 +137,13 @@ Toshiba Satellite P10-554 s3_bios,s3_mode (4)(****) Toshiba M30 (2) xor X with nvidia driver using internal AGP Uniwill 244IIO ??? (*) +Known working desktop systems +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Mainboard Graphics card hack (or "how to do it") +------------------------------------------------------------------------------ +Asus A7V8X nVidia RIVA TNT2 model 64 s3_bios,s3_mode (4) + (*) from http://www.ubuntulinux.org/wiki/HoaryPMResults, not sure which options to use. If you know, please tell me. -- cgit v1.2.3 From dc19d507b17135069d9c5d6093d4458dc60e1861 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 7 Nov 2005 00:58:40 -0800 Subject: [PATCH] swsusp cleanups This cleans spaces between * and pointer up, and adds "int" in "unsigned int". Signed-off-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/power/snapshot.c | 19 +++++++++---------- kernel/power/swsusp.c | 36 ++++++++++++++++++------------------ 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 42a62870439..723f5179883 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -168,9 +168,8 @@ static unsigned count_data_pages(void) { struct zone *zone; unsigned long zone_pfn; - unsigned n; + unsigned int n = 0; - n = 0; for_each_zone (zone) { if (is_highmem(zone)) continue; @@ -250,10 +249,10 @@ static inline void fill_pb_page(struct pbe *pbpage) * of memory pages allocated with alloc_pagedir() */ -void create_pbe_list(struct pbe *pblist, unsigned nr_pages) +void create_pbe_list(struct pbe *pblist, unsigned int nr_pages) { struct pbe *pbpage, *p; - unsigned num = PBES_PER_PAGE; + unsigned int num = PBES_PER_PAGE; for_each_pb_page (pbpage, pblist) { if (num >= nr_pages) @@ -293,9 +292,9 @@ static void *alloc_image_page(void) * On each page we set up a list of struct_pbe elements. */ -struct pbe *alloc_pagedir(unsigned nr_pages) +struct pbe *alloc_pagedir(unsigned int nr_pages) { - unsigned num; + unsigned int num; struct pbe *pblist, *pbe; if (!nr_pages) @@ -329,7 +328,7 @@ void swsusp_free(void) for_each_zone(zone) { for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) if (pfn_valid(zone_pfn + zone->zone_start_pfn)) { - struct page * page; + struct page *page; page = pfn_to_page(zone_pfn + zone->zone_start_pfn); if (PageNosave(page) && PageNosaveFree(page)) { ClearPageNosave(page); @@ -348,7 +347,7 @@ void swsusp_free(void) * free pages. */ -static int enough_free_mem(unsigned nr_pages) +static int enough_free_mem(unsigned int nr_pages) { pr_debug("swsusp: available memory: %u pages\n", nr_free_pages()); return nr_free_pages() > (nr_pages + PAGES_FOR_IO + @@ -356,7 +355,7 @@ static int enough_free_mem(unsigned nr_pages) } -static struct pbe *swsusp_alloc(unsigned nr_pages) +static struct pbe *swsusp_alloc(unsigned int nr_pages) { struct pbe *pblist, *p; @@ -380,7 +379,7 @@ static struct pbe *swsusp_alloc(unsigned nr_pages) asmlinkage int swsusp_save(void) { - unsigned nr_pages; + unsigned int nr_pages; pr_debug("swsusp: critical section: \n"); if (save_highmem()) { diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 12db1d2ad61..a1300717dc3 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -122,8 +122,8 @@ static struct swsusp_info swsusp_info; static unsigned short swapfile_used[MAX_SWAPFILES]; static unsigned short root_swap; -static int write_page(unsigned long addr, swp_entry_t * loc); -static int bio_read_page(pgoff_t page_off, void * page); +static int write_page(unsigned long addr, swp_entry_t *loc); +static int bio_read_page(pgoff_t page_off, void *page); static u8 key_iv[MAXKEY+MAXIV]; @@ -355,7 +355,7 @@ static void lock_swapdevices(void) * This is a partial improvement, since we will at least return other * errors, though we need to eventually fix the damn code. */ -static int write_page(unsigned long addr, swp_entry_t * loc) +static int write_page(unsigned long addr, swp_entry_t *loc) { swp_entry_t entry; int error = 0; @@ -383,7 +383,7 @@ static int write_page(unsigned long addr, swp_entry_t * loc) static void data_free(void) { swp_entry_t entry; - struct pbe * p; + struct pbe *p; for_each_pbe(p, pagedir_nosave) { entry = p->swap_address; @@ -492,8 +492,8 @@ static void free_pagedir_entries(void) static int write_pagedir(void) { int error = 0; - unsigned n = 0; - struct pbe * pbe; + unsigned int n = 0; + struct pbe *pbe; printk( "Writing pagedir..."); for_each_pb_page (pbe, pagedir_nosave) { @@ -543,7 +543,7 @@ static int write_suspend_image(void) * We should only consider resume_device. */ -int enough_swap(unsigned nr_pages) +int enough_swap(unsigned int nr_pages) { struct sysinfo i; @@ -694,7 +694,7 @@ static int check_pagedir(struct pbe *pblist) * restore from the loaded pages later. We relocate them here. */ -static struct pbe * swsusp_pagedir_relocate(struct pbe *pblist) +static struct pbe *swsusp_pagedir_relocate(struct pbe *pblist) { struct zone *zone; unsigned long zone_pfn; @@ -770,7 +770,7 @@ static struct pbe * swsusp_pagedir_relocate(struct pbe *pblist) static atomic_t io_done = ATOMIC_INIT(0); -static int end_io(struct bio * bio, unsigned int num, int err) +static int end_io(struct bio *bio, unsigned int num, int err) { if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) panic("I/O error reading memory image"); @@ -778,7 +778,7 @@ static int end_io(struct bio * bio, unsigned int num, int err) return 0; } -static struct block_device * resume_bdev; +static struct block_device *resume_bdev; /** * submit - submit BIO request. @@ -791,10 +791,10 @@ static struct block_device * resume_bdev; * Then submit it and wait. */ -static int submit(int rw, pgoff_t page_off, void * page) +static int submit(int rw, pgoff_t page_off, void *page) { int error = 0; - struct bio * bio; + struct bio *bio; bio = bio_alloc(GFP_ATOMIC, 1); if (!bio) @@ -823,12 +823,12 @@ static int submit(int rw, pgoff_t page_off, void * page) return error; } -static int bio_read_page(pgoff_t page_off, void * page) +static int bio_read_page(pgoff_t page_off, void *page) { return submit(READ, page_off, page); } -static int bio_write_page(pgoff_t page_off, void * page) +static int bio_write_page(pgoff_t page_off, void *page) { return submit(WRITE, page_off, page); } @@ -838,7 +838,7 @@ static int bio_write_page(pgoff_t page_off, void * page) * I really don't think that it's foolproof but more than nothing.. */ -static const char * sanity_check(void) +static const char *sanity_check(void) { dump_info(); if (swsusp_info.version_code != LINUX_VERSION_CODE) @@ -864,7 +864,7 @@ static const char * sanity_check(void) static int check_header(void) { - const char * reason = NULL; + const char *reason = NULL; int error; if ((error = bio_read_page(swp_offset(swsusp_header.swsusp_info), &swsusp_info))) @@ -912,7 +912,7 @@ static int check_sig(void) static int data_read(struct pbe *pblist) { - struct pbe * p; + struct pbe *p; int error = 0; int i = 0; int mod = swsusp_info.image_pages / 100; @@ -950,7 +950,7 @@ static int data_read(struct pbe *pblist) static int read_pagedir(struct pbe *pblist) { struct pbe *pbpage, *p; - unsigned i = 0; + unsigned int i = 0; int error; if (!pblist) -- cgit v1.2.3 From 47b90ffe5c10ab9b5cfd14087b28b13109673ee5 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 7 Nov 2005 00:58:41 -0800 Subject: [PATCH] swsusp: remove unused variable Remove unused variable, and make code less evil that way. Fix whitespace around for-loop-like macro. Signed-off-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/power/swsusp.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index a1300717dc3..e1ab28b9b21 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -85,18 +85,11 @@ unsigned int nr_copy_pages __nosavedata = 0; /* Suspend pagedir is allocated before final copy, therefore it must be freed after resume - Warning: this is evil. There are actually two pagedirs at time of - resume. One is "pagedir_save", which is empty frame allocated at - time of suspend, that must be freed. Second is "pagedir_nosave", - allocated at time of resume, that travels through memory not to - collide with anything. - Warning: this is even more evil than it seems. Pagedirs this file talks about are completely different from page directories used by MMU hardware. */ suspend_pagedir_t *pagedir_nosave __nosavedata = NULL; -suspend_pagedir_t *pagedir_save; #define SWSUSP_SIG "S1SUSPEND" @@ -385,7 +378,7 @@ static void data_free(void) swp_entry_t entry; struct pbe *p; - for_each_pbe(p, pagedir_nosave) { + for_each_pbe (p, pagedir_nosave) { entry = p->swap_address; if (entry.val) swap_free(entry); -- cgit v1.2.3 From 31ab269a0307d8725737dfbbdeb5dcde7b41bc36 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Mon, 7 Nov 2005 00:58:42 -0800 Subject: [PATCH] x86: add MCE resume It's widely seen a MCE non-fatal error reported after resume. It seems MCE resume is lacked under ia32. This patch tries to fix the gap. Signed-off-by: Shaohua Li Acked-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpu/common.c | 5 +---- arch/i386/kernel/cpu/mcheck/k7.c | 2 +- arch/i386/kernel/cpu/mcheck/mce.c | 4 ++-- arch/i386/kernel/cpu/mcheck/p4.c | 4 ++-- arch/i386/kernel/cpu/mcheck/p5.c | 2 +- arch/i386/kernel/cpu/mcheck/p6.c | 2 +- arch/i386/kernel/cpu/mcheck/winchip.c | 2 +- arch/i386/power/cpu.c | 1 + include/asm-i386/processor.h | 6 ++++++ 9 files changed, 16 insertions(+), 12 deletions(-) diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index 74145a33cb0..c145fb30002 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -30,8 +30,6 @@ static int disable_x86_serial_nr __devinitdata = 1; struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {}; -extern void mcheck_init(struct cpuinfo_x86 *c); - extern int disable_pse; static void default_init(struct cpuinfo_x86 * c) @@ -429,9 +427,8 @@ void __devinit identify_cpu(struct cpuinfo_x86 *c) } /* Init Machine Check Exception if available. */ -#ifdef CONFIG_X86_MCE mcheck_init(c); -#endif + if (c == &boot_cpu_data) sysenter_setup(); enable_sep_cpu(); diff --git a/arch/i386/kernel/cpu/mcheck/k7.c b/arch/i386/kernel/cpu/mcheck/k7.c index 7c6b9c73522..fc5d5215e23 100644 --- a/arch/i386/kernel/cpu/mcheck/k7.c +++ b/arch/i386/kernel/cpu/mcheck/k7.c @@ -68,7 +68,7 @@ static fastcall void k7_machine_check(struct pt_regs * regs, long error_code) /* AMD K7 machine check is Intel like */ -void __devinit amd_mcheck_init(struct cpuinfo_x86 *c) +void amd_mcheck_init(struct cpuinfo_x86 *c) { u32 l, h; int i; diff --git a/arch/i386/kernel/cpu/mcheck/mce.c b/arch/i386/kernel/cpu/mcheck/mce.c index 2cf25d2ba0f..6170af3c271 100644 --- a/arch/i386/kernel/cpu/mcheck/mce.c +++ b/arch/i386/kernel/cpu/mcheck/mce.c @@ -16,7 +16,7 @@ #include "mce.h" -int mce_disabled __devinitdata = 0; +int mce_disabled = 0; int nr_mce_banks; EXPORT_SYMBOL_GPL(nr_mce_banks); /* non-fatal.o */ @@ -31,7 +31,7 @@ static fastcall void unexpected_machine_check(struct pt_regs * regs, long error_ void fastcall (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check; /* This has to be run for each processor */ -void __devinit mcheck_init(struct cpuinfo_x86 *c) +void mcheck_init(struct cpuinfo_x86 *c) { if (mce_disabled==1) return; diff --git a/arch/i386/kernel/cpu/mcheck/p4.c b/arch/i386/kernel/cpu/mcheck/p4.c index 1d1e885f500..fd2c459a31e 100644 --- a/arch/i386/kernel/cpu/mcheck/p4.c +++ b/arch/i386/kernel/cpu/mcheck/p4.c @@ -77,7 +77,7 @@ fastcall void smp_thermal_interrupt(struct pt_regs *regs) } /* P4/Xeon Thermal regulation detect and init */ -static void __devinit intel_init_thermal(struct cpuinfo_x86 *c) +static void intel_init_thermal(struct cpuinfo_x86 *c) { u32 l, h; unsigned int cpu = smp_processor_id(); @@ -231,7 +231,7 @@ static fastcall void intel_machine_check(struct pt_regs * regs, long error_code) } -void __devinit intel_p4_mcheck_init(struct cpuinfo_x86 *c) +void intel_p4_mcheck_init(struct cpuinfo_x86 *c) { u32 l, h; int i; diff --git a/arch/i386/kernel/cpu/mcheck/p5.c b/arch/i386/kernel/cpu/mcheck/p5.c index 3a2e24baddc..94bc43d950c 100644 --- a/arch/i386/kernel/cpu/mcheck/p5.c +++ b/arch/i386/kernel/cpu/mcheck/p5.c @@ -28,7 +28,7 @@ static fastcall void pentium_machine_check(struct pt_regs * regs, long error_cod } /* Set up machine check reporting for processors with Intel style MCE */ -void __devinit intel_p5_mcheck_init(struct cpuinfo_x86 *c) +void intel_p5_mcheck_init(struct cpuinfo_x86 *c) { u32 l, h; diff --git a/arch/i386/kernel/cpu/mcheck/p6.c b/arch/i386/kernel/cpu/mcheck/p6.c index 979b18bc95c..deeae42ce19 100644 --- a/arch/i386/kernel/cpu/mcheck/p6.c +++ b/arch/i386/kernel/cpu/mcheck/p6.c @@ -79,7 +79,7 @@ static fastcall void intel_machine_check(struct pt_regs * regs, long error_code) } /* Set up machine check reporting for processors with Intel style MCE */ -void __devinit intel_p6_mcheck_init(struct cpuinfo_x86 *c) +void intel_p6_mcheck_init(struct cpuinfo_x86 *c) { u32 l, h; int i; diff --git a/arch/i386/kernel/cpu/mcheck/winchip.c b/arch/i386/kernel/cpu/mcheck/winchip.c index 5b9d2dd411d..9e424b6c293 100644 --- a/arch/i386/kernel/cpu/mcheck/winchip.c +++ b/arch/i386/kernel/cpu/mcheck/winchip.c @@ -22,7 +22,7 @@ static fastcall void winchip_machine_check(struct pt_regs * regs, long error_cod } /* Set up machine check reporting on the Winchip C6 series */ -void __devinit winchip_mcheck_init(struct cpuinfo_x86 *c) +void winchip_mcheck_init(struct cpuinfo_x86 *c) { u32 lo, hi; machine_check_vector = winchip_machine_check; diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c index 1f1572692e0..50a0bef8c85 100644 --- a/arch/i386/power/cpu.c +++ b/arch/i386/power/cpu.c @@ -118,6 +118,7 @@ void __restore_processor_state(struct saved_context *ctxt) fix_processor_context(); do_fpu_end(); mtrr_ap_init(); + mcheck_init(&boot_cpu_data); } void restore_processor_state(void) diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index 0a4ec764377..8c02b031870 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h @@ -718,4 +718,10 @@ extern void mtrr_bp_init(void); #define mtrr_bp_init() do {} while (0) #endif +#ifdef CONFIG_X86_MCE +extern void mcheck_init(struct cpuinfo_x86 *c); +#else +#define mcheck_init(c) do {} while(0) +#endif + #endif /* __ASM_I386_PROCESSOR_H */ -- cgit v1.2.3 From 5f9c3cbcd5d41be597aef9c0ff64ebfc8a91cd6f Mon Sep 17 00:00:00 2001 From: Arthur Othieno Date: Mon, 7 Nov 2005 00:58:43 -0800 Subject: [PATCH] cris: printk() duplicate declaration printk() already declared in include/linux/kernel.h so squish the duplication. Besides, no printk() usage here. Bye bye. Signed-off-by: Arthur Othieno Cc: Mikael Starvik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-cris/semaphore.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/asm-cris/semaphore.h b/include/asm-cris/semaphore.h index 39faf69bcf7..a19568e6aae 100644 --- a/include/asm-cris/semaphore.h +++ b/include/asm-cris/semaphore.h @@ -18,8 +18,6 @@ * CRIS semaphores, implemented in C-only so far. */ -int printk(const char *fmt, ...); - struct semaphore { atomic_t count; atomic_t waking; -- cgit v1.2.3 From d9b5444eeb3a663ca4a625878b1421c9e9b18e8b Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 00:58:44 -0800 Subject: [PATCH] cris: "extern inline" -> "static inline" "extern inline" doesn't make much sense. Signed-off-by: Adrian Bunk Acked-by: Mikael Starvik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/cris/arch-v10/README.mm | 6 ++--- arch/cris/arch-v10/kernel/signal.c | 2 +- arch/cris/arch-v32/kernel/signal.c | 2 +- arch/cris/mm/ioremap.c | 2 +- include/asm-cris/arch-v10/byteorder.h | 4 +-- include/asm-cris/arch-v10/checksum.h | 2 +- include/asm-cris/arch-v10/delay.h | 2 +- include/asm-cris/arch-v10/ide.h | 8 +++--- include/asm-cris/arch-v10/system.h | 8 +++--- include/asm-cris/arch-v10/thread_info.h | 2 +- include/asm-cris/arch-v10/timex.h | 2 +- include/asm-cris/arch-v10/uaccess.h | 4 +-- include/asm-cris/arch-v32/bitops.h | 10 +++---- include/asm-cris/arch-v32/byteorder.h | 4 +-- include/asm-cris/arch-v32/checksum.h | 2 +- include/asm-cris/arch-v32/delay.h | 2 +- include/asm-cris/arch-v32/ide.h | 4 +-- include/asm-cris/arch-v32/io.h | 6 ++--- include/asm-cris/arch-v32/system.h | 6 ++--- include/asm-cris/arch-v32/thread_info.h | 2 +- include/asm-cris/arch-v32/timex.h | 2 +- include/asm-cris/arch-v32/uaccess.h | 4 +-- include/asm-cris/atomic.h | 22 ++++++++-------- include/asm-cris/bitops.h | 18 ++++++------- include/asm-cris/checksum.h | 8 +++--- include/asm-cris/current.h | 2 +- include/asm-cris/delay.h | 2 +- include/asm-cris/io.h | 6 ++--- include/asm-cris/irq.h | 2 +- include/asm-cris/pgalloc.h | 12 ++++----- include/asm-cris/pgtable.h | 46 ++++++++++++++++----------------- include/asm-cris/processor.h | 4 +-- include/asm-cris/semaphore.h | 14 +++++----- include/asm-cris/system.h | 2 +- include/asm-cris/timex.h | 2 +- include/asm-cris/tlbflush.h | 4 +-- include/asm-cris/uaccess.h | 22 ++++++++-------- include/asm-cris/unistd.h | 20 +++++++------- 38 files changed, 136 insertions(+), 136 deletions(-) diff --git a/arch/cris/arch-v10/README.mm b/arch/cris/arch-v10/README.mm index 6f08903f313..517d1f027fe 100644 --- a/arch/cris/arch-v10/README.mm +++ b/arch/cris/arch-v10/README.mm @@ -177,7 +177,7 @@ The example address is 0xd004000c; in binary this is: Given the top-level Page Directory, the offset in that directory is calculated using the upper 8 bits: -extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address) +static inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address) { return mm->pgd + (address >> PGDIR_SHIFT); } @@ -190,14 +190,14 @@ The pgd_t from our example will therefore be the 208'th (0xd0) entry in mm->pgd. Since the Middle Directory does not exist, it is a unity mapping: -extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) +static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) { return (pmd_t *) dir; } The Page Table provides the final lookup by using bits 13 to 23 as index: -extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address) +static inline pte_t * pte_offset(pmd_t * dir, unsigned long address) { return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)); diff --git a/arch/cris/arch-v10/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c index 693771961f8..19bcad05716 100644 --- a/arch/cris/arch-v10/kernel/signal.c +++ b/arch/cris/arch-v10/kernel/signal.c @@ -476,7 +476,7 @@ give_sigsegv: * OK, we're invoking a handler */ -extern inline void +static inline void handle_signal(int canrestart, unsigned long sig, siginfo_t *info, struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs) diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c index 0a3614dab88..99e59b3eacf 100644 --- a/arch/cris/arch-v32/kernel/signal.c +++ b/arch/cris/arch-v32/kernel/signal.c @@ -513,7 +513,7 @@ give_sigsegv: } /* Invoke a singal handler to, well, handle the signal. */ -extern inline void +static inline void handle_signal(int canrestart, unsigned long sig, siginfo_t *info, struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs) diff --git a/arch/cris/mm/ioremap.c b/arch/cris/mm/ioremap.c index a92ac987758..1780df3ed9e 100644 --- a/arch/cris/mm/ioremap.c +++ b/arch/cris/mm/ioremap.c @@ -16,7 +16,7 @@ #include #include -extern inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, +static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, unsigned long phys_addr, pgprot_t prot) { unsigned long end; diff --git a/include/asm-cris/arch-v10/byteorder.h b/include/asm-cris/arch-v10/byteorder.h index e24465d1f40..255b646b7fa 100644 --- a/include/asm-cris/arch-v10/byteorder.h +++ b/include/asm-cris/arch-v10/byteorder.h @@ -9,14 +9,14 @@ * them together into ntohl etc. */ -extern __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x) +static inline __attribute_const__ __u32 ___arch__swab32(__u32 x) { __asm__ ("swapwb %0" : "=r" (x) : "0" (x)); return(x); } -extern __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x) +static inline __attribute_const__ __u16 ___arch__swab16(__u16 x) { __asm__ ("swapb %0" : "=r" (x) : "0" (x)); diff --git a/include/asm-cris/arch-v10/checksum.h b/include/asm-cris/arch-v10/checksum.h index fde1d00aaa9..633f234f336 100644 --- a/include/asm-cris/arch-v10/checksum.h +++ b/include/asm-cris/arch-v10/checksum.h @@ -8,7 +8,7 @@ * to split all of those into 16-bit components, then add. */ -extern inline unsigned int +static inline unsigned int csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len, unsigned short proto, unsigned int sum) { diff --git a/include/asm-cris/arch-v10/delay.h b/include/asm-cris/arch-v10/delay.h index cfedae0d2f5..39481f6e0c3 100644 --- a/include/asm-cris/arch-v10/delay.h +++ b/include/asm-cris/arch-v10/delay.h @@ -1,7 +1,7 @@ #ifndef _CRIS_ARCH_DELAY_H #define _CRIS_ARCH_DELAY_H -extern __inline__ void __delay(int loops) +static inline void __delay(int loops) { __asm__ __volatile__ ( "move.d %0,$r9\n\t" diff --git a/include/asm-cris/arch-v10/ide.h b/include/asm-cris/arch-v10/ide.h index 8cf2d7cb22a..78b301ed7b1 100644 --- a/include/asm-cris/arch-v10/ide.h +++ b/include/asm-cris/arch-v10/ide.h @@ -25,7 +25,7 @@ #define MAX_HWIFS 4 -extern __inline__ int ide_default_irq(unsigned long base) +static inline int ide_default_irq(unsigned long base) { /* all IDE busses share the same IRQ, number 4. * this has the side-effect that ide-probe.c will cluster our 4 interfaces @@ -35,7 +35,7 @@ extern __inline__ int ide_default_irq(unsigned long base) return 4; } -extern __inline__ unsigned long ide_default_io_base(int index) +static inline unsigned long ide_default_io_base(int index) { /* we have no real I/O base address per interface, since all go through the * same register. but in a bitfield in that register, we have the i/f number. @@ -54,7 +54,7 @@ extern __inline__ unsigned long ide_default_io_base(int index) * of the ide_default_io_base call above. ctrl_port will be 0, but that is don't care for us. */ -extern __inline__ void ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, unsigned long ctrl_port, int *irq) +static inline void ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, unsigned long ctrl_port, int *irq) { int i; @@ -77,7 +77,7 @@ extern __inline__ void ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_por hw->io_ports[IDE_IRQ_OFFSET] = 0; } -extern __inline__ void ide_init_default_hwifs(void) +static inline void ide_init_default_hwifs(void) { hw_regs_t hw; int index; diff --git a/include/asm-cris/arch-v10/system.h b/include/asm-cris/arch-v10/system.h index 6cc35642b8a..1ac7b639b1b 100644 --- a/include/asm-cris/arch-v10/system.h +++ b/include/asm-cris/arch-v10/system.h @@ -5,7 +5,7 @@ /* read the CPU version register */ -extern inline unsigned long rdvr(void) { +static inline unsigned long rdvr(void) { unsigned char vr; __asm__ volatile ("move $vr,%0" : "=rm" (vr)); return vr; @@ -15,7 +15,7 @@ extern inline unsigned long rdvr(void) { /* read/write the user-mode stackpointer */ -extern inline unsigned long rdusp(void) { +static inline unsigned long rdusp(void) { unsigned long usp; __asm__ __volatile__("move $usp,%0" : "=rm" (usp)); return usp; @@ -26,13 +26,13 @@ extern inline unsigned long rdusp(void) { /* read the current stackpointer */ -extern inline unsigned long rdsp(void) { +static inline unsigned long rdsp(void) { unsigned long sp; __asm__ __volatile__("move.d $sp,%0" : "=rm" (sp)); return sp; } -extern inline unsigned long _get_base(char * addr) +static inline unsigned long _get_base(char * addr) { return 0; } diff --git a/include/asm-cris/arch-v10/thread_info.h b/include/asm-cris/arch-v10/thread_info.h index 357f5df0c90..218f4152d3e 100644 --- a/include/asm-cris/arch-v10/thread_info.h +++ b/include/asm-cris/arch-v10/thread_info.h @@ -2,7 +2,7 @@ #define _ASM_ARCH_THREAD_INFO_H /* how to get the thread information struct from C */ -extern inline struct thread_info *current_thread_info(void) +static inline struct thread_info *current_thread_info(void) { struct thread_info *ti; __asm__("and.d $sp,%0; ":"=r" (ti) : "0" (~8191UL)); diff --git a/include/asm-cris/arch-v10/timex.h b/include/asm-cris/arch-v10/timex.h index ecfc553c06a..e48447d94fa 100644 --- a/include/asm-cris/arch-v10/timex.h +++ b/include/asm-cris/arch-v10/timex.h @@ -22,7 +22,7 @@ unsigned long get_ns_in_jiffie(void); -extern inline unsigned long get_us_in_jiffie_highres(void) +static inline unsigned long get_us_in_jiffie_highres(void) { return get_ns_in_jiffie()/1000; } diff --git a/include/asm-cris/arch-v10/uaccess.h b/include/asm-cris/arch-v10/uaccess.h index 787d2e60c83..65b02d9b605 100644 --- a/include/asm-cris/arch-v10/uaccess.h +++ b/include/asm-cris/arch-v10/uaccess.h @@ -87,7 +87,7 @@ * bytes copied if we hit a null byte * (without the null byte) */ -extern inline long +static inline long __do_strncpy_from_user(char *dst, const char *src, long count) { long res; @@ -602,7 +602,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) * or 0 for error. Return a value greater than N if too long. */ -extern inline long +static inline long strnlen_user(const char *s, long n) { long res, tmp1; diff --git a/include/asm-cris/arch-v32/bitops.h b/include/asm-cris/arch-v32/bitops.h index e40a58d3b86..147689d6b62 100644 --- a/include/asm-cris/arch-v32/bitops.h +++ b/include/asm-cris/arch-v32/bitops.h @@ -8,7 +8,7 @@ * inverts all bits in the input. */ -extern inline unsigned long +static inline unsigned long cris_swapnwbrlz(unsigned long w) { unsigned long res; @@ -20,7 +20,7 @@ cris_swapnwbrlz(unsigned long w) return res; } -extern inline unsigned long +static inline unsigned long cris_swapwbrlz(unsigned long w) { unsigned long res; @@ -36,7 +36,7 @@ cris_swapwbrlz(unsigned long w) * Find First Zero in word. Undefined if no zero exist, so the caller should * check against ~0 first. */ -extern inline unsigned long +static inline unsigned long ffz(unsigned long w) { return cris_swapnwbrlz(w); @@ -46,7 +46,7 @@ ffz(unsigned long w) * Find First Set bit in word. Undefined if no 1 exist, so the caller * should check against 0 first. */ -extern inline unsigned long +static inline unsigned long __ffs(unsigned long w) { return cris_swapnwbrlz(~w); @@ -55,7 +55,7 @@ __ffs(unsigned long w) /* * Find First Bit that is set. */ -extern inline unsigned long +static inline unsigned long kernel_ffs(unsigned long w) { return w ? cris_swapwbrlz (w) + 1 : 0; diff --git a/include/asm-cris/arch-v32/byteorder.h b/include/asm-cris/arch-v32/byteorder.h index 74846ee6cf9..6ef8fb4a35f 100644 --- a/include/asm-cris/arch-v32/byteorder.h +++ b/include/asm-cris/arch-v32/byteorder.h @@ -3,14 +3,14 @@ #include -extern __inline__ __const__ __u32 +static inline __const__ __u32 ___arch__swab32(__u32 x) { __asm__ __volatile__ ("swapwb %0" : "=r" (x) : "0" (x)); return (x); } -extern __inline__ __const__ __u16 +static inline __const__ __u16 ___arch__swab16(__u16 x) { __asm__ __volatile__ ("swapb %0" : "=r" (x) : "0" (x)); diff --git a/include/asm-cris/arch-v32/checksum.h b/include/asm-cris/arch-v32/checksum.h index a1d6b2a6cc4..97ef89efea6 100644 --- a/include/asm-cris/arch-v32/checksum.h +++ b/include/asm-cris/arch-v32/checksum.h @@ -9,7 +9,7 @@ * checksum. Which means it would be necessary to split all those into * 16-bit components and then add. */ -extern inline unsigned int +static inline unsigned int csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len, unsigned short proto, unsigned int sum) { diff --git a/include/asm-cris/arch-v32/delay.h b/include/asm-cris/arch-v32/delay.h index f36f7f760e8..b6e941e637d 100644 --- a/include/asm-cris/arch-v32/delay.h +++ b/include/asm-cris/arch-v32/delay.h @@ -1,7 +1,7 @@ #ifndef _ASM_CRIS_ARCH_DELAY_H #define _ASM_CRIS_ARCH_DELAY_H -extern __inline__ void +static inline void __delay(int loops) { __asm__ __volatile__ ( diff --git a/include/asm-cris/arch-v32/ide.h b/include/asm-cris/arch-v32/ide.h index 24f5604f566..6590f657500 100644 --- a/include/asm-cris/arch-v32/ide.h +++ b/include/asm-cris/arch-v32/ide.h @@ -26,7 +26,7 @@ #define MAX_HWIFS 4 -extern __inline__ int ide_default_irq(unsigned long base) +static inline int ide_default_irq(unsigned long base) { /* all IDE busses share the same IRQ, * this has the side-effect that ide-probe.c will cluster our 4 interfaces @@ -36,7 +36,7 @@ extern __inline__ int ide_default_irq(unsigned long base) return ATA_INTR_VECT; } -extern __inline__ unsigned long ide_default_io_base(int index) +static inline unsigned long ide_default_io_base(int index) { reg_ata_rw_ctrl2 ctrl2 = {.sel = index}; /* we have no real I/O base address per interface, since all go through the diff --git a/include/asm-cris/arch-v32/io.h b/include/asm-cris/arch-v32/io.h index 4c80263ec63..043c9ce5294 100644 --- a/include/asm-cris/arch-v32/io.h +++ b/include/asm-cris/arch-v32/io.h @@ -35,7 +35,7 @@ extern struct crisv32_iopin crisv32_led2_red; extern struct crisv32_iopin crisv32_led3_green; extern struct crisv32_iopin crisv32_led3_red; -extern inline void crisv32_io_set(struct crisv32_iopin* iopin, +static inline void crisv32_io_set(struct crisv32_iopin* iopin, int val) { if (val) @@ -44,7 +44,7 @@ extern inline void crisv32_io_set(struct crisv32_iopin* iopin, *iopin->port->data &= ~iopin->bit; } -extern inline void crisv32_io_set_dir(struct crisv32_iopin* iopin, +static inline void crisv32_io_set_dir(struct crisv32_iopin* iopin, enum crisv32_io_dir dir) { if (dir == crisv32_io_dir_in) @@ -53,7 +53,7 @@ extern inline void crisv32_io_set_dir(struct crisv32_iopin* iopin, *iopin->port->oe |= iopin->bit; } -extern inline int crisv32_io_rd(struct crisv32_iopin* iopin) +static inline int crisv32_io_rd(struct crisv32_iopin* iopin) { return ((*iopin->port->data_in & iopin->bit) ? 1 : 0); } diff --git a/include/asm-cris/arch-v32/system.h b/include/asm-cris/arch-v32/system.h index b9afbb95e0b..a3d75d581e2 100644 --- a/include/asm-cris/arch-v32/system.h +++ b/include/asm-cris/arch-v32/system.h @@ -4,7 +4,7 @@ #include /* Read the CPU version register. */ -extern inline unsigned long rdvr(void) +static inline unsigned long rdvr(void) { unsigned char vr; @@ -15,7 +15,7 @@ extern inline unsigned long rdvr(void) #define cris_machine_name "crisv32" /* Read the user-mode stack pointer. */ -extern inline unsigned long rdusp(void) +static inline unsigned long rdusp(void) { unsigned long usp; @@ -24,7 +24,7 @@ extern inline unsigned long rdusp(void) } /* Read the current stack pointer. */ -extern inline unsigned long rdsp(void) +static inline unsigned long rdsp(void) { unsigned long sp; diff --git a/include/asm-cris/arch-v32/thread_info.h b/include/asm-cris/arch-v32/thread_info.h index a7a182307da..d6936956a3c 100644 --- a/include/asm-cris/arch-v32/thread_info.h +++ b/include/asm-cris/arch-v32/thread_info.h @@ -2,7 +2,7 @@ #define _ASM_CRIS_ARCH_THREAD_INFO_H /* Return a thread_info struct. */ -extern inline struct thread_info *current_thread_info(void) +static inline struct thread_info *current_thread_info(void) { struct thread_info *ti; diff --git a/include/asm-cris/arch-v32/timex.h b/include/asm-cris/arch-v32/timex.h index 4d0fd23b21e..5a4aa285d5f 100644 --- a/include/asm-cris/arch-v32/timex.h +++ b/include/asm-cris/arch-v32/timex.h @@ -22,7 +22,7 @@ extern unsigned long get_ns_in_jiffie(void); -extern inline unsigned long get_us_in_jiffie_highres(void) +static inline unsigned long get_us_in_jiffie_highres(void) { return get_ns_in_jiffie() / 1000; } diff --git a/include/asm-cris/arch-v32/uaccess.h b/include/asm-cris/arch-v32/uaccess.h index 055a0bdbe83..6b207f1b662 100644 --- a/include/asm-cris/arch-v32/uaccess.h +++ b/include/asm-cris/arch-v32/uaccess.h @@ -93,7 +93,7 @@ * bytes copied if we hit a null byte * (without the null byte) */ -extern inline long +static inline long __do_strncpy_from_user(char *dst, const char *src, long count) { long res; @@ -695,7 +695,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count) * or 0 for error. Return a value greater than N if too long. */ -extern inline long +static inline long strnlen_user(const char *s, long n) { long res, tmp1; diff --git a/include/asm-cris/atomic.h b/include/asm-cris/atomic.h index 70605b09e8b..8c2e7830452 100644 --- a/include/asm-cris/atomic.h +++ b/include/asm-cris/atomic.h @@ -20,7 +20,7 @@ typedef struct { volatile int counter; } atomic_t; /* These should be written in asm but we do it in C for now. */ -extern __inline__ void atomic_add(int i, volatile atomic_t *v) +static inline void atomic_add(int i, volatile atomic_t *v) { unsigned long flags; cris_atomic_save(v, flags); @@ -28,7 +28,7 @@ extern __inline__ void atomic_add(int i, volatile atomic_t *v) cris_atomic_restore(v, flags); } -extern __inline__ void atomic_sub(int i, volatile atomic_t *v) +static inline void atomic_sub(int i, volatile atomic_t *v) { unsigned long flags; cris_atomic_save(v, flags); @@ -36,7 +36,7 @@ extern __inline__ void atomic_sub(int i, volatile atomic_t *v) cris_atomic_restore(v, flags); } -extern __inline__ int atomic_add_return(int i, volatile atomic_t *v) +static inline int atomic_add_return(int i, volatile atomic_t *v) { unsigned long flags; int retval; @@ -48,7 +48,7 @@ extern __inline__ int atomic_add_return(int i, volatile atomic_t *v) #define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) -extern __inline__ int atomic_sub_return(int i, volatile atomic_t *v) +static inline int atomic_sub_return(int i, volatile atomic_t *v) { unsigned long flags; int retval; @@ -58,7 +58,7 @@ extern __inline__ int atomic_sub_return(int i, volatile atomic_t *v) return retval; } -extern __inline__ int atomic_sub_and_test(int i, volatile atomic_t *v) +static inline int atomic_sub_and_test(int i, volatile atomic_t *v) { int retval; unsigned long flags; @@ -68,7 +68,7 @@ extern __inline__ int atomic_sub_and_test(int i, volatile atomic_t *v) return retval; } -extern __inline__ void atomic_inc(volatile atomic_t *v) +static inline void atomic_inc(volatile atomic_t *v) { unsigned long flags; cris_atomic_save(v, flags); @@ -76,7 +76,7 @@ extern __inline__ void atomic_inc(volatile atomic_t *v) cris_atomic_restore(v, flags); } -extern __inline__ void atomic_dec(volatile atomic_t *v) +static inline void atomic_dec(volatile atomic_t *v) { unsigned long flags; cris_atomic_save(v, flags); @@ -84,7 +84,7 @@ extern __inline__ void atomic_dec(volatile atomic_t *v) cris_atomic_restore(v, flags); } -extern __inline__ int atomic_inc_return(volatile atomic_t *v) +static inline int atomic_inc_return(volatile atomic_t *v) { unsigned long flags; int retval; @@ -94,7 +94,7 @@ extern __inline__ int atomic_inc_return(volatile atomic_t *v) return retval; } -extern __inline__ int atomic_dec_return(volatile atomic_t *v) +static inline int atomic_dec_return(volatile atomic_t *v) { unsigned long flags; int retval; @@ -103,7 +103,7 @@ extern __inline__ int atomic_dec_return(volatile atomic_t *v) cris_atomic_restore(v, flags); return retval; } -extern __inline__ int atomic_dec_and_test(volatile atomic_t *v) +static inline int atomic_dec_and_test(volatile atomic_t *v) { int retval; unsigned long flags; @@ -113,7 +113,7 @@ extern __inline__ int atomic_dec_and_test(volatile atomic_t *v) return retval; } -extern __inline__ int atomic_inc_and_test(volatile atomic_t *v) +static inline int atomic_inc_and_test(volatile atomic_t *v) { int retval; unsigned long flags; diff --git a/include/asm-cris/bitops.h b/include/asm-cris/bitops.h index e3da57f9796..1bddb3f3a28 100644 --- a/include/asm-cris/bitops.h +++ b/include/asm-cris/bitops.h @@ -89,7 +89,7 @@ struct __dummy { unsigned long a[100]; }; * It also implies a memory barrier. */ -extern inline int test_and_set_bit(int nr, volatile unsigned long *addr) +static inline int test_and_set_bit(int nr, volatile unsigned long *addr) { unsigned int mask, retval; unsigned long flags; @@ -105,7 +105,7 @@ extern inline int test_and_set_bit(int nr, volatile unsigned long *addr) return retval; } -extern inline int __test_and_set_bit(int nr, volatile unsigned long *addr) +static inline int __test_and_set_bit(int nr, volatile unsigned long *addr) { unsigned int mask, retval; unsigned int *adr = (unsigned int *)addr; @@ -132,7 +132,7 @@ extern inline int __test_and_set_bit(int nr, volatile unsigned long *addr) * It also implies a memory barrier. */ -extern inline int test_and_clear_bit(int nr, volatile unsigned long *addr) +static inline int test_and_clear_bit(int nr, volatile unsigned long *addr) { unsigned int mask, retval; unsigned long flags; @@ -157,7 +157,7 @@ extern inline int test_and_clear_bit(int nr, volatile unsigned long *addr) * but actually fail. You must protect multiple accesses with a lock. */ -extern inline int __test_and_clear_bit(int nr, volatile unsigned long *addr) +static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr) { unsigned int mask, retval; unsigned int *adr = (unsigned int *)addr; @@ -177,7 +177,7 @@ extern inline int __test_and_clear_bit(int nr, volatile unsigned long *addr) * It also implies a memory barrier. */ -extern inline int test_and_change_bit(int nr, volatile unsigned long *addr) +static inline int test_and_change_bit(int nr, volatile unsigned long *addr) { unsigned int mask, retval; unsigned long flags; @@ -193,7 +193,7 @@ extern inline int test_and_change_bit(int nr, volatile unsigned long *addr) /* WARNING: non atomic and it can be reordered! */ -extern inline int __test_and_change_bit(int nr, volatile unsigned long *addr) +static inline int __test_and_change_bit(int nr, volatile unsigned long *addr) { unsigned int mask, retval; unsigned int *adr = (unsigned int *)addr; @@ -214,7 +214,7 @@ extern inline int __test_and_change_bit(int nr, volatile unsigned long *addr) * This routine doesn't need to be atomic. */ -extern inline int test_bit(int nr, const volatile unsigned long *addr) +static inline int test_bit(int nr, const volatile unsigned long *addr) { unsigned int mask; unsigned int *adr = (unsigned int *)addr; @@ -258,7 +258,7 @@ extern inline int test_bit(int nr, const volatile unsigned long *addr) * @offset: The bitnumber to start searching at * @size: The maximum size to search */ -extern inline int find_next_zero_bit (const unsigned long * addr, int size, int offset) +static inline int find_next_zero_bit (const unsigned long * addr, int size, int offset) { unsigned long *p = ((unsigned long *) addr) + (offset >> 5); unsigned long result = offset & ~31UL; @@ -366,7 +366,7 @@ found_middle: #define minix_test_bit(nr,addr) test_bit(nr,addr) #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) -extern inline int sched_find_first_bit(const unsigned long *b) +static inline int sched_find_first_bit(const unsigned long *b) { if (unlikely(b[0])) return __ffs(b[0]); diff --git a/include/asm-cris/checksum.h b/include/asm-cris/checksum.h index 15ca8aec5c6..26a7719bbb8 100644 --- a/include/asm-cris/checksum.h +++ b/include/asm-cris/checksum.h @@ -34,7 +34,7 @@ unsigned int csum_partial_copy_nocheck(const char *src, char *dst, * Fold a partial checksum into a word */ -extern inline unsigned int csum_fold(unsigned int sum) +static inline unsigned int csum_fold(unsigned int sum) { /* the while loop is unnecessary really, it's always enough with two iterations */ @@ -55,7 +55,7 @@ extern unsigned int csum_partial_copy_from_user(const char *src, char *dst, * */ -extern inline unsigned short ip_fast_csum(unsigned char * iph, +static inline unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl) { return csum_fold(csum_partial(iph, ihl * 4, 0)); @@ -66,7 +66,7 @@ extern inline unsigned short ip_fast_csum(unsigned char * iph, * returns a 16-bit checksum, already complemented */ -extern inline unsigned short int csum_tcpudp_magic(unsigned long saddr, +static inline unsigned short int csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len, unsigned short proto, @@ -80,7 +80,7 @@ extern inline unsigned short int csum_tcpudp_magic(unsigned long saddr, * in icmp.c */ -extern inline unsigned short ip_compute_csum(unsigned char * buff, int len) { +static inline unsigned short ip_compute_csum(unsigned char * buff, int len) { return csum_fold (csum_partial(buff, len, 0)); } diff --git a/include/asm-cris/current.h b/include/asm-cris/current.h index dce69c99da3..5f5c0efd00b 100644 --- a/include/asm-cris/current.h +++ b/include/asm-cris/current.h @@ -5,7 +5,7 @@ struct task_struct; -extern inline struct task_struct * get_current(void) +static inline struct task_struct * get_current(void) { return current_thread_info()->task; } diff --git a/include/asm-cris/delay.h b/include/asm-cris/delay.h index efc41aad484..d3a39780371 100644 --- a/include/asm-cris/delay.h +++ b/include/asm-cris/delay.h @@ -13,7 +13,7 @@ extern unsigned long loops_per_usec; /* arch/cris/mm/init.c */ -extern __inline__ void udelay(unsigned long usecs) +static inline void udelay(unsigned long usecs) { __delay(usecs * loops_per_usec); } diff --git a/include/asm-cris/io.h b/include/asm-cris/io.h index 16e791b3c72..716c69bc58f 100644 --- a/include/asm-cris/io.h +++ b/include/asm-cris/io.h @@ -23,12 +23,12 @@ extern struct cris_io_operations *cris_iops; * Change virtual addresses to physical addresses and vv. */ -extern inline unsigned long virt_to_phys(volatile void * address) +static inline unsigned long virt_to_phys(volatile void * address) { return __pa(address); } -extern inline void * phys_to_virt(unsigned long address) +static inline void * phys_to_virt(unsigned long address) { return __va(address); } @@ -36,7 +36,7 @@ extern inline void * phys_to_virt(unsigned long address) extern void __iomem * __ioremap(unsigned long offset, unsigned long size, unsigned long flags); extern void __iomem * __ioremap_prot(unsigned long phys_addr, unsigned long size, pgprot_t prot); -extern inline void __iomem * ioremap (unsigned long offset, unsigned long size) +static inline void __iomem * ioremap (unsigned long offset, unsigned long size) { return __ioremap(offset, size, 0); } diff --git a/include/asm-cris/irq.h b/include/asm-cris/irq.h index 4fab5c3b2e1..4b338792218 100644 --- a/include/asm-cris/irq.h +++ b/include/asm-cris/irq.h @@ -8,7 +8,7 @@ #include -extern __inline__ int irq_canonicalize(int irq) +static inline int irq_canonicalize(int irq) { return irq; } diff --git a/include/asm-cris/pgalloc.h b/include/asm-cris/pgalloc.h index a131776edf4..deaddfe79bb 100644 --- a/include/asm-cris/pgalloc.h +++ b/include/asm-cris/pgalloc.h @@ -11,35 +11,35 @@ * Allocate and free page tables. */ -extern inline pgd_t *pgd_alloc (struct mm_struct *mm) +static inline pgd_t *pgd_alloc (struct mm_struct *mm) { return (pgd_t *)get_zeroed_page(GFP_KERNEL); } -extern inline void pgd_free (pgd_t *pgd) +static inline void pgd_free (pgd_t *pgd) { free_page((unsigned long)pgd); } -extern inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) +static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) { pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); return pte; } -extern inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) +static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) { struct page *pte; pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0); return pte; } -extern inline void pte_free_kernel(pte_t *pte) +static inline void pte_free_kernel(pte_t *pte) { free_page((unsigned long)pte); } -extern inline void pte_free(struct page *pte) +static inline void pte_free(struct page *pte) { __free_page(pte); } diff --git a/include/asm-cris/pgtable.h b/include/asm-cris/pgtable.h index a9143bed99d..70a832514f6 100644 --- a/include/asm-cris/pgtable.h +++ b/include/asm-cris/pgtable.h @@ -112,44 +112,44 @@ extern unsigned long empty_zero_page; * Undefined behaviour if not.. */ -extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; } -extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; } -extern inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_READ; } -extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_MODIFIED; } -extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } -extern inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; } - -extern inline pte_t pte_wrprotect(pte_t pte) +static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; } +static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; } +static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_READ; } +static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_MODIFIED; } +static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } +static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; } + +static inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE); return pte; } -extern inline pte_t pte_rdprotect(pte_t pte) +static inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ); return pte; } -extern inline pte_t pte_exprotect(pte_t pte) +static inline pte_t pte_exprotect(pte_t pte) { pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ); return pte; } -extern inline pte_t pte_mkclean(pte_t pte) +static inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE); return pte; } -extern inline pte_t pte_mkold(pte_t pte) +static inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~(_PAGE_ACCESSED | _PAGE_SILENT_READ); return pte; } -extern inline pte_t pte_mkwrite(pte_t pte) +static inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_WRITE; if (pte_val(pte) & _PAGE_MODIFIED) @@ -157,7 +157,7 @@ extern inline pte_t pte_mkwrite(pte_t pte) return pte; } -extern inline pte_t pte_mkread(pte_t pte) +static inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_READ; if (pte_val(pte) & _PAGE_ACCESSED) @@ -165,7 +165,7 @@ extern inline pte_t pte_mkread(pte_t pte) return pte; } -extern inline pte_t pte_mkexec(pte_t pte) +static inline pte_t pte_mkexec(pte_t pte) { pte_val(pte) |= _PAGE_READ; if (pte_val(pte) & _PAGE_ACCESSED) @@ -173,7 +173,7 @@ extern inline pte_t pte_mkexec(pte_t pte) return pte; } -extern inline pte_t pte_mkdirty(pte_t pte) +static inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_MODIFIED; if (pte_val(pte) & _PAGE_WRITE) @@ -181,7 +181,7 @@ extern inline pte_t pte_mkdirty(pte_t pte) return pte; } -extern inline pte_t pte_mkyoung(pte_t pte) +static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; if (pte_val(pte) & _PAGE_READ) @@ -205,7 +205,7 @@ extern inline pte_t pte_mkyoung(pte_t pte) * addresses (the 0xc0xxxxxx's) goes as void *'s. */ -extern inline pte_t __mk_pte(void * page, pgprot_t pgprot) +static inline pte_t __mk_pte(void * page, pgprot_t pgprot) { pte_t pte; /* the PTE needs a physical address */ @@ -223,7 +223,7 @@ extern inline pte_t __mk_pte(void * page, pgprot_t pgprot) __pte; \ }) -extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) +static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; } @@ -232,7 +232,7 @@ extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) * pte_pagenr refers to the page-number counted starting from the virtual DRAM start */ -extern inline unsigned long __pte_page(pte_t pte) +static inline unsigned long __pte_page(pte_t pte) { /* the PTE contains a physical address */ return (unsigned long)__va(pte_val(pte) & PAGE_MASK); @@ -250,7 +250,7 @@ extern inline unsigned long __pte_page(pte_t pte) * don't need the __pa and __va transformations. */ -extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep) +static inline void pmd_set(pmd_t * pmdp, pte_t * ptep) { pmd_val(*pmdp) = _PAGE_TABLE | (unsigned long) ptep; } #define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)) @@ -260,7 +260,7 @@ extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep) #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) /* to find an entry in a page-table-directory */ -extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address) +static inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address) { return mm->pgd + pgd_index(address); } @@ -296,7 +296,7 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* defined in head.S */ * * Actually I am not sure on what this could be used for. */ -extern inline void update_mmu_cache(struct vm_area_struct * vma, +static inline void update_mmu_cache(struct vm_area_struct * vma, unsigned long address, pte_t pte) { } diff --git a/include/asm-cris/processor.h b/include/asm-cris/processor.h index 0dc218117bd..e8b2abb2ae5 100644 --- a/include/asm-cris/processor.h +++ b/include/asm-cris/processor.h @@ -45,7 +45,7 @@ #define current_regs() user_regs(current->thread_info) -extern inline void prepare_to_copy(struct task_struct *tsk) +static inline void prepare_to_copy(struct task_struct *tsk) { } @@ -58,7 +58,7 @@ unsigned long get_wchan(struct task_struct *p); extern unsigned long thread_saved_pc(struct task_struct *tsk); /* Free all resources held by a thread. */ -extern inline void release_thread(struct task_struct *dead_task) +static inline void release_thread(struct task_struct *dead_task) { /* Nothing needs to be done. */ } diff --git a/include/asm-cris/semaphore.h b/include/asm-cris/semaphore.h index a19568e6aae..53f548b791c 100644 --- a/include/asm-cris/semaphore.h +++ b/include/asm-cris/semaphore.h @@ -37,17 +37,17 @@ struct semaphore { #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1) #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0) -extern inline void sema_init(struct semaphore *sem, int val) +static inline void sema_init(struct semaphore *sem, int val) { *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val); } -extern inline void init_MUTEX (struct semaphore *sem) +static inline void init_MUTEX (struct semaphore *sem) { sema_init(sem, 1); } -extern inline void init_MUTEX_LOCKED (struct semaphore *sem) +static inline void init_MUTEX_LOCKED (struct semaphore *sem) { sema_init(sem, 0); } @@ -59,7 +59,7 @@ extern void __up(struct semaphore * sem); /* notice - we probably can do cli/sti here instead of saving */ -extern inline void down(struct semaphore * sem) +static inline void down(struct semaphore * sem) { unsigned long flags; int failed; @@ -81,7 +81,7 @@ extern inline void down(struct semaphore * sem) * returns negative for signalled and zero for semaphore acquired. */ -extern inline int down_interruptible(struct semaphore * sem) +static inline int down_interruptible(struct semaphore * sem) { unsigned long flags; int failed; @@ -97,7 +97,7 @@ extern inline int down_interruptible(struct semaphore * sem) return(failed); } -extern inline int down_trylock(struct semaphore * sem) +static inline int down_trylock(struct semaphore * sem) { unsigned long flags; int failed; @@ -117,7 +117,7 @@ extern inline int down_trylock(struct semaphore * sem) * The default case (no contention) will result in NO * jumps for both down() and up(). */ -extern inline void up(struct semaphore * sem) +static inline void up(struct semaphore * sem) { unsigned long flags; int wakeup; diff --git a/include/asm-cris/system.h b/include/asm-cris/system.h index e06739806d4..d48670107a8 100644 --- a/include/asm-cris/system.h +++ b/include/asm-cris/system.h @@ -41,7 +41,7 @@ extern struct task_struct *resume(struct task_struct *prev, struct task_struct * void disable_hlt(void); void enable_hlt(void); -extern inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) +static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) { /* since Etrax doesn't have any atomic xchg instructions, we need to disable irq's (if enabled) and do it with move.d's */ diff --git a/include/asm-cris/timex.h b/include/asm-cris/timex.h index 3fb069a3771..b92e0e80fe8 100644 --- a/include/asm-cris/timex.h +++ b/include/asm-cris/timex.h @@ -16,7 +16,7 @@ typedef unsigned long long cycles_t; -extern inline cycles_t get_cycles(void) +static inline cycles_t get_cycles(void) { return 0; } diff --git a/include/asm-cris/tlbflush.h b/include/asm-cris/tlbflush.h index 6ed7d9ae90d..c52238005b5 100644 --- a/include/asm-cris/tlbflush.h +++ b/include/asm-cris/tlbflush.h @@ -39,14 +39,14 @@ static inline void flush_tlb_range(struct vm_area_struct * vma, unsigned long st flush_tlb_mm(vma->vm_mm); } -extern inline void flush_tlb_pgtables(struct mm_struct *mm, +static inline void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start, unsigned long end) { /* CRIS does not keep any page table caches in TLB */ } -extern inline void flush_tlb(void) +static inline void flush_tlb(void) { flush_tlb_mm(current->mm); } diff --git a/include/asm-cris/uaccess.h b/include/asm-cris/uaccess.h index 7d50086eb5e..69d48a2dc8e 100644 --- a/include/asm-cris/uaccess.h +++ b/include/asm-cris/uaccess.h @@ -213,7 +213,7 @@ extern unsigned long __copy_user(void *to, const void *from, unsigned long n); extern unsigned long __copy_user_zeroing(void *to, const void *from, unsigned long n); extern unsigned long __do_clear_user(void *to, unsigned long n); -extern inline unsigned long +static inline unsigned long __generic_copy_to_user(void __user *to, const void *from, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) @@ -221,7 +221,7 @@ __generic_copy_to_user(void __user *to, const void *from, unsigned long n) return n; } -extern inline unsigned long +static inline unsigned long __generic_copy_from_user(void *to, const void __user *from, unsigned long n) { if (access_ok(VERIFY_READ, from, n)) @@ -229,7 +229,7 @@ __generic_copy_from_user(void *to, const void __user *from, unsigned long n) return n; } -extern inline unsigned long +static inline unsigned long __generic_clear_user(void __user *to, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) @@ -237,13 +237,13 @@ __generic_clear_user(void __user *to, unsigned long n) return n; } -extern inline long +static inline long __strncpy_from_user(char *dst, const char __user *src, long count) { return __do_strncpy_from_user(dst, src, count); } -extern inline long +static inline long strncpy_from_user(char *dst, const char __user *src, long count) { long res = -EFAULT; @@ -256,7 +256,7 @@ strncpy_from_user(char *dst, const char __user *src, long count) /* Note that if these expand awfully if made into switch constructs, so don't do that. */ -extern inline unsigned long +static inline unsigned long __constant_copy_from_user(void *to, const void __user *from, unsigned long n) { unsigned long ret = 0; @@ -306,7 +306,7 @@ __constant_copy_from_user(void *to, const void __user *from, unsigned long n) /* Ditto, don't make a switch out of this. */ -extern inline unsigned long +static inline unsigned long __constant_copy_to_user(void __user *to, const void *from, unsigned long n) { unsigned long ret = 0; @@ -356,7 +356,7 @@ __constant_copy_to_user(void __user *to, const void *from, unsigned long n) /* No switch, please. */ -extern inline unsigned long +static inline unsigned long __constant_clear_user(void __user *to, unsigned long n) { unsigned long ret = 0; @@ -406,19 +406,19 @@ __constant_clear_user(void __user *to, unsigned long n) * used in fast paths and have only a small space overhead. */ -extern inline unsigned long +static inline unsigned long __generic_copy_from_user_nocheck(void *to, const void *from, unsigned long n) { return __copy_user_zeroing(to,from,n); } -extern inline unsigned long +static inline unsigned long __generic_copy_to_user_nocheck(void *to, const void *from, unsigned long n) { return __copy_user(to,from,n); } -extern inline unsigned long +static inline unsigned long __generic_clear_user_nocheck(void *to, unsigned long n) { return __do_clear_user(to,n); diff --git a/include/asm-cris/unistd.h b/include/asm-cris/unistd.h index 156a34bfc58..2627bbdf8a1 100644 --- a/include/asm-cris/unistd.h +++ b/include/asm-cris/unistd.h @@ -343,14 +343,14 @@ * some others too. */ #define __NR__exit __NR_exit -extern inline _syscall0(pid_t,setsid) -extern inline _syscall3(int,write,int,fd,const char *,buf,off_t,count) -extern inline _syscall3(int,read,int,fd,char *,buf,off_t,count) -extern inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count) -extern inline _syscall1(int,dup,int,fd) -extern inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp) -extern inline _syscall3(int,open,const char *,file,int,flag,int,mode) -extern inline _syscall1(int,close,int,fd) +static inline _syscall0(pid_t,setsid) +static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count) +static inline _syscall3(int,read,int,fd,char *,buf,off_t,count) +static inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count) +static inline _syscall1(int,dup,int,fd) +static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp) +static inline _syscall3(int,open,const char *,file,int,flag,int,mode) +static inline _syscall1(int,close,int,fd) struct pt_regs; asmlinkage long sys_mmap2( @@ -382,8 +382,8 @@ asmlinkage long sys_rt_sigaction(int sig, #ifdef __KERNEL__ #define _exit kernel_syscall_exit #endif -extern inline _syscall1(int,_exit,int,exitcode) -extern inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options) +static inline _syscall1(int,_exit,int,exitcode) +static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options) #endif -- cgit v1.2.3 From 953206858070e5921b9d5931c293ec983a6790cb Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 7 Nov 2005 00:58:45 -0800 Subject: [PATCH] uml: improve stub debugging Add some more debugging information when a stub does something unexpected, usually segfaulting. Now, it dumps out the stub's registers as well as the signal. Signed-off-by: Jeff Dike Cc: Paolo Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/skas/process.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index 5cd0e992978..42f2da687dc 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -69,6 +69,17 @@ void wait_stub_done(int pid, int sig, char * fname) if((n < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){ + unsigned long regs[FRAME_SIZE]; + if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) + printk("Failed to get registers from stub, " + "errno = %d\n", errno); + else { + int i; + + printk("Stub registers -\n"); + for(i = 0; i < FRAME_SIZE; i++) + printk("\t%d - %lx\n", i, regs[i]); + } panic("%s : failed to wait for SIGUSR1/SIGTRAP, " "pid = %d, n = %d, errno = %d, status = 0x%x\n", fname, pid, n, errno, status); -- cgit v1.2.3 From 4f0272415ad1867cea2a7ef5659769243ae50fbe Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Mon, 7 Nov 2005 00:58:46 -0800 Subject: [PATCH] uml: fix syscall stubs Jeff Dike noted that the assembly code for syscall stubs is misassembled with GCC 3.2.3: the values copied in registers weren't preserved between one asm() and the following one. So I fixed the thing by rewriting the __asm__ constraints more like unistd.h ones. Note: in syscall6 case I had to add one more instruction (i.e. moving arg6 in eax and shuffling things around) - it's needed for the function to be valid in general (we can't load the value from the stack, relative to ebp, because we change it), but could be avoided since we actually use a constant as param 6. The only fix would be to turn stub_syscall6 to a macro and use a "i" constraint for arg6 (i.e., specify it's a constant value). Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/sysdep-i386/stub.h | 64 +++++++++++++++++++++++++----------- arch/um/include/sysdep-x86_64/stub.h | 61 ++++++++++++++++++++++++++-------- 2 files changed, 92 insertions(+), 33 deletions(-) diff --git a/arch/um/include/sysdep-i386/stub.h b/arch/um/include/sysdep-i386/stub.h index d3699fe1c61..a49ceb199ee 100644 --- a/arch/um/include/sysdep-i386/stub.h +++ b/arch/um/include/sysdep-i386/stub.h @@ -16,45 +16,69 @@ extern void stub_clone_handler(void); #define STUB_MMAP_NR __NR_mmap2 #define MMAP_OFFSET(o) ((o) >> PAGE_SHIFT) +static inline long stub_syscall1(long syscall, long arg1) +{ + long ret; + + __asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1)); + + return ret; +} + static inline long stub_syscall2(long syscall, long arg1, long arg2) { long ret; - __asm__("movl %0, %%ecx; " : : "g" (arg2) : "%ecx"); - __asm__("movl %0, %%ebx; " : : "g" (arg1) : "%ebx"); - __asm__("movl %0, %%eax; " : : "g" (syscall) : "%eax"); - __asm__("int $0x80;" : : : "%eax"); - __asm__ __volatile__("movl %%eax, %0; " : "=g" (ret) :); - return(ret); + __asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1), + "c" (arg2)); + + return ret; } static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3) { - __asm__("movl %0, %%edx; " : : "g" (arg3) : "%edx"); - return(stub_syscall2(syscall, arg1, arg2)); + long ret; + + __asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1), + "c" (arg2), "d" (arg3)); + + return ret; } static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3, long arg4) { - __asm__("movl %0, %%esi; " : : "g" (arg4) : "%esi"); - return(stub_syscall3(syscall, arg1, arg2, arg3)); + long ret; + + __asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1), + "c" (arg2), "d" (arg3), "S" (arg4)); + + return ret; +} + +static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3, + long arg4, long arg5) +{ + long ret; + + __asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1), + "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5)); + + return ret; } static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6) { long ret; - __asm__("movl %0, %%eax; " : : "g" (syscall) : "%eax"); - __asm__("movl %0, %%ebx; " : : "g" (arg1) : "%ebx"); - __asm__("movl %0, %%ecx; " : : "g" (arg2) : "%ecx"); - __asm__("movl %0, %%edx; " : : "g" (arg3) : "%edx"); - __asm__("movl %0, %%esi; " : : "g" (arg4) : "%esi"); - __asm__("movl %0, %%edi; " : : "g" (arg5) : "%edi"); - __asm__ __volatile__("pushl %%ebp ; movl %1, %%ebp; " - "int $0x80; popl %%ebp ; " - "movl %%eax, %0; " : "=g" (ret) : "g" (arg6) : "%eax"); - return(ret); + + __asm__ volatile ("push %%ebp ; movl %%eax,%%ebp ; movl %1,%%eax ; " + "int $0x80 ; pop %%ebp" + : "=a" (ret) + : "g" (syscall), "b" (arg1), "c" (arg2), "d" (arg3), + "S" (arg4), "D" (arg5), "0" (arg6)); + + return ret; } static inline void trap_myself(void) diff --git a/arch/um/include/sysdep-x86_64/stub.h b/arch/um/include/sysdep-x86_64/stub.h index f599058d826..2bd6e7a9728 100644 --- a/arch/um/include/sysdep-x86_64/stub.h +++ b/arch/um/include/sysdep-x86_64/stub.h @@ -17,37 +17,72 @@ extern void stub_clone_handler(void); #define STUB_MMAP_NR __NR_mmap #define MMAP_OFFSET(o) (o) +#define __syscall_clobber "r11","rcx","memory" +#define __syscall "syscall" + static inline long stub_syscall2(long syscall, long arg1, long arg2) { long ret; - __asm__("movq %0, %%rsi; " : : "g" (arg2) : "%rsi"); - __asm__("movq %0, %%rdi; " : : "g" (arg1) : "%rdi"); - __asm__("movq %0, %%rax; " : : "g" (syscall) : "%rax"); - __asm__("syscall;" : : : "%rax", "%r11", "%rcx"); - __asm__ __volatile__("movq %%rax, %0; " : "=g" (ret) :); - return(ret); + __asm__ volatile (__syscall + : "=a" (ret) + : "0" (syscall), "D" (arg1), "S" (arg2) : __syscall_clobber ); + + return ret; } static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3) { - __asm__("movq %0, %%rdx; " : : "g" (arg3) : "%rdx"); - return(stub_syscall2(syscall, arg1, arg2)); + long ret; + + __asm__ volatile (__syscall + : "=a" (ret) + : "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3) + : __syscall_clobber ); + + return ret; } static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3, long arg4) { - __asm__("movq %0, %%r10; " : : "g" (arg4) : "%r10"); - return(stub_syscall3(syscall, arg1, arg2, arg3)); + long ret; + + __asm__ volatile ("movq %5,%%r10 ; " __syscall + : "=a" (ret) + : "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3), + "g" (arg4) + : __syscall_clobber, "r10" ); + + return ret; +} + +static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3, + long arg4, long arg5) +{ + long ret; + + __asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; " __syscall + : "=a" (ret) + : "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3), + "g" (arg4), "g" (arg5) + : __syscall_clobber, "r10", "r8" ); + + return ret; } static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6) { - __asm__("movq %0, %%r9; " : : "g" (arg6) : "%r9"); - __asm__("movq %0, %%r8; " : : "g" (arg5) : "%r8"); - return(stub_syscall4(syscall, arg1, arg2, arg3, arg4)); + long ret; + + __asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; " + "movq %7, %%r9; " __syscall : "=a" (ret) + : "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3), + "g" (arg4), "g" (arg5), "g" (arg6) + : __syscall_clobber, "r10", "r8", "r9" ); + + return ret; } static inline void trap_myself(void) -- cgit v1.2.3 From 0e76422ca5f34bb43b97c0945646ef072bcc1776 Mon Sep 17 00:00:00 2001 From: Bodo Stroesser Date: Mon, 7 Nov 2005 00:58:47 -0800 Subject: [PATCH] uml: fix UML network driver endianness bugs ifa->ifa_address and ifa->ifa_mask are defined as __u32, but used as if they were char[4]. Network code uses htons() to convert it. So UML's method to access these fields is wrong for bigendians (e.g. s390) I replaced bytewise copying by memcpy(), maybe even that might be removed, if ifa->ifa_address/mask may be used immediately. Signed-off-by: Bodo Stroesser Signed-off-by: Jeff Dike Cc: Paolo Giarrusso Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/net_kern.c | 38 +++++++------------------------------- arch/um/include/net_user.h | 2 +- 2 files changed, 8 insertions(+), 32 deletions(-) diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 721e2601a75..fe865d9a372 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -96,7 +96,6 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs) static int uml_net_open(struct net_device *dev) { struct uml_net_private *lp = dev->priv; - char addr[sizeof("255.255.255.255\0")]; int err; spin_lock(&lp->lock); @@ -107,7 +106,7 @@ static int uml_net_open(struct net_device *dev) } if(!lp->have_mac){ - dev_ip_addr(dev, addr, &lp->mac[2]); + dev_ip_addr(dev, &lp->mac[2]); set_ether_mac(dev, lp->mac); } @@ -664,8 +663,6 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event, void *ptr) { struct in_ifaddr *ifa = ptr; - u32 addr = ifa->ifa_address; - u32 netmask = ifa->ifa_mask; struct net_device *dev = ifa->ifa_dev->dev; struct uml_net_private *lp; void (*proc)(unsigned char *, unsigned char *, void *); @@ -685,14 +682,8 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event, break; } if(proc != NULL){ - addr_buf[0] = addr & 0xff; - addr_buf[1] = (addr >> 8) & 0xff; - addr_buf[2] = (addr >> 16) & 0xff; - addr_buf[3] = addr >> 24; - netmask_buf[0] = netmask & 0xff; - netmask_buf[1] = (netmask >> 8) & 0xff; - netmask_buf[2] = (netmask >> 16) & 0xff; - netmask_buf[3] = netmask >> 24; + memcpy(addr_buf, &ifa->ifa_address, sizeof(addr_buf)); + memcpy(netmask_buf, &ifa->ifa_mask, sizeof(netmask_buf)); (*proc)(addr_buf, netmask_buf, &lp->user); } return(NOTIFY_DONE); @@ -774,27 +765,18 @@ int setup_etheraddr(char *str, unsigned char *addr) return(1); } -void dev_ip_addr(void *d, char *buf, char *bin_buf) +void dev_ip_addr(void *d, unsigned char *bin_buf) { struct net_device *dev = d; struct in_device *ip = dev->ip_ptr; struct in_ifaddr *in; - u32 addr; if((ip == NULL) || ((in = ip->ifa_list) == NULL)){ printk(KERN_WARNING "dev_ip_addr - device not assigned an " "IP address\n"); return; } - addr = in->ifa_address; - sprintf(buf, "%d.%d.%d.%d", addr & 0xff, (addr >> 8) & 0xff, - (addr >> 16) & 0xff, addr >> 24); - if(bin_buf){ - bin_buf[0] = addr & 0xff; - bin_buf[1] = (addr >> 8) & 0xff; - bin_buf[2] = (addr >> 16) & 0xff; - bin_buf[3] = addr >> 24; - } + memcpy(bin_buf, &in->ifa_address, sizeof(in->ifa_address)); } void set_ether_mac(void *d, unsigned char *addr) @@ -829,14 +811,8 @@ void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, if(ip == NULL) return; in = ip->ifa_list; while(in != NULL){ - address[0] = in->ifa_address & 0xff; - address[1] = (in->ifa_address >> 8) & 0xff; - address[2] = (in->ifa_address >> 16) & 0xff; - address[3] = in->ifa_address >> 24; - netmask[0] = in->ifa_mask & 0xff; - netmask[1] = (in->ifa_mask >> 8) & 0xff; - netmask[2] = (in->ifa_mask >> 16) & 0xff; - netmask[3] = in->ifa_mask >> 24; + memcpy(address, &in->ifa_address, sizeof(address)); + memcpy(netmask, &in->ifa_mask, sizeof(netmask)); (*cb)(address, netmask, arg); in = in->ifa_next; } diff --git a/arch/um/include/net_user.h b/arch/um/include/net_user.h index 89885a77a77..800c403920b 100644 --- a/arch/um/include/net_user.h +++ b/arch/um/include/net_user.h @@ -25,7 +25,7 @@ struct net_user_info { }; extern void ether_user_init(void *data, void *dev); -extern void dev_ip_addr(void *d, char *buf, char *bin_buf); +extern void dev_ip_addr(void *d, unsigned char *bin_buf); extern void set_ether_mac(void *d, unsigned char *addr); extern void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, void *), -- cgit v1.2.3 From bb578426253ab9950cc20b4e5dd6aefb5500144f Mon Sep 17 00:00:00 2001 From: Gennady Sharapov Date: Mon, 7 Nov 2005 00:58:50 -0800 Subject: [PATCH] uml: separate libc-dependent uaccess code The serial UML OS-abstraction layer patch (um/kernel dir). This moves all systemcalls from uaccess_user.c file under os-Linux dir Signed-off-by: Gennady Sharapov Signed-off-by: Jeff Dike Cc: Paolo Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/os.h | 6 ++++ arch/um/include/uml_uaccess.h | 4 --- arch/um/kernel/Makefile | 2 +- arch/um/kernel/tt/uaccess_user.c | 1 + arch/um/kernel/uaccess.c | 30 +++++++++++++++++++ arch/um/kernel/uaccess_user.c | 64 ---------------------------------------- arch/um/os-Linux/Makefile | 4 +-- arch/um/os-Linux/uaccess.c | 32 ++++++++++++++++++++ 8 files changed, 72 insertions(+), 71 deletions(-) create mode 100644 arch/um/kernel/uaccess.c delete mode 100644 arch/um/kernel/uaccess_user.c create mode 100644 arch/um/os-Linux/uaccess.c diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 2e58e304b8b..b9f53519bbe 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -199,6 +199,12 @@ extern void forward_pending_sigio(int target); extern int start_fork_tramp(void *arg, unsigned long temp_stack, int clone_flags, int (*tramp)(void *)); +/* uaccess.c */ +extern unsigned long __do_user_copy(void *to, const void *from, int n, + void **fault_addr, void **fault_catcher, + void (*op)(void *to, const void *from, + int n), int *faulted_out); + #endif /* diff --git a/arch/um/include/uml_uaccess.h b/arch/um/include/uml_uaccess.h index f77eb642845..c0df11d06f5 100644 --- a/arch/um/include/uml_uaccess.h +++ b/arch/um/include/uml_uaccess.h @@ -8,10 +8,6 @@ extern int __do_copy_to_user(void *to, const void *from, int n, void **fault_addr, void **fault_catcher); -extern unsigned long __do_user_copy(void *to, const void *from, int n, - void **fault_addr, void **fault_catcher, - void (*op)(void *to, const void *from, - int n), int *faulted_out); void __do_copy(void *to, const void *from, int n); #endif diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 1a0001b3850..72fd4eada9c 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -10,7 +10,7 @@ obj-y = config.o exec_kern.o exitcode.o \ helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o physmem.o \ process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \ signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \ - time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o \ + time_kern.o tlb.o trap_kern.o trap_user.o uaccess.o um_arch.o \ umid.o user_util.o obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o diff --git a/arch/um/kernel/tt/uaccess_user.c b/arch/um/kernel/tt/uaccess_user.c index 8c220f054b6..6c92bbccb49 100644 --- a/arch/um/kernel/tt/uaccess_user.c +++ b/arch/um/kernel/tt/uaccess_user.c @@ -10,6 +10,7 @@ #include "uml_uaccess.h" #include "task.h" #include "kern_util.h" +#include "os.h" int __do_copy_from_user(void *to, const void *from, int n, void **fault_addr, void **fault_catcher) diff --git a/arch/um/kernel/uaccess.c b/arch/um/kernel/uaccess.c new file mode 100644 index 00000000000..054e3de0784 --- /dev/null +++ b/arch/um/kernel/uaccess.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) + * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +/* These are here rather than tt/uaccess.c because skas mode needs them in + * order to do SIGBUS recovery when a tmpfs mount runs out of room. + */ + +#include +#include "os.h" + +void __do_copy(void *to, const void *from, int n) +{ + memcpy(to, from, n); +} + + +int __do_copy_to_user(void *to, const void *from, int n, + void **fault_addr, void **fault_catcher) +{ + unsigned long fault; + int faulted; + + fault = __do_user_copy(to, from, n, fault_addr, fault_catcher, + __do_copy, &faulted); + if(!faulted) return(0); + else return(n - (fault - (unsigned long) to)); +} diff --git a/arch/um/kernel/uaccess_user.c b/arch/um/kernel/uaccess_user.c deleted file mode 100644 index d035257ed0a..00000000000 --- a/arch/um/kernel/uaccess_user.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include -#include - -/* These are here rather than tt/uaccess.c because skas mode needs them in - * order to do SIGBUS recovery when a tmpfs mount runs out of room. - */ - -unsigned long __do_user_copy(void *to, const void *from, int n, - void **fault_addr, void **fault_catcher, - void (*op)(void *to, const void *from, - int n), int *faulted_out) -{ - unsigned long *faddrp = (unsigned long *) fault_addr, ret; - - sigjmp_buf jbuf; - *fault_catcher = &jbuf; - if(sigsetjmp(jbuf, 1) == 0){ - (*op)(to, from, n); - ret = 0; - *faulted_out = 0; - } - else { - ret = *faddrp; - *faulted_out = 1; - } - *fault_addr = NULL; - *fault_catcher = NULL; - return ret; -} - -void __do_copy(void *to, const void *from, int n) -{ - memcpy(to, from, n); -} - - -int __do_copy_to_user(void *to, const void *from, int n, - void **fault_addr, void **fault_catcher) -{ - unsigned long fault; - int faulted; - - fault = __do_user_copy(to, from, n, fault_addr, fault_catcher, - __do_copy, &faulted); - if(!faulted) return(0); - else return(n - (fault - (unsigned long) to)); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index d15ec2af6a2..d389c58b18b 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile @@ -4,10 +4,10 @@ # obj-y = aio.o elf_aux.o file.o mem.o process.o signal.o start_up.o time.o \ - tt.o tty.o user_syms.o drivers/ sys-$(SUBARCH)/ + tt.o tty.o uaccess.o user_syms.o drivers/ sys-$(SUBARCH)/ USER_OBJS := aio.o elf_aux.o file.o mem.o process.o signal.o start_up.o \ - time.o tt.o tty.o + time.o tt.o tty.o uaccess.o elf_aux.o: $(ARCH_DIR)/kernel-offsets.h CFLAGS_elf_aux.o += -I$(objtree)/arch/um diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c new file mode 100644 index 00000000000..38d710158c3 --- /dev/null +++ b/arch/um/os-Linux/uaccess.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) + * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include + +unsigned long __do_user_copy(void *to, const void *from, int n, + void **fault_addr, void **fault_catcher, + void (*op)(void *to, const void *from, + int n), int *faulted_out) +{ + unsigned long *faddrp = (unsigned long *) fault_addr, ret; + + sigjmp_buf jbuf; + *fault_catcher = &jbuf; + if(sigsetjmp(jbuf, 1) == 0){ + (*op)(to, from, n); + ret = 0; + *faulted_out = 0; + } + else { + ret = *faddrp; + *faulted_out = 1; + } + *fault_addr = NULL; + *fault_catcher = NULL; + return ret; +} + -- cgit v1.2.3 From 52c653b3bed323df9006c06cdfb4548ec44b3109 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 7 Nov 2005 00:58:50 -0800 Subject: [PATCH] uml: separate libc-dependent early initialization The serial UML OS-abstraction layer patch (um/kernel dir). This moves all systemcalls from main.c file under os-Linux dir and joins mem.c and um_arch.c files. Signed-off-by: Gennady Sharapov Signed-off-by: Jeff Dike Cc: Paolo Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/Makefile | 4 +- arch/um/kernel/main.c | 270 ---------------------------------------------- arch/um/os-Linux/Makefile | 8 +- arch/um/os-Linux/main.c | 259 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 265 insertions(+), 276 deletions(-) delete mode 100644 arch/um/kernel/main.c create mode 100644 arch/um/os-Linux/main.c diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 72fd4eada9c..f9858583863 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -7,7 +7,7 @@ extra-y := vmlinux.lds clean-files := obj-y = config.o exec_kern.o exitcode.o \ - helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o physmem.o \ + helper.o init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \ process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \ signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \ time_kern.o tlb.o trap_kern.o trap_user.o uaccess.o um_arch.o \ @@ -24,7 +24,7 @@ obj-$(CONFIG_MODE_SKAS) += skas/ user-objs-$(CONFIG_TTY_LOG) += tty_log.o -USER_OBJS := $(user-objs-y) config.o helper.o main.o time.o tty_log.o umid.o \ +USER_OBJS := $(user-objs-y) config.o helper.o time.o tty_log.o umid.o \ user_util.o include arch/um/scripts/Makefile.rules diff --git a/arch/um/kernel/main.c b/arch/um/kernel/main.c deleted file mode 100644 index d31027f0fe3..00000000000 --- a/arch/um/kernel/main.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "user_util.h" -#include "kern_util.h" -#include "mem_user.h" -#include "signal_user.h" -#include "time_user.h" -#include "irq_user.h" -#include "user.h" -#include "init.h" -#include "mode.h" -#include "choose-mode.h" -#include "uml-config.h" -#include "os.h" - -/* Set in set_stklim, which is called from main and __wrap_malloc. - * __wrap_malloc only calls it if main hasn't started. - */ -unsigned long stacksizelim; - -/* Set in main */ -char *linux_prog; - -#define PGD_BOUND (4 * 1024 * 1024) -#define STACKSIZE (8 * 1024 * 1024) -#define THREAD_NAME_LEN (256) - -static void set_stklim(void) -{ - struct rlimit lim; - - if(getrlimit(RLIMIT_STACK, &lim) < 0){ - perror("getrlimit"); - exit(1); - } - if((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)){ - lim.rlim_cur = STACKSIZE; - if(setrlimit(RLIMIT_STACK, &lim) < 0){ - perror("setrlimit"); - exit(1); - } - } - stacksizelim = (lim.rlim_cur + PGD_BOUND - 1) & ~(PGD_BOUND - 1); -} - -static __init void do_uml_initcalls(void) -{ - initcall_t *call; - - call = &__uml_initcall_start; - while (call < &__uml_initcall_end){; - (*call)(); - call++; - } -} - -static void last_ditch_exit(int sig) -{ - signal(SIGINT, SIG_DFL); - signal(SIGTERM, SIG_DFL); - signal(SIGHUP, SIG_DFL); - uml_cleanup(); - exit(1); -} - -extern int uml_exitcode; - -extern void scan_elf_aux( char **envp); - -int main(int argc, char **argv, char **envp) -{ - char **new_argv; - sigset_t mask; - int ret, i, err; - - /* Enable all signals except SIGIO - in some environments, we can - * enter with some signals blocked - */ - - sigemptyset(&mask); - sigaddset(&mask, SIGIO); - if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){ - perror("sigprocmask"); - exit(1); - } - -#ifdef UML_CONFIG_CMDLINE_ON_HOST - /* Allocate memory for thread command lines */ - if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){ - - char padding[THREAD_NAME_LEN] = { - [ 0 ... THREAD_NAME_LEN - 2] = ' ', '\0' - }; - - new_argv = malloc((argc + 2) * sizeof(char*)); - if(!new_argv) { - perror("Allocating extended argv"); - exit(1); - } - - new_argv[0] = argv[0]; - new_argv[1] = padding; - - for(i = 2; i <= argc; i++) - new_argv[i] = argv[i - 1]; - new_argv[argc + 1] = NULL; - - execvp(new_argv[0], new_argv); - perror("execing with extended args"); - exit(1); - } -#endif - - linux_prog = argv[0]; - - set_stklim(); - - new_argv = malloc((argc + 1) * sizeof(char *)); - if(new_argv == NULL){ - perror("Mallocing argv"); - exit(1); - } - for(i=0;i= uml_physmem) && (addr < high_physmem)){ - if(CAN_KMALLOC()) - kfree(ptr); - } - else if((addr >= start_vm) && (addr < end_vm)){ - if(CAN_KMALLOC()) - vfree(ptr); - } - else __real_free(ptr); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index d389c58b18b..0b761a08f0d 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile @@ -3,11 +3,11 @@ # Licensed under the GPL # -obj-y = aio.o elf_aux.o file.o mem.o process.o signal.o start_up.o time.o \ - tt.o tty.o uaccess.o user_syms.o drivers/ sys-$(SUBARCH)/ +obj-y = aio.o elf_aux.o file.o main.o mem.o process.o signal.o start_up.o \ + time.o tt.o tty.o uaccess.o user_syms.o drivers/ sys-$(SUBARCH)/ -USER_OBJS := aio.o elf_aux.o file.o mem.o process.o signal.o start_up.o \ - time.o tt.o tty.o uaccess.o +USER_OBJS := aio.o elf_aux.o file.o main.o mem.o process.o signal.o \ + start_up.o time.o tt.o tty.o uaccess.o elf_aux.o: $(ARCH_DIR)/kernel-offsets.h CFLAGS_elf_aux.o += -I$(objtree)/arch/um diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c new file mode 100644 index 00000000000..23da27d2256 --- /dev/null +++ b/arch/um/os-Linux/main.c @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "user_util.h" +#include "kern_util.h" +#include "mem_user.h" +#include "signal_user.h" +#include "time_user.h" +#include "irq_user.h" +#include "user.h" +#include "init.h" +#include "mode.h" +#include "choose-mode.h" +#include "uml-config.h" +#include "os.h" + +/* Set in set_stklim, which is called from main and __wrap_malloc. + * __wrap_malloc only calls it if main hasn't started. + */ +unsigned long stacksizelim; + +/* Set in main */ +char *linux_prog; + +#define PGD_BOUND (4 * 1024 * 1024) +#define STACKSIZE (8 * 1024 * 1024) +#define THREAD_NAME_LEN (256) + +static void set_stklim(void) +{ + struct rlimit lim; + + if(getrlimit(RLIMIT_STACK, &lim) < 0){ + perror("getrlimit"); + exit(1); + } + if((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)){ + lim.rlim_cur = STACKSIZE; + if(setrlimit(RLIMIT_STACK, &lim) < 0){ + perror("setrlimit"); + exit(1); + } + } + stacksizelim = (lim.rlim_cur + PGD_BOUND - 1) & ~(PGD_BOUND - 1); +} + +static __init void do_uml_initcalls(void) +{ + initcall_t *call; + + call = &__uml_initcall_start; + while (call < &__uml_initcall_end){; + (*call)(); + call++; + } +} + +static void last_ditch_exit(int sig) +{ + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGHUP, SIG_DFL); + uml_cleanup(); + exit(1); +} + +extern int uml_exitcode; + +extern void scan_elf_aux( char **envp); + +int main(int argc, char **argv, char **envp) +{ + char **new_argv; + sigset_t mask; + int ret, i, err; + + /* Enable all signals except SIGIO - in some environments, we can + * enter with some signals blocked + */ + + sigemptyset(&mask); + sigaddset(&mask, SIGIO); + if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){ + perror("sigprocmask"); + exit(1); + } + +#ifdef UML_CONFIG_CMDLINE_ON_HOST + /* Allocate memory for thread command lines */ + if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){ + + char padding[THREAD_NAME_LEN] = { + [ 0 ... THREAD_NAME_LEN - 2] = ' ', '\0' + }; + + new_argv = malloc((argc + 2) * sizeof(char*)); + if(!new_argv) { + perror("Allocating extended argv"); + exit(1); + } + + new_argv[0] = argv[0]; + new_argv[1] = padding; + + for(i = 2; i <= argc; i++) + new_argv[i] = argv[i - 1]; + new_argv[argc + 1] = NULL; + + execvp(new_argv[0], new_argv); + perror("execing with extended args"); + exit(1); + } +#endif + + linux_prog = argv[0]; + + set_stklim(); + + new_argv = malloc((argc + 1) * sizeof(char *)); + if(new_argv == NULL){ + perror("Mallocing argv"); + exit(1); + } + for(i=0;i= uml_physmem) && (addr < high_physmem)){ + if(CAN_KMALLOC()) + kfree(ptr); + } + else if((addr >= start_vm) && (addr < end_vm)){ + if(CAN_KMALLOC()) + vfree(ptr); + } + else __real_free(ptr); +} -- cgit v1.2.3 From ff5c6ff54215fe284e515032878111de5d8a5ce1 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 7 Nov 2005 00:58:51 -0800 Subject: [PATCH] uml: separate libc-dependent helper code The serial UML OS-abstraction layer patch (um/kernel dir). This moves all systemcalls from helper.c file under os-Linux dir Signed-off-by: Gennady Sharapov Signed-off-by: Jeff Dike Cc: Paolo Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/chan_user.c | 1 - arch/um/drivers/harddog_kern.c | 1 - arch/um/drivers/harddog_user.c | 1 - arch/um/drivers/net_user.c | 1 - arch/um/drivers/port_user.c | 1 - arch/um/drivers/slip_user.c | 1 - arch/um/drivers/slirp_user.c | 1 - arch/um/drivers/xterm.c | 1 - arch/um/include/helper.h | 27 ----- arch/um/include/os.h | 8 ++ arch/um/kernel/Makefile | 5 +- arch/um/kernel/helper.c | 165 ------------------------------- arch/um/kernel/ksyms.c | 1 - arch/um/kernel/sigio_user.c | 1 - arch/um/kernel/user_util.c | 1 - arch/um/os-Linux/Makefile | 7 +- arch/um/os-Linux/aio.c | 1 - arch/um/os-Linux/drivers/ethertap_user.c | 1 - arch/um/os-Linux/drivers/tuntap_user.c | 1 - arch/um/os-Linux/helper.c | 165 +++++++++++++++++++++++++++++++ 20 files changed, 179 insertions(+), 212 deletions(-) delete mode 100644 arch/um/include/helper.h delete mode 100644 arch/um/kernel/helper.c create mode 100644 arch/um/os-Linux/helper.c diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index de3bce71aeb..1c55d580248 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c @@ -16,7 +16,6 @@ #include "user_util.h" #include "chan_user.h" #include "user.h" -#include "helper.h" #include "os.h" #include "choose-mode.h" #include "mode.h" diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c index 147ec19f6bb..49acb2badf3 100644 --- a/arch/um/drivers/harddog_kern.c +++ b/arch/um/drivers/harddog_kern.c @@ -46,7 +46,6 @@ #include #include #include -#include "helper.h" #include "mconsole.h" MODULE_LICENSE("GPL"); diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c index d934181b8d4..def013b5a3c 100644 --- a/arch/um/drivers/harddog_user.c +++ b/arch/um/drivers/harddog_user.c @@ -8,7 +8,6 @@ #include #include "user_util.h" #include "user.h" -#include "helper.h" #include "mconsole.h" #include "os.h" #include "choose-mode.h" diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c index 3730d4f1271..098fa65981a 100644 --- a/arch/um/drivers/net_user.c +++ b/arch/um/drivers/net_user.c @@ -16,7 +16,6 @@ #include "user_util.h" #include "kern_util.h" #include "net_user.h" -#include "helper.h" #include "os.h" int tap_open_common(void *dev, char *gate_addr) diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c index 14dd2002d2d..ed4a1a6c5d8 100644 --- a/arch/um/drivers/port_user.c +++ b/arch/um/drivers/port_user.c @@ -18,7 +18,6 @@ #include "user.h" #include "chan_user.h" #include "port.h" -#include "helper.h" #include "os.h" struct port_chan { diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c index 71af444e591..89fbec185cc 100644 --- a/arch/um/drivers/slip_user.c +++ b/arch/um/drivers/slip_user.c @@ -14,7 +14,6 @@ #include "net_user.h" #include "slip.h" #include "slip_common.h" -#include "helper.h" #include "os.h" void slip_user_init(void *data, void *dev) diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c index 8d91f663d82..b94c66114bc 100644 --- a/arch/um/drivers/slirp_user.c +++ b/arch/um/drivers/slirp_user.c @@ -13,7 +13,6 @@ #include "net_user.h" #include "slirp.h" #include "slip_common.h" -#include "helper.h" #include "os.h" void slirp_user_init(void *data, void *dev) diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index 90e0e5ff451..b530f1a6540 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c @@ -14,7 +14,6 @@ #include #include "kern_util.h" #include "chan_user.h" -#include "helper.h" #include "user_util.h" #include "user.h" #include "os.h" diff --git a/arch/um/include/helper.h b/arch/um/include/helper.h deleted file mode 100644 index 162ac31192f..00000000000 --- a/arch/um/include/helper.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __HELPER_H__ -#define __HELPER_H__ - -extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, - unsigned long *stack_out); -extern int run_helper_thread(int (*proc)(void *), void *arg, - unsigned int flags, unsigned long *stack_out, - int stack_order); -extern int helper_wait(int pid); - -#endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/include/os.h b/arch/um/include/os.h index b9f53519bbe..112d7288f0c 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -205,6 +205,14 @@ extern unsigned long __do_user_copy(void *to, const void *from, int n, void (*op)(void *to, const void *from, int n), int *faulted_out); +/* helper.c */ +extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, + unsigned long *stack_out); +extern int run_helper_thread(int (*proc)(void *), void *arg, + unsigned int flags, unsigned long *stack_out, + int stack_order); +extern int helper_wait(int pid); + #endif /* diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index f9858583863..3de9d21e36b 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -7,7 +7,7 @@ extra-y := vmlinux.lds clean-files := obj-y = config.o exec_kern.o exitcode.o \ - helper.o init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \ + init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \ process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \ signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \ time_kern.o tlb.o trap_kern.o trap_user.o uaccess.o um_arch.o \ @@ -24,8 +24,7 @@ obj-$(CONFIG_MODE_SKAS) += skas/ user-objs-$(CONFIG_TTY_LOG) += tty_log.o -USER_OBJS := $(user-objs-y) config.o helper.o time.o tty_log.o umid.o \ - user_util.o +USER_OBJS := $(user-objs-y) config.o time.o tty_log.o umid.o user_util.o include arch/um/scripts/Makefile.rules diff --git a/arch/um/kernel/helper.c b/arch/um/kernel/helper.c deleted file mode 100644 index 33fb0bd3b11..00000000000 --- a/arch/um/kernel/helper.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include -#include -#include -#include -#include -#include -#include -#include "user.h" -#include "kern_util.h" -#include "user_util.h" -#include "helper.h" -#include "os.h" - -struct helper_data { - void (*pre_exec)(void*); - void *pre_data; - char **argv; - int fd; -}; - -/* Debugging aid, changed only from gdb */ -int helper_pause = 0; - -static void helper_hup(int sig) -{ -} - -static int helper_child(void *arg) -{ - struct helper_data *data = arg; - char **argv = data->argv; - int errval; - - if(helper_pause){ - signal(SIGHUP, helper_hup); - pause(); - } - if(data->pre_exec != NULL) - (*data->pre_exec)(data->pre_data); - execvp(argv[0], argv); - errval = errno; - printk("execvp of '%s' failed - errno = %d\n", argv[0], errno); - os_write_file(data->fd, &errval, sizeof(errval)); - os_kill_process(os_getpid(), 0); - return(0); -} - -/* Returns either the pid of the child process we run or -E* on failure. - * XXX The alloc_stack here breaks if this is called in the tracing thread */ -int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, - unsigned long *stack_out) -{ - struct helper_data data; - unsigned long stack, sp; - int pid, fds[2], ret, n; - - if((stack_out != NULL) && (*stack_out != 0)) - stack = *stack_out; - else stack = alloc_stack(0, um_in_interrupt()); - if(stack == 0) - return(-ENOMEM); - - ret = os_pipe(fds, 1, 0); - if(ret < 0){ - printk("run_helper : pipe failed, ret = %d\n", -ret); - goto out_free; - } - - ret = os_set_exec_close(fds[1], 1); - if(ret < 0){ - printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n", - -ret); - goto out_close; - } - - sp = stack + page_size() - sizeof(void *); - data.pre_exec = pre_exec; - data.pre_data = pre_data; - data.argv = argv; - data.fd = fds[1]; - pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data); - if(pid < 0){ - ret = -errno; - printk("run_helper : clone failed, errno = %d\n", errno); - goto out_close; - } - - os_close_file(fds[1]); - fds[1] = -1; - - /*Read the errno value from the child.*/ - n = os_read_file(fds[0], &ret, sizeof(ret)); - if(n < 0){ - printk("run_helper : read on pipe failed, ret = %d\n", -n); - ret = n; - os_kill_process(pid, 1); - } - else if(n != 0){ - CATCH_EINTR(n = waitpid(pid, NULL, 0)); - ret = -errno; - } else { - ret = pid; - } - -out_close: - if (fds[1] != -1) - os_close_file(fds[1]); - os_close_file(fds[0]); -out_free: - if(stack_out == NULL) - free_stack(stack, 0); - else *stack_out = stack; - return(ret); -} - -int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, - unsigned long *stack_out, int stack_order) -{ - unsigned long stack, sp; - int pid, status, err; - - stack = alloc_stack(stack_order, um_in_interrupt()); - if(stack == 0) return(-ENOMEM); - - sp = stack + (page_size() << stack_order) - sizeof(void *); - pid = clone(proc, (void *) sp, flags | SIGCHLD, arg); - if(pid < 0){ - err = -errno; - printk("run_helper_thread : clone failed, errno = %d\n", - errno); - return err; - } - if(stack_out == NULL){ - CATCH_EINTR(pid = waitpid(pid, &status, 0)); - if(pid < 0){ - err = -errno; - printk("run_helper_thread - wait failed, errno = %d\n", - errno); - pid = err; - } - if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) - printk("run_helper_thread - thread returned status " - "0x%x\n", status); - free_stack(stack, stack_order); - } - else *stack_out = stack; - return(pid); -} - -int helper_wait(int pid) -{ - int ret; - - CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG)); - if(ret < 0){ - ret = -errno; - printk("helper_wait : waitpid failed, errno = %d\n", errno); - } - return(ret); -} diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c index a97a72e516a..7713e7a6f47 100644 --- a/arch/um/kernel/ksyms.c +++ b/arch/um/kernel/ksyms.c @@ -20,7 +20,6 @@ #include "user_util.h" #include "mem_user.h" #include "os.h" -#include "helper.h" EXPORT_SYMBOL(stop); EXPORT_SYMBOL(uml_physmem); diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c index a52751108aa..3fbfd956bfe 100644 --- a/arch/um/kernel/sigio_user.c +++ b/arch/um/kernel/sigio_user.c @@ -18,7 +18,6 @@ #include "kern_util.h" #include "user_util.h" #include "sigio.h" -#include "helper.h" #include "os.h" /* Changed during early boot */ diff --git a/arch/um/kernel/user_util.c b/arch/um/kernel/user_util.c index 41d17c71511..4c231161f25 100644 --- a/arch/um/kernel/user_util.c +++ b/arch/um/kernel/user_util.c @@ -27,7 +27,6 @@ #include "user.h" #include "mem_user.h" #include "init.h" -#include "helper.h" #include "ptrace_user.h" #include "uml-config.h" diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index 0b761a08f0d..b83ac8e21c3 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile @@ -3,10 +3,11 @@ # Licensed under the GPL # -obj-y = aio.o elf_aux.o file.o main.o mem.o process.o signal.o start_up.o \ - time.o tt.o tty.o uaccess.o user_syms.o drivers/ sys-$(SUBARCH)/ +obj-y = aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \ + start_up.o time.o tt.o tty.o uaccess.o user_syms.o drivers/ \ + sys-$(SUBARCH)/ -USER_OBJS := aio.o elf_aux.o file.o main.o mem.o process.o signal.o \ +USER_OBJS := aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \ start_up.o time.o tt.o tty.o uaccess.o elf_aux.o: $(ARCH_DIR)/kernel-offsets.h diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c index 41cfb094420..ffa759addd3 100644 --- a/arch/um/os-Linux/aio.c +++ b/arch/um/os-Linux/aio.c @@ -10,7 +10,6 @@ #include #include #include "os.h" -#include "helper.h" #include "aio.h" #include "init.h" #include "user.h" diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c index cd4d6544da7..901b85e8a1c 100644 --- a/arch/um/os-Linux/drivers/ethertap_user.c +++ b/arch/um/os-Linux/drivers/ethertap_user.c @@ -19,7 +19,6 @@ #include "user_util.h" #include "net_user.h" #include "etap.h" -#include "helper.h" #include "os.h" #define MAX_PACKET ETH_MAX_PACKET diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c index 4ba9b17adf1..52945338b64 100644 --- a/arch/um/os-Linux/drivers/tuntap_user.c +++ b/arch/um/os-Linux/drivers/tuntap_user.c @@ -20,7 +20,6 @@ #include "kern_util.h" #include "user_util.h" #include "user.h" -#include "helper.h" #include "os.h" #define MAX_PACKET ETH_MAX_PACKET diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c new file mode 100644 index 00000000000..36cc8475bcd --- /dev/null +++ b/arch/um/os-Linux/helper.c @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include +#include +#include +#include +#include +#include +#include "user.h" +#include "kern_util.h" +#include "user_util.h" +#include "os.h" + +struct helper_data { + void (*pre_exec)(void*); + void *pre_data; + char **argv; + int fd; +}; + +/* Debugging aid, changed only from gdb */ +int helper_pause = 0; + +static void helper_hup(int sig) +{ +} + +static int helper_child(void *arg) +{ + struct helper_data *data = arg; + char **argv = data->argv; + int errval; + + if(helper_pause){ + signal(SIGHUP, helper_hup); + pause(); + } + if(data->pre_exec != NULL) + (*data->pre_exec)(data->pre_data); + execvp(argv[0], argv); + errval = errno; + printk("execvp of '%s' failed - errno = %d\n", argv[0], errno); + os_write_file(data->fd, &errval, sizeof(errval)); + kill(os_getpid(), SIGKILL); + return(0); +} + +/* Returns either the pid of the child process we run or -E* on failure. + * XXX The alloc_stack here breaks if this is called in the tracing thread */ +int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, + unsigned long *stack_out) +{ + struct helper_data data; + unsigned long stack, sp; + int pid, fds[2], ret, n; + + if((stack_out != NULL) && (*stack_out != 0)) + stack = *stack_out; + else stack = alloc_stack(0, um_in_interrupt()); + if(stack == 0) + return(-ENOMEM); + + ret = os_pipe(fds, 1, 0); + if(ret < 0){ + printk("run_helper : pipe failed, ret = %d\n", -ret); + goto out_free; + } + + ret = os_set_exec_close(fds[1], 1); + if(ret < 0){ + printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n", + -ret); + goto out_close; + } + + sp = stack + page_size() - sizeof(void *); + data.pre_exec = pre_exec; + data.pre_data = pre_data; + data.argv = argv; + data.fd = fds[1]; + pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data); + if(pid < 0){ + ret = -errno; + printk("run_helper : clone failed, errno = %d\n", errno); + goto out_close; + } + + close(fds[1]); + fds[1] = -1; + + /*Read the errno value from the child.*/ + n = os_read_file(fds[0], &ret, sizeof(ret)); + if(n < 0){ + printk("run_helper : read on pipe failed, ret = %d\n", -n); + ret = n; + kill(pid, SIGKILL); + CATCH_EINTR(waitpid(pid, NULL, 0)); + } + else if(n != 0){ + CATCH_EINTR(n = waitpid(pid, NULL, 0)); + ret = -errno; + } else { + ret = pid; + } + +out_close: + if (fds[1] != -1) + close(fds[1]); + close(fds[0]); +out_free: + if(stack_out == NULL) + free_stack(stack, 0); + else *stack_out = stack; + return(ret); +} + +int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, + unsigned long *stack_out, int stack_order) +{ + unsigned long stack, sp; + int pid, status, err; + + stack = alloc_stack(stack_order, um_in_interrupt()); + if(stack == 0) return(-ENOMEM); + + sp = stack + (page_size() << stack_order) - sizeof(void *); + pid = clone(proc, (void *) sp, flags | SIGCHLD, arg); + if(pid < 0){ + err = -errno; + printk("run_helper_thread : clone failed, errno = %d\n", + errno); + return err; + } + if(stack_out == NULL){ + CATCH_EINTR(pid = waitpid(pid, &status, 0)); + if(pid < 0){ + err = -errno; + printk("run_helper_thread - wait failed, errno = %d\n", + errno); + pid = err; + } + if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) + printk("run_helper_thread - thread returned status " + "0x%x\n", status); + free_stack(stack, stack_order); + } + else *stack_out = stack; + return(pid); +} + +int helper_wait(int pid) +{ + int ret; + + CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG)); + if(ret < 0){ + ret = -errno; + printk("helper_wait : waitpid failed, errno = %d\n", errno); + } + return(ret); +} -- cgit v1.2.3 From e763b793f7e5c09a859fc420eb0de385d80cf636 Mon Sep 17 00:00:00 2001 From: Ben Lahaise Date: Mon, 7 Nov 2005 00:58:52 -0800 Subject: [PATCH] uml: switch_mm fix Not quite, something along the lines of the patch below works correctly (and makes aio performance not suffer from multiple second delays), as skas0 mode correctly switches mm contexts, unlike TT (which should probably get nuked from the kernel now that skas0 seems to be working). Signed-off-by: Benjamin LaHaise Signed-off-by: Jeff Dike Cc: Paolo Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-um/mmu_context.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/asm-um/mmu_context.h b/include/asm-um/mmu_context.h index 2edb4f1f789..9a0e48eb542 100644 --- a/include/asm-um/mmu_context.h +++ b/include/asm-um/mmu_context.h @@ -29,7 +29,8 @@ static inline void activate_mm(struct mm_struct *old, struct mm_struct *new) * possible. */ if (old != new && (current->flags & PF_BORROWED_MM)) - force_flush_all(); + CHOOSE_MODE(force_flush_all(), + switch_mm_skas(&new->context.skas.id)); } static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, -- cgit v1.2.3 From 858259cf7d1c443c836a2022b78cb281f0a9b95e Mon Sep 17 00:00:00 2001 From: Bodo Stroesser Date: Mon, 7 Nov 2005 00:58:55 -0800 Subject: [PATCH] uml: maintain own LDT entries Patch imlements full LDT handling in SKAS: * UML holds it's own LDT table, used to deliver data on modify_ldt(READ) * UML disables the default_ldt, inherited from the host (SKAS3) or resets LDT entries, set by host's clib and inherited in SKAS0 * A new global variable skas_needs_stub is inserted, that can be used to decide, whether stub-pages must be supported or not. * Uses the syscall-stub to replace missing PTRACE_LDT (therefore, write_ldt_entry needs to be modified) Signed-off-by: Bodo Stroesser Signed-off-by: Jeff Dike Cc: Paolo Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/skas/include/mmu-skas.h | 2 + arch/um/kernel/skas/include/skas.h | 3 +- arch/um/kernel/skas/mem.c | 2 +- arch/um/kernel/skas/mmu.c | 44 +-- arch/um/kernel/skas/process.c | 6 +- arch/um/kernel/skas/process_kern.c | 2 +- arch/um/os-Linux/start_up.c | 75 ++++- arch/um/scripts/Makefile.rules | 7 +- arch/um/sys-i386/ldt.c | 506 ++++++++++++++++++++++++++++++--- arch/um/sys-x86_64/Makefile | 5 +- arch/um/sys-x86_64/syscalls.c | 75 ----- include/asm-um/ldt-i386.h | 69 +++++ include/asm-um/ldt.h | 69 +++++ 13 files changed, 724 insertions(+), 141 deletions(-) create mode 100644 include/asm-um/ldt-i386.h diff --git a/arch/um/kernel/skas/include/mmu-skas.h b/arch/um/kernel/skas/include/mmu-skas.h index 09536f81ee4..44110c521e4 100644 --- a/arch/um/kernel/skas/include/mmu-skas.h +++ b/arch/um/kernel/skas/include/mmu-skas.h @@ -8,6 +8,7 @@ #include "linux/config.h" #include "mm_id.h" +#include "asm/ldt.h" struct mmu_context_skas { struct mm_id id; @@ -15,6 +16,7 @@ struct mmu_context_skas { #ifdef CONFIG_3_LEVEL_PGTABLES unsigned long last_pmd; #endif + uml_ldt_t ldt; }; extern void switch_mm_skas(struct mm_id * mm_idp); diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h index 060934740f9..daa2f85b684 100644 --- a/arch/um/kernel/skas/include/skas.h +++ b/arch/um/kernel/skas/include/skas.h @@ -10,7 +10,8 @@ #include "sysdep/ptrace.h" extern int userspace_pid[]; -extern int proc_mm, ptrace_faultinfo; +extern int proc_mm, ptrace_faultinfo, ptrace_ldt; +extern int skas_needs_stub; extern void switch_threads(void *me, void *next); extern void thread_wait(void *sw, void *fb); diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c index 147466d7ff4..88ab96c609c 100644 --- a/arch/um/kernel/skas/mem.c +++ b/arch/um/kernel/skas/mem.c @@ -20,7 +20,7 @@ unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out, *task_size_out = CONFIG_HOST_TASK_SIZE; #else *host_size_out = top; - if (proc_mm && ptrace_faultinfo) + if (!skas_needs_stub) *task_size_out = top; else *task_size_out = CONFIG_STUB_START & PGDIR_MASK; #endif diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 9e5e39cea82..677871f1b37 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c @@ -15,6 +15,7 @@ #include "asm/mmu.h" #include "asm/pgalloc.h" #include "asm/pgtable.h" +#include "asm/ldt.h" #include "os.h" #include "skas.h" @@ -74,13 +75,12 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc, int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) { - struct mm_struct *cur_mm = current->mm; - struct mm_id *cur_mm_id = &cur_mm->context.skas.id; - struct mm_id *mm_id = &mm->context.skas.id; + struct mmu_context_skas *from_mm = NULL; + struct mmu_context_skas *to_mm = &mm->context.skas; unsigned long stack = 0; - int from, ret = -ENOMEM; + int from_fd, ret = -ENOMEM; - if(!proc_mm || !ptrace_faultinfo){ + if(skas_needs_stub){ stack = get_zeroed_page(GFP_KERNEL); if(stack == 0) goto out; @@ -102,33 +102,43 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) mm->nr_ptes--; } - mm_id->stack = stack; + + to_mm->id.stack = stack; + if(current->mm != NULL && current->mm != &init_mm) + from_mm = ¤t->mm->context.skas; if(proc_mm){ - if((cur_mm != NULL) && (cur_mm != &init_mm)) - from = cur_mm_id->u.mm_fd; - else from = -1; + if(from_mm) + from_fd = from_mm->id.u.mm_fd; + else from_fd = -1; - ret = new_mm(from, stack); + ret = new_mm(from_fd, stack); if(ret < 0){ printk("init_new_context_skas - new_mm failed, " "errno = %d\n", ret); goto out_free; } - mm_id->u.mm_fd = ret; + to_mm->id.u.mm_fd = ret; } else { - if((cur_mm != NULL) && (cur_mm != &init_mm)) - mm_id->u.pid = copy_context_skas0(stack, - cur_mm_id->u.pid); - else mm_id->u.pid = start_userspace(stack); + if(from_mm) + to_mm->id.u.pid = copy_context_skas0(stack, + from_mm->id.u.pid); + else to_mm->id.u.pid = start_userspace(stack); + } + + ret = init_new_ldt(to_mm, from_mm); + if(ret < 0){ + printk("init_new_context_skas - init_ldt" + " failed, errno = %d\n", ret); + goto out_free; } return 0; out_free: - if(mm_id->stack != 0) - free_page(mm_id->stack); + if(to_mm->id.stack != 0) + free_page(to_mm->id.stack); out: return ret; } diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index 42f2da687dc..599d679bd4f 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -381,9 +381,9 @@ int copy_context_skas0(unsigned long new_stack, int pid) } /* - * This is used only, if proc_mm is available, while PTRACE_FAULTINFO - * isn't. Opening /proc/mm creates a new mm_context, which lacks the stub-pages - * Thus, we map them using /proc/mm-fd + * This is used only, if stub pages are needed, while proc_mm is + * availabl. Opening /proc/mm creates a new mm_context, which lacks + * the stub-pages. Thus, we map them using /proc/mm-fd */ void map_stub_pages(int fd, unsigned long code, unsigned long data, unsigned long stack) diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c index efe92e8aa2a..9c990253966 100644 --- a/arch/um/kernel/skas/process_kern.c +++ b/arch/um/kernel/skas/process_kern.c @@ -145,7 +145,7 @@ int new_mm(int from, unsigned long stack) "err = %d\n", -n); } - if(!ptrace_faultinfo) + if(skas_needs_stub) map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack); return(fd); diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index b99ab414542..553a09c7d0b 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -135,7 +135,9 @@ static int stop_ptraced_child(int pid, void *stack, int exitcode, } int ptrace_faultinfo = 1; +int ptrace_ldt = 1; int proc_mm = 1; +int skas_needs_stub = 0; static int __init skas0_cmd_param(char *str, int* add) { @@ -352,14 +354,26 @@ __uml_setup("noptracefaultinfo", noptracefaultinfo_cmd_param, " it. To support PTRACE_FAULTINFO, the host needs to be patched\n" " using the current skas3 patch.\n\n"); +static int __init noptraceldt_cmd_param(char *str, int* add) +{ + ptrace_ldt = 0; + return 0; +} + +__uml_setup("noptraceldt", noptraceldt_cmd_param, +"noptraceldt\n" +" Turns off usage of PTRACE_LDT, even if host supports it.\n" +" To support PTRACE_LDT, the host needs to be patched using\n" +" the current skas3 patch.\n\n"); + #ifdef UML_CONFIG_MODE_SKAS -static inline void check_skas3_ptrace_support(void) +static inline void check_skas3_ptrace_faultinfo(void) { struct ptrace_faultinfo fi; void *stack; int pid, n; - printf("Checking for the skas3 patch in the host..."); + printf(" - PTRACE_FAULTINFO..."); pid = start_ptraced_child(&stack); n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); @@ -381,9 +395,49 @@ static inline void check_skas3_ptrace_support(void) stop_ptraced_child(pid, stack, 1, 1); } -int can_do_skas(void) +static inline void check_skas3_ptrace_ldt(void) +{ +#ifdef PTRACE_LDT + void *stack; + int pid, n; + unsigned char ldtbuf[40]; + struct ptrace_ldt ldt_op = (struct ptrace_ldt) { + .func = 2, /* read default ldt */ + .ptr = ldtbuf, + .bytecount = sizeof(ldtbuf)}; + + printf(" - PTRACE_LDT..."); + pid = start_ptraced_child(&stack); + + n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op); + if (n < 0) { + if(errno == EIO) + printf("not found\n"); + else { + perror("not found"); + } + ptrace_ldt = 0; + } + else { + if(ptrace_ldt) + printf("found\n"); + else + printf("found, but use is disabled\n"); + } + + stop_ptraced_child(pid, stack, 1, 1); +#else + /* PTRACE_LDT might be disabled via cmdline option. + * We want to override this, else we might use the stub + * without real need + */ + ptrace_ldt = 1; +#endif +} + +static inline void check_skas3_proc_mm(void) { - printf("Checking for /proc/mm..."); + printf(" - /proc/mm..."); if (os_access("/proc/mm", OS_ACC_W_OK) < 0) { proc_mm = 0; printf("not found\n"); @@ -394,8 +448,19 @@ int can_do_skas(void) else printf("found\n"); } +} + +int can_do_skas(void) +{ + printf("Checking for the skas3 patch in the host:\n"); + + check_skas3_proc_mm(); + check_skas3_ptrace_faultinfo(); + check_skas3_ptrace_ldt(); + + if(!proc_mm || !ptrace_faultinfo || !ptrace_ldt) + skas_needs_stub = 1; - check_skas3_ptrace_support(); return 1; } #else diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules index 651d9d88b65..b3fbf125709 100644 --- a/arch/um/scripts/Makefile.rules +++ b/arch/um/scripts/Makefile.rules @@ -26,8 +26,13 @@ define unprofile $(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1))) endef +# cmd_make_link checks to see if the $(foo-dir) variable starts with a /. If +# so, it's considered to be a path relative to $(srcdir) rather than +# $(srcdir)/arch/$(SUBARCH). This is because x86_64 wants to get ldt.c from +# arch/um/sys-i386 rather than arch/i386 like the other borrowed files. So, +# it sets $(ldt.c-dir) to /arch/um/sys-i386. quiet_cmd_make_link = SYMLINK $@ -cmd_make_link = ln -sf $(srctree)/arch/$(SUBARCH)/$($(notdir $@)-dir)/$(notdir $@) $@ +cmd_make_link = rm -f $@; ln -sf $(srctree)$(if $(filter-out /%,$($(notdir $@)-dir)),/arch/$(SUBARCH))/$($(notdir $@)-dir)/$(notdir $@) $@ # this needs to be before the foreach, because targets does not accept # complete paths like $(obj)/$(f). To make sure this works, use a := assignment diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c index 36b5c2c1328..6360f1c958d 100644 --- a/arch/um/sys-i386/ldt.c +++ b/arch/um/sys-i386/ldt.c @@ -3,53 +3,26 @@ * Licensed under the GPL */ +#include "linux/stddef.h" #include "linux/config.h" #include "linux/sched.h" #include "linux/slab.h" #include "linux/types.h" +#include "linux/errno.h" #include "asm/uaccess.h" -#include "asm/ptrace.h" #include "asm/smp.h" #include "asm/ldt.h" +#include "asm/unistd.h" #include "choose-mode.h" #include "kern.h" #include "mode_kern.h" -#ifdef CONFIG_MODE_TT - extern int modify_ldt(int func, void *ptr, unsigned long bytecount); -static int do_modify_ldt_tt(int func, void *ptr, unsigned long bytecount) -{ - return modify_ldt(func, ptr, bytecount); -} - -#endif - -#ifdef CONFIG_MODE_SKAS - -#include "skas.h" -#include "skas_ptrace.h" - -static int do_modify_ldt_skas(int func, void *ptr, unsigned long bytecount) -{ - struct ptrace_ldt ldt; - u32 cpu; - int res; - - ldt = ((struct ptrace_ldt) { .func = func, - .ptr = ptr, - .bytecount = bytecount }); - - cpu = get_cpu(); - res = ptrace(PTRACE_LDT, userspace_pid[cpu], 0, (unsigned long) &ldt); - put_cpu(); - - return res; -} -#endif +#ifdef CONFIG_MODE_TT -int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) +static long do_modify_ldt_tt(int func, void __user *ptr, + unsigned long bytecount) { struct user_desc info; int res = 0; @@ -89,8 +62,7 @@ int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) goto out; } - res = CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func, - p, bytecount); + res = modify_ldt(func, p, bytecount); if(res < 0) goto out; @@ -108,3 +80,467 @@ out: kfree(buf); return res; } + +#endif + +#ifdef CONFIG_MODE_SKAS + +#include "skas.h" +#include "skas_ptrace.h" +#include "asm/mmu_context.h" + +long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc, + void **addr, int done) +{ + long res; + + if(proc_mm){ + /* This is a special handling for the case, that the mm to + * modify isn't current->active_mm. + * If this is called directly by modify_ldt, + * (current->active_mm->context.skas.u == mm_idp) + * will be true. So no call to switch_mm_skas(mm_idp) is done. + * If this is called in case of init_new_ldt or PTRACE_LDT, + * mm_idp won't belong to current->active_mm, but child->mm. + * So we need to switch child's mm into our userspace, then + * later switch back. + * + * Note: I'm unshure: should interrupts be disabled here? + */ + if(!current->active_mm || current->active_mm == &init_mm || + mm_idp != ¤t->active_mm->context.skas.id) + switch_mm_skas(mm_idp); + } + + if(ptrace_ldt) { + struct ptrace_ldt ldt_op = (struct ptrace_ldt) { + .func = func, + .ptr = desc, + .bytecount = sizeof(*desc)}; + u32 cpu; + int pid; + + if(!proc_mm) + pid = mm_idp->u.pid; + else { + cpu = get_cpu(); + pid = userspace_pid[cpu]; + } + + res = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op); + if(res) + res = errno; + + if(proc_mm) + put_cpu(); + } + else { + void *stub_addr; + res = syscall_stub_data(mm_idp, (unsigned long *)desc, + (sizeof(*desc) + sizeof(long) - 1) & + ~(sizeof(long) - 1), + addr, &stub_addr); + if(!res){ + unsigned long args[] = { func, + (unsigned long)stub_addr, + sizeof(*desc), + 0, 0, 0 }; + res = run_syscall_stub(mm_idp, __NR_modify_ldt, args, + 0, addr, done); + } + } + + if(proc_mm){ + /* This is the second part of special handling, that makes + * PTRACE_LDT possible to implement. + */ + if(current->active_mm && current->active_mm != &init_mm && + mm_idp != ¤t->active_mm->context.skas.id) + switch_mm_skas(¤t->active_mm->context.skas.id); + } + + return res; +} + +static long read_ldt_from_host(void __user * ptr, unsigned long bytecount) +{ + int res, n; + struct ptrace_ldt ptrace_ldt = (struct ptrace_ldt) { + .func = 0, + .bytecount = bytecount, + .ptr = (void *)kmalloc(bytecount, GFP_KERNEL)}; + u32 cpu; + + if(ptrace_ldt.ptr == NULL) + return -ENOMEM; + + /* This is called from sys_modify_ldt only, so userspace_pid gives + * us the right number + */ + + cpu = get_cpu(); + res = ptrace(PTRACE_LDT, userspace_pid[cpu], 0, + (unsigned long) &ptrace_ldt); + put_cpu(); + if(res < 0) + goto out; + + n = copy_to_user(ptr, ptrace_ldt.ptr, res); + if(n != 0) + res = -EFAULT; + + out: + kfree(ptrace_ldt.ptr); + + return res; +} + +/* + * In skas mode, we hold our own ldt data in UML. + * Thus, the code implementing sys_modify_ldt_skas + * is very similar to (and mostly stolen from) sys_modify_ldt + * for arch/i386/kernel/ldt.c + * The routines copied and modified in part are: + * - read_ldt + * - read_default_ldt + * - write_ldt + * - sys_modify_ldt_skas + */ + +static int read_ldt(void __user * ptr, unsigned long bytecount) +{ + int i, err = 0; + unsigned long size; + uml_ldt_t * ldt = ¤t->mm->context.skas.ldt; + + if(!ldt->entry_count) + goto out; + if(bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES) + bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES; + err = bytecount; + + if(ptrace_ldt){ + return read_ldt_from_host(ptr, bytecount); + } + + down(&ldt->semaphore); + if(ldt->entry_count <= LDT_DIRECT_ENTRIES){ + size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES; + if(size > bytecount) + size = bytecount; + if(copy_to_user(ptr, ldt->entries, size)) + err = -EFAULT; + bytecount -= size; + ptr += size; + } + else { + for(i=0; ientry_count/LDT_ENTRIES_PER_PAGE && bytecount; + i++){ + size = PAGE_SIZE; + if(size > bytecount) + size = bytecount; + if(copy_to_user(ptr, ldt->pages[i], size)){ + err = -EFAULT; + break; + } + bytecount -= size; + ptr += size; + } + } + up(&ldt->semaphore); + + if(bytecount == 0 || err == -EFAULT) + goto out; + + if(clear_user(ptr, bytecount)) + err = -EFAULT; + +out: + return err; +} + +static int read_default_ldt(void __user * ptr, unsigned long bytecount) +{ + int err; + + if(bytecount > 5*LDT_ENTRY_SIZE) + bytecount = 5*LDT_ENTRY_SIZE; + + err = bytecount; + /* UML doesn't support lcall7 and lcall27. + * So, we don't really have a default ldt, but emulate + * an empty ldt of common host default ldt size. + */ + if(clear_user(ptr, bytecount)) + err = -EFAULT; + + return err; +} + +static int write_ldt(void __user * ptr, unsigned long bytecount, int func) +{ + uml_ldt_t * ldt = ¤t->mm->context.skas.ldt; + struct mm_id * mm_idp = ¤t->mm->context.skas.id; + int i, err; + struct user_desc ldt_info; + struct ldt_entry entry0, *ldt_p; + void *addr = NULL; + + err = -EINVAL; + if(bytecount != sizeof(ldt_info)) + goto out; + err = -EFAULT; + if(copy_from_user(&ldt_info, ptr, sizeof(ldt_info))) + goto out; + + err = -EINVAL; + if(ldt_info.entry_number >= LDT_ENTRIES) + goto out; + if(ldt_info.contents == 3){ + if (func == 1) + goto out; + if (ldt_info.seg_not_present == 0) + goto out; + } + + if(!ptrace_ldt) + down(&ldt->semaphore); + + err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1); + if(err) + goto out_unlock; + else if(ptrace_ldt) { + /* With PTRACE_LDT available, this is used as a flag only */ + ldt->entry_count = 1; + goto out; + } + + if(ldt_info.entry_number >= ldt->entry_count && + ldt_info.entry_number >= LDT_DIRECT_ENTRIES){ + for(i=ldt->entry_count/LDT_ENTRIES_PER_PAGE; + i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number; + i++){ + if(i == 0) + memcpy(&entry0, ldt->entries, sizeof(entry0)); + ldt->pages[i] = (struct ldt_entry *) + __get_free_page(GFP_KERNEL|__GFP_ZERO); + if(!ldt->pages[i]){ + err = -ENOMEM; + /* Undo the change in host */ + memset(&ldt_info, 0, sizeof(ldt_info)); + write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1); + goto out_unlock; + } + if(i == 0) { + memcpy(ldt->pages[0], &entry0, sizeof(entry0)); + memcpy(ldt->pages[0]+1, ldt->entries+1, + sizeof(entry0)*(LDT_DIRECT_ENTRIES-1)); + } + ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE; + } + } + if(ldt->entry_count <= ldt_info.entry_number) + ldt->entry_count = ldt_info.entry_number + 1; + + if(ldt->entry_count <= LDT_DIRECT_ENTRIES) + ldt_p = ldt->entries + ldt_info.entry_number; + else + ldt_p = ldt->pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] + + ldt_info.entry_number%LDT_ENTRIES_PER_PAGE; + + if(ldt_info.base_addr == 0 && ldt_info.limit == 0 && + (func == 1 || LDT_empty(&ldt_info))){ + ldt_p->a = 0; + ldt_p->b = 0; + } + else{ + if (func == 1) + ldt_info.useable = 0; + ldt_p->a = LDT_entry_a(&ldt_info); + ldt_p->b = LDT_entry_b(&ldt_info); + } + err = 0; + +out_unlock: + up(&ldt->semaphore); +out: + return err; +} + +static long do_modify_ldt_skas(int func, void __user *ptr, + unsigned long bytecount) +{ + int ret = -ENOSYS; + + switch (func) { + case 0: + ret = read_ldt(ptr, bytecount); + break; + case 1: + case 0x11: + ret = write_ldt(ptr, bytecount, func); + break; + case 2: + ret = read_default_ldt(ptr, bytecount); + break; + } + return ret; +} + +short dummy_list[9] = {0, -1}; +short * host_ldt_entries = NULL; + +void ldt_get_host_info(void) +{ + long ret; + struct ldt_entry * ldt; + int i, size, k, order; + + host_ldt_entries = dummy_list+1; + + for(i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++); + + ldt = (struct ldt_entry *) + __get_free_pages(GFP_KERNEL|__GFP_ZERO, order); + if(ldt == NULL) { + printk("ldt_get_host_info: couldn't allocate buffer for host ldt\n"); + return; + } + + ret = modify_ldt(0, ldt, (1<ldt.semaphore); + + if(!from_mm){ + /* + * We have to initialize a clean ldt. + */ + if(proc_mm) { + /* + * If the new mm was created using proc_mm, host's + * default-ldt currently is assigned, which normally + * contains the call-gates for lcall7 and lcall27. + * To remove these gates, we simply write an empty + * entry as number 0 to the host. + */ + err = write_ldt_entry(&new_mm->id, 1, &desc, + &addr, 1); + } + else{ + /* + * Now we try to retrieve info about the ldt, we + * inherited from the host. All ldt-entries found + * will be reset in the following loop + */ + if(host_ldt_entries == NULL) + ldt_get_host_info(); + for(num_p=host_ldt_entries; *num_p != -1; num_p++){ + desc.entry_number = *num_p; + err = write_ldt_entry(&new_mm->id, 1, &desc, + &addr, *(num_p + 1) == -1); + if(err) + break; + } + } + new_mm->ldt.entry_count = 0; + } + else if (!ptrace_ldt) { + /* Our local LDT is used to supply the data for + * modify_ldt(READLDT), if PTRACE_LDT isn't available, + * i.e., we have to use the stub for modify_ldt, which + * can't handle the big read buffer of up to 64kB. + */ + down(&from_mm->ldt.semaphore); + if(from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES){ + memcpy(new_mm->ldt.entries, from_mm->ldt.entries, + sizeof(new_mm->ldt.entries)); + } + else{ + i = from_mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE; + while(i-->0){ + page = __get_free_page(GFP_KERNEL|__GFP_ZERO); + if (!page){ + err = -ENOMEM; + break; + } + new_mm->ldt.pages[i] = (struct ldt_entry*)page; + memcpy(new_mm->ldt.pages[i], + from_mm->ldt.pages[i], PAGE_SIZE); + } + } + new_mm->ldt.entry_count = from_mm->ldt.entry_count; + up(&from_mm->ldt.semaphore); + } + + return err; +} + + +void free_ldt(struct mmu_context_skas * mm) +{ + int i; + + if(!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES){ + i = mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE; + while(i-- > 0){ + free_page((long )mm->ldt.pages[i]); + } + } + mm->ldt.entry_count = 0; +} +#endif + +int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) +{ + return(CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func, + ptr, bytecount)); +} diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile index 06c3633457a..ea977df395a 100644 --- a/arch/um/sys-x86_64/Makefile +++ b/arch/um/sys-x86_64/Makefile @@ -5,7 +5,7 @@ # #XXX: why into lib-y? -lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o mem.o memcpy.o \ +lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o ldt.o mem.o memcpy.o \ ptrace.o ptrace_user.o sigcontext.o signal.o stub.o \ stub_segv.o syscalls.o syscall_table.o sysrq.o thunk.o @@ -14,7 +14,7 @@ obj-$(CONFIG_MODULES) += module.o um_module.o USER_OBJS := ptrace_user.o sigcontext.o -SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c memcpy.S \ +SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c ldt.c memcpy.S \ thunk.S module.c include arch/um/scripts/Makefile.rules @@ -23,6 +23,7 @@ bitops.c-dir = lib csum-copy.S-dir = lib csum-partial.c-dir = lib csum-wrappers.c-dir = lib +ldt.c-dir = /arch/um/sys-i386 memcpy.S-dir = lib thunk.S-dir = lib module.c-dir = kernel diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c index 3259a4db453..6acee5c4ada 100644 --- a/arch/um/sys-x86_64/syscalls.c +++ b/arch/um/sys-x86_64/syscalls.c @@ -28,81 +28,6 @@ asmlinkage long sys_uname64(struct new_utsname __user * name) return err ? -EFAULT : 0; } -#ifdef CONFIG_MODE_TT -extern int modify_ldt(int func, void *ptr, unsigned long bytecount); - -long sys_modify_ldt_tt(int func, void *ptr, unsigned long bytecount) -{ - /* XXX This should check VERIFY_WRITE depending on func, check this - * in i386 as well. - */ - if (!access_ok(VERIFY_READ, ptr, bytecount)) - return -EFAULT; - return(modify_ldt(func, ptr, bytecount)); -} -#endif - -#ifdef CONFIG_MODE_SKAS -extern int userspace_pid[]; - -#include "skas_ptrace.h" - -long sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount) -{ - struct ptrace_ldt ldt; - void *buf; - int res, n; - - buf = kmalloc(bytecount, GFP_KERNEL); - if(buf == NULL) - return(-ENOMEM); - - res = 0; - - switch(func){ - case 1: - case 0x11: - res = copy_from_user(buf, ptr, bytecount); - break; - } - - if(res != 0){ - res = -EFAULT; - goto out; - } - - ldt = ((struct ptrace_ldt) { .func = func, - .ptr = buf, - .bytecount = bytecount }); -#warning Need to look up userspace_pid by cpu - res = ptrace(PTRACE_LDT, userspace_pid[0], 0, (unsigned long) &ldt); - if(res < 0) - goto out; - - switch(func){ - case 0: - case 2: - n = res; - res = copy_to_user(ptr, buf, n); - if(res != 0) - res = -EFAULT; - else - res = n; - break; - } - - out: - kfree(buf); - return(res); -} -#endif - -long sys_modify_ldt(int func, void *ptr, unsigned long bytecount) -{ - return(CHOOSE_MODE_PROC(sys_modify_ldt_tt, sys_modify_ldt_skas, func, - ptr, bytecount)); -} - #ifdef CONFIG_MODE_TT extern long arch_prctl(int code, unsigned long addr); diff --git a/include/asm-um/ldt-i386.h b/include/asm-um/ldt-i386.h new file mode 100644 index 00000000000..b42662929b6 --- /dev/null +++ b/include/asm-um/ldt-i386.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2004 Fujitsu Siemens Computers GmbH + * Licensed under the GPL + * + * Author: Bodo Stroesser + */ + +#ifndef __ASM_LDT_I386_H +#define __ASM_LDT_I386_H + +#include "asm/semaphore.h" +#include "asm/arch/ldt.h" + +struct mmu_context_skas; +extern void ldt_host_info(void); +extern long init_new_ldt(struct mmu_context_skas * to_mm, + struct mmu_context_skas * from_mm); +extern void free_ldt(struct mmu_context_skas * mm); + +#define LDT_PAGES_MAX \ + ((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE) +#define LDT_ENTRIES_PER_PAGE \ + (PAGE_SIZE/LDT_ENTRY_SIZE) +#define LDT_DIRECT_ENTRIES \ + ((LDT_PAGES_MAX*sizeof(void *))/LDT_ENTRY_SIZE) + +struct ldt_entry { + __u32 a; + __u32 b; +}; + +typedef struct uml_ldt { + int entry_count; + struct semaphore semaphore; + union { + struct ldt_entry * pages[LDT_PAGES_MAX]; + struct ldt_entry entries[LDT_DIRECT_ENTRIES]; + }; +} uml_ldt_t; + +/* + * macros stolen from include/asm-i386/desc.h + */ +#define LDT_entry_a(info) \ + ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff)) + +#define LDT_entry_b(info) \ + (((info)->base_addr & 0xff000000) | \ + (((info)->base_addr & 0x00ff0000) >> 16) | \ + ((info)->limit & 0xf0000) | \ + (((info)->read_exec_only ^ 1) << 9) | \ + ((info)->contents << 10) | \ + (((info)->seg_not_present ^ 1) << 15) | \ + ((info)->seg_32bit << 22) | \ + ((info)->limit_in_pages << 23) | \ + ((info)->useable << 20) | \ + 0x7000) + +#define LDT_empty(info) (\ + (info)->base_addr == 0 && \ + (info)->limit == 0 && \ + (info)->contents == 0 && \ + (info)->read_exec_only == 1 && \ + (info)->seg_32bit == 0 && \ + (info)->limit_in_pages == 0 && \ + (info)->seg_not_present == 1 && \ + (info)->useable == 0 ) + +#endif diff --git a/include/asm-um/ldt.h b/include/asm-um/ldt.h index e908439d338..4466ff6de0f 100644 --- a/include/asm-um/ldt.h +++ b/include/asm-um/ldt.h @@ -1,3 +1,72 @@ +/* + * Copyright (C) 2004 Fujitsu Siemens Computers GmbH + * Licensed under the GPL + * + * Author: Bodo Stroesser + */ + +#ifndef __ASM_LDT_I386_H +#define __ASM_LDT_I386_H + +#include "asm/semaphore.h" +#include "asm/arch/ldt.h" + +struct mmu_context_skas; +extern void ldt_host_info(void); +extern long init_new_ldt(struct mmu_context_skas * to_mm, + struct mmu_context_skas * from_mm); +extern void free_ldt(struct mmu_context_skas * mm); + +#define LDT_PAGES_MAX \ + ((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE) +#define LDT_ENTRIES_PER_PAGE \ + (PAGE_SIZE/LDT_ENTRY_SIZE) +#define LDT_DIRECT_ENTRIES \ + ((LDT_PAGES_MAX*sizeof(void *))/LDT_ENTRY_SIZE) + +struct ldt_entry { + __u32 a; + __u32 b; +}; + +typedef struct uml_ldt { + int entry_count; + struct semaphore semaphore; + union { + struct ldt_entry * pages[LDT_PAGES_MAX]; + struct ldt_entry entries[LDT_DIRECT_ENTRIES]; + }; +} uml_ldt_t; + +/* + * macros stolen from include/asm-i386/desc.h + */ +#define LDT_entry_a(info) \ + ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff)) + +#define LDT_entry_b(info) \ + (((info)->base_addr & 0xff000000) | \ + (((info)->base_addr & 0x00ff0000) >> 16) | \ + ((info)->limit & 0xf0000) | \ + (((info)->read_exec_only ^ 1) << 9) | \ + ((info)->contents << 10) | \ + (((info)->seg_not_present ^ 1) << 15) | \ + ((info)->seg_32bit << 22) | \ + ((info)->limit_in_pages << 23) | \ + ((info)->useable << 20) | \ + 0x7000) + +#define LDT_empty(info) (\ + (info)->base_addr == 0 && \ + (info)->limit == 0 && \ + (info)->contents == 0 && \ + (info)->read_exec_only == 1 && \ + (info)->seg_32bit == 0 && \ + (info)->limit_in_pages == 0 && \ + (info)->seg_not_present == 1 && \ + (info)->useable == 0 ) + +#endif #ifndef __UM_LDT_H #define __UM_LDT_H -- cgit v1.2.3 From ae17381608a11781a6a67e0ce51607f36780aac7 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 7 Nov 2005 00:58:57 -0800 Subject: [PATCH] uml: big memory fixes A number of fixes to improve behavior when large physical memory sizes are specified: - libc files need -D_FILE_OFFSET_BITS=64 because there are unavoidable uses of non-64 interfaces in libc - some %d need to be %u Signed-off-by: Jeff Dike Cc: Paolo Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/Makefile | 2 +- arch/um/include/mem_user.h | 2 +- arch/um/include/os.h | 2 +- arch/um/kernel/physmem.c | 4 ++-- arch/um/kernel/um_arch.c | 10 +++++----- arch/um/os-Linux/mem.c | 6 +++--- arch/um/os-Linux/start_up.c | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/arch/um/Makefile b/arch/um/Makefile index e1ffad22460..e55d32e903b 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -60,7 +60,7 @@ AFLAGS += $(ARCH_INCLUDE) USER_CFLAGS := $(patsubst -I%,,$(CFLAGS)) USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \ - $(MODE_INCLUDE) + $(MODE_INCLUDE) -D_FILE_OFFSET_BITS=64 # -Derrno=kernel_errno - This turns all kernel references to errno into # kernel_errno to separate them from the libc errno. This allows -fno-common diff --git a/arch/um/include/mem_user.h b/arch/um/include/mem_user.h index 9fef4123a65..a1064c5823b 100644 --- a/arch/um/include/mem_user.h +++ b/arch/um/include/mem_user.h @@ -57,7 +57,7 @@ extern int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem); extern unsigned long get_vm(unsigned long len); extern void setup_physmem(unsigned long start, unsigned long usable, - unsigned long len, unsigned long highmem); + unsigned long len, unsigned long long highmem); extern void add_iomem(char *name, int fd, unsigned long size); extern unsigned long phys_offset(unsigned long phys); extern void unmap_physmem(void); diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 112d7288f0c..2cccfa5b8ab 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -167,7 +167,7 @@ extern int can_do_skas(void); #endif /* mem.c */ -extern int create_mem_file(unsigned long len); +extern int create_mem_file(unsigned long long len); /* process.c */ extern unsigned long os_process_pc(int pid); diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index ea670fcc8af..f3b583a878a 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -246,7 +246,7 @@ int is_remapped(void *virt) /* Changed during early boot */ unsigned long high_physmem; -extern unsigned long physmem_size; +extern unsigned long long physmem_size; int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem) { @@ -321,7 +321,7 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len, extern int __syscall_stub_start, __binary_start; void setup_physmem(unsigned long start, unsigned long reserve_end, - unsigned long len, unsigned long highmem) + unsigned long len, unsigned long long highmem) { unsigned long reserve = reserve_end - start; int pfn = PFN_UP(__pa(reserve_end)); diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 93dc782dc1c..142a9493912 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -137,7 +137,7 @@ static char *argv1_end = NULL; /* Set in early boot */ static int have_root __initdata = 0; -long physmem_size = 32 * 1024 * 1024; +long long physmem_size = 32 * 1024 * 1024; void set_cmdline(char *cmd) { @@ -402,7 +402,7 @@ int linux_main(int argc, char **argv) #ifndef CONFIG_HIGHMEM highmem = 0; printf("CONFIG_HIGHMEM not enabled - physical memory shrunk " - "to %ld bytes\n", physmem_size); + "to %lu bytes\n", physmem_size); #endif } @@ -414,8 +414,8 @@ int linux_main(int argc, char **argv) setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem); if(init_maps(physmem_size, iomem_size, highmem)){ - printf("Failed to allocate mem_map for %ld bytes of physical " - "memory and %ld bytes of highmem\n", physmem_size, + printf("Failed to allocate mem_map for %lu bytes of physical " + "memory and %lu bytes of highmem\n", physmem_size, highmem); exit(1); } @@ -426,7 +426,7 @@ int linux_main(int argc, char **argv) end_vm = start_vm + virtmem_size; if(virtmem_size < physmem_size) - printf("Kernel virtual memory size shrunk to %ld bytes\n", + printf("Kernel virtual memory size shrunk to %lu bytes\n", virtmem_size); uml_postsetup(); diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c index 8e71edaaf80..9d7d69a523b 100644 --- a/arch/um/os-Linux/mem.c +++ b/arch/um/os-Linux/mem.c @@ -88,7 +88,7 @@ int make_tempfile(const char *template, char **out_tempname, int do_unlink) * This proc is used in start_up.c * So it isn't 'static'. */ -int create_tmp_file(unsigned long len) +int create_tmp_file(unsigned long long len) { int fd, err; char zero; @@ -121,7 +121,7 @@ int create_tmp_file(unsigned long len) return(fd); } -static int create_anon_file(unsigned long len) +static int create_anon_file(unsigned long long len) { void *addr; int fd; @@ -144,7 +144,7 @@ static int create_anon_file(unsigned long len) extern int have_devanon; -int create_mem_file(unsigned long len) +int create_mem_file(unsigned long long len) { int err, fd; diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 553a09c7d0b..37517d49c4a 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -296,7 +296,7 @@ static void __init check_ptrace(void) check_sysemu(); } -extern int create_tmp_file(unsigned long len); +extern int create_tmp_file(unsigned long long len); static void check_tmpexec(void) { -- cgit v1.2.3 From 77cc0db46e5d04b476e1984134892edb86cda8e6 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 7 Nov 2005 00:58:57 -0800 Subject: [PATCH] uml: make tt mode-dependent options depend on MODE_TT This makes some of the tt-specific options actually depend on CONFIG_MODE_TT. Signed-off-by: Jeff Dike Cc: Paolo Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/Kconfig | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/arch/um/Kconfig b/arch/um/Kconfig index cd06ed7d842..3b5f47c4690 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -65,6 +65,30 @@ config STATIC_LINK chroot, and you disable CONFIG_MODE_TT, you probably want to say Y here. +config HOST_2G_2G + bool "2G/2G host address space split" + default n + depends on MODE_TT + help + This is needed when the host on which you run has a 2G/2G memory + split, instead of the customary 3G/1G. + + Note that to enable such a host + configuration, which makes sense only in some cases, you need special + host patches. + + So, if you do not know what to do here, say 'N'. + +config KERNEL_HALF_GIGS + int "Kernel address space size (in .5G units)" + default "1" + depends on MODE_TT + help + This determines the amount of address space that UML will allocate for + its own, measured in half Gigabyte units. The default is 1. + Change this only if you need to boot UML with an unusually large amount + of physical memory. + config MODE_SKAS bool "Separate Kernel Address Space support" default y @@ -182,19 +206,6 @@ config MAGIC_SYSRQ The keys are documented in . Don't say Y unless you really know what this hack does. -config HOST_2G_2G - bool "2G/2G host address space split" - default n - help - This is needed when the host on which you run has a 2G/2G memory - split, instead of the customary 3G/1G. - - Note that to enable such a host - configuration, which makes sense only in some cases, you need special - host patches. - - So, if you do not know what to do here, say 'N'. - config SMP bool "Symmetric multi-processing support (EXPERIMENTAL)" default n @@ -241,15 +252,6 @@ config NEST_LEVEL set to the host's CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS. Only change this if you are running nested UMLs. -config KERNEL_HALF_GIGS - int "Kernel address space size (in .5G units)" - default "1" - help - This determines the amount of address space that UML will allocate for - its own, measured in half Gigabyte units. The default is 1. - Change this only if you need to boot UML with an unusually large amount - of physical memory. - config HIGHMEM bool "Highmem support" depends on !64BIT -- cgit v1.2.3 From 353f8d1cd5b8540c1591f00a5cbd3aeca699cfcf Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Mon, 7 Nov 2005 00:58:58 -0800 Subject: [PATCH] uml: fix hardcoded ZONE_* constants in zone setup Remove usage of hardcoded constants in paging_init(). By chance I spotted a bug in zones_setup involving a change to ZONE_* constants, due to the ZONE_DMA32 patch from Andi Kleen (which is in -mm). So, possibly, instead of zones_size[2] you will find zones_size[3] in the code, but that change is wrong and this patch is still correct. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/mem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 462cc9d6538..fa4f915be5c 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -234,8 +234,8 @@ void paging_init(void) empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); for(i=0;i> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT); - zones_size[2] = highmem >> PAGE_SHIFT; + zones_size[ZONE_DMA] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT); + zones_size[ZONE_HIGHMEM] = highmem >> PAGE_SHIFT; free_area_init(zones_size); /* -- cgit v1.2.3 From 26d89d1eef38473d0da64b7137952c56d0b6d13f Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Mon, 7 Nov 2005 00:58:59 -0800 Subject: [PATCH] uml: build host-binaries with the native host arch again This patch reverts back the changes to HOSTCFLAGS and HOSTLDFLAGS When we were building complete binaries to get constants (such as ptrace register layout on stack) from host userspace headers, we needed to make the arch for building HOST binaries match our one: i.e. on a 64bit system compiling 32bit binaries, we compile 32-bit hostprogs and need, say, 32-bit ncurses. Now we can revert that - that avoids problem with, say, menuconfig and ncurses, on a system which can't compile well 32-bit programs. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/Makefile-i386 | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 index aef7c50f8e1..1f7dcb064ae 100644 --- a/arch/um/Makefile-i386 +++ b/arch/um/Makefile-i386 @@ -17,8 +17,6 @@ ifeq ("$(origin SUBARCH)", "command line") ifneq ("$(shell uname -m | sed -e s/i.86/i386/)", "$(SUBARCH)") CFLAGS += $(call cc-option,-m32) USER_CFLAGS += $(call cc-option,-m32) -HOSTCFLAGS += $(call cc-option,-m32) -HOSTLDFLAGS += $(call cc-option,-m32) AFLAGS += $(call cc-option,-m32) LINK-y += $(call cc-option,-m32) UML_OBJCOPYFLAGS += -F $(ELF_FORMAT) -- cgit v1.2.3 From 23f88fe4bffe01a0d29326789cb5813cd6f8158e Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 00:59:00 -0800 Subject: [PATCH] include/asm-v850/ "extern inline" -> "static inline" "extern inline" doesn't make much sense. Signed-off-by: Adrian Bunk Cc: Miles Bader Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-v850/atomic.h | 2 +- include/asm-v850/bitops.h | 6 +++--- include/asm-v850/delay.h | 4 ++-- include/asm-v850/hw_irq.h | 2 +- include/asm-v850/processor.h | 4 ++-- include/asm-v850/semaphore.h | 10 +++++----- include/asm-v850/system.h | 2 +- include/asm-v850/tlbflush.h | 4 ++-- include/asm-v850/uaccess.h | 2 +- include/asm-v850/unaligned.h | 6 +++--- 10 files changed, 21 insertions(+), 21 deletions(-) diff --git a/include/asm-v850/atomic.h b/include/asm-v850/atomic.h index 8284aa7363f..395268a8c0d 100644 --- a/include/asm-v850/atomic.h +++ b/include/asm-v850/atomic.h @@ -31,7 +31,7 @@ typedef struct { int counter; } atomic_t; #define atomic_read(v) ((v)->counter) #define atomic_set(v,i) (((v)->counter) = (i)) -extern __inline__ int atomic_add_return (int i, volatile atomic_t *v) +static inline int atomic_add_return (int i, volatile atomic_t *v) { unsigned long flags; int res; diff --git a/include/asm-v850/bitops.h b/include/asm-v850/bitops.h index 0e5c2f21087..b91e799763f 100644 --- a/include/asm-v850/bitops.h +++ b/include/asm-v850/bitops.h @@ -30,7 +30,7 @@ * ffz = Find First Zero in word. Undefined if no zero exists, * so code should check against ~0UL first.. */ -extern __inline__ unsigned long ffz (unsigned long word) +static inline unsigned long ffz (unsigned long word) { unsigned long result = 0; @@ -135,7 +135,7 @@ extern __inline__ unsigned long ffz (unsigned long word) "m" (*((const char *)(addr) + ((nr) >> 3)))); \ __test_bit_res; \ }) -extern __inline__ int __test_bit (int nr, const void *addr) +static inline int __test_bit (int nr, const void *addr) { int res; __asm__ __volatile__ ("tst1 %1, [%2]; setf nz, %0" @@ -157,7 +157,7 @@ extern __inline__ int __test_bit (int nr, const void *addr) #define find_first_zero_bit(addr, size) \ find_next_zero_bit ((addr), (size), 0) -extern __inline__ int find_next_zero_bit(const void *addr, int size, int offset) +static inline int find_next_zero_bit(const void *addr, int size, int offset) { unsigned long *p = ((unsigned long *) addr) + (offset >> 5); unsigned long result = offset & ~31UL; diff --git a/include/asm-v850/delay.h b/include/asm-v850/delay.h index 1ce65d48a7c..6d028e6b235 100644 --- a/include/asm-v850/delay.h +++ b/include/asm-v850/delay.h @@ -16,7 +16,7 @@ #include -extern __inline__ void __delay(unsigned long loops) +static inline void __delay(unsigned long loops) { if (loops) __asm__ __volatile__ ("1: add -1, %0; bnz 1b" @@ -33,7 +33,7 @@ extern __inline__ void __delay(unsigned long loops) extern unsigned long loops_per_jiffy; -extern __inline__ void udelay(unsigned long usecs) +static inline void udelay(unsigned long usecs) { register unsigned long full_loops, part_loops; diff --git a/include/asm-v850/hw_irq.h b/include/asm-v850/hw_irq.h index 4bdc98edb9f..a8aab434271 100644 --- a/include/asm-v850/hw_irq.h +++ b/include/asm-v850/hw_irq.h @@ -1,7 +1,7 @@ #ifndef __V850_HW_IRQ_H__ #define __V850_HW_IRQ_H__ -extern inline void hw_resend_irq (struct hw_interrupt_type *h, unsigned int i) +static inline void hw_resend_irq (struct hw_interrupt_type *h, unsigned int i) { } diff --git a/include/asm-v850/processor.h b/include/asm-v850/processor.h index d41f925f518..98f929427d3 100644 --- a/include/asm-v850/processor.h +++ b/include/asm-v850/processor.h @@ -59,7 +59,7 @@ struct thread_struct { /* Do necessary setup to start up a newly executed thread. */ -extern inline void start_thread (struct pt_regs *regs, +static inline void start_thread (struct pt_regs *regs, unsigned long pc, unsigned long usp) { regs->pc = pc; @@ -68,7 +68,7 @@ extern inline void start_thread (struct pt_regs *regs, } /* Free all resources held by a thread. */ -extern inline void release_thread (struct task_struct *dead_task) +static inline void release_thread (struct task_struct *dead_task) { } diff --git a/include/asm-v850/semaphore.h b/include/asm-v850/semaphore.h index df6cdecf6c1..735baaf3a16 100644 --- a/include/asm-v850/semaphore.h +++ b/include/asm-v850/semaphore.h @@ -24,7 +24,7 @@ struct semaphore { #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC (name,1) #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC (name,0) -extern inline void sema_init (struct semaphore *sem, int val) +static inline void sema_init (struct semaphore *sem, int val) { *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val); } @@ -52,14 +52,14 @@ extern int __down_interruptible (struct semaphore * sem); extern int __down_trylock (struct semaphore * sem); extern void __up (struct semaphore * sem); -extern inline void down (struct semaphore * sem) +static inline void down (struct semaphore * sem) { might_sleep(); if (atomic_dec_return (&sem->count) < 0) __down (sem); } -extern inline int down_interruptible (struct semaphore * sem) +static inline int down_interruptible (struct semaphore * sem) { int ret = 0; might_sleep(); @@ -68,7 +68,7 @@ extern inline int down_interruptible (struct semaphore * sem) return ret; } -extern inline int down_trylock (struct semaphore *sem) +static inline int down_trylock (struct semaphore *sem) { int ret = 0; if (atomic_dec_return (&sem->count) < 0) @@ -76,7 +76,7 @@ extern inline int down_trylock (struct semaphore *sem) return ret; } -extern inline void up (struct semaphore * sem) +static inline void up (struct semaphore * sem) { if (atomic_inc_return (&sem->count) <= 0) __up (sem); diff --git a/include/asm-v850/system.h b/include/asm-v850/system.h index 20f4c738c04..107decbd6e6 100644 --- a/include/asm-v850/system.h +++ b/include/asm-v850/system.h @@ -81,7 +81,7 @@ static inline int irqs_disabled (void) ((__typeof__ (*(ptr)))__xchg ((unsigned long)(with), (ptr), sizeof (*(ptr)))) #define tas(ptr) (xchg ((ptr), 1)) -extern inline unsigned long __xchg (unsigned long with, +static inline unsigned long __xchg (unsigned long with, __volatile__ void *ptr, int size) { unsigned long tmp, flags; diff --git a/include/asm-v850/tlbflush.h b/include/asm-v850/tlbflush.h index 501e4498172..5f2f85f636e 100644 --- a/include/asm-v850/tlbflush.h +++ b/include/asm-v850/tlbflush.h @@ -56,12 +56,12 @@ static inline void flush_tlb_range(struct vm_area_struct *vma, BUG (); } -extern inline void flush_tlb_kernel_page(unsigned long addr) +static inline void flush_tlb_kernel_page(unsigned long addr) { BUG (); } -extern inline void flush_tlb_pgtables(struct mm_struct *mm, +static inline void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start, unsigned long end) { BUG (); diff --git a/include/asm-v850/uaccess.h b/include/asm-v850/uaccess.h index 188b28597cf..64563c409bb 100644 --- a/include/asm-v850/uaccess.h +++ b/include/asm-v850/uaccess.h @@ -14,7 +14,7 @@ #define VERIFY_READ 0 #define VERIFY_WRITE 1 -extern inline int access_ok (int type, const void *addr, unsigned long size) +static inline int access_ok (int type, const void *addr, unsigned long size) { /* XXX I guess we should check against real ram bounds at least, and possibly make sure ADDR is not within the kernel. diff --git a/include/asm-v850/unaligned.h b/include/asm-v850/unaligned.h index 65e38362142..e30b18653a9 100644 --- a/include/asm-v850/unaligned.h +++ b/include/asm-v850/unaligned.h @@ -82,19 +82,19 @@ extern int __bug_unaligned_x(void *ptr); }) -extern inline void __put_unaligned_2(__u32 __v, register __u8 *__p) +static inline void __put_unaligned_2(__u32 __v, register __u8 *__p) { *__p++ = __v; *__p++ = __v >> 8; } -extern inline void __put_unaligned_4(__u32 __v, register __u8 *__p) +static inline void __put_unaligned_4(__u32 __v, register __u8 *__p) { __put_unaligned_2(__v >> 16, __p + 2); __put_unaligned_2(__v, __p); } -extern inline void __put_unaligned_8(const unsigned long long __v, register __u8 *__p) +static inline void __put_unaligned_8(const unsigned long long __v, register __u8 *__p) { /* * tradeoff: 8 bytes of stack for all unaligned puts (2 -- cgit v1.2.3 From aa3a6f456f6ca162d3406a6e2c09a5c928833e4f Mon Sep 17 00:00:00 2001 From: Arthur Othieno Date: Mon, 7 Nov 2005 00:59:01 -0800 Subject: [PATCH] xtensa: struct semaphore.sleepers initialization No one may sleep on us until we've been down()'d. So on allocation, initialize `sleepers' to 0, just like everyone else does. Signed-off-by: Arthur Othieno Acked-by: Christian Zankel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-xtensa/semaphore.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/asm-xtensa/semaphore.h b/include/asm-xtensa/semaphore.h index 2a10e193b92..f10c3487cd4 100644 --- a/include/asm-xtensa/semaphore.h +++ b/include/asm-xtensa/semaphore.h @@ -38,6 +38,7 @@ struct semaphore { static inline void sema_init (struct semaphore *sem, int val) { atomic_set(&sem->count, val); + sem->sleepers = 0; init_waitqueue_head(&sem->wait); } -- cgit v1.2.3 From e1c3ad96f662bf1071a71feffadfe0f7604f14e2 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 7 Nov 2005 00:59:02 -0800 Subject: [PATCH] s390: signal delivery Always create all signal frames for pending signals before returning to userspace, not just a single one. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/kernel/entry.S | 4 ++-- arch/s390/kernel/entry64.S | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 9b30f4cf32c..27b07730b7b 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -288,7 +288,7 @@ sysc_sigpending: bo BASED(sysc_restart) tm __TI_flags+3(%r9),_TIF_SINGLE_STEP bo BASED(sysc_singlestep) - b BASED(sysc_leave) # out of here, do NOT recheck + b BASED(sysc_work_loop) # # _TIF_RESTART_SVC is set, set up registers and restart svc @@ -645,7 +645,7 @@ io_sigpending: l %r1,BASED(.Ldo_signal) basr %r14,%r1 # call do_signal stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts - b BASED(io_leave) # out of here, do NOT recheck + b BASED(io_work_loop) /* * External interrupt handler routine diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 7b9b4a2ba1d..4eb71ffcf48 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -283,7 +283,7 @@ sysc_sigpending: jo sysc_restart tm __TI_flags+7(%r9),_TIF_SINGLE_STEP jo sysc_singlestep - j sysc_leave # out of here, do NOT recheck + j sysc_work_loop # # _TIF_RESTART_SVC is set, set up registers and restart svc @@ -684,7 +684,7 @@ io_sigpending: slgr %r3,%r3 # clear *oldset brasl %r14,do_signal # call do_signal stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts - j sysc_leave # out of here, do NOT recheck + j io_work_loop /* * External interrupt handler routine -- cgit v1.2.3 From 1b44e98d7d0754bbcf0222baf179f5e2e3dbea7b Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Mon, 7 Nov 2005 00:59:02 -0800 Subject: [PATCH] s390: stop_hz_timer vs. xtime updates The calculation of the value return by next_timer_interrupt from jiffies to jiffies_64 is racy against xtime updates. We need to protect the calculation with read_seqbegin/read_seqretry. Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/kernel/time.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 9a1d95894f3..c36353e8c14 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -237,6 +237,8 @@ int sysctl_hz_timer = 1; */ static inline void stop_hz_timer(void) { + unsigned long flags; + unsigned long seq, next; __u64 timer, todval; if (sysctl_hz_timer != 0) @@ -257,7 +259,11 @@ static inline void stop_hz_timer(void) * This cpu is going really idle. Set up the clock comparator * for the next event. */ - timer = (__u64) (next_timer_interrupt() - jiffies) + jiffies_64; + next = next_timer_interrupt(); + do { + seq = read_seqbegin_irqsave(&xtime_lock, flags); + timer = (__u64)(next - jiffies) + jiffies_64; + } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); todval = -1ULL; /* Be careful about overflows. */ if (timer < (-1ULL / CLK_TICKS_PER_JIFFY)) { -- cgit v1.2.3 From 373c491f6d15f29ab2f87d4a60f90cb0b770aaf6 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Mon, 7 Nov 2005 00:59:03 -0800 Subject: [PATCH] s390: documentation update Fix typos and add a section about cpus in the driver-model documentation. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/s390/driver-model.txt | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/Documentation/s390/driver-model.txt b/Documentation/s390/driver-model.txt index 19461958e2b..df09758bf3f 100644 --- a/Documentation/s390/driver-model.txt +++ b/Documentation/s390/driver-model.txt @@ -8,11 +8,10 @@ All devices which can be addressed by means of ccws are called 'CCW devices' - even if they aren't actually driven by ccws. All ccw devices are accessed via a subchannel, this is reflected in the -structures under root/: +structures under devices/: -root/ - - sys - - legacy +devices/ + - system/ - css0/ - 0.0.0000/0.0.0815/ - 0.0.0001/0.0.4711/ @@ -36,7 +35,7 @@ availability: Can be 'good' or 'boxed'; 'no path' or 'no device' for online: An interface to set the device online and offline. In the special case of the device being disconnected (see the - notify function under 1.2), piping 0 to online will focibly delete + notify function under 1.2), piping 0 to online will forcibly delete the device. The device drivers can add entries to export per-device data and interfaces. @@ -222,7 +221,7 @@ and are called 'chp0.'. They have no driver and do not belong to any bus. Please note, that unlike /proc/chpids in 2.4, the channel path objects reflect only the logical state and not the physical state, since we cannot track the latter consistently due to lacking machine support (we don't need to be aware -of anyway). +of it anyway). status - Can be 'online' or 'offline'. Piping 'on' or 'off' sets the chpid logically online/offline. @@ -235,12 +234,16 @@ status - Can be 'online' or 'offline'. 3. System devices ----------------- -Note: cpus may yet be added here. - 3.1 xpram --------- -xpram shows up under sys/ as 'xpram'. +xpram shows up under devices/system/ as 'xpram'. + +3.2 cpus +-------- + +For each cpu, a directory is created under devices/system/cpu/. Each cpu has an +attribute 'online' which can be 0 or 1. 4. Other devices -- cgit v1.2.3 From 9b4554aa21270f5b6fa19a9dd2285f16e11f15f1 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 7 Nov 2005 00:59:04 -0800 Subject: [PATCH] s390: memory query wait psw Don't switch back to 24 bit addressing mode when waiting for an external interrupt and set the correct bit in wait PSW (external mask instead of I/O mask). Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/kernel/head.S | 3 +-- arch/s390/kernel/head64.S | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index 039354d7234..4ca02933211 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S @@ -572,8 +572,7 @@ startup:basr %r13,0 # get base .Lcr: .long 0x00 # place holder for cr0 .Lwaitsclp: - .long 0x020A0000 - .long .Lsclph + .long 0x010a0000,0x80000000 + .Lsclph .Lrcp: .int 0x00120001 # Read SCP forced code .Lrcp2: diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index 193aafa72f5..d9be8f96f2e 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -530,7 +530,7 @@ startup:basr %r13,0 # get base be .Lfchunk-.LPG1(%r13) # leave chi %r1,2 be .Lservicecall-.LPG1(%r13) - lpsw .Lwaitsclp-.LPG1(%r13) + lpswe .Lwaitsclp-.LPG1(%r13) .Lsclph: lh %r1,.Lsccbr-PARMAREA(%r4) chi %r1,0x10 # 0x0010 is the sucess code @@ -567,8 +567,7 @@ startup:basr %r13,0 # get base .Lcr: .quad 0x00 # place holder for cr0 .Lwaitsclp: - .long 0x020A0000 - .quad .Lsclph + .quad 0x0102000180000000,.Lsclph .Lrcp: .int 0x00120001 # Read SCP forced code .Lrcp2: -- cgit v1.2.3 From a0016408f2428225f1532cbf63ca1c7008e1cc93 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Mon, 7 Nov 2005 00:59:05 -0800 Subject: [PATCH] s390: ccwgroup online attribute Make the interface for setting ccw group devices on-/offline consistent with that for ccw devices: Check if the device driver provided a set_{on,off}line function and just set the device on-/offline if not. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/cio/ccwgroup.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index dbb3eb0e330..e7bd7f37f08 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/ccwgroup.c * bus driver for ccwgroup - * $Revision: 1.29 $ + * $Revision: 1.32 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -274,7 +274,7 @@ ccwgroup_set_online(struct ccwgroup_device *gdev) goto out; } gdrv = to_ccwgroupdrv (gdev->dev.driver); - if ((ret = gdrv->set_online(gdev))) + if ((ret = gdrv->set_online ? gdrv->set_online(gdev) : 0)) goto out; gdev->state = CCWGROUP_ONLINE; @@ -300,7 +300,7 @@ ccwgroup_set_offline(struct ccwgroup_device *gdev) goto out; } gdrv = to_ccwgroupdrv (gdev->dev.driver); - if ((ret = gdrv->set_offline(gdev))) + if ((ret = gdrv->set_offline ? gdrv->set_offline(gdev) : 0)) goto out; gdev->state = CCWGROUP_OFFLINE; -- cgit v1.2.3 From d4b68996785326a67e9842219ab69984243ec658 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Mon, 7 Nov 2005 00:59:06 -0800 Subject: [PATCH] s390: remove pagex support Remove pagex pseudo page fault code. It does not work together with the system call speedup that makes the complete system call path enabled for interrupts. To make pagex and the syscall speedup code work together we would have to add code to the program check handler to do a critical section cleanup like the asynchronous interrupt code. This would make program checks slower. Not what we want. Newer versions of z/VM have the improved pfault pseudo page fault interface. This replaces the old pagex interface and does not have the problem. So its better to just rip out the pagex code. Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/kernel/traps.c | 29 ++---------- arch/s390/mm/fault.c | 113 +---------------------------------------------- 2 files changed, 5 insertions(+), 137 deletions(-) diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 6b8703ec2ae..c5bd36fae56 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -57,7 +57,6 @@ int sysctl_userprocess_debug = 0; extern pgm_check_handler_t do_protection_exception; extern pgm_check_handler_t do_dat_exception; -extern pgm_check_handler_t do_pseudo_page_fault; #ifdef CONFIG_PFAULT extern int pfault_init(void); extern void pfault_fini(void); @@ -676,20 +675,6 @@ asmlinkage void kernel_stack_overflow(struct pt_regs * regs) panic("Corrupt kernel stack, can't continue."); } -#ifndef CONFIG_ARCH_S390X -static int -pagex_reboot_event(struct notifier_block *this, unsigned long event, void *ptr) -{ - if (MACHINE_IS_VM) - cpcmd("SET PAGEX OFF", NULL, 0, NULL); - return NOTIFY_DONE; -} - -static struct notifier_block pagex_reboot_notifier = { - .notifier_call = &pagex_reboot_event, -}; -#endif - /* init is done in lowcore.S and head.S */ void __init trap_init(void) @@ -717,9 +702,7 @@ void __init trap_init(void) pgm_check_table[0x11] = &do_dat_exception; pgm_check_table[0x12] = &translation_exception; pgm_check_table[0x13] = &special_op_exception; -#ifndef CONFIG_ARCH_S390X - pgm_check_table[0x14] = &do_pseudo_page_fault; -#else /* CONFIG_ARCH_S390X */ +#ifdef CONFIG_ARCH_S390X pgm_check_table[0x38] = &do_dat_exception; pgm_check_table[0x39] = &do_dat_exception; pgm_check_table[0x3A] = &do_dat_exception; @@ -731,12 +714,10 @@ void __init trap_init(void) pgm_check_table[0x40] = &do_monitor_call; if (MACHINE_IS_VM) { +#ifdef CONFIG_PFAULT /* - * First try to get pfault pseudo page faults going. - * If this isn't available turn on pagex page faults. + * Try to get pfault pseudo page faults going. */ -#ifdef CONFIG_PFAULT - /* request the 0x2603 external interrupt */ if (register_early_external_interrupt(0x2603, pfault_interrupt, &ext_int_pfault) != 0) panic("Couldn't request external interrupt 0x2603"); @@ -747,10 +728,6 @@ void __init trap_init(void) /* Tough luck, no pfault. */ unregister_early_external_interrupt(0x2603, pfault_interrupt, &ext_int_pfault); -#endif -#ifndef CONFIG_ARCH_S390X - register_reboot_notifier(&pagex_reboot_notifier); - cpcmd("SET PAGEX ON", NULL, 0, NULL); #endif } } diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 856a971759b..64e32da7775 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -352,115 +352,6 @@ void do_dat_exception(struct pt_regs *regs, unsigned long error_code) do_exception(regs, error_code & 0xff, 0); } -#ifndef CONFIG_ARCH_S390X - -typedef struct _pseudo_wait_t { - struct _pseudo_wait_t *next; - wait_queue_head_t queue; - unsigned long address; - int resolved; -} pseudo_wait_t; - -static pseudo_wait_t *pseudo_lock_queue = NULL; -static spinlock_t pseudo_wait_spinlock; /* spinlock to protect lock queue */ - -/* - * This routine handles 'pagex' pseudo page faults. - */ -asmlinkage void -do_pseudo_page_fault(struct pt_regs *regs, unsigned long error_code) -{ - pseudo_wait_t wait_struct; - pseudo_wait_t *ptr, *last, *next; - unsigned long address; - - /* - * get the failing address - * more specific the segment and page table portion of - * the address - */ - address = S390_lowcore.trans_exc_code & 0xfffff000; - - if (address & 0x80000000) { - /* high bit set -> a page has been swapped in by VM */ - address &= 0x7fffffff; - spin_lock(&pseudo_wait_spinlock); - last = NULL; - ptr = pseudo_lock_queue; - while (ptr != NULL) { - next = ptr->next; - if (address == ptr->address) { - /* - * This is one of the processes waiting - * for the page. Unchain from the queue. - * There can be more than one process - * waiting for the same page. VM presents - * an initial and a completion interrupt for - * every process that tries to access a - * page swapped out by VM. - */ - if (last == NULL) - pseudo_lock_queue = next; - else - last->next = next; - /* now wake up the process */ - ptr->resolved = 1; - wake_up(&ptr->queue); - } else - last = ptr; - ptr = next; - } - spin_unlock(&pseudo_wait_spinlock); - } else { - /* Pseudo page faults in kernel mode is a bad idea */ - if (!(regs->psw.mask & PSW_MASK_PSTATE)) { - /* - * VM presents pseudo page faults if the interrupted - * state was not disabled for interrupts. So we can - * get pseudo page fault interrupts while running - * in kernel mode. We simply access the page here - * while we are running disabled. VM will then swap - * in the page synchronously. - */ - if (check_user_space(regs, error_code) == 0) - /* dereference a virtual kernel address */ - __asm__ __volatile__ ( - " ic 0,0(%0)" - : : "a" (address) : "0"); - else - /* dereference a virtual user address */ - __asm__ __volatile__ ( - " la 2,0(%0)\n" - " sacf 512\n" - " ic 2,0(2)\n" - "0:sacf 0\n" - ".section __ex_table,\"a\"\n" - " .align 4\n" - " .long 0b,0b\n" - ".previous" - : : "a" (address) : "2" ); - - return; - } - /* initialize and add element to pseudo_lock_queue */ - init_waitqueue_head (&wait_struct.queue); - wait_struct.address = address; - wait_struct.resolved = 0; - spin_lock(&pseudo_wait_spinlock); - wait_struct.next = pseudo_lock_queue; - pseudo_lock_queue = &wait_struct; - spin_unlock(&pseudo_wait_spinlock); - /* - * The instruction that caused the program check will - * be repeated. Don't signal single step via SIGTRAP. - */ - clear_tsk_thread_flag(current, TIF_SINGLE_STEP); - /* go to sleep */ - wait_event(wait_struct.queue, wait_struct.resolved); - } -} -#endif /* CONFIG_ARCH_S390X */ - #ifdef CONFIG_PFAULT /* * 'pfault' pseudo page faults routines. @@ -508,7 +399,7 @@ int pfault_init(void) " .quad 0b,1b\n" #endif /* CONFIG_ARCH_S390X */ ".previous" - : "=d" (rc) : "a" (&refbk) : "cc" ); + : "=d" (rc) : "a" (&refbk), "m" (refbk) : "cc" ); __ctl_set_bit(0, 9); return rc; } @@ -532,7 +423,7 @@ void pfault_fini(void) " .quad 0b,0b\n" #endif /* CONFIG_ARCH_S390X */ ".previous" - : : "a" (&refbk) : "cc" ); + : : "a" (&refbk), "m" (refbk) : "cc" ); } asmlinkage void -- cgit v1.2.3 From 187dfc67b461058bbb84a923a17871ed54e10f30 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Mon, 7 Nov 2005 00:59:07 -0800 Subject: [PATCH] s390: test_bit return value The test_bit function returns a non-boolean value, it returns 0,1,2,4,... instead of only 0 or 1. This causes wrongs results in the mincore system call. Check against 0 to get a proper boolean value. Signed-off-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-s390/bitops.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h index 8651524217f..b07c578b22e 100644 --- a/include/asm-s390/bitops.h +++ b/include/asm-s390/bitops.h @@ -518,8 +518,8 @@ static inline int __test_bit(unsigned long nr, const volatile unsigned long *ptr static inline int __constant_test_bit(unsigned long nr, const volatile unsigned long *addr) { - return (((volatile char *) addr) - [(nr^(__BITOPS_WORDSIZE-8))>>3] & (1<<(nr&7))); + return ((((volatile char *) addr) + [(nr^(__BITOPS_WORDSIZE-8))>>3] & (1<<(nr&7)))) != 0; } #define test_bit(nr,addr) \ -- cgit v1.2.3 From 86b368a5804d05a6508791f10ebabf7b779eb845 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Mon, 7 Nov 2005 00:59:08 -0800 Subject: [PATCH] s390: dasd diag inline assembly Future versions of gcc may remove initialization code for control blocks used by the diag250 inline assembly due to incompletely specified constraints. This may lead to erratic behavior. Fix the diag250 inline assembly constraints. Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/dasd_diag.c | 16 ++++++++-------- drivers/s390/block/dasd_diag.h | 10 +++++----- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 7478423b53b..9aa608f528e 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -6,7 +6,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.49 $ + * $Revision: 1.50 $ */ #include @@ -67,9 +67,9 @@ static const u8 DASD_DIAG_CMS1[] = { 0xc3, 0xd4, 0xe2, 0xf1 };/* EBCDIC CMS1 */ static __inline__ int dia250(void *iob, int cmd) { - typedef struct { - char _[max(sizeof (struct dasd_diag_init_io), - sizeof (struct dasd_diag_rw_io))]; + typedef union { + struct dasd_diag_init_io init_io; + struct dasd_diag_rw_io rw_io; } addr_type; int rc; @@ -190,7 +190,7 @@ dasd_start_diag(struct dasd_ccw_req * cqr) private->iob.flags = DASD_DIAG_RWFLAG_ASYNC; private->iob.block_count = dreq->block_count; private->iob.interrupt_params = (addr_t) cqr; - private->iob.bio_list = __pa(dreq->bio); + private->iob.bio_list = dreq->bio; private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT; cqr->startclk = get_clock(); @@ -394,14 +394,14 @@ dasd_diag_check_device(struct dasd_device *device) memset(&bio, 0, sizeof (struct dasd_diag_bio)); bio.type = MDSK_READ_REQ; bio.block_number = private->pt_block + 1; - bio.buffer = __pa(label); + bio.buffer = label; memset(&private->iob, 0, sizeof (struct dasd_diag_rw_io)); private->iob.dev_nr = rdc_data->dev_nr; private->iob.key = 0; private->iob.flags = 0; /* do synchronous io */ private->iob.block_count = 1; private->iob.interrupt_params = 0; - private->iob.bio_list = __pa(&bio); + private->iob.bio_list = &bio; private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT; rc = dia250(&private->iob, RW_BIO); if (rc == 0 || rc == 3) @@ -529,7 +529,7 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req) memset(dbio, 0, sizeof (struct dasd_diag_bio)); dbio->type = rw_cmd; dbio->block_number = recid + 1; - dbio->buffer = __pa(dst); + dbio->buffer = dst; dbio++; dst += blksize; recid++; diff --git a/drivers/s390/block/dasd_diag.h b/drivers/s390/block/dasd_diag.h index b26eb28df4b..df31484d73a 100644 --- a/drivers/s390/block/dasd_diag.h +++ b/drivers/s390/block/dasd_diag.h @@ -6,7 +6,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.7 $ + * $Revision: 1.8 $ */ #define MDSK_WRITE_REQ 0x01 @@ -78,7 +78,7 @@ struct dasd_diag_bio { u8 spare1[2]; u32 alet; blocknum_t block_number; - u64 buffer; + void *buffer; } __attribute__ ((packed, aligned(8))); struct dasd_diag_init_io { @@ -104,7 +104,7 @@ struct dasd_diag_rw_io { u32 alet; u8 spare3[4]; u64 interrupt_params; - u64 bio_list; + struct dasd_diag_bio *bio_list; u8 spare4[8]; } __attribute__ ((packed, aligned(8))); #else /* CONFIG_ARCH_S390X */ @@ -119,7 +119,7 @@ struct dasd_diag_bio { u16 spare1; blocknum_t block_number; u32 alet; - u32 buffer; + void *buffer; } __attribute__ ((packed, aligned(8))); struct dasd_diag_init_io { @@ -142,7 +142,7 @@ struct dasd_diag_rw_io { u8 spare2[2]; u32 block_count; u32 alet; - u32 bio_list; + struct dasd_diag_bio *bio_list; u32 interrupt_params; u8 spare3[20]; } __attribute__ ((packed, aligned(8))); -- cgit v1.2.3 From 1e0291bade7678efe4d3ab70ed14bd7bd216bcef Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Mon, 7 Nov 2005 00:59:08 -0800 Subject: [PATCH] s390: dasd diag with block sizes > 512 Access to FBA disks via DIAG fails for block sizes > 512 byte. The device analysis code of the DIAG discipline does not properly initialize the DIAG250 device environment after completion of the analysis. This results in VM only serving 512 bytes per block I/O request whereas Linux expects larger block sizes. Add proper device environment setup to end of analysis code. Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/dasd_diag.c | 50 +++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 9aa608f528e..ab8754e566b 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c @@ -6,7 +6,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.50 $ + * $Revision: 1.51 $ */ #include @@ -404,37 +404,47 @@ dasd_diag_check_device(struct dasd_device *device) private->iob.bio_list = &bio; private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT; rc = dia250(&private->iob, RW_BIO); - if (rc == 0 || rc == 3) - break; + if (rc == 3) { + DEV_MESSAGE(KERN_WARNING, device, "%s", + "DIAG call failed"); + rc = -EOPNOTSUPP; + goto out; + } mdsk_term_io(device); + if (rc == 0) + break; } - if (rc == 3) { - DEV_MESSAGE(KERN_WARNING, device, "%s", "DIAG call failed"); - rc = -EOPNOTSUPP; - } else if (rc != 0) { + if (bsize > PAGE_SIZE) { DEV_MESSAGE(KERN_WARNING, device, "device access failed " "(rc=%d)", rc); rc = -EIO; + goto out; + } + /* check for label block */ + if (memcmp(label->label_id, DASD_DIAG_CMS1, + sizeof(DASD_DIAG_CMS1)) == 0) { + /* get formatted blocksize from label block */ + bsize = (unsigned int) label->block_size; + device->blocks = (unsigned long) label->block_count; + } else + device->blocks = end_block; + device->bp_block = bsize; + device->s2b_shift = 0; /* bits to shift 512 to get a block */ + for (sb = 512; sb < bsize; sb = sb << 1) + device->s2b_shift++; + rc = mdsk_init_io(device, device->bp_block, 0, NULL); + if (rc) { + DEV_MESSAGE(KERN_WARNING, device, "DIAG initialization " + "failed (rc=%d)", rc); + rc = -EIO; } else { - if (memcmp(label->label_id, DASD_DIAG_CMS1, - sizeof(DASD_DIAG_CMS1)) == 0) { - /* get formatted blocksize from label block */ - bsize = (unsigned int) label->block_size; - device->blocks = (unsigned long) label->block_count; - } else - device->blocks = end_block; - device->bp_block = bsize; - device->s2b_shift = 0; /* bits to shift 512 to get a block */ - for (sb = 512; sb < bsize; sb = sb << 1) - device->s2b_shift++; - DEV_MESSAGE(KERN_INFO, device, "(%ld B/blk): %ldkB", (unsigned long) device->bp_block, (unsigned long) (device->blocks << device->s2b_shift) >> 1); - rc = 0; } +out: free_page((long) label); return rc; } -- cgit v1.2.3 From 4cd5b9f6df96494b8667deea71b61b66f783cca3 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Mon, 7 Nov 2005 00:59:09 -0800 Subject: [PATCH] s390: cleanup of include/asm-s390/vtoc.h Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/partitions/ibm.c | 15 +- include/asm-s390/vtoc.h | 505 +++++++++++++++--------------------------------- 2 files changed, 164 insertions(+), 356 deletions(-) diff --git a/fs/partitions/ibm.c b/fs/partitions/ibm.c index d59dcbf2bd4..6327bcb2d73 100644 --- a/fs/partitions/ibm.c +++ b/fs/partitions/ibm.c @@ -29,7 +29,7 @@ * cyl-cyl-head-head structure */ static inline int -cchh2blk (cchh_t *ptr, struct hd_geometry *geo) { +cchh2blk (struct vtoc_cchh *ptr, struct hd_geometry *geo) { return ptr->cc * geo->heads * geo->sectors + ptr->hh * geo->sectors; } @@ -40,7 +40,7 @@ cchh2blk (cchh_t *ptr, struct hd_geometry *geo) { * cyl-cyl-head-head-block structure */ static inline int -cchhb2blk (cchhb_t *ptr, struct hd_geometry *geo) { +cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) { return ptr->cc * geo->heads * geo->sectors + ptr->hh * geo->sectors + ptr->b; @@ -56,7 +56,7 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) struct hd_geometry *geo; char type[5] = {0,}; char name[7] = {0,}; - volume_label_t *vlabel; + struct vtoc_volume_label *vlabel; unsigned char *data; Sector sect; @@ -64,7 +64,8 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) goto out_noinfo; if ((geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL)) == NULL) goto out_nogeo; - if ((vlabel = kmalloc(sizeof(volume_label_t), GFP_KERNEL)) == NULL) + if ((vlabel = kmalloc(sizeof(struct vtoc_volume_label), + GFP_KERNEL)) == NULL) goto out_novlab; if (ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)info) != 0 || @@ -86,7 +87,7 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) strncpy(name, data + 8, 6); else strncpy(name, data + 4, 6); - memcpy (vlabel, data, sizeof(volume_label_t)); + memcpy (vlabel, data, sizeof(struct vtoc_volume_label)); put_dev_sector(sect); EBCASC(type, 4); @@ -129,9 +130,9 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) counter = 0; while ((data = read_dev_sector(bdev, blk*(blocksize/512), §)) != NULL) { - format1_label_t f1; + struct vtoc_format1_label f1; - memcpy(&f1, data, sizeof(format1_label_t)); + memcpy(&f1, data, sizeof(struct vtoc_format1_label)); put_dev_sector(sect); /* skip FMT4 / FMT5 / FMT7 labels */ diff --git a/include/asm-s390/vtoc.h b/include/asm-s390/vtoc.h index a14e34e80b8..41d369f38b0 100644 --- a/include/asm-s390/vtoc.h +++ b/include/asm-s390/vtoc.h @@ -1,372 +1,179 @@ -#ifndef __KERNEL__ -#include -#include -#include -#include -#include -#include -#include -#include +/* + * include/asm-s390/vtoc.h + * + * This file contains volume label definitions for DASD devices. + * + * (C) Copyright IBM Corp. 2005 + * + * Author(s): Volker Sameske + * + */ + +#ifndef _ASM_S390_VTOC_H +#define _ASM_S390_VTOC_H -#include -#include - -#include #include -#include -#include -#endif - - -#define LINE_LENGTH 80 -#define VTOC_START_CC 0x0 -#define VTOC_START_HH 0x1 -#define FIRST_USABLE_CYL 1 -#define FIRST_USABLE_TRK 2 - -#define DASD_3380_TYPE 13148 -#define DASD_3390_TYPE 13200 -#define DASD_9345_TYPE 37701 - -#define DASD_3380_VALUE 0xbb60 -#define DASD_3390_VALUE 0xe5a2 -#define DASD_9345_VALUE 0xbc98 - -#define VOLSER_LENGTH 6 -#define BIG_DISK_SIZE 0x10000 - -#define VTOC_ERROR "VTOC error:" - -typedef struct ttr +struct vtoc_ttr { - __u16 tt; - __u8 r; -} __attribute__ ((packed)) ttr_t; + __u16 tt; + __u8 r; +} __attribute__ ((packed)); -typedef struct cchhb +struct vtoc_cchhb { - __u16 cc; - __u16 hh; - __u8 b; -} __attribute__ ((packed)) cchhb_t; + __u16 cc; + __u16 hh; + __u8 b; +} __attribute__ ((packed)); -typedef struct cchh +struct vtoc_cchh { - __u16 cc; - __u16 hh; -} __attribute__ ((packed)) cchh_t; + __u16 cc; + __u16 hh; +} __attribute__ ((packed)); -typedef struct labeldate +struct vtoc_labeldate { - __u8 year; - __u16 day; -} __attribute__ ((packed)) labeldate_t; + __u8 year; + __u16 day; +} __attribute__ ((packed)); - -typedef struct volume_label +struct vtoc_volume_label { - char volkey[4]; /* volume key = volume label */ - char vollbl[4]; /* volume label */ - char volid[6]; /* volume identifier */ - __u8 security; /* security byte */ - cchhb_t vtoc; /* VTOC address */ - char res1[5]; /* reserved */ - char cisize[4]; /* CI-size for FBA,... */ - /* ...blanks for CKD */ - char blkperci[4]; /* no of blocks per CI (FBA), blanks for CKD */ - char labperci[4]; /* no of labels per CI (FBA), blanks for CKD */ - char res2[4]; /* reserved */ - char lvtoc[14]; /* owner code for LVTOC */ - char res3[29]; /* reserved */ -} __attribute__ ((packed)) volume_label_t; - - -typedef struct extent + char volkey[4]; /* volume key = volume label */ + char vollbl[4]; /* volume label */ + char volid[6]; /* volume identifier */ + __u8 security; /* security byte */ + struct vtoc_cchhb vtoc; /* VTOC address */ + char res1[5]; /* reserved */ + char cisize[4]; /* CI-size for FBA,... */ + /* ...blanks for CKD */ + char blkperci[4]; /* no of blocks per CI (FBA), blanks for CKD */ + char labperci[4]; /* no of labels per CI (FBA), blanks for CKD */ + char res2[4]; /* reserved */ + char lvtoc[14]; /* owner code for LVTOC */ + char res3[29]; /* reserved */ +} __attribute__ ((packed)); + +struct vtoc_extent { - __u8 typeind; /* extent type indicator */ - __u8 seqno; /* extent sequence number */ - cchh_t llimit; /* starting point of this extent */ - cchh_t ulimit; /* ending point of this extent */ -} __attribute__ ((packed)) extent_t; - + __u8 typeind; /* extent type indicator */ + __u8 seqno; /* extent sequence number */ + struct vtoc_cchh llimit; /* starting point of this extent */ + struct vtoc_cchh ulimit; /* ending point of this extent */ +} __attribute__ ((packed)); -typedef struct dev_const +struct vtoc_dev_const { - __u16 DS4DSCYL; /* number of logical cyls */ - __u16 DS4DSTRK; /* number of tracks in a logical cylinder */ - __u16 DS4DEVTK; /* device track length */ - __u8 DS4DEVI; /* non-last keyed record overhead */ - __u8 DS4DEVL; /* last keyed record overhead */ - __u8 DS4DEVK; /* non-keyed record overhead differential */ - __u8 DS4DEVFG; /* flag byte */ - __u16 DS4DEVTL; /* device tolerance */ - __u8 DS4DEVDT; /* number of DSCB's per track */ - __u8 DS4DEVDB; /* number of directory blocks per track */ -} __attribute__ ((packed)) dev_const_t; - - -typedef struct format1_label + __u16 DS4DSCYL; /* number of logical cyls */ + __u16 DS4DSTRK; /* number of tracks in a logical cylinder */ + __u16 DS4DEVTK; /* device track length */ + __u8 DS4DEVI; /* non-last keyed record overhead */ + __u8 DS4DEVL; /* last keyed record overhead */ + __u8 DS4DEVK; /* non-keyed record overhead differential */ + __u8 DS4DEVFG; /* flag byte */ + __u16 DS4DEVTL; /* device tolerance */ + __u8 DS4DEVDT; /* number of DSCB's per track */ + __u8 DS4DEVDB; /* number of directory blocks per track */ +} __attribute__ ((packed)); + +struct vtoc_format1_label { - char DS1DSNAM[44]; /* data set name */ - __u8 DS1FMTID; /* format identifier */ - char DS1DSSN[6]; /* data set serial number */ - __u16 DS1VOLSQ; /* volume sequence number */ - labeldate_t DS1CREDT; /* creation date: ydd */ - labeldate_t DS1EXPDT; /* expiration date */ - __u8 DS1NOEPV; /* number of extents on volume */ - __u8 DS1NOBDB; /* no. of bytes used in last direction blk */ - __u8 DS1FLAG1; /* flag 1 */ - char DS1SYSCD[13]; /* system code */ - labeldate_t DS1REFD; /* date last referenced */ - __u8 DS1SMSFG; /* system managed storage indicators */ - __u8 DS1SCXTF; /* sec. space extension flag byte */ - __u16 DS1SCXTV; /* secondary space extension value */ - __u8 DS1DSRG1; /* data set organisation byte 1 */ - __u8 DS1DSRG2; /* data set organisation byte 2 */ - __u8 DS1RECFM; /* record format */ - __u8 DS1OPTCD; /* option code */ - __u16 DS1BLKL; /* block length */ - __u16 DS1LRECL; /* record length */ - __u8 DS1KEYL; /* key length */ - __u16 DS1RKP; /* relative key position */ - __u8 DS1DSIND; /* data set indicators */ - __u8 DS1SCAL1; /* secondary allocation flag byte */ - char DS1SCAL3[3]; /* secondary allocation quantity */ - ttr_t DS1LSTAR; /* last used track and block on track */ - __u16 DS1TRBAL; /* space remaining on last used track */ - __u16 res1; /* reserved */ - extent_t DS1EXT1; /* first extent description */ - extent_t DS1EXT2; /* second extent description */ - extent_t DS1EXT3; /* third extent description */ - cchhb_t DS1PTRDS; /* possible pointer to f2 or f3 DSCB */ -} __attribute__ ((packed)) format1_label_t; - - -typedef struct format4_label + char DS1DSNAM[44]; /* data set name */ + __u8 DS1FMTID; /* format identifier */ + char DS1DSSN[6]; /* data set serial number */ + __u16 DS1VOLSQ; /* volume sequence number */ + struct vtoc_labeldate DS1CREDT; /* creation date: ydd */ + struct vtoc_labeldate DS1EXPDT; /* expiration date */ + __u8 DS1NOEPV; /* number of extents on volume */ + __u8 DS1NOBDB; /* no. of bytes used in last direction blk */ + __u8 DS1FLAG1; /* flag 1 */ + char DS1SYSCD[13]; /* system code */ + struct vtoc_labeldate DS1REFD; /* date last referenced */ + __u8 DS1SMSFG; /* system managed storage indicators */ + __u8 DS1SCXTF; /* sec. space extension flag byte */ + __u16 DS1SCXTV; /* secondary space extension value */ + __u8 DS1DSRG1; /* data set organisation byte 1 */ + __u8 DS1DSRG2; /* data set organisation byte 2 */ + __u8 DS1RECFM; /* record format */ + __u8 DS1OPTCD; /* option code */ + __u16 DS1BLKL; /* block length */ + __u16 DS1LRECL; /* record length */ + __u8 DS1KEYL; /* key length */ + __u16 DS1RKP; /* relative key position */ + __u8 DS1DSIND; /* data set indicators */ + __u8 DS1SCAL1; /* secondary allocation flag byte */ + char DS1SCAL3[3]; /* secondary allocation quantity */ + struct vtoc_ttr DS1LSTAR; /* last used track and block on track */ + __u16 DS1TRBAL; /* space remaining on last used track */ + __u16 res1; /* reserved */ + struct vtoc_extent DS1EXT1; /* first extent description */ + struct vtoc_extent DS1EXT2; /* second extent description */ + struct vtoc_extent DS1EXT3; /* third extent description */ + struct vtoc_cchhb DS1PTRDS; /* possible pointer to f2 or f3 DSCB */ +} __attribute__ ((packed)); + +struct vtoc_format4_label { - char DS4KEYCD[44]; /* key code for VTOC labels: 44 times 0x04 */ - __u8 DS4IDFMT; /* format identifier */ - cchhb_t DS4HPCHR; /* highest address of a format 1 DSCB */ - __u16 DS4DSREC; /* number of available DSCB's */ - cchh_t DS4HCCHH; /* CCHH of next available alternate track */ - __u16 DS4NOATK; /* number of remaining alternate tracks */ - __u8 DS4VTOCI; /* VTOC indicators */ - __u8 DS4NOEXT; /* number of extents in VTOC */ - __u8 DS4SMSFG; /* system managed storage indicators */ - __u8 DS4DEVAC; /* number of alternate cylinders. - Subtract from first two bytes of - DS4DEVSZ to get number of usable - cylinders. can be zero. valid - only if DS4DEVAV on. */ - dev_const_t DS4DEVCT; /* device constants */ - char DS4AMTIM[8]; /* VSAM time stamp */ - char DS4AMCAT[3]; /* VSAM catalog indicator */ - char DS4R2TIM[8]; /* VSAM volume/catalog match time stamp */ - char res1[5]; /* reserved */ - char DS4F6PTR[5]; /* pointer to first format 6 DSCB */ - extent_t DS4VTOCE; /* VTOC extent description */ - char res2[10]; /* reserved */ - __u8 DS4EFLVL; /* extended free-space management level */ - cchhb_t DS4EFPTR; /* pointer to extended free-space info */ - char res3[9]; /* reserved */ -} __attribute__ ((packed)) format4_label_t; - - -typedef struct ds5ext + char DS4KEYCD[44]; /* key code for VTOC labels: 44 times 0x04 */ + __u8 DS4IDFMT; /* format identifier */ + struct vtoc_cchhb DS4HPCHR; /* highest address of a format 1 DSCB */ + __u16 DS4DSREC; /* number of available DSCB's */ + struct vtoc_cchh DS4HCCHH; /* CCHH of next available alternate track */ + __u16 DS4NOATK; /* number of remaining alternate tracks */ + __u8 DS4VTOCI; /* VTOC indicators */ + __u8 DS4NOEXT; /* number of extents in VTOC */ + __u8 DS4SMSFG; /* system managed storage indicators */ + __u8 DS4DEVAC; /* number of alternate cylinders. + * Subtract from first two bytes of + * DS4DEVSZ to get number of usable + * cylinders. can be zero. valid + * only if DS4DEVAV on. */ + struct vtoc_dev_const DS4DEVCT; /* device constants */ + char DS4AMTIM[8]; /* VSAM time stamp */ + char DS4AMCAT[3]; /* VSAM catalog indicator */ + char DS4R2TIM[8]; /* VSAM volume/catalog match time stamp */ + char res1[5]; /* reserved */ + char DS4F6PTR[5]; /* pointer to first format 6 DSCB */ + struct vtoc_extent DS4VTOCE; /* VTOC extent description */ + char res2[10]; /* reserved */ + __u8 DS4EFLVL; /* extended free-space management level */ + struct vtoc_cchhb DS4EFPTR; /* pointer to extended free-space info */ + char res3[9]; /* reserved */ +} __attribute__ ((packed)); + +struct vtoc_ds5ext { - __u16 t; /* RTA of the first track of free extent */ - __u16 fc; /* number of whole cylinders in free ext. */ - __u8 ft; /* number of remaining free tracks */ -} __attribute__ ((packed)) ds5ext_t; - + __u16 t; /* RTA of the first track of free extent */ + __u16 fc; /* number of whole cylinders in free ext. */ + __u8 ft; /* number of remaining free tracks */ +} __attribute__ ((packed)); -typedef struct format5_label +struct vtoc_format5_label { - char DS5KEYID[4]; /* key identifier */ - ds5ext_t DS5AVEXT; /* first available (free-space) extent. */ - ds5ext_t DS5EXTAV[7]; /* seven available extents */ - __u8 DS5FMTID; /* format identifier */ - ds5ext_t DS5MAVET[18]; /* eighteen available extents */ - cchhb_t DS5PTRDS; /* pointer to next format5 DSCB */ -} __attribute__ ((packed)) format5_label_t; - - -typedef struct ds7ext + char DS5KEYID[4]; /* key identifier */ + struct vtoc_ds5ext DS5AVEXT; /* first available (free-space) extent. */ + struct vtoc_ds5ext DS5EXTAV[7]; /* seven available extents */ + __u8 DS5FMTID; /* format identifier */ + struct vtoc_ds5ext DS5MAVET[18]; /* eighteen available extents */ + struct vtoc_cchhb DS5PTRDS; /* pointer to next format5 DSCB */ +} __attribute__ ((packed)); + +struct vtoc_ds7ext { - __u32 a; /* starting RTA value */ - __u32 b; /* ending RTA value + 1 */ -} __attribute__ ((packed)) ds7ext_t; + __u32 a; /* starting RTA value */ + __u32 b; /* ending RTA value + 1 */ +} __attribute__ ((packed)); - -typedef struct format7_label +struct vtoc_format7_label { - char DS7KEYID[4]; /* key identifier */ - ds7ext_t DS7EXTNT[5]; /* space for 5 extent descriptions */ - __u8 DS7FMTID; /* format identifier */ - ds7ext_t DS7ADEXT[11]; /* space for 11 extent descriptions */ - char res1[2]; /* reserved */ - cchhb_t DS7PTRDS; /* pointer to next FMT7 DSCB */ -} __attribute__ ((packed)) format7_label_t; - - -char * vtoc_ebcdic_enc ( - unsigned char source[LINE_LENGTH], - unsigned char target[LINE_LENGTH], - int l); -char * vtoc_ebcdic_dec ( - unsigned char source[LINE_LENGTH], - unsigned char target[LINE_LENGTH], - int l); -void vtoc_set_extent ( - extent_t * ext, - __u8 typeind, - __u8 seqno, - cchh_t * lower, - cchh_t * upper); -void vtoc_set_cchh ( - cchh_t * addr, - __u16 cc, - __u16 hh); -void vtoc_set_cchhb ( - cchhb_t * addr, - __u16 cc, - __u16 hh, - __u8 b); -void vtoc_set_date ( - labeldate_t * d, - __u8 year, - __u16 day); - -void vtoc_volume_label_init ( - volume_label_t *vlabel); - -int vtoc_read_volume_label ( - char * device, - unsigned long vlabel_start, - volume_label_t * vlabel); - -int vtoc_write_volume_label ( - char *device, - unsigned long vlabel_start, - volume_label_t *vlabel); - -void vtoc_volume_label_set_volser ( - volume_label_t *vlabel, - char *volser); - -char *vtoc_volume_label_get_volser ( - volume_label_t *vlabel, - char *volser); - -void vtoc_volume_label_set_key ( - volume_label_t *vlabel, - char *key); - -void vtoc_volume_label_set_label ( - volume_label_t *vlabel, - char *lbl); - -char *vtoc_volume_label_get_label ( - volume_label_t *vlabel, - char *lbl); - -void vtoc_read_label ( - char *device, - unsigned long position, - format1_label_t *f1, - format4_label_t *f4, - format5_label_t *f5, - format7_label_t *f7); - -void vtoc_write_label ( - char *device, - unsigned long position, - format1_label_t *f1, - format4_label_t *f4, - format5_label_t *f5, - format7_label_t *f7); - - -void vtoc_init_format1_label ( - char *volid, - unsigned int blksize, - extent_t *part_extent, - format1_label_t *f1); - - -void vtoc_init_format4_label ( - format4_label_t *f4lbl, - unsigned int usable_partitions, - unsigned int cylinders, - unsigned int tracks, - unsigned int blocks, - unsigned int blksize, - __u16 dev_type); - -void vtoc_update_format4_label ( - format4_label_t *f4, - cchhb_t *highest_f1, - __u16 unused_update); - - -void vtoc_init_format5_label ( - format5_label_t *f5); - -void vtoc_update_format5_label_add ( - format5_label_t *f5, - int verbose, - int cyl, - int trk, - __u16 a, - __u16 b, - __u8 c); - -void vtoc_update_format5_label_del ( - format5_label_t *f5, - int verbose, - int cyl, - int trk, - __u16 a, - __u16 b, - __u8 c); - - -void vtoc_init_format7_label ( - format7_label_t *f7); - -void vtoc_update_format7_label_add ( - format7_label_t *f7, - int verbose, - __u32 a, - __u32 b); - -void vtoc_update_format7_label_del ( - format7_label_t *f7, - int verbose, - __u32 a, - __u32 b); - - -void vtoc_set_freespace( - format4_label_t *f4, - format5_label_t *f5, - format7_label_t *f7, - char ch, - int verbose, - __u32 start, - __u32 stop, - int cyl, - int trk); - - - - - - - - - - - - + char DS7KEYID[4]; /* key identifier */ + struct vtoc_ds7ext DS7EXTNT[5]; /* space for 5 extent descriptions */ + __u8 DS7FMTID; /* format identifier */ + struct vtoc_ds7ext DS7ADEXT[11]; /* space for 11 extent descriptions */ + char res1[2]; /* reserved */ + struct vtoc_cchhb DS7PTRDS; /* pointer to next FMT7 DSCB */ +} __attribute__ ((packed)); + +#endif /* _ASM_S390_VTOC_H */ -- cgit v1.2.3 From cdb32dc90bd38503befd1f4d0b762a1ace09bb28 Mon Sep 17 00:00:00 2001 From: Ursula Braun-Krahl Date: Mon, 7 Nov 2005 00:59:10 -0800 Subject: [PATCH] s390: duplicate timeout in qdio Remove duplicate timeout in qdio_establish(). Signed-off-by: Ursula Braun-Krahl Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/cio/qdio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 381f339e320..ef5cd07011b 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c @@ -56,7 +56,7 @@ #include "ioasm.h" #include "chsc.h" -#define VERSION_QDIO_C "$Revision: 1.101 $" +#define VERSION_QDIO_C "$Revision: 1.108 $" /****************** MODULE PARAMETER VARIABLES ********************/ MODULE_AUTHOR("Utz Bacher "); @@ -2873,10 +2873,10 @@ qdio_establish(struct qdio_initialize *init_data) return result; } - wait_event_interruptible_timeout(cdev->private->wait_q, + /* Timeout is cared for already by using ccw_device_start_timeout(). */ + wait_event_interruptible(cdev->private->wait_q, irq_ptr->state == QDIO_IRQ_STATE_ESTABLISHED || - irq_ptr->state == QDIO_IRQ_STATE_ERR, - QDIO_ESTABLISH_TIMEOUT); + irq_ptr->state == QDIO_IRQ_STATE_ERR); if (irq_ptr->state == QDIO_IRQ_STATE_ESTABLISHED) result = 0; -- cgit v1.2.3 From 1047aa7723997620ba03a21429d2c5d923ebf48f Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Mon, 7 Nov 2005 00:59:11 -0800 Subject: [PATCH] s390: const pointer uaccess Using __typeof__(*ptr) on a pointer to const makes the __x variable in __get_user const as well. The latest gcc will refuse to write to it. Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-s390/uaccess.h | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/include/asm-s390/uaccess.h b/include/asm-s390/uaccess.h index 38a5cf8ab9e..10a619da476 100644 --- a/include/asm-s390/uaccess.h +++ b/include/asm-s390/uaccess.h @@ -200,21 +200,37 @@ extern int __put_user_bad(void) __attribute__((noreturn)); #define __get_user(x, ptr) \ ({ \ - __typeof__(*(ptr)) __x; \ int __gu_err; \ __chk_user_ptr(ptr); \ switch (sizeof(*(ptr))) { \ - case 1: \ - case 2: \ - case 4: \ - case 8: \ + case 1: { \ + unsigned char __x; \ + __get_user_asm(__x, ptr, __gu_err); \ + (x) = (__typeof__(*(ptr))) __x; \ + break; \ + }; \ + case 2: { \ + unsigned short __x; \ + __get_user_asm(__x, ptr, __gu_err); \ + (x) = (__typeof__(*(ptr))) __x; \ + break; \ + }; \ + case 4: { \ + unsigned int __x; \ + __get_user_asm(__x, ptr, __gu_err); \ + (x) = (__typeof__(*(ptr))) __x; \ + break; \ + }; \ + case 8: { \ + unsigned long long __x; \ __get_user_asm(__x, ptr, __gu_err); \ + (x) = (__typeof__(*(ptr))) __x; \ break; \ + }; \ default: \ __get_user_bad(); \ break; \ } \ - (x) = __x; \ __gu_err; \ }) -- cgit v1.2.3 From a5da866fe0272db6b664d4c790ad98320bf2feb6 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Mon, 7 Nov 2005 00:59:12 -0800 Subject: [PATCH] s390: fix memory leak in vmcp If vmcp is interrupted by a signal the vmcp command buffer is not freed. Found by Pete Zaitcev. Signed-off-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/char/vmcp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c index 8990d8076e7..19762f3476a 100644 --- a/drivers/s390/char/vmcp.c +++ b/drivers/s390/char/vmcp.c @@ -103,8 +103,10 @@ vmcp_write(struct file *file, const char __user * buff, size_t count, } cmd[count] = '\0'; session = (struct vmcp_session *)file->private_data; - if (down_interruptible(&session->mutex)) + if (down_interruptible(&session->mutex)) { + kfree(cmd); return -ERESTARTSYS; + } if (!session->response) session->response = (char *)__get_free_pages(GFP_KERNEL | __GFP_REPEAT | GFP_DMA, -- cgit v1.2.3 From 0ad775dbba12de3b7d25f586efe81ad995ca75a7 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 7 Nov 2005 00:59:12 -0800 Subject: [PATCH] s390: merge common parts of head.S and head64.S Merge common parts of head.S and head64.S into head.S and move architecture specific parts to head31.S and head64.S respectively. Saves us ~500 lines of duplicated assembly code. Acked-by: Martin Schwidefsky Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/Makefile | 4 +- arch/s390/kernel/Makefile | 4 +- arch/s390/kernel/head.S | 382 +++----------------------------- arch/s390/kernel/head31.S | 336 +++++++++++++++++++++++++++++ arch/s390/kernel/head64.S | 538 +--------------------------------------------- 5 files changed, 381 insertions(+), 883 deletions(-) create mode 100644 arch/s390/kernel/head31.S diff --git a/arch/s390/Makefile b/arch/s390/Makefile index 98db30481d9..73a09a6ee6c 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -76,9 +76,7 @@ AFLAGS += $(aflags-y) OBJCOPYFLAGS := -O binary LDFLAGS_vmlinux := -e start -head-$(CONFIG_ARCH_S390_31) += arch/$(ARCH)/kernel/head.o -head-$(CONFIG_ARCH_S390X) += arch/$(ARCH)/kernel/head64.o -head-y += arch/$(ARCH)/kernel/init_task.o +head-y := arch/$(ARCH)/kernel/head.o arch/$(ARCH)/kernel/init_task.o core-y += arch/$(ARCH)/mm/ arch/$(ARCH)/kernel/ arch/$(ARCH)/crypto/ \ arch/$(ARCH)/appldata/ diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 8584dd82321..7434c32bc63 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -8,9 +8,7 @@ obj-y := bitmap.o traps.o time.o process.o \ setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ semaphore.o s390_ext.o debug.o profile.o irq.o reipl_diag.o -extra-$(CONFIG_ARCH_S390_31) += head.o -extra-$(CONFIG_ARCH_S390X) += head64.o -extra-y += init_task.o vmlinux.lds +extra-y += head.o init_task.o vmlinux.lds obj-$(CONFIG_MODULES) += s390_ksyms.o module.o obj-$(CONFIG_SMP) += smp.o diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index 4ca02933211..d31a97c89f6 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S @@ -1,11 +1,12 @@ /* * arch/s390/kernel/head.S * - * S390 version - * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Hartmut Penner (hp@de.ibm.com), - * Martin Schwidefsky (schwidefsky@de.ibm.com), - * Rob van der Heij (rvdhei@iae.nl) + * (C) Copyright IBM Corp. 1999, 2005 + * + * Author(s): Hartmut Penner + * Martin Schwidefsky + * Rob van der Heij + * Heiko Carstens * * There are 5 different IPL methods * 1) load the image directly into ram at address 0 and do an PSW restart @@ -19,12 +20,7 @@ * 5) direct call of start by the SALIPL loader * We use the cpuid to distinguish between VM and native ipl * params for kernel are pushed to 0x10400 (see setup.h) - - Changes: - Okt 25 2000 - added code to skip HDR and EOF to allow SL tape IPL (5 retries) - changed first CCW from rewind to backspace block - + * */ #include @@ -34,6 +30,12 @@ #include #include +#ifdef CONFIG_ARCH_S390X +#define ARCH_OFFSET 4 +#else +#define ARCH_OFFSET 0 +#endif + #ifndef CONFIG_IPL .org 0 .long 0x00080000,0x80000000+startup # Just a restart PSW @@ -201,7 +203,7 @@ ssch 0(%r3) # load chunk of 1600 bytes bnz .Llderr .Lwait4irq: - mvc __LC_IO_NEW_PSW(8),.Lnewpsw # set up IO interrupt psw + mvc 0x78(8),.Lnewpsw # set up IO interrupt psw lpsw .Lwaitpsw .Lioint: c %r1,0xb8 # compare subchannel number @@ -265,13 +267,13 @@ iplstart: la %r2,IPL_BS # load start address bas %r14,.Lloader # load rest of ipl image l %r12,.Lparm # pointer to parameter area - st %r1,IPL_DEVICE-PARMAREA(%r12) # store ipl device number + st %r1,IPL_DEVICE+ARCH_OFFSET-PARMAREA(%r12) # save ipl device number # # load parameter file from ipl device # .Lagain1: - l %r2,INITRD_START-PARMAREA(%r12) # use ramdisk location as temp + l %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # ramdisk loc. is temp bas %r14,.Lloader # load parameter file ltr %r2,%r2 # got anything ? bz .Lnopf @@ -279,7 +281,7 @@ iplstart: bnh .Lnotrunc la %r2,895 .Lnotrunc: - l %r4,INITRD_START-PARMAREA(%r12) + l %r4,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) clc 0(3,%r4),.L_hdr # if it is HDRx bz .Lagain1 # skip dataset header clc 0(3,%r4),.L_eof # if it is EOFx @@ -322,14 +324,14 @@ iplstart: # load ramdisk from ipl device # .Lagain2: - l %r2,INITRD_START-PARMAREA(%r12) # load adr. of ramdisk + l %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # addr of ramdisk bas %r14,.Lloader # load ramdisk - st %r2,INITRD_SIZE-PARMAREA(%r12) # store size of ramdisk + st %r2,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r12) # store size of ramdisk ltr %r2,%r2 bnz .Lrdcont - st %r2,INITRD_START-PARMAREA(%r12) # no ramdisk found, null it + st %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # no ramdisk found .Lrdcont: - l %r2,INITRD_START-PARMAREA(%r12) + l %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) clc 0(3,%r2),.L_hdr # skip HDRx and EOFx bz .Lagain2 @@ -432,10 +434,10 @@ start: la %r3,1(%r3) .done: l %r1,.memsize - st %r3,0(%r1) + st %r3,ARCH_OFFSET(%r1) slr %r0,%r0 - st %r0,INITRD_SIZE-PARMAREA(%r11) - st %r0,INITRD_START-PARMAREA(%r11) + st %r0,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r11) + st %r0,INITRD_START+ARCH_OFFSET-PARMAREA(%r11) j startup # continue with startup .tbl: .long _ebcasc # translate table .cmd: .long COMMAND_LINE # address of command line buffer @@ -478,303 +480,23 @@ start: .byte 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7 .byte 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff -# -# startup-code at 0x10000, running in real mode -# this is called either by the ipl loader or directly by PSW restart -# or linload or SALIPL -# - .org 0x10000 -startup:basr %r13,0 # get base -.LPG1: l %r1, .Lget_ipl_device_addr-.LPG1(%r13) - basr %r14, %r1 - lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers - la %r12,_pstart-.LPG1(%r13) # pointer to parameter area - # move IPL device to lowcore - mvc __LC_IPLDEV(4),IPL_DEVICE-PARMAREA(%r12) - -# -# clear bss memory -# - l %r2,.Lbss_bgn-.LPG1(%r13) # start of bss - l %r3,.Lbss_end-.LPG1(%r13) # end of bss - sr %r3,%r2 # length of bss - sr %r4,%r4 # - sr %r5,%r5 # set src,length and pad to zero - sr %r0,%r0 # - mvcle %r2,%r4,0 # clear mem - jo .-4 # branch back, if not finish - - l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word -.Lservicecall: - stosm .Lpmask-.LPG1(%r13),0x01 # authorize ext interrupts - - stctl %r0, %r0,.Lcr-.LPG1(%r13) # get cr0 - la %r1,0x200 # set bit 22 - o %r1,.Lcr-.LPG1(%r13) # or old cr0 with r1 - st %r1,.Lcr-.LPG1(%r13) - lctl %r0, %r0,.Lcr-.LPG1(%r13) # load modified cr0 - - mvc __LC_EXT_NEW_PSW(8),.Lpcext-.LPG1(%r13) # set postcall psw - la %r1, .Lsclph-.LPG1(%r13) - a %r1,__LC_EXT_NEW_PSW+4 # set handler - st %r1,__LC_EXT_NEW_PSW+4 - - la %r4,_pstart-.LPG1(%r13) # %r4 is our index for sccb stuff - la %r1, .Lsccb-PARMAREA(%r4) # our sccb - .insn rre,0xb2200000,%r2,%r1 # service call - ipm %r1 - srl %r1,28 # get cc code - xr %r3, %r3 - chi %r1,3 - be .Lfchunk-.LPG1(%r13) # leave - chi %r1,2 - be .Lservicecall-.LPG1(%r13) - lpsw .Lwaitsclp-.LPG1(%r13) -.Lsclph: - lh %r1,.Lsccbr-PARMAREA(%r4) - chi %r1,0x10 # 0x0010 is the sucess code - je .Lprocsccb # let's process the sccb - chi %r1,0x1f0 - bne .Lfchunk-.LPG1(%r13) # unhandled error code - c %r2, .Lrcp-.LPG1(%r13) # Did we try Read SCP forced - bne .Lfchunk-.LPG1(%r13) # if no, give up - l %r2, .Lrcp2-.LPG1(%r13) # try with Read SCP - b .Lservicecall-.LPG1(%r13) -.Lprocsccb: - lhi %r1,0 - icm %r1,3,.Lscpincr1-PARMAREA(%r4) # use this one if != 0 - jnz .Lscnd - lhi %r1,0x800 # otherwise report 2GB -.Lscnd: - lhi %r3,0x800 # limit reported memory size to 2GB - cr %r1,%r3 - jl .Lno2gb - lr %r1,%r3 -.Lno2gb: - xr %r3,%r3 # same logic - ic %r3,.Lscpa1-PARMAREA(%r4) - chi %r3,0x00 - jne .Lcompmem - l %r3,.Lscpa2-PARMAREA(%r13) -.Lcompmem: - mr %r2,%r1 # mem in MB on 128-bit - l %r1,.Lonemb-.LPG1(%r13) - mr %r2,%r1 # mem size in bytes in %r3 - b .Lfchunk-.LPG1(%r13) - - .align 4 -.Lget_ipl_device_addr: - .long .Lget_ipl_device -.Lpmask: - .byte 0 -.align 8 -.Lpcext:.long 0x00080000,0x80000000 -.Lcr: - .long 0x00 # place holder for cr0 -.Lwaitsclp: - .long 0x010a0000,0x80000000 + .Lsclph -.Lrcp: - .int 0x00120001 # Read SCP forced code -.Lrcp2: - .int 0x00020001 # Read SCP code -.Lonemb: - .int 0x100000 -.Lfchunk: - -# -# find memory chunks. -# - lr %r9,%r3 # end of mem - mvc __LC_PGM_NEW_PSW(8),.Lpcmem-.LPG1(%r13) - la %r1,1 # test in increments of 128KB - sll %r1,17 - l %r3,.Lmchunk-.LPG1(%r13) # get pointer to memory_chunk array - slr %r4,%r4 # set start of chunk to zero - slr %r5,%r5 # set end of chunk to zero - slr %r6,%r6 # set access code to zero - la %r10, MEMORY_CHUNKS # number of chunks -.Lloop: - tprot 0(%r5),0 # test protection of first byte - ipm %r7 - srl %r7,28 - clr %r6,%r7 # compare cc with last access code - be .Lsame-.LPG1(%r13) - b .Lchkmem-.LPG1(%r13) -.Lsame: - ar %r5,%r1 # add 128KB to end of chunk - bno .Lloop-.LPG1(%r13) # r1 < 0x80000000 -> loop -.Lchkmem: # > 2GB or tprot got a program check - clr %r4,%r5 # chunk size > 0? - be .Lchkloop-.LPG1(%r13) - st %r4,0(%r3) # store start address of chunk - lr %r0,%r5 - slr %r0,%r4 - st %r0,4(%r3) # store size of chunk - st %r6,8(%r3) # store type of chunk - la %r3,12(%r3) - l %r4,.Lmemsize-.LPG1(%r13) # address of variable memory_size - st %r5,0(%r4) # store last end to memory size - ahi %r10,-1 # update chunk number -.Lchkloop: - lr %r6,%r7 # set access code to last cc - # we got an exception or we're starting a new - # chunk , we must check if we should - # still try to find valid memory (if we detected - # the amount of available storage), and if we - # have chunks left - xr %r0,%r0 - clr %r0,%r9 # did we detect memory? - je .Ldonemem # if not, leave - chi %r10,0 # do we have chunks left? - je .Ldonemem - alr %r5,%r1 # add 128KB to end of chunk - lr %r4,%r5 # potential new chunk - clr %r5,%r9 # should we go on? - jl .Lloop -.Ldonemem: - l %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags -# -# find out if we are running under VM -# - stidp __LC_CPUID # store cpuid - tm __LC_CPUID,0xff # running under VM ? - bno .Lnovm-.LPG1(%r13) - oi 3(%r12),1 # set VM flag -.Lnovm: - lh %r0,__LC_CPUID+4 # get cpu version - chi %r0,0x7490 # running on a P/390 ? - bne .Lnop390-.LPG1(%r13) - oi 3(%r12),4 # set P/390 flag -.Lnop390: - -# -# find out if we have an IEEE fpu -# - mvc __LC_PGM_NEW_PSW(8),.Lpcfpu-.LPG1(%r13) - efpc %r0,0 # test IEEE extract fpc instruction - oi 3(%r12),2 # set IEEE fpu flag -.Lchkfpu: - -# -# find out if we have the CSP instruction -# - mvc __LC_PGM_NEW_PSW(8),.Lpccsp-.LPG1(%r13) - la %r0,0 - lr %r1,%r0 - la %r2,4 - csp %r0,%r2 # Test CSP instruction - oi 3(%r12),8 # set CSP flag -.Lchkcsp: - -# -# find out if we have the MVPG instruction -# - mvc __LC_PGM_NEW_PSW(8),.Lpcmvpg-.LPG1(%r13) - sr %r0,%r0 - la %r1,0 - la %r2,0 - mvpg %r1,%r2 # Test CSP instruction - oi 3(%r12),16 # set MVPG flag -.Lchkmvpg: - -# -# find out if we have the IDTE instruction -# - mvc __LC_PGM_NEW_PSW(8),.Lpcidte-.LPG1(%r13) - .long 0xb2b10000 # store facility list - tm 0xc8,0x08 # check bit for clearing-by-ASCE - bno .Lchkidte-.LPG1(%r13) - lhi %r1,2094 - lhi %r2,0 - .long 0xb98e2001 - oi 3(%r12),0x80 # set IDTE flag -.Lchkidte: - - lpsw .Lentry-.LPG1(13) # jump to _stext in primary-space, - # virtual and never return ... - .align 8 -.Lentry:.long 0x00080000,0x80000000 + _stext -.Lctl: .long 0x04b50002 # cr0: various things - .long 0 # cr1: primary space segment table - .long .Lduct # cr2: dispatchable unit control table - .long 0 # cr3: instruction authorization - .long 0 # cr4: instruction authorization - .long 0xffffffff # cr5: primary-aste origin - .long 0 # cr6: I/O interrupts - .long 0 # cr7: secondary space segment table - .long 0 # cr8: access registers translation - .long 0 # cr9: tracing off - .long 0 # cr10: tracing off - .long 0 # cr11: tracing off - .long 0 # cr12: tracing off - .long 0 # cr13: home space segment table - .long 0xc0000000 # cr14: machine check handling off - .long 0 # cr15: linkage stack operations -.Lpcmem:.long 0x00080000,0x80000000 + .Lchkmem -.Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu -.Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp -.Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg -.Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte -.Lmemsize:.long memory_size -.Lmchunk:.long memory_chunk -.Lmflags:.long machine_flags -.Lbss_bgn: .long __bss_start -.Lbss_end: .long _end - - .org PARMAREA-64 -.Lduct: .long 0,0,0,0,0,0,0,0 - .long 0,0,0,0,0,0,0,0 - -# -# params at 10400 (setup.h) -# - .org PARMAREA - .global _pstart -_pstart: - .long 0,0 # IPL_DEVICE - .long 0,RAMDISK_ORIGIN # INITRD_START - .long 0,RAMDISK_SIZE # INITRD_SIZE - - .org COMMAND_LINE - .byte "root=/dev/ram0 ro" - .byte 0 - .org 0x11000 -.Lsccb: - .hword 0x1000 # length, one page - .byte 0x00,0x00,0x00 - .byte 0x80 # variable response bit set -.Lsccbr: - .hword 0x00 # response code -.Lscpincr1: - .hword 0x00 -.Lscpa1: - .byte 0x00 - .fill 89,1,0 -.Lscpa2: - .int 0x00 -.Lscpincr2: - .quad 0x00 - .fill 3984,1,0 - .org 0x12000 - .global _pend -_pend: - +.macro GET_IPL_DEVICE .Lget_ipl_device: basr %r12,0 -.LPG2: l %r1,0xb8 # get sid +.LGID: l %r1,0xb8 # get sid sll %r1,15 # test if subchannel is enabled srl %r1,31 ltr %r1,%r1 bz 0(%r14) # subchannel disabled l %r1,0xb8 - la %r5,.Lipl_schib-.LPG2(%r12) + la %r5,.Lipl_schib-.LGID(%r12) stsch 0(%r5) # get schib of subchannel bnz 0(%r14) # schib not available tm 5(%r5),0x01 # devno valid? bno 0(%r14) - la %r6,ipl_parameter_flags-.LPG2(%r12) + la %r6,ipl_parameter_flags-.LGID(%r12) oi 3(%r6),0x01 # set flag - la %r2,ipl_devno-.LPG2(%r12) + la %r2,ipl_devno-.LGID(%r12) mvc 0(2,%r2),6(%r5) # store devno tm 4(%r5),0x80 # qdio capable device? bno 0(%r14) @@ -815,46 +537,10 @@ ipl_parameter_flags: .globl ipl_devno ipl_devno: .word 0 +.endm -#ifdef CONFIG_SHARED_KERNEL - .org 0x100000 +#ifdef CONFIG_ARCH_S390X +#include "head64.S" +#else +#include "head31.S" #endif - -# -# startup-code, running in virtual mode -# - .globl _stext -_stext: basr %r13,0 # get base -.LPG3: -# -# Setup stack -# - l %r15,.Linittu-.LPG3(%r13) - mvc __LC_CURRENT(4),__TI_task(%r15) - ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE - st %r15,__LC_KERNEL_STACK # set end of kernel stack - ahi %r15,-96 - xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain - -# check control registers - stctl %c0,%c15,0(%r15) - oi 2(%r15),0x40 # enable sigp emergency signal - oi 0(%r15),0x10 # switch on low address protection - lctl %c0,%c15,0(%r15) - -# - lam 0,15,.Laregs-.LPG3(%r13) # load access regs needed by uaccess - l %r14,.Lstart-.LPG3(%r13) - basr %r14,%r14 # call start_kernel -# -# We returned from start_kernel ?!? PANIK -# - basr %r13,0 - lpsw .Ldw-.(%r13) # load disabled wait psw -# - .align 8 -.Ldw: .long 0x000a0000,0x00000000 -.Linittu: .long init_thread_union -.Lstart: .long start_kernel -.Laregs: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S new file mode 100644 index 00000000000..2d3b089bfb8 --- /dev/null +++ b/arch/s390/kernel/head31.S @@ -0,0 +1,336 @@ +/* + * arch/s390/kernel/head31.S + * + * (C) Copyright IBM Corp. 2005 + * + * Author(s): Hartmut Penner + * Martin Schwidefsky + * Rob van der Heij + * Heiko Carstens + * + */ + +# +# startup-code at 0x10000, running in absolute addressing mode +# this is called either by the ipl loader or directly by PSW restart +# or linload or SALIPL +# + .org 0x10000 +startup:basr %r13,0 # get base +.LPG1: l %r1, .Lget_ipl_device_addr-.LPG1(%r13) + basr %r14, %r1 + lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers + la %r12,_pstart-.LPG1(%r13) # pointer to parameter area + # move IPL device to lowcore + mvc __LC_IPLDEV(4),IPL_DEVICE-PARMAREA(%r12) + +# +# clear bss memory +# + l %r2,.Lbss_bgn-.LPG1(%r13) # start of bss + l %r3,.Lbss_end-.LPG1(%r13) # end of bss + sr %r3,%r2 # length of bss + sr %r4,%r4 + sr %r5,%r5 # set src,length and pad to zero + sr %r0,%r0 + mvcle %r2,%r4,0 # clear mem + jo .-4 # branch back, if not finish + + l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word +.Lservicecall: + stosm .Lpmask-.LPG1(%r13),0x01 # authorize ext interrupts + + stctl %r0, %r0,.Lcr-.LPG1(%r13) # get cr0 + la %r1,0x200 # set bit 22 + o %r1,.Lcr-.LPG1(%r13) # or old cr0 with r1 + st %r1,.Lcr-.LPG1(%r13) + lctl %r0, %r0,.Lcr-.LPG1(%r13) # load modified cr0 + + mvc __LC_EXT_NEW_PSW(8),.Lpcext-.LPG1(%r13) # set postcall psw + la %r1, .Lsclph-.LPG1(%r13) + a %r1,__LC_EXT_NEW_PSW+4 # set handler + st %r1,__LC_EXT_NEW_PSW+4 + + la %r4,_pstart-.LPG1(%r13) # %r4 is our index for sccb stuff + la %r1, .Lsccb-PARMAREA(%r4) # our sccb + .insn rre,0xb2200000,%r2,%r1 # service call + ipm %r1 + srl %r1,28 # get cc code + xr %r3, %r3 + chi %r1,3 + be .Lfchunk-.LPG1(%r13) # leave + chi %r1,2 + be .Lservicecall-.LPG1(%r13) + lpsw .Lwaitsclp-.LPG1(%r13) +.Lsclph: + lh %r1,.Lsccbr-PARMAREA(%r4) + chi %r1,0x10 # 0x0010 is the sucess code + je .Lprocsccb # let's process the sccb + chi %r1,0x1f0 + bne .Lfchunk-.LPG1(%r13) # unhandled error code + c %r2, .Lrcp-.LPG1(%r13) # Did we try Read SCP forced + bne .Lfchunk-.LPG1(%r13) # if no, give up + l %r2, .Lrcp2-.LPG1(%r13) # try with Read SCP + b .Lservicecall-.LPG1(%r13) +.Lprocsccb: + lhi %r1,0 + icm %r1,3,.Lscpincr1-PARMAREA(%r4) # use this one if != 0 + jnz .Lscnd + lhi %r1,0x800 # otherwise report 2GB +.Lscnd: + lhi %r3,0x800 # limit reported memory size to 2GB + cr %r1,%r3 + jl .Lno2gb + lr %r1,%r3 +.Lno2gb: + xr %r3,%r3 # same logic + ic %r3,.Lscpa1-PARMAREA(%r4) + chi %r3,0x00 + jne .Lcompmem + l %r3,.Lscpa2-PARMAREA(%r13) +.Lcompmem: + mr %r2,%r1 # mem in MB on 128-bit + l %r1,.Lonemb-.LPG1(%r13) + mr %r2,%r1 # mem size in bytes in %r3 + b .Lfchunk-.LPG1(%r13) + + .align 4 +.Lget_ipl_device_addr: + .long .Lget_ipl_device +.Lpmask: + .byte 0 +.align 8 +.Lpcext:.long 0x00080000,0x80000000 +.Lcr: + .long 0x00 # place holder for cr0 +.Lwaitsclp: + .long 0x010a0000,0x80000000 + .Lsclph +.Lrcp: + .int 0x00120001 # Read SCP forced code +.Lrcp2: + .int 0x00020001 # Read SCP code +.Lonemb: + .int 0x100000 +.Lfchunk: + +# +# find memory chunks. +# + lr %r9,%r3 # end of mem + mvc __LC_PGM_NEW_PSW(8),.Lpcmem-.LPG1(%r13) + la %r1,1 # test in increments of 128KB + sll %r1,17 + l %r3,.Lmchunk-.LPG1(%r13) # get pointer to memory_chunk array + slr %r4,%r4 # set start of chunk to zero + slr %r5,%r5 # set end of chunk to zero + slr %r6,%r6 # set access code to zero + la %r10, MEMORY_CHUNKS # number of chunks +.Lloop: + tprot 0(%r5),0 # test protection of first byte + ipm %r7 + srl %r7,28 + clr %r6,%r7 # compare cc with last access code + be .Lsame-.LPG1(%r13) + b .Lchkmem-.LPG1(%r13) +.Lsame: + ar %r5,%r1 # add 128KB to end of chunk + bno .Lloop-.LPG1(%r13) # r1 < 0x80000000 -> loop +.Lchkmem: # > 2GB or tprot got a program check + clr %r4,%r5 # chunk size > 0? + be .Lchkloop-.LPG1(%r13) + st %r4,0(%r3) # store start address of chunk + lr %r0,%r5 + slr %r0,%r4 + st %r0,4(%r3) # store size of chunk + st %r6,8(%r3) # store type of chunk + la %r3,12(%r3) + l %r4,.Lmemsize-.LPG1(%r13) # address of variable memory_size + st %r5,0(%r4) # store last end to memory size + ahi %r10,-1 # update chunk number +.Lchkloop: + lr %r6,%r7 # set access code to last cc + # we got an exception or we're starting a new + # chunk , we must check if we should + # still try to find valid memory (if we detected + # the amount of available storage), and if we + # have chunks left + xr %r0,%r0 + clr %r0,%r9 # did we detect memory? + je .Ldonemem # if not, leave + chi %r10,0 # do we have chunks left? + je .Ldonemem + alr %r5,%r1 # add 128KB to end of chunk + lr %r4,%r5 # potential new chunk + clr %r5,%r9 # should we go on? + jl .Lloop +.Ldonemem: + l %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags +# +# find out if we are running under VM +# + stidp __LC_CPUID # store cpuid + tm __LC_CPUID,0xff # running under VM ? + bno .Lnovm-.LPG1(%r13) + oi 3(%r12),1 # set VM flag +.Lnovm: + lh %r0,__LC_CPUID+4 # get cpu version + chi %r0,0x7490 # running on a P/390 ? + bne .Lnop390-.LPG1(%r13) + oi 3(%r12),4 # set P/390 flag +.Lnop390: + +# +# find out if we have an IEEE fpu +# + mvc __LC_PGM_NEW_PSW(8),.Lpcfpu-.LPG1(%r13) + efpc %r0,0 # test IEEE extract fpc instruction + oi 3(%r12),2 # set IEEE fpu flag +.Lchkfpu: + +# +# find out if we have the CSP instruction +# + mvc __LC_PGM_NEW_PSW(8),.Lpccsp-.LPG1(%r13) + la %r0,0 + lr %r1,%r0 + la %r2,4 + csp %r0,%r2 # Test CSP instruction + oi 3(%r12),8 # set CSP flag +.Lchkcsp: + +# +# find out if we have the MVPG instruction +# + mvc __LC_PGM_NEW_PSW(8),.Lpcmvpg-.LPG1(%r13) + sr %r0,%r0 + la %r1,0 + la %r2,0 + mvpg %r1,%r2 # Test CSP instruction + oi 3(%r12),16 # set MVPG flag +.Lchkmvpg: + +# +# find out if we have the IDTE instruction +# + mvc __LC_PGM_NEW_PSW(8),.Lpcidte-.LPG1(%r13) + .long 0xb2b10000 # store facility list + tm 0xc8,0x08 # check bit for clearing-by-ASCE + bno .Lchkidte-.LPG1(%r13) + lhi %r1,2094 + lhi %r2,0 + .long 0xb98e2001 + oi 3(%r12),0x80 # set IDTE flag +.Lchkidte: + + lpsw .Lentry-.LPG1(13) # jump to _stext in primary-space, + # virtual and never return ... + .align 8 +.Lentry:.long 0x00080000,0x80000000 + _stext +.Lctl: .long 0x04b50002 # cr0: various things + .long 0 # cr1: primary space segment table + .long .Lduct # cr2: dispatchable unit control table + .long 0 # cr3: instruction authorization + .long 0 # cr4: instruction authorization + .long 0xffffffff # cr5: primary-aste origin + .long 0 # cr6: I/O interrupts + .long 0 # cr7: secondary space segment table + .long 0 # cr8: access registers translation + .long 0 # cr9: tracing off + .long 0 # cr10: tracing off + .long 0 # cr11: tracing off + .long 0 # cr12: tracing off + .long 0 # cr13: home space segment table + .long 0xc0000000 # cr14: machine check handling off + .long 0 # cr15: linkage stack operations +.Lpcmem:.long 0x00080000,0x80000000 + .Lchkmem +.Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu +.Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp +.Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg +.Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte +.Lmemsize:.long memory_size +.Lmchunk:.long memory_chunk +.Lmflags:.long machine_flags +.Lbss_bgn: .long __bss_start +.Lbss_end: .long _end + + .org PARMAREA-64 +.Lduct: .long 0,0,0,0,0,0,0,0 + .long 0,0,0,0,0,0,0,0 + +# +# params at 10400 (setup.h) +# + .org PARMAREA + .global _pstart +_pstart: + .long 0,0 # IPL_DEVICE + .long 0,RAMDISK_ORIGIN # INITRD_START + .long 0,RAMDISK_SIZE # INITRD_SIZE + + .org COMMAND_LINE + .byte "root=/dev/ram0 ro" + .byte 0 + .org 0x11000 +.Lsccb: + .hword 0x1000 # length, one page + .byte 0x00,0x00,0x00 + .byte 0x80 # variable response bit set +.Lsccbr: + .hword 0x00 # response code +.Lscpincr1: + .hword 0x00 +.Lscpa1: + .byte 0x00 + .fill 89,1,0 +.Lscpa2: + .int 0x00 +.Lscpincr2: + .quad 0x00 + .fill 3984,1,0 + .org 0x12000 + .global _pend +_pend: + + GET_IPL_DEVICE + +#ifdef CONFIG_SHARED_KERNEL + .org 0x100000 +#endif + +# +# startup-code, running in virtual mode +# + .globl _stext +_stext: basr %r13,0 # get base +.LPG3: +# +# Setup stack +# + l %r15,.Linittu-.LPG3(%r13) + mvc __LC_CURRENT(4),__TI_task(%r15) + ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union+THREAD_SIZE + st %r15,__LC_KERNEL_STACK # set end of kernel stack + ahi %r15,-96 + xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain + +# check control registers + stctl %c0,%c15,0(%r15) + oi 2(%r15),0x40 # enable sigp emergency signal + oi 0(%r15),0x10 # switch on low address protection + lctl %c0,%c15,0(%r15) + +# + lam 0,15,.Laregs-.LPG3(%r13) # load access regs needed by uaccess + l %r14,.Lstart-.LPG3(%r13) + basr %r14,%r14 # call start_kernel +# +# We returned from start_kernel ?!? PANIK +# + basr %r13,0 + lpsw .Ldw-.(%r13) # load disabled wait psw +# + .align 8 +.Ldw: .long 0x000a0000,0x00000000 +.Linittu:.long init_thread_union +.Lstart:.long start_kernel +.Laregs:.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index d9be8f96f2e..f08c06f45d5 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -1,482 +1,17 @@ /* - * arch/s390/kernel/head.S + * arch/s390/kernel/head64.S * - * S390 version - * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Hartmut Penner (hp@de.ibm.com), - * Martin Schwidefsky (schwidefsky@de.ibm.com), - * Rob van der Heij (rvdhei@iae.nl) + * (C) Copyright IBM Corp. 1999,2005 + * + * Author(s): Hartmut Penner + * Martin Schwidefsky + * Rob van der Heij + * Heiko Carstens * - * There are 5 different IPL methods - * 1) load the image directly into ram at address 0 and do an PSW restart - * 2) linload will load the image from address 0x10000 to memory 0x10000 - * and start the code thru LPSW 0x0008000080010000 (VM only, deprecated) - * 3) generate the tape ipl header, store the generated image on a tape - * and ipl from it - * In case of SL tape you need to IPL 5 times to get past VOL1 etc - * 4) generate the vm reader ipl header, move the generated image to the - * VM reader (use option NOH!) and do a ipl from reader (VM only) - * 5) direct call of start by the SALIPL loader - * We use the cpuid to distinguish between VM and native ipl - * params for kernel are pushed to 0x10400 (see setup.h) - - Changes: - Okt 25 2000 - added code to skip HDR and EOF to allow SL tape IPL (5 retries) - changed first CCW from rewind to backspace block - */ -#include -#include -#include -#include -#include -#include - -#ifndef CONFIG_IPL - .org 0 - .long 0x00080000,0x80000000+startup # Just a restart PSW -#else -#ifdef CONFIG_IPL_TAPE -#define IPL_BS 1024 - .org 0 - .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded - .long 0x27000000,0x60000001 # by ipl to addresses 0-23. - .long 0x02000000,0x20000000+IPL_BS # (a PSW and two CCWs). - .long 0x00000000,0x00000000 # external old psw - .long 0x00000000,0x00000000 # svc old psw - .long 0x00000000,0x00000000 # program check old psw - .long 0x00000000,0x00000000 # machine check old psw - .long 0x00000000,0x00000000 # io old psw - .long 0x00000000,0x00000000 - .long 0x00000000,0x00000000 - .long 0x00000000,0x00000000 - .long 0x000a0000,0x00000058 # external new psw - .long 0x000a0000,0x00000060 # svc new psw - .long 0x000a0000,0x00000068 # program check new psw - .long 0x000a0000,0x00000070 # machine check new psw - .long 0x00080000,0x80000000+.Lioint # io new psw - - .org 0x100 -# -# subroutine for loading from tape -# Paramters: -# R1 = device number -# R2 = load address -.Lloader: - st %r14,.Lldret - la %r3,.Lorbread # r3 = address of orb - la %r5,.Lirb # r5 = address of irb - st %r2,.Lccwread+4 # initialize CCW data addresses - lctl %c6,%c6,.Lcr6 - slr %r2,%r2 -.Lldlp: - la %r6,3 # 3 retries -.Lssch: - ssch 0(%r3) # load chunk of IPL_BS bytes - bnz .Llderr -.Lw4end: - bas %r14,.Lwait4io - tm 8(%r5),0x82 # do we have a problem ? - bnz .Lrecov - slr %r7,%r7 - icm %r7,3,10(%r5) # get residual count - lcr %r7,%r7 - la %r7,IPL_BS(%r7) # IPL_BS-residual=#bytes read - ar %r2,%r7 # add to total size - tm 8(%r5),0x01 # found a tape mark ? - bnz .Ldone - l %r0,.Lccwread+4 # update CCW data addresses - ar %r0,%r7 - st %r0,.Lccwread+4 - b .Lldlp -.Ldone: - l %r14,.Lldret - br %r14 # r2 contains the total size -.Lrecov: - bas %r14,.Lsense # do the sensing - bct %r6,.Lssch # dec. retry count & branch - b .Llderr -# -# Sense subroutine -# -.Lsense: - st %r14,.Lsnsret - la %r7,.Lorbsense - ssch 0(%r7) # start sense command - bnz .Llderr - bas %r14,.Lwait4io - l %r14,.Lsnsret - tm 8(%r5),0x82 # do we have a problem ? - bnz .Llderr - br %r14 -# -# Wait for interrupt subroutine -# -.Lwait4io: - lpsw .Lwaitpsw -.Lioint: - c %r1,0xb8 # compare subchannel number - bne .Lwait4io - tsch 0(%r5) - slr %r0,%r0 - tm 8(%r5),0x82 # do we have a problem ? - bnz .Lwtexit - tm 8(%r5),0x04 # got device end ? - bz .Lwait4io -.Lwtexit: - br %r14 -.Llderr: - lpsw .Lcrash - - .align 8 -.Lorbread: - .long 0x00000000,0x0080ff00,.Lccwread - .align 8 -.Lorbsense: - .long 0x00000000,0x0080ff00,.Lccwsense - .align 8 -.Lccwread: - .long 0x02200000+IPL_BS,0x00000000 -.Lccwsense: - .long 0x04200001,0x00000000 -.Lwaitpsw: - .long 0x020a0000,0x80000000+.Lioint - -.Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -.Lcr6: .long 0xff000000 - .align 8 -.Lcrash:.long 0x000a0000,0x00000000 -.Lldret:.long 0 -.Lsnsret: .long 0 -#endif /* CONFIG_IPL_TAPE */ - -#ifdef CONFIG_IPL_VM -#define IPL_BS 0x730 - .org 0 - .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded - .long 0x02000018,0x60000050 # by ipl to addresses 0-23. - .long 0x02000068,0x60000050 # (a PSW and two CCWs). - .fill 80-24,1,0x40 # bytes 24-79 are discarded !! - .long 0x020000f0,0x60000050 # The next 160 byte are loaded - .long 0x02000140,0x60000050 # to addresses 0x18-0xb7 - .long 0x02000190,0x60000050 # They form the continuation - .long 0x020001e0,0x60000050 # of the CCW program started - .long 0x02000230,0x60000050 # by ipl and load the range - .long 0x02000280,0x60000050 # 0x0f0-0x730 from the image - .long 0x020002d0,0x60000050 # to the range 0x0f0-0x730 - .long 0x02000320,0x60000050 # in memory. At the end of - .long 0x02000370,0x60000050 # the channel program the PSW - .long 0x020003c0,0x60000050 # at location 0 is loaded. - .long 0x02000410,0x60000050 # Initial processing starts - .long 0x02000460,0x60000050 # at 0xf0 = iplstart. - .long 0x020004b0,0x60000050 - .long 0x02000500,0x60000050 - .long 0x02000550,0x60000050 - .long 0x020005a0,0x60000050 - .long 0x020005f0,0x60000050 - .long 0x02000640,0x60000050 - .long 0x02000690,0x60000050 - .long 0x020006e0,0x20000050 - - .org 0xf0 -# -# subroutine for loading cards from the reader -# -.Lloader: - la %r3,.Lorb # r2 = address of orb into r2 - la %r5,.Lirb # r4 = address of irb - la %r6,.Lccws - la %r7,20 -.Linit: - st %r2,4(%r6) # initialize CCW data addresses - la %r2,0x50(%r2) - la %r6,8(%r6) - bct 7,.Linit - - lctl %c6,%c6,.Lcr6 # set IO subclass mask - slr %r2,%r2 -.Lldlp: - ssch 0(%r3) # load chunk of 1600 bytes - bnz .Llderr -.Lwait4irq: - mvc 0x78(8),.Lnewpsw # set up IO interrupt psw - lpsw .Lwaitpsw -.Lioint: - c %r1,0xb8 # compare subchannel number - bne .Lwait4irq - tsch 0(%r5) - - slr %r0,%r0 - ic %r0,8(%r5) # get device status - chi %r0,8 # channel end ? - be .Lcont - chi %r0,12 # channel end + device end ? - be .Lcont - - l %r0,4(%r5) - s %r0,8(%r3) # r0/8 = number of ccws executed - mhi %r0,10 # *10 = number of bytes in ccws - lh %r3,10(%r5) # get residual count - sr %r0,%r3 # #ccws*80-residual=#bytes read - ar %r2,%r0 - - br %r14 # r2 contains the total size - -.Lcont: - ahi %r2,0x640 # add 0x640 to total size - la %r6,.Lccws - la %r7,20 -.Lincr: - l %r0,4(%r6) # update CCW data addresses - ahi %r0,0x640 - st %r0,4(%r6) - ahi %r6,8 - bct 7,.Lincr - - b .Lldlp -.Llderr: - lpsw .Lcrash - - .align 8 -.Lorb: .long 0x00000000,0x0080ff00,.Lccws -.Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -.Lcr6: .long 0xff000000 -.Lloadp:.long 0,0 - .align 8 -.Lcrash:.long 0x000a0000,0x00000000 -.Lnewpsw: - .long 0x00080000,0x80000000+.Lioint -.Lwaitpsw: - .long 0x020a0000,0x80000000+.Lioint - - .align 8 -.Lccws: .rept 19 - .long 0x02600050,0x00000000 - .endr - .long 0x02200050,0x00000000 -#endif /* CONFIG_IPL_VM */ - -iplstart: - lh %r1,0xb8 # test if subchannel number - bct %r1,.Lnoload # is valid - l %r1,0xb8 # load ipl subchannel number - la %r2,IPL_BS # load start address - bas %r14,.Lloader # load rest of ipl image - larl %r12,_pstart # pointer to parameter area - st %r1,IPL_DEVICE+4-PARMAREA(%r12) # store ipl device number - -# -# load parameter file from ipl device # -.Lagain1: - l %r2,INITRD_START+4-PARMAREA(%r12)# use ramdisk location as temp - bas %r14,.Lloader # load parameter file - ltr %r2,%r2 # got anything ? - bz .Lnopf - chi %r2,895 - bnh .Lnotrunc - la %r2,895 -.Lnotrunc: - l %r4,INITRD_START+4-PARMAREA(%r12) - clc 0(3,%r4),.L_hdr # if it is HDRx - bz .Lagain1 # skip dataset header - clc 0(3,%r4),.L_eof # if it is EOFx - bz .Lagain1 # skip dateset trailer - la %r5,0(%r4,%r2) - lr %r3,%r2 -.Lidebc: - tm 0(%r5),0x80 # high order bit set ? - bo .Ldocv # yes -> convert from EBCDIC - ahi %r5,-1 - bct %r3,.Lidebc - b .Lnocv -.Ldocv: - l %r3,.Lcvtab - tr 0(256,%r4),0(%r3) # convert parameters to ascii - tr 256(256,%r4),0(%r3) - tr 512(256,%r4),0(%r3) - tr 768(122,%r4),0(%r3) -.Lnocv: la %r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line - mvc 0(256,%r3),0(%r4) - mvc 256(256,%r3),256(%r4) - mvc 512(256,%r3),512(%r4) - mvc 768(122,%r3),768(%r4) - slr %r0,%r0 - b .Lcntlp -.Ldelspc: - ic %r0,0(%r2,%r3) - chi %r0,0x20 # is it a space ? - be .Lcntlp - ahi %r2,1 - b .Leolp -.Lcntlp: - brct %r2,.Ldelspc -.Leolp: - slr %r0,%r0 - stc %r0,0(%r2,%r3) # terminate buffer -.Lnopf: - -# -# load ramdisk from ipl device -# -.Lagain2: - l %r2,INITRD_START+4-PARMAREA(%r12)# load adr. of ramdisk - bas %r14,.Lloader # load ramdisk - st %r2,INITRD_SIZE+4-PARMAREA(%r12) # store size of ramdisk - ltr %r2,%r2 - bnz .Lrdcont - st %r2,INITRD_START+4-PARMAREA(%r12)# no ramdisk found, null it -.Lrdcont: - l %r2,INITRD_START+4-PARMAREA(%r12) - clc 0(3,%r2),.L_hdr # skip HDRx and EOFx - bz .Lagain2 - clc 0(3,%r2),.L_eof - bz .Lagain2 - -#ifdef CONFIG_IPL_VM -# -# reset files in VM reader -# - stidp __LC_CPUID # store cpuid - tm __LC_CPUID,0xff # running VM ? - bno .Lnoreset - la %r2,.Lreset - lhi %r3,26 - diag %r2,%r3,8 - la %r5,.Lirb - stsch 0(%r5) # check if irq is pending - tm 30(%r5),0x0f # by verifying if any of the - bnz .Lwaitforirq # activity or status control - tm 31(%r5),0xff # bits is set in the schib - bz .Lnoreset -.Lwaitforirq: - mvc 0x78(8),.Lrdrnewpsw # set up IO interrupt psw -.Lwaitrdrirq: - lpsw .Lrdrwaitpsw -.Lrdrint: - c %r1,0xb8 # compare subchannel number - bne .Lwaitrdrirq - la %r5,.Lirb - tsch 0(%r5) -.Lnoreset: - b .Lnoload - - .align 8 -.Lrdrnewpsw: - .long 0x00080000,0x80000000+.Lrdrint -.Lrdrwaitpsw: - .long 0x020a0000,0x80000000+.Lrdrint -#endif - -# -# everything loaded, go for it -# -.Lnoload: - l %r1,.Lstartup - br %r1 - -.Lstartup: .long startup -.Lcvtab:.long _ebcasc # ebcdic to ascii table -.Lreset:.byte 0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40 - .byte 0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6 - .byte 0xc8,0xd6,0xd3,0xc4 # "change rdr all keep nohold" -.L_eof: .long 0xc5d6c600 /* C'EOF' */ -.L_hdr: .long 0xc8c4d900 /* C'HDR' */ -#endif /* CONFIG_IPL */ - -# -# SALIPL loader support. Based on a patch by Rob van der Heij. -# This entry point is called directly from the SALIPL loader and -# doesn't need a builtin ipl record. -# - .org 0x800 - .globl start -start: - stm %r0,%r15,0x07b0 # store registers - basr %r12,%r0 -.base: - l %r11,.parm - l %r8,.cmd # pointer to command buffer - - ltr %r9,%r9 # do we have SALIPL parameters? - bp .sk8x8 - - mvc 0(64,%r8),0x00b0 # copy saved registers - xc 64(240-64,%r8),0(%r8) # remainder of buffer - tr 0(64,%r8),.lowcase - b .gotr -.sk8x8: - mvc 0(240,%r8),0(%r9) # copy iplparms into buffer -.gotr: - l %r10,.tbl # EBCDIC to ASCII table - tr 0(240,%r8),0(%r10) - stidp __LC_CPUID # Are we running on VM maybe - cli __LC_CPUID,0xff - bnz .test - .long 0x83300060 # diag 3,0,x'0060' - storage size - b .done -.test: - mvc 0x68(8),.pgmnw # set up pgm check handler - l %r2,.fourmeg - lr %r3,%r2 - bctr %r3,%r0 # 4M-1 -.loop: iske %r0,%r3 - ar %r3,%r2 -.pgmx: - sr %r3,%r2 - la %r3,1(%r3) -.done: - l %r1,.memsize - st %r3,4(%r1) - slr %r0,%r0 - st %r0,INITRD_SIZE+4-PARMAREA(%r11) - st %r0,INITRD_START+4-PARMAREA(%r11) - j startup # continue with startup -.tbl: .long _ebcasc # translate table -.cmd: .long COMMAND_LINE # address of command line buffer -.parm: .long PARMAREA -.fourmeg: .long 0x00400000 # 4M -.pgmnw: .long 0x00080000,.pgmx -.memsize: .long memory_size -.lowcase: - .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 - .byte 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f - .byte 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 - .byte 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f - .byte 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 - .byte 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f - .byte 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37 - .byte 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f - .byte 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47 - .byte 0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f - .byte 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57 - .byte 0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f - .byte 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67 - .byte 0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f - .byte 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77 - .byte 0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f - - .byte 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87 - .byte 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f - .byte 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97 - .byte 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f - .byte 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7 - .byte 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf - .byte 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7 - .byte 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf - .byte 0xc0,0x81,0x82,0x83,0x84,0x85,0x86,0x87 # .abcdefg - .byte 0x88,0x89,0xca,0xcb,0xcc,0xcd,0xce,0xcf # hi - .byte 0xd0,0x91,0x92,0x93,0x94,0x95,0x96,0x97 # .jklmnop - .byte 0x98,0x99,0xda,0xdb,0xdc,0xdd,0xde,0xdf # qr - .byte 0xe0,0xe1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7 # ..stuvwx - .byte 0xa8,0xa9,0xea,0xeb,0xec,0xed,0xee,0xef # yz - .byte 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7 - .byte 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff - -# -# startup-code at 0x10000, running in real mode +# startup-code at 0x10000, running in absolute addressing mode # this is called either by the ipl loader or directly by PSW restart # or linload or SALIPL # @@ -750,62 +285,7 @@ _pstart: .global _pend _pend: -.Lget_ipl_device: - basr %r12,0 -.LPG2: l %r1,0xb8 # get sid - sll %r1,15 # test if subchannel is enabled - srl %r1,31 - ltr %r1,%r1 - bz 0(%r14) # subchannel disabled - l %r1,0xb8 - la %r5,.Lipl_schib-.LPG2(%r12) - stsch 0(%r5) # get schib of subchannel - bnz 0(%r14) # schib not available - tm 5(%r5),0x01 # devno valid? - bno 0(%r14) - la %r6,ipl_parameter_flags-.LPG2(%r12) - oi 3(%r6),0x01 # set flag - la %r2,ipl_devno-.LPG2(%r12) - mvc 0(2,%r2),6(%r5) # store devno - tm 4(%r5),0x80 # qdio capable device? - bno 0(%r14) - oi 3(%r6),0x02 # set flag - - # copy ipl parameters - - lhi %r0,4096 - l %r2,20(%r0) # get address of parameter list - lhi %r3,IPL_PARMBLOCK_ORIGIN - st %r3,20(%r0) - lhi %r4,1 - cr %r2,%r3 # start parameters < destination ? - jl 0f - lhi %r1,1 # copy direction is upwards - j 1f -0: lhi %r1,-1 # copy direction is downwards - ar %r2,%r0 - ar %r3,%r0 - ar %r2,%r1 - ar %r3,%r1 -1: mvc 0(1,%r3),0(%r2) # finally copy ipl parameters - ar %r3,%r1 - ar %r2,%r1 - sr %r0,%r4 - jne 1b - b 0(%r14) - - .align 4 -.Lipl_schib: - .rept 13 - .long 0 - .endr - - .globl ipl_parameter_flags -ipl_parameter_flags: - .long 0 - .globl ipl_devno -ipl_devno: - .word 0 + GET_IPL_DEVICE #ifdef CONFIG_SHARED_KERNEL .org 0x100000 -- cgit v1.2.3 From 78512ece148992a5c00c63fbf4404f3cde635016 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 7 Nov 2005 00:59:13 -0800 Subject: [PATCH] serial console: touch NMI watchdog Large console spews from IRQ or local_irq_disable() sections can cause the NMI watchdog to go off. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/8250.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 186e96c47b3..98820603e75 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -2208,6 +2209,8 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) unsigned int ier; int i; + touch_nmi_watchdog(); + /* * First save the UER then disable the interrupts */ -- cgit v1.2.3 From cd6b0762a04978baf48412456a687842de97e381 Mon Sep 17 00:00:00 2001 From: Prasanna S Panchamukhi Date: Mon, 7 Nov 2005 00:59:14 -0800 Subject: [PATCH] Move Kprobes and Oprofile to "Instrumentation Support" menu Andrew Morton suggested to move kprobes from kernel hacking menu, since kernel hacking menu is in-appropriate for the Kprobes. This patch moves Kprobes and Oprofile under instrumentation menu. (akpm: it's not a natural fit, but things like djprobes and the s390 guys' statistics library need a home) Signed-of-by: Prasanna S Panchamukhi Cc: Philippe Elie Cc: John Levon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/Kconfig | 13 +++++++++++++ arch/i386/Kconfig.debug | 10 ---------- arch/i386/oprofile/Kconfig | 6 ------ arch/ia64/Kconfig | 13 +++++++++++++ arch/ia64/Kconfig.debug | 11 ----------- arch/ia64/oprofile/Kconfig | 6 ------ arch/powerpc/Kconfig | 13 +++++++++++++ arch/powerpc/Kconfig.debug | 10 ---------- arch/powerpc/oprofile/Kconfig | 6 ------ arch/sparc64/Kconfig | 13 +++++++++++++ arch/sparc64/Kconfig.debug | 10 ---------- arch/sparc64/oprofile/Kconfig | 6 ------ arch/x86_64/Kconfig | 13 +++++++++++++ arch/x86_64/Kconfig.debug | 10 ---------- arch/x86_64/oprofile/Kconfig | 6 ------ 15 files changed, 65 insertions(+), 81 deletions(-) diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index bac0da731ee..dbf90ad6eac 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -997,8 +997,21 @@ source "drivers/Kconfig" source "fs/Kconfig" +menu "Instrumentation Support" + depends on EXPERIMENTAL + source "arch/i386/oprofile/Kconfig" +config KPROBES + bool "Kprobes (EXPERIMENTAL)" + help + Kprobes allows you to trap at almost any kernel address and + execute a callback function. register_kprobe() establishes + a probepoint and specifies the callback. Kprobes is useful + for kernel debugging, non-intrusive instrumentation and testing. + If in doubt, say "N". +endmenu + source "arch/i386/Kconfig.debug" source "security/Kconfig" diff --git a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug index 5228c40a6fb..c48b424dd64 100644 --- a/arch/i386/Kconfig.debug +++ b/arch/i386/Kconfig.debug @@ -22,16 +22,6 @@ config DEBUG_STACKOVERFLOW This option will cause messages to be printed if free stack space drops below a certain limit. -config KPROBES - bool "Kprobes" - depends on DEBUG_KERNEL - help - Kprobes allows you to trap at almost any kernel address and - execute a callback function. register_kprobe() establishes - a probepoint and specifies the callback. Kprobes is useful - for kernel debugging, non-intrusive instrumentation and testing. - If in doubt, say "N". - config DEBUG_STACK_USAGE bool "Stack utilization instrumentation" depends on DEBUG_KERNEL diff --git a/arch/i386/oprofile/Kconfig b/arch/i386/oprofile/Kconfig index 5ade19801b9..d8a84088471 100644 --- a/arch/i386/oprofile/Kconfig +++ b/arch/i386/oprofile/Kconfig @@ -1,7 +1,3 @@ - -menu "Profiling support" - depends on EXPERIMENTAL - config PROFILING bool "Profiling support (EXPERIMENTAL)" help @@ -19,5 +15,3 @@ config OPROFILE If unsure, say N. -endmenu - diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 3b4248cff9a..9f2093c1f44 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -426,8 +426,21 @@ config GENERIC_PENDING_IRQ source "arch/ia64/hp/sim/Kconfig" +menu "Instrumentation Support" + depends on EXPERIMENTAL + source "arch/ia64/oprofile/Kconfig" +config KPROBES + bool "Kprobes (EXPERIMENTAL)" + help + Kprobes allows you to trap at almost any kernel address and + execute a callback function. register_kprobe() establishes + a probepoint and specifies the callback. Kprobes is useful + for kernel debugging, non-intrusive instrumentation and testing. + If in doubt, say "N". +endmenu + source "arch/ia64/Kconfig.debug" source "security/Kconfig" diff --git a/arch/ia64/Kconfig.debug b/arch/ia64/Kconfig.debug index fda67ac993d..de9d507ba0f 100644 --- a/arch/ia64/Kconfig.debug +++ b/arch/ia64/Kconfig.debug @@ -2,17 +2,6 @@ menu "Kernel hacking" source "lib/Kconfig.debug" -config KPROBES - bool "Kprobes" - depends on DEBUG_KERNEL - help - Kprobes allows you to trap at almost any kernel address and - execute a callback function. register_kprobe() establishes - a probepoint and specifies the callback. Kprobes is useful - for kernel debugging, non-intrusive instrumentation and testing. - If in doubt, say "N". - - choice prompt "Physical memory granularity" default IA64_GRANULE_64MB diff --git a/arch/ia64/oprofile/Kconfig b/arch/ia64/oprofile/Kconfig index 56e6f614b04..97271ab484d 100644 --- a/arch/ia64/oprofile/Kconfig +++ b/arch/ia64/oprofile/Kconfig @@ -1,7 +1,3 @@ - -menu "Profiling support" - depends on EXPERIMENTAL - config PROFILING bool "Profiling support (EXPERIMENTAL)" help @@ -22,5 +18,3 @@ config OPROFILE If unsure, say N. -endmenu - diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 55ce4957052..6ffae2d2b3f 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -917,8 +917,21 @@ source "arch/powerpc/platforms/iseries/Kconfig" source "lib/Kconfig" +menu "Instrumentation Support" + depends on EXPERIMENTAL + source "arch/powerpc/oprofile/Kconfig" +config KPROBES + bool "Kprobes (EXPERIMENTAL)" + help + Kprobes allows you to trap at almost any kernel address and + execute a callback function. register_kprobe() establishes + a probepoint and specifies the callback. Kprobes is useful + for kernel debugging, non-intrusive instrumentation and testing. + If in doubt, say "N". +endmenu + source "arch/powerpc/Kconfig.debug" source "security/Kconfig" diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index 0baf64ec80d..30a30bf559e 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -9,16 +9,6 @@ config DEBUG_STACKOVERFLOW This option will cause messages to be printed if free stack space drops below a certain limit. -config KPROBES - bool "Kprobes" - depends on DEBUG_KERNEL && PPC64 - help - Kprobes allows you to trap at almost any kernel address and - execute a callback function. register_kprobe() establishes - a probepoint and specifies the callback. Kprobes is useful - for kernel debugging, non-intrusive instrumentation and testing. - If in doubt, say "N". - config DEBUG_STACK_USAGE bool "Stack utilization instrumentation" depends on DEBUG_KERNEL && PPC64 diff --git a/arch/powerpc/oprofile/Kconfig b/arch/powerpc/oprofile/Kconfig index 19d37730b66..eb2dece76a5 100644 --- a/arch/powerpc/oprofile/Kconfig +++ b/arch/powerpc/oprofile/Kconfig @@ -1,7 +1,3 @@ - -menu "Profiling support" - depends on EXPERIMENTAL - config PROFILING bool "Profiling support (EXPERIMENTAL)" help @@ -19,5 +15,3 @@ config OPROFILE If unsure, say N. -endmenu - diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index 1e9d8638a28..3fded69b192 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -377,8 +377,21 @@ source "drivers/fc4/Kconfig" source "fs/Kconfig" +menu "Instrumentation Support" + depends on EXPERIMENTAL + source "arch/sparc64/oprofile/Kconfig" +config KPROBES + bool "Kprobes (EXPERIMENTAL)" + help + Kprobes allows you to trap at almost any kernel address and + execute a callback function. register_kprobe() establishes + a probepoint and specifies the callback. Kprobes is useful + for kernel debugging, non-intrusive instrumentation and testing. + If in doubt, say "N". +endmenu + source "arch/sparc64/Kconfig.debug" source "security/Kconfig" diff --git a/arch/sparc64/Kconfig.debug b/arch/sparc64/Kconfig.debug index fa06ea04837..3e31be494e5 100644 --- a/arch/sparc64/Kconfig.debug +++ b/arch/sparc64/Kconfig.debug @@ -11,16 +11,6 @@ config DEBUG_STACK_USAGE This option will slow down process creation somewhat. -config KPROBES - bool "Kprobes" - depends on DEBUG_KERNEL - help - Kprobes allows you to trap at almost any kernel address and - execute a callback function. register_kprobe() establishes - a probepoint and specifies the callback. Kprobes is useful - for kernel debugging, non-intrusive instrumentation and testing. - If in doubt, say "N". - config DEBUG_DCFLUSH bool "D-cache flush debugging" depends on DEBUG_KERNEL diff --git a/arch/sparc64/oprofile/Kconfig b/arch/sparc64/oprofile/Kconfig index 5ade19801b9..d8a84088471 100644 --- a/arch/sparc64/oprofile/Kconfig +++ b/arch/sparc64/oprofile/Kconfig @@ -1,7 +1,3 @@ - -menu "Profiling support" - depends on EXPERIMENTAL - config PROFILING bool "Profiling support (EXPERIMENTAL)" help @@ -19,5 +15,3 @@ config OPROFILE If unsure, say N. -endmenu - diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 21afa69a086..4cce2f6f170 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -532,8 +532,21 @@ source "drivers/firmware/Kconfig" source fs/Kconfig +menu "Instrumentation Support" + depends on EXPERIMENTAL + source "arch/x86_64/oprofile/Kconfig" +config KPROBES + bool "Kprobes (EXPERIMENTAL)" + help + Kprobes allows you to trap at almost any kernel address and + execute a callback function. register_kprobe() establishes + a probepoint and specifies the callback. Kprobes is useful + for kernel debugging, non-intrusive instrumentation and testing. + If in doubt, say "N". +endmenu + source "arch/x86_64/Kconfig.debug" source "security/Kconfig" diff --git a/arch/x86_64/Kconfig.debug b/arch/x86_64/Kconfig.debug index 9cf1410d2f5..d584ecc27ea 100644 --- a/arch/x86_64/Kconfig.debug +++ b/arch/x86_64/Kconfig.debug @@ -33,16 +33,6 @@ config IOMMU_DEBUG options. See Documentation/x86_64/boot-options.txt for more details. -config KPROBES - bool "Kprobes" - depends on DEBUG_KERNEL - help - Kprobes allows you to trap at almost any kernel address and - execute a callback function. register_kprobe() establishes - a probepoint and specifies the callback. Kprobes is useful - for kernel debugging, non-intrusive instrumentation and testing. - If in doubt, say "N". - config IOMMU_LEAK bool "IOMMU leak tracing" depends on DEBUG_KERNEL diff --git a/arch/x86_64/oprofile/Kconfig b/arch/x86_64/oprofile/Kconfig index 5ade19801b9..d8a84088471 100644 --- a/arch/x86_64/oprofile/Kconfig +++ b/arch/x86_64/oprofile/Kconfig @@ -1,7 +1,3 @@ - -menu "Profiling support" - depends on EXPERIMENTAL - config PROFILING bool "Profiling support (EXPERIMENTAL)" help @@ -19,5 +15,3 @@ config OPROFILE If unsure, say N. -endmenu - -- cgit v1.2.3 From 49364ce2534418462d681ad99e52e79a00b0f40b Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 7 Nov 2005 00:59:15 -0800 Subject: [PATCH] write_inode_now(): write inode if not BDI_CAP_NO_WRITEBACK If the backing_dev_info doesn't have BDI_CAP_NO_WRITEBACK we're not supposed to write back an inode's pages. But in this situation write_inode_now() refuses to write the inode itself as well. Fix. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fs-writeback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index c27f8d4098b..1361a4a6415 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -562,7 +562,7 @@ int write_inode_now(struct inode *inode, int sync) }; if (!mapping_cap_writeback_dirty(inode->i_mapping)) - return 0; + wbc.nr_to_write = 0; might_sleep(); spin_lock(&inode_lock); -- cgit v1.2.3 From 9f46080c41d5f3f7c00b4e169ba4b0b2865258bf Mon Sep 17 00:00:00 2001 From: Matt Helsley Date: Mon, 7 Nov 2005 00:59:16 -0800 Subject: [PATCH] Process Events Connector This patch adds a connector that reports fork, exec, id change, and exit events for all processes to userspace. It replaces the fork_advisor patch that ELSA is currently using. Applications that may find these events useful include accounting/auditing (e.g. ELSA), system activity monitoring (e.g. top), security, and resource management (e.g. CKRM). Signed-off-by: Matt Helsley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/connector/Kconfig | 8 ++ drivers/connector/Makefile | 1 + drivers/connector/cn_proc.c | 222 ++++++++++++++++++++++++++++++++++++++++++++ fs/exec.c | 2 + include/linux/cn_proc.h | 127 +++++++++++++++++++++++++ include/linux/connector.h | 6 ++ kernel/exit.c | 2 + kernel/fork.c | 2 + kernel/sys.c | 9 ++ 9 files changed, 379 insertions(+) create mode 100644 drivers/connector/cn_proc.c create mode 100644 include/linux/cn_proc.h diff --git a/drivers/connector/Kconfig b/drivers/connector/Kconfig index 0bc2059c1e0..e0bdc0db964 100644 --- a/drivers/connector/Kconfig +++ b/drivers/connector/Kconfig @@ -10,4 +10,12 @@ config CONNECTOR Connector support can also be built as a module. If so, the module will be called cn.ko. +config PROC_EVENTS + boolean "Report process events to userspace" + depends on CONNECTOR=y + default y + ---help--- + Provide a connector that reports process events to userspace. Send + events such as fork, exec, id change (uid, gid, suid, etc), and exit. + endmenu diff --git a/drivers/connector/Makefile b/drivers/connector/Makefile index 12ca79e8234..1f255e46e91 100644 --- a/drivers/connector/Makefile +++ b/drivers/connector/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_CONNECTOR) += cn.o +obj-$(CONFIG_PROC_EVENTS) += cn_proc.o cn-y += cn_queue.o connector.o diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c new file mode 100644 index 00000000000..fcdf0fff13a --- /dev/null +++ b/drivers/connector/cn_proc.c @@ -0,0 +1,222 @@ +/* + * cn_proc.c - process events connector + * + * Copyright (C) Matt Helsley, IBM Corp. 2005 + * Based on cn_fork.c by Guillaume Thouvenin + * Original copyright notice follows: + * Copyright (C) 2005 BULL SA. + * + * + * 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 option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include + +#define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event)) + +static atomic_t proc_event_num_listeners = ATOMIC_INIT(0); +static struct cb_id cn_proc_event_id = { CN_IDX_PROC, CN_VAL_PROC }; + +/* proc_counts is used as the sequence number of the netlink message */ +static DEFINE_PER_CPU(__u32, proc_event_counts) = { 0 }; + +static inline void get_seq(__u32 *ts, int *cpu) +{ + *ts = get_cpu_var(proc_event_counts)++; + *cpu = smp_processor_id(); + put_cpu_var(proc_counts); +} + +void proc_fork_connector(struct task_struct *task) +{ + struct cn_msg *msg; + struct proc_event *ev; + __u8 buffer[CN_PROC_MSG_SIZE]; + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + + msg = (struct cn_msg*)buffer; + ev = (struct proc_event*)msg->data; + get_seq(&msg->seq, &ev->cpu); + ev->what = PROC_EVENT_FORK; + ev->event_data.fork.parent_pid = task->real_parent->pid; + ev->event_data.fork.parent_tgid = task->real_parent->tgid; + ev->event_data.fork.child_pid = task->pid; + ev->event_data.fork.child_tgid = task->tgid; + + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = 0; /* not used */ + msg->len = sizeof(*ev); + /* If cn_netlink_send() failed, the data is not sent */ + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); +} + +void proc_exec_connector(struct task_struct *task) +{ + struct cn_msg *msg; + struct proc_event *ev; + __u8 buffer[CN_PROC_MSG_SIZE]; + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + + msg = (struct cn_msg*)buffer; + ev = (struct proc_event*)msg->data; + get_seq(&msg->seq, &ev->cpu); + ev->what = PROC_EVENT_EXEC; + ev->event_data.exec.process_pid = task->pid; + ev->event_data.exec.process_tgid = task->tgid; + + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = 0; /* not used */ + msg->len = sizeof(*ev); + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); +} + +void proc_id_connector(struct task_struct *task, int which_id) +{ + struct cn_msg *msg; + struct proc_event *ev; + __u8 buffer[CN_PROC_MSG_SIZE]; + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + + msg = (struct cn_msg*)buffer; + ev = (struct proc_event*)msg->data; + ev->what = which_id; + ev->event_data.id.process_pid = task->pid; + ev->event_data.id.process_tgid = task->tgid; + if (which_id == PROC_EVENT_UID) { + ev->event_data.id.r.ruid = task->uid; + ev->event_data.id.e.euid = task->euid; + } else if (which_id == PROC_EVENT_GID) { + ev->event_data.id.r.rgid = task->gid; + ev->event_data.id.e.egid = task->egid; + } else + return; + get_seq(&msg->seq, &ev->cpu); + + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = 0; /* not used */ + msg->len = sizeof(*ev); + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); +} + +void proc_exit_connector(struct task_struct *task) +{ + struct cn_msg *msg; + struct proc_event *ev; + __u8 buffer[CN_PROC_MSG_SIZE]; + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + + msg = (struct cn_msg*)buffer; + ev = (struct proc_event*)msg->data; + get_seq(&msg->seq, &ev->cpu); + ev->what = PROC_EVENT_EXIT; + ev->event_data.exit.process_pid = task->pid; + ev->event_data.exit.process_tgid = task->tgid; + ev->event_data.exit.exit_code = task->exit_code; + ev->event_data.exit.exit_signal = task->exit_signal; + + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = 0; /* not used */ + msg->len = sizeof(*ev); + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); +} + +/* + * Send an acknowledgement message to userspace + * + * Use 0 for success, EFOO otherwise. + * Note: this is the negative of conventional kernel error + * values because it's not being returned via syscall return + * mechanisms. + */ +static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) +{ + struct cn_msg *msg; + struct proc_event *ev; + __u8 buffer[CN_PROC_MSG_SIZE]; + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + + msg = (struct cn_msg*)buffer; + ev = (struct proc_event*)msg->data; + msg->seq = rcvd_seq; + ev->cpu = -1; + ev->what = PROC_EVENT_NONE; + ev->event_data.ack.err = err; + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = rcvd_ack + 1; + msg->len = sizeof(*ev); + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); +} + +/** + * cn_proc_mcast_ctl + * @data: message sent from userspace via the connector + */ +static void cn_proc_mcast_ctl(void *data) +{ + struct cn_msg *msg = data; + enum proc_cn_mcast_op *mc_op = NULL; + int err = 0; + + if (msg->len != sizeof(*mc_op)) + return; + + mc_op = (enum proc_cn_mcast_op*)msg->data; + switch (*mc_op) { + case PROC_CN_MCAST_LISTEN: + atomic_inc(&proc_event_num_listeners); + break; + case PROC_CN_MCAST_IGNORE: + atomic_dec(&proc_event_num_listeners); + break; + default: + err = EINVAL; + break; + } + cn_proc_ack(err, msg->seq, msg->ack); +} + +/* + * cn_proc_init - initialization entry point + * + * Adds the connector callback to the connector driver. + */ +static int __init cn_proc_init(void) +{ + int err; + + if ((err = cn_add_callback(&cn_proc_event_id, "cn_proc", + &cn_proc_mcast_ctl))) { + printk(KERN_WARNING "cn_proc failed to register\n"); + return err; + } + return 0; +} + +module_init(cn_proc_init); diff --git a/fs/exec.c b/fs/exec.c index 10d493fea7c..ce76b33f25a 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -1096,6 +1097,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) fput(bprm->file); bprm->file = NULL; current->did_exec = 1; + proc_exec_connector(current); return retval; } read_lock(&binfmt_lock); diff --git a/include/linux/cn_proc.h b/include/linux/cn_proc.h new file mode 100644 index 00000000000..70ab5631738 --- /dev/null +++ b/include/linux/cn_proc.h @@ -0,0 +1,127 @@ +/* + * cn_proc.h - process events connector + * + * Copyright (C) Matt Helsley, IBM Corp. 2005 + * Based on cn_fork.h by Nguyen Anh Quynh and Guillaume Thouvenin + * Original copyright notice follows: + * Copyright (C) 2005 Nguyen Anh Quynh + * Copyright (C) 2005 Guillaume Thouvenin + * + * 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 option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef CN_PROC_H +#define CN_PROC_H + +#include +#include + +/* + * Userspace sends this enum to register with the kernel that it is listening + * for events on the connector. + */ +enum proc_cn_mcast_op { + PROC_CN_MCAST_LISTEN = 1, + PROC_CN_MCAST_IGNORE = 2 +}; + +/* + * From the user's point of view, the process + * ID is the thread group ID and thread ID is the internal + * kernel "pid". So, fields are assigned as follow: + * + * In user space - In kernel space + * + * parent process ID = parent->tgid + * parent thread ID = parent->pid + * child process ID = child->tgid + * child thread ID = child->pid + */ + +struct proc_event { + enum what { + /* Use successive bits so the enums can be used to record + * sets of events as well + */ + PROC_EVENT_NONE = 0x00000000, + PROC_EVENT_FORK = 0x00000001, + PROC_EVENT_EXEC = 0x00000002, + PROC_EVENT_UID = 0x00000004, + PROC_EVENT_GID = 0x00000040, + /* "next" should be 0x00000400 */ + /* "last" is the last process event: exit */ + PROC_EVENT_EXIT = 0x80000000 + } what; + __u32 cpu; + union { /* must be last field of proc_event struct */ + struct { + __u32 err; + } ack; + + struct fork_proc_event { + pid_t parent_pid; + pid_t parent_tgid; + pid_t child_pid; + pid_t child_tgid; + } fork; + + struct exec_proc_event { + pid_t process_pid; + pid_t process_tgid; + } exec; + + struct id_proc_event { + pid_t process_pid; + pid_t process_tgid; + union { + uid_t ruid; /* current->uid */ + gid_t rgid; /* current->gid */ + } r; + union { + uid_t euid; + gid_t egid; + } e; + } id; + + struct exit_proc_event { + pid_t process_pid; + pid_t process_tgid; + __u32 exit_code, exit_signal; + } exit; + } event_data; +}; + +#ifdef __KERNEL__ +#ifdef CONFIG_PROC_EVENTS +void proc_fork_connector(struct task_struct *task); +void proc_exec_connector(struct task_struct *task); +void proc_id_connector(struct task_struct *task, int which_id); +void proc_exit_connector(struct task_struct *task); +#else +static inline void proc_fork_connector(struct task_struct *task) +{} + +static inline void proc_exec_connector(struct task_struct *task) +{} + +static inline void proc_id_connector(struct task_struct *task, + int which_id) +{} + +static inline void proc_exit_connector(struct task_struct *task) +{} +#endif /* CONFIG_PROC_EVENTS */ +#endif /* __KERNEL__ */ +#endif /* CN_PROC_H */ diff --git a/include/linux/connector.h b/include/linux/connector.h index 95952cc1f52..c5769c6585f 100644 --- a/include/linux/connector.h +++ b/include/linux/connector.h @@ -27,6 +27,12 @@ #define CN_IDX_CONNECTOR 0xffffffff #define CN_VAL_CONNECTOR 0xffffffff +/* + * Process Events connector unique ids -- used for message routing + */ +#define CN_IDX_PROC 0x1 +#define CN_VAL_PROC 0x1 + #define CN_NETLINK_USERS 1 /* diff --git a/kernel/exit.c b/kernel/exit.c index 537394b25e8..452a1d11617 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -863,6 +864,7 @@ fastcall NORET_TYPE void do_exit(long code) module_put(tsk->binfmt->module); tsk->exit_code = code; + proc_exit_connector(tsk); exit_notify(tsk); #ifdef CONFIG_NUMA mpol_free(tsk->mempolicy); diff --git a/kernel/fork.c b/kernel/fork.c index 8a069612eac..efac2c58ec7 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -1143,6 +1144,7 @@ static task_t *copy_process(unsigned long clone_flags, __get_cpu_var(process_counts)++; } + proc_fork_connector(p); if (!current->signal->tty && p->signal->tty) p->signal->tty = NULL; diff --git a/kernel/sys.c b/kernel/sys.c index 2fa1ed18123..1e1f41b3fdf 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -623,6 +624,7 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid) current->egid = new_egid; current->gid = new_rgid; key_fsgid_changed(current); + proc_id_connector(current, PROC_EVENT_GID); return 0; } @@ -662,6 +664,7 @@ asmlinkage long sys_setgid(gid_t gid) return -EPERM; key_fsgid_changed(current); + proc_id_connector(current, PROC_EVENT_GID); return 0; } @@ -751,6 +754,7 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid) current->fsuid = current->euid; key_fsuid_changed(current); + proc_id_connector(current, PROC_EVENT_UID); return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RE); } @@ -798,6 +802,7 @@ asmlinkage long sys_setuid(uid_t uid) current->suid = new_suid; key_fsuid_changed(current); + proc_id_connector(current, PROC_EVENT_UID); return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID); } @@ -846,6 +851,7 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) current->suid = suid; key_fsuid_changed(current); + proc_id_connector(current, PROC_EVENT_UID); return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RES); } @@ -898,6 +904,7 @@ asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid) current->sgid = sgid; key_fsgid_changed(current); + proc_id_connector(current, PROC_EVENT_GID); return 0; } @@ -940,6 +947,7 @@ asmlinkage long sys_setfsuid(uid_t uid) } key_fsuid_changed(current); + proc_id_connector(current, PROC_EVENT_UID); security_task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS); @@ -968,6 +976,7 @@ asmlinkage long sys_setfsgid(gid_t gid) } current->fsgid = gid; key_fsgid_changed(current); + proc_id_connector(current, PROC_EVENT_GID); } return old_fsgid; } -- cgit v1.2.3 From 665a7583f32ab5b3bfe7a4d88da506542f7cdd75 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 7 Nov 2005 00:59:17 -0800 Subject: [PATCH] Remove hlist_for_each_rcu() API, convert existing use to hlist_for_each_entry_rcu Remove the hlist_for_each_rcu() API, which is used only in one place, and is trivially converted to hlist_for_each_entry_rcu(), making the code shorter and more readable. Any out-of-tree uses may be similarly converted. Signed-off-by: "Paul E. McKenney" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/RCU/whatisRCU.txt | 2 -- fs/dcache.c | 10 ++++------ include/linux/list.h | 13 ++++--------- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt index 354d89c7837..15da16861fa 100644 --- a/Documentation/RCU/whatisRCU.txt +++ b/Documentation/RCU/whatisRCU.txt @@ -772,8 +772,6 @@ RCU pointer/list traversal: list_for_each_entry_rcu list_for_each_continue_rcu (to be deprecated in favor of new list_for_each_entry_continue_rcu) - hlist_for_each_rcu (to be deprecated in favor of - hlist_for_each_entry_rcu) hlist_for_each_entry_rcu RCU pointer update: diff --git a/fs/dcache.c b/fs/dcache.c index e90512ed35a..17e43913868 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -644,7 +644,7 @@ void shrink_dcache_parent(struct dentry * parent) * * Prune the dentries that are anonymous * - * parsing d_hash list does not hlist_for_each_rcu() as it + * parsing d_hash list does not hlist_for_each_entry_rcu() as it * done under dcache_lock. * */ @@ -1043,15 +1043,13 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name) struct hlist_head *head = d_hash(parent,hash); struct dentry *found = NULL; struct hlist_node *node; + struct dentry *dentry; rcu_read_lock(); - hlist_for_each_rcu(node, head) { - struct dentry *dentry; + hlist_for_each_entry_rcu(dentry, node, head, d_hash) { struct qstr *qstr; - dentry = hlist_entry(node, struct dentry, d_hash); - if (dentry->d_name.hash != hash) continue; if (dentry->d_parent != parent) @@ -1123,7 +1121,7 @@ int d_validate(struct dentry *dentry, struct dentry *dparent) spin_lock(&dcache_lock); base = d_hash(dparent, dentry->d_name.hash); hlist_for_each(lhp,base) { - /* hlist_for_each_rcu() not required for d_hash list + /* hlist_for_each_entry_rcu() not required for d_hash list * as it is parsed under dcache_lock */ if (dentry == hlist_entry(lhp, struct dentry, d_hash)) { diff --git a/include/linux/list.h b/include/linux/list.h index 084971f333f..fbfca73355a 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -601,7 +601,7 @@ static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) * or hlist_del_rcu(), running on this same list. * However, it is perfectly legal to run concurrently with * the _rcu list-traversal primitives, such as - * hlist_for_each_rcu(), used to prevent memory-consistency + * hlist_for_each_entry_rcu(), used to prevent memory-consistency * problems on Alpha CPUs. Regardless of the type of CPU, the * list-traversal primitive must be guarded by rcu_read_lock(). */ @@ -650,7 +650,7 @@ static inline void hlist_add_after(struct hlist_node *n, * or hlist_del_rcu(), running on this same list. * However, it is perfectly legal to run concurrently with * the _rcu list-traversal primitives, such as - * hlist_for_each_rcu(), used to prevent memory-consistency + * hlist_for_each_entry_rcu(), used to prevent memory-consistency * problems on Alpha CPUs. */ static inline void hlist_add_before_rcu(struct hlist_node *n, @@ -675,7 +675,7 @@ static inline void hlist_add_before_rcu(struct hlist_node *n, * or hlist_del_rcu(), running on this same list. * However, it is perfectly legal to run concurrently with * the _rcu list-traversal primitives, such as - * hlist_for_each_rcu(), used to prevent memory-consistency + * hlist_for_each_entry_rcu(), used to prevent memory-consistency * problems on Alpha CPUs. */ static inline void hlist_add_after_rcu(struct hlist_node *prev, @@ -699,11 +699,6 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev, for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ pos = n) -#define hlist_for_each_rcu(pos, head) \ - for ((pos) = (head)->first; \ - rcu_dereference((pos)) && ({ prefetch((pos)->next); 1; }); \ - (pos) = (pos)->next) - /** * hlist_for_each_entry - iterate over list of given type * @tpos: the type * to use as a loop counter. @@ -756,7 +751,7 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev, /** * hlist_for_each_entry_rcu - iterate over rcu list of given type - * @pos: the type * to use as a loop counter. + * @tpos: the type * to use as a loop counter. * @pos: the &struct hlist_node to use as a loop counter. * @head: the head for your list. * @member: the name of the hlist_node within the struct. -- cgit v1.2.3 From 878129a30435920f74346907baeee68a0be147b8 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 7 Nov 2005 00:59:18 -0800 Subject: [PATCH] hfs needs nls Reported by Eddy Petrisor fs/built-in.o(.text+0x35fdc): In function `hfs_mdb_put': : undefined reference to `unload_nls' fs/built-in.o(.text+0x35ff1): In function `hfs_mdb_put': : undefined reference to `unload_nls' fs/built-in.o(.text+0x367a5): In function `parse_options': super.c: undefined reference to `load_nls' fs/built-in.o(.text+0x367db):super.c: undefined reference to `load_nls' fs/built-in.o(.text+0x36938):super.c: undefined reference to `load_nls_default' Signed-off-by: Lennert Buytenhek Acked-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/Kconfig b/fs/Kconfig index 01a295232f7..7cf36ca157f 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -898,6 +898,7 @@ config AFFS_FS config HFS_FS tristate "Apple Macintosh file system support (EXPERIMENTAL)" depends on EXPERIMENTAL + select NLS help If you say Y here, you will be able to mount Macintosh-formatted floppy disks and hard drive partitions with full read-write access. -- cgit v1.2.3 From b9b0332fcf122809b9e40e2f0051eebb295ededf Mon Sep 17 00:00:00 2001 From: Bob Picco Date: Mon, 7 Nov 2005 00:59:19 -0800 Subject: [PATCH] HPET, Maintainers This patch identifies the HPET Maintainers. Clemens in taking over as primary maintainer for the HPET driver. Clemens has i386 hardware with HPET and is a better choice than me because of this. I've shared this patch with all cc: recipients and there is agreement on ownership. Hopefully this eliminates future confusion in terms of where HPET maintenance is owned. Signed-off-by: Bob Picco Cc: Cc: Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index d57c491212b..4cba302c275 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1077,6 +1077,26 @@ P: Jaroslav Kysela M: perex@suse.cz S: Maintained +HPET: High Precision Event Timers driver (hpet.c) +P: Clemens Ladisch +M: clemens@ladisch.de +S: Maintained + +HPET: i386 +P: Venkatesh Pallipadi (Venki) +M: venkatesh.pallipadi@intel.com +S: Maintained + +HPET: x86_64 +P: Andi Kleen and Vojtech Pavlik +M: ak@muc.de and vojtech@suse.cz +S: Maintained + +HPET: ACPI hpet.c +P: Bob Picco +M: bob.picco@hp.com +S: Maintained + HPFS FILESYSTEM P: Mikulas Patocka M: mikulas@artax.karlin.mff.cuni.cz -- cgit v1.2.3 From 57432345b644ef92dcd0a378db6bc40ab0e7f314 Mon Sep 17 00:00:00 2001 From: Kirill Smelkov Date: Mon, 7 Nov 2005 00:59:20 -0800 Subject: [PATCH] serial moxa: cleanup mxser_init Remove explicit tty_driver ops initialisation, because this is already done by tty_set_operations. Signed-off-by: Kirill Smelkov Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/mxser.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 45d012d85e8..4b783d9bbd5 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -470,6 +470,8 @@ static struct tty_operations mxser_ops = { .stop = mxser_stop, .start = mxser_start, .hangup = mxser_hangup, + .break_ctl = mxser_rs_break, + .wait_until_sent = mxser_wait_until_sent, .tiocmget = mxser_tiocmget, .tiocmset = mxser_tiocmset, }; @@ -722,24 +724,6 @@ static int mxser_init(void) mxvar_sdriver->termios = mxvar_termios; mxvar_sdriver->termios_locked = mxvar_termios_locked; - mxvar_sdriver->open = mxser_open; - mxvar_sdriver->close = mxser_close; - mxvar_sdriver->write = mxser_write; - mxvar_sdriver->put_char = mxser_put_char; - mxvar_sdriver->flush_chars = mxser_flush_chars; - mxvar_sdriver->write_room = mxser_write_room; - mxvar_sdriver->chars_in_buffer = mxser_chars_in_buffer; - mxvar_sdriver->flush_buffer = mxser_flush_buffer; - mxvar_sdriver->ioctl = mxser_ioctl; - mxvar_sdriver->throttle = mxser_throttle; - mxvar_sdriver->unthrottle = mxser_unthrottle; - mxvar_sdriver->set_termios = mxser_set_termios; - mxvar_sdriver->stop = mxser_stop; - mxvar_sdriver->start = mxser_start; - mxvar_sdriver->hangup = mxser_hangup; - mxvar_sdriver->break_ctl = mxser_rs_break; - mxvar_sdriver->wait_until_sent = mxser_wait_until_sent; - mxvar_diagflag = 0; memset(mxvar_table, 0, MXSER_PORTS * sizeof(struct mxser_struct)); memset(&mxvar_log, 0, sizeof(struct mxser_log)); -- cgit v1.2.3 From 64698b694db96b8db6f379de7d2040f61c6fc7bf Mon Sep 17 00:00:00 2001 From: Kirill Smelkov Date: Mon, 7 Nov 2005 00:59:22 -0800 Subject: [PATCH] serial moxa: fix leaks of struct tty_driver Fix leak of struct tty_driver in mxser_init & mxser_module_exit Signed-off-by: Kirill Smelkov Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/mxser.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 4b783d9bbd5..d5c34af8752 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -494,14 +494,18 @@ static int __init mxser_module_init(void) static void __exit mxser_module_exit(void) { - int i, err = 0; + int i, err; if (verbose) printk(KERN_DEBUG "Unloading module mxser ...\n"); - if ((err |= tty_unregister_driver(mxvar_sdriver))) + err = tty_unregister_driver(mxvar_sdriver); + if (!err) + put_tty_driver(mxvar_sdriver); + else printk(KERN_ERR "Couldn't unregister MOXA Smartio/Industio family serial driver\n"); + for (i = 0; i < MXSER_BOARDS; i++) { struct pci_dev *pdev; @@ -690,7 +694,6 @@ static int mxser_get_PCI_conf(int busnum, int devnum, int board_type, struct mxs static int mxser_init(void) { int i, m, retval, b, n; - int ret1; struct pci_dev *pdev = NULL; int index; unsigned char busnum, devnum; @@ -854,14 +857,11 @@ static int mxser_init(void) } #endif - ret1 = 0; - if (!(ret1 = tty_register_driver(mxvar_sdriver))) { - return 0; - } else + retval = tty_register_driver(mxvar_sdriver); + if (retval) { printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family driver !\n"); + put_tty_driver(mxvar_sdriver); - - if (ret1) { for (i = 0; i < MXSER_BOARDS; i++) { if (mxsercfg[i].board_type == -1) continue; @@ -870,10 +870,10 @@ static int mxser_init(void) //todo: release io, vector } } - return -1; + return retval; } - return (0); + return 0; } static void mxser_do_softint(void *private_) -- cgit v1.2.3 From 6f08b72cdd4b99a190c4e1fcddd63b401e5b572d Mon Sep 17 00:00:00 2001 From: Kirill Smelkov Date: Mon, 7 Nov 2005 00:59:23 -0800 Subject: [PATCH] serial moxa: fix wrong BUG There is a wrong BUG in mxser_close. The BUG is triggered when tty->driver_data == NULL, But in fact this is not a bug, because tty->driver->close is called even when tty->driver->open fails. LDD3 tells us to do nothing in such cases. Signed-off-by: Kirill Smelkov Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/mxser.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index d5c34af8752..3b965a651da 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -917,6 +917,9 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) struct mxser_struct *info; int retval, line; + /* initialize driver_data in case something fails */ + tty->driver_data = NULL; + line = tty->index; if (line == MXSER_PORTS) return 0; @@ -979,7 +982,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) if (tty->index == MXSER_PORTS) return; if (!info) - BUG(); + return; spin_lock_irqsave(&info->slock, flags); -- cgit v1.2.3 From ccb6e363a68144cdfdaa6d964d63d620c8ac9a9b Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 00:59:23 -0800 Subject: [PATCH] fs/smbfs/request.c: turn NULL dereference into BUG() In a case documented as We should never be called with any of these states BUG() in a case that would later result in a NULL pointer dereference. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/smbfs/request.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/smbfs/request.c b/fs/smbfs/request.c index 2d85dd7415b..a0f296d9928 100644 --- a/fs/smbfs/request.c +++ b/fs/smbfs/request.c @@ -786,8 +786,7 @@ int smb_request_recv(struct smb_sb_info *server) /* We should never be called with any of these states */ case SMB_RECV_END: case SMB_RECV_REQUEST: - server->rstate = SMB_RECV_END; - break; + BUG(); } if (result < 0) { -- cgit v1.2.3 From e2a8f7a129aff5173c238c8896f004e07a2a3abe Mon Sep 17 00:00:00 2001 From: Kylene Jo Hall Date: Mon, 7 Nov 2005 00:59:25 -0800 Subject: [PATCH] tpm: Fix lack of driver_unregister in init failcases driver_unregister is not being properly called when the init function returns an error case. Restructured the return logic such that this and the other cleanups all happen in one place. Preformed many of the cleanups that Andrew Morton's patch on Thursday made in tpm_atmel.c. Fixed Matthieu's concern about writing before discovery. (akpm: rmk said: This driver is buggy. You must not provide your own release function - it doesn't solve the problem which the warning (which you get when you don't provide one) is telling you about. You should convert your device driver over to the replacement dynamic platform support, once it is merged. IOW, something like: pdev = platform_device_alloc("mydev", id); if (pdev) { err = platform_device_add_resources(pdev, &resources, ARRAY_SIZE(resources)); if (err == 0) err = platform_device_add_data(pdev, &platform_data, sizeof(platform_data)); if (err == 0) err = platform_device_add(pdev); } else { err = -ENOMEM; } if (err) platform_device_put(pdev); ) Signed-off-by: Kylene Jo Hall Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tpm/tpm_nsc.c | 48 ++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c index 8d125c974a2..680a8e33188 100644 --- a/drivers/char/tpm/tpm_nsc.c +++ b/drivers/char/tpm/tpm_nsc.c @@ -287,10 +287,6 @@ static int __init init_nsc(void) int lo, hi; int nscAddrBase = TPM_ADDR; - driver_register(&nsc_drv); - - /* select PM channel 1 */ - tpm_write_index(nscAddrBase,NSC_LDN_INDEX, 0x12); /* verify that it is a National part (SID) */ if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) { @@ -300,6 +296,8 @@ static int __init init_nsc(void) return -ENODEV; } + driver_register(&nsc_drv); + hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI); lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO); tpm_nsc.base = (hi<<8) | lo; @@ -307,11 +305,11 @@ static int __init init_nsc(void) /* enable the DPM module */ tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01); - pdev = kmalloc(sizeof(struct platform_device), GFP_KERNEL); - if ( !pdev ) - return -ENOMEM; - - memset(pdev, 0, sizeof(struct platform_device)); + pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL); + if (!pdev) { + rc = -ENOMEM; + goto err_unreg_drv; + } pdev->name = "tpm_nscl0"; pdev->id = -1; @@ -319,26 +317,16 @@ static int __init init_nsc(void) pdev->dev.release = tpm_nsc_remove; pdev->dev.driver = &nsc_drv; - if ((rc=platform_device_register(pdev)) < 0) { - kfree(pdev); - pdev = NULL; - return rc; - } + if ((rc = platform_device_register(pdev)) < 0) + goto err_free_dev; if (request_region(tpm_nsc.base, 2, "tpm_nsc0") == NULL ) { - platform_device_unregister(pdev); - kfree(pdev); - pdev = NULL; - return -EBUSY; + rc = -EBUSY; + goto err_unreg_dev; } - if ((rc = tpm_register_hardware(&pdev->dev, &tpm_nsc)) < 0) { - release_region(tpm_nsc.base, 2); - platform_device_unregister(pdev); - kfree(pdev); - pdev = NULL; - return rc; - } + if ((rc = tpm_register_hardware(&pdev->dev, &tpm_nsc)) < 0) + goto err_rel_reg; dev_dbg(&pdev->dev, "NSC TPM detected\n"); dev_dbg(&pdev->dev, @@ -374,6 +362,16 @@ static int __init init_nsc(void) tpm_read_index(nscAddrBase, 0x27) & 0x1F); return 0; + +err_rel_reg: + release_region(tpm_nsc.base, 2); +err_unreg_dev: + platform_device_unregister(pdev); +err_free_dev: + kfree(pdev); +err_unreg_drv: + driver_unregister(&nsc_drv); + return rc; } static void __exit cleanup_nsc(void) -- cgit v1.2.3 From 274b69335d8f18fe198af2d939331f01fec70659 Mon Sep 17 00:00:00 2001 From: Abhay Salunke Date: Mon, 7 Nov 2005 00:59:26 -0800 Subject: [PATCH] dell_rbu: Adding BIOS memory floor support This patch has the changes to support the memory floor fix done in Dell BIOS. The BIOS incase of packet update mechanism would not accept packet placed in memory below a cretain address. This address is by default 128K but can change. The driver now can accept the memory floor if the user chooses to make it will try to allocate contiguous physical memory above the memory floor by allocating a set of packets till a valid memory allocation is made. All the allocates then are freed. This repeats for everty packet. This patch was created by Michael E Brown and has been tested on 2.6.14-rc5 Signed-of-by: Michael E Brown Signed-off-by: Abhay Salunke Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/firmware/dell_rbu.c | 121 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 95 insertions(+), 26 deletions(-) diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index 125929c9048..ba17292eb29 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c @@ -50,7 +50,7 @@ MODULE_AUTHOR("Abhay Salunke "); MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); MODULE_LICENSE("GPL"); -MODULE_VERSION("3.0"); +MODULE_VERSION("3.1"); #define BIOS_SCAN_LIMIT 0xffffffff #define MAX_IMAGE_LENGTH 16 @@ -73,6 +73,11 @@ module_param_string(image_type, image_type, sizeof (image_type), 0); MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet or init"); +static unsigned long allocation_floor = 0x100000; +module_param(allocation_floor, ulong, 0644); +MODULE_PARM_DESC(allocation_floor, + "Minimum address for allocations when using Packet mode"); + struct packet_data { struct list_head list; size_t length; @@ -99,61 +104,122 @@ static int create_packet(void *data, size_t length) { struct packet_data *newpacket; int ordernum = 0; + int retval = 0; + unsigned int packet_array_size = 0; + void **invalid_addr_packet_array = 0; + void *packet_data_temp_buf = 0; + unsigned int idx = 0; pr_debug("create_packet: entry \n"); if (!rbu_data.packetsize) { pr_debug("create_packet: packetsize not specified\n"); - return -EINVAL; + retval = -EINVAL; + goto out_noalloc; } + spin_unlock(&rbu_data.lock); - newpacket = kmalloc(sizeof (struct packet_data), GFP_KERNEL); - spin_lock(&rbu_data.lock); + + newpacket = kzalloc(sizeof (struct packet_data), GFP_KERNEL); if (!newpacket) { printk(KERN_WARNING "dell_rbu:%s: failed to allocate new " "packet\n", __FUNCTION__); - return -ENOMEM; + retval = -ENOMEM; + spin_lock(&rbu_data.lock); + goto out_noalloc; } ordernum = get_order(length); + /* - * there is no upper limit on memory - * address for packetized mechanism + * BIOS errata mean we cannot allocate packets below 1MB or they will + * be overwritten by BIOS. + * + * array to temporarily hold packets + * that are below the allocation floor + * + * NOTE: very simplistic because we only need the floor to be at 1MB + * due to BIOS errata. This shouldn't be used for higher floors + * or you will run out of mem trying to allocate the array. */ - spin_unlock(&rbu_data.lock); - newpacket->data = (unsigned char *) __get_free_pages(GFP_KERNEL, - ordernum); - spin_lock(&rbu_data.lock); + packet_array_size = max( + (unsigned int)(allocation_floor / rbu_data.packetsize), + (unsigned int)1); + invalid_addr_packet_array = kzalloc(packet_array_size * sizeof(void*), + GFP_KERNEL); - pr_debug("create_packet: newpacket %p\n", newpacket->data); - - if (!newpacket->data) { + if (!invalid_addr_packet_array) { printk(KERN_WARNING - "dell_rbu:%s: failed to allocate new " - "packet\n", __FUNCTION__); - kfree(newpacket); - return -ENOMEM; + "dell_rbu:%s: failed to allocate " + "invalid_addr_packet_array \n", + __FUNCTION__); + retval = -ENOMEM; + spin_lock(&rbu_data.lock); + goto out_alloc_packet; } + while (!packet_data_temp_buf) { + packet_data_temp_buf = (unsigned char *) + __get_free_pages(GFP_KERNEL, ordernum); + if (!packet_data_temp_buf) { + printk(KERN_WARNING + "dell_rbu:%s: failed to allocate new " + "packet\n", __FUNCTION__); + retval = -ENOMEM; + spin_lock(&rbu_data.lock); + goto out_alloc_packet_array; + } + + if ((unsigned long)virt_to_phys(packet_data_temp_buf) + < allocation_floor) { + pr_debug("packet 0x%lx below floor at 0x%lx.\n", + (unsigned long)virt_to_phys( + packet_data_temp_buf), + allocation_floor); + invalid_addr_packet_array[idx++] = packet_data_temp_buf; + packet_data_temp_buf = 0; + } + } + spin_lock(&rbu_data.lock); + + newpacket->data = packet_data_temp_buf; + + pr_debug("create_packet: newpacket at physical addr %lx\n", + (unsigned long)virt_to_phys(newpacket->data)); + + /* packets may not have fixed size */ + newpacket->length = length; newpacket->ordernum = ordernum; ++rbu_data.num_packets; - /* - * initialize the newly created packet headers - */ + + /* initialize the newly created packet headers */ INIT_LIST_HEAD(&newpacket->list); list_add_tail(&newpacket->list, &packet_data_head.list); - /* - * packets may not have fixed size - */ - newpacket->length = length; memcpy(newpacket->data, data, length); pr_debug("create_packet: exit \n"); - return 0; +out_alloc_packet_array: + /* always free packet array */ + for (;idx>0;idx--) { + pr_debug("freeing unused packet below floor 0x%lx.\n", + (unsigned long)virt_to_phys( + invalid_addr_packet_array[idx-1])); + free_pages((unsigned long)invalid_addr_packet_array[idx-1], + ordernum); + } + kfree(invalid_addr_packet_array); + +out_alloc_packet: + /* if error, free data */ + if (retval) + kfree(newpacket); + +out_noalloc: + return retval; } static int packetize_data(void *data, size_t length) @@ -693,3 +759,6 @@ static __exit void dcdrbu_exit(void) module_exit(dcdrbu_exit); module_init(dcdrbu_init); + +/* vim:noet:ts=8:sw=8 +*/ -- cgit v1.2.3 From d8ba3b731086bcae5468f9ea509f39a921b3f9a6 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 00:59:26 -0800 Subject: [PATCH] fuse: remove dead code from fuse_permission The -EROFS check has moved up to permission() in the VFS a while ago. Signed-off-by: Christoph Hellwig Acked-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dir.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 70dba721aca..61b58fdd973 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -491,9 +491,6 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) return err; } else { int mode = inode->i_mode; - if ((mask & MAY_WRITE) && IS_RDONLY(inode) && - (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) - return -EROFS; if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO)) return -EACCES; return 0; -- cgit v1.2.3 From bf8f972d3a1daf969cf44f64cc36d53bfd76441f Mon Sep 17 00:00:00 2001 From: Badari Pulavarty Date: Mon, 7 Nov 2005 00:59:27 -0800 Subject: [PATCH] SHM_NORESERVE flags for shmget() Add SHM_NORESERVE functionality similar to MAP_NORESERVE for shared memory segments. This is mainly to avoid abuse of OVERCOMMIT_ALWAYS and this flag is ignored for OVERCOMMIT_NEVER. Signed-off-by: Badari Pulavarty Cc: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/shm.h | 1 + ipc/shm.c | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/linux/shm.h b/include/linux/shm.h index 80113a1f60b..a2c896ad0be 100644 --- a/include/linux/shm.h +++ b/include/linux/shm.h @@ -92,6 +92,7 @@ struct shmid_kernel /* private to the kernel */ #define SHM_DEST 01000 /* segment will be destroyed on last detach */ #define SHM_LOCKED 02000 /* segment will not be swapped */ #define SHM_HUGETLB 04000 /* segment will use huge TLB pages */ +#define SHM_NORESERVE 010000 /* don't check for reservations */ #ifdef CONFIG_SYSVIPC long do_shmat(int shmid, char __user *shmaddr, int shmflg, unsigned long *addr); diff --git a/ipc/shm.c b/ipc/shm.c index b58c651d31a..587d836d80d 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -212,8 +212,16 @@ static int newseg (key_t key, int shmflg, size_t size) file = hugetlb_zero_setup(size); shp->mlock_user = current->user; } else { + int acctflag = VM_ACCOUNT; + /* + * Do not allow no accounting for OVERCOMMIT_NEVER, even + * if it's asked for. + */ + if ((shmflg & SHM_NORESERVE) && + sysctl_overcommit_memory != OVERCOMMIT_NEVER) + acctflag = 0; sprintf (name, "SYSV%08x", key); - file = shmem_file_setup(name, size, VM_ACCOUNT); + file = shmem_file_setup(name, size, acctflag); } error = PTR_ERR(file); if (IS_ERR(file)) -- cgit v1.2.3 From 7361f4d8ca65d23a18ba009b4484612183332c2f Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 7 Nov 2005 00:59:28 -0800 Subject: [PATCH] readahead commentary Add a few comments surrounding the generic readahead API. Also convert some ulongs into pgoff_t: the identifier for PAGE_CACHE_SIZE offsets into pagecache. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mm.h | 8 ++++---- mm/readahead.c | 31 ++++++++++++++++++++++--------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 5c1fb0a2e80..7b115feca4d 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -932,13 +932,13 @@ int write_one_page(struct page *page, int wait); * turning readahead off */ int do_page_cache_readahead(struct address_space *mapping, struct file *filp, - unsigned long offset, unsigned long nr_to_read); + pgoff_t offset, unsigned long nr_to_read); int force_page_cache_readahead(struct address_space *mapping, struct file *filp, - unsigned long offset, unsigned long nr_to_read); -unsigned long page_cache_readahead(struct address_space *mapping, + pgoff_t offset, unsigned long nr_to_read); +unsigned long page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra, struct file *filp, - unsigned long offset, + pgoff_t offset, unsigned long size); void handle_ra_miss(struct address_space *mapping, struct file_ra_state *ra, pgoff_t offset); diff --git a/mm/readahead.c b/mm/readahead.c index d0b50034e24..72e7adbb87c 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -254,7 +254,7 @@ out: */ static int __do_page_cache_readahead(struct address_space *mapping, struct file *filp, - unsigned long offset, unsigned long nr_to_read) + pgoff_t offset, unsigned long nr_to_read) { struct inode *inode = mapping->host; struct page *page; @@ -274,7 +274,7 @@ __do_page_cache_readahead(struct address_space *mapping, struct file *filp, */ read_lock_irq(&mapping->tree_lock); for (page_idx = 0; page_idx < nr_to_read; page_idx++) { - unsigned long page_offset = offset + page_idx; + pgoff_t page_offset = offset + page_idx; if (page_offset > end_index) break; @@ -311,7 +311,7 @@ out: * memory at once. */ int force_page_cache_readahead(struct address_space *mapping, struct file *filp, - unsigned long offset, unsigned long nr_to_read) + pgoff_t offset, unsigned long nr_to_read) { int ret = 0; @@ -368,7 +368,7 @@ static inline int check_ra_success(struct file_ra_state *ra, * request queues. */ int do_page_cache_readahead(struct address_space *mapping, struct file *filp, - unsigned long offset, unsigned long nr_to_read) + pgoff_t offset, unsigned long nr_to_read) { if (bdi_read_congested(mapping->backing_dev_info)) return -1; @@ -385,7 +385,7 @@ int do_page_cache_readahead(struct address_space *mapping, struct file *filp, */ static int blockable_page_cache_readahead(struct address_space *mapping, struct file *filp, - unsigned long offset, unsigned long nr_to_read, + pgoff_t offset, unsigned long nr_to_read, struct file_ra_state *ra, int block) { int actual; @@ -430,14 +430,27 @@ static int make_ahead_window(struct address_space *mapping, struct file *filp, return ret; } -/* - * page_cache_readahead is the main function. If performs the adaptive +/** + * page_cache_readahead - generic adaptive readahead + * @mapping: address_space which holds the pagecache and I/O vectors + * @ra: file_ra_state which holds the readahead state + * @filp: passed on to ->readpage() and ->readpages() + * @offset: start offset into @mapping, in PAGE_CACHE_SIZE units + * @req_size: hint: total size of the read which the caller is performing in + * PAGE_CACHE_SIZE units + * + * page_cache_readahead() is the main function. If performs the adaptive * readahead window size management and submits the readahead I/O. + * + * Note that @filp is purely used for passing on to the ->readpage[s]() + * handler: it may refer to a different file from @mapping (so we may not use + * @filp->f_mapping or @filp->f_dentry->d_inode here). + * Also, @ra may not be equal to &@filp->f_ra. + * */ unsigned long page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra, - struct file *filp, unsigned long offset, - unsigned long req_size) + struct file *filp, pgoff_t offset, unsigned long req_size) { unsigned long max, newsize; int sequential; -- cgit v1.2.3 From a43313668f62a06e14c915b8c8994fc8a1257394 Mon Sep 17 00:00:00 2001 From: Hans Reiser Date: Mon, 7 Nov 2005 00:59:29 -0800 Subject: [PATCH] reiser4: add radix_tree_lookup_slot() Reiser4 uses radix trees to solve a trouble reiser4_readdir has serving nfs requests. Unfortunately, radix tree api lacks an operation suitable for modifying existing entry. This patch adds radix_tree_lookup_slot which returns pointer to found item within the tree. That location can be then updated. Both Nick and Christoph Lameter have patches which need this as well. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/radix-tree.h | 1 + lib/radix-tree.c | 51 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h index 9f0f9281f42..36e5d269612 100644 --- a/include/linux/radix-tree.h +++ b/include/linux/radix-tree.h @@ -46,6 +46,7 @@ do { \ int radix_tree_insert(struct radix_tree_root *, unsigned long, void *); void *radix_tree_lookup(struct radix_tree_root *, unsigned long); +void **radix_tree_lookup_slot(struct radix_tree_root *, unsigned long); void *radix_tree_delete(struct radix_tree_root *, unsigned long); unsigned int radix_tree_gang_lookup(struct radix_tree_root *root, void **results, diff --git a/lib/radix-tree.c b/lib/radix-tree.c index d1c057e71b6..88511c3805a 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -281,35 +281,60 @@ int radix_tree_insert(struct radix_tree_root *root, } EXPORT_SYMBOL(radix_tree_insert); -/** - * radix_tree_lookup - perform lookup operation on a radix tree - * @root: radix tree root - * @index: index key - * - * Lookup the item at the position @index in the radix tree @root. - */ -void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index) +static inline void **__lookup_slot(struct radix_tree_root *root, + unsigned long index) { unsigned int height, shift; - struct radix_tree_node *slot; + struct radix_tree_node **slot; height = root->height; if (index > radix_tree_maxindex(height)) return NULL; shift = (height-1) * RADIX_TREE_MAP_SHIFT; - slot = root->rnode; + slot = &root->rnode; while (height > 0) { - if (slot == NULL) + if (*slot == NULL) return NULL; - slot = slot->slots[(index >> shift) & RADIX_TREE_MAP_MASK]; + slot = (struct radix_tree_node **) + ((*slot)->slots + + ((index >> shift) & RADIX_TREE_MAP_MASK)); shift -= RADIX_TREE_MAP_SHIFT; height--; } - return slot; + return (void **)slot; +} + +/** + * radix_tree_lookup_slot - lookup a slot in a radix tree + * @root: radix tree root + * @index: index key + * + * Lookup the slot corresponding to the position @index in the radix tree + * @root. This is useful for update-if-exists operations. + */ +void **radix_tree_lookup_slot(struct radix_tree_root *root, unsigned long index) +{ + return __lookup_slot(root, index); +} +EXPORT_SYMBOL(radix_tree_lookup_slot); + +/** + * radix_tree_lookup - perform lookup operation on a radix tree + * @root: radix tree root + * @index: index key + * + * Lookup the item at the position @index in the radix tree @root. + */ +void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index) +{ + void **slot; + + slot = __lookup_slot(root, index); + return slot != NULL ? *slot : NULL; } EXPORT_SYMBOL(radix_tree_lookup); -- cgit v1.2.3 From 28ef35845f2c8da8e1bed068277d2fab1e8c8979 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 7 Nov 2005 00:59:29 -0800 Subject: [PATCH] small kernel_stat.h cleanup cleanup: use for_each_cpu() instead of an open-coded NR_CPUS loop. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/kernel_stat.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h index dba27749b42..a484572c302 100644 --- a/include/linux/kernel_stat.h +++ b/include/linux/kernel_stat.h @@ -6,6 +6,7 @@ #include #include #include +#include #include /* @@ -43,11 +44,10 @@ extern unsigned long long nr_context_switches(void); */ static inline int kstat_irqs(int irq) { - int i, sum=0; + int cpu, sum = 0; - for (i = 0; i < NR_CPUS; i++) - if (cpu_possible(i)) - sum += kstat_cpu(i).irqs[irq]; + for_each_cpu(cpu) + sum += kstat_cpu(cpu).irqs[irq]; return sum; } -- cgit v1.2.3 From 0f6ed7c2641fe4cea83cd09c21928ca30c0983ec Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 7 Nov 2005 00:59:30 -0800 Subject: [PATCH] Keys: Remove incorrect and obsolete '!' operators The attached patch removes a couple of incorrect and obsolete '!' operators left over from the conversion of the key permission functions from true/false returns to zero/error returns. Signed-Off-By: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- security/keys/keyring.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/security/keys/keyring.c b/security/keys/keyring.c index e1cc4dd7901..c7a0ab1cfda 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -434,8 +434,8 @@ ascend: if (sp >= KEYRING_SEARCH_MAX_DEPTH) continue; - if (!key_task_permission(make_key_ref(key, possessed), - context, KEY_SEARCH) < 0) + if (key_task_permission(make_key_ref(key, possessed), + context, KEY_SEARCH) < 0) continue; /* stack the current position */ @@ -621,8 +621,8 @@ struct key *find_keyring_by_name(const char *name, key_serial_t bound) if (strcmp(keyring->description, name) != 0) continue; - if (!key_permission(make_key_ref(keyring, 0), - KEY_SEARCH) < 0) + if (key_permission(make_key_ref(keyring, 0), + KEY_SEARCH) < 0) continue; /* found a potential candidate, but we still need to -- cgit v1.2.3 From d55b5fdaf40846221d543937b786956e27837fda Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Mon, 7 Nov 2005 00:59:31 -0800 Subject: [PATCH] aio: remove aio_max_nr accounting race AIO was adding a new context's max requests to the global total before testing if that resulting total was over the global limit. This let innocent tasks get their new limit tested along with a racing guilty task that was crossing the limit. This serializes the _nr accounting with a spinlock It also switches to using unsigned long for the global totals. Individual contexts are still limited to an unsigned int's worth of requests by the syscall interface. The problem and fix were verified with a simple program that spun creating and destroying a context while holding on to another long lived context. Before the patch a task creating a tiny context could get a spurious EAGAIN if it raced with a task creating a very large context that overran the limit. Signed-off-by: Zach Brown Cc: Benjamin LaHaise Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/aio.c | 31 +++++++++++++++++++++---------- include/linux/aio.h | 5 +++-- kernel/sysctl.c | 4 ++-- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index edfca5b7553..20bb919eb19 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -42,8 +42,9 @@ #endif /*------ sysctl variables----*/ -atomic_t aio_nr = ATOMIC_INIT(0); /* current system wide number of aio requests */ -unsigned aio_max_nr = 0x10000; /* system wide maximum number of aio requests */ +static DEFINE_SPINLOCK(aio_nr_lock); +unsigned long aio_nr; /* current system wide number of aio requests */ +unsigned long aio_max_nr = 0x10000; /* system wide maximum number of aio requests */ /*----end sysctl variables---*/ static kmem_cache_t *kiocb_cachep; @@ -208,7 +209,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) return ERR_PTR(-EINVAL); } - if (nr_events > aio_max_nr) + if ((unsigned long)nr_events > aio_max_nr) return ERR_PTR(-EAGAIN); ctx = kmem_cache_alloc(kioctx_cachep, GFP_KERNEL); @@ -233,8 +234,14 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) goto out_freectx; /* limit the number of system wide aios */ - atomic_add(ctx->max_reqs, &aio_nr); /* undone by __put_ioctx */ - if (unlikely(atomic_read(&aio_nr) > aio_max_nr)) + spin_lock(&aio_nr_lock); + if (aio_nr + ctx->max_reqs > aio_max_nr || + aio_nr + ctx->max_reqs < aio_nr) + ctx->max_reqs = 0; + else + aio_nr += ctx->max_reqs; + spin_unlock(&aio_nr_lock); + if (ctx->max_reqs == 0) goto out_cleanup; /* now link into global list. kludge. FIXME */ @@ -248,8 +255,6 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) return ctx; out_cleanup: - atomic_sub(ctx->max_reqs, &aio_nr); - ctx->max_reqs = 0; /* prevent __put_ioctx from sub'ing aio_nr */ __put_ioctx(ctx); return ERR_PTR(-EAGAIN); @@ -374,7 +379,12 @@ void fastcall __put_ioctx(struct kioctx *ctx) pr_debug("__put_ioctx: freeing %p\n", ctx); kmem_cache_free(kioctx_cachep, ctx); - atomic_sub(nr_events, &aio_nr); + if (nr_events) { + spin_lock(&aio_nr_lock); + BUG_ON(aio_nr - nr_events > aio_nr); + aio_nr -= nr_events; + spin_unlock(&aio_nr_lock); + } } /* aio_get_req @@ -1258,8 +1268,9 @@ asmlinkage long sys_io_setup(unsigned nr_events, aio_context_t __user *ctxp) goto out; ret = -EINVAL; - if (unlikely(ctx || (int)nr_events <= 0)) { - pr_debug("EINVAL: io_setup: ctx or nr_events > max\n"); + if (unlikely(ctx || nr_events == 0)) { + pr_debug("EINVAL: io_setup: ctx %lu nr_events %u\n", + ctx, nr_events); goto out; } diff --git a/include/linux/aio.h b/include/linux/aio.h index 0decf66117c..403d71dcb7c 100644 --- a/include/linux/aio.h +++ b/include/linux/aio.h @@ -183,6 +183,7 @@ struct kioctx { struct list_head active_reqs; /* used for cancellation */ struct list_head run_list; /* used for kicked reqs */ + /* sys_io_setup currently limits this to an unsigned int */ unsigned max_reqs; struct aio_ring_info ring_info; @@ -234,7 +235,7 @@ static inline struct kiocb *list_kiocb(struct list_head *h) } /* for sysctl: */ -extern atomic_t aio_nr; -extern unsigned aio_max_nr; +extern unsigned long aio_nr; +extern unsigned long aio_max_nr; #endif /* __LINUX__AIO_H */ diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 8e56e249554..e1351200ce8 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -952,7 +952,7 @@ static ctl_table fs_table[] = { .data = &aio_nr, .maxlen = sizeof(aio_nr), .mode = 0444, - .proc_handler = &proc_dointvec, + .proc_handler = &proc_doulongvec_minmax, }, { .ctl_name = FS_AIO_MAX_NR, @@ -960,7 +960,7 @@ static ctl_table fs_table[] = { .data = &aio_max_nr, .maxlen = sizeof(aio_max_nr), .mode = 0644, - .proc_handler = &proc_dointvec, + .proc_handler = &proc_doulongvec_minmax, }, #ifdef CONFIG_INOTIFY { -- cgit v1.2.3 From 796f8d9b98fc92a5e9aaea8cf932957850332f51 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 7 Nov 2005 00:59:33 -0800 Subject: [PATCH] FUTEX_WAKE_OP: enhanced error handling The code for FUTEX_WAKE_OP calls an arch callback, futex_atomic_op_inuser(). That callback can return an error code, but currently the caller assumes any error is EFAULT, and will try various things to resolve the fault before eventually giving up with EFAULT (regardless of the original error code). This is not a theoretical case - arch callbacks currently return -ENOSYS if the opcode they are given is bogus. This patch alters the code to detect non-EFAULT errors and return them directly to the user. Of course, whether -ENOSYS is the correct return value for the bogus opcode case, or whether EINVAL would be more appropriate is another question. Signed-off-by: David Gibson Cc: Rusty Russell Cc: Ingo Molnar Cc: Jamie Lokier Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/futex.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kernel/futex.c b/kernel/futex.c index 3b4d5ad44cc..aca8d10704f 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -365,6 +365,11 @@ retry: if (bh1 != bh2) spin_unlock(&bh2->lock); + if (unlikely(op_ret != -EFAULT)) { + ret = op_ret; + goto out; + } + /* futex_atomic_op_inuser needs to both read and write * *(int __user *)uaddr2, but we can't modify it * non-atomically. Therefore, if get_user below is not -- cgit v1.2.3 From e3f17f0f6e98f58edb13cb38810d93e6d4808e68 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Mon, 7 Nov 2005 00:59:34 -0800 Subject: [PATCH] Only disallow _setting_ of function key string Mikael Pettersson noted that the current 2.6-git (and 2.4) patch to disallow KDSKBSENT for unpriviledged users should be less restrictive allowing reading of current function key string entry, but not writing. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/vt_ioctl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index 003dda147cd..24011e7c81f 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -80,6 +80,9 @@ do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, struct kbd_str if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry))) return -EFAULT; + if (!capable(CAP_SYS_TTY_CONFIG)) + perm = 0; + switch (cmd) { case KDGKBENT: key_map = key_maps[s]; @@ -193,7 +196,7 @@ do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm) int ret; if (!capable(CAP_SYS_TTY_CONFIG)) - return -EPERM; + perm = 0; kbs = kmalloc(sizeof(*kbs), GFP_KERNEL); if (!kbs) { -- cgit v1.2.3 From be586bab8bfbf5d429bdfcb6136bdde89583c5c4 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 00:59:35 -0800 Subject: [PATCH] quota: small cleanups - "extern inline" -> "static inline" - every file should #include the headers containing the prototypes for it's global functions Signed-off-by: Adrian Bunk Signed-off-by: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/dquot.c | 1 + fs/quota.c | 1 + include/linux/quotaops.h | 12 ++++++------ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/fs/dquot.c b/fs/dquot.c index ea7644227a6..afa06a89346 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -77,6 +77,7 @@ #include #include #include +#include #include diff --git a/fs/quota.c b/fs/quota.c index 1df7832b4e0..612e04db4b9 100644 --- a/fs/quota.c +++ b/fs/quota.c @@ -15,6 +15,7 @@ #include #include #include +#include /* Check validity of generic quotactl commands */ static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id) diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index d211507ab24..4f34d3d60f2 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -198,38 +198,38 @@ static __inline__ int DQUOT_OFF(struct super_block *sb) #define DQUOT_SYNC(sb) do { } while(0) #define DQUOT_OFF(sb) do { } while(0) #define DQUOT_TRANSFER(inode, iattr) (0) -extern __inline__ int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) +static inline int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) { inode_add_bytes(inode, nr); return 0; } -extern __inline__ int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr) +static inline int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr) { DQUOT_PREALLOC_SPACE_NODIRTY(inode, nr); mark_inode_dirty(inode); return 0; } -extern __inline__ int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) +static inline int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) { inode_add_bytes(inode, nr); return 0; } -extern __inline__ int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr) +static inline int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr) { DQUOT_ALLOC_SPACE_NODIRTY(inode, nr); mark_inode_dirty(inode); return 0; } -extern __inline__ void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr) +static inline void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr) { inode_sub_bytes(inode, nr); } -extern __inline__ void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr) +static inline void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr) { DQUOT_FREE_SPACE_NODIRTY(inode, nr); mark_inode_dirty(inode); -- cgit v1.2.3 From ce44eeb6906cf2b093b76ea69b952621712a4a3c Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Mon, 7 Nov 2005 00:59:36 -0800 Subject: [PATCH] V9FS: 'names_cache' memory leak Data allocated with "__getname()" should always be free'd with "__putname()" because of the AUDITSYSCALL code. Signed-off-by: Davi Arnaut Cc: Cc: Eric Van Hensbergen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/9p/v9fs.c | 6 +++--- fs/9p/vfs_inode.c | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 82303f3bf76..418c3743fde 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -266,7 +266,7 @@ v9fs_session_init(struct v9fs_session_info *v9ses, v9ses->remotename = __getname(); if (!v9ses->remotename) { - putname(v9ses->name); + __putname(v9ses->name); return -ENOMEM; } @@ -411,8 +411,8 @@ void v9fs_session_close(struct v9fs_session_info *v9ses) if (v9ses->transport) v9ses->transport->close(v9ses->transport); - putname(v9ses->name); - putname(v9ses->remotename); + __putname(v9ses->name); + __putname(v9ses->remotename); } /** diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 2b696ae6655..be7288184fa 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -1105,7 +1105,7 @@ static int v9fs_vfs_readlink(struct dentry *dentry, char __user * buffer, } } - putname(link); + __putname(link); return retval; } @@ -1129,7 +1129,7 @@ static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd) len = v9fs_readlink(dentry, link, strlen(link)); if (len < 0) { - putname(link); + __putname(link); link = ERR_PTR(len); } else link[len] = 0; @@ -1152,7 +1152,7 @@ static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void dprintk(DEBUG_VFS, " %s %s\n", dentry->d_name.name, s); if (!IS_ERR(s)) - putname(s); + __putname(s); } /** @@ -1228,7 +1228,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, FreeMem: kfree(mistat); kfree(fcall); - putname(symname); + __putname(symname); return retval; } @@ -1319,7 +1319,7 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) FreeMem: kfree(mistat); kfree(fcall); - putname(symname); + __putname(symname); return retval; } -- cgit v1.2.3 From 53b27584db0446e356c86b3aa43f5107b0170704 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Mon, 7 Nov 2005 00:59:37 -0800 Subject: [PATCH] smbfs: 'names_cache' memory leak Data allocated with "__getname()" should always be free'd with "__putname()" because of the AUDITSYSCALL code. Signed-off-by: Davi Arnaut Cc: Urban Widmark Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/smbfs/symlink.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/smbfs/symlink.c b/fs/smbfs/symlink.c index 0c64bc3a012..cdc53c4fb38 100644 --- a/fs/smbfs/symlink.c +++ b/fs/smbfs/symlink.c @@ -45,7 +45,7 @@ static void *smb_follow_link(struct dentry *dentry, struct nameidata *nd) int len = smb_proc_read_link(server_from_dentry(dentry), dentry, link, PATH_MAX - 1); if (len < 0) { - putname(link); + __putname(link); link = ERR_PTR(len); } else { link[len] = 0; @@ -59,7 +59,7 @@ static void smb_put_link(struct dentry *dentry, struct nameidata *nd, void *p) { char *s = nd_get_link(nd); if (!IS_ERR(s)) - putname(s); + __putname(s); } struct inode_operations smb_link_inode_operations = -- cgit v1.2.3 From 385fd4c59d8bf7895ad3641c4cea615346f684ed Mon Sep 17 00:00:00 2001 From: Coywolf Qi Hunt Date: Mon, 7 Nov 2005 00:59:39 -0800 Subject: [PATCH] __find_get_block_slow() cleanup Get rid of the `int unused' parameter of __find_get_block_slow(). Signed-off-by: Coywolf Qi Hunt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/buffer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/buffer.c b/fs/buffer.c index 35fa34977e8..5287be18633 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -396,7 +396,7 @@ asmlinkage long sys_fdatasync(unsigned int fd) * private_lock is contended then so is mapping->tree_lock). */ static struct buffer_head * -__find_get_block_slow(struct block_device *bdev, sector_t block, int unused) +__find_get_block_slow(struct block_device *bdev, sector_t block) { struct inode *bd_inode = bdev->bd_inode; struct address_space *bd_mapping = bd_inode->i_mapping; @@ -1438,7 +1438,7 @@ __find_get_block(struct block_device *bdev, sector_t block, int size) struct buffer_head *bh = lookup_bh_lru(bdev, block, size); if (bh == NULL) { - bh = __find_get_block_slow(bdev, block, size); + bh = __find_get_block_slow(bdev, block); if (bh) bh_lru_install(bh); } @@ -1705,7 +1705,7 @@ void unmap_underlying_metadata(struct block_device *bdev, sector_t block) might_sleep(); - old_bh = __find_get_block_slow(bdev, block, 0); + old_bh = __find_get_block_slow(bdev, block); if (old_bh) { clear_buffer_dirty(old_bh); wait_on_buffer(old_bh); -- cgit v1.2.3 From 5c7ad5104d8ecf2c3a6428d73748126e91b1a250 Mon Sep 17 00:00:00 2001 From: Muli Ben-Yehuda Date: Mon, 7 Nov 2005 00:59:42 -0800 Subject: [PATCH] perform maintenance on Documentation/vm/hugetlbpage.txt Updates to Documentation/vm/hugetlbpage.txt: - there's no need to select HUGETLB_PAGE manually and it's no longer under the processor menu. Update the text accordingly. - fix typos and trim trailing whitespace. Signed-Off-By: Muli Ben-Yehuda Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/vm/hugetlbpage.txt | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt index 1b9bcd1fe98..1ad9af1ca4d 100644 --- a/Documentation/vm/hugetlbpage.txt +++ b/Documentation/vm/hugetlbpage.txt @@ -13,12 +13,13 @@ This optimization is more critical now as bigger and bigger physical memories Users can use the huge page support in Linux kernel by either using the mmap system call or standard SYSv shared memory system calls (shmget, shmat). -First the Linux kernel needs to be built with CONFIG_HUGETLB_PAGE (present -under Processor types and feature) and CONFIG_HUGETLBFS (present under file -system option on config menu) config options. +First the Linux kernel needs to be built with the CONFIG_HUGETLBFS +(present under "File systems") and CONFIG_HUGETLB_PAGE (selected +automatically when CONFIG_HUGETLBFS is selected) configuration +options. The kernel built with hugepage support should show the number of configured -hugepages in the system by running the "cat /proc/meminfo" command. +hugepages in the system by running the "cat /proc/meminfo" command. /proc/meminfo also provides information about the total number of hugetlb pages configured in the kernel. It also displays information about the @@ -38,19 +39,19 @@ in the kernel. /proc/sys/vm/nr_hugepages indicates the current number of configured hugetlb pages in the kernel. Super user can dynamically request more (or free some -pre-configured) hugepages. -The allocation( or deallocation) of hugetlb pages is posible only if there are +pre-configured) hugepages. +The allocation (or deallocation) of hugetlb pages is possible only if there are enough physically contiguous free pages in system (freeing of hugepages is -possible only if there are enough hugetlb pages free that can be transfered +possible only if there are enough hugetlb pages free that can be transfered back to regular memory pool). Pages that are used as hugetlb pages are reserved inside the kernel and can -not be used for other purposes. +not be used for other purposes. Once the kernel with Hugetlb page support is built and running, a user can use either the mmap system call or shared memory system calls to start using the huge pages. It is required that the system administrator preallocate -enough memory for huge page purposes. +enough memory for huge page purposes. Use the following command to dynamically allocate/deallocate hugepages: @@ -80,9 +81,9 @@ memory (huge pages) allowed for that filesystem (/mnt/huge). The size is rounded down to HPAGE_SIZE. The option nr_inode sets the maximum number of inodes that /mnt/huge can use. If the size or nr_inode options are not provided on command line then no limits are set. For size and nr_inodes -options, you can use [G|g]/[M|m]/[K|k] to represent giga/mega/kilo. For -example, size=2K has the same meaning as size=2048. An example is given at -the end of this document. +options, you can use [G|g]/[M|m]/[K|k] to represent giga/mega/kilo. For +example, size=2K has the same meaning as size=2048. An example is given at +the end of this document. read and write system calls are not supported on files that reside on hugetlb file systems. -- cgit v1.2.3 From 6fdcc2162285a8fc96ab12ff85086c37bceaa494 Mon Sep 17 00:00:00 2001 From: Peter Staubach Date: Mon, 7 Nov 2005 00:59:42 -0800 Subject: [PATCH] memory leak in dentry_open() There is a memory leak possible in dentry_open(). If get_empty_filp() fails, then the references to dentry and mnt need to be released. The attached patch adds the calls to dput() and mntput() to release these two references. Signed-off-by: Peter Staubach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/open.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/fs/open.c b/fs/open.c index 8d06ec911fd..2835f096c68 100644 --- a/fs/open.c +++ b/fs/open.c @@ -887,6 +887,10 @@ struct file *nameidata_to_filp(struct nameidata *nd, int flags) return filp; } +/* + * dentry_open() will have done dput(dentry) and mntput(mnt) if it returns an + * error. + */ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) { int error; @@ -894,8 +898,11 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) error = -ENFILE; f = get_empty_filp(); - if (f == NULL) + if (f == NULL) { + dput(dentry); + mntput(mnt); return ERR_PTR(error); + } return __dentry_open(dentry, mnt, flags, f, NULL); } -- cgit v1.2.3 From 8c65b4a60450590e79a28e9717ceffa9e4debb3f Mon Sep 17 00:00:00 2001 From: Tim Schmielau Date: Mon, 7 Nov 2005 00:59:43 -0800 Subject: [PATCH] fix remaining missing includes Fix more include file problems that surfaced since I submitted the previous fix-missing-includes.patch. This should now allow not to include sched.h from module.h, which is done by a followup patch. Signed-off-by: Tim Schmielau Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/mach-aaec2000/clock.c | 1 + arch/arm/mach-epxa10db/mm.c | 1 + arch/arm/mach-pxa/corgi_lcd.c | 1 + arch/ppc/syslib/ppc_sys.c | 1 + drivers/base/power/sysfs.c | 1 + drivers/char/agp/amd64-agp.c | 1 + drivers/hwmon/hwmon.c | 1 + drivers/infiniband/core/agent.c | 3 +++ drivers/infiniband/core/packer.c | 2 ++ drivers/infiniband/core/sysfs.c | 3 +++ drivers/infiniband/core/ud_header.c | 1 + drivers/infiniband/core/verbs.c | 1 + drivers/infiniband/hw/mthca/mthca_catas.c | 3 +++ drivers/infiniband/hw/mthca/mthca_srq.c | 3 +++ drivers/media/dvb/frontends/cx24110.c | 1 + drivers/message/i2o/exec-osm.c | 1 + drivers/mfd/mcp-core.c | 2 ++ drivers/pci/hotplug/pciehprm_nonacpi.c | 1 + drivers/pci/pci-driver.c | 1 + drivers/scsi/atari_dma_emul.c | 2 ++ drivers/scsi/raid_class.c | 2 ++ drivers/scsi/scsi_transport_sas.c | 2 ++ drivers/scsi/sym53c8xx_2/sym_hipd.c | 1 + fs/9p/error.c | 1 + include/asm-alpha/pgtable.h | 3 +++ include/asm-cris/processor.h | 2 ++ include/asm-frv/pgtable.h | 2 ++ include/asm-generic/pgtable.h | 1 + include/asm-i386/elf.h | 2 ++ include/asm-i386/pgtable.h | 3 +++ include/asm-ia64/pgtable.h | 1 + include/asm-m32r/pgtable.h | 3 +++ include/asm-mips/elf.h | 2 ++ include/asm-mips/pgtable.h | 3 +++ include/asm-parisc/pgtable.h | 3 ++- include/asm-powerpc/elf.h | 2 ++ include/asm-ppc/pgtable.h | 1 + include/asm-ppc64/pgtable.h | 1 + include/asm-s390/elf.h | 1 + include/asm-s390/pgtable.h | 1 + include/asm-sh/elf.h | 1 + include/asm-sh/pgtable.h | 2 ++ include/asm-sh64/pgtable.h | 2 ++ include/asm-x86_64/elf.h | 2 ++ include/asm-x86_64/pgtable.h | 2 ++ include/asm-xtensa/elf.h | 2 ++ include/asm-xtensa/pgtable.h | 3 +++ include/linux/irq.h | 1 + include/linux/memory.h | 3 +++ include/linux/sem.h | 2 ++ include/linux/wait.h | 1 + kernel/module.c | 1 + 52 files changed, 89 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-aaec2000/clock.c b/arch/arm/mach-aaec2000/clock.c index 99e019169dd..0340ddc4824 100644 --- a/arch/arm/mach-aaec2000/clock.c +++ b/arch/arm/mach-aaec2000/clock.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/mach-epxa10db/mm.c b/arch/arm/mach-epxa10db/mm.c index e8832d0910e..cfd0d2182d4 100644 --- a/arch/arm/mach-epxa10db/mm.c +++ b/arch/arm/mach-epxa10db/mm.c @@ -25,6 +25,7 @@ #include #include #include +#include #include diff --git a/arch/arm/mach-pxa/corgi_lcd.c b/arch/arm/mach-pxa/corgi_lcd.c index 54162ba9541..698eb06545c 100644 --- a/arch/arm/mach-pxa/corgi_lcd.c +++ b/arch/arm/mach-pxa/corgi_lcd.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c index 62ee86e8071..603f0119081 100644 --- a/arch/ppc/syslib/ppc_sys.c +++ b/arch/ppc/syslib/ppc_sys.c @@ -14,6 +14,7 @@ * option) any later version. */ +#include #include int (*ppc_sys_device_fixup) (struct platform_device * pdev); diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index 89c57875f3e..f3a0c562bcb 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c @@ -3,6 +3,7 @@ */ #include +#include #include "power.h" diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 0e6c3a31d34..78ce98a69f3 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -13,6 +13,7 @@ #include #include #include +#include #include /* PAGE_SIZE */ #include "agp.h" diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index 6f48579799b..dddd3eb9b38 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -16,6 +16,7 @@ #include #include #include +#include #define HWMON_ID_PREFIX "hwmon" #define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d" diff --git a/drivers/infiniband/core/agent.c b/drivers/infiniband/core/agent.c index 7545775d38e..34b724afd28 100644 --- a/drivers/infiniband/core/agent.c +++ b/drivers/infiniband/core/agent.c @@ -37,6 +37,9 @@ * $Id: agent.c 1389 2004-12-27 22:56:47Z roland $ */ +#include +#include + #include "agent.h" #include "smi.h" diff --git a/drivers/infiniband/core/packer.c b/drivers/infiniband/core/packer.c index 35df5010e72..c972d723576 100644 --- a/drivers/infiniband/core/packer.c +++ b/drivers/infiniband/core/packer.c @@ -33,6 +33,8 @@ * $Id: packer.c 1349 2004-12-16 21:09:43Z roland $ */ +#include + #include static u64 value_read(int offset, int size, void *structure) diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index b8120650e71..08648b1a387 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c @@ -36,6 +36,9 @@ #include "core_priv.h" +#include +#include + #include struct ib_port { diff --git a/drivers/infiniband/core/ud_header.c b/drivers/infiniband/core/ud_header.c index 527b23450ab..997c07db6d8 100644 --- a/drivers/infiniband/core/ud_header.c +++ b/drivers/infiniband/core/ud_header.c @@ -34,6 +34,7 @@ */ #include +#include #include diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 72d3ef786db..4186cc888ea 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -40,6 +40,7 @@ #include #include +#include #include #include diff --git a/drivers/infiniband/hw/mthca/mthca_catas.c b/drivers/infiniband/hw/mthca/mthca_catas.c index 7ac52af43b9..25ebab64bc4 100644 --- a/drivers/infiniband/hw/mthca/mthca_catas.c +++ b/drivers/infiniband/hw/mthca/mthca_catas.c @@ -32,6 +32,9 @@ * $Id$ */ +#include +#include + #include "mthca_dev.h" enum { diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index 292f55be8cb..26d5161fde0 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -32,6 +32,9 @@ * $Id: mthca_srq.c 3047 2005-08-10 03:59:35Z roland $ */ +#include +#include + #include "mthca_dev.h" #include "mthca_cmd.h" #include "mthca_memfree.h" diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c index d4b97989e3e..654d7dc879d 100644 --- a/drivers/media/dvb/frontends/cx24110.c +++ b/drivers/media/dvb/frontends/cx24110.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "dvb_frontend.h" #include "cx24110.h" diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index b675b4ebbeb..9c339a2505b 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c @@ -33,6 +33,7 @@ #include #include #include +#include /* wait_event_interruptible_timeout() needs this */ #include /* HZ */ #include "core.h" diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c index c75d713c01e..55ba23075c9 100644 --- a/drivers/mfd/mcp-core.c +++ b/drivers/mfd/mcp-core.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c index 33b2c69a082..76c727c74cc 100644 --- a/drivers/pci/hotplug/pciehprm_nonacpi.c +++ b/drivers/pci/hotplug/pciehprm_nonacpi.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index ae986e590b4..94e68c54d27 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "pci.h" /* diff --git a/drivers/scsi/atari_dma_emul.c b/drivers/scsi/atari_dma_emul.c index 7026045527f..8d5d2a5da96 100644 --- a/drivers/scsi/atari_dma_emul.c +++ b/drivers/scsi/atari_dma_emul.c @@ -19,6 +19,8 @@ * this code. */ +#include +#include #include #define hades_dma_ctrl (*(unsigned char *) 0xffff8717) diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c index f1ea5027865..caa0c362962 100644 --- a/drivers/scsi/raid_class.c +++ b/drivers/scsi/raid_class.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 0cc766a9aa6..edabbd05d25 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index a1a58e1d5ad..a7420cad454 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -39,6 +39,7 @@ */ #include +#include /* for timeouts in units of HZ */ #include "sym_glue.h" #include "sym_nvram.h" diff --git a/fs/9p/error.c b/fs/9p/error.c index fee5d19179c..834cb179e38 100644 --- a/fs/9p/error.c +++ b/fs/9p/error.c @@ -33,6 +33,7 @@ #include #include +#include #include "debug.h" #include "error.h" diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h index 8393bf374b2..a985cd29b6d 100644 --- a/include/asm-alpha/pgtable.h +++ b/include/asm-alpha/pgtable.h @@ -17,6 +17,9 @@ #include /* For TASK_SIZE */ #include +struct mm_struct; +struct vm_area_struct; + /* Certain architectures need to do special things when PTEs * within a page table are directly modified. Thus, the following * hook is made available. diff --git a/include/asm-cris/processor.h b/include/asm-cris/processor.h index e8b2abb2ae5..dce41009eeb 100644 --- a/include/asm-cris/processor.h +++ b/include/asm-cris/processor.h @@ -16,6 +16,8 @@ #include #include +struct task_struct; + /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ diff --git a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h index b247e99dff4..844666377dc 100644 --- a/include/asm-frv/pgtable.h +++ b/include/asm-frv/pgtable.h @@ -26,6 +26,8 @@ #include #include #include +struct mm_struct; +struct vm_area_struct; #endif #ifndef __ASSEMBLY__ diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index 7dca30a26c5..358e4d309ce 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -128,6 +128,7 @@ do { \ #endif #ifndef __HAVE_ARCH_PTEP_SET_WRPROTECT +struct mm_struct; static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long address, pte_t *ptep) { pte_t old_pte = *ptep; diff --git a/include/asm-i386/elf.h b/include/asm-i386/elf.h index fa11117d3cf..4153d80e4d2 100644 --- a/include/asm-i386/elf.h +++ b/include/asm-i386/elf.h @@ -119,6 +119,8 @@ typedef struct user_fxsr_struct elf_fpxregset_t; */ #define elf_read_implies_exec(ex, executable_stack) (executable_stack != EXSTACK_DISABLE_X) +struct task_struct; + extern int dump_task_regs (struct task_struct *, elf_gregset_t *); extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *); extern int dump_task_extended_fpu (struct task_struct *, struct user_fxsr_struct *); diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h index 03f3c8ac638..088a945bf26 100644 --- a/include/asm-i386/pgtable.h +++ b/include/asm-i386/pgtable.h @@ -25,6 +25,9 @@ #include #include +struct mm_struct; +struct vm_area_struct; + /* * ZERO_PAGE is a global shared page that is always zero: used * for zero-mapped memory areas etc.. diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h index 21e32a06bc8..c34ba80c1c3 100644 --- a/include/asm-ia64/pgtable.h +++ b/include/asm-ia64/pgtable.h @@ -127,6 +127,7 @@ # ifndef __ASSEMBLY__ +#include /* for mm_struct */ #include #include #include diff --git a/include/asm-m32r/pgtable.h b/include/asm-m32r/pgtable.h index 1cd5fd4a5b2..75740debcd0 100644 --- a/include/asm-m32r/pgtable.h +++ b/include/asm-m32r/pgtable.h @@ -27,6 +27,9 @@ #include #include +struct mm_struct; +struct vm_area_struct; + extern pgd_t swapper_pg_dir[1024]; extern void paging_init(void); diff --git a/include/asm-mips/elf.h b/include/asm-mips/elf.h index 7420f12742b..d2c9a25f845 100644 --- a/include/asm-mips/elf.h +++ b/include/asm-mips/elf.h @@ -275,6 +275,8 @@ do { \ #endif /* CONFIG_64BIT */ +struct task_struct; + extern void dump_regs(elf_greg_t *, struct pt_regs *regs); extern int dump_task_regs (struct task_struct *, elf_gregset_t *); extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *); diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h index 34facd99650..702a28fa7a3 100644 --- a/include/asm-mips/pgtable.h +++ b/include/asm-mips/pgtable.h @@ -19,6 +19,9 @@ #include #include +struct mm_struct; +struct vm_area_struct; + #define PAGE_NONE __pgprot(_PAGE_PRESENT | _CACHE_CACHABLE_NONCOHERENT) #define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ PAGE_CACHABLE_DEFAULT) diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h index c28fb6f48c6..b4554711c3e 100644 --- a/include/asm-parisc/pgtable.h +++ b/include/asm-parisc/pgtable.h @@ -12,6 +12,7 @@ */ #include +#include /* for vm_area_struct */ #include #include #include @@ -418,7 +419,6 @@ extern void paging_init (void); #define PG_dcache_dirty PG_arch_1 -struct vm_area_struct; /* forward declaration (include/linux/mm.h) */ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); /* Encode and de-code a swap entry */ @@ -464,6 +464,7 @@ static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned extern spinlock_t pa_dbit_lock; +struct mm_struct; static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { pte_t old_pte; diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h index d140577d0a0..feac3458d71 100644 --- a/include/asm-powerpc/elf.h +++ b/include/asm-powerpc/elf.h @@ -1,11 +1,13 @@ #ifndef _ASM_POWERPC_ELF_H #define _ASM_POWERPC_ELF_H +#include /* for task_struct */ #include #include #include #include #include +#include /* PowerPC relocations defined by the ABIs */ #define R_PPC_NONE 0 diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h index b28a713ba86..6d1c39e8a6a 100644 --- a/include/asm-ppc/pgtable.h +++ b/include/asm-ppc/pgtable.h @@ -12,6 +12,7 @@ #include /* For TASK_SIZE */ #include #include +struct mm_struct; extern unsigned long va_to_phys(unsigned long address); extern pte_t *va_to_pte(unsigned long address); diff --git a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h index fde93ec36ab..a9783ba7fe9 100644 --- a/include/asm-ppc64/pgtable.h +++ b/include/asm-ppc64/pgtable.h @@ -13,6 +13,7 @@ #include #include #include +struct mm_struct; #endif /* __ASSEMBLY__ */ #ifdef CONFIG_PPC_64K_PAGES diff --git a/include/asm-s390/elf.h b/include/asm-s390/elf.h index 3b8bd46832a..372d51cccd5 100644 --- a/include/asm-s390/elf.h +++ b/include/asm-s390/elf.h @@ -96,6 +96,7 @@ * ELF register definitions.. */ +#include /* for task_struct */ #include #include #include /* for save_access_regs */ diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h index df94f89038c..9be741bb149 100644 --- a/include/asm-s390/pgtable.h +++ b/include/asm-s390/pgtable.h @@ -36,6 +36,7 @@ #include struct vm_area_struct; /* forward declaration (include/linux/mm.h) */ +struct mm_struct; extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096))); extern void paging_init(void); diff --git a/include/asm-sh/elf.h b/include/asm-sh/elf.h index 8fe00a1981c..1b63dfeea4f 100644 --- a/include/asm-sh/elf.h +++ b/include/asm-sh/elf.h @@ -111,6 +111,7 @@ typedef struct user_fpu_struct elf_fpregset_t; #ifdef __KERNEL__ #define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT) +struct task_struct; extern int dump_task_regs (struct task_struct *, elf_gregset_t *); extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *); diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h index dee36bcbcf9..bb0efb31a8c 100644 --- a/include/asm-sh/pgtable.h +++ b/include/asm-sh/pgtable.h @@ -284,6 +284,8 @@ typedef pte_t *pte_addr_t; #define GET_IOSPACE(pfn) 0 #define GET_PFN(pfn) (pfn) +struct mm_struct; + /* * No page table caches to initialise */ diff --git a/include/asm-sh64/pgtable.h b/include/asm-sh64/pgtable.h index 51b05818e4e..a1906a772df 100644 --- a/include/asm-sh64/pgtable.h +++ b/include/asm-sh64/pgtable.h @@ -24,6 +24,8 @@ #include #include +struct vm_area_struct; + extern void paging_init(void); /* We provide our own get_unmapped_area to avoid cache synonym issue */ diff --git a/include/asm-x86_64/elf.h b/include/asm-x86_64/elf.h index a60a35e7922..43862cd6a56 100644 --- a/include/asm-x86_64/elf.h +++ b/include/asm-x86_64/elf.h @@ -149,6 +149,8 @@ extern void set_personality_64bit(void); */ #define elf_read_implies_exec(ex, executable_stack) (executable_stack != EXSTACK_DISABLE_X) +struct task_struct; + extern int dump_task_regs (struct task_struct *, elf_gregset_t *); extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *); diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h index 7a07196a720..7309fffeec9 100644 --- a/include/asm-x86_64/pgtable.h +++ b/include/asm-x86_64/pgtable.h @@ -105,6 +105,8 @@ static inline void pgd_clear (pgd_t * pgd) #define ptep_get_and_clear(mm,addr,xp) __pte(xchg(&(xp)->pte, 0)) +struct mm_struct; + static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full) { pte_t pte; diff --git a/include/asm-xtensa/elf.h b/include/asm-xtensa/elf.h index 64f1f53874f..de0667453b2 100644 --- a/include/asm-xtensa/elf.h +++ b/include/asm-xtensa/elf.h @@ -209,6 +209,8 @@ extern void xtensa_elf_core_copy_regs (xtensa_gregset_t *, struct pt_regs *); #define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT) +struct task_struct; + extern void do_copy_regs (xtensa_gregset_t*, struct pt_regs*, struct task_struct*); extern void do_restore_regs (xtensa_gregset_t*, struct pt_regs*, diff --git a/include/asm-xtensa/pgtable.h b/include/asm-xtensa/pgtable.h index 987e3b80231..7b15afb70c5 100644 --- a/include/asm-xtensa/pgtable.h +++ b/include/asm-xtensa/pgtable.h @@ -278,6 +278,8 @@ static inline void update_pte(pte_t *ptep, pte_t pteval) #endif } +struct mm_struct; + static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval) { @@ -294,6 +296,7 @@ set_pmd(pmd_t *pmdp, pmd_t pmdval) #endif } +struct vm_area_struct; static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, diff --git a/include/linux/irq.h b/include/linux/irq.h index 69681c3b1f0..c516382fbec 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -10,6 +10,7 @@ */ #include +#include /* cpu_online_map */ #if !defined(CONFIG_ARCH_S390) diff --git a/include/linux/memory.h b/include/linux/memory.h index 0def328ab5c..9a424383e6c 100644 --- a/include/linux/memory.h +++ b/include/linux/memory.h @@ -54,6 +54,9 @@ struct memory_block { */ #define MEM_MAPPING_INVALID (1<<3) +struct notifier_block; +struct mem_section; + #ifndef CONFIG_MEMORY_HOTPLUG static inline int memory_dev_init(void) { diff --git a/include/linux/sem.h b/include/linux/sem.h index 106f9757339..3c1f1120fe8 100644 --- a/include/linux/sem.h +++ b/include/linux/sem.h @@ -79,6 +79,8 @@ struct seminfo { #ifdef __KERNEL__ +struct task_struct; + /* One semaphore structure for each semaphore in the system. */ struct sem { int semval; /* current value */ diff --git a/include/linux/wait.h b/include/linux/wait.h index d38c9fecdc3..d28518236b6 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -54,6 +54,7 @@ struct __wait_queue_head { }; typedef struct __wait_queue_head wait_queue_head_t; +struct task_struct; /* * Macros for declaration and initialisaton of the datatypes diff --git a/kernel/module.c b/kernel/module.c index ff5c500ab62..2ea929d51ad 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 2cf06916217b5dcb2cc52a495e1f130cc8434ef5 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 00:59:44 -0800 Subject: [PATCH] befs: use generic_ro_fops No need to duplicate a generic readonly file ops table in befs. Signed-off-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/befs/linuxvfs.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index e0a6025f1d0..e8112ad5365 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -73,12 +73,6 @@ static struct inode_operations befs_dir_inode_operations = { .lookup = befs_lookup, }; -static struct file_operations befs_file_operations = { - .llseek = default_llseek, - .read = generic_file_read, - .mmap = generic_file_readonly_mmap, -}; - static struct address_space_operations befs_aops = { .readpage = befs_readpage, .sync_page = block_sync_page, @@ -398,7 +392,7 @@ befs_read_inode(struct inode *inode) inode->i_mapping->a_ops = &befs_aops; if (S_ISREG(inode->i_mode)) { - inode->i_fop = &befs_file_operations; + inode->i_fop = &generic_ro_fops; } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &befs_dir_inode_operations; inode->i_fop = &befs_dir_operations; -- cgit v1.2.3 From dc487002a26a5733967292356434e61dc5da9c98 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 00:59:45 -0800 Subject: [PATCH] vxfs: use generic_ro_fops No need to duplicate a generic readonly file ops table in befs. Signed-off-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/freevxfs/vxfs_inode.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c index 9672d2facff..f544aae9169 100644 --- a/fs/freevxfs/vxfs_inode.c +++ b/fs/freevxfs/vxfs_inode.c @@ -46,15 +46,6 @@ extern struct address_space_operations vxfs_immed_aops; extern struct inode_operations vxfs_immed_symlink_iops; -static struct file_operations vxfs_file_operations = { - .open = generic_file_open, - .llseek = generic_file_llseek, - .read = generic_file_read, - .mmap = generic_file_mmap, - .sendfile = generic_file_sendfile, -}; - - kmem_cache_t *vxfs_inode_cachep; @@ -318,7 +309,7 @@ vxfs_read_inode(struct inode *ip) aops = &vxfs_aops; if (S_ISREG(ip->i_mode)) { - ip->i_fop = &vxfs_file_operations; + ip->i_fop = &generic_ro_fops; ip->i_mapping->a_ops = aops; } else if (S_ISDIR(ip->i_mode)) { ip->i_op = &vxfs_dir_inode_ops; -- cgit v1.2.3 From a463ddd343dacf5f1badae514ed2c5135ec0c3a9 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 00:59:46 -0800 Subject: [PATCH] afs: use generic_ro_fops afs actually had a write method that returned different errors depending on whether some flag was set - better return the standard EINVAL errno. Signed-off-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/afs/file.c | 30 ------------------------------ fs/afs/inode.c | 2 +- fs/afs/internal.h | 1 - 3 files changed, 1 insertion(+), 32 deletions(-) diff --git a/fs/afs/file.c b/fs/afs/file.c index 4975c9c193d..f53971a543b 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -31,24 +31,10 @@ static int afs_file_readpage(struct file *file, struct page *page); static int afs_file_invalidatepage(struct page *page, unsigned long offset); static int afs_file_releasepage(struct page *page, gfp_t gfp_flags); -static ssize_t afs_file_write(struct file *file, const char __user *buf, - size_t size, loff_t *off); - struct inode_operations afs_file_inode_operations = { .getattr = afs_inode_getattr, }; -struct file_operations afs_file_file_operations = { - .read = generic_file_read, - .write = afs_file_write, - .mmap = generic_file_mmap, -#if 0 - .open = afs_file_open, - .release = afs_file_release, - .fsync = afs_file_fsync, -#endif -}; - struct address_space_operations afs_fs_aops = { .readpage = afs_file_readpage, .sync_page = block_sync_page, @@ -57,22 +43,6 @@ struct address_space_operations afs_fs_aops = { .invalidatepage = afs_file_invalidatepage, }; -/*****************************************************************************/ -/* - * AFS file write - */ -static ssize_t afs_file_write(struct file *file, const char __user *buf, - size_t size, loff_t *off) -{ - struct afs_vnode *vnode; - - vnode = AFS_FS_I(file->f_dentry->d_inode); - if (vnode->flags & AFS_VNODE_DELETED) - return -ESTALE; - - return -EIO; -} /* end afs_file_write() */ - /*****************************************************************************/ /* * deal with notification that a page was read from the cache diff --git a/fs/afs/inode.c b/fs/afs/inode.c index c476fde33fb..4ebb30a50ed 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -49,7 +49,7 @@ static int afs_inode_map_status(struct afs_vnode *vnode) case AFS_FTYPE_FILE: inode->i_mode = S_IFREG | vnode->status.mode; inode->i_op = &afs_file_inode_operations; - inode->i_fop = &afs_file_file_operations; + inode->i_fop = &generic_ro_fops; break; case AFS_FTYPE_DIR: inode->i_mode = S_IFDIR | vnode->status.mode; diff --git a/fs/afs/internal.h b/fs/afs/internal.h index f09860b45c1..ab8f87c6631 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -71,7 +71,6 @@ extern struct file_operations afs_dir_file_operations; */ extern struct address_space_operations afs_fs_aops; extern struct inode_operations afs_file_inode_operations; -extern struct file_operations afs_file_file_operations; #ifdef AFS_CACHING_SUPPORT extern int afs_cache_get_page_cookie(struct page *page, -- cgit v1.2.3 From db73e9aa99bf093427b79877f9475392724fd5e5 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 00:59:46 -0800 Subject: [PATCH] remove superflous ctime/mtime updates in affs Both AFFS and HPFS update the ctime and mtime in the write path, after generic_file_write returned and marked the inode dirty. Signed-off-by: Christoph Hellwig Acked-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/affs/file.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/fs/affs/file.c b/fs/affs/file.c index 6744924b690..f72fb776ecd 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -22,14 +22,13 @@ static int affs_grow_extcache(struct inode *inode, u32 lc_idx); static struct buffer_head *affs_alloc_extblock(struct inode *inode, struct buffer_head *bh, u32 ext); static inline struct buffer_head *affs_get_extblock(struct inode *inode, u32 ext); static struct buffer_head *affs_get_extblock_slow(struct inode *inode, u32 ext); -static ssize_t affs_file_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos); static int affs_file_open(struct inode *inode, struct file *filp); static int affs_file_release(struct inode *inode, struct file *filp); struct file_operations affs_file_operations = { .llseek = generic_file_llseek, .read = generic_file_read, - .write = affs_file_write, + .write = generic_file_write, .mmap = generic_file_mmap, .open = affs_file_open, .release = affs_file_release, @@ -473,21 +472,6 @@ affs_getemptyblk_ino(struct inode *inode, int block) return ERR_PTR(err); } -static ssize_t -affs_file_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - ssize_t retval; - - retval = generic_file_write (file, buf, count, ppos); - if (retval >0) { - struct inode *inode = file->f_dentry->d_inode; - inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; - mark_inode_dirty(inode); - } - return retval; -} - static int affs_do_readpage_ofs(struct file *file, struct page *page, unsigned from, unsigned to) { -- cgit v1.2.3 From 481bed454247538e9f57d4ea37b153ccba24ba7b Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 00:59:47 -0800 Subject: [PATCH] consolidate sys_ptrace() The sys_ptrace boilerplate code (everything outside the big switch statement for the arch-specific requests) is shared by most architectures. This patch moves it to kernel/ptrace.c and leaves the arch-specific code as arch_ptrace. Some architectures have a too different ptrace so we have to exclude them. They continue to keep their implementations. For sh64 I had to add a sh64_ptrace wrapper because it does some initialization on the first call. For um I removed an ifdefed SUBARCH_PTRACE_SPECIAL block, but SUBARCH_PTRACE_SPECIAL isn't defined anywhere in the tree. Signed-off-by: Christoph Hellwig Acked-by: Paul Mackerras Acked-by: Ralf Baechle Acked-By: David Howells Acked-by: Russell King Acked-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/kernel/ptrace.c | 49 +--------------------- arch/arm26/kernel/ptrace.c | 49 +--------------------- arch/cris/arch-v10/kernel/ptrace.c | 51 +---------------------- arch/cris/arch-v32/kernel/ptrace.c | 51 +---------------------- arch/frv/kernel/ptrace.c | 43 +------------------- arch/h8300/kernel/ptrace.c | 39 +----------------- arch/i386/kernel/ptrace.c | 44 +------------------- arch/m68k/kernel/ptrace.c | 47 ++------------------- arch/m68knommu/kernel/ptrace.c | 39 +----------------- arch/mips/kernel/ptrace.c | 55 +++---------------------- arch/parisc/kernel/ptrace.c | 50 ++--------------------- arch/powerpc/kernel/ptrace.c | 43 +------------------- arch/sh/kernel/ptrace.c | 44 +------------------- arch/sh64/kernel/ptrace.c | 83 +++++++++++++------------------------- arch/sh64/kernel/syscalls.S | 2 +- arch/um/kernel/ptrace.c | 50 +---------------------- arch/v850/kernel/ptrace.c | 43 +------------------- arch/x86_64/kernel/ptrace.c | 43 +------------------- arch/xtensa/kernel/ptrace.c | 55 +------------------------ include/asm-alpha/ptrace.h | 3 ++ include/asm-ia64/ptrace.h | 3 ++ include/asm-m32r/ptrace.h | 3 ++ include/asm-s390/ptrace.h | 2 + include/asm-sparc/ptrace.h | 3 ++ include/asm-sparc64/ptrace.h | 3 ++ include/linux/ptrace.h | 2 + kernel/ptrace.c | 82 +++++++++++++++++++++++++++++++++++++ 27 files changed, 163 insertions(+), 818 deletions(-) diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 9bd8609a292..9a340e790da 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -648,7 +648,7 @@ static int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp) #endif -static int do_ptrace(int request, struct task_struct *child, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { unsigned long tmp; int ret; @@ -782,53 +782,6 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat return ret; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) -{ - struct task_struct *child; - int ret; - - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret == 0) - ret = do_ptrace(request, child, addr, data); - -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); - return ret; -} - asmlinkage void syscall_trace(int why, struct pt_regs *regs) { unsigned long ip; diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c index cf7e977d18c..4e6b7356a72 100644 --- a/arch/arm26/kernel/ptrace.c +++ b/arch/arm26/kernel/ptrace.c @@ -546,7 +546,7 @@ static int ptrace_setfpregs(struct task_struct *tsk, void *ufp) sizeof(struct user_fp)) ? -EFAULT : 0; } -static int do_ptrace(int request, struct task_struct *child, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { unsigned long tmp; int ret; @@ -665,53 +665,6 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat return ret; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) -{ - struct task_struct *child; - int ret; - - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret == 0) - ret = do_ptrace(request, child, addr, data); - -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); - return ret; -} - asmlinkage void syscall_trace(int why, struct pt_regs *regs) { unsigned long ip; diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c index 130dd214e41..6cbd34a27b9 100644 --- a/arch/cris/arch-v10/kernel/ptrace.c +++ b/arch/cris/arch-v10/kernel/ptrace.c @@ -76,55 +76,11 @@ ptrace_disable(struct task_struct *child) * (in user space) where the result of the ptrace call is written (instead of * being returned). */ -asmlinkage int -sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int ret; unsigned long __user *datap = (unsigned long __user *)data; - lock_kernel(); - ret = -EPERM; - - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - - if (child) - get_task_struct(child); - - read_unlock(&tasklist_lock); - - if (!child) - goto out; - - ret = -EPERM; - - if (pid == 1) /* Leave the init process alone! */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* Read word at location address. */ case PTRACE_PEEKTEXT: @@ -289,10 +245,7 @@ sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + return ret; } diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c index 208489da2a8..5528b83a622 100644 --- a/arch/cris/arch-v32/kernel/ptrace.c +++ b/arch/cris/arch-v32/kernel/ptrace.c @@ -99,55 +99,11 @@ ptrace_disable(struct task_struct *child) } -asmlinkage int -sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int ret; unsigned long __user *datap = (unsigned long __user *)data; - lock_kernel(); - ret = -EPERM; - - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - - if (child) - get_task_struct(child); - - read_unlock(&tasklist_lock); - - if (!child) - goto out; - - ret = -EPERM; - - if (pid == 1) /* Leave the init process alone! */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* Read word at location address. */ case PTRACE_PEEKTEXT: @@ -347,10 +303,7 @@ sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + return ret; } diff --git a/arch/frv/kernel/ptrace.c b/arch/frv/kernel/ptrace.c index cb335a14a31..f953484e7d5 100644 --- a/arch/frv/kernel/ptrace.c +++ b/arch/frv/kernel/ptrace.c @@ -106,48 +106,11 @@ void ptrace_enable(struct task_struct *child) child->thread.frame0->__status |= REG__STATUS_STEP; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; unsigned long tmp; int ret; - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -351,10 +314,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = -EIO; break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); return ret; } diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c index a569fe4aa28..0ff6f79b0fe 100644 --- a/arch/h8300/kernel/ptrace.c +++ b/arch/h8300/kernel/ptrace.c @@ -57,43 +57,10 @@ void ptrace_disable(struct task_struct *child) h8300_disable_trace(child); } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int ret; - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: { @@ -251,10 +218,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = -EIO; break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); return ret; } diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index efd11f09c99..5ffbb4b7ad0 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c @@ -354,49 +354,12 @@ ptrace_set_thread_area(struct task_struct *child, return 0; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; struct user * dummy = NULL; int i, ret; unsigned long __user *datap = (unsigned long __user *)data; - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -663,10 +626,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + out_tsk: return ret; } diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index f7f1d2e5b90..7e54422685c 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c @@ -121,48 +121,11 @@ void ptrace_disable(struct task_struct *child) child->thread.work.syscall_trace = 0; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; unsigned long tmp; int i, ret = 0; - lock_kernel(); - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) { - ret = -EPERM; - goto out; - } - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - goto out; - } - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (unlikely(!child)) { - ret = -ESRCH; - goto out; - } - - /* you may not mess with init */ - if (unlikely(pid == 1)) { - ret = -EPERM; - goto out_tsk; - } - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -317,14 +280,10 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + return ret; out_eio: - ret = -EIO; - goto out_tsk; + return -EIO; } asmlinkage void syscall_trace(void) diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c index 621d7b91ccf..262ab8c72e5 100644 --- a/arch/m68knommu/kernel/ptrace.c +++ b/arch/m68knommu/kernel/ptrace.c @@ -101,43 +101,10 @@ void ptrace_disable(struct task_struct *child) put_reg(child, PT_SR, tmp); } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(truct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int ret; - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -357,10 +324,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = -EIO; break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); return ret; } diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index f1b0f3e1f95..510da5fda56 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -174,51 +174,10 @@ int ptrace_setfpregs (struct task_struct *child, __u32 __user *data) return 0; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int ret; -#if 0 - printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n", - (int) request, (int) pid, (unsigned long) addr, - (unsigned long) data); -#endif - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - if ((ret = security_ptrace(current->parent, current))) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -319,7 +278,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) if (!cpu_has_dsp) { tmp = 0; ret = -EIO; - goto out_tsk; + goto out; } if (child->thread.dsp.used_dsp) { dregs = __get_dsp_regs(child); @@ -333,14 +292,14 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) if (!cpu_has_dsp) { tmp = 0; ret = -EIO; - goto out_tsk; + goto out; } tmp = child->thread.dsp.dspcontrol; break; default: tmp = 0; ret = -EIO; - goto out_tsk; + goto out; } ret = put_user(tmp, (unsigned long __user *) data); break; @@ -495,11 +454,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } - -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + out: return ret; } diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index 18130c3748f..b6fe202a620 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c @@ -78,52 +78,13 @@ void ptrace_disable(struct task_struct *child) pa_psw(child)->l = 0; } -long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; long ret; #ifdef DEBUG_PTRACE long oaddr=addr, odata=data; #endif - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - ret = -EPERM; - if (pid == 1) /* no messing around with init! */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: { @@ -383,11 +344,11 @@ long sys_ptrace(long request, long pid, long addr, long data) case PTRACE_GETEVENTMSG: ret = put_user(child->ptrace_message, (unsigned int __user *) data); - goto out_tsk; + goto out; default: ret = ptrace_request(child, request, addr, data); - goto out_tsk; + goto out; } out_wake_notrap: @@ -396,10 +357,7 @@ out_wake: wake_up_process(child); ret = 0; out_tsk: - put_task_struct(child); -out: - unlock_kernel(); - DBG("sys_ptrace(%ld, %d, %lx, %lx) returning %ld\n", + DBG("arch_ptrace(%ld, %d, %lx, %lx) returning %ld\n", request, pid, oaddr, odata, ret); return ret; } diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 568ea335d61..3d2abd95c7a 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -248,46 +248,10 @@ void ptrace_disable(struct task_struct *child) clear_single_step(child); } -long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int ret = -EPERM; - lock_kernel(); - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -540,10 +504,7 @@ long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + return ret; } diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c index 1fbe5a428e3..1a8be06519e 100644 --- a/arch/sh/kernel/ptrace.c +++ b/arch/sh/kernel/ptrace.c @@ -80,48 +80,11 @@ void ptrace_disable(struct task_struct *child) /* nothing to do.. */ } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; struct user * dummy = NULL; int ret; - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -289,10 +252,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + return ret; } diff --git a/arch/sh64/kernel/ptrace.c b/arch/sh64/kernel/ptrace.c index 71f2eec00b9..cd22e947131 100644 --- a/arch/sh64/kernel/ptrace.c +++ b/arch/sh64/kernel/ptrace.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -121,61 +122,11 @@ put_fpu_long(struct task_struct *task, unsigned long addr, unsigned long data) return 0; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) + +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; - extern void poke_real_address_q(unsigned long long addr, unsigned long long data); -#define WPC_DBRMODE 0x0d104008 - static int first_call = 1; int ret; - lock_kernel(); - - if (first_call) { - /* Set WPC.DBRMODE to 0. This makes all debug events get - * delivered through RESVEC, i.e. into the handlers in entry.S. - * (If the kernel was downloaded using a remote gdb, WPC.DBRMODE - * would normally be left set to 1, which makes debug events get - * delivered through DBRVEC, i.e. into the remote gdb's - * handlers. This prevents ptrace getting them, and confuses - * the remote gdb.) */ - printk("DBRMODE set to 0 to permit native debugging\n"); - poke_real_address_q(WPC_DBRMODE, 0); - first_call = 0; - } - - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -313,13 +264,33 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); return ret; } +asmlinkage int sh64_ptrace(long request, long pid, long addr, long data) +{ + extern void poke_real_address_q(unsigned long long addr, unsigned long long data); +#define WPC_DBRMODE 0x0d104008 + static int first_call = 1; + + lock_kernel(); + if (first_call) { + /* Set WPC.DBRMODE to 0. This makes all debug events get + * delivered through RESVEC, i.e. into the handlers in entry.S. + * (If the kernel was downloaded using a remote gdb, WPC.DBRMODE + * would normally be left set to 1, which makes debug events get + * delivered through DBRVEC, i.e. into the remote gdb's + * handlers. This prevents ptrace getting them, and confuses + * the remote gdb.) */ + printk("DBRMODE set to 0 to permit native debugging\n"); + poke_real_address_q(WPC_DBRMODE, 0); + first_call = 0; + } + unlock_kernel(); + + return sys_ptrace(request, pid, addr, data); +} + asmlinkage void syscall_trace(void) { struct task_struct *tsk = current; diff --git a/arch/sh64/kernel/syscalls.S b/arch/sh64/kernel/syscalls.S index a3d037805f1..c0079d54c85 100644 --- a/arch/sh64/kernel/syscalls.S +++ b/arch/sh64/kernel/syscalls.S @@ -46,7 +46,7 @@ sys_call_table: .long sys_setuid16 .long sys_getuid16 .long sys_stime /* 25 */ - .long sys_ptrace + .long sh64_ptrace .long sys_alarm .long sys_fstat .long sys_pause diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 71af4d50389..98e09395c09 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -43,53 +43,10 @@ void ptrace_disable(struct task_struct *child) extern int peek_user(struct task_struct * child, long addr, long data); extern int poke_user(struct task_struct * child, long addr, long data); -long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int i, ret; - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - -#ifdef SUBACH_PTRACE_SPECIAL - SUBARCH_PTRACE_SPECIAL(child,request,addr,data); -#endif - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -282,10 +239,7 @@ long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } - out_tsk: - put_task_struct(child); - out: - unlock_kernel(); + return ret; } diff --git a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c index d6077ff47d2..18492d02aaf 100644 --- a/arch/v850/kernel/ptrace.c +++ b/arch/v850/kernel/ptrace.c @@ -113,45 +113,10 @@ static int set_single_step (struct task_struct *t, int val) return 1; } -long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int rval; - lock_kernel(); - - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) { - rval = -EPERM; - goto out; - } - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - rval = 0; - goto out; - } - rval = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - rval = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - rval = ptrace_attach(child); - goto out_tsk; - } - rval = ptrace_check_attach(child, request == PTRACE_KILL); - if (rval < 0) - goto out_tsk; - switch (request) { unsigned long val, copied; @@ -248,11 +213,7 @@ long sys_ptrace(long request, long pid, long addr, long data) rval = -EIO; goto out; } - -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + out: return rval; } diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c index bbf64b59a21..a87b6cebe80 100644 --- a/arch/x86_64/kernel/ptrace.c +++ b/arch/x86_64/kernel/ptrace.c @@ -313,48 +313,11 @@ static unsigned long getreg(struct task_struct *child, unsigned long regno) } -asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; long i, ret; unsigned ui; - /* This lock_kernel fixes a subtle race with suid exec */ - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -608,10 +571,6 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); return ret; } diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c index 14460743de0..ab5c4c65b5c 100644 --- a/arch/xtensa/kernel/ptrace.c +++ b/arch/xtensa/kernel/ptrace.c @@ -45,58 +45,10 @@ void ptrace_disable(struct task_struct *child) /* Nothing to do.. */ } -long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int ret = -EPERM; - lock_kernel(); - -#if 0 - if ((int)request != 1) - printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n", - (int) request, (int) pid, (unsigned long) addr, - (unsigned long) data); -#endif - - if (request == PTRACE_TRACEME) { - - /* Are we already being traced? */ - - if (current->ptrace & PT_PTRACED) - goto out; - - if ((ret = security_ptrace(current->parent, current))) - goto out; - - /* Set the ptrace bit in the process flags. */ - - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - if ((ret = ptrace_check_attach(child, request == PTRACE_KILL)) < 0) - goto out_tsk; - switch (request) { case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: @@ -375,10 +327,7 @@ long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); goto out; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + out: return ret; } diff --git a/include/asm-alpha/ptrace.h b/include/asm-alpha/ptrace.h index d462c5e14c1..072375c135b 100644 --- a/include/asm-alpha/ptrace.h +++ b/include/asm-alpha/ptrace.h @@ -67,6 +67,9 @@ struct switch_stack { }; #ifdef __KERNEL__ + +#define __ARCH_SYS_PTRACE 1 + #define user_mode(regs) (((regs)->ps & 8) != 0) #define instruction_pointer(regs) ((regs)->pc) #define profile_pc(regs) instruction_pointer(regs) diff --git a/include/asm-ia64/ptrace.h b/include/asm-ia64/ptrace.h index a79d1a7ecc7..2c703d6e0c8 100644 --- a/include/asm-ia64/ptrace.h +++ b/include/asm-ia64/ptrace.h @@ -229,6 +229,9 @@ struct switch_stack { }; #ifdef __KERNEL__ + +#define __ARCH_SYS_PTRACE 1 + /* * We use the ia64_psr(regs)->ri to determine which of the three * instructions in bundle (16 bytes) took the sample. Generate diff --git a/include/asm-m32r/ptrace.h b/include/asm-m32r/ptrace.h index 976417126b2..55cd7ecfde4 100644 --- a/include/asm-m32r/ptrace.h +++ b/include/asm-m32r/ptrace.h @@ -145,6 +145,9 @@ struct pt_regs { #define PTRACE_O_TRACESYSGOOD 0x00000001 #ifdef __KERNEL__ + +#define __ARCH_SYS_PTRACE 1 + #if defined(CONFIG_ISA_M32R2) || defined(CONFIG_CHIP_VDEC2) #define user_mode(regs) ((M32R_PSW_BPM & (regs)->psw) != 0) #elif defined(CONFIG_ISA_M32R) diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h index fc7c96edc69..a949cc077cc 100644 --- a/include/asm-s390/ptrace.h +++ b/include/asm-s390/ptrace.h @@ -468,6 +468,8 @@ struct user_regs_struct }; #ifdef __KERNEL__ +#define __ARCH_SYS_PTRACE 1 + #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0) #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN) #define profile_pc(regs) instruction_pointer(regs) diff --git a/include/asm-sparc/ptrace.h b/include/asm-sparc/ptrace.h index a8ecb2d6977..714497099a4 100644 --- a/include/asm-sparc/ptrace.h +++ b/include/asm-sparc/ptrace.h @@ -60,6 +60,9 @@ struct sparc_stackf { #define STACKFRAME_SZ sizeof(struct sparc_stackf) #ifdef __KERNEL__ + +#define __ARCH_SYS_PTRACE 1 + #define user_mode(regs) (!((regs)->psr & PSR_PS)) #define instruction_pointer(regs) ((regs)->pc) unsigned long profile_pc(struct pt_regs *); diff --git a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h index 6194f771e9f..7eba90c6c75 100644 --- a/include/asm-sparc64/ptrace.h +++ b/include/asm-sparc64/ptrace.h @@ -94,6 +94,9 @@ struct sparc_trapf { #define STACKFRAME32_SZ sizeof(struct sparc_stackf32) #ifdef __KERNEL__ + +#define __ARCH_SYS_PTRACE 1 + #define force_successful_syscall_return() \ do { current_thread_info()->syscall_noerror = 1; \ } while (0) diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index dc6f3647bfb..b2b3dba1298 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h @@ -78,6 +78,8 @@ #include /* For unlikely. */ #include /* For struct task_struct. */ + +extern long arch_ptrace(struct task_struct *child, long request, long addr, long data); extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); extern int ptrace_attach(struct task_struct *tsk); diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 863eee8bff4..5b8dd98a230 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -406,3 +406,85 @@ int ptrace_request(struct task_struct *child, long request, return ret; } + +#ifndef __ARCH_SYS_PTRACE +static int ptrace_get_task_struct(long request, long pid, + struct task_struct **childp) +{ + struct task_struct *child; + int ret; + + /* + * Callers use child == NULL as an indication to exit early even + * when the return value is 0, so make sure it is non-NULL here. + */ + *childp = NULL; + + if (request == PTRACE_TRACEME) { + /* + * Are we already being traced? + */ + if (current->ptrace & PT_PTRACED) + return -EPERM; + ret = security_ptrace(current->parent, current); + if (ret) + return -EPERM; + /* + * Set the ptrace bit in the process ptrace flags. + */ + current->ptrace |= PT_PTRACED; + return 0; + } + + /* + * You may not mess with init + */ + if (pid == 1) + return -EPERM; + + ret = -ESRCH; + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); + if (!child) + return -ESRCH; + + *childp = child; + return 0; +} + +asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +{ + struct task_struct *child; + long ret; + + /* + * This lock_kernel fixes a subtle race with suid exec + */ + lock_kernel(); + ret = ptrace_get_task_struct(request, pid, &child); + if (!child) + goto out; + + if (request == PTRACE_ATTACH) { + ret = ptrace_attach(child); + goto out; + } + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (ret < 0) + goto out_put_task_struct; + + ret = arch_ptrace(child, request, addr, data); + if (ret < 0) + goto out_put_task_struct; + + out_put_task_struct: + put_task_struct(child); + out: + unlock_kernel(); + return ret; +} +#endif /* __ARCH_SYS_PTRACE */ -- cgit v1.2.3 From cc4e69dee4a080f6eae3f410daec2593f4fa6f00 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 7 Nov 2005 00:59:49 -0800 Subject: [PATCH] VFS: pass file pointer to filesystem from ftruncate() This patch extends the iattr structure with a file pointer memeber, and adds an ATTR_FILE validity flag for this member. This is set if do_truncate() is invoked from ftruncate() or from do_coredump(). The change is source and binary compatible. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/exec.c | 2 +- fs/namei.c | 2 +- fs/open.c | 10 +++++++--- include/linux/fs.h | 10 +++++++++- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index ce76b33f25a..cd6c574557d 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1511,7 +1511,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) goto close_fail; if (!file->f_op->write) goto close_fail; - if (do_truncate(file->f_dentry, 0) != 0) + if (do_truncate(file->f_dentry, 0, file) != 0) goto close_fail; retval = binfmt->core_dump(signr, regs, file); diff --git a/fs/namei.c b/fs/namei.c index c5769c4fcab..b3f8a1966c9 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1459,7 +1459,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) if (!error) { DQUOT_INIT(inode); - error = do_truncate(dentry, 0); + error = do_truncate(dentry, 0, NULL); } put_write_access(inode); if (error) diff --git a/fs/open.c b/fs/open.c index 2835f096c68..6e8136751e9 100644 --- a/fs/open.c +++ b/fs/open.c @@ -194,7 +194,7 @@ out: return error; } -int do_truncate(struct dentry *dentry, loff_t length) +int do_truncate(struct dentry *dentry, loff_t length, struct file *filp) { int err; struct iattr newattrs; @@ -205,6 +205,10 @@ int do_truncate(struct dentry *dentry, loff_t length) newattrs.ia_size = length; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; + if (filp) { + newattrs.ia_file = filp; + newattrs.ia_valid |= ATTR_FILE; + } down(&dentry->d_inode->i_sem); err = notify_change(dentry, &newattrs); @@ -262,7 +266,7 @@ static inline long do_sys_truncate(const char __user * path, loff_t length) error = locks_verify_truncate(inode, NULL, length); if (!error) { DQUOT_INIT(inode); - error = do_truncate(nd.dentry, length); + error = do_truncate(nd.dentry, length, NULL); } put_write_access(inode); @@ -314,7 +318,7 @@ static inline long do_sys_ftruncate(unsigned int fd, loff_t length, int small) error = locks_verify_truncate(inode, file, length); if (!error) - error = do_truncate(dentry, length); + error = do_truncate(dentry, length, file); out_putf: fput(file); out: diff --git a/include/linux/fs.h b/include/linux/fs.h index 6d6226732c9..0c89fc9481a 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -264,6 +264,7 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset, #define ATTR_ATTR_FLAG 1024 #define ATTR_KILL_SUID 2048 #define ATTR_KILL_SGID 4096 +#define ATTR_FILE 8192 /* * This is the Inode Attributes structure, used for notify_change(). It @@ -283,6 +284,13 @@ struct iattr { struct timespec ia_atime; struct timespec ia_mtime; struct timespec ia_ctime; + + /* + * Not an attribute, but an auxilary info for filesystems wanting to + * implement an ftruncate() like method. NOTE: filesystem should + * check for (ia_valid & ATTR_FILE), and not for (ia_file != NULL). + */ + struct file *ia_file; }; /* @@ -1288,7 +1296,7 @@ static inline int break_lease(struct inode *inode, unsigned int mode) /* fs/open.c */ -extern int do_truncate(struct dentry *, loff_t start); +extern int do_truncate(struct dentry *, loff_t start, struct file *filp); extern long do_sys_open(const char __user *filename, int flags, int mode); extern struct file *filp_open(const char *, int, int); extern struct file * dentry_open(struct dentry *, struct vfsmount *, int); -- cgit v1.2.3 From 5b62073d502a88fedc5c369f8a004bda7c9d1999 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 7 Nov 2005 00:59:49 -0800 Subject: [PATCH] FUSE: bump interface minor version Though the following changes are all backward compatible (from the kernel's as well as the library's POV) change the minor version, so interested applications can detect new features. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/fuse.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/fuse.h b/include/linux/fuse.h index f98854c2abd..6e91c9a3a0b 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -14,7 +14,7 @@ #define FUSE_KERNEL_VERSION 7 /** Minor version number of this interface */ -#define FUSE_KERNEL_MINOR_VERSION 2 +#define FUSE_KERNEL_MINOR_VERSION 3 /** The node ID of the root inode */ #define FUSE_ROOT_ID 1 -- cgit v1.2.3 From 31d40d74b402a6fa18a006fb3745f64609f35b77 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 7 Nov 2005 00:59:50 -0800 Subject: [PATCH] FUSE: add access call Add a new access call, which will only be called if ->permission is invoked from sys_access(). In all other cases permission checking is delayed until the actual filesystem operation. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dir.c | 35 +++++++++++++++++++++++++++++++++++ fs/fuse/fuse_i.h | 3 +++ include/linux/fuse.h | 8 +++++++- 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 61b58fdd973..4bc1afcc476 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -461,6 +461,38 @@ static int fuse_revalidate(struct dentry *entry) return fuse_do_getattr(inode); } +static int fuse_access(struct inode *inode, int mask) +{ + struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_req *req; + struct fuse_access_in inarg; + int err; + + if (fc->no_access) + return 0; + + req = fuse_get_request(fc); + if (!req) + return -EINTR; + + memset(&inarg, 0, sizeof(inarg)); + inarg.mask = mask; + req->in.h.opcode = FUSE_ACCESS; + req->in.h.nodeid = get_node_id(inode); + req->inode = inode; + req->in.numargs = 1; + req->in.args[0].size = sizeof(inarg); + req->in.args[0].value = &inarg; + request_send(fc, req); + err = req->out.h.error; + fuse_put_request(fc, req); + if (err == -ENOSYS) { + fc->no_access = 1; + err = 0; + } + return err; +} + static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) { struct fuse_conn *fc = get_fuse_conn(inode); @@ -493,6 +525,9 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) int mode = inode->i_mode; if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO)) return -EACCES; + + if (nd && (nd->flags & LOOKUP_ACCESS)) + return fuse_access(inode, mask); return 0; } } diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 5cb456f572c..c4e8c3b4798 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -266,6 +266,9 @@ struct fuse_conn { /** Is removexattr not implemented by fs? */ unsigned no_removexattr : 1; + /** Is access not implemented by fs? */ + unsigned no_access : 1; + /** Backing dev info */ struct backing_dev_info bdi; }; diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 6e91c9a3a0b..507913b65af 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -99,7 +99,8 @@ enum fuse_opcode { FUSE_OPENDIR = 27, FUSE_READDIR = 28, FUSE_RELEASEDIR = 29, - FUSE_FSYNCDIR = 30 + FUSE_FSYNCDIR = 30, + FUSE_ACCESS = 34 }; /* Conservative buffer size for the client */ @@ -222,6 +223,11 @@ struct fuse_getxattr_out { __u32 padding; }; +struct fuse_access_in { + __u32 mask; + __u32 padding; +}; + struct fuse_init_in_out { __u32 major; __u32 minor; -- cgit v1.2.3 From fd72faac95d7e47610e981d7ed7b3c1529e55c88 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 7 Nov 2005 00:59:51 -0800 Subject: [PATCH] FUSE: atomic create+open This patch adds an atomic create+open operation. This does not yet work if the file type changes between lookup and create+open, but solves the permission checking problems for the separte create and open methods. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dev.c | 7 +++ fs/fuse/dir.c | 106 ++++++++++++++++++++++++++++++++++++++++- fs/fuse/file.c | 132 +++++++++++++++++++++++++++++++++------------------ fs/fuse/fuse_i.h | 14 ++++++ include/linux/fuse.h | 5 +- 5 files changed, 214 insertions(+), 50 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index a6f90a6c754..8f873e621f4 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -184,6 +184,13 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) fuse_putback_request() */ for (i = 1; i < FUSE_MAX_OUTSTANDING; i++) up(&fc->outstanding_sem); + } else if (req->in.h.opcode == FUSE_RELEASE && req->inode == NULL) { + /* Special case for failed iget in CREATE */ + u64 nodeid = req->in.h.nodeid; + __fuse_get_request(req); + fuse_reset_request(req); + fuse_send_forget(fc, req, nodeid, 1); + putback = 0; } if (putback) fuse_putback_request(fc, req); diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 4bc1afcc476..83be119ef06 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -13,6 +13,7 @@ #include #include #include +#include static inline unsigned long time_to_jiffies(unsigned long sec, unsigned long nsec) @@ -134,6 +135,101 @@ static void fuse_invalidate_entry(struct dentry *entry) entry->d_time = jiffies - 1; } +static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, + struct nameidata *nd) +{ + int err; + struct inode *inode; + struct fuse_conn *fc = get_fuse_conn(dir); + struct fuse_req *req; + struct fuse_open_in inarg; + struct fuse_open_out outopen; + struct fuse_entry_out outentry; + struct fuse_inode *fi; + struct fuse_file *ff; + struct file *file; + int flags = nd->intent.open.flags - 1; + + err = -ENOSYS; + if (fc->no_create) + goto out; + + err = -ENAMETOOLONG; + if (entry->d_name.len > FUSE_NAME_MAX) + goto out; + + err = -EINTR; + req = fuse_get_request(fc); + if (!req) + goto out; + + ff = fuse_file_alloc(); + if (!ff) + goto out_put_request; + + flags &= ~O_NOCTTY; + memset(&inarg, 0, sizeof(inarg)); + inarg.flags = flags; + inarg.mode = mode; + req->in.h.opcode = FUSE_CREATE; + req->in.h.nodeid = get_node_id(dir); + req->inode = dir; + req->in.numargs = 2; + req->in.args[0].size = sizeof(inarg); + req->in.args[0].value = &inarg; + req->in.args[1].size = entry->d_name.len + 1; + req->in.args[1].value = entry->d_name.name; + req->out.numargs = 2; + req->out.args[0].size = sizeof(outentry); + req->out.args[0].value = &outentry; + req->out.args[1].size = sizeof(outopen); + req->out.args[1].value = &outopen; + request_send(fc, req); + err = req->out.h.error; + if (err) { + if (err == -ENOSYS) + fc->no_create = 1; + goto out_free_ff; + } + + err = -EIO; + if (!S_ISREG(outentry.attr.mode)) + goto out_free_ff; + + inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, + &outentry.attr); + err = -ENOMEM; + if (!inode) { + flags &= ~(O_CREAT | O_EXCL | O_TRUNC); + ff->fh = outopen.fh; + fuse_send_release(fc, ff, outentry.nodeid, NULL, flags, 0); + goto out_put_request; + } + fuse_put_request(fc, req); + entry->d_time = time_to_jiffies(outentry.entry_valid, + outentry.entry_valid_nsec); + fi = get_fuse_inode(inode); + fi->i_time = time_to_jiffies(outentry.attr_valid, + outentry.attr_valid_nsec); + + d_instantiate(entry, inode); + file = lookup_instantiate_filp(nd, entry, generic_file_open); + if (IS_ERR(file)) { + ff->fh = outopen.fh; + fuse_send_release(fc, ff, outentry.nodeid, inode, flags, 0); + return PTR_ERR(file); + } + fuse_finish_open(inode, file, ff, &outopen); + return 0; + + out_free_ff: + fuse_file_free(ff); + out_put_request: + fuse_put_request(fc, req); + out: + return err; +} + static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, struct inode *dir, struct dentry *entry, int mode) @@ -208,6 +304,12 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode, static int fuse_create(struct inode *dir, struct dentry *entry, int mode, struct nameidata *nd) { + if (nd && (nd->flags & LOOKUP_CREATE)) { + int err = fuse_create_open(dir, entry, mode, nd); + if (err != -ENOSYS) + return err; + /* Fall back on mknod */ + } return fuse_mknod(dir, entry, mode, 0); } @@ -767,7 +869,9 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd) { struct inode *inode; - int err = fuse_lookup_iget(dir, entry, &inode); + int err; + + err = fuse_lookup_iget(dir, entry, &inode); if (err) return ERR_PTR(err); if (inode && S_ISDIR(inode->i_mode)) { diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 657ab11c173..2ca86141d13 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -14,11 +14,69 @@ static struct file_operations fuse_direct_io_file_operations; -int fuse_open_common(struct inode *inode, struct file *file, int isdir) +static int fuse_send_open(struct inode *inode, struct file *file, int isdir, + struct fuse_open_out *outargp) { struct fuse_conn *fc = get_fuse_conn(inode); - struct fuse_req *req; struct fuse_open_in inarg; + struct fuse_req *req; + int err; + + req = fuse_get_request(fc); + if (!req) + return -EINTR; + + memset(&inarg, 0, sizeof(inarg)); + inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); + req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; + req->in.h.nodeid = get_node_id(inode); + req->inode = inode; + req->in.numargs = 1; + req->in.args[0].size = sizeof(inarg); + req->in.args[0].value = &inarg; + req->out.numargs = 1; + req->out.args[0].size = sizeof(*outargp); + req->out.args[0].value = outargp; + request_send(fc, req); + err = req->out.h.error; + fuse_put_request(fc, req); + + return err; +} + +struct fuse_file *fuse_file_alloc(void) +{ + struct fuse_file *ff; + ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL); + if (ff) { + ff->release_req = fuse_request_alloc(); + if (!ff->release_req) { + kfree(ff); + ff = NULL; + } + } + return ff; +} + +void fuse_file_free(struct fuse_file *ff) +{ + fuse_request_free(ff->release_req); + kfree(ff); +} + +void fuse_finish_open(struct inode *inode, struct file *file, + struct fuse_file *ff, struct fuse_open_out *outarg) +{ + if (outarg->open_flags & FOPEN_DIRECT_IO) + file->f_op = &fuse_direct_io_file_operations; + if (!(outarg->open_flags & FOPEN_KEEP_CACHE)) + invalidate_inode_pages(inode->i_mapping); + ff->fh = outarg->fh; + file->private_data = ff; +} + +int fuse_open_common(struct inode *inode, struct file *file, int isdir) +{ struct fuse_open_out outarg; struct fuse_file *ff; int err; @@ -34,73 +92,53 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir) /* If opening the root node, no lookup has been performed on it, so the attributes must be refreshed */ if (get_node_id(inode) == FUSE_ROOT_ID) { - int err = fuse_do_getattr(inode); + err = fuse_do_getattr(inode); if (err) return err; } - req = fuse_get_request(fc); - if (!req) - return -EINTR; - - err = -ENOMEM; - ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL); + ff = fuse_file_alloc(); if (!ff) - goto out_put_request; + return -ENOMEM; - ff->release_req = fuse_request_alloc(); - if (!ff->release_req) { - kfree(ff); - goto out_put_request; - } - - memset(&inarg, 0, sizeof(inarg)); - inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); - req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; - req->in.h.nodeid = get_node_id(inode); - req->inode = inode; - req->in.numargs = 1; - req->in.args[0].size = sizeof(inarg); - req->in.args[0].value = &inarg; - req->out.numargs = 1; - req->out.args[0].size = sizeof(outarg); - req->out.args[0].value = &outarg; - request_send(fc, req); - err = req->out.h.error; - if (err) { - fuse_request_free(ff->release_req); - kfree(ff); - } else { - if (!isdir && (outarg.open_flags & FOPEN_DIRECT_IO)) - file->f_op = &fuse_direct_io_file_operations; - if (!(outarg.open_flags & FOPEN_KEEP_CACHE)) - invalidate_inode_pages(inode->i_mapping); - ff->fh = outarg.fh; - file->private_data = ff; + err = fuse_send_open(inode, file, isdir, &outarg); + if (err) + fuse_file_free(ff); + else { + if (isdir) + outarg.open_flags &= ~FOPEN_DIRECT_IO; + fuse_finish_open(inode, file, ff, &outarg); } - out_put_request: - fuse_put_request(fc, req); return err; } -int fuse_release_common(struct inode *inode, struct file *file, int isdir) +void fuse_send_release(struct fuse_conn *fc, struct fuse_file *ff, + u64 nodeid, struct inode *inode, int flags, int isdir) { - struct fuse_conn *fc = get_fuse_conn(inode); - struct fuse_file *ff = file->private_data; - struct fuse_req *req = ff->release_req; + struct fuse_req * req = ff->release_req; struct fuse_release_in *inarg = &req->misc.release_in; inarg->fh = ff->fh; - inarg->flags = file->f_flags & ~O_EXCL; + inarg->flags = flags; req->in.h.opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE; - req->in.h.nodeid = get_node_id(inode); + req->in.h.nodeid = nodeid; req->inode = inode; req->in.numargs = 1; req->in.args[0].size = sizeof(struct fuse_release_in); req->in.args[0].value = inarg; request_send_background(fc, req); kfree(ff); +} + +int fuse_release_common(struct inode *inode, struct file *file, int isdir) +{ + struct fuse_file *ff = file->private_data; + if (ff) { + struct fuse_conn *fc = get_fuse_conn(inode); + u64 nodeid = get_node_id(inode); + fuse_send_release(fc, ff, nodeid, inode, file->f_flags, isdir); + } /* Return value is ignored by VFS */ return 0; diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index c4e8c3b4798..0ea5301f86b 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -269,6 +269,9 @@ struct fuse_conn { /** Is access not implemented by fs? */ unsigned no_access : 1; + /** Is create not implemented by fs? */ + unsigned no_create : 1; + /** Backing dev info */ struct backing_dev_info bdi; }; @@ -340,6 +343,17 @@ size_t fuse_send_read_common(struct fuse_req *req, struct file *file, */ int fuse_open_common(struct inode *inode, struct file *file, int isdir); +struct fuse_file *fuse_file_alloc(void); +void fuse_file_free(struct fuse_file *ff); +void fuse_finish_open(struct inode *inode, struct file *file, + struct fuse_file *ff, struct fuse_open_out *outarg); + +/** + * Send a RELEASE request + */ +void fuse_send_release(struct fuse_conn *fc, struct fuse_file *ff, + u64 nodeid, struct inode *inode, int flags, int isdir); + /** * Send RELEASE or RELEASEDIR request */ diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 507913b65af..45c398f0824 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -100,7 +100,8 @@ enum fuse_opcode { FUSE_READDIR = 28, FUSE_RELEASEDIR = 29, FUSE_FSYNCDIR = 30, - FUSE_ACCESS = 34 + FUSE_ACCESS = 34, + FUSE_CREATE = 35 }; /* Conservative buffer size for the client */ @@ -158,7 +159,7 @@ struct fuse_setattr_in { struct fuse_open_in { __u32 flags; - __u32 padding; + __u32 mode; }; struct fuse_open_out { -- cgit v1.2.3 From befc649c2274a1c35f0cd1e888dd83652cbb0422 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 7 Nov 2005 00:59:52 -0800 Subject: [PATCH] FUSE: pass file handle in setattr This patch passes the file handle supplied in iattr to userspace, in case the ->setattr() was invoked from sys_ftruncate(). This solves the permission checking (or lack thereof) in ftruncate() for the class of filesystems served by an unprivileged userspace process. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dir.c | 28 ++++++++++++++-------------- include/linux/fuse.h | 16 +++++++++++++++- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 83be119ef06..c045cc70c74 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -763,29 +763,29 @@ static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync) return file ? fuse_fsync_common(file, de, datasync, 1) : 0; } -static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr) +static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg) { unsigned ivalid = iattr->ia_valid; - unsigned fvalid = 0; - - memset(fattr, 0, sizeof(*fattr)); if (ivalid & ATTR_MODE) - fvalid |= FATTR_MODE, fattr->mode = iattr->ia_mode; + arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode; if (ivalid & ATTR_UID) - fvalid |= FATTR_UID, fattr->uid = iattr->ia_uid; + arg->valid |= FATTR_UID, arg->uid = iattr->ia_uid; if (ivalid & ATTR_GID) - fvalid |= FATTR_GID, fattr->gid = iattr->ia_gid; + arg->valid |= FATTR_GID, arg->gid = iattr->ia_gid; if (ivalid & ATTR_SIZE) - fvalid |= FATTR_SIZE, fattr->size = iattr->ia_size; + arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size; /* You can only _set_ these together (they may change by themselves) */ if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) { - fvalid |= FATTR_ATIME | FATTR_MTIME; - fattr->atime = iattr->ia_atime.tv_sec; - fattr->mtime = iattr->ia_mtime.tv_sec; + arg->valid |= FATTR_ATIME | FATTR_MTIME; + arg->atime = iattr->ia_atime.tv_sec; + arg->mtime = iattr->ia_mtime.tv_sec; + } + if (ivalid & ATTR_FILE) { + struct fuse_file *ff = iattr->ia_file->private_data; + arg->valid |= FATTR_FH; + arg->fh = ff->fh; } - - return fvalid; } static int fuse_setattr(struct dentry *entry, struct iattr *attr) @@ -820,7 +820,7 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr) return -EINTR; memset(&inarg, 0, sizeof(inarg)); - inarg.valid = iattr_to_fattr(attr, &inarg.attr); + iattr_to_fattr(attr, &inarg); req->in.h.opcode = FUSE_SETATTR; req->in.h.nodeid = get_node_id(inode); req->inode = inode; diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 45c398f0824..b76b558b03d 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -61,6 +61,7 @@ struct fuse_kstatfs { #define FATTR_SIZE (1 << 3) #define FATTR_ATIME (1 << 4) #define FATTR_MTIME (1 << 5) +#define FATTR_FH (1 << 6) /** * Flags returned by the OPEN request @@ -154,7 +155,20 @@ struct fuse_link_in { struct fuse_setattr_in { __u32 valid; __u32 padding; - struct fuse_attr attr; + __u64 fh; + __u64 size; + __u64 unused1; + __u64 atime; + __u64 mtime; + __u64 unused2; + __u32 atimensec; + __u32 mtimensec; + __u32 unused3; + __u32 mode; + __u32 unused4; + __u32 uid; + __u32 gid; + __u32 unused5; }; struct fuse_open_in { -- cgit v1.2.3 From f5b3db0017f8415301f3427b30263186e8478c3f Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Mon, 7 Nov 2005 00:59:53 -0800 Subject: [PATCH] as: cooperating processes Introduce the notion of cooperating processes (those that submit requests close to one another), and use these statistics to make better choices about whether or not to do anticipatory waiting. Help and analysis from Seetharami Seelam Performance testing from Seelam: I set up my system and executed a couple of tests that I used for OLS. I tested with AS, cooperative process patch merged in -mm tree (which I called Nick, below) and the cooperative patch with modifications to as_update_iohist (which I called Seelam). I used a dual-processor (2.28GHz Pentium 4 Xeon) system, with 1 GB main memory and 1 MB L2 cache, running Linux 2.6.9. Only a single processor is used for the experiments. I used 7.2K RPM Maxtor 10GB drive configured with ext2 file system. Experiment 1 (ex1) consists of reading one Linux source trees using find . -type f -exec cat '{}' ';' > /dev/null. Experiment 2 (ex2) consists of reading two disjoint Linux source trees using find . -type f -exec cat '{}' ';' > /dev/null. Experiment 3 (ex3) consists of streaming read of a 2GB file in the background and 1 instance of the chunk reads in Experiment 1. Timings for reading the Linux source are shown below: AS Nick Seelam ex1: 0m25.813s 0m27.859s 0m27.640s ex2: 1m11.468s 1m13.918s 1m5.869s ex3: 81m44.352s 10m38.572s 6m47.994s The difference between the numbers in Experiment 3 must be due to the code in as_update_iohist. (akpm: that's not part of this patch. So this patch is "Nick"). Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/as-iosched.c | 310 ++++++++++++++++++++++++--------------------- 1 file changed, 165 insertions(+), 145 deletions(-) diff --git a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c index c6744ff3829..a78e160b59a 100644 --- a/drivers/block/as-iosched.c +++ b/drivers/block/as-iosched.c @@ -4,7 +4,7 @@ * Anticipatory & deadline i/o scheduler. * * Copyright (C) 2002 Jens Axboe - * Nick Piggin + * Nick Piggin * */ #include @@ -69,7 +69,7 @@ /* Bits in as_io_context.state */ enum as_io_states { - AS_TASK_RUNNING=0, /* Process has not exitted */ + AS_TASK_RUNNING=0, /* Process has not exited */ AS_TASK_IOSTARTED, /* Process has started some IO */ AS_TASK_IORUNNING, /* Process has completed some IO */ }; @@ -102,6 +102,9 @@ struct as_data { unsigned long exit_prob; /* probability a task will exit while being waited on */ + unsigned long exit_no_coop; /* probablility an exited task will + not be part of a later cooperating + request */ unsigned long new_ttime_total; /* mean thinktime on new proc */ unsigned long new_ttime_mean; u64 new_seek_total; /* mean seek on new proc */ @@ -636,37 +639,152 @@ static void as_antic_timeout(unsigned long data) kblockd_schedule_work(&ad->antic_work); if (aic->ttime_samples == 0) { - /* process anticipated on has exitted or timed out*/ + /* process anticipated on has exited or timed out*/ ad->exit_prob = (7*ad->exit_prob + 256)/8; } + if (!test_bit(AS_TASK_RUNNING, &aic->state)) { + /* process not "saved" by a cooperating request */ + ad->exit_no_coop = (7*ad->exit_no_coop + 256)/8; + } } spin_unlock_irqrestore(q->queue_lock, flags); } +static void as_update_thinktime(struct as_data *ad, struct as_io_context *aic, + unsigned long ttime) +{ + /* fixed point: 1.0 == 1<<8 */ + if (aic->ttime_samples == 0) { + ad->new_ttime_total = (7*ad->new_ttime_total + 256*ttime) / 8; + ad->new_ttime_mean = ad->new_ttime_total / 256; + + ad->exit_prob = (7*ad->exit_prob)/8; + } + aic->ttime_samples = (7*aic->ttime_samples + 256) / 8; + aic->ttime_total = (7*aic->ttime_total + 256*ttime) / 8; + aic->ttime_mean = (aic->ttime_total + 128) / aic->ttime_samples; +} + +static void as_update_seekdist(struct as_data *ad, struct as_io_context *aic, + sector_t sdist) +{ + u64 total; + + if (aic->seek_samples == 0) { + ad->new_seek_total = (7*ad->new_seek_total + 256*(u64)sdist)/8; + ad->new_seek_mean = ad->new_seek_total / 256; + } + + /* + * Don't allow the seek distance to get too large from the + * odd fragment, pagein, etc + */ + if (aic->seek_samples <= 60) /* second&third seek */ + sdist = min(sdist, (aic->seek_mean * 4) + 2*1024*1024); + else + sdist = min(sdist, (aic->seek_mean * 4) + 2*1024*64); + + aic->seek_samples = (7*aic->seek_samples + 256) / 8; + aic->seek_total = (7*aic->seek_total + (u64)256*sdist) / 8; + total = aic->seek_total + (aic->seek_samples/2); + do_div(total, aic->seek_samples); + aic->seek_mean = (sector_t)total; +} + +/* + * as_update_iohist keeps a decaying histogram of IO thinktimes, and + * updates @aic->ttime_mean based on that. It is called when a new + * request is queued. + */ +static void as_update_iohist(struct as_data *ad, struct as_io_context *aic, + struct request *rq) +{ + struct as_rq *arq = RQ_DATA(rq); + int data_dir = arq->is_sync; + unsigned long thinktime = 0; + sector_t seek_dist; + + if (aic == NULL) + return; + + if (data_dir == REQ_SYNC) { + unsigned long in_flight = atomic_read(&aic->nr_queued) + + atomic_read(&aic->nr_dispatched); + spin_lock(&aic->lock); + if (test_bit(AS_TASK_IORUNNING, &aic->state) || + test_bit(AS_TASK_IOSTARTED, &aic->state)) { + /* Calculate read -> read thinktime */ + if (test_bit(AS_TASK_IORUNNING, &aic->state) + && in_flight == 0) { + thinktime = jiffies - aic->last_end_request; + thinktime = min(thinktime, MAX_THINKTIME-1); + } + as_update_thinktime(ad, aic, thinktime); + + /* Calculate read -> read seek distance */ + if (aic->last_request_pos < rq->sector) + seek_dist = rq->sector - aic->last_request_pos; + else + seek_dist = aic->last_request_pos - rq->sector; + as_update_seekdist(ad, aic, seek_dist); + } + aic->last_request_pos = rq->sector + rq->nr_sectors; + set_bit(AS_TASK_IOSTARTED, &aic->state); + spin_unlock(&aic->lock); + } +} + /* * as_close_req decides if one request is considered "close" to the * previous one issued. */ -static int as_close_req(struct as_data *ad, struct as_rq *arq) +static int as_close_req(struct as_data *ad, struct as_io_context *aic, + struct as_rq *arq) { unsigned long delay; /* milliseconds */ sector_t last = ad->last_sector[ad->batch_data_dir]; sector_t next = arq->request->sector; sector_t delta; /* acceptable close offset (in sectors) */ + sector_t s; if (ad->antic_status == ANTIC_OFF || !ad->ioc_finished) delay = 0; else delay = ((jiffies - ad->antic_start) * 1000) / HZ; - if (delay <= 1) - delta = 64; + if (delay == 0) + delta = 8192; else if (delay <= 20 && delay <= ad->antic_expire) - delta = 64 << (delay-1); + delta = 8192 << delay; else return 1; - return (last - (delta>>1) <= next) && (next <= last + delta); + if ((last <= next + (delta>>1)) && (next <= last + delta)) + return 1; + + if (last < next) + s = next - last; + else + s = last - next; + + if (aic->seek_samples == 0) { + /* + * Process has just started IO. Use past statistics to + * gauge success possibility + */ + if (ad->new_seek_mean > s) { + /* this request is better than what we're expecting */ + return 1; + } + + } else { + if (aic->seek_mean > s) { + /* this request is better than what we're expecting */ + return 1; + } + } + + return 0; } /* @@ -678,7 +796,7 @@ static int as_close_req(struct as_data *ad, struct as_rq *arq) * dispatch it ASAP, because we know that application will not be submitting * any new reads. * - * If the task which has submitted the request has exitted, break anticipation. + * If the task which has submitted the request has exited, break anticipation. * * If this task has queued some other IO, do not enter enticipation. */ @@ -686,7 +804,6 @@ static int as_can_break_anticipation(struct as_data *ad, struct as_rq *arq) { struct io_context *ioc; struct as_io_context *aic; - sector_t s; ioc = ad->io_context; BUG_ON(!ioc); @@ -708,13 +825,6 @@ static int as_can_break_anticipation(struct as_data *ad, struct as_rq *arq) if (!aic) return 0; - if (!test_bit(AS_TASK_RUNNING, &aic->state)) { - /* process anticipated on has exitted */ - if (aic->ttime_samples == 0) - ad->exit_prob = (7*ad->exit_prob + 256)/8; - return 1; - } - if (atomic_read(&aic->nr_queued) > 0) { /* process has more requests queued */ return 1; @@ -725,57 +835,45 @@ static int as_can_break_anticipation(struct as_data *ad, struct as_rq *arq) return 1; } - if (arq && arq->is_sync == REQ_SYNC && as_close_req(ad, arq)) { + if (arq && arq->is_sync == REQ_SYNC && as_close_req(ad, aic, arq)) { /* * Found a close request that is not one of ours. * - * This makes close requests from another process reset - * our thinktime delay. Is generally useful when there are + * This makes close requests from another process update + * our IO history. Is generally useful when there are * two or more cooperating processes working in the same * area. */ - spin_lock(&aic->lock); - aic->last_end_request = jiffies; - spin_unlock(&aic->lock); + if (!test_bit(AS_TASK_RUNNING, &aic->state)) { + if (aic->ttime_samples == 0) + ad->exit_prob = (7*ad->exit_prob + 256)/8; + + ad->exit_no_coop = (7*ad->exit_no_coop)/8; + } + + as_update_iohist(ad, aic, arq->request); return 1; } + if (!test_bit(AS_TASK_RUNNING, &aic->state)) { + /* process anticipated on has exited */ + if (aic->ttime_samples == 0) + ad->exit_prob = (7*ad->exit_prob + 256)/8; + + if (ad->exit_no_coop > 128) + return 1; + } if (aic->ttime_samples == 0) { if (ad->new_ttime_mean > ad->antic_expire) return 1; - if (ad->exit_prob > 128) + if (ad->exit_prob * ad->exit_no_coop > 128*256) return 1; } else if (aic->ttime_mean > ad->antic_expire) { /* the process thinks too much between requests */ return 1; } - if (!arq) - return 0; - - if (ad->last_sector[REQ_SYNC] < arq->request->sector) - s = arq->request->sector - ad->last_sector[REQ_SYNC]; - else - s = ad->last_sector[REQ_SYNC] - arq->request->sector; - - if (aic->seek_samples == 0) { - /* - * Process has just started IO. Use past statistics to - * guage success possibility - */ - if (ad->new_seek_mean > s) { - /* this request is better than what we're expecting */ - return 1; - } - - } else { - if (aic->seek_mean > s) { - /* this request is better than what we're expecting */ - return 1; - } - } - return 0; } @@ -809,94 +907,11 @@ static int as_can_anticipate(struct as_data *ad, struct as_rq *arq) * Status is either ANTIC_OFF so start waiting, * ANTIC_WAIT_REQ so continue waiting for request to finish * or ANTIC_WAIT_NEXT so continue waiting for an acceptable request. - * */ return 1; } -static void as_update_thinktime(struct as_data *ad, struct as_io_context *aic, unsigned long ttime) -{ - /* fixed point: 1.0 == 1<<8 */ - if (aic->ttime_samples == 0) { - ad->new_ttime_total = (7*ad->new_ttime_total + 256*ttime) / 8; - ad->new_ttime_mean = ad->new_ttime_total / 256; - - ad->exit_prob = (7*ad->exit_prob)/8; - } - aic->ttime_samples = (7*aic->ttime_samples + 256) / 8; - aic->ttime_total = (7*aic->ttime_total + 256*ttime) / 8; - aic->ttime_mean = (aic->ttime_total + 128) / aic->ttime_samples; -} - -static void as_update_seekdist(struct as_data *ad, struct as_io_context *aic, sector_t sdist) -{ - u64 total; - - if (aic->seek_samples == 0) { - ad->new_seek_total = (7*ad->new_seek_total + 256*(u64)sdist)/8; - ad->new_seek_mean = ad->new_seek_total / 256; - } - - /* - * Don't allow the seek distance to get too large from the - * odd fragment, pagein, etc - */ - if (aic->seek_samples <= 60) /* second&third seek */ - sdist = min(sdist, (aic->seek_mean * 4) + 2*1024*1024); - else - sdist = min(sdist, (aic->seek_mean * 4) + 2*1024*64); - - aic->seek_samples = (7*aic->seek_samples + 256) / 8; - aic->seek_total = (7*aic->seek_total + (u64)256*sdist) / 8; - total = aic->seek_total + (aic->seek_samples/2); - do_div(total, aic->seek_samples); - aic->seek_mean = (sector_t)total; -} - -/* - * as_update_iohist keeps a decaying histogram of IO thinktimes, and - * updates @aic->ttime_mean based on that. It is called when a new - * request is queued. - */ -static void as_update_iohist(struct as_data *ad, struct as_io_context *aic, struct request *rq) -{ - struct as_rq *arq = RQ_DATA(rq); - int data_dir = arq->is_sync; - unsigned long thinktime; - sector_t seek_dist; - - if (aic == NULL) - return; - - if (data_dir == REQ_SYNC) { - unsigned long in_flight = atomic_read(&aic->nr_queued) - + atomic_read(&aic->nr_dispatched); - spin_lock(&aic->lock); - if (test_bit(AS_TASK_IORUNNING, &aic->state) || - test_bit(AS_TASK_IOSTARTED, &aic->state)) { - /* Calculate read -> read thinktime */ - if (test_bit(AS_TASK_IORUNNING, &aic->state) - && in_flight == 0) { - thinktime = jiffies - aic->last_end_request; - thinktime = min(thinktime, MAX_THINKTIME-1); - } else - thinktime = 0; - as_update_thinktime(ad, aic, thinktime); - - /* Calculate read -> read seek distance */ - if (aic->last_request_pos < rq->sector) - seek_dist = rq->sector - aic->last_request_pos; - else - seek_dist = aic->last_request_pos - rq->sector; - as_update_seekdist(ad, aic, seek_dist); - } - aic->last_request_pos = rq->sector + rq->nr_sectors; - set_bit(AS_TASK_IOSTARTED, &aic->state); - spin_unlock(&aic->lock); - } -} - /* * as_update_arq must be called whenever a request (arq) is added to * the sort_list. This function keeps caches up to date, and checks if the @@ -1201,7 +1216,7 @@ static int as_dispatch_request(request_queue_t *q, int force) || ad->changed_batch) return 0; - if (!(reads && writes && as_batch_expired(ad)) ) { + if (!(reads && writes && as_batch_expired(ad))) { /* * batch is still running or no reads or no writes */ @@ -1316,7 +1331,8 @@ fifo_expired: * Add arq to a list behind alias */ static inline void -as_add_aliased_request(struct as_data *ad, struct as_rq *arq, struct as_rq *alias) +as_add_aliased_request(struct as_data *ad, struct as_rq *arq, + struct as_rq *alias) { struct request *req = arq->request; struct list_head *insert = alias->request->queuelist.prev; @@ -1441,8 +1457,8 @@ static int as_queue_empty(request_queue_t *q) && list_empty(&ad->fifo_list[REQ_SYNC]); } -static struct request * -as_former_request(request_queue_t *q, struct request *rq) +static struct request *as_former_request(request_queue_t *q, + struct request *rq) { struct as_rq *arq = RQ_DATA(rq); struct rb_node *rbprev = rb_prev(&arq->rb_node); @@ -1454,8 +1470,8 @@ as_former_request(request_queue_t *q, struct request *rq) return ret; } -static struct request * -as_latter_request(request_queue_t *q, struct request *rq) +static struct request *as_latter_request(request_queue_t *q, + struct request *rq) { struct as_rq *arq = RQ_DATA(rq); struct rb_node *rbnext = rb_next(&arq->rb_node); @@ -1537,7 +1553,7 @@ static void as_merged_request(request_queue_t *q, struct request *req) * currently don't bother. Ditto the next function. */ as_del_arq_rb(ad, arq); - if ((alias = as_add_arq_rb(ad, arq)) ) { + if ((alias = as_add_arq_rb(ad, arq))) { list_del_init(&arq->fifo); as_add_aliased_request(ad, arq, alias); if (next_arq) @@ -1551,9 +1567,8 @@ static void as_merged_request(request_queue_t *q, struct request *req) } } -static void -as_merged_requests(request_queue_t *q, struct request *req, - struct request *next) +static void as_merged_requests(request_queue_t *q, struct request *req, + struct request *next) { struct as_data *ad = q->elevator->elevator_data; struct as_rq *arq = RQ_DATA(req); @@ -1576,7 +1591,7 @@ as_merged_requests(request_queue_t *q, struct request *req, next_arq = as_find_next_arq(ad, arq); as_del_arq_rb(ad, arq); - if ((alias = as_add_arq_rb(ad, arq)) ) { + if ((alias = as_add_arq_rb(ad, arq))) { list_del_init(&arq->fifo); as_add_aliased_request(ad, arq, alias); if (next_arq) @@ -1806,9 +1821,14 @@ static ssize_t as_est_show(struct as_data *ad, char *page) { int pos = 0; - pos += sprintf(page+pos, "%lu %% exit probability\n", 100*ad->exit_prob/256); + pos += sprintf(page+pos, "%lu %% exit probability\n", + 100*ad->exit_prob/256); + pos += sprintf(page+pos, "%lu %% probability of exiting without a " + "cooperating process submitting IO\n", + 100*ad->exit_no_coop/256); pos += sprintf(page+pos, "%lu ms new thinktime\n", ad->new_ttime_mean); - pos += sprintf(page+pos, "%llu sectors new seek distance\n", (unsigned long long)ad->new_seek_mean); + pos += sprintf(page+pos, "%llu sectors new seek distance\n", + (unsigned long long)ad->new_seek_mean); return pos; } -- cgit v1.2.3 From 393d2cc354d150b8b4bb888a9da7db4c935e12bd Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 7 Nov 2005 00:59:54 -0800 Subject: [PATCH] ipmi: use refcount in message handler This patch is rather large, but it really can't be done in smaller chunks easily and I believe it is an important change. This has been out and tested for a while in the latest IPMI driver release. There are no functional changes, just changes as necessary to convert the locking over (and a few minor style updates). The IPMI driver uses read/write locks to ensure that things exist while they are in use. This is bad from a number of points of view. This patch removes the rwlocks and uses refcounts and RCU lists to manage what the locks did. Signed-off-by: Corey Minyard Cc: Matt Domsch Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_msghandler.c | 953 +++++++++++++++++++----------------- include/linux/ipmi.h | 5 +- 2 files changed, 499 insertions(+), 459 deletions(-) diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 32fa82c78c7..320d7f035bf 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -38,13 +38,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #define PFX "IPMI message handler: " @@ -65,10 +65,19 @@ struct proc_dir_entry *proc_ipmi_root = NULL; the max message timer. This is in milliseconds. */ #define MAX_MSG_TIMEOUT 60000 + +/* + * The main "user" data structure. + */ struct ipmi_user { struct list_head link; + /* Set to "0" when the user is destroyed. */ + int valid; + + struct kref refcount; + /* The upper layer that handles receive messages. */ struct ipmi_user_hndl *handler; void *handler_data; @@ -87,6 +96,15 @@ struct cmd_rcvr ipmi_user_t user; unsigned char netfn; unsigned char cmd; + + /* + * This is used to form a linked lised during mass deletion. + * Since this is in an RCU list, we cannot use the link above + * or change any data until the RCU period completes. So we + * use this next variable during mass deletion so we can have + * a list and don't have to wait and restart the search on + * every individual deletion of a command. */ + struct cmd_rcvr *next; }; struct seq_table @@ -150,13 +168,11 @@ struct ipmi_smi /* What interface number are we? */ int intf_num; - /* The list of upper layers that are using me. We read-lock - this when delivering messages to the upper layer to keep - the user from going away while we are processing the - message. This means that you cannot add or delete a user - from the receive callback. */ - rwlock_t users_lock; - struct list_head users; + struct kref refcount; + + /* The list of upper layers that are using me. seq_lock + * protects this. */ + struct list_head users; /* Used for wake ups at startup. */ wait_queue_head_t waitq; @@ -193,7 +209,7 @@ struct ipmi_smi /* The list of command receivers that are registered for commands on this interface. */ - rwlock_t cmd_rcvr_lock; + spinlock_t cmd_rcvrs_lock; struct list_head cmd_rcvrs; /* Events that were queues because no one was there to receive @@ -296,16 +312,17 @@ struct ipmi_smi unsigned int events; }; +/* Used to mark an interface entry that cannot be used but is not a + * free entry, either, primarily used at creation and deletion time so + * a slot doesn't get reused too quickly. */ +#define IPMI_INVALID_INTERFACE_ENTRY ((ipmi_smi_t) ((long) 1)) +#define IPMI_INVALID_INTERFACE(i) (((i) == NULL) \ + || (i == IPMI_INVALID_INTERFACE_ENTRY)) + #define MAX_IPMI_INTERFACES 4 static ipmi_smi_t ipmi_interfaces[MAX_IPMI_INTERFACES]; -/* Used to keep interfaces from going away while operations are - operating on interfaces. Grab read if you are not modifying the - interfaces, write if you are. */ -static DECLARE_RWSEM(interfaces_sem); - -/* Directly protects the ipmi_interfaces data structure. This is - claimed in the timer interrupt. */ +/* Directly protects the ipmi_interfaces data structure. */ static DEFINE_SPINLOCK(interfaces_lock); /* List of watchers that want to know when smi's are added and @@ -313,20 +330,73 @@ static DEFINE_SPINLOCK(interfaces_lock); static struct list_head smi_watchers = LIST_HEAD_INIT(smi_watchers); static DECLARE_RWSEM(smi_watchers_sem); + +static void free_recv_msg_list(struct list_head *q) +{ + struct ipmi_recv_msg *msg, *msg2; + + list_for_each_entry_safe(msg, msg2, q, link) { + list_del(&msg->link); + ipmi_free_recv_msg(msg); + } +} + +static void clean_up_interface_data(ipmi_smi_t intf) +{ + int i; + struct cmd_rcvr *rcvr, *rcvr2; + unsigned long flags; + struct list_head list; + + free_recv_msg_list(&intf->waiting_msgs); + free_recv_msg_list(&intf->waiting_events); + + /* Wholesale remove all the entries from the list in the + * interface and wait for RCU to know that none are in use. */ + spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); + list_add_rcu(&list, &intf->cmd_rcvrs); + list_del_rcu(&intf->cmd_rcvrs); + spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); + synchronize_rcu(); + + list_for_each_entry_safe(rcvr, rcvr2, &list, link) + kfree(rcvr); + + for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { + if ((intf->seq_table[i].inuse) + && (intf->seq_table[i].recv_msg)) + { + ipmi_free_recv_msg(intf->seq_table[i].recv_msg); + } + } +} + +static void intf_free(struct kref *ref) +{ + ipmi_smi_t intf = container_of(ref, struct ipmi_smi, refcount); + + clean_up_interface_data(intf); + kfree(intf); +} + int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher) { - int i; + int i; + unsigned long flags; - down_read(&interfaces_sem); down_write(&smi_watchers_sem); list_add(&(watcher->link), &smi_watchers); + up_write(&smi_watchers_sem); + spin_lock_irqsave(&interfaces_lock, flags); for (i = 0; i < MAX_IPMI_INTERFACES; i++) { - if (ipmi_interfaces[i] != NULL) { - watcher->new_smi(i); - } + ipmi_smi_t intf = ipmi_interfaces[i]; + if (IPMI_INVALID_INTERFACE(intf)) + continue; + spin_unlock_irqrestore(&interfaces_lock, flags); + watcher->new_smi(i); + spin_lock_irqsave(&interfaces_lock, flags); } - up_write(&smi_watchers_sem); - up_read(&interfaces_sem); + spin_unlock_irqrestore(&interfaces_lock, flags); return 0; } @@ -471,8 +541,8 @@ static void deliver_response(struct ipmi_recv_msg *msg) } ipmi_free_recv_msg(msg); } else { - msg->user->handler->ipmi_recv_hndl(msg, - msg->user->handler_data); + ipmi_user_t user = msg->user; + user->handler->ipmi_recv_hndl(msg, user->handler_data); } } @@ -662,15 +732,18 @@ int ipmi_create_user(unsigned int if_num, if (! new_user) return -ENOMEM; - down_read(&interfaces_sem); - if ((if_num >= MAX_IPMI_INTERFACES) || ipmi_interfaces[if_num] == NULL) - { - rv = -EINVAL; - goto out_unlock; + spin_lock_irqsave(&interfaces_lock, flags); + intf = ipmi_interfaces[if_num]; + if ((if_num >= MAX_IPMI_INTERFACES) || IPMI_INVALID_INTERFACE(intf)) { + spin_unlock_irqrestore(&interfaces_lock, flags); + return -EINVAL; } - intf = ipmi_interfaces[if_num]; + /* Note that each existing user holds a refcount to the interface. */ + kref_get(&intf->refcount); + spin_unlock_irqrestore(&interfaces_lock, flags); + kref_init(&new_user->refcount); new_user->handler = handler; new_user->handler_data = handler_data; new_user->intf = intf; @@ -678,98 +751,92 @@ int ipmi_create_user(unsigned int if_num, if (!try_module_get(intf->handlers->owner)) { rv = -ENODEV; - goto out_unlock; + goto out_err; } if (intf->handlers->inc_usecount) { rv = intf->handlers->inc_usecount(intf->send_info); if (rv) { module_put(intf->handlers->owner); - goto out_unlock; + goto out_err; } } - write_lock_irqsave(&intf->users_lock, flags); - list_add_tail(&new_user->link, &intf->users); - write_unlock_irqrestore(&intf->users_lock, flags); - - out_unlock: - if (rv) { - kfree(new_user); - } else { - *user = new_user; - } + new_user->valid = 1; + spin_lock_irqsave(&intf->seq_lock, flags); + list_add_rcu(&new_user->link, &intf->users); + spin_unlock_irqrestore(&intf->seq_lock, flags); + *user = new_user; + return 0; - up_read(&interfaces_sem); + out_err: + kfree(new_user); + kref_put(&intf->refcount, intf_free); return rv; } -static int ipmi_destroy_user_nolock(ipmi_user_t user) +static void free_user(struct kref *ref) +{ + ipmi_user_t user = container_of(ref, struct ipmi_user, refcount); + kfree(user); +} + +int ipmi_destroy_user(ipmi_user_t user) { int rv = -ENODEV; - ipmi_user_t t_user; - struct cmd_rcvr *rcvr, *rcvr2; + ipmi_smi_t intf = user->intf; int i; unsigned long flags; + struct cmd_rcvr *rcvr; + struct list_head *entry1, *entry2; + struct cmd_rcvr *rcvrs = NULL; - /* Find the user and delete them from the list. */ - list_for_each_entry(t_user, &(user->intf->users), link) { - if (t_user == user) { - list_del(&t_user->link); - rv = 0; - break; - } - } + user->valid = 1; - if (rv) { - goto out_unlock; - } + /* Remove the user from the interface's sequence table. */ + spin_lock_irqsave(&intf->seq_lock, flags); + list_del_rcu(&user->link); - /* Remove the user from the interfaces sequence table. */ - spin_lock_irqsave(&(user->intf->seq_lock), flags); for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { - if (user->intf->seq_table[i].inuse - && (user->intf->seq_table[i].recv_msg->user == user)) + if (intf->seq_table[i].inuse + && (intf->seq_table[i].recv_msg->user == user)) { - user->intf->seq_table[i].inuse = 0; + intf->seq_table[i].inuse = 0; } } - spin_unlock_irqrestore(&(user->intf->seq_lock), flags); - - /* Remove the user from the command receiver's table. */ - write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags); - list_for_each_entry_safe(rcvr, rcvr2, &(user->intf->cmd_rcvrs), link) { + spin_unlock_irqrestore(&intf->seq_lock, flags); + + /* + * Remove the user from the command receiver's table. First + * we build a list of everything (not using the standard link, + * since other things may be using it till we do + * synchronize_rcu()) then free everything in that list. + */ + spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); + list_for_each_safe_rcu(entry1, entry2, &intf->cmd_rcvrs) { + rcvr = list_entry(entry1, struct cmd_rcvr, link); if (rcvr->user == user) { - list_del(&rcvr->link); - kfree(rcvr); + list_del_rcu(&rcvr->link); + rcvr->next = rcvrs; + rcvrs = rcvr; } } - write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags); + spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); + synchronize_rcu(); + while (rcvrs) { + rcvr = rcvrs; + rcvrs = rcvr->next; + kfree(rcvr); + } - kfree(user); + module_put(intf->handlers->owner); + if (intf->handlers->dec_usecount) + intf->handlers->dec_usecount(intf->send_info); - out_unlock: + kref_put(&intf->refcount, intf_free); - return rv; -} - -int ipmi_destroy_user(ipmi_user_t user) -{ - int rv; - ipmi_smi_t intf = user->intf; - unsigned long flags; + kref_put(&user->refcount, free_user); - down_read(&interfaces_sem); - write_lock_irqsave(&intf->users_lock, flags); - rv = ipmi_destroy_user_nolock(user); - if (!rv) { - module_put(intf->handlers->owner); - if (intf->handlers->dec_usecount) - intf->handlers->dec_usecount(intf->send_info); - } - - write_unlock_irqrestore(&intf->users_lock, flags); - up_read(&interfaces_sem); return rv; } @@ -823,62 +890,78 @@ int ipmi_get_my_LUN(ipmi_user_t user, int ipmi_set_gets_events(ipmi_user_t user, int val) { - unsigned long flags; - struct ipmi_recv_msg *msg, *msg2; + unsigned long flags; + ipmi_smi_t intf = user->intf; + struct ipmi_recv_msg *msg, *msg2; + struct list_head msgs; - read_lock(&(user->intf->users_lock)); - spin_lock_irqsave(&(user->intf->events_lock), flags); + INIT_LIST_HEAD(&msgs); + + spin_lock_irqsave(&intf->events_lock, flags); user->gets_events = val; if (val) { /* Deliver any queued events. */ - list_for_each_entry_safe(msg, msg2, &(user->intf->waiting_events), link) { + list_for_each_entry_safe(msg, msg2, &intf->waiting_events, link) { list_del(&msg->link); - msg->user = user; - deliver_response(msg); + list_add_tail(&msg->link, &msgs); } } - - spin_unlock_irqrestore(&(user->intf->events_lock), flags); - read_unlock(&(user->intf->users_lock)); + + /* Hold the events lock while doing this to preserve order. */ + list_for_each_entry_safe(msg, msg2, &msgs, link) { + msg->user = user; + kref_get(&user->refcount); + deliver_response(msg); + } + + spin_unlock_irqrestore(&intf->events_lock, flags); return 0; } +static struct cmd_rcvr *find_cmd_rcvr(ipmi_smi_t intf, + unsigned char netfn, + unsigned char cmd) +{ + struct cmd_rcvr *rcvr; + + list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) { + if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) + return rcvr; + } + return NULL; +} + int ipmi_register_for_cmd(ipmi_user_t user, unsigned char netfn, unsigned char cmd) { - struct cmd_rcvr *cmp; - unsigned long flags; - struct cmd_rcvr *rcvr; - int rv = 0; + ipmi_smi_t intf = user->intf; + struct cmd_rcvr *rcvr; + struct cmd_rcvr *entry; + int rv = 0; rcvr = kmalloc(sizeof(*rcvr), GFP_KERNEL); if (! rcvr) return -ENOMEM; + rcvr->cmd = cmd; + rcvr->netfn = netfn; + rcvr->user = user; - read_lock(&(user->intf->users_lock)); - write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags); + spin_lock_irq(&intf->cmd_rcvrs_lock); /* Make sure the command/netfn is not already registered. */ - list_for_each_entry(cmp, &(user->intf->cmd_rcvrs), link) { - if ((cmp->netfn == netfn) && (cmp->cmd == cmd)) { - rv = -EBUSY; - break; - } - } - - if (! rv) { - rcvr->cmd = cmd; - rcvr->netfn = netfn; - rcvr->user = user; - list_add_tail(&(rcvr->link), &(user->intf->cmd_rcvrs)); + entry = find_cmd_rcvr(intf, netfn, cmd); + if (entry) { + rv = -EBUSY; + goto out_unlock; } - write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags); - read_unlock(&(user->intf->users_lock)); + list_add_rcu(&rcvr->link, &intf->cmd_rcvrs); + out_unlock: + spin_unlock_irq(&intf->cmd_rcvrs_lock); if (rv) kfree(rcvr); @@ -889,31 +972,28 @@ int ipmi_unregister_for_cmd(ipmi_user_t user, unsigned char netfn, unsigned char cmd) { - unsigned long flags; - struct cmd_rcvr *rcvr; - int rv = -ENOENT; + ipmi_smi_t intf = user->intf; + struct cmd_rcvr *rcvr; - read_lock(&(user->intf->users_lock)); - write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags); + spin_lock_irq(&intf->cmd_rcvrs_lock); /* Make sure the command/netfn is not already registered. */ - list_for_each_entry(rcvr, &(user->intf->cmd_rcvrs), link) { - if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { - rv = 0; - list_del(&rcvr->link); - kfree(rcvr); - break; - } + rcvr = find_cmd_rcvr(intf, netfn, cmd); + if ((rcvr) && (rcvr->user == user)) { + list_del_rcu(&rcvr->link); + spin_unlock_irq(&intf->cmd_rcvrs_lock); + synchronize_rcu(); + kfree(rcvr); + return 0; + } else { + spin_unlock_irq(&intf->cmd_rcvrs_lock); + return -ENOENT; } - write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags); - read_unlock(&(user->intf->users_lock)); - - return rv; } void ipmi_user_set_run_to_completion(ipmi_user_t user, int val) { - user->intf->handlers->set_run_to_completion(user->intf->send_info, - val); + ipmi_smi_t intf = user->intf; + intf->handlers->set_run_to_completion(intf->send_info, val); } static unsigned char @@ -1010,19 +1090,19 @@ static inline void format_lan_msg(struct ipmi_smi_msg *smi_msg, supplied in certain circumstances (mainly at panic time). If messages are supplied, they will be freed, even if an error occurs. */ -static inline int i_ipmi_request(ipmi_user_t user, - ipmi_smi_t intf, - struct ipmi_addr *addr, - long msgid, - struct kernel_ipmi_msg *msg, - void *user_msg_data, - void *supplied_smi, - struct ipmi_recv_msg *supplied_recv, - int priority, - unsigned char source_address, - unsigned char source_lun, - int retries, - unsigned int retry_time_ms) +static int i_ipmi_request(ipmi_user_t user, + ipmi_smi_t intf, + struct ipmi_addr *addr, + long msgid, + struct kernel_ipmi_msg *msg, + void *user_msg_data, + void *supplied_smi, + struct ipmi_recv_msg *supplied_recv, + int priority, + unsigned char source_address, + unsigned char source_lun, + int retries, + unsigned int retry_time_ms) { int rv = 0; struct ipmi_smi_msg *smi_msg; @@ -1051,6 +1131,8 @@ static inline int i_ipmi_request(ipmi_user_t user, } recv_msg->user = user; + if (user) + kref_get(&user->refcount); recv_msg->msgid = msgid; /* Store the message to send in the receive message so timeout responses can get the proper response data. */ @@ -1725,11 +1807,11 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, unsigned char version_major, unsigned char version_minor, unsigned char slave_addr, - ipmi_smi_t *intf) + ipmi_smi_t *new_intf) { int i, j; int rv; - ipmi_smi_t new_intf; + ipmi_smi_t intf; unsigned long flags; @@ -1745,189 +1827,142 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, return -ENODEV; } - new_intf = kmalloc(sizeof(*new_intf), GFP_KERNEL); - if (!new_intf) + intf = kmalloc(sizeof(*intf), GFP_KERNEL); + if (!intf) return -ENOMEM; - memset(new_intf, 0, sizeof(*new_intf)); - - new_intf->proc_dir = NULL; + memset(intf, 0, sizeof(*intf)); + intf->intf_num = -1; + kref_init(&intf->refcount); + intf->version_major = version_major; + intf->version_minor = version_minor; + for (j = 0; j < IPMI_MAX_CHANNELS; j++) { + intf->channels[j].address = IPMI_BMC_SLAVE_ADDR; + intf->channels[j].lun = 2; + } + if (slave_addr != 0) + intf->channels[0].address = slave_addr; + INIT_LIST_HEAD(&intf->users); + intf->handlers = handlers; + intf->send_info = send_info; + spin_lock_init(&intf->seq_lock); + for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) { + intf->seq_table[j].inuse = 0; + intf->seq_table[j].seqid = 0; + } + intf->curr_seq = 0; +#ifdef CONFIG_PROC_FS + spin_lock_init(&intf->proc_entry_lock); +#endif + spin_lock_init(&intf->waiting_msgs_lock); + INIT_LIST_HEAD(&intf->waiting_msgs); + spin_lock_init(&intf->events_lock); + INIT_LIST_HEAD(&intf->waiting_events); + intf->waiting_events_count = 0; + spin_lock_init(&intf->cmd_rcvrs_lock); + INIT_LIST_HEAD(&intf->cmd_rcvrs); + init_waitqueue_head(&intf->waitq); + + spin_lock_init(&intf->counter_lock); + intf->proc_dir = NULL; rv = -ENOMEM; - - down_write(&interfaces_sem); + spin_lock_irqsave(&interfaces_lock, flags); for (i = 0; i < MAX_IPMI_INTERFACES; i++) { if (ipmi_interfaces[i] == NULL) { - new_intf->intf_num = i; - new_intf->version_major = version_major; - new_intf->version_minor = version_minor; - for (j = 0; j < IPMI_MAX_CHANNELS; j++) { - new_intf->channels[j].address - = IPMI_BMC_SLAVE_ADDR; - new_intf->channels[j].lun = 2; - } - if (slave_addr != 0) - new_intf->channels[0].address = slave_addr; - rwlock_init(&(new_intf->users_lock)); - INIT_LIST_HEAD(&(new_intf->users)); - new_intf->handlers = handlers; - new_intf->send_info = send_info; - spin_lock_init(&(new_intf->seq_lock)); - for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) { - new_intf->seq_table[j].inuse = 0; - new_intf->seq_table[j].seqid = 0; - } - new_intf->curr_seq = 0; -#ifdef CONFIG_PROC_FS - spin_lock_init(&(new_intf->proc_entry_lock)); -#endif - spin_lock_init(&(new_intf->waiting_msgs_lock)); - INIT_LIST_HEAD(&(new_intf->waiting_msgs)); - spin_lock_init(&(new_intf->events_lock)); - INIT_LIST_HEAD(&(new_intf->waiting_events)); - new_intf->waiting_events_count = 0; - rwlock_init(&(new_intf->cmd_rcvr_lock)); - init_waitqueue_head(&new_intf->waitq); - INIT_LIST_HEAD(&(new_intf->cmd_rcvrs)); - - spin_lock_init(&(new_intf->counter_lock)); - - spin_lock_irqsave(&interfaces_lock, flags); - ipmi_interfaces[i] = new_intf; - spin_unlock_irqrestore(&interfaces_lock, flags); - + intf->intf_num = i; + /* Reserve the entry till we are done. */ + ipmi_interfaces[i] = IPMI_INVALID_INTERFACE_ENTRY; rv = 0; - *intf = new_intf; break; } } + spin_unlock_irqrestore(&interfaces_lock, flags); + if (rv) + goto out; - downgrade_write(&interfaces_sem); - - if (rv == 0) - rv = add_proc_entries(*intf, i); - - if (rv == 0) { - if ((version_major > 1) - || ((version_major == 1) && (version_minor >= 5))) - { - /* Start scanning the channels to see what is - available. */ - (*intf)->null_user_handler = channel_handler; - (*intf)->curr_channel = 0; - rv = send_channel_info_cmd(*intf, 0); - if (rv) - goto out; + /* FIXME - this is an ugly kludge, this sets the intf for the + caller before sending any messages with it. */ + *new_intf = intf; - /* Wait for the channel info to be read. */ - up_read(&interfaces_sem); - wait_event((*intf)->waitq, - ((*intf)->curr_channel>=IPMI_MAX_CHANNELS)); - down_read(&interfaces_sem); + if ((version_major > 1) + || ((version_major == 1) && (version_minor >= 5))) + { + /* Start scanning the channels to see what is + available. */ + intf->null_user_handler = channel_handler; + intf->curr_channel = 0; + rv = send_channel_info_cmd(intf, 0); + if (rv) + goto out; - if (ipmi_interfaces[i] != new_intf) - /* Well, it went away. Just return. */ - goto out; - } else { - /* Assume a single IPMB channel at zero. */ - (*intf)->channels[0].medium = IPMI_CHANNEL_MEDIUM_IPMB; - (*intf)->channels[0].protocol - = IPMI_CHANNEL_PROTOCOL_IPMB; - } - - /* Call all the watcher interfaces to tell - them that a new interface is available. */ - call_smi_watchers(i); + /* Wait for the channel info to be read. */ + wait_event(intf->waitq, + intf->curr_channel >= IPMI_MAX_CHANNELS); + } else { + /* Assume a single IPMB channel at zero. */ + intf->channels[0].medium = IPMI_CHANNEL_MEDIUM_IPMB; + intf->channels[0].protocol = IPMI_CHANNEL_PROTOCOL_IPMB; } - out: - up_read(&interfaces_sem); + if (rv == 0) + rv = add_proc_entries(intf, i); + out: if (rv) { - if (new_intf->proc_dir) - remove_proc_entries(new_intf); - kfree(new_intf); + if (intf->proc_dir) + remove_proc_entries(intf); + kref_put(&intf->refcount, intf_free); + if (i < MAX_IPMI_INTERFACES) { + spin_lock_irqsave(&interfaces_lock, flags); + ipmi_interfaces[i] = NULL; + spin_unlock_irqrestore(&interfaces_lock, flags); + } + } else { + spin_lock_irqsave(&interfaces_lock, flags); + ipmi_interfaces[i] = intf; + spin_unlock_irqrestore(&interfaces_lock, flags); + call_smi_watchers(i); } return rv; } -static void free_recv_msg_list(struct list_head *q) -{ - struct ipmi_recv_msg *msg, *msg2; - - list_for_each_entry_safe(msg, msg2, q, link) { - list_del(&msg->link); - ipmi_free_recv_msg(msg); - } -} - -static void free_cmd_rcvr_list(struct list_head *q) -{ - struct cmd_rcvr *rcvr, *rcvr2; - - list_for_each_entry_safe(rcvr, rcvr2, q, link) { - list_del(&rcvr->link); - kfree(rcvr); - } -} - -static void clean_up_interface_data(ipmi_smi_t intf) -{ - int i; - - free_recv_msg_list(&(intf->waiting_msgs)); - free_recv_msg_list(&(intf->waiting_events)); - free_cmd_rcvr_list(&(intf->cmd_rcvrs)); - - for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { - if ((intf->seq_table[i].inuse) - && (intf->seq_table[i].recv_msg)) - { - ipmi_free_recv_msg(intf->seq_table[i].recv_msg); - } - } -} - int ipmi_unregister_smi(ipmi_smi_t intf) { - int rv = -ENODEV; int i; struct ipmi_smi_watcher *w; unsigned long flags; - down_write(&interfaces_sem); - if (list_empty(&(intf->users))) - { - for (i = 0; i < MAX_IPMI_INTERFACES; i++) { - if (ipmi_interfaces[i] == intf) { - remove_proc_entries(intf); - spin_lock_irqsave(&interfaces_lock, flags); - ipmi_interfaces[i] = NULL; - clean_up_interface_data(intf); - spin_unlock_irqrestore(&interfaces_lock,flags); - kfree(intf); - rv = 0; - goto out_call_watcher; - } + spin_lock_irqsave(&interfaces_lock, flags); + for (i = 0; i < MAX_IPMI_INTERFACES; i++) { + if (ipmi_interfaces[i] == intf) { + /* Set the interface number reserved until we + * are done. */ + ipmi_interfaces[i] = IPMI_INVALID_INTERFACE_ENTRY; + intf->intf_num = -1; + break; } - } else { - rv = -EBUSY; } - up_write(&interfaces_sem); + spin_unlock_irqrestore(&interfaces_lock,flags); - return rv; + if (i == MAX_IPMI_INTERFACES) + return -ENODEV; - out_call_watcher: - downgrade_write(&interfaces_sem); + remove_proc_entries(intf); /* Call all the watcher interfaces to tell them that an interface is gone. */ down_read(&smi_watchers_sem); - list_for_each_entry(w, &smi_watchers, link) { + list_for_each_entry(w, &smi_watchers, link) w->smi_gone(i); - } up_read(&smi_watchers_sem); - up_read(&interfaces_sem); + + /* Allow the entry to be reused now. */ + spin_lock_irqsave(&interfaces_lock, flags); + ipmi_interfaces[i] = NULL; + spin_unlock_irqrestore(&interfaces_lock,flags); + + kref_put(&intf->refcount, intf_free); return 0; } @@ -1998,14 +2033,14 @@ static int handle_ipmb_get_msg_rsp(ipmi_smi_t intf, static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, struct ipmi_smi_msg *msg) { - struct cmd_rcvr *rcvr; - int rv = 0; - unsigned char netfn; - unsigned char cmd; - ipmi_user_t user = NULL; - struct ipmi_ipmb_addr *ipmb_addr; - struct ipmi_recv_msg *recv_msg; - unsigned long flags; + struct cmd_rcvr *rcvr; + int rv = 0; + unsigned char netfn; + unsigned char cmd; + ipmi_user_t user = NULL; + struct ipmi_ipmb_addr *ipmb_addr; + struct ipmi_recv_msg *recv_msg; + unsigned long flags; if (msg->rsp_size < 10) { /* Message not big enough, just ignore it. */ @@ -2023,16 +2058,14 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, netfn = msg->rsp[4] >> 2; cmd = msg->rsp[8]; - read_lock(&(intf->cmd_rcvr_lock)); - - /* Find the command/netfn. */ - list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) { - if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { - user = rcvr->user; - break; - } - } - read_unlock(&(intf->cmd_rcvr_lock)); + spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); + rcvr = find_cmd_rcvr(intf, netfn, cmd); + if (rcvr) { + user = rcvr->user; + kref_get(&user->refcount); + } else + user = NULL; + spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); if (user == NULL) { /* We didn't find a user, deliver an error response. */ @@ -2079,6 +2112,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, message, so requeue it for handling later. */ rv = 1; + kref_put(&user->refcount, free_user); } else { /* Extract the source address from the data. */ ipmb_addr = (struct ipmi_ipmb_addr *) &recv_msg->addr; @@ -2179,14 +2213,14 @@ static int handle_lan_get_msg_rsp(ipmi_smi_t intf, static int handle_lan_get_msg_cmd(ipmi_smi_t intf, struct ipmi_smi_msg *msg) { - struct cmd_rcvr *rcvr; - int rv = 0; - unsigned char netfn; - unsigned char cmd; - ipmi_user_t user = NULL; - struct ipmi_lan_addr *lan_addr; - struct ipmi_recv_msg *recv_msg; - unsigned long flags; + struct cmd_rcvr *rcvr; + int rv = 0; + unsigned char netfn; + unsigned char cmd; + ipmi_user_t user = NULL; + struct ipmi_lan_addr *lan_addr; + struct ipmi_recv_msg *recv_msg; + unsigned long flags; if (msg->rsp_size < 12) { /* Message not big enough, just ignore it. */ @@ -2204,19 +2238,17 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf, netfn = msg->rsp[6] >> 2; cmd = msg->rsp[10]; - read_lock(&(intf->cmd_rcvr_lock)); - - /* Find the command/netfn. */ - list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) { - if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { - user = rcvr->user; - break; - } - } - read_unlock(&(intf->cmd_rcvr_lock)); + spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); + rcvr = find_cmd_rcvr(intf, netfn, cmd); + if (rcvr) { + user = rcvr->user; + kref_get(&user->refcount); + } else + user = NULL; + spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); if (user == NULL) { - /* We didn't find a user, deliver an error response. */ + /* We didn't find a user, just give up. */ spin_lock_irqsave(&intf->counter_lock, flags); intf->unhandled_commands++; spin_unlock_irqrestore(&intf->counter_lock, flags); @@ -2235,6 +2267,7 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf, message, so requeue it for handling later. */ rv = 1; + kref_put(&user->refcount, free_user); } else { /* Extract the source address from the data. */ lan_addr = (struct ipmi_lan_addr *) &recv_msg->addr; @@ -2286,8 +2319,6 @@ static void copy_event_into_recv_msg(struct ipmi_recv_msg *recv_msg, recv_msg->msg.data_len = msg->rsp_size - 3; } -/* This will be called with the intf->users_lock read-locked, so no need - to do that here. */ static int handle_read_event_rsp(ipmi_smi_t intf, struct ipmi_smi_msg *msg) { @@ -2313,7 +2344,7 @@ static int handle_read_event_rsp(ipmi_smi_t intf, INIT_LIST_HEAD(&msgs); - spin_lock_irqsave(&(intf->events_lock), flags); + spin_lock_irqsave(&intf->events_lock, flags); spin_lock(&intf->counter_lock); intf->events++; @@ -2321,12 +2352,14 @@ static int handle_read_event_rsp(ipmi_smi_t intf, /* Allocate and fill in one message for every user that is getting events. */ - list_for_each_entry(user, &(intf->users), link) { + rcu_read_lock(); + list_for_each_entry_rcu(user, &intf->users, link) { if (! user->gets_events) continue; recv_msg = ipmi_alloc_recv_msg(); if (! recv_msg) { + rcu_read_unlock(); list_for_each_entry_safe(recv_msg, recv_msg2, &msgs, link) { list_del(&recv_msg->link); ipmi_free_recv_msg(recv_msg); @@ -2342,8 +2375,10 @@ static int handle_read_event_rsp(ipmi_smi_t intf, copy_event_into_recv_msg(recv_msg, msg); recv_msg->user = user; + kref_get(&user->refcount); list_add_tail(&(recv_msg->link), &msgs); } + rcu_read_unlock(); if (deliver_count) { /* Now deliver all the messages. */ @@ -2382,9 +2417,8 @@ static int handle_bmc_rsp(ipmi_smi_t intf, struct ipmi_smi_msg *msg) { struct ipmi_recv_msg *recv_msg; - int found = 0; - struct ipmi_user *user; unsigned long flags; + struct ipmi_user *user; recv_msg = (struct ipmi_recv_msg *) msg->user_data; if (recv_msg == NULL) @@ -2396,16 +2430,9 @@ static int handle_bmc_rsp(ipmi_smi_t intf, return 0; } + user = recv_msg->user; /* Make sure the user still exists. */ - list_for_each_entry(user, &(intf->users), link) { - if (user == recv_msg->user) { - /* Found it, so we can deliver it */ - found = 1; - break; - } - } - - if ((! found) && recv_msg->user) { + if (user && !user->valid) { /* The user for the message went away, so give up. */ spin_lock_irqsave(&intf->counter_lock, flags); intf->unhandled_local_responses++; @@ -2486,7 +2513,7 @@ static int handle_new_recv_msg(ipmi_smi_t intf, { /* It's a response to a response we sent. For this we deliver a send message response to the user. */ - struct ipmi_recv_msg *recv_msg = msg->user_data; + struct ipmi_recv_msg *recv_msg = msg->user_data; requeue = 0; if (msg->rsp_size < 2) @@ -2498,13 +2525,18 @@ static int handle_new_recv_msg(ipmi_smi_t intf, /* Invalid channel number */ goto out; - if (recv_msg) { - recv_msg->recv_type = IPMI_RESPONSE_RESPONSE_TYPE; - recv_msg->msg.data = recv_msg->msg_data; - recv_msg->msg.data_len = 1; - recv_msg->msg_data[0] = msg->rsp[2]; - deliver_response(recv_msg); - } + if (!recv_msg) + goto out; + + /* Make sure the user still exists. */ + if (!recv_msg->user || !recv_msg->user->valid) + goto out; + + recv_msg->recv_type = IPMI_RESPONSE_RESPONSE_TYPE; + recv_msg->msg.data = recv_msg->msg_data; + recv_msg->msg.data_len = 1; + recv_msg->msg_data[0] = msg->rsp[2]; + deliver_response(recv_msg); } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2)) && (msg->rsp[1] == IPMI_GET_MSG_CMD)) { @@ -2570,14 +2602,11 @@ void ipmi_smi_msg_received(ipmi_smi_t intf, int rv; - /* Lock the user lock so the user can't go away while we are - working on it. */ - read_lock(&(intf->users_lock)); - if ((msg->data_size >= 2) && (msg->data[0] == (IPMI_NETFN_APP_REQUEST << 2)) && (msg->data[1] == IPMI_SEND_MSG_CMD) - && (msg->user_data == NULL)) { + && (msg->user_data == NULL)) + { /* This is the local response to a command send, start the timer for these. The user_data will not be NULL if this is a response send, and we will let @@ -2612,46 +2641,46 @@ void ipmi_smi_msg_received(ipmi_smi_t intf, } ipmi_free_smi_msg(msg); - goto out_unlock; + goto out; } /* To preserve message order, if the list is not empty, we tack this message onto the end of the list. */ - spin_lock_irqsave(&(intf->waiting_msgs_lock), flags); - if (!list_empty(&(intf->waiting_msgs))) { - list_add_tail(&(msg->link), &(intf->waiting_msgs)); - spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags); - goto out_unlock; + spin_lock_irqsave(&intf->waiting_msgs_lock, flags); + if (!list_empty(&intf->waiting_msgs)) { + list_add_tail(&msg->link, &intf->waiting_msgs); + spin_unlock(&intf->waiting_msgs_lock); + goto out; } - spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags); + spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags); rv = handle_new_recv_msg(intf, msg); if (rv > 0) { /* Could not handle the message now, just add it to a list to handle later. */ - spin_lock_irqsave(&(intf->waiting_msgs_lock), flags); - list_add_tail(&(msg->link), &(intf->waiting_msgs)); - spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags); + spin_lock(&intf->waiting_msgs_lock); + list_add_tail(&msg->link, &intf->waiting_msgs); + spin_unlock(&intf->waiting_msgs_lock); } else if (rv == 0) { ipmi_free_smi_msg(msg); } - out_unlock: - read_unlock(&(intf->users_lock)); + out: + return; } void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf) { ipmi_user_t user; - read_lock(&(intf->users_lock)); - list_for_each_entry(user, &(intf->users), link) { + rcu_read_lock(); + list_for_each_entry_rcu(user, &intf->users, link) { if (! user->handler->ipmi_watchdog_pretimeout) continue; user->handler->ipmi_watchdog_pretimeout(user->handler_data); } - read_unlock(&(intf->users_lock)); + rcu_read_unlock(); } static void @@ -2691,8 +2720,65 @@ smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg, return smi_msg; } -static void -ipmi_timeout_handler(long timeout_period) +static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, + struct list_head *timeouts, long timeout_period, + int slot, unsigned long *flags) +{ + struct ipmi_recv_msg *msg; + + if (!ent->inuse) + return; + + ent->timeout -= timeout_period; + if (ent->timeout > 0) + return; + + if (ent->retries_left == 0) { + /* The message has used all its retries. */ + ent->inuse = 0; + msg = ent->recv_msg; + list_add_tail(&msg->link, timeouts); + spin_lock(&intf->counter_lock); + if (ent->broadcast) + intf->timed_out_ipmb_broadcasts++; + else if (ent->recv_msg->addr.addr_type == IPMI_LAN_ADDR_TYPE) + intf->timed_out_lan_commands++; + else + intf->timed_out_ipmb_commands++; + spin_unlock(&intf->counter_lock); + } else { + struct ipmi_smi_msg *smi_msg; + /* More retries, send again. */ + + /* Start with the max timer, set to normal + timer after the message is sent. */ + ent->timeout = MAX_MSG_TIMEOUT; + ent->retries_left--; + spin_lock(&intf->counter_lock); + if (ent->recv_msg->addr.addr_type == IPMI_LAN_ADDR_TYPE) + intf->retransmitted_lan_commands++; + else + intf->retransmitted_ipmb_commands++; + spin_unlock(&intf->counter_lock); + + smi_msg = smi_from_recv_msg(intf, ent->recv_msg, slot, + ent->seqid); + if (! smi_msg) + return; + + spin_unlock_irqrestore(&intf->seq_lock, *flags); + /* Send the new message. We send with a zero + * priority. It timed out, I doubt time is + * that critical now, and high priority + * messages are really only for messages to the + * local MC, which don't get resent. */ + intf->handlers->sender(intf->send_info, + smi_msg, 0); + spin_lock_irqsave(&intf->seq_lock, *flags); + } +} + +static void ipmi_timeout_handler(long timeout_period) { ipmi_smi_t intf; struct list_head timeouts; @@ -2706,14 +2792,14 @@ ipmi_timeout_handler(long timeout_period) spin_lock(&interfaces_lock); for (i = 0; i < MAX_IPMI_INTERFACES; i++) { intf = ipmi_interfaces[i]; - if (intf == NULL) + if (IPMI_INVALID_INTERFACE(intf)) continue; - - read_lock(&(intf->users_lock)); + kref_get(&intf->refcount); + spin_unlock(&interfaces_lock); /* See if any waiting messages need to be processed. */ - spin_lock_irqsave(&(intf->waiting_msgs_lock), flags); - list_for_each_entry_safe(smi_msg, smi_msg2, &(intf->waiting_msgs), link) { + spin_lock_irqsave(&intf->waiting_msgs_lock, flags); + list_for_each_entry_safe(smi_msg, smi_msg2, &intf->waiting_msgs, link) { if (! handle_new_recv_msg(intf, smi_msg)) { list_del(&smi_msg->link); ipmi_free_smi_msg(smi_msg); @@ -2723,73 +2809,23 @@ ipmi_timeout_handler(long timeout_period) break; } } - spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags); + spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags); /* Go through the seq table and find any messages that have timed out, putting them in the timeouts list. */ - spin_lock_irqsave(&(intf->seq_lock), flags); - for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) { - struct seq_table *ent = &(intf->seq_table[j]); - if (!ent->inuse) - continue; - - ent->timeout -= timeout_period; - if (ent->timeout > 0) - continue; - - if (ent->retries_left == 0) { - /* The message has used all its retries. */ - ent->inuse = 0; - msg = ent->recv_msg; - list_add_tail(&(msg->link), &timeouts); - spin_lock(&intf->counter_lock); - if (ent->broadcast) - intf->timed_out_ipmb_broadcasts++; - else if (ent->recv_msg->addr.addr_type - == IPMI_LAN_ADDR_TYPE) - intf->timed_out_lan_commands++; - else - intf->timed_out_ipmb_commands++; - spin_unlock(&intf->counter_lock); - } else { - struct ipmi_smi_msg *smi_msg; - /* More retries, send again. */ - - /* Start with the max timer, set to normal - timer after the message is sent. */ - ent->timeout = MAX_MSG_TIMEOUT; - ent->retries_left--; - spin_lock(&intf->counter_lock); - if (ent->recv_msg->addr.addr_type - == IPMI_LAN_ADDR_TYPE) - intf->retransmitted_lan_commands++; - else - intf->retransmitted_ipmb_commands++; - spin_unlock(&intf->counter_lock); - smi_msg = smi_from_recv_msg(intf, - ent->recv_msg, j, ent->seqid); - if (! smi_msg) - continue; - - spin_unlock_irqrestore(&(intf->seq_lock),flags); - /* Send the new message. We send with a zero - * priority. It timed out, I doubt time is - * that critical now, and high priority - * messages are really only for messages to the - * local MC, which don't get resent. */ - intf->handlers->sender(intf->send_info, - smi_msg, 0); - spin_lock_irqsave(&(intf->seq_lock), flags); - } - } - spin_unlock_irqrestore(&(intf->seq_lock), flags); - - list_for_each_entry_safe(msg, msg2, &timeouts, link) { + spin_lock_irqsave(&intf->seq_lock, flags); + for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) + check_msg_timeout(intf, &(intf->seq_table[j]), + &timeouts, timeout_period, j, + &flags); + spin_unlock_irqrestore(&intf->seq_lock, flags); + + list_for_each_entry_safe(msg, msg2, &timeouts, link) handle_msg_timeout(msg); - } - read_unlock(&(intf->users_lock)); + kref_put(&intf->refcount, intf_free); + spin_lock(&interfaces_lock); } spin_unlock(&interfaces_lock); } @@ -2802,7 +2838,7 @@ static void ipmi_request_event(void) spin_lock(&interfaces_lock); for (i = 0; i < MAX_IPMI_INTERFACES; i++) { intf = ipmi_interfaces[i]; - if (intf == NULL) + if (IPMI_INVALID_INTERFACE(intf)) continue; intf->handlers->request_events(intf->send_info); @@ -2884,6 +2920,13 @@ struct ipmi_recv_msg *ipmi_alloc_recv_msg(void) return rv; } +void ipmi_free_recv_msg(struct ipmi_recv_msg *msg) +{ + if (msg->user) + kref_put(&msg->user->refcount, free_user); + msg->done(msg); +} + #ifdef CONFIG_IPMI_PANIC_EVENT static void dummy_smi_done_handler(struct ipmi_smi_msg *msg) @@ -2964,7 +3007,7 @@ static void send_panic_events(char *str) /* For every registered interface, send the event. */ for (i = 0; i < MAX_IPMI_INTERFACES; i++) { intf = ipmi_interfaces[i]; - if (intf == NULL) + if (IPMI_INVALID_INTERFACE(intf)) continue; /* Send the event announcing the panic. */ @@ -2995,7 +3038,7 @@ static void send_panic_events(char *str) int j; intf = ipmi_interfaces[i]; - if (intf == NULL) + if (IPMI_INVALID_INTERFACE(intf)) continue; /* First job here is to figure out where to send the @@ -3131,7 +3174,7 @@ static int panic_event(struct notifier_block *this, /* For every registered interface, set it to run to completion. */ for (i = 0; i < MAX_IPMI_INTERFACES; i++) { intf = ipmi_interfaces[i]; - if (intf == NULL) + if (IPMI_INVALID_INTERFACE(intf)) continue; intf->handlers->set_run_to_completion(intf->send_info, 1); @@ -3160,9 +3203,8 @@ static int ipmi_init_msghandler(void) printk(KERN_INFO "ipmi message handler version " IPMI_DRIVER_VERSION "\n"); - for (i = 0; i < MAX_IPMI_INTERFACES; i++) { + for (i = 0; i < MAX_IPMI_INTERFACES; i++) ipmi_interfaces[i] = NULL; - } #ifdef CONFIG_PROC_FS proc_ipmi_root = proc_mkdir("ipmi", NULL); @@ -3258,3 +3300,4 @@ EXPORT_SYMBOL(ipmi_get_my_LUN); EXPORT_SYMBOL(ipmi_smi_add_proc_entry); EXPORT_SYMBOL(proc_ipmi_root); EXPORT_SYMBOL(ipmi_user_set_run_to_completion); +EXPORT_SYMBOL(ipmi_free_recv_msg); diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h index 938d55b813a..d6276e60b3b 100644 --- a/include/linux/ipmi.h +++ b/include/linux/ipmi.h @@ -256,10 +256,7 @@ struct ipmi_recv_msg }; /* Allocate and free the receive message. */ -static inline void ipmi_free_recv_msg(struct ipmi_recv_msg *msg) -{ - msg->done(msg); -} +void ipmi_free_recv_msg(struct ipmi_recv_msg *msg); struct ipmi_user_hndl { -- cgit v1.2.3 From c4edff1c19ef23e15aae64ca03f32c6719822d54 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 7 Nov 2005 00:59:56 -0800 Subject: [PATCH] ipmi: various si cleanup A number of small changes for the various system interface drivers, consolidated from a number of patches from Matt Domsch. Clear B2H_ATN and drain the BMC message buffer on command timeout. This prevents further commands from failing after a timeout. Add bt_debug and smic_debug module parameters, expose them in sysfs. This lets you enable and disable debugging messages at runtime. Unsigned jiffies math in ipmi_si_intf.c causes a too-large value to be passed to ->event() after jiffies wrap-around. The BT driver had caught this, but didn't know how to fix it. Now all calls to ->event() use a sane value for time. Increase timeout for commands handed to the BT driver from 2 seconds to 5 seconds. This is necessary particularly when the previous command was a "Clear SEL", as that command completes, yet the BMC isn't really ready to handle another command yet. Silence BT debugging messages which were being printed on the console. Increase SMIC timeout form 1/10s to 2s. This is needed on Dell PowerEdge 2650 and PowerEdge 750 with ERA/O cards to allow commands to complete without timing out. Adds kcs_debug module param, to match behavior of BT and SMIC. This also prevents messages from being sent to the console unless explicitly requested. Signed-off-by: Matt Domsch Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_bt_sm.c | 34 +++++++++++++--------------------- drivers/char/ipmi/ipmi_kcs_sm.c | 40 +++++++++++++++++++++++++++------------- drivers/char/ipmi/ipmi_si_intf.c | 4 ++-- drivers/char/ipmi/ipmi_smic_sm.c | 6 +++++- 4 files changed, 47 insertions(+), 37 deletions(-) diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c index 33862670e28..7c4a195dfc9 100644 --- a/drivers/char/ipmi/ipmi_bt_sm.c +++ b/drivers/char/ipmi/ipmi_bt_sm.c @@ -28,6 +28,8 @@ #include /* For printk. */ #include +#include +#include #include /* for completion codes */ #include "ipmi_si_sm.h" @@ -36,6 +38,8 @@ static int bt_debug = 0x00; /* Production value 0, see following flags */ #define BT_DEBUG_ENABLE 1 #define BT_DEBUG_MSG 2 #define BT_DEBUG_STATES 4 +module_param(bt_debug, int, 0644); +MODULE_PARM_DESC(bt_debug, "debug bitmask, 1=enable, 2=messages, 4=states"); /* Typical "Get BT Capabilities" values are 2-3 retries, 5-10 seconds, and 64 byte buffers. However, one HP implementation wants 255 bytes of @@ -43,7 +47,7 @@ static int bt_debug = 0x00; /* Production value 0, see following flags */ Since the Open IPMI architecture is single-message oriented at this stage, the queue depth of BT is of no concern. */ -#define BT_NORMAL_TIMEOUT 2000000 /* seconds in microseconds */ +#define BT_NORMAL_TIMEOUT 5000000 /* seconds in microseconds */ #define BT_RETRY_LIMIT 2 #define BT_RESET_DELAY 6000000 /* 6 seconds after warm reset */ @@ -202,7 +206,7 @@ static int bt_get_result(struct si_sm_data *bt, msg_len = bt->read_count - 2; /* account for length & seq */ /* Always NetFn, Cmd, cCode */ if (msg_len < 3 || msg_len > IPMI_MAX_MSG_LENGTH) { - printk(KERN_WARNING "BT results: bad msg_len = %d\n", msg_len); + printk(KERN_DEBUG "BT results: bad msg_len = %d\n", msg_len); data[0] = bt->write_data[1] | 0x4; /* Kludge a response */ data[1] = bt->write_data[3]; data[2] = IPMI_ERR_UNSPECIFIED; @@ -240,7 +244,7 @@ static void reset_flags(struct si_sm_data *bt) BT_CONTROL(BT_B_BUSY); BT_CONTROL(BT_CLR_WR_PTR); BT_CONTROL(BT_SMS_ATN); -#ifdef DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION + if (BT_STATUS & BT_B2H_ATN) { int i; BT_CONTROL(BT_H_BUSY); @@ -250,7 +254,6 @@ static void reset_flags(struct si_sm_data *bt) BMC2HOST; BT_CONTROL(BT_H_BUSY); } -#endif } static inline void write_all_bytes(struct si_sm_data *bt) @@ -295,7 +298,7 @@ static inline int read_all_bytes(struct si_sm_data *bt) printk ("\n"); } if (bt->seq != bt->write_data[2]) /* idiot check */ - printk(KERN_WARNING "BT: internal error: sequence mismatch\n"); + printk(KERN_DEBUG "BT: internal error: sequence mismatch\n"); /* per the spec, the (NetFn, Seq, Cmd) tuples should match */ if ((bt->read_data[3] == bt->write_data[3]) && /* Cmd */ @@ -321,18 +324,18 @@ static void error_recovery(struct si_sm_data *bt, char *reason) bt->timeout = BT_NORMAL_TIMEOUT; /* various places want to retry */ status = BT_STATUS; - printk(KERN_WARNING "BT: %s in %s %s ", reason, STATE2TXT, + printk(KERN_DEBUG "BT: %s in %s %s\n", reason, STATE2TXT, STATUS2TXT(buf)); (bt->error_retries)++; if (bt->error_retries > BT_RETRY_LIMIT) { - printk("retry limit (%d) exceeded\n", BT_RETRY_LIMIT); + printk(KERN_DEBUG "retry limit (%d) exceeded\n", BT_RETRY_LIMIT); bt->state = BT_STATE_HOSED; if (!bt->nonzero_status) printk(KERN_ERR "IPMI: BT stuck, try power cycle\n"); else if (bt->seq == FIRST_SEQ + BT_RETRY_LIMIT) { /* most likely during insmod */ - printk(KERN_WARNING "IPMI: BT reset (takes 5 secs)\n"); + printk(KERN_DEBUG "IPMI: BT reset (takes 5 secs)\n"); bt->state = BT_STATE_RESET1; } return; @@ -340,11 +343,11 @@ static void error_recovery(struct si_sm_data *bt, char *reason) /* Sometimes the BMC queues get in an "off-by-one" state...*/ if ((bt->state == BT_STATE_B2H_WAIT) && (status & BT_B2H_ATN)) { - printk("retry B2H_WAIT\n"); + printk(KERN_DEBUG "retry B2H_WAIT\n"); return; } - printk("restart command\n"); + printk(KERN_DEBUG "restart command\n"); bt->state = BT_STATE_RESTART; } @@ -372,17 +375,6 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) return SI_SM_HOSED; if (bt->state != BT_STATE_IDLE) { /* do timeout test */ - - /* Certain states, on error conditions, can lock up a CPU - because they are effectively in an infinite loop with - CALL_WITHOUT_DELAY (right back here with time == 0). - Prevent infinite lockup by ALWAYS decrementing timeout. */ - - /* FIXME: bt_event is sometimes called with time > BT_NORMAL_TIMEOUT - (noticed in ipmi_smic_sm.c January 2004) */ - - if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT)) - time = 100; bt->timeout -= time; if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) { error_recovery(bt, "timed out"); diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c index d21853a594a..dc83365ede4 100644 --- a/drivers/char/ipmi/ipmi_kcs_sm.c +++ b/drivers/char/ipmi/ipmi_kcs_sm.c @@ -38,16 +38,24 @@ */ #include /* For printk. */ +#include +#include #include #include /* for completion codes */ #include "ipmi_si_sm.h" -/* Set this if you want a printout of why the state machine was hosed - when it gets hosed. */ -#define DEBUG_HOSED_REASON +/* kcs_debug is a bit-field + * KCS_DEBUG_ENABLE - turned on for now + * KCS_DEBUG_MSG - commands and their responses + * KCS_DEBUG_STATES - state machine + */ +#define KCS_DEBUG_STATES 4 +#define KCS_DEBUG_MSG 2 +#define KCS_DEBUG_ENABLE 1 -/* Print the state machine state on entry every time. */ -#undef DEBUG_STATE +static int kcs_debug; +module_param(kcs_debug, int, 0644); +MODULE_PARM_DESC(kcs_debug, "debug bitmask, 1=enable, 2=messages, 4=states"); /* The states the KCS driver may be in. */ enum kcs_states { @@ -175,9 +183,8 @@ static inline void start_error_recovery(struct si_sm_data *kcs, char *reason) { (kcs->error_retries)++; if (kcs->error_retries > MAX_ERROR_RETRIES) { -#ifdef DEBUG_HOSED_REASON - printk("ipmi_kcs_sm: kcs hosed: %s\n", reason); -#endif + if (kcs_debug & KCS_DEBUG_ENABLE) + printk(KERN_DEBUG "ipmi_kcs_sm: kcs hosed: %s\n", reason); kcs->state = KCS_HOSED; } else { kcs->state = KCS_ERROR0; @@ -248,14 +255,21 @@ static void restart_kcs_transaction(struct si_sm_data *kcs) static int start_kcs_transaction(struct si_sm_data *kcs, unsigned char *data, unsigned int size) { + unsigned int i; + if ((size < 2) || (size > MAX_KCS_WRITE_SIZE)) { return -1; } - if ((kcs->state != KCS_IDLE) && (kcs->state != KCS_HOSED)) { return -2; } - + if (kcs_debug & KCS_DEBUG_MSG) { + printk(KERN_DEBUG "start_kcs_transaction -"); + for (i = 0; i < size; i ++) { + printk(" %02x", (unsigned char) (data [i])); + } + printk ("\n"); + } kcs->error_retries = 0; memcpy(kcs->write_data, data, size); kcs->write_count = size; @@ -305,9 +319,9 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time) status = read_status(kcs); -#ifdef DEBUG_STATE - printk(" State = %d, %x\n", kcs->state, status); -#endif + if (kcs_debug & KCS_DEBUG_STATES) + printk(KERN_DEBUG "KCS: State = %d, %x\n", kcs->state, status); + /* All states wait for ibf, so just do it here. */ if (!check_ibf(kcs, status, time)) return SI_SM_CALL_WITH_DELAY; diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index b6e5cbfb09f..204e2e987e9 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -819,7 +819,7 @@ static void smi_timeout(unsigned long data) enum si_sm_result smi_result; unsigned long flags; unsigned long jiffies_now; - unsigned long time_diff; + long time_diff; #ifdef DEBUG_TIMING struct timeval t; #endif @@ -835,7 +835,7 @@ static void smi_timeout(unsigned long data) printk("**Timer: %d.%9.9d\n", t.tv_sec, t.tv_usec); #endif jiffies_now = jiffies; - time_diff = ((jiffies_now - smi_info->last_timeout_jiffies) + time_diff = (((long)jiffies_now - (long)smi_info->last_timeout_jiffies) * SI_USEC_PER_JIFFY); smi_result = smi_event_handler(smi_info, time_diff); diff --git a/drivers/char/ipmi/ipmi_smic_sm.c b/drivers/char/ipmi/ipmi_smic_sm.c index add2aa2732f..f17043da9dd 100644 --- a/drivers/char/ipmi/ipmi_smic_sm.c +++ b/drivers/char/ipmi/ipmi_smic_sm.c @@ -43,6 +43,8 @@ #include /* For printk. */ #include +#include +#include #include /* for completion codes */ #include "ipmi_si_sm.h" @@ -56,6 +58,8 @@ #define SMIC_DEBUG_ENABLE 1 static int smic_debug = 1; +module_param(smic_debug, int, 0644); +MODULE_PARM_DESC(smic_debug, "debug bitmask, 1=enable, 2=messages, 4=states"); enum smic_states { SMIC_IDLE, @@ -76,7 +80,7 @@ enum smic_states { #define SMIC_MAX_ERROR_RETRIES 3 /* Timeouts in microseconds. */ -#define SMIC_RETRY_TIMEOUT 100000 +#define SMIC_RETRY_TIMEOUT 2000000 /* SMIC Flags Register Bits */ #define SMIC_RX_DATA_READY 0x80 -- cgit v1.2.3 From cc4673eecdcc4a918e4d8796295d798b5e98d602 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 7 Nov 2005 00:59:57 -0800 Subject: [PATCH] ipmi: watchdog parms in sysfs Modify the IPMI watchdog parameters (the ones that make sense) to be exported from sysfs. This is somewhat complicated because these parameters have side-effects that must be handled. Signed-off-by: Corey Minyard Cc: Matt Domsch Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_watchdog.c | 246 ++++++++++++++++++++++++++++++-------- 1 file changed, 196 insertions(+), 50 deletions(-) diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 2da64bf7469..405697a9f4d 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -47,6 +47,8 @@ #include #include #include +#include +#include #ifdef CONFIG_X86_LOCAL_APIC #include #endif @@ -158,27 +160,120 @@ static struct fasync_struct *fasync_q = NULL; static char pretimeout_since_last_heartbeat = 0; static char expect_close; +static DECLARE_RWSEM(register_sem); + +/* Parameters to ipmi_set_timeout */ +#define IPMI_SET_TIMEOUT_NO_HB 0 +#define IPMI_SET_TIMEOUT_HB_IF_NECESSARY 1 +#define IPMI_SET_TIMEOUT_FORCE_HB 2 + +static int ipmi_set_timeout(int do_heartbeat); + /* If true, the driver will start running as soon as it is configured and ready. */ static int start_now = 0; -module_param(timeout, int, 0); +static int set_param_int(const char *val, struct kernel_param *kp) +{ + char *endp; + int l; + int rv = 0; + + if (!val) + return -EINVAL; + l = simple_strtoul(val, &endp, 0); + if (endp == val) + return -EINVAL; + + down_read(®ister_sem); + *((int *)kp->arg) = l; + if (watchdog_user) + rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); + up_read(®ister_sem); + + return rv; +} + +static int get_param_int(char *buffer, struct kernel_param *kp) +{ + return sprintf(buffer, "%i", *((int *)kp->arg)); +} + +typedef int (*action_fn)(const char *intval, char *outval); + +static int action_op(const char *inval, char *outval); +static int preaction_op(const char *inval, char *outval); +static int preop_op(const char *inval, char *outval); +static void check_parms(void); + +static int set_param_str(const char *val, struct kernel_param *kp) +{ + action_fn fn = (action_fn) kp->arg; + int rv = 0; + const char *end; + char valcp[16]; + int len; + + /* Truncate leading and trailing spaces. */ + while (isspace(*val)) + val++; + end = val + strlen(val) - 1; + while ((end >= val) && isspace(*end)) + end--; + len = end - val + 1; + if (len > sizeof(valcp) - 1) + return -EINVAL; + memcpy(valcp, val, len); + valcp[len] = '\0'; + + down_read(®ister_sem); + rv = fn(valcp, NULL); + if (rv) + goto out_unlock; + + check_parms(); + if (watchdog_user) + rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); + + out_unlock: + up_read(®ister_sem); + return rv; +} + +static int get_param_str(char *buffer, struct kernel_param *kp) +{ + action_fn fn = (action_fn) kp->arg; + int rv; + + rv = fn(NULL, buffer); + if (rv) + return rv; + return strlen(buffer); +} + +module_param_call(timeout, set_param_int, get_param_int, &timeout, 0644); MODULE_PARM_DESC(timeout, "Timeout value in seconds."); -module_param(pretimeout, int, 0); + +module_param_call(pretimeout, set_param_int, get_param_int, &pretimeout, 0644); MODULE_PARM_DESC(pretimeout, "Pretimeout value in seconds."); -module_param_string(action, action, sizeof(action), 0); + +module_param_call(action, set_param_str, get_param_str, action_op, 0644); MODULE_PARM_DESC(action, "Timeout action. One of: " "reset, none, power_cycle, power_off."); -module_param_string(preaction, preaction, sizeof(preaction), 0); + +module_param_call(preaction, set_param_str, get_param_str, preaction_op, 0644); MODULE_PARM_DESC(preaction, "Pretimeout action. One of: " "pre_none, pre_smi, pre_nmi, pre_int."); -module_param_string(preop, preop, sizeof(preop), 0); + +module_param_call(preop, set_param_str, get_param_str, preop_op, 0644); MODULE_PARM_DESC(preop, "Pretimeout driver operation. One of: " "preop_none, preop_panic, preop_give_data."); + module_param(start_now, int, 0); MODULE_PARM_DESC(start_now, "Set to 1 to start the watchdog as" "soon as the driver is loaded."); -module_param(nowayout, int, 0); + +module_param(nowayout, int, 0644); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); /* Default state of the timer. */ @@ -294,11 +389,6 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg, return rv; } -/* Parameters to ipmi_set_timeout */ -#define IPMI_SET_TIMEOUT_NO_HB 0 -#define IPMI_SET_TIMEOUT_HB_IF_NECESSARY 1 -#define IPMI_SET_TIMEOUT_FORCE_HB 2 - static int ipmi_set_timeout(int do_heartbeat) { int send_heartbeat_now; @@ -732,8 +822,6 @@ static struct miscdevice ipmi_wdog_miscdev = { .fops = &ipmi_wdog_fops }; -static DECLARE_RWSEM(register_sem); - static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg, void *handler_data) { @@ -839,6 +927,7 @@ static struct nmi_handler ipmi_nmi_handler = .handler = ipmi_nmi, .priority = 0, /* Call us last. */ }; +int nmi_handler_registered; #endif static int wdog_reboot_handler(struct notifier_block *this, @@ -921,59 +1010,86 @@ static struct ipmi_smi_watcher smi_watcher = .smi_gone = ipmi_smi_gone }; -static int __init ipmi_wdog_init(void) +static int action_op(const char *inval, char *outval) { - int rv; + if (outval) + strcpy(outval, action); + + if (!inval) + return 0; - if (strcmp(action, "reset") == 0) { + if (strcmp(inval, "reset") == 0) action_val = WDOG_TIMEOUT_RESET; - } else if (strcmp(action, "none") == 0) { + else if (strcmp(inval, "none") == 0) action_val = WDOG_TIMEOUT_NONE; - } else if (strcmp(action, "power_cycle") == 0) { + else if (strcmp(inval, "power_cycle") == 0) action_val = WDOG_TIMEOUT_POWER_CYCLE; - } else if (strcmp(action, "power_off") == 0) { + else if (strcmp(inval, "power_off") == 0) action_val = WDOG_TIMEOUT_POWER_DOWN; - } else { - action_val = WDOG_TIMEOUT_RESET; - printk(KERN_INFO PFX "Unknown action '%s', defaulting to" - " reset\n", action); - } + else + return -EINVAL; + strcpy(action, inval); + return 0; +} + +static int preaction_op(const char *inval, char *outval) +{ + if (outval) + strcpy(outval, preaction); - if (strcmp(preaction, "pre_none") == 0) { + if (!inval) + return 0; + + if (strcmp(inval, "pre_none") == 0) preaction_val = WDOG_PRETIMEOUT_NONE; - } else if (strcmp(preaction, "pre_smi") == 0) { + else if (strcmp(inval, "pre_smi") == 0) preaction_val = WDOG_PRETIMEOUT_SMI; #ifdef HAVE_NMI_HANDLER - } else if (strcmp(preaction, "pre_nmi") == 0) { + else if (strcmp(inval, "pre_nmi") == 0) preaction_val = WDOG_PRETIMEOUT_NMI; #endif - } else if (strcmp(preaction, "pre_int") == 0) { + else if (strcmp(inval, "pre_int") == 0) preaction_val = WDOG_PRETIMEOUT_MSG_INT; - } else { - preaction_val = WDOG_PRETIMEOUT_NONE; - printk(KERN_INFO PFX "Unknown preaction '%s', defaulting to" - " none\n", preaction); - } + else + return -EINVAL; + strcpy(preaction, inval); + return 0; +} + +static int preop_op(const char *inval, char *outval) +{ + if (outval) + strcpy(outval, preop); - if (strcmp(preop, "preop_none") == 0) { + if (!inval) + return 0; + + if (strcmp(inval, "preop_none") == 0) preop_val = WDOG_PREOP_NONE; - } else if (strcmp(preop, "preop_panic") == 0) { + else if (strcmp(inval, "preop_panic") == 0) preop_val = WDOG_PREOP_PANIC; - } else if (strcmp(preop, "preop_give_data") == 0) { + else if (strcmp(inval, "preop_give_data") == 0) preop_val = WDOG_PREOP_GIVE_DATA; - } else { - preop_val = WDOG_PREOP_NONE; - printk(KERN_INFO PFX "Unknown preop '%s', defaulting to" - " none\n", preop); - } + else + return -EINVAL; + strcpy(preop, inval); + return 0; +} +static void check_parms(void) +{ #ifdef HAVE_NMI_HANDLER + int do_nmi = 0; + int rv; + if (preaction_val == WDOG_PRETIMEOUT_NMI) { + do_nmi = 1; if (preop_val == WDOG_PREOP_GIVE_DATA) { printk(KERN_WARNING PFX "Pretimeout op is to give data" " but NMI pretimeout is enabled, setting" " pretimeout op to none\n"); - preop_val = WDOG_PREOP_NONE; + preop_op("preop_none", NULL); + do_nmi = 0; } #ifdef CONFIG_X86_LOCAL_APIC if (nmi_watchdog == NMI_IO_APIC) { @@ -983,18 +1099,48 @@ static int __init ipmi_wdog_init(void) " Disabling IPMI nmi pretimeout.\n", nmi_watchdog); preaction_val = WDOG_PRETIMEOUT_NONE; - } else { + do_nmi = 0; + } #endif + } + if (do_nmi && !nmi_handler_registered) { rv = request_nmi(&ipmi_nmi_handler); if (rv) { - printk(KERN_WARNING PFX "Can't register nmi handler\n"); - return rv; - } -#ifdef CONFIG_X86_LOCAL_APIC - } -#endif + printk(KERN_WARNING PFX + "Can't register nmi handler\n"); + return; + } else + nmi_handler_registered = 1; + } else if (!do_nmi && nmi_handler_registered) { + release_nmi(&ipmi_nmi_handler); + nmi_handler_registered = 0; } #endif +} + +static int __init ipmi_wdog_init(void) +{ + int rv; + + if (action_op(action, NULL)) { + action_op("reset", NULL); + printk(KERN_INFO PFX "Unknown action '%s', defaulting to" + " reset\n", action); + } + + if (preaction_op(preaction, NULL)) { + preaction_op("pre_none", NULL); + printk(KERN_INFO PFX "Unknown preaction '%s', defaulting to" + " none\n", preaction); + } + + if (preop_op(preop, NULL)) { + preop_op("preop_none", NULL); + printk(KERN_INFO PFX "Unknown preop '%s', defaulting to" + " none\n", preop); + } + + check_parms(); rv = ipmi_smi_watcher_register(&smi_watcher); if (rv) { @@ -1021,7 +1167,7 @@ static __exit void ipmi_unregister_watchdog(void) down_write(®ister_sem); #ifdef HAVE_NMI_HANDLER - if (preaction_val == WDOG_PRETIMEOUT_NMI) + if (nmi_handler_registered) release_nmi(&ipmi_nmi_handler); #endif -- cgit v1.2.3 From 21d6c542153c680f689a9badf5534bf27704350b Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 7 Nov 2005 00:59:57 -0800 Subject: [PATCH] ipmi: poweroff cleanups Make module_param and MODULE_PARAM_DESC agree on poweroff_powercycle name. There was an extraneous ifdef in the IPMI poweroff code that prevented it from working if PROC_FS was disabled. Signed-off-by: Matt Domsch Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_poweroff.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index f66947722e1..e053eade036 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c @@ -56,7 +56,7 @@ static int poweroff_powercycle; /* parameter definition to allow user to flag power cycle */ module_param(poweroff_powercycle, int, 0644); -MODULE_PARM_DESC(poweroff_powercycles, " Set to non-zero to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down."); +MODULE_PARM_DESC(poweroff_powercycle, " Set to non-zero to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down."); /* Stuff from the get device id command. */ static unsigned int mfg_id; @@ -611,9 +611,7 @@ static int ipmi_poweroff_init (void) } #endif -#ifdef CONFIG_PROC_FS rv = ipmi_smi_watcher_register(&smi_watcher); -#endif if (rv) { unregister_sysctl_table(ipmi_table_header); printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv); -- cgit v1.2.3 From d5a2b89a4943b423b5b0a07783fee4e08424b0b2 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 7 Nov 2005 00:59:58 -0800 Subject: [PATCH] ipmi: more dell fixes Make SMIC driver ignore EVT_AVAIL and SMS_ATN bits in flags register, as they're used by systems management interrupts, not the host OS. Make the OEM0 Data Available handler work for pre-IPMI 1.5 systems from Dell too. Without these two fixes, PowerEdge 2650 and other similar systems with SMIC may hang a process (modprobe or anything using /dev/ipmi0). Signed-off-by: Matt Domsch Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_si_intf.c | 23 ++++++++++++++++------- drivers/char/ipmi/ipmi_smic_sm.c | 9 +++++++-- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 204e2e987e9..df7dbbff57a 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -2052,6 +2052,9 @@ static int oem_data_avail_to_receive_msg_avail(struct smi_info *smi_info) * IPMI Version = 0x51 IPMI 1.5 * Manufacturer ID = A2 02 00 Dell IANA * + * Additionally, PowerEdge systems with IPMI < 1.5 may also assert + * OEM0_DATA_AVAIL and needs to be treated as RECEIVE_MSG_AVAIL. + * */ #define DELL_POWEREDGE_8G_BMC_DEVICE_ID 0x20 #define DELL_POWEREDGE_8G_BMC_DEVICE_REV 0x80 @@ -2061,13 +2064,19 @@ static void setup_dell_poweredge_oem_data_handler(struct smi_info *smi_info) { struct ipmi_device_id *id = &smi_info->device_id; const char mfr[3]=DELL_IANA_MFR_ID; - if (! memcmp(mfr, id->manufacturer_id, sizeof(mfr)) - && (id->device_id == DELL_POWEREDGE_8G_BMC_DEVICE_ID) - && (id->device_revision == DELL_POWEREDGE_8G_BMC_DEVICE_REV) - && (id->ipmi_version == DELL_POWEREDGE_8G_BMC_IPMI_VERSION)) - { - smi_info->oem_data_avail_handler = - oem_data_avail_to_receive_msg_avail; + if (! memcmp(mfr, id->manufacturer_id, sizeof(mfr))) { + if (id->device_id == DELL_POWEREDGE_8G_BMC_DEVICE_ID && + id->device_revision == DELL_POWEREDGE_8G_BMC_DEVICE_REV && + id->ipmi_version == DELL_POWEREDGE_8G_BMC_IPMI_VERSION) { + smi_info->oem_data_avail_handler = + oem_data_avail_to_receive_msg_avail; + } + else if (ipmi_version_major(id) < 1 || + (ipmi_version_major(id) == 1 && + ipmi_version_minor(id) < 5)) { + smi_info->oem_data_avail_handler = + oem_data_avail_to_receive_msg_avail; + } } } diff --git a/drivers/char/ipmi/ipmi_smic_sm.c b/drivers/char/ipmi/ipmi_smic_sm.c index f17043da9dd..39d7e5ef1a2 100644 --- a/drivers/char/ipmi/ipmi_smic_sm.c +++ b/drivers/char/ipmi/ipmi_smic_sm.c @@ -85,6 +85,12 @@ enum smic_states { /* SMIC Flags Register Bits */ #define SMIC_RX_DATA_READY 0x80 #define SMIC_TX_DATA_READY 0x40 +/* + * SMIC_SMI and SMIC_EVM_DATA_AVAIL are only used by + * a few systems, and then only by Systems Management + * Interrupts, not by the OS. Always ignore these bits. + * + */ #define SMIC_SMI 0x10 #define SMIC_EVM_DATA_AVAIL 0x08 #define SMIC_SMS_DATA_AVAIL 0x04 @@ -368,8 +374,7 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time) switch (smic->state) { case SMIC_IDLE: /* in IDLE we check for available messages */ - if (flags & (SMIC_SMI | - SMIC_EVM_DATA_AVAIL | SMIC_SMS_DATA_AVAIL)) + if (flags & SMIC_SMS_DATA_AVAIL) { return SI_SM_ATTN; } -- cgit v1.2.3 From ea94027b92dd0d02d238d5984cd9089343c1d6cc Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 7 Nov 2005 00:59:59 -0800 Subject: [PATCH] ipmi: si start transaction hook Some commands, on some system BMCs, don't respond at at all. This is seen on Dell PowerEdge x6xx and x7xx systems with IPMI 1.0 BT controllers when a "Get SDR" command is issued, with a length field of 0x3A, which happens to be the length of about SDR entries. If another length is passed, this command succeeds. This patch adds general infrastructure for receiving commands before they're passed down to the low-level drivers, such that they can be completed immediately, or modified, prior to being sent to ->start_transaction(). Signed-off-by: Matt Domsch Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_si_intf.c | 84 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index df7dbbff57a..2ace62b1d32 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #ifdef CONFIG_HIGH_RES_TIMERS #include @@ -222,6 +223,12 @@ struct smi_info unsigned long incoming_messages; }; +static struct notifier_block *xaction_notifier_list; +static int register_xaction_notifier(struct notifier_block * nb) +{ + return notifier_chain_register(&xaction_notifier_list, nb); +} + static void si_restart_short_timer(struct smi_info *smi_info); static void deliver_recv_msg(struct smi_info *smi_info, @@ -281,6 +288,11 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info) do_gettimeofday(&t); printk("**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec); #endif + err = notifier_call_chain(&xaction_notifier_list, 0, smi_info); + if (err & NOTIFY_STOP_MASK) { + rv = SI_SM_CALL_WITHOUT_DELAY; + goto out; + } err = smi_info->handlers->start_transaction( smi_info->si_sm, smi_info->curr_msg->data, @@ -291,6 +303,7 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info) rv = SI_SM_CALL_WITHOUT_DELAY; } + out: spin_unlock(&(smi_info->msg_lock)); return rv; @@ -2080,6 +2093,71 @@ static void setup_dell_poweredge_oem_data_handler(struct smi_info *smi_info) } } +#define CANNOT_RETURN_REQUESTED_LENGTH 0xCA +static void return_hosed_msg_badsize(struct smi_info *smi_info) +{ + struct ipmi_smi_msg *msg = smi_info->curr_msg; + + /* Make it a reponse */ + msg->rsp[0] = msg->data[0] | 4; + msg->rsp[1] = msg->data[1]; + msg->rsp[2] = CANNOT_RETURN_REQUESTED_LENGTH; + msg->rsp_size = 3; + smi_info->curr_msg = NULL; + deliver_recv_msg(smi_info, msg); +} + +/* + * dell_poweredge_bt_xaction_handler + * @info - smi_info.device_id must be populated + * + * Dell PowerEdge servers with the BT interface (x6xx and 1750) will + * not respond to a Get SDR command if the length of the data + * requested is exactly 0x3A, which leads to command timeouts and no + * data returned. This intercepts such commands, and causes userspace + * callers to try again with a different-sized buffer, which succeeds. + */ + +#define STORAGE_NETFN 0x0A +#define STORAGE_CMD_GET_SDR 0x23 +static int dell_poweredge_bt_xaction_handler(struct notifier_block *self, + unsigned long unused, + void *in) +{ + struct smi_info *smi_info = in; + unsigned char *data = smi_info->curr_msg->data; + unsigned int size = smi_info->curr_msg->data_size; + if (size >= 8 && + (data[0]>>2) == STORAGE_NETFN && + data[1] == STORAGE_CMD_GET_SDR && + data[7] == 0x3A) { + return_hosed_msg_badsize(smi_info); + return NOTIFY_STOP; + } + return NOTIFY_DONE; +} + +static struct notifier_block dell_poweredge_bt_xaction_notifier = { + .notifier_call = dell_poweredge_bt_xaction_handler, +}; + +/* + * setup_dell_poweredge_bt_xaction_handler + * @info - smi_info.device_id must be filled in already + * + * Fills in smi_info.device_id.start_transaction_pre_hook + * when we know what function to use there. + */ +static void +setup_dell_poweredge_bt_xaction_handler(struct smi_info *smi_info) +{ + struct ipmi_device_id *id = &smi_info->device_id; + const char mfr[3]=DELL_IANA_MFR_ID; + if (! memcmp(mfr, id->manufacturer_id, sizeof(mfr)) && + smi_info->si_type == SI_BT) + register_xaction_notifier(&dell_poweredge_bt_xaction_notifier); +} + /* * setup_oem_data_handler * @info - smi_info.device_id must be filled in already @@ -2093,6 +2171,11 @@ static void setup_oem_data_handler(struct smi_info *smi_info) setup_dell_poweredge_oem_data_handler(smi_info); } +static void setup_xaction_handlers(struct smi_info *smi_info) +{ + setup_dell_poweredge_bt_xaction_handler(smi_info); +} + /* Returns 0 if initialized, or negative on an error. */ static int init_one_smi(int intf_num, struct smi_info **smi) { @@ -2188,6 +2271,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi) goto out_err; setup_oem_data_handler(new_smi); + setup_xaction_handlers(new_smi); /* Try to claim any interrupts. */ new_smi->irq_setup(new_smi); -- cgit v1.2.3 From 21dcd300b15f87ce10df8773d029708f27499aa7 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 7 Nov 2005 01:00:01 -0800 Subject: [PATCH] ipmi: bt restart reset fixes The current BT retry/reset mechanism fails to succeed on a PowerEdge 1650, when the controller is wedged with B2H_ATN asserted at XACTION_START. If this occurs, no further commands will ever succeed unless the state of the controller is first cleared out. Furthermore, the soft reset would only occur if the first command after insmod was the one that timed out, not if a later command timed out. This patch changes the retry/reset mechanism to be as follows: Before retrying a command, clear the state of the BT controller such that the flags represent ready for a new transaction. This increases the chance of success of the restarted transaction. After 2 retries, issue a soft reset and retry one more time before giving up and reporting back a failure. Signed-off-by: Matt Domsch Acked-by: Rocky Craig Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_bt_sm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c index 7c4a195dfc9..58dcdee1cd7 100644 --- a/drivers/char/ipmi/ipmi_bt_sm.c +++ b/drivers/char/ipmi/ipmi_bt_sm.c @@ -333,8 +333,7 @@ static void error_recovery(struct si_sm_data *bt, char *reason) bt->state = BT_STATE_HOSED; if (!bt->nonzero_status) printk(KERN_ERR "IPMI: BT stuck, try power cycle\n"); - else if (bt->seq == FIRST_SEQ + BT_RETRY_LIMIT) { - /* most likely during insmod */ + else if (bt->error_retries <= BT_RETRY_LIMIT + 1) { printk(KERN_DEBUG "IPMI: BT reset (takes 5 secs)\n"); bt->state = BT_STATE_RESET1; } @@ -475,6 +474,7 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) break; case BT_STATE_RESTART: /* don't reset retries! */ + reset_flags(bt); bt->write_data[2] = ++bt->seq; bt->read_count = 0; bt->nonzero_status = 0; -- cgit v1.2.3 From c3e7e7916ec61cf58c88af12f4db17f28cffd83a Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 7 Nov 2005 01:00:02 -0800 Subject: [PATCH] ipmi: kcs error0 delay BMCs can get into ERROR0 state while flashing new firmware, particularly while the BMC is erasing the next flash block, which may take a just under 2 seconds on a Dell PowerEdge 2800 (1.75 seconds typical), during which time the single-threaded firmware may not be able to process new commands. In particular, clearing OBF may not take effect immediately. We want it to delay in ERROR0 after clearing OBF a bit waiting for OBF to actually be clear before proceeding. This introduces a new return value from the LLDD's event loop, SI_SM_CALL_WITH_TICK_DELAY. This means the calling thread/timer should schedule_timeout() at least 1 tick, rather than busy-wait. This is a longer delay than SI_SM_CALL_WITH_DELAY, which is typically a 250us busy-wait. Signed-off-by: Matt Domsch Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_kcs_sm.c | 8 ++++++++ drivers/char/ipmi/ipmi_si_intf.c | 3 ++- drivers/char/ipmi/ipmi_si_sm.h | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c index dc83365ede4..da1554194d3 100644 --- a/drivers/char/ipmi/ipmi_kcs_sm.c +++ b/drivers/char/ipmi/ipmi_kcs_sm.c @@ -41,6 +41,7 @@ #include #include #include +#include #include /* for completion codes */ #include "ipmi_si_sm.h" @@ -99,6 +100,7 @@ enum kcs_states { #define IBF_RETRY_TIMEOUT 1000000 #define OBF_RETRY_TIMEOUT 1000000 #define MAX_ERROR_RETRIES 10 +#define ERROR0_OBF_WAIT_JIFFIES (2*HZ) struct si_sm_data { @@ -115,6 +117,7 @@ struct si_sm_data unsigned int error_retries; long ibf_timeout; long obf_timeout; + unsigned long error0_timeout; }; static unsigned int init_kcs_data(struct si_sm_data *kcs, @@ -187,6 +190,7 @@ static inline void start_error_recovery(struct si_sm_data *kcs, char *reason) printk(KERN_DEBUG "ipmi_kcs_sm: kcs hosed: %s\n", reason); kcs->state = KCS_HOSED; } else { + kcs->error0_timeout = jiffies + ERROR0_OBF_WAIT_JIFFIES; kcs->state = KCS_ERROR0; } } @@ -423,6 +427,10 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time) case KCS_ERROR0: clear_obf(kcs, status); + status = read_status(kcs); + if (GET_STATUS_OBF(status)) /* controller isn't responding */ + if (time_before(jiffies, kcs->error0_timeout)) + return SI_SM_CALL_WITH_TICK_DELAY; write_cmd(kcs, KCS_GET_STATUS_ABORT); kcs->state = KCS_ERROR1; break; diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 2ace62b1d32..d514df7c728 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -1932,7 +1932,8 @@ static int try_get_dev_id(struct smi_info *smi_info) smi_result = smi_info->handlers->event(smi_info->si_sm, 0); for (;;) { - if (smi_result == SI_SM_CALL_WITH_DELAY) { + if (smi_result == SI_SM_CALL_WITH_DELAY || + smi_result == SI_SM_CALL_WITH_TICK_DELAY) { schedule_timeout_uninterruptible(1); smi_result = smi_info->handlers->event( smi_info->si_sm, 100); diff --git a/drivers/char/ipmi/ipmi_si_sm.h b/drivers/char/ipmi/ipmi_si_sm.h index 62791dd4298..bf3d4962d6a 100644 --- a/drivers/char/ipmi/ipmi_si_sm.h +++ b/drivers/char/ipmi/ipmi_si_sm.h @@ -62,6 +62,7 @@ enum si_sm_result { SI_SM_CALL_WITHOUT_DELAY, /* Call the driver again immediately */ SI_SM_CALL_WITH_DELAY, /* Delay some before calling again. */ + SI_SM_CALL_WITH_TICK_DELAY, /* Delay at least 1 tick before calling again. */ SI_SM_TRANSACTION_COMPLETE, /* A transaction is finished. */ SI_SM_IDLE, /* The SM is in idle state. */ SI_SM_HOSED, /* The hardware violated the state machine. */ -- cgit v1.2.3 From a9a2c44ff0a1350f8bfe3a162ecf71b1c9ce5cc2 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 7 Nov 2005 01:00:03 -0800 Subject: [PATCH] ipmi: add timer thread We must poll for responses to commands when interrupts aren't in use. The default poll interval is based on using a kernel timer, which varies with HZ. For character-based interfaces like KCS and SMIC though, that can be way too slow (>15 minutes to flash a new firmware with KCS, >20 seconds to retrieve the sensor list). This creates a low-priority kernel thread to poll more often. If the state machine is idle, so is the kernel thread. But if there's an active command, it polls quite rapidly. This decrease a firmware flash time from 15 minutes to 1.5 minutes, and the sensor list time to 4.5 seconds, on a Dell PowerEdge x8x system. The timer-based polling remains, to ensure some amount of responsiveness even under high user process CPU load. Checking for a stopped timer at rmmod now uses atomics and del_timer_sync() to ensure safe stoppage. Signed-off-by: Matt Domsch Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_si_intf.c | 84 ++++++++++++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 21 deletions(-) diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index d514df7c728..fa3be622ca9 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -126,6 +126,7 @@ struct ipmi_device_id { struct smi_info { + int intf_num; ipmi_smi_t intf; struct si_sm_data *si_sm; struct si_sm_handlers *handlers; @@ -193,8 +194,7 @@ struct smi_info unsigned long last_timeout_jiffies; /* Used to gracefully stop the timer without race conditions. */ - volatile int stop_operation; - volatile int timer_stopped; + atomic_t stop_operation; /* The driver will disable interrupts when it gets into a situation where it cannot handle messages due to lack of @@ -221,6 +221,9 @@ struct smi_info unsigned long events; unsigned long watchdog_pretimeouts; unsigned long incoming_messages; + + struct completion exiting; + long thread_pid; }; static struct notifier_block *xaction_notifier_list; @@ -779,6 +782,38 @@ static void set_run_to_completion(void *send_info, int i_run_to_completion) spin_unlock_irqrestore(&(smi_info->si_lock), flags); } +static int ipmi_thread(void *data) +{ + struct smi_info *smi_info = data; + unsigned long flags, last=1; + enum si_sm_result smi_result; + + daemonize("kipmi%d", smi_info->intf_num); + allow_signal(SIGKILL); + set_user_nice(current, 19); + while (!atomic_read(&smi_info->stop_operation)) { + schedule_timeout(last); + spin_lock_irqsave(&(smi_info->si_lock), flags); + smi_result=smi_event_handler(smi_info, 0); + spin_unlock_irqrestore(&(smi_info->si_lock), flags); + if (smi_result == SI_SM_CALL_WITHOUT_DELAY) + last = 0; + else if (smi_result == SI_SM_CALL_WITH_DELAY) { + udelay(1); + last = 0; + } + else { + /* System is idle; go to sleep */ + last = 1; + current->state = TASK_INTERRUPTIBLE; + } + } + smi_info->thread_pid = 0; + complete_and_exit(&(smi_info->exiting), 0); + return 0; +} + + static void poll(void *send_info) { struct smi_info *smi_info = send_info; @@ -837,10 +872,8 @@ static void smi_timeout(unsigned long data) struct timeval t; #endif - if (smi_info->stop_operation) { - smi_info->timer_stopped = 1; + if (atomic_read(&smi_info->stop_operation)) return; - } spin_lock_irqsave(&(smi_info->si_lock), flags); #ifdef DEBUG_TIMING @@ -913,7 +946,7 @@ static irqreturn_t si_irq_handler(int irq, void *data, struct pt_regs *regs) smi_info->interrupts++; spin_unlock(&smi_info->count_lock); - if (smi_info->stop_operation) + if (atomic_read(&smi_info->stop_operation)) goto out; #ifdef DEBUG_TIMING @@ -1432,7 +1465,7 @@ static u32 ipmi_acpi_gpe(void *context) smi_info->interrupts++; spin_unlock(&smi_info->count_lock); - if (smi_info->stop_operation) + if (atomic_read(&smi_info->stop_operation)) goto out; #ifdef DEBUG_TIMING @@ -2177,6 +2210,16 @@ static void setup_xaction_handlers(struct smi_info *smi_info) setup_dell_poweredge_bt_xaction_handler(smi_info); } +static inline void wait_for_timer_and_thread(struct smi_info *smi_info) +{ + if (smi_info->thread_pid > 0) { + /* wake the potentially sleeping thread */ + kill_proc(smi_info->thread_pid, SIGKILL, 0); + wait_for_completion(&(smi_info->exiting)); + } + del_timer_sync(&smi_info->si_timer); +} + /* Returns 0 if initialized, or negative on an error. */ static int init_one_smi(int intf_num, struct smi_info **smi) { @@ -2284,8 +2327,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi) new_smi->run_to_completion = 0; new_smi->interrupt_disabled = 0; - new_smi->timer_stopped = 0; - new_smi->stop_operation = 0; + atomic_set(&new_smi->stop_operation, 0); + new_smi->intf_num = intf_num; /* Start clearing the flags before we enable interrupts or the timer to avoid racing with the timer. */ @@ -2303,7 +2346,14 @@ static int init_one_smi(int intf_num, struct smi_info **smi) new_smi->si_timer.function = smi_timeout; new_smi->last_timeout_jiffies = jiffies; new_smi->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; + add_timer(&(new_smi->si_timer)); + if (new_smi->si_type != SI_BT) { + init_completion(&(new_smi->exiting)); + new_smi->thread_pid = kernel_thread(ipmi_thread, new_smi, + CLONE_FS|CLONE_FILES| + CLONE_SIGHAND); + } rv = ipmi_register_smi(&handlers, new_smi, @@ -2345,12 +2395,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi) return 0; out_err_stop_timer: - new_smi->stop_operation = 1; - - /* Wait for the timer to stop. This avoids problems with race - conditions removing the timer here. */ - while (!new_smi->timer_stopped) - schedule_timeout_uninterruptible(1); + atomic_inc(&new_smi->stop_operation); + wait_for_timer_and_thread(new_smi); out_err: if (new_smi->intf) @@ -2456,8 +2502,7 @@ static void __exit cleanup_one_si(struct smi_info *to_clean) spin_lock_irqsave(&(to_clean->si_lock), flags); spin_lock(&(to_clean->msg_lock)); - to_clean->stop_operation = 1; - + atomic_inc(&to_clean->stop_operation); to_clean->irq_cleanup(to_clean); spin_unlock(&(to_clean->msg_lock)); @@ -2468,10 +2513,7 @@ static void __exit cleanup_one_si(struct smi_info *to_clean) interrupt. */ synchronize_sched(); - /* Wait for the timer to stop. This avoids problems with race - conditions removing the timer here. */ - while (!to_clean->timer_stopped) - schedule_timeout_uninterruptible(1); + wait_for_timer_and_thread(to_clean); /* Interrupts and timeouts are stopped, now make sure the interface is in a clean state. */ -- cgit v1.2.3 From e9a705a0a0ed99833cfef40d509f63a052638f00 Mon Sep 17 00:00:00 2001 From: Matt Domsch Date: Mon, 7 Nov 2005 01:00:04 -0800 Subject: [PATCH] ipmi: use kthread API Convert ipmi driver thread to kthread API, only sleep when interface is idle. Signed-off-by: Matt Domsch Cc: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_si_intf.c | 45 ++++++++++++++-------------------------- 1 file changed, 15 insertions(+), 30 deletions(-) diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index fa3be622ca9..ea89dca3dbb 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #ifdef CONFIG_HIGH_RES_TIMERS #include @@ -222,8 +223,7 @@ struct smi_info unsigned long watchdog_pretimeouts; unsigned long incoming_messages; - struct completion exiting; - long thread_pid; + struct task_struct *thread; }; static struct notifier_block *xaction_notifier_list; @@ -785,31 +785,22 @@ static void set_run_to_completion(void *send_info, int i_run_to_completion) static int ipmi_thread(void *data) { struct smi_info *smi_info = data; - unsigned long flags, last=1; + unsigned long flags; enum si_sm_result smi_result; - daemonize("kipmi%d", smi_info->intf_num); - allow_signal(SIGKILL); set_user_nice(current, 19); - while (!atomic_read(&smi_info->stop_operation)) { - schedule_timeout(last); + while (!kthread_should_stop()) { spin_lock_irqsave(&(smi_info->si_lock), flags); smi_result=smi_event_handler(smi_info, 0); spin_unlock_irqrestore(&(smi_info->si_lock), flags); - if (smi_result == SI_SM_CALL_WITHOUT_DELAY) - last = 0; - else if (smi_result == SI_SM_CALL_WITH_DELAY) { - udelay(1); - last = 0; - } - else { - /* System is idle; go to sleep */ - last = 1; - current->state = TASK_INTERRUPTIBLE; + if (smi_result == SI_SM_CALL_WITHOUT_DELAY) { + /* do nothing */ } + else if (smi_result == SI_SM_CALL_WITH_DELAY) + udelay(1); + else + schedule_timeout_interruptible(1); } - smi_info->thread_pid = 0; - complete_and_exit(&(smi_info->exiting), 0); return 0; } @@ -2212,11 +2203,8 @@ static void setup_xaction_handlers(struct smi_info *smi_info) static inline void wait_for_timer_and_thread(struct smi_info *smi_info) { - if (smi_info->thread_pid > 0) { - /* wake the potentially sleeping thread */ - kill_proc(smi_info->thread_pid, SIGKILL, 0); - wait_for_completion(&(smi_info->exiting)); - } + if (smi_info->thread != ERR_PTR(-ENOMEM)) + kthread_stop(smi_info->thread); del_timer_sync(&smi_info->si_timer); } @@ -2348,12 +2336,9 @@ static int init_one_smi(int intf_num, struct smi_info **smi) new_smi->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; add_timer(&(new_smi->si_timer)); - if (new_smi->si_type != SI_BT) { - init_completion(&(new_smi->exiting)); - new_smi->thread_pid = kernel_thread(ipmi_thread, new_smi, - CLONE_FS|CLONE_FILES| - CLONE_SIGHAND); - } + if (new_smi->si_type != SI_BT) + new_smi->thread = kthread_run(ipmi_thread, new_smi, + "kipmi%d", new_smi->intf_num); rv = ipmi_register_smi(&handlers, new_smi, -- cgit v1.2.3 From e61fb5b65150ace7192d1f0ce840fe4cd6285e73 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 7 Nov 2005 01:00:05 -0800 Subject: [PATCH] ipmi: use rcu lock for using command receivers Use rcu_read_lock for the cmd_rcvrs list, since that was what what intended, anyway. This means that all the users of the cmd_rcvrs_lock are tasks, so the irq disables are no longer required for that lock and it can become a semaphore. Signed-off-by: Corey Minyard Acked-by: "Paul E. McKenney" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_msghandler.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 320d7f035bf..c1d06ba449b 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -209,7 +209,7 @@ struct ipmi_smi /* The list of command receivers that are registered for commands on this interface. */ - spinlock_t cmd_rcvrs_lock; + struct semaphore cmd_rcvrs_lock; struct list_head cmd_rcvrs; /* Events that were queues because no one was there to receive @@ -345,7 +345,6 @@ static void clean_up_interface_data(ipmi_smi_t intf) { int i; struct cmd_rcvr *rcvr, *rcvr2; - unsigned long flags; struct list_head list; free_recv_msg_list(&intf->waiting_msgs); @@ -353,10 +352,10 @@ static void clean_up_interface_data(ipmi_smi_t intf) /* Wholesale remove all the entries from the list in the * interface and wait for RCU to know that none are in use. */ - spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); + down(&intf->cmd_rcvrs_lock); list_add_rcu(&list, &intf->cmd_rcvrs); list_del_rcu(&intf->cmd_rcvrs); - spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); + up(&intf->cmd_rcvrs_lock); synchronize_rcu(); list_for_each_entry_safe(rcvr, rcvr2, &list, link) @@ -812,7 +811,7 @@ int ipmi_destroy_user(ipmi_user_t user) * since other things may be using it till we do * synchronize_rcu()) then free everything in that list. */ - spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); + down(&intf->cmd_rcvrs_lock); list_for_each_safe_rcu(entry1, entry2, &intf->cmd_rcvrs) { rcvr = list_entry(entry1, struct cmd_rcvr, link); if (rcvr->user == user) { @@ -821,7 +820,7 @@ int ipmi_destroy_user(ipmi_user_t user) rcvrs = rcvr; } } - spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); + up(&intf->cmd_rcvrs_lock); synchronize_rcu(); while (rcvrs) { rcvr = rcvrs; @@ -950,7 +949,7 @@ int ipmi_register_for_cmd(ipmi_user_t user, rcvr->netfn = netfn; rcvr->user = user; - spin_lock_irq(&intf->cmd_rcvrs_lock); + down(&intf->cmd_rcvrs_lock); /* Make sure the command/netfn is not already registered. */ entry = find_cmd_rcvr(intf, netfn, cmd); if (entry) { @@ -961,7 +960,7 @@ int ipmi_register_for_cmd(ipmi_user_t user, list_add_rcu(&rcvr->link, &intf->cmd_rcvrs); out_unlock: - spin_unlock_irq(&intf->cmd_rcvrs_lock); + up(&intf->cmd_rcvrs_lock); if (rv) kfree(rcvr); @@ -975,17 +974,17 @@ int ipmi_unregister_for_cmd(ipmi_user_t user, ipmi_smi_t intf = user->intf; struct cmd_rcvr *rcvr; - spin_lock_irq(&intf->cmd_rcvrs_lock); + down(&intf->cmd_rcvrs_lock); /* Make sure the command/netfn is not already registered. */ rcvr = find_cmd_rcvr(intf, netfn, cmd); if ((rcvr) && (rcvr->user == user)) { list_del_rcu(&rcvr->link); - spin_unlock_irq(&intf->cmd_rcvrs_lock); + up(&intf->cmd_rcvrs_lock); synchronize_rcu(); kfree(rcvr); return 0; } else { - spin_unlock_irq(&intf->cmd_rcvrs_lock); + up(&intf->cmd_rcvrs_lock); return -ENOENT; } } @@ -1858,7 +1857,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, spin_lock_init(&intf->events_lock); INIT_LIST_HEAD(&intf->waiting_events); intf->waiting_events_count = 0; - spin_lock_init(&intf->cmd_rcvrs_lock); + init_MUTEX(&intf->cmd_rcvrs_lock); INIT_LIST_HEAD(&intf->cmd_rcvrs); init_waitqueue_head(&intf->waitq); @@ -2058,14 +2057,14 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, netfn = msg->rsp[4] >> 2; cmd = msg->rsp[8]; - spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); + rcu_read_lock(); rcvr = find_cmd_rcvr(intf, netfn, cmd); if (rcvr) { user = rcvr->user; kref_get(&user->refcount); } else user = NULL; - spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); + rcu_read_unlock(); if (user == NULL) { /* We didn't find a user, deliver an error response. */ @@ -2238,14 +2237,14 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf, netfn = msg->rsp[6] >> 2; cmd = msg->rsp[10]; - spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); + rcu_read_lock(); rcvr = find_cmd_rcvr(intf, netfn, cmd); if (rcvr) { user = rcvr->user; kref_get(&user->refcount); } else user = NULL; - spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); + rcu_read_unlock(); if (user == NULL) { /* We didn't find a user, just give up. */ -- cgit v1.2.3 From b385676b355549afc9a7507ce09c7df47f166521 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 7 Nov 2005 01:00:05 -0800 Subject: [PATCH] ipmi: fix watchdog timeout panic handling If a panic came from the IPMI watchdog pretimeout and that was reported via an NMI, it would also be reported via the standard IPMI flags, which would get picked up when reporting panic events and cause another panic. This adds an atomic to avoid calling panic twice. Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_watchdog.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 405697a9f4d..1f3159eb1ed 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -49,6 +49,7 @@ #include #include #include +#include #ifdef CONFIG_X86_LOCAL_APIC #include #endif @@ -295,6 +296,8 @@ static int ipmi_start_timer_on_heartbeat = 0; static unsigned char ipmi_version_major; static unsigned char ipmi_version_minor; +/* If a pretimeout occurs, this is used to allow only one panic to happen. */ +static atomic_t preop_panic_excl = ATOMIC_INIT(-1); static int ipmi_heartbeat(void); static void panic_halt_ipmi_heartbeat(void); @@ -837,9 +840,10 @@ static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg, static void ipmi_wdog_pretimeout_handler(void *handler_data) { if (preaction_val != WDOG_PRETIMEOUT_NONE) { - if (preop_val == WDOG_PREOP_PANIC) - panic("Watchdog pre-timeout"); - else if (preop_val == WDOG_PREOP_GIVE_DATA) { + if (preop_val == WDOG_PREOP_PANIC) { + if (atomic_inc_and_test(&preop_panic_excl)) + panic("Watchdog pre-timeout"); + } else if (preop_val == WDOG_PREOP_GIVE_DATA) { spin_lock(&ipmi_read_lock); data_to_read = 1; wake_up_interruptible(&read_q); @@ -913,7 +917,8 @@ ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled) an error and not work unless we re-enable the timer. So do so. */ pretimeout_since_last_heartbeat = 1; - panic(PFX "pre-timeout"); + if (atomic_inc_and_test(&preop_panic_excl)) + panic(PFX "pre-timeout"); } return NOTIFY_DONE; -- cgit v1.2.3 From 66ff2d0691e00e1e7bfdf398a970310c9a0fe671 Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Mon, 7 Nov 2005 01:00:07 -0800 Subject: [PATCH] Kprobes: rearrange preempt_disable/enable() calls The following set of patches are aimed at improving kprobes scalability. We currently serialize kprobe registration, unregistration and handler execution using a single spinlock - kprobe_lock. With these changes, kprobe handlers can run without any locks held. It also allows for simultaneous kprobe handler executions on different processors as we now track kprobe execution on a per processor basis. It is now necessary that the handlers be re-entrant since handlers can run concurrently on multiple processors. All changes have been tested on i386, ia64, ppc64 and x86_64, while sparc64 has been compile tested only. The patches can be viewed as 3 logical chunks: patch 1: Reorder preempt_(dis/en)able calls patches 2-7: Introduce per_cpu data areas to track kprobe execution patches 8-9: Use RCU to synchronize kprobe (un)registration and handler execution. Thanks to Maneesh Soni, James Keniston and Anil Keshavamurthy for their review and suggestions. Thanks again to Anil, Hien Nguyen and Kevin Stafford for testing the patches. This patch: Reorder preempt_disable/enable() calls in arch kprobes files in preparation to introduce locking changes. No functional changes introduced by this patch. Signed-off-by: Ananth N Mavinakayahanalli Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/kprobes.c | 35 ++++++++++++++++++----------------- arch/ia64/kernel/kprobes.c | 22 ++++++++++++++-------- arch/ppc64/kernel/kprobes.c | 11 ++++++----- arch/sparc64/kernel/kprobes.c | 25 +++++++++++++------------ arch/x86_64/kernel/kprobes.c | 28 ++++++++++++++-------------- 5 files changed, 65 insertions(+), 56 deletions(-) diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index 6345b430b10..fd35039859e 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c @@ -158,8 +158,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) kprobe_opcode_t *addr = NULL; unsigned long *lp; - /* We're in an interrupt, but this is clear and BUG()-safe. */ - preempt_disable(); /* Check if the application is using LDT entry for its code segment and * calculate the address by reading the base address from the LDT entry. */ @@ -232,6 +230,11 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) goto no_kprobe; } + /* + * This preempt_disable() matches the preempt_enable_no_resched() + * in post_kprobe_handler() + */ + preempt_disable(); kprobe_status = KPROBE_HIT_ACTIVE; set_current_kprobe(p, regs); @@ -245,7 +248,6 @@ ss_probe: return 1; no_kprobe: - preempt_enable_no_resched(); return ret; } @@ -313,11 +315,11 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) unlock_kprobes(); preempt_enable_no_resched(); - /* - * By returning a non-zero value, we are telling - * kprobe_handler() that we have handled unlocking - * and re-enabling preemption. - */ + /* + * By returning a non-zero value, we are telling + * kprobe_handler() that we have handled unlocking + * and re-enabling preemption + */ return 1; } @@ -453,29 +455,29 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *data) { struct die_args *args = (struct die_args *)data; + int ret = NOTIFY_DONE; + + preempt_disable(); switch (val) { case DIE_INT3: if (kprobe_handler(args->regs)) - return NOTIFY_STOP; + ret = NOTIFY_STOP; break; case DIE_DEBUG: if (post_kprobe_handler(args->regs)) - return NOTIFY_STOP; + ret = NOTIFY_STOP; break; case DIE_GPF: - if (kprobe_running() && - kprobe_fault_handler(args->regs, args->trapnr)) - return NOTIFY_STOP; - break; case DIE_PAGE_FAULT: if (kprobe_running() && kprobe_fault_handler(args->regs, args->trapnr)) - return NOTIFY_STOP; + ret = NOTIFY_STOP; break; default: break; } - return NOTIFY_DONE; + preempt_enable(); + return ret; } int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) @@ -502,7 +504,6 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) void __kprobes jprobe_return(void) { - preempt_enable_no_resched(); asm volatile (" xchgl %%ebx,%%esp \n" " int3 \n" " .globl jprobe_return_end \n" diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 471086b808a..1e80ec80dd2 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c @@ -395,7 +395,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) /* * By returning a non-zero value, we are telling * kprobe_handler() that we have handled unlocking - * and re-enabling preemption. + * and re-enabling preemption */ return 1; } @@ -607,8 +607,6 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) struct pt_regs *regs = args->regs; kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs); - preempt_disable(); - /* Handle recursion cases */ if (kprobe_running()) { p = get_kprobe(addr); @@ -665,6 +663,11 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) goto no_kprobe; } + /* + * This preempt_disable() matches the preempt_enable_no_resched() + * in post_kprobes_handler() + */ + preempt_disable(); kprobe_status = KPROBE_HIT_ACTIVE; set_current_kprobe(p); @@ -682,7 +685,6 @@ ss_probe: return 1; no_kprobe: - preempt_enable_no_resched(); return ret; } @@ -733,22 +735,26 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *data) { struct die_args *args = (struct die_args *)data; + int ret = NOTIFY_DONE; + + preempt_disable(); switch(val) { case DIE_BREAK: if (pre_kprobes_handler(args)) - return NOTIFY_STOP; + ret = NOTIFY_STOP; break; case DIE_SS: if (post_kprobes_handler(args->regs)) - return NOTIFY_STOP; + ret = NOTIFY_STOP; break; case DIE_PAGE_FAULT: if (kprobes_fault_handler(args->regs, args->trapnr)) - return NOTIFY_STOP; + ret = NOTIFY_STOP; default: break; } - return NOTIFY_DONE; + preempt_enable(); + return ret; } int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c index ed876a5178a..6071ee99f5c 100644 --- a/arch/ppc64/kernel/kprobes.c +++ b/arch/ppc64/kernel/kprobes.c @@ -209,6 +209,11 @@ static inline int kprobe_handler(struct pt_regs *regs) goto no_kprobe; } + /* + * This preempt_disable() matches the preempt_enable_no_resched() + * in post_kprobe_handler(). + */ + preempt_disable(); kprobe_status = KPROBE_HIT_ACTIVE; current_kprobe = p; kprobe_saved_msr = regs->msr; @@ -219,11 +224,6 @@ static inline int kprobe_handler(struct pt_regs *regs) ss_probe: prepare_singlestep(p, regs); kprobe_status = KPROBE_HIT_SS; - /* - * This preempt_disable() matches the preempt_enable_no_resched() - * in post_kprobe_handler(). - */ - preempt_disable(); return 1; no_kprobe: @@ -293,6 +293,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) regs->nip = orig_ret_address; unlock_kprobes(); + preempt_enable_no_resched(); /* * By returning a non-zero value, we are telling diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c index 0d66d07c8c6..755a0d7d887 100644 --- a/arch/sparc64/kernel/kprobes.c +++ b/arch/sparc64/kernel/kprobes.c @@ -118,8 +118,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) void *addr = (void *) regs->tpc; int ret = 0; - preempt_disable(); - if (kprobe_running()) { /* We *are* holding lock here, so this is safe. * Disarm the probe we just hit, and ignore it. @@ -171,6 +169,11 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) goto no_kprobe; } + /* + * This preempt_disable() matches the preempt_enable_no_resched() + * in post_kprobes_handler() + */ + preempt_disable(); set_current_kprobe(p, regs); kprobe_status = KPROBE_HIT_ACTIVE; if (p->pre_handler && p->pre_handler(p, regs)) @@ -182,7 +185,6 @@ ss_probe: return 1; no_kprobe: - preempt_enable_no_resched(); return ret; } @@ -322,29 +324,29 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *data) { struct die_args *args = (struct die_args *)data; + int ret = NOTIFY_DONE; + + preempt_disable(); switch (val) { case DIE_DEBUG: if (kprobe_handler(args->regs)) - return NOTIFY_STOP; + ret = NOTIFY_STOP; break; case DIE_DEBUG_2: if (post_kprobe_handler(args->regs)) - return NOTIFY_STOP; + ret = NOTIFY_STOP; break; case DIE_GPF: - if (kprobe_running() && - kprobe_fault_handler(args->regs, args->trapnr)) - return NOTIFY_STOP; - break; case DIE_PAGE_FAULT: if (kprobe_running() && kprobe_fault_handler(args->regs, args->trapnr)) - return NOTIFY_STOP; + ret = NOTIFY_STOP; break; default: break; } - return NOTIFY_DONE; + preempt_enable(); + return ret; } asmlinkage void __kprobes kprobe_trap(unsigned long trap_level, @@ -396,7 +398,6 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) void __kprobes jprobe_return(void) { - preempt_enable_no_resched(); __asm__ __volatile__( ".globl jprobe_return_trap_instruction\n" "jprobe_return_trap_instruction:\n\t" diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c index 76a28b007be..ebfa2c9241c 100644 --- a/arch/x86_64/kernel/kprobes.c +++ b/arch/x86_64/kernel/kprobes.c @@ -302,9 +302,6 @@ int __kprobes kprobe_handler(struct pt_regs *regs) int ret = 0; kprobe_opcode_t *addr = (kprobe_opcode_t *)(regs->rip - sizeof(kprobe_opcode_t)); - /* We're in an interrupt, but this is clear and BUG()-safe. */ - preempt_disable(); - /* Check we're not actually recursing */ if (kprobe_running()) { /* We *are* holding lock here, so this is safe. @@ -372,6 +369,11 @@ int __kprobes kprobe_handler(struct pt_regs *regs) goto no_kprobe; } + /* + * This preempt_disable() matches the preempt_enable_no_resched() + * in post_kprobe_handler() + */ + preempt_disable(); kprobe_status = KPROBE_HIT_ACTIVE; set_current_kprobe(p, regs); @@ -385,7 +387,6 @@ ss_probe: return 1; no_kprobe: - preempt_enable_no_resched(); return ret; } @@ -456,7 +457,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) /* * By returning a non-zero value, we are telling * kprobe_handler() that we have handled unlocking - * and re-enabling preemption. + * and re-enabling preemption */ return 1; } @@ -599,29 +600,29 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *data) { struct die_args *args = (struct die_args *)data; + int ret = NOTIFY_DONE; + + preempt_disable(); switch (val) { case DIE_INT3: if (kprobe_handler(args->regs)) - return NOTIFY_STOP; + ret = NOTIFY_STOP; break; case DIE_DEBUG: if (post_kprobe_handler(args->regs)) - return NOTIFY_STOP; + ret = NOTIFY_STOP; break; case DIE_GPF: - if (kprobe_running() && - kprobe_fault_handler(args->regs, args->trapnr)) - return NOTIFY_STOP; - break; case DIE_PAGE_FAULT: if (kprobe_running() && kprobe_fault_handler(args->regs, args->trapnr)) - return NOTIFY_STOP; + ret = NOTIFY_STOP; break; default: break; } - return NOTIFY_DONE; + preempt_enable(); + return ret; } int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) @@ -647,7 +648,6 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) void __kprobes jprobe_return(void) { - preempt_enable_no_resched(); asm volatile (" xchg %%rbx,%%rsp \n" " int3 \n" " .globl jprobe_return_end \n" -- cgit v1.2.3 From e65845235c8120be63001fc1a4ac00c819194bbe Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Mon, 7 Nov 2005 01:00:07 -0800 Subject: [PATCH] Kprobes: Track kprobe on a per_cpu basis - base changes Changes to the base kprobe infrastructure to track kprobe execution on a per-cpu basis. Signed-off-by: Ananth N Mavinakayanahalli Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/kprobes.h | 31 ++++++++++++++++++++++--------- kernel/kprobes.c | 43 ++++++++++++++++++++++++++++--------------- 2 files changed, 50 insertions(+), 24 deletions(-) diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index e30afdca791..6720305a31e 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -106,6 +107,9 @@ struct jprobe { kprobe_opcode_t *entry; /* probe handling code to jump to */ }; +DECLARE_PER_CPU(struct kprobe *, current_kprobe); +DECLARE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); + #ifdef ARCH_SUPPORTS_KRETPROBES extern void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs); #else /* ARCH_SUPPORTS_KRETPROBES */ @@ -146,13 +150,6 @@ struct kretprobe_instance { void lock_kprobes(void); void unlock_kprobes(void); -/* kprobe running now on this CPU? */ -static inline int kprobe_running(void) -{ - extern unsigned int kprobe_cpu; - return kprobe_cpu == smp_processor_id(); -} - extern int arch_prepare_kprobe(struct kprobe *p); extern void arch_copy_kprobe(struct kprobe *p); extern void arch_arm_kprobe(struct kprobe *p); @@ -167,6 +164,22 @@ extern void free_insn_slot(kprobe_opcode_t *slot); struct kprobe *get_kprobe(void *addr); struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk); +/* kprobe_running() will just return the current_kprobe on this CPU */ +static inline struct kprobe *kprobe_running(void) +{ + return (__get_cpu_var(current_kprobe)); +} + +static inline void reset_current_kprobe(void) +{ + __get_cpu_var(current_kprobe) = NULL; +} + +static inline struct kprobe_ctlblk *get_kprobe_ctlblk(void) +{ + return (&__get_cpu_var(kprobe_ctlblk)); +} + int register_kprobe(struct kprobe *p); void unregister_kprobe(struct kprobe *p); int setjmp_pre_handler(struct kprobe *, struct pt_regs *); @@ -183,9 +196,9 @@ void add_rp_inst(struct kretprobe_instance *ri); void kprobe_flush_task(struct task_struct *tk); void recycle_rp_inst(struct kretprobe_instance *ri); #else /* CONFIG_KPROBES */ -static inline int kprobe_running(void) +static inline struct kprobe *kprobe_running(void) { - return 0; + return NULL; } static inline int register_kprobe(struct kprobe *p) { diff --git a/kernel/kprobes.c b/kernel/kprobes.c index ce4915dd683..6da8f9b33d1 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -51,7 +51,7 @@ static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE]; unsigned int kprobe_cpu = NR_CPUS; static DEFINE_SPINLOCK(kprobe_lock); -static struct kprobe *curr_kprobe; +static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL; /* * kprobe->ainsn.insn points to the copy of the instruction to be @@ -188,6 +188,17 @@ void __kprobes unlock_kprobes(void) local_irq_restore(flags); } +/* We have preemption disabled.. so it is safe to use __ versions */ +static inline void set_kprobe_instance(struct kprobe *kp) +{ + __get_cpu_var(kprobe_instance) = kp; +} + +static inline void reset_kprobe_instance(void) +{ + __get_cpu_var(kprobe_instance) = NULL; +} + /* You have to be holding the kprobe_lock */ struct kprobe __kprobes *get_kprobe(void *addr) { @@ -213,11 +224,11 @@ static int __kprobes aggr_pre_handler(struct kprobe *p, struct pt_regs *regs) list_for_each_entry(kp, &p->list, list) { if (kp->pre_handler) { - curr_kprobe = kp; + set_kprobe_instance(kp); if (kp->pre_handler(kp, regs)) return 1; } - curr_kprobe = NULL; + reset_kprobe_instance(); } return 0; } @@ -229,9 +240,9 @@ static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs, list_for_each_entry(kp, &p->list, list) { if (kp->post_handler) { - curr_kprobe = kp; + set_kprobe_instance(kp); kp->post_handler(kp, regs, flags); - curr_kprobe = NULL; + reset_kprobe_instance(); } } return; @@ -240,12 +251,14 @@ static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs, static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs, int trapnr) { + struct kprobe *cur = __get_cpu_var(kprobe_instance); + /* * if we faulted "during" the execution of a user specified * probe handler, invoke just that probe's fault handler */ - if (curr_kprobe && curr_kprobe->fault_handler) { - if (curr_kprobe->fault_handler(curr_kprobe, regs, trapnr)) + if (cur && cur->fault_handler) { + if (cur->fault_handler(cur, regs, trapnr)) return 1; } return 0; @@ -253,15 +266,15 @@ static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs, static int __kprobes aggr_break_handler(struct kprobe *p, struct pt_regs *regs) { - struct kprobe *kp = curr_kprobe; - if (curr_kprobe && kp->break_handler) { - if (kp->break_handler(kp, regs)) { - curr_kprobe = NULL; - return 1; - } + struct kprobe *cur = __get_cpu_var(kprobe_instance); + int ret = 0; + + if (cur && cur->break_handler) { + if (cur->break_handler(cur, regs)) + ret = 1; } - curr_kprobe = NULL; - return 0; + reset_kprobe_instance(); + return ret; } struct kretprobe_instance __kprobes *get_free_rp_inst(struct kretprobe *rp) -- cgit v1.2.3 From 9a0e3a86837ac7542e601c18346102c9d9e65fa5 Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Mon, 7 Nov 2005 01:00:08 -0800 Subject: [PATCH] Kprobes: Track kprobe on a per_cpu basis - i386 changes I386 changes to track kprobe execution on a per-cpu basis. We now track the kprobe state machine independently on each cpu, using an arch specific kprobe control block. Signed-off-by: Ananth N Mavinakayanahalli Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/kprobes.c | 126 +++++++++++++++++++++++++-------------------- include/asm-i386/kprobes.h | 17 ++++++ 2 files changed, 86 insertions(+), 57 deletions(-) diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index fd35039859e..99565a66915 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c @@ -37,16 +37,11 @@ #include #include -static struct kprobe *current_kprobe; -static unsigned long kprobe_status, kprobe_old_eflags, kprobe_saved_eflags; -static struct kprobe *kprobe_prev; -static unsigned long kprobe_status_prev, kprobe_old_eflags_prev, kprobe_saved_eflags_prev; -static struct pt_regs jprobe_saved_regs; -static long *jprobe_saved_esp; -/* copy of the kernel stack at the probe fire time */ -static kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE]; void jprobe_return_end(void); +DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; +DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); + /* * returns non-zero if opcode modifies the interrupt flag. */ @@ -91,29 +86,30 @@ void __kprobes arch_remove_kprobe(struct kprobe *p) { } -static inline void save_previous_kprobe(void) +static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb) { - kprobe_prev = current_kprobe; - kprobe_status_prev = kprobe_status; - kprobe_old_eflags_prev = kprobe_old_eflags; - kprobe_saved_eflags_prev = kprobe_saved_eflags; + kcb->prev_kprobe.kp = kprobe_running(); + kcb->prev_kprobe.status = kcb->kprobe_status; + kcb->prev_kprobe.old_eflags = kcb->kprobe_old_eflags; + kcb->prev_kprobe.saved_eflags = kcb->kprobe_saved_eflags; } -static inline void restore_previous_kprobe(void) +static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb) { - current_kprobe = kprobe_prev; - kprobe_status = kprobe_status_prev; - kprobe_old_eflags = kprobe_old_eflags_prev; - kprobe_saved_eflags = kprobe_saved_eflags_prev; + __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; + kcb->kprobe_status = kcb->prev_kprobe.status; + kcb->kprobe_old_eflags = kcb->prev_kprobe.old_eflags; + kcb->kprobe_saved_eflags = kcb->prev_kprobe.saved_eflags; } -static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs) +static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs, + struct kprobe_ctlblk *kcb) { - current_kprobe = p; - kprobe_saved_eflags = kprobe_old_eflags + __get_cpu_var(current_kprobe) = p; + kcb->kprobe_saved_eflags = kcb->kprobe_old_eflags = (regs->eflags & (TF_MASK | IF_MASK)); if (is_IF_modifier(p->opcode)) - kprobe_saved_eflags &= ~IF_MASK; + kcb->kprobe_saved_eflags &= ~IF_MASK; } static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) @@ -157,6 +153,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) int ret = 0; kprobe_opcode_t *addr = NULL; unsigned long *lp; + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); /* Check if the application is using LDT entry for its code segment and * calculate the address by reading the base address from the LDT entry. @@ -175,10 +172,10 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) Disarm the probe we just hit, and ignore it. */ p = get_kprobe(addr); if (p) { - if (kprobe_status == KPROBE_HIT_SS && + if (kcb->kprobe_status == KPROBE_HIT_SS && *p->ainsn.insn == BREAKPOINT_INSTRUCTION) { regs->eflags &= ~TF_MASK; - regs->eflags |= kprobe_saved_eflags; + regs->eflags |= kcb->kprobe_saved_eflags; unlock_kprobes(); goto no_kprobe; } @@ -188,14 +185,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) * just single step on the instruction of the new probe * without calling any user handlers. */ - save_previous_kprobe(); - set_current_kprobe(p, regs); + save_previous_kprobe(kcb); + set_current_kprobe(p, regs, kcb); p->nmissed++; prepare_singlestep(p, regs); - kprobe_status = KPROBE_REENTER; + kcb->kprobe_status = KPROBE_REENTER; return 1; } else { - p = current_kprobe; + p = __get_cpu_var(current_kprobe); if (p->break_handler && p->break_handler(p, regs)) { goto ss_probe; } @@ -235,8 +232,8 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) * in post_kprobe_handler() */ preempt_disable(); - kprobe_status = KPROBE_HIT_ACTIVE; - set_current_kprobe(p, regs); + set_current_kprobe(p, regs, kcb); + kcb->kprobe_status = KPROBE_HIT_ACTIVE; if (p->pre_handler && p->pre_handler(p, regs)) /* handler has already set things up, so skip ss setup */ @@ -244,7 +241,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) ss_probe: prepare_singlestep(p, regs); - kprobe_status = KPROBE_HIT_SS; + kcb->kprobe_status = KPROBE_HIT_SS; return 1; no_kprobe: @@ -312,6 +309,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address)); regs->eip = orig_ret_address; + reset_current_kprobe(); unlock_kprobes(); preempt_enable_no_resched(); @@ -345,7 +343,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) * that is atop the stack is the address following the copied instruction. * We need to make it the address following the original instruction. */ -static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) +static void __kprobes resume_execution(struct kprobe *p, + struct pt_regs *regs, struct kprobe_ctlblk *kcb) { unsigned long *tos = (unsigned long *)®s->esp; unsigned long next_eip = 0; @@ -355,7 +354,7 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) switch (p->ainsn.insn[0]) { case 0x9c: /* pushfl */ *tos &= ~(TF_MASK | IF_MASK); - *tos |= kprobe_old_eflags; + *tos |= kcb->kprobe_old_eflags; break; case 0xc3: /* ret/lret */ case 0xcb: @@ -400,22 +399,26 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) */ static inline int post_kprobe_handler(struct pt_regs *regs) { - if (!kprobe_running()) + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (!cur) return 0; - if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) { - kprobe_status = KPROBE_HIT_SSDONE; - current_kprobe->post_handler(current_kprobe, regs, 0); + if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) { + kcb->kprobe_status = KPROBE_HIT_SSDONE; + cur->post_handler(cur, regs, 0); } - resume_execution(current_kprobe, regs); - regs->eflags |= kprobe_saved_eflags; + resume_execution(cur, regs, kcb); + regs->eflags |= kcb->kprobe_saved_eflags; /*Restore back the original saved kprobes variables and continue. */ - if (kprobe_status == KPROBE_REENTER) { - restore_previous_kprobe(); + if (kcb->kprobe_status == KPROBE_REENTER) { + restore_previous_kprobe(kcb); goto out; } + reset_current_kprobe(); unlock_kprobes(); out: preempt_enable_no_resched(); @@ -434,14 +437,17 @@ out: /* Interrupts disabled, kprobe_lock held. */ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) { - if (current_kprobe->fault_handler - && current_kprobe->fault_handler(current_kprobe, regs, trapnr)) + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) return 1; - if (kprobe_status & KPROBE_HIT_SS) { - resume_execution(current_kprobe, regs); - regs->eflags |= kprobe_old_eflags; + if (kcb->kprobe_status & KPROBE_HIT_SS) { + resume_execution(cur, regs, kcb); + regs->eflags |= kcb->kprobe_old_eflags; + reset_current_kprobe(); unlock_kprobes(); preempt_enable_no_resched(); } @@ -484,10 +490,11 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct jprobe *jp = container_of(p, struct jprobe, kp); unsigned long addr; + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - jprobe_saved_regs = *regs; - jprobe_saved_esp = ®s->esp; - addr = (unsigned long)jprobe_saved_esp; + kcb->jprobe_saved_regs = *regs; + kcb->jprobe_saved_esp = ®s->esp; + addr = (unsigned long)(kcb->jprobe_saved_esp); /* * TBD: As Linus pointed out, gcc assumes that the callee @@ -496,7 +503,8 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) * we also save and restore enough stack bytes to cover * the argument area. */ - memcpy(jprobes_stack, (kprobe_opcode_t *) addr, MIN_STACK_SIZE(addr)); + memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr, + MIN_STACK_SIZE(addr)); regs->eflags &= ~IF_MASK; regs->eip = (unsigned long)(jp->entry); return 1; @@ -504,34 +512,38 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) void __kprobes jprobe_return(void) { + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + asm volatile (" xchgl %%ebx,%%esp \n" " int3 \n" " .globl jprobe_return_end \n" " jprobe_return_end: \n" " nop \n"::"b" - (jprobe_saved_esp):"memory"); + (kcb->jprobe_saved_esp):"memory"); } int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) { + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); u8 *addr = (u8 *) (regs->eip - 1); - unsigned long stack_addr = (unsigned long)jprobe_saved_esp; + unsigned long stack_addr = (unsigned long)(kcb->jprobe_saved_esp); struct jprobe *jp = container_of(p, struct jprobe, kp); if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) { - if (®s->esp != jprobe_saved_esp) { + if (®s->esp != kcb->jprobe_saved_esp) { struct pt_regs *saved_regs = - container_of(jprobe_saved_esp, struct pt_regs, esp); + container_of(kcb->jprobe_saved_esp, + struct pt_regs, esp); printk("current esp %p does not match saved esp %p\n", - ®s->esp, jprobe_saved_esp); + ®s->esp, kcb->jprobe_saved_esp); printk("Saved registers for jprobe %p\n", jp); show_registers(saved_regs); printk("Current registers\n"); show_registers(regs); BUG(); } - *regs = jprobe_saved_regs; - memcpy((kprobe_opcode_t *) stack_addr, jprobes_stack, + *regs = kcb->jprobe_saved_regs; + memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack, MIN_STACK_SIZE(stack_addr)); return 1; } diff --git a/include/asm-i386/kprobes.h b/include/asm-i386/kprobes.h index 8b6d3a90cd7..ca916a89287 100644 --- a/include/asm-i386/kprobes.h +++ b/include/asm-i386/kprobes.h @@ -49,6 +49,23 @@ struct arch_specific_insn { kprobe_opcode_t insn[MAX_INSN_SIZE]; }; +struct prev_kprobe { + struct kprobe *kp; + unsigned long status; + unsigned long old_eflags; + unsigned long saved_eflags; +}; + +/* per-cpu kprobe control block */ +struct kprobe_ctlblk { + unsigned long kprobe_status; + unsigned long kprobe_old_eflags; + unsigned long kprobe_saved_eflags; + long *jprobe_saved_esp; + struct pt_regs jprobe_saved_regs; + kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE]; + struct prev_kprobe prev_kprobe; +}; /* trap3/1 are intr gates for kprobes. So, restore the status of IF, * if necessary, before executing the original int3/1 (trap) handler. -- cgit v1.2.3 From 8a5c4dc5e5d72b7802f5647082ccf3861a94f013 Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Mon, 7 Nov 2005 01:00:09 -0800 Subject: [PATCH] Kprobes: Track kprobe on a per_cpu basis - ia64 changes IA64 changes to track kprobe execution on a per-cpu basis. We now track the kprobe state machine independently on each cpu using an arch specific kprobe control block. Signed-off-by: Ananth N Mavinakayanahalli Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ia64/kernel/kprobes.c | 83 +++++++++++++++++++++++++--------------------- include/asm-ia64/kprobes.h | 13 ++++++++ 2 files changed, 58 insertions(+), 38 deletions(-) diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 1e80ec80dd2..17e70b1b8d7 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c @@ -38,13 +38,8 @@ extern void jprobe_inst_return(void); -/* kprobe_status settings */ -#define KPROBE_HIT_ACTIVE 0x00000001 -#define KPROBE_HIT_SS 0x00000002 - -static struct kprobe *current_kprobe, *kprobe_prev; -static unsigned long kprobe_status, kprobe_status_prev; -static struct pt_regs jprobe_saved_regs; +DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; +DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); enum instruction_type {A, I, M, F, B, L, X, u}; static enum instruction_type bundle_encoding[32][3] = { @@ -313,21 +308,22 @@ static int __kprobes valid_kprobe_addr(int template, int slot, return 0; } -static inline void save_previous_kprobe(void) +static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb) { - kprobe_prev = current_kprobe; - kprobe_status_prev = kprobe_status; + kcb->prev_kprobe.kp = kprobe_running(); + kcb->prev_kprobe.status = kcb->kprobe_status; } -static inline void restore_previous_kprobe(void) +static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb) { - current_kprobe = kprobe_prev; - kprobe_status = kprobe_status_prev; + __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; + kcb->kprobe_status = kcb->prev_kprobe.status; } -static inline void set_current_kprobe(struct kprobe *p) +static inline void set_current_kprobe(struct kprobe *p, + struct kprobe_ctlblk *kcb) { - current_kprobe = p; + __get_cpu_var(current_kprobe) = p; } static void kretprobe_trampoline(void) @@ -389,6 +385,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address)); regs->cr_iip = orig_ret_address; + reset_current_kprobe(); unlock_kprobes(); preempt_enable_no_resched(); @@ -606,12 +603,13 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) int ret = 0; struct pt_regs *regs = args->regs; kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); /* Handle recursion cases */ if (kprobe_running()) { p = get_kprobe(addr); if (p) { - if ( (kprobe_status == KPROBE_HIT_SS) && + if ((kcb->kprobe_status == KPROBE_HIT_SS) && (p->ainsn.inst_flag == INST_FLAG_BREAK_INST)) { ia64_psr(regs)->ss = 0; unlock_kprobes(); @@ -623,17 +621,17 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) * just single step on the instruction of the new probe * without calling any user handlers. */ - save_previous_kprobe(); - set_current_kprobe(p); + save_previous_kprobe(kcb); + set_current_kprobe(p, kcb); p->nmissed++; prepare_ss(p, regs); - kprobe_status = KPROBE_REENTER; + kcb->kprobe_status = KPROBE_REENTER; return 1; } else if (args->err == __IA64_BREAK_JPROBE) { /* * jprobe instrumented function just completed */ - p = current_kprobe; + p = __get_cpu_var(current_kprobe); if (p->break_handler && p->break_handler(p, regs)) { goto ss_probe; } @@ -668,8 +666,8 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) * in post_kprobes_handler() */ preempt_disable(); - kprobe_status = KPROBE_HIT_ACTIVE; - set_current_kprobe(p); + set_current_kprobe(p, kcb); + kcb->kprobe_status = KPROBE_HIT_ACTIVE; if (p->pre_handler && p->pre_handler(p, regs)) /* @@ -681,7 +679,7 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) ss_probe: prepare_ss(p, regs); - kprobe_status = KPROBE_HIT_SS; + kcb->kprobe_status = KPROBE_HIT_SS; return 1; no_kprobe: @@ -690,22 +688,25 @@ no_kprobe: static int __kprobes post_kprobes_handler(struct pt_regs *regs) { - if (!kprobe_running()) + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (!cur) return 0; - if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) { - kprobe_status = KPROBE_HIT_SSDONE; - current_kprobe->post_handler(current_kprobe, regs, 0); + if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) { + kcb->kprobe_status = KPROBE_HIT_SSDONE; + cur->post_handler(cur, regs, 0); } - resume_execution(current_kprobe, regs); + resume_execution(cur, regs); /*Restore back the original saved kprobes variables and continue. */ - if (kprobe_status == KPROBE_REENTER) { - restore_previous_kprobe(); + if (kcb->kprobe_status == KPROBE_REENTER) { + restore_previous_kprobe(kcb); goto out; } - + reset_current_kprobe(); unlock_kprobes(); out: @@ -715,15 +716,18 @@ out: static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr) { - if (!kprobe_running()) + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (!cur) return 0; - if (current_kprobe->fault_handler && - current_kprobe->fault_handler(current_kprobe, regs, trapnr)) + if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) return 1; - if (kprobe_status & KPROBE_HIT_SS) { - resume_execution(current_kprobe, regs); + if (kcb->kprobe_status & KPROBE_HIT_SS) { + resume_execution(cur, regs); + reset_current_kprobe(); unlock_kprobes(); preempt_enable_no_resched(); } @@ -761,9 +765,10 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct jprobe *jp = container_of(p, struct jprobe, kp); unsigned long addr = ((struct fnptr *)(jp->entry))->ip; + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); /* save architectural state */ - jprobe_saved_regs = *regs; + kcb->jprobe_saved_regs = *regs; /* after rfi, execute the jprobe instrumented function */ regs->cr_iip = addr & ~0xFULL; @@ -781,7 +786,9 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) { - *regs = jprobe_saved_regs; + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + *regs = kcb->jprobe_saved_regs; return 1; } diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h index 573a3574a24..592abb000e2 100644 --- a/include/asm-ia64/kprobes.h +++ b/include/asm-ia64/kprobes.h @@ -26,6 +26,7 @@ */ #include #include +#include #include #define MAX_INSN_SIZE 16 @@ -62,6 +63,18 @@ typedef struct _bundle { } quad1; } __attribute__((__aligned__(16))) bundle_t; +struct prev_kprobe { + struct kprobe *kp; + unsigned long status; +}; + +/* per-cpu kprobe control block */ +struct kprobe_ctlblk { + unsigned long kprobe_status; + struct pt_regs jprobe_saved_regs; + struct prev_kprobe prev_kprobe; +}; + #define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry #define ARCH_SUPPORTS_KRETPROBES -- cgit v1.2.3 From 0dc036c91ac11b2b76bb91b59d8c7af919aa4a8d Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Mon, 7 Nov 2005 01:00:10 -0800 Subject: [PATCH] Kprobes: Track kprobe on a per_cpu basis - ppc64 changes PPC64 changes to track kprobe execution on a per-cpu basis. We now track the kprobe state machine independently on each cpu using an arch specific kprobe control block. Signed-off-by: Ananth N Mavinakayanahalli Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/kprobes.c | 94 +++++++++++++++++++++++++------------------ include/asm-powerpc/kprobes.h | 15 +++++++ 2 files changed, 69 insertions(+), 40 deletions(-) diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c index 6071ee99f5c..3f89f3e5584 100644 --- a/arch/ppc64/kernel/kprobes.c +++ b/arch/ppc64/kernel/kprobes.c @@ -37,12 +37,8 @@ #include static DECLARE_MUTEX(kprobe_mutex); - -static struct kprobe *current_kprobe; -static unsigned long kprobe_status, kprobe_saved_msr; -static struct kprobe *kprobe_prev; -static unsigned long kprobe_status_prev, kprobe_saved_msr_prev; -static struct pt_regs jprobe_saved_regs; +DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; +DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); int __kprobes arch_prepare_kprobe(struct kprobe *p) { @@ -108,18 +104,25 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) regs->nip = (unsigned long)p->ainsn.insn; } -static inline void save_previous_kprobe(void) +static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb) +{ + kcb->prev_kprobe.kp = kprobe_running(); + kcb->prev_kprobe.status = kcb->kprobe_status; + kcb->prev_kprobe.saved_msr = kcb->kprobe_saved_msr; +} + +static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb) { - kprobe_prev = current_kprobe; - kprobe_status_prev = kprobe_status; - kprobe_saved_msr_prev = kprobe_saved_msr; + __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; + kcb->kprobe_status = kcb->prev_kprobe.status; + kcb->kprobe_saved_msr = kcb->prev_kprobe.saved_msr; } -static inline void restore_previous_kprobe(void) +static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs, + struct kprobe_ctlblk *kcb) { - current_kprobe = kprobe_prev; - kprobe_status = kprobe_status_prev; - kprobe_saved_msr = kprobe_saved_msr_prev; + __get_cpu_var(current_kprobe) = p; + kcb->kprobe_saved_msr = regs->msr; } void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, @@ -145,6 +148,7 @@ static inline int kprobe_handler(struct pt_regs *regs) struct kprobe *p; int ret = 0; unsigned int *addr = (unsigned int *)regs->nip; + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); /* Check we're not actually recursing */ if (kprobe_running()) { @@ -153,10 +157,10 @@ static inline int kprobe_handler(struct pt_regs *regs) p = get_kprobe(addr); if (p) { kprobe_opcode_t insn = *p->ainsn.insn; - if (kprobe_status == KPROBE_HIT_SS && + if (kcb->kprobe_status == KPROBE_HIT_SS && is_trap(insn)) { regs->msr &= ~MSR_SE; - regs->msr |= kprobe_saved_msr; + regs->msr |= kcb->kprobe_saved_msr; unlock_kprobes(); goto no_kprobe; } @@ -166,15 +170,15 @@ static inline int kprobe_handler(struct pt_regs *regs) * just single step on the instruction of the new probe * without calling any user handlers. */ - save_previous_kprobe(); - current_kprobe = p; - kprobe_saved_msr = regs->msr; + save_previous_kprobe(kcb); + set_current_kprobe(p, regs, kcb); + kcb->kprobe_saved_msr = regs->msr; p->nmissed++; prepare_singlestep(p, regs); - kprobe_status = KPROBE_REENTER; + kcb->kprobe_status = KPROBE_REENTER; return 1; } else { - p = current_kprobe; + p = __get_cpu_var(current_kprobe); if (p->break_handler && p->break_handler(p, regs)) { goto ss_probe; } @@ -214,16 +218,15 @@ static inline int kprobe_handler(struct pt_regs *regs) * in post_kprobe_handler(). */ preempt_disable(); - kprobe_status = KPROBE_HIT_ACTIVE; - current_kprobe = p; - kprobe_saved_msr = regs->msr; + kcb->kprobe_status = KPROBE_HIT_ACTIVE; + set_current_kprobe(p, regs, kcb); if (p->pre_handler && p->pre_handler(p, regs)) /* handler has already set things up, so skip ss setup */ return 1; ss_probe: prepare_singlestep(p, regs); - kprobe_status = KPROBE_HIT_SS; + kcb->kprobe_status = KPROBE_HIT_SS; return 1; no_kprobe: @@ -292,6 +295,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address)); regs->nip = orig_ret_address; + reset_current_kprobe(); unlock_kprobes(); preempt_enable_no_resched(); @@ -324,22 +328,26 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) static inline int post_kprobe_handler(struct pt_regs *regs) { - if (!kprobe_running()) + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (!cur) return 0; - if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) { - kprobe_status = KPROBE_HIT_SSDONE; - current_kprobe->post_handler(current_kprobe, regs, 0); + if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) { + kcb->kprobe_status = KPROBE_HIT_SSDONE; + cur->post_handler(cur, regs, 0); } - resume_execution(current_kprobe, regs); - regs->msr |= kprobe_saved_msr; + resume_execution(cur, regs); + regs->msr |= kcb->kprobe_saved_msr; /*Restore back the original saved kprobes variables and continue. */ - if (kprobe_status == KPROBE_REENTER) { - restore_previous_kprobe(); + if (kcb->kprobe_status == KPROBE_REENTER) { + restore_previous_kprobe(kcb); goto out; } + reset_current_kprobe(); unlock_kprobes(); out: preempt_enable_no_resched(); @@ -358,15 +366,18 @@ out: /* Interrupts disabled, kprobe_lock held. */ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) { - if (current_kprobe->fault_handler - && current_kprobe->fault_handler(current_kprobe, regs, trapnr)) + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) return 1; - if (kprobe_status & KPROBE_HIT_SS) { - resume_execution(current_kprobe, regs); + if (kcb->kprobe_status & KPROBE_HIT_SS) { + resume_execution(cur, regs); regs->msr &= ~MSR_SE; - regs->msr |= kprobe_saved_msr; + regs->msr |= kcb->kprobe_saved_msr; + reset_current_kprobe(); unlock_kprobes(); preempt_enable_no_resched(); } @@ -411,8 +422,9 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct jprobe *jp = container_of(p, struct jprobe, kp); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - memcpy(&jprobe_saved_regs, regs, sizeof(struct pt_regs)); + memcpy(&kcb->jprobe_saved_regs, regs, sizeof(struct pt_regs)); /* setup return addr to the jprobe handler routine */ regs->nip = (unsigned long)(((func_descr_t *)jp->entry)->entry); @@ -432,12 +444,14 @@ void __kprobes jprobe_return_end(void) int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) { + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + /* * FIXME - we should ideally be validating that we got here 'cos * of the "trap" in jprobe_return() above, before restoring the * saved regs... */ - memcpy(regs, &jprobe_saved_regs, sizeof(struct pt_regs)); + memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs)); return 1; } diff --git a/include/asm-powerpc/kprobes.h b/include/asm-powerpc/kprobes.h index b2f09f17fbe..6cd0a3bfa28 100644 --- a/include/asm-powerpc/kprobes.h +++ b/include/asm-powerpc/kprobes.h @@ -27,6 +27,7 @@ */ #include #include +#include struct pt_regs; @@ -53,6 +54,20 @@ struct arch_specific_insn { kprobe_opcode_t *insn; }; +struct prev_kprobe { + struct kprobe *kp; + unsigned long status; + unsigned long saved_msr; +}; + +/* per-cpu kprobe control block */ +struct kprobe_ctlblk { + unsigned long kprobe_status; + unsigned long kprobe_saved_msr; + struct pt_regs jprobe_saved_regs; + struct prev_kprobe prev_kprobe; +}; + #ifdef CONFIG_KPROBES extern int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *data); -- cgit v1.2.3 From f215d985e936cf493959b365a10593b6d5f80447 Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Mon, 7 Nov 2005 01:00:11 -0800 Subject: [PATCH] Kprobes: Track kprobe on a per_cpu basis - sparc64 changes Sparc64 changes to track kprobe execution on a per-cpu basis. We now track the kprobe state machine independently on each cpu using an arch specific kprobe control block. Signed-off-by: Ananth N Mavinakayanahalli Signed-off-by: Anil S Keshavamurthy Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sparc64/kernel/kprobes.c | 131 +++++++++++++++++++++--------------------- include/asm-sparc64/kprobes.h | 20 +++++++ 2 files changed, 87 insertions(+), 64 deletions(-) diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c index 755a0d7d887..b95984154db 100644 --- a/arch/sparc64/kernel/kprobes.c +++ b/arch/sparc64/kernel/kprobes.c @@ -38,6 +38,9 @@ * - Mark that we are no longer actively in a kprobe. */ +DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; +DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); + int __kprobes arch_prepare_kprobe(struct kprobe *p) { return 0; @@ -66,46 +69,39 @@ void __kprobes arch_remove_kprobe(struct kprobe *p) { } -static struct kprobe *current_kprobe; -static unsigned long current_kprobe_orig_tnpc; -static unsigned long current_kprobe_orig_tstate_pil; -static unsigned int kprobe_status; -static struct kprobe *kprobe_prev; -static unsigned long kprobe_orig_tnpc_prev; -static unsigned long kprobe_orig_tstate_pil_prev; -static unsigned int kprobe_status_prev; - -static inline void save_previous_kprobe(void) +static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb) { - kprobe_status_prev = kprobe_status; - kprobe_orig_tnpc_prev = current_kprobe_orig_tnpc; - kprobe_orig_tstate_pil_prev = current_kprobe_orig_tstate_pil; - kprobe_prev = current_kprobe; + kcb->prev_kprobe.kp = kprobe_running(); + kcb->prev_kprobe.status = kcb->kprobe_status; + kcb->prev_kprobe.orig_tnpc = kcb->kprobe_orig_tnpc; + kcb->prev_kprobe.orig_tstate_pil = kcb->kprobe_orig_tstate_pil; } -static inline void restore_previous_kprobe(void) +static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb) { - kprobe_status = kprobe_status_prev; - current_kprobe_orig_tnpc = kprobe_orig_tnpc_prev; - current_kprobe_orig_tstate_pil = kprobe_orig_tstate_pil_prev; - current_kprobe = kprobe_prev; + __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; + kcb->kprobe_status = kcb->prev_kprobe.status; + kcb->kprobe_orig_tnpc = kcb->prev_kprobe.orig_tnpc; + kcb->kprobe_orig_tstate_pil = kcb->prev_kprobe.orig_tstate_pil; } -static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs) +static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs, + struct kprobe_ctlblk *kcb) { - current_kprobe_orig_tnpc = regs->tnpc; - current_kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL); - current_kprobe = p; + __get_cpu_var(current_kprobe) = p; + kcb->kprobe_orig_tnpc = regs->tnpc; + kcb->kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL); } -static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) +static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs, + struct kprobe_ctlblk *kcb) { regs->tstate |= TSTATE_PIL; /*single step inline, if it a breakpoint instruction*/ if (p->opcode == BREAKPOINT_INSTRUCTION) { regs->tpc = (unsigned long) p->addr; - regs->tnpc = current_kprobe_orig_tnpc; + regs->tnpc = kcb->kprobe_orig_tnpc; } else { regs->tpc = (unsigned long) &p->ainsn.insn[0]; regs->tnpc = (unsigned long) &p->ainsn.insn[1]; @@ -117,6 +113,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) struct kprobe *p; void *addr = (void *) regs->tpc; int ret = 0; + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); if (kprobe_running()) { /* We *are* holding lock here, so this is safe. @@ -124,9 +121,9 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) */ p = get_kprobe(addr); if (p) { - if (kprobe_status == KPROBE_HIT_SS) { + if (kcb->kprobe_status == KPROBE_HIT_SS) { regs->tstate = ((regs->tstate & ~TSTATE_PIL) | - current_kprobe_orig_tstate_pil); + kcb->kprobe_orig_tstate_pil); unlock_kprobes(); goto no_kprobe; } @@ -136,14 +133,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) * just single step on the instruction of the new probe * without calling any user handlers. */ - save_previous_kprobe(); - set_current_kprobe(p, regs); + save_previous_kprobe(kcb); + set_current_kprobe(p, regs, kcb); p->nmissed++; - kprobe_status = KPROBE_REENTER; - prepare_singlestep(p, regs); + kcb->kprobe_status = KPROBE_REENTER; + prepare_singlestep(p, regs, kcb); return 1; } else { - p = current_kprobe; + p = __get_cpu_var(current_kprobe); if (p->break_handler && p->break_handler(p, regs)) goto ss_probe; } @@ -174,14 +171,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) * in post_kprobes_handler() */ preempt_disable(); - set_current_kprobe(p, regs); - kprobe_status = KPROBE_HIT_ACTIVE; + set_current_kprobe(p, regs, kcb); + kcb->kprobe_status = KPROBE_HIT_ACTIVE; if (p->pre_handler && p->pre_handler(p, regs)) return 1; ss_probe: - prepare_singlestep(p, regs); - kprobe_status = KPROBE_HIT_SS; + prepare_singlestep(p, regs, kcb); + kcb->kprobe_status = KPROBE_HIT_SS; return 1; no_kprobe: @@ -262,11 +259,12 @@ static void __kprobes retpc_fixup(struct pt_regs *regs, u32 insn, * This function prepares to return from the post-single-step * breakpoint trap. */ -static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) +static void __kprobes resume_execution(struct kprobe *p, + struct pt_regs *regs, struct kprobe_ctlblk *kcb) { u32 insn = p->ainsn.insn[0]; - regs->tpc = current_kprobe_orig_tnpc; + regs->tpc = kcb->kprobe_orig_tnpc; regs->tnpc = relbranch_fixup(insn, (unsigned long) p->addr, (unsigned long) &p->ainsn.insn[0], @@ -274,26 +272,30 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) retpc_fixup(regs, insn, (unsigned long) p->addr); regs->tstate = ((regs->tstate & ~TSTATE_PIL) | - current_kprobe_orig_tstate_pil); + kcb->kprobe_orig_tstate_pil); } static inline int post_kprobe_handler(struct pt_regs *regs) { - if (!kprobe_running()) + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (!cur) return 0; - if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) { - kprobe_status = KPROBE_HIT_SSDONE; - current_kprobe->post_handler(current_kprobe, regs, 0); + if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) { + kcb->kprobe_status = KPROBE_HIT_SSDONE; + cur->post_handler(cur, regs, 0); } - resume_execution(current_kprobe, regs); + resume_execution(cur, regs, kcb); /*Restore back the original saved kprobes variables and continue. */ - if (kprobe_status == KPROBE_REENTER) { - restore_previous_kprobe(); + if (kcb->kprobe_status == KPROBE_REENTER) { + restore_previous_kprobe(kcb); goto out; } + reset_current_kprobe(); unlock_kprobes(); out: preempt_enable_no_resched(); @@ -304,13 +306,16 @@ out: /* Interrupts disabled, kprobe_lock held. */ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) { - if (current_kprobe->fault_handler - && current_kprobe->fault_handler(current_kprobe, regs, trapnr)) + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) return 1; - if (kprobe_status & KPROBE_HIT_SS) { - resume_execution(current_kprobe, regs); + if (kcb->kprobe_status & KPROBE_HIT_SS) { + resume_execution(cur, regs, kcb); + reset_current_kprobe(); unlock_kprobes(); preempt_enable_no_resched(); } @@ -370,24 +375,21 @@ asmlinkage void __kprobes kprobe_trap(unsigned long trap_level, } /* Jprobes support. */ -static struct pt_regs jprobe_saved_regs; -static struct pt_regs *jprobe_saved_regs_location; -static struct sparc_stackf jprobe_saved_stack; - int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct jprobe *jp = container_of(p, struct jprobe, kp); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - jprobe_saved_regs_location = regs; - memcpy(&jprobe_saved_regs, regs, sizeof(*regs)); + kcb->jprobe_saved_regs_location = regs; + memcpy(&(kcb->jprobe_saved_regs), regs, sizeof(*regs)); /* Save a whole stack frame, this gets arguments * pushed onto the stack after using up all the * arg registers. */ - memcpy(&jprobe_saved_stack, + memcpy(&(kcb->jprobe_saved_stack), (char *) (regs->u_regs[UREG_FP] + STACK_BIAS), - sizeof(jprobe_saved_stack)); + sizeof(kcb->jprobe_saved_stack)); regs->tpc = (unsigned long) jp->entry; regs->tnpc = ((unsigned long) jp->entry) + 0x4UL; @@ -411,14 +413,15 @@ extern void __show_regs(struct pt_regs * regs); int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) { u32 *addr = (u32 *) regs->tpc; + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); if (addr == (u32 *) jprobe_return_trap_instruction) { - if (jprobe_saved_regs_location != regs) { + if (kcb->jprobe_saved_regs_location != regs) { printk("JPROBE: Current regs (%p) does not match " "saved regs (%p).\n", - regs, jprobe_saved_regs_location); + regs, kcb->jprobe_saved_regs_location); printk("JPROBE: Saved registers\n"); - __show_regs(jprobe_saved_regs_location); + __show_regs(kcb->jprobe_saved_regs_location); printk("JPROBE: Current registers\n"); __show_regs(regs); BUG(); @@ -427,11 +430,11 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) * first so that UREG_FP is the original one for * the stack frame restore. */ - memcpy(regs, &jprobe_saved_regs, sizeof(*regs)); + memcpy(regs, &(kcb->jprobe_saved_regs), sizeof(*regs)); memcpy((char *) (regs->u_regs[UREG_FP] + STACK_BIAS), - &jprobe_saved_stack, - sizeof(jprobe_saved_stack)); + &(kcb->jprobe_saved_stack), + sizeof(kcb->jprobe_saved_stack)); return 1; } diff --git a/include/asm-sparc64/kprobes.h b/include/asm-sparc64/kprobes.h index a8d326a598f..7ba845320f5 100644 --- a/include/asm-sparc64/kprobes.h +++ b/include/asm-sparc64/kprobes.h @@ -3,6 +3,7 @@ #include #include +#include typedef u32 kprobe_opcode_t; @@ -18,6 +19,25 @@ struct arch_specific_insn { kprobe_opcode_t insn[MAX_INSN_SIZE]; }; +struct prev_kprobe { + struct kprobe *kp; + unsigned int status; + unsigned long orig_tnpc; + unsigned long orig_tstate_pil; +}; + +/* per-cpu kprobe control block */ +struct kprobe_ctlblk { + unsigned long kprobe_status; + unsigned long kprobe_orig_tnpc; + unsigned long kprobe_orig_tstate_pil; + long *jprobe_saved_esp; + struct pt_regs jprobe_saved_regs; + struct pt_regs *jprobe_saved_regs_location; + struct sparc_stackf jprobe_saved_stack; + struct prev_kprobe prev_kprobe; +}; + #ifdef CONFIG_KPROBES extern int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *data); -- cgit v1.2.3 From e7a510f92c1e482a7db05afd3cb84af1f4cfe0bc Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Mon, 7 Nov 2005 01:00:12 -0800 Subject: [PATCH] Kprobes: Track kprobe on a per_cpu basis - x86_64 changes x86_64 changes to track kprobe execution on a per-cpu basis. We now track the kprobe state machine independently on each cpu using a arch specific kprobe control block. Signed-off-by: Ananth N Mavinakayanahalli Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/kprobes.c | 129 +++++++++++++++++++++++-------------------- include/asm-x86_64/kprobes.h | 19 +++++++ 2 files changed, 89 insertions(+), 59 deletions(-) diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c index ebfa2c9241c..6cb40d133b7 100644 --- a/arch/x86_64/kernel/kprobes.c +++ b/arch/x86_64/kernel/kprobes.c @@ -44,17 +44,10 @@ #include static DECLARE_MUTEX(kprobe_mutex); - -static struct kprobe *current_kprobe; -static unsigned long kprobe_status, kprobe_old_rflags, kprobe_saved_rflags; -static struct kprobe *kprobe_prev; -static unsigned long kprobe_status_prev, kprobe_old_rflags_prev, kprobe_saved_rflags_prev; -static struct pt_regs jprobe_saved_regs; -static long *jprobe_saved_rsp; void jprobe_return_end(void); -/* copy of the kernel stack at the probe fire time */ -static kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE]; +DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; +DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); /* * returns non-zero if opcode modifies the interrupt flag. @@ -236,29 +229,30 @@ void __kprobes arch_remove_kprobe(struct kprobe *p) up(&kprobe_mutex); } -static inline void save_previous_kprobe(void) +static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb) { - kprobe_prev = current_kprobe; - kprobe_status_prev = kprobe_status; - kprobe_old_rflags_prev = kprobe_old_rflags; - kprobe_saved_rflags_prev = kprobe_saved_rflags; + kcb->prev_kprobe.kp = kprobe_running(); + kcb->prev_kprobe.status = kcb->kprobe_status; + kcb->prev_kprobe.old_rflags = kcb->kprobe_old_rflags; + kcb->prev_kprobe.saved_rflags = kcb->kprobe_saved_rflags; } -static inline void restore_previous_kprobe(void) +static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb) { - current_kprobe = kprobe_prev; - kprobe_status = kprobe_status_prev; - kprobe_old_rflags = kprobe_old_rflags_prev; - kprobe_saved_rflags = kprobe_saved_rflags_prev; + __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; + kcb->kprobe_status = kcb->prev_kprobe.status; + kcb->kprobe_old_rflags = kcb->prev_kprobe.old_rflags; + kcb->kprobe_saved_rflags = kcb->prev_kprobe.saved_rflags; } -static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs) +static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs, + struct kprobe_ctlblk *kcb) { - current_kprobe = p; - kprobe_saved_rflags = kprobe_old_rflags + __get_cpu_var(current_kprobe) = p; + kcb->kprobe_saved_rflags = kcb->kprobe_old_rflags = (regs->eflags & (TF_MASK | IF_MASK)); if (is_IF_modifier(p->ainsn.insn)) - kprobe_saved_rflags &= ~IF_MASK; + kcb->kprobe_saved_rflags &= ~IF_MASK; } static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) @@ -301,6 +295,7 @@ int __kprobes kprobe_handler(struct pt_regs *regs) struct kprobe *p; int ret = 0; kprobe_opcode_t *addr = (kprobe_opcode_t *)(regs->rip - sizeof(kprobe_opcode_t)); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); /* Check we're not actually recursing */ if (kprobe_running()) { @@ -308,13 +303,13 @@ int __kprobes kprobe_handler(struct pt_regs *regs) Disarm the probe we just hit, and ignore it. */ p = get_kprobe(addr); if (p) { - if (kprobe_status == KPROBE_HIT_SS && + if (kcb->kprobe_status == KPROBE_HIT_SS && *p->ainsn.insn == BREAKPOINT_INSTRUCTION) { regs->eflags &= ~TF_MASK; - regs->eflags |= kprobe_saved_rflags; + regs->eflags |= kcb->kprobe_saved_rflags; unlock_kprobes(); goto no_kprobe; - } else if (kprobe_status == KPROBE_HIT_SSDONE) { + } else if (kcb->kprobe_status == KPROBE_HIT_SSDONE) { /* TODO: Provide re-entrancy from * post_kprobes_handler() and avoid exception * stack corruption while single-stepping on @@ -322,6 +317,7 @@ int __kprobes kprobe_handler(struct pt_regs *regs) */ arch_disarm_kprobe(p); regs->rip = (unsigned long)p->addr; + reset_current_kprobe(); ret = 1; } else { /* We have reentered the kprobe_handler(), since @@ -331,15 +327,15 @@ int __kprobes kprobe_handler(struct pt_regs *regs) * of the new probe without calling any user * handlers. */ - save_previous_kprobe(); - set_current_kprobe(p, regs); + save_previous_kprobe(kcb); + set_current_kprobe(p, regs, kcb); p->nmissed++; prepare_singlestep(p, regs); - kprobe_status = KPROBE_REENTER; + kcb->kprobe_status = KPROBE_REENTER; return 1; } } else { - p = current_kprobe; + p = __get_cpu_var(current_kprobe); if (p->break_handler && p->break_handler(p, regs)) { goto ss_probe; } @@ -374,8 +370,8 @@ int __kprobes kprobe_handler(struct pt_regs *regs) * in post_kprobe_handler() */ preempt_disable(); - kprobe_status = KPROBE_HIT_ACTIVE; - set_current_kprobe(p, regs); + set_current_kprobe(p, regs, kcb); + kcb->kprobe_status = KPROBE_HIT_ACTIVE; if (p->pre_handler && p->pre_handler(p, regs)) /* handler has already set things up, so skip ss setup */ @@ -383,7 +379,7 @@ int __kprobes kprobe_handler(struct pt_regs *regs) ss_probe: prepare_singlestep(p, regs); - kprobe_status = KPROBE_HIT_SS; + kcb->kprobe_status = KPROBE_HIT_SS; return 1; no_kprobe: @@ -451,6 +447,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address)); regs->rip = orig_ret_address; + reset_current_kprobe(); unlock_kprobes(); preempt_enable_no_resched(); @@ -484,7 +481,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) * that is atop the stack is the address following the copied instruction. * We need to make it the address following the original instruction. */ -static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) +static void __kprobes resume_execution(struct kprobe *p, + struct pt_regs *regs, struct kprobe_ctlblk *kcb) { unsigned long *tos = (unsigned long *)regs->rsp; unsigned long next_rip = 0; @@ -499,7 +497,7 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) switch (*insn) { case 0x9c: /* pushfl */ *tos &= ~(TF_MASK | IF_MASK); - *tos |= kprobe_old_rflags; + *tos |= kcb->kprobe_old_rflags; break; case 0xc3: /* ret/lret */ case 0xcb: @@ -544,24 +542,28 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) */ int __kprobes post_kprobe_handler(struct pt_regs *regs) { - if (!kprobe_running()) + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (!cur) return 0; - if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) { - kprobe_status = KPROBE_HIT_SSDONE; - current_kprobe->post_handler(current_kprobe, regs, 0); + if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) { + kcb->kprobe_status = KPROBE_HIT_SSDONE; + cur->post_handler(cur, regs, 0); } - resume_execution(current_kprobe, regs); - regs->eflags |= kprobe_saved_rflags; + resume_execution(cur, regs, kcb); + regs->eflags |= kcb->kprobe_saved_rflags; /* Restore the original saved kprobes variables and continue. */ - if (kprobe_status == KPROBE_REENTER) { - restore_previous_kprobe(); + if (kcb->kprobe_status == KPROBE_REENTER) { + restore_previous_kprobe(kcb); goto out; } else { unlock_kprobes(); } + reset_current_kprobe(); out: preempt_enable_no_resched(); @@ -579,14 +581,17 @@ out: /* Interrupts disabled, kprobe_lock held. */ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) { - if (current_kprobe->fault_handler - && current_kprobe->fault_handler(current_kprobe, regs, trapnr)) + struct kprobe *cur = kprobe_running(); + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) return 1; - if (kprobe_status & KPROBE_HIT_SS) { - resume_execution(current_kprobe, regs); - regs->eflags |= kprobe_old_rflags; + if (kcb->kprobe_status & KPROBE_HIT_SS) { + resume_execution(cur, regs, kcb); + regs->eflags |= kcb->kprobe_old_rflags; + reset_current_kprobe(); unlock_kprobes(); preempt_enable_no_resched(); } @@ -629,10 +634,11 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct jprobe *jp = container_of(p, struct jprobe, kp); unsigned long addr; + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - jprobe_saved_regs = *regs; - jprobe_saved_rsp = (long *) regs->rsp; - addr = (unsigned long)jprobe_saved_rsp; + kcb->jprobe_saved_regs = *regs; + kcb->jprobe_saved_rsp = (long *) regs->rsp; + addr = (unsigned long)(kcb->jprobe_saved_rsp); /* * As Linus pointed out, gcc assumes that the callee * owns the argument space and could overwrite it, e.g. @@ -640,7 +646,8 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) * we also save and restore enough stack bytes to cover * the argument area. */ - memcpy(jprobes_stack, (kprobe_opcode_t *) addr, MIN_STACK_SIZE(addr)); + memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr, + MIN_STACK_SIZE(addr)); regs->eflags &= ~IF_MASK; regs->rip = (unsigned long)(jp->entry); return 1; @@ -648,34 +655,38 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) void __kprobes jprobe_return(void) { + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + asm volatile (" xchg %%rbx,%%rsp \n" " int3 \n" " .globl jprobe_return_end \n" " jprobe_return_end: \n" " nop \n"::"b" - (jprobe_saved_rsp):"memory"); + (kcb->jprobe_saved_rsp):"memory"); } int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) { + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); u8 *addr = (u8 *) (regs->rip - 1); - unsigned long stack_addr = (unsigned long)jprobe_saved_rsp; + unsigned long stack_addr = (unsigned long)(kcb->jprobe_saved_rsp); struct jprobe *jp = container_of(p, struct jprobe, kp); if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) { - if ((long *)regs->rsp != jprobe_saved_rsp) { + if ((long *)regs->rsp != kcb->jprobe_saved_rsp) { struct pt_regs *saved_regs = - container_of(jprobe_saved_rsp, struct pt_regs, rsp); + container_of(kcb->jprobe_saved_rsp, + struct pt_regs, rsp); printk("current rsp %p does not match saved rsp %p\n", - (long *)regs->rsp, jprobe_saved_rsp); + (long *)regs->rsp, kcb->jprobe_saved_rsp); printk("Saved registers for jprobe %p\n", jp); show_registers(saved_regs); printk("Current registers\n"); show_registers(regs); BUG(); } - *regs = jprobe_saved_regs; - memcpy((kprobe_opcode_t *) stack_addr, jprobes_stack, + *regs = kcb->jprobe_saved_regs; + memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack, MIN_STACK_SIZE(stack_addr)); return 1; } diff --git a/include/asm-x86_64/kprobes.h b/include/asm-x86_64/kprobes.h index 6d6d883fdf6..4dd7a7e148d 100644 --- a/include/asm-x86_64/kprobes.h +++ b/include/asm-x86_64/kprobes.h @@ -25,6 +25,7 @@ */ #include #include +#include struct pt_regs; @@ -48,6 +49,24 @@ struct arch_specific_insn { kprobe_opcode_t *insn; }; +struct prev_kprobe { + struct kprobe *kp; + unsigned long status; + unsigned long old_rflags; + unsigned long saved_rflags; +}; + +/* per-cpu kprobe control block */ +struct kprobe_ctlblk { + unsigned long kprobe_status; + unsigned long kprobe_old_rflags; + unsigned long kprobe_saved_rflags; + long *jprobe_saved_rsp; + struct pt_regs jprobe_saved_regs; + kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE]; + struct prev_kprobe prev_kprobe; +}; + /* trap3/1 are intr gates for kprobes. So, restore the status of IF, * if necessary, before executing the original int3/1 (trap) handler. */ -- cgit v1.2.3 From 3516a46042508a495fac13c2e73530d936ebe015 Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Mon, 7 Nov 2005 01:00:13 -0800 Subject: [PATCH] Kprobes: Use RCU for (un)register synchronization - base changes Changes to the base kprobes infrastructure to use RCU for synchronization during kprobe registration and unregistration. These changes coupled with the arch kprobe changes (next in series): a. serialize registration and unregistration of kprobes. b. enable lockless execution of handlers. Handlers can now run in parallel. Signed-off-by: Ananth N Mavinakayanahalli Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/kprobes.h | 9 ++--- kernel/kprobes.c | 103 ++++++++++++++++++++---------------------------- 2 files changed, 46 insertions(+), 66 deletions(-) diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 6720305a31e..cff281cf70c 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include @@ -146,10 +148,7 @@ struct kretprobe_instance { }; #ifdef CONFIG_KPROBES -/* Locks kprobe: irq must be disabled */ -void lock_kprobes(void); -void unlock_kprobes(void); - +extern spinlock_t kretprobe_lock; extern int arch_prepare_kprobe(struct kprobe *p); extern void arch_copy_kprobe(struct kprobe *p); extern void arch_arm_kprobe(struct kprobe *p); @@ -160,7 +159,7 @@ extern void show_registers(struct pt_regs *regs); extern kprobe_opcode_t *get_insn_slot(void); extern void free_insn_slot(kprobe_opcode_t *slot); -/* Get the kprobe at this addr (if any). Must have called lock_kprobes */ +/* Get the kprobe at this addr (if any) - called under a rcu_read_lock() */ struct kprobe *get_kprobe(void *addr); struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk); diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 6da8f9b33d1..cfef426e4cd 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -32,7 +32,6 @@ * added function-return probes. */ #include -#include #include #include #include @@ -49,8 +48,8 @@ static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE]; static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE]; -unsigned int kprobe_cpu = NR_CPUS; -static DEFINE_SPINLOCK(kprobe_lock); +static DEFINE_SPINLOCK(kprobe_lock); /* Protects kprobe_table */ +DEFINE_SPINLOCK(kretprobe_lock); /* Protects kretprobe_inst_table */ static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL; /* @@ -153,41 +152,6 @@ void __kprobes free_insn_slot(kprobe_opcode_t *slot) } } -/* Locks kprobe: irqs must be disabled */ -void __kprobes lock_kprobes(void) -{ - unsigned long flags = 0; - - /* Avoiding local interrupts to happen right after we take the kprobe_lock - * and before we get a chance to update kprobe_cpu, this to prevent - * deadlock when we have a kprobe on ISR routine and a kprobe on task - * routine - */ - local_irq_save(flags); - - spin_lock(&kprobe_lock); - kprobe_cpu = smp_processor_id(); - - local_irq_restore(flags); -} - -void __kprobes unlock_kprobes(void) -{ - unsigned long flags = 0; - - /* Avoiding local interrupts to happen right after we update - * kprobe_cpu and before we get a a chance to release kprobe_lock, - * this to prevent deadlock when we have a kprobe on ISR routine and - * a kprobe on task routine - */ - local_irq_save(flags); - - kprobe_cpu = NR_CPUS; - spin_unlock(&kprobe_lock); - - local_irq_restore(flags); -} - /* We have preemption disabled.. so it is safe to use __ versions */ static inline void set_kprobe_instance(struct kprobe *kp) { @@ -199,15 +163,20 @@ static inline void reset_kprobe_instance(void) __get_cpu_var(kprobe_instance) = NULL; } -/* You have to be holding the kprobe_lock */ +/* + * This routine is called either: + * - under the kprobe_lock spinlock - during kprobe_[un]register() + * OR + * - under an rcu_read_lock() - from arch/xxx/kernel/kprobes.c + */ struct kprobe __kprobes *get_kprobe(void *addr) { struct hlist_head *head; struct hlist_node *node; + struct kprobe *p; head = &kprobe_table[hash_ptr(addr, KPROBE_HASH_BITS)]; - hlist_for_each(node, head) { - struct kprobe *p = hlist_entry(node, struct kprobe, hlist); + hlist_for_each_entry_rcu(p, node, head, hlist) { if (p->addr == addr) return p; } @@ -222,7 +191,7 @@ static int __kprobes aggr_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct kprobe *kp; - list_for_each_entry(kp, &p->list, list) { + list_for_each_entry_rcu(kp, &p->list, list) { if (kp->pre_handler) { set_kprobe_instance(kp); if (kp->pre_handler(kp, regs)) @@ -238,7 +207,7 @@ static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs, { struct kprobe *kp; - list_for_each_entry(kp, &p->list, list) { + list_for_each_entry_rcu(kp, &p->list, list) { if (kp->post_handler) { set_kprobe_instance(kp); kp->post_handler(kp, regs, flags); @@ -277,6 +246,7 @@ static int __kprobes aggr_break_handler(struct kprobe *p, struct pt_regs *regs) return ret; } +/* Called with kretprobe_lock held */ struct kretprobe_instance __kprobes *get_free_rp_inst(struct kretprobe *rp) { struct hlist_node *node; @@ -286,6 +256,7 @@ struct kretprobe_instance __kprobes *get_free_rp_inst(struct kretprobe *rp) return NULL; } +/* Called with kretprobe_lock held */ static struct kretprobe_instance __kprobes *get_used_rp_inst(struct kretprobe *rp) { @@ -296,6 +267,7 @@ static struct kretprobe_instance __kprobes *get_used_rp_inst(struct kretprobe return NULL; } +/* Called with kretprobe_lock held */ void __kprobes add_rp_inst(struct kretprobe_instance *ri) { /* @@ -314,6 +286,7 @@ void __kprobes add_rp_inst(struct kretprobe_instance *ri) hlist_add_head(&ri->uflist, &ri->rp->used_instances); } +/* Called with kretprobe_lock held */ void __kprobes recycle_rp_inst(struct kretprobe_instance *ri) { /* remove rp inst off the rprobe_inst_table */ @@ -347,13 +320,13 @@ void __kprobes kprobe_flush_task(struct task_struct *tk) struct hlist_node *node, *tmp; unsigned long flags = 0; - spin_lock_irqsave(&kprobe_lock, flags); + spin_lock_irqsave(&kretprobe_lock, flags); head = kretprobe_inst_table_head(current); hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { if (ri->task == tk) recycle_rp_inst(ri); } - spin_unlock_irqrestore(&kprobe_lock, flags); + spin_unlock_irqrestore(&kretprobe_lock, flags); } /* @@ -364,9 +337,12 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs) { struct kretprobe *rp = container_of(p, struct kretprobe, kp); + unsigned long flags = 0; /*TODO: consider to only swap the RA after the last pre_handler fired */ + spin_lock_irqsave(&kretprobe_lock, flags); arch_prepare_kretprobe(rp, regs); + spin_unlock_irqrestore(&kretprobe_lock, flags); return 0; } @@ -397,13 +373,13 @@ static int __kprobes add_new_kprobe(struct kprobe *old_p, struct kprobe *p) struct kprobe *kp; if (p->break_handler) { - list_for_each_entry(kp, &old_p->list, list) { + list_for_each_entry_rcu(kp, &old_p->list, list) { if (kp->break_handler) return -EEXIST; } - list_add_tail(&p->list, &old_p->list); + list_add_tail_rcu(&p->list, &old_p->list); } else - list_add(&p->list, &old_p->list); + list_add_rcu(&p->list, &old_p->list); return 0; } @@ -421,18 +397,18 @@ static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p) ap->break_handler = aggr_break_handler; INIT_LIST_HEAD(&ap->list); - list_add(&p->list, &ap->list); + list_add_rcu(&p->list, &ap->list); INIT_HLIST_NODE(&ap->hlist); - hlist_del(&p->hlist); - hlist_add_head(&ap->hlist, + hlist_del_rcu(&p->hlist); + hlist_add_head_rcu(&ap->hlist, &kprobe_table[hash_ptr(ap->addr, KPROBE_HASH_BITS)]); } /* * This is the second or subsequent kprobe at the address - handle * the intricacies - * TODO: Move kcalloc outside the spinlock + * TODO: Move kcalloc outside the spin_lock */ static int __kprobes register_aggr_kprobe(struct kprobe *old_p, struct kprobe *p) @@ -458,7 +434,7 @@ static int __kprobes register_aggr_kprobe(struct kprobe *old_p, static inline void cleanup_kprobe(struct kprobe *p, unsigned long flags) { arch_disarm_kprobe(p); - hlist_del(&p->hlist); + hlist_del_rcu(&p->hlist); spin_unlock_irqrestore(&kprobe_lock, flags); arch_remove_kprobe(p); } @@ -466,11 +442,10 @@ static inline void cleanup_kprobe(struct kprobe *p, unsigned long flags) static inline void cleanup_aggr_kprobe(struct kprobe *old_p, struct kprobe *p, unsigned long flags) { - list_del(&p->list); - if (list_empty(&old_p->list)) { + list_del_rcu(&p->list); + if (list_empty(&old_p->list)) cleanup_kprobe(old_p, flags); - kfree(old_p); - } else + else spin_unlock_irqrestore(&kprobe_lock, flags); } @@ -493,9 +468,9 @@ int __kprobes register_kprobe(struct kprobe *p) if ((ret = arch_prepare_kprobe(p)) != 0) goto rm_kprobe; + p->nmissed = 0; spin_lock_irqsave(&kprobe_lock, flags); old_p = get_kprobe(p->addr); - p->nmissed = 0; if (old_p) { ret = register_aggr_kprobe(old_p, p); goto out; @@ -503,7 +478,7 @@ int __kprobes register_kprobe(struct kprobe *p) arch_copy_kprobe(p); INIT_HLIST_NODE(&p->hlist); - hlist_add_head(&p->hlist, + hlist_add_head_rcu(&p->hlist, &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]); arch_arm_kprobe(p); @@ -524,10 +499,16 @@ void __kprobes unregister_kprobe(struct kprobe *p) spin_lock_irqsave(&kprobe_lock, flags); old_p = get_kprobe(p->addr); if (old_p) { + /* cleanup_*_kprobe() does the spin_unlock_irqrestore */ if (old_p->pre_handler == aggr_pre_handler) cleanup_aggr_kprobe(old_p, p, flags); else cleanup_kprobe(p, flags); + + synchronize_sched(); + if (old_p->pre_handler == aggr_pre_handler && + list_empty(&old_p->list)) + kfree(old_p); } else spin_unlock_irqrestore(&kprobe_lock, flags); } @@ -604,13 +585,13 @@ void __kprobes unregister_kretprobe(struct kretprobe *rp) unregister_kprobe(&rp->kp); /* No race here */ - spin_lock_irqsave(&kprobe_lock, flags); + spin_lock_irqsave(&kretprobe_lock, flags); free_rp_inst(rp); while ((ri = get_used_rp_inst(rp)) != NULL) { ri->rp = NULL; hlist_del(&ri->uflist); } - spin_unlock_irqrestore(&kprobe_lock, flags); + spin_unlock_irqrestore(&kretprobe_lock, flags); } static int __init init_kprobes(void) -- cgit v1.2.3 From 991a51d83a3d9bebfafdd1e692cf310899d60791 Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Mon, 7 Nov 2005 01:00:14 -0800 Subject: [PATCH] Kprobes: Use RCU for (un)register synchronization - arch changes Changes to the arch kprobes infrastructure to take advantage of the locking changes introduced by usage of RCU for synchronization. All handlers are now run without any locks held, so they have to be re-entrant or provide their own synchronization. Signed-off-by: Ananth N Mavinakayanahalli Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/kprobes.c | 22 +++++++--------------- arch/ia64/kernel/kprobes.c | 16 ++++++---------- arch/ppc64/kernel/kprobes.c | 24 ++++++------------------ arch/sparc64/kernel/kprobes.c | 14 ++------------ arch/x86_64/kernel/kprobes.c | 25 ++++++------------------- 5 files changed, 27 insertions(+), 74 deletions(-) diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index 99565a66915..ad469299267 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -123,6 +122,7 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) regs->eip = (unsigned long)&p->ainsn.insn; } +/* Called with kretprobe_lock held */ void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) { @@ -168,15 +168,12 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) } /* Check we're not actually recursing */ if (kprobe_running()) { - /* We *are* holding lock here, so this is safe. - Disarm the probe we just hit, and ignore it. */ p = get_kprobe(addr); if (p) { if (kcb->kprobe_status == KPROBE_HIT_SS && *p->ainsn.insn == BREAKPOINT_INSTRUCTION) { regs->eflags &= ~TF_MASK; regs->eflags |= kcb->kprobe_saved_eflags; - unlock_kprobes(); goto no_kprobe; } /* We have reentered the kprobe_handler(), since @@ -197,14 +194,11 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) goto ss_probe; } } - /* If it's not ours, can't be delete race, (we hold lock). */ goto no_kprobe; } - lock_kprobes(); p = get_kprobe(addr); if (!p) { - unlock_kprobes(); if (regs->eflags & VM_MASK) { /* We are in virtual-8086 mode. Return 0 */ goto no_kprobe; @@ -268,9 +262,10 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) struct kretprobe_instance *ri = NULL; struct hlist_head *head; struct hlist_node *node, *tmp; - unsigned long orig_ret_address = 0; + unsigned long flags, orig_ret_address = 0; unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline; + spin_lock_irqsave(&kretprobe_lock, flags); head = kretprobe_inst_table_head(current); /* @@ -310,7 +305,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) regs->eip = orig_ret_address; reset_current_kprobe(); - unlock_kprobes(); + spin_unlock_irqrestore(&kretprobe_lock, flags); preempt_enable_no_resched(); /* @@ -395,7 +390,7 @@ static void __kprobes resume_execution(struct kprobe *p, /* * Interrupts are disabled on entry as trap1 is an interrupt gate and they - * remain disabled thoroughout this function. And we hold kprobe lock. + * remain disabled thoroughout this function. */ static inline int post_kprobe_handler(struct pt_regs *regs) { @@ -419,7 +414,6 @@ static inline int post_kprobe_handler(struct pt_regs *regs) goto out; } reset_current_kprobe(); - unlock_kprobes(); out: preempt_enable_no_resched(); @@ -434,7 +428,6 @@ out: return 1; } -/* Interrupts disabled, kprobe_lock held. */ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) { struct kprobe *cur = kprobe_running(); @@ -448,7 +441,6 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) regs->eflags |= kcb->kprobe_old_eflags; reset_current_kprobe(); - unlock_kprobes(); preempt_enable_no_resched(); } return 0; @@ -463,7 +455,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - preempt_disable(); + rcu_read_lock(); switch (val) { case DIE_INT3: if (kprobe_handler(args->regs)) @@ -482,7 +474,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, default: break; } - preempt_enable(); + rcu_read_unlock(); return ret; } diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 17e70b1b8d7..fddbac32d44 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -343,10 +342,11 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) struct kretprobe_instance *ri = NULL; struct hlist_head *head; struct hlist_node *node, *tmp; - unsigned long orig_ret_address = 0; + unsigned long flags, orig_ret_address = 0; unsigned long trampoline_address = ((struct fnptr *)kretprobe_trampoline)->ip; + spin_lock_irqsave(&kretprobe_lock, flags); head = kretprobe_inst_table_head(current); /* @@ -386,7 +386,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) regs->cr_iip = orig_ret_address; reset_current_kprobe(); - unlock_kprobes(); + spin_unlock_irqrestore(&kretprobe_lock, flags); preempt_enable_no_resched(); /* @@ -397,6 +397,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) return 1; } +/* Called with kretprobe_lock held */ void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) { @@ -612,7 +613,6 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) if ((kcb->kprobe_status == KPROBE_HIT_SS) && (p->ainsn.inst_flag == INST_FLAG_BREAK_INST)) { ia64_psr(regs)->ss = 0; - unlock_kprobes(); goto no_kprobe; } /* We have reentered the pre_kprobe_handler(), since @@ -641,10 +641,8 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) } } - lock_kprobes(); p = get_kprobe(addr); if (!p) { - unlock_kprobes(); if (!is_ia64_break_inst(regs)) { /* * The breakpoint instruction was removed right @@ -707,7 +705,6 @@ static int __kprobes post_kprobes_handler(struct pt_regs *regs) goto out; } reset_current_kprobe(); - unlock_kprobes(); out: preempt_enable_no_resched(); @@ -728,7 +725,6 @@ static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr) if (kcb->kprobe_status & KPROBE_HIT_SS) { resume_execution(cur, regs); reset_current_kprobe(); - unlock_kprobes(); preempt_enable_no_resched(); } @@ -741,7 +737,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - preempt_disable(); + rcu_read_lock(); switch(val) { case DIE_BREAK: if (pre_kprobes_handler(args)) @@ -757,7 +753,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, default: break; } - preempt_enable(); + rcu_read_unlock(); return ret; } diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c index 3f89f3e5584..e0a25b35437 100644 --- a/arch/ppc64/kernel/kprobes.c +++ b/arch/ppc64/kernel/kprobes.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -125,6 +124,7 @@ static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs, kcb->kprobe_saved_msr = regs->msr; } +/* Called with kretprobe_lock held */ void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) { @@ -152,8 +152,6 @@ static inline int kprobe_handler(struct pt_regs *regs) /* Check we're not actually recursing */ if (kprobe_running()) { - /* We *are* holding lock here, so this is safe. - Disarm the probe we just hit, and ignore it. */ p = get_kprobe(addr); if (p) { kprobe_opcode_t insn = *p->ainsn.insn; @@ -161,7 +159,6 @@ static inline int kprobe_handler(struct pt_regs *regs) is_trap(insn)) { regs->msr &= ~MSR_SE; regs->msr |= kcb->kprobe_saved_msr; - unlock_kprobes(); goto no_kprobe; } /* We have reentered the kprobe_handler(), since @@ -183,14 +180,11 @@ static inline int kprobe_handler(struct pt_regs *regs) goto ss_probe; } } - /* If it's not ours, can't be delete race, (we hold lock). */ goto no_kprobe; } - lock_kprobes(); p = get_kprobe(addr); if (!p) { - unlock_kprobes(); if (*addr != BREAKPOINT_INSTRUCTION) { /* * PowerPC has multiple variants of the "trap" @@ -254,9 +248,10 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) struct kretprobe_instance *ri = NULL; struct hlist_head *head; struct hlist_node *node, *tmp; - unsigned long orig_ret_address = 0; + unsigned long flags, orig_ret_address = 0; unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline; + spin_lock_irqsave(&kretprobe_lock, flags); head = kretprobe_inst_table_head(current); /* @@ -296,7 +291,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) regs->nip = orig_ret_address; reset_current_kprobe(); - unlock_kprobes(); + spin_unlock_irqrestore(&kretprobe_lock, flags); preempt_enable_no_resched(); /* @@ -348,7 +343,6 @@ static inline int post_kprobe_handler(struct pt_regs *regs) goto out; } reset_current_kprobe(); - unlock_kprobes(); out: preempt_enable_no_resched(); @@ -363,7 +357,6 @@ out: return 1; } -/* Interrupts disabled, kprobe_lock held. */ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) { struct kprobe *cur = kprobe_running(); @@ -378,7 +371,6 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) regs->msr |= kcb->kprobe_saved_msr; reset_current_kprobe(); - unlock_kprobes(); preempt_enable_no_resched(); } return 0; @@ -393,11 +385,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - /* - * Interrupts are not disabled here. We need to disable - * preemption, because kprobe_running() uses smp_processor_id(). - */ - preempt_disable(); + rcu_read_lock(); switch (val) { case DIE_BPT: if (kprobe_handler(args->regs)) @@ -415,7 +403,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, default: break; } - preempt_enable_no_resched(); + rcu_read_unlock(); return ret; } diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c index b95984154db..58a815e9037 100644 --- a/arch/sparc64/kernel/kprobes.c +++ b/arch/sparc64/kernel/kprobes.c @@ -116,15 +116,11 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); if (kprobe_running()) { - /* We *are* holding lock here, so this is safe. - * Disarm the probe we just hit, and ignore it. - */ p = get_kprobe(addr); if (p) { if (kcb->kprobe_status == KPROBE_HIT_SS) { regs->tstate = ((regs->tstate & ~TSTATE_PIL) | kcb->kprobe_orig_tstate_pil); - unlock_kprobes(); goto no_kprobe; } /* We have reentered the kprobe_handler(), since @@ -144,14 +140,11 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) if (p->break_handler && p->break_handler(p, regs)) goto ss_probe; } - /* If it's not ours, can't be delete race, (we hold lock). */ goto no_kprobe; } - lock_kprobes(); p = get_kprobe(addr); if (!p) { - unlock_kprobes(); if (*(u32 *)addr != BREAKPOINT_INSTRUCTION) { /* * The breakpoint instruction was removed right @@ -296,14 +289,12 @@ static inline int post_kprobe_handler(struct pt_regs *regs) goto out; } reset_current_kprobe(); - unlock_kprobes(); out: preempt_enable_no_resched(); return 1; } -/* Interrupts disabled, kprobe_lock held. */ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) { struct kprobe *cur = kprobe_running(); @@ -316,7 +307,6 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) resume_execution(cur, regs, kcb); reset_current_kprobe(); - unlock_kprobes(); preempt_enable_no_resched(); } return 0; @@ -331,7 +321,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - preempt_disable(); + rcu_read_lock(); switch (val) { case DIE_DEBUG: if (kprobe_handler(args->regs)) @@ -350,7 +340,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, default: break; } - preempt_enable(); + rcu_read_unlock(); return ret; } diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c index 6cb40d133b7..9bef2c8dc12 100644 --- a/arch/x86_64/kernel/kprobes.c +++ b/arch/x86_64/kernel/kprobes.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -266,6 +265,7 @@ static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) regs->rip = (unsigned long)p->ainsn.insn; } +/* Called with kretprobe_lock held */ void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) { @@ -299,15 +299,12 @@ int __kprobes kprobe_handler(struct pt_regs *regs) /* Check we're not actually recursing */ if (kprobe_running()) { - /* We *are* holding lock here, so this is safe. - Disarm the probe we just hit, and ignore it. */ p = get_kprobe(addr); if (p) { if (kcb->kprobe_status == KPROBE_HIT_SS && *p->ainsn.insn == BREAKPOINT_INSTRUCTION) { regs->eflags &= ~TF_MASK; regs->eflags |= kcb->kprobe_saved_rflags; - unlock_kprobes(); goto no_kprobe; } else if (kcb->kprobe_status == KPROBE_HIT_SSDONE) { /* TODO: Provide re-entrancy from @@ -340,14 +337,11 @@ int __kprobes kprobe_handler(struct pt_regs *regs) goto ss_probe; } } - /* If it's not ours, can't be delete race, (we hold lock). */ goto no_kprobe; } - lock_kprobes(); p = get_kprobe(addr); if (!p) { - unlock_kprobes(); if (*addr != BREAKPOINT_INSTRUCTION) { /* * The breakpoint instruction was removed right @@ -406,9 +400,10 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) struct kretprobe_instance *ri = NULL; struct hlist_head *head; struct hlist_node *node, *tmp; - unsigned long orig_ret_address = 0; + unsigned long flags, orig_ret_address = 0; unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline; + spin_lock_irqsave(&kretprobe_lock, flags); head = kretprobe_inst_table_head(current); /* @@ -448,7 +443,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) regs->rip = orig_ret_address; reset_current_kprobe(); - unlock_kprobes(); + spin_unlock_irqrestore(&kretprobe_lock, flags); preempt_enable_no_resched(); /* @@ -536,10 +531,6 @@ static void __kprobes resume_execution(struct kprobe *p, } } -/* - * Interrupts are disabled on entry as trap1 is an interrupt gate and they - * remain disabled thoroughout this function. And we hold kprobe lock. - */ int __kprobes post_kprobe_handler(struct pt_regs *regs) { struct kprobe *cur = kprobe_running(); @@ -560,8 +551,6 @@ int __kprobes post_kprobe_handler(struct pt_regs *regs) if (kcb->kprobe_status == KPROBE_REENTER) { restore_previous_kprobe(kcb); goto out; - } else { - unlock_kprobes(); } reset_current_kprobe(); out: @@ -578,7 +567,6 @@ out: return 1; } -/* Interrupts disabled, kprobe_lock held. */ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) { struct kprobe *cur = kprobe_running(); @@ -592,7 +580,6 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) regs->eflags |= kcb->kprobe_old_rflags; reset_current_kprobe(); - unlock_kprobes(); preempt_enable_no_resched(); } return 0; @@ -607,7 +594,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - preempt_disable(); + rcu_read_lock(); switch (val) { case DIE_INT3: if (kprobe_handler(args->regs)) @@ -626,7 +613,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, default: break; } - preempt_enable(); + rcu_read_unlock(); return ret; } -- cgit v1.2.3 From d217d5450f11d8c907c0458d175b0dc999b4d06d Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Mon, 7 Nov 2005 01:00:14 -0800 Subject: [PATCH] Kprobes: preempt_disable/enable() simplification Reorganize the preempt_disable/enable calls to eliminate the extra preempt depth. Changes based on Paul McKenney's review suggestions for the kprobes RCU changeset. Signed-off-by: Ananth N Mavinakayanahalli Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/kprobes.c | 25 +++++++++++++++---------- arch/ia64/kernel/kprobes.c | 37 ++++++++++++++++++++----------------- arch/ppc64/kernel/kprobes.c | 25 +++++++++++++++---------- arch/sparc64/kernel/kprobes.c | 21 +++++++++++++-------- arch/x86_64/kernel/kprobes.c | 29 +++++++++++++++-------------- include/linux/kprobes.h | 2 +- kernel/kprobes.c | 2 +- 7 files changed, 80 insertions(+), 61 deletions(-) diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index ad469299267..32b0c24ab9a 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c @@ -153,7 +153,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) int ret = 0; kprobe_opcode_t *addr = NULL; unsigned long *lp; - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + struct kprobe_ctlblk *kcb; + + /* + * We don't want to be preempted for the entire + * duration of kprobe processing + */ + preempt_disable(); + kcb = get_kprobe_ctlblk(); /* Check if the application is using LDT entry for its code segment and * calculate the address by reading the base address from the LDT entry. @@ -221,11 +228,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) goto no_kprobe; } - /* - * This preempt_disable() matches the preempt_enable_no_resched() - * in post_kprobe_handler() - */ - preempt_disable(); set_current_kprobe(p, regs, kcb); kcb->kprobe_status = KPROBE_HIT_ACTIVE; @@ -239,6 +241,7 @@ ss_probe: return 1; no_kprobe: + preempt_enable_no_resched(); return ret; } @@ -310,8 +313,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) /* * By returning a non-zero value, we are telling - * kprobe_handler() that we have handled unlocking - * and re-enabling preemption + * kprobe_handler() that we don't want the post_handler + * to run (and have re-enabled preemption) */ return 1; } @@ -455,7 +458,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - rcu_read_lock(); switch (val) { case DIE_INT3: if (kprobe_handler(args->regs)) @@ -467,14 +469,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, break; case DIE_GPF: case DIE_PAGE_FAULT: + /* kprobe_running() needs smp_processor_id() */ + preempt_disable(); if (kprobe_running() && kprobe_fault_handler(args->regs, args->trapnr)) ret = NOTIFY_STOP; + preempt_enable(); break; default: break; } - rcu_read_unlock(); return ret; } @@ -537,6 +541,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) *regs = kcb->jprobe_saved_regs; memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack, MIN_STACK_SIZE(stack_addr)); + preempt_enable_no_resched(); return 1; } return 0; diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index fddbac32d44..96736a119c9 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c @@ -389,11 +389,11 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) spin_unlock_irqrestore(&kretprobe_lock, flags); preempt_enable_no_resched(); - /* - * By returning a non-zero value, we are telling - * kprobe_handler() that we have handled unlocking - * and re-enabling preemption - */ + /* + * By returning a non-zero value, we are telling + * kprobe_handler() that we don't want the post_handler + * to run (and have re-enabled preemption) + */ return 1; } @@ -604,7 +604,14 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) int ret = 0; struct pt_regs *regs = args->regs; kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs); - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + struct kprobe_ctlblk *kcb; + + /* + * We don't want to be preempted for the entire + * duration of kprobe processing + */ + preempt_disable(); + kcb = get_kprobe_ctlblk(); /* Handle recursion cases */ if (kprobe_running()) { @@ -659,11 +666,6 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) goto no_kprobe; } - /* - * This preempt_disable() matches the preempt_enable_no_resched() - * in post_kprobes_handler() - */ - preempt_disable(); set_current_kprobe(p, kcb); kcb->kprobe_status = KPROBE_HIT_ACTIVE; @@ -681,6 +683,7 @@ ss_probe: return 1; no_kprobe: + preempt_enable_no_resched(); return ret; } @@ -716,9 +719,6 @@ static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr) struct kprobe *cur = kprobe_running(); struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - if (!cur) - return 0; - if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) return 1; @@ -737,7 +737,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - rcu_read_lock(); switch(val) { case DIE_BREAK: if (pre_kprobes_handler(args)) @@ -748,12 +747,15 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, ret = NOTIFY_STOP; break; case DIE_PAGE_FAULT: - if (kprobes_fault_handler(args->regs, args->trapnr)) + /* kprobe_running() needs smp_processor_id() */ + preempt_disable(); + if (kprobe_running() && + kprobes_fault_handler(args->regs, args->trapnr)) ret = NOTIFY_STOP; + preempt_enable(); default: break; } - rcu_read_unlock(); return ret; } @@ -785,6 +787,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); *regs = kcb->jprobe_saved_regs; + preempt_enable_no_resched(); return 1; } diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c index e0a25b35437..511af54e623 100644 --- a/arch/ppc64/kernel/kprobes.c +++ b/arch/ppc64/kernel/kprobes.c @@ -148,7 +148,14 @@ static inline int kprobe_handler(struct pt_regs *regs) struct kprobe *p; int ret = 0; unsigned int *addr = (unsigned int *)regs->nip; - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + struct kprobe_ctlblk *kcb; + + /* + * We don't want to be preempted for the entire + * duration of kprobe processing + */ + preempt_disable(); + kcb = get_kprobe_ctlblk(); /* Check we're not actually recursing */ if (kprobe_running()) { @@ -207,11 +214,6 @@ static inline int kprobe_handler(struct pt_regs *regs) goto no_kprobe; } - /* - * This preempt_disable() matches the preempt_enable_no_resched() - * in post_kprobe_handler(). - */ - preempt_disable(); kcb->kprobe_status = KPROBE_HIT_ACTIVE; set_current_kprobe(p, regs, kcb); if (p->pre_handler && p->pre_handler(p, regs)) @@ -224,6 +226,7 @@ ss_probe: return 1; no_kprobe: + preempt_enable_no_resched(); return ret; } @@ -296,8 +299,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) /* * By returning a non-zero value, we are telling - * kprobe_handler() that we have handled unlocking - * and re-enabling preemption. + * kprobe_handler() that we don't want the post_handler + * to run (and have re-enabled preemption) */ return 1; } @@ -385,7 +388,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - rcu_read_lock(); switch (val) { case DIE_BPT: if (kprobe_handler(args->regs)) @@ -396,14 +398,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, ret = NOTIFY_STOP; break; case DIE_PAGE_FAULT: + /* kprobe_running() needs smp_processor_id() */ + preempt_disable(); if (kprobe_running() && kprobe_fault_handler(args->regs, args->trapnr)) ret = NOTIFY_STOP; + preempt_enable(); break; default: break; } - rcu_read_unlock(); return ret; } @@ -440,6 +444,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) * saved regs... */ memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs)); + preempt_enable_no_resched(); return 1; } diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c index 58a815e9037..96bd09b098f 100644 --- a/arch/sparc64/kernel/kprobes.c +++ b/arch/sparc64/kernel/kprobes.c @@ -113,7 +113,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) struct kprobe *p; void *addr = (void *) regs->tpc; int ret = 0; - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + struct kprobe_ctlblk *kcb; + + /* + * We don't want to be preempted for the entire + * duration of kprobe processing + */ + preempt_disable(); + kcb = get_kprobe_ctlblk(); if (kprobe_running()) { p = get_kprobe(addr); @@ -159,11 +166,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) goto no_kprobe; } - /* - * This preempt_disable() matches the preempt_enable_no_resched() - * in post_kprobes_handler() - */ - preempt_disable(); set_current_kprobe(p, regs, kcb); kcb->kprobe_status = KPROBE_HIT_ACTIVE; if (p->pre_handler && p->pre_handler(p, regs)) @@ -175,6 +177,7 @@ ss_probe: return 1; no_kprobe: + preempt_enable_no_resched(); return ret; } @@ -321,7 +324,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - rcu_read_lock(); switch (val) { case DIE_DEBUG: if (kprobe_handler(args->regs)) @@ -333,14 +335,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, break; case DIE_GPF: case DIE_PAGE_FAULT: + /* kprobe_running() needs smp_processor_id() */ + preempt_disable(); if (kprobe_running() && kprobe_fault_handler(args->regs, args->trapnr)) ret = NOTIFY_STOP; + preempt_enable(); break; default: break; } - rcu_read_unlock(); return ret; } @@ -426,6 +430,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) &(kcb->jprobe_saved_stack), sizeof(kcb->jprobe_saved_stack)); + preempt_enable_no_resched(); return 1; } return 0; diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c index 9bef2c8dc12..dddeb678b44 100644 --- a/arch/x86_64/kernel/kprobes.c +++ b/arch/x86_64/kernel/kprobes.c @@ -286,16 +286,19 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, } } -/* - * Interrupts are disabled on entry as trap3 is an interrupt gate and they - * remain disabled thorough out this function. - */ int __kprobes kprobe_handler(struct pt_regs *regs) { struct kprobe *p; int ret = 0; kprobe_opcode_t *addr = (kprobe_opcode_t *)(regs->rip - sizeof(kprobe_opcode_t)); - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + struct kprobe_ctlblk *kcb; + + /* + * We don't want to be preempted for the entire + * duration of kprobe processing + */ + preempt_disable(); + kcb = get_kprobe_ctlblk(); /* Check we're not actually recursing */ if (kprobe_running()) { @@ -359,11 +362,6 @@ int __kprobes kprobe_handler(struct pt_regs *regs) goto no_kprobe; } - /* - * This preempt_disable() matches the preempt_enable_no_resched() - * in post_kprobe_handler() - */ - preempt_disable(); set_current_kprobe(p, regs, kcb); kcb->kprobe_status = KPROBE_HIT_ACTIVE; @@ -377,6 +375,7 @@ ss_probe: return 1; no_kprobe: + preempt_enable_no_resched(); return ret; } @@ -448,8 +447,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) /* * By returning a non-zero value, we are telling - * kprobe_handler() that we have handled unlocking - * and re-enabling preemption + * kprobe_handler() that we don't want the post_handler + * to run (and have re-enabled preemption) */ return 1; } @@ -594,7 +593,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - rcu_read_lock(); switch (val) { case DIE_INT3: if (kprobe_handler(args->regs)) @@ -606,14 +604,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, break; case DIE_GPF: case DIE_PAGE_FAULT: + /* kprobe_running() needs smp_processor_id() */ + preempt_disable(); if (kprobe_running() && kprobe_fault_handler(args->regs, args->trapnr)) ret = NOTIFY_STOP; + preempt_enable(); break; default: break; } - rcu_read_unlock(); return ret; } @@ -675,6 +675,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) *regs = kcb->jprobe_saved_regs; memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack, MIN_STACK_SIZE(stack_addr)); + preempt_enable_no_resched(); return 1; } return 0; diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index cff281cf70c..e373c4a9de5 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -159,7 +159,7 @@ extern void show_registers(struct pt_regs *regs); extern kprobe_opcode_t *get_insn_slot(void); extern void free_insn_slot(kprobe_opcode_t *slot); -/* Get the kprobe at this addr (if any) - called under a rcu_read_lock() */ +/* Get the kprobe at this addr (if any) - called with preemption disabled */ struct kprobe *get_kprobe(void *addr); struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk); diff --git a/kernel/kprobes.c b/kernel/kprobes.c index cfef426e4cd..5beda378cc7 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -167,7 +167,7 @@ static inline void reset_kprobe_instance(void) * This routine is called either: * - under the kprobe_lock spinlock - during kprobe_[un]register() * OR - * - under an rcu_read_lock() - from arch/xxx/kernel/kprobes.c + * - with preemption disabled - from arch/xxx/kernel/kprobes.c */ struct kprobe __kprobes *get_kprobe(void *addr) { -- cgit v1.2.3 From 394b701ce4fbfde919a9bcbf84cb4820a7c6d47c Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 7 Nov 2005 01:00:15 -0800 Subject: [PATCH] RapidIO support: core base Adds a RapidIO subsystem to the kernel. RIO is a switched fabric interconnect used in higher-end embedded applications. The curious can look at the specs over at http://www.rapidio.org The core code implements enumeration/discovery, management of devices/resources, and interfaces for RIO drivers. There's a lot more to do to take advantages of all the hardware features. However, this should provide a good base for folks with RIO hardware to start contributing. Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/DocBook/Makefile | 2 +- Documentation/DocBook/rapidio.tmpl | 160 ++++++++++++ MAINTAINERS | 6 + drivers/Makefile | 1 + drivers/rapidio/Kconfig | 18 ++ drivers/rapidio/Makefile | 6 + drivers/rapidio/rio-access.c | 175 +++++++++++++ drivers/rapidio/rio-driver.c | 229 +++++++++++++++++ drivers/rapidio/rio-sysfs.c | 230 +++++++++++++++++ drivers/rapidio/rio.c | 503 +++++++++++++++++++++++++++++++++++++ drivers/rapidio/rio.h | 57 +++++ include/asm-generic/vmlinux.lds.h | 7 + 12 files changed, 1393 insertions(+), 1 deletion(-) create mode 100644 Documentation/DocBook/rapidio.tmpl create mode 100644 drivers/rapidio/Kconfig create mode 100644 drivers/rapidio/Makefile create mode 100644 drivers/rapidio/rio-access.c create mode 100644 drivers/rapidio/rio-driver.c create mode 100644 drivers/rapidio/rio-sysfs.c create mode 100644 drivers/rapidio/rio.c create mode 100644 drivers/rapidio/rio.h diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index fa3e29ad8a4..7018f5c6a44 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -10,7 +10,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \ kernel-hacking.xml kernel-locking.xml deviceiobook.xml \ procfs-guide.xml writing_usb_driver.xml \ sis900.xml kernel-api.xml journal-api.xml lsm.xml usb.xml \ - gadget.xml libata.xml mtdnand.xml librs.xml + gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml ### # The build process is as follows (targets): diff --git a/Documentation/DocBook/rapidio.tmpl b/Documentation/DocBook/rapidio.tmpl new file mode 100644 index 00000000000..1becf27ba27 --- /dev/null +++ b/Documentation/DocBook/rapidio.tmpl @@ -0,0 +1,160 @@ + + + ]> + + + + RapidIO Subsystem Guide + + + + Matt + Porter + +
+ mporter@kernel.crashing.org + mporter@mvista.com +
+
+
+
+ + + 2005 + MontaVista Software, Inc. + + + + + This documentation is free software; you can redistribute + it and/or modify it under the terms of the GNU General Public + License version 2 as published by the Free Software Foundation. + + + + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + + + + For more details see the file COPYING in the source + distribution of Linux. + + +
+ + + + + Introduction + + RapidIO is a high speed switched fabric interconnect with + features aimed at the embedded market. RapidIO provides + support for memory-mapped I/O as well as message-based + transactions over the switched fabric network. RapidIO has + a standardized discovery mechanism not unlike the PCI bus + standard that allows simple detection of devices in a + network. + + + This documentation is provided for developers intending + to support RapidIO on new architectures, write new drivers, + or to understand the subsystem internals. + + + + + Known Bugs and Limitations + + + Bugs + None. ;) + + + Limitations + + + Access/management of RapidIO memory regions is not supported + Multiple host enumeration is not supported + + + + + + + RapidIO driver interface + + Drivers are provided a set of calls in order + to interface with the subsystem to gather info + on devices, request/map memory region resources, + and manage mailboxes/doorbells. + + + Functions +!Iinclude/linux/rio_drv.h +!Edrivers/rapidio/rio-driver.c +!Edrivers/rapidio/rio.c + + + + + Internals + + + This chapter contains the autogenerated documentation of the RapidIO + subsystem. + + + Structures +!Iinclude/linux/rio.h + + Enumeration and Discovery +!Idrivers/rapidio/rio-scan.c + + Driver functionality +!Idrivers/rapidio/rio.c +!Idrivers/rapidio/rio-access.c + + Device model support +!Idrivers/rapidio/rio-driver.c + + Sysfs support +!Idrivers/rapidio/rio-sysfs.c + + PPC32 support +!Iarch/ppc/kernel/rio.c +!Earch/ppc/syslib/ppc85xx_rio.c +!Iarch/ppc/syslib/ppc85xx_rio.c + + + + + Credits + + The following people have contributed to the RapidIO + subsystem directly or indirectly: + + Matt Portermporter@kernel.crashing.org + Randy Vinsonrvinson@mvista.com + Dan Malekdan@embeddedalley.com + + + + The following people have contributed to this document: + + Matt Portermporter@kernel.crashing.org + + + +
diff --git a/MAINTAINERS b/MAINTAINERS index 4cba302c275..3ccbfa96eee 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2071,6 +2071,12 @@ P: Matt Mackall M: mpm@selenic.com S: Maintained +RAPIDIO SUBSYSTEM +P: Matt Porter +M: mporter@kernel.crashing.org +L: linux-kernel@vger.kernel.org +S: Maintained + REAL TIME CLOCK DRIVER P: Paul Gortmaker M: p_gortmaker@yahoo.com diff --git a/drivers/Makefile b/drivers/Makefile index 61c64f76836..fac1e160309 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_PCI) += pci/ usb/ obj-$(CONFIG_PARISC) += parisc/ +obj-$(CONFIG_RAPIDIO) += rapidio/ obj-y += video/ obj-$(CONFIG_ACPI) += acpi/ # PnP must come after ACPI since it will eventually need to check if acpi diff --git a/drivers/rapidio/Kconfig b/drivers/rapidio/Kconfig new file mode 100644 index 00000000000..0b2d2c3579a --- /dev/null +++ b/drivers/rapidio/Kconfig @@ -0,0 +1,18 @@ +# +# RapidIO configuration +# +config RAPIDIO_8_BIT_TRANSPORT + bool "8-bit transport addressing" + depends on RAPIDIO + ---help--- + By default, the kernel assumes a 16-bit addressed RapidIO + network. By selecting this option, the kernel will support + an 8-bit addressed network. + +config RAPIDIO_DISC_TIMEOUT + int "Discovery timeout duration (seconds)" + depends on RAPIDIO + default "30" + ---help--- + Amount of time a discovery node waits for a host to complete + enumeration beforing giving up. diff --git a/drivers/rapidio/Makefile b/drivers/rapidio/Makefile new file mode 100644 index 00000000000..7c0e1818de5 --- /dev/null +++ b/drivers/rapidio/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for RapidIO interconnect services +# +obj-y += rio.o rio-access.o rio-driver.o rio-scan.o rio-sysfs.o + +obj-$(CONFIG_RAPIDIO) += switches/ diff --git a/drivers/rapidio/rio-access.c b/drivers/rapidio/rio-access.c new file mode 100644 index 00000000000..b9fab2ae3a3 --- /dev/null +++ b/drivers/rapidio/rio-access.c @@ -0,0 +1,175 @@ +/* + * RapidIO configuration space access support + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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 + * option) any later version. + */ + +#include +#include + +/* + * These interrupt-safe spinlocks protect all accesses to RIO + * configuration space and doorbell access. + */ +static spinlock_t rio_config_lock = SPIN_LOCK_UNLOCKED; +static spinlock_t rio_doorbell_lock = SPIN_LOCK_UNLOCKED; + +/* + * Wrappers for all RIO configuration access functions. They just check + * alignment, do locking and call the low-level functions pointed to + * by rio_mport->ops. + */ + +#define RIO_8_BAD 0 +#define RIO_16_BAD (offset & 1) +#define RIO_32_BAD (offset & 3) + +/** + * RIO_LOP_READ - Generate rio_local_read_config_* functions + * @size: Size of configuration space read (8, 16, 32 bits) + * @type: C type of value argument + * @len: Length of configuration space read (1, 2, 4 bytes) + * + * Generates rio_local_read_config_* functions used to access + * configuration space registers on the local device. + */ +#define RIO_LOP_READ(size,type,len) \ +int __rio_local_read_config_##size \ + (struct rio_mport *mport, u32 offset, type *value) \ +{ \ + int res; \ + unsigned long flags; \ + u32 data = 0; \ + if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ + spin_lock_irqsave(&rio_config_lock, flags); \ + res = mport->ops->lcread(mport->id, offset, len, &data); \ + *value = (type)data; \ + spin_unlock_irqrestore(&rio_config_lock, flags); \ + return res; \ +} + +/** + * RIO_LOP_WRITE - Generate rio_local_write_config_* functions + * @size: Size of configuration space write (8, 16, 32 bits) + * @type: C type of value argument + * @len: Length of configuration space write (1, 2, 4 bytes) + * + * Generates rio_local_write_config_* functions used to access + * configuration space registers on the local device. + */ +#define RIO_LOP_WRITE(size,type,len) \ +int __rio_local_write_config_##size \ + (struct rio_mport *mport, u32 offset, type value) \ +{ \ + int res; \ + unsigned long flags; \ + if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ + spin_lock_irqsave(&rio_config_lock, flags); \ + res = mport->ops->lcwrite(mport->id, offset, len, value); \ + spin_unlock_irqrestore(&rio_config_lock, flags); \ + return res; \ +} + +RIO_LOP_READ(8, u8, 1) +RIO_LOP_READ(16, u16, 2) +RIO_LOP_READ(32, u32, 4) +RIO_LOP_WRITE(8, u8, 1) +RIO_LOP_WRITE(16, u16, 2) +RIO_LOP_WRITE(32, u32, 4) + +EXPORT_SYMBOL_GPL(__rio_local_read_config_8); +EXPORT_SYMBOL_GPL(__rio_local_read_config_16); +EXPORT_SYMBOL_GPL(__rio_local_read_config_32); +EXPORT_SYMBOL_GPL(__rio_local_write_config_8); +EXPORT_SYMBOL_GPL(__rio_local_write_config_16); +EXPORT_SYMBOL_GPL(__rio_local_write_config_32); + +/** + * RIO_OP_READ - Generate rio_mport_read_config_* functions + * @size: Size of configuration space read (8, 16, 32 bits) + * @type: C type of value argument + * @len: Length of configuration space read (1, 2, 4 bytes) + * + * Generates rio_mport_read_config_* functions used to access + * configuration space registers on the local device. + */ +#define RIO_OP_READ(size,type,len) \ +int rio_mport_read_config_##size \ + (struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type *value) \ +{ \ + int res; \ + unsigned long flags; \ + u32 data = 0; \ + if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ + spin_lock_irqsave(&rio_config_lock, flags); \ + res = mport->ops->cread(mport->id, destid, hopcount, offset, len, &data); \ + *value = (type)data; \ + spin_unlock_irqrestore(&rio_config_lock, flags); \ + return res; \ +} + +/** + * RIO_OP_WRITE - Generate rio_mport_write_config_* functions + * @size: Size of configuration space write (8, 16, 32 bits) + * @type: C type of value argument + * @len: Length of configuration space write (1, 2, 4 bytes) + * + * Generates rio_mport_write_config_* functions used to access + * configuration space registers on the local device. + */ +#define RIO_OP_WRITE(size,type,len) \ +int rio_mport_write_config_##size \ + (struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type value) \ +{ \ + int res; \ + unsigned long flags; \ + if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ + spin_lock_irqsave(&rio_config_lock, flags); \ + res = mport->ops->cwrite(mport->id, destid, hopcount, offset, len, value); \ + spin_unlock_irqrestore(&rio_config_lock, flags); \ + return res; \ +} + +RIO_OP_READ(8, u8, 1) +RIO_OP_READ(16, u16, 2) +RIO_OP_READ(32, u32, 4) +RIO_OP_WRITE(8, u8, 1) +RIO_OP_WRITE(16, u16, 2) +RIO_OP_WRITE(32, u32, 4) + +EXPORT_SYMBOL_GPL(rio_mport_read_config_8); +EXPORT_SYMBOL_GPL(rio_mport_read_config_16); +EXPORT_SYMBOL_GPL(rio_mport_read_config_32); +EXPORT_SYMBOL_GPL(rio_mport_write_config_8); +EXPORT_SYMBOL_GPL(rio_mport_write_config_16); +EXPORT_SYMBOL_GPL(rio_mport_write_config_32); + +/** + * rio_mport_send_doorbell - Send a doorbell message + * + * @mport: RIO master port + * @destid: RIO device destination ID + * @data: Doorbell message data + * + * Send a doorbell message to a RIO device. The doorbell message + * has a 16-bit info field provided by the data argument. + */ +int rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, u16 data) +{ + int res; + unsigned long flags; + + spin_lock_irqsave(&rio_doorbell_lock, flags); + res = mport->ops->dsend(mport->id, destid, data); + spin_unlock_irqrestore(&rio_doorbell_lock, flags); + + return res; +} + +EXPORT_SYMBOL_GPL(rio_mport_send_doorbell); diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c new file mode 100644 index 00000000000..dc749609699 --- /dev/null +++ b/drivers/rapidio/rio-driver.c @@ -0,0 +1,229 @@ +/* + * RapidIO driver support + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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 + * option) any later version. + */ + +#include +#include +#include +#include + +#include "rio.h" + +/** + * rio_match_device - Tell if a RIO device has a matching RIO device id structure + * @id: the RIO device id structure to match against + * @rdev: the RIO device structure to match against + * + * Used from driver probe and bus matching to check whether a RIO device + * matches a device id structure provided by a RIO driver. Returns the + * matching &struct rio_device_id or %NULL if there is no match. + */ +static const struct rio_device_id *rio_match_device(const struct rio_device_id + *id, + const struct rio_dev *rdev) +{ + while (id->vid || id->asm_vid) { + if (((id->vid == RIO_ANY_ID) || (id->vid == rdev->vid)) && + ((id->did == RIO_ANY_ID) || (id->did == rdev->did)) && + ((id->asm_vid == RIO_ANY_ID) + || (id->asm_vid == rdev->asm_vid)) + && ((id->asm_did == RIO_ANY_ID) + || (id->asm_did == rdev->asm_did))) + return id; + id++; + } + return NULL; +} + +/** + * rio_dev_get - Increments the reference count of the RIO device structure + * + * @rdev: RIO device being referenced + * + * Each live reference to a device should be refcounted. + * + * Drivers for RIO devices should normally record such references in + * their probe() methods, when they bind to a device, and release + * them by calling rio_dev_put(), in their disconnect() methods. + */ +struct rio_dev *rio_dev_get(struct rio_dev *rdev) +{ + if (rdev) + get_device(&rdev->dev); + + return rdev; +} + +/** + * rio_dev_put - Release a use of the RIO device structure + * + * @rdev: RIO device being disconnected + * + * Must be called when a user of a device is finished with it. + * When the last user of the device calls this function, the + * memory of the device is freed. + */ +void rio_dev_put(struct rio_dev *rdev) +{ + if (rdev) + put_device(&rdev->dev); +} + +/** + * rio_device_probe - Tell if a RIO device structure has a matching RIO + * device id structure + * @id: the RIO device id structure to match against + * @dev: the RIO device structure to match against + * + * return 0 and set rio_dev->driver when drv claims rio_dev, else error + */ +static int rio_device_probe(struct device *dev) +{ + struct rio_driver *rdrv = to_rio_driver(dev->driver); + struct rio_dev *rdev = to_rio_dev(dev); + int error = -ENODEV; + const struct rio_device_id *id; + + if (!rdev->driver && rdrv->probe) { + if (!rdrv->id_table) + return error; + id = rio_match_device(rdrv->id_table, rdev); + rio_dev_get(rdev); + if (id) + error = rdrv->probe(rdev, id); + if (error >= 0) { + rdev->driver = rdrv; + error = 0; + rio_dev_put(rdev); + } + } + return error; +} + +/** + * rio_device_remove - Remove a RIO device from the system + * + * @dev: the RIO device structure to match against + * + * Remove a RIO device from the system. If it has an associated + * driver, then run the driver remove() method. Then update + * the reference count. + */ +static int rio_device_remove(struct device *dev) +{ + struct rio_dev *rdev = to_rio_dev(dev); + struct rio_driver *rdrv = rdev->driver; + + if (rdrv) { + if (rdrv->remove) + rdrv->remove(rdev); + rdev->driver = NULL; + } + + rio_dev_put(rdev); + + return 0; +} + +/** + * rio_register_driver - register a new RIO driver + * @rdrv: the RIO driver structure to register + * + * Adds a &struct rio_driver to the list of registered drivers + * Returns a negative value on error, otherwise 0. If no error + * occurred, the driver remains registered even if no device + * was claimed during registration. + */ +int rio_register_driver(struct rio_driver *rdrv) +{ + /* initialize common driver fields */ + rdrv->driver.name = rdrv->name; + rdrv->driver.bus = &rio_bus_type; + rdrv->driver.probe = rio_device_probe; + rdrv->driver.remove = rio_device_remove; + + /* register with core */ + return driver_register(&rdrv->driver); +} + +/** + * rio_unregister_driver - unregister a RIO driver + * @rdrv: the RIO driver structure to unregister + * + * Deletes the &struct rio_driver from the list of registered RIO + * drivers, gives it a chance to clean up by calling its remove() + * function for each device it was responsible for, and marks those + * devices as driverless. + */ +void rio_unregister_driver(struct rio_driver *rdrv) +{ + driver_unregister(&rdrv->driver); +} + +/** + * rio_match_bus - Tell if a RIO device structure has a matching RIO + * driver device id structure + * @dev: the standard device structure to match against + * @drv: the standard driver structure containing the ids to match against + * + * Used by a driver to check whether a RIO device present in the + * system is in its list of supported devices. Returns 1 if + * there is a matching &struct rio_device_id or 0 if there is + * no match. + */ +static int rio_match_bus(struct device *dev, struct device_driver *drv) +{ + struct rio_dev *rdev = to_rio_dev(dev); + struct rio_driver *rdrv = to_rio_driver(drv); + const struct rio_device_id *id = rdrv->id_table; + const struct rio_device_id *found_id; + + if (!id) + goto out; + + found_id = rio_match_device(id, rdev); + + if (found_id) + return 1; + + out:return 0; +} + +static struct device rio_bus = { + .bus_id = "rapidio", +}; + +struct bus_type rio_bus_type = { + .name = "rapidio", + .match = rio_match_bus, + .dev_attrs = rio_dev_attrs +}; + +/** + * rio_bus_init - Register the RapidIO bus with the device model + * + * Registers the RIO bus device and RIO bus type with the Linux + * device model. + */ +static int __init rio_bus_init(void) +{ + if (device_register(&rio_bus) < 0) + printk("RIO: failed to register RIO bus device\n"); + return bus_register(&rio_bus_type); +} + +postcore_initcall(rio_bus_init); + +EXPORT_SYMBOL_GPL(rio_register_driver); +EXPORT_SYMBOL_GPL(rio_unregister_driver); +EXPORT_SYMBOL_GPL(rio_bus_type); +EXPORT_SYMBOL_GPL(rio_dev_get); +EXPORT_SYMBOL_GPL(rio_dev_put); diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c new file mode 100644 index 00000000000..73218a37506 --- /dev/null +++ b/drivers/rapidio/rio-sysfs.c @@ -0,0 +1,230 @@ +/* + * RapidIO sysfs attributes and support + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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 + * option) any later version. + */ + +#include +#include +#include +#include +#include + +#include "rio.h" + +/* Sysfs support */ +#define rio_config_attr(field, format_string) \ +static ssize_t \ + field##_show(struct device *dev, char *buf) \ +{ \ + struct rio_dev *rdev = to_rio_dev(dev); \ + \ + return sprintf(buf, format_string, rdev->field); \ +} \ + +rio_config_attr(did, "0x%04x\n"); +rio_config_attr(vid, "0x%04x\n"); +rio_config_attr(device_rev, "0x%08x\n"); +rio_config_attr(asm_did, "0x%04x\n"); +rio_config_attr(asm_vid, "0x%04x\n"); +rio_config_attr(asm_rev, "0x%04x\n"); + +static ssize_t routes_show(struct device *dev, char *buf) +{ + struct rio_dev *rdev = to_rio_dev(dev); + char *str = buf; + int i; + + if (!rdev->rswitch) + goto out; + + for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++) { + if (rdev->rswitch->route_table[i] == RIO_INVALID_ROUTE) + continue; + str += + sprintf(str, "%04x %02x\n", i, + rdev->rswitch->route_table[i]); + } + + out: + return (str - buf); +} + +struct device_attribute rio_dev_attrs[] = { + __ATTR_RO(did), + __ATTR_RO(vid), + __ATTR_RO(device_rev), + __ATTR_RO(asm_did), + __ATTR_RO(asm_vid), + __ATTR_RO(asm_rev), + __ATTR_RO(routes), + __ATTR_NULL, +}; + +static ssize_t +rio_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count) +{ + struct rio_dev *dev = + to_rio_dev(container_of(kobj, struct device, kobj)); + unsigned int size = 0x100; + loff_t init_off = off; + u8 *data = (u8 *) buf; + + /* Several chips lock up trying to read undefined config space */ + if (capable(CAP_SYS_ADMIN)) + size = 0x200000; + + if (off > size) + return 0; + if (off + count > size) { + size -= off; + count = size; + } else { + size = count; + } + + if ((off & 1) && size) { + u8 val; + rio_read_config_8(dev, off, &val); + data[off - init_off] = val; + off++; + size--; + } + + if ((off & 3) && size > 2) { + u16 val; + rio_read_config_16(dev, off, &val); + data[off - init_off] = (val >> 8) & 0xff; + data[off - init_off + 1] = val & 0xff; + off += 2; + size -= 2; + } + + while (size > 3) { + u32 val; + rio_read_config_32(dev, off, &val); + data[off - init_off] = (val >> 24) & 0xff; + data[off - init_off + 1] = (val >> 16) & 0xff; + data[off - init_off + 2] = (val >> 8) & 0xff; + data[off - init_off + 3] = val & 0xff; + off += 4; + size -= 4; + } + + if (size >= 2) { + u16 val; + rio_read_config_16(dev, off, &val); + data[off - init_off] = (val >> 8) & 0xff; + data[off - init_off + 1] = val & 0xff; + off += 2; + size -= 2; + } + + if (size > 0) { + u8 val; + rio_read_config_8(dev, off, &val); + data[off - init_off] = val; + off++; + --size; + } + + return count; +} + +static ssize_t +rio_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count) +{ + struct rio_dev *dev = + to_rio_dev(container_of(kobj, struct device, kobj)); + unsigned int size = count; + loff_t init_off = off; + u8 *data = (u8 *) buf; + + if (off > 0x200000) + return 0; + if (off + count > 0x200000) { + size = 0x200000 - off; + count = size; + } + + if ((off & 1) && size) { + rio_write_config_8(dev, off, data[off - init_off]); + off++; + size--; + } + + if ((off & 3) && (size > 2)) { + u16 val = data[off - init_off + 1]; + val |= (u16) data[off - init_off] << 8; + rio_write_config_16(dev, off, val); + off += 2; + size -= 2; + } + + while (size > 3) { + u32 val = data[off - init_off + 3]; + val |= (u32) data[off - init_off + 2] << 8; + val |= (u32) data[off - init_off + 1] << 16; + val |= (u32) data[off - init_off] << 24; + rio_write_config_32(dev, off, val); + off += 4; + size -= 4; + } + + if (size >= 2) { + u16 val = data[off - init_off + 1]; + val |= (u16) data[off - init_off] << 8; + rio_write_config_16(dev, off, val); + off += 2; + size -= 2; + } + + if (size) { + rio_write_config_8(dev, off, data[off - init_off]); + off++; + --size; + } + + return count; +} + +static struct bin_attribute rio_config_attr = { + .attr = { + .name = "config", + .mode = S_IRUGO | S_IWUSR, + .owner = THIS_MODULE, + }, + .size = 0x200000, + .read = rio_read_config, + .write = rio_write_config, +}; + +/** + * rio_create_sysfs_dev_files - create RIO specific sysfs files + * @rdev: device whose entries should be created + * + * Create files when @rdev is added to sysfs. + */ +int rio_create_sysfs_dev_files(struct rio_dev *rdev) +{ + sysfs_create_bin_file(&rdev->dev.kobj, &rio_config_attr); + + return 0; +} + +/** + * rio_remove_sysfs_dev_files - cleanup RIO specific sysfs files + * @rdev: device whose entries we should free + * + * Cleanup when @rdev is removed from sysfs. + */ +void rio_remove_sysfs_dev_files(struct rio_dev *rdev) +{ + sysfs_remove_bin_file(&rdev->dev.kobj, &rio_config_attr); +} diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c new file mode 100644 index 00000000000..adc299e2b07 --- /dev/null +++ b/drivers/rapidio/rio.c @@ -0,0 +1,503 @@ +/* + * RapidIO interconnect services + * (RapidIO Interconnect Specification, http://www.rapidio.org) + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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 + * option) any later version. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rio.h" + +static LIST_HEAD(rio_mports); + +/** + * rio_local_get_device_id - Get the base/extended device id for a port + * @port: RIO master port from which to get the deviceid + * + * Reads the base/extended device id from the local device + * implementing the master port. Returns the 8/16-bit device + * id. + */ +u16 rio_local_get_device_id(struct rio_mport *port) +{ + u32 result; + + rio_local_read_config_32(port, RIO_DID_CSR, &result); + + return (RIO_GET_DID(result)); +} + +/** + * rio_request_inb_mbox - request inbound mailbox service + * @mport: RIO master port from which to allocate the mailbox resource + * @mbox: Mailbox number to claim + * @entries: Number of entries in inbound mailbox queue + * @minb: Callback to execute when inbound message is received + * + * Requests ownership of an inbound mailbox resource and binds + * a callback function to the resource. Returns %0 on success. + */ +int rio_request_inb_mbox(struct rio_mport *mport, + int mbox, + int entries, + void (*minb) (struct rio_mport * mport, int mbox, + int slot)) +{ + int rc = 0; + + struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL); + + if (res) { + rio_init_mbox_res(res, mbox, mbox); + + /* Make sure this mailbox isn't in use */ + if ((rc = + request_resource(&mport->riores[RIO_INB_MBOX_RESOURCE], + res)) < 0) { + kfree(res); + goto out; + } + + mport->inb_msg[mbox].res = res; + + /* Hook the inbound message callback */ + mport->inb_msg[mbox].mcback = minb; + + rc = rio_open_inb_mbox(mport, mbox, entries); + } else + rc = -ENOMEM; + + out: + return rc; +} + +/** + * rio_release_inb_mbox - release inbound mailbox message service + * @mport: RIO master port from which to release the mailbox resource + * @mbox: Mailbox number to release + * + * Releases ownership of an inbound mailbox resource. Returns 0 + * if the request has been satisfied. + */ +int rio_release_inb_mbox(struct rio_mport *mport, int mbox) +{ + rio_close_inb_mbox(mport, mbox); + + /* Release the mailbox resource */ + return release_resource(mport->inb_msg[mbox].res); +} + +/** + * rio_request_outb_mbox - request outbound mailbox service + * @mport: RIO master port from which to allocate the mailbox resource + * @mbox: Mailbox number to claim + * @entries: Number of entries in outbound mailbox queue + * @moutb: Callback to execute when outbound message is sent + * + * Requests ownership of an outbound mailbox resource and binds + * a callback function to the resource. Returns 0 on success. + */ +int rio_request_outb_mbox(struct rio_mport *mport, + int mbox, + int entries, + void (*moutb) (struct rio_mport * mport, int mbox, + int slot)) +{ + int rc = 0; + + struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL); + + if (res) { + rio_init_mbox_res(res, mbox, mbox); + + /* Make sure this outbound mailbox isn't in use */ + if ((rc = + request_resource(&mport->riores[RIO_OUTB_MBOX_RESOURCE], + res)) < 0) { + kfree(res); + goto out; + } + + mport->outb_msg[mbox].res = res; + + /* Hook the inbound message callback */ + mport->outb_msg[mbox].mcback = moutb; + + rc = rio_open_outb_mbox(mport, mbox, entries); + } else + rc = -ENOMEM; + + out: + return rc; +} + +/** + * rio_release_outb_mbox - release outbound mailbox message service + * @mport: RIO master port from which to release the mailbox resource + * @mbox: Mailbox number to release + * + * Releases ownership of an inbound mailbox resource. Returns 0 + * if the request has been satisfied. + */ +int rio_release_outb_mbox(struct rio_mport *mport, int mbox) +{ + rio_close_outb_mbox(mport, mbox); + + /* Release the mailbox resource */ + return release_resource(mport->outb_msg[mbox].res); +} + +/** + * rio_setup_inb_dbell - bind inbound doorbell callback + * @mport: RIO master port to bind the doorbell callback + * @res: Doorbell message resource + * @dinb: Callback to execute when doorbell is received + * + * Adds a doorbell resource/callback pair into a port's + * doorbell event list. Returns 0 if the request has been + * satisfied. + */ +static int +rio_setup_inb_dbell(struct rio_mport *mport, struct resource *res, + void (*dinb) (struct rio_mport * mport, u16 src, u16 dst, + u16 info)) +{ + int rc = 0; + struct rio_dbell *dbell; + + if (!(dbell = kmalloc(sizeof(struct rio_dbell), GFP_KERNEL))) { + rc = -ENOMEM; + goto out; + } + + dbell->res = res; + dbell->dinb = dinb; + + list_add_tail(&dbell->node, &mport->dbells); + + out: + return rc; +} + +/** + * rio_request_inb_dbell - request inbound doorbell message service + * @mport: RIO master port from which to allocate the doorbell resource + * @start: Doorbell info range start + * @end: Doorbell info range end + * @dinb: Callback to execute when doorbell is received + * + * Requests ownership of an inbound doorbell resource and binds + * a callback function to the resource. Returns 0 if the request + * has been satisfied. + */ +int rio_request_inb_dbell(struct rio_mport *mport, + u16 start, + u16 end, + void (*dinb) (struct rio_mport * mport, u16 src, + u16 dst, u16 info)) +{ + int rc = 0; + + struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL); + + if (res) { + rio_init_dbell_res(res, start, end); + + /* Make sure these doorbells aren't in use */ + if ((rc = + request_resource(&mport->riores[RIO_DOORBELL_RESOURCE], + res)) < 0) { + kfree(res); + goto out; + } + + /* Hook the doorbell callback */ + rc = rio_setup_inb_dbell(mport, res, dinb); + } else + rc = -ENOMEM; + + out: + return rc; +} + +/** + * rio_release_inb_dbell - release inbound doorbell message service + * @mport: RIO master port from which to release the doorbell resource + * @start: Doorbell info range start + * @end: Doorbell info range end + * + * Releases ownership of an inbound doorbell resource and removes + * callback from the doorbell event list. Returns 0 if the request + * has been satisfied. + */ +int rio_release_inb_dbell(struct rio_mport *mport, u16 start, u16 end) +{ + int rc = 0, found = 0; + struct rio_dbell *dbell; + + list_for_each_entry(dbell, &mport->dbells, node) { + if ((dbell->res->start == start) && (dbell->res->end == end)) { + found = 1; + break; + } + } + + /* If we can't find an exact match, fail */ + if (!found) { + rc = -EINVAL; + goto out; + } + + /* Delete from list */ + list_del(&dbell->node); + + /* Release the doorbell resource */ + rc = release_resource(dbell->res); + + /* Free the doorbell event */ + kfree(dbell); + + out: + return rc; +} + +/** + * rio_request_outb_dbell - request outbound doorbell message range + * @rdev: RIO device from which to allocate the doorbell resource + * @start: Doorbell message range start + * @end: Doorbell message range end + * + * Requests ownership of a doorbell message range. Returns a resource + * if the request has been satisfied or %NULL on failure. + */ +struct resource *rio_request_outb_dbell(struct rio_dev *rdev, u16 start, + u16 end) +{ + struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL); + + if (res) { + rio_init_dbell_res(res, start, end); + + /* Make sure these doorbells aren't in use */ + if (request_resource(&rdev->riores[RIO_DOORBELL_RESOURCE], res) + < 0) { + kfree(res); + res = NULL; + } + } + + return res; +} + +/** + * rio_release_outb_dbell - release outbound doorbell message range + * @rdev: RIO device from which to release the doorbell resource + * @res: Doorbell resource to be freed + * + * Releases ownership of a doorbell message range. Returns 0 if the + * request has been satisfied. + */ +int rio_release_outb_dbell(struct rio_dev *rdev, struct resource *res) +{ + int rc = release_resource(res); + + kfree(res); + + return rc; +} + +/** + * rio_mport_get_feature - query for devices' extended features + * @port: Master port to issue transaction + * @local: Indicate a local master port or remote device access + * @destid: Destination ID of the device + * @hopcount: Number of switch hops to the device + * @ftr: Extended feature code + * + * Tell if a device supports a given RapidIO capability. + * Returns the offset of the requested extended feature + * block within the device's RIO configuration space or + * 0 in case the device does not support it. Possible + * values for @ftr: + * + * %RIO_EFB_PAR_EP_ID LP/LVDS EP Devices + * + * %RIO_EFB_PAR_EP_REC_ID LP/LVDS EP Recovery Devices + * + * %RIO_EFB_PAR_EP_FREE_ID LP/LVDS EP Free Devices + * + * %RIO_EFB_SER_EP_ID LP/Serial EP Devices + * + * %RIO_EFB_SER_EP_REC_ID LP/Serial EP Recovery Devices + * + * %RIO_EFB_SER_EP_FREE_ID LP/Serial EP Free Devices + */ +u32 +rio_mport_get_feature(struct rio_mport * port, int local, u16 destid, + u8 hopcount, int ftr) +{ + u32 asm_info, ext_ftr_ptr, ftr_header; + + if (local) + rio_local_read_config_32(port, RIO_ASM_INFO_CAR, &asm_info); + else + rio_mport_read_config_32(port, destid, hopcount, + RIO_ASM_INFO_CAR, &asm_info); + + ext_ftr_ptr = asm_info & RIO_EXT_FTR_PTR_MASK; + + while (ext_ftr_ptr) { + if (local) + rio_local_read_config_32(port, ext_ftr_ptr, + &ftr_header); + else + rio_mport_read_config_32(port, destid, hopcount, + ext_ftr_ptr, &ftr_header); + if (RIO_GET_BLOCK_ID(ftr_header) == ftr) + return ext_ftr_ptr; + if (!(ext_ftr_ptr = RIO_GET_BLOCK_PTR(ftr_header))) + break; + } + + return 0; +} + +/** + * rio_get_asm - Begin or continue searching for a RIO device by vid/did/asm_vid/asm_did + * @vid: RIO vid to match or %RIO_ANY_ID to match all vids + * @did: RIO did to match or %RIO_ANY_ID to match all dids + * @asm_vid: RIO asm_vid to match or %RIO_ANY_ID to match all asm_vids + * @asm_did: RIO asm_did to match or %RIO_ANY_ID to match all asm_dids + * @from: Previous RIO device found in search, or %NULL for new search + * + * Iterates through the list of known RIO devices. If a RIO device is + * found with a matching @vid, @did, @asm_vid, @asm_did, the reference + * count to the device is incrememted and a pointer to its device + * structure is returned. Otherwise, %NULL is returned. A new search + * is initiated by passing %NULL to the @from argument. Otherwise, if + * @from is not %NULL, searches continue from next device on the global + * list. The reference count for @from is always decremented if it is + * not %NULL. + */ +struct rio_dev *rio_get_asm(u16 vid, u16 did, + u16 asm_vid, u16 asm_did, struct rio_dev *from) +{ + struct list_head *n; + struct rio_dev *rdev; + + WARN_ON(in_interrupt()); + spin_lock(&rio_global_list_lock); + n = from ? from->global_list.next : rio_devices.next; + + while (n && (n != &rio_devices)) { + rdev = rio_dev_g(n); + if ((vid == RIO_ANY_ID || rdev->vid == vid) && + (did == RIO_ANY_ID || rdev->did == did) && + (asm_vid == RIO_ANY_ID || rdev->asm_vid == asm_vid) && + (asm_did == RIO_ANY_ID || rdev->asm_did == asm_did)) + goto exit; + n = n->next; + } + rdev = NULL; + exit: + rio_dev_put(from); + rdev = rio_dev_get(rdev); + spin_unlock(&rio_global_list_lock); + return rdev; +} + +/** + * rio_get_device - Begin or continue searching for a RIO device by vid/did + * @vid: RIO vid to match or %RIO_ANY_ID to match all vids + * @did: RIO did to match or %RIO_ANY_ID to match all dids + * @from: Previous RIO device found in search, or %NULL for new search + * + * Iterates through the list of known RIO devices. If a RIO device is + * found with a matching @vid and @did, the reference count to the + * device is incrememted and a pointer to its device structure is returned. + * Otherwise, %NULL is returned. A new search is initiated by passing %NULL + * to the @from argument. Otherwise, if @from is not %NULL, searches + * continue from next device on the global list. The reference count for + * @from is always decremented if it is not %NULL. + */ +struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from) +{ + return rio_get_asm(vid, did, RIO_ANY_ID, RIO_ANY_ID, from); +} + +static void rio_fixup_device(struct rio_dev *dev) +{ +} + +static int __devinit rio_init(void) +{ + struct rio_dev *dev = NULL; + + while ((dev = rio_get_device(RIO_ANY_ID, RIO_ANY_ID, dev)) != NULL) { + rio_fixup_device(dev); + } + return 0; +} + +device_initcall(rio_init); + +int rio_init_mports(void) +{ + int rc = 0; + struct rio_mport *port; + + list_for_each_entry(port, &rio_mports, node) { + if (!request_mem_region(port->iores.start, + port->iores.end - port->iores.start, + port->name)) { + printk(KERN_ERR + "RIO: Error requesting master port region %8.8lx-%8.8lx\n", + port->iores.start, port->iores.end - 1); + rc = -ENOMEM; + goto out; + } + + if (port->host_deviceid >= 0) + rio_enum_mport(port); + else + rio_disc_mport(port); + } + + out: + return rc; +} + +void rio_register_mport(struct rio_mport *port) +{ + list_add_tail(&port->node, &rio_mports); +} + +EXPORT_SYMBOL_GPL(rio_local_get_device_id); +EXPORT_SYMBOL_GPL(rio_get_device); +EXPORT_SYMBOL_GPL(rio_get_asm); +EXPORT_SYMBOL_GPL(rio_request_inb_dbell); +EXPORT_SYMBOL_GPL(rio_release_inb_dbell); +EXPORT_SYMBOL_GPL(rio_request_outb_dbell); +EXPORT_SYMBOL_GPL(rio_release_outb_dbell); +EXPORT_SYMBOL_GPL(rio_request_inb_mbox); +EXPORT_SYMBOL_GPL(rio_release_inb_mbox); +EXPORT_SYMBOL_GPL(rio_request_outb_mbox); +EXPORT_SYMBOL_GPL(rio_release_outb_mbox); diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h new file mode 100644 index 00000000000..f865a68cd3d --- /dev/null +++ b/drivers/rapidio/rio.h @@ -0,0 +1,57 @@ +/* + * RapidIO interconnect services + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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 + * option) any later version. + */ + +#include +#include +#include + +/* Functions internal to the RIO core code */ + +extern u32 rio_mport_get_feature(struct rio_mport *mport, int local, u16 destid, + u8 hopcount, int ftr); +extern int rio_create_sysfs_dev_files(struct rio_dev *rdev); +extern int rio_enum_mport(struct rio_mport *mport); +extern int rio_disc_mport(struct rio_mport *mport); + +/* Structures internal to the RIO core code */ +extern struct device_attribute rio_dev_attrs[]; +extern spinlock_t rio_global_list_lock; + +/* Helpers internal to the RIO core code */ +#define DECLARE_RIO_ROUTE_SECTION(section, vid, did, add_hook, get_hook) \ + static struct rio_route_ops __rio_route_ops __attribute_used__ \ + __attribute__((__section__(#section))) = { vid, did, add_hook, get_hook }; + +/** + * DECLARE_RIO_ROUTE_OPS - Registers switch routing operations + * @vid: RIO vendor ID + * @did: RIO device ID + * @add_hook: Callback that adds a route entry + * @get_hook: Callback that gets a route entry + * + * Manipulating switch route tables in RIO is switch specific. This + * registers a switch by vendor and device ID with two callbacks for + * modifying and retrieving route entries in a switch. A &struct + * rio_route_ops is initialized with the ops and placed into a + * RIO-specific kernel section. + */ +#define DECLARE_RIO_ROUTE_OPS(vid, did, add_hook, get_hook) \ + DECLARE_RIO_ROUTE_SECTION(.rio_route_ops, \ + vid, did, add_hook, get_hook) + +#ifdef CONFIG_RAPIDIO_8_BIT_TRANSPORT +#define RIO_GET_DID(x) ((x & 0x00ff0000) >> 16) +#define RIO_SET_DID(x) ((x & 0x000000ff) << 16) +#else +#define RIO_GET_DID(x) (x & 0xffff) +#define RIO_SET_DID(x) (x & 0xffff) +#endif diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index a9c55490fb8..094d4917c1a 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -35,6 +35,13 @@ VMLINUX_SYMBOL(__end_pci_fixups_enable) = .; \ } \ \ + /* RapidIO route ops */ \ + .rio_route : AT(ADDR(.rio_route) - LOAD_OFFSET) { \ + VMLINUX_SYMBOL(__start_rio_route_ops) = .; \ + *(.rio_route_ops) \ + VMLINUX_SYMBOL(__end_rio_route_ops) = .; \ + } \ + \ /* Kernel symbol table: Normal symbols */ \ __ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \ VMLINUX_SYMBOL(__start___ksymtab) = .; \ -- cgit v1.2.3 From 70a50ebd9a94533964c19f918dbbd66763e3f9e5 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 7 Nov 2005 01:00:16 -0800 Subject: [PATCH] RapidIO support: core includes Add RapidIO core include files. The core code implements enumeration/discovery, management of devices/resources, and interfaces for RIO drivers. Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/rio.h | 321 ++++++++++++++++++++++++++++++++ include/linux/rio_drv.h | 469 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/rio_ids.h | 24 +++ include/linux/rio_regs.h | 202 ++++++++++++++++++++ 4 files changed, 1016 insertions(+) create mode 100644 include/linux/rio.h create mode 100644 include/linux/rio_drv.h create mode 100644 include/linux/rio_ids.h create mode 100644 include/linux/rio_regs.h diff --git a/include/linux/rio.h b/include/linux/rio.h new file mode 100644 index 00000000000..930bbb7c380 --- /dev/null +++ b/include/linux/rio.h @@ -0,0 +1,321 @@ +/* + * RapidIO interconnect services + * (RapidIO Interconnect Specification, http://www.rapidio.org) + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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 + * option) any later version. + */ + +#ifndef LINUX_RIO_H +#define LINUX_RIO_H + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include +#include +#include + +#define RIO_ANY_DESTID 0xff +#define RIO_NO_HOPCOUNT -1 + +#define RIO_MAX_MPORT_RESOURCES 16 +#define RIO_MAX_DEV_RESOURCES 16 + +#define RIO_GLOBAL_TABLE 0xff /* Indicates access of a switch's + global routing table if it + has multiple (or per port) + tables */ + +#define RIO_INVALID_ROUTE 0xff /* Indicates that a route table + entry is invalid (no route + exists for the device ID) */ + +#ifdef CONFIG_RAPIDIO_8_BIT_TRANSPORT +#define RIO_MAX_ROUTE_ENTRIES (1 << 8) +#else +#define RIO_MAX_ROUTE_ENTRIES (1 << 16) +#endif + +#define RIO_MAX_MBOX 4 +#define RIO_MAX_MSG_SIZE 0x1000 + +/* + * Error values that may be returned by RIO functions. + */ +#define RIO_SUCCESSFUL 0x00 +#define RIO_BAD_SIZE 0x81 + +/* + * For RIO devices, the region numbers are assigned this way: + * + * 0 RapidIO outbound doorbells + * 1-15 RapidIO memory regions + * + * For RIO master ports, the region number are assigned this way: + * + * 0 RapidIO inbound doorbells + * 1 RapidIO inbound mailboxes + * 1 RapidIO outbound mailboxes + */ +#define RIO_DOORBELL_RESOURCE 0 +#define RIO_INB_MBOX_RESOURCE 1 +#define RIO_OUTB_MBOX_RESOURCE 2 + +extern struct bus_type rio_bus_type; +extern struct list_head rio_devices; /* list of all devices */ + +struct rio_mport; + +/** + * struct rio_dev - RIO device info + * @global_list: Node in list of all RIO devices + * @net_list: Node in list of RIO devices in a network + * @net: Network this device is a part of + * @did: Device ID + * @vid: Vendor ID + * @device_rev: Device revision + * @asm_did: Assembly device ID + * @asm_vid: Assembly vendor ID + * @asm_rev: Assembly revision + * @efptr: Extended feature pointer + * @pef: Processing element features + * @swpinfo: Switch port info + * @src_ops: Source operation capabilities + * @dst_ops: Destination operation capabilities + * @rswitch: Pointer to &struct rio_switch if valid for this device + * @driver: Driver claiming this device + * @dev: Device model device + * @riores: RIO resources this device owns + * @destid: Network destination ID + */ +struct rio_dev { + struct list_head global_list; /* node in list of all RIO devices */ + struct list_head net_list; /* node in per net list */ + struct rio_net *net; /* RIO net this device resides in */ + u16 did; + u16 vid; + u32 device_rev; + u16 asm_did; + u16 asm_vid; + u16 asm_rev; + u16 efptr; + u32 pef; + u32 swpinfo; /* Only used for switches */ + u32 src_ops; + u32 dst_ops; + struct rio_switch *rswitch; /* RIO switch info */ + struct rio_driver *driver; /* RIO driver claiming this device */ + struct device dev; /* LDM device structure */ + struct resource riores[RIO_MAX_DEV_RESOURCES]; + u16 destid; +}; + +#define rio_dev_g(n) list_entry(n, struct rio_dev, global_list) +#define rio_dev_f(n) list_entry(n, struct rio_dev, net_list) +#define to_rio_dev(n) container_of(n, struct rio_dev, dev) + +/** + * struct rio_msg - RIO message event + * @res: Mailbox resource + * @mcback: Message event callback + */ +struct rio_msg { + struct resource *res; + void (*mcback) (struct rio_mport * mport, int mbox, int slot); +}; + +/** + * struct rio_dbell - RIO doorbell event + * @node: Node in list of doorbell events + * @res: Doorbell resource + * @dinb: Doorbell event callback + */ +struct rio_dbell { + struct list_head node; + struct resource *res; + void (*dinb) (struct rio_mport * mport, u16 src, u16 dst, u16 info); +}; + +/** + * struct rio_mport - RIO master port info + * @dbells: List of doorbell events + * @node: Node in global list of master ports + * @nnode: Node in network list of master ports + * @iores: I/O mem resource that this master port interface owns + * @riores: RIO resources that this master port interfaces owns + * @inb_msg: RIO inbound message event descriptors + * @outb_msg: RIO outbound message event descriptors + * @host_deviceid: Host device ID associated with this master port + * @ops: configuration space functions + * @id: Port ID, unique among all ports + * @index: Port index, unique among all port interfaces of the same type + * @name: Port name string + */ +struct rio_mport { + struct list_head dbells; /* list of doorbell events */ + struct list_head node; /* node in global list of ports */ + struct list_head nnode; /* node in net list of ports */ + struct resource iores; + struct resource riores[RIO_MAX_MPORT_RESOURCES]; + struct rio_msg inb_msg[RIO_MAX_MBOX]; + struct rio_msg outb_msg[RIO_MAX_MBOX]; + int host_deviceid; /* Host device ID */ + struct rio_ops *ops; /* maintenance transaction functions */ + unsigned char id; /* port ID, unique among all ports */ + unsigned char index; /* port index, unique among all port + interfaces of the same type */ + unsigned char name[40]; +}; + +/** + * struct rio_net - RIO network info + * @node: Node in global list of RIO networks + * @devices: List of devices in this network + * @mports: List of master ports accessing this network + * @hport: Default port for accessing this network + * @id: RIO network ID + */ +struct rio_net { + struct list_head node; /* node in list of networks */ + struct list_head devices; /* list of devices in this net */ + struct list_head mports; /* list of ports accessing net */ + struct rio_mport *hport; /* primary port for accessing net */ + unsigned char id; /* RIO network ID */ +}; + +/** + * struct rio_switch - RIO switch info + * @node: Node in global list of switches + * @switchid: Switch ID that is unique across a network + * @hopcount: Hopcount to this switch + * @destid: Associated destid in the path + * @route_table: Copy of switch routing table + * @add_entry: Callback for switch-specific route add function + * @get_entry: Callback for switch-specific route get function + */ +struct rio_switch { + struct list_head node; + u16 switchid; + u16 hopcount; + u16 destid; + u8 route_table[RIO_MAX_ROUTE_ENTRIES]; + int (*add_entry) (struct rio_mport * mport, u16 destid, u8 hopcount, + u16 table, u16 route_destid, u8 route_port); + int (*get_entry) (struct rio_mport * mport, u16 destid, u8 hopcount, + u16 table, u16 route_destid, u8 * route_port); +}; + +/* Low-level architecture-dependent routines */ + +/** + * struct rio_ops - Low-level RIO configuration space operations + * @lcread: Callback to perform local (master port) read of config space. + * @lcwrite: Callback to perform local (master port) write of config space. + * @cread: Callback to perform network read of config space. + * @cwrite: Callback to perform network write of config space. + * @dsend: Callback to send a doorbell message. + */ +struct rio_ops { + int (*lcread) (int index, u32 offset, int len, u32 * data); + int (*lcwrite) (int index, u32 offset, int len, u32 data); + int (*cread) (int index, u16 destid, u8 hopcount, u32 offset, int len, + u32 * data); + int (*cwrite) (int index, u16 destid, u8 hopcount, u32 offset, int len, + u32 data); + int (*dsend) (int index, u16 destid, u16 data); +}; + +#define RIO_RESOURCE_MEM 0x00000100 +#define RIO_RESOURCE_DOORBELL 0x00000200 +#define RIO_RESOURCE_MAILBOX 0x00000400 + +#define RIO_RESOURCE_CACHEABLE 0x00010000 +#define RIO_RESOURCE_PCI 0x00020000 + +#define RIO_RESOURCE_BUSY 0x80000000 + +/** + * struct rio_driver - RIO driver info + * @node: Node in list of drivers + * @name: RIO driver name + * @id_table: RIO device ids to be associated with this driver + * @probe: RIO device inserted + * @remove: RIO device removed + * @suspend: RIO device suspended + * @resume: RIO device awakened + * @enable_wake: RIO device enable wake event + * @driver: LDM driver struct + * + * Provides info on a RIO device driver for insertion/removal and + * power management purposes. + */ +struct rio_driver { + struct list_head node; + char *name; + const struct rio_device_id *id_table; + int (*probe) (struct rio_dev * dev, const struct rio_device_id * id); + void (*remove) (struct rio_dev * dev); + int (*suspend) (struct rio_dev * dev, u32 state); + int (*resume) (struct rio_dev * dev); + int (*enable_wake) (struct rio_dev * dev, u32 state, int enable); + struct device_driver driver; +}; + +#define to_rio_driver(drv) container_of(drv,struct rio_driver, driver) + +/** + * struct rio_device_id - RIO device identifier + * @did: RIO device ID + * @vid: RIO vendor ID + * @asm_did: RIO assembly device ID + * @asm_vid: RIO assembly vendor ID + * + * Identifies a RIO device based on both the device/vendor IDs and + * the assembly device/vendor IDs. + */ +struct rio_device_id { + u16 did, vid; + u16 asm_did, asm_vid; +}; + +/** + * struct rio_route_ops - Per-switch route operations + * @vid: RIO vendor ID + * @did: RIO device ID + * @add_hook: Callback that adds a route entry + * @get_hook: Callback that gets a route entry + * + * Defines the operations that are necessary to manipulate the route + * tables for a particular RIO switch device. + */ +struct rio_route_ops { + u16 vid, did; + int (*add_hook) (struct rio_mport * mport, u16 destid, u8 hopcount, + u16 table, u16 route_destid, u8 route_port); + int (*get_hook) (struct rio_mport * mport, u16 destid, u8 hopcount, + u16 table, u16 route_destid, u8 * route_port); +}; + +/* Architecture and hardware-specific functions */ +extern int rio_init_mports(void); +extern void rio_register_mport(struct rio_mport *); +extern int rio_hw_add_outb_message(struct rio_mport *, struct rio_dev *, int, + void *, size_t); +extern int rio_hw_add_inb_buffer(struct rio_mport *, int, void *); +extern void *rio_hw_get_inb_message(struct rio_mport *, int); +extern int rio_open_inb_mbox(struct rio_mport *, int, int); +extern void rio_close_inb_mbox(struct rio_mport *, int); +extern int rio_open_outb_mbox(struct rio_mport *, int, int); +extern void rio_close_outb_mbox(struct rio_mport *, int); + +#endif /* __KERNEL__ */ +#endif /* LINUX_RIO_H */ diff --git a/include/linux/rio_drv.h b/include/linux/rio_drv.h new file mode 100644 index 00000000000..7483dfc0dfa --- /dev/null +++ b/include/linux/rio_drv.h @@ -0,0 +1,469 @@ +/* + * RapidIO driver services + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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 + * option) any later version. + */ + +#ifndef LINUX_RIO_DRV_H +#define LINUX_RIO_DRV_H + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include +#include +#include + +extern int __rio_local_read_config_32(struct rio_mport *port, u32 offset, + u32 * data); +extern int __rio_local_write_config_32(struct rio_mport *port, u32 offset, + u32 data); +extern int __rio_local_read_config_16(struct rio_mport *port, u32 offset, + u16 * data); +extern int __rio_local_write_config_16(struct rio_mport *port, u32 offset, + u16 data); +extern int __rio_local_read_config_8(struct rio_mport *port, u32 offset, + u8 * data); +extern int __rio_local_write_config_8(struct rio_mport *port, u32 offset, + u8 data); + +extern int rio_mport_read_config_32(struct rio_mport *port, u16 destid, + u8 hopcount, u32 offset, u32 * data); +extern int rio_mport_write_config_32(struct rio_mport *port, u16 destid, + u8 hopcount, u32 offset, u32 data); +extern int rio_mport_read_config_16(struct rio_mport *port, u16 destid, + u8 hopcount, u32 offset, u16 * data); +extern int rio_mport_write_config_16(struct rio_mport *port, u16 destid, + u8 hopcount, u32 offset, u16 data); +extern int rio_mport_read_config_8(struct rio_mport *port, u16 destid, + u8 hopcount, u32 offset, u8 * data); +extern int rio_mport_write_config_8(struct rio_mport *port, u16 destid, + u8 hopcount, u32 offset, u8 data); + +/** + * rio_local_read_config_32 - Read 32 bits from local configuration space + * @port: Master port + * @offset: Offset into local configuration space + * @data: Pointer to read data into + * + * Reads 32 bits of data from the specified offset within the local + * device's configuration space. + */ +static inline int rio_local_read_config_32(struct rio_mport *port, u32 offset, + u32 * data) +{ + return __rio_local_read_config_32(port, offset, data); +} + +/** + * rio_local_write_config_32 - Write 32 bits to local configuration space + * @port: Master port + * @offset: Offset into local configuration space + * @data: Data to be written + * + * Writes 32 bits of data to the specified offset within the local + * device's configuration space. + */ +static inline int rio_local_write_config_32(struct rio_mport *port, u32 offset, + u32 data) +{ + return __rio_local_write_config_32(port, offset, data); +} + +/** + * rio_local_read_config_16 - Read 16 bits from local configuration space + * @port: Master port + * @offset: Offset into local configuration space + * @data: Pointer to read data into + * + * Reads 16 bits of data from the specified offset within the local + * device's configuration space. + */ +static inline int rio_local_read_config_16(struct rio_mport *port, u32 offset, + u16 * data) +{ + return __rio_local_read_config_16(port, offset, data); +} + +/** + * rio_local_write_config_16 - Write 16 bits to local configuration space + * @port: Master port + * @offset: Offset into local configuration space + * @data: Data to be written + * + * Writes 16 bits of data to the specified offset within the local + * device's configuration space. + */ + +static inline int rio_local_write_config_16(struct rio_mport *port, u32 offset, + u16 data) +{ + return __rio_local_write_config_16(port, offset, data); +} + +/** + * rio_local_read_config_8 - Read 8 bits from local configuration space + * @port: Master port + * @offset: Offset into local configuration space + * @data: Pointer to read data into + * + * Reads 8 bits of data from the specified offset within the local + * device's configuration space. + */ +static inline int rio_local_read_config_8(struct rio_mport *port, u32 offset, + u8 * data) +{ + return __rio_local_read_config_8(port, offset, data); +} + +/** + * rio_local_write_config_8 - Write 8 bits to local configuration space + * @port: Master port + * @offset: Offset into local configuration space + * @data: Data to be written + * + * Writes 8 bits of data to the specified offset within the local + * device's configuration space. + */ +static inline int rio_local_write_config_8(struct rio_mport *port, u32 offset, + u8 data) +{ + return __rio_local_write_config_8(port, offset, data); +} + +/** + * rio_read_config_32 - Read 32 bits from configuration space + * @rdev: RIO device + * @offset: Offset into device configuration space + * @data: Pointer to read data into + * + * Reads 32 bits of data from the specified offset within the + * RIO device's configuration space. + */ +static inline int rio_read_config_32(struct rio_dev *rdev, u32 offset, + u32 * data) +{ + u8 hopcount = 0xff; + u16 destid = rdev->destid; + + if (rdev->rswitch) { + destid = rdev->rswitch->destid; + hopcount = rdev->rswitch->hopcount; + } + + return rio_mport_read_config_32(rdev->net->hport, destid, hopcount, + offset, data); +}; + +/** + * rio_write_config_32 - Write 32 bits to configuration space + * @rdev: RIO device + * @offset: Offset into device configuration space + * @data: Data to be written + * + * Writes 32 bits of data to the specified offset within the + * RIO device's configuration space. + */ +static inline int rio_write_config_32(struct rio_dev *rdev, u32 offset, + u32 data) +{ + u8 hopcount = 0xff; + u16 destid = rdev->destid; + + if (rdev->rswitch) { + destid = rdev->rswitch->destid; + hopcount = rdev->rswitch->hopcount; + } + + return rio_mport_write_config_32(rdev->net->hport, destid, hopcount, + offset, data); +}; + +/** + * rio_read_config_16 - Read 16 bits from configuration space + * @rdev: RIO device + * @offset: Offset into device configuration space + * @data: Pointer to read data into + * + * Reads 16 bits of data from the specified offset within the + * RIO device's configuration space. + */ +static inline int rio_read_config_16(struct rio_dev *rdev, u32 offset, + u16 * data) +{ + u8 hopcount = 0xff; + u16 destid = rdev->destid; + + if (rdev->rswitch) { + destid = rdev->rswitch->destid; + hopcount = rdev->rswitch->hopcount; + } + + return rio_mport_read_config_16(rdev->net->hport, destid, hopcount, + offset, data); +}; + +/** + * rio_write_config_16 - Write 16 bits to configuration space + * @rdev: RIO device + * @offset: Offset into device configuration space + * @data: Data to be written + * + * Writes 16 bits of data to the specified offset within the + * RIO device's configuration space. + */ +static inline int rio_write_config_16(struct rio_dev *rdev, u32 offset, + u16 data) +{ + u8 hopcount = 0xff; + u16 destid = rdev->destid; + + if (rdev->rswitch) { + destid = rdev->rswitch->destid; + hopcount = rdev->rswitch->hopcount; + } + + return rio_mport_write_config_16(rdev->net->hport, destid, hopcount, + offset, data); +}; + +/** + * rio_read_config_8 - Read 8 bits from configuration space + * @rdev: RIO device + * @offset: Offset into device configuration space + * @data: Pointer to read data into + * + * Reads 8 bits of data from the specified offset within the + * RIO device's configuration space. + */ +static inline int rio_read_config_8(struct rio_dev *rdev, u32 offset, u8 * data) +{ + u8 hopcount = 0xff; + u16 destid = rdev->destid; + + if (rdev->rswitch) { + destid = rdev->rswitch->destid; + hopcount = rdev->rswitch->hopcount; + } + + return rio_mport_read_config_8(rdev->net->hport, destid, hopcount, + offset, data); +}; + +/** + * rio_write_config_8 - Write 8 bits to configuration space + * @rdev: RIO device + * @offset: Offset into device configuration space + * @data: Data to be written + * + * Writes 8 bits of data to the specified offset within the + * RIO device's configuration space. + */ +static inline int rio_write_config_8(struct rio_dev *rdev, u32 offset, u8 data) +{ + u8 hopcount = 0xff; + u16 destid = rdev->destid; + + if (rdev->rswitch) { + destid = rdev->rswitch->destid; + hopcount = rdev->rswitch->hopcount; + } + + return rio_mport_write_config_8(rdev->net->hport, destid, hopcount, + offset, data); +}; + +extern int rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, + u16 data); + +/** + * rio_send_doorbell - Send a doorbell message to a device + * @rdev: RIO device + * @data: Doorbell message data + * + * Send a doorbell message to a RIO device. The doorbell message + * has a 16-bit info field provided by the @data argument. + */ +static inline int rio_send_doorbell(struct rio_dev *rdev, u16 data) +{ + return rio_mport_send_doorbell(rdev->net->hport, rdev->destid, data); +}; + +/** + * rio_init_mbox_res - Initialize a RIO mailbox resource + * @res: resource struct + * @start: start of mailbox range + * @end: end of mailbox range + * + * This function is used to initialize the fields of a resource + * for use as a mailbox resource. It initializes a range of + * mailboxes using the start and end arguments. + */ +static inline void rio_init_mbox_res(struct resource *res, int start, int end) +{ + memset(res, 0, sizeof(struct resource)); + res->start = start; + res->end = end; + res->flags = RIO_RESOURCE_MAILBOX; +} + +/** + * rio_init_dbell_res - Initialize a RIO doorbell resource + * @res: resource struct + * @start: start of doorbell range + * @end: end of doorbell range + * + * This function is used to initialize the fields of a resource + * for use as a doorbell resource. It initializes a range of + * doorbell messages using the start and end arguments. + */ +static inline void rio_init_dbell_res(struct resource *res, u16 start, u16 end) +{ + memset(res, 0, sizeof(struct resource)); + res->start = start; + res->end = end; + res->flags = RIO_RESOURCE_DOORBELL; +} + +/** + * RIO_DEVICE - macro used to describe a specific RIO device + * @vid: the 16 bit RIO vendor ID + * @did: the 16 bit RIO device ID + * + * This macro is used to create a struct rio_device_id that matches a + * specific device. The assembly vendor and assembly device fields + * will be set to %RIO_ANY_ID. + */ +#define RIO_DEVICE(dev,ven) \ + .did = (dev), .vid = (ven), \ + .asm_did = RIO_ANY_ID, .asm_vid = RIO_ANY_ID + +/* Mailbox management */ +extern int rio_request_outb_mbox(struct rio_mport *, int, int, + void (*)(struct rio_mport *, int, int)); +extern int rio_release_outb_mbox(struct rio_mport *, int); + +/** + * rio_add_outb_message - Add RIO message to an outbound mailbox queue + * @mport: RIO master port containing the outbound queue + * @rdev: RIO device the message is be sent to + * @mbox: The outbound mailbox queue + * @buffer: Pointer to the message buffer + * @len: Length of the message buffer + * + * Adds a RIO message buffer to an outbound mailbox queue for + * transmission. Returns 0 on success. + */ +static inline int rio_add_outb_message(struct rio_mport *mport, + struct rio_dev *rdev, int mbox, + void *buffer, size_t len) +{ + return rio_hw_add_outb_message(mport, rdev, mbox, buffer, len); +} + +extern int rio_request_inb_mbox(struct rio_mport *, int, int, + void (*)(struct rio_mport *, int, int)); +extern int rio_release_inb_mbox(struct rio_mport *, int); + +/** + * rio_add_inb_buffer - Add buffer to an inbound mailbox queue + * @mport: Master port containing the inbound mailbox + * @mbox: The inbound mailbox number + * @buffer: Pointer to the message buffer + * + * Adds a buffer to an inbound mailbox queue for reception. Returns + * 0 on success. + */ +static inline int rio_add_inb_buffer(struct rio_mport *mport, int mbox, + void *buffer) +{ + return rio_hw_add_inb_buffer(mport, mbox, buffer); +} + +/** + * rio_get_inb_message - Get A RIO message from an inbound mailbox queue + * @mport: Master port containing the inbound mailbox + * @mbox: The inbound mailbox number + * @buffer: Pointer to the message buffer + * + * Get a RIO message from an inbound mailbox queue. Returns 0 on success. + */ +static inline void *rio_get_inb_message(struct rio_mport *mport, int mbox) +{ + return rio_hw_get_inb_message(mport, mbox); +} + +/* Doorbell management */ +extern int rio_request_inb_dbell(struct rio_mport *, u16, u16, + void (*)(struct rio_mport *, u16, u16, u16)); +extern int rio_release_inb_dbell(struct rio_mport *, u16, u16); +extern struct resource *rio_request_outb_dbell(struct rio_dev *, u16, u16); +extern int rio_release_outb_dbell(struct rio_dev *, struct resource *); + +/* Memory region management */ +int rio_claim_resource(struct rio_dev *, int); +int rio_request_regions(struct rio_dev *, char *); +void rio_release_regions(struct rio_dev *); +int rio_request_region(struct rio_dev *, int, char *); +void rio_release_region(struct rio_dev *, int); + +/* LDM support */ +int rio_register_driver(struct rio_driver *); +void rio_unregister_driver(struct rio_driver *); +struct rio_dev *rio_dev_get(struct rio_dev *); +void rio_dev_put(struct rio_dev *); + +/** + * rio_name - Get the unique RIO device identifier + * @rdev: RIO device + * + * Get the unique RIO device identifier. Returns the device + * identifier string. + */ +static inline char *rio_name(struct rio_dev *rdev) +{ + return rdev->dev.bus_id; +} + +/** + * rio_get_drvdata - Get RIO driver specific data + * @rdev: RIO device + * + * Get RIO driver specific data. Returns a pointer to the + * driver specific data. + */ +static inline void *rio_get_drvdata(struct rio_dev *rdev) +{ + return dev_get_drvdata(&rdev->dev); +} + +/** + * rio_set_drvdata - Set RIO driver specific data + * @rdev: RIO device + * @data: Pointer to driver specific data + * + * Set RIO driver specific data. device struct driver data pointer + * is set to the @data argument. + */ +static inline void rio_set_drvdata(struct rio_dev *rdev, void *data) +{ + dev_set_drvdata(&rdev->dev, data); +} + +/* Misc driver helpers */ +extern u16 rio_local_get_device_id(struct rio_mport *port); +extern struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from); +extern struct rio_dev *rio_get_asm(u16 vid, u16 did, u16 asm_vid, u16 asm_did, + struct rio_dev *from); + +#endif /* __KERNEL__ */ +#endif /* LINUX_RIO_DRV_H */ diff --git a/include/linux/rio_ids.h b/include/linux/rio_ids.h new file mode 100644 index 00000000000..919d4e07d54 --- /dev/null +++ b/include/linux/rio_ids.h @@ -0,0 +1,24 @@ +/* + * RapidIO devices + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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 + * option) any later version. + */ + +#ifndef LINUX_RIO_IDS_H +#define LINUX_RIO_IDS_H + +#define RIO_ANY_ID 0xffff + +#define RIO_VID_FREESCALE 0x0002 +#define RIO_DID_MPC8560 0x0003 + +#define RIO_VID_TUNDRA 0x000d +#define RIO_DID_TSI500 0x0500 + +#endif /* LINUX_RIO_IDS_H */ diff --git a/include/linux/rio_regs.h b/include/linux/rio_regs.h new file mode 100644 index 00000000000..f419be3be49 --- /dev/null +++ b/include/linux/rio_regs.h @@ -0,0 +1,202 @@ +/* + * RapidIO register definitions + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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 + * option) any later version. + */ + +#ifndef LINUX_RIO_REGS_H +#define LINUX_RIO_REGS_H + +/* + * In RapidIO, each device has a 2MB configuration space that is + * accessed via maintenance transactions. Portions of configuration + * space are standardized and/or reserved. + */ +#define RIO_DEV_ID_CAR 0x00 /* [I] Device Identity CAR */ +#define RIO_DEV_INFO_CAR 0x04 /* [I] Device Information CAR */ +#define RIO_ASM_ID_CAR 0x08 /* [I] Assembly Identity CAR */ +#define RIO_ASM_ID_MASK 0xffff0000 /* [I] Asm ID Mask */ +#define RIO_ASM_VEN_ID_MASK 0x0000ffff /* [I] Asm Vend Mask */ + +#define RIO_ASM_INFO_CAR 0x0c /* [I] Assembly Information CAR */ +#define RIO_ASM_REV_MASK 0xffff0000 /* [I] Asm Rev Mask */ +#define RIO_EXT_FTR_PTR_MASK 0x0000ffff /* [I] EF_PTR Mask */ + +#define RIO_PEF_CAR 0x10 /* [I] Processing Element Features CAR */ +#define RIO_PEF_BRIDGE 0x80000000 /* [I] Bridge */ +#define RIO_PEF_MEMORY 0x40000000 /* [I] MMIO */ +#define RIO_PEF_PROCESSOR 0x20000000 /* [I] Processor */ +#define RIO_PEF_SWITCH 0x10000000 /* [I] Switch */ +#define RIO_PEF_INB_MBOX 0x00f00000 /* [II] Mailboxes */ +#define RIO_PEF_INB_MBOX0 0x00800000 /* [II] Mailbox 0 */ +#define RIO_PEF_INB_MBOX1 0x00400000 /* [II] Mailbox 1 */ +#define RIO_PEF_INB_MBOX2 0x00200000 /* [II] Mailbox 2 */ +#define RIO_PEF_INB_MBOX3 0x00100000 /* [II] Mailbox 3 */ +#define RIO_PEF_INB_DOORBELL 0x00080000 /* [II] Doorbells */ +#define RIO_PEF_CTLS 0x00000010 /* [III] CTLS */ +#define RIO_PEF_EXT_FEATURES 0x00000008 /* [I] EFT_PTR valid */ +#define RIO_PEF_ADDR_66 0x00000004 /* [I] 66 bits */ +#define RIO_PEF_ADDR_50 0x00000002 /* [I] 50 bits */ +#define RIO_PEF_ADDR_34 0x00000001 /* [I] 34 bits */ + +#define RIO_SWP_INFO_CAR 0x14 /* [I] Switch Port Information CAR */ +#define RIO_SWP_INFO_PORT_TOTAL_MASK 0x0000ff00 /* [I] Total number of ports */ +#define RIO_SWP_INFO_PORT_NUM_MASK 0x000000ff /* [I] Maintenance transaction port number */ +#define RIO_GET_TOTAL_PORTS(x) ((x & RIO_SWP_INFO_PORT_TOTAL_MASK) >> 8) + +#define RIO_SRC_OPS_CAR 0x18 /* [I] Source Operations CAR */ +#define RIO_SRC_OPS_READ 0x00008000 /* [I] Read op */ +#define RIO_SRC_OPS_WRITE 0x00004000 /* [I] Write op */ +#define RIO_SRC_OPS_STREAM_WRITE 0x00002000 /* [I] Str-write op */ +#define RIO_SRC_OPS_WRITE_RESPONSE 0x00001000 /* [I] Write/resp op */ +#define RIO_SRC_OPS_DATA_MSG 0x00000800 /* [II] Data msg op */ +#define RIO_SRC_OPS_DOORBELL 0x00000400 /* [II] Doorbell op */ +#define RIO_SRC_OPS_ATOMIC_TST_SWP 0x00000100 /* [I] Atomic TAS op */ +#define RIO_SRC_OPS_ATOMIC_INC 0x00000080 /* [I] Atomic inc op */ +#define RIO_SRC_OPS_ATOMIC_DEC 0x00000040 /* [I] Atomic dec op */ +#define RIO_SRC_OPS_ATOMIC_SET 0x00000020 /* [I] Atomic set op */ +#define RIO_SRC_OPS_ATOMIC_CLR 0x00000010 /* [I] Atomic clr op */ +#define RIO_SRC_OPS_PORT_WRITE 0x00000004 /* [I] Port-write op */ + +#define RIO_DST_OPS_CAR 0x1c /* Destination Operations CAR */ +#define RIO_DST_OPS_READ 0x00008000 /* [I] Read op */ +#define RIO_DST_OPS_WRITE 0x00004000 /* [I] Write op */ +#define RIO_DST_OPS_STREAM_WRITE 0x00002000 /* [I] Str-write op */ +#define RIO_DST_OPS_WRITE_RESPONSE 0x00001000 /* [I] Write/resp op */ +#define RIO_DST_OPS_DATA_MSG 0x00000800 /* [II] Data msg op */ +#define RIO_DST_OPS_DOORBELL 0x00000400 /* [II] Doorbell op */ +#define RIO_DST_OPS_ATOMIC_TST_SWP 0x00000100 /* [I] Atomic TAS op */ +#define RIO_DST_OPS_ATOMIC_INC 0x00000080 /* [I] Atomic inc op */ +#define RIO_DST_OPS_ATOMIC_DEC 0x00000040 /* [I] Atomic dec op */ +#define RIO_DST_OPS_ATOMIC_SET 0x00000020 /* [I] Atomic set op */ +#define RIO_DST_OPS_ATOMIC_CLR 0x00000010 /* [I] Atomic clr op */ +#define RIO_DST_OPS_PORT_WRITE 0x00000004 /* [I] Port-write op */ + + /* 0x20-0x3c *//* Reserved */ + +#define RIO_MBOX_CSR 0x40 /* [II] Mailbox CSR */ +#define RIO_MBOX0_AVAIL 0x80000000 /* [II] Mbox 0 avail */ +#define RIO_MBOX0_FULL 0x40000000 /* [II] Mbox 0 full */ +#define RIO_MBOX0_EMPTY 0x20000000 /* [II] Mbox 0 empty */ +#define RIO_MBOX0_BUSY 0x10000000 /* [II] Mbox 0 busy */ +#define RIO_MBOX0_FAIL 0x08000000 /* [II] Mbox 0 fail */ +#define RIO_MBOX0_ERROR 0x04000000 /* [II] Mbox 0 error */ +#define RIO_MBOX1_AVAIL 0x00800000 /* [II] Mbox 1 avail */ +#define RIO_MBOX1_FULL 0x00200000 /* [II] Mbox 1 full */ +#define RIO_MBOX1_EMPTY 0x00200000 /* [II] Mbox 1 empty */ +#define RIO_MBOX1_BUSY 0x00100000 /* [II] Mbox 1 busy */ +#define RIO_MBOX1_FAIL 0x00080000 /* [II] Mbox 1 fail */ +#define RIO_MBOX1_ERROR 0x00040000 /* [II] Mbox 1 error */ +#define RIO_MBOX2_AVAIL 0x00008000 /* [II] Mbox 2 avail */ +#define RIO_MBOX2_FULL 0x00004000 /* [II] Mbox 2 full */ +#define RIO_MBOX2_EMPTY 0x00002000 /* [II] Mbox 2 empty */ +#define RIO_MBOX2_BUSY 0x00001000 /* [II] Mbox 2 busy */ +#define RIO_MBOX2_FAIL 0x00000800 /* [II] Mbox 2 fail */ +#define RIO_MBOX2_ERROR 0x00000400 /* [II] Mbox 2 error */ +#define RIO_MBOX3_AVAIL 0x00000080 /* [II] Mbox 3 avail */ +#define RIO_MBOX3_FULL 0x00000040 /* [II] Mbox 3 full */ +#define RIO_MBOX3_EMPTY 0x00000020 /* [II] Mbox 3 empty */ +#define RIO_MBOX3_BUSY 0x00000010 /* [II] Mbox 3 busy */ +#define RIO_MBOX3_FAIL 0x00000008 /* [II] Mbox 3 fail */ +#define RIO_MBOX3_ERROR 0x00000004 /* [II] Mbox 3 error */ + +#define RIO_WRITE_PORT_CSR 0x44 /* [I] Write Port CSR */ +#define RIO_DOORBELL_CSR 0x44 /* [II] Doorbell CSR */ +#define RIO_DOORBELL_AVAIL 0x80000000 /* [II] Doorbell avail */ +#define RIO_DOORBELL_FULL 0x40000000 /* [II] Doorbell full */ +#define RIO_DOORBELL_EMPTY 0x20000000 /* [II] Doorbell empty */ +#define RIO_DOORBELL_BUSY 0x10000000 /* [II] Doorbell busy */ +#define RIO_DOORBELL_FAILED 0x08000000 /* [II] Doorbell failed */ +#define RIO_DOORBELL_ERROR 0x04000000 /* [II] Doorbell error */ +#define RIO_WRITE_PORT_AVAILABLE 0x00000080 /* [I] Write Port Available */ +#define RIO_WRITE_PORT_FULL 0x00000040 /* [I] Write Port Full */ +#define RIO_WRITE_PORT_EMPTY 0x00000020 /* [I] Write Port Empty */ +#define RIO_WRITE_PORT_BUSY 0x00000010 /* [I] Write Port Busy */ +#define RIO_WRITE_PORT_FAILED 0x00000008 /* [I] Write Port Failed */ +#define RIO_WRITE_PORT_ERROR 0x00000004 /* [I] Write Port Error */ + + /* 0x48 *//* Reserved */ + +#define RIO_PELL_CTRL_CSR 0x4c /* [I] PE Logical Layer Control CSR */ +#define RIO_PELL_ADDR_66 0x00000004 /* [I] 66-bit addr */ +#define RIO_PELL_ADDR_50 0x00000002 /* [I] 50-bit addr */ +#define RIO_PELL_ADDR_34 0x00000001 /* [I] 34-bit addr */ + + /* 0x50-0x54 *//* Reserved */ + +#define RIO_LCSH_BA 0x58 /* [I] LCS High Base Address */ +#define RIO_LCSL_BA 0x5c /* [I] LCS Base Address */ + +#define RIO_DID_CSR 0x60 /* [III] Base Device ID CSR */ + + /* 0x64 *//* Reserved */ + +#define RIO_HOST_DID_LOCK_CSR 0x68 /* [III] Host Base Device ID Lock CSR */ +#define RIO_COMPONENT_TAG_CSR 0x6c /* [III] Component Tag CSR */ + + /* 0x70-0xf8 *//* Reserved */ + /* 0x100-0xfff8 *//* [I] Extended Features Space */ + /* 0x10000-0xfffff8 *//* [I] Implementation-defined Space */ + +/* + * Extended Features Space is a configuration space area where + * functionality is mapped into extended feature blocks via a + * singly linked list of extended feature pointers (EFT_PTR). + * + * Each extended feature block can be identified/located in + * Extended Features Space by walking the extended feature + * list starting with the Extended Feature Pointer located + * in the Assembly Information CAR. + * + * Extended Feature Blocks (EFBs) are identified with an assigned + * EFB ID. Extended feature block offsets in the definitions are + * relative to the offset of the EFB within the Extended Features + * Space. + */ + +/* Helper macros to parse the Extended Feature Block header */ +#define RIO_EFB_PTR_MASK 0xffff0000 +#define RIO_EFB_ID_MASK 0x0000ffff +#define RIO_GET_BLOCK_PTR(x) ((x & RIO_EFB_PTR_MASK) >> 16) +#define RIO_GET_BLOCK_ID(x) (x & RIO_EFB_ID_MASK) + +/* Extended Feature Block IDs */ +#define RIO_EFB_PAR_EP_ID 0x0001 /* [IV] LP/LVDS EP Devices */ +#define RIO_EFB_PAR_EP_REC_ID 0x0002 /* [IV] LP/LVDS EP Recovery Devices */ +#define RIO_EFB_PAR_EP_FREE_ID 0x0003 /* [IV] LP/LVDS EP Free Devices */ +#define RIO_EFB_SER_EP_ID 0x0004 /* [VI] LP/Serial EP Devices */ +#define RIO_EFB_SER_EP_REC_ID 0x0005 /* [VI] LP/Serial EP Recovery Devices */ +#define RIO_EFB_SER_EP_FREE_ID 0x0006 /* [VI] LP/Serial EP Free Devices */ + +/* + * Physical 8/16 LP-LVDS + * ID=0x0001, Generic End Point Devices + * ID=0x0002, Generic End Point Devices, software assisted recovery option + * ID=0x0003, Generic End Point Free Devices + * + * Physical LP-Serial + * ID=0x0004, Generic End Point Devices + * ID=0x0005, Generic End Point Devices, software assisted recovery option + * ID=0x0006, Generic End Point Free Devices + */ +#define RIO_PORT_MNT_HEADER 0x0000 +#define RIO_PORT_REQ_CTL_CSR 0x0020 +#define RIO_PORT_RSP_CTL_CSR 0x0024 /* 0x0001/0x0002 */ +#define RIO_PORT_GEN_CTL_CSR 0x003c +#define RIO_PORT_GEN_HOST 0x80000000 +#define RIO_PORT_GEN_MASTER 0x40000000 +#define RIO_PORT_GEN_DISCOVERED 0x20000000 +#define RIO_PORT_N_MNT_REQ_CSR(x) (0x0040 + x*0x20) /* 0x0002 */ +#define RIO_PORT_N_MNT_RSP_CSR(x) (0x0044 + x*0x20) /* 0x0002 */ +#define RIO_PORT_N_ACK_STS_CSR(x) (0x0048 + x*0x20) /* 0x0002 */ +#define RIO_PORT_N_ERR_STS_CSR(x) (0x58 + x*0x20) +#define PORT_N_ERR_STS_PORT_OK 0x00000002 +#define RIO_PORT_N_CTL_CSR(x) (0x5c + x*0x20) + +#endif /* LINUX_RIO_REGS_H */ -- cgit v1.2.3 From eb188d0e857c436b5d365d5ccc629da5a06ed102 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 7 Nov 2005 01:00:17 -0800 Subject: [PATCH] RapidIO support: core enum Adds RapidIO enumeration/discovery. The core code implements enumeration/discovery, management of devices/resources, and interfaces for RIO drivers. Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rapidio/rio-scan.c | 960 ++++++++++++++++++++++++++++++++++++++ drivers/rapidio/switches/Makefile | 5 + drivers/rapidio/switches/tsi500.c | 60 +++ 3 files changed, 1025 insertions(+) create mode 100644 drivers/rapidio/rio-scan.c create mode 100644 drivers/rapidio/switches/Makefile create mode 100644 drivers/rapidio/switches/tsi500.c diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c new file mode 100644 index 00000000000..20e1d8f7459 --- /dev/null +++ b/drivers/rapidio/rio-scan.c @@ -0,0 +1,960 @@ +/* + * RapidIO enumeration and discovery support + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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 + * option) any later version. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rio.h" + +LIST_HEAD(rio_devices); +static LIST_HEAD(rio_switches); + +#define RIO_ENUM_CMPL_MAGIC 0xdeadbeef + +static void rio_enum_timeout(unsigned long); + +spinlock_t rio_global_list_lock = SPIN_LOCK_UNLOCKED; +static int next_destid = 0; +static int next_switchid = 0; +static int next_net = 0; + +static struct timer_list rio_enum_timer = +TIMER_INITIALIZER(rio_enum_timeout, 0, 0); + +static int rio_mport_phys_table[] = { + RIO_EFB_PAR_EP_ID, + RIO_EFB_PAR_EP_REC_ID, + RIO_EFB_SER_EP_ID, + RIO_EFB_SER_EP_REC_ID, + -1, +}; + +static int rio_sport_phys_table[] = { + RIO_EFB_PAR_EP_FREE_ID, + RIO_EFB_SER_EP_FREE_ID, + -1, +}; + +extern struct rio_route_ops __start_rio_route_ops[]; +extern struct rio_route_ops __end_rio_route_ops[]; + +/** + * rio_get_device_id - Get the base/extended device id for a device + * @port: RIO master port + * @destid: Destination ID of device + * @hopcount: Hopcount to device + * + * Reads the base/extended device id from a device. Returns the + * 8/16-bit device ID. + */ +static u16 rio_get_device_id(struct rio_mport *port, u16 destid, u8 hopcount) +{ + u32 result; + + rio_mport_read_config_32(port, destid, hopcount, RIO_DID_CSR, &result); + + return RIO_GET_DID(result); +} + +/** + * rio_set_device_id - Set the base/extended device id for a device + * @port: RIO master port + * @destid: Destination ID of device + * @hopcount: Hopcount to device + * @did: Device ID value to be written + * + * Writes the base/extended device id from a device. + */ +static void +rio_set_device_id(struct rio_mport *port, u16 destid, u8 hopcount, u16 did) +{ + rio_mport_write_config_32(port, destid, hopcount, RIO_DID_CSR, + RIO_SET_DID(did)); +} + +/** + * rio_local_set_device_id - Set the base/extended device id for a port + * @port: RIO master port + * @did: Device ID value to be written + * + * Writes the base/extended device id from a device. + */ +static void rio_local_set_device_id(struct rio_mport *port, u16 did) +{ + rio_local_write_config_32(port, RIO_DID_CSR, RIO_SET_DID(did)); +} + +/** + * rio_clear_locks- Release all host locks and signal enumeration complete + * @port: Master port to issue transaction + * + * Marks the component tag CSR on each device with the enumeration + * complete flag. When complete, it then release the host locks on + * each device. Returns 0 on success or %-EINVAL on failure. + */ +static int rio_clear_locks(struct rio_mport *port) +{ + struct rio_dev *rdev; + u32 result; + int ret = 0; + + /* Write component tag CSR magic complete value */ + rio_local_write_config_32(port, RIO_COMPONENT_TAG_CSR, + RIO_ENUM_CMPL_MAGIC); + list_for_each_entry(rdev, &rio_devices, global_list) + rio_write_config_32(rdev, RIO_COMPONENT_TAG_CSR, + RIO_ENUM_CMPL_MAGIC); + + /* Release host device id locks */ + rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR, + port->host_deviceid); + rio_local_read_config_32(port, RIO_HOST_DID_LOCK_CSR, &result); + if ((result & 0xffff) != 0xffff) { + printk(KERN_INFO + "RIO: badness when releasing host lock on master port, result %8.8x\n", + result); + ret = -EINVAL; + } + list_for_each_entry(rdev, &rio_devices, global_list) { + rio_write_config_32(rdev, RIO_HOST_DID_LOCK_CSR, + port->host_deviceid); + rio_read_config_32(rdev, RIO_HOST_DID_LOCK_CSR, &result); + if ((result & 0xffff) != 0xffff) { + printk(KERN_INFO + "RIO: badness when releasing host lock on vid %4.4x did %4.4x\n", + rdev->vid, rdev->did); + ret = -EINVAL; + } + } + + return ret; +} + +/** + * rio_enum_host- Set host lock and initialize host destination ID + * @port: Master port to issue transaction + * + * Sets the local host master port lock and destination ID register + * with the host device ID value. The host device ID value is provided + * by the platform. Returns %0 on success or %-1 on failure. + */ +static int rio_enum_host(struct rio_mport *port) +{ + u32 result; + + /* Set master port host device id lock */ + rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR, + port->host_deviceid); + + rio_local_read_config_32(port, RIO_HOST_DID_LOCK_CSR, &result); + if ((result & 0xffff) != port->host_deviceid) + return -1; + + /* Set master port destid and init destid ctr */ + rio_local_set_device_id(port, port->host_deviceid); + + if (next_destid == port->host_deviceid) + next_destid++; + + return 0; +} + +/** + * rio_device_has_destid- Test if a device contains a destination ID register + * @port: Master port to issue transaction + * @src_ops: RIO device source operations + * @dst_ops: RIO device destination operations + * + * Checks the provided @src_ops and @dst_ops for the necessary transaction + * capabilities that indicate whether or not a device will implement a + * destination ID register. Returns 1 if true or 0 if false. + */ +static int rio_device_has_destid(struct rio_mport *port, int src_ops, + int dst_ops) +{ + if (((src_ops & RIO_SRC_OPS_READ) || + (src_ops & RIO_SRC_OPS_WRITE) || + (src_ops & RIO_SRC_OPS_ATOMIC_TST_SWP) || + (src_ops & RIO_SRC_OPS_ATOMIC_INC) || + (src_ops & RIO_SRC_OPS_ATOMIC_DEC) || + (src_ops & RIO_SRC_OPS_ATOMIC_SET) || + (src_ops & RIO_SRC_OPS_ATOMIC_CLR)) && + ((dst_ops & RIO_DST_OPS_READ) || + (dst_ops & RIO_DST_OPS_WRITE) || + (dst_ops & RIO_DST_OPS_ATOMIC_TST_SWP) || + (dst_ops & RIO_DST_OPS_ATOMIC_INC) || + (dst_ops & RIO_DST_OPS_ATOMIC_DEC) || + (dst_ops & RIO_DST_OPS_ATOMIC_SET) || + (dst_ops & RIO_DST_OPS_ATOMIC_CLR))) { + return 1; + } else + return 0; +} + +/** + * rio_release_dev- Frees a RIO device struct + * @dev: LDM device associated with a RIO device struct + * + * Gets the RIO device struct associated a RIO device struct. + * The RIO device struct is freed. + */ +static void rio_release_dev(struct device *dev) +{ + struct rio_dev *rdev; + + rdev = to_rio_dev(dev); + kfree(rdev); +} + +/** + * rio_is_switch- Tests if a RIO device has switch capabilities + * @rdev: RIO device + * + * Gets the RIO device Processing Element Features register + * contents and tests for switch capabilities. Returns 1 if + * the device is a switch or 0 if it is not a switch. + * The RIO device struct is freed. + */ +static int rio_is_switch(struct rio_dev *rdev) +{ + if (rdev->pef & RIO_PEF_SWITCH) + return 1; + return 0; +} + +/** + * rio_route_set_ops- Sets routing operations for a particular vendor switch + * @rdev: RIO device + * + * Searches the RIO route ops table for known switch types. If the vid + * and did match a switch table entry, then set the add_entry() and + * get_entry() ops to the table entry values. + */ +static void rio_route_set_ops(struct rio_dev *rdev) +{ + struct rio_route_ops *cur = __start_rio_route_ops; + struct rio_route_ops *end = __end_rio_route_ops; + + while (cur < end) { + if ((cur->vid == rdev->vid) && (cur->did == rdev->did)) { + pr_debug("RIO: adding routing ops for %s\n", rio_name(rdev)); + rdev->rswitch->add_entry = cur->add_hook; + rdev->rswitch->get_entry = cur->get_hook; + } + cur++; + } + + if (!rdev->rswitch->add_entry || !rdev->rswitch->get_entry) + printk(KERN_ERR "RIO: missing routing ops for %s\n", + rio_name(rdev)); +} + +/** + * rio_add_device- Adds a RIO device to the device model + * @rdev: RIO device + * + * Adds the RIO device to the global device list and adds the RIO + * device to the RIO device list. Creates the generic sysfs nodes + * for an RIO device. + */ +static void __devinit rio_add_device(struct rio_dev *rdev) +{ + device_add(&rdev->dev); + + spin_lock(&rio_global_list_lock); + list_add_tail(&rdev->global_list, &rio_devices); + spin_unlock(&rio_global_list_lock); + + rio_create_sysfs_dev_files(rdev); +} + +/** + * rio_setup_device- Allocates and sets up a RIO device + * @net: RIO network + * @port: Master port to send transactions + * @destid: Current destination ID + * @hopcount: Current hopcount + * @do_enum: Enumeration/Discovery mode flag + * + * Allocates a RIO device and configures fields based on configuration + * space contents. If device has a destination ID register, a destination + * ID is either assigned in enumeration mode or read from configuration + * space in discovery mode. If the device has switch capabilities, then + * a switch is allocated and configured appropriately. Returns a pointer + * to a RIO device on success or NULL on failure. + * + */ +static struct rio_dev *rio_setup_device(struct rio_net *net, + struct rio_mport *port, u16 destid, + u8 hopcount, int do_enum) +{ + struct rio_dev *rdev; + struct rio_switch *rswitch; + int result, rdid; + + rdev = kmalloc(sizeof(struct rio_dev), GFP_KERNEL); + if (!rdev) + goto out; + + memset(rdev, 0, sizeof(struct rio_dev)); + rdev->net = net; + rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_ID_CAR, + &result); + rdev->did = result >> 16; + rdev->vid = result & 0xffff; + rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_INFO_CAR, + &rdev->device_rev); + rio_mport_read_config_32(port, destid, hopcount, RIO_ASM_ID_CAR, + &result); + rdev->asm_did = result >> 16; + rdev->asm_vid = result & 0xffff; + rio_mport_read_config_32(port, destid, hopcount, RIO_ASM_INFO_CAR, + &result); + rdev->asm_rev = result >> 16; + rio_mport_read_config_32(port, destid, hopcount, RIO_PEF_CAR, + &rdev->pef); + if (rdev->pef & RIO_PEF_EXT_FEATURES) + rdev->efptr = result & 0xffff; + + rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR, + &rdev->src_ops); + rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR, + &rdev->dst_ops); + + if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops) + && do_enum) { + rio_set_device_id(port, destid, hopcount, next_destid); + rdev->destid = next_destid++; + if (next_destid == port->host_deviceid) + next_destid++; + } else + rdev->destid = rio_get_device_id(port, destid, hopcount); + + /* If a PE has both switch and other functions, show it as a switch */ + if (rio_is_switch(rdev)) { + rio_mport_read_config_32(port, destid, hopcount, + RIO_SWP_INFO_CAR, &rdev->swpinfo); + rswitch = kmalloc(sizeof(struct rio_switch), GFP_KERNEL); + if (!rswitch) { + kfree(rdev); + rdev = NULL; + goto out; + } + rswitch->switchid = next_switchid; + rswitch->hopcount = hopcount; + rswitch->destid = 0xffff; + /* Initialize switch route table */ + for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES; rdid++) + rswitch->route_table[rdid] = RIO_INVALID_ROUTE; + rdev->rswitch = rswitch; + sprintf(rio_name(rdev), "%02x:s:%04x", rdev->net->id, + rdev->rswitch->switchid); + rio_route_set_ops(rdev); + + list_add_tail(&rswitch->node, &rio_switches); + + } else + sprintf(rio_name(rdev), "%02x:e:%04x", rdev->net->id, + rdev->destid); + + rdev->dev.bus = &rio_bus_type; + + device_initialize(&rdev->dev); + rdev->dev.release = rio_release_dev; + rio_dev_get(rdev); + + rdev->dev.dma_mask = (u64 *) 0xffffffff; + rdev->dev.coherent_dma_mask = 0xffffffffULL; + + if ((rdev->pef & RIO_PEF_INB_DOORBELL) && + (rdev->dst_ops & RIO_DST_OPS_DOORBELL)) + rio_init_dbell_res(&rdev->riores[RIO_DOORBELL_RESOURCE], + 0, 0xffff); + + rio_add_device(rdev); + + out: + return rdev; +} + +/** + * rio_sport_is_active- Tests if a switch port has an active connection. + * @port: Master port to send transaction + * @destid: Associated destination ID for switch + * @hopcount: Hopcount to reach switch + * @sport: Switch port number + * + * Reads the port error status CSR for a particular switch port to + * determine if the port has an active link. Returns + * %PORT_N_ERR_STS_PORT_OK if the port is active or %0 if it is + * inactive. + */ +static int +rio_sport_is_active(struct rio_mport *port, u16 destid, u8 hopcount, int sport) +{ + u32 result; + u32 ext_ftr_ptr; + + int *entry = rio_sport_phys_table; + + do { + if ((ext_ftr_ptr = + rio_mport_get_feature(port, 0, destid, hopcount, *entry))) + + break; + } while (*++entry >= 0); + + if (ext_ftr_ptr) + rio_mport_read_config_32(port, destid, hopcount, + ext_ftr_ptr + + RIO_PORT_N_ERR_STS_CSR(sport), + &result); + + return (result & PORT_N_ERR_STS_PORT_OK); +} + +/** + * rio_route_add_entry- Add a route entry to a switch routing table + * @mport: Master port to send transaction + * @rdev: Switch device + * @table: Routing table ID + * @route_destid: Destination ID to be routed + * @route_port: Port number to be routed + * + * Calls the switch specific add_entry() method to add a route entry + * on a switch. The route table can be specified using the @table + * argument if a switch has per port routing tables or the normal + * use is to specific all tables (or the global table) by passing + * %RIO_GLOBAL_TABLE in @table. Returns %0 on success or %-EINVAL + * on failure. + */ +static int rio_route_add_entry(struct rio_mport *mport, struct rio_dev *rdev, + u16 table, u16 route_destid, u8 route_port) +{ + return rdev->rswitch->add_entry(mport, rdev->rswitch->destid, + rdev->rswitch->hopcount, table, + route_destid, route_port); +} + +/** + * rio_route_get_entry- Read a route entry in a switch routing table + * @mport: Master port to send transaction + * @rdev: Switch device + * @table: Routing table ID + * @route_destid: Destination ID to be routed + * @route_port: Pointer to read port number into + * + * Calls the switch specific get_entry() method to read a route entry + * in a switch. The route table can be specified using the @table + * argument if a switch has per port routing tables or the normal + * use is to specific all tables (or the global table) by passing + * %RIO_GLOBAL_TABLE in @table. Returns %0 on success or %-EINVAL + * on failure. + */ +static int +rio_route_get_entry(struct rio_mport *mport, struct rio_dev *rdev, u16 table, + u16 route_destid, u8 * route_port) +{ + return rdev->rswitch->get_entry(mport, rdev->rswitch->destid, + rdev->rswitch->hopcount, table, + route_destid, route_port); +} + +/** + * rio_get_host_deviceid_lock- Reads the Host Device ID Lock CSR on a device + * @port: Master port to send transaction + * @hopcount: Number of hops to the device + * + * Used during enumeration to read the Host Device ID Lock CSR on a + * RIO device. Returns the value of the lock register. + */ +static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount) +{ + u32 result; + + rio_mport_read_config_32(port, RIO_ANY_DESTID, hopcount, + RIO_HOST_DID_LOCK_CSR, &result); + + return (u16) (result & 0xffff); +} + +/** + * rio_get_swpinfo_inport- Gets the ingress port number + * @mport: Master port to send transaction + * @destid: Destination ID associated with the switch + * @hopcount: Number of hops to the device + * + * Returns port number being used to access the switch device. + */ +static u8 +rio_get_swpinfo_inport(struct rio_mport *mport, u16 destid, u8 hopcount) +{ + u32 result; + + rio_mport_read_config_32(mport, destid, hopcount, RIO_SWP_INFO_CAR, + &result); + + return (u8) (result & 0xff); +} + +/** + * rio_get_swpinfo_tports- Gets total number of ports on the switch + * @mport: Master port to send transaction + * @destid: Destination ID associated with the switch + * @hopcount: Number of hops to the device + * + * Returns total numbers of ports implemented by the switch device. + */ +static u8 rio_get_swpinfo_tports(struct rio_mport *mport, u16 destid, + u8 hopcount) +{ + u32 result; + + rio_mport_read_config_32(mport, destid, hopcount, RIO_SWP_INFO_CAR, + &result); + + return RIO_GET_TOTAL_PORTS(result); +} + +/** + * rio_net_add_mport- Add a master port to a RIO network + * @net: RIO network + * @port: Master port to add + * + * Adds a master port to the network list of associated master + * ports.. + */ +static void rio_net_add_mport(struct rio_net *net, struct rio_mport *port) +{ + spin_lock(&rio_global_list_lock); + list_add_tail(&port->nnode, &net->mports); + spin_unlock(&rio_global_list_lock); +} + +/** + * rio_enum_peer- Recursively enumerate a RIO network through a master port + * @net: RIO network being enumerated + * @port: Master port to send transactions + * @hopcount: Number of hops into the network + * + * Recursively enumerates a RIO network. Transactions are sent via the + * master port passed in @port. + */ +static int rio_enum_peer(struct rio_net *net, struct rio_mport *port, + u8 hopcount) +{ + int port_num; + int num_ports; + int cur_destid; + struct rio_dev *rdev; + u16 destid; + int tmp; + + if (rio_get_host_deviceid_lock(port, hopcount) == port->host_deviceid) { + pr_debug("RIO: PE already discovered by this host\n"); + /* + * Already discovered by this host. Add it as another + * master port for the current network. + */ + rio_net_add_mport(net, port); + return 0; + } + + /* Attempt to acquire device lock */ + rio_mport_write_config_32(port, RIO_ANY_DESTID, hopcount, + RIO_HOST_DID_LOCK_CSR, port->host_deviceid); + while ((tmp = rio_get_host_deviceid_lock(port, hopcount)) + < port->host_deviceid) { + /* Delay a bit */ + mdelay(1); + /* Attempt to acquire device lock again */ + rio_mport_write_config_32(port, RIO_ANY_DESTID, hopcount, + RIO_HOST_DID_LOCK_CSR, + port->host_deviceid); + } + + if (rio_get_host_deviceid_lock(port, hopcount) > port->host_deviceid) { + pr_debug( + "RIO: PE locked by a higher priority host...retreating\n"); + return -1; + } + + /* Setup new RIO device */ + if ((rdev = rio_setup_device(net, port, RIO_ANY_DESTID, hopcount, 1))) { + /* Add device to the global and bus/net specific list. */ + list_add_tail(&rdev->net_list, &net->devices); + } else + return -1; + + if (rio_is_switch(rdev)) { + next_switchid++; + + for (destid = 0; destid < next_destid; destid++) { + rio_route_add_entry(port, rdev, RIO_GLOBAL_TABLE, + destid, rio_get_swpinfo_inport(port, + RIO_ANY_DESTID, + hopcount)); + rdev->rswitch->route_table[destid] = + rio_get_swpinfo_inport(port, RIO_ANY_DESTID, + hopcount); + } + + num_ports = + rio_get_swpinfo_tports(port, RIO_ANY_DESTID, hopcount); + pr_debug( + "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", + rio_name(rdev), rdev->vid, rdev->did, num_ports); + for (port_num = 0; port_num < num_ports; port_num++) { + if (rio_get_swpinfo_inport + (port, RIO_ANY_DESTID, hopcount) == port_num) + continue; + + cur_destid = next_destid; + + if (rio_sport_is_active + (port, RIO_ANY_DESTID, hopcount, port_num)) { + pr_debug( + "RIO: scanning device on port %d\n", + port_num); + rio_route_add_entry(port, rdev, + RIO_GLOBAL_TABLE, + RIO_ANY_DESTID, port_num); + + if (rio_enum_peer(net, port, hopcount + 1) < 0) + return -1; + + /* Update routing tables */ + if (next_destid > cur_destid) { + for (destid = cur_destid; + destid < next_destid; destid++) { + rio_route_add_entry(port, rdev, + RIO_GLOBAL_TABLE, + destid, + port_num); + rdev->rswitch-> + route_table[destid] = + port_num; + } + rdev->rswitch->destid = cur_destid; + } + } + } + } else + pr_debug("RIO: found %s (vid %4.4x did %4.4x)\n", + rio_name(rdev), rdev->vid, rdev->did); + + return 0; +} + +/** + * rio_enum_complete- Tests if enumeration of a network is complete + * @port: Master port to send transaction + * + * Tests the Component Tag CSR for presence of the magic enumeration + * complete flag. Return %1 if enumeration is complete or %0 if + * enumeration is incomplete. + */ +static int rio_enum_complete(struct rio_mport *port) +{ + u32 tag_csr; + int ret = 0; + + rio_local_read_config_32(port, RIO_COMPONENT_TAG_CSR, &tag_csr); + + if (tag_csr == RIO_ENUM_CMPL_MAGIC) + ret = 1; + + return ret; +} + +/** + * rio_disc_peer- Recursively discovers a RIO network through a master port + * @net: RIO network being discovered + * @port: Master port to send transactions + * @destid: Current destination ID in network + * @hopcount: Number of hops into the network + * + * Recursively discovers a RIO network. Transactions are sent via the + * master port passed in @port. + */ +static int +rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, + u8 hopcount) +{ + u8 port_num, route_port; + int num_ports; + struct rio_dev *rdev; + u16 ndestid; + + /* Setup new RIO device */ + if ((rdev = rio_setup_device(net, port, destid, hopcount, 0))) { + /* Add device to the global and bus/net specific list. */ + list_add_tail(&rdev->net_list, &net->devices); + } else + return -1; + + if (rio_is_switch(rdev)) { + next_switchid++; + + /* Associated destid is how we accessed this switch */ + rdev->rswitch->destid = destid; + + num_ports = rio_get_swpinfo_tports(port, destid, hopcount); + pr_debug( + "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", + rio_name(rdev), rdev->vid, rdev->did, num_ports); + for (port_num = 0; port_num < num_ports; port_num++) { + if (rio_get_swpinfo_inport(port, destid, hopcount) == + port_num) + continue; + + if (rio_sport_is_active + (port, destid, hopcount, port_num)) { + pr_debug( + "RIO: scanning device on port %d\n", + port_num); + for (ndestid = 0; ndestid < RIO_ANY_DESTID; + ndestid++) { + rio_route_get_entry(port, rdev, + RIO_GLOBAL_TABLE, + ndestid, + &route_port); + if (route_port == port_num) + break; + } + + if (rio_disc_peer + (net, port, ndestid, hopcount + 1) < 0) + return -1; + } + } + } else + pr_debug("RIO: found %s (vid %4.4x did %4.4x)\n", + rio_name(rdev), rdev->vid, rdev->did); + + return 0; +} + +/** + * rio_mport_is_active- Tests if master port link is active + * @port: Master port to test + * + * Reads the port error status CSR for the master port to + * determine if the port has an active link. Returns + * %PORT_N_ERR_STS_PORT_OK if the master port is active + * or %0 if it is inactive. + */ +static int rio_mport_is_active(struct rio_mport *port) +{ + u32 result = 0; + u32 ext_ftr_ptr; + int *entry = rio_mport_phys_table; + + do { + if ((ext_ftr_ptr = + rio_mport_get_feature(port, 1, 0, 0, *entry))) + break; + } while (*++entry >= 0); + + if (ext_ftr_ptr) + rio_local_read_config_32(port, + ext_ftr_ptr + + RIO_PORT_N_ERR_STS_CSR(port->index), + &result); + + return (result & PORT_N_ERR_STS_PORT_OK); +} + +/** + * rio_alloc_net- Allocate and configure a new RIO network + * @port: Master port associated with the RIO network + * + * Allocates a RIO network structure, initializes per-network + * list heads, and adds the associated master port to the + * network list of associated master ports. Returns a + * RIO network pointer on success or %NULL on failure. + */ +static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port) +{ + struct rio_net *net; + + net = kmalloc(sizeof(struct rio_net), GFP_KERNEL); + if (net) { + memset(net, 0, sizeof(struct rio_net)); + INIT_LIST_HEAD(&net->node); + INIT_LIST_HEAD(&net->devices); + INIT_LIST_HEAD(&net->mports); + list_add_tail(&port->nnode, &net->mports); + net->hport = port; + net->id = next_net++; + } + return net; +} + +/** + * rio_enum_mport- Start enumeration through a master port + * @mport: Master port to send transactions + * + * Starts the enumeration process. If somebody has enumerated our + * master port device, then give up. If not and we have an active + * link, then start recursive peer enumeration. Returns %0 if + * enumeration succeeds or %-EBUSY if enumeration fails. + */ +int rio_enum_mport(struct rio_mport *mport) +{ + struct rio_net *net = NULL; + int rc = 0; + + printk(KERN_INFO "RIO: enumerate master port %d, %s\n", mport->id, + mport->name); + /* If somebody else enumerated our master port device, bail. */ + if (rio_enum_host(mport) < 0) { + printk(KERN_INFO + "RIO: master port %d device has been enumerated by a remote host\n", + mport->id); + rc = -EBUSY; + goto out; + } + + /* If master port has an active link, allocate net and enum peers */ + if (rio_mport_is_active(mport)) { + if (!(net = rio_alloc_net(mport))) { + printk(KERN_ERR "RIO: failed to allocate new net\n"); + rc = -ENOMEM; + goto out; + } + if (rio_enum_peer(net, mport, 0) < 0) { + /* A higher priority host won enumeration, bail. */ + printk(KERN_INFO + "RIO: master port %d device has lost enumeration to a remote host\n", + mport->id); + rio_clear_locks(mport); + rc = -EBUSY; + goto out; + } + rio_clear_locks(mport); + } else { + printk(KERN_INFO "RIO: master port %d link inactive\n", + mport->id); + rc = -EINVAL; + } + + out: + return rc; +} + +/** + * rio_build_route_tables- Generate route tables from switch route entries + * + * For each switch device, generate a route table by copying existing + * route entries from the switch. + */ +static void rio_build_route_tables(void) +{ + struct rio_dev *rdev; + int i; + u8 sport; + + list_for_each_entry(rdev, &rio_devices, global_list) + if (rio_is_switch(rdev)) + for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++) { + if (rio_route_get_entry + (rdev->net->hport, rdev, RIO_GLOBAL_TABLE, i, + &sport) < 0) + continue; + rdev->rswitch->route_table[i] = sport; + } +} + +/** + * rio_enum_timeout- Signal that enumeration timed out + * @data: Address of timeout flag. + * + * When the enumeration complete timer expires, set a flag that + * signals to the discovery process that enumeration did not + * complete in a sane amount of time. + */ +static void rio_enum_timeout(unsigned long data) +{ + /* Enumeration timed out, set flag */ + *(int *)data = 1; +} + +/** + * rio_disc_mport- Start discovery through a master port + * @mport: Master port to send transactions + * + * Starts the discovery process. If we have an active link, + * then wait for the signal that enumeration is complete. + * When enumeration completion is signaled, start recursive + * peer discovery. Returns %0 if discovery succeeds or %-EBUSY + * on failure. + */ +int rio_disc_mport(struct rio_mport *mport) +{ + struct rio_net *net = NULL; + int enum_timeout_flag = 0; + + printk(KERN_INFO "RIO: discover master port %d, %s\n", mport->id, + mport->name); + + /* If master port has an active link, allocate net and discover peers */ + if (rio_mport_is_active(mport)) { + if (!(net = rio_alloc_net(mport))) { + printk(KERN_ERR "RIO: Failed to allocate new net\n"); + goto bail; + } + + pr_debug("RIO: wait for enumeration complete..."); + + rio_enum_timer.expires = + jiffies + CONFIG_RAPIDIO_DISC_TIMEOUT * HZ; + rio_enum_timer.data = (unsigned long)&enum_timeout_flag; + add_timer(&rio_enum_timer); + while (!rio_enum_complete(mport)) { + mdelay(1); + if (enum_timeout_flag) { + del_timer_sync(&rio_enum_timer); + goto timeout; + } + } + del_timer_sync(&rio_enum_timer); + + pr_debug("done\n"); + if (rio_disc_peer(net, mport, RIO_ANY_DESTID, 0) < 0) { + printk(KERN_INFO + "RIO: master port %d device has failed discovery\n", + mport->id); + goto bail; + } + + rio_build_route_tables(); + } + + return 0; + + timeout: + pr_debug("timeout\n"); + bail: + return -EBUSY; +} diff --git a/drivers/rapidio/switches/Makefile b/drivers/rapidio/switches/Makefile new file mode 100644 index 00000000000..b924f830176 --- /dev/null +++ b/drivers/rapidio/switches/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for RIO switches +# + +obj-$(CONFIG_RAPIDIO) += tsi500.o diff --git a/drivers/rapidio/switches/tsi500.c b/drivers/rapidio/switches/tsi500.c new file mode 100644 index 00000000000..c77c23bd984 --- /dev/null +++ b/drivers/rapidio/switches/tsi500.c @@ -0,0 +1,60 @@ +/* + * RapidIO Tsi500 switch support + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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 + * option) any later version. + */ + +#include +#include +#include +#include "../rio.h" + +static int +tsi500_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount, u16 table, u16 route_destid, u8 route_port) +{ + int i; + u32 offset = 0x10000 + 0xa00 + ((route_destid / 2)&~0x3); + u32 result; + + if (table == 0xff) { + rio_mport_read_config_32(mport, destid, hopcount, offset, &result); + result &= ~(0xf << (4*(route_destid & 0x7))); + for (i=0;i<4;i++) + rio_mport_write_config_32(mport, destid, hopcount, offset + (0x20000*i), result | (route_port << (4*(route_destid & 0x7)))); + } + else { + rio_mport_read_config_32(mport, destid, hopcount, offset + (0x20000*table), &result); + result &= ~(0xf << (4*(route_destid & 0x7))); + rio_mport_write_config_32(mport, destid, hopcount, offset + (0x20000*table), result | (route_port << (4*(route_destid & 0x7)))); + } + + return 0; +} + +static int +tsi500_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount, u16 table, u16 route_destid, u8 *route_port) +{ + int ret = 0; + u32 offset = 0x10000 + 0xa00 + ((route_destid / 2)&~0x3); + u32 result; + + if (table == 0xff) + rio_mport_read_config_32(mport, destid, hopcount, offset, &result); + else + rio_mport_read_config_32(mport, destid, hopcount, offset + (0x20000*table), &result); + + result &= 0xf << (4*(route_destid & 0x7)); + *route_port = result >> (4*(route_destid & 0x7)); + if (*route_port > 3) + ret = -1; + + return ret; +} + +DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI500, tsi500_route_add_entry, tsi500_route_get_entry); -- cgit v1.2.3 From fa78cc51794912b7e6ee98cd823fcc84cf79d04a Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 7 Nov 2005 01:00:18 -0800 Subject: [PATCH] rapidio: core updates Addresses issues raised with the 2.6.12-rc6-mm1 RIO support. Fix dma_mask init, shrink some code, general cleanup. Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rapidio/rio-scan.c | 35 ++++++++++------------------------- drivers/rapidio/rio.h | 3 +++ include/linux/rio.h | 2 ++ include/linux/rio_regs.h | 13 +++++++++++++ 4 files changed, 28 insertions(+), 25 deletions(-) diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 20e1d8f7459..4f7ed4bd3be 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -33,7 +34,8 @@ static LIST_HEAD(rio_switches); static void rio_enum_timeout(unsigned long); -spinlock_t rio_global_list_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(rio_global_list_lock); + static int next_destid = 0; static int next_switchid = 0; static int next_net = 0; @@ -55,9 +57,6 @@ static int rio_sport_phys_table[] = { -1, }; -extern struct rio_route_ops __start_rio_route_ops[]; -extern struct rio_route_ops __end_rio_route_ops[]; - /** * rio_get_device_id - Get the base/extended device id for a device * @port: RIO master port @@ -85,8 +84,7 @@ static u16 rio_get_device_id(struct rio_mport *port, u16 destid, u8 hopcount) * * Writes the base/extended device id from a device. */ -static void -rio_set_device_id(struct rio_mport *port, u16 destid, u8 hopcount, u16 did) +static void rio_set_device_id(struct rio_mport *port, u16 destid, u8 hopcount, u16 did) { rio_mport_write_config_32(port, destid, hopcount, RIO_DID_CSR, RIO_SET_DID(did)); @@ -192,23 +190,9 @@ static int rio_enum_host(struct rio_mport *port) static int rio_device_has_destid(struct rio_mport *port, int src_ops, int dst_ops) { - if (((src_ops & RIO_SRC_OPS_READ) || - (src_ops & RIO_SRC_OPS_WRITE) || - (src_ops & RIO_SRC_OPS_ATOMIC_TST_SWP) || - (src_ops & RIO_SRC_OPS_ATOMIC_INC) || - (src_ops & RIO_SRC_OPS_ATOMIC_DEC) || - (src_ops & RIO_SRC_OPS_ATOMIC_SET) || - (src_ops & RIO_SRC_OPS_ATOMIC_CLR)) && - ((dst_ops & RIO_DST_OPS_READ) || - (dst_ops & RIO_DST_OPS_WRITE) || - (dst_ops & RIO_DST_OPS_ATOMIC_TST_SWP) || - (dst_ops & RIO_DST_OPS_ATOMIC_INC) || - (dst_ops & RIO_DST_OPS_ATOMIC_DEC) || - (dst_ops & RIO_DST_OPS_ATOMIC_SET) || - (dst_ops & RIO_DST_OPS_ATOMIC_CLR))) { - return 1; - } else - return 0; + u32 mask = RIO_OPS_READ | RIO_OPS_WRITE | RIO_OPS_ATOMIC_TST_SWP | RIO_OPS_ATOMIC_INC | RIO_OPS_ATOMIC_DEC | RIO_OPS_ATOMIC_SET | RIO_OPS_ATOMIC_CLR; + + return !!((src_ops | dst_ops) & mask); } /** @@ -383,8 +367,9 @@ static struct rio_dev *rio_setup_device(struct rio_net *net, rdev->dev.release = rio_release_dev; rio_dev_get(rdev); - rdev->dev.dma_mask = (u64 *) 0xffffffff; - rdev->dev.coherent_dma_mask = 0xffffffffULL; + rdev->dma_mask = DMA_32BIT_MASK; + rdev->dev.dma_mask = &rdev->dma_mask; + rdev->dev.coherent_dma_mask = DMA_32BIT_MASK; if ((rdev->pef & RIO_PEF_INB_DOORBELL) && (rdev->dst_ops & RIO_DST_OPS_DOORBELL)) diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h index f865a68cd3d..b242cee656e 100644 --- a/drivers/rapidio/rio.h +++ b/drivers/rapidio/rio.h @@ -26,6 +26,9 @@ extern int rio_disc_mport(struct rio_mport *mport); extern struct device_attribute rio_dev_attrs[]; extern spinlock_t rio_global_list_lock; +extern struct rio_route_ops __start_rio_route_ops[]; +extern struct rio_route_ops __end_rio_route_ops[]; + /* Helpers internal to the RIO core code */ #define DECLARE_RIO_ROUTE_SECTION(section, vid, did, add_hook, get_hook) \ static struct rio_route_ops __rio_route_ops __attribute_used__ \ diff --git a/include/linux/rio.h b/include/linux/rio.h index 930bbb7c380..5c29f2f477c 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h @@ -91,6 +91,7 @@ struct rio_mport; * @swpinfo: Switch port info * @src_ops: Source operation capabilities * @dst_ops: Destination operation capabilities + * @dma_mask: Mask of bits of RIO address this device implements * @rswitch: Pointer to &struct rio_switch if valid for this device * @driver: Driver claiming this device * @dev: Device model device @@ -112,6 +113,7 @@ struct rio_dev { u32 swpinfo; /* Only used for switches */ u32 src_ops; u32 dst_ops; + u64 dma_mask; struct rio_switch *rswitch; /* RIO switch info */ struct rio_driver *driver; /* RIO driver claiming this device */ struct device dev; /* LDM device structure */ diff --git a/include/linux/rio_regs.h b/include/linux/rio_regs.h index f419be3be49..326540f9b54 100644 --- a/include/linux/rio_regs.h +++ b/include/linux/rio_regs.h @@ -78,6 +78,19 @@ #define RIO_DST_OPS_ATOMIC_CLR 0x00000010 /* [I] Atomic clr op */ #define RIO_DST_OPS_PORT_WRITE 0x00000004 /* [I] Port-write op */ +#define RIO_OPS_READ 0x00008000 /* [I] Read op */ +#define RIO_OPS_WRITE 0x00004000 /* [I] Write op */ +#define RIO_OPS_STREAM_WRITE 0x00002000 /* [I] Str-write op */ +#define RIO_OPS_WRITE_RESPONSE 0x00001000 /* [I] Write/resp op */ +#define RIO_OPS_DATA_MSG 0x00000800 /* [II] Data msg op */ +#define RIO_OPS_DOORBELL 0x00000400 /* [II] Doorbell op */ +#define RIO_OPS_ATOMIC_TST_SWP 0x00000100 /* [I] Atomic TAS op */ +#define RIO_OPS_ATOMIC_INC 0x00000080 /* [I] Atomic inc op */ +#define RIO_OPS_ATOMIC_DEC 0x00000040 /* [I] Atomic dec op */ +#define RIO_OPS_ATOMIC_SET 0x00000020 /* [I] Atomic set op */ +#define RIO_OPS_ATOMIC_CLR 0x00000010 /* [I] Atomic clr op */ +#define RIO_OPS_PORT_WRITE 0x00000004 /* [I] Port-write op */ + /* 0x20-0x3c *//* Reserved */ #define RIO_MBOX_CSR 0x40 /* [II] Mailbox CSR */ -- cgit v1.2.3 From 2b0c28d7f8846f80a436093e906f5175d1fa8f55 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 7 Nov 2005 01:00:19 -0800 Subject: [PATCH] RapidIO support: ppc32 Adds PPC32 RIO support. Init code for the MPC85xx RIO ports and glue for the STx GP3 board to use it. Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/Kconfig | 8 + arch/ppc/configs/stx_gp3_defconfig | 86 ++- arch/ppc/kernel/Makefile | 1 + arch/ppc/kernel/rio.c | 52 ++ arch/ppc/platforms/85xx/mpc85xx_ads_common.c | 10 + arch/ppc/platforms/85xx/stx_gp3.c | 14 + arch/ppc/syslib/Makefile | 1 + arch/ppc/syslib/ppc85xx_rio.c | 932 +++++++++++++++++++++++++++ arch/ppc/syslib/ppc85xx_rio.h | 21 + include/asm-ppc/rio.h | 18 + 10 files changed, 1109 insertions(+), 34 deletions(-) create mode 100644 arch/ppc/kernel/rio.c create mode 100644 arch/ppc/syslib/ppc85xx_rio.c create mode 100644 arch/ppc/syslib/ppc85xx_rio.h create mode 100644 include/asm-ppc/rio.h diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index f8db33d5527..8fa51b0a32d 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -1257,6 +1257,14 @@ source "drivers/pci/Kconfig" source "drivers/pcmcia/Kconfig" +config RAPIDIO + bool "RapidIO support" if MPC8540 || MPC8560 + help + If you say Y here, the kernel will include drivers and + infrastructure code to support RapidIO interconnect devices. + +source "drivers/rapidio/Kconfig" + endmenu menu "Advanced setup" diff --git a/arch/ppc/configs/stx_gp3_defconfig b/arch/ppc/configs/stx_gp3_defconfig index 66dae836765..3fedc43e44a 100644 --- a/arch/ppc/configs/stx_gp3_defconfig +++ b/arch/ppc/configs/stx_gp3_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.11-rc2 -# Wed Jan 26 14:32:58 2005 +# Linux kernel version: 2.6.12-rc4 +# Tue May 24 18:11:04 2005 # CONFIG_MMU=y CONFIG_GENERIC_HARDIRQS=y @@ -11,6 +11,7 @@ CONFIG_HAVE_DEC_LOCK=y CONFIG_PPC=y CONFIG_PPC32=y CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y # # Code maturity level options @@ -18,6 +19,7 @@ CONFIG_GENERIC_NVRAM=y CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 # # General setup @@ -29,7 +31,6 @@ CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set @@ -37,6 +38,9 @@ CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set @@ -46,6 +50,7 @@ CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 # CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 # # Loadable module support @@ -69,9 +74,11 @@ CONFIG_KMOD=y CONFIG_E500=y CONFIG_BOOKE=y CONFIG_FSL_BOOKE=y +# CONFIG_PHYS_64BIT is not set # CONFIG_SPE is not set CONFIG_MATH_EMULATION=y # CONFIG_CPU_FREQ is not set +# CONFIG_PM is not set CONFIG_85xx=y CONFIG_PPC_INDIRECT_PCI_BE=y @@ -96,6 +103,7 @@ CONFIG_HIGHMEM=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m # CONFIG_CMDLINE_BOOL is not set +CONFIG_ISA_DMA_API=y # # Bus options @@ -104,15 +112,15 @@ CONFIG_PCI=y CONFIG_PCI_DOMAINS=y # CONFIG_PCI_LEGACY_PROC is not set # CONFIG_PCI_NAMES is not set +# CONFIG_PCI_DEBUG is not set # # PCCARD (PCMCIA/CardBus) support # # CONFIG_PCCARD is not set - -# -# PC-card bridges -# +CONFIG_RAPIDIO=y +CONFIG_RAPIDIO_8_BIT_TRANSPORT=y +CONFIG_RAPIDIO_DISC_TIMEOUT=30 # # Advanced setup @@ -152,7 +160,7 @@ CONFIG_PARPORT=m CONFIG_PARPORT_PC=m # CONFIG_PARPORT_PC_FIFO is not set # CONFIG_PARPORT_PC_SUPERIO is not set -# CONFIG_PARPORT_OTHER is not set +# CONFIG_PARPORT_GSC is not set # CONFIG_PARPORT_1284 is not set # @@ -264,7 +272,6 @@ CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_IPS is not set @@ -274,7 +281,6 @@ CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_IMM is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_IPR is not set -# CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set CONFIG_SCSI_QLA2XXX=m @@ -283,6 +289,7 @@ CONFIG_SCSI_QLA2XXX=m # CONFIG_SCSI_QLA2300 is not set # CONFIG_SCSI_QLA2322 is not set # CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_NSP32 is not set @@ -322,7 +329,6 @@ CONFIG_NET=y # CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK_DEV is not set CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y @@ -431,7 +437,7 @@ CONFIG_IP_NF_NAT_FTP=m # # Network testing # -# CONFIG_NET_PKTGEN is not set +CONFIG_NET_PKTGEN=y # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set # CONFIG_HAMRADIO is not set @@ -499,6 +505,7 @@ CONFIG_GFAR_NAPI=y # Wan interfaces # # CONFIG_WAN is not set +CONFIG_RIONET=y # CONFIG_FDDI is not set # CONFIG_HIPPI is not set # CONFIG_PLIP is not set @@ -535,20 +542,6 @@ CONFIG_INPUT_JOYDEV=m CONFIG_INPUT_EVDEV=m # CONFIG_INPUT_EVBUG is not set -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -CONFIG_SERIO_I8042=y -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PARKBD is not set -# CONFIG_SERIO_PCIPS2 is not set -CONFIG_SERIO_LIBPS2=y -# CONFIG_SERIO_RAW is not set - # # Input Device Drivers # @@ -566,6 +559,19 @@ CONFIG_MOUSE_PS2=y # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y + # # Character devices # @@ -590,6 +596,7 @@ CONFIG_SERIAL_CPM_SCC2=y # CONFIG_SERIAL_CPM_SCC4 is not set # CONFIG_SERIAL_CPM_SMC1 is not set # CONFIG_SERIAL_CPM_SMC2 is not set +# CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -625,6 +632,11 @@ CONFIG_DRM=m # CONFIG_DRM_SIS is not set # CONFIG_RAW_DRIVER is not set +# +# TPM devices +# +# CONFIG_TCG_TPM is not set + # # I2C support # @@ -648,12 +660,12 @@ CONFIG_I2C_ALGOBIT=m # CONFIG_I2C_AMD8111 is not set # CONFIG_I2C_I801 is not set # CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_ISA is not set # CONFIG_I2C_MPC is not set # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT is not set # CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_PROSAVAGE is not set # CONFIG_I2C_SAVAGE4 is not set # CONFIG_SCx200_ACB is not set @@ -677,7 +689,9 @@ CONFIG_I2C_ALGOBIT=m # CONFIG_SENSORS_ASB100 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set # CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set # CONFIG_SENSORS_IT87 is not set # CONFIG_SENSORS_LM63 is not set # CONFIG_SENSORS_LM75 is not set @@ -688,9 +702,11 @@ CONFIG_I2C_ALGOBIT=m # CONFIG_SENSORS_LM85 is not set # CONFIG_SENSORS_LM87 is not set # CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set @@ -700,10 +716,12 @@ CONFIG_I2C_ALGOBIT=m # # Other I2C Chip support # +# CONFIG_SENSORS_DS1337 is not set # CONFIG_SENSORS_EEPROM is not set # CONFIG_SENSORS_PCF8574 is not set # CONFIG_SENSORS_PCF8591 is not set # CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_M41T00 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set @@ -732,7 +750,6 @@ CONFIG_I2C_ALGOBIT=m # Graphics support # # CONFIG_FB is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Sound @@ -752,13 +769,9 @@ CONFIG_SOUND=m # # USB support # -# CONFIG_USB is not set CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y - -# -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information -# +# CONFIG_USB is not set # # USB Gadget Support @@ -789,6 +802,10 @@ CONFIG_JBD_DEBUG=y CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set + +# +# XFS support +# # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set @@ -859,7 +876,6 @@ CONFIG_NFS_V3=y CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y -# CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set @@ -942,8 +958,10 @@ CONFIG_ZLIB_INFLATE=m # # Kernel hacking # +# CONFIG_PRINTK_TIME is not set CONFIG_DEBUG_KERNEL=y # CONFIG_MAGIC_SYSRQ is not set +CONFIG_LOG_BUF_SHIFT=14 # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index c610ca933a2..76a55a438f2 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_POWER4) += cpu_setup_power4.o obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-mapping.o obj-$(CONFIG_PCI) += pci.o +obj-$(CONFIG_RAPIDIO) += rio.o obj-$(CONFIG_KGDB) += ppc-stub.o obj-$(CONFIG_SMP) += smp.o smp-tbsync.o obj-$(CONFIG_TAU) += temp.o diff --git a/arch/ppc/kernel/rio.c b/arch/ppc/kernel/rio.c new file mode 100644 index 00000000000..29487fedfc7 --- /dev/null +++ b/arch/ppc/kernel/rio.c @@ -0,0 +1,52 @@ +/* + * RapidIO PPC32 support + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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 + * option) any later version. + */ + +#include +#include +#include + +#include + +/** + * platform_rio_init - Do platform specific RIO init + * + * Any platform specific initialization of RapdIO + * hardware is done here as well as registration + * of any active master ports in the system. + */ +void __attribute__ ((weak)) + platform_rio_init(void) +{ + printk(KERN_WARNING "RIO: No platform_rio_init() present\n"); +} + +/** + * ppc_rio_init - Do PPC32 RIO init + * + * Calls platform-specific RIO init code and then calls + * rio_init_mports() to initialize any master ports that + * have been registered with the RIO subsystem. + */ +static int __init ppc_rio_init(void) +{ + printk(KERN_INFO "RIO: RapidIO init\n"); + + /* Platform specific initialization */ + platform_rio_init(); + + /* Enumerate all registered ports */ + rio_init_mports(); + + return 0; +} + +subsys_initcall(ppc_rio_init); diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c index bd3ac013675..16ad092d8a0 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c @@ -45,6 +45,8 @@ #include +#include + #include #ifndef CONFIG_PCI @@ -189,3 +191,11 @@ mpc85xx_exclude_device(u_char bus, u_char devfn) } #endif /* CONFIG_PCI */ + +#ifdef CONFIG_RAPIDIO +void platform_rio_init(void) +{ + /* 512MB RIO LAW at 0xc0000000 */ + mpc85xx_rio_setup(0xc0000000, 0x20000000); +} +#endif /* CONFIG_RAPIDIO */ diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c index 1e1b85f8193..15ce9d07063 100644 --- a/arch/ppc/platforms/85xx/stx_gp3.c +++ b/arch/ppc/platforms/85xx/stx_gp3.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -57,6 +58,7 @@ #include #include +#include unsigned char __res[sizeof(bd_t)]; @@ -273,6 +275,18 @@ int mpc85xx_exclude_device(u_char bus, u_char devfn) } #endif /* CONFIG_PCI */ +#ifdef CONFIG_RAPIDIO +void +platform_rio_init(void) +{ + /* + * The STx firmware configures the RapidIO Local Access Window + * at 0xc0000000 with a size of 512MB. + */ + mpc85xx_rio_setup(0xc0000000, 0x20000000); +} +#endif /* CONFIG_RAPIDIO */ + void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index dcd168f9a7a..5bd33baac24 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_PPC4xx_DMA) += ppc4xx_dma.o obj-$(CONFIG_PPC4xx_EDMA) += ppc4xx_sgdma.o ifeq ($(CONFIG_40x),y) obj-$(CONFIG_PCI) += pci_auto.o ppc405_pci.o +obj-$(CONFIG_RAPIDIO) += ppc85xx_rio.o endif endif obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \ diff --git a/arch/ppc/syslib/ppc85xx_rio.c b/arch/ppc/syslib/ppc85xx_rio.c new file mode 100644 index 00000000000..9d09c2715e0 --- /dev/null +++ b/arch/ppc/syslib/ppc85xx_rio.c @@ -0,0 +1,932 @@ +/* + * MPC85xx RapidIO support + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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 + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define RIO_REGS_BASE (CCSRBAR + 0xc0000) +#define RIO_ATMU_REGS_OFFSET 0x10c00 +#define RIO_MSG_REGS_OFFSET 0x11000 +#define RIO_MAINT_WIN_SIZE 0x400000 +#define RIO_DBELL_WIN_SIZE 0x1000 + +#define RIO_MSG_OMR_MUI 0x00000002 +#define RIO_MSG_OSR_TE 0x00000080 +#define RIO_MSG_OSR_QOI 0x00000020 +#define RIO_MSG_OSR_QFI 0x00000010 +#define RIO_MSG_OSR_MUB 0x00000004 +#define RIO_MSG_OSR_EOMI 0x00000002 +#define RIO_MSG_OSR_QEI 0x00000001 + +#define RIO_MSG_IMR_MI 0x00000002 +#define RIO_MSG_ISR_TE 0x00000080 +#define RIO_MSG_ISR_QFI 0x00000010 +#define RIO_MSG_ISR_DIQI 0x00000001 + +#define RIO_MSG_DESC_SIZE 32 +#define RIO_MSG_BUFFER_SIZE 4096 +#define RIO_MIN_TX_RING_SIZE 2 +#define RIO_MAX_TX_RING_SIZE 2048 +#define RIO_MIN_RX_RING_SIZE 2 +#define RIO_MAX_RX_RING_SIZE 2048 + +#define DOORBELL_DMR_DI 0x00000002 +#define DOORBELL_DSR_TE 0x00000080 +#define DOORBELL_DSR_QFI 0x00000010 +#define DOORBELL_DSR_DIQI 0x00000001 +#define DOORBELL_TID_OFFSET 0x03 +#define DOORBELL_SID_OFFSET 0x05 +#define DOORBELL_INFO_OFFSET 0x06 + +#define DOORBELL_MESSAGE_SIZE 0x08 +#define DBELL_SID(x) (*(u8 *)(x + DOORBELL_SID_OFFSET)) +#define DBELL_TID(x) (*(u8 *)(x + DOORBELL_TID_OFFSET)) +#define DBELL_INF(x) (*(u16 *)(x + DOORBELL_INFO_OFFSET)) + +#define is_power_of_2(x) (((x) & ((x) - 1)) == 0) + +struct rio_atmu_regs { + u32 rowtar; + u32 pad1; + u32 rowbar; + u32 pad2; + u32 rowar; + u32 pad3[3]; +}; + +struct rio_msg_regs { + u32 omr; + u32 osr; + u32 pad1; + u32 odqdpar; + u32 pad2; + u32 osar; + u32 odpr; + u32 odatr; + u32 odcr; + u32 pad3; + u32 odqepar; + u32 pad4[13]; + u32 imr; + u32 isr; + u32 pad5; + u32 ifqdpar; + u32 pad6; + u32 ifqepar; + u32 pad7[250]; + u32 dmr; + u32 dsr; + u32 pad8; + u32 dqdpar; + u32 pad9; + u32 dqepar; + u32 pad10[26]; + u32 pwmr; + u32 pwsr; + u32 pad11; + u32 pwqbar; +}; + +struct rio_tx_desc { + u32 res1; + u32 saddr; + u32 dport; + u32 dattr; + u32 res2; + u32 res3; + u32 dwcnt; + u32 res4; +}; + +static u32 regs_win; +static struct rio_atmu_regs *atmu_regs; +static struct rio_atmu_regs *maint_atmu_regs; +static struct rio_atmu_regs *dbell_atmu_regs; +static u32 dbell_win; +static u32 maint_win; +static struct rio_msg_regs *msg_regs; + +static struct rio_dbell_ring { + void *virt; + dma_addr_t phys; +} dbell_ring; + +static struct rio_msg_tx_ring { + void *virt; + dma_addr_t phys; + void *virt_buffer[RIO_MAX_TX_RING_SIZE]; + dma_addr_t phys_buffer[RIO_MAX_TX_RING_SIZE]; + int tx_slot; + int size; +} msg_tx_ring; + +static struct rio_msg_rx_ring { + void *virt; + dma_addr_t phys; + void *virt_buffer[RIO_MAX_RX_RING_SIZE]; + int rx_slot; + int size; +} msg_rx_ring; + +/** + * mpc85xx_rio_doorbell_send - Send a MPC85xx doorbell message + * @index: ID of RapidIO interface + * @destid: Destination ID of target device + * @data: 16-bit info field of RapidIO doorbell message + * + * Sends a MPC85xx doorbell message. Returns %0 on success or + * %-EINVAL on failure. + */ +static int mpc85xx_rio_doorbell_send(int index, u16 destid, u16 data) +{ + pr_debug("mpc85xx_doorbell_send: index %d destid %4.4x data %4.4x\n", + index, destid, data); + out_be32((void *)&dbell_atmu_regs->rowtar, destid << 22); + out_be16((void *)(dbell_win), data); + + return 0; +} + +/** + * mpc85xx_local_config_read - Generate a MPC85xx local config space read + * @index: ID of RapdiIO interface + * @offset: Offset into configuration space + * @len: Length (in bytes) of the maintenance transaction + * @data: Value to be read into + * + * Generates a MPC85xx local configuration space read. Returns %0 on + * success or %-EINVAL on failure. + */ +static int mpc85xx_local_config_read(int index, u32 offset, int len, u32 * data) +{ + pr_debug("mpc85xx_local_config_read: index %d offset %8.8x\n", index, + offset); + *data = in_be32((void *)(regs_win + offset)); + + return 0; +} + +/** + * mpc85xx_local_config_write - Generate a MPC85xx local config space write + * @index: ID of RapdiIO interface + * @offset: Offset into configuration space + * @len: Length (in bytes) of the maintenance transaction + * @data: Value to be written + * + * Generates a MPC85xx local configuration space write. Returns %0 on + * success or %-EINVAL on failure. + */ +static int mpc85xx_local_config_write(int index, u32 offset, int len, u32 data) +{ + pr_debug + ("mpc85xx_local_config_write: index %d offset %8.8x data %8.8x\n", + index, offset, data); + out_be32((void *)(regs_win + offset), data); + + return 0; +} + +/** + * mpc85xx_rio_config_read - Generate a MPC85xx read maintenance transaction + * @index: ID of RapdiIO interface + * @destid: Destination ID of transaction + * @hopcount: Number of hops to target device + * @offset: Offset into configuration space + * @len: Length (in bytes) of the maintenance transaction + * @val: Location to be read into + * + * Generates a MPC85xx read maintenance transaction. Returns %0 on + * success or %-EINVAL on failure. + */ +static int +mpc85xx_rio_config_read(int index, u16 destid, u8 hopcount, u32 offset, int len, + u32 * val) +{ + u8 *data; + + pr_debug + ("mpc85xx_rio_config_read: index %d destid %d hopcount %d offset %8.8x len %d\n", + index, destid, hopcount, offset, len); + out_be32((void *)&maint_atmu_regs->rowtar, + (destid << 22) | (hopcount << 12) | ((offset & ~0x3) >> 9)); + + data = (u8 *) maint_win + offset; + switch (len) { + case 1: + *val = in_8((u8 *) data); + break; + case 2: + *val = in_be16((u16 *) data); + break; + default: + *val = in_be32((u32 *) data); + break; + } + + return 0; +} + +/** + * mpc85xx_rio_config_write - Generate a MPC85xx write maintenance transaction + * @index: ID of RapdiIO interface + * @destid: Destination ID of transaction + * @hopcount: Number of hops to target device + * @offset: Offset into configuration space + * @len: Length (in bytes) of the maintenance transaction + * @val: Value to be written + * + * Generates an MPC85xx write maintenance transaction. Returns %0 on + * success or %-EINVAL on failure. + */ +static int +mpc85xx_rio_config_write(int index, u16 destid, u8 hopcount, u32 offset, + int len, u32 val) +{ + u8 *data; + pr_debug + ("mpc85xx_rio_config_write: index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n", + index, destid, hopcount, offset, len, val); + out_be32((void *)&maint_atmu_regs->rowtar, + (destid << 22) | (hopcount << 12) | ((offset & ~0x3) >> 9)); + + data = (u8 *) maint_win + offset; + switch (len) { + case 1: + out_8((u8 *) data, val); + break; + case 2: + out_be16((u16 *) data, val); + break; + default: + out_be32((u32 *) data, val); + break; + } + + return 0; +} + +/** + * rio_hw_add_outb_message - Add message to the MPC85xx outbound message queue + * @mport: Master port with outbound message queue + * @rdev: Target of outbound message + * @mbox: Outbound mailbox + * @buffer: Message to add to outbound queue + * @len: Length of message + * + * Adds the @buffer message to the MPC85xx outbound message queue. Returns + * %0 on success or %-EINVAL on failure. + */ +int +rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, + void *buffer, size_t len) +{ + u32 omr; + struct rio_tx_desc *desc = + (struct rio_tx_desc *)msg_tx_ring.virt + msg_tx_ring.tx_slot; + int ret = 0; + + pr_debug + ("RIO: rio_hw_add_outb_message(): destid %4.4x mbox %d buffer %8.8x len %8.8x\n", + rdev->destid, mbox, (int)buffer, len); + + if ((len < 8) || (len > RIO_MAX_MSG_SIZE)) { + ret = -EINVAL; + goto out; + } + + /* Copy and clear rest of buffer */ + memcpy(msg_tx_ring.virt_buffer[msg_tx_ring.tx_slot], buffer, len); + if (len < (RIO_MAX_MSG_SIZE - 4)) + memset((void *)((u32) msg_tx_ring. + virt_buffer[msg_tx_ring.tx_slot] + len), 0, + RIO_MAX_MSG_SIZE - len); + + /* Set mbox field for message */ + desc->dport = mbox & 0x3; + + /* Enable EOMI interrupt, set priority, and set destid */ + desc->dattr = 0x28000000 | (rdev->destid << 2); + + /* Set transfer size aligned to next power of 2 (in double words) */ + desc->dwcnt = is_power_of_2(len) ? len : 1 << get_bitmask_order(len); + + /* Set snooping and source buffer address */ + desc->saddr = 0x00000004 | msg_tx_ring.phys_buffer[msg_tx_ring.tx_slot]; + + /* Increment enqueue pointer */ + omr = in_be32((void *)&msg_regs->omr); + out_be32((void *)&msg_regs->omr, omr | RIO_MSG_OMR_MUI); + + /* Go to next descriptor */ + if (++msg_tx_ring.tx_slot == msg_tx_ring.size) + msg_tx_ring.tx_slot = 0; + + out: + return ret; +} + +EXPORT_SYMBOL_GPL(rio_hw_add_outb_message); + +/** + * mpc85xx_rio_tx_handler - MPC85xx outbound message interrupt handler + * @irq: Linux interrupt number + * @dev_instance: Pointer to interrupt-specific data + * @regs: Register context + * + * Handles outbound message interrupts. Executes a register outbound + * mailbox event handler and acks the interrupt occurence. + */ +static irqreturn_t +mpc85xx_rio_tx_handler(int irq, void *dev_instance, struct pt_regs *regs) +{ + int osr; + struct rio_mport *port = (struct rio_mport *)dev_instance; + + osr = in_be32((void *)&msg_regs->osr); + + if (osr & RIO_MSG_OSR_TE) { + pr_info("RIO: outbound message transmission error\n"); + out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_TE); + goto out; + } + + if (osr & RIO_MSG_OSR_QOI) { + pr_info("RIO: outbound message queue overflow\n"); + out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_QOI); + goto out; + } + + if (osr & RIO_MSG_OSR_EOMI) { + u32 dqp = in_be32((void *)&msg_regs->odqdpar); + int slot = (dqp - msg_tx_ring.phys) >> 5; + port->outb_msg[0].mcback(port, -1, slot); + + /* Ack the end-of-message interrupt */ + out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_EOMI); + } + + out: + return IRQ_HANDLED; +} + +/** + * rio_open_outb_mbox - Initialize MPC85xx outbound mailbox + * @mport: Master port implementing the outbound message unit + * @mbox: Mailbox to open + * @entries: Number of entries in the outbound mailbox ring + * + * Initializes buffer ring, request the outbound message interrupt, + * and enables the outbound message unit. Returns %0 on success and + * %-EINVAL or %-ENOMEM on failure. + */ +int rio_open_outb_mbox(struct rio_mport *mport, int mbox, int entries) +{ + int i, j, rc = 0; + + if ((entries < RIO_MIN_TX_RING_SIZE) || + (entries > RIO_MAX_TX_RING_SIZE) || (!is_power_of_2(entries))) { + rc = -EINVAL; + goto out; + } + + /* Initialize shadow copy ring */ + msg_tx_ring.size = entries; + + for (i = 0; i < msg_tx_ring.size; i++) { + if (! + (msg_tx_ring.virt_buffer[i] = + dma_alloc_coherent(NULL, RIO_MSG_BUFFER_SIZE, + &msg_tx_ring.phys_buffer[i], + GFP_KERNEL))) { + rc = -ENOMEM; + for (j = 0; j < msg_tx_ring.size; j++) + if (msg_tx_ring.virt_buffer[j]) + dma_free_coherent(NULL, + RIO_MSG_BUFFER_SIZE, + msg_tx_ring. + virt_buffer[j], + msg_tx_ring. + phys_buffer[j]); + goto out; + } + } + + /* Initialize outbound message descriptor ring */ + if (!(msg_tx_ring.virt = dma_alloc_coherent(NULL, + msg_tx_ring.size * + RIO_MSG_DESC_SIZE, + &msg_tx_ring.phys, + GFP_KERNEL))) { + rc = -ENOMEM; + goto out_dma; + } + memset(msg_tx_ring.virt, 0, msg_tx_ring.size * RIO_MSG_DESC_SIZE); + msg_tx_ring.tx_slot = 0; + + /* Point dequeue/enqueue pointers at first entry in ring */ + out_be32((void *)&msg_regs->odqdpar, msg_tx_ring.phys); + out_be32((void *)&msg_regs->odqepar, msg_tx_ring.phys); + + /* Configure for snooping */ + out_be32((void *)&msg_regs->osar, 0x00000004); + + /* Clear interrupt status */ + out_be32((void *)&msg_regs->osr, 0x000000b3); + + /* Hook up outbound message handler */ + if ((rc = + request_irq(MPC85xx_IRQ_RIO_TX, mpc85xx_rio_tx_handler, 0, + "msg_tx", (void *)mport)) < 0) + goto out_irq; + + /* + * Configure outbound message unit + * Snooping + * Interrupts (all enabled, except QEIE) + * Chaining mode + * Disable + */ + out_be32((void *)&msg_regs->omr, 0x00100220); + + /* Set number of entries */ + out_be32((void *)&msg_regs->omr, + in_be32((void *)&msg_regs->omr) | + ((get_bitmask_order(entries) - 2) << 12)); + + /* Now enable the unit */ + out_be32((void *)&msg_regs->omr, in_be32((void *)&msg_regs->omr) | 0x1); + + out: + return rc; + + out_irq: + dma_free_coherent(NULL, msg_tx_ring.size * RIO_MSG_DESC_SIZE, + msg_tx_ring.virt, msg_tx_ring.phys); + + out_dma: + for (i = 0; i < msg_tx_ring.size; i++) + dma_free_coherent(NULL, RIO_MSG_BUFFER_SIZE, + msg_tx_ring.virt_buffer[i], + msg_tx_ring.phys_buffer[i]); + + return rc; +} + +/** + * rio_close_outb_mbox - Shut down MPC85xx outbound mailbox + * @mport: Master port implementing the outbound message unit + * @mbox: Mailbox to close + * + * Disables the outbound message unit, free all buffers, and + * frees the outbound message interrupt. + */ +void rio_close_outb_mbox(struct rio_mport *mport, int mbox) +{ + /* Disable inbound message unit */ + out_be32((void *)&msg_regs->omr, 0); + + /* Free ring */ + dma_free_coherent(NULL, msg_tx_ring.size * RIO_MSG_DESC_SIZE, + msg_tx_ring.virt, msg_tx_ring.phys); + + /* Free interrupt */ + free_irq(MPC85xx_IRQ_RIO_TX, (void *)mport); +} + +/** + * mpc85xx_rio_rx_handler - MPC85xx inbound message interrupt handler + * @irq: Linux interrupt number + * @dev_instance: Pointer to interrupt-specific data + * @regs: Register context + * + * Handles inbound message interrupts. Executes a registered inbound + * mailbox event handler and acks the interrupt occurence. + */ +static irqreturn_t +mpc85xx_rio_rx_handler(int irq, void *dev_instance, struct pt_regs *regs) +{ + int isr; + struct rio_mport *port = (struct rio_mport *)dev_instance; + + isr = in_be32((void *)&msg_regs->isr); + + if (isr & RIO_MSG_ISR_TE) { + pr_info("RIO: inbound message reception error\n"); + out_be32((void *)&msg_regs->isr, RIO_MSG_ISR_TE); + goto out; + } + + /* XXX Need to check/dispatch until queue empty */ + if (isr & RIO_MSG_ISR_DIQI) { + /* + * We implement *only* mailbox 0, but can receive messages + * for any mailbox/letter to that mailbox destination. So, + * make the callback with an unknown/invalid mailbox number + * argument. + */ + port->inb_msg[0].mcback(port, -1, -1); + + /* Ack the queueing interrupt */ + out_be32((void *)&msg_regs->isr, RIO_MSG_ISR_DIQI); + } + + out: + return IRQ_HANDLED; +} + +/** + * rio_open_inb_mbox - Initialize MPC85xx inbound mailbox + * @mport: Master port implementing the inbound message unit + * @mbox: Mailbox to open + * @entries: Number of entries in the inbound mailbox ring + * + * Initializes buffer ring, request the inbound message interrupt, + * and enables the inbound message unit. Returns %0 on success + * and %-EINVAL or %-ENOMEM on failure. + */ +int rio_open_inb_mbox(struct rio_mport *mport, int mbox, int entries) +{ + int i, rc = 0; + + if ((entries < RIO_MIN_RX_RING_SIZE) || + (entries > RIO_MAX_RX_RING_SIZE) || (!is_power_of_2(entries))) { + rc = -EINVAL; + goto out; + } + + /* Initialize client buffer ring */ + msg_rx_ring.size = entries; + msg_rx_ring.rx_slot = 0; + for (i = 0; i < msg_rx_ring.size; i++) + msg_rx_ring.virt_buffer[i] = NULL; + + /* Initialize inbound message ring */ + if (!(msg_rx_ring.virt = dma_alloc_coherent(NULL, + msg_rx_ring.size * + RIO_MAX_MSG_SIZE, + &msg_rx_ring.phys, + GFP_KERNEL))) { + rc = -ENOMEM; + goto out; + } + + /* Point dequeue/enqueue pointers at first entry in ring */ + out_be32((void *)&msg_regs->ifqdpar, (u32) msg_rx_ring.phys); + out_be32((void *)&msg_regs->ifqepar, (u32) msg_rx_ring.phys); + + /* Clear interrupt status */ + out_be32((void *)&msg_regs->isr, 0x00000091); + + /* Hook up inbound message handler */ + if ((rc = + request_irq(MPC85xx_IRQ_RIO_RX, mpc85xx_rio_rx_handler, 0, + "msg_rx", (void *)mport)) < 0) { + dma_free_coherent(NULL, RIO_MSG_BUFFER_SIZE, + msg_tx_ring.virt_buffer[i], + msg_tx_ring.phys_buffer[i]); + goto out; + } + + /* + * Configure inbound message unit: + * Snooping + * 4KB max message size + * Unmask all interrupt sources + * Disable + */ + out_be32((void *)&msg_regs->imr, 0x001b0060); + + /* Set number of queue entries */ + out_be32((void *)&msg_regs->imr, + in_be32((void *)&msg_regs->imr) | + ((get_bitmask_order(entries) - 2) << 12)); + + /* Now enable the unit */ + out_be32((void *)&msg_regs->imr, in_be32((void *)&msg_regs->imr) | 0x1); + + out: + return rc; +} + +/** + * rio_close_inb_mbox - Shut down MPC85xx inbound mailbox + * @mport: Master port implementing the inbound message unit + * @mbox: Mailbox to close + * + * Disables the inbound message unit, free all buffers, and + * frees the inbound message interrupt. + */ +void rio_close_inb_mbox(struct rio_mport *mport, int mbox) +{ + /* Disable inbound message unit */ + out_be32((void *)&msg_regs->imr, 0); + + /* Free ring */ + dma_free_coherent(NULL, msg_rx_ring.size * RIO_MAX_MSG_SIZE, + msg_rx_ring.virt, msg_rx_ring.phys); + + /* Free interrupt */ + free_irq(MPC85xx_IRQ_RIO_RX, (void *)mport); +} + +/** + * rio_hw_add_inb_buffer - Add buffer to the MPC85xx inbound message queue + * @mport: Master port implementing the inbound message unit + * @mbox: Inbound mailbox number + * @buf: Buffer to add to inbound queue + * + * Adds the @buf buffer to the MPC85xx inbound message queue. Returns + * %0 on success or %-EINVAL on failure. + */ +int rio_hw_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf) +{ + int rc = 0; + + pr_debug("RIO: rio_hw_add_inb_buffer(), msg_rx_ring.rx_slot %d\n", + msg_rx_ring.rx_slot); + + if (msg_rx_ring.virt_buffer[msg_rx_ring.rx_slot]) { + printk(KERN_ERR + "RIO: error adding inbound buffer %d, buffer exists\n", + msg_rx_ring.rx_slot); + rc = -EINVAL; + goto out; + } + + msg_rx_ring.virt_buffer[msg_rx_ring.rx_slot] = buf; + if (++msg_rx_ring.rx_slot == msg_rx_ring.size) + msg_rx_ring.rx_slot = 0; + + out: + return rc; +} + +EXPORT_SYMBOL_GPL(rio_hw_add_inb_buffer); + +/** + * rio_hw_get_inb_message - Fetch inbound message from the MPC85xx message unit + * @mport: Master port implementing the inbound message unit + * @mbox: Inbound mailbox number + * + * Gets the next available inbound message from the inbound message queue. + * A pointer to the message is returned on success or NULL on failure. + */ +void *rio_hw_get_inb_message(struct rio_mport *mport, int mbox) +{ + u32 imr; + u32 phys_buf, virt_buf; + void *buf = NULL; + int buf_idx; + + phys_buf = in_be32((void *)&msg_regs->ifqdpar); + + /* If no more messages, then bail out */ + if (phys_buf == in_be32((void *)&msg_regs->ifqepar)) + goto out2; + + virt_buf = (u32) msg_rx_ring.virt + (phys_buf - msg_rx_ring.phys); + buf_idx = (phys_buf - msg_rx_ring.phys) / RIO_MAX_MSG_SIZE; + buf = msg_rx_ring.virt_buffer[buf_idx]; + + if (!buf) { + printk(KERN_ERR + "RIO: inbound message copy failed, no buffers\n"); + goto out1; + } + + /* Copy max message size, caller is expected to allocate that big */ + memcpy(buf, (void *)virt_buf, RIO_MAX_MSG_SIZE); + + /* Clear the available buffer */ + msg_rx_ring.virt_buffer[buf_idx] = NULL; + + out1: + imr = in_be32((void *)&msg_regs->imr); + out_be32((void *)&msg_regs->imr, imr | RIO_MSG_IMR_MI); + + out2: + return buf; +} + +EXPORT_SYMBOL_GPL(rio_hw_get_inb_message); + +/** + * mpc85xx_rio_dbell_handler - MPC85xx doorbell interrupt handler + * @irq: Linux interrupt number + * @dev_instance: Pointer to interrupt-specific data + * @regs: Register context + * + * Handles doorbell interrupts. Parses a list of registered + * doorbell event handlers and executes a matching event handler. + */ +static irqreturn_t +mpc85xx_rio_dbell_handler(int irq, void *dev_instance, struct pt_regs *regs) +{ + int dsr; + struct rio_mport *port = (struct rio_mport *)dev_instance; + + dsr = in_be32((void *)&msg_regs->dsr); + + if (dsr & DOORBELL_DSR_TE) { + pr_info("RIO: doorbell reception error\n"); + out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_TE); + goto out; + } + + if (dsr & DOORBELL_DSR_QFI) { + pr_info("RIO: doorbell queue full\n"); + out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_QFI); + goto out; + } + + /* XXX Need to check/dispatch until queue empty */ + if (dsr & DOORBELL_DSR_DIQI) { + u32 dmsg = + (u32) dbell_ring.virt + + (in_be32((void *)&msg_regs->dqdpar) & 0xfff); + u32 dmr; + struct rio_dbell *dbell; + int found = 0; + + pr_debug + ("RIO: processing doorbell, sid %2.2x tid %2.2x info %4.4x\n", + DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg)); + + list_for_each_entry(dbell, &port->dbells, node) { + if ((dbell->res->start <= DBELL_INF(dmsg)) && + (dbell->res->end >= DBELL_INF(dmsg))) { + found = 1; + break; + } + } + if (found) { + dbell->dinb(port, DBELL_SID(dmsg), DBELL_TID(dmsg), + DBELL_INF(dmsg)); + } else { + pr_debug + ("RIO: spurious doorbell, sid %2.2x tid %2.2x info %4.4x\n", + DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg)); + } + dmr = in_be32((void *)&msg_regs->dmr); + out_be32((void *)&msg_regs->dmr, dmr | DOORBELL_DMR_DI); + out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_DIQI); + } + + out: + return IRQ_HANDLED; +} + +/** + * mpc85xx_rio_doorbell_init - MPC85xx doorbell interface init + * @mport: Master port implementing the inbound doorbell unit + * + * Initializes doorbell unit hardware and inbound DMA buffer + * ring. Called from mpc85xx_rio_setup(). Returns %0 on success + * or %-ENOMEM on failure. + */ +static int mpc85xx_rio_doorbell_init(struct rio_mport *mport) +{ + int rc = 0; + + /* Map outbound doorbell window immediately after maintenance window */ + if (!(dbell_win = + (u32) ioremap(mport->iores.start + RIO_MAINT_WIN_SIZE, + RIO_DBELL_WIN_SIZE))) { + printk(KERN_ERR + "RIO: unable to map outbound doorbell window\n"); + rc = -ENOMEM; + goto out; + } + + /* Initialize inbound doorbells */ + if (!(dbell_ring.virt = dma_alloc_coherent(NULL, + 512 * DOORBELL_MESSAGE_SIZE, + &dbell_ring.phys, + GFP_KERNEL))) { + printk(KERN_ERR "RIO: unable allocate inbound doorbell ring\n"); + rc = -ENOMEM; + iounmap((void *)dbell_win); + goto out; + } + + /* Point dequeue/enqueue pointers at first entry in ring */ + out_be32((void *)&msg_regs->dqdpar, (u32) dbell_ring.phys); + out_be32((void *)&msg_regs->dqepar, (u32) dbell_ring.phys); + + /* Clear interrupt status */ + out_be32((void *)&msg_regs->dsr, 0x00000091); + + /* Hook up doorbell handler */ + if ((rc = + request_irq(MPC85xx_IRQ_RIO_BELL, mpc85xx_rio_dbell_handler, 0, + "dbell_rx", (void *)mport) < 0)) { + iounmap((void *)dbell_win); + dma_free_coherent(NULL, 512 * DOORBELL_MESSAGE_SIZE, + dbell_ring.virt, dbell_ring.phys); + printk(KERN_ERR + "MPC85xx RIO: unable to request inbound doorbell irq"); + goto out; + } + + /* Configure doorbells for snooping, 512 entries, and enable */ + out_be32((void *)&msg_regs->dmr, 0x00108161); + + out: + return rc; +} + +static char *cmdline = NULL; + +static int mpc85xx_rio_get_hdid(int index) +{ + /* XXX Need to parse multiple entries in some format */ + if (!cmdline) + return -1; + + return simple_strtol(cmdline, NULL, 0); +} + +static int mpc85xx_rio_get_cmdline(char *s) +{ + if (!s) + return 0; + + cmdline = s; + return 1; +} + +__setup("riohdid=", mpc85xx_rio_get_cmdline); + +/** + * mpc85xx_rio_setup - Setup MPC85xx RapidIO interface + * @law_start: Starting physical address of RapidIO LAW + * @law_size: Size of RapidIO LAW + * + * Initializes MPC85xx RapidIO hardware interface, configures + * master port with system-specific info, and registers the + * master port with the RapidIO subsystem. + */ +void mpc85xx_rio_setup(int law_start, int law_size) +{ + struct rio_ops *ops; + struct rio_mport *port; + + ops = kmalloc(sizeof(struct rio_ops), GFP_KERNEL); + ops->lcread = mpc85xx_local_config_read; + ops->lcwrite = mpc85xx_local_config_write; + ops->cread = mpc85xx_rio_config_read; + ops->cwrite = mpc85xx_rio_config_write; + ops->dsend = mpc85xx_rio_doorbell_send; + + port = kmalloc(sizeof(struct rio_mport), GFP_KERNEL); + port->id = 0; + port->index = 0; + INIT_LIST_HEAD(&port->dbells); + port->iores.start = law_start; + port->iores.end = law_start + law_size; + port->iores.flags = IORESOURCE_MEM; + + rio_init_dbell_res(&port->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff); + rio_init_mbox_res(&port->riores[RIO_INB_MBOX_RESOURCE], 0, 0); + rio_init_mbox_res(&port->riores[RIO_OUTB_MBOX_RESOURCE], 0, 0); + strcpy(port->name, "RIO0 mport"); + + port->ops = ops; + port->host_deviceid = mpc85xx_rio_get_hdid(port->id); + + rio_register_mport(port); + + regs_win = (u32) ioremap(RIO_REGS_BASE, 0x20000); + atmu_regs = (struct rio_atmu_regs *)(regs_win + RIO_ATMU_REGS_OFFSET); + maint_atmu_regs = atmu_regs + 1; + dbell_atmu_regs = atmu_regs + 2; + msg_regs = (struct rio_msg_regs *)(regs_win + RIO_MSG_REGS_OFFSET); + + /* Configure maintenance transaction window */ + out_be32((void *)&maint_atmu_regs->rowbar, 0x000c0000); + out_be32((void *)&maint_atmu_regs->rowar, 0x80077015); + + maint_win = (u32) ioremap(law_start, RIO_MAINT_WIN_SIZE); + + /* Configure outbound doorbell window */ + out_be32((void *)&dbell_atmu_regs->rowbar, 0x000c0400); + out_be32((void *)&dbell_atmu_regs->rowar, 0x8004200b); + mpc85xx_rio_doorbell_init(port); +} diff --git a/arch/ppc/syslib/ppc85xx_rio.h b/arch/ppc/syslib/ppc85xx_rio.h new file mode 100644 index 00000000000..c0827a2c3ee --- /dev/null +++ b/arch/ppc/syslib/ppc85xx_rio.h @@ -0,0 +1,21 @@ +/* + * MPC85xx RapidIO definitions + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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 + * option) any later version. + */ + +#ifndef __PPC_SYSLIB_PPC85XX_RIO_H +#define __PPC_SYSLIB_PPC85XX_RIO_H + +#include +#include + +extern void mpc85xx_rio_setup(int law_start, int law_size); + +#endif /* __PPC_SYSLIB_PPC85XX_RIO_H */ diff --git a/include/asm-ppc/rio.h b/include/asm-ppc/rio.h new file mode 100644 index 00000000000..0018bf80cb2 --- /dev/null +++ b/include/asm-ppc/rio.h @@ -0,0 +1,18 @@ +/* + * RapidIO architecture support + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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 + * option) any later version. + */ + +#ifndef ASM_PPC_RIO_H +#define ASM_PPC_RIO_H + +extern void platform_rio_init(void); + +#endif /* ASM_PPC_RIO_H */ -- cgit v1.2.3 From 6978bbc097c2f665c336927a9d56ae39ef75fa56 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 7 Nov 2005 01:00:20 -0800 Subject: [PATCH] rapidio: message interface updates Updates the RIO messaging interface to pass a device instance into the event registeration and callbacks. Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/syslib/ppc85xx_rio.c | 16 +++++++++++----- drivers/rapidio/rio-sysfs.c | 4 ++-- drivers/rapidio/rio.c | 25 ++++++++++++++++--------- include/linux/rio.h | 10 ++++++---- include/linux/rio_drv.h | 12 ++++++------ 5 files changed, 41 insertions(+), 26 deletions(-) diff --git a/arch/ppc/syslib/ppc85xx_rio.c b/arch/ppc/syslib/ppc85xx_rio.c index 9d09c2715e0..297f3b54917 100644 --- a/arch/ppc/syslib/ppc85xx_rio.c +++ b/arch/ppc/syslib/ppc85xx_rio.c @@ -135,6 +135,7 @@ static struct rio_msg_tx_ring { dma_addr_t phys_buffer[RIO_MAX_TX_RING_SIZE]; int tx_slot; int size; + void *dev_id; } msg_tx_ring; static struct rio_msg_rx_ring { @@ -143,6 +144,7 @@ static struct rio_msg_rx_ring { void *virt_buffer[RIO_MAX_RX_RING_SIZE]; int rx_slot; int size; + void *dev_id; } msg_rx_ring; /** @@ -376,7 +378,7 @@ mpc85xx_rio_tx_handler(int irq, void *dev_instance, struct pt_regs *regs) if (osr & RIO_MSG_OSR_EOMI) { u32 dqp = in_be32((void *)&msg_regs->odqdpar); int slot = (dqp - msg_tx_ring.phys) >> 5; - port->outb_msg[0].mcback(port, -1, slot); + port->outb_msg[0].mcback(port, msg_tx_ring.dev_id, -1, slot); /* Ack the end-of-message interrupt */ out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_EOMI); @@ -389,6 +391,7 @@ mpc85xx_rio_tx_handler(int irq, void *dev_instance, struct pt_regs *regs) /** * rio_open_outb_mbox - Initialize MPC85xx outbound mailbox * @mport: Master port implementing the outbound message unit + * @dev_id: Device specific pointer to pass on event * @mbox: Mailbox to open * @entries: Number of entries in the outbound mailbox ring * @@ -396,7 +399,7 @@ mpc85xx_rio_tx_handler(int irq, void *dev_instance, struct pt_regs *regs) * and enables the outbound message unit. Returns %0 on success and * %-EINVAL or %-ENOMEM on failure. */ -int rio_open_outb_mbox(struct rio_mport *mport, int mbox, int entries) +int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) { int i, j, rc = 0; @@ -407,6 +410,7 @@ int rio_open_outb_mbox(struct rio_mport *mport, int mbox, int entries) } /* Initialize shadow copy ring */ + msg_tx_ring.dev_id = dev_id; msg_tx_ring.size = entries; for (i = 0; i < msg_tx_ring.size; i++) { @@ -541,7 +545,7 @@ mpc85xx_rio_rx_handler(int irq, void *dev_instance, struct pt_regs *regs) * make the callback with an unknown/invalid mailbox number * argument. */ - port->inb_msg[0].mcback(port, -1, -1); + port->inb_msg[0].mcback(port, msg_rx_ring.dev_id, -1, -1); /* Ack the queueing interrupt */ out_be32((void *)&msg_regs->isr, RIO_MSG_ISR_DIQI); @@ -554,6 +558,7 @@ mpc85xx_rio_rx_handler(int irq, void *dev_instance, struct pt_regs *regs) /** * rio_open_inb_mbox - Initialize MPC85xx inbound mailbox * @mport: Master port implementing the inbound message unit + * @dev_id: Device specific pointer to pass on event * @mbox: Mailbox to open * @entries: Number of entries in the inbound mailbox ring * @@ -561,7 +566,7 @@ mpc85xx_rio_rx_handler(int irq, void *dev_instance, struct pt_regs *regs) * and enables the inbound message unit. Returns %0 on success * and %-EINVAL or %-ENOMEM on failure. */ -int rio_open_inb_mbox(struct rio_mport *mport, int mbox, int entries) +int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) { int i, rc = 0; @@ -572,6 +577,7 @@ int rio_open_inb_mbox(struct rio_mport *mport, int mbox, int entries) } /* Initialize client buffer ring */ + msg_rx_ring.dev_id = dev_id; msg_rx_ring.size = entries; msg_rx_ring.rx_slot = 0; for (i = 0; i < msg_rx_ring.size; i++) @@ -777,7 +783,7 @@ mpc85xx_rio_dbell_handler(int irq, void *dev_instance, struct pt_regs *regs) } } if (found) { - dbell->dinb(port, DBELL_SID(dmsg), DBELL_TID(dmsg), + dbell->dinb(port, dbell->dev_id, DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg)); } else { pr_debug diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c index 73218a37506..30a11436e24 100644 --- a/drivers/rapidio/rio-sysfs.c +++ b/drivers/rapidio/rio-sysfs.c @@ -21,7 +21,7 @@ /* Sysfs support */ #define rio_config_attr(field, format_string) \ static ssize_t \ - field##_show(struct device *dev, char *buf) \ +field##_show(struct device *dev, struct device_attribute *attr, char *buf) \ { \ struct rio_dev *rdev = to_rio_dev(dev); \ \ @@ -35,7 +35,7 @@ rio_config_attr(asm_did, "0x%04x\n"); rio_config_attr(asm_vid, "0x%04x\n"); rio_config_attr(asm_rev, "0x%04x\n"); -static ssize_t routes_show(struct device *dev, char *buf) +static ssize_t routes_show(struct device *dev, struct device_attribute *attr, char *buf) { struct rio_dev *rdev = to_rio_dev(dev); char *str = buf; diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index adc299e2b07..3ca1011ceaa 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -48,6 +48,7 @@ u16 rio_local_get_device_id(struct rio_mport *port) /** * rio_request_inb_mbox - request inbound mailbox service * @mport: RIO master port from which to allocate the mailbox resource + * @dev_id: Device specific pointer to pass on event * @mbox: Mailbox number to claim * @entries: Number of entries in inbound mailbox queue * @minb: Callback to execute when inbound message is received @@ -56,9 +57,10 @@ u16 rio_local_get_device_id(struct rio_mport *port) * a callback function to the resource. Returns %0 on success. */ int rio_request_inb_mbox(struct rio_mport *mport, + void *dev_id, int mbox, int entries, - void (*minb) (struct rio_mport * mport, int mbox, + void (*minb) (struct rio_mport * mport, void *dev_id, int mbox, int slot)) { int rc = 0; @@ -81,7 +83,7 @@ int rio_request_inb_mbox(struct rio_mport *mport, /* Hook the inbound message callback */ mport->inb_msg[mbox].mcback = minb; - rc = rio_open_inb_mbox(mport, mbox, entries); + rc = rio_open_inb_mbox(mport, dev_id, mbox, entries); } else rc = -ENOMEM; @@ -108,6 +110,7 @@ int rio_release_inb_mbox(struct rio_mport *mport, int mbox) /** * rio_request_outb_mbox - request outbound mailbox service * @mport: RIO master port from which to allocate the mailbox resource + * @dev_id: Device specific pointer to pass on event * @mbox: Mailbox number to claim * @entries: Number of entries in outbound mailbox queue * @moutb: Callback to execute when outbound message is sent @@ -116,10 +119,10 @@ int rio_release_inb_mbox(struct rio_mport *mport, int mbox) * a callback function to the resource. Returns 0 on success. */ int rio_request_outb_mbox(struct rio_mport *mport, + void *dev_id, int mbox, int entries, - void (*moutb) (struct rio_mport * mport, int mbox, - int slot)) + void (*moutb) (struct rio_mport * mport, void *dev_id, int mbox, int slot)) { int rc = 0; @@ -141,7 +144,7 @@ int rio_request_outb_mbox(struct rio_mport *mport, /* Hook the inbound message callback */ mport->outb_msg[mbox].mcback = moutb; - rc = rio_open_outb_mbox(mport, mbox, entries); + rc = rio_open_outb_mbox(mport, dev_id, mbox, entries); } else rc = -ENOMEM; @@ -168,6 +171,7 @@ int rio_release_outb_mbox(struct rio_mport *mport, int mbox) /** * rio_setup_inb_dbell - bind inbound doorbell callback * @mport: RIO master port to bind the doorbell callback + * @dev_id: Device specific pointer to pass on event * @res: Doorbell message resource * @dinb: Callback to execute when doorbell is received * @@ -176,8 +180,8 @@ int rio_release_outb_mbox(struct rio_mport *mport, int mbox) * satisfied. */ static int -rio_setup_inb_dbell(struct rio_mport *mport, struct resource *res, - void (*dinb) (struct rio_mport * mport, u16 src, u16 dst, +rio_setup_inb_dbell(struct rio_mport *mport, void *dev_id, struct resource *res, + void (*dinb) (struct rio_mport * mport, void *dev_id, u16 src, u16 dst, u16 info)) { int rc = 0; @@ -190,6 +194,7 @@ rio_setup_inb_dbell(struct rio_mport *mport, struct resource *res, dbell->res = res; dbell->dinb = dinb; + dbell->dev_id = dev_id; list_add_tail(&dbell->node, &mport->dbells); @@ -200,6 +205,7 @@ rio_setup_inb_dbell(struct rio_mport *mport, struct resource *res, /** * rio_request_inb_dbell - request inbound doorbell message service * @mport: RIO master port from which to allocate the doorbell resource + * @dev_id: Device specific pointer to pass on event * @start: Doorbell info range start * @end: Doorbell info range end * @dinb: Callback to execute when doorbell is received @@ -209,9 +215,10 @@ rio_setup_inb_dbell(struct rio_mport *mport, struct resource *res, * has been satisfied. */ int rio_request_inb_dbell(struct rio_mport *mport, + void *dev_id, u16 start, u16 end, - void (*dinb) (struct rio_mport * mport, u16 src, + void (*dinb) (struct rio_mport * mport, void *dev_id, u16 src, u16 dst, u16 info)) { int rc = 0; @@ -230,7 +237,7 @@ int rio_request_inb_dbell(struct rio_mport *mport, } /* Hook the doorbell callback */ - rc = rio_setup_inb_dbell(mport, res, dinb); + rc = rio_setup_inb_dbell(mport, dev_id, res, dinb); } else rc = -ENOMEM; diff --git a/include/linux/rio.h b/include/linux/rio.h index 5c29f2f477c..c7e907faae9 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h @@ -132,7 +132,7 @@ struct rio_dev { */ struct rio_msg { struct resource *res; - void (*mcback) (struct rio_mport * mport, int mbox, int slot); + void (*mcback) (struct rio_mport * mport, void *dev_id, int mbox, int slot); }; /** @@ -140,11 +140,13 @@ struct rio_msg { * @node: Node in list of doorbell events * @res: Doorbell resource * @dinb: Doorbell event callback + * @dev_id: Device specific pointer to pass on event */ struct rio_dbell { struct list_head node; struct resource *res; - void (*dinb) (struct rio_mport * mport, u16 src, u16 dst, u16 info); + void (*dinb) (struct rio_mport *mport, void *dev_id, u16 src, u16 dst, u16 info); + void *dev_id; }; /** @@ -314,9 +316,9 @@ extern int rio_hw_add_outb_message(struct rio_mport *, struct rio_dev *, int, void *, size_t); extern int rio_hw_add_inb_buffer(struct rio_mport *, int, void *); extern void *rio_hw_get_inb_message(struct rio_mport *, int); -extern int rio_open_inb_mbox(struct rio_mport *, int, int); +extern int rio_open_inb_mbox(struct rio_mport *, void *, int, int); extern void rio_close_inb_mbox(struct rio_mport *, int); -extern int rio_open_outb_mbox(struct rio_mport *, int, int); +extern int rio_open_outb_mbox(struct rio_mport *, void *, int, int); extern void rio_close_outb_mbox(struct rio_mport *, int); #endif /* __KERNEL__ */ diff --git a/include/linux/rio_drv.h b/include/linux/rio_drv.h index 7483dfc0dfa..3bd7cce19e2 100644 --- a/include/linux/rio_drv.h +++ b/include/linux/rio_drv.h @@ -348,8 +348,8 @@ static inline void rio_init_dbell_res(struct resource *res, u16 start, u16 end) .asm_did = RIO_ANY_ID, .asm_vid = RIO_ANY_ID /* Mailbox management */ -extern int rio_request_outb_mbox(struct rio_mport *, int, int, - void (*)(struct rio_mport *, int, int)); +extern int rio_request_outb_mbox(struct rio_mport *, void *, int, int, + void (*)(struct rio_mport *, void *,int, int)); extern int rio_release_outb_mbox(struct rio_mport *, int); /** @@ -370,8 +370,8 @@ static inline int rio_add_outb_message(struct rio_mport *mport, return rio_hw_add_outb_message(mport, rdev, mbox, buffer, len); } -extern int rio_request_inb_mbox(struct rio_mport *, int, int, - void (*)(struct rio_mport *, int, int)); +extern int rio_request_inb_mbox(struct rio_mport *, void *, int, int, + void (*)(struct rio_mport *, void *, int, int)); extern int rio_release_inb_mbox(struct rio_mport *, int); /** @@ -403,8 +403,8 @@ static inline void *rio_get_inb_message(struct rio_mport *mport, int mbox) } /* Doorbell management */ -extern int rio_request_inb_dbell(struct rio_mport *, u16, u16, - void (*)(struct rio_mport *, u16, u16, u16)); +extern int rio_request_inb_dbell(struct rio_mport *, void *, u16, u16, + void (*)(struct rio_mport *, void *, u16, u16, u16)); extern int rio_release_inb_dbell(struct rio_mport *, u16, u16); extern struct resource *rio_request_outb_dbell(struct rio_dev *, u16, u16); extern int rio_release_outb_dbell(struct rio_dev *, struct resource *); -- cgit v1.2.3 From 597a107b1d5587dc230dbbe3faeca242daed494e Mon Sep 17 00:00:00 2001 From: Martin Bachem Date: Mon, 7 Nov 2005 01:00:20 -0800 Subject: [PATCH] i4l: update hfc_usb driver - cleanup source - remove nonfunctional code parts Signed-off-by: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/hisax/hfc_usb.c | 292 +++++++++++++++++-------------------------- drivers/isdn/hisax/hfc_usb.h | 6 +- 2 files changed, 121 insertions(+), 177 deletions(-) diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c index e2c3af49d72..32bf0d5d0f9 100644 --- a/drivers/isdn/hisax/hfc_usb.c +++ b/drivers/isdn/hisax/hfc_usb.c @@ -1,7 +1,7 @@ /* * hfc_usb.c * - * $Id: hfc_usb.c,v 4.34 2005/01/26 17:25:53 martinb1 Exp $ + * $Id: hfc_usb.c,v 4.36 2005/04/08 09:55:13 martinb1 Exp $ * * modular HiSax ISDN driver for Colognechip HFC-S USB chip * @@ -44,12 +44,8 @@ #include "hisax_if.h" #include "hfc_usb.h" -/* -* Version Information -* (do not modify the CVS Makros $Revision: 4.34 $ and $Date: 2005/01/26 17:25:53 $ !) -*/ static const char *hfcusb_revision = - "Revision: 4.34 $ Date: 2005/01/26 17:25:53 $ "; + "$Revision: 4.36 $ $Date: 2005/04/08 09:55:13 $ "; /* Hisax debug support * use "modprobe debug=x" where x is bitfield of USB_DBG & ISDN_DBG @@ -63,81 +59,89 @@ module_param(debug, uint, 0); static int hfc_debug; #endif +/* private vendor specific data */ +typedef struct { + __u8 led_scheme; // led display scheme + signed short led_bits[8]; // array of 8 possible LED bitmask settings + char *vend_name; // device name +} hfcsusb_vdata; /****************************************/ /* data defining the devices to be used */ /****************************************/ -static struct usb_device_id hfc_usb_idtab[] = { - {USB_DEVICE(0x0959, 0x2bd0)}, /* Colognechip USB eval TA */ - {USB_DEVICE(0x0675, 0x1688)}, /* DrayTek miniVigor 128 USB ISDN TA */ - {USB_DEVICE(0x07b0, 0x0007)}, /* Billion USB TA 2 */ - {USB_DEVICE(0x0742, 0x2008)}, /* Stollmann USB TA */ - {USB_DEVICE(0x0742, 0x2009)}, /* Aceex USB ISDN TA */ - {USB_DEVICE(0x0742, 0x200A)}, /* OEM USB ISDN TA */ - {USB_DEVICE(0x08e3, 0x0301)}, /* OliTec ISDN USB */ - {USB_DEVICE(0x07fa, 0x0846)}, /* Bewan ISDN USB TA */ - {USB_DEVICE(0x07fa, 0x0847)}, /* Djinn Numeris USB */ - {USB_DEVICE(0x07b0, 0x0006)}, /* Twister ISDN USB TA */ - {} /* end with an all-zeroes entry */ +static struct usb_device_id hfcusb_idtab[] = { + { + .idVendor = 0x0959, + .idProduct = 0x2bd0, + .driver_info = (unsigned long) &((hfcsusb_vdata) + {LED_OFF, {4, 0, 2, 1}, + "ISDN USB TA (Cologne Chip HFC-S USB based)"}), + }, + { + .idVendor = 0x0675, + .idProduct = 0x1688, + .driver_info = (unsigned long) &((hfcsusb_vdata) + {LED_SCHEME1, {1, 2, 0, 0}, + "DrayTek miniVigor 128 USB ISDN TA"}), + }, + { + .idVendor = 0x07b0, + .idProduct = 0x0007, + .driver_info = (unsigned long) &((hfcsusb_vdata) + {LED_SCHEME1, {0x80, -64, -32, -16}, + "Billion tiny USB ISDN TA 128"}), + }, + { + .idVendor = 0x0742, + .idProduct = 0x2008, + .driver_info = (unsigned long) &((hfcsusb_vdata) + {LED_SCHEME1, {4, 0, 2, 1}, + "Stollmann USB TA"}), + }, + { + .idVendor = 0x0742, + .idProduct = 0x2009, + .driver_info = (unsigned long) &((hfcsusb_vdata) + {LED_SCHEME1, {4, 0, 2, 1}, + "Aceex USB ISDN TA"}), + }, + { + .idVendor = 0x0742, + .idProduct = 0x200A, + .driver_info = (unsigned long) &((hfcsusb_vdata) + {LED_SCHEME1, {4, 0, 2, 1}, + "OEM USB ISDN TA"}), + }, + { + .idVendor = 0x08e3, + .idProduct = 0x0301, + .driver_info = (unsigned long) &((hfcsusb_vdata) + {LED_SCHEME1, {2, 0, 1, 4}, + "Olitec USB RNIS"}), + }, + { + .idVendor = 0x07fa, + .idProduct = 0x0846, + .driver_info = (unsigned long) &((hfcsusb_vdata) + {LED_SCHEME1, {0x80, -64, -32, -16}, + "Bewan Modem RNIS USB"}), + }, + { + .idVendor = 0x07fa, + .idProduct = 0x0847, + .driver_info = (unsigned long) &((hfcsusb_vdata) + {LED_SCHEME1, {0x80, -64, -32, -16}, + "Djinn Numeris USB"}), + }, + { + .idVendor = 0x07b0, + .idProduct = 0x0006, + .driver_info = (unsigned long) &((hfcsusb_vdata) + {LED_SCHEME1, {0x80, -64, -32, -16}, + "Twister ISDN TA"}), + }, }; -/* driver internal device specific data: -* VendorID, ProductID, Devicename, LED_SCHEME, -* LED's BitMask in HFCUSB_P_DATA Register : LED_USB, LED_S0, LED_B1, LED_B2 -*/ -static vendor_data vdata[] = { - /* CologneChip Eval TA */ - {0x0959, 0x2bd0, "ISDN USB TA (Cologne Chip HFC-S USB based)", - LED_OFF, {4, 0, 2, 1} - } - , - /* DrayTek miniVigor 128 USB ISDN TA */ - {0x0675, 0x1688, "DrayTek miniVigor 128 USB ISDN TA", - LED_SCHEME1, {1, 2, 0, 0} - } - , - /* Billion TA */ - {0x07b0, 0x0007, "Billion tiny USB ISDN TA 128", - LED_SCHEME1, {0x80, -64, -32, -16} - } - , - /* Stollmann TA */ - {0x0742, 0x2008, "Stollmann USB TA", - LED_SCHEME1, {4, 0, 2, 1} - } - , - /* Aceex USB ISDN TA */ - {0x0742, 0x2009, "Aceex USB ISDN TA", - LED_SCHEME1, {4, 0, 2, 1} - } - , - /* OEM USB ISDN TA */ - {0x0742, 0x200A, "OEM USB ISDN TA", - LED_SCHEME1, {4, 0, 2, 1} - } - , - /* Olitec TA */ - {0x08e3, 0x0301, "Olitec USB RNIS", - LED_SCHEME1, {2, 0, 1, 4} - } - , - /* Bewan TA */ - {0x07fa, 0x0846, "Bewan Modem RNIS USB", - LED_SCHEME1, {0x80, -64, -32, -16} - } - , - /* Bewan TA */ - {0x07fa, 0x0847, "Djinn Numeris USB", - LED_SCHEME1, {0x80, -64, -32, -16} - } - , - /* Twister ISDN TA */ - {0x07b0, 0x0006, "Twister ISDN TA", - LED_SCHEME1, {0x80, -64, -32, -16} - } - , - {0, 0, 0} /* EOL element */ -}; /***************************************************************/ /* structure defining input+output fifos (interrupt/bulk mode) */ @@ -211,8 +215,6 @@ typedef struct hfcusb_data { volatile __u8 l1_state; /* actual l1 state */ struct timer_list t3_timer; /* timer 3 for activation/deactivation */ struct timer_list t4_timer; /* timer 4 for activation/deactivation */ - struct timer_list led_timer; /* timer flashing leds */ - } hfcusb_data; @@ -227,7 +229,7 @@ symbolic(struct hfcusb_symbolic_list list[], const int num) for (i = 0; list[i].name != NULL; i++) if (list[i].num == num) return (list[i].name); - return ""; + return ""; } @@ -335,93 +337,57 @@ set_led_bit(hfcusb_data * hfc, signed short led_bits, int unset) } } -/******************************************/ -/* invert B-channel LEDs if data is sent */ -/******************************************/ -static void -led_timer(hfcusb_data * hfc) -{ - static int cnt = 0; - - if (cnt) { - if (hfc->led_b_active & 1) - set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[2], - 0); - if (hfc->led_b_active & 2) - set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[3], - 0); - } else { - if (!(hfc->led_b_active & 1) || hfc->led_new_data & 1) - set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[2], - 1); - if (!(hfc->led_b_active & 2) || hfc->led_new_data & 2) - set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[3], - 1); - } - - write_led(hfc, hfc->led_state); - hfc->led_new_data = 0; - - cnt = !cnt; - - /* restart 4 hz timer */ - if (!timer_pending(&hfc->led_timer)) { - add_timer(&hfc->led_timer); - hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000; - } -} - /**************************/ /* handle LED requests */ /**************************/ static void handle_led(hfcusb_data * hfc, int event) { + hfcsusb_vdata *driver_info = + (hfcsusb_vdata *) hfcusb_idtab[hfc->vend_idx].driver_info; + /* if no scheme -> no LED action */ - if (vdata[hfc->vend_idx].led_scheme == LED_OFF) + if (driver_info->led_scheme == LED_OFF) return; switch (event) { case LED_POWER_ON: - set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[0], + set_led_bit(hfc, driver_info->led_bits[0], 0); - set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[1], + set_led_bit(hfc, driver_info->led_bits[1], 1); - set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[2], + set_led_bit(hfc, driver_info->led_bits[2], 1); - set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[3], + set_led_bit(hfc, driver_info->led_bits[3], 1); break; case LED_POWER_OFF: /* no Power off handling */ break; case LED_S0_ON: - set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[1], + set_led_bit(hfc, driver_info->led_bits[1], 0); break; case LED_S0_OFF: - set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[1], + set_led_bit(hfc, driver_info->led_bits[1], 1); break; case LED_B1_ON: - hfc->led_b_active |= 1; + set_led_bit(hfc, driver_info->led_bits[2], + 0); break; case LED_B1_OFF: - hfc->led_b_active &= ~1; - break; - case LED_B1_DATA: - hfc->led_new_data |= 1; + set_led_bit(hfc, driver_info->led_bits[2], + 1); break; case LED_B2_ON: - hfc->led_b_active |= 2; + set_led_bit(hfc, driver_info->led_bits[3], + 0); break; case LED_B2_OFF: - hfc->led_b_active &= ~2; - break; - case LED_B2_DATA: - hfc->led_new_data |= 2; + set_led_bit(hfc, driver_info->led_bits[3], + 1); break; } - write_led(hfc, hfc->led_state); } @@ -725,14 +691,6 @@ tx_iso_complete(struct urb *urb, struct pt_regs *regs) current_len + 1; tx_offset += (current_len + 1); - if (!transp_mode) { - if (fifon == HFCUSB_B1_TX) - handle_led(hfc, - LED_B1_DATA); - if (fifon == HFCUSB_B2_TX) - handle_led(hfc, - LED_B2_DATA); - } } else { urb->iso_frame_desc[k].offset = tx_offset++; @@ -966,14 +924,6 @@ collect_rx_frame(usb_fifo * fifo, __u8 * data, int len, int finish) skb_trim(fifo->skbuff, 0); } } - - /* LED flashing only in HDLC mode */ - if (!transp_mode) { - if (fifon == HFCUSB_B1_RX) - handle_led(hfc, LED_B1_DATA); - if (fifon == HFCUSB_B2_RX) - handle_led(hfc, LED_B2_DATA); - } } /***********************************************/ @@ -1339,17 +1289,6 @@ usb_init(hfcusb_data * hfc) hfc->t4_timer.data = (long) hfc; hfc->t4_timer.function = (void *) l1_timer_expire_t4; - /* init the led timer */ - init_timer(&hfc->led_timer); - hfc->led_timer.data = (long) hfc; - hfc->led_timer.function = (void *) led_timer; - - /* trigger 4 hz led timer */ - if (!timer_pending(&hfc->led_timer)) { - hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000; - add_timer(&hfc->led_timer); - } - /* init the background machinery for control requests */ hfc->ctrl_read.bRequestType = 0xc0; hfc->ctrl_read.bRequest = 1; @@ -1440,13 +1379,18 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) attr, cfg_found, cidx, ep_addr; int cmptbl[16], small_match, iso_packet_size, packet_size, alt_used = 0; + hfcsusb_vdata *driver_info; vend_idx = 0xffff; - for (i = 0; vdata[i].vendor; i++) { - if (dev->descriptor.idVendor == vdata[i].vendor - && dev->descriptor.idProduct == vdata[i].prod_id) + for (i = 0; hfcusb_idtab[i].idVendor; i++) { + if (dev->descriptor.idVendor == hfcusb_idtab[i].idVendor + && dev->descriptor.idProduct == + hfcusb_idtab[i].idProduct) { vend_idx = i; + continue; + } } + #ifdef CONFIG_HISAX_DEBUG DBG(USB_DBG, "HFC-USB: probing interface(%d) actalt(%d) minor(%d)\n", ifnum, @@ -1457,10 +1401,6 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) ifnum, iface->desc.bAlternateSetting, intf->minor); if (vend_idx != 0xffff) { -#ifdef CONFIG_HISAX_DEBUG - DBG(USB_DBG, "HFC-S USB: found vendor idx:%d name:%s", - vend_idx, vdata[vend_idx].vend_name); -#endif /* if vendor and product ID is OK, start probing alternate settings */ alt_idx = 0; small_match = 0xffff; @@ -1687,9 +1627,11 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) usb_sndctrlpipe(context->dev, 0); context->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL); - printk(KERN_INFO - "HFC-S USB: detected \"%s\"\n", - vdata[vend_idx].vend_name); + driver_info = + (hfcsusb_vdata *) hfcusb_idtab[vend_idx]. + driver_info; + printk(KERN_INFO "HFC-S USB: detected \"%s\"\n", + driver_info->vend_name); #ifdef CONFIG_HISAX_DEBUG DBG(USB_DBG, "HFC-S USB: Endpoint-Config: %s (if=%d alt=%d)\n", @@ -1740,8 +1682,6 @@ hfc_usb_disconnect(struct usb_interface del_timer(&context->t3_timer); if (timer_pending(&context->t4_timer)) del_timer(&context->t4_timer); - if (timer_pending(&context->led_timer)) - del_timer(&context->led_timer); /* tell all fifos to terminate */ for (i = 0; i < HFCUSB_NUM_FIFOS; i++) { if (context->fifos[i].usb_transfer_mode == USB_ISOC) { @@ -1785,9 +1725,11 @@ hfc_usb_disconnect(struct usb_interface /* our driver information structure */ /************************************/ static struct usb_driver hfc_drv = { - .owner = THIS_MODULE,.name = - "hfc_usb",.id_table = hfc_usb_idtab,.probe = - hfc_usb_probe,.disconnect = hfc_usb_disconnect, + .owner = THIS_MODULE, + .name = "hfc_usb", + .id_table = hfcusb_idtab, + .probe = hfc_usb_probe, + .disconnect = hfc_usb_disconnect, }; static void __exit hfc_usb_exit(void) @@ -1825,4 +1767,4 @@ module_exit(hfc_usb_exit); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(usb, hfc_usb_idtab); +MODULE_DEVICE_TABLE(usb, hfcusb_idtab); diff --git a/drivers/isdn/hisax/hfc_usb.h b/drivers/isdn/hisax/hfc_usb.h index 280dd29b30d..ec52c1a7c22 100644 --- a/drivers/isdn/hisax/hfc_usb.h +++ b/drivers/isdn/hisax/hfc_usb.h @@ -1,7 +1,7 @@ /* * hfc_usb.h * -* $Id: hfc_usb.h,v 4.1 2005/01/26 17:25:53 martinb1 Exp $ +* $Id: hfc_usb.h,v 4.2 2005/04/07 15:27:17 martinb1 Exp $ */ #ifndef __HFC_USB_H__ @@ -91,7 +91,7 @@ /**********/ /* macros */ /**********/ -#define write_usb(a,b,c)usb_control_msg((a)->dev,(a)->ctrl_out_pipe,0,0x40,(c),(b),0,0,HFC_CTRL_TIMEOUT) +#define write_usb(a,b,c)usb_control_msg((a)->dev,(a)->ctrl_out_pipe,0,0x40,(c),(b),NULL,0,HFC_CTRL_TIMEOUT) #define read_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_in_pipe,1,0xC0,0,(b),(c),1,HFC_CTRL_TIMEOUT) @@ -186,6 +186,7 @@ static int validconf[][19] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} // EOL element }; +#ifdef CONFIG_HISAX_DEBUG // string description of chosen config static char *conf_str[] = { "4 Interrupt IN + 3 Isochron OUT", @@ -193,6 +194,7 @@ static char *conf_str[] = { "4 Isochron IN + 3 Isochron OUT", "3 Isochron IN + 3 Isochron OUT" }; +#endif typedef struct { -- cgit v1.2.3 From 8bc3efcfbf6521ec7bf3e5d969b31745fbd986f8 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Mon, 7 Nov 2005 01:00:22 -0800 Subject: [PATCH] prevent dmesg warning in zr36067 driver Fix the warning "Debug: sleeping function called from invalid context at include/asm/semaphore.h:102" that the zr36067 driver emits every time an application using JPEG capture starts up (e.g. mjpegtools' lavrec). The warning is harmless, but clogs up the dmesg output. This was logged as bugzilla #5403. (Thanks to Christian Casteyde for helping me in fixing this long-standing annoyance.) Signed-off-by: Ronald S. Bultje Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/zoran_driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index 53adeb70f2c..07bde9acd67 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -996,8 +996,6 @@ zoran_jpg_queue_frame (struct file *file, return -EINVAL; } - spin_lock_irqsave(&zr->spinlock, flags); - if (fh->jpg_buffers.active == ZORAN_FREE) { if (zr->jpg_buffers.active == ZORAN_FREE) { zr->jpg_buffers = fh->jpg_buffers; @@ -1016,6 +1014,8 @@ zoran_jpg_queue_frame (struct file *file, zr36057_enable_jpg(zr, mode); } + spin_lock_irqsave(&zr->spinlock, flags); + if (!res) { switch (zr->jpg_buffers.buffer[num].state) { case BUZ_STATE_DONE: -- cgit v1.2.3 From 15b7a1b86d663ef40108b1ba322973e32d5b62d6 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 7 Nov 2005 01:00:23 -0800 Subject: [PATCH] knfsd: fix setattr-on-symlink error return This is a somewhat cosmetic fix to keep the SpecFS validation test from complaining. SpecFS want's to try chmod on symlinks, and ext3 and reiser (at least) return ENOTSUPP. Probably both sides are being silly, but it is easiest to simply make it a non-issue and filter out chmod requests on symlinks at the nfsd level. Signed-off-by: Olaf Kirch Signed-off-by: J. Bruce Fields Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/vfs.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 4f2cd3d2756..af7c3c3074b 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -254,12 +254,19 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, /* Get inode */ err = fh_verify(rqstp, fhp, ftype, accmode); - if (err || !iap->ia_valid) + if (err) goto out; dentry = fhp->fh_dentry; inode = dentry->d_inode; + /* Ignore any mode updates on symlinks */ + if (S_ISLNK(inode->i_mode)) + iap->ia_valid &= ~ATTR_MODE; + + if (!iap->ia_valid) + goto out; + /* NFSv2 does not differentiate between "set-[ac]time-to-now" * which only requires access, and "set-[ac]time-to-X" which * requires ownership. -- cgit v1.2.3 From 7390022d697bcc62a7556d6fdc61ec56ce3a381a Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 7 Nov 2005 01:00:24 -0800 Subject: [PATCH] knfsd: Restore functionality to read from file in /proc/fs/nfsd/ Most files in the nfsd filesystems are transaction files. You write a request, and read a response. For some (e.g. 'threads') it makes sense to just be able to read and get the current value. This functionality did exist but was broken recently when someone modified nfsctl.c without going through the maintainer. This patch fixes the regression. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/nfsctl.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 841c562991e..2a99a0bf54f 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -104,9 +104,23 @@ static ssize_t nfsctl_transaction_write(struct file *file, const char __user *bu return rv; } +static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos) +{ + if (! file->private_data) { + /* An attempt to read a transaction file without writing + * causes a 0-byte write so that the file can return + * state information + */ + ssize_t rv = nfsctl_transaction_write(file, buf, 0, pos); + if (rv < 0) + return rv; + } + return simple_transaction_read(file, buf, size, pos); +} + static struct file_operations transaction_ops = { .write = nfsctl_transaction_write, - .read = simple_transaction_read, + .read = nfsctl_transaction_read, .release = simple_transaction_release, }; -- cgit v1.2.3 From 70c3b76c28b012452d63bb27f6d0517afb05d86f Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 7 Nov 2005 01:00:25 -0800 Subject: [PATCH] knfsd: Allow run-time selection of NFS versions to export Provide a file in the NFSD filesystem that allows setting and querying of which version of NFS are being exported. Changes are only allowed while no server is running. Signed-off-by: Steve Dickson Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/nfsctl.c | 82 ++++++++++++++++++++++++++++++++++++++++++++ fs/nfsd/nfssvc.c | 79 +++++++++++++++++++++++++++--------------- include/linux/nfsd/nfsd.h | 2 +- include/linux/nfsd/syscall.h | 17 +++++++++ 4 files changed, 151 insertions(+), 29 deletions(-) diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 2a99a0bf54f..a0871b3efeb 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,8 @@ #include +unsigned int nfsd_versbits = ~0; + /* * We have a single directory with 9 nodes in it. */ @@ -50,8 +53,15 @@ enum { NFSD_List, NFSD_Fh, NFSD_Threads, + NFSD_Versions, + /* + * The below MUST come last. Otherwise we leave a hole in nfsd_files[] + * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops + */ +#ifdef CONFIG_NFSD_V4 NFSD_Leasetime, NFSD_RecoveryDir, +#endif }; /* @@ -66,8 +76,11 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size); static ssize_t write_getfs(struct file *file, char *buf, size_t size); static ssize_t write_filehandle(struct file *file, char *buf, size_t size); static ssize_t write_threads(struct file *file, char *buf, size_t size); +static ssize_t write_versions(struct file *file, char *buf, size_t size); +#ifdef CONFIG_NFSD_V4 static ssize_t write_leasetime(struct file *file, char *buf, size_t size); static ssize_t write_recoverydir(struct file *file, char *buf, size_t size); +#endif static ssize_t (*write_op[])(struct file *, char *, size_t) = { [NFSD_Svc] = write_svc, @@ -79,8 +92,11 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = { [NFSD_Getfs] = write_getfs, [NFSD_Fh] = write_filehandle, [NFSD_Threads] = write_threads, + [NFSD_Versions] = write_versions, +#ifdef CONFIG_NFSD_V4 [NFSD_Leasetime] = write_leasetime, [NFSD_RecoveryDir] = write_recoverydir, +#endif }; static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) @@ -343,6 +359,70 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size) return strlen(buf); } +static ssize_t write_versions(struct file *file, char *buf, size_t size) +{ + /* + * Format: + * [-/+]vers [-/+]vers ... + */ + char *mesg = buf; + char *vers, sign; + int len, num; + ssize_t tlen = 0; + char *sep; + + if (size>0) { + if (nfsd_serv) + return -EBUSY; + if (buf[size-1] != '\n') + return -EINVAL; + buf[size-1] = 0; + + vers = mesg; + len = qword_get(&mesg, vers, size); + if (len <= 0) return -EINVAL; + do { + sign = *vers; + if (sign == '+' || sign == '-') + num = simple_strtol((vers+1), NULL, 0); + else + num = simple_strtol(vers, NULL, 0); + switch(num) { + case 2: + case 3: + case 4: + if (sign != '-') + NFSCTL_VERSET(nfsd_versbits, num); + else + NFSCTL_VERUNSET(nfsd_versbits, num); + break; + default: + return -EINVAL; + } + vers += len + 1; + tlen += len; + } while ((len = qword_get(&mesg, vers, size)) > 0); + /* If all get turned off, turn them back on, as + * having no versions is BAD + */ + if ((nfsd_versbits & NFSCTL_VERALL)==0) + nfsd_versbits = NFSCTL_VERALL; + } + /* Now write current state into reply buffer */ + len = 0; + sep = ""; + for (num=2 ; num <= 4 ; num++) + if (NFSCTL_VERISSET(NFSCTL_VERALL, num)) { + len += sprintf(buf+len, "%s%c%d", sep, + NFSCTL_VERISSET(nfsd_versbits, num)?'+':'-', + num); + sep = " "; + } + len += sprintf(buf+len, "\n"); + return len; +} + +#ifdef CONFIG_NFSD_V4 extern time_t nfs4_leasetime(void); static ssize_t write_leasetime(struct file *file, char *buf, size_t size) @@ -384,6 +464,7 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size) status = nfs4_reset_recoverydir(recdir); return strlen(buf); } +#endif /*----------------------------------------------------------------------------*/ /* @@ -403,6 +484,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) [NFSD_List] = {"exports", &exports_operations, S_IRUGO}, [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR}, + [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, #ifdef CONFIG_NFSD_V4 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR}, diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 1697539a717..0568ff8565b 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -52,7 +53,7 @@ extern struct svc_program nfsd_program; static void nfsd(struct svc_rqst *rqstp); struct timeval nfssvc_boot; -static struct svc_serv *nfsd_serv; + struct svc_serv *nfsd_serv; static atomic_t nfsd_busy; static unsigned long nfsd_last_call; static DEFINE_SPINLOCK(nfsd_call_lock); @@ -63,6 +64,31 @@ struct nfsd_list { }; static struct list_head nfsd_list = LIST_HEAD_INIT(nfsd_list); +static struct svc_version * nfsd_version[] = { + [2] = &nfsd_version2, +#if defined(CONFIG_NFSD_V3) + [3] = &nfsd_version3, +#endif +#if defined(CONFIG_NFSD_V4) + [4] = &nfsd_version4, +#endif +}; + +#define NFSD_MINVERS 2 +#define NFSD_NRVERS (sizeof(nfsd_version)/sizeof(nfsd_version[0])) +static struct svc_version *nfsd_versions[NFSD_NRVERS]; + +struct svc_program nfsd_program = { + .pg_prog = NFS_PROGRAM, /* program number */ + .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */ + .pg_vers = nfsd_versions, /* version table */ + .pg_name = "nfsd", /* program name */ + .pg_class = "nfsd", /* authentication class */ + .pg_stats = &nfsd_svcstats, /* version table */ + .pg_authenticate = &svc_set_client, /* export authentication */ + +}; + /* * Maximum number of nfsd processes */ @@ -80,11 +106,12 @@ int nfsd_svc(unsigned short port, int nrservs) { int error; - int none_left; + int none_left, found_one, i; struct list_head *victim; lock_kernel(); - dprintk("nfsd: creating service\n"); + dprintk("nfsd: creating service: vers 0x%x\n", + nfsd_versbits); error = -EINVAL; if (nrservs <= 0) nrservs = 0; @@ -99,6 +126,27 @@ nfsd_svc(unsigned short port, int nrservs) if (error<0) goto out; if (!nfsd_serv) { + /* + * Use the nfsd_ctlbits to define which + * versions that will be advertised. + * If nfsd_ctlbits doesn't list any version, + * export them all. + */ + found_one = 0; + + for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) { + if (NFSCTL_VERISSET(nfsd_versbits, i)) { + nfsd_program.pg_vers[i] = nfsd_version[i]; + found_one = 1; + } else + nfsd_program.pg_vers[i] = NULL; + } + + if (!found_one) { + for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) + nfsd_program.pg_vers[i] = nfsd_version[i]; + } + atomic_set(&nfsd_busy, 0); error = -ENOMEM; nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE); @@ -389,28 +437,3 @@ static struct svc_stat nfsd_acl_svcstats = { #else #define nfsd_acl_program_p NULL #endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */ - -extern struct svc_version nfsd_version2, nfsd_version3, nfsd_version4; - -static struct svc_version * nfsd_version[] = { - [2] = &nfsd_version2, -#if defined(CONFIG_NFSD_V3) - [3] = &nfsd_version3, -#endif -#if defined(CONFIG_NFSD_V4) - [4] = &nfsd_version4, -#endif -}; - -#define NFSD_NRVERS (sizeof(nfsd_version)/sizeof(nfsd_version[0])) -struct svc_program nfsd_program = { - .pg_next = nfsd_acl_program_p, - .pg_prog = NFS_PROGRAM, /* program number */ - .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */ - .pg_vers = nfsd_version, /* version table */ - .pg_name = "nfsd", /* program name */ - .pg_class = "nfsd", /* authentication class */ - .pg_stats = &nfsd_svcstats, /* version table */ - .pg_authenticate = &svc_set_client, /* export authentication */ - -}; diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index 6d5a24f3fc6..51c231a1e5a 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h @@ -60,7 +60,7 @@ typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int); extern struct svc_program nfsd_program; extern struct svc_version nfsd_version2, nfsd_version3, nfsd_version4; - +extern struct svc_serv *nfsd_serv; /* * Function prototypes. */ diff --git a/include/linux/nfsd/syscall.h b/include/linux/nfsd/syscall.h index e65c9db6d13..781efbf94ed 100644 --- a/include/linux/nfsd/syscall.h +++ b/include/linux/nfsd/syscall.h @@ -39,6 +39,21 @@ #define NFSCTL_GETFD 7 /* get an fh by path (used by mountd) */ #define NFSCTL_GETFS 8 /* get an fh by path with max FH len */ +/* + * Macros used to set version + */ +#define NFSCTL_VERSET(_cltbits, _v) ((_cltbits) |= (1 << (_v))) +#define NFSCTL_VERUNSET(_cltbits, _v) ((_cltbits) &= ~(1 << (_v))) +#define NFSCTL_VERISSET(_cltbits, _v) ((_cltbits) & (1 << (_v))) + +#if defined(CONFIG_NFSD_V4) +#define NFSCTL_VERALL (0x1c /* 0b011100 */) +#elif defined(CONFIG_NFSD_V3) +#define NFSCTL_VERALL (0x0c /* 0b001100 */) +#else +#define NFSCTL_VERALL (0x04 /* 0b000100 */) +#endif + /* SVC */ struct nfsctl_svc { unsigned short svc_port; @@ -120,6 +135,8 @@ extern int exp_delclient(struct nfsctl_client *ncp); extern int exp_export(struct nfsctl_export *nxp); extern int exp_unexport(struct nfsctl_export *nxp); +extern unsigned int nfsd_versbits; + #endif /* __KERNEL__ */ #endif /* NFSD_SYSCALL_H */ -- cgit v1.2.3 From 0ba7536d5d47e4ecf2259a80b207158dc4e711eb Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 7 Nov 2005 01:00:26 -0800 Subject: [PATCH] knfsd: Fix some minor sign problems in nfsd/xdr There are a couple of tests which could possibly be confused by extremely large numbers appearing in 'xdr' packets. I think the closest to an exploit you could get would be writing random data from a free page into a file - i.e. leak data out of kernel space. I'm fairly sure they cannot be used for remote compromise. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/nfs3xdr.c | 3 ++- include/linux/nfsd/xdr3.h | 2 +- include/linux/sunrpc/svc.h | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index e0e134d6bab..9147b8524d0 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -366,7 +366,8 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p, len = args->len = ntohl(*p++); hdr = (void*)p - rqstp->rq_arg.head[0].iov_base; - if (rqstp->rq_arg.len < len + hdr) + if (rqstp->rq_arg.len < hdr || + rqstp->rq_arg.len - hdr < len) return 0; args->vec[0].iov_base = (void*)p; diff --git a/include/linux/nfsd/xdr3.h b/include/linux/nfsd/xdr3.h index 21e18ce7ca6..3c2a71b43ba 100644 --- a/include/linux/nfsd/xdr3.h +++ b/include/linux/nfsd/xdr3.h @@ -42,7 +42,7 @@ struct nfsd3_writeargs { __u64 offset; __u32 count; int stable; - int len; + __u32 len; struct kvec vec[RPCSVC_MAXPAGES]; int vlen; }; diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 5af8800e0ce..e4086ec8b95 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -171,7 +171,8 @@ xdr_argsize_check(struct svc_rqst *rqstp, u32 *p) { char *cp = (char *)p; struct kvec *vec = &rqstp->rq_arg.head[0]; - return cp - (char*)vec->iov_base <= vec->iov_len; + return cp >= (char*)vec->iov_base + && cp <= (char*)vec->iov_base + vec->iov_len; } static inline int -- cgit v1.2.3 From 80d188a643b0f550a2aaedf7bf4dd1abd86cfc45 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 7 Nov 2005 01:00:27 -0800 Subject: [PATCH] knfsd: make sure svc_process call the correct pg_authenticate for multi-service port If an RPC socket is serving multiple programs, then the pg_authenticate of the first program in the list is called, instead of pg_authenticate for the program to be run. This does not cause a problem with any programs in the current kernel, but could confuse future code. Also set pg_authenticate for nfsd_acl_program incase it ever gets used. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/nfssvc.c | 1 + net/sunrpc/svc.c | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 0568ff8565b..89ed0469686 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -427,6 +427,7 @@ static struct svc_program nfsd_acl_program = { .pg_name = "nfsd", .pg_class = "nfsd", .pg_stats = &nfsd_acl_svcstats, + .pg_authenticate = &svc_set_client, }; static struct svc_stat nfsd_acl_svcstats = { diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index e9bd91265f7..5a220b2bb37 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -313,6 +313,11 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp) rqstp->rq_proc = proc = ntohl(svc_getu32(argv)); /* procedure number */ progp = serv->sv_program; + + for (progp = serv->sv_program; progp; progp = progp->pg_next) + if (prog == progp->pg_prog) + break; + /* * Decode auth data, and add verifier to reply buffer. * We do this before anything else in order to get a decent @@ -320,7 +325,7 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp) */ auth_res = svc_authenticate(rqstp, &auth_stat); /* Also give the program a chance to reject this call: */ - if (auth_res == SVC_OK) { + if (auth_res == SVC_OK && progp) { auth_stat = rpc_autherr_badcred; auth_res = progp->pg_authenticate(rqstp); } @@ -340,10 +345,7 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp) case SVC_COMPLETE: goto sendit; } - - for (progp = serv->sv_program; progp; progp = progp->pg_next) - if (prog == progp->pg_prog) - break; + if (progp == NULL) goto err_bad_prog; -- cgit v1.2.3 From e65c0850ae811a53554e1abe71627fba1261cfc7 Mon Sep 17 00:00:00 2001 From: "Randy.Dunlap" Date: Mon, 7 Nov 2005 01:00:28 -0800 Subject: [PATCH] framebuffer: add some help text in Kconfig Frame buffer driver help text changes: - Move S3 Trio next to S3 Savage; - add or clarify help text for several FB drivers; - add help text for FB console; - add help text for bootup logos; Acked-by: Antonino Daplas Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/Kconfig | 17 ++++++++++------- drivers/video/console/Kconfig | 2 ++ drivers/video/logo/Kconfig | 2 ++ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 7192b770bfb..564881ff1b2 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -182,6 +182,9 @@ config FB_CLPS711X select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT select FB_SOFT_CURSOR + help + Say Y to enable the Framebuffer driver for the CLPS7111 and + EP7212 processors. config FB_SA1100 bool "SA-1100 LCD support" @@ -405,7 +408,7 @@ config FB_CT65550 65550 graphics chip in PowerBooks. config FB_ASILIANT - bool "Chips 69000 display support" + bool "Asiliant (Chips) 69000 display support" depends on (FB = y) && PCI select FB_CFB_FILLRECT select FB_CFB_COPYAREA @@ -422,12 +425,6 @@ config FB_IMSTT The IMS Twin Turbo is a PCI-based frame buffer card bundled with many Macintosh and compatible computers. -config FB_S3TRIO - bool "S3 Trio display support" - depends on (FB = y) && PPC && BROKEN - help - If you have a S3 Trio say Y. Say N for S3 Virge. - config FB_VGA16 tristate "VGA 16-color graphics support" depends on FB && (X86 || PPC) @@ -1047,6 +1044,12 @@ config FB_ATY_GX is at . +config FB_S3TRIO + bool "S3 Trio display support" + depends on (FB = y) && PPC && BROKEN + help + If you have a S3 Trio say Y. Say N for S3 Virge. + config FB_SAVAGE tristate "S3 Savage support" depends on FB && PCI && EXPERIMENTAL diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index 6a9ae2b3d1a..81d44995f9e 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -98,6 +98,8 @@ config FRAMEBUFFER_CONSOLE tristate "Framebuffer Console support" depends on FB select CRC32 + help + Low-level framebuffer-based console driver. config STI_CONSOLE tristate "STI text console" diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig index 3e9ccf370ab..8cb7fb4db44 100644 --- a/drivers/video/logo/Kconfig +++ b/drivers/video/logo/Kconfig @@ -7,6 +7,8 @@ menu "Logo configuration" config LOGO bool "Bootup logo" depends on FB || SGI_NEWPORT_CONSOLE + help + Enable and select frame buffer bootup logos. config LOGO_LINUX_MONO bool "Standard black and white Linux logo" -- cgit v1.2.3 From ecc41d5e0267de2c010e0fdf8da3c9e3e394f752 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 7 Nov 2005 01:00:29 -0800 Subject: [PATCH] fb: straighten up fb drivers menu Arrange frame buffer menu: - puts all Epson drivers together - removes split of FB_PXA and FB_PXA_PARAMETERS by FB_W100 - results in PXA, W100, Epson, S3C2410, & Virtual FB drivers being presented at the same menu level as all other FB drivers Signed-off-by: Randy Dunlap Acked-by: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/Kconfig | 118 +++++++++++++++++++++++++------------------------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 564881ff1b2..1eec03a9b10 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -638,6 +638,50 @@ config FB_EPSON1355 framebuffer. Product specs at . +config FB_E1356 + tristate "Epson SED1356 framebuffer support" + depends on FB && EXPERIMENTAL && PCI && MIPS + +config PB1000_CRT + bool "Use CRT on Pb1000 (J65)" + depends on MIPS_PB1000=y && FB_E1356 + +config PB1000_NTSC + bool "Use Compsite NTSC on Pb1000 (J63)" + depends on MIPS_PB1000=y && FB_E1356 + +config PB1000_TFT + bool "Use TFT Panel on Pb1000 (J64)" + depends on MIPS_PB1000=y && FB_E1356 + +config PB1500_CRT + bool "Use CRT on Pb1500 " if MIPS_PB1500=y + depends on FB_E1356 + +config PB1500_CRT + prompt "Use CRT on Pb1100 " + depends on FB_E1356 && MIPS_PB1100=y + +config PB1500_TFT + bool "Use TFT Panel on Pb1500 " if MIPS_PB1500=y + depends on FB_E1356 + +config PB1500_TFT + prompt "Use TFT Panel on Pb1100 " + depends on FB_E1356 && MIPS_PB1100=y + +config FB_S1D13XXX + tristate "Epson S1D13XXX framebuffer support" + depends on FB + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_SOFT_CURSOR + help + Support for S1D13XXX framebuffer device family (currently only + working with S1D13806). Product specs at + + config FB_NVIDIA tristate "nVidia Framebuffer Support" depends on FB && PCI @@ -1253,38 +1297,6 @@ config FB_PM3 similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000 and maybe other boards. -config FB_E1356 - tristate "Epson SED1356 framebuffer support" - depends on FB && EXPERIMENTAL && PCI && MIPS - -config PB1000_CRT - bool "Use CRT on Pb1000 (J65)" - depends on MIPS_PB1000=y && FB_E1356 - -config PB1000_NTSC - bool "Use Compsite NTSC on Pb1000 (J63)" - depends on MIPS_PB1000=y && FB_E1356 - -config PB1000_TFT - bool "Use TFT Panel on Pb1000 (J64)" - depends on MIPS_PB1000=y && FB_E1356 - -config PB1500_CRT - bool "Use CRT on Pb1500 " if MIPS_PB1500=y - depends on FB_E1356 - -config PB1500_CRT - prompt "Use CRT on Pb1100 " - depends on FB_E1356 && MIPS_PB1100=y - -config PB1500_TFT - bool "Use TFT Panel on Pb1500 " if MIPS_PB1500=y - depends on FB_E1356 - -config PB1500_TFT - prompt "Use TFT Panel on Pb1100 " - depends on FB_E1356 && MIPS_PB1100=y - config FB_AU1100 bool "Au1100 LCD Driver" depends on (FB = y) && EXPERIMENTAL && PCI && MIPS && MIPS_PB1100=y @@ -1476,23 +1488,6 @@ config FB_PXA If unsure, say N. -config FB_W100 - tristate "W100 frame buffer support" - depends on FB && PXA_SHARPSL - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR - ---help--- - Frame buffer driver for the w100 as found on the Sharp SL-Cxx series. - - This driver is also available as a module ( = code which can be - inserted and removed from the running kernel whenever you want). The - module will be called vfb. If you want to compile it as a module, - say M here and read . - - If unsure, say N. - config FB_PXA_PARAMETERS bool "PXA LCD command line parameters" default n @@ -1510,17 +1505,22 @@ config FB_PXA_PARAMETERS describes the available parameters. -config FB_S1D13XXX - tristate "Epson S1D13XXX framebuffer support" - depends on FB - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT +config FB_W100 + tristate "W100 frame buffer support" + depends on FB && PXA_SHARPSL + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT select FB_SOFT_CURSOR - help - Support for S1D13XXX framebuffer device family (currently only - working with S1D13806). Product specs at - + ---help--- + Frame buffer driver for the w100 as found on the Sharp SL-Cxx series. + + This driver is also available as a module ( = code which can be + inserted and removed from the running kernel whenever you want). The + module will be called vfb. If you want to compile it as a module, + say M here and read . + + If unsure, say N. config FB_S3C2410 tristate "S3C2410 LCD framebuffer support" -- cgit v1.2.3 From 85f1503aff46089acd9f780b5259752839cf0162 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 7 Nov 2005 01:00:30 -0800 Subject: [PATCH] nvidiafb: Fix mode setting & PPC support This patch fixes nvifiafb mode setting code to be closer to what the X driver does, which actually makes it work on the 5200FX I have access to. It also fix the routine that gets the EDID from Open Firmware on PPC, it was broken in various ways and would crash at boot. Compared to the patch I posted to linux-fbdev last week, this one just changes a printk to be closer to the other ones in the driver. Signed-off-by: Benjamin Herrenschmidt Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/Kconfig | 2 +- drivers/video/nvidia/nv_of.c | 64 +++++++++++++++++++++---------- drivers/video/nvidia/nv_proto.h | 14 ++++--- drivers/video/nvidia/nv_setup.c | 16 +++++--- drivers/video/nvidia/nvidia.c | 84 ++++++++++++++++++++++++++++++++++------- 5 files changed, 137 insertions(+), 43 deletions(-) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 1eec03a9b10..9c54695911c 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -703,7 +703,7 @@ config FB_NVIDIA config FB_NVIDIA_I2C bool "Enable DDC Support" - depends on FB_NVIDIA && !PPC_OF + depends on FB_NVIDIA help This enables I2C support for nVidia Chipsets. This is used only for getting EDID information from the attached display diff --git a/drivers/video/nvidia/nv_of.c b/drivers/video/nvidia/nv_of.c index 4fa2cf9a8af..7a03d040b1a 100644 --- a/drivers/video/nvidia/nv_of.c +++ b/drivers/video/nvidia/nv_of.c @@ -27,34 +27,60 @@ #include "nv_local.h" #include "nv_proto.h" -void nvidia_create_i2c_busses(struct nvidia_par *par) {} -void nvidia_delete_i2c_busses(struct nvidia_par *par) {} +#include "../edid.h" -int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid) +int nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid) { struct nvidia_par *par = info->par; - struct device_node *dp; + struct device_node *parent, *dp; unsigned char *pedid = NULL; - unsigned char *disptype = NULL; static char *propnames[] = { - "DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID,B", "EDID,A", NULL }; + "DFP,EDID", "LCD,EDID", "EDID", "EDID1", + "EDID,B", "EDID,A", NULL }; int i; - dp = pci_device_to_OF_node(par->pci_dev); - for (; dp != NULL; dp = dp->child) { - disptype = (unsigned char *)get_property(dp, "display-type", NULL); - if (disptype == NULL) - continue; - if (strncmp(disptype, "LCD", 3) != 0) - continue; + parent = pci_device_to_OF_node(par->pci_dev); + if (parent == NULL) + return -1; + if (par->twoHeads) { + char *pname; + int len; + + for (dp = NULL; + (dp = of_get_next_child(parent, dp)) != NULL;) { + pname = (char *)get_property(dp, "name", NULL); + if (!pname) + continue; + len = strlen(pname); + if ((pname[len-1] == 'A' && conn == 1) || + (pname[len-1] == 'B' && conn == 2)) { + for (i = 0; propnames[i] != NULL; ++i) { + pedid = (unsigned char *) + get_property(dp, propnames[i], + NULL); + if (pedid != NULL) + break; + } + of_node_put(dp); + break; + } + } + } + if (pedid == NULL) { for (i = 0; propnames[i] != NULL; ++i) { pedid = (unsigned char *) - get_property(dp, propnames[i], NULL); - if (pedid != NULL) { - *out_edid = pedid; - return 0; - } + get_property(parent, propnames[i], NULL); + if (pedid != NULL) + break; } } - return 1; + if (pedid) { + *out_edid = kmalloc(EDID_LENGTH, GFP_KERNEL); + if (*out_edid == NULL) + return -1; + memcpy(*out_edid, pedid, EDID_LENGTH); + printk(KERN_DEBUG "nvidiafb: Found OF EDID for head %d\n", conn); + return 0; + } + return -1; } diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h index cac44fc7f58..3d35b77a4af 100644 --- a/drivers/video/nvidia/nv_proto.h +++ b/drivers/video/nvidia/nv_proto.h @@ -31,7 +31,7 @@ int NVShowHideCursor(struct nvidia_par *par, int); void NVLockUnlock(struct nvidia_par *par, int); /* in nvidia-i2c.c */ -#if defined(CONFIG_FB_NVIDIA_I2C) || defined (CONFIG_PPC_OF) +#ifdef CONFIG_FB_NVIDIA_I2C void nvidia_create_i2c_busses(struct nvidia_par *par); void nvidia_delete_i2c_busses(struct nvidia_par *par); int nvidia_probe_i2c_connector(struct fb_info *info, int conn, @@ -39,10 +39,14 @@ int nvidia_probe_i2c_connector(struct fb_info *info, int conn, #else #define nvidia_create_i2c_busses(...) #define nvidia_delete_i2c_busses(...) -#define nvidia_probe_i2c_connector(p, c, edid) \ -do { \ - *(edid) = NULL; \ -} while(0) +#define nvidia_probe_i2c_connector(p, c, edid) (-1) +#endif + +#ifdef CONFIG_FB_OF +int nvidia_probe_of_connector(struct fb_info *info, int conn, + u8 ** out_edid); +#else +#define nvidia_probe_of_connector(p, c, edid) (-1) #endif /* in nv_accel.c */ diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c index 11c84178f42..1f06a9f1bd0 100644 --- a/drivers/video/nvidia/nv_setup.c +++ b/drivers/video/nvidia/nv_setup.c @@ -190,9 +190,9 @@ static int NVIsConnected(struct nvidia_par *par, int output) present = (NV_RD32(PRAMDAC, 0x0608) & (1 << 28)) ? 1 : 0; if (present) - printk("nvidiafb: CRTC%i found\n", output); + printk("nvidiafb: CRTC%i analog found\n", output); else - printk("nvidiafb: CRTC%i not found\n", output); + printk("nvidiafb: CRTC%i analog not found\n", output); NV_WR32(par->PRAMDAC0, 0x0608, NV_RD32(par->PRAMDAC0, 0x0608) & 0x0000EFFF); @@ -305,6 +305,9 @@ void NVCommonSetup(struct fb_info *info) int FlatPanel = -1; /* really means the CRTC is slaved */ int Television = 0; + memset(&monitorA, 0, sizeof(struct fb_monspecs)); + memset(&monitorB, 0, sizeof(struct fb_monspecs)); + par->PRAMIN = par->REGS + (0x00710000 / 4); par->PCRTC0 = par->REGS + (0x00600000 / 4); par->PRAMDAC0 = par->REGS + (0x00680000 / 4); @@ -401,7 +404,8 @@ void NVCommonSetup(struct fb_info *info) nvidia_create_i2c_busses(par); if (!par->twoHeads) { par->CRTCnumber = 0; - nvidia_probe_i2c_connector(info, 1, &edidA); + if (nvidia_probe_i2c_connector(info, 1, &edidA)) + nvidia_probe_of_connector(info, 1, &edidA); if (edidA && !fb_parse_edid(edidA, &var)) { printk("nvidiafb: EDID found from BUS1\n"); monA = &monitorA; @@ -488,14 +492,16 @@ void NVCommonSetup(struct fb_info *info) oldhead = NV_RD32(par->PCRTC0, 0x00000860); NV_WR32(par->PCRTC0, 0x00000860, oldhead | 0x00000010); - nvidia_probe_i2c_connector(info, 1, &edidA); + if (nvidia_probe_i2c_connector(info, 1, &edidA)) + nvidia_probe_of_connector(info, 1, &edidA); if (edidA && !fb_parse_edid(edidA, &var)) { printk("nvidiafb: EDID found from BUS1\n"); monA = &monitorA; fb_edid_to_monspecs(edidA, monA); } - nvidia_probe_i2c_connector(info, 2, &edidB); + if (nvidia_probe_i2c_connector(info, 2, &edidB)) + nvidia_probe_of_connector(info, 2, &edidB); if (edidB && !fb_parse_edid(edidB, &var)) { printk("nvidiafb: EDID found from BUS2\n"); monB = &monitorB; diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index 308defc389a..96d51144094 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -627,41 +627,85 @@ static void nvidia_save_vga(struct nvidia_par *par, NVTRACE_LEAVE(); } +#undef DUMP_REG + static void nvidia_write_regs(struct nvidia_par *par) { struct _riva_hw_state *state = &par->ModeReg; int i; NVTRACE_ENTER(); - NVWriteCrtc(par, 0x11, 0x00); - - NVLockUnlock(par, 0); NVLoadStateExt(par, state); NVWriteMiscOut(par, state->misc_output); + for (i = 1; i < NUM_SEQ_REGS; i++) { +#ifdef DUMP_REG + printk(" SEQ[%02x] = %08x\n", i, state->seq[i]); +#endif + NVWriteSeq(par, i, state->seq[i]); + } + + /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */ + NVWriteCrtc(par, 0x11, state->crtc[0x11] & ~0x80); + for (i = 0; i < NUM_CRT_REGS; i++) { switch (i) { case 0x19: case 0x20 ... 0x40: break; default: +#ifdef DUMP_REG + printk("CRTC[%02x] = %08x\n", i, state->crtc[i]); +#endif NVWriteCrtc(par, i, state->crtc[i]); } } - for (i = 0; i < NUM_ATC_REGS; i++) - NVWriteAttr(par, i, state->attr[i]); - - for (i = 0; i < NUM_GRC_REGS; i++) + for (i = 0; i < NUM_GRC_REGS; i++) { +#ifdef DUMP_REG + printk(" GRA[%02x] = %08x\n", i, state->gra[i]); +#endif NVWriteGr(par, i, state->gra[i]); + } + + for (i = 0; i < NUM_ATC_REGS; i++) { +#ifdef DUMP_REG + printk("ATTR[%02x] = %08x\n", i, state->attr[i]); +#endif + NVWriteAttr(par, i, state->attr[i]); + } - for (i = 0; i < NUM_SEQ_REGS; i++) - NVWriteSeq(par, i, state->seq[i]); NVTRACE_LEAVE(); } +static void nvidia_vga_protect(struct nvidia_par *par, int on) +{ + unsigned char tmp; + + if (on) { + /* + * Turn off screen and disable sequencer. + */ + tmp = NVReadSeq(par, 0x01); + + NVWriteSeq(par, 0x00, 0x01); /* Synchronous Reset */ + NVWriteSeq(par, 0x01, tmp | 0x20); /* disable the display */ + } else { + /* + * Reenable sequencer, then turn on screen. + */ + + tmp = NVReadSeq(par, 0x01); + + NVWriteSeq(par, 0x01, tmp & ~0x20); /* reenable display */ + NVWriteSeq(par, 0x00, 0x03); /* End Reset */ + } +} + + + static int nvidia_calc_regs(struct fb_info *info) { struct nvidia_par *par = info->par; @@ -868,7 +912,7 @@ static void nvidia_init_vga(struct fb_info *info) for (i = 0; i < 0x10; i++) state->attr[i] = i; state->attr[0x10] = 0x41; - state->attr[0x11] = 0x01; + state->attr[0x11] = 0xff; state->attr[0x12] = 0x0f; state->attr[0x13] = 0x00; state->attr[0x14] = 0x00; @@ -991,7 +1035,6 @@ static int nvidiafb_set_par(struct fb_info *info) nvidia_init_vga(info); nvidia_calc_regs(info); - nvidia_write_regs(par); NVLockUnlock(par, 0); if (par->twoHeads) { @@ -1000,7 +1043,22 @@ static int nvidiafb_set_par(struct fb_info *info) NVLockUnlock(par, 0); } - NVWriteCrtc(par, 0x11, 0x00); + nvidia_vga_protect(par, 1); + + nvidia_write_regs(par); + +#if defined (__BIG_ENDIAN) + /* turn on LFB swapping */ + { + unsigned char tmp; + + VGA_WR08(par->PCIO, 0x3d4, 0x46); + tmp = VGA_RD08(par->PCIO, 0x3d5); + tmp |= (1 << 7); + VGA_WR08(par->PCIO, 0x3d5, tmp); + } +#endif + info->fix.line_length = (info->var.xres_virtual * info->var.bits_per_pixel) >> 3; if (info->var.accel_flags) { @@ -1022,7 +1080,7 @@ static int nvidiafb_set_par(struct fb_info *info) par->cursor_reset = 1; - NVWriteCrtc(par, 0x11, 0xff); + nvidia_vga_protect(par, 0); NVTRACE_LEAVE(); return 0; -- cgit v1.2.3 From 7f8c54d20b258acf291dd4490b0e22fa10b2a17f Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 7 Nov 2005 01:00:31 -0800 Subject: [PATCH] nvidiafb-fix-mode-setting-ppc-support-warning-fixes drivers/video/nvidia/nv_setup.c: In function `NVCommonSetup': drivers/video/nvidia/nv_setup.c:408: warning: statement with no effect drivers/video/nvidia/nv_setup.c:496: warning: statement with no effect drivers/video/nvidia/nv_setup.c:504: warning: statement with no effect Cc: Benjamin Herrenschmidt Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/nvidia/nv_proto.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h index 3d35b77a4af..f60b1f43227 100644 --- a/drivers/video/nvidia/nv_proto.h +++ b/drivers/video/nvidia/nv_proto.h @@ -46,7 +46,11 @@ int nvidia_probe_i2c_connector(struct fb_info *info, int conn, int nvidia_probe_of_connector(struct fb_info *info, int conn, u8 ** out_edid); #else -#define nvidia_probe_of_connector(p, c, edid) (-1) +static inline int nvidia_probe_of_connector(struct fb_info *info, int conn, + u8 ** out_edid) +{ + return -1; +} #endif /* in nv_accel.c */ -- cgit v1.2.3 From b8c49ef6aeef662e7920435012be8c2ecc41c30d Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 7 Nov 2005 01:00:32 -0800 Subject: [PATCH] nvidiafb: Add flat panel dither support nvidiafb didn't fully hook-up the code it borrowed from X for doing flat panel dithering (this is useful for 6 bits panels). This adds a driver option to force it, and by default "reads" the current value from the chip to get the firmware setting. It significantly improves the quality of images on the iMac G5 I have here (though the X driver doesn't yet "read" the current value and defaults to 0, so you have to add Option "FBDither" "true" to your X config file to get that, I'll try to fix X.org to "read" the default unless specified asap). Signed-off-by: Benjamin Herrenschmidt Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/nvidia/nvidia.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index 96d51144094..691151e2bce 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -411,6 +411,7 @@ MODULE_DEVICE_TABLE(pci, nvidiafb_pci_tbl); /* command line data, set in nvidiafb_setup() */ static int flatpanel __devinitdata = -1; /* Autodetect later */ +static int fpdither __devinitdata = -1; static int forceCRTC __devinitdata = -1; static int hwcur __devinitdata = 0; static int noaccel __devinitdata = 0; @@ -1026,10 +1027,19 @@ static int nvidiafb_set_par(struct fb_info *info) NVTRACE_ENTER(); NVLockUnlock(par, 1); - if (!par->FlatPanel || (info->var.bits_per_pixel != 24) || - !par->twoHeads) + if (!par->FlatPanel || !par->twoHeads) par->FPDither = 0; + if (par->FPDither < 0) { + if ((par->Chipset & 0x0ff0) == 0x0110) + par->FPDither = !!(NV_RD32(par->PRAMDAC, 0x0528) + & 0x00010000); + else + par->FPDither = !!(NV_RD32(par->PRAMDAC, 0x083C) & 1); + printk(KERN_INFO PFX "Flat panel dithering %s\n", + par->FPDither ? "enabled" : "disabled"); + } + info->fix.visual = (info->var.bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; @@ -1548,9 +1558,9 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd, sprintf(nvidiafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4); par->FlatPanel = flatpanel; - if (flatpanel == 1) printk(KERN_INFO PFX "flatpanel support enabled\n"); + par->FPDither = fpdither; par->CRTCnumber = forceCRTC; par->FpScale = (!noscale); @@ -1729,6 +1739,8 @@ static int __devinit nvidiafb_setup(char *options) } else if (!strncmp(this_opt, "nomtrr", 6)) { nomtrr = 1; #endif + } else if (!strncmp(this_opt, "fpdither:", 9)) { + fpdither = simple_strtol(this_opt+9, NULL, 0); } else mode_option = this_opt; } @@ -1775,7 +1787,11 @@ module_exit(nvidiafb_exit); module_param(flatpanel, int, 0); MODULE_PARM_DESC(flatpanel, "Enables experimental flat panel support for some chipsets. " - "(0 or 1=enabled) (default=0)"); + "(0=disabled, 1=enabled, -1=autodetect) (default=-1)"); +module_param(fpdither, int, 0); +MODULE_PARM_DESC(fpdither, + "Enables dithering of flat panel for 6 bits panels. " + "(0=disabled, 1=enabled, -1=autodetect) (default=-1)"); module_param(hwcur, int, 0); MODULE_PARM_DESC(hwcur, "Enables hardware cursor implementation. (0 or 1=enabled) " -- cgit v1.2.3 From 3a59026ba111d85b1a86af0f1c4e5a8ef1242d82 Mon Sep 17 00:00:00 2001 From: Scott MacKenzie Date: Mon, 7 Nov 2005 01:00:33 -0800 Subject: [PATCH] intelfb: extend partial support of i915G to include i915GM Add partial support for GMA900 within the i915GM chipset. Signed-off-by: Scott MacKenzie Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/intelfb/intelfb.h | 6 ++++-- drivers/video/intelfb/intelfbdrv.c | 8 +++++--- drivers/video/intelfb/intelfbhw.c | 5 +++++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h index 011e1162655..f077ca34fab 100644 --- a/drivers/video/intelfb/intelfb.h +++ b/drivers/video/intelfb/intelfb.h @@ -10,7 +10,7 @@ /*** Version/name ***/ #define INTELFB_VERSION "0.9.2" #define INTELFB_MODULE_NAME "intelfb" -#define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G" +#define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G/915GM" /*** Debug/feature defines ***/ @@ -47,6 +47,7 @@ #define PCI_DEVICE_ID_INTEL_85XGM 0x3582 #define PCI_DEVICE_ID_INTEL_865G 0x2572 #define PCI_DEVICE_ID_INTEL_915G 0x2582 +#define PCI_DEVICE_ID_INTEL_915GM 0x2592 /* Size of MMIO region */ #define INTEL_REG_SIZE 0x80000 @@ -119,7 +120,8 @@ enum intel_chips { INTEL_855GM, INTEL_855GME, INTEL_865G, - INTEL_915G + INTEL_915G, + INTEL_915GM }; struct intelfb_hwstate { diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index 80a09344f1a..e6d75b926dc 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c @@ -1,7 +1,7 @@ /* * intelfb * - * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G + * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM * integrated graphics chips. * * Copyright © 2002, 2003 David Dawes @@ -186,6 +186,7 @@ static struct pci_device_id intelfb_pci_table[] __devinitdata = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_85XGM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_85XGM }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_865G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_865G }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915G }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM }, { 0, } }; @@ -549,10 +550,11 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) } /* Set base addresses. */ - if (ent->device == PCI_DEVICE_ID_INTEL_915G) { + if ((ent->device == PCI_DEVICE_ID_INTEL_915G) || + (ent->device == PCI_DEVICE_ID_INTEL_915GM)) { aperture_bar = 2; mmio_bar = 0; - /* Disable HW cursor on 915G (not implemented yet) */ + /* Disable HW cursor on 915G/M (not implemented yet) */ hwcursor = 0; } dinfo->aperture.physical = pci_resource_start(pdev, aperture_bar); diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index 5bafc3c54db..ac94c2e5ff8 100644 --- a/drivers/video/intelfb/intelfbhw.c +++ b/drivers/video/intelfb/intelfbhw.c @@ -99,6 +99,11 @@ intelfbhw_get_chipset(struct pci_dev *pdev, const char **name, int *chipset, *chipset = INTEL_915G; *mobile = 0; return 0; + case PCI_DEVICE_ID_INTEL_915GM: + *name = "Intel(R) 915GM"; + *chipset = INTEL_915GM; + *mobile = 1; + return 0; default: return 1; } -- cgit v1.2.3 From e764a20196f4e1b497a42fdc6e9d254e7ec290f2 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 7 Nov 2005 01:00:34 -0800 Subject: [PATCH] radeonfb: prevent spurious recompilations Prevent spurious recompilations of the radeonfb driver when I2C/DDC support is not included and i2c header files are modified. Signed-off-by: Jean Delvare Acked-by: Benjamin Herrenschmidt Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/aty/radeon_base.c | 1 - drivers/video/aty/radeonfb.h | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 8a24a66d9ba..7ef4b901b93 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -69,7 +69,6 @@ #include #include #include -#include #include #include diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h index 01b8b2f7851..217e00ab4a2 100644 --- a/drivers/video/aty/radeonfb.h +++ b/drivers/video/aty/radeonfb.h @@ -10,9 +10,10 @@ #include +#ifdef CONFIG_FB_RADEON_I2C #include -#include #include +#endif #include -- cgit v1.2.3 From c465e05a03209651078b95686158648fd7ed84c5 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 7 Nov 2005 01:00:35 -0800 Subject: [PATCH] fbcon/fbdev: Move softcursor out of fbdev to fbcon According to Jon Smirl, filling in the field fb_cursor with soft_cursor for drivers that do not support hardware cursors is redundant. The soft_cursor function is usable by all drivers because it is just a wrapper around fb_imageblit. And because soft_cursor is an fbcon-specific hook, the file is moved to the console directory. Thus, drivers that do not support hardware cursors can leave the fb_cursor field blank. For drivers that do, they can fill up this field with their own version. The end result is a smaller code size. And if the framebuffer console is not loaded, module/kernel size is also reduced because the soft_cursor module will also not be loaded. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/68328fb.c | 1 - drivers/video/Kconfig | 79 ---------------------------------- drivers/video/Makefile | 1 - drivers/video/acornfb.c | 1 - drivers/video/amba-clcd.c | 1 - drivers/video/amifb.c | 1 - drivers/video/arcfb.c | 1 - drivers/video/asiliantfb.c | 1 - drivers/video/aty/aty128fb.c | 1 - drivers/video/aty/atyfb_base.c | 1 - drivers/video/aty/radeon_base.c | 1 - drivers/video/bw2.c | 1 - drivers/video/cg14.c | 1 - drivers/video/cg3.c | 1 - drivers/video/cg6.c | 1 - drivers/video/chipsfb.c | 1 - drivers/video/cirrusfb.c | 1 - drivers/video/clps711xfb.c | 1 - drivers/video/console/Makefile | 2 +- drivers/video/console/bitblit.c | 7 ++- drivers/video/console/fbcon.h | 2 +- drivers/video/console/softcursor.c | 72 +++++++++++++++++++++++++++++++ drivers/video/controlfb.c | 1 - drivers/video/cyber2000fb.c | 1 - drivers/video/cyblafb.c | 1 - drivers/video/dnfb.c | 1 - drivers/video/epson1355fb.c | 1 - drivers/video/ffb.c | 3 -- drivers/video/fm2fb.c | 1 - drivers/video/gbefb.c | 1 - drivers/video/geode/Kconfig | 1 - drivers/video/geode/gx1fb_core.c | 1 - drivers/video/hitfb.c | 1 - drivers/video/hpfb.c | 1 - drivers/video/imsttfb.c | 1 - drivers/video/imxfb.c | 1 - drivers/video/intelfb/intelfbdrv.c | 2 +- drivers/video/kyro/fbdev.c | 1 - drivers/video/leo.c | 1 - drivers/video/macfb.c | 1 - drivers/video/matrox/matroxfb_accel.c | 2 +- drivers/video/matrox/matroxfb_crtc2.c | 1 - drivers/video/maxinefb.c | 1 - drivers/video/neofb.c | 1 - drivers/video/nvidia/nvidia.c | 2 +- drivers/video/offb.c | 1 - drivers/video/p9100.c | 1 - drivers/video/platinumfb.c | 1 - drivers/video/pm2fb.c | 1 - drivers/video/pmag-ba-fb.c | 1 - drivers/video/pmagb-b-fb.c | 1 - drivers/video/pvr2fb.c | 1 - drivers/video/pxafb.c | 1 - drivers/video/q40fb.c | 1 - drivers/video/radeonfb.c | 1 - drivers/video/s1d13xxxfb.c | 1 - drivers/video/s3c2410fb.c | 1 - drivers/video/sa1100fb.c | 1 - drivers/video/savage/savagefb_driver.c | 1 - drivers/video/sgivwfb.c | 1 - drivers/video/sis/sis_main.c | 2 + drivers/video/skeletonfb.c | 9 ++-- drivers/video/softcursor.c | 72 ------------------------------- drivers/video/sstfb.c | 1 - drivers/video/stifb.c | 1 - drivers/video/tcx.c | 1 - drivers/video/tdfxfb.c | 1 - drivers/video/tgafb.c | 1 - drivers/video/tridentfb.c | 1 - drivers/video/tx3912fb.c | 1 - drivers/video/valkyriefb.c | 1 - drivers/video/vesafb.c | 1 - drivers/video/vfb.c | 1 - drivers/video/vga16fb.c | 1 - drivers/video/w100fb.c | 1 - include/linux/fb.h | 1 - 76 files changed, 88 insertions(+), 230 deletions(-) create mode 100644 drivers/video/console/softcursor.c delete mode 100644 drivers/video/softcursor.c diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c index 6a3cfbdc6dc..3b0ddc55236 100644 --- a/drivers/video/68328fb.c +++ b/drivers/video/68328fb.c @@ -113,7 +113,6 @@ static struct fb_ops mc68x328fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_mmap = mc68x328fb_mmap, }; diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 9c54695911c..44b6ca290ce 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -65,15 +65,6 @@ config FB_CFB_IMAGEBLIT blitting. This is used by drivers that don't provide their own (accelerated) version. -config FB_SOFT_CURSOR - tristate - depends on FB - default n - ---help--- - Include the soft_cursor function for generic software cursor support. - This is used by drivers that don't provide their own (accelerated) - version. - config FB_MACMODES tristate depends on FB @@ -114,7 +105,6 @@ config FB_CIRRUS select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- This enables support for Cirrus Logic GD542x/543x based boards on Amiga: SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum. @@ -133,7 +123,6 @@ config FB_PM2 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Permedia2 AGP frame buffer card from ASK, aka `Graphic Blaster Exxtreme'. There is a @@ -152,7 +141,6 @@ config FB_ARMCLCD select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This framebuffer device driver is for the ARM PrimeCell PL110 Colour LCD controller. ARM PrimeCells provide the building @@ -169,7 +157,6 @@ config FB_ACORN select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Acorn VIDC graphics hardware found in Acorn RISC PCs and other ARM-based machines. If @@ -181,7 +168,6 @@ config FB_CLPS711X select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Say Y to enable the Framebuffer driver for the CLPS7111 and EP7212 processors. @@ -192,7 +178,6 @@ config FB_SA1100 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is a framebuffer device for the SA-1100 LCD Controller. See for information on framebuffer @@ -207,7 +192,6 @@ config FB_IMX select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR config FB_CYBER2000 tristate "CyberPro 2000/2010/5000 support" @@ -215,7 +199,6 @@ config FB_CYBER2000 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This enables support for the Integraphics CyberPro 20x0 and 5000 VGA chips used in the Rebel.com Netwinder and other machines. @@ -228,7 +211,6 @@ config FB_APOLLO default y select FB_CFB_FILLRECT select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR config FB_Q40 bool @@ -237,12 +219,10 @@ config FB_Q40 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR config FB_AMIGA tristate "Amiga native chipset support" depends on FB && AMIGA - select FB_SOFT_CURSOR help This is the frame buffer device driver for the builtin graphics chipset found in Amigas. @@ -282,7 +262,6 @@ config FB_CYBER select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This enables support for the Cybervision 64 graphics card from Phase5. Please note that its use is not all that intuitive (i.e. if @@ -297,7 +276,6 @@ config FB_VIRGE select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This enables support for the Cybervision 64/3D graphics card from Phase5. Please note that its use is not all that intuitive (i.e. if @@ -320,7 +298,6 @@ config FB_FM2 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Amiga FrameMaster card from BSC (exhibited 1992 but not shipped as a CBM product). @@ -331,7 +308,6 @@ config FB_ARC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This enables support for the Arc Monochrome LCD board. The board is based on the KS-108 lcd controller and is typically a matrix @@ -354,7 +330,6 @@ config FB_OF select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES help Say Y if you want support with Open Firmware for your graphics @@ -366,7 +341,6 @@ config FB_CONTROL select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES help This driver supports a frame buffer for the graphics adapter in the @@ -378,7 +352,6 @@ config FB_PLATINUM select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES help This driver supports a frame buffer for the "platinum" graphics @@ -390,7 +363,6 @@ config FB_VALKYRIE select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES help This driver supports a frame buffer for the "valkyrie" graphics @@ -402,7 +374,6 @@ config FB_CT65550 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Chips & Technologies 65550 graphics chip in PowerBooks. @@ -413,13 +384,11 @@ config FB_ASILIANT select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR config FB_IMSTT bool "IMS Twin Turbo display support" depends on (FB = y) && PCI select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES if PPC help The IMS Twin Turbo is a PCI-based frame buffer card bundled with @@ -431,7 +400,6 @@ config FB_VGA16 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for VGA 16 color graphic cards. Say Y if you have such a card. @@ -445,7 +413,6 @@ config FB_STI select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR default y ---help--- STI refers to the HP "Standard Text Interface" which is a set of @@ -466,7 +433,6 @@ config FB_MAC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES # bool ' Apple DAFB display support' CONFIG_FB_DAFB @@ -475,7 +441,6 @@ config FB_HP300 depends on (FB = y) && HP300 select FB_CFB_FILLRECT select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR default y config FB_TGA @@ -484,7 +449,6 @@ config FB_TGA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for generic TGA graphic cards. Say Y if you have one of those. @@ -495,7 +459,6 @@ config FB_VESA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for generic VESA 2.0 compliant graphic cards. The older VESA 1.2 cards are not supported. @@ -513,7 +476,6 @@ config FB_HGA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Say Y here if you have a Hercules mono graphics card. @@ -542,7 +504,6 @@ config FB_SGIVW select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help SGI Visual Workstation support for framebuffer graphics. @@ -552,7 +513,6 @@ config FB_GBE select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for SGI Graphics Backend. This chip is used in SGI O2 and Visual Workstation 320/540. @@ -580,7 +540,6 @@ config FB_BW2 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the BWtwo frame buffer. @@ -589,7 +548,6 @@ config FB_CG3 depends on (FB = y) && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3) select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the CGthree frame buffer. @@ -598,7 +556,6 @@ config FB_CG6 depends on (FB = y) && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3) select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the CGsix (GX, TurboGX) frame buffer. @@ -609,7 +566,6 @@ config FB_PVR2 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Say Y here if you have a PowerVR 2 card in your box. If you plan to run linux on your Dreamcast, you will have to say Y here. @@ -631,7 +587,6 @@ config FB_EPSON1355 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Build in support for the SED1355 Epson Research Embedded RAMDAC LCD/CRT Controller (since redesignated as the S1D13505) as a @@ -676,7 +631,6 @@ config FB_S1D13XXX select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Support for S1D13XXX framebuffer device family (currently only working with S1D13806). Product specs at @@ -691,7 +645,6 @@ config FB_NVIDIA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This driver supports graphics boards with the nVidia chips, TNT and newer. For very old chipsets, such as the RIVA128, then use @@ -809,7 +762,6 @@ config FB_INTEL select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This driver supports the on-board graphics built in to the Intel 830M/845G/852GM/855GM/865G chipsets. @@ -832,7 +784,6 @@ config FB_MATROX select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_TILEBLITTING select FB_MACMODES if PPC_PMAC ---help--- @@ -973,7 +924,6 @@ config FB_RADEON_OLD select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES if PPC help Choose this option if you want to use an ATI Radeon graphics card as @@ -991,7 +941,6 @@ config FB_RADEON select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES if PPC_OF help Choose this option if you want to use an ATI Radeon graphics card as @@ -1029,7 +978,6 @@ config FB_ATY128 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES if PPC_PMAC help This driver supports graphics boards with the ATI Rage128 chips. @@ -1045,7 +993,6 @@ config FB_ATY select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES if PPC help This driver supports graphics boards with the ATI Mach64 chips. @@ -1103,7 +1050,6 @@ config FB_SAVAGE select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This driver supports notebooks and computers with S3 Savage PCI/AGP chips. @@ -1140,7 +1086,6 @@ config FB_SIS select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the SiS 300, 315, 330 and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets. @@ -1170,7 +1115,6 @@ config FB_NEOMAGIC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This driver supports notebooks with NeoMagic PCI chips. Say Y if you have such a graphics card. @@ -1184,7 +1128,6 @@ config FB_KYRO select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Say Y here if you have a STG4000 / Kyro / PowerVR 3 based graphics board. @@ -1198,7 +1141,6 @@ config FB_3DFX select FB_CFB_IMAGEBLIT select FB_CFB_FILLRECT select FB_CFB_COPYAREA - select FB_SOFT_CURSOR help This driver supports graphics boards with the 3Dfx Banshee/Voodoo3 chips. Say Y if you have such a graphics board. @@ -1220,7 +1162,6 @@ config FB_VOODOO1 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Say Y here if you have a 3Dfx Voodoo Graphics (Voodoo1/sst1) or Voodoo2 (cvg) based graphics card. @@ -1237,7 +1178,6 @@ config FB_CYBLA tristate "Cyberblade/i1 support" depends on FB && PCI select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select VIDEO_SELECT ---help--- This driver is supposed to support the Trident Cyberblade/i1 @@ -1265,7 +1205,6 @@ config FB_TRIDENT select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- This driver is supposed to support graphics boards with the Trident CyberXXXX/Image/CyberBlade chips mostly found in laptops @@ -1314,7 +1253,6 @@ config FB_FFB depends on FB_SBUS && SPARC64 select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Creator, Creator3D, and Elite3D graphics boards. @@ -1325,7 +1263,6 @@ config FB_TCX select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the TCX 24/8bit frame buffer. @@ -1336,7 +1273,6 @@ config FB_CG14 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the CGfourteen frame buffer on Desktop SPARCsystems with the SX graphics option. @@ -1347,7 +1283,6 @@ config FB_P9100 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the P9100 card supported on Sparcbook 3 machines. @@ -1358,7 +1293,6 @@ config FB_LEO select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the SBUS-based Sun ZX (leo) frame buffer cards. @@ -1373,7 +1307,6 @@ config FB_IGA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the framebuffer device for the INTERGRAPHICS 1680 and successor frame buffer cards. @@ -1384,7 +1317,6 @@ config FB_HIT select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Hitachi HD64461 LCD frame buffer card. @@ -1395,7 +1327,6 @@ config FB_PMAG_AA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Support for the PMAG-AA TURBOchannel framebuffer card (1280x1024x1) used mainly in the MIPS-based DECstation series. @@ -1406,7 +1337,6 @@ config FB_PMAG_BA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Support for the PMAG-BA TURBOchannel framebuffer card (1024x864x8) used mainly in the MIPS-based DECstation series. @@ -1417,7 +1347,6 @@ config FB_PMAGB_B select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Support for the PMAGB-B TURBOchannel framebuffer card used mainly in the MIPS-based DECstation series. The card is currently only @@ -1429,7 +1358,6 @@ config FB_MAXINE select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Support for the onboard framebuffer (1024x768x8) in the Personal DECstation series (Personal DECstation 5000/20, /25, /33, /50, @@ -1441,7 +1369,6 @@ config FB_TX3912 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help The TX3912 is a Toshiba RISC processor based on the MIPS 3900 core see . @@ -1454,7 +1381,6 @@ config FB_G364 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help The G364 driver is the framebuffer used in MIPS Magnum 4000 and Olivetti M700-10 systems. @@ -1465,7 +1391,6 @@ config FB_68328 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Say Y here if you want to support the built-in frame buffer of the Motorola 68328 CPU family. @@ -1476,7 +1401,6 @@ config FB_PXA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Frame buffer driver for the built-in LCD controller in the Intel PXA2x0 processor. @@ -1511,7 +1435,6 @@ config FB_W100 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Frame buffer driver for the w100 as found on the Sharp SL-Cxx series. @@ -1528,7 +1451,6 @@ config FB_S3C2410 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Frame buffer driver for the built-in LCD controller in the Samsung S3C2410 processor. @@ -1552,7 +1474,6 @@ config FB_VIRTUAL select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- This is a `virtual' frame buffer device. It operates on a chunk of unswappable kernel memory instead of on the memory of a graphics diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 97c5d03ac8d..aa434e725c0 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -16,7 +16,6 @@ fb-objs := $(fb-y) obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o -obj-$(CONFIG_FB_SOFT_CURSOR) += softcursor.o obj-$(CONFIG_FB_MACMODES) += macmodes.o # Hardware specific drivers go first diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index 9b6a39348f8..193b482570c 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c @@ -926,7 +926,6 @@ static struct fb_ops acornfb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_mmap = acornfb_mmap, - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index 4fc93dc2b4d..467a1d7ebbd 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c @@ -333,7 +333,6 @@ static struct fb_ops clcdfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_mmap = clcdfb_mmap, }; diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index cf8bb67462d..d549e215f3c 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -1185,7 +1185,6 @@ static struct fb_ops amifb_ops = { .fb_fillrect = amifb_fillrect, .fb_copyarea = amifb_copyarea, .fb_imageblit = amifb_imageblit, - .fb_cursor = soft_cursor, .fb_ioctl = amifb_ioctl, }; diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c index 6aa9f824c18..a1fc8bbb109 100644 --- a/drivers/video/arcfb.c +++ b/drivers/video/arcfb.c @@ -511,7 +511,6 @@ static struct fb_ops arcfb_ops = { .fb_fillrect = arcfb_fillrect, .fb_copyarea = arcfb_copyarea, .fb_imageblit = arcfb_imageblit, - .fb_cursor = soft_cursor, .fb_ioctl = arcfb_ioctl, }; diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c index f4729f4df8c..c64de59398f 100644 --- a/drivers/video/asiliantfb.c +++ b/drivers/video/asiliantfb.c @@ -106,7 +106,6 @@ static struct fb_ops asiliantfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* Calculate the ratios for the dot clocks without using a single long long diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index e380ee8b024..e686185a076 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -478,7 +478,6 @@ static struct fb_ops aty128fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; #ifdef CONFIG_PMAC_BACKLIGHT diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 037fe9d32fe..5e4523ae85b 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -292,7 +292,6 @@ static struct fb_ops atyfb_ops = { .fb_fillrect = atyfb_fillrect, .fb_copyarea = atyfb_copyarea, .fb_imageblit = atyfb_imageblit, - .fb_cursor = soft_cursor, #ifdef __sparc__ .fb_mmap = atyfb_mmap, #endif diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 7ef4b901b93..29f5b2cdbb7 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -1873,7 +1873,6 @@ static struct fb_ops radeonfb_ops = { .fb_fillrect = radeonfb_fillrect, .fb_copyarea = radeonfb_copyarea, .fb_imageblit = radeonfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index 3d20b2d47d4..f53bf3ba127 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c @@ -51,7 +51,6 @@ static struct fb_ops bw2_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = bw2_mmap, .fb_ioctl = bw2_ioctl, - .fb_cursor = soft_cursor, }; /* OBio addresses for the bwtwo registers */ diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index 18e60b941e2..030d4b13b1c 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c @@ -49,7 +49,6 @@ static struct fb_ops cg14_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = cg14_mmap, .fb_ioctl = cg14_ioctl, - .fb_cursor = soft_cursor, }; #define CG14_MCR_INTENABLE_SHIFT 7 diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c index 6e7d8d45dc6..b94eee8c42d 100644 --- a/drivers/video/cg3.c +++ b/drivers/video/cg3.c @@ -50,7 +50,6 @@ static struct fb_ops cg3_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = cg3_mmap, .fb_ioctl = cg3_ioctl, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 49a2545671d..3280bb9560e 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c @@ -54,7 +54,6 @@ static struct fb_ops cg6_ops = { .fb_sync = cg6_sync, .fb_mmap = cg6_mmap, .fb_ioctl = cg6_ioctl, - .fb_cursor = soft_cursor, }; /* Offset of interesting structures in the OBIO space */ diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c index 4131243cfdf..bc061d4ec78 100644 --- a/drivers/video/chipsfb.c +++ b/drivers/video/chipsfb.c @@ -91,7 +91,6 @@ static struct fb_ops chipsfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int chipsfb_check_var(struct fb_var_screeninfo *var, diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 3a26f9cc858..2858c5c8ba3 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -548,7 +548,6 @@ static struct fb_ops cirrusfb_ops = { .fb_fillrect = cirrusfb_fillrect, .fb_copyarea = cirrusfb_copyarea, .fb_imageblit = cirrusfb_imageblit, - .fb_cursor = soft_cursor, }; /*--- Hardware Specific Routines -------------------------------------------*/ diff --git a/drivers/video/clps711xfb.c b/drivers/video/clps711xfb.c index 8692e002986..50b78af0fa2 100644 --- a/drivers/video/clps711xfb.c +++ b/drivers/video/clps711xfb.c @@ -219,7 +219,6 @@ static struct fb_ops clps7111fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile index 42c7b8dcd22..71b4b626e32 100644 --- a/drivers/video/console/Makefile +++ b/drivers/video/console/Makefile @@ -26,7 +26,7 @@ obj-$(CONFIG_PROM_CONSOLE) += promcon.o promcon_tbl.o obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o font.o obj-$(CONFIG_VGA_CONSOLE) += vgacon.o obj-$(CONFIG_MDA_CONSOLE) += mdacon.o -obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o bitblit.o font.o +obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o bitblit.o font.o softcursor.o ifeq ($(CONFIG_FB_TILEBLITTING),y) obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += tileblit.o endif diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c index 9f70e512b88..67857b3cfc8 100644 --- a/drivers/video/console/bitblit.c +++ b/drivers/video/console/bitblit.c @@ -272,6 +272,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int w = (vc->vc_font.width + 7) >> 3, c; int y = real_y(p, vc->vc_y); int attribute, use_sw = (vc->vc_cursor_type & 0x10); + int err = 1; char *src; cursor.set = 0; @@ -408,7 +409,11 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, cursor.image.depth = 1; cursor.rop = ROP_XOR; - info->fbops->fb_cursor(info, &cursor); + if (info->fbops->fb_cursor) + err = info->fbops->fb_cursor(info, &cursor); + + if (err) + soft_cursor(info, &cursor); ops->cursor_reset = 0; } diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h index 0738cd62def..b68e0e2c2d1 100644 --- a/drivers/video/console/fbcon.h +++ b/drivers/video/console/fbcon.h @@ -167,5 +167,5 @@ extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info, struct display *p, struct fbcon_ops *ops); #endif extern void fbcon_set_bitops(struct fbcon_ops *ops); - +extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor); #endif /* _VIDEO_FBCON_H */ diff --git a/drivers/video/console/softcursor.c b/drivers/video/console/softcursor.c new file mode 100644 index 00000000000..8529bf08db2 --- /dev/null +++ b/drivers/video/console/softcursor.c @@ -0,0 +1,72 @@ +/* + * linux/drivers/video/softcursor.c -- Generic software cursor for frame buffer devices + * + * Created 14 Nov 2002 by James Simmons + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include + +#include +#include + +int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) +{ + unsigned int scan_align = info->pixmap.scan_align - 1; + unsigned int buf_align = info->pixmap.buf_align - 1; + unsigned int i, size, dsize, s_pitch, d_pitch; + struct fb_image *image; + u8 *dst, *src; + + if (info->state != FBINFO_STATE_RUNNING) + return 0; + + s_pitch = (cursor->image.width + 7) >> 3; + dsize = s_pitch * cursor->image.height; + + src = kmalloc(dsize + sizeof(struct fb_image), GFP_ATOMIC); + if (!src) + return -ENOMEM; + + image = (struct fb_image *) (src + dsize); + *image = cursor->image; + d_pitch = (s_pitch + scan_align) & ~scan_align; + + size = d_pitch * image->height + buf_align; + size &= ~buf_align; + dst = fb_get_buffer_offset(info, &info->pixmap, size); + + if (cursor->enable) { + switch (cursor->rop) { + case ROP_XOR: + for (i = 0; i < dsize; i++) + src[i] = image->data[i] ^ cursor->mask[i]; + break; + case ROP_COPY: + default: + for (i = 0; i < dsize; i++) + src[i] = image->data[i] & cursor->mask[i]; + break; + } + } else + memcpy(src, image->data, dsize); + + fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, image->height); + image->data = dst; + info->fbops->fb_imageblit(info, image); + kfree(src); + return 0; +} + +EXPORT_SYMBOL(soft_cursor); + +MODULE_AUTHOR("James Simmons "); +MODULE_DESCRIPTION("Generic software cursor"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index 989e700159e..403d17377f8 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c @@ -176,7 +176,6 @@ static struct fb_ops controlfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index 3894b2a501d..c589d23e7f9 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c @@ -1064,7 +1064,6 @@ static struct fb_ops cyber2000fb_ops = { .fb_fillrect = cyber2000fb_fillrect, .fb_copyarea = cyber2000fb_copyarea, .fb_imageblit = cyber2000fb_imageblit, - .fb_cursor = soft_cursor, .fb_sync = cyber2000fb_sync, }; diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c index 6992100a508..03fbe83d71a 100644 --- a/drivers/video/cyblafb.c +++ b/drivers/video/cyblafb.c @@ -968,7 +968,6 @@ static struct fb_ops cyblafb_ops __devinitdata = { .fb_fillrect = cyblafb_fillrect, .fb_copyarea= cyblafb_copyarea, .fb_imageblit = cyblafb_imageblit, - .fb_cursor = soft_cursor, }; //========================================================================== diff --git a/drivers/video/dnfb.c b/drivers/video/dnfb.c index 1785686a7f1..957a3ada2b7 100644 --- a/drivers/video/dnfb.c +++ b/drivers/video/dnfb.c @@ -116,7 +116,6 @@ static struct fb_ops dn_fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = dnfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; struct fb_var_screeninfo dnfb_var __devinitdata = { diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c index 7363d0b25fd..6a81a1dd8f3 100644 --- a/drivers/video/epson1355fb.c +++ b/drivers/video/epson1355fb.c @@ -484,7 +484,6 @@ static struct fb_ops epson1355fb_fbops = { .fb_imageblit = cfb_imageblit, .fb_read = epson1355fb_read, .fb_write = epson1355fb_write, - .fb_cursor = soft_cursor, }; /* ------------------------------------------------------------------------- */ diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index 10cd05059fe..04417dc16c2 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c @@ -57,9 +57,6 @@ static struct fb_ops ffb_ops = { .fb_sync = ffb_sync, .fb_mmap = ffb_mmap, .fb_ioctl = ffb_ioctl, - - /* XXX Use FFB hw cursor once fb cursor API is better understood... */ - .fb_cursor = soft_cursor, }; /* Register layout and definitions */ diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c index a0763283d77..998374cfae6 100644 --- a/drivers/video/fm2fb.c +++ b/drivers/video/fm2fb.c @@ -172,7 +172,6 @@ static struct fb_ops fm2fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index ed853bef19e..9d5e4f34211 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c @@ -1038,7 +1038,6 @@ static struct fb_ops gbefb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/geode/Kconfig b/drivers/video/geode/Kconfig index 5a9b89c3831..42fb9a89a79 100644 --- a/drivers/video/geode/Kconfig +++ b/drivers/video/geode/Kconfig @@ -14,7 +14,6 @@ config FB_GEODE_GX1 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Framebuffer driver for the display controller integrated into the AMD Geode GX1 processor. diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c index 74a5fca86b8..8e8da743399 100644 --- a/drivers/video/geode/gx1fb_core.c +++ b/drivers/video/geode/gx1fb_core.c @@ -275,7 +275,6 @@ static struct fb_ops gx1fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static struct fb_info * __init gx1fb_init_fbinfo(struct device *dev) diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c index 0d376ba5481..f04ca721f94 100644 --- a/drivers/video/hitfb.c +++ b/drivers/video/hitfb.c @@ -262,7 +262,6 @@ static struct fb_ops hitfb_ops = { .fb_fillrect = hitfb_fillrect, .fb_copyarea = hitfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; int __init hitfb_init(void) diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c index e97fe8481d5..bebdac59d23 100644 --- a/drivers/video/hpfb.c +++ b/drivers/video/hpfb.c @@ -193,7 +193,6 @@ static struct fb_ops hpfb_ops = { .fb_fillrect = hpfb_fillrect, .fb_copyarea = hpfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_sync = hpfb_sync, }; diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c index 7b9bf45ab6f..7fbe24206b1 100644 --- a/drivers/video/imsttfb.c +++ b/drivers/video/imsttfb.c @@ -1344,7 +1344,6 @@ static struct fb_ops imsttfb_ops = { .fb_fillrect = imsttfb_fillrect, .fb_copyarea = imsttfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_ioctl = imsttfb_ioctl, }; diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 64d9bcc38da..e20b9f3a255 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -298,7 +298,6 @@ static struct fb_ops imxfb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_blank = imxfb_blank, - .fb_cursor = soft_cursor, /* FIXME: i.MX can do hardware cursor */ }; /* diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index e6d75b926dc..0799b999b31 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c @@ -1485,7 +1485,7 @@ intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor) #endif if (!dinfo->hwcursor) - return soft_cursor(info, cursor); + return -ENODEV; intelfbhw_cursor_hide(dinfo); diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c index d8bac9e9784..5eb4d5c177b 100644 --- a/drivers/video/kyro/fbdev.c +++ b/drivers/video/kyro/fbdev.c @@ -669,7 +669,6 @@ static struct fb_ops kyrofb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int __devinit kyrofb_probe(struct pci_dev *pdev, diff --git a/drivers/video/leo.c b/drivers/video/leo.c index 7e1e7fb168b..84a7fe435bb 100644 --- a/drivers/video/leo.c +++ b/drivers/video/leo.c @@ -51,7 +51,6 @@ static struct fb_ops leo_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = leo_mmap, .fb_ioctl = leo_ioctl, - .fb_cursor = soft_cursor, }; #define LEO_OFF_LC_SS0_KRN 0x00200000UL diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c index 4945a4c0220..cfc748e9427 100644 --- a/drivers/video/macfb.c +++ b/drivers/video/macfb.c @@ -589,7 +589,6 @@ static struct fb_ops macfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; void __init macfb_setup(char *options) diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c index c7f3e132122..a5c825d9946 100644 --- a/drivers/video/matrox/matroxfb_accel.c +++ b/drivers/video/matrox/matroxfb_accel.c @@ -122,7 +122,7 @@ void matrox_cfbX_init(WPMINFO2) { ACCESS_FBINFO(fbops).fb_copyarea = cfb_copyarea; ACCESS_FBINFO(fbops).fb_fillrect = cfb_fillrect; ACCESS_FBINFO(fbops).fb_imageblit = cfb_imageblit; - ACCESS_FBINFO(fbops).fb_cursor = soft_cursor; + ACCESS_FBINFO(fbops).fb_cursor = NULL; accel = (ACCESS_FBINFO(fbcon).var.accel_flags & FB_ACCELF_TEXT) == FB_ACCELF_TEXT; diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index 429047ac615..d52d7d825c4 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c @@ -576,7 +576,6 @@ static struct fb_ops matroxfb_dh_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static struct fb_var_screeninfo matroxfb_dh_defined = { diff --git a/drivers/video/maxinefb.c b/drivers/video/maxinefb.c index f192d995d03..743e7ad26ac 100644 --- a/drivers/video/maxinefb.c +++ b/drivers/video/maxinefb.c @@ -113,7 +113,6 @@ static struct fb_ops maxinefb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; int __init maxinefb_init(void) diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index 5d424a30270..8486e77872d 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c @@ -1665,7 +1665,6 @@ static struct fb_ops neofb_ops = { .fb_fillrect = neofb_fillrect, .fb_copyarea = neofb_copyarea, .fb_imageblit = neofb_imageblit, - .fb_cursor = soft_cursor, }; /* --------------------------------------------------------------------- */ diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index 691151e2bce..cbe165bb181 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -1433,7 +1433,7 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info) info->pixmap.flags = FB_PIXMAP_SYSTEM; if (!hwcur) - info->fbops->fb_cursor = soft_cursor; + info->fbops->fb_cursor = NULL; info->var.accel_flags = (!noaccel); diff --git a/drivers/video/offb.c b/drivers/video/offb.c index 611922c0b22..2c856838694 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -85,7 +85,6 @@ static struct fb_ops offb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c index b76a5a9a125..9aaf65fb623 100644 --- a/drivers/video/p9100.c +++ b/drivers/video/p9100.c @@ -48,7 +48,6 @@ static struct fb_ops p9100_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = p9100_mmap, .fb_ioctl = p9100_ioctl, - .fb_cursor = soft_cursor, }; /* P9100 control registers */ diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index b00887e9851..ca4082ae5a1 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c @@ -109,7 +109,6 @@ static struct fb_ops platinumfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 42c17efa9fb..f4188fe6dd9 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c @@ -1034,7 +1034,6 @@ static struct fb_ops pm2fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c index c98f1c8d7dc..f3927b6cda9 100644 --- a/drivers/video/pmag-ba-fb.c +++ b/drivers/video/pmag-ba-fb.c @@ -128,7 +128,6 @@ static struct fb_ops pmagbafb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c index a483b13e117..25148de5fe6 100644 --- a/drivers/video/pmagb-b-fb.c +++ b/drivers/video/pmagb-b-fb.c @@ -132,7 +132,6 @@ static struct fb_ops pmagbbfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c index 31c547fd383..ec4bacf9dd2 100644 --- a/drivers/video/pvr2fb.c +++ b/drivers/video/pvr2fb.c @@ -230,7 +230,6 @@ static struct fb_ops pvr2fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static struct fb_videomode pvr2_modedb[] __initdata = { diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index efd9333b05c..f305a5b77b2 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -418,7 +418,6 @@ static struct fb_ops pxafb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_blank = pxafb_blank, - .fb_cursor = soft_cursor, .fb_mmap = pxafb_mmap, }; diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c index 8416b2e2b50..bfc41f2c902 100644 --- a/drivers/video/q40fb.c +++ b/drivers/video/q40fb.c @@ -84,7 +84,6 @@ static struct fb_ops q40fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int __init q40fb_probe(struct device *device) diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c index a78b9bd8f89..600318f708f 100644 --- a/drivers/video/radeonfb.c +++ b/drivers/video/radeonfb.c @@ -2218,7 +2218,6 @@ static struct fb_ops radeonfb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, #endif - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c index f4437430dc5..3edbd14c5c4 100644 --- a/drivers/video/s1d13xxxfb.c +++ b/drivers/video/s1d13xxxfb.c @@ -388,7 +388,6 @@ static struct fb_ops s1d13xxxfb_fbops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor }; static int s1d13xxxfb_width_tab[2][4] __devinitdata = { diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index 3cef90456a4..bf679312be0 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c @@ -495,7 +495,6 @@ static struct fb_ops s3c2410fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index 3d35b28aaac..a5184575cfa 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -853,7 +853,6 @@ static struct fb_ops sa1100fb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_blank = sa1100fb_blank, - .fb_cursor = soft_cursor, .fb_mmap = sa1100fb_mmap, }; diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index 7c285455c92..378ea1e34de 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c @@ -1470,7 +1470,6 @@ static struct fb_ops savagefb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, #endif - .fb_cursor = soft_cursor, }; /* --------------------------------------------------------------------- */ diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c index 5ce81f44c76..2e8769dd345 100644 --- a/drivers/video/sgivwfb.c +++ b/drivers/video/sgivwfb.c @@ -126,7 +126,6 @@ static struct fb_ops sgivwfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_mmap = sgivwfb_mmap, }; diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 42c54b69726..dea1a46c67c 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -2002,7 +2002,9 @@ static struct fb_ops sisfb_ops = { .fb_fillrect = fbcon_sis_fillrect, .fb_copyarea = fbcon_sis_copyarea, .fb_imageblit = cfb_imageblit, +#ifdef CONFIG_FB_SOFT_CURSOR .fb_cursor = soft_cursor, +#endif .fb_sync = fbcon_sis_sync, #ifdef SIS_NEW_CONFIG_COMPAT .fb_compat_ioctl= sisfb_compat_ioctl, diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c index 7b43716ab66..a01e7ecc15e 100644 --- a/drivers/video/skeletonfb.c +++ b/drivers/video/skeletonfb.c @@ -457,11 +457,8 @@ void xxxfb_imageblit(struct fb_info *p, const struct fb_image *image) } /** - * xxxfb_cursor - REQUIRED function. If your hardware lacks support - * for a cursor you can use the default cursor whose - * function is called soft_cursor. It will always - * work since it uses xxxfb_imageblit function which - * is required. + * xxxfb_cursor - OPTIONAL. If your hardware lacks support + * for a cursor, leave this field NULL. * * @info: frame buffer structure that represents a single frame buffer * @cursor: structure defining the cursor to draw. @@ -663,7 +660,7 @@ static struct fb_ops xxxfb_ops = { .fb_fillrect = xxxfb_fillrect, /* Needed !!! */ .fb_copyarea = xxxfb_copyarea, /* Needed !!! */ .fb_imageblit = xxxfb_imageblit, /* Needed !!! */ - .fb_cursor = xxxfb_cursor, /* Needed !!! */ + .fb_cursor = xxxfb_cursor, /* Optional !!! */ .fb_rotate = xxxfb_rotate, .fb_poll = xxxfb_poll, .fb_sync = xxxfb_sync, diff --git a/drivers/video/softcursor.c b/drivers/video/softcursor.c deleted file mode 100644 index 229c4bc3507..00000000000 --- a/drivers/video/softcursor.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * linux/drivers/video/softcursor.c -- Generic software cursor for frame buffer devices - * - * Created 14 Nov 2002 by James Simmons - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - */ - -#include -#include -#include -#include -#include - -#include -#include - -int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) -{ - unsigned int scan_align = info->pixmap.scan_align - 1; - unsigned int buf_align = info->pixmap.buf_align - 1; - unsigned int i, size, dsize, s_pitch, d_pitch; - struct fb_image *image; - u8 *dst, *src; - - if (info->state != FBINFO_STATE_RUNNING) - return 0; - - s_pitch = (cursor->image.width + 7) >> 3; - dsize = s_pitch * cursor->image.height; - - src = kmalloc(dsize + sizeof(struct fb_image), GFP_ATOMIC); - if (!src) - return -ENOMEM; - - image = (struct fb_image *) (src + dsize); - *image = cursor->image; - d_pitch = (s_pitch + scan_align) & ~scan_align; - - size = d_pitch * image->height + buf_align; - size &= ~buf_align; - dst = fb_get_buffer_offset(info, &info->pixmap, size); - - if (cursor->enable) { - switch (cursor->rop) { - case ROP_XOR: - for (i = 0; i < dsize; i++) - src[i] = image->data[i] ^ cursor->mask[i]; - break; - case ROP_COPY: - default: - for (i = 0; i < dsize; i++) - src[i] = image->data[i] & cursor->mask[i]; - break; - } - } else - memcpy(src, image->data, dsize); - - fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, image->height); - image->data = dst; - info->fbops->fb_imageblit(info, image); - kfree(src); - return 0; -} - -EXPORT_SYMBOL(soft_cursor); - -MODULE_AUTHOR("James Simmons "); -MODULE_DESCRIPTION("Generic software cursor"); -MODULE_LICENSE("GPL"); diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c index 663d53657fa..e0f14df840d 100644 --- a/drivers/video/sstfb.c +++ b/drivers/video/sstfb.c @@ -1382,7 +1382,6 @@ static struct fb_ops sstfb_ops = { .fb_fillrect = cfb_fillrect, /* sstfb_fillrect */ .fb_copyarea = cfb_copyarea, /* sstfb_copyarea */ .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_ioctl = sstfb_ioctl, }; diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index 9e52794768e..fbb17332afd 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c @@ -1147,7 +1147,6 @@ static struct fb_ops stifb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c index 1986a8b3833..59fff29bc02 100644 --- a/drivers/video/tcx.c +++ b/drivers/video/tcx.c @@ -52,7 +52,6 @@ static struct fb_ops tcx_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = tcx_mmap, .fb_ioctl = tcx_ioctl, - .fb_cursor = soft_cursor, }; /* THC definitions */ diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index 7044226c5d4..9d53387e6a6 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c @@ -184,7 +184,6 @@ static struct fb_ops tdfxfb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, #endif - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c index 9d9d2009ad8..7398bd48ba6 100644 --- a/drivers/video/tgafb.c +++ b/drivers/video/tgafb.c @@ -63,7 +63,6 @@ static struct fb_ops tgafb_ops = { .fb_fillrect = tgafb_fillrect, .fb_copyarea = tgafb_copyarea, .fb_imageblit = tgafb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index 81a6d9f188c..9ac2d317118 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c @@ -1293,7 +1293,6 @@ static struct fb_ops tridentfb_ops = { .fb_fillrect = tridentfb_fillrect, .fb_copyarea= tridentfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; module_init(tridentfb_init); diff --git a/drivers/video/tx3912fb.c b/drivers/video/tx3912fb.c index 39d9ca71856..d904da44e1a 100644 --- a/drivers/video/tx3912fb.c +++ b/drivers/video/tx3912fb.c @@ -89,7 +89,6 @@ static struct fb_ops tx3912fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int tx3912fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index 31a2bbc5397..ce97ec8eae9 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c @@ -135,7 +135,6 @@ static struct fb_ops valkyriefb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* Sets the video mode according to info->var */ diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 3cc23106641..4f02615225a 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -215,7 +215,6 @@ static struct fb_ops vesafb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int __init vesafb_setup(char *options) diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index 92d46555dd8..8794dc5d246 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c @@ -92,7 +92,6 @@ static struct fb_ops vfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_mmap = vfb_mmap, }; diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index b46454c55c9..690bb6fe828 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c @@ -1326,7 +1326,6 @@ static struct fb_ops vga16fb_ops = { .fb_fillrect = vga16fb_fillrect, .fb_copyarea = vga16fb_copyarea, .fb_imageblit = vga16fb_imageblit, - .fb_cursor = soft_cursor, }; #ifndef MODULE diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index cf8cdb108fd..48e70f153c4 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c @@ -397,7 +397,6 @@ static struct fb_ops w100fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; #ifdef CONFIG_PM diff --git a/include/linux/fb.h b/include/linux/fb.h index c698055266d..008ea71f4d7 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -810,7 +810,6 @@ struct fb_info { extern int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var); extern int fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var); extern int fb_blank(struct fb_info *info, int blank); -extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor); extern void cfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect); extern void cfb_copyarea(struct fb_info *info, const struct fb_copyarea *area); extern void cfb_imageblit(struct fb_info *info, const struct fb_image *image); -- cgit v1.2.3 From 4d9c5b6eb42d9e235003dd4531b44462a77131ea Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 7 Nov 2005 01:00:36 -0800 Subject: [PATCH] fbcon: Consolidate redundant code Lot's of redundant code scattered throughout fbcon.c. Consolidate them all into one function, fbcon_update_softback(). Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/fbcon.c | 85 ++++++++++++------------------------------- 1 file changed, 23 insertions(+), 62 deletions(-) diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 0fc8bb499c3..188053eafc6 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -281,6 +281,18 @@ static inline int get_color(struct vc_data *vc, struct fb_info *info, return color; } +static void fbcon_update_softback(struct vc_data *vc) +{ + int l = fbcon_softback_size / vc->vc_size_row; + + if (l > 5) + softback_end = softback_buf + l * vc->vc_size_row; + else + /* Smaller scrollback makes no sense, and 0 would screw + the operation totally */ + softback_top = 0; +} + static void fb_flashcursor(void *private) { struct fb_info *info = private; @@ -1007,16 +1019,8 @@ static void fbcon_init(struct vc_data *vc, int init) if (logo) fbcon_prepare_logo(vc, info, cols, rows, new_cols, new_rows); - if (vc == svc && softback_buf) { - int l = fbcon_softback_size / vc->vc_size_row; - if (l > 5) - softback_end = softback_buf + l * vc->vc_size_row; - else { - /* Smaller scrollback makes no sense, and 0 would screw - the operation totally */ - softback_top = 0; - } - } + if (vc == svc && softback_buf) + fbcon_update_softback(vc); } static void fbcon_deinit(struct vc_data *vc) @@ -1223,18 +1227,8 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, vc_resize(vc, cols, rows); if (CON_IS_VISIBLE(vc)) { update_screen(vc); - if (softback_buf) { - int l = fbcon_softback_size / vc->vc_size_row; - - if (l > 5) - softback_end = softback_buf + l * - vc->vc_size_row; - else { - /* Smaller scrollback makes no sense, and 0 - would screw the operation totally */ - softback_top = 0; - } - } + if (softback_buf) + fbcon_update_softback(vc); } } @@ -1933,19 +1927,11 @@ static int fbcon_switch(struct vc_data *vc) info = registered_fb[con2fb_map[vc->vc_num]]; if (softback_top) { - int l = fbcon_softback_size / vc->vc_size_row; if (softback_lines) fbcon_set_origin(vc); softback_top = softback_curr = softback_in = softback_buf; softback_lines = 0; - - if (l > 5) - softback_end = softback_buf + l * vc->vc_size_row; - else { - /* Smaller scrollback makes no sense, and 0 would screw - the operation totally */ - softback_top = 0; - } + fbcon_update_softback(vc); } if (logo_shown >= 0) { @@ -2235,17 +2221,8 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, /* reset wrap/pan */ info->var.xoffset = info->var.yoffset = p->yscroll = 0; vc_resize(vc, info->var.xres / w, info->var.yres / h); - if (CON_IS_VISIBLE(vc) && softback_buf) { - int l = fbcon_softback_size / vc->vc_size_row; - if (l > 5) - softback_end = - softback_buf + l * vc->vc_size_row; - else { - /* Smaller scrollback makes no sense, and 0 would screw - the operation totally */ - softback_top = 0; - } - } + if (CON_IS_VISIBLE(vc) && softback_buf) + fbcon_update_softback(vc); } else if (CON_IS_VISIBLE(vc) && vc->vc_mode == KD_TEXT) { fbcon_clear_margins(vc, 0); @@ -2615,16 +2592,8 @@ static void fbcon_modechanged(struct fb_info *info) update_var(vc->vc_num, info); fbcon_set_palette(vc, color_table); update_screen(vc); - if (softback_buf) { - int l = fbcon_softback_size / vc->vc_size_row; - if (l > 5) - softback_end = softback_buf + l * vc->vc_size_row; - else { - /* Smaller scrollback makes no sense, and 0 - would screw the operation totally */ - softback_top = 0; - } - } + if (softback_buf) + fbcon_update_softback(vc); } } @@ -2659,16 +2628,8 @@ static void fbcon_set_all_vcs(struct fb_info *info) update_var(vc->vc_num, info); fbcon_set_palette(vc, color_table); update_screen(vc); - if (softback_buf) { - int l = fbcon_softback_size / vc->vc_size_row; - if (l > 5) - softback_end = softback_buf + l * vc->vc_size_row; - else { - /* Smaller scrollback makes no sense, and 0 - would screw the operation totally */ - softback_top = 0; - } - } + if (softback_buf) + fbcon_update_softback(vc); } } } -- cgit v1.2.3 From 3084a895c2a963cb9b32271061c832977ff7293c Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 7 Nov 2005 01:00:37 -0800 Subject: [PATCH] fbcon: Use helper function when filling out var structure Instead of manually filling up the fields in struct fb_var_screeninfo, use the display_to_var() helper. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/fbcon.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 188053eafc6..e111a88612f 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -1886,24 +1886,11 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, mode = fb_find_best_mode(&var, &info->modelist); if (mode == NULL) return -EINVAL; + display_to_var(&var, p); fb_videomode_to_var(&var, mode); + if (width > var.xres/fw || height > var.yres/fh) return -EINVAL; - /* - * The following can probably have any value... Do we need to - * set all of them? - */ - var.bits_per_pixel = p->bits_per_pixel; - var.xres_virtual = p->xres_virtual; - var.yres_virtual = p->yres_virtual; - var.accel_flags = p->accel_flags; - var.width = p->width; - var.height = p->height; - var.red = p->red; - var.green = p->green; - var.blue = p->blue; - var.transp = p->transp; - var.nonstd = p->nonstd; DPRINTK("resize now %ix%i\n", var.xres, var.yres); if (CON_IS_VISIBLE(vc)) { -- cgit v1.2.3 From dd0314f7bb407bc4bdb3ea769b9c8a3a5d39ffd7 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 7 Nov 2005 01:00:38 -0800 Subject: [PATCH] fbcon: Initialize new driver when old driver is released If machine has more than 1 driver installed, and they all drive the same hardware, it's possible that the driver's fb_release() method will attempt to restore the hardware state to the initial state. This will leave the new driver in an undefined state. To prevent this problem, initialize the new driver by calling fb_set_par() when the old driver is released by fbcon. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/fbcon.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index e111a88612f..5ff51cd0a2a 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -630,6 +630,15 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo, kfree(oldinfo->fbcon_par); oldinfo->fbcon_par = NULL; module_put(oldinfo->fbops->owner); + /* + If oldinfo and newinfo are driving the same hardware, + the fb_release() method of oldinfo may attempt to + restore the hardware state. This will leave the + newinfo in an undefined state. Thus, a call to + fb_set_par() may be needed for the newinfo. + */ + if (newinfo->fbops->fb_set_par) + newinfo->fbops->fb_set_par(newinfo); } return err; -- cgit v1.2.3 From b4d8aea6d66aabc1d79aaeb1ecc90562abb8f575 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 7 Nov 2005 01:00:39 -0800 Subject: [PATCH] fbdev: Remove software clipping from drawing functions Remove software clipping from imageblit, fillrect and copyarea. Clipping is not needed because the console layer assures that reads/writes doest not happen beyond the extents of the framebuffer. And software clipping tends to hide bugs, if they do exist. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/cfbcopyarea.c | 36 ------------------------------------ drivers/video/cfbfillrect.c | 24 ++---------------------- drivers/video/cfbimgblt.c | 22 +--------------------- 3 files changed, 3 insertions(+), 79 deletions(-) diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c index 67711f7b11b..cdc71572cf3 100644 --- a/drivers/video/cfbcopyarea.c +++ b/drivers/video/cfbcopyarea.c @@ -349,46 +349,10 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) unsigned long __iomem *dst = NULL, *src = NULL; int bits = BITS_PER_LONG, bytes = bits >> 3; int dst_idx = 0, src_idx = 0, rev_copy = 0; - int x2, y2, vxres, vyres; if (p->state != FBINFO_STATE_RUNNING) return; - /* We want rotation but lack hardware to do it for us. */ - if (!p->fbops->fb_rotate && p->var.rotate) { - } - - vxres = p->var.xres_virtual; - vyres = p->var.yres_virtual; - - if (area->dx > vxres || area->sx > vxres || - area->dy > vyres || area->sy > vyres) - return; - - /* clip the destination - * We could use hardware clipping but on many cards you get around - * hardware clipping by writing to framebuffer directly. - */ - x2 = area->dx + area->width; - y2 = area->dy + area->height; - dx = area->dx > 0 ? area->dx : 0; - dy = area->dy > 0 ? area->dy : 0; - x2 = x2 < vxres ? x2 : vxres; - y2 = y2 < vyres ? y2 : vyres; - width = x2 - dx; - height = y2 - dy; - - if ((width==0) ||(height==0)) - return; - - /* update sx1,sy1 */ - sx += (dx - area->dx); - sy += (dy - area->dy); - - /* the source must be completely inside the virtual screen */ - if (sx < 0 || sy < 0 || (sx + width) > vxres || (sy + height) > vyres) - return; - /* if the beginning of the target area might overlap with the end of the source area, be have to copy the area reverse. */ if ((dy == sy && dx > sx) || (dy > sy)) { diff --git a/drivers/video/cfbfillrect.c b/drivers/video/cfbfillrect.c index e4fc42b013e..167d9314e6e 100644 --- a/drivers/video/cfbfillrect.c +++ b/drivers/video/cfbfillrect.c @@ -344,7 +344,8 @@ bitfill_unaligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) { - unsigned long x2, y2, vxres, vyres, height, width, pat, fg; + unsigned long pat, fg; + unsigned long width = rect->width, height = rect->height; int bits = BITS_PER_LONG, bytes = bits >> 3; u32 bpp = p->var.bits_per_pixel; unsigned long __iomem *dst; @@ -353,27 +354,6 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) if (p->state != FBINFO_STATE_RUNNING) return; - /* We want rotation but lack hardware to do it for us. */ - if (!p->fbops->fb_rotate && p->var.rotate) { - } - - vxres = p->var.xres_virtual; - vyres = p->var.yres_virtual; - - if (!rect->width || !rect->height || - rect->dx > vxres || rect->dy > vyres) - return; - - /* We could use hardware clipping but on many cards you get around - * hardware clipping by writing to framebuffer directly. */ - - x2 = rect->dx + rect->width; - y2 = rect->dy + rect->height; - x2 = x2 < vxres ? x2 : vxres; - y2 = y2 < vyres ? y2 : vyres; - width = x2 - rect->dx; - height = y2 - rect->dy; - if (p->fix.visual == FB_VISUAL_TRUECOLOR || p->fix.visual == FB_VISUAL_DIRECTCOLOR ) fg = ((u32 *) (p->pseudo_palette))[rect->color]; diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c index 4c123abaa84..da664cea7ec 100644 --- a/drivers/video/cfbimgblt.c +++ b/drivers/video/cfbimgblt.c @@ -272,33 +272,13 @@ void cfb_imageblit(struct fb_info *p, const struct fb_image *image) { u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0; u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel; - u32 width = image->width, height = image->height; + u32 width = image->width; u32 dx = image->dx, dy = image->dy; - int x2, y2, vxres, vyres; u8 __iomem *dst1; if (p->state != FBINFO_STATE_RUNNING) return; - vxres = p->var.xres_virtual; - vyres = p->var.yres_virtual; - /* - * We could use hardware clipping but on many cards you get around - * hardware clipping by writing to framebuffer directly like we are - * doing here. - */ - if (image->dx > vxres || image->dy > vyres) - return; - - x2 = image->dx + image->width; - y2 = image->dy + image->height; - dx = image->dx > 0 ? image->dx : 0; - dy = image->dy > 0 ? image->dy : 0; - x2 = x2 < vxres ? x2 : vxres; - y2 = y2 < vyres ? y2 : vyres; - width = x2 - dx; - height = y2 - dy; - bitstart = (dy * p->fix.line_length * 8) + (dx * bpp); start_index = bitstart & (32 - 1); pitch_index = (p->fix.line_length & (bpl - 1)) * 8; -- cgit v1.2.3 From eba50850458cf6e907b6b751cb18711666819406 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 7 Nov 2005 01:00:40 -0800 Subject: [PATCH] vesafb: Fix color palette handling Fix out-of-bounds bug. The pseudopalette has room only for 16 entries, thus, write only the first 16 entries to the pseudopalette. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/vesafb.c | 56 ++++++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 4f02615225a..67e21544395 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -166,45 +166,39 @@ static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green, if (regno >= info->cmap.len) return 1; - switch (info->var.bits_per_pixel) { - case 8: + if (info->var.bits_per_pixel == 8) vesa_setpalette(regno,red,green,blue); - break; - case 16: - if (info->var.red.offset == 10) { - /* 1:5:5:5 */ - ((u32*) (info->pseudo_palette))[regno] = + else if (regno < 16) { + switch (info->var.bits_per_pixel) { + case 16: + if (info->var.red.offset == 10) { + /* 1:5:5:5 */ + ((u32*) (info->pseudo_palette))[regno] = ((red & 0xf800) >> 1) | ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11); - } else { - /* 0:5:6:5 */ - ((u32*) (info->pseudo_palette))[regno] = + } else { + /* 0:5:6:5 */ + ((u32*) (info->pseudo_palette))[regno] = ((red & 0xf800) ) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); + } + break; + case 24: + case 32: + red >>= 8; + green >>= 8; + blue >>= 8; + ((u32 *)(info->pseudo_palette))[regno] = + (red << info->var.red.offset) | + (green << info->var.green.offset) | + (blue << info->var.blue.offset); + break; } - break; - case 24: - red >>= 8; - green >>= 8; - blue >>= 8; - ((u32 *)(info->pseudo_palette))[regno] = - (red << info->var.red.offset) | - (green << info->var.green.offset) | - (blue << info->var.blue.offset); - break; - case 32: - red >>= 8; - green >>= 8; - blue >>= 8; - ((u32 *)(info->pseudo_palette))[regno] = - (red << info->var.red.offset) | - (green << info->var.green.offset) | - (blue << info->var.blue.offset); - break; - } - return 0; + } + + return 0; } static struct fb_ops vesafb_ops = { -- cgit v1.2.3 From 1013d26663199f8c1c31e1fe8e9352da09630d69 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 7 Nov 2005 01:00:41 -0800 Subject: [PATCH] atyfb: Get initial mode timings from LCD BIOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported by: Jean-Philippe Guérard (Bugzilla Bug 1782) "I've tried with video=atyfb:debug and video=atyfb:debug,mode:1280x600, \ nomtrr. In both case, the screen stays black, but seems divided into 4 vertical bands. Some white lines pop up randomly on each vertical band." The problem is a combination of an incorrect xclk plus lack of timing information. The adapter is attached to an LCD device that can do 1280x600 (which is not a standard resolution). The global mode database does not have an entry for it. Fortunately, the Video BIOS contains the complete timing info for this display, however, atyfb is not making use of it. Add support to get the timing information from the BIOS, if available. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/aty/atyfb_base.c | 58 ++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 5e4523ae85b..08edbfcfca5 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -2156,11 +2156,38 @@ static void __init aty_calc_mem_refresh(struct atyfb_par *par, int xclk) static struct fb_info *fb_list = NULL; +#if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) +static int __devinit atyfb_get_timings_from_lcd(struct atyfb_par *par, + struct fb_var_screeninfo *var) +{ + int ret = -EINVAL; + + if (par->lcd_table != 0 && (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { + *var = default_var; + var->xres = var->xres_virtual = par->lcd_hdisp; + var->right_margin = par->lcd_right_margin; + var->left_margin = par->lcd_hblank_len - + (par->lcd_right_margin + par->lcd_hsync_dly + + par->lcd_hsync_len); + var->hsync_len = par->lcd_hsync_len + par->lcd_hsync_dly; + var->yres = var->yres_virtual = par->lcd_vdisp; + var->lower_margin = par->lcd_lower_margin; + var->upper_margin = par->lcd_vblank_len - + (par->lcd_lower_margin + par->lcd_vsync_len); + var->vsync_len = par->lcd_vsync_len; + var->pixclock = par->lcd_pixclock; + ret = 0; + } + + return ret; +} +#endif /* defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) */ + static int __init aty_init(struct fb_info *info, const char *name) { struct atyfb_par *par = (struct atyfb_par *) info->par; const char *ramname = NULL, *xtal; - int gtb_memsize; + int gtb_memsize, has_var = 0; struct fb_var_screeninfo var; u8 pll_ref_div; u32 i; @@ -2468,8 +2495,8 @@ static int __init aty_init(struct fb_info *info, const char *name) * applies to all Mac video cards */ if (mode) { - if (!mac_find_mode(&var, info, mode, 8)) - var = default_var; + if (mac_find_mode(&var, info, mode, 8)) + has_var = 1; } else { if (default_vmode == VMODE_CHOOSE) { if (M64_HAS(G3_PB_1024x768)) @@ -2491,20 +2518,23 @@ static int __init aty_init(struct fb_info *info, const char *name) default_vmode = VMODE_640_480_60; if (default_cmode < CMODE_8 || default_cmode > CMODE_32) default_cmode = CMODE_8; - if (mac_vmode_to_var(default_vmode, default_cmode, &var)) - var = default_var; + if (!mac_vmode_to_var(default_vmode, default_cmode, + &var)) + has_var = 1; } - } else + } + #endif /* !CONFIG_PPC */ - if ( -#if defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64) - /* On Sparc, unless the user gave a specific mode - * specification, use the PROM probed values in - * default_var. - */ - !mode || + +#if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) + if (!atyfb_get_timings_from_lcd(par, &var)) + has_var = 1; #endif - !fb_find_mode(&var, info, mode, NULL, 0, &defmode, 8)) + + if (mode && fb_find_mode(&var, info, mode, NULL, 0, &defmode, 8)) + has_var = 1; + + if (!has_var) var = default_var; if (noaccel) -- cgit v1.2.3 From 1cc650c69f3079ce3c616c998a741bcf6ddf4f4d Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 7 Nov 2005 01:00:41 -0800 Subject: [PATCH] savagefb: Convert from VGA IO access to MMIO access Use MMIO registers instead of banging the VGA IO registers. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/savage/savagefb.h | 206 +++++---- drivers/video/savage/savagefb_driver.c | 818 +++++++++++++++++---------------- 2 files changed, 537 insertions(+), 487 deletions(-) diff --git a/drivers/video/savage/savagefb.h b/drivers/video/savage/savagefb.h index ea17f7e0482..58cfdfb4183 100644 --- a/drivers/video/savage/savagefb.h +++ b/drivers/video/savage/savagefb.h @@ -169,6 +169,7 @@ struct savagefb_par { struct savagefb_i2c_chan chan; unsigned char *edid; u32 pseudo_palette[16]; + int paletteEnabled; int pm_state; int display_type; int dvi; @@ -244,105 +245,150 @@ struct savagefb_par { /* IO functions */ +static inline u8 savage_in8(u32 addr, struct savagefb_par *par) +{ + return readb(par->mmio.vbase + addr); +} + +static inline u16 savage_in16(u32 addr, struct savagefb_par *par) +{ + return readw(par->mmio.vbase + addr); +} + +static inline u32 savage_in32(u32 addr, struct savagefb_par *par) +{ + return readl(par->mmio.vbase + addr); +} + +static inline void savage_out8(u32 addr, u8 val, struct savagefb_par *par) +{ + writeb(val, par->mmio.vbase + addr); +} + +static inline void savage_out16(u32 addr, u16 val, struct savagefb_par *par) +{ + writew(val, par->mmio.vbase + addr); +} + +static inline void savage_out32(u32 addr, u32 val, struct savagefb_par *par) +{ + writel(val, par->mmio.vbase + addr); +} + +static inline u8 vga_in8(int addr, struct savagefb_par *par) +{ + return savage_in8(0x8000 + addr, par); +} + +static inline u16 vga_in16(int addr, struct savagefb_par *par) +{ + return savage_in16(0x8000 + addr, par); +} + +static inline u8 vga_in32(int addr, struct savagefb_par *par) +{ + return savage_in32(0x8000 + addr, par); +} + +static inline void vga_out8(int addr, u8 val, struct savagefb_par *par) +{ + savage_out8(0x8000 + addr, val, par); +} + +static inline void vga_out16(int addr, u16 val, struct savagefb_par *par) +{ + savage_out16(0x8000 + addr, val, par); +} + +static inline void vga_out32(int addr, u32 val, struct savagefb_par *par) +{ + savage_out32(0x8000 + addr, val, par); +} -#define vga_in8(addr) (inb (addr)) -#define vga_in16(addr) (inw (addr)) -#define vga_in32(addr) (inl (addr)) +static inline u8 VGArCR (u8 index, struct savagefb_par *par) +{ + vga_out8(0x3d4, index, par); + return vga_in8(0x3d5, par); +} + +static inline u8 VGArGR (u8 index, struct savagefb_par *par) +{ + vga_out8(0x3ce, index, par); + return vga_in8(0x3cf, par); +} + +static inline u8 VGArSEQ (u8 index, struct savagefb_par *par) +{ + vga_out8(0x3c4, index, par); + return vga_in8(0x3c5, par); +} -#define vga_out8(addr,val) (outb ((val), (addr))) -#define vga_out16(addr,val) (outw ((val), (addr))) -#define vga_out32(addr,val) (outl ((val), (addr))) +static inline void VGAwCR(u8 index, u8 val, struct savagefb_par *par) +{ + vga_out8(0x3d4, index, par); + vga_out8(0x3d5, val, par); +} -#define savage_in16(addr) readw(par->mmio.vbase + (addr)) -#define savage_in32(addr) readl(par->mmio.vbase + (addr)) +static inline void VGAwGR(u8 index, u8 val, struct savagefb_par *par) +{ + vga_out8(0x3ce, index, par); + vga_out8(0x3cf, val, par); +} -#define savage_out16(addr,val) writew((val), par->mmio.vbase + (addr)) -#define savage_out32(addr,val) writel((val), par->mmio.vbase + (addr)) +static inline void VGAwSEQ(u8 index, u8 val, struct savagefb_par *par) +{ + vga_out8(0x3c4, index, par); + vga_out8 (0x3c5, val, par); +} -static inline u8 VGArCR (u8 index) +static inline void VGAenablePalette(struct savagefb_par *par) { - outb (index, 0x3d4); - return inb (0x3d5); + u8 tmp; + + tmp = vga_in8(0x3da, par); + vga_out8(0x3c0, 0x00, par); + par->paletteEnabled = 1; } -static inline u8 VGArGR (u8 index) +static inline void VGAdisablePalette(struct savagefb_par *par) { - outb (index, 0x3ce); - return inb (0x3cf); + u8 tmp; + + tmp = vga_in8(0x3da, par); + vga_out8(0x3c0, 0x20, par); + par->paletteEnabled = 0; } -static inline u8 VGArSEQ (u8 index) +static inline void VGAwATTR(u8 index, u8 value, struct savagefb_par *par) { - outb (index, 0x3c4); - return inb (0x3c5); + u8 tmp; + + if (par->paletteEnabled) + index &= ~0x20; + else + index |= 0x20; + + tmp = vga_in8(0x3da, par); + vga_out8(0x3c0, index, par); + vga_out8 (0x3c0, value, par); } -#define VGAwCR(index, val) \ -do { \ - vga_out8 (0x3d4, index); \ - vga_out8 (0x3d5, val); \ -} while (0) - -#define VGAwGR(index, val) \ -do { \ - vga_out8 (0x3ce, index); \ - vga_out8 (0x3cf, val); \ -} while (0) - -#define VGAwSEQ(index, val) \ -do { \ - vga_out8 (0x3c4, index); \ - vga_out8 (0x3c5, val); \ -} while (0) - -#define VGAenablePalette() \ -do { \ - u8 tmp; \ - \ - tmp = vga_in8 (0x3da); \ - vga_out8 (0x3c0, 0x00); \ - paletteEnabled = 1; \ -} while (0) - -#define VGAdisablePalette() \ -do { \ - u8 tmp; \ - \ - tmp = vga_in8 (0x3da); \ - vga_out8 (0x3c0, 0x20); \ - paletteEnabled = 0; \ -} while (0) - -#define VGAwATTR(index, value) \ -do { \ - u8 tmp; \ - \ - if (paletteEnabled) \ - index &= ~0x20; \ - else \ - index |= 0x20; \ - \ - tmp = vga_in8 (0x3da); \ - vga_out8 (0x3c0, index); \ - vga_out8 (0x3c0, value); \ -} while (0) - -#define VGAwMISC(value) \ -do { \ - vga_out8 (0x3c2, value); \ -} while (0) +static inline void VGAwMISC(u8 value, struct savagefb_par *par) +{ + vga_out8(0x3c2, value, par); +} #ifndef CONFIG_FB_SAVAGE_ACCEL #define savagefb_set_clip(x) #endif -#define VerticalRetraceWait() \ -{ \ - vga_out8 (0x3d4, 0x17); \ - if (vga_in8 (0x3d5) & 0x80) { \ - while ((vga_in8(0x3da) & 0x08) == 0x08) ; \ - while ((vga_in8(0x3da) & 0x08) == 0x00) ; \ - } \ +static inline void VerticalRetraceWait(struct savagefb_par *par) +{ + vga_out8(0x3d4, 0x17, par); + if (vga_in8(0x3d5, par) & 0x80) { + while ((vga_in8(0x3da, par) & 0x08) == 0x08); + while ((vga_in8(0x3da, par) & 0x08) == 0x00); + } } extern int savagefb_probe_i2c_connector(struct fb_info *info, diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index 378ea1e34de..06e989ba3d1 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c @@ -74,7 +74,6 @@ static char *mode_option __initdata = NULL; -static int paletteEnabled = 0; #ifdef MODULE @@ -90,9 +89,9 @@ MODULE_DESCRIPTION("FBDev driver for S3 Savage PCI/AGP Chips"); static void vgaHWSeqReset (struct savagefb_par *par, int start) { if (start) - VGAwSEQ (0x00, 0x01); /* Synchronous Reset */ + VGAwSEQ (0x00, 0x01, par); /* Synchronous Reset */ else - VGAwSEQ (0x00, 0x03); /* End Reset */ + VGAwSEQ (0x00, 0x03, par); /* End Reset */ } static void vgaHWProtect (struct savagefb_par *par, int on) @@ -103,23 +102,23 @@ static void vgaHWProtect (struct savagefb_par *par, int on) /* * Turn off screen and disable sequencer. */ - tmp = VGArSEQ (0x01); + tmp = VGArSEQ (0x01, par); vgaHWSeqReset (par, 1); /* start synchronous reset */ - VGAwSEQ (0x01, tmp | 0x20); /* disable the display */ + VGAwSEQ (0x01, tmp | 0x20, par);/* disable the display */ - VGAenablePalette(); + VGAenablePalette(par); } else { /* * Reenable sequencer, then turn on screen. */ - tmp = VGArSEQ (0x01); + tmp = VGArSEQ (0x01, par); - VGAwSEQ (0x01, tmp & ~0x20); /* reenable display */ + VGAwSEQ (0x01, tmp & ~0x20, par);/* reenable display */ vgaHWSeqReset (par, 0); /* clear synchronous reset */ - VGAdisablePalette(); + VGAdisablePalette(par); } } @@ -127,27 +126,27 @@ static void vgaHWRestore (struct savagefb_par *par) { int i; - VGAwMISC (par->MiscOutReg); + VGAwMISC (par->MiscOutReg, par); for (i = 1; i < 5; i++) - VGAwSEQ (i, par->Sequencer[i]); + VGAwSEQ (i, par->Sequencer[i], par); /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or CRTC[17] */ - VGAwCR (17, par->CRTC[17] & ~0x80); + VGAwCR (17, par->CRTC[17] & ~0x80, par); for (i = 0; i < 25; i++) - VGAwCR (i, par->CRTC[i]); + VGAwCR (i, par->CRTC[i], par); for (i = 0; i < 9; i++) - VGAwGR (i, par->Graphics[i]); + VGAwGR (i, par->Graphics[i], par); - VGAenablePalette(); + VGAenablePalette(par); for (i = 0; i < 21; i++) - VGAwATTR (i, par->Attribute[i]); + VGAwATTR (i, par->Attribute[i], par); - VGAdisablePalette(); + VGAdisablePalette(par); } static void vgaHWInit (struct fb_var_screeninfo *var, @@ -267,7 +266,7 @@ savage3D_waitfifo(struct savagefb_par *par, int space) { int slots = MAXFIFO - space; - while ((savage_in32(0x48C00) & 0x0000ffff) > slots); + while ((savage_in32(0x48C00, par) & 0x0000ffff) > slots); } static void @@ -275,7 +274,7 @@ savage4_waitfifo(struct savagefb_par *par, int space) { int slots = MAXFIFO - space; - while ((savage_in32(0x48C60) & 0x001fffff) > slots); + while ((savage_in32(0x48C60, par) & 0x001fffff) > slots); } static void @@ -283,26 +282,26 @@ savage2000_waitfifo(struct savagefb_par *par, int space) { int slots = MAXFIFO - space; - while ((savage_in32(0x48C60) & 0x0000ffff) > slots); + while ((savage_in32(0x48C60, par) & 0x0000ffff) > slots); } /* Wait for idle accelerator */ static void savage3D_waitidle(struct savagefb_par *par) { - while ((savage_in32(0x48C00) & 0x0008ffff) != 0x80000); + while ((savage_in32(0x48C00, par) & 0x0008ffff) != 0x80000); } static void savage4_waitidle(struct savagefb_par *par) { - while ((savage_in32(0x48C60) & 0x00a00000) != 0x00a00000); + while ((savage_in32(0x48C60, par) & 0x00a00000) != 0x00a00000); } static void savage2000_waitidle(struct savagefb_par *par) { - while ((savage_in32(0x48C60) & 0x009fffff)); + while ((savage_in32(0x48C60, par) & 0x009fffff)); } @@ -319,59 +318,64 @@ SavageSetup2DEngine (struct savagefb_par *par) case S3_SAVAGE3D: case S3_SAVAGE_MX: /* Disable BCI */ - savage_out32(0x48C18, savage_in32(0x48C18) & 0x3FF0); + savage_out32(0x48C18, savage_in32(0x48C18, par) & 0x3FF0, par); /* Setup BCI command overflow buffer */ - savage_out32(0x48C14, (par->cob_offset >> 11) | (par->cob_index << 29)); + savage_out32(0x48C14, + (par->cob_offset >> 11) | (par->cob_index << 29), + par); /* Program shadow status update. */ - savage_out32(0x48C10, 0x78207220); - savage_out32(0x48C0C, 0); + savage_out32(0x48C10, 0x78207220, par); + savage_out32(0x48C0C, 0, par); /* Enable BCI and command overflow buffer */ - savage_out32(0x48C18, savage_in32(0x48C18) | 0x0C); + savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x0C, par); break; case S3_SAVAGE4: case S3_PROSAVAGE: case S3_SUPERSAVAGE: /* Disable BCI */ - savage_out32(0x48C18, savage_in32(0x48C18) & 0x3FF0); + savage_out32(0x48C18, savage_in32(0x48C18, par) & 0x3FF0, par); /* Program shadow status update */ - savage_out32(0x48C10, 0x00700040); - savage_out32(0x48C0C, 0); + savage_out32(0x48C10, 0x00700040, par); + savage_out32(0x48C0C, 0, par); /* Enable BCI without the COB */ - savage_out32(0x48C18, savage_in32(0x48C18) | 0x08); + savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x08, par); break; case S3_SAVAGE2000: /* Disable BCI */ - savage_out32(0x48C18, 0); + savage_out32(0x48C18, 0, par); /* Setup BCI command overflow buffer */ - savage_out32(0x48C18, (par->cob_offset >> 7) | (par->cob_index)); + savage_out32(0x48C18, + (par->cob_offset >> 7) | (par->cob_index), + par); /* Disable shadow status update */ - savage_out32(0x48A30, 0); + savage_out32(0x48A30, 0, par); /* Enable BCI and command overflow buffer */ - savage_out32(0x48C18, savage_in32(0x48C18) | 0x00280000 ); + savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x00280000, + par); break; default: break; } /* Turn on 16-bit register access. */ - vga_out8(0x3d4, 0x31); - vga_out8(0x3d5, 0x0c); + vga_out8(0x3d4, 0x31, par); + vga_out8(0x3d5, 0x0c, par); /* Set stride to use GBD. */ - vga_out8 (0x3d4, 0x50); - vga_out8 (0x3d5, vga_in8 (0x3d5 ) | 0xC1); + vga_out8 (0x3d4, 0x50, par); + vga_out8 (0x3d5, vga_in8(0x3d5, par) | 0xC1, par); /* Enable 2D engine. */ - vga_out8 (0x3d4, 0x40 ); - vga_out8 (0x3d5, 0x01 ); + vga_out8 (0x3d4, 0x40, par); + vga_out8 (0x3d5, 0x01, par); - savage_out32 (MONO_PAT_0, ~0); - savage_out32 (MONO_PAT_1, ~0); + savage_out32 (MONO_PAT_0, ~0, par); + savage_out32 (MONO_PAT_1, ~0, par); /* Setup plane masks */ - savage_out32 (0x8128, ~0 ); /* enable all write planes */ - savage_out32 (0x812C, ~0 ); /* enable all read planes */ - savage_out16 (0x8134, 0x27 ); - savage_out16 (0x8136, 0x07 ); + savage_out32 (0x8128, ~0, par); /* enable all write planes */ + savage_out32 (0x812C, ~0, par); /* enable all read planes */ + savage_out16 (0x8134, 0x27, par); + savage_out16 (0x8136, 0x07, par); /* Now set the GBD */ par->bci_ptr = 0; @@ -489,8 +493,8 @@ static void SavagePrintRegs(void) for( i = 0; i < 0x70; i++ ) { if( !(i % 16) ) printk(KERN_DEBUG "\nSR%xx ", i >> 4 ); - vga_out8( 0x3c4, i ); - printk(KERN_DEBUG " %02x", vga_in8(0x3c5) ); + vga_out8( 0x3c4, i, par); + printk(KERN_DEBUG " %02x", vga_in8(0x3c5, par) ); } printk(KERN_DEBUG "\n\nCR x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC " @@ -499,8 +503,8 @@ static void SavagePrintRegs(void) for( i = 0; i < 0xB7; i++ ) { if( !(i % 16) ) printk(KERN_DEBUG "\nCR%xx ", i >> 4 ); - vga_out8( vgaCRIndex, i ); - printk(KERN_DEBUG " %02x", vga_in8(vgaCRReg) ); + vga_out8( vgaCRIndex, i, par); + printk(KERN_DEBUG " %02x", vga_in8(vgaCRReg, par) ); } printk(KERN_DEBUG "\n\n"); @@ -513,152 +517,152 @@ static void savage_get_default_par(struct savagefb_par *par) { unsigned char cr3a, cr53, cr66; - vga_out16 (0x3d4, 0x4838); - vga_out16 (0x3d4, 0xa039); - vga_out16 (0x3c4, 0x0608); - - vga_out8 (0x3d4, 0x66); - cr66 = vga_in8 (0x3d5); - vga_out8 (0x3d5, cr66 | 0x80); - vga_out8 (0x3d4, 0x3a); - cr3a = vga_in8 (0x3d5); - vga_out8 (0x3d5, cr3a | 0x80); - vga_out8 (0x3d4, 0x53); - cr53 = vga_in8 (0x3d5); - vga_out8 (0x3d5, cr53 & 0x7f); - - vga_out8 (0x3d4, 0x66); - vga_out8 (0x3d5, cr66); - vga_out8 (0x3d4, 0x3a); - vga_out8 (0x3d5, cr3a); - - vga_out8 (0x3d4, 0x66); - vga_out8 (0x3d5, cr66); - vga_out8 (0x3d4, 0x3a); - vga_out8 (0x3d5, cr3a); + vga_out16 (0x3d4, 0x4838, par); + vga_out16 (0x3d4, 0xa039, par); + vga_out16 (0x3c4, 0x0608, par); + + vga_out8 (0x3d4, 0x66, par); + cr66 = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, cr66 | 0x80, par); + vga_out8 (0x3d4, 0x3a, par); + cr3a = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, cr3a | 0x80, par); + vga_out8 (0x3d4, 0x53, par); + cr53 = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, cr53 & 0x7f, par); + + vga_out8 (0x3d4, 0x66, par); + vga_out8 (0x3d5, cr66, par); + vga_out8 (0x3d4, 0x3a, par); + vga_out8 (0x3d5, cr3a, par); + + vga_out8 (0x3d4, 0x66, par); + vga_out8 (0x3d5, cr66, par); + vga_out8 (0x3d4, 0x3a, par); + vga_out8 (0x3d5, cr3a, par); /* unlock extended seq regs */ - vga_out8 (0x3c4, 0x08); - par->SR08 = vga_in8 (0x3c5); - vga_out8 (0x3c5, 0x06); + vga_out8 (0x3c4, 0x08, par); + par->SR08 = vga_in8 (0x3c5, par); + vga_out8 (0x3c5, 0x06, par); /* now save all the extended regs we need */ - vga_out8 (0x3d4, 0x31); - par->CR31 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x32); - par->CR32 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x34); - par->CR34 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x36); - par->CR36 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x3a); - par->CR3A = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x40); - par->CR40 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x42); - par->CR42 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x45); - par->CR45 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x50); - par->CR50 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x51); - par->CR51 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x53); - par->CR53 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x58); - par->CR58 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x60); - par->CR60 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x66); - par->CR66 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x67); - par->CR67 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x68); - par->CR68 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x69); - par->CR69 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x6f); - par->CR6F = vga_in8 (0x3d5); - - vga_out8 (0x3d4, 0x33); - par->CR33 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x86); - par->CR86 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x88); - par->CR88 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x90); - par->CR90 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x91); - par->CR91 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0xb0); - par->CRB0 = vga_in8 (0x3d5) | 0x80; + vga_out8 (0x3d4, 0x31, par); + par->CR31 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x32, par); + par->CR32 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x34, par); + par->CR34 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x36, par); + par->CR36 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x3a, par); + par->CR3A = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x40, par); + par->CR40 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x42, par); + par->CR42 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x45, par); + par->CR45 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x50, par); + par->CR50 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x51, par); + par->CR51 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x53, par); + par->CR53 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x58, par); + par->CR58 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x60, par); + par->CR60 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x66, par); + par->CR66 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x67, par); + par->CR67 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x68, par); + par->CR68 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x69, par); + par->CR69 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x6f, par); + par->CR6F = vga_in8 (0x3d5, par); + + vga_out8 (0x3d4, 0x33, par); + par->CR33 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x86, par); + par->CR86 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x88, par); + par->CR88 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x90, par); + par->CR90 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x91, par); + par->CR91 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0xb0, par); + par->CRB0 = vga_in8 (0x3d5, par) | 0x80; /* extended mode timing regs */ - vga_out8 (0x3d4, 0x3b); - par->CR3B = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x3c); - par->CR3C = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x43); - par->CR43 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x5d); - par->CR5D = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x5e); - par->CR5E = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x65); - par->CR65 = vga_in8 (0x3d5); + vga_out8 (0x3d4, 0x3b, par); + par->CR3B = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x3c, par); + par->CR3C = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x43, par); + par->CR43 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x5d, par); + par->CR5D = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x5e, par); + par->CR5E = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x65, par); + par->CR65 = vga_in8 (0x3d5, par); /* save seq extended regs for DCLK PLL programming */ - vga_out8 (0x3c4, 0x0e); - par->SR0E = vga_in8 (0x3c5); - vga_out8 (0x3c4, 0x0f); - par->SR0F = vga_in8 (0x3c5); - vga_out8 (0x3c4, 0x10); - par->SR10 = vga_in8 (0x3c5); - vga_out8 (0x3c4, 0x11); - par->SR11 = vga_in8 (0x3c5); - vga_out8 (0x3c4, 0x12); - par->SR12 = vga_in8 (0x3c5); - vga_out8 (0x3c4, 0x13); - par->SR13 = vga_in8 (0x3c5); - vga_out8 (0x3c4, 0x29); - par->SR29 = vga_in8 (0x3c5); - - vga_out8 (0x3c4, 0x15); - par->SR15 = vga_in8 (0x3c5); - vga_out8 (0x3c4, 0x30); - par->SR30 = vga_in8 (0x3c5); - vga_out8 (0x3c4, 0x18); - par->SR18 = vga_in8 (0x3c5); + vga_out8 (0x3c4, 0x0e, par); + par->SR0E = vga_in8 (0x3c5, par); + vga_out8 (0x3c4, 0x0f, par); + par->SR0F = vga_in8 (0x3c5, par); + vga_out8 (0x3c4, 0x10, par); + par->SR10 = vga_in8 (0x3c5, par); + vga_out8 (0x3c4, 0x11, par); + par->SR11 = vga_in8 (0x3c5, par); + vga_out8 (0x3c4, 0x12, par); + par->SR12 = vga_in8 (0x3c5, par); + vga_out8 (0x3c4, 0x13, par); + par->SR13 = vga_in8 (0x3c5, par); + vga_out8 (0x3c4, 0x29, par); + par->SR29 = vga_in8 (0x3c5, par); + + vga_out8 (0x3c4, 0x15, par); + par->SR15 = vga_in8 (0x3c5, par); + vga_out8 (0x3c4, 0x30, par); + par->SR30 = vga_in8 (0x3c5, par); + vga_out8 (0x3c4, 0x18, par); + par->SR18 = vga_in8 (0x3c5, par); /* Save flat panel expansion regsters. */ if (par->chip == S3_SAVAGE_MX) { int i; for (i = 0; i < 8; i++) { - vga_out8 (0x3c4, 0x54+i); - par->SR54[i] = vga_in8 (0x3c5); + vga_out8 (0x3c4, 0x54+i, par); + par->SR54[i] = vga_in8 (0x3c5, par); } } - vga_out8 (0x3d4, 0x66); - cr66 = vga_in8 (0x3d5); - vga_out8 (0x3d5, cr66 | 0x80); - vga_out8 (0x3d4, 0x3a); - cr3a = vga_in8 (0x3d5); - vga_out8 (0x3d5, cr3a | 0x80); + vga_out8 (0x3d4, 0x66, par); + cr66 = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, cr66 | 0x80, par); + vga_out8 (0x3d4, 0x3a, par); + cr3a = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, cr3a | 0x80, par); /* now save MIU regs */ if (par->chip != S3_SAVAGE_MX) { - par->MMPR0 = savage_in32(FIFO_CONTROL_REG); - par->MMPR1 = savage_in32(MIU_CONTROL_REG); - par->MMPR2 = savage_in32(STREAMS_TIMEOUT_REG); - par->MMPR3 = savage_in32(MISC_TIMEOUT_REG); + par->MMPR0 = savage_in32(FIFO_CONTROL_REG, par); + par->MMPR1 = savage_in32(MIU_CONTROL_REG, par); + par->MMPR2 = savage_in32(STREAMS_TIMEOUT_REG, par); + par->MMPR3 = savage_in32(MISC_TIMEOUT_REG, par); } - vga_out8 (0x3d4, 0x3a); - vga_out8 (0x3d5, cr3a); - vga_out8 (0x3d4, 0x66); - vga_out8 (0x3d5, cr66); + vga_out8 (0x3d4, 0x3a, par); + vga_out8 (0x3d5, cr3a, par); + vga_out8 (0x3d4, 0x66, par); + vga_out8 (0x3d5, cr66, par); } static void savage_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb) @@ -868,8 +872,8 @@ static int savagefb_decode_var (struct fb_var_screeninfo *var, * match. Fall back to traditional register-crunching. */ - vga_out8 (0x3d4, 0x3a); - tmp = vga_in8 (0x3d5); + vga_out8 (0x3d4, 0x3a, par); + tmp = vga_in8 (0x3d5, par); if (1 /*FIXME:psav->pci_burst*/) par->CR3A = (tmp & 0x7f) | 0x15; else @@ -879,16 +883,16 @@ static int savagefb_decode_var (struct fb_var_screeninfo *var, par->CR31 = 0x8c; par->CR66 = 0x89; - vga_out8 (0x3d4, 0x58); - par->CR58 = vga_in8 (0x3d5) & 0x80; + vga_out8 (0x3d4, 0x58, par); + par->CR58 = vga_in8 (0x3d5, par) & 0x80; par->CR58 |= 0x13; par->SR15 = 0x03 | 0x80; par->SR18 = 0x00; par->CR43 = par->CR45 = par->CR65 = 0x00; - vga_out8 (0x3d4, 0x40); - par->CR40 = vga_in8 (0x3d5) & ~0x01; + vga_out8 (0x3d4, 0x40, par); + par->CR40 = vga_in8 (0x3d5, par) & ~0x01; par->MMPR0 = 0x010400; par->MMPR1 = 0x00; @@ -992,19 +996,19 @@ static int savagefb_decode_var (struct fb_var_screeninfo *var, par->CR67 |= 1; - vga_out8(0x3d4, 0x36); - par->CR36 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x68); - par->CR68 = vga_in8 (0x3d5); + vga_out8(0x3d4, 0x36, par); + par->CR36 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x68, par); + par->CR68 = vga_in8 (0x3d5, par); par->CR69 = 0; - vga_out8 (0x3d4, 0x6f); - par->CR6F = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x86); - par->CR86 = vga_in8 (0x3d5); - vga_out8 (0x3d4, 0x88); - par->CR88 = vga_in8 (0x3d5) | 0x08; - vga_out8 (0x3d4, 0xb0); - par->CRB0 = vga_in8 (0x3d5) | 0x80; + vga_out8 (0x3d4, 0x6f, par); + par->CR6F = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x86, par); + par->CR86 = vga_in8 (0x3d5, par); + vga_out8 (0x3d4, 0x88, par); + par->CR88 = vga_in8 (0x3d5, par) | 0x08; + vga_out8 (0x3d4, 0xb0, par); + par->CRB0 = vga_in8 (0x3d5, par) | 0x80; return 0; } @@ -1033,11 +1037,11 @@ static int savagefb_setcolreg(unsigned regno, switch (info->var.bits_per_pixel) { case 8: - vga_out8 (0x3c8, regno); + vga_out8 (0x3c8, regno, par); - vga_out8 (0x3c9, red >> 10); - vga_out8 (0x3c9, green >> 10); - vga_out8 (0x3c9, blue >> 10); + vga_out8 (0x3c9, red >> 10, par); + vga_out8 (0x3c9, green >> 10, par); + vga_out8 (0x3c9, blue >> 10, par); break; case 16: @@ -1079,11 +1083,11 @@ static void savagefb_set_par_int (struct savagefb_par *par) par->SavageWaitIdle (par); - vga_out8 (0x3c2, 0x23); + vga_out8 (0x3c2, 0x23, par); - vga_out16 (0x3d4, 0x4838); - vga_out16 (0x3d4, 0xa539); - vga_out16 (0x3c4, 0x0608); + vga_out16 (0x3d4, 0x4838, par); + vga_out16 (0x3d4, 0xa539, par); + vga_out16 (0x3c4, 0x0608, par); vgaHWProtect (par, 1); @@ -1094,197 +1098,197 @@ static void savagefb_set_par_int (struct savagefb_par *par) * switch to mode 3 here seems to eliminate the issue. */ - VerticalRetraceWait(); - vga_out8 (0x3d4, 0x67); - cr67 = vga_in8 (0x3d5); - vga_out8 (0x3d5, cr67/*par->CR67*/ & ~0x0c); /* no STREAMS yet */ + VerticalRetraceWait(par); + vga_out8 (0x3d4, 0x67, par); + cr67 = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, cr67/*par->CR67*/ & ~0x0c, par); /* no STREAMS yet */ - vga_out8 (0x3d4, 0x23); - vga_out8 (0x3d5, 0x00); - vga_out8 (0x3d4, 0x26); - vga_out8 (0x3d5, 0x00); + vga_out8 (0x3d4, 0x23, par); + vga_out8 (0x3d5, 0x00, par); + vga_out8 (0x3d4, 0x26, par); + vga_out8 (0x3d5, 0x00, par); /* restore extended regs */ - vga_out8 (0x3d4, 0x66); - vga_out8 (0x3d5, par->CR66); - vga_out8 (0x3d4, 0x3a); - vga_out8 (0x3d5, par->CR3A); - vga_out8 (0x3d4, 0x31); - vga_out8 (0x3d5, par->CR31); - vga_out8 (0x3d4, 0x32); - vga_out8 (0x3d5, par->CR32); - vga_out8 (0x3d4, 0x58); - vga_out8 (0x3d5, par->CR58); - vga_out8 (0x3d4, 0x53); - vga_out8 (0x3d5, par->CR53 & 0x7f); - - vga_out16 (0x3c4, 0x0608); + vga_out8 (0x3d4, 0x66, par); + vga_out8 (0x3d5, par->CR66, par); + vga_out8 (0x3d4, 0x3a, par); + vga_out8 (0x3d5, par->CR3A, par); + vga_out8 (0x3d4, 0x31, par); + vga_out8 (0x3d5, par->CR31, par); + vga_out8 (0x3d4, 0x32, par); + vga_out8 (0x3d5, par->CR32, par); + vga_out8 (0x3d4, 0x58, par); + vga_out8 (0x3d5, par->CR58, par); + vga_out8 (0x3d4, 0x53, par); + vga_out8 (0x3d5, par->CR53 & 0x7f, par); + + vga_out16 (0x3c4, 0x0608, par); /* Restore DCLK registers. */ - vga_out8 (0x3c4, 0x0e); - vga_out8 (0x3c5, par->SR0E); - vga_out8 (0x3c4, 0x0f); - vga_out8 (0x3c5, par->SR0F); - vga_out8 (0x3c4, 0x29); - vga_out8 (0x3c5, par->SR29); - vga_out8 (0x3c4, 0x15); - vga_out8 (0x3c5, par->SR15); + vga_out8 (0x3c4, 0x0e, par); + vga_out8 (0x3c5, par->SR0E, par); + vga_out8 (0x3c4, 0x0f, par); + vga_out8 (0x3c5, par->SR0F, par); + vga_out8 (0x3c4, 0x29, par); + vga_out8 (0x3c5, par->SR29, par); + vga_out8 (0x3c4, 0x15, par); + vga_out8 (0x3c5, par->SR15, par); /* Restore flat panel expansion regsters. */ if( par->chip == S3_SAVAGE_MX ) { int i; for( i = 0; i < 8; i++ ) { - vga_out8 (0x3c4, 0x54+i); - vga_out8 (0x3c5, par->SR54[i]); + vga_out8 (0x3c4, 0x54+i, par); + vga_out8 (0x3c5, par->SR54[i], par); } } vgaHWRestore (par); /* extended mode timing registers */ - vga_out8 (0x3d4, 0x53); - vga_out8 (0x3d5, par->CR53); - vga_out8 (0x3d4, 0x5d); - vga_out8 (0x3d5, par->CR5D); - vga_out8 (0x3d4, 0x5e); - vga_out8 (0x3d5, par->CR5E); - vga_out8 (0x3d4, 0x3b); - vga_out8 (0x3d5, par->CR3B); - vga_out8 (0x3d4, 0x3c); - vga_out8 (0x3d5, par->CR3C); - vga_out8 (0x3d4, 0x43); - vga_out8 (0x3d5, par->CR43); - vga_out8 (0x3d4, 0x65); - vga_out8 (0x3d5, par->CR65); + vga_out8 (0x3d4, 0x53, par); + vga_out8 (0x3d5, par->CR53, par); + vga_out8 (0x3d4, 0x5d, par); + vga_out8 (0x3d5, par->CR5D, par); + vga_out8 (0x3d4, 0x5e, par); + vga_out8 (0x3d5, par->CR5E, par); + vga_out8 (0x3d4, 0x3b, par); + vga_out8 (0x3d5, par->CR3B, par); + vga_out8 (0x3d4, 0x3c, par); + vga_out8 (0x3d5, par->CR3C, par); + vga_out8 (0x3d4, 0x43, par); + vga_out8 (0x3d5, par->CR43, par); + vga_out8 (0x3d4, 0x65, par); + vga_out8 (0x3d5, par->CR65, par); /* restore the desired video mode with cr67 */ - vga_out8 (0x3d4, 0x67); + vga_out8 (0x3d4, 0x67, par); /* following part not present in X11 driver */ - cr67 = vga_in8 (0x3d5) & 0xf; - vga_out8 (0x3d5, 0x50 | cr67); + cr67 = vga_in8 (0x3d5, par) & 0xf; + vga_out8 (0x3d5, 0x50 | cr67, par); udelay (10000); - vga_out8 (0x3d4, 0x67); + vga_out8 (0x3d4, 0x67, par); /* end of part */ - vga_out8 (0x3d5, par->CR67 & ~0x0c); + vga_out8 (0x3d5, par->CR67 & ~0x0c, par); /* other mode timing and extended regs */ - vga_out8 (0x3d4, 0x34); - vga_out8 (0x3d5, par->CR34); - vga_out8 (0x3d4, 0x40); - vga_out8 (0x3d5, par->CR40); - vga_out8 (0x3d4, 0x42); - vga_out8 (0x3d5, par->CR42); - vga_out8 (0x3d4, 0x45); - vga_out8 (0x3d5, par->CR45); - vga_out8 (0x3d4, 0x50); - vga_out8 (0x3d5, par->CR50); - vga_out8 (0x3d4, 0x51); - vga_out8 (0x3d5, par->CR51); + vga_out8 (0x3d4, 0x34, par); + vga_out8 (0x3d5, par->CR34, par); + vga_out8 (0x3d4, 0x40, par); + vga_out8 (0x3d5, par->CR40, par); + vga_out8 (0x3d4, 0x42, par); + vga_out8 (0x3d5, par->CR42, par); + vga_out8 (0x3d4, 0x45, par); + vga_out8 (0x3d5, par->CR45, par); + vga_out8 (0x3d4, 0x50, par); + vga_out8 (0x3d5, par->CR50, par); + vga_out8 (0x3d4, 0x51, par); + vga_out8 (0x3d5, par->CR51, par); /* memory timings */ - vga_out8 (0x3d4, 0x36); - vga_out8 (0x3d5, par->CR36); - vga_out8 (0x3d4, 0x60); - vga_out8 (0x3d5, par->CR60); - vga_out8 (0x3d4, 0x68); - vga_out8 (0x3d5, par->CR68); - vga_out8 (0x3d4, 0x69); - vga_out8 (0x3d5, par->CR69); - vga_out8 (0x3d4, 0x6f); - vga_out8 (0x3d5, par->CR6F); - - vga_out8 (0x3d4, 0x33); - vga_out8 (0x3d5, par->CR33); - vga_out8 (0x3d4, 0x86); - vga_out8 (0x3d5, par->CR86); - vga_out8 (0x3d4, 0x88); - vga_out8 (0x3d5, par->CR88); - vga_out8 (0x3d4, 0x90); - vga_out8 (0x3d5, par->CR90); - vga_out8 (0x3d4, 0x91); - vga_out8 (0x3d5, par->CR91); + vga_out8 (0x3d4, 0x36, par); + vga_out8 (0x3d5, par->CR36, par); + vga_out8 (0x3d4, 0x60, par); + vga_out8 (0x3d5, par->CR60, par); + vga_out8 (0x3d4, 0x68, par); + vga_out8 (0x3d5, par->CR68, par); + vga_out8 (0x3d4, 0x69, par); + vga_out8 (0x3d5, par->CR69, par); + vga_out8 (0x3d4, 0x6f, par); + vga_out8 (0x3d5, par->CR6F, par); + + vga_out8 (0x3d4, 0x33, par); + vga_out8 (0x3d5, par->CR33, par); + vga_out8 (0x3d4, 0x86, par); + vga_out8 (0x3d5, par->CR86, par); + vga_out8 (0x3d4, 0x88, par); + vga_out8 (0x3d5, par->CR88, par); + vga_out8 (0x3d4, 0x90, par); + vga_out8 (0x3d5, par->CR90, par); + vga_out8 (0x3d4, 0x91, par); + vga_out8 (0x3d5, par->CR91, par); if (par->chip == S3_SAVAGE4) { - vga_out8 (0x3d4, 0xb0); - vga_out8 (0x3d5, par->CRB0); + vga_out8 (0x3d4, 0xb0, par); + vga_out8 (0x3d5, par->CRB0, par); } - vga_out8 (0x3d4, 0x32); - vga_out8 (0x3d5, par->CR32); + vga_out8 (0x3d4, 0x32, par); + vga_out8 (0x3d5, par->CR32, par); /* unlock extended seq regs */ - vga_out8 (0x3c4, 0x08); - vga_out8 (0x3c5, 0x06); + vga_out8 (0x3c4, 0x08, par); + vga_out8 (0x3c5, 0x06, par); /* Restore extended sequencer regs for MCLK. SR10 == 255 indicates * that we should leave the default SR10 and SR11 values there. */ if (par->SR10 != 255) { - vga_out8 (0x3c4, 0x10); - vga_out8 (0x3c5, par->SR10); - vga_out8 (0x3c4, 0x11); - vga_out8 (0x3c5, par->SR11); + vga_out8 (0x3c4, 0x10, par); + vga_out8 (0x3c5, par->SR10, par); + vga_out8 (0x3c4, 0x11, par); + vga_out8 (0x3c5, par->SR11, par); } /* restore extended seq regs for dclk */ - vga_out8 (0x3c4, 0x0e); - vga_out8 (0x3c5, par->SR0E); - vga_out8 (0x3c4, 0x0f); - vga_out8 (0x3c5, par->SR0F); - vga_out8 (0x3c4, 0x12); - vga_out8 (0x3c5, par->SR12); - vga_out8 (0x3c4, 0x13); - vga_out8 (0x3c5, par->SR13); - vga_out8 (0x3c4, 0x29); - vga_out8 (0x3c5, par->SR29); - - vga_out8 (0x3c4, 0x18); - vga_out8 (0x3c5, par->SR18); + vga_out8 (0x3c4, 0x0e, par); + vga_out8 (0x3c5, par->SR0E, par); + vga_out8 (0x3c4, 0x0f, par); + vga_out8 (0x3c5, par->SR0F, par); + vga_out8 (0x3c4, 0x12, par); + vga_out8 (0x3c5, par->SR12, par); + vga_out8 (0x3c4, 0x13, par); + vga_out8 (0x3c5, par->SR13, par); + vga_out8 (0x3c4, 0x29, par); + vga_out8 (0x3c5, par->SR29, par); + + vga_out8 (0x3c4, 0x18, par); + vga_out8 (0x3c5, par->SR18, par); /* load new m, n pll values for dclk & mclk */ - vga_out8 (0x3c4, 0x15); - tmp = vga_in8 (0x3c5) & ~0x21; + vga_out8 (0x3c4, 0x15, par); + tmp = vga_in8 (0x3c5, par) & ~0x21; - vga_out8 (0x3c5, tmp | 0x03); - vga_out8 (0x3c5, tmp | 0x23); - vga_out8 (0x3c5, tmp | 0x03); - vga_out8 (0x3c5, par->SR15); + vga_out8 (0x3c5, tmp | 0x03, par); + vga_out8 (0x3c5, tmp | 0x23, par); + vga_out8 (0x3c5, tmp | 0x03, par); + vga_out8 (0x3c5, par->SR15, par); udelay (100); - vga_out8 (0x3c4, 0x30); - vga_out8 (0x3c5, par->SR30); - vga_out8 (0x3c4, 0x08); - vga_out8 (0x3c5, par->SR08); + vga_out8 (0x3c4, 0x30, par); + vga_out8 (0x3c5, par->SR30, par); + vga_out8 (0x3c4, 0x08, par); + vga_out8 (0x3c5, par->SR08, par); /* now write out cr67 in full, possibly starting STREAMS */ - VerticalRetraceWait(); - vga_out8 (0x3d4, 0x67); - vga_out8 (0x3d5, par->CR67); + VerticalRetraceWait(par); + vga_out8 (0x3d4, 0x67, par); + vga_out8 (0x3d5, par->CR67, par); - vga_out8 (0x3d4, 0x66); - cr66 = vga_in8 (0x3d5); - vga_out8 (0x3d5, cr66 | 0x80); - vga_out8 (0x3d4, 0x3a); - cr3a = vga_in8 (0x3d5); - vga_out8 (0x3d5, cr3a | 0x80); + vga_out8 (0x3d4, 0x66, par); + cr66 = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, cr66 | 0x80, par); + vga_out8 (0x3d4, 0x3a, par); + cr3a = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, cr3a | 0x80, par); if (par->chip != S3_SAVAGE_MX) { - VerticalRetraceWait(); - savage_out32 (FIFO_CONTROL_REG, par->MMPR0); + VerticalRetraceWait(par); + savage_out32 (FIFO_CONTROL_REG, par->MMPR0, par); par->SavageWaitIdle (par); - savage_out32 (MIU_CONTROL_REG, par->MMPR1); + savage_out32 (MIU_CONTROL_REG, par->MMPR1, par); par->SavageWaitIdle (par); - savage_out32 (STREAMS_TIMEOUT_REG, par->MMPR2); + savage_out32 (STREAMS_TIMEOUT_REG, par->MMPR2, par); par->SavageWaitIdle (par); - savage_out32 (MISC_TIMEOUT_REG, par->MMPR3); + savage_out32 (MISC_TIMEOUT_REG, par->MMPR3, par); } - vga_out8 (0x3d4, 0x66); - vga_out8 (0x3d5, cr66); - vga_out8 (0x3d4, 0x3a); - vga_out8 (0x3d5, cr3a); + vga_out8 (0x3d4, 0x66, par); + vga_out8 (0x3d5, cr66, par); + vga_out8 (0x3d4, 0x3a, par); + vga_out8 (0x3d5, cr3a, par); SavageSetup2DEngine (par); vgaHWProtect (par, 0); @@ -1299,10 +1303,10 @@ static void savagefb_update_start (struct savagefb_par *par, * ((var->bits_per_pixel+7) / 8)) >> 2; /* now program the start address registers */ - vga_out16(0x3d4, (base & 0x00ff00) | 0x0c); - vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d); - vga_out8 (0x3d4, 0x69); - vga_out8 (0x3d5, (base & 0x7f0000) >> 16); + vga_out16(0x3d4, (base & 0x00ff00) | 0x0c, par); + vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d, par); + vga_out8 (0x3d4, 0x69, par); + vga_out8 (0x3d5, (base & 0x7f0000) >> 16, par); } @@ -1406,12 +1410,12 @@ static int savagefb_blank(int blank, struct fb_info *info) u8 sr8 = 0, srd = 0; if (par->display_type == DISP_CRT) { - vga_out8(0x3c4, 0x08); - sr8 = vga_in8(0x3c5); + vga_out8(0x3c4, 0x08, par); + sr8 = vga_in8(0x3c5, par); sr8 |= 0x06; - vga_out8(0x3c5, sr8); - vga_out8(0x3c4, 0x0d); - srd = vga_in8(0x3c5); + vga_out8(0x3c5, sr8, par); + vga_out8(0x3c4, 0x0d, par); + srd = vga_in8(0x3c5, par); srd &= 0x03; switch (blank) { @@ -1429,8 +1433,8 @@ static int savagefb_blank(int blank, struct fb_info *info) break; } - vga_out8(0x3c4, 0x0d); - vga_out8(0x3c5, srd); + vga_out8(0x3c4, 0x0d, par); + vga_out8(0x3c5, srd, par); } if (par->display_type == DISP_LCD || @@ -1438,14 +1442,14 @@ static int savagefb_blank(int blank, struct fb_info *info) switch(blank) { case FB_BLANK_UNBLANK: case FB_BLANK_NORMAL: - vga_out8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */ - vga_out8(0x3c5, vga_in8(0x3c5) | 0x10); + vga_out8(0x3c4, 0x31, par); /* SR31 bit 4 - FP enable */ + vga_out8(0x3c5, vga_in8(0x3c5, par) | 0x10, par); break; case FB_BLANK_VSYNC_SUSPEND: case FB_BLANK_HSYNC_SUSPEND: case FB_BLANK_POWERDOWN: - vga_out8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */ - vga_out8(0x3c5, vga_in8(0x3c5) & ~0x10); + vga_out8(0x3c4, 0x31, par); /* SR31 bit 4 - FP enable */ + vga_out8(0x3c5, vga_in8(0x3c5, par) & ~0x10, par); break; } } @@ -1498,15 +1502,15 @@ static void savage_enable_mmio (struct savagefb_par *par) DBG ("savage_enable_mmio\n"); - val = vga_in8 (0x3c3); - vga_out8 (0x3c3, val | 0x01); - val = vga_in8 (0x3cc); - vga_out8 (0x3c2, val | 0x01); + val = vga_in8 (0x3c3, par); + vga_out8 (0x3c3, val | 0x01, par); + val = vga_in8 (0x3cc, par); + vga_out8 (0x3c2, val | 0x01, par); if (par->chip >= S3_SAVAGE4) { - vga_out8 (0x3d4, 0x40); - val = vga_in8 (0x3d5); - vga_out8 (0x3d5, val | 1); + vga_out8 (0x3d4, 0x40, par); + val = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, val | 1, par); } } @@ -1518,9 +1522,9 @@ static void savage_disable_mmio (struct savagefb_par *par) DBG ("savage_disable_mmio\n"); if(par->chip >= S3_SAVAGE4 ) { - vga_out8 (0x3d4, 0x40); - val = vga_in8 (0x3d5); - vga_out8 (0x3d5, val | 1); + vga_out8 (0x3d4, 0x40, par); + val = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, val | 1, par); } } @@ -1640,30 +1644,30 @@ static int __devinit savage_init_hw (struct savagefb_par *par) DBG("savage_init_hw"); /* unprotect CRTC[0-7] */ - vga_out8(0x3d4, 0x11); - tmp = vga_in8(0x3d5); - vga_out8(0x3d5, tmp & 0x7f); + vga_out8(0x3d4, 0x11, par); + tmp = vga_in8(0x3d5, par); + vga_out8(0x3d5, tmp & 0x7f, par); /* unlock extended regs */ - vga_out16(0x3d4, 0x4838); - vga_out16(0x3d4, 0xa039); - vga_out16(0x3c4, 0x0608); + vga_out16(0x3d4, 0x4838, par); + vga_out16(0x3d4, 0xa039, par); + vga_out16(0x3c4, 0x0608, par); - vga_out8(0x3d4, 0x40); - tmp = vga_in8(0x3d5); - vga_out8(0x3d5, tmp & ~0x01); + vga_out8(0x3d4, 0x40, par); + tmp = vga_in8(0x3d5, par); + vga_out8(0x3d5, tmp & ~0x01, par); /* unlock sys regs */ - vga_out8(0x3d4, 0x38); - vga_out8(0x3d5, 0x48); + vga_out8(0x3d4, 0x38, par); + vga_out8(0x3d5, 0x48, par); /* Unlock system registers. */ - vga_out16(0x3d4, 0x4838); + vga_out16(0x3d4, 0x4838, par); /* Next go on to detect amount of installed ram */ - vga_out8(0x3d4, 0x36); /* for register CR36 (CONFG_REG1), */ - config1 = vga_in8(0x3d5); /* get amount of vram installed */ + vga_out8(0x3d4, 0x36, par); /* for register CR36 (CONFG_REG1), */ + config1 = vga_in8(0x3d5, par); /* get amount of vram installed */ /* Compute the amount of video memory and offscreen memory. */ @@ -1679,8 +1683,8 @@ static int __devinit savage_init_hw (struct savagefb_par *par) * when it really means 8MB. Why do it the same when you * can do it different... */ - vga_out8(0x3d4, 0x68); /* memory control 1 */ - if( (vga_in8(0x3d5) & 0xC0) == (0x01 << 6) ) + vga_out8(0x3d4, 0x68, par); /* memory control 1 */ + if( (vga_in8(0x3d5, par) & 0xC0) == (0x01 << 6) ) RamSavage4[1] = 8; /*FALLTHROUGH*/ @@ -1709,13 +1713,13 @@ static int __devinit savage_init_hw (struct savagefb_par *par) printk (KERN_INFO "savagefb: probed videoram: %dk\n", videoRam); /* reset graphics engine to avoid memory corruption */ - vga_out8 (0x3d4, 0x66); - cr66 = vga_in8 (0x3d5); - vga_out8 (0x3d5, cr66 | 0x02); + vga_out8 (0x3d4, 0x66, par); + cr66 = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, cr66 | 0x02, par); udelay (10000); - vga_out8 (0x3d4, 0x66); - vga_out8 (0x3d5, cr66 & ~0x02); /* clear reset flag */ + vga_out8 (0x3d4, 0x66, par); + vga_out8 (0x3d5, cr66 & ~0x02, par); /* clear reset flag */ udelay (10000); @@ -1723,13 +1727,13 @@ static int __devinit savage_init_hw (struct savagefb_par *par) * reset memory interface, 3D engine, AGP master, PCI master, * master engine unit, motion compensation/LPB */ - vga_out8 (0x3d4, 0x3f); - cr3f = vga_in8 (0x3d5); - vga_out8 (0x3d5, cr3f | 0x08); + vga_out8 (0x3d4, 0x3f, par); + cr3f = vga_in8 (0x3d5, par); + vga_out8 (0x3d5, cr3f | 0x08, par); udelay (10000); - vga_out8 (0x3d4, 0x3f); - vga_out8 (0x3d5, cr3f & ~0x08); /* clear reset flags */ + vga_out8 (0x3d4, 0x3f, par); + vga_out8 (0x3d5, cr3f & ~0x08, par); /* clear reset flags */ udelay (10000); /* Savage ramdac speeds */ @@ -1740,15 +1744,15 @@ static int __devinit savage_init_hw (struct savagefb_par *par) par->clock[3] = 220000; /* detect current mclk */ - vga_out8(0x3c4, 0x08); - sr8 = vga_in8(0x3c5); - vga_out8(0x3c5, 0x06); - vga_out8(0x3c4, 0x10); - n = vga_in8(0x3c5); - vga_out8(0x3c4, 0x11); - m = vga_in8(0x3c5); - vga_out8(0x3c4, 0x08); - vga_out8(0x3c5, sr8); + vga_out8(0x3c4, 0x08, par); + sr8 = vga_in8(0x3c5, par); + vga_out8(0x3c5, 0x06, par); + vga_out8(0x3c4, 0x10, par); + n = vga_in8(0x3c5, par); + vga_out8(0x3c4, 0x11, par); + m = vga_in8(0x3c5, par); + vga_out8(0x3c4, 0x08, par); + vga_out8(0x3c5, sr8, par); m &= 0x7f; n1 = n & 0x1f; n2 = (n >> 5) & 0x03; @@ -1762,10 +1766,10 @@ static int __devinit savage_init_hw (struct savagefb_par *par) if (par->chip == S3_SAVAGE4) { unsigned char sr30 = 0x00; - vga_out8(0x3c4, 0x30); + vga_out8(0x3c4, 0x30, par); /* clear bit 1 */ - vga_out8(0x3c5, vga_in8(0x3c5) & ~0x02); - sr30 = vga_in8(0x3c5); + vga_out8(0x3c5, vga_in8(0x3c5, par) & ~0x02, par); + sr30 = vga_in8(0x3c5, par); if (sr30 & 0x02 /*0x04 */) { dvi = 1; printk("savagefb: Digital Flat Panel Detected\n"); @@ -1782,12 +1786,12 @@ static int __devinit savage_init_hw (struct savagefb_par *par) /* Check LCD panel parrmation */ if (par->display_type == DISP_LCD) { - unsigned char cr6b = VGArCR( 0x6b ); + unsigned char cr6b = VGArCR( 0x6b, par); - int panelX = (VGArSEQ (0x61) + - ((VGArSEQ (0x66) & 0x02) << 7) + 1) * 8; - int panelY = (VGArSEQ (0x69) + - ((VGArSEQ (0x6e) & 0x70) << 4) + 1); + int panelX = (VGArSEQ (0x61, par) + + ((VGArSEQ (0x66, par) & 0x02) << 7) + 1) * 8; + int panelY = (VGArSEQ (0x69, par) + + ((VGArSEQ (0x6e, par) & 0x70) << 4) + 1); char * sTechnology = "Unknown"; @@ -1809,9 +1813,9 @@ static int __devinit savage_init_hw (struct savagefb_par *par) ActiveDUO = 0x80 }; - if ((VGArSEQ (0x39) & 0x03) == 0) { + if ((VGArSEQ (0x39, par) & 0x03) == 0) { sTechnology = "TFT"; - } else if ((VGArSEQ (0x30) & 0x01) == 0) { + } else if ((VGArSEQ (0x30, par) & 0x01) == 0) { sTechnology = "DSTN"; } else { sTechnology = "STN"; -- cgit v1.2.3 From 9127fa28595093a146fc3e2c937747e014e4bfa2 Mon Sep 17 00:00:00 2001 From: Peter 'p2' De Schrijver Date: Mon, 7 Nov 2005 01:00:42 -0800 Subject: [PATCH] pm2fb: Manual configuration of timings for Elsa Winner 2000 Office Attached is a small patch which configures the correct memory clock and timings on the Elsa Winner 2000 Office pm2 based card. This is necessary when the card is used on a platform which does not support PC style BIOS initialization. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/pm2fb.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index f4188fe6dd9..0277ce031e5 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c @@ -1120,6 +1120,22 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev, default_par->mem_control, default_par->boot_address, default_par->mem_config); + if(default_par->mem_control == 0 && + default_par->boot_address == 0x31 && + default_par->mem_config == 0x259fffff && + pdev->subsystem_vendor == 0x1048 && + pdev->subsystem_device == 0x0a31) { + DPRINTK("subsystem_vendor: %04x, subsystem_device: %04x\n", + pdev->subsystem_vendor, pdev->subsystem_device); + DPRINTK("We have not been initialized by VGA BIOS " + "and are running on an Elsa Winner 2000 Office\n"); + DPRINTK("Initializing card timings manually...\n"); + default_par->mem_control=0; + default_par->boot_address=0x20; + default_par->mem_config=0xe6002021; + default_par->memclock=100000; + } + /* Now work out how big lfb is going to be. */ switch(default_par->mem_config & PM2F_MEM_CONFIG_RAM_MASK) { case PM2F_MEM_BANKS_1: -- cgit v1.2.3 From 475666d4f80f148a091fa20257fe2381223d3c62 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 7 Nov 2005 01:00:46 -0800 Subject: [PATCH] fbdev: Workaround for buggy EDID blocks Some EDID blocks set the flag "prefer first detailed timing" without providing any detailed timing at all. Clear this flag if the block does not provide detailed timings. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/fbmon.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c index 713226cdf3c..442a52d1091 100644 --- a/drivers/video/fbmon.c +++ b/drivers/video/fbmon.c @@ -827,7 +827,7 @@ int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var) void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs) { unsigned char *block; - int i; + int i, found = 0; if (edid == NULL) return; @@ -869,6 +869,22 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs) get_monspecs(edid, specs); specs->modedb = fb_create_modedb(edid, &specs->modedb_len); + + /* + * Workaround for buggy EDIDs that sets that the first + * detailed timing is preferred but has not detailed + * timing specified + */ + for (i = 0; i < specs->modedb_len; i++) { + if (specs->modedb[i].flag & FB_MODE_IS_DETAILED) { + found = 1; + break; + } + } + + if (!found) + specs->misc &= ~FB_MISC_1ST_DETAIL; + DPRINTK("========================================\n"); } -- cgit v1.2.3 From 2fe0175491c4784d95f3237ebdc985da7b26a99d Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 7 Nov 2005 01:00:46 -0800 Subject: [PATCH] nvidiafb: Fix empty macro Use do {} while(0) for empty reverse_order() macro. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/nvidia/nv_local.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/nvidia/nv_local.h b/drivers/video/nvidia/nv_local.h index afee284fc73..4243d7fae97 100644 --- a/drivers/video/nvidia/nv_local.h +++ b/drivers/video/nvidia/nv_local.h @@ -105,7 +105,7 @@ do { \ *a = byte_rev[*a]; \ } while(0) #else -#define reverse_order(l) +#define reverse_order(l) do { } while(0) #endif /* __LITTLE_ENDIAN */ #endif /* __NV_LOCAL_H__ */ -- cgit v1.2.3 From 8fb6567e347a04d44b57e2b223cc5845859dfc6a Mon Sep 17 00:00:00 2001 From: Michal Januszewski Date: Mon, 7 Nov 2005 01:00:47 -0800 Subject: [PATCH] fbdev: fix the fb_find_nearest_mode() function Currently the fb_find_nearest_mode() function finds a mode with screen resolution closest to that described by the 'var' argument and with some arbitrary refresh rate (eg. in the following sequence of refresh rates: 70 60 53 85 75, 53 is selected). This patch fixes the function so that it looks for the closest mode as far as both resolution and refresh rate are concerned. The function's first argument is changed to fb_videomode so that the refresh rate can be specified by the caller, as fb_var_screeninfo doesn't have any fields that could directly hold this data. Signed-off-by: Michal Januszewski Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/fbcon.c | 3 ++- drivers/video/modedb.c | 24 +++++++++++++----------- include/linux/fb.h | 2 +- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 5ff51cd0a2a..3cf1b61ff1f 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -2715,7 +2715,8 @@ static void fbcon_new_modelist(struct fb_info *info) continue; vc = vc_cons[i].d; display_to_var(&var, &fb_display[i]); - mode = fb_find_nearest_mode(&var, &info->modelist); + mode = fb_find_nearest_mode(fb_display[i].mode, + &info->modelist); fb_videomode_to_var(&var, mode); if (vc) diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index 47516c44a39..aadef046ce7 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c @@ -676,6 +676,8 @@ void fb_var_to_videomode(struct fb_videomode *mode, mode->sync = var->sync; mode->vmode = var->vmode & FB_VMODE_MASK; mode->flag = FB_MODE_IS_FROM_VAR; + mode->refresh = 0; + if (!var->pixclock) return; @@ -785,39 +787,39 @@ struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var, } /** - * fb_find_nearest_mode - find mode closest video mode + * fb_find_nearest_mode - find closest videomode * - * @var: pointer to struct fb_var_screeninfo + * @mode: pointer to struct fb_videomode * @head: pointer to modelist * * Finds best matching videomode, smaller or greater in dimension. * If more than 1 videomode is found, will return the videomode with - * the closest refresh rate + * the closest refresh rate. */ -struct fb_videomode *fb_find_nearest_mode(struct fb_var_screeninfo *var, +struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode, struct list_head *head) { struct list_head *pos; struct fb_modelist *modelist; - struct fb_videomode *mode, *best = NULL; + struct fb_videomode *cmode, *best = NULL; u32 diff = -1, diff_refresh = -1; list_for_each(pos, head) { u32 d; modelist = list_entry(pos, struct fb_modelist, list); - mode = &modelist->mode; + cmode = &modelist->mode; - d = abs(mode->xres - var->xres) + - abs(mode->yres - var->yres); + d = abs(cmode->xres - mode->xres) + + abs(cmode->yres - mode->yres); if (diff > d) { diff = d; - best = mode; + best = cmode; } else if (diff == d) { - d = abs(mode->refresh - best->refresh); + d = abs(cmode->refresh - mode->refresh); if (diff_refresh > d) { diff_refresh = d; - best = mode; + best = cmode; } } } diff --git a/include/linux/fb.h b/include/linux/fb.h index 008ea71f4d7..68a787914d8 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -897,7 +897,7 @@ extern struct fb_videomode *fb_match_mode(struct fb_var_screeninfo *var, struct list_head *head); extern struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var, struct list_head *head); -extern struct fb_videomode *fb_find_nearest_mode(struct fb_var_screeninfo *var, +extern struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode, struct list_head *head); extern void fb_destroy_modelist(struct list_head *head); extern void fb_videomode_to_modelist(struct fb_videomode *modedb, int num, -- cgit v1.2.3 From 2726bff34441dce3854c62c3748bac2e7879e791 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 7 Nov 2005 01:00:48 -0800 Subject: [PATCH] s3c2410fb: initialise device_driver .owner Initialise the .owner field, so that if the driver is built as a module, the system has a link to the owner Signed-off-by: Ben Dooks Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/s3c2410fb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index bf679312be0..855a6778b9e 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c @@ -884,6 +884,7 @@ static int s3c2410fb_resume(struct device *dev) static struct device_driver s3c2410fb_driver = { .name = "s3c2410-lcd", + .owner = THIS_MODULE, .bus = &platform_bus_type, .probe = s3c2410fb_probe, .suspend = s3c2410fb_suspend, -- cgit v1.2.3 From 8a0934f2969df4cdea81cf48fde4c8626b32325d Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 7 Nov 2005 01:00:49 -0800 Subject: [PATCH] vesafb: Disable mtrr as the default vesafb occassionally gets the size wrong when setting the mtrr. When X or DRI attempts to set the mtrr, it will fail due to range overlap significantly affecting their performance. Disable mtrr and let the user explicitly enable it with the mtrr:n option. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/fb/vesafb.txt | 4 ++-- drivers/video/vesafb.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/fb/vesafb.txt b/Documentation/fb/vesafb.txt index 62db6758d1c..ee277dd204b 100644 --- a/Documentation/fb/vesafb.txt +++ b/Documentation/fb/vesafb.txt @@ -146,10 +146,10 @@ pmipal Use the protected mode interface for palette changes. mtrr:n setup memory type range registers for the vesafb framebuffer where n: - 0 - disabled (equivalent to nomtrr) + 0 - disabled (equivalent to nomtrr) (default) 1 - uncachable 2 - write-back - 3 - write-combining (default) + 3 - write-combining 4 - write-through If you see the following in dmesg, choose the type that matches the diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 67e21544395..e25eae1a78c 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -48,7 +48,7 @@ static struct fb_fix_screeninfo vesafb_fix __initdata = { }; static int inverse = 0; -static int mtrr = 3; /* default to write-combining */ +static int mtrr = 0; /* disable mtrr */ static int vram_remap __initdata = 0; /* Set amount of memory to be used */ static int vram_total __initdata = 0; /* Set total amount of memory */ static int pmi_setpal = 0; /* pmi for palette changes ??? */ -- cgit v1.2.3 From 5fab851ea15206cc375582ad0db79f7827325098 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 7 Nov 2005 01:00:50 -0800 Subject: [PATCH] i810fb: Cleanup I2C code - The functions for reading the 1st and 2nd bus are essentially the same, except for the register. Consolidate them all. - According to Nicolas Boichat, there is an undocumented 3rd i2c bus for attaching daughter cards. Add support for this. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/i810/i810-i2c.c | 135 ++++++++++++++--------------------------- drivers/video/i810/i810.h | 3 +- drivers/video/i810/i810_main.c | 2 +- drivers/video/i810/i810_regs.h | 1 + 4 files changed, 51 insertions(+), 90 deletions(-) diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c index 689d2586366..c61bad0da20 100644 --- a/drivers/video/i810/i810-i2c.c +++ b/drivers/video/i810/i810-i2c.c @@ -46,92 +46,45 @@ static void i810i2c_setscl(void *data, int state) struct i810fb_par *par = chan->par; u8 __iomem *mmio = par->mmio_start_virtual; - i810_writel(mmio, GPIOB, (state ? SCL_VAL_OUT : 0) | SCL_DIR | + i810_writel(mmio, chan->ddc_base, (state ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK); - i810_readl(mmio, GPIOB); /* flush posted write */ + i810_readl(mmio, chan->ddc_base); /* flush posted write */ } static void i810i2c_setsda(void *data, int state) { - struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; + struct i810fb_i2c_chan *chan = data; struct i810fb_par *par = chan->par; u8 __iomem *mmio = par->mmio_start_virtual; - i810_writel(mmio, GPIOB, (state ? SDA_VAL_OUT : 0) | SDA_DIR | + i810_writel(mmio, chan->ddc_base, (state ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK); - i810_readl(mmio, GPIOB); /* flush posted write */ + i810_readl(mmio, chan->ddc_base); /* flush posted write */ } static int i810i2c_getscl(void *data) { - struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; + struct i810fb_i2c_chan *chan = data; struct i810fb_par *par = chan->par; u8 __iomem *mmio = par->mmio_start_virtual; - i810_writel(mmio, GPIOB, SCL_DIR_MASK); - i810_writel(mmio, GPIOB, 0); - return (0 != (i810_readl(mmio, GPIOB) & SCL_VAL_IN)); + i810_writel(mmio, chan->ddc_base, SCL_DIR_MASK); + i810_writel(mmio, chan->ddc_base, 0); + return ((i810_readl(mmio, chan->ddc_base) & SCL_VAL_IN) != 0); } static int i810i2c_getsda(void *data) { - struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; + struct i810fb_i2c_chan *chan = data; struct i810fb_par *par = chan->par; u8 __iomem *mmio = par->mmio_start_virtual; - i810_writel(mmio, GPIOB, SDA_DIR_MASK); - i810_writel(mmio, GPIOB, 0); - return (0 != (i810_readl(mmio, GPIOB) & SDA_VAL_IN)); -} - -static void i810ddc_setscl(void *data, int state) -{ - struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; - struct i810fb_par *par = chan->par; - u8 __iomem *mmio = par->mmio_start_virtual; - - i810_writel(mmio, GPIOA, (state ? SCL_VAL_OUT : 0) | SCL_DIR | - SCL_DIR_MASK | SCL_VAL_MASK); - i810_readl(mmio, GPIOA); /* flush posted write */ -} - -static void i810ddc_setsda(void *data, int state) -{ - struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; - struct i810fb_par *par = chan->par; - u8 __iomem *mmio = par->mmio_start_virtual; - - i810_writel(mmio, GPIOA, (state ? SDA_VAL_OUT : 0) | SDA_DIR | - SDA_DIR_MASK | SDA_VAL_MASK); - i810_readl(mmio, GPIOA); /* flush posted write */ -} - -static int i810ddc_getscl(void *data) -{ - struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; - struct i810fb_par *par = chan->par; - u8 __iomem *mmio = par->mmio_start_virtual; - - i810_writel(mmio, GPIOA, SCL_DIR_MASK); - i810_writel(mmio, GPIOA, 0); - return (0 != (i810_readl(mmio, GPIOA) & SCL_VAL_IN)); -} - -static int i810ddc_getsda(void *data) -{ - struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; - struct i810fb_par *par = chan->par; - u8 __iomem *mmio = par->mmio_start_virtual; - - i810_writel(mmio, GPIOA, SDA_DIR_MASK); - i810_writel(mmio, GPIOA, 0); - return (0 != (i810_readl(mmio, GPIOA) & SDA_VAL_IN)); + i810_writel(mmio, chan->ddc_base, SDA_DIR_MASK); + i810_writel(mmio, chan->ddc_base, 0); + return ((i810_readl(mmio, chan->ddc_base) & SDA_VAL_IN) != 0); } -#define I2C_ALGO_DDC_I810 0x0e0000 -#define I2C_ALGO_I2C_I810 0x0f0000 -static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name, - int conn) +static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name) { int rc; @@ -139,22 +92,11 @@ static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name, chan->adapter.owner = THIS_MODULE; chan->adapter.algo_data = &chan->algo; chan->adapter.dev.parent = &chan->par->dev->dev; - switch (conn) { - case 1: - chan->adapter.id = I2C_ALGO_DDC_I810; - chan->algo.setsda = i810ddc_setsda; - chan->algo.setscl = i810ddc_setscl; - chan->algo.getsda = i810ddc_getsda; - chan->algo.getscl = i810ddc_getscl; - break; - case 2: - chan->adapter.id = I2C_ALGO_I2C_I810; - chan->algo.setsda = i810i2c_setsda; - chan->algo.setscl = i810i2c_setscl; - chan->algo.getsda = i810i2c_getsda; - chan->algo.getscl = i810i2c_getscl; - break; - } + chan->adapter.id = I2C_HW_B_I810; + chan->algo.setsda = i810i2c_setsda; + chan->algo.setscl = i810i2c_setscl; + chan->algo.getsda = i810i2c_getsda; + chan->algo.getscl = i810i2c_getscl; chan->algo.udelay = 10; chan->algo.mdelay = 10; chan->algo.timeout = (HZ/2); @@ -168,11 +110,15 @@ static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name, udelay(20); rc = i2c_bit_add_bus(&chan->adapter); + if (rc == 0) dev_dbg(&chan->par->dev->dev, "I2C bus %s registered.\n",name); - else + else { dev_warn(&chan->par->dev->dev, "Failed to register I2C bus " "%s.\n", name); + chan->par = NULL; + } + return rc; } @@ -180,8 +126,14 @@ void i810_create_i2c_busses(struct i810fb_par *par) { par->chan[0].par = par; par->chan[1].par = par; - i810_setup_i2c_bus(&par->chan[0], "I810-DDC", 1); - i810_setup_i2c_bus(&par->chan[1], "I810-I2C", 2); + par->chan[2].par = par; + + par->chan[0].ddc_base = GPIOA; + i810_setup_i2c_bus(&par->chan[0], "I810-DDC"); + par->chan[1].ddc_base = GPIOB; + i810_setup_i2c_bus(&par->chan[1], "I810-I2C"); + par->chan[2].ddc_base = GPIOC; + i810_setup_i2c_bus(&par->chan[2], "I810-GPIOC"); } void i810_delete_i2c_busses(struct i810fb_par *par) @@ -189,9 +141,14 @@ void i810_delete_i2c_busses(struct i810fb_par *par) if (par->chan[0].par) i2c_bit_del_bus(&par->chan[0].adapter); par->chan[0].par = NULL; + if (par->chan[1].par) i2c_bit_del_bus(&par->chan[1].adapter); par->chan[1].par = NULL; + + if (par->chan[2].par) + i2c_bit_del_bus(&par->chan[2].adapter); + par->chan[2].par = NULL; } static u8 *i810_do_probe_i2c_edid(struct i810fb_i2c_chan *chan) @@ -221,6 +178,7 @@ static u8 *i810_do_probe_i2c_edid(struct i810fb_i2c_chan *chan) DPRINTK("i810-i2c: I2C Transfer successful\n"); return buf; } + DPRINTK("i810-i2c: Unable to read EDID block.\n"); kfree(buf); return NULL; @@ -233,7 +191,7 @@ int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn) int i; DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn); - if (conn < 3) { + if (conn < 4) { for (i = 0; i < 3; i++) { /* Do the real work */ edid = i810_do_probe_i2c_edid(&par->chan[conn-1]); @@ -241,11 +199,14 @@ int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn) break; } } else { - DPRINTK("i810-i2c: Getting EDID from BIOS\n"); - edid = kmalloc(EDID_LENGTH, GFP_KERNEL); - if (edid) - memcpy(edid, fb_firmware_edid(info->device), - EDID_LENGTH); + const u8 *e = fb_firmware_edid(info->device); + + if (e != NULL) { + DPRINTK("i810-i2c: Getting EDID from BIOS\n"); + edid = kmalloc(EDID_LENGTH, GFP_KERNEL); + if (edid) + memcpy(edid, e, EDID_LENGTH); + } } if (out_edid) @@ -253,5 +214,3 @@ int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn) return (edid) ? 0 : 1; } - - diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h index d48949ceaac..6c187d5fe95 100644 --- a/drivers/video/i810/i810.h +++ b/drivers/video/i810/i810.h @@ -249,6 +249,7 @@ struct i810fb_i2c_chan { struct i810fb_par *par; struct i2c_adapter adapter; struct i2c_algo_bit_data algo; + unsigned long ddc_base; }; struct i810fb_par { @@ -262,7 +263,7 @@ struct i810fb_par { struct heap_data iring; struct heap_data cursor_heap; struct vgastate state; - struct i810fb_i2c_chan chan[2]; + struct i810fb_i2c_chan chan[3]; atomic_t use_count; u32 pseudo_palette[17]; unsigned long mmio_start_phys; diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 0dbc9ddb676..4175b2d8513 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c @@ -1854,7 +1854,7 @@ static void __devinit i810fb_find_init_mode(struct fb_info *info) #ifdef CONFIG_FB_I810_I2C i810_create_i2c_busses(par); - for (i = 0; i < 3; i++) { + for (i = 0; i < 4; i++) { err = i810_probe_i2c_connector(info, &par->edid, i+1); if (!err) break; diff --git a/drivers/video/i810/i810_regs.h b/drivers/video/i810/i810_regs.h index 6e4b9afa4d9..91c6bd9d0d0 100644 --- a/drivers/video/i810/i810_regs.h +++ b/drivers/video/i810/i810_regs.h @@ -70,6 +70,7 @@ #define HVSYNC 0x05000 #define GPIOA 0x05010 #define GPIOB 0x05014 +#define GPIOC 0x0501C /* Clock Control and Power Management Registers (06000h 06FFFh) */ #define DCLK_0D 0x06000 -- cgit v1.2.3 From e07dea98761270249f33e733ff86420bc52ccab6 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 7 Nov 2005 01:00:51 -0800 Subject: [PATCH] console: Fix compile error Fix following compile error (From Kernel Bugzilla Bug 5427): include/linux/console_struct.h:53: error: field `vt_mode' has incomplete type Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/console_struct.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h index 725be90ef55..f8e5587a0f9 100644 --- a/include/linux/console_struct.h +++ b/include/linux/console_struct.h @@ -9,6 +9,8 @@ * to achieve effects such as fast scrolling by changing the origin. */ +#include + struct vt_struct; #define NPAR 16 -- cgit v1.2.3 From 998e6d51162707685336ff99c029c8911b270d32 Mon Sep 17 00:00:00 2001 From: Zach Smith Date: Mon, 7 Nov 2005 01:00:52 -0800 Subject: [PATCH] fbcon: Add rl (Roman Large) font I converted the "rl" console font from the kbd utility to be a built-in font for the framebuffer console, and I was wondering if you would be OK with including it. I've generated a font_rl.c file and related minor modifications. I find it's the most visually appealing of the kbd fonts which is why I use it and selected it for conversion. I believe the font is GPL'd. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/Kconfig | 7 + drivers/video/console/Makefile | 1 + drivers/video/console/font_rl.c | 4374 +++++++++++++++++++++++++++++++++++++++ drivers/video/console/fonts.c | 4 + include/linux/font.h | 2 + 5 files changed, 4388 insertions(+) create mode 100644 drivers/video/console/font_rl.c diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index 81d44995f9e..fadf7c5d216 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -205,5 +205,12 @@ config FONT_10x18 big letters. It fits between the sun 12x22 and the normal 8x16 font. If other fonts are too big or too small for you, say Y, otherwise say N. +config FONT_RL + bool "console Roman Large 8x16 font" if FONTS + depends on FRAMEBUFFER_CONSOLE + help + This is the visually-appealing "RL" console font that is + included with the kbd package. + endmenu diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile index 71b4b626e32..5222628accc 100644 --- a/drivers/video/console/Makefile +++ b/drivers/video/console/Makefile @@ -15,6 +15,7 @@ font-objs-$(CONFIG_FONT_10x18) += font_10x18.o font-objs-$(CONFIG_FONT_PEARL_8x8) += font_pearl_8x8.o font-objs-$(CONFIG_FONT_ACORN_8x8) += font_acorn_8x8.o font-objs-$(CONFIG_FONT_MINI_4x6) += font_mini_4x6.o +font-objs-$(CONFIG_FONT_RL) += font_rl.o font-objs += $(font-objs-y) diff --git a/drivers/video/console/font_rl.c b/drivers/video/console/font_rl.c new file mode 100644 index 00000000000..dfecc27d8de --- /dev/null +++ b/drivers/video/console/font_rl.c @@ -0,0 +1,4374 @@ + +/* This font is simply the "rl.fnt" console font from the kbd utility. + * Converted by Zack T Smith, fbui@comcast.net. + * The original binary file is covered under the GNU Public License. + */ + +#include + +#define FONTDATAMAX 4096 + +static unsigned char patterns[4096] = { +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x3c, +0x42, +0x81, +0xe7, +0xa5, +0x99, +0x81, +0x81, +0x99, +0x42, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x3c, +0x7e, +0xff, +0x99, +0xdb, +0xe7, +0xff, +0xff, +0xe7, +0x7e, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x6c, +0xfe, +0xfe, +0xfe, +0xfe, +0xfe, +0x7c, +0x38, +0x10, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x10, +0x38, +0x7c, +0xfe, +0x7c, +0x38, +0x10, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x38, +0x38, +0x10, +0xd6, +0xfe, +0xd6, +0x10, +0x10, +0x38, +0x7c, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x10, +0x38, +0x7c, +0xfe, +0xfe, +0x54, +0x10, +0x10, +0x38, +0x7c, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x18, +0x3c, +0x3c, +0x18, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xe7, +0xc3, +0xc3, +0xe7, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x3c, +0x66, +0x42, +0x42, +0x66, +0x3c, +0x00, +0x00, +0x00, +0x00, +0x00, + +0xff, +0xff, +0xff, +0xff, +0xff, +0xc3, +0x99, +0xbd, +0xbd, +0x99, +0xc3, +0xff, +0xff, +0xff, +0xff, +0xff, + +0x00, +0x00, +0x0f, +0x07, +0x0d, +0x18, +0x78, +0xcc, +0xcc, +0xcc, +0xcc, +0x78, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x3c, +0x66, +0x66, +0x66, +0x3c, +0x18, +0x7e, +0x18, +0x18, +0x18, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x08, +0x0c, +0x0a, +0x0a, +0x0a, +0x08, +0x08, +0x08, +0x38, +0x78, +0x30, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x10, +0x18, +0x1c, +0x1e, +0x1e, +0x16, +0x12, +0x72, +0xf2, +0x62, +0x0e, +0x1e, +0x0c, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x10, +0x92, +0x54, +0x38, +0xfe, +0x38, +0x54, +0x92, +0x10, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x80, +0xc0, +0xe0, +0xb8, +0x8e, +0xb8, +0xe0, +0xc0, +0x80, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x02, +0x06, +0x0e, +0x3a, +0xe2, +0x3a, +0x0e, +0x06, +0x02, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x10, +0x38, +0x7c, +0xd6, +0x10, +0x10, +0x10, +0x10, +0xd6, +0x7c, +0x38, +0x10, +0x00, +0x00, + +0x00, +0x42, +0xe7, +0xe7, +0xe7, +0xe7, +0x42, +0x42, +0x42, +0x00, +0x66, +0x66, +0x66, +0x00, +0x00, +0x00, + +0x00, +0x7f, +0xca, +0xca, +0xca, +0xca, +0x7a, +0x0a, +0x0a, +0x0a, +0x0a, +0x0a, +0x1b, +0x00, +0x00, +0x00, + +0x00, +0x1e, +0x31, +0x78, +0xcc, +0xc6, +0xc3, +0x63, +0x33, +0x1e, +0x8c, +0x78, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xfe, +0xfe, +0xfe, +0xfe, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x10, +0x38, +0x7c, +0xd6, +0x10, +0x10, +0x10, +0x10, +0xd6, +0x7c, +0x38, +0x10, +0xfe, +0x00, + +0x00, +0x00, +0x10, +0x38, +0x7c, +0xd6, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x00, +0x00, + +0x00, +0x00, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0xd6, +0x7c, +0x38, +0x10, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x08, +0x0c, +0x06, +0xff, +0x06, +0x0c, +0x08, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x10, +0x30, +0x60, +0xff, +0x60, +0x30, +0x10, +0x00, +0x00, +0x00, +0x00, + +0x22, +0x44, +0x88, +0xcc, +0xee, +0x44, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x24, +0x42, +0xff, +0x42, +0x24, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x10, +0x38, +0x38, +0x6c, +0x6c, +0xc6, +0xfe, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0xfe, +0xc6, +0x6c, +0x6c, +0x38, +0x38, +0x10, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x18, +0x3c, +0x3c, +0x3c, +0x3c, +0x18, +0x18, +0x18, +0x10, +0x00, +0x18, +0x18, +0x00, +0x00, +0x00, + +0x22, +0x77, +0x33, +0x11, +0x22, +0x44, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x12, +0x12, +0x12, +0x7f, +0x24, +0x24, +0x24, +0xfe, +0x48, +0x48, +0x48, +0x00, +0x00, +0x00, + +0x10, +0x10, +0x7c, +0xd2, +0xd0, +0xd0, +0xd0, +0x7c, +0x16, +0x16, +0x16, +0x96, +0x7c, +0x10, +0x10, +0x00, + +0x00, +0x42, +0xbe, +0x44, +0x0c, +0x08, +0x18, +0x10, +0x30, +0x20, +0x64, +0x4a, +0xc4, +0x00, +0x00, +0x00, + +0x00, +0x38, +0x6c, +0x6c, +0x6c, +0x38, +0x37, +0x72, +0xdc, +0xcc, +0xcc, +0xcc, +0x77, +0x00, +0x00, +0x00, + +0x10, +0x38, +0x18, +0x08, +0x10, +0x20, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x04, +0x08, +0x10, +0x10, +0x30, +0x30, +0x30, +0x30, +0x30, +0x10, +0x10, +0x08, +0x04, +0x00, +0x00, + +0x00, +0x20, +0x10, +0x08, +0x08, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x08, +0x08, +0x10, +0x20, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x44, +0x28, +0x38, +0xfe, +0x38, +0x28, +0x44, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x18, +0x18, +0x7e, +0x18, +0x18, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x10, +0x38, +0x18, +0x08, +0x10, +0x20, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x7e, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x10, +0x38, +0x10, +0x00, +0x00, +0x00, + +0x00, +0x06, +0x06, +0x0c, +0x0c, +0x18, +0x18, +0x30, +0x30, +0x60, +0x60, +0xc0, +0xc0, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x3c, +0x46, +0xc6, +0xc6, +0xc6, +0xc6, +0xc6, +0xc4, +0x78, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x08, +0x18, +0x78, +0x18, +0x18, +0x18, +0x18, +0x18, +0x7e, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x7c, +0x86, +0x06, +0x0c, +0x18, +0x20, +0x40, +0xc1, +0xfe, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x3c, +0x46, +0x04, +0x08, +0x1c, +0x06, +0x06, +0x06, +0x06, +0x0c, +0x70, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x04, +0x08, +0x10, +0x2c, +0x4c, +0x8c, +0x8c, +0xfe, +0x0c, +0x0c, +0x0c, +0x00, + +0x00, +0x00, +0x00, +0x02, +0x3c, +0x20, +0x20, +0x70, +0x0c, +0x06, +0x06, +0x06, +0x06, +0x0c, +0x70, +0x00, + +0x00, +0x00, +0x18, +0x20, +0x40, +0xc0, +0xdc, +0xc6, +0xc6, +0xc6, +0xc6, +0x44, +0x38, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x40, +0x7e, +0x82, +0x06, +0x04, +0x0c, +0x18, +0x18, +0x30, +0x30, +0x30, +0x30, +0x00, + +0x00, +0x00, +0x7c, +0xc6, +0xc6, +0x64, +0x38, +0x4c, +0xc6, +0xc6, +0xc6, +0xc6, +0x7c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x38, +0x44, +0xc6, +0xc6, +0x76, +0x06, +0x06, +0x06, +0x04, +0x08, +0x30, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x10, +0x38, +0x10, +0x00, +0x00, +0x00, +0x10, +0x38, +0x10, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x10, +0x38, +0x10, +0x00, +0x00, +0x00, +0x10, +0x38, +0x18, +0x08, +0x10, +0x20, + +0x00, +0x06, +0x0c, +0x18, +0x30, +0x60, +0xa0, +0xa0, +0x60, +0x30, +0x18, +0x0c, +0x06, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x7e, +0x00, +0x00, +0x7e, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x60, +0x30, +0x18, +0x0c, +0x06, +0x05, +0x05, +0x06, +0x0c, +0x18, +0x30, +0x60, +0x00, +0x00, +0x00, + +0x00, +0x7c, +0x86, +0xc6, +0x06, +0x04, +0x08, +0x10, +0x10, +0x18, +0x00, +0x18, +0x18, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x3c, +0x46, +0xc6, +0xce, +0xd6, +0xd6, +0xd6, +0xdc, +0xc0, +0xc4, +0x78, +0x00, +0x00, +0x00, + +0x00, +0x18, +0x18, +0x18, +0x3c, +0x2c, +0x2c, +0x2c, +0x7e, +0x46, +0x46, +0x46, +0xef, +0x00, +0x00, +0x00, + +0x00, +0xfc, +0x66, +0x66, +0x66, +0x66, +0x7c, +0x66, +0x66, +0x66, +0x66, +0x66, +0xfc, +0x00, +0x00, +0x00, + +0x00, +0x3a, +0x66, +0xc2, +0xc0, +0xc0, +0xc0, +0xc0, +0xc0, +0xc0, +0xc0, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0xfc, +0x66, +0x63, +0x63, +0x63, +0x63, +0x63, +0x63, +0x63, +0x63, +0x66, +0xfc, +0x00, +0x00, +0x00, + +0x00, +0xff, +0x61, +0x60, +0x60, +0x64, +0x7c, +0x64, +0x60, +0x60, +0x60, +0x61, +0xfe, +0x00, +0x00, +0x00, + +0x00, +0xff, +0x61, +0x61, +0x60, +0x64, +0x7c, +0x64, +0x60, +0x60, +0x60, +0x60, +0xf0, +0x00, +0x00, +0x00, + +0x00, +0x3a, +0x66, +0xc2, +0xc0, +0xc0, +0xc0, +0xcf, +0xc6, +0xc6, +0xc6, +0x66, +0x38, +0x00, +0x00, +0x00, + +0x00, +0xf7, +0x62, +0x62, +0x62, +0x62, +0x7e, +0x62, +0x62, +0x62, +0x62, +0x62, +0xf7, +0x00, +0x00, +0x00, + +0x00, +0x3c, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x1e, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x08, +0xf0, + +0x00, +0xf7, +0x64, +0x6c, +0x68, +0x68, +0x78, +0x6c, +0x6c, +0x6c, +0x66, +0x66, +0xf7, +0x00, +0x00, +0x00, + +0x00, +0xf8, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x61, +0xfe, +0x00, +0x00, +0x00, + +0x00, +0xc3, +0x66, +0x76, +0x7e, +0x56, +0x56, +0x46, +0x46, +0x46, +0x46, +0x46, +0xef, +0x00, +0x00, +0x00, + +0x00, +0xe7, +0x62, +0x62, +0x72, +0x52, +0x5a, +0x4a, +0x4e, +0x46, +0x46, +0x42, +0xe2, +0x00, +0x00, +0x00, + +0x00, +0x3c, +0x66, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0xfc, +0x66, +0x66, +0x66, +0x66, +0x6c, +0x60, +0x60, +0x60, +0x60, +0x60, +0xf0, +0x00, +0x00, +0x00, + +0x00, +0x3c, +0x66, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0x66, +0x3c, +0x10, +0x39, +0x0e, + +0x00, +0xfc, +0x66, +0x66, +0x66, +0x66, +0x7c, +0x6c, +0x66, +0x66, +0x66, +0x66, +0xf3, +0x00, +0x00, +0x00, + +0x00, +0x7a, +0xc6, +0xc2, +0xc0, +0x70, +0x3c, +0x0e, +0x06, +0x06, +0x86, +0xc6, +0xbc, +0x00, +0x00, +0x00, + +0x00, +0xff, +0x99, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0xf7, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0xf7, +0x62, +0x62, +0x62, +0x76, +0x34, +0x34, +0x34, +0x3c, +0x18, +0x18, +0x18, +0x00, +0x00, +0x00, + +0x00, +0xf7, +0x62, +0x62, +0x62, +0x62, +0x6a, +0x6a, +0x6a, +0x6a, +0x7e, +0x7e, +0x34, +0x00, +0x00, +0x00, + +0x00, +0xf7, +0x62, +0x62, +0x34, +0x34, +0x18, +0x18, +0x2c, +0x2c, +0x46, +0x46, +0xef, +0x00, +0x00, +0x00, + +0x00, +0xf7, +0x62, +0x62, +0x62, +0x34, +0x34, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x7f, +0x46, +0x86, +0x0c, +0x0c, +0x18, +0x18, +0x30, +0x30, +0x61, +0x62, +0xfe, +0x00, +0x00, +0x00, + +0x00, +0x3c, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0xc0, +0xc0, +0x60, +0x60, +0x30, +0x30, +0x18, +0x18, +0x0c, +0x0c, +0x06, +0x06, +0x00, +0x00, +0x00, + +0x00, +0x3c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x10, +0x38, +0x4c, +0x86, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0x00, +0x00, + +0x00, +0x18, +0x20, +0x30, +0x38, +0x10, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x78, +0x8c, +0x0c, +0x3c, +0xcc, +0xcc, +0xcd, +0x76, +0x00, +0x00, +0x00, + +0x00, +0x20, +0xe0, +0x60, +0x60, +0x6c, +0x76, +0x66, +0x66, +0x66, +0x66, +0x76, +0x6c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x3c, +0x66, +0x60, +0x60, +0x60, +0x60, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x04, +0x1c, +0x0c, +0x0c, +0x6c, +0xdc, +0xcc, +0xcc, +0xcc, +0xcc, +0xdc, +0x66, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x3c, +0x66, +0x7e, +0x60, +0x60, +0x60, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x1e, +0x31, +0x33, +0x30, +0x30, +0x78, +0x30, +0x30, +0x30, +0x30, +0x30, +0x78, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x7b, +0xce, +0xcc, +0xcc, +0xcc, +0x78, +0x60, +0x7c, +0x86, +0xc6, +0x7c, + +0x00, +0x20, +0xe0, +0x60, +0x60, +0x6c, +0x76, +0x66, +0x66, +0x66, +0x66, +0x66, +0xf7, +0x00, +0x00, +0x00, + +0x00, +0x10, +0x38, +0x10, +0x00, +0x18, +0x38, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x08, +0x1c, +0x08, +0x00, +0x0c, +0x1c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x6c, +0x4c, +0x38, +0x00, + +0x00, +0x20, +0xe0, +0x60, +0x60, +0x67, +0x66, +0x6c, +0x78, +0x6c, +0x6c, +0x66, +0xe7, +0x00, +0x00, +0x00, + +0x00, +0x08, +0x38, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x6a, +0xfe, +0x6a, +0x6a, +0x6a, +0x62, +0x62, +0xf7, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x5c, +0xf6, +0x66, +0x66, +0x66, +0x66, +0x66, +0xf7, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x3c, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x5c, +0xe6, +0x66, +0x66, +0x66, +0x66, +0x66, +0x7c, +0x60, +0x60, +0xf0, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x76, +0xcc, +0xcc, +0xcc, +0xcc, +0xcc, +0xcc, +0x7c, +0x0c, +0x0c, +0x1e, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x5e, +0xf6, +0x60, +0x60, +0x60, +0x60, +0x60, +0xf0, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x7a, +0xc6, +0x72, +0x1c, +0x06, +0x86, +0xc6, +0xbc, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x10, +0x30, +0x7c, +0x30, +0x30, +0x30, +0x30, +0x30, +0x34, +0x18, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0xee, +0x66, +0x66, +0x66, +0x66, +0x66, +0x67, +0x3a, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0xf7, +0x62, +0x76, +0x34, +0x34, +0x3c, +0x18, +0x18, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0xf7, +0x62, +0x6a, +0x6a, +0x6a, +0x6a, +0x7e, +0x24, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0xf7, +0x62, +0x34, +0x18, +0x2c, +0x46, +0x46, +0xef, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0xf7, +0x62, +0x62, +0x34, +0x34, +0x18, +0x18, +0x18, +0x10, +0xb0, +0xe0, + +0x00, +0x00, +0x00, +0x00, +0x00, +0xfe, +0x8c, +0x18, +0x30, +0x30, +0x60, +0xc2, +0xfe, +0x00, +0x00, +0x00, + +0x00, +0x0e, +0x18, +0x10, +0x10, +0x08, +0x70, +0x70, +0x08, +0x10, +0x10, +0x18, +0x0e, +0x00, +0x00, +0x00, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x00, +0x00, + +0x00, +0x70, +0x18, +0x08, +0x08, +0x10, +0x0e, +0x0e, +0x10, +0x08, +0x08, +0x18, +0x70, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x76, +0xdc, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x10, +0x38, +0x6c, +0xc6, +0xc6, +0xc6, +0xfe, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x3a, +0x66, +0xc2, +0xc0, +0xc0, +0xc0, +0xc0, +0xc0, +0x62, +0x3c, +0x18, +0x0c, +0x24, +0x18, + +0x00, +0x00, +0x66, +0x00, +0x00, +0xee, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3b, +0x00, +0x00, +0x00, + +0x00, +0x0c, +0x18, +0x20, +0x00, +0x3c, +0x66, +0x7e, +0x60, +0x60, +0x60, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x30, +0x58, +0x8c, +0x00, +0x78, +0x8c, +0x0c, +0x3c, +0xcc, +0xcc, +0xcd, +0x76, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x66, +0x00, +0x00, +0x78, +0x8c, +0x0c, +0x3c, +0xcc, +0xcc, +0xcd, +0x76, +0x00, +0x00, +0x00, + +0x00, +0x30, +0x18, +0x04, +0x00, +0x78, +0x8c, +0x0c, +0x3c, +0xcc, +0xcc, +0xcd, +0x76, +0x00, +0x00, +0x00, + +0x38, +0x44, +0x44, +0x38, +0x00, +0x78, +0x8c, +0x0c, +0x3c, +0xcc, +0xcc, +0xcd, +0x76, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x3c, +0x66, +0x60, +0x60, +0x60, +0x60, +0x62, +0x3c, +0x08, +0x24, +0x18, + +0x00, +0x18, +0x2c, +0x46, +0x00, +0x3c, +0x66, +0x7e, +0x60, +0x60, +0x60, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x66, +0x00, +0x00, +0x3c, +0x66, +0x7e, +0x60, +0x60, +0x60, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x30, +0x18, +0x04, +0x00, +0x3c, +0x66, +0x7e, +0x60, +0x60, +0x60, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x66, +0x00, +0x00, +0x38, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x18, +0x2c, +0x46, +0x00, +0x38, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x60, +0x30, +0x08, +0x00, +0x38, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x66, +0x18, +0x18, +0x18, +0x3c, +0x2c, +0x2c, +0x2c, +0x7e, +0x46, +0x46, +0x46, +0xef, +0x00, +0x00, +0x00, + +0x18, +0x24, +0x18, +0x18, +0x3c, +0x2c, +0x2c, +0x2c, +0x7e, +0x46, +0x46, +0x46, +0xef, +0x00, +0x00, +0x00, + +0x0c, +0x18, +0xff, +0x61, +0x60, +0x60, +0x64, +0x7c, +0x64, +0x60, +0x60, +0x61, +0xfe, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x76, +0x9b, +0x1b, +0x3f, +0xd8, +0xd8, +0xd9, +0x6e, +0x00, +0x00, +0x00, + +0x00, +0x1f, +0x1d, +0x1d, +0x3c, +0x2c, +0x2e, +0x2c, +0x7c, +0x4c, +0x4c, +0x4d, +0xef, +0x00, +0x00, +0x00, + +0x00, +0x18, +0x2c, +0x46, +0x00, +0x3c, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x66, +0x00, +0x00, +0x3c, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x30, +0x18, +0x04, +0x00, +0x3c, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x18, +0x2c, +0x46, +0x00, +0xee, +0x66, +0x66, +0x66, +0x66, +0x66, +0x67, +0x3a, +0x00, +0x00, +0x00, + +0x00, +0x30, +0x18, +0x04, +0x00, +0xee, +0x66, +0x66, +0x66, +0x66, +0x66, +0x67, +0x3a, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x66, +0x00, +0x00, +0xf7, +0x62, +0x62, +0x34, +0x34, +0x18, +0x18, +0x18, +0x10, +0xb0, +0xe0, + +0x66, +0x00, +0x3c, +0x66, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x66, +0x00, +0xf7, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x10, +0x10, +0x10, +0x7c, +0xc6, +0xc0, +0xc0, +0xc0, +0xc0, +0xc2, +0x7c, +0x10, +0x10, +0x00, + +0x00, +0x38, +0x64, +0x6c, +0x60, +0x60, +0xf0, +0x60, +0x60, +0x60, +0x60, +0x66, +0xfc, +0x00, +0x00, +0x00, + +0x00, +0x81, +0xc3, +0x66, +0x3c, +0x18, +0xff, +0x18, +0x18, +0xff, +0x18, +0x18, +0x18, +0x00, +0x00, +0x00, + +0x00, +0xfe, +0x63, +0x63, +0x63, +0x63, +0x6e, +0x60, +0x64, +0x6e, +0x64, +0x64, +0xf5, +0x06, +0x00, +0x00, + +0x00, +0x0e, +0x19, +0x1b, +0x18, +0x18, +0x3c, +0x18, +0x18, +0x18, +0x18, +0xd8, +0x98, +0x70, +0x00, +0x00, + +0x00, +0x0c, +0x18, +0x20, +0x00, +0x78, +0x8c, +0x0c, +0x3c, +0xcc, +0xcc, +0xcd, +0x76, +0x00, +0x00, +0x00, + +0x00, +0x06, +0x0c, +0x10, +0x00, +0x38, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x0c, +0x18, +0x20, +0x00, +0x3c, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x0c, +0x18, +0x20, +0x00, +0xee, +0x66, +0x66, +0x66, +0x66, +0x66, +0x67, +0x3a, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x32, +0x4c, +0x00, +0x5c, +0xf6, +0x66, +0x66, +0x66, +0x66, +0x66, +0xf7, +0x00, +0x00, +0x00, + +0x32, +0x4c, +0x00, +0xe7, +0x72, +0x52, +0x5a, +0x4a, +0x4e, +0x46, +0x46, +0x42, +0xe2, +0x00, +0x00, +0x00, + +0x00, +0x78, +0x8c, +0x0c, +0x3c, +0xcc, +0xcc, +0xcd, +0x76, +0x00, +0xfe, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x3c, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3c, +0x00, +0x7e, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x30, +0x30, +0x00, +0x30, +0x10, +0x10, +0x20, +0x40, +0xc0, +0xc6, +0xc2, +0x7c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xfe, +0xc0, +0xc0, +0xc0, +0xc0, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xfe, +0x06, +0x06, +0x06, +0x06, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x20, +0xe0, +0x63, +0x66, +0xfc, +0x18, +0x30, +0x60, +0xce, +0x93, +0x06, +0x0c, +0x1f, +0x00, +0x00, + +0x00, +0x20, +0xe0, +0x63, +0x66, +0xfc, +0x18, +0x30, +0x64, +0xc8, +0x96, +0x3f, +0x06, +0x06, +0x00, +0x00, + +0x00, +0x18, +0x18, +0x00, +0x08, +0x18, +0x18, +0x18, +0x3c, +0x3c, +0x3c, +0x3c, +0x18, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x36, +0x6c, +0xd8, +0xd8, +0x6c, +0x36, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0xd8, +0x6c, +0x36, +0x36, +0x6c, +0xd8, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x82, +0x10, +0x82, +0x10, +0x82, +0x10, +0x82, +0x10, +0x82, +0x10, +0x82, +0x10, +0x82, +0x10, +0x82, +0x10, + +0x00, +0x95, +0x00, +0xa9, +0x00, +0x95, +0x00, +0xa9, +0x00, +0x95, +0x00, +0xa9, +0x00, +0x95, +0x00, +0xa9, + +0x92, +0x49, +0x92, +0x49, +0x92, +0x49, +0x92, +0x49, +0x92, +0x49, +0x92, +0x49, +0x92, +0x49, +0x92, +0x49, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xf8, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xf8, +0x18, +0x18, +0xf8, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xe6, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xfe, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xf8, +0x18, +0x18, +0xf8, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xe6, +0x06, +0x06, +0xe6, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xfe, +0x06, +0x06, +0xe6, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xe6, +0x06, +0x06, +0xfe, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xfe, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xf8, +0x18, +0x18, +0xf8, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xf8, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1f, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xff, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1f, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xff, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1f, +0x18, +0x18, +0x1f, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x67, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x67, +0x60, +0x60, +0x7f, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x7f, +0x60, +0x60, +0x67, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xe7, +0x00, +0x00, +0xff, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0x00, +0x00, +0xe7, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x67, +0x60, +0x60, +0x67, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0x00, +0x00, +0xff, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xe7, +0x00, +0x00, +0xe7, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xff, +0x00, +0x00, +0xff, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xff, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0x00, +0x00, +0xff, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x7f, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1f, +0x18, +0x18, +0x1f, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x1f, +0x18, +0x18, +0x1f, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x7f, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xff, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xff, +0x00, +0x00, +0xff, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xf8, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x1f, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, + +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, + +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, + +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x77, +0xcc, +0xcc, +0xcc, +0xcc, +0xde, +0x73, +0x00, +0x00, +0x00, + +0x00, +0x7c, +0xc6, +0xc6, +0xc6, +0xc4, +0xc8, +0xc4, +0xc6, +0xc6, +0xc6, +0xc6, +0xdc, +0xc0, +0xc0, +0x00, + +0x00, +0xff, +0x61, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0xf0, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x01, +0x7e, +0xa4, +0x24, +0x2c, +0x6c, +0x6c, +0x6c, +0x48, +0x00, +0x00, +0x00, + +0x00, +0xff, +0xc1, +0x60, +0x30, +0x18, +0x0c, +0x18, +0x30, +0x60, +0xc0, +0xc1, +0xfe, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x7f, +0xc8, +0xc8, +0xc8, +0xc8, +0xc8, +0xc8, +0x70, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x22, +0x66, +0x66, +0x66, +0x66, +0x66, +0x7c, +0x60, +0x60, +0x60, +0xc0, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x76, +0xdc, +0x18, +0x18, +0x18, +0x18, +0x18, +0x10, +0x00, +0x00, +0x00, + +0x00, +0x38, +0x10, +0x7c, +0xd6, +0xd6, +0xd6, +0xd6, +0xd6, +0xd6, +0x7c, +0x10, +0x38, +0x00, +0x00, +0x00, + +0x00, +0x38, +0x6c, +0xc6, +0xc6, +0xc6, +0xfe, +0xc6, +0xc6, +0xc6, +0xc6, +0x6c, +0x38, +0x00, +0x00, +0x00, + +0x00, +0x3c, +0x66, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0x66, +0x24, +0x24, +0xa5, +0xe7, +0x00, +0x00, +0x00, + +0x00, +0x1e, +0x31, +0x30, +0x18, +0x0c, +0x3e, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x6e, +0xff, +0x99, +0x99, +0x99, +0x99, +0xff, +0x76, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x02, +0x04, +0x7c, +0xca, +0x92, +0xa6, +0x7c, +0x40, +0x80, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x1c, +0x30, +0x60, +0x60, +0x60, +0x7c, +0x60, +0x60, +0x60, +0x60, +0x30, +0x1c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x7c, +0xc6, +0xc6, +0xc6, +0xc6, +0xc6, +0xc6, +0xc6, +0xc6, +0xc6, +0xc6, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0xfe, +0x00, +0x00, +0x00, +0x7c, +0x00, +0x00, +0x00, +0xfe, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x18, +0x18, +0x7e, +0x18, +0x18, +0x00, +0x00, +0x7e, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x30, +0x18, +0x0c, +0x06, +0x0c, +0x18, +0x30, +0x00, +0x7e, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x0c, +0x18, +0x30, +0x60, +0x30, +0x18, +0x0c, +0x00, +0x7e, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x0e, +0x19, +0x1b, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xd8, +0x98, +0x70, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x18, +0x18, +0x00, +0x7e, +0x00, +0x18, +0x18, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x76, +0xdc, +0x00, +0x00, +0x76, +0xdc, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x38, +0x44, +0x44, +0x44, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x18, +0x18, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x18, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x07, +0x06, +0x06, +0x0c, +0x0c, +0x08, +0x98, +0xd0, +0xf0, +0x60, +0x20, +0x00, +0x00, +0x00, + +0x00, +0xcc, +0x76, +0x66, +0x66, +0x66, +0x66, +0xf7, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x70, +0x98, +0x18, +0x30, +0x60, +0x88, +0xf8, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x7c, +0x64, +0x64, +0x64, +0x64, +0x64, +0x7c, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +}; + + +const struct font_desc font_rl = { + RL_IDX, + "RomanLarge", + 8, + 16, + patterns, + -1 +}; diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c index 4fd07d9eca0..9be83bed195 100644 --- a/drivers/video/console/fonts.c +++ b/drivers/video/console/fonts.c @@ -64,6 +64,10 @@ static const struct font_desc *fonts[] = { #undef NO_FONTS &font_mini_4x6, #endif +#ifdef CONFIG_FONT_RL +#undef NO_FONTS + &font_rl, +#endif }; #define num_fonts (sizeof(fonts)/sizeof(*fonts)) diff --git a/include/linux/font.h b/include/linux/font.h index 53b129f07f6..8aac48c37f3 100644 --- a/include/linux/font.h +++ b/include/linux/font.h @@ -31,6 +31,7 @@ struct font_desc { #define SUN12x22_IDX 7 #define ACORN8x8_IDX 8 #define MINI4x6_IDX 9 +#define RL_IDX 10 extern const struct font_desc font_vga_8x8, font_vga_8x16, @@ -41,6 +42,7 @@ extern const struct font_desc font_vga_8x8, font_sun_8x16, font_sun_12x22, font_acorn_8x8, + font_rl, font_mini_4x6; /* Find a font with a specific name */ -- cgit v1.2.3 From 14c8102ffc9d08aa86fb08ed4bdb005768650e44 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 7 Nov 2005 01:00:53 -0800 Subject: [PATCH] fbdev: Rearrange mode database entries Rearrange mode database entries such that preferred timings are entered first, and less preferred timings are entered last. (Detailed, VESA, established/standard). Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/fbmon.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c index 442a52d1091..fc7965b6677 100644 --- a/drivers/video/fbmon.c +++ b/drivers/video/fbmon.c @@ -538,25 +538,12 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize) *dbsize = 0; - DPRINTK(" Supported VESA Modes\n"); - block = edid + ESTABLISHED_TIMING_1; - num += get_est_timing(block, &mode[num]); - - DPRINTK(" Standard Timings\n"); - block = edid + STD_TIMING_DESCRIPTIONS_START; - for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE) - num += get_std_timing(block, &mode[num]); - DPRINTK(" Detailed Timings\n"); block = edid + DETAILED_TIMING_DESCRIPTIONS_START; for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) { int first = 1; - if (block[0] == 0x00 && block[1] == 0x00) { - if (block[3] == 0xfa) { - num += get_dst_timing(block + 5, &mode[num]); - } - } else { + if (!(block[0] == 0x00 && block[1] == 0x00)) { get_detailed_timing(block, &mode[num]); if (first) { mode[num].flag |= FB_MODE_IS_FIRST; @@ -565,6 +552,21 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize) num++; } } + + DPRINTK(" Supported VESA Modes\n"); + block = edid + ESTABLISHED_TIMING_1; + num += get_est_timing(block, &mode[num]); + + DPRINTK(" Standard Timings\n"); + block = edid + STD_TIMING_DESCRIPTIONS_START; + for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE) + num += get_std_timing(block, &mode[num]); + + block = edid + DETAILED_TIMING_DESCRIPTIONS_START; + for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) { + if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa) + num += get_dst_timing(block + 5, &mode[num]); + } /* Yikes, EDID data is totally useless */ if (!num) { -- cgit v1.2.3 From 003cfc0c56977f1c3ce48ddfd2073b7c6d75a5d8 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 7 Nov 2005 01:00:54 -0800 Subject: [PATCH] fbdev: Add helper to get an appropriate initial mode Add new helper, fb_find_best_display(), which will search the modelist for the best mode for the attached display. This requires an EDID block that is converted to struct fb_monspecs and a private modelist. The search will be done in this manner: - if 1st detailed timing is preferred, use that - else if dimensions of the display are known, use that to estimate xres and - else if modelist has detailed timings, use the first detailed timing - else, use the very first entry from the modelist Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/modedb.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/fb.h | 2 ++ 2 files changed, 62 insertions(+) diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index aadef046ce7..1789a52d776 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c @@ -944,6 +944,66 @@ void fb_videomode_to_modelist(struct fb_videomode *modedb, int num, } } +struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs, + struct list_head *head) +{ + struct list_head *pos; + struct fb_modelist *modelist; + struct fb_videomode *m, *m1 = NULL, *md = NULL, *best = NULL; + int first = 0; + + if (!head->prev || !head->next || list_empty(head)) + goto finished; + + /* get the first detailed mode and the very first mode */ + list_for_each(pos, head) { + modelist = list_entry(pos, struct fb_modelist, list); + m = &modelist->mode; + + if (!first) { + m1 = m; + first = 1; + } + + if (m->flag & FB_MODE_IS_FIRST) { + md = m; + break; + } + } + + /* first detailed timing is preferred */ + if (specs->misc & FB_MISC_1ST_DETAIL) { + best = md; + goto finished; + } + + /* find best mode based on display width and height */ + if (specs->max_x && specs->max_y) { + struct fb_var_screeninfo var; + + memset(&var, 0, sizeof(struct fb_var_screeninfo)); + var.xres = (specs->max_x * 7200)/254; + var.yres = (specs->max_y * 7200)/254; + m = fb_find_best_mode(&var, head); + if (m) { + best = m; + goto finished; + } + } + + /* use first detailed mode */ + if (md) { + best = md; + goto finished; + } + + /* last resort, use the very first mode */ + best = m1; +finished: + return best; +} +EXPORT_SYMBOL(fb_find_best_display); + EXPORT_SYMBOL(fb_videomode_to_var); EXPORT_SYMBOL(fb_var_to_videomode); EXPORT_SYMBOL(fb_mode_is_equal); diff --git a/include/linux/fb.h b/include/linux/fb.h index 68a787914d8..e7ff98e395f 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -902,6 +902,8 @@ extern struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode, extern void fb_destroy_modelist(struct list_head *head); extern void fb_videomode_to_modelist(struct fb_videomode *modedb, int num, struct list_head *head); +extern struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs, + struct list_head *head); /* drivers/video/fbcmap.c */ extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp); -- cgit v1.2.3 From 5ee1ef96a0d5c49809c61bdbb30cdda88e1d23cf Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 7 Nov 2005 01:00:55 -0800 Subject: [PATCH] fbdev: Convert a few drivers to use the fb_find_best_display helper Convert i810fb, nvidiafb and savagefb to use the fb_find_best_display helper when searching for the initial video mode. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/i810/i810_main.c | 17 ++++------------- drivers/video/nvidia/nvidia.c | 18 +++--------------- drivers/video/savage/savagefb_driver.c | 21 ++++----------------- 3 files changed, 11 insertions(+), 45 deletions(-) diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 4175b2d8513..1d148c5a5a4 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c @@ -1871,27 +1871,18 @@ static void __devinit i810fb_find_init_mode(struct fb_info *info) fb_videomode_to_modelist(specs->modedb, specs->modedb_len, &info->modelist); if (specs->modedb != NULL) { - if (xres && yres) { - struct fb_videomode *m; + struct fb_videomode *m; + if (xres && yres) { if ((m = fb_find_best_mode(&var, &info->modelist))) { mode = *m; found = 1; } } - if (!found && specs->misc & FB_MISC_1ST_DETAIL) { - for (i = 0; i < specs->modedb_len; i++) { - if (specs->modedb[i].flag & FB_MODE_IS_FIRST) { - mode = specs->modedb[i]; - found = 1; - break; - } - } - } - if (!found) { - mode = specs->modedb[0]; + m = fb_find_best_display(&info->monspecs, &info->modelist); + mode = *m; found = 1; } diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index cbe165bb181..0b40a2a721c 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -1383,22 +1383,10 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info) fb_var_to_videomode(&modedb, &nvidiafb_default_var); if (specs->modedb != NULL) { - /* get preferred timing */ - if (specs->misc & FB_MISC_1ST_DETAIL) { - int i; - - for (i = 0; i < specs->modedb_len; i++) { - if (specs->modedb[i].flag & FB_MODE_IS_FIRST) { - modedb = specs->modedb[i]; - break; - } - } - } else { - /* otherwise, get first mode in database */ - modedb = specs->modedb[0]; - } + struct fb_videomode *modedb; - fb_videomode_to_var(&nvidiafb_default_var, &modedb); + modedb = fb_find_best_display(specs, &info->modelist); + fb_videomode_to_var(&nvidiafb_default_var, modedb); nvidiafb_default_var.bits_per_pixel = 8; } else if (par->fpWidth && par->fpHeight) { char buf[16]; diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index 06e989ba3d1..f0dfb35e319 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c @@ -2052,24 +2052,11 @@ static int __devinit savagefb_probe (struct pci_dev* dev, info->monspecs.modedb, info->monspecs.modedb_len, NULL, 8); } else if (info->monspecs.modedb != NULL) { - struct fb_monspecs *specs = &info->monspecs; - struct fb_videomode modedb; + struct fb_videomode *modedb; - if (info->monspecs.misc & FB_MISC_1ST_DETAIL) { - int i; - - for (i = 0; i < specs->modedb_len; i++) { - if (specs->modedb[i].flag & FB_MODE_IS_FIRST) { - modedb = specs->modedb[i]; - break; - } - } - } else { - /* otherwise, get first mode in database */ - modedb = specs->modedb[0]; - } - - savage_update_var(&info->var, &modedb); + modedb = fb_find_best_display(&info->monspecs, + &info->modelist); + savage_update_var(&info->var, modedb); } /* maximize virtual vertical length */ -- cgit v1.2.3 From 183dee0f02d878def016476afd7995bec8d5f3a6 Mon Sep 17 00:00:00 2001 From: Jake Moilanen Date: Mon, 7 Nov 2005 01:00:55 -0800 Subject: [PATCH] fbdev: ATI RN50 pci id Here's the PCI ID for the ATI RN50 chip. Signed-off-by: Jake Moilanen Signed-off-by: Benjamin Herrenschmidt Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/aty/ati_ids.h | 1 + drivers/video/aty/radeon_base.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/video/aty/ati_ids.h b/drivers/video/aty/ati_ids.h index 13321c689cf..39ab483fc25 100644 --- a/drivers/video/aty/ati_ids.h +++ b/drivers/video/aty/ati_ids.h @@ -150,6 +150,7 @@ #define PCI_CHIP_RV200_QX 0x5158 #define PCI_CHIP_RV100_QY 0x5159 #define PCI_CHIP_RV100_QZ 0x515A +#define PCI_CHIP_RN50 0x515E #define PCI_CHIP_RAGE128RE 0x5245 #define PCI_CHIP_RAGE128RF 0x5246 #define PCI_CHIP_RAGE128RG 0x5247 diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 29f5b2cdbb7..4f01ccc02aa 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -112,6 +112,7 @@ static struct pci_device_id radeonfb_pci_table[] = { /* Radeon VE/7000 */ CHIP_DEF(PCI_CHIP_RV100_QY, RV100, CHIP_HAS_CRTC2), CHIP_DEF(PCI_CHIP_RV100_QZ, RV100, CHIP_HAS_CRTC2), + CHIP_DEF(PCI_CHIP_RN50, RV100, CHIP_HAS_CRTC2), /* Radeon IGP320M (U1) */ CHIP_DEF(PCI_CHIP_RS100_4336, RS100, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY), /* Radeon IGP320 (A3) */ -- cgit v1.2.3 From b1e91fdf56930fd3bd11f0df26e686feabf65ebe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=E4l=E4?= Date: Mon, 7 Nov 2005 01:00:56 -0800 Subject: [PATCH] matroxfb: Remove an unused wait queue entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wait_event_event_interruptible() uses a private wait queue entry so there's no need for the caller to initialize one. Signed-off-by: Ville Syrjälä Signed-off-by: Petr Vandrovec Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/matrox/matroxfb_base.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index e02da41f1b2..5f2df1725e6 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -264,7 +264,6 @@ static void matroxfb_disable_irq(WPMINFO2) { } int matroxfb_wait_for_sync(WPMINFO u_int32_t crtc) { - wait_queue_t __wait; struct matrox_vsync *vs; unsigned int cnt; int ret; @@ -286,7 +285,6 @@ int matroxfb_wait_for_sync(WPMINFO u_int32_t crtc) { if (ret) { return ret; } - init_waitqueue_entry(&__wait, current); cnt = vs->cnt; ret = wait_event_interruptible_timeout(vs->wait, cnt != vs->cnt, HZ/10); -- cgit v1.2.3 From 63921fbfbd87ec745e65d2e9aecdfdc9a4ce73f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=E4l=E4?= Date: Mon, 7 Nov 2005 01:00:57 -0800 Subject: [PATCH] matroxfb: Add support for Mystique AGP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add new entries for Mystique AGP with the PCI ID 0x051e. I don't actually have such boards but according to google they do exist. Curiosly X.Org doesn't recognize that PCI ID. And what's even more interesting is that Matrox's own Windows drivers don't recognize it either. After going through about a dozen different versions I did find one older driver that does list this particular ID. It is also listed in the pci.ids file. I'm not sure if non-220 AGP chips exist. I left the chip revision check intact for AGP chips nonetheless. Signed-off-by: Ville Syrjälä Signed-off-by: Petr Vandrovec Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/matrox/matroxfb_base.c | 14 ++++++++++++++ include/linux/pci_ids.h | 1 + 2 files changed, 15 insertions(+) diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 5f2df1725e6..1734438f7d7 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -1428,6 +1428,20 @@ static struct board { MGA_1164, &vbMystique, "Mystique 220 (PCI)"}, + {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS_AGP, 0x02, + 0, 0, + DEVF_VIDEO64BIT | DEVF_CROSS4MB, + 180000, + MGA_1064, + &vbMystique, + "Mystique (AGP)"}, + {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS_AGP, 0xFF, + 0, 0, + DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB, + 220000, + MGA_1164, + &vbMystique, + "Mystique 220 (AGP)"}, #endif #ifdef CONFIG_FB_MATROX_G {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_MM, 0xFF, diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 88de3f8ce1a..cd62a39ce06 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -519,6 +519,7 @@ #define PCI_DEVICE_ID_MATROX_MIL 0x0519 #define PCI_DEVICE_ID_MATROX_MYS 0x051A #define PCI_DEVICE_ID_MATROX_MIL_2 0x051b +#define PCI_DEVICE_ID_MATROX_MYS_AGP 0x051e #define PCI_DEVICE_ID_MATROX_MIL_2_AGP 0x051f #define PCI_DEVICE_ID_MATROX_MGA_IMP 0x0d10 #define PCI_DEVICE_ID_MATROX_G100_MM 0x1000 -- cgit v1.2.3 From 6c12f30554f29069afd485ecd05a1d54c8aece9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=E4l=E4?= Date: Mon, 7 Nov 2005 01:00:58 -0800 Subject: [PATCH] matroxfb: Use CACHEFLUSH on all chips MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the CACHEFLUSH register on all chip types. The register is listed in all other specs except 2064W. However I have verified that the register does work on a 2064W despite being marked reserved in the specs. There were no noticeable side effects after writing to the register. Signed-off-by: Ville Syrjälä Signed-off-by: Petr Vandrovec Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/matrox/matroxfb_DAC1064.c | 2 -- drivers/video/matrox/matroxfb_base.c | 9 ++------- drivers/video/matrox/matroxfb_base.h | 5 ----- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c index 149680f8bcf..94ba81543cd 100644 --- a/drivers/video/matrox/matroxfb_DAC1064.c +++ b/drivers/video/matrox/matroxfb_DAC1064.c @@ -657,7 +657,6 @@ static int MGA1064_preinit(WPMINFO2) { /* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */ ACCESS_FBINFO(capable.text) = 1; ACCESS_FBINFO(capable.vxres) = vxres_mystique; - ACCESS_FBINFO(features.accel.has_cacheflush) = 1; ACCESS_FBINFO(outputs[0]).output = &m1064; ACCESS_FBINFO(outputs[0]).src = ACCESS_FBINFO(outputs[0]).default_src; @@ -842,7 +841,6 @@ static int MGAG100_preinit(WPMINFO2) { /* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */ ACCESS_FBINFO(capable.text) = 1; ACCESS_FBINFO(capable.vxres) = vxres_g100; - ACCESS_FBINFO(features.accel.has_cacheflush) = 1; ACCESS_FBINFO(capable.plnwt) = ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100 ? ACCESS_FBINFO(devflags.sgram) : 1; diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 1734438f7d7..a780bb30ffc 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -1283,7 +1283,7 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi vaddr_t vm; unsigned int offs; unsigned int offs2; - unsigned char store, orig; + unsigned char orig; unsigned char bytes[32]; unsigned char* tmp; @@ -1299,16 +1299,12 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi orig = mga_inb(M_EXTVGA_DATA); mga_outb(M_EXTVGA_DATA, orig | 0x80); - store = mga_readb(vm, 0x1234); tmp = bytes; for (offs = 0x100000; offs < maxSize; offs += 0x200000) *tmp++ = mga_readb(vm, offs); for (offs = 0x100000; offs < maxSize; offs += 0x200000) mga_writeb(vm, offs, 0x02); - if (ACCESS_FBINFO(features.accel.has_cacheflush)) - mga_outb(M_CACHEFLUSH, 0x00); - else - mga_writeb(vm, 0x1234, 0x99); + mga_outb(M_CACHEFLUSH, 0x00); for (offs = 0x100000; offs < maxSize; offs += 0x200000) { if (mga_readb(vm, offs) != 0x02) break; @@ -1319,7 +1315,6 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi tmp = bytes; for (offs2 = 0x100000; offs2 < maxSize; offs2 += 0x200000) mga_writeb(vm, offs2, *tmp++); - mga_writeb(vm, 0x1234, store); mga_outb(M_EXTVGA_INDEX, 0x03); mga_outb(M_EXTVGA_DATA, orig); diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h index 85a0b255845..a8c47ad2cdb 100644 --- a/drivers/video/matrox/matroxfb_base.h +++ b/drivers/video/matrox/matroxfb_base.h @@ -272,10 +272,6 @@ struct matrox_DAC1064_features { u_int8_t xmiscctrl; }; -struct matrox_accel_features { - int has_cacheflush; -}; - /* current hardware status */ struct mavenregs { u_int8_t regs[256]; @@ -440,7 +436,6 @@ struct matrox_fb_info { struct { struct matrox_pll_features pll; struct matrox_DAC1064_features DAC1064; - struct matrox_accel_features accel; } features; struct { spinlock_t DAC; -- cgit v1.2.3 From 5ea8d9d0384761251db10ecce7618f84b67d50d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=E4l=E4?= Date: Mon, 7 Nov 2005 01:00:59 -0800 Subject: [PATCH] matroxfb: Kill a useless message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No point in spamming the logs with a message about xres rounding. Signed-off-by: Ville Syrjälä Signed-off-by: Petr Vandrovec Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/matrox/matroxfb_base.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index a780bb30ffc..1e74f4cca53 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -498,10 +498,6 @@ static int matroxfb_pitch_adjust(CPMINFO int xres, int bpp) { } else { xres_new = matroxfb_test_and_set_rounding(PMINFO xres, bpp); } - if (!xres_new) return 0; - if (xres != xres_new) { - printk(KERN_INFO "matroxfb: cannot set xres to %d, rounded up to %d\n", xres, xres_new); - } return xres_new; } -- cgit v1.2.3 From f73195ad7e68fb4e546350222d31e19ebc1d3578 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=E4l=E4?= Date: Mon, 7 Nov 2005 01:01:00 -0800 Subject: [PATCH] matroxfb: Set maxhipri to 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current init code sets hiprilvl to 0 and maxhipri to 5. According to the specs those values are illegal on both G200 and G400. It also causes distortions on the TV-out at least when CRTC2 is in YUV mode as is the case with DirectFB. This patch resets both values to 0. Signed-off-by: Ville Syrjälä Signed-off-by: Petr Vandrovec Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/matrox/matroxfb_DAC1064.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c index 94ba81543cd..0fbd9b5149f 100644 --- a/drivers/video/matrox/matroxfb_DAC1064.c +++ b/drivers/video/matrox/matroxfb_DAC1064.c @@ -978,7 +978,7 @@ static void MGAG100_reset(WPMINFO2) { hw->MXoptionReg |= 0x40; /* FIXME... */ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); } - mga_setr(M_EXTVGA_INDEX, 0x06, 0x50); + mga_setr(M_EXTVGA_INDEX, 0x06, 0x00); } } if (ACCESS_FBINFO(devflags.g450dac)) { -- cgit v1.2.3 From 411f11405c99141233970c98d23d6a5ec88a4f7f Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Mon, 7 Nov 2005 01:01:01 -0800 Subject: [PATCH] Fix dm-snapshot tutorial in Documentation I've recently added this documentation, Alasdair gave some corrections, and here are some further corrections on top of his work (partly style issue, partly a technical error due to different past experience, partly a note which I've added - i.e. transient snapshots are lighter). Cc: Alasdair G Kergon Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/device-mapper/snapshot.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/device-mapper/snapshot.txt b/Documentation/device-mapper/snapshot.txt index dca274ff400..a5009c8300f 100644 --- a/Documentation/device-mapper/snapshot.txt +++ b/Documentation/device-mapper/snapshot.txt @@ -19,7 +19,6 @@ There are two dm targets available: snapshot and snapshot-origin. *) snapshot-origin which will normally have one or more snapshots based on it. -You must create the snapshot-origin device before you can create snapshots. Reads will be mapped directly to the backing device. For each write, the original data will be saved in the of each snapshot to keep its visible content unchanged, at least until the fills up. @@ -27,7 +26,7 @@ its visible content unchanged, at least until the fills up. *) snapshot -A snapshot is created of the block device. Changed chunks of +A snapshot of the block device is created. Changed chunks of sectors will be stored on the . Writes will only go to the . Reads will come from the or from for unchanged data. will often be @@ -37,6 +36,8 @@ the amount of free space and expand the before it fills up. is P (Persistent) or N (Not persistent - will not survive after reboot). +The difference is that for transient snapshots less metadata must be +saved on disk - they can be kept in memory by the kernel. How this is used by LVM2 -- cgit v1.2.3 From 55032eacdb3acf54f5ba2e4dd9205db2c5c0bce2 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 7 Nov 2005 01:01:02 -0800 Subject: [PATCH] Documentation/sparse.txt: mention CF=-Wbitwise Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/sparse.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/sparse.txt b/Documentation/sparse.txt index 1829009db77..3f1c5464b1c 100644 --- a/Documentation/sparse.txt +++ b/Documentation/sparse.txt @@ -41,9 +41,9 @@ sure that bitwise types don't get mixed up (little-endian vs big-endian vs cpu-endian vs whatever), and there the constant "0" really _is_ special. -Modify top-level Makefile to say +Use -CHECK = sparse -Wbitwise + make C=[12] CF=-Wbitwise or you don't get any checking at all. -- cgit v1.2.3 From 62a07e6e9e93eda88a6eeb5009fc46d44ca60281 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 7 Nov 2005 01:01:03 -0800 Subject: [PATCH] ksymoops related docs update Update ksymoops related documentation to reflect current 2.6 reality. Signed-off-by: Jesper Juhl Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/Changes | 11 ++++++++--- Documentation/filesystems/devfs/README | 5 ----- Documentation/networking/decnet.txt | 2 -- Documentation/oops-tracing.txt | 2 +- Documentation/video4linux/bttv/README.freeze | 6 +++--- 5 files changed, 12 insertions(+), 14 deletions(-) diff --git a/Documentation/Changes b/Documentation/Changes index 783ddc3ce4e..86b86399d61 100644 --- a/Documentation/Changes +++ b/Documentation/Changes @@ -139,9 +139,14 @@ You'll probably want to upgrade. Ksymoops -------- -If the unthinkable happens and your kernel oopses, you'll need a 2.4 -version of ksymoops to decode the report; see REPORTING-BUGS in the -root of the Linux source for more information. +If the unthinkable happens and your kernel oopses, you may need the +ksymoops tool to decode it, but in most cases you don't. +In the 2.6 kernel it is generally preferred to build the kernel with +CONFIG_KALLSYMS so that it produces readable dumps that can be used as-is +(this also produces better output than ksymoops). +If for some reason your kernel is not build with CONFIG_KALLSYMS and +you have no way to rebuild and reproduce the Oops with that option, then +you can still decode that Oops with ksymoops. Module-Init-Tools ----------------- diff --git a/Documentation/filesystems/devfs/README b/Documentation/filesystems/devfs/README index 54366ecc241..aabfba24bc2 100644 --- a/Documentation/filesystems/devfs/README +++ b/Documentation/filesystems/devfs/README @@ -1812,11 +1812,6 @@ it may overflow the messages buffer, but try to get as much of it as you can -if you get an Oops, run ksymoops to decode it so that the -names of the offending functions are provided. A non-decoded Oops is -pretty useless - - send a copy of your devfsd configuration file(s) send the bug report to me first. diff --git a/Documentation/networking/decnet.txt b/Documentation/networking/decnet.txt index c6bd25f5d61..e6c39c5831f 100644 --- a/Documentation/networking/decnet.txt +++ b/Documentation/networking/decnet.txt @@ -176,8 +176,6 @@ information (_most_ of which _is_ _essential_) includes: - Which client caused the problem ? - How much data was being transferred ? - Was the network congested ? - - If there was a kernel panic, please run the output through ksymoops - before sending it to me, otherwise its _useless_. - How can the problem be reproduced ? - Can you use tcpdump to get a trace ? (N.B. Most (all?) versions of tcpdump don't understand how to dump DECnet properly, so including diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt index 66eaaab7773..c563842ed80 100644 --- a/Documentation/oops-tracing.txt +++ b/Documentation/oops-tracing.txt @@ -1,6 +1,6 @@ NOTE: ksymoops is useless on 2.6. Please use the Oops in its original format (from dmesg, etc). Ignore any references in this or other docs to "decoding -the Oops" or "running it through ksymoops". If you post an Oops fron 2.6 that +the Oops" or "running it through ksymoops". If you post an Oops from 2.6 that has been run through ksymoops, people will just tell you to repost it. Quick Summary diff --git a/Documentation/video4linux/bttv/README.freeze b/Documentation/video4linux/bttv/README.freeze index 51f8d4379a9..4259dccc828 100644 --- a/Documentation/video4linux/bttv/README.freeze +++ b/Documentation/video4linux/bttv/README.freeze @@ -27,9 +27,9 @@ information out of a register+stack dump printed by the kernel on protection faults (so-called "kernel oops"). If you run into some kind of deadlock, you can try to dump a call trace -for each process using sysrq-t (see Documentation/sysrq.txt). ksymoops -will translate these dumps into kernel symbols too. This way it is -possible to figure where *exactly* some process in "D" state is stuck. +for each process using sysrq-t (see Documentation/sysrq.txt). +This way it is possible to figure where *exactly* some process in "D" +state is stuck. I've seen reports that bttv 0.7.x crashes whereas 0.8.x works rock solid for some people. Thus probably a small buglet left somewhere in bttv -- cgit v1.2.3 From 2500e7abc8f606d87b2590f205dac080640b6b04 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 7 Nov 2005 01:01:03 -0800 Subject: [PATCH] Doc/MSI-HOWTO: cleanups Clean up typos, kernel function interfaces, acronyms, add whitespace, improve readability. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/MSI-HOWTO.txt | 174 +++++++++++++++++++++++--------------------- 1 file changed, 91 insertions(+), 83 deletions(-) diff --git a/Documentation/MSI-HOWTO.txt b/Documentation/MSI-HOWTO.txt index 63edc5f847c..3ec6c720b01 100644 --- a/Documentation/MSI-HOWTO.txt +++ b/Documentation/MSI-HOWTO.txt @@ -10,14 +10,22 @@ This guide describes the basics of Message Signaled Interrupts (MSI), the advantages of using MSI over traditional interrupt mechanisms, and how to enable your driver to use MSI or MSI-X. Also included is -a Frequently Asked Questions. +a Frequently Asked Questions (FAQ) section. + +1.1 Terminology + +PCI devices can be single-function or multi-function. In either case, +when this text talks about enabling or disabling MSI on a "device +function," it is referring to one specific PCI device and function and +not to all functions on a PCI device (unless the PCI device has only +one function). 2. Copyright 2003 Intel Corporation 3. What is MSI/MSI-X? Message Signaled Interrupt (MSI), as described in the PCI Local Bus -Specification Revision 2.3 or latest, is an optional feature, and a +Specification Revision 2.3 or later, is an optional feature, and a required feature for PCI Express devices. MSI enables a device function to request service by sending an Inbound Memory Write on its PCI bus to the FSB as a Message Signal Interrupt transaction. Because MSI is @@ -27,7 +35,7 @@ supported. A PCI device that supports MSI must also support pin IRQ assertion interrupt mechanism to provide backward compatibility for systems that -do not support MSI. In Systems, which support MSI, the bus driver is +do not support MSI. In systems which support MSI, the bus driver is responsible for initializing the message address and message data of the device function's MSI/MSI-X capability structure during device initial configuration. @@ -61,17 +69,17 @@ over the MSI capability structure as described below. - MSI and MSI-X both support per-vector masking. Per-vector masking is an optional extension of MSI but a required - feature for MSI-X. Per-vector masking provides the kernel - the ability to mask/unmask MSI when servicing its software - interrupt service routing handler. If per-vector masking is + feature for MSI-X. Per-vector masking provides the kernel the + ability to mask/unmask a single MSI while running its + interrupt service routine. If per-vector masking is not supported, then the device driver should provide the hardware/software synchronization to ensure that the device generates MSI when the driver wants it to do so. 4. Why use MSI? -As a benefit the simplification of board design, MSI allows board -designers to remove out of band interrupt routing. MSI is another +As a benefit to the simplification of board design, MSI allows board +designers to remove out-of-band interrupt routing. MSI is another step towards a legacy-free environment. Due to increasing pressure on chipset and processor packages to @@ -87,7 +95,7 @@ support. As a result, the PCI Express technology requires MSI support for better interrupt performance. Using MSI enables the device functions to support two or more -vectors, which can be configured to target different CPU's to +vectors, which can be configured to target different CPUs to increase scalability. 5. Configuring a driver to use MSI/MSI-X @@ -119,13 +127,13 @@ pci_enable_msi() explicitly. int pci_enable_msi(struct pci_dev *dev) -With this new API, any existing device driver, which like to have -MSI enabled on its device function, must call this API to enable MSI +With this new API, a device driver that wants to have MSI +enabled on its device function must call this API to enable MSI. A successful call will initialize the MSI capability structure with ONE vector, regardless of whether a device function is capable of supporting multiple messages. This vector replaces the -pre-assigned dev->irq with a new MSI vector. To avoid the conflict -of new assigned vector with existing pre-assigned vector requires +pre-assigned dev->irq with a new MSI vector. To avoid a conflict +of the new assigned vector with existing pre-assigned vector requires a device driver to call this API before calling request_irq(). 5.2.2 API pci_disable_msi @@ -137,14 +145,14 @@ when a device driver is unloading. This API restores dev->irq with the pre-assigned IOAPIC vector and switches a device's interrupt mode to PCI pin-irq assertion/INTx emulation mode. -Note that a device driver should always call free_irq() on MSI vector -it has done request_irq() on before calling this API. Failure to do -so results a BUG_ON() and a device will be left with MSI enabled and +Note that a device driver should always call free_irq() on the MSI vector +that it has done request_irq() on before calling this API. Failure to do +so results in a BUG_ON() and a device will be left with MSI enabled and leaks its vector. 5.2.3 MSI mode vs. legacy mode diagram -The below diagram shows the events, which switches the interrupt +The below diagram shows the events which switch the interrupt mode on the MSI-capable device function between MSI mode and PIN-IRQ assertion mode. @@ -155,9 +163,9 @@ PIN-IRQ assertion mode. ------------ pci_disable_msi ------------------------ -Figure 1.0 MSI Mode vs. Legacy Mode +Figure 1. MSI Mode vs. Legacy Mode -In Figure 1.0, a device operates by default in legacy mode. Legacy +In Figure 1, a device operates by default in legacy mode. Legacy in this context means PCI pin-irq assertion or PCI-Express INTx emulation. A successful MSI request (using pci_enable_msi()) switches a device's interrupt mode to MSI mode. A pre-assigned IOAPIC vector @@ -166,11 +174,11 @@ assigned MSI vector will replace dev->irq. To return back to its default mode, a device driver should always call pci_disable_msi() to undo the effect of pci_enable_msi(). Note that a -device driver should always call free_irq() on MSI vector it has done -request_irq() on before calling pci_disable_msi(). Failure to do so -results a BUG_ON() and a device will be left with MSI enabled and +device driver should always call free_irq() on the MSI vector it has +done request_irq() on before calling pci_disable_msi(). Failure to do +so results in a BUG_ON() and a device will be left with MSI enabled and leaks its vector. Otherwise, the PCI subsystem restores a device's -dev->irq with a pre-assigned IOAPIC vector and marks released +dev->irq with a pre-assigned IOAPIC vector and marks the released MSI vector as unused. Once being marked as unused, there is no guarantee that the PCI @@ -178,8 +186,8 @@ subsystem will reserve this MSI vector for a device. Depending on the availability of current PCI vector resources and the number of MSI/MSI-X requests from other drivers, this MSI may be re-assigned. -For the case where the PCI subsystem re-assigned this MSI vector -another driver, a request to switching back to MSI mode may result +For the case where the PCI subsystem re-assigns this MSI vector to +another driver, a request to switch back to MSI mode may result in being assigned a different MSI vector or a failure if no more vectors are available. @@ -208,12 +216,12 @@ Unlike the function pci_enable_msi(), the function pci_enable_msix() does not replace the pre-assigned IOAPIC dev->irq with a new MSI vector because the PCI subsystem writes the 1:1 vector-to-entry mapping into the field vector of each element contained in a second argument. -Note that the pre-assigned IO-APIC dev->irq is valid only if the device -operates in PIN-IRQ assertion mode. In MSI-X mode, any attempt of +Note that the pre-assigned IOAPIC dev->irq is valid only if the device +operates in PIN-IRQ assertion mode. In MSI-X mode, any attempt at using dev->irq by the device driver to request for interrupt service may result unpredictabe behavior. -For each MSI-X vector granted, a device driver is responsible to call +For each MSI-X vector granted, a device driver is responsible for calling other functions like request_irq(), enable_irq(), etc. to enable this vector with its corresponding interrupt service handler. It is a device driver's choice to assign all vectors with the same @@ -224,13 +232,13 @@ service handler. The PCI 3.0 specification has implementation notes that MMIO address space for a device's MSI-X structure should be isolated so that the -software system can set different page for controlling accesses to -the MSI-X structure. The implementation of MSI patch requires the PCI +software system can set different pages for controlling accesses to the +MSI-X structure. The implementation of MSI support requires the PCI subsystem, not a device driver, to maintain full control of the MSI-X -table/MSI-X PBA and MMIO address space of the MSI-X table/MSI-X PBA. -A device driver is prohibited from requesting the MMIO address space -of the MSI-X table/MSI-X PBA. Otherwise, the PCI subsystem will fail -enabling MSI-X on its hardware device when it calls the function +table/MSI-X PBA (Pending Bit Array) and MMIO address space of the MSI-X +table/MSI-X PBA. A device driver is prohibited from requesting the MMIO +address space of the MSI-X table/MSI-X PBA. Otherwise, the PCI subsystem +will fail enabling MSI-X on its hardware device when it calls the function pci_enable_msix(). 5.3.2 Handling MSI-X allocation @@ -274,9 +282,9 @@ For the case where fewer MSI-X vectors are allocated to a function than requested, the function pci_enable_msix() will return the maximum number of MSI-X vectors available to the caller. A device driver may re-send its request with fewer or equal vectors indicated -in a return. For example, if a device driver requests 5 vectors, but -the number of available vectors is 3 vectors, a value of 3 will be a -return as a result of pci_enable_msix() call. A function could be +in the return. For example, if a device driver requests 5 vectors, but +the number of available vectors is 3 vectors, a value of 3 will be +returned as a result of pci_enable_msix() call. A function could be designed for its driver to use only 3 MSI-X table entries as different combinations as ABC--, A-B-C, A--CB, etc. Note that this patch does not support multiple entries with the same vector. Such @@ -285,49 +293,46 @@ as ABBCC, AABCC, BCCBA, etc will result as a failure by the function pci_enable_msix(). Below are the reasons why supporting multiple entries with the same vector is an undesirable solution. - - The PCI subsystem can not determine which entry, which - generated the message, to mask/unmask MSI while handling + - The PCI subsystem cannot determine the entry that + generated the message to mask/unmask MSI while handling software driver ISR. Attempting to walk through all MSI-X table entries (2048 max) to mask/unmask any match vector is an undesirable solution. - - Walk through all MSI-X table entries (2048 max) to handle + - Walking through all MSI-X table entries (2048 max) to handle SMP affinity of any match vector is an undesirable solution. 5.3.4 API pci_enable_msix -int pci_enable_msix(struct pci_dev *dev, u32 *entries, int nvec) +int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec) This API enables a device driver to request the PCI subsystem -for enabling MSI-X messages on its hardware device. Depending on +to enable MSI-X messages on its hardware device. Depending on the availability of PCI vectors resources, the PCI subsystem enables -either all or nothing. +either all or none of the requested vectors. -Argument dev points to the device (pci_dev) structure. +Argument 'dev' points to the device (pci_dev) structure. -Argument entries is a pointer of unsigned integer type. The number of -elements is indicated in argument nvec. The content of each element -will be mapped to the following struct defined in /driver/pci/msi.h. +Argument 'entries' is a pointer to an array of msix_entry structs. +The number of entries is indicated in argument 'nvec'. +struct msix_entry is defined in /driver/pci/msi.h: struct msix_entry { u16 vector; /* kernel uses to write alloc vector */ u16 entry; /* driver uses to specify entry */ }; -A device driver is responsible for initializing the field entry of -each element with unique entry supported by MSI-X table. Otherwise, +A device driver is responsible for initializing the field 'entry' of +each element with a unique entry supported by MSI-X table. Otherwise, -EINVAL will be returned as a result. A successful return of zero -indicates the PCI subsystem completes initializing each of requested +indicates the PCI subsystem completed initializing each of the requested entries of the MSI-X table with message address and message data. Last but not least, the PCI subsystem will write the 1:1 -vector-to-entry mapping into the field vector of each element. A -device driver is responsible of keeping track of allocated MSI-X +vector-to-entry mapping into the field 'vector' of each element. A +device driver is responsible for keeping track of allocated MSI-X vectors in its internal data structure. -Argument nvec is an integer indicating the number of messages -requested. - -A return of zero indicates that the number of MSI-X vectors is +A return of zero indicates that the number of MSI-X vectors was successfully allocated. A return of greater than zero indicates MSI-X vector shortage. Or a return of less than zero indicates a failure. This failure may be a result of duplicate entries @@ -341,12 +346,12 @@ void pci_disable_msix(struct pci_dev *dev) This API should always be used to undo the effect of pci_enable_msix() when a device driver is unloading. Note that a device driver should always call free_irq() on all MSI-X vectors it has done request_irq() -on before calling this API. Failure to do so results a BUG_ON() and +on before calling this API. Failure to do so results in a BUG_ON() and a device will be left with MSI-X enabled and leaks its vectors. 5.3.6 MSI-X mode vs. legacy mode diagram -The below diagram shows the events, which switches the interrupt +The below diagram shows the events which switch the interrupt mode on the MSI-X capable device function between MSI-X mode and PIN-IRQ assertion mode (legacy). @@ -356,22 +361,22 @@ PIN-IRQ assertion mode (legacy). | | ===============> | | ------------ pci_disable_msix ------------------------ -Figure 2.0 MSI-X Mode vs. Legacy Mode +Figure 2. MSI-X Mode vs. Legacy Mode -In Figure 2.0, a device operates by default in legacy mode. A +In Figure 2, a device operates by default in legacy mode. A successful MSI-X request (using pci_enable_msix()) switches a device's interrupt mode to MSI-X mode. A pre-assigned IOAPIC vector stored in dev->irq will be saved by the PCI subsystem; however, unlike MSI mode, the PCI subsystem will not replace dev->irq with assigned MSI-X vector because the PCI subsystem already writes the 1:1 -vector-to-entry mapping into the field vector of each element +vector-to-entry mapping into the field 'vector' of each element specified in second argument. To return back to its default mode, a device driver should always call pci_disable_msix() to undo the effect of pci_enable_msix(). Note that a device driver should always call free_irq() on all MSI-X vectors it has done request_irq() on before calling pci_disable_msix(). Failure -to do so results a BUG_ON() and a device will be left with MSI-X +to do so results in a BUG_ON() and a device will be left with MSI-X enabled and leaks its vectors. Otherwise, the PCI subsystem switches a device function's interrupt mode from MSI-X mode to legacy mode and marks all allocated MSI-X vectors as unused. @@ -383,53 +388,56 @@ MSI/MSI-X requests from other drivers, these MSI-X vectors may be re-assigned. For the case where the PCI subsystem re-assigned these MSI-X vectors -to other driver, a request to switching back to MSI-X mode may result +to other drivers, a request to switch back to MSI-X mode may result being assigned with another set of MSI-X vectors or a failure if no more vectors are available. -5.4 Handling function implementng both MSI and MSI-X capabilities +5.4 Handling function implementing both MSI and MSI-X capabilities For the case where a function implements both MSI and MSI-X capabilities, the PCI subsystem enables a device to run either in MSI mode or MSI-X mode but not both. A device driver determines whether it wants MSI or MSI-X enabled on its hardware device. Once a device -driver requests for MSI, for example, it is prohibited to request for +driver requests for MSI, for example, it is prohibited from requesting MSI-X; in other words, a device driver is not permitted to ping-pong between MSI mod MSI-X mode during a run-time. 5.5 Hardware requirements for MSI/MSI-X support + MSI/MSI-X support requires support from both system hardware and individual hardware device functions. 5.5.1 System hardware support + Since the target of MSI address is the local APIC CPU, enabling -MSI/MSI-X support in Linux kernel is dependent on whether existing -system hardware supports local APIC. Users should verify their -system whether it runs when CONFIG_X86_LOCAL_APIC=y. +MSI/MSI-X support in the Linux kernel is dependent on whether existing +system hardware supports local APIC. Users should verify that their +system supports local APIC operation by testing that it runs when +CONFIG_X86_LOCAL_APIC=y. In SMP environment, CONFIG_X86_LOCAL_APIC is automatically set; however, in UP environment, users must manually set CONFIG_X86_LOCAL_APIC. Once CONFIG_X86_LOCAL_APIC=y, setting -CONFIG_PCI_MSI enables the VECTOR based scheme and -the option for MSI-capable device drivers to selectively enable -MSI/MSI-X. +CONFIG_PCI_MSI enables the VECTOR based scheme and the option for +MSI-capable device drivers to selectively enable MSI/MSI-X. Note that CONFIG_X86_IO_APIC setting is irrelevant because MSI/MSI-X vector is allocated new during runtime and MSI/MSI-X support does not depend on BIOS support. This key independency enables MSI/MSI-X -support on future IOxAPIC free platform. +support on future IOxAPIC free platforms. 5.5.2 Device hardware support + The hardware device function supports MSI by indicating the MSI/MSI-X capability structure on its PCI capability list. By default, this capability structure will not be initialized by the kernel to enable MSI during the system boot. In other words, the device function is running on its default pin assertion mode. Note that in many cases the hardware supporting MSI have bugs, -which may result in system hang. The software driver of specific -MSI-capable hardware is responsible for whether calling +which may result in system hangs. The software driver of specific +MSI-capable hardware is responsible for deciding whether to call pci_enable_msi or not. A return of zero indicates the kernel -successfully initializes the MSI/MSI-X capability structure of the +successfully initialized the MSI/MSI-X capability structure of the device function. The device function is now running on MSI/MSI-X mode. 5.6 How to tell whether MSI/MSI-X is enabled on device function @@ -439,10 +447,10 @@ pci_enable_msi()/pci_enable_msix() indicates to a device driver that its device function is initialized successfully and ready to run in MSI/MSI-X mode. -At the user level, users can use command 'cat /proc/interrupts' -to display the vector allocated for a device and its interrupt -MSI/MSI-X mode ("PCI MSI"/"PCI MSIX"). Below shows below MSI mode is -enabled on a SCSI Adaptec 39320D Ultra320. +At the user level, users can use the command 'cat /proc/interrupts' +to display the vectors allocated for devices and their interrupt +MSI/MSI-X modes ("PCI-MSI"/"PCI-MSI-X"). Below shows MSI mode is +enabled on a SCSI Adaptec 39320D Ultra320 controller. CPU0 CPU1 0: 324639 0 IO-APIC-edge timer @@ -453,8 +461,8 @@ enabled on a SCSI Adaptec 39320D Ultra320. 15: 1 0 IO-APIC-edge ide1 169: 0 0 IO-APIC-level uhci-hcd 185: 0 0 IO-APIC-level uhci-hcd -193: 138 10 PCI MSI aic79xx -201: 30 0 PCI MSI aic79xx +193: 138 10 PCI-MSI aic79xx +201: 30 0 PCI-MSI aic79xx 225: 30 0 IO-APIC-level aic7xxx 233: 30 0 IO-APIC-level aic7xxx NMI: 0 0 @@ -490,8 +498,8 @@ target address set as 0xfeexxxxx, as conformed to PCI specification 2.3 or latest, then it should work. Q4. From the driver point of view, if the MSI is lost because -of the errors occur during inbound memory write, then it may -wait for ever. Is there a mechanism for it to recover? +of errors occurring during inbound memory write, then it may +wait forever. Is there a mechanism for it to recover? A4. Since the target of the transaction is an inbound memory write, all transaction termination conditions (Retry, -- cgit v1.2.3 From 6c8bec6d5f24b01c53b792b06a645e78d482020d Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 7 Nov 2005 01:01:04 -0800 Subject: [PATCH] jbd doc: fix some kernel-doc warnings Add structure fields kernel-doc for 2 fields in struct journal_s. Warning(/var/linsrc/linux-2614-rc4//include/linux/jbd.h:808): No description found for parameter 'j_wbuf' Warning(/var/linsrc/linux-2614-rc4//include/linux/jbd.h:808): No description found for parameter 'j_wbufsize' Convert fs/jbd/recovery.c non-static functions to kernel-doc format. fs/jbd/recovery.c doesn't export any symbols, so it should use !I instead of !E to eliminate this warning message: Warning(/var/linsrc/linux-2614-rc4//fs/jbd/recovery.c): no structured comments found Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/DocBook/journal-api.tmpl | 2 +- fs/jbd/recovery.c | 4 ++-- include/linux/jbd.h | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Documentation/DocBook/journal-api.tmpl b/Documentation/DocBook/journal-api.tmpl index 341aaa4ce48..2077f9a28c1 100644 --- a/Documentation/DocBook/journal-api.tmpl +++ b/Documentation/DocBook/journal-api.tmpl @@ -306,7 +306,7 @@ an example. Journal Level !Efs/jbd/journal.c -!Efs/jbd/recovery.c +!Ifs/jbd/recovery.c Transasction Level !Efs/jbd/transaction.c diff --git a/fs/jbd/recovery.c b/fs/jbd/recovery.c index 103c34e4fb2..80d7f53fd0a 100644 --- a/fs/jbd/recovery.c +++ b/fs/jbd/recovery.c @@ -210,7 +210,7 @@ do { \ } while (0) /** - * int journal_recover(journal_t *journal) - recovers a on-disk journal + * journal_recover - recovers a on-disk journal * @journal: the journal to recover * * The primary function for recovering the log contents when mounting a @@ -266,7 +266,7 @@ int journal_recover(journal_t *journal) } /** - * int journal_skip_recovery() - Start journal and wipe exiting records + * journal_skip_recovery - Start journal and wipe exiting records * @journal: journal to startup * * Locate any valid recovery information from the journal and set up the diff --git a/include/linux/jbd.h b/include/linux/jbd.h index be197eb9007..aa56172c6fe 100644 --- a/include/linux/jbd.h +++ b/include/linux/jbd.h @@ -611,6 +611,9 @@ struct transaction_s * @j_revoke: The revoke table - maintains the list of revoked blocks in the * current transaction. * @j_revoke_table: alternate revoke tables for j_revoke + * @j_wbuf: array of buffer_heads for journal_commit_transaction + * @j_wbufsize: maximum number of buffer_heads allowed in j_wbuf, the + * number that will fit in j_blocksize * @j_private: An opaque pointer to fs-private information. */ -- cgit v1.2.3 From 8f2709b542c96a2b1910ca5f2fe27dc9023b1225 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 7 Nov 2005 01:01:05 -0800 Subject: [PATCH] kernel-doc: fix some kernel-api warnings Fix various warnings in kernel-doc: Warning(linux-2614-rc4//include/linux/net.h:89): Enum value 'SOCK_DCCP' not described in enum 'sock_type' usercopy.c: should use !E instead of !I for exported symbols: Warning(linux-2614-rc4//arch/i386/lib/usercopy.c): no structured comments found fs.h does not need to use !E since it has no exported symbols: Warning(linux-2614-rc4//include/linux/fs.h:1182): No description found for parameter 'find_exported_dentry' Warning(linux-2614-rc4//include/linux/fs.h): no structured comments found irq/manage.c should use !E for its exported symbols: Warning(linux-2614-rc4//kernel/irq/manage.c): no structured comments found macmodes.c should use !E for its exported symbols: Warning(linux-2614-rc4//drivers/video/macmodes.c): no structured comments found Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/DocBook/kernel-api.tmpl | 7 +++---- include/linux/fs.h | 2 ++ include/linux/net.h | 1 + 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index ec474e5a25e..a8316b1a3e3 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -118,7 +118,7 @@ X!Ilib/string.c User Space Memory Access !Iinclude/asm-i386/uaccess.h -!Iarch/i386/lib/usercopy.c +!Earch/i386/lib/usercopy.c More Memory Management Functions !Iinclude/linux/rmap.h @@ -174,7 +174,6 @@ X!Ilib/string.c The Linux VFS The Filesystem types !Iinclude/linux/fs.h -!Einclude/linux/fs.h The Directory Cache !Efs/dcache.c @@ -266,7 +265,7 @@ X!Ekernel/module.c Hardware Interfaces Interrupt Handling -!Ikernel/irq/manage.c +!Ekernel/irq/manage.c Resources Management @@ -501,7 +500,7 @@ KAO --> !Edrivers/video/modedb.c Frame Buffer Macintosh Video Mode Database -!Idrivers/video/macmodes.c +!Edrivers/video/macmodes.c Frame Buffer Fonts diff --git a/include/linux/fs.h b/include/linux/fs.h index 0c89fc9481a..9a593ef262e 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1096,6 +1096,8 @@ int sync_inode(struct inode *inode, struct writeback_control *wbc); * @get_name: find the name for a given inode in a given directory * @get_parent: find the parent of a given directory * @get_dentry: find a dentry for the inode given a file handle sub-fragment + * @find_exported_dentry: + * set by the exporting module to a standard helper function. * * Description: * The export_operations structure provides a means for nfsd to communicate diff --git a/include/linux/net.h b/include/linux/net.h index 4e981585a89..d6a41e6577f 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -71,6 +71,7 @@ typedef enum { * @SOCK_RAW: raw socket * @SOCK_RDM: reliably-delivered message * @SOCK_SEQPACKET: sequential packet socket + * @SOCK_DCCP: Datagram Congestion Control Protocol socket * @SOCK_PACKET: linux specific way of getting packets at the dev level. * For writing rarp and other similar things on the user level. * -- cgit v1.2.3 From 8a0d4900697f2d615a77cd99585e743c1af555a3 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 7 Nov 2005 01:01:06 -0800 Subject: [PATCH] Doc/hpet.txt: change to < 80 columns Put text into < 80 columns. No other changes. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/hpet.txt | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/Documentation/hpet.txt b/Documentation/hpet.txt index 4e7cc8d3359..e52457581f4 100644 --- a/Documentation/hpet.txt +++ b/Documentation/hpet.txt @@ -1,18 +1,21 @@ High Precision Event Timer Driver for Linux -The High Precision Event Timer (HPET) hardware is the future replacement for the 8254 and Real -Time Clock (RTC) periodic timer functionality. Each HPET can have up two 32 timers. It is possible -to configure the first two timers as legacy replacements for 8254 and RTC periodic. A specification -done by INTEL and Microsoft can be found at http://www.intel.com/labs/platcomp/hpet/hpetspec.htm. - -The driver supports detection of HPET driver allocation and initialization of the HPET before the -driver module_init routine is called. This enables platform code which uses timer 0 or 1 as the -main timer to intercept HPET initialization. An example of this initialization can be found in +The High Precision Event Timer (HPET) hardware is the future replacement +for the 8254 and Real Time Clock (RTC) periodic timer functionality. +Each HPET can have up two 32 timers. It is possible to configure the +first two timers as legacy replacements for 8254 and RTC periodic timers. +A specification done by Intel and Microsoft can be found at +. + +The driver supports detection of HPET driver allocation and initialization +of the HPET before the driver module_init routine is called. This enables +platform code which uses timer 0 or 1 as the main timer to intercept HPET +initialization. An example of this initialization can be found in arch/i386/kernel/time_hpet.c. -The driver provides two APIs which are very similar to the API found in the rtc.c driver. -There is a user space API and a kernel space API. An example user space program is provided -below. +The driver provides two APIs which are very similar to the API found in +the rtc.c driver. There is a user space API and a kernel space API. +An example user space program is provided below. #include #include @@ -290,9 +293,8 @@ The kernel API has three interfaces exported from the driver: hpet_unregister(struct hpet_task *tp) hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg) -The kernel module using this interface fills in the ht_func and ht_data members of the -hpet_task structure before calling hpet_register. hpet_control simply vectors to the hpet_ioctl -routine and has the same commands and respective arguments as the user API. hpet_unregister +The kernel module using this interface fills in the ht_func and ht_data +members of the hpet_task structure before calling hpet_register. +hpet_control simply vectors to the hpet_ioctl routine and has the same +commands and respective arguments as the user API. hpet_unregister is used to terminate usage of the HPET timer reserved by hpet_register. - - -- cgit v1.2.3 From 1e5d533142c1c178a31d4cc81837eb078f9269bc Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 7 Nov 2005 01:01:06 -0800 Subject: [PATCH] more kernel-doc cleanups, additions Various core kernel-doc cleanups: - add missing function parameters in ipc, irq/manage, kernel/sys, kernel/sysctl, and mm/slab; - move description to just above function for kernel_restart() Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- ipc/util.c | 9 +++++---- kernel/irq/manage.c | 1 + kernel/sys.c | 15 +++++++++------ kernel/sysctl.c | 1 + mm/slab.c | 1 + 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/ipc/util.c b/ipc/util.c index 10e836d0d89..23f1cec150c 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -410,7 +410,8 @@ void ipc_rcu_getref(void *ptr) } /** - * ipc_schedule_free - free ipc + rcu space + * ipc_schedule_free - free ipc + rcu space + * @head: RCU callback structure for queued work * * Since RCU callback function is called in bh, * we need to defer the vfree to schedule_work @@ -427,10 +428,10 @@ static void ipc_schedule_free(struct rcu_head *head) } /** - * ipc_immediate_free - free ipc + rcu space - * - * Free from the RCU callback context + * ipc_immediate_free - free ipc + rcu space + * @head: RCU callback structure that contains pointer to be freed * + * Free from the RCU callback context */ static void ipc_immediate_free(struct rcu_head *head) { diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 1cfdb08ddf2..3bd7226d15f 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -24,6 +24,7 @@ cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS]; /** * synchronize_irq - wait for pending IRQ handlers (on other CPUs) + * @irq: interrupt number to wait for * * This function waits for any pending IRQ handlers for this interrupt * to complete before returning. If you use this function while diff --git a/kernel/sys.c b/kernel/sys.c index 1e1f41b3fdf..3e332131000 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -376,18 +376,21 @@ void emergency_restart(void) } EXPORT_SYMBOL_GPL(emergency_restart); -/** - * kernel_restart - reboot the system - * - * Shutdown everything and perform a clean reboot. - * This is not safe to call in interrupt context. - */ void kernel_restart_prepare(char *cmd) { notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd); system_state = SYSTEM_RESTART; device_shutdown(); } + +/** + * kernel_restart - reboot the system + * @cmd: pointer to buffer containing command to execute for restart + * or NULL + * + * Shutdown everything and perform a clean reboot. + * This is not safe to call in interrupt context. + */ void kernel_restart(char *cmd) { kernel_restart_prepare(cmd); diff --git a/kernel/sysctl.c b/kernel/sysctl.c index e1351200ce8..c4f35f96884 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1997,6 +1997,7 @@ int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp, * @filp: the file structure * @buffer: the user buffer * @lenp: the size of the user buffer + * @ppos: pointer to the file position * * Reads/writes up to table->maxlen/sizeof(unsigned int) integer * values from/to the user buffer, treated as an ASCII string. diff --git a/mm/slab.c b/mm/slab.c index 1db4d731385..e291f5e1afb 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -3263,6 +3263,7 @@ static void drain_array_locked(kmem_cache_t *cachep, /** * cache_reap - Reclaim memory from caches. + * @unused: unused parameter * * Called from workqueue/eventd every few seconds. * Purpose: -- cgit v1.2.3 From b8887e6e8c04bcefb512cdb08fc7e9c310ac847e Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 7 Nov 2005 01:01:07 -0800 Subject: [PATCH] kernel-docs: fix kernel-doc format problems Convert to proper kernel-doc format. Some have extra blank lines (not allowed immed. after the function name) or need blank lines (after all parameters). Function summary must be only one line. Colon (":") in a function description does weird things (causes kernel-doc to think that it's a new section head sadly). Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/ll_rw_blk.c | 1 - fs/fs-writeback.c | 5 +++-- include/linux/kernel.h | 1 - kernel/sys.c | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 2747741677f..5f52e30b43f 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -706,7 +706,6 @@ EXPORT_SYMBOL(blk_queue_dma_alignment); /** * blk_queue_find_tag - find a request by its tag and queue - * * @q: The request queue for the device * @tag: The tag of the request * diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 1361a4a6415..785c7213a54 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -606,7 +606,7 @@ EXPORT_SYMBOL(sync_inode); * O_SYNC flag set, to flush dirty writes to disk. * * @what is a bitmask, specifying which part of the inode's data should be - * written and waited upon: + * written and waited upon. * * OSYNC_DATA: i_mapping's dirty data * OSYNC_METADATA: the buffers at i_mapping->private_list @@ -672,8 +672,9 @@ int writeback_acquire(struct backing_dev_info *bdi) /** * writeback_in_progress: determine whether there is writeback in progress - * against a backing device. * @bdi: the device's backing_dev_info structure. + * + * Determine whether there is writeback in progress against a backing device. */ int writeback_in_progress(struct backing_dev_info *bdi) { diff --git a/include/linux/kernel.h b/include/linux/kernel.h index f1925ccc9fe..b6419489b27 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -266,7 +266,6 @@ extern void dump_stack(void); /** * container_of - cast a member of a structure out to the containing structure - * * @ptr: the pointer to the member. * @type: the type of the container struct this is embedded in. * @member: the name of the member within the struct. diff --git a/kernel/sys.c b/kernel/sys.c index 3e332131000..bce933ebb29 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -386,7 +386,7 @@ void kernel_restart_prepare(char *cmd) /** * kernel_restart - reboot the system * @cmd: pointer to buffer containing command to execute for restart - * or NULL + * or %NULL * * Shutdown everything and perform a clean reboot. * This is not safe to call in interrupt context. -- cgit v1.2.3 From cc7d1f8f96a4d048b56edb22e8c5b0f2c2bd7549 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Mon, 7 Nov 2005 01:01:08 -0800 Subject: [PATCH] VFS: update overview document This patch updates the Documentation/filesystems/vfs.txt document. I rearranged and rewrote parts of the introduction chapter and added better headings for each section. I also added a description for the inode rename() operation which was missing and added links to some useful external VFS documentation. Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/filesystems/vfs.txt | 263 +++++++++++++++++++++----------------- 1 file changed, 149 insertions(+), 114 deletions(-) diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index f042c12e0ed..821090946a1 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -3,7 +3,7 @@ Original author: Richard Gooch - Last updated on August 25, 2005 + Last updated on October 28, 2005 Copyright (C) 1999 Richard Gooch Copyright (C) 2005 Pekka Enberg @@ -11,62 +11,61 @@ This file is released under the GPLv2. -What is it? -=========== +Introduction +============ -The Virtual File System (otherwise known as the Virtual Filesystem -Switch) is the software layer in the kernel that provides the -filesystem interface to userspace programs. It also provides an -abstraction within the kernel which allows different filesystem -implementations to coexist. +The Virtual File System (also known as the Virtual Filesystem Switch) +is the software layer in the kernel that provides the filesystem +interface to userspace programs. It also provides an abstraction +within the kernel which allows different filesystem implementations to +coexist. +VFS system calls open(2), stat(2), read(2), write(2), chmod(2) and so +on are called from a process context. Filesystem locking is described +in the document Documentation/filesystems/Locking. -A Quick Look At How It Works -============================ -In this section I'll briefly describe how things work, before -launching into the details. I'll start with describing what happens -when user programs open and manipulate files, and then look from the -other view which is how a filesystem is supported and subsequently -mounted. - - -Opening a File --------------- - -The VFS implements the open(2), stat(2), chmod(2) and similar system -calls. The pathname argument is used by the VFS to search through the -directory entry cache (dentry cache or "dcache"). This provides a very -fast look-up mechanism to translate a pathname (filename) into a -specific dentry. - -An individual dentry usually has a pointer to an inode. Inodes are the -things that live on disc drives, and can be regular files (you know: -those things that you write data into), directories, FIFOs and other -beasts. Dentries live in RAM and are never saved to disc: they exist -only for performance. Inodes live on disc and are copied into memory -when required. Later any changes are written back to disc. The inode -that lives in RAM is a VFS inode, and it is this which the dentry -points to. A single inode can be pointed to by multiple dentries -(think about hardlinks). - -The dcache is meant to be a view into your entire filespace. Unlike -Linus, most of us losers can't fit enough dentries into RAM to cover -all of our filespace, so the dcache has bits missing. In order to -resolve your pathname into a dentry, the VFS may have to resort to -creating dentries along the way, and then loading the inode. This is -done by looking up the inode. - -To look up an inode (usually read from disc) requires that the VFS -calls the lookup() method of the parent directory inode. This method -is installed by the specific filesystem implementation that the inode -lives in. There will be more on this later. +Directory Entry Cache (dcache) +------------------------------ -Once the VFS has the required dentry (and hence the inode), we can do -all those boring things like open(2) the file, or stat(2) it to peek -at the inode data. The stat(2) operation is fairly simple: once the -VFS has the dentry, it peeks at the inode data and passes some of it -back to userspace. +The VFS implements the open(2), stat(2), chmod(2), and similar system +calls. The pathname argument that is passed to them is used by the VFS +to search through the directory entry cache (also known as the dentry +cache or dcache). This provides a very fast look-up mechanism to +translate a pathname (filename) into a specific dentry. Dentries live +in RAM and are never saved to disc: they exist only for performance. + +The dentry cache is meant to be a view into your entire filespace. As +most computers cannot fit all dentries in the RAM at the same time, +some bits of the cache are missing. In order to resolve your pathname +into a dentry, the VFS may have to resort to creating dentries along +the way, and then loading the inode. This is done by looking up the +inode. + + +The Inode Object +---------------- + +An individual dentry usually has a pointer to an inode. Inodes are +filesystem objects such as regular files, directories, FIFOs and other +beasts. They live either on the disc (for block device filesystems) +or in the memory (for pseudo filesystems). Inodes that live on the +disc are copied into the memory when required and changes to the inode +are written back to disc. A single inode can be pointed to by multiple +dentries (hard links, for example, do this). + +To look up an inode requires that the VFS calls the lookup() method of +the parent directory inode. This method is installed by the specific +filesystem implementation that the inode lives in. Once the VFS has +the required dentry (and hence the inode), we can do all those boring +things like open(2) the file, or stat(2) it to peek at the inode +data. The stat(2) operation is fairly simple: once the VFS has the +dentry, it peeks at the inode data and passes some of it back to +userspace. + + +The File Object +--------------- Opening a file requires another operation: allocation of a file structure (this is the kernel-side implementation of file @@ -74,51 +73,39 @@ descriptors). The freshly allocated file structure is initialized with a pointer to the dentry and a set of file operation member functions. These are taken from the inode data. The open() file method is then called so the specific filesystem implementation can do it's work. You -can see that this is another switch performed by the VFS. - -The file structure is placed into the file descriptor table for the -process. +can see that this is another switch performed by the VFS. The file +structure is placed into the file descriptor table for the process. Reading, writing and closing files (and other assorted VFS operations) is done by using the userspace file descriptor to grab the appropriate -file structure, and then calling the required file structure method -function to do whatever is required. - -For as long as the file is open, it keeps the dentry "open" (in use), -which in turn means that the VFS inode is still in use. - -All VFS system calls (i.e. open(2), stat(2), read(2), write(2), -chmod(2) and so on) are called from a process context. You should -assume that these calls are made without any kernel locks being -held. This means that the processes may be executing the same piece of -filesystem or driver code at the same time, on different -processors. You should ensure that access to shared resources is -protected by appropriate locks. +file structure, and then calling the required file structure method to +do whatever is required. For as long as the file is open, it keeps the +dentry in use, which in turn means that the VFS inode is still in use. Registering and Mounting a Filesystem -------------------------------------- +===================================== -If you want to support a new kind of filesystem in the kernel, all you -need to do is call register_filesystem(). You pass a structure -describing the filesystem implementation (struct file_system_type) -which is then added to an internal table of supported filesystems. You -can do: +To register and unregister a filesystem, use the following API +functions: -% cat /proc/filesystems + #include -to see what filesystems are currently available on your system. + extern int register_filesystem(struct file_system_type *); + extern int unregister_filesystem(struct file_system_type *); -When a request is made to mount a block device onto a directory in -your filespace the VFS will call the appropriate method for the -specific filesystem. The dentry for the mount point will then be -updated to point to the root inode for the new filesystem. +The passed struct file_system_type describes your filesystem. When a +request is made to mount a device onto a directory in your filespace, +the VFS will call the appropriate get_sb() method for the specific +filesystem. The dentry for the mount point will then be updated to +point to the root inode for the new filesystem. -It's now time to look at things in more detail. +You can see all filesystems that are registered to the kernel in the +file /proc/filesystems. struct file_system_type -======================= +----------------------- This describes the filesystem. As of kernel 2.6.13, the following members are defined: @@ -197,8 +184,14 @@ A fill_super() method implementation has the following arguments: int silent: whether or not to be silent on error +The Superblock Object +===================== + +A superblock object represents a mounted filesystem. + + struct super_operations -======================= +----------------------- This describes how the VFS can manipulate the superblock of your filesystem. As of kernel 2.6.13, the following members are defined: @@ -286,9 +279,9 @@ or bottom half). a superblock. The second parameter indicates whether the method should wait until the write out has been completed. Optional. - write_super_lockfs: called when VFS is locking a filesystem and forcing - it into a consistent state. This function is currently used by the - Logical Volume Manager (LVM). + write_super_lockfs: called when VFS is locking a filesystem and + forcing it into a consistent state. This method is currently + used by the Logical Volume Manager (LVM). unlockfs: called when VFS is unlocking a filesystem and making it writable again. @@ -317,8 +310,14 @@ field. This is a pointer to a "struct inode_operations" which describes the methods that can be performed on individual inodes. +The Inode Object +================ + +An inode object represents an object within the filesystem. + + struct inode_operations -======================= +----------------------- This describes how the VFS can manipulate an inode in your filesystem. As of kernel 2.6.13, the following members are defined: @@ -394,51 +393,62 @@ otherwise noted. will probably need to call d_instantiate() just as you would in the create() method + rename: called by the rename(2) system call to rename the object to + have the parent and name given by the second inode and dentry. + readlink: called by the readlink(2) system call. Only required if you want to support reading symbolic links follow_link: called by the VFS to follow a symbolic link to the inode it points to. Only required if you want to support - symbolic links. This function returns a void pointer cookie + symbolic links. This method returns a void pointer cookie that is passed to put_link(). put_link: called by the VFS to release resources allocated by - follow_link(). The cookie returned by follow_link() is passed to - to this function as the last parameter. It is used by filesystems - such as NFS where page cache is not stable (i.e. page that was - installed when the symbolic link walk started might not be in the - page cache at the end of the walk). - - truncate: called by the VFS to change the size of a file. The i_size - field of the inode is set to the desired size by the VFS before - this function is called. This function is called by the truncate(2) - system call and related functionality. + follow_link(). The cookie returned by follow_link() is passed + to to this method as the last parameter. It is used by + filesystems such as NFS where page cache is not stable + (i.e. page that was installed when the symbolic link walk + started might not be in the page cache at the end of the + walk). + + truncate: called by the VFS to change the size of a file. The + i_size field of the inode is set to the desired size by the + VFS before this method is called. This method is called by + the truncate(2) system call and related functionality. permission: called by the VFS to check for access rights on a POSIX-like filesystem. - setattr: called by the VFS to set attributes for a file. This function is - called by chmod(2) and related system calls. + setattr: called by the VFS to set attributes for a file. This method + is called by chmod(2) and related system calls. - getattr: called by the VFS to get attributes of a file. This function is - called by stat(2) and related system calls. + getattr: called by the VFS to get attributes of a file. This method + is called by stat(2) and related system calls. setxattr: called by the VFS to set an extended attribute for a file. - Extended attribute is a name:value pair associated with an inode. This - function is called by setxattr(2) system call. + Extended attribute is a name:value pair associated with an + inode. This method is called by setxattr(2) system call. + + getxattr: called by the VFS to retrieve the value of an extended + attribute name. This method is called by getxattr(2) function + call. + + listxattr: called by the VFS to list all extended attributes for a + given file. This method is called by listxattr(2) system call. - getxattr: called by the VFS to retrieve the value of an extended attribute - name. This function is called by getxattr(2) function call. + removexattr: called by the VFS to remove an extended attribute from + a file. This method is called by removexattr(2) system call. - listxattr: called by the VFS to list all extended attributes for a given - file. This function is called by listxattr(2) system call. - removexattr: called by the VFS to remove an extended attribute from a file. - This function is called by removexattr(2) system call. +The Address Space Object +======================== + +The address space object is used to identify pages in the page cache. struct address_space_operations -=============================== +------------------------------- This describes how the VFS can manipulate mapping of a file to page cache in your filesystem. As of kernel 2.6.13, the following members are defined: @@ -502,8 +512,14 @@ struct address_space_operations { it. An example implementation can be found in fs/ext2/xip.c. +The File Object +=============== + +A file object represents a file opened by a process. + + struct file_operations -====================== +---------------------- This describes how the VFS can manipulate an open file. As of kernel 2.6.13, the following members are defined: @@ -661,7 +677,7 @@ of child dentries. Child dentries are basically like files in a directory. -Directory Entry Cache APIs +Directory Entry Cache API -------------------------- There are a number of functions defined which permit a filesystem to @@ -880,3 +896,22 @@ Papers and other documentation on dcache locking 1. Scaling dcache with RCU (http://linuxjournal.com/article.php?sid=7124). 2. http://lse.sourceforge.net/locking/dcache/dcache.html + + +Resources +========= + +(Note some of these resources are not up-to-date with the latest kernel + version.) + +Creating Linux virtual filesystems. 2002 + + +The Linux Virtual File-system Layer by Neil Brown. 1999 + + +A tour of the Linux VFS by Michael K. Johnson. 1996 + + +A small trail through the Linux kernel by Andries Brouwer. 2001 + -- cgit v1.2.3 From cbf8f0f36a2339f87b9dabbbd301ffd86744620c Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Mon, 7 Nov 2005 01:01:09 -0800 Subject: [PATCH] VFS: split dentry locking documentation This patch splits dentry locking documentation from Documentation/filesystems/vfs.txt to a separate file. The dentry locking bits are useful but do not fit into the VFS overview document as is. Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/filesystems/dentry-locking.txt | 173 ++++++++++++++++++++++++++ Documentation/filesystems/vfs.txt | 177 +-------------------------- 2 files changed, 175 insertions(+), 175 deletions(-) create mode 100644 Documentation/filesystems/dentry-locking.txt diff --git a/Documentation/filesystems/dentry-locking.txt b/Documentation/filesystems/dentry-locking.txt new file mode 100644 index 00000000000..4c0c575a401 --- /dev/null +++ b/Documentation/filesystems/dentry-locking.txt @@ -0,0 +1,173 @@ +RCU-based dcache locking model +============================== + +On many workloads, the most common operation on dcache is to look up a +dentry, given a parent dentry and the name of the child. Typically, +for every open(), stat() etc., the dentry corresponding to the +pathname will be looked up by walking the tree starting with the first +component of the pathname and using that dentry along with the next +component to look up the next level and so on. Since it is a frequent +operation for workloads like multiuser environments and web servers, +it is important to optimize this path. + +Prior to 2.5.10, dcache_lock was acquired in d_lookup and thus in +every component during path look-up. Since 2.5.10 onwards, fast-walk +algorithm changed this by holding the dcache_lock at the beginning and +walking as many cached path component dentries as possible. This +significantly decreases the number of acquisition of +dcache_lock. However it also increases the lock hold time +significantly and affects performance in large SMP machines. Since +2.5.62 kernel, dcache has been using a new locking model that uses RCU +to make dcache look-up lock-free. + +The current dcache locking model is not very different from the +existing dcache locking model. Prior to 2.5.62 kernel, dcache_lock +protected the hash chain, d_child, d_alias, d_lru lists as well as +d_inode and several other things like mount look-up. RCU-based changes +affect only the way the hash chain is protected. For everything else +the dcache_lock must be taken for both traversing as well as +updating. The hash chain updates too take the dcache_lock. The +significant change is the way d_lookup traverses the hash chain, it +doesn't acquire the dcache_lock for this and rely on RCU to ensure +that the dentry has not been *freed*. + + +Dcache locking details +====================== + +For many multi-user workloads, open() and stat() on files are very +frequently occurring operations. Both involve walking of path names to +find the dentry corresponding to the concerned file. In 2.4 kernel, +dcache_lock was held during look-up of each path component. Contention +and cache-line bouncing of this global lock caused significant +scalability problems. With the introduction of RCU in Linux kernel, +this was worked around by making the look-up of path components during +path walking lock-free. + + +Safe lock-free look-up of dcache hash table +=========================================== + +Dcache is a complex data structure with the hash table entries also +linked together in other lists. In 2.4 kernel, dcache_lock protected +all the lists. We applied RCU only on hash chain walking. The rest of +the lists are still protected by dcache_lock. Some of the important +changes are : + +1. The deletion from hash chain is done using hlist_del_rcu() macro + which doesn't initialize next pointer of the deleted dentry and + this allows us to walk safely lock-free while a deletion is + happening. + +2. Insertion of a dentry into the hash table is done using + hlist_add_head_rcu() which take care of ordering the writes - the + writes to the dentry must be visible before the dentry is + inserted. This works in conjunction with hlist_for_each_rcu() while + walking the hash chain. The only requirement is that all + initialization to the dentry must be done before + hlist_add_head_rcu() since we don't have dcache_lock protection + while traversing the hash chain. This isn't different from the + existing code. + +3. The dentry looked up without holding dcache_lock by cannot be + returned for walking if it is unhashed. It then may have a NULL + d_inode or other bogosity since RCU doesn't protect the other + fields in the dentry. We therefore use a flag DCACHE_UNHASHED to + indicate unhashed dentries and use this in conjunction with a + per-dentry lock (d_lock). Once looked up without the dcache_lock, + we acquire the per-dentry lock (d_lock) and check if the dentry is + unhashed. If so, the look-up is failed. If not, the reference count + of the dentry is increased and the dentry is returned. + +4. Once a dentry is looked up, it must be ensured during the path walk + for that component it doesn't go away. In pre-2.5.10 code, this was + done holding a reference to the dentry. dcache_rcu does the same. + In some sense, dcache_rcu path walking looks like the pre-2.5.10 + version. + +5. All dentry hash chain updates must take the dcache_lock as well as + the per-dentry lock in that order. dput() does this to ensure that + a dentry that has just been looked up in another CPU doesn't get + deleted before dget() can be done on it. + +6. There are several ways to do reference counting of RCU protected + objects. One such example is in ipv4 route cache where deferred + freeing (using call_rcu()) is done as soon as the reference count + goes to zero. This cannot be done in the case of dentries because + tearing down of dentries require blocking (dentry_iput()) which + isn't supported from RCU callbacks. Instead, tearing down of + dentries happen synchronously in dput(), but actual freeing happens + later when RCU grace period is over. This allows safe lock-free + walking of the hash chains, but a matched dentry may have been + partially torn down. The checking of DCACHE_UNHASHED flag with + d_lock held detects such dentries and prevents them from being + returned from look-up. + + +Maintaining POSIX rename semantics +================================== + +Since look-up of dentries is lock-free, it can race against a +concurrent rename operation. For example, during rename of file A to +B, look-up of either A or B must succeed. So, if look-up of B happens +after A has been removed from the hash chain but not added to the new +hash chain, it may fail. Also, a comparison while the name is being +written concurrently by a rename may result in false positive matches +violating rename semantics. Issues related to race with rename are +handled as described below : + +1. Look-up can be done in two ways - d_lookup() which is safe from + simultaneous renames and __d_lookup() which is not. If + __d_lookup() fails, it must be followed up by a d_lookup() to + correctly determine whether a dentry is in the hash table or + not. d_lookup() protects look-ups using a sequence lock + (rename_lock). + +2. The name associated with a dentry (d_name) may be changed if a + rename is allowed to happen simultaneously. To avoid memcmp() in + __d_lookup() go out of bounds due to a rename and false positive + comparison, the name comparison is done while holding the + per-dentry lock. This prevents concurrent renames during this + operation. + +3. Hash table walking during look-up may move to a different bucket as + the current dentry is moved to a different bucket due to rename. + But we use hlists in dcache hash table and they are + null-terminated. So, even if a dentry moves to a different bucket, + hash chain walk will terminate. [with a list_head list, it may not + since termination is when the list_head in the original bucket is + reached]. Since we redo the d_parent check and compare name while + holding d_lock, lock-free look-up will not race against d_move(). + +4. There can be a theoretical race when a dentry keeps coming back to + original bucket due to double moves. Due to this look-up may + consider that it has never moved and can end up in a infinite loop. + But this is not any worse that theoretical livelocks we already + have in the kernel. + + +Important guidelines for filesystem developers related to dcache_rcu +==================================================================== + +1. Existing dcache interfaces (pre-2.5.62) exported to filesystem + don't change. Only dcache internal implementation changes. However + filesystems *must not* delete from the dentry hash chains directly + using the list macros like allowed earlier. They must use dcache + APIs like d_drop() or __d_drop() depending on the situation. + +2. d_flags is now protected by a per-dentry lock (d_lock). All access + to d_flags must be protected by it. + +3. For a hashed dentry, checking of d_count needs to be protected by + d_lock. + + +Papers and other documentation on dcache locking +================================================ + +1. Scaling dcache with RCU (http://linuxjournal.com/article.php?sid=7124). + +2. http://lse.sourceforge.net/locking/dcache/dcache.html + + + diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 821090946a1..ee4c0a8b8db 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -721,181 +721,8 @@ manipulate dentries: and the dentry is returned. The caller must use d_put() to free the dentry when it finishes using it. - -RCU-based dcache locking model ------------------------------- - -On many workloads, the most common operation on dcache is -to look up a dentry, given a parent dentry and the name -of the child. Typically, for every open(), stat() etc., -the dentry corresponding to the pathname will be looked -up by walking the tree starting with the first component -of the pathname and using that dentry along with the next -component to look up the next level and so on. Since it -is a frequent operation for workloads like multiuser -environments and web servers, it is important to optimize -this path. - -Prior to 2.5.10, dcache_lock was acquired in d_lookup and thus -in every component during path look-up. Since 2.5.10 onwards, -fast-walk algorithm changed this by holding the dcache_lock -at the beginning and walking as many cached path component -dentries as possible. This significantly decreases the number -of acquisition of dcache_lock. However it also increases the -lock hold time significantly and affects performance in large -SMP machines. Since 2.5.62 kernel, dcache has been using -a new locking model that uses RCU to make dcache look-up -lock-free. - -The current dcache locking model is not very different from the existing -dcache locking model. Prior to 2.5.62 kernel, dcache_lock -protected the hash chain, d_child, d_alias, d_lru lists as well -as d_inode and several other things like mount look-up. RCU-based -changes affect only the way the hash chain is protected. For everything -else the dcache_lock must be taken for both traversing as well as -updating. The hash chain updates too take the dcache_lock. -The significant change is the way d_lookup traverses the hash chain, -it doesn't acquire the dcache_lock for this and rely on RCU to -ensure that the dentry has not been *freed*. - - -Dcache locking details ----------------------- - -For many multi-user workloads, open() and stat() on files are -very frequently occurring operations. Both involve walking -of path names to find the dentry corresponding to the -concerned file. In 2.4 kernel, dcache_lock was held -during look-up of each path component. Contention and -cache-line bouncing of this global lock caused significant -scalability problems. With the introduction of RCU -in Linux kernel, this was worked around by making -the look-up of path components during path walking lock-free. - - -Safe lock-free look-up of dcache hash table -=========================================== - -Dcache is a complex data structure with the hash table entries -also linked together in other lists. In 2.4 kernel, dcache_lock -protected all the lists. We applied RCU only on hash chain -walking. The rest of the lists are still protected by dcache_lock. -Some of the important changes are : - -1. The deletion from hash chain is done using hlist_del_rcu() macro which - doesn't initialize next pointer of the deleted dentry and this - allows us to walk safely lock-free while a deletion is happening. - -2. Insertion of a dentry into the hash table is done using - hlist_add_head_rcu() which take care of ordering the writes - - the writes to the dentry must be visible before the dentry - is inserted. This works in conjunction with hlist_for_each_rcu() - while walking the hash chain. The only requirement is that - all initialization to the dentry must be done before hlist_add_head_rcu() - since we don't have dcache_lock protection while traversing - the hash chain. This isn't different from the existing code. - -3. The dentry looked up without holding dcache_lock by cannot be - returned for walking if it is unhashed. It then may have a NULL - d_inode or other bogosity since RCU doesn't protect the other - fields in the dentry. We therefore use a flag DCACHE_UNHASHED to - indicate unhashed dentries and use this in conjunction with a - per-dentry lock (d_lock). Once looked up without the dcache_lock, - we acquire the per-dentry lock (d_lock) and check if the - dentry is unhashed. If so, the look-up is failed. If not, the - reference count of the dentry is increased and the dentry is returned. - -4. Once a dentry is looked up, it must be ensured during the path - walk for that component it doesn't go away. In pre-2.5.10 code, - this was done holding a reference to the dentry. dcache_rcu does - the same. In some sense, dcache_rcu path walking looks like - the pre-2.5.10 version. - -5. All dentry hash chain updates must take the dcache_lock as well as - the per-dentry lock in that order. dput() does this to ensure - that a dentry that has just been looked up in another CPU - doesn't get deleted before dget() can be done on it. - -6. There are several ways to do reference counting of RCU protected - objects. One such example is in ipv4 route cache where - deferred freeing (using call_rcu()) is done as soon as - the reference count goes to zero. This cannot be done in - the case of dentries because tearing down of dentries - require blocking (dentry_iput()) which isn't supported from - RCU callbacks. Instead, tearing down of dentries happen - synchronously in dput(), but actual freeing happens later - when RCU grace period is over. This allows safe lock-free - walking of the hash chains, but a matched dentry may have - been partially torn down. The checking of DCACHE_UNHASHED - flag with d_lock held detects such dentries and prevents - them from being returned from look-up. - - -Maintaining POSIX rename semantics -================================== - -Since look-up of dentries is lock-free, it can race against -a concurrent rename operation. For example, during rename -of file A to B, look-up of either A or B must succeed. -So, if look-up of B happens after A has been removed from the -hash chain but not added to the new hash chain, it may fail. -Also, a comparison while the name is being written concurrently -by a rename may result in false positive matches violating -rename semantics. Issues related to race with rename are -handled as described below : - -1. Look-up can be done in two ways - d_lookup() which is safe - from simultaneous renames and __d_lookup() which is not. - If __d_lookup() fails, it must be followed up by a d_lookup() - to correctly determine whether a dentry is in the hash table - or not. d_lookup() protects look-ups using a sequence - lock (rename_lock). - -2. The name associated with a dentry (d_name) may be changed if - a rename is allowed to happen simultaneously. To avoid memcmp() - in __d_lookup() go out of bounds due to a rename and false - positive comparison, the name comparison is done while holding the - per-dentry lock. This prevents concurrent renames during this - operation. - -3. Hash table walking during look-up may move to a different bucket as - the current dentry is moved to a different bucket due to rename. - But we use hlists in dcache hash table and they are null-terminated. - So, even if a dentry moves to a different bucket, hash chain - walk will terminate. [with a list_head list, it may not since - termination is when the list_head in the original bucket is reached]. - Since we redo the d_parent check and compare name while holding - d_lock, lock-free look-up will not race against d_move(). - -4. There can be a theoretical race when a dentry keeps coming back - to original bucket due to double moves. Due to this look-up may - consider that it has never moved and can end up in a infinite loop. - But this is not any worse that theoretical livelocks we already - have in the kernel. - - -Important guidelines for filesystem developers related to dcache_rcu -==================================================================== - -1. Existing dcache interfaces (pre-2.5.62) exported to filesystem - don't change. Only dcache internal implementation changes. However - filesystems *must not* delete from the dentry hash chains directly - using the list macros like allowed earlier. They must use dcache - APIs like d_drop() or __d_drop() depending on the situation. - -2. d_flags is now protected by a per-dentry lock (d_lock). All - access to d_flags must be protected by it. - -3. For a hashed dentry, checking of d_count needs to be protected - by d_lock. - - -Papers and other documentation on dcache locking -================================================ - -1. Scaling dcache with RCU (http://linuxjournal.com/article.php?sid=7124). - -2. http://lse.sourceforge.net/locking/dcache/dcache.html +For further information on dentry locking, please refer to the document +Documentation/filesystems/dentry-locking.txt. Resources -- cgit v1.2.3 From 7f46a240b0a1797eb641c046d445f026563463d4 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 7 Nov 2005 01:01:09 -0800 Subject: [PATCH] ramfs, rootfs, and initramfs docs Docs for ramfs, rootfs, and initramfs. Signed-off-by: Rob Landley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- .../filesystems/ramfs-rootfs-initramfs.txt | 195 +++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 Documentation/filesystems/ramfs-rootfs-initramfs.txt diff --git a/Documentation/filesystems/ramfs-rootfs-initramfs.txt b/Documentation/filesystems/ramfs-rootfs-initramfs.txt new file mode 100644 index 00000000000..b3404a03259 --- /dev/null +++ b/Documentation/filesystems/ramfs-rootfs-initramfs.txt @@ -0,0 +1,195 @@ +ramfs, rootfs and initramfs +October 17, 2005 +Rob Landley +============================= + +What is ramfs? +-------------- + +Ramfs is a very simple filesystem that exports Linux's disk caching +mechanisms (the page cache and dentry cache) as a dynamically resizable +ram-based filesystem. + +Normally all files are cached in memory by Linux. Pages of data read from +backing store (usually the block device the filesystem is mounted on) are kept +around in case it's needed again, but marked as clean (freeable) in case the +Virtual Memory system needs the memory for something else. Similarly, data +written to files is marked clean as soon as it has been written to backing +store, but kept around for caching purposes until the VM reallocates the +memory. A similar mechanism (the dentry cache) greatly speeds up access to +directories. + +With ramfs, there is no backing store. Files written into ramfs allocate +dentries and page cache as usual, but there's nowhere to write them to. +This means the pages are never marked clean, so they can't be freed by the +VM when it's looking to recycle memory. + +The amount of code required to implement ramfs is tiny, because all the +work is done by the existing Linux caching infrastructure. Basically, +you're mounting the disk cache as a filesystem. Because of this, ramfs is not +an optional component removable via menuconfig, since there would be negligible +space savings. + +ramfs and ramdisk: +------------------ + +The older "ram disk" mechanism created a synthetic block device out of +an area of ram and used it as backing store for a filesystem. This block +device was of fixed size, so the filesystem mounted on it was of fixed +size. Using a ram disk also required unnecessarily copying memory from the +fake block device into the page cache (and copying changes back out), as well +as creating and destroying dentries. Plus it needed a filesystem driver +(such as ext2) to format and interpret this data. + +Compared to ramfs, this wastes memory (and memory bus bandwidth), creates +unnecessary work for the CPU, and pollutes the CPU caches. (There are tricks +to avoid this copying by playing with the page tables, but they're unpleasantly +complicated and turn out to be about as expensive as the copying anyway.) +More to the point, all the work ramfs is doing has to happen _anyway_, +since all file access goes through the page and dentry caches. The ram +disk is simply unnecessary, ramfs is internally much simpler. + +Another reason ramdisks are semi-obsolete is that the introduction of +loopback devices offered a more flexible and convenient way to create +synthetic block devices, now from files instead of from chunks of memory. +See losetup (8) for details. + +ramfs and tmpfs: +---------------- + +One downside of ramfs is you can keep writing data into it until you fill +up all memory, and the VM can't free it because the VM thinks that files +should get written to backing store (rather than swap space), but ramfs hasn't +got any backing store. Because of this, only root (or a trusted user) should +be allowed write access to a ramfs mount. + +A ramfs derivative called tmpfs was created to add size limits, and the ability +to write the data to swap space. Normal users can be allowed write access to +tmpfs mounts. See Documentation/filesystems/tmpfs.txt for more information. + +What is rootfs? +--------------- + +Rootfs is a special instance of ramfs, which is always present in 2.6 systems. +(It's used internally as the starting and stopping point for searches of the +kernel's doubly-linked list of mount points.) + +Most systems just mount another filesystem over it and ignore it. The +amount of space an empty instance of ramfs takes up is tiny. + +What is initramfs? +------------------ + +All 2.6 Linux kernels contain a gzipped "cpio" format archive, which is +extracted into rootfs when the kernel boots up. After extracting, the kernel +checks to see if rootfs contains a file "init", and if so it executes it as PID +1. If found, this init process is responsible for bringing the system the +rest of the way up, including locating and mounting the real root device (if +any). If rootfs does not contain an init program after the embedded cpio +archive is extracted into it, the kernel will fall through to the older code +to locate and mount a root partition, then exec some variant of /sbin/init +out of that. + +All this differs from the old initrd in several ways: + + - The old initrd was a separate file, while the initramfs archive is linked + into the linux kernel image. (The directory linux-*/usr is devoted to + generating this archive during the build.) + + - The old initrd file was a gzipped filesystem image (in some file format, + such as ext2, that had to be built into the kernel), while the new + initramfs archive is a gzipped cpio archive (like tar only simpler, + see cpio(1) and Documentation/early-userspace/buffer-format.txt). + + - The program run by the old initrd (which was called /initrd, not /init) did + some setup and then returned to the kernel, while the init program from + initramfs is not expected to return to the kernel. (If /init needs to hand + off control it can overmount / with a new root device and exec another init + program. See the switch_root utility, below.) + + - When switching another root device, initrd would pivot_root and then + umount the ramdisk. But initramfs is rootfs: you can neither pivot_root + rootfs, nor unmount it. Instead delete everything out of rootfs to + free up the space (find -xdev / -exec rm '{}' ';'), overmount rootfs + with the new root (cd /newmount; mount --move . /; chroot .), attach + stdin/stdout/stderr to the new /dev/console, and exec the new init. + + Since this is a remarkably persnickity process (and involves deleting + commands before you can run them), the klibc package introduced a helper + program (utils/run_init.c) to do all this for you. Most other packages + (such as busybox) have named this command "switch_root". + +Populating initramfs: +--------------------- + +The 2.6 kernel build process always creates a gzipped cpio format initramfs +archive and links it into the resulting kernel binary. By default, this +archive is empty (consuming 134 bytes on x86). The config option +CONFIG_INITRAMFS_SOURCE (for some reason buried under devices->block devices +in menuconfig, and living in usr/Kconfig) can be used to specify a source for +the initramfs archive, which will automatically be incorporated into the +resulting binary. This option can point to an existing gzipped cpio archive, a +directory containing files to be archived, or a text file specification such +as the following example: + + dir /dev 755 0 0 + nod /dev/console 644 0 0 c 5 1 + nod /dev/loop0 644 0 0 b 7 0 + dir /bin 755 1000 1000 + slink /bin/sh busybox 777 0 0 + file /bin/busybox initramfs/busybox 755 0 0 + dir /proc 755 0 0 + dir /sys 755 0 0 + dir /mnt 755 0 0 + file /init initramfs/init.sh 755 0 0 + +One advantage of the text file is that root access is not required to +set permissions or create device nodes in the new archive. (Note that those +two example "file" entries expect to find files named "init.sh" and "busybox" in +a directory called "initramfs", under the linux-2.6.* directory. See +Documentation/early-userspace/README for more details.) + +If you don't already understand what shared libraries, devices, and paths +you need to get a minimal root filesystem up and running, here are some +references: +http://www.tldp.org/HOWTO/Bootdisk-HOWTO/ +http://www.tldp.org/HOWTO/From-PowerUp-To-Bash-Prompt-HOWTO.html +http://www.linuxfromscratch.org/lfs/view/stable/ + +The "klibc" package (http://www.kernel.org/pub/linux/libs/klibc) is +designed to be a tiny C library to statically link early userspace +code against, along with some related utilities. It is BSD licensed. + +I use uClibc (http://www.uclibc.org) and busybox (http://www.busybox.net) +myself. These are LGPL and GPL, respectively. + +In theory you could use glibc, but that's not well suited for small embedded +uses like this. (A "hello world" program statically linked against glibc is +over 400k. With uClibc it's 7k. Also note that glibc dlopens libnss to do +name lookups, even when otherwise statically linked.) + +Future directions: +------------------ + +Today (2.6.14), initramfs is always compiled in, but not always used. The +kernel falls back to legacy boot code that is reached only if initramfs does +not contain an /init program. The fallback is legacy code, there to ensure a +smooth transition and allowing early boot functionality to gradually move to +"early userspace" (I.E. initramfs). + +The move to early userspace is necessary because finding and mounting the real +root device is complex. Root partitions can span multiple devices (raid or +separate journal). They can be out on the network (requiring dhcp, setting a +specific mac address, logging into a server, etc). They can live on removable +media, with dynamically allocated major/minor numbers and persistent naming +issues requiring a full udev implementation to sort out. They can be +compressed, encrypted, copy-on-write, loopback mounted, strangely partitioned, +and so on. + +This kind of complexity (which inevitably includes policy) is rightly handled +in userspace. Both klibc and busybox/uClibc are working on simple initramfs +packages to drop into a kernel build, and when standard solutions are ready +and widely deployed, the kernel's legacy early boot code will become obsolete +and a candidate for the feature removal schedule. + +But that's a while off yet. -- cgit v1.2.3 From d44e0780bcc47c9b8851099c0dfc1dda3c9db5a9 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 7 Nov 2005 01:01:10 -0800 Subject: [PATCH] kernel-doc: fix warnings in vmalloc.c Fix new kernel-doc errors in vmalloc.c. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmalloc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 54a90e83cb3..729eb3eec75 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -457,7 +457,7 @@ void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask, pgprot_t prot) * @size: allocation size * @gfp_mask: flags for the page level allocator * @prot: protection mask for the allocated pages - * @node node to use for allocation or -1 + * @node: node to use for allocation or -1 * * Allocate enough pages to cover @size from the page level * allocator with @gfp_mask flags. Map them into contiguous @@ -507,7 +507,7 @@ EXPORT_SYMBOL(vmalloc); * vmalloc_node - allocate memory on a specific node * * @size: allocation size - * @node; numa node + * @node: numa node * * Allocate enough pages to cover @size from the page level * allocator and map them into contiguous kernel virtual space. -- cgit v1.2.3 From 9e173c031a7542b1f66b6da853772e5de1804399 Mon Sep 17 00:00:00 2001 From: Nishanth Aravamudan Date: Mon, 7 Nov 2005 01:01:11 -0800 Subject: [PATCH] ia64: fix-up schedule_timeout() usage Use schedule_timeout_interruptible() instead of set_current_state()/schedule_timeout() to reduce kernel size. Signed-off-by: Nishanth Aravamudan Cc: "Luck, Tony" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ia64/hp/sim/simserial.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index b42ec37be51..19ee635eeb7 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -642,10 +642,8 @@ static void rs_close(struct tty_struct *tty, struct file * filp) info->event = 0; info->tty = 0; if (info->blocked_open) { - if (info->close_delay) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(info->close_delay); - } + if (info->close_delay) + schedule_timeout_interruptible(info->close_delay); wake_up_interruptible(&info->open_wait); } info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); -- cgit v1.2.3 From 28faa4298ec069d1de4f54597f963be8ef35e706 Mon Sep 17 00:00:00 2001 From: Nishanth Aravamudan Date: Mon, 7 Nov 2005 01:01:12 -0800 Subject: [PATCH] m68k: fix-up schedule_timeout() usage Use schedule_timeout_interruptible() instead of set_current_state()/schedule_timeout() to reduce kernel size. Signed-off-by: Nishanth Aravamudan Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/m68k/atari/time.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c index 6df7fb60dfe..e79bbc94216 100644 --- a/arch/m68k/atari/time.c +++ b/arch/m68k/atari/time.c @@ -212,10 +212,8 @@ int atari_tt_hwclk( int op, struct rtc_time *t ) * additionally the RTC_SET bit is set to prevent an update cycle. */ - while( RTC_READ(RTC_FREQ_SELECT) & RTC_UIP ) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HWCLK_POLL_INTERVAL); - } + while( RTC_READ(RTC_FREQ_SELECT) & RTC_UIP ) + schedule_timeout_interruptible(HWCLK_POLL_INTERVAL); local_irq_save(flags); RTC_WRITE( RTC_CONTROL, ctrl | RTC_SET ); -- cgit v1.2.3 From 8f09f4a25a927080e1fa1331735c3d1b5664866b Mon Sep 17 00:00:00 2001 From: Nishanth Aravamudan Date: Mon, 7 Nov 2005 01:01:13 -0800 Subject: [PATCH] ppc: fix-up schedule_timeout() usage Use schedule_timeout_interruptible() instead of set_current_state()/schedule_timeout() to reduce kernel size. Also use human-time conversion functions instead of hard-coded HZ division to avoid rounding errors. Signed-off-by: Nishanth Aravamudan Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/4xx_io/serial_sicc.c | 17 +++++++---------- arch/ppc/8260_io/fcc_enet.c | 3 +-- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/arch/ppc/4xx_io/serial_sicc.c b/arch/ppc/4xx_io/serial_sicc.c index e95c48d5757..84d96b857e4 100644 --- a/arch/ppc/4xx_io/serial_sicc.c +++ b/arch/ppc/4xx_io/serial_sicc.c @@ -1145,8 +1145,8 @@ static int set_serial_info(struct SICC_info *info, info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) | (info->flags & ASYNC_INTERNAL_FLAGS)); state->custom_divisor = new_serial.custom_divisor; - state->close_delay = new_serial.close_delay * HZ / 100; - state->closing_wait = new_serial.closing_wait * HZ / 100; + state->close_delay = msecs_to_jiffies(10 * new_serial.close_delay); + state->closing_wait = msecs_to_jiffies(10 * new_serial.closing_wait); info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; port->fifosize = new_serial.xmit_fifo_size; @@ -1465,10 +1465,8 @@ static void siccuart_close(struct tty_struct *tty, struct file *filp) info->event = 0; info->tty = NULL; if (info->blocked_open) { - if (info->state->close_delay) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(info->state->close_delay); - } + if (info->state->close_delay) + schedule_timeout_interruptible(info->state->close_delay); wake_up_interruptible(&info->open_wait); } info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); @@ -1496,7 +1494,7 @@ static void siccuart_wait_until_sent(struct tty_struct *tty, int timeout) * Note: we have to use pretty tight timings here to satisfy * the NIST-PCTS. */ - char_time = (info->timeout - HZ/50) / info->port->fifosize; + char_time = (info->timeout - msecs_to_jiffies(20)) / info->port->fifosize; char_time = char_time / 5; if (char_time == 0) char_time = 1; @@ -1521,8 +1519,7 @@ static void siccuart_wait_until_sent(struct tty_struct *tty, int timeout) tty->index, jiffies, expire, char_time); while ((readb(info->port->uart_base + BL_SICC_LSR) & _LSR_TX_ALL) != _LSR_TX_ALL) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(char_time); + schedule_timeout_interruptible(char_time); if (signal_pending(current)) break; if (timeout && time_after(jiffies, expire)) @@ -1773,7 +1770,7 @@ int __init siccuart_init(void) for (i = 0; i < SERIAL_SICC_NR; i++) { struct SICC_state *state = sicc_state + i; state->line = i; - state->close_delay = 5 * HZ / 10; + state->close_delay = msecs_to_jiffies(500); state->closing_wait = 30 * HZ; spin_lock_init(&state->sicc_lock); } diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c index 2086c6ad114..4edeede9ccf 100644 --- a/arch/ppc/8260_io/fcc_enet.c +++ b/arch/ppc/8260_io/fcc_enet.c @@ -1309,8 +1309,7 @@ static void mii_dm9161_wait(uint mii_reg, struct net_device *dev) /* Davicom takes a bit to come up after a reset, * so wait here for a bit */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(timeout); + schedule_timeout_uninterruptible(timeout); } static phy_info_t phy_info_dm9161 = { -- cgit v1.2.3 From bc874d174b224c016adac85fc9dd6da1161ffc57 Mon Sep 17 00:00:00 2001 From: Nishanth Aravamudan Date: Mon, 7 Nov 2005 01:01:14 -0800 Subject: [PATCH] um: fix-up schedule_timeout() usage Use schedule_timeout_interruptible() instead of set_current_state()/schedule_timeout() to reduce kernel size. Signed-off-by: Nishanth Aravamudan Acked-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/random.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c index f9e22198e01..ba471f5864a 100644 --- a/arch/um/drivers/random.c +++ b/arch/um/drivers/random.c @@ -58,10 +58,8 @@ static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size, if (filp->f_flags & O_NONBLOCK) return ret ? : -EAGAIN; - if(need_resched()){ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - } + if(need_resched()) + schedule_timeout_interruptible(1); } else return n; if (signal_pending (current)) -- cgit v1.2.3 From 01a527ec7c62efea601a39f0cd8e6a8517259014 Mon Sep 17 00:00:00 2001 From: Nishanth Aravamudan Date: Mon, 7 Nov 2005 01:01:14 -0800 Subject: [PATCH] drivers/acpi: fix-up schedule_timeout() usage Use schedule_timeout_interruptible() instead of set_current_state()/schedule_timeout() to reduce kernel size. Also use msecs_to_jiffies() instead of direct HZ division to avoid rounding errors. Signed-off-by: Nishanth Aravamudan Cc: "Brown, Len" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/acpi/osl.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index d528c750a38..e3cd0b16031 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -313,8 +313,7 @@ acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler) void acpi_os_sleep(acpi_integer ms) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(((signed long)ms * HZ) / 1000); + schedule_timeout_interruptible(msecs_to_jiffies(ms)); } EXPORT_SYMBOL(acpi_os_sleep); @@ -838,8 +837,7 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout) ret = down_trylock(sem); for (i = timeout; (i > 0 && ret < 0); i -= quantum_ms) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); + schedule_timeout_interruptible(1); ret = down_trylock(sem); } -- cgit v1.2.3 From 4de4ebc6d83de6d9739fa24e49ae4a305d5d1268 Mon Sep 17 00:00:00 2001 From: Nishanth Aravamudan Date: Mon, 7 Nov 2005 01:01:15 -0800 Subject: [PATCH] ieee1394: fix-up schedule_timeout() usage Use schedule_timeout_interruptible() instead of set_current_state()/schedule_timeout() to reduce kernel size. Signed-off-by: Nishanth Aravamudan Cc: Ben Collins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ieee1394/amdtp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c index e8e28569a66..75897509c40 100644 --- a/drivers/ieee1394/amdtp.c +++ b/drivers/ieee1394/amdtp.c @@ -320,8 +320,7 @@ static void ohci1394_stop_it_ctx(struct ti_ohci *ohci, int ctx, int synchronous) if ((control & OHCI1394_CONTEXT_ACTIVE) == 0) break; - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_interruptible(1); } } } -- cgit v1.2.3 From 24763c48a3c9cdf0a138038b51a7fca65859cd78 Mon Sep 17 00:00:00 2001 From: Nishanth Aravamudan Date: Mon, 7 Nov 2005 01:01:16 -0800 Subject: [PATCH] isdn: fix-up schedule_timeout() usage Use schedule_timeout_interruptible() instead of set_current_state()/schedule_timeout() to reduce kernel size. Signed-off-by: Nishanth Aravamudan Cc: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/i4l/isdn_tty.c | 3 +-- drivers/isdn/icn/icn.c | 3 +-- drivers/isdn/isdnloop/isdnloop.c | 9 +++------ drivers/isdn/sc/init.c | 3 +-- drivers/isdn/sc/message.c | 3 +-- 5 files changed, 7 insertions(+), 14 deletions(-) diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index b37ef1f06b3..356ee485be4 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1721,8 +1721,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) */ timeout = jiffies + HZ; while (!(info->lsr & UART_LSR_TEMT)) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(20); + schedule_timeout_interruptible(20); if (time_after(jiffies,timeout)) break; } diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c index 386df71eee7..6649f8bc995 100644 --- a/drivers/isdn/icn/icn.c +++ b/drivers/isdn/icn/icn.c @@ -947,8 +947,7 @@ icn_loadproto(u_char __user * buffer, icn_card * card) icn_maprelease_channel(card, 0); return -EIO; } - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(10); + schedule_timeout_interruptible(10); } } writeb(0x20, &sbuf_n); diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index 14e1f8fbc61..33d33970041 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c @@ -1161,12 +1161,9 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card) if (a) { if (!card->leased) { card->leased = 1; - while (card->ptype == ISDN_PTYPE_UNKNOWN) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(10); - } - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(10); + while (card->ptype == ISDN_PTYPE_UNKNOWN) + schedule_timeout_interruptible(10); + schedule_timeout_interruptible(10); sprintf(cbuf, "00;FV2ON\n01;EAZ1\n02;EAZ2\n"); i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); printk(KERN_INFO diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c index 1ebed041672..62b7acfad8a 100644 --- a/drivers/isdn/sc/init.c +++ b/drivers/isdn/sc/init.c @@ -529,8 +529,7 @@ static int identify_board(unsigned long rambase, unsigned int iobase) */ x = 0; while((inb(iobase + FIFOSTAT_OFFSET) & RF_HAS_DATA) && x < 100) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_interruptible(1); x++; } if(x == 100) { diff --git a/drivers/isdn/sc/message.c b/drivers/isdn/sc/message.c index ca204da3257..0a0fe6b8039 100644 --- a/drivers/isdn/sc/message.c +++ b/drivers/isdn/sc/message.c @@ -208,8 +208,7 @@ int send_and_receive(int card, tries = 0; /* wait for the response */ while (tries < timeout) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_interruptible(1); pr_debug("SAR waiting..\n"); -- cgit v1.2.3 From 12621a163b78d775a95dea60357bc90e58e1a3aa Mon Sep 17 00:00:00 2001 From: Nishanth Aravamudan Date: Mon, 7 Nov 2005 01:01:17 -0800 Subject: [PATCH] drivers/macintosh: fix-up schedule_timeout() usage Use schedule_timeout_interruptible() instead of set_current_state()/schedule_timeout() to reduce kernel size. Signed-off-by: Nishanth Aravamudan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/macintosh/therm_pm72.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c index cc507ceef15..3fc8cdd94c3 100644 --- a/drivers/macintosh/therm_pm72.c +++ b/drivers/macintosh/therm_pm72.c @@ -1678,10 +1678,9 @@ static int main_control_loop(void *x) } // FIXME: Deal with signals - set_current_state(TASK_INTERRUPTIBLE); elapsed = jiffies - start; if (elapsed < HZ) - schedule_timeout(HZ - elapsed); + schedule_timeout_interruptible(HZ - elapsed); } out: -- cgit v1.2.3 From 66c006a55137cc51f8761549e2024a7593180d27 Mon Sep 17 00:00:00 2001 From: Nishanth Aravamudan Date: Mon, 7 Nov 2005 01:01:17 -0800 Subject: [PATCH] drivers/md: fix-up schedule_timeout() usage Use schedule_timeout_interruptible() instead of set_current_state()/schedule_timeout() to reduce kernel size. Signed-off-by: Nishanth Aravamudan Cc: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/raid5.c | 3 +-- drivers/md/raid6main.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 6497295ebfb..1223e98ecd7 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1587,8 +1587,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i /* make sure we don't swamp the stripe cache if someone else * is trying to get access */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 0); spin_lock(&sh->lock); diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c index 6437a95ffc1..77578694770 100644 --- a/drivers/md/raid6main.c +++ b/drivers/md/raid6main.c @@ -1746,8 +1746,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i /* make sure we don't swamp the stripe cache if someone else * is trying to get access */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 0); spin_lock(&sh->lock); -- cgit v1.2.3 From 8b93ec77a6423cc57189561567ee41fa7fa1f5b6 Mon Sep 17 00:00:00 2001 From: Nishanth Aravamudan Date: Mon, 7 Nov 2005 01:01:18 -0800 Subject: [PATCH] drivers/media: fix-up schedule_timeout() usage Use schedule_timeout_interruptible() instead of set_current_state()/schedule_timeout() to reduce kernel size. Signed-off-by: Nishanth Aravamudan Cc: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/msp3400.c | 4 ++-- drivers/media/video/saa7134/saa7134-tvaudio.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index 262890cb20a..e75e7948fd9 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -741,8 +741,8 @@ static int msp34xx_sleep(struct msp3400c *msp, int timeout) set_current_state(TASK_INTERRUPTIBLE); schedule(); } else { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(msecs_to_jiffies(timeout)); + schedule_timeout_interruptible + (msecs_to_jiffies(timeout)); } } diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index badf2f9e307..61a2d6b50ee 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -342,8 +342,8 @@ static int tvaudio_sleep(struct saa7134_dev *dev, int timeout) set_current_state(TASK_INTERRUPTIBLE); schedule(); } else { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(msecs_to_jiffies(timeout)); + schedule_timeout_interruptible + (msecs_to_jiffies(timeout)); } } remove_wait_queue(&dev->thread.wq, &wait); -- cgit v1.2.3 From 6521018d4bf9522b4de47254ea15e8c1be1ec00f Mon Sep 17 00:00:00 2001 From: Nishanth Aravamudan Date: Mon, 7 Nov 2005 01:01:19 -0800 Subject: [PATCH] message: fix-up schedule_timeout() usage Use schedule_timeout_interruptible() instead of set_current_state()/schedule_timeout() to reduce kernel size. Signed-off-by: Nishanth Aravamudan Cc: "Moore, Eric Dean" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/message/fusion/mptlan.c | 10 ++++------ drivers/message/fusion/mptscsih.c | 6 ++---- drivers/message/i2o/iop.c | 15 +++++---------- 3 files changed, 11 insertions(+), 20 deletions(-) diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index ed3c891e388..014085d8ec8 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c @@ -511,7 +511,7 @@ mpt_lan_close(struct net_device *dev) { struct mpt_lan_priv *priv = netdev_priv(dev); MPT_ADAPTER *mpt_dev = priv->mpt_dev; - unsigned int timeout; + unsigned long timeout; int i; dlprintk((KERN_INFO MYNAM ": mpt_lan_close called\n")); @@ -526,11 +526,9 @@ mpt_lan_close(struct net_device *dev) mpt_lan_reset(dev); - timeout = 2 * HZ; - while (atomic_read(&priv->buckets_out) && --timeout) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } + timeout = jiffies + 2 * HZ; + while (atomic_read(&priv->buckets_out) && time_before(jiffies, timeout)) + schedule_timeout_interruptible(1); for (i = 0; i < priv->max_buckets_out; i++) { if (priv->RcvCtl[i].skb != NULL) { diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 5cb07eb224d..4330ed0ceda 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1013,10 +1013,8 @@ mptscsih_remove(struct pci_dev *pdev) spin_lock_irqsave(&dvtaskQ_lock, flags); if (dvtaskQ_active) { spin_unlock_irqrestore(&dvtaskQ_lock, flags); - while(dvtaskQ_active && --count) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } + while(dvtaskQ_active && --count) + schedule_timeout_interruptible(1); } else { spin_unlock_irqrestore(&dvtaskQ_lock, flags); } diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c index 61b837de4b6..4eb53258842 100644 --- a/drivers/message/i2o/iop.c +++ b/drivers/message/i2o/iop.c @@ -93,8 +93,7 @@ u32 i2o_msg_get_wait(struct i2o_controller *c, c->name); return I2O_QUEUE_EMPTY; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } return m; @@ -485,8 +484,7 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c) osm_warn("%s: Timeout Initializing\n", c->name); return -ETIMEDOUT; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } m = c->out_queue.phys; @@ -548,8 +546,7 @@ static int i2o_iop_reset(struct i2o_controller *c) if (time_after(jiffies, timeout)) break; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } switch (*status) { @@ -577,8 +574,7 @@ static int i2o_iop_reset(struct i2o_controller *c) rc = -ETIMEDOUT; goto exit; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET); } @@ -989,8 +985,7 @@ int i2o_status_get(struct i2o_controller *c) return -ETIMEDOUT; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } #ifdef DEBUG -- cgit v1.2.3 From a9a3047dd8ae43ff24caae5ec733a93df129568e Mon Sep 17 00:00:00 2001 From: Nishanth Aravamudan Date: Mon, 7 Nov 2005 01:01:20 -0800 Subject: [PATCH] drivers/scsi: fix-up schedule_timeout() usage Use schedule_timeout_uninterruptible() instead of set_current_state()/schedule_timeout() to reduce kernel size. Signed-off-by: Nishanth Aravamudan Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/NCR5380.c | 5 +---- drivers/scsi/aacraid/rkt.c | 6 ++---- drivers/scsi/aacraid/rx.c | 6 ++---- drivers/scsi/aacraid/sa.c | 6 ++---- drivers/scsi/dpt_i2o.c | 34 +++++++++++----------------------- drivers/scsi/lpfc/lpfc_scsi.c | 12 ++++-------- drivers/scsi/osst.c | 9 +++------ 7 files changed, 25 insertions(+), 53 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index cc9ecb35b41..cba9655d0f1 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -606,10 +606,7 @@ static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible) NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL); while (probe_irq == SCSI_IRQ_NONE && time_before(jiffies, timeout)) - { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); - } + schedule_timeout_uninterruptible(1); NCR5380_write(SELECT_ENABLE_REG, 0); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c index fc4c73c2a6a..e9b775d6bec 100644 --- a/drivers/scsi/aacraid/rkt.c +++ b/drivers/scsi/aacraid/rkt.c @@ -183,8 +183,7 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, /* * Yield the processor in case we are slow */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } if (ok != 1) { /* @@ -452,8 +451,7 @@ int aac_rkt_init(struct aac_dev *dev) dev->name, instance, status); goto error_iounmap; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } if (request_irq(dev->scsi_host_ptr->irq, aac_rkt_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev)<0) { diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index da99046e539..6998bc877dd 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -183,8 +183,7 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, /* * Yield the processor in case we are slow */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } if (ok != 1) { /* @@ -452,8 +451,7 @@ int aac_rx_init(struct aac_dev *dev) dev->name, instance, status); goto error_iounmap; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } if (request_irq(dev->scsi_host_ptr->irq, aac_rx_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev)<0) { diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c index 8b959620916..466f05cfbf0 100644 --- a/drivers/scsi/aacraid/sa.c +++ b/drivers/scsi/aacraid/sa.c @@ -189,8 +189,7 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command, ok = 1; break; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } if (ok != 1) @@ -325,8 +324,7 @@ int aac_sa_init(struct aac_dev *dev) name, instance, status); goto error_iounmap; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } if (request_irq(dev->scsi_host_ptr->irq, aac_sa_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev ) < 0) { diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 7235f94f119..46d5571ec55 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -1218,8 +1218,7 @@ static s32 adpt_i2o_post_this(adpt_hba* pHba, u32* data, int len) printk(KERN_WARNING"dpti%d: Timeout waiting for message frame!\n", pHba->unit); return -ETIMEDOUT; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } while(m == EMPTY_QUEUE); msg = pHba->msg_addr_virt + m; @@ -1294,8 +1293,7 @@ static s32 adpt_i2o_reset_hba(adpt_hba* pHba) printk(KERN_WARNING"Timeout waiting for message!\n"); return -ETIMEDOUT; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } while (m == EMPTY_QUEUE); status = (u8*)kmalloc(4, GFP_KERNEL|ADDR32); @@ -1327,8 +1325,7 @@ static s32 adpt_i2o_reset_hba(adpt_hba* pHba) return -ETIMEDOUT; } rmb(); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } if(*status == 0x01 /*I2O_EXEC_IOP_RESET_IN_PROGRESS*/) { @@ -1345,8 +1342,7 @@ static s32 adpt_i2o_reset_hba(adpt_hba* pHba) printk(KERN_ERR "%s:Timeout waiting for IOP Reset.\n",pHba->name); return -ETIMEDOUT; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } while (m == EMPTY_QUEUE); // Flush the offset adpt_send_nop(pHba, m); @@ -1917,11 +1913,8 @@ static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd, return -ENXIO; } - while((volatile u32) pHba->state & DPTI_STATE_RESET ) { - set_task_state(current,TASK_UNINTERRUPTIBLE); - schedule_timeout(2); - - } + while((volatile u32) pHba->state & DPTI_STATE_RESET ) + schedule_timeout_uninterruptible(2); switch (cmd) { // TODO: handle 3 cases @@ -2635,8 +2628,7 @@ static s32 adpt_send_nop(adpt_hba*pHba,u32 m) printk(KERN_ERR "%s: Timeout waiting for message frame!\n",pHba->name); return 2; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } msg = (u32 __iomem *)(pHba->msg_addr_virt + m); writel( THREE_WORD_MSG_SIZE | SGL_OFFSET_0,&msg[0]); @@ -2670,8 +2662,7 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba) printk(KERN_WARNING"%s: Timeout waiting for message frame\n",pHba->name); return -ETIMEDOUT; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } while(m == EMPTY_QUEUE); msg=(u32 __iomem *)(pHba->msg_addr_virt+m); @@ -2709,8 +2700,7 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba) printk(KERN_WARNING"%s: Timeout Initializing\n",pHba->name); return -ETIMEDOUT; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } while (1); // If the command was successful, fill the fifo with our reply @@ -2788,8 +2778,7 @@ static s32 adpt_i2o_status_get(adpt_hba* pHba) pHba->name); return -ETIMEDOUT; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } while(m==EMPTY_QUEUE); @@ -2816,8 +2805,7 @@ static s32 adpt_i2o_status_get(adpt_hba* pHba) return -ETIMEDOUT; } rmb(); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } // Set up our number of outbound and inbound messages diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index c34d3cf4f19..c63275e66e2 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -825,8 +825,7 @@ __lpfc_abort_handler(struct scsi_cmnd *cmnd) while (lpfc_cmd->pCmd == cmnd) { spin_unlock_irq(phba->host->host_lock); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(LPFC_ABORT_WAIT*HZ); + schedule_timeout_uninterruptible(LPFC_ABORT_WAIT*HZ); spin_lock_irq(phba->host->host_lock); if (++loop_count > (2 * phba->cfg_nodev_tmo)/LPFC_ABORT_WAIT) @@ -885,8 +884,7 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) if (pnode->nlp_state != NLP_STE_MAPPED_NODE) { spin_unlock_irq(phba->host->host_lock); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout( HZ/2); + schedule_timeout_uninterruptible(msecs_to_jiffies(500)); spin_lock_irq(phba->host->host_lock); } if ((pnode) && (pnode->nlp_state == NLP_STE_MAPPED_NODE)) @@ -939,8 +937,7 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) cmnd->device->id, cmnd->device->lun, LPFC_CTX_LUN))) { spin_unlock_irq(phba->host->host_lock); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(LPFC_RESET_WAIT*HZ); + schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ); spin_lock_irq(phba->host->host_lock); if (++loopcnt @@ -1038,8 +1035,7 @@ __lpfc_reset_bus_handler(struct scsi_cmnd *cmnd) &phba->sli.ring[phba->sli.fcp_ring], 0, 0, LPFC_CTX_HOST))) { spin_unlock_irq(phba->host->host_lock); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(LPFC_RESET_WAIT*HZ); + schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ); spin_lock_irq(phba->host->host_lock); if (++loopcnt diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 1cf11c3322f..d9946bd9549 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -862,8 +862,7 @@ static int osst_recover_wait_frame(struct osst_tape * STp, struct scsi_request * retval = osst_write_error_recovery(STp, aSRpnt, 0); break; } - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout (HZ / OSST_POLL_PER_SEC); + schedule_timeout_interruptible(HZ / OSST_POLL_PER_SEC); STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24; memset(cmd, 0, MAX_COMMAND_SIZE); @@ -1558,8 +1557,7 @@ static int osst_reposition_and_retry(struct osst_tape * STp, struct scsi_request osst_set_frame_position(STp, aSRpnt, frame + skip, 1); flag = 0; attempts--; - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ / 10); + schedule_timeout_interruptible(msecs_to_jiffies(100)); } if (osst_get_frame_position(STp, aSRpnt) < 0) { /* additional write error */ #if DEBUG @@ -1620,8 +1618,7 @@ static int osst_reposition_and_retry(struct osst_tape * STp, struct scsi_request debugging = 0; } #endif - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ / 10); + schedule_timeout_interruptible(msecs_to_jiffies(100)); } printk(KERN_ERR "%s:E: Failed to find valid tape media\n", name); #if DEBUG -- cgit v1.2.3 From 3c76bc5bfda308aa42d5f42fde8dc1931e45e8a6 Mon Sep 17 00:00:00 2001 From: Nishanth Aravamudan Date: Mon, 7 Nov 2005 01:01:21 -0800 Subject: [PATCH] serial: fix-up schedule_timeout() usage Use schedule_timeout_uninterruptible() instead of set_current_state()/schedule_timeout() to reduce kernel size. Signed-off-by: Nishanth Aravamudan Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/crisv10.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 40d3e7139cf..08c42c00018 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c @@ -4416,10 +4416,8 @@ rs_close(struct tty_struct *tty, struct file * filp) info->event = 0; info->tty = 0; if (info->blocked_open) { - if (info->close_delay) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(info->close_delay); - } + if (info->close_delay) + schedule_timeout_interruptible(info->close_delay); wake_up_interruptible(&info->open_wait); } info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); @@ -4469,8 +4467,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) while (info->xmit.head != info->xmit.tail || /* More in send queue */ (*info->ostatusadr & 0x007f) || /* more in FIFO */ (elapsed_usec < 2*info->char_time_usec)) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_interruptible(1); if (signal_pending(current)) break; if (timeout && time_after(jiffies, orig_jiffies + timeout)) -- cgit v1.2.3 From 5c857eeb0c18adaa7432afb519db066a6349687f Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Mon, 7 Nov 2005 01:01:22 -0800 Subject: [PATCH] drivers/cdrom: kmalloc + memset -> kzalloc conversion Signed-off-by: Deepak Saxena Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/cdrom/mcdx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c index b89420e6d70..a0b580c22d8 100644 --- a/drivers/cdrom/mcdx.c +++ b/drivers/cdrom/mcdx.c @@ -1085,7 +1085,7 @@ static int __init mcdx_init_drive(int drive) xtrace(INIT, "kmalloc space for stuffpt's\n"); xtrace(MALLOC, "init() malloc %d bytes\n", size); - if (!(stuffp = kmalloc(size, GFP_KERNEL))) { + if (!(stuffp = kzalloc(size, GFP_KERNEL))) { xwarn("init() malloc failed\n"); return 1; } @@ -1101,8 +1101,6 @@ static int __init mcdx_init_drive(int drive) sizeof(*stuffp), stuffp); /* set default values */ - memset(stuffp, 0, sizeof(*stuffp)); - stuffp->present = 0; /* this should be 0 already */ stuffp->toc = NULL; /* this should be NULL already */ -- cgit v1.2.3 From e66860cbda4a1880fa379bee17d6ab926e5cc58e Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Mon, 7 Nov 2005 01:01:22 -0800 Subject: [PATCH] drivers/dio: kmalloc + memset -> kzalloc conversion Signed-off-by: Deepak Saxena Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/dio/dio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/dio/dio.c b/drivers/dio/dio.c index a620f7d9ac8..17502d6efae 100644 --- a/drivers/dio/dio.c +++ b/drivers/dio/dio.c @@ -224,11 +224,10 @@ static int __init dio_init(void) set_fs(fs); /* Found a board, allocate it an entry in the list */ - dev = kmalloc(sizeof(struct dio_dev), GFP_KERNEL); + dev = kzalloc(sizeof(struct dio_dev), GFP_KERNEL); if (!dev) return 0; - memset(dev, 0, sizeof(struct dio_dev)); dev->bus = &dio_bus; dev->dev.parent = &dio_bus.dev; dev->dev.bus = &dio_bus_type; -- cgit v1.2.3 From 8ac5436ced2fd4eab3abe7cbc6d5a29881fa9ccb Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Mon, 7 Nov 2005 01:01:23 -0800 Subject: [PATCH] drivers/eisa: kmalloc + memset -> kzalloc conversion Signed-off-by: Deepak Saxena Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/eisa/eisa-bus.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c index 1937743c8e2..4196137e66d 100644 --- a/drivers/eisa/eisa-bus.c +++ b/drivers/eisa/eisa-bus.c @@ -281,13 +281,11 @@ static int __init eisa_probe (struct eisa_root_device *root) /* First try to get hold of slot 0. If there is no device * here, simply fail, unless root->force_probe is set. */ - if (!(edev = kmalloc (sizeof (*edev), GFP_KERNEL))) { + if (!(edev = kzalloc (sizeof (*edev), GFP_KERNEL))) { printk (KERN_ERR "EISA: Couldn't allocate mainboard slot\n"); return -ENOMEM; } - memset (edev, 0, sizeof (*edev)); - if (eisa_request_resources (root, edev, 0)) { printk (KERN_WARNING \ "EISA: Cannot allocate resource for mainboard\n"); @@ -317,13 +315,11 @@ static int __init eisa_probe (struct eisa_root_device *root) force_probe: for (c = 0, i = 1; i <= root->slots; i++) { - if (!(edev = kmalloc (sizeof (*edev), GFP_KERNEL))) { + if (!(edev = kzalloc (sizeof (*edev), GFP_KERNEL))) { printk (KERN_ERR "EISA: Out of memory for slot %d\n", i); continue; } - - memset (edev, 0, sizeof (*edev)); if (eisa_request_resources (root, edev, i)) { printk (KERN_WARNING \ -- cgit v1.2.3 From 49d0c6039dd36791cad36624e68bce5fe011bf12 Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Mon, 7 Nov 2005 01:01:24 -0800 Subject: [PATCH] drivers/fc4: kmalloc + memset -> kzalloc conversion Signed-off-by: Deepak Saxena Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/fc4/fc.c | 27 +++++++++------------------ drivers/fc4/soc.c | 3 +-- drivers/fc4/socal.c | 3 +-- 3 files changed, 11 insertions(+), 22 deletions(-) diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c index e4710d1d1f9..e375995a2e9 100644 --- a/drivers/fc4/fc.c +++ b/drivers/fc4/fc.c @@ -266,13 +266,12 @@ static void fcp_report_map_done(fc_channel *fc, int i, int status) printk ("FC: Bad magic from REPORT_AL_MAP on %s - %08x\n", fc->name, p->magic); fc->state = FC_STATE_OFFLINE; } else { - fc->posmap = (fcp_posmap *)kmalloc(sizeof(fcp_posmap)+p->len, GFP_KERNEL); + fc->posmap = (fcp_posmap *)kzalloc(sizeof(fcp_posmap)+p->len, GFP_KERNEL); if (!fc->posmap) { printk("FC: Not enough memory, offlining channel\n"); fc->state = FC_STATE_OFFLINE; } else { int k; - memset(fc->posmap, 0, sizeof(fcp_posmap)+p->len); /* FIXME: This is where SOCAL transfers our AL-PA. Keep it here till we found out what other cards do... */ fc->sid = (p->magic & 0xff); @@ -351,14 +350,12 @@ void fcp_register(fc_channel *fc, u8 type, int unregister) fc->dma_scsi_rsp = fc->dma_scsi_cmd + slots * sizeof (fcp_cmd); fc->scsi_bitmap_end = (slots + 63) & ~63; size = fc->scsi_bitmap_end / 8; - fc->scsi_bitmap = kmalloc (size, GFP_KERNEL); - memset (fc->scsi_bitmap, 0, size); + fc->scsi_bitmap = kzalloc (size, GFP_KERNEL); set_bit (0, fc->scsi_bitmap); for (i = fc->can_queue; i < fc->scsi_bitmap_end; i++) set_bit (i, fc->scsi_bitmap); fc->scsi_free = fc->can_queue; - fc->cmd_slots = (fcp_cmnd **)kmalloc(slots * sizeof(fcp_cmnd*), GFP_KERNEL); - memset(fc->cmd_slots, 0, slots * sizeof(fcp_cmnd*)); + fc->cmd_slots = (fcp_cmnd **)kzalloc(slots * sizeof(fcp_cmnd*), GFP_KERNEL); fc->abort_count = 0; } else { fc->scsi_name[0] = 0; @@ -541,12 +538,11 @@ int fcp_initialize(fc_channel *fcchain, int count) FCND(("fcp_inititialize %08lx\n", (long)fcp_init)) FCND(("fc_channels %08lx\n", (long)fc_channels)) FCND((" SID %d DID %d\n", fcchain->sid, fcchain->did)) - l = kmalloc(sizeof (ls) + count, GFP_KERNEL); + l = kzalloc(sizeof (ls) + count, GFP_KERNEL); if (!l) { printk ("FC: Cannot allocate memory for initialization\n"); return -ENOMEM; } - memset (l, 0, sizeof(ls) + count); l->magic = LSMAGIC; l->count = count; FCND(("FCP Init for %d channels\n", count)) @@ -555,8 +551,8 @@ int fcp_initialize(fc_channel *fcchain, int count) l->timer.function = fcp_login_timeout; l->timer.data = (unsigned long)l; atomic_set (&l->todo, count); - l->logi = kmalloc (count * 3 * sizeof(logi), GFP_KERNEL); - l->fcmds = kmalloc (count * sizeof(fcp_cmnd), GFP_KERNEL); + l->logi = kzalloc (count * 3 * sizeof(logi), GFP_KERNEL); + l->fcmds = kzalloc (count * sizeof(fcp_cmnd), GFP_KERNEL); if (!l->logi || !l->fcmds) { if (l->logi) kfree (l->logi); if (l->fcmds) kfree (l->fcmds); @@ -564,8 +560,6 @@ int fcp_initialize(fc_channel *fcchain, int count) printk ("FC: Cannot allocate DMA memory for initialization\n"); return -ENOMEM; } - memset (l->logi, 0, count * 3 * sizeof(logi)); - memset (l->fcmds, 0, count * sizeof(fcp_cmnd)); for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) { fc->state = FC_STATE_UNINITED; fc->rst_pkt = NULL; /* kmalloc when first used */ @@ -678,13 +672,12 @@ int fcp_forceoffline(fc_channel *fcchain, int count) l.timer.function = fcp_login_timeout; l.timer.data = (unsigned long)&l; atomic_set (&l.todo, count); - l.fcmds = kmalloc (count * sizeof(fcp_cmnd), GFP_KERNEL); + l.fcmds = kzalloc (count * sizeof(fcp_cmnd), GFP_KERNEL); if (!l.fcmds) { kfree (l.fcmds); printk ("FC: Cannot allocate memory for forcing offline\n"); return -ENOMEM; } - memset (l.fcmds, 0, count * sizeof(fcp_cmnd)); FCND(("Initializing OFFLINE packets\n")) for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) { fc->state = FC_STATE_UNINITED; @@ -1114,9 +1107,8 @@ int fc_do_plogi(fc_channel *fc, unsigned char alpa, fc_wwn *node, fc_wwn *nport) logi *l; int status; - l = (logi *)kmalloc(2 * sizeof(logi), GFP_KERNEL); + l = (logi *)kzalloc(2 * sizeof(logi), GFP_KERNEL); if (!l) return -ENOMEM; - memset(l, 0, 2 * sizeof(logi)); l->code = LS_PLOGI; memcpy (&l->nport_wwn, &fc->wwn_nport, sizeof(fc_wwn)); memcpy (&l->node_wwn, &fc->wwn_node, sizeof(fc_wwn)); @@ -1149,9 +1141,8 @@ int fc_do_prli(fc_channel *fc, unsigned char alpa) prli *p; int status; - p = (prli *)kmalloc(2 * sizeof(prli), GFP_KERNEL); + p = (prli *)kzalloc(2 * sizeof(prli), GFP_KERNEL); if (!p) return -ENOMEM; - memset(p, 0, 2 * sizeof(prli)); p->code = LS_PRLI; p->params[0] = 0x08002000; p->params[3] = 0x00000022; diff --git a/drivers/fc4/soc.c b/drivers/fc4/soc.c index 247b4630277..ec1f94738c5 100644 --- a/drivers/fc4/soc.c +++ b/drivers/fc4/soc.c @@ -556,10 +556,9 @@ static inline void soc_init(struct sbus_dev *sdev, int no) int size, i; int irq; - s = kmalloc (sizeof (struct soc), GFP_KERNEL); + s = kzalloc (sizeof (struct soc), GFP_KERNEL); if (s == NULL) return; - memset (s, 0, sizeof(struct soc)); spin_lock_init(&s->lock); s->soc_no = no; diff --git a/drivers/fc4/socal.c b/drivers/fc4/socal.c index b2377dbd84a..922e9613b2c 100644 --- a/drivers/fc4/socal.c +++ b/drivers/fc4/socal.c @@ -665,9 +665,8 @@ static inline void socal_init(struct sbus_dev *sdev, int no) int size, i; int irq, node; - s = kmalloc (sizeof (struct socal), GFP_KERNEL); + s = kzalloc (sizeof (struct socal), GFP_KERNEL); if (!s) return; - memset (s, 0, sizeof(struct socal)); spin_lock_init(&s->lock); s->socal_no = no; -- cgit v1.2.3 From 9c2153844d72ac92b6da0ee42f7f81fb0aa91f8a Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Mon, 7 Nov 2005 01:01:24 -0800 Subject: [PATCH] drivers/firmware: kmalloc + memset -> kzalloc conversion Signed-off-by: Deepak Saxena Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/firmware/edd.c | 3 +-- drivers/firmware/efivars.c | 10 +++------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c index 6996476669f..b4502ed6579 100644 --- a/drivers/firmware/edd.c +++ b/drivers/firmware/edd.c @@ -715,7 +715,6 @@ edd_device_register(struct edd_device *edev, int i) if (!edev) return 1; - memset(edev, 0, sizeof (*edev)); edd_dev_set_info(edev, i); kobject_set_name(&edev->kobj, "int13_dev%02x", 0x80 + i); @@ -756,7 +755,7 @@ edd_init(void) return rc; for (i = 0; i < edd_num_devices() && !rc; i++) { - edev = kmalloc(sizeof (*edev), GFP_KERNEL); + edev = kzalloc(sizeof (*edev), GFP_KERNEL); if (!edev) return -ENOMEM; diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 33b17c6a46f..bda5bce681b 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c @@ -614,16 +614,14 @@ efivar_create_sysfs_entry(unsigned long variable_name_size, char *short_name; struct efivar_entry *new_efivar; - short_name = kmalloc(short_name_size + 1, GFP_KERNEL); - new_efivar = kmalloc(sizeof(struct efivar_entry), GFP_KERNEL); + short_name = kzalloc(short_name_size + 1, GFP_KERNEL); + new_efivar = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL); if (!short_name || !new_efivar) { kfree(short_name); kfree(new_efivar); return 1; } - memset(short_name, 0, short_name_size+1); - memset(new_efivar, 0, sizeof(struct efivar_entry)); memcpy(new_efivar->var.VariableName, variable_name, variable_name_size); @@ -674,14 +672,12 @@ efivars_init(void) if (!efi_enabled) return -ENODEV; - variable_name = kmalloc(variable_name_size, GFP_KERNEL); + variable_name = kzalloc(variable_name_size, GFP_KERNEL); if (!variable_name) { printk(KERN_ERR "efivars: Memory allocation failed.\n"); return -ENOMEM; } - memset(variable_name, 0, variable_name_size); - printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION, EFIVARS_DATE); -- cgit v1.2.3 From f5e3c2faa20615e900ab26bd957f898400435924 Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Mon, 7 Nov 2005 01:01:25 -0800 Subject: [PATCH] ide: kmalloc + memset -> kzalloc conversion Signed-off-by: Deepak Saxena Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/ide-cd.c | 4 +--- drivers/ide/ide-disk.c | 4 +--- drivers/ide/ide-floppy.c | 4 +--- drivers/ide/ide-probe.c | 3 +-- drivers/ide/ide-tape.c | 4 +--- drivers/ide/ide-taskfile.c | 12 ++++-------- drivers/ide/ide.c | 3 +-- drivers/ide/legacy/ide-cs.c | 6 ++---- drivers/ide/pci/hpt366.c | 3 +-- drivers/ide/pci/it821x.c | 3 +-- 10 files changed, 14 insertions(+), 32 deletions(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 8b9d8552659..74d2ab0d901 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -3455,7 +3455,7 @@ static int ide_cd_probe(struct device *dev) printk(KERN_INFO "ide-cd: passing drive %s to ide-scsi emulation.\n", drive->name); goto failed; } - info = kmalloc(sizeof(struct cdrom_info), GFP_KERNEL); + info = kzalloc(sizeof(struct cdrom_info), GFP_KERNEL); if (info == NULL) { printk(KERN_ERR "%s: Can't allocate a cdrom structure\n", drive->name); goto failed; @@ -3469,8 +3469,6 @@ static int ide_cd_probe(struct device *dev) ide_register_subdriver(drive, &ide_cdrom_driver); - memset(info, 0, sizeof (struct cdrom_info)); - kref_init(&info->kref); info->drive = drive; diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 234f5de3e92..e827b39e4b3 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -1215,7 +1215,7 @@ static int ide_disk_probe(struct device *dev) if (drive->media != ide_disk) goto failed; - idkp = kmalloc(sizeof(*idkp), GFP_KERNEL); + idkp = kzalloc(sizeof(*idkp), GFP_KERNEL); if (!idkp) goto failed; @@ -1228,8 +1228,6 @@ static int ide_disk_probe(struct device *dev) ide_register_subdriver(drive, &idedisk_driver); - memset(idkp, 0, sizeof(*idkp)); - kref_init(&idkp->kref); idkp->drive = drive; diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 29c22fc278c..e83f54d37f9 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -2146,7 +2146,7 @@ static int ide_floppy_probe(struct device *dev) printk("ide-floppy: passing drive %s to ide-scsi emulation.\n", drive->name); goto failed; } - if ((floppy = (idefloppy_floppy_t *) kmalloc (sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) { + if ((floppy = (idefloppy_floppy_t *) kzalloc (sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) { printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name); goto failed; } @@ -2159,8 +2159,6 @@ static int ide_floppy_probe(struct device *dev) ide_register_subdriver(drive, &idefloppy_driver); - memset(floppy, 0, sizeof(*floppy)); - kref_init(&floppy->kref); floppy->drive = drive; diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index c1128ae5cd2..e6695e5df5b 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -596,14 +596,13 @@ static inline u8 probe_for_drive (ide_drive_t *drive) * Also note that 0 everywhere means "can't do X" */ - drive->id = kmalloc(SECTOR_WORDS *4, GFP_KERNEL); + drive->id = kzalloc(SECTOR_WORDS *4, GFP_KERNEL); drive->id_read = 0; if(drive->id == NULL) { printk(KERN_ERR "ide: out of memory for id data.\n"); return 0; } - memset(drive->id, 0, SECTOR_WORDS * 4); strcpy(drive->id->model, "UNKNOWN"); /* skip probing? */ diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 47f2b832555..0ac7eb8f40d 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -4850,7 +4850,7 @@ static int ide_tape_probe(struct device *dev) printk(KERN_WARNING "ide-tape: Use drive %s with ide-scsi emulation and osst.\n", drive->name); printk(KERN_WARNING "ide-tape: OnStream support will be removed soon from ide-tape!\n"); } - tape = (idetape_tape_t *) kmalloc (sizeof (idetape_tape_t), GFP_KERNEL); + tape = (idetape_tape_t *) kzalloc (sizeof (idetape_tape_t), GFP_KERNEL); if (tape == NULL) { printk(KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name); goto failed; @@ -4864,8 +4864,6 @@ static int ide_tape_probe(struct device *dev) ide_register_subdriver(drive, &idetape_driver); - memset(tape, 0, sizeof(*tape)); - kref_init(&tape->kref); tape->drive = drive; diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index ace8edad6e9..9c3b4f61562 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -528,9 +528,8 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) // printk("IDE Taskfile ...\n"); - req_task = kmalloc(tasksize, GFP_KERNEL); + req_task = kzalloc(tasksize, GFP_KERNEL); if (req_task == NULL) return -ENOMEM; - memset(req_task, 0, tasksize); if (copy_from_user(req_task, buf, tasksize)) { kfree(req_task); return -EFAULT; @@ -541,12 +540,11 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) if (taskout) { int outtotal = tasksize; - outbuf = kmalloc(taskout, GFP_KERNEL); + outbuf = kzalloc(taskout, GFP_KERNEL); if (outbuf == NULL) { err = -ENOMEM; goto abort; } - memset(outbuf, 0, taskout); if (copy_from_user(outbuf, buf + outtotal, taskout)) { err = -EFAULT; goto abort; @@ -555,12 +553,11 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) if (taskin) { int intotal = tasksize + taskout; - inbuf = kmalloc(taskin, GFP_KERNEL); + inbuf = kzalloc(taskin, GFP_KERNEL); if (inbuf == NULL) { err = -ENOMEM; goto abort; } - memset(inbuf, 0, taskin); if (copy_from_user(inbuf, buf + intotal, taskin)) { err = -EFAULT; goto abort; @@ -709,10 +706,9 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) if (args[3]) { argsize = 4 + (SECTOR_WORDS * 4 * args[3]); - argbuf = kmalloc(argsize, GFP_KERNEL); + argbuf = kzalloc(argsize, GFP_KERNEL); if (argbuf == NULL) return -ENOMEM; - memcpy(argbuf, args, 4); } if (set_transfer(drive, &tfargs)) { xfer_rate = args[1]; diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 73ca8f73917..1bbf67882ae 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -864,9 +864,8 @@ static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int r down(&ide_setting_sem); while ((*p) && strcmp((*p)->name, name) < 0) p = &((*p)->next); - if ((setting = kmalloc(sizeof(*setting), GFP_KERNEL)) == NULL) + if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL) goto abort; - memset(setting, 0, sizeof(*setting)); if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL) goto abort; strcpy(setting->name, name); diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index a35a58bef1a..1dafffa7e51 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -116,9 +116,8 @@ static dev_link_t *ide_attach(void) DEBUG(0, "ide_attach()\n"); /* Create new ide device */ - info = kmalloc(sizeof(*info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return NULL; - memset(info, 0, sizeof(*info)); link = &info->link; link->priv = info; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; @@ -221,9 +220,8 @@ static void ide_config(dev_link_t *link) DEBUG(0, "ide_config(0x%p)\n", link); - stk = kmalloc(sizeof(*stk), GFP_KERNEL); + stk = kzalloc(sizeof(*stk), GFP_KERNEL); if (!stk) goto err_mem; - memset(stk, 0, sizeof(*stk)); cfg = &stk->parse.cftable_entry; tuple.TupleData = (cisdata_t *)&stk->buf; diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 127619a109e..7b589d948bf 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -1516,7 +1516,7 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) static void __devinit init_iops_hpt366(ide_hwif_t *hwif) { - struct hpt_info *info = kmalloc(sizeof(struct hpt_info), GFP_KERNEL); + struct hpt_info *info = kzalloc(sizeof(struct hpt_info), GFP_KERNEL); unsigned long dmabase = pci_resource_start(hwif->pci_dev, 4); u8 did, rid; @@ -1524,7 +1524,6 @@ static void __devinit init_iops_hpt366(ide_hwif_t *hwif) printk(KERN_WARNING "hpt366: out of memory.\n"); return; } - memset(info, 0, sizeof(struct hpt_info)); ide_set_hwifdata(hwif, info); if(dmabase) { diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c index e440036e651..108fda83fea 100644 --- a/drivers/ide/pci/it821x.c +++ b/drivers/ide/pci/it821x.c @@ -642,14 +642,13 @@ static void __devinit it821x_fixups(ide_hwif_t *hwif) static void __devinit init_hwif_it821x(ide_hwif_t *hwif) { - struct it821x_dev *idev = kmalloc(sizeof(struct it821x_dev), GFP_KERNEL); + struct it821x_dev *idev = kzalloc(sizeof(struct it821x_dev), GFP_KERNEL); u8 conf; if(idev == NULL) { printk(KERN_ERR "it821x: out of memory, falling back to legacy behaviour.\n"); goto fallback; } - memset(idev, 0, sizeof(struct it821x_dev)); ide_set_hwifdata(hwif, idev); pci_read_config_byte(hwif->pci_dev, 0x50, &conf); -- cgit v1.2.3 From 089b1dbbde28f0f641c20beabba28fa89ab4fab9 Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Mon, 7 Nov 2005 01:01:26 -0800 Subject: [PATCH] bluetooth: kmalloc + memset -> kzalloc conversion Signed-off-by: Deepak Saxena Cc: Marcel Holtmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/bluetooth/bcm203x.c | 4 +--- drivers/bluetooth/bfusb.c | 4 +--- drivers/bluetooth/bluecard_cs.c | 3 +-- drivers/bluetooth/bpa10x.c | 4 +--- drivers/bluetooth/bt3c_cs.c | 3 +-- drivers/bluetooth/btuart_cs.c | 3 +-- drivers/bluetooth/dtl1_cs.c | 3 +-- drivers/bluetooth/hci_bcsp.c | 3 +-- drivers/bluetooth/hci_h4.c | 4 +--- drivers/bluetooth/hci_ldisc.c | 4 +--- drivers/bluetooth/hci_usb.c | 4 +--- drivers/bluetooth/hci_vhci.c | 4 +--- 12 files changed, 12 insertions(+), 31 deletions(-) diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c index 5fd3e4cb752..8e7fb355177 100644 --- a/drivers/bluetooth/bcm203x.c +++ b/drivers/bluetooth/bcm203x.c @@ -179,14 +179,12 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id if (ignore || (intf->cur_altsetting->desc.bInterfaceNumber != 0)) return -ENODEV; - data = kmalloc(sizeof(*data), GFP_KERNEL); + data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) { BT_ERR("Can't allocate memory for data structure"); return -ENOMEM; } - memset(data, 0, sizeof(*data)); - data->udev = udev; data->state = BCM203X_LOAD_MINIDRV; diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c index 1e9db0156ea..067e27893e4 100644 --- a/drivers/bluetooth/bfusb.c +++ b/drivers/bluetooth/bfusb.c @@ -673,13 +673,11 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i } /* Initialize control structure and load firmware */ - if (!(bfusb = kmalloc(sizeof(struct bfusb), GFP_KERNEL))) { + if (!(bfusb = kzalloc(sizeof(struct bfusb), GFP_KERNEL))) { BT_ERR("Can't allocate memory for control structure"); goto done; } - memset(bfusb, 0, sizeof(struct bfusb)); - bfusb->udev = udev; bfusb->bulk_in_ep = bulk_in_ep->desc.bEndpointAddress; bfusb->bulk_out_ep = bulk_out_ep->desc.bEndpointAddress; diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 26fe9c0e1d2..f36c563d72c 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -870,10 +870,9 @@ static dev_link_t *bluecard_attach(void) int ret; /* Create new info device */ - info = kmalloc(sizeof(*info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return NULL; - memset(info, 0, sizeof(*info)); link = &info->link; link->priv = info; diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index 0db0400519c..ecbeb7eaba8 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c @@ -553,14 +553,12 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id * if (intf->cur_altsetting->desc.bInterfaceNumber > 0) return -ENODEV; - data = kmalloc(sizeof(*data), GFP_KERNEL); + data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) { BT_ERR("Can't allocate data structure"); return -ENOMEM; } - memset(data, 0, sizeof(*data)); - data->udev = udev; rwlock_init(&data->lock); diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 2e0338d80f3..d2a0add19cc 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -671,10 +671,9 @@ static dev_link_t *bt3c_attach(void) int ret; /* Create new info device */ - info = kmalloc(sizeof(*info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return NULL; - memset(info, 0, sizeof(*info)); link = &info->link; link->priv = info; diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index 89486ea7a02..529a28a3209 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -590,10 +590,9 @@ static dev_link_t *btuart_attach(void) int ret; /* Create new info device */ - info = kmalloc(sizeof(*info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return NULL; - memset(info, 0, sizeof(*info)); link = &info->link; link->priv = info; diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 84c1f883942..dec5980a1cd 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -569,10 +569,9 @@ static dev_link_t *dtl1_attach(void) int ret; /* Create new info device */ - info = kmalloc(sizeof(*info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return NULL; - memset(info, 0, sizeof(*info)); link = &info->link; link->priv = info; diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c index 0a4761415ac..8fddfdfd0fb 100644 --- a/drivers/bluetooth/hci_bcsp.c +++ b/drivers/bluetooth/hci_bcsp.c @@ -715,10 +715,9 @@ static int bcsp_open(struct hci_uart *hu) BT_DBG("hu %p", hu); - bcsp = kmalloc(sizeof(*bcsp), GFP_ATOMIC); + bcsp = kzalloc(sizeof(*bcsp), GFP_ATOMIC); if (!bcsp) return -ENOMEM; - memset(bcsp, 0, sizeof(*bcsp)); hu->priv = bcsp; skb_queue_head_init(&bcsp->unack); diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c index 12e369a66fc..4804d474dc8 100644 --- a/drivers/bluetooth/hci_h4.c +++ b/drivers/bluetooth/hci_h4.c @@ -76,12 +76,10 @@ static int h4_open(struct hci_uart *hu) BT_DBG("hu %p", hu); - h4 = kmalloc(sizeof(*h4), GFP_ATOMIC); + h4 = kzalloc(sizeof(*h4), GFP_ATOMIC); if (!h4) return -ENOMEM; - memset(h4, 0, sizeof(*h4)); - skb_queue_head_init(&h4->txq); hu->priv = h4; diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 4a775f6ea39..573ff6c1be5 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -272,13 +272,11 @@ static int hci_uart_tty_open(struct tty_struct *tty) if (hu) return -EEXIST; - if (!(hu = kmalloc(sizeof(struct hci_uart), GFP_KERNEL))) { + if (!(hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL))) { BT_ERR("Can't allocate controll structure"); return -ENFILE; } - memset(hu, 0, sizeof(struct hci_uart)); - tty->disc_data = hu; hu->tty = tty; diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c index 6756cb20b75..f510b25b2c5 100644 --- a/drivers/bluetooth/hci_usb.c +++ b/drivers/bluetooth/hci_usb.c @@ -875,13 +875,11 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id goto done; } - if (!(husb = kmalloc(sizeof(struct hci_usb), GFP_KERNEL))) { + if (!(husb = kzalloc(sizeof(struct hci_usb), GFP_KERNEL))) { BT_ERR("Can't allocate: control structure"); goto done; } - memset(husb, 0, sizeof(struct hci_usb)); - husb->udev = udev; husb->bulk_out_ep = bulk_out_ep; husb->bulk_in_ep = bulk_in_ep; diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index 52cbd45c308..85738223ff0 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -261,12 +261,10 @@ static int vhci_open(struct inode *inode, struct file *file) struct vhci_data *vhci; struct hci_dev *hdev; - vhci = kmalloc(sizeof(struct vhci_data), GFP_KERNEL); + vhci = kzalloc(sizeof(struct vhci_data), GFP_KERNEL); if (!vhci) return -ENOMEM; - memset(vhci, 0, sizeof(struct vhci_data)); - skb_queue_head_init(&vhci->readq); init_waitqueue_head(&vhci->read_wait); -- cgit v1.2.3 From c9475cb0c358ff0dd473544280d92482df491913 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 7 Nov 2005 01:01:26 -0800 Subject: [PATCH] kfree cleanup: drivers/scsi This is the drivers/scsi/ part of the big kfree cleanup patch. Remove pointless checks for NULL prior to calling kfree() in drivers/scsi/. Signed-off-by: Jesper Juhl Cc: James Bottomley Acked-by: Kai Makisara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/3w-9xxx.c | 3 +-- drivers/scsi/aacraid/commsup.c | 14 +++++--------- drivers/scsi/advansys.c | 12 ++++-------- drivers/scsi/aha1542.c | 36 ++++++++++++----------------------- drivers/scsi/aic7xxx_old.c | 3 +-- drivers/scsi/arm/queue.c | 3 +-- drivers/scsi/dc395x.c | 3 +-- drivers/scsi/dpt_i2o.c | 27 ++++++++------------------ drivers/scsi/eata.c | 3 +-- drivers/scsi/ide-scsi.c | 10 +++++----- drivers/scsi/ips.c | 18 ++++++------------ drivers/scsi/lpfc/lpfc_els.c | 9 +++------ drivers/scsi/lpfc/lpfc_init.c | 6 ++---- drivers/scsi/lpfc/lpfc_mbox.c | 7 ++----- drivers/scsi/lpfc/lpfc_sli.c | 7 ++----- drivers/scsi/megaraid/megaraid_mbox.c | 5 ++--- drivers/scsi/megaraid/megaraid_mm.c | 11 +++-------- drivers/scsi/qla2xxx/qla_init.c | 16 +++++----------- drivers/scsi/sg.c | 9 +++------ drivers/scsi/st.c | 3 +-- drivers/scsi/u14-34f.c | 9 +++++---- 21 files changed, 73 insertions(+), 141 deletions(-) diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index d06ee65d668..3ff74f47224 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -1017,8 +1017,7 @@ static void twa_free_device_extension(TW_Device_Extension *tw_dev) tw_dev->generic_buffer_virt[0], tw_dev->generic_buffer_phys[0]); - if (tw_dev->event_queue[0]) - kfree(tw_dev->event_queue[0]); + kfree(tw_dev->event_queue[0]); } /* End twa_free_device_extension() */ /* This function will free a request id */ diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index ee906725593..723c0cea7c0 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -1164,7 +1164,7 @@ int aac_command_thread(struct aac_dev * dev) kfree(hw_fib_pool); hw_fib_pool = NULL; } - } else if (hw_fib_pool) { + } else { kfree(hw_fib_pool); hw_fib_pool = NULL; } @@ -1247,17 +1247,13 @@ int aac_command_thread(struct aac_dev * dev) hw_fib_p = hw_fib_pool; fib_p = fib_pool; while (hw_fib_p < &hw_fib_pool[num]) { - if (*hw_fib_p) - kfree(*hw_fib_p); - if (*fib_p) - kfree(*fib_p); + kfree(*hw_fib_p); + kfree(*fib_p); ++fib_p; ++hw_fib_p; } - if (hw_fib_pool) - kfree(hw_fib_pool); - if (fib_pool) - kfree(fib_pool); + kfree(hw_fib_pool); + kfree(fib_pool); } kfree(fib); spin_lock_irqsave(dev->queues->queue[HostNormCmdQueue].lock, flags); diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 37ec5411e32..f4cfb8f2962 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -5402,10 +5402,8 @@ advansys_detect(struct scsi_host_template *tpnt) release_region(shp->io_port, boardp->asc_n_io_port); if (ASC_WIDE_BOARD(boardp)) { iounmap(boardp->ioremap_addr); - if (boardp->orig_carrp) { - kfree(boardp->orig_carrp); - boardp->orig_carrp = NULL; - } + kfree(boardp->orig_carrp); + boardp->orig_carrp = NULL; if (boardp->orig_reqp) { kfree(boardp->orig_reqp); boardp->orig_reqp = boardp->adv_reqp = NULL; @@ -5457,10 +5455,8 @@ advansys_release(struct Scsi_Host *shp) adv_sgblk_t *sgp = NULL; iounmap(boardp->ioremap_addr); - if (boardp->orig_carrp) { - kfree(boardp->orig_carrp); - boardp->orig_carrp = NULL; - } + kfree(boardp->orig_carrp); + boardp->orig_carrp = NULL; if (boardp->orig_reqp) { kfree(boardp->orig_reqp); boardp->orig_reqp = boardp->adv_reqp = NULL; diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c index adda750412f..1b1adfb384c 100644 --- a/drivers/scsi/aha1542.c +++ b/drivers/scsi/aha1542.c @@ -543,10 +543,8 @@ static void aha1542_intr_handle(struct Scsi_Host *shost, void *dev_id, struct pt return; } my_done = SCtmp->scsi_done; - if (SCtmp->host_scribble) { - kfree(SCtmp->host_scribble); - SCtmp->host_scribble = NULL; - } + kfree(SCtmp->host_scribble); + SCtmp->host_scribble = NULL; /* Fetch the sense data, and tuck it away, in the required slot. The Adaptec automatically fetches it, and there is no guarantee that we will still have it in the cdb when we come back */ @@ -1432,10 +1430,8 @@ static int aha1542_dev_reset(Scsi_Cmnd * SCpnt) HOSTDATA(SCpnt->host)->SCint[i]->target == SCpnt->target) { Scsi_Cmnd *SCtmp; SCtmp = HOSTDATA(SCpnt->host)->SCint[i]; - if (SCtmp->host_scribble) { - kfree(SCtmp->host_scribble); - SCtmp->host_scribble = NULL; - } + kfree(SCtmp->host_scribble); + SCtmp->host_scribble = NULL; HOSTDATA(SCpnt->host)->SCint[i] = NULL; HOSTDATA(SCpnt->host)->mb[i].status = 0; } @@ -1495,10 +1491,8 @@ static int aha1542_bus_reset(Scsi_Cmnd * SCpnt) */ continue; } - if (SCtmp->host_scribble) { - kfree(SCtmp->host_scribble); - SCtmp->host_scribble = NULL; - } + kfree(SCtmp->host_scribble); + SCtmp->host_scribble = NULL; HOSTDATA(SCpnt->device->host)->SCint[i] = NULL; HOSTDATA(SCpnt->device->host)->mb[i].status = 0; } @@ -1565,10 +1559,8 @@ static int aha1542_host_reset(Scsi_Cmnd * SCpnt) */ continue; } - if (SCtmp->host_scribble) { - kfree(SCtmp->host_scribble); - SCtmp->host_scribble = NULL; - } + kfree(SCtmp->host_scribble); + SCtmp->host_scribble = NULL; HOSTDATA(SCpnt->device->host)->SCint[i] = NULL; HOSTDATA(SCpnt->device->host)->mb[i].status = 0; } @@ -1711,10 +1703,8 @@ static int aha1542_old_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags) Scsi_Cmnd *SCtmp; SCtmp = HOSTDATA(SCpnt->host)->SCint[i]; SCtmp->result = DID_RESET << 16; - if (SCtmp->host_scribble) { - kfree(SCtmp->host_scribble); - SCtmp->host_scribble = NULL; - } + kfree(SCtmp->host_scribble); + SCtmp->host_scribble = NULL; printk(KERN_WARNING "Sending DID_RESET for target %d\n", SCpnt->target); SCtmp->scsi_done(SCpnt); @@ -1757,10 +1747,8 @@ fail: Scsi_Cmnd *SCtmp; SCtmp = HOSTDATA(SCpnt->host)->SCint[i]; SCtmp->result = DID_RESET << 16; - if (SCtmp->host_scribble) { - kfree(SCtmp->host_scribble); - SCtmp->host_scribble = NULL; - } + kfree(SCtmp->host_scribble); + SCtmp->host_scribble = NULL; printk(KERN_WARNING "Sending DID_RESET for target %d\n", SCpnt->target); SCtmp->scsi_done(SCpnt); diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c index 52b72d7794f..880e2d9ffe9 100644 --- a/drivers/scsi/aic7xxx_old.c +++ b/drivers/scsi/aic7xxx_old.c @@ -8492,8 +8492,7 @@ aic7xxx_free(struct aic7xxx_host *p) - scb_dma->dma_offset), scb_dma->dma_address); } - if (p->scb_data->scb_array[i]->kmalloc_ptr != NULL) - kfree(p->scb_data->scb_array[i]->kmalloc_ptr); + kfree(p->scb_data->scb_array[i]->kmalloc_ptr); p->scb_data->scb_array[i] = NULL; } diff --git a/drivers/scsi/arm/queue.c b/drivers/scsi/arm/queue.c index e6d159270d2..b10750bb5c0 100644 --- a/drivers/scsi/arm/queue.c +++ b/drivers/scsi/arm/queue.c @@ -91,8 +91,7 @@ void queue_free (Queue_t *queue) { if (!list_empty(&queue->head)) printk(KERN_WARNING "freeing non-empty queue %p\n", queue); - if (queue->alloc) - kfree(queue->alloc); + kfree(queue->alloc); } diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index c44af5795b1..c8a32cf47d7 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -4270,8 +4270,7 @@ static void adapter_sg_tables_free(struct AdapterCtlBlk *acb) const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN; for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page) - if (acb->srb_array[i].segment_x) - kfree(acb->srb_array[i].segment_x); + kfree(acb->srb_array[i].segment_x); } diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 46d5571ec55..c28e3aea1c3 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -1037,18 +1037,10 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba) if(pHba->msg_addr_virt != pHba->base_addr_virt){ iounmap(pHba->msg_addr_virt); } - if(pHba->hrt) { - kfree(pHba->hrt); - } - if(pHba->lct){ - kfree(pHba->lct); - } - if(pHba->status_block) { - kfree(pHba->status_block); - } - if(pHba->reply_pool){ - kfree(pHba->reply_pool); - } + kfree(pHba->hrt); + kfree(pHba->lct); + kfree(pHba->status_block); + kfree(pHba->reply_pool); for(d = pHba->devices; d ; d = next){ next = d->next; @@ -2706,14 +2698,12 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba) // If the command was successful, fill the fifo with our reply // message packets if(*status != 0x04 /*I2O_EXEC_OUTBOUND_INIT_COMPLETE*/) { - kfree((void*)status); + kfree(status); return -2; } - kfree((void*)status); + kfree(status); - if(pHba->reply_pool != NULL){ - kfree(pHba->reply_pool); - } + kfree(pHba->reply_pool); pHba->reply_pool = (u32*)kmalloc(pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, GFP_KERNEL|ADDR32); if(!pHba->reply_pool){ @@ -2929,8 +2919,7 @@ static int adpt_i2o_build_sys_table(void) sys_tbl_len = sizeof(struct i2o_sys_tbl) + // Header + IOPs (hba_count) * sizeof(struct i2o_sys_tbl_entry); - if(sys_tbl) - kfree(sys_tbl); + kfree(sys_tbl); sys_tbl = kmalloc(sys_tbl_len, GFP_KERNEL|ADDR32); if(!sys_tbl) { diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c index b45a4c73023..b3f9de8f759 100644 --- a/drivers/scsi/eata.c +++ b/drivers/scsi/eata.c @@ -2580,8 +2580,7 @@ static int eata2x_release(struct Scsi_Host *shost) unsigned int i; for (i = 0; i < shost->can_queue; i++) - if ((&ha->cp[i])->sglist) - kfree((&ha->cp[i])->sglist); + kfree((&ha->cp[i])->sglist); for (i = 0; i < shost->can_queue; i++) pci_unmap_single(ha->pdev, ha->cp[i].cp_dma_addr, diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index f04f3289938..c888af4a456 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -331,9 +331,9 @@ static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_co rq = kmalloc (sizeof (struct request), GFP_ATOMIC); buf = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_ATOMIC); if (pc == NULL || rq == NULL || buf == NULL) { - if (pc) kfree(pc); - if (rq) kfree(rq); - if (buf) kfree(buf); + kfree(buf); + kfree(rq); + kfree(pc); return -ENOMEM; } memset (pc, 0, sizeof (idescsi_pc_t)); @@ -949,8 +949,8 @@ static int idescsi_queue (struct scsi_cmnd *cmd, spin_lock_irq(host->host_lock); return 0; abort: - if (pc) kfree (pc); - if (rq) kfree (rq); + kfree (pc); + kfree (rq); cmd->result = DID_ERROR << 16; done(cmd); return 0; diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 68e5b2ab27c..cd9b95db5a7 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -4517,10 +4517,8 @@ ips_free(ips_ha_t * ha) ha->enq = NULL; } - if (ha->conf) { - kfree(ha->conf); - ha->conf = NULL; - } + kfree(ha->conf); + ha->conf = NULL; if (ha->adapt) { pci_free_consistent(ha->pcidev, @@ -4538,15 +4536,11 @@ ips_free(ips_ha_t * ha) ha->logical_drive_info = NULL; } - if (ha->nvram) { - kfree(ha->nvram); - ha->nvram = NULL; - } + kfree(ha->nvram); + ha->nvram = NULL; - if (ha->subsys) { - kfree(ha->subsys); - ha->subsys = NULL; - } + kfree(ha->subsys); + ha->subsys = NULL; if (ha->ioctl_data) { pci_free_consistent(ha->pcidev, ha->ioctl_len, diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 08a0c00cfc3..bcc29ec126d 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -127,8 +127,7 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, if (((pcmd = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL)) == 0) || ((pcmd->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(pcmd->phys))) == 0)) { - if (pcmd) - kfree(pcmd); + kfree(pcmd); spin_lock_irq(phba->host->host_lock); lpfc_sli_release_iocbq(phba, elsiocb); @@ -145,8 +144,7 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, prsp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &prsp->phys); if (prsp == 0 || prsp->virt == 0) { - if (prsp) - kfree(prsp); + kfree(prsp); lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys); kfree(pcmd); spin_lock_irq(phba->host->host_lock); @@ -172,8 +170,7 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, lpfc_mbuf_free(phba, prsp->virt, prsp->phys); kfree(pcmd); kfree(prsp); - if (pbuflist) - kfree(pbuflist); + kfree(pbuflist); return NULL; } diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 4e04470321a..c90723860a0 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -894,8 +894,7 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt, mp1->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &mp1->phys); if (mp1 == 0 || mp1->virt == 0) { - if (mp1) - kfree(mp1); + kfree(mp1); spin_lock_irq(phba->host->host_lock); lpfc_sli_release_iocbq(phba, iocb); spin_unlock_irq(phba->host->host_lock); @@ -911,8 +910,7 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt, mp2->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &mp2->phys); if (mp2 == 0 || mp2->virt == 0) { - if (mp2) - kfree(mp2); + kfree(mp2); lpfc_mbuf_free(phba, mp1->virt, mp1->phys); kfree(mp1); spin_lock_irq(phba->host->host_lock); diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 31c20cc0060..e3bc8d3f730 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -248,8 +248,7 @@ lpfc_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) if (((mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL)) == 0) || ((mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys))) == 0)) { - if (mp) - kfree(mp); + kfree(mp); mb->mbxCommand = MBX_READ_SPARM64; /* READ_SPARAM: no buffers */ lpfc_printf_log(phba, @@ -363,9 +362,7 @@ lpfc_reg_login(struct lpfc_hba * phba, /* Get a buffer to hold NPorts Service Parameters */ if (((mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL)) == NULL) || ((mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys))) == 0)) { - if (mp) - kfree(mp); - + kfree(mp); mb->mbxCommand = MBX_REG_LOGIN64; /* REG_LOGIN: no buffers */ lpfc_printf_log(phba, diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 508710001ed..e2c08c5d83f 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -2269,11 +2269,8 @@ lpfc_sli_hba_down(struct lpfc_hba * phba) INIT_LIST_HEAD(&(pring->txq)); - if (pring->fast_lookup) { - kfree(pring->fast_lookup); - pring->fast_lookup = NULL; - } - + kfree(pring->fast_lookup); + pring->fast_lookup = NULL; } spin_unlock_irqrestore(phba->host->host_lock, flags); diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index c9e743ba09e..1a3d195a2d3 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -3937,9 +3937,8 @@ megaraid_sysfs_free_resources(adapter_t *adapter) { mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); - if (raid_dev->sysfs_uioc) kfree(raid_dev->sysfs_uioc); - - if (raid_dev->sysfs_mbox64) kfree(raid_dev->sysfs_mbox64); + kfree(raid_dev->sysfs_uioc); + kfree(raid_dev->sysfs_mbox64); if (raid_dev->sysfs_buffer) { pci_free_consistent(adapter->pdev, PAGE_SIZE, diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c index 37d110e864c..8f3ce043229 100644 --- a/drivers/scsi/megaraid/megaraid_mm.c +++ b/drivers/scsi/megaraid/megaraid_mm.c @@ -995,17 +995,13 @@ pthru_dma_pool_error: memalloc_error: - if (adapter->kioc_list) - kfree(adapter->kioc_list); - - if (adapter->mbox_list) - kfree(adapter->mbox_list); + kfree(adapter->kioc_list); + kfree(adapter->mbox_list); if (adapter->pthru_dma_pool) pci_pool_destroy(adapter->pthru_dma_pool); - if (adapter) - kfree(adapter); + kfree(adapter); return rval; } @@ -1157,7 +1153,6 @@ mraid_mm_free_adp_resources(mraid_mmadp_t *adp) } kfree(adp->kioc_list); - kfree(adp->mbox_list); pci_pool_destroy(adp->pthru_dma_pool); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 290a6b92616..72d9090df3d 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1977,8 +1977,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) } cleanup_allocation: - if (new_fcport) - kfree(new_fcport); + kfree(new_fcport); if (rval != QLA_SUCCESS) { DEBUG2(printk("scsi(%ld): Configure local loop error exit: " @@ -2348,8 +2347,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) /* Allocate temporary fcport for any new fcports discovered. */ new_fcport = qla2x00_alloc_fcport(ha, GFP_KERNEL); if (new_fcport == NULL) { - if (swl) - kfree(swl); + kfree(swl); return (QLA_MEMORY_ALLOC_FAILED); } new_fcport->flags |= (FCF_FABRIC_DEVICE | FCF_LOGIN_NEEDED); @@ -2485,19 +2483,15 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) nxt_d_id.b24 = new_fcport->d_id.b24; new_fcport = qla2x00_alloc_fcport(ha, GFP_KERNEL); if (new_fcport == NULL) { - if (swl) - kfree(swl); + kfree(swl); return (QLA_MEMORY_ALLOC_FAILED); } new_fcport->flags |= (FCF_FABRIC_DEVICE | FCF_LOGIN_NEEDED); new_fcport->d_id.b24 = nxt_d_id.b24; } - if (swl) - kfree(swl); - - if (new_fcport) - kfree(new_fcport); + kfree(swl); + kfree(new_fcport); if (!list_empty(new_fcports)) ha->device_flags |= DFLG_FABRIC_DEVICES; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 4f30a37db63..62e3f340cc5 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -476,8 +476,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) sg_finish_rem_req(srp); retval = count; free_old_hdr: - if (old_hdr) - kfree(old_hdr); + kfree(old_hdr); return retval; } @@ -1703,10 +1702,8 @@ exit_sg(void) sg_sysfs_valid = 0; unregister_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0), SG_MAX_DEVS); - if (sg_dev_arr != NULL) { - kfree((char *) sg_dev_arr); - sg_dev_arr = NULL; - } + kfree((char *)sg_dev_arr); + sg_dev_arr = NULL; sg_dev_max = 0; } diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 6b85f84c839..770c4324f3d 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -4107,8 +4107,7 @@ out_free_tape: write_unlock(&st_dev_arr_lock); out_put_disk: put_disk(disk); - if (tpnt) - kfree(tpnt); + kfree(tpnt); out_buffer_free: kfree(buffer); out: diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c index cfab8f19708..1ce29ba683e 100644 --- a/drivers/scsi/u14-34f.c +++ b/drivers/scsi/u14-34f.c @@ -1953,11 +1953,11 @@ static int u14_34f_release(struct Scsi_Host *shpnt) { for (j = 0; sh[j] != NULL && sh[j] != shpnt; j++); - if (sh[j] == NULL) panic("%s: release, invalid Scsi_Host pointer.\n", - driver_name); + if (sh[j] == NULL) + panic("%s: release, invalid Scsi_Host pointer.\n", driver_name); for (i = 0; i < sh[j]->can_queue; i++) - if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist); + kfree((&HD(j)->cp[i])->sglist); for (i = 0; i < sh[j]->can_queue; i++) pci_unmap_single(HD(j)->pdev, HD(j)->cp[i].cp_dma_addr, @@ -1965,7 +1965,8 @@ static int u14_34f_release(struct Scsi_Host *shpnt) { free_irq(sh[j]->irq, &sha[j]); - if (sh[j]->dma_channel != NO_DMA) free_dma(sh[j]->dma_channel); + if (sh[j]->dma_channel != NO_DMA) + free_dma(sh[j]->dma_channel); release_region(sh[j]->io_port, sh[j]->n_io_port); scsi_unregister(sh[j]); -- cgit v1.2.3 From fa671646f61182cd18234461a6e65f50c6558695 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 7 Nov 2005 01:01:27 -0800 Subject: [PATCH] kfree cleanup: drivers/mtd This is the drivers/mtd part of the big kfree cleanup patch. Remove pointless checks for NULL prior to calling kfree() in drivers/mtd/. Signed-off-by: Jesper Juhl Cc: David Woodhouse Acked-by: Joern Engel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/chips/cfi_cmdset_0001.c | 3 +-- drivers/mtd/chips/cfi_cmdset_0002.c | 4 ++-- drivers/mtd/devices/blkmtd.c | 7 ++----- drivers/mtd/inftlcore.c | 12 ++++-------- drivers/mtd/maps/amd76xrom.c | 4 +--- drivers/mtd/maps/bast-flash.c | 3 +-- drivers/mtd/maps/ceiva.c | 3 +-- drivers/mtd/maps/ichxrom.c | 5 ++--- drivers/mtd/maps/integrator-flash.c | 6 ++---- drivers/mtd/maps/ipaq-flash.c | 3 +-- drivers/mtd/maps/iq80310.c | 3 +-- drivers/mtd/maps/ixp2000.c | 3 +-- drivers/mtd/maps/ixp4xx.c | 3 +-- drivers/mtd/maps/lubbock-flash.c | 3 +-- drivers/mtd/maps/omap-toto-flash.c | 3 +-- drivers/mtd/maps/sa1100-flash.c | 3 +-- drivers/mtd/maps/sun_uflash.c | 4 +--- drivers/mtd/maps/tqm8xxl.c | 6 ++---- drivers/mtd/nand/nand_base.c | 5 ++--- drivers/mtd/nftlcore.c | 12 ++++-------- 20 files changed, 32 insertions(+), 63 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 0cfcd88468e..c3fc9b2f21f 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -455,8 +455,7 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd) setup_err: if(mtd) { - if(mtd->eraseregions) - kfree(mtd->eraseregions); + kfree(mtd->eraseregions); kfree(mtd); } kfree(cfi->cmdset_priv); diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 8505f118f2d..0e6475050da 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -378,8 +378,7 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) setup_err: if(mtd) { - if(mtd->eraseregions) - kfree(mtd->eraseregions); + kfree(mtd->eraseregions); kfree(mtd); } kfree(cfi->cmdset_priv); @@ -1742,6 +1741,7 @@ static void cfi_amdstd_destroy(struct mtd_info *mtd) { struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; + kfree(cfi->cmdset_priv); kfree(cfi->cfiq); kfree(cfi); diff --git a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c index 662e807801e..59a29e616a2 100644 --- a/drivers/mtd/devices/blkmtd.c +++ b/drivers/mtd/devices/blkmtd.c @@ -539,11 +539,8 @@ static void free_device(struct blkmtd_dev *dev) { DEBUG(2, "blkmtd: free_device() dev = %p\n", dev); if(dev) { - if(dev->mtd_info.eraseregions) - kfree(dev->mtd_info.eraseregions); - if(dev->mtd_info.name) - kfree(dev->mtd_info.name); - + kfree(dev->mtd_info.eraseregions); + kfree(dev->mtd_info.name); if(dev->blkdev) { invalidate_inode_pages(dev->blkdev->bd_inode->i_mapping); close_bdev_excl(dev->blkdev); diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c index 39eb53f6551..8db65bf029e 100644 --- a/drivers/mtd/inftlcore.c +++ b/drivers/mtd/inftlcore.c @@ -126,10 +126,8 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) } if (add_mtd_blktrans_dev(&inftl->mbd)) { - if (inftl->PUtable) - kfree(inftl->PUtable); - if (inftl->VUtable) - kfree(inftl->VUtable); + kfree(inftl->PUtable); + kfree(inftl->VUtable); kfree(inftl); return; } @@ -147,10 +145,8 @@ static void inftl_remove_dev(struct mtd_blktrans_dev *dev) del_mtd_blktrans_dev(dev); - if (inftl->PUtable) - kfree(inftl->PUtable); - if (inftl->VUtable) - kfree(inftl->VUtable); + kfree(inftl->PUtable); + kfree(inftl->VUtable); kfree(inftl); } diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c index e8a900a7768..9a64149f431 100644 --- a/drivers/mtd/maps/amd76xrom.c +++ b/drivers/mtd/maps/amd76xrom.c @@ -259,9 +259,7 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev, out: /* Free any left over map structures */ - if (map) { - kfree(map); - } + kfree(map); /* See if I have any map structures */ if (list_empty(&window->maps)) { amd76xrom_cleanup(window); diff --git a/drivers/mtd/maps/bast-flash.c b/drivers/mtd/maps/bast-flash.c index bfe994e5926..8c19d722ac7 100644 --- a/drivers/mtd/maps/bast-flash.c +++ b/drivers/mtd/maps/bast-flash.c @@ -104,8 +104,7 @@ static int bast_flash_remove(struct device *dev) map_destroy(info->mtd); } - if (info->partitions) - kfree(info->partitions); + kfree(info->partitions); if (info->area) { release_resource(info->area); diff --git a/drivers/mtd/maps/ceiva.c b/drivers/mtd/maps/ceiva.c index c68b31dc7e6..5a95ab370a9 100644 --- a/drivers/mtd/maps/ceiva.c +++ b/drivers/mtd/maps/ceiva.c @@ -313,8 +313,7 @@ static void __init clps_locate_partitions(struct mtd_info *mtd) static void __exit clps_destroy_partitions(void) { - if (parsed_parts) - kfree(parsed_parts); + kfree(parsed_parts); } static struct mtd_info *mymtd; diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c index e505207cd48..c5e2111ba14 100644 --- a/drivers/mtd/maps/ichxrom.c +++ b/drivers/mtd/maps/ichxrom.c @@ -306,9 +306,8 @@ static int __devinit ichxrom_init_one (struct pci_dev *pdev, out: /* Free any left over map structures */ - if (map) { - kfree(map); - } + kfree(map); + /* See if I have any map structures */ if (list_empty(&window->maps)) { ichxrom_cleanup(window); diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c index d14a0185b8f..93f50d6d548 100644 --- a/drivers/mtd/maps/integrator-flash.c +++ b/drivers/mtd/maps/integrator-flash.c @@ -148,8 +148,7 @@ static int armflash_probe(struct device *_dev) del_mtd_partitions(info->mtd); map_destroy(info->mtd); } - if (info->parts) - kfree(info->parts); + kfree(info->parts); no_device: iounmap(base); @@ -176,8 +175,7 @@ static int armflash_remove(struct device *_dev) del_mtd_partitions(info->mtd); map_destroy(info->mtd); } - if (info->parts) - kfree(info->parts); + kfree(info->parts); iounmap(info->map.virt); release_resource(info->res); diff --git a/drivers/mtd/maps/ipaq-flash.c b/drivers/mtd/maps/ipaq-flash.c index 71240181084..70b0e0b82c3 100644 --- a/drivers/mtd/maps/ipaq-flash.c +++ b/drivers/mtd/maps/ipaq-flash.c @@ -431,8 +431,7 @@ static void __exit ipaq_mtd_cleanup(void) if (my_sub_mtd[i]) map_destroy(my_sub_mtd[i]); } - if (parsed_parts) - kfree(parsed_parts); + kfree(parsed_parts); } } diff --git a/drivers/mtd/maps/iq80310.c b/drivers/mtd/maps/iq80310.c index 558d014e7ac..2e7577492a2 100644 --- a/drivers/mtd/maps/iq80310.c +++ b/drivers/mtd/maps/iq80310.c @@ -103,8 +103,7 @@ static void __exit cleanup_iq80310(void) if (mymtd) { del_mtd_partitions(mymtd); map_destroy(mymtd); - if (parsed_parts) - kfree(parsed_parts); + kfree(parsed_parts); } if (iq80310_map.virt) iounmap((void *)iq80310_map.virt); diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c index 00b9f67580f..6f36497022d 100644 --- a/drivers/mtd/maps/ixp2000.c +++ b/drivers/mtd/maps/ixp2000.c @@ -129,8 +129,7 @@ static int ixp2000_flash_remove(struct device *_dev) if (info->map.map_priv_1) iounmap((void *) info->map.map_priv_1); - if (info->partitions) { - kfree(info->partitions); } + kfree(info->partitions); if (info->res) { release_resource(info->res); diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c index 733a9297a56..0d87c02dee0 100644 --- a/drivers/mtd/maps/ixp4xx.c +++ b/drivers/mtd/maps/ixp4xx.c @@ -124,8 +124,7 @@ static int ixp4xx_flash_remove(struct device *_dev) if (info->map.map_priv_1) iounmap((void *) info->map.map_priv_1); - if (info->partitions) - kfree(info->partitions); + kfree(info->partitions); if (info->res) { release_resource(info->res); diff --git a/drivers/mtd/maps/lubbock-flash.c b/drivers/mtd/maps/lubbock-flash.c index 2337e0c4675..2b4c5058787 100644 --- a/drivers/mtd/maps/lubbock-flash.c +++ b/drivers/mtd/maps/lubbock-flash.c @@ -158,8 +158,7 @@ static void __exit cleanup_lubbock(void) if (lubbock_maps[i].cached) iounmap(lubbock_maps[i].cached); - if (parsed_parts[i]) - kfree(parsed_parts[i]); + kfree(parsed_parts[i]); } } diff --git a/drivers/mtd/maps/omap-toto-flash.c b/drivers/mtd/maps/omap-toto-flash.c index da36e8dddd1..763304154a9 100644 --- a/drivers/mtd/maps/omap-toto-flash.c +++ b/drivers/mtd/maps/omap-toto-flash.c @@ -124,8 +124,7 @@ static void __exit omap_toto_mtd_cleanup(void) if (flash_mtd) { del_mtd_partitions(flash_mtd); map_destroy(flash_mtd); - if (parsed_parts) - kfree(parsed_parts); + kfree(parsed_parts); } } diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c index c8d0da19d89..a31f6ee8a4b 100644 --- a/drivers/mtd/maps/sa1100-flash.c +++ b/drivers/mtd/maps/sa1100-flash.c @@ -241,8 +241,7 @@ static void sa1100_destroy(struct sa_info *info, struct flash_platform_data *pla #endif } - if (info->parts) - kfree(info->parts); + kfree(info->parts); for (i = info->num_subdev - 1; i >= 0; i--) sa1100_destroy_subdev(&info->subdev[i]); diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c index 29091d10030..1355c28f90a 100644 --- a/drivers/mtd/maps/sun_uflash.c +++ b/drivers/mtd/maps/sun_uflash.c @@ -166,9 +166,7 @@ static void __exit uflash_cleanup(void) iounmap(udev->map.virt); udev->map.virt = NULL; } - if(0 != udev->name) { - kfree(udev->name); - } + kfree(udev->name); kfree(udev); } } diff --git a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c index 4e28b977f22..0aca8179f27 100644 --- a/drivers/mtd/maps/tqm8xxl.c +++ b/drivers/mtd/maps/tqm8xxl.c @@ -224,10 +224,8 @@ int __init init_tqm_mtd(void) error_mem: for(idx = 0 ; idx < FLASH_BANK_MAX ; idx++) { if(map_banks[idx] != NULL) { - if(map_banks[idx]->name != NULL) { - kfree(map_banks[idx]->name); - map_banks[idx]->name = NULL; - } + kfree(map_banks[idx]->name); + map_banks[idx]->name = NULL; kfree(map_banks[idx]); map_banks[idx] = NULL; } diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 04e54318bc6..8e78d7b96a5 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2676,9 +2676,8 @@ void nand_release (struct mtd_info *mtd) /* Deregister the device */ del_mtd_device (mtd); - /* Free bad block table memory, if allocated */ - if (this->bbt) - kfree (this->bbt); + /* Free bad block table memory */ + kfree (this->bbt); /* Buffer allocated by nand_scan ? */ if (this->options & NAND_OOBBUF_ALLOC) kfree (this->oob_buf); diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index b2014043634..062ff387753 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c @@ -114,10 +114,8 @@ static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) } if (add_mtd_blktrans_dev(&nftl->mbd)) { - if (nftl->ReplUnitTable) - kfree(nftl->ReplUnitTable); - if (nftl->EUNtable) - kfree(nftl->EUNtable); + kfree(nftl->ReplUnitTable); + kfree(nftl->EUNtable); kfree(nftl); return; } @@ -133,10 +131,8 @@ static void nftl_remove_dev(struct mtd_blktrans_dev *dev) DEBUG(MTD_DEBUG_LEVEL1, "NFTL: remove_dev (i=%d)\n", dev->devnum); del_mtd_blktrans_dev(dev); - if (nftl->ReplUnitTable) - kfree(nftl->ReplUnitTable); - if (nftl->EUNtable) - kfree(nftl->EUNtable); + kfree(nftl->ReplUnitTable); + kfree(nftl->EUNtable); kfree(nftl); } -- cgit v1.2.3 From 735d5661d5c5f023a78fbe68e771e261040ff1b7 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 7 Nov 2005 01:01:29 -0800 Subject: [PATCH] kfree cleanup: drivers/char This is the drivers/char/ part of the big kfree cleanup patch. Remove pointless checks for NULL prior to calling kfree() in drivers/char/. Signed-off-by: Jesper Juhl Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/consolemap.c | 12 +++++------- drivers/char/drm/ffb_context.c | 6 ++---- drivers/char/drm/ffb_drv.c | 6 ++---- drivers/char/ip2/i2ellis.c | 4 +--- drivers/char/istallion.c | 7 +++---- drivers/char/n_hdlc.c | 3 +-- drivers/char/pcmcia/synclink_cs.c | 3 +-- drivers/char/rocket.c | 6 ++---- drivers/char/selection.c | 3 +-- drivers/char/stallion.c | 6 ++---- drivers/char/synclink.c | 10 +++------- drivers/char/synclinkmp.c | 9 +++------ drivers/char/tty_io.c | 9 +++------ 13 files changed, 29 insertions(+), 55 deletions(-) diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c index 406dea91463..c85a4fa60da 100644 --- a/drivers/char/consolemap.c +++ b/drivers/char/consolemap.c @@ -345,17 +345,15 @@ static void con_release_unimap(struct uni_pagedir *p) for (i = 0; i < 32; i++) { if ((p1 = p->uni_pgdir[i]) != NULL) { for (j = 0; j < 32; j++) - if (p1[j]) - kfree(p1[j]); + kfree(p1[j]); kfree(p1); } p->uni_pgdir[i] = NULL; } - for (i = 0; i < 4; i++) - if (p->inverse_translations[i]) { - kfree(p->inverse_translations[i]); - p->inverse_translations[i] = NULL; - } + for (i = 0; i < 4; i++) { + kfree(p->inverse_translations[i]); + p->inverse_translations[i] = NULL; + } } void con_free_unimap(struct vc_data *vc) diff --git a/drivers/char/drm/ffb_context.c b/drivers/char/drm/ffb_context.c index 8a6cc2751bc..1383727b443 100644 --- a/drivers/char/drm/ffb_context.c +++ b/drivers/char/drm/ffb_context.c @@ -526,10 +526,8 @@ int ffb_driver_rmctx(struct inode *inode, struct file *filp, unsigned int cmd, if (idx < 0 || idx >= FFB_MAX_CTXS) return -EINVAL; - if (fpriv->hw_state[idx] != NULL) { - kfree(fpriv->hw_state[idx]); - fpriv->hw_state[idx] = NULL; - } + kfree(fpriv->hw_state[idx]); + fpriv->hw_state[idx] = NULL; return 0; } diff --git a/drivers/char/drm/ffb_drv.c b/drivers/char/drm/ffb_drv.c index 5c121d6df9f..c13f9abb41e 100644 --- a/drivers/char/drm/ffb_drv.c +++ b/drivers/char/drm/ffb_drv.c @@ -245,14 +245,12 @@ static void ffb_driver_release(drm_device_t * dev, struct file *filp) static void ffb_driver_pretakedown(drm_device_t * dev) { - if (dev->dev_private) - kfree(dev->dev_private); + kfree(dev->dev_private); } static int ffb_driver_postcleanup(drm_device_t * dev) { - if (ffb_position != NULL) - kfree(ffb_position); + kfree(ffb_position); return 0; } diff --git a/drivers/char/ip2/i2ellis.c b/drivers/char/ip2/i2ellis.c index f834d05ccc9..dd761a1e4f0 100644 --- a/drivers/char/ip2/i2ellis.c +++ b/drivers/char/ip2/i2ellis.c @@ -106,9 +106,7 @@ iiEllisInit(void) static void iiEllisCleanup(void) { - if ( pDelayTimer != NULL ) { - kfree ( pDelayTimer ); - } + kfree(pDelayTimer); } //****************************************************************************** diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index e3ddbdb85a2..ce3bc0d45f1 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -860,10 +860,9 @@ static void __exit istallion_module_exit(void) if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"))) printk("STALLION: failed to un-register serial memory device, " "errno=%d\n", -i); - if (stli_tmpwritebuf != (char *) NULL) - kfree(stli_tmpwritebuf); - if (stli_txcookbuf != (char *) NULL) - kfree(stli_txcookbuf); + + kfree(stli_tmpwritebuf); + kfree(stli_txcookbuf); for (i = 0; (i < stli_nrbrds); i++) { if ((brdp = stli_brds[i]) == (stlibrd_t *) NULL) diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index 5079beda69b..c3660d8781a 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c @@ -264,8 +264,7 @@ static void n_hdlc_release(struct n_hdlc *n_hdlc) } else break; } - if (n_hdlc->tbuf) - kfree(n_hdlc->tbuf); + kfree(n_hdlc->tbuf); kfree(n_hdlc); } /* end of n_hdlc_release() */ diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 02d7f046c10..2c326ea5342 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -2994,8 +2994,7 @@ int rx_alloc_buffers(MGSLPC_INFO *info) void rx_free_buffers(MGSLPC_INFO *info) { - if (info->rx_buf) - kfree(info->rx_buf); + kfree(info->rx_buf); info->rx_buf = NULL; } diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 928b850cc67..d3bc731fbb2 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -2512,10 +2512,8 @@ static void rp_cleanup_module(void) "rocketport driver\n", -retval); put_tty_driver(rocket_driver); - for (i = 0; i < MAX_RP_PORTS; i++) { - if (rp_table[i]) - kfree(rp_table[i]); - } + for (i = 0; i < MAX_RP_PORTS; i++) + kfree(rp_table[i]); for (i = 0; i < NUM_BOARDS; i++) { if (rcktpt_io_addr[i] <= 0 || is_PCI[i]) diff --git a/drivers/char/selection.c b/drivers/char/selection.c index 16d630f58bb..5b187c895c1 100644 --- a/drivers/char/selection.c +++ b/drivers/char/selection.c @@ -246,8 +246,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t clear_selection(); return -ENOMEM; } - if (sel_buffer) - kfree(sel_buffer); + kfree(sel_buffer); sel_buffer = bp; obp = bp; diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 1c686414e0a..95af2a94159 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -785,8 +785,7 @@ static void __exit stallion_module_exit(void) "errno=%d\n", -i); class_destroy(stallion_class); - if (stl_tmpwritebuf != (char *) NULL) - kfree(stl_tmpwritebuf); + kfree(stl_tmpwritebuf); for (i = 0; (i < stl_nrbrds); i++) { if ((brdp = stl_brds[i]) == (stlbrd_t *) NULL) @@ -804,8 +803,7 @@ static void __exit stallion_module_exit(void) continue; if (portp->tty != (struct tty_struct *) NULL) stl_hangup(portp->tty); - if (portp->tx.buf != (char *) NULL) - kfree(portp->tx.buf); + kfree(portp->tx.buf); kfree(portp); } kfree(panelp); diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 0133dc0e25d..5d1ffa3bd4c 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -4016,9 +4016,7 @@ static int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info) */ static void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info) { - if ( info->intermediate_rxbuffer ) - kfree(info->intermediate_rxbuffer); - + kfree(info->intermediate_rxbuffer); info->intermediate_rxbuffer = NULL; } /* end of mgsl_free_intermediate_rxbuffer_memory() */ @@ -4072,10 +4070,8 @@ static void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info) int i; for ( i=0; inum_tx_holding_buffers; ++i ) { - if ( info->tx_holding_buffers[i].buffer ) { - kfree(info->tx_holding_buffers[i].buffer); - info->tx_holding_buffers[i].buffer=NULL; - } + kfree(info->tx_holding_buffers[i].buffer); + info->tx_holding_buffers[i].buffer = NULL; } info->get_tx_holding_index = 0; diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index f185724448b..7c063c5abc5 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -2788,10 +2788,8 @@ static void shutdown(SLMP_INFO * info) del_timer(&info->tx_timer); del_timer(&info->status_timer); - if (info->tx_buf) { - kfree(info->tx_buf); - info->tx_buf = NULL; - } + kfree(info->tx_buf); + info->tx_buf = NULL; spin_lock_irqsave(&info->lock,flags); @@ -3611,8 +3609,7 @@ int alloc_tmp_rx_buf(SLMP_INFO *info) void free_tmp_rx_buf(SLMP_INFO *info) { - if (info->tmp_rx_buf) - kfree(info->tmp_rx_buf); + kfree(info->tmp_rx_buf); info->tmp_rx_buf = NULL; } diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index c586bfa852e..4b1eef51ec5 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1416,14 +1416,11 @@ end_init: /* Release locally allocated memory ... nothing placed in slots */ free_mem_out: - if (o_tp) - kfree(o_tp); + kfree(o_tp); if (o_tty) free_tty_struct(o_tty); - if (ltp) - kfree(ltp); - if (tp) - kfree(tp); + kfree(ltp); + kfree(tp); free_tty_struct(tty); fail_no_mem: -- cgit v1.2.3 From 3c7208f253571ee5f157b98f0e315b5172afe092 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 7 Nov 2005 01:01:29 -0800 Subject: [PATCH] kfree cleanup: drivers/isdn This is the drivers/isdn/ part of the big kfree cleanup patch. Remove pointless checks for NULL prior to calling kfree() in drivers/isdn/. Signed-off-by: Jesper Juhl Acked-by: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/hardware/avm/avm_cs.c | 5 +---- drivers/isdn/hisax/avm_pci.c | 12 ++++-------- drivers/isdn/hisax/avma1_cs.c | 4 +--- drivers/isdn/hisax/config.c | 9 +++------ drivers/isdn/hisax/hfc_2bds0.c | 18 ++++++------------ drivers/isdn/hisax/hfc_2bs0.c | 12 ++++-------- drivers/isdn/hisax/hscx.c | 12 ++++-------- drivers/isdn/hisax/icc.c | 12 ++++-------- drivers/isdn/hisax/ipacx.c | 12 ++++-------- drivers/isdn/hisax/isac.c | 15 ++++++--------- drivers/isdn/hisax/isar.c | 6 ++---- drivers/isdn/hisax/jade.c | 12 ++++-------- drivers/isdn/hisax/netjet.c | 32 ++++++++++---------------------- drivers/isdn/hisax/st5481_usb.c | 12 ++++-------- drivers/isdn/hisax/w6692.c | 12 ++++-------- drivers/isdn/hysdn/hysdn_procconf.c | 3 +-- drivers/isdn/i4l/isdn_ppp.c | 21 +++++++-------------- drivers/isdn/i4l/isdn_tty.c | 24 ++++++++---------------- drivers/isdn/pcbit/drv.c | 6 ++---- 19 files changed, 79 insertions(+), 160 deletions(-) diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index db9bad2b3d1..27391c32f3e 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c @@ -212,11 +212,8 @@ static void avmcs_detach(dev_link_t *link) /* Unlink device structure, free pieces */ *linkp = link->next; - if (link->priv) { - kfree(link->priv); - } + kfree(link->priv); kfree(link); - } /* avmcs_detach */ /*====================================================================== diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c index 625799ab0d1..5d8ee7368f7 100644 --- a/drivers/isdn/hisax/avm_pci.c +++ b/drivers/isdn/hisax/avm_pci.c @@ -552,14 +552,10 @@ close_hdlcstate(struct BCState *bcs) { modehdlc(bcs, 0, 0); if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { - if (bcs->hw.hdlc.rcvbuf) { - kfree(bcs->hw.hdlc.rcvbuf); - bcs->hw.hdlc.rcvbuf = NULL; - } - if (bcs->blog) { - kfree(bcs->blog); - bcs->blog = NULL; - } + kfree(bcs->hw.hdlc.rcvbuf); + bcs->hw.hdlc.rcvbuf = NULL; + kfree(bcs->blog); + bcs->blog = NULL; skb_queue_purge(&bcs->rqueue); skb_queue_purge(&bcs->squeue); if (bcs->tx_skb) { diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index 0e22991635e..5f5a5ae740d 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -236,9 +236,7 @@ static void avma1cs_detach(dev_link_t *link) /* Unlink device structure, free pieces */ *linkp = link->next; - if (link->priv) { - kfree(link->priv); - } + kfree(link->priv); kfree(link); } /* avma1cs_detach */ diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index fbaab435290..8159bcecd0c 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -787,8 +787,7 @@ static void ll_unload(struct IsdnCardState *cs) ic.command = ISDN_STAT_UNLOAD; ic.driver = cs->myid; cs->iif.statcallb(&ic); - if (cs->status_buf) - kfree(cs->status_buf); + kfree(cs->status_buf); cs->status_read = NULL; cs->status_write = NULL; cs->status_end = NULL; @@ -807,10 +806,8 @@ static void closecard(int cardnr) skb_queue_purge(&csta->rq); skb_queue_purge(&csta->sq); - if (csta->rcvbuf) { - kfree(csta->rcvbuf); - csta->rcvbuf = NULL; - } + kfree(csta->rcvbuf); + csta->rcvbuf = NULL; if (csta->tx_skb) { dev_kfree_skb(csta->tx_skb); csta->tx_skb = NULL; diff --git a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c index 7cf87793e79..637a261c931 100644 --- a/drivers/isdn/hisax/hfc_2bds0.c +++ b/drivers/isdn/hisax/hfc_2bds0.c @@ -1052,18 +1052,12 @@ init2bds0(struct IsdnCardState *cs) void release2bds0(struct IsdnCardState *cs) { - if (cs->bcs[0].hw.hfc.send) { - kfree(cs->bcs[0].hw.hfc.send); - cs->bcs[0].hw.hfc.send = NULL; - } - if (cs->bcs[1].hw.hfc.send) { - kfree(cs->bcs[1].hw.hfc.send); - cs->bcs[1].hw.hfc.send = NULL; - } - if (cs->hw.hfcD.send) { - kfree(cs->hw.hfcD.send); - cs->hw.hfcD.send = NULL; - } + kfree(cs->bcs[0].hw.hfc.send); + cs->bcs[0].hw.hfc.send = NULL; + kfree(cs->bcs[1].hw.hfc.send); + cs->bcs[1].hw.hfc.send = NULL; + kfree(cs->hw.hfcD.send); + cs->hw.hfcD.send = NULL; } void diff --git a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c index f978a5af866..c964539cc43 100644 --- a/drivers/isdn/hisax/hfc_2bs0.c +++ b/drivers/isdn/hisax/hfc_2bs0.c @@ -582,12 +582,8 @@ inithfc(struct IsdnCardState *cs) void releasehfc(struct IsdnCardState *cs) { - if (cs->bcs[0].hw.hfc.send) { - kfree(cs->bcs[0].hw.hfc.send); - cs->bcs[0].hw.hfc.send = NULL; - } - if (cs->bcs[1].hw.hfc.send) { - kfree(cs->bcs[1].hw.hfc.send); - cs->bcs[1].hw.hfc.send = NULL; - } + kfree(cs->bcs[0].hw.hfc.send); + cs->bcs[0].hw.hfc.send = NULL; + kfree(cs->bcs[1].hw.hfc.send); + cs->bcs[1].hw.hfc.send = NULL; } diff --git a/drivers/isdn/hisax/hscx.c b/drivers/isdn/hisax/hscx.c index 66dbaee77bf..c8f9951f791 100644 --- a/drivers/isdn/hisax/hscx.c +++ b/drivers/isdn/hisax/hscx.c @@ -156,14 +156,10 @@ close_hscxstate(struct BCState *bcs) { modehscx(bcs, 0, bcs->channel); if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { - if (bcs->hw.hscx.rcvbuf) { - kfree(bcs->hw.hscx.rcvbuf); - bcs->hw.hscx.rcvbuf = NULL; - } - if (bcs->blog) { - kfree(bcs->blog); - bcs->blog = NULL; - } + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; + kfree(bcs->blog); + bcs->blog = NULL; skb_queue_purge(&bcs->rqueue); skb_queue_purge(&bcs->squeue); if (bcs->tx_skb) { diff --git a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c index b4ca5859b17..c615752b96a 100644 --- a/drivers/isdn/hisax/icc.c +++ b/drivers/isdn/hisax/icc.c @@ -571,14 +571,10 @@ setstack_icc(struct PStack *st, struct IsdnCardState *cs) static void DC_Close_icc(struct IsdnCardState *cs) { - if (cs->dc.icc.mon_rx) { - kfree(cs->dc.icc.mon_rx); - cs->dc.icc.mon_rx = NULL; - } - if (cs->dc.icc.mon_tx) { - kfree(cs->dc.icc.mon_tx); - cs->dc.icc.mon_tx = NULL; - } + kfree(cs->dc.icc.mon_rx); + cs->dc.icc.mon_rx = NULL; + kfree(cs->dc.icc.mon_tx); + cs->dc.icc.mon_tx = NULL; } static void diff --git a/drivers/isdn/hisax/ipacx.c b/drivers/isdn/hisax/ipacx.c index efba2f44801..2e9afae1254 100644 --- a/drivers/isdn/hisax/ipacx.c +++ b/drivers/isdn/hisax/ipacx.c @@ -762,14 +762,10 @@ bch_close_state(struct BCState *bcs) { bch_mode(bcs, 0, bcs->channel); if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { - if (bcs->hw.hscx.rcvbuf) { - kfree(bcs->hw.hscx.rcvbuf); - bcs->hw.hscx.rcvbuf = NULL; - } - if (bcs->blog) { - kfree(bcs->blog); - bcs->blog = NULL; - } + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; + kfree(bcs->blog); + bcs->blog = NULL; skb_queue_purge(&bcs->rqueue); skb_queue_purge(&bcs->squeue); if (bcs->tx_skb) { diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c index 85e063a08d2..565b7892c26 100644 --- a/drivers/isdn/hisax/isac.c +++ b/drivers/isdn/hisax/isac.c @@ -570,15 +570,12 @@ setstack_isac(struct PStack *st, struct IsdnCardState *cs) } static void -DC_Close_isac(struct IsdnCardState *cs) { - if (cs->dc.isac.mon_rx) { - kfree(cs->dc.isac.mon_rx); - cs->dc.isac.mon_rx = NULL; - } - if (cs->dc.isac.mon_tx) { - kfree(cs->dc.isac.mon_tx); - cs->dc.isac.mon_tx = NULL; - } +DC_Close_isac(struct IsdnCardState *cs) +{ + kfree(cs->dc.isac.mon_rx); + cs->dc.isac.mon_rx = NULL; + kfree(cs->dc.isac.mon_tx); + cs->dc.isac.mon_tx = NULL; } static void diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c index 642a87c5129..674af673ff9 100644 --- a/drivers/isdn/hisax/isar.c +++ b/drivers/isdn/hisax/isar.c @@ -1688,10 +1688,8 @@ close_isarstate(struct BCState *bcs) { modeisar(bcs, 0, bcs->channel); if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { - if (bcs->hw.isar.rcvbuf) { - kfree(bcs->hw.isar.rcvbuf); - bcs->hw.isar.rcvbuf = NULL; - } + kfree(bcs->hw.isar.rcvbuf); + bcs->hw.isar.rcvbuf = NULL; skb_queue_purge(&bcs->rqueue); skb_queue_purge(&bcs->squeue); if (bcs->tx_skb) { diff --git a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c index 363ae3179bb..2659fecc267 100644 --- a/drivers/isdn/hisax/jade.c +++ b/drivers/isdn/hisax/jade.c @@ -195,14 +195,10 @@ close_jadestate(struct BCState *bcs) { modejade(bcs, 0, bcs->channel); if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { - if (bcs->hw.hscx.rcvbuf) { - kfree(bcs->hw.hscx.rcvbuf); - bcs->hw.hscx.rcvbuf = NULL; - } - if (bcs->blog) { - kfree(bcs->blog); - bcs->blog = NULL; - } + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; + kfree(bcs->blog); + bcs->blog = NULL; skb_queue_purge(&bcs->rqueue); skb_queue_purge(&bcs->squeue); if (bcs->tx_skb) { diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c index 94da03c30c5..47a47ef0968 100644 --- a/drivers/isdn/hisax/netjet.c +++ b/drivers/isdn/hisax/netjet.c @@ -855,14 +855,10 @@ close_tigerstate(struct BCState *bcs) { mode_tiger(bcs, 0, bcs->channel); if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { - if (bcs->hw.tiger.rcvbuf) { - kfree(bcs->hw.tiger.rcvbuf); - bcs->hw.tiger.rcvbuf = NULL; - } - if (bcs->hw.tiger.sendbuf) { - kfree(bcs->hw.tiger.sendbuf); - bcs->hw.tiger.sendbuf = NULL; - } + kfree(bcs->hw.tiger.rcvbuf); + bcs->hw.tiger.rcvbuf = NULL; + kfree(bcs->hw.tiger.sendbuf); + bcs->hw.tiger.sendbuf = NULL; skb_queue_purge(&bcs->rqueue); skb_queue_purge(&bcs->squeue); if (bcs->tx_skb) { @@ -967,20 +963,12 @@ inittiger(struct IsdnCardState *cs) static void releasetiger(struct IsdnCardState *cs) { - if (cs->bcs[0].hw.tiger.send) { - kfree(cs->bcs[0].hw.tiger.send); - cs->bcs[0].hw.tiger.send = NULL; - } - if (cs->bcs[1].hw.tiger.send) { - cs->bcs[1].hw.tiger.send = NULL; - } - if (cs->bcs[0].hw.tiger.rec) { - kfree(cs->bcs[0].hw.tiger.rec); - cs->bcs[0].hw.tiger.rec = NULL; - } - if (cs->bcs[1].hw.tiger.rec) { - cs->bcs[1].hw.tiger.rec = NULL; - } + kfree(cs->bcs[0].hw.tiger.send); + cs->bcs[0].hw.tiger.send = NULL; + cs->bcs[1].hw.tiger.send = NULL; + kfree(cs->bcs[0].hw.tiger.rec); + cs->bcs[0].hw.tiger.rec = NULL; + cs->bcs[1].hw.tiger.rec = NULL; } void diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c index 89fbeb58485..b096b64b025 100644 --- a/drivers/isdn/hisax/st5481_usb.c +++ b/drivers/isdn/hisax/st5481_usb.c @@ -335,14 +335,12 @@ void st5481_release_usb(struct st5481_adapter *adapter) // Stop and free Control and Interrupt URBs usb_kill_urb(ctrl->urb); - if (ctrl->urb->transfer_buffer) - kfree(ctrl->urb->transfer_buffer); + kfree(ctrl->urb->transfer_buffer); usb_free_urb(ctrl->urb); ctrl->urb = NULL; usb_kill_urb(intr->urb); - if (intr->urb->transfer_buffer) - kfree(intr->urb->transfer_buffer); + kfree(intr->urb->transfer_buffer); usb_free_urb(intr->urb); ctrl->urb = NULL; } @@ -457,8 +455,7 @@ st5481_setup_isocpipes(struct urb* urb[2], struct usb_device *dev, err: for (j = 0; j < 2; j++) { if (urb[j]) { - if (urb[j]->transfer_buffer) - kfree(urb[j]->transfer_buffer); + kfree(urb[j]->transfer_buffer); urb[j]->transfer_buffer = NULL; usb_free_urb(urb[j]); urb[j] = NULL; @@ -473,8 +470,7 @@ void st5481_release_isocpipes(struct urb* urb[2]) for (j = 0; j < 2; j++) { usb_kill_urb(urb[j]); - if (urb[j]->transfer_buffer) - kfree(urb[j]->transfer_buffer); + kfree(urb[j]->transfer_buffer); usb_free_urb(urb[j]); urb[j] = NULL; } diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c index 7baf8e48847..0352ee5f706 100644 --- a/drivers/isdn/hisax/w6692.c +++ b/drivers/isdn/hisax/w6692.c @@ -819,14 +819,10 @@ close_w6692state(struct BCState *bcs) { W6692Bmode(bcs, 0, bcs->channel); if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { - if (bcs->hw.w6692.rcvbuf) { - kfree(bcs->hw.w6692.rcvbuf); - bcs->hw.w6692.rcvbuf = NULL; - } - if (bcs->blog) { - kfree(bcs->blog); - bcs->blog = NULL; - } + kfree(bcs->hw.w6692.rcvbuf); + bcs->hw.w6692.rcvbuf = NULL; + kfree(bcs->blog); + bcs->blog = NULL; skb_queue_purge(&bcs->rqueue); skb_queue_purge(&bcs->squeue); if (bcs->tx_skb) { diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c index 639582f61f4..87f59a0e2a9 100644 --- a/drivers/isdn/hysdn/hysdn_procconf.c +++ b/drivers/isdn/hysdn/hysdn_procconf.c @@ -359,8 +359,7 @@ hysdn_conf_close(struct inode *ino, struct file *filep) } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { /* read access -> output card info data */ - if (filep->private_data) - kfree(filep->private_data); /* release memory */ + kfree(filep->private_data); /* release memory */ } unlock_kernel(); return (retval); diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c index d97a9be5469..1a19a0f8942 100644 --- a/drivers/isdn/i4l/isdn_ppp.c +++ b/drivers/isdn/i4l/isdn_ppp.c @@ -364,10 +364,8 @@ isdn_ppp_release(int min, struct file *file) isdn_net_hangup(&p->dev); } for (i = 0; i < NUM_RCV_BUFFS; i++) { - if (is->rq[i].buf) { - kfree(is->rq[i].buf); - is->rq[i].buf = NULL; - } + kfree(is->rq[i].buf); + is->rq[i].buf = NULL; } is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */ is->last = is->rq; @@ -378,14 +376,10 @@ isdn_ppp_release(int min, struct file *file) is->slcomp = NULL; #endif #ifdef CONFIG_IPPP_FILTER - if (is->pass_filter) { - kfree(is->pass_filter); - is->pass_filter = NULL; - } - if (is->active_filter) { - kfree(is->active_filter); - is->active_filter = NULL; - } + kfree(is->pass_filter); + is->pass_filter = NULL; + kfree(is->active_filter); + is->active_filter = NULL; #endif /* TODO: if this was the previous master: link the stuff to the new master */ @@ -914,8 +908,7 @@ isdn_ppp_cleanup(void) kfree(ippp_table[i]); #ifdef CONFIG_ISDN_MPP - if (isdn_ppp_bundle_arr) - kfree(isdn_ppp_bundle_arr); + kfree(isdn_ppp_bundle_arr); #endif /* CONFIG_ISDN_MPP */ } diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 356ee485be4..8c404b4e248 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -712,22 +712,14 @@ isdn_tty_modem_hup(modem_info * info, int local) #endif info->emu.vpar[4] = 0; info->emu.vpar[5] = 8; - if (info->dtmf_state) { - kfree(info->dtmf_state); - info->dtmf_state = NULL; - } - if (info->silence_state) { - kfree(info->silence_state); - info->silence_state = NULL; - } - if (info->adpcms) { - kfree(info->adpcms); - info->adpcms = NULL; - } - if (info->adpcmr) { - kfree(info->adpcmr); - info->adpcmr = NULL; - } + kfree(info->dtmf_state); + info->dtmf_state = NULL; + kfree(info->silence_state); + info->silence_state = NULL; + kfree(info->adpcms); + info->adpcms = NULL; + kfree(info->adpcmr); + info->adpcmr = NULL; #endif if ((info->msr & UART_MSR_RI) && (info->emu.mdmreg[REG_RUNG] & BIT_RUNG)) diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c index 5de861f4081..94f21486bb2 100644 --- a/drivers/isdn/pcbit/drv.c +++ b/drivers/isdn/pcbit/drv.c @@ -561,10 +561,8 @@ void pcbit_l3_receive(struct pcbit_dev * dev, ulong msg, else pcbit_fsm_event(dev, chan, EV_USR_RELEASE_REQ, NULL); - if (cbdata.data.setup.CalledPN) - kfree(cbdata.data.setup.CalledPN); - if (cbdata.data.setup.CallingPN) - kfree(cbdata.data.setup.CallingPN); + kfree(cbdata.data.setup.CalledPN); + kfree(cbdata.data.setup.CallingPN); break; case MSG_CONN_CONF: -- cgit v1.2.3 From 17fd682e544556a2a829e94383239c029bb21c5e Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 7 Nov 2005 01:01:30 -0800 Subject: [PATCH] kfree cleanup: drivers/s390 This is the drivers/s390/ part of the big kfree cleanup patch. Remove pointless checks for NULL prior to calling kfree() in drivers/s390/. Signed-off-by: Jesper Juhl Acked-by: Cornelia Huck Acked-by: Stefan Bader Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/block/dasd.c | 12 ++++-------- drivers/s390/block/dasd_devmap.c | 3 +-- drivers/s390/char/con3215.c | 3 +-- drivers/s390/char/keyboard.c | 15 +++++---------- drivers/s390/char/raw3270.c | 3 +-- drivers/s390/char/tape_core.c | 9 +++------ drivers/s390/cio/cmf.c | 3 +-- drivers/s390/cio/device_ops.c | 6 ++---- drivers/s390/cio/qdio.c | 9 +++------ drivers/s390/crypto/z90main.c | 7 +++---- drivers/s390/net/claw.c | 36 ++++++++++++------------------------ drivers/s390/net/fsm.c | 3 +-- drivers/s390/net/iucv.c | 12 ++++-------- drivers/s390/net/lcs.c | 3 +-- drivers/s390/net/qeth_eddp.c | 3 +-- drivers/s390/scsi/zfcp_aux.c | 3 +-- 16 files changed, 44 insertions(+), 86 deletions(-) diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 8fc891a9d47..7008d32433b 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -115,8 +115,7 @@ dasd_alloc_device(void) void dasd_free_device(struct dasd_device *device) { - if (device->private) - kfree(device->private); + kfree(device->private); free_page((unsigned long) device->erp_mem); free_pages((unsigned long) device->ccw_mem, 1); kfree(device); @@ -539,8 +538,7 @@ dasd_kmalloc_request(char *magic, int cplength, int datasize, if (datasize > 0) { cqr->data = kmalloc(datasize, GFP_ATOMIC | GFP_DMA); if (cqr->data == NULL) { - if (cqr->cpaddr != NULL) - kfree(cqr->cpaddr); + kfree(cqr->cpaddr); kfree(cqr); return ERR_PTR(-ENOMEM); } @@ -615,10 +613,8 @@ dasd_kfree_request(struct dasd_ccw_req * cqr, struct dasd_device * device) clear_normalized_cda(ccw); } while (ccw++->flags & (CCW_FLAG_CC | CCW_FLAG_DC)); #endif - if (cqr->cpaddr != NULL) - kfree(cqr->cpaddr); - if (cqr->data != NULL) - kfree(cqr->data); + kfree(cqr->cpaddr); + kfree(cqr->data); kfree(cqr); dasd_put_device(device); } diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index bda896d9d78..caee16a3dc6 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -387,8 +387,7 @@ dasd_add_busid(char *bus_id, int features) new = 0; } spin_unlock(&dasd_devmap_lock); - if (new) - kfree(new); + kfree(new); return devmap; } diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index f11a67fda40..75419cf9d35 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -727,8 +727,7 @@ raw3215_remove (struct ccw_device *cdev) raw = cdev->dev.driver_data; if (raw) { cdev->dev.driver_data = NULL; - if (raw->buffer) - kfree(raw->buffer); + kfree(raw->buffer); kfree(raw); } } diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c index fd43d99b45a..5bda2340a39 100644 --- a/drivers/s390/char/keyboard.c +++ b/drivers/s390/char/keyboard.c @@ -99,13 +99,11 @@ out_fn_handler: kfree(kbd->fn_handler); out_func: for (i = 0; i < ARRAY_SIZE(func_table); i++) - if (kbd->func_table[i]) - kfree(kbd->func_table[i]); + kfree(kbd->func_table[i]); kfree(kbd->func_table); out_maps: for (i = 0; i < ARRAY_SIZE(key_maps); i++) - if (kbd->key_maps[i]) - kfree(kbd->key_maps[i]); + kfree(kbd->key_maps[i]); kfree(kbd->key_maps); out_kbd: kfree(kbd); @@ -121,12 +119,10 @@ kbd_free(struct kbd_data *kbd) kfree(kbd->accent_table); kfree(kbd->fn_handler); for (i = 0; i < ARRAY_SIZE(func_table); i++) - if (kbd->func_table[i]) - kfree(kbd->func_table[i]); + kfree(kbd->func_table[i]); kfree(kbd->func_table); for (i = 0; i < ARRAY_SIZE(key_maps); i++) - if (kbd->key_maps[i]) - kfree(kbd->key_maps[i]); + kfree(kbd->key_maps[i]); kfree(kbd->key_maps); kfree(kbd); } @@ -452,8 +448,7 @@ do_kdgkb_ioctl(struct kbd_data *kbd, struct kbsentry __user *u_kbs, return -EFAULT; } p[len] = 0; - if (kbd->func_table[kb_func]) - kfree(kbd->func_table[kb_func]); + kfree(kbd->func_table[kb_func]); kbd->func_table[kb_func] = p; break; } diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index d66946443df..f5b7d360fc1 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -183,8 +183,7 @@ raw3270_request_alloc_bootmem(size_t size) void raw3270_request_free (struct raw3270_request *rq) { - if (rq->buffer) - kfree(rq->buffer); + kfree(rq->buffer); kfree(rq); } diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index 6c52e8307dc..8f486e1a850 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c @@ -682,8 +682,7 @@ tape_alloc_request(int cplength, int datasize) request->cpdata = kmalloc(datasize, GFP_KERNEL | GFP_DMA); if (request->cpdata == NULL) { DBF_EXCEPTION(1, "cqra nomem\n"); - if (request->cpaddr != NULL) - kfree(request->cpaddr); + kfree(request->cpaddr); kfree(request); return ERR_PTR(-ENOMEM); } @@ -706,10 +705,8 @@ tape_free_request (struct tape_request * request) if (request->device != NULL) { request->device = tape_put_device(request->device); } - if (request->cpdata != NULL) - kfree(request->cpdata); - if (request->cpaddr != NULL) - kfree(request->cpaddr); + kfree(request->cpdata); + kfree(request->cpaddr); kfree(request); } diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index c05b069c299..b978f7fe832 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c @@ -642,8 +642,7 @@ static void free_cmbe (struct ccw_device *cdev) { spin_lock_irq(cdev->ccwlock); - if (cdev->private->cmb) - kfree(cdev->private->cmb); + kfree(cdev->private->cmb); cdev->private->cmb = NULL; spin_unlock_irq(cdev->ccwlock); diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index ad3fe5aeb66..85a3026e690 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -550,10 +550,8 @@ ccw_device_stlck(struct ccw_device *cdev) /* Clear irb. */ memset(&cdev->private->irb, 0, sizeof(struct irb)); out_unlock: - if (buf) - kfree(buf); - if (buf2) - kfree(buf2); + kfree(buf); + kfree(buf2); spin_unlock_irqrestore(&sch->lock, flags); return ret; } diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index ef5cd07011b..eb39218b925 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c @@ -1338,16 +1338,14 @@ qdio_release_irq_memory(struct qdio_irq *irq_ptr) if (!irq_ptr->input_qs[i]) goto next; - if (irq_ptr->input_qs[i]->slib) - kfree(irq_ptr->input_qs[i]->slib); + kfree(irq_ptr->input_qs[i]->slib); kfree(irq_ptr->input_qs[i]); next: if (!irq_ptr->output_qs[i]) continue; - if (irq_ptr->output_qs[i]->slib) - kfree(irq_ptr->output_qs[i]->slib); + kfree(irq_ptr->output_qs[i]->slib); kfree(irq_ptr->output_qs[i]); } @@ -3315,8 +3313,7 @@ qdio_get_qdio_memory(void) static void qdio_release_qdio_memory(void) { - if (indicators) - kfree(indicators); + kfree(indicators); } static void diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c index 0cb47eca91f..04c2ef778ec 100644 --- a/drivers/s390/crypto/z90main.c +++ b/drivers/s390/crypto/z90main.c @@ -3051,8 +3051,7 @@ destroy_crypto_device(int index) if (dev_ptr) { disabledFlag = dev_ptr->disabled; t = dev_ptr->dev_type; - if (dev_ptr->dev_resp_p) - kfree(dev_ptr->dev_resp_p); + kfree(dev_ptr->dev_resp_p); kfree(dev_ptr); } else { disabledFlag = 0; @@ -3080,11 +3079,11 @@ static void destroy_z90crypt(void) { int i; + for (i = 0; i < z90crypt.max_count; i++) if (z90crypt.device_p[i]) destroy_crypto_device(i); - if (z90crypt.hdware_info) - kfree((void *)z90crypt.hdware_info); + kfree(z90crypt.hdware_info); memset((void *)&z90crypt, 0, sizeof(z90crypt)); } diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index 3092473991a..1a1c3decea7 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -2743,14 +2743,10 @@ probe_error( struct ccwgroup_device *cgdev) #endif privptr=(struct claw_privbk *)cgdev->dev.driver_data; if (privptr!=NULL) { - if (privptr->p_env != NULL) { - kfree(privptr->p_env); - privptr->p_env=NULL; - } - if (privptr->p_mtc_envelope!=NULL) { - kfree(privptr->p_mtc_envelope); - privptr->p_mtc_envelope=NULL; - } + kfree(privptr->p_env); + privptr->p_env=NULL; + kfree(privptr->p_mtc_envelope); + privptr->p_mtc_envelope=NULL; kfree(privptr); privptr=NULL; } @@ -4121,22 +4117,14 @@ claw_remove_device(struct ccwgroup_device *cgdev) if (cgdev->state == CCWGROUP_ONLINE) claw_shutdown_device(cgdev); claw_remove_files(&cgdev->dev); - if (priv->p_mtc_envelope!=NULL) { - kfree(priv->p_mtc_envelope); - priv->p_mtc_envelope=NULL; - } - if (priv->p_env != NULL) { - kfree(priv->p_env); - priv->p_env=NULL; - } - if (priv->channel[0].irb != NULL) { - kfree(priv->channel[0].irb); - priv->channel[0].irb=NULL; - } - if (priv->channel[1].irb != NULL) { - kfree(priv->channel[1].irb); - priv->channel[1].irb=NULL; - } + kfree(priv->p_mtc_envelope); + priv->p_mtc_envelope=NULL; + kfree(priv->p_env); + priv->p_env=NULL; + kfree(priv->channel[0].irb); + priv->channel[0].irb=NULL; + kfree(priv->channel[1].irb); + priv->channel[1].irb=NULL; kfree(priv); cgdev->dev.driver_data=NULL; cgdev->cdev[READ]->dev.driver_data = NULL; diff --git a/drivers/s390/net/fsm.c b/drivers/s390/net/fsm.c index 38f50b7129a..24029bd9c7d 100644 --- a/drivers/s390/net/fsm.c +++ b/drivers/s390/net/fsm.c @@ -78,8 +78,7 @@ kfree_fsm(fsm_instance *this) { if (this) { if (this->f) { - if (this->f->jumpmatrix) - kfree(this->f->jumpmatrix); + kfree(this->f->jumpmatrix); kfree(this->f); } kfree(this); diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c index e08e74e1612..df7647c3c10 100644 --- a/drivers/s390/net/iucv.c +++ b/drivers/s390/net/iucv.c @@ -447,14 +447,10 @@ static void iucv_exit(void) { iucv_retrieve_buffer(); - if (iucv_external_int_buffer) { - kfree(iucv_external_int_buffer); - iucv_external_int_buffer = NULL; - } - if (iucv_param_pool) { - kfree(iucv_param_pool); - iucv_param_pool = NULL; - } + kfree(iucv_external_int_buffer); + iucv_external_int_buffer = NULL; + kfree(iucv_param_pool); + iucv_param_pool = NULL; s390_root_dev_unregister(iucv_root); bus_unregister(&iucv_bus); printk(KERN_INFO "IUCV lowlevel driver unloaded\n"); diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 46f34ba93ac..1c8ad2fcad8 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -145,8 +145,7 @@ lcs_free_channel(struct lcs_channel *channel) LCS_DBF_TEXT(2, setup, "ichfree"); for (cnt = 0; cnt < LCS_NUM_BUFFS; cnt++) { - if (channel->iob[cnt].data != NULL) - kfree(channel->iob[cnt].data); + kfree(channel->iob[cnt].data); channel->iob[cnt].data = NULL; } } diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c index f94f1f25eec..011915d5e24 100644 --- a/drivers/s390/net/qeth_eddp.c +++ b/drivers/s390/net/qeth_eddp.c @@ -62,8 +62,7 @@ qeth_eddp_free_context(struct qeth_eddp_context *ctx) for (i = 0; i < ctx->num_pages; ++i) free_page((unsigned long)ctx->pages[i]); kfree(ctx->pages); - if (ctx->elements != NULL) - kfree(ctx->elements); + kfree(ctx->elements); kfree(ctx); } diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index cab098556b4..c218b5c944a 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -450,8 +450,7 @@ zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command, kfree(sg_list); } - if (sense_data != NULL) - kfree(sense_data); + kfree(sense_data); return retval; } -- cgit v1.2.3 From 2ea7533060e361810c21b2f5ee02151c4dfb85d8 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 7 Nov 2005 01:01:31 -0800 Subject: [PATCH] kfree cleanup: drivers/media This is the drivers/media/ part of the big kfree cleanup patch. Remove pointless checks for NULL prior to calling kfree() in drivers/media/. Signed-off-by: Jesper Juhl Cc: Johannes Stezenbach Cc: Michael Krufky Cc: Mauro Carvalho Chehab Acked-by : Manu Abraham Acked-by: Andreas Oberritter Acked-by: Wilson Michaels Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/bt8xx/dst.c | 8 ++------ drivers/media/dvb/frontends/dvb_dummy_fe.c | 4 ++-- drivers/media/dvb/frontends/l64781.c | 3 ++- drivers/media/dvb/frontends/lgdt330x.c | 3 +-- drivers/media/dvb/frontends/mt312.c | 3 +-- drivers/media/dvb/frontends/or51132.c | 3 +-- drivers/media/video/arv.c | 12 ++++-------- drivers/media/video/bttv-driver.c | 6 ++---- drivers/media/video/v4l1-compat.c | 6 ++---- drivers/media/video/videocodec.c | 6 ++---- drivers/media/video/videodev.c | 3 +-- drivers/media/video/zoran_card.c | 14 ++++++-------- 12 files changed, 26 insertions(+), 45 deletions(-) diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 34a837a1abf..b3c9d7327ac 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -1331,9 +1331,7 @@ struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_ad { /* check if the ASIC is there */ if (dst_probe(state) < 0) { - if (state) - kfree(state); - + kfree(state); return NULL; } /* determine settings based on type */ @@ -1349,9 +1347,7 @@ struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_ad break; default: dprintk(verbose, DST_ERROR, 1, "unknown DST type. please report to the LinuxTV.org DVB mailinglist."); - if (state) - kfree(state); - + kfree(state); return NULL; } diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb/frontends/dvb_dummy_fe.c index 794be520d59..645946a992d 100644 --- a/drivers/media/dvb/frontends/dvb_dummy_fe.c +++ b/drivers/media/dvb/frontends/dvb_dummy_fe.c @@ -148,7 +148,7 @@ struct dvb_frontend* dvb_dummy_fe_qpsk_attach() return &state->frontend; error: - if (state) kfree(state); + kfree(state); return NULL; } @@ -171,7 +171,7 @@ struct dvb_frontend* dvb_dummy_fe_qam_attach() return &state->frontend; error: - if (state) kfree(state); + kfree(state); return NULL; } diff --git a/drivers/media/dvb/frontends/l64781.c b/drivers/media/dvb/frontends/l64781.c index faaad1ae855..19b4bf7c21a 100644 --- a/drivers/media/dvb/frontends/l64781.c +++ b/drivers/media/dvb/frontends/l64781.c @@ -559,7 +559,8 @@ struct dvb_frontend* l64781_attach(const struct l64781_config* config, return &state->frontend; error: - if (reg0x3e >= 0) l64781_writereg (state, 0x3e, reg0x3e); /* restore reg 0x3e */ + if (reg0x3e >= 0) + l64781_writereg (state, 0x3e, reg0x3e); /* restore reg 0x3e */ kfree(state); return NULL; } diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index 8dde72bd104..7852b83b82d 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c @@ -731,8 +731,7 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config, return &state->frontend; error: - if (state) - kfree(state); + kfree(state); dprintk("%s: ERROR\n",__FUNCTION__); return NULL; } diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c index e38454901dd..9c67f406d58 100644 --- a/drivers/media/dvb/frontends/mt312.c +++ b/drivers/media/dvb/frontends/mt312.c @@ -677,8 +677,7 @@ struct dvb_frontend* mt312_attach(const struct mt312_config* config, return &state->frontend; error: - if (state) - kfree(state); + kfree(state); return NULL; } diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c index 817b044c7fd..fc74c40d647 100644 --- a/drivers/media/dvb/frontends/or51132.c +++ b/drivers/media/dvb/frontends/or51132.c @@ -577,8 +577,7 @@ struct dvb_frontend* or51132_attach(const struct or51132_config* config, return &state->frontend; error: - if (state) - kfree(state); + kfree(state); return NULL; } diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index 87fd3a7bb39..0823ddaf700 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -865,10 +865,8 @@ out_dev: out_irq: #endif - for (i = 0; i < MAX_AR_HEIGHT; i++) { - if (ar->frame[i]) - kfree(ar->frame[i]); - } + for (i = 0; i < MAX_AR_HEIGHT; i++) + kfree(ar->frame[i]); out_line_buff: #if USE_INT @@ -899,10 +897,8 @@ static void __exit ar_cleanup_module(void) #if USE_INT free_irq(M32R_IRQ_INT3, ar); #endif - for (i = 0; i < MAX_AR_HEIGHT; i++) { - if (ar->frame[i]) - kfree(ar->frame[i]); - } + for (i = 0; i < MAX_AR_HEIGHT; i++) + kfree(ar->frame[i]); #if USE_INT kfree(ar->line_buff); #endif diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index c062a017491..d538a994ff0 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -1951,8 +1951,7 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv, } down(&fh->cap.lock); - if (fh->ov.clips) - kfree(fh->ov.clips); + kfree(fh->ov.clips); fh->ov.clips = clips; fh->ov.nclips = n; @@ -2723,8 +2722,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, fh->ov.w.height = fb->fmt.height; btv->init.ov.w.width = fb->fmt.width; btv->init.ov.w.height = fb->fmt.height; - if (fh->ov.clips) - kfree(fh->ov.clips); + kfree(fh->ov.clips); fh->ov.clips = NULL; fh->ov.nclips = 0; diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index 59bb71381a1..d679ca23ded 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c @@ -1006,10 +1006,8 @@ v4l_compat_translate_ioctl(struct inode *inode, break; } - if (cap2) - kfree(cap2); - if (fmt2) - kfree(fmt2); + kfree(cap2); + kfree(fmt2); return err; } diff --git a/drivers/media/video/videocodec.c b/drivers/media/video/videocodec.c index c9d5f1a873c..839db622040 100644 --- a/drivers/media/video/videocodec.c +++ b/drivers/media/video/videocodec.c @@ -353,8 +353,7 @@ videocodec_build_table (void) dprintk(3, "videocodec_build table: %d entries, %d bytes\n", i, size); - if (videocodec_buf) - kfree(videocodec_buf); + kfree(videocodec_buf); videocodec_buf = (char *) kmalloc(size, GFP_KERNEL); i = 0; @@ -471,8 +470,7 @@ videocodec_exit (void) { #ifdef CONFIG_PROC_FS remove_proc_entry("videocodecs", NULL); - if (videocodec_buf) - kfree(videocodec_buf); + kfree(videocodec_buf); #endif } diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 06df15f75de..83c49f9610d 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -215,8 +215,7 @@ video_usercopy(struct inode *inode, struct file *file, } out: - if (mbuf) - kfree(mbuf); + kfree(mbuf); return err; } diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c index eed2acea177..39a0d238900 100644 --- a/drivers/media/video/zoran_card.c +++ b/drivers/media/video/zoran_card.c @@ -1057,10 +1057,8 @@ zr36057_init (struct zoran *zr) KERN_ERR "%s: zr36057_init() - kmalloc (STAT_COM) failed\n", ZR_DEVNAME(zr)); - if (vdev) - kfree(vdev); - if (mem) - kfree((void *)mem); + kfree(vdev); + kfree((void *)mem); return -ENOMEM; } memset((void *) mem, 0, mem_needed); @@ -1105,15 +1103,15 @@ zoran_release (struct zoran *zr) /* unregister videocodec bus */ if (zr->codec) { struct videocodec_master *master = zr->codec->master_data; + videocodec_detach(zr->codec); - if (master) - kfree(master); + kfree(master); } if (zr->vfe) { struct videocodec_master *master = zr->vfe->master_data; + videocodec_detach(zr->vfe); - if (master) - kfree(master); + kfree(master); } /* unregister i2c bus */ -- cgit v1.2.3 From 6044ec8882c726e325017bd948aa0cd94ad33abc Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 7 Nov 2005 01:01:32 -0800 Subject: [PATCH] kfree cleanup: misc remaining drivers This is the remaining misc drivers/ part of the big kfree cleanup patch. Remove pointless checks for NULL prior to calling kfree() in misc files in drivers/. Signed-off-by: Jesper Juhl Acked-by: Aristeu Sergio Rozanski Filho Acked-by: Roland Dreier Acked-by: Pierre Ossman Acked-by: Jean Delvare Acked-by: Greg Kroah-Hartman Acked-by: Len Brown Acked-by: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/acpi/container.c | 6 ++---- drivers/acpi/scan.c | 6 ++---- drivers/acpi/video.c | 12 ++++-------- drivers/block/DAC960.c | 31 +++++++++++-------------------- drivers/block/cciss.c | 12 ++++-------- drivers/fc4/fc.c | 5 ++--- drivers/hwmon/w83781d.c | 6 ++---- drivers/i2c/busses/i2c-amd756-s4882.c | 6 ++---- drivers/ide/ide-cd.c | 18 ++++++------------ drivers/ide/ide-probe.c | 6 ++---- drivers/ide/ide-taskfile.c | 6 ++---- drivers/ide/ide.c | 3 +-- drivers/infiniband/core/mad.c | 6 ++---- drivers/input/misc/uinput.c | 10 +++------- drivers/macintosh/adbhid.c | 3 +-- drivers/mmc/wbsd.c | 3 +-- drivers/parport/probe.c | 21 ++++++++++----------- drivers/parport/share.c | 19 +++++++------------ drivers/pci/hotplug/cpqphp_pci.c | 15 +++++---------- drivers/pcmcia/cistpl.c | 12 ++++-------- drivers/pcmcia/cs.c | 6 ++---- drivers/sbus/char/envctrl.c | 13 +++++-------- drivers/video/i810/i810_main.c | 3 +-- drivers/w1/w1_ds2433.c | 6 ++---- 24 files changed, 83 insertions(+), 151 deletions(-) diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 10dd695a1dd..27ec12c1fab 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -118,11 +118,9 @@ static int acpi_container_remove(struct acpi_device *device, int type) { acpi_status status = AE_OK; struct acpi_container *pc = NULL; - pc = (struct acpi_container *)acpi_driver_data(device); - - if (pc) - kfree(pc); + pc = (struct acpi_container *)acpi_driver_data(device); + kfree(pc); return status; } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index c6db591479d..23e2c6968a1 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -28,8 +28,7 @@ static int acpi_bus_trim(struct acpi_device *start, int rmdevice); static void acpi_device_release(struct kobject *kobj) { struct acpi_device *dev = container_of(kobj, struct acpi_device, kobj); - if (dev->pnp.cid_list) - kfree(dev->pnp.cid_list); + kfree(dev->pnp.cid_list); kfree(dev); } @@ -1117,8 +1116,7 @@ acpi_add_single_object(struct acpi_device **child, if (!result) *child = device; else { - if (device->pnp.cid_list) - kfree(device->pnp.cid_list); + kfree(device->pnp.cid_list); kfree(device); } diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index e383d6109ae..f051b151580 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -334,8 +334,7 @@ acpi_video_device_lcd_query_levels(struct acpi_video_device *device, return_VALUE(0); err: - if (buffer.pointer) - kfree(buffer.pointer); + kfree(buffer.pointer); return_VALUE(status); } @@ -1488,8 +1487,7 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) } active_device_list[count].value.int_val = ACPI_VIDEO_HEAD_END; - if (video->attached_array) - kfree(video->attached_array); + kfree(video->attached_array); video->attached_array = active_device_list; video->attached_count = count; @@ -1645,8 +1643,7 @@ static int acpi_video_bus_put_devices(struct acpi_video_bus *video) printk(KERN_WARNING PREFIX "hhuuhhuu bug in acpi video driver.\n"); - if (data->brightness) - kfree(data->brightness); + kfree(data->brightness); kfree(data); } @@ -1831,8 +1828,7 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type) acpi_video_bus_put_devices(video); acpi_video_bus_remove_fs(device); - if (video->attached_array) - kfree(video->attached_array); + kfree(video->attached_array); kfree(video); return_VALUE(0); diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 3760edfdc65..70eaa5c7ac0 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -417,14 +417,12 @@ static void DAC960_DestroyAuxiliaryStructures(DAC960_Controller_T *Controller) * Remember the beginning of the group, but don't free it * until we've reached the beginning of the next group. */ - if (CommandGroup != NULL) - kfree(CommandGroup); - CommandGroup = Command; + kfree(CommandGroup); + CommandGroup = Command; } Controller->Commands[i] = NULL; } - if (CommandGroup != NULL) - kfree(CommandGroup); + kfree(CommandGroup); if (Controller->CombinedStatusBuffer != NULL) { @@ -435,30 +433,23 @@ static void DAC960_DestroyAuxiliaryStructures(DAC960_Controller_T *Controller) if (ScatterGatherPool != NULL) pci_pool_destroy(ScatterGatherPool); - if (Controller->FirmwareType == DAC960_V1_Controller) return; + if (Controller->FirmwareType == DAC960_V1_Controller) + return; if (RequestSensePool != NULL) pci_pool_destroy(RequestSensePool); - for (i = 0; i < DAC960_MaxLogicalDrives; i++) - if (Controller->V2.LogicalDeviceInformation[i] != NULL) - { + for (i = 0; i < DAC960_MaxLogicalDrives; i++) { kfree(Controller->V2.LogicalDeviceInformation[i]); Controller->V2.LogicalDeviceInformation[i] = NULL; - } + } for (i = 0; i < DAC960_V2_MaxPhysicalDevices; i++) { - if (Controller->V2.PhysicalDeviceInformation[i] != NULL) - { - kfree(Controller->V2.PhysicalDeviceInformation[i]); - Controller->V2.PhysicalDeviceInformation[i] = NULL; - } - if (Controller->V2.InquiryUnitSerialNumber[i] != NULL) - { - kfree(Controller->V2.InquiryUnitSerialNumber[i]); - Controller->V2.InquiryUnitSerialNumber[i] = NULL; - } + kfree(Controller->V2.PhysicalDeviceInformation[i]); + Controller->V2.PhysicalDeviceInformation[i] = NULL; + kfree(Controller->V2.InquiryUnitSerialNumber[i]); + Controller->V2.InquiryUnitSerialNumber[i] = NULL; } } diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 486b6e1c7df..a97c80b5773 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -1096,14 +1096,11 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, cleanup1: if (buff) { for(i=0; icmd_pool_bits) - kfree(hba[i]->cmd_pool_bits); + kfree(hba[i]->cmd_pool_bits); if(hba[i]->cmd_pool) pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct), diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c index e375995a2e9..5c8943509cc 100644 --- a/drivers/fc4/fc.c +++ b/drivers/fc4/fc.c @@ -554,8 +554,8 @@ int fcp_initialize(fc_channel *fcchain, int count) l->logi = kzalloc (count * 3 * sizeof(logi), GFP_KERNEL); l->fcmds = kzalloc (count * sizeof(fcp_cmnd), GFP_KERNEL); if (!l->logi || !l->fcmds) { - if (l->logi) kfree (l->logi); - if (l->fcmds) kfree (l->fcmds); + kfree (l->logi); + kfree (l->fcmds); kfree (l); printk ("FC: Cannot allocate DMA memory for initialization\n"); return -ENOMEM; @@ -674,7 +674,6 @@ int fcp_forceoffline(fc_channel *fcchain, int count) atomic_set (&l.todo, count); l.fcmds = kzalloc (count * sizeof(fcp_cmnd), GFP_KERNEL); if (!l.fcmds) { - kfree (l.fcmds); printk ("FC: Cannot allocate memory for forcing offline\n"); return -ENOMEM; } diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index 9265f32122f..ffdb3a03e2b 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -976,11 +976,9 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind, ERROR_SC_3: i2c_detach_client(data->lm75[0]); ERROR_SC_2: - if (data->lm75[1]) - kfree(data->lm75[1]); + kfree(data->lm75[1]); ERROR_SC_1: - if (data->lm75[0]) - kfree(data->lm75[0]); + kfree(data->lm75[0]); ERROR_SC_0: return err; } diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c index f51ab652300..56c7d987590 100644 --- a/drivers/i2c/busses/i2c-amd756-s4882.c +++ b/drivers/i2c/busses/i2c-amd756-s4882.c @@ -245,10 +245,8 @@ static void __exit amd756_s4882_exit(void) kfree(s4882_adapter); s4882_adapter = NULL; } - if (s4882_algo) { - kfree(s4882_algo); - s4882_algo = NULL; - } + kfree(s4882_algo); + s4882_algo = NULL; /* Restore physical bus */ if (i2c_add_adapter(&amd756_smbus)) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 74d2ab0d901..c2f47923d17 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -3292,12 +3292,9 @@ static void ide_cd_release(struct kref *kref) ide_drive_t *drive = info->drive; struct gendisk *g = info->disk; - if (info->buffer != NULL) - kfree(info->buffer); - if (info->toc != NULL) - kfree(info->toc); - if (info->changer_info != NULL) - kfree(info->changer_info); + kfree(info->buffer); + kfree(info->toc); + kfree(info->changer_info); if (devinfo->handle == drive && unregister_cdrom(devinfo)) printk(KERN_ERR "%s: %s failed to unregister device from the cdrom " "driver.\n", __FUNCTION__, drive->name); @@ -3487,12 +3484,9 @@ static int ide_cd_probe(struct device *dev) if (ide_cdrom_setup(drive)) { struct cdrom_device_info *devinfo = &info->devinfo; ide_unregister_subdriver(drive, &ide_cdrom_driver); - if (info->buffer != NULL) - kfree(info->buffer); - if (info->toc != NULL) - kfree(info->toc); - if (info->changer_info != NULL) - kfree(info->changer_info); + kfree(info->buffer); + kfree(info->toc); + kfree(info->changer_info); if (devinfo->handle == drive && unregister_cdrom(devinfo)) printk (KERN_ERR "%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name); kfree(info); diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index e6695e5df5b..02167a5b751 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1315,10 +1315,8 @@ static void drive_release_dev (struct device *dev) drive->devfs_name[0] = '\0'; } ide_remove_drive_from_hwgroup(drive); - if (drive->id != NULL) { - kfree(drive->id); - drive->id = NULL; - } + kfree(drive->id); + drive->id = NULL; drive->present = 0; /* Messed up locking ... */ spin_unlock_irq(&ide_lock); diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 9c3b4f61562..7ec18fa3b5f 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -646,10 +646,8 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) } abort: kfree(req_task); - if (outbuf != NULL) - kfree(outbuf); - if (inbuf != NULL) - kfree(inbuf); + kfree(outbuf); + kfree(inbuf); // printk("IDE Taskfile ioctl ended. rc = %i\n", err); diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 1bbf67882ae..9fe19808d81 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -888,8 +888,7 @@ static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int r return 0; abort: up(&ide_setting_sem); - if (setting) - kfree(setting); + kfree(setting); return -1; } diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 3d8175e5f05..41d6b4017ac 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -508,8 +508,7 @@ static void unregister_mad_agent(struct ib_mad_agent_private *mad_agent_priv) wait_event(mad_agent_priv->wait, !atomic_read(&mad_agent_priv->refcount)); - if (mad_agent_priv->reg_req) - kfree(mad_agent_priv->reg_req); + kfree(mad_agent_priv->reg_req); ib_dereg_mr(mad_agent_priv->agent.mr); kfree(mad_agent_priv); } @@ -2500,8 +2499,7 @@ error: static void destroy_mad_qp(struct ib_mad_qp_info *qp_info) { ib_destroy_qp(qp_info->qp); - if (qp_info->snoop_table) - kfree(qp_info->snoop_table); + kfree(qp_info->snoop_table); } /* diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 4015a91f4b6..948c1cc01bc 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -271,8 +271,7 @@ static int uinput_alloc_device(struct file *file, const char __user *buffer, siz goto exit; } - if (dev->name) - kfree(dev->name); + kfree(dev->name); size = strnlen(user_dev->name, UINPUT_MAX_NAME_SIZE) + 1; dev->name = name = kmalloc(size, GFP_KERNEL); @@ -372,11 +371,8 @@ static int uinput_burn_device(struct uinput_device *udev) if (test_bit(UIST_CREATED, &udev->state)) uinput_destroy_device(udev); - if (udev->dev->name) - kfree(udev->dev->name); - if (udev->dev->phys) - kfree(udev->dev->phys); - + kfree(udev->dev->name); + kfree(udev->dev->phys); kfree(udev->dev); kfree(udev); diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c index 8f02c155fdc..c0b46bceb5d 100644 --- a/drivers/macintosh/adbhid.c +++ b/drivers/macintosh/adbhid.c @@ -857,8 +857,7 @@ adbhid_input_register(int id, int default_id, int original_handler_id, static void adbhid_input_unregister(int id) { input_unregister_device(adbhid[id]->input); - if (adbhid[id]->keycode) - kfree(adbhid[id]->keycode); + kfree(adbhid[id]->keycode); kfree(adbhid[id]); adbhid[id] = NULL; } diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index 4ff67e7363d..e954b8354fe 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c @@ -1602,8 +1602,7 @@ static void __devexit wbsd_release_dma(struct wbsd_host* host) if (host->dma_addr) dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE, DMA_BIDIRECTIONAL); - if (host->dma_buffer) - kfree(host->dma_buffer); + kfree(host->dma_buffer); if (host->dma >= 0) free_dma(host->dma); diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c index 6e6f42d01e6..4b48b31ec23 100644 --- a/drivers/parport/probe.c +++ b/drivers/parport/probe.c @@ -78,17 +78,15 @@ static void parse_data(struct parport *port, int device, char *str) u++; } if (!strcmp(p, "MFG") || !strcmp(p, "MANUFACTURER")) { - if (info->mfr) - kfree (info->mfr); + kfree(info->mfr); info->mfr = kstrdup(sep, GFP_KERNEL); } else if (!strcmp(p, "MDL") || !strcmp(p, "MODEL")) { - if (info->model) - kfree (info->model); + kfree(info->model); info->model = kstrdup(sep, GFP_KERNEL); } else if (!strcmp(p, "CLS") || !strcmp(p, "CLASS")) { int i; - if (info->class_name) - kfree (info->class_name); + + kfree(info->class_name); info->class_name = kstrdup(sep, GFP_KERNEL); for (u = sep; *u; u++) *u = toupper(*u); @@ -102,21 +100,22 @@ static void parse_data(struct parport *port, int device, char *str) info->class = PARPORT_CLASS_OTHER; } else if (!strcmp(p, "CMD") || !strcmp(p, "COMMAND SET")) { - if (info->cmdset) - kfree (info->cmdset); + kfree(info->cmdset); info->cmdset = kstrdup(sep, GFP_KERNEL); /* if it speaks printer language, it's probably a printer */ if (strstr(sep, "PJL") || strstr(sep, "PCL")) guessed_class = PARPORT_CLASS_PRINTER; } else if (!strcmp(p, "DES") || !strcmp(p, "DESCRIPTION")) { - if (info->description) - kfree (info->description); + kfree(info->description); info->description = kstrdup(sep, GFP_KERNEL); } } rock_on: - if (q) p = q+1; else p=NULL; + if (q) + p = q + 1; + else + p = NULL; } /* If the device didn't tell us its class, maybe we have managed to diff --git a/drivers/parport/share.c b/drivers/parport/share.c index ae7becf7efa..9cb3ab156b0 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c @@ -202,16 +202,11 @@ static void free_port (struct parport *port) list_del(&port->full_list); spin_unlock(&full_list_lock); for (d = 0; d < 5; d++) { - if (port->probe_info[d].class_name) - kfree (port->probe_info[d].class_name); - if (port->probe_info[d].mfr) - kfree (port->probe_info[d].mfr); - if (port->probe_info[d].model) - kfree (port->probe_info[d].model); - if (port->probe_info[d].cmdset) - kfree (port->probe_info[d].cmdset); - if (port->probe_info[d].description) - kfree (port->probe_info[d].description); + kfree(port->probe_info[d].class_name); + kfree(port->probe_info[d].mfr); + kfree(port->probe_info[d].model); + kfree(port->probe_info[d].cmdset); + kfree(port->probe_info[d].description); } kfree(port->name); @@ -618,9 +613,9 @@ parport_register_device(struct parport *port, const char *name, return tmp; out_free_all: - kfree (tmp->state); + kfree(tmp->state); out_free_pardevice: - kfree (tmp); + kfree(tmp); out: parport_put_port (port); module_put(port->ops->owner); diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c index 93e39c4096a..00b81a7bdd2 100644 --- a/drivers/pci/hotplug/cpqphp_pci.c +++ b/drivers/pci/hotplug/cpqphp_pci.c @@ -259,8 +259,7 @@ static int PCI_GetBusDevHelper(struct controller *ctrl, u8 *bus_num, u8 *dev_num sizeof(struct irq_routing_table)) / sizeof(struct irq_info); // Make sure I got at least one entry if (len == 0) { - if (PCIIRQRoutingInfoLength != NULL) - kfree(PCIIRQRoutingInfoLength ); + kfree(PCIIRQRoutingInfoLength ); return -1; } @@ -275,8 +274,7 @@ static int PCI_GetBusDevHelper(struct controller *ctrl, u8 *bus_num, u8 *dev_num ctrl->pci_bus->number = tbus; pci_bus_read_config_dword (ctrl->pci_bus, *dev_num, PCI_VENDOR_ID, &work); if (!nobridge || (work == 0xffffffff)) { - if (PCIIRQRoutingInfoLength != NULL) - kfree(PCIIRQRoutingInfoLength ); + kfree(PCIIRQRoutingInfoLength ); return 0; } @@ -289,20 +287,17 @@ static int PCI_GetBusDevHelper(struct controller *ctrl, u8 *bus_num, u8 *dev_num dbg("Scan bus for Non Bridge: bus %d\n", tbus); if (PCI_ScanBusForNonBridge(ctrl, tbus, dev_num) == 0) { *bus_num = tbus; - if (PCIIRQRoutingInfoLength != NULL) - kfree(PCIIRQRoutingInfoLength ); + kfree(PCIIRQRoutingInfoLength ); return 0; } } else { - if (PCIIRQRoutingInfoLength != NULL) - kfree(PCIIRQRoutingInfoLength ); + kfree(PCIIRQRoutingInfoLength ); return 0; } } } - if (PCIIRQRoutingInfoLength != NULL) - kfree(PCIIRQRoutingInfoLength ); + kfree(PCIIRQRoutingInfoLength ); return -1; } diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 3afb682255a..2dc3e611a9a 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -334,10 +334,8 @@ void destroy_cis_cache(struct pcmcia_socket *s) /* * If there was a fake CIS, destroy that as well. */ - if (s->fake_cis) { - kfree(s->fake_cis); - s->fake_cis = NULL; - } + kfree(s->fake_cis); + s->fake_cis = NULL; } EXPORT_SYMBOL(destroy_cis_cache); @@ -386,10 +384,8 @@ int verify_cis_cache(struct pcmcia_socket *s) int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis) { - if (s->fake_cis != NULL) { - kfree(s->fake_cis); - s->fake_cis = NULL; - } + kfree(s->fake_cis); + s->fake_cis = NULL; if (cis->Length > CISTPL_MAX_CIS_SIZE) return CS_BAD_SIZE; s->fake_cis = kmalloc(cis->Length, GFP_KERNEL); diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index d5e76423a0e..234cdca6fe1 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -331,10 +331,8 @@ static void shutdown_socket(struct pcmcia_socket *s) cb_free(s); #endif s->functions = 0; - if (s->config) { - kfree(s->config); - s->config = NULL; - } + kfree(s->config); + s->config = NULL; { int status; diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index b0cc3c2588f..ba56762b05f 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -1125,10 +1125,9 @@ out_deregister: misc_deregister(&envctrl_dev); out_iounmap: iounmap(i2c); - for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++) { - if (i2c_childlist[i].tables) - kfree(i2c_childlist[i].tables); - } + for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++) + kfree(i2c_childlist[i].tables); + return err; } @@ -1141,10 +1140,8 @@ static void __exit envctrl_cleanup(void) iounmap(i2c); misc_deregister(&envctrl_dev); - for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++) { - if (i2c_childlist[i].tables) - kfree(i2c_childlist[i].tables); - } + for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++) + kfree(i2c_childlist[i].tables); } module_init(envctrl_init); diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 1d148c5a5a4..c0c974b1afa 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c @@ -2057,8 +2057,7 @@ static void i810fb_release_resource(struct fb_info *info, iounmap(par->mmio_start_virtual); if (par->aperture.virtual) iounmap(par->aperture.virtual); - if (par->edid) - kfree(par->edid); + kfree(par->edid); if (par->res_flags & FRAMEBUFFER_REQ) release_mem_region(par->aperture.physical, par->aperture.size); diff --git a/drivers/w1/w1_ds2433.c b/drivers/w1/w1_ds2433.c index 279e0e0363d..1e3d98aac12 100644 --- a/drivers/w1/w1_ds2433.c +++ b/drivers/w1/w1_ds2433.c @@ -299,10 +299,8 @@ static int w1_f23_add_slave(struct w1_slave *sl) static void w1_f23_remove_slave(struct w1_slave *sl) { #ifdef CONFIG_W1_F23_CRC - if (sl->family_data) { - kfree(sl->family_data); - sl->family_data = NULL; - } + kfree(sl->family_data); + sl->family_data = NULL; #endif /* CONFIG_W1_F23_CRC */ sysfs_remove_bin_file(&sl->dev.kobj, &w1_f23_bin_attr); } -- cgit v1.2.3 From f99d49adf527fa6f7a9c42257fa76bca6b8df1e3 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 7 Nov 2005 01:01:34 -0800 Subject: [PATCH] kfree cleanup: fs This is the fs/ part of the big kfree cleanup patch. Remove pointless checks for NULL prior to calling kfree() in fs/. Signed-off-by: Jesper Juhl Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/9p/trans_sock.c | 3 +- fs/affs/super.c | 16 ++++------ fs/afs/file.c | 3 +- fs/autofs/waitq.c | 6 ++-- fs/autofs4/inode.c | 6 ++-- fs/autofs4/waitq.c | 6 ++-- fs/befs/linuxvfs.c | 12 +++----- fs/binfmt_elf.c | 3 +- fs/binfmt_elf_fdpic.c | 15 +++------ fs/cifs/asn1.c | 3 +- fs/cifs/connect.c | 81 +++++++++++++++++-------------------------------- fs/cifs/link.c | 23 +++++--------- fs/cifs/misc.c | 15 +++------ fs/cifs/xattr.c | 15 +++------ fs/compat_ioctl.c | 3 +- fs/devfs/base.c | 6 ++-- fs/ext2/acl.c | 6 ++-- fs/hostfs/hostfs_kern.c | 3 +- fs/hpfs/dnode.c | 8 ++--- fs/hpfs/super.c | 10 +++--- fs/isofs/inode.c | 12 +++----- fs/jbd/commit.c | 6 ++-- fs/jbd/transaction.c | 9 ++---- fs/jffs/intrep.c | 18 +++++------ fs/jffs2/readinode.c | 8 ++--- fs/jffs2/wbuf.c | 3 +- fs/lockd/clntproc.c | 3 +- fs/mbcache.c | 3 +- fs/nfs/delegation.c | 3 +- fs/nfs/inode.c | 15 +++------ fs/nfs/nfs4state.c | 9 ++---- fs/nfs/unlink.c | 3 +- fs/nfsd/export.c | 6 ++-- fs/nfsd/nfs4xdr.c | 9 ++---- fs/nfsd/nfscache.c | 3 +- fs/openpromfs/inode.c | 3 +- fs/udf/udf_sb.h | 3 +- fs/ufs/super.c | 14 +++++---- fs/xattr.c | 9 ++---- 39 files changed, 137 insertions(+), 245 deletions(-) diff --git a/fs/9p/trans_sock.c b/fs/9p/trans_sock.c index 01e26f0013a..a93c2bf94c3 100644 --- a/fs/9p/trans_sock.c +++ b/fs/9p/trans_sock.c @@ -269,8 +269,7 @@ static void v9fs_sock_close(struct v9fs_transport *trans) dprintk(DEBUG_TRANS, "socket closed\n"); } - if (ts) - kfree(ts); + kfree(ts); trans->priv = NULL; } diff --git a/fs/affs/super.c b/fs/affs/super.c index 9c3080716c9..aaec015a16e 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -35,8 +35,7 @@ affs_put_super(struct super_block *sb) mark_buffer_dirty(sbi->s_root_bh); } - if (sbi->s_prefix) - kfree(sbi->s_prefix); + kfree(sbi->s_prefix); affs_free_bitmap(sb); affs_brelse(sbi->s_root_bh); kfree(sbi); @@ -198,10 +197,9 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s *mount_opts |= SF_MUFS; break; case Opt_prefix: - if (*prefix) { /* Free any previous prefix */ - kfree(*prefix); - *prefix = NULL; - } + /* Free any previous prefix */ + kfree(*prefix); + *prefix = NULL; *prefix = match_strdup(&args[0]); if (!*prefix) return 0; @@ -462,11 +460,9 @@ got_root: out_error: if (root_inode) iput(root_inode); - if (sbi->s_bitmap) - kfree(sbi->s_bitmap); + kfree(sbi->s_bitmap); affs_brelse(root_bh); - if (sbi->s_prefix) - kfree(sbi->s_prefix); + kfree(sbi->s_prefix); kfree(sbi); sb->s_fs_info = NULL; return -EINVAL; diff --git a/fs/afs/file.c b/fs/afs/file.c index f53971a543b..150b1922792 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -265,8 +265,7 @@ static int afs_file_releasepage(struct page *page, gfp_t gfp_flags) set_page_private(page, 0); ClearPagePrivate(page); - if (pageio) - kfree(pageio); + kfree(pageio); } _leave(" = 0"); diff --git a/fs/autofs/waitq.c b/fs/autofs/waitq.c index 1fcaa156854..633f628005b 100644 --- a/fs/autofs/waitq.c +++ b/fs/autofs/waitq.c @@ -150,10 +150,8 @@ int autofs_wait(struct autofs_sb_info *sbi, struct qstr *name) if ( sbi->catatonic ) { /* We might have slept, so check again for catatonic mode */ wq->status = -ENOENT; - if ( wq->name ) { - kfree(wq->name); - wq->name = NULL; - } + kfree(wq->name); + wq->name = NULL; } if ( wq->name ) { diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 0a3c05d1016..818b37be515 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -22,10 +22,8 @@ static void ino_lnkfree(struct autofs_info *ino) { - if (ino->u.symlink) { - kfree(ino->u.symlink); - ino->u.symlink = NULL; - } + kfree(ino->u.symlink); + ino->u.symlink = NULL; } struct autofs_info *autofs4_init_ino(struct autofs_info *ino, diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index 3df86285a1c..394ff36ef8f 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c @@ -243,10 +243,8 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, if ( sbi->catatonic ) { /* We might have slept, so check again for catatonic mode */ wq->status = -ENOENT; - if ( wq->name ) { - kfree(wq->name); - wq->name = NULL; - } + kfree(wq->name); + wq->name = NULL; } if ( wq->name ) { diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index e8112ad5365..2d365cb8eec 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -725,20 +725,16 @@ parse_options(char *options, befs_mount_options * opts) static void befs_put_super(struct super_block *sb) { - if (BEFS_SB(sb)->mount_opts.iocharset) { - kfree(BEFS_SB(sb)->mount_opts.iocharset); - BEFS_SB(sb)->mount_opts.iocharset = NULL; - } + kfree(BEFS_SB(sb)->mount_opts.iocharset); + BEFS_SB(sb)->mount_opts.iocharset = NULL; if (BEFS_SB(sb)->nls) { unload_nls(BEFS_SB(sb)->nls); BEFS_SB(sb)->nls = NULL; } - if (sb->s_fs_info) { - kfree(sb->s_fs_info); - sb->s_fs_info = NULL; - } + kfree(sb->s_fs_info); + sb->s_fs_info = NULL; return; } diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 6fa6adc4097..f36f2210204 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1006,8 +1006,7 @@ out_free_dentry: if (interpreter) fput(interpreter); out_free_interp: - if (elf_interpreter) - kfree(elf_interpreter); + kfree(elf_interpreter); out_free_file: sys_close(elf_exec_fileno); out_free_fh: diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index dda87c4c82a..e0344f69c79 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -411,16 +411,11 @@ error: allow_write_access(interpreter); fput(interpreter); } - if (interpreter_name) - kfree(interpreter_name); - if (exec_params.phdrs) - kfree(exec_params.phdrs); - if (exec_params.loadmap) - kfree(exec_params.loadmap); - if (interp_params.phdrs) - kfree(interp_params.phdrs); - if (interp_params.loadmap) - kfree(interp_params.loadmap); + kfree(interpreter_name); + kfree(exec_params.phdrs); + kfree(exec_params.loadmap); + kfree(interp_params.phdrs); + kfree(interp_params.loadmap); return retval; /* unrecoverable error - kill the process */ diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index 98539e2afe8..086ae8f4a20 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c @@ -553,8 +553,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, *(oid + 3))); rc = compare_oid(oid, oidlen, NTLMSSP_OID, NTLMSSP_OID_LEN); - if(oid) - kfree(oid); + kfree(oid); if (rc) use_ntlmssp = TRUE; } diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index d74367a08d5..450ab75d654 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1265,8 +1265,7 @@ connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, the helper that resolves tcp names, mount to it, try to tcon to it unmount it if fail */ - if(referrals) - kfree(referrals); + kfree(referrals); return rc; } @@ -1535,10 +1534,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, memset(&volume_info,0,sizeof(struct smb_vol)); if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { - if(volume_info.UNC) - kfree(volume_info.UNC); - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.UNC); + kfree(volume_info.password); FreeXid(xid); return -EINVAL; } @@ -1551,10 +1548,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cifserror("No username specified "); /* In userspace mount helper we can get user name from alternate locations such as env variables and files on disk */ - if(volume_info.UNC) - kfree(volume_info.UNC); - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.UNC); + kfree(volume_info.password); FreeXid(xid); return -EINVAL; } @@ -1573,10 +1568,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, if(rc <= 0) { /* we failed translating address */ - if(volume_info.UNC) - kfree(volume_info.UNC); - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.UNC); + kfree(volume_info.password); FreeXid(xid); return -EINVAL; } @@ -1587,19 +1580,15 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, } else if (volume_info.UNCip){ /* BB using ip addr as server name connect to the DFS root below */ cERROR(1,("Connecting to DFS root not implemented yet")); - if(volume_info.UNC) - kfree(volume_info.UNC); - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.UNC); + kfree(volume_info.password); FreeXid(xid); return -EINVAL; } else /* which servers DFS root would we conect to */ { cERROR(1, ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified ")); - if(volume_info.UNC) - kfree(volume_info.UNC); - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.UNC); + kfree(volume_info.password); FreeXid(xid); return -EINVAL; } @@ -1612,10 +1601,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cifs_sb->local_nls = load_nls(volume_info.iocharset); if(cifs_sb->local_nls == NULL) { cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset)); - if(volume_info.UNC) - kfree(volume_info.UNC); - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.UNC); + kfree(volume_info.password); FreeXid(xid); return -ELIBACC; } @@ -1630,10 +1617,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, &sin_server6.sin6_addr, volume_info.username, &srvTcp); else { - if(volume_info.UNC) - kfree(volume_info.UNC); - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.UNC); + kfree(volume_info.password); FreeXid(xid); return -EINVAL; } @@ -1654,10 +1639,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ("Error connecting to IPv4 socket. Aborting operation")); if(csocket != NULL) sock_release(csocket); - if(volume_info.UNC) - kfree(volume_info.UNC); - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.UNC); + kfree(volume_info.password); FreeXid(xid); return rc; } @@ -1666,10 +1649,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, if (srvTcp == NULL) { rc = -ENOMEM; sock_release(csocket); - if(volume_info.UNC) - kfree(volume_info.UNC); - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.UNC); + kfree(volume_info.password); FreeXid(xid); return rc; } else { @@ -1692,10 +1673,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, if(rc < 0) { rc = -ENOMEM; sock_release(csocket); - if(volume_info.UNC) - kfree(volume_info.UNC); - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.UNC); + kfree(volume_info.password); FreeXid(xid); return rc; } @@ -1710,8 +1689,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, if (existingCifsSes) { pSesInfo = existingCifsSes; cFYI(1, ("Existing smb sess found ")); - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.password); /* volume_info.UNC freed at end of function */ } else if (!rc) { cFYI(1, ("Existing smb sess not found ")); @@ -1741,8 +1719,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, if(!rc) atomic_inc(&srvTcp->socketUseCount); } else - if(volume_info.password) - kfree(volume_info.password); + kfree(volume_info.password); } /* search for existing tcon to this server share */ @@ -1821,8 +1798,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, "", cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - if(volume_info.UNC) - kfree(volume_info.UNC); + kfree(volume_info.UNC); FreeXid(xid); return -ENODEV; } else { @@ -1925,8 +1901,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, (in which case it is not needed anymore) but when new sesion is created the password ptr is put in the new session structure (in which case the password will be freed at unmount time) */ - if(volume_info.UNC) - kfree(volume_info.UNC); + kfree(volume_info.UNC); FreeXid(xid); return rc; } @@ -3283,8 +3258,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, if ((bcc_ptr + (2 * length)) - pByteArea(smb_buffer_response) <= BCC(smb_buffer_response)) { - if(tcon->nativeFileSystem) - kfree(tcon->nativeFileSystem); + kfree(tcon->nativeFileSystem); tcon->nativeFileSystem = kzalloc(length + 2, GFP_KERNEL); cifs_strfromUCS_le(tcon->nativeFileSystem, @@ -3301,8 +3275,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, if ((bcc_ptr + length) - pByteArea(smb_buffer_response) <= BCC(smb_buffer_response)) { - if(tcon->nativeFileSystem) - kfree(tcon->nativeFileSystem); + kfree(tcon->nativeFileSystem); tcon->nativeFileSystem = kzalloc(length + 1, GFP_KERNEL); strncpy(tcon->nativeFileSystem, bcc_ptr, diff --git a/fs/cifs/link.c b/fs/cifs/link.c index b43e071fe11..0f99aae3316 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -84,10 +84,8 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, cifsInode->time = 0; /* will force revalidate to go get info when needed */ cifs_hl_exit: - if (fromName) - kfree(fromName); - if (toName) - kfree(toName); + kfree(fromName); + kfree(toName); FreeXid(xid); return rc; } @@ -206,8 +204,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) } } - if (full_path) - kfree(full_path); + kfree(full_path); FreeXid(xid); return rc; } @@ -253,8 +250,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) len = buflen; tmpbuffer = kmalloc(len,GFP_KERNEL); if(tmpbuffer == NULL) { - if (full_path) - kfree(full_path); + kfree(full_path); FreeXid(xid); return -ENOMEM; } @@ -303,8 +299,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) strncpy(tmpbuffer, referrals, len-1); } } - if(referrals) - kfree(referrals); + kfree(referrals); kfree(tmp_path); } /* BB add code like else decode referrals then memcpy to @@ -323,12 +318,8 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) rc)); } - if (tmpbuffer) { - kfree(tmpbuffer); - } - if (full_path) { - kfree(full_path); - } + kfree(tmpbuffer); + kfree(full_path); FreeXid(xid); return rc; } diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index eba1de917f2..34a06692e4f 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -98,14 +98,10 @@ sesInfoFree(struct cifsSesInfo *buf_to_free) atomic_dec(&sesInfoAllocCount); list_del(&buf_to_free->cifsSessionList); write_unlock(&GlobalSMBSeslock); - if (buf_to_free->serverOS) - kfree(buf_to_free->serverOS); - if (buf_to_free->serverDomain) - kfree(buf_to_free->serverDomain); - if (buf_to_free->serverNOS) - kfree(buf_to_free->serverNOS); - if (buf_to_free->password) - kfree(buf_to_free->password); + kfree(buf_to_free->serverOS); + kfree(buf_to_free->serverDomain); + kfree(buf_to_free->serverNOS); + kfree(buf_to_free->password); kfree(buf_to_free); } @@ -144,8 +140,7 @@ tconInfoFree(struct cifsTconInfo *buf_to_free) atomic_dec(&tconInfoAllocCount); list_del(&buf_to_free->cifsConnectionList); write_unlock(&GlobalSMBSeslock); - if (buf_to_free->nativeFileSystem) - kfree(buf_to_free->nativeFileSystem); + kfree(buf_to_free->nativeFileSystem); kfree(buf_to_free); } diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index c1e02eff1d2..f375f87c7db 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -87,8 +87,7 @@ int cifs_removexattr(struct dentry * direntry, const char * ea_name) cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); } remove_ea_exit: - if (full_path) - kfree(full_path); + kfree(full_path); FreeXid(xid); #endif return rc; @@ -132,8 +131,7 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name, returns as xattrs */ if(value_size > MAX_EA_VALUE_SIZE) { cFYI(1,("size of EA value too large")); - if(full_path) - kfree(full_path); + kfree(full_path); FreeXid(xid); return -EOPNOTSUPP; } @@ -195,8 +193,7 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name, } set_ea_exit: - if (full_path) - kfree(full_path); + kfree(full_path); FreeXid(xid); #endif return rc; @@ -298,8 +295,7 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name, rc = -EOPNOTSUPP; get_ea_exit: - if (full_path) - kfree(full_path); + kfree(full_path); FreeXid(xid); #endif return rc; @@ -345,8 +341,7 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size) cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - if (full_path) - kfree(full_path); + kfree(full_path); FreeXid(xid); #endif return rc; diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 43dbcb0b21e..4909754ea84 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -2235,7 +2235,8 @@ static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) if (err) err = -EFAULT; -out: if (karg) kfree(karg); +out: + kfree(karg); return err; } diff --git a/fs/devfs/base.c b/fs/devfs/base.c index 8b679b67e5e..1274422a538 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -2738,10 +2738,8 @@ static int devfsd_close(struct inode *inode, struct file *file) entry = fs_info->devfsd_first_event; fs_info->devfsd_first_event = NULL; fs_info->devfsd_last_event = NULL; - if (fs_info->devfsd_info) { - kfree(fs_info->devfsd_info); - fs_info->devfsd_info = NULL; - } + kfree(fs_info->devfsd_info); + fs_info->devfsd_info = NULL; spin_unlock(&fs_info->devfsd_buffer_lock); fs_info->devfsd_pgrp = 0; fs_info->devfsd_task = NULL; diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c index 213148c36eb..6af2f413029 100644 --- a/fs/ext2/acl.c +++ b/fs/ext2/acl.c @@ -194,8 +194,7 @@ ext2_get_acl(struct inode *inode, int type) acl = NULL; else acl = ERR_PTR(retval); - if (value) - kfree(value); + kfree(value); if (!IS_ERR(acl)) { switch(type) { @@ -262,8 +261,7 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl) error = ext2_xattr_set(inode, name_index, "", value, size, 0); - if (value) - kfree(value); + kfree(value); if (!error) { switch(type) { case ACL_TYPE_ACCESS: diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index dd711310626..a33fb1d9137 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -294,8 +294,7 @@ static void hostfs_delete_inode(struct inode *inode) static void hostfs_destroy_inode(struct inode *inode) { - if(HOSTFS_I(inode)->host_filename) - kfree(HOSTFS_I(inode)->host_filename); + kfree(HOSTFS_I(inode)->host_filename); /*XXX: This should not happen, probably. The check is here for * additional safety.*/ diff --git a/fs/hpfs/dnode.c b/fs/hpfs/dnode.c index 1d21307730a..229ff2fb180 100644 --- a/fs/hpfs/dnode.c +++ b/fs/hpfs/dnode.c @@ -244,12 +244,12 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno, go_up: if (namelen >= 256) { hpfs_error(i->i_sb, "hpfs_add_to_dnode: namelen == %d", namelen); - if (nd) kfree(nd); + kfree(nd); kfree(nname); return 1; } if (!(d = hpfs_map_dnode(i->i_sb, dno, &qbh))) { - if (nd) kfree(nd); + kfree(nd); kfree(nname); return 1; } @@ -257,7 +257,7 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno, if (hpfs_sb(i->i_sb)->sb_chk) if (hpfs_stop_cycles(i->i_sb, dno, &c1, &c2, "hpfs_add_to_dnode")) { hpfs_brelse4(&qbh); - if (nd) kfree(nd); + kfree(nd); kfree(nname); return 1; } @@ -270,7 +270,7 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno, for_all_poss(i, hpfs_pos_subst, 5, t + 1); hpfs_mark_4buffers_dirty(&qbh); hpfs_brelse4(&qbh); - if (nd) kfree(nd); + kfree(nd); kfree(nname); return 0; } diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 8eefa6366db..63e88d7e2c3 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -75,7 +75,7 @@ void hpfs_error(struct super_block *s, char *m,...) } else if (s->s_flags & MS_RDONLY) printk("; going on - but anything won't be destroyed because it's read-only\n"); else printk("; corrupted filesystem mounted read/write - your computer will explode within 20 seconds ... but you wanted it so!\n"); } else printk("\n"); - if (buf) kfree(buf); + kfree(buf); hpfs_sb(s)->sb_was_error = 1; } @@ -102,8 +102,8 @@ int hpfs_stop_cycles(struct super_block *s, int key, int *c1, int *c2, static void hpfs_put_super(struct super_block *s) { struct hpfs_sb_info *sbi = hpfs_sb(s); - if (sbi->sb_cp_table) kfree(sbi->sb_cp_table); - if (sbi->sb_bmp_dir) kfree(sbi->sb_bmp_dir); + kfree(sbi->sb_cp_table); + kfree(sbi->sb_bmp_dir); unmark_dirty(s); s->s_fs_info = NULL; kfree(sbi); @@ -654,8 +654,8 @@ bail3: brelse(bh1); bail2: brelse(bh0); bail1: bail0: - if (sbi->sb_bmp_dir) kfree(sbi->sb_bmp_dir); - if (sbi->sb_cp_table) kfree(sbi->sb_cp_table); + kfree(sbi->sb_bmp_dir); + kfree(sbi->sb_cp_table); s->s_fs_info = NULL; kfree(sbi); return -EINVAL; diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 1652de1b6cb..298f08be22d 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -855,8 +855,7 @@ root_found: if (opt.check == 'r') table++; s->s_root->d_op = &isofs_dentry_ops[table]; - if (opt.iocharset) - kfree(opt.iocharset); + kfree(opt.iocharset); return 0; @@ -895,8 +894,7 @@ out_unknown_format: out_freebh: brelse(bh); out_freesbi: - if (opt.iocharset) - kfree(opt.iocharset); + kfree(opt.iocharset); kfree(sbi); s->s_fs_info = NULL; return -EINVAL; @@ -1164,8 +1162,7 @@ out_nomem: out_noread: printk(KERN_INFO "ISOFS: unable to read i-node block %lu\n", block); - if (tmpde) - kfree(tmpde); + kfree(tmpde); return -EIO; out_toomany: @@ -1334,8 +1331,7 @@ static void isofs_read_inode(struct inode *inode) init_special_inode(inode, inode->i_mode, inode->i_rdev); out: - if (tmpde) - kfree(tmpde); + kfree(tmpde); if (bh) brelse(bh); return; diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 2a3e310f79e..002ad2bbc76 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c @@ -261,10 +261,8 @@ void journal_commit_transaction(journal_t *journal) struct buffer_head *bh = jh2bh(jh); jbd_lock_bh_state(bh); - if (jh->b_committed_data) { - kfree(jh->b_committed_data); - jh->b_committed_data = NULL; - } + kfree(jh->b_committed_data); + jh->b_committed_data = NULL; jbd_unlock_bh_state(bh); } journal_refile_buffer(journal, jh); diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index 13cb05bf604..429f4b263cf 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -227,8 +227,7 @@ repeat_locked: spin_unlock(&transaction->t_handle_lock); spin_unlock(&journal->j_state_lock); out: - if (new_transaction) - kfree(new_transaction); + kfree(new_transaction); return ret; } @@ -725,8 +724,7 @@ done: journal_cancel_revoke(handle, jh); out: - if (frozen_buffer) - kfree(frozen_buffer); + kfree(frozen_buffer); JBUFFER_TRACE(jh, "exit"); return error; @@ -905,8 +903,7 @@ repeat: jbd_unlock_bh_state(bh); out: journal_put_journal_head(jh); - if (committed_data) - kfree(committed_data); + kfree(committed_data); return err; } diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c index 27f199e94cf..b2e95421d93 100644 --- a/fs/jffs/intrep.c +++ b/fs/jffs/intrep.c @@ -462,7 +462,7 @@ jffs_checksum_flash(struct mtd_info *mtd, loff_t start, int size, __u32 *result) } /* Free read buffer */ - kfree (read_buf); + kfree(read_buf); /* Return result */ D3(printk("checksum result: 0x%08x\n", sum)); @@ -1011,12 +1011,12 @@ jffs_scan_flash(struct jffs_control *c) offset , fmc->sector_size); flash_safe_release(fmc->mtd); - kfree (read_buf); + kfree(read_buf); return -1; /* bad, bad, bad! */ } flash_safe_release(fmc->mtd); - kfree (read_buf); + kfree(read_buf); return -EAGAIN; /* erased offending sector. Try mount one more time please. */ } @@ -1112,7 +1112,7 @@ jffs_scan_flash(struct jffs_control *c) if (!node) { if (!(node = jffs_alloc_node())) { /* Free read buffer */ - kfree (read_buf); + kfree(read_buf); /* Release the flash device */ flash_safe_release(fmc->mtd); @@ -1269,7 +1269,7 @@ jffs_scan_flash(struct jffs_control *c) DJM(no_jffs_node--); /* Free read buffer */ - kfree (read_buf); + kfree(read_buf); /* Release the flash device */ flash_safe_release(fmc->mtd); @@ -1296,7 +1296,7 @@ jffs_scan_flash(struct jffs_control *c) flash_safe_release(fmc->flash_part); /* Free read buffer */ - kfree (read_buf); + kfree(read_buf); return -ENOMEM; } @@ -1324,7 +1324,7 @@ jffs_scan_flash(struct jffs_control *c) jffs_build_end(fmc); /* Free read buffer */ - kfree (read_buf); + kfree(read_buf); if(!num_free_space){ printk(KERN_WARNING "jffs_scan_flash(): Did not find even a single " @@ -1747,9 +1747,7 @@ jffs_find_child(struct jffs_file *dir, const char *name, int len) } printk("jffs_find_child(): Didn't find the file \"%s\".\n", (copy ? copy : "")); - if (copy) { - kfree(copy); - } + kfree(copy); }); return f; diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 5b2a83599d7..1a96903e3ef 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -490,7 +490,7 @@ int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *i up(&f->sem); jffs2_do_clear_inode(c, f); } - kfree (f); + kfree(f); return ret; } @@ -742,10 +742,8 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) /* For symlink inodes we us f->dents to store the target path name */ if (S_ISLNK(OFNI_EDONI_2SFFJ(f)->i_mode)) { - if (f->dents) { - kfree(f->dents); - f->dents = NULL; - } + kfree(f->dents); + f->dents = NULL; } else { fds = f->dents; diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 316133c626b..7bc7f2d571f 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -327,8 +327,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) c->wbuf_ofs = ofs + towrite; memmove(c->wbuf, rewrite_buf + towrite, c->wbuf_len); /* Don't muck about with c->wbuf_inodes. False positives are harmless. */ - if (buf) - kfree(buf); + kfree(buf); } else { /* OK, now we're left with the dregs in whichever buffer we're using */ if (buf) { diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 87332f30141..c5a33648e9f 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -112,8 +112,7 @@ static struct nlm_lockowner *nlm_find_lockowner(struct nlm_host *host, fl_owner_ } } spin_unlock(&host->h_lock); - if (new != NULL) - kfree(new); + kfree(new); return res; } diff --git a/fs/mbcache.c b/fs/mbcache.c index 298997f1747..0f1e4530670 100644 --- a/fs/mbcache.c +++ b/fs/mbcache.c @@ -301,8 +301,7 @@ fail: if (cache) { while (--m >= 0) kfree(cache->c_indexes_hash[m]); - if (cache->c_block_hash) - kfree(cache->c_block_hash); + kfree(cache->c_block_hash); kfree(cache); } return NULL; diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 3976c177a7d..618a327027b 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -149,8 +149,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct } } spin_unlock(&clp->cl_lock); - if (delegation != NULL) - kfree(delegation); + kfree(delegation); return status; } diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 24d2fbf549b..6391d896421 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -1688,8 +1688,7 @@ static void nfs_kill_super(struct super_block *s) rpciod_down(); /* release rpciod */ - if (server->hostname != NULL) - kfree(server->hostname); + kfree(server->hostname); kfree(server); } @@ -1908,8 +1907,7 @@ nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen) return ERR_PTR(-ENOMEM); } if (copy_from_user(dst, src->data, maxlen)) { - if (p != NULL) - kfree(p); + kfree(p); return ERR_PTR(-EFAULT); } dst[maxlen] = '\0'; @@ -2000,10 +1998,8 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, out_err: s = (struct super_block *)p; out_free: - if (server->mnt_path) - kfree(server->mnt_path); - if (server->hostname) - kfree(server->hostname); + kfree(server->mnt_path); + kfree(server->hostname); kfree(server); return s; } @@ -2023,8 +2019,7 @@ static void nfs4_kill_super(struct super_block *sb) destroy_nfsv4_state(server); - if (server->hostname != NULL) - kfree(server->hostname); + kfree(server->hostname); kfree(server); } diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 52a26baa114..0675f3215e0 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -69,10 +69,8 @@ init_nfsv4_state(struct nfs_server *server) void destroy_nfsv4_state(struct nfs_server *server) { - if (server->mnt_path) { - kfree(server->mnt_path); - server->mnt_path = NULL; - } + kfree(server->mnt_path); + server->mnt_path = NULL; if (server->nfs4_state) { nfs4_put_client(server->nfs4_state); server->nfs4_state = NULL; @@ -311,8 +309,7 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct new = NULL; } spin_unlock(&clp->cl_lock); - if (new) - kfree(new); + kfree(new); if (sp != NULL) return sp; put_rpccred(cred); diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index f732541a333..d639d172d56 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c @@ -52,8 +52,7 @@ nfs_put_unlinkdata(struct nfs_unlinkdata *data) { if (--data->count == 0) { nfs_detach_unlinkdata(data); - if (data->name.name != NULL) - kfree(data->name.name); + kfree(data->name.name); kfree(data); } } diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 057aff74550..417ec02df44 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -190,8 +190,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) out: if (dom) auth_domain_put(dom); - if (buf) - kfree(buf); + kfree(buf); return err; } @@ -428,8 +427,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) path_release(&nd); if (dom) auth_domain_put(dom); - if (buf) - kfree(buf); + kfree(buf); return err; } diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 4c414635023..dcd67318694 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -151,8 +151,7 @@ static u32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes) if (nbytes <= sizeof(argp->tmp)) p = argp->tmp; else { - if (argp->tmpp) - kfree(argp->tmpp); + kfree(argp->tmpp); p = argp->tmpp = kmalloc(nbytes, GFP_KERNEL); if (!p) return NULL; @@ -2476,10 +2475,8 @@ void nfsd4_release_compoundargs(struct nfsd4_compoundargs *args) kfree(args->ops); args->ops = args->iops; } - if (args->tmpp) { - kfree(args->tmpp); - args->tmpp = NULL; - } + kfree(args->tmpp); + args->tmpp = NULL; while (args->to_free) { struct tmpbuf *tb = args->to_free; args->to_free = tb->next; diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c index 119e4d4495b..d852ebb538e 100644 --- a/fs/nfsd/nfscache.c +++ b/fs/nfsd/nfscache.c @@ -93,8 +93,7 @@ nfsd_cache_shutdown(void) cache_disabled = 1; - if (hash_list) - kfree (hash_list); + kfree (hash_list); hash_list = NULL; } diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c index 1be11ce96b0..aeb0106890e 100644 --- a/fs/openpromfs/inode.c +++ b/fs/openpromfs/inode.c @@ -1088,8 +1088,7 @@ static void __exit exit_openprom_fs(void) unregister_filesystem(&openprom_fs_type); free_pages ((unsigned long)nodes, alloced); for (i = 0; i < aliases_nodes; i++) - if (alias_names [i]) - kfree (alias_names [i]); + kfree (alias_names [i]); nodes = NULL; } diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h index 0e54922daa0..663669810be 100644 --- a/fs/udf/udf_sb.h +++ b/fs/udf/udf_sb.h @@ -39,8 +39,7 @@ static inline struct udf_sb_info *UDF_SB(struct super_block *sb) {\ if (UDF_SB(X))\ {\ - if (UDF_SB_PARTMAPS(X))\ - kfree(UDF_SB_PARTMAPS(X));\ + kfree(UDF_SB_PARTMAPS(X));\ UDF_SB_PARTMAPS(X) = NULL;\ }\ } diff --git a/fs/ufs/super.c b/fs/ufs/super.c index f036d694ba5..54828ebcf1b 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -472,13 +472,14 @@ static int ufs_read_cylinder_structures (struct super_block *sb) { return 1; failed: - if (base) kfree (base); + kfree (base); if (sbi->s_ucg) { for (i = 0; i < uspi->s_ncg; i++) - if (sbi->s_ucg[i]) brelse (sbi->s_ucg[i]); + if (sbi->s_ucg[i]) + brelse (sbi->s_ucg[i]); kfree (sbi->s_ucg); for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) - if (sbi->s_ucpi[i]) kfree (sbi->s_ucpi[i]); + kfree (sbi->s_ucpi[i]); } UFSD(("EXIT (FAILED)\n")) return 0; @@ -981,9 +982,10 @@ magic_found: dalloc_failed: iput(inode); failed: - if (ubh) ubh_brelse_uspi (uspi); - if (uspi) kfree (uspi); - if (sbi) kfree(sbi); + if (ubh) + ubh_brelse_uspi (uspi); + kfree (uspi); + kfree(sbi); sb->s_fs_info = NULL; UFSD(("EXIT (FAILED)\n")) return -EINVAL; diff --git a/fs/xattr.c b/fs/xattr.c index f6e00c0e114..a9db2255799 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -74,8 +74,7 @@ setxattr(struct dentry *d, char __user *name, void __user *value, } out: up(&d->d_inode->i_sem); - if (kvalue) - kfree(kvalue); + kfree(kvalue); return error; } @@ -173,8 +172,7 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size) error = -E2BIG; } out: - if (kvalue) - kfree(kvalue); + kfree(kvalue); return error; } @@ -259,8 +257,7 @@ listxattr(struct dentry *d, char __user *list, size_t size) error = -E2BIG; } out: - if (klist) - kfree(klist); + kfree(klist); return error; } -- cgit v1.2.3 From b2325fe1b7e5654fac9e9419423aa2c58a3dbd83 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 7 Nov 2005 01:01:35 -0800 Subject: [PATCH] kfree cleanup: arch This is the arch/ part of the big kfree cleanup patch. Remove pointless checks for NULL prior to calling kfree() in arch/. Signed-off-by: Jesper Juhl Acked-by: Grant Grundler Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/mach-integrator/impd1.c | 3 +-- arch/cris/arch-v32/drivers/cryptocop.c | 14 +++++++------- arch/ia64/kernel/perfmon.c | 2 +- arch/powerpc/platforms/pseries/reconfig.c | 6 ++---- arch/ppc/8xx_io/cs4218_tdm.c | 3 +-- arch/ppc/syslib/prom.c | 6 ++---- arch/ppc64/kernel/lparcfg.c | 4 +--- arch/ppc64/kernel/scanlog.c | 3 +-- arch/s390/mm/extmem.c | 8 ++++---- arch/sparc64/kernel/us2e_cpufreq.c | 7 ++----- arch/sparc64/kernel/us3_cpufreq.c | 7 ++----- arch/um/kernel/sigio_user.c | 2 +- 12 files changed, 25 insertions(+), 40 deletions(-) diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index a1b153d1626..a4bafee77a0 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c @@ -420,8 +420,7 @@ static int impd1_probe(struct lm_device *dev) free_impd1: if (impd1 && impd1->base) iounmap(impd1->base); - if (impd1) - kfree(impd1); + kfree(impd1); release_lm: release_mem_region(dev->resource.start, SZ_4K); return ret; diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c index ca72076c630..501fa52d8d3 100644 --- a/arch/cris/arch-v32/drivers/cryptocop.c +++ b/arch/cris/arch-v32/drivers/cryptocop.c @@ -277,7 +277,7 @@ struct file_operations cryptocop_fops = { static void free_cdesc(struct cryptocop_dma_desc *cdesc) { DEBUG(printk("free_cdesc: cdesc 0x%p, from_pool=%d\n", cdesc, cdesc->from_pool)); - if (cdesc->free_buf) kfree(cdesc->free_buf); + kfree(cdesc->free_buf); if (cdesc->from_pool) { unsigned long int flags; @@ -2950,15 +2950,15 @@ static int cryptocop_ioctl_process(struct inode *inode, struct file *filp, unsig put_page(outpages[i]); } - if (digest_result) kfree(digest_result); - if (inpages) kfree(inpages); - if (outpages) kfree(outpages); + kfree(digest_result); + kfree(inpages); + kfree(outpages); if (cop){ - if (cop->tfrm_op.indata) kfree(cop->tfrm_op.indata); - if (cop->tfrm_op.outdata) kfree(cop->tfrm_op.outdata); + kfree(cop->tfrm_op.indata); + kfree(cop->tfrm_op.outdata); kfree(cop); } - if (jc) kfree(jc); + kfree(jc); DEBUG(print_lock_status()); diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index f7dfc107cb7..410d4804fa6 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -4940,7 +4940,7 @@ abort_locked: if (call_made && PFM_CMD_RW_ARG(cmd) && copy_to_user(arg, args_k, base_sz*count)) ret = -EFAULT; error_args: - if (args_k) kfree(args_k); + kfree(args_k); DPRINT(("cmd=%s ret=%ld\n", PFM_CMD_NAME(cmd), ret)); diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 58c61219d08..d7d40033945 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -286,10 +286,8 @@ static struct property *new_property(const char *name, const int length, return new; cleanup: - if (new->name) - kfree(new->name); - if (new->value) - kfree(new->value); + kfree(new->name); + kfree(new->value); kfree(new); return NULL; } diff --git a/arch/ppc/8xx_io/cs4218_tdm.c b/arch/ppc/8xx_io/cs4218_tdm.c index 532caa388dc..49eb2a7e65c 100644 --- a/arch/ppc/8xx_io/cs4218_tdm.c +++ b/arch/ppc/8xx_io/cs4218_tdm.c @@ -1013,8 +1013,7 @@ static void CS_IrqCleanup(void) */ cpm_free_handler(CPMVEC_SMC2); - if (beep_buf) - kfree(beep_buf); + kfree(beep_buf); kd_mksound = orig_mksound; } #endif /* MODULE */ diff --git a/arch/ppc/syslib/prom.c b/arch/ppc/syslib/prom.c index 278da6ee62e..1b9aa0d6a92 100644 --- a/arch/ppc/syslib/prom.c +++ b/arch/ppc/syslib/prom.c @@ -1335,10 +1335,8 @@ release_OF_resource(struct device_node* node, int index) if (!res) return -ENODEV; - if (res->name) { - kfree(res->name); - res->name = NULL; - } + kfree(res->name); + res->name = NULL; release_resource(res); kfree(res); diff --git a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c index e86155770bb..3e7b2f28ec8 100644 --- a/arch/ppc64/kernel/lparcfg.c +++ b/arch/ppc64/kernel/lparcfg.c @@ -599,9 +599,7 @@ int __init lparcfg_init(void) void __exit lparcfg_cleanup(void) { if (proc_ppc64_lparcfg) { - if (proc_ppc64_lparcfg->data) { - kfree(proc_ppc64_lparcfg->data); - } + kfree(proc_ppc64_lparcfg->data); remove_proc_entry("lparcfg", proc_ppc64_lparcfg->parent); } } diff --git a/arch/ppc64/kernel/scanlog.c b/arch/ppc64/kernel/scanlog.c index 215bf890030..2edc947f7c4 100644 --- a/arch/ppc64/kernel/scanlog.c +++ b/arch/ppc64/kernel/scanlog.c @@ -225,8 +225,7 @@ int __init scanlog_init(void) void __exit scanlog_cleanup(void) { if (proc_ppc64_scan_log_dump) { - if (proc_ppc64_scan_log_dump->data) - kfree(proc_ppc64_scan_log_dump->data); + kfree(proc_ppc64_scan_log_dump->data); remove_proc_entry("scan-log-dump", proc_ppc64_scan_log_dump->parent); } } diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c index c5348108ca3..506a33b51e4 100644 --- a/arch/s390/mm/extmem.c +++ b/arch/s390/mm/extmem.c @@ -234,8 +234,8 @@ query_segment_type (struct dcss_segment *seg) rc = 0; out_free: - if (qin) kfree(qin); - if (qout) kfree(qout); + kfree(qin); + kfree(qout); return rc; } @@ -394,7 +394,7 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long segtype_string[seg->vm_segtype]); goto out; out_free: - kfree (seg); + kfree(seg); out: return rc; } @@ -505,7 +505,7 @@ segment_modify_shared (char *name, int do_nonshared) list_del(&seg->list); dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); - kfree (seg); + kfree(seg); out_unlock: spin_unlock(&dcss_lock); return rc; diff --git a/arch/sparc64/kernel/us2e_cpufreq.c b/arch/sparc64/kernel/us2e_cpufreq.c index 686e526bec0..b35dc8dc995 100644 --- a/arch/sparc64/kernel/us2e_cpufreq.c +++ b/arch/sparc64/kernel/us2e_cpufreq.c @@ -388,10 +388,8 @@ err_out: kfree(driver); cpufreq_us2e_driver = NULL; } - if (us2e_freq_table) { - kfree(us2e_freq_table); - us2e_freq_table = NULL; - } + kfree(us2e_freq_table); + us2e_freq_table = NULL; return ret; } @@ -402,7 +400,6 @@ static void __exit us2e_freq_exit(void) { if (cpufreq_us2e_driver) { cpufreq_unregister_driver(cpufreq_us2e_driver); - kfree(cpufreq_us2e_driver); cpufreq_us2e_driver = NULL; kfree(us2e_freq_table); diff --git a/arch/sparc64/kernel/us3_cpufreq.c b/arch/sparc64/kernel/us3_cpufreq.c index 0340041f614..6d1f9a3c464 100644 --- a/arch/sparc64/kernel/us3_cpufreq.c +++ b/arch/sparc64/kernel/us3_cpufreq.c @@ -249,10 +249,8 @@ err_out: kfree(driver); cpufreq_us3_driver = NULL; } - if (us3_freq_table) { - kfree(us3_freq_table); - us3_freq_table = NULL; - } + kfree(us3_freq_table); + us3_freq_table = NULL; return ret; } @@ -263,7 +261,6 @@ static void __exit us3_freq_exit(void) { if (cpufreq_us3_driver) { cpufreq_unregister_driver(cpufreq_us3_driver); - kfree(cpufreq_us3_driver); cpufreq_us3_driver = NULL; kfree(us3_freq_table); diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c index 3fbfd956bfe..48b1f644b9a 100644 --- a/arch/um/kernel/sigio_user.c +++ b/arch/um/kernel/sigio_user.c @@ -224,7 +224,7 @@ static int need_poll(int n) next_poll.used = n; return(0); } - if(next_poll.poll != NULL) kfree(next_poll.poll); + kfree(next_poll.poll); next_poll.poll = um_kmalloc_atomic(n * sizeof(struct pollfd)); if(next_poll.poll == NULL){ printk("need_poll : failed to allocate new pollfds\n"); -- cgit v1.2.3 From a7f988ba304c5f6e78f937a06d120a0097b4d351 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 7 Nov 2005 01:01:35 -0800 Subject: [PATCH] kfree cleanup: security This is the security/ part of the big kfree cleanup patch. Remove pointless checks for NULL prior to calling kfree() in security/. Signed-off-by: Jesper Juhl Acked-by: James Morris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- security/keys/key.c | 3 +-- security/selinux/ss/policydb.c | 12 ++++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/security/keys/key.c b/security/keys/key.c index ccde17aff61..01bcfecb7ea 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -115,8 +115,7 @@ struct key_user *key_user_lookup(uid_t uid) found: atomic_inc(&user->usage); spin_unlock(&key_user_lock); - if (candidate) - kfree(candidate); + kfree(candidate); out: return user; diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 2f5f539875f..0ac311dc837 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -632,22 +632,22 @@ void policydb_destroy(struct policydb *p) cond_policydb_destroy(p); for (tr = p->role_tr; tr; tr = tr->next) { - if (ltr) kfree(ltr); + kfree(ltr); ltr = tr; } - if (ltr) kfree(ltr); + kfree(ltr); for (ra = p->role_allow; ra; ra = ra -> next) { - if (lra) kfree(lra); + kfree(lra); lra = ra; } - if (lra) kfree(lra); + kfree(lra); for (rt = p->range_tr; rt; rt = rt -> next) { - if (lrt) kfree(lrt); + kfree(lrt); lrt = rt; } - if (lrt) kfree(lrt); + kfree(lrt); if (p->type_attr_map) { for (i = 0; i < p->p_types.nprim; i++) -- cgit v1.2.3 From 55be570c529643e83195d6688805127533184aa4 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 01:01:37 -0800 Subject: [PATCH] mm/{mmap,nommu}.c: several unexports I didn't find any possible modular usage in the kernel. This patch was already ACK'ed by Christoph Hellwig. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/mmap.c | 4 ---- mm/nommu.c | 4 ---- 2 files changed, 8 deletions(-) diff --git a/mm/mmap.c b/mm/mmap.c index 320dda1778c..6c997b15960 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -155,10 +155,6 @@ int __vm_enough_memory(long pages, int cap_sys_admin) return -ENOMEM; } -EXPORT_SYMBOL(sysctl_overcommit_memory); -EXPORT_SYMBOL(sysctl_overcommit_ratio); -EXPORT_SYMBOL(sysctl_max_map_count); -EXPORT_SYMBOL(vm_committed_space); EXPORT_SYMBOL(__vm_enough_memory); /* diff --git a/mm/nommu.c b/mm/nommu.c index d1e076a487c..6deb6ab3d6a 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -44,10 +44,6 @@ int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT; int heap_stack_gap = 0; EXPORT_SYMBOL(mem_map); -EXPORT_SYMBOL(sysctl_max_map_count); -EXPORT_SYMBOL(sysctl_overcommit_memory); -EXPORT_SYMBOL(sysctl_overcommit_ratio); -EXPORT_SYMBOL(vm_committed_space); EXPORT_SYMBOL(__vm_enough_memory); /* list of shareable VMAs */ -- cgit v1.2.3 From 99697dc02d2c1e8234c88d4256879d080483a57a Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 01:01:37 -0800 Subject: [PATCH] unexport hugetlb_total_pages I didn't find any possible modular usage in the kernel. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/hugetlb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 9a565808da3..728e9bda12e 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -237,7 +237,6 @@ unsigned long hugetlb_total_pages(void) { return nr_huge_pages * (HPAGE_SIZE / PAGE_SIZE); } -EXPORT_SYMBOL(hugetlb_total_pages); /* * We cannot handle pagefaults against hugetlb pages at all. They cause -- cgit v1.2.3 From e6a7e0e7cee3d4bc9a9d2f82ef2f9de4687a5656 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 01:01:38 -0800 Subject: [PATCH] unexport clear_page_dirty_for_io I didn't find any possible modular usage in the kernel. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page-writeback.c | 1 - 1 file changed, 1 deletion(-) diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 0166ea15c9e..74138c9a22b 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -750,7 +750,6 @@ int clear_page_dirty_for_io(struct page *page) } return TestClearPageDirty(page); } -EXPORT_SYMBOL(clear_page_dirty_for_io); int test_clear_page_writeback(struct page *page) { -- cgit v1.2.3 From f8b8db77b0cc36670ef4ed6bc31e64537ffa197e Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 01:01:39 -0800 Subject: [PATCH] unexport nr_swap_pages I didn't find any possible modular usage in the kernel. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_alloc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 2dbdd98426f..ff81b5c6551 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -64,7 +64,6 @@ long nr_swap_pages; int sysctl_lowmem_reserve_ratio[MAX_NR_ZONES-1] = { 256, 32 }; EXPORT_SYMBOL(totalram_pages); -EXPORT_SYMBOL(nr_swap_pages); /* * Used by page_zone() to look up the address of the struct zone whose -- cgit v1.2.3 From 47bdfb96de47d25bea423b5adbfe1c2e1ceaa296 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 01:01:39 -0800 Subject: [PATCH] unexport console_unblank I didn't find any possible modular usage of console_unblank in the kernel. This patch was already ACK'ed by Alan Cox. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/printk.c | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/printk.c b/kernel/printk.c index 3cb9708209b..e9be027bc93 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -806,7 +806,6 @@ void console_unblank(void) c->unblank(); release_console_sem(); } -EXPORT_SYMBOL(console_unblank); /* * Return the console tty driver structure and its associated index -- cgit v1.2.3 From 1b09d16489f831bfc23d1c7311ee331b0680e90e Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 01:01:40 -0800 Subject: [PATCH] mm/swap.c: unexport vm_acct_memory I didn't find any possible modular usage in the kernel. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/swap.c | 1 - 1 file changed, 1 deletion(-) diff --git a/mm/swap.c b/mm/swap.c index 154ae13d8b7..d09cf7f03e7 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -413,7 +413,6 @@ void vm_acct_memory(long pages) } preempt_enable(); } -EXPORT_SYMBOL(vm_acct_memory); #ifdef CONFIG_HOTPLUG_CPU static void lru_drain_cache(unsigned int cpu) -- cgit v1.2.3 From e2de225710b0f7480c29700bf93326b078657db8 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 01:01:41 -0800 Subject: [PATCH] mm/swapfile.c: unexport total_swap_pages I didn't find any possible modular usage in the kernel. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/swapfile.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/mm/swapfile.c b/mm/swapfile.c index 8970c0b7419..edafeace301 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -36,8 +36,6 @@ unsigned int nr_swapfiles; long total_swap_pages; static int swap_overflow; -EXPORT_SYMBOL(total_swap_pages); - static const char Bad_file[] = "Bad swap file entry "; static const char Unused_file[] = "Unused swap file entry "; static const char Bad_offset[] = "Bad swap offset entry "; -- cgit v1.2.3 From 4936967374c1ad0eb3b734f24875e2484c3786cc Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 01:01:41 -0800 Subject: [PATCH] mm/swap_state.c: unexport swapper_space I didn't find any possible modular usage in the kernel. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/swap_state.c | 1 - 1 file changed, 1 deletion(-) diff --git a/mm/swap_state.c b/mm/swap_state.c index dfd9a46755b..0df9a57b1de 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -40,7 +40,6 @@ struct address_space swapper_space = { .i_mmap_nonlinear = LIST_HEAD_INIT(swapper_space.i_mmap_nonlinear), .backing_dev_info = &swap_backing_dev_info, }; -EXPORT_SYMBOL(swapper_space); #define INC_CACHE_INFO(x) do { swap_cache_info.x++; } while (0) -- cgit v1.2.3 From 4664957b8ec78533f542900cecf7c38fbdc0d8da Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 01:01:42 -0800 Subject: [PATCH] unexport idle_cpu I didn't find any possible modular usage in the kernel. Signed-off-by: Adrian Bunk Acked-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/sched.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 013f1448006..3ce26954be1 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3563,8 +3563,6 @@ int idle_cpu(int cpu) return cpu_curr(cpu) == cpu_rq(cpu)->idle; } -EXPORT_SYMBOL_GPL(idle_cpu); - /** * idle_task - return the idle task for a given cpu. * @cpu: the processor in question. -- cgit v1.2.3 From b26b9bc58263acda274f82a9dde8b6d96559878a Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 01:01:43 -0800 Subject: [PATCH] unexport uts_sem I didn't find any possible modular usage in the kernel. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/sys.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/kernel/sys.c b/kernel/sys.c index bce933ebb29..c43b3e22bbd 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1497,8 +1497,6 @@ EXPORT_SYMBOL(in_egroup_p); DECLARE_RWSEM(uts_sem); -EXPORT_SYMBOL(uts_sem); - asmlinkage long sys_newuname(struct new_utsname __user * name) { int errno = 0; -- cgit v1.2.3 From 24622efd11fc5ee569b008b9f89e5e268265811b Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 01:01:44 -0800 Subject: [PATCH] __deprecated_for_modules: insert_resource This looks like something which out-of-tree code could possibly be using. Give insert_resource the twelve-month treatment. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/feature-removal-schedule.txt | 8 ++++++++ include/linux/ioport.h | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index b67189a8d8d..7fd8c80fa0f 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -69,6 +69,14 @@ Who: Grant Coady --------------------------- +What: remove EXPORT_SYMBOL(insert_resource) +When: April 2006 +Files: kernel/resource.c +Why: No modular usage in the kernel. +Who: Adrian Bunk + +--------------------------- + What: PCMCIA control ioctl (needed for pcmcia-cs [cardmgr, cardctl]) When: November 2005 Files: drivers/pcmcia/: pcmcia_ioctl.c diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 18d010bee63..cd6bd001ba4 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -94,7 +94,7 @@ extern struct resource iomem_resource; extern int request_resource(struct resource *root, struct resource *new); extern struct resource * ____request_resource(struct resource *root, struct resource *new); extern int release_resource(struct resource *new); -extern int insert_resource(struct resource *parent, struct resource *new); +extern __deprecated_for_modules int insert_resource(struct resource *parent, struct resource *new); extern int allocate_resource(struct resource *root, struct resource *new, unsigned long size, unsigned long min, unsigned long max, -- cgit v1.2.3 From dfed04492f2459e47dcb290be6ed5a8bc37096d5 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 01:01:44 -0800 Subject: [PATCH] __deprecated_for_modules: panic_timeout This looks like something which out-of-tree code could possibly be using. Give panic_timeout the twelve-month treatment. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/feature-removal-schedule.txt | 8 ++++++++ include/linux/kernel.h | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 7fd8c80fa0f..decdf9917e0 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -69,6 +69,14 @@ Who: Grant Coady --------------------------- +What: remove EXPORT_SYMBOL(panic_timeout) +When: April 2006 +Files: kernel/panic.c +Why: No modular usage in the kernel. +Who: Adrian Bunk + +--------------------------- + What: remove EXPORT_SYMBOL(insert_resource) When: April 2006 Files: kernel/resource.c diff --git a/include/linux/kernel.h b/include/linux/kernel.h index b6419489b27..b1e407a4fbd 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -168,7 +168,7 @@ static inline void console_verbose(void) extern void bust_spinlocks(int yes); extern int oops_in_progress; /* If set, an oops, panic(), BUG() or die() is in progress */ -extern int panic_timeout; +extern __deprecated_for_modules int panic_timeout; extern int panic_on_oops; extern int tainted; extern const char *print_tainted(void); -- cgit v1.2.3 From 59fee5fa4162d567c2a3c48bb40f74b94952b545 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 01:01:45 -0800 Subject: [PATCH] sound/oss/sequencer_syms: unexport reprogram_timer This patch remoes an unneeded EXPORT_SYMBOL. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- sound/oss/sequencer_syms.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/oss/sequencer_syms.c b/sound/oss/sequencer_syms.c index 45edfd767e4..5d008798c31 100644 --- a/sound/oss/sequencer_syms.c +++ b/sound/oss/sequencer_syms.c @@ -19,7 +19,6 @@ EXPORT_SYMBOL(sequencer_timer); EXPORT_SYMBOL(sound_timer_init); EXPORT_SYMBOL(sound_timer_interrupt); EXPORT_SYMBOL(sound_timer_syncinterval); -EXPORT_SYMBOL(reprogram_timer); /* Tuning */ -- cgit v1.2.3 From 233c1234d36cd6f0a38d524f0655c7eca27113e4 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 01:01:46 -0800 Subject: [PATCH] fs/super.c: unexport user_get_super There's no modular usage in the kernel and modules shouldn't use this symbol. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/super.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/super.c b/fs/super.c index f60155ec778..eed6c313290 100644 --- a/fs/super.c +++ b/fs/super.c @@ -474,8 +474,6 @@ rescan: return NULL; } -EXPORT_SYMBOL(user_get_super); - asmlinkage long sys_ustat(unsigned dev, struct ustat __user * ubuf) { struct super_block *s; -- cgit v1.2.3 From 5fed0578be842dd7d24e5240a75b02bbc748501f Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 01:01:46 -0800 Subject: [PATCH] unexport phys_proc_id and cpu_core_id EXPORT_SYMBOL's for phys_proc_id and cpu_core_id were added this year but never used. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/smpboot.c | 2 -- arch/x86_64/kernel/smpboot.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index e6488ffc1f7..47ec76794d0 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -68,11 +68,9 @@ EXPORT_SYMBOL(smp_num_siblings); /* Package ID of each logical CPU */ int phys_proc_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID}; -EXPORT_SYMBOL(phys_proc_id); /* Core ID of each logical CPU */ int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID}; -EXPORT_SYMBOL(cpu_core_id); cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; EXPORT_SYMBOL(cpu_sibling_map); diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index 658a81b33f3..4b5b088ec10 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c @@ -65,8 +65,6 @@ int smp_num_siblings = 1; /* Package ID of each logical CPU */ u8 phys_proc_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; u8 cpu_core_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; -EXPORT_SYMBOL(phys_proc_id); -EXPORT_SYMBOL(cpu_core_id); /* Bitmask of currently online CPUs */ cpumask_t cpu_online_map __read_mostly; -- cgit v1.2.3 From b449f63c8ce4a517cb91f237cc3d68d083ec2dd3 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 01:01:48 -0800 Subject: [PATCH] drivers/pnp/: cleanups This patch contains the following possible cleanups: - make needlessly global code static - #if 0 the following unused global function: - core.c: pnp_remove_device - #if 0 the following unneeded EXPORT_SYMBOL's: - card.c: pnp_add_card - card.c: pnp_remove_card - card.c: pnp_add_card_device - card.c: pnp_remove_card_device - card.c: pnp_add_card_id - core.c: pnp_register_protocol - core.c: pnp_unregister_protocol - core.c: pnp_add_device - core.c: pnp_remove_device - pnpacpi/core.c: pnpacpi_protocol - driver.c: pnp_add_id - isapnp/core.c: isapnp_read_byte - manager.c: pnp_auto_config_dev - resource.c: pnp_register_dependent_option - resource.c: pnp_register_independent_option - resource.c: pnp_register_irq_resource - resource.c: pnp_register_dma_resource - resource.c: pnp_register_port_resource - resource.c: pnp_register_mem_resource Note that this patch #if 0's exactly one functions and removes no functions. Most it does is the #if 0 of EXPORT_SYMBOL's, so if any modular code will use any of them, re-adding will be trivial. Modular ISAPnP might be interesting in some cases, but this is more legacy code. If someone would work on it to sort all the issues out (starting with the point that most users of __ISAPNP__ will have to be fixed) re-enabling the required EXPORT_SYMBOL's won't be hard for him. Signed-off-by: Adrian Bunk Cc: Adam Belay Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pnp/card.c | 4 +++- drivers/pnp/core.c | 5 ++++- drivers/pnp/driver.c | 2 ++ drivers/pnp/isapnp/core.c | 2 ++ drivers/pnp/manager.c | 2 ++ drivers/pnp/pnpacpi/core.c | 6 ++++-- drivers/pnp/resource.c | 2 ++ include/linux/pnp.h | 2 -- 8 files changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c index e95ed67d4f0..bd7c966ea2d 100644 --- a/drivers/pnp/card.c +++ b/drivers/pnp/card.c @@ -12,7 +12,7 @@ #include "base.h" LIST_HEAD(pnp_cards); -LIST_HEAD(pnp_card_drivers); +static LIST_HEAD(pnp_card_drivers); static const struct pnp_card_device_id * match_card(struct pnp_card_driver * drv, struct pnp_card * card) @@ -374,11 +374,13 @@ void pnp_unregister_card_driver(struct pnp_card_driver * drv) pnp_unregister_driver(&drv->link); } +#if 0 EXPORT_SYMBOL(pnp_add_card); EXPORT_SYMBOL(pnp_remove_card); EXPORT_SYMBOL(pnp_add_card_device); EXPORT_SYMBOL(pnp_remove_card_device); EXPORT_SYMBOL(pnp_add_card_id); +#endif /* 0 */ EXPORT_SYMBOL(pnp_request_card_device); EXPORT_SYMBOL(pnp_release_card_device); EXPORT_SYMBOL(pnp_register_card_driver); diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c index deed92459bc..aec83ec5ea2 100644 --- a/drivers/pnp/core.c +++ b/drivers/pnp/core.c @@ -158,13 +158,14 @@ void __pnp_remove_device(struct pnp_dev *dev) * * this function will free all mem used by dev */ - +#if 0 void pnp_remove_device(struct pnp_dev *dev) { if (!dev || dev->card) return; __pnp_remove_device(dev); } +#endif /* 0 */ static int __init pnp_init(void) { @@ -174,7 +175,9 @@ static int __init pnp_init(void) subsys_initcall(pnp_init); +#if 0 EXPORT_SYMBOL(pnp_register_protocol); EXPORT_SYMBOL(pnp_unregister_protocol); EXPORT_SYMBOL(pnp_add_device); EXPORT_SYMBOL(pnp_remove_device); +#endif /* 0 */ diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index 33da25f3213..d3ccce706ab 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c @@ -214,6 +214,8 @@ int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev) EXPORT_SYMBOL(pnp_register_driver); EXPORT_SYMBOL(pnp_unregister_driver); +#if 0 EXPORT_SYMBOL(pnp_add_id); +#endif EXPORT_SYMBOL(pnp_device_attach); EXPORT_SYMBOL(pnp_device_detach); diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index beedd86800f..57fd60314d5 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -941,7 +941,9 @@ EXPORT_SYMBOL(isapnp_protocol); EXPORT_SYMBOL(isapnp_present); EXPORT_SYMBOL(isapnp_cfg_begin); EXPORT_SYMBOL(isapnp_cfg_end); +#if 0 EXPORT_SYMBOL(isapnp_read_byte); +#endif EXPORT_SYMBOL(isapnp_write_byte); static int isapnp_read_resources(struct pnp_dev *dev, struct pnp_resource_table *res) diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index cbb2749db17..261668618b2 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -555,7 +555,9 @@ void pnp_resource_change(struct resource *resource, unsigned long start, unsigne EXPORT_SYMBOL(pnp_manual_config_dev); +#if 0 EXPORT_SYMBOL(pnp_auto_config_dev); +#endif EXPORT_SYMBOL(pnp_activate_dev); EXPORT_SYMBOL(pnp_disable_dev); EXPORT_SYMBOL(pnp_resource_change); diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 1a8915e7416..816479ad217 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -117,7 +117,7 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev) return ACPI_FAILURE(status) ? -ENODEV : 0; } -struct pnp_protocol pnpacpi_protocol = { +static struct pnp_protocol pnpacpi_protocol = { .name = "Plug and Play ACPI", .get = pnpacpi_get_resources, .set = pnpacpi_set_resources, @@ -234,7 +234,7 @@ static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle, } int pnpacpi_disabled __initdata; -int __init pnpacpi_init(void) +static int __init pnpacpi_init(void) { if (acpi_disabled || pnpacpi_disabled) { pnp_info("PnP ACPI: disabled"); @@ -258,4 +258,6 @@ static int __init pnpacpi_setup(char *str) } __setup("pnpacpi=", pnpacpi_setup); +#if 0 EXPORT_SYMBOL(pnpacpi_protocol); +#endif diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 887ad893934..6ded527169f 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -477,12 +477,14 @@ int pnp_check_dma(struct pnp_dev * dev, int idx) } +#if 0 EXPORT_SYMBOL(pnp_register_dependent_option); EXPORT_SYMBOL(pnp_register_independent_option); EXPORT_SYMBOL(pnp_register_irq_resource); EXPORT_SYMBOL(pnp_register_dma_resource); EXPORT_SYMBOL(pnp_register_port_resource); EXPORT_SYMBOL(pnp_register_mem_resource); +#endif /* 0 */ /* format is: pnp_reserve_irq=irq1[,irq2] .... */ diff --git a/include/linux/pnp.h b/include/linux/pnp.h index aadbac29103..584d57cb393 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -353,7 +353,6 @@ struct pnp_protocol { int pnp_register_protocol(struct pnp_protocol *protocol); void pnp_unregister_protocol(struct pnp_protocol *protocol); int pnp_add_device(struct pnp_dev *dev); -void pnp_remove_device(struct pnp_dev *dev); int pnp_device_attach(struct pnp_dev *pnp_dev); void pnp_device_detach(struct pnp_dev *pnp_dev); extern struct list_head pnp_global; @@ -399,7 +398,6 @@ static inline int pnp_register_protocol(struct pnp_protocol *protocol) { return static inline void pnp_unregister_protocol(struct pnp_protocol *protocol) { } static inline int pnp_init_device(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_add_device(struct pnp_dev *dev) { return -ENODEV; } -static inline void pnp_remove_device(struct pnp_dev *dev) { } static inline int pnp_device_attach(struct pnp_dev *pnp_dev) { return -ENODEV; } static inline void pnp_device_detach(struct pnp_dev *pnp_dev) { ; } -- cgit v1.2.3 From b0020e3f526cdbb2eb9408bc1b12171b3b91625b Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 7 Nov 2005 01:01:49 -0800 Subject: [PATCH] max1619 fix Something horrid has happened to the indenting and braces in this function, producing a warning: drivers/hwmon/max1619.c: In function `max1619_detect': drivers/hwmon/max1619.c:196: warning: `man_id' might be used uninitialized in this function drivers/hwmon/max1619.c:196: warning: `chip_id' might be used uninitialized in this function Acked-by: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/hwmon/max1619.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c index 6a82ffae1bf..69e7e125683 100644 --- a/drivers/hwmon/max1619.c +++ b/drivers/hwmon/max1619.c @@ -193,7 +193,7 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind) int err = 0; const char *name = ""; u8 reg_config=0, reg_convrate=0, reg_status=0; - u8 man_id, chip_id; + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) goto exit; @@ -238,16 +238,15 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind) } if (kind <= 0) { /* identification */ + u8 man_id, chip_id; man_id = i2c_smbus_read_byte_data(new_client, MAX1619_REG_R_MAN_ID); chip_id = i2c_smbus_read_byte_data(new_client, MAX1619_REG_R_CHIP_ID); - if ((man_id == 0x4D) && (chip_id == 0x04)){ - kind = max1619; - } - } + if ((man_id == 0x4D) && (chip_id == 0x04)) + kind = max1619; if (kind <= 0) { /* identification failed */ dev_info(&adapter->dev, @@ -255,11 +254,10 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind) "chip_id=0x%02X).\n", man_id, chip_id); goto exit_free; } - + } - if (kind == max1619){ + if (kind == max1619) name = "max1619"; - } /* We can fill in the remaining client fields */ strlcpy(new_client->name, name, I2C_NAME_SIZE); -- cgit v1.2.3 From 54b03d133b63223e3c358f882a935d9a244ed852 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 7 Nov 2005 14:09:50 +1000 Subject: [PATCH] m68knommu: add ColdFire 5208 setup support Add setup support for the new Freescale 5208 ColdFire processor. (Also fixed a little typo in there, "UNKOWN" -> "UNKNOWN"). Patch originally from Matt Waddel (from code originally written by Mike Lavender). Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds --- arch/m68knommu/kernel/setup.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c index a220345e974..abb80fa2b94 100644 --- a/arch/m68knommu/kernel/setup.c +++ b/arch/m68knommu/kernel/setup.c @@ -107,6 +107,9 @@ void (*mach_power_off)( void ) = NULL; #if defined(CONFIG_M5206e) #define CPU "COLDFIRE(m5206e)" #endif +#if defined(CONFIG_M520x) + #define CPU "COLDFIRE(m520x)" +#endif #if defined(CONFIG_M523x) #define CPU "COLDFIRE(m523x)" #endif @@ -132,7 +135,7 @@ void (*mach_power_off)( void ) = NULL; #define CPU "COLDFIRE(m5407)" #endif #ifndef CPU - #define CPU "UNKOWN" + #define CPU "UNKNOWN" #endif /* (es) */ -- cgit v1.2.3 From 9c899990ba94d5d6df25ef868aa7d5249653868c Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 7 Nov 2005 14:09:50 +1000 Subject: [PATCH] m68knommu: add 5208 ColdFire platform Makefile Add Freescale 5208 ColdFire platform Makefile. Patch originally from Matt Waddel (from code originally written by Mike Lavender). Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds --- arch/m68knommu/platform/520x/Makefile | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 arch/m68knommu/platform/520x/Makefile diff --git a/arch/m68knommu/platform/520x/Makefile b/arch/m68knommu/platform/520x/Makefile new file mode 100644 index 00000000000..e861b05106b --- /dev/null +++ b/arch/m68knommu/platform/520x/Makefile @@ -0,0 +1,19 @@ +# +# Makefile for the M5208 specific file. +# + +# +# If you want to play with the HW breakpoints then you will +# need to add define this, which will give you a stack backtrace +# on the console port whenever a DBG interrupt occurs. You have to +# set up you HW breakpoints to trigger a DBG interrupt: +# +# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT +# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT +# + +ifdef CONFIG_FULLDEBUG +AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 +endif + +obj-y := config.o -- cgit v1.2.3 From 3aec6fe2a24067ffeb2e7641bd9dd18e41654842 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 7 Nov 2005 14:09:50 +1000 Subject: [PATCH] m68knommu: use the ColdFire PIT timer for new 5208 The Freescale 5208 ColdFire uses the common PIT timer code for its internal timer. Build it when configured for the 5208 processor. Add support for the internal register map of the 5208 ColdFire fmaily. Patch originally from Matt Waddel (from code originally written by Mike Lavender). Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds --- arch/m68knommu/platform/5307/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/m68knommu/platform/5307/Makefile b/arch/m68knommu/platform/5307/Makefile index 6fe5a2b8fb0..8d1619dc1ea 100644 --- a/arch/m68knommu/platform/5307/Makefile +++ b/arch/m68knommu/platform/5307/Makefile @@ -19,6 +19,7 @@ endif obj-$(CONFIG_COLDFIRE) += entry.o vectors.o ints.o obj-$(CONFIG_M5206) += timers.o obj-$(CONFIG_M5206e) += timers.o +obj-$(CONFIG_M520x) += pit.o obj-$(CONFIG_M523x) += pit.o obj-$(CONFIG_M5249) += timers.o obj-$(CONFIG_M527x) += pit.o -- cgit v1.2.3 From 8766af935f3f018ec4fd420644360643838ec323 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 7 Nov 2005 14:09:50 +1000 Subject: [PATCH] check for failed kmalloc in inftlmount.c The INFTL mount code contains a kmalloc() followed by a memset() without handling a possible memory allocation failure. Signed-off-by: Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds --- drivers/mtd/inftlmount.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c index b5dda47395a..3dac53feeee 100644 --- a/drivers/mtd/inftlmount.c +++ b/drivers/mtd/inftlmount.c @@ -574,6 +574,12 @@ int INFTL_mount(struct INFTLrecord *s) /* Temporary buffer to store ANAC numbers. */ ANACtable = kmalloc(s->nb_blocks * sizeof(u8), GFP_KERNEL); + if (!ANACtable) { + printk(KERN_WARNING "INFTL: allocation of ANACtable " + "failed (%zd bytes)\n", + s->nb_blocks * sizeof(u8)); + return -ENOMEM; + } memset(ANACtable, 0, s->nb_blocks); /* -- cgit v1.2.3 From 9ed8a0d6c80bce78c703c85fa2f15db277fde933 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 7 Nov 2005 14:09:50 +1000 Subject: [PATCH] m68knommu: add ColdFire 5208 and M5208EVB build support Add build support for the new Freescale 5208 ColdFire processor, and its M5208EVB eval board. Patch originally from Matt Waddel. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds --- arch/m68knommu/Makefile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/m68knommu/Makefile b/arch/m68knommu/Makefile index b8fdf191b8f..b6b5c14e55f 100644 --- a/arch/m68knommu/Makefile +++ b/arch/m68knommu/Makefile @@ -14,6 +14,7 @@ platform-$(CONFIG_M68VZ328) := 68VZ328 platform-$(CONFIG_M68360) := 68360 platform-$(CONFIG_M5206) := 5206 platform-$(CONFIG_M5206e) := 5206e +platform-$(CONFIG_M520x) := 520x platform-$(CONFIG_M523x) := 523x platform-$(CONFIG_M5249) := 5249 platform-$(CONFIG_M527x) := 527x @@ -29,7 +30,7 @@ board-$(CONFIG_UCDIMM) := ucdimm board-$(CONFIG_UCQUICC) := uCquicc board-$(CONFIG_DRAGEN2) := de2 board-$(CONFIG_ARNEWSH) := ARNEWSH -board-$(CONFIG_MOTOROLA) := MOTOROLA +board-$(CONFIG_FREESCALE) := FREESCALE board-$(CONFIG_M5235EVB) := M5235EVB board-$(CONFIG_M5271EVB) := M5271EVB board-$(CONFIG_M5275EVB) := M5275EVB @@ -41,6 +42,7 @@ board-$(CONFIG_SECUREEDGEMP3) := MP3 board-$(CONFIG_CLEOPATRA) := CLEOPATRA board-$(CONFIG_senTec) := senTec board-$(CONFIG_SNEHA) := SNEHA +board-$(CONFIG_M5208EVB) := M5208EVB board-$(CONFIG_MOD5272) := MOD5272 BOARD := $(board-y) @@ -56,6 +58,7 @@ MODEL := $(model-y) # cpuclass-$(CONFIG_M5206) := 5307 cpuclass-$(CONFIG_M5206e) := 5307 +cpuclass-$(CONFIG_M520x) := 5307 cpuclass-$(CONFIG_M523x) := 5307 cpuclass-$(CONFIG_M5249) := 5307 cpuclass-$(CONFIG_M527x) := 5307 @@ -80,6 +83,7 @@ export PLATFORM BOARD MODEL CPUCLASS # cflags-$(CONFIG_M5206) := -m5200 -Wa,-S -Wa,-m5200 cflags-$(CONFIG_M5206e) := -m5200 -Wa,-S -Wa,-m5200 +cflags-$(CONFIG_M520x) := -m5307 -Wa,-S -Wa,-m5307 cflags-$(CONFIG_M523x) := -m5307 -Wa,-S -Wa,-m5307 cflags-$(CONFIG_M5249) := -m5200 -Wa,-S -Wa,-m5200 cflags-$(CONFIG_M527x) := -m5307 -Wa,-S -Wa,-m5307 @@ -95,7 +99,6 @@ cflags-$(CONFIG_M68360) := -m68332 AFLAGS += $(cflags-y) CFLAGS += $(cflags-y) -CFLAGS += -fno-builtin CFLAGS += -O1 -g CFLAGS += -D__linux__ CFLAGS += -DUTS_SYSNAME=\"uClinux\" -- cgit v1.2.3 From 88a605b02449852213a46f8a8ab760cfc5b9b7c8 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 7 Nov 2005 14:09:50 +1000 Subject: [PATCH] m68knommu: platform config code for 5208 ColdFire Platform configuration code for the Freescale 5208 ColdFire processor. Patch originally from Matt Waddel (from code originally written by Mike Lavender). Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds --- arch/m68knommu/platform/520x/config.c | 65 +++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 arch/m68knommu/platform/520x/config.c diff --git a/arch/m68knommu/platform/520x/config.c b/arch/m68knommu/platform/520x/config.c new file mode 100644 index 00000000000..71dea2e0f45 --- /dev/null +++ b/arch/m68knommu/platform/520x/config.c @@ -0,0 +1,65 @@ +/***************************************************************************/ + +/* + * linux/arch/m68knommu/platform/520x/config.c + * + * Copyright (C) 2005, Freescale (www.freescale.com) + * Copyright (C) 2005, Intec Automation (mike@steroidmicros.com) + * Copyright (C) 1999-2003, Greg Ungerer (gerg@snapgear.com) + * Copyright (C) 2001-2003, SnapGear Inc. (www.snapgear.com) + */ + +/***************************************************************************/ + +#include +#include +#include +#include +#include + +/***************************************************************************/ + +/* + * DMA channel base address table. + */ +unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS]; +unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS]; + +/***************************************************************************/ + +void coldfire_pit_tick(void); +void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)); +unsigned long coldfire_pit_offset(void); +void coldfire_trap_init(void); +void coldfire_reset(void); + +/***************************************************************************/ + +/* + * Program the vector to be an auto-vectored. + */ + +void mcf_autovector(unsigned int vec) +{ + /* Everything is auto-vectored on the 520x devices */ +} + +/***************************************************************************/ + +void config_BSP(char *commandp, int size) +{ +#ifdef CONFIG_BOOTPARAM + strncpy(commandp, CONFIG_BOOTPARAM_STRING, size); + commandp[size-1] = 0; +#else + memset(commandp, 0, size); +#endif + + mach_sched_init = coldfire_pit_init; + mach_tick = coldfire_pit_tick; + mach_gettimeoffset = coldfire_pit_offset; + mach_trap_init = coldfire_trap_init; + mach_reset = coldfire_reset; +} + +/***************************************************************************/ -- cgit v1.2.3 From f15bf19b49854c984c27209bd4ade31a9c84f4de Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 7 Nov 2005 14:09:50 +1000 Subject: [PATCH] m68knommu: modify the ColdFire PIT timer for new 5208 Modified common ColdFire PIT timer code to support the 5208 as well. It uses a different set of mask and interrupt bits than other ColdFire processors. The defines for these bits have been moved in header files and set appropriately for the different processor varients. Patch originally from Matt Waddel. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds --- arch/m68knommu/platform/5307/pit.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/m68knommu/platform/5307/pit.c b/arch/m68knommu/platform/5307/pit.c index a9b2c2e7e28..323f2677e49 100644 --- a/arch/m68knommu/platform/5307/pit.c +++ b/arch/m68knommu/platform/5307/pit.c @@ -3,7 +3,7 @@ /* * pit.c -- Motorola ColdFire PIT timer. Currently this type of * hardware timer only exists in the Motorola ColdFire - * 5270/5271 and 5282 CPUs. + * 5270/5271, 5282 and other CPUs. * * Copyright (C) 1999-2004, Greg Ungerer (gerg@snapgear.com) * Copyright (C) 2001-2004, SnapGear Inc. (www.snapgear.com) @@ -47,10 +47,10 @@ void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)) icrp = (volatile unsigned char *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0 + MCFINT_PIT1); - *icrp = 0x2b; /* PIT1 with level 5, priority 3 */ + *icrp = ICR_INTRCONF; - imrp = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH); - *imrp &= ~(1 << (MCFINT_PIT1 - 32)); + imrp = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFPIT_IMR); + *imrp &= ~MCFPIT_IMR_IBIT; /* Set up PIT timer 1 as poll clock */ tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1); @@ -70,7 +70,7 @@ unsigned long coldfire_pit_offset(void) unsigned long pmr, pcntr, offset; tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1); - ipr = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IPRH); + ipr = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFPIT_IMR); pmr = *(&tp->pmr); pcntr = *(&tp->pcntr); @@ -80,7 +80,7 @@ unsigned long coldfire_pit_offset(void) * timer interupt is pending, then add on a ticks worth of time. */ offset = ((pmr - pcntr) * (1000000 / HZ)) / pmr; - if ((offset < (1000000 / HZ / 2)) && (*ipr & (1 << (MCFINT_PIT1 - 32)))) + if ((offset < (1000000 / HZ / 2)) && (*ipr & MCFPIT_IMR_IBIT)) offset += 1000000 / HZ; return offset; } -- cgit v1.2.3 From 5b3d98bb7f2842551bf3dc76ade09826d70a1cbe Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 7 Nov 2005 14:09:50 +1000 Subject: [PATCH] m68knommu: handle non base address 0 memory of M5208EVB board The Freescale M5208EVB ColdFire eval board is one of the few that doesn't have its DRAM based at address 0. Handle this special case in the common ColdFire startup code. Patch originally from Matt Waddel. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds --- arch/m68knommu/platform/5307/head.S | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/m68knommu/platform/5307/head.S b/arch/m68knommu/platform/5307/head.S index 7f4ba837901..c30c462b99b 100644 --- a/arch/m68knommu/platform/5307/head.S +++ b/arch/m68knommu/platform/5307/head.S @@ -113,6 +113,9 @@ #define MEM_BASE 0x02000000 #define VBR_BASE 0x20000000 /* vectors in SRAM */ #endif +#if defined(CONFIG_M5208EVB) +#define MEM_BASE 0x40000000 +#endif #ifndef MEM_BASE #define MEM_BASE 0x00000000 /* memory base at address 0 */ -- cgit v1.2.3 From 124df2df0c905b8762cd860a0e3fc9201fba8777 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 7 Nov 2005 14:09:50 +1000 Subject: [PATCH] m68knommu: align param section and add 5208EVB linker support Align the param section. It can end up starting on an unalingned boundary depending on the size of ksymtab_strings. If it is unaligned things like modules will fail to load with unaligned access traps. Add linker scipt support for the M5208EVB board. Patch originally from Matt Waddel. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds --- arch/m68knommu/kernel/vmlinux.lds.S | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S index 47f06787190..0eab92ca4b9 100644 --- a/arch/m68knommu/kernel/vmlinux.lds.S +++ b/arch/m68knommu/kernel/vmlinux.lds.S @@ -124,6 +124,14 @@ #define RAM_LENGTH 0x3e0000 #endif +/* + * The Freescale 5208EVB board has 32MB of RAM. + */ +#if defined(CONFIG_M5208EVB) +#define RAM_START 0x40020000 +#define RAM_LENGTH 0x01e00000 +#endif + /* * The senTec COBRA5272 board has nearly the same memory layout as * the M5272C3. We assume 16MiB ram. @@ -275,6 +283,7 @@ SECTIONS { *(__ksymtab_strings) /* Built-in module parameters */ + . = ALIGN(4) ; __start___param = .; *(__param) __stop___param = .; -- cgit v1.2.3 From 7f04d62b51828fa3d1dee9fd1ea7f37815595bfa Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 7 Nov 2005 14:09:50 +1000 Subject: [PATCH] m68knommu: add 5208 ColdFire UART support to ColdFire serial driver Add support for the Freescale 5208 processor UART's to the common ColdFire serial port code. Patch originally from Matt Waddel (from code originally written by Mike Lavender). Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds --- drivers/serial/mcfserial.c | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c index e2ebdcad553..47f7404cb04 100644 --- a/drivers/serial/mcfserial.c +++ b/drivers/serial/mcfserial.c @@ -57,7 +57,8 @@ struct timer_list mcfrs_timer_struct; * keep going. Perhaps one day the cflag settings for the * console can be used instead. */ -#if defined(CONFIG_ARNEWSH) || defined(CONFIG_MOTOROLA) || defined(CONFIG_senTec) || defined(CONFIG_SNEHA) +#if defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \ + defined(CONFIG_senTec) || defined(CONFIG_SNEHA) #define CONSOLE_BAUD_RATE 19200 #define DEFAULT_CBAUD B19200 #endif @@ -67,7 +68,7 @@ struct timer_list mcfrs_timer_struct; #define DEFAULT_CBAUD B38400 #endif -#if defined(CONFIG_MOD5272) +#if defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) #define CONSOLE_BAUD_RATE 115200 #define DEFAULT_CBAUD B115200 #endif @@ -95,7 +96,8 @@ static struct tty_driver *mcfrs_serial_driver; #undef SERIAL_DEBUG_OPEN #undef SERIAL_DEBUG_FLOW -#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) +#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ + defined(CONFIG_M520x) #define IRQBASE (MCFINT_VECBASE+MCFINT_UART0) #else #define IRQBASE 73 @@ -1528,6 +1530,35 @@ static void mcfrs_irqinit(struct mcf_serial *info) imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 + MCFINTC_IMRL); *imrp &= ~((1 << (info->irq - MCFINT_VECBASE)) | 1); +#elif defined(CONFIG_M520x) + volatile unsigned char *icrp, *uartp; + volatile unsigned long *imrp; + + uartp = info->addr; + + icrp = (volatile unsigned char *) (MCF_MBAR + MCFICM_INTC0 + + MCFINTC_ICR0 + MCFINT_UART0 + info->line); + *icrp = 0x03; + + imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 + + MCFINTC_IMRL); + *imrp &= ~((1 << (info->irq - MCFINT_VECBASE)) | 1); + if (info->line < 2) { + unsigned short *uart_par; + uart_par = (unsigned short *)(MCF_IPSBAR + MCF_GPIO_PAR_UART); + if (info->line == 0) + *uart_par |= MCF_GPIO_PAR_UART_PAR_UTXD0 + | MCF_GPIO_PAR_UART_PAR_URXD0; + else if (info->line == 1) + *uart_par |= MCF_GPIO_PAR_UART_PAR_UTXD1 + | MCF_GPIO_PAR_UART_PAR_URXD1; + } else if (info->line == 2) { + unsigned char *feci2c_par; + feci2c_par = (unsigned char *)(MCF_IPSBAR + MCF_GPIO_PAR_FECI2C); + *feci2c_par &= ~0x0F; + *feci2c_par |= MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2 + | MCF_GPIO_PAR_FECI2C_PAR_SDA_URXD2; + } #else volatile unsigned char *icrp, *uartp; -- cgit v1.2.3 From 4e51f674588009163d70a650bf7bc2a2e914ef89 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 7 Nov 2005 14:09:50 +1000 Subject: [PATCH] m68knommu: add ColdFire 5208 configure support Added support for the new Freescale 5208 ColdFire processor. Also changed name "Motorola" to new company name "Freescale". Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds --- arch/m68knommu/Kconfig | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig index 8520df9cee6..b96498120fe 100644 --- a/arch/m68knommu/Kconfig +++ b/arch/m68knommu/Kconfig @@ -71,6 +71,11 @@ config M5206e help Motorola ColdFire 5206e processor support. +config M520x + bool "MCF520x" + help + Freescale Coldfire 5207/5208 processor support. + config M523x bool "MCF523x" help @@ -120,7 +125,7 @@ config M527x config COLDFIRE bool - depends on (M5206 || M5206e || M523x || M5249 || M527x || M5272 || M528x || M5307 || M5407) + depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M5407) default y choice @@ -322,6 +327,12 @@ config ELITE help Support for the Motorola M5206eLITE board. +config M5208EVB + bool "Freescale M5208EVB board support" + depends on M520x + help + Support for the Freescale Coldfire M5208EVB. + config M5235EVB bool "Freescale M5235EVB support" depends on M523x @@ -465,10 +476,10 @@ config ARNEWSH default y depends on (ARN5206 || ARN5307) -config MOTOROLA +config FREESCALE bool default y - depends on (M5206eC3 || M5235EVB || M5249C3 || M5271EVB || M5272C3 || M5275EVB || M5282EVB || M5307C3 || M5407C3) + depends on (M5206eC3 || M5208EVB || M5235EVB || M5249C3 || M5271EVB || M5272C3 || M5275EVB || M5282EVB || M5307C3 || M5407C3) config HW_FEITH bool -- cgit v1.2.3 From 3dead1a36069e0697a22ab9d623ac2c37247dfd0 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 7 Nov 2005 14:09:50 +1000 Subject: [PATCH] m68knommu: enable cache support code for ColdFIre 5249 Enable the ColdFire 5249 cache support code - it should have been on. Also one more change of "extern inline" to "static inline". Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds --- include/asm-m68knommu/cacheflush.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/asm-m68knommu/cacheflush.h b/include/asm-m68knommu/cacheflush.h index 026bbc9565b..49925e91e89 100644 --- a/include/asm-m68knommu/cacheflush.h +++ b/include/asm-m68knommu/cacheflush.h @@ -25,7 +25,7 @@ #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ memcpy(dst, src, len) -extern inline void __flush_cache_all(void) +static inline void __flush_cache_all(void) { #ifdef CONFIG_M5407 /* @@ -64,7 +64,7 @@ extern inline void __flush_cache_all(void) "nop\n\t" : : : "d0" ); #endif /* CONFIG_M5272 */ -#if CONFIG_M5249 +#ifdef CONFIG_M5249 __asm__ __volatile__ ( "movel #0xa1000200, %%d0\n\t" "movec %%d0, %%CACR\n\t" -- cgit v1.2.3 From 7a77d918ad8fb152312525b70780f6e0052b3ee3 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 7 Nov 2005 14:09:50 +1000 Subject: [PATCH] m68knommu: FEC ethernet header support for the ColdFire 5208 Add support for the new 5208 ColdFire in the FEC ethernet header. Patch originally from Matt Waddel (from code originally written by Mike Lavender). Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds --- drivers/net/fec.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/fec.h b/drivers/net/fec.h index 045761b8a60..965c5c49fcd 100644 --- a/drivers/net/fec.h +++ b/drivers/net/fec.h @@ -1,11 +1,10 @@ /****************************************************************************/ /* - * fec.h -- Fast Ethernet Controller for Motorola ColdFire 5230, - * 5231, 5232, 5234, 5235, 5270, 5271, 5272, 5274, 5275, - * 5280 and 5282. + * fec.h -- Fast Ethernet Controller for Motorola ColdFire SoC + * processors. * - * (C) Copyright 2000-2003, Greg Ungerer (gerg@snapgear.com) + * (C) Copyright 2000-2005, Greg Ungerer (gerg@snapgear.com) * (C) Copyright 2000-2001, Lineo (www.lineo.com) */ @@ -14,7 +13,8 @@ #define FEC_H /****************************************************************************/ -#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) +#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ + defined(CONFIG_M520x) /* * Just figures, Motorola would have to change the offsets for * registers in the same peripheral device on different models -- cgit v1.2.3 From 562d2f8ce4e463e1427ddfab5e84440323856f43 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 7 Nov 2005 14:09:50 +1000 Subject: [PATCH] m68knommu: FEC ethernet support for the ColdFire 5208 Add support for the new 5208 ColdFire (Matt Waddel / Mike Lavender) Patch originally from Matt Waddel (from code originally written by Mike Lavender). I also re-ordered the init code to avoid interrupt lockups on some platforms (at least the 5275, but others have reported it on the 5235 as well). Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds --- drivers/net/fec.c | 240 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 218 insertions(+), 22 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 85504fb900d..bd6983d1afb 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -18,8 +18,8 @@ * Much better multiple PHY support by Magnus Damm. * Copyright (c) 2000 Ericsson Radio Systems AB. * - * Support for FEC controller of ColdFire/5270/5271/5272/5274/5275/5280/5282. - * Copyright (c) 2001-2004 Greg Ungerer (gerg@snapgear.com) + * Support for FEC controller of ColdFire processors. + * Copyright (c) 2001-2005 Greg Ungerer (gerg@snapgear.com) * * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be) * Copyright (c) 2004-2005 Macq Electronique SA. @@ -50,7 +50,8 @@ #include #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \ - defined(CONFIG_M5272) || defined(CONFIG_M528x) + defined(CONFIG_M5272) || defined(CONFIG_M528x) || \ + defined(CONFIG_M520x) #include #include #include "fec.h" @@ -77,6 +78,8 @@ static unsigned int fec_hw[] = { (MCF_MBAR + 0x1800), #elif defined(CONFIG_M523x) || defined(CONFIG_M528x) (MCF_MBAR + 0x1000), +#elif defined(CONFIG_M520x) + (MCF_MBAR+0x30000), #else &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec), #endif @@ -139,6 +142,10 @@ typedef struct { #define TX_RING_SIZE 16 /* Must be power of two */ #define TX_RING_MOD_MASK 15 /* for this to work */ +#if (((RX_RING_SIZE + TX_RING_SIZE) * 8) > PAGE_SIZE) +#error "FEC: descriptor ring size contants too large" +#endif + /* Interrupt events/masks. */ #define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */ @@ -164,7 +171,8 @@ typedef struct { * size bits. Other FEC hardware does not, so we need to take that into * account when setting it. */ -#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) +#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ + defined(CONFIG_M520x) #define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) #else #define OPT_FRAME_SIZE 0 @@ -1136,6 +1144,65 @@ static phy_info_t const phy_info_ks8721bl = { .shutdown = phy_cmd_ks8721bl_shutdown }; +/* ------------------------------------------------------------------------- */ +/* register definitions for the DP83848 */ + +#define MII_DP8384X_PHYSTST 16 /* PHY Status Register */ + +static void mii_parse_dp8384x_sr2(uint mii_reg, struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + volatile uint *s = &(fep->phy_status); + + *s &= ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC); + + /* Link up */ + if (mii_reg & 0x0001) { + fep->link = 1; + *s |= PHY_STAT_LINK; + } else + fep->link = 0; + /* Status of link */ + if (mii_reg & 0x0010) /* Autonegotioation complete */ + *s |= PHY_STAT_ANC; + if (mii_reg & 0x0002) { /* 10MBps? */ + if (mii_reg & 0x0004) /* Full Duplex? */ + *s |= PHY_STAT_10FDX; + else + *s |= PHY_STAT_10HDX; + } else { /* 100 Mbps? */ + if (mii_reg & 0x0004) /* Full Duplex? */ + *s |= PHY_STAT_100FDX; + else + *s |= PHY_STAT_100HDX; + } + if (mii_reg & 0x0008) + *s |= PHY_STAT_FAULT; +} + +static phy_info_t phy_info_dp83848= { + 0x020005c9, + "DP83848", + + (const phy_cmd_t []) { /* config */ + { mk_mii_read(MII_REG_CR), mii_parse_cr }, + { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, + { mk_mii_read(MII_DP8384X_PHYSTST), mii_parse_dp8384x_sr2 }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* startup - enable interrupts */ + { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ + { mk_mii_read(MII_REG_SR), mii_parse_sr }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* ack_int - never happens, no interrupt */ + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* shutdown */ + { mk_mii_end, } + }, +}; + /* ------------------------------------------------------------------------- */ static phy_info_t const * const phy_info[] = { @@ -1144,6 +1211,7 @@ static phy_info_t const * const phy_info[] = { &phy_info_qs6612, &phy_info_am79c874, &phy_info_ks8721bl, + &phy_info_dp83848, NULL }; @@ -1422,6 +1490,134 @@ static void __inline__ fec_uncache(unsigned long addr) /* ------------------------------------------------------------------------- */ +#elif defined(CONFIG_M520x) + +/* + * Code specific to Coldfire 520x + */ +static void __inline__ fec_request_intrs(struct net_device *dev) +{ + struct fec_enet_private *fep; + int b; + static const struct idesc { + char *name; + unsigned short irq; + } *idp, id[] = { + { "fec(TXF)", 23 }, + { "fec(TXB)", 24 }, + { "fec(TXFIFO)", 25 }, + { "fec(TXCR)", 26 }, + { "fec(RXF)", 27 }, + { "fec(RXB)", 28 }, + { "fec(MII)", 29 }, + { "fec(LC)", 30 }, + { "fec(HBERR)", 31 }, + { "fec(GRA)", 32 }, + { "fec(EBERR)", 33 }, + { "fec(BABT)", 34 }, + { "fec(BABR)", 35 }, + { NULL }, + }; + + fep = netdev_priv(dev); + b = 64 + 13; + + /* Setup interrupt handlers. */ + for (idp = id; idp->name; idp++) { + if (request_irq(b+idp->irq,fec_enet_interrupt,0,idp->name,dev)!=0) + printk("FEC: Could not allocate %s IRQ(%d)!\n", idp->name, b+idp->irq); + } + + /* Unmask interrupts at ColdFire interrupt controller */ + { + volatile unsigned char *icrp; + volatile unsigned long *imrp; + + icrp = (volatile unsigned char *) (MCF_IPSBAR + MCFICM_INTC0 + + MCFINTC_ICR0); + for (b = 36; (b < 49); b++) + icrp[b] = 0x04; + imrp = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + + MCFINTC_IMRH); + *imrp &= ~0x0001FFF0; + } + *(volatile unsigned char *)(MCF_IPSBAR + MCF_GPIO_PAR_FEC) |= 0xf0; + *(volatile unsigned char *)(MCF_IPSBAR + MCF_GPIO_PAR_FECI2C) |= 0x0f; +} + +static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep) +{ + volatile fec_t *fecp; + + fecp = fep->hwp; + fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04; + fecp->fec_x_cntrl = 0x00; + + /* + * Set MII speed to 2.5 MHz + * See 5282 manual section 17.5.4.7: MSCR + */ + fep->phy_speed = ((((MCF_CLK / 2) / (2500000 / 10)) + 5) / 10) * 2; + fecp->fec_mii_speed = fep->phy_speed; + + fec_restart(dev, 0); +} + +static void __inline__ fec_get_mac(struct net_device *dev) +{ + struct fec_enet_private *fep = netdev_priv(dev); + volatile fec_t *fecp; + unsigned char *iap, tmpaddr[ETH_ALEN]; + + fecp = fep->hwp; + + if (FEC_FLASHMAC) { + /* + * Get MAC address from FLASH. + * If it is all 1's or 0's, use the default. + */ + iap = FEC_FLASHMAC; + if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) && + (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0)) + iap = fec_mac_default; + if ((iap[0] == 0xff) && (iap[1] == 0xff) && (iap[2] == 0xff) && + (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff)) + iap = fec_mac_default; + } else { + *((unsigned long *) &tmpaddr[0]) = fecp->fec_addr_low; + *((unsigned short *) &tmpaddr[4]) = (fecp->fec_addr_high >> 16); + iap = &tmpaddr[0]; + } + + memcpy(dev->dev_addr, iap, ETH_ALEN); + + /* Adjust MAC if using default MAC address */ + if (iap == fec_mac_default) + dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index; +} + +static void __inline__ fec_enable_phy_intr(void) +{ +} + +static void __inline__ fec_disable_phy_intr(void) +{ +} + +static void __inline__ fec_phy_ack_intr(void) +{ +} + +static void __inline__ fec_localhw_setup(void) +{ +} + +static void __inline__ fec_uncache(unsigned long addr) +{ +} + +/* ------------------------------------------------------------------------- */ + #else /* @@ -1952,6 +2148,14 @@ int __init fec_enet_init(struct net_device *dev) if (index >= FEC_MAX_PORTS) return -ENXIO; + /* Allocate memory for buffer descriptors. + */ + mem_addr = __get_free_page(GFP_KERNEL); + if (mem_addr == 0) { + printk("FEC: allocate descriptor memory failed?\n"); + return -ENOMEM; + } + /* Create an Ethernet device instance. */ fecp = (volatile fec_t *) fec_hw[index]; @@ -1964,16 +2168,6 @@ int __init fec_enet_init(struct net_device *dev) fecp->fec_ecntrl = 1; udelay(10); - /* Clear and enable interrupts */ - fecp->fec_ievent = 0xffc00000; - fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB | - FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII); - fecp->fec_hash_table_high = 0; - fecp->fec_hash_table_low = 0; - fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; - fecp->fec_ecntrl = 2; - fecp->fec_r_des_active = 0x01000000; - /* Set the Ethernet address. If using multiple Enets on the 8xx, * this needs some work to get unique addresses. * @@ -1982,14 +2176,6 @@ int __init fec_enet_init(struct net_device *dev) */ fec_get_mac(dev); - /* Allocate memory for buffer descriptors. - */ - if (((RX_RING_SIZE + TX_RING_SIZE) * sizeof(cbd_t)) > PAGE_SIZE) { - printk("FEC init error. Need more space.\n"); - printk("FEC initialization failed.\n"); - return 1; - } - mem_addr = __get_free_page(GFP_KERNEL); cbd_base = (cbd_t *)mem_addr; /* XXX: missing check for allocation failure */ @@ -2067,6 +2253,16 @@ int __init fec_enet_init(struct net_device *dev) */ fec_request_intrs(dev); + /* Clear and enable interrupts */ + fecp->fec_ievent = 0xffc00000; + fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB | + FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII); + fecp->fec_hash_table_high = 0; + fecp->fec_hash_table_low = 0; + fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; + fecp->fec_ecntrl = 2; + fecp->fec_r_des_active = 0x01000000; + dev->base_addr = (unsigned long)fecp; /* The FEC Ethernet specific entries in the device structure. */ -- cgit v1.2.3 From 2ed5e6d09e266bd2288d49aaaf240ed8c468c13c Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 7 Nov 2005 14:09:50 +1000 Subject: [PATCH] m68knommu: move some platform irq support out of irq.h Move some of the m68knommu platform specific irq core support to its own header, irqnode.h. Having it in asm-m68knommu/irq.h causes some build pain, since it is included in a number of common code places (and not all the required definitions will be included at these places). Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds --- arch/m68knommu/kernel/asm-offsets.c | 1 + arch/m68knommu/platform/5307/ints.c | 1 + include/asm-m68knommu/irq.h | 31 ------------------------------- include/asm-m68knommu/irqnode.h | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 38 insertions(+), 31 deletions(-) create mode 100644 include/asm-m68knommu/irqnode.h diff --git a/arch/m68knommu/kernel/asm-offsets.c b/arch/m68knommu/kernel/asm-offsets.c index cd3ffe12653..b988c7bdc6e 100644 --- a/arch/m68knommu/kernel/asm-offsets.c +++ b/arch/m68knommu/kernel/asm-offsets.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #define DEFINE(sym, val) \ diff --git a/arch/m68knommu/platform/5307/ints.c b/arch/m68knommu/platform/5307/ints.c index 0117754d44f..a134fb2f056 100644 --- a/arch/m68knommu/platform/5307/ints.c +++ b/arch/m68knommu/platform/5307/ints.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include diff --git a/include/asm-m68knommu/irq.h b/include/asm-m68knommu/irq.h index 208ccd969e4..a08fa9b958d 100644 --- a/include/asm-m68knommu/irq.h +++ b/include/asm-m68knommu/irq.h @@ -2,7 +2,6 @@ #define _M68K_IRQ_H_ #include -#include #include #ifdef CONFIG_COLDFIRE @@ -82,36 +81,6 @@ extern void (*mach_disable_irq)(unsigned int); #endif /* CONFIG_M68360 */ -/* - * This structure is used to chain together the ISRs for a particular - * interrupt source (if it supports chaining). - */ -typedef struct irq_node { - irqreturn_t (*handler)(int, void *, struct pt_regs *); - unsigned long flags; - void *dev_id; - const char *devname; - struct irq_node *next; -} irq_node_t; - -/* - * This structure has only 4 elements for speed reasons - */ -typedef struct irq_handler { - irqreturn_t (*handler)(int, void *, struct pt_regs *); - unsigned long flags; - void *dev_id; - const char *devname; -} irq_handler_t; - -/* count of spurious interrupts */ -extern volatile unsigned int num_spurious; - -/* - * This function returns a new irq_node_t - */ -extern irq_node_t *new_irq_node(void); - /* * Some drivers want these entry points */ diff --git a/include/asm-m68knommu/irqnode.h b/include/asm-m68knommu/irqnode.h new file mode 100644 index 00000000000..a2503dfc554 --- /dev/null +++ b/include/asm-m68knommu/irqnode.h @@ -0,0 +1,36 @@ +#ifndef _M68K_IRQNODE_H_ +#define _M68K_IRQNODE_H_ + +#include + +/* + * This structure is used to chain together the ISRs for a particular + * interrupt source (if it supports chaining). + */ +typedef struct irq_node { + irqreturn_t (*handler)(int, void *, struct pt_regs *); + unsigned long flags; + void *dev_id; + const char *devname; + struct irq_node *next; +} irq_node_t; + +/* + * This structure has only 4 elements for speed reasons + */ +typedef struct irq_handler { + irqreturn_t (*handler)(int, void *, struct pt_regs *); + unsigned long flags; + void *dev_id; + const char *devname; +} irq_handler_t; + +/* count of spurious interrupts */ +extern volatile unsigned int num_spurious; + +/* + * This function returns a new irq_node_t + */ +extern irq_node_t *new_irq_node(void); + +#endif /* _M68K_IRQNODE_H_ */ -- cgit v1.2.3 From afc4841d8a0118fcce9fd520b21ec1da401603a3 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 31 Oct 2005 00:30:39 +0000 Subject: Turn rtlx upside down. o Coding style o Race condition on open o Switch to dynamic major o Header file cleanup Signed-off-by: Ralf Baechle --- arch/mips/kernel/rtlx.c | 197 +++++++++++++++++++++++------------------------- include/asm-mips/rtlx.h | 28 +++---- 2 files changed, 105 insertions(+), 120 deletions(-) diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c index 8c81f3cb4e2..1d855112bac 100644 --- a/arch/mips/kernel/rtlx.c +++ b/arch/mips/kernel/rtlx.c @@ -20,42 +20,42 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include #include -#include -#include +#include #include #include -#include #include +#include -#define RTLX_MAJOR 64 #define RTLX_TARG_VPE 1 -struct rtlx_info *rtlx; +static struct rtlx_info *rtlx; static int major; static char module_name[] = "rtlx"; -static inline int spacefree(int read, int write, int size); +static struct irqaction irq; +static int irq_num; + +static inline int spacefree(int read, int write, int size) +{ + if (read == write) { + /* + * never fill the buffer completely, so indexes are always + * equal if empty and only empty, or !equal if data available + */ + return size - 1; + } + + return ((read + size - write) % size) - 1; +} static struct chan_waitqueues { wait_queue_head_t rt_queue; wait_queue_head_t lx_queue; } channel_wqs[RTLX_CHANNELS]; -static struct irqaction irq; -static int irq_num; - extern void *vpe_get_shared(int index); static void rtlx_dispatch(struct pt_regs *regs) @@ -63,9 +63,8 @@ static void rtlx_dispatch(struct pt_regs *regs) do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ, regs); } -irqreturn_t rtlx_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t rtlx_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - irqreturn_t r = IRQ_HANDLED; int i; for (i = 0; i < RTLX_CHANNELS; i++) { @@ -75,30 +74,7 @@ irqreturn_t rtlx_interrupt(int irq, void *dev_id, struct pt_regs *regs) wake_up_interruptible(&channel_wqs[i].lx_queue); } - return r; -} - -void dump_rtlx(void) -{ - int i; - - printk("id 0x%lx state %d\n", rtlx->id, rtlx->state); - - for (i = 0; i < RTLX_CHANNELS; i++) { - struct rtlx_channel *chan = &rtlx->channel[i]; - - printk(" rt_state %d lx_state %d buffer_size %d\n", - chan->rt_state, chan->lx_state, chan->buffer_size); - - printk(" rt_read %d rt_write %d\n", - chan->rt_read, chan->rt_write); - - printk(" lx_read %d lx_write %d\n", - chan->lx_read, chan->lx_write); - - printk(" rt_buffer <%s>\n", chan->rt_buffer); - printk(" lx_buffer <%s>\n", chan->lx_buffer); - } + return IRQ_HANDLED; } /* call when we have the address of the shared structure from the SP side. */ @@ -108,7 +84,7 @@ static int rtlx_init(struct rtlx_info *rtlxi) if (rtlxi->id != RTLX_ID) { printk(KERN_WARNING "no valid RTLX id at 0x%p\n", rtlxi); - return (-ENOEXEC); + return -ENOEXEC; } /* initialise the wait queues */ @@ -120,9 +96,8 @@ static int rtlx_init(struct rtlx_info *rtlxi) /* set up for interrupt handling */ memset(&irq, 0, sizeof(struct irqaction)); - if (cpu_has_vint) { + if (cpu_has_vint) set_vi_handler(MIPS_CPU_RTLX_IRQ, rtlx_dispatch); - } irq_num = MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ; irq.handler = rtlx_interrupt; @@ -132,7 +107,8 @@ static int rtlx_init(struct rtlx_info *rtlxi) setup_irq(irq_num, &irq); rtlx = rtlxi; - return (0); + + return 0; } /* only allow one open process at a time to open each channel */ @@ -147,36 +123,36 @@ static int rtlx_open(struct inode *inode, struct file *filp) if (rtlx == NULL) { struct rtlx_info **p; if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) { - printk(" vpe_get_shared is NULL. Has an SP program been loaded?\n"); - return (-EFAULT); + printk(KERN_ERR "vpe_get_shared is NULL. " + "Has an SP program been loaded?\n"); + return -EFAULT; } if (*p == NULL) { - printk(" vpe_shared %p %p\n", p, *p); - return (-EFAULT); + printk(KERN_ERR "vpe_shared %p %p\n", p, *p); + return -EFAULT; } if ((ret = rtlx_init(*p)) < 0) - return (ret); + return ret; } chan = &rtlx->channel[minor]; - /* already open? */ - if (chan->lx_state == RTLX_STATE_OPENED) - return (-EBUSY); + if (test_and_set_bit(RTLX_STATE_OPENED, &chan->lx_state)) + return -EBUSY; - chan->lx_state = RTLX_STATE_OPENED; - return (0); + return 0; } static int rtlx_release(struct inode *inode, struct file *filp) { - int minor; + int minor = MINOR(inode->i_rdev); - minor = MINOR(inode->i_rdev); - rtlx->channel[minor].lx_state = RTLX_STATE_UNUSED; - return (0); + clear_bit(RTLX_STATE_OPENED, &rtlx->channel[minor].lx_state); + smp_mb__after_clear_bit(); + + return 0; } static unsigned int rtlx_poll(struct file *file, poll_table * wait) @@ -199,12 +175,13 @@ static unsigned int rtlx_poll(struct file *file, poll_table * wait) if (spacefree(chan->rt_read, chan->rt_write, chan->buffer_size)) mask |= POLLOUT | POLLWRNORM; - return (mask); + return mask; } static ssize_t rtlx_read(struct file *file, char __user * buffer, size_t count, loff_t * ppos) { + unsigned long failed; size_t fl = 0L; int minor; struct rtlx_channel *lx; @@ -216,7 +193,7 @@ static ssize_t rtlx_read(struct file *file, char __user * buffer, size_t count, /* data available? */ if (lx->lx_write == lx->lx_read) { if (file->f_flags & O_NONBLOCK) - return (0); // -EAGAIN makes cat whinge + return 0; /* -EAGAIN makes cat whinge */ /* go to sleep */ add_wait_queue(&channel_wqs[minor].lx_queue, &wait); @@ -232,39 +209,39 @@ static ssize_t rtlx_read(struct file *file, char __user * buffer, size_t count, } /* find out how much in total */ - count = min( count, - (size_t)(lx->lx_write + lx->buffer_size - lx->lx_read) % lx->buffer_size); + count = min(count, + (size_t)(lx->lx_write + lx->buffer_size - lx->lx_read) % lx->buffer_size); /* then how much from the read pointer onwards */ - fl = min( count, (size_t)lx->buffer_size - lx->lx_read); + fl = min(count, (size_t)lx->buffer_size - lx->lx_read); - copy_to_user (buffer, &lx->lx_buffer[lx->lx_read], fl); + failed = copy_to_user (buffer, &lx->lx_buffer[lx->lx_read], fl); + if (failed) { + count = fl - failed; + goto out; + } /* and if there is anything left at the beginning of the buffer */ - if ( count - fl ) - copy_to_user (buffer + fl, lx->lx_buffer, count - fl); + if (count - fl) { + failed = copy_to_user (buffer + fl, lx->lx_buffer, count - fl); + if (failed) { + count -= failed; + goto out; + } + } +out: /* update the index */ lx->lx_read += count; lx->lx_read %= lx->buffer_size; - return (count); -} - -static inline int spacefree(int read, int write, int size) -{ - if (read == write) { - /* never fill the buffer completely, so indexes are always equal if empty - and only empty, or !equal if data available */ - return (size - 1); - } - - return ((read + size - write) % size) - 1; + return count; } static ssize_t rtlx_write(struct file *file, const char __user * buffer, size_t count, loff_t * ppos) { + unsigned long failed; int minor; struct rtlx_channel *rt; size_t fl; @@ -277,7 +254,7 @@ static ssize_t rtlx_write(struct file *file, const char __user * buffer, if (!spacefree(rt->rt_read, rt->rt_write, rt->buffer_size)) { if (file->f_flags & O_NONBLOCK) - return (-EAGAIN); + return -EAGAIN; add_wait_queue(&channel_wqs[minor].rt_queue, &wait); set_current_state(TASK_INTERRUPTIBLE); @@ -290,52 +267,64 @@ static ssize_t rtlx_write(struct file *file, const char __user * buffer, } /* total number of bytes to copy */ - count = min( count, (size_t)spacefree(rt->rt_read, rt->rt_write, rt->buffer_size) ); + count = min(count, (size_t)spacefree(rt->rt_read, rt->rt_write, rt->buffer_size) ); /* first bit from write pointer to the end of the buffer, or count */ fl = min(count, (size_t) rt->buffer_size - rt->rt_write); - copy_from_user(&rt->rt_buffer[rt->rt_write], buffer, fl); + failed = copy_from_user(&rt->rt_buffer[rt->rt_write], buffer, fl); + if (failed) { + count = fl - failed; + goto out; + } /* if there's any left copy to the beginning of the buffer */ - if( count - fl ) - copy_from_user(rt->rt_buffer, buffer + fl, count - fl); + if (count - fl) { + failed = copy_from_user(rt->rt_buffer, buffer + fl, count - fl); + if (failed) { + count -= failed; + goto out; + } + } +out: rt->rt_write += count; rt->rt_write %= rt->buffer_size; - return(count); + return count; } static struct file_operations rtlx_fops = { - .owner = THIS_MODULE, - .open = rtlx_open, - .release = rtlx_release, - .write = rtlx_write, - .read = rtlx_read, - .poll = rtlx_poll + .owner = THIS_MODULE, + .open = rtlx_open, + .release = rtlx_release, + .write = rtlx_write, + .read = rtlx_read, + .poll = rtlx_poll }; -static int rtlx_module_init(void) +static char register_chrdev_failed[] __initdata = + KERN_ERR "rtlx_module_init: unable to register device\n"; + +static int __init rtlx_module_init(void) { - if ((major = register_chrdev(RTLX_MAJOR, module_name, &rtlx_fops)) < 0) { - printk("rtlx_module_init: unable to register device\n"); - return (-EBUSY); + major = register_chrdev(0, module_name, &rtlx_fops); + if (major < 0) { + printk(register_chrdev_failed); + return major; } - if (major == 0) - major = RTLX_MAJOR; - - return (0); + return 0; } -static void rtlx_module_exit(void) +static void __exit rtlx_module_exit(void) { unregister_chrdev(major, module_name); } module_init(rtlx_module_init); module_exit(rtlx_module_exit); + MODULE_DESCRIPTION("MIPS RTLX"); -MODULE_AUTHOR("Elizabeth Clarke, MIPS Technologies, Inc"); +MODULE_AUTHOR("Elizabeth Clarke, MIPS Technologies, Inc."); MODULE_LICENSE("GPL"); diff --git a/include/asm-mips/rtlx.h b/include/asm-mips/rtlx.h index 83cdf6ab0d1..1298c3fdf6c 100644 --- a/include/asm-mips/rtlx.h +++ b/include/asm-mips/rtlx.h @@ -16,21 +16,19 @@ #define RTLX_ID (RTLX_xID | RTLX_VERSION) #define RTLX_CHANNELS 8 -enum rtlx_state { - RTLX_STATE_UNUSED = 0, - RTLX_STATE_INITIALISED, - RTLX_STATE_REMOTE_READY, - RTLX_STATE_OPENED -}; - #define RTLX_BUFFER_SIZE 1024 + +/* + * lx_state bits + */ +#define RTLX_STATE_OPENED 1UL + /* each channel supports read and write. linux (vpe0) reads lx_buffer and writes rt_buffer SP (vpe1) reads rt_buffer and writes lx_buffer */ -typedef struct rtlx_channel { - enum rtlx_state rt_state; - enum rtlx_state lx_state; +struct rtlx_channel { + unsigned long lx_state; int buffer_size; @@ -43,14 +41,12 @@ typedef struct rtlx_channel { void *queues; -} rtlx_channel_t; +}; -typedef struct rtlx_info { +struct rtlx_info { unsigned long id; - enum rtlx_state state; struct rtlx_channel channel[RTLX_CHANNELS]; +}; -} rtlx_info_t; - -#endif +#endif /* _RTLX_H_ */ -- cgit v1.2.3 From b0c705161f3088d384f755b0d92822a2214cba70 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 31 Oct 2005 00:33:01 +0000 Subject: Add spaces to MODULE_PROC_FAMILY values. Only a cosmetic fix to make the output of modinfo look readable. Signed-off-by: Ralf Baechle --- include/asm-mips/module.h | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/include/asm-mips/module.h b/include/asm-mips/module.h index 2be399311ee..2af496c78c1 100644 --- a/include/asm-mips/module.h +++ b/include/asm-mips/module.h @@ -76,43 +76,43 @@ search_module_dbetables(unsigned long addr) #endif #ifdef CONFIG_CPU_MIPS32_R1 -#define MODULE_PROC_FAMILY "MIPS32_R1" +#define MODULE_PROC_FAMILY "MIPS32_R1 " #elif defined CONFIG_CPU_MIPS32_R2 -#define MODULE_PROC_FAMILY "MIPS32_R2" +#define MODULE_PROC_FAMILY "MIPS32_R2 " #elif defined CONFIG_CPU_MIPS64_R1 -#define MODULE_PROC_FAMILY "MIPS64_R1" +#define MODULE_PROC_FAMILY "MIPS64_R1 " #elif defined CONFIG_CPU_MIPS64_R2 -#define MODULE_PROC_FAMILY "MIPS64_R2" +#define MODULE_PROC_FAMILY "MIPS64_R2 " #elif defined CONFIG_CPU_R3000 -#define MODULE_PROC_FAMILY "R3000" +#define MODULE_PROC_FAMILY "R3000 " #elif defined CONFIG_CPU_TX39XX -#define MODULE_PROC_FAMILY "TX39XX" +#define MODULE_PROC_FAMILY "TX39XX " #elif defined CONFIG_CPU_VR41XX -#define MODULE_PROC_FAMILY "VR41XX" +#define MODULE_PROC_FAMILY "VR41XX " #elif defined CONFIG_CPU_R4300 -#define MODULE_PROC_FAMILY "R4300" +#define MODULE_PROC_FAMILY "R4300 " #elif defined CONFIG_CPU_R4X00 -#define MODULE_PROC_FAMILY "R4X00" +#define MODULE_PROC_FAMILY "R4X00 " #elif defined CONFIG_CPU_TX49XX -#define MODULE_PROC_FAMILY "TX49XX" +#define MODULE_PROC_FAMILY "TX49XX " #elif defined CONFIG_CPU_R5000 -#define MODULE_PROC_FAMILY "R5000" +#define MODULE_PROC_FAMILY "R5000 " #elif defined CONFIG_CPU_R5432 -#define MODULE_PROC_FAMILY "R5432" +#define MODULE_PROC_FAMILY "R5432 " #elif defined CONFIG_CPU_R6000 -#define MODULE_PROC_FAMILY "R6000" +#define MODULE_PROC_FAMILY "R6000 " #elif defined CONFIG_CPU_NEVADA -#define MODULE_PROC_FAMILY "NEVADA" +#define MODULE_PROC_FAMILY "NEVADA " #elif defined CONFIG_CPU_R8000 -#define MODULE_PROC_FAMILY "R8000" +#define MODULE_PROC_FAMILY "R8000 " #elif defined CONFIG_CPU_R10000 -#define MODULE_PROC_FAMILY "R10000" +#define MODULE_PROC_FAMILY "R10000 " #elif defined CONFIG_CPU_RM7000 -#define MODULE_PROC_FAMILY "RM7000" +#define MODULE_PROC_FAMILY "RM7000 " #elif defined CONFIG_CPU_RM9000 -#define MODULE_PROC_FAMILY "RM9000" +#define MODULE_PROC_FAMILY "RM9000 " #elif defined CONFIG_CPU_SB1 -#define MODULE_PROC_FAMILY "SB1" +#define MODULE_PROC_FAMILY "SB1 " #else #error MODULE_PROC_FAMILY undefined for your processor configuration #endif -- cgit v1.2.3 From 6a4dea1ddea9d95c165ed15f08fa4e4dbbce9b82 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 30 Oct 2005 02:05:26 +0200 Subject: OSS MIPS drivers: "extern inline" -> "static inline" "extern inline" doesn't make much sense. Signed-off-by: Adrian Bunk Signed-off-by: Ralf Baechle --- sound/oss/au1000.c | 6 +++--- sound/oss/nec_vrc5477.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/oss/au1000.c b/sound/oss/au1000.c index 2c2ae2ee01a..c407de86cbb 100644 --- a/sound/oss/au1000.c +++ b/sound/oss/au1000.c @@ -563,7 +563,7 @@ static void start_adc(struct au1000_state *s) #define DMABUF_DEFAULTORDER (17-PAGE_SHIFT) #define DMABUF_MINORDER 1 -extern inline void dealloc_dmabuf(struct au1000_state *s, struct dmabuf *db) +static inline void dealloc_dmabuf(struct au1000_state *s, struct dmabuf *db) { struct page *page, *pend; @@ -667,14 +667,14 @@ static int prog_dmabuf(struct au1000_state *s, struct dmabuf *db) return 0; } -extern inline int prog_dmabuf_adc(struct au1000_state *s) +static inline int prog_dmabuf_adc(struct au1000_state *s) { stop_adc(s); return prog_dmabuf(s, &s->dma_adc); } -extern inline int prog_dmabuf_dac(struct au1000_state *s) +static inline int prog_dmabuf_dac(struct au1000_state *s) { stop_dac(s); return prog_dmabuf(s, &s->dma_dac); diff --git a/sound/oss/nec_vrc5477.c b/sound/oss/nec_vrc5477.c index 0481e5e54dd..9ac4bf7e1e8 100644 --- a/sound/oss/nec_vrc5477.c +++ b/sound/oss/nec_vrc5477.c @@ -435,7 +435,7 @@ static int ac97_codec_not_present(struct ac97_codec *codec) /* --------------------------------------------------------------------- */ -extern inline void +static inline void stop_dac(struct vrc5477_ac97_state *s) { struct dmabuf* db = &s->dma_dac; @@ -553,7 +553,7 @@ static void start_dac(struct vrc5477_ac97_state *s) spin_unlock_irqrestore(&s->lock, flags); } -extern inline void stop_adc(struct vrc5477_ac97_state *s) +static inline void stop_adc(struct vrc5477_ac97_state *s) { struct dmabuf* db = &s->dma_adc; unsigned long flags; @@ -652,7 +652,7 @@ static void start_adc(struct vrc5477_ac97_state *s) #define DMABUF_DEFAULTORDER (16-PAGE_SHIFT) #define DMABUF_MINORDER 1 -extern inline void dealloc_dmabuf(struct vrc5477_ac97_state *s, +static inline void dealloc_dmabuf(struct vrc5477_ac97_state *s, struct dmabuf *db) { if (db->lbuf) { -- cgit v1.2.3 From 08eaabfce0ba6eef7a0188888cc42f006914273e Mon Sep 17 00:00:00 2001 From: "Ilya A. Volynets-Evenbakh" Date: Wed, 26 Oct 2005 15:30:21 -0700 Subject: O2 parport definitions Signed-off-by: Ralf Baechle --- include/asm-mips/ip32/mace.h | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/include/asm-mips/ip32/mace.h b/include/asm-mips/ip32/mace.h index 432011b16c2..5bdc51d85b6 100644 --- a/include/asm-mips/ip32/mace.h +++ b/include/asm-mips/ip32/mace.h @@ -147,6 +147,29 @@ struct mace_audio { } chan[3]; }; + +/* register definitions for parallel port DMA */ +struct mace_parport { +/* 0 - do nothing, 1 - pulse terminal count to the device after buffer is drained */ +#define MACEPAR_CONTEXT_LASTFLAG BIT(63) +/* Should not cross 4K page boundary */ +#define MACEPAR_CONTEXT_DATALEN_MASK 0xfff00000000 +/* Can be arbitrarily aligned on any byte boundary on output, 64 byte aligned on input */ +#define MACEPAR_CONTEXT_BASEADDR_MASK 0xffffffff + volatile u64 context_a; + volatile u64 context_b; +#define MACEPAR_CTLSTAT_DIRECTION BIT(0) /* 0 - mem->device, 1 - device->mem */ +#define MACEPAR_CTLSTAT_ENABLE BIT(1) /* 0 - channel frozen, 1 - channel enabled */ +#define MACEPAR_CTLSTAT_RESET BIT(2) /* 0 - channel active, 1 - complete channel reset */ +#define MACEPAR_CTLSTAT_CTXB_VALID BIT(3) +#define MACEPAR_CTLSTAT_CTXA_VALID BIT(4) + volatile u64 cntlstat; /* Control/Status register */ +#define MACEPAR_DIAG_CTXINUSE BIT(1) +#define MACEPAR_DIAG_DMACTIVE BIT(2) /* 1 - Dma engine is enabled and processing something */ +#define MACEPAR_DIAG_CTRMASK 0x3ffc /* Counter of bytes left */ + volatile u64 diagnostic; /* RO: diagnostic register */ +}; + /* ISA Control and DMA registers */ struct mace_isactrl { volatile unsigned long ringbase; @@ -199,6 +222,7 @@ struct mace_isactrl { volatile unsigned long _pad[0x2000/8 - 4]; volatile unsigned long dp_ram[0x400]; + struct mace_parport parport; }; /* Keyboard & Mouse registers @@ -277,7 +301,7 @@ struct mace_perif { */ /* Parallel port */ -struct mace_parallel { /* later... */ +struct mace_parallel { }; struct mace_ecp1284 { /* later... */ -- cgit v1.2.3 From b8c2a77ce38defcf539a4ba5c666f8e9f093f887 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 31 Oct 2005 13:08:37 +0000 Subject: PNX8550 uses a MIPS32-like processor core, not R4xx0. Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 +- arch/mips/configs/pnx8550-jbs_defconfig | 11 ++++++----- arch/mips/configs/pnx8550-v2pci_defconfig | 10 ++++++---- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 0097a0d53b3..e380a8322a9 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -958,7 +958,7 @@ config SOC_PNX8550 bool select DMA_NONCOHERENT select HW_HAS_PCI - select SYS_HAS_CPU_R4X00 + select SYS_HAS_CPU_MIPS32_R1 select SYS_SUPPORTS_32BIT_KERNEL config SWAP_IO_SPACE diff --git a/arch/mips/configs/pnx8550-jbs_defconfig b/arch/mips/configs/pnx8550-jbs_defconfig index 95f84d71191..555837e4c06 100644 --- a/arch/mips/configs/pnx8550-jbs_defconfig +++ b/arch/mips/configs/pnx8550-jbs_defconfig @@ -129,7 +129,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5 # # CPU selection # -# CONFIG_CPU_MIPS32_R1 is not set +CONFIG_CPU_MIPS32_R1=y # CONFIG_CPU_MIPS32_R2 is not set # CONFIG_CPU_MIPS64_R1 is not set # CONFIG_CPU_MIPS64_R2 is not set @@ -137,7 +137,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5 # CONFIG_CPU_TX39XX is not set # CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set -CONFIG_CPU_R4X00=y +# CONFIG_CPU_R4X00 is not set # CONFIG_CPU_TX49XX is not set # CONFIG_CPU_R5000 is not set # CONFIG_CPU_R5432 is not set @@ -148,10 +148,11 @@ CONFIG_CPU_R4X00=y # CONFIG_CPU_RM7000 is not set # CONFIG_CPU_RM9000 is not set # CONFIG_CPU_SB1 is not set -CONFIG_SYS_HAS_CPU_R4X00=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_CPU_MIPS32=y +CONFIG_CPU_MIPSR1=y CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y # # Kernel type @@ -162,11 +163,11 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set # CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y # CONFIG_MIPS_MT is not set # CONFIG_64BIT_PHYS_ADDR is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y CONFIG_CPU_HAS_SYNC=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y diff --git a/arch/mips/configs/pnx8550-v2pci_defconfig b/arch/mips/configs/pnx8550-v2pci_defconfig index deb24c29ac0..05e65206a7b 100644 --- a/arch/mips/configs/pnx8550-v2pci_defconfig +++ b/arch/mips/configs/pnx8550-v2pci_defconfig @@ -128,7 +128,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5 # # CPU selection # -# CONFIG_CPU_MIPS32_R1 is not set +CONFIG_CPU_MIPS32_R1=y # CONFIG_CPU_MIPS32_R2 is not set # CONFIG_CPU_MIPS64_R1 is not set # CONFIG_CPU_MIPS64_R2 is not set @@ -136,7 +136,7 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5 # CONFIG_CPU_TX39XX is not set # CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set -CONFIG_CPU_R4X00=y +# CONFIG_CPU_R4X00 is not set # CONFIG_CPU_TX49XX is not set # CONFIG_CPU_R5000 is not set # CONFIG_CPU_R5432 is not set @@ -147,10 +147,11 @@ CONFIG_CPU_R4X00=y # CONFIG_CPU_RM7000 is not set # CONFIG_CPU_RM9000 is not set # CONFIG_CPU_SB1 is not set -CONFIG_SYS_HAS_CPU_R4X00=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_CPU_MIPS32=y +CONFIG_CPU_MIPSR1=y CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y # # Kernel type @@ -161,6 +162,7 @@ CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set # CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y # CONFIG_MIPS_MT is not set # CONFIG_64BIT_PHYS_ADDR is not set CONFIG_CPU_ADVANCED=y -- cgit v1.2.3 From 307bd284c205616e02fb85557b97f0e3e969662e Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 31 Oct 2005 23:34:52 +0000 Subject: VPE loader janitoring o Switch to dynamic major o Remove duplicate SHN_MIPS_SCOMMON definition o Coding style: remove typedefs. o Coding style: reorder to avoid the need for forward declarations o Use kzalloc. Signed-off-by: Ralf Baechle --- arch/mips/kernel/vpe.c | 100 ++++++++++++++++++++++--------------------------- 1 file changed, 44 insertions(+), 56 deletions(-) diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 97fefcc9dbe..06be405be39 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -58,10 +58,6 @@ typedef void *vpe_handle; -// defined here because the kernel module loader doesn't have -// anything to do with it. -#define SHN_MIPS_SCOMMON 0xff03 - #ifndef ARCH_SHF_SMALL #define ARCH_SHF_SMALL 0 #endif @@ -69,11 +65,8 @@ typedef void *vpe_handle; /* If this is set, the section belongs in the init part of the module */ #define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1)) -// temp number, -#define VPE_MAJOR 63 - static char module_name[] = "vpe"; -static int major = 0; +static int major; /* grab the likely amount of memory we will need. */ #ifdef CONFIG_MIPS_VPE_LOADER_TOM @@ -98,22 +91,7 @@ enum tc_state { TC_STATE_DYNAMIC }; -struct vpe; -typedef struct tc { - enum tc_state state; - int index; - - /* parent VPE */ - struct vpe *pvpe; - - /* The list of TC's with this VPE */ - struct list_head tc; - - /* The global list of tc's */ - struct list_head list; -} tc_t; - -typedef struct vpe { +struct vpe { enum vpe_state state; /* (device) minor associated with this vpe */ @@ -135,7 +113,21 @@ typedef struct vpe { /* shared symbol address */ void *shared_ptr; -} vpe_t; +}; + +struct tc { + enum tc_state state; + int index; + + /* parent VPE */ + struct vpe *pvpe; + + /* The list of TC's with this VPE */ + struct list_head tc; + + /* The global list of tc's */ + struct list_head list; +}; struct vpecontrol_ { /* Virtual processing elements */ @@ -146,7 +138,7 @@ struct vpecontrol_ { } vpecontrol; static void release_progmem(void *ptr); -static void dump_vpe(vpe_t * v); +static void dump_vpe(struct vpe * v); extern void save_gp_address(unsigned int secbase, unsigned int rel); /* get the vpe associated with this minor */ @@ -197,13 +189,11 @@ struct vpe *alloc_vpe(int minor) { struct vpe *v; - if ((v = kmalloc(sizeof(struct vpe), GFP_KERNEL)) == NULL) { + if ((v = kzalloc(sizeof(struct vpe), GFP_KERNEL)) == NULL) { printk(KERN_WARNING "VPE: alloc_vpe no mem\n"); return NULL; } - memset(v, 0, sizeof(struct vpe)); - INIT_LIST_HEAD(&v->tc); list_add_tail(&v->list, &vpecontrol.vpe_list); @@ -216,13 +206,11 @@ struct tc *alloc_tc(int index) { struct tc *t; - if ((t = kmalloc(sizeof(struct tc), GFP_KERNEL)) == NULL) { + if ((t = kzalloc(sizeof(struct tc), GFP_KERNEL)) == NULL) { printk(KERN_WARNING "VPE: alloc_tc no mem\n"); return NULL; } - memset(t, 0, sizeof(struct tc)); - INIT_LIST_HEAD(&t->tc); list_add_tail(&t->list, &vpecontrol.tc_list); @@ -412,16 +400,17 @@ static int apply_r_mips_26(struct module *me, uint32_t *location, return -ENOEXEC; } -/* Not desperately convinced this is a good check of an overflow condition - anyway. But it gets in the way of handling undefined weak symbols which - we want to set to zero. - if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { - printk(KERN_ERR - "module %s: relocation overflow\n", - me->name); - return -ENOEXEC; - } -*/ +/* + * Not desperately convinced this is a good check of an overflow condition + * anyway. But it gets in the way of handling undefined weak symbols which + * we want to set to zero. + * if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { + * printk(KERN_ERR + * "module %s: relocation overflow\n", + * me->name); + * return -ENOEXEC; + * } + */ *location = (*location & ~0x03ffffff) | ((*location + (v >> 2)) & 0x03ffffff); @@ -681,7 +670,7 @@ static void dump_tclist(void) } /* We are prepared so configure and start the VPE... */ -int vpe_run(vpe_t * v) +int vpe_run(struct vpe * v) { unsigned long val; struct tc *t; @@ -772,7 +761,7 @@ int vpe_run(vpe_t * v) return 0; } -static unsigned long find_vpe_symbols(vpe_t * v, Elf_Shdr * sechdrs, +static unsigned long find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs, unsigned int symindex, const char *strtab, struct module *mod) { @@ -792,10 +781,12 @@ static unsigned long find_vpe_symbols(vpe_t * v, Elf_Shdr * sechdrs, return 0; } -/* Allocates a VPE with some program code space(the load address), copies the contents - of the program (p)buffer performing relocatations/etc, free's it when finished. +/* + * Allocates a VPE with some program code space(the load address), copies + * the contents of the program (p)buffer performing relocatations/etc, + * free's it when finished. */ -int vpe_elfload(vpe_t * v) +int vpe_elfload(struct vpe * v) { Elf_Ehdr *hdr; Elf_Shdr *sechdrs; @@ -931,7 +922,7 @@ cleanup: return err; } -static void dump_vpe(vpe_t * v) +static void dump_vpe(struct vpe * v) { struct tc *t; @@ -947,7 +938,7 @@ static void dump_vpe(vpe_t * v) static int vpe_open(struct inode *inode, struct file *filp) { int minor; - vpe_t *v; + struct vpe *v; /* assume only 1 device at the mo. */ if ((minor = MINOR(inode->i_rdev)) != 1) { @@ -1001,7 +992,7 @@ static int vpe_open(struct inode *inode, struct file *filp) static int vpe_release(struct inode *inode, struct file *filp) { int minor, ret = 0; - vpe_t *v; + struct vpe *v; Elf_Ehdr *hdr; minor = MINOR(inode->i_rdev); @@ -1035,7 +1026,7 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer, { int minor; size_t ret = count; - vpe_t *v; + struct vpe *v; minor = MINOR(file->f_dentry->d_inode->i_rdev); if ((v = get_vpe(minor)) == NULL) @@ -1180,14 +1171,11 @@ static int __init vpe_module_init(void) return -ENODEV; } - if ((major = register_chrdev(VPE_MAJOR, module_name, &vpe_fops) < 0)) { + if ((major = register_chrdev(0, module_name, &vpe_fops) < 0)) { printk("VPE loader: unable to register character device\n"); - return -EBUSY; + return major; } - if (major == 0) - major = VPE_MAJOR; - dmt(); dvpe(); -- cgit v1.2.3 From 15b96a475706bfac71697a5d2f256750bdf749d3 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 7 Nov 2005 18:05:37 +0000 Subject: Add .gitignore files for MIPS. --- arch/mips/boot/.gitignore | 4 ++++ include/asm-mips/.gitignore | 1 + 2 files changed, 5 insertions(+) create mode 100644 arch/mips/boot/.gitignore create mode 100644 include/asm-mips/.gitignore diff --git a/arch/mips/boot/.gitignore b/arch/mips/boot/.gitignore new file mode 100644 index 00000000000..ba63401c6e1 --- /dev/null +++ b/arch/mips/boot/.gitignore @@ -0,0 +1,4 @@ +mkboot +elf2ecoff +zImage +zImage.tmp diff --git a/include/asm-mips/.gitignore b/include/asm-mips/.gitignore new file mode 100644 index 00000000000..4ec57ad5bc3 --- /dev/null +++ b/include/asm-mips/.gitignore @@ -0,0 +1 @@ +asm_offsets.h -- cgit v1.2.3 From 28622795972984359b74aa36f9645c7ca23e460b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 7 Nov 2005 18:05:37 +0000 Subject: Add .gitignore files for Turbochannel --- drivers/tc/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 drivers/tc/.gitignore diff --git a/drivers/tc/.gitignore b/drivers/tc/.gitignore new file mode 100644 index 00000000000..acc0e1e6a65 --- /dev/null +++ b/drivers/tc/.gitignore @@ -0,0 +1 @@ +lk201-map.c -- cgit v1.2.3 From e329331aedeca0f2a7e15bd26a829ee1619c05e0 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Thu, 3 Nov 2005 01:02:40 +0900 Subject: Remove mips_rtc_lock The mips_rtc_lock is no longer needed because RTC operations should be protected already by other mechanism. (rtc_lock, local_irq_save, etc.) Also, locking whole rtc_get_time/rtc_set_time should be avoided while some RTC routines might take very long time (a few seconds). Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- include/asm-mips/rtc.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/include/asm-mips/rtc.h b/include/asm-mips/rtc.h index a60e0dc7c9b..a2abc4572b6 100644 --- a/include/asm-mips/rtc.h +++ b/include/asm-mips/rtc.h @@ -14,7 +14,6 @@ #ifdef __KERNEL__ -#include #include #include @@ -29,17 +28,13 @@ #define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */ #define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */ -static DEFINE_SPINLOCK(mips_rtc_lock); - static inline unsigned int get_rtc_time(struct rtc_time *time) { unsigned long nowtime; - spin_lock(&mips_rtc_lock); nowtime = rtc_get_time(); to_tm(nowtime, time); time->tm_year -= 1900; - spin_unlock(&mips_rtc_lock); return RTC_24H; } @@ -49,12 +44,10 @@ static inline int set_rtc_time(struct rtc_time *time) unsigned long nowtime; int ret; - spin_lock(&mips_rtc_lock); nowtime = mktime(time->tm_year+1900, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec); ret = rtc_set_time(nowtime); - spin_unlock(&mips_rtc_lock); return ret; } -- cgit v1.2.3 From 53c2df2f4ebbc1d8231ca7cc13ac5381230888b1 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Thu, 3 Nov 2005 01:01:15 +0900 Subject: Use rtc_lock to protect RTC operations Many RTC routines were not protected against each other, so there are potential races, for example, ntp-update against /dev/rtc. This patch fixes them using rtc_lock. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/ddb5xxx/common/rtc_ds1386.c | 6 ++++++ arch/mips/dec/time.c | 24 ++++++++++++++++++++++-- arch/mips/jmr3927/common/rtc_ds1742.c | 6 ++++++ arch/mips/lasat/ds1603.c | 9 +++++++++ arch/mips/momentum/jaguar_atx/setup.c | 6 ++++++ arch/mips/momentum/ocelot_3/setup.c | 6 ++++++ arch/mips/momentum/ocelot_c/setup.c | 6 ++++++ arch/mips/pmc-sierra/yosemite/setup.c | 6 ++++++ arch/mips/sgi-ip22/ip22-time.c | 6 ++++++ arch/mips/sibyte/swarm/rtc_m41t81.c | 7 +++++++ arch/mips/sibyte/swarm/rtc_xicor1241.c | 6 ++++++ include/asm-mips/mc146818-time.h | 24 ++++++++++++++++++++++-- include/asm-mips/time.h | 3 +++ 13 files changed, 111 insertions(+), 4 deletions(-) diff --git a/arch/mips/ddb5xxx/common/rtc_ds1386.c b/arch/mips/ddb5xxx/common/rtc_ds1386.c index f5b11508ff2..995896ac0e3 100644 --- a/arch/mips/ddb5xxx/common/rtc_ds1386.c +++ b/arch/mips/ddb5xxx/common/rtc_ds1386.c @@ -41,7 +41,9 @@ rtc_ds1386_get_time(void) u8 byte; u8 temp; unsigned int year, month, day, hour, minute, second; + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); /* let us freeze external registers */ byte = READ_RTC(0xB); byte &= 0x3f; @@ -60,6 +62,7 @@ rtc_ds1386_get_time(void) /* enable time transfer */ byte |= 0x80; WRITE_RTC(0xB, byte); + spin_unlock_irqrestore(&rtc_lock, flags); /* calc hour */ if (temp & 0x40) { @@ -81,7 +84,9 @@ rtc_ds1386_set_time(unsigned long t) u8 byte; u8 temp; u8 year, month, day, hour, minute, second; + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); /* let us freeze external registers */ byte = READ_RTC(0xB); byte &= 0x3f; @@ -133,6 +138,7 @@ rtc_ds1386_set_time(unsigned long t) if (second != READ_RTC(0x1)) { WRITE_RTC(0x1, second); } + spin_unlock_irqrestore(&rtc_lock, flags); return 0; } diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c index dc7091caa7a..17482234413 100644 --- a/arch/mips/dec/time.c +++ b/arch/mips/dec/time.c @@ -37,10 +37,25 @@ #include +/* + * Returns true if a clock update is in progress + */ +static inline unsigned char dec_rtc_is_updating(void) +{ + unsigned char uip; + unsigned long flags; + + spin_lock_irqsave(&rtc_lock, flags); + uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); + spin_unlock_irqrestore(&rtc_lock, flags); + return uip; +} + static unsigned long dec_rtc_get_time(void) { unsigned int year, mon, day, hour, min, sec, real_year; int i; + unsigned long flags; /* The Linux interpretation of the DS1287 clock register contents: * When the Update-In-Progress (UIP) flag goes from 1 to 0, the @@ -49,11 +64,12 @@ static unsigned long dec_rtc_get_time(void) */ /* read RTC exactly on falling edge of update flag */ for (i = 0; i < 1000000; i++) /* may take up to 1 second... */ - if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) + if (dec_rtc_is_updating()) break; for (i = 0; i < 1000000; i++) /* must try at least 2.228 ms */ - if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) + if (!dec_rtc_is_updating()) break; + spin_lock_irqsave(&rtc_lock, flags); /* Isn't this overkill? UIP above should guarantee consistency */ do { sec = CMOS_READ(RTC_SECONDS); @@ -77,6 +93,7 @@ static unsigned long dec_rtc_get_time(void) * of unused BBU RAM locations. */ real_year = CMOS_READ(RTC_DEC_YEAR); + spin_unlock_irqrestore(&rtc_lock, flags); year += real_year - 72 + 2000; return mktime(year, mon, day, hour, min, sec); @@ -95,6 +112,8 @@ static int dec_rtc_set_mmss(unsigned long nowtime) int real_seconds, real_minutes, cmos_minutes; unsigned char save_control, save_freq_select; + /* irq are locally disabled here */ + spin_lock(&rtc_lock); /* tell the clock it's being set */ save_control = CMOS_READ(RTC_CONTROL); CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL); @@ -141,6 +160,7 @@ static int dec_rtc_set_mmss(unsigned long nowtime) */ CMOS_WRITE(save_control, RTC_CONTROL); CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + spin_unlock(&rtc_lock); return retval; } diff --git a/arch/mips/jmr3927/common/rtc_ds1742.c b/arch/mips/jmr3927/common/rtc_ds1742.c index 1ae4318e135..8b407d7dc46 100644 --- a/arch/mips/jmr3927/common/rtc_ds1742.c +++ b/arch/mips/jmr3927/common/rtc_ds1742.c @@ -57,7 +57,9 @@ rtc_ds1742_get_time(void) { unsigned int year, month, day, hour, minute, second; unsigned int century; + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); CMOS_WRITE(RTC_READ, RTC_CONTROL); second = BCD2BIN(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK); minute = BCD2BIN(CMOS_READ(RTC_MINUTES)); @@ -67,6 +69,7 @@ rtc_ds1742_get_time(void) year = BCD2BIN(CMOS_READ(RTC_YEAR)); century = BCD2BIN(CMOS_READ(RTC_CENTURY) & RTC_CENTURY_MASK); CMOS_WRITE(0, RTC_CONTROL); + spin_unlock_irqrestore(&rtc_lock, flags); year += century * 100; @@ -81,7 +84,9 @@ rtc_ds1742_set_time(unsigned long t) u8 year, month, day, hour, minute, second; u8 cmos_year, cmos_month, cmos_day, cmos_hour, cmos_minute, cmos_second; int cmos_century; + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); CMOS_WRITE(RTC_READ, RTC_CONTROL); cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK); cmos_minute = (u8)CMOS_READ(RTC_MINUTES); @@ -139,6 +144,7 @@ rtc_ds1742_set_time(unsigned long t) /* RTC_CENTURY and RTC_CONTROL share same address... */ CMOS_WRITE(cmos_century, RTC_CONTROL); + spin_unlock_irqrestore(&rtc_lock, flags); return 0; } diff --git a/arch/mips/lasat/ds1603.c b/arch/mips/lasat/ds1603.c index 9d7812e03dc..7dced67c55e 100644 --- a/arch/mips/lasat/ds1603.c +++ b/arch/mips/lasat/ds1603.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "ds1603.h" @@ -138,19 +139,27 @@ static void rtc_end_op(void) unsigned long ds1603_read(void) { unsigned long word; + unsigned long flags; + + spin_lock_irqsave(&rtc_lock, flags); rtc_init_op(); rtc_write_byte(READ_TIME_CMD); word = rtc_read_word(); rtc_end_op(); + spin_unlock_irqrestore(&rtc_lock, flags); return word; } int ds1603_set(unsigned long time) { + unsigned long flags; + + spin_lock_irqsave(&rtc_lock, flags); rtc_init_op(); rtc_write_byte(SET_TIME_CMD); rtc_write_word(time); rtc_end_op(); + spin_unlock_irqrestore(&rtc_lock, flags); return 0; } diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c index 768bf440645..bab192ddc18 100644 --- a/arch/mips/momentum/jaguar_atx/setup.c +++ b/arch/mips/momentum/jaguar_atx/setup.c @@ -149,7 +149,9 @@ arch_initcall(per_cpu_mappings); unsigned long m48t37y_get_time(void) { unsigned int year, month, day, hour, min, sec; + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); /* stop the update */ rtc_base[0x7ff8] = 0x40; @@ -166,6 +168,7 @@ unsigned long m48t37y_get_time(void) /* start the update */ rtc_base[0x7ff8] = 0x00; + spin_unlock_irqrestore(&rtc_lock, flags); return mktime(year, month, day, hour, min, sec); } @@ -173,11 +176,13 @@ unsigned long m48t37y_get_time(void) int m48t37y_set_time(unsigned long sec) { struct rtc_time tm; + unsigned long flags; /* convert to a more useful format -- note months count from 0 */ to_tm(sec, &tm); tm.tm_mon += 1; + spin_lock_irqsave(&rtc_lock, flags); /* enable writing */ rtc_base[0x7ff8] = 0x80; @@ -201,6 +206,7 @@ int m48t37y_set_time(unsigned long sec) /* disable writing */ rtc_base[0x7ff8] = 0x00; + spin_unlock_irqrestore(&rtc_lock, flags); return 0; } diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c index a7803e08f9d..c9b7ff8148e 100644 --- a/arch/mips/momentum/ocelot_3/setup.c +++ b/arch/mips/momentum/ocelot_3/setup.c @@ -135,7 +135,9 @@ void setup_wired_tlb_entries(void) unsigned long m48t37y_get_time(void) { unsigned int year, month, day, hour, min, sec; + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); /* stop the update */ rtc_base[0x7ff8] = 0x40; @@ -152,6 +154,7 @@ unsigned long m48t37y_get_time(void) /* start the update */ rtc_base[0x7ff8] = 0x00; + spin_unlock_irqrestore(&rtc_lock, flags); return mktime(year, month, day, hour, min, sec); } @@ -159,11 +162,13 @@ unsigned long m48t37y_get_time(void) int m48t37y_set_time(unsigned long sec) { struct rtc_time tm; + unsigned long flags; /* convert to a more useful format -- note months count from 0 */ to_tm(sec, &tm); tm.tm_mon += 1; + spin_lock_irqsave(&rtc_lock, flags); /* enable writing */ rtc_base[0x7ff8] = 0x80; @@ -187,6 +192,7 @@ int m48t37y_set_time(unsigned long sec) /* disable writing */ rtc_base[0x7ff8] = 0x00; + spin_unlock_irqrestore(&rtc_lock, flags); return 0; } diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c index ce70fc96f16..2755c154747 100644 --- a/arch/mips/momentum/ocelot_c/setup.c +++ b/arch/mips/momentum/ocelot_c/setup.c @@ -140,7 +140,9 @@ unsigned long m48t37y_get_time(void) unsigned char* rtc_base = (unsigned char*)0xfc800000; #endif unsigned int year, month, day, hour, min, sec; + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); /* stop the update */ rtc_base[0x7ff8] = 0x40; @@ -157,6 +159,7 @@ unsigned long m48t37y_get_time(void) /* start the update */ rtc_base[0x7ff8] = 0x00; + spin_unlock_irqrestore(&rtc_lock, flags); return mktime(year, month, day, hour, min, sec); } @@ -169,11 +172,13 @@ int m48t37y_set_time(unsigned long sec) unsigned char* rtc_base = (unsigned char*)0xfc800000; #endif struct rtc_time tm; + unsigned long flags; /* convert to a more useful format -- note months count from 0 */ to_tm(sec, &tm); tm.tm_mon += 1; + spin_lock_irqsave(&rtc_lock, flags); /* enable writing */ rtc_base[0x7ff8] = 0x80; @@ -197,6 +202,7 @@ int m48t37y_set_time(unsigned long sec) /* disable writing */ rtc_base[0x7ff8] = 0x00; + spin_unlock_irqrestore(&rtc_lock, flags); return 0; } diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c index bdc2ab55bed..059755b5ed5 100644 --- a/arch/mips/pmc-sierra/yosemite/setup.c +++ b/arch/mips/pmc-sierra/yosemite/setup.c @@ -73,7 +73,9 @@ void __init bus_error_init(void) unsigned long m48t37y_get_time(void) { unsigned int year, month, day, hour, min, sec; + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); /* Stop the update to the time */ m48t37_base->control = 0x40; @@ -88,6 +90,7 @@ unsigned long m48t37y_get_time(void) /* Start the update to the time again */ m48t37_base->control = 0x00; + spin_unlock_irqrestore(&rtc_lock, flags); return mktime(year, month, day, hour, min, sec); } @@ -95,11 +98,13 @@ unsigned long m48t37y_get_time(void) int m48t37y_set_time(unsigned long sec) { struct rtc_time tm; + unsigned long flags; /* convert to a more useful format -- note months count from 0 */ to_tm(sec, &tm); tm.tm_mon += 1; + spin_lock_irqsave(&rtc_lock, flags); /* enable writing */ m48t37_base->control = 0x80; @@ -123,6 +128,7 @@ int m48t37y_set_time(unsigned long sec) /* disable writing */ m48t37_base->control = 0x00; + spin_unlock_irqrestore(&rtc_lock, flags); return 0; } diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c index df9b5694328..b7300cc5c5a 100644 --- a/arch/mips/sgi-ip22/ip22-time.c +++ b/arch/mips/sgi-ip22/ip22-time.c @@ -35,7 +35,9 @@ static unsigned long indy_rtc_get_time(void) { unsigned int yrs, mon, day, hrs, min, sec; unsigned int save_control; + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); save_control = hpc3c0->rtcregs[RTC_CMD] & 0xff; hpc3c0->rtcregs[RTC_CMD] = save_control | RTC_TE; @@ -47,6 +49,7 @@ static unsigned long indy_rtc_get_time(void) yrs = BCD2BIN(hpc3c0->rtcregs[RTC_YEAR] & 0xff); hpc3c0->rtcregs[RTC_CMD] = save_control; + spin_unlock_irqrestore(&rtc_lock, flags); if (yrs < 45) yrs += 30; @@ -60,6 +63,7 @@ static int indy_rtc_set_time(unsigned long tim) { struct rtc_time tm; unsigned int save_control; + unsigned long flags; to_tm(tim, &tm); @@ -68,6 +72,7 @@ static int indy_rtc_set_time(unsigned long tim) if (tm.tm_year >= 100) tm.tm_year -= 100; + spin_lock_irqsave(&rtc_lock, flags); save_control = hpc3c0->rtcregs[RTC_CMD] & 0xff; hpc3c0->rtcregs[RTC_CMD] = save_control | RTC_TE; @@ -80,6 +85,7 @@ static int indy_rtc_set_time(unsigned long tim) hpc3c0->rtcregs[RTC_HUNDREDTH_SECOND] = 0; hpc3c0->rtcregs[RTC_CMD] = save_control; + spin_unlock_irqrestore(&rtc_lock, flags); return 0; } diff --git a/arch/mips/sibyte/swarm/rtc_m41t81.c b/arch/mips/sibyte/swarm/rtc_m41t81.c index 5b4fc26c1b3..c13914bdda5 100644 --- a/arch/mips/sibyte/swarm/rtc_m41t81.c +++ b/arch/mips/sibyte/swarm/rtc_m41t81.c @@ -144,6 +144,7 @@ static int m41t81_write(uint8_t addr, int b) int m41t81_set_time(unsigned long t) { struct rtc_time tm; + unsigned long flags; to_tm(t, &tm); @@ -153,6 +154,7 @@ int m41t81_set_time(unsigned long t) * believe we should finish writing min within a second. */ + spin_lock_irqsave(&rtc_lock, flags); tm.tm_sec = BIN2BCD(tm.tm_sec); m41t81_write(M41T81REG_SC, tm.tm_sec); @@ -180,6 +182,7 @@ int m41t81_set_time(unsigned long t) tm.tm_year %= 100; tm.tm_year = BIN2BCD(tm.tm_year); m41t81_write(M41T81REG_YR, tm.tm_year); + spin_unlock_irqrestore(&rtc_lock, flags); return 0; } @@ -187,19 +190,23 @@ int m41t81_set_time(unsigned long t) unsigned long m41t81_get_time(void) { unsigned int year, mon, day, hour, min, sec; + unsigned long flags; /* * min is valid if two reads of sec are the same. */ for (;;) { + spin_lock_irqsave(&rtc_lock, flags); sec = m41t81_read(M41T81REG_SC); min = m41t81_read(M41T81REG_MN); if (sec == m41t81_read(M41T81REG_SC)) break; + spin_unlock_irqrestore(&rtc_lock, flags); } hour = m41t81_read(M41T81REG_HR) & 0x3f; day = m41t81_read(M41T81REG_DT); mon = m41t81_read(M41T81REG_MO); year = m41t81_read(M41T81REG_YR); + spin_unlock_irqrestore(&rtc_lock, flags); sec = BCD2BIN(sec); min = BCD2BIN(min); diff --git a/arch/mips/sibyte/swarm/rtc_xicor1241.c b/arch/mips/sibyte/swarm/rtc_xicor1241.c index d9ff9323f24..f4a17883641 100644 --- a/arch/mips/sibyte/swarm/rtc_xicor1241.c +++ b/arch/mips/sibyte/swarm/rtc_xicor1241.c @@ -113,9 +113,11 @@ int xicor_set_time(unsigned long t) { struct rtc_time tm; int tmp; + unsigned long flags; to_tm(t, &tm); + spin_lock_irqsave(&rtc_lock, flags); /* unlock writes to the CCR */ xicor_write(X1241REG_SR, X1241REG_SR_WEL); xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL); @@ -160,6 +162,7 @@ int xicor_set_time(unsigned long t) xicor_write(X1241REG_HR, tmp); xicor_write(X1241REG_SR, 0); + spin_unlock_irqrestore(&rtc_lock, flags); return 0; } @@ -167,7 +170,9 @@ int xicor_set_time(unsigned long t) unsigned long xicor_get_time(void) { unsigned int year, mon, day, hour, min, sec, y2k; + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); sec = xicor_read(X1241REG_SC); min = xicor_read(X1241REG_MN); hour = xicor_read(X1241REG_HR); @@ -183,6 +188,7 @@ unsigned long xicor_get_time(void) mon = xicor_read(X1241REG_MO); year = xicor_read(X1241REG_YR); y2k = xicor_read(X1241REG_Y2K); + spin_unlock_irqrestore(&rtc_lock, flags); sec = BCD2BIN(sec); min = BCD2BIN(min); diff --git a/include/asm-mips/mc146818-time.h b/include/asm-mips/mc146818-time.h index a2c2d2c2430..47214861093 100644 --- a/include/asm-mips/mc146818-time.h +++ b/include/asm-mips/mc146818-time.h @@ -33,7 +33,9 @@ static inline int mc146818_set_rtc_mmss(unsigned long nowtime) int real_seconds, real_minutes, cmos_minutes; unsigned char save_control, save_freq_select; int retval = 0; + unsigned long flags; + spin_lock_irqsave(&rtc_lock, flags); save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); @@ -79,14 +81,30 @@ static inline int mc146818_set_rtc_mmss(unsigned long nowtime) */ CMOS_WRITE(save_control, RTC_CONTROL); CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + spin_unlock_irqrestore(&rtc_lock, flags); return retval; } +/* + * Returns true if a clock update is in progress + */ +static inline unsigned char rtc_is_updating(void) +{ + unsigned char uip; + unsigned long flags; + + spin_lock_irqsave(&rtc_lock, flags); + uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); + spin_unlock_irqrestore(&rtc_lock, flags); + return uip; +} + static inline unsigned long mc146818_get_cmos_time(void) { unsigned int year, mon, day, hour, min, sec; int i; + unsigned long flags; /* * The Linux interpretation of the CMOS clock register contents: @@ -97,12 +115,13 @@ static inline unsigned long mc146818_get_cmos_time(void) /* read RTC exactly on falling edge of update flag */ for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ - if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) + if (rtc_is_updating()) break; for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ - if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) + if (!rtc_is_updating()) break; + spin_lock_irqsave(&rtc_lock, flags); do { /* Isn't this overkill ? UIP above should guarantee consistency */ sec = CMOS_READ(RTC_SECONDS); min = CMOS_READ(RTC_MINUTES); @@ -120,6 +139,7 @@ static inline unsigned long mc146818_get_cmos_time(void) BCD_TO_BIN(mon); BCD_TO_BIN(year); } + spin_unlock_irqrestore(&rtc_lock, flags); year = mc146818_decode_year(year); return mktime(year, mon, day, hour, min, sec); diff --git a/include/asm-mips/time.h b/include/asm-mips/time.h index e22a2066587..9cc3564cc2c 100644 --- a/include/asm-mips/time.h +++ b/include/asm-mips/time.h @@ -20,6 +20,9 @@ #include #include #include +#include + +extern spinlock_t rtc_lock; /* * RTC ops. By default, they point to no-RTC functions. -- cgit v1.2.3 From a0f08209c685b4f7dccaf013da74e0e80986c477 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Sat, 5 Nov 2005 02:02:54 +0900 Subject: Define MAX_UDELAY_MS If HZ was 1000, mdelay(2) cause overflow on multiplication in __udelay. We should define MAX_UDELAY_MS properly to prevent this. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- include/asm-mips/delay.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/asm-mips/delay.h b/include/asm-mips/delay.h index 85435a8d4e5..48d00cccdaf 100644 --- a/include/asm-mips/delay.h +++ b/include/asm-mips/delay.h @@ -84,4 +84,13 @@ static inline void __udelay(unsigned long usecs, unsigned long lpj) #define udelay(usecs) __udelay((usecs),__udelay_val) +/* make sure "usecs *= ..." in udelay do not overflow. */ +#if HZ >= 1000 +#define MAX_UDELAY_MS 1 +#elif HZ <= 200 +#define MAX_UDELAY_MS 5 +#else +#define MAX_UDELAY_MS (1000 / HZ) +#endif + #endif /* _ASM_DELAY_H */ -- cgit v1.2.3 From 0d959c260e98b6b046d268b5ef5b76caf0026ab2 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 5 Nov 2005 11:26:43 +0000 Subject: IRIX: Use schedule_timeout_interruptible. Signed-off-by: Ralf Baechle --- arch/mips/kernel/irixsig.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c index 908e6368420..dd118c60bcd 100644 --- a/arch/mips/kernel/irixsig.c +++ b/arch/mips/kernel/irixsig.c @@ -502,8 +502,7 @@ asmlinkage int irix_sigpoll_sys(unsigned long __user *set, while(1) { long tmp = 0; - current->state = TASK_INTERRUPTIBLE; - expire = schedule_timeout(expire); + expire = schedule_timeout_interruptible(expire); for (i=0; i<=4; i++) tmp |= (current->pending.signal.sig[i] & kset.sig[i]); -- cgit v1.2.3 From 16cd3951366a013d52006982108437d3343c2fae Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Sat, 5 Nov 2005 23:00:58 +0900 Subject: Fix return type of setup_frame variants Since 2.6.13-rc1 setup_frame and its variants return int. But some bits were missed in the conversion. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- arch/mips/kernel/signal.c | 3 --- arch/mips/kernel/signal32.c | 13 ++++++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 9202a17db8f..05e09eedabf 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -384,9 +384,6 @@ give_sigsegv: return 0; } -extern void setup_rt_frame_n32(struct k_sigaction * ka, - struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info); - static inline int handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) { diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index dbe82130312..e315d3f6aa6 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c @@ -647,8 +647,8 @@ static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, return (void *)((sp - frame_size) & ALMASK); } -void setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, - int signr, sigset_t *set) +int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, + int signr, sigset_t *set) { struct sigframe *frame; int err = 0; @@ -694,13 +694,15 @@ void setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, current->comm, current->pid, frame, regs->cp0_epc, frame->sf_code); #endif - return; + return 1; give_sigsegv: force_sigsegv(signr, current); + return 0; } -void setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info) +int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, + int signr, sigset_t *set, siginfo_t *info) { struct rt_sigframe32 *frame; int err = 0; @@ -763,10 +765,11 @@ void setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, int signr, current->comm, current->pid, frame, regs->cp0_epc, frame->rs_code); #endif - return; + return 1; give_sigsegv: force_sigsegv(signr, current); + return 0; } static inline int handle_signal(unsigned long sig, siginfo_t *info, -- cgit v1.2.3 From 4fa0997be8050ea34f117f813d3aafa7956a5711 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 7 Nov 2005 15:36:44 +0000 Subject: Delete duplicate definitions. This reverts 8f91ed6c2fec8cb746e4dc86a79247162b4c5a7a. Signed-off-by: Ralf Baechle --- include/asm-mips/errno.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/asm-mips/errno.h b/include/asm-mips/errno.h index 9d3e6e7cdb9..3c0d840e457 100644 --- a/include/asm-mips/errno.h +++ b/include/asm-mips/errno.h @@ -119,10 +119,6 @@ #define EOWNERDEAD 165 /* Owner died */ #define ENOTRECOVERABLE 166 /* State not recoverable */ -/* for robust mutexes */ -#define EOWNERDEAD 165 /* Owner died */ -#define ENOTRECOVERABLE 166 /* State not recoverable */ - #define EDQUOT 1133 /* Quota exceeded */ #ifdef __KERNEL__ -- cgit v1.2.3 From a06d61c648890ad7e86d5ea04bd6999b254db193 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Sun, 6 Nov 2005 23:58:21 +0900 Subject: Redefine outs[wl] for ide_outs[wl]. Add missing bits to fix D-cache aliasing problem in the PIO IDE driver. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle --- include/asm-mips/mach-generic/ide.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/asm-mips/mach-generic/ide.h b/include/asm-mips/mach-generic/ide.h index 961006948c7..550979a9ea9 100644 --- a/include/asm-mips/mach-generic/ide.h +++ b/include/asm-mips/mach-generic/ide.h @@ -168,8 +168,12 @@ static inline void __ide_mm_outsl(void __iomem * port, void *addr, u32 count) /* ide_insw calls insw, not __ide_insw. Why? */ #undef insw #undef insl +#undef outsw +#undef outsl #define insw(port, addr, count) __ide_insw(port, addr, count) #define insl(port, addr, count) __ide_insl(port, addr, count) +#define outsw(port, addr, count) __ide_outsw(port, addr, count) +#define outsl(port, addr, count) __ide_outsl(port, addr, count) #endif /* __KERNEL__ */ -- cgit v1.2.3 From a637a114f36b94a1ad8b9867f43bac0414958420 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Thu, 1 Sep 2005 15:07:34 +0000 Subject: VINO driver version 0.0.5. Second cut of the VINO / Indycam driver for the Silicon Graphics Indy, much more feature complete and bug free. --- drivers/media/video/indycam.c | 262 +++++---- drivers/media/video/indycam.h | 88 ++-- drivers/media/video/saa7191.c | 533 +++++++++++++++---- drivers/media/video/saa7191.h | 172 +++++- drivers/media/video/vino.c | 1170 +++++++++++++++++++++++++++-------------- 5 files changed, 1545 insertions(+), 680 deletions(-) diff --git a/drivers/media/video/indycam.c b/drivers/media/video/indycam.c index 26dd06ec89a..deeef125eb9 100644 --- a/drivers/media/video/indycam.c +++ b/drivers/media/video/indycam.c @@ -27,15 +27,15 @@ #include "indycam.h" -//#define INDYCAM_DEBUG - -#define INDYCAM_MODULE_VERSION "0.0.3" +#define INDYCAM_MODULE_VERSION "0.0.5" MODULE_DESCRIPTION("SGI IndyCam driver"); MODULE_VERSION(INDYCAM_MODULE_VERSION); MODULE_AUTHOR("Mikael Nousiainen "); MODULE_LICENSE("GPL"); +// #define INDYCAM_DEBUG + #ifdef INDYCAM_DEBUG #define dprintk(x...) printk("IndyCam: " x); #define indycam_regdump(client) indycam_regdump_debug(client) @@ -46,14 +46,14 @@ MODULE_LICENSE("GPL"); struct indycam { struct i2c_client *client; - int version; + u8 version; }; static struct i2c_driver i2c_driver_indycam; -static const unsigned char initseq[] = { +static const u8 initseq[] = { INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */ - INDYCAM_SHUTTER_DEFAULT, /* INDYCAM_SHUTTER */ + INDYCAM_SHUTTER_60, /* INDYCAM_SHUTTER */ INDYCAM_GAIN_DEFAULT, /* INDYCAM_GAIN */ 0x00, /* INDYCAM_BRIGHTNESS (read-only) */ INDYCAM_RED_BALANCE_DEFAULT, /* INDYCAM_RED_BALANCE */ @@ -64,12 +64,11 @@ static const unsigned char initseq[] = { /* IndyCam register handling */ -static int indycam_read_reg(struct i2c_client *client, unsigned char reg, - unsigned char *value) +static int indycam_read_reg(struct i2c_client *client, u8 reg, u8 *value) { int ret; - if (reg == INDYCAM_RESET) { + if (reg == INDYCAM_REG_RESET) { dprintk("indycam_read_reg(): " "skipping write-only register %d\n", reg); *value = 0; @@ -77,24 +76,24 @@ static int indycam_read_reg(struct i2c_client *client, unsigned char reg, } ret = i2c_smbus_read_byte_data(client, reg); + if (ret < 0) { printk(KERN_ERR "IndyCam: indycam_read_reg(): read failed, " "register = 0x%02x\n", reg); return ret; } - *value = (unsigned char)ret; + *value = (u8)ret; return 0; } -static int indycam_write_reg(struct i2c_client *client, unsigned char reg, - unsigned char value) +static int indycam_write_reg(struct i2c_client *client, u8 reg, u8 value) { int err; - if ((reg == INDYCAM_BRIGHTNESS) - || (reg == INDYCAM_VERSION)) { + if ((reg == INDYCAM_REG_BRIGHTNESS) + || (reg == INDYCAM_REG_VERSION)) { dprintk("indycam_write_reg(): " "skipping read-only register %d\n", reg); return 0; @@ -102,6 +101,7 @@ static int indycam_write_reg(struct i2c_client *client, unsigned char reg, dprintk("Writing Reg %d = 0x%02x\n", reg, value); err = i2c_smbus_write_byte_data(client, reg, value); + if (err) { printk(KERN_ERR "IndyCam: indycam_write_reg(): write failed, " "register = 0x%02x, value = 0x%02x\n", reg, value); @@ -109,13 +109,12 @@ static int indycam_write_reg(struct i2c_client *client, unsigned char reg, return err; } -static int indycam_write_block(struct i2c_client *client, unsigned char reg, - unsigned char length, unsigned char *data) +static int indycam_write_block(struct i2c_client *client, u8 reg, + u8 length, u8 *data) { - unsigned char i; - int err; + int i, err; - for (i = reg; i < length; i++) { + for (i = 0; i < length; i++) { err = indycam_write_reg(client, reg + i, data[i]); if (err) return err; @@ -130,7 +129,7 @@ static int indycam_write_block(struct i2c_client *client, unsigned char reg, static void indycam_regdump_debug(struct i2c_client *client) { int i; - unsigned char val; + u8 val; for (i = 0; i < 9; i++) { indycam_read_reg(client, i, &val); @@ -139,76 +138,144 @@ static void indycam_regdump_debug(struct i2c_client *client) } #endif -static int indycam_get_controls(struct i2c_client *client, - struct indycam_control *ctrl) +static int indycam_get_control(struct i2c_client *client, + struct indycam_control *ctrl) { - unsigned char ctrl_reg; - - indycam_read_reg(client, INDYCAM_CONTROL, &ctrl_reg); - ctrl->agc = (ctrl_reg & INDYCAM_CONTROL_AGCENA) - ? INDYCAM_VALUE_ENABLED - : INDYCAM_VALUE_DISABLED; - ctrl->awb = (ctrl_reg & INDYCAM_CONTROL_AWBCTL) - ? INDYCAM_VALUE_ENABLED - : INDYCAM_VALUE_DISABLED; - indycam_read_reg(client, INDYCAM_SHUTTER, - (unsigned char *)&ctrl->shutter); - indycam_read_reg(client, INDYCAM_GAIN, - (unsigned char *)&ctrl->gain); - indycam_read_reg(client, INDYCAM_RED_BALANCE, - (unsigned char *)&ctrl->red_balance); - indycam_read_reg(client, INDYCAM_BLUE_BALANCE, - (unsigned char *)&ctrl->blue_balance); - indycam_read_reg(client, INDYCAM_RED_SATURATION, - (unsigned char *)&ctrl->red_saturation); - indycam_read_reg(client, INDYCAM_BLUE_SATURATION, - (unsigned char *)&ctrl->blue_saturation); - indycam_read_reg(client, INDYCAM_GAMMA, - (unsigned char *)&ctrl->gamma); + struct indycam *camera = i2c_get_clientdata(client); + u8 reg; + int ret = 0; + + switch (ctrl->type) { + case INDYCAM_CONTROL_AGC: + case INDYCAM_CONTROL_AWB: + ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, ®); + if (ret) + return -EIO; + if (ctrl->type == INDYCAM_CONTROL_AGC) + ctrl->value = (reg & INDYCAM_CONTROL_AGCENA) + ? 1 : 0; + else + ctrl->value = (reg & INDYCAM_CONTROL_AWBCTL) + ? 1 : 0; + break; + case INDYCAM_CONTROL_SHUTTER: + ret = indycam_read_reg(client, INDYCAM_REG_SHUTTER, ®); + if (ret) + return -EIO; + ctrl->value = ((s32)reg == 0x00) ? 0xff : ((s32)reg - 1); + break; + case INDYCAM_CONTROL_GAIN: + ret = indycam_read_reg(client, INDYCAM_REG_GAIN, ®); + if (ret) + return -EIO; + ctrl->value = (s32)reg; + break; + case INDYCAM_CONTROL_RED_BALANCE: + ret = indycam_read_reg(client, INDYCAM_REG_RED_BALANCE, ®); + if (ret) + return -EIO; + ctrl->value = (s32)reg; + break; + case INDYCAM_CONTROL_BLUE_BALANCE: + ret = indycam_read_reg(client, INDYCAM_REG_BLUE_BALANCE, ®); + if (ret) + return -EIO; + ctrl->value = (s32)reg; + break; + case INDYCAM_CONTROL_RED_SATURATION: + ret = indycam_read_reg(client, + INDYCAM_REG_RED_SATURATION, ®); + if (ret) + return -EIO; + ctrl->value = (s32)reg; + break; + case INDYCAM_CONTROL_BLUE_SATURATION: + ret = indycam_read_reg(client, + INDYCAM_REG_BLUE_SATURATION, ®); + if (ret) + return -EIO; + ctrl->value = (s32)reg; + break; + case INDYCAM_CONTROL_GAMMA: + if (camera->version == CAMERA_VERSION_MOOSE) { + ret = indycam_read_reg(client, + INDYCAM_REG_GAMMA, ®); + if (ret) + return -EIO; + ctrl->value = (s32)reg; + } else { + ctrl->value = INDYCAM_GAMMA_DEFAULT; + } + break; + default: + ret = -EINVAL; + } - return 0; + return ret; } -static int indycam_set_controls(struct i2c_client *client, - struct indycam_control *ctrl) +static int indycam_set_control(struct i2c_client *client, + struct indycam_control *ctrl) { - unsigned char ctrl_reg; + struct indycam *camera = i2c_get_clientdata(client); + u8 reg; + int ret = 0; + + switch (ctrl->type) { + case INDYCAM_CONTROL_AGC: + case INDYCAM_CONTROL_AWB: + ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, ®); + if (ret) + break; - indycam_read_reg(client, INDYCAM_CONTROL, &ctrl_reg); - if (ctrl->agc != INDYCAM_VALUE_UNCHANGED) { - if (ctrl->agc) - ctrl_reg |= INDYCAM_CONTROL_AGCENA; - else - ctrl_reg &= ~INDYCAM_CONTROL_AGCENA; - } - if (ctrl->awb != INDYCAM_VALUE_UNCHANGED) { - if (ctrl->awb) - ctrl_reg |= INDYCAM_CONTROL_AWBCTL; - else - ctrl_reg &= ~INDYCAM_CONTROL_AWBCTL; + if (ctrl->type == INDYCAM_CONTROL_AGC) { + if (ctrl->value) + reg |= INDYCAM_CONTROL_AGCENA; + else + reg &= ~INDYCAM_CONTROL_AGCENA; + } else { + if (ctrl->value) + reg |= INDYCAM_CONTROL_AWBCTL; + else + reg &= ~INDYCAM_CONTROL_AWBCTL; + } + + ret = indycam_write_reg(client, INDYCAM_REG_CONTROL, reg); + break; + case INDYCAM_CONTROL_SHUTTER: + reg = (ctrl->value == 0xff) ? 0x00 : (ctrl->value + 1); + ret = indycam_write_reg(client, INDYCAM_REG_SHUTTER, reg); + break; + case INDYCAM_CONTROL_GAIN: + ret = indycam_write_reg(client, INDYCAM_REG_GAIN, ctrl->value); + break; + case INDYCAM_CONTROL_RED_BALANCE: + ret = indycam_write_reg(client, INDYCAM_REG_RED_BALANCE, + ctrl->value); + break; + case INDYCAM_CONTROL_BLUE_BALANCE: + ret = indycam_write_reg(client, INDYCAM_REG_BLUE_BALANCE, + ctrl->value); + break; + case INDYCAM_CONTROL_RED_SATURATION: + ret = indycam_write_reg(client, INDYCAM_REG_RED_SATURATION, + ctrl->value); + break; + case INDYCAM_CONTROL_BLUE_SATURATION: + ret = indycam_write_reg(client, INDYCAM_REG_BLUE_SATURATION, + ctrl->value); + break; + case INDYCAM_CONTROL_GAMMA: + if (camera->version == CAMERA_VERSION_MOOSE) { + ret = indycam_write_reg(client, INDYCAM_REG_GAMMA, + ctrl->value); + } + break; + default: + ret = -EINVAL; } - indycam_write_reg(client, INDYCAM_CONTROL, ctrl_reg); - - if (ctrl->shutter >= 0) - indycam_write_reg(client, INDYCAM_SHUTTER, ctrl->shutter); - if (ctrl->gain >= 0) - indycam_write_reg(client, INDYCAM_GAIN, ctrl->gain); - if (ctrl->red_balance >= 0) - indycam_write_reg(client, INDYCAM_RED_BALANCE, - ctrl->red_balance); - if (ctrl->blue_balance >= 0) - indycam_write_reg(client, INDYCAM_BLUE_BALANCE, - ctrl->blue_balance); - if (ctrl->red_saturation >= 0) - indycam_write_reg(client, INDYCAM_RED_SATURATION, - ctrl->red_saturation); - if (ctrl->blue_saturation >= 0) - indycam_write_reg(client, INDYCAM_BLUE_SATURATION, - ctrl->blue_saturation); - if (ctrl->gamma >= 0) - indycam_write_reg(client, INDYCAM_GAMMA, ctrl->gamma); - return 0; + return ret; } /* I2C-interface */ @@ -247,7 +314,8 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) if (err) goto out_free_camera; - camera->version = i2c_smbus_read_byte_data(client, INDYCAM_VERSION); + camera->version = i2c_smbus_read_byte_data(client, + INDYCAM_REG_VERSION); if (camera->version != CAMERA_VERSION_INDY && camera->version != CAMERA_VERSION_MOOSE) { err = -ENODEV; @@ -260,8 +328,7 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) indycam_regdump(client); // initialize - err = indycam_write_block(client, 0, sizeof(initseq), - (unsigned char *)&initseq); + err = indycam_write_block(client, 0, sizeof(initseq), (u8 *)&initseq); if (err) { printk(KERN_ERR "IndyCam initalization failed\n"); err = -EIO; @@ -271,11 +338,10 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) indycam_regdump(client); // white balance - err = indycam_write_reg(client, INDYCAM_CONTROL, + err = indycam_write_reg(client, INDYCAM_REG_CONTROL, INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL); if (err) { - printk(KERN_ERR "IndyCam white balance " - "initialization failed\n"); + printk(KERN_ERR "IndyCam: White balancing camera failed\n"); err = -EIO; goto out_detach_client; } @@ -371,13 +437,11 @@ static int indycam_command(struct i2c_client *client, unsigned int cmd, /* TODO: convert values for indycam_set_controls() */ break; } - case DECODER_INDYCAM_GET_CONTROLS: { - struct indycam_control *ctrl = arg; - indycam_get_controls(client, ctrl); + case DECODER_INDYCAM_GET_CONTROL: { + return indycam_get_control(client, arg); } - case DECODER_INDYCAM_SET_CONTROLS: { - struct indycam_control *ctrl = arg; - indycam_set_controls(client, ctrl); + case DECODER_INDYCAM_SET_CONTROL: { + return indycam_set_control(client, arg); } default: return -EINVAL; @@ -388,12 +452,12 @@ static int indycam_command(struct i2c_client *client, unsigned int cmd, static struct i2c_driver i2c_driver_indycam = { .owner = THIS_MODULE, - .name = "indycam", - .id = I2C_DRIVERID_INDYCAM, - .flags = I2C_DF_NOTIFY, + .name = "indycam", + .id = I2C_DRIVERID_INDYCAM, + .flags = I2C_DF_NOTIFY, .attach_adapter = indycam_probe, - .detach_client = indycam_detach, - .command = indycam_command, + .detach_client = indycam_detach, + .command = indycam_command, }; static int __init indycam_init(void) diff --git a/drivers/media/video/indycam.h b/drivers/media/video/indycam.h index d9ddb6b79a0..e6ee82063ed 100644 --- a/drivers/media/video/indycam.h +++ b/drivers/media/video/indycam.h @@ -22,21 +22,21 @@ #define INDYCAM_VERSION_MINOR(x) ((x) & 0x0f) /* Register bus addresses */ -#define INDYCAM_CONTROL 0x00 -#define INDYCAM_SHUTTER 0x01 -#define INDYCAM_GAIN 0x02 -#define INDYCAM_BRIGHTNESS 0x03 /* read-only */ -#define INDYCAM_RED_BALANCE 0x04 -#define INDYCAM_BLUE_BALANCE 0x05 -#define INDYCAM_RED_SATURATION 0x06 -#define INDYCAM_BLUE_SATURATION 0x07 -#define INDYCAM_GAMMA 0x08 -#define INDYCAM_VERSION 0x0e /* read-only */ -#define INDYCAM_RESET 0x0f /* write-only */ - -#define INDYCAM_LED 0x46 -#define INDYCAM_ORIENTATION 0x47 -#define INDYCAM_BUTTON 0x48 +#define INDYCAM_REG_CONTROL 0x00 +#define INDYCAM_REG_SHUTTER 0x01 +#define INDYCAM_REG_GAIN 0x02 +#define INDYCAM_REG_BRIGHTNESS 0x03 /* read-only */ +#define INDYCAM_REG_RED_BALANCE 0x04 +#define INDYCAM_REG_BLUE_BALANCE 0x05 +#define INDYCAM_REG_RED_SATURATION 0x06 +#define INDYCAM_REG_BLUE_SATURATION 0x07 +#define INDYCAM_REG_GAMMA 0x08 +#define INDYCAM_REG_VERSION 0x0e /* read-only */ +#define INDYCAM_REG_RESET 0x0f /* write-only */ + +#define INDYCAM_REG_LED 0x46 +#define INDYCAM_REG_ORIENTATION 0x47 +#define INDYCAM_REG_BUTTON 0x48 /* Field definitions of registers */ #define INDYCAM_CONTROL_AGCENA (1<<0) /* automatic gain control */ @@ -59,13 +59,14 @@ #define INDYCAM_ORIENTATION_BOTTOM_TO_TOP 0x40 #define INDYCAM_BUTTON_RELEASED 0x10 +/* Values for controls */ #define INDYCAM_SHUTTER_MIN 0x00 #define INDYCAM_SHUTTER_MAX 0xff #define INDYCAM_GAIN_MIN 0x00 #define INDYCAM_GAIN_MAX 0xff -#define INDYCAM_RED_BALANCE_MIN 0x00 /* the effect is the opposite? */ -#define INDYCAM_RED_BALANCE_MAX 0xff -#define INDYCAM_BLUE_BALANCE_MIN 0x00 /* the effect is the opposite? */ +#define INDYCAM_RED_BALANCE_MIN 0x00 +#define INDYCAM_RED_BALANCE_MAX 0xff +#define INDYCAM_BLUE_BALANCE_MIN 0x00 #define INDYCAM_BLUE_BALANCE_MAX 0xff #define INDYCAM_RED_SATURATION_MIN 0x00 #define INDYCAM_RED_SATURATION_MAX 0xff @@ -74,34 +75,9 @@ #define INDYCAM_GAMMA_MIN 0x00 #define INDYCAM_GAMMA_MAX 0xff -/* Driver interface definitions */ - -#define INDYCAM_VALUE_ENABLED 1 -#define INDYCAM_VALUE_DISABLED 0 -#define INDYCAM_VALUE_UNCHANGED -1 - -/* When setting controls, a value of -1 leaves the control unchanged. */ -struct indycam_control { - int agc; /* boolean */ - int awb; /* boolean */ - int shutter; - int gain; - int red_balance; - int blue_balance; - int red_saturation; - int blue_saturation; - int gamma; -}; - -#define DECODER_INDYCAM_GET_CONTROLS _IOR('d', 193, struct indycam_control) -#define DECODER_INDYCAM_SET_CONTROLS _IOW('d', 194, struct indycam_control) - -/* Default values for controls */ - -#define INDYCAM_AGC_DEFAULT INDYCAM_VALUE_ENABLED -#define INDYCAM_AWB_DEFAULT INDYCAM_VALUE_ENABLED - -#define INDYCAM_SHUTTER_DEFAULT INDYCAM_SHUTTER_60 +#define INDYCAM_AGC_DEFAULT 1 +#define INDYCAM_AWB_DEFAULT 0 +#define INDYCAM_SHUTTER_DEFAULT 0xff #define INDYCAM_GAIN_DEFAULT 0x80 #define INDYCAM_RED_BALANCE_DEFAULT 0x18 #define INDYCAM_BLUE_BALANCE_DEFAULT 0xa4 @@ -109,4 +85,24 @@ struct indycam_control { #define INDYCAM_BLUE_SATURATION_DEFAULT 0xc0 #define INDYCAM_GAMMA_DEFAULT 0x80 +/* Driver interface definitions */ + +#define INDYCAM_CONTROL_AGC 0 /* boolean */ +#define INDYCAM_CONTROL_AWB 1 /* boolean */ +#define INDYCAM_CONTROL_SHUTTER 2 +#define INDYCAM_CONTROL_GAIN 3 +#define INDYCAM_CONTROL_RED_BALANCE 4 +#define INDYCAM_CONTROL_BLUE_BALANCE 5 +#define INDYCAM_CONTROL_RED_SATURATION 6 +#define INDYCAM_CONTROL_BLUE_SATURATION 7 +#define INDYCAM_CONTROL_GAMMA 8 + +struct indycam_control { + u8 type; + s32 value; +}; + +#define DECODER_INDYCAM_GET_CONTROL _IOR('d', 193, struct indycam_control) +#define DECODER_INDYCAM_SET_CONTROL _IOW('d', 194, struct indycam_control) + #endif diff --git a/drivers/media/video/saa7191.c b/drivers/media/video/saa7191.c index 3ddbb62312b..cbca896e8cf 100644 --- a/drivers/media/video/saa7191.c +++ b/drivers/media/video/saa7191.c @@ -26,71 +26,95 @@ #include "saa7191.h" -#define SAA7191_MODULE_VERSION "0.0.3" +#define SAA7191_MODULE_VERSION "0.0.5" MODULE_DESCRIPTION("Philips SAA7191 video decoder driver"); MODULE_VERSION(SAA7191_MODULE_VERSION); MODULE_AUTHOR("Mikael Nousiainen "); MODULE_LICENSE("GPL"); +// #define SAA7191_DEBUG + +#ifdef SAA7191_DEBUG +#define dprintk(x...) printk("SAA7191: " x); +#else +#define dprintk(x...) +#endif + +#define SAA7191_SYNC_COUNT 30 +#define SAA7191_SYNC_DELAY 100 /* milliseconds */ + struct saa7191 { struct i2c_client *client; /* the register values are stored here as the actual * I2C-registers are write-only */ - unsigned char reg[25]; + u8 reg[25]; - unsigned char norm; - unsigned char input; + int input; + int norm; }; static struct i2c_driver i2c_driver_saa7191; -static const unsigned char initseq[] = { +static const u8 initseq[] = { 0, /* Subaddress */ - 0x50, /* SAA7191_REG_IDEL */ - 0x30, /* SAA7191_REG_HSYB */ - 0x00, /* SAA7191_REG_HSYS */ - 0xe8, /* SAA7191_REG_HCLB */ - 0xb6, /* SAA7191_REG_HCLS */ - 0xf4, /* SAA7191_REG_HPHI */ - 0x01, /* SAA7191_REG_LUMA - chrominance trap active (CVBS) */ - 0x00, /* SAA7191_REG_HUEC */ - 0xf8, /* SAA7191_REG_CKTQ */ - 0xf8, /* SAA7191_REG_CKTS */ - 0x90, /* SAA7191_REG_PLSE */ - 0x90, /* SAA7191_REG_SESE */ - 0x00, /* SAA7191_REG_GAIN */ - 0x0c, /* SAA7191_REG_STDC - not SECAM, slow time constant */ - 0x78, /* SAA7191_REG_IOCK - chrominance from CVBS, GPSW1 & 2 off */ - 0x99, /* SAA7191_REG_CTL3 - automatic field detection */ - 0x00, /* SAA7191_REG_CTL4 */ - 0x2c, /* SAA7191_REG_CHCV */ + + 0x50, /* (0x50) SAA7191_REG_IDEL */ + + /* 50 Hz signal timing */ + 0x30, /* (0x30) SAA7191_REG_HSYB */ + 0x00, /* (0x00) SAA7191_REG_HSYS */ + 0xe8, /* (0xe8) SAA7191_REG_HCLB */ + 0xb6, /* (0xb6) SAA7191_REG_HCLS */ + 0xf4, /* (0xf4) SAA7191_REG_HPHI */ + + /* control */ + SAA7191_LUMA_APER_1, /* (0x01) SAA7191_REG_LUMA - CVBS mode */ + 0x00, /* (0x00) SAA7191_REG_HUEC */ + 0xf8, /* (0xf8) SAA7191_REG_CKTQ */ + 0xf8, /* (0xf8) SAA7191_REG_CKTS */ + 0x90, /* (0x90) SAA7191_REG_PLSE */ + 0x90, /* (0x90) SAA7191_REG_SESE */ + 0x00, /* (0x00) SAA7191_REG_GAIN */ + SAA7191_STDC_NFEN | SAA7191_STDC_HRMV, /* (0x0c) SAA7191_REG_STDC + * - not SECAM, + * slow time constant */ + SAA7191_IOCK_OEDC | SAA7191_IOCK_OEHS | SAA7191_IOCK_OEVS + | SAA7191_IOCK_OEDY, /* (0x78) SAA7191_REG_IOCK + * - chroma from CVBS, GPSW1 & 2 off */ + SAA7191_CTL3_AUFD | SAA7191_CTL3_SCEN | SAA7191_CTL3_OFTS + | SAA7191_CTL3_YDEL0, /* (0x99) SAA7191_REG_CTL3 + * - automatic field detection */ + 0x00, /* (0x00) SAA7191_REG_CTL4 */ + 0x2c, /* (0x2c) SAA7191_REG_CHCV - PAL nominal value */ 0x00, /* unused */ 0x00, /* unused */ - 0x34, /* SAA7191_REG_HS6B */ - 0x0a, /* SAA7191_REG_HS6S */ - 0xf4, /* SAA7191_REG_HC6B */ - 0xce, /* SAA7191_REG_HC6S */ - 0xf4, /* SAA7191_REG_HP6I */ + + /* 60 Hz signal timing */ + 0x34, /* (0x34) SAA7191_REG_HS6B */ + 0x0a, /* (0x0a) SAA7191_REG_HS6S */ + 0xf4, /* (0xf4) SAA7191_REG_HC6B */ + 0xce, /* (0xce) SAA7191_REG_HC6S */ + 0xf4, /* (0xf4) SAA7191_REG_HP6I */ }; /* SAA7191 register handling */ -static unsigned char saa7191_read_reg(struct i2c_client *client, - unsigned char reg) +static u8 saa7191_read_reg(struct i2c_client *client, + u8 reg) { return ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg]; } static int saa7191_read_status(struct i2c_client *client, - unsigned char *value) + u8 *value) { int ret; ret = i2c_master_recv(client, value, 1); if (ret < 0) { - printk(KERN_ERR "SAA7191: saa7191_read_status(): read failed"); + printk(KERN_ERR "SAA7191: saa7191_read_status(): read failed\n"); return ret; } @@ -98,17 +122,16 @@ static int saa7191_read_status(struct i2c_client *client, } -static int saa7191_write_reg(struct i2c_client *client, unsigned char reg, - unsigned char value) +static int saa7191_write_reg(struct i2c_client *client, u8 reg, + u8 value) { - ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg] = value; return i2c_smbus_write_byte_data(client, reg, value); } /* the first byte of data must be the first subaddress number (register) */ static int saa7191_write_block(struct i2c_client *client, - unsigned char length, unsigned char *data) + u8 length, u8 *data) { int i; int ret; @@ -121,7 +144,7 @@ static int saa7191_write_block(struct i2c_client *client, ret = i2c_master_send(client, data, length); if (ret < 0) { printk(KERN_ERR "SAA7191: saa7191_write_block(): " - "write failed"); + "write failed\n"); return ret; } @@ -132,8 +155,9 @@ static int saa7191_write_block(struct i2c_client *client, static int saa7191_set_input(struct i2c_client *client, int input) { - unsigned char luma = saa7191_read_reg(client, SAA7191_REG_LUMA); - unsigned char iock = saa7191_read_reg(client, SAA7191_REG_IOCK); + struct saa7191 *decoder = i2c_get_clientdata(client); + u8 luma = saa7191_read_reg(client, SAA7191_REG_LUMA); + u8 iock = saa7191_read_reg(client, SAA7191_REG_IOCK); int err; switch (input) { @@ -159,32 +183,20 @@ static int saa7191_set_input(struct i2c_client *client, int input) if (err) return -EIO; + decoder->input = input; + return 0; } static int saa7191_set_norm(struct i2c_client *client, int norm) { struct saa7191 *decoder = i2c_get_clientdata(client); - unsigned char stdc = saa7191_read_reg(client, SAA7191_REG_STDC); - unsigned char ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3); - unsigned char chcv = saa7191_read_reg(client, SAA7191_REG_CHCV); + u8 stdc = saa7191_read_reg(client, SAA7191_REG_STDC); + u8 ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3); + u8 chcv = saa7191_read_reg(client, SAA7191_REG_CHCV); int err; switch(norm) { - case SAA7191_NORM_AUTO: { - unsigned char status; - - // does status depend on current norm ? - if (saa7191_read_status(client, &status)) - return -EIO; - - stdc &= ~SAA7191_STDC_SECS; - ctl3 &= ~SAA7191_CTL3_FSEL; - ctl3 |= SAA7191_CTL3_AUFD; - chcv = (status & SAA7191_STATUS_FIDT) - ? SAA7191_CHCV_NTSC : SAA7191_CHCV_PAL; - break; - } case SAA7191_NORM_PAL: stdc &= ~SAA7191_STDC_SECS; ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL); @@ -217,60 +229,335 @@ static int saa7191_set_norm(struct i2c_client *client, int norm) decoder->norm = norm; + dprintk("ctl3: %02x stdc: %02x chcv: %02x\n", ctl3, + stdc, chcv); + dprintk("norm: %d\n", norm); + return 0; } -static int saa7191_get_controls(struct i2c_client *client, - struct saa7191_control *ctrl) +static int saa7191_wait_for_signal(struct i2c_client *client, u8 *status) { - unsigned char hue = saa7191_read_reg(client, SAA7191_REG_HUEC); - unsigned char stdc = saa7191_read_reg(client, SAA7191_REG_STDC); + int i = 0; - if (hue < 0x80) { - hue += 0x80; - } else { - hue -= 0x80; + dprintk("Checking for signal...\n"); + + for (i = 0; i < SAA7191_SYNC_COUNT; i++) { + if (saa7191_read_status(client, status)) + return -EIO; + + if (((*status) & SAA7191_STATUS_HLCK) == 0) { + dprintk("Signal found\n"); + return 0; + } + + msleep(SAA7191_SYNC_DELAY); } - ctrl->hue = hue; - ctrl->vtrc = (stdc & SAA7191_STDC_VTRC) - ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED; + dprintk("No signal\n"); - return 0; + return -EBUSY; } -static int saa7191_set_controls(struct i2c_client *client, - struct saa7191_control *ctrl) +static int saa7191_autodetect_norm_extended(struct i2c_client *client) { - int err; + u8 stdc = saa7191_read_reg(client, SAA7191_REG_STDC); + u8 ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3); + u8 status; + int err = 0; - if (ctrl->hue >= 0) { - unsigned char hue = ctrl->hue & 0xff; - if (hue < 0x80) { - hue += 0x80; - } else { - hue -= 0x80; + dprintk("SAA7191 extended signal auto-detection...\n"); + + stdc &= ~SAA7191_STDC_SECS; + ctl3 &= ~(SAA7191_CTL3_FSEL); + + err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc); + if (err) { + err = -EIO; + goto out; + } + err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3); + if (err) { + err = -EIO; + goto out; + } + + ctl3 |= SAA7191_CTL3_AUFD; + err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3); + if (err) { + err = -EIO; + goto out; + } + + msleep(SAA7191_SYNC_DELAY); + + err = saa7191_wait_for_signal(client, &status); + if (err) + goto out; + + if (status & SAA7191_STATUS_FIDT) { + /* 60Hz signal -> NTSC */ + dprintk("60Hz signal: NTSC\n"); + return saa7191_set_norm(client, SAA7191_NORM_NTSC); + } + + /* 50Hz signal */ + dprintk("50Hz signal: Trying PAL...\n"); + + /* try PAL first */ + err = saa7191_set_norm(client, SAA7191_NORM_PAL); + if (err) + goto out; + + msleep(SAA7191_SYNC_DELAY); + + err = saa7191_wait_for_signal(client, &status); + if (err) + goto out; + + /* not 50Hz ? */ + if (status & SAA7191_STATUS_FIDT) { + dprintk("No 50Hz signal\n"); + err = -EAGAIN; + goto out; + } + + if (status & SAA7191_STATUS_CODE) { + dprintk("PAL\n"); + return 0; + } + + dprintk("No color detected with PAL - Trying SECAM...\n"); + + /* no color detected ? -> try SECAM */ + err = saa7191_set_norm(client, + SAA7191_NORM_SECAM); + if (err) + goto out; + + msleep(SAA7191_SYNC_DELAY); + + err = saa7191_wait_for_signal(client, &status); + if (err) + goto out; + + /* not 50Hz ? */ + if (status & SAA7191_STATUS_FIDT) { + dprintk("No 50Hz signal\n"); + err = -EAGAIN; + goto out; + } + + if (status & SAA7191_STATUS_CODE) { + /* Color detected -> SECAM */ + dprintk("SECAM\n"); + return 0; + } + + dprintk("No color detected with SECAM - Going back to PAL.\n"); + + /* still no color detected ? + * -> set norm back to PAL */ + err = saa7191_set_norm(client, + SAA7191_NORM_PAL); + if (err) + goto out; + +out: + ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3); + if (ctl3 & SAA7191_CTL3_AUFD) { + ctl3 &= ~(SAA7191_CTL3_AUFD); + err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3); + if (err) { + err = -EIO; } - err = saa7191_write_reg(client, SAA7191_REG_HUEC, hue); - if (err) - return -EIO; } - if (ctrl->vtrc >= 0) { - unsigned char stdc = - saa7191_read_reg(client, SAA7191_REG_STDC); - if (ctrl->vtrc) { - stdc |= SAA7191_STDC_VTRC; - } else { - stdc &= ~SAA7191_STDC_VTRC; + return err; +} + +static int saa7191_autodetect_norm(struct i2c_client *client) +{ + u8 status; + + dprintk("SAA7191 signal auto-detection...\n"); + + dprintk("Reading status...\n"); + + if (saa7191_read_status(client, &status)) + return -EIO; + + dprintk("Checking for signal...\n"); + + /* no signal ? */ + if (status & SAA7191_STATUS_HLCK) { + dprintk("No signal\n"); + return -EBUSY; + } + + dprintk("Signal found\n"); + + if (status & SAA7191_STATUS_FIDT) { + /* 60hz signal -> NTSC */ + dprintk("NTSC\n"); + return saa7191_set_norm(client, SAA7191_NORM_NTSC); + } else { + /* 50hz signal -> PAL */ + dprintk("PAL\n"); + return saa7191_set_norm(client, SAA7191_NORM_PAL); + } +} + +static int saa7191_get_control(struct i2c_client *client, + struct saa7191_control *ctrl) +{ + u8 reg; + int ret = 0; + + switch (ctrl->type) { + case SAA7191_CONTROL_BANDPASS: + case SAA7191_CONTROL_BANDPASS_WEIGHT: + case SAA7191_CONTROL_CORING: + reg = saa7191_read_reg(client, SAA7191_REG_LUMA); + switch (ctrl->type) { + case SAA7191_CONTROL_BANDPASS: + ctrl->value = ((s32)reg & SAA7191_LUMA_BPSS_MASK) + >> SAA7191_LUMA_BPSS_SHIFT; + break; + case SAA7191_CONTROL_BANDPASS_WEIGHT: + ctrl->value = ((s32)reg & SAA7191_LUMA_APER_MASK) + >> SAA7191_LUMA_APER_SHIFT; + break; + case SAA7191_CONTROL_CORING: + ctrl->value = ((s32)reg & SAA7191_LUMA_CORI_MASK) + >> SAA7191_LUMA_CORI_SHIFT; + break; } + break; + case SAA7191_CONTROL_FORCE_COLOUR: + case SAA7191_CONTROL_CHROMA_GAIN: + reg = saa7191_read_reg(client, SAA7191_REG_GAIN); + if (ctrl->type == SAA7191_CONTROL_FORCE_COLOUR) + ctrl->value = ((s32)reg & SAA7191_GAIN_COLO) ? 1 : 0; + else + ctrl->value = ((s32)reg & SAA7191_GAIN_LFIS_MASK) + >> SAA7191_GAIN_LFIS_SHIFT; + break; + case SAA7191_CONTROL_HUE: + reg = saa7191_read_reg(client, SAA7191_REG_HUEC); + if (reg < 0x80) + reg += 0x80; + else + reg -= 0x80; + ctrl->value = (s32)reg; + break; + case SAA7191_CONTROL_VTRC: + reg = saa7191_read_reg(client, SAA7191_REG_STDC); + ctrl->value = ((s32)reg & SAA7191_STDC_VTRC) ? 1 : 0; + break; + case SAA7191_CONTROL_LUMA_DELAY: + reg = saa7191_read_reg(client, SAA7191_REG_CTL3); + ctrl->value = ((s32)reg & SAA7191_CTL3_YDEL_MASK) + >> SAA7191_CTL3_YDEL_SHIFT; + if (ctrl->value >= 4) + ctrl->value -= 8; + break; + case SAA7191_CONTROL_VNR: + reg = saa7191_read_reg(client, SAA7191_REG_CTL4); + ctrl->value = ((s32)reg & SAA7191_CTL4_VNOI_MASK) + >> SAA7191_CTL4_VNOI_SHIFT; + break; + default: + ret = -EINVAL; + } - err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc); - if (err) - return -EIO; + return ret; +} + +static int saa7191_set_control(struct i2c_client *client, + struct saa7191_control *ctrl) +{ + u8 reg; + int ret = 0; + + switch (ctrl->type) { + case SAA7191_CONTROL_BANDPASS: + case SAA7191_CONTROL_BANDPASS_WEIGHT: + case SAA7191_CONTROL_CORING: + reg = saa7191_read_reg(client, SAA7191_REG_LUMA); + switch (ctrl->type) { + case SAA7191_CONTROL_BANDPASS: + reg &= ~SAA7191_LUMA_BPSS_MASK; + reg |= (ctrl->value << SAA7191_LUMA_BPSS_SHIFT) + & SAA7191_LUMA_BPSS_MASK; + break; + case SAA7191_CONTROL_BANDPASS_WEIGHT: + reg &= ~SAA7191_LUMA_APER_MASK; + reg |= (ctrl->value << SAA7191_LUMA_APER_SHIFT) + & SAA7191_LUMA_APER_MASK; + break; + case SAA7191_CONTROL_CORING: + reg &= ~SAA7191_LUMA_CORI_MASK; + reg |= (ctrl->value << SAA7191_LUMA_CORI_SHIFT) + & SAA7191_LUMA_CORI_MASK; + break; + } + ret = saa7191_write_reg(client, SAA7191_REG_LUMA, reg); + break; + case SAA7191_CONTROL_FORCE_COLOUR: + case SAA7191_CONTROL_CHROMA_GAIN: + reg = saa7191_read_reg(client, SAA7191_REG_GAIN); + if (ctrl->type == SAA7191_CONTROL_FORCE_COLOUR) { + if (ctrl->value) + reg |= SAA7191_GAIN_COLO; + else + reg &= ~SAA7191_GAIN_COLO; + } else { + reg &= ~SAA7191_GAIN_LFIS_MASK; + reg |= (ctrl->value << SAA7191_GAIN_LFIS_SHIFT) + & SAA7191_GAIN_LFIS_MASK; + } + ret = saa7191_write_reg(client, SAA7191_REG_GAIN, reg); + break; + case SAA7191_CONTROL_HUE: + reg = ctrl->value & 0xff; + if (reg < 0x80) + reg += 0x80; + else + reg -= 0x80; + ret = saa7191_write_reg(client, SAA7191_REG_HUEC, reg); + break; + case SAA7191_CONTROL_VTRC: + reg = saa7191_read_reg(client, SAA7191_REG_STDC); + if (ctrl->value) + reg |= SAA7191_STDC_VTRC; + else + reg &= ~SAA7191_STDC_VTRC; + ret = saa7191_write_reg(client, SAA7191_REG_STDC, reg); + break; + case SAA7191_CONTROL_LUMA_DELAY: { + s32 value = ctrl->value; + if (value < 0) + value += 8; + reg = saa7191_read_reg(client, SAA7191_REG_CTL3); + reg &= ~SAA7191_CTL3_YDEL_MASK; + reg |= (value << SAA7191_CTL3_YDEL_SHIFT) + & SAA7191_CTL3_YDEL_MASK; + ret = saa7191_write_reg(client, SAA7191_REG_CTL3, reg); + break; + } + case SAA7191_CONTROL_VNR: + reg = saa7191_read_reg(client, SAA7191_REG_CTL4); + reg &= ~SAA7191_CTL4_VNOI_MASK; + reg |= (ctrl->value << SAA7191_CTL4_VNOI_SHIFT) + & SAA7191_CTL4_VNOI_MASK; + ret = saa7191_write_reg(client, SAA7191_REG_CTL4, reg); + break; + default: + ret = -EINVAL; } - return 0; + return ret; } /* I2C-interface */ @@ -309,11 +596,7 @@ static int saa7191_attach(struct i2c_adapter *adap, int addr, int kind) if (err) goto out_free_decoder; - decoder->input = SAA7191_INPUT_COMPOSITE; - decoder->norm = SAA7191_NORM_AUTO; - - err = saa7191_write_block(client, sizeof(initseq), - (unsigned char *)initseq); + err = saa7191_write_block(client, sizeof(initseq), (u8 *)initseq); if (err) { printk(KERN_ERR "SAA7191 initialization failed\n"); goto out_detach_client; @@ -321,6 +604,14 @@ static int saa7191_attach(struct i2c_adapter *adap, int addr, int kind) printk(KERN_INFO "SAA7191 initialized\n"); + decoder->input = SAA7191_INPUT_COMPOSITE; + decoder->norm = SAA7191_NORM_PAL; + + err = saa7191_autodetect_norm(client); + if (err && (err != -EBUSY)) { + printk(KERN_ERR "SAA7191: Signal auto-detection failed\n"); + } + return 0; out_detach_client: @@ -368,7 +659,7 @@ static int saa7191_command(struct i2c_client *client, unsigned int cmd, } case DECODER_GET_STATUS: { int *iarg = arg; - unsigned char status; + u8 status; int res = 0; if (saa7191_read_status(client, &status)) { @@ -404,7 +695,7 @@ static int saa7191_command(struct i2c_client *client, unsigned int cmd, switch (*iarg) { case VIDEO_MODE_AUTO: - return saa7191_set_norm(client, SAA7191_NORM_AUTO); + return saa7191_autodetect_norm(client); case VIDEO_MODE_PAL: return saa7191_set_norm(client, SAA7191_NORM_PAL); case VIDEO_MODE_NTSC: @@ -446,38 +737,48 @@ static int saa7191_command(struct i2c_client *client, unsigned int cmd, int err; val = (pic->hue >> 8) - 0x80; + err = saa7191_write_reg(client, SAA7191_REG_HUEC, val); if (err) return -EIO; + break; } case DECODER_SAA7191_GET_STATUS: { struct saa7191_status *status = arg; - unsigned char status_reg; + u8 status_reg; if (saa7191_read_status(client, &status_reg)) return -EIO; + status->signal = ((status_reg & SAA7191_STATUS_HLCK) == 0) - ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED; - status->ntsc = (status_reg & SAA7191_STATUS_FIDT) - ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED; - status->color = (status_reg & SAA7191_STATUS_CODE) - ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED; + ? 1 : 0; + status->signal_60hz = (status_reg & SAA7191_STATUS_FIDT) + ? 1 : 0; + status->color = (status_reg & SAA7191_STATUS_CODE) ? 1 : 0; status->input = decoder->input; status->norm = decoder->norm; + + break; } case DECODER_SAA7191_SET_NORM: { int *norm = arg; - return saa7191_set_norm(client, *norm); + + switch (*norm) { + case SAA7191_NORM_AUTO: + return saa7191_autodetect_norm(client); + case SAA7191_NORM_AUTO_EXT: + return saa7191_autodetect_norm_extended(client); + default: + return saa7191_set_norm(client, *norm); + } } - case DECODER_SAA7191_GET_CONTROLS: { - struct saa7191_control *ctrl = arg; - return saa7191_get_controls(client, ctrl); + case DECODER_SAA7191_GET_CONTROL: { + return saa7191_get_control(client, arg); } - case DECODER_SAA7191_SET_CONTROLS: { - struct saa7191_control *ctrl = arg; - return saa7191_set_controls(client, ctrl); + case DECODER_SAA7191_SET_CONTROL: { + return saa7191_set_control(client, arg); } default: return -EINVAL; @@ -488,12 +789,12 @@ static int saa7191_command(struct i2c_client *client, unsigned int cmd, static struct i2c_driver i2c_driver_saa7191 = { .owner = THIS_MODULE, - .name = "saa7191", - .id = I2C_DRIVERID_SAA7191, - .flags = I2C_DF_NOTIFY, + .name = "saa7191", + .id = I2C_DRIVERID_SAA7191, + .flags = I2C_DF_NOTIFY, .attach_adapter = saa7191_probe, - .detach_client = saa7191_detach, - .command = saa7191_command + .detach_client = saa7191_detach, + .command = saa7191_command }; static int saa7191_init(void) diff --git a/drivers/media/video/saa7191.h b/drivers/media/video/saa7191.h index 27204503143..a2310da1940 100644 --- a/drivers/media/video/saa7191.h +++ b/drivers/media/video/saa7191.h @@ -24,8 +24,8 @@ #define SAA7191_REG_HPHI 0x05 #define SAA7191_REG_LUMA 0x06 #define SAA7191_REG_HUEC 0x07 -#define SAA7191_REG_CKTQ 0x08 -#define SAA7191_REG_CKTS 0x09 +#define SAA7191_REG_CKTQ 0x08 /* bits 3-7 */ +#define SAA7191_REG_CKTS 0x09 /* bits 3-7 */ #define SAA7191_REG_PLSE 0x0a #define SAA7191_REG_SESE 0x0b #define SAA7191_REG_GAIN 0x0c @@ -43,30 +43,82 @@ /* Status Register definitions */ #define SAA7191_STATUS_CODE 0x01 /* color detected flag */ -#define SAA7191_STATUS_FIDT 0x20 /* format type NTSC/PAL */ -#define SAA7191_STATUS_HLCK 0x40 /* PLL unlocked/locked */ +#define SAA7191_STATUS_FIDT 0x20 /* signal type 50/60 Hz */ +#define SAA7191_STATUS_HLCK 0x40 /* PLL unlocked(1)/locked(0) */ #define SAA7191_STATUS_STTC 0x80 /* tv/vtr time constant */ /* Luminance Control Register definitions */ +/* input mode select bit: + * 0=CVBS (chrominance trap active), 1=S-Video (trap bypassed) */ #define SAA7191_LUMA_BYPS 0x80 - -/* Chroma Gain Control Settings Register definitions */ -/* 0=automatic colour-killer enabled, 1=forced colour on */ +/* pre-filter (only when chrominance trap is active) */ +#define SAA7191_LUMA_PREF 0x40 +/* aperture bandpass to select different characteristics with maximums + * (bits 4-5) */ +#define SAA7191_LUMA_BPSS_MASK 0x30 +#define SAA7191_LUMA_BPSS_SHIFT 4 +#define SAA7191_LUMA_BPSS_3 0x30 +#define SAA7191_LUMA_BPSS_2 0x20 +#define SAA7191_LUMA_BPSS_1 0x10 +#define SAA7191_LUMA_BPSS_0 0x00 +/* coring range for high frequency components according to 8-bit luminance + * (bits 2-3) + * 0=coring off, n= (+-)n LSB */ +#define SAA7191_LUMA_CORI_MASK 0x0c +#define SAA7191_LUMA_CORI_SHIFT 2 +#define SAA7191_LUMA_CORI_3 0x0c +#define SAA7191_LUMA_CORI_2 0x08 +#define SAA7191_LUMA_CORI_1 0x04 +#define SAA7191_LUMA_CORI_0 0x00 +/* aperture bandpass filter weights high frequency components of luminance + * signal (bits 0-1) + * 0=factor 0, 1=0.25, 2=0.5, 3=1 */ +#define SAA7191_LUMA_APER_MASK 0x03 +#define SAA7191_LUMA_APER_SHIFT 0 +#define SAA7191_LUMA_APER_3 0x03 +#define SAA7191_LUMA_APER_2 0x02 +#define SAA7191_LUMA_APER_1 0x01 +#define SAA7191_LUMA_APER_0 0x00 + +/* Chrominance Gain Control Settings Register definitions */ +/* colour on: 0=automatic colour-killer enabled, 1=forced colour on */ #define SAA7191_GAIN_COLO 0x80 +/* chrominance gain control (AGC filter) + * 0=loop filter time constant slow, 1=medium, 2=fast, 3=actual gain */ +#define SAA7191_GAIN_LFIS_MASK 0x60 +#define SAA7191_GAIN_LFIS_SHIFT 5 +#define SAA7191_GAIN_LFIS_3 0x60 +#define SAA7191_GAIN_LFIS_2 0x40 +#define SAA7191_GAIN_LFIS_1 0x20 +#define SAA7191_GAIN_LFIS_0 0x00 /* Standard/Mode Control Register definitions */ /* tv/vtr mode bit: 0=TV mode (slow time constant), * 1=VTR mode (fast time constant) */ #define SAA7191_STDC_VTRC 0x80 +/* SAA7191B-specific functions enable (RTCO, ODD and GPSW0 outputs) + * 0=outputs set to high-impedance (circuit equals SAA7191), 1=enabled */ +#define SAA7191_STDC_NFEN 0x08 +/* HREF generation: 0=like SAA7191, 1=HREF is 8xLLC2 clocks earlier */ +#define SAA7191_STDC_HRMV 0x04 +/* general purpose switch 0 + * (not used with VINO afaik) */ +#define SAA7191_STDC_GPSW0 0x02 /* SECAM mode bit: 0=other standards, 1=SECAM */ #define SAA7191_STDC_SECS 0x01 -/* the bit fields above must be or'd with this value */ -#define SAA7191_STDC_VALUE 0x0c /* I/O and Clock Control Register definitions */ /* horizontal clock PLL: 0=PLL closed, * 1=PLL circuit open and horizontal freq fixed */ #define SAA7191_IOCK_HPLL 0x80 +/* colour-difference output enable (outputs UV0-UV7) */ +#define SAA7191_IOCK_OEDC 0x40 +/* H-sync output enable */ +#define SAA7191_IOCK_OEHS 0x20 +/* V-sync output enable */ +#define SAA7191_IOCK_OEVS 0x10 +/* luminance output enable (outputs Y0-Y7) */ +#define SAA7191_IOCK_OEDY 0x08 /* S-VHS bit (chrominance from CVBS or from chrominance input): * 0=controlled by BYPS-bit, 1=from chrominance input */ #define SAA7191_IOCK_CHRS 0x04 @@ -83,11 +135,40 @@ /* field select: (if AUFD=0) * 0=50Hz (625 lines), 1=60Hz (525 lines) */ #define SAA7191_CTL3_FSEL 0x40 -/* the bit fields above must be or'd with this value */ -#define SAA7191_CTL3_VALUE 0x19 +/* SECAM cross-colour reduction enable */ +#define SAA7191_CTL3_SXCR 0x20 +/* sync and clamping pulse enable (HCL and HSY outputs) */ +#define SAA7191_CTL3_SCEN 0x10 +/* output format: 0=4:1:1, 1=4:2:2 (4:2:2 for VINO) */ +#define SAA7191_CTL3_OFTS 0x08 +/* luminance delay compensation + * 0=0*2/LLC, 1=+1*2/LLC, 2=+2*2/LLC, 3=+3*2/LLC, + * 4=-4*2/LLC, 5=-3*2/LLC, 6=-2*2/LLC, 7=-1*2/LLC + * step size = 2/LLC = 67.8ns for 50Hz, 81.5ns for 60Hz */ +#define SAA7191_CTL3_YDEL_MASK 0x07 +#define SAA7191_CTL3_YDEL_SHIFT 0 +#define SAA7191_CTL3_YDEL2 0x04 +#define SAA7191_CTL3_YDEL1 0x02 +#define SAA7191_CTL3_YDEL0 0x01 + +/* Miscellaneous Control #2 Register definitions */ +/* select HREF position + * 0=normal, HREF is matched to YUV output port, + * 1=HREF is matched to CVBS input port */ +#define SAA7191_CTL4_HRFS 0x04 +/* vertical noise reduction + * 0=normal, 1=searching window, 2=auto-deflection, 3=reduction bypassed */ +#define SAA7191_CTL4_VNOI_MASK 0x03 +#define SAA7191_CTL4_VNOI_SHIFT 0 +#define SAA7191_CTL4_VNOI_3 0x03 +#define SAA7191_CTL4_VNOI_2 0x02 +#define SAA7191_CTL4_VNOI_1 0x01 +#define SAA7191_CTL4_VNOI_0 0x00 /* Chrominance Gain Control Register definitions - * (nominal value for UV CCIR level) */ + * - for QAM-modulated input signals, effects output amplitude + * (SECAM gain fixed) + * (nominal values for UV CCIR level) */ #define SAA7191_CHCV_NTSC 0x2c #define SAA7191_CHCV_PAL 0x59 @@ -99,16 +180,13 @@ #define SAA7191_NORM_PAL 1 #define SAA7191_NORM_NTSC 2 #define SAA7191_NORM_SECAM 3 - -#define SAA7191_VALUE_ENABLED 1 -#define SAA7191_VALUE_DISABLED 0 -#define SAA7191_VALUE_UNCHANGED -1 +#define SAA7191_NORM_AUTO_EXT 4 /* extended auto-detection */ struct saa7191_status { - /* 0=no signal, 1=signal active*/ + /* 0=no signal, 1=signal detected */ int signal; /* 0=50hz (pal) signal, 1=60hz (ntsc) signal */ - int ntsc; + int signal_60hz; /* 0=no color detected, 1=color detected */ int color; @@ -118,22 +196,60 @@ struct saa7191_status { int norm; }; -#define SAA7191_HUE_MIN 0x00 -#define SAA7191_HUE_MAX 0xff -#define SAA7191_HUE_DEFAULT 0x80 +#define SAA7191_BANDPASS_MIN 0x00 +#define SAA7191_BANDPASS_MAX 0x03 +#define SAA7191_BANDPASS_DEFAULT 0x00 + +#define SAA7191_BANDPASS_WEIGHT_MIN 0x00 +#define SAA7191_BANDPASS_WEIGHT_MAX 0x03 +#define SAA7191_BANDPASS_WEIGHT_DEFAULT 0x01 + +#define SAA7191_CORING_MIN 0x00 +#define SAA7191_CORING_MAX 0x03 +#define SAA7191_CORING_DEFAULT 0x00 + +#define SAA7191_HUE_MIN 0x00 +#define SAA7191_HUE_MAX 0xff +#define SAA7191_HUE_DEFAULT 0x80 + +#define SAA7191_VTRC_MIN 0x00 +#define SAA7191_VTRC_MAX 0x01 +#define SAA7191_VTRC_DEFAULT 0x00 + +#define SAA7191_FORCE_COLOUR_MIN 0x00 +#define SAA7191_FORCE_COLOUR_MAX 0x01 +#define SAA7191_FORCE_COLOUR_DEFAULT 0x00 + +#define SAA7191_CHROMA_GAIN_MIN 0x00 +#define SAA7191_CHROMA_GAIN_MAX 0x03 +#define SAA7191_CHROMA_GAIN_DEFAULT 0x00 + +#define SAA7191_LUMA_DELAY_MIN -0x04 +#define SAA7191_LUMA_DELAY_MAX 0x03 +#define SAA7191_LUMA_DELAY_DEFAULT 0x01 + +#define SAA7191_VNR_MIN 0x00 +#define SAA7191_VNR_MAX 0x03 +#define SAA7191_VNR_DEFAULT 0x00 -#define SAA7191_VTRC_MIN 0x00 -#define SAA7191_VTRC_MAX 0x01 -#define SAA7191_VTRC_DEFAULT 0x00 +#define SAA7191_CONTROL_BANDPASS 0 +#define SAA7191_CONTROL_BANDPASS_WEIGHT 1 +#define SAA7191_CONTROL_CORING 2 +#define SAA7191_CONTROL_FORCE_COLOUR 3 /* boolean */ +#define SAA7191_CONTROL_CHROMA_GAIN 4 +#define SAA7191_CONTROL_HUE 5 +#define SAA7191_CONTROL_VTRC 6 /* boolean */ +#define SAA7191_CONTROL_LUMA_DELAY 7 +#define SAA7191_CONTROL_VNR 8 struct saa7191_control { - int hue; - int vtrc; + u8 type; + s32 value; }; #define DECODER_SAA7191_GET_STATUS _IOR('d', 195, struct saa7191_status) #define DECODER_SAA7191_SET_NORM _IOW('d', 196, int) -#define DECODER_SAA7191_GET_CONTROLS _IOR('d', 197, struct saa7191_control) -#define DECODER_SAA7191_SET_CONTROLS _IOW('d', 198, struct saa7191_control) +#define DECODER_SAA7191_GET_CONTROL _IOR('d', 197, struct saa7191_control) +#define DECODER_SAA7191_SET_CONTROL _IOW('d', 198, struct saa7191_control) #endif diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index ed4394e854a..71b28e9e085 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -12,15 +12,11 @@ /* * TODO: - * - remove "hacks" from memory allocation code and implement nopage() + * - remove "mark pages reserved-hacks" from memory allocation code + * and implement nopage() * - check decimation, calculating and reporting image size when * using decimation - * - check vino_acquire_input(), vino_set_input() and channel - * ownership handling - * - report VINO error-interrupts via ioctls ? - * - implement picture controls (all implemented?) - * - use macros for boolean values (?) - * - implement user mode buffers and overlay (?) + * - implement read(), user mode buffers and overlay (?) */ #include @@ -60,18 +56,16 @@ * debug info. * Note that the debug output also slows down the driver significantly */ // #define VINO_DEBUG +// #define VINO_DEBUG_INT -#define VINO_MODULE_VERSION "0.0.3" -#define VINO_VERSION_CODE KERNEL_VERSION(0, 0, 3) +#define VINO_MODULE_VERSION "0.0.5" +#define VINO_VERSION_CODE KERNEL_VERSION(0, 0, 5) MODULE_DESCRIPTION("SGI VINO Video4Linux2 driver"); MODULE_VERSION(VINO_MODULE_VERSION); MODULE_AUTHOR("Mikael Nousiainen "); MODULE_LICENSE("GPL"); -#define mem_map_reserve(p) set_bit(PG_reserved, &((p)->flags)) -#define mem_map_unreserve(p) clear_bit(PG_reserved, &((p)->flags)) - #ifdef VINO_DEBUG #define dprintk(x...) printk("VINO: " x); #else @@ -91,15 +85,16 @@ MODULE_LICENSE("GPL"); #define VINO_MIN_HEIGHT 32 #define VINO_CLIPPING_START_ODD_D1 1 -#define VINO_CLIPPING_START_ODD_PAL 1 -#define VINO_CLIPPING_START_ODD_NTSC 1 +#define VINO_CLIPPING_START_ODD_PAL 15 +#define VINO_CLIPPING_START_ODD_NTSC 12 #define VINO_CLIPPING_START_EVEN_D1 2 -#define VINO_CLIPPING_START_EVEN_PAL 2 -#define VINO_CLIPPING_START_EVEN_NTSC 2 +#define VINO_CLIPPING_START_EVEN_PAL 15 +#define VINO_CLIPPING_START_EVEN_NTSC 12 #define VINO_INPUT_CHANNEL_COUNT 3 +/* the number is the index for vino_inputs */ #define VINO_INPUT_NONE -1 #define VINO_INPUT_COMPOSITE 0 #define VINO_INPUT_SVIDEO 1 @@ -107,15 +102,13 @@ MODULE_LICENSE("GPL"); #define VINO_PAGE_RATIO (PAGE_SIZE / VINO_PAGE_SIZE) -#define VINO_FIFO_THRESHOLD_DEFAULT 512 +#define VINO_FIFO_THRESHOLD_DEFAULT 16 -/*#define VINO_FRAMEBUFFER_SIZE (VINO_PAL_WIDTH * VINO_PAL_HEIGHT * 4 \ - + 2 * PAGE_SIZE)*/ #define VINO_FRAMEBUFFER_SIZE ((VINO_PAL_WIDTH \ * VINO_PAL_HEIGHT * 4 \ + 3 * PAGE_SIZE) & ~(PAGE_SIZE - 1)) -#define VINO_FRAMEBUFFER_MAX_COUNT 8 +#define VINO_FRAMEBUFFER_COUNT_MAX 8 #define VINO_FRAMEBUFFER_UNUSED 0 #define VINO_FRAMEBUFFER_IN_USE 1 @@ -131,24 +124,27 @@ MODULE_LICENSE("GPL"); #define VINO_DUMMY_DESC_COUNT 4 #define VINO_DESC_FETCH_DELAY 5 /* microseconds */ +#define VINO_MAX_FRAME_SKIP_COUNT 128 + /* the number is the index for vino_data_formats */ #define VINO_DATA_FMT_NONE -1 #define VINO_DATA_FMT_GREY 0 #define VINO_DATA_FMT_RGB332 1 #define VINO_DATA_FMT_RGB32 2 #define VINO_DATA_FMT_YUV 3 -//#define VINO_DATA_FMT_RGB24 4 #define VINO_DATA_FMT_COUNT 4 +/* the number is the index for vino_data_norms */ #define VINO_DATA_NORM_NONE -1 #define VINO_DATA_NORM_NTSC 0 #define VINO_DATA_NORM_PAL 1 #define VINO_DATA_NORM_SECAM 2 #define VINO_DATA_NORM_D1 3 -/* The following is a special entry that can be used to +/* The following are special entries that can be used to * autodetect the norm. */ -#define VINO_DATA_NORM_AUTO 0xff +#define VINO_DATA_NORM_AUTO 0xfe +#define VINO_DATA_NORM_AUTO_EXT 0xff #define VINO_DATA_NORM_COUNT 4 @@ -232,7 +228,7 @@ struct vino_framebuffer_fifo { unsigned int head; unsigned int tail; - unsigned int data[VINO_FRAMEBUFFER_MAX_COUNT]; + unsigned int data[VINO_FRAMEBUFFER_COUNT_MAX]; }; struct vino_framebuffer_queue { @@ -246,13 +242,20 @@ struct vino_framebuffer_queue { struct vino_framebuffer_fifo in; struct vino_framebuffer_fifo out; - struct vino_framebuffer *buffer[VINO_FRAMEBUFFER_MAX_COUNT]; + struct vino_framebuffer *buffer[VINO_FRAMEBUFFER_COUNT_MAX]; spinlock_t queue_lock; struct semaphore queue_sem; wait_queue_head_t frame_wait_queue; }; +struct vino_interrupt_data { + struct timeval timestamp; + unsigned int frame_counter; + unsigned int skip_count; + unsigned int skip; +}; + struct vino_channel_settings { unsigned int channel; @@ -285,6 +288,8 @@ struct vino_channel_settings { unsigned int users; + struct vino_interrupt_data int_data; + /* V4L support */ struct video_device *v4l_device; }; @@ -315,7 +320,7 @@ struct vino_settings { /* Module parameters */ /* - * Using vino_pixel_conversion the ARGB32-format pixels supplied + * Using vino_pixel_conversion the ABGR32-format pixels supplied * by the VINO chip can be converted to more common formats * like RGBA32 (or probably RGB24 in the future). This way we * can give out data that can be specified correctly with @@ -329,7 +334,9 @@ struct vino_settings { * Use non-zero value to enable conversion. */ static int vino_pixel_conversion = 0; + module_param_named(pixelconv, vino_pixel_conversion, int, 0); + MODULE_PARM_DESC(pixelconv, "enable pixel conversion (non-zero value enables)"); @@ -345,15 +352,22 @@ static const char *vino_bus_name = "GIO64 bus"; static const char *vino_v4l_device_name_a = "SGI VINO Channel A"; static const char *vino_v4l_device_name_b = "SGI VINO Channel B"; +static void vino_capture_tasklet(unsigned long channel); + +DECLARE_TASKLET(vino_tasklet_a, vino_capture_tasklet, VINO_CHANNEL_A); +DECLARE_TASKLET(vino_tasklet_b, vino_capture_tasklet, VINO_CHANNEL_B); + static const struct vino_input vino_inputs[] = { { .name = "Composite", - .std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, + .std = V4L2_STD_NTSC | V4L2_STD_PAL + | V4L2_STD_SECAM, },{ .name = "S-Video", - .std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, + .std = V4L2_STD_NTSC | V4L2_STD_PAL + | V4L2_STD_SECAM, },{ - .name = "D1 (IndyCam)", + .name = "D1/IndyCam", .std = V4L2_STD_NTSC, } }; @@ -376,15 +390,10 @@ static const struct vino_data_format vino_data_formats[] = { .colorspace = V4L2_COLORSPACE_SRGB, },{ .description = "YUV 4:2:2", - .bpp = 4, + .bpp = 2, .pixelformat = V4L2_PIX_FMT_YUYV, // XXX: swapped? .colorspace = V4L2_COLORSPACE_SMPTE170M, - }/*,{ - .description = "24-bit RGB", - .bpp = 3, - .pixelformat = V4L2_PIX_FMT_RGB24, - .colorspace = V4L2_COLORSPACE_SRGB, - }*/ + } }; static const struct vino_data_norm vino_data_norms[] = { @@ -397,18 +406,18 @@ static const struct vino_data_norm vino_data_norms[] = { .width = VINO_NTSC_WIDTH, .height = VINO_NTSC_HEIGHT, .odd = { - .top = VINO_CLIPPING_START_ODD_NTSC, - .left = 0, + .top = VINO_CLIPPING_START_ODD_NTSC, + .left = 0, .bottom = VINO_CLIPPING_START_ODD_NTSC + VINO_NTSC_HEIGHT / 2 - 1, - .right = VINO_NTSC_WIDTH, + .right = VINO_NTSC_WIDTH, }, .even = { - .top = VINO_CLIPPING_START_EVEN_NTSC, - .left = 0, + .top = VINO_CLIPPING_START_EVEN_NTSC, + .left = 0, .bottom = VINO_CLIPPING_START_EVEN_NTSC + VINO_NTSC_HEIGHT / 2 - 1, - .right = VINO_NTSC_WIDTH, + .right = VINO_NTSC_WIDTH, }, },{ .description = "PAL", @@ -419,18 +428,18 @@ static const struct vino_data_norm vino_data_norms[] = { .width = VINO_PAL_WIDTH, .height = VINO_PAL_HEIGHT, .odd = { - .top = VINO_CLIPPING_START_ODD_PAL, - .left = 0, + .top = VINO_CLIPPING_START_ODD_PAL, + .left = 0, .bottom = VINO_CLIPPING_START_ODD_PAL + VINO_PAL_HEIGHT / 2 - 1, - .right = VINO_PAL_WIDTH, + .right = VINO_PAL_WIDTH, }, .even = { - .top = VINO_CLIPPING_START_EVEN_PAL, - .left = 0, + .top = VINO_CLIPPING_START_EVEN_PAL, + .left = 0, .bottom = VINO_CLIPPING_START_EVEN_PAL + VINO_PAL_HEIGHT / 2 - 1, - .right = VINO_PAL_WIDTH, + .right = VINO_PAL_WIDTH, }, },{ .description = "SECAM", @@ -441,21 +450,21 @@ static const struct vino_data_norm vino_data_norms[] = { .width = VINO_PAL_WIDTH, .height = VINO_PAL_HEIGHT, .odd = { - .top = VINO_CLIPPING_START_ODD_PAL, - .left = 0, + .top = VINO_CLIPPING_START_ODD_PAL, + .left = 0, .bottom = VINO_CLIPPING_START_ODD_PAL + VINO_PAL_HEIGHT / 2 - 1, - .right = VINO_PAL_WIDTH, + .right = VINO_PAL_WIDTH, }, .even = { - .top = VINO_CLIPPING_START_EVEN_PAL, - .left = 0, + .top = VINO_CLIPPING_START_EVEN_PAL, + .left = 0, .bottom = VINO_CLIPPING_START_EVEN_PAL + VINO_PAL_HEIGHT / 2 - 1, - .right = VINO_PAL_WIDTH, + .right = VINO_PAL_WIDTH, }, },{ - .description = "NTSC (D1 input)", + .description = "NTSC/D1", .std = V4L2_STD_NTSC, .fps_min = 6, .fps_max = 30, @@ -463,18 +472,18 @@ static const struct vino_data_norm vino_data_norms[] = { .width = VINO_NTSC_WIDTH, .height = VINO_NTSC_HEIGHT, .odd = { - .top = VINO_CLIPPING_START_ODD_D1, - .left = 0, + .top = VINO_CLIPPING_START_ODD_D1, + .left = 0, .bottom = VINO_CLIPPING_START_ODD_D1 + VINO_NTSC_HEIGHT / 2 - 1, - .right = VINO_NTSC_WIDTH, + .right = VINO_NTSC_WIDTH, }, .even = { - .top = VINO_CLIPPING_START_EVEN_D1, - .left = 0, + .top = VINO_CLIPPING_START_EVEN_D1, + .left = 0, .bottom = VINO_CLIPPING_START_EVEN_D1 + VINO_NTSC_HEIGHT / 2 - 1, - .right = VINO_NTSC_WIDTH, + .right = VINO_NTSC_WIDTH, }, } }; @@ -491,7 +500,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .step = 1, .default_value = INDYCAM_AGC_DEFAULT, .flags = 0, - .reserved = { 0, 0 }, + .reserved = { INDYCAM_CONTROL_AGC, 0 }, },{ .id = V4L2_CID_AUTO_WHITE_BALANCE, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -501,7 +510,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .step = 1, .default_value = INDYCAM_AWB_DEFAULT, .flags = 0, - .reserved = { 0, 0 }, + .reserved = { INDYCAM_CONTROL_AWB, 0 }, },{ .id = V4L2_CID_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, @@ -511,7 +520,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .step = 1, .default_value = INDYCAM_GAIN_DEFAULT, .flags = 0, - .reserved = { 0, 0 }, + .reserved = { INDYCAM_CONTROL_GAIN, 0 }, },{ .id = V4L2_CID_PRIVATE_BASE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -521,7 +530,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .step = 1, .default_value = INDYCAM_RED_SATURATION_DEFAULT, .flags = 0, - .reserved = { 0, 0 }, + .reserved = { INDYCAM_CONTROL_RED_SATURATION, 0 }, },{ .id = V4L2_CID_PRIVATE_BASE + 1, .type = V4L2_CTRL_TYPE_INTEGER, @@ -531,7 +540,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .step = 1, .default_value = INDYCAM_BLUE_SATURATION_DEFAULT, .flags = 0, - .reserved = { 0, 0 }, + .reserved = { INDYCAM_CONTROL_BLUE_SATURATION, 0 }, },{ .id = V4L2_CID_RED_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -541,7 +550,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .step = 1, .default_value = INDYCAM_RED_BALANCE_DEFAULT, .flags = 0, - .reserved = { 0, 0 }, + .reserved = { INDYCAM_CONTROL_RED_BALANCE, 0 }, },{ .id = V4L2_CID_BLUE_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -551,7 +560,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .step = 1, .default_value = INDYCAM_BLUE_BALANCE_DEFAULT, .flags = 0, - .reserved = { 0, 0 }, + .reserved = { INDYCAM_CONTROL_BLUE_BALANCE, 0 }, },{ .id = V4L2_CID_EXPOSURE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -561,7 +570,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .step = 1, .default_value = INDYCAM_SHUTTER_DEFAULT, .flags = 0, - .reserved = { 0, 0 }, + .reserved = { INDYCAM_CONTROL_SHUTTER, 0 }, },{ .id = V4L2_CID_GAMMA, .type = V4L2_CTRL_TYPE_INTEGER, @@ -571,11 +580,11 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .step = 1, .default_value = INDYCAM_GAMMA_DEFAULT, .flags = 0, - .reserved = { 0, 0 }, + .reserved = { INDYCAM_CONTROL_GAMMA, 0 }, } }; -#define VINO_SAA7191_V4L2_CONTROL_COUNT 2 +#define VINO_SAA7191_V4L2_CONTROL_COUNT 9 struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = { { @@ -587,9 +596,59 @@ struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = { .step = 1, .default_value = SAA7191_HUE_DEFAULT, .flags = 0, - .reserved = { 0, 0 }, + .reserved = { SAA7191_CONTROL_HUE, 0 }, },{ .id = V4L2_CID_PRIVATE_BASE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Luminance Bandpass", + .minimum = SAA7191_BANDPASS_MIN, + .maximum = SAA7191_BANDPASS_MAX, + .step = 1, + .default_value = SAA7191_BANDPASS_DEFAULT, + .flags = 0, + .reserved = { SAA7191_CONTROL_BANDPASS, 0 }, + },{ + .id = V4L2_CID_PRIVATE_BASE + 1, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Luminance Bandpass Weight", + .minimum = SAA7191_BANDPASS_WEIGHT_MIN, + .maximum = SAA7191_BANDPASS_WEIGHT_MAX, + .step = 1, + .default_value = SAA7191_BANDPASS_WEIGHT_DEFAULT, + .flags = 0, + .reserved = { SAA7191_CONTROL_BANDPASS_WEIGHT, 0 }, + },{ + .id = V4L2_CID_PRIVATE_BASE + 2, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "HF Luminance Coring", + .minimum = SAA7191_CORING_MIN, + .maximum = SAA7191_CORING_MAX, + .step = 1, + .default_value = SAA7191_CORING_DEFAULT, + .flags = 0, + .reserved = { SAA7191_CONTROL_CORING, 0 }, + },{ + .id = V4L2_CID_PRIVATE_BASE + 3, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Force Colour", + .minimum = SAA7191_FORCE_COLOUR_MIN, + .maximum = SAA7191_FORCE_COLOUR_MAX, + .step = 1, + .default_value = SAA7191_FORCE_COLOUR_DEFAULT, + .flags = 0, + .reserved = { SAA7191_CONTROL_FORCE_COLOUR, 0 }, + },{ + .id = V4L2_CID_PRIVATE_BASE + 4, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Chrominance Gain Control", + .minimum = SAA7191_CHROMA_GAIN_MIN, + .maximum = SAA7191_CHROMA_GAIN_MAX, + .step = 1, + .default_value = SAA7191_CHROMA_GAIN_DEFAULT, + .flags = 0, + .reserved = { SAA7191_CONTROL_CHROMA_GAIN, 0 }, + },{ + .id = V4L2_CID_PRIVATE_BASE + 5, .type = V4L2_CTRL_TYPE_BOOLEAN, .name = "VTR Time Constant", .minimum = SAA7191_VTRC_MIN, @@ -597,7 +656,27 @@ struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = { .step = 1, .default_value = SAA7191_VTRC_DEFAULT, .flags = 0, - .reserved = { 0, 0 }, + .reserved = { SAA7191_CONTROL_VTRC, 0 }, + },{ + .id = V4L2_CID_PRIVATE_BASE + 6, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Luminance Delay Compensation", + .minimum = SAA7191_LUMA_DELAY_MIN, + .maximum = SAA7191_LUMA_DELAY_MAX, + .step = 1, + .default_value = SAA7191_LUMA_DELAY_DEFAULT, + .flags = 0, + .reserved = { SAA7191_CONTROL_LUMA_DELAY, 0 }, + },{ + .id = V4L2_CID_PRIVATE_BASE + 7, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Vertical Noise Reduction", + .minimum = SAA7191_VNR_MIN, + .maximum = SAA7191_VNR_MAX, + .step = 1, + .default_value = SAA7191_VNR_DEFAULT, + .flags = 0, + .reserved = { SAA7191_CONTROL_VNR, 0 }, } }; @@ -639,9 +718,10 @@ static struct i2c_algo_sgi_data i2c_sgi_vino_data = */ static int i2c_vino_client_reg(struct i2c_client *client) { + unsigned long flags; int ret = 0; - spin_lock(&vino_drvdata->input_lock); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); switch (client->driver->id) { case I2C_DRIVERID_SAA7191: if (vino_drvdata->decoder.driver) @@ -658,16 +738,17 @@ static int i2c_vino_client_reg(struct i2c_client *client) default: ret = -ENODEV; } - spin_unlock(&vino_drvdata->input_lock); + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); return ret; } static int i2c_vino_client_unreg(struct i2c_client *client) { + unsigned long flags; int ret = 0; - spin_lock(&vino_drvdata->input_lock); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); if (client == vino_drvdata->decoder.driver) { if (vino_drvdata->decoder.owner != VINO_NO_CHANNEL) ret = -EBUSY; @@ -679,7 +760,7 @@ static int i2c_vino_client_unreg(struct i2c_client *client) else vino_drvdata->camera.driver = NULL; } - spin_unlock(&vino_drvdata->input_lock); + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); return ret; } @@ -727,7 +808,7 @@ static void vino_free_buffer_with_count(struct vino_framebuffer *fb, dprintk("vino_free_buffer_with_count(): count = %d\n", count); for (i = 0; i < count; i++) { - mem_map_unreserve(virt_to_page(fb->desc_table.virtual[i])); + ClearPageReserved(virt_to_page(fb->desc_table.virtual[i])); dma_unmap_single(NULL, fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i], PAGE_SIZE, DMA_FROM_DEVICE); @@ -805,7 +886,7 @@ static int vino_allocate_buffer(struct vino_framebuffer *fb, dma_data_addr + VINO_PAGE_SIZE * j; } - mem_map_reserve(virt_to_page(fb->desc_table.virtual[i])); + SetPageReserved(virt_to_page(fb->desc_table.virtual[i])); } /* page_count needs to be set anyway, because the descriptor table has @@ -892,7 +973,7 @@ static int vino_prepare_user_buffer(struct vino_framebuffer *fb, dma_data_addr + VINO_PAGE_SIZE * j; } - mem_map_reserve(virt_to_page(fb->desc_table.virtual[i])); + SetPageReserved(virt_to_page(fb->desc_table.virtual[i])); } /* page_count needs to be set anyway, because the descriptor table has @@ -933,7 +1014,7 @@ static void vino_sync_buffer(struct vino_framebuffer *fb) /* Framebuffer fifo functions (need to be locked externally) */ -static void vino_fifo_init(struct vino_framebuffer_fifo *f, +static inline void vino_fifo_init(struct vino_framebuffer_fifo *f, unsigned int length) { f->length = 0; @@ -941,16 +1022,18 @@ static void vino_fifo_init(struct vino_framebuffer_fifo *f, f->head = 0; f->tail = 0; - if (length > VINO_FRAMEBUFFER_MAX_COUNT) - length = VINO_FRAMEBUFFER_MAX_COUNT; + if (length > VINO_FRAMEBUFFER_COUNT_MAX) + length = VINO_FRAMEBUFFER_COUNT_MAX; f->length = length; } /* returns true/false */ -static int vino_fifo_has_id(struct vino_framebuffer_fifo *f, unsigned int id) +static inline int vino_fifo_has_id(struct vino_framebuffer_fifo *f, + unsigned int id) { unsigned int i; + for (i = f->head; i == (f->tail - 1); i = (i + 1) % f->length) { if (f->data[i] == id) return 1; @@ -959,13 +1042,15 @@ static int vino_fifo_has_id(struct vino_framebuffer_fifo *f, unsigned int id) return 0; } +#if 0 /* returns true/false */ -static int vino_fifo_full(struct vino_framebuffer_fifo *f) +static inline int vino_fifo_full(struct vino_framebuffer_fifo *f) { return (f->used == f->length); } +#endif -static unsigned int vino_fifo_get_used(struct vino_framebuffer_fifo *f) +static inline unsigned int vino_fifo_get_used(struct vino_framebuffer_fifo *f) { return f->used; } @@ -1076,8 +1161,8 @@ static int vino_queue_init(struct vino_framebuffer_queue *q, down(&q->queue_sem); - if (*length > VINO_FRAMEBUFFER_MAX_COUNT) - *length = VINO_FRAMEBUFFER_MAX_COUNT; + if (*length > VINO_FRAMEBUFFER_COUNT_MAX) + *length = VINO_FRAMEBUFFER_COUNT_MAX; q->length = 0; @@ -1313,6 +1398,7 @@ out: return ret; } +#if 0 static int vino_queue_get_total(struct vino_framebuffer_queue *q, unsigned int *total) { @@ -1338,6 +1424,7 @@ out: return ret; } +#endif static struct vino_framebuffer *vino_queue_peek(struct vino_framebuffer_queue *q, @@ -1471,12 +1558,14 @@ static void vino_update_line_size(struct vino_channel_settings *vcs) dprintk("update_line_size(): before: w = %d, d = %d, " "line_size = %d\n", w, d, vcs->line_size); + /* line size must be multiple of 8 bytes */ lsize = (bpp * (w / d)) & ~7; w = (lsize / bpp) * d; vcs->clipping.right = vcs->clipping.left + w; vcs->line_size = lsize; + dprintk("update_line_size(): after: w = %d, d = %d, " "line_size = %d\n", w, d, vcs->line_size); } @@ -1532,7 +1621,7 @@ static void vino_set_clipping(struct vino_channel_settings *vcs, } /* execute with input_lock locked */ -static void vino_set_default_clipping(struct vino_channel_settings *vcs) +static inline void vino_set_default_clipping(struct vino_channel_settings *vcs) { vino_set_clipping(vcs, 0, 0, vino_data_norms[vcs->data_norm].width, vino_data_norms[vcs->data_norm].height); @@ -1556,8 +1645,7 @@ static void vino_set_scaling(struct vino_channel_settings *vcs, if (d < 1) { d = 1; - } - if (d > 8) { + } else if (d > 8) { d = 8; } @@ -1570,7 +1658,7 @@ static void vino_set_scaling(struct vino_channel_settings *vcs, } /* execute with input_lock locked */ -static void vino_reset_scaling(struct vino_channel_settings *vcs) +static inline void vino_set_default_scaling(struct vino_channel_settings *vcs) { vino_set_scaling(vcs, vcs->clipping.right - vcs->clipping.left, vcs->clipping.bottom - vcs->clipping.top); @@ -1649,7 +1737,8 @@ static void vino_set_framerate(struct vino_channel_settings *vcs, } /* execute with input_lock locked */ -static void vino_set_default_framerate(struct vino_channel_settings *vcs) +static inline void vino_set_default_framerate(struct + vino_channel_settings *vcs) { vino_set_framerate(vcs, vino_data_norms[vcs->data_norm].fps_max); } @@ -1687,6 +1776,9 @@ static int vino_dma_setup(struct vino_channel_settings *vcs, * should be more than enough time */ udelay(VINO_DESC_FETCH_DELAY); + dprintk("vino_dma_setup(): start desc = %08x, next 4 desc = %08x\n", + ch->start_desc_tbl, ch->next_4_desc); + /* set the alpha register */ ch->alpha = vcs->alpha; @@ -1700,9 +1792,6 @@ static int vino_dma_setup(struct vino_channel_settings *vcs, VINO_CLIP_EVEN(norm->even.top + vcs->clipping.bottom / 2 - 1) | VINO_CLIP_X(vcs->clipping.right); - /* FIXME: end-of-field bug workaround - VINO_CLIP_X(VINO_PAL_WIDTH); - */ /* set the size of actual content in the buffer (DECIMATION !) */ fb->data_size = ((vcs->clipping.right - vcs->clipping.left) / @@ -1802,7 +1891,7 @@ static int vino_dma_setup(struct vino_channel_settings *vcs, } /* (execute only with vino_lock locked) */ -static void vino_dma_start(struct vino_channel_settings *vcs) +static inline void vino_dma_start(struct vino_channel_settings *vcs) { u32 ctrl = vino->control; @@ -1813,12 +1902,14 @@ static void vino_dma_start(struct vino_channel_settings *vcs) } /* (execute only with vino_lock locked) */ -static void vino_dma_stop(struct vino_channel_settings *vcs) +static inline void vino_dma_stop(struct vino_channel_settings *vcs) { u32 ctrl = vino->control; ctrl &= (vcs->channel == VINO_CHANNEL_A) ? ~VINO_CTRL_A_DMA_ENBL : ~VINO_CTRL_B_DMA_ENBL; + ctrl &= (vcs->channel == VINO_CHANNEL_A) ? + ~VINO_CTRL_A_INT : ~VINO_CTRL_B_INT; vino->control = ctrl; dprintk("vino_dma_stop():\n"); } @@ -1902,7 +1993,7 @@ static int vino_capture_next(struct vino_channel_settings *vcs, int start) struct vino_framebuffer *fb; unsigned int incoming, id; int err = 0; - unsigned long flags, flags2; + unsigned long flags; dprintk("vino_capture_next():\n"); @@ -1943,10 +2034,6 @@ static int vino_capture_next(struct vino_channel_settings *vcs, int start) goto out; } - spin_lock_irqsave(&fb->state_lock, flags2); - fb->state = VINO_FRAMEBUFFER_UNUSED; - spin_unlock_irqrestore(&fb->state_lock, flags2); - if (start) { vcs->capturing = 1; } @@ -1964,7 +2051,7 @@ out: return err; } -static int vino_is_capturing(struct vino_channel_settings *vcs) +static inline int vino_is_capturing(struct vino_channel_settings *vcs) { int ret; unsigned long flags; @@ -2076,6 +2163,7 @@ static void vino_capture_stop(struct vino_channel_settings *vcs) dprintk("vino_capture_stop():\n"); spin_lock_irqsave(&vcs->capture_lock, flags); + /* unset capturing to stop queue processing */ vcs->capturing = 0; @@ -2121,6 +2209,7 @@ out: spin_unlock_irqrestore(&vcs->capture_lock, flags); } +#if 0 static int vino_capture_failed(struct vino_channel_settings *vcs) { struct vino_framebuffer *fb; @@ -2165,9 +2254,31 @@ static int vino_capture_failed(struct vino_channel_settings *vcs) return 0; } +#endif + +static void vino_skip_frame(struct vino_channel_settings *vcs) +{ + struct vino_framebuffer *fb; + unsigned long flags; + unsigned int id; + + spin_lock_irqsave(&vcs->capture_lock, flags); + fb = vino_queue_peek(&vcs->fb_queue, &id); + if (!fb) { + spin_unlock_irqrestore(&vcs->capture_lock, flags); + dprintk("vino_skip_frame(): vino_queue_peek() failed!\n"); + return; + } + spin_unlock_irqrestore(&vcs->capture_lock, flags); + + spin_lock_irqsave(&fb->state_lock, flags); + fb->state = VINO_FRAMEBUFFER_UNUSED; + spin_unlock_irqrestore(&fb->state_lock, flags); + + vino_capture_next(vcs, 0); +} -static void vino_frame_done(struct vino_channel_settings *vcs, - unsigned int fc) +static void vino_frame_done(struct vino_channel_settings *vcs) { struct vino_framebuffer *fb; unsigned long flags; @@ -2181,8 +2292,9 @@ static void vino_frame_done(struct vino_channel_settings *vcs, } spin_unlock_irqrestore(&vcs->capture_lock, flags); - fb->frame_counter = fc; - do_gettimeofday(&fb->timestamp); + fb->frame_counter = vcs->int_data.frame_counter; + memcpy(&fb->timestamp, &vcs->int_data.timestamp, + sizeof(struct timeval)); spin_lock_irqsave(&fb->state_lock, flags); if (fb->state == VINO_FRAMEBUFFER_IN_USE) @@ -2194,72 +2306,175 @@ static void vino_frame_done(struct vino_channel_settings *vcs, vino_capture_next(vcs, 0); } +static void vino_capture_tasklet(unsigned long channel) { + struct vino_channel_settings *vcs; + + vcs = (channel == VINO_CHANNEL_A) + ? &vino_drvdata->a : &vino_drvdata->b; + + if (vcs->int_data.skip) + vcs->int_data.skip_count++; + + if (vcs->int_data.skip && (vcs->int_data.skip_count + <= VINO_MAX_FRAME_SKIP_COUNT)) { + vino_skip_frame(vcs); + } else { + vcs->int_data.skip_count = 0; + vino_frame_done(vcs); + } +} + static irqreturn_t vino_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - u32 intr; + u32 ctrl, intr; unsigned int fc_a, fc_b; - int done_a = 0; - int done_b = 0; + int handled_a = 0, skip_a = 0, done_a = 0; + int handled_b = 0, skip_b = 0, done_b = 0; + +#ifdef VINO_DEBUG_INT + int loop = 0; + unsigned int line_count = vino->a.line_count, + page_index = vino->a.page_index, + field_counter = vino->a.field_counter, + start_desc_tbl = vino->a.start_desc_tbl, + next_4_desc = vino->a.next_4_desc; + unsigned int line_count_2, + page_index_2, + field_counter_2, + start_desc_tbl_2, + next_4_desc_2; +#endif spin_lock(&vino_drvdata->vino_lock); - intr = vino->intr_status; - fc_a = vino->a.field_counter / 2; - fc_b = vino->b.field_counter / 2; - - // TODO: handle error-interrupts in some special way ? - - if (intr & VINO_INTSTAT_A) { - if (intr & VINO_INTSTAT_A_EOF) { - vino_drvdata->a.field++; - if (vino_drvdata->a.field > 1) { + while ((intr = vino->intr_status)) { + fc_a = vino->a.field_counter >> 1; + fc_b = vino->b.field_counter >> 1; + + /* handle error-interrupts in some special way ? + * --> skips frames */ + if (intr & VINO_INTSTAT_A) { + if (intr & VINO_INTSTAT_A_EOF) { + vino_drvdata->a.field++; + if (vino_drvdata->a.field > 1) { + vino_dma_stop(&vino_drvdata->a); + vino_clear_interrupt(&vino_drvdata->a); + vino_drvdata->a.field = 0; + done_a = 1; + } else { + if (vino->a.page_index + != vino_drvdata->a.line_size) { + vino->a.line_count = 0; + vino->a.page_index = + vino_drvdata-> + a.line_size; + vino->a.next_4_desc = + vino->a.start_desc_tbl; + } + } + dprintk("channel A end-of-field " + "interrupt: %04x\n", intr); + } else { vino_dma_stop(&vino_drvdata->a); vino_clear_interrupt(&vino_drvdata->a); vino_drvdata->a.field = 0; - done_a = 1; + skip_a = 1; + dprintk("channel A error interrupt: %04x\n", + intr); } - dprintk("intr: channel A end-of-field interrupt: " - "%04x\n", intr); - } else { - vino_dma_stop(&vino_drvdata->a); - vino_clear_interrupt(&vino_drvdata->a); - done_a = 1; - dprintk("channel A error interrupt: %04x\n", intr); + +#ifdef VINO_DEBUG_INT + line_count_2 = vino->a.line_count; + page_index_2 = vino->a.page_index; + field_counter_2 = vino->a.field_counter; + start_desc_tbl_2 = vino->a.start_desc_tbl; + next_4_desc_2 = vino->a.next_4_desc; + + printk("intr = %04x, loop = %d, field = %d\n", + intr, loop, vino_drvdata->a.field); + printk("1- line count = %04d, page index = %04d, " + "start = %08x, next = %08x\n" + " fieldc = %d, framec = %d\n", + line_count, page_index, start_desc_tbl, + next_4_desc, field_counter, fc_a); + printk("12-line count = %04d, page index = %04d, " + " start = %08x, next = %08x\n", + line_count_2, page_index_2, start_desc_tbl_2, + next_4_desc_2); + + if (done_a) + printk("\n"); +#endif } - } - if (intr & VINO_INTSTAT_B) { - if (intr & VINO_INTSTAT_B_EOF) { - vino_drvdata->b.field++; - if (vino_drvdata->b.field > 1) { + + if (intr & VINO_INTSTAT_B) { + if (intr & VINO_INTSTAT_B_EOF) { + vino_drvdata->b.field++; + if (vino_drvdata->b.field > 1) { + vino_dma_stop(&vino_drvdata->b); + vino_clear_interrupt(&vino_drvdata->b); + vino_drvdata->b.field = 0; + done_b = 1; + } + dprintk("channel B end-of-field " + "interrupt: %04x\n", intr); + } else { vino_dma_stop(&vino_drvdata->b); vino_clear_interrupt(&vino_drvdata->b); vino_drvdata->b.field = 0; - done_b = 1; + skip_b = 1; + dprintk("channel B error interrupt: %04x\n", + intr); } - dprintk("intr: channel B end-of-field interrupt: " - "%04x\n", intr); - } else { - vino_dma_stop(&vino_drvdata->b); - vino_clear_interrupt(&vino_drvdata->b); - done_b = 1; - dprintk("channel B error interrupt: %04x\n", intr); } - } - /* always remember to clear interrupt status */ - vino->intr_status = ~intr; + /* Always remember to clear interrupt status. + * Disable VINO interrupts while we do this. */ + ctrl = vino->control; + vino->control = ctrl & ~(VINO_CTRL_A_INT | VINO_CTRL_B_INT); + vino->intr_status = ~intr; + vino->control = ctrl; - spin_unlock(&vino_drvdata->vino_lock); + spin_unlock(&vino_drvdata->vino_lock); - if (done_a) { - vino_frame_done(&vino_drvdata->a, fc_a); - dprintk("channel A frame done, interrupt: %d\n", intr); - } - if (done_b) { - vino_frame_done(&vino_drvdata->b, fc_b); - dprintk("channel B frame done, interrupt: %d\n", intr); + if ((!handled_a) && (done_a || skip_a)) { + if (!skip_a) { + do_gettimeofday(&vino_drvdata-> + a.int_data.timestamp); + vino_drvdata->a.int_data.frame_counter = fc_a; + } + vino_drvdata->a.int_data.skip = skip_a; + + dprintk("channel A %s, interrupt: %d\n", + skip_a ? "skipping frame" : "frame done", + intr); + tasklet_hi_schedule(&vino_tasklet_a); + handled_a = 1; + } + + if ((!handled_b) && (done_b || skip_b)) { + if (!skip_b) { + do_gettimeofday(&vino_drvdata-> + b.int_data.timestamp); + vino_drvdata->b.int_data.frame_counter = fc_b; + } + vino_drvdata->b.int_data.skip = skip_b; + + dprintk("channel B %s, interrupt: %d\n", + skip_b ? "skipping frame" : "frame done", + intr); + tasklet_hi_schedule(&vino_tasklet_b); + handled_b = 1; + } + +#ifdef VINO_DEBUG_INT + loop++; +#endif + spin_lock(&vino_drvdata->vino_lock); } + spin_unlock(&vino_drvdata->vino_lock); + return IRQ_HANDLED; } @@ -2279,11 +2494,13 @@ static int vino_get_saa7191_input(int input) } } -static int vino_get_saa7191_norm(int norm) +static int vino_get_saa7191_norm(unsigned int data_norm) { - switch (norm) { + switch (data_norm) { case VINO_DATA_NORM_AUTO: return SAA7191_NORM_AUTO; + case VINO_DATA_NORM_AUTO_EXT: + return SAA7191_NORM_AUTO_EXT; case VINO_DATA_NORM_PAL: return SAA7191_NORM_PAL; case VINO_DATA_NORM_NTSC: @@ -2297,6 +2514,57 @@ static int vino_get_saa7191_norm(int norm) } } +static int vino_get_from_saa7191_norm(int saa7191_norm) +{ + switch (saa7191_norm) { + case SAA7191_NORM_PAL: + return VINO_DATA_NORM_PAL; + case SAA7191_NORM_NTSC: + return VINO_DATA_NORM_NTSC; + case SAA7191_NORM_SECAM: + return VINO_DATA_NORM_SECAM; + default: + printk(KERN_ERR "VINO: vino_get_from_saa7191_norm(): " + "invalid norm!\n"); + return VINO_DATA_NORM_NONE; + } +} + +static int vino_saa7191_set_norm(unsigned int *data_norm) +{ + int saa7191_norm, new_data_norm; + int err = 0; + + saa7191_norm = vino_get_saa7191_norm(*data_norm); + + err = i2c_decoder_command(DECODER_SAA7191_SET_NORM, + &saa7191_norm); + if (err) + goto out; + + if ((*data_norm == VINO_DATA_NORM_AUTO) + || (*data_norm == VINO_DATA_NORM_AUTO_EXT)) { + struct saa7191_status status; + + err = i2c_decoder_command(DECODER_SAA7191_GET_STATUS, + &status); + if (err) + goto out; + + new_data_norm = + vino_get_from_saa7191_norm(status.norm); + if (new_data_norm == VINO_DATA_NORM_NONE) { + err = -EINVAL; + goto out; + } + + *data_norm = (unsigned int)new_data_norm; + } + +out: + return err; +} + /* execute with input_lock locked */ static int vino_is_input_owner(struct vino_channel_settings *vcs) { @@ -2313,11 +2581,12 @@ static int vino_is_input_owner(struct vino_channel_settings *vcs) static int vino_acquire_input(struct vino_channel_settings *vcs) { + unsigned long flags; int ret = 0; dprintk("vino_acquire_input():\n"); - spin_lock(&vino_drvdata->input_lock); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); /* First try D1 and then SAA7191 */ if (vino_drvdata->camera.driver @@ -2332,23 +2601,48 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) vcs->data_norm = VINO_DATA_NORM_D1; } else if (vino_drvdata->decoder.driver && (vino_drvdata->decoder.owner == VINO_NO_CHANNEL)) { + int input, data_norm; int saa7191_input; - int saa7191_norm; if (i2c_use_client(vino_drvdata->decoder.driver)) { ret = -ENODEV; goto out; } - vino_drvdata->decoder.owner = vcs->channel; - vcs->input = VINO_INPUT_COMPOSITE; - vcs->data_norm = VINO_DATA_NORM_PAL; + input = VINO_INPUT_COMPOSITE; + + saa7191_input = vino_get_saa7191_input(input); + ret = i2c_decoder_command(DECODER_SET_INPUT, + &saa7191_input); + if (ret) { + ret = -EINVAL; + goto out; + } + + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - saa7191_input = vino_get_saa7191_input(vcs->input); - i2c_decoder_command(DECODER_SET_INPUT, &saa7191_input); + /* Don't hold spinlocks while auto-detecting norm + * as it may take a while... */ - saa7191_norm = vino_get_saa7191_norm(vcs->data_norm); - i2c_decoder_command(DECODER_SAA7191_SET_NORM, &saa7191_norm); + data_norm = VINO_DATA_NORM_AUTO_EXT; + + ret = vino_saa7191_set_norm(&data_norm); + if ((ret == -EBUSY) || (ret == -EAGAIN)) { + data_norm = VINO_DATA_NORM_PAL; + ret = vino_saa7191_set_norm(&data_norm); + } + + spin_lock_irqsave(&vino_drvdata->input_lock, flags); + + if (ret) { + ret = -EINVAL; + goto out; + } + + vino_drvdata->decoder.owner = vcs->channel; + + vcs->input = input; + vcs->data_norm = data_norm; } else { vcs->input = (vcs->channel == VINO_CHANNEL_A) ? vino_drvdata->b.input : vino_drvdata->a.input; @@ -2361,15 +2655,14 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) goto out; } - if (vino_is_input_owner(vcs)) { - vino_set_default_clipping(vcs); - vino_set_default_framerate(vcs); - } + vino_set_default_clipping(vcs); + vino_set_default_scaling(vcs); + vino_set_default_framerate(vcs); dprintk("vino_acquire_input(): %s\n", vino_inputs[vcs->input].name); out: - spin_unlock(&vino_drvdata->input_lock); + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); return ret; } @@ -2378,16 +2671,17 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) { struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ? &vino_drvdata->b : &vino_drvdata->a; + unsigned long flags; int ret = 0; dprintk("vino_set_input():\n"); - spin_lock(&vino_drvdata->input_lock); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); if (vcs->input == input) goto out; - switch(input) { + switch (input) { case VINO_INPUT_COMPOSITE: case VINO_INPUT_SVIDEO: if (!vino_drvdata->decoder.driver) { @@ -2404,19 +2698,43 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) } if (vino_drvdata->decoder.owner == vcs->channel) { + int data_norm; int saa7191_input; - int saa7191_norm; - vcs->input = input; - vcs->data_norm = VINO_DATA_NORM_PAL; + saa7191_input = vino_get_saa7191_input(input); + ret = i2c_decoder_command(DECODER_SET_INPUT, + &saa7191_input); + if (ret) { + vino_drvdata->decoder.owner = VINO_NO_CHANNEL; + ret = -EINVAL; + goto out; + } + + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); + + /* Don't hold spinlocks while auto-detecting norm + * as it may take a while... */ + + data_norm = VINO_DATA_NORM_AUTO_EXT; + + ret = vino_saa7191_set_norm(&data_norm); + if ((ret == -EBUSY) || (ret == -EAGAIN)) { + data_norm = VINO_DATA_NORM_PAL; + ret = vino_saa7191_set_norm(&data_norm); + } - saa7191_input = vino_get_saa7191_input(vcs->input); - i2c_decoder_command(DECODER_SET_INPUT, &saa7191_input); - saa7191_norm = vino_get_saa7191_norm(vcs->data_norm); - i2c_decoder_command(DECODER_SAA7191_SET_NORM, - &saa7191_norm); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); + + if (ret) { + vino_drvdata->decoder.owner = VINO_NO_CHANNEL; + ret = -EINVAL; + goto out; + } + + vcs->input = input; + vcs->data_norm = data_norm; } else { - if (vcs2->input != input) { + if (input != vcs2->input) { ret = -EBUSY; goto out; } @@ -2471,12 +2789,13 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) } vino_set_default_clipping(vcs); + vino_set_default_scaling(vcs); vino_set_default_framerate(vcs); dprintk("vino_set_input(): %s\n", vino_inputs[vcs->input].name); out: - spin_unlock(&vino_drvdata->input_lock); + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); return ret; } @@ -2485,10 +2804,11 @@ static void vino_release_input(struct vino_channel_settings *vcs) { struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ? &vino_drvdata->b : &vino_drvdata->a; + unsigned long flags; dprintk("vino_release_input():\n"); - spin_lock(&vino_drvdata->input_lock); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); /* Release ownership of the channel * and if the other channel takes input from @@ -2511,34 +2831,61 @@ static void vino_release_input(struct vino_channel_settings *vcs) } vcs->input = VINO_INPUT_NONE; - spin_unlock(&vino_drvdata->input_lock); + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); } /* execute with input_lock locked */ static int vino_set_data_norm(struct vino_channel_settings *vcs, - unsigned int data_norm) + unsigned int data_norm, + unsigned long *flags) { - int saa7191_norm; + int err = 0; + + if (data_norm == vcs->data_norm) + return 0; switch (vcs->input) { case VINO_INPUT_D1: /* only one "norm" supported */ - if (data_norm != VINO_DATA_NORM_D1) + if ((data_norm != VINO_DATA_NORM_D1) + && (data_norm != VINO_DATA_NORM_AUTO) + && (data_norm != VINO_DATA_NORM_AUTO_EXT)) return -EINVAL; break; case VINO_INPUT_COMPOSITE: - case VINO_INPUT_SVIDEO: + case VINO_INPUT_SVIDEO: { + if ((data_norm != VINO_DATA_NORM_PAL) + && (data_norm != VINO_DATA_NORM_NTSC) + && (data_norm != VINO_DATA_NORM_SECAM) + && (data_norm != VINO_DATA_NORM_AUTO) + && (data_norm != VINO_DATA_NORM_AUTO_EXT)) + return -EINVAL; - saa7191_norm = vino_get_saa7191_norm(data_norm); + spin_unlock_irqrestore(&vino_drvdata->input_lock, *flags); + + /* Don't hold spinlocks while setting norm + * as it may take a while... */ + + err = vino_saa7191_set_norm(&data_norm); + + spin_lock_irqsave(&vino_drvdata->input_lock, *flags); + + if (err) + goto out; - i2c_decoder_command(DECODER_SAA7191_SET_NORM, &saa7191_norm); vcs->data_norm = data_norm; + + vino_set_default_clipping(vcs); + vino_set_default_scaling(vcs); + vino_set_default_framerate(vcs); break; + } default: return -EINVAL; } - return 0; +out: + return err; } /* V4L2 helper functions */ @@ -2558,8 +2905,9 @@ static int vino_find_data_format(__u32 pixelformat) static int vino_enum_data_norm(struct vino_channel_settings *vcs, __u32 index) { int data_norm = VINO_DATA_NORM_NONE; + unsigned long flags; - spin_lock(&vino_drvdata->input_lock); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); switch(vcs->input) { case VINO_INPUT_COMPOSITE: case VINO_INPUT_SVIDEO: @@ -2577,7 +2925,7 @@ static int vino_enum_data_norm(struct vino_channel_settings *vcs, __u32 index) } break; } - spin_unlock(&vino_drvdata->input_lock); + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); return data_norm; } @@ -2585,8 +2933,9 @@ static int vino_enum_data_norm(struct vino_channel_settings *vcs, __u32 index) static int vino_enum_input(struct vino_channel_settings *vcs, __u32 index) { int input = VINO_INPUT_NONE; + unsigned long flags; - spin_lock(&vino_drvdata->input_lock); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) { switch (index) { case 0: @@ -2615,7 +2964,7 @@ static int vino_enum_input(struct vino_channel_settings *vcs, __u32 index) break; } } - spin_unlock(&vino_drvdata->input_lock); + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); return input; } @@ -2704,15 +3053,16 @@ static int vino_v4l2_enuminput(struct vino_channel_settings *vcs, } static int vino_v4l2_g_input(struct vino_channel_settings *vcs, - struct v4l2_input *i) + unsigned int *i) { __u32 index; int input; + unsigned long flags; - spin_lock(&vino_drvdata->input_lock); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); input = vcs->input; index = vino_find_input_index(vcs); - spin_unlock(&vino_drvdata->input_lock); + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); dprintk("input = %d\n", input); @@ -2720,23 +3070,18 @@ static int vino_v4l2_g_input(struct vino_channel_settings *vcs, return -EINVAL; } - memset(i, 0, sizeof(struct v4l2_input)); - - i->index = index; - i->type = V4L2_INPUT_TYPE_CAMERA; - i->std = vino_inputs[input].std; - strcpy(i->name, vino_inputs[input].name); + *i = index; return 0; } static int vino_v4l2_s_input(struct vino_channel_settings *vcs, - struct v4l2_input *i) + unsigned int *i) { int input; - dprintk("requested input = %d\n", i->index); + dprintk("requested input = %d\n", *i); - input = vino_enum_input(vcs, i->index); + input = vino_enum_input(vcs, *i); if (input == VINO_INPUT_NONE) return -EINVAL; @@ -2747,7 +3092,9 @@ static int vino_v4l2_enumstd(struct vino_channel_settings *vcs, struct v4l2_standard *s) { int index = s->index; - int data_norm = vino_enum_data_norm(vcs, index); + int data_norm; + + data_norm = vino_enum_data_norm(vcs, index); dprintk("standard index = %d\n", index); if (data_norm == VINO_DATA_NORM_NONE) @@ -2771,13 +3118,55 @@ static int vino_v4l2_enumstd(struct vino_channel_settings *vcs, return 0; } +static int vino_v4l2_querystd(struct vino_channel_settings *vcs, + v4l2_std_id *std) +{ + unsigned long flags; + int err = 0; + + spin_lock_irqsave(&vino_drvdata->input_lock, flags); + + switch (vcs->input) { + case VINO_INPUT_D1: + *std = vino_inputs[vcs->input].std; + break; + case VINO_INPUT_COMPOSITE: + case VINO_INPUT_SVIDEO: { + struct saa7191_status status; + + i2c_decoder_command(DECODER_SAA7191_GET_STATUS, &status); + + if (status.signal) { + if (status.signal_60hz) { + *std = V4L2_STD_NTSC; + } else { + *std = V4L2_STD_PAL | V4L2_STD_SECAM; + } + } else { + *std = vino_inputs[vcs->input].std; + } + break; + } + default: + err = -EINVAL; + } + + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); + + return err; +} + static int vino_v4l2_g_std(struct vino_channel_settings *vcs, v4l2_std_id *std) { - spin_lock(&vino_drvdata->input_lock); - dprintk("current standard = %d\n", vcs->data_norm); + unsigned long flags; + + spin_lock_irqsave(&vino_drvdata->input_lock, flags); + *std = vino_data_norms[vcs->data_norm].std; - spin_unlock(&vino_drvdata->input_lock); + dprintk("current standard = %d\n", vcs->data_norm); + + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); return 0; } @@ -2785,13 +3174,18 @@ static int vino_v4l2_g_std(struct vino_channel_settings *vcs, static int vino_v4l2_s_std(struct vino_channel_settings *vcs, v4l2_std_id *std) { + unsigned long flags; int ret = 0; - spin_lock(&vino_drvdata->input_lock); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); + + if (!vino_is_input_owner(vcs)) { + ret = -EBUSY; + goto out; + } /* check if the standard is valid for the current input */ - if (vino_is_input_owner(vcs) - && (vino_inputs[vcs->input].std & (*std))) { + if ((*std) & vino_inputs[vcs->input].std) { dprintk("standard accepted\n"); /* change the video norm for SAA7191 @@ -2800,24 +3194,33 @@ static int vino_v4l2_s_std(struct vino_channel_settings *vcs, if (vcs->input == VINO_INPUT_D1) goto out; - if ((*std) & V4L2_STD_PAL) { - vino_set_data_norm(vcs, VINO_DATA_NORM_PAL); - vcs->data_norm = VINO_DATA_NORM_PAL; + if (((*std) & V4L2_STD_PAL) + && ((*std) & V4L2_STD_NTSC) + && ((*std) & V4L2_STD_SECAM)) { + ret = vino_set_data_norm(vcs, VINO_DATA_NORM_AUTO_EXT, + &flags); + } else if ((*std) & V4L2_STD_PAL) { + ret = vino_set_data_norm(vcs, VINO_DATA_NORM_PAL, + &flags); } else if ((*std) & V4L2_STD_NTSC) { - vino_set_data_norm(vcs, VINO_DATA_NORM_NTSC); - vcs->data_norm = VINO_DATA_NORM_NTSC; + ret = vino_set_data_norm(vcs, VINO_DATA_NORM_NTSC, + &flags); } else if ((*std) & V4L2_STD_SECAM) { - vino_set_data_norm(vcs, VINO_DATA_NORM_SECAM); - vcs->data_norm = VINO_DATA_NORM_SECAM; + ret = vino_set_data_norm(vcs, VINO_DATA_NORM_SECAM, + &flags); } else { ret = -EINVAL; } + + if (ret) { + ret = -EINVAL; + } } else { ret = -EINVAL; } out: - spin_unlock(&vino_drvdata->input_lock); + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); return ret; } @@ -2855,6 +3258,7 @@ static int vino_v4l2_try_fmt(struct vino_channel_settings *vcs, struct v4l2_format *f) { struct vino_channel_settings tempvcs; + unsigned long flags; switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: { @@ -2863,13 +3267,13 @@ static int vino_v4l2_try_fmt(struct vino_channel_settings *vcs, dprintk("requested: w = %d, h = %d\n", pf->width, pf->height); - spin_lock(&vino_drvdata->input_lock); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings)); - spin_unlock(&vino_drvdata->input_lock); + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); tempvcs.data_format = vino_find_data_format(pf->pixelformat); if (tempvcs.data_format == VINO_DATA_FMT_NONE) { - tempvcs.data_format = VINO_DATA_FMT_RGB32; + tempvcs.data_format = VINO_DATA_FMT_GREY; pf->pixelformat = vino_data_formats[tempvcs.data_format]. pixelformat; @@ -2908,10 +3312,13 @@ static int vino_v4l2_try_fmt(struct vino_channel_settings *vcs, static int vino_v4l2_g_fmt(struct vino_channel_settings *vcs, struct v4l2_format *f) { + unsigned long flags; + switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: { struct v4l2_pix_format *pf = &f->fmt.pix; - spin_lock(&vino_drvdata->input_lock); + + spin_lock_irqsave(&vino_drvdata->input_lock, flags); pf->width = (vcs->clipping.right - vcs->clipping.left) / vcs->decimation; @@ -2930,7 +3337,7 @@ static int vino_v4l2_g_fmt(struct vino_channel_settings *vcs, pf->priv = 0; - spin_unlock(&vino_drvdata->input_lock); + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); break; } case V4L2_BUF_TYPE_VIDEO_OVERLAY: @@ -2945,20 +3352,18 @@ static int vino_v4l2_s_fmt(struct vino_channel_settings *vcs, struct v4l2_format *f) { int data_format; + unsigned long flags; switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: { struct v4l2_pix_format *pf = &f->fmt.pix; - spin_lock(&vino_drvdata->input_lock); - if (!vino_is_input_owner(vcs)) { - spin_unlock(&vino_drvdata->input_lock); - return -EINVAL; - } + spin_lock_irqsave(&vino_drvdata->input_lock, flags); data_format = vino_find_data_format(pf->pixelformat); + if (data_format == VINO_DATA_FMT_NONE) { - vcs->data_format = VINO_DATA_FMT_RGB32; + vcs->data_format = VINO_DATA_FMT_GREY; pf->pixelformat = vino_data_formats[vcs->data_format]. pixelformat; @@ -2985,7 +3390,7 @@ static int vino_v4l2_s_fmt(struct vino_channel_settings *vcs, pf->priv = 0; - spin_unlock(&vino_drvdata->input_lock); + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); break; } case V4L2_BUF_TYPE_VIDEO_OVERLAY: @@ -3000,12 +3405,15 @@ static int vino_v4l2_cropcap(struct vino_channel_settings *vcs, struct v4l2_cropcap *ccap) { const struct vino_data_norm *norm; + unsigned long flags; switch (ccap->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - spin_lock(&vino_drvdata->input_lock); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); + norm = &vino_data_norms[vcs->data_norm]; - spin_unlock(&vino_drvdata->input_lock); + + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); ccap->bounds.left = 0; ccap->bounds.top = 0; @@ -3028,16 +3436,18 @@ static int vino_v4l2_cropcap(struct vino_channel_settings *vcs, static int vino_v4l2_g_crop(struct vino_channel_settings *vcs, struct v4l2_crop *c) { + unsigned long flags; + switch (c->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - spin_lock(&vino_drvdata->input_lock); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); c->c.left = vcs->clipping.left; c->c.top = vcs->clipping.top; c->c.width = vcs->clipping.right - vcs->clipping.left; c->c.height = vcs->clipping.bottom - vcs->clipping.top; - spin_unlock(&vino_drvdata->input_lock); + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); break; case V4L2_BUF_TYPE_VIDEO_OVERLAY: default: @@ -3050,18 +3460,16 @@ static int vino_v4l2_g_crop(struct vino_channel_settings *vcs, static int vino_v4l2_s_crop(struct vino_channel_settings *vcs, struct v4l2_crop *c) { + unsigned long flags; + switch (c->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - spin_lock(&vino_drvdata->input_lock); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); - if (!vino_is_input_owner(vcs)) { - spin_unlock(&vino_drvdata->input_lock); - return -EINVAL; - } vino_set_clipping(vcs, c->c.left, c->c.top, c->c.width, c->c.height); - spin_unlock(&vino_drvdata->input_lock); + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); break; case V4L2_BUF_TYPE_VIDEO_OVERLAY: default: @@ -3074,6 +3482,8 @@ static int vino_v4l2_s_crop(struct vino_channel_settings *vcs, static int vino_v4l2_g_parm(struct vino_channel_settings *vcs, struct v4l2_streamparm *sp) { + unsigned long flags; + switch (sp->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: { struct v4l2_captureparm *cp = &sp->parm.capture; @@ -3082,9 +3492,11 @@ static int vino_v4l2_g_parm(struct vino_channel_settings *vcs, cp->capability = V4L2_CAP_TIMEPERFRAME; cp->timeperframe.numerator = 1; - spin_lock(&vino_drvdata->input_lock); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); + cp->timeperframe.denominator = vcs->fps; - spin_unlock(&vino_drvdata->input_lock); + + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); // TODO: cp->readbuffers = xxx; break; @@ -3100,15 +3512,13 @@ static int vino_v4l2_g_parm(struct vino_channel_settings *vcs, static int vino_v4l2_s_parm(struct vino_channel_settings *vcs, struct v4l2_streamparm *sp) { + unsigned long flags; + switch (sp->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: { struct v4l2_captureparm *cp = &sp->parm.capture; - spin_lock(&vino_drvdata->input_lock); - if (!vino_is_input_owner(vcs)) { - spin_unlock(&vino_drvdata->input_lock); - return -EINVAL; - } + spin_lock_irqsave(&vino_drvdata->input_lock, flags); if ((cp->timeperframe.numerator == 0) || (cp->timeperframe.denominator == 0)) { @@ -3118,7 +3528,8 @@ static int vino_v4l2_s_parm(struct vino_channel_settings *vcs, vino_set_framerate(vcs, cp->timeperframe.denominator / cp->timeperframe.numerator); } - spin_unlock(&vino_drvdata->input_lock); + + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); // TODO: set buffers according to cp->readbuffers break; @@ -3145,21 +3556,23 @@ static int vino_v4l2_reqbufs(struct vino_channel_settings *vcs, return -EINVAL; } - if (vino_is_capturing(vcs)) { - dprintk("busy, capturing\n"); - return -EBUSY; - } - dprintk("count = %d\n", rb->count); if (rb->count > 0) { + if (vino_is_capturing(vcs)) { + dprintk("busy, capturing\n"); + return -EBUSY; + } + if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) { dprintk("busy, buffers still mapped\n"); return -EBUSY; } else { + vcs->streaming = 0; vino_queue_free(&vcs->fb_queue); vino_queue_init(&vcs->fb_queue, &rb->count); } } else { + vcs->streaming = 0; vino_capture_stop(vcs); vino_queue_free(&vcs->fb_queue); } @@ -3302,12 +3715,12 @@ static int vino_v4l2_dqbuf(struct vino_channel_settings *vcs, err = vino_queue_get_incoming(&vcs->fb_queue, &incoming); if (err) { dprintk("vino_queue_get_incoming() failed\n"); - return -EIO; + return -EINVAL; } err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing); if (err) { dprintk("vino_queue_get_outgoing() failed\n"); - return -EIO; + return -EINVAL; } dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing); @@ -3327,8 +3740,10 @@ static int vino_v4l2_dqbuf(struct vino_channel_settings *vcs, if (err) { err = vino_wait_for_frame(vcs); if (err) { - /* interrupted */ - vino_capture_failed(vcs); + /* interrupted or + * no frames captured because + * of frame skipping */ + // vino_capture_failed(vcs); return -EIO; } } @@ -3341,10 +3756,12 @@ static int vino_v4l2_dqbuf(struct vino_channel_settings *vcs, } err = vino_check_buffer(vcs, fb); + + vino_v4l2_get_buffer_status(vcs, fb, b); + if (err) return -EIO; - vino_v4l2_get_buffer_status(vcs, fb, b); break; } case V4L2_BUF_TYPE_VIDEO_OVERLAY: @@ -3401,8 +3818,8 @@ static int vino_v4l2_streamoff(struct vino_channel_settings *vcs) if (!vcs->streaming) return 0; - vino_capture_stop(vcs); vcs->streaming = 0; + vino_capture_stop(vcs); return 0; } @@ -3410,10 +3827,11 @@ static int vino_v4l2_streamoff(struct vino_channel_settings *vcs) static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs, struct v4l2_queryctrl *queryctrl) { + unsigned long flags; int i; int err = 0; - spin_lock(&vino_drvdata->input_lock); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); switch (vcs->input) { case VINO_INPUT_D1: @@ -3423,6 +3841,7 @@ static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs, memcpy(queryctrl, &vino_indycam_v4l2_controls[i], sizeof(struct v4l2_queryctrl)); + queryctrl->reserved[0] = 0; goto found; } } @@ -3437,6 +3856,7 @@ static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs, memcpy(queryctrl, &vino_saa7191_v4l2_controls[i], sizeof(struct v4l2_queryctrl)); + queryctrl->reserved[0] = 0; goto found; } } @@ -3448,7 +3868,7 @@ static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs, } found: - spin_unlock(&vino_drvdata->input_lock); + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); return err; } @@ -3456,70 +3876,72 @@ static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs, static int vino_v4l2_g_ctrl(struct vino_channel_settings *vcs, struct v4l2_control *control) { - struct indycam_control indycam_ctrl; - struct saa7191_control saa7191_ctrl; + unsigned long flags; + int i; int err = 0; - spin_lock(&vino_drvdata->input_lock); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); switch (vcs->input) { - case VINO_INPUT_D1: - i2c_camera_command(DECODER_INDYCAM_GET_CONTROLS, - &indycam_ctrl); + case VINO_INPUT_D1: { + struct indycam_control indycam_ctrl; - switch(control->id) { - case V4L2_CID_AUTOGAIN: - control->value = indycam_ctrl.agc; - break; - case V4L2_CID_AUTO_WHITE_BALANCE: - control->value = indycam_ctrl.awb; - break; - case V4L2_CID_GAIN: - control->value = indycam_ctrl.gain; - break; - case V4L2_CID_PRIVATE_BASE: - control->value = indycam_ctrl.red_saturation; - break; - case V4L2_CID_PRIVATE_BASE + 1: - control->value = indycam_ctrl.blue_saturation; - break; - case V4L2_CID_RED_BALANCE: - control->value = indycam_ctrl.red_balance; - break; - case V4L2_CID_BLUE_BALANCE: - control->value = indycam_ctrl.blue_balance; - break; - case V4L2_CID_EXPOSURE: - control->value = indycam_ctrl.shutter; - break; - case V4L2_CID_GAMMA: - control->value = indycam_ctrl.gamma; - break; - default: + for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) { + if (vino_indycam_v4l2_controls[i].id == + control->id) { + goto found1; + } + } + + err = -EINVAL; + goto out; + +found1: + indycam_ctrl.type = vino_indycam_v4l2_controls[i].reserved[0]; + + err = i2c_camera_command(DECODER_INDYCAM_GET_CONTROL, + &indycam_ctrl); + if (err) { err = -EINVAL; + goto out; } + + control->value = indycam_ctrl.value; break; + } case VINO_INPUT_COMPOSITE: - case VINO_INPUT_SVIDEO: - i2c_decoder_command(DECODER_SAA7191_GET_CONTROLS, - &saa7191_ctrl); + case VINO_INPUT_SVIDEO: { + struct saa7191_control saa7191_ctrl; - switch(control->id) { - case V4L2_CID_HUE: - control->value = saa7191_ctrl.hue; - break; - case V4L2_CID_PRIVATE_BASE: - control->value = saa7191_ctrl.vtrc; - break; - default: + for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) { + if (vino_saa7191_v4l2_controls[i].id == + control->id) { + goto found2; + } + } + + err = -EINVAL; + goto out; + +found2: + saa7191_ctrl.type = vino_saa7191_v4l2_controls[i].reserved[0]; + + err = i2c_decoder_command(DECODER_SAA7191_GET_CONTROL, + &saa7191_ctrl); + if (err) { err = -EINVAL; + goto out; } + + control->value = saa7191_ctrl.value; break; + } default: err = -EINVAL; } - spin_unlock(&vino_drvdata->input_lock); +out: + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); return err; } @@ -3527,15 +3949,21 @@ static int vino_v4l2_g_ctrl(struct vino_channel_settings *vcs, static int vino_v4l2_s_ctrl(struct vino_channel_settings *vcs, struct v4l2_control *control) { - struct indycam_control indycam_ctrl; - struct saa7191_control saa7191_ctrl; + unsigned long flags; int i; int err = 0; - spin_lock(&vino_drvdata->input_lock); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); + + if (!vino_is_input_owner(vcs)) { + err = -EBUSY; + goto out; + } switch (vcs->input) { - case VINO_INPUT_D1: + case VINO_INPUT_D1: { + struct indycam_control indycam_ctrl; + for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) { if (vino_indycam_v4l2_controls[i].id == control->id) { @@ -3544,65 +3972,31 @@ static int vino_v4l2_s_ctrl(struct vino_channel_settings *vcs, && (control->value <= vino_indycam_v4l2_controls[i]. maximum)) { - goto ok1; + goto found1; } else { err = -ERANGE; - goto error; + goto out; } } } + err = -EINVAL; - goto error; + goto out; -ok1: - indycam_ctrl.agc = INDYCAM_VALUE_UNCHANGED; - indycam_ctrl.awb = INDYCAM_VALUE_UNCHANGED; - indycam_ctrl.shutter = INDYCAM_VALUE_UNCHANGED; - indycam_ctrl.gain = INDYCAM_VALUE_UNCHANGED; - indycam_ctrl.red_balance = INDYCAM_VALUE_UNCHANGED; - indycam_ctrl.blue_balance = INDYCAM_VALUE_UNCHANGED; - indycam_ctrl.red_saturation = INDYCAM_VALUE_UNCHANGED; - indycam_ctrl.blue_saturation = INDYCAM_VALUE_UNCHANGED; - indycam_ctrl.gamma = INDYCAM_VALUE_UNCHANGED; - - switch(control->id) { - case V4L2_CID_AUTOGAIN: - indycam_ctrl.agc = control->value; - break; - case V4L2_CID_AUTO_WHITE_BALANCE: - indycam_ctrl.awb = control->value; - break; - case V4L2_CID_GAIN: - indycam_ctrl.gain = control->value; - break; - case V4L2_CID_PRIVATE_BASE: - indycam_ctrl.red_saturation = control->value; - break; - case V4L2_CID_PRIVATE_BASE + 1: - indycam_ctrl.blue_saturation = control->value; - break; - case V4L2_CID_RED_BALANCE: - indycam_ctrl.red_balance = control->value; - break; - case V4L2_CID_BLUE_BALANCE: - indycam_ctrl.blue_balance = control->value; - break; - case V4L2_CID_EXPOSURE: - indycam_ctrl.shutter = control->value; - break; - case V4L2_CID_GAMMA: - indycam_ctrl.gamma = control->value; - break; - default: - err = -EINVAL; - } +found1: + indycam_ctrl.type = vino_indycam_v4l2_controls[i].reserved[0]; + indycam_ctrl.value = control->value; - if (!err) - i2c_camera_command(DECODER_INDYCAM_SET_CONTROLS, - &indycam_ctrl); + err = i2c_camera_command(DECODER_INDYCAM_SET_CONTROL, + &indycam_ctrl); + if (err) + err = -EINVAL; break; + } case VINO_INPUT_COMPOSITE: - case VINO_INPUT_SVIDEO: + case VINO_INPUT_SVIDEO: { + struct saa7191_control saa7191_ctrl; + for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) { if (vino_saa7191_v4l2_controls[i].id == control->id) { @@ -3611,41 +4005,32 @@ ok1: && (control->value <= vino_saa7191_v4l2_controls[i]. maximum)) { - goto ok2; + goto found2; } else { err = -ERANGE; - goto error; + goto out; } } } err = -EINVAL; - goto error; - -ok2: - saa7191_ctrl.hue = SAA7191_VALUE_UNCHANGED; - saa7191_ctrl.vtrc = SAA7191_VALUE_UNCHANGED; + goto out; - switch(control->id) { - case V4L2_CID_HUE: - saa7191_ctrl.hue = control->value; - break; - case V4L2_CID_PRIVATE_BASE: - saa7191_ctrl.vtrc = control->value; - break; - default: - err = -EINVAL; - } +found2: + saa7191_ctrl.type = vino_saa7191_v4l2_controls[i].reserved[0]; + saa7191_ctrl.value = control->value; - if (!err) - i2c_decoder_command(DECODER_SAA7191_SET_CONTROLS, - &saa7191_ctrl); + err = i2c_decoder_command(DECODER_SAA7191_SET_CONTROL, + &saa7191_ctrl); + if (err) + err = -EINVAL; break; + } default: err = -EINVAL; } -error: - spin_unlock(&vino_drvdata->input_lock); +out: + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); return err; } @@ -3865,9 +4250,9 @@ static unsigned int vino_poll(struct file *file, poll_table *pt) over: dprintk("poll(): data %savailable\n", (outgoing > 0) ? "" : "not "); - if (outgoing > 0) { + + if (outgoing > 0) ret = POLLIN | POLLRDNORM; - } error: @@ -3880,6 +4265,7 @@ static int vino_do_ioctl(struct inode *inode, struct file *file, struct video_device *dev = video_devdata(file); struct vino_channel_settings *vcs = video_get_drvdata(dev); +#ifdef VINO_DEBUG switch (_IOC_TYPE(cmd)) { case 'v': dprintk("ioctl(): V4L1 unsupported (0x%08x)\n", cmd); @@ -3891,9 +4277,9 @@ static int vino_do_ioctl(struct inode *inode, struct file *file, default: dprintk("ioctl(): unsupported command 0x%08x\n", cmd); } +#endif switch (cmd) { - /* TODO: V4L1 interface (use compatibility layer?) */ /* V4L2 interface */ case VIDIOC_QUERYCAP: { vino_v4l2_querycap(arg); @@ -3911,6 +4297,9 @@ static int vino_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_ENUMSTD: { return vino_v4l2_enumstd(vcs, arg); } + case VIDIOC_QUERYSTD: { + return vino_v4l2_querystd(vcs, arg); + } case VIDIOC_G_STD: { return vino_v4l2_g_std(vcs, arg); } @@ -4100,8 +4489,7 @@ static int vino_probe(void) return -ENODEV; } - printk(KERN_INFO "VINO with chip ID %ld, revision %ld found\n", - VINO_ID_VALUE(rev_id), VINO_REV_NUM(rev_id)); + printk(KERN_INFO "VINO revision %ld found\n", VINO_REV_NUM(rev_id)); return 0; } -- cgit v1.2.3 From 9138d581b0ef855c0314c41c14852a7231b9941c Mon Sep 17 00:00:00 2001 From: Keith Owens Date: Mon, 7 Nov 2005 11:27:13 -0800 Subject: [IA64] Extend notify_die() hooks for IA64 notify_die() added for MCA_{MONARCH,SLAVE,RENDEZVOUS}_{ENTER,PROCESS,LEAVE} and INIT_{MONARCH,SLAVE}_{ENTER,PROCESS,LEAVE}. We need multiple notification points for these events because they can take many seconds to run which has nasty effects on the behaviour of the rest of the system. DIE_SS replaced by a generic DIE_FAULT which checks the vector number, to allow interception of faults other than SS. DIE_MACHINE_{HALT,RESTART} added to allow last minute close down processing, especially when the halt/restart routines are called from error handlers. DIE_OOPS added. The check for kprobe's break numbers has been moved from traps.c to kprobes.c, allowing DIE_BREAK to be used for any additional break numbers, i.e. it is no longer kprobes specific. Hooks for kernel debuggers and kernel dumpers added, ENTER and LEAVE. Both of these disable the system for long periods which impact on watchdogs and heartbeat systems in general. More patches to come that use these events to reset watchdogs and heartbeats. unregister_die_notifier() added and both routines exported. Requested by Dean Nelson. Lock removed from {un,}register_die_notifier. notifier_chain_register() already takes a lock. Also the generic notifier chain locking is being reworked to distinguish between callbacks that can block and those that cannot, the lock in {un,}register_die_notifier would interfere with that change. http://marc.theaimsgroup.com/?l=linux-kernel&m=113018709002036&w=2 Leading white space removed from arch/ia64/kernel/kprobes.c. Typo in mca.c in original version of this patch found & fixed by Dean Nelson. Signed-off-by: Keith Owens Acked-by: Dean Nelson Acked-by: Anil Keshavamurthy Signed-off-by: Tony Luck --- arch/ia64/kernel/kprobes.c | 22 +++++---- arch/ia64/kernel/mca.c | 120 +++++++++++++++++++++++++++++++++++---------- arch/ia64/kernel/process.c | 6 +++ arch/ia64/kernel/traps.c | 44 ++++++++--------- include/asm-ia64/kdebug.h | 30 +++++++++++- 5 files changed, 162 insertions(+), 60 deletions(-) diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 96736a119c9..801eeaeaf3d 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c @@ -347,7 +347,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) ((struct fnptr *)kretprobe_trampoline)->ip; spin_lock_irqsave(&kretprobe_lock, flags); - head = kretprobe_inst_table_head(current); + head = kretprobe_inst_table_head(current); /* * It is possible to have multiple instances associated with a given @@ -363,9 +363,9 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) * kretprobe_trampoline */ hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { - if (ri->task != current) + if (ri->task != current) /* another task is sharing our hash bucket */ - continue; + continue; if (ri->rp && ri->rp->handler) ri->rp->handler(ri, regs); @@ -394,7 +394,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) * kprobe_handler() that we don't want the post_handler * to run (and have re-enabled preemption) */ - return 1; + return 1; } /* Called with kretprobe_lock held */ @@ -739,12 +739,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, switch(val) { case DIE_BREAK: - if (pre_kprobes_handler(args)) - ret = NOTIFY_STOP; + /* err is break number from ia64_bad_break() */ + if (args->err == 0x80200 || args->err == 0x80300) + if (pre_kprobes_handler(args)) + ret = NOTIFY_STOP; break; - case DIE_SS: - if (post_kprobes_handler(args->regs)) - ret = NOTIFY_STOP; + case DIE_FAULT: + /* err is vector number from ia64_fault() */ + if (args->err == 36) + if (post_kprobes_handler(args->regs)) + ret = NOTIFY_STOP; break; case DIE_PAGE_FAULT: /* kprobe_running() needs smp_processor_id() */ diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 52c47da1724..355af15287c 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -51,6 +51,9 @@ * * 2005-08-12 Keith Owens * Convert MCA/INIT handlers to use per event stacks and SAL/OS state. + * + * 2005-10-07 Keith Owens + * Add notify_die() hooks. */ #include #include @@ -58,7 +61,6 @@ #include #include #include -#include #include #include #include @@ -69,6 +71,7 @@ #include #include +#include #include #include #include @@ -132,6 +135,14 @@ extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe); static int mca_init; + +static void inline +ia64_mca_spin(const char *func) +{ + printk(KERN_EMERG "%s: spinning here, not returning to SAL\n", func); + while (1) + cpu_relax(); +} /* * IA64_MCA log support */ @@ -526,13 +537,16 @@ ia64_mca_wakeup_all(void) * Outputs : None */ static irqreturn_t -ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs) +ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *regs) { unsigned long flags; int cpu = smp_processor_id(); /* Mask all interrupts */ local_irq_save(flags); + if (notify_die(DIE_MCA_RENDZVOUS_ENTER, "MCA", regs, 0, 0, 0) + == NOTIFY_STOP) + ia64_mca_spin(__FUNCTION__); ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_DONE; /* Register with the SAL monarch that the slave has @@ -540,10 +554,18 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs) */ ia64_sal_mc_rendez(); + if (notify_die(DIE_MCA_RENDZVOUS_PROCESS, "MCA", regs, 0, 0, 0) + == NOTIFY_STOP) + ia64_mca_spin(__FUNCTION__); + /* Wait for the monarch cpu to exit. */ while (monarch_cpu != -1) cpu_relax(); /* spin until monarch leaves */ + if (notify_die(DIE_MCA_RENDZVOUS_LEAVE, "MCA", regs, 0, 0, 0) + == NOTIFY_STOP) + ia64_mca_spin(__FUNCTION__); + /* Enable all interrupts */ local_irq_restore(flags); return IRQ_HANDLED; @@ -933,6 +955,9 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */ previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA"); monarch_cpu = cpu; + if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, 0, 0, 0) + == NOTIFY_STOP) + ia64_mca_spin(__FUNCTION__); ia64_wait_for_slaves(cpu); /* Wakeup all the processors which are spinning in the rendezvous loop. @@ -942,6 +967,9 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, * spinning in SAL does not work. */ ia64_mca_wakeup_all(); + if (notify_die(DIE_MCA_MONARCH_PROCESS, "MCA", regs, 0, 0, 0) + == NOTIFY_STOP) + ia64_mca_spin(__FUNCTION__); /* Get the MCA error record and log it */ ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA); @@ -960,6 +988,9 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, ia64_sal_clear_state_info(SAL_INFO_TYPE_MCA); sos->os_status = IA64_MCA_CORRECTED; } + if (notify_die(DIE_MCA_MONARCH_LEAVE, "MCA", regs, 0, 0, recover) + == NOTIFY_STOP) + ia64_mca_spin(__FUNCTION__); set_curr_task(cpu, previous_current); monarch_cpu = -1; @@ -1188,6 +1219,37 @@ ia64_mca_cpe_poll (unsigned long dummy) #endif /* CONFIG_ACPI */ +static int +default_monarch_init_process(struct notifier_block *self, unsigned long val, void *data) +{ + int c; + struct task_struct *g, *t; + if (val != DIE_INIT_MONARCH_PROCESS) + return NOTIFY_DONE; + printk(KERN_ERR "Processes interrupted by INIT -"); + for_each_online_cpu(c) { + struct ia64_sal_os_state *s; + t = __va(__per_cpu_mca[c] + IA64_MCA_CPU_INIT_STACK_OFFSET); + s = (struct ia64_sal_os_state *)((char *)t + MCA_SOS_OFFSET); + g = s->prev_task; + if (g) { + if (g->pid) + printk(" %d", g->pid); + else + printk(" %d (cpu %d task 0x%p)", g->pid, task_cpu(g), g); + } + } + printk("\n\n"); + if (read_trylock(&tasklist_lock)) { + do_each_thread (g, t) { + printk("\nBacktrace of pid %d (%s)\n", t->pid, t->comm); + show_stack(t, NULL); + } while_each_thread (g, t); + read_unlock(&tasklist_lock); + } + return NOTIFY_DONE; +} + /* * C portion of the OS INIT handler * @@ -1212,8 +1274,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw, static atomic_t slaves; static atomic_t monarchs; task_t *previous_current; - int cpu = smp_processor_id(), c; - struct task_struct *g, *t; + int cpu = smp_processor_id(); oops_in_progress = 1; /* FIXME: make printk NMI/MCA/INIT safe */ console_loglevel = 15; /* make sure printks make it to console */ @@ -1253,8 +1314,17 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw, ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_INIT; while (monarch_cpu == -1) cpu_relax(); /* spin until monarch enters */ + if (notify_die(DIE_INIT_SLAVE_ENTER, "INIT", regs, 0, 0, 0) + == NOTIFY_STOP) + ia64_mca_spin(__FUNCTION__); + if (notify_die(DIE_INIT_SLAVE_PROCESS, "INIT", regs, 0, 0, 0) + == NOTIFY_STOP) + ia64_mca_spin(__FUNCTION__); while (monarch_cpu != -1) cpu_relax(); /* spin until monarch leaves */ + if (notify_die(DIE_INIT_SLAVE_LEAVE, "INIT", regs, 0, 0, 0) + == NOTIFY_STOP) + ia64_mca_spin(__FUNCTION__); printk("Slave on cpu %d returning to normal service.\n", cpu); set_curr_task(cpu, previous_current); ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; @@ -1263,6 +1333,9 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw, } monarch_cpu = cpu; + if (notify_die(DIE_INIT_MONARCH_ENTER, "INIT", regs, 0, 0, 0) + == NOTIFY_STOP) + ia64_mca_spin(__FUNCTION__); /* * Wait for a bit. On some machines (e.g., HP's zx2000 and zx6000, INIT can be @@ -1273,27 +1346,16 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw, printk("Delaying for 5 seconds...\n"); udelay(5*1000000); ia64_wait_for_slaves(cpu); - printk(KERN_ERR "Processes interrupted by INIT -"); - for_each_online_cpu(c) { - struct ia64_sal_os_state *s; - t = __va(__per_cpu_mca[c] + IA64_MCA_CPU_INIT_STACK_OFFSET); - s = (struct ia64_sal_os_state *)((char *)t + MCA_SOS_OFFSET); - g = s->prev_task; - if (g) { - if (g->pid) - printk(" %d", g->pid); - else - printk(" %d (cpu %d task 0x%p)", g->pid, task_cpu(g), g); - } - } - printk("\n\n"); - if (read_trylock(&tasklist_lock)) { - do_each_thread (g, t) { - printk("\nBacktrace of pid %d (%s)\n", t->pid, t->comm); - show_stack(t, NULL); - } while_each_thread (g, t); - read_unlock(&tasklist_lock); - } + /* If nobody intercepts DIE_INIT_MONARCH_PROCESS then we drop through + * to default_monarch_init_process() above and just print all the + * tasks. + */ + if (notify_die(DIE_INIT_MONARCH_PROCESS, "INIT", regs, 0, 0, 0) + == NOTIFY_STOP) + ia64_mca_spin(__FUNCTION__); + if (notify_die(DIE_INIT_MONARCH_LEAVE, "INIT", regs, 0, 0, 0) + == NOTIFY_STOP) + ia64_mca_spin(__FUNCTION__); printk("\nINIT dump complete. Monarch on cpu %d returning to normal service.\n", cpu); atomic_dec(&monarchs); set_curr_task(cpu, previous_current); @@ -1462,6 +1524,10 @@ ia64_mca_init(void) s64 rc; struct ia64_sal_retval isrv; u64 timeout = IA64_MCA_RENDEZ_TIMEOUT; /* platform specific */ + static struct notifier_block default_init_monarch_nb = { + .notifier_call = default_monarch_init_process, + .priority = 0/* we need to notified last */ + }; IA64_MCA_DEBUG("%s: begin\n", __FUNCTION__); @@ -1555,6 +1621,10 @@ ia64_mca_init(void) "(status %ld)\n", rc); return; } + if (register_die_notifier(&default_init_monarch_nb)) { + printk(KERN_ERR "Failed to register default monarch INIT process\n"); + return; + } IA64_MCA_DEBUG("%s: registered OS INIT handler with SAL\n", __FUNCTION__); diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 051e050359e..c78355cb890 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -4,6 +4,9 @@ * Copyright (C) 1998-2003 Hewlett-Packard Co * David Mosberger-Tang * 04/11/17 Ashok Raj Added CPU Hotplug Support + * + * 2005-10-07 Keith Owens + * Add notify_die() hooks. */ #define __KERNEL_SYSCALLS__ /* see */ #include @@ -34,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -804,12 +808,14 @@ cpu_halt (void) void machine_restart (char *restart_cmd) { + (void) notify_die(DIE_MACHINE_RESTART, restart_cmd, NULL, 0, 0, 0); (*efi.reset_system)(EFI_RESET_WARM, 0, 0, NULL); } void machine_halt (void) { + (void) notify_die(DIE_MACHINE_HALT, "", NULL, 0, 0, 0); cpu_halt(); } diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index f970359e7ed..fba5fdd1f96 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c @@ -30,17 +30,20 @@ fpswa_interface_t *fpswa_interface; EXPORT_SYMBOL(fpswa_interface); struct notifier_block *ia64die_chain; -static DEFINE_SPINLOCK(die_notifier_lock); -int register_die_notifier(struct notifier_block *nb) +int +register_die_notifier(struct notifier_block *nb) { - int err = 0; - unsigned long flags; - spin_lock_irqsave(&die_notifier_lock, flags); - err = notifier_chain_register(&ia64die_chain, nb); - spin_unlock_irqrestore(&die_notifier_lock, flags); - return err; + return notifier_chain_register(&ia64die_chain, nb); } +EXPORT_SYMBOL_GPL(register_die_notifier); + +int +unregister_die_notifier(struct notifier_block *nb) +{ + return notifier_chain_unregister(&ia64die_chain, nb); +} +EXPORT_SYMBOL_GPL(unregister_die_notifier); void __init trap_init (void) @@ -105,6 +108,7 @@ die (const char *str, struct pt_regs *regs, long err) if (++die.lock_owner_depth < 3) { printk("%s[%d]: %s %ld [%d]\n", current->comm, current->pid, str, err, ++die_counter); + (void) notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV); show_regs(regs); } else printk(KERN_ERR "Recursive die() failure, output suppressed\n"); @@ -155,9 +159,8 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs) switch (break_num) { case 0: /* unknown error (used by GCC for __builtin_abort()) */ if (notify_die(DIE_BREAK, "break 0", regs, break_num, TRAP_BRKPT, SIGTRAP) - == NOTIFY_STOP) { + == NOTIFY_STOP) return; - } die_if_kernel("bugcheck!", regs, break_num); sig = SIGILL; code = ILL_ILLOPC; break; @@ -210,15 +213,6 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs) sig = SIGILL; code = __ILL_BNDMOD; break; - case 0x80200: - case 0x80300: - if (notify_die(DIE_BREAK, "kprobe", regs, break_num, TRAP_BRKPT, SIGTRAP) - == NOTIFY_STOP) { - return; - } - sig = SIGTRAP; code = TRAP_BRKPT; - break; - default: if (break_num < 0x40000 || break_num > 0x100000) die_if_kernel("Bad break", regs, break_num); @@ -226,6 +220,9 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs) if (break_num < 0x80000) { sig = SIGILL; code = __ILL_BREAK; } else { + if (notify_die(DIE_BREAK, "bad break", regs, break_num, TRAP_BRKPT, SIGTRAP) + == NOTIFY_STOP) + return; sig = SIGTRAP; code = TRAP_BRKPT; } } @@ -578,12 +575,11 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, #endif break; case 35: siginfo.si_code = TRAP_BRANCH; ifa = 0; break; - case 36: - if (notify_die(DIE_SS, "ss", ®s, vector, - vector, SIGTRAP) == NOTIFY_STOP) - return; - siginfo.si_code = TRAP_TRACE; ifa = 0; break; + case 36: siginfo.si_code = TRAP_TRACE; ifa = 0; break; } + if (notify_die(DIE_FAULT, "ia64_fault", ®s, vector, siginfo.si_code, SIGTRAP) + == NOTIFY_STOP) + return; siginfo.si_signo = SIGTRAP; siginfo.si_errno = 0; siginfo.si_addr = (void __user *) ifa; diff --git a/include/asm-ia64/kdebug.h b/include/asm-ia64/kdebug.h index 4d376e1663f..8b01a083dde 100644 --- a/include/asm-ia64/kdebug.h +++ b/include/asm-ia64/kdebug.h @@ -22,6 +22,9 @@ * 2005-Apr Rusty Lynch and Anil S Keshavamurthy * adopted from * include/asm-x86_64/kdebug.h + * + * 2005-Oct Keith Owens . Expand notify_die to cover more + * events. */ #include @@ -35,13 +38,36 @@ struct die_args { int signr; }; -int register_die_notifier(struct notifier_block *nb); +extern int register_die_notifier(struct notifier_block *); +extern int unregister_die_notifier(struct notifier_block *); extern struct notifier_block *ia64die_chain; enum die_val { DIE_BREAK = 1, - DIE_SS, + DIE_FAULT, + DIE_OOPS, DIE_PAGE_FAULT, + DIE_MACHINE_HALT, + DIE_MACHINE_RESTART, + DIE_MCA_MONARCH_ENTER, + DIE_MCA_MONARCH_PROCESS, + DIE_MCA_MONARCH_LEAVE, + DIE_MCA_SLAVE_ENTER, + DIE_MCA_SLAVE_PROCESS, + DIE_MCA_SLAVE_LEAVE, + DIE_MCA_RENDZVOUS_ENTER, + DIE_MCA_RENDZVOUS_PROCESS, + DIE_MCA_RENDZVOUS_LEAVE, + DIE_INIT_MONARCH_ENTER, + DIE_INIT_MONARCH_PROCESS, + DIE_INIT_MONARCH_LEAVE, + DIE_INIT_SLAVE_ENTER, + DIE_INIT_SLAVE_PROCESS, + DIE_INIT_SLAVE_LEAVE, + DIE_KDEBUG_ENTER, + DIE_KDEBUG_LEAVE, + DIE_KDUMP_ENTER, + DIE_KDUMP_LEAVE, }; static inline int notify_die(enum die_val val, char *str, struct pt_regs *regs, -- cgit v1.2.3 From 9b1283bedd6b8fe2f4dfc47705d6cea1b5e2d853 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 7 Nov 2005 21:01:06 +0000 Subject: [ARM] Add support for Realview with MPcore tile Add uniprocessor support for Realview platform fitted with the MPcore (SMP) tile. Signed-off-by: Russell King --- arch/arm/mach-realview/Kconfig | 9 ++++++ arch/arm/mach-realview/realview_eb.c | 5 +++ include/asm-arm/arch-realview/platform.h | 55 ++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig index 4b63dc9eabf..129976866d4 100644 --- a/arch/arm/mach-realview/Kconfig +++ b/arch/arm/mach-realview/Kconfig @@ -8,4 +8,13 @@ config MACH_REALVIEW_EB help Include support for the ARM(R) RealView Emulation Baseboard platform. +config REALVIEW_MPCORE + bool "Support MPcore tile" + depends on MACH_REALVIEW_EB + help + Enable support for the MPCore tile on the Realview platform. + Since there are device address and interrupt differences, a + kernel built with this option enabled is not compatible with + other tiles. + endmenu diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index 267bb07e39b..7dc32503fdf 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -136,6 +136,11 @@ static struct amba_device *amba_devs[] __initdata = { static void __init gic_init_irq(void) { +#ifdef CONFIG_REALVIEW_MPCORE + writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK)); + writel(0x008003c0, __io_address(REALVIEW_SYS_BASE) + 0xd8); + writel(0x00000000, __io_address(REALVIEW_SYS_LOCK)); +#endif gic_dist_init(__io_address(REALVIEW_GIC_DIST_BASE)); gic_cpu_init(__io_address(REALVIEW_GIC_CPU_BASE)); } diff --git a/include/asm-arm/arch-realview/platform.h b/include/asm-arm/arch-realview/platform.h index 4b6de13a6b9..432260121c8 100644 --- a/include/asm-arm/arch-realview/platform.h +++ b/include/asm-arm/arch-realview/platform.h @@ -203,8 +203,13 @@ /* Reserved 0x1001A000 - 0x1001FFFF */ #define REALVIEW_CLCD_BASE 0x10020000 /* CLCD */ #define REALVIEW_DMAC_BASE 0x10030000 /* DMA controller */ +#ifndef CONFIG_REALVIEW_MPCORE #define REALVIEW_GIC_CPU_BASE 0x10040000 /* Generic interrupt controller CPU interface */ #define REALVIEW_GIC_DIST_BASE 0x10041000 /* Generic interrupt controller distributor */ +#else +#define REALVIEW_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */ +#define REALVIEW_GIC_DIST_BASE 0x10101000 /* Generic interrupt controller distributor */ +#endif #define REALVIEW_SMC_BASE 0x10080000 /* SMC */ /* Reserved 0x10090000 - 0x100EFFFF */ @@ -265,6 +270,7 @@ * Interrupts - bit assignment (primary) * ------------------------------------------------------------------------ */ +#ifndef CONFIG_REALVIEW_MPCORE #define INT_WDOGINT 0 /* Watchdog timer */ #define INT_SOFTINT 1 /* Software interrupt */ #define INT_COMMRx 2 /* Debug Comm Rx interrupt */ @@ -297,6 +303,55 @@ #define INT_USB 29 /* USB controller */ #define INT_TSPENINT 30 /* Touchscreen pen */ #define INT_TSKPADINT 31 /* Touchscreen keypad */ +#else +#define INT_LOCALTIMER 29 +#define INT_LOCALWDOG 30 + +#define INT_AACI 0 +#define INT_TIMERINT0_1 1 +#define INT_TIMERINT2_3 2 +#define INT_USB 3 +#define INT_UARTINT0 4 +#define INT_UARTINT1 5 +#define INT_RTCINT 6 +#define INT_KMI0 7 +#define INT_KMI1 8 +#define INT_ETH 9 +#define INT_EB_IRQ1 10 /* main GIC */ +#define INT_EB_IRQ2 11 /* tile GIC */ +#define INT_EB_FIQ1 12 /* main GIC */ +#define INT_EB_FIQ2 13 /* tile GIC */ +#define INT_MMCI0A 14 +#define INT_MMCI0B 15 + +#define INT_PMU_CPU0 17 +#define INT_PMU_CPU1 18 +#define INT_PMU_CPU2 19 +#define INT_PMU_CPU3 20 +#define INT_PMU_SCU0 21 +#define INT_PMU_SCU1 22 +#define INT_PMU_SCU2 23 +#define INT_PMU_SCU3 24 +#define INT_PMU_SCU4 25 +#define INT_PMU_SCU5 26 +#define INT_PMU_SCU6 27 +#define INT_PMU_SCU7 28 + +#define INT_L220_EVENT 29 +#define INT_L220_SLAVE 30 +#define INT_L220_DECODE 31 + +#define INT_UARTINT2 -1 +#define INT_UARTINT3 -1 +#define INT_CLCDINT -1 +#define INT_DMAINT -1 +#define INT_WDOGINT -1 +#define INT_GPIOINT0 -1 +#define INT_GPIOINT1 -1 +#define INT_GPIOINT2 -1 +#define INT_SCIINT -1 +#define INT_SSPINT -1 +#endif /* * Interrupt bit positions -- cgit v1.2.3 From 862184fe013146a0d9654a5598c5a2691747541c Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 7 Nov 2005 21:05:42 +0000 Subject: [ARM SMP] Add Realview MPcore SMP support Add SMP support for the MPcore tile fitted to the Realview ARM platform. Signed-off-by: Russell King --- arch/arm/mach-realview/Makefile | 1 + arch/arm/mach-realview/headsmp.S | 39 ++++++ arch/arm/mach-realview/platsmp.c | 195 ++++++++++++++++++++++++++++ arch/arm/mm/proc-v6.S | 18 +++ include/asm-arm/arch-realview/entry-macro.S | 14 ++ include/asm-arm/arch-realview/platform.h | 1 + include/asm-arm/arch-realview/smp.h | 31 +++++ include/asm-arm/hardware/arm_scu.h | 13 ++ 8 files changed, 312 insertions(+) create mode 100644 arch/arm/mach-realview/headsmp.S create mode 100644 arch/arm/mach-realview/platsmp.c create mode 100644 include/asm-arm/arch-realview/smp.h create mode 100644 include/asm-arm/hardware/arm_scu.h diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile index 8d37ea1605f..011a85c1062 100644 --- a/arch/arm/mach-realview/Makefile +++ b/arch/arm/mach-realview/Makefile @@ -4,3 +4,4 @@ obj-y := core.o clock.o obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o +obj-$(CONFIG_SMP) += platsmp.o headsmp.o diff --git a/arch/arm/mach-realview/headsmp.S b/arch/arm/mach-realview/headsmp.S new file mode 100644 index 00000000000..4075473cf68 --- /dev/null +++ b/arch/arm/mach-realview/headsmp.S @@ -0,0 +1,39 @@ +/* + * linux/arch/arm/mach-realview/headsmp.S + * + * Copyright (c) 2003 ARM Limited + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include + + __INIT + +/* + * Realview specific entry point for secondary CPUs. This provides + * a "holding pen" into which all secondary cores are held until we're + * ready for them to initialise. + */ +ENTRY(realview_secondary_startup) + mrc p15, 0, r0, c0, c0, 5 + and r0, r0, #15 + adr r4, 1f + ldmia r4, {r5, r6} + sub r4, r4, r5 + add r6, r6, r4 +pen: ldr r7, [r6] + cmp r7, r0 + bne pen + + /* + * we've been released from the holding pen: secondary_stack + * should now contain the SVC stack for this core + */ + b secondary_startup + +1: .long . + .long pen_release diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c new file mode 100644 index 00000000000..9844644d0fb --- /dev/null +++ b/arch/arm/mach-realview/platsmp.c @@ -0,0 +1,195 @@ +/* + * linux/arch/arm/mach-realview/platsmp.c + * + * Copyright (C) 2002 ARM Ltd. + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "core.h" + +extern void realview_secondary_startup(void); + +/* + * control for which core is the next to come out of the secondary + * boot "holding pen" + */ +volatile int __cpuinitdata pen_release = -1; + +static unsigned int __init get_core_count(void) +{ + unsigned int ncores; + + ncores = __raw_readl(IO_ADDRESS(REALVIEW_MPCORE_SCU_BASE) + SCU_CONFIG); + + return (ncores & 0x03) + 1; +} + +static DEFINE_SPINLOCK(boot_lock); + +void __cpuinit platform_secondary_init(unsigned int cpu) +{ + /* + * the primary core may have used a "cross call" soft interrupt + * to get this processor out of WFI in the BootMonitor - make + * sure that we are no longer being sent this soft interrupt + */ + smp_cross_call_done(cpumask_of_cpu(cpu)); + + /* + * if any interrupts are already enabled for the primary + * core (e.g. timer irq), then they will not have been enabled + * for us: do so + */ + gic_cpu_init(__io_address(REALVIEW_GIC_CPU_BASE)); + + /* + * let the primary processor know we're out of the + * pen, then head off into the C entry point + */ + pen_release = -1; + + /* + * Synchronise with the boot thread. + */ + spin_lock(&boot_lock); + spin_unlock(&boot_lock); +} + +int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + unsigned long timeout; + + /* + * set synchronisation state between this boot processor + * and the secondary one + */ + spin_lock(&boot_lock); + + /* + * The secondary processor is waiting to be released from + * the holding pen - release it, then wait for it to flag + * that it has been released by resetting pen_release. + * + * Note that "pen_release" is the hardware CPU ID, whereas + * "cpu" is Linux's internal ID. + */ + pen_release = cpu; + flush_cache_all(); + + /* + * XXX + * + * This is a later addition to the booting protocol: the + * bootMonitor now puts secondary cores into WFI, so + * poke_milo() no longer gets the cores moving; we need + * to send a soft interrupt to wake the secondary core. + * Use smp_cross_call() for this, since there's little + * point duplicating the code here + */ + smp_cross_call(cpumask_of_cpu(cpu)); + + timeout = jiffies + (1 * HZ); + while (time_before(jiffies, timeout)) { + if (pen_release == -1) + break; + + udelay(10); + } + + /* + * now the secondary core is starting up let it run its + * calibrations, then wait for it to finish + */ + spin_unlock(&boot_lock); + + return pen_release != -1 ? -ENOSYS : 0; +} + +static void __init poke_milo(void) +{ + extern void secondary_startup(void); + + /* nobody is to be released from the pen yet */ + pen_release = -1; + + /* + * write the address of secondary startup into the system-wide + * flags register, then clear the bottom two bits, which is what + * BootMonitor is waiting for + */ +#if 1 +#define REALVIEW_SYS_FLAGSS_OFFSET 0x30 + __raw_writel(virt_to_phys(realview_secondary_startup), + (IO_ADDRESS(REALVIEW_SYS_BASE) + + REALVIEW_SYS_FLAGSS_OFFSET)); +#define REALVIEW_SYS_FLAGSC_OFFSET 0x34 + __raw_writel(3, + (IO_ADDRESS(REALVIEW_SYS_BASE) + + REALVIEW_SYS_FLAGSC_OFFSET)); +#endif + + mb(); +} + +void __init smp_prepare_cpus(unsigned int max_cpus) +{ + unsigned int ncores = get_core_count(); + unsigned int cpu = smp_processor_id(); + int i; + + /* sanity check */ + if (ncores == 0) { + printk(KERN_ERR + "Realview: strange CM count of 0? Default to 1\n"); + + ncores = 1; + } + + if (ncores > NR_CPUS) { + printk(KERN_WARNING + "Realview: no. of cores (%d) greater than configured " + "maximum of %d - clipping\n", + ncores, NR_CPUS); + ncores = NR_CPUS; + } + + smp_store_cpu_info(cpu); + + /* + * are we trying to boot more cores than exist? + */ + if (max_cpus > ncores) + max_cpus = ncores; + + /* + * Initialise the possible/present maps. + * cpu_possible_map describes the set of CPUs which may be present + * cpu_present_map describes the set of CPUs populated + */ + for (i = 0; i < max_cpus; i++) { + cpu_set(i, cpu_possible_map); + cpu_set(i, cpu_present_map); + } + + /* + * Do we need any more CPUs? If so, then let them know where + * to start. Note that, on modern versions of MILO, the "poke" + * doesn't actually do anything until each individual core is + * sent a soft interrupt to get it out of WFI + */ + if (max_cpus > 1) + poke_milo(); +} diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index a39d8fa2ede..92f3ca31b7b 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -194,6 +195,23 @@ cpu_v6_name: * - cache type register is implemented */ __v6_setup: +#ifdef CONFIG_SMP + /* Set up the SCU on core 0 only */ + mrc p15, 0, r0, c0, c0, 5 @ CPU core number + ands r0, r0, #15 + moveq r0, #0x10000000 @ SCU_BASE + orreq r0, r0, #0x00100000 + ldreq r5, [r0, #SCU_CTRL] + orreq r5, r5, #1 + streq r5, [r0, #SCU_CTRL] + +#ifndef CONFIG_CPU_DCACHE_DISABLE + mrc p15, 0, r0, c1, c0, 1 @ Enable SMP/nAMP mode + orr r0, r0, #0x20 + mcr p15, 0, r0, c1, c0, 1 +#endif +#endif + mov r0, #0 mcr p15, 0, r0, c7, c14, 0 @ clean+invalidate D cache mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache diff --git a/include/asm-arm/arch-realview/entry-macro.S b/include/asm-arm/arch-realview/entry-macro.S index 2712ba77bb3..4df469bf42e 100644 --- a/include/asm-arm/arch-realview/entry-macro.S +++ b/include/asm-arm/arch-realview/entry-macro.S @@ -47,3 +47,17 @@ cmpcs \irqnr, \irqnr .endm + + /* We assume that irqstat (the raw value of the IRQ acknowledge + * register) is preserved from the macro above. + * If there is an IPI, we immediately signal end of interrupt on the + * controller, since this requires the original irqstat value which + * we won't easily be able to recreate later. + */ + + .macro test_for_ipi, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + cmp \irqnr, #16 + strcc \irqstat, [\base, #GIC_CPU_EOI] + cmpcs \irqnr, \irqnr + .endm diff --git a/include/asm-arm/arch-realview/platform.h b/include/asm-arm/arch-realview/platform.h index 432260121c8..aef9b36b3c3 100644 --- a/include/asm-arm/arch-realview/platform.h +++ b/include/asm-arm/arch-realview/platform.h @@ -207,6 +207,7 @@ #define REALVIEW_GIC_CPU_BASE 0x10040000 /* Generic interrupt controller CPU interface */ #define REALVIEW_GIC_DIST_BASE 0x10041000 /* Generic interrupt controller distributor */ #else +#define REALVIEW_MPCORE_SCU_BASE 0x10100000 /* SCU registers */ #define REALVIEW_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */ #define REALVIEW_GIC_DIST_BASE 0x10101000 /* Generic interrupt controller distributor */ #endif diff --git a/include/asm-arm/arch-realview/smp.h b/include/asm-arm/arch-realview/smp.h new file mode 100644 index 00000000000..fc87783e8e8 --- /dev/null +++ b/include/asm-arm/arch-realview/smp.h @@ -0,0 +1,31 @@ +#ifndef ASMARM_ARCH_SMP_H +#define ASMARM_ARCH_SMP_H + +#include + +#include + +#define hard_smp_processor_id() \ + ({ \ + unsigned int cpunum; \ + __asm__("mrc p15, 0, %0, c0, c0, 5" \ + : "=r" (cpunum)); \ + cpunum &= 0x0F; \ + }) + +/* + * We use IRQ1 as the IPI + */ +static inline void smp_cross_call(cpumask_t callmap) +{ + gic_raise_softirq(callmap, 1); +} + +/* + * Do nothing on MPcore. + */ +static inline void smp_cross_call_done(cpumask_t callmap) +{ +} + +#endif diff --git a/include/asm-arm/hardware/arm_scu.h b/include/asm-arm/hardware/arm_scu.h new file mode 100644 index 00000000000..9903f60c84b --- /dev/null +++ b/include/asm-arm/hardware/arm_scu.h @@ -0,0 +1,13 @@ +#ifndef ASMARM_HARDWARE_ARM_SCU_H +#define ASMARM_HARDWARE_ARM_SCU_H + +/* + * SCU registers + */ +#define SCU_CTRL 0x00 +#define SCU_CONFIG 0x04 +#define SCU_CPU_STATUS 0x08 +#define SCU_INVALIDATE 0x0c +#define SCU_FPGA_REVISION 0x10 + +#endif -- cgit v1.2.3 From 06c03cac9487555478c7d80065ebf7818bf6fd06 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 7 Nov 2005 21:12:07 +0000 Subject: [ARM] 3117/1: nwfpe kernel memory info leak Patch from Lennert Buytenhek The routine that nwfpe uses for converting floats/doubles to extended precision fails to zero two bytes of kernel stack. This is not immediately obvious, as the floatx80 structure has 16 bits of implicit padding (by design.) These two bytes are copied to userspace when an stfe is emulated, causing a possible info leak. Make the padding explicit and zero it out in the relevant places. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- arch/arm/nwfpe/fpopcode.c | 16 ++++++++-------- arch/arm/nwfpe/softfloat-specialize | 1 + arch/arm/nwfpe/softfloat.c | 6 ++++++ arch/arm/nwfpe/softfloat.h | 1 + 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/arch/arm/nwfpe/fpopcode.c b/arch/arm/nwfpe/fpopcode.c index 4c9f5703148..67ff2ab08ea 100644 --- a/arch/arm/nwfpe/fpopcode.c +++ b/arch/arm/nwfpe/fpopcode.c @@ -29,14 +29,14 @@ #ifdef CONFIG_FPE_NWFPE_XP const floatx80 floatx80Constant[] = { - {0x0000, 0x0000000000000000ULL}, /* extended 0.0 */ - {0x3fff, 0x8000000000000000ULL}, /* extended 1.0 */ - {0x4000, 0x8000000000000000ULL}, /* extended 2.0 */ - {0x4000, 0xc000000000000000ULL}, /* extended 3.0 */ - {0x4001, 0x8000000000000000ULL}, /* extended 4.0 */ - {0x4001, 0xa000000000000000ULL}, /* extended 5.0 */ - {0x3ffe, 0x8000000000000000ULL}, /* extended 0.5 */ - {0x4002, 0xa000000000000000ULL} /* extended 10.0 */ + { .high = 0x0000, .low = 0x0000000000000000ULL},/* extended 0.0 */ + { .high = 0x3fff, .low = 0x8000000000000000ULL},/* extended 1.0 */ + { .high = 0x4000, .low = 0x8000000000000000ULL},/* extended 2.0 */ + { .high = 0x4000, .low = 0xc000000000000000ULL},/* extended 3.0 */ + { .high = 0x4001, .low = 0x8000000000000000ULL},/* extended 4.0 */ + { .high = 0x4001, .low = 0xa000000000000000ULL},/* extended 5.0 */ + { .high = 0x3ffe, .low = 0x8000000000000000ULL},/* extended 0.5 */ + { .high = 0x4002, .low = 0xa000000000000000ULL},/* extended 10.0 */ }; #endif diff --git a/arch/arm/nwfpe/softfloat-specialize b/arch/arm/nwfpe/softfloat-specialize index acf40914476..d4a4c8e0663 100644 --- a/arch/arm/nwfpe/softfloat-specialize +++ b/arch/arm/nwfpe/softfloat-specialize @@ -332,6 +332,7 @@ static floatx80 commonNaNToFloatx80( commonNaNT a ) z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; + z.__padding = 0; return z; } diff --git a/arch/arm/nwfpe/softfloat.c b/arch/arm/nwfpe/softfloat.c index f9f049132a1..0f9656e482b 100644 --- a/arch/arm/nwfpe/softfloat.c +++ b/arch/arm/nwfpe/softfloat.c @@ -531,6 +531,7 @@ INLINE floatx80 packFloatx80( flag zSign, int32 zExp, bits64 zSig ) z.low = zSig; z.high = ( ( (bits16) zSign )<<15 ) + zExp; + z.__padding = 0; return z; } @@ -2831,6 +2832,7 @@ static floatx80 subFloatx80Sigs( struct roundingData *roundData, floatx80 a, flo roundData->exception |= float_flag_invalid; z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; + z.__padding = 0; return z; } if ( aExp == 0 ) { @@ -2950,6 +2952,7 @@ floatx80 floatx80_mul( struct roundingData *roundData, floatx80 a, floatx80 b ) roundData->exception |= float_flag_invalid; z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; + z.__padding = 0; return z; } return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); @@ -3015,6 +3018,7 @@ floatx80 floatx80_div( struct roundingData *roundData, floatx80 a, floatx80 b ) roundData->exception |= float_flag_invalid; z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; + z.__padding = 0; return z; } roundData->exception |= float_flag_divbyzero; @@ -3093,6 +3097,7 @@ floatx80 floatx80_rem( struct roundingData *roundData, floatx80 a, floatx80 b ) roundData->exception |= float_flag_invalid; z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; + z.__padding = 0; return z; } normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); @@ -3184,6 +3189,7 @@ floatx80 floatx80_sqrt( struct roundingData *roundData, floatx80 a ) roundData->exception |= float_flag_invalid; z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; + z.__padding = 0; return z; } if ( aExp == 0 ) { diff --git a/arch/arm/nwfpe/softfloat.h b/arch/arm/nwfpe/softfloat.h index 14151700b6b..1301d97e037 100644 --- a/arch/arm/nwfpe/softfloat.h +++ b/arch/arm/nwfpe/softfloat.h @@ -55,6 +55,7 @@ typedef unsigned long int float32; typedef unsigned long long float64; typedef struct { unsigned short high; + unsigned short __padding; unsigned long long low; } floatx80; -- cgit v1.2.3 From bedf142b8bba4331ed93161292a4ce4f8cde7308 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 7 Nov 2005 21:12:08 +0000 Subject: [ARM] 3118/1: fix and reenable nwfpe extended precision emulation for big-endian Patch from Lennert Buytenhek nwfpe extended precision emulation used to be broken on big-endian and was therefore disabled. This patch fixes nwfpe so that it copies extended precision floats to/from userspace in the proper word order (similar to patch #2046, see the description of that patch for an explanation) and reenables the Kconfig option. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- arch/arm/Kconfig | 2 +- arch/arm/nwfpe/fpa11.h | 2 +- arch/arm/nwfpe/fpa11_cpdt.c | 10 ++++++++++ arch/arm/nwfpe/softfloat.h | 15 ++++++++++----- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 296bc03d1cf..056adc8a7d3 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -585,7 +585,7 @@ config FPE_NWFPE config FPE_NWFPE_XP bool "Support extended precision" - depends on FPE_NWFPE && !CPU_BIG_ENDIAN + depends on FPE_NWFPE help Say Y to include 80-bit support in the kernel floating-point emulator. Otherwise, only 32 and 64-bit support is compiled in. diff --git a/arch/arm/nwfpe/fpa11.h b/arch/arm/nwfpe/fpa11.h index 9677ae8448e..da4c616b6c4 100644 --- a/arch/arm/nwfpe/fpa11.h +++ b/arch/arm/nwfpe/fpa11.h @@ -60,7 +60,7 @@ typedef union tagFPREG { #ifdef CONFIG_FPE_NWFPE_XP floatx80 fExtended; #else - int padding[3]; + u32 padding[3]; #endif } FPREG; diff --git a/arch/arm/nwfpe/fpa11_cpdt.c b/arch/arm/nwfpe/fpa11_cpdt.c index b0db5cbcc3b..32859fa8dcf 100644 --- a/arch/arm/nwfpe/fpa11_cpdt.c +++ b/arch/arm/nwfpe/fpa11_cpdt.c @@ -59,8 +59,13 @@ static inline void loadExtended(const unsigned int Fn, const unsigned int __user p = (unsigned int *) &fpa11->fpreg[Fn].fExtended; fpa11->fType[Fn] = typeExtended; get_user(p[0], &pMem[0]); /* sign & exponent */ +#ifdef __ARMEB__ + get_user(p[1], &pMem[1]); /* ms bits */ + get_user(p[2], &pMem[2]); /* ls bits */ +#else get_user(p[1], &pMem[2]); /* ls bits */ get_user(p[2], &pMem[1]); /* ms bits */ +#endif } #endif @@ -177,8 +182,13 @@ static inline void storeExtended(const unsigned int Fn, unsigned int __user *pMe } put_user(val.i[0], &pMem[0]); /* sign & exp */ +#ifdef __ARMEB__ + put_user(val.i[1], &pMem[1]); /* msw */ + put_user(val.i[2], &pMem[2]); +#else put_user(val.i[1], &pMem[2]); put_user(val.i[2], &pMem[1]); /* msw */ +#endif } #endif diff --git a/arch/arm/nwfpe/softfloat.h b/arch/arm/nwfpe/softfloat.h index 1301d97e037..978c699673c 100644 --- a/arch/arm/nwfpe/softfloat.h +++ b/arch/arm/nwfpe/softfloat.h @@ -51,12 +51,17 @@ input or output the `floatx80' type will be defined. Software IEC/IEEE floating-point types. ------------------------------------------------------------------------------- */ -typedef unsigned long int float32; -typedef unsigned long long float64; +typedef u32 float32; +typedef u64 float64; typedef struct { - unsigned short high; - unsigned short __padding; - unsigned long long low; +#ifdef __ARMEB__ + u16 __padding; + u16 high; +#else + u16 high; + u16 __padding; +#endif + u64 low; } floatx80; /* -- cgit v1.2.3 From 5391473f7be88748ec248e0e70f1a4430a03eb52 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 7 Nov 2005 21:12:09 +0000 Subject: [ARM] 3121/1: unconditionally use XCB=101 on ixp2000 Patch from Lennert Buytenhek Since we have to use XCB=101 instead of XCB=000 on the ixp2400 to prevent it from regularly falling over, and since we have to deal with manual write buffer flushing because of that, we might as well use XCB=101 on all ixp2000 platforms since it's faster than XCB=000. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- arch/arm/mach-ixp2000/core.c | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c index df140962bb0..6851abaf552 100644 --- a/arch/arm/mach-ixp2000/core.c +++ b/arch/arm/mach-ixp2000/core.c @@ -84,63 +84,54 @@ static struct map_desc ixp2000_io_desc[] __initdata = { .virtual = IXP2000_CAP_VIRT_BASE, .pfn = __phys_to_pfn(IXP2000_CAP_PHYS_BASE), .length = IXP2000_CAP_SIZE, - .type = MT_DEVICE + .type = MT_IXP2000_DEVICE, }, { .virtual = IXP2000_INTCTL_VIRT_BASE, .pfn = __phys_to_pfn(IXP2000_INTCTL_PHYS_BASE), .length = IXP2000_INTCTL_SIZE, - .type = MT_DEVICE + .type = MT_IXP2000_DEVICE, }, { .virtual = IXP2000_PCI_CREG_VIRT_BASE, .pfn = __phys_to_pfn(IXP2000_PCI_CREG_PHYS_BASE), .length = IXP2000_PCI_CREG_SIZE, - .type = MT_DEVICE + .type = MT_IXP2000_DEVICE, }, { .virtual = IXP2000_PCI_CSR_VIRT_BASE, .pfn = __phys_to_pfn(IXP2000_PCI_CSR_PHYS_BASE), .length = IXP2000_PCI_CSR_SIZE, - .type = MT_DEVICE + .type = MT_IXP2000_DEVICE, }, { .virtual = IXP2000_MSF_VIRT_BASE, .pfn = __phys_to_pfn(IXP2000_MSF_PHYS_BASE), .length = IXP2000_MSF_SIZE, - .type = MT_DEVICE + .type = MT_IXP2000_DEVICE, }, { .virtual = IXP2000_PCI_IO_VIRT_BASE, .pfn = __phys_to_pfn(IXP2000_PCI_IO_PHYS_BASE), .length = IXP2000_PCI_IO_SIZE, - .type = MT_DEVICE + .type = MT_IXP2000_DEVICE, }, { .virtual = IXP2000_PCI_CFG0_VIRT_BASE, .pfn = __phys_to_pfn(IXP2000_PCI_CFG0_PHYS_BASE), .length = IXP2000_PCI_CFG0_SIZE, - .type = MT_DEVICE + .type = MT_IXP2000_DEVICE, }, { .virtual = IXP2000_PCI_CFG1_VIRT_BASE, .pfn = __phys_to_pfn(IXP2000_PCI_CFG1_PHYS_BASE), .length = IXP2000_PCI_CFG1_SIZE, - .type = MT_DEVICE + .type = MT_IXP2000_DEVICE, } }; void __init ixp2000_map_io(void) { - extern unsigned int processor_id; - /* - * On IXP2400 CPUs we need to use MT_IXP2000_DEVICE for - * tweaking the PMDs so XCB=101. On IXP2800s we use the normal - * PMD flags. + * On IXP2400 CPUs we need to use MT_IXP2000_DEVICE so that + * XCB=101 (to avoid triggering erratum #66), and given that + * this mode speeds up I/O accesses and we have write buffer + * flushes in the right places anyway, it doesn't hurt to use + * XCB=101 for all IXP2000s. */ - if ((processor_id & 0xfffffff0) == 0x69054190) { - int i; - - printk(KERN_INFO "Enabling IXP2400 erratum #66 workaround\n"); - - for(i=0;i Date: Mon, 7 Nov 2005 21:22:07 +0000 Subject: [ARM] 3120/1: Fix MMC/SD card driver resume deadlock Patch from Uli Luckas This is a simplification of patch 3116/1 as sugested by Russell King. Signed-off-by: Uli Luckas Signed-off-by: Russell King --- drivers/mmc/mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index ceae379a4d4..da528390acf 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1263,7 +1263,7 @@ EXPORT_SYMBOL(mmc_suspend_host); */ int mmc_resume_host(struct mmc_host *host) { - mmc_detect_change(host, 0); + mmc_rescan(host); return 0; } -- cgit v1.2.3 From f6db449ca312d33045907337b68de1f647cf0730 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 7 Nov 2005 21:30:21 +0000 Subject: [ARM] Allow SMP if Realview MPcore is selected This patch puts into place the final piece of the puzzle for SMP support on ARM. Signed-off-by: Russell King --- arch/arm/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 056adc8a7d3..91d5ef3397b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -324,7 +324,7 @@ menu "Kernel Features" config SMP bool "Symmetric Multi-Processing (EXPERIMENTAL)" - depends on EXPERIMENTAL && BROKEN #&& n + depends on EXPERIMENTAL && REALVIEW_MPCORE help This enables support for systems with more than one CPU. If you have a system with only one CPU, like most personal computers, say N. If -- cgit v1.2.3 From ee1858d3122dedd2e82a61b6ab56b229aefd9447 Mon Sep 17 00:00:00 2001 From: Lars Kotthoff Date: Mon, 7 Nov 2005 14:08:04 -0800 Subject: [SPARC]: Add sun4m LED driver. This is a forward port of a 2.4.x sun4m LED driver written by Lars Kotthoff. Signed-off-by: Lars Kotthoff Signed-off-by: David S. Miller --- arch/sparc/Kconfig | 8 +++ arch/sparc/kernel/Makefile | 1 + arch/sparc/kernel/led.c | 139 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 arch/sparc/kernel/led.c diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 6537445dac0..3cfb8be3ff6 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -201,6 +201,14 @@ config SUN_OPENPROMFS Only choose N if you know in advance that you will not need to modify OpenPROM settings on the running system. +config SPARC_LED + tristate "Sun4m LED driver" + help + This driver toggles the front-panel LED on sun4m systems + in a user-specifyable manner. It's state can be probed + by reading /proc/led and it's blinking mode can be changed + via writes to /proc/led + source "fs/Kconfig.binfmt" config SUNOS_EMUL diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 3d22ba2af01..1b83e21841b 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_SUN_AUXIO) += auxio.o obj-$(CONFIG_PCI) += ebus.o obj-$(CONFIG_SUN_PM) += apc.o pmc.o obj-$(CONFIG_MODULES) += module.o sparc_ksyms.o +obj-$(CONFIG_SPARC_LED) += led.o ifdef CONFIG_SUNOS_EMUL obj-y += sys_sunos.o sunos_ioctl.o diff --git a/arch/sparc/kernel/led.c b/arch/sparc/kernel/led.c new file mode 100644 index 00000000000..2a3afca453c --- /dev/null +++ b/arch/sparc/kernel/led.c @@ -0,0 +1,139 @@ +#include +#include +#include +#include +#include + +#include + +#define LED_MAX_LENGTH 8 /* maximum chars written to proc file */ + +static inline void led_toggle(void) +{ + unsigned char val = get_auxio(); + unsigned char on, off; + + if (val & AUXIO_LED) { + on = 0; + off = AUXIO_LED; + } else { + on = AUXIO_LED; + off = 0; + } + + set_auxio(on, off); +} + +static struct timer_list led_blink_timer; + +static void led_blink(unsigned long timeout) +{ + led_toggle(); + + /* reschedule */ + if (!timeout) { /* blink according to load */ + led_blink_timer.expires = jiffies + + ((1 + (avenrun[0] >> FSHIFT)) * HZ); + led_blink_timer.data = 0; + } else { /* blink at user specified interval */ + led_blink_timer.expires = jiffies + (timeout * HZ); + led_blink_timer.data = timeout; + } + add_timer(&led_blink_timer); +} + +static int led_read_proc(char *buf, char **start, off_t offset, int count, + int *eof, void *data) +{ + int len = 0; + + if (get_auxio() & AUXIO_LED) + len = sprintf(buf, "on\n"); + else + len = sprintf(buf, "off\n"); + + return len; +} + +static int led_write_proc(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + char *buf = NULL; + + if (count > LED_MAX_LENGTH) + count = LED_MAX_LENGTH; + + buf = kmalloc(sizeof(char) * (count + 1), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + if (copy_from_user(buf, buffer, count)) { + kfree(buf); + return -EFAULT; + } + + buf[count] = '\0'; + + /* work around \n when echo'ing into proc */ + if (buf[count - 1] == '\n') + buf[count - 1] = '\0'; + + /* before we change anything we want to stop any running timers, + * otherwise calls such as on will have no persistent effect + */ + del_timer_sync(&led_blink_timer); + + if (!strcmp(buf, "on")) { + auxio_set_led(AUXIO_LED_ON); + } else if (!strcmp(buf, "toggle")) { + led_toggle(); + } else if ((*buf > '0') && (*buf <= '9')) { + led_blink(simple_strtoul(buf, NULL, 10)); + } else if (!strcmp(buf, "load")) { + led_blink(0); + } else { + auxio_set_led(AUXIO_LED_OFF); + } + + kfree(buf); + + return count; +} + +static struct proc_dir_entry *led; + +#define LED_VERSION "0.1" + +static int __init led_init(void) +{ + init_timer(&led_blink_timer); + led_blink_timer.function = led_blink; + + led = create_proc_entry("led", 0, NULL); + if (!led) + return -ENOMEM; + + led->read_proc = led_read_proc; /* reader function */ + led->write_proc = led_write_proc; /* writer function */ + led->owner = THIS_MODULE; + + printk(KERN_INFO + "led: version %s, Lars Kotthoff \n", + LED_VERSION); + + return 0; +} + +static void __exit led_exit(void) +{ + remove_proc_entry("led", NULL); + del_timer_sync(&led_blink_timer); +} + +module_init(led_init); +module_exit(led_exit); + +MODULE_AUTHOR("Lars Kotthoff "); +MODULE_DESCRIPTION("Provides control of the front LED on SPARC systems."); +MODULE_LICENSE("GPL"); +MODULE_VERSION(LED_VERSION); -- cgit v1.2.3 From 5a820fa7e1a34f12fec4e6766e5c335ae9427028 Mon Sep 17 00:00:00 2001 From: Georg Chini Date: Mon, 7 Nov 2005 14:08:25 -0800 Subject: [SPARC]: Make SBUS dma code similar to EBUS From: Georg Chini Introduce some sbus_dma routines similar to the ebus_dma stuff to make the code look nearly the same for both cases. Thanks to Christopher for testing. Signed-off-by: David S. Miller --- sound/sparc/cs4231.c | 311 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 199 insertions(+), 112 deletions(-) diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index f4361c518e4..110d64d4848 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -61,6 +61,14 @@ MODULE_DESCRIPTION("Sun CS4231"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Sun,CS4231}}"); +#ifdef SBUS_SUPPORT +struct sbus_dma_info { + spinlock_t lock; + int dir; + void __iomem *regs; +}; +#endif + typedef struct snd_cs4231 { spinlock_t lock; void __iomem *port; @@ -69,6 +77,11 @@ typedef struct snd_cs4231 { struct ebus_dma_info eb2p; #endif +#ifdef SBUS_SUPPORT + struct sbus_dma_info sb2c; + struct sbus_dma_info sb2p; +#endif + u32 flags; #define CS4231_FLAG_EBUS 0x00000001 #define CS4231_FLAG_PLAYBACK 0x00000002 @@ -251,6 +264,15 @@ static cs4231_t *cs4231_list; #define APCPNVA 0x38UL /* APC Play DMA Next Address */ #define APCPNC 0x3cUL /* APC Play Next Count */ +/* Defines for SBUS DMA-routines */ + +#define APCVA 0x0UL /* APC DMA Address */ +#define APCC 0x4UL /* APC Count */ +#define APCNVA 0x8UL /* APC DMA Next Address */ +#define APCNC 0xcUL /* APC Next Count */ +#define APC_PLAY 0x30UL /* Play registers start at 0x30 */ +#define APC_RECORD 0x20UL /* Record registers start at 0x20 */ + /* APCCSR bits */ #define APC_INT_PENDING 0x800000 /* Interrupt Pending */ @@ -471,6 +493,103 @@ static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg) return ret; } +/* + * SBUS DMA routines + */ +#ifdef SBUS_SUPPORT + +int sbus_dma_request(struct sbus_dma_info *base, dma_addr_t bus_addr, size_t len) +{ + unsigned long flags; + u32 test, csr; + int err; + + if (len >= (1 << 24)) + return -EINVAL; + spin_lock_irqsave(&base->lock, flags); + csr = sbus_readl(base->regs + APCCSR); + err = -EINVAL; + test = APC_CDMA_READY; + if ( base->dir == APC_PLAY ) + test = APC_PDMA_READY; + if (!(csr & test)) + goto out; + err = -EBUSY; + csr = sbus_readl(base->regs + APCCSR); + test = APC_XINT_CNVA; + if ( base->dir == APC_PLAY ) + test = APC_XINT_PNVA; + if (!(csr & test)) + goto out; + err = 0; + sbus_writel(bus_addr, base->regs + base->dir + APCNVA); + sbus_writel(len, base->regs + base->dir + APCNC); +out: + spin_unlock_irqrestore(&base->lock, flags); + return err; +} + +void sbus_dma_prepare(struct sbus_dma_info *base) +{ + unsigned long flags; + u32 csr, test; + + spin_lock_irqsave(&base->lock, flags); + csr = sbus_readl(base->regs + APCCSR); + test = APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA | + APC_XINT_PLAY | APC_XINT_PEMP | APC_XINT_GENL | + APC_XINT_PENA; + if ( base->dir == APC_RECORD ) + test = APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA | + APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL; + csr |= test; + sbus_writel(csr, base->regs + APCCSR); + spin_unlock_irqrestore(&base->lock, flags); +} + +void sbus_dma_enable(struct sbus_dma_info *base, int on) +{ + unsigned long flags; + u32 csr, shift; + + spin_lock_irqsave(&base->lock, flags); + if (!on) { + if (base->dir == APC_PLAY) { + sbus_writel(0, base->regs + base->dir + APCNVA); + sbus_writel(1, base->regs + base->dir + APCC); + } + else + { + sbus_writel(0, base->regs + base->dir + APCNC); + sbus_writel(0, base->regs + base->dir + APCVA); + } + } + udelay(500); + csr = sbus_readl(base->regs + APCCSR); + shift = 0; + if ( base->dir == APC_PLAY ) + shift = 1; + if (on) + csr &= ~(APC_CPAUSE << shift); + else + csr |= (APC_CPAUSE << shift); + sbus_writel(csr, base->regs + APCCSR); + if (on) + csr |= (APC_CDMA_READY << shift); + else + csr &= ~(APC_CDMA_READY << shift); + sbus_writel(csr, base->regs + APCCSR); + + spin_unlock_irqrestore(&base->lock, flags); +} + +unsigned int sbus_dma_addr(struct sbus_dma_info *base) +{ + return sbus_readl(base->regs + base->dir + APCVA); +} + +#endif + /* * CS4231 detection / MCE routines */ @@ -589,29 +708,21 @@ static void snd_cs4231_ebus_advance_dma(struct ebus_dma_info *p, snd_pcm_substre #endif #ifdef SBUS_SUPPORT -static void snd_cs4231_sbus_advance_dma(snd_pcm_substream_t *substream, unsigned int *periods_sent) +static void snd_cs4231_sbus_advance_dma(struct sbus_dma_info *p, snd_pcm_substream_t *substream, unsigned int *periods_sent) { - cs4231_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; - unsigned int period_size = snd_pcm_lib_period_bytes(substream); - unsigned int offset = period_size * (*periods_sent % runtime->periods); - - if (runtime->period_size > 0xffff + 1) - BUG(); - - switch (substream->stream) { - case SNDRV_PCM_STREAM_PLAYBACK: - sbus_writel(runtime->dma_addr + offset, chip->port + APCPNVA); - sbus_writel(period_size, chip->port + APCPNC); - break; - case SNDRV_PCM_STREAM_CAPTURE: - sbus_writel(runtime->dma_addr + offset, chip->port + APCCNVA); - sbus_writel(period_size, chip->port + APCCNC); - break; - } + while (1) { + unsigned int period_size = snd_pcm_lib_period_bytes(substream); + unsigned int offset = period_size * (*periods_sent); - (*periods_sent) = (*periods_sent + 1) % runtime->periods; + if (period_size > 0xffff + 1) + BUG(); + + if (sbus_dma_request(p, runtime->dma_addr + offset, period_size)) + return; + (*periods_sent) = (*periods_sent + 1) % runtime->periods; + } } #endif @@ -646,59 +757,27 @@ static void cs4231_dma_trigger(snd_pcm_substream_t *substream, unsigned int what } else { #endif #ifdef SBUS_SUPPORT - u32 csr = sbus_readl(chip->port + APCCSR); - /* I don't know why, but on sbus the period counter must - * only start counting after the first period is sent. - * Therefore this dummy thing. - */ - unsigned int dummy = 0; - - switch (what) { - case CS4231_PLAYBACK_ENABLE: + if (what & CS4231_PLAYBACK_ENABLE) { if (on) { - csr &= ~APC_XINT_PLAY; - sbus_writel(csr, chip->port + APCCSR); - - csr &= ~APC_PPAUSE; - sbus_writel(csr, chip->port + APCCSR); - - snd_cs4231_sbus_advance_dma(substream, &dummy); - - csr |= APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA | - APC_XINT_PLAY | APC_XINT_EMPT | APC_XINT_GENL | - APC_XINT_PENA | APC_PDMA_READY; - sbus_writel(csr, chip->port + APCCSR); + sbus_dma_prepare(&chip->sb2p); + sbus_dma_enable(&chip->sb2p, 1); + snd_cs4231_sbus_advance_dma(&chip->sb2p, + chip->playback_substream, + &chip->p_periods_sent); } else { - csr |= APC_PPAUSE; - sbus_writel(csr, chip->port + APCCSR); - - csr &= ~APC_PDMA_READY; - sbus_writel(csr, chip->port + APCCSR); + sbus_dma_enable(&chip->sb2p, 0); } - break; - case CS4231_RECORD_ENABLE: + } + if (what & CS4231_RECORD_ENABLE) { if (on) { - csr &= ~APC_XINT_CAPT; - sbus_writel(csr, chip->port + APCCSR); - - csr &= ~APC_CPAUSE; - sbus_writel(csr, chip->port + APCCSR); - - snd_cs4231_sbus_advance_dma(substream, &dummy); - - csr |= APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA | - APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL | - APC_CDMA_READY; - - sbus_writel(csr, chip->port + APCCSR); + sbus_dma_prepare(&chip->sb2c); + sbus_dma_enable(&chip->sb2c, 1); + snd_cs4231_sbus_advance_dma(&chip->sb2c, + chip->capture_substream, + &chip->c_periods_sent); } else { - csr |= APC_CPAUSE; - sbus_writel(csr, chip->port + APCCSR); - - csr &= ~APC_CDMA_READY; - sbus_writel(csr, chip->port + APCCSR); + sbus_dma_enable(&chip->sb2c, 0); } - break; } #endif #ifdef EBUS_SUPPORT @@ -1136,10 +1215,7 @@ static int snd_cs4231_playback_prepare(snd_pcm_substream_t *substream) if (runtime->period_size > 0xffff + 1) BUG(); - snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, (runtime->period_size - 1) & 0x00ff); - snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, (runtime->period_size - 1) >> 8 & 0x00ff); chip->p_periods_sent = 0; - spin_unlock_irqrestore(&chip->lock, flags); return 0; @@ -1171,16 +1247,14 @@ static int snd_cs4231_capture_hw_free(snd_pcm_substream_t *substream) static int snd_cs4231_capture_prepare(snd_pcm_substream_t *substream) { cs4231_t *chip = snd_pcm_substream_chip(substream); - snd_pcm_runtime_t *runtime = substream->runtime; unsigned long flags; spin_lock_irqsave(&chip->lock, flags); chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | CS4231_RECORD_PIO); - snd_cs4231_out(chip, CS4231_REC_LWR_CNT, (runtime->period_size - 1) & 0x00ff); - snd_cs4231_out(chip, CS4231_REC_LWR_CNT, (runtime->period_size - 1) >> 8 & 0x00ff); + chip->c_periods_sent = 0; spin_unlock_irqrestore(&chip->lock, flags); return 0; @@ -1199,40 +1273,20 @@ static void snd_cs4231_overrange(cs4231_t *chip) chip->capture_substream->runtime->overrange++; } -static irqreturn_t snd_cs4231_generic_interrupt(cs4231_t *chip) +#ifdef SBUS_SUPPORT +static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs) { unsigned long flags; unsigned char status; + u32 csr; + cs4231_t *chip = dev_id; /*This is IRQ is not raised by the cs4231*/ if (!(__cs4231_readb(chip, CS4231P(chip, STATUS)) & CS4231_GLOBALIRQ)) return IRQ_NONE; - status = snd_cs4231_in(chip, CS4231_IRQ_STATUS); - - if (status & CS4231_TIMER_IRQ) { - if (chip->timer) - snd_timer_interrupt(chip->timer, chip->timer->sticks); - } - - if (status & CS4231_RECORD_IRQ) - snd_cs4231_overrange(chip); - - /* ACK the CS4231 interrupt. */ - spin_lock_irqsave(&chip->lock, flags); - snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0); - spin_unlock_irqrestore(&chip->lock, flags); - - return 0; -} - -#ifdef SBUS_SUPPORT -static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - cs4231_t *chip = dev_id; - /* ACK the APC interrupt. */ - u32 csr = sbus_readl(chip->port + APCCSR); + csr = sbus_readl(chip->port + APCCSR); sbus_writel(csr, chip->port + APCCSR); @@ -1240,20 +1294,36 @@ static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_re (csr & APC_PLAY_INT) && (csr & APC_XINT_PNVA) && !(csr & APC_XINT_EMPT)) { - snd_cs4231_sbus_advance_dma(chip->playback_substream, - &chip->p_periods_sent); snd_pcm_period_elapsed(chip->playback_substream); + snd_cs4231_sbus_advance_dma(&chip->sb2p, chip->playback_substream, + &chip->p_periods_sent); } if ((chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) && (csr & APC_CAPT_INT) && - (csr & APC_XINT_CNVA)) { - snd_cs4231_sbus_advance_dma(chip->capture_substream, - &chip->c_periods_sent); + (csr & APC_XINT_CNVA) && + !(csr & APC_XINT_EMPT)) { snd_pcm_period_elapsed(chip->capture_substream); + snd_cs4231_sbus_advance_dma(&chip->sb2c,chip->capture_substream, + &chip->c_periods_sent); } + + status = snd_cs4231_in(chip, CS4231_IRQ_STATUS); + + if (status & CS4231_TIMER_IRQ) { + if (chip->timer) + snd_timer_interrupt(chip->timer, chip->timer->sticks); + } + + if (status & CS4231_RECORD_IRQ) + snd_cs4231_overrange(chip); - return snd_cs4231_generic_interrupt(chip); + /* ACK the CS4231 interrupt. */ + spin_lock_irqsave(&chip->lock, flags); + snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0); + spin_unlock_irqrestore(&chip->lock, flags); + + return 0; } #endif @@ -1284,24 +1354,29 @@ static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event, static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t *substream) { cs4231_t *chip = snd_pcm_substream_chip(substream); - size_t ptr, residue, period_bytes; - + size_t ptr; +#ifdef EBUS_SUPPORT + size_t residue, period_bytes; +#endif + if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) return 0; +#ifdef EBUS_SUPPORT period_bytes = snd_pcm_lib_period_bytes(substream); ptr = period_bytes * chip->p_periods_sent; -#ifdef EBUS_SUPPORT if (chip->flags & CS4231_FLAG_EBUS) { residue = ebus_dma_residue(&chip->eb2p); + ptr += period_bytes - residue; } else { #endif #ifdef SBUS_SUPPORT - residue = sbus_readl(chip->port + APCPC); + ptr = sbus_dma_addr(&chip->sb2p); + if (ptr != 0) + ptr -= substream->runtime->dma_addr; #endif #ifdef EBUS_SUPPORT } #endif - ptr += period_bytes - residue; return bytes_to_frames(substream->runtime, ptr); } @@ -1309,24 +1384,29 @@ static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t *substr static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substream) { cs4231_t *chip = snd_pcm_substream_chip(substream); - size_t ptr, residue, period_bytes; + size_t ptr; +#ifdef EBUS_SUPPORT + size_t residue, period_bytes; +#endif if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE)) return 0; +#ifdef EBUS_SUPPORT period_bytes = snd_pcm_lib_period_bytes(substream); ptr = period_bytes * chip->c_periods_sent; -#ifdef EBUS_SUPPORT if (chip->flags & CS4231_FLAG_EBUS) { residue = ebus_dma_residue(&chip->eb2c); + ptr += period_bytes - residue; } else { #endif #ifdef SBUS_SUPPORT - residue = sbus_readl(chip->port + APCCC); + ptr = sbus_dma_addr(&chip->sb2c); + if (ptr != 0) + ptr -= substream->runtime->dma_addr; #endif #ifdef EBUS_SUPPORT } #endif - ptr += period_bytes - residue; return bytes_to_frames(substream->runtime, ptr); } @@ -1983,6 +2063,8 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card, return -ENOMEM; spin_lock_init(&chip->lock); + spin_lock_init(&chip->sb2c.lock); + spin_lock_init(&chip->sb2p.lock); init_MUTEX(&chip->mce_mutex); init_MUTEX(&chip->open_mutex); chip->card = card; @@ -1998,6 +2080,11 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card, return -EIO; } + chip->sb2c.regs = chip->port; + chip->sb2p.regs = chip->port; + chip->sb2c.dir = APC_RECORD; + chip->sb2p.dir = APC_PLAY; + if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt, SA_SHIRQ, "cs4231", chip)) { snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %s\n", -- cgit v1.2.3 From b8ae48656db860d4c83a29aa7b0588fc89361935 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 7 Nov 2005 14:08:46 -0800 Subject: [SPARC64] mm: don't re-evaluate *ptep sparc64 prom_callback and new_setup_frame32 each operates on a user page table without holding lock, and no doubt they've good reason. But I'd feel more confident if they were to do a "pte = *ptep" and then operate on pte, rather than re-evaluating *ptep. Signed-off-by: Hugh Dickins Signed-off-by: David S. Miller --- arch/sparc64/kernel/setup.c | 12 ++++++++---- arch/sparc64/kernel/signal32.c | 6 ++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index c1f34237cdf..bf1849dd9c4 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -154,6 +154,7 @@ int prom_callback(long *args) pud_t *pudp; pmd_t *pmdp; pte_t *ptep; + pte_t pte; for_each_process(p) { mm = p->mm; @@ -178,8 +179,9 @@ int prom_callback(long *args) * being called from inside OBP. */ ptep = pte_offset_map(pmdp, va); - if (pte_present(*ptep)) { - tte = pte_val(*ptep); + pte = *ptep; + if (pte_present(pte)) { + tte = pte_val(pte); res = PROM_TRUE; } pte_unmap(ptep); @@ -218,6 +220,7 @@ int prom_callback(long *args) pud_t *pudp; pmd_t *pmdp; pte_t *ptep; + pte_t pte; int error; if ((va >= LOW_OBP_ADDRESS) && (va < HI_OBP_ADDRESS)) { @@ -240,8 +243,9 @@ int prom_callback(long *args) * being called from inside OBP. */ ptep = pte_offset_kernel(pmdp, va); - if (pte_present(*ptep)) { - tte = pte_val(*ptep); + pte = *ptep; + if (pte_present(pte)) { + tte = pte_val(pte); res = PROM_TRUE; } goto done; diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index aecccd0df1d..009a86e5ded 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c @@ -863,6 +863,7 @@ static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, pud_t *pudp = pud_offset(pgdp, address); pmd_t *pmdp = pmd_offset(pudp, address); pte_t *ptep; + pte_t pte; regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2); @@ -873,9 +874,10 @@ static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, preempt_disable(); ptep = pte_offset_map(pmdp, address); - if (pte_present(*ptep)) { + pte = *ptep; + if (pte_present(pte)) { unsigned long page = (unsigned long) - page_address(pte_page(*ptep)); + page_address(pte_page(pte)); wmb(); __asm__ __volatile__("flush %0 + %1" -- cgit v1.2.3 From dedeb0029b9c83420fc1337d4ee53daa7b2a0ad4 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 7 Nov 2005 14:09:01 -0800 Subject: [SPARC64] mm: context switch ptlock sparc64 is unique among architectures in taking the page_table_lock in its context switch (well, cris does too, but erroneously, and it's not yet SMP anyway). This seems to be a private affair between switch_mm and activate_mm, using page_table_lock as a per-mm lock, without any relation to its uses elsewhere. That's fine, but comment it as such; and unlock sooner in switch_mm, more like in activate_mm (preemption is disabled here). There is a block of "if (0)"ed code in smp_flush_tlb_pending which would have liked to rely on the page_table_lock, in switch_mm and elsewhere; but its comment explains how dup_mmap's flush_tlb_mm defeated it. And though that could have been changed at any time over the past few years, now the chance vanishes as we push the page_table_lock downwards, and perhaps split it per page table page. Just delete that block of code. Which leaves the mysterious spin_unlock_wait(&oldmm->page_table_lock) in kernel/fork.c copy_mm. Textual analysis (supported by Nick Piggin) suggests that the comment was written by DaveM, and that it relates to the defeated approach in the sparc64 smp_flush_tlb_pending. Just delete this block too. Signed-off-by: Hugh Dickins Signed-off-by: David S. Miller --- arch/sparc64/kernel/smp.c | 31 +++++--------------------- include/asm-sparc64/mmu_context.h | 46 ++++++++++++++++++++------------------- kernel/fork.c | 7 ------ 3 files changed, 29 insertions(+), 55 deletions(-) diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index b137fd63f5e..a9089e2140e 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -883,34 +883,13 @@ void smp_flush_tlb_pending(struct mm_struct *mm, unsigned long nr, unsigned long u32 ctx = CTX_HWBITS(mm->context); int cpu = get_cpu(); - if (mm == current->active_mm && atomic_read(&mm->mm_users) == 1) { + if (mm == current->active_mm && atomic_read(&mm->mm_users) == 1) mm->cpu_vm_mask = cpumask_of_cpu(cpu); - goto local_flush_and_out; - } else { - /* This optimization is not valid. Normally - * we will be holding the page_table_lock, but - * there is an exception which is copy_page_range() - * when forking. The lock is held during the individual - * page table updates in the parent, but not at the - * top level, which is where we are invoked. - */ - if (0) { - cpumask_t this_cpu_mask = cpumask_of_cpu(cpu); - - /* By virtue of running under the mm->page_table_lock, - * and mmu_context.h:switch_mm doing the same, the - * following operation is safe. - */ - if (cpus_equal(mm->cpu_vm_mask, this_cpu_mask)) - goto local_flush_and_out; - } - } - - smp_cross_call_masked(&xcall_flush_tlb_pending, - ctx, nr, (unsigned long) vaddrs, - mm->cpu_vm_mask); + else + smp_cross_call_masked(&xcall_flush_tlb_pending, + ctx, nr, (unsigned long) vaddrs, + mm->cpu_vm_mask); -local_flush_and_out: __flush_tlb_pending(ctx, nr, vaddrs); put_cpu(); diff --git a/include/asm-sparc64/mmu_context.h b/include/asm-sparc64/mmu_context.h index 87c43c67866..08ba72d7722 100644 --- a/include/asm-sparc64/mmu_context.h +++ b/include/asm-sparc64/mmu_context.h @@ -87,37 +87,35 @@ extern void __flush_tlb_mm(unsigned long, unsigned long); static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk) { unsigned long ctx_valid; + int cpu; + /* Note: page_table_lock is used here to serialize switch_mm + * and activate_mm, and their calls to get_new_mmu_context. + * This use of page_table_lock is unrelated to its other uses. + */ spin_lock(&mm->page_table_lock); - if (CTX_VALID(mm->context)) - ctx_valid = 1; - else - ctx_valid = 0; + ctx_valid = CTX_VALID(mm->context); + if (!ctx_valid) + get_new_mmu_context(mm); + spin_unlock(&mm->page_table_lock); if (!ctx_valid || (old_mm != mm)) { - if (!ctx_valid) - get_new_mmu_context(mm); - load_secondary_context(mm); reload_tlbmiss_state(tsk, mm); } - { - int cpu = smp_processor_id(); - - /* Even if (mm == old_mm) we _must_ check - * the cpu_vm_mask. If we do not we could - * corrupt the TLB state because of how - * smp_flush_tlb_{page,range,mm} on sparc64 - * and lazy tlb switches work. -DaveM - */ - if (!ctx_valid || !cpu_isset(cpu, mm->cpu_vm_mask)) { - cpu_set(cpu, mm->cpu_vm_mask); - __flush_tlb_mm(CTX_HWBITS(mm->context), - SECONDARY_CONTEXT); - } + /* Even if (mm == old_mm) we _must_ check + * the cpu_vm_mask. If we do not we could + * corrupt the TLB state because of how + * smp_flush_tlb_{page,range,mm} on sparc64 + * and lazy tlb switches work. -DaveM + */ + cpu = smp_processor_id(); + if (!ctx_valid || !cpu_isset(cpu, mm->cpu_vm_mask)) { + cpu_set(cpu, mm->cpu_vm_mask); + __flush_tlb_mm(CTX_HWBITS(mm->context), + SECONDARY_CONTEXT); } - spin_unlock(&mm->page_table_lock); } #define deactivate_mm(tsk,mm) do { } while (0) @@ -127,6 +125,10 @@ static inline void activate_mm(struct mm_struct *active_mm, struct mm_struct *mm { int cpu; + /* Note: page_table_lock is used here to serialize switch_mm + * and activate_mm, and their calls to get_new_mmu_context. + * This use of page_table_lock is unrelated to its other uses. + */ spin_lock(&mm->page_table_lock); if (!CTX_VALID(mm->context)) get_new_mmu_context(mm); diff --git a/kernel/fork.c b/kernel/fork.c index efac2c58ec7..158710d2256 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -470,13 +470,6 @@ static int copy_mm(unsigned long clone_flags, struct task_struct * tsk) if (clone_flags & CLONE_VM) { atomic_inc(&oldmm->mm_users); mm = oldmm; - /* - * There are cases where the PTL is held to ensure no - * new threads start up in user mode using an mm, which - * allows optimizing out ipis; the tlb_gather_mmu code - * is an example. - */ - spin_unlock_wait(&oldmm->page_table_lock); goto good_mm; } -- cgit v1.2.3 From b128254fdb172eaa3273de24fa6ce405a1f534c9 Mon Sep 17 00:00:00 2001 From: Georg Chini Date: Mon, 7 Nov 2005 14:09:19 -0800 Subject: [SPARC]: More abstractions and cleanups of dma handling in cs4231. From: Georg Chini Signed-off-by: David S. Miller --- include/asm-sparc64/ebus.h | 1 + sound/sparc/cs4231.c | 683 +++++++++++++++++++++++---------------------- 2 files changed, 343 insertions(+), 341 deletions(-) diff --git a/include/asm-sparc64/ebus.h b/include/asm-sparc64/ebus.h index 543e4e500a7..7a408a030f5 100644 --- a/include/asm-sparc64/ebus.h +++ b/include/asm-sparc64/ebus.h @@ -79,6 +79,7 @@ extern int ebus_dma_request(struct ebus_dma_info *p, dma_addr_t bus_addr, size_t len); extern void ebus_dma_prepare(struct ebus_dma_info *p, int write); extern unsigned int ebus_dma_residue(struct ebus_dma_info *p); +extern unsigned int ebus_dma_addr(struct ebus_dma_info *p); extern void ebus_dma_enable(struct ebus_dma_info *p, int on); extern struct linux_ebus *ebus_chain; diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 110d64d4848..1f8d27a6152 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -62,25 +62,36 @@ MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Sun,CS4231}}"); #ifdef SBUS_SUPPORT -struct sbus_dma_info { +typedef struct sbus_dma_info { spinlock_t lock; int dir; void __iomem *regs; -}; +} sbus_dma_info_t; #endif -typedef struct snd_cs4231 { - spinlock_t lock; - void __iomem *port; +typedef struct snd_cs4231 cs4231_t; + +typedef struct cs4231_dma_control { + void (*prepare)(struct cs4231_dma_control *dma_cont, int dir); + void (*enable)(struct cs4231_dma_control *dma_cont, int on); + int (*request)(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len); + unsigned int (*address)(struct cs4231_dma_control *dma_cont); + void (*reset)(cs4231_t *chip); + void (*preallocate)(cs4231_t *chip, snd_pcm_t *pcm); #ifdef EBUS_SUPPORT - struct ebus_dma_info eb2c; - struct ebus_dma_info eb2p; + struct ebus_dma_info ebus_info; #endif - #ifdef SBUS_SUPPORT - struct sbus_dma_info sb2c; - struct sbus_dma_info sb2p; + struct sbus_dma_info sbus_info; #endif +} cs4231_dma_control_t; + +struct snd_cs4231 { + spinlock_t lock; + void __iomem *port; + + cs4231_dma_control_t p_dma; + cs4231_dma_control_t c_dma; u32 flags; #define CS4231_FLAG_EBUS 0x00000001 @@ -119,7 +130,7 @@ typedef struct snd_cs4231 { unsigned int irq[2]; unsigned int regs_size; struct snd_cs4231 *next; -} cs4231_t; +}; static cs4231_t *cs4231_list; @@ -493,103 +504,6 @@ static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg) return ret; } -/* - * SBUS DMA routines - */ -#ifdef SBUS_SUPPORT - -int sbus_dma_request(struct sbus_dma_info *base, dma_addr_t bus_addr, size_t len) -{ - unsigned long flags; - u32 test, csr; - int err; - - if (len >= (1 << 24)) - return -EINVAL; - spin_lock_irqsave(&base->lock, flags); - csr = sbus_readl(base->regs + APCCSR); - err = -EINVAL; - test = APC_CDMA_READY; - if ( base->dir == APC_PLAY ) - test = APC_PDMA_READY; - if (!(csr & test)) - goto out; - err = -EBUSY; - csr = sbus_readl(base->regs + APCCSR); - test = APC_XINT_CNVA; - if ( base->dir == APC_PLAY ) - test = APC_XINT_PNVA; - if (!(csr & test)) - goto out; - err = 0; - sbus_writel(bus_addr, base->regs + base->dir + APCNVA); - sbus_writel(len, base->regs + base->dir + APCNC); -out: - spin_unlock_irqrestore(&base->lock, flags); - return err; -} - -void sbus_dma_prepare(struct sbus_dma_info *base) -{ - unsigned long flags; - u32 csr, test; - - spin_lock_irqsave(&base->lock, flags); - csr = sbus_readl(base->regs + APCCSR); - test = APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA | - APC_XINT_PLAY | APC_XINT_PEMP | APC_XINT_GENL | - APC_XINT_PENA; - if ( base->dir == APC_RECORD ) - test = APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA | - APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL; - csr |= test; - sbus_writel(csr, base->regs + APCCSR); - spin_unlock_irqrestore(&base->lock, flags); -} - -void sbus_dma_enable(struct sbus_dma_info *base, int on) -{ - unsigned long flags; - u32 csr, shift; - - spin_lock_irqsave(&base->lock, flags); - if (!on) { - if (base->dir == APC_PLAY) { - sbus_writel(0, base->regs + base->dir + APCNVA); - sbus_writel(1, base->regs + base->dir + APCC); - } - else - { - sbus_writel(0, base->regs + base->dir + APCNC); - sbus_writel(0, base->regs + base->dir + APCVA); - } - } - udelay(500); - csr = sbus_readl(base->regs + APCCSR); - shift = 0; - if ( base->dir == APC_PLAY ) - shift = 1; - if (on) - csr &= ~(APC_CPAUSE << shift); - else - csr |= (APC_CPAUSE << shift); - sbus_writel(csr, base->regs + APCCSR); - if (on) - csr |= (APC_CDMA_READY << shift); - else - csr &= ~(APC_CDMA_READY << shift); - sbus_writel(csr, base->regs + APCCSR); - - spin_unlock_irqrestore(&base->lock, flags); -} - -unsigned int sbus_dma_addr(struct sbus_dma_info *base) -{ - return sbus_readl(base->regs + base->dir + APCVA); -} - -#endif - /* * CS4231 detection / MCE routines */ @@ -688,8 +602,7 @@ static void snd_cs4231_mce_down(cs4231_t *chip) spin_unlock_irqrestore(&chip->lock, flags); } -#ifdef EBUS_SUPPORT -static void snd_cs4231_ebus_advance_dma(struct ebus_dma_info *p, snd_pcm_substream_t *substream, unsigned int *periods_sent) +static void snd_cs4231_advance_dma(struct cs4231_dma_control *dma_cont, snd_pcm_substream_t *substream, unsigned int *periods_sent) { snd_pcm_runtime_t *runtime = substream->runtime; @@ -700,89 +613,41 @@ static void snd_cs4231_ebus_advance_dma(struct ebus_dma_info *p, snd_pcm_substre if (period_size >= (1 << 24)) BUG(); - if (ebus_dma_request(p, runtime->dma_addr + offset, period_size)) + if (dma_cont->request(dma_cont, runtime->dma_addr + offset, period_size)) return; (*periods_sent) = ((*periods_sent) + 1) % runtime->periods; } } -#endif - -#ifdef SBUS_SUPPORT -static void snd_cs4231_sbus_advance_dma(struct sbus_dma_info *p, snd_pcm_substream_t *substream, unsigned int *periods_sent) -{ - snd_pcm_runtime_t *runtime = substream->runtime; - - while (1) { - unsigned int period_size = snd_pcm_lib_period_bytes(substream); - unsigned int offset = period_size * (*periods_sent); - - if (period_size > 0xffff + 1) - BUG(); - - if (sbus_dma_request(p, runtime->dma_addr + offset, period_size)) - return; - (*periods_sent) = (*periods_sent + 1) % runtime->periods; - } -} -#endif static void cs4231_dma_trigger(snd_pcm_substream_t *substream, unsigned int what, int on) { cs4231_t *chip = snd_pcm_substream_chip(substream); + cs4231_dma_control_t *dma_cont; -#ifdef EBUS_SUPPORT - if (chip->flags & CS4231_FLAG_EBUS) { - if (what & CS4231_PLAYBACK_ENABLE) { - if (on) { - ebus_dma_prepare(&chip->eb2p, 0); - ebus_dma_enable(&chip->eb2p, 1); - snd_cs4231_ebus_advance_dma(&chip->eb2p, - chip->playback_substream, - &chip->p_periods_sent); - } else { - ebus_dma_enable(&chip->eb2p, 0); - } - } - if (what & CS4231_RECORD_ENABLE) { - if (on) { - ebus_dma_prepare(&chip->eb2c, 1); - ebus_dma_enable(&chip->eb2c, 1); - snd_cs4231_ebus_advance_dma(&chip->eb2c, - chip->capture_substream, - &chip->c_periods_sent); - } else { - ebus_dma_enable(&chip->eb2c, 0); - } - } - } else { -#endif -#ifdef SBUS_SUPPORT if (what & CS4231_PLAYBACK_ENABLE) { + dma_cont = &chip->p_dma; if (on) { - sbus_dma_prepare(&chip->sb2p); - sbus_dma_enable(&chip->sb2p, 1); - snd_cs4231_sbus_advance_dma(&chip->sb2p, + dma_cont->prepare(dma_cont, 0); + dma_cont->enable(dma_cont, 1); + snd_cs4231_advance_dma(dma_cont, chip->playback_substream, &chip->p_periods_sent); } else { - sbus_dma_enable(&chip->sb2p, 0); + dma_cont->enable(dma_cont, 0); } } if (what & CS4231_RECORD_ENABLE) { + dma_cont = &chip->c_dma; if (on) { - sbus_dma_prepare(&chip->sb2c); - sbus_dma_enable(&chip->sb2c, 1); - snd_cs4231_sbus_advance_dma(&chip->sb2c, + dma_cont->prepare(dma_cont, 1); + dma_cont->enable(dma_cont, 1); + snd_cs4231_advance_dma(dma_cont, chip->capture_substream, &chip->c_periods_sent); } else { - sbus_dma_enable(&chip->sb2c, 0); + dma_cont->enable(dma_cont, 0); } } -#endif -#ifdef EBUS_SUPPORT - } -#endif } static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd) @@ -1273,140 +1138,55 @@ static void snd_cs4231_overrange(cs4231_t *chip) chip->capture_substream->runtime->overrange++; } -#ifdef SBUS_SUPPORT -static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - unsigned char status; - u32 csr; - cs4231_t *chip = dev_id; - - /*This is IRQ is not raised by the cs4231*/ - if (!(__cs4231_readb(chip, CS4231P(chip, STATUS)) & CS4231_GLOBALIRQ)) - return IRQ_NONE; - - /* ACK the APC interrupt. */ - csr = sbus_readl(chip->port + APCCSR); - - sbus_writel(csr, chip->port + APCCSR); - - if ((chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE) && - (csr & APC_PLAY_INT) && - (csr & APC_XINT_PNVA) && - !(csr & APC_XINT_EMPT)) { - snd_pcm_period_elapsed(chip->playback_substream); - snd_cs4231_sbus_advance_dma(&chip->sb2p, chip->playback_substream, - &chip->p_periods_sent); - } - - if ((chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) && - (csr & APC_CAPT_INT) && - (csr & APC_XINT_CNVA) && - !(csr & APC_XINT_EMPT)) { - snd_pcm_period_elapsed(chip->capture_substream); - snd_cs4231_sbus_advance_dma(&chip->sb2c,chip->capture_substream, - &chip->c_periods_sent); - } - - status = snd_cs4231_in(chip, CS4231_IRQ_STATUS); - - if (status & CS4231_TIMER_IRQ) { - if (chip->timer) - snd_timer_interrupt(chip->timer, chip->timer->sticks); - } - - if (status & CS4231_RECORD_IRQ) - snd_cs4231_overrange(chip); - - /* ACK the CS4231 interrupt. */ - spin_lock_irqsave(&chip->lock, flags); - snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0); - spin_unlock_irqrestore(&chip->lock, flags); - - return 0; -} -#endif - -#ifdef EBUS_SUPPORT -static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event, void *cookie) +static void snd_cs4231_play_callback(cs4231_t *cookie) { cs4231_t *chip = cookie; if (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE) { snd_pcm_period_elapsed(chip->playback_substream); - snd_cs4231_ebus_advance_dma(p, chip->playback_substream, + snd_cs4231_advance_dma(&chip->p_dma, chip->playback_substream, &chip->p_periods_sent); } } -static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event, void *cookie) +static void snd_cs4231_capture_callback(cs4231_t *cookie) { cs4231_t *chip = cookie; if (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) { snd_pcm_period_elapsed(chip->capture_substream); - snd_cs4231_ebus_advance_dma(p, chip->capture_substream, + snd_cs4231_advance_dma(&chip->c_dma, chip->capture_substream, &chip->c_periods_sent); } } -#endif static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t *substream) { cs4231_t *chip = snd_pcm_substream_chip(substream); + cs4231_dma_control_t *dma_cont = &chip->p_dma; size_t ptr; -#ifdef EBUS_SUPPORT - size_t residue, period_bytes; -#endif if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) return 0; -#ifdef EBUS_SUPPORT - period_bytes = snd_pcm_lib_period_bytes(substream); - ptr = period_bytes * chip->p_periods_sent; - if (chip->flags & CS4231_FLAG_EBUS) { - residue = ebus_dma_residue(&chip->eb2p); - ptr += period_bytes - residue; - } else { -#endif -#ifdef SBUS_SUPPORT - ptr = sbus_dma_addr(&chip->sb2p); - if (ptr != 0) - ptr -= substream->runtime->dma_addr; -#endif -#ifdef EBUS_SUPPORT - } -#endif - + ptr = dma_cont->address(dma_cont); + if (ptr != 0) + ptr -= substream->runtime->dma_addr; + return bytes_to_frames(substream->runtime, ptr); } static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substream) { cs4231_t *chip = snd_pcm_substream_chip(substream); + cs4231_dma_control_t *dma_cont = &chip->c_dma; size_t ptr; -#ifdef EBUS_SUPPORT - size_t residue, period_bytes; -#endif if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE)) return 0; -#ifdef EBUS_SUPPORT - period_bytes = snd_pcm_lib_period_bytes(substream); - ptr = period_bytes * chip->c_periods_sent; - if (chip->flags & CS4231_FLAG_EBUS) { - residue = ebus_dma_residue(&chip->eb2c); - ptr += period_bytes - residue; - } else { -#endif -#ifdef SBUS_SUPPORT - ptr = sbus_dma_addr(&chip->sb2c); - if (ptr != 0) - ptr -= substream->runtime->dma_addr; -#endif -#ifdef EBUS_SUPPORT - } -#endif + ptr = dma_cont->address(dma_cont); + if (ptr != 0) + ptr -= substream->runtime->dma_addr; + return bytes_to_frames(substream->runtime, ptr); } @@ -1442,30 +1222,8 @@ static int snd_cs4231_probe(cs4231_t *chip) spin_lock_irqsave(&chip->lock, flags); - /* Reset DMA engine. */ -#ifdef EBUS_SUPPORT - if (chip->flags & CS4231_FLAG_EBUS) { - /* Done by ebus_dma_register */ - } else { -#endif -#ifdef SBUS_SUPPORT - sbus_writel(APC_CHIP_RESET, chip->port + APCCSR); - sbus_writel(0x00, chip->port + APCCSR); - sbus_writel(sbus_readl(chip->port + APCCSR) | APC_CDC_RESET, - chip->port + APCCSR); - - udelay(20); - - sbus_writel(sbus_readl(chip->port + APCCSR) & ~APC_CDC_RESET, - chip->port + APCCSR); - sbus_writel(sbus_readl(chip->port + APCCSR) | (APC_XINT_ENA | - APC_XINT_PENA | - APC_XINT_CENA), - chip->port + APCCSR); -#endif -#ifdef EBUS_SUPPORT - } -#endif + /* Reset DMA engine (sbus only). */ + chip->p_dma.reset(chip); __cs4231_readb(chip, CS4231P(chip, STATUS)); /* clear any pendings IRQ */ __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); @@ -1585,8 +1343,8 @@ static int snd_cs4231_playback_close(snd_pcm_substream_t *substream) { cs4231_t *chip = snd_pcm_substream_chip(substream); - chip->playback_substream = NULL; snd_cs4231_close(chip, CS4231_MODE_PLAY); + chip->playback_substream = NULL; return 0; } @@ -1595,8 +1353,8 @@ static int snd_cs4231_capture_close(snd_pcm_substream_t *substream) { cs4231_t *chip = snd_pcm_substream_chip(substream); - chip->capture_substream = NULL; snd_cs4231_close(chip, CS4231_MODE_RECORD); + chip->capture_substream = NULL; return 0; } @@ -1651,21 +1409,7 @@ int snd_cs4231_pcm(cs4231_t *chip) pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; strcpy(pcm->name, "CS4231"); -#ifdef EBUS_SUPPORT - if (chip->flags & CS4231_FLAG_EBUS) { - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->dev_u.pdev), - 64*1024, 128*1024); - } else { -#endif -#ifdef SBUS_SUPPORT - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_SBUS, - snd_dma_sbus_data(chip->dev_u.sdev), - 64*1024, 128*1024); -#endif -#ifdef EBUS_SUPPORT - } -#endif + chip->p_dma.preallocate(chip, pcm); chip->pcm = pcm; @@ -2022,6 +1766,180 @@ out_err: } #ifdef SBUS_SUPPORT + +static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long flags; + unsigned char status; + u32 csr; + cs4231_t *chip = dev_id; + + /*This is IRQ is not raised by the cs4231*/ + if (!(__cs4231_readb(chip, CS4231P(chip, STATUS)) & CS4231_GLOBALIRQ)) + return IRQ_NONE; + + /* ACK the APC interrupt. */ + csr = sbus_readl(chip->port + APCCSR); + + sbus_writel(csr, chip->port + APCCSR); + + if ((csr & APC_PDMA_READY) && + (csr & APC_PLAY_INT) && + (csr & APC_XINT_PNVA) && + !(csr & APC_XINT_EMPT)) + snd_cs4231_play_callback(chip); + + if ((csr & APC_CDMA_READY) && + (csr & APC_CAPT_INT) && + (csr & APC_XINT_CNVA) && + !(csr & APC_XINT_EMPT)) + snd_cs4231_capture_callback(chip); + + status = snd_cs4231_in(chip, CS4231_IRQ_STATUS); + + if (status & CS4231_TIMER_IRQ) { + if (chip->timer) + snd_timer_interrupt(chip->timer, chip->timer->sticks); + } + + if ((status & CS4231_RECORD_IRQ) && (csr & APC_CDMA_READY)) + snd_cs4231_overrange(chip); + + /* ACK the CS4231 interrupt. */ + spin_lock_irqsave(&chip->lock, flags); + snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0); + spin_unlock_irqrestore(&chip->lock, flags); + + return 0; +} + +/* + * SBUS DMA routines + */ + +int sbus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len) +{ + unsigned long flags; + u32 test, csr; + int err; + sbus_dma_info_t *base = &dma_cont->sbus_info; + + if (len >= (1 << 24)) + return -EINVAL; + spin_lock_irqsave(&base->lock, flags); + csr = sbus_readl(base->regs + APCCSR); + err = -EINVAL; + test = APC_CDMA_READY; + if ( base->dir == APC_PLAY ) + test = APC_PDMA_READY; + if (!(csr & test)) + goto out; + err = -EBUSY; + csr = sbus_readl(base->regs + APCCSR); + test = APC_XINT_CNVA; + if ( base->dir == APC_PLAY ) + test = APC_XINT_PNVA; + if (!(csr & test)) + goto out; + err = 0; + sbus_writel(bus_addr, base->regs + base->dir + APCNVA); + sbus_writel(len, base->regs + base->dir + APCNC); +out: + spin_unlock_irqrestore(&base->lock, flags); + return err; +} + +void sbus_dma_prepare(struct cs4231_dma_control *dma_cont, int d) +{ + unsigned long flags; + u32 csr, test; + sbus_dma_info_t *base = &dma_cont->sbus_info; + + spin_lock_irqsave(&base->lock, flags); + csr = sbus_readl(base->regs + APCCSR); + test = APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA | + APC_XINT_PLAY | APC_XINT_PEMP | APC_XINT_GENL | + APC_XINT_PENA; + if ( base->dir == APC_RECORD ) + test = APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA | + APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL; + csr |= test; + sbus_writel(csr, base->regs + APCCSR); + spin_unlock_irqrestore(&base->lock, flags); +} + +void sbus_dma_enable(struct cs4231_dma_control *dma_cont, int on) +{ + unsigned long flags; + u32 csr, shift; + sbus_dma_info_t *base = &dma_cont->sbus_info; + + spin_lock_irqsave(&base->lock, flags); + if (!on) { + if (base->dir == APC_PLAY) { + sbus_writel(0, base->regs + base->dir + APCNVA); + sbus_writel(1, base->regs + base->dir + APCC); + } + else + { + sbus_writel(0, base->regs + base->dir + APCNC); + sbus_writel(0, base->regs + base->dir + APCVA); + } + } + udelay(600); + csr = sbus_readl(base->regs + APCCSR); + shift = 0; + if ( base->dir == APC_PLAY ) + shift = 1; + if (on) + csr &= ~(APC_CPAUSE << shift); + else + csr |= (APC_CPAUSE << shift); + sbus_writel(csr, base->regs + APCCSR); + if (on) + csr |= (APC_CDMA_READY << shift); + else + csr &= ~(APC_CDMA_READY << shift); + sbus_writel(csr, base->regs + APCCSR); + + spin_unlock_irqrestore(&base->lock, flags); +} + +unsigned int sbus_dma_addr(struct cs4231_dma_control *dma_cont) +{ + sbus_dma_info_t *base = &dma_cont->sbus_info; + + return sbus_readl(base->regs + base->dir + APCVA); +} + +void sbus_dma_reset(cs4231_t *chip) +{ + sbus_writel(APC_CHIP_RESET, chip->port + APCCSR); + sbus_writel(0x00, chip->port + APCCSR); + sbus_writel(sbus_readl(chip->port + APCCSR) | APC_CDC_RESET, + chip->port + APCCSR); + + udelay(20); + + sbus_writel(sbus_readl(chip->port + APCCSR) & ~APC_CDC_RESET, + chip->port + APCCSR); + sbus_writel(sbus_readl(chip->port + APCCSR) | (APC_XINT_ENA | + APC_XINT_PENA | + APC_XINT_CENA), + chip->port + APCCSR); +} + +void sbus_dma_preallocate(cs4231_t *chip, snd_pcm_t *pcm) +{ + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_SBUS, + snd_dma_sbus_data(chip->dev_u.sdev), + 64*1024, 128*1024); +} + +/* + * Init and exit routines + */ + static int snd_cs4231_sbus_free(cs4231_t *chip) { if (chip->irq[0]) @@ -2063,8 +1981,8 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card, return -ENOMEM; spin_lock_init(&chip->lock); - spin_lock_init(&chip->sb2c.lock); - spin_lock_init(&chip->sb2p.lock); + spin_lock_init(&chip->c_dma.sbus_info.lock); + spin_lock_init(&chip->p_dma.sbus_info.lock); init_MUTEX(&chip->mce_mutex); init_MUTEX(&chip->open_mutex); chip->card = card; @@ -2080,10 +1998,24 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card, return -EIO; } - chip->sb2c.regs = chip->port; - chip->sb2p.regs = chip->port; - chip->sb2c.dir = APC_RECORD; - chip->sb2p.dir = APC_PLAY; + chip->c_dma.sbus_info.regs = chip->port; + chip->p_dma.sbus_info.regs = chip->port; + chip->c_dma.sbus_info.dir = APC_RECORD; + chip->p_dma.sbus_info.dir = APC_PLAY; + + chip->p_dma.prepare = sbus_dma_prepare; + chip->p_dma.enable = sbus_dma_enable; + chip->p_dma.request = sbus_dma_request; + chip->p_dma.address = sbus_dma_addr; + chip->p_dma.reset = sbus_dma_reset; + chip->p_dma.preallocate = sbus_dma_preallocate; + + chip->c_dma.prepare = sbus_dma_prepare; + chip->c_dma.enable = sbus_dma_enable; + chip->c_dma.request = sbus_dma_request; + chip->c_dma.address = sbus_dma_addr; + chip->c_dma.reset = sbus_dma_reset; + chip->c_dma.preallocate = sbus_dma_preallocate; if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt, SA_SHIRQ, "cs4231", chip)) { @@ -2138,15 +2070,70 @@ static int cs4231_sbus_attach(struct sbus_dev *sdev) #endif #ifdef EBUS_SUPPORT + +static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event, void *cookie) +{ + cs4231_t *chip = cookie; + + snd_cs4231_play_callback(chip); +} + +static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event, void *cookie) +{ + cs4231_t *chip = cookie; + + snd_cs4231_capture_callback(chip); +} + +/* + * EBUS DMA wrappers + */ + +int _ebus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len) +{ + return ebus_dma_request(&dma_cont->ebus_info, bus_addr, len); +} + +void _ebus_dma_enable(struct cs4231_dma_control *dma_cont, int on) +{ + ebus_dma_enable(&dma_cont->ebus_info, on); +} + +void _ebus_dma_prepare(struct cs4231_dma_control *dma_cont, int dir) +{ + ebus_dma_prepare(&dma_cont->ebus_info, dir); +} + +unsigned int _ebus_dma_addr(struct cs4231_dma_control *dma_cont) +{ + return ebus_dma_addr(&dma_cont->ebus_info); +} + +void _ebus_dma_reset(cs4231_t *chip) +{ + return; +} + +void _ebus_dma_preallocate(cs4231_t *chip, snd_pcm_t *pcm) +{ + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, + snd_dma_pci_data(chip->dev_u.pdev), + 64*1024, 128*1024); +} + +/* + * Init and exit routines + */ + static int snd_cs4231_ebus_free(cs4231_t *chip) { - if (chip->eb2c.regs) { - ebus_dma_unregister(&chip->eb2c); - iounmap(chip->eb2c.regs); + if (chip->c_dma.ebus_info.regs) { + ebus_dma_unregister(&chip->c_dma.ebus_info); + iounmap(chip->c_dma.ebus_info.regs); } - if (chip->eb2p.regs) { - ebus_dma_unregister(&chip->eb2p); - iounmap(chip->eb2p.regs); + if (chip->p_dma.ebus_info.regs) { + ebus_dma_unregister(&chip->p_dma.ebus_info); + iounmap(chip->p_dma.ebus_info.regs); } if (chip->port) @@ -2184,8 +2171,8 @@ static int __init snd_cs4231_ebus_create(snd_card_t *card, return -ENOMEM; spin_lock_init(&chip->lock); - spin_lock_init(&chip->eb2c.lock); - spin_lock_init(&chip->eb2p.lock); + spin_lock_init(&chip->c_dma.ebus_info.lock); + spin_lock_init(&chip->p_dma.ebus_info.lock); init_MUTEX(&chip->mce_mutex); init_MUTEX(&chip->open_mutex); chip->flags |= CS4231_FLAG_EBUS; @@ -2193,43 +2180,57 @@ static int __init snd_cs4231_ebus_create(snd_card_t *card, chip->dev_u.pdev = edev->bus->self; memcpy(&chip->image, &snd_cs4231_original_image, sizeof(snd_cs4231_original_image)); - strcpy(chip->eb2c.name, "cs4231(capture)"); - chip->eb2c.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER; - chip->eb2c.callback = snd_cs4231_ebus_capture_callback; - chip->eb2c.client_cookie = chip; - chip->eb2c.irq = edev->irqs[0]; - strcpy(chip->eb2p.name, "cs4231(play)"); - chip->eb2p.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER; - chip->eb2p.callback = snd_cs4231_ebus_play_callback; - chip->eb2p.client_cookie = chip; - chip->eb2p.irq = edev->irqs[1]; + strcpy(chip->c_dma.ebus_info.name, "cs4231(capture)"); + chip->c_dma.ebus_info.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER; + chip->c_dma.ebus_info.callback = snd_cs4231_ebus_capture_callback; + chip->c_dma.ebus_info.client_cookie = chip; + chip->c_dma.ebus_info.irq = edev->irqs[0]; + strcpy(chip->p_dma.ebus_info.name, "cs4231(play)"); + chip->p_dma.ebus_info.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER; + chip->p_dma.ebus_info.callback = snd_cs4231_ebus_play_callback; + chip->p_dma.ebus_info.client_cookie = chip; + chip->p_dma.ebus_info.irq = edev->irqs[1]; + + chip->p_dma.prepare = _ebus_dma_prepare; + chip->p_dma.enable = _ebus_dma_enable; + chip->p_dma.request = _ebus_dma_request; + chip->p_dma.address = _ebus_dma_addr; + chip->p_dma.reset = _ebus_dma_reset; + chip->p_dma.preallocate = _ebus_dma_preallocate; + + chip->c_dma.prepare = _ebus_dma_prepare; + chip->c_dma.enable = _ebus_dma_enable; + chip->c_dma.request = _ebus_dma_request; + chip->c_dma.address = _ebus_dma_addr; + chip->c_dma.reset = _ebus_dma_reset; + chip->c_dma.preallocate = _ebus_dma_preallocate; chip->port = ioremap(edev->resource[0].start, 0x10); - chip->eb2p.regs = ioremap(edev->resource[1].start, 0x10); - chip->eb2c.regs = ioremap(edev->resource[2].start, 0x10); - if (!chip->port || !chip->eb2p.regs || !chip->eb2c.regs) { + chip->p_dma.ebus_info.regs = ioremap(edev->resource[1].start, 0x10); + chip->c_dma.ebus_info.regs = ioremap(edev->resource[2].start, 0x10); + if (!chip->port || !chip->p_dma.ebus_info.regs || !chip->c_dma.ebus_info.regs) { snd_cs4231_ebus_free(chip); snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev); return -EIO; } - if (ebus_dma_register(&chip->eb2c)) { + if (ebus_dma_register(&chip->c_dma.ebus_info)) { snd_cs4231_ebus_free(chip); snd_printdd("cs4231-%d: Unable to register EBUS capture DMA\n", dev); return -EBUSY; } - if (ebus_dma_irq_enable(&chip->eb2c, 1)) { + if (ebus_dma_irq_enable(&chip->c_dma.ebus_info, 1)) { snd_cs4231_ebus_free(chip); snd_printdd("cs4231-%d: Unable to enable EBUS capture IRQ\n", dev); return -EBUSY; } - if (ebus_dma_register(&chip->eb2p)) { + if (ebus_dma_register(&chip->p_dma.ebus_info)) { snd_cs4231_ebus_free(chip); snd_printdd("cs4231-%d: Unable to register EBUS play DMA\n", dev); return -EBUSY; } - if (ebus_dma_irq_enable(&chip->eb2p, 1)) { + if (ebus_dma_irq_enable(&chip->p_dma.ebus_info, 1)) { snd_cs4231_ebus_free(chip); snd_printdd("cs4231-%d: Unable to enable EBUS play IRQ\n", dev); return -EBUSY; -- cgit v1.2.3 From 4c85ce522fc4bf1b8fcd6255fadc11cfb75773df Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 7 Nov 2005 14:09:44 -0800 Subject: [SPARC]: Remove bogus register programming in cg6 driver. Don't write garbage into the overlay plane. Noted by Bob Breuer. Signed-off-by: David S. Miller --- drivers/video/cg6.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 3280bb9560e..414c4409e92 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c @@ -653,12 +653,6 @@ static void cg6_chip_init(struct fb_info *info) sbus_writel(0, &fbc->clipminy); sbus_writel(info->var.xres - 1, &fbc->clipmaxx); sbus_writel(info->var.yres - 1, &fbc->clipmaxy); - - /* Disable cursor in Brooktree DAC. */ - sbus_writel(0x06 << 24, &par->bt->addr); - tmp = sbus_readl(&par->bt->control); - tmp &= ~(0x03 << 24); - sbus_writel(tmp, &par->bt->control); } struct all_info { -- cgit v1.2.3 From 62dbec78be652c28f63ad5eda3d01c244c916040 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 7 Nov 2005 14:09:58 -0800 Subject: [SPARC64] mm: Do not flush TLB mm in tlb_finish_mmu() It isn't needed any longer, as noted by Hugh Dickins. We still need the flush routines, due to the one remaining call site in hugetlb_prefault_arch_hook(). That can be eliminated at some later point, however. Signed-off-by: David S. Miller --- arch/sparc64/kernel/smp.c | 48 +++++++++++++++++------------------------------ include/asm-sparc64/tlb.h | 6 ++---- 2 files changed, 19 insertions(+), 35 deletions(-) diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index a9089e2140e..5d90ee9aebf 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -839,43 +839,29 @@ void smp_flush_tlb_all(void) * questionable (in theory the big win for threads is the massive sharing of * address space state across processors). */ + +/* This currently is only used by the hugetlb arch pre-fault + * hook on UltraSPARC-III+ and later when changing the pagesize + * bits of the context register for an address space. + */ void smp_flush_tlb_mm(struct mm_struct *mm) { - /* - * This code is called from two places, dup_mmap and exit_mmap. In the - * former case, we really need a flush. In the later case, the callers - * are single threaded exec_mmap (really need a flush), multithreaded - * exec_mmap case (do not need to flush, since the caller gets a new - * context via activate_mm), and all other callers of mmput() whence - * the flush can be optimized since the associated threads are dead and - * the mm is being torn down (__exit_mm and other mmput callers) or the - * owning thread is dissociating itself from the mm. The - * (atomic_read(&mm->mm_users) == 0) check ensures real work is done - * for single thread exec and dup_mmap cases. An alternate check might - * have been (current->mm != mm). - * Kanoj Sarcar - */ - if (atomic_read(&mm->mm_users) == 0) - return; - - { - u32 ctx = CTX_HWBITS(mm->context); - int cpu = get_cpu(); + u32 ctx = CTX_HWBITS(mm->context); + int cpu = get_cpu(); - if (atomic_read(&mm->mm_users) == 1) { - mm->cpu_vm_mask = cpumask_of_cpu(cpu); - goto local_flush_and_out; - } + if (atomic_read(&mm->mm_users) == 1) { + mm->cpu_vm_mask = cpumask_of_cpu(cpu); + goto local_flush_and_out; + } - smp_cross_call_masked(&xcall_flush_tlb_mm, - ctx, 0, 0, - mm->cpu_vm_mask); + smp_cross_call_masked(&xcall_flush_tlb_mm, + ctx, 0, 0, + mm->cpu_vm_mask); - local_flush_and_out: - __flush_tlb_mm(ctx, SECONDARY_CONTEXT); +local_flush_and_out: + __flush_tlb_mm(ctx, SECONDARY_CONTEXT); - put_cpu(); - } + put_cpu(); } void smp_flush_tlb_pending(struct mm_struct *mm, unsigned long nr, unsigned long *vaddrs) diff --git a/include/asm-sparc64/tlb.h b/include/asm-sparc64/tlb.h index 66138d959df..1eda17954f3 100644 --- a/include/asm-sparc64/tlb.h +++ b/include/asm-sparc64/tlb.h @@ -78,11 +78,9 @@ static inline void tlb_finish_mmu(struct mmu_gather *mp, unsigned long start, un { tlb_flush_mmu(mp); - if (mp->fullmm) { - if (CTX_VALID(mp->mm->context)) - do_flush_tlb_mm(mp->mm); + if (mp->fullmm) mp->fullmm = 0; - } else + else flush_tlb_pending(); /* keep the page table cache within bounds */ -- cgit v1.2.3 From fc3214952fac07fef7e102fdd4a18b3d736f33f1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 7 Nov 2005 14:10:10 -0800 Subject: [SPARC64]: Kill off dummy_tick_ops. It only serves to generate false-positive buildcheck warnings. Just set it initially to tick_operations which uses the v9 %tick register which every sparc64 processor has. Signed-off-by: David S. Miller --- arch/sparc64/kernel/time.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 38c5525087a..459c8fbe02b 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -60,17 +60,6 @@ static void __iomem *mstk48t59_regs; static int set_rtc_mmss(unsigned long); -static __init unsigned long dummy_get_tick(void) -{ - return 0; -} - -static __initdata struct sparc64_tick_ops dummy_tick_ops = { - .get_tick = dummy_get_tick, -}; - -struct sparc64_tick_ops *tick_ops __read_mostly = &dummy_tick_ops; - #define TICK_PRIV_BIT (1UL << 63) #ifdef CONFIG_SMP @@ -200,6 +189,8 @@ static struct sparc64_tick_ops tick_operations __read_mostly = { .softint_mask = 1UL << 0, }; +struct sparc64_tick_ops *tick_ops __read_mostly = &tick_operations; + static void stick_init_tick(unsigned long offset) { tick_disable_protection(); -- cgit v1.2.3 From 483772469d4a15d77402c2ac819c80dff9be8421 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 7 Nov 2005 14:10:21 -0800 Subject: [SUNSU]: Do not mark sunsu_console_setup() __init Sets off buildcheck warnings. Signed-off-by: David S. Miller --- drivers/serial/sunsu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 656c0e8d160..f0738533f39 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1441,7 +1441,7 @@ static void sunsu_console_write(struct console *co, const char *s, * - initialize the serial port * Return non-zero if we didn't find a serial port. */ -static int __init sunsu_console_setup(struct console *co, char *options) +static int sunsu_console_setup(struct console *co, char *options) { struct uart_port *port; int baud = 9600; -- cgit v1.2.3 From d16436e686949a17b3bcfff2d688c97354b599aa Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 7 Nov 2005 14:10:42 -0800 Subject: [SPARC]: remove duplicate TIOCPKT_ definitions The TIOCPKT_ macros are defined by all other architectures in asm/ioctls.h and so does sparc and sparc64, so reomve the duplicates in asm/termios.h. Signed-off-by: Stephen Rothwell Signed-off-by: David S. Miller --- include/asm-sparc/termios.h | 9 --------- include/asm-sparc64/termios.h | 9 --------- 2 files changed, 18 deletions(-) diff --git a/include/asm-sparc/termios.h b/include/asm-sparc/termios.h index 0a8ad4cac12..d05f83c8098 100644 --- a/include/asm-sparc/termios.h +++ b/include/asm-sparc/termios.h @@ -38,15 +38,6 @@ struct sunos_ttysize { int st_columns; /* Columns on the terminal */ }; -/* Used for packet mode */ -#define TIOCPKT_DATA 0 -#define TIOCPKT_FLUSHREAD 1 -#define TIOCPKT_FLUSHWRITE 2 -#define TIOCPKT_STOP 4 -#define TIOCPKT_START 8 -#define TIOCPKT_NOSTOP 16 -#define TIOCPKT_DOSTOP 32 - struct winsize { unsigned short ws_row; unsigned short ws_col; diff --git a/include/asm-sparc64/termios.h b/include/asm-sparc64/termios.h index 9777a9cca88..ee26a071c67 100644 --- a/include/asm-sparc64/termios.h +++ b/include/asm-sparc64/termios.h @@ -38,15 +38,6 @@ struct sunos_ttysize { int st_columns; /* Columns on the terminal */ }; -/* Used for packet mode */ -#define TIOCPKT_DATA 0 -#define TIOCPKT_FLUSHREAD 1 -#define TIOCPKT_FLUSHWRITE 2 -#define TIOCPKT_STOP 4 -#define TIOCPKT_START 8 -#define TIOCPKT_NOSTOP 16 -#define TIOCPKT_DOSTOP 32 - struct winsize { unsigned short ws_row; unsigned short ws_col; -- cgit v1.2.3 From e0436b3164fd071acd30a50339b7b6ba5f053cf6 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 14:11:02 -0800 Subject: [SPARC64]: remove alloc_user_space() this inline routine in arch/sparc64/kernel/ioctl32.c is completely unused and superceeded by compat_alloc_user_space() Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- arch/sparc64/kernel/ioctl32.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index e6a00325075..0e587d6de31 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -27,17 +27,6 @@ */ #define A(__x) compat_ptr(__x) -static __inline__ void *alloc_user_space(long len) -{ - struct pt_regs *regs = current_thread_info()->kregs; - unsigned long usp = regs->u_regs[UREG_I6]; - - if (!(test_thread_flag(TIF_32BIT))) - usp += STACK_BIAS; - - return (void *) (usp - len); -} - #define CODE #include "compat_ioctl.c" -- cgit v1.2.3 From 9d3c7d1bfd41d5082a541666db404aae7699b79e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 14:11:14 -0800 Subject: [SPARC]: remove audioio.h The old sound drivers are gone in 2.6, so the only user left are the compat ioctls. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- arch/sparc64/kernel/ioctl32.c | 7 -- include/asm-sparc/audioio.h | 234 ------------------------------------------ include/asm-sparc64/audioio.h | 234 ------------------------------------------ 3 files changed, 475 deletions(-) delete mode 100644 include/asm-sparc/audioio.h delete mode 100644 include/asm-sparc64/audioio.h diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index 0e587d6de31..6fda044a737 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -19,7 +19,6 @@ #include #include #include -#include #include /* Use this to get at 32-bit user passed pointers. @@ -524,12 +523,6 @@ COMPATIBLE_IOCTL(OPROMPATH2NODE) COMPATIBLE_IOCTL(LOOP_SET_STATUS64) COMPATIBLE_IOCTL(LOOP_GET_STATUS64) /* Big A */ -COMPATIBLE_IOCTL(AUDIO_GETINFO) -COMPATIBLE_IOCTL(AUDIO_SETINFO) -COMPATIBLE_IOCTL(AUDIO_DRAIN) -COMPATIBLE_IOCTL(AUDIO_GETDEV) -COMPATIBLE_IOCTL(AUDIO_GETDEV_SUNOS) -COMPATIBLE_IOCTL(AUDIO_FLUSH) COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI) #if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) COMPATIBLE_IOCTL(DRM_IOCTL_GET_MAGIC) diff --git a/include/asm-sparc/audioio.h b/include/asm-sparc/audioio.h deleted file mode 100644 index cf16173f521..00000000000 --- a/include/asm-sparc/audioio.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - * include/asm-sparc/audioio.h - * - * Sparc Audio Midlayer - * Copyright (C) 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu) - */ - -#ifndef _AUDIOIO_H_ -#define _AUDIOIO_H_ - -/* - * SunOS/Solaris /dev/audio interface - */ - -#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) -#include -#include -#include -#endif - -/* - * This structure contains state information for audio device IO streams. - */ -typedef struct audio_prinfo { - /* - * The following values describe the audio data encoding. - */ - unsigned int sample_rate; /* samples per second */ - unsigned int channels; /* number of interleaved channels */ - unsigned int precision; /* bit-width of each sample */ - unsigned int encoding; /* data encoding method */ - - /* - * The following values control audio device configuration - */ - unsigned int gain; /* gain level: 0 - 255 */ - unsigned int port; /* selected I/O port (see below) */ - unsigned int avail_ports; /* available I/O ports (see below) */ - unsigned int _xxx[2]; /* Reserved for future use */ - - unsigned int buffer_size; /* I/O buffer size */ - - /* - * The following values describe driver state - */ - unsigned int samples; /* number of samples converted */ - unsigned int eof; /* End Of File counter (play only) */ - - unsigned char pause; /* non-zero for pause, zero to resume */ - unsigned char error; /* non-zero if overflow/underflow */ - unsigned char waiting; /* non-zero if a process wants access */ - unsigned char balance; /* stereo channel balance */ - - unsigned short minordev; - - /* - * The following values are read-only state flags - */ - unsigned char open; /* non-zero if open access permitted */ - unsigned char active; /* non-zero if I/O is active */ -} audio_prinfo_t; - - -/* - * This structure describes the current state of the audio device. - */ -typedef struct audio_info { - /* - * Per-stream information - */ - audio_prinfo_t play; /* output status information */ - audio_prinfo_t record; /* input status information */ - - /* - * Per-unit/channel information - */ - unsigned int monitor_gain; /* input to output mix: 0 - 255 */ - unsigned char output_muted; /* non-zero if output is muted */ - unsigned char _xxx[3]; /* Reserved for future use */ - unsigned int _yyy[3]; /* Reserved for future use */ -} audio_info_t; - - -/* - * Audio encoding types - */ -#define AUDIO_ENCODING_NONE (0) /* no encoding assigned */ -#define AUDIO_ENCODING_ULAW (1) /* u-law encoding */ -#define AUDIO_ENCODING_ALAW (2) /* A-law encoding */ -#define AUDIO_ENCODING_LINEAR (3) /* Linear PCM encoding */ -#define AUDIO_ENCODING_FLOAT (4) /* IEEE float (-1. <-> +1.) */ -#define AUDIO_ENCODING_DVI (104) /* DVI ADPCM */ -#define AUDIO_ENCODING_LINEAR8 (105) /* 8 bit UNSIGNED */ -#define AUDIO_ENCODING_LINEARLE (106) /* Linear PCM LE encoding */ - -/* - * These ranges apply to record, play, and monitor gain values - */ -#define AUDIO_MIN_GAIN (0) /* minimum gain value */ -#define AUDIO_MAX_GAIN (255) /* maximum gain value */ - -/* - * These values apply to the balance field to adjust channel gain values - */ -#define AUDIO_LEFT_BALANCE (0) /* left channel only */ -#define AUDIO_MID_BALANCE (32) /* equal left/right channel */ -#define AUDIO_RIGHT_BALANCE (64) /* right channel only */ -#define AUDIO_BALANCE_SHIFT (3) - -/* - * Generic minimum/maximum limits for number of channels, both modes - */ -#define AUDIO_MIN_PLAY_CHANNELS (1) -#define AUDIO_MAX_PLAY_CHANNELS (4) -#define AUDIO_MIN_REC_CHANNELS (1) -#define AUDIO_MAX_REC_CHANNELS (4) - -/* - * Generic minimum/maximum limits for sample precision - */ -#define AUDIO_MIN_PLAY_PRECISION (8) -#define AUDIO_MAX_PLAY_PRECISION (32) -#define AUDIO_MIN_REC_PRECISION (8) -#define AUDIO_MAX_REC_PRECISION (32) - -/* - * Define some convenient names for typical audio ports - */ -/* - * output ports (several may be enabled simultaneously) - */ -#define AUDIO_SPEAKER 0x01 /* output to built-in speaker */ -#define AUDIO_HEADPHONE 0x02 /* output to headphone jack */ -#define AUDIO_LINE_OUT 0x04 /* output to line out */ - -/* - * input ports (usually only one at a time) - */ -#define AUDIO_MICROPHONE 0x01 /* input from microphone */ -#define AUDIO_LINE_IN 0x02 /* input from line in */ -#define AUDIO_CD 0x04 /* input from on-board CD inputs */ -#define AUDIO_INTERNAL_CD_IN AUDIO_CD /* input from internal CDROM */ -#define AUDIO_ANALOG_LOOPBACK 0x40 /* input from output */ - - -/* - * This macro initializes an audio_info structure to 'harmless' values. - * Note that (~0) might not be a harmless value for a flag that was - * a signed int. - */ -#define AUDIO_INITINFO(i) { \ - unsigned int *__x__; \ - for (__x__ = (unsigned int *)(i); \ - (char *) __x__ < (((char *)(i)) + sizeof (audio_info_t)); \ - *__x__++ = ~0); \ -} - -/* - * These allow testing for what the user wants to set - */ -#define AUD_INITVALUE (~0) -#define Modify(X) ((unsigned int)(X) != AUD_INITVALUE) -#define Modifys(X) ((X) != (unsigned short)AUD_INITVALUE) -#define Modifyc(X) ((X) != (unsigned char)AUD_INITVALUE) - -/* - * Parameter for the AUDIO_GETDEV ioctl to determine current - * audio devices. - */ -#define MAX_AUDIO_DEV_LEN (16) -typedef struct audio_device { - char name[MAX_AUDIO_DEV_LEN]; - char version[MAX_AUDIO_DEV_LEN]; - char config[MAX_AUDIO_DEV_LEN]; -} audio_device_t; - - -/* - * Ioctl calls for the audio device. - */ - -/* - * AUDIO_GETINFO retrieves the current state of the audio device. - * - * AUDIO_SETINFO copies all fields of the audio_info structure whose - * values are not set to the initialized value (-1) to the device state. - * It performs an implicit AUDIO_GETINFO to return the new state of the - * device. Note that the record.samples and play.samples fields are set - * to the last value before the AUDIO_SETINFO took effect. This allows - * an application to reset the counters while atomically retrieving the - * last value. - * - * AUDIO_DRAIN suspends the calling process until the write buffers are - * empty. - * - * AUDIO_GETDEV returns a structure of type audio_device_t which contains - * three strings. The string "name" is a short identifying string (for - * example, the SBus Fcode name string), the string "version" identifies - * the current version of the device, and the "config" string identifies - * the specific configuration of the audio stream. All fields are - * device-dependent -- see the device specific manual pages for details. - * - * AUDIO_GETDEV_SUNOS returns a number which is an audio device defined - * herein (making it not too portable) - * - * AUDIO_FLUSH stops all playback and recording, clears all queued buffers, - * resets error counters, and restarts recording and playback as appropriate - * for the current sampling mode. - */ -#define AUDIO_GETINFO _IOR('A', 1, audio_info_t) -#define AUDIO_SETINFO _IOWR('A', 2, audio_info_t) -#define AUDIO_DRAIN _IO('A', 3) -#define AUDIO_GETDEV _IOR('A', 4, audio_device_t) -#define AUDIO_GETDEV_SUNOS _IOR('A', 4, int) -#define AUDIO_FLUSH _IO('A', 5) - -/* Define possible audio hardware configurations for - * old SunOS-style AUDIO_GETDEV ioctl */ -#define AUDIO_DEV_UNKNOWN (0) /* not defined */ -#define AUDIO_DEV_AMD (1) /* audioamd device */ -#define AUDIO_DEV_SPEAKERBOX (2) /* dbri device with speakerbox */ -#define AUDIO_DEV_CODEC (3) /* dbri device (internal speaker) */ -#define AUDIO_DEV_CS4231 (5) /* cs4231 device */ - -/* - * The following ioctl sets the audio device into an internal loopback mode, - * if the hardware supports this. The argument is TRUE to set loopback, - * FALSE to reset to normal operation. If the hardware does not support - * internal loopback, the ioctl should fail with EINVAL. - * Causes ADC data to be digitally mixed in and sent to the DAC. - */ -#define AUDIO_DIAG_LOOPBACK _IOW('A', 101, int) - -#endif /* _AUDIOIO_H_ */ diff --git a/include/asm-sparc64/audioio.h b/include/asm-sparc64/audioio.h deleted file mode 100644 index cf16173f521..00000000000 --- a/include/asm-sparc64/audioio.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - * include/asm-sparc/audioio.h - * - * Sparc Audio Midlayer - * Copyright (C) 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu) - */ - -#ifndef _AUDIOIO_H_ -#define _AUDIOIO_H_ - -/* - * SunOS/Solaris /dev/audio interface - */ - -#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) -#include -#include -#include -#endif - -/* - * This structure contains state information for audio device IO streams. - */ -typedef struct audio_prinfo { - /* - * The following values describe the audio data encoding. - */ - unsigned int sample_rate; /* samples per second */ - unsigned int channels; /* number of interleaved channels */ - unsigned int precision; /* bit-width of each sample */ - unsigned int encoding; /* data encoding method */ - - /* - * The following values control audio device configuration - */ - unsigned int gain; /* gain level: 0 - 255 */ - unsigned int port; /* selected I/O port (see below) */ - unsigned int avail_ports; /* available I/O ports (see below) */ - unsigned int _xxx[2]; /* Reserved for future use */ - - unsigned int buffer_size; /* I/O buffer size */ - - /* - * The following values describe driver state - */ - unsigned int samples; /* number of samples converted */ - unsigned int eof; /* End Of File counter (play only) */ - - unsigned char pause; /* non-zero for pause, zero to resume */ - unsigned char error; /* non-zero if overflow/underflow */ - unsigned char waiting; /* non-zero if a process wants access */ - unsigned char balance; /* stereo channel balance */ - - unsigned short minordev; - - /* - * The following values are read-only state flags - */ - unsigned char open; /* non-zero if open access permitted */ - unsigned char active; /* non-zero if I/O is active */ -} audio_prinfo_t; - - -/* - * This structure describes the current state of the audio device. - */ -typedef struct audio_info { - /* - * Per-stream information - */ - audio_prinfo_t play; /* output status information */ - audio_prinfo_t record; /* input status information */ - - /* - * Per-unit/channel information - */ - unsigned int monitor_gain; /* input to output mix: 0 - 255 */ - unsigned char output_muted; /* non-zero if output is muted */ - unsigned char _xxx[3]; /* Reserved for future use */ - unsigned int _yyy[3]; /* Reserved for future use */ -} audio_info_t; - - -/* - * Audio encoding types - */ -#define AUDIO_ENCODING_NONE (0) /* no encoding assigned */ -#define AUDIO_ENCODING_ULAW (1) /* u-law encoding */ -#define AUDIO_ENCODING_ALAW (2) /* A-law encoding */ -#define AUDIO_ENCODING_LINEAR (3) /* Linear PCM encoding */ -#define AUDIO_ENCODING_FLOAT (4) /* IEEE float (-1. <-> +1.) */ -#define AUDIO_ENCODING_DVI (104) /* DVI ADPCM */ -#define AUDIO_ENCODING_LINEAR8 (105) /* 8 bit UNSIGNED */ -#define AUDIO_ENCODING_LINEARLE (106) /* Linear PCM LE encoding */ - -/* - * These ranges apply to record, play, and monitor gain values - */ -#define AUDIO_MIN_GAIN (0) /* minimum gain value */ -#define AUDIO_MAX_GAIN (255) /* maximum gain value */ - -/* - * These values apply to the balance field to adjust channel gain values - */ -#define AUDIO_LEFT_BALANCE (0) /* left channel only */ -#define AUDIO_MID_BALANCE (32) /* equal left/right channel */ -#define AUDIO_RIGHT_BALANCE (64) /* right channel only */ -#define AUDIO_BALANCE_SHIFT (3) - -/* - * Generic minimum/maximum limits for number of channels, both modes - */ -#define AUDIO_MIN_PLAY_CHANNELS (1) -#define AUDIO_MAX_PLAY_CHANNELS (4) -#define AUDIO_MIN_REC_CHANNELS (1) -#define AUDIO_MAX_REC_CHANNELS (4) - -/* - * Generic minimum/maximum limits for sample precision - */ -#define AUDIO_MIN_PLAY_PRECISION (8) -#define AUDIO_MAX_PLAY_PRECISION (32) -#define AUDIO_MIN_REC_PRECISION (8) -#define AUDIO_MAX_REC_PRECISION (32) - -/* - * Define some convenient names for typical audio ports - */ -/* - * output ports (several may be enabled simultaneously) - */ -#define AUDIO_SPEAKER 0x01 /* output to built-in speaker */ -#define AUDIO_HEADPHONE 0x02 /* output to headphone jack */ -#define AUDIO_LINE_OUT 0x04 /* output to line out */ - -/* - * input ports (usually only one at a time) - */ -#define AUDIO_MICROPHONE 0x01 /* input from microphone */ -#define AUDIO_LINE_IN 0x02 /* input from line in */ -#define AUDIO_CD 0x04 /* input from on-board CD inputs */ -#define AUDIO_INTERNAL_CD_IN AUDIO_CD /* input from internal CDROM */ -#define AUDIO_ANALOG_LOOPBACK 0x40 /* input from output */ - - -/* - * This macro initializes an audio_info structure to 'harmless' values. - * Note that (~0) might not be a harmless value for a flag that was - * a signed int. - */ -#define AUDIO_INITINFO(i) { \ - unsigned int *__x__; \ - for (__x__ = (unsigned int *)(i); \ - (char *) __x__ < (((char *)(i)) + sizeof (audio_info_t)); \ - *__x__++ = ~0); \ -} - -/* - * These allow testing for what the user wants to set - */ -#define AUD_INITVALUE (~0) -#define Modify(X) ((unsigned int)(X) != AUD_INITVALUE) -#define Modifys(X) ((X) != (unsigned short)AUD_INITVALUE) -#define Modifyc(X) ((X) != (unsigned char)AUD_INITVALUE) - -/* - * Parameter for the AUDIO_GETDEV ioctl to determine current - * audio devices. - */ -#define MAX_AUDIO_DEV_LEN (16) -typedef struct audio_device { - char name[MAX_AUDIO_DEV_LEN]; - char version[MAX_AUDIO_DEV_LEN]; - char config[MAX_AUDIO_DEV_LEN]; -} audio_device_t; - - -/* - * Ioctl calls for the audio device. - */ - -/* - * AUDIO_GETINFO retrieves the current state of the audio device. - * - * AUDIO_SETINFO copies all fields of the audio_info structure whose - * values are not set to the initialized value (-1) to the device state. - * It performs an implicit AUDIO_GETINFO to return the new state of the - * device. Note that the record.samples and play.samples fields are set - * to the last value before the AUDIO_SETINFO took effect. This allows - * an application to reset the counters while atomically retrieving the - * last value. - * - * AUDIO_DRAIN suspends the calling process until the write buffers are - * empty. - * - * AUDIO_GETDEV returns a structure of type audio_device_t which contains - * three strings. The string "name" is a short identifying string (for - * example, the SBus Fcode name string), the string "version" identifies - * the current version of the device, and the "config" string identifies - * the specific configuration of the audio stream. All fields are - * device-dependent -- see the device specific manual pages for details. - * - * AUDIO_GETDEV_SUNOS returns a number which is an audio device defined - * herein (making it not too portable) - * - * AUDIO_FLUSH stops all playback and recording, clears all queued buffers, - * resets error counters, and restarts recording and playback as appropriate - * for the current sampling mode. - */ -#define AUDIO_GETINFO _IOR('A', 1, audio_info_t) -#define AUDIO_SETINFO _IOWR('A', 2, audio_info_t) -#define AUDIO_DRAIN _IO('A', 3) -#define AUDIO_GETDEV _IOR('A', 4, audio_device_t) -#define AUDIO_GETDEV_SUNOS _IOR('A', 4, int) -#define AUDIO_FLUSH _IO('A', 5) - -/* Define possible audio hardware configurations for - * old SunOS-style AUDIO_GETDEV ioctl */ -#define AUDIO_DEV_UNKNOWN (0) /* not defined */ -#define AUDIO_DEV_AMD (1) /* audioamd device */ -#define AUDIO_DEV_SPEAKERBOX (2) /* dbri device with speakerbox */ -#define AUDIO_DEV_CODEC (3) /* dbri device (internal speaker) */ -#define AUDIO_DEV_CS4231 (5) /* cs4231 device */ - -/* - * The following ioctl sets the audio device into an internal loopback mode, - * if the hardware supports this. The argument is TRUE to set loopback, - * FALSE to reset to normal operation. If the hardware does not support - * internal loopback, the ioctl should fail with EINVAL. - * Causes ADC data to be digitally mixed in and sent to the DAC. - */ -#define AUDIO_DIAG_LOOPBACK _IOW('A', 101, int) - -#endif /* _AUDIOIO_H_ */ -- cgit v1.2.3 From e1413315b8dfcdebc61416dadc1334619dfb4543 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 14:11:25 -0800 Subject: [SPARC]: remove kbio.h The old keyboard driver is gone in 2.6, so the only user left are the compat ioctls. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- arch/sparc64/kernel/ioctl32.c | 11 --------- include/asm-sparc/kbio.h | 56 ------------------------------------------- include/asm-sparc64/kbio.h | 56 ------------------------------------------- 3 files changed, 123 deletions(-) delete mode 100644 include/asm-sparc/kbio.h delete mode 100644 include/asm-sparc64/kbio.h diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index 6fda044a737..947bd265aaa 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -473,16 +472,6 @@ COMPATIBLE_IOCTL(FBIOSCURPOS) COMPATIBLE_IOCTL(FBIOGCURPOS) COMPATIBLE_IOCTL(FBIOGCURMAX) /* Little k */ -COMPATIBLE_IOCTL(KIOCTYPE) -COMPATIBLE_IOCTL(KIOCLAYOUT) -COMPATIBLE_IOCTL(KIOCGTRANS) -COMPATIBLE_IOCTL(KIOCTRANS) -COMPATIBLE_IOCTL(KIOCCMD) -COMPATIBLE_IOCTL(KIOCSDIRECT) -COMPATIBLE_IOCTL(KIOCSLED) -COMPATIBLE_IOCTL(KIOCGLED) -COMPATIBLE_IOCTL(KIOCSRATE) -COMPATIBLE_IOCTL(KIOCGRATE) COMPATIBLE_IOCTL(VUIDSFORMAT) COMPATIBLE_IOCTL(VUIDGFORMAT) /* Little v, the video4linux ioctls */ diff --git a/include/asm-sparc/kbio.h b/include/asm-sparc/kbio.h deleted file mode 100644 index 3cf496bdf39..00000000000 --- a/include/asm-sparc/kbio.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef __LINUX_KBIO_H -#define __LINUX_KBIO_H - -/* Return keyboard type */ -#define KIOCTYPE _IOR('k', 9, int) -/* Return Keyboard layout */ -#define KIOCLAYOUT _IOR('k', 20, int) - -enum { - TR_NONE, - TR_ASCII, /* keyboard is in regular state */ - TR_EVENT, /* keystrokes sent as firm events */ - TR_UNTRANS_EVENT /* EVENT+up and down+no translation */ -}; - -/* Return the current keyboard translation */ -#define KIOCGTRANS _IOR('k', 5, int) -/* Set the keyboard translation */ -#define KIOCTRANS _IOW('k', 0, int) - -/* Send a keyboard command */ -#define KIOCCMD _IOW('k', 8, int) - -/* Return if keystrokes are being sent to /dev/kbd */ - -/* Set routing of keystrokes to /dev/kbd */ -#define KIOCSDIRECT _IOW('k', 10, int) - -/* Set keyboard leds */ -#define KIOCSLED _IOW('k', 14, unsigned char) - -/* Get keyboard leds */ -#define KIOCGLED _IOR('k', 15, unsigned char) - -/* Used by KIOC[GS]RATE */ -struct kbd_rate { - unsigned char delay; /* Delay in Hz before first repeat. */ - unsigned char rate; /* In characters per second (0..50). */ -}; - -/* Set keyboard rate */ -#define KIOCSRATE _IOW('k', 40, struct kbd_rate) - -/* Get keyboard rate */ -#define KIOCGRATE _IOW('k', 41, struct kbd_rate) - -/* Top bit records if the key is up or down */ -#define KBD_UP 0x80 - -/* Usable information */ -#define KBD_KEYMASK 0x7f - -/* All keys up */ -#define KBD_IDLE 0x75 - -#endif /* __LINUX_KBIO_H */ diff --git a/include/asm-sparc64/kbio.h b/include/asm-sparc64/kbio.h deleted file mode 100644 index 3cf496bdf39..00000000000 --- a/include/asm-sparc64/kbio.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef __LINUX_KBIO_H -#define __LINUX_KBIO_H - -/* Return keyboard type */ -#define KIOCTYPE _IOR('k', 9, int) -/* Return Keyboard layout */ -#define KIOCLAYOUT _IOR('k', 20, int) - -enum { - TR_NONE, - TR_ASCII, /* keyboard is in regular state */ - TR_EVENT, /* keystrokes sent as firm events */ - TR_UNTRANS_EVENT /* EVENT+up and down+no translation */ -}; - -/* Return the current keyboard translation */ -#define KIOCGTRANS _IOR('k', 5, int) -/* Set the keyboard translation */ -#define KIOCTRANS _IOW('k', 0, int) - -/* Send a keyboard command */ -#define KIOCCMD _IOW('k', 8, int) - -/* Return if keystrokes are being sent to /dev/kbd */ - -/* Set routing of keystrokes to /dev/kbd */ -#define KIOCSDIRECT _IOW('k', 10, int) - -/* Set keyboard leds */ -#define KIOCSLED _IOW('k', 14, unsigned char) - -/* Get keyboard leds */ -#define KIOCGLED _IOR('k', 15, unsigned char) - -/* Used by KIOC[GS]RATE */ -struct kbd_rate { - unsigned char delay; /* Delay in Hz before first repeat. */ - unsigned char rate; /* In characters per second (0..50). */ -}; - -/* Set keyboard rate */ -#define KIOCSRATE _IOW('k', 40, struct kbd_rate) - -/* Get keyboard rate */ -#define KIOCGRATE _IOW('k', 41, struct kbd_rate) - -/* Top bit records if the key is up or down */ -#define KBD_UP 0x80 - -/* Usable information */ -#define KBD_KEYMASK 0x7f - -/* All keys up */ -#define KBD_IDLE 0x75 - -#endif /* __LINUX_KBIO_H */ -- cgit v1.2.3 From 59f85dc95e81281b424b2eb0e7b002cf7f77db03 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 14:11:38 -0800 Subject: [SPARC]: remove vuid_event.h I don't know if we ever implemented this, but the only user in any 2.6 tree are the compat ioctls. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- arch/sparc64/kernel/ioctl32.c | 3 --- include/asm-m68k/vuid_event.h | 4 ---- include/asm-sparc/vuid_event.h | 41 ---------------------------------------- include/asm-sparc64/vuid_event.h | 40 --------------------------------------- 4 files changed, 88 deletions(-) delete mode 100644 include/asm-m68k/vuid_event.h delete mode 100644 include/asm-sparc/vuid_event.h delete mode 100644 include/asm-sparc64/vuid_event.h diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index 947bd265aaa..94e2b99802c 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -472,8 +471,6 @@ COMPATIBLE_IOCTL(FBIOSCURPOS) COMPATIBLE_IOCTL(FBIOGCURPOS) COMPATIBLE_IOCTL(FBIOGCURMAX) /* Little k */ -COMPATIBLE_IOCTL(VUIDSFORMAT) -COMPATIBLE_IOCTL(VUIDGFORMAT) /* Little v, the video4linux ioctls */ COMPATIBLE_IOCTL(_IOR('p', 20, int[7])) /* RTCGET */ COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */ diff --git a/include/asm-m68k/vuid_event.h b/include/asm-m68k/vuid_event.h deleted file mode 100644 index 52ecb521a39..00000000000 --- a/include/asm-m68k/vuid_event.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef _M68K_VUID_EVENT_H -#define _M68K_VUID_EVENT_H -#include -#endif diff --git a/include/asm-sparc/vuid_event.h b/include/asm-sparc/vuid_event.h deleted file mode 100644 index 7781e9f2fdd..00000000000 --- a/include/asm-sparc/vuid_event.h +++ /dev/null @@ -1,41 +0,0 @@ -/* SunOS Virtual User Input Device (VUID) compatibility */ - - -typedef struct firm_event { - unsigned short id; /* tag for this event */ - unsigned char pair_type; /* unused by X11 */ - unsigned char pair; /* unused by X11 */ - int value; /* VKEY_UP, VKEY_DOWN or delta */ - struct timeval time; -} Firm_event; - -enum { - FE_PAIR_NONE, - FE_PAIR_SET, - FE_PAIR_DELTA, - FE_PAIR_ABSOLUTE -}; - -/* VUID stream formats */ -#define VUID_NATIVE 0 /* Native byte stream format */ -#define VUID_FIRM_EVENT 1 /* send firm_event structures */ - -/* ioctls */ - /* Set input device byte stream format (any of VUID_{NATIVE,FIRM_EVENT}) */ -#define VUIDSFORMAT _IOW('v', 1, int) - /* Retrieve input device byte stream format */ -#define VUIDGFORMAT _IOR('v', 2, int) - -/* Possible tag values */ -/* mouse buttons: */ -#define MS_LEFT 0x7f20 -#define MS_MIDDLE 0x7f21 -#define MS_RIGHT 0x7f22 -/* motion: */ -#define LOC_X_DELTA 0x7f80 -#define LOC_Y_DELTA 0x7f81 -#define LOC_X_ABSOLUTE 0x7f82 /* X compat, unsupported */ -#define LOC_Y_ABSOLUTE 0x7f83 /* X compat, unsupported */ - -#define VKEY_UP 0 -#define VKEY_DOWN 1 diff --git a/include/asm-sparc64/vuid_event.h b/include/asm-sparc64/vuid_event.h deleted file mode 100644 index 9ef4d17ad08..00000000000 --- a/include/asm-sparc64/vuid_event.h +++ /dev/null @@ -1,40 +0,0 @@ -/* SunOS Virtual User Input Device (VUID) compatibility */ - -typedef struct firm_event { - unsigned short id; /* tag for this event */ - unsigned char pair_type; /* unused by X11 */ - unsigned char pair; /* unused by X11 */ - int value; /* VKEY_UP, VKEY_DOWN or delta */ - struct timeval time; -} Firm_event; - -enum { - FE_PAIR_NONE, - FE_PAIR_SET, - FE_PAIR_DELTA, - FE_PAIR_ABSOLUTE -}; - -/* VUID stream formats */ -#define VUID_NATIVE 0 /* Native byte stream format */ -#define VUID_FIRM_EVENT 1 /* send firm_event structures */ - -/* ioctls */ - /* Set input device byte stream format (any of VUID_{NATIVE,FIRM_EVENT}) */ -#define VUIDSFORMAT _IOW('v', 1, int) - /* Retrieve input device byte stream format */ -#define VUIDGFORMAT _IOR('v', 2, int) - -/* Possible tag values */ -/* mouse buttons: */ -#define MS_LEFT 0x7f20 -#define MS_MIDDLE 0x7f21 -#define MS_RIGHT 0x7f22 -/* motion: */ -#define LOC_X_DELTA 0x7f80 -#define LOC_Y_DELTA 0x7f81 -#define LOC_X_ABSOLUTE 0x7f82 /* X compat, unsupported */ -#define LOC_Y_ABSOLUTE 0x7f83 /* X compat, unsupported */ - -#define VKEY_UP 0 -#define VKEY_DOWN 1 -- cgit v1.2.3 From 261b033afc2db37ad371263db2e1316f37c8ed51 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 14:11:49 -0800 Subject: [SPARC64]: remove duplicated compat ioctl entries all these are handled by fs/compat_ioctls.c already. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- arch/sparc64/kernel/ioctl32.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index 94e2b99802c..fa486229c61 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -505,11 +505,7 @@ COMPATIBLE_IOCTL(OPROMGETBOOTARGS) COMPATIBLE_IOCTL(OPROMSETCUR) COMPATIBLE_IOCTL(OPROMPCI2NODE) COMPATIBLE_IOCTL(OPROMPATH2NODE) -/* Big L */ -COMPATIBLE_IOCTL(LOOP_SET_STATUS64) -COMPATIBLE_IOCTL(LOOP_GET_STATUS64) /* Big A */ -COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI) #if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) COMPATIBLE_IOCTL(DRM_IOCTL_GET_MAGIC) COMPATIBLE_IOCTL(DRM_IOCTL_IRQ_BUSID) -- cgit v1.2.3 From 59871bcd1197014aacdf8e398c407cab70ab74e7 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 7 Nov 2005 14:12:08 -0800 Subject: [SPARC64] mm: simpler tlb_flush_mmu Minor simplification to the sparc64 tlb_flush_mmu: tlb_remove_page set need_flush only after handling the tlb_fast_mode case, then tlb_flush_mmu need not consider whether it's tlb_fast_mode. Signed-off-by: Hugh Dickins Signed-off-by: David S. Miller --- include/asm-sparc64/tlb.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/include/asm-sparc64/tlb.h b/include/asm-sparc64/tlb.h index 1eda17954f3..61c01882b56 100644 --- a/include/asm-sparc64/tlb.h +++ b/include/asm-sparc64/tlb.h @@ -58,11 +58,9 @@ static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm, unsigned i static inline void tlb_flush_mmu(struct mmu_gather *mp) { if (mp->need_flush) { + free_pages_and_swap_cache(mp->pages, mp->pages_nr); + mp->pages_nr = 0; mp->need_flush = 0; - if (!tlb_fast_mode(mp)) { - free_pages_and_swap_cache(mp->pages, mp->pages_nr); - mp->pages_nr = 0; - } } } @@ -91,11 +89,11 @@ static inline void tlb_finish_mmu(struct mmu_gather *mp, unsigned long start, un static inline void tlb_remove_page(struct mmu_gather *mp, struct page *page) { - mp->need_flush = 1; if (tlb_fast_mode(mp)) { free_page_and_swap_cache(page); return; } + mp->need_flush = 1; mp->pages[mp->pages_nr++] = page; if (mp->pages_nr >= FREE_PTE_NR) tlb_flush_mmu(mp); -- cgit v1.2.3 From 16cf0d816541fde06ed8f37c0f5cf9940cdfc145 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 14:12:21 -0800 Subject: [SPARC]: Kill remaining kbio.h references. Would you mind applying the following patch that kills those two + the m68k and Documentation/ references? Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- Documentation/ioctl-number.txt | 2 -- arch/sparc/kernel/sunos_ioctl.c | 1 - arch/sparc64/kernel/sunos_ioctl32.c | 1 - include/asm-m68k/kbio.h | 1 - 4 files changed, 5 deletions(-) delete mode 100644 include/asm-m68k/kbio.h diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt index 769f925c852..87f4d052e39 100644 --- a/Documentation/ioctl-number.txt +++ b/Documentation/ioctl-number.txt @@ -130,8 +130,6 @@ Code Seq# Include File Comments 'i' 00-3F linux/i2o.h 'j' 00-3F linux/joystick.h -'k' all asm-sparc/kbio.h - asm-sparc64/kbio.h 'l' 00-3F linux/tcfs_fs.h transparent cryptographic file system 'l' 40-7F linux/udf_fs_i.h in development: diff --git a/arch/sparc/kernel/sunos_ioctl.c b/arch/sparc/kernel/sunos_ioctl.c index df1c0b31a93..a6ba3d26222 100644 --- a/arch/sparc/kernel/sunos_ioctl.c +++ b/arch/sparc/kernel/sunos_ioctl.c @@ -23,7 +23,6 @@ #include #include #include -#include #if 0 extern char sunkbd_type; diff --git a/arch/sparc64/kernel/sunos_ioctl32.c b/arch/sparc64/kernel/sunos_ioctl32.c index 7654b8a7f03..3f619ead22c 100644 --- a/arch/sparc64/kernel/sunos_ioctl32.c +++ b/arch/sparc64/kernel/sunos_ioctl32.c @@ -24,7 +24,6 @@ #include #include #include -#include #define SUNOS_NR_OPEN 256 diff --git a/include/asm-m68k/kbio.h b/include/asm-m68k/kbio.h deleted file mode 100644 index e1fbf8fba3e..00000000000 --- a/include/asm-m68k/kbio.h +++ /dev/null @@ -1 +0,0 @@ -#include -- cgit v1.2.3 From 1928f8e541245eae933f8c95b64b2bc3683f9661 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 14:12:34 -0800 Subject: [SPARC] envctrl: implement ->unlocked_ioctl and ->compat_ioctl all the ioctls in the driver are 32bit compat clean and don't need BKL, so we can switch it to ->unlocked_ioctl and ->compat_ioctl trivially. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- arch/sparc64/kernel/ioctl32.c | 10 ---------- drivers/sbus/char/envctrl.c | 18 ++++++++++-------- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index fa486229c61..d20c8098cdf 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -474,16 +474,6 @@ COMPATIBLE_IOCTL(FBIOGCURMAX) /* Little v, the video4linux ioctls */ COMPATIBLE_IOCTL(_IOR('p', 20, int[7])) /* RTCGET */ COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */ -COMPATIBLE_IOCTL(ENVCTRL_RD_WARNING_TEMPERATURE) -COMPATIBLE_IOCTL(ENVCTRL_RD_SHUTDOWN_TEMPERATURE) -COMPATIBLE_IOCTL(ENVCTRL_RD_CPU_TEMPERATURE) -COMPATIBLE_IOCTL(ENVCTRL_RD_FAN_STATUS) -COMPATIBLE_IOCTL(ENVCTRL_RD_VOLTAGE_STATUS) -COMPATIBLE_IOCTL(ENVCTRL_RD_SCSI_TEMPERATURE) -COMPATIBLE_IOCTL(ENVCTRL_RD_ETHERNET_TEMPERATURE) -COMPATIBLE_IOCTL(ENVCTRL_RD_MTHRBD_TEMPERATURE) -COMPATIBLE_IOCTL(ENVCTRL_RD_CPU_VOLTAGE) -COMPATIBLE_IOCTL(ENVCTRL_RD_GLOBALADDRESS) /* COMPATIBLE_IOCTL(D7SIOCRD) same value as ENVCTRL_RD_VOLTAGE_STATUS */ COMPATIBLE_IOCTL(D7SIOCWR) COMPATIBLE_IOCTL(D7SIOCTM) diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index ba56762b05f..19e8eddf887 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -654,9 +654,8 @@ envctrl_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) /* Function Description: Command what to read. Mapped to user ioctl(). * Return: Gives 0 for implemented commands, -EINVAL otherwise. */ -static int -envctrl_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long +envctrl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { char __user *infobuf; @@ -715,11 +714,14 @@ envctrl_release(struct inode *inode, struct file *file) } static struct file_operations envctrl_fops = { - .owner = THIS_MODULE, - .read = envctrl_read, - .ioctl = envctrl_ioctl, - .open = envctrl_open, - .release = envctrl_release, + .owner = THIS_MODULE, + .read = envctrl_read, + .unlocked_ioctl = envctrl_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = envctrl_ioctl, +#endif + .open = envctrl_open, + .release = envctrl_release, }; static struct miscdevice envctrl_dev = { -- cgit v1.2.3 From b31023fc24e5c39d246e9c6fc75dba1a2902c1d6 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 14:12:47 -0800 Subject: [SPARC] openprom: implement ->compat_ioctl implement a compat_ioctl handle in the driver instead of having table entries in sparc64 ioctl32.c (I plan to get rid of the arch ioctl32.c file eventually) Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- arch/sparc64/kernel/ioctl32.c | 18 ------------------ drivers/sbus/char/openprom.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index d20c8098cdf..ec4e08c523f 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -477,24 +477,6 @@ COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */ /* COMPATIBLE_IOCTL(D7SIOCRD) same value as ENVCTRL_RD_VOLTAGE_STATUS */ COMPATIBLE_IOCTL(D7SIOCWR) COMPATIBLE_IOCTL(D7SIOCTM) -/* OPENPROMIO, SunOS/Solaris only, the NetBSD one's have - * embedded pointers in the arg which we'd need to clean up... - */ -COMPATIBLE_IOCTL(OPROMGETOPT) -COMPATIBLE_IOCTL(OPROMSETOPT) -COMPATIBLE_IOCTL(OPROMNXTOPT) -COMPATIBLE_IOCTL(OPROMSETOPT2) -COMPATIBLE_IOCTL(OPROMNEXT) -COMPATIBLE_IOCTL(OPROMCHILD) -COMPATIBLE_IOCTL(OPROMGETPROP) -COMPATIBLE_IOCTL(OPROMNXTPROP) -COMPATIBLE_IOCTL(OPROMU2P) -COMPATIBLE_IOCTL(OPROMGETCONS) -COMPATIBLE_IOCTL(OPROMGETFBNAME) -COMPATIBLE_IOCTL(OPROMGETBOOTARGS) -COMPATIBLE_IOCTL(OPROMSETCUR) -COMPATIBLE_IOCTL(OPROMPCI2NODE) -COMPATIBLE_IOCTL(OPROMPATH2NODE) /* Big A */ #if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) COMPATIBLE_IOCTL(DRM_IOCTL_GET_MAGIC) diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c index 58ed3374957..5028ac21432 100644 --- a/drivers/sbus/char/openprom.c +++ b/drivers/sbus/char/openprom.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -565,6 +566,38 @@ static int openprom_ioctl(struct inode * inode, struct file * file, } } +static long openprom_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + long rval = -ENOTTY; + + /* + * SunOS/Solaris only, the NetBSD one's have embedded pointers in + * the arg which we'd need to clean up... + */ + switch (cmd) { + case OPROMGETOPT: + case OPROMSETOPT: + case OPROMNXTOPT: + case OPROMSETOPT2: + case OPROMNEXT: + case OPROMCHILD: + case OPROMGETPROP: + case OPROMNXTPROP: + case OPROMU2P: + case OPROMGETCONS: + case OPROMGETFBNAME: + case OPROMGETBOOTARGS: + case OPROMSETCUR: + case OPROMPCI2NODE: + case OPROMPATH2NODE: + lock_kernel(); + rval = openprom_ioctl(file->f_dentry->d_inode, file, cmd, arg); + lock_kernel(); + break; + } +} + static int openprom_open(struct inode * inode, struct file * file) { DATA *data; -- cgit v1.2.3 From 1d5d00bd9c44ab4730d353ee6ba0c8ebbff295c7 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 14:13:01 -0800 Subject: [SPARC] display7seg: implement ->unlocked_ioctl and ->compat_ioctl all ioctls are 32bit compat clean, so the driver can use ->compat_ioctl and ->unlocked_ioctl easily. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- arch/sparc64/kernel/ioctl32.c | 3 --- drivers/sbus/char/display7seg.c | 32 ++++++++++++++++++++------------ 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index ec4e08c523f..f8e9ffb125c 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -474,9 +474,6 @@ COMPATIBLE_IOCTL(FBIOGCURMAX) /* Little v, the video4linux ioctls */ COMPATIBLE_IOCTL(_IOR('p', 20, int[7])) /* RTCGET */ COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */ -/* COMPATIBLE_IOCTL(D7SIOCRD) same value as ENVCTRL_RD_VOLTAGE_STATUS */ -COMPATIBLE_IOCTL(D7SIOCWR) -COMPATIBLE_IOCTL(D7SIOCTM) /* Big A */ #if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) COMPATIBLE_IOCTL(DRM_IOCTL_GET_MAGIC) diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index 24ed5893b4f..39f54213a6d 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c @@ -15,6 +15,7 @@ #include #include #include /* request_region */ +#include #include #include /* EBus device */ #include /* OpenProm Library */ @@ -114,22 +115,25 @@ static int d7s_release(struct inode *inode, struct file *f) return 0; } -static int d7s_ioctl(struct inode *inode, struct file *f, - unsigned int cmd, unsigned long arg) +static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { __u8 regs = readb(d7s_regs); __u8 ireg = 0; + int error = 0 - if (D7S_MINOR != iminor(inode)) + if (D7S_MINOR != iminor(file->f_dentry->d_inode)) return -ENODEV; + lock_kernel(); switch (cmd) { case D7SIOCWR: /* assign device register values * we mask-out D7S_FLIP if in sol_compat mode */ - if (get_user(ireg, (int __user *) arg)) - return -EFAULT; + if (get_user(ireg, (int __user *) arg)) { + error = -EFAULT; + break; + } if (0 != sol_compat) { (regs & D7S_FLIP) ? (ireg |= D7S_FLIP) : (ireg &= ~D7S_FLIP); @@ -144,8 +148,10 @@ static int d7s_ioctl(struct inode *inode, struct file *f, * This driver will not misinform you about the state * of your hardware while in sol_compat mode */ - if (put_user(regs, (int __user *) arg)) - return -EFAULT; + if (put_user(regs, (int __user *) arg)) { + error = -EFAULT; + break; + } break; case D7SIOCTM: @@ -155,15 +161,17 @@ static int d7s_ioctl(struct inode *inode, struct file *f, writeb(regs, d7s_regs); break; }; + lock_kernel(); - return 0; + return error; } static struct file_operations d7s_fops = { - .owner = THIS_MODULE, - .ioctl = d7s_ioctl, - .open = d7s_open, - .release = d7s_release, + .owner = THIS_MODULE, + .unlocked_ioctl = d7s_ioctl, + .compat_ioctl = d7s_ioctl, + .open = d7s_open, + .release = d7s_release, }; static struct miscdevice d7s_miscdev = { D7S_MINOR, D7S_DEVNAME, &d7s_fops }; -- cgit v1.2.3 From b66621fef30e15810d459212bc8bdc274e08f14f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 14:13:14 -0800 Subject: [SPARC] cpwatchdog: implement ->compat_ioctl Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- arch/sparc64/kernel/ioctl32.c | 3 --- drivers/sbus/char/cpwatchdog.c | 24 ++++++++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index f8e9ffb125c..398ddbffc6a 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -496,9 +496,6 @@ COMPATIBLE_IOCTL(DRM_IOCTL_LOCK) COMPATIBLE_IOCTL(DRM_IOCTL_UNLOCK) COMPATIBLE_IOCTL(DRM_IOCTL_FINISH) #endif /* DRM */ -COMPATIBLE_IOCTL(WIOCSTART) -COMPATIBLE_IOCTL(WIOCSTOP) -COMPATIBLE_IOCTL(WIOCGSTAT) /* And these ioctls need translation */ /* Note SIOCRTMSG is no longer, so this is safe and * the user would have seen just an -EINVAL anyways. */ HANDLE_IOCTL(FBIOPUTCMAP32, fbiogetputcmap) diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c index c82abeb59d3..071ae24be89 100644 --- a/drivers/sbus/char/cpwatchdog.c +++ b/drivers/sbus/char/cpwatchdog.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -394,6 +395,28 @@ static int wd_ioctl(struct inode *inode, struct file *file, return(0); } +static long wd_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int rval = -ENOIOCTLCMD; + + switch (cmd) { + /* solaris ioctls are specific to this driver */ + case WIOCSTART: + case WIOCSTOP: + case WIOCGSTAT: + lock_kernel(); + rval = wd_ioctl(file->f_dentry->d_inode, file, cmd, arg); + lock_kernel(); + break; + /* everything else is handled by the generic compat layer */ + default: + break; + } + + return rval; +} + static ssize_t wd_write(struct file *file, const char __user *buf, size_t count, @@ -441,6 +464,7 @@ static irqreturn_t wd_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct file_operations wd_fops = { .owner = THIS_MODULE, .ioctl = wd_ioctl, + .compat_ioctl = wd_compat_ioctl, .open = wd_open, .write = wd_write, .read = wd_read, -- cgit v1.2.3 From f48497e38331464c25e564d9e76ee915ca55fea8 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 14:13:27 -0800 Subject: [SPARC64]: remove drm compat ioctl handling drivers/drm/ now implements proper ->compat_ioctl methods, so this isn't needed anymore. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- arch/sparc64/kernel/ioctl32.c | 384 ------------------------------------------ 1 file changed, 384 deletions(-) diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index 398ddbffc6a..5eab41c1b1c 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -97,357 +97,6 @@ static int fbiogscursor(unsigned int fd, unsigned int cmd, unsigned long arg) return sys_ioctl (fd, FBIOSCURSOR, (unsigned long)p); } -#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) -/* This really belongs in include/linux/drm.h -DaveM */ -#include "../../../drivers/char/drm/drm.h" - -typedef struct drm32_version { - int version_major; /* Major version */ - int version_minor; /* Minor version */ - int version_patchlevel;/* Patch level */ - int name_len; /* Length of name buffer */ - u32 name; /* Name of driver */ - int date_len; /* Length of date buffer */ - u32 date; /* User-space buffer to hold date */ - int desc_len; /* Length of desc buffer */ - u32 desc; /* User-space buffer to hold desc */ -} drm32_version_t; -#define DRM32_IOCTL_VERSION DRM_IOWR(0x00, drm32_version_t) - -static int drm32_version(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_version_t __user *uversion = (drm32_version_t __user *)arg; - drm_version_t __user *p = compat_alloc_user_space(sizeof(*p)); - compat_uptr_t addr; - int n; - int ret; - - if (clear_user(p, 3 * sizeof(int)) || - get_user(n, &uversion->name_len) || - put_user(n, &p->name_len) || - get_user(addr, &uversion->name) || - put_user(compat_ptr(addr), &p->name) || - get_user(n, &uversion->date_len) || - put_user(n, &p->date_len) || - get_user(addr, &uversion->date) || - put_user(compat_ptr(addr), &p->date) || - get_user(n, &uversion->desc_len) || - put_user(n, &p->desc_len) || - get_user(addr, &uversion->desc) || - put_user(compat_ptr(addr), &p->desc)) - return -EFAULT; - - ret = sys_ioctl(fd, DRM_IOCTL_VERSION, (unsigned long)p); - if (ret) - return ret; - - if (copy_in_user(uversion, p, 3 * sizeof(int)) || - get_user(n, &p->name_len) || - put_user(n, &uversion->name_len) || - get_user(n, &p->date_len) || - put_user(n, &uversion->date_len) || - get_user(n, &p->desc_len) || - put_user(n, &uversion->desc_len)) - return -EFAULT; - - return 0; -} - -typedef struct drm32_unique { - int unique_len; /* Length of unique */ - u32 unique; /* Unique name for driver instantiation */ -} drm32_unique_t; -#define DRM32_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm32_unique_t) -#define DRM32_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm32_unique_t) - -static int drm32_getsetunique(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_unique_t __user *uarg = (drm32_unique_t __user *)arg; - drm_unique_t __user *p = compat_alloc_user_space(sizeof(*p)); - compat_uptr_t addr; - int n; - int ret; - - if (get_user(n, &uarg->unique_len) || - put_user(n, &p->unique_len) || - get_user(addr, &uarg->unique) || - put_user(compat_ptr(addr), &p->unique)) - return -EFAULT; - - if (cmd == DRM32_IOCTL_GET_UNIQUE) - ret = sys_ioctl (fd, DRM_IOCTL_GET_UNIQUE, (unsigned long)p); - else - ret = sys_ioctl (fd, DRM_IOCTL_SET_UNIQUE, (unsigned long)p); - - if (ret) - return ret; - - if (get_user(n, &p->unique_len) || put_user(n, &uarg->unique_len)) - return -EFAULT; - - return 0; -} - -typedef struct drm32_map { - u32 offset; /* Requested physical address (0 for SAREA)*/ - u32 size; /* Requested physical size (bytes) */ - drm_map_type_t type; /* Type of memory to map */ - drm_map_flags_t flags; /* Flags */ - u32 handle; /* User-space: "Handle" to pass to mmap */ - /* Kernel-space: kernel-virtual address */ - int mtrr; /* MTRR slot used */ - /* Private data */ -} drm32_map_t; -#define DRM32_IOCTL_ADD_MAP DRM_IOWR(0x15, drm32_map_t) - -static int drm32_addmap(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_map_t __user *uarg = (drm32_map_t __user *) arg; - drm_map_t karg; - mm_segment_t old_fs; - u32 tmp; - int ret; - - ret = get_user(karg.offset, &uarg->offset); - ret |= get_user(karg.size, &uarg->size); - ret |= get_user(karg.type, &uarg->type); - ret |= get_user(karg.flags, &uarg->flags); - ret |= get_user(tmp, &uarg->handle); - ret |= get_user(karg.mtrr, &uarg->mtrr); - if (ret) - return -EFAULT; - - karg.handle = (void *) (unsigned long) tmp; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, DRM_IOCTL_ADD_MAP, (unsigned long) &karg); - set_fs(old_fs); - - if (!ret) { - ret = put_user(karg.offset, &uarg->offset); - ret |= put_user(karg.size, &uarg->size); - ret |= put_user(karg.type, &uarg->type); - ret |= put_user(karg.flags, &uarg->flags); - tmp = (u32) (long)karg.handle; - ret |= put_user(tmp, &uarg->handle); - ret |= put_user(karg.mtrr, &uarg->mtrr); - if (ret) - ret = -EFAULT; - } - - return ret; -} - -typedef struct drm32_buf_info { - int count; /* Entries in list */ - u32 list; /* (drm_buf_desc_t *) */ -} drm32_buf_info_t; -#define DRM32_IOCTL_INFO_BUFS DRM_IOWR(0x18, drm32_buf_info_t) - -static int drm32_info_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_buf_info_t __user *uarg = (drm32_buf_info_t __user *)arg; - drm_buf_info_t __user *p = compat_alloc_user_space(sizeof(*p)); - compat_uptr_t addr; - int n; - int ret; - - if (get_user(n, &uarg->count) || put_user(n, &p->count) || - get_user(addr, &uarg->list) || put_user(compat_ptr(addr), &p->list)) - return -EFAULT; - - ret = sys_ioctl(fd, DRM_IOCTL_INFO_BUFS, (unsigned long)p); - if (ret) - return ret; - - if (get_user(n, &p->count) || put_user(n, &uarg->count)) - return -EFAULT; - - return 0; -} - -typedef struct drm32_buf_free { - int count; - u32 list; /* (int *) */ -} drm32_buf_free_t; -#define DRM32_IOCTL_FREE_BUFS DRM_IOW( 0x1a, drm32_buf_free_t) - -static int drm32_free_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_buf_free_t __user *uarg = (drm32_buf_free_t __user *)arg; - drm_buf_free_t __user *p = compat_alloc_user_space(sizeof(*p)); - compat_uptr_t addr; - int n; - - if (get_user(n, &uarg->count) || put_user(n, &p->count) || - get_user(addr, &uarg->list) || put_user(compat_ptr(addr), &p->list)) - return -EFAULT; - - return sys_ioctl(fd, DRM_IOCTL_FREE_BUFS, (unsigned long)p); -} - -typedef struct drm32_buf_pub { - int idx; /* Index into master buflist */ - int total; /* Buffer size */ - int used; /* Amount of buffer in use (for DMA) */ - u32 address; /* Address of buffer (void *) */ -} drm32_buf_pub_t; - -typedef struct drm32_buf_map { - int count; /* Length of buflist */ - u32 virtual; /* Mmaped area in user-virtual (void *) */ - u32 list; /* Buffer information (drm_buf_pub_t *) */ -} drm32_buf_map_t; -#define DRM32_IOCTL_MAP_BUFS DRM_IOWR(0x19, drm32_buf_map_t) - -static int drm32_map_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_buf_map_t __user *uarg = (drm32_buf_map_t __user *)arg; - drm32_buf_pub_t __user *ulist; - drm_buf_map_t __user *arg64; - drm_buf_pub_t __user *list; - int orig_count, ret, i; - int n; - compat_uptr_t addr; - - if (get_user(orig_count, &uarg->count)) - return -EFAULT; - - arg64 = compat_alloc_user_space(sizeof(drm_buf_map_t) + - (size_t)orig_count * sizeof(drm_buf_pub_t)); - list = (void __user *)(arg64 + 1); - - if (put_user(orig_count, &arg64->count) || - put_user(list, &arg64->list) || - get_user(addr, &uarg->virtual) || - put_user(compat_ptr(addr), &arg64->virtual) || - get_user(addr, &uarg->list)) - return -EFAULT; - - ulist = compat_ptr(addr); - - for (i = 0; i < orig_count; i++) { - if (get_user(n, &ulist[i].idx) || - put_user(n, &list[i].idx) || - get_user(n, &ulist[i].total) || - put_user(n, &list[i].total) || - get_user(n, &ulist[i].used) || - put_user(n, &list[i].used) || - get_user(addr, &ulist[i].address) || - put_user(compat_ptr(addr), &list[i].address)) - return -EFAULT; - } - - ret = sys_ioctl(fd, DRM_IOCTL_MAP_BUFS, (unsigned long) arg64); - if (ret) - return ret; - - for (i = 0; i < orig_count; i++) { - void __user *p; - if (get_user(n, &list[i].idx) || - put_user(n, &ulist[i].idx) || - get_user(n, &list[i].total) || - put_user(n, &ulist[i].total) || - get_user(n, &list[i].used) || - put_user(n, &ulist[i].used) || - get_user(p, &list[i].address) || - put_user((unsigned long)p, &ulist[i].address)) - return -EFAULT; - } - - if (get_user(n, &arg64->count) || put_user(n, &uarg->count)) - return -EFAULT; - - return 0; -} - -typedef struct drm32_dma { - /* Indices here refer to the offset into - buflist in drm_buf_get_t. */ - int context; /* Context handle */ - int send_count; /* Number of buffers to send */ - u32 send_indices; /* List of handles to buffers (int *) */ - u32 send_sizes; /* Lengths of data to send (int *) */ - drm_dma_flags_t flags; /* Flags */ - int request_count; /* Number of buffers requested */ - int request_size; /* Desired size for buffers */ - u32 request_indices; /* Buffer information (int *) */ - u32 request_sizes; /* (int *) */ - int granted_count; /* Number of buffers granted */ -} drm32_dma_t; -#define DRM32_IOCTL_DMA DRM_IOWR(0x29, drm32_dma_t) - -/* RED PEN The DRM layer blindly dereferences the send/request - * index/size arrays even though they are userland - * pointers. -DaveM - */ -static int drm32_dma(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_dma_t __user *uarg = (drm32_dma_t __user *) arg; - drm_dma_t __user *p = compat_alloc_user_space(sizeof(*p)); - compat_uptr_t addr; - int ret; - - if (copy_in_user(p, uarg, 2 * sizeof(int)) || - get_user(addr, &uarg->send_indices) || - put_user(compat_ptr(addr), &p->send_indices) || - get_user(addr, &uarg->send_sizes) || - put_user(compat_ptr(addr), &p->send_sizes) || - copy_in_user(&p->flags, &uarg->flags, sizeof(drm_dma_flags_t)) || - copy_in_user(&p->request_count, &uarg->request_count, sizeof(int))|| - copy_in_user(&p->request_size, &uarg->request_size, sizeof(int)) || - get_user(addr, &uarg->request_indices) || - put_user(compat_ptr(addr), &p->request_indices) || - get_user(addr, &uarg->request_sizes) || - put_user(compat_ptr(addr), &p->request_sizes) || - copy_in_user(&p->granted_count, &uarg->granted_count, sizeof(int))) - return -EFAULT; - - ret = sys_ioctl(fd, DRM_IOCTL_DMA, (unsigned long)p); - if (ret) - return ret; - - if (copy_in_user(uarg, p, 2 * sizeof(int)) || - copy_in_user(&uarg->flags, &p->flags, sizeof(drm_dma_flags_t)) || - copy_in_user(&uarg->request_count, &p->request_count, sizeof(int))|| - copy_in_user(&uarg->request_size, &p->request_size, sizeof(int)) || - copy_in_user(&uarg->granted_count, &p->granted_count, sizeof(int))) - return -EFAULT; - - return 0; -} - -typedef struct drm32_ctx_res { - int count; - u32 contexts; /* (drm_ctx_t *) */ -} drm32_ctx_res_t; -#define DRM32_IOCTL_RES_CTX DRM_IOWR(0x26, drm32_ctx_res_t) - -static int drm32_res_ctx(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_ctx_res_t __user *uarg = (drm32_ctx_res_t __user *) arg; - drm_ctx_res_t __user *p = compat_alloc_user_space(sizeof(*p)); - compat_uptr_t addr; - int ret; - - if (copy_in_user(p, uarg, sizeof(int)) || - get_user(addr, &uarg->contexts) || - put_user(compat_ptr(addr), &p->contexts)) - return -EFAULT; - - ret = sys_ioctl(fd, DRM_IOCTL_RES_CTX, (unsigned long)p); - if (ret) - return ret; - - if (copy_in_user(uarg, p, sizeof(int))) - return -EFAULT; - - return 0; -} - -#endif - typedef int (* ioctl32_handler_t)(unsigned int, unsigned int, unsigned long, struct file *); #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),sys_ioctl) @@ -474,44 +123,11 @@ COMPATIBLE_IOCTL(FBIOGCURMAX) /* Little v, the video4linux ioctls */ COMPATIBLE_IOCTL(_IOR('p', 20, int[7])) /* RTCGET */ COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */ -/* Big A */ -#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) -COMPATIBLE_IOCTL(DRM_IOCTL_GET_MAGIC) -COMPATIBLE_IOCTL(DRM_IOCTL_IRQ_BUSID) -COMPATIBLE_IOCTL(DRM_IOCTL_AUTH_MAGIC) -COMPATIBLE_IOCTL(DRM_IOCTL_BLOCK) -COMPATIBLE_IOCTL(DRM_IOCTL_UNBLOCK) -COMPATIBLE_IOCTL(DRM_IOCTL_CONTROL) -COMPATIBLE_IOCTL(DRM_IOCTL_ADD_BUFS) -COMPATIBLE_IOCTL(DRM_IOCTL_MARK_BUFS) -COMPATIBLE_IOCTL(DRM_IOCTL_ADD_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_RM_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_MOD_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_GET_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_SWITCH_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_NEW_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_ADD_DRAW) -COMPATIBLE_IOCTL(DRM_IOCTL_RM_DRAW) -COMPATIBLE_IOCTL(DRM_IOCTL_LOCK) -COMPATIBLE_IOCTL(DRM_IOCTL_UNLOCK) -COMPATIBLE_IOCTL(DRM_IOCTL_FINISH) -#endif /* DRM */ /* And these ioctls need translation */ /* Note SIOCRTMSG is no longer, so this is safe and * the user would have seen just an -EINVAL anyways. */ HANDLE_IOCTL(FBIOPUTCMAP32, fbiogetputcmap) HANDLE_IOCTL(FBIOGETCMAP32, fbiogetputcmap) HANDLE_IOCTL(FBIOSCURSOR32, fbiogscursor) -#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) -HANDLE_IOCTL(DRM32_IOCTL_VERSION, drm32_version) -HANDLE_IOCTL(DRM32_IOCTL_GET_UNIQUE, drm32_getsetunique) -HANDLE_IOCTL(DRM32_IOCTL_SET_UNIQUE, drm32_getsetunique) -HANDLE_IOCTL(DRM32_IOCTL_ADD_MAP, drm32_addmap) -HANDLE_IOCTL(DRM32_IOCTL_INFO_BUFS, drm32_info_bufs) -HANDLE_IOCTL(DRM32_IOCTL_FREE_BUFS, drm32_free_bufs) -HANDLE_IOCTL(DRM32_IOCTL_MAP_BUFS, drm32_map_bufs) -HANDLE_IOCTL(DRM32_IOCTL_DMA, drm32_dma) -HANDLE_IOCTL(DRM32_IOCTL_RES_CTX, drm32_res_ctx) -#endif /* DRM */ #if 0 HANDLE_IOCTL(RTC32_IRQP_READ, do_rtc_ioctl) HANDLE_IOCTL(RTC32_IRQP_SET, do_rtc_ioctl) -- cgit v1.2.3 From dd3e2dcf3408843ed35501c28626f389b30be756 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 7 Nov 2005 14:13:46 -0800 Subject: [SPARC64]: Kill some unnecessary includes from ioctl32.c Signed-off-by: David S. Miller --- arch/sparc64/kernel/ioctl32.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index 5eab41c1b1c..92e26304de9 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -11,13 +11,8 @@ #define INCLUDES #include "compat_ioctl.c" -#include #include #include -#include -#include -#include -#include /* Use this to get at 32-bit user passed pointers. * See sys_sparc32.c for description about it. -- cgit v1.2.3 From 81f875208e7f46d003bedb82d5cfe54458a3ab60 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Mon, 24 Oct 2005 10:20:53 -0500 Subject: scripts/Lindent on ieee80211 subsystem. Signed-off-by: James Ketrenos --- net/ieee80211/ieee80211_wx.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c index 1ce7af9bec3..f5b80535500 100644 --- a/net/ieee80211/ieee80211_wx.c +++ b/net/ieee80211/ieee80211_wx.c @@ -161,9 +161,11 @@ static inline char *ipw2100_translate_scan(struct ieee80211_device *ieee, (ieee->perfect_rssi - ieee->worst_rssi) - (ieee->perfect_rssi - network->stats.rssi) * (15 * (ieee->perfect_rssi - ieee->worst_rssi) + - 62 * (ieee->perfect_rssi - network->stats.rssi))) / - ((ieee->perfect_rssi - ieee->worst_rssi) * - (ieee->perfect_rssi - ieee->worst_rssi)); + 62 * (ieee->perfect_rssi - + network->stats.rssi))) / + ((ieee->perfect_rssi - + ieee->worst_rssi) * (ieee->perfect_rssi - + ieee->worst_rssi)); if (iwe.u.qual.qual > 100) iwe.u.qual.qual = 100; else if (iwe.u.qual.qual < 1) -- cgit v1.2.3 From e189277a3f1cbb0f1282e0f4b8fa8c91e004c286 Mon Sep 17 00:00:00 2001 From: Volker Braun Date: Mon, 24 Oct 2005 10:15:36 -0500 Subject: Fix problem with WEP unicast key > index 0 The functions ieee80211_wx_{get,set}_encodeext fail if one tries to set unicast (IW_ENCODE_EXT_GROUP_KEY not set) keys at key indices>0. But at least some Cisco APs dish out dynamic WEP unicast keys at index !=0. Signed-off-by: Volker Braun Signed-off-by: James Ketrenos --- net/ieee80211/ieee80211_wx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c index f5b80535500..181755f2aa8 100644 --- a/net/ieee80211/ieee80211_wx.c +++ b/net/ieee80211/ieee80211_wx.c @@ -522,7 +522,8 @@ int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee, crypt = &ieee->crypt[idx]; group_key = 1; } else { - if (idx != 0) + /* some Cisco APs use idx>0 for unicast in dynamic WEP */ + if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP) return -EINVAL; if (ieee->iw_mode == IW_MODE_INFRA) crypt = &ieee->crypt[idx]; @@ -690,7 +691,8 @@ int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee, } else idx = ieee->tx_keyidx; - if (!ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) + if (!ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY && + ext->alg != IW_ENCODE_ALG_WEP) if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA) return -EINVAL; -- cgit v1.2.3 From d7e02edbc52bc689279154b117b90fe6635fc14b Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Mon, 24 Oct 2005 20:44:06 -0500 Subject: Update version ieee80211 stamp to 1.1.7 --- include/net/ieee80211.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h index 5e38dca1d08..b93fd8c1d88 100644 --- a/include/net/ieee80211.h +++ b/include/net/ieee80211.h @@ -29,7 +29,7 @@ #include /* ARRAY_SIZE */ #include -#define IEEE80211_VERSION "git-1.1.6" +#define IEEE80211_VERSION "git-1.1.7" #define IEEE80211_DATA_LEN 2304 /* Maximum size for the MA-UNITDATA primitive, 802.11 standard section -- cgit v1.2.3 From ee8e365aa6395e721399127ccf3d28d269136f0e Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Wed, 14 Sep 2005 09:47:29 -0500 Subject: Ran scripts/Lindent on drivers/net/wireless/ipw2{1,2}00.{c,h} No other changes. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2100.c | 2217 ++++++++++++++++++++-------------------- drivers/net/wireless/ipw2100.h | 156 ++- 2 files changed, 1155 insertions(+), 1218 deletions(-) diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index ad7f8cd76db..a15eef1c2a6 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -174,10 +174,9 @@ that only one external action is invoked at a time. #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2100 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation" - /* Debugging stuff */ #ifdef CONFIG_IPW_DEBUG -#define CONFIG_IPW2100_RX_DEBUG /* Reception debugging */ +#define CONFIG_IPW2100_RX_DEBUG /* Reception debugging */ #endif MODULE_DESCRIPTION(DRV_DESCRIPTION); @@ -220,18 +219,18 @@ do { \ } while (0) #else #define IPW_DEBUG(level, message...) do {} while (0) -#endif /* CONFIG_IPW_DEBUG */ +#endif /* CONFIG_IPW_DEBUG */ #ifdef CONFIG_IPW_DEBUG static const char *command_types[] = { "undefined", - "unused", /* HOST_ATTENTION */ + "unused", /* HOST_ATTENTION */ "HOST_COMPLETE", - "unused", /* SLEEP */ - "unused", /* HOST_POWER_DOWN */ + "unused", /* SLEEP */ + "unused", /* HOST_POWER_DOWN */ "unused", "SYSTEM_CONFIG", - "unused", /* SET_IMR */ + "unused", /* SET_IMR */ "SSID", "MANDATORY_BSSID", "AUTHENTICATION_TYPE", @@ -277,17 +276,16 @@ static const char *command_types[] = { "GROUP_ORDINALS", "SHORT_RETRY_LIMIT", "LONG_RETRY_LIMIT", - "unused", /* SAVE_CALIBRATION */ - "unused", /* RESTORE_CALIBRATION */ + "unused", /* SAVE_CALIBRATION */ + "unused", /* RESTORE_CALIBRATION */ "undefined", "undefined", "undefined", "HOST_PRE_POWER_DOWN", - "unused", /* HOST_INTERRUPT_COALESCING */ + "unused", /* HOST_INTERRUPT_COALESCING */ "undefined", "CARD_DISABLE_PHY_OFF", - "MSDU_TX_RATES" - "undefined", + "MSDU_TX_RATES" "undefined", "undefined", "SET_STATION_STAT_BITS", "CLEAR_STATIONS_STAT_BITS", @@ -298,7 +296,6 @@ static const char *command_types[] = { }; #endif - /* Pre-decl until we get the code solid and then we can clean it up */ static void ipw2100_tx_send_commands(struct ipw2100_priv *priv); static void ipw2100_tx_send_data(struct ipw2100_priv *priv); @@ -321,11 +318,10 @@ static void ipw2100_release_firmware(struct ipw2100_priv *priv, static int ipw2100_ucode_download(struct ipw2100_priv *priv, struct ipw2100_fw *fw); static void ipw2100_wx_event_work(struct ipw2100_priv *priv); -static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device * dev); +static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device *dev); static struct iw_handler_def ipw2100_wx_handler_def; - -static inline void read_register(struct net_device *dev, u32 reg, u32 *val) +static inline void read_register(struct net_device *dev, u32 reg, u32 * val) { *val = readl((void __iomem *)(dev->base_addr + reg)); IPW_DEBUG_IO("r: 0x%08X => 0x%08X\n", reg, *val); @@ -337,13 +333,14 @@ static inline void write_register(struct net_device *dev, u32 reg, u32 val) IPW_DEBUG_IO("w: 0x%08X <= 0x%08X\n", reg, val); } -static inline void read_register_word(struct net_device *dev, u32 reg, u16 *val) +static inline void read_register_word(struct net_device *dev, u32 reg, + u16 * val) { *val = readw((void __iomem *)(dev->base_addr + reg)); IPW_DEBUG_IO("r: 0x%08X => %04X\n", reg, *val); } -static inline void read_register_byte(struct net_device *dev, u32 reg, u8 *val) +static inline void read_register_byte(struct net_device *dev, u32 reg, u8 * val) { *val = readb((void __iomem *)(dev->base_addr + reg)); IPW_DEBUG_IO("r: 0x%08X => %02X\n", reg, *val); @@ -355,14 +352,13 @@ static inline void write_register_word(struct net_device *dev, u32 reg, u16 val) IPW_DEBUG_IO("w: 0x%08X <= %04X\n", reg, val); } - static inline void write_register_byte(struct net_device *dev, u32 reg, u8 val) { writeb(val, (void __iomem *)(dev->base_addr + reg)); IPW_DEBUG_IO("w: 0x%08X =< %02X\n", reg, val); } -static inline void read_nic_dword(struct net_device *dev, u32 addr, u32 *val) +static inline void read_nic_dword(struct net_device *dev, u32 addr, u32 * val) { write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS, addr & IPW_REG_INDIRECT_ADDR_MASK); @@ -376,7 +372,7 @@ static inline void write_nic_dword(struct net_device *dev, u32 addr, u32 val) write_register(dev, IPW_REG_INDIRECT_ACCESS_DATA, val); } -static inline void read_nic_word(struct net_device *dev, u32 addr, u16 *val) +static inline void read_nic_word(struct net_device *dev, u32 addr, u16 * val) { write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS, addr & IPW_REG_INDIRECT_ADDR_MASK); @@ -390,7 +386,7 @@ static inline void write_nic_word(struct net_device *dev, u32 addr, u16 val) write_register_word(dev, IPW_REG_INDIRECT_ACCESS_DATA, val); } -static inline void read_nic_byte(struct net_device *dev, u32 addr, u8 *val) +static inline void read_nic_byte(struct net_device *dev, u32 addr, u8 * val) { write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS, addr & IPW_REG_INDIRECT_ADDR_MASK); @@ -416,7 +412,7 @@ static inline void write_nic_dword_auto_inc(struct net_device *dev, u32 val) } static inline void write_nic_memory(struct net_device *dev, u32 addr, u32 len, - const u8 *buf) + const u8 * buf) { u32 aligned_addr; u32 aligned_len; @@ -431,32 +427,30 @@ static inline void write_nic_memory(struct net_device *dev, u32 addr, u32 len, write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS, aligned_addr); for (i = dif_len; i < 4; i++, buf++) - write_register_byte( - dev, IPW_REG_INDIRECT_ACCESS_DATA + i, - *buf); + write_register_byte(dev, + IPW_REG_INDIRECT_ACCESS_DATA + i, + *buf); len -= dif_len; aligned_addr += 4; } /* read DWs through autoincrement registers */ - write_register(dev, IPW_REG_AUTOINCREMENT_ADDRESS, - aligned_addr); + write_register(dev, IPW_REG_AUTOINCREMENT_ADDRESS, aligned_addr); aligned_len = len & (~0x3); for (i = 0; i < aligned_len; i += 4, buf += 4, aligned_addr += 4) - write_register( - dev, IPW_REG_AUTOINCREMENT_DATA, *(u32 *)buf); + write_register(dev, IPW_REG_AUTOINCREMENT_DATA, *(u32 *) buf); /* copy the last nibble */ dif_len = len - aligned_len; write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS, aligned_addr); for (i = 0; i < dif_len; i++, buf++) - write_register_byte( - dev, IPW_REG_INDIRECT_ACCESS_DATA + i, *buf); + write_register_byte(dev, IPW_REG_INDIRECT_ACCESS_DATA + i, + *buf); } static inline void read_nic_memory(struct net_device *dev, u32 addr, u32 len, - u8 *buf) + u8 * buf) { u32 aligned_addr; u32 aligned_len; @@ -471,39 +465,38 @@ static inline void read_nic_memory(struct net_device *dev, u32 addr, u32 len, write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS, aligned_addr); for (i = dif_len; i < 4; i++, buf++) - read_register_byte( - dev, IPW_REG_INDIRECT_ACCESS_DATA + i, buf); + read_register_byte(dev, + IPW_REG_INDIRECT_ACCESS_DATA + i, + buf); len -= dif_len; aligned_addr += 4; } /* read DWs through autoincrement registers */ - write_register(dev, IPW_REG_AUTOINCREMENT_ADDRESS, - aligned_addr); + write_register(dev, IPW_REG_AUTOINCREMENT_ADDRESS, aligned_addr); aligned_len = len & (~0x3); for (i = 0; i < aligned_len; i += 4, buf += 4, aligned_addr += 4) - read_register(dev, IPW_REG_AUTOINCREMENT_DATA, - (u32 *)buf); + read_register(dev, IPW_REG_AUTOINCREMENT_DATA, (u32 *) buf); /* copy the last nibble */ dif_len = len - aligned_len; - write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS, - aligned_addr); + write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS, aligned_addr); for (i = 0; i < dif_len; i++, buf++) - read_register_byte(dev, IPW_REG_INDIRECT_ACCESS_DATA + - i, buf); + read_register_byte(dev, IPW_REG_INDIRECT_ACCESS_DATA + i, buf); } static inline int ipw2100_hw_is_adapter_in_system(struct net_device *dev) { return (dev->base_addr && - (readl((void __iomem *)(dev->base_addr + IPW_REG_DOA_DEBUG_AREA_START)) + (readl + ((void __iomem *)(dev->base_addr + + IPW_REG_DOA_DEBUG_AREA_START)) == IPW_DATA_DOA_DEBUG_VALUE)); } static int ipw2100_get_ordinal(struct ipw2100_priv *priv, u32 ord, - void *val, u32 *len) + void *val, u32 * len) { struct ipw2100_ordinals *ordinals = &priv->ordinals; u32 addr; @@ -529,8 +522,8 @@ static int ipw2100_get_ordinal(struct ipw2100_priv *priv, u32 ord, return -EINVAL; } - read_nic_dword(priv->net_dev, ordinals->table1_addr + (ord << 2), - &addr); + read_nic_dword(priv->net_dev, + ordinals->table1_addr + (ord << 2), &addr); read_nic_dword(priv->net_dev, addr, val); *len = IPW_ORD_TAB_1_ENTRY_SIZE; @@ -543,8 +536,8 @@ static int ipw2100_get_ordinal(struct ipw2100_priv *priv, u32 ord, ord -= IPW_START_ORD_TAB_2; /* get the address of statistic */ - read_nic_dword(priv->net_dev, ordinals->table2_addr + (ord << 3), - &addr); + read_nic_dword(priv->net_dev, + ordinals->table2_addr + (ord << 3), &addr); /* get the second DW of statistics ; * two 16-bit words - first is length, second is count */ @@ -553,10 +546,10 @@ static int ipw2100_get_ordinal(struct ipw2100_priv *priv, u32 ord, &field_info); /* get each entry length */ - field_len = *((u16 *)&field_info); + field_len = *((u16 *) & field_info); /* get number of entries */ - field_count = *(((u16 *)&field_info) + 1); + field_count = *(((u16 *) & field_info) + 1); /* abort if no enought memory */ total_length = field_len * field_count; @@ -581,8 +574,8 @@ static int ipw2100_get_ordinal(struct ipw2100_priv *priv, u32 ord, return -EINVAL; } -static int ipw2100_set_ordinal(struct ipw2100_priv *priv, u32 ord, u32 *val, - u32 *len) +static int ipw2100_set_ordinal(struct ipw2100_priv *priv, u32 ord, u32 * val, + u32 * len) { struct ipw2100_ordinals *ordinals = &priv->ordinals; u32 addr; @@ -594,8 +587,8 @@ static int ipw2100_set_ordinal(struct ipw2100_priv *priv, u32 ord, u32 *val, return -EINVAL; } - read_nic_dword(priv->net_dev, ordinals->table1_addr + (ord << 2), - &addr); + read_nic_dword(priv->net_dev, + ordinals->table1_addr + (ord << 2), &addr); write_nic_dword(priv->net_dev, addr, *val); @@ -612,7 +605,7 @@ static int ipw2100_set_ordinal(struct ipw2100_priv *priv, u32 ord, u32 *val, } static char *snprint_line(char *buf, size_t count, - const u8 *data, u32 len, u32 ofs) + const u8 * data, u32 len, u32 ofs) { int out, i, j, l; char c; @@ -646,7 +639,7 @@ static char *snprint_line(char *buf, size_t count, return buf; } -static void printk_buf(int level, const u8 *data, u32 len) +static void printk_buf(int level, const u8 * data, u32 len) { char line[81]; u32 ofs = 0; @@ -662,8 +655,6 @@ static void printk_buf(int level, const u8 *data, u32 len) } } - - #define MAX_RESET_BACKOFF 10 static inline void schedule_reset(struct ipw2100_priv *priv) @@ -703,7 +694,7 @@ static inline void schedule_reset(struct ipw2100_priv *priv) #define HOST_COMPLETE_TIMEOUT (2 * HZ) static int ipw2100_hw_send_command(struct ipw2100_priv *priv, - struct host_command * cmd) + struct host_command *cmd) { struct list_head *element; struct ipw2100_tx_packet *packet; @@ -713,25 +704,28 @@ static int ipw2100_hw_send_command(struct ipw2100_priv *priv, IPW_DEBUG_HC("Sending %s command (#%d), %d bytes\n", command_types[cmd->host_command], cmd->host_command, cmd->host_command_length); - printk_buf(IPW_DL_HC, (u8*)cmd->host_command_parameters, + printk_buf(IPW_DL_HC, (u8 *) cmd->host_command_parameters, cmd->host_command_length); spin_lock_irqsave(&priv->low_lock, flags); if (priv->fatal_error) { - IPW_DEBUG_INFO("Attempt to send command while hardware in fatal error condition.\n"); + IPW_DEBUG_INFO + ("Attempt to send command while hardware in fatal error condition.\n"); err = -EIO; goto fail_unlock; } if (!(priv->status & STATUS_RUNNING)) { - IPW_DEBUG_INFO("Attempt to send command while hardware is not running.\n"); + IPW_DEBUG_INFO + ("Attempt to send command while hardware is not running.\n"); err = -EIO; goto fail_unlock; } if (priv->status & STATUS_CMD_ACTIVE) { - IPW_DEBUG_INFO("Attempt to send command while another command is pending.\n"); + IPW_DEBUG_INFO + ("Attempt to send command while another command is pending.\n"); err = -EBUSY; goto fail_unlock; } @@ -752,7 +746,8 @@ static int ipw2100_hw_send_command(struct ipw2100_priv *priv, /* initialize the firmware command packet */ packet->info.c_struct.cmd->host_command_reg = cmd->host_command; packet->info.c_struct.cmd->host_command_reg1 = cmd->host_command1; - packet->info.c_struct.cmd->host_command_len_reg = cmd->host_command_length; + packet->info.c_struct.cmd->host_command_len_reg = + cmd->host_command_length; packet->info.c_struct.cmd->sequence = cmd->host_command_sequence; memcpy(packet->info.c_struct.cmd->host_command_params_reg, @@ -776,9 +771,11 @@ static int ipw2100_hw_send_command(struct ipw2100_priv *priv, * then there is a problem. */ - err = wait_event_interruptible_timeout( - priv->wait_command_queue, !(priv->status & STATUS_CMD_ACTIVE), - HOST_COMPLETE_TIMEOUT); + err = + wait_event_interruptible_timeout(priv->wait_command_queue, + !(priv-> + status & STATUS_CMD_ACTIVE), + HOST_COMPLETE_TIMEOUT); if (err == 0) { IPW_DEBUG_INFO("Command completion failed out after %dms.\n", @@ -804,13 +801,12 @@ static int ipw2100_hw_send_command(struct ipw2100_priv *priv, return 0; - fail_unlock: + fail_unlock: spin_unlock_irqrestore(&priv->low_lock, flags); return err; } - /* * Verify the values and data access of the hardware * No locks needed or used. No functions called. @@ -825,8 +821,7 @@ static int ipw2100_verify(struct ipw2100_priv *priv) /* Domain 0 check - all values should be DOA_DEBUG */ for (address = IPW_REG_DOA_DEBUG_AREA_START; - address < IPW_REG_DOA_DEBUG_AREA_END; - address += sizeof(u32)) { + address < IPW_REG_DOA_DEBUG_AREA_END; address += sizeof(u32)) { read_register(priv->net_dev, address, &data1); if (data1 != IPW_DATA_DOA_DEBUG_VALUE) return -EIO; @@ -898,7 +893,6 @@ static int ipw2100_wait_for_card_state(struct ipw2100_priv *priv, int state) return -EIO; } - /********************************************************************* Procedure : sw_reset_and_clock Purpose : Asserts s/w reset, asserts clock initialization @@ -975,17 +969,16 @@ static int ipw2100_download_firmware(struct ipw2100_priv *priv) if (priv->fatal_error) { IPW_DEBUG_ERROR("%s: ipw2100_download_firmware called after " - "fatal error %d. Interface must be brought down.\n", - priv->net_dev->name, priv->fatal_error); + "fatal error %d. Interface must be brought down.\n", + priv->net_dev->name, priv->fatal_error); return -EINVAL; } - #ifdef CONFIG_PM if (!ipw2100_firmware.version) { err = ipw2100_get_firmware(priv, &ipw2100_firmware); if (err) { IPW_DEBUG_ERROR("%s: ipw2100_get_firmware failed: %d\n", - priv->net_dev->name, err); + priv->net_dev->name, err); priv->fatal_error = IPW2100_ERR_FW_LOAD; goto fail; } @@ -994,7 +987,7 @@ static int ipw2100_download_firmware(struct ipw2100_priv *priv) err = ipw2100_get_firmware(priv, &ipw2100_firmware); if (err) { IPW_DEBUG_ERROR("%s: ipw2100_get_firmware failed: %d\n", - priv->net_dev->name, err); + priv->net_dev->name, err); priv->fatal_error = IPW2100_ERR_FW_LOAD; goto fail; } @@ -1005,21 +998,20 @@ static int ipw2100_download_firmware(struct ipw2100_priv *priv) err = sw_reset_and_clock(priv); if (err) { IPW_DEBUG_ERROR("%s: sw_reset_and_clock failed: %d\n", - priv->net_dev->name, err); + priv->net_dev->name, err); goto fail; } err = ipw2100_verify(priv); if (err) { IPW_DEBUG_ERROR("%s: ipw2100_verify failed: %d\n", - priv->net_dev->name, err); + priv->net_dev->name, err); goto fail; } /* Hold ARC */ write_nic_dword(priv->net_dev, - IPW_INTERNAL_REGISTER_HALT_AND_RESET, - 0x80000000); + IPW_INTERNAL_REGISTER_HALT_AND_RESET, 0x80000000); /* allow ARC to run */ write_register(priv->net_dev, IPW_REG_RESET_REG, 0); @@ -1034,13 +1026,13 @@ static int ipw2100_download_firmware(struct ipw2100_priv *priv) /* release ARC */ write_nic_dword(priv->net_dev, - IPW_INTERNAL_REGISTER_HALT_AND_RESET, - 0x00000000); + IPW_INTERNAL_REGISTER_HALT_AND_RESET, 0x00000000); /* s/w reset and clock stabilization (again!!!) */ err = sw_reset_and_clock(priv); if (err) { - printk(KERN_ERR DRV_NAME ": %s: sw_reset_and_clock failed: %d\n", + printk(KERN_ERR DRV_NAME + ": %s: sw_reset_and_clock failed: %d\n", priv->net_dev->name, err); goto fail; } @@ -1049,10 +1041,9 @@ static int ipw2100_download_firmware(struct ipw2100_priv *priv) err = ipw2100_fw_download(priv, &ipw2100_firmware); if (err) { IPW_DEBUG_ERROR("%s: Error loading firmware: %d\n", - priv->net_dev->name, err); + priv->net_dev->name, err); goto fail; } - #ifndef CONFIG_PM /* * When the .resume method of the driver is called, the other @@ -1084,7 +1075,7 @@ static int ipw2100_download_firmware(struct ipw2100_priv *priv) return 0; - fail: + fail: ipw2100_release_firmware(priv, &ipw2100_firmware); return err; } @@ -1105,7 +1096,6 @@ static inline void ipw2100_disable_interrupts(struct ipw2100_priv *priv) write_register(priv->net_dev, IPW_REG_INTA_MASK, 0x0); } - static void ipw2100_initialize_ordinals(struct ipw2100_priv *priv) { struct ipw2100_ordinals *ord = &priv->ordinals; @@ -1177,11 +1167,10 @@ static int ipw2100_get_hw_features(struct ipw2100_priv *priv) * EEPROM_SRAM_DB_START_ADDRESS using ordinal in ordinal table 1 */ len = sizeof(addr); - if (ipw2100_get_ordinal( - priv, IPW_ORD_EEPROM_SRAM_DB_BLOCK_START_ADDRESS, - &addr, &len)) { + if (ipw2100_get_ordinal + (priv, IPW_ORD_EEPROM_SRAM_DB_BLOCK_START_ADDRESS, &addr, &len)) { IPW_DEBUG_INFO("failed querying ordinals at line %d\n", - __LINE__); + __LINE__); return -EIO; } @@ -1194,7 +1183,7 @@ static int ipw2100_get_hw_features(struct ipw2100_priv *priv) priv->eeprom_version = (val >> 24) & 0xFF; IPW_DEBUG_INFO("EEPROM version: %d\n", priv->eeprom_version); - /* + /* * HW RF Kill enable is bit 0 in byte at offset 0x21 in firmware * * notice that the EEPROM bit is reverse polarity, i.e. @@ -1206,8 +1195,7 @@ static int ipw2100_get_hw_features(struct ipw2100_priv *priv) priv->hw_features |= HW_FEATURE_RFKILL; IPW_DEBUG_INFO("HW RF Kill: %ssupported.\n", - (priv->hw_features & HW_FEATURE_RFKILL) ? - "" : "not "); + (priv->hw_features & HW_FEATURE_RFKILL) ? "" : "not "); return 0; } @@ -1234,7 +1222,8 @@ static int ipw2100_start_adapter(struct ipw2100_priv *priv) * fw & dino ucode */ if (ipw2100_download_firmware(priv)) { - printk(KERN_ERR DRV_NAME ": %s: Failed to power on the adapter.\n", + printk(KERN_ERR DRV_NAME + ": %s: Failed to power on the adapter.\n", priv->net_dev->name); return -EIO; } @@ -1293,7 +1282,8 @@ static int ipw2100_start_adapter(struct ipw2100_priv *priv) i ? "SUCCESS" : "FAILED"); if (!i) { - printk(KERN_WARNING DRV_NAME ": %s: Firmware did not initialize.\n", + printk(KERN_WARNING DRV_NAME + ": %s: Firmware did not initialize.\n", priv->net_dev->name); return -EIO; } @@ -1326,7 +1316,6 @@ static inline void ipw2100_reset_fatalerror(struct ipw2100_priv *priv) priv->fatal_error = 0; } - /* NOTE: Our interrupt is disabled when this method is called */ static int ipw2100_power_cycle_adapter(struct ipw2100_priv *priv) { @@ -1350,19 +1339,19 @@ static int ipw2100_power_cycle_adapter(struct ipw2100_priv *priv) if (reg & IPW_AUX_HOST_RESET_REG_MASTER_DISABLED) break; - } while(i--); + } while (i--); priv->status &= ~STATUS_RESET_PENDING; if (!i) { - IPW_DEBUG_INFO("exit - waited too long for master assert stop\n"); + IPW_DEBUG_INFO + ("exit - waited too long for master assert stop\n"); return -EIO; } write_register(priv->net_dev, IPW_REG_RESET_REG, IPW_AUX_HOST_RESET_REG_SW_RESET); - /* Reset any fatal_error conditions */ ipw2100_reset_fatalerror(priv); @@ -1415,7 +1404,6 @@ static int ipw2100_hw_phy_off(struct ipw2100_priv *priv) return -EIO; } - static int ipw2100_enable_adapter(struct ipw2100_priv *priv) { struct host_command cmd = { @@ -1445,9 +1433,8 @@ static int ipw2100_enable_adapter(struct ipw2100_priv *priv) err = ipw2100_wait_for_card_state(priv, IPW_HW_STATE_ENABLED); if (err) { - IPW_DEBUG_INFO( - "%s: card not responding to init command.\n", - priv->net_dev->name); + IPW_DEBUG_INFO("%s: card not responding to init command.\n", + priv->net_dev->name); goto fail_up; } @@ -1456,7 +1443,7 @@ static int ipw2100_enable_adapter(struct ipw2100_priv *priv) queue_delayed_work(priv->workqueue, &priv->hang_check, HZ / 2); } -fail_up: + fail_up: up(&priv->adapter_sem); return err; } @@ -1488,7 +1475,8 @@ static int ipw2100_hw_stop_adapter(struct ipw2100_priv *priv) err = ipw2100_hw_phy_off(priv); if (err) - printk(KERN_WARNING DRV_NAME ": Error disabling radio %d\n", err); + printk(KERN_WARNING DRV_NAME + ": Error disabling radio %d\n", err); /* * If in D0-standby mode going directly to D3 may cause a @@ -1566,7 +1554,6 @@ static int ipw2100_hw_stop_adapter(struct ipw2100_priv *priv) return 0; } - static int ipw2100_disable_adapter(struct ipw2100_priv *priv) { struct host_command cmd = { @@ -1593,19 +1580,21 @@ static int ipw2100_disable_adapter(struct ipw2100_priv *priv) err = ipw2100_hw_send_command(priv, &cmd); if (err) { - printk(KERN_WARNING DRV_NAME ": exit - failed to send CARD_DISABLE command\n"); + printk(KERN_WARNING DRV_NAME + ": exit - failed to send CARD_DISABLE command\n"); goto fail_up; } err = ipw2100_wait_for_card_state(priv, IPW_HW_STATE_DISABLED); if (err) { - printk(KERN_WARNING DRV_NAME ": exit - card failed to change to DISABLED\n"); + printk(KERN_WARNING DRV_NAME + ": exit - card failed to change to DISABLED\n"); goto fail_up; } IPW_DEBUG_INFO("TODO: implement scan state machine\n"); -fail_up: + fail_up: up(&priv->adapter_sem); return err; } @@ -1709,8 +1698,9 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred) (priv->status & STATUS_RESET_PENDING)) { /* Power cycle the card ... */ if (ipw2100_power_cycle_adapter(priv)) { - printk(KERN_WARNING DRV_NAME ": %s: Could not cycle adapter.\n", - priv->net_dev->name); + printk(KERN_WARNING DRV_NAME + ": %s: Could not cycle adapter.\n", + priv->net_dev->name); rc = 1; goto exit; } @@ -1719,8 +1709,9 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred) /* Load the firmware, start the clocks, etc. */ if (ipw2100_start_adapter(priv)) { - printk(KERN_ERR DRV_NAME ": %s: Failed to start the firmware.\n", - priv->net_dev->name); + printk(KERN_ERR DRV_NAME + ": %s: Failed to start the firmware.\n", + priv->net_dev->name); rc = 1; goto exit; } @@ -1729,16 +1720,18 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred) /* Determine capabilities of this particular HW configuration */ if (ipw2100_get_hw_features(priv)) { - printk(KERN_ERR DRV_NAME ": %s: Failed to determine HW features.\n", - priv->net_dev->name); + printk(KERN_ERR DRV_NAME + ": %s: Failed to determine HW features.\n", + priv->net_dev->name); rc = 1; goto exit; } lock = LOCK_NONE; if (ipw2100_set_ordinal(priv, IPW_ORD_PERS_DB_LOCK, &lock, &ord_len)) { - printk(KERN_ERR DRV_NAME ": %s: Failed to clear ordinal lock.\n", - priv->net_dev->name); + printk(KERN_ERR DRV_NAME + ": %s: Failed to clear ordinal lock.\n", + priv->net_dev->name); rc = 1; goto exit; } @@ -1764,7 +1757,7 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred) * HOST_COMPLETE */ if (ipw2100_adapter_setup(priv)) { printk(KERN_ERR DRV_NAME ": %s: Failed to start the card.\n", - priv->net_dev->name); + priv->net_dev->name); rc = 1; goto exit; } @@ -1773,20 +1766,19 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred) /* Enable the adapter - sends HOST_COMPLETE */ if (ipw2100_enable_adapter(priv)) { printk(KERN_ERR DRV_NAME ": " - "%s: failed in call to enable adapter.\n", - priv->net_dev->name); + "%s: failed in call to enable adapter.\n", + priv->net_dev->name); ipw2100_hw_stop_adapter(priv); rc = 1; goto exit; } - /* Start a scan . . . */ ipw2100_set_scan_options(priv); ipw2100_start_scan(priv); } - exit: + exit: return rc; } @@ -1802,8 +1794,7 @@ static void ipw2100_down(struct ipw2100_priv *priv) unsigned long flags; union iwreq_data wrqu = { .ap_addr = { - .sa_family = ARPHRD_ETHER - } + .sa_family = ARPHRD_ETHER} }; int associated = priv->status & STATUS_ASSOCIATED; @@ -1862,8 +1853,7 @@ static void ipw2100_reset_adapter(struct ipw2100_priv *priv) unsigned long flags; union iwreq_data wrqu = { .ap_addr = { - .sa_family = ARPHRD_ETHER - } + .sa_family = ARPHRD_ETHER} }; int associated = priv->status & STATUS_ASSOCIATED; @@ -1894,7 +1884,6 @@ static void ipw2100_reset_adapter(struct ipw2100_priv *priv) } - static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status) { @@ -1904,7 +1893,7 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status) u32 txrate; u32 chan; char *txratename; - u8 bssid[ETH_ALEN]; + u8 bssid[ETH_ALEN]; /* * TBD: BSSID is usually 00:00:00:00:00:00 here and not @@ -1918,16 +1907,15 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status) essid, &essid_len); if (ret) { IPW_DEBUG_INFO("failed querying ordinals at line %d\n", - __LINE__); + __LINE__); return; } len = sizeof(u32); - ret = ipw2100_get_ordinal(priv, IPW_ORD_CURRENT_TX_RATE, - &txrate, &len); + ret = ipw2100_get_ordinal(priv, IPW_ORD_CURRENT_TX_RATE, &txrate, &len); if (ret) { IPW_DEBUG_INFO("failed querying ordinals at line %d\n", - __LINE__); + __LINE__); return; } @@ -1935,19 +1923,18 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status) ret = ipw2100_get_ordinal(priv, IPW_ORD_OUR_FREQ, &chan, &len); if (ret) { IPW_DEBUG_INFO("failed querying ordinals at line %d\n", - __LINE__); + __LINE__); return; } len = ETH_ALEN; - ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID, &bssid, &len); + ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID, &bssid, &len); if (ret) { IPW_DEBUG_INFO("failed querying ordinals at line %d\n", - __LINE__); + __LINE__); return; } memcpy(priv->ieee->bssid, bssid, ETH_ALEN); - switch (txrate) { case TX_RATE_1_MBIT: txratename = "1Mbps"; @@ -1974,7 +1961,7 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status) /* now we copy read ssid into dev */ if (!(priv->config & CFG_STATIC_ESSID)) { - priv->essid_len = min((u8)essid_len, (u8)IW_ESSID_MAX_SIZE); + priv->essid_len = min((u8) essid_len, (u8) IW_ESSID_MAX_SIZE); memcpy(priv->essid, essid, priv->essid_len); } priv->channel = chan; @@ -1986,7 +1973,6 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status) queue_delayed_work(priv->workqueue, &priv->wx_event_work, HZ / 10); } - static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid, int length, int batch_mode) { @@ -2001,8 +1987,7 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid, IPW_DEBUG_HC("SSID: '%s'\n", escape_essid(essid, ssid_len)); if (ssid_len) - memcpy((char*)cmd.host_command_parameters, - essid, ssid_len); + memcpy((char *)cmd.host_command_parameters, essid, ssid_len); if (!batch_mode) { err = ipw2100_disable_adapter(priv); @@ -2014,7 +1999,7 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid, * disable auto association -- so we cheat by setting a bogus SSID */ if (!ssid_len && !(priv->config & CFG_ASSOCIATE)) { int i; - u8 *bogus = (u8*)cmd.host_command_parameters; + u8 *bogus = (u8 *) cmd.host_command_parameters; for (i = 0; i < IW_ESSID_MAX_SIZE; i++) bogus[i] = 0x18 + i; cmd.host_command_length = IW_ESSID_MAX_SIZE; @@ -2025,8 +2010,7 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid, err = ipw2100_hw_send_command(priv, &cmd); if (!err) { - memset(priv->essid + ssid_len, 0, - IW_ESSID_MAX_SIZE - ssid_len); + memset(priv->essid + ssid_len, 0, IW_ESSID_MAX_SIZE - ssid_len); memcpy(priv->essid, essid, ssid_len); priv->essid_len = ssid_len; } @@ -2071,7 +2055,7 @@ static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status) static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status) { IPW_DEBUG_INFO("%s: RF Kill state changed to radio OFF.\n", - priv->net_dev->name); + priv->net_dev->name); /* RF_KILL is now enabled (else we wouldn't be here) */ priv->status |= STATUS_RF_KILL_HW; @@ -2102,16 +2086,16 @@ static void isr_scan_complete(struct ipw2100_priv *priv, u32 status) #define IPW2100_HANDLER(v, f) { v, f, # v } struct ipw2100_status_indicator { int status; - void (*cb)(struct ipw2100_priv *priv, u32 status); + void (*cb) (struct ipw2100_priv * priv, u32 status); char *name; }; #else #define IPW2100_HANDLER(v, f) { v, f } struct ipw2100_status_indicator { int status; - void (*cb)(struct ipw2100_priv *priv, u32 status); + void (*cb) (struct ipw2100_priv * priv, u32 status); }; -#endif /* CONFIG_IPW_DEBUG */ +#endif /* CONFIG_IPW_DEBUG */ static void isr_indicate_scanning(struct ipw2100_priv *priv, u32 status) { @@ -2135,7 +2119,6 @@ static const struct ipw2100_status_indicator status_handlers[] = { IPW2100_HANDLER(-1, NULL) }; - static void isr_status_change(struct ipw2100_priv *priv, int status) { int i; @@ -2153,7 +2136,7 @@ static void isr_status_change(struct ipw2100_priv *priv, int status) for (i = 0; status_handlers[i].status != -1; i++) { if (status == status_handlers[i].status) { IPW_DEBUG_NOTIF("Status change: %s\n", - status_handlers[i].name); + status_handlers[i].name); if (status_handlers[i].cb) status_handlers[i].cb(priv, status); priv->wstats.status = status; @@ -2164,9 +2147,8 @@ static void isr_status_change(struct ipw2100_priv *priv, int status) IPW_DEBUG_NOTIF("unknown status received: %04x\n", status); } -static void isr_rx_complete_command( - struct ipw2100_priv *priv, - struct ipw2100_cmd_header *cmd) +static void isr_rx_complete_command(struct ipw2100_priv *priv, + struct ipw2100_cmd_header *cmd) { #ifdef CONFIG_IPW_DEBUG if (cmd->host_command_reg < ARRAY_SIZE(command_types)) { @@ -2196,10 +2178,8 @@ static const char *frame_types[] = { }; #endif - -static inline int ipw2100_alloc_skb( - struct ipw2100_priv *priv, - struct ipw2100_rx_packet *packet) +static inline int ipw2100_alloc_skb(struct ipw2100_priv *priv, + struct ipw2100_rx_packet *packet) { packet->skb = dev_alloc_skb(sizeof(struct ipw2100_rx)); if (!packet->skb) @@ -2215,7 +2195,6 @@ static inline int ipw2100_alloc_skb( return 0; } - #define SEARCH_ERROR 0xffffffff #define SEARCH_FAIL 0xfffffffe #define SEARCH_SUCCESS 0xfffffff0 @@ -2229,10 +2208,10 @@ static inline int ipw2100_snapshot_alloc(struct ipw2100_priv *priv) if (priv->snapshot[0]) return 1; for (i = 0; i < 0x30; i++) { - priv->snapshot[i] = (u8*)kmalloc(0x1000, GFP_ATOMIC); + priv->snapshot[i] = (u8 *) kmalloc(0x1000, GFP_ATOMIC); if (!priv->snapshot[i]) { IPW_DEBUG_INFO("%s: Error allocating snapshot " - "buffer %d\n", priv->net_dev->name, i); + "buffer %d\n", priv->net_dev->name, i); while (i > 0) kfree(priv->snapshot[--i]); priv->snapshot[0] = NULL; @@ -2253,7 +2232,7 @@ static inline void ipw2100_snapshot_free(struct ipw2100_priv *priv) priv->snapshot[0] = NULL; } -static inline u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 *in_buf, +static inline u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf, size_t len, int mode) { u32 i, j; @@ -2270,9 +2249,9 @@ static inline u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 *in_buf, for (ret = SEARCH_FAIL, i = 0; i < 0x30000; i += 4) { read_nic_dword(priv->net_dev, i, &tmp); if (mode == SEARCH_SNAPSHOT) - *(u32 *)SNAPSHOT_ADDR(i) = tmp; + *(u32 *) SNAPSHOT_ADDR(i) = tmp; if (ret == SEARCH_FAIL) { - d = (u8*)&tmp; + d = (u8 *) & tmp; for (j = 0; j < 4; j++) { if (*s != *d) { s = in_buf; @@ -2310,8 +2289,7 @@ static inline u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 *in_buf, static u8 packet_data[IPW_RX_NIC_BUFFER_LENGTH]; #endif -static inline void ipw2100_corruption_detected(struct ipw2100_priv *priv, - int i) +static inline void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i) { #ifdef CONFIG_IPW_DEBUG_C3 struct ipw2100_status *status = &priv->status_queue.drv[i]; @@ -2346,9 +2324,9 @@ static inline void ipw2100_corruption_detected(struct ipw2100_priv *priv, if (reg & IPW_AUX_HOST_RESET_REG_MASTER_DISABLED) break; - } while (j--); + } while (j--); - match = ipw2100_match_buf(priv, (u8*)status, + match = ipw2100_match_buf(priv, (u8 *) status, sizeof(struct ipw2100_status), SEARCH_SNAPSHOT); if (match < SEARCH_SUCCESS) @@ -2360,7 +2338,7 @@ static inline void ipw2100_corruption_detected(struct ipw2100_priv *priv, IPW_DEBUG_INFO("%s: No DMA status match in " "Firmware.\n", priv->net_dev->name); - printk_buf((u8*)priv->status_queue.drv, + printk_buf((u8 *) priv->status_queue.drv, sizeof(struct ipw2100_status) * RX_QUEUE_LENGTH); #endif @@ -2401,17 +2379,15 @@ static inline void isr_rx(struct ipw2100_priv *priv, int i, } if (unlikely(priv->ieee->iw_mode != IW_MODE_MONITOR && - !(priv->status & STATUS_ASSOCIATED))) { + !(priv->status & STATUS_ASSOCIATED))) { IPW_DEBUG_DROP("Dropping packet while not associated.\n"); priv->wstats.discard.misc++; return; } - pci_unmap_single(priv->pci_dev, packet->dma_addr, - sizeof(struct ipw2100_rx), - PCI_DMA_FROMDEVICE); + sizeof(struct ipw2100_rx), PCI_DMA_FROMDEVICE); skb_put(packet->skb, status->frame_size); @@ -2438,8 +2414,8 @@ static inline void isr_rx(struct ipw2100_priv *priv, int i, /* We need to allocate a new SKB and attach it to the RDB. */ if (unlikely(ipw2100_alloc_skb(priv, packet))) { printk(KERN_WARNING DRV_NAME ": " - "%s: Unable to allocate SKB onto RBD ring - disabling " - "adapter.\n", priv->net_dev->name); + "%s: Unable to allocate SKB onto RBD ring - disabling " + "adapter.\n", priv->net_dev->name); /* TODO: schedule adapter shutdown */ IPW_DEBUG_INFO("TODO: Shutdown adapter...\n"); } @@ -2534,11 +2510,11 @@ static inline void __ipw2100_rx_process(struct ipw2100_priv *priv) /* Sync the DMA for the STATUS buffer so CPU is sure to get * the correct values */ - pci_dma_sync_single_for_cpu( - priv->pci_dev, - sq->nic + sizeof(struct ipw2100_status) * i, - sizeof(struct ipw2100_status), - PCI_DMA_FROMDEVICE); + pci_dma_sync_single_for_cpu(priv->pci_dev, + sq->nic + + sizeof(struct ipw2100_status) * i, + sizeof(struct ipw2100_status), + PCI_DMA_FROMDEVICE); /* Sync the DMA for the RX buffer so CPU is sure to get * the correct values */ @@ -2552,8 +2528,7 @@ static inline void __ipw2100_rx_process(struct ipw2100_priv *priv) } u = packet->rxp; - frame_type = sq->drv[i].status_fields & - STATUS_TYPE_MASK; + frame_type = sq->drv[i].status_fields & STATUS_TYPE_MASK; stats.rssi = sq->drv[i].rssi + IPW2100_RSSI_TO_DBM; stats.len = sq->drv[i].frame_size; @@ -2562,16 +2537,14 @@ static inline void __ipw2100_rx_process(struct ipw2100_priv *priv) stats.mask |= IEEE80211_STATMASK_RSSI; stats.freq = IEEE80211_24GHZ_BAND; - IPW_DEBUG_RX( - "%s: '%s' frame type received (%d).\n", - priv->net_dev->name, frame_types[frame_type], - stats.len); + IPW_DEBUG_RX("%s: '%s' frame type received (%d).\n", + priv->net_dev->name, frame_types[frame_type], + stats.len); switch (frame_type) { case COMMAND_STATUS_VAL: /* Reset Rx watchdog */ - isr_rx_complete_command( - priv, &u->rx_data.command); + isr_rx_complete_command(priv, &u->rx_data.command); break; case STATUS_CHANGE_VAL: @@ -2588,12 +2561,10 @@ static inline void __ipw2100_rx_process(struct ipw2100_priv *priv) #endif if (stats.len < sizeof(u->rx_data.header)) break; - switch (WLAN_FC_GET_TYPE(u->rx_data.header. - frame_ctl)) { + switch (WLAN_FC_GET_TYPE(u->rx_data.header.frame_ctl)) { case IEEE80211_FTYPE_MGMT: ieee80211_rx_mgt(priv->ieee, - &u->rx_data.header, - &stats); + &u->rx_data.header, &stats); break; case IEEE80211_FTYPE_CTL: @@ -2607,7 +2578,7 @@ static inline void __ipw2100_rx_process(struct ipw2100_priv *priv) break; } - increment: + increment: /* clear status field associated with this RBD */ rxq->drv[i].status.info.field = 0; @@ -2619,12 +2590,10 @@ static inline void __ipw2100_rx_process(struct ipw2100_priv *priv) rxq->next = (i ? i : rxq->entries) - 1; write_register(priv->net_dev, - IPW_MEM_HOST_SHARED_RX_WRITE_INDEX, - rxq->next); + IPW_MEM_HOST_SHARED_RX_WRITE_INDEX, rxq->next); } } - /* * __ipw2100_tx_process * @@ -2667,7 +2636,7 @@ static inline void __ipw2100_rx_process(struct ipw2100_priv *priv) static inline int __ipw2100_tx_process(struct ipw2100_priv *priv) { struct ipw2100_bd_queue *txq = &priv->tx_queue; - struct ipw2100_bd *tbd; + struct ipw2100_bd *tbd; struct list_head *element; struct ipw2100_tx_packet *packet; int descriptors_used; @@ -2680,7 +2649,7 @@ static inline int __ipw2100_tx_process(struct ipw2100_priv *priv) element = priv->fw_pend_list.next; packet = list_entry(element, struct ipw2100_tx_packet, list); - tbd = &txq->drv[packet->index]; + tbd = &txq->drv[packet->index]; /* Determine how many TBD entries must be finished... */ switch (packet->type) { @@ -2693,14 +2662,14 @@ static inline int __ipw2100_tx_process(struct ipw2100_priv *priv) case DATA: /* DATA uses two slots; advance and loop position. */ descriptors_used = tbd->num_fragments; - frag_num = tbd->num_fragments - 1; + frag_num = tbd->num_fragments - 1; e = txq->oldest + frag_num; e %= txq->entries; break; default: printk(KERN_WARNING DRV_NAME ": %s: Bad fw_pend_list entry!\n", - priv->net_dev->name); + priv->net_dev->name); return 0; } @@ -2716,13 +2685,12 @@ static inline int __ipw2100_tx_process(struct ipw2100_priv *priv) printk(KERN_WARNING DRV_NAME ": %s: write index mismatch\n", priv->net_dev->name); - /* + /* * txq->next is the index of the last packet written txq->oldest is * the index of the r is the index of the next packet to be read by * firmware */ - /* * Quick graphic to help you visualize the following * if / else statement @@ -2750,23 +2718,20 @@ static inline int __ipw2100_tx_process(struct ipw2100_priv *priv) #ifdef CONFIG_IPW_DEBUG { int i = txq->oldest; - IPW_DEBUG_TX( - "TX%d V=%p P=%04X T=%04X L=%d\n", i, - &txq->drv[i], - (u32)(txq->nic + i * sizeof(struct ipw2100_bd)), - txq->drv[i].host_addr, - txq->drv[i].buf_length); + IPW_DEBUG_TX("TX%d V=%p P=%04X T=%04X L=%d\n", i, + &txq->drv[i], + (u32) (txq->nic + i * sizeof(struct ipw2100_bd)), + txq->drv[i].host_addr, txq->drv[i].buf_length); if (packet->type == DATA) { i = (i + 1) % txq->entries; - IPW_DEBUG_TX( - "TX%d V=%p P=%04X T=%04X L=%d\n", i, - &txq->drv[i], - (u32)(txq->nic + i * - sizeof(struct ipw2100_bd)), - (u32)txq->drv[i].host_addr, - txq->drv[i].buf_length); + IPW_DEBUG_TX("TX%d V=%p P=%04X T=%04X L=%d\n", i, + &txq->drv[i], + (u32) (txq->nic + i * + sizeof(struct ipw2100_bd)), + (u32) txq->drv[i].host_addr, + txq->drv[i].buf_length); } } #endif @@ -2782,21 +2747,19 @@ static inline int __ipw2100_tx_process(struct ipw2100_priv *priv) /* DATA packet; we have to unmap and free the SKB */ priv->ieee->stats.tx_packets++; for (i = 0; i < frag_num; i++) { - tbd = &txq->drv[(packet->index + 1 + i) % - txq->entries]; + tbd = &txq->drv[(packet->index + 1 + i) % txq->entries]; - IPW_DEBUG_TX( - "TX%d P=%08x L=%d\n", - (packet->index + 1 + i) % txq->entries, - tbd->host_addr, tbd->buf_length); + IPW_DEBUG_TX("TX%d P=%08x L=%d\n", + (packet->index + 1 + i) % txq->entries, + tbd->host_addr, tbd->buf_length); pci_unmap_single(priv->pci_dev, tbd->host_addr, - tbd->buf_length, - PCI_DMA_TODEVICE); + tbd->buf_length, PCI_DMA_TODEVICE); } - priv->ieee->stats.tx_bytes += packet->info.d_struct.txb->payload_size; + priv->ieee->stats.tx_bytes += + packet->info.d_struct.txb->payload_size; ieee80211_txb_free(packet->info.d_struct.txb); packet->info.d_struct.txb = NULL; @@ -2808,8 +2771,8 @@ static inline int __ipw2100_tx_process(struct ipw2100_priv *priv) if (priv->status & STATUS_ASSOCIATED && netif_queue_stopped(priv->net_dev)) { IPW_DEBUG_INFO(KERN_INFO - "%s: Waking net queue.\n", - priv->net_dev->name); + "%s: Waking net queue.\n", + priv->net_dev->name); netif_wake_queue(priv->net_dev); } @@ -2829,11 +2792,12 @@ static inline int __ipw2100_tx_process(struct ipw2100_priv *priv) #ifdef CONFIG_IPW_DEBUG if (packet->info.c_struct.cmd->host_command_reg < sizeof(command_types) / sizeof(*command_types)) - IPW_DEBUG_TX( - "Command '%s (%d)' processed: %d.\n", - command_types[packet->info.c_struct.cmd->host_command_reg], - packet->info.c_struct.cmd->host_command_reg, - packet->info.c_struct.cmd->cmd_status_reg); + IPW_DEBUG_TX("Command '%s (%d)' processed: %d.\n", + command_types[packet->info.c_struct.cmd-> + host_command_reg], + packet->info.c_struct.cmd-> + host_command_reg, + packet->info.c_struct.cmd->cmd_status_reg); #endif list_add_tail(element, &priv->msg_free_list); @@ -2848,17 +2812,17 @@ static inline int __ipw2100_tx_process(struct ipw2100_priv *priv) SET_STAT(&priv->txq_stat, txq->available); IPW_DEBUG_TX("packet latency (send to process) %ld jiffies\n", - jiffies - packet->jiffy_start); + jiffies - packet->jiffy_start); return (!list_empty(&priv->fw_pend_list)); } - static inline void __ipw2100_tx_complete(struct ipw2100_priv *priv) { int i = 0; - while (__ipw2100_tx_process(priv) && i < 200) i++; + while (__ipw2100_tx_process(priv) && i < 200) + i++; if (i == 200) { printk(KERN_WARNING DRV_NAME ": " @@ -2867,7 +2831,6 @@ static inline void __ipw2100_tx_complete(struct ipw2100_priv *priv) } } - static void ipw2100_tx_send_commands(struct ipw2100_priv *priv) { struct list_head *element; @@ -2892,13 +2855,12 @@ static void ipw2100_tx_send_commands(struct ipw2100_priv *priv) list_del(element); DEC_STAT(&priv->msg_pend_stat); - packet = list_entry(element, - struct ipw2100_tx_packet, list); + packet = list_entry(element, struct ipw2100_tx_packet, list); IPW_DEBUG_TX("using TBD at virt=%p, phys=%p\n", - &txq->drv[txq->next], - (void*)(txq->nic + txq->next * - sizeof(struct ipw2100_bd))); + &txq->drv[txq->next], + (void *)(txq->nic + txq->next * + sizeof(struct ipw2100_bd))); packet->index = txq->next; @@ -2911,8 +2873,8 @@ static void ipw2100_tx_send_commands(struct ipw2100_priv *priv) * with f/w debug version */ tbd->num_fragments = 1; tbd->status.info.field = - IPW_BD_STATUS_TX_FRAME_COMMAND | - IPW_BD_STATUS_TX_INTERRUPT_ENABLE; + IPW_BD_STATUS_TX_FRAME_COMMAND | + IPW_BD_STATUS_TX_INTERRUPT_ENABLE; /* update TBD queue counters */ txq->next++; @@ -2934,7 +2896,6 @@ static void ipw2100_tx_send_commands(struct ipw2100_priv *priv) } } - /* * ipw2100_tx_send_data * @@ -2946,7 +2907,7 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv) struct ipw2100_bd_queue *txq = &priv->tx_queue; struct ipw2100_bd *tbd; int next = txq->next; - int i = 0; + int i = 0; struct ipw2100_data_header *ipw_hdr; struct ieee80211_hdr_3addr *hdr; @@ -2958,20 +2919,18 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv) * maintained between the r and w indexes */ element = priv->tx_pend_list.next; - packet = list_entry(element, struct ipw2100_tx_packet, list); + packet = list_entry(element, struct ipw2100_tx_packet, list); if (unlikely(1 + packet->info.d_struct.txb->nr_frags > IPW_MAX_BDS)) { /* TODO: Support merging buffers if more than * IPW_MAX_BDS are used */ - IPW_DEBUG_INFO( - "%s: Maximum BD theshold exceeded. " - "Increase fragmentation level.\n", - priv->net_dev->name); + IPW_DEBUG_INFO("%s: Maximum BD theshold exceeded. " + "Increase fragmentation level.\n", + priv->net_dev->name); } - if (txq->available <= 3 + - packet->info.d_struct.txb->nr_frags) { + if (txq->available <= 3 + packet->info.d_struct.txb->nr_frags) { IPW_DEBUG_TX("no room in tx_queue\n"); break; } @@ -2985,7 +2944,7 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv) ipw_hdr = packet->info.d_struct.data; hdr = (struct ieee80211_hdr_3addr *)packet->info.d_struct.txb-> - fragments[0]->data; + fragments[0]->data; if (priv->ieee->iw_mode == IW_MODE_INFRA) { /* To DS: Addr1 = BSSID, Addr2 = SA, @@ -3007,7 +2966,8 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv) ipw_hdr->encrypted = packet->info.d_struct.txb->encrypted; if (packet->info.d_struct.txb->nr_frags > 1) ipw_hdr->fragment_size = - packet->info.d_struct.txb->frag_size - IEEE80211_3ADDR_LEN; + packet->info.d_struct.txb->frag_size - + IEEE80211_3ADDR_LEN; else ipw_hdr->fragment_size = 0; @@ -3015,54 +2975,53 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv) tbd->buf_length = sizeof(struct ipw2100_data_header); tbd->num_fragments = 1 + packet->info.d_struct.txb->nr_frags; tbd->status.info.field = - IPW_BD_STATUS_TX_FRAME_802_3 | - IPW_BD_STATUS_TX_FRAME_NOT_LAST_FRAGMENT; + IPW_BD_STATUS_TX_FRAME_802_3 | + IPW_BD_STATUS_TX_FRAME_NOT_LAST_FRAGMENT; txq->next++; txq->next %= txq->entries; - IPW_DEBUG_TX( - "data header tbd TX%d P=%08x L=%d\n", - packet->index, tbd->host_addr, - tbd->buf_length); + IPW_DEBUG_TX("data header tbd TX%d P=%08x L=%d\n", + packet->index, tbd->host_addr, tbd->buf_length); #ifdef CONFIG_IPW_DEBUG if (packet->info.d_struct.txb->nr_frags > 1) IPW_DEBUG_FRAG("fragment Tx: %d frames\n", packet->info.d_struct.txb->nr_frags); #endif - for (i = 0; i < packet->info.d_struct.txb->nr_frags; i++) { - tbd = &txq->drv[txq->next]; + for (i = 0; i < packet->info.d_struct.txb->nr_frags; i++) { + tbd = &txq->drv[txq->next]; if (i == packet->info.d_struct.txb->nr_frags - 1) tbd->status.info.field = - IPW_BD_STATUS_TX_FRAME_802_3 | - IPW_BD_STATUS_TX_INTERRUPT_ENABLE; + IPW_BD_STATUS_TX_FRAME_802_3 | + IPW_BD_STATUS_TX_INTERRUPT_ENABLE; else tbd->status.info.field = - IPW_BD_STATUS_TX_FRAME_802_3 | - IPW_BD_STATUS_TX_FRAME_NOT_LAST_FRAGMENT; + IPW_BD_STATUS_TX_FRAME_802_3 | + IPW_BD_STATUS_TX_FRAME_NOT_LAST_FRAGMENT; tbd->buf_length = packet->info.d_struct.txb-> - fragments[i]->len - IEEE80211_3ADDR_LEN; + fragments[i]->len - IEEE80211_3ADDR_LEN; - tbd->host_addr = pci_map_single( - priv->pci_dev, - packet->info.d_struct.txb->fragments[i]->data + - IEEE80211_3ADDR_LEN, - tbd->buf_length, - PCI_DMA_TODEVICE); + tbd->host_addr = pci_map_single(priv->pci_dev, + packet->info.d_struct. + txb->fragments[i]-> + data + + IEEE80211_3ADDR_LEN, + tbd->buf_length, + PCI_DMA_TODEVICE); - IPW_DEBUG_TX( - "data frag tbd TX%d P=%08x L=%d\n", - txq->next, tbd->host_addr, tbd->buf_length); + IPW_DEBUG_TX("data frag tbd TX%d P=%08x L=%d\n", + txq->next, tbd->host_addr, + tbd->buf_length); - pci_dma_sync_single_for_device( - priv->pci_dev, tbd->host_addr, - tbd->buf_length, - PCI_DMA_TODEVICE); + pci_dma_sync_single_for_device(priv->pci_dev, + tbd->host_addr, + tbd->buf_length, + PCI_DMA_TODEVICE); txq->next++; txq->next %= txq->entries; - } + } txq->available -= 1 + packet->info.d_struct.txb->nr_frags; SET_STAT(&priv->txq_stat, txq->available); @@ -3078,7 +3037,7 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv) IPW_MEM_HOST_SHARED_TX_QUEUE_WRITE_INDEX, txq->next); } - return; + return; } static void ipw2100_irq_tasklet(struct ipw2100_priv *priv) @@ -3106,11 +3065,9 @@ static void ipw2100_irq_tasklet(struct ipw2100_priv *priv) if (inta & IPW2100_INTA_FATAL_ERROR) { printk(KERN_WARNING DRV_NAME - ": Fatal interrupt. Scheduling firmware restart.\n"); + ": Fatal interrupt. Scheduling firmware restart.\n"); priv->inta_other++; - write_register( - dev, IPW_REG_INTA, - IPW2100_INTA_FATAL_ERROR); + write_register(dev, IPW_REG_INTA, IPW2100_INTA_FATAL_ERROR); read_nic_dword(dev, IPW_NIC_FATAL_ERROR, &priv->fatal_error); IPW_DEBUG_INFO("%s: Fatal error value: 0x%08X\n", @@ -3125,11 +3082,10 @@ static void ipw2100_irq_tasklet(struct ipw2100_priv *priv) } if (inta & IPW2100_INTA_PARITY_ERROR) { - printk(KERN_ERR DRV_NAME ": ***** PARITY ERROR INTERRUPT !!!! \n"); + printk(KERN_ERR DRV_NAME + ": ***** PARITY ERROR INTERRUPT !!!! \n"); priv->inta_other++; - write_register( - dev, IPW_REG_INTA, - IPW2100_INTA_PARITY_ERROR); + write_register(dev, IPW_REG_INTA, IPW2100_INTA_PARITY_ERROR); } if (inta & IPW2100_INTA_RX_TRANSFER) { @@ -3137,9 +3093,7 @@ static void ipw2100_irq_tasklet(struct ipw2100_priv *priv) priv->rx_interrupts++; - write_register( - dev, IPW_REG_INTA, - IPW2100_INTA_RX_TRANSFER); + write_register(dev, IPW_REG_INTA, IPW2100_INTA_RX_TRANSFER); __ipw2100_rx_process(priv); __ipw2100_tx_complete(priv); @@ -3150,8 +3104,7 @@ static void ipw2100_irq_tasklet(struct ipw2100_priv *priv) priv->tx_interrupts++; - write_register(dev, IPW_REG_INTA, - IPW2100_INTA_TX_TRANSFER); + write_register(dev, IPW_REG_INTA, IPW2100_INTA_TX_TRANSFER); __ipw2100_tx_complete(priv); ipw2100_tx_send_commands(priv); @@ -3161,9 +3114,7 @@ static void ipw2100_irq_tasklet(struct ipw2100_priv *priv) if (inta & IPW2100_INTA_TX_COMPLETE) { IPW_DEBUG_ISR("TX complete\n"); priv->inta_other++; - write_register( - dev, IPW_REG_INTA, - IPW2100_INTA_TX_COMPLETE); + write_register(dev, IPW_REG_INTA, IPW2100_INTA_TX_COMPLETE); __ipw2100_tx_complete(priv); } @@ -3171,9 +3122,7 @@ static void ipw2100_irq_tasklet(struct ipw2100_priv *priv) if (inta & IPW2100_INTA_EVENT_INTERRUPT) { /* ipw2100_handle_event(dev); */ priv->inta_other++; - write_register( - dev, IPW_REG_INTA, - IPW2100_INTA_EVENT_INTERRUPT); + write_register(dev, IPW_REG_INTA, IPW2100_INTA_EVENT_INTERRUPT); } if (inta & IPW2100_INTA_FW_INIT_DONE) { @@ -3183,30 +3132,25 @@ static void ipw2100_irq_tasklet(struct ipw2100_priv *priv) read_register(dev, IPW_REG_INTA, &tmp); if (tmp & (IPW2100_INTA_FATAL_ERROR | IPW2100_INTA_PARITY_ERROR)) { - write_register( - dev, IPW_REG_INTA, - IPW2100_INTA_FATAL_ERROR | - IPW2100_INTA_PARITY_ERROR); + write_register(dev, IPW_REG_INTA, + IPW2100_INTA_FATAL_ERROR | + IPW2100_INTA_PARITY_ERROR); } - write_register(dev, IPW_REG_INTA, - IPW2100_INTA_FW_INIT_DONE); + write_register(dev, IPW_REG_INTA, IPW2100_INTA_FW_INIT_DONE); } if (inta & IPW2100_INTA_STATUS_CHANGE) { IPW_DEBUG_ISR("Status change interrupt\n"); priv->inta_other++; - write_register( - dev, IPW_REG_INTA, - IPW2100_INTA_STATUS_CHANGE); + write_register(dev, IPW_REG_INTA, IPW2100_INTA_STATUS_CHANGE); } if (inta & IPW2100_INTA_SLAVE_MODE_HOST_COMMAND_DONE) { IPW_DEBUG_ISR("slave host mode interrupt\n"); priv->inta_other++; - write_register( - dev, IPW_REG_INTA, - IPW2100_INTA_SLAVE_MODE_HOST_COMMAND_DONE); + write_register(dev, IPW_REG_INTA, + IPW2100_INTA_SLAVE_MODE_HOST_COMMAND_DONE); } priv->in_isr--; @@ -3217,9 +3161,7 @@ static void ipw2100_irq_tasklet(struct ipw2100_priv *priv) IPW_DEBUG_ISR("exit\n"); } - -static irqreturn_t ipw2100_interrupt(int irq, void *data, - struct pt_regs *regs) +static irqreturn_t ipw2100_interrupt(int irq, void *data, struct pt_regs *regs) { struct ipw2100_priv *priv = data; u32 inta, inta_mask; @@ -3227,7 +3169,7 @@ static irqreturn_t ipw2100_interrupt(int irq, void *data, if (!data) return IRQ_NONE; - spin_lock(&priv->low_lock); + spin_lock(&priv->low_lock); /* We check to see if we should be ignoring interrupts before * we touch the hardware. During ucode load if we try and handle @@ -3261,10 +3203,10 @@ static irqreturn_t ipw2100_interrupt(int irq, void *data, ipw2100_disable_interrupts(priv); tasklet_schedule(&priv->irq_tasklet); - spin_unlock(&priv->low_lock); + spin_unlock(&priv->low_lock); return IRQ_HANDLED; - none: + none: spin_unlock(&priv->low_lock); return IRQ_NONE; } @@ -3294,10 +3236,8 @@ static int ipw2100_tx(struct ieee80211_txb *txb, struct net_device *dev, packet->info.d_struct.txb = txb; - IPW_DEBUG_TX("Sending fragment (%d bytes):\n", - txb->fragments[0]->len); - printk_buf(IPW_DL_TX, txb->fragments[0]->data, - txb->fragments[0]->len); + IPW_DEBUG_TX("Sending fragment (%d bytes):\n", txb->fragments[0]->len); + printk_buf(IPW_DL_TX, txb->fragments[0]->data, txb->fragments[0]->len); packet->jiffy_start = jiffies; @@ -3312,22 +3252,23 @@ static int ipw2100_tx(struct ieee80211_txb *txb, struct net_device *dev, spin_unlock_irqrestore(&priv->low_lock, flags); return 0; - fail_unlock: + fail_unlock: netif_stop_queue(dev); spin_unlock_irqrestore(&priv->low_lock, flags); return 1; } - static int ipw2100_msg_allocate(struct ipw2100_priv *priv) { int i, j, err = -EINVAL; void *v; dma_addr_t p; - priv->msg_buffers = (struct ipw2100_tx_packet *)kmalloc( - IPW_COMMAND_POOL_SIZE * sizeof(struct ipw2100_tx_packet), - GFP_KERNEL); + priv->msg_buffers = + (struct ipw2100_tx_packet *)kmalloc(IPW_COMMAND_POOL_SIZE * + sizeof(struct + ipw2100_tx_packet), + GFP_KERNEL); if (!priv->msg_buffers) { printk(KERN_ERR DRV_NAME ": %s: PCI alloc failed for msg " "buffers.\n", priv->net_dev->name); @@ -3335,15 +3276,12 @@ static int ipw2100_msg_allocate(struct ipw2100_priv *priv) } for (i = 0; i < IPW_COMMAND_POOL_SIZE; i++) { - v = pci_alloc_consistent( - priv->pci_dev, - sizeof(struct ipw2100_cmd_header), - &p); + v = pci_alloc_consistent(priv->pci_dev, + sizeof(struct ipw2100_cmd_header), &p); if (!v) { printk(KERN_ERR DRV_NAME ": " "%s: PCI alloc failed for msg " - "buffers.\n", - priv->net_dev->name); + "buffers.\n", priv->net_dev->name); err = -ENOMEM; break; } @@ -3352,7 +3290,7 @@ static int ipw2100_msg_allocate(struct ipw2100_priv *priv) priv->msg_buffers[i].type = COMMAND; priv->msg_buffers[i].info.c_struct.cmd = - (struct ipw2100_cmd_header*)v; + (struct ipw2100_cmd_header *)v; priv->msg_buffers[i].info.c_struct.cmd_phys = p; } @@ -3360,11 +3298,11 @@ static int ipw2100_msg_allocate(struct ipw2100_priv *priv) return 0; for (j = 0; j < i; j++) { - pci_free_consistent( - priv->pci_dev, - sizeof(struct ipw2100_cmd_header), - priv->msg_buffers[j].info.c_struct.cmd, - priv->msg_buffers[j].info.c_struct.cmd_phys); + pci_free_consistent(priv->pci_dev, + sizeof(struct ipw2100_cmd_header), + priv->msg_buffers[j].info.c_struct.cmd, + priv->msg_buffers[j].info.c_struct. + cmd_phys); } kfree(priv->msg_buffers); @@ -3398,7 +3336,8 @@ static void ipw2100_msg_free(struct ipw2100_priv *priv) pci_free_consistent(priv->pci_dev, sizeof(struct ipw2100_cmd_header), priv->msg_buffers[i].info.c_struct.cmd, - priv->msg_buffers[i].info.c_struct.cmd_phys); + priv->msg_buffers[i].info.c_struct. + cmd_phys); } kfree(priv->msg_buffers); @@ -3424,6 +3363,7 @@ static ssize_t show_pci(struct device *d, struct device_attribute *attr, return out - buf; } + static DEVICE_ATTR(pci, S_IRUGO, show_pci, NULL); static ssize_t show_cfg(struct device *d, struct device_attribute *attr, @@ -3432,209 +3372,269 @@ static ssize_t show_cfg(struct device *d, struct device_attribute *attr, struct ipw2100_priv *p = d->driver_data; return sprintf(buf, "0x%08x\n", (int)p->config); } + static DEVICE_ATTR(cfg, S_IRUGO, show_cfg, NULL); static ssize_t show_status(struct device *d, struct device_attribute *attr, - char *buf) + char *buf) { struct ipw2100_priv *p = d->driver_data; return sprintf(buf, "0x%08x\n", (int)p->status); } + static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); static ssize_t show_capability(struct device *d, struct device_attribute *attr, - char *buf) + char *buf) { struct ipw2100_priv *p = d->driver_data; return sprintf(buf, "0x%08x\n", (int)p->capability); } -static DEVICE_ATTR(capability, S_IRUGO, show_capability, NULL); +static DEVICE_ATTR(capability, S_IRUGO, show_capability, NULL); #define IPW2100_REG(x) { IPW_ ##x, #x } static const struct { u32 addr; const char *name; } hw_data[] = { - IPW2100_REG(REG_GP_CNTRL), - IPW2100_REG(REG_GPIO), - IPW2100_REG(REG_INTA), - IPW2100_REG(REG_INTA_MASK), - IPW2100_REG(REG_RESET_REG), -}; +IPW2100_REG(REG_GP_CNTRL), + IPW2100_REG(REG_GPIO), + IPW2100_REG(REG_INTA), + IPW2100_REG(REG_INTA_MASK), IPW2100_REG(REG_RESET_REG),}; #define IPW2100_NIC(x, s) { x, #x, s } static const struct { u32 addr; const char *name; size_t size; } nic_data[] = { - IPW2100_NIC(IPW2100_CONTROL_REG, 2), - IPW2100_NIC(0x210014, 1), - IPW2100_NIC(0x210000, 1), -}; +IPW2100_NIC(IPW2100_CONTROL_REG, 2), + IPW2100_NIC(0x210014, 1), IPW2100_NIC(0x210000, 1),}; #define IPW2100_ORD(x, d) { IPW_ORD_ ##x, #x, d } static const struct { u8 index; const char *name; const char *desc; } ord_data[] = { - IPW2100_ORD(STAT_TX_HOST_REQUESTS, "requested Host Tx's (MSDU)"), - IPW2100_ORD(STAT_TX_HOST_COMPLETE, "successful Host Tx's (MSDU)"), - IPW2100_ORD(STAT_TX_DIR_DATA, "successful Directed Tx's (MSDU)"), - IPW2100_ORD(STAT_TX_DIR_DATA1, "successful Directed Tx's (MSDU) @ 1MB"), - IPW2100_ORD(STAT_TX_DIR_DATA2, "successful Directed Tx's (MSDU) @ 2MB"), - IPW2100_ORD(STAT_TX_DIR_DATA5_5, "successful Directed Tx's (MSDU) @ 5_5MB"), - IPW2100_ORD(STAT_TX_DIR_DATA11, "successful Directed Tx's (MSDU) @ 11MB"), - IPW2100_ORD(STAT_TX_NODIR_DATA1, "successful Non_Directed Tx's (MSDU) @ 1MB"), - IPW2100_ORD(STAT_TX_NODIR_DATA2, "successful Non_Directed Tx's (MSDU) @ 2MB"), - IPW2100_ORD(STAT_TX_NODIR_DATA5_5, "successful Non_Directed Tx's (MSDU) @ 5.5MB"), - IPW2100_ORD(STAT_TX_NODIR_DATA11, "successful Non_Directed Tx's (MSDU) @ 11MB"), - IPW2100_ORD(STAT_NULL_DATA, "successful NULL data Tx's"), - IPW2100_ORD(STAT_TX_RTS, "successful Tx RTS"), - IPW2100_ORD(STAT_TX_CTS, "successful Tx CTS"), - IPW2100_ORD(STAT_TX_ACK, "successful Tx ACK"), - IPW2100_ORD(STAT_TX_ASSN, "successful Association Tx's"), - IPW2100_ORD(STAT_TX_ASSN_RESP, "successful Association response Tx's"), - IPW2100_ORD(STAT_TX_REASSN, "successful Reassociation Tx's"), - IPW2100_ORD(STAT_TX_REASSN_RESP, "successful Reassociation response Tx's"), - IPW2100_ORD(STAT_TX_PROBE, "probes successfully transmitted"), - IPW2100_ORD(STAT_TX_PROBE_RESP, "probe responses successfully transmitted"), - IPW2100_ORD(STAT_TX_BEACON, "tx beacon"), - IPW2100_ORD(STAT_TX_ATIM, "Tx ATIM"), - IPW2100_ORD(STAT_TX_DISASSN, "successful Disassociation TX"), - IPW2100_ORD(STAT_TX_AUTH, "successful Authentication Tx"), - IPW2100_ORD(STAT_TX_DEAUTH, "successful Deauthentication TX"), - IPW2100_ORD(STAT_TX_TOTAL_BYTES, "Total successful Tx data bytes"), - IPW2100_ORD(STAT_TX_RETRIES, "Tx retries"), - IPW2100_ORD(STAT_TX_RETRY1, "Tx retries at 1MBPS"), - IPW2100_ORD(STAT_TX_RETRY2, "Tx retries at 2MBPS"), - IPW2100_ORD(STAT_TX_RETRY5_5, "Tx retries at 5.5MBPS"), - IPW2100_ORD(STAT_TX_RETRY11, "Tx retries at 11MBPS"), - IPW2100_ORD(STAT_TX_FAILURES, "Tx Failures"), - IPW2100_ORD(STAT_TX_MAX_TRIES_IN_HOP,"times max tries in a hop failed"), - IPW2100_ORD(STAT_TX_DISASSN_FAIL, "times disassociation failed"), - IPW2100_ORD(STAT_TX_ERR_CTS, "missed/bad CTS frames"), - IPW2100_ORD(STAT_TX_ERR_ACK, "tx err due to acks"), - IPW2100_ORD(STAT_RX_HOST, "packets passed to host"), - IPW2100_ORD(STAT_RX_DIR_DATA, "directed packets"), - IPW2100_ORD(STAT_RX_DIR_DATA1, "directed packets at 1MB"), - IPW2100_ORD(STAT_RX_DIR_DATA2, "directed packets at 2MB"), - IPW2100_ORD(STAT_RX_DIR_DATA5_5, "directed packets at 5.5MB"), - IPW2100_ORD(STAT_RX_DIR_DATA11, "directed packets at 11MB"), - IPW2100_ORD(STAT_RX_NODIR_DATA,"nondirected packets"), - IPW2100_ORD(STAT_RX_NODIR_DATA1, "nondirected packets at 1MB"), - IPW2100_ORD(STAT_RX_NODIR_DATA2, "nondirected packets at 2MB"), - IPW2100_ORD(STAT_RX_NODIR_DATA5_5, "nondirected packets at 5.5MB"), - IPW2100_ORD(STAT_RX_NODIR_DATA11, "nondirected packets at 11MB"), - IPW2100_ORD(STAT_RX_NULL_DATA, "null data rx's"), - IPW2100_ORD(STAT_RX_RTS, "Rx RTS"), - IPW2100_ORD(STAT_RX_CTS, "Rx CTS"), - IPW2100_ORD(STAT_RX_ACK, "Rx ACK"), - IPW2100_ORD(STAT_RX_CFEND, "Rx CF End"), - IPW2100_ORD(STAT_RX_CFEND_ACK, "Rx CF End + CF Ack"), - IPW2100_ORD(STAT_RX_ASSN, "Association Rx's"), - IPW2100_ORD(STAT_RX_ASSN_RESP, "Association response Rx's"), - IPW2100_ORD(STAT_RX_REASSN, "Reassociation Rx's"), - IPW2100_ORD(STAT_RX_REASSN_RESP, "Reassociation response Rx's"), - IPW2100_ORD(STAT_RX_PROBE, "probe Rx's"), - IPW2100_ORD(STAT_RX_PROBE_RESP, "probe response Rx's"), - IPW2100_ORD(STAT_RX_BEACON, "Rx beacon"), - IPW2100_ORD(STAT_RX_ATIM, "Rx ATIM"), - IPW2100_ORD(STAT_RX_DISASSN, "disassociation Rx"), - IPW2100_ORD(STAT_RX_AUTH, "authentication Rx"), - IPW2100_ORD(STAT_RX_DEAUTH, "deauthentication Rx"), - IPW2100_ORD(STAT_RX_TOTAL_BYTES,"Total rx data bytes received"), - IPW2100_ORD(STAT_RX_ERR_CRC, "packets with Rx CRC error"), - IPW2100_ORD(STAT_RX_ERR_CRC1, "Rx CRC errors at 1MB"), - IPW2100_ORD(STAT_RX_ERR_CRC2, "Rx CRC errors at 2MB"), - IPW2100_ORD(STAT_RX_ERR_CRC5_5, "Rx CRC errors at 5.5MB"), - IPW2100_ORD(STAT_RX_ERR_CRC11, "Rx CRC errors at 11MB"), - IPW2100_ORD(STAT_RX_DUPLICATE1, "duplicate rx packets at 1MB"), - IPW2100_ORD(STAT_RX_DUPLICATE2, "duplicate rx packets at 2MB"), - IPW2100_ORD(STAT_RX_DUPLICATE5_5, "duplicate rx packets at 5.5MB"), - IPW2100_ORD(STAT_RX_DUPLICATE11, "duplicate rx packets at 11MB"), - IPW2100_ORD(STAT_RX_DUPLICATE, "duplicate rx packets"), - IPW2100_ORD(PERS_DB_LOCK, "locking fw permanent db"), - IPW2100_ORD(PERS_DB_SIZE, "size of fw permanent db"), - IPW2100_ORD(PERS_DB_ADDR, "address of fw permanent db"), - IPW2100_ORD(STAT_RX_INVALID_PROTOCOL, "rx frames with invalid protocol"), - IPW2100_ORD(SYS_BOOT_TIME, "Boot time"), - IPW2100_ORD(STAT_RX_NO_BUFFER, "rx frames rejected due to no buffer"), - IPW2100_ORD(STAT_RX_MISSING_FRAG, "rx frames dropped due to missing fragment"), - IPW2100_ORD(STAT_RX_ORPHAN_FRAG, "rx frames dropped due to non-sequential fragment"), - IPW2100_ORD(STAT_RX_ORPHAN_FRAME, "rx frames dropped due to unmatched 1st frame"), - IPW2100_ORD(STAT_RX_FRAG_AGEOUT, "rx frames dropped due to uncompleted frame"), - IPW2100_ORD(STAT_RX_ICV_ERRORS, "ICV errors during decryption"), - IPW2100_ORD(STAT_PSP_SUSPENSION,"times adapter suspended"), - IPW2100_ORD(STAT_PSP_BCN_TIMEOUT, "beacon timeout"), - IPW2100_ORD(STAT_PSP_POLL_TIMEOUT, "poll response timeouts"), - IPW2100_ORD(STAT_PSP_NONDIR_TIMEOUT, "timeouts waiting for last {broad,multi}cast pkt"), - IPW2100_ORD(STAT_PSP_RX_DTIMS, "PSP DTIMs received"), - IPW2100_ORD(STAT_PSP_RX_TIMS, "PSP TIMs received"), - IPW2100_ORD(STAT_PSP_STATION_ID,"PSP Station ID"), - IPW2100_ORD(LAST_ASSN_TIME, "RTC time of last association"), - IPW2100_ORD(STAT_PERCENT_MISSED_BCNS,"current calculation of % missed beacons"), - IPW2100_ORD(STAT_PERCENT_RETRIES,"current calculation of % missed tx retries"), - IPW2100_ORD(ASSOCIATED_AP_PTR, "0 if not associated, else pointer to AP table entry"), - IPW2100_ORD(AVAILABLE_AP_CNT, "AP's decsribed in the AP table"), - IPW2100_ORD(AP_LIST_PTR, "Ptr to list of available APs"), - IPW2100_ORD(STAT_AP_ASSNS, "associations"), - IPW2100_ORD(STAT_ASSN_FAIL, "association failures"), - IPW2100_ORD(STAT_ASSN_RESP_FAIL,"failures due to response fail"), - IPW2100_ORD(STAT_FULL_SCANS, "full scans"), - IPW2100_ORD(CARD_DISABLED, "Card Disabled"), - IPW2100_ORD(STAT_ROAM_INHIBIT, "times roaming was inhibited due to activity"), - IPW2100_ORD(RSSI_AT_ASSN, "RSSI of associated AP at time of association"), - IPW2100_ORD(STAT_ASSN_CAUSE1, "reassociation: no probe response or TX on hop"), - IPW2100_ORD(STAT_ASSN_CAUSE2, "reassociation: poor tx/rx quality"), - IPW2100_ORD(STAT_ASSN_CAUSE3, "reassociation: tx/rx quality (excessive AP load"), - IPW2100_ORD(STAT_ASSN_CAUSE4, "reassociation: AP RSSI level"), - IPW2100_ORD(STAT_ASSN_CAUSE5, "reassociations due to load leveling"), - IPW2100_ORD(STAT_AUTH_FAIL, "times authentication failed"), - IPW2100_ORD(STAT_AUTH_RESP_FAIL,"times authentication response failed"), - IPW2100_ORD(STATION_TABLE_CNT, "entries in association table"), - IPW2100_ORD(RSSI_AVG_CURR, "Current avg RSSI"), - IPW2100_ORD(POWER_MGMT_MODE, "Power mode - 0=CAM, 1=PSP"), - IPW2100_ORD(COUNTRY_CODE, "IEEE country code as recv'd from beacon"), - IPW2100_ORD(COUNTRY_CHANNELS, "channels suported by country"), - IPW2100_ORD(RESET_CNT, "adapter resets (warm)"), - IPW2100_ORD(BEACON_INTERVAL, "Beacon interval"), - IPW2100_ORD(ANTENNA_DIVERSITY, "TRUE if antenna diversity is disabled"), - IPW2100_ORD(DTIM_PERIOD, "beacon intervals between DTIMs"), - IPW2100_ORD(OUR_FREQ, "current radio freq lower digits - channel ID"), - IPW2100_ORD(RTC_TIME, "current RTC time"), - IPW2100_ORD(PORT_TYPE, "operating mode"), - IPW2100_ORD(CURRENT_TX_RATE, "current tx rate"), - IPW2100_ORD(SUPPORTED_RATES, "supported tx rates"), - IPW2100_ORD(ATIM_WINDOW, "current ATIM Window"), - IPW2100_ORD(BASIC_RATES, "basic tx rates"), - IPW2100_ORD(NIC_HIGHEST_RATE, "NIC highest tx rate"), - IPW2100_ORD(AP_HIGHEST_RATE, "AP highest tx rate"), - IPW2100_ORD(CAPABILITIES, "Management frame capability field"), - IPW2100_ORD(AUTH_TYPE, "Type of authentication"), - IPW2100_ORD(RADIO_TYPE, "Adapter card platform type"), - IPW2100_ORD(RTS_THRESHOLD, "Min packet length for RTS handshaking"), - IPW2100_ORD(INT_MODE, "International mode"), - IPW2100_ORD(FRAGMENTATION_THRESHOLD, "protocol frag threshold"), - IPW2100_ORD(EEPROM_SRAM_DB_BLOCK_START_ADDRESS, "EEPROM offset in SRAM"), - IPW2100_ORD(EEPROM_SRAM_DB_BLOCK_SIZE, "EEPROM size in SRAM"), - IPW2100_ORD(EEPROM_SKU_CAPABILITY, "EEPROM SKU Capability"), - IPW2100_ORD(EEPROM_IBSS_11B_CHANNELS, "EEPROM IBSS 11b channel set"), - IPW2100_ORD(MAC_VERSION, "MAC Version"), - IPW2100_ORD(MAC_REVISION, "MAC Revision"), - IPW2100_ORD(RADIO_VERSION, "Radio Version"), - IPW2100_ORD(NIC_MANF_DATE_TIME, "MANF Date/Time STAMP"), - IPW2100_ORD(UCODE_VERSION, "Ucode Version"), -}; - +IPW2100_ORD(STAT_TX_HOST_REQUESTS, "requested Host Tx's (MSDU)"), + IPW2100_ORD(STAT_TX_HOST_COMPLETE, + "successful Host Tx's (MSDU)"), + IPW2100_ORD(STAT_TX_DIR_DATA, + "successful Directed Tx's (MSDU)"), + IPW2100_ORD(STAT_TX_DIR_DATA1, + "successful Directed Tx's (MSDU) @ 1MB"), + IPW2100_ORD(STAT_TX_DIR_DATA2, + "successful Directed Tx's (MSDU) @ 2MB"), + IPW2100_ORD(STAT_TX_DIR_DATA5_5, + "successful Directed Tx's (MSDU) @ 5_5MB"), + IPW2100_ORD(STAT_TX_DIR_DATA11, + "successful Directed Tx's (MSDU) @ 11MB"), + IPW2100_ORD(STAT_TX_NODIR_DATA1, + "successful Non_Directed Tx's (MSDU) @ 1MB"), + IPW2100_ORD(STAT_TX_NODIR_DATA2, + "successful Non_Directed Tx's (MSDU) @ 2MB"), + IPW2100_ORD(STAT_TX_NODIR_DATA5_5, + "successful Non_Directed Tx's (MSDU) @ 5.5MB"), + IPW2100_ORD(STAT_TX_NODIR_DATA11, + "successful Non_Directed Tx's (MSDU) @ 11MB"), + IPW2100_ORD(STAT_NULL_DATA, "successful NULL data Tx's"), + IPW2100_ORD(STAT_TX_RTS, "successful Tx RTS"), + IPW2100_ORD(STAT_TX_CTS, "successful Tx CTS"), + IPW2100_ORD(STAT_TX_ACK, "successful Tx ACK"), + IPW2100_ORD(STAT_TX_ASSN, "successful Association Tx's"), + IPW2100_ORD(STAT_TX_ASSN_RESP, + "successful Association response Tx's"), + IPW2100_ORD(STAT_TX_REASSN, + "successful Reassociation Tx's"), + IPW2100_ORD(STAT_TX_REASSN_RESP, + "successful Reassociation response Tx's"), + IPW2100_ORD(STAT_TX_PROBE, + "probes successfully transmitted"), + IPW2100_ORD(STAT_TX_PROBE_RESP, + "probe responses successfully transmitted"), + IPW2100_ORD(STAT_TX_BEACON, "tx beacon"), + IPW2100_ORD(STAT_TX_ATIM, "Tx ATIM"), + IPW2100_ORD(STAT_TX_DISASSN, + "successful Disassociation TX"), + IPW2100_ORD(STAT_TX_AUTH, "successful Authentication Tx"), + IPW2100_ORD(STAT_TX_DEAUTH, + "successful Deauthentication TX"), + IPW2100_ORD(STAT_TX_TOTAL_BYTES, + "Total successful Tx data bytes"), + IPW2100_ORD(STAT_TX_RETRIES, "Tx retries"), + IPW2100_ORD(STAT_TX_RETRY1, "Tx retries at 1MBPS"), + IPW2100_ORD(STAT_TX_RETRY2, "Tx retries at 2MBPS"), + IPW2100_ORD(STAT_TX_RETRY5_5, "Tx retries at 5.5MBPS"), + IPW2100_ORD(STAT_TX_RETRY11, "Tx retries at 11MBPS"), + IPW2100_ORD(STAT_TX_FAILURES, "Tx Failures"), + IPW2100_ORD(STAT_TX_MAX_TRIES_IN_HOP, + "times max tries in a hop failed"), + IPW2100_ORD(STAT_TX_DISASSN_FAIL, + "times disassociation failed"), + IPW2100_ORD(STAT_TX_ERR_CTS, "missed/bad CTS frames"), + IPW2100_ORD(STAT_TX_ERR_ACK, "tx err due to acks"), + IPW2100_ORD(STAT_RX_HOST, "packets passed to host"), + IPW2100_ORD(STAT_RX_DIR_DATA, "directed packets"), + IPW2100_ORD(STAT_RX_DIR_DATA1, "directed packets at 1MB"), + IPW2100_ORD(STAT_RX_DIR_DATA2, "directed packets at 2MB"), + IPW2100_ORD(STAT_RX_DIR_DATA5_5, + "directed packets at 5.5MB"), + IPW2100_ORD(STAT_RX_DIR_DATA11, "directed packets at 11MB"), + IPW2100_ORD(STAT_RX_NODIR_DATA, "nondirected packets"), + IPW2100_ORD(STAT_RX_NODIR_DATA1, + "nondirected packets at 1MB"), + IPW2100_ORD(STAT_RX_NODIR_DATA2, + "nondirected packets at 2MB"), + IPW2100_ORD(STAT_RX_NODIR_DATA5_5, + "nondirected packets at 5.5MB"), + IPW2100_ORD(STAT_RX_NODIR_DATA11, + "nondirected packets at 11MB"), + IPW2100_ORD(STAT_RX_NULL_DATA, "null data rx's"), + IPW2100_ORD(STAT_RX_RTS, "Rx RTS"), IPW2100_ORD(STAT_RX_CTS, + "Rx CTS"), + IPW2100_ORD(STAT_RX_ACK, "Rx ACK"), + IPW2100_ORD(STAT_RX_CFEND, "Rx CF End"), + IPW2100_ORD(STAT_RX_CFEND_ACK, "Rx CF End + CF Ack"), + IPW2100_ORD(STAT_RX_ASSN, "Association Rx's"), + IPW2100_ORD(STAT_RX_ASSN_RESP, "Association response Rx's"), + IPW2100_ORD(STAT_RX_REASSN, "Reassociation Rx's"), + IPW2100_ORD(STAT_RX_REASSN_RESP, + "Reassociation response Rx's"), + IPW2100_ORD(STAT_RX_PROBE, "probe Rx's"), + IPW2100_ORD(STAT_RX_PROBE_RESP, "probe response Rx's"), + IPW2100_ORD(STAT_RX_BEACON, "Rx beacon"), + IPW2100_ORD(STAT_RX_ATIM, "Rx ATIM"), + IPW2100_ORD(STAT_RX_DISASSN, "disassociation Rx"), + IPW2100_ORD(STAT_RX_AUTH, "authentication Rx"), + IPW2100_ORD(STAT_RX_DEAUTH, "deauthentication Rx"), + IPW2100_ORD(STAT_RX_TOTAL_BYTES, + "Total rx data bytes received"), + IPW2100_ORD(STAT_RX_ERR_CRC, "packets with Rx CRC error"), + IPW2100_ORD(STAT_RX_ERR_CRC1, "Rx CRC errors at 1MB"), + IPW2100_ORD(STAT_RX_ERR_CRC2, "Rx CRC errors at 2MB"), + IPW2100_ORD(STAT_RX_ERR_CRC5_5, "Rx CRC errors at 5.5MB"), + IPW2100_ORD(STAT_RX_ERR_CRC11, "Rx CRC errors at 11MB"), + IPW2100_ORD(STAT_RX_DUPLICATE1, + "duplicate rx packets at 1MB"), + IPW2100_ORD(STAT_RX_DUPLICATE2, + "duplicate rx packets at 2MB"), + IPW2100_ORD(STAT_RX_DUPLICATE5_5, + "duplicate rx packets at 5.5MB"), + IPW2100_ORD(STAT_RX_DUPLICATE11, + "duplicate rx packets at 11MB"), + IPW2100_ORD(STAT_RX_DUPLICATE, "duplicate rx packets"), + IPW2100_ORD(PERS_DB_LOCK, "locking fw permanent db"), + IPW2100_ORD(PERS_DB_SIZE, "size of fw permanent db"), + IPW2100_ORD(PERS_DB_ADDR, "address of fw permanent db"), + IPW2100_ORD(STAT_RX_INVALID_PROTOCOL, + "rx frames with invalid protocol"), + IPW2100_ORD(SYS_BOOT_TIME, "Boot time"), + IPW2100_ORD(STAT_RX_NO_BUFFER, + "rx frames rejected due to no buffer"), + IPW2100_ORD(STAT_RX_MISSING_FRAG, + "rx frames dropped due to missing fragment"), + IPW2100_ORD(STAT_RX_ORPHAN_FRAG, + "rx frames dropped due to non-sequential fragment"), + IPW2100_ORD(STAT_RX_ORPHAN_FRAME, + "rx frames dropped due to unmatched 1st frame"), + IPW2100_ORD(STAT_RX_FRAG_AGEOUT, + "rx frames dropped due to uncompleted frame"), + IPW2100_ORD(STAT_RX_ICV_ERRORS, + "ICV errors during decryption"), + IPW2100_ORD(STAT_PSP_SUSPENSION, "times adapter suspended"), + IPW2100_ORD(STAT_PSP_BCN_TIMEOUT, "beacon timeout"), + IPW2100_ORD(STAT_PSP_POLL_TIMEOUT, + "poll response timeouts"), + IPW2100_ORD(STAT_PSP_NONDIR_TIMEOUT, + "timeouts waiting for last {broad,multi}cast pkt"), + IPW2100_ORD(STAT_PSP_RX_DTIMS, "PSP DTIMs received"), + IPW2100_ORD(STAT_PSP_RX_TIMS, "PSP TIMs received"), + IPW2100_ORD(STAT_PSP_STATION_ID, "PSP Station ID"), + IPW2100_ORD(LAST_ASSN_TIME, "RTC time of last association"), + IPW2100_ORD(STAT_PERCENT_MISSED_BCNS, + "current calculation of % missed beacons"), + IPW2100_ORD(STAT_PERCENT_RETRIES, + "current calculation of % missed tx retries"), + IPW2100_ORD(ASSOCIATED_AP_PTR, + "0 if not associated, else pointer to AP table entry"), + IPW2100_ORD(AVAILABLE_AP_CNT, + "AP's decsribed in the AP table"), + IPW2100_ORD(AP_LIST_PTR, "Ptr to list of available APs"), + IPW2100_ORD(STAT_AP_ASSNS, "associations"), + IPW2100_ORD(STAT_ASSN_FAIL, "association failures"), + IPW2100_ORD(STAT_ASSN_RESP_FAIL, + "failures due to response fail"), + IPW2100_ORD(STAT_FULL_SCANS, "full scans"), + IPW2100_ORD(CARD_DISABLED, "Card Disabled"), + IPW2100_ORD(STAT_ROAM_INHIBIT, + "times roaming was inhibited due to activity"), + IPW2100_ORD(RSSI_AT_ASSN, + "RSSI of associated AP at time of association"), + IPW2100_ORD(STAT_ASSN_CAUSE1, + "reassociation: no probe response or TX on hop"), + IPW2100_ORD(STAT_ASSN_CAUSE2, + "reassociation: poor tx/rx quality"), + IPW2100_ORD(STAT_ASSN_CAUSE3, + "reassociation: tx/rx quality (excessive AP load"), + IPW2100_ORD(STAT_ASSN_CAUSE4, + "reassociation: AP RSSI level"), + IPW2100_ORD(STAT_ASSN_CAUSE5, + "reassociations due to load leveling"), + IPW2100_ORD(STAT_AUTH_FAIL, "times authentication failed"), + IPW2100_ORD(STAT_AUTH_RESP_FAIL, + "times authentication response failed"), + IPW2100_ORD(STATION_TABLE_CNT, + "entries in association table"), + IPW2100_ORD(RSSI_AVG_CURR, "Current avg RSSI"), + IPW2100_ORD(POWER_MGMT_MODE, "Power mode - 0=CAM, 1=PSP"), + IPW2100_ORD(COUNTRY_CODE, + "IEEE country code as recv'd from beacon"), + IPW2100_ORD(COUNTRY_CHANNELS, + "channels suported by country"), + IPW2100_ORD(RESET_CNT, "adapter resets (warm)"), + IPW2100_ORD(BEACON_INTERVAL, "Beacon interval"), + IPW2100_ORD(ANTENNA_DIVERSITY, + "TRUE if antenna diversity is disabled"), + IPW2100_ORD(DTIM_PERIOD, "beacon intervals between DTIMs"), + IPW2100_ORD(OUR_FREQ, + "current radio freq lower digits - channel ID"), + IPW2100_ORD(RTC_TIME, "current RTC time"), + IPW2100_ORD(PORT_TYPE, "operating mode"), + IPW2100_ORD(CURRENT_TX_RATE, "current tx rate"), + IPW2100_ORD(SUPPORTED_RATES, "supported tx rates"), + IPW2100_ORD(ATIM_WINDOW, "current ATIM Window"), + IPW2100_ORD(BASIC_RATES, "basic tx rates"), + IPW2100_ORD(NIC_HIGHEST_RATE, "NIC highest tx rate"), + IPW2100_ORD(AP_HIGHEST_RATE, "AP highest tx rate"), + IPW2100_ORD(CAPABILITIES, + "Management frame capability field"), + IPW2100_ORD(AUTH_TYPE, "Type of authentication"), + IPW2100_ORD(RADIO_TYPE, "Adapter card platform type"), + IPW2100_ORD(RTS_THRESHOLD, + "Min packet length for RTS handshaking"), + IPW2100_ORD(INT_MODE, "International mode"), + IPW2100_ORD(FRAGMENTATION_THRESHOLD, + "protocol frag threshold"), + IPW2100_ORD(EEPROM_SRAM_DB_BLOCK_START_ADDRESS, + "EEPROM offset in SRAM"), + IPW2100_ORD(EEPROM_SRAM_DB_BLOCK_SIZE, + "EEPROM size in SRAM"), + IPW2100_ORD(EEPROM_SKU_CAPABILITY, "EEPROM SKU Capability"), + IPW2100_ORD(EEPROM_IBSS_11B_CHANNELS, + "EEPROM IBSS 11b channel set"), + IPW2100_ORD(MAC_VERSION, "MAC Version"), + IPW2100_ORD(MAC_REVISION, "MAC Revision"), + IPW2100_ORD(RADIO_VERSION, "Radio Version"), + IPW2100_ORD(NIC_MANF_DATE_TIME, "MANF Date/Time STAMP"), + IPW2100_ORD(UCODE_VERSION, "Ucode Version"),}; static ssize_t show_registers(struct device *d, struct device_attribute *attr, - char *buf) + char *buf) { int i; struct ipw2100_priv *priv = dev_get_drvdata(d); struct net_device *dev = priv->net_dev; - char * out = buf; + char *out = buf; u32 val = 0; out += sprintf(out, "%30s [Address ] : Hex\n", "Register"); @@ -3647,15 +3647,15 @@ static ssize_t show_registers(struct device *d, struct device_attribute *attr, return out - buf; } -static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL); +static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL); static ssize_t show_hardware(struct device *d, struct device_attribute *attr, - char *buf) + char *buf) { struct ipw2100_priv *priv = dev_get_drvdata(d); struct net_device *dev = priv->net_dev; - char * out = buf; + char *out = buf; int i; out += sprintf(out, "%30s [Address ] : Hex\n", "NIC entry"); @@ -3688,11 +3688,11 @@ static ssize_t show_hardware(struct device *d, struct device_attribute *attr, } return out - buf; } -static DEVICE_ATTR(hardware, S_IRUGO, show_hardware, NULL); +static DEVICE_ATTR(hardware, S_IRUGO, show_hardware, NULL); static ssize_t show_memory(struct device *d, struct device_attribute *attr, - char *buf) + char *buf) { struct ipw2100_priv *priv = dev_get_drvdata(d); struct net_device *dev = priv->net_dev; @@ -3708,10 +3708,13 @@ static ssize_t show_memory(struct device *d, struct device_attribute *attr, /* sysfs provides us PAGE_SIZE buffer */ while (len < PAGE_SIZE - 128 && loop < 0x30000) { - if (priv->snapshot[0]) for (i = 0; i < 4; i++) - buffer[i] = *(u32 *)SNAPSHOT_ADDR(loop + i * 4); - else for (i = 0; i < 4; i++) - read_nic_dword(dev, loop + i * 4, &buffer[i]); + if (priv->snapshot[0]) + for (i = 0; i < 4; i++) + buffer[i] = + *(u32 *) SNAPSHOT_ADDR(loop + i * 4); + else + for (i = 0; i < 4; i++) + read_nic_dword(dev, loop + i * 4, &buffer[i]); if (priv->dump_raw) len += sprintf(buf + len, @@ -3719,26 +3722,26 @@ static ssize_t show_memory(struct device *d, struct device_attribute *attr, "%c%c%c%c" "%c%c%c%c" "%c%c%c%c", - ((u8*)buffer)[0x0], - ((u8*)buffer)[0x1], - ((u8*)buffer)[0x2], - ((u8*)buffer)[0x3], - ((u8*)buffer)[0x4], - ((u8*)buffer)[0x5], - ((u8*)buffer)[0x6], - ((u8*)buffer)[0x7], - ((u8*)buffer)[0x8], - ((u8*)buffer)[0x9], - ((u8*)buffer)[0xa], - ((u8*)buffer)[0xb], - ((u8*)buffer)[0xc], - ((u8*)buffer)[0xd], - ((u8*)buffer)[0xe], - ((u8*)buffer)[0xf]); + ((u8 *) buffer)[0x0], + ((u8 *) buffer)[0x1], + ((u8 *) buffer)[0x2], + ((u8 *) buffer)[0x3], + ((u8 *) buffer)[0x4], + ((u8 *) buffer)[0x5], + ((u8 *) buffer)[0x6], + ((u8 *) buffer)[0x7], + ((u8 *) buffer)[0x8], + ((u8 *) buffer)[0x9], + ((u8 *) buffer)[0xa], + ((u8 *) buffer)[0xb], + ((u8 *) buffer)[0xc], + ((u8 *) buffer)[0xd], + ((u8 *) buffer)[0xe], + ((u8 *) buffer)[0xf]); else len += sprintf(buf + len, "%s\n", snprint_line(line, sizeof(line), - (u8*)buffer, 16, loop)); + (u8 *) buffer, 16, loop)); loop += 16; } @@ -3746,7 +3749,7 @@ static ssize_t show_memory(struct device *d, struct device_attribute *attr, } static ssize_t store_memory(struct device *d, struct device_attribute *attr, - const char *buf, size_t count) + const char *buf, size_t count) { struct ipw2100_priv *priv = dev_get_drvdata(d); struct net_device *dev = priv->net_dev; @@ -3758,32 +3761,30 @@ static ssize_t store_memory(struct device *d, struct device_attribute *attr, if (p[0] == '1' || (count >= 2 && tolower(p[0]) == 'o' && tolower(p[1]) == 'n')) { IPW_DEBUG_INFO("%s: Setting memory dump to RAW mode.\n", - dev->name); + dev->name); priv->dump_raw = 1; } else if (p[0] == '0' || (count >= 2 && tolower(p[0]) == 'o' && - tolower(p[1]) == 'f')) { + tolower(p[1]) == 'f')) { IPW_DEBUG_INFO("%s: Setting memory dump to HEX mode.\n", - dev->name); + dev->name); priv->dump_raw = 0; } else if (tolower(p[0]) == 'r') { - IPW_DEBUG_INFO("%s: Resetting firmware snapshot.\n", - dev->name); + IPW_DEBUG_INFO("%s: Resetting firmware snapshot.\n", dev->name); ipw2100_snapshot_free(priv); } else IPW_DEBUG_INFO("%s: Usage: 0|on = HEX, 1|off = RAW, " - "reset = clear memory snapshot\n", - dev->name); + "reset = clear memory snapshot\n", dev->name); return count; } -static DEVICE_ATTR(memory, S_IWUSR|S_IRUGO, show_memory, store_memory); +static DEVICE_ATTR(memory, S_IWUSR | S_IRUGO, show_memory, store_memory); static ssize_t show_ordinals(struct device *d, struct device_attribute *attr, - char *buf) + char *buf) { struct ipw2100_priv *priv = dev_get_drvdata(d); u32 val = 0; @@ -3814,14 +3815,14 @@ static ssize_t show_ordinals(struct device *d, struct device_attribute *attr, return len; } -static DEVICE_ATTR(ordinals, S_IRUGO, show_ordinals, NULL); +static DEVICE_ATTR(ordinals, S_IRUGO, show_ordinals, NULL); static ssize_t show_stats(struct device *d, struct device_attribute *attr, - char *buf) + char *buf) { struct ipw2100_priv *priv = dev_get_drvdata(d); - char * out = buf; + char *out = buf; out += sprintf(out, "interrupts: %d {tx: %d, rx: %d, other: %d}\n", priv->interrupts, priv->tx_interrupts, @@ -3835,8 +3836,8 @@ static ssize_t show_stats(struct device *d, struct device_attribute *attr, return out - buf; } -static DEVICE_ATTR(stats, S_IRUGO, show_stats, NULL); +static DEVICE_ATTR(stats, S_IRUGO, show_stats, NULL); static int ipw2100_switch_mode(struct ipw2100_priv *priv, u32 mode) { @@ -3864,19 +3865,18 @@ static int ipw2100_switch_mode(struct ipw2100_priv *priv, u32 mode) priv->last_mode = priv->ieee->iw_mode; priv->net_dev->type = ARPHRD_IEEE80211; break; -#endif /* CONFIG_IPW2100_MONITOR */ +#endif /* CONFIG_IPW2100_MONITOR */ } priv->ieee->iw_mode = mode; #ifdef CONFIG_PM - /* Indicate ipw2100_download_firmware download firmware + /* Indicate ipw2100_download_firmware download firmware * from disk instead of memory. */ ipw2100_firmware.version = 0; #endif - printk(KERN_INFO "%s: Reseting on mode change.\n", - priv->net_dev->name); + printk(KERN_INFO "%s: Reseting on mode change.\n", priv->net_dev->name); priv->reset_backoff = 0; schedule_reset(priv); @@ -3884,12 +3884,12 @@ static int ipw2100_switch_mode(struct ipw2100_priv *priv, u32 mode) } static ssize_t show_internals(struct device *d, struct device_attribute *attr, - char *buf) + char *buf) { struct ipw2100_priv *priv = dev_get_drvdata(d); int len = 0; -#define DUMP_VAR(x,y) len += sprintf(buf + len, # x ": %" # y "\n", priv-> x) +#define DUMP_VAR(x,y) len += sprintf(buf + len, # x ": %" y "\n", priv-> x) if (priv->status & STATUS_ASSOCIATED) len += sprintf(buf + len, "connected: %lu\n", @@ -3897,52 +3897,54 @@ static ssize_t show_internals(struct device *d, struct device_attribute *attr, else len += sprintf(buf + len, "not connected\n"); - DUMP_VAR(ieee->crypt[priv->ieee->tx_keyidx], p); - DUMP_VAR(status, 08lx); - DUMP_VAR(config, 08lx); - DUMP_VAR(capability, 08lx); + DUMP_VAR(ieee->crypt[priv->ieee->tx_keyidx], "p"); + DUMP_VAR(status, "08lx"); + DUMP_VAR(config, "08lx"); + DUMP_VAR(capability, "08lx"); - len += sprintf(buf + len, "last_rtc: %lu\n", (unsigned long)priv->last_rtc); + len += + sprintf(buf + len, "last_rtc: %lu\n", + (unsigned long)priv->last_rtc); - DUMP_VAR(fatal_error, d); - DUMP_VAR(stop_hang_check, d); - DUMP_VAR(stop_rf_kill, d); - DUMP_VAR(messages_sent, d); + DUMP_VAR(fatal_error, "d"); + DUMP_VAR(stop_hang_check, "d"); + DUMP_VAR(stop_rf_kill, "d"); + DUMP_VAR(messages_sent, "d"); - DUMP_VAR(tx_pend_stat.value, d); - DUMP_VAR(tx_pend_stat.hi, d); + DUMP_VAR(tx_pend_stat.value, "d"); + DUMP_VAR(tx_pend_stat.hi, "d"); - DUMP_VAR(tx_free_stat.value, d); - DUMP_VAR(tx_free_stat.lo, d); + DUMP_VAR(tx_free_stat.value, "d"); + DUMP_VAR(tx_free_stat.lo, "d"); - DUMP_VAR(msg_free_stat.value, d); - DUMP_VAR(msg_free_stat.lo, d); + DUMP_VAR(msg_free_stat.value, "d"); + DUMP_VAR(msg_free_stat.lo, "d"); - DUMP_VAR(msg_pend_stat.value, d); - DUMP_VAR(msg_pend_stat.hi, d); + DUMP_VAR(msg_pend_stat.value, "d"); + DUMP_VAR(msg_pend_stat.hi, "d"); - DUMP_VAR(fw_pend_stat.value, d); - DUMP_VAR(fw_pend_stat.hi, d); + DUMP_VAR(fw_pend_stat.value, "d"); + DUMP_VAR(fw_pend_stat.hi, "d"); - DUMP_VAR(txq_stat.value, d); - DUMP_VAR(txq_stat.lo, d); + DUMP_VAR(txq_stat.value, "d"); + DUMP_VAR(txq_stat.lo, "d"); - DUMP_VAR(ieee->scans, d); - DUMP_VAR(reset_backoff, d); + DUMP_VAR(ieee->scans, "d"); + DUMP_VAR(reset_backoff, "d"); return len; } -static DEVICE_ATTR(internals, S_IRUGO, show_internals, NULL); +static DEVICE_ATTR(internals, S_IRUGO, show_internals, NULL); static ssize_t show_bssinfo(struct device *d, struct device_attribute *attr, - char *buf) + char *buf) { struct ipw2100_priv *priv = dev_get_drvdata(d); char essid[IW_ESSID_MAX_SIZE + 1]; u8 bssid[ETH_ALEN]; u32 chan = 0; - char * out = buf; + char *out = buf; int length; int ret; @@ -3976,8 +3978,8 @@ static ssize_t show_bssinfo(struct device *d, struct device_attribute *attr, return out - buf; } -static DEVICE_ATTR(bssinfo, S_IRUGO, show_bssinfo, NULL); +static DEVICE_ATTR(bssinfo, S_IRUGO, show_bssinfo, NULL); #ifdef CONFIG_IPW_DEBUG static ssize_t show_debug_level(struct device_driver *d, char *buf) @@ -4000,27 +4002,26 @@ static ssize_t store_debug_level(struct device_driver *d, const char *buf, val = simple_strtoul(p, &p, 10); if (p == buf) IPW_DEBUG_INFO(DRV_NAME - ": %s is not in hex or decimal form.\n", buf); + ": %s is not in hex or decimal form.\n", buf); else ipw2100_debug_level = val; return strnlen(buf, count); } + static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, show_debug_level, store_debug_level); -#endif /* CONFIG_IPW_DEBUG */ - +#endif /* CONFIG_IPW_DEBUG */ static ssize_t show_fatal_error(struct device *d, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, char *buf) { struct ipw2100_priv *priv = dev_get_drvdata(d); char *out = buf; int i; if (priv->fatal_error) - out += sprintf(out, "0x%08X\n", - priv->fatal_error); + out += sprintf(out, "0x%08X\n", priv->fatal_error); else out += sprintf(out, "0\n"); @@ -4038,24 +4039,26 @@ static ssize_t show_fatal_error(struct device *d, } static ssize_t store_fatal_error(struct device *d, - struct device_attribute *attr, const char *buf, size_t count) + struct device_attribute *attr, const char *buf, + size_t count) { struct ipw2100_priv *priv = dev_get_drvdata(d); schedule_reset(priv); return count; } -static DEVICE_ATTR(fatal_error, S_IWUSR|S_IRUGO, show_fatal_error, store_fatal_error); +static DEVICE_ATTR(fatal_error, S_IWUSR | S_IRUGO, show_fatal_error, + store_fatal_error); static ssize_t show_scan_age(struct device *d, struct device_attribute *attr, - char *buf) + char *buf) { struct ipw2100_priv *priv = dev_get_drvdata(d); return sprintf(buf, "%d\n", priv->ieee->scan_age); } static ssize_t store_scan_age(struct device *d, struct device_attribute *attr, - const char *buf, size_t count) + const char *buf, size_t count) { struct ipw2100_priv *priv = dev_get_drvdata(d); struct net_device *dev = priv->net_dev; @@ -4078,8 +4081,7 @@ static ssize_t store_scan_age(struct device *d, struct device_attribute *attr, } else val = simple_strtoul(p, &p, 10); if (p == buffer) { - IPW_DEBUG_INFO("%s: user supplied invalid value.\n", - dev->name); + IPW_DEBUG_INFO("%s: user supplied invalid value.\n", dev->name); } else { priv->ieee->scan_age = val; IPW_DEBUG_INFO("set scan_age = %u\n", priv->ieee->scan_age); @@ -4088,11 +4090,11 @@ static ssize_t store_scan_age(struct device *d, struct device_attribute *attr, IPW_DEBUG_INFO("exit\n"); return len; } -static DEVICE_ATTR(scan_age, S_IWUSR | S_IRUGO, show_scan_age, store_scan_age); +static DEVICE_ATTR(scan_age, S_IWUSR | S_IRUGO, show_scan_age, store_scan_age); static ssize_t show_rf_kill(struct device *d, struct device_attribute *attr, - char *buf) + char *buf) { /* 0 - RF kill not enabled 1 - SW based RF kill active (sysfs) @@ -4100,7 +4102,7 @@ static ssize_t show_rf_kill(struct device *d, struct device_attribute *attr, 3 - Both HW and SW baed RF kill active */ struct ipw2100_priv *priv = (struct ipw2100_priv *)d->driver_data; int val = ((priv->status & STATUS_RF_KILL_SW) ? 0x1 : 0x0) | - (rf_kill_active(priv) ? 0x2 : 0x0); + (rf_kill_active(priv) ? 0x2 : 0x0); return sprintf(buf, "%i\n", val); } @@ -4108,7 +4110,7 @@ static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio) { if ((disable_radio ? 1 : 0) == (priv->status & STATUS_RF_KILL_SW ? 1 : 0)) - return 0 ; + return 0; IPW_DEBUG_RF_KILL("Manual SW RF Kill set to: RADIO %s\n", disable_radio ? "OFF" : "ON"); @@ -4126,8 +4128,7 @@ static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio) /* Make sure the RF_KILL check timer is running */ priv->stop_rf_kill = 0; cancel_delayed_work(&priv->rf_kill); - queue_delayed_work(priv->workqueue, &priv->rf_kill, - HZ); + queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ); } else schedule_reset(priv); } @@ -4137,14 +4138,14 @@ static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio) } static ssize_t store_rf_kill(struct device *d, struct device_attribute *attr, - const char *buf, size_t count) + const char *buf, size_t count) { struct ipw2100_priv *priv = dev_get_drvdata(d); ipw_radio_kill_sw(priv, buf[0] == '1'); return count; } -static DEVICE_ATTR(rf_kill, S_IWUSR|S_IRUGO, show_rf_kill, store_rf_kill); +static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill); static struct attribute *ipw2100_sysfs_entries[] = { &dev_attr_hardware.attr, @@ -4168,7 +4169,6 @@ static struct attribute_group ipw2100_attribute_group = { .attrs = ipw2100_sysfs_entries, }; - static int status_queue_allocate(struct ipw2100_priv *priv, int entries) { struct ipw2100_status_queue *q = &priv->status_queue; @@ -4176,11 +4176,11 @@ static int status_queue_allocate(struct ipw2100_priv *priv, int entries) IPW_DEBUG_INFO("enter\n"); q->size = entries * sizeof(struct ipw2100_status); - q->drv = (struct ipw2100_status *)pci_alloc_consistent( - priv->pci_dev, q->size, &q->nic); + q->drv = + (struct ipw2100_status *)pci_alloc_consistent(priv->pci_dev, + q->size, &q->nic); if (!q->drv) { - IPW_DEBUG_WARNING( - "Can not allocate status queue.\n"); + IPW_DEBUG_WARNING("Can not allocate status queue.\n"); return -ENOMEM; } @@ -4196,9 +4196,9 @@ static void status_queue_free(struct ipw2100_priv *priv) IPW_DEBUG_INFO("enter\n"); if (priv->status_queue.drv) { - pci_free_consistent( - priv->pci_dev, priv->status_queue.size, - priv->status_queue.drv, priv->status_queue.nic); + pci_free_consistent(priv->pci_dev, priv->status_queue.size, + priv->status_queue.drv, + priv->status_queue.nic); priv->status_queue.drv = NULL; } @@ -4216,7 +4216,8 @@ static int bd_queue_allocate(struct ipw2100_priv *priv, q->size = entries * sizeof(struct ipw2100_bd); q->drv = pci_alloc_consistent(priv->pci_dev, q->size, &q->nic); if (!q->drv) { - IPW_DEBUG_INFO("can't allocate shared memory for buffer descriptors\n"); + IPW_DEBUG_INFO + ("can't allocate shared memory for buffer descriptors\n"); return -ENOMEM; } memset(q->drv, 0, q->size); @@ -4226,8 +4227,7 @@ static int bd_queue_allocate(struct ipw2100_priv *priv, return 0; } -static void bd_queue_free(struct ipw2100_priv *priv, - struct ipw2100_bd_queue *q) +static void bd_queue_free(struct ipw2100_priv *priv, struct ipw2100_bd_queue *q) { IPW_DEBUG_INFO("enter\n"); @@ -4235,21 +4235,21 @@ static void bd_queue_free(struct ipw2100_priv *priv, return; if (q->drv) { - pci_free_consistent(priv->pci_dev, - q->size, q->drv, q->nic); + pci_free_consistent(priv->pci_dev, q->size, q->drv, q->nic); q->drv = NULL; } IPW_DEBUG_INFO("exit\n"); } -static void bd_queue_initialize( - struct ipw2100_priv *priv, struct ipw2100_bd_queue * q, - u32 base, u32 size, u32 r, u32 w) +static void bd_queue_initialize(struct ipw2100_priv *priv, + struct ipw2100_bd_queue *q, u32 base, u32 size, + u32 r, u32 w) { IPW_DEBUG_INFO("enter\n"); - IPW_DEBUG_INFO("initializing bd queue at virt=%p, phys=%08x\n", q->drv, (u32)q->nic); + IPW_DEBUG_INFO("initializing bd queue at virt=%p, phys=%08x\n", q->drv, + (u32) q->nic); write_register(priv->net_dev, base, q->nic); write_register(priv->net_dev, size, q->entries); @@ -4285,32 +4285,38 @@ static int ipw2100_tx_allocate(struct ipw2100_priv *priv) err = bd_queue_allocate(priv, &priv->tx_queue, TX_QUEUE_LENGTH); if (err) { IPW_DEBUG_ERROR("%s: failed bd_queue_allocate\n", - priv->net_dev->name); + priv->net_dev->name); return err; } - priv->tx_buffers = (struct ipw2100_tx_packet *)kmalloc( - TX_PENDED_QUEUE_LENGTH * sizeof(struct ipw2100_tx_packet), - GFP_ATOMIC); + priv->tx_buffers = + (struct ipw2100_tx_packet *)kmalloc(TX_PENDED_QUEUE_LENGTH * + sizeof(struct + ipw2100_tx_packet), + GFP_ATOMIC); if (!priv->tx_buffers) { - printk(KERN_ERR DRV_NAME ": %s: alloc failed form tx buffers.\n", + printk(KERN_ERR DRV_NAME + ": %s: alloc failed form tx buffers.\n", priv->net_dev->name); bd_queue_free(priv, &priv->tx_queue); return -ENOMEM; } for (i = 0; i < TX_PENDED_QUEUE_LENGTH; i++) { - v = pci_alloc_consistent( - priv->pci_dev, sizeof(struct ipw2100_data_header), &p); + v = pci_alloc_consistent(priv->pci_dev, + sizeof(struct ipw2100_data_header), + &p); if (!v) { - printk(KERN_ERR DRV_NAME ": %s: PCI alloc failed for tx " - "buffers.\n", priv->net_dev->name); + printk(KERN_ERR DRV_NAME + ": %s: PCI alloc failed for tx " "buffers.\n", + priv->net_dev->name); err = -ENOMEM; break; } priv->tx_buffers[i].type = DATA; - priv->tx_buffers[i].info.d_struct.data = (struct ipw2100_data_header*)v; + priv->tx_buffers[i].info.d_struct.data = + (struct ipw2100_data_header *)v; priv->tx_buffers[i].info.d_struct.data_phys = p; priv->tx_buffers[i].info.d_struct.txb = NULL; } @@ -4319,11 +4325,11 @@ static int ipw2100_tx_allocate(struct ipw2100_priv *priv) return 0; for (j = 0; j < i; j++) { - pci_free_consistent( - priv->pci_dev, - sizeof(struct ipw2100_data_header), - priv->tx_buffers[j].info.d_struct.data, - priv->tx_buffers[j].info.d_struct.data_phys); + pci_free_consistent(priv->pci_dev, + sizeof(struct ipw2100_data_header), + priv->tx_buffers[j].info.d_struct.data, + priv->tx_buffers[j].info.d_struct. + data_phys); } kfree(priv->tx_buffers); @@ -4356,7 +4362,8 @@ static void ipw2100_tx_initialize(struct ipw2100_priv *priv) /* We simply drop any SKBs that have been queued for * transmit */ if (priv->tx_buffers[i].info.d_struct.txb) { - ieee80211_txb_free(priv->tx_buffers[i].info.d_struct.txb); + ieee80211_txb_free(priv->tx_buffers[i].info.d_struct. + txb); priv->tx_buffers[i].info.d_struct.txb = NULL; } @@ -4394,15 +4401,17 @@ static void ipw2100_tx_free(struct ipw2100_priv *priv) for (i = 0; i < TX_PENDED_QUEUE_LENGTH; i++) { if (priv->tx_buffers[i].info.d_struct.txb) { - ieee80211_txb_free(priv->tx_buffers[i].info.d_struct.txb); + ieee80211_txb_free(priv->tx_buffers[i].info.d_struct. + txb); priv->tx_buffers[i].info.d_struct.txb = NULL; } if (priv->tx_buffers[i].info.d_struct.data) - pci_free_consistent( - priv->pci_dev, - sizeof(struct ipw2100_data_header), - priv->tx_buffers[i].info.d_struct.data, - priv->tx_buffers[i].info.d_struct.data_phys); + pci_free_consistent(priv->pci_dev, + sizeof(struct ipw2100_data_header), + priv->tx_buffers[i].info.d_struct. + data, + priv->tx_buffers[i].info.d_struct. + data_phys); } kfree(priv->tx_buffers); @@ -4411,8 +4420,6 @@ static void ipw2100_tx_free(struct ipw2100_priv *priv) IPW_DEBUG_INFO("exit\n"); } - - static int ipw2100_rx_allocate(struct ipw2100_priv *priv) { int i, j, err = -EINVAL; @@ -4542,14 +4549,13 @@ static int ipw2100_read_mac_address(struct ipw2100_priv *priv) int err; - err = ipw2100_get_ordinal(priv, IPW_ORD_STAT_ADAPTER_MAC, - mac, &length); + err = ipw2100_get_ordinal(priv, IPW_ORD_STAT_ADAPTER_MAC, mac, &length); if (err) { IPW_DEBUG_INFO("MAC address read failed\n"); return -EIO; } IPW_DEBUG_INFO("card MAC is %02X:%02X:%02X:%02X:%02X:%02X\n", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); memcpy(priv->net_dev->dev_addr, mac, ETH_ALEN); @@ -4576,8 +4582,7 @@ static int ipw2100_set_mac_address(struct ipw2100_priv *priv, int batch_mode) IPW_DEBUG_INFO("enter\n"); if (priv->config & CFG_CUSTOM_MAC) { - memcpy(cmd.host_command_parameters, priv->mac_addr, - ETH_ALEN); + memcpy(cmd.host_command_parameters, priv->mac_addr, ETH_ALEN); memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN); } else memcpy(cmd.host_command_parameters, priv->net_dev->dev_addr, @@ -4614,7 +4619,8 @@ static int ipw2100_set_port_type(struct ipw2100_priv *priv, u32 port_type, if (!batch_mode) { err = ipw2100_disable_adapter(priv); if (err) { - printk(KERN_ERR DRV_NAME ": %s: Could not disable adapter %d\n", + printk(KERN_ERR DRV_NAME + ": %s: Could not disable adapter %d\n", priv->net_dev->name, err); return err; } @@ -4629,7 +4635,6 @@ static int ipw2100_set_port_type(struct ipw2100_priv *priv, u32 port_type, return err; } - static int ipw2100_set_channel(struct ipw2100_priv *priv, u32 channel, int batch_mode) { @@ -4660,8 +4665,7 @@ static int ipw2100_set_channel(struct ipw2100_priv *priv, u32 channel, err = ipw2100_hw_send_command(priv, &cmd); if (err) { - IPW_DEBUG_INFO("Failed to set channel to %d", - channel); + IPW_DEBUG_INFO("Failed to set channel to %d", channel); return err; } @@ -4703,15 +4707,14 @@ static int ipw2100_system_config(struct ipw2100_priv *priv, int batch_mode) cmd.host_command_parameters[0] |= IPW_CFG_IBSS_AUTO_START; cmd.host_command_parameters[0] |= IPW_CFG_IBSS_MASK | - IPW_CFG_BSS_MASK | - IPW_CFG_802_1x_ENABLE; + IPW_CFG_BSS_MASK | IPW_CFG_802_1x_ENABLE; if (!(priv->config & CFG_LONG_PREAMBLE)) cmd.host_command_parameters[0] |= IPW_CFG_PREAMBLE_AUTO; err = ipw2100_get_ordinal(priv, IPW_ORD_EEPROM_IBSS_11B_CHANNELS, - &ibss_mask, &len); + &ibss_mask, &len); if (err) ibss_mask = IPW_IBSS_11B_DEFAULT_MASK; @@ -4719,7 +4722,7 @@ static int ipw2100_system_config(struct ipw2100_priv *priv, int batch_mode) cmd.host_command_parameters[2] = REG_CHANNEL_MASK & ibss_mask; /* 11b only */ - /*cmd.host_command_parameters[0] |= DIVERSITY_ANTENNA_A;*/ + /*cmd.host_command_parameters[0] |= DIVERSITY_ANTENNA_A; */ err = ipw2100_hw_send_command(priv, &cmd); if (err) @@ -4783,8 +4786,7 @@ static int ipw2100_set_tx_rates(struct ipw2100_priv *priv, u32 rate, return 0; } -static int ipw2100_set_power_mode(struct ipw2100_priv *priv, - int power_level) +static int ipw2100_set_power_mode(struct ipw2100_priv *priv, int power_level) { struct host_command cmd = { .host_command = POWER_MODE, @@ -4805,11 +4807,10 @@ static int ipw2100_set_power_mode(struct ipw2100_priv *priv, priv->power_mode = IPW_POWER_ENABLED | power_level; #ifdef CONFIG_IPW2100_TX_POWER - if (priv->port_type == IBSS && - priv->adhoc_power != DFTL_IBSS_TX_POWER) { + if (priv->port_type == IBSS && priv->adhoc_power != DFTL_IBSS_TX_POWER) { /* Set beacon interval */ cmd.host_command = TX_POWER_INDEX; - cmd.host_command_parameters[0] = (u32)priv->adhoc_power; + cmd.host_command_parameters[0] = (u32) priv->adhoc_power; err = ipw2100_hw_send_command(priv, &cmd); if (err) @@ -4820,7 +4821,6 @@ static int ipw2100_set_power_mode(struct ipw2100_priv *priv, return 0; } - static int ipw2100_set_rts_threshold(struct ipw2100_priv *priv, u32 threshold) { struct host_command cmd = { @@ -4925,8 +4925,7 @@ static int ipw2100_set_long_retry(struct ipw2100_priv *priv, u32 retry) return 0; } - -static int ipw2100_set_mandatory_bssid(struct ipw2100_priv *priv, u8 *bssid, +static int ipw2100_set_mandatory_bssid(struct ipw2100_priv *priv, u8 * bssid, int batch_mode) { struct host_command cmd = { @@ -4938,16 +4937,15 @@ static int ipw2100_set_mandatory_bssid(struct ipw2100_priv *priv, u8 *bssid, #ifdef CONFIG_IPW_DEBUG if (bssid != NULL) - IPW_DEBUG_HC( - "MANDATORY_BSSID: %02X:%02X:%02X:%02X:%02X:%02X\n", - bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], - bssid[5]); + IPW_DEBUG_HC("MANDATORY_BSSID: %02X:%02X:%02X:%02X:%02X:%02X\n", + bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], + bssid[5]); else IPW_DEBUG_HC("MANDATORY_BSSID: \n"); #endif /* if BSSID is empty then we disable mandatory bssid mode */ if (bssid != NULL) - memcpy((u8 *)cmd.host_command_parameters, bssid, ETH_ALEN); + memcpy((u8 *) cmd.host_command_parameters, bssid, ETH_ALEN); if (!batch_mode) { err = ipw2100_disable_adapter(priv); @@ -4997,8 +4995,7 @@ void x(struct ieee80211_assoc_frame *wpa_assoc) { struct ipw2100_wpa_assoc_frame frame; frame->fixed_ie_mask = IPW_WPA_CAPABILTIES | - IPW_WPA_LISTENINTERVAL | - IPW_WPA_AP_ADDRESS; + IPW_WPA_LISTENINTERVAL | IPW_WPA_AP_ADDRESS; frame->capab_info = wpa_assoc->capab_info; frame->lisen_interval = wpa_assoc->listent_interval; memcpy(frame->current_ap, wpa_assoc->current_ap, ETH_ALEN); @@ -5011,18 +5008,15 @@ void x(struct ieee80211_assoc_frame *wpa_assoc) * the IEs from wpa_frame into frame. */ frame->var_ie_len = calculate_ie_len(wpa_assoc); - memcpy(frame->var_ie, wpa_assoc->variable, frame->var_ie_len); + memcpy(frame->var_ie, wpa_assoc->variable, frame->var_ie_len); ipw2100_set_wpa_ie(priv, &frame, 0); } #endif - - - static int ipw2100_set_wpa_ie(struct ipw2100_priv *, struct ipw2100_wpa_assoc_frame *, int) -__attribute__ ((unused)); + __attribute__ ((unused)); static int ipw2100_set_wpa_ie(struct ipw2100_priv *priv, struct ipw2100_wpa_assoc_frame *wpa_frame, @@ -5076,7 +5070,7 @@ static int ipw2100_set_security_information(struct ipw2100_priv *priv, .host_command_length = sizeof(struct security_info_params) }; struct security_info_params *security = - (struct security_info_params *)&cmd.host_command_parameters; + (struct security_info_params *)&cmd.host_command_parameters; int err; memset(security, 0, sizeof(*security)); @@ -5094,25 +5088,25 @@ static int ipw2100_set_security_information(struct ipw2100_priv *priv, break; case SEC_LEVEL_1: security->allowed_ciphers = IPW_WEP40_CIPHER | - IPW_WEP104_CIPHER; + IPW_WEP104_CIPHER; break; case SEC_LEVEL_2: security->allowed_ciphers = IPW_WEP40_CIPHER | - IPW_WEP104_CIPHER | IPW_TKIP_CIPHER; + IPW_WEP104_CIPHER | IPW_TKIP_CIPHER; break; case SEC_LEVEL_2_CKIP: security->allowed_ciphers = IPW_WEP40_CIPHER | - IPW_WEP104_CIPHER | IPW_CKIP_CIPHER; + IPW_WEP104_CIPHER | IPW_CKIP_CIPHER; break; case SEC_LEVEL_3: security->allowed_ciphers = IPW_WEP40_CIPHER | - IPW_WEP104_CIPHER | IPW_TKIP_CIPHER | IPW_CCMP_CIPHER; + IPW_WEP104_CIPHER | IPW_TKIP_CIPHER | IPW_CCMP_CIPHER; break; } - IPW_DEBUG_HC( - "SET_SECURITY_INFORMATION: auth:%d cipher:0x%02X (level %d)\n", - security->auth_mode, security->allowed_ciphers, security_level); + IPW_DEBUG_HC + ("SET_SECURITY_INFORMATION: auth:%d cipher:0x%02X (level %d)\n", + security->auth_mode, security->allowed_ciphers, security_level); security->replay_counters_number = 0; @@ -5130,8 +5124,7 @@ static int ipw2100_set_security_information(struct ipw2100_priv *priv, return err; } -static int ipw2100_set_tx_power(struct ipw2100_priv *priv, - u32 tx_power) +static int ipw2100_set_tx_power(struct ipw2100_priv *priv, u32 tx_power) { struct host_command cmd = { .host_command = TX_POWER_INDEX, @@ -5185,7 +5178,6 @@ static int ipw2100_set_ibss_beacon_interval(struct ipw2100_priv *priv, return 0; } - void ipw2100_queues_initialize(struct ipw2100_priv *priv) { ipw2100_tx_initialize(priv); @@ -5203,13 +5195,12 @@ void ipw2100_queues_free(struct ipw2100_priv *priv) int ipw2100_queues_allocate(struct ipw2100_priv *priv) { if (ipw2100_tx_allocate(priv) || - ipw2100_rx_allocate(priv) || - ipw2100_msg_allocate(priv)) + ipw2100_rx_allocate(priv) || ipw2100_msg_allocate(priv)) goto fail; return 0; - fail: + fail: ipw2100_tx_free(priv); ipw2100_rx_free(priv); ipw2100_msg_free(priv); @@ -5235,7 +5226,8 @@ static int ipw2100_set_wep_flags(struct ipw2100_priv *priv, u32 flags, if (!batch_mode) { err = ipw2100_disable_adapter(priv); if (err) { - printk(KERN_ERR DRV_NAME ": %s: Could not disable adapter %d\n", + printk(KERN_ERR DRV_NAME + ": %s: Could not disable adapter %d\n", priv->net_dev->name, err); return err; } @@ -5262,7 +5254,6 @@ struct ipw2100_wep_key { #define WEP_STR_64(x) x[0],x[1],x[2],x[3],x[4] #define WEP_STR_128(x) x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10] - /** * Set a the wep key * @@ -5287,11 +5278,11 @@ static int ipw2100_set_key(struct ipw2100_priv *priv, .host_command_sequence = 0, .host_command_length = sizeof(struct ipw2100_wep_key), }; - struct ipw2100_wep_key *wep_key = (void*)cmd.host_command_parameters; + struct ipw2100_wep_key *wep_key = (void *)cmd.host_command_parameters; int err; IPW_DEBUG_HC("WEP_KEY_INFO: index = %d, len = %d/%d\n", - idx, keylen, len); + idx, keylen, len); /* NOTE: We don't check cached values in case the firmware was reset * or some other problem is occuring. If the user is setting the key, @@ -5308,22 +5299,23 @@ static int ipw2100_set_key(struct ipw2100_priv *priv, /* Will be optimized out on debug not being configured in */ if (keylen == 0) IPW_DEBUG_WEP("%s: Clearing key %d\n", - priv->net_dev->name, wep_key->idx); + priv->net_dev->name, wep_key->idx); else if (keylen == 5) IPW_DEBUG_WEP("%s: idx: %d, len: %d key: " WEP_FMT_64 "\n", - priv->net_dev->name, wep_key->idx, wep_key->len, - WEP_STR_64(wep_key->key)); + priv->net_dev->name, wep_key->idx, wep_key->len, + WEP_STR_64(wep_key->key)); else IPW_DEBUG_WEP("%s: idx: %d, len: %d key: " WEP_FMT_128 - "\n", - priv->net_dev->name, wep_key->idx, wep_key->len, - WEP_STR_128(wep_key->key)); + "\n", + priv->net_dev->name, wep_key->idx, wep_key->len, + WEP_STR_128(wep_key->key)); if (!batch_mode) { err = ipw2100_disable_adapter(priv); /* FIXME: IPG: shouldn't this prink be in _disable_adapter()? */ if (err) { - printk(KERN_ERR DRV_NAME ": %s: Could not disable adapter %d\n", + printk(KERN_ERR DRV_NAME + ": %s: Could not disable adapter %d\n", priv->net_dev->name, err); return err; } @@ -5347,7 +5339,7 @@ static int ipw2100_set_key_index(struct ipw2100_priv *priv, .host_command = WEP_KEY_INDEX, .host_command_sequence = 0, .host_command_length = 4, - .host_command_parameters = { idx }, + .host_command_parameters = {idx}, }; int err; @@ -5359,7 +5351,8 @@ static int ipw2100_set_key_index(struct ipw2100_priv *priv, if (!batch_mode) { err = ipw2100_disable_adapter(priv); if (err) { - printk(KERN_ERR DRV_NAME ": %s: Could not disable adapter %d\n", + printk(KERN_ERR DRV_NAME + ": %s: Could not disable adapter %d\n", priv->net_dev->name, err); return err; } @@ -5374,9 +5367,7 @@ static int ipw2100_set_key_index(struct ipw2100_priv *priv, return err; } - -static int ipw2100_configure_security(struct ipw2100_priv *priv, - int batch_mode) +static int ipw2100_configure_security(struct ipw2100_priv *priv, int batch_mode) { int i, err, auth_mode, sec_level, use_group; @@ -5390,8 +5381,9 @@ static int ipw2100_configure_security(struct ipw2100_priv *priv, } if (!priv->sec.enabled) { - err = ipw2100_set_security_information( - priv, IPW_AUTH_OPEN, SEC_LEVEL_0, 0, 1); + err = + ipw2100_set_security_information(priv, IPW_AUTH_OPEN, + SEC_LEVEL_0, 0, 1); } else { auth_mode = IPW_AUTH_OPEN; if ((priv->sec.flags & SEC_AUTH_MODE) && @@ -5406,8 +5398,9 @@ static int ipw2100_configure_security(struct ipw2100_priv *priv, if (priv->sec.flags & SEC_UNICAST_GROUP) use_group = priv->sec.unicast_uses_group; - err = ipw2100_set_security_information( - priv, auth_mode, sec_level, use_group, 1); + err = + ipw2100_set_security_information(priv, auth_mode, sec_level, + use_group, 1); } if (err) @@ -5433,14 +5426,16 @@ static int ipw2100_configure_security(struct ipw2100_priv *priv, /* Always enable privacy so the Host can filter WEP packets if * encrypted data is sent up */ - err = ipw2100_set_wep_flags( - priv, priv->sec.enabled ? IPW_PRIVACY_CAPABLE : 0, 1); + err = + ipw2100_set_wep_flags(priv, + priv->sec.enabled ? IPW_PRIVACY_CAPABLE : 0, + 1); if (err) goto exit; priv->status &= ~STATUS_SECURITY_UPDATED; - exit: + exit: if (!batch_mode) ipw2100_enable_adapter(priv); @@ -5498,31 +5493,29 @@ static void shim__set_security(struct net_device *dev, priv->status |= STATUS_SECURITY_UPDATED; } - if (sec->flags & SEC_ENABLED && - priv->sec.enabled != sec->enabled) { + if (sec->flags & SEC_ENABLED && priv->sec.enabled != sec->enabled) { priv->sec.flags |= SEC_ENABLED; priv->sec.enabled = sec->enabled; priv->status |= STATUS_SECURITY_UPDATED; force_update = 1; } - if (sec->flags & SEC_LEVEL && - priv->sec.level != sec->level) { + if (sec->flags & SEC_LEVEL && priv->sec.level != sec->level) { priv->sec.level = sec->level; priv->sec.flags |= SEC_LEVEL; priv->status |= STATUS_SECURITY_UPDATED; } IPW_DEBUG_WEP("Security flags: %c %c%c%c%c %c%c%c%c\n", - priv->sec.flags & (1<<8) ? '1' : '0', - priv->sec.flags & (1<<7) ? '1' : '0', - priv->sec.flags & (1<<6) ? '1' : '0', - priv->sec.flags & (1<<5) ? '1' : '0', - priv->sec.flags & (1<<4) ? '1' : '0', - priv->sec.flags & (1<<3) ? '1' : '0', - priv->sec.flags & (1<<2) ? '1' : '0', - priv->sec.flags & (1<<1) ? '1' : '0', - priv->sec.flags & (1<<0) ? '1' : '0'); + priv->sec.flags & (1 << 8) ? '1' : '0', + priv->sec.flags & (1 << 7) ? '1' : '0', + priv->sec.flags & (1 << 6) ? '1' : '0', + priv->sec.flags & (1 << 5) ? '1' : '0', + priv->sec.flags & (1 << 4) ? '1' : '0', + priv->sec.flags & (1 << 3) ? '1' : '0', + priv->sec.flags & (1 << 2) ? '1' : '0', + priv->sec.flags & (1 << 1) ? '1' : '0', + priv->sec.flags & (1 << 0) ? '1' : '0'); /* As a temporary work around to enable WPA until we figure out why * wpa_supplicant toggles the security capability of the driver, which @@ -5531,7 +5524,7 @@ static void shim__set_security(struct net_device *dev, * if (force_update || !(priv->status & STATUS_ASSOCIATED))*/ if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING))) ipw2100_configure_security(priv, 0); -done: + done: up(&priv->action_sem); } @@ -5556,7 +5549,7 @@ static int ipw2100_adapter_setup(struct ipw2100_priv *priv) return 0; } -#endif /* CONFIG_IPW2100_MONITOR */ +#endif /* CONFIG_IPW2100_MONITOR */ err = ipw2100_read_mac_address(priv); if (err) @@ -5576,7 +5569,7 @@ static int ipw2100_adapter_setup(struct ipw2100_priv *priv) return err; } - err = ipw2100_system_config(priv, batch_mode); + err = ipw2100_system_config(priv, batch_mode); if (err) return err; @@ -5614,8 +5607,10 @@ static int ipw2100_adapter_setup(struct ipw2100_priv *priv) return err; if (priv->ieee->iw_mode == IW_MODE_ADHOC) { - err = ipw2100_set_ibss_beacon_interval( - priv, priv->beacon_interval, batch_mode); + err = + ipw2100_set_ibss_beacon_interval(priv, + priv->beacon_interval, + batch_mode); if (err) return err; @@ -5625,18 +5620,17 @@ static int ipw2100_adapter_setup(struct ipw2100_priv *priv) } /* - err = ipw2100_set_fragmentation_threshold( - priv, priv->frag_threshold, batch_mode); - if (err) - return err; - */ + err = ipw2100_set_fragmentation_threshold( + priv, priv->frag_threshold, batch_mode); + if (err) + return err; + */ IPW_DEBUG_INFO("exit\n"); return 0; } - /************************************************************************* * * EXTERNALLY CALLED METHODS @@ -5669,7 +5663,7 @@ static int ipw2100_set_address(struct net_device *dev, void *p) ipw2100_reset_adapter(priv); return 0; - done: + done: up(&priv->action_sem); return err; } @@ -5708,7 +5702,7 @@ static int ipw2100_close(struct net_device *dev) /* Flush the TX queue ... */ while (!list_empty(&priv->tx_pend_list)) { element = priv->tx_pend_list.next; - packet = list_entry(element, struct ipw2100_tx_packet, list); + packet = list_entry(element, struct ipw2100_tx_packet, list); list_del(element); DEC_STAT(&priv->tx_pend_stat); @@ -5726,8 +5720,6 @@ static int ipw2100_close(struct net_device *dev) return 0; } - - /* * TODO: Fix this function... its just wrong */ @@ -5747,7 +5739,6 @@ static void ipw2100_tx_timeout(struct net_device *dev) schedule_reset(priv); } - /* * TODO: reimplement it so that it reads statistics * from the adapter using ordinal tables @@ -5796,7 +5787,7 @@ static struct net_device_stats *ipw2100_stats(struct net_device *dev) struct ipw2100_param { u32 cmd; u8 sta_addr[ETH_ALEN]; - union { + union { struct { u8 name; u32 value; @@ -5805,16 +5796,16 @@ struct ipw2100_param { u32 len; u8 *data; } wpa_ie; - struct{ + struct { int command; - int reason_code; + int reason_code; } mlme; struct { u8 alg[IPW2100_CRYPT_ALG_NAME_LEN]; u8 set_tx; u32 err; u8 idx; - u8 seq[8]; /* sequence counter (set: RX, get: TX) */ + u8 seq[8]; /* sequence counter (set: RX, get: TX) */ u16 key_len; u8 key[0]; } crypt; @@ -5824,7 +5815,8 @@ struct ipw2100_param { /* end of driver_ipw2100.c code */ -static int ipw2100_wpa_enable(struct ipw2100_priv *priv, int value){ +static int ipw2100_wpa_enable(struct ipw2100_priv *priv, int value) +{ struct ieee80211_device *ieee = priv->ieee; struct ieee80211_security sec = { @@ -5834,7 +5826,7 @@ static int ipw2100_wpa_enable(struct ipw2100_priv *priv, int value){ ieee->wpa_enabled = value; - if (value){ + if (value) { sec.level = SEC_LEVEL_3; sec.enabled = 1; } else { @@ -5853,7 +5845,8 @@ static int ipw2100_wpa_enable(struct ipw2100_priv *priv, int value){ #define AUTH_ALG_OPEN_SYSTEM 0x1 #define AUTH_ALG_SHARED_KEY 0x2 -static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value){ +static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value) +{ struct ieee80211_device *ieee = priv->ieee; struct ieee80211_security sec = { @@ -5861,7 +5854,7 @@ static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value){ }; int ret = 0; - if (value & AUTH_ALG_SHARED_KEY){ + if (value & AUTH_ALG_SHARED_KEY) { sec.auth_mode = WLAN_AUTH_SHARED_KEY; ieee->open_wep = 0; } else { @@ -5877,72 +5870,73 @@ static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value){ return ret; } - -static int ipw2100_wpa_set_param(struct net_device *dev, u8 name, u32 value){ +static int ipw2100_wpa_set_param(struct net_device *dev, u8 name, u32 value) +{ struct ipw2100_priv *priv = ieee80211_priv(dev); - int ret=0; + int ret = 0; - switch(name){ - case IPW2100_PARAM_WPA_ENABLED: - ret = ipw2100_wpa_enable(priv, value); - break; + switch (name) { + case IPW2100_PARAM_WPA_ENABLED: + ret = ipw2100_wpa_enable(priv, value); + break; - case IPW2100_PARAM_TKIP_COUNTERMEASURES: - priv->ieee->tkip_countermeasures=value; - break; + case IPW2100_PARAM_TKIP_COUNTERMEASURES: + priv->ieee->tkip_countermeasures = value; + break; - case IPW2100_PARAM_DROP_UNENCRYPTED: - priv->ieee->drop_unencrypted=value; - break; + case IPW2100_PARAM_DROP_UNENCRYPTED: + priv->ieee->drop_unencrypted = value; + break; - case IPW2100_PARAM_PRIVACY_INVOKED: - priv->ieee->privacy_invoked=value; - break; + case IPW2100_PARAM_PRIVACY_INVOKED: + priv->ieee->privacy_invoked = value; + break; - case IPW2100_PARAM_AUTH_ALGS: - ret = ipw2100_wpa_set_auth_algs(priv, value); - break; + case IPW2100_PARAM_AUTH_ALGS: + ret = ipw2100_wpa_set_auth_algs(priv, value); + break; - case IPW2100_PARAM_IEEE_802_1X: - priv->ieee->ieee802_1x=value; - break; + case IPW2100_PARAM_IEEE_802_1X: + priv->ieee->ieee802_1x = value; + break; - default: - printk(KERN_ERR DRV_NAME ": %s: Unknown WPA param: %d\n", - dev->name, name); - ret = -EOPNOTSUPP; + default: + printk(KERN_ERR DRV_NAME ": %s: Unknown WPA param: %d\n", + dev->name, name); + ret = -EOPNOTSUPP; } return ret; } -static int ipw2100_wpa_mlme(struct net_device *dev, int command, int reason){ +static int ipw2100_wpa_mlme(struct net_device *dev, int command, int reason) +{ struct ipw2100_priv *priv = ieee80211_priv(dev); - int ret=0; + int ret = 0; - switch(command){ - case IPW2100_MLME_STA_DEAUTH: - // silently ignore - break; + switch (command) { + case IPW2100_MLME_STA_DEAUTH: + // silently ignore + break; - case IPW2100_MLME_STA_DISASSOC: - ipw2100_disassociate_bssid(priv); - break; + case IPW2100_MLME_STA_DISASSOC: + ipw2100_disassociate_bssid(priv); + break; - default: - printk(KERN_ERR DRV_NAME ": %s: Unknown MLME request: %d\n", - dev->name, command); - ret = -EOPNOTSUPP; + default: + printk(KERN_ERR DRV_NAME ": %s: Unknown MLME request: %d\n", + dev->name, command); + ret = -EOPNOTSUPP; } return ret; } - void ipw2100_wpa_assoc_frame(struct ipw2100_priv *priv, - char *wpa_ie, int wpa_ie_len){ + char *wpa_ie, int wpa_ie_len) +{ struct ipw2100_wpa_assoc_frame frame; @@ -5957,23 +5951,22 @@ void ipw2100_wpa_assoc_frame(struct ipw2100_priv *priv, ipw2100_set_wpa_ie(priv, &frame, 0); } - static int ipw2100_wpa_set_wpa_ie(struct net_device *dev, - struct ipw2100_param *param, int plen){ + struct ipw2100_param *param, int plen) +{ struct ipw2100_priv *priv = ieee80211_priv(dev); struct ieee80211_device *ieee = priv->ieee; u8 *buf; - if (! ieee->wpa_enabled) - return -EOPNOTSUPP; + if (!ieee->wpa_enabled) + return -EOPNOTSUPP; if (param->u.wpa_ie.len > MAX_WPA_IE_LEN || - (param->u.wpa_ie.len && - param->u.wpa_ie.data==NULL)) + (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL)) return -EINVAL; - if (param->u.wpa_ie.len){ + if (param->u.wpa_ie.len) { buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL); if (buf == NULL) return -ENOMEM; @@ -5998,7 +5991,9 @@ static int ipw2100_wpa_set_wpa_ie(struct net_device *dev, /* implementation borrowed from hostap driver */ static int ipw2100_wpa_set_encryption(struct net_device *dev, - struct ipw2100_param *param, int param_len){ + struct ipw2100_param *param, + int param_len) +{ int ret = 0; struct ipw2100_priv *priv = ieee80211_priv(dev); @@ -6014,9 +6009,10 @@ static int ipw2100_wpa_set_encryption(struct net_device *dev, param->u.crypt.alg[IPW2100_CRYPT_ALG_NAME_LEN - 1] = '\0'; if (param_len != - (int) ((char *) param->u.crypt.key - (char *) param) + - param->u.crypt.key_len){ - IPW_DEBUG_INFO("Len mismatch %d, %d\n", param_len, param->u.crypt.key_len); + (int)((char *)param->u.crypt.key - (char *)param) + + param->u.crypt.key_len) { + IPW_DEBUG_INFO("Len mismatch %d, %d\n", param_len, + param->u.crypt.key_len); return -EINVAL; } if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && @@ -6030,7 +6026,7 @@ static int ipw2100_wpa_set_encryption(struct net_device *dev, } if (strcmp(param->u.crypt.alg, "none") == 0) { - if (crypt){ + if (crypt) { sec.enabled = 0; sec.level = SEC_LEVEL_0; sec.flags |= SEC_ENABLED | SEC_LEVEL; @@ -6054,7 +6050,7 @@ static int ipw2100_wpa_set_encryption(struct net_device *dev, } if (ops == NULL) { IPW_DEBUG_INFO("%s: unknown crypto alg '%s'\n", - dev->name, param->u.crypt.alg); + dev->name, param->u.crypt.alg); param->u.crypt.err = IPW2100_CRYPT_ERR_UNKNOWN_ALG; ret = -EINVAL; goto done; @@ -6066,7 +6062,7 @@ static int ipw2100_wpa_set_encryption(struct net_device *dev, ieee80211_crypt_delayed_deinit(ieee, crypt); new_crypt = (struct ieee80211_crypt_data *) - kmalloc(sizeof(struct ieee80211_crypt_data), GFP_KERNEL); + kmalloc(sizeof(struct ieee80211_crypt_data), GFP_KERNEL); if (new_crypt == NULL) { ret = -ENOMEM; goto done; @@ -6074,12 +6070,13 @@ static int ipw2100_wpa_set_encryption(struct net_device *dev, memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data)); new_crypt->ops = ops; if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) - new_crypt->priv = new_crypt->ops->init(param->u.crypt.idx); + new_crypt->priv = + new_crypt->ops->init(param->u.crypt.idx); if (new_crypt->priv == NULL) { kfree(new_crypt); param->u.crypt.err = - IPW2100_CRYPT_ERR_CRYPT_INIT_FAILED; + IPW2100_CRYPT_ERR_CRYPT_INIT_FAILED; ret = -EINVAL; goto done; } @@ -6091,24 +6088,25 @@ static int ipw2100_wpa_set_encryption(struct net_device *dev, (*crypt)->ops->set_key(param->u.crypt.key, param->u.crypt.key_len, param->u.crypt.seq, (*crypt)->priv) < 0) { - IPW_DEBUG_INFO("%s: key setting failed\n", - dev->name); + IPW_DEBUG_INFO("%s: key setting failed\n", dev->name); param->u.crypt.err = IPW2100_CRYPT_ERR_KEY_SET_FAILED; ret = -EINVAL; goto done; } - if (param->u.crypt.set_tx){ + if (param->u.crypt.set_tx) { ieee->tx_keyidx = param->u.crypt.idx; sec.active_key = param->u.crypt.idx; sec.flags |= SEC_ACTIVE_KEY; } - if (ops->name != NULL){ + if (ops->name != NULL) { if (strcmp(ops->name, "WEP") == 0) { - memcpy(sec.keys[param->u.crypt.idx], param->u.crypt.key, param->u.crypt.key_len); - sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len; + memcpy(sec.keys[param->u.crypt.idx], param->u.crypt.key, + param->u.crypt.key_len); + sec.key_sizes[param->u.crypt.idx] = + param->u.crypt.key_len; sec.flags |= (1 << param->u.crypt.idx); sec.flags |= SEC_LEVEL; sec.level = SEC_LEVEL_1; @@ -6120,7 +6118,7 @@ static int ipw2100_wpa_set_encryption(struct net_device *dev, sec.level = SEC_LEVEL_3; } } - done: + done: if (ieee->set_security) ieee->set_security(ieee->dev, &sec); @@ -6131,8 +6129,7 @@ static int ipw2100_wpa_set_encryption(struct net_device *dev, * the callbacks structures used to initialize the 802.11 stack. */ if (ieee->reset_on_keychange && ieee->iw_mode != IW_MODE_INFRA && - ieee->reset_port && - ieee->reset_port(dev)) { + ieee->reset_port && ieee->reset_port(dev)) { IPW_DEBUG_INFO("%s: reset_port failed\n", dev->name); param->u.crypt.err = IPW2100_CRYPT_ERR_CARD_CONF_FAILED; return -EINVAL; @@ -6141,11 +6138,11 @@ static int ipw2100_wpa_set_encryption(struct net_device *dev, return ret; } - -static int ipw2100_wpa_supplicant(struct net_device *dev, struct iw_point *p){ +static int ipw2100_wpa_supplicant(struct net_device *dev, struct iw_point *p) +{ struct ipw2100_param *param; - int ret=0; + int ret = 0; IPW_DEBUG_IOCTL("wpa_supplicant: len=%d\n", p->length); @@ -6156,12 +6153,12 @@ static int ipw2100_wpa_supplicant(struct net_device *dev, struct iw_point *p){ if (param == NULL) return -ENOMEM; - if (copy_from_user(param, p->pointer, p->length)){ + if (copy_from_user(param, p->pointer, p->length)) { kfree(param); return -EFAULT; } - switch (param->cmd){ + switch (param->cmd) { case IPW2100_CMD_SET_WPA_PARAM: ret = ipw2100_wpa_set_param(dev, param->u.wpa_param.name, @@ -6182,8 +6179,9 @@ static int ipw2100_wpa_supplicant(struct net_device *dev, struct iw_point *p){ break; default: - printk(KERN_ERR DRV_NAME ": %s: Unknown WPA supplicant request: %d\n", - dev->name, param->cmd); + printk(KERN_ERR DRV_NAME + ": %s: Unknown WPA supplicant request: %d\n", dev->name, + param->cmd); ret = -EOPNOTSUPP; } @@ -6194,28 +6192,27 @@ static int ipw2100_wpa_supplicant(struct net_device *dev, struct iw_point *p){ kfree(param); return ret; } -#endif /* CONFIG_IEEE80211_WPA */ +#endif /* CONFIG_IEEE80211_WPA */ static int ipw2100_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { #ifdef CONFIG_IEEE80211_WPA - struct iwreq *wrq = (struct iwreq *) rq; - int ret=-1; - switch (cmd){ - case IPW2100_IOCTL_WPA_SUPPLICANT: + struct iwreq *wrq = (struct iwreq *)rq; + int ret = -1; + switch (cmd) { + case IPW2100_IOCTL_WPA_SUPPLICANT: ret = ipw2100_wpa_supplicant(dev, &wrq->u.data); return ret; - default: + default: return -EOPNOTSUPP; } -#endif /* CONFIG_IEEE80211_WPA */ +#endif /* CONFIG_IEEE80211_WPA */ return -EOPNOTSUPP; } - static void ipw_ethtool_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { @@ -6236,14 +6233,13 @@ static void ipw_ethtool_get_drvinfo(struct net_device *dev, static u32 ipw2100_ethtool_get_link(struct net_device *dev) { - struct ipw2100_priv *priv = ieee80211_priv(dev); - return (priv->status & STATUS_ASSOCIATED) ? 1 : 0; + struct ipw2100_priv *priv = ieee80211_priv(dev); + return (priv->status & STATUS_ASSOCIATED) ? 1 : 0; } - static struct ethtool_ops ipw2100_ethtool_ops = { - .get_link = ipw2100_ethtool_get_link, - .get_drvinfo = ipw_ethtool_get_drvinfo, + .get_link = ipw2100_ethtool_get_link, + .get_drvinfo = ipw_ethtool_get_drvinfo, }; static void ipw2100_hang_check(void *adapter) @@ -6288,7 +6284,6 @@ static void ipw2100_hang_check(void *adapter) spin_unlock_irqrestore(&priv->low_lock, flags); } - static void ipw2100_rf_kill(void *adapter) { struct ipw2100_priv *priv = adapter; @@ -6313,7 +6308,7 @@ static void ipw2100_rf_kill(void *adapter) IPW_DEBUG_RF_KILL("HW RF Kill deactivated. SW RF Kill still " "enabled\n"); - exit_unlock: + exit_unlock: spin_unlock_irqrestore(&priv->low_lock, flags); } @@ -6321,11 +6316,10 @@ static void ipw2100_irq_tasklet(struct ipw2100_priv *priv); /* Look into using netdev destructor to shutdown ieee80211? */ -static struct net_device *ipw2100_alloc_device( - struct pci_dev *pci_dev, - void __iomem *base_addr, - unsigned long mem_start, - unsigned long mem_len) +static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, + void __iomem * base_addr, + unsigned long mem_start, + unsigned long mem_len) { struct ipw2100_priv *priv; struct net_device *dev; @@ -6351,7 +6345,7 @@ static struct net_device *ipw2100_alloc_device( dev->wireless_handlers = &ipw2100_wx_handler_def; dev->get_wireless_stats = ipw2100_wx_wireless_stats; dev->set_mac_address = ipw2100_set_address; - dev->watchdog_timeo = 3*HZ; + dev->watchdog_timeo = 3 * HZ; dev->irq = 0; dev->base_addr = (unsigned long)base_addr; @@ -6364,22 +6358,19 @@ static struct net_device *ipw2100_alloc_device( * ends up causing problems. So, we just handle * the WX extensions through the ipw2100_ioctl interface */ - /* memset() puts everything to 0, so we only have explicitely set * those values that need to be something else */ /* If power management is turned on, default to AUTO mode */ priv->power_mode = IPW_POWER_AUTO; - - #ifdef CONFIG_IEEE80211_WPA priv->ieee->wpa_enabled = 0; priv->ieee->tkip_countermeasures = 0; priv->ieee->drop_unencrypted = 0; priv->ieee->privacy_invoked = 0; priv->ieee->ieee802_1x = 1; -#endif /* CONFIG_IEEE80211_WPA */ +#endif /* CONFIG_IEEE80211_WPA */ /* Set module parameters */ switch (mode) { @@ -6401,8 +6392,7 @@ static struct net_device *ipw2100_alloc_device( priv->status |= STATUS_RF_KILL_SW; if (channel != 0 && - ((channel >= REG_MIN_CHANNEL) && - (channel <= REG_MAX_CHANNEL))) { + ((channel >= REG_MIN_CHANNEL) && (channel <= REG_MAX_CHANNEL))) { priv->config |= CFG_STATIC_CHANNEL; priv->channel = channel; } @@ -6441,7 +6431,6 @@ static struct net_device *ipw2100_alloc_device( INIT_LIST_HEAD(&priv->fw_pend_list); INIT_STAT(&priv->fw_pend_stat); - #ifdef CONFIG_SOFTWARE_SUSPEND2 priv->workqueue = create_workqueue(DRV_NAME, 0); #else @@ -6535,7 +6524,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, return err; } - /* We disable the RETRY_TIMEOUT register (0x41) to keep + /* We disable the RETRY_TIMEOUT register (0x41) to keep * PCI Tx retries from interfering with C3 CPU state */ pci_read_config_dword(pci_dev, 0x40, &val); if ((val & 0x0000ff00) != 0) @@ -6566,12 +6555,10 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, ipw2100_queues_initialize(priv); err = request_irq(pci_dev->irq, - ipw2100_interrupt, SA_SHIRQ, - dev->name, priv); + ipw2100_interrupt, SA_SHIRQ, dev->name, priv); if (err) { printk(KERN_WARNING DRV_NAME - "Error calling request_irq: %d.\n", - pci_dev->irq); + "Error calling request_irq: %d.\n", pci_dev->irq); goto fail; } dev->irq = pci_dev->irq; @@ -6634,10 +6621,10 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, return 0; - fail_unlock: + fail_unlock: up(&priv->action_sem); - fail: + fail: if (dev) { if (registered) unregister_netdev(dev); @@ -6653,7 +6640,8 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, /* These are safe to call even if they weren't allocated */ ipw2100_queues_free(priv); - sysfs_remove_group(&pci_dev->dev.kobj, &ipw2100_attribute_group); + sysfs_remove_group(&pci_dev->dev.kobj, + &ipw2100_attribute_group); free_ieee80211(dev); pci_set_drvdata(pci_dev, NULL); @@ -6679,7 +6667,8 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev) priv->status &= ~STATUS_INITIALIZED; dev = priv->net_dev; - sysfs_remove_group(&pci_dev->dev.kobj, &ipw2100_attribute_group); + sysfs_remove_group(&pci_dev->dev.kobj, + &ipw2100_attribute_group); #ifdef CONFIG_PM if (ipw2100_firmware.version) @@ -6721,7 +6710,6 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev) IPW_DEBUG_INFO("exit\n"); } - #ifdef CONFIG_PM #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) static int ipw2100_suspend(struct pci_dev *pci_dev, u32 state) @@ -6732,8 +6720,7 @@ static int ipw2100_suspend(struct pci_dev *pci_dev, pm_message_t state) struct ipw2100_priv *priv = pci_get_drvdata(pci_dev); struct net_device *dev = priv->net_dev; - IPW_DEBUG_INFO("%s: Going into suspend...\n", - dev->name); + IPW_DEBUG_INFO("%s: Going into suspend...\n", dev->name); down(&priv->action_sem); if (priv->status & STATUS_INITIALIZED) { @@ -6745,7 +6732,7 @@ static int ipw2100_suspend(struct pci_dev *pci_dev, pm_message_t state) netif_device_detach(dev); pci_save_state(pci_dev); - pci_disable_device (pci_dev); + pci_disable_device(pci_dev); pci_set_power_state(pci_dev, PCI_D3hot); up(&priv->action_sem); @@ -6764,8 +6751,7 @@ static int ipw2100_resume(struct pci_dev *pci_dev) down(&priv->action_sem); - IPW_DEBUG_INFO("%s: Coming out of suspend...\n", - dev->name); + IPW_DEBUG_INFO("%s: Coming out of suspend...\n", dev->name); pci_set_power_state(pci_dev, PCI_D0); pci_enable_device(pci_dev); @@ -6785,9 +6771,9 @@ static int ipw2100_resume(struct pci_dev *pci_dev) * the queue of needed */ netif_device_attach(dev); - /* Bring the device back up */ - if (!(priv->status & STATUS_RF_KILL_SW)) - ipw2100_up(priv, 0); + /* Bring the device back up */ + if (!(priv->status & STATUS_RF_KILL_SW)) + ipw2100_up(priv, 0); up(&priv->action_sem); @@ -6795,56 +6781,55 @@ static int ipw2100_resume(struct pci_dev *pci_dev) } #endif - #define IPW2100_DEV_ID(x) { PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, x } static struct pci_device_id ipw2100_pci_id_table[] __devinitdata = { - IPW2100_DEV_ID(0x2520), /* IN 2100A mPCI 3A */ - IPW2100_DEV_ID(0x2521), /* IN 2100A mPCI 3B */ - IPW2100_DEV_ID(0x2524), /* IN 2100A mPCI 3B */ - IPW2100_DEV_ID(0x2525), /* IN 2100A mPCI 3B */ - IPW2100_DEV_ID(0x2526), /* IN 2100A mPCI Gen A3 */ - IPW2100_DEV_ID(0x2522), /* IN 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2523), /* IN 2100 mPCI 3A */ - IPW2100_DEV_ID(0x2527), /* IN 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2528), /* IN 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2529), /* IN 2100 mPCI 3B */ - IPW2100_DEV_ID(0x252B), /* IN 2100 mPCI 3A */ - IPW2100_DEV_ID(0x252C), /* IN 2100 mPCI 3A */ - IPW2100_DEV_ID(0x252D), /* IN 2100 mPCI 3A */ - - IPW2100_DEV_ID(0x2550), /* IB 2100A mPCI 3B */ - IPW2100_DEV_ID(0x2551), /* IB 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2553), /* IB 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2554), /* IB 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2555), /* IB 2100 mPCI 3B */ - - IPW2100_DEV_ID(0x2560), /* DE 2100A mPCI 3A */ - IPW2100_DEV_ID(0x2562), /* DE 2100A mPCI 3A */ - IPW2100_DEV_ID(0x2563), /* DE 2100A mPCI 3A */ - IPW2100_DEV_ID(0x2561), /* DE 2100 mPCI 3A */ - IPW2100_DEV_ID(0x2565), /* DE 2100 mPCI 3A */ - IPW2100_DEV_ID(0x2566), /* DE 2100 mPCI 3A */ - IPW2100_DEV_ID(0x2567), /* DE 2100 mPCI 3A */ - - IPW2100_DEV_ID(0x2570), /* GA 2100 mPCI 3B */ - - IPW2100_DEV_ID(0x2580), /* TO 2100A mPCI 3B */ - IPW2100_DEV_ID(0x2582), /* TO 2100A mPCI 3B */ - IPW2100_DEV_ID(0x2583), /* TO 2100A mPCI 3B */ - IPW2100_DEV_ID(0x2581), /* TO 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2585), /* TO 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2586), /* TO 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2587), /* TO 2100 mPCI 3B */ - - IPW2100_DEV_ID(0x2590), /* SO 2100A mPCI 3B */ - IPW2100_DEV_ID(0x2592), /* SO 2100A mPCI 3B */ - IPW2100_DEV_ID(0x2591), /* SO 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2593), /* SO 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2596), /* SO 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2598), /* SO 2100 mPCI 3B */ - - IPW2100_DEV_ID(0x25A0), /* HP 2100 mPCI 3B */ + IPW2100_DEV_ID(0x2520), /* IN 2100A mPCI 3A */ + IPW2100_DEV_ID(0x2521), /* IN 2100A mPCI 3B */ + IPW2100_DEV_ID(0x2524), /* IN 2100A mPCI 3B */ + IPW2100_DEV_ID(0x2525), /* IN 2100A mPCI 3B */ + IPW2100_DEV_ID(0x2526), /* IN 2100A mPCI Gen A3 */ + IPW2100_DEV_ID(0x2522), /* IN 2100 mPCI 3B */ + IPW2100_DEV_ID(0x2523), /* IN 2100 mPCI 3A */ + IPW2100_DEV_ID(0x2527), /* IN 2100 mPCI 3B */ + IPW2100_DEV_ID(0x2528), /* IN 2100 mPCI 3B */ + IPW2100_DEV_ID(0x2529), /* IN 2100 mPCI 3B */ + IPW2100_DEV_ID(0x252B), /* IN 2100 mPCI 3A */ + IPW2100_DEV_ID(0x252C), /* IN 2100 mPCI 3A */ + IPW2100_DEV_ID(0x252D), /* IN 2100 mPCI 3A */ + + IPW2100_DEV_ID(0x2550), /* IB 2100A mPCI 3B */ + IPW2100_DEV_ID(0x2551), /* IB 2100 mPCI 3B */ + IPW2100_DEV_ID(0x2553), /* IB 2100 mPCI 3B */ + IPW2100_DEV_ID(0x2554), /* IB 2100 mPCI 3B */ + IPW2100_DEV_ID(0x2555), /* IB 2100 mPCI 3B */ + + IPW2100_DEV_ID(0x2560), /* DE 2100A mPCI 3A */ + IPW2100_DEV_ID(0x2562), /* DE 2100A mPCI 3A */ + IPW2100_DEV_ID(0x2563), /* DE 2100A mPCI 3A */ + IPW2100_DEV_ID(0x2561), /* DE 2100 mPCI 3A */ + IPW2100_DEV_ID(0x2565), /* DE 2100 mPCI 3A */ + IPW2100_DEV_ID(0x2566), /* DE 2100 mPCI 3A */ + IPW2100_DEV_ID(0x2567), /* DE 2100 mPCI 3A */ + + IPW2100_DEV_ID(0x2570), /* GA 2100 mPCI 3B */ + + IPW2100_DEV_ID(0x2580), /* TO 2100A mPCI 3B */ + IPW2100_DEV_ID(0x2582), /* TO 2100A mPCI 3B */ + IPW2100_DEV_ID(0x2583), /* TO 2100A mPCI 3B */ + IPW2100_DEV_ID(0x2581), /* TO 2100 mPCI 3B */ + IPW2100_DEV_ID(0x2585), /* TO 2100 mPCI 3B */ + IPW2100_DEV_ID(0x2586), /* TO 2100 mPCI 3B */ + IPW2100_DEV_ID(0x2587), /* TO 2100 mPCI 3B */ + + IPW2100_DEV_ID(0x2590), /* SO 2100A mPCI 3B */ + IPW2100_DEV_ID(0x2592), /* SO 2100A mPCI 3B */ + IPW2100_DEV_ID(0x2591), /* SO 2100 mPCI 3B */ + IPW2100_DEV_ID(0x2593), /* SO 2100 mPCI 3B */ + IPW2100_DEV_ID(0x2596), /* SO 2100 mPCI 3B */ + IPW2100_DEV_ID(0x2598), /* SO 2100 mPCI 3B */ + + IPW2100_DEV_ID(0x25A0), /* HP 2100 mPCI 3B */ {0,}, }; @@ -6861,7 +6846,6 @@ static struct pci_driver ipw2100_pci_driver = { #endif }; - /** * Initialize the ipw2100 driver/module * @@ -6893,7 +6877,6 @@ static int __init ipw2100_init(void) return ret; } - /** * Cleanup ipw2100 driver registration */ @@ -6949,7 +6932,6 @@ static int ipw2100_wx_get_name(struct net_device *dev, return 0; } - static int ipw2100_wx_set_freq(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -6969,8 +6951,7 @@ static int ipw2100_wx_set_freq(struct net_device *dev, /* if setting by freq convert to channel */ if (fwrq->e == 1) { - if ((fwrq->m >= (int) 2.412e8 && - fwrq->m <= (int) 2.487e8)) { + if ((fwrq->m >= (int)2.412e8 && fwrq->m <= (int)2.487e8)) { int f = fwrq->m / 100000; int c = 0; @@ -6986,17 +6967,16 @@ static int ipw2100_wx_set_freq(struct net_device *dev, if (fwrq->e > 0 || fwrq->m > 1000) return -EOPNOTSUPP; - else { /* Set the channel */ + else { /* Set the channel */ IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m); err = ipw2100_set_channel(priv, fwrq->m, 0); } - done: + done: up(&priv->action_sem); return err; } - static int ipw2100_wx_get_freq(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -7045,7 +7025,7 @@ static int ipw2100_wx_set_mode(struct net_device *dev, case IW_MODE_MONITOR: err = ipw2100_switch_mode(priv, IW_MODE_MONITOR); break; -#endif /* CONFIG_IPW2100_MONITOR */ +#endif /* CONFIG_IPW2100_MONITOR */ case IW_MODE_ADHOC: err = ipw2100_switch_mode(priv, IW_MODE_ADHOC); break; @@ -7056,9 +7036,9 @@ static int ipw2100_wx_set_mode(struct net_device *dev, break; } -done: + done: up(&priv->action_sem); - return err; + return err; } static int ipw2100_wx_get_mode(struct net_device *dev, @@ -7077,7 +7057,6 @@ static int ipw2100_wx_get_mode(struct net_device *dev, return 0; } - #define POWER_MODES 5 /* Values are in microsecond */ @@ -7124,19 +7103,19 @@ static int ipw2100_wx_get_range(struct net_device *dev, /* ~5 Mb/s real (802.11b) */ range->throughput = 5 * 1000 * 1000; -// range->sensitivity; /* signal level threshold range */ +// range->sensitivity; /* signal level threshold range */ range->max_qual.qual = 100; /* TODO: Find real max RSSI and stick here */ range->max_qual.level = 0; range->max_qual.noise = 0; - range->max_qual.updated = 7; /* Updated all three */ + range->max_qual.updated = 7; /* Updated all three */ - range->avg_qual.qual = 70; /* > 8% missed beacons is 'bad' */ + range->avg_qual.qual = 70; /* > 8% missed beacons is 'bad' */ /* TODO: Find real 'good' to 'bad' threshol value for RSSI */ range->avg_qual.level = 20 + IPW2100_RSSI_TO_DBM; range->avg_qual.noise = 0; - range->avg_qual.updated = 7; /* Updated all three */ + range->avg_qual.updated = 7; /* Updated all three */ range->num_bitrates = RATE_COUNT; @@ -7150,61 +7129,62 @@ static int ipw2100_wx_get_range(struct net_device *dev, range->max_frag = MAX_FRAG_THRESHOLD; range->min_pmp = period_duration[0]; /* Minimal PM period */ - range->max_pmp = period_duration[POWER_MODES-1];/* Maximal PM period */ - range->min_pmt = timeout_duration[POWER_MODES-1]; /* Minimal PM timeout */ - range->max_pmt = timeout_duration[0];/* Maximal PM timeout */ + range->max_pmp = period_duration[POWER_MODES - 1]; /* Maximal PM period */ + range->min_pmt = timeout_duration[POWER_MODES - 1]; /* Minimal PM timeout */ + range->max_pmt = timeout_duration[0]; /* Maximal PM timeout */ - /* How to decode max/min PM period */ + /* How to decode max/min PM period */ range->pmp_flags = IW_POWER_PERIOD; - /* How to decode max/min PM period */ + /* How to decode max/min PM period */ range->pmt_flags = IW_POWER_TIMEOUT; /* What PM options are supported */ range->pm_capa = IW_POWER_TIMEOUT | IW_POWER_PERIOD; range->encoding_size[0] = 5; - range->encoding_size[1] = 13; /* Different token sizes */ - range->num_encoding_sizes = 2; /* Number of entry in the list */ - range->max_encoding_tokens = WEP_KEYS; /* Max number of tokens */ -// range->encoding_login_index; /* token index for login token */ + range->encoding_size[1] = 13; /* Different token sizes */ + range->num_encoding_sizes = 2; /* Number of entry in the list */ + range->max_encoding_tokens = WEP_KEYS; /* Max number of tokens */ +// range->encoding_login_index; /* token index for login token */ if (priv->ieee->iw_mode == IW_MODE_ADHOC) { range->txpower_capa = IW_TXPOW_DBM; range->num_txpower = IW_MAX_TXPOWER; - for (i = 0, level = (IPW_TX_POWER_MAX_DBM * 16); i < IW_MAX_TXPOWER; - i++, level -= ((IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM) * 16) / - (IW_MAX_TXPOWER - 1)) + for (i = 0, level = (IPW_TX_POWER_MAX_DBM * 16); + i < IW_MAX_TXPOWER; + i++, level -= + ((IPW_TX_POWER_MAX_DBM - + IPW_TX_POWER_MIN_DBM) * 16) / (IW_MAX_TXPOWER - 1)) range->txpower[i] = level / 16; } else { range->txpower_capa = 0; range->num_txpower = 0; } - /* Set the Wireless Extension versions */ range->we_version_compiled = WIRELESS_EXT; range->we_version_source = 16; -// range->retry_capa; /* What retry options are supported */ -// range->retry_flags; /* How to decode max/min retry limit */ -// range->r_time_flags; /* How to decode max/min retry life */ -// range->min_retry; /* Minimal number of retries */ -// range->max_retry; /* Maximal number of retries */ -// range->min_r_time; /* Minimal retry lifetime */ -// range->max_r_time; /* Maximal retry lifetime */ +// range->retry_capa; /* What retry options are supported */ +// range->retry_flags; /* How to decode max/min retry limit */ +// range->r_time_flags; /* How to decode max/min retry life */ +// range->min_retry; /* Minimal number of retries */ +// range->max_retry; /* Maximal number of retries */ +// range->min_r_time; /* Minimal retry lifetime */ +// range->max_r_time; /* Maximal retry lifetime */ - range->num_channels = FREQ_COUNT; + range->num_channels = FREQ_COUNT; val = 0; for (i = 0; i < FREQ_COUNT; i++) { // TODO: Include only legal frequencies for some countries -// if (local->channel_mask & (1 << i)) { - range->freq[val].i = i + 1; - range->freq[val].m = ipw2100_frequencies[i] * 100000; - range->freq[val].e = 1; - val++; -// } +// if (local->channel_mask & (1 << i)) { + range->freq[val].i = i + 1; + range->freq[val].m = ipw2100_frequencies[i] * 100000; + range->freq[val].e = 1; + val++; +// } if (val == IW_MAX_FREQUENCIES) - break; + break; } range->num_frequency = val; @@ -7259,7 +7239,7 @@ static int ipw2100_wx_set_wap(struct net_device *dev, wrqu->ap_addr.sa_data[4] & 0xff, wrqu->ap_addr.sa_data[5] & 0xff); - done: + done: up(&priv->action_sem); return err; } @@ -7276,8 +7256,7 @@ static int ipw2100_wx_get_wap(struct net_device *dev, /* If we are associated, trying to associate, or have a statically * configured BSSID then return that; otherwise return ANY */ - if (priv->config & CFG_STATIC_BSSID || - priv->status & STATUS_ASSOCIATED) { + if (priv->config & CFG_STATIC_BSSID || priv->status & STATUS_ASSOCIATED) { wrqu->ap_addr.sa_family = ARPHRD_ETHER; memcpy(wrqu->ap_addr.sa_data, &priv->bssid, ETH_ALEN); } else @@ -7293,7 +7272,7 @@ static int ipw2100_wx_set_essid(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw2100_priv *priv = ieee80211_priv(dev); - char *essid = ""; /* ANY */ + char *essid = ""; /* ANY */ int length = 0; int err = 0; @@ -7333,7 +7312,7 @@ static int ipw2100_wx_set_essid(struct net_device *dev, err = ipw2100_set_essid(priv, essid, length, 0); - done: + done: up(&priv->action_sem); return err; } @@ -7350,17 +7329,16 @@ static int ipw2100_wx_get_essid(struct net_device *dev, /* If we are associated, trying to associate, or have a statically * configured ESSID then return that; otherwise return ANY */ - if (priv->config & CFG_STATIC_ESSID || - priv->status & STATUS_ASSOCIATED) { + if (priv->config & CFG_STATIC_ESSID || priv->status & STATUS_ASSOCIATED) { IPW_DEBUG_WX("Getting essid: '%s'\n", escape_essid(priv->essid, priv->essid_len)); memcpy(extra, priv->essid, priv->essid_len); wrqu->essid.length = priv->essid_len; - wrqu->essid.flags = 1; /* active */ + wrqu->essid.flags = 1; /* active */ } else { IPW_DEBUG_WX("Getting essid: ANY\n"); wrqu->essid.length = 0; - wrqu->essid.flags = 0; /* active */ + wrqu->essid.flags = 0; /* active */ } return 0; @@ -7379,9 +7357,9 @@ static int ipw2100_wx_set_nick(struct net_device *dev, if (wrqu->data.length > IW_ESSID_MAX_SIZE) return -E2BIG; - wrqu->data.length = min((size_t)wrqu->data.length, sizeof(priv->nick)); + wrqu->data.length = min((size_t) wrqu->data.length, sizeof(priv->nick)); memset(priv->nick, 0, sizeof(priv->nick)); - memcpy(priv->nick, extra, wrqu->data.length); + memcpy(priv->nick, extra, wrqu->data.length); IPW_DEBUG_WX("SET Nickname -> %s \n", priv->nick); @@ -7400,7 +7378,7 @@ static int ipw2100_wx_get_nick(struct net_device *dev, wrqu->data.length = strlen(priv->nick) + 1; memcpy(extra, priv->nick, wrqu->data.length); - wrqu->data.flags = 1; /* active */ + wrqu->data.flags = 1; /* active */ IPW_DEBUG_WX("GET Nickname -> %s \n", extra); @@ -7442,12 +7420,11 @@ static int ipw2100_wx_set_rate(struct net_device *dev, err = ipw2100_set_tx_rates(priv, rate, 0); IPW_DEBUG_WX("SET Rate -> %04X \n", rate); - done: + done: up(&priv->action_sem); return err; } - static int ipw2100_wx_get_rate(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -7495,7 +7472,7 @@ static int ipw2100_wx_get_rate(struct net_device *dev, IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value); - done: + done: up(&priv->action_sem); return err; } @@ -7520,8 +7497,7 @@ static int ipw2100_wx_set_rts(struct net_device *dev, if (wrqu->rts.disabled) value = priv->rts_threshold | RTS_DISABLED; else { - if (wrqu->rts.value < 1 || - wrqu->rts.value > 2304) { + if (wrqu->rts.value < 1 || wrqu->rts.value > 2304) { err = -EINVAL; goto done; } @@ -7531,7 +7507,7 @@ static int ipw2100_wx_set_rts(struct net_device *dev, err = ipw2100_set_rts_threshold(priv, value); IPW_DEBUG_WX("SET RTS Threshold -> 0x%08X \n", value); - done: + done: up(&priv->action_sem); return err; } @@ -7547,7 +7523,7 @@ static int ipw2100_wx_get_rts(struct net_device *dev, struct ipw2100_priv *priv = ieee80211_priv(dev); wrqu->rts.value = priv->rts_threshold & ~RTS_DISABLED; - wrqu->rts.fixed = 1; /* no auto select */ + wrqu->rts.fixed = 1; /* no auto select */ /* If RTS is set to the default value, then it is disabled */ wrqu->rts.disabled = (priv->rts_threshold & RTS_DISABLED) ? 1 : 0; @@ -7575,7 +7551,7 @@ static int ipw2100_wx_set_txpow(struct net_device *dev, return -EINVAL; value = (wrqu->txpower.value - IPW_TX_POWER_MIN_DBM) * 16 / - (IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM); + (IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM); } down(&priv->action_sem); @@ -7588,7 +7564,7 @@ static int ipw2100_wx_set_txpow(struct net_device *dev, IPW_DEBUG_WX("SET TX Power -> %d \n", value); - done: + done: up(&priv->action_sem); return err; } @@ -7616,10 +7592,10 @@ static int ipw2100_wx_get_txpow(struct net_device *dev, wrqu->power.disabled = 0; wrqu->power.fixed = 1; wrqu->power.value = - (priv->tx_power * - (IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM)) / - (IPW_TX_POWER_MAX - IPW_TX_POWER_MIN) + - IPW_TX_POWER_MIN_DBM; + (priv->tx_power * + (IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM)) / + (IPW_TX_POWER_MAX - IPW_TX_POWER_MIN) + + IPW_TX_POWER_MIN_DBM; } wrqu->power.flags = IW_TXPOW_DBM; @@ -7684,8 +7660,7 @@ static int ipw2100_wx_set_retry(struct net_device *dev, struct ipw2100_priv *priv = ieee80211_priv(dev); int err = 0; - if (wrqu->retry.flags & IW_RETRY_LIFETIME || - wrqu->retry.disabled) + if (wrqu->retry.flags & IW_RETRY_LIFETIME || wrqu->retry.disabled) return -EINVAL; if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) @@ -7700,14 +7675,14 @@ static int ipw2100_wx_set_retry(struct net_device *dev, if (wrqu->retry.flags & IW_RETRY_MIN) { err = ipw2100_set_short_retry(priv, wrqu->retry.value); IPW_DEBUG_WX("SET Short Retry Limit -> %d \n", - wrqu->retry.value); + wrqu->retry.value); goto done; } if (wrqu->retry.flags & IW_RETRY_MAX) { err = ipw2100_set_long_retry(priv, wrqu->retry.value); IPW_DEBUG_WX("SET Long Retry Limit -> %d \n", - wrqu->retry.value); + wrqu->retry.value); goto done; } @@ -7717,7 +7692,7 @@ static int ipw2100_wx_set_retry(struct net_device *dev, IPW_DEBUG_WX("SET Both Retry Limits -> %d \n", wrqu->retry.value); - done: + done: up(&priv->action_sem); return err; } @@ -7732,10 +7707,9 @@ static int ipw2100_wx_get_retry(struct net_device *dev, struct ipw2100_priv *priv = ieee80211_priv(dev); - wrqu->retry.disabled = 0; /* can't be disabled */ + wrqu->retry.disabled = 0; /* can't be disabled */ - if ((wrqu->retry.flags & IW_RETRY_TYPE) == - IW_RETRY_LIFETIME) + if ((wrqu->retry.flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) return -EINVAL; if (wrqu->retry.flags & IW_RETRY_MAX) { @@ -7769,15 +7743,14 @@ static int ipw2100_wx_set_scan(struct net_device *dev, } IPW_DEBUG_WX("Initiating scan...\n"); - if (ipw2100_set_scan_options(priv) || - ipw2100_start_scan(priv)) { + if (ipw2100_set_scan_options(priv) || ipw2100_start_scan(priv)) { IPW_DEBUG_WX("Start scan failed.\n"); /* TODO: Mark a scan as pending so when hardware initialized * a scan starts */ } - done: + done: up(&priv->action_sem); return err; } @@ -7794,7 +7767,6 @@ static int ipw2100_wx_get_scan(struct net_device *dev, return ieee80211_wx_get_scan(priv->ieee, info, wrqu, extra); } - /* * Implementation based on code in hostap-driver v0.1.3 hostap_ioctl.c */ @@ -7823,8 +7795,8 @@ static int ipw2100_wx_get_encode(struct net_device *dev, } static int ipw2100_wx_set_power(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { struct ipw2100_priv *priv = ieee80211_priv(dev); int err = 0; @@ -7843,11 +7815,11 @@ static int ipw2100_wx_set_power(struct net_device *dev, } switch (wrqu->power.flags & IW_POWER_MODE) { - case IW_POWER_ON: /* If not specified */ - case IW_POWER_MODE: /* If set all mask */ - case IW_POWER_ALL_R: /* If explicitely state all */ + case IW_POWER_ON: /* If not specified */ + case IW_POWER_MODE: /* If set all mask */ + case IW_POWER_ALL_R: /* If explicitely state all */ break; - default: /* Otherwise we don't support it */ + default: /* Otherwise we don't support it */ IPW_DEBUG_WX("SET PM Mode: %X not supported.\n", wrqu->power.flags); err = -EOPNOTSUPP; @@ -7859,18 +7831,17 @@ static int ipw2100_wx_set_power(struct net_device *dev, priv->power_mode = IPW_POWER_ENABLED | priv->power_mode; err = ipw2100_set_power_mode(priv, IPW_POWER_LEVEL(priv->power_mode)); - IPW_DEBUG_WX("SET Power Management Mode -> 0x%02X\n", - priv->power_mode); + IPW_DEBUG_WX("SET Power Management Mode -> 0x%02X\n", priv->power_mode); - done: + done: up(&priv->action_sem); return err; } static int ipw2100_wx_get_power(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { /* * This can be called at any time. No action lock required @@ -7890,7 +7861,6 @@ static int ipw2100_wx_get_power(struct net_device *dev, return 0; } - /* * * IWPRIV handlers @@ -7923,7 +7893,7 @@ static int ipw2100_wx_set_promisc(struct net_device *dev, if (priv->ieee->iw_mode == IW_MODE_MONITOR) err = ipw2100_switch_mode(priv, priv->last_mode); } - done: + done: up(&priv->action_sem); return err; } @@ -7958,7 +7928,7 @@ static int ipw2100_wx_set_powermode(struct net_device *dev, if (priv->power_mode != mode) err = ipw2100_set_power_mode(priv, mode); - done: + done: up(&priv->action_sem); return err; } @@ -7986,8 +7956,8 @@ static int ipw2100_wx_get_powermode(struct net_device *dev, "Power save level: %d (None)", level); break; case IPW_POWER_AUTO: - snprintf(extra, MAX_POWER_STRING, - "Power save level: %d (Auto)", 0); + snprintf(extra, MAX_POWER_STRING, + "Power save level: %d (Auto)", 0); break; default: timeout = timeout_duration[level - 1] / 1000; @@ -8004,7 +7974,6 @@ static int ipw2100_wx_get_powermode(struct net_device *dev, return 0; } - static int ipw2100_wx_set_preamble(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -8029,14 +7998,14 @@ static int ipw2100_wx_set_preamble(struct net_device *dev, err = ipw2100_system_config(priv, 0); -done: + done: up(&priv->action_sem); return err; } static int ipw2100_wx_get_preamble(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { /* * This can be called at any time. No action lock required @@ -8052,54 +8021,53 @@ static int ipw2100_wx_get_preamble(struct net_device *dev, return 0; } -static iw_handler ipw2100_wx_handlers[] = -{ - NULL, /* SIOCSIWCOMMIT */ - ipw2100_wx_get_name, /* SIOCGIWNAME */ - NULL, /* SIOCSIWNWID */ - NULL, /* SIOCGIWNWID */ - ipw2100_wx_set_freq, /* SIOCSIWFREQ */ - ipw2100_wx_get_freq, /* SIOCGIWFREQ */ - ipw2100_wx_set_mode, /* SIOCSIWMODE */ - ipw2100_wx_get_mode, /* SIOCGIWMODE */ - NULL, /* SIOCSIWSENS */ - NULL, /* SIOCGIWSENS */ - NULL, /* SIOCSIWRANGE */ - ipw2100_wx_get_range, /* SIOCGIWRANGE */ - NULL, /* SIOCSIWPRIV */ - NULL, /* SIOCGIWPRIV */ - NULL, /* SIOCSIWSTATS */ - NULL, /* SIOCGIWSTATS */ - NULL, /* SIOCSIWSPY */ - NULL, /* SIOCGIWSPY */ - NULL, /* SIOCGIWTHRSPY */ - NULL, /* SIOCWIWTHRSPY */ - ipw2100_wx_set_wap, /* SIOCSIWAP */ - ipw2100_wx_get_wap, /* SIOCGIWAP */ - NULL, /* -- hole -- */ - NULL, /* SIOCGIWAPLIST -- deprecated */ - ipw2100_wx_set_scan, /* SIOCSIWSCAN */ - ipw2100_wx_get_scan, /* SIOCGIWSCAN */ - ipw2100_wx_set_essid, /* SIOCSIWESSID */ - ipw2100_wx_get_essid, /* SIOCGIWESSID */ - ipw2100_wx_set_nick, /* SIOCSIWNICKN */ - ipw2100_wx_get_nick, /* SIOCGIWNICKN */ - NULL, /* -- hole -- */ - NULL, /* -- hole -- */ - ipw2100_wx_set_rate, /* SIOCSIWRATE */ - ipw2100_wx_get_rate, /* SIOCGIWRATE */ - ipw2100_wx_set_rts, /* SIOCSIWRTS */ - ipw2100_wx_get_rts, /* SIOCGIWRTS */ - ipw2100_wx_set_frag, /* SIOCSIWFRAG */ - ipw2100_wx_get_frag, /* SIOCGIWFRAG */ - ipw2100_wx_set_txpow, /* SIOCSIWTXPOW */ - ipw2100_wx_get_txpow, /* SIOCGIWTXPOW */ - ipw2100_wx_set_retry, /* SIOCSIWRETRY */ - ipw2100_wx_get_retry, /* SIOCGIWRETRY */ - ipw2100_wx_set_encode, /* SIOCSIWENCODE */ - ipw2100_wx_get_encode, /* SIOCGIWENCODE */ - ipw2100_wx_set_power, /* SIOCSIWPOWER */ - ipw2100_wx_get_power, /* SIOCGIWPOWER */ +static iw_handler ipw2100_wx_handlers[] = { + NULL, /* SIOCSIWCOMMIT */ + ipw2100_wx_get_name, /* SIOCGIWNAME */ + NULL, /* SIOCSIWNWID */ + NULL, /* SIOCGIWNWID */ + ipw2100_wx_set_freq, /* SIOCSIWFREQ */ + ipw2100_wx_get_freq, /* SIOCGIWFREQ */ + ipw2100_wx_set_mode, /* SIOCSIWMODE */ + ipw2100_wx_get_mode, /* SIOCGIWMODE */ + NULL, /* SIOCSIWSENS */ + NULL, /* SIOCGIWSENS */ + NULL, /* SIOCSIWRANGE */ + ipw2100_wx_get_range, /* SIOCGIWRANGE */ + NULL, /* SIOCSIWPRIV */ + NULL, /* SIOCGIWPRIV */ + NULL, /* SIOCSIWSTATS */ + NULL, /* SIOCGIWSTATS */ + NULL, /* SIOCSIWSPY */ + NULL, /* SIOCGIWSPY */ + NULL, /* SIOCGIWTHRSPY */ + NULL, /* SIOCWIWTHRSPY */ + ipw2100_wx_set_wap, /* SIOCSIWAP */ + ipw2100_wx_get_wap, /* SIOCGIWAP */ + NULL, /* -- hole -- */ + NULL, /* SIOCGIWAPLIST -- deprecated */ + ipw2100_wx_set_scan, /* SIOCSIWSCAN */ + ipw2100_wx_get_scan, /* SIOCGIWSCAN */ + ipw2100_wx_set_essid, /* SIOCSIWESSID */ + ipw2100_wx_get_essid, /* SIOCGIWESSID */ + ipw2100_wx_set_nick, /* SIOCSIWNICKN */ + ipw2100_wx_get_nick, /* SIOCGIWNICKN */ + NULL, /* -- hole -- */ + NULL, /* -- hole -- */ + ipw2100_wx_set_rate, /* SIOCSIWRATE */ + ipw2100_wx_get_rate, /* SIOCGIWRATE */ + ipw2100_wx_set_rts, /* SIOCSIWRTS */ + ipw2100_wx_get_rts, /* SIOCGIWRTS */ + ipw2100_wx_set_frag, /* SIOCSIWFRAG */ + ipw2100_wx_get_frag, /* SIOCGIWFRAG */ + ipw2100_wx_set_txpow, /* SIOCSIWTXPOW */ + ipw2100_wx_get_txpow, /* SIOCGIWTXPOW */ + ipw2100_wx_set_retry, /* SIOCSIWRETRY */ + ipw2100_wx_get_retry, /* SIOCGIWRETRY */ + ipw2100_wx_set_encode, /* SIOCSIWENCODE */ + ipw2100_wx_get_encode, /* SIOCGIWENCODE */ + ipw2100_wx_set_power, /* SIOCSIWPOWER */ + ipw2100_wx_get_power, /* SIOCGIWPOWER */ }; #define IPW2100_PRIV_SET_MONITOR SIOCIWFIRSTPRIV @@ -8113,55 +8081,49 @@ static const struct iw_priv_args ipw2100_private_args[] = { #ifdef CONFIG_IPW2100_MONITOR { - IPW2100_PRIV_SET_MONITOR, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "monitor" - }, + IPW2100_PRIV_SET_MONITOR, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "monitor"}, { - IPW2100_PRIV_RESET, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 0, 0, "reset" - }, -#endif /* CONFIG_IPW2100_MONITOR */ + IPW2100_PRIV_RESET, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 0, 0, "reset"}, +#endif /* CONFIG_IPW2100_MONITOR */ { - IPW2100_PRIV_SET_POWER, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_power" - }, + IPW2100_PRIV_SET_POWER, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_power"}, { - IPW2100_PRIV_GET_POWER, - 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_POWER_STRING, "get_power" - }, + IPW2100_PRIV_GET_POWER, + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_POWER_STRING, + "get_power"}, { - IPW2100_PRIV_SET_LONGPREAMBLE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_preamble" - }, + IPW2100_PRIV_SET_LONGPREAMBLE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_preamble"}, { - IPW2100_PRIV_GET_LONGPREAMBLE, - 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "get_preamble" - }, + IPW2100_PRIV_GET_LONGPREAMBLE, + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "get_preamble"}, }; static iw_handler ipw2100_private_handler[] = { #ifdef CONFIG_IPW2100_MONITOR ipw2100_wx_set_promisc, ipw2100_wx_reset, -#else /* CONFIG_IPW2100_MONITOR */ +#else /* CONFIG_IPW2100_MONITOR */ NULL, NULL, -#endif /* CONFIG_IPW2100_MONITOR */ +#endif /* CONFIG_IPW2100_MONITOR */ ipw2100_wx_set_powermode, ipw2100_wx_get_powermode, ipw2100_wx_set_preamble, ipw2100_wx_get_preamble, }; -static struct iw_handler_def ipw2100_wx_handler_def = -{ +static struct iw_handler_def ipw2100_wx_handler_def = { .standard = ipw2100_wx_handlers, .num_standard = sizeof(ipw2100_wx_handlers) / sizeof(iw_handler), .num_private = sizeof(ipw2100_private_handler) / sizeof(iw_handler), - .num_private_args = sizeof(ipw2100_private_args) / - sizeof(struct iw_priv_args), - .private = (iw_handler *)ipw2100_private_handler, + .num_private_args = sizeof(ipw2100_private_args) / + sizeof(struct iw_priv_args), + .private = (iw_handler *) ipw2100_private_handler, .private_args = (struct iw_priv_args *)ipw2100_private_args, }; @@ -8170,7 +8132,7 @@ static struct iw_handler_def ipw2100_wx_handler_def = * Called by /proc/net/wireless * Also called by SIOCGIWSTATS */ -static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device * dev) +static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device *dev) { enum { POOR = 30, @@ -8190,7 +8152,7 @@ static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device * dev) u32 ord_len = sizeof(u32); if (!priv) - return (struct iw_statistics *) NULL; + return (struct iw_statistics *)NULL; wstats = &priv->wstats; @@ -8207,7 +8169,7 @@ static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device * dev) wstats->qual.noise = 0; wstats->qual.updated = 7; wstats->qual.updated |= IW_QUAL_NOISE_INVALID | - IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID; + IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID; return wstats; } @@ -8215,7 +8177,7 @@ static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device * dev) &missed_beacons, &ord_len)) goto fail_get_ordinal; - /* If we don't have a connection the quality and level is 0*/ + /* If we don't have a connection the quality and level is 0 */ if (!(priv->status & STATUS_ASSOCIATED)) { wstats->qual.qual = 0; wstats->qual.level = 0; @@ -8232,10 +8194,10 @@ static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device * dev) rssi_qual = (rssi - 15) * (GOOD - FAIR) / 5 + FAIR; else if (rssi < 30) rssi_qual = (rssi - 20) * (VERY_GOOD - GOOD) / - 10 + GOOD; + 10 + GOOD; else rssi_qual = (rssi - 30) * (PERFECT - VERY_GOOD) / - 10 + VERY_GOOD; + 10 + VERY_GOOD; if (ipw2100_get_ordinal(priv, IPW_ORD_STAT_PERCENT_RETRIES, &tx_retries, &ord_len)) @@ -8249,25 +8211,25 @@ static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device * dev) tx_qual = (70 - tx_retries) * (GOOD - FAIR) / 5 + FAIR; else if (tx_retries > 50) tx_qual = (65 - tx_retries) * (VERY_GOOD - GOOD) / - 15 + GOOD; + 15 + GOOD; else tx_qual = (50 - tx_retries) * - (PERFECT - VERY_GOOD) / 50 + VERY_GOOD; + (PERFECT - VERY_GOOD) / 50 + VERY_GOOD; if (missed_beacons > 50) beacon_qual = (60 - missed_beacons) * POOR / 10; else if (missed_beacons > 40) beacon_qual = (50 - missed_beacons) * (FAIR - POOR) / - 10 + POOR; + 10 + POOR; else if (missed_beacons > 32) beacon_qual = (40 - missed_beacons) * (GOOD - FAIR) / - 18 + FAIR; + 18 + FAIR; else if (missed_beacons > 20) beacon_qual = (32 - missed_beacons) * - (VERY_GOOD - GOOD) / 20 + GOOD; + (VERY_GOOD - GOOD) / 20 + GOOD; else beacon_qual = (20 - missed_beacons) * - (PERFECT - VERY_GOOD) / 20 + VERY_GOOD; + (PERFECT - VERY_GOOD) / 20 + VERY_GOOD; quality = min(beacon_qual, min(tx_qual, rssi_qual)); @@ -8290,7 +8252,7 @@ static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device * dev) wstats->qual.updated = 7; wstats->qual.updated |= IW_QUAL_NOISE_INVALID; - /* FIXME: this is percent and not a # */ + /* FIXME: this is percent and not a # */ wstats->miss.beacon = missed_beacons; if (ipw2100_get_ordinal(priv, IPW_ORD_STAT_TX_FAILURES, @@ -8300,10 +8262,10 @@ static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device * dev) return wstats; - fail_get_ordinal: + fail_get_ordinal: IPW_DEBUG_WX("failed querying ordinals.\n"); - return (struct iw_statistics *) NULL; + return (struct iw_statistics *)NULL; } static void ipw2100_wx_event_work(struct ipw2100_priv *priv) @@ -8326,7 +8288,7 @@ static void ipw2100_wx_event_work(struct ipw2100_priv *priv) if (!(priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED)) || priv->status & STATUS_RF_KILL_MASK || ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID, - &priv->bssid, &len)) { + &priv->bssid, &len)) { memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); } else { /* We now have the BSSID, so can finish setting to the full @@ -8351,7 +8313,8 @@ static void ipw2100_wx_event_work(struct ipw2100_priv *priv) /* This is a disassociation event, so kick the firmware to * look for another AP */ if (priv->config & CFG_STATIC_ESSID) - ipw2100_set_essid(priv, priv->essid, priv->essid_len, 0); + ipw2100_set_essid(priv, priv->essid, priv->essid_len, + 0); else ipw2100_set_essid(priv, NULL, 0, 0); up(&priv->action_sem); @@ -8374,7 +8337,6 @@ static void ipw2100_wx_event_work(struct ipw2100_priv *priv) #define IPW2100_FW_NAME(x) IPW2100_FW_PREFIX "" x ".fw" - /* BINARY FIRMWARE HEADER FORMAT @@ -8396,12 +8358,10 @@ struct ipw2100_fw_header { unsigned int uc_size; } __attribute__ ((packed)); - - static int ipw2100_mod_firmware_load(struct ipw2100_fw *fw) { struct ipw2100_fw_header *h = - (struct ipw2100_fw_header *)fw->fw_entry->data; + (struct ipw2100_fw_header *)fw->fw_entry->data; if (IPW2100_FW_MAJOR(h->version) != IPW2100_FW_MAJOR_VERSION) { printk(KERN_WARNING DRV_NAME ": Firmware image not compatible " @@ -8420,7 +8380,6 @@ static int ipw2100_mod_firmware_load(struct ipw2100_fw *fw) return 0; } - static int ipw2100_get_firmware(struct ipw2100_priv *priv, struct ipw2100_fw *fw) { @@ -8428,7 +8387,7 @@ static int ipw2100_get_firmware(struct ipw2100_priv *priv, int rc; IPW_DEBUG_INFO("%s: Using hotplug firmware load.\n", - priv->net_dev->name); + priv->net_dev->name); switch (priv->ieee->iw_mode) { case IW_MODE_ADHOC: @@ -8454,7 +8413,7 @@ static int ipw2100_get_firmware(struct ipw2100_priv *priv, return rc; } IPW_DEBUG_INFO("firmware data %p size %zd\n", fw->fw_entry->data, - fw->fw_entry->size); + fw->fw_entry->size); ipw2100_mod_firmware_load(fw); @@ -8470,7 +8429,6 @@ static void ipw2100_release_firmware(struct ipw2100_priv *priv, fw->fw_entry = NULL; } - static int ipw2100_get_fwversion(struct ipw2100_priv *priv, char *buf, size_t max) { @@ -8479,8 +8437,7 @@ static int ipw2100_get_fwversion(struct ipw2100_priv *priv, char *buf, u32 tmp; int i; /* firmware version is an ascii string (max len of 14) */ - if (ipw2100_get_ordinal(priv, IPW_ORD_STAT_FW_VER_NUM, - ver, &len)) + if (ipw2100_get_ordinal(priv, IPW_ORD_STAT_FW_VER_NUM, ver, &len)) return -EIO; tmp = max; if (len >= max) @@ -8497,8 +8454,7 @@ static int ipw2100_get_ucodeversion(struct ipw2100_priv *priv, char *buf, u32 ver; u32 len = sizeof(ver); /* microcode version is a 32 bit integer */ - if (ipw2100_get_ordinal(priv, IPW_ORD_UCODE_VERSION, - &ver, &len)) + if (ipw2100_get_ordinal(priv, IPW_ORD_UCODE_VERSION, &ver, &len)) return -EIO; return snprintf(buf, max, "%08X", ver); } @@ -8506,8 +8462,7 @@ static int ipw2100_get_ucodeversion(struct ipw2100_priv *priv, char *buf, /* * On exit, the firmware will have been freed from the fw list */ -static int ipw2100_fw_download(struct ipw2100_priv *priv, - struct ipw2100_fw *fw) +static int ipw2100_fw_download(struct ipw2100_priv *priv, struct ipw2100_fw *fw) { /* firmware is constructed of N contiguous entries, each entry is * structured as: @@ -8515,7 +8470,7 @@ static int ipw2100_fw_download(struct ipw2100_priv *priv, * offset sie desc * 0 4 address to write to * 4 2 length of data run - * 6 length data + * 6 length data */ unsigned int addr; unsigned short len; @@ -8524,12 +8479,12 @@ static int ipw2100_fw_download(struct ipw2100_priv *priv, unsigned int firmware_data_left = fw->fw.size; while (firmware_data_left > 0) { - addr = *(u32 *)(firmware_data); - firmware_data += 4; + addr = *(u32 *) (firmware_data); + firmware_data += 4; firmware_data_left -= 4; - len = *(u16 *)(firmware_data); - firmware_data += 2; + len = *(u16 *) (firmware_data); + firmware_data += 2; firmware_data_left -= 2; if (len > 32) { @@ -8540,7 +8495,7 @@ static int ipw2100_fw_download(struct ipw2100_priv *priv, } write_nic_memory(priv->net_dev, addr, len, firmware_data); - firmware_data += len; + firmware_data += len; firmware_data_left -= len; } @@ -8654,21 +8609,19 @@ static int ipw2100_ucode_download(struct ipw2100_priv *priv, for (i = 0; i < 30; i++) { /* Read alive response structure */ for (j = 0; - j < (sizeof(struct symbol_alive_response) >> 1); - j++) - read_nic_word(dev, 0x210004, - ((u16 *)&response) + j); + j < (sizeof(struct symbol_alive_response) >> 1); j++) + read_nic_word(dev, 0x210004, ((u16 *) & response) + j); - if ((response.cmd_id == 1) && - (response.ucode_valid == 0x1)) + if ((response.cmd_id == 1) && (response.ucode_valid == 0x1)) break; udelay(10); } if (i == 30) { - printk(KERN_ERR DRV_NAME ": %s: No response from Symbol - hw not alive\n", + printk(KERN_ERR DRV_NAME + ": %s: No response from Symbol - hw not alive\n", dev->name); - printk_buf(IPW_DL_ERROR, (u8*)&response, sizeof(response)); + printk_buf(IPW_DL_ERROR, (u8 *) & response, sizeof(response)); return -EIO; } diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h index c9e99ce15d6..3eb5c384eaa 100644 --- a/drivers/net/wireless/ipw2100.h +++ b/drivers/net/wireless/ipw2100.h @@ -93,7 +93,6 @@ struct ipw2100_rx_packet; #define IPW_DL_IOCTL (1<<14) #define IPW_DL_RF_KILL (1<<17) - #define IPW_DL_MANAGE (1<<15) #define IPW_DL_FW (1<<16) @@ -156,7 +155,9 @@ extern const char *band_str[]; struct bd_status { union { - struct { u8 nlf:1, txType:2, intEnabled:1, reserved:4;} fields; + struct { + u8 nlf:1, txType:2, intEnabled:1, reserved:4; + } fields; u8 field; } info; } __attribute__ ((packed)); @@ -165,7 +166,7 @@ struct ipw2100_bd { u32 host_addr; u32 buf_length; struct bd_status status; - /* number of fragments for frame (should be set only for + /* number of fragments for frame (should be set only for * 1st TBD) */ u8 num_fragments; u8 reserved[6]; @@ -293,10 +294,10 @@ struct ipw2100_cmd_header { struct ipw2100_data_header { u32 host_command_reg; u32 host_command_reg1; - u8 encrypted; // BOOLEAN in win! TRUE if frame is enc by driver + u8 encrypted; // BOOLEAN in win! TRUE if frame is enc by driver u8 needs_encryption; // BOOLEAN in win! TRUE if frma need to be enc in NIC u8 wep_index; // 0 no key, 1-4 key index, 0xff immediate key - u8 key_size; // 0 no imm key, 0x5 64bit encr, 0xd 128bit encr, 0x10 128bit encr and 128bit IV + u8 key_size; // 0 no imm key, 0x5 64bit encr, 0xd 128bit encr, 0x10 128bit encr and 128bit IV u8 key[16]; u8 reserved[10]; // f/w reserved u8 src_addr[ETH_ALEN]; @@ -306,14 +307,13 @@ struct ipw2100_data_header { /* Host command data structure */ struct host_command { - u32 host_command; // COMMAND ID - u32 host_command1; // COMMAND ID + u32 host_command; // COMMAND ID + u32 host_command1; // COMMAND ID u32 host_command_sequence; // UNIQUE COMMAND NUMBER (ID) u32 host_command_length; // LENGTH u32 host_command_parameters[HOST_COMMAND_PARAMS_REG_LEN]; // COMMAND PARAMETERS } __attribute__ ((packed)); - typedef enum { POWER_ON_RESET, EXIT_POWER_DOWN_RESET, @@ -328,17 +328,16 @@ enum { RX }; - struct ipw2100_tx_packet { int type; int index; union { - struct { /* COMMAND */ - struct ipw2100_cmd_header* cmd; + struct { /* COMMAND */ + struct ipw2100_cmd_header *cmd; dma_addr_t cmd_phys; } c_struct; - struct { /* DATA */ - struct ipw2100_data_header* data; + struct { /* DATA */ + struct ipw2100_data_header *data; dma_addr_t data_phys; struct ieee80211_txb *txb; } d_struct; @@ -348,7 +347,6 @@ struct ipw2100_tx_packet { struct list_head list; }; - struct ipw2100_rx_packet { struct ipw2100_rx *rxp; dma_addr_t dma_addr; @@ -432,13 +430,13 @@ enum { }; #define STATUS_POWERED (1<<0) -#define STATUS_CMD_ACTIVE (1<<1) /**< host command in progress */ -#define STATUS_RUNNING (1<<2) /* Card initialized, but not enabled */ -#define STATUS_ENABLED (1<<3) /* Card enabled -- can scan,Tx,Rx */ -#define STATUS_STOPPING (1<<4) /* Card is in shutdown phase */ -#define STATUS_INITIALIZED (1<<5) /* Card is ready for external calls */ -#define STATUS_ASSOCIATING (1<<9) /* Associated, but no BSSID yet */ -#define STATUS_ASSOCIATED (1<<10) /* Associated and BSSID valid */ +#define STATUS_CMD_ACTIVE (1<<1) /**< host command in progress */ +#define STATUS_RUNNING (1<<2) /* Card initialized, but not enabled */ +#define STATUS_ENABLED (1<<3) /* Card enabled -- can scan,Tx,Rx */ +#define STATUS_STOPPING (1<<4) /* Card is in shutdown phase */ +#define STATUS_INITIALIZED (1<<5) /* Card is ready for external calls */ +#define STATUS_ASSOCIATING (1<<9) /* Associated, but no BSSID yet */ +#define STATUS_ASSOCIATED (1<<10) /* Associated and BSSID valid */ #define STATUS_INT_ENABLED (1<<11) #define STATUS_RF_KILL_HW (1<<12) #define STATUS_RF_KILL_SW (1<<13) @@ -451,9 +449,7 @@ enum { #define STATUS_SCAN_COMPLETE (1<<26) #define STATUS_WX_EVENT_PENDING (1<<27) #define STATUS_RESET_PENDING (1<<29) -#define STATUS_SECURITY_UPDATED (1<<30) /* Security sync needed */ - - +#define STATUS_SECURITY_UPDATED (1<<30) /* Security sync needed */ /* Internal NIC states */ #define IPW_STATE_INITIALIZED (1<<0) @@ -469,11 +465,9 @@ enum { #define IPW_STATE_POWER_DOWN (1<<10) #define IPW_STATE_SCANNING (1<<11) - - -#define CFG_STATIC_CHANNEL (1<<0) /* Restrict assoc. to single channel */ -#define CFG_STATIC_ESSID (1<<1) /* Restrict assoc. to single SSID */ -#define CFG_STATIC_BSSID (1<<2) /* Restrict assoc. to single BSSID */ +#define CFG_STATIC_CHANNEL (1<<0) /* Restrict assoc. to single channel */ +#define CFG_STATIC_ESSID (1<<1) /* Restrict assoc. to single SSID */ +#define CFG_STATIC_BSSID (1<<2) /* Restrict assoc. to single BSSID */ #define CFG_CUSTOM_MAC (1<<3) #define CFG_LONG_PREAMBLE (1<<4) #define CFG_ASSOCIATE (1<<6) @@ -482,13 +476,13 @@ enum { #define CFG_C3_DISABLED (1<<9) #define CFG_PASSIVE_SCAN (1<<10) -#define CAP_SHARED_KEY (1<<0) /* Off = OPEN */ -#define CAP_PRIVACY_ON (1<<1) /* Off = No privacy */ +#define CAP_SHARED_KEY (1<<0) /* Off = OPEN */ +#define CAP_PRIVACY_ON (1<<1) /* Off = No privacy */ struct ipw2100_priv { - int stop_hang_check; /* Set 1 when shutting down to kill hang_check */ - int stop_rf_kill; /* Set 1 when shutting down to kill rf_kill */ + int stop_hang_check; /* Set 1 when shutting down to kill hang_check */ + int stop_rf_kill; /* Set 1 when shutting down to kill rf_kill */ struct ieee80211_device *ieee; unsigned long status; @@ -519,8 +513,8 @@ struct ipw2100_priv { unsigned long hw_features; int hangs; u32 last_rtc; - int dump_raw; /* 1 to dump raw bytes in /sys/.../memory */ - u8* snapshot[0x30]; + int dump_raw; /* 1 to dump raw bytes in /sys/.../memory */ + u8 *snapshot[0x30]; u8 mandatory_bssid_mac[ETH_ALEN]; u8 mac_addr[ETH_ALEN]; @@ -531,7 +525,6 @@ struct ipw2100_priv { struct ieee80211_security sec; int messages_sent; - int short_retry_limit; int long_retry_limit; @@ -599,7 +592,6 @@ struct ipw2100_priv { wait_queue_head_t wait_command_queue; }; - /********************************************************* * Host Command -> From Driver to FW *********************************************************/ @@ -646,7 +638,6 @@ struct ipw2100_priv { #define CARD_DISABLE_PHY_OFF 61 #define MSDU_TX_RATES 62 - /* Rogue AP Detection */ #define SET_STATION_STAT_BITS 64 #define CLEAR_STATIONS_STAT_BITS 65 @@ -655,8 +646,6 @@ struct ipw2100_priv { #define DISASSOCIATION_BSSID 68 #define SET_WPA_IE 69 - - /* system configuration bit mask: */ #define IPW_CFG_MONITOR 0x00004 #define IPW_CFG_PREAMBLE_AUTO 0x00010 @@ -704,7 +693,7 @@ struct ipw2100_priv { #define IPW2100_INTA_TX_TRANSFER (0x00000001) // Bit 0 (LSB) #define IPW2100_INTA_RX_TRANSFER (0x00000002) // Bit 1 #define IPW2100_INTA_TX_COMPLETE (0x00000004) // Bit 2 -#define IPW2100_INTA_EVENT_INTERRUPT (0x00000008) // Bit 3 +#define IPW2100_INTA_EVENT_INTERRUPT (0x00000008) // Bit 3 #define IPW2100_INTA_STATUS_CHANGE (0x00000010) // Bit 4 #define IPW2100_INTA_BEACON_PERIOD_EXPIRED (0x00000020) // Bit 5 #define IPW2100_INTA_SLAVE_MODE_HOST_COMMAND_DONE (0x00010000) // Bit 16 @@ -784,9 +773,6 @@ struct ipw2100_priv { #define IPW_CARD_DISABLE_PHY_OFF_COMPLETE_WAIT 100 // 100 milli #define IPW_PREPARE_POWER_DOWN_COMPLETE_WAIT 100 // 100 milli - - - #define IPW_HEADER_802_11_SIZE sizeof(struct ieee80211_hdr_3addr) #define IPW_MAX_80211_PAYLOAD_SIZE 2304U #define IPW_MAX_802_11_PAYLOAD_LENGTH 2312 @@ -843,8 +829,8 @@ struct ipw2100_rx { #define IPW_TX_POWER_MIN_DBM (-12) #define IPW_TX_POWER_MAX_DBM 16 -#define FW_SCAN_DONOT_ASSOCIATE 0x0001 // Dont Attempt to Associate after Scan -#define FW_SCAN_PASSIVE 0x0008 // Force PASSSIVE Scan +#define FW_SCAN_DONOT_ASSOCIATE 0x0001 // Dont Attempt to Associate after Scan +#define FW_SCAN_PASSIVE 0x0008 // Force PASSSIVE Scan #define REG_MIN_CHANNEL 0 #define REG_MAX_CHANNEL 14 @@ -856,7 +842,6 @@ struct ipw2100_rx { #define DIVERSITY_ANTENNA_A 1 // Use antenna A #define DIVERSITY_ANTENNA_B 2 // Use antenna B - #define HOST_COMMAND_WAIT 0 #define HOST_COMMAND_NO_WAIT 1 @@ -873,7 +858,6 @@ struct ipw2100_rx { #define TYPE_ASSOCIATION_REQUEST 0x0013 #define TYPE_REASSOCIATION_REQUEST 0x0014 - #define HW_FEATURE_RFKILL (0x0001) #define RF_KILLSWITCH_OFF (1) #define RF_KILLSWITCH_ON (0) @@ -895,7 +879,7 @@ struct ipw2100_rx { // Fixed size data: Ordinal Table 1 typedef enum _ORDINAL_TABLE_1 { // NS - means Not Supported by FW // Transmit statistics - IPW_ORD_STAT_TX_HOST_REQUESTS = 1,// # of requested Host Tx's (MSDU) + IPW_ORD_STAT_TX_HOST_REQUESTS = 1, // # of requested Host Tx's (MSDU) IPW_ORD_STAT_TX_HOST_COMPLETE, // # of successful Host Tx's (MSDU) IPW_ORD_STAT_TX_DIR_DATA, // # of successful Directed Tx's (MSDU) @@ -905,42 +889,42 @@ typedef enum _ORDINAL_TABLE_1 { // NS - means Not Supported by FW IPW_ORD_STAT_TX_DIR_DATA11, // # of successful Directed Tx's (MSDU) @ 11MB IPW_ORD_STAT_TX_DIR_DATA22, // # of successful Directed Tx's (MSDU) @ 22MB - IPW_ORD_STAT_TX_NODIR_DATA1 = 13,// # of successful Non_Directed Tx's (MSDU) @ 1MB + IPW_ORD_STAT_TX_NODIR_DATA1 = 13, // # of successful Non_Directed Tx's (MSDU) @ 1MB IPW_ORD_STAT_TX_NODIR_DATA2, // # of successful Non_Directed Tx's (MSDU) @ 2MB IPW_ORD_STAT_TX_NODIR_DATA5_5, // # of successful Non_Directed Tx's (MSDU) @ 5.5MB IPW_ORD_STAT_TX_NODIR_DATA11, // # of successful Non_Directed Tx's (MSDU) @ 11MB IPW_ORD_STAT_NULL_DATA = 21, // # of successful NULL data Tx's - IPW_ORD_STAT_TX_RTS, // # of successful Tx RTS - IPW_ORD_STAT_TX_CTS, // # of successful Tx CTS - IPW_ORD_STAT_TX_ACK, // # of successful Tx ACK - IPW_ORD_STAT_TX_ASSN, // # of successful Association Tx's + IPW_ORD_STAT_TX_RTS, // # of successful Tx RTS + IPW_ORD_STAT_TX_CTS, // # of successful Tx CTS + IPW_ORD_STAT_TX_ACK, // # of successful Tx ACK + IPW_ORD_STAT_TX_ASSN, // # of successful Association Tx's IPW_ORD_STAT_TX_ASSN_RESP, // # of successful Association response Tx's - IPW_ORD_STAT_TX_REASSN, // # of successful Reassociation Tx's + IPW_ORD_STAT_TX_REASSN, // # of successful Reassociation Tx's IPW_ORD_STAT_TX_REASSN_RESP, // # of successful Reassociation response Tx's - IPW_ORD_STAT_TX_PROBE, // # of probes successfully transmitted + IPW_ORD_STAT_TX_PROBE, // # of probes successfully transmitted IPW_ORD_STAT_TX_PROBE_RESP, // # of probe responses successfully transmitted - IPW_ORD_STAT_TX_BEACON, // # of tx beacon - IPW_ORD_STAT_TX_ATIM, // # of Tx ATIM + IPW_ORD_STAT_TX_BEACON, // # of tx beacon + IPW_ORD_STAT_TX_ATIM, // # of Tx ATIM IPW_ORD_STAT_TX_DISASSN, // # of successful Disassociation TX - IPW_ORD_STAT_TX_AUTH, // # of successful Authentication Tx - IPW_ORD_STAT_TX_DEAUTH, // # of successful Deauthentication TX + IPW_ORD_STAT_TX_AUTH, // # of successful Authentication Tx + IPW_ORD_STAT_TX_DEAUTH, // # of successful Deauthentication TX - IPW_ORD_STAT_TX_TOTAL_BYTES = 41,// Total successful Tx data bytes - IPW_ORD_STAT_TX_RETRIES, // # of Tx retries - IPW_ORD_STAT_TX_RETRY1, // # of Tx retries at 1MBPS - IPW_ORD_STAT_TX_RETRY2, // # of Tx retries at 2MBPS - IPW_ORD_STAT_TX_RETRY5_5, // # of Tx retries at 5.5MBPS - IPW_ORD_STAT_TX_RETRY11, // # of Tx retries at 11MBPS + IPW_ORD_STAT_TX_TOTAL_BYTES = 41, // Total successful Tx data bytes + IPW_ORD_STAT_TX_RETRIES, // # of Tx retries + IPW_ORD_STAT_TX_RETRY1, // # of Tx retries at 1MBPS + IPW_ORD_STAT_TX_RETRY2, // # of Tx retries at 2MBPS + IPW_ORD_STAT_TX_RETRY5_5, // # of Tx retries at 5.5MBPS + IPW_ORD_STAT_TX_RETRY11, // # of Tx retries at 11MBPS IPW_ORD_STAT_TX_FAILURES = 51, // # of Tx Failures IPW_ORD_STAT_TX_ABORT_AT_HOP, //NS // # of Tx's aborted at hop time - IPW_ORD_STAT_TX_MAX_TRIES_IN_HOP,// # of times max tries in a hop failed + IPW_ORD_STAT_TX_MAX_TRIES_IN_HOP, // # of times max tries in a hop failed IPW_ORD_STAT_TX_ABORT_LATE_DMA, //NS // # of times tx aborted due to late dma setup IPW_ORD_STAT_TX_ABORT_STX, //NS // # of times backoff aborted IPW_ORD_STAT_TX_DISASSN_FAIL, // # of times disassociation failed - IPW_ORD_STAT_TX_ERR_CTS, // # of missed/bad CTS frames - IPW_ORD_STAT_TX_BPDU, //NS // # of spanning tree BPDUs sent + IPW_ORD_STAT_TX_ERR_CTS, // # of missed/bad CTS frames + IPW_ORD_STAT_TX_BPDU, //NS // # of spanning tree BPDUs sent IPW_ORD_STAT_TX_ERR_ACK, // # of tx err due to acks // Receive statistics @@ -952,7 +936,7 @@ typedef enum _ORDINAL_TABLE_1 { // NS - means Not Supported by FW IPW_ORD_STAT_RX_DIR_DATA11, // # of directed packets at 11MB IPW_ORD_STAT_RX_DIR_DATA22, // # of directed packets at 22MB - IPW_ORD_STAT_RX_NODIR_DATA = 71,// # of nondirected packets + IPW_ORD_STAT_RX_NODIR_DATA = 71, // # of nondirected packets IPW_ORD_STAT_RX_NODIR_DATA1, // # of nondirected packets at 1MB IPW_ORD_STAT_RX_NODIR_DATA2, // # of nondirected packets at 2MB IPW_ORD_STAT_RX_NODIR_DATA5_5, // # of nondirected packets at 5.5MB @@ -977,18 +961,18 @@ typedef enum _ORDINAL_TABLE_1 { // NS - means Not Supported by FW IPW_ORD_STAT_RX_AUTH, // # of authentication Rx IPW_ORD_STAT_RX_DEAUTH, // # of deauthentication Rx - IPW_ORD_STAT_RX_TOTAL_BYTES = 101,// Total rx data bytes received - IPW_ORD_STAT_RX_ERR_CRC, // # of packets with Rx CRC error - IPW_ORD_STAT_RX_ERR_CRC1, // # of Rx CRC errors at 1MB - IPW_ORD_STAT_RX_ERR_CRC2, // # of Rx CRC errors at 2MB - IPW_ORD_STAT_RX_ERR_CRC5_5, // # of Rx CRC errors at 5.5MB - IPW_ORD_STAT_RX_ERR_CRC11, // # of Rx CRC errors at 11MB + IPW_ORD_STAT_RX_TOTAL_BYTES = 101, // Total rx data bytes received + IPW_ORD_STAT_RX_ERR_CRC, // # of packets with Rx CRC error + IPW_ORD_STAT_RX_ERR_CRC1, // # of Rx CRC errors at 1MB + IPW_ORD_STAT_RX_ERR_CRC2, // # of Rx CRC errors at 2MB + IPW_ORD_STAT_RX_ERR_CRC5_5, // # of Rx CRC errors at 5.5MB + IPW_ORD_STAT_RX_ERR_CRC11, // # of Rx CRC errors at 11MB - IPW_ORD_STAT_RX_DUPLICATE1 = 112, // # of duplicate rx packets at 1MB - IPW_ORD_STAT_RX_DUPLICATE2, // # of duplicate rx packets at 2MB - IPW_ORD_STAT_RX_DUPLICATE5_5, // # of duplicate rx packets at 5.5MB - IPW_ORD_STAT_RX_DUPLICATE11, // # of duplicate rx packets at 11MB - IPW_ORD_STAT_RX_DUPLICATE = 119, // # of duplicate rx packets + IPW_ORD_STAT_RX_DUPLICATE1 = 112, // # of duplicate rx packets at 1MB + IPW_ORD_STAT_RX_DUPLICATE2, // # of duplicate rx packets at 2MB + IPW_ORD_STAT_RX_DUPLICATE5_5, // # of duplicate rx packets at 5.5MB + IPW_ORD_STAT_RX_DUPLICATE11, // # of duplicate rx packets at 11MB + IPW_ORD_STAT_RX_DUPLICATE = 119, // # of duplicate rx packets IPW_ORD_PERS_DB_LOCK = 120, // # locking fw permanent db IPW_ORD_PERS_DB_SIZE, // # size of fw permanent db @@ -1006,17 +990,17 @@ typedef enum _ORDINAL_TABLE_1 { // NS - means Not Supported by FW IPW_ORD_STAT_RX_ICV_ERRORS, // # of ICV errors during decryption // PSP Statistics - IPW_ORD_STAT_PSP_SUSPENSION = 137,// # of times adapter suspended + IPW_ORD_STAT_PSP_SUSPENSION = 137, // # of times adapter suspended IPW_ORD_STAT_PSP_BCN_TIMEOUT, // # of beacon timeout IPW_ORD_STAT_PSP_POLL_TIMEOUT, // # of poll response timeouts - IPW_ORD_STAT_PSP_NONDIR_TIMEOUT,// # of timeouts waiting for last broadcast/muticast pkt + IPW_ORD_STAT_PSP_NONDIR_TIMEOUT, // # of timeouts waiting for last broadcast/muticast pkt IPW_ORD_STAT_PSP_RX_DTIMS, // # of PSP DTIMs received IPW_ORD_STAT_PSP_RX_TIMS, // # of PSP TIMs received IPW_ORD_STAT_PSP_STATION_ID, // PSP Station ID // Association and roaming IPW_ORD_LAST_ASSN_TIME = 147, // RTC time of last association - IPW_ORD_STAT_PERCENT_MISSED_BCNS,// current calculation of % missed beacons + IPW_ORD_STAT_PERCENT_MISSED_BCNS, // current calculation of % missed beacons IPW_ORD_STAT_PERCENT_RETRIES, // current calculation of % missed tx retries IPW_ORD_ASSOCIATED_AP_PTR, // If associated, this is ptr to the associated // AP table entry. set to 0 if not associated @@ -1151,7 +1135,7 @@ struct ipw2100_fw_chunk { }; struct ipw2100_fw_chunk_set { - const void *data; + const void *data; unsigned long size; }; @@ -1164,4 +1148,4 @@ struct ipw2100_fw { #define MAX_FW_VERSION_LEN 14 -#endif /* _IPW2100_H */ +#endif /* _IPW2100_H */ -- cgit v1.2.3 From a1e695adca76f5729224242e4f2f9f6ceb6863d1 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 4 Jul 2005 14:06:00 +0800 Subject: IPW_DEBUG has already included DRV_NAME, remove double prefix print. --- drivers/net/wireless/ipw2100.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index a15eef1c2a6..449c1c085fb 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -1833,7 +1833,7 @@ static void ipw2100_down(struct ipw2100_priv *priv) #ifdef ACPI_CSTATE_LIMIT_DEFINED if (priv->config & CFG_C3_DISABLED) { - IPW_DEBUG_INFO(DRV_NAME ": Resetting C3 transitions.\n"); + IPW_DEBUG_INFO(": Resetting C3 transitions.\n"); acpi_set_cstate_limit(priv->cstate_limit); priv->config &= ~CFG_C3_DISABLED; } @@ -1858,8 +1858,7 @@ static void ipw2100_reset_adapter(struct ipw2100_priv *priv) int associated = priv->status & STATUS_ASSOCIATED; spin_lock_irqsave(&priv->low_lock, flags); - IPW_DEBUG_INFO(DRV_NAME ": %s: Restarting adapter.\n", - priv->net_dev->name); + IPW_DEBUG_INFO(": %s: Restarting adapter.\n", priv->net_dev->name); priv->resets++; priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); priv->status |= STATUS_SECURITY_UPDATED; @@ -2062,7 +2061,7 @@ static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status) #ifdef ACPI_CSTATE_LIMIT_DEFINED if (priv->config & CFG_C3_DISABLED) { - IPW_DEBUG_INFO(DRV_NAME ": Resetting C3 transitions.\n"); + IPW_DEBUG_INFO(": Resetting C3 transitions.\n"); acpi_set_cstate_limit(priv->cstate_limit); priv->config &= ~CFG_C3_DISABLED; } @@ -2300,11 +2299,11 @@ static inline void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i) int limit; #endif - IPW_DEBUG_INFO(DRV_NAME ": PCI latency error detected at " - "0x%04zX.\n", i * sizeof(struct ipw2100_status)); + IPW_DEBUG_INFO(": PCI latency error detected at 0x%04zX.\n", + i * sizeof(struct ipw2100_status)); #ifdef ACPI_CSTATE_LIMIT_DEFINED - IPW_DEBUG_INFO(DRV_NAME ": Disabling C3 transitions.\n"); + IPW_DEBUG_INFO(": Disabling C3 transitions.\n"); limit = acpi_get_cstate_limit(); if (limit > 2) { priv->cstate_limit = limit; @@ -4001,8 +4000,7 @@ static ssize_t store_debug_level(struct device_driver *d, const char *buf, } else val = simple_strtoul(p, &p, 10); if (p == buf) - IPW_DEBUG_INFO(DRV_NAME - ": %s is not in hex or decimal form.\n", buf); + IPW_DEBUG_INFO(": %s is not in hex or decimal form.\n", buf); else ipw2100_debug_level = val; -- cgit v1.2.3 From ea2b26e0a0264650e13acac8e66d315bb818897c Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Wed, 24 Aug 2005 21:25:16 -0500 Subject: Catch ipw2200 up to equivelancy with v1.0.1 This commit contains the following fixes: Fixed #559: iwconfig rate support (thanks to Florian Hackenberger) Improved link signal quality calculation (thanks to Bill Moss) Fixed a problem with sensitivity threshold during association Added iwpriv for turning forcing long preamble support: % iwpriv eth1 set_preamble 1|0 Fixed #542 and #377 support for short preamble Fixed locked BSSID reporting channel number (thanks to Pedro Ramalhais) Fixed type-o with scan watchdog timeout message (thanks to Pedro Ramalhais) Changed logic for displaying get_mode output so the code is easier to follow (thanks to Pedro Ramalhais) Added initial support for WPA (thanks to Yi Zhu) -- tested with wpa_supplicant (either tip w/ ipw driver, or with -Dipw2100) with both CCMP and TKIP Fixed problem with CCMP not working due to uninitialized 802.11 header fields (thanks to Pedro Ramalhais) Bug references are to defects stored on http://bughost.org Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 1694 +++++++++++++++++++++++++++++----------- drivers/net/wireless/ipw2200.h | 23 +- 2 files changed, 1247 insertions(+), 470 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 3db0c32afe8..ddbee3edcd8 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -32,7 +32,7 @@ #include "ipw2200.h" -#define IPW2200_VERSION "1.0.0" +#define IPW2200_VERSION "1.0.1" #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation" #define DRV_VERSION IPW2200_VERSION @@ -44,7 +44,6 @@ MODULE_LICENSE("GPL"); static int debug = 0; static int channel = 0; -static char *ifname; static int mode = 0; static u32 ipw_debug_level; @@ -289,32 +288,33 @@ static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, { u32 aligned_addr = addr & CX2_INDIRECT_ADDR_MASK; u32 dif_len = addr - aligned_addr; - u32 aligned_len; u32 i; IPW_DEBUG_IO("addr = %i, buf = %p, num = %i\n", addr, buf, num); + if (num <= 0) { + return; + } + /* Read the first nibble byte by byte */ if (unlikely(dif_len)) { - /* Start reading at aligned_addr + dif_len */ _ipw_write32(priv, CX2_INDIRECT_ADDR, aligned_addr); - for (i = dif_len; i < 4; i++, buf++) - *buf = _ipw_read8(priv, CX2_INDIRECT_DATA + i); - num -= dif_len; + /* Start reading at aligned_addr + dif_len */ + for (i = dif_len; ((i < 4) && (num > 0)); i++, num--) + *buf++ = _ipw_read8(priv, CX2_INDIRECT_DATA + i); aligned_addr += 4; } - /* Read DWs through autoinc register */ _ipw_write32(priv, CX2_AUTOINC_ADDR, aligned_addr); - aligned_len = num & CX2_INDIRECT_ADDR_MASK; - for (i = 0; i < aligned_len; i += 4, buf += 4, aligned_addr += 4) - *(u32 *) buf = ipw_read32(priv, CX2_AUTOINC_DATA); + for (; num >= 4; buf += 4, aligned_addr += 4, num -= 4) + *(u32 *) buf = _ipw_read32(priv, CX2_AUTOINC_DATA); /* Copy the last nibble */ - dif_len = num - aligned_len; - _ipw_write32(priv, CX2_INDIRECT_ADDR, aligned_addr); - for (i = 0; i < dif_len; i++, buf++) - *buf = ipw_read8(priv, CX2_INDIRECT_DATA + i); + if (unlikely(num)) { + _ipw_write32(priv, CX2_INDIRECT_ADDR, aligned_addr); + for (i = 0; num > 0; i++, num--) + *buf++ = ipw_read8(priv, CX2_INDIRECT_DATA + i); + } } static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, @@ -322,32 +322,33 @@ static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, { u32 aligned_addr = addr & CX2_INDIRECT_ADDR_MASK; u32 dif_len = addr - aligned_addr; - u32 aligned_len; u32 i; IPW_DEBUG_IO("addr = %i, buf = %p, num = %i\n", addr, buf, num); + if (num <= 0) { + return; + } + /* Write the first nibble byte by byte */ if (unlikely(dif_len)) { - /* Start writing at aligned_addr + dif_len */ _ipw_write32(priv, CX2_INDIRECT_ADDR, aligned_addr); - for (i = dif_len; i < 4; i++, buf++) + /* Start reading at aligned_addr + dif_len */ + for (i = dif_len; ((i < 4) && (num > 0)); i++, num--, buf++) _ipw_write8(priv, CX2_INDIRECT_DATA + i, *buf); - num -= dif_len; aligned_addr += 4; } - /* Write DWs through autoinc register */ _ipw_write32(priv, CX2_AUTOINC_ADDR, aligned_addr); - aligned_len = num & CX2_INDIRECT_ADDR_MASK; - for (i = 0; i < aligned_len; i += 4, buf += 4, aligned_addr += 4) + for (; num >= 4; buf += 4, aligned_addr += 4, num -= 4) _ipw_write32(priv, CX2_AUTOINC_DATA, *(u32 *) buf); /* Copy the last nibble */ - dif_len = num - aligned_len; - _ipw_write32(priv, CX2_INDIRECT_ADDR, aligned_addr); - for (i = 0; i < dif_len; i++, buf++) - _ipw_write8(priv, CX2_INDIRECT_DATA + i, *buf); + if (unlikely(num)) { + _ipw_write32(priv, CX2_INDIRECT_ADDR, aligned_addr); + for (i = 0; num > 0; i++, num--, buf++) + _ipw_write8(priv, CX2_INDIRECT_DATA + i, *buf); + } } static void ipw_write_direct(struct ipw_priv *priv, u32 addr, void *buf, @@ -945,7 +946,7 @@ static ssize_t show_rf_kill(struct device *d, struct device_attribute *attr, static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio) { if ((disable_radio ? 1 : 0) == - (priv->status & STATUS_RF_KILL_SW ? 1 : 0)) + ((priv->status & STATUS_RF_KILL_SW) ? 1 : 0)) return 0; IPW_DEBUG_RF_KILL("Manual SW RF Kill set to: RADIO %s\n", @@ -987,6 +988,17 @@ static ssize_t store_rf_kill(struct device *d, struct device_attribute *attr, static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill); +static void notify_wx_assoc_event(struct ipw_priv *priv) +{ + union iwreq_data wrqu; + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + if (priv->status & STATUS_ASSOCIATED) + memcpy(wrqu.ap_addr.sa_data, priv->bssid, ETH_ALEN); + else + memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); + wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL); +} + static void ipw_irq_tasklet(struct ipw_priv *priv) { u32 inta, inta_mask, handled = 0; @@ -1071,6 +1083,8 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) wake_up_interruptible(&priv->wait_command_queue); netif_carrier_off(priv->net_dev); netif_stop_queue(priv->net_dev); + priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); + notify_wx_assoc_event(priv); cancel_delayed_work(&priv->request_scan); queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ); handled |= CX2_INTA_BIT_RF_KILL_DONE; @@ -1162,7 +1176,7 @@ static char *get_cmd_string(u8 cmd) return "UNKNOWN"; } } -#endif /* CONFIG_IPW_DEBUG */ +#endif #define HOST_COMPLETE_TIMEOUT HZ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) @@ -2445,10 +2459,10 @@ static int ipw_load(struct ipw_priv *priv) rc = ipw_get_fw(priv, &firmware, IPW_FW_NAME("ibss")); break; -#ifdef CONFIG_IPW_PROMISC +#ifdef CONFIG_IPW_MONITOR case IW_MODE_MONITOR: rc = ipw_get_fw(priv, &ucode, - IPW_FW_NAME("ibss_ucode")); + IPW_FW_NAME("sniffer_ucode")); if (rc) goto error; @@ -2929,17 +2943,6 @@ static void ipw_disassociate(void *data) ipw_send_disassociate(data, 0); } -static void notify_wx_assoc_event(struct ipw_priv *priv) -{ - union iwreq_data wrqu; - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - if (priv->status & STATUS_ASSOCIATED) - memcpy(wrqu.ap_addr.sa_data, priv->bssid, ETH_ALEN); - else - memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); - wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL); -} - struct ipw_status_code { u16 status; const char *reason; @@ -2997,7 +3000,7 @@ static const char *ipw_get_status_code(u16 status) { int i; for (i = 0; i < ARRAY_SIZE(ipw_status_codes); i++) - if (ipw_status_codes[i].status == status) + if (ipw_status_codes[i].status == (status & 0xff)) return ipw_status_codes[i].reason; return "Unknown status value."; } @@ -3076,18 +3079,30 @@ static inline u32 ipw_get_max_rate(struct ipw_priv *priv) while (i && !(mask & i)) i >>= 1; switch (i) { - case IEEE80211_CCK_RATE_1MB_MASK: return 1000000; - case IEEE80211_CCK_RATE_2MB_MASK: return 2000000; - case IEEE80211_CCK_RATE_5MB_MASK: return 5500000; - case IEEE80211_OFDM_RATE_6MB_MASK: return 6000000; - case IEEE80211_OFDM_RATE_9MB_MASK: return 9000000; - case IEEE80211_CCK_RATE_11MB_MASK: return 11000000; - case IEEE80211_OFDM_RATE_12MB_MASK: return 12000000; - case IEEE80211_OFDM_RATE_18MB_MASK: return 18000000; - case IEEE80211_OFDM_RATE_24MB_MASK: return 24000000; - case IEEE80211_OFDM_RATE_36MB_MASK: return 36000000; - case IEEE80211_OFDM_RATE_48MB_MASK: return 48000000; - case IEEE80211_OFDM_RATE_54MB_MASK: return 54000000; + case IEEE80211_CCK_RATE_1MB_MASK: + return 1000000; + case IEEE80211_CCK_RATE_2MB_MASK: + return 2000000; + case IEEE80211_CCK_RATE_5MB_MASK: + return 5500000; + case IEEE80211_OFDM_RATE_6MB_MASK: + return 6000000; + case IEEE80211_OFDM_RATE_9MB_MASK: + return 9000000; + case IEEE80211_CCK_RATE_11MB_MASK: + return 11000000; + case IEEE80211_OFDM_RATE_12MB_MASK: + return 12000000; + case IEEE80211_OFDM_RATE_18MB_MASK: + return 18000000; + case IEEE80211_OFDM_RATE_24MB_MASK: + return 24000000; + case IEEE80211_OFDM_RATE_36MB_MASK: + return 36000000; + case IEEE80211_OFDM_RATE_48MB_MASK: + return 48000000; + case IEEE80211_OFDM_RATE_54MB_MASK: + return 54000000; } if (priv->ieee->mode == IEEE_B) @@ -3115,24 +3130,36 @@ static u32 ipw_get_current_rate(struct ipw_priv *priv) return ipw_get_max_rate(priv); switch (rate) { - case IPW_TX_RATE_1MB: return 1000000; - case IPW_TX_RATE_2MB: return 2000000; - case IPW_TX_RATE_5MB: return 5500000; - case IPW_TX_RATE_6MB: return 6000000; - case IPW_TX_RATE_9MB: return 9000000; - case IPW_TX_RATE_11MB: return 11000000; - case IPW_TX_RATE_12MB: return 12000000; - case IPW_TX_RATE_18MB: return 18000000; - case IPW_TX_RATE_24MB: return 24000000; - case IPW_TX_RATE_36MB: return 36000000; - case IPW_TX_RATE_48MB: return 48000000; - case IPW_TX_RATE_54MB: return 54000000; + case IPW_TX_RATE_1MB: + return 1000000; + case IPW_TX_RATE_2MB: + return 2000000; + case IPW_TX_RATE_5MB: + return 5500000; + case IPW_TX_RATE_6MB: + return 6000000; + case IPW_TX_RATE_9MB: + return 9000000; + case IPW_TX_RATE_11MB: + return 11000000; + case IPW_TX_RATE_12MB: + return 12000000; + case IPW_TX_RATE_18MB: + return 18000000; + case IPW_TX_RATE_24MB: + return 24000000; + case IPW_TX_RATE_36MB: + return 36000000; + case IPW_TX_RATE_48MB: + return 48000000; + case IPW_TX_RATE_54MB: + return 54000000; } return 0; } -#define PERFECT_RSSI (-50) +#define PERFECT_RSSI (-20) #define WORST_RSSI (-85) #define IPW_STATS_INTERVAL (2 * HZ) static void ipw_gather_stats(struct ipw_priv *priv) @@ -3145,6 +3172,7 @@ static void ipw_gather_stats(struct ipw_priv *priv) s16 rssi; u32 beacon_quality, signal_quality, tx_quality, rx_quality, rate_quality; + u32 max_rate; if (!(priv->status & STATUS_ASSOCIATED)) { priv->quality = 0; @@ -3201,7 +3229,8 @@ static void ipw_gather_stats(struct ipw_priv *priv) beacon_quality, missed_beacons_percent); priv->last_rate = ipw_get_current_rate(priv); - rate_quality = priv->last_rate * 40 / priv->last_rate + 60; + max_rate = ipw_get_max_rate(priv); + rate_quality = priv->last_rate * 40 / max_rate + 60; IPW_DEBUG_STATS("Rate quality : %3d%% (%dMbs)\n", rate_quality, priv->last_rate / 1000000); @@ -3226,9 +3255,16 @@ static void ipw_gather_stats(struct ipw_priv *priv) signal_quality = 100; else if (rssi < WORST_RSSI) signal_quality = 0; - else - signal_quality = (rssi - WORST_RSSI) * 100 / - (PERFECT_RSSI - WORST_RSSI); + else /* qual = 100a^2 - 15ab + 62b^2 / a^2 */ + signal_quality = + (100 * + (PERFECT_RSSI - WORST_RSSI) * + (PERFECT_RSSI - WORST_RSSI) - + (PERFECT_RSSI - rssi) * + (15 * (PERFECT_RSSI - WORST_RSSI) + + 62 * (PERFECT_RSSI - rssi))) / + ((PERFECT_RSSI - WORST_RSSI) * (PERFECT_RSSI - WORST_RSSI)); + IPW_DEBUG_STATS("Signal level : %3d%% (%d dBm)\n", signal_quality, rssi); @@ -3257,6 +3293,62 @@ static void ipw_gather_stats(struct ipw_priv *priv) IPW_STATS_INTERVAL); } +static inline void ipw_handle_missed_beacon(struct ipw_priv *priv, + int missed_count) +{ + priv->notif_missed_beacons = missed_count; + + if (missed_count > priv->missed_beacon_threshold && + priv->status & STATUS_ASSOCIATED) { + /* If associated and we've hit the missed + * beacon threshold, disassociate, turn + * off roaming, and abort any active scans */ + IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF | + IPW_DL_STATE, + "Missed beacon: %d - disassociate\n", missed_count); + priv->status &= ~STATUS_ROAMING; + if (priv->status & STATUS_SCANNING) + queue_work(priv->workqueue, &priv->abort_scan); + queue_work(priv->workqueue, &priv->disassociate); + return; + } + + if (priv->status & STATUS_ROAMING) { + /* If we are currently roaming, then just + * print a debug statement... */ + IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE, + "Missed beacon: %d - roam in progress\n", + missed_count); + return; + } + + if (missed_count > priv->roaming_threshold) { + /* If we are not already roaming, set the ROAM + * bit in the status and kick off a scan */ + IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE, + "Missed beacon: %d - initiate " + "roaming\n", missed_count); + if (!(priv->status & STATUS_ROAMING)) { + priv->status |= STATUS_ROAMING; + if (!(priv->status & STATUS_SCANNING)) + queue_work(priv->workqueue, + &priv->request_scan); + } + return; + } + + if (priv->status & STATUS_SCANNING) { + /* Stop scan to keep fw from getting + * stuck (only if we aren't roaming -- + * otherwise we'll never scan more than 2 or 3 + * channels..) */ + queue_work(priv->workqueue, &priv->abort_scan); + } + + IPW_DEBUG_NOTIF("Missed beacon: %d\n", missed_count); + +} + /** * Handle host notification packet. * Called from interrupt routine @@ -3383,6 +3475,24 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, } case CMAS_INIT:{ + if (priv->status & STATUS_AUTH) { + struct + ieee80211_assoc_response + *resp; + resp = + (struct + ieee80211_assoc_response + *)¬if->u.raw; + IPW_DEBUG(IPW_DL_NOTIF | + IPW_DL_STATE | + IPW_DL_ASSOC, + "association failed (0x%04X): %s\n", + ntohs(resp->status), + ipw_get_status_code + (ntohs + (resp->status))); + } + IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC, "disassociated: '%s' " MAC_FMT @@ -3629,36 +3739,8 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, break; } - if (x->state == HOST_NOTIFICATION_STATUS_BEACON_MISSING) { - if (priv->status & STATUS_SCANNING) { - /* Stop scan to keep fw from getting - * stuck... */ - queue_work(priv->workqueue, - &priv->abort_scan); - } - - if (x->number > priv->missed_beacon_threshold && - priv->status & STATUS_ASSOCIATED) { - IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF | - IPW_DL_STATE, - "Missed beacon: %d - disassociate\n", - x->number); - queue_work(priv->workqueue, - &priv->disassociate); - } else if (x->number > priv->roaming_threshold) { - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE, - "Missed beacon: %d - initiate " - "roaming\n", x->number); - queue_work(priv->workqueue, - &priv->roam); - } else { - IPW_DEBUG_NOTIF("Missed beacon: %d\n", - x->number); - } - - priv->notif_missed_beacons = x->number; - - } + if (x->state == HOST_NOTIFICATION_STATUS_BEACON_MISSING) + ipw_handle_missed_beacon(priv, x->number); break; } @@ -4137,6 +4219,13 @@ static int ipw_compatible_rates(struct ipw_priv *priv, for (i = 0; i < num_rates; i++) { if (!ipw_is_rate_in_mask (priv, network->mode, network->rates[i])) { + if (network->rates[i] & IEEE80211_BASIC_RATE_MASK) { + IPW_DEBUG_SCAN + ("Basic rate %02X masked: 0x%08X\n", + network->rates[i], priv->rates_mask); + return 0; + } + IPW_DEBUG_SCAN("Rate %02X masked : 0x%08X\n", network->rates[i], priv->rates_mask); continue; @@ -4150,6 +4239,13 @@ static int ipw_compatible_rates(struct ipw_priv *priv, for (i = 0; i < num_rates; i++) { if (!ipw_is_rate_in_mask (priv, network->mode, network->rates_ex[i])) { + if (network->rates_ex[i] & IEEE80211_BASIC_RATE_MASK) { + IPW_DEBUG_SCAN + ("Basic rate %02X masked: 0x%08X\n", + network->rates_ex[i], priv->rates_mask); + return 0; + } + IPW_DEBUG_SCAN("Rate %02X masked : 0x%08X\n", network->rates_ex[i], priv->rates_mask); continue; @@ -4159,7 +4255,7 @@ static int ipw_compatible_rates(struct ipw_priv *priv, network->rates_ex[i]; } - return rates->num_rates; + return 1; } static inline void ipw_copy_rates(struct ipw_supported_rates *dest, @@ -4322,7 +4418,7 @@ static int ipw_best_network(struct ipw_priv *priv, /* If this network has already had an association attempt within the * last 3 seconds, do not try and associate again... */ if (network->last_associate && - time_after(network->last_associate + (HZ * 5UL), jiffies)) { + time_after(network->last_associate + (HZ * 3UL), jiffies)) { IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " "because of storming (%lu since last " "assoc attempt).\n", @@ -4334,7 +4430,7 @@ static int ipw_best_network(struct ipw_priv *priv, /* Now go through and see if the requested network is valid... */ if (priv->ieee->scan_age != 0 && - jiffies - network->last_scanned > priv->ieee->scan_age) { + time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) { IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " "because of age: %lums.\n", escape_essid(network->ssid, network->ssid_len), @@ -4386,7 +4482,17 @@ static int ipw_best_network(struct ipw_priv *priv, return 0; } - ipw_compatible_rates(priv, network, &rates); + /* Ensure that the rates supported by the driver are compatible with + * this AP, including verification of basic rates (mandatory) */ + if (!ipw_compatible_rates(priv, network, &rates)) { + IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " + "because configured rate mask excludes " + "AP mandatory rate.\n", + escape_essid(network->ssid, network->ssid_len), + MAC_ARG(network->bssid)); + return 0; + } + if (rates.num_rates == 0) { IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " "because of no compatible rates.\n", @@ -4448,6 +4554,8 @@ static void ipw_adhoc_create(struct ipw_priv *priv, memcpy(network->ssid, priv->essid, priv->essid_len); memset(&network->stats, 0, sizeof(network->stats)); network->capability = WLAN_CAPABILITY_IBSS; + if (!(priv->config & CFG_PREAMBLE_LONG)) + network->capability |= WLAN_CAPABILITY_SHORT_PREAMBLE; if (priv->capability & CAP_PRIVACY_ON) network->capability |= WLAN_CAPABILITY_PRIVACY; network->rates_len = min(priv->rates.num_rates, MAX_RATES_LENGTH); @@ -4530,7 +4638,8 @@ static void ipw_debug_config(struct ipw_priv *priv) else IPW_DEBUG_INFO("ESSID unlocked.\n"); if (priv->config & CFG_STATIC_BSSID) - IPW_DEBUG_INFO("BSSID locked to %d\n", priv->channel); + IPW_DEBUG_INFO("BSSID locked to " MAC_FMT "\n", + MAC_ARG(priv->bssid)); else IPW_DEBUG_INFO("BSSID unlocked.\n"); if (priv->capability & CAP_PRIVACY_ON) @@ -4561,6 +4670,8 @@ static inline void ipw_set_fixed_rate(struct ipw_priv *priv, /* IEEE_A */ if (priv->rates_mask & ~IEEE80211_OFDM_RATES_MASK) { /* Invalid fixed rate mask */ + IPW_DEBUG_WX + ("invalid fixed rate mask in ipw_set_fixed_rate\n"); fr.tx_rates = 0; break; } @@ -4573,6 +4684,8 @@ static inline void ipw_set_fixed_rate(struct ipw_priv *priv, if (network->mode == IEEE_B) { if (fr.tx_rates & ~IEEE80211_CCK_RATES_MASK) { /* Invalid fixed rate mask */ + IPW_DEBUG_WX + ("invalid fixed rate mask in ipw_set_fixed_rate\n"); fr.tx_rates = 0; } break; @@ -4582,6 +4695,8 @@ static inline void ipw_set_fixed_rate(struct ipw_priv *priv, if (fr.tx_rates & ~(IEEE80211_CCK_RATES_MASK | IEEE80211_OFDM_RATES_MASK)) { /* Invalid fixed rate mask */ + IPW_DEBUG_WX + ("invalid fixed rate mask in ipw_set_fixed_rate\n"); fr.tx_rates = 0; break; } @@ -4609,134 +4724,748 @@ static inline void ipw_set_fixed_rate(struct ipw_priv *priv, ipw_write_reg32(priv, reg, *(u32 *) & fr); } -static int ipw_associate_network(struct ipw_priv *priv, - struct ieee80211_network *network, - struct ipw_supported_rates *rates, int roaming) +static void ipw_abort_scan(struct ipw_priv *priv) { int err; - if (priv->config & CFG_FIXED_RATE) - ipw_set_fixed_rate(priv, network); + if (priv->status & STATUS_SCAN_ABORTING) { + IPW_DEBUG_HC("Ignoring concurrent scan abort request.\n"); + return; + } + priv->status |= STATUS_SCAN_ABORTING; - if (!(priv->config & CFG_STATIC_ESSID)) { - priv->essid_len = min(network->ssid_len, - (u8) IW_ESSID_MAX_SIZE); - memcpy(priv->essid, network->ssid, priv->essid_len); + err = ipw_send_scan_abort(priv); + if (err) + IPW_DEBUG_HC("Request to abort scan failed.\n"); +} + +static int ipw_request_scan(struct ipw_priv *priv) +{ + struct ipw_scan_request_ext scan; + int channel_index = 0; + int i, err, scan_type; + + if (priv->status & STATUS_EXIT_PENDING) { + IPW_DEBUG_SCAN("Aborting scan due to device shutdown\n"); + priv->status |= STATUS_SCAN_PENDING; + return 0; } - network->last_associate = jiffies; + if (priv->status & STATUS_SCANNING) { + IPW_DEBUG_HC("Concurrent scan requested. Aborting first.\n"); + priv->status |= STATUS_SCAN_PENDING; + ipw_abort_scan(priv); + return 0; + } - memset(&priv->assoc_request, 0, sizeof(priv->assoc_request)); - priv->assoc_request.channel = network->channel; - if ((priv->capability & CAP_PRIVACY_ON) && - (priv->capability & CAP_SHARED_KEY)) { - priv->assoc_request.auth_type = AUTH_SHARED_KEY; - priv->assoc_request.auth_key = priv->sec.active_key; - } else { - priv->assoc_request.auth_type = AUTH_OPEN; - priv->assoc_request.auth_key = 0; + if (priv->status & STATUS_SCAN_ABORTING) { + IPW_DEBUG_HC("Scan request while abort pending. Queuing.\n"); + priv->status |= STATUS_SCAN_PENDING; + return 0; } - if (priv->capability & CAP_PRIVACY_ON) - ipw_send_wep_keys(priv); + if (priv->status & STATUS_RF_KILL_MASK) { + IPW_DEBUG_HC("Aborting scan due to RF Kill activation\n"); + priv->status |= STATUS_SCAN_PENDING; + return 0; + } - /* - * It is valid for our ieee device to support multiple modes, but - * when it comes to associating to a given network we have to choose - * just one mode. - */ - if (network->mode & priv->ieee->mode & IEEE_A) - priv->assoc_request.ieee_mode = IPW_A_MODE; - else if (network->mode & priv->ieee->mode & IEEE_G) - priv->assoc_request.ieee_mode = IPW_G_MODE; - else if (network->mode & priv->ieee->mode & IEEE_B) - priv->assoc_request.ieee_mode = IPW_B_MODE; + memset(&scan, 0, sizeof(scan)); - IPW_DEBUG_ASSOC("%sssocation attempt: '%s', channel %d, " - "802.11%c [%d], enc=%s%s%s%c%c\n", - roaming ? "Rea" : "A", - escape_essid(priv->essid, priv->essid_len), - network->channel, - ipw_modes[priv->assoc_request.ieee_mode], - rates->num_rates, - priv->capability & CAP_PRIVACY_ON ? "on " : "off", - priv->capability & CAP_PRIVACY_ON ? - (priv->capability & CAP_SHARED_KEY ? "(shared)" : - "(open)") : "", - priv->capability & CAP_PRIVACY_ON ? " key=" : "", - priv->capability & CAP_PRIVACY_ON ? - '1' + priv->sec.active_key : '.', - priv->capability & CAP_PRIVACY_ON ? '.' : ' '); + scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = 20; + scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] = 20; + scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = 20; - priv->assoc_request.beacon_interval = network->beacon_interval; - if ((priv->ieee->iw_mode == IW_MODE_ADHOC) && - (network->time_stamp[0] == 0) && (network->time_stamp[1] == 0)) { - priv->assoc_request.assoc_type = HC_IBSS_START; - priv->assoc_request.assoc_tsf_msw = 0; - priv->assoc_request.assoc_tsf_lsw = 0; - } else { - if (unlikely(roaming)) - priv->assoc_request.assoc_type = HC_REASSOCIATE; - else - priv->assoc_request.assoc_type = HC_ASSOCIATE; - priv->assoc_request.assoc_tsf_msw = network->time_stamp[1]; - priv->assoc_request.assoc_tsf_lsw = network->time_stamp[0]; - } + scan.full_scan_index = ieee80211_get_scans(priv->ieee); - memcpy(&priv->assoc_request.bssid, network->bssid, ETH_ALEN); +#ifdef CONFIG_IPW_MONITOR + if (priv->ieee->iw_mode == IW_MODE_MONITOR) { + u8 band = 0, channel = priv->channel; - if (priv->ieee->iw_mode == IW_MODE_ADHOC) { - memset(&priv->assoc_request.dest, 0xFF, ETH_ALEN); - priv->assoc_request.atim_window = network->atim_window; + if (is_valid_channel(IEEE_A, channel)) + band = (u8) (IPW_A_MODE << 6) | 1; + + if (is_valid_channel(IEEE_B | IEEE_G, channel)) + band = (u8) (IPW_B_MODE << 6) | 1; + + if (band == 0) { + band = (u8) (IPW_B_MODE << 6) | 1; + channel = 9; + } + + scan.channels_list[channel_index++] = band; + scan.channels_list[channel_index] = channel; + ipw_set_scan_type(&scan, channel_index, + IPW_SCAN_PASSIVE_FULL_DWELL_SCAN); + + scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = 2000; } else { - memcpy(&priv->assoc_request.dest, network->bssid, ETH_ALEN); - priv->assoc_request.atim_window = 0; - } +#endif /* CONFIG_IPW_MONITOR */ + /* If we are roaming, then make this a directed scan for the current + * network. Otherwise, ensure that every other scan is a fast + * channel hop scan */ + if ((priv->status & STATUS_ROAMING) + || (!(priv->status & STATUS_ASSOCIATED) + && (priv->config & CFG_STATIC_ESSID) + && (scan.full_scan_index % 2))) { + err = ipw_send_ssid(priv, priv->essid, priv->essid_len); + if (err) { + IPW_DEBUG_HC + ("Attempt to send SSID command failed.\n"); + return err; + } - priv->assoc_request.capability = network->capability; - priv->assoc_request.listen_interval = network->listen_interval; + scan_type = IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN; + } else { + scan_type = IPW_SCAN_ACTIVE_BROADCAST_SCAN; + } - err = ipw_send_ssid(priv, priv->essid, priv->essid_len); - if (err) { - IPW_DEBUG_HC("Attempt to send SSID command failed.\n"); - return err; - } + if (priv->ieee->freq_band & IEEE80211_52GHZ_BAND) { + int start = channel_index; + for (i = 0; i < MAX_A_CHANNELS; i++) { + if (band_a_active_channel[i] == 0) + break; + if ((priv->status & STATUS_ASSOCIATED) && + band_a_active_channel[i] == priv->channel) + continue; + channel_index++; + scan.channels_list[channel_index] = + band_a_active_channel[i]; + ipw_set_scan_type(&scan, channel_index, + scan_type); + } - rates->ieee_mode = priv->assoc_request.ieee_mode; - rates->purpose = IPW_RATE_CONNECT; - ipw_send_supported_rates(priv, rates); + if (start != channel_index) { + scan.channels_list[start] = + (u8) (IPW_A_MODE << 6) | (channel_index - + start); + channel_index++; + } + } - if (priv->assoc_request.ieee_mode == IPW_G_MODE) - priv->sys_config.dot11g_auto_detection = 1; - else - priv->sys_config.dot11g_auto_detection = 0; - err = ipw_send_system_config(priv, &priv->sys_config); - if (err) { - IPW_DEBUG_HC("Attempt to send sys config command failed.\n"); - return err; + if (priv->ieee->freq_band & IEEE80211_24GHZ_BAND) { + int start = channel_index; + for (i = 0; i < MAX_B_CHANNELS; i++) { + if (band_b_active_channel[i] == 0) + break; + if ((priv->status & STATUS_ASSOCIATED) && + band_b_active_channel[i] == priv->channel) + continue; + channel_index++; + scan.channels_list[channel_index] = + band_b_active_channel[i]; + ipw_set_scan_type(&scan, channel_index, + scan_type); + } + + if (start != channel_index) { + scan.channels_list[start] = + (u8) (IPW_B_MODE << 6) | (channel_index - + start); + } + } +#ifdef CONFIG_IPW_MONITOR } +#endif - IPW_DEBUG_ASSOC("Association sensitivity: %d\n", network->stats.rssi); - err = ipw_set_sensitivity(priv, network->stats.rssi); + err = ipw_send_scan_request_ext(priv, &scan); if (err) { - IPW_DEBUG_HC("Attempt to send associate command failed.\n"); - return err; + IPW_DEBUG_HC("Sending scan command failed: %08X\n", err); + return -EIO; } - /* - * If preemption is enabled, it is possible for the association - * to complete before we return from ipw_send_associate. Therefore - * we have to be sure and update our priviate data first. - */ - priv->channel = network->channel; - memcpy(priv->bssid, network->bssid, ETH_ALEN); - priv->status |= STATUS_ASSOCIATING; - priv->status &= ~STATUS_SECURITY_UPDATED; + priv->status |= STATUS_SCANNING; + priv->status &= ~STATUS_SCAN_PENDING; - priv->assoc_network = network; + return 0; +} - err = ipw_send_associate(priv, &priv->assoc_request); - if (err) { +/* Support for wpa_supplicant. Will be replaced with WEXT once + * they get WPA support. */ +#ifdef CONFIG_IEEE80211_WPA + +/* following definitions must match definitions in driver_ipw.c */ + +#define IPW_IOCTL_WPA_SUPPLICANT SIOCIWFIRSTPRIV+30 + +#define IPW_CMD_SET_WPA_PARAM 1 +#define IPW_CMD_SET_WPA_IE 2 +#define IPW_CMD_SET_ENCRYPTION 3 +#define IPW_CMD_MLME 4 + +#define IPW_PARAM_WPA_ENABLED 1 +#define IPW_PARAM_TKIP_COUNTERMEASURES 2 +#define IPW_PARAM_DROP_UNENCRYPTED 3 +#define IPW_PARAM_PRIVACY_INVOKED 4 +#define IPW_PARAM_AUTH_ALGS 5 +#define IPW_PARAM_IEEE_802_1X 6 + +#define IPW_MLME_STA_DEAUTH 1 +#define IPW_MLME_STA_DISASSOC 2 + +#define IPW_CRYPT_ERR_UNKNOWN_ALG 2 +#define IPW_CRYPT_ERR_UNKNOWN_ADDR 3 +#define IPW_CRYPT_ERR_CRYPT_INIT_FAILED 4 +#define IPW_CRYPT_ERR_KEY_SET_FAILED 5 +#define IPW_CRYPT_ERR_TX_KEY_SET_FAILED 6 +#define IPW_CRYPT_ERR_CARD_CONF_FAILED 7 + +#define IPW_CRYPT_ALG_NAME_LEN 16 + +struct ipw_param { + u32 cmd; + u8 sta_addr[ETH_ALEN]; + union { + struct { + u8 name; + u32 value; + } wpa_param; + struct { + u32 len; + u8 *data; + } wpa_ie; + struct { + int command; + int reason_code; + } mlme; + struct { + u8 alg[IPW_CRYPT_ALG_NAME_LEN]; + u8 set_tx; + u32 err; + u8 idx; + u8 seq[8]; /* sequence counter (set: RX, get: TX) */ + u16 key_len; + u8 key[0]; + } crypt; + + } u; +}; + +/* end of driver_ipw.c code */ + +static int ipw_wpa_enable(struct ipw_priv *priv, int value) +{ + struct ieee80211_device *ieee = priv->ieee; + struct ieee80211_security sec = { + .flags = SEC_LEVEL | SEC_ENABLED, + }; + int ret = 0; + + ieee->wpa_enabled = value; + + if (value) { + sec.level = SEC_LEVEL_3; + sec.enabled = 1; + } else { + sec.level = SEC_LEVEL_0; + sec.enabled = 0; + } + + if (ieee->set_security) + ieee->set_security(ieee->dev, &sec); + else + ret = -EOPNOTSUPP; + + return ret; +} + +#define AUTH_ALG_OPEN_SYSTEM 0x1 +#define AUTH_ALG_SHARED_KEY 0x2 + +static int ipw_wpa_set_auth_algs(struct ipw_priv *priv, int value) +{ + struct ieee80211_device *ieee = priv->ieee; + struct ieee80211_security sec = { + .flags = SEC_AUTH_MODE, + }; + int ret = 0; + + if (value & AUTH_ALG_SHARED_KEY) { + sec.auth_mode = WLAN_AUTH_SHARED_KEY; + ieee->open_wep = 0; + } else { + sec.auth_mode = WLAN_AUTH_OPEN; + ieee->open_wep = 1; + } + + if (ieee->set_security) + ieee->set_security(ieee->dev, &sec); + else + ret = -EOPNOTSUPP; + + return ret; +} + +static int ipw_wpa_set_param(struct net_device *dev, u8 name, u32 value) +{ + struct ipw_priv *priv = ieee80211_priv(dev); + int ret = 0; + + switch (name) { + case IPW_PARAM_WPA_ENABLED: + ret = ipw_wpa_enable(priv, value); + break; + + case IPW_PARAM_TKIP_COUNTERMEASURES: + priv->ieee->tkip_countermeasures = value; + break; + + case IPW_PARAM_DROP_UNENCRYPTED: + priv->ieee->drop_unencrypted = value; + break; + + case IPW_PARAM_PRIVACY_INVOKED: + priv->ieee->privacy_invoked = value; + break; + + case IPW_PARAM_AUTH_ALGS: + ret = ipw_wpa_set_auth_algs(priv, value); + break; + + case IPW_PARAM_IEEE_802_1X: + priv->ieee->ieee802_1x = value; + break; + + default: + IPW_ERROR("%s: Unknown WPA param: %d\n", dev->name, name); + ret = -EOPNOTSUPP; + } + + return ret; +} + +static int ipw_wpa_mlme(struct net_device *dev, int command, int reason) +{ + struct ipw_priv *priv = ieee80211_priv(dev); + int ret = 0; + + switch (command) { + case IPW_MLME_STA_DEAUTH: + // silently ignore + break; + + case IPW_MLME_STA_DISASSOC: + ipw_disassociate(priv); + break; + + default: + IPW_ERROR("%s: Unknown MLME request: %d\n", dev->name, command); + ret = -EOPNOTSUPP; + } + + return ret; +} + +static int ipw_set_rsn_capa(struct ipw_priv *priv, + char *capabilities, int length) +{ + struct host_cmd cmd = { + .cmd = IPW_CMD_RSN_CAPABILITIES, + .len = length, + }; + + IPW_DEBUG_HC("HOST_CMD_RSN_CAPABILITIES\n"); + + memcpy(&cmd.param, capabilities, length); + if (ipw_send_cmd(priv, &cmd)) { + IPW_ERROR("failed to send HOST_CMD_RSN_CAPABILITIES command\n"); + return -1; + } + return 0; +} + +void ipw_wpa_assoc_frame(struct ipw_priv *priv, char *wpa_ie, int wpa_ie_len) +{ + /* make sure WPA is enabled */ + ipw_wpa_enable(priv, 1); + + if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) + ipw_disassociate(priv); +} + +static int ipw_wpa_set_wpa_ie(struct net_device *dev, + struct ipw_param *param, int plen) +{ + struct ipw_priv *priv = ieee80211_priv(dev); + struct ieee80211_device *ieee = priv->ieee; + u8 *buf; + + if (!ieee->wpa_enabled) + return -EOPNOTSUPP; + + if (param->u.wpa_ie.len > MAX_WPA_IE_LEN || + (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL)) + return -EINVAL; + + if (param->u.wpa_ie.len) { + buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + + memcpy(buf, param->u.wpa_ie.data, param->u.wpa_ie.len); + kfree(ieee->wpa_ie); + ieee->wpa_ie = buf; + ieee->wpa_ie_len = param->u.wpa_ie.len; + } else { + kfree(ieee->wpa_ie); + ieee->wpa_ie = NULL; + ieee->wpa_ie_len = 0; + } + + ipw_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len); + return 0; +} + +/* implementation borrowed from hostap driver */ + +static int ipw_wpa_set_encryption(struct net_device *dev, + struct ipw_param *param, int param_len) +{ + int ret = 0; + struct ipw_priv *priv = ieee80211_priv(dev); + struct ieee80211_device *ieee = priv->ieee; + struct ieee80211_crypto_ops *ops; + struct ieee80211_crypt_data **crypt; + + struct ieee80211_security sec = { + .flags = 0, + }; + + param->u.crypt.err = 0; + param->u.crypt.alg[IPW_CRYPT_ALG_NAME_LEN - 1] = '\0'; + + if (param_len != + (int)((char *)param->u.crypt.key - (char *)param) + + param->u.crypt.key_len) { + IPW_DEBUG_INFO("Len mismatch %d, %d\n", param_len, + param->u.crypt.key_len); + return -EINVAL; + } + if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && + param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && + param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { + if (param->u.crypt.idx >= WEP_KEYS) + return -EINVAL; + crypt = &ieee->crypt[param->u.crypt.idx]; + } else { + return -EINVAL; + } + + if (strcmp(param->u.crypt.alg, "none") == 0) { + if (crypt) { + sec.enabled = 0; + sec.level = SEC_LEVEL_0; + sec.flags |= SEC_ENABLED | SEC_LEVEL; + ieee80211_crypt_delayed_deinit(ieee, crypt); + } + goto done; + } + sec.enabled = 1; + sec.flags |= SEC_ENABLED; + + ops = ieee80211_get_crypto_ops(param->u.crypt.alg); + if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) { + request_module("ieee80211_crypt_wep"); + ops = ieee80211_get_crypto_ops(param->u.crypt.alg); + } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) { + request_module("ieee80211_crypt_tkip"); + ops = ieee80211_get_crypto_ops(param->u.crypt.alg); + } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) { + request_module("ieee80211_crypt_ccmp"); + ops = ieee80211_get_crypto_ops(param->u.crypt.alg); + } + if (ops == NULL) { + IPW_DEBUG_INFO("%s: unknown crypto alg '%s'\n", + dev->name, param->u.crypt.alg); + param->u.crypt.err = IPW_CRYPT_ERR_UNKNOWN_ALG; + ret = -EINVAL; + goto done; + } + + if (*crypt == NULL || (*crypt)->ops != ops) { + struct ieee80211_crypt_data *new_crypt; + + ieee80211_crypt_delayed_deinit(ieee, crypt); + + new_crypt = (struct ieee80211_crypt_data *) + kmalloc(sizeof(*new_crypt), GFP_KERNEL); + if (new_crypt == NULL) { + ret = -ENOMEM; + goto done; + } + memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data)); + new_crypt->ops = ops; + if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) + new_crypt->priv = + new_crypt->ops->init(param->u.crypt.idx); + + if (new_crypt->priv == NULL) { + kfree(new_crypt); + param->u.crypt.err = IPW_CRYPT_ERR_CRYPT_INIT_FAILED; + ret = -EINVAL; + goto done; + } + + *crypt = new_crypt; + } + + if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key && + (*crypt)->ops->set_key(param->u.crypt.key, + param->u.crypt.key_len, param->u.crypt.seq, + (*crypt)->priv) < 0) { + IPW_DEBUG_INFO("%s: key setting failed\n", dev->name); + param->u.crypt.err = IPW_CRYPT_ERR_KEY_SET_FAILED; + ret = -EINVAL; + goto done; + } + + if (param->u.crypt.set_tx) { + ieee->tx_keyidx = param->u.crypt.idx; + sec.active_key = param->u.crypt.idx; + sec.flags |= SEC_ACTIVE_KEY; + } + + if (ops->name != NULL) { + if (strcmp(ops->name, "WEP") == 0) { + memcpy(sec.keys[param->u.crypt.idx], + param->u.crypt.key, param->u.crypt.key_len); + sec.key_sizes[param->u.crypt.idx] = + param->u.crypt.key_len; + sec.flags |= (1 << param->u.crypt.idx); + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_1; + } else if (strcmp(ops->name, "TKIP") == 0) { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_2; + } else if (strcmp(ops->name, "CCMP") == 0) { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_3; + } + } + done: + if (ieee->set_security) + ieee->set_security(ieee->dev, &sec); + + /* Do not reset port if card is in Managed mode since resetting will + * generate new IEEE 802.11 authentication which may end up in looping + * with IEEE 802.1X. If your hardware requires a reset after WEP + * configuration (for example... Prism2), implement the reset_port in + * the callbacks structures used to initialize the 802.11 stack. */ + if (ieee->reset_on_keychange && + ieee->iw_mode != IW_MODE_INFRA && + ieee->reset_port && ieee->reset_port(dev)) { + IPW_DEBUG_INFO("%s: reset_port failed\n", dev->name); + param->u.crypt.err = IPW_CRYPT_ERR_CARD_CONF_FAILED; + return -EINVAL; + } + + return ret; +} + +static int ipw_wpa_supplicant(struct net_device *dev, struct iw_point *p) +{ + struct ipw_param *param; + int ret = 0; + + IPW_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length); + + if (p->length < sizeof(struct ipw_param) || !p->pointer) + return -EINVAL; + + param = (struct ipw_param *)kmalloc(p->length, GFP_KERNEL); + if (param == NULL) + return -ENOMEM; + + if (copy_from_user(param, p->pointer, p->length)) { + kfree(param); + return -EFAULT; + } + + switch (param->cmd) { + + case IPW_CMD_SET_WPA_PARAM: + ret = ipw_wpa_set_param(dev, param->u.wpa_param.name, + param->u.wpa_param.value); + break; + + case IPW_CMD_SET_WPA_IE: + ret = ipw_wpa_set_wpa_ie(dev, param, p->length); + break; + + case IPW_CMD_SET_ENCRYPTION: + ret = ipw_wpa_set_encryption(dev, param, p->length); + break; + + case IPW_CMD_MLME: + ret = ipw_wpa_mlme(dev, param->u.mlme.command, + param->u.mlme.reason_code); + break; + + default: + IPW_ERROR("%s: Unknown WPA supplicant request: %d\n", + dev->name, param->cmd); + ret = -EOPNOTSUPP; + } + + if (ret == 0 && copy_to_user(p->pointer, param, p->length)) + ret = -EFAULT; + + kfree(param); + return ret; +} +#endif /* CONFIG_IEEE80211_WPA */ + +static int ipw_associate_network(struct ipw_priv *priv, + struct ieee80211_network *network, + struct ipw_supported_rates *rates, int roaming) +{ + int err; + + if (priv->config & CFG_FIXED_RATE) + ipw_set_fixed_rate(priv, network); + + if (!(priv->config & CFG_STATIC_ESSID)) { + priv->essid_len = min(network->ssid_len, + (u8) IW_ESSID_MAX_SIZE); + memcpy(priv->essid, network->ssid, priv->essid_len); + } + + network->last_associate = jiffies; + + memset(&priv->assoc_request, 0, sizeof(priv->assoc_request)); + priv->assoc_request.channel = network->channel; + if ((priv->capability & CAP_PRIVACY_ON) && + (priv->capability & CAP_SHARED_KEY)) { + priv->assoc_request.auth_type = AUTH_SHARED_KEY; + priv->assoc_request.auth_key = priv->sec.active_key; + } else { + priv->assoc_request.auth_type = AUTH_OPEN; + priv->assoc_request.auth_key = 0; + } + + if (priv->capability & CAP_PRIVACY_ON) + ipw_send_wep_keys(priv); + +#ifdef CONFIG_IEEE80211_WPA + if (priv->ieee->wpa_enabled) { + priv->assoc_request.policy_support = 0x02; /* RSN active */ + ipw_set_rsn_capa(priv, priv->ieee->wpa_ie, + priv->ieee->wpa_ie_len); + } +#endif + + /* + * It is valid for our ieee device to support multiple modes, but + * when it comes to associating to a given network we have to choose + * just one mode. + */ + if (network->mode & priv->ieee->mode & IEEE_A) + priv->assoc_request.ieee_mode = IPW_A_MODE; + else if (network->mode & priv->ieee->mode & IEEE_G) + priv->assoc_request.ieee_mode = IPW_G_MODE; + else if (network->mode & priv->ieee->mode & IEEE_B) + priv->assoc_request.ieee_mode = IPW_B_MODE; + + priv->assoc_request.capability = network->capability; + if ((network->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) + && !(priv->config & CFG_PREAMBLE_LONG)) { + priv->assoc_request.preamble_length = DCT_FLAG_SHORT_PREAMBLE; + } else { + priv->assoc_request.preamble_length = DCT_FLAG_LONG_PREAMBLE; + + /* Clear the short preamble if we won't be supporting it */ + priv->assoc_request.capability &= + ~WLAN_CAPABILITY_SHORT_PREAMBLE; + } + + IPW_DEBUG_ASSOC("%sssocation attempt: '%s', channel %d, " + "802.11%c [%d], %s[:%s], enc=%s%s%s%c%c\n", + roaming ? "Rea" : "A", + escape_essid(priv->essid, priv->essid_len), + network->channel, + ipw_modes[priv->assoc_request.ieee_mode], + rates->num_rates, + (priv->assoc_request.preamble_length == + DCT_FLAG_LONG_PREAMBLE) ? "long" : "short", + network->capability & + WLAN_CAPABILITY_SHORT_PREAMBLE ? "short" : "long", + priv->capability & CAP_PRIVACY_ON ? "on " : "off", + priv->capability & CAP_PRIVACY_ON ? + (priv->capability & CAP_SHARED_KEY ? "(shared)" : + "(open)") : "", + priv->capability & CAP_PRIVACY_ON ? " key=" : "", + priv->capability & CAP_PRIVACY_ON ? + '1' + priv->sec.active_key : '.', + priv->capability & CAP_PRIVACY_ON ? '.' : ' '); + + priv->assoc_request.beacon_interval = network->beacon_interval; + if ((priv->ieee->iw_mode == IW_MODE_ADHOC) && + (network->time_stamp[0] == 0) && (network->time_stamp[1] == 0)) { + priv->assoc_request.assoc_type = HC_IBSS_START; + priv->assoc_request.assoc_tsf_msw = 0; + priv->assoc_request.assoc_tsf_lsw = 0; + } else { + if (unlikely(roaming)) + priv->assoc_request.assoc_type = HC_REASSOCIATE; + else + priv->assoc_request.assoc_type = HC_ASSOCIATE; + priv->assoc_request.assoc_tsf_msw = network->time_stamp[1]; + priv->assoc_request.assoc_tsf_lsw = network->time_stamp[0]; + } + + memcpy(&priv->assoc_request.bssid, network->bssid, ETH_ALEN); + + if (priv->ieee->iw_mode == IW_MODE_ADHOC) { + memset(&priv->assoc_request.dest, 0xFF, ETH_ALEN); + priv->assoc_request.atim_window = network->atim_window; + } else { + memcpy(&priv->assoc_request.dest, network->bssid, ETH_ALEN); + priv->assoc_request.atim_window = 0; + } + + priv->assoc_request.listen_interval = network->listen_interval; + + err = ipw_send_ssid(priv, priv->essid, priv->essid_len); + if (err) { + IPW_DEBUG_HC("Attempt to send SSID command failed.\n"); + return err; + } + + rates->ieee_mode = priv->assoc_request.ieee_mode; + rates->purpose = IPW_RATE_CONNECT; + ipw_send_supported_rates(priv, rates); + + if (priv->assoc_request.ieee_mode == IPW_G_MODE) + priv->sys_config.dot11g_auto_detection = 1; + else + priv->sys_config.dot11g_auto_detection = 0; + err = ipw_send_system_config(priv, &priv->sys_config); + if (err) { + IPW_DEBUG_HC("Attempt to send sys config command failed.\n"); + return err; + } + + IPW_DEBUG_ASSOC("Association sensitivity: %d\n", network->stats.rssi); + err = ipw_set_sensitivity(priv, network->stats.rssi + IPW_RSSI_TO_DBM); + if (err) { + IPW_DEBUG_HC("Attempt to send associate command failed.\n"); + return err; + } + + /* + * If preemption is enabled, it is possible for the association + * to complete before we return from ipw_send_associate. Therefore + * we have to be sure and update our priviate data first. + */ + priv->channel = network->channel; + memcpy(priv->bssid, network->bssid, ETH_ALEN); + priv->status |= STATUS_ASSOCIATING; + priv->status &= ~STATUS_SECURITY_UPDATED; + + priv->assoc_network = network; + + err = ipw_send_associate(priv, &priv->assoc_request); + if (err) { IPW_DEBUG_HC("Attempt to send associate command failed.\n"); return err; } @@ -4899,6 +5628,32 @@ static inline void ipw_handle_data_packet(struct ipw_priv *priv, rxb->skb = NULL; } +static inline int is_network_packet(struct ipw_priv *priv, + struct ieee80211_hdr_4addr *header) +{ + /* Filter incoming packets to determine if they are targetted toward + * this network, discarding packets coming from ourselves */ + switch (priv->ieee->iw_mode) { + case IW_MODE_ADHOC: + if (is_broadcast_ether_addr(header->addr1) || + is_multicast_ether_addr(header->addr1)) + return !memcmp(header->addr3, priv->bssid, ETH_ALEN); + else + return memcmp(header->addr1, priv->net_dev->dev_addr, + ETH_ALEN); + break; + case IW_MODE_INFRA: + if (is_broadcast_ether_addr(header->addr3) || + is_multicast_ether_addr(header->addr3)) + return !memcmp(header->addr1, priv->bssid, ETH_ALEN); + else + return memcmp(header->addr3, priv->net_dev->dev_addr, + ETH_ALEN); + break; + } + return 1; +} + /* * Main entry function for recieving a packet with 80211 headers. This * should be called when ever the FW has notified us that there is a new @@ -4962,7 +5717,7 @@ static void ipw_rx(struct ipw_priv *priv) priv->rx_packets++; -#ifdef CONFIG_IPW_PROMISC +#ifdef CONFIG_IPW_MONITOR if (priv->ieee->iw_mode == IW_MODE_MONITOR) { ipw_handle_data_packet(priv, rxb, &stats); @@ -4979,35 +5734,9 @@ static void ipw_rx(struct ipw_priv *priv) * correctly -- we should probably use the * frame control of the packet and disregard * the current iw_mode */ - switch (priv->ieee->iw_mode) { - case IW_MODE_ADHOC: - network_packet = - !memcmp(header->addr1, - priv->net_dev->dev_addr, - ETH_ALEN) || - !memcmp(header->addr3, - priv->bssid, ETH_ALEN) || - is_broadcast_ether_addr(header-> - addr1) - || is_multicast_ether_addr(header-> - addr1); - break; - - case IW_MODE_INFRA: - default: - network_packet = - !memcmp(header->addr3, - priv->bssid, ETH_ALEN) || - !memcmp(header->addr1, - priv->net_dev->dev_addr, - ETH_ALEN) || - is_broadcast_ether_addr(header-> - addr1) - || is_multicast_ether_addr(header-> - addr1); - break; - } + network_packet = + is_network_packet(priv, header); if (network_packet && priv->assoc_network) { priv->assoc_network->stats.rssi = stats.rssi; @@ -5108,130 +5837,6 @@ static void ipw_rx(struct ipw_priv *priv) ipw_rx_queue_restock(priv); } -static void ipw_abort_scan(struct ipw_priv *priv) -{ - int err; - - if (priv->status & STATUS_SCAN_ABORTING) { - IPW_DEBUG_HC("Ignoring concurrent scan abort request.\n"); - return; - } - priv->status |= STATUS_SCAN_ABORTING; - - err = ipw_send_scan_abort(priv); - if (err) - IPW_DEBUG_HC("Request to abort scan failed.\n"); -} - -static int ipw_request_scan(struct ipw_priv *priv) -{ - struct ipw_scan_request_ext scan; - int channel_index = 0; - int i, err, scan_type; - - if (priv->status & STATUS_EXIT_PENDING) { - IPW_DEBUG_SCAN("Aborting scan due to device shutdown\n"); - priv->status |= STATUS_SCAN_PENDING; - return 0; - } - - if (priv->status & STATUS_SCANNING) { - IPW_DEBUG_HC("Concurrent scan requested. Aborting first.\n"); - priv->status |= STATUS_SCAN_PENDING; - ipw_abort_scan(priv); - return 0; - } - - if (priv->status & STATUS_SCAN_ABORTING) { - IPW_DEBUG_HC("Scan request while abort pending. Queuing.\n"); - priv->status |= STATUS_SCAN_PENDING; - return 0; - } - - if (priv->status & STATUS_RF_KILL_MASK) { - IPW_DEBUG_HC("Aborting scan due to RF Kill activation\n"); - priv->status |= STATUS_SCAN_PENDING; - return 0; - } - - memset(&scan, 0, sizeof(scan)); - - scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = 20; - scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] = 20; - scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = 20; - - scan.full_scan_index = ieee80211_get_scans(priv->ieee); - /* If we are roaming, then make this a directed scan for the current - * network. Otherwise, ensure that every other scan is a fast - * channel hop scan */ - if ((priv->status & STATUS_ROAMING) - || (!(priv->status & STATUS_ASSOCIATED) - && (priv->config & CFG_STATIC_ESSID) - && (scan.full_scan_index % 2))) { - err = ipw_send_ssid(priv, priv->essid, priv->essid_len); - if (err) { - IPW_DEBUG_HC("Attempt to send SSID command failed.\n"); - return err; - } - - scan_type = IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN; - } else { - scan_type = IPW_SCAN_ACTIVE_BROADCAST_SCAN; - } - - if (priv->ieee->freq_band & IEEE80211_52GHZ_BAND) { - int start = channel_index; - for (i = 0; i < MAX_A_CHANNELS; i++) { - if (band_a_active_channel[i] == 0) - break; - if ((priv->status & STATUS_ASSOCIATED) && - band_a_active_channel[i] == priv->channel) - continue; - channel_index++; - scan.channels_list[channel_index] = - band_a_active_channel[i]; - ipw_set_scan_type(&scan, channel_index, scan_type); - } - - if (start != channel_index) { - scan.channels_list[start] = (u8) (IPW_A_MODE << 6) | - (channel_index - start); - channel_index++; - } - } - - if (priv->ieee->freq_band & IEEE80211_24GHZ_BAND) { - int start = channel_index; - for (i = 0; i < MAX_B_CHANNELS; i++) { - if (band_b_active_channel[i] == 0) - break; - if ((priv->status & STATUS_ASSOCIATED) && - band_b_active_channel[i] == priv->channel) - continue; - channel_index++; - scan.channels_list[channel_index] = - band_b_active_channel[i]; - ipw_set_scan_type(&scan, channel_index, scan_type); - } - - if (start != channel_index) { - scan.channels_list[start] = (u8) (IPW_B_MODE << 6) | - (channel_index - start); - } - } - - err = ipw_send_scan_request_ext(priv, &scan); - if (err) { - IPW_DEBUG_HC("Sending scan command failed: %08X\n", err); - return -EIO; - } - - priv->status |= STATUS_SCANNING; - priv->status &= ~STATUS_SCAN_PENDING; - - return 0; -} - /* * This file defines the Wireless Extension handlers. It does not * define any methods of hardware manipulation and relies on the @@ -5357,7 +5962,7 @@ static int ipw_wx_set_mode(struct net_device *dev, return 0; switch (wrqu->mode) { -#ifdef CONFIG_IPW_PROMISC +#ifdef CONFIG_IPW_MONITOR case IW_MODE_MONITOR: #endif case IW_MODE_ADHOC: @@ -5370,13 +5975,13 @@ static int ipw_wx_set_mode(struct net_device *dev, return -EINVAL; } -#ifdef CONFIG_IPW_PROMISC +#ifdef CONFIG_IPW_MONITOR if (priv->ieee->iw_mode == IW_MODE_MONITOR) priv->net_dev->type = ARPHRD_ETHER; if (wrqu->mode == IW_MODE_MONITOR) priv->net_dev->type = ARPHRD_IEEE80211; -#endif /* CONFIG_IPW_PROMISC */ +#endif /* CONFIG_IPW_MONITOR */ #ifdef CONFIG_PM /* Free the existing firmware and reset the fw_loaded @@ -5680,8 +6285,111 @@ static int ipw_wx_set_rate(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { - IPW_DEBUG_WX("0x%p, 0x%p, 0x%p\n", dev, info, wrqu); - return -EOPNOTSUPP; + /* TODO: We should use semaphores or locks for access to priv */ + struct ipw_priv *priv = ieee80211_priv(dev); + u32 target_rate = wrqu->bitrate.value; + u32 fixed, mask; + + /* value = -1, fixed = 0 means auto only, so we should use all rates offered by AP */ + /* value = X, fixed = 1 means only rate X */ + /* value = X, fixed = 0 means all rates lower equal X */ + + if (target_rate == -1) { + fixed = 0; + mask = IEEE80211_DEFAULT_RATES_MASK; + /* Now we should reassociate */ + goto apply; + } + + mask = 0; + fixed = wrqu->bitrate.fixed; + + if (target_rate == 1000000 || !fixed) + mask |= IEEE80211_CCK_RATE_1MB_MASK; + if (target_rate == 1000000) + goto apply; + + if (target_rate == 2000000 || !fixed) + mask |= IEEE80211_CCK_RATE_2MB_MASK; + if (target_rate == 2000000) + goto apply; + + if (target_rate == 5500000 || !fixed) + mask |= IEEE80211_CCK_RATE_5MB_MASK; + if (target_rate == 5500000) + goto apply; + + if (target_rate == 6000000 || !fixed) + mask |= IEEE80211_OFDM_RATE_6MB_MASK; + if (target_rate == 6000000) + goto apply; + + if (target_rate == 9000000 || !fixed) + mask |= IEEE80211_OFDM_RATE_9MB_MASK; + if (target_rate == 9000000) + goto apply; + + if (target_rate == 11000000 || !fixed) + mask |= IEEE80211_CCK_RATE_11MB_MASK; + if (target_rate == 11000000) + goto apply; + + if (target_rate == 12000000 || !fixed) + mask |= IEEE80211_OFDM_RATE_12MB_MASK; + if (target_rate == 12000000) + goto apply; + + if (target_rate == 18000000 || !fixed) + mask |= IEEE80211_OFDM_RATE_18MB_MASK; + if (target_rate == 18000000) + goto apply; + + if (target_rate == 24000000 || !fixed) + mask |= IEEE80211_OFDM_RATE_24MB_MASK; + if (target_rate == 24000000) + goto apply; + + if (target_rate == 36000000 || !fixed) + mask |= IEEE80211_OFDM_RATE_36MB_MASK; + if (target_rate == 36000000) + goto apply; + + if (target_rate == 48000000 || !fixed) + mask |= IEEE80211_OFDM_RATE_48MB_MASK; + if (target_rate == 48000000) + goto apply; + + if (target_rate == 54000000 || !fixed) + mask |= IEEE80211_OFDM_RATE_54MB_MASK; + if (target_rate == 54000000) + goto apply; + + IPW_DEBUG_WX("invalid rate specified, returning error\n"); + return -EINVAL; + + apply: + IPW_DEBUG_WX("Setting rate mask to 0x%08X [%s]\n", + mask, fixed ? "fixed" : "sub-rates"); + + if (mask == IEEE80211_DEFAULT_RATES_MASK) + priv->config &= ~CFG_FIXED_RATE; + else + priv->config |= CFG_FIXED_RATE; + + if (priv->rates_mask != mask) { + priv->rates_mask = mask; + /* If we are already associated or are currently trying to + * associate, disassociate and try again */ + if ((priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING))) { + IPW_DEBUG_ASSOC("Disassociating due to RATE change.\n"); + ipw_disassociate(priv); + } + } else { + /* We are not yet associated, so kick one off... */ + ipw_associate(priv); + } + + return 0; } static int ipw_wx_get_rate(struct net_device *dev, @@ -5888,7 +6596,6 @@ static int ipw_wx_set_power(struct net_device *dev, IPW_DEBUG_WX("failed setting power mode.\n"); return err; } - IPW_DEBUG_WX("SET Power Management Mode -> off\n"); return 0; @@ -6069,37 +6776,30 @@ static int ipw_wx_get_wireless_mode(struct net_device *dev, { struct ipw_priv *priv = ieee80211_priv(dev); - switch (priv->ieee->freq_band) { - case IEEE80211_24GHZ_BAND: - switch (priv->ieee->modulation) { - case IEEE80211_CCK_MODULATION: - strncpy(extra, "802.11b (2)", MAX_WX_STRING); - break; - case IEEE80211_OFDM_MODULATION: - strncpy(extra, "802.11g (4)", MAX_WX_STRING); - break; - default: - strncpy(extra, "802.11bg (6)", MAX_WX_STRING); - break; - } - break; - - case IEEE80211_52GHZ_BAND: + switch (priv->ieee->mode) { + case IEEE_A: strncpy(extra, "802.11a (1)", MAX_WX_STRING); break; - - default: /* Mixed Band */ - switch (priv->ieee->modulation) { - case IEEE80211_CCK_MODULATION: - strncpy(extra, "802.11ab (3)", MAX_WX_STRING); - break; - case IEEE80211_OFDM_MODULATION: - strncpy(extra, "802.11ag (5)", MAX_WX_STRING); - break; - default: - strncpy(extra, "802.11abg (7)", MAX_WX_STRING); - break; - } + case IEEE_B: + strncpy(extra, "802.11b (2)", MAX_WX_STRING); + break; + case IEEE_A | IEEE_B: + strncpy(extra, "802.11ab (3)", MAX_WX_STRING); + break; + case IEEE_G: + strncpy(extra, "802.11g (4)", MAX_WX_STRING); + break; + case IEEE_A | IEEE_G: + strncpy(extra, "802.11ag (5)", MAX_WX_STRING); + break; + case IEEE_B | IEEE_G: + strncpy(extra, "802.11bg (6)", MAX_WX_STRING); + break; + case IEEE_A | IEEE_B | IEEE_G: + strncpy(extra, "802.11abg (7)", MAX_WX_STRING); + break; + default: + strncpy(extra, "unknown", MAX_WX_STRING); break; } @@ -6110,8 +6810,55 @@ static int ipw_wx_get_wireless_mode(struct net_device *dev, return 0; } -#ifdef CONFIG_IPW_PROMISC -static int ipw_wx_set_promisc(struct net_device *dev, +static int ipw_wx_set_preamble(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ipw_priv *priv = ieee80211_priv(dev); + int mode = *(int *)extra; + + /* Switching from SHORT -> LONG requires a disassociation */ + if (mode == 1) { + if (!(priv->config & CFG_PREAMBLE_LONG)) { + priv->config |= CFG_PREAMBLE_LONG; + if (priv->status & + (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { + IPW_DEBUG_ASSOC + ("Disassociating due to preamble " + "change.\n"); + ipw_disassociate(priv); + } + } + goto done; + } + + if (mode == 0) { + priv->config &= ~CFG_PREAMBLE_LONG; + goto done; + } + + return -EINVAL; + + done: + return 0; +} + +static int ipw_wx_get_preamble(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ipw_priv *priv = ieee80211_priv(dev); + + if (priv->config & CFG_PREAMBLE_LONG) + snprintf(wrqu->name, IFNAMSIZ, "long (1)"); + else + snprintf(wrqu->name, IFNAMSIZ, "auto (0)"); + + return 0; +} + +#ifdef CONFIG_IPW_MONITOR +static int ipw_wx_set_monitor(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { @@ -6119,7 +6866,7 @@ static int ipw_wx_set_promisc(struct net_device *dev, int *parms = (int *)extra; int enable = (parms[0] > 0); - IPW_DEBUG_WX("SET PROMISC: %d %d\n", enable, parms[1]); + IPW_DEBUG_WX("SET MONITOR: %d %d\n", enable, parms[1]); if (enable) { if (priv->ieee->iw_mode != IW_MODE_MONITOR) { priv->net_dev->type = ARPHRD_IEEE80211; @@ -6145,47 +6892,49 @@ static int ipw_wx_reset(struct net_device *dev, ipw_adapter_restart(priv); return 0; } -#endif // CONFIG_IPW_PROMISC +#endif // CONFIG_IPW_MONITOR /* Rebase the WE IOCTLs to zero for the handler array */ #define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT] static iw_handler ipw_wx_handlers[] = { - IW_IOCTL(SIOCGIWNAME) = ipw_wx_get_name, - IW_IOCTL(SIOCSIWFREQ) = ipw_wx_set_freq, - IW_IOCTL(SIOCGIWFREQ) = ipw_wx_get_freq, - IW_IOCTL(SIOCSIWMODE) = ipw_wx_set_mode, - IW_IOCTL(SIOCGIWMODE) = ipw_wx_get_mode, - IW_IOCTL(SIOCGIWRANGE) = ipw_wx_get_range, - IW_IOCTL(SIOCSIWAP) = ipw_wx_set_wap, - IW_IOCTL(SIOCGIWAP) = ipw_wx_get_wap, - IW_IOCTL(SIOCSIWSCAN) = ipw_wx_set_scan, - IW_IOCTL(SIOCGIWSCAN) = ipw_wx_get_scan, - IW_IOCTL(SIOCSIWESSID) = ipw_wx_set_essid, - IW_IOCTL(SIOCGIWESSID) = ipw_wx_get_essid, - IW_IOCTL(SIOCSIWNICKN) = ipw_wx_set_nick, - IW_IOCTL(SIOCGIWNICKN) = ipw_wx_get_nick, - IW_IOCTL(SIOCSIWRATE) = ipw_wx_set_rate, - IW_IOCTL(SIOCGIWRATE) = ipw_wx_get_rate, - IW_IOCTL(SIOCSIWRTS) = ipw_wx_set_rts, - IW_IOCTL(SIOCGIWRTS) = ipw_wx_get_rts, - IW_IOCTL(SIOCSIWFRAG) = ipw_wx_set_frag, - IW_IOCTL(SIOCGIWFRAG) = ipw_wx_get_frag, - IW_IOCTL(SIOCSIWTXPOW) = ipw_wx_set_txpow, - IW_IOCTL(SIOCGIWTXPOW) = ipw_wx_get_txpow, - IW_IOCTL(SIOCSIWRETRY) = ipw_wx_set_retry, - IW_IOCTL(SIOCGIWRETRY) = ipw_wx_get_retry, - IW_IOCTL(SIOCSIWENCODE) = ipw_wx_set_encode, - IW_IOCTL(SIOCGIWENCODE) = ipw_wx_get_encode, - IW_IOCTL(SIOCSIWPOWER) = ipw_wx_set_power, - IW_IOCTL(SIOCGIWPOWER) = ipw_wx_get_power, + IW_IOCTL(SIOCGIWNAME) = ipw_wx_get_name, + IW_IOCTL(SIOCSIWFREQ) = ipw_wx_set_freq, + IW_IOCTL(SIOCGIWFREQ) = ipw_wx_get_freq, + IW_IOCTL(SIOCSIWMODE) = ipw_wx_set_mode, + IW_IOCTL(SIOCGIWMODE) = ipw_wx_get_mode, + IW_IOCTL(SIOCGIWRANGE) = ipw_wx_get_range, + IW_IOCTL(SIOCSIWAP) = ipw_wx_set_wap, + IW_IOCTL(SIOCGIWAP) = ipw_wx_get_wap, + IW_IOCTL(SIOCSIWSCAN) = ipw_wx_set_scan, + IW_IOCTL(SIOCGIWSCAN) = ipw_wx_get_scan, + IW_IOCTL(SIOCSIWESSID) = ipw_wx_set_essid, + IW_IOCTL(SIOCGIWESSID) = ipw_wx_get_essid, + IW_IOCTL(SIOCSIWNICKN) = ipw_wx_set_nick, + IW_IOCTL(SIOCGIWNICKN) = ipw_wx_get_nick, + IW_IOCTL(SIOCSIWRATE) = ipw_wx_set_rate, + IW_IOCTL(SIOCGIWRATE) = ipw_wx_get_rate, + IW_IOCTL(SIOCSIWRTS) = ipw_wx_set_rts, + IW_IOCTL(SIOCGIWRTS) = ipw_wx_get_rts, + IW_IOCTL(SIOCSIWFRAG) = ipw_wx_set_frag, + IW_IOCTL(SIOCGIWFRAG) = ipw_wx_get_frag, + IW_IOCTL(SIOCSIWTXPOW) = ipw_wx_set_txpow, + IW_IOCTL(SIOCGIWTXPOW) = ipw_wx_get_txpow, + IW_IOCTL(SIOCSIWRETRY) = ipw_wx_set_retry, + IW_IOCTL(SIOCGIWRETRY) = ipw_wx_get_retry, + IW_IOCTL(SIOCSIWENCODE) = ipw_wx_set_encode, + IW_IOCTL(SIOCGIWENCODE) = ipw_wx_get_encode, + IW_IOCTL(SIOCSIWPOWER) = ipw_wx_set_power, + IW_IOCTL(SIOCGIWPOWER) = ipw_wx_get_power, }; #define IPW_PRIV_SET_POWER SIOCIWFIRSTPRIV #define IPW_PRIV_GET_POWER SIOCIWFIRSTPRIV+1 #define IPW_PRIV_SET_MODE SIOCIWFIRSTPRIV+2 #define IPW_PRIV_GET_MODE SIOCIWFIRSTPRIV+3 -#define IPW_PRIV_SET_PROMISC SIOCIWFIRSTPRIV+4 -#define IPW_PRIV_RESET SIOCIWFIRSTPRIV+5 +#define IPW_PRIV_SET_PREAMBLE SIOCIWFIRSTPRIV+4 +#define IPW_PRIV_GET_PREAMBLE SIOCIWFIRSTPRIV+5 +#define IPW_PRIV_SET_MONITOR SIOCIWFIRSTPRIV+6 +#define IPW_PRIV_RESET SIOCIWFIRSTPRIV+7 static struct iw_priv_args ipw_priv_args[] = { { @@ -6204,14 +6953,22 @@ static struct iw_priv_args ipw_priv_args[] = { .cmd = IPW_PRIV_GET_MODE, .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, .name = "get_mode"}, -#ifdef CONFIG_IPW_PROMISC { - IPW_PRIV_SET_PROMISC, + .cmd = IPW_PRIV_SET_PREAMBLE, + .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + .name = "set_preamble"}, + { + .cmd = IPW_PRIV_GET_PREAMBLE, + .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, + .name = "get_preamble"}, +#ifdef CONFIG_IPW_MONITOR + { + IPW_PRIV_SET_MONITOR, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "monitor"}, { IPW_PRIV_RESET, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 0, 0, "reset"}, -#endif /* CONFIG_IPW_PROMISC */ +#endif /* CONFIG_IPW_MONITOR */ }; static iw_handler ipw_priv_handler[] = { @@ -6219,19 +6976,21 @@ static iw_handler ipw_priv_handler[] = { ipw_wx_get_powermode, ipw_wx_set_wireless_mode, ipw_wx_get_wireless_mode, -#ifdef CONFIG_IPW_PROMISC - ipw_wx_set_promisc, + ipw_wx_set_preamble, + ipw_wx_get_preamble, +#ifdef CONFIG_IPW_MONITOR + ipw_wx_set_monitor, ipw_wx_reset, #endif }; static struct iw_handler_def ipw_wx_handler_def = { - .standard = ipw_wx_handlers, - .num_standard = ARRAY_SIZE(ipw_wx_handlers), - .num_private = ARRAY_SIZE(ipw_priv_handler), - .num_private_args = ARRAY_SIZE(ipw_priv_args), - .private = ipw_priv_handler, - .private_args = ipw_priv_args, + .standard = ipw_wx_handlers, + .num_standard = ARRAY_SIZE(ipw_wx_handlers), + .num_private = ARRAY_SIZE(ipw_priv_handler), + .num_private_args = ARRAY_SIZE(ipw_priv_args), + .private = ipw_priv_handler, + .private_args = ipw_priv_args, }; /* @@ -6246,7 +7005,7 @@ static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev) wstats = &priv->wstats; - /* if hw is disabled, then ipw2100_get_ordinal() can't be called. + /* if hw is disabled, then ipw_get_ordinal() can't be called. * ipw2100_wx_wireless_stats seems to be called before fw is * initialized. STATUS_ASSOCIATED will only be set if the hw is up * and associated; if not associcated, the values are all meaningless @@ -6384,8 +7143,8 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb) else tfd->u.data.tx_flags_ext = DCT_FLAG_EXT_MODE_OFDM; - if (priv->config & CFG_PREAMBLE) - tfd->u.data.tx_flags |= DCT_FLAG_SHORT_PREMBL; + if (priv->assoc_request.preamble_length == DCT_FLAG_SHORT_PREAMBLE) + tfd->u.data.tx_flags |= DCT_FLAG_SHORT_PREAMBLE; memcpy(&tfd->u.data.tfd.tfd_24.mchdr, hdr, hdr_len); @@ -6568,11 +7327,11 @@ static int ipw_ethtool_set_eeprom(struct net_device *dev, } static struct ethtool_ops ipw_ethtool_ops = { - .get_link = ipw_ethtool_get_link, - .get_drvinfo = ipw_ethtool_get_drvinfo, - .get_eeprom_len = ipw_ethtool_get_eeprom_len, - .get_eeprom = ipw_ethtool_get_eeprom, - .set_eeprom = ipw_ethtool_set_eeprom, + .get_link = ipw_ethtool_get_link, + .get_drvinfo = ipw_ethtool_get_drvinfo, + .get_eeprom_len = ipw_ethtool_get_eeprom_len, + .get_eeprom = ipw_ethtool_get_eeprom, + .set_eeprom = ipw_ethtool_set_eeprom, }; static irqreturn_t ipw_isr(int irq, void *data, struct pt_regs *regs) @@ -6918,6 +7677,25 @@ static void ipw_down(struct ipw_priv *priv) ipw_stop_nic(priv); } +static int ipw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ +#ifdef CONFIG_IEEE80211_WPA + struct iwreq *wrq = (struct iwreq *)rq; + int ret = -1; + switch (cmd) { + case IPW_IOCTL_WPA_SUPPLICANT: + ret = ipw_wpa_supplicant(dev, &wrq->u.data); + return ret; + + default: + return -EOPNOTSUPP; + } + +#endif /* CONFIG_IEEE80211_WPA */ + + return -EOPNOTSUPP; +} + /* Called by register_netdev() */ static int ipw_net_init(struct net_device *dev) { @@ -7065,9 +7843,6 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } /* Initialize module parameter values here */ - if (ifname) - strncpy(net_dev->name, ifname, IFNAMSIZ); - if (associate) priv->config |= CFG_ASSOCIATE; else @@ -7095,7 +7870,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) case 1: priv->ieee->iw_mode = IW_MODE_ADHOC; break; -#ifdef CONFIG_IPW_PROMISC +#ifdef CONFIG_IPW_MONITOR case 2: priv->ieee->iw_mode = IW_MODE_MONITOR; break; @@ -7164,6 +7939,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) net_dev->open = ipw_net_open; net_dev->stop = ipw_net_stop; net_dev->init = ipw_net_init; + net_dev->do_ioctl = ipw_ioctl; net_dev->get_stats = ipw_net_get_stats; net_dev->set_multicast_list = ipw_net_set_multicast_list; net_dev->set_mac_address = ipw_net_set_mac_address; @@ -7287,13 +8063,10 @@ static int ipw_pci_resume(struct pci_dev *pdev) printk(KERN_INFO "%s: Coming out of suspend...\n", dev->name); - pci_set_power_state(pdev, 0); + pci_set_power_state(pdev, PCI_D0); pci_enable_device(pdev); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - pci_restore_state(pdev, priv->pm_state); -#else pci_restore_state(pdev); -#endif + /* * Suspend/Resume resets the PCI configuration space, so we have to * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries @@ -7371,10 +8144,7 @@ MODULE_PARM_DESC(debug, "debug output mask"); module_param(channel, int, 0444); MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])"); -module_param(ifname, charp, 0444); -MODULE_PARM_DESC(ifname, "network device name (default eth%d)"); - -#ifdef CONFIG_IPW_PROMISC +#ifdef CONFIG_IPW_MONITOR module_param(mode, int, 0444); MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS,2=Monitor)"); #else diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index e9cf32bf3e3..06802796318 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -168,7 +168,8 @@ enum connection_manager_assoc_states { #define DCT_FLAG_CTS_REQUIRED 0x02 /* use short preamble */ -#define DCT_FLAG_SHORT_PREMBL 0x04 +#define DCT_FLAG_LONG_PREAMBLE 0x00 +#define DCT_FLAG_SHORT_PREAMBLE 0x04 /* RTS/CTS first */ #define DCT_FLAG_RTS_REQD 0x08 @@ -899,7 +900,7 @@ struct ipw_cmd { #define CFG_STATIC_ESSID (1<<1) /* Restrict assoc. to single SSID */ #define CFG_STATIC_BSSID (1<<2) /* Restrict assoc. to single BSSID */ #define CFG_CUSTOM_MAC (1<<3) -#define CFG_PREAMBLE (1<<4) +#define CFG_PREAMBLE_LONG (1<<4) #define CFG_ADHOC_PERSIST (1<<5) #define CFG_ASSOCIATE (1<<6) #define CFG_FIXED_RATE (1<<7) @@ -1206,12 +1207,18 @@ do { if (ipw_debug_level & (level)) \ /* * RESET Register Bit Indexes */ -#define CBD_RESET_REG_PRINCETON_RESET 0x00000001 /* Bit 0 (LSB) */ -#define CX2_RESET_REG_SW_RESET 0x00000080 /* Bit 7 */ -#define CX2_RESET_REG_MASTER_DISABLED 0x00000100 /* Bit 8 */ -#define CX2_RESET_REG_STOP_MASTER 0x00000200 /* Bit 9 */ -#define CX2_ARC_KESHET_CONFIG 0x08000000 /* Bit 27 */ -#define CX2_START_STANDBY 0x00000004 /* Bit 2 */ +#define CBD_RESET_REG_PRINCETON_RESET (1<<0) +#define CX2_START_STANDBY (1<<2) +#define CX2_ACTIVITY_LED (1<<4) +#define CX2_ASSOCIATED_LED (1<<5) +#define CX2_OFDM_LED (1<<6) +#define CX2_RESET_REG_SW_RESET (1<<7) +#define CX2_RESET_REG_MASTER_DISABLED (1<<8) +#define CX2_RESET_REG_STOP_MASTER (1<<9) +#define CX2_GATE_ODMA (1<<25) +#define CX2_GATE_IDMA (1<<26) +#define CX2_ARC_KESHET_CONFIG (1<<27) +#define CX2_GATE_ADMA (1<<29) #define CX2_CSR_CIS_UPPER_BOUND 0x00000200 #define CX2_DOMAIN_0_END 0x1000 -- cgit v1.2.3 From a613bffd3aac89bb0a8c9b7afa72af9b0ae30f0a Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Wed, 24 Aug 2005 21:43:11 -0500 Subject: Catch ipw2200 up to equivelancy with v1.0.2 Removed unneeded parenthesis around numeric constant defines Added support for iwspy Put in fix for Ad-Hoc mode not passing through all packets (thanks to KKH) Put in fix for fragmentation not working for fragment sizes between 441-464 bytes (thanks to Mohamed Abbas) Fixed #592 problem of CONFIG_IEEE80211_WPA_MODULE not including WPA support into the driver -- fixed as a result of no longer limiting WPAs inclusion Fixed #594 problem with user rates mask causing lack of association if AP mandatory rate is masked out. We now add back in as a supported rate any mandatory rate. Fixed #597 kernel oops due to calling dev_kfree_skb on an skb multiple times. Added code to control LEDs that can be controlled through the wireless NIC (vs. non-wireless HW interfaces) -- this is currently disabled by default due to reports by some users of it hanging their laptop. Added some more debug messages around fragmentation logic Added locking around STATUS_HCMD_ACTIVE to prevent re-entry race conditions Moved ipw_adapter_restart to only execute on the priv->workqueue to keep keyboard errors from occuring during adapter restart Added CFG_BACKGROUND_SCAN to easily allow people to play with background scanning implementations Modified WPA logic to send WPA IE if one is set (vs. being based on wpa_enabled) Modified scan result logic to report WPA and RSN IEs if set (vs. being based on wpa_enabled) Fixed issues with endianess compatability between the host and wireless adapter (thanks to York Liu and Yi Zhu) Fixed problem with Ad-Hoc network creation causing a firmware error if a scan was actively running (thanks to Mohamed Abbas) Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 962 +++++++++++++++++++++++++++++++---------- drivers/net/wireless/ipw2200.h | 73 ++-- 2 files changed, 773 insertions(+), 262 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index ddbee3edcd8..ea7a3dcf1da 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -32,7 +32,7 @@ #include "ipw2200.h" -#define IPW2200_VERSION "1.0.1" +#define IPW2200_VERSION "1.0.2" #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation" #define DRV_VERSION IPW2200_VERSION @@ -49,6 +49,7 @@ static int mode = 0; static u32 ipw_debug_level; static int associate = 1; static int auto_create = 1; +static int led = 0; static int disable = 0; static const char ipw_modes[] = { 'a', 'b', 'g', '?' @@ -637,6 +638,313 @@ static void ipw_init_ordinals(struct ipw_priv *priv) } +u32 ipw_register_toggle(u32 reg) +{ + reg &= ~CX2_START_STANDBY; + if (reg & CX2_GATE_ODMA) + reg &= ~CX2_GATE_ODMA; + if (reg & CX2_GATE_IDMA) + reg &= ~CX2_GATE_IDMA; + if (reg & CX2_GATE_ADMA) + reg &= ~CX2_GATE_ADMA; + return reg; +} + +/* + * LED behavior: + * - On radio ON, turn on any LEDs that require to be on during start + * - On initialization, start unassociated blink + * - On association, disable unassociated blink + * - On disassociation, start unassociated blink + * - On radio OFF, turn off any LEDs started during radio on + * + */ +#define LD_TIME_LINK_ON 300 +#define LD_TIME_LINK_OFF 2700 +#define LD_TIME_ACT_ON 250 + +void ipw_led_link_on(struct ipw_priv *priv) +{ + unsigned long flags; + u32 led; + + /* If configured to not use LEDs, or nic_type is 1, + * then we don't toggle a LINK led */ + if (priv->config & CFG_NO_LED || priv->nic_type == EEPROM_NIC_TYPE_1) + return; + + spin_lock_irqsave(&priv->lock, flags); + + if (!(priv->status & STATUS_RF_KILL_MASK) && + !(priv->status & STATUS_LED_LINK_ON)) { + IPW_DEBUG_LED("Link LED On\n"); + led = ipw_read_reg32(priv, CX2_EVENT_REG); + led |= priv->led_association_on; + + led = ipw_register_toggle(led); + + IPW_DEBUG_LED("Reg: 0x%08X\n", led); + ipw_write_reg32(priv, CX2_EVENT_REG, led); + + priv->status |= STATUS_LED_LINK_ON; + + /* If we aren't associated, schedule turning the LED off */ + if (!(priv->status & STATUS_ASSOCIATED)) + queue_delayed_work(priv->workqueue, + &priv->led_link_off, + LD_TIME_LINK_ON); + } + + spin_unlock_irqrestore(&priv->lock, flags); +} + +void ipw_led_link_off(struct ipw_priv *priv) +{ + unsigned long flags; + u32 led; + + /* If configured not to use LEDs, or nic type is 1, + * then we don't goggle the LINK led. */ + if (priv->config & CFG_NO_LED || priv->nic_type == EEPROM_NIC_TYPE_1) + return; + + spin_lock_irqsave(&priv->lock, flags); + + if (priv->status & STATUS_LED_LINK_ON) { + led = ipw_read_reg32(priv, CX2_EVENT_REG); + led &= priv->led_association_off; + led = ipw_register_toggle(led); + + IPW_DEBUG_LED("Reg: 0x%08X\n", led); + ipw_write_reg32(priv, CX2_EVENT_REG, led); + + IPW_DEBUG_LED("Link LED Off\n"); + + priv->status &= ~STATUS_LED_LINK_ON; + + /* If we aren't associated and the radio is on, schedule + * turning the LED on (blink while unassociated) */ + if (!(priv->status & STATUS_RF_KILL_MASK) && + !(priv->status & STATUS_ASSOCIATED)) + queue_delayed_work(priv->workqueue, &priv->led_link_on, + LD_TIME_LINK_OFF); + + } + + spin_unlock_irqrestore(&priv->lock, flags); +} + +void ipw_led_activity_on(struct ipw_priv *priv) +{ + unsigned long flags; + u32 led; + + if (priv->config & CFG_NO_LED) + return; + + spin_lock_irqsave(&priv->lock, flags); + + if (priv->status & STATUS_RF_KILL_MASK) { + spin_unlock_irqrestore(&priv->lock, flags); + return; + } + + if (!(priv->status & STATUS_LED_ACT_ON)) { + led = ipw_read_reg32(priv, CX2_EVENT_REG); + led |= priv->led_activity_on; + + led = ipw_register_toggle(led); + + IPW_DEBUG_LED("Reg: 0x%08X\n", led); + ipw_write_reg32(priv, CX2_EVENT_REG, led); + + IPW_DEBUG_LED("Activity LED On\n"); + + priv->status |= STATUS_LED_ACT_ON; + + queue_delayed_work(priv->workqueue, &priv->led_act_off, + LD_TIME_ACT_ON); + } else { + /* Reschedule LED off for full time period */ + cancel_delayed_work(&priv->led_act_off); + queue_delayed_work(priv->workqueue, &priv->led_act_off, + LD_TIME_ACT_ON); + } + + spin_unlock_irqrestore(&priv->lock, flags); +} + +void ipw_led_activity_off(struct ipw_priv *priv) +{ + unsigned long flags; + u32 led; + + if (priv->config & CFG_NO_LED) + return; + + spin_lock_irqsave(&priv->lock, flags); + + if (priv->status & STATUS_LED_ACT_ON) { + led = ipw_read_reg32(priv, CX2_EVENT_REG); + led &= priv->led_activity_off; + + led = ipw_register_toggle(led); + + IPW_DEBUG_LED("Reg: 0x%08X\n", led); + ipw_write_reg32(priv, CX2_EVENT_REG, led); + + IPW_DEBUG_LED("Activity LED Off\n"); + + priv->status &= ~STATUS_LED_ACT_ON; + } + + spin_unlock_irqrestore(&priv->lock, flags); +} + +void ipw_led_band_on(struct ipw_priv *priv) +{ + unsigned long flags; + u32 led; + + /* Only nic type 1 supports mode LEDs */ + if (priv->config & CFG_NO_LED || priv->nic_type != EEPROM_NIC_TYPE_1) + return; + + spin_lock_irqsave(&priv->lock, flags); + + led = ipw_read_reg32(priv, CX2_EVENT_REG); + if (priv->assoc_network->mode == IEEE_A) { + led |= priv->led_ofdm_on; + led &= priv->led_association_off; + IPW_DEBUG_LED("Mode LED On: 802.11a\n"); + } else if (priv->assoc_network->mode == IEEE_G) { + led |= priv->led_ofdm_on; + led |= priv->led_association_on; + IPW_DEBUG_LED("Mode LED On: 802.11g\n"); + } else { + led &= priv->led_ofdm_off; + led |= priv->led_association_on; + IPW_DEBUG_LED("Mode LED On: 802.11b\n"); + } + + led = ipw_register_toggle(led); + + IPW_DEBUG_LED("Reg: 0x%08X\n", led); + ipw_write_reg32(priv, CX2_EVENT_REG, led); + + spin_unlock_irqrestore(&priv->lock, flags); +} + +void ipw_led_band_off(struct ipw_priv *priv) +{ + unsigned long flags; + u32 led; + + /* Only nic type 1 supports mode LEDs */ + if (priv->config & CFG_NO_LED || priv->nic_type != EEPROM_NIC_TYPE_1) + return; + + spin_lock_irqsave(&priv->lock, flags); + + led = ipw_read_reg32(priv, CX2_EVENT_REG); + led &= priv->led_ofdm_off; + led &= priv->led_association_off; + + led = ipw_register_toggle(led); + + IPW_DEBUG_LED("Reg: 0x%08X\n", led); + ipw_write_reg32(priv, CX2_EVENT_REG, led); + + spin_unlock_irqrestore(&priv->lock, flags); +} + +void ipw_led_radio_on(struct ipw_priv *priv) +{ + ipw_led_link_on(priv); +} + +void ipw_led_radio_off(struct ipw_priv *priv) +{ + ipw_led_activity_off(priv); + ipw_led_link_off(priv); +} + +void ipw_led_link_up(struct ipw_priv *priv) +{ + /* Set the Link Led on for all nic types */ + ipw_led_link_on(priv); +} + +void ipw_led_link_down(struct ipw_priv *priv) +{ + ipw_led_activity_off(priv); + ipw_led_link_off(priv); + + if (priv->status & STATUS_RF_KILL_MASK) + ipw_led_radio_off(priv); +} + +void ipw_led_init(struct ipw_priv *priv) +{ + priv->nic_type = priv->eeprom[EEPROM_NIC_TYPE]; + + /* Set the default PINs for the link and activity leds */ + priv->led_activity_on = CX2_ACTIVITY_LED; + priv->led_activity_off = ~(CX2_ACTIVITY_LED); + + priv->led_association_on = CX2_ASSOCIATED_LED; + priv->led_association_off = ~(CX2_ASSOCIATED_LED); + + /* Set the default PINs for the OFDM leds */ + priv->led_ofdm_on = CX2_OFDM_LED; + priv->led_ofdm_off = ~(CX2_OFDM_LED); + + switch (priv->nic_type) { + case EEPROM_NIC_TYPE_1: + /* In this NIC type, the LEDs are reversed.... */ + priv->led_activity_on = CX2_ASSOCIATED_LED; + priv->led_activity_off = ~(CX2_ASSOCIATED_LED); + priv->led_association_on = CX2_ACTIVITY_LED; + priv->led_association_off = ~(CX2_ACTIVITY_LED); + + if (!(priv->config & CFG_NO_LED)) + ipw_led_band_on(priv); + + /* And we don't blink link LEDs for this nic, so + * just return here */ + return; + + case EEPROM_NIC_TYPE_3: + case EEPROM_NIC_TYPE_2: + case EEPROM_NIC_TYPE_4: + case EEPROM_NIC_TYPE_0: + break; + + default: + IPW_DEBUG_INFO("Unknown NIC type from EEPROM: %d\n", + priv->nic_type); + priv->nic_type = EEPROM_NIC_TYPE_0; + break; + } + + if (!(priv->config & CFG_NO_LED)) { + if (priv->status & STATUS_ASSOCIATED) + ipw_led_link_on(priv); + else + ipw_led_link_off(priv); + } +} + +void ipw_led_shutdown(struct ipw_priv *priv) +{ + cancel_delayed_work(&priv->led_link_on); + cancel_delayed_work(&priv->led_link_off); + cancel_delayed_work(&priv->led_act_off); + ipw_led_activity_off(priv); + ipw_led_link_off(priv); + ipw_led_band_off(priv); +} + /* * The following adds a new attribute to the sysfs representation * of this device driver (i.e. a new file in /sys/bus/pci/drivers/ipw/) @@ -648,8 +956,9 @@ static ssize_t show_debug_level(struct device_driver *d, char *buf) { return sprintf(buf, "0x%08X\n", ipw_debug_level); } -static ssize_t store_debug_level(struct device_driver *d, - const char *buf, size_t count) + +static ssize_t store_debug_level(struct device_driver *d, const char *buf, + size_t count) { char *p = (char *)buf; u32 val; @@ -673,6 +982,82 @@ static ssize_t store_debug_level(struct device_driver *d, static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, show_debug_level, store_debug_level); +static ssize_t show_scan_age(struct device *d, struct device_attribute *attr, + char *buf) +{ + struct ipw_priv *priv = dev_get_drvdata(d); + return sprintf(buf, "%d\n", priv->ieee->scan_age); +} + +static ssize_t store_scan_age(struct device *d, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ipw_priv *priv = dev_get_drvdata(d); + struct net_device *dev = priv->net_dev; + char buffer[] = "00000000"; + unsigned long len = + (sizeof(buffer) - 1) > count ? count : sizeof(buffer) - 1; + unsigned long val; + char *p = buffer; + + IPW_DEBUG_INFO("enter\n"); + + strncpy(buffer, buf, len); + buffer[len] = 0; + + if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { + p++; + if (p[0] == 'x' || p[0] == 'X') + p++; + val = simple_strtoul(p, &p, 16); + } else + val = simple_strtoul(p, &p, 10); + if (p == buffer) { + IPW_DEBUG_INFO("%s: user supplied invalid value.\n", dev->name); + } else { + priv->ieee->scan_age = val; + IPW_DEBUG_INFO("set scan_age = %u\n", priv->ieee->scan_age); + } + + IPW_DEBUG_INFO("exit\n"); + return len; +} + +static DEVICE_ATTR(scan_age, S_IWUSR | S_IRUGO, show_scan_age, store_scan_age); + +static ssize_t show_led(struct device *d, struct device_attribute *attr, + char *buf) +{ + struct ipw_priv *priv = dev_get_drvdata(d); + return sprintf(buf, "%d\n", (priv->config & CFG_NO_LED) ? 0 : 1); +} + +static ssize_t store_led(struct device *d, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ipw_priv *priv = dev_get_drvdata(d); + + IPW_DEBUG_INFO("enter\n"); + + if (count == 0) + return 0; + + if (*buf == 0) { + IPW_DEBUG_LED("Disabling LED control.\n"); + priv->config |= CFG_NO_LED; + ipw_led_shutdown(priv); + } else { + IPW_DEBUG_LED("Enabling LED control.\n"); + priv->config &= ~CFG_NO_LED; + ipw_led_init(priv); + } + + IPW_DEBUG_INFO("exit\n"); + return count; +} + +static DEVICE_ATTR(led, S_IWUSR | S_IRUGO, show_led, store_led); + static ssize_t show_status(struct device *d, struct device_attribute *attr, char *buf) { @@ -694,23 +1079,8 @@ static DEVICE_ATTR(cfg, S_IRUGO, show_cfg, NULL); static ssize_t show_nic_type(struct device *d, struct device_attribute *attr, char *buf) { - struct ipw_priv *p = d->driver_data; - u8 type = p->eeprom[EEPROM_NIC_TYPE]; - - switch (type) { - case EEPROM_NIC_TYPE_STANDARD: - return sprintf(buf, "STANDARD\n"); - case EEPROM_NIC_TYPE_DELL: - return sprintf(buf, "DELL\n"); - case EEPROM_NIC_TYPE_FUJITSU: - return sprintf(buf, "FUJITSU\n"); - case EEPROM_NIC_TYPE_IBM: - return sprintf(buf, "IBM\n"); - case EEPROM_NIC_TYPE_HP: - return sprintf(buf, "HP\n"); - } - - return sprintf(buf, "UNKNOWN\n"); + struct ipw_priv *priv = d->driver_data; + return sprintf(buf, "TYPE: %d\n", priv->nic_type); } static DEVICE_ATTR(nic_type, S_IRUGO, show_nic_type, NULL); @@ -955,9 +1325,8 @@ static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio) if (disable_radio) { priv->status |= STATUS_RF_KILL_SW; - if (priv->workqueue) { + if (priv->workqueue) cancel_delayed_work(&priv->request_scan); - } wake_up_interruptible(&priv->wait_command_queue); queue_work(priv->workqueue, &priv->down); } else { @@ -1081,11 +1450,9 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) IPW_DEBUG_RF_KILL("RF_KILL_DONE\n"); priv->status |= STATUS_RF_KILL_HW; wake_up_interruptible(&priv->wait_command_queue); - netif_carrier_off(priv->net_dev); - netif_stop_queue(priv->net_dev); priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); - notify_wx_assoc_event(priv); cancel_delayed_work(&priv->request_scan); + schedule_work(&priv->link_down); queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ); handled |= CX2_INTA_BIT_RF_KILL_DONE; } @@ -1182,9 +1549,12 @@ static char *get_cmd_string(u8 cmd) static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) { int rc = 0; + unsigned long flags; + spin_lock_irqsave(&priv->lock, flags); if (priv->status & STATUS_HCMD_ACTIVE) { IPW_ERROR("Already sending a command\n"); + spin_unlock_irqrestore(&priv->lock, flags); return -1; } @@ -1195,19 +1565,30 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) printk_buf(IPW_DL_HOST_COMMAND, (u8 *) cmd->param, cmd->len); rc = ipw_queue_tx_hcmd(priv, cmd->cmd, &cmd->param, cmd->len, 0); - if (rc) + if (rc) { + priv->status &= ~STATUS_HCMD_ACTIVE; + spin_unlock_irqrestore(&priv->lock, flags); return rc; + } + spin_unlock_irqrestore(&priv->lock, flags); rc = wait_event_interruptible_timeout(priv->wait_command_queue, !(priv-> status & STATUS_HCMD_ACTIVE), HOST_COMPLETE_TIMEOUT); if (rc == 0) { - IPW_DEBUG_INFO("Command completion failed out after %dms.\n", - jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); - priv->status &= ~STATUS_HCMD_ACTIVE; - return -EIO; + spin_lock_irqsave(&priv->lock, flags); + if (priv->status & STATUS_HCMD_ACTIVE) { + IPW_DEBUG_INFO("Command completion failed out after " + "%dms.\n", + 1000 * (HOST_COMPLETE_TIMEOUT / HZ)); + priv->status &= ~STATUS_HCMD_ACTIVE; + spin_unlock_irqrestore(&priv->lock, flags); + return -EIO; + } + spin_unlock_irqrestore(&priv->lock, flags); } + if (priv->status & STATUS_RF_KILL_MASK) { IPW_DEBUG_INFO("Command aborted due to RF Kill Switch\n"); return -EIO; @@ -1304,6 +1685,11 @@ static int ipw_send_adapter_address(struct ipw_priv *priv, u8 * mac) return 0; } +/* + * NOTE: This must be executed from our workqueue as it results in udelay + * being called which may corrupt the keyboard if executed on default + * workqueue + */ static void ipw_adapter_restart(void *adapter) { struct ipw_priv *priv = adapter; @@ -1327,7 +1713,7 @@ static void ipw_scan_check(void *data) IPW_DEBUG_SCAN("Scan completion watchdog resetting " "adapter (%dms).\n", IPW_SCAN_CHECK_WATCHDOG / 100); - ipw_adapter_restart(priv); + queue_work(priv->workqueue, &priv->adapter_restart); } } @@ -1400,12 +1786,25 @@ static int ipw_send_associate(struct ipw_priv *priv, .len = sizeof(*associate) }; + struct ipw_associate tmp_associate; + memcpy(&tmp_associate, associate, sizeof(*associate)); + tmp_associate.policy_support = + cpu_to_le16(tmp_associate.policy_support); + tmp_associate.assoc_tsf_msw = cpu_to_le32(tmp_associate.assoc_tsf_msw); + tmp_associate.assoc_tsf_lsw = cpu_to_le32(tmp_associate.assoc_tsf_lsw); + tmp_associate.capability = cpu_to_le16(tmp_associate.capability); + tmp_associate.listen_interval = + cpu_to_le16(tmp_associate.listen_interval); + tmp_associate.beacon_interval = + cpu_to_le16(tmp_associate.beacon_interval); + tmp_associate.atim_window = cpu_to_le16(tmp_associate.atim_window); + if (!priv || !associate) { IPW_ERROR("Invalid args\n"); return -1; } - memcpy(&cmd.param, associate, sizeof(*associate)); + memcpy(&cmd.param, &tmp_associate, sizeof(*associate)); if (ipw_send_cmd(priv, &cmd)) { IPW_ERROR("failed to send ASSOCIATE command\n"); return -1; @@ -1706,7 +2105,7 @@ static void ipw_eeprom_init_sram(struct ipw_priv *priv) /* read entire contents of eeprom into private buffer */ for (i = 0; i < 128; i++) - eeprom[i] = eeprom_read_u16(priv, (u8) i); + eeprom[i] = le16_to_cpu(eeprom_read_u16(priv, (u8) i)); /* If the data looks correct, then copy it to our private @@ -2001,6 +2400,9 @@ static void ipw_remove_current_network(struct ipw_priv *priv) { struct list_head *element, *safe; struct ieee80211_network *network = NULL; + unsigned long flags; + + spin_lock_irqsave(&priv->ieee->lock, flags); list_for_each_safe(element, safe, &priv->ieee->network_list) { network = list_entry(element, struct ieee80211_network, list); if (!memcmp(network->bssid, priv->bssid, ETH_ALEN)) { @@ -2009,6 +2411,7 @@ static void ipw_remove_current_network(struct ipw_priv *priv) &priv->ieee->network_free_list); } } + spin_unlock_irqrestore(&priv->ieee->lock, flags); } /** @@ -2158,7 +2561,8 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) */ /* load new ipw uCode */ for (i = 0; i < len / 2; i++) - ipw_write_reg16(priv, CX2_BASEBAND_CONTROL_STORE, image[i]); + ipw_write_reg16(priv, CX2_BASEBAND_CONTROL_STORE, + cpu_to_le16(image[i])); /* enable DINO */ ipw_write_reg8(priv, CX2_BASEBAND_CONTROL_STATUS, 0); @@ -2181,7 +2585,8 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) for (i = 0; i < ARRAY_SIZE(response_buffer); i++) response_buffer[i] = - ipw_read_reg32(priv, CX2_BASEBAND_RX_FIFO_READ); + le32_to_cpu(ipw_read_reg32(priv, + CX2_BASEBAND_RX_FIFO_READ)); memcpy(&priv->dino_alive, response_buffer, sizeof(priv->dino_alive)); if (priv->dino_alive.alive_command == 1 @@ -2250,13 +2655,14 @@ static int ipw_load_firmware(struct ipw_priv *priv, u8 * data, size_t len) * offeset*/ /* Dma loading */ rc = ipw_fw_dma_add_buffer(priv, shared_phys + offset, - chunk->address, chunk->length); + le32_to_cpu(chunk->address), + le32_to_cpu(chunk->length)); if (rc) { IPW_DEBUG_INFO("dmaAddBuffer Failed\n"); goto out; } - offset += chunk->length; + offset += le32_to_cpu(chunk->length); } while (offset < len); /* Run the DMA and wait for the answer */ @@ -2351,14 +2757,17 @@ static int ipw_init_nic(struct ipw_priv *priv) static int ipw_reset_nic(struct ipw_priv *priv) { int rc = 0; + unsigned long flags; IPW_DEBUG_TRACE(">>\n"); rc = ipw_init_nic(priv); + spin_lock_irqsave(&priv->lock, flags); /* Clear the 'host command active' bit... */ priv->status &= ~STATUS_HCMD_ACTIVE; wake_up_interruptible(&priv->wait_command_queue); + spin_unlock_irqrestore(&priv->lock, flags); IPW_DEBUG_TRACE("<<\n"); return rc; @@ -2378,17 +2787,18 @@ static int ipw_get_fw(struct ipw_priv *priv, } header = (struct fw_header *)(*fw)->data; - if (IPW_FW_MAJOR(header->version) != IPW_FW_MAJOR_VERSION) { + if (IPW_FW_MAJOR(le32_to_cpu(header->version)) != IPW_FW_MAJOR_VERSION) { IPW_ERROR("'%s' firmware version not compatible (%d != %d)\n", name, - IPW_FW_MAJOR(header->version), IPW_FW_MAJOR_VERSION); + IPW_FW_MAJOR(le32_to_cpu(header->version)), + IPW_FW_MAJOR_VERSION); return -EINVAL; } IPW_DEBUG_INFO("Loading firmware '%s' file v%d.%d (%zd bytes)\n", name, - IPW_FW_MAJOR(header->version), - IPW_FW_MINOR(header->version), + IPW_FW_MAJOR(le32_to_cpu(header->version)), + IPW_FW_MINOR(le32_to_cpu(header->version)), (*fw)->size - sizeof(struct fw_header)); return 0; } @@ -2414,6 +2824,7 @@ static inline void ipw_rx_queue_reset(struct ipw_priv *priv, pci_unmap_single(priv->pci_dev, rxq->pool[i].dma_addr, CX2_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); dev_kfree_skb(rxq->pool[i].skb); + rxq->pool[i].skb = NULL; } list_add_tail(&rxq->pool[i].list, &rxq->rx_used); } @@ -2769,16 +3180,18 @@ static void ipw_queue_tx_free_tfd(struct ipw_priv *priv, return; /* sanity check */ - if (bd->u.data.num_chunks > NUM_TFD_CHUNKS) { - IPW_ERROR("Too many chunks: %i\n", bd->u.data.num_chunks); + if (le32_to_cpu(bd->u.data.num_chunks) > NUM_TFD_CHUNKS) { + IPW_ERROR("Too many chunks: %i\n", + le32_to_cpu(bd->u.data.num_chunks)); /** @todo issue fatal error, it is quite serious situation */ return; } /* unmap chunks if any */ - for (i = 0; i < bd->u.data.num_chunks; i++) { - pci_unmap_single(dev, bd->u.data.chunk_ptr[i], - bd->u.data.chunk_len[i], PCI_DMA_TODEVICE); + for (i = 0; i < le32_to_cpu(bd->u.data.num_chunks); i++) { + pci_unmap_single(dev, le32_to_cpu(bd->u.data.chunk_ptr[i]), + le16_to_cpu(bd->u.data.chunk_len[i]), + PCI_DMA_TODEVICE); if (txq->txb[txq->q.last_used]) { ieee80211_txb_free(txq->txb[txq->q.last_used]); txq->txb[txq->q.last_used] = NULL; @@ -2841,9 +3254,8 @@ static void inline __maybe_wake_tx(struct ipw_priv *priv) switch (priv->port_type) { case DCR_TYPE_MU_BSS: case DCR_TYPE_MU_IBSS: - if (!(priv->status & STATUS_ASSOCIATED)) { + if (!(priv->status & STATUS_ASSOCIATED)) return; - } } netif_wake_queue(priv->net_dev); } @@ -3307,8 +3719,13 @@ static inline void ipw_handle_missed_beacon(struct ipw_priv *priv, IPW_DL_STATE, "Missed beacon: %d - disassociate\n", missed_count); priv->status &= ~STATUS_ROAMING; - if (priv->status & STATUS_SCANNING) + if (priv->status & STATUS_SCANNING) { + IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF | + IPW_DL_STATE, + "Aborting scan with missed beacon.\n"); queue_work(priv->workqueue, &priv->abort_scan); + } + queue_work(priv->workqueue, &priv->disassociate); return; } @@ -3342,6 +3759,8 @@ static inline void ipw_handle_missed_beacon(struct ipw_priv *priv, * stuck (only if we aren't roaming -- * otherwise we'll never scan more than 2 or 3 * channels..) */ + IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF | + IPW_DL_STATE, "Aborting scan with missed beacon.\n"); queue_work(priv->workqueue, &priv->abort_scan); } @@ -3356,6 +3775,8 @@ static inline void ipw_handle_missed_beacon(struct ipw_priv *priv, static inline void ipw_rx_notification(struct ipw_priv *priv, struct ipw_rx_notification *notif) { + notif->size = le16_to_cpu(notif->size); + IPW_DEBUG_NOTIF("type = %i (%d bytes)\n", notif->subtype, notif->size); switch (notif->subtype) { @@ -3400,29 +3821,8 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, priv->status &= ~STATUS_ASSOCIATING; priv->status |= STATUS_ASSOCIATED; - netif_carrier_on(priv->net_dev); - if (netif_queue_stopped(priv->net_dev)) { - IPW_DEBUG_NOTIF - ("waking queue\n"); - netif_wake_queue(priv->net_dev); - } else { - IPW_DEBUG_NOTIF - ("starting queue\n"); - netif_start_queue(priv-> - net_dev); - } + schedule_work(&priv->link_up); - ipw_reset_stats(priv); - /* Ensure the rate is updated immediately */ - priv->last_rate = - ipw_get_current_rate(priv); - schedule_work(&priv->gather_stats); - notify_wx_assoc_event(priv); - -/* queue_delayed_work(priv->workqueue, - &priv->request_scan, - SCAN_ASSOCIATED_INTERVAL); -*/ break; } @@ -3455,12 +3855,7 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, STATUS_AUTH | STATUS_ASSOCIATED); - netif_carrier_off(priv-> - net_dev); - netif_stop_queue(priv->net_dev); - queue_work(priv->workqueue, - &priv->request_scan); - notify_wx_assoc_event(priv); + schedule_work(&priv->link_down); break; } @@ -3506,31 +3901,8 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, STATUS_ASSOCIATING | STATUS_ASSOCIATED | STATUS_AUTH); - netif_stop_queue(priv->net_dev); - if (!(priv->status & STATUS_ROAMING)) { - netif_carrier_off(priv-> - net_dev); - notify_wx_assoc_event(priv); - - /* Cancel any queued work ... */ - cancel_delayed_work(&priv-> - request_scan); - cancel_delayed_work(&priv-> - adhoc_check); - - /* Queue up another scan... */ - queue_work(priv->workqueue, - &priv->request_scan); - - cancel_delayed_work(&priv-> - gather_stats); - } else { - priv->status |= STATUS_ROAMING; - queue_work(priv->workqueue, - &priv->request_scan); - } + schedule_work(&priv->link_down); - ipw_reset_stats(priv); break; } @@ -3576,11 +3948,7 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, STATUS_AUTH | STATUS_ASSOCIATED); - netif_carrier_off(priv->net_dev); - netif_stop_queue(priv->net_dev); - queue_work(priv->workqueue, - &priv->request_scan); - notify_wx_assoc_event(priv); + schedule_work(&priv->link_down); break; case CMAS_TX_AUTH_SEQ_1: @@ -3682,6 +4050,10 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, } else if (priv->status & STATUS_SCAN_PENDING) queue_work(priv->workqueue, &priv->request_scan); + else if (priv->config & CFG_BACKGROUND_SCAN + && priv->status & STATUS_ASSOCIATED) + queue_delayed_work(priv->workqueue, + &priv->request_scan, HZ); priv->ieee->scans++; break; @@ -3690,13 +4062,13 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, case HOST_NOTIFICATION_STATUS_FRAG_LENGTH:{ struct notif_frag_length *x = ¬if->u.frag_len; - if (notif->size == sizeof(*x)) { - IPW_ERROR("Frag length: %d\n", x->frag_length); - } else { + if (notif->size == sizeof(*x)) + IPW_ERROR("Frag length: %d\n", + le16_to_cpu(x->frag_length)); + else IPW_ERROR("Frag length of wrong size %d " "(should be %zd)\n", notif->size, sizeof(*x)); - } break; } @@ -3722,11 +4094,9 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, case HOST_NOTIFICATION_DINO_CONFIG_RESPONSE:{ IPW_ERROR("Dino config\n"); if (priv->hcmd - && priv->hcmd->cmd == HOST_CMD_DINO_CONFIG) { - /* TODO: Do anything special? */ - } else { + && priv->hcmd->cmd != HOST_CMD_DINO_CONFIG) IPW_ERROR("Unexpected DINO_CONFIG_RESPONSE\n"); - } + break; } @@ -3739,8 +4109,11 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, break; } - if (x->state == HOST_NOTIFICATION_STATUS_BEACON_MISSING) - ipw_handle_missed_beacon(priv, x->number); + if (le32_to_cpu(x->state) == + HOST_NOTIFICATION_STATUS_BEACON_MISSING) + ipw_handle_missed_beacon(priv, + le32_to_cpu(x-> + number)); break; } @@ -3779,7 +4152,8 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, case HOST_NOTIFICATION_NOISE_STATS:{ if (notif->size == sizeof(u32)) { priv->last_noise = - (u8) (notif->u.noise.value & 0xff); + (u8) (le32_to_cpu(notif->u.noise.value) & + 0xff); average_add(&priv->average_noise, priv->last_noise); break; @@ -3896,9 +4270,8 @@ static int ipw_queue_tx_reclaim(struct ipw_priv *priv, priv->tx_packets++; } done: - if (ipw_queue_space(q) > q->low_mark && qindex >= 0) { + if (ipw_queue_space(q) > q->low_mark && qindex >= 0) __maybe_wake_tx(priv); - } used = q->first_empty - q->last_used; if (used < 0) used += q->n_bd; @@ -4217,13 +4590,16 @@ static int ipw_compatible_rates(struct ipw_priv *priv, num_rates = min(network->rates_len, (u8) IPW_MAX_RATES); rates->num_rates = 0; for (i = 0; i < num_rates; i++) { - if (!ipw_is_rate_in_mask - (priv, network->mode, network->rates[i])) { + if (!ipw_is_rate_in_mask(priv, network->mode, + network->rates[i])) { + if (network->rates[i] & IEEE80211_BASIC_RATE_MASK) { - IPW_DEBUG_SCAN - ("Basic rate %02X masked: 0x%08X\n", - network->rates[i], priv->rates_mask); - return 0; + IPW_DEBUG_SCAN("Adding masked mandatory " + "rate %02X\n", + network->rates[i]); + rates->supported_rates[rates->num_rates++] = + network->rates[i]; + continue; } IPW_DEBUG_SCAN("Rate %02X masked : 0x%08X\n", @@ -4234,16 +4610,18 @@ static int ipw_compatible_rates(struct ipw_priv *priv, rates->supported_rates[rates->num_rates++] = network->rates[i]; } - num_rates = - min(network->rates_ex_len, (u8) (IPW_MAX_RATES - num_rates)); + num_rates = min(network->rates_ex_len, + (u8) (IPW_MAX_RATES - num_rates)); for (i = 0; i < num_rates; i++) { - if (!ipw_is_rate_in_mask - (priv, network->mode, network->rates_ex[i])) { + if (!ipw_is_rate_in_mask(priv, network->mode, + network->rates_ex[i])) { if (network->rates_ex[i] & IEEE80211_BASIC_RATE_MASK) { - IPW_DEBUG_SCAN - ("Basic rate %02X masked: 0x%08X\n", - network->rates_ex[i], priv->rates_mask); - return 0; + IPW_DEBUG_SCAN("Adding masked mandatory " + "rate %02X\n", + network->rates_ex[i]); + rates->supported_rates[rates->num_rates++] = + network->rates[i]; + continue; } IPW_DEBUG_SCAN("Rate %02X masked : 0x%08X\n", @@ -4531,9 +4909,7 @@ static void ipw_adhoc_create(struct ipw_priv *priv, * FW fatal error. */ network->mode = is_valid_channel(priv->ieee->mode, priv->channel); - if (network->mode) { - network->channel = priv->channel; - } else { + if (!network->mode) { IPW_WARNING("Overriding invalid channel\n"); if (priv->ieee->mode & IEEE_A) { network->mode = IEEE_A; @@ -4572,10 +4948,8 @@ static void ipw_adhoc_create(struct ipw_priv *priv, network->beacon_interval = 100; /* Default */ network->listen_interval = 10; /* Default */ network->atim_window = 0; /* Default */ -#ifdef CONFIG_IEEE80211_WPA network->wpa_ie_len = 0; network->rsn_ie_len = 0; -#endif /* CONFIG_IEEE80211_WPA */ } static void ipw_send_wep_keys(struct ipw_priv *priv) @@ -4593,9 +4967,9 @@ static void ipw_send_wep_keys(struct ipw_priv *priv) for (i = 0; i < 4; i++) { key->key_index = i; - if (!(priv->sec.flags & (1 << i))) { + if (!(priv->sec.flags & (1 << i))) key->key_size = 0; - } else { + else { key->key_size = priv->sec.key_sizes[i]; memcpy(key->key, priv->sec.keys[i], key->key_size); } @@ -4752,9 +5126,10 @@ static int ipw_request_scan(struct ipw_priv *priv) } if (priv->status & STATUS_SCANNING) { - IPW_DEBUG_HC("Concurrent scan requested. Aborting first.\n"); + IPW_DEBUG_HC("Concurrent scan requested. Ignoring.\n"); +// IPW_DEBUG_HC("Concurrent scan requested. Aborting first.\n"); priv->status |= STATUS_SCAN_PENDING; - ipw_abort_scan(priv); +// ipw_abort_scan(priv); return 0; } @@ -4772,11 +5147,12 @@ static int ipw_request_scan(struct ipw_priv *priv) memset(&scan, 0, sizeof(scan)); - scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = 20; - scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] = 20; - scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = 20; + scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = cpu_to_le16(20); + scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] = + cpu_to_le16(20); + scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(20); - scan.full_scan_index = ieee80211_get_scans(priv->ieee); + scan.full_scan_index = cpu_to_le32(ieee80211_get_scans(priv->ieee)); #ifdef CONFIG_IPW_MONITOR if (priv->ieee->iw_mode == IW_MODE_MONITOR) { @@ -4798,7 +5174,8 @@ static int ipw_request_scan(struct ipw_priv *priv) ipw_set_scan_type(&scan, channel_index, IPW_SCAN_PASSIVE_FULL_DWELL_SCAN); - scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = 2000; + scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = + cpu_to_le16(2000); } else { #endif /* CONFIG_IPW_MONITOR */ /* If we are roaming, then make this a directed scan for the current @@ -4807,7 +5184,7 @@ static int ipw_request_scan(struct ipw_priv *priv) if ((priv->status & STATUS_ROAMING) || (!(priv->status & STATUS_ASSOCIATED) && (priv->config & CFG_STATIC_ESSID) - && (scan.full_scan_index % 2))) { + && (le32_to_cpu(scan.full_scan_index) % 2))) { err = ipw_send_ssid(priv, priv->essid, priv->essid_len); if (err) { IPW_DEBUG_HC @@ -4882,7 +5259,6 @@ static int ipw_request_scan(struct ipw_priv *priv) /* Support for wpa_supplicant. Will be replaced with WEXT once * they get WPA support. */ -#ifdef CONFIG_IEEE80211_WPA /* following definitions must match definitions in driver_ipw.c */ @@ -4959,6 +5335,7 @@ static int ipw_wpa_enable(struct ipw_priv *priv, int value) } else { sec.level = SEC_LEVEL_0; sec.enabled = 0; + ieee->wpa_ie_len = 0; } if (ieee->set_security) @@ -4999,6 +5376,8 @@ static int ipw_wpa_set_auth_algs(struct ipw_priv *priv, int value) static int ipw_wpa_set_param(struct net_device *dev, u8 name, u32 value) { struct ipw_priv *priv = ieee80211_priv(dev); + struct ieee80211_crypt_data *crypt; + unsigned long flags; int ret = 0; switch (name) { @@ -5007,7 +5386,22 @@ static int ipw_wpa_set_param(struct net_device *dev, u8 name, u32 value) break; case IPW_PARAM_TKIP_COUNTERMEASURES: - priv->ieee->tkip_countermeasures = value; + crypt = priv->ieee->crypt[priv->ieee->tx_keyidx]; + if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) { + IPW_WARNING("Can't set TKIP countermeasures: " + "crypt not set!\n"); + break; + } + + flags = crypt->ops->get_flags(crypt->priv); + + if (value) + flags |= IEEE80211_CRYPTO_TKIP_COUNTERMEASURES; + else + flags &= ~IEEE80211_CRYPTO_TKIP_COUNTERMEASURES; + + crypt->ops->set_flags(flags, crypt->priv); + break; case IPW_PARAM_DROP_UNENCRYPTED: @@ -5313,7 +5707,6 @@ static int ipw_wpa_supplicant(struct net_device *dev, struct iw_point *p) kfree(param); return ret; } -#endif /* CONFIG_IEEE80211_WPA */ static int ipw_associate_network(struct ipw_priv *priv, struct ieee80211_network *network, @@ -5346,13 +5739,11 @@ static int ipw_associate_network(struct ipw_priv *priv, if (priv->capability & CAP_PRIVACY_ON) ipw_send_wep_keys(priv); -#ifdef CONFIG_IEEE80211_WPA - if (priv->ieee->wpa_enabled) { + if (priv->ieee->wpa_ie_len) { priv->assoc_request.policy_support = 0x02; /* RSN active */ ipw_set_rsn_capa(priv, priv->ieee->wpa_ie, priv->ieee->wpa_ie_len); } -#endif /* * It is valid for our ieee device to support multiple modes, but @@ -5511,12 +5902,15 @@ static void ipw_roam(void *data) if (priv->status & STATUS_ASSOCIATED) { /* First pass through ROAM process -- look for a better * network */ + unsigned long flags; u8 rssi = priv->assoc_network->stats.rssi; priv->assoc_network->stats.rssi = -128; + spin_lock_irqsave(&priv->ieee->lock, flags); list_for_each_entry(network, &priv->ieee->network_list, list) { if (network != priv->assoc_network) ipw_best_network(priv, &match, network, 1); } + spin_unlock_irqrestore(&priv->ieee->lock, flags); priv->assoc_network->stats.rssi = rssi; if (match.network == priv->assoc_network) { @@ -5549,6 +5943,7 @@ static void ipw_associate(void *data) }; struct ipw_supported_rates *rates; struct list_head *element; + unsigned long flags; if (!(priv->config & CFG_ASSOCIATE) && !(priv->config & (CFG_STATIC_ESSID | @@ -5557,6 +5952,8 @@ static void ipw_associate(void *data) return; } + /* Protect our use of the network_list */ + spin_lock_irqsave(&priv->ieee->lock, flags); list_for_each_entry(network, &priv->ieee->network_list, list) ipw_best_network(priv, &match, network, 0); @@ -5567,6 +5964,7 @@ static void ipw_associate(void *data) priv->ieee->iw_mode == IW_MODE_ADHOC && priv->config & CFG_ADHOC_CREATE && priv->config & CFG_STATIC_ESSID && + priv->config & CFG_STATIC_CHANNEL && !list_empty(&priv->ieee->network_free_list)) { element = priv->ieee->network_free_list.next; network = list_entry(element, struct ieee80211_network, list); @@ -5575,14 +5973,16 @@ static void ipw_associate(void *data) list_del(element); list_add_tail(&network->list, &priv->ieee->network_list); } + spin_unlock_irqrestore(&priv->ieee->lock, flags); /* If we reached the end of the list, then we don't have any valid * matching APs */ if (!network) { ipw_debug_config(priv); - queue_delayed_work(priv->workqueue, &priv->request_scan, - SCAN_INTERVAL); + if (!(priv->status & STATUS_SCANNING)) + queue_delayed_work(priv->workqueue, &priv->request_scan, + SCAN_INTERVAL); return; } @@ -5601,7 +6001,7 @@ static inline void ipw_handle_data_packet(struct ipw_priv *priv, /* We only process data packets if the * interface is open */ - if (unlikely((pkt->u.frame.length + IPW_RX_FRAME_SIZE) > + if (unlikely((le16_to_cpu(pkt->u.frame.length) + IPW_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) { priv->ieee->stats.rx_errors++; priv->wstats.discard.misc++; @@ -5618,14 +6018,16 @@ static inline void ipw_handle_data_packet(struct ipw_priv *priv, skb_reserve(rxb->skb, offsetof(struct ipw_rx_packet, u.frame.data)); /* Set the size of the skb to the size of the frame */ - skb_put(rxb->skb, pkt->u.frame.length); + skb_put(rxb->skb, le16_to_cpu(pkt->u.frame.length)); IPW_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len); if (!ieee80211_rx(priv->ieee, rxb->skb, stats)) priv->ieee->stats.rx_errors++; - else /* ieee80211_rx succeeded, so it now owns the SKB */ + else { /* ieee80211_rx succeeded, so it now owns the SKB */ rxb->skb = NULL; + ipw_led_activity_on(priv); + } } static inline int is_network_packet(struct ipw_priv *priv, @@ -5634,23 +6036,29 @@ static inline int is_network_packet(struct ipw_priv *priv, /* Filter incoming packets to determine if they are targetted toward * this network, discarding packets coming from ourselves */ switch (priv->ieee->iw_mode) { - case IW_MODE_ADHOC: + case IW_MODE_ADHOC: /* Header: Dest. | Source | BSSID */ + /* {broad,multi}cast packets to our IBSS go through */ if (is_broadcast_ether_addr(header->addr1) || is_multicast_ether_addr(header->addr1)) return !memcmp(header->addr3, priv->bssid, ETH_ALEN); - else - return memcmp(header->addr1, priv->net_dev->dev_addr, - ETH_ALEN); + + /* packets to our adapter go through */ + return !memcmp(header->addr1, priv->net_dev->dev_addr, + ETH_ALEN); break; - case IW_MODE_INFRA: - if (is_broadcast_ether_addr(header->addr3) || - is_multicast_ether_addr(header->addr3)) - return !memcmp(header->addr1, priv->bssid, ETH_ALEN); - else - return memcmp(header->addr3, priv->net_dev->dev_addr, - ETH_ALEN); + + case IW_MODE_INFRA: /* Header: Dest. | AP{BSSID} | Source */ + /* {broad,multi}cast packets to our IBSS go through */ + if (is_broadcast_ether_addr(header->addr1) || + is_multicast_ether_addr(header->addr1)) + return !memcmp(header->addr2, priv->bssid, ETH_ALEN); + + /* packets to our adapter go through */ + return !memcmp(header->addr1, priv->net_dev->dev_addr, + ETH_ALEN); break; } + return 1; } @@ -5695,7 +6103,7 @@ static void ipw_rx(struct ipw_priv *priv) struct ieee80211_rx_stats stats = { .rssi = pkt->u.frame.rssi_dbm - IPW_RSSI_TO_DBM, - .signal = pkt->u.frame.signal, + /* .signal = le16_to_cpu(pkt->u.frame.signal), */ .rate = pkt->u.frame.rate, .mac_time = jiffies, .received_channel = @@ -5705,7 +6113,7 @@ static void ipw_rx(struct ipw_priv *priv) control & (1 << 0)) ? IEEE80211_24GHZ_BAND : IEEE80211_52GHZ_BAND, - .len = pkt->u.frame.length, + .len = le16_to_cpu(pkt->u.frame.length), }; if (stats.rssi != 0) @@ -5746,9 +6154,10 @@ static void ipw_rx(struct ipw_priv *priv) } IPW_DEBUG_RX("Frame: len=%u\n", - pkt->u.frame.length); + le16_to_cpu(pkt->u.frame.length)); - if (pkt->u.frame.length < frame_hdr_len(header)) { + if (le16_to_cpu(pkt->u.frame.length) < + frame_hdr_len(header)) { IPW_DEBUG_DROP ("Received packet is too small. " "Dropping.\n"); @@ -5757,19 +6166,20 @@ static void ipw_rx(struct ipw_priv *priv) break; } - switch (WLAN_FC_GET_TYPE(header->frame_ctl)) { + switch (WLAN_FC_GET_TYPE + (le16_to_cpu(header->frame_ctl))) { case IEEE80211_FTYPE_MGMT: ieee80211_rx_mgt(priv->ieee, header, &stats); if (priv->ieee->iw_mode == IW_MODE_ADHOC && ((WLAN_FC_GET_STYPE - (header->frame_ctl) == - IEEE80211_STYPE_PROBE_RESP) + (le16_to_cpu(header->frame_ctl)) + == IEEE80211_STYPE_PROBE_RESP) || (WLAN_FC_GET_STYPE - (header->frame_ctl) == - IEEE80211_STYPE_BEACON)) + (le16_to_cpu(header->frame_ctl)) + == IEEE80211_STYPE_BEACON)) && !memcmp(header->addr3, priv->bssid, ETH_ALEN)) ipw_add_station(priv, @@ -5852,7 +6262,9 @@ static int ipw_wx_get_name(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - if (!(priv->status & STATUS_ASSOCIATED)) + if (priv->status & STATUS_RF_KILL_MASK) { + strcpy(wrqu->name, "radio off"); + } else if (!(priv->status & STATUS_ASSOCIATED)) strcpy(wrqu->name, "unassociated"); else snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11%c", @@ -5892,9 +6304,8 @@ static int ipw_set_channel(struct ipw_priv *priv, u8 channel) if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { IPW_DEBUG_ASSOC("Disassociating due to channel change.\n"); ipw_disassociate(priv); - } else { + } else if (!(priv->status & (STATUS_SCANNING))) ipw_associate(priv); - } return 0; } @@ -5986,9 +6397,8 @@ static int ipw_wx_set_mode(struct net_device *dev, #ifdef CONFIG_PM /* Free the existing firmware and reset the fw_loaded * flag so ipw_load() will bring in the new firmawre */ - if (fw_loaded) { + if (fw_loaded) fw_loaded = 0; - } release_firmware(bootfw); release_firmware(ucode); @@ -5997,7 +6407,7 @@ static int ipw_wx_set_mode(struct net_device *dev, #endif priv->ieee->iw_mode = wrqu->mode; - ipw_adapter_restart(priv); + queue_work(priv->workqueue, &priv->adapter_restart); return err; } @@ -6149,9 +6559,8 @@ static int ipw_wx_set_wap(struct net_device *dev, if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { IPW_DEBUG_ASSOC("Disassociating due to BSSID change.\n"); ipw_disassociate(priv); - } else { + } else if (!(priv->status & (STATUS_SCANNING))) ipw_associate(priv); - } return 0; } @@ -6220,9 +6629,8 @@ static int ipw_wx_set_essid(struct net_device *dev, if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { IPW_DEBUG_ASSOC("Disassociating due to ESSID change.\n"); ipw_disassociate(priv); - } else { + } else if (!(priv->status & (STATUS_SCANNING))) ipw_associate(priv); - } return 0; } @@ -6383,10 +6791,10 @@ static int ipw_wx_set_rate(struct net_device *dev, if ((priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING))) { IPW_DEBUG_ASSOC("Disassociating due to RATE change.\n"); ipw_disassociate(priv); + } else if (!(priv->status & (STATUS_SCANNING))) { + /* We are not yet associated, so kick one off... */ + ipw_associate(priv); } - } else { - /* We are not yet associated, so kick one off... */ - ipw_associate(priv); } return 0; @@ -6635,11 +7043,10 @@ static int ipw_wx_get_power(struct net_device *dev, { struct ipw_priv *priv = ieee80211_priv(dev); - if (!(priv->power_mode & IPW_POWER_ENABLED)) { + if (!(priv->power_mode & IPW_POWER_ENABLED)) wrqu->power.disabled = 1; - } else { + else wrqu->power.disabled = 0; - } IPW_DEBUG_WX("GET Power Management Mode -> %02X\n", priv->power_mode); @@ -6764,6 +7171,9 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev, } else ipw_send_supported_rates(priv, &priv->rates); + /* Update the band LEDs */ + ipw_led_band_on(priv); + IPW_DEBUG_WX("PRIV SET MODE: %c%c%c\n", mode & IEEE_A ? 'a' : '.', mode & IEEE_B ? 'b' : '.', mode & IEEE_G ? 'g' : '.'); @@ -6870,7 +7280,7 @@ static int ipw_wx_set_monitor(struct net_device *dev, if (enable) { if (priv->ieee->iw_mode != IW_MODE_MONITOR) { priv->net_dev->type = ARPHRD_IEEE80211; - ipw_adapter_restart(priv); + queue_work(priv->workqueue, &priv->adapter_restart); } ipw_set_channel(priv, parms[1]); @@ -6878,7 +7288,7 @@ static int ipw_wx_set_monitor(struct net_device *dev, if (priv->ieee->iw_mode != IW_MODE_MONITOR) return 0; priv->net_dev->type = ARPHRD_ETHER; - ipw_adapter_restart(priv); + queue_work(priv->workqueue, &priv->adapter_restart); } return 0; } @@ -6889,7 +7299,7 @@ static int ipw_wx_reset(struct net_device *dev, { struct ipw_priv *priv = ieee80211_priv(dev); IPW_DEBUG_WX("RESET\n"); - ipw_adapter_restart(priv); + queue_work(priv->workqueue, &priv->adapter_restart); return 0; } #endif // CONFIG_IPW_MONITOR @@ -6925,6 +7335,10 @@ static iw_handler ipw_wx_handlers[] = { IW_IOCTL(SIOCGIWENCODE) = ipw_wx_get_encode, IW_IOCTL(SIOCSIWPOWER) = ipw_wx_set_power, IW_IOCTL(SIOCGIWPOWER) = ipw_wx_get_power, + IW_IOCTL(SIOCSIWSPY) = iw_handler_set_spy, + IW_IOCTL(SIOCGIWSPY) = iw_handler_get_spy, + IW_IOCTL(SIOCSIWTHRSPY) = iw_handler_set_thrspy, + IW_IOCTL(SIOCGIWTHRSPY) = iw_handler_get_thrspy, }; #define IPW_PRIV_SET_POWER SIOCIWFIRSTPRIV @@ -6993,6 +7407,8 @@ static struct iw_handler_def ipw_wx_handler_def = { .private_args = ipw_priv_args, }; +static struct iw_public_data ipw_wx_data; + /* * Get wireless statistics. * Called by /proc/net/wireless @@ -7057,7 +7473,7 @@ static inline void init_sys_config(struct ipw_sys_config *sys_config) sys_config->dot11g_auto_detection = 0; sys_config->enable_cts_to_self = 0; sys_config->bt_coexist_collision_thr = 0; - sys_config->pass_noise_stats_to_host = 1; + sys_config->pass_noise_stats_to_host = 0; //1 -- fix for 256 } static int ipw_net_open(struct net_device *dev) @@ -7131,7 +7547,7 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb) tfd->control_flags.control_bits = TFD_NEED_IRQ_MASK; tfd->u.data.cmd_id = DINO_CMD_TX; - tfd->u.data.len = txb->payload_size; + tfd->u.data.len = cpu_to_le16(txb->payload_size); remaining_bytes = txb->payload_size; if (unlikely(!unicast)) tfd->u.data.tx_flags = DCT_FLAG_NO_WEP; @@ -7149,8 +7565,14 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb) memcpy(&tfd->u.data.tfd.tfd_24.mchdr, hdr, hdr_len); /* payload */ - tfd->u.data.num_chunks = min((u8) (NUM_TFD_CHUNKS - 2), txb->nr_frags); - for (i = 0; i < tfd->u.data.num_chunks; i++) { + tfd->u.data.num_chunks = cpu_to_le32(min((u8) (NUM_TFD_CHUNKS - 2), + txb->nr_frags)); + IPW_DEBUG_FRAG("%i fragments being sent as %i chunks.\n", + txb->nr_frags, le32_to_cpu(tfd->u.data.num_chunks)); + for (i = 0; i < le32_to_cpu(tfd->u.data.num_chunks); i++) { + IPW_DEBUG_FRAG("Adding fragment %i of %i (%d bytes).\n", + i, le32_to_cpu(tfd->u.data.num_chunks), + txb->fragments[i]->len - hdr_len); IPW_DEBUG_TX("Dumping TX packet frag %i of %i (%d bytes):\n", i, tfd->u.data.num_chunks, txb->fragments[i]->len - hdr_len); @@ -7158,11 +7580,13 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb) txb->fragments[i]->len - hdr_len); tfd->u.data.chunk_ptr[i] = - pci_map_single(priv->pci_dev, - txb->fragments[i]->data + hdr_len, - txb->fragments[i]->len - hdr_len, - PCI_DMA_TODEVICE); - tfd->u.data.chunk_len[i] = txb->fragments[i]->len - hdr_len; + cpu_to_le32(pci_map_single + (priv->pci_dev, + txb->fragments[i]->data + hdr_len, + txb->fragments[i]->len - hdr_len, + PCI_DMA_TODEVICE)); + tfd->u.data.chunk_len[i] = + cpu_to_le16(txb->fragments[i]->len - hdr_len); } if (i != txb->nr_frags) { @@ -7177,7 +7601,7 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb) remaining_bytes); skb = alloc_skb(remaining_bytes, GFP_ATOMIC); if (skb != NULL) { - tfd->u.data.chunk_len[i] = remaining_bytes; + tfd->u.data.chunk_len[i] = cpu_to_le16(remaining_bytes); for (j = i; j < txb->nr_frags; j++) { int size = txb->fragments[j]->len - hdr_len; printk(KERN_INFO "Adding frag %d %d...\n", @@ -7188,10 +7612,14 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb) dev_kfree_skb_any(txb->fragments[i]); txb->fragments[i] = skb; tfd->u.data.chunk_ptr[i] = - pci_map_single(priv->pci_dev, skb->data, - tfd->u.data.chunk_len[i], - PCI_DMA_TODEVICE); - tfd->u.data.num_chunks++; + cpu_to_le32(pci_map_single + (priv->pci_dev, skb->data, + tfd->u.data.chunk_len[i], + PCI_DMA_TODEVICE)); + + tfd->u.data.num_chunks = + cpu_to_le32(le32_to_cpu(tfd->u.data.num_chunks) + + 1); } } @@ -7227,6 +7655,7 @@ static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb, } ipw_tx_skb(priv, txb); + ipw_led_activity_on(priv); spin_unlock_irqrestore(&priv->lock, flags); return 0; @@ -7260,7 +7689,7 @@ static int ipw_net_set_mac_address(struct net_device *dev, void *p) memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN); printk(KERN_INFO "%s: Setting MAC to " MAC_FMT "\n", priv->net_dev->name, MAC_ARG(priv->mac_addr)); - ipw_adapter_restart(priv); + queue_work(priv->workqueue, &priv->adapter_restart); return 0; } @@ -7414,6 +7843,46 @@ static void ipw_rf_kill(void *adapter) spin_unlock_irqrestore(&priv->lock, flags); } +void ipw_link_up(struct ipw_priv *priv) +{ + netif_carrier_on(priv->net_dev); + if (netif_queue_stopped(priv->net_dev)) { + IPW_DEBUG_NOTIF("waking queue\n"); + netif_wake_queue(priv->net_dev); + } else { + IPW_DEBUG_NOTIF("starting queue\n"); + netif_start_queue(priv->net_dev); + } + + ipw_reset_stats(priv); + /* Ensure the rate is updated immediately */ + priv->last_rate = ipw_get_current_rate(priv); + ipw_gather_stats(priv); + ipw_led_link_up(priv); + notify_wx_assoc_event(priv); + + if (priv->config & CFG_BACKGROUND_SCAN) + queue_delayed_work(priv->workqueue, &priv->request_scan, HZ); +} + +void ipw_link_down(struct ipw_priv *priv) +{ + ipw_led_link_down(priv); + netif_carrier_off(priv->net_dev); + netif_stop_queue(priv->net_dev); + notify_wx_assoc_event(priv); + + /* Cancel any queued work ... */ + cancel_delayed_work(&priv->request_scan); + cancel_delayed_work(&priv->adhoc_check); + cancel_delayed_work(&priv->gather_stats); + + ipw_reset_stats(priv); + + /* Queue up another scan... */ + queue_work(priv->workqueue, &priv->request_scan); +} + static int ipw_setup_deferred_work(struct ipw_priv *priv) { int ret = 0; @@ -7436,6 +7905,13 @@ static int ipw_setup_deferred_work(struct ipw_priv *priv) INIT_WORK(&priv->abort_scan, (void (*)(void *))ipw_abort_scan, priv); INIT_WORK(&priv->roam, ipw_roam, priv); INIT_WORK(&priv->scan_check, ipw_scan_check, priv); + INIT_WORK(&priv->link_up, (void (*)(void *))ipw_link_up, priv); + INIT_WORK(&priv->link_down, (void (*)(void *))ipw_link_down, priv); + INIT_WORK(&priv->led_link_on, (void (*)(void *))ipw_led_link_on, priv); + INIT_WORK(&priv->led_link_off, (void (*)(void *))ipw_led_link_off, + priv); + INIT_WORK(&priv->led_act_off, (void (*)(void *))ipw_led_activity_off, + priv); tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) ipw_irq_tasklet, (unsigned long)priv); @@ -7636,8 +8112,9 @@ static int ipw_up(struct ipw_priv *priv) rc = ipw_config(priv); if (!rc) { IPW_DEBUG_INFO("Configured device on count %i\n", i); + ipw_led_init(priv); + ipw_led_radio_on(priv); priv->notif_missed_beacons = 0; - netif_start_queue(priv->net_dev); return 0; } else { IPW_DEBUG_INFO("Device configuration failed: 0x%08X\n", @@ -7675,11 +8152,12 @@ static void ipw_down(struct ipw_priv *priv) netif_stop_queue(priv->net_dev); ipw_stop_nic(priv); + + ipw_led_radio_off(priv); } static int ipw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { -#ifdef CONFIG_IEEE80211_WPA struct iwreq *wrq = (struct iwreq *)rq; int ret = -1; switch (cmd) { @@ -7691,8 +8169,6 @@ static int ipw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return -EOPNOTSUPP; } -#endif /* CONFIG_IEEE80211_WPA */ - return -EOPNOTSUPP; } @@ -7739,7 +8215,7 @@ static struct pci_device_id card_ids[] = { {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2762, 0, 0, 0}, {PCI_VENDOR_ID_INTEL, 0x104f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_INTEL, 0x4220, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* BG */ - {PCI_VENDOR_ID_INTEL, 0x4221, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* 2225BG */ + {PCI_VENDOR_ID_INTEL, 0x4221, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* BG */ {PCI_VENDOR_ID_INTEL, 0x4223, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* ABG */ {PCI_VENDOR_ID_INTEL, 0x4224, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* ABG */ @@ -7764,6 +8240,8 @@ static struct attribute *ipw_sysfs_entries[] = { &dev_attr_eeprom_delay.attr, &dev_attr_ucode_version.attr, &dev_attr_rtc.attr, + &dev_attr_scan_age.attr, + &dev_attr_led.attr, NULL }; @@ -7789,6 +8267,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) priv = ieee80211_priv(net_dev); priv->ieee = netdev_priv(net_dev); + priv->net_dev = net_dev; priv->pci_dev = pdev; #ifdef CONFIG_IPW_DEBUG @@ -7843,6 +8322,12 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } /* Initialize module parameter values here */ + + /* We default to disabling the LED code as right now it causes + * too many systems to lock up... */ + if (!led) + priv->config |= CFG_NO_LED; + if (associate) priv->config |= CFG_ASSOCIATE; else @@ -7893,14 +8378,9 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) priv->adapter = IPW_2915ABG; priv->ieee->mode = IEEE_A | IEEE_G | IEEE_B; } else { - if (priv->pci_dev->device == 0x4221) - printk(KERN_INFO DRV_NAME - ": Detected Intel PRO/Wireless 2225BG Network " - "Connection\n"); - else - printk(KERN_INFO DRV_NAME - ": Detected Intel PRO/Wireless 2200BG Network " - "Connection\n"); + printk(KERN_INFO DRV_NAME + ": Detected Intel PRO/Wireless 2200BG Network " + "Connection\n"); priv->ieee->abg_true = 0; band = IEEE80211_24GHZ_BAND; @@ -7933,6 +8413,9 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) SET_MODULE_OWNER(net_dev); SET_NETDEV_DEV(net_dev, &pdev->dev); + ipw_wx_data.spy_data = &priv->ieee->spy_data; + ipw_wx_data.ieee80211 = priv->ieee; + priv->ieee->hard_start_xmit = ipw_net_hard_start_xmit; priv->ieee->set_security = shim__set_security; @@ -7944,6 +8427,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) net_dev->set_multicast_list = ipw_net_set_multicast_list; net_dev->set_mac_address = ipw_net_set_mac_address; net_dev->get_wireless_stats = ipw_get_wireless_stats; + net_dev->wireless_data = &ipw_wx_data; net_dev->wireless_handlers = &ipw_wx_handler_def; net_dev->ethtool_ops = &ipw_ethtool_ops; net_dev->irq = pdev->irq; @@ -7960,12 +8444,12 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = register_netdev(net_dev); if (err) { IPW_ERROR("failed to register network device\n"); - goto out_remove_group; + goto out_remove_sysfs; } return 0; - out_remove_group: + out_remove_sysfs: sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group); out_release_irq: free_irq(pdev->irq, priv); @@ -8005,17 +8489,17 @@ static void ipw_pci_remove(struct pci_dev *pdev) } ipw_tx_queue_free(priv); + ipw_led_shutdown(priv); + /* ipw_down will ensure that there is no more pending work * in the workqueue's, so we can safely remove them now. */ - if (priv->workqueue) { - cancel_delayed_work(&priv->adhoc_check); - cancel_delayed_work(&priv->gather_stats); - cancel_delayed_work(&priv->request_scan); - cancel_delayed_work(&priv->rf_kill); - cancel_delayed_work(&priv->scan_check); - destroy_workqueue(priv->workqueue); - priv->workqueue = NULL; - } + cancel_delayed_work(&priv->adhoc_check); + cancel_delayed_work(&priv->gather_stats); + cancel_delayed_work(&priv->request_scan); + cancel_delayed_work(&priv->rf_kill); + cancel_delayed_work(&priv->scan_check); + destroy_workqueue(priv->workqueue); + priv->workqueue = NULL; free_irq(pdev->irq, priv); iounmap(priv->hw_base); @@ -8138,6 +8622,10 @@ MODULE_PARM_DESC(associate, "auto associate when scanning (default on)"); module_param(auto_create, int, 0444); MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)"); +module_param(led, int, 0444); +MODULE_PARM_DESC(auto_create, + "enable led control on some systems (default 0 off)\n"); + module_param(debug, int, 0444); MODULE_PARM_DESC(debug, "debug output mask"); diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index 06802796318..1b339cb7a52 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -403,9 +403,9 @@ struct clx2_tx_queue { #define RX_FREE_BUFFERS 32 #define RX_LOW_WATERMARK 8 -#define SUP_RATE_11A_MAX_NUM_CHANNELS (8) -#define SUP_RATE_11B_MAX_NUM_CHANNELS (4) -#define SUP_RATE_11G_MAX_NUM_CHANNELS (12) +#define SUP_RATE_11A_MAX_NUM_CHANNELS 8 +#define SUP_RATE_11B_MAX_NUM_CHANNELS 4 +#define SUP_RATE_11G_MAX_NUM_CHANNELS 12 // Used for passing to driver number of successes and failures per rate struct rate_histogram { @@ -890,6 +890,9 @@ struct ipw_cmd { #define STATUS_SCANNING (1<<21) #define STATUS_SCAN_ABORTING (1<<22) +#define STATUS_LED_LINK_ON (1<<24) +#define STATUS_LED_ACT_ON (1<<25) + #define STATUS_INDIRECT_BYTE (1<<28) /* sysfs entry configured for access */ #define STATUS_INDIRECT_DWORD (1<<29) /* sysfs entry configured for access */ #define STATUS_DIRECT_DWORD (1<<30) /* sysfs entry configured for access */ @@ -905,6 +908,8 @@ struct ipw_cmd { #define CFG_ASSOCIATE (1<<6) #define CFG_FIXED_RATE (1<<7) #define CFG_ADHOC_CREATE (1<<8) +#define CFG_NO_LED (1<<9) +#define CFG_BACKGROUND_SCAN (1<<10) #define CAP_SHARED_KEY (1<<0) /* Off = OPEN */ #define CAP_PRIVACY_ON (1<<1) /* Off = No privacy */ @@ -1046,9 +1051,24 @@ struct ipw_priv { struct work_struct abort_scan; struct work_struct roam; struct work_struct scan_check; + struct work_struct link_up; + struct work_struct link_down; struct tasklet_struct irq_tasklet; + /* LED related variables and work_struct */ + u8 nic_type; + u32 led_activity_on; + u32 led_activity_off; + u32 led_association_on; + u32 led_association_off; + u32 led_ofdm_on; + u32 led_ofdm_off; + + struct work_struct led_link_on; + struct work_struct led_link_off; + struct work_struct led_act_off; + #define IPW_2200BG 1 #define IPW_2915ABG 2 u8 adapter; @@ -1126,6 +1146,8 @@ do { if (ipw_debug_level & (level)) \ #define IPW_DL_RF_KILL (1<<17) #define IPW_DL_FW_ERRORS (1<<18) +#define IPW_DL_LED (1<<19) + #define IPW_DL_ORD (1<<20) #define IPW_DL_FRAG (1<<21) @@ -1151,6 +1173,7 @@ do { if (ipw_debug_level & (level)) \ #define IPW_DEBUG_TX(f, a...) IPW_DEBUG(IPW_DL_TX, f, ## a) #define IPW_DEBUG_ISR(f, a...) IPW_DEBUG(IPW_DL_ISR, f, ## a) #define IPW_DEBUG_MANAGEMENT(f, a...) IPW_DEBUG(IPW_DL_MANAGE, f, ## a) +#define IPW_DEBUG_LED(f, a...) IPW_DEBUG(IPW_DL_LED, f, ## a) #define IPW_DEBUG_WEP(f, a...) IPW_DEBUG(IPW_DL_WEP, f, ## a) #define IPW_DEBUG_HC(f, a...) IPW_DEBUG(IPW_DL_HOST_COMMAND, f, ## a) #define IPW_DEBUG_FRAG(f, a...) IPW_DEBUG(IPW_DL_FRAG, f, ## a) @@ -1268,25 +1291,25 @@ do { if (ipw_debug_level & (level)) \ #define CX2_DMA_I_DMA_CONTROL 0x003000A4 #define CX2_DMA_I_CB_BASE 0x003000A0 -#define CX2_TX_CMD_QUEUE_BD_BASE (0x00000200) -#define CX2_TX_CMD_QUEUE_BD_SIZE (0x00000204) -#define CX2_TX_QUEUE_0_BD_BASE (0x00000208) +#define CX2_TX_CMD_QUEUE_BD_BASE 0x00000200 +#define CX2_TX_CMD_QUEUE_BD_SIZE 0x00000204 +#define CX2_TX_QUEUE_0_BD_BASE 0x00000208 #define CX2_TX_QUEUE_0_BD_SIZE (0x0000020C) -#define CX2_TX_QUEUE_1_BD_BASE (0x00000210) -#define CX2_TX_QUEUE_1_BD_SIZE (0x00000214) -#define CX2_TX_QUEUE_2_BD_BASE (0x00000218) +#define CX2_TX_QUEUE_1_BD_BASE 0x00000210 +#define CX2_TX_QUEUE_1_BD_SIZE 0x00000214 +#define CX2_TX_QUEUE_2_BD_BASE 0x00000218 #define CX2_TX_QUEUE_2_BD_SIZE (0x0000021C) -#define CX2_TX_QUEUE_3_BD_BASE (0x00000220) -#define CX2_TX_QUEUE_3_BD_SIZE (0x00000224) -#define CX2_RX_BD_BASE (0x00000240) -#define CX2_RX_BD_SIZE (0x00000244) -#define CX2_RFDS_TABLE_LOWER (0x00000500) - -#define CX2_TX_CMD_QUEUE_READ_INDEX (0x00000280) -#define CX2_TX_QUEUE_0_READ_INDEX (0x00000284) -#define CX2_TX_QUEUE_1_READ_INDEX (0x00000288) +#define CX2_TX_QUEUE_3_BD_BASE 0x00000220 +#define CX2_TX_QUEUE_3_BD_SIZE 0x00000224 +#define CX2_RX_BD_BASE 0x00000240 +#define CX2_RX_BD_SIZE 0x00000244 +#define CX2_RFDS_TABLE_LOWER 0x00000500 + +#define CX2_TX_CMD_QUEUE_READ_INDEX 0x00000280 +#define CX2_TX_QUEUE_0_READ_INDEX 0x00000284 +#define CX2_TX_QUEUE_1_READ_INDEX 0x00000288 #define CX2_TX_QUEUE_2_READ_INDEX (0x0000028C) -#define CX2_TX_QUEUE_3_READ_INDEX (0x00000290) +#define CX2_TX_QUEUE_3_READ_INDEX 0x00000290 #define CX2_RX_READ_INDEX (0x000002A0) #define CX2_TX_CMD_QUEUE_WRITE_INDEX (0x00000F80) @@ -1333,15 +1356,15 @@ do { if (ipw_debug_level & (level)) \ #define EEPROM_HW_VERSION (GET_EEPROM_ADDR(0x72,LSB)) /* 2 bytes */ /* NIC type as found in the one byte EEPROM_NIC_TYPE offset*/ -#define EEPROM_NIC_TYPE_STANDARD 0 -#define EEPROM_NIC_TYPE_DELL 1 -#define EEPROM_NIC_TYPE_FUJITSU 2 -#define EEPROM_NIC_TYPE_IBM 3 -#define EEPROM_NIC_TYPE_HP 4 +#define EEPROM_NIC_TYPE_0 0 +#define EEPROM_NIC_TYPE_1 1 +#define EEPROM_NIC_TYPE_2 2 +#define EEPROM_NIC_TYPE_3 3 +#define EEPROM_NIC_TYPE_4 4 #define FW_MEM_REG_LOWER_BOUND 0x00300000 #define FW_MEM_REG_EEPROM_ACCESS (FW_MEM_REG_LOWER_BOUND + 0x40) - +#define CX2_EVENT_REG (FW_MEM_REG_LOWER_BOUND + 0x04) #define EEPROM_BIT_SK (1<<0) #define EEPROM_BIT_CS (1<<1) #define EEPROM_BIT_DI (1<<2) -- cgit v1.2.3 From c848d0af404f00835f038e370005733d90a186fd Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Wed, 24 Aug 2005 21:56:24 -0500 Subject: Catch ipw2200 up to equivelancy with v1.0.3 * Fix #616 problem with OOPS on module load (thanks to Yi Zhu) * Fixed problem with led module parameter being described as 'auto_create' * Added support to merge between adhoc networks (thanks to Mohamed Abbas) * Added semaphore lock at the driver's entry points to protect against re-entry (thanks to Mohamed Abbas) * Added semaphore lock to background scheduled driver actions (thanks to Mohamed Abbas) * Changed how signal quality is reported for scan output (thanks to Peter Jones) * Fixed how high/low clamp values of signal quality are reported so a more consistent ramp is provided (thanks to Bill Moss) * Fix #624 problem with duplicate addresses (again) (thanks to Bernard Blackham) * Fix #385 problem with fragmentation and certain sized packets (thanks to Mohamed Abbas) * Modified iwconfig network name if RF kill is enabled to say 'radio off' * Fix #382 problem with driver not responding to probe requests in Ad-Hoc mode (thanks to Mohamed Abbas) Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 841 ++++++++++++++++++++++++++++++++--------- drivers/net/wireless/ipw2200.h | 5 +- 2 files changed, 668 insertions(+), 178 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index ea7a3dcf1da..0bf1931ac5f 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -32,7 +32,7 @@ #include "ipw2200.h" -#define IPW2200_VERSION "1.0.2" +#define IPW2200_VERSION "1.0.3" #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation" #define DRV_VERSION IPW2200_VERSION @@ -68,9 +68,10 @@ static void ipw_tx_queue_free(struct ipw_priv *); static struct ipw_rx_queue *ipw_rx_queue_alloc(struct ipw_priv *); static void ipw_rx_queue_free(struct ipw_priv *, struct ipw_rx_queue *); static void ipw_rx_queue_replenish(void *); - static int ipw_up(struct ipw_priv *); +static void ipw_bg_up(void *); static void ipw_down(struct ipw_priv *); +static void ipw_bg_down(void *); static int ipw_config(struct ipw_priv *); static int init_supported_rates(struct ipw_priv *priv, struct ipw_supported_rates *prates); @@ -473,6 +474,11 @@ static void ipw_dump_nic_event_log(struct ipw_priv *priv) } } +static inline int ipw_is_init(struct ipw_priv *priv) +{ + return (priv->status & STATUS_INIT) ? 1 : 0; +} + static int ipw_get_ordinal(struct ipw_priv *priv, u32 ord, void *val, u32 * len) { u32 addr, field_info, field_len, field_count, total_len; @@ -698,6 +704,14 @@ void ipw_led_link_on(struct ipw_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } +static void ipw_bg_led_link_on(void *data) +{ + struct ipw_priv *priv = data; + down(&priv->sem); + ipw_led_link_on(data); + up(&priv->sem); +} + void ipw_led_link_off(struct ipw_priv *priv) { unsigned long flags; @@ -734,6 +748,14 @@ void ipw_led_link_off(struct ipw_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } +static void ipw_bg_led_link_off(void *data) +{ + struct ipw_priv *priv = data; + down(&priv->sem); + ipw_led_link_off(data); + up(&priv->sem); +} + void ipw_led_activity_on(struct ipw_priv *priv) { unsigned long flags; @@ -762,6 +784,7 @@ void ipw_led_activity_on(struct ipw_priv *priv) priv->status |= STATUS_LED_ACT_ON; + cancel_delayed_work(&priv->led_act_off); queue_delayed_work(priv->workqueue, &priv->led_act_off, LD_TIME_ACT_ON); } else { @@ -801,13 +824,22 @@ void ipw_led_activity_off(struct ipw_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } +static void ipw_bg_led_activity_off(void *data) +{ + struct ipw_priv *priv = data; + down(&priv->sem); + ipw_led_activity_off(data); + up(&priv->sem); +} + void ipw_led_band_on(struct ipw_priv *priv) { unsigned long flags; u32 led; /* Only nic type 1 supports mode LEDs */ - if (priv->config & CFG_NO_LED || priv->nic_type != EEPROM_NIC_TYPE_1) + if (priv->config & CFG_NO_LED || + priv->nic_type != EEPROM_NIC_TYPE_1 || !priv->assoc_network) return; spin_lock_irqsave(&priv->lock, flags); @@ -993,7 +1025,9 @@ static ssize_t store_scan_age(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { struct ipw_priv *priv = dev_get_drvdata(d); +#ifdef CONFIG_IPW_DEBUG struct net_device *dev = priv->net_dev; +#endif char buffer[] = "00000000"; unsigned long len = (sizeof(buffer) - 1) > count ? count : sizeof(buffer) - 1; @@ -1704,6 +1738,14 @@ static void ipw_adapter_restart(void *adapter) } } +static void ipw_bg_adapter_restart(void *data) +{ + struct ipw_priv *priv = data; + down(&priv->sem); + ipw_adapter_restart(data); + up(&priv->sem); +} + #define IPW_SCAN_CHECK_WATCHDOG (5 * HZ) static void ipw_scan_check(void *data) @@ -1717,6 +1759,14 @@ static void ipw_scan_check(void *data) } } +static void ipw_bg_scan_check(void *data) +{ + struct ipw_priv *priv = data; + down(&priv->sem); + ipw_scan_check(data); + up(&priv->sem); +} + static int ipw_send_scan_request_ext(struct ipw_priv *priv, struct ipw_scan_request_ext *request) { @@ -2982,6 +3032,8 @@ static int ipw_load(struct ipw_priv *priv) /* Ensure interrupts are disabled */ ipw_write32(priv, CX2_INTA_MASK_R, ~CX2_INTA_MASK_ALL); + /* ack pending interrupts */ + ipw_write32(priv, CX2_INTA_RW, CX2_INTA_MASK_ALL); /* kick start the device */ ipw_start_nic(priv); @@ -3350,9 +3402,21 @@ static void ipw_send_disassociate(struct ipw_priv *priv, int quiet) } -static void ipw_disassociate(void *data) +static int ipw_disassociate(void *data) { + struct ipw_priv *priv = data; + if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING))) + return 0; ipw_send_disassociate(data, 0); + return 1; +} + +static void ipw_bg_disassociate(void *data) +{ + struct ipw_priv *priv = data; + down(&priv->sem); + ipw_disassociate(data); + up(&priv->sem); } struct ipw_status_code { @@ -3571,8 +3635,6 @@ static u32 ipw_get_current_rate(struct ipw_priv *priv) return 0; } -#define PERFECT_RSSI (-20) -#define WORST_RSSI (-85) #define IPW_STATS_INTERVAL (2 * HZ) static void ipw_gather_stats(struct ipw_priv *priv) { @@ -3663,19 +3725,19 @@ static void ipw_gather_stats(struct ipw_priv *priv) tx_quality, tx_failures_delta, tx_packets_delta); rssi = average_value(&priv->average_rssi); - if (rssi > PERFECT_RSSI) + signal_quality = + (100 * + (priv->ieee->perfect_rssi - priv->ieee->worst_rssi) * + (priv->ieee->perfect_rssi - priv->ieee->worst_rssi) - + (priv->ieee->perfect_rssi - rssi) * + (15 * (priv->ieee->perfect_rssi - priv->ieee->worst_rssi) + + 62 * (priv->ieee->perfect_rssi - rssi))) / + ((priv->ieee->perfect_rssi - priv->ieee->worst_rssi) * + (priv->ieee->perfect_rssi - priv->ieee->worst_rssi)); + if (signal_quality > 100) signal_quality = 100; - else if (rssi < WORST_RSSI) + else if (signal_quality < 1) signal_quality = 0; - else /* qual = 100a^2 - 15ab + 62b^2 / a^2 */ - signal_quality = - (100 * - (PERFECT_RSSI - WORST_RSSI) * - (PERFECT_RSSI - WORST_RSSI) - - (PERFECT_RSSI - rssi) * - (15 * (PERFECT_RSSI - WORST_RSSI) + - 62 * (PERFECT_RSSI - rssi))) / - ((PERFECT_RSSI - WORST_RSSI) * (PERFECT_RSSI - WORST_RSSI)); IPW_DEBUG_STATS("Signal level : %3d%% (%d dBm)\n", signal_quality, rssi); @@ -3705,6 +3767,14 @@ static void ipw_gather_stats(struct ipw_priv *priv) IPW_STATS_INTERVAL); } +static void ipw_bg_gather_stats(void *data) +{ + struct ipw_priv *priv = data; + down(&priv->sem); + ipw_gather_stats(data); + up(&priv->sem); +} + static inline void ipw_handle_missed_beacon(struct ipw_priv *priv, int missed_count) { @@ -4456,6 +4526,14 @@ static void ipw_rx_queue_replenish(void *data) ipw_rx_queue_restock(priv); } +static void ipw_bg_rx_queue_replenish(void *data) +{ + struct ipw_priv *priv = data; + down(&priv->sem); + ipw_rx_queue_replenish(data); + up(&priv->sem); +} + /* Assumes that the skb field of the buffers in 'pool' is kept accurate. * If an SKB has been detached, the POOL needs to have it's SKB set to NULL * This free routine walks the list of POOL entries and if SKB is set to @@ -4715,6 +4793,215 @@ struct ipw_network_match { struct ipw_supported_rates rates; }; +static int ipw_find_adhoc_network(struct ipw_priv *priv, + struct ipw_network_match *match, + struct ieee80211_network *network, + int roaming) +{ + struct ipw_supported_rates rates; + + /* Verify that this network's capability is compatible with the + * current mode (AdHoc or Infrastructure) */ + if ((priv->ieee->iw_mode == IW_MODE_ADHOC && + !(network->capability & WLAN_CAPABILITY_IBSS))) { + IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded due to " + "capability mismatch.\n", + escape_essid(network->ssid, network->ssid_len), + MAC_ARG(network->bssid)); + return 0; + } + + /* If we do not have an ESSID for this AP, we can not associate with + * it */ + if (network->flags & NETWORK_EMPTY_ESSID) { + IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded " + "because of hidden ESSID.\n", + escape_essid(network->ssid, network->ssid_len), + MAC_ARG(network->bssid)); + return 0; + } + + if (unlikely(roaming)) { + /* If we are roaming, then ensure check if this is a valid + * network to try and roam to */ + if ((network->ssid_len != match->network->ssid_len) || + memcmp(network->ssid, match->network->ssid, + network->ssid_len)) { + IPW_DEBUG_MERGE("Netowrk '%s (" MAC_FMT ")' excluded " + "because of non-network ESSID.\n", + escape_essid(network->ssid, + network->ssid_len), + MAC_ARG(network->bssid)); + return 0; + } + } else { + /* If an ESSID has been configured then compare the broadcast + * ESSID to ours */ + if ((priv->config & CFG_STATIC_ESSID) && + ((network->ssid_len != priv->essid_len) || + memcmp(network->ssid, priv->essid, + min(network->ssid_len, priv->essid_len)))) { + char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; + strncpy(escaped, + escape_essid(network->ssid, network->ssid_len), + sizeof(escaped)); + IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded " + "because of ESSID mismatch: '%s'.\n", + escaped, MAC_ARG(network->bssid), + escape_essid(priv->essid, + priv->essid_len)); + return 0; + } + } + + /* If the old network rate is better than this one, don't bother + * testing everything else. */ + + if (network->time_stamp[0] < match->network->time_stamp[0]) { + IPW_DEBUG_MERGE + ("Network '%s excluded because newer than current network.\n", + escape_essid(match->network->ssid, + match->network->ssid_len)); + return 0; + } else if (network->time_stamp[1] < match->network->time_stamp[1]) { + IPW_DEBUG_MERGE + ("Network '%s excluded because newer than current network.\n", + escape_essid(match->network->ssid, + match->network->ssid_len)); + return 0; + } + + /* Now go through and see if the requested network is valid... */ + if (priv->ieee->scan_age != 0 && + time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) { + IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded " + "because of age: %lums.\n", + escape_essid(network->ssid, network->ssid_len), + MAC_ARG(network->bssid), + (jiffies - network->last_scanned) / (HZ / 100)); + return 0; + } + + if ((priv->config & CFG_STATIC_CHANNEL) && + (network->channel != priv->channel)) { + IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded " + "because of channel mismatch: %d != %d.\n", + escape_essid(network->ssid, network->ssid_len), + MAC_ARG(network->bssid), + network->channel, priv->channel); + return 0; + } + + /* Verify privacy compatability */ + if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) != + ((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) { + IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded " + "because of privacy mismatch: %s != %s.\n", + escape_essid(network->ssid, network->ssid_len), + MAC_ARG(network->bssid), + priv->capability & CAP_PRIVACY_ON ? "on" : + "off", + network->capability & + WLAN_CAPABILITY_PRIVACY ? "on" : "off"); + return 0; + } + + if (!memcmp(network->bssid, priv->bssid, ETH_ALEN)) { + IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded " + "because of the same BSSID match: " MAC_FMT + ".\n", escape_essid(network->ssid, + network->ssid_len), + MAC_ARG(network->bssid), MAC_ARG(priv->bssid)); + return 0; + } + + /* Filter out any incompatible freq / mode combinations */ + if (!ieee80211_is_valid_mode(priv->ieee, network->mode)) { + IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded " + "because of invalid frequency/mode " + "combination.\n", + escape_essid(network->ssid, network->ssid_len), + MAC_ARG(network->bssid)); + return 0; + } + + /* Ensure that the rates supported by the driver are compatible with + * this AP, including verification of basic rates (mandatory) */ + if (!ipw_compatible_rates(priv, network, &rates)) { + IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded " + "because configured rate mask excludes " + "AP mandatory rate.\n", + escape_essid(network->ssid, network->ssid_len), + MAC_ARG(network->bssid)); + return 0; + } + + if (rates.num_rates == 0) { + IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded " + "because of no compatible rates.\n", + escape_essid(network->ssid, network->ssid_len), + MAC_ARG(network->bssid)); + return 0; + } + + /* TODO: Perform any further minimal comparititive tests. We do not + * want to put too much policy logic here; intelligent scan selection + * should occur within a generic IEEE 802.11 user space tool. */ + + /* Set up 'new' AP to this network */ + ipw_copy_rates(&match->rates, &rates); + match->network = network; + IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' is a viable match.\n", + escape_essid(network->ssid, network->ssid_len), + MAC_ARG(network->bssid)); + + return 1; +} + +static void ipw_merge_adhoc_network(void *data) +{ + struct ipw_priv *priv = data; + struct ieee80211_network *network = NULL; + struct ipw_network_match match = { + .network = priv->assoc_network + }; + + if ((priv->status & STATUS_ASSOCIATED) + && (priv->ieee->iw_mode == IW_MODE_ADHOC)) { + /* First pass through ROAM process -- look for a better + * network */ + unsigned long flags; + + spin_lock_irqsave(&priv->ieee->lock, flags); + list_for_each_entry(network, &priv->ieee->network_list, list) { + if (network != priv->assoc_network) + ipw_find_adhoc_network(priv, &match, network, + 1); + } + spin_unlock_irqrestore(&priv->ieee->lock, flags); + + if (match.network == priv->assoc_network) { + IPW_DEBUG_MERGE("No better ADHOC in this network to " + "merge to.\n"); + return; + } + + down(&priv->sem); + if ((priv->ieee->iw_mode == IW_MODE_ADHOC)) { + IPW_DEBUG_MERGE("remove network %s\n", + escape_essid(priv->essid, + priv->essid_len)); + ipw_remove_current_network(priv); + } + + ipw_disassociate(priv); + priv->assoc_network = match.network; + up(&priv->sem); + return; + } + +} + static int ipw_best_network(struct ipw_priv *priv, struct ipw_network_match *match, struct ieee80211_network *network, int roaming) @@ -4997,6 +5284,14 @@ static void ipw_adhoc_check(void *data) priv->assoc_request.beacon_interval); } +static void ipw_bg_adhoc_check(void *data) +{ + struct ipw_priv *priv = data; + down(&priv->sem); + ipw_adhoc_check(data); + up(&priv->sem); +} + #ifdef CONFIG_IPW_DEBUG static void ipw_debug_config(struct ipw_priv *priv) { @@ -5181,10 +5476,9 @@ static int ipw_request_scan(struct ipw_priv *priv) /* If we are roaming, then make this a directed scan for the current * network. Otherwise, ensure that every other scan is a fast * channel hop scan */ - if ((priv->status & STATUS_ROAMING) - || (!(priv->status & STATUS_ASSOCIATED) - && (priv->config & CFG_STATIC_ESSID) - && (le32_to_cpu(scan.full_scan_index) % 2))) { + if ((priv->status & STATUS_ROAMING) || (!(priv->status & STATUS_ASSOCIATED) && (priv->config & CFG_STATIC_ESSID) && (le32_to_cpu(scan.full_scan_index) % 2))) { /* || ( + (priv->status & STATUS_ASSOCIATED) && + (priv->ieee->iw_mode == IW_MODE_ADHOC))) { */ err = ipw_send_ssid(priv, priv->essid, priv->essid_len); if (err) { IPW_DEBUG_HC @@ -5257,6 +5551,22 @@ static int ipw_request_scan(struct ipw_priv *priv) return 0; } +static void ipw_bg_request_scan(void *data) +{ + struct ipw_priv *priv = data; + down(&priv->sem); + ipw_request_scan(data); + up(&priv->sem); +} + +static void ipw_bg_abort_scan(void *data) +{ + struct ipw_priv *priv = data; + down(&priv->sem); + ipw_abort_scan(data); + up(&priv->sem); +} + /* Support for wpa_supplicant. Will be replaced with WEXT once * they get WPA support. */ @@ -5473,8 +5783,7 @@ void ipw_wpa_assoc_frame(struct ipw_priv *priv, char *wpa_ie, int wpa_ie_len) /* make sure WPA is enabled */ ipw_wpa_enable(priv, 1); - if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) - ipw_disassociate(priv); + ipw_disassociate(priv); } static int ipw_wpa_set_wpa_ie(struct net_device *dev, @@ -5830,6 +6139,12 @@ static int ipw_associate_network(struct ipw_priv *priv, priv->sys_config.dot11g_auto_detection = 1; else priv->sys_config.dot11g_auto_detection = 0; + + if (priv->ieee->iw_mode == IW_MODE_ADHOC) + priv->sys_config.answer_broadcast_ssid_probe = 1; + else + priv->sys_config.answer_broadcast_ssid_probe = 0; + err = ipw_send_system_config(priv, &priv->sys_config); if (err) { IPW_DEBUG_HC("Attempt to send sys config command failed.\n"); @@ -5933,7 +6248,15 @@ static void ipw_roam(void *data) priv->status &= ~STATUS_ROAMING; } -static void ipw_associate(void *data) +static void ipw_bg_roam(void *data) +{ + struct ipw_priv *priv = data; + down(&priv->sem); + ipw_roam(data); + up(&priv->sem); +} + +static int ipw_associate(void *data) { struct ipw_priv *priv = data; @@ -5945,11 +6268,23 @@ static void ipw_associate(void *data) struct list_head *element; unsigned long flags; + if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { + IPW_DEBUG_ASSOC + ("Not attempting association (already in progress)\n"); + return 0; + } + + if (!ipw_is_init(priv) || (priv->status & STATUS_SCANNING)) { + IPW_DEBUG_ASSOC + ("Not attempting association (scanning or not initialized)\n"); + return 0; + } + if (!(priv->config & CFG_ASSOCIATE) && !(priv->config & (CFG_STATIC_ESSID | CFG_STATIC_CHANNEL | CFG_STATIC_BSSID))) { IPW_DEBUG_ASSOC("Not attempting association (associate=0)\n"); - return; + return 0; } /* Protect our use of the network_list */ @@ -5984,10 +6319,20 @@ static void ipw_associate(void *data) queue_delayed_work(priv->workqueue, &priv->request_scan, SCAN_INTERVAL); - return; + return 0; } ipw_associate_network(priv, network, rates, 0); + + return 1; +} + +static void ipw_bg_associate(void *data) +{ + struct ipw_priv *priv = data; + down(&priv->sem); + ipw_associate(data); + up(&priv->sem); } static inline void ipw_handle_data_packet(struct ipw_priv *priv, @@ -6037,6 +6382,10 @@ static inline int is_network_packet(struct ipw_priv *priv, * this network, discarding packets coming from ourselves */ switch (priv->ieee->iw_mode) { case IW_MODE_ADHOC: /* Header: Dest. | Source | BSSID */ + /* packets from our adapter are dropped (echo) */ + if (!memcmp(header->addr2, priv->net_dev->dev_addr, ETH_ALEN)) + return 0; + /* {broad,multi}cast packets to our IBSS go through */ if (is_broadcast_ether_addr(header->addr1) || is_multicast_ether_addr(header->addr1)) @@ -6045,9 +6394,12 @@ static inline int is_network_packet(struct ipw_priv *priv, /* packets to our adapter go through */ return !memcmp(header->addr1, priv->net_dev->dev_addr, ETH_ALEN); - break; case IW_MODE_INFRA: /* Header: Dest. | AP{BSSID} | Source */ + /* packets from our adapter are dropped (echo) */ + if (!memcmp(header->addr3, priv->net_dev->dev_addr, ETH_ALEN)) + return 0; + /* {broad,multi}cast packets to our IBSS go through */ if (is_broadcast_ether_addr(header->addr1) || is_multicast_ether_addr(header->addr1)) @@ -6056,7 +6408,6 @@ static inline int is_network_packet(struct ipw_priv *priv, /* packets to our adapter go through */ return !memcmp(header->addr1, priv->net_dev->dev_addr, ETH_ALEN); - break; } return 1; @@ -6101,9 +6452,13 @@ static void ipw_rx(struct ipw_priv *priv) switch (pkt->header.message_type) { case RX_FRAME_TYPE: /* 802.11 frame */ { struct ieee80211_rx_stats stats = { - .rssi = pkt->u.frame.rssi_dbm - + .rssi = + le16_to_cpu(pkt->u.frame.rssi_dbm) - IPW_RSSI_TO_DBM, - /* .signal = le16_to_cpu(pkt->u.frame.signal), */ + .signal = + le16_to_cpu(pkt->u.frame.signal), + .noise = + le16_to_cpu(pkt->u.frame.noise), .rate = pkt->u.frame.rate, .mac_time = jiffies, .received_channel = @@ -6120,6 +6475,8 @@ static void ipw_rx(struct ipw_priv *priv) stats.mask |= IEEE80211_STATMASK_RSSI; if (stats.signal != 0) stats.mask |= IEEE80211_STATMASK_SIGNAL; + if (stats.noise != 0) + stats.mask |= IEEE80211_STATMASK_NOISE; if (stats.rate != 0) stats.mask |= IEEE80211_STATMASK_RATE; @@ -6179,11 +6536,34 @@ static void ipw_rx(struct ipw_priv *priv) || (WLAN_FC_GET_STYPE (le16_to_cpu(header->frame_ctl)) - == IEEE80211_STYPE_BEACON)) - && !memcmp(header->addr3, - priv->bssid, ETH_ALEN)) - ipw_add_station(priv, - header->addr2); + == IEEE80211_STYPE_BEACON))) { + if (!memcmp + (header->addr3, priv->bssid, + ETH_ALEN)) + ipw_add_station(priv, + header-> + addr2); + else { + struct + ieee80211_probe_response + *beacon; + beacon = + (struct + ieee80211_probe_response + *)header; + if (le16_to_cpu + (beacon-> + capability) & + WLAN_CAPABILITY_IBSS) + { + queue_work + (priv-> + workqueue, + &priv-> + merge_networks); + } + } + } break; case IEEE80211_FTYPE_CTL: @@ -6262,14 +6642,16 @@ static int ipw_wx_get_name(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - if (priv->status & STATUS_RF_KILL_MASK) { + down(&priv->sem); + if (priv->status & STATUS_RF_KILL_MASK) strcpy(wrqu->name, "radio off"); - } else if (!(priv->status & STATUS_ASSOCIATED)) + else if (!(priv->status & STATUS_ASSOCIATED)) strcpy(wrqu->name, "unassociated"); else snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11%c", ipw_modes[priv->assoc_request.ieee_mode]); IPW_DEBUG_WX("Name: %s\n", wrqu->name); + up(&priv->sem); return 0; } @@ -6278,13 +6660,9 @@ static int ipw_set_channel(struct ipw_priv *priv, u8 channel) if (channel == 0) { IPW_DEBUG_INFO("Setting channel to ANY (0)\n"); priv->config &= ~CFG_STATIC_CHANNEL; - if (!(priv->status & (STATUS_SCANNING | STATUS_ASSOCIATED | - STATUS_ASSOCIATING))) { - IPW_DEBUG_ASSOC("Attempting to associate with new " - "parameters.\n"); - ipw_associate(priv); - } - + IPW_DEBUG_ASSOC("Attempting to associate with new " + "parameters.\n"); + ipw_associate(priv); return 0; } @@ -6299,12 +6677,9 @@ static int ipw_set_channel(struct ipw_priv *priv, u8 channel) IPW_DEBUG_INFO("Setting channel to %i\n", (int)channel); priv->channel = channel; - /* If we are currently associated, or trying to associate - * then see if this is a new channel (causing us to disassociate) */ - if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { - IPW_DEBUG_ASSOC("Disassociating due to channel change.\n"); - ipw_disassociate(priv); - } else if (!(priv->status & (STATUS_SCANNING))) + /* Network configuration changed -- force [re]association */ + IPW_DEBUG_ASSOC("[re]association triggered due to channel change.\n"); + if (!ipw_disassociate(priv)) ipw_associate(priv); return 0; @@ -6316,6 +6691,7 @@ static int ipw_wx_set_freq(struct net_device *dev, { struct ipw_priv *priv = ieee80211_priv(dev); struct iw_freq *fwrq = &wrqu->freq; + int ret = 0; /* if setting by freq convert to channel */ if (fwrq->e == 1) { @@ -6337,7 +6713,10 @@ static int ipw_wx_set_freq(struct net_device *dev, return -EOPNOTSUPP; IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m); - return ipw_set_channel(priv, (u8) fwrq->m); + down(&priv->sem); + ret = ipw_set_channel(priv, (u8) fwrq->m); + up(&priv->sem); + return ret; } static int ipw_wx_get_freq(struct net_device *dev, @@ -6350,12 +6729,14 @@ static int ipw_wx_get_freq(struct net_device *dev, /* If we are associated, trying to associate, or have a statically * configured CHANNEL then return that; otherwise return ANY */ + down(&priv->sem); if (priv->config & CFG_STATIC_CHANNEL || priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED)) wrqu->freq.m = priv->channel; else wrqu->freq.m = 0; + up(&priv->sem); IPW_DEBUG_WX("GET Freq/Channel -> %d \n", priv->channel); return 0; } @@ -6368,9 +6749,11 @@ static int ipw_wx_set_mode(struct net_device *dev, int err = 0; IPW_DEBUG_WX("Set MODE: %d\n", wrqu->mode); - - if (wrqu->mode == priv->ieee->iw_mode) + down(&priv->sem); + if (wrqu->mode == priv->ieee->iw_mode) { + up(&priv->sem); return 0; + } switch (wrqu->mode) { #ifdef CONFIG_IPW_MONITOR @@ -6383,6 +6766,7 @@ static int ipw_wx_set_mode(struct net_device *dev, wrqu->mode = IW_MODE_INFRA; break; default: + up(&priv->sem); return -EINVAL; } @@ -6407,8 +6791,9 @@ static int ipw_wx_set_mode(struct net_device *dev, #endif priv->ieee->iw_mode = wrqu->mode; - queue_work(priv->workqueue, &priv->adapter_restart); + queue_work(priv->workqueue, &priv->adapter_restart); + up(&priv->sem); return err; } @@ -6417,10 +6802,10 @@ static int ipw_wx_get_mode(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - + down(&priv->sem); wrqu->mode = priv->ieee->iw_mode; IPW_DEBUG_WX("Get MODE -> %d\n", wrqu->mode); - + up(&priv->sem); return 0; } @@ -6466,7 +6851,7 @@ static int ipw_wx_get_range(struct net_device *dev, range->max_qual.qual = 100; /* TODO: Find real max RSSI and stick here */ range->max_qual.level = 0; - range->max_qual.noise = 0; + range->max_qual.noise = priv->ieee->worst_rssi + 0x100; range->max_qual.updated = 7; /* Updated all three */ range->avg_qual.qual = 70; @@ -6474,7 +6859,7 @@ static int ipw_wx_get_range(struct net_device *dev, range->avg_qual.level = 0; /* FIXME to real average level */ range->avg_qual.noise = 0; range->avg_qual.updated = 7; /* Updated all three */ - + down(&priv->sem); range->num_bitrates = min(priv->rates.num_rates, (u8) IW_MAX_BITRATES); for (i = 0; i < range->num_bitrates; i++) @@ -6507,7 +6892,7 @@ static int ipw_wx_get_range(struct net_device *dev, break; } range->num_frequency = val; - + up(&priv->sem); IPW_DEBUG_WX("GET Range\n"); return 0; } @@ -6527,25 +6912,23 @@ static int ipw_wx_set_wap(struct net_device *dev, if (wrqu->ap_addr.sa_family != ARPHRD_ETHER) return -EINVAL; - + down(&priv->sem); if (!memcmp(any, wrqu->ap_addr.sa_data, ETH_ALEN) || !memcmp(off, wrqu->ap_addr.sa_data, ETH_ALEN)) { /* we disable mandatory BSSID association */ IPW_DEBUG_WX("Setting AP BSSID to ANY\n"); priv->config &= ~CFG_STATIC_BSSID; - if (!(priv->status & (STATUS_SCANNING | STATUS_ASSOCIATED | - STATUS_ASSOCIATING))) { - IPW_DEBUG_ASSOC("Attempting to associate with new " - "parameters.\n"); - ipw_associate(priv); - } - + IPW_DEBUG_ASSOC("Attempting to associate with new " + "parameters.\n"); + ipw_associate(priv); + up(&priv->sem); return 0; } priv->config |= CFG_STATIC_BSSID; if (!memcmp(priv->bssid, wrqu->ap_addr.sa_data, ETH_ALEN)) { IPW_DEBUG_WX("BSSID set to current BSSID.\n"); + up(&priv->sem); return 0; } @@ -6554,14 +6937,12 @@ static int ipw_wx_set_wap(struct net_device *dev, memcpy(priv->bssid, wrqu->ap_addr.sa_data, ETH_ALEN); - /* If we are currently associated, or trying to associate - * then see if this is a new BSSID (causing us to disassociate) */ - if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { - IPW_DEBUG_ASSOC("Disassociating due to BSSID change.\n"); - ipw_disassociate(priv); - } else if (!(priv->status & (STATUS_SCANNING))) + /* Network configuration changed -- force [re]association */ + IPW_DEBUG_ASSOC("[re]association triggered due to BSSID change.\n"); + if (!ipw_disassociate(priv)) ipw_associate(priv); + up(&priv->sem); return 0; } @@ -6572,6 +6953,7 @@ static int ipw_wx_get_wap(struct net_device *dev, struct ipw_priv *priv = ieee80211_priv(dev); /* If we are associated, trying to associate, or have a statically * configured BSSID then return that; otherwise return ANY */ + down(&priv->sem); if (priv->config & CFG_STATIC_BSSID || priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { wrqu->ap_addr.sa_family = ARPHRD_ETHER; @@ -6581,6 +6963,7 @@ static int ipw_wx_get_wap(struct net_device *dev, IPW_DEBUG_WX("Getting WAP BSSID: " MAC_FMT "\n", MAC_ARG(wrqu->ap_addr.sa_data)); + up(&priv->sem); return 0; } @@ -6591,7 +6974,7 @@ static int ipw_wx_set_essid(struct net_device *dev, struct ipw_priv *priv = ieee80211_priv(dev); char *essid = ""; /* ANY */ int length = 0; - + down(&priv->sem); if (wrqu->essid.flags && wrqu->essid.length) { length = wrqu->essid.length - 1; essid = extra; @@ -6599,13 +6982,12 @@ static int ipw_wx_set_essid(struct net_device *dev, if (length == 0) { IPW_DEBUG_WX("Setting ESSID to ANY\n"); priv->config &= ~CFG_STATIC_ESSID; - if (!(priv->status & (STATUS_SCANNING | STATUS_ASSOCIATED | - STATUS_ASSOCIATING))) { + if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING))) { IPW_DEBUG_ASSOC("Attempting to associate with new " "parameters.\n"); ipw_associate(priv); } - + up(&priv->sem); return 0; } @@ -6615,6 +6997,7 @@ static int ipw_wx_set_essid(struct net_device *dev, if (priv->essid_len == length && !memcmp(priv->essid, extra, length)) { IPW_DEBUG_WX("ESSID set to current ESSID.\n"); + up(&priv->sem); return 0; } @@ -6624,14 +7007,12 @@ static int ipw_wx_set_essid(struct net_device *dev, priv->essid_len = length; memcpy(priv->essid, essid, priv->essid_len); - /* If we are currently associated, or trying to associate - * then see if this is a new ESSID (causing us to disassociate) */ - if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { - IPW_DEBUG_ASSOC("Disassociating due to ESSID change.\n"); - ipw_disassociate(priv); - } else if (!(priv->status & (STATUS_SCANNING))) + /* Network configuration changed -- force [re]association */ + IPW_DEBUG_ASSOC("[re]association triggered due to ESSID change.\n"); + if (!ipw_disassociate(priv)) ipw_associate(priv); + up(&priv->sem); return 0; } @@ -6643,6 +7024,7 @@ static int ipw_wx_get_essid(struct net_device *dev, /* If we are associated, trying to associate, or have a statically * configured ESSID then return that; otherwise return ANY */ + down(&priv->sem); if (priv->config & CFG_STATIC_ESSID || priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { IPW_DEBUG_WX("Getting essid: '%s'\n", @@ -6655,7 +7037,7 @@ static int ipw_wx_get_essid(struct net_device *dev, wrqu->essid.length = 0; wrqu->essid.flags = 0; /* active */ } - + up(&priv->sem); return 0; } @@ -6668,11 +7050,12 @@ static int ipw_wx_set_nick(struct net_device *dev, IPW_DEBUG_WX("Setting nick to '%s'\n", extra); if (wrqu->data.length > IW_ESSID_MAX_SIZE) return -E2BIG; - + down(&priv->sem); wrqu->data.length = min((size_t) wrqu->data.length, sizeof(priv->nick)); memset(priv->nick, 0, sizeof(priv->nick)); memcpy(priv->nick, extra, wrqu->data.length); IPW_DEBUG_TRACE("<<\n"); + up(&priv->sem); return 0; } @@ -6683,9 +7066,11 @@ static int ipw_wx_get_nick(struct net_device *dev, { struct ipw_priv *priv = ieee80211_priv(dev); IPW_DEBUG_WX("Getting nick\n"); + down(&priv->sem); wrqu->data.length = strlen(priv->nick) + 1; memcpy(extra, priv->nick, wrqu->data.length); wrqu->data.flags = 1; /* active */ + up(&priv->sem); return 0; } @@ -6778,25 +7163,26 @@ static int ipw_wx_set_rate(struct net_device *dev, apply: IPW_DEBUG_WX("Setting rate mask to 0x%08X [%s]\n", mask, fixed ? "fixed" : "sub-rates"); - + down(&priv->sem); if (mask == IEEE80211_DEFAULT_RATES_MASK) priv->config &= ~CFG_FIXED_RATE; else priv->config |= CFG_FIXED_RATE; - if (priv->rates_mask != mask) { - priv->rates_mask = mask; - /* If we are already associated or are currently trying to - * associate, disassociate and try again */ - if ((priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING))) { - IPW_DEBUG_ASSOC("Disassociating due to RATE change.\n"); - ipw_disassociate(priv); - } else if (!(priv->status & (STATUS_SCANNING))) { - /* We are not yet associated, so kick one off... */ - ipw_associate(priv); - } + if (priv->rates_mask == mask) { + IPW_DEBUG_WX("Mask set to current mask.\n"); + up(&priv->sem); + return 0; } + priv->rates_mask = mask; + + /* Network configuration changed -- force [re]association */ + IPW_DEBUG_ASSOC("[re]association triggered due to rates change.\n"); + if (!ipw_disassociate(priv)) + ipw_associate(priv); + + up(&priv->sem); return 0; } @@ -6805,8 +7191,9 @@ static int ipw_wx_get_rate(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); + down(&priv->sem); wrqu->bitrate.value = priv->last_rate; - + up(&priv->sem); IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value); return 0; } @@ -6816,18 +7203,20 @@ static int ipw_wx_set_rts(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - + down(&priv->sem); if (wrqu->rts.disabled) priv->rts_threshold = DEFAULT_RTS_THRESHOLD; else { if (wrqu->rts.value < MIN_RTS_THRESHOLD || - wrqu->rts.value > MAX_RTS_THRESHOLD) + wrqu->rts.value > MAX_RTS_THRESHOLD) { + up(&priv->sem); return -EINVAL; - + } priv->rts_threshold = wrqu->rts.value; } ipw_send_rts_threshold(priv, priv->rts_threshold); + up(&priv->sem); IPW_DEBUG_WX("SET RTS Threshold -> %d \n", priv->rts_threshold); return 0; } @@ -6837,10 +7226,11 @@ static int ipw_wx_get_rts(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); + down(&priv->sem); wrqu->rts.value = priv->rts_threshold; wrqu->rts.fixed = 0; /* no auto select */ wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); - + up(&priv->sem); IPW_DEBUG_WX("GET RTS Threshold -> %d \n", wrqu->rts.value); return 0; } @@ -6852,15 +7242,21 @@ static int ipw_wx_set_txpow(struct net_device *dev, struct ipw_priv *priv = ieee80211_priv(dev); struct ipw_tx_power tx_power; int i; - - if (ipw_radio_kill_sw(priv, wrqu->power.disabled)) + down(&priv->sem); + if (ipw_radio_kill_sw(priv, wrqu->power.disabled)) { + up(&priv->sem); return -EINPROGRESS; + } - if (wrqu->power.flags != IW_TXPOW_DBM) + if (wrqu->power.flags != IW_TXPOW_DBM) { + up(&priv->sem); return -EINVAL; + } - if ((wrqu->power.value > 20) || (wrqu->power.value < -12)) + if ((wrqu->power.value > 20) || (wrqu->power.value < -12)) { + up(&priv->sem); return -EINVAL; + } priv->tx_power = wrqu->power.value; @@ -6881,9 +7277,11 @@ static int ipw_wx_set_txpow(struct net_device *dev, if (ipw_send_tx_power(priv, &tx_power)) goto error; + up(&priv->sem); return 0; error: + up(&priv->sem); return -EIO; } @@ -6892,11 +7290,12 @@ static int ipw_wx_get_txpow(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - + down(&priv->sem); wrqu->power.value = priv->tx_power; wrqu->power.fixed = 1; wrqu->power.flags = IW_TXPOW_DBM; wrqu->power.disabled = (priv->status & STATUS_RF_KILL_MASK) ? 1 : 0; + up(&priv->sem); IPW_DEBUG_WX("GET TX Power -> %s %d \n", wrqu->power.disabled ? "ON" : "OFF", wrqu->power.value); @@ -6909,7 +7308,7 @@ static int ipw_wx_set_frag(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - + down(&priv->sem); if (wrqu->frag.disabled) priv->ieee->fts = DEFAULT_FTS; else { @@ -6921,6 +7320,7 @@ static int ipw_wx_set_frag(struct net_device *dev, } ipw_send_frag_threshold(priv, wrqu->frag.value); + up(&priv->sem); IPW_DEBUG_WX("SET Frag Threshold -> %d \n", wrqu->frag.value); return 0; } @@ -6930,10 +7330,11 @@ static int ipw_wx_get_frag(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); + down(&priv->sem); wrqu->frag.value = priv->ieee->fts; wrqu->frag.fixed = 0; /* no auto select */ wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FTS); - + up(&priv->sem); IPW_DEBUG_WX("GET Frag Threshold -> %d \n", wrqu->frag.value); return 0; @@ -6961,8 +7362,12 @@ static int ipw_wx_set_scan(struct net_device *dev, { struct ipw_priv *priv = ieee80211_priv(dev); IPW_DEBUG_WX("Start scan\n"); - if (ipw_request_scan(priv)) + down(&priv->sem); + if (ipw_request_scan(priv)) { + up(&priv->sem); return -EIO; + } + up(&priv->sem); return 0; } @@ -6996,16 +7401,17 @@ static int ipw_wx_set_power(struct net_device *dev, { struct ipw_priv *priv = ieee80211_priv(dev); int err; - + down(&priv->sem); if (wrqu->power.disabled) { priv->power_mode = IPW_POWER_LEVEL(priv->power_mode); err = ipw_send_power_mode(priv, IPW_POWER_MODE_CAM); if (err) { IPW_DEBUG_WX("failed setting power mode.\n"); + up(&priv->sem); return err; } IPW_DEBUG_WX("SET Power Management Mode -> off\n"); - + up(&priv->sem); return 0; } @@ -7017,6 +7423,7 @@ static int ipw_wx_set_power(struct net_device *dev, default: /* Otherwise we don't support it */ IPW_DEBUG_WX("SET PM Mode: %X not supported.\n", wrqu->power.flags); + up(&priv->sem); return -EOPNOTSUPP; } @@ -7029,11 +7436,12 @@ static int ipw_wx_set_power(struct net_device *dev, err = ipw_send_power_mode(priv, IPW_POWER_LEVEL(priv->power_mode)); if (err) { IPW_DEBUG_WX("failed setting power mode.\n"); + up(&priv->sem); return err; } IPW_DEBUG_WX("SET Power Management Mode -> 0x%02X\n", priv->power_mode); - + up(&priv->sem); return 0; } @@ -7042,12 +7450,13 @@ static int ipw_wx_get_power(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - + down(&priv->sem); if (!(priv->power_mode & IPW_POWER_ENABLED)) wrqu->power.disabled = 1; else wrqu->power.disabled = 0; + up(&priv->sem); IPW_DEBUG_WX("GET Power Management Mode -> %02X\n", priv->power_mode); return 0; @@ -7060,7 +7469,7 @@ static int ipw_wx_set_powermode(struct net_device *dev, struct ipw_priv *priv = ieee80211_priv(dev); int mode = *(int *)extra; int err; - + down(&priv->sem); if ((mode < 1) || (mode > IPW_POWER_LIMIT)) { mode = IPW_POWER_AC; priv->power_mode = mode; @@ -7073,10 +7482,11 @@ static int ipw_wx_set_powermode(struct net_device *dev, if (err) { IPW_DEBUG_WX("failed setting power mode.\n"); + up(&priv->sem); return err; } } - + up(&priv->sem); return 0; } @@ -7125,7 +7535,7 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev, IPW_WARNING("Attempt to set invalid wireless mode: %d\n", mode); return -EINVAL; } - + down(&priv->sem); if (priv->adapter == IPW_2915ABG) { priv->ieee->abg_true = 1; if (mode & IEEE_A) { @@ -7137,6 +7547,7 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev, if (mode & IEEE_A) { IPW_WARNING("Attempt to set 2200BG into " "802.11a mode\n"); + up(&priv->sem); return -EINVAL; } @@ -7160,16 +7571,12 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev, priv->ieee->modulation = modulation; init_supported_rates(priv, &priv->rates); - /* If we are currently associated, or trying to associate - * then see if this is a new configuration (causing us to - * disassociate) */ - if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { - /* The resulting association will trigger - * the new rates to be sent to the device */ - IPW_DEBUG_ASSOC("Disassociating due to mode change.\n"); - ipw_disassociate(priv); - } else + /* Network configuration changed -- force [re]association */ + IPW_DEBUG_ASSOC("[re]association triggered due to mode change.\n"); + if (!ipw_disassociate(priv)) { ipw_send_supported_rates(priv, &priv->rates); + ipw_associate(priv); + } /* Update the band LEDs */ ipw_led_band_on(priv); @@ -7177,6 +7584,7 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev, IPW_DEBUG_WX("PRIV SET MODE: %c%c%c\n", mode & IEEE_A ? 'a' : '.', mode & IEEE_B ? 'b' : '.', mode & IEEE_G ? 'g' : '.'); + up(&priv->sem); return 0; } @@ -7185,7 +7593,7 @@ static int ipw_wx_get_wireless_mode(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - + down(&priv->sem); switch (priv->ieee->mode) { case IEEE_A: strncpy(extra, "802.11a (1)", MAX_WX_STRING); @@ -7216,6 +7624,7 @@ static int ipw_wx_get_wireless_mode(struct net_device *dev, IPW_DEBUG_WX("PRIV GET MODE: %s\n", extra); wrqu->data.length = strlen(extra) + 1; + up(&priv->sem); return 0; } @@ -7226,18 +7635,17 @@ static int ipw_wx_set_preamble(struct net_device *dev, { struct ipw_priv *priv = ieee80211_priv(dev); int mode = *(int *)extra; - + down(&priv->sem); /* Switching from SHORT -> LONG requires a disassociation */ if (mode == 1) { if (!(priv->config & CFG_PREAMBLE_LONG)) { priv->config |= CFG_PREAMBLE_LONG; - if (priv->status & - (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { - IPW_DEBUG_ASSOC - ("Disassociating due to preamble " - "change.\n"); - ipw_disassociate(priv); - } + + /* Network configuration changed -- force [re]association */ + IPW_DEBUG_ASSOC + ("[re]association triggered due to preamble change.\n"); + if (!ipw_disassociate(priv)) + ipw_associate(priv); } goto done; } @@ -7246,10 +7654,11 @@ static int ipw_wx_set_preamble(struct net_device *dev, priv->config &= ~CFG_PREAMBLE_LONG; goto done; } - + up(&priv->sem); return -EINVAL; done: + up(&priv->sem); return 0; } @@ -7258,12 +7667,12 @@ static int ipw_wx_get_preamble(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - + down(&priv->sem); if (priv->config & CFG_PREAMBLE_LONG) snprintf(wrqu->name, IFNAMSIZ, "long (1)"); else snprintf(wrqu->name, IFNAMSIZ, "auto (0)"); - + up(&priv->sem); return 0; } @@ -7275,7 +7684,7 @@ static int ipw_wx_set_monitor(struct net_device *dev, struct ipw_priv *priv = ieee80211_priv(dev); int *parms = (int *)extra; int enable = (parms[0] > 0); - + down(&priv->sem); IPW_DEBUG_WX("SET MONITOR: %d %d\n", enable, parms[1]); if (enable) { if (priv->ieee->iw_mode != IW_MODE_MONITOR) { @@ -7285,11 +7694,14 @@ static int ipw_wx_set_monitor(struct net_device *dev, ipw_set_channel(priv, parms[1]); } else { - if (priv->ieee->iw_mode != IW_MODE_MONITOR) + if (priv->ieee->iw_mode != IW_MODE_MONITOR) { + up(&priv->sem); return 0; + } priv->net_dev->type = ARPHRD_ETHER; queue_work(priv->workqueue, &priv->adapter_restart); } + up(&priv->sem); return 0; } @@ -7473,7 +7885,7 @@ static inline void init_sys_config(struct ipw_sys_config *sys_config) sys_config->dot11g_auto_detection = 0; sys_config->enable_cts_to_self = 0; sys_config->bt_coexist_collision_thr = 0; - sys_config->pass_noise_stats_to_host = 0; //1 -- fix for 256 + sys_config->pass_noise_stats_to_host = 1; //1 -- fix for 256 } static int ipw_net_open(struct net_device *dev) @@ -7481,9 +7893,11 @@ static int ipw_net_open(struct net_device *dev) struct ipw_priv *priv = ieee80211_priv(dev); IPW_DEBUG_INFO("dev->open\n"); /* we should be verifying the device is ready to be opened */ + down(&priv->sem); if (!(priv->status & STATUS_RF_KILL_MASK) && (priv->status & STATUS_ASSOCIATED)) netif_start_queue(dev); + up(&priv->sem); return 0; } @@ -7511,6 +7925,7 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb) struct clx2_queue *q = &txq->q; u8 id, hdr_len, unicast; u16 remaining_bytes; + int fc; switch (priv->ieee->iw_mode) { case IW_MODE_ADHOC: @@ -7562,6 +7977,9 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb) if (priv->assoc_request.preamble_length == DCT_FLAG_SHORT_PREAMBLE) tfd->u.data.tx_flags |= DCT_FLAG_SHORT_PREAMBLE; + fc = le16_to_cpu(hdr->frame_ctl); + hdr->frame_ctl = cpu_to_le16(fc & ~IEEE80211_FCTL_MOREFRAGS); + memcpy(&tfd->u.data.tfd.tfd_24.mchdr, hdr, hdr_len); /* payload */ @@ -7644,7 +8062,6 @@ static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb, unsigned long flags; IPW_DEBUG_TX("dev->xmit(%d bytes)\n", txb->payload_size); - spin_lock_irqsave(&priv->lock, flags); if (!(priv->status & STATUS_ASSOCIATED)) { @@ -7655,13 +8072,15 @@ static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb, } ipw_tx_skb(priv, txb); + spin_unlock_irqrestore(&priv->lock, flags); ipw_led_activity_on(priv); - spin_unlock_irqrestore(&priv->lock, flags); +// up(&priv->sem); return 0; fail_unlock: spin_unlock_irqrestore(&priv->lock, flags); +// up(&priv->sem); return 1; } @@ -7685,11 +8104,13 @@ static int ipw_net_set_mac_address(struct net_device *dev, void *p) struct sockaddr *addr = p; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; + down(&priv->sem); priv->config |= CFG_CUSTOM_MAC; memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN); printk(KERN_INFO "%s: Setting MAC to " MAC_FMT "\n", priv->net_dev->name, MAC_ARG(priv->mac_addr)); queue_work(priv->workqueue, &priv->adapter_restart); + up(&priv->sem); return 0; } @@ -7733,8 +8154,9 @@ static int ipw_ethtool_get_eeprom(struct net_device *dev, if (eeprom->offset + eeprom->len > CX2_EEPROM_IMAGE_SIZE) return -EINVAL; - + down(&p->sem); memcpy(bytes, &((u8 *) p->eeprom)[eeprom->offset], eeprom->len); + up(&p->sem); return 0; } @@ -7746,12 +8168,12 @@ static int ipw_ethtool_set_eeprom(struct net_device *dev, if (eeprom->offset + eeprom->len > CX2_EEPROM_IMAGE_SIZE) return -EINVAL; - + down(&p->sem); memcpy(&((u8 *) p->eeprom)[eeprom->offset], bytes, eeprom->len); for (i = IPW_EEPROM_DATA; i < IPW_EEPROM_DATA + CX2_EEPROM_IMAGE_SIZE; i++) ipw_write8(p, i, p->eeprom[i]); - + up(&p->sem); return 0; } @@ -7775,6 +8197,8 @@ static irqreturn_t ipw_isr(int irq, void *data, struct pt_regs *regs) if (!(priv->status & STATUS_INT_ENABLED)) { /* Shared IRQ */ +// ipw_write32(priv, CX2_INTA_RW, CX2_INTA_MASK_ALL); +// return IRQ_HANDLED; goto none; } @@ -7843,6 +8267,14 @@ static void ipw_rf_kill(void *adapter) spin_unlock_irqrestore(&priv->lock, flags); } +static void ipw_bg_rf_kill(void *data) +{ + struct ipw_priv *priv = data; + down(&priv->sem); + ipw_rf_kill(data); + up(&priv->sem); +} + void ipw_link_up(struct ipw_priv *priv) { netif_carrier_on(priv->net_dev); @@ -7854,6 +8286,7 @@ void ipw_link_up(struct ipw_priv *priv) netif_start_queue(priv->net_dev); } + cancel_delayed_work(&priv->request_scan); ipw_reset_stats(priv); /* Ensure the rate is updated immediately */ priv->last_rate = ipw_get_current_rate(priv); @@ -7865,6 +8298,14 @@ void ipw_link_up(struct ipw_priv *priv) queue_delayed_work(priv->workqueue, &priv->request_scan, HZ); } +static void ipw_bg_link_up(void *data) +{ + struct ipw_priv *priv = data; + down(&priv->sem); + ipw_link_up(data); + up(&priv->sem); +} + void ipw_link_down(struct ipw_priv *priv) { ipw_led_link_down(priv); @@ -7883,6 +8324,14 @@ void ipw_link_down(struct ipw_priv *priv) queue_work(priv->workqueue, &priv->request_scan); } +static void ipw_bg_link_down(void *data) +{ + struct ipw_priv *priv = data; + down(&priv->sem); + ipw_link_down(data); + up(&priv->sem); +} + static int ipw_setup_deferred_work(struct ipw_priv *priv) { int ret = 0; @@ -7890,28 +8339,31 @@ static int ipw_setup_deferred_work(struct ipw_priv *priv) priv->workqueue = create_workqueue(DRV_NAME); init_waitqueue_head(&priv->wait_command_queue); - INIT_WORK(&priv->adhoc_check, ipw_adhoc_check, priv); - INIT_WORK(&priv->associate, ipw_associate, priv); - INIT_WORK(&priv->disassociate, ipw_disassociate, priv); - INIT_WORK(&priv->rx_replenish, ipw_rx_queue_replenish, priv); - INIT_WORK(&priv->adapter_restart, ipw_adapter_restart, priv); - INIT_WORK(&priv->rf_kill, ipw_rf_kill, priv); - INIT_WORK(&priv->up, (void (*)(void *))ipw_up, priv); - INIT_WORK(&priv->down, (void (*)(void *))ipw_down, priv); + INIT_WORK(&priv->adhoc_check, ipw_bg_adhoc_check, priv); + INIT_WORK(&priv->associate, ipw_bg_associate, priv); + INIT_WORK(&priv->disassociate, ipw_bg_disassociate, priv); + INIT_WORK(&priv->rx_replenish, ipw_bg_rx_queue_replenish, priv); + INIT_WORK(&priv->adapter_restart, ipw_bg_adapter_restart, priv); + INIT_WORK(&priv->rf_kill, ipw_bg_rf_kill, priv); + INIT_WORK(&priv->up, (void (*)(void *))ipw_bg_up, priv); + INIT_WORK(&priv->down, (void (*)(void *))ipw_bg_down, priv); INIT_WORK(&priv->request_scan, - (void (*)(void *))ipw_request_scan, priv); + (void (*)(void *))ipw_bg_request_scan, priv); INIT_WORK(&priv->gather_stats, - (void (*)(void *))ipw_gather_stats, priv); - INIT_WORK(&priv->abort_scan, (void (*)(void *))ipw_abort_scan, priv); - INIT_WORK(&priv->roam, ipw_roam, priv); - INIT_WORK(&priv->scan_check, ipw_scan_check, priv); - INIT_WORK(&priv->link_up, (void (*)(void *))ipw_link_up, priv); - INIT_WORK(&priv->link_down, (void (*)(void *))ipw_link_down, priv); - INIT_WORK(&priv->led_link_on, (void (*)(void *))ipw_led_link_on, priv); - INIT_WORK(&priv->led_link_off, (void (*)(void *))ipw_led_link_off, + (void (*)(void *))ipw_bg_gather_stats, priv); + INIT_WORK(&priv->abort_scan, (void (*)(void *))ipw_bg_abort_scan, priv); + INIT_WORK(&priv->roam, ipw_bg_roam, priv); + INIT_WORK(&priv->scan_check, ipw_bg_scan_check, priv); + INIT_WORK(&priv->link_up, (void (*)(void *))ipw_bg_link_up, priv); + INIT_WORK(&priv->link_down, (void (*)(void *))ipw_bg_link_down, priv); + INIT_WORK(&priv->led_link_on, (void (*)(void *))ipw_bg_led_link_on, + priv); + INIT_WORK(&priv->led_link_off, (void (*)(void *))ipw_bg_led_link_off, priv); - INIT_WORK(&priv->led_act_off, (void (*)(void *))ipw_led_activity_off, + INIT_WORK(&priv->led_act_off, (void (*)(void *))ipw_bg_led_activity_off, priv); + INIT_WORK(&priv->merge_networks, + (void (*)(void *))ipw_merge_adhoc_network, priv); tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) ipw_irq_tasklet, (unsigned long)priv); @@ -7924,7 +8376,7 @@ static void shim__set_security(struct net_device *dev, { struct ipw_priv *priv = ieee80211_priv(dev); int i; - + down(&priv->sem); for (i = 0; i < 4; i++) { if (sec->flags & (1 << i)) { priv->sec.key_sizes[i] = sec->key_sizes[i]; @@ -7989,6 +8441,7 @@ static void shim__set_security(struct net_device *dev, ipw_disassociate(priv); } #endif + up(&priv->sem); } static int init_supported_rates(struct ipw_priv *priv, @@ -8054,6 +8507,11 @@ static int ipw_config(struct ipw_priv *priv) /* set basic system config settings */ init_sys_config(&priv->sys_config); + if (priv->ieee->iw_mode == IW_MODE_ADHOC) + priv->sys_config.answer_broadcast_ssid_probe = 1; + else + priv->sys_config.answer_broadcast_ssid_probe = 0; + if (ipw_send_system_config(priv, &priv->sys_config)) goto error; @@ -8075,8 +8533,10 @@ static int ipw_config(struct ipw_priv *priv) goto error; /* If configured to try and auto-associate, kick off a scan */ - if ((priv->config & CFG_ASSOCIATE) && ipw_request_scan(priv)) + if ((priv->config & CFG_ASSOCIATE) && ipw_request_scan(priv)) { + IPW_WARNING("error sending scan request\n"); goto error; + } return 0; @@ -8106,8 +8566,9 @@ static int ipw_up(struct ipw_priv *priv) eeprom_parse_mac(priv, priv->mac_addr); memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN); - if (priv->status & STATUS_RF_KILL_MASK) + if (priv->status & STATUS_RF_KILL_MASK) { return 0; + } rc = ipw_config(priv); if (!rc) { @@ -8115,12 +8576,11 @@ static int ipw_up(struct ipw_priv *priv) ipw_led_init(priv); ipw_led_radio_on(priv); priv->notif_missed_beacons = 0; + priv->status |= STATUS_INIT; return 0; - } else { - IPW_DEBUG_INFO("Device configuration failed: 0x%08X\n", - rc); } + IPW_DEBUG_INFO("Device configuration failed: 0x%08X\n", rc); IPW_DEBUG_INFO("Failed to config device on retry %d of %d\n", i, MAX_HW_RESTARTS); @@ -8132,13 +8592,22 @@ static int ipw_up(struct ipw_priv *priv) /* tried to restart and config the device for as long as our * patience could withstand */ IPW_ERROR("Unable to initialize device after %d attempts.\n", i); + return -EIO; } +static void ipw_bg_up(void *data) +{ + struct ipw_priv *priv = data; + down(&priv->sem); + ipw_up(data); + up(&priv->sem); +} + static void ipw_down(struct ipw_priv *priv) { - /* Attempt to disable the card */ #if 0 + /* Attempt to disable the card */ ipw_send_card_disable(priv, 0); #endif @@ -8147,7 +8616,6 @@ static void ipw_down(struct ipw_priv *priv) /* Clear all bits but the RF Kill */ priv->status &= STATUS_RF_KILL_MASK; - netif_carrier_off(priv->net_dev); netif_stop_queue(priv->net_dev); @@ -8156,6 +8624,14 @@ static void ipw_down(struct ipw_priv *priv) ipw_led_radio_off(priv); } +static void ipw_bg_down(void *data) +{ + struct ipw_priv *priv = data; + down(&priv->sem); + ipw_down(data); + up(&priv->sem); +} + static int ipw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct iwreq *wrq = (struct iwreq *)rq; @@ -8176,21 +8652,26 @@ static int ipw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) static int ipw_net_init(struct net_device *dev) { struct ipw_priv *priv = ieee80211_priv(dev); - + down(&priv->sem); if (priv->status & STATUS_RF_KILL_SW) { IPW_WARNING("Radio disabled by module parameter.\n"); + up(&priv->sem); return 0; } else if (rf_kill_active(priv)) { IPW_WARNING("Radio Frequency Kill Switch is On:\n" "Kill switch must be turned off for " "wireless networking to work.\n"); queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ); + up(&priv->sem); return 0; } - if (ipw_up(priv)) + if (ipw_up(priv)) { + up(&priv->sem); return -EIO; + } + up(&priv->sem); return 0; } @@ -8275,6 +8756,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) #endif spin_lock_init(&priv->lock); + init_MUTEX(&priv->sem); if (pci_enable_device(pdev)) { err = -ENODEV; goto out_free_ieee80211; @@ -8416,9 +8898,14 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ipw_wx_data.spy_data = &priv->ieee->spy_data; ipw_wx_data.ieee80211 = priv->ieee; + down(&priv->sem); + priv->ieee->hard_start_xmit = ipw_net_hard_start_xmit; priv->ieee->set_security = shim__set_security; + priv->ieee->perfect_rssi = -20; + priv->ieee->worst_rssi = -85; + net_dev->open = ipw_net_open; net_dev->stop = ipw_net_stop; net_dev->init = ipw_net_init; @@ -8438,15 +8925,16 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = sysfs_create_group(&pdev->dev.kobj, &ipw_attribute_group); if (err) { IPW_ERROR("failed to create sysfs device attributes\n"); + up(&priv->sem); goto out_release_irq; } + up(&priv->sem); err = register_netdev(net_dev); if (err) { IPW_ERROR("failed to register network device\n"); goto out_remove_sysfs; } - return 0; out_remove_sysfs: @@ -8623,8 +9111,7 @@ module_param(auto_create, int, 0444); MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)"); module_param(led, int, 0444); -MODULE_PARM_DESC(auto_create, - "enable led control on some systems (default 0 off)\n"); +MODULE_PARM_DESC(led, "enable led control on some systems (default 0 off)\n"); module_param(debug, int, 0444); MODULE_PARM_DESC(debug, "debug output mask"); diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index 1b339cb7a52..243b8ea1414 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -936,8 +936,8 @@ struct ipw_priv { struct ieee80211_device *ieee; struct ieee80211_security sec; - /* spinlock */ spinlock_t lock; + struct semaphore sem; /* basic pci-network driver stuff */ struct pci_dev *pci_dev; @@ -1068,6 +1068,7 @@ struct ipw_priv { struct work_struct led_link_on; struct work_struct led_link_off; struct work_struct led_act_off; + struct work_struct merge_networks; #define IPW_2200BG 1 #define IPW_2915ABG 2 @@ -1160,6 +1161,7 @@ do { if (ipw_debug_level & (level)) \ #define IPW_DL_TRACE (1<<28) #define IPW_DL_STATS (1<<29) +#define IPW_DL_MERGE (1<<30) #define IPW_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a) #define IPW_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a) @@ -1187,6 +1189,7 @@ do { if (ipw_debug_level & (level)) \ #define IPW_DEBUG_STATE(f, a...) IPW_DEBUG(IPW_DL_STATE | IPW_DL_ASSOC | IPW_DL_INFO, f, ## a) #define IPW_DEBUG_ASSOC(f, a...) IPW_DEBUG(IPW_DL_ASSOC | IPW_DL_INFO, f, ## a) #define IPW_DEBUG_STATS(f, a...) IPW_DEBUG(IPW_DL_STATS, f, ## a) +#define IPW_DEBUG_MERGE(f, a...) IPW_DEBUG(IPW_DL_MERGE, f, ## a) #include -- cgit v1.2.3 From b095c3819805f87d73d41641a53e4c070360d783 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Wed, 24 Aug 2005 22:04:42 -0500 Subject: Catch ipw2200 up to equivelancy with v1.0.4 * Fixed #627 problem with open APs not working with wpa_supplicant * Fixed #632 problem with 'txpower auto' setting power incorrectly (thanks to Kai Groner) * Fixed #634 problem with 'iwconfig eth1 frag 0' hanging the shell * Fixed problem with adapter not fully powering off during suspend to RAM or when module unloaded. * Fixed #645 problem with turning fixed rates off not taking effect until you reload the driver * Fixed problem with firmware restart if wpa_supplicant was used to set a key that wasn't exactly 5 or 13 bytes in length. * Fixed #623 Added iwpriv sw_reset extension to reset sw parameters * Added managment frame export to user space with frame statistics * Fixed #652 Modified the driver to load the EEPROM data even if RF KILL is active during driver load * Global s:CX2_:IPW_:g to make code more consistent * Fixed #572 problem with setting txpower to auto * Fixed #656 problem with kernel oops if mode auto; modprobe -r ipw2200 * Added QoS (CONFIG_IPW_QOS) support. This is being actively developed but is the first step in getting WMM support into the driver and the kernel. * Fixed some race conditions with channel changes, association, and scan abort that could periodically cause a firmware restart. * Added some extensions to export scan and network statistics to user space (exposed through speed_scan and net_stats sysfs entries) * Fixed a few bugs in how monitor mode was supported (scan lists weren't quite right) * Updated the firmware requirement from 2.2 to 2.3 which supports monitor mode. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 2604 +++++++++++++++++++++++++++++----------- drivers/net/wireless/ipw2200.h | 457 ++++--- 2 files changed, 2177 insertions(+), 884 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 0bf1931ac5f..0a583afbcdd 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -32,11 +32,13 @@ #include "ipw2200.h" -#define IPW2200_VERSION "1.0.3" +#define IPW2200_VERSION "1.0.4" #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation" #define DRV_VERSION IPW2200_VERSION +#define ETH_P_80211_STATS (ETH_P_80211_RAW + 1) + MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_VERSION(DRV_VERSION); MODULE_AUTHOR(DRV_COPYRIGHT); @@ -51,10 +53,78 @@ static int associate = 1; static int auto_create = 1; static int led = 0; static int disable = 0; +static int hwcrypto = 1; static const char ipw_modes[] = { 'a', 'b', 'g', '?' }; +#ifdef CONFIG_IPW_QOS +static int qos_enable = 0; +static int qos_burst_enable = 0; +static int qos_no_ack_mask = 0; +static int burst_duration_CCK = 0; +static int burst_duration_OFDM = 0; + +static struct ieee80211_qos_parameters def_qos_parameters_OFDM = { + {QOS_TX0_CW_MIN_OFDM, QOS_TX1_CW_MIN_OFDM, QOS_TX2_CW_MIN_OFDM, + QOS_TX3_CW_MIN_OFDM}, + {QOS_TX0_CW_MAX_OFDM, QOS_TX1_CW_MAX_OFDM, QOS_TX2_CW_MAX_OFDM, + QOS_TX3_CW_MAX_OFDM}, + {QOS_TX0_AIFS, QOS_TX1_AIFS, QOS_TX2_AIFS, QOS_TX3_AIFS}, + {QOS_TX0_ACM, QOS_TX1_ACM, QOS_TX2_ACM, QOS_TX3_ACM}, + {QOS_TX0_TXOP_LIMIT_OFDM, QOS_TX1_TXOP_LIMIT_OFDM, + QOS_TX2_TXOP_LIMIT_OFDM, QOS_TX3_TXOP_LIMIT_OFDM} +}; + +static struct ieee80211_qos_parameters def_qos_parameters_CCK = { + {QOS_TX0_CW_MIN_CCK, QOS_TX1_CW_MIN_CCK, QOS_TX2_CW_MIN_CCK, + QOS_TX3_CW_MIN_CCK}, + {QOS_TX0_CW_MAX_CCK, QOS_TX1_CW_MAX_CCK, QOS_TX2_CW_MAX_CCK, + QOS_TX3_CW_MAX_CCK}, + {QOS_TX0_AIFS, QOS_TX1_AIFS, QOS_TX2_AIFS, QOS_TX3_AIFS}, + {QOS_TX0_ACM, QOS_TX1_ACM, QOS_TX2_ACM, QOS_TX3_ACM}, + {QOS_TX0_TXOP_LIMIT_CCK, QOS_TX1_TXOP_LIMIT_CCK, QOS_TX2_TXOP_LIMIT_CCK, + QOS_TX3_TXOP_LIMIT_CCK} +}; + +static struct ieee80211_qos_parameters def_parameters_OFDM = { + {DEF_TX0_CW_MIN_OFDM, DEF_TX1_CW_MIN_OFDM, DEF_TX2_CW_MIN_OFDM, + DEF_TX3_CW_MIN_OFDM}, + {DEF_TX0_CW_MAX_OFDM, DEF_TX1_CW_MAX_OFDM, DEF_TX2_CW_MAX_OFDM, + DEF_TX3_CW_MAX_OFDM}, + {DEF_TX0_AIFS, DEF_TX1_AIFS, DEF_TX2_AIFS, DEF_TX3_AIFS}, + {DEF_TX0_ACM, DEF_TX1_ACM, DEF_TX2_ACM, DEF_TX3_ACM}, + {DEF_TX0_TXOP_LIMIT_OFDM, DEF_TX1_TXOP_LIMIT_OFDM, + DEF_TX2_TXOP_LIMIT_OFDM, DEF_TX3_TXOP_LIMIT_OFDM} +}; + +static struct ieee80211_qos_parameters def_parameters_CCK = { + {DEF_TX0_CW_MIN_CCK, DEF_TX1_CW_MIN_CCK, DEF_TX2_CW_MIN_CCK, + DEF_TX3_CW_MIN_CCK}, + {DEF_TX0_CW_MAX_CCK, DEF_TX1_CW_MAX_CCK, DEF_TX2_CW_MAX_CCK, + DEF_TX3_CW_MAX_CCK}, + {DEF_TX0_AIFS, DEF_TX1_AIFS, DEF_TX2_AIFS, DEF_TX3_AIFS}, + {DEF_TX0_ACM, DEF_TX1_ACM, DEF_TX2_ACM, DEF_TX3_ACM}, + {DEF_TX0_TXOP_LIMIT_CCK, DEF_TX1_TXOP_LIMIT_CCK, DEF_TX2_TXOP_LIMIT_CCK, + DEF_TX3_TXOP_LIMIT_CCK} +}; + +static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 }; + +static int from_priority_to_tx_queue[] = { + IPW_TX_QUEUE_1, IPW_TX_QUEUE_2, IPW_TX_QUEUE_2, IPW_TX_QUEUE_1, + IPW_TX_QUEUE_3, IPW_TX_QUEUE_3, IPW_TX_QUEUE_4, IPW_TX_QUEUE_4 +}; + +static u32 ipw_qos_get_burst_duration(struct ipw_priv *priv); + +static int ipw_send_qos_params_command(struct ipw_priv *priv, struct ieee80211_qos_parameters + *qos_param); +static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos_information_element + *qos_param); +#endif /* CONFIG_IPW_QOS */ + +static void ipw_remove_current_network(struct ipw_priv *priv); static void ipw_rx(struct ipw_priv *priv); static int ipw_queue_tx_reclaim(struct ipw_priv *priv, struct clx2_tx_queue *txq, int qindex); @@ -75,33 +145,8 @@ static void ipw_bg_down(void *); static int ipw_config(struct ipw_priv *); static int init_supported_rates(struct ipw_priv *priv, struct ipw_supported_rates *prates); - -static u8 band_b_active_channel[MAX_B_CHANNELS] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0 -}; -static u8 band_a_active_channel[MAX_A_CHANNELS] = { - 36, 40, 44, 48, 149, 153, 157, 161, 165, 52, 56, 60, 64, 0 -}; - -static int is_valid_channel(int mode_mask, int channel) -{ - int i; - - if (!channel) - return 0; - - if (mode_mask & IEEE_A) - for (i = 0; i < MAX_A_CHANNELS; i++) - if (band_a_active_channel[i] == channel) - return IEEE_A; - - if (mode_mask & (IEEE_B | IEEE_G)) - for (i = 0; i < MAX_B_CHANNELS; i++) - if (band_b_active_channel[i] == channel) - return mode_mask & (IEEE_B | IEEE_G); - - return 0; -} +static void ipw_set_hwcrypto_keys(struct ipw_priv *); +static void ipw_send_wep_keys(struct ipw_priv *, int); static char *snprint_line(char *buf, size_t count, const u8 * data, u32 len, u32 ofs) @@ -241,24 +286,24 @@ static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * data, static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value) { IPW_DEBUG_IO(" %p : reg = 0x%8X : value = 0x%8X\n", priv, reg, value); - _ipw_write32(priv, CX2_INDIRECT_ADDR, reg); - _ipw_write32(priv, CX2_INDIRECT_DATA, value); + _ipw_write32(priv, IPW_INDIRECT_ADDR, reg); + _ipw_write32(priv, IPW_INDIRECT_DATA, value); } static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value) { IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value); - _ipw_write32(priv, CX2_INDIRECT_ADDR, reg & CX2_INDIRECT_ADDR_MASK); - _ipw_write8(priv, CX2_INDIRECT_DATA, value); + _ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK); + _ipw_write8(priv, IPW_INDIRECT_DATA, value); IPW_DEBUG_IO(" reg = 0x%8lX : value = 0x%8X\n", - (unsigned long)(priv->hw_base + CX2_INDIRECT_DATA), value); + (unsigned long)(priv->hw_base + IPW_INDIRECT_DATA), value); } static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value) { IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value); - _ipw_write32(priv, CX2_INDIRECT_ADDR, reg & CX2_INDIRECT_ADDR_MASK); - _ipw_write16(priv, CX2_INDIRECT_DATA, value); + _ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK); + _ipw_write16(priv, IPW_INDIRECT_DATA, value); } /* indirect read s */ @@ -266,9 +311,9 @@ static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value) static u8 _ipw_read_reg8(struct ipw_priv *priv, u32 reg) { u32 word; - _ipw_write32(priv, CX2_INDIRECT_ADDR, reg & CX2_INDIRECT_ADDR_MASK); + _ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK); IPW_DEBUG_IO(" reg = 0x%8X : \n", reg); - word = _ipw_read32(priv, CX2_INDIRECT_DATA); + word = _ipw_read32(priv, IPW_INDIRECT_DATA); return (word >> ((reg & 0x3) * 8)) & 0xff; } @@ -278,8 +323,8 @@ static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg) IPW_DEBUG_IO("%p : reg = 0x%08x\n", priv, reg); - _ipw_write32(priv, CX2_INDIRECT_ADDR, reg); - value = _ipw_read32(priv, CX2_INDIRECT_DATA); + _ipw_write32(priv, IPW_INDIRECT_ADDR, reg); + value = _ipw_read32(priv, IPW_INDIRECT_DATA); IPW_DEBUG_IO(" reg = 0x%4X : value = 0x%4x \n", reg, value); return value; } @@ -288,7 +333,7 @@ static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg) static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, int num) { - u32 aligned_addr = addr & CX2_INDIRECT_ADDR_MASK; + u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK; u32 dif_len = addr - aligned_addr; u32 i; @@ -300,29 +345,29 @@ static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, /* Read the first nibble byte by byte */ if (unlikely(dif_len)) { - _ipw_write32(priv, CX2_INDIRECT_ADDR, aligned_addr); + _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); /* Start reading at aligned_addr + dif_len */ for (i = dif_len; ((i < 4) && (num > 0)); i++, num--) - *buf++ = _ipw_read8(priv, CX2_INDIRECT_DATA + i); + *buf++ = _ipw_read8(priv, IPW_INDIRECT_DATA + i); aligned_addr += 4; } - _ipw_write32(priv, CX2_AUTOINC_ADDR, aligned_addr); + _ipw_write32(priv, IPW_AUTOINC_ADDR, aligned_addr); for (; num >= 4; buf += 4, aligned_addr += 4, num -= 4) - *(u32 *) buf = _ipw_read32(priv, CX2_AUTOINC_DATA); + *(u32 *) buf = _ipw_read32(priv, IPW_AUTOINC_DATA); /* Copy the last nibble */ if (unlikely(num)) { - _ipw_write32(priv, CX2_INDIRECT_ADDR, aligned_addr); + _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); for (i = 0; num > 0; i++, num--) - *buf++ = ipw_read8(priv, CX2_INDIRECT_DATA + i); + *buf++ = ipw_read8(priv, IPW_INDIRECT_DATA + i); } } static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, int num) { - u32 aligned_addr = addr & CX2_INDIRECT_ADDR_MASK; + u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK; u32 dif_len = addr - aligned_addr; u32 i; @@ -334,22 +379,22 @@ static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, /* Write the first nibble byte by byte */ if (unlikely(dif_len)) { - _ipw_write32(priv, CX2_INDIRECT_ADDR, aligned_addr); + _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); /* Start reading at aligned_addr + dif_len */ for (i = dif_len; ((i < 4) && (num > 0)); i++, num--, buf++) - _ipw_write8(priv, CX2_INDIRECT_DATA + i, *buf); + _ipw_write8(priv, IPW_INDIRECT_DATA + i, *buf); aligned_addr += 4; } - _ipw_write32(priv, CX2_AUTOINC_ADDR, aligned_addr); + _ipw_write32(priv, IPW_AUTOINC_ADDR, aligned_addr); for (; num >= 4; buf += 4, aligned_addr += 4, num -= 4) - _ipw_write32(priv, CX2_AUTOINC_DATA, *(u32 *) buf); + _ipw_write32(priv, IPW_AUTOINC_DATA, *(u32 *) buf); /* Copy the last nibble */ if (unlikely(num)) { - _ipw_write32(priv, CX2_INDIRECT_ADDR, aligned_addr); + _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); for (i = 0; num > 0; i++, num--, buf++) - _ipw_write8(priv, CX2_INDIRECT_DATA + i, *buf); + _ipw_write8(priv, IPW_INDIRECT_DATA + i, *buf); } } @@ -374,7 +419,7 @@ static inline void ipw_enable_interrupts(struct ipw_priv *priv) if (priv->status & STATUS_INT_ENABLED) return; priv->status |= STATUS_INT_ENABLED; - ipw_write32(priv, CX2_INTA_MASK_R, CX2_INTA_MASK_ALL); + ipw_write32(priv, IPW_INTA_MASK_R, IPW_INTA_MASK_ALL); } static inline void ipw_disable_interrupts(struct ipw_priv *priv) @@ -382,7 +427,7 @@ static inline void ipw_disable_interrupts(struct ipw_priv *priv) if (!(priv->status & STATUS_INT_ENABLED)) return; priv->status &= ~STATUS_INT_ENABLED; - ipw_write32(priv, CX2_INTA_MASK_R, ~CX2_INTA_MASK_ALL); + ipw_write32(priv, IPW_INTA_MASK_R, ~IPW_INTA_MASK_ALL); } static char *ipw_error_desc(u32 val) @@ -397,29 +442,29 @@ static char *ipw_error_desc(u32 val) case IPW_FW_ERROR_MEMORY_OVERFLOW: return "MEMORY_OVERFLOW"; case IPW_FW_ERROR_BAD_PARAM: - return "ERROR_BAD_PARAM"; + return "BAD_PARAM"; case IPW_FW_ERROR_BAD_CHECKSUM: - return "ERROR_BAD_CHECKSUM"; + return "BAD_CHECKSUM"; case IPW_FW_ERROR_NMI_INTERRUPT: - return "ERROR_NMI_INTERRUPT"; + return "NMI_INTERRUPT"; case IPW_FW_ERROR_BAD_DATABASE: - return "ERROR_BAD_DATABASE"; + return "BAD_DATABASE"; case IPW_FW_ERROR_ALLOC_FAIL: - return "ERROR_ALLOC_FAIL"; + return "ALLOC_FAIL"; case IPW_FW_ERROR_DMA_UNDERRUN: - return "ERROR_DMA_UNDERRUN"; + return "DMA_UNDERRUN"; case IPW_FW_ERROR_DMA_STATUS: - return "ERROR_DMA_STATUS"; - case IPW_FW_ERROR_DINOSTATUS_ERROR: - return "ERROR_DINOSTATUS_ERROR"; - case IPW_FW_ERROR_EEPROMSTATUS_ERROR: - return "ERROR_EEPROMSTATUS_ERROR"; + return "DMA_STATUS"; + case IPW_FW_ERROR_DINO_ERROR: + return "DINO_ERROR"; + case IPW_FW_ERROR_EEPROM_ERROR: + return "EEPROM_ERROR"; case IPW_FW_ERROR_SYSASSERT: - return "ERROR_SYSASSERT"; + return "SYSASSERT"; case IPW_FW_ERROR_FATAL_ERROR: - return "ERROR_FATALSTATUS_ERROR"; + return "FATAL_ERROR"; default: - return "UNKNOWNSTATUS_ERROR"; + return "UNKNOWN_ERROR"; } } @@ -646,13 +691,13 @@ static void ipw_init_ordinals(struct ipw_priv *priv) u32 ipw_register_toggle(u32 reg) { - reg &= ~CX2_START_STANDBY; - if (reg & CX2_GATE_ODMA) - reg &= ~CX2_GATE_ODMA; - if (reg & CX2_GATE_IDMA) - reg &= ~CX2_GATE_IDMA; - if (reg & CX2_GATE_ADMA) - reg &= ~CX2_GATE_ADMA; + reg &= ~IPW_START_STANDBY; + if (reg & IPW_GATE_ODMA) + reg &= ~IPW_GATE_ODMA; + if (reg & IPW_GATE_IDMA) + reg &= ~IPW_GATE_IDMA; + if (reg & IPW_GATE_ADMA) + reg &= ~IPW_GATE_ADMA; return reg; } @@ -684,13 +729,13 @@ void ipw_led_link_on(struct ipw_priv *priv) if (!(priv->status & STATUS_RF_KILL_MASK) && !(priv->status & STATUS_LED_LINK_ON)) { IPW_DEBUG_LED("Link LED On\n"); - led = ipw_read_reg32(priv, CX2_EVENT_REG); + led = ipw_read_reg32(priv, IPW_EVENT_REG); led |= priv->led_association_on; led = ipw_register_toggle(led); IPW_DEBUG_LED("Reg: 0x%08X\n", led); - ipw_write_reg32(priv, CX2_EVENT_REG, led); + ipw_write_reg32(priv, IPW_EVENT_REG, led); priv->status |= STATUS_LED_LINK_ON; @@ -725,12 +770,12 @@ void ipw_led_link_off(struct ipw_priv *priv) spin_lock_irqsave(&priv->lock, flags); if (priv->status & STATUS_LED_LINK_ON) { - led = ipw_read_reg32(priv, CX2_EVENT_REG); + led = ipw_read_reg32(priv, IPW_EVENT_REG); led &= priv->led_association_off; led = ipw_register_toggle(led); IPW_DEBUG_LED("Reg: 0x%08X\n", led); - ipw_write_reg32(priv, CX2_EVENT_REG, led); + ipw_write_reg32(priv, IPW_EVENT_REG, led); IPW_DEBUG_LED("Link LED Off\n"); @@ -756,29 +801,24 @@ static void ipw_bg_led_link_off(void *data) up(&priv->sem); } -void ipw_led_activity_on(struct ipw_priv *priv) +static inline void __ipw_led_activity_on(struct ipw_priv *priv) { - unsigned long flags; u32 led; if (priv->config & CFG_NO_LED) return; - spin_lock_irqsave(&priv->lock, flags); - - if (priv->status & STATUS_RF_KILL_MASK) { - spin_unlock_irqrestore(&priv->lock, flags); + if (priv->status & STATUS_RF_KILL_MASK) return; - } if (!(priv->status & STATUS_LED_ACT_ON)) { - led = ipw_read_reg32(priv, CX2_EVENT_REG); + led = ipw_read_reg32(priv, IPW_EVENT_REG); led |= priv->led_activity_on; led = ipw_register_toggle(led); IPW_DEBUG_LED("Reg: 0x%08X\n", led); - ipw_write_reg32(priv, CX2_EVENT_REG, led); + ipw_write_reg32(priv, IPW_EVENT_REG, led); IPW_DEBUG_LED("Activity LED On\n"); @@ -793,7 +833,13 @@ void ipw_led_activity_on(struct ipw_priv *priv) queue_delayed_work(priv->workqueue, &priv->led_act_off, LD_TIME_ACT_ON); } +} +void ipw_led_activity_on(struct ipw_priv *priv) +{ + unsigned long flags; + spin_lock_irqsave(&priv->lock, flags); + __ipw_led_activity_on(priv); spin_unlock_irqrestore(&priv->lock, flags); } @@ -808,13 +854,13 @@ void ipw_led_activity_off(struct ipw_priv *priv) spin_lock_irqsave(&priv->lock, flags); if (priv->status & STATUS_LED_ACT_ON) { - led = ipw_read_reg32(priv, CX2_EVENT_REG); + led = ipw_read_reg32(priv, IPW_EVENT_REG); led &= priv->led_activity_off; led = ipw_register_toggle(led); IPW_DEBUG_LED("Reg: 0x%08X\n", led); - ipw_write_reg32(priv, CX2_EVENT_REG, led); + ipw_write_reg32(priv, IPW_EVENT_REG, led); IPW_DEBUG_LED("Activity LED Off\n"); @@ -844,7 +890,7 @@ void ipw_led_band_on(struct ipw_priv *priv) spin_lock_irqsave(&priv->lock, flags); - led = ipw_read_reg32(priv, CX2_EVENT_REG); + led = ipw_read_reg32(priv, IPW_EVENT_REG); if (priv->assoc_network->mode == IEEE_A) { led |= priv->led_ofdm_on; led &= priv->led_association_off; @@ -862,7 +908,7 @@ void ipw_led_band_on(struct ipw_priv *priv) led = ipw_register_toggle(led); IPW_DEBUG_LED("Reg: 0x%08X\n", led); - ipw_write_reg32(priv, CX2_EVENT_REG, led); + ipw_write_reg32(priv, IPW_EVENT_REG, led); spin_unlock_irqrestore(&priv->lock, flags); } @@ -878,14 +924,14 @@ void ipw_led_band_off(struct ipw_priv *priv) spin_lock_irqsave(&priv->lock, flags); - led = ipw_read_reg32(priv, CX2_EVENT_REG); + led = ipw_read_reg32(priv, IPW_EVENT_REG); led &= priv->led_ofdm_off; led &= priv->led_association_off; led = ipw_register_toggle(led); IPW_DEBUG_LED("Reg: 0x%08X\n", led); - ipw_write_reg32(priv, CX2_EVENT_REG, led); + ipw_write_reg32(priv, IPW_EVENT_REG, led); spin_unlock_irqrestore(&priv->lock, flags); } @@ -921,23 +967,23 @@ void ipw_led_init(struct ipw_priv *priv) priv->nic_type = priv->eeprom[EEPROM_NIC_TYPE]; /* Set the default PINs for the link and activity leds */ - priv->led_activity_on = CX2_ACTIVITY_LED; - priv->led_activity_off = ~(CX2_ACTIVITY_LED); + priv->led_activity_on = IPW_ACTIVITY_LED; + priv->led_activity_off = ~(IPW_ACTIVITY_LED); - priv->led_association_on = CX2_ASSOCIATED_LED; - priv->led_association_off = ~(CX2_ASSOCIATED_LED); + priv->led_association_on = IPW_ASSOCIATED_LED; + priv->led_association_off = ~(IPW_ASSOCIATED_LED); /* Set the default PINs for the OFDM leds */ - priv->led_ofdm_on = CX2_OFDM_LED; - priv->led_ofdm_off = ~(CX2_OFDM_LED); + priv->led_ofdm_on = IPW_OFDM_LED; + priv->led_ofdm_off = ~(IPW_OFDM_LED); switch (priv->nic_type) { case EEPROM_NIC_TYPE_1: /* In this NIC type, the LEDs are reversed.... */ - priv->led_activity_on = CX2_ASSOCIATED_LED; - priv->led_activity_off = ~(CX2_ASSOCIATED_LED); - priv->led_association_on = CX2_ACTIVITY_LED; - priv->led_association_off = ~(CX2_ACTIVITY_LED); + priv->led_activity_on = IPW_ASSOCIATED_LED; + priv->led_activity_off = ~(IPW_ASSOCIATED_LED); + priv->led_association_on = IPW_ACTIVITY_LED; + priv->led_association_off = ~(IPW_ACTIVITY_LED); if (!(priv->config & CFG_NO_LED)) ipw_led_band_on(priv); @@ -1203,7 +1249,7 @@ static ssize_t show_command_event_reg(struct device *d, u32 reg = 0; struct ipw_priv *p = d->driver_data; - reg = ipw_read_reg32(p, CX2_INTERNAL_CMD_EVENT); + reg = ipw_read_reg32(p, IPW_INTERNAL_CMD_EVENT); return sprintf(buf, "0x%08x\n", reg); } static ssize_t store_command_event_reg(struct device *d, @@ -1214,7 +1260,7 @@ static ssize_t store_command_event_reg(struct device *d, struct ipw_priv *p = d->driver_data; sscanf(buf, "%x", ®); - ipw_write_reg32(p, CX2_INTERNAL_CMD_EVENT, reg); + ipw_write_reg32(p, IPW_INTERNAL_CMD_EVENT, reg); return strnlen(buf, count); } @@ -1361,7 +1407,6 @@ static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio) if (priv->workqueue) cancel_delayed_work(&priv->request_scan); - wake_up_interruptible(&priv->wait_command_queue); queue_work(priv->workqueue, &priv->down); } else { priv->status &= ~STATUS_RF_KILL_SW; @@ -1391,6 +1436,82 @@ static ssize_t store_rf_kill(struct device *d, struct device_attribute *attr, static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill); +static ssize_t show_speed_scan(struct device *d, struct device_attribute *attr, + char *buf) +{ + struct ipw_priv *priv = (struct ipw_priv *)d->driver_data; + int pos = 0, len = 0; + if (priv->config & CFG_SPEED_SCAN) { + while (priv->speed_scan[pos] != 0) + len += sprintf(&buf[len], "%d ", + priv->speed_scan[pos++]); + return len + sprintf(&buf[len], "\n"); + } + + return sprintf(buf, "0\n"); +} + +static ssize_t store_speed_scan(struct device *d, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ipw_priv *priv = (struct ipw_priv *)d->driver_data; + int channel, pos = 0; + const char *p = buf; + + /* list of space separated channels to scan, optionally ending with 0 */ + while ((channel = simple_strtol(p, NULL, 0))) { + if (pos == MAX_SPEED_SCAN - 1) { + priv->speed_scan[pos] = 0; + break; + } + + if (ieee80211_is_valid_channel(priv->ieee, channel)) + priv->speed_scan[pos++] = channel; + else + IPW_WARNING("Skipping invalid channel request: %d\n", + channel); + p = strchr(p, ' '); + if (!p) + break; + while (*p == ' ' || *p == '\t') + p++; + } + + if (pos == 0) + priv->config &= ~CFG_SPEED_SCAN; + else { + priv->speed_scan_pos = 0; + priv->config |= CFG_SPEED_SCAN; + } + + return count; +} + +static DEVICE_ATTR(speed_scan, S_IWUSR | S_IRUGO, show_speed_scan, + store_speed_scan); + +static ssize_t show_net_stats(struct device *d, struct device_attribute *attr, + char *buf) +{ + struct ipw_priv *priv = (struct ipw_priv *)d->driver_data; + return sprintf(buf, "%c\n", (priv->config & CFG_NET_STATS) ? '1' : '0'); +} + +static ssize_t store_net_stats(struct device *d, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ipw_priv *priv = (struct ipw_priv *)d->driver_data; + if (buf[0] == '1') + priv->config |= CFG_NET_STATS; + else + priv->config &= ~CFG_NET_STATS; + + return count; +} + +static DEVICE_ATTR(net_stats, S_IWUSR | S_IRUGO, show_net_stats, + store_net_stats); + static void notify_wx_assoc_event(struct ipw_priv *priv) { union iwreq_data wrqu; @@ -1410,77 +1531,77 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) spin_lock_irqsave(&priv->lock, flags); - inta = ipw_read32(priv, CX2_INTA_RW); - inta_mask = ipw_read32(priv, CX2_INTA_MASK_R); - inta &= (CX2_INTA_MASK_ALL & inta_mask); + inta = ipw_read32(priv, IPW_INTA_RW); + inta_mask = ipw_read32(priv, IPW_INTA_MASK_R); + inta &= (IPW_INTA_MASK_ALL & inta_mask); /* Add any cached INTA values that need to be handled */ inta |= priv->isr_inta; /* handle all the justifications for the interrupt */ - if (inta & CX2_INTA_BIT_RX_TRANSFER) { + if (inta & IPW_INTA_BIT_RX_TRANSFER) { ipw_rx(priv); - handled |= CX2_INTA_BIT_RX_TRANSFER; + handled |= IPW_INTA_BIT_RX_TRANSFER; } - if (inta & CX2_INTA_BIT_TX_CMD_QUEUE) { + if (inta & IPW_INTA_BIT_TX_CMD_QUEUE) { IPW_DEBUG_HC("Command completed.\n"); rc = ipw_queue_tx_reclaim(priv, &priv->txq_cmd, -1); priv->status &= ~STATUS_HCMD_ACTIVE; wake_up_interruptible(&priv->wait_command_queue); - handled |= CX2_INTA_BIT_TX_CMD_QUEUE; + handled |= IPW_INTA_BIT_TX_CMD_QUEUE; } - if (inta & CX2_INTA_BIT_TX_QUEUE_1) { + if (inta & IPW_INTA_BIT_TX_QUEUE_1) { IPW_DEBUG_TX("TX_QUEUE_1\n"); rc = ipw_queue_tx_reclaim(priv, &priv->txq[0], 0); - handled |= CX2_INTA_BIT_TX_QUEUE_1; + handled |= IPW_INTA_BIT_TX_QUEUE_1; } - if (inta & CX2_INTA_BIT_TX_QUEUE_2) { + if (inta & IPW_INTA_BIT_TX_QUEUE_2) { IPW_DEBUG_TX("TX_QUEUE_2\n"); rc = ipw_queue_tx_reclaim(priv, &priv->txq[1], 1); - handled |= CX2_INTA_BIT_TX_QUEUE_2; + handled |= IPW_INTA_BIT_TX_QUEUE_2; } - if (inta & CX2_INTA_BIT_TX_QUEUE_3) { + if (inta & IPW_INTA_BIT_TX_QUEUE_3) { IPW_DEBUG_TX("TX_QUEUE_3\n"); rc = ipw_queue_tx_reclaim(priv, &priv->txq[2], 2); - handled |= CX2_INTA_BIT_TX_QUEUE_3; + handled |= IPW_INTA_BIT_TX_QUEUE_3; } - if (inta & CX2_INTA_BIT_TX_QUEUE_4) { + if (inta & IPW_INTA_BIT_TX_QUEUE_4) { IPW_DEBUG_TX("TX_QUEUE_4\n"); rc = ipw_queue_tx_reclaim(priv, &priv->txq[3], 3); - handled |= CX2_INTA_BIT_TX_QUEUE_4; + handled |= IPW_INTA_BIT_TX_QUEUE_4; } - if (inta & CX2_INTA_BIT_STATUS_CHANGE) { + if (inta & IPW_INTA_BIT_STATUS_CHANGE) { IPW_WARNING("STATUS_CHANGE\n"); - handled |= CX2_INTA_BIT_STATUS_CHANGE; + handled |= IPW_INTA_BIT_STATUS_CHANGE; } - if (inta & CX2_INTA_BIT_BEACON_PERIOD_EXPIRED) { + if (inta & IPW_INTA_BIT_BEACON_PERIOD_EXPIRED) { IPW_WARNING("TX_PERIOD_EXPIRED\n"); - handled |= CX2_INTA_BIT_BEACON_PERIOD_EXPIRED; + handled |= IPW_INTA_BIT_BEACON_PERIOD_EXPIRED; } - if (inta & CX2_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE) { + if (inta & IPW_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE) { IPW_WARNING("HOST_CMD_DONE\n"); - handled |= CX2_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE; + handled |= IPW_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE; } - if (inta & CX2_INTA_BIT_FW_INITIALIZATION_DONE) { + if (inta & IPW_INTA_BIT_FW_INITIALIZATION_DONE) { IPW_WARNING("FW_INITIALIZATION_DONE\n"); - handled |= CX2_INTA_BIT_FW_INITIALIZATION_DONE; + handled |= IPW_INTA_BIT_FW_INITIALIZATION_DONE; } - if (inta & CX2_INTA_BIT_FW_CARD_DISABLE_PHY_OFF_DONE) { + if (inta & IPW_INTA_BIT_FW_CARD_DISABLE_PHY_OFF_DONE) { IPW_WARNING("PHY_OFF_DONE\n"); - handled |= CX2_INTA_BIT_FW_CARD_DISABLE_PHY_OFF_DONE; + handled |= IPW_INTA_BIT_FW_CARD_DISABLE_PHY_OFF_DONE; } - if (inta & CX2_INTA_BIT_RF_KILL_DONE) { + if (inta & IPW_INTA_BIT_RF_KILL_DONE) { IPW_DEBUG_RF_KILL("RF_KILL_DONE\n"); priv->status |= STATUS_RF_KILL_HW; wake_up_interruptible(&priv->wait_command_queue); @@ -1488,10 +1609,10 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) cancel_delayed_work(&priv->request_scan); schedule_work(&priv->link_down); queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ); - handled |= CX2_INTA_BIT_RF_KILL_DONE; + handled |= IPW_INTA_BIT_RF_KILL_DONE; } - if (inta & CX2_INTA_BIT_FATAL_ERROR) { + if (inta & IPW_INTA_BIT_FATAL_ERROR) { IPW_ERROR("Firmware error detected. Restarting.\n"); #ifdef CONFIG_IPW_DEBUG if (ipw_debug_level & IPW_DL_FW_ERRORS) { @@ -1499,13 +1620,23 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) ipw_dump_nic_event_log(priv); } #endif + /* XXX: If hardware encryption is for WPA/WPA2, + * we have to notify the supplicant. */ + if (priv->ieee->sec.encrypt) { + priv->status &= ~STATUS_ASSOCIATED; + notify_wx_assoc_event(priv); + } + + /* Keep the restart process from trying to send host + * commands by clearing the INIT status bit */ + priv->status &= ~STATUS_INIT; queue_work(priv->workqueue, &priv->adapter_restart); - handled |= CX2_INTA_BIT_FATAL_ERROR; + handled |= IPW_INTA_BIT_FATAL_ERROR; } - if (inta & CX2_INTA_BIT_PARITY_ERROR) { + if (inta & IPW_INTA_BIT_PARITY_ERROR) { IPW_ERROR("Parity error\n"); - handled |= CX2_INTA_BIT_PARITY_ERROR; + handled |= IPW_INTA_BIT_PARITY_ERROR; } if (handled != inta) { @@ -1594,8 +1725,9 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) priv->status |= STATUS_HCMD_ACTIVE; - IPW_DEBUG_HC("Sending %s command (#%d), %d bytes\n", - get_cmd_string(cmd->cmd), cmd->cmd, cmd->len); + IPW_DEBUG_HC("%s command (#%d) %d bytes: 0x%08X\n", + get_cmd_string(cmd->cmd), cmd->cmd, cmd->len, + priv->status); printk_buf(IPW_DL_HOST_COMMAND, (u8 *) cmd->param, cmd->len); rc = ipw_queue_tx_hcmd(priv, cmd->cmd, &cmd->param, cmd->len, 0); @@ -1623,7 +1755,7 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) spin_unlock_irqrestore(&priv->lock, flags); } - if (priv->status & STATUS_RF_KILL_MASK) { + if (priv->status & STATUS_RF_KILL_HW) { IPW_DEBUG_INFO("Command aborted due to RF Kill Switch\n"); return -EIO; } @@ -1732,10 +1864,20 @@ static void ipw_adapter_restart(void *adapter) return; ipw_down(priv); + + if (priv->assoc_network && + (priv->assoc_network->capability & WLAN_CAPABILITY_IBSS)) + ipw_remove_current_network(priv); + if (ipw_up(priv)) { IPW_ERROR("Failed to up device\n"); return; } + + if ((priv->capability & CAP_PRIVACY_ON) && + (priv->ieee->sec.level == SEC_LEVEL_1) && + !(priv->ieee->host_encrypt || priv->ieee->host_decrypt)) + ipw_set_hwcrypto_keys(priv); } static void ipw_bg_adapter_restart(void *data) @@ -1775,11 +1917,6 @@ static int ipw_send_scan_request_ext(struct ipw_priv *priv, .len = sizeof(*request) }; - if (!priv || !request) { - IPW_ERROR("Invalid args\n"); - return -1; - } - memcpy(&cmd.param, request, sizeof(*request)); if (ipw_send_cmd(priv, &cmd)) { IPW_ERROR("failed to send SCAN_REQUEST_EXT command\n"); @@ -1907,7 +2044,6 @@ static int ipw_set_random_seed(struct ipw_priv *priv) return 0; } -#if 0 static int ipw_send_card_disable(struct ipw_priv *priv, u32 phy_off) { struct host_cmd cmd = { @@ -1929,7 +2065,6 @@ static int ipw_send_card_disable(struct ipw_priv *priv, u32 phy_off) return 0; } -#endif static int ipw_send_tx_power(struct ipw_priv *priv, struct ipw_tx_power *power) { @@ -2166,7 +2301,7 @@ static void ipw_eeprom_init_sram(struct ipw_priv *priv) IPW_DEBUG_INFO("Writing EEPROM data into SRAM\n"); /* write the eeprom data to sram */ - for (i = 0; i < CX2_EEPROM_IMAGE_SIZE; i++) + for (i = 0; i < IPW_EEPROM_IMAGE_SIZE; i++) ipw_write8(priv, IPW_EEPROM_DATA + i, priv->eeprom[i]); /* Do not load eeprom data on fatal error or suspend */ @@ -2186,14 +2321,14 @@ static inline void ipw_zero_memory(struct ipw_priv *priv, u32 start, u32 count) count >>= 2; if (!count) return; - _ipw_write32(priv, CX2_AUTOINC_ADDR, start); + _ipw_write32(priv, IPW_AUTOINC_ADDR, start); while (count--) - _ipw_write32(priv, CX2_AUTOINC_DATA, 0); + _ipw_write32(priv, IPW_AUTOINC_DATA, 0); } static inline void ipw_fw_dma_reset_command_blocks(struct ipw_priv *priv) { - ipw_zero_memory(priv, CX2_SHARED_SRAM_DMA_CONTROL, + ipw_zero_memory(priv, IPW_SHARED_SRAM_DMA_CONTROL, CB_NUMBER_OF_ELEMENTS_SMALL * sizeof(struct command_block)); } @@ -2207,7 +2342,7 @@ static int ipw_fw_dma_enable(struct ipw_priv *priv) ipw_fw_dma_reset_command_blocks(priv); /* Write CB base address */ - ipw_write_reg32(priv, CX2_DMA_I_CB_BASE, CX2_SHARED_SRAM_DMA_CONTROL); + ipw_write_reg32(priv, IPW_DMA_I_CB_BASE, IPW_SHARED_SRAM_DMA_CONTROL); IPW_DEBUG_FW("<< : \n"); return 0; @@ -2221,7 +2356,7 @@ static void ipw_fw_dma_abort(struct ipw_priv *priv) //set the Stop and Abort bit control = DMA_CONTROL_SMALL_CB_CONST_VALUE | DMA_CB_STOP_AND_ABORT; - ipw_write_reg32(priv, CX2_DMA_I_DMA_CONTROL, control); + ipw_write_reg32(priv, IPW_DMA_I_DMA_CONTROL, control); priv->sram_desc.last_cb_index = 0; IPW_DEBUG_FW("<< \n"); @@ -2231,7 +2366,7 @@ static int ipw_fw_dma_write_command_block(struct ipw_priv *priv, int index, struct command_block *cb) { u32 address = - CX2_SHARED_SRAM_DMA_CONTROL + + IPW_SHARED_SRAM_DMA_CONTROL + (sizeof(struct command_block) * index); IPW_DEBUG_FW(">> :\n"); @@ -2255,13 +2390,13 @@ static int ipw_fw_dma_kick(struct ipw_priv *priv) &priv->sram_desc.cb_list[index]); /* Enable the DMA in the CSR register */ - ipw_clear_bit(priv, CX2_RESET_REG, - CX2_RESET_REG_MASTER_DISABLED | - CX2_RESET_REG_STOP_MASTER); + ipw_clear_bit(priv, IPW_RESET_REG, + IPW_RESET_REG_MASTER_DISABLED | + IPW_RESET_REG_STOP_MASTER); /* Set the Start bit. */ control = DMA_CONTROL_SMALL_CB_CONST_VALUE | DMA_CB_START; - ipw_write_reg32(priv, CX2_DMA_I_DMA_CONTROL, control); + ipw_write_reg32(priv, IPW_DMA_I_DMA_CONTROL, control); IPW_DEBUG_FW("<< :\n"); return 0; @@ -2274,12 +2409,12 @@ static void ipw_fw_dma_dump_command_block(struct ipw_priv *priv) u32 cb_fields_address = 0; IPW_DEBUG_FW(">> :\n"); - address = ipw_read_reg32(priv, CX2_DMA_I_CURRENT_CB); + address = ipw_read_reg32(priv, IPW_DMA_I_CURRENT_CB); IPW_DEBUG_FW_INFO("Current CB is 0x%x \n", address); /* Read the DMA Controlor register */ - register_value = ipw_read_reg32(priv, CX2_DMA_I_DMA_CONTROL); - IPW_DEBUG_FW_INFO("CX2_DMA_I_DMA_CONTROL is 0x%x \n", register_value); + register_value = ipw_read_reg32(priv, IPW_DMA_I_DMA_CONTROL); + IPW_DEBUG_FW_INFO("IPW_DMA_I_DMA_CONTROL is 0x%x \n", register_value); /* Print the CB values */ cb_fields_address = address; @@ -2308,9 +2443,9 @@ static int ipw_fw_dma_command_block_index(struct ipw_priv *priv) u32 current_cb_index = 0; IPW_DEBUG_FW("<< :\n"); - current_cb_address = ipw_read_reg32(priv, CX2_DMA_I_CURRENT_CB); + current_cb_address = ipw_read_reg32(priv, IPW_DMA_I_CURRENT_CB); - current_cb_index = (current_cb_address - CX2_SHARED_SRAM_DMA_CONTROL) / + current_cb_index = (current_cb_address - IPW_SHARED_SRAM_DMA_CONTROL) / sizeof(struct command_block); IPW_DEBUG_FW_INFO("Current CB index 0x%x address = 0x%X \n", @@ -2439,8 +2574,8 @@ static int ipw_fw_dma_wait(struct ipw_priv *priv) ipw_fw_dma_abort(priv); /*Disable the DMA in the CSR register */ - ipw_set_bit(priv, CX2_RESET_REG, - CX2_RESET_REG_MASTER_DISABLED | CX2_RESET_REG_STOP_MASTER); + ipw_set_bit(priv, IPW_RESET_REG, + IPW_RESET_REG_MASTER_DISABLED | IPW_RESET_REG_STOP_MASTER); IPW_DEBUG_FW("<< dmaWaitSync \n"); return 0; @@ -2504,10 +2639,10 @@ static int ipw_stop_master(struct ipw_priv *priv) IPW_DEBUG_TRACE(">> \n"); /* stop master. typical delay - 0 */ - ipw_set_bit(priv, CX2_RESET_REG, CX2_RESET_REG_STOP_MASTER); + ipw_set_bit(priv, IPW_RESET_REG, IPW_RESET_REG_STOP_MASTER); - rc = ipw_poll_bit(priv, CX2_RESET_REG, - CX2_RESET_REG_MASTER_DISABLED, 100); + rc = ipw_poll_bit(priv, IPW_RESET_REG, + IPW_RESET_REG_MASTER_DISABLED, 100); if (rc < 0) { IPW_ERROR("stop master failed in 10ms\n"); return -1; @@ -2523,7 +2658,7 @@ static void ipw_arc_release(struct ipw_priv *priv) IPW_DEBUG_TRACE(">> \n"); mdelay(5); - ipw_clear_bit(priv, CX2_RESET_REG, CBD_RESET_REG_PRINCETON_RESET); + ipw_clear_bit(priv, IPW_RESET_REG, CBD_RESET_REG_PRINCETON_RESET); /* no one knows timing, for safety add some delay */ mdelay(5); @@ -2540,7 +2675,7 @@ struct fw_chunk { }; #define IPW_FW_MAJOR_VERSION 2 -#define IPW_FW_MINOR_VERSION 2 +#define IPW_FW_MINOR_VERSION 3 #define IPW_FW_MINOR(x) ((x & 0xff) >> 8) #define IPW_FW_MAJOR(x) (x & 0xff) @@ -2574,8 +2709,8 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) // spin_lock_irqsave(&priv->lock, flags); - for (addr = CX2_SHARED_LOWER_BOUND; - addr < CX2_REGISTER_DOMAIN1_END; addr += 4) { + for (addr = IPW_SHARED_LOWER_BOUND; + addr < IPW_REGISTER_DOMAIN1_END; addr += 4) { ipw_write32(priv, addr, 0); } @@ -2584,16 +2719,16 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) /* destroy DMA queues */ /* reset sequence */ - ipw_write_reg32(priv, CX2_MEM_HALT_AND_RESET, CX2_BIT_HALT_RESET_ON); + ipw_write_reg32(priv, IPW_MEM_HALT_AND_RESET, IPW_BIT_HALT_RESET_ON); ipw_arc_release(priv); - ipw_write_reg32(priv, CX2_MEM_HALT_AND_RESET, CX2_BIT_HALT_RESET_OFF); + ipw_write_reg32(priv, IPW_MEM_HALT_AND_RESET, IPW_BIT_HALT_RESET_OFF); mdelay(1); /* reset PHY */ - ipw_write_reg32(priv, CX2_INTERNAL_CMD_EVENT, CX2_BASEBAND_POWER_DOWN); + ipw_write_reg32(priv, IPW_INTERNAL_CMD_EVENT, IPW_BASEBAND_POWER_DOWN); mdelay(1); - ipw_write_reg32(priv, CX2_INTERNAL_CMD_EVENT, 0); + ipw_write_reg32(priv, IPW_INTERNAL_CMD_EVENT, 0); mdelay(1); /* enable ucode store */ @@ -2611,19 +2746,19 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) */ /* load new ipw uCode */ for (i = 0; i < len / 2; i++) - ipw_write_reg16(priv, CX2_BASEBAND_CONTROL_STORE, + ipw_write_reg16(priv, IPW_BASEBAND_CONTROL_STORE, cpu_to_le16(image[i])); /* enable DINO */ - ipw_write_reg8(priv, CX2_BASEBAND_CONTROL_STATUS, 0); - ipw_write_reg8(priv, CX2_BASEBAND_CONTROL_STATUS, DINO_ENABLE_SYSTEM); + ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, 0); + ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, DINO_ENABLE_SYSTEM); /* this is where the igx / win driver deveates from the VAP driver. */ /* wait for alive response */ for (i = 0; i < 100; i++) { /* poll for incoming data */ - cr = ipw_read_reg8(priv, CX2_BASEBAND_CONTROL_STATUS); + cr = ipw_read_reg8(priv, IPW_BASEBAND_CONTROL_STATUS); if (cr & DINO_RXFIFO_DATA) break; mdelay(1); @@ -2636,7 +2771,7 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) for (i = 0; i < ARRAY_SIZE(response_buffer); i++) response_buffer[i] = le32_to_cpu(ipw_read_reg32(priv, - CX2_BASEBAND_RX_FIFO_READ)); + IPW_BASEBAND_RX_FIFO_READ)); memcpy(&priv->dino_alive, response_buffer, sizeof(priv->dino_alive)); if (priv->dino_alive.alive_command == 1 @@ -2665,7 +2800,7 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) /* disable DINO, otherwise for some reason firmware have problem getting alive resp. */ - ipw_write_reg8(priv, CX2_BASEBAND_CONTROL_STATUS, 0); + ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, 0); // spin_unlock_irqrestore(&priv->lock, flags); @@ -2738,16 +2873,16 @@ static int ipw_stop_nic(struct ipw_priv *priv) int rc = 0; /* stop */ - ipw_write32(priv, CX2_RESET_REG, CX2_RESET_REG_STOP_MASTER); + ipw_write32(priv, IPW_RESET_REG, IPW_RESET_REG_STOP_MASTER); - rc = ipw_poll_bit(priv, CX2_RESET_REG, - CX2_RESET_REG_MASTER_DISABLED, 500); + rc = ipw_poll_bit(priv, IPW_RESET_REG, + IPW_RESET_REG_MASTER_DISABLED, 500); if (rc < 0) { IPW_ERROR("wait for reg master disabled failed\n"); return rc; } - ipw_set_bit(priv, CX2_RESET_REG, CBD_RESET_REG_PRINCETON_RESET); + ipw_set_bit(priv, IPW_RESET_REG, CBD_RESET_REG_PRINCETON_RESET); return rc; } @@ -2757,14 +2892,14 @@ static void ipw_start_nic(struct ipw_priv *priv) IPW_DEBUG_TRACE(">>\n"); /* prvHwStartNic release ARC */ - ipw_clear_bit(priv, CX2_RESET_REG, - CX2_RESET_REG_MASTER_DISABLED | - CX2_RESET_REG_STOP_MASTER | + ipw_clear_bit(priv, IPW_RESET_REG, + IPW_RESET_REG_MASTER_DISABLED | + IPW_RESET_REG_STOP_MASTER | CBD_RESET_REG_PRINCETON_RESET); /* enable power management */ - ipw_set_bit(priv, CX2_GP_CNTRL_RW, - CX2_GP_CNTRL_BIT_HOST_ALLOWS_STANDBY); + ipw_set_bit(priv, IPW_GP_CNTRL_RW, + IPW_GP_CNTRL_BIT_HOST_ALLOWS_STANDBY); IPW_DEBUG_TRACE("<<\n"); } @@ -2777,25 +2912,25 @@ static int ipw_init_nic(struct ipw_priv *priv) /* reset */ /*prvHwInitNic */ /* set "initialization complete" bit to move adapter to D0 state */ - ipw_set_bit(priv, CX2_GP_CNTRL_RW, CX2_GP_CNTRL_BIT_INIT_DONE); + ipw_set_bit(priv, IPW_GP_CNTRL_RW, IPW_GP_CNTRL_BIT_INIT_DONE); /* low-level PLL activation */ - ipw_write32(priv, CX2_READ_INT_REGISTER, - CX2_BIT_INT_HOST_SRAM_READ_INT_REGISTER); + ipw_write32(priv, IPW_READ_INT_REGISTER, + IPW_BIT_INT_HOST_SRAM_READ_INT_REGISTER); /* wait for clock stabilization */ - rc = ipw_poll_bit(priv, CX2_GP_CNTRL_RW, - CX2_GP_CNTRL_BIT_CLOCK_READY, 250); + rc = ipw_poll_bit(priv, IPW_GP_CNTRL_RW, + IPW_GP_CNTRL_BIT_CLOCK_READY, 250); if (rc < 0) IPW_DEBUG_INFO("FAILED wait for clock stablization\n"); /* assert SW reset */ - ipw_set_bit(priv, CX2_RESET_REG, CX2_RESET_REG_SW_RESET); + ipw_set_bit(priv, IPW_RESET_REG, IPW_RESET_REG_SW_RESET); udelay(10); /* set "initialization complete" bit to move adapter to D0 state */ - ipw_set_bit(priv, CX2_GP_CNTRL_RW, CX2_GP_CNTRL_BIT_INIT_DONE); + ipw_set_bit(priv, IPW_GP_CNTRL_RW, IPW_GP_CNTRL_BIT_INIT_DONE); IPW_DEBUG_TRACE(">>\n"); return 0; @@ -2853,7 +2988,7 @@ static int ipw_get_fw(struct ipw_priv *priv, return 0; } -#define CX2_RX_BUF_SIZE (3000) +#define IPW_RX_BUF_SIZE (3000) static inline void ipw_rx_queue_reset(struct ipw_priv *priv, struct ipw_rx_queue *rxq) @@ -2872,7 +3007,7 @@ static inline void ipw_rx_queue_reset(struct ipw_priv *priv, * to an SKB, so we need to unmap and free potential storage */ if (rxq->pool[i].skb != NULL) { pci_unmap_single(priv->pci_dev, rxq->pool[i].dma_addr, - CX2_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); + IPW_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); dev_kfree_skb(rxq->pool[i].skb); rxq->pool[i].skb = NULL; } @@ -2920,7 +3055,7 @@ static int ipw_load(struct ipw_priv *priv) rc = ipw_get_fw(priv, &firmware, IPW_FW_NAME("ibss")); break; -#ifdef CONFIG_IPW_MONITOR +#ifdef CONFIG_IPW2200_MONITOR case IW_MODE_MONITOR: rc = ipw_get_fw(priv, &ucode, IPW_FW_NAME("sniffer_ucode")); @@ -2962,11 +3097,11 @@ static int ipw_load(struct ipw_priv *priv) retry: /* Ensure interrupts are disabled */ - ipw_write32(priv, CX2_INTA_MASK_R, ~CX2_INTA_MASK_ALL); + ipw_write32(priv, IPW_INTA_MASK_R, ~IPW_INTA_MASK_ALL); priv->status &= ~STATUS_INT_ENABLED; /* ack pending interrupts */ - ipw_write32(priv, CX2_INTA_RW, CX2_INTA_MASK_ALL); + ipw_write32(priv, IPW_INTA_RW, IPW_INTA_MASK_ALL); ipw_stop_nic(priv); @@ -2976,8 +3111,8 @@ static int ipw_load(struct ipw_priv *priv) goto error; } - ipw_zero_memory(priv, CX2_NIC_SRAM_LOWER_BOUND, - CX2_NIC_SRAM_UPPER_BOUND - CX2_NIC_SRAM_LOWER_BOUND); + ipw_zero_memory(priv, IPW_NIC_SRAM_LOWER_BOUND, + IPW_NIC_SRAM_UPPER_BOUND - IPW_NIC_SRAM_LOWER_BOUND); /* DMA the initial boot firmware into the device */ rc = ipw_load_firmware(priv, bootfw->data + sizeof(struct fw_header), @@ -2991,8 +3126,8 @@ static int ipw_load(struct ipw_priv *priv) ipw_start_nic(priv); /* wait for the device to finish it's initial startup sequence */ - rc = ipw_poll_bit(priv, CX2_INTA_RW, - CX2_INTA_BIT_FW_INITIALIZATION_DONE, 500); + rc = ipw_poll_bit(priv, IPW_INTA_RW, + IPW_INTA_BIT_FW_INITIALIZATION_DONE, 500); if (rc < 0) { IPW_ERROR("device failed to boot initial fw image\n"); goto error; @@ -3000,7 +3135,7 @@ static int ipw_load(struct ipw_priv *priv) IPW_DEBUG_INFO("initial device response after %dms\n", rc); /* ack fw init done interrupt */ - ipw_write32(priv, CX2_INTA_RW, CX2_INTA_BIT_FW_INITIALIZATION_DONE); + ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE); /* DMA the ucode into the device */ rc = ipw_load_ucode(priv, ucode->data + sizeof(struct fw_header), @@ -3031,14 +3166,14 @@ static int ipw_load(struct ipw_priv *priv) } /* Ensure interrupts are disabled */ - ipw_write32(priv, CX2_INTA_MASK_R, ~CX2_INTA_MASK_ALL); + ipw_write32(priv, IPW_INTA_MASK_R, ~IPW_INTA_MASK_ALL); /* ack pending interrupts */ - ipw_write32(priv, CX2_INTA_RW, CX2_INTA_MASK_ALL); + ipw_write32(priv, IPW_INTA_RW, IPW_INTA_MASK_ALL); /* kick start the device */ ipw_start_nic(priv); - if (ipw_read32(priv, CX2_INTA_RW) & CX2_INTA_BIT_PARITY_ERROR) { + if (ipw_read32(priv, IPW_INTA_RW) & IPW_INTA_BIT_PARITY_ERROR) { if (retries > 0) { IPW_WARNING("Parity error. Retrying init.\n"); retries--; @@ -3051,8 +3186,8 @@ static int ipw_load(struct ipw_priv *priv) } /* wait for the device */ - rc = ipw_poll_bit(priv, CX2_INTA_RW, - CX2_INTA_BIT_FW_INITIALIZATION_DONE, 500); + rc = ipw_poll_bit(priv, IPW_INTA_RW, + IPW_INTA_BIT_FW_INITIALIZATION_DONE, 500); if (rc < 0) { IPW_ERROR("device failed to start after 500ms\n"); goto error; @@ -3060,7 +3195,7 @@ static int ipw_load(struct ipw_priv *priv) IPW_DEBUG_INFO("device response after %dms\n", rc); /* ack fw init done interrupt */ - ipw_write32(priv, CX2_INTA_RW, CX2_INTA_BIT_FW_INITIALIZATION_DONE); + ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE); /* read eeprom data and initialize the eeprom region of sram */ priv->eeprom_delay = 1; @@ -3072,10 +3207,10 @@ static int ipw_load(struct ipw_priv *priv) /* Ensure our queue has valid packets */ ipw_rx_queue_replenish(priv); - ipw_write32(priv, CX2_RX_READ_INDEX, priv->rxq->read); + ipw_write32(priv, IPW_RX_READ_INDEX, priv->rxq->read); /* ack pending interrupts */ - ipw_write32(priv, CX2_INTA_RW, CX2_INTA_MASK_ALL); + ipw_write32(priv, IPW_INTA_RW, IPW_INTA_MASK_ALL); #ifndef CONFIG_PM release_firmware(bootfw); @@ -3829,8 +3964,8 @@ static inline void ipw_handle_missed_beacon(struct ipw_priv *priv, * stuck (only if we aren't roaming -- * otherwise we'll never scan more than 2 or 3 * channels..) */ - IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF | - IPW_DL_STATE, "Aborting scan with missed beacon.\n"); + IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF | IPW_DL_STATE, + "Aborting scan with missed beacon.\n"); queue_work(priv->workqueue, &priv->abort_scan); } @@ -3891,6 +4026,35 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, priv->status &= ~STATUS_ASSOCIATING; priv->status |= STATUS_ASSOCIATED; +#ifdef CONFIG_IPW_QOS + if (priv->status & STATUS_AUTH) { + if ((sizeof + (struct + ieee80211_assoc_response_frame) + <= notif->size) + && (notif->size <= 2314)) { + struct + ieee80211_rx_stats + stats = { + .len = + notif-> + size - 1, + }; + + IPW_DEBUG_QOS + ("QoS Associate " + "size %d\n", + notif->size); + ieee80211_rx_mgt(priv-> + ieee, + (struct + ieee80211_hdr + *) + ¬if->u.raw, &stats); + } + } +#endif + schedule_work(&priv->link_up); break; @@ -3970,12 +4134,21 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, ~(STATUS_DISASSOCIATING | STATUS_ASSOCIATING | STATUS_ASSOCIATED | STATUS_AUTH); + if (priv->assoc_network + && (priv->assoc_network-> + capability & + WLAN_CAPABILITY_IBSS)) + ipw_remove_current_network + (priv); schedule_work(&priv->link_down); break; } + case CMAS_RX_ASSOC_RESP: + break; + default: IPW_ERROR("assoc: unknown (%d)\n", assoc->state); @@ -4060,6 +4233,7 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, case CMAS_RX_ASSOC_RESP: IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC, "RX_ASSOC_RESP\n"); + break; case CMAS_ASSOCIATED: IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | @@ -4106,6 +4280,19 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, cancel_delayed_work(&priv->scan_check); + if (priv->status & STATUS_EXIT_PENDING) + break; + + priv->ieee->scans++; + +#ifdef CONFIG_IPW2200_MONITOR + if (priv->ieee->iw_mode == IW_MODE_MONITOR) { + queue_work(priv->workqueue, + &priv->request_scan); + break; + } +#endif /* CONFIG_IPW2200_MONITOR */ + if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING | STATUS_ROAMING | @@ -4124,8 +4311,6 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, && priv->status & STATUS_ASSOCIATED) queue_delayed_work(priv->workqueue, &priv->request_scan, HZ); - - priv->ieee->scans++; break; } @@ -4256,43 +4441,43 @@ static int ipw_queue_reset(struct ipw_priv *priv) ipw_tx_queue_free(priv); /* Tx CMD queue */ rc = ipw_queue_tx_init(priv, &priv->txq_cmd, nTxCmd, - CX2_TX_CMD_QUEUE_READ_INDEX, - CX2_TX_CMD_QUEUE_WRITE_INDEX, - CX2_TX_CMD_QUEUE_BD_BASE, - CX2_TX_CMD_QUEUE_BD_SIZE); + IPW_TX_CMD_QUEUE_READ_INDEX, + IPW_TX_CMD_QUEUE_WRITE_INDEX, + IPW_TX_CMD_QUEUE_BD_BASE, + IPW_TX_CMD_QUEUE_BD_SIZE); if (rc) { IPW_ERROR("Tx Cmd queue init failed\n"); goto error; } /* Tx queue(s) */ rc = ipw_queue_tx_init(priv, &priv->txq[0], nTx, - CX2_TX_QUEUE_0_READ_INDEX, - CX2_TX_QUEUE_0_WRITE_INDEX, - CX2_TX_QUEUE_0_BD_BASE, CX2_TX_QUEUE_0_BD_SIZE); + IPW_TX_QUEUE_0_READ_INDEX, + IPW_TX_QUEUE_0_WRITE_INDEX, + IPW_TX_QUEUE_0_BD_BASE, IPW_TX_QUEUE_0_BD_SIZE); if (rc) { IPW_ERROR("Tx 0 queue init failed\n"); goto error; } rc = ipw_queue_tx_init(priv, &priv->txq[1], nTx, - CX2_TX_QUEUE_1_READ_INDEX, - CX2_TX_QUEUE_1_WRITE_INDEX, - CX2_TX_QUEUE_1_BD_BASE, CX2_TX_QUEUE_1_BD_SIZE); + IPW_TX_QUEUE_1_READ_INDEX, + IPW_TX_QUEUE_1_WRITE_INDEX, + IPW_TX_QUEUE_1_BD_BASE, IPW_TX_QUEUE_1_BD_SIZE); if (rc) { IPW_ERROR("Tx 1 queue init failed\n"); goto error; } rc = ipw_queue_tx_init(priv, &priv->txq[2], nTx, - CX2_TX_QUEUE_2_READ_INDEX, - CX2_TX_QUEUE_2_WRITE_INDEX, - CX2_TX_QUEUE_2_BD_BASE, CX2_TX_QUEUE_2_BD_SIZE); + IPW_TX_QUEUE_2_READ_INDEX, + IPW_TX_QUEUE_2_WRITE_INDEX, + IPW_TX_QUEUE_2_BD_BASE, IPW_TX_QUEUE_2_BD_SIZE); if (rc) { IPW_ERROR("Tx 2 queue init failed\n"); goto error; } rc = ipw_queue_tx_init(priv, &priv->txq[3], nTx, - CX2_TX_QUEUE_3_READ_INDEX, - CX2_TX_QUEUE_3_WRITE_INDEX, - CX2_TX_QUEUE_3_BD_BASE, CX2_TX_QUEUE_3_BD_SIZE); + IPW_TX_QUEUE_3_READ_INDEX, + IPW_TX_QUEUE_3_WRITE_INDEX, + IPW_TX_QUEUE_3_BD_BASE, IPW_TX_QUEUE_3_BD_SIZE); if (rc) { IPW_ERROR("Tx 3 queue init failed\n"); goto error; @@ -4382,7 +4567,7 @@ static int ipw_queue_tx_hcmd(struct ipw_priv *priv, int hcmd, void *buf, * Rx theory of operation * * The host allocates 32 DMA target addresses and passes the host address - * to the firmware at register CX2_RFDS_TABLE_LOWER + N * RFD_SIZE where N is + * to the firmware at register IPW_RFDS_TABLE_LOWER + N * RFD_SIZE where N is * 0 to 31 * * Rx Queue Indexes @@ -4466,7 +4651,7 @@ static void ipw_rx_queue_restock(struct ipw_priv *priv) rxb = list_entry(element, struct ipw_rx_mem_buffer, list); list_del(element); - ipw_write32(priv, CX2_RFDS_TABLE_LOWER + rxq->write * RFD_SIZE, + ipw_write32(priv, IPW_RFDS_TABLE_LOWER + rxq->write * RFD_SIZE, rxb->dma_addr); rxq->queue[rxq->write] = rxb; rxq->write = (rxq->write + 1) % RX_QUEUE_SIZE; @@ -4481,7 +4666,7 @@ static void ipw_rx_queue_restock(struct ipw_priv *priv) /* If we've added more space for the firmware to place data, tell it */ if (write != rxq->write) - ipw_write32(priv, CX2_RX_WRITE_INDEX, rxq->write); + ipw_write32(priv, IPW_RX_WRITE_INDEX, rxq->write); } /* @@ -4502,7 +4687,7 @@ static void ipw_rx_queue_replenish(void *data) while (!list_empty(&rxq->rx_used)) { element = rxq->rx_used.next; rxb = list_entry(element, struct ipw_rx_mem_buffer, list); - rxb->skb = alloc_skb(CX2_RX_BUF_SIZE, GFP_ATOMIC); + rxb->skb = alloc_skb(IPW_RX_BUF_SIZE, GFP_ATOMIC); if (!rxb->skb) { printk(KERN_CRIT "%s: Can not allocate SKB buffers.\n", priv->net_dev->name); @@ -4516,7 +4701,7 @@ static void ipw_rx_queue_replenish(void *data) rxb->rxb = (struct ipw_rx_buffer *)rxb->skb->data; rxb->dma_addr = pci_map_single(priv->pci_dev, rxb->skb->data, - CX2_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); + IPW_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); list_add_tail(&rxb->list, &rxq->rx_free); rxq->free_count++; @@ -4549,7 +4734,7 @@ static void ipw_rx_queue_free(struct ipw_priv *priv, struct ipw_rx_queue *rxq) for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { if (rxq->pool[i].skb != NULL) { pci_unmap_single(priv->pci_dev, rxq->pool[i].dma_addr, - CX2_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); + IPW_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); dev_kfree_skb(rxq->pool[i].skb); } } @@ -5195,20 +5380,21 @@ static void ipw_adhoc_create(struct ipw_priv *priv, * with an invalid channel for wireless mode will trigger a * FW fatal error. */ - network->mode = is_valid_channel(priv->ieee->mode, priv->channel); - if (!network->mode) { + if (!ieee80211_is_valid_channel(priv->ieee, priv->channel)) { + const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); IPW_WARNING("Overriding invalid channel\n"); if (priv->ieee->mode & IEEE_A) { network->mode = IEEE_A; - priv->channel = band_a_active_channel[0]; + priv->channel = geo->a[0].channel; } else if (priv->ieee->mode & IEEE_G) { network->mode = IEEE_G; - priv->channel = band_b_active_channel[0]; + priv->channel = geo->bg[0].channel; } else { network->mode = IEEE_B; - priv->channel = band_b_active_channel[0]; + priv->channel = geo->bg[0].channel; } - } + } else + network->mode = priv->ieee->mode; network->channel = priv->channel; priv->config |= CFG_ADHOC_PERSIST; @@ -5239,7 +5425,34 @@ static void ipw_adhoc_create(struct ipw_priv *priv, network->rsn_ie_len = 0; } -static void ipw_send_wep_keys(struct ipw_priv *priv) +static void ipw_send_tgi_tx_key(struct ipw_priv *priv, int type, int index) +{ + struct ipw_tgi_tx_key *key; + struct host_cmd cmd = { + .cmd = IPW_CMD_TGI_TX_KEY, + .len = sizeof(*key) + }; + + if (!(priv->ieee->sec.flags & (1 << index))) + return; + + key = (struct ipw_tgi_tx_key *)&cmd.param; + key->key_id = index; + memcpy(key->key, priv->ieee->sec.keys[index], SCM_TEMPORAL_KEY_LENGTH); + key->security_type = type; + key->station_index = 0; /* always 0 for BSS */ + key->flags = 0; + /* 0 for new key; previous value of counter (after fatal error) */ + key->tx_counter[0] = 0; + key->tx_counter[1] = 0; + + if (ipw_send_cmd(priv, &cmd)) { + IPW_ERROR("failed to send TGI_TX_KEY command\n"); + return; + } +} + +static void ipw_send_wep_keys(struct ipw_priv *priv, int type) { struct ipw_wep_key *key; int i; @@ -5252,15 +5465,18 @@ static void ipw_send_wep_keys(struct ipw_priv *priv) key->cmd_id = DINO_CMD_WEP_KEY; key->seq_num = 0; + /* Note: AES keys cannot be set for multiple times. + * Only set it at the first time. */ for (i = 0; i < 4; i++) { - key->key_index = i; - if (!(priv->sec.flags & (1 << i))) + key->key_index = i | type; + if (!(priv->ieee->sec.flags & (1 << i))) { key->key_size = 0; - else { - key->key_size = priv->sec.key_sizes[i]; - memcpy(key->key, priv->sec.keys[i], key->key_size); + continue; } + key->key_size = priv->ieee->sec.key_sizes[i]; + memcpy(key->key, priv->ieee->sec.keys[i], key->key_size); + if (ipw_send_cmd(priv, &cmd)) { IPW_ERROR("failed to send WEP_KEY command\n"); return; @@ -5268,6 +5484,52 @@ static void ipw_send_wep_keys(struct ipw_priv *priv) } } +static void ipw_set_hwcrypto_keys(struct ipw_priv *priv) +{ + switch (priv->ieee->sec.level) { + case SEC_LEVEL_3: + if (priv->ieee->sec.flags & SEC_ACTIVE_KEY) + ipw_send_tgi_tx_key(priv, + DCT_FLAG_EXT_SECURITY_CCM, + priv->ieee->sec.active_key); + ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_CCM); + + priv->sys_config.disable_unicast_decryption = 0; + priv->sys_config.disable_multicast_decryption = 0; + priv->ieee->host_decrypt = 0; + if (ipw_send_system_config(priv, &priv->sys_config)) + IPW_ERROR("ipw_send_system_config failed\n"); + + break; + case SEC_LEVEL_2: + if (priv->ieee->sec.flags & SEC_ACTIVE_KEY) + ipw_send_tgi_tx_key(priv, + DCT_FLAG_EXT_SECURITY_TKIP, + priv->ieee->sec.active_key); + + priv->sys_config.disable_unicast_decryption = 1; + priv->sys_config.disable_multicast_decryption = 1; + priv->ieee->host_decrypt = 1; + if (ipw_send_system_config(priv, &priv->sys_config)) + IPW_ERROR("ipw_send_system_config failed\n"); + + break; + case SEC_LEVEL_1: + ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_WEP); + + priv->sys_config.disable_unicast_decryption = 0; + priv->sys_config.disable_multicast_decryption = 0; + priv->ieee->host_decrypt = 0; + if (ipw_send_system_config(priv, &priv->sys_config)) + IPW_ERROR("ipw_send_system_config failed\n"); + + break; + case SEC_LEVEL_0: + default: + break; + } +} + static void ipw_adhoc_check(void *data) { struct ipw_priv *priv = data; @@ -5321,8 +5583,7 @@ static void ipw_debug_config(struct ipw_priv *priv) #define ipw_debug_config(x) do {} while (0) #endif -static inline void ipw_set_fixed_rate(struct ipw_priv *priv, - struct ieee80211_network *network) +static inline void ipw_set_fixed_rate(struct ipw_priv *priv, int mode) { /* TODO: Verify that this works... */ struct ipw_fixed_rate fr = { @@ -5350,7 +5611,7 @@ static inline void ipw_set_fixed_rate(struct ipw_priv *priv, default: /* 2.4Ghz or Mixed */ /* IEEE_B */ - if (network->mode == IEEE_B) { + if (mode == IEEE_B) { if (fr.tx_rates & ~IEEE80211_CCK_RATES_MASK) { /* Invalid fixed rate mask */ IPW_DEBUG_WX @@ -5412,78 +5673,98 @@ static int ipw_request_scan(struct ipw_priv *priv) { struct ipw_scan_request_ext scan; int channel_index = 0; - int i, err, scan_type; + int i, err = 0, scan_type; + const struct ieee80211_geo *geo; +#ifdef CONFIG_IPW2200_MONITOR + u8 channel; +#endif - if (priv->status & STATUS_EXIT_PENDING) { - IPW_DEBUG_SCAN("Aborting scan due to device shutdown\n"); - priv->status |= STATUS_SCAN_PENDING; - return 0; - } + down(&priv->sem); + + geo = ieee80211_get_geo(priv->ieee); if (priv->status & STATUS_SCANNING) { IPW_DEBUG_HC("Concurrent scan requested. Ignoring.\n"); -// IPW_DEBUG_HC("Concurrent scan requested. Aborting first.\n"); priv->status |= STATUS_SCAN_PENDING; -// ipw_abort_scan(priv); - return 0; + goto done; } if (priv->status & STATUS_SCAN_ABORTING) { IPW_DEBUG_HC("Scan request while abort pending. Queuing.\n"); priv->status |= STATUS_SCAN_PENDING; - return 0; + goto done; } if (priv->status & STATUS_RF_KILL_MASK) { IPW_DEBUG_HC("Aborting scan due to RF Kill activation\n"); priv->status |= STATUS_SCAN_PENDING; - return 0; + goto done; } memset(&scan, 0, sizeof(scan)); - scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = cpu_to_le16(20); + if (priv->config & CFG_SPEED_SCAN) + scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = + cpu_to_le16(30); + else + scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = + cpu_to_le16(20); + scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] = cpu_to_le16(20); scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(20); scan.full_scan_index = cpu_to_le32(ieee80211_get_scans(priv->ieee)); -#ifdef CONFIG_IPW_MONITOR +#ifdef CONFIG_IPW2200_MONITOR if (priv->ieee->iw_mode == IW_MODE_MONITOR) { - u8 band = 0, channel = priv->channel; + u8 band = 0; - if (is_valid_channel(IEEE_A, channel)) + switch (ieee80211_is_valid_channel(priv->ieee, priv->channel)) { + case IEEE80211_52GHZ_BAND: band = (u8) (IPW_A_MODE << 6) | 1; + channel = priv->channel; + break; - if (is_valid_channel(IEEE_B | IEEE_G, channel)) + case IEEE80211_24GHZ_BAND: band = (u8) (IPW_B_MODE << 6) | 1; + channel = priv->channel; + break; - if (band == 0) { + default: band = (u8) (IPW_B_MODE << 6) | 1; channel = 9; + break; } - scan.channels_list[channel_index++] = band; - scan.channels_list[channel_index] = channel; - ipw_set_scan_type(&scan, channel_index, - IPW_SCAN_PASSIVE_FULL_DWELL_SCAN); + scan.channels_list[0] = band; + scan.channels_list[1] = channel; + ipw_set_scan_type(&scan, 1, IPW_SCAN_PASSIVE_FULL_DWELL_SCAN); + /* NOTE: The card will sit on this channel for this time + * period. Scan aborts are timing sensitive and frequently + * result in firmware restarts. As such, it is best to + * set a small dwell_time here and just keep re-issuing + * scans. Otherwise fast channel hopping will not actually + * hop channels. + * + * TODO: Move SPEED SCAN support to all modes and bands */ scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(2000); } else { -#endif /* CONFIG_IPW_MONITOR */ - /* If we are roaming, then make this a directed scan for the current - * network. Otherwise, ensure that every other scan is a fast - * channel hop scan */ - if ((priv->status & STATUS_ROAMING) || (!(priv->status & STATUS_ASSOCIATED) && (priv->config & CFG_STATIC_ESSID) && (le32_to_cpu(scan.full_scan_index) % 2))) { /* || ( - (priv->status & STATUS_ASSOCIATED) && - (priv->ieee->iw_mode == IW_MODE_ADHOC))) { */ +#endif /* CONFIG_IPW2200_MONITOR */ + /* If we are roaming, then make this a directed scan for the + * current network. Otherwise, ensure that every other scan + * is a fast channel hop scan */ + if ((priv->status & STATUS_ROAMING) + || (!(priv->status & STATUS_ASSOCIATED) + && (priv->config & CFG_STATIC_ESSID) + && (le32_to_cpu(scan.full_scan_index) % 2))) { err = ipw_send_ssid(priv, priv->essid, priv->essid_len); if (err) { - IPW_DEBUG_HC - ("Attempt to send SSID command failed.\n"); - return err; + IPW_DEBUG_HC("Attempt to send SSID command " + "failed.\n"); + goto done; } scan_type = IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN; @@ -5491,17 +5772,16 @@ static int ipw_request_scan(struct ipw_priv *priv) scan_type = IPW_SCAN_ACTIVE_BROADCAST_SCAN; } + /* Add channels to the scan list */ if (priv->ieee->freq_band & IEEE80211_52GHZ_BAND) { int start = channel_index; - for (i = 0; i < MAX_A_CHANNELS; i++) { - if (band_a_active_channel[i] == 0) - break; + for (i = 0; i < geo->a_channels; i++) { if ((priv->status & STATUS_ASSOCIATED) && - band_a_active_channel[i] == priv->channel) + geo->a[i].channel == priv->channel) continue; channel_index++; scan.channels_list[channel_index] = - band_a_active_channel[i]; + geo->a[i].channel; ipw_set_scan_type(&scan, channel_index, scan_type); } @@ -5516,17 +5796,55 @@ static int ipw_request_scan(struct ipw_priv *priv) if (priv->ieee->freq_band & IEEE80211_24GHZ_BAND) { int start = channel_index; - for (i = 0; i < MAX_B_CHANNELS; i++) { - if (band_b_active_channel[i] == 0) - break; - if ((priv->status & STATUS_ASSOCIATED) && - band_b_active_channel[i] == priv->channel) - continue; - channel_index++; - scan.channels_list[channel_index] = - band_b_active_channel[i]; - ipw_set_scan_type(&scan, channel_index, - scan_type); + if (priv->config & CFG_SPEED_SCAN) { + u8 channels[IEEE80211_24GHZ_CHANNELS] = { + /* nop out the list */ + [0] = 0 + }; + + u8 channel; + while (channel_index < IPW_SCAN_CHANNELS) { + channel = + priv->speed_scan[priv-> + speed_scan_pos]; + if (channel == 0) { + priv->speed_scan_pos = 0; + channel = priv->speed_scan[0]; + } + if ((priv->status & STATUS_ASSOCIATED) + && channel == priv->channel) { + priv->speed_scan_pos++; + continue; + } + + /* If this channel has already been + * added in scan, break from loop + * and this will be the first channel + * in the next scan. + */ + if (channels[channel - 1] != 0) + break; + + channels[channel - 1] = 1; + priv->speed_scan_pos++; + channel_index++; + scan.channels_list[channel_index] = + channel; + ipw_set_scan_type(&scan, channel_index, + scan_type); + } + } else { + for (i = 0; i < geo->bg_channels; i++) { + if ((priv->status & STATUS_ASSOCIATED) + && geo->bg[i].channel == + priv->channel) + continue; + channel_index++; + scan.channels_list[channel_index] = + geo->bg[i].channel; + ipw_set_scan_type(&scan, channel_index, + scan_type); + } } if (start != channel_index) { @@ -5535,28 +5853,22 @@ static int ipw_request_scan(struct ipw_priv *priv) start); } } -#ifdef CONFIG_IPW_MONITOR +#ifdef CONFIG_IPW2200_MONITOR } #endif err = ipw_send_scan_request_ext(priv, &scan); if (err) { IPW_DEBUG_HC("Sending scan command failed: %08X\n", err); - return -EIO; + goto done; } priv->status |= STATUS_SCANNING; priv->status &= ~STATUS_SCAN_PENDING; - return 0; -} - -static void ipw_bg_request_scan(void *data) -{ - struct ipw_priv *priv = data; - down(&priv->sem); - ipw_request_scan(data); + done: up(&priv->sem); + return err; } static void ipw_bg_abort_scan(void *data) @@ -5608,7 +5920,8 @@ struct ipw_param { } wpa_param; struct { u32 len; - u8 *data; + u8 reserved[32]; + u8 data[0]; } wpa_ie; struct { int command; @@ -5631,29 +5944,9 @@ struct ipw_param { static int ipw_wpa_enable(struct ipw_priv *priv, int value) { - struct ieee80211_device *ieee = priv->ieee; - struct ieee80211_security sec = { - .flags = SEC_LEVEL | SEC_ENABLED, - }; - int ret = 0; - - ieee->wpa_enabled = value; - - if (value) { - sec.level = SEC_LEVEL_3; - sec.enabled = 1; - } else { - sec.level = SEC_LEVEL_0; - sec.enabled = 0; - ieee->wpa_ie_len = 0; - } - - if (ieee->set_security) - ieee->set_security(ieee->dev, &sec); - else - ret = -EOPNOTSUPP; - - return ret; + /* This is called when wpa_supplicant loads and closes the driver + * interface. */ + return 0; } #define AUTH_ALG_OPEN_SYSTEM 0x1 @@ -5714,9 +6007,37 @@ static int ipw_wpa_set_param(struct net_device *dev, u8 name, u32 value) break; - case IPW_PARAM_DROP_UNENCRYPTED: - priv->ieee->drop_unencrypted = value; - break; + case IPW_PARAM_DROP_UNENCRYPTED:{ + /* HACK: + * + * wpa_supplicant calls set_wpa_enabled when the driver + * is loaded and unloaded, regardless of if WPA is being + * used. No other calls are made which can be used to + * determine if encryption will be used or not prior to + * association being expected. If encryption is not being + * used, drop_unencrypted is set to false, else true -- we + * can use this to determine if the CAP_PRIVACY_ON bit should + * be set. + */ + struct ieee80211_security sec = { + .flags = SEC_ENABLED, + .enabled = value, + }; + priv->ieee->drop_unencrypted = value; + /* We only change SEC_LEVEL for open mode. Others + * are set by ipw_wpa_set_encryption. + */ + if (!value) { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_0; + } else { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_1; + } + if (priv->ieee->set_security) + priv->ieee->set_security(priv->ieee->dev, &sec); + break; + } case IPW_PARAM_PRIVACY_INVOKED: priv->ieee->privacy_invoked = value; @@ -5793,9 +6114,6 @@ static int ipw_wpa_set_wpa_ie(struct net_device *dev, struct ieee80211_device *ieee = priv->ieee; u8 *buf; - if (!ieee->wpa_enabled) - return -EOPNOTSUPP; - if (param->u.wpa_ie.len > MAX_WPA_IE_LEN || (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL)) return -EINVAL; @@ -5857,6 +6175,7 @@ static int ipw_wpa_set_encryption(struct net_device *dev, if (strcmp(param->u.crypt.alg, "none") == 0) { if (crypt) { sec.enabled = 0; + sec.encrypt = 0; sec.level = SEC_LEVEL_0; sec.flags |= SEC_ENABLED | SEC_LEVEL; ieee80211_crypt_delayed_deinit(ieee, crypt); @@ -5864,8 +6183,14 @@ static int ipw_wpa_set_encryption(struct net_device *dev, goto done; } sec.enabled = 1; + sec.encrypt = 1; sec.flags |= SEC_ENABLED; + /* IPW HW cannot build TKIP MIC, host decryption still needed. */ + if (!(ieee->host_encrypt || ieee->host_decrypt) && + strcmp(param->u.crypt.alg, "TKIP")) + goto skip_host_crypt; + ops = ieee80211_get_crypto_ops(param->u.crypt.alg); if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) { request_module("ieee80211_crypt_wep"); @@ -5922,25 +6247,27 @@ static int ipw_wpa_set_encryption(struct net_device *dev, goto done; } + skip_host_crypt: if (param->u.crypt.set_tx) { ieee->tx_keyidx = param->u.crypt.idx; sec.active_key = param->u.crypt.idx; sec.flags |= SEC_ACTIVE_KEY; - } + } else + sec.flags &= ~SEC_ACTIVE_KEY; - if (ops->name != NULL) { - if (strcmp(ops->name, "WEP") == 0) { - memcpy(sec.keys[param->u.crypt.idx], - param->u.crypt.key, param->u.crypt.key_len); - sec.key_sizes[param->u.crypt.idx] = - param->u.crypt.key_len; - sec.flags |= (1 << param->u.crypt.idx); + if (param->u.crypt.alg != NULL) { + memcpy(sec.keys[param->u.crypt.idx], + param->u.crypt.key, param->u.crypt.key_len); + sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len; + sec.flags |= (1 << param->u.crypt.idx); + + if (strcmp(param->u.crypt.alg, "WEP") == 0) { sec.flags |= SEC_LEVEL; sec.level = SEC_LEVEL_1; - } else if (strcmp(ops->name, "TKIP") == 0) { + } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) { sec.flags |= SEC_LEVEL; sec.level = SEC_LEVEL_2; - } else if (strcmp(ops->name, "CCMP") == 0) { + } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) { sec.flags |= SEC_LEVEL; sec.level = SEC_LEVEL_3; } @@ -6017,38 +6344,552 @@ static int ipw_wpa_supplicant(struct net_device *dev, struct iw_point *p) return ret; } -static int ipw_associate_network(struct ipw_priv *priv, - struct ieee80211_network *network, - struct ipw_supported_rates *rates, int roaming) +#ifdef CONFIG_IPW_QOS + +/* QoS */ +/* +* get the modulation type of the current network or +* the card current mode +*/ +u8 ipw_qos_current_mode(struct ipw_priv * priv) { - int err; + u8 mode = 0; - if (priv->config & CFG_FIXED_RATE) - ipw_set_fixed_rate(priv, network); + if (priv->status & STATUS_ASSOCIATED) { + unsigned long flags; - if (!(priv->config & CFG_STATIC_ESSID)) { - priv->essid_len = min(network->ssid_len, - (u8) IW_ESSID_MAX_SIZE); - memcpy(priv->essid, network->ssid, priv->essid_len); + spin_lock_irqsave(&priv->ieee->lock, flags); + mode = priv->assoc_network->mode; + spin_unlock_irqrestore(&priv->ieee->lock, flags); + } else { + mode = priv->ieee->mode; } + IPW_DEBUG_QOS("QoS network/card mode %d \n", mode); + return mode; +} - network->last_associate = jiffies; - - memset(&priv->assoc_request, 0, sizeof(priv->assoc_request)); - priv->assoc_request.channel = network->channel; - if ((priv->capability & CAP_PRIVACY_ON) && - (priv->capability & CAP_SHARED_KEY)) { - priv->assoc_request.auth_type = AUTH_SHARED_KEY; - priv->assoc_request.auth_key = priv->sec.active_key; +/* +* Handle management frame beacon and probe response +*/ +static int ipw_qos_handle_probe_reponse(struct ipw_priv *priv, + int active_network, + struct ieee80211_network *network) +{ + u32 size = sizeof(struct ieee80211_qos_parameters); + + if ((network->capability & WLAN_CAPABILITY_IBSS)) + network->qos_data.active = network->qos_data.supported; + + if (network->flags & NETWORK_HAS_QOS_MASK) { + if (active_network + && (network->flags & NETWORK_HAS_QOS_PARAMETERS)) + network->qos_data.active = network->qos_data.supported; + + if ((network->qos_data.active == 1) && (active_network == 1) && + (network->flags & NETWORK_HAS_QOS_PARAMETERS) && + (network->qos_data.old_param_count != + network->qos_data.param_count)) { + network->qos_data.old_param_count = + network->qos_data.param_count; + schedule_work(&priv->qos_activate); + IPW_DEBUG_QOS + ("QoS parameters change call qos_activate\n"); + } } else { - priv->assoc_request.auth_type = AUTH_OPEN; - priv->assoc_request.auth_key = 0; + if ((priv->ieee->mode == IEEE_B) || (network->mode == IEEE_B)) { + memcpy(&(network->qos_data.parameters), + &def_parameters_CCK, size); + } else { + memcpy(&(network->qos_data.parameters), + &def_parameters_OFDM, size); + } + if ((network->qos_data.active == 1) && (active_network == 1)) { + IPW_DEBUG_QOS("QoS was disabled call qos_activate \n"); + schedule_work(&priv->qos_activate); + } + + network->qos_data.active = 0; + network->qos_data.supported = 0; } + if ((priv->status & STATUS_ASSOCIATED) + && (priv->ieee->iw_mode == IW_MODE_ADHOC) + && (active_network == 0)) { + + if (memcmp(network->bssid, priv->bssid, ETH_ALEN)) { + if ((network->capability & WLAN_CAPABILITY_IBSS) + && !(network->flags & NETWORK_EMPTY_ESSID)) { + if ((network->ssid_len == + priv->assoc_network->ssid_len) + && !memcmp(network->ssid, + priv->assoc_network->ssid, + network->ssid_len)) { + queue_work(priv->workqueue, + &priv->merge_networks); + } - if (priv->capability & CAP_PRIVACY_ON) - ipw_send_wep_keys(priv); + } + } + } - if (priv->ieee->wpa_ie_len) { + return 0; +} + +/* +* This function set up the firmware to support QoS. It sends +* IPW_CMD_QOS_PARAMETERS and IPW_CMD_WME_INFO +*/ +static int ipw_qos_activate(struct ipw_priv *priv, + struct ieee80211_qos_data *qos_network_data) +{ + int err; + struct ieee80211_qos_parameters qos_parameters[QOS_QOS_SETS]; + struct ieee80211_qos_parameters *active_one = NULL; + u32 size = sizeof(struct ieee80211_qos_parameters); + u32 burst_duration; + int i; + u8 type; + + type = ipw_qos_current_mode(priv); + + active_one = &(qos_parameters[QOS_PARAM_SET_DEF_CCK]); + memcpy(active_one, priv->qos_data.def_qos_parm_CCK, size); + active_one = &(qos_parameters[QOS_PARAM_SET_DEF_OFDM]); + memcpy(active_one, priv->qos_data.def_qos_parm_OFDM, size); + + if (qos_network_data == NULL) { + if (type == IEEE_B) { + IPW_DEBUG_QOS("QoS activate network mode %d\n", type); + active_one = &def_parameters_CCK; + } else + active_one = &def_parameters_OFDM; + + memcpy(&(qos_parameters[QOS_PARAM_SET_ACTIVE]), active_one, + size); + burst_duration = ipw_qos_get_burst_duration(priv); + for (i = 0; i < QOS_QUEUE_NUM; i++) + qos_parameters[QOS_PARAM_SET_ACTIVE]. + tx_op_limit[i] = (u16) burst_duration; + } else if ((priv->ieee->iw_mode == IW_MODE_ADHOC)) { + if (type == IEEE_B) { + IPW_DEBUG_QOS("QoS activate IBSS nework mode %d\n", + type); + if (priv->qos_data.qos_enable == 0) + active_one = &def_parameters_CCK; + else + active_one = priv->qos_data.def_qos_parm_CCK; + } else { + if (priv->qos_data.qos_enable == 0) + active_one = &def_parameters_OFDM; + else + active_one = priv->qos_data.def_qos_parm_OFDM; + } + memcpy(&(qos_parameters[QOS_PARAM_SET_ACTIVE]), active_one, + size); + } else { + unsigned long flags; + int active; + + spin_lock_irqsave(&priv->ieee->lock, flags); + active_one = &(qos_network_data->parameters); + qos_network_data->old_param_count = + qos_network_data->param_count; + memcpy(&(qos_parameters[QOS_PARAM_SET_ACTIVE]), active_one, + size); + active = qos_network_data->supported; + spin_unlock_irqrestore(&priv->ieee->lock, flags); + + if (active == 0) { + burst_duration = ipw_qos_get_burst_duration(priv); + for (i = 0; i < QOS_QUEUE_NUM; i++) + qos_parameters[QOS_PARAM_SET_ACTIVE]. + tx_op_limit[i] = (u16) burst_duration; + } + } + + IPW_DEBUG_QOS("QoS sending IPW_CMD_QOS_PARAMETERS\n"); + err = + ipw_send_qos_params_command(priv, + (struct ieee80211_qos_parameters *) + &(qos_parameters[0])); + if (err) + IPW_DEBUG_QOS("QoS IPW_CMD_QOS_PARAMETERS failed\n"); + + return err; +} + +/* +* send IPW_CMD_WME_INFO to the firmware +*/ +static int ipw_qos_set_info_element(struct ipw_priv *priv) +{ + int ret = 0; + struct ieee80211_qos_information_element qos_info; + + if (priv == NULL) + return -1; + + qos_info.elementID = QOS_ELEMENT_ID; + qos_info.length = sizeof(struct ieee80211_qos_information_element) - 2; + + qos_info.version = QOS_VERSION_1; + qos_info.ac_info = 0; + + memcpy(qos_info.qui, qos_oui, QOS_OUI_LEN); + qos_info.qui_type = QOS_OUI_TYPE; + qos_info.qui_subtype = QOS_OUI_INFO_SUB_TYPE; + + ret = ipw_send_qos_info_command(priv, &qos_info); + if (ret != 0) { + IPW_DEBUG_QOS("QoS error calling ipw_send_qos_info_command\n"); + } + return ret; +} + +/* +* Set the QoS parameter with the association request structure +*/ +static int ipw_qos_association(struct ipw_priv *priv, + struct ieee80211_network *network) +{ + int err = 0; + struct ieee80211_qos_data *qos_data = NULL; + struct ieee80211_qos_data ibss_data = { + .supported = 1, + .active = 1, + }; + + switch (priv->ieee->iw_mode) { + case IW_MODE_ADHOC: + if (!(network->capability & WLAN_CAPABILITY_IBSS)) + BUG(); + + qos_data = &ibss_data; + break; + + case IW_MODE_INFRA: + qos_data = &network->qos_data; + break; + + default: + BUG(); + break; + } + + err = ipw_qos_activate(priv, qos_data); + if (err) { + priv->assoc_request.policy_support &= ~HC_QOS_SUPPORT_ASSOC; + return err; + } + + if (priv->qos_data.qos_enable && qos_data->supported) { + IPW_DEBUG_QOS("QoS will be enabled for this association\n"); + priv->assoc_request.policy_support |= HC_QOS_SUPPORT_ASSOC; + return ipw_qos_set_info_element(priv); + } + + return 0; +} + +/* +* handling the beaconing responces. if we get different QoS setting +* of the network from the the associated setting adjust the QoS +* setting +*/ +static int ipw_qos_association_resp(struct ipw_priv *priv, + struct ieee80211_network *network) +{ + int ret = 0; + unsigned long flags; + u32 size = sizeof(struct ieee80211_qos_parameters); + int set_qos_param = 0; + + if ((priv == NULL) || (network == NULL) + || (priv->assoc_network == NULL)) + + return ret; + + if (!(priv->status & STATUS_ASSOCIATED)) + return ret; + + if ((priv->ieee->iw_mode != IW_MODE_INFRA)) { + return ret; + } + + spin_lock_irqsave(&priv->ieee->lock, flags); + if (network->flags & NETWORK_HAS_QOS_PARAMETERS) { + memcpy(&(priv->assoc_network->qos_data), &(network->qos_data), + sizeof(struct ieee80211_qos_data)); + priv->assoc_network->qos_data.active = 1; + if ((network->qos_data.old_param_count != + network->qos_data.param_count)) { + set_qos_param = 1; + network->qos_data.old_param_count = + network->qos_data.param_count; + } + + } else { + if ((network->mode == IEEE_B) || (priv->ieee->mode == IEEE_B)) { + memcpy(&(priv->assoc_network->qos_data.parameters), + &def_parameters_CCK, size); + } else { + memcpy(&(priv->assoc_network->qos_data.parameters), + &def_parameters_OFDM, size); + } + priv->assoc_network->qos_data.active = 0; + priv->assoc_network->qos_data.supported = 0; + set_qos_param = 1; + } + + spin_unlock_irqrestore(&priv->ieee->lock, flags); + + if (set_qos_param == 1) + schedule_work(&priv->qos_activate); + + return ret; +} + +static u32 ipw_qos_get_burst_duration(struct ipw_priv *priv) +{ + u32 ret = 0; + + if ((priv == NULL)) + return 0; + + if (!(priv->ieee->modulation & IEEE80211_OFDM_MODULATION)) { + ret = priv->qos_data.burst_duration_CCK; + } else { + ret = priv->qos_data.burst_duration_OFDM; + } + return ret; +} + +/* +* Initialize the setting of QoS global +*/ +static void ipw_qos_init(struct ipw_priv *priv, int enable, + int burst_enable, u32 burst_duration_CCK, + u32 burst_duration_OFDM) +{ + priv->qos_data.qos_enable = enable; + + if (priv->qos_data.qos_enable) { + priv->qos_data.def_qos_parm_CCK = &def_qos_parameters_CCK; + priv->qos_data.def_qos_parm_OFDM = &def_qos_parameters_OFDM; + IPW_DEBUG_QOS("QoS is enabled\n"); + } else { + priv->qos_data.def_qos_parm_CCK = &def_parameters_CCK; + priv->qos_data.def_qos_parm_OFDM = &def_parameters_OFDM; + IPW_DEBUG_QOS("QoS is not enabled\n"); + } + + priv->qos_data.burst_enable = burst_enable; + + if (burst_enable) { + priv->qos_data.burst_duration_CCK = burst_duration_CCK; + priv->qos_data.burst_duration_OFDM = burst_duration_OFDM; + } else { + priv->qos_data.burst_duration_CCK = 0; + priv->qos_data.burst_duration_OFDM = 0; + } +} + +/* +* map the packet priority to the right TX Queue +*/ +static int ipw_get_tx_queue_number(struct ipw_priv *priv, u16 priority) +{ + if (priority > 7 || !priv->qos_data.qos_enable) + priority = 0; + + return from_priority_to_tx_queue[priority] - 1; +} + +/* +* add QoS parameter to the TX command +*/ +static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv, + u16 priority, + struct tfd_data *tfd, u8 unicast) +{ + int ret = 0; + int tx_queue_id = 0; + struct ieee80211_qos_data *qos_data = NULL; + int active, supported; + unsigned long flags; + + if (!(priv->status & STATUS_ASSOCIATED)) + return 0; + + qos_data = &priv->assoc_network->qos_data; + + spin_lock_irqsave(&priv->ieee->lock, flags); + + if (priv->ieee->iw_mode == IW_MODE_ADHOC) { + if (unicast == 0) + qos_data->active = 0; + else + qos_data->active = qos_data->supported; + } + + active = qos_data->active; + supported = qos_data->supported; + + spin_unlock_irqrestore(&priv->ieee->lock, flags); + + IPW_DEBUG_QOS + ("QoS %d network is QoS active %d supported %d unicast %d\n", + priv->qos_data.qos_enable, active, supported, unicast); + if (active && priv->qos_data.qos_enable) { + ret = from_priority_to_tx_queue[priority]; + tx_queue_id = ret - 1; + IPW_DEBUG_QOS("QoS packet priority is %d \n", priority); + if (priority <= 7) { + tfd->tx_flags_ext |= DCT_FLAG_EXT_QOS_ENABLED; + tfd->tfd.tfd_26.mchdr.qos_ctrl = priority; + tfd->tfd.tfd_26.mchdr.frame_ctl |= + IEEE80211_STYPE_QOS_DATA; + + if (priv->qos_data.qos_no_ack_mask & + (1UL << tx_queue_id)) { + tfd->tx_flags &= ~DCT_FLAG_ACK_REQD; + tfd->tfd.tfd_26.mchdr.qos_ctrl |= + CTRL_QOS_NO_ACK; + } + } + } + + return ret; +} + +/* +* background support to run QoS activate functionality +*/ +static void ipw_bg_qos_activate(void *data) +{ + struct ipw_priv *priv = data; + + if (priv == NULL) + return; + + down(&priv->sem); + + if (priv->status & STATUS_ASSOCIATED) + ipw_qos_activate(priv, &(priv->assoc_network->qos_data)); + + up(&priv->sem); +} + +/* +* Handler for probe responce and beacon frame +*/ +static int ipw_handle_management_frame(struct net_device *dev, + struct ieee80211_network *network, + u16 type) +{ + struct ipw_priv *priv = ieee80211_priv(dev); + int active_network; + + if (priv->status & STATUS_ASSOCIATED && network == priv->assoc_network) + active_network = 1; + else + active_network = 0; + + switch (type) { + case IEEE80211_STYPE_PROBE_RESP: + case IEEE80211_STYPE_BEACON: + ipw_qos_handle_probe_reponse(priv, active_network, network); + break; + case IEEE80211_STYPE_ASSOC_RESP: + ipw_qos_association_resp(priv, network); + break; + default: + break; + } + + return 0; +} + +static int ipw_send_qos_params_command(struct ipw_priv *priv, struct ieee80211_qos_parameters + *qos_param) +{ + struct host_cmd cmd = { + .cmd = IPW_CMD_QOS_PARAMETERS, + .len = (sizeof(struct ieee80211_qos_parameters) * 3) + }; + + if (!priv || !qos_param) { + IPW_ERROR("Invalid args\n"); + return -1; + } + + memcpy(&cmd.param, qos_param, + (sizeof(struct ieee80211_qos_parameters) * 3)); + if (ipw_send_cmd(priv, &cmd)) { + IPW_ERROR("failed to send IPW_CMD_QOS_PARAMETERS command\n"); + return -1; + } + + return 0; +} + +static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos_information_element + *qos_param) +{ + struct host_cmd cmd = { + .cmd = IPW_CMD_WME_INFO, + .len = sizeof(*qos_param) + }; + + if (!priv || !qos_param) { + IPW_ERROR("Invalid args\n"); + return -1; + } + + memcpy(&cmd.param, qos_param, sizeof(*qos_param)); + if (ipw_send_cmd(priv, &cmd)) { + IPW_ERROR("failed to send CMD_QOS_INFO command\n"); + return -1; + } + + return 0; +} + +#endif /* CONFIG_IPW_QOS */ + +static int ipw_associate_network(struct ipw_priv *priv, + struct ieee80211_network *network, + struct ipw_supported_rates *rates, int roaming) +{ + int err; + + if (priv->config & CFG_FIXED_RATE) + ipw_set_fixed_rate(priv, network->mode); + + if (!(priv->config & CFG_STATIC_ESSID)) { + priv->essid_len = min(network->ssid_len, + (u8) IW_ESSID_MAX_SIZE); + memcpy(priv->essid, network->ssid, priv->essid_len); + } + + network->last_associate = jiffies; + + memset(&priv->assoc_request, 0, sizeof(priv->assoc_request)); + priv->assoc_request.channel = network->channel; + if ((priv->capability & CAP_PRIVACY_ON) && + (priv->capability & CAP_SHARED_KEY)) { + priv->assoc_request.auth_type = AUTH_SHARED_KEY; + priv->assoc_request.auth_key = priv->ieee->sec.active_key; + + if ((priv->capability & CAP_PRIVACY_ON) && + (priv->ieee->sec.level == SEC_LEVEL_1) && + !(priv->ieee->host_encrypt || priv->ieee->host_decrypt)) + ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_WEP); + } else { + priv->assoc_request.auth_type = AUTH_OPEN; + priv->assoc_request.auth_key = 0; + } + + if (priv->ieee->wpa_ie_len) { priv->assoc_request.policy_support = 0x02; /* RSN active */ ipw_set_rsn_capa(priv, priv->ieee->wpa_ie, priv->ieee->wpa_ie_len); @@ -6095,7 +6936,7 @@ static int ipw_associate_network(struct ipw_priv *priv, "(open)") : "", priv->capability & CAP_PRIVACY_ON ? " key=" : "", priv->capability & CAP_PRIVACY_ON ? - '1' + priv->sec.active_key : '.', + '1' + priv->ieee->sec.active_key : '.', priv->capability & CAP_PRIVACY_ON ? '.' : ' '); priv->assoc_request.beacon_interval = network->beacon_interval; @@ -6170,6 +7011,10 @@ static int ipw_associate_network(struct ipw_priv *priv, priv->assoc_network = network; +#ifdef CONFIG_IPW_QOS + ipw_qos_association(priv, network); +#endif + err = ipw_send_associate(priv, &priv->assoc_request); if (err) { IPW_DEBUG_HC("Attempt to send associate command failed.\n"); @@ -6268,6 +7113,11 @@ static int ipw_associate(void *data) struct list_head *element; unsigned long flags; + if (priv->ieee->iw_mode == IW_MODE_MONITOR) { + IPW_DEBUG_ASSOC("Not attempting association (monitor mode)\n"); + return 0; + } + if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { IPW_DEBUG_ASSOC ("Not attempting association (already in progress)\n"); @@ -6315,9 +7165,15 @@ static int ipw_associate(void *data) if (!network) { ipw_debug_config(priv); - if (!(priv->status & STATUS_SCANNING)) - queue_delayed_work(priv->workqueue, &priv->request_scan, - SCAN_INTERVAL); + if (!(priv->status & STATUS_SCANNING)) { + if (!(priv->config & CFG_SPEED_SCAN)) + queue_delayed_work(priv->workqueue, + &priv->request_scan, + SCAN_INTERVAL); + else + queue_work(priv->workqueue, + &priv->request_scan); + } return 0; } @@ -6335,9 +7191,48 @@ static void ipw_bg_associate(void *data) up(&priv->sem); } -static inline void ipw_handle_data_packet(struct ipw_priv *priv, - struct ipw_rx_mem_buffer *rxb, - struct ieee80211_rx_stats *stats) +static void ipw_rebuild_decrypted_skb(struct ipw_priv *priv, + struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr; + u16 fc; + + hdr = (struct ieee80211_hdr *)skb->data; + fc = le16_to_cpu(hdr->frame_ctl); + if (!(fc & IEEE80211_FCTL_PROTECTED)) + return; + + fc &= ~IEEE80211_FCTL_PROTECTED; + hdr->frame_ctl = cpu_to_le16(fc); + switch (priv->ieee->sec.level) { + case SEC_LEVEL_3: + /* Remove CCMP HDR */ + memmove(skb->data + IEEE80211_3ADDR_LEN, + skb->data + IEEE80211_3ADDR_LEN + 8, + skb->len - IEEE80211_3ADDR_LEN - 8); + skb_trim(skb, skb->len - 8); /* MIC */ + break; + case SEC_LEVEL_2: + break; + case SEC_LEVEL_1: + /* Remove IV */ + memmove(skb->data + IEEE80211_3ADDR_LEN, + skb->data + IEEE80211_3ADDR_LEN + 4, + skb->len - IEEE80211_3ADDR_LEN - 4); + skb_trim(skb, skb->len - 4); /* ICV */ + break; + case SEC_LEVEL_0: + break; + default: + printk(KERN_ERR "Unknow security level %d\n", + priv->ieee->sec.level); + break; + } +} + +static void ipw_handle_data_packet(struct ipw_priv *priv, + struct ipw_rx_mem_buffer *rxb, + struct ieee80211_rx_stats *stats) { struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data; @@ -6367,11 +7262,15 @@ static inline void ipw_handle_data_packet(struct ipw_priv *priv, IPW_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len); + /* HW decrypt will not clear the WEP bit, MIC, PN, etc. */ + if (!priv->ieee->host_decrypt) + ipw_rebuild_decrypted_skb(priv, rxb->skb); + if (!ieee80211_rx(priv->ieee, rxb->skb, stats)) priv->ieee->stats.rx_errors++; else { /* ieee80211_rx succeeded, so it now owns the SKB */ rxb->skb = NULL; - ipw_led_activity_on(priv); + __ipw_led_activity_on(priv); } } @@ -6413,6 +7312,53 @@ static inline int is_network_packet(struct ipw_priv *priv, return 1; } +static void ipw_handle_mgmt_packet(struct ipw_priv *priv, + struct ipw_rx_mem_buffer *rxb, + struct ieee80211_rx_stats *stats) +{ + struct sk_buff *skb = rxb->skb; + struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)skb->data; + struct ieee80211_hdr_4addr *header = (struct ieee80211_hdr_4addr *) + (skb->data + IPW_RX_FRAME_SIZE); + + ieee80211_rx_mgt(priv->ieee, header, stats); + + if (priv->ieee->iw_mode == IW_MODE_ADHOC && + ((WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl)) == + IEEE80211_STYPE_PROBE_RESP) || + (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl)) == + IEEE80211_STYPE_BEACON))) { + if (!memcmp(header->addr3, priv->bssid, ETH_ALEN)) + ipw_add_station(priv, header->addr2); + } + + if (priv->config & CFG_NET_STATS) { + IPW_DEBUG_HC("sending stat packet\n"); + + /* Set the size of the skb to the size of the full + * ipw header and 802.11 frame */ + skb_put(skb, le16_to_cpu(pkt->u.frame.length) + + IPW_RX_FRAME_SIZE); + + /* Advance past the ipw packet header to the 802.11 frame */ + skb_pull(skb, IPW_RX_FRAME_SIZE); + + /* Push the ieee80211_rx_stats before the 802.11 frame */ + memcpy(skb_push(skb, sizeof(*stats)), stats, sizeof(*stats)); + + skb->dev = priv->ieee->dev; + + /* Point raw at the ieee80211_stats */ + skb->mac.raw = skb->data; + + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = __constant_htons(ETH_P_80211_STATS); + memset(skb->cb, 0, sizeof(rxb->skb->cb)); + netif_rx(skb); + rxb->skb = NULL; + } +} + /* * Main entry function for recieving a packet with 80211 headers. This * should be called when ever the FW has notified us that there is a new @@ -6426,8 +7372,8 @@ static void ipw_rx(struct ipw_priv *priv) u32 r, w, i; u8 network_packet; - r = ipw_read32(priv, CX2_RX_READ_INDEX); - w = ipw_read32(priv, CX2_RX_WRITE_INDEX); + r = ipw_read32(priv, IPW_RX_READ_INDEX); + w = ipw_read32(priv, IPW_RX_WRITE_INDEX); i = (priv->rxq->processed + 1) % RX_QUEUE_SIZE; while (i != r) { @@ -6441,7 +7387,7 @@ static void ipw_rx(struct ipw_priv *priv) priv->rxq->queue[i] = NULL; pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr, - CX2_RX_BUF_SIZE, + IPW_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); pkt = (struct ipw_rx_packet *)rxb->skb->data; @@ -6482,7 +7428,7 @@ static void ipw_rx(struct ipw_priv *priv) priv->rx_packets++; -#ifdef CONFIG_IPW_MONITOR +#ifdef CONFIG_IPW2200_MONITOR if (priv->ieee->iw_mode == IW_MODE_MONITOR) { ipw_handle_data_packet(priv, rxb, &stats); @@ -6525,56 +7471,17 @@ static void ipw_rx(struct ipw_priv *priv) switch (WLAN_FC_GET_TYPE (le16_to_cpu(header->frame_ctl))) { + case IEEE80211_FTYPE_MGMT: - ieee80211_rx_mgt(priv->ieee, header, - &stats); - if (priv->ieee->iw_mode == IW_MODE_ADHOC - && - ((WLAN_FC_GET_STYPE - (le16_to_cpu(header->frame_ctl)) - == IEEE80211_STYPE_PROBE_RESP) - || - (WLAN_FC_GET_STYPE - (le16_to_cpu(header->frame_ctl)) - == IEEE80211_STYPE_BEACON))) { - if (!memcmp - (header->addr3, priv->bssid, - ETH_ALEN)) - ipw_add_station(priv, - header-> - addr2); - else { - struct - ieee80211_probe_response - *beacon; - beacon = - (struct - ieee80211_probe_response - *)header; - if (le16_to_cpu - (beacon-> - capability) & - WLAN_CAPABILITY_IBSS) - { - queue_work - (priv-> - workqueue, - &priv-> - merge_networks); - } - } - } + ipw_handle_mgmt_packet(priv, rxb, + &stats); break; case IEEE80211_FTYPE_CTL: break; case IEEE80211_FTYPE_DATA: - if (network_packet) - ipw_handle_data_packet(priv, - rxb, - &stats); - else + if (unlikely(!network_packet)) { IPW_DEBUG_DROP("Dropping: " MAC_FMT ", " MAC_FMT ", " @@ -6585,6 +7492,12 @@ static void ipw_rx(struct ipw_priv *priv) addr2), MAC_ARG(header-> addr3)); + break; + } + + ipw_handle_data_packet(priv, rxb, + &stats); + break; } break; @@ -6615,7 +7528,7 @@ static void ipw_rx(struct ipw_priv *priv) } pci_unmap_single(priv->pci_dev, rxb->dma_addr, - CX2_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); + IPW_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); list_add_tail(&rxb->list, &priv->rxq->rx_used); i = (i + 1) % RX_QUEUE_SIZE; @@ -6657,6 +7570,8 @@ static int ipw_wx_get_name(struct net_device *dev, static int ipw_set_channel(struct ipw_priv *priv, u8 channel) { + int i; + if (channel == 0) { IPW_DEBUG_INFO("Setting channel to ANY (0)\n"); priv->config &= ~CFG_STATIC_CHANNEL; @@ -6677,6 +7592,27 @@ static int ipw_set_channel(struct ipw_priv *priv, u8 channel) IPW_DEBUG_INFO("Setting channel to %i\n", (int)channel); priv->channel = channel; +#ifdef CONFIG_IPW2200_MONITOR + if (priv->ieee->iw_mode == IW_MODE_MONITOR) { + if (priv->status & STATUS_SCANNING) { + IPW_DEBUG_SCAN("scan abort triggered due to " + "channel change.\n"); + queue_work(priv->workqueue, &priv->abort_scan); + } + + for (i = 1000; i && (priv->status & STATUS_SCANNING); i--) + udelay(10); + + if (priv->status & STATUS_SCANNING) + IPW_DEBUG_SCAN("Still scanning...\n"); + else + IPW_DEBUG_SCAN("Took %dms to abort current scan\n", + 1000 - i); + + return 0; + } +#endif /* CONFIG_IPW2200_MONITOR */ + /* Network configuration changed -- force [re]association */ IPW_DEBUG_ASSOC("[re]association triggered due to channel change.\n"); if (!ipw_disassociate(priv)) @@ -6692,29 +7628,30 @@ static int ipw_wx_set_freq(struct net_device *dev, struct ipw_priv *priv = ieee80211_priv(dev); struct iw_freq *fwrq = &wrqu->freq; int ret = 0; + u8 channel; + + if (fwrq->m == 0) { + IPW_DEBUG_WX("SET Freq/Channel -> any\n"); + down(&priv->sem); + ret = ipw_set_channel(priv, 0); + up(&priv->sem); + return ret; + } /* if setting by freq convert to channel */ if (fwrq->e == 1) { - if ((fwrq->m >= (int)2.412e8 && fwrq->m <= (int)2.487e8)) { - int f = fwrq->m / 100000; - int c = 0; - - while ((c < REG_MAX_CHANNEL) && - (f != ipw_frequencies[c])) - c++; - - /* hack to fall through */ - fwrq->e = 0; - fwrq->m = c + 1; - } - } + channel = ieee80211_freq_to_channel(priv->ieee, fwrq->m); + if (channel == 0) + return -EINVAL; + } else + channel = fwrq->m; - if (fwrq->e > 0 || fwrq->m > 1000) - return -EOPNOTSUPP; + if (!ieee80211_is_valid_channel(priv->ieee, channel)) + return -EINVAL; IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m); down(&priv->sem); - ret = ipw_set_channel(priv, (u8) fwrq->m); + ret = ipw_set_channel(priv, channel); up(&priv->sem); return ret; } @@ -6749,14 +7686,9 @@ static int ipw_wx_set_mode(struct net_device *dev, int err = 0; IPW_DEBUG_WX("Set MODE: %d\n", wrqu->mode); - down(&priv->sem); - if (wrqu->mode == priv->ieee->iw_mode) { - up(&priv->sem); - return 0; - } switch (wrqu->mode) { -#ifdef CONFIG_IPW_MONITOR +#ifdef CONFIG_IPW2200_MONITOR case IW_MODE_MONITOR: #endif case IW_MODE_ADHOC: @@ -6766,17 +7698,19 @@ static int ipw_wx_set_mode(struct net_device *dev, wrqu->mode = IW_MODE_INFRA; break; default: - up(&priv->sem); return -EINVAL; } + if (wrqu->mode == priv->ieee->iw_mode) + return 0; -#ifdef CONFIG_IPW_MONITOR + down(&priv->sem); +#ifdef CONFIG_IPW2200_MONITOR if (priv->ieee->iw_mode == IW_MODE_MONITOR) priv->net_dev->type = ARPHRD_ETHER; if (wrqu->mode == IW_MODE_MONITOR) priv->net_dev->type = ARPHRD_IEEE80211; -#endif /* CONFIG_IPW_MONITOR */ +#endif /* CONFIG_IPW2200_MONITOR */ #ifdef CONFIG_PM /* Free the existing firmware and reset the fw_loaded @@ -6839,8 +7773,8 @@ static int ipw_wx_get_range(struct net_device *dev, { struct ipw_priv *priv = ieee80211_priv(dev); struct iw_range *range = (struct iw_range *)extra; - u16 val; - int i; + const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); + int i = 0, j; wrqu->data.length = sizeof(*range); memset(range, 0, sizeof(*range)); @@ -6879,19 +7813,28 @@ static int ipw_wx_get_range(struct net_device *dev, range->we_version_compiled = WIRELESS_EXT; range->we_version_source = 16; - range->num_channels = FREQ_COUNT; - - val = 0; - for (i = 0; i < FREQ_COUNT; i++) { - range->freq[val].i = i + 1; - range->freq[val].m = ipw_frequencies[i] * 100000; - range->freq[val].e = 1; - val++; + i = 0; + if (priv->ieee->mode & (IEEE_B | IEEE_G)) { + for (j = 0; j < geo->bg_channels && i < IW_MAX_FREQUENCIES; + i++, j++) { + range->freq[i].i = geo->bg[j].channel; + range->freq[i].m = geo->bg[j].freq * 100000; + range->freq[i].e = 1; + } + } - if (val == IW_MAX_FREQUENCIES) - break; + if (priv->ieee->mode & IEEE_A) { + for (j = 0; j < geo->a_channels && i < IW_MAX_FREQUENCIES; + i++, j++) { + range->freq[i].i = geo->a[j].channel; + range->freq[i].m = geo->a[j].freq * 100000; + range->freq[i].e = 1; + } } - range->num_frequency = val; + + range->num_channels = i; + range->num_frequency = i; + up(&priv->sem); IPW_DEBUG_WX("GET Range\n"); return 0; @@ -7164,9 +8107,10 @@ static int ipw_wx_set_rate(struct net_device *dev, IPW_DEBUG_WX("Setting rate mask to 0x%08X [%s]\n", mask, fixed ? "fixed" : "sub-rates"); down(&priv->sem); - if (mask == IEEE80211_DEFAULT_RATES_MASK) + if (mask == IEEE80211_DEFAULT_RATES_MASK) { priv->config &= ~CFG_FIXED_RATE; - else + ipw_set_fixed_rate(priv, priv->ieee->mode); + } else priv->config |= CFG_FIXED_RATE; if (priv->rates_mask == mask) { @@ -7242,18 +8186,23 @@ static int ipw_wx_set_txpow(struct net_device *dev, struct ipw_priv *priv = ieee80211_priv(dev); struct ipw_tx_power tx_power; int i; + down(&priv->sem); if (ipw_radio_kill_sw(priv, wrqu->power.disabled)) { up(&priv->sem); return -EINPROGRESS; } + if (!wrqu->power.fixed) + wrqu->power.value = IPW_TX_POWER_DEFAULT; + if (wrqu->power.flags != IW_TXPOW_DBM) { up(&priv->sem); return -EINVAL; } - if ((wrqu->power.value > 20) || (wrqu->power.value < -12)) { + if ((wrqu->power.value > IPW_TX_POWER_MAX) || + (wrqu->power.value < -IPW_TX_POWER_MAX) || !wrqu->power.fixed) { up(&priv->sem); return -EINVAL; } @@ -7313,8 +8262,10 @@ static int ipw_wx_set_frag(struct net_device *dev, priv->ieee->fts = DEFAULT_FTS; else { if (wrqu->frag.value < MIN_FRAG_THRESHOLD || - wrqu->frag.value > MAX_FRAG_THRESHOLD) + wrqu->frag.value > MAX_FRAG_THRESHOLD) { + up(&priv->sem); return -EINVAL; + } priv->ieee->fts = wrqu->frag.value & ~0x1; } @@ -7362,12 +8313,9 @@ static int ipw_wx_set_scan(struct net_device *dev, { struct ipw_priv *priv = ieee80211_priv(dev); IPW_DEBUG_WX("Start scan\n"); - down(&priv->sem); - if (ipw_request_scan(priv)) { - up(&priv->sem); - return -EIO; - } - up(&priv->sem); + + queue_work(priv->workqueue, &priv->request_scan); + return 0; } @@ -7621,100 +8569,243 @@ static int ipw_wx_get_wireless_mode(struct net_device *dev, break; } - IPW_DEBUG_WX("PRIV GET MODE: %s\n", extra); + IPW_DEBUG_WX("PRIV GET MODE: %s\n", extra); + + wrqu->data.length = strlen(extra) + 1; + up(&priv->sem); + + return 0; +} + +static int ipw_wx_set_preamble(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ipw_priv *priv = ieee80211_priv(dev); + int mode = *(int *)extra; + down(&priv->sem); + /* Switching from SHORT -> LONG requires a disassociation */ + if (mode == 1) { + if (!(priv->config & CFG_PREAMBLE_LONG)) { + priv->config |= CFG_PREAMBLE_LONG; + + /* Network configuration changed -- force [re]association */ + IPW_DEBUG_ASSOC + ("[re]association triggered due to preamble change.\n"); + if (!ipw_disassociate(priv)) + ipw_associate(priv); + } + goto done; + } + + if (mode == 0) { + priv->config &= ~CFG_PREAMBLE_LONG; + goto done; + } + up(&priv->sem); + return -EINVAL; + + done: + up(&priv->sem); + return 0; +} + +static int ipw_wx_get_preamble(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ipw_priv *priv = ieee80211_priv(dev); + down(&priv->sem); + if (priv->config & CFG_PREAMBLE_LONG) + snprintf(wrqu->name, IFNAMSIZ, "long (1)"); + else + snprintf(wrqu->name, IFNAMSIZ, "auto (0)"); + up(&priv->sem); + return 0; +} + +#ifdef CONFIG_IPW2200_MONITOR +static int ipw_wx_set_monitor(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ipw_priv *priv = ieee80211_priv(dev); + int *parms = (int *)extra; + int enable = (parms[0] > 0); + down(&priv->sem); + IPW_DEBUG_WX("SET MONITOR: %d %d\n", enable, parms[1]); + if (enable) { + if (priv->ieee->iw_mode != IW_MODE_MONITOR) { + priv->net_dev->type = ARPHRD_IEEE80211; + queue_work(priv->workqueue, &priv->adapter_restart); + } + + ipw_set_channel(priv, parms[1]); + } else { + if (priv->ieee->iw_mode != IW_MODE_MONITOR) { + up(&priv->sem); + return 0; + } + priv->net_dev->type = ARPHRD_ETHER; + queue_work(priv->workqueue, &priv->adapter_restart); + } + up(&priv->sem); + return 0; +} + +#endif // CONFIG_IPW2200_MONITOR + +static int ipw_wx_reset(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ipw_priv *priv = ieee80211_priv(dev); + IPW_DEBUG_WX("RESET\n"); + queue_work(priv->workqueue, &priv->adapter_restart); + return 0; +} + +static void ipw_sw_reset(struct ipw_priv *priv, int init) +{ + int band, modulation; + + /* Initialize module parameter values here */ + priv->config = 0; + + /* We default to disabling the LED code as right now it causes + * too many systems to lock up... */ + if (!led) + priv->config |= CFG_NO_LED; + + if (associate) + priv->config |= CFG_ASSOCIATE; + else + IPW_DEBUG_INFO("Auto associate disabled.\n"); + + if (auto_create) + priv->config |= CFG_ADHOC_CREATE; + else + IPW_DEBUG_INFO("Auto adhoc creation disabled.\n"); + + if (disable) { + priv->status |= STATUS_RF_KILL_SW; + IPW_DEBUG_INFO("Radio disabled.\n"); + } + + if (channel != 0) { + priv->config |= CFG_STATIC_CHANNEL; + priv->channel = channel; + IPW_DEBUG_INFO("Bind to static channel %d\n", channel); + /* TODO: Validate that provided channel is in range */ + } +#ifdef CONFIG_IPW_QOS + ipw_qos_init(priv, qos_enable, qos_burst_enable, + burst_duration_CCK, burst_duration_OFDM); +#endif /* CONFIG_IPW_QOS */ + + switch (mode) { + case 1: + priv->ieee->iw_mode = IW_MODE_ADHOC; + priv->net_dev->type = ARPHRD_ETHER; + + break; +#ifdef CONFIG_IPW2200_MONITOR + case 2: + priv->ieee->iw_mode = IW_MODE_MONITOR; + priv->net_dev->type = ARPHRD_IEEE80211; + break; +#endif + default: + case 0: + priv->net_dev->type = ARPHRD_ETHER; + priv->ieee->iw_mode = IW_MODE_INFRA; + break; + } + + if (hwcrypto) { + priv->ieee->host_encrypt = 0; + priv->ieee->host_decrypt = 0; + } + IPW_DEBUG_INFO("Hardware crypto [%s]\n", hwcrypto ? "on" : "off"); + + if ((priv->pci_dev->device == 0x4223) || + (priv->pci_dev->device == 0x4224)) { + if (init) + printk(KERN_INFO DRV_NAME + ": Detected Intel PRO/Wireless 2915ABG Network " + "Connection\n"); + priv->ieee->abg_true = 1; + band = IEEE80211_52GHZ_BAND | IEEE80211_24GHZ_BAND; + modulation = IEEE80211_OFDM_MODULATION | + IEEE80211_CCK_MODULATION; + priv->adapter = IPW_2915ABG; + priv->ieee->mode = IEEE_A | IEEE_G | IEEE_B; + } else { + if (init) + printk(KERN_INFO DRV_NAME + ": Detected Intel PRO/Wireless 2200BG Network " + "Connection\n"); + + priv->ieee->abg_true = 0; + band = IEEE80211_24GHZ_BAND; + modulation = IEEE80211_OFDM_MODULATION | + IEEE80211_CCK_MODULATION; + priv->adapter = IPW_2200BG; + priv->ieee->mode = IEEE_G | IEEE_B; + } + + priv->ieee->freq_band = band; + priv->ieee->modulation = modulation; - wrqu->data.length = strlen(extra) + 1; - up(&priv->sem); + priv->rates_mask = IEEE80211_DEFAULT_RATES_MASK; - return 0; + priv->missed_beacon_threshold = IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT; + priv->roaming_threshold = IPW_MB_ROAMING_THRESHOLD_DEFAULT; + + priv->rts_threshold = DEFAULT_RTS_THRESHOLD; + + /* If power management is turned on, default to AC mode */ + priv->power_mode = IPW_POWER_AC; + priv->tx_power = IPW_TX_POWER_DEFAULT; } -static int ipw_wx_set_preamble(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) +static int ipw_wx_sw_reset(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - int mode = *(int *)extra; - down(&priv->sem); - /* Switching from SHORT -> LONG requires a disassociation */ - if (mode == 1) { - if (!(priv->config & CFG_PREAMBLE_LONG)) { - priv->config |= CFG_PREAMBLE_LONG; + union iwreq_data wrqu_sec = { + .encoding = { + .flags = IW_ENCODE_DISABLED, + }, + }; - /* Network configuration changed -- force [re]association */ - IPW_DEBUG_ASSOC - ("[re]association triggered due to preamble change.\n"); - if (!ipw_disassociate(priv)) - ipw_associate(priv); - } - goto done; - } + IPW_DEBUG_WX("SW_RESET\n"); - if (mode == 0) { - priv->config &= ~CFG_PREAMBLE_LONG; - goto done; - } - up(&priv->sem); - return -EINVAL; + down(&priv->sem); - done: - up(&priv->sem); - return 0; -} + ipw_sw_reset(priv, 0); -static int ipw_wx_get_preamble(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = ieee80211_priv(dev); - down(&priv->sem); - if (priv->config & CFG_PREAMBLE_LONG) - snprintf(wrqu->name, IFNAMSIZ, "long (1)"); - else - snprintf(wrqu->name, IFNAMSIZ, "auto (0)"); - up(&priv->sem); - return 0; -} + /* The SW reset bit might have been toggled on by the 'disable' + * module parameter, so take appropriate action */ + ipw_radio_kill_sw(priv, priv->status & STATUS_RF_KILL_SW); -#ifdef CONFIG_IPW_MONITOR -static int ipw_wx_set_monitor(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = ieee80211_priv(dev); - int *parms = (int *)extra; - int enable = (parms[0] > 0); + up(&priv->sem); + ieee80211_wx_set_encode(priv->ieee, info, &wrqu_sec, NULL); down(&priv->sem); - IPW_DEBUG_WX("SET MONITOR: %d %d\n", enable, parms[1]); - if (enable) { - if (priv->ieee->iw_mode != IW_MODE_MONITOR) { - priv->net_dev->type = ARPHRD_IEEE80211; - queue_work(priv->workqueue, &priv->adapter_restart); - } - ipw_set_channel(priv, parms[1]); - } else { - if (priv->ieee->iw_mode != IW_MODE_MONITOR) { - up(&priv->sem); - return 0; - } - priv->net_dev->type = ARPHRD_ETHER; - queue_work(priv->workqueue, &priv->adapter_restart); + if (!(priv->status & STATUS_RF_KILL_MASK)) { + /* Configuration likely changed -- force [re]association */ + IPW_DEBUG_ASSOC("[re]association triggered due to sw " + "reset.\n"); + if (!ipw_disassociate(priv)) + ipw_associate(priv); } + up(&priv->sem); - return 0; -} -static int ipw_wx_reset(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = ieee80211_priv(dev); - IPW_DEBUG_WX("RESET\n"); - queue_work(priv->workqueue, &priv->adapter_restart); return 0; } -#endif // CONFIG_IPW_MONITOR /* Rebase the WE IOCTLs to zero for the handler array */ #define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT] @@ -7753,14 +8844,19 @@ static iw_handler ipw_wx_handlers[] = { IW_IOCTL(SIOCGIWTHRSPY) = iw_handler_get_thrspy, }; -#define IPW_PRIV_SET_POWER SIOCIWFIRSTPRIV -#define IPW_PRIV_GET_POWER SIOCIWFIRSTPRIV+1 -#define IPW_PRIV_SET_MODE SIOCIWFIRSTPRIV+2 -#define IPW_PRIV_GET_MODE SIOCIWFIRSTPRIV+3 -#define IPW_PRIV_SET_PREAMBLE SIOCIWFIRSTPRIV+4 -#define IPW_PRIV_GET_PREAMBLE SIOCIWFIRSTPRIV+5 -#define IPW_PRIV_SET_MONITOR SIOCIWFIRSTPRIV+6 -#define IPW_PRIV_RESET SIOCIWFIRSTPRIV+7 +enum { + IPW_PRIV_SET_POWER = SIOCIWFIRSTPRIV, + IPW_PRIV_GET_POWER, + IPW_PRIV_SET_MODE, + IPW_PRIV_GET_MODE, + IPW_PRIV_SET_PREAMBLE, + IPW_PRIV_GET_PREAMBLE, + IPW_PRIV_RESET, + IPW_PRIV_SW_RESET, +#ifdef CONFIG_IPW2200_MONITOR + IPW_PRIV_SET_MONITOR, +#endif +}; static struct iw_priv_args ipw_priv_args[] = { { @@ -7787,14 +8883,17 @@ static struct iw_priv_args ipw_priv_args[] = { .cmd = IPW_PRIV_GET_PREAMBLE, .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, .name = "get_preamble"}, -#ifdef CONFIG_IPW_MONITOR - { - IPW_PRIV_SET_MONITOR, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "monitor"}, { IPW_PRIV_RESET, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 0, 0, "reset"}, -#endif /* CONFIG_IPW_MONITOR */ + { + IPW_PRIV_SW_RESET, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 0, 0, "sw_reset"}, +#ifdef CONFIG_IPW2200_MONITOR + { + IPW_PRIV_SET_MONITOR, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "monitor"}, +#endif /* CONFIG_IPW2200_MONITOR */ }; static iw_handler ipw_priv_handler[] = { @@ -7804,9 +8903,10 @@ static iw_handler ipw_priv_handler[] = { ipw_wx_get_wireless_mode, ipw_wx_set_preamble, ipw_wx_get_preamble, -#ifdef CONFIG_IPW_MONITOR - ipw_wx_set_monitor, ipw_wx_reset, + ipw_wx_sw_reset, +#ifdef CONFIG_IPW2200_MONITOR + ipw_wx_set_monitor, #endif }; @@ -7915,13 +9015,19 @@ modify to send one tfd per fragment instead of using chunking. otherwise we need to heavily modify the ieee80211_skb_to_txb. */ -static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb) +static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, + int pri) { struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *) txb->fragments[0]->data; int i = 0; struct tfd_frame *tfd; +#ifdef CONFIG_IPW_QOS + int tx_id = ipw_get_tx_queue_number(priv, pri); + struct clx2_tx_queue *txq = &priv->txq[tx_id]; +#else struct clx2_tx_queue *txq = &priv->txq[0]; +#endif struct clx2_queue *q = &txq->q; u8 id, hdr_len, unicast; u16 remaining_bytes; @@ -7964,15 +9070,11 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb) tfd->u.data.cmd_id = DINO_CMD_TX; tfd->u.data.len = cpu_to_le16(txb->payload_size); remaining_bytes = txb->payload_size; - if (unlikely(!unicast)) - tfd->u.data.tx_flags = DCT_FLAG_NO_WEP; - else - tfd->u.data.tx_flags = DCT_FLAG_NO_WEP | DCT_FLAG_ACK_REQD; if (priv->assoc_request.ieee_mode == IPW_B_MODE) - tfd->u.data.tx_flags_ext = DCT_FLAG_EXT_MODE_CCK; + tfd->u.data.tx_flags_ext |= DCT_FLAG_EXT_MODE_CCK; else - tfd->u.data.tx_flags_ext = DCT_FLAG_EXT_MODE_OFDM; + tfd->u.data.tx_flags_ext |= DCT_FLAG_EXT_MODE_OFDM; if (priv->assoc_request.preamble_length == DCT_FLAG_SHORT_PREAMBLE) tfd->u.data.tx_flags |= DCT_FLAG_SHORT_PREAMBLE; @@ -7982,6 +9084,58 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb) memcpy(&tfd->u.data.tfd.tfd_24.mchdr, hdr, hdr_len); + if (likely(unicast)) + tfd->u.data.tx_flags |= DCT_FLAG_ACK_REQD; + + if (txb->encrypted && !priv->ieee->host_encrypt) { + switch (priv->ieee->sec.level) { + case SEC_LEVEL_3: + tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |= + IEEE80211_FCTL_PROTECTED; + /* XXX: ACK flag must be set for CCMP even if it + * is a multicast/broadcast packet, because CCMP + * group communication encrypted by GTK is + * actually done by the AP. */ + if (!unicast) + tfd->u.data.tx_flags |= DCT_FLAG_ACK_REQD; + + tfd->u.data.tx_flags &= ~DCT_FLAG_NO_WEP; + tfd->u.data.tx_flags_ext |= DCT_FLAG_EXT_SECURITY_CCM; + tfd->u.data.key_index = 0; + tfd->u.data.key_index |= DCT_WEP_INDEX_USE_IMMEDIATE; + break; + case SEC_LEVEL_2: + tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |= + IEEE80211_FCTL_PROTECTED; + tfd->u.data.tx_flags &= ~DCT_FLAG_NO_WEP; + tfd->u.data.tx_flags_ext |= DCT_FLAG_EXT_SECURITY_TKIP; + tfd->u.data.key_index = DCT_WEP_INDEX_USE_IMMEDIATE; + break; + case SEC_LEVEL_1: + tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |= + IEEE80211_FCTL_PROTECTED; + tfd->u.data.key_index = priv->ieee->tx_keyidx; + if (priv->ieee->sec.key_sizes[priv->ieee->tx_keyidx] <= + 40) + tfd->u.data.key_index |= DCT_WEP_KEY_64Bit; + else + tfd->u.data.key_index |= DCT_WEP_KEY_128Bit; + break; + case SEC_LEVEL_0: + break; + default: + printk(KERN_ERR "Unknow security level %d\n", + priv->ieee->sec.level); + break; + } + } else + /* No hardware encryption */ + tfd->u.data.tx_flags |= DCT_FLAG_NO_WEP; + +#ifdef CONFIG_IPW_QOS + ipw_qos_set_tx_queue_command(priv, pri, &(tfd->u.data), unicast); +#endif /* CONFIG_IPW_QOS */ + /* payload */ tfd->u.data.num_chunks = cpu_to_le32(min((u8) (NUM_TFD_CHUNKS - 2), txb->nr_frags)); @@ -8071,16 +9225,14 @@ static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb, goto fail_unlock; } - ipw_tx_skb(priv, txb); + ipw_tx_skb(priv, txb, pri); + __ipw_led_activity_on(priv); spin_unlock_irqrestore(&priv->lock, flags); - ipw_led_activity_on(priv); -// up(&priv->sem); return 0; fail_unlock: spin_unlock_irqrestore(&priv->lock, flags); -// up(&priv->sem); return 1; } @@ -8133,7 +9285,7 @@ static void ipw_ethtool_get_drvinfo(struct net_device *dev, snprintf(info->fw_version, sizeof(info->fw_version), "%s (%s)", vers, date); strcpy(info->bus_info, pci_name(p->pci_dev)); - info->eedump_len = CX2_EEPROM_IMAGE_SIZE; + info->eedump_len = IPW_EEPROM_IMAGE_SIZE; } static u32 ipw_ethtool_get_link(struct net_device *dev) @@ -8144,7 +9296,7 @@ static u32 ipw_ethtool_get_link(struct net_device *dev) static int ipw_ethtool_get_eeprom_len(struct net_device *dev) { - return CX2_EEPROM_IMAGE_SIZE; + return IPW_EEPROM_IMAGE_SIZE; } static int ipw_ethtool_get_eeprom(struct net_device *dev, @@ -8152,7 +9304,7 @@ static int ipw_ethtool_get_eeprom(struct net_device *dev, { struct ipw_priv *p = ieee80211_priv(dev); - if (eeprom->offset + eeprom->len > CX2_EEPROM_IMAGE_SIZE) + if (eeprom->offset + eeprom->len > IPW_EEPROM_IMAGE_SIZE) return -EINVAL; down(&p->sem); memcpy(bytes, &((u8 *) p->eeprom)[eeprom->offset], eeprom->len); @@ -8166,12 +9318,12 @@ static int ipw_ethtool_set_eeprom(struct net_device *dev, struct ipw_priv *p = ieee80211_priv(dev); int i; - if (eeprom->offset + eeprom->len > CX2_EEPROM_IMAGE_SIZE) + if (eeprom->offset + eeprom->len > IPW_EEPROM_IMAGE_SIZE) return -EINVAL; down(&p->sem); memcpy(&((u8 *) p->eeprom)[eeprom->offset], bytes, eeprom->len); for (i = IPW_EEPROM_DATA; - i < IPW_EEPROM_DATA + CX2_EEPROM_IMAGE_SIZE; i++) + i < IPW_EEPROM_DATA + IPW_EEPROM_IMAGE_SIZE; i++) ipw_write8(p, i, p->eeprom[i]); up(&p->sem); return 0; @@ -8197,13 +9349,11 @@ static irqreturn_t ipw_isr(int irq, void *data, struct pt_regs *regs) if (!(priv->status & STATUS_INT_ENABLED)) { /* Shared IRQ */ -// ipw_write32(priv, CX2_INTA_RW, CX2_INTA_MASK_ALL); -// return IRQ_HANDLED; goto none; } - inta = ipw_read32(priv, CX2_INTA_RW); - inta_mask = ipw_read32(priv, CX2_INTA_MASK_R); + inta = ipw_read32(priv, IPW_INTA_RW); + inta_mask = ipw_read32(priv, IPW_INTA_MASK_R); if (inta == 0xFFFFFFFF) { /* Hardware disappeared */ @@ -8211,7 +9361,7 @@ static irqreturn_t ipw_isr(int irq, void *data, struct pt_regs *regs) goto none; } - if (!(inta & (CX2_INTA_MASK_ALL & inta_mask))) { + if (!(inta & (IPW_INTA_MASK_ALL & inta_mask))) { /* Shared interrupt */ goto none; } @@ -8220,8 +9370,8 @@ static irqreturn_t ipw_isr(int irq, void *data, struct pt_regs *regs) ipw_disable_interrupts(priv); /* ack current interrupts */ - inta &= (CX2_INTA_MASK_ALL & inta_mask); - ipw_write32(priv, CX2_INTA_RW, inta); + inta &= (IPW_INTA_MASK_ALL & inta_mask); + ipw_write32(priv, IPW_INTA_RW, inta); /* Cache INTA value for our tasklet */ priv->isr_inta = inta; @@ -8348,7 +9498,7 @@ static int ipw_setup_deferred_work(struct ipw_priv *priv) INIT_WORK(&priv->up, (void (*)(void *))ipw_bg_up, priv); INIT_WORK(&priv->down, (void (*)(void *))ipw_bg_down, priv); INIT_WORK(&priv->request_scan, - (void (*)(void *))ipw_bg_request_scan, priv); + (void (*)(void *))ipw_request_scan, priv); INIT_WORK(&priv->gather_stats, (void (*)(void *))ipw_bg_gather_stats, priv); INIT_WORK(&priv->abort_scan, (void (*)(void *))ipw_bg_abort_scan, priv); @@ -8365,6 +9515,11 @@ static int ipw_setup_deferred_work(struct ipw_priv *priv) INIT_WORK(&priv->merge_networks, (void (*)(void *))ipw_merge_adhoc_network, priv); +#ifdef CONFIG_IPW_QOS + INIT_WORK(&priv->qos_activate, (void (*)(void *))ipw_bg_qos_activate, + priv); +#endif /* CONFIG_IPW_QOS */ + tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) ipw_irq_tasklet, (unsigned long)priv); @@ -8379,31 +9534,33 @@ static void shim__set_security(struct net_device *dev, down(&priv->sem); for (i = 0; i < 4; i++) { if (sec->flags & (1 << i)) { - priv->sec.key_sizes[i] = sec->key_sizes[i]; + priv->ieee->sec.key_sizes[i] = sec->key_sizes[i]; if (sec->key_sizes[i] == 0) - priv->sec.flags &= ~(1 << i); - else - memcpy(priv->sec.keys[i], sec->keys[i], + priv->ieee->sec.flags &= ~(1 << i); + else { + memcpy(priv->ieee->sec.keys[i], sec->keys[i], sec->key_sizes[i]); - priv->sec.flags |= (1 << i); + priv->ieee->sec.flags |= (1 << i); + } priv->status |= STATUS_SECURITY_UPDATED; - } + } else if (sec->level != SEC_LEVEL_1) + priv->ieee->sec.flags &= ~(1 << i); } - if ((sec->flags & SEC_ACTIVE_KEY) && - priv->sec.active_key != sec->active_key) { + if (sec->flags & SEC_ACTIVE_KEY) { if (sec->active_key <= 3) { - priv->sec.active_key = sec->active_key; - priv->sec.flags |= SEC_ACTIVE_KEY; + priv->ieee->sec.active_key = sec->active_key; + priv->ieee->sec.flags |= SEC_ACTIVE_KEY; } else - priv->sec.flags &= ~SEC_ACTIVE_KEY; + priv->ieee->sec.flags &= ~SEC_ACTIVE_KEY; priv->status |= STATUS_SECURITY_UPDATED; - } + } else + priv->ieee->sec.flags &= ~SEC_ACTIVE_KEY; if ((sec->flags & SEC_AUTH_MODE) && - (priv->sec.auth_mode != sec->auth_mode)) { - priv->sec.auth_mode = sec->auth_mode; - priv->sec.flags |= SEC_AUTH_MODE; + (priv->ieee->sec.auth_mode != sec->auth_mode)) { + priv->ieee->sec.auth_mode = sec->auth_mode; + priv->ieee->sec.flags |= SEC_AUTH_MODE; if (sec->auth_mode == WLAN_AUTH_SHARED_KEY) priv->capability |= CAP_SHARED_KEY; else @@ -8411,22 +9568,26 @@ static void shim__set_security(struct net_device *dev, priv->status |= STATUS_SECURITY_UPDATED; } - if (sec->flags & SEC_ENABLED && priv->sec.enabled != sec->enabled) { - priv->sec.flags |= SEC_ENABLED; - priv->sec.enabled = sec->enabled; + if (sec->flags & SEC_ENABLED && priv->ieee->sec.enabled != sec->enabled) { + priv->ieee->sec.flags |= SEC_ENABLED; + priv->ieee->sec.enabled = sec->enabled; priv->status |= STATUS_SECURITY_UPDATED; if (sec->enabled) priv->capability |= CAP_PRIVACY_ON; else priv->capability &= ~CAP_PRIVACY_ON; } + priv->ieee->sec.encrypt = sec->encrypt; - if (sec->flags & SEC_LEVEL && priv->sec.level != sec->level) { - priv->sec.level = sec->level; - priv->sec.flags |= SEC_LEVEL; + if (sec->flags & SEC_LEVEL && priv->ieee->sec.level != sec->level) { + priv->ieee->sec.level = sec->level; + priv->ieee->sec.flags |= SEC_LEVEL; priv->status |= STATUS_SECURITY_UPDATED; } + if (!priv->ieee->host_encrypt) + ipw_set_hwcrypto_keys(priv); + /* To match current functionality of ipw2100 (which works well w/ * various supplicants, we don't force a disassociate if the * privacy capability changes ... */ @@ -8524,6 +9685,10 @@ static int ipw_config(struct ipw_priv *priv) if (ipw_send_rts_threshold(priv, priv->rts_threshold)) goto error; } +#ifdef CONFIG_IPW_QOS + IPW_DEBUG_QOS("QoS: call ipw_qos_activate\n"); + ipw_qos_activate(priv, NULL); +#endif /* CONFIG_IPW_QOS */ if (ipw_set_random_seed(priv)) goto error; @@ -8533,10 +9698,8 @@ static int ipw_config(struct ipw_priv *priv) goto error; /* If configured to try and auto-associate, kick off a scan */ - if ((priv->config & CFG_ASSOCIATE) && ipw_request_scan(priv)) { - IPW_WARNING("error sending scan request\n"); - goto error; - } + if (priv->config & CFG_ASSOCIATE) + queue_work(priv->workqueue, &priv->request_scan); return 0; @@ -8566,7 +9729,15 @@ static int ipw_up(struct ipw_priv *priv) eeprom_parse_mac(priv, priv->mac_addr); memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN); - if (priv->status & STATUS_RF_KILL_MASK) { + if (priv->status & STATUS_RF_KILL_SW) { + IPW_WARNING("Radio disabled by module parameter.\n"); + return 0; + } else if (rf_kill_active(priv)) { + IPW_WARNING("Radio Frequency Kill Switch is On:\n" + "Kill switch must be turned off for " + "wireless networking to work.\n"); + queue_delayed_work(priv->workqueue, &priv->rf_kill, + 2 * HZ); return 0; } @@ -8604,18 +9775,61 @@ static void ipw_bg_up(void *data) up(&priv->sem); } -static void ipw_down(struct ipw_priv *priv) +static void ipw_deinit(struct ipw_priv *priv) { -#if 0 + int i; + + if (priv->status & STATUS_SCANNING) { + IPW_DEBUG_INFO("Aborting scan during shutdown.\n"); + ipw_abort_scan(priv); + } + + if (priv->status & STATUS_ASSOCIATED) { + IPW_DEBUG_INFO("Disassociating during shutdown.\n"); + ipw_disassociate(priv); + } + + ipw_led_shutdown(priv); + + /* Wait up to 1s for status to change to not scanning and not + * associated (disassociation can take a while for a ful 802.11 + * exchange */ + for (i = 1000; i && (priv->status & + (STATUS_DISASSOCIATING | + STATUS_ASSOCIATED | STATUS_SCANNING)); i--) + udelay(10); + + if (priv->status & (STATUS_DISASSOCIATING | + STATUS_ASSOCIATED | STATUS_SCANNING)) + IPW_DEBUG_INFO("Still associated or scanning...\n"); + else + IPW_DEBUG_INFO("Took %dms to de-init\n", 1000 - i); + /* Attempt to disable the card */ ipw_send_card_disable(priv, 0); -#endif + + priv->status &= ~STATUS_INIT; +} + +static void ipw_down(struct ipw_priv *priv) +{ + int exit_pending = priv->status & STATUS_EXIT_PENDING; + + priv->status |= STATUS_EXIT_PENDING; + + if (ipw_is_init(priv)) + ipw_deinit(priv); + + /* Wipe out the EXIT_PENDING status bit if we are not actually + * exiting the module */ + if (!exit_pending) + priv->status &= ~STATUS_EXIT_PENDING; /* tell the device to stop sending interrupts */ ipw_disable_interrupts(priv); /* Clear all bits but the RF Kill */ - priv->status &= STATUS_RF_KILL_MASK; + priv->status &= STATUS_RF_KILL_MASK | STATUS_EXIT_PENDING; netif_carrier_off(priv->net_dev); netif_stop_queue(priv->net_dev); @@ -8653,18 +9867,6 @@ static int ipw_net_init(struct net_device *dev) { struct ipw_priv *priv = ieee80211_priv(dev); down(&priv->sem); - if (priv->status & STATUS_RF_KILL_SW) { - IPW_WARNING("Radio disabled by module parameter.\n"); - up(&priv->sem); - return 0; - } else if (rf_kill_active(priv)) { - IPW_WARNING("Radio Frequency Kill Switch is On:\n" - "Kill switch must be turned off for " - "wireless networking to work.\n"); - queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ); - up(&priv->sem); - return 0; - } if (ipw_up(priv)) { up(&priv->sem); @@ -8723,6 +9925,8 @@ static struct attribute *ipw_sysfs_entries[] = { &dev_attr_rtc.attr, &dev_attr_scan_age.attr, &dev_attr_led.attr, + &dev_attr_speed_scan.attr, + &dev_attr_net_stats.attr, NULL }; @@ -8738,7 +9942,6 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) void __iomem *base; u32 length, val; struct ipw_priv *priv; - int band, modulation; net_dev = alloc_ieee80211(sizeof(struct ipw_priv)); if (net_dev == NULL) { @@ -8803,88 +10006,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_iounmap; } - /* Initialize module parameter values here */ - - /* We default to disabling the LED code as right now it causes - * too many systems to lock up... */ - if (!led) - priv->config |= CFG_NO_LED; - - if (associate) - priv->config |= CFG_ASSOCIATE; - else - IPW_DEBUG_INFO("Auto associate disabled.\n"); - - if (auto_create) - priv->config |= CFG_ADHOC_CREATE; - else - IPW_DEBUG_INFO("Auto adhoc creation disabled.\n"); - - if (disable) { - priv->status |= STATUS_RF_KILL_SW; - IPW_DEBUG_INFO("Radio disabled.\n"); - } - - if (channel != 0) { - priv->config |= CFG_STATIC_CHANNEL; - priv->channel = channel; - IPW_DEBUG_INFO("Bind to static channel %d\n", channel); - IPW_DEBUG_INFO("Bind to static channel %d\n", channel); - /* TODO: Validate that provided channel is in range */ - } - - switch (mode) { - case 1: - priv->ieee->iw_mode = IW_MODE_ADHOC; - break; -#ifdef CONFIG_IPW_MONITOR - case 2: - priv->ieee->iw_mode = IW_MODE_MONITOR; - break; -#endif - default: - case 0: - priv->ieee->iw_mode = IW_MODE_INFRA; - break; - } - - if ((priv->pci_dev->device == 0x4223) || - (priv->pci_dev->device == 0x4224)) { - printk(KERN_INFO DRV_NAME - ": Detected Intel PRO/Wireless 2915ABG Network " - "Connection\n"); - priv->ieee->abg_true = 1; - band = IEEE80211_52GHZ_BAND | IEEE80211_24GHZ_BAND; - modulation = IEEE80211_OFDM_MODULATION | - IEEE80211_CCK_MODULATION; - priv->adapter = IPW_2915ABG; - priv->ieee->mode = IEEE_A | IEEE_G | IEEE_B; - } else { - printk(KERN_INFO DRV_NAME - ": Detected Intel PRO/Wireless 2200BG Network " - "Connection\n"); - - priv->ieee->abg_true = 0; - band = IEEE80211_24GHZ_BAND; - modulation = IEEE80211_OFDM_MODULATION | - IEEE80211_CCK_MODULATION; - priv->adapter = IPW_2200BG; - priv->ieee->mode = IEEE_G | IEEE_B; - } - - priv->ieee->freq_band = band; - priv->ieee->modulation = modulation; - - priv->rates_mask = IEEE80211_DEFAULT_RATES_MASK; - - priv->missed_beacon_threshold = IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT; - priv->roaming_threshold = IPW_MB_ROAMING_THRESHOLD_DEFAULT; - - priv->rts_threshold = DEFAULT_RTS_THRESHOLD; - - /* If power management is turned on, default to AC mode */ - priv->power_mode = IPW_POWER_AC; - priv->tx_power = IPW_DEFAULT_TX_POWER; + ipw_sw_reset(priv, 1); err = request_irq(pdev->irq, ipw_isr, SA_SHIRQ, DRV_NAME, priv); if (err) { @@ -8903,6 +10025,10 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) priv->ieee->hard_start_xmit = ipw_net_hard_start_xmit; priv->ieee->set_security = shim__set_security; +#ifdef CONFIG_IPW_QOS + priv->ieee->handle_management_frame = ipw_handle_management_frame; +#endif /* CONFIG_IPW_QOS */ + priv->ieee->perfect_rssi = -20; priv->ieee->worst_rssi = -85; @@ -8960,14 +10086,14 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) static void ipw_pci_remove(struct pci_dev *pdev) { struct ipw_priv *priv = pci_get_drvdata(pdev); + if (!priv) return; - priv->status |= STATUS_EXIT_PENDING; - - sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group); - + down(&priv->sem); ipw_down(priv); + sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group); + up(&priv->sem); unregister_netdev(priv->net_dev); @@ -8977,8 +10103,6 @@ static void ipw_pci_remove(struct pci_dev *pdev) } ipw_tx_queue_free(priv); - ipw_led_shutdown(priv); - /* ipw_down will ensure that there is no more pending work * in the workqueue's, so we can safely remove them now. */ cancel_delayed_work(&priv->adhoc_check); @@ -9119,7 +10243,24 @@ MODULE_PARM_DESC(debug, "debug output mask"); module_param(channel, int, 0444); MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])"); -#ifdef CONFIG_IPW_MONITOR +#ifdef CONFIG_IPW_QOS +module_param(qos_enable, int, 0444); +MODULE_PARM_DESC(qos_enable, "enable all QoS functionalitis"); + +module_param(qos_burst_enable, int, 0444); +MODULE_PARM_DESC(qos_burst_enable, "enable QoS burst mode"); + +module_param(qos_no_ack_mask, int, 0444); +MODULE_PARM_DESC(qos_no_ack_mask, "mask Tx_Queue to no ack"); + +module_param(burst_duration_CCK, int, 0444); +MODULE_PARM_DESC(burst_duration_CCK, "set CCK burst value"); + +module_param(burst_duration_OFDM, int, 0444); +MODULE_PARM_DESC(burst_duration_OFDM, "set OFDM burst value"); +#endif /* CONFIG_IPW_QOS */ + +#ifdef CONFIG_IPW2200_MONITOR module_param(mode, int, 0444); MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS,2=Monitor)"); #else @@ -9127,5 +10268,8 @@ module_param(mode, int, 0444); MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS)"); #endif +module_param(hwcrypto, int, 0444); +MODULE_PARM_DESC(hwcrypto, "enable hardware crypto (default on)"); + module_exit(ipw_exit); module_init(ipw_init); diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index 243b8ea1414..9dbd73a4209 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -161,6 +161,16 @@ enum connection_manager_assoc_states { * TX Queue Flag Definitions */ +/* tx wep key definition */ +#define DCT_WEP_KEY_NOT_IMMIDIATE 0x00 +#define DCT_WEP_KEY_64Bit 0x40 +#define DCT_WEP_KEY_128Bit 0x80 +#define DCT_WEP_KEY_128bitIV 0xC0 +#define DCT_WEP_KEY_SIZE_MASK 0xC0 + +#define DCT_WEP_KEY_INDEX_MASK 0x0F +#define DCT_WEP_INDEX_USE_IMMEDIATE 0x20 + /* abort attempt if mgmt frame is rx'd */ #define DCT_FLAG_ABORT_MGMT 0x01 @@ -186,9 +196,23 @@ enum connection_manager_assoc_states { /* ACK rx is expected to follow */ #define DCT_FLAG_ACK_REQD 0x80 +/* TX flags extension */ #define DCT_FLAG_EXT_MODE_CCK 0x01 #define DCT_FLAG_EXT_MODE_OFDM 0x00 +#define DCT_FLAG_EXT_SECURITY_WEP 0x00 +#define DCT_FLAG_EXT_SECURITY_NO DCT_FLAG_EXT_SECURITY_WEP +#define DCT_FLAG_EXT_SECURITY_CKIP 0x04 +#define DCT_FLAG_EXT_SECURITY_CCM 0x08 +#define DCT_FLAG_EXT_SECURITY_TKIP 0x0C +#define DCT_FLAG_EXT_SECURITY_MASK 0x0C + +#define DCT_FLAG_EXT_QOS_ENABLED 0x10 + +#define DCT_FLAG_EXT_HC_NO_SIFS_PIFS 0x00 +#define DCT_FLAG_EXT_HC_SIFS 0x20 +#define DCT_FLAG_EXT_HC_PIFS 0x40 + #define TX_RX_TYPE_MASK 0xFF #define TX_FRAME_TYPE 0x00 #define TX_HOST_COMMAND_TYPE 0x01 @@ -234,6 +258,117 @@ enum connection_manager_assoc_states { #define DCR_TYPE_SNIFFER 0x06 #define DCR_TYPE_MU_BSS DCR_TYPE_MU_ESS +/* QoS definitions */ + +#define CW_MIN_OFDM 15 +#define CW_MAX_OFDM 1023 +#define CW_MIN_CCK 31 +#define CW_MAX_CCK 1023 + +#define QOS_TX0_CW_MIN_OFDM CW_MIN_OFDM +#define QOS_TX1_CW_MIN_OFDM CW_MIN_OFDM +#define QOS_TX2_CW_MIN_OFDM ( (CW_MIN_OFDM + 1) / 2 - 1 ) +#define QOS_TX3_CW_MIN_OFDM ( (CW_MIN_OFDM + 1) / 4 - 1 ) + +#define QOS_TX0_CW_MIN_CCK CW_MIN_CCK +#define QOS_TX1_CW_MIN_CCK CW_MIN_CCK +#define QOS_TX2_CW_MIN_CCK ( (CW_MIN_CCK + 1) / 2 - 1 ) +#define QOS_TX3_CW_MIN_CCK ( (CW_MIN_CCK + 1) / 4 - 1 ) + +#define QOS_TX0_CW_MAX_OFDM CW_MAX_OFDM +#define QOS_TX1_CW_MAX_OFDM CW_MAX_OFDM +#define QOS_TX2_CW_MAX_OFDM CW_MIN_OFDM +#define QOS_TX3_CW_MAX_OFDM ( (CW_MIN_OFDM + 1) / 2 - 1 ) + +#define QOS_TX0_CW_MAX_CCK CW_MAX_CCK +#define QOS_TX1_CW_MAX_CCK CW_MAX_CCK +#define QOS_TX2_CW_MAX_CCK CW_MIN_CCK +#define QOS_TX3_CW_MAX_CCK ( (CW_MIN_CCK + 1) / 2 - 1 ) + +#define QOS_TX0_AIFS (3 - QOS_AIFSN_MIN_VALUE) +#define QOS_TX1_AIFS (7 - QOS_AIFSN_MIN_VALUE) +#define QOS_TX2_AIFS (2 - QOS_AIFSN_MIN_VALUE) +#define QOS_TX3_AIFS (2 - QOS_AIFSN_MIN_VALUE) + +#define QOS_TX0_ACM 0 +#define QOS_TX1_ACM 0 +#define QOS_TX2_ACM 0 +#define QOS_TX3_ACM 0 + +#define QOS_TX0_TXOP_LIMIT_CCK 0 +#define QOS_TX1_TXOP_LIMIT_CCK 0 +#define QOS_TX2_TXOP_LIMIT_CCK 6016 +#define QOS_TX3_TXOP_LIMIT_CCK 3264 + +#define QOS_TX0_TXOP_LIMIT_OFDM 0 +#define QOS_TX1_TXOP_LIMIT_OFDM 0 +#define QOS_TX2_TXOP_LIMIT_OFDM 3008 +#define QOS_TX3_TXOP_LIMIT_OFDM 1504 + +#define DEF_TX0_CW_MIN_OFDM CW_MIN_OFDM +#define DEF_TX1_CW_MIN_OFDM CW_MIN_OFDM +#define DEF_TX2_CW_MIN_OFDM CW_MIN_OFDM +#define DEF_TX3_CW_MIN_OFDM CW_MIN_OFDM + +#define DEF_TX0_CW_MIN_CCK CW_MIN_CCK +#define DEF_TX1_CW_MIN_CCK CW_MIN_CCK +#define DEF_TX2_CW_MIN_CCK CW_MIN_CCK +#define DEF_TX3_CW_MIN_CCK CW_MIN_CCK + +#define DEF_TX0_CW_MAX_OFDM CW_MAX_OFDM +#define DEF_TX1_CW_MAX_OFDM CW_MAX_OFDM +#define DEF_TX2_CW_MAX_OFDM CW_MAX_OFDM +#define DEF_TX3_CW_MAX_OFDM CW_MAX_OFDM + +#define DEF_TX0_CW_MAX_CCK CW_MAX_CCK +#define DEF_TX1_CW_MAX_CCK CW_MAX_CCK +#define DEF_TX2_CW_MAX_CCK CW_MAX_CCK +#define DEF_TX3_CW_MAX_CCK CW_MAX_CCK + +#define DEF_TX0_AIFS 0 +#define DEF_TX1_AIFS 0 +#define DEF_TX2_AIFS 0 +#define DEF_TX3_AIFS 0 + +#define DEF_TX0_ACM 0 +#define DEF_TX1_ACM 0 +#define DEF_TX2_ACM 0 +#define DEF_TX3_ACM 0 + +#define DEF_TX0_TXOP_LIMIT_CCK 0 +#define DEF_TX1_TXOP_LIMIT_CCK 0 +#define DEF_TX2_TXOP_LIMIT_CCK 0 +#define DEF_TX3_TXOP_LIMIT_CCK 0 + +#define DEF_TX0_TXOP_LIMIT_OFDM 0 +#define DEF_TX1_TXOP_LIMIT_OFDM 0 +#define DEF_TX2_TXOP_LIMIT_OFDM 0 +#define DEF_TX3_TXOP_LIMIT_OFDM 0 + +#define QOS_QOS_SETS 3 +#define QOS_PARAM_SET_ACTIVE 0 +#define QOS_PARAM_SET_DEF_CCK 1 +#define QOS_PARAM_SET_DEF_OFDM 2 + +#define CTRL_QOS_NO_ACK (0x0020) + +#define IPW_TX_QUEUE_1 1 +#define IPW_TX_QUEUE_2 2 +#define IPW_TX_QUEUE_3 3 +#define IPW_TX_QUEUE_4 4 + +/* QoS sturctures */ +struct ipw_qos_info { + int qos_enable; + struct ieee80211_qos_parameters *def_qos_parm_OFDM; + struct ieee80211_qos_parameters *def_qos_parm_CCK; + u32 burst_duration_CCK; + u32 burst_duration_OFDM; + u16 qos_no_ack_mask; + int burst_enable; +}; + +/**************************************************************/ /** * Generic queue structure * @@ -658,6 +793,19 @@ struct ipw_multicast_addr { u8 mac4[6]; } __attribute__ ((packed)); +#define DCW_WEP_KEY_INDEX_MASK 0x03 /* bits [0:1] */ +#define DCW_WEP_KEY_SEC_TYPE_MASK 0x30 /* bits [4:5] */ + +#define DCW_WEP_KEY_SEC_TYPE_WEP 0x00 +#define DCW_WEP_KEY_SEC_TYPE_CCM 0x20 +#define DCW_WEP_KEY_SEC_TYPE_TKIP 0x30 + +#define DCW_WEP_KEY_INVALID_SIZE 0x00 /* 0 = Invalid key */ +#define DCW_WEP_KEY64Bit_SIZE 0x05 /* 64-bit encryption */ +#define DCW_WEP_KEY128Bit_SIZE 0x0D /* 128-bit encryption */ +#define DCW_CCM_KEY128Bit_SIZE 0x10 /* 128-bit key */ +//#define DCW_WEP_KEY128BitIV_SIZE 0x10 /* 128-bit key and 128-bit IV */ + struct ipw_wep_key { u8 cmd_id; u8 seq_num; @@ -819,14 +967,6 @@ struct ipw_tx_power { struct ipw_channel_tx_power channels_tx_power[MAX_A_CHANNELS]; } __attribute__ ((packed)); -struct ipw_qos_parameters { - u16 cw_min[4]; - u16 cw_max[4]; - u8 aifs[4]; - u8 flag[4]; - u16 tx_op_limit[4]; -} __attribute__ ((packed)); - struct ipw_rsn_capabilities { u8 id; u8 length; @@ -910,6 +1050,8 @@ struct ipw_cmd { #define CFG_ADHOC_CREATE (1<<8) #define CFG_NO_LED (1<<9) #define CFG_BACKGROUND_SCAN (1<<10) +#define CFG_SPEED_SCAN (1<<11) +#define CFG_NET_STATS (1<<12) #define CAP_SHARED_KEY (1<<0) /* Off = OPEN */ #define CAP_PRIVACY_ON (1<<1) /* Off = No privacy */ @@ -931,10 +1073,11 @@ struct average { s32 sum; }; +#define MAX_SPEED_SCAN 100 + struct ipw_priv { /* ieee device used by generic ieee processing code */ struct ieee80211_device *ieee; - struct ieee80211_security sec; spinlock_t lock; struct semaphore sem; @@ -1030,6 +1173,9 @@ struct ipw_priv { u32 tx_packets; u32 quality; + u8 speed_scan[MAX_SPEED_SCAN]; + u8 speed_scan_pos; + /* eeprom */ u8 eeprom[0x100]; /* 256 bytes of eeprom */ int eeprom_delay; @@ -1074,8 +1220,7 @@ struct ipw_priv { #define IPW_2915ABG 2 u8 adapter; -#define IPW_DEFAULT_TX_POWER 0x14 - u8 tx_power; + s8 tx_power; #ifdef CONFIG_PM u32 pm_state[16]; @@ -1086,6 +1231,11 @@ struct ipw_priv { /* Used to pass the current INTA value from ISR to Tasklet */ u32 isr_inta; + /* QoS */ + struct ipw_qos_info qos_data; + struct work_struct qos_activate; + /*********************************/ + /* debugging info */ u32 indirect_dword; u32 direct_dword; @@ -1162,6 +1312,7 @@ do { if (ipw_debug_level & (level)) \ #define IPW_DL_STATS (1<<29) #define IPW_DL_MERGE (1<<30) +#define IPW_DL_QOS (1<<31) #define IPW_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a) #define IPW_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a) @@ -1190,6 +1341,7 @@ do { if (ipw_debug_level & (level)) \ #define IPW_DEBUG_ASSOC(f, a...) IPW_DEBUG(IPW_DL_ASSOC | IPW_DL_INFO, f, ## a) #define IPW_DEBUG_STATS(f, a...) IPW_DEBUG(IPW_DL_STATS, f, ## a) #define IPW_DEBUG_MERGE(f, a...) IPW_DEBUG(IPW_DL_MERGE, f, ## a) +#define IPW_DEBUG_QOS(f, a...) IPW_DEBUG(IPW_DL_QOS, f, ## a) #include @@ -1204,65 +1356,65 @@ do { if (ipw_debug_level & (level)) \ #define DINO_RXFIFO_DATA 0x01 #define DINO_CONTROL_REG 0x00200000 -#define CX2_INTA_RW 0x00000008 -#define CX2_INTA_MASK_R 0x0000000C -#define CX2_INDIRECT_ADDR 0x00000010 -#define CX2_INDIRECT_DATA 0x00000014 -#define CX2_AUTOINC_ADDR 0x00000018 -#define CX2_AUTOINC_DATA 0x0000001C -#define CX2_RESET_REG 0x00000020 -#define CX2_GP_CNTRL_RW 0x00000024 +#define IPW_INTA_RW 0x00000008 +#define IPW_INTA_MASK_R 0x0000000C +#define IPW_INDIRECT_ADDR 0x00000010 +#define IPW_INDIRECT_DATA 0x00000014 +#define IPW_AUTOINC_ADDR 0x00000018 +#define IPW_AUTOINC_DATA 0x0000001C +#define IPW_RESET_REG 0x00000020 +#define IPW_GP_CNTRL_RW 0x00000024 -#define CX2_READ_INT_REGISTER 0xFF4 +#define IPW_READ_INT_REGISTER 0xFF4 -#define CX2_GP_CNTRL_BIT_INIT_DONE 0x00000004 +#define IPW_GP_CNTRL_BIT_INIT_DONE 0x00000004 -#define CX2_REGISTER_DOMAIN1_END 0x00001000 -#define CX2_SRAM_READ_INT_REGISTER 0x00000ff4 +#define IPW_REGISTER_DOMAIN1_END 0x00001000 +#define IPW_SRAM_READ_INT_REGISTER 0x00000ff4 -#define CX2_SHARED_LOWER_BOUND 0x00000200 -#define CX2_INTERRUPT_AREA_LOWER_BOUND 0x00000f80 +#define IPW_SHARED_LOWER_BOUND 0x00000200 +#define IPW_INTERRUPT_AREA_LOWER_BOUND 0x00000f80 -#define CX2_NIC_SRAM_LOWER_BOUND 0x00000000 -#define CX2_NIC_SRAM_UPPER_BOUND 0x00030000 +#define IPW_NIC_SRAM_LOWER_BOUND 0x00000000 +#define IPW_NIC_SRAM_UPPER_BOUND 0x00030000 -#define CX2_BIT_INT_HOST_SRAM_READ_INT_REGISTER (1 << 29) -#define CX2_GP_CNTRL_BIT_CLOCK_READY 0x00000001 -#define CX2_GP_CNTRL_BIT_HOST_ALLOWS_STANDBY 0x00000002 +#define IPW_BIT_INT_HOST_SRAM_READ_INT_REGISTER (1 << 29) +#define IPW_GP_CNTRL_BIT_CLOCK_READY 0x00000001 +#define IPW_GP_CNTRL_BIT_HOST_ALLOWS_STANDBY 0x00000002 /* * RESET Register Bit Indexes */ #define CBD_RESET_REG_PRINCETON_RESET (1<<0) -#define CX2_START_STANDBY (1<<2) -#define CX2_ACTIVITY_LED (1<<4) -#define CX2_ASSOCIATED_LED (1<<5) -#define CX2_OFDM_LED (1<<6) -#define CX2_RESET_REG_SW_RESET (1<<7) -#define CX2_RESET_REG_MASTER_DISABLED (1<<8) -#define CX2_RESET_REG_STOP_MASTER (1<<9) -#define CX2_GATE_ODMA (1<<25) -#define CX2_GATE_IDMA (1<<26) -#define CX2_ARC_KESHET_CONFIG (1<<27) -#define CX2_GATE_ADMA (1<<29) - -#define CX2_CSR_CIS_UPPER_BOUND 0x00000200 -#define CX2_DOMAIN_0_END 0x1000 +#define IPW_START_STANDBY (1<<2) +#define IPW_ACTIVITY_LED (1<<4) +#define IPW_ASSOCIATED_LED (1<<5) +#define IPW_OFDM_LED (1<<6) +#define IPW_RESET_REG_SW_RESET (1<<7) +#define IPW_RESET_REG_MASTER_DISABLED (1<<8) +#define IPW_RESET_REG_STOP_MASTER (1<<9) +#define IPW_GATE_ODMA (1<<25) +#define IPW_GATE_IDMA (1<<26) +#define IPW_ARC_KESHET_CONFIG (1<<27) +#define IPW_GATE_ADMA (1<<29) + +#define IPW_CSR_CIS_UPPER_BOUND 0x00000200 +#define IPW_DOMAIN_0_END 0x1000 #define CLX_MEM_BAR_SIZE 0x1000 -#define CX2_BASEBAND_CONTROL_STATUS 0X00200000 -#define CX2_BASEBAND_TX_FIFO_WRITE 0X00200004 -#define CX2_BASEBAND_RX_FIFO_READ 0X00200004 -#define CX2_BASEBAND_CONTROL_STORE 0X00200010 +#define IPW_BASEBAND_CONTROL_STATUS 0X00200000 +#define IPW_BASEBAND_TX_FIFO_WRITE 0X00200004 +#define IPW_BASEBAND_RX_FIFO_READ 0X00200004 +#define IPW_BASEBAND_CONTROL_STORE 0X00200010 -#define CX2_INTERNAL_CMD_EVENT 0X00300004 -#define CX2_BASEBAND_POWER_DOWN 0x00000001 +#define IPW_INTERNAL_CMD_EVENT 0X00300004 +#define IPW_BASEBAND_POWER_DOWN 0x00000001 -#define CX2_MEM_HALT_AND_RESET 0x003000e0 +#define IPW_MEM_HALT_AND_RESET 0x003000e0 /* defgroup bits_halt_reset MEM_HALT_AND_RESET register bits */ -#define CX2_BIT_HALT_RESET_ON 0x80000000 -#define CX2_BIT_HALT_RESET_OFF 0x00000000 +#define IPW_BIT_HALT_RESET_ON 0x80000000 +#define IPW_BIT_HALT_RESET_OFF 0x00000000 #define CB_LAST_VALID 0x20000000 #define CB_INT_ENABLED 0x40000000 @@ -1281,63 +1433,63 @@ do { if (ipw_debug_level & (level)) \ #define DMA_CB_STOP_AND_ABORT 0x00000C00 #define DMA_CB_START 0x00000100 -#define CX2_SHARED_SRAM_SIZE 0x00030000 -#define CX2_SHARED_SRAM_DMA_CONTROL 0x00027000 +#define IPW_SHARED_SRAM_SIZE 0x00030000 +#define IPW_SHARED_SRAM_DMA_CONTROL 0x00027000 #define CB_MAX_LENGTH 0x1FFF -#define CX2_HOST_EEPROM_DATA_SRAM_SIZE 0xA18 -#define CX2_EEPROM_IMAGE_SIZE 0x100 +#define IPW_HOST_EEPROM_DATA_SRAM_SIZE 0xA18 +#define IPW_EEPROM_IMAGE_SIZE 0x100 /* DMA defs */ -#define CX2_DMA_I_CURRENT_CB 0x003000D0 -#define CX2_DMA_O_CURRENT_CB 0x003000D4 -#define CX2_DMA_I_DMA_CONTROL 0x003000A4 -#define CX2_DMA_I_CB_BASE 0x003000A0 - -#define CX2_TX_CMD_QUEUE_BD_BASE 0x00000200 -#define CX2_TX_CMD_QUEUE_BD_SIZE 0x00000204 -#define CX2_TX_QUEUE_0_BD_BASE 0x00000208 -#define CX2_TX_QUEUE_0_BD_SIZE (0x0000020C) -#define CX2_TX_QUEUE_1_BD_BASE 0x00000210 -#define CX2_TX_QUEUE_1_BD_SIZE 0x00000214 -#define CX2_TX_QUEUE_2_BD_BASE 0x00000218 -#define CX2_TX_QUEUE_2_BD_SIZE (0x0000021C) -#define CX2_TX_QUEUE_3_BD_BASE 0x00000220 -#define CX2_TX_QUEUE_3_BD_SIZE 0x00000224 -#define CX2_RX_BD_BASE 0x00000240 -#define CX2_RX_BD_SIZE 0x00000244 -#define CX2_RFDS_TABLE_LOWER 0x00000500 - -#define CX2_TX_CMD_QUEUE_READ_INDEX 0x00000280 -#define CX2_TX_QUEUE_0_READ_INDEX 0x00000284 -#define CX2_TX_QUEUE_1_READ_INDEX 0x00000288 -#define CX2_TX_QUEUE_2_READ_INDEX (0x0000028C) -#define CX2_TX_QUEUE_3_READ_INDEX 0x00000290 -#define CX2_RX_READ_INDEX (0x000002A0) - -#define CX2_TX_CMD_QUEUE_WRITE_INDEX (0x00000F80) -#define CX2_TX_QUEUE_0_WRITE_INDEX (0x00000F84) -#define CX2_TX_QUEUE_1_WRITE_INDEX (0x00000F88) -#define CX2_TX_QUEUE_2_WRITE_INDEX (0x00000F8C) -#define CX2_TX_QUEUE_3_WRITE_INDEX (0x00000F90) -#define CX2_RX_WRITE_INDEX (0x00000FA0) +#define IPW_DMA_I_CURRENT_CB 0x003000D0 +#define IPW_DMA_O_CURRENT_CB 0x003000D4 +#define IPW_DMA_I_DMA_CONTROL 0x003000A4 +#define IPW_DMA_I_CB_BASE 0x003000A0 + +#define IPW_TX_CMD_QUEUE_BD_BASE 0x00000200 +#define IPW_TX_CMD_QUEUE_BD_SIZE 0x00000204 +#define IPW_TX_QUEUE_0_BD_BASE 0x00000208 +#define IPW_TX_QUEUE_0_BD_SIZE (0x0000020C) +#define IPW_TX_QUEUE_1_BD_BASE 0x00000210 +#define IPW_TX_QUEUE_1_BD_SIZE 0x00000214 +#define IPW_TX_QUEUE_2_BD_BASE 0x00000218 +#define IPW_TX_QUEUE_2_BD_SIZE (0x0000021C) +#define IPW_TX_QUEUE_3_BD_BASE 0x00000220 +#define IPW_TX_QUEUE_3_BD_SIZE 0x00000224 +#define IPW_RX_BD_BASE 0x00000240 +#define IPW_RX_BD_SIZE 0x00000244 +#define IPW_RFDS_TABLE_LOWER 0x00000500 + +#define IPW_TX_CMD_QUEUE_READ_INDEX 0x00000280 +#define IPW_TX_QUEUE_0_READ_INDEX 0x00000284 +#define IPW_TX_QUEUE_1_READ_INDEX 0x00000288 +#define IPW_TX_QUEUE_2_READ_INDEX (0x0000028C) +#define IPW_TX_QUEUE_3_READ_INDEX 0x00000290 +#define IPW_RX_READ_INDEX (0x000002A0) + +#define IPW_TX_CMD_QUEUE_WRITE_INDEX (0x00000F80) +#define IPW_TX_QUEUE_0_WRITE_INDEX (0x00000F84) +#define IPW_TX_QUEUE_1_WRITE_INDEX (0x00000F88) +#define IPW_TX_QUEUE_2_WRITE_INDEX (0x00000F8C) +#define IPW_TX_QUEUE_3_WRITE_INDEX (0x00000F90) +#define IPW_RX_WRITE_INDEX (0x00000FA0) /* * EEPROM Related Definitions */ -#define IPW_EEPROM_DATA_SRAM_ADDRESS (CX2_SHARED_LOWER_BOUND + 0x814) -#define IPW_EEPROM_DATA_SRAM_SIZE (CX2_SHARED_LOWER_BOUND + 0x818) -#define IPW_EEPROM_LOAD_DISABLE (CX2_SHARED_LOWER_BOUND + 0x81C) -#define IPW_EEPROM_DATA (CX2_SHARED_LOWER_BOUND + 0x820) -#define IPW_EEPROM_UPPER_ADDRESS (CX2_SHARED_LOWER_BOUND + 0x9E0) +#define IPW_EEPROM_DATA_SRAM_ADDRESS (IPW_SHARED_LOWER_BOUND + 0x814) +#define IPW_EEPROM_DATA_SRAM_SIZE (IPW_SHARED_LOWER_BOUND + 0x818) +#define IPW_EEPROM_LOAD_DISABLE (IPW_SHARED_LOWER_BOUND + 0x81C) +#define IPW_EEPROM_DATA (IPW_SHARED_LOWER_BOUND + 0x820) +#define IPW_EEPROM_UPPER_ADDRESS (IPW_SHARED_LOWER_BOUND + 0x9E0) -#define IPW_STATION_TABLE_LOWER (CX2_SHARED_LOWER_BOUND + 0xA0C) -#define IPW_STATION_TABLE_UPPER (CX2_SHARED_LOWER_BOUND + 0xB0C) -#define IPW_REQUEST_ATIM (CX2_SHARED_LOWER_BOUND + 0xB0C) -#define IPW_ATIM_SENT (CX2_SHARED_LOWER_BOUND + 0xB10) -#define IPW_WHO_IS_AWAKE (CX2_SHARED_LOWER_BOUND + 0xB14) -#define IPW_DURING_ATIM_WINDOW (CX2_SHARED_LOWER_BOUND + 0xB18) +#define IPW_STATION_TABLE_LOWER (IPW_SHARED_LOWER_BOUND + 0xA0C) +#define IPW_STATION_TABLE_UPPER (IPW_SHARED_LOWER_BOUND + 0xB0C) +#define IPW_REQUEST_ATIM (IPW_SHARED_LOWER_BOUND + 0xB0C) +#define IPW_ATIM_SENT (IPW_SHARED_LOWER_BOUND + 0xB10) +#define IPW_WHO_IS_AWAKE (IPW_SHARED_LOWER_BOUND + 0xB14) +#define IPW_DURING_ATIM_WINDOW (IPW_SHARED_LOWER_BOUND + 0xB18) #define MSB 1 #define LSB 0 @@ -1367,7 +1519,7 @@ do { if (ipw_debug_level & (level)) \ #define FW_MEM_REG_LOWER_BOUND 0x00300000 #define FW_MEM_REG_EEPROM_ACCESS (FW_MEM_REG_LOWER_BOUND + 0x40) -#define CX2_EVENT_REG (FW_MEM_REG_LOWER_BOUND + 0x04) +#define IPW_EVENT_REG (FW_MEM_REG_LOWER_BOUND + 0x04) #define EEPROM_BIT_SK (1<<0) #define EEPROM_BIT_CS (1<<1) #define EEPROM_BIT_DI (1<<2) @@ -1376,50 +1528,47 @@ do { if (ipw_debug_level & (level)) \ #define EEPROM_CMD_READ 0x2 /* Interrupts masks */ -#define CX2_INTA_NONE 0x00000000 +#define IPW_INTA_NONE 0x00000000 -#define CX2_INTA_BIT_RX_TRANSFER 0x00000002 -#define CX2_INTA_BIT_STATUS_CHANGE 0x00000010 -#define CX2_INTA_BIT_BEACON_PERIOD_EXPIRED 0x00000020 +#define IPW_INTA_BIT_RX_TRANSFER 0x00000002 +#define IPW_INTA_BIT_STATUS_CHANGE 0x00000010 +#define IPW_INTA_BIT_BEACON_PERIOD_EXPIRED 0x00000020 //Inta Bits for CF -#define CX2_INTA_BIT_TX_CMD_QUEUE 0x00000800 -#define CX2_INTA_BIT_TX_QUEUE_1 0x00001000 -#define CX2_INTA_BIT_TX_QUEUE_2 0x00002000 -#define CX2_INTA_BIT_TX_QUEUE_3 0x00004000 -#define CX2_INTA_BIT_TX_QUEUE_4 0x00008000 +#define IPW_INTA_BIT_TX_CMD_QUEUE 0x00000800 +#define IPW_INTA_BIT_TX_QUEUE_1 0x00001000 +#define IPW_INTA_BIT_TX_QUEUE_2 0x00002000 +#define IPW_INTA_BIT_TX_QUEUE_3 0x00004000 +#define IPW_INTA_BIT_TX_QUEUE_4 0x00008000 -#define CX2_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE 0x00010000 +#define IPW_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE 0x00010000 -#define CX2_INTA_BIT_PREPARE_FOR_POWER_DOWN 0x00100000 -#define CX2_INTA_BIT_POWER_DOWN 0x00200000 +#define IPW_INTA_BIT_PREPARE_FOR_POWER_DOWN 0x00100000 +#define IPW_INTA_BIT_POWER_DOWN 0x00200000 -#define CX2_INTA_BIT_FW_INITIALIZATION_DONE 0x01000000 -#define CX2_INTA_BIT_FW_CARD_DISABLE_PHY_OFF_DONE 0x02000000 -#define CX2_INTA_BIT_RF_KILL_DONE 0x04000000 -#define CX2_INTA_BIT_FATAL_ERROR 0x40000000 -#define CX2_INTA_BIT_PARITY_ERROR 0x80000000 +#define IPW_INTA_BIT_FW_INITIALIZATION_DONE 0x01000000 +#define IPW_INTA_BIT_FW_CARD_DISABLE_PHY_OFF_DONE 0x02000000 +#define IPW_INTA_BIT_RF_KILL_DONE 0x04000000 +#define IPW_INTA_BIT_FATAL_ERROR 0x40000000 +#define IPW_INTA_BIT_PARITY_ERROR 0x80000000 /* Interrupts enabled at init time. */ -#define CX2_INTA_MASK_ALL \ - (CX2_INTA_BIT_TX_QUEUE_1 | \ - CX2_INTA_BIT_TX_QUEUE_2 | \ - CX2_INTA_BIT_TX_QUEUE_3 | \ - CX2_INTA_BIT_TX_QUEUE_4 | \ - CX2_INTA_BIT_TX_CMD_QUEUE | \ - CX2_INTA_BIT_RX_TRANSFER | \ - CX2_INTA_BIT_FATAL_ERROR | \ - CX2_INTA_BIT_PARITY_ERROR | \ - CX2_INTA_BIT_STATUS_CHANGE | \ - CX2_INTA_BIT_FW_INITIALIZATION_DONE | \ - CX2_INTA_BIT_BEACON_PERIOD_EXPIRED | \ - CX2_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE | \ - CX2_INTA_BIT_PREPARE_FOR_POWER_DOWN | \ - CX2_INTA_BIT_POWER_DOWN | \ - CX2_INTA_BIT_RF_KILL_DONE ) - -#define IPWSTATUS_ERROR_LOG (CX2_SHARED_LOWER_BOUND + 0x410) -#define IPW_EVENT_LOG (CX2_SHARED_LOWER_BOUND + 0x414) +#define IPW_INTA_MASK_ALL \ + (IPW_INTA_BIT_TX_QUEUE_1 | \ + IPW_INTA_BIT_TX_QUEUE_2 | \ + IPW_INTA_BIT_TX_QUEUE_3 | \ + IPW_INTA_BIT_TX_QUEUE_4 | \ + IPW_INTA_BIT_TX_CMD_QUEUE | \ + IPW_INTA_BIT_RX_TRANSFER | \ + IPW_INTA_BIT_FATAL_ERROR | \ + IPW_INTA_BIT_PARITY_ERROR | \ + IPW_INTA_BIT_STATUS_CHANGE | \ + IPW_INTA_BIT_FW_INITIALIZATION_DONE | \ + IPW_INTA_BIT_BEACON_PERIOD_EXPIRED | \ + IPW_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE | \ + IPW_INTA_BIT_PREPARE_FOR_POWER_DOWN | \ + IPW_INTA_BIT_POWER_DOWN | \ + IPW_INTA_BIT_RF_KILL_DONE ) /* FW event log definitions */ #define EVENT_ELEM_SIZE (3 * sizeof(u32)) @@ -1429,6 +1578,11 @@ do { if (ipw_debug_level & (level)) \ #define ERROR_ELEM_SIZE (7 * sizeof(u32)) #define ERROR_START_OFFSET (1 * sizeof(u32)) +/* TX power level (dbm) */ +#define IPW_TX_POWER_MIN -12 +#define IPW_TX_POWER_MAX 20 +#define IPW_TX_POWER_DEFAULT IPW_TX_POWER_MAX + enum { IPW_FW_ERROR_OK = 0, IPW_FW_ERROR_FAIL, @@ -1441,8 +1595,8 @@ enum { IPW_FW_ERROR_ALLOC_FAIL, IPW_FW_ERROR_DMA_UNDERRUN, IPW_FW_ERROR_DMA_STATUS, - IPW_FW_ERROR_DINOSTATUS_ERROR, - IPW_FW_ERROR_EEPROMSTATUS_ERROR, + IPW_FW_ERROR_DINO_ERROR, + IPW_FW_ERROR_EEPROM_ERROR, IPW_FW_ERROR_SYSASSERT, IPW_FW_ERROR_FATAL_ERROR }; @@ -1458,6 +1612,8 @@ enum { #define HC_IBSS_RECONF 4 #define HC_DISASSOC_QUIET 5 +#define HC_QOS_SUPPORT_ASSOC 0x01 + #define IPW_RATE_CAPABILITIES 1 #define IPW_RATE_CONNECT 0 @@ -1628,18 +1784,20 @@ enum { IPW_ORD_TABLE_7_LAST }; -#define IPW_ORDINALS_TABLE_LOWER (CX2_SHARED_LOWER_BOUND + 0x500) -#define IPW_ORDINALS_TABLE_0 (CX2_SHARED_LOWER_BOUND + 0x180) -#define IPW_ORDINALS_TABLE_1 (CX2_SHARED_LOWER_BOUND + 0x184) -#define IPW_ORDINALS_TABLE_2 (CX2_SHARED_LOWER_BOUND + 0x188) -#define IPW_MEM_FIXED_OVERRIDE (CX2_SHARED_LOWER_BOUND + 0x41C) +#define IPWSTATUS_ERROR_LOG (IPW_SHARED_LOWER_BOUND + 0x410) +#define IPW_EVENT_LOG (IPW_SHARED_LOWER_BOUND + 0x414) +#define IPW_ORDINALS_TABLE_LOWER (IPW_SHARED_LOWER_BOUND + 0x500) +#define IPW_ORDINALS_TABLE_0 (IPW_SHARED_LOWER_BOUND + 0x180) +#define IPW_ORDINALS_TABLE_1 (IPW_SHARED_LOWER_BOUND + 0x184) +#define IPW_ORDINALS_TABLE_2 (IPW_SHARED_LOWER_BOUND + 0x188) +#define IPW_MEM_FIXED_OVERRIDE (IPW_SHARED_LOWER_BOUND + 0x41C) struct ipw_fixed_rate { u16 tx_rates; u16 reserved; } __attribute__ ((packed)); -#define CX2_INDIRECT_ADDR_MASK (~0x3ul) +#define IPW_INDIRECT_ADDR_MASK (~0x3ul) struct host_cmd { u8 cmd; @@ -1676,15 +1834,6 @@ struct host_cmd { #define REG_CHANNEL_MASK 0x00003FFF #define IPW_IBSS_11B_DEFAULT_MASK 0x87ff -static const long ipw_frequencies[] = { - 2412, 2417, 2422, 2427, - 2432, 2437, 2442, 2447, - 2452, 2457, 2462, 2467, - 2472, 2484 -}; - -#define FREQ_COUNT ARRAY_SIZE(ipw_frequencies) - #define IPW_MAX_CONFIG_RETRIES 10 static inline u32 frame_hdr_len(struct ieee80211_hdr_4addr *hdr) -- cgit v1.2.3 From 823283549da144ff49e65c6e4a670b7784203e0b Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Wed, 24 Aug 2005 22:33:31 -0500 Subject: Catch ipw2100 up to equivelancy with v1.1.1 * Added WE-18 support. This allows the use of -Dext with wpa_supplicant > 0.4.x (thanks to Hong Liu) * Fixed #339 problem with iwconfig set/get txpower (thanks to Hong Liu) * Fixed #598 problem when with error messages when module loaded with 'disable=1' (thanks to Hong Liu) * Fixed #640 problem with 'iwlist retry' now showing min/max retry * Fixed compatibility with wpa_supplicant and the new -Dipw interface (that included a fix for 64-bit compatibility) * Added CFG_CRC_CHECK which allows passing through packets with bad CRCs while in monitor mode. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2100.c | 577 +++++++++++++++++++++++++++++++---------- drivers/net/wireless/ipw2100.h | 11 +- 2 files changed, 451 insertions(+), 137 deletions(-) diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 449c1c085fb..e7c222119da 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -167,12 +167,12 @@ that only one external action is invoked at a time. #include "ipw2100.h" -#define IPW2100_VERSION "1.1.0" +#define IPW2100_VERSION "1.1.1" #define DRV_NAME "ipw2100" #define DRV_VERSION IPW2100_VERSION #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation" +#define DRV_COPYRIGHT "Copyright(c) 2003-2005 Intel Corporation" /* Debugging stuff */ #ifdef CONFIG_IPW_DEBUG @@ -779,7 +779,7 @@ static int ipw2100_hw_send_command(struct ipw2100_priv *priv, if (err == 0) { IPW_DEBUG_INFO("Command completion failed out after %dms.\n", - HOST_COMPLETE_TIMEOUT / (HZ / 100)); + 1000 * (HOST_COMPLETE_TIMEOUT / HZ)); priv->fatal_error = IPW2100_ERR_MSG_TIMEOUT; priv->status &= ~STATUS_CMD_ACTIVE; schedule_reset(priv); @@ -1986,7 +1986,7 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid, IPW_DEBUG_HC("SSID: '%s'\n", escape_essid(essid, ssid_len)); if (ssid_len) - memcpy((char *)cmd.host_command_parameters, essid, ssid_len); + memcpy(cmd.host_command_parameters, essid, ssid_len); if (!batch_mode) { err = ipw2100_disable_adapter(priv); @@ -2369,13 +2369,15 @@ static inline void isr_rx(struct ipw2100_priv *priv, int i, IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); return; } - +#ifdef CONFIG_IPW2100_MONITOR if (unlikely(priv->ieee->iw_mode == IW_MODE_MONITOR && + priv->config & CFG_CRC_CHECK && status->flags & IPW_STATUS_FLAG_CRC_ERROR)) { IPW_DEBUG_RX("CRC error in packet. Dropping.\n"); priv->ieee->stats.rx_errors++; return; } +#endif if (unlikely(priv->ieee->iw_mode != IW_MODE_MONITOR && !(priv->status & STATUS_ASSOCIATED))) { @@ -2744,7 +2746,6 @@ static inline int __ipw2100_tx_process(struct ipw2100_priv *priv) priv->net_dev->name, txq->oldest, packet->index); /* DATA packet; we have to unmap and free the SKB */ - priv->ieee->stats.tx_packets++; for (i = 0; i < frag_num; i++) { tbd = &txq->drv[(packet->index + 1 + i) % txq->entries]; @@ -2757,8 +2758,6 @@ static inline int __ipw2100_tx_process(struct ipw2100_priv *priv) tbd->buf_length, PCI_DMA_TODEVICE); } - priv->ieee->stats.tx_bytes += - packet->info.d_struct.txb->payload_size; ieee80211_txb_free(packet->info.d_struct.txb); packet->info.d_struct.txb = NULL; @@ -2767,13 +2766,8 @@ static inline int __ipw2100_tx_process(struct ipw2100_priv *priv) /* We have a free slot in the Tx queue, so wake up the * transmit layer if it is stopped. */ - if (priv->status & STATUS_ASSOCIATED && - netif_queue_stopped(priv->net_dev)) { - IPW_DEBUG_INFO(KERN_INFO - "%s: Waking net queue.\n", - priv->net_dev->name); + if (priv->status & STATUS_ASSOCIATED) netif_wake_queue(priv->net_dev); - } /* A packet was processed by the hardware, so update the * watchdog */ @@ -3791,6 +3785,9 @@ static ssize_t show_ordinals(struct device *d, struct device_attribute *attr, u32 val_len; static int loop = 0; + if (priv->status & STATUS_RF_KILL_MASK) + return 0; + if (loop >= sizeof(ord_data) / sizeof(*ord_data)) loop = 0; @@ -3947,6 +3944,9 @@ static ssize_t show_bssinfo(struct device *d, struct device_attribute *attr, int length; int ret; + if (priv->status & STATUS_RF_KILL_MASK) + return 0; + memset(essid, 0, sizeof(essid)); memset(bssid, 0, sizeof(bssid)); @@ -3986,8 +3986,8 @@ static ssize_t show_debug_level(struct device_driver *d, char *buf) return sprintf(buf, "0x%08X\n", ipw2100_debug_level); } -static ssize_t store_debug_level(struct device_driver *d, const char *buf, - size_t count) +static ssize_t store_debug_level(struct device_driver *d, + const char *buf, size_t count) { char *p = (char *)buf; u32 val; @@ -4943,7 +4943,7 @@ static int ipw2100_set_mandatory_bssid(struct ipw2100_priv *priv, u8 * bssid, #endif /* if BSSID is empty then we disable mandatory bssid mode */ if (bssid != NULL) - memcpy((u8 *) cmd.host_command_parameters, bssid, ETH_ALEN); + memcpy(cmd.host_command_parameters, bssid, ETH_ALEN); if (!batch_mode) { err = ipw2100_disable_adapter(priv); @@ -4959,7 +4959,6 @@ static int ipw2100_set_mandatory_bssid(struct ipw2100_priv *priv, u8 * bssid, return err; } -#ifdef CONFIG_IEEE80211_WPA static int ipw2100_disassociate_bssid(struct ipw2100_priv *priv) { struct host_command cmd = { @@ -4983,34 +4982,6 @@ static int ipw2100_disassociate_bssid(struct ipw2100_priv *priv) return err; } -#endif - -/* - * Pseudo code for setting up wpa_frame: - */ -#if 0 -void x(struct ieee80211_assoc_frame *wpa_assoc) -{ - struct ipw2100_wpa_assoc_frame frame; - frame->fixed_ie_mask = IPW_WPA_CAPABILTIES | - IPW_WPA_LISTENINTERVAL | IPW_WPA_AP_ADDRESS; - frame->capab_info = wpa_assoc->capab_info; - frame->lisen_interval = wpa_assoc->listent_interval; - memcpy(frame->current_ap, wpa_assoc->current_ap, ETH_ALEN); - - /* UNKNOWN -- I'm not postivive about this part; don't have any WPA - * setup here to test it with. - * - * Walk the IEs in the wpa_assoc and figure out the total size of all - * that data. Stick that into frame->var_ie_len. Then memcpy() all of - * the IEs from wpa_frame into frame. - */ - frame->var_ie_len = calculate_ie_len(wpa_assoc); - memcpy(frame->var_ie, wpa_assoc->variable, frame->var_ie_len); - - ipw2100_set_wpa_ie(priv, &frame, 0); -} -#endif static int ipw2100_set_wpa_ie(struct ipw2100_priv *, struct ipw2100_wpa_assoc_frame *, int) @@ -5750,11 +5721,10 @@ static struct net_device_stats *ipw2100_stats(struct net_device *dev) return &priv->ieee->stats; } -/* Support for wpa_supplicant. Will be replaced with WEXT once - * they get WPA support. */ -#ifdef CONFIG_IEEE80211_WPA +#if WIRELESS_EXT < 18 +/* Support for wpa_supplicant before WE-18, deprecated. */ -/* following definitions must match definitions in driver_ipw2100.c */ +/* following definitions must match definitions in driver_ipw.c */ #define IPW2100_IOCTL_WPA_SUPPLICANT SIOCIWFIRSTPRIV+30 @@ -5792,11 +5762,12 @@ struct ipw2100_param { } wpa_param; struct { u32 len; - u8 *data; + u8 reserved[32]; + u8 data[0]; } wpa_ie; struct { - int command; - int reason_code; + u32 command; + u32 reason_code; } mlme; struct { u8 alg[IPW2100_CRYPT_ALG_NAME_LEN]; @@ -5811,37 +5782,21 @@ struct ipw2100_param { } u; }; -/* end of driver_ipw2100.c code */ +/* end of driver_ipw.c code */ +#endif /* WIRELESS_EXT < 18 */ static int ipw2100_wpa_enable(struct ipw2100_priv *priv, int value) { - - struct ieee80211_device *ieee = priv->ieee; - struct ieee80211_security sec = { - .flags = SEC_LEVEL | SEC_ENABLED, - }; - int ret = 0; - - ieee->wpa_enabled = value; - - if (value) { - sec.level = SEC_LEVEL_3; - sec.enabled = 1; - } else { - sec.level = SEC_LEVEL_0; - sec.enabled = 0; - } - - if (ieee->set_security) - ieee->set_security(ieee->dev, &sec); - else - ret = -EOPNOTSUPP; - - return ret; + /* This is called when wpa_supplicant loads and closes the driver + * interface. */ + priv->ieee->wpa_enabled = value; + return 0; } -#define AUTH_ALG_OPEN_SYSTEM 0x1 -#define AUTH_ALG_SHARED_KEY 0x2 +#if WIRELESS_EXT < 18 +#define IW_AUTH_ALG_OPEN_SYSTEM 0x1 +#define IW_AUTH_ALG_SHARED_KEY 0x2 +#endif static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value) { @@ -5852,13 +5807,14 @@ static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value) }; int ret = 0; - if (value & AUTH_ALG_SHARED_KEY) { + if (value & IW_AUTH_ALG_SHARED_KEY) { sec.auth_mode = WLAN_AUTH_SHARED_KEY; ieee->open_wep = 0; - } else { + } else if (value & IW_AUTH_ALG_OPEN_SYSTEM) { sec.auth_mode = WLAN_AUTH_OPEN; ieee->open_wep = 1; - } + } else + return -EINVAL; if (ieee->set_security) ieee->set_security(ieee->dev, &sec); @@ -5868,10 +5824,29 @@ static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value) return ret; } -static int ipw2100_wpa_set_param(struct net_device *dev, u8 name, u32 value) +void ipw2100_wpa_assoc_frame(struct ipw2100_priv *priv, + char *wpa_ie, int wpa_ie_len) { + struct ipw2100_wpa_assoc_frame frame; + + frame.fixed_ie_mask = 0; + + /* copy WPA IE */ + memcpy(frame.var_ie, wpa_ie, wpa_ie_len); + frame.var_ie_len = wpa_ie_len; + + /* make sure WPA is enabled */ + ipw2100_wpa_enable(priv, 1); + ipw2100_set_wpa_ie(priv, &frame, 0); +} + +#if WIRELESS_EXT < 18 +static int ipw2100_wpa_set_param(struct net_device *dev, u8 name, u32 value) +{ struct ipw2100_priv *priv = ieee80211_priv(dev); + struct ieee80211_crypt_data *crypt; + unsigned long flags; int ret = 0; switch (name) { @@ -5880,7 +5855,22 @@ static int ipw2100_wpa_set_param(struct net_device *dev, u8 name, u32 value) break; case IPW2100_PARAM_TKIP_COUNTERMEASURES: - priv->ieee->tkip_countermeasures = value; + crypt = priv->ieee->crypt[priv->ieee->tx_keyidx]; + if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) { + IPW_DEBUG_WARNING("Can't set TKIP countermeasures: " + "crypt not set!\n"); + break; + } + + flags = crypt->ops->get_flags(crypt->priv); + + if (value) + flags |= IEEE80211_CRYPTO_TKIP_COUNTERMEASURES; + else + flags &= ~IEEE80211_CRYPTO_TKIP_COUNTERMEASURES; + + crypt->ops->set_flags(flags, crypt->priv); + break; case IPW2100_PARAM_DROP_UNENCRYPTED: @@ -5932,23 +5922,6 @@ static int ipw2100_wpa_mlme(struct net_device *dev, int command, int reason) return ret; } -void ipw2100_wpa_assoc_frame(struct ipw2100_priv *priv, - char *wpa_ie, int wpa_ie_len) -{ - - struct ipw2100_wpa_assoc_frame frame; - - frame.fixed_ie_mask = 0; - - /* copy WPA IE */ - memcpy(frame.var_ie, wpa_ie, wpa_ie_len); - frame.var_ie_len = wpa_ie_len; - - /* make sure WPA is enabled */ - ipw2100_wpa_enable(priv, 1); - ipw2100_set_wpa_ie(priv, &frame, 0); -} - static int ipw2100_wpa_set_wpa_ie(struct net_device *dev, struct ipw2100_param *param, int plen) { @@ -5992,7 +5965,6 @@ static int ipw2100_wpa_set_encryption(struct net_device *dev, struct ipw2100_param *param, int param_len) { - int ret = 0; struct ipw2100_priv *priv = ieee80211_priv(dev); struct ieee80211_device *ieee = priv->ieee; @@ -6101,8 +6073,8 @@ static int ipw2100_wpa_set_encryption(struct net_device *dev, if (ops->name != NULL) { if (strcmp(ops->name, "WEP") == 0) { - memcpy(sec.keys[param->u.crypt.idx], param->u.crypt.key, - param->u.crypt.key_len); + memcpy(sec.keys[param->u.crypt.idx], + param->u.crypt.key, param->u.crypt.key_len); sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len; sec.flags |= (1 << param->u.crypt.idx); @@ -6190,11 +6162,9 @@ static int ipw2100_wpa_supplicant(struct net_device *dev, struct iw_point *p) kfree(param); return ret; } -#endif /* CONFIG_IEEE80211_WPA */ static int ipw2100_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { -#ifdef CONFIG_IEEE80211_WPA struct iwreq *wrq = (struct iwreq *)rq; int ret = -1; switch (cmd) { @@ -6206,10 +6176,9 @@ static int ipw2100_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return -EOPNOTSUPP; } -#endif /* CONFIG_IEEE80211_WPA */ - return -EOPNOTSUPP; } +#endif /* WIRELESS_EXT < 18 */ static void ipw_ethtool_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) @@ -6333,10 +6302,15 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, priv->ieee->hard_start_xmit = ipw2100_tx; priv->ieee->set_security = shim__set_security; + priv->ieee->perfect_rssi = -20; + priv->ieee->worst_rssi = -85; + dev->open = ipw2100_open; dev->stop = ipw2100_close; dev->init = ipw2100_net_init; +#if WIRELESS_EXT < 18 dev->do_ioctl = ipw2100_ioctl; +#endif dev->get_stats = ipw2100_stats; dev->ethtool_ops = &ipw2100_ethtool_ops; dev->tx_timeout = ipw2100_tx_timeout; @@ -6362,13 +6336,13 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, /* If power management is turned on, default to AUTO mode */ priv->power_mode = IPW_POWER_AUTO; -#ifdef CONFIG_IEEE80211_WPA +#ifdef CONFIG_IPW2100_MONITOR + priv->config |= CFG_CRC_CHECK; +#endif priv->ieee->wpa_enabled = 0; - priv->ieee->tkip_countermeasures = 0; priv->ieee->drop_unencrypted = 0; priv->ieee->privacy_invoked = 0; priv->ieee->ieee802_1x = 1; -#endif /* CONFIG_IEEE80211_WPA */ /* Set module parameters */ switch (mode) { @@ -6429,7 +6403,7 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, INIT_LIST_HEAD(&priv->fw_pend_list); INIT_STAT(&priv->fw_pend_stat); -#ifdef CONFIG_SOFTWARE_SUSPEND2 +#ifdef PF_SYNCTHREAD priv->workqueue = create_workqueue(DRV_NAME, 0); #else priv->workqueue = create_workqueue(DRV_NAME); @@ -6591,7 +6565,6 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, /* perform this after register_netdev so that dev->name is set */ sysfs_create_group(&pci_dev->dev.kobj, &ipw2100_attribute_group); - netif_carrier_off(dev); /* If the RF Kill switch is disabled, go ahead and complete the * startup sequence */ @@ -6860,10 +6833,6 @@ static int __init ipw2100_init(void) printk(KERN_INFO DRV_NAME ": %s, %s\n", DRV_DESCRIPTION, DRV_VERSION); printk(KERN_INFO DRV_NAME ": %s\n", DRV_COPYRIGHT); -#ifdef CONFIG_IEEE80211_NOWEP - IPW_DEBUG_INFO(DRV_NAME ": Compiled with WEP disabled.\n"); -#endif - ret = pci_module_init(&ipw2100_pci_driver); #ifdef CONFIG_IPW_DEBUG @@ -6963,9 +6932,10 @@ static int ipw2100_wx_set_freq(struct net_device *dev, } } - if (fwrq->e > 0 || fwrq->m > 1000) - return -EOPNOTSUPP; - else { /* Set the channel */ + if (fwrq->e > 0 || fwrq->m > 1000) { + err = -EOPNOTSUPP; + goto done; + } else { /* Set the channel */ IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m); err = ipw2100_set_channel(priv, fwrq->m, 0); } @@ -7256,7 +7226,7 @@ static int ipw2100_wx_get_wap(struct net_device *dev, * configured BSSID then return that; otherwise return ANY */ if (priv->config & CFG_STATIC_BSSID || priv->status & STATUS_ASSOCIATED) { wrqu->ap_addr.sa_family = ARPHRD_ETHER; - memcpy(wrqu->ap_addr.sa_data, &priv->bssid, ETH_ALEN); + memcpy(wrqu->ap_addr.sa_data, priv->bssid, ETH_ALEN); } else memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN); @@ -7711,13 +7681,13 @@ static int ipw2100_wx_get_retry(struct net_device *dev, return -EINVAL; if (wrqu->retry.flags & IW_RETRY_MAX) { - wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MAX; + wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; wrqu->retry.value = priv->long_retry_limit; } else { wrqu->retry.flags = (priv->short_retry_limit != priv->long_retry_limit) ? - IW_RETRY_LIMIT & IW_RETRY_MIN : IW_RETRY_LIMIT; + IW_RETRY_LIMIT | IW_RETRY_MIN : IW_RETRY_LIMIT; wrqu->retry.value = priv->short_retry_limit; } @@ -7847,9 +7817,9 @@ static int ipw2100_wx_get_power(struct net_device *dev, struct ipw2100_priv *priv = ieee80211_priv(dev); - if (!(priv->power_mode & IPW_POWER_ENABLED)) { + if (!(priv->power_mode & IPW_POWER_ENABLED)) wrqu->power.disabled = 1; - } else { + else { wrqu->power.disabled = 0; wrqu->power.flags = 0; } @@ -7859,6 +7829,273 @@ static int ipw2100_wx_get_power(struct net_device *dev, return 0; } +#if WIRELESS_EXT > 17 +/* + * WE-18 WPA support + */ + +/* SIOCSIWGENIE */ +static int ipw2100_wx_set_genie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + + struct ipw2100_priv *priv = ieee80211_priv(dev); + struct ieee80211_device *ieee = priv->ieee; + u8 *buf; + + if (!ieee->wpa_enabled) + return -EOPNOTSUPP; + + if (wrqu->data.length > MAX_WPA_IE_LEN || + (wrqu->data.length && extra == NULL)) + return -EINVAL; + + if (wrqu->data.length) { + buf = kmalloc(wrqu->data.length, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + + memcpy(buf, extra, wrqu->data.length); + kfree(ieee->wpa_ie); + ieee->wpa_ie = buf; + ieee->wpa_ie_len = wrqu->data.length; + } else { + kfree(ieee->wpa_ie); + ieee->wpa_ie = NULL; + ieee->wpa_ie_len = 0; + } + + ipw2100_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len); + + return 0; +} + +/* SIOCGIWGENIE */ +static int ipw2100_wx_get_genie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ipw2100_priv *priv = ieee80211_priv(dev); + struct ieee80211_device *ieee = priv->ieee; + + if (ieee->wpa_ie_len == 0 || ieee->wpa_ie == NULL) { + wrqu->data.length = 0; + return 0; + } + + if (wrqu->data.length < ieee->wpa_ie_len) + return -E2BIG; + + wrqu->data.length = ieee->wpa_ie_len; + memcpy(extra, ieee->wpa_ie, ieee->wpa_ie_len); + + return 0; +} + +/* SIOCSIWAUTH */ +static int ipw2100_wx_set_auth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ipw2100_priv *priv = ieee80211_priv(dev); + struct ieee80211_device *ieee = priv->ieee; + struct iw_param *param = &wrqu->param; + struct ieee80211_crypt_data *crypt; + unsigned long flags; + int ret = 0; + + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + case IW_AUTH_CIPHER_PAIRWISE: + case IW_AUTH_CIPHER_GROUP: + case IW_AUTH_KEY_MGMT: + /* + * ipw2200 does not use these parameters + */ + break; + + case IW_AUTH_TKIP_COUNTERMEASURES: + crypt = priv->ieee->crypt[priv->ieee->tx_keyidx]; + if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) { + IPW_DEBUG_WARNING("Can't set TKIP countermeasures: " + "crypt not set!\n"); + break; + } + + flags = crypt->ops->get_flags(crypt->priv); + + if (param->value) + flags |= IEEE80211_CRYPTO_TKIP_COUNTERMEASURES; + else + flags &= ~IEEE80211_CRYPTO_TKIP_COUNTERMEASURES; + + crypt->ops->set_flags(flags, crypt->priv); + + break; + + case IW_AUTH_DROP_UNENCRYPTED:{ + /* HACK: + * + * wpa_supplicant calls set_wpa_enabled when the driver + * is loaded and unloaded, regardless of if WPA is being + * used. No other calls are made which can be used to + * determine if encryption will be used or not prior to + * association being expected. If encryption is not being + * used, drop_unencrypted is set to false, else true -- we + * can use this to determine if the CAP_PRIVACY_ON bit should + * be set. + */ + struct ieee80211_security sec = { + .flags = SEC_ENABLED, + .enabled = param->value, + }; + priv->ieee->drop_unencrypted = param->value; + /* We only change SEC_LEVEL for open mode. Others + * are set by ipw_wpa_set_encryption. + */ + if (!param->value) { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_0; + } else { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_1; + } + if (priv->ieee->set_security) + priv->ieee->set_security(priv->ieee->dev, &sec); + break; + } + + case IW_AUTH_80211_AUTH_ALG: + ret = ipw2100_wpa_set_auth_algs(priv, param->value); + break; + + case IW_AUTH_WPA_ENABLED: + ret = ipw2100_wpa_enable(priv, param->value); + break; + + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + ieee->ieee802_1x = param->value; + break; + + //case IW_AUTH_ROAMING_CONTROL: + case IW_AUTH_PRIVACY_INVOKED: + ieee->privacy_invoked = param->value; + break; + + default: + return -EOPNOTSUPP; + } + return ret; +} + +/* SIOCGIWAUTH */ +static int ipw2100_wx_get_auth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ipw2100_priv *priv = ieee80211_priv(dev); + struct ieee80211_device *ieee = priv->ieee; + struct ieee80211_crypt_data *crypt; + struct iw_param *param = &wrqu->param; + int ret = 0; + + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + case IW_AUTH_CIPHER_PAIRWISE: + case IW_AUTH_CIPHER_GROUP: + case IW_AUTH_KEY_MGMT: + /* + * wpa_supplicant will control these internally + */ + ret = -EOPNOTSUPP; + break; + + case IW_AUTH_TKIP_COUNTERMEASURES: + crypt = priv->ieee->crypt[priv->ieee->tx_keyidx]; + if (!crypt || !crypt->ops->get_flags) { + IPW_DEBUG_WARNING("Can't get TKIP countermeasures: " + "crypt not set!\n"); + break; + } + + param->value = (crypt->ops->get_flags(crypt->priv) & + IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) ? 1 : 0; + + break; + + case IW_AUTH_DROP_UNENCRYPTED: + param->value = ieee->drop_unencrypted; + break; + + case IW_AUTH_80211_AUTH_ALG: + param->value = priv->sec.auth_mode; + break; + + case IW_AUTH_WPA_ENABLED: + param->value = ieee->wpa_enabled; + break; + + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + param->value = ieee->ieee802_1x; + break; + + case IW_AUTH_ROAMING_CONTROL: + case IW_AUTH_PRIVACY_INVOKED: + param->value = ieee->privacy_invoked; + break; + + default: + return -EOPNOTSUPP; + } + return 0; +} + +/* SIOCSIWENCODEEXT */ +static int ipw2100_wx_set_encodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ipw2100_priv *priv = ieee80211_priv(dev); + return ieee80211_wx_set_encodeext(priv->ieee, info, wrqu, extra); +} + +/* SIOCGIWENCODEEXT */ +static int ipw2100_wx_get_encodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ipw2100_priv *priv = ieee80211_priv(dev); + return ieee80211_wx_get_encodeext(priv->ieee, info, wrqu, extra); +} + +/* SIOCSIWMLME */ +static int ipw2100_wx_set_mlme(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ipw2100_priv *priv = ieee80211_priv(dev); + struct iw_mlme *mlme = (struct iw_mlme *)extra; + u16 reason; + + reason = cpu_to_le16(mlme->reason_code); + + switch (mlme->cmd) { + case IW_MLME_DEAUTH: + // silently ignore + break; + + case IW_MLME_DISASSOC: + ipw2100_disassociate_bssid(priv); + break; + + default: + return -EOPNOTSUPP; + } + return 0; +} +#endif /* WIRELESS_EXT > 17 */ + /* * * IWPRIV handlers @@ -8019,6 +8256,54 @@ static int ipw2100_wx_get_preamble(struct net_device *dev, return 0; } +#ifdef CONFIG_IPW2100_MONITOR +static int ipw2100_wx_set_crc_check(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ipw2100_priv *priv = ieee80211_priv(dev); + int err, mode = *(int *)extra; + + down(&priv->action_sem); + if (!(priv->status & STATUS_INITIALIZED)) { + err = -EIO; + goto done; + } + + if (mode == 1) + priv->config |= CFG_CRC_CHECK; + else if (mode == 0) + priv->config &= ~CFG_CRC_CHECK; + else { + err = -EINVAL; + goto done; + } + err = 0; + + done: + up(&priv->action_sem); + return err; +} + +static int ipw2100_wx_get_crc_check(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + /* + * This can be called at any time. No action lock required + */ + + struct ipw2100_priv *priv = ieee80211_priv(dev); + + if (priv->config & CFG_CRC_CHECK) + snprintf(wrqu->name, IFNAMSIZ, "CRC checked (1)"); + else + snprintf(wrqu->name, IFNAMSIZ, "CRC ignored (0)"); + + return 0; +} +#endif /* CONFIG_IPW2100_MONITOR */ + static iw_handler ipw2100_wx_handlers[] = { NULL, /* SIOCSIWCOMMIT */ ipw2100_wx_get_name, /* SIOCGIWNAME */ @@ -8042,7 +8327,11 @@ static iw_handler ipw2100_wx_handlers[] = { NULL, /* SIOCWIWTHRSPY */ ipw2100_wx_set_wap, /* SIOCSIWAP */ ipw2100_wx_get_wap, /* SIOCGIWAP */ +#if WIRELESS_EXT > 17 + ipw2100_wx_set_mlme, /* SIOCSIWMLME */ +#else NULL, /* -- hole -- */ +#endif NULL, /* SIOCGIWAPLIST -- deprecated */ ipw2100_wx_set_scan, /* SIOCSIWSCAN */ ipw2100_wx_get_scan, /* SIOCGIWSCAN */ @@ -8066,6 +8355,17 @@ static iw_handler ipw2100_wx_handlers[] = { ipw2100_wx_get_encode, /* SIOCGIWENCODE */ ipw2100_wx_set_power, /* SIOCSIWPOWER */ ipw2100_wx_get_power, /* SIOCGIWPOWER */ +#if WIRELESS_EXT > 17 + NULL, /* -- hole -- */ + NULL, /* -- hole -- */ + ipw2100_wx_set_genie, /* SIOCSIWGENIE */ + ipw2100_wx_get_genie, /* SIOCGIWGENIE */ + ipw2100_wx_set_auth, /* SIOCSIWAUTH */ + ipw2100_wx_get_auth, /* SIOCGIWAUTH */ + ipw2100_wx_set_encodeext, /* SIOCSIWENCODEEXT */ + ipw2100_wx_get_encodeext, /* SIOCGIWENCODEEXT */ + NULL, /* SIOCSIWPMKSA */ +#endif }; #define IPW2100_PRIV_SET_MONITOR SIOCIWFIRSTPRIV @@ -8074,6 +8374,8 @@ static iw_handler ipw2100_wx_handlers[] = { #define IPW2100_PRIV_GET_POWER SIOCIWFIRSTPRIV+3 #define IPW2100_PRIV_SET_LONGPREAMBLE SIOCIWFIRSTPRIV+4 #define IPW2100_PRIV_GET_LONGPREAMBLE SIOCIWFIRSTPRIV+5 +#define IPW2100_PRIV_SET_CRC_CHECK SIOCIWFIRSTPRIV+6 +#define IPW2100_PRIV_GET_CRC_CHECK SIOCIWFIRSTPRIV+7 static const struct iw_priv_args ipw2100_private_args[] = { @@ -8099,6 +8401,14 @@ static const struct iw_priv_args ipw2100_private_args[] = { { IPW2100_PRIV_GET_LONGPREAMBLE, 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "get_preamble"}, +#ifdef CONFIG_IPW2100_MONITOR + { + IPW2100_PRIV_SET_CRC_CHECK, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_crc_check"}, + { + IPW2100_PRIV_GET_CRC_CHECK, + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "get_crc_check"}, +#endif /* CONFIG_IPW2100_MONITOR */ }; static iw_handler ipw2100_private_handler[] = { @@ -8113,6 +8423,13 @@ static iw_handler ipw2100_private_handler[] = { ipw2100_wx_get_powermode, ipw2100_wx_set_preamble, ipw2100_wx_get_preamble, +#ifdef CONFIG_IPW2100_MONITOR + ipw2100_wx_set_crc_check, + ipw2100_wx_get_crc_check, +#else /* CONFIG_IPW2100_MONITOR */ + NULL, + NULL, +#endif /* CONFIG_IPW2100_MONITOR */ }; static struct iw_handler_def ipw2100_wx_handler_def = { @@ -8292,17 +8609,11 @@ static void ipw2100_wx_event_work(struct ipw2100_priv *priv) /* We now have the BSSID, so can finish setting to the full * associated state */ memcpy(wrqu.ap_addr.sa_data, priv->bssid, ETH_ALEN); - memcpy(&priv->ieee->bssid, priv->bssid, ETH_ALEN); + memcpy(priv->ieee->bssid, priv->bssid, ETH_ALEN); priv->status &= ~STATUS_ASSOCIATING; priv->status |= STATUS_ASSOCIATED; netif_carrier_on(priv->net_dev); - if (netif_queue_stopped(priv->net_dev)) { - IPW_DEBUG_INFO("Waking net queue.\n"); - netif_wake_queue(priv->net_dev); - } else { - IPW_DEBUG_INFO("Starting net queue.\n"); - netif_start_queue(priv->net_dev); - } + netif_wake_queue(priv->net_dev); } if (!(priv->status & STATUS_ASSOCIATED)) { diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h index 3eb5c384eaa..99fce99b701 100644 --- a/drivers/net/wireless/ipw2100.h +++ b/drivers/net/wireless/ipw2100.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as @@ -475,6 +475,9 @@ enum { #define CFG_ADHOC_CREATE (1<<8) #define CFG_C3_DISABLED (1<<9) #define CFG_PASSIVE_SCAN (1<<10) +#ifdef CONFIG_IPW2100_MONITOR +#define CFG_CRC_CHECK (1<<11) +#endif #define CAP_SHARED_KEY (1<<0) /* Off = OPEN */ #define CAP_PRIVACY_ON (1<<1) /* Off = No privacy */ @@ -858,9 +861,9 @@ struct ipw2100_rx { #define TYPE_ASSOCIATION_REQUEST 0x0013 #define TYPE_REASSOCIATION_REQUEST 0x0014 -#define HW_FEATURE_RFKILL (0x0001) -#define RF_KILLSWITCH_OFF (1) -#define RF_KILLSWITCH_ON (0) +#define HW_FEATURE_RFKILL 0x0001 +#define RF_KILLSWITCH_OFF 1 +#define RF_KILLSWITCH_ON 0 #define IPW_COMMAND_POOL_SIZE 40 -- cgit v1.2.3 From 25b645be1e25e16ea7a25678ac195a0e7595c629 Mon Sep 17 00:00:00 2001 From: Date: Tue, 12 Jul 2005 15:45:30 -0500 Subject: Fixed WEP on ipw2100 (priv->sec was being used instead of priv->ieee->sec) --- drivers/net/wireless/ipw2100.c | 97 ++++++++++++++++++++++-------------------- drivers/net/wireless/ipw2100.h | 2 - 2 files changed, 51 insertions(+), 48 deletions(-) diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index e7c222119da..cf5da20d1d4 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -1616,7 +1616,7 @@ static int ipw2100_set_scan_options(struct ipw2100_priv *priv) if (!(priv->config & CFG_ASSOCIATE)) cmd.host_command_parameters[0] |= IPW_SCAN_NOASSOCIATE; - if ((priv->sec.flags & SEC_ENABLED) && priv->sec.enabled) + if ((priv->ieee->sec.flags & SEC_ENABLED) && priv->ieee->sec.enabled) cmd.host_command_parameters[0] |= IPW_SCAN_MIXED_CELL; if (priv->config & CFG_PASSIVE_SCAN) cmd.host_command_parameters[0] |= IPW_SCAN_PASSIVE; @@ -5349,23 +5349,23 @@ static int ipw2100_configure_security(struct ipw2100_priv *priv, int batch_mode) return err; } - if (!priv->sec.enabled) { + if (!priv->ieee->sec.enabled) { err = ipw2100_set_security_information(priv, IPW_AUTH_OPEN, SEC_LEVEL_0, 0, 1); } else { auth_mode = IPW_AUTH_OPEN; - if ((priv->sec.flags & SEC_AUTH_MODE) && - (priv->sec.auth_mode == WLAN_AUTH_SHARED_KEY)) + if ((priv->ieee->sec.flags & SEC_AUTH_MODE) && + (priv->ieee->sec.auth_mode == WLAN_AUTH_SHARED_KEY)) auth_mode = IPW_AUTH_SHARED; sec_level = SEC_LEVEL_0; - if (priv->sec.flags & SEC_LEVEL) - sec_level = priv->sec.level; + if (priv->ieee->sec.flags & SEC_LEVEL) + sec_level = priv->ieee->sec.level; use_group = 0; - if (priv->sec.flags & SEC_UNICAST_GROUP) - use_group = priv->sec.unicast_uses_group; + if (priv->ieee->sec.flags & SEC_UNICAST_GROUP) + use_group = priv->ieee->sec.unicast_uses_group; err = ipw2100_set_security_information(priv, auth_mode, sec_level, @@ -5375,16 +5375,16 @@ static int ipw2100_configure_security(struct ipw2100_priv *priv, int batch_mode) if (err) goto exit; - if (priv->sec.enabled) { + if (priv->ieee->sec.enabled) { for (i = 0; i < 4; i++) { - if (!(priv->sec.flags & (1 << i))) { - memset(priv->sec.keys[i], 0, WEP_KEY_LEN); - priv->sec.key_sizes[i] = 0; + if (!(priv->ieee->sec.flags & (1 << i))) { + memset(priv->ieee->sec.keys[i], 0, WEP_KEY_LEN); + priv->ieee->sec.key_sizes[i] = 0; } else { err = ipw2100_set_key(priv, i, - priv->sec.keys[i], - priv->sec.key_sizes[i], - 1); + priv->ieee->sec.keys[i], + priv->ieee->sec. + key_sizes[i], 1); if (err) goto exit; } @@ -5397,8 +5397,8 @@ static int ipw2100_configure_security(struct ipw2100_priv *priv, int batch_mode) * encrypted data is sent up */ err = ipw2100_set_wep_flags(priv, - priv->sec.enabled ? IPW_PRIVACY_CAPABLE : 0, - 1); + priv->ieee->sec. + enabled ? IPW_PRIVACY_CAPABLE : 0, 1); if (err) goto exit; @@ -5433,58 +5433,61 @@ static void shim__set_security(struct net_device *dev, for (i = 0; i < 4; i++) { if (sec->flags & (1 << i)) { - priv->sec.key_sizes[i] = sec->key_sizes[i]; + priv->ieee->sec.key_sizes[i] = sec->key_sizes[i]; if (sec->key_sizes[i] == 0) - priv->sec.flags &= ~(1 << i); + priv->ieee->sec.flags &= ~(1 << i); else - memcpy(priv->sec.keys[i], sec->keys[i], + memcpy(priv->ieee->sec.keys[i], sec->keys[i], sec->key_sizes[i]); - priv->sec.flags |= (1 << i); + priv->ieee->sec.flags |= (1 << i); priv->status |= STATUS_SECURITY_UPDATED; } } if ((sec->flags & SEC_ACTIVE_KEY) && - priv->sec.active_key != sec->active_key) { + priv->ieee->sec.active_key != sec->active_key) { if (sec->active_key <= 3) { - priv->sec.active_key = sec->active_key; - priv->sec.flags |= SEC_ACTIVE_KEY; + priv->ieee->sec.active_key = sec->active_key; + priv->ieee->sec.flags |= SEC_ACTIVE_KEY; } else - priv->sec.flags &= ~SEC_ACTIVE_KEY; + priv->ieee->sec.flags &= ~SEC_ACTIVE_KEY; priv->status |= STATUS_SECURITY_UPDATED; } if ((sec->flags & SEC_AUTH_MODE) && - (priv->sec.auth_mode != sec->auth_mode)) { - priv->sec.auth_mode = sec->auth_mode; - priv->sec.flags |= SEC_AUTH_MODE; + (priv->ieee->sec.auth_mode != sec->auth_mode)) { + priv->ieee->sec.auth_mode = sec->auth_mode; + priv->ieee->sec.flags |= SEC_AUTH_MODE; priv->status |= STATUS_SECURITY_UPDATED; } - if (sec->flags & SEC_ENABLED && priv->sec.enabled != sec->enabled) { - priv->sec.flags |= SEC_ENABLED; - priv->sec.enabled = sec->enabled; + if (sec->flags & SEC_ENABLED && priv->ieee->sec.enabled != sec->enabled) { + priv->ieee->sec.flags |= SEC_ENABLED; + priv->ieee->sec.enabled = sec->enabled; priv->status |= STATUS_SECURITY_UPDATED; force_update = 1; } - if (sec->flags & SEC_LEVEL && priv->sec.level != sec->level) { - priv->sec.level = sec->level; - priv->sec.flags |= SEC_LEVEL; + if (sec->flags & SEC_ENCRYPT) + priv->ieee->sec.encrypt = sec->encrypt; + + if (sec->flags & SEC_LEVEL && priv->ieee->sec.level != sec->level) { + priv->ieee->sec.level = sec->level; + priv->ieee->sec.flags |= SEC_LEVEL; priv->status |= STATUS_SECURITY_UPDATED; } IPW_DEBUG_WEP("Security flags: %c %c%c%c%c %c%c%c%c\n", - priv->sec.flags & (1 << 8) ? '1' : '0', - priv->sec.flags & (1 << 7) ? '1' : '0', - priv->sec.flags & (1 << 6) ? '1' : '0', - priv->sec.flags & (1 << 5) ? '1' : '0', - priv->sec.flags & (1 << 4) ? '1' : '0', - priv->sec.flags & (1 << 3) ? '1' : '0', - priv->sec.flags & (1 << 2) ? '1' : '0', - priv->sec.flags & (1 << 1) ? '1' : '0', - priv->sec.flags & (1 << 0) ? '1' : '0'); + priv->ieee->sec.flags & (1 << 8) ? '1' : '0', + priv->ieee->sec.flags & (1 << 7) ? '1' : '0', + priv->ieee->sec.flags & (1 << 6) ? '1' : '0', + priv->ieee->sec.flags & (1 << 5) ? '1' : '0', + priv->ieee->sec.flags & (1 << 4) ? '1' : '0', + priv->ieee->sec.flags & (1 << 3) ? '1' : '0', + priv->ieee->sec.flags & (1 << 2) ? '1' : '0', + priv->ieee->sec.flags & (1 << 1) ? '1' : '0', + priv->ieee->sec.flags & (1 << 0) ? '1' : '0'); /* As a temporary work around to enable WPA until we figure out why * wpa_supplicant toggles the security capability of the driver, which @@ -5995,17 +5998,19 @@ static int ipw2100_wpa_set_encryption(struct net_device *dev, return -EINVAL; } + sec.flags |= SEC_ENABLED | SEC_ENCRYPT; if (strcmp(param->u.crypt.alg, "none") == 0) { if (crypt) { sec.enabled = 0; + sec.encrypt = 0; sec.level = SEC_LEVEL_0; - sec.flags |= SEC_ENABLED | SEC_LEVEL; + sec.flags |= SEC_LEVEL; ieee80211_crypt_delayed_deinit(ieee, crypt); } goto done; } sec.enabled = 1; - sec.flags |= SEC_ENABLED; + sec.encrypt = 1; ops = ieee80211_get_crypto_ops(param->u.crypt.alg); if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) { @@ -8029,7 +8034,7 @@ static int ipw2100_wx_get_auth(struct net_device *dev, break; case IW_AUTH_80211_AUTH_ALG: - param->value = priv->sec.auth_mode; + param->value = priv->ieee->sec.auth_mode; break; case IW_AUTH_WPA_ENABLED: diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h index 99fce99b701..a1a9cbcf6c2 100644 --- a/drivers/net/wireless/ipw2100.h +++ b/drivers/net/wireless/ipw2100.h @@ -524,8 +524,6 @@ struct ipw2100_priv { int power_mode; - /* WEP data */ - struct ieee80211_security sec; int messages_sent; int short_retry_limit; -- cgit v1.2.3 From f75459e6f64ca0632f23029e2ca47b424dd33373 Mon Sep 17 00:00:00 2001 From: Liu Hong Date: Wed, 13 Jul 2005 12:29:21 -0500 Subject: [Bug 339] Fix ipw2100 iwconfig set/get txpower. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2100.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index cf5da20d1d4..73287ab7bff 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -5102,6 +5102,10 @@ static int ipw2100_set_tx_power(struct ipw2100_priv *priv, u32 tx_power) }; int err = 0; + if (tx_power != IPW_TX_POWER_DEFAULT) + tx_power = (tx_power - IPW_TX_POWER_MIN_DBM) * 16 / + (IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM); + cmd.host_command_parameters[0] = tx_power; if (priv->ieee->iw_mode == IW_MODE_ADHOC) @@ -7523,8 +7527,7 @@ static int ipw2100_wx_set_txpow(struct net_device *dev, wrqu->txpower.value > IPW_TX_POWER_MAX_DBM) return -EINVAL; - value = (wrqu->txpower.value - IPW_TX_POWER_MIN_DBM) * 16 / - (IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM); + value = wrqu->txpower.value; } down(&priv->action_sem); @@ -7564,11 +7567,7 @@ static int ipw2100_wx_get_txpow(struct net_device *dev, } else { wrqu->power.disabled = 0; wrqu->power.fixed = 1; - wrqu->power.value = - (priv->tx_power * - (IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM)) / - (IPW_TX_POWER_MAX - IPW_TX_POWER_MIN) + - IPW_TX_POWER_MIN_DBM; + wrqu->power.value = priv->tx_power; } wrqu->power.flags = IW_TXPOW_DBM; -- cgit v1.2.3 From e4cc28998724661c19cd979a78eaf9a424da52ef Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Wed, 13 Jul 2005 12:30:34 -0500 Subject: Move code from ipw2100_wpa_enable to IPW2100_PARAM_DROP_UNENCRYPTED to support wpa_supplicant with open AP. We need this to make driver_ipw work. driver_ext has already had the similar code with the WE-18 support added. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2100.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 73287ab7bff..eaf47078ee5 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -5880,9 +5880,27 @@ static int ipw2100_wpa_set_param(struct net_device *dev, u8 name, u32 value) break; - case IPW2100_PARAM_DROP_UNENCRYPTED: - priv->ieee->drop_unencrypted = value; - break; + case IPW2100_PARAM_DROP_UNENCRYPTED:{ + /* See IW_AUTH_DROP_UNENCRYPTED handling for details */ + struct ieee80211_security sec = { + .flags = SEC_ENABLED, + .enabled = value, + }; + priv->ieee->drop_unencrypted = value; + /* We only change SEC_LEVEL for open mode. Others + * are set by ipw_wpa_set_encryption. + */ + if (!value) { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_0; + } else { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_1; + } + if (priv->ieee->set_security) + priv->ieee->set_security(priv->ieee->dev, &sec); + break; + } case IPW2100_PARAM_PRIVACY_INVOKED: priv->ieee->privacy_invoked = value; -- cgit v1.2.3 From afbf30a2b78cac38e6ddae10a73063943b4783ee Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Thu, 25 Aug 2005 00:05:33 -0500 Subject: Catch ipw2200 up to equivelancy with v1.0.5 * Fixed #452 problem with setting retry limit (thanks to Hong Liu) * Fixed #592 race condition during association causing firmware errors * Fixed #602 problem with building in 64-bit environment * Fixed #625 problem with SCAN_REQUEST_EXT sometimes failing * Fixed #645 problem with bit rate not decreasing when moving laptop farther from AP * Fixed #656 problem with 'iwconfig eth1 mode auto' and 'modprobe' locking the system * Fixed #667 problem with "No space for Tx" for hwcrypto=1 * Fixed #685 kernel panic in rmmod caused by led work is still queued * Fixed #695 problem with network doesn't reassociate after suspend/resume * Fixed #701 problem with 'iwprvi sw_reset' not resetting the card from monitor mode * Fixed #710 problem with monitor mode being used after a WEP key has been configured * Fixed network->mode vs. priv->ieee->iw_mode checking (thanks to Ben Cahill) * Fixed "Unknown management packet %d" warning * Fixed setting channels multiple times in monitor mode causes scan stopped * Fixed ipw_wx_sw_reset doesn't switch firmware if mode is changed. * Add duplicate packet checking code (kill ping DUP! and TKIP replay warning) * Fix hardware encryption (both WEP and AES) doesn't work with fragmentation. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 1544 ++++++++++++++++++++++++++++------------ drivers/net/wireless/ipw2200.h | 26 +- 2 files changed, 1123 insertions(+), 447 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 0a583afbcdd..1b6f0277a3e 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved. + Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved. 802.11 status code portion of this file from ethereal-0.10.6: Copyright 2000, Axis Communications AB @@ -32,7 +32,7 @@ #include "ipw2200.h" -#define IPW2200_VERSION "1.0.4" +#define IPW2200_VERSION "1.0.5" #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation" #define DRV_VERSION IPW2200_VERSION @@ -273,14 +273,14 @@ static inline u32 __ipw_read32(char *f, u32 l, struct ipw_priv *ipw, u32 ofs) static void _ipw_read_indirect(struct ipw_priv *, u32, u8 *, int); #define ipw_read_indirect(a, b, c, d) \ - IPW_DEBUG_IO("%s %d: read_inddirect(0x%08X) %d bytes\n", __FILE__, __LINE__, (u32)(b), d); \ + IPW_DEBUG_IO("%s %d: read_indirect(0x%08X) %d bytes\n", __FILE__, __LINE__, (u32)(b), d); \ _ipw_read_indirect(a, b, c, d) static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * data, int num); #define ipw_write_indirect(a, b, c, d) \ IPW_DEBUG_IO("%s %d: write_indirect(0x%08X) %d bytes\n", __FILE__, __LINE__, (u32)(b), d); \ - _ipw_write_indirect(a, b, c, d) + _ipw_write_indirect(a, b, c, d) /* indirect write s */ static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value) @@ -295,8 +295,6 @@ static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value) IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value); _ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK); _ipw_write8(priv, IPW_INDIRECT_DATA, value); - IPW_DEBUG_IO(" reg = 0x%8lX : value = 0x%8X\n", - (unsigned long)(priv->hw_base + IPW_INDIRECT_DATA), value); } static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value) @@ -1015,12 +1013,12 @@ void ipw_led_init(struct ipw_priv *priv) void ipw_led_shutdown(struct ipw_priv *priv) { - cancel_delayed_work(&priv->led_link_on); - cancel_delayed_work(&priv->led_link_off); - cancel_delayed_work(&priv->led_act_off); ipw_led_activity_off(priv); ipw_led_link_off(priv); ipw_led_band_off(priv); + cancel_delayed_work(&priv->led_link_on); + cancel_delayed_work(&priv->led_link_off); + cancel_delayed_work(&priv->led_act_off); } /* @@ -1296,6 +1294,7 @@ static ssize_t show_indirect_dword(struct device *d, { u32 reg = 0; struct ipw_priv *priv = d->driver_data; + if (priv->status & STATUS_INDIRECT_DWORD) reg = ipw_read_reg32(priv, priv->indirect_dword); else @@ -1322,6 +1321,7 @@ static ssize_t show_indirect_byte(struct device *d, { u8 reg = 0; struct ipw_priv *priv = d->driver_data; + if (priv->status & STATUS_INDIRECT_BYTE) reg = ipw_read_reg8(priv, priv->indirect_byte); else @@ -1509,8 +1509,8 @@ static ssize_t store_net_stats(struct device *d, struct device_attribute *attr, return count; } -static DEVICE_ATTR(net_stats, S_IWUSR | S_IRUGO, show_net_stats, - store_net_stats); +static DEVICE_ATTR(net_stats, S_IWUSR | S_IRUGO, + show_net_stats, store_net_stats); static void notify_wx_assoc_event(struct ipw_priv *priv) { @@ -1630,6 +1630,11 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) /* Keep the restart process from trying to send host * commands by clearing the INIT status bit */ priv->status &= ~STATUS_INIT; + + /* Cancel currently queued command. */ + priv->status &= ~STATUS_HCMD_ACTIVE; + wake_up_interruptible(&priv->wait_command_queue); + queue_work(priv->workqueue, &priv->adapter_restart); handled |= IPW_INTA_BIT_FATAL_ERROR; } @@ -1796,7 +1801,7 @@ static int ipw_send_system_config(struct ipw_priv *priv, return -1; } - memcpy(&cmd.param, config, sizeof(*config)); + memcpy(cmd.param, config, sizeof(*config)); if (ipw_send_cmd(priv, &cmd)) { IPW_ERROR("failed to send SYSTEM_CONFIG command\n"); return -1; @@ -1817,7 +1822,7 @@ static int ipw_send_ssid(struct ipw_priv *priv, u8 * ssid, int len) return -1; } - memcpy(&cmd.param, ssid, cmd.len); + memcpy(cmd.param, ssid, cmd.len); if (ipw_send_cmd(priv, &cmd)) { IPW_ERROR("failed to send SSID command\n"); return -1; @@ -1841,8 +1846,7 @@ static int ipw_send_adapter_address(struct ipw_priv *priv, u8 * mac) IPW_DEBUG_INFO("%s: Setting MAC to " MAC_FMT "\n", priv->net_dev->name, MAC_ARG(mac)); - memcpy(&cmd.param, mac, ETH_ALEN); - + memcpy(cmd.param, mac, ETH_ALEN); if (ipw_send_cmd(priv, &cmd)) { IPW_ERROR("failed to send ADAPTER_ADDRESS command\n"); return -1; @@ -1873,11 +1877,6 @@ static void ipw_adapter_restart(void *adapter) IPW_ERROR("Failed to up device\n"); return; } - - if ((priv->capability & CAP_PRIVACY_ON) && - (priv->ieee->sec.level == SEC_LEVEL_1) && - !(priv->ieee->host_encrypt || priv->ieee->host_decrypt)) - ipw_set_hwcrypto_keys(priv); } static void ipw_bg_adapter_restart(void *data) @@ -1917,14 +1916,12 @@ static int ipw_send_scan_request_ext(struct ipw_priv *priv, .len = sizeof(*request) }; - memcpy(&cmd.param, request, sizeof(*request)); + memcpy(cmd.param, request, sizeof(*request)); if (ipw_send_cmd(priv, &cmd)) { IPW_ERROR("failed to send SCAN_REQUEST_EXT command\n"); return -1; } - queue_delayed_work(priv->workqueue, &priv->scan_check, - IPW_SCAN_CHECK_WATCHDOG); return 0; } @@ -1991,7 +1988,7 @@ static int ipw_send_associate(struct ipw_priv *priv, return -1; } - memcpy(&cmd.param, &tmp_associate, sizeof(*associate)); + memcpy(cmd.param, &tmp_associate, sizeof(*associate)); if (ipw_send_cmd(priv, &cmd)) { IPW_ERROR("failed to send ASSOCIATE command\n"); return -1; @@ -2013,7 +2010,7 @@ static int ipw_send_supported_rates(struct ipw_priv *priv, return -1; } - memcpy(&cmd.param, rates, sizeof(*rates)); + memcpy(cmd.param, rates, sizeof(*rates)); if (ipw_send_cmd(priv, &cmd)) { IPW_ERROR("failed to send SUPPORTED_RATES command\n"); return -1; @@ -2078,7 +2075,7 @@ static int ipw_send_tx_power(struct ipw_priv *priv, struct ipw_tx_power *power) return -1; } - memcpy(&cmd.param, power, sizeof(*power)); + memcpy(cmd.param, power, sizeof(*power)); if (ipw_send_cmd(priv, &cmd)) { IPW_ERROR("failed to send TX_POWER command\n"); return -1; @@ -2102,7 +2099,7 @@ static int ipw_send_rts_threshold(struct ipw_priv *priv, u16 rts) return -1; } - memcpy(&cmd.param, &rts_threshold, sizeof(rts_threshold)); + memcpy(cmd.param, &rts_threshold, sizeof(rts_threshold)); if (ipw_send_cmd(priv, &cmd)) { IPW_ERROR("failed to send RTS_THRESHOLD command\n"); return -1; @@ -2126,7 +2123,7 @@ static int ipw_send_frag_threshold(struct ipw_priv *priv, u16 frag) return -1; } - memcpy(&cmd.param, &frag_threshold, sizeof(frag_threshold)); + memcpy(cmd.param, &frag_threshold, sizeof(frag_threshold)); if (ipw_send_cmd(priv, &cmd)) { IPW_ERROR("failed to send FRAG_THRESHOLD command\n"); return -1; @@ -2170,6 +2167,31 @@ static int ipw_send_power_mode(struct ipw_priv *priv, u32 mode) return 0; } +static int ipw_send_retry_limit(struct ipw_priv *priv, u8 slimit, u8 llimit) +{ + struct ipw_retry_limit retry_limit = { + .short_retry_limit = slimit, + .long_retry_limit = llimit + }; + struct host_cmd cmd = { + .cmd = IPW_CMD_RETRY_LIMIT, + .len = sizeof(retry_limit) + }; + + if (!priv) { + IPW_ERROR("Invalid args\n"); + return -1; + } + + memcpy(cmd.param, &retry_limit, sizeof(retry_limit)); + if (ipw_send_cmd(priv, &cmd)) { + IPW_ERROR("failed to send RETRY_LIMIT command\n"); + return -1; + } + + return 0; +} + /* * The IPW device contains a Microwire compatible EEPROM that stores * various data like the MAC address. Usually the firmware has exclusive @@ -2269,8 +2291,7 @@ static u16 eeprom_read_u16(struct ipw_priv *priv, u8 addr) /* data's copy of the eeprom data */ static void eeprom_parse_mac(struct ipw_priv *priv, u8 * mac) { - u8 *ee = (u8 *) priv->eeprom; - memcpy(mac, &ee[EEPROM_MAC_ADDRESS], 6); + memcpy(mac, &priv->eeprom[EEPROM_MAC_ADDRESS], 6); } /* @@ -2680,8 +2701,7 @@ struct fw_chunk { #define IPW_FW_MINOR(x) ((x & 0xff) >> 8) #define IPW_FW_MAJOR(x) (x & 0xff) -#define IPW_FW_VERSION ((IPW_FW_MINOR_VERSION << 8) | \ - IPW_FW_MAJOR_VERSION) +#define IPW_FW_VERSION ((IPW_FW_MINOR_VERSION << 8) | IPW_FW_MAJOR_VERSION) #define IPW_FW_PREFIX "ipw-" __stringify(IPW_FW_MAJOR_VERSION) \ "." __stringify(IPW_FW_MINOR_VERSION) "-" @@ -2952,6 +2972,8 @@ static int ipw_reset_nic(struct ipw_priv *priv) /* Clear the 'host command active' bit... */ priv->status &= ~STATUS_HCMD_ACTIVE; wake_up_interruptible(&priv->wait_command_queue); + priv->status &= ~(STATUS_SCANNING | STATUS_SCAN_ABORTING); + wake_up_interruptible(&priv->wait_state); spin_unlock_irqrestore(&priv->lock, flags); IPW_DEBUG_TRACE("<<\n"); @@ -3027,6 +3049,19 @@ static int fw_loaded = 0; static const struct firmware *bootfw = NULL; static const struct firmware *firmware = NULL; static const struct firmware *ucode = NULL; + +static void free_firmware(void) +{ + if (fw_loaded) { + release_firmware(bootfw); + release_firmware(ucode); + release_firmware(firmware); + bootfw = ucode = firmware = NULL; + fw_loaded = 0; + } +} +#else +#define free_firmware() do {} while (0) #endif static int ipw_load(struct ipw_priv *priv) @@ -3915,13 +3950,13 @@ static inline void ipw_handle_missed_beacon(struct ipw_priv *priv, { priv->notif_missed_beacons = missed_count; - if (missed_count > priv->missed_beacon_threshold && + if (missed_count > priv->disassociate_threshold && priv->status & STATUS_ASSOCIATED) { /* If associated and we've hit the missed * beacon threshold, disassociate, turn * off roaming, and abort any active scans */ IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF | - IPW_DL_STATE, + IPW_DL_STATE | IPW_DL_ASSOC, "Missed beacon: %d - disassociate\n", missed_count); priv->status &= ~STATUS_ROAMING; if (priv->status & STATUS_SCANNING) { @@ -4027,7 +4062,11 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, priv->status |= STATUS_ASSOCIATED; #ifdef CONFIG_IPW_QOS - if (priv->status & STATUS_AUTH) { +#define IPW_GET_PACKET_STYPE(x) WLAN_FC_GET_STYPE( \ + le16_to_cpu(((struct ieee80211_hdr *)(x))->frame_ctl)) + if ((priv->status & STATUS_AUTH) && + (IPW_GET_PACKET_STYPE(¬if->u.raw) + == IEEE80211_STYPE_ASSOC_RESP)) { if ((sizeof (struct ieee80211_assoc_response_frame) @@ -4287,10 +4326,12 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, #ifdef CONFIG_IPW2200_MONITOR if (priv->ieee->iw_mode == IW_MODE_MONITOR) { + priv->status |= STATUS_SCAN_FORCED; queue_work(priv->workqueue, &priv->request_scan); break; } + priv->status &= ~STATUS_SCAN_FORCED; #endif /* CONFIG_IPW2200_MONITOR */ if (!(priv->status & (STATUS_ASSOCIATED | @@ -4330,6 +4371,7 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, case HOST_NOTIFICATION_STATUS_LINK_DETERIORATION:{ struct notif_link_deterioration *x = ¬if->u.link_deterioration; + if (notif->size == sizeof(*x)) { IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE, "link deterioration: '%s' " MAC_FMT @@ -5027,6 +5069,7 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, memcmp(network->ssid, priv->essid, min(network->ssid_len, priv->essid_len)))) { char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; + strncpy(escaped, escape_essid(network->ssid, network->ssid_len), sizeof(escaped)); @@ -5043,16 +5086,16 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, * testing everything else. */ if (network->time_stamp[0] < match->network->time_stamp[0]) { - IPW_DEBUG_MERGE - ("Network '%s excluded because newer than current network.\n", - escape_essid(match->network->ssid, - match->network->ssid_len)); + IPW_DEBUG_MERGE("Network '%s excluded because newer than " + "current network.\n", + escape_essid(match->network->ssid, + match->network->ssid_len)); return 0; } else if (network->time_stamp[1] < match->network->time_stamp[1]) { - IPW_DEBUG_MERGE - ("Network '%s excluded because newer than current network.\n", - escape_essid(match->network->ssid, - match->network->ssid_len)); + IPW_DEBUG_MERGE("Network '%s excluded because newer than " + "current network.\n", + escape_essid(match->network->ssid, + match->network->ssid_len)); return 0; } @@ -5063,7 +5106,7 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, "because of age: %lums.\n", escape_essid(network->ssid, network->ssid_len), MAC_ARG(network->bssid), - (jiffies - network->last_scanned) / (HZ / 100)); + 1000 * (jiffies - network->last_scanned) / HZ); return 0; } @@ -5084,10 +5127,11 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, "because of privacy mismatch: %s != %s.\n", escape_essid(network->ssid, network->ssid_len), MAC_ARG(network->bssid), - priv->capability & CAP_PRIVACY_ON ? "on" : - "off", - network->capability & - WLAN_CAPABILITY_PRIVACY ? "on" : "off"); + priv-> + capability & CAP_PRIVACY_ON ? "on" : "off", + network-> + capability & WLAN_CAPABILITY_PRIVACY ? "on" : + "off"); return 0; } @@ -5151,8 +5195,8 @@ static void ipw_merge_adhoc_network(void *data) .network = priv->assoc_network }; - if ((priv->status & STATUS_ASSOCIATED) - && (priv->ieee->iw_mode == IW_MODE_ADHOC)) { + if ((priv->status & STATUS_ASSOCIATED) && + (priv->ieee->iw_mode == IW_MODE_ADHOC)) { /* First pass through ROAM process -- look for a better * network */ unsigned long flags; @@ -5184,7 +5228,6 @@ static void ipw_merge_adhoc_network(void *data) up(&priv->sem); return; } - } static int ipw_best_network(struct ipw_priv *priv, @@ -5270,7 +5313,7 @@ static int ipw_best_network(struct ipw_priv *priv, if (network->last_associate && time_after(network->last_associate + (HZ * 3UL), jiffies)) { IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " - "because of storming (%lu since last " + "because of storming (%lus since last " "assoc attempt).\n", escape_essid(network->ssid, network->ssid_len), MAC_ARG(network->bssid), @@ -5285,7 +5328,7 @@ static int ipw_best_network(struct ipw_priv *priv, "because of age: %lums.\n", escape_essid(network->ssid, network->ssid_len), MAC_ARG(network->bssid), - (jiffies - network->last_scanned) / (HZ / 100)); + 1000 * (jiffies - network->last_scanned) / HZ); return 0; } @@ -5369,6 +5412,9 @@ static int ipw_best_network(struct ipw_priv *priv, static void ipw_adhoc_create(struct ipw_priv *priv, struct ieee80211_network *network) { + const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); + int i; + /* * For the purposes of scanning, we can set our wireless mode * to trigger scans across combinations of bands, but when it @@ -5379,9 +5425,28 @@ static void ipw_adhoc_create(struct ipw_priv *priv, * chossen band. Attempting to create a new ad-hoc network * with an invalid channel for wireless mode will trigger a * FW fatal error. + * */ - if (!ieee80211_is_valid_channel(priv->ieee, priv->channel)) { - const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); + switch (ieee80211_is_valid_channel(priv->ieee, priv->channel)) { + case IEEE80211_52GHZ_BAND: + network->mode = IEEE_A; + i = ieee80211_channel_to_index(priv->ieee, priv->channel); + if (i == -1) + BUG(); + if (geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY) { + IPW_WARNING("Overriding invalid channel\n"); + priv->channel = geo->a[0].channel; + } + break; + + case IEEE80211_24GHZ_BAND: + if (priv->ieee->mode & IEEE_G) + network->mode = IEEE_G; + else + network->mode = IEEE_B; + break; + + default: IPW_WARNING("Overriding invalid channel\n"); if (priv->ieee->mode & IEEE_A) { network->mode = IEEE_A; @@ -5393,8 +5458,8 @@ static void ipw_adhoc_create(struct ipw_priv *priv, network->mode = IEEE_B; priv->channel = geo->bg[0].channel; } - } else - network->mode = priv->ieee->mode; + break; + } network->channel = priv->channel; priv->config |= CFG_ADHOC_PERSIST; @@ -5488,10 +5553,11 @@ static void ipw_set_hwcrypto_keys(struct ipw_priv *priv) { switch (priv->ieee->sec.level) { case SEC_LEVEL_3: - if (priv->ieee->sec.flags & SEC_ACTIVE_KEY) - ipw_send_tgi_tx_key(priv, - DCT_FLAG_EXT_SECURITY_CCM, - priv->ieee->sec.active_key); + if (!(priv->ieee->sec.flags & SEC_ACTIVE_KEY)) + break; + + ipw_send_tgi_tx_key(priv, DCT_FLAG_EXT_SECURITY_CCM, + priv->ieee->sec.active_key); ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_CCM); priv->sys_config.disable_unicast_decryption = 0; @@ -5502,10 +5568,11 @@ static void ipw_set_hwcrypto_keys(struct ipw_priv *priv) break; case SEC_LEVEL_2: - if (priv->ieee->sec.flags & SEC_ACTIVE_KEY) - ipw_send_tgi_tx_key(priv, - DCT_FLAG_EXT_SECURITY_TKIP, - priv->ieee->sec.active_key); + if (!(priv->ieee->sec.flags & SEC_ACTIVE_KEY)) + break; + + ipw_send_tgi_tx_key(priv, DCT_FLAG_EXT_SECURITY_TKIP, + priv->ieee->sec.active_key); priv->sys_config.disable_unicast_decryption = 1; priv->sys_config.disable_multicast_decryption = 1; @@ -5534,9 +5601,12 @@ static void ipw_adhoc_check(void *data) { struct ipw_priv *priv = data; - if (priv->missed_adhoc_beacons++ > priv->missed_beacon_threshold && + if (priv->missed_adhoc_beacons++ > priv->disassociate_threshold && !(priv->config & CFG_ADHOC_PERSIST)) { - IPW_DEBUG_SCAN("Disassociating due to missed beacons\n"); + IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF | + IPW_DL_STATE | IPW_DL_ASSOC, + "Missed beacon: %d - disassociate\n", + priv->missed_adhoc_beacons); ipw_remove_current_network(priv); ipw_disassociate(priv); return; @@ -5669,27 +5739,110 @@ static void ipw_abort_scan(struct ipw_priv *priv) IPW_DEBUG_HC("Request to abort scan failed.\n"); } -static int ipw_request_scan(struct ipw_priv *priv) +static void ipw_add_scan_channels(struct ipw_priv *priv, + struct ipw_scan_request_ext *scan, + int scan_type) { - struct ipw_scan_request_ext scan; int channel_index = 0; - int i, err = 0, scan_type; const struct ieee80211_geo *geo; -#ifdef CONFIG_IPW2200_MONITOR - u8 channel; -#endif - - down(&priv->sem); + int i; geo = ieee80211_get_geo(priv->ieee); + if (priv->ieee->freq_band & IEEE80211_52GHZ_BAND) { + int start = channel_index; + for (i = 0; i < geo->a_channels; i++) { + if ((priv->status & STATUS_ASSOCIATED) && + geo->a[i].channel == priv->channel) + continue; + channel_index++; + scan->channels_list[channel_index] = geo->a[i].channel; + ipw_set_scan_type(scan, channel_index, scan_type); + } + + if (start != channel_index) { + scan->channels_list[start] = (u8) (IPW_A_MODE << 6) | + (channel_index - start); + channel_index++; + } + } + + if (priv->ieee->freq_band & IEEE80211_24GHZ_BAND) { + int start = channel_index; + if (priv->config & CFG_SPEED_SCAN) { + u8 channels[IEEE80211_24GHZ_CHANNELS] = { + /* nop out the list */ + [0] = 0 + }; + + u8 channel; + while (channel_index < IPW_SCAN_CHANNELS) { + channel = + priv->speed_scan[priv->speed_scan_pos]; + if (channel == 0) { + priv->speed_scan_pos = 0; + channel = priv->speed_scan[0]; + } + if ((priv->status & STATUS_ASSOCIATED) && + channel == priv->channel) { + priv->speed_scan_pos++; + continue; + } + + /* If this channel has already been + * added in scan, break from loop + * and this will be the first channel + * in the next scan. + */ + if (channels[channel - 1] != 0) + break; + + channels[channel - 1] = 1; + priv->speed_scan_pos++; + channel_index++; + scan->channels_list[channel_index] = channel; + ipw_set_scan_type(scan, channel_index, + scan_type); + } + } else { + for (i = 0; i < geo->bg_channels; i++) { + if ((priv->status & STATUS_ASSOCIATED) && + geo->bg[i].channel == priv->channel) + continue; + channel_index++; + scan->channels_list[channel_index] = + geo->bg[i].channel; + ipw_set_scan_type(scan, channel_index, + scan_type); + } + } + + if (start != channel_index) { + scan->channels_list[start] = (u8) (IPW_B_MODE << 6) | + (channel_index - start); + } + } +} + +static int ipw_request_scan(struct ipw_priv *priv) +{ + struct ipw_scan_request_ext scan; + int err = 0, scan_type; + + if (!(priv->status & STATUS_INIT) || + (priv->status & STATUS_EXIT_PENDING)) + return 0; + + down(&priv->sem); + if (priv->status & STATUS_SCANNING) { IPW_DEBUG_HC("Concurrent scan requested. Ignoring.\n"); priv->status |= STATUS_SCAN_PENDING; goto done; } - if (priv->status & STATUS_SCAN_ABORTING) { + if (!(priv->status & STATUS_SCAN_FORCED) && + priv->status & STATUS_SCAN_ABORTING) { IPW_DEBUG_HC("Scan request while abort pending. Queuing.\n"); priv->status |= STATUS_SCAN_PENDING; goto done; @@ -5718,6 +5871,7 @@ static int ipw_request_scan(struct ipw_priv *priv) #ifdef CONFIG_IPW2200_MONITOR if (priv->ieee->iw_mode == IW_MODE_MONITOR) { + u8 channel; u8 band = 0; switch (ieee80211_is_valid_channel(priv->ieee, priv->channel)) { @@ -5768,91 +5922,10 @@ static int ipw_request_scan(struct ipw_priv *priv) } scan_type = IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN; - } else { + } else scan_type = IPW_SCAN_ACTIVE_BROADCAST_SCAN; - } - - /* Add channels to the scan list */ - if (priv->ieee->freq_band & IEEE80211_52GHZ_BAND) { - int start = channel_index; - for (i = 0; i < geo->a_channels; i++) { - if ((priv->status & STATUS_ASSOCIATED) && - geo->a[i].channel == priv->channel) - continue; - channel_index++; - scan.channels_list[channel_index] = - geo->a[i].channel; - ipw_set_scan_type(&scan, channel_index, - scan_type); - } - - if (start != channel_index) { - scan.channels_list[start] = - (u8) (IPW_A_MODE << 6) | (channel_index - - start); - channel_index++; - } - } - - if (priv->ieee->freq_band & IEEE80211_24GHZ_BAND) { - int start = channel_index; - if (priv->config & CFG_SPEED_SCAN) { - u8 channels[IEEE80211_24GHZ_CHANNELS] = { - /* nop out the list */ - [0] = 0 - }; - - u8 channel; - while (channel_index < IPW_SCAN_CHANNELS) { - channel = - priv->speed_scan[priv-> - speed_scan_pos]; - if (channel == 0) { - priv->speed_scan_pos = 0; - channel = priv->speed_scan[0]; - } - if ((priv->status & STATUS_ASSOCIATED) - && channel == priv->channel) { - priv->speed_scan_pos++; - continue; - } - - /* If this channel has already been - * added in scan, break from loop - * and this will be the first channel - * in the next scan. - */ - if (channels[channel - 1] != 0) - break; - - channels[channel - 1] = 1; - priv->speed_scan_pos++; - channel_index++; - scan.channels_list[channel_index] = - channel; - ipw_set_scan_type(&scan, channel_index, - scan_type); - } - } else { - for (i = 0; i < geo->bg_channels; i++) { - if ((priv->status & STATUS_ASSOCIATED) - && geo->bg[i].channel == - priv->channel) - continue; - channel_index++; - scan.channels_list[channel_index] = - geo->bg[i].channel; - ipw_set_scan_type(&scan, channel_index, - scan_type); - } - } - if (start != channel_index) { - scan.channels_list[start] = - (u8) (IPW_B_MODE << 6) | (channel_index - - start); - } - } + ipw_add_scan_channels(priv, &scan, scan_type); #ifdef CONFIG_IPW2200_MONITOR } #endif @@ -5865,7 +5938,8 @@ static int ipw_request_scan(struct ipw_priv *priv) priv->status |= STATUS_SCANNING; priv->status &= ~STATUS_SCAN_PENDING; - + queue_delayed_work(priv->workqueue, &priv->scan_check, + IPW_SCAN_CHECK_WATCHDOG); done: up(&priv->sem); return err; @@ -5879,8 +5953,8 @@ static void ipw_bg_abort_scan(void *data) up(&priv->sem); } -/* Support for wpa_supplicant. Will be replaced with WEXT once - * they get WPA support. */ +#if WIRELESS_EXT < 18 +/* Support for wpa_supplicant before WE-18, deprecated. */ /* following definitions must match definitions in driver_ipw.c */ @@ -5924,8 +5998,8 @@ struct ipw_param { u8 data[0]; } wpa_ie; struct { - int command; - int reason_code; + u32 command; + u32 reason_code; } mlme; struct { u8 alg[IPW_CRYPT_ALG_NAME_LEN]; @@ -5941,6 +6015,7 @@ struct ipw_param { }; /* end of driver_ipw.c code */ +#endif static int ipw_wpa_enable(struct ipw_priv *priv, int value) { @@ -5949,8 +6024,10 @@ static int ipw_wpa_enable(struct ipw_priv *priv, int value) return 0; } -#define AUTH_ALG_OPEN_SYSTEM 0x1 -#define AUTH_ALG_SHARED_KEY 0x2 +#if WIRELESS_EXT < 18 +#define IW_AUTH_ALG_OPEN_SYSTEM 0x1 +#define IW_AUTH_ALG_SHARED_KEY 0x2 +#endif static int ipw_wpa_set_auth_algs(struct ipw_priv *priv, int value) { @@ -5960,13 +6037,14 @@ static int ipw_wpa_set_auth_algs(struct ipw_priv *priv, int value) }; int ret = 0; - if (value & AUTH_ALG_SHARED_KEY) { + if (value & IW_AUTH_ALG_SHARED_KEY) { sec.auth_mode = WLAN_AUTH_SHARED_KEY; ieee->open_wep = 0; - } else { + } else if (value & IW_AUTH_ALG_OPEN_SYSTEM) { sec.auth_mode = WLAN_AUTH_OPEN; ieee->open_wep = 1; - } + } else + return -EINVAL; if (ieee->set_security) ieee->set_security(ieee->dev, &sec); @@ -5976,6 +6054,33 @@ static int ipw_wpa_set_auth_algs(struct ipw_priv *priv, int value) return ret; } +void ipw_wpa_assoc_frame(struct ipw_priv *priv, char *wpa_ie, int wpa_ie_len) +{ + /* make sure WPA is enabled */ + ipw_wpa_enable(priv, 1); + + ipw_disassociate(priv); +} + +static int ipw_set_rsn_capa(struct ipw_priv *priv, + char *capabilities, int length) +{ + struct host_cmd cmd = { + .cmd = IPW_CMD_RSN_CAPABILITIES, + .len = length, + }; + + IPW_DEBUG_HC("HOST_CMD_RSN_CAPABILITIES\n"); + + memcpy(cmd.param, capabilities, length); + if (ipw_send_cmd(priv, &cmd)) { + IPW_ERROR("failed to send HOST_CMD_RSN_CAPABILITIES command\n"); + return -1; + } + return 0; +} + +#if WIRELESS_EXT < 18 static int ipw_wpa_set_param(struct net_device *dev, u8 name, u32 value) { struct ipw_priv *priv = ieee80211_priv(dev); @@ -6081,32 +6186,6 @@ static int ipw_wpa_mlme(struct net_device *dev, int command, int reason) return ret; } -static int ipw_set_rsn_capa(struct ipw_priv *priv, - char *capabilities, int length) -{ - struct host_cmd cmd = { - .cmd = IPW_CMD_RSN_CAPABILITIES, - .len = length, - }; - - IPW_DEBUG_HC("HOST_CMD_RSN_CAPABILITIES\n"); - - memcpy(&cmd.param, capabilities, length); - if (ipw_send_cmd(priv, &cmd)) { - IPW_ERROR("failed to send HOST_CMD_RSN_CAPABILITIES command\n"); - return -1; - } - return 0; -} - -void ipw_wpa_assoc_frame(struct ipw_priv *priv, char *wpa_ie, int wpa_ie_len) -{ - /* make sure WPA is enabled */ - ipw_wpa_enable(priv, 1); - - ipw_disassociate(priv); -} - static int ipw_wpa_set_wpa_ie(struct net_device *dev, struct ipw_param *param, int plen) { @@ -6172,23 +6251,26 @@ static int ipw_wpa_set_encryption(struct net_device *dev, return -EINVAL; } + sec.flags |= SEC_ENABLED | SEC_ENCRYPT; if (strcmp(param->u.crypt.alg, "none") == 0) { if (crypt) { sec.enabled = 0; sec.encrypt = 0; sec.level = SEC_LEVEL_0; - sec.flags |= SEC_ENABLED | SEC_LEVEL; + sec.flags |= SEC_LEVEL; ieee80211_crypt_delayed_deinit(ieee, crypt); } goto done; } sec.enabled = 1; sec.encrypt = 1; - sec.flags |= SEC_ENABLED; /* IPW HW cannot build TKIP MIC, host decryption still needed. */ - if (!(ieee->host_encrypt || ieee->host_decrypt) && - strcmp(param->u.crypt.alg, "TKIP")) + if (strcmp(param->u.crypt.alg, "TKIP") == 0) + ieee->host_encrypt_msdu = 1; + + if (!(ieee->host_encrypt || ieee->host_encrypt_msdu || + ieee->host_decrypt)) goto skip_host_crypt; ops = ieee80211_get_crypto_ops(param->u.crypt.alg); @@ -6295,6 +6377,7 @@ static int ipw_wpa_set_encryption(struct net_device *dev, static int ipw_wpa_supplicant(struct net_device *dev, struct iw_point *p) { struct ipw_param *param; + struct ipw_priv *priv = ieee80211_priv(dev); int ret = 0; IPW_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length); @@ -6311,6 +6394,7 @@ static int ipw_wpa_supplicant(struct net_device *dev, struct iw_point *p) return -EFAULT; } + down(&priv->sem); switch (param->cmd) { case IPW_CMD_SET_WPA_PARAM: @@ -6337,35 +6421,336 @@ static int ipw_wpa_supplicant(struct net_device *dev, struct iw_point *p) ret = -EOPNOTSUPP; } + up(&priv->sem); if (ret == 0 && copy_to_user(p->pointer, param, p->length)) ret = -EFAULT; kfree(param); return ret; } - -#ifdef CONFIG_IPW_QOS - -/* QoS */ +#else /* -* get the modulation type of the current network or -* the card current mode -*/ -u8 ipw_qos_current_mode(struct ipw_priv * priv) + * WE-18 support + */ + +/* SIOCSIWGENIE */ +static int ipw_wx_set_genie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { - u8 mode = 0; + struct ipw_priv *priv = ieee80211_priv(dev); + struct ieee80211_device *ieee = priv->ieee; + u8 *buf; + int err = 0; - if (priv->status & STATUS_ASSOCIATED) { - unsigned long flags; + if (wrqu->data.length > MAX_WPA_IE_LEN || + (wrqu->data.length && extra == NULL)) + return -EINVAL; - spin_lock_irqsave(&priv->ieee->lock, flags); - mode = priv->assoc_network->mode; - spin_unlock_irqrestore(&priv->ieee->lock, flags); + //down(&priv->sem); + + //if (!ieee->wpa_enabled) { + // err = -EOPNOTSUPP; + // goto out; + //} + + if (wrqu->data.length) { + buf = kmalloc(wrqu->data.length, GFP_KERNEL); + if (buf == NULL) { + err = -ENOMEM; + goto out; + } + + memcpy(buf, extra, wrqu->data.length); + kfree(ieee->wpa_ie); + ieee->wpa_ie = buf; + ieee->wpa_ie_len = wrqu->data.length; } else { - mode = priv->ieee->mode; + kfree(ieee->wpa_ie); + ieee->wpa_ie = NULL; + ieee->wpa_ie_len = 0; } - IPW_DEBUG_QOS("QoS network/card mode %d \n", mode); - return mode; + + ipw_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len); + out: + //up(&priv->sem); + return err; +} + +/* SIOCGIWGENIE */ +static int ipw_wx_get_genie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ipw_priv *priv = ieee80211_priv(dev); + struct ieee80211_device *ieee = priv->ieee; + int err = 0; + + //down(&priv->sem); + + //if (!ieee->wpa_enabled) { + // err = -EOPNOTSUPP; + // goto out; + //} + + if (ieee->wpa_ie_len == 0 || ieee->wpa_ie == NULL) { + wrqu->data.length = 0; + goto out; + } + + if (wrqu->data.length < ieee->wpa_ie_len) { + err = -E2BIG; + goto out; + } + + wrqu->data.length = ieee->wpa_ie_len; + memcpy(extra, ieee->wpa_ie, ieee->wpa_ie_len); + + out: + //up(&priv->sem); + return err; +} + +/* SIOCSIWAUTH */ +static int ipw_wx_set_auth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ipw_priv *priv = ieee80211_priv(dev); + struct ieee80211_device *ieee = priv->ieee; + struct iw_param *param = &wrqu->param; + struct ieee80211_crypt_data *crypt; + unsigned long flags; + int ret = 0; + + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + case IW_AUTH_CIPHER_PAIRWISE: + case IW_AUTH_CIPHER_GROUP: + case IW_AUTH_KEY_MGMT: + /* + * ipw2200 does not use these parameters + */ + break; + + case IW_AUTH_TKIP_COUNTERMEASURES: + crypt = priv->ieee->crypt[priv->ieee->tx_keyidx]; + if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) { + IPW_WARNING("Can't set TKIP countermeasures: " + "crypt not set!\n"); + break; + } + + flags = crypt->ops->get_flags(crypt->priv); + + if (param->value) + flags |= IEEE80211_CRYPTO_TKIP_COUNTERMEASURES; + else + flags &= ~IEEE80211_CRYPTO_TKIP_COUNTERMEASURES; + + crypt->ops->set_flags(flags, crypt->priv); + + break; + + case IW_AUTH_DROP_UNENCRYPTED:{ + /* HACK: + * + * wpa_supplicant calls set_wpa_enabled when the driver + * is loaded and unloaded, regardless of if WPA is being + * used. No other calls are made which can be used to + * determine if encryption will be used or not prior to + * association being expected. If encryption is not being + * used, drop_unencrypted is set to false, else true -- we + * can use this to determine if the CAP_PRIVACY_ON bit should + * be set. + */ + struct ieee80211_security sec = { + .flags = SEC_ENABLED, + .enabled = param->value, + }; + priv->ieee->drop_unencrypted = param->value; + /* We only change SEC_LEVEL for open mode. Others + * are set by ipw_wpa_set_encryption. + */ + if (!param->value) { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_0; + } else { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_1; + } + if (priv->ieee->set_security) + priv->ieee->set_security(priv->ieee->dev, &sec); + break; + } + + case IW_AUTH_80211_AUTH_ALG: + ret = ipw_wpa_set_auth_algs(priv, param->value); + break; + + case IW_AUTH_WPA_ENABLED: + ret = ipw_wpa_enable(priv, param->value); + break; + + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + ieee->ieee802_1x = param->value; + break; + + //case IW_AUTH_ROAMING_CONTROL: + case IW_AUTH_PRIVACY_INVOKED: + ieee->privacy_invoked = param->value; + break; + + default: + return -EOPNOTSUPP; + } + return ret; +} + +/* SIOCGIWAUTH */ +static int ipw_wx_get_auth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ipw_priv *priv = ieee80211_priv(dev); + struct ieee80211_device *ieee = priv->ieee; + struct ieee80211_crypt_data *crypt; + struct iw_param *param = &wrqu->param; + int ret = 0; + + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + case IW_AUTH_CIPHER_PAIRWISE: + case IW_AUTH_CIPHER_GROUP: + case IW_AUTH_KEY_MGMT: + /* + * wpa_supplicant will control these internally + */ + ret = -EOPNOTSUPP; + break; + + case IW_AUTH_TKIP_COUNTERMEASURES: + crypt = priv->ieee->crypt[priv->ieee->tx_keyidx]; + if (!crypt || !crypt->ops->get_flags) { + IPW_WARNING("Can't get TKIP countermeasures: " + "crypt not set!\n"); + break; + } + + param->value = (crypt->ops->get_flags(crypt->priv) & + IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) ? 1 : 0; + + break; + + case IW_AUTH_DROP_UNENCRYPTED: + param->value = ieee->drop_unencrypted; + break; + + case IW_AUTH_80211_AUTH_ALG: + param->value = ieee->sec.auth_mode; + break; + + case IW_AUTH_WPA_ENABLED: + param->value = ieee->wpa_enabled; + break; + + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + param->value = ieee->ieee802_1x; + break; + + case IW_AUTH_ROAMING_CONTROL: + case IW_AUTH_PRIVACY_INVOKED: + param->value = ieee->privacy_invoked; + break; + + default: + return -EOPNOTSUPP; + } + return 0; +} + +/* SIOCSIWENCODEEXT */ +static int ipw_wx_set_encodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ipw_priv *priv = ieee80211_priv(dev); + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + + if (hwcrypto) { + /* IPW HW can't build TKIP MIC, host decryption still needed */ + if (ext->alg == IW_ENCODE_ALG_TKIP) { + priv->ieee->host_encrypt = 0; + priv->ieee->host_encrypt_msdu = 1; + priv->ieee->host_decrypt = 1; + } else { + priv->ieee->host_encrypt = 0; + priv->ieee->host_encrypt_msdu = 0; + priv->ieee->host_decrypt = 0; + } + } + + return ieee80211_wx_set_encodeext(priv->ieee, info, wrqu, extra); +} + +/* SIOCGIWENCODEEXT */ +static int ipw_wx_get_encodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ipw_priv *priv = ieee80211_priv(dev); + return ieee80211_wx_get_encodeext(priv->ieee, info, wrqu, extra); +} + +/* SIOCSIWMLME */ +static int ipw_wx_set_mlme(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ipw_priv *priv = ieee80211_priv(dev); + struct iw_mlme *mlme = (struct iw_mlme *)extra; + u16 reason; + + reason = cpu_to_le16(mlme->reason_code); + + switch (mlme->cmd) { + case IW_MLME_DEAUTH: + // silently ignore + break; + + case IW_MLME_DISASSOC: + ipw_disassociate(priv); + break; + + default: + return -EOPNOTSUPP; + } + return 0; +} +#endif + +#ifdef CONFIG_IPW_QOS + +/* QoS */ +/* +* get the modulation type of the current network or +* the card current mode +*/ +u8 ipw_qos_current_mode(struct ipw_priv * priv) +{ + u8 mode = 0; + + if (priv->status & STATUS_ASSOCIATED) { + unsigned long flags; + + spin_lock_irqsave(&priv->ieee->lock, flags); + mode = priv->assoc_network->mode; + spin_unlock_irqrestore(&priv->ieee->lock, flags); + } else { + mode = priv->ieee->mode; + } + IPW_DEBUG_QOS("QoS network/card mode %d \n", mode); + return mode; } /* @@ -6377,12 +6762,12 @@ static int ipw_qos_handle_probe_reponse(struct ipw_priv *priv, { u32 size = sizeof(struct ieee80211_qos_parameters); - if ((network->capability & WLAN_CAPABILITY_IBSS)) + if (network->capability & WLAN_CAPABILITY_IBSS) network->qos_data.active = network->qos_data.supported; if (network->flags & NETWORK_HAS_QOS_MASK) { - if (active_network - && (network->flags & NETWORK_HAS_QOS_PARAMETERS)) + if (active_network && + (network->flags & NETWORK_HAS_QOS_PARAMETERS)) network->qos_data.active = network->qos_data.supported; if ((network->qos_data.active == 1) && (active_network == 1) && @@ -6392,17 +6777,17 @@ static int ipw_qos_handle_probe_reponse(struct ipw_priv *priv, network->qos_data.old_param_count = network->qos_data.param_count; schedule_work(&priv->qos_activate); - IPW_DEBUG_QOS - ("QoS parameters change call qos_activate\n"); + IPW_DEBUG_QOS("QoS parameters change call " + "qos_activate\n"); } } else { - if ((priv->ieee->mode == IEEE_B) || (network->mode == IEEE_B)) { - memcpy(&(network->qos_data.parameters), + if ((priv->ieee->mode == IEEE_B) || (network->mode == IEEE_B)) + memcpy(&network->qos_data.parameters, &def_parameters_CCK, size); - } else { - memcpy(&(network->qos_data.parameters), + else + memcpy(&network->qos_data.parameters, &def_parameters_OFDM, size); - } + if ((network->qos_data.active == 1) && (active_network == 1)) { IPW_DEBUG_QOS("QoS was disabled call qos_activate \n"); schedule_work(&priv->qos_activate); @@ -6411,24 +6796,19 @@ static int ipw_qos_handle_probe_reponse(struct ipw_priv *priv, network->qos_data.active = 0; network->qos_data.supported = 0; } - if ((priv->status & STATUS_ASSOCIATED) - && (priv->ieee->iw_mode == IW_MODE_ADHOC) - && (active_network == 0)) { - - if (memcmp(network->bssid, priv->bssid, ETH_ALEN)) { - if ((network->capability & WLAN_CAPABILITY_IBSS) - && !(network->flags & NETWORK_EMPTY_ESSID)) { + if ((priv->status & STATUS_ASSOCIATED) && + (priv->ieee->iw_mode == IW_MODE_ADHOC) && (active_network == 0)) { + if (memcmp(network->bssid, priv->bssid, ETH_ALEN)) + if ((network->capability & WLAN_CAPABILITY_IBSS) && + !(network->flags & NETWORK_EMPTY_ESSID)) if ((network->ssid_len == - priv->assoc_network->ssid_len) - && !memcmp(network->ssid, - priv->assoc_network->ssid, - network->ssid_len)) { + priv->assoc_network->ssid_len) && + !memcmp(network->ssid, + priv->assoc_network->ssid, + network->ssid_len)) { queue_work(priv->workqueue, &priv->merge_networks); } - - } - } } return 0; @@ -6463,13 +6843,12 @@ static int ipw_qos_activate(struct ipw_priv *priv, } else active_one = &def_parameters_OFDM; - memcpy(&(qos_parameters[QOS_PARAM_SET_ACTIVE]), active_one, - size); + memcpy(&qos_parameters[QOS_PARAM_SET_ACTIVE], active_one, size); burst_duration = ipw_qos_get_burst_duration(priv); for (i = 0; i < QOS_QUEUE_NUM; i++) - qos_parameters[QOS_PARAM_SET_ACTIVE]. - tx_op_limit[i] = (u16) burst_duration; - } else if ((priv->ieee->iw_mode == IW_MODE_ADHOC)) { + qos_parameters[QOS_PARAM_SET_ACTIVE].tx_op_limit[i] = + (u16) burst_duration; + } else if (priv->ieee->iw_mode == IW_MODE_ADHOC) { if (type == IEEE_B) { IPW_DEBUG_QOS("QoS activate IBSS nework mode %d\n", type); @@ -6483,8 +6862,7 @@ static int ipw_qos_activate(struct ipw_priv *priv, else active_one = priv->qos_data.def_qos_parm_OFDM; } - memcpy(&(qos_parameters[QOS_PARAM_SET_ACTIVE]), active_one, - size); + memcpy(&qos_parameters[QOS_PARAM_SET_ACTIVE], active_one, size); } else { unsigned long flags; int active; @@ -6493,8 +6871,7 @@ static int ipw_qos_activate(struct ipw_priv *priv, active_one = &(qos_network_data->parameters); qos_network_data->old_param_count = qos_network_data->param_count; - memcpy(&(qos_parameters[QOS_PARAM_SET_ACTIVE]), active_one, - size); + memcpy(&qos_parameters[QOS_PARAM_SET_ACTIVE], active_one, size); active = qos_network_data->supported; spin_unlock_irqrestore(&priv->ieee->lock, flags); @@ -6507,10 +6884,9 @@ static int ipw_qos_activate(struct ipw_priv *priv, } IPW_DEBUG_QOS("QoS sending IPW_CMD_QOS_PARAMETERS\n"); - err = - ipw_send_qos_params_command(priv, - (struct ieee80211_qos_parameters *) - &(qos_parameters[0])); + err = ipw_send_qos_params_command(priv, + (struct ieee80211_qos_parameters *) + &(qos_parameters[0])); if (err) IPW_DEBUG_QOS("QoS IPW_CMD_QOS_PARAMETERS failed\n"); @@ -6603,21 +6979,19 @@ static int ipw_qos_association_resp(struct ipw_priv *priv, u32 size = sizeof(struct ieee80211_qos_parameters); int set_qos_param = 0; - if ((priv == NULL) || (network == NULL) - || (priv->assoc_network == NULL)) - + if ((priv == NULL) || (network == NULL) || + (priv->assoc_network == NULL)) return ret; if (!(priv->status & STATUS_ASSOCIATED)) return ret; - if ((priv->ieee->iw_mode != IW_MODE_INFRA)) { + if ((priv->ieee->iw_mode != IW_MODE_INFRA)) return ret; - } spin_lock_irqsave(&priv->ieee->lock, flags); if (network->flags & NETWORK_HAS_QOS_PARAMETERS) { - memcpy(&(priv->assoc_network->qos_data), &(network->qos_data), + memcpy(&priv->assoc_network->qos_data, &network->qos_data, sizeof(struct ieee80211_qos_data)); priv->assoc_network->qos_data.active = 1; if ((network->qos_data.old_param_count != @@ -6628,13 +7002,12 @@ static int ipw_qos_association_resp(struct ipw_priv *priv, } } else { - if ((network->mode == IEEE_B) || (priv->ieee->mode == IEEE_B)) { - memcpy(&(priv->assoc_network->qos_data.parameters), + if ((network->mode == IEEE_B) || (priv->ieee->mode == IEEE_B)) + memcpy(&priv->assoc_network->qos_data.parameters, &def_parameters_CCK, size); - } else { - memcpy(&(priv->assoc_network->qos_data.parameters), + else + memcpy(&priv->assoc_network->qos_data.parameters, &def_parameters_OFDM, size); - } priv->assoc_network->qos_data.active = 0; priv->assoc_network->qos_data.supported = 0; set_qos_param = 1; @@ -6655,11 +7028,11 @@ static u32 ipw_qos_get_burst_duration(struct ipw_priv *priv) if ((priv == NULL)) return 0; - if (!(priv->ieee->modulation & IEEE80211_OFDM_MODULATION)) { + if (!(priv->ieee->modulation & IEEE80211_OFDM_MODULATION)) ret = priv->qos_data.burst_duration_CCK; - } else { + else ret = priv->qos_data.burst_duration_OFDM; - } + return ret; } @@ -6736,9 +7109,9 @@ static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv, spin_unlock_irqrestore(&priv->ieee->lock, flags); - IPW_DEBUG_QOS - ("QoS %d network is QoS active %d supported %d unicast %d\n", - priv->qos_data.qos_enable, active, supported, unicast); + IPW_DEBUG_QOS("QoS %d network is QoS active %d supported %d " + "unicast %d\n", + priv->qos_data.qos_enable, active, supported, unicast); if (active && priv->qos_data.qos_enable) { ret = from_priority_to_tx_queue[priority]; tx_queue_id = ret - 1; @@ -6822,8 +7195,7 @@ static int ipw_send_qos_params_command(struct ipw_priv *priv, struct ieee80211_q return -1; } - memcpy(&cmd.param, qos_param, - (sizeof(struct ieee80211_qos_parameters) * 3)); + memcpy(cmd.param, qos_param, sizeof(*qos_param) * 3); if (ipw_send_cmd(priv, &cmd)) { IPW_ERROR("failed to send IPW_CMD_QOS_PARAMETERS command\n"); return -1; @@ -6845,7 +7217,7 @@ static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos return -1; } - memcpy(&cmd.param, qos_param, sizeof(*qos_param)); + memcpy(cmd.param, qos_param, sizeof(*qos_param)); if (ipw_send_cmd(priv, &cmd)) { IPW_ERROR("failed to send CMD_QOS_INFO command\n"); return -1; @@ -6919,6 +7291,11 @@ static int ipw_associate_network(struct ipw_priv *priv, ~WLAN_CAPABILITY_SHORT_PREAMBLE; } + /* Clear capability bits that aren't used in Ad Hoc */ + if (priv->ieee->iw_mode == IW_MODE_ADHOC) + priv->assoc_request.capability &= + ~WLAN_CAPABILITY_SHORT_SLOT_TIME; + IPW_DEBUG_ASSOC("%sssocation attempt: '%s', channel %d, " "802.11%c [%d], %s[:%s], enc=%s%s%s%c%c\n", roaming ? "Rea" : "A", @@ -6954,13 +7331,13 @@ static int ipw_associate_network(struct ipw_priv *priv, priv->assoc_request.assoc_tsf_lsw = network->time_stamp[0]; } - memcpy(&priv->assoc_request.bssid, network->bssid, ETH_ALEN); + memcpy(priv->assoc_request.bssid, network->bssid, ETH_ALEN); if (priv->ieee->iw_mode == IW_MODE_ADHOC) { memset(&priv->assoc_request.dest, 0xFF, ETH_ALEN); priv->assoc_request.atim_window = network->atim_window; } else { - memcpy(&priv->assoc_request.dest, network->bssid, ETH_ALEN); + memcpy(priv->assoc_request.dest, network->bssid, ETH_ALEN); priv->assoc_request.atim_window = 0; } @@ -7119,14 +7496,14 @@ static int ipw_associate(void *data) } if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { - IPW_DEBUG_ASSOC - ("Not attempting association (already in progress)\n"); + IPW_DEBUG_ASSOC("Not attempting association (already in " + "progress)\n"); return 0; } if (!ipw_is_init(priv) || (priv->status & STATUS_SCANNING)) { - IPW_DEBUG_ASSOC - ("Not attempting association (scanning or not initialized)\n"); + IPW_DEBUG_ASSOC("Not attempting association (scanning or not " + "initialized)\n"); return 0; } @@ -7285,9 +7662,8 @@ static inline int is_network_packet(struct ipw_priv *priv, if (!memcmp(header->addr2, priv->net_dev->dev_addr, ETH_ALEN)) return 0; - /* {broad,multi}cast packets to our IBSS go through */ - if (is_broadcast_ether_addr(header->addr1) || - is_multicast_ether_addr(header->addr1)) + /* multicast packets to our IBSS go through */ + if (is_multicast_ether_addr(header->addr1)) return !memcmp(header->addr3, priv->bssid, ETH_ALEN); /* packets to our adapter go through */ @@ -7300,8 +7676,7 @@ static inline int is_network_packet(struct ipw_priv *priv, return 0; /* {broad,multi}cast packets to our IBSS go through */ - if (is_broadcast_ether_addr(header->addr1) || - is_multicast_ether_addr(header->addr1)) + if (is_multicast_ether_addr(header->addr1)) return !memcmp(header->addr2, priv->bssid, ETH_ALEN); /* packets to our adapter go through */ @@ -7312,6 +7687,79 @@ static inline int is_network_packet(struct ipw_priv *priv, return 1; } +#define IPW_PACKET_RETRY_TIME HZ + +static inline int is_duplicate_packet(struct ipw_priv *priv, + struct ieee80211_hdr_4addr *header) +{ + u16 fc = le16_to_cpu(header->frame_ctl); + u16 sc = le16_to_cpu(header->seq_ctl); + u16 seq = WLAN_GET_SEQ_SEQ(sc); + u16 frag = WLAN_GET_SEQ_FRAG(sc); + u16 *last_seq, *last_frag; + unsigned long *last_time; + + switch (priv->ieee->iw_mode) { + case IW_MODE_ADHOC: + { + struct list_head *p; + struct ipw_ibss_seq *entry = NULL; + u8 *mac = header->addr2; + int index = mac[5] % IPW_IBSS_MAC_HASH_SIZE; + + __list_for_each(p, &priv->ibss_mac_hash[index]) { + entry = + list_entry(p, struct ipw_ibss_seq, list); + if (!memcmp(entry->mac, mac, ETH_ALEN)) + break; + } + if (p == &priv->ibss_mac_hash[index]) { + entry = kmalloc(sizeof(*entry), GFP_ATOMIC); + if (!entry) { + IPW_ERROR + ("Cannot malloc new mac entry\n"); + return 0; + } + memcpy(entry->mac, mac, ETH_ALEN); + entry->seq_num = seq; + entry->frag_num = frag; + entry->packet_time = jiffies; + list_add(&entry->list, + &priv->ibss_mac_hash[index]); + return 0; + } + last_seq = &entry->seq_num; + last_frag = &entry->frag_num; + last_time = &entry->packet_time; + break; + } + case IW_MODE_INFRA: + last_seq = &priv->last_seq_num; + last_frag = &priv->last_frag_num; + last_time = &priv->last_packet_time; + break; + default: + return 0; + } + if ((*last_seq == seq) && + time_after(*last_time + IPW_PACKET_RETRY_TIME, jiffies)) { + if (*last_frag == frag) + goto drop; + if (*last_frag + 1 != frag) + /* out-of-order fragment */ + goto drop; + *last_frag = frag; + } else + *last_seq = seq; + + *last_time = jiffies; + return 0; + + drop: + BUG_ON(!(fc & IEEE80211_FCTL_RETRY)); + return 1; +} + static void ipw_handle_mgmt_packet(struct ipw_priv *priv, struct ipw_rx_mem_buffer *rxb, struct ieee80211_rx_stats *stats) @@ -7481,7 +7929,10 @@ static void ipw_rx(struct ipw_priv *priv) break; case IEEE80211_FTYPE_DATA: - if (unlikely(!network_packet)) { + if (unlikely(!network_packet || + is_duplicate_packet(priv, + header))) + { IPW_DEBUG_DROP("Dropping: " MAC_FMT ", " MAC_FMT ", " @@ -7540,6 +7991,123 @@ static void ipw_rx(struct ipw_priv *priv) ipw_rx_queue_restock(priv); } +#define DEFAULT_RTS_THRESHOLD 2304U +#define MIN_RTS_THRESHOLD 1U +#define MAX_RTS_THRESHOLD 2304U +#define DEFAULT_BEACON_INTERVAL 100U +#define DEFAULT_SHORT_RETRY_LIMIT 7U +#define DEFAULT_LONG_RETRY_LIMIT 4U + +static int ipw_sw_reset(struct ipw_priv *priv, int init) +{ + int band, modulation; + int old_mode = priv->ieee->iw_mode; + + /* Initialize module parameter values here */ + priv->config = 0; + + /* We default to disabling the LED code as right now it causes + * too many systems to lock up... */ + if (!led) + priv->config |= CFG_NO_LED; + + if (associate) + priv->config |= CFG_ASSOCIATE; + else + IPW_DEBUG_INFO("Auto associate disabled.\n"); + + if (auto_create) + priv->config |= CFG_ADHOC_CREATE; + else + IPW_DEBUG_INFO("Auto adhoc creation disabled.\n"); + + if (disable) { + priv->status |= STATUS_RF_KILL_SW; + IPW_DEBUG_INFO("Radio disabled.\n"); + } + + if (channel != 0) { + priv->config |= CFG_STATIC_CHANNEL; + priv->channel = channel; + IPW_DEBUG_INFO("Bind to static channel %d\n", channel); + /* TODO: Validate that provided channel is in range */ + } +#ifdef CONFIG_IPW_QOS + ipw_qos_init(priv, qos_enable, qos_burst_enable, + burst_duration_CCK, burst_duration_OFDM); +#endif /* CONFIG_IPW_QOS */ + + switch (mode) { + case 1: + priv->ieee->iw_mode = IW_MODE_ADHOC; + priv->net_dev->type = ARPHRD_ETHER; + + break; +#ifdef CONFIG_IPW2200_MONITOR + case 2: + priv->ieee->iw_mode = IW_MODE_MONITOR; + priv->net_dev->type = ARPHRD_IEEE80211; + break; +#endif + default: + case 0: + priv->net_dev->type = ARPHRD_ETHER; + priv->ieee->iw_mode = IW_MODE_INFRA; + break; + } + + if (hwcrypto) { + priv->ieee->host_encrypt = 0; + priv->ieee->host_encrypt_msdu = 0; + priv->ieee->host_decrypt = 0; + } + IPW_DEBUG_INFO("Hardware crypto [%s]\n", hwcrypto ? "on" : "off"); + + if ((priv->pci_dev->device == 0x4223) || + (priv->pci_dev->device == 0x4224)) { + if (init) + printk(KERN_INFO DRV_NAME + ": Detected Intel PRO/Wireless 2915ABG Network " + "Connection\n"); + priv->ieee->abg_true = 1; + band = IEEE80211_52GHZ_BAND | IEEE80211_24GHZ_BAND; + modulation = IEEE80211_OFDM_MODULATION | + IEEE80211_CCK_MODULATION; + priv->adapter = IPW_2915ABG; + priv->ieee->mode = IEEE_A | IEEE_G | IEEE_B; + } else { + if (init) + printk(KERN_INFO DRV_NAME + ": Detected Intel PRO/Wireless 2200BG Network " + "Connection\n"); + + priv->ieee->abg_true = 0; + band = IEEE80211_24GHZ_BAND; + modulation = IEEE80211_OFDM_MODULATION | + IEEE80211_CCK_MODULATION; + priv->adapter = IPW_2200BG; + priv->ieee->mode = IEEE_G | IEEE_B; + } + + priv->ieee->freq_band = band; + priv->ieee->modulation = modulation; + + priv->rates_mask = IEEE80211_DEFAULT_RATES_MASK; + + priv->disassociate_threshold = IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT; + priv->roaming_threshold = IPW_MB_ROAMING_THRESHOLD_DEFAULT; + + priv->rts_threshold = DEFAULT_RTS_THRESHOLD; + priv->short_retry_limit = DEFAULT_SHORT_RETRY_LIMIT; + priv->long_retry_limit = DEFAULT_LONG_RETRY_LIMIT; + + /* If power management is turned on, default to AC mode */ + priv->power_mode = IPW_POWER_AC; + priv->tx_power = IPW_TX_POWER_DEFAULT; + + return old_mode == priv->ieee->mode; +} + /* * This file defines the Wireless Extension handlers. It does not * define any methods of hardware manipulation and relies on the @@ -7569,9 +8137,7 @@ static int ipw_wx_get_name(struct net_device *dev, } static int ipw_set_channel(struct ipw_priv *priv, u8 channel) -{ - int i; - +{ if (channel == 0) { IPW_DEBUG_INFO("Setting channel to ANY (0)\n"); priv->config &= ~CFG_STATIC_CHANNEL; @@ -7594,10 +8160,11 @@ static int ipw_set_channel(struct ipw_priv *priv, u8 channel) #ifdef CONFIG_IPW2200_MONITOR if (priv->ieee->iw_mode == IW_MODE_MONITOR) { + int i; if (priv->status & STATUS_SCANNING) { - IPW_DEBUG_SCAN("scan abort triggered due to " + IPW_DEBUG_SCAN("Scan abort triggered due to " "channel change.\n"); - queue_work(priv->workqueue, &priv->abort_scan); + ipw_abort_scan(priv); } for (i = 1000; i && (priv->status & STATUS_SCANNING); i--) @@ -7626,8 +8193,9 @@ static int ipw_wx_set_freq(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); + const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); struct iw_freq *fwrq = &wrqu->freq; - int ret = 0; + int ret = 0, i; u8 channel; if (fwrq->m == 0) { @@ -7637,7 +8205,6 @@ static int ipw_wx_set_freq(struct net_device *dev, up(&priv->sem); return ret; } - /* if setting by freq convert to channel */ if (fwrq->e == 1) { channel = ieee80211_freq_to_channel(priv->ieee, fwrq->m); @@ -7649,6 +8216,16 @@ static int ipw_wx_set_freq(struct net_device *dev, if (!ieee80211_is_valid_channel(priv->ieee, channel)) return -EINVAL; + if (priv->ieee->iw_mode == IW_MODE_ADHOC && priv->ieee->mode & IEEE_A) { + i = ieee80211_channel_to_index(priv->ieee, channel); + if (i == -1) + return -EINVAL; + if (geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY) { + IPW_DEBUG_WX("Invalid Ad-Hoc channel for 802.11a\n"); + return -EINVAL; + } + } + IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m); down(&priv->sem); ret = ipw_set_channel(priv, channel); @@ -7704,6 +8281,9 @@ static int ipw_wx_set_mode(struct net_device *dev, return 0; down(&priv->sem); + + ipw_sw_reset(priv, 0); + #ifdef CONFIG_IPW2200_MONITOR if (priv->ieee->iw_mode == IW_MODE_MONITOR) priv->net_dev->type = ARPHRD_ETHER; @@ -7712,17 +8292,9 @@ static int ipw_wx_set_mode(struct net_device *dev, priv->net_dev->type = ARPHRD_IEEE80211; #endif /* CONFIG_IPW2200_MONITOR */ -#ifdef CONFIG_PM /* Free the existing firmware and reset the fw_loaded * flag so ipw_load() will bring in the new firmawre */ - if (fw_loaded) - fw_loaded = 0; - - release_firmware(bootfw); - release_firmware(ucode); - release_firmware(firmware); - bootfw = ucode = firmware = NULL; -#endif + free_firmware(); priv->ieee->iw_mode = wrqu->mode; @@ -7743,13 +8315,6 @@ static int ipw_wx_get_mode(struct net_device *dev, return 0; } -#define DEFAULT_RTS_THRESHOLD 2304U -#define MIN_RTS_THRESHOLD 1U -#define MAX_RTS_THRESHOLD 2304U -#define DEFAULT_BEACON_INTERVAL 100U -#define DEFAULT_SHORT_RETRY_LIMIT 7U -#define DEFAULT_LONG_RETRY_LIMIT 4U - /* Values are in microsecond */ static const s32 timeout_duration[] = { 350000, @@ -7900,7 +8465,7 @@ static int ipw_wx_get_wap(struct net_device *dev, if (priv->config & CFG_STATIC_BSSID || priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { wrqu->ap_addr.sa_family = ARPHRD_ETHER; - memcpy(wrqu->ap_addr.sa_data, &priv->bssid, ETH_ALEN); + memcpy(wrqu->ap_addr.sa_data, priv->bssid, ETH_ALEN); } else memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN); @@ -7924,10 +8489,12 @@ static int ipw_wx_set_essid(struct net_device *dev, } if (length == 0) { IPW_DEBUG_WX("Setting ESSID to ANY\n"); - priv->config &= ~CFG_STATIC_ESSID; - if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING))) { + if ((priv->config & CFG_STATIC_ESSID) && + !(priv->status & (STATUS_ASSOCIATED | + STATUS_ASSOCIATING))) { IPW_DEBUG_ASSOC("Attempting to associate with new " "parameters.\n"); + priv->config &= ~CFG_STATIC_ESSID; ipw_associate(priv); } up(&priv->sem); @@ -8202,7 +8769,7 @@ static int ipw_wx_set_txpow(struct net_device *dev, } if ((wrqu->power.value > IPW_TX_POWER_MAX) || - (wrqu->power.value < -IPW_TX_POWER_MAX) || !wrqu->power.fixed) { + (wrqu->power.value < IPW_TX_POWER_MIN)) { up(&priv->sem); return -EINVAL; } @@ -8295,23 +8862,149 @@ static int ipw_wx_set_retry(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { - IPW_DEBUG_WX("0x%p, 0x%p, 0x%p\n", dev, info, wrqu); - return -EOPNOTSUPP; + struct ipw_priv *priv = ieee80211_priv(dev); + + if (wrqu->retry.flags & IW_RETRY_LIFETIME || wrqu->retry.disabled) + return -EINVAL; + + if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) + return 0; + + if (wrqu->retry.value < 0 || wrqu->retry.value > 255) + return -EINVAL; + + down(&priv->sem); + if (wrqu->retry.flags & IW_RETRY_MIN) + priv->short_retry_limit = (u8) wrqu->retry.value; + else if (wrqu->retry.flags & IW_RETRY_MAX) + priv->long_retry_limit = (u8) wrqu->retry.value; + else { + priv->short_retry_limit = (u8) wrqu->retry.value; + priv->long_retry_limit = (u8) wrqu->retry.value; + } + + ipw_send_retry_limit(priv, priv->short_retry_limit, + priv->long_retry_limit); + up(&priv->sem); + IPW_DEBUG_WX("SET retry limit -> short:%d long:%d\n", + priv->short_retry_limit, priv->long_retry_limit); + return 0; } static int ipw_wx_get_retry(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { - IPW_DEBUG_WX("0x%p, 0x%p, 0x%p\n", dev, info, wrqu); - return -EOPNOTSUPP; + struct ipw_priv *priv = ieee80211_priv(dev); + + down(&priv->sem); + wrqu->retry.disabled = 0; + + if ((wrqu->retry.flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { + up(&priv->sem); + return -EINVAL; + } + + if (wrqu->retry.flags & IW_RETRY_MAX) { + wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; + wrqu->retry.value = priv->long_retry_limit; + } else if (wrqu->retry.flags & IW_RETRY_MIN) { + wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN; + wrqu->retry.value = priv->short_retry_limit; + } else { + wrqu->retry.flags = IW_RETRY_LIMIT; + wrqu->retry.value = priv->short_retry_limit; + } + up(&priv->sem); + + IPW_DEBUG_WX("GET retry -> %d \n", wrqu->retry.value); + + return 0; +} + +#if WIRELESS_EXT > 17 +static int ipw_request_direct_scan(struct ipw_priv *priv, char *essid, + int essid_len) +{ + struct ipw_scan_request_ext scan; + int err = 0, scan_type; + + down(&priv->sem); + + if (priv->status & STATUS_RF_KILL_MASK) { + IPW_DEBUG_HC("Aborting scan due to RF kill activation\n"); + priv->status |= STATUS_SCAN_PENDING; + goto done; + } + + IPW_DEBUG_HC("starting request direct scan!\n"); + + if (priv->status & (STATUS_SCANNING | STATUS_SCAN_ABORTING)) { + err = wait_event_interruptible(priv->wait_state, + !(priv-> + status & (STATUS_SCANNING | + STATUS_SCAN_ABORTING))); + if (err) { + IPW_DEBUG_HC("aborting direct scan"); + goto done; + } + } + memset(&scan, 0, sizeof(scan)); + + if (priv->config & CFG_SPEED_SCAN) + scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = + cpu_to_le16(30); + else + scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = + cpu_to_le16(20); + + scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] = + cpu_to_le16(20); + scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(20); + scan.dwell_time[IPW_SCAN_ACTIVE_DIRECT_SCAN] = cpu_to_le16(20); + + scan.full_scan_index = cpu_to_le32(ieee80211_get_scans(priv->ieee)); + + err = ipw_send_ssid(priv, essid, essid_len); + if (err) { + IPW_DEBUG_HC("Attempt to send SSID command failed\n"); + goto done; + } + scan_type = IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN; + + ipw_add_scan_channels(priv, &scan, scan_type); + + err = ipw_send_scan_request_ext(priv, &scan); + if (err) { + IPW_DEBUG_HC("Sending scan command failed: %08X\n", err); + goto done; + } + + priv->status |= STATUS_SCANNING; + + done: + up(&priv->sem); + return err; } +#endif /* WIRELESS_EXT > 17 */ static int ipw_wx_set_scan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); +#if WIRELESS_EXT > 17 + struct iw_scan_req *req = NULL; + if (wrqu->data.length + && wrqu->data.length == sizeof(struct iw_scan_req)) { + req = (struct iw_scan_req *)extra; + if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { + ipw_request_direct_scan(priv, req->essid, + req->essid_len); + return 0; + } + } +#endif IPW_DEBUG_WX("Start scan\n"); queue_work(priv->workqueue, &priv->request_scan); @@ -8332,7 +9025,13 @@ static int ipw_wx_set_encode(struct net_device *dev, union iwreq_data *wrqu, char *key) { struct ipw_priv *priv = ieee80211_priv(dev); - return ieee80211_wx_set_encode(priv->ieee, info, wrqu, key); + int ret; + + down(&priv->sem); + ret = ieee80211_wx_set_encode(priv->ieee, info, wrqu, key); + up(&priv->sem); + + return ret; } static int ipw_wx_get_encode(struct net_device *dev, @@ -8665,110 +9364,6 @@ static int ipw_wx_reset(struct net_device *dev, return 0; } -static void ipw_sw_reset(struct ipw_priv *priv, int init) -{ - int band, modulation; - - /* Initialize module parameter values here */ - priv->config = 0; - - /* We default to disabling the LED code as right now it causes - * too many systems to lock up... */ - if (!led) - priv->config |= CFG_NO_LED; - - if (associate) - priv->config |= CFG_ASSOCIATE; - else - IPW_DEBUG_INFO("Auto associate disabled.\n"); - - if (auto_create) - priv->config |= CFG_ADHOC_CREATE; - else - IPW_DEBUG_INFO("Auto adhoc creation disabled.\n"); - - if (disable) { - priv->status |= STATUS_RF_KILL_SW; - IPW_DEBUG_INFO("Radio disabled.\n"); - } - - if (channel != 0) { - priv->config |= CFG_STATIC_CHANNEL; - priv->channel = channel; - IPW_DEBUG_INFO("Bind to static channel %d\n", channel); - /* TODO: Validate that provided channel is in range */ - } -#ifdef CONFIG_IPW_QOS - ipw_qos_init(priv, qos_enable, qos_burst_enable, - burst_duration_CCK, burst_duration_OFDM); -#endif /* CONFIG_IPW_QOS */ - - switch (mode) { - case 1: - priv->ieee->iw_mode = IW_MODE_ADHOC; - priv->net_dev->type = ARPHRD_ETHER; - - break; -#ifdef CONFIG_IPW2200_MONITOR - case 2: - priv->ieee->iw_mode = IW_MODE_MONITOR; - priv->net_dev->type = ARPHRD_IEEE80211; - break; -#endif - default: - case 0: - priv->net_dev->type = ARPHRD_ETHER; - priv->ieee->iw_mode = IW_MODE_INFRA; - break; - } - - if (hwcrypto) { - priv->ieee->host_encrypt = 0; - priv->ieee->host_decrypt = 0; - } - IPW_DEBUG_INFO("Hardware crypto [%s]\n", hwcrypto ? "on" : "off"); - - if ((priv->pci_dev->device == 0x4223) || - (priv->pci_dev->device == 0x4224)) { - if (init) - printk(KERN_INFO DRV_NAME - ": Detected Intel PRO/Wireless 2915ABG Network " - "Connection\n"); - priv->ieee->abg_true = 1; - band = IEEE80211_52GHZ_BAND | IEEE80211_24GHZ_BAND; - modulation = IEEE80211_OFDM_MODULATION | - IEEE80211_CCK_MODULATION; - priv->adapter = IPW_2915ABG; - priv->ieee->mode = IEEE_A | IEEE_G | IEEE_B; - } else { - if (init) - printk(KERN_INFO DRV_NAME - ": Detected Intel PRO/Wireless 2200BG Network " - "Connection\n"); - - priv->ieee->abg_true = 0; - band = IEEE80211_24GHZ_BAND; - modulation = IEEE80211_OFDM_MODULATION | - IEEE80211_CCK_MODULATION; - priv->adapter = IPW_2200BG; - priv->ieee->mode = IEEE_G | IEEE_B; - } - - priv->ieee->freq_band = band; - priv->ieee->modulation = modulation; - - priv->rates_mask = IEEE80211_DEFAULT_RATES_MASK; - - priv->missed_beacon_threshold = IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT; - priv->roaming_threshold = IPW_MB_ROAMING_THRESHOLD_DEFAULT; - - priv->rts_threshold = DEFAULT_RTS_THRESHOLD; - - /* If power management is turned on, default to AC mode */ - priv->power_mode = IPW_POWER_AC; - priv->tx_power = IPW_TX_POWER_DEFAULT; -} - static int ipw_wx_sw_reset(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -8779,12 +9374,17 @@ static int ipw_wx_sw_reset(struct net_device *dev, .flags = IW_ENCODE_DISABLED, }, }; + int ret; IPW_DEBUG_WX("SW_RESET\n"); down(&priv->sem); - ipw_sw_reset(priv, 0); + ret = ipw_sw_reset(priv, 0); + if (!ret) { + free_firmware(); + ipw_adapter_restart(priv); + } /* The SW reset bit might have been toggled on by the 'disable' * module parameter, so take appropriate action */ @@ -8842,6 +9442,15 @@ static iw_handler ipw_wx_handlers[] = { IW_IOCTL(SIOCGIWSPY) = iw_handler_get_spy, IW_IOCTL(SIOCSIWTHRSPY) = iw_handler_set_thrspy, IW_IOCTL(SIOCGIWTHRSPY) = iw_handler_get_thrspy, +#if WIRELESS_EXT > 17 + IW_IOCTL(SIOCSIWGENIE) = ipw_wx_set_genie, + IW_IOCTL(SIOCGIWGENIE) = ipw_wx_get_genie, + IW_IOCTL(SIOCSIWMLME) = ipw_wx_set_mlme, + IW_IOCTL(SIOCSIWAUTH) = ipw_wx_set_auth, + IW_IOCTL(SIOCGIWAUTH) = ipw_wx_get_auth, + IW_IOCTL(SIOCSIWENCODEEXT) = ipw_wx_set_encodeext, + IW_IOCTL(SIOCGIWENCODEEXT) = ipw_wx_get_encodeext, +#endif }; enum { @@ -8934,7 +9543,7 @@ static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev) wstats = &priv->wstats; /* if hw is disabled, then ipw_get_ordinal() can't be called. - * ipw2100_wx_wireless_stats seems to be called before fw is + * netdev->get_wireless_stats seems to be called before fw is * initialized. STATUS_ASSOCIATED will only be set if the hw is up * and associated; if not associcated, the values are all meaningless * anyway, so set them all to NULL and INVALID */ @@ -9036,8 +9645,7 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, switch (priv->ieee->iw_mode) { case IW_MODE_ADHOC: hdr_len = IEEE80211_3ADDR_LEN; - unicast = !is_broadcast_ether_addr(hdr->addr1) && - !is_multicast_ether_addr(hdr->addr1); + unicast = !is_multicast_ether_addr(hdr->addr1); id = ipw_find_station(priv, hdr->addr1); if (id == IPW_INVALID_STATION) { id = ipw_add_station(priv, hdr->addr1); @@ -9052,8 +9660,7 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, case IW_MODE_INFRA: default: - unicast = !is_broadcast_ether_addr(hdr->addr3) && - !is_multicast_ether_addr(hdr->addr3); + unicast = !is_multicast_ether_addr(hdr->addr3); hdr_len = IEEE80211_3ADDR_LEN; id = 0; break; @@ -9176,6 +9783,7 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, tfd->u.data.chunk_len[i] = cpu_to_le16(remaining_bytes); for (j = i; j < txb->nr_frags; j++) { int size = txb->fragments[j]->len - hdr_len; + printk(KERN_INFO "Adding frag %d %d...\n", j, size); memcpy(skb_put(skb, size), @@ -9307,7 +9915,7 @@ static int ipw_ethtool_get_eeprom(struct net_device *dev, if (eeprom->offset + eeprom->len > IPW_EEPROM_IMAGE_SIZE) return -EINVAL; down(&p->sem); - memcpy(bytes, &((u8 *) p->eeprom)[eeprom->offset], eeprom->len); + memcpy(bytes, &p->eeprom[eeprom->offset], eeprom->len); up(&p->sem); return 0; } @@ -9321,7 +9929,7 @@ static int ipw_ethtool_set_eeprom(struct net_device *dev, if (eeprom->offset + eeprom->len > IPW_EEPROM_IMAGE_SIZE) return -EINVAL; down(&p->sem); - memcpy(&((u8 *) p->eeprom)[eeprom->offset], bytes, eeprom->len); + memcpy(&p->eeprom[eeprom->offset], bytes, eeprom->len); for (i = IPW_EEPROM_DATA; i < IPW_EEPROM_DATA + IPW_EEPROM_IMAGE_SIZE; i++) ipw_write8(p, i, p->eeprom[i]); @@ -9427,6 +10035,10 @@ static void ipw_bg_rf_kill(void *data) void ipw_link_up(struct ipw_priv *priv) { + priv->last_seq_num = -1; + priv->last_frag_num = -1; + priv->last_packet_time = 0; + netif_carrier_on(priv->net_dev); if (netif_queue_stopped(priv->net_dev)) { IPW_DEBUG_NOTIF("waking queue\n"); @@ -9470,8 +10082,10 @@ void ipw_link_down(struct ipw_priv *priv) ipw_reset_stats(priv); - /* Queue up another scan... */ - queue_work(priv->workqueue, &priv->request_scan); + if (!(priv->status & STATUS_EXIT_PENDING)) { + /* Queue up another scan... */ + queue_work(priv->workqueue, &priv->request_scan); + } } static void ipw_bg_link_down(void *data) @@ -9488,6 +10102,7 @@ static int ipw_setup_deferred_work(struct ipw_priv *priv) priv->workqueue = create_workqueue(DRV_NAME); init_waitqueue_head(&priv->wait_command_queue); + init_waitqueue_head(&priv->wait_state); INIT_WORK(&priv->adhoc_check, ipw_bg_adhoc_check, priv); INIT_WORK(&priv->associate, ipw_bg_associate, priv); @@ -9531,9 +10146,9 @@ static void shim__set_security(struct net_device *dev, { struct ipw_priv *priv = ieee80211_priv(dev); int i; - down(&priv->sem); for (i = 0; i < 4; i++) { if (sec->flags & (1 << i)) { + priv->ieee->sec.encode_alg[i] = sec->encode_alg[i]; priv->ieee->sec.key_sizes[i] = sec->key_sizes[i]; if (sec->key_sizes[i] == 0) priv->ieee->sec.flags &= ~(1 << i); @@ -9577,7 +10192,9 @@ static void shim__set_security(struct net_device *dev, else priv->capability &= ~CAP_PRIVACY_ON; } - priv->ieee->sec.encrypt = sec->encrypt; + + if (sec->flags & SEC_ENCRYPT) + priv->ieee->sec.encrypt = sec->encrypt; if (sec->flags & SEC_LEVEL && priv->ieee->sec.level != sec->level) { priv->ieee->sec.level = sec->level; @@ -9602,7 +10219,6 @@ static void shim__set_security(struct net_device *dev, ipw_disassociate(priv); } #endif - up(&priv->sem); } static int init_supported_rates(struct ipw_priv *priv, @@ -9707,6 +10323,24 @@ static int ipw_config(struct ipw_priv *priv) return -EIO; } +static const struct ieee80211_geo ipw_geo = { + "---", + .bg_channels = 11, + .bg = {{2412, 1}, {2417, 2}, {2422, 3}, + {2427, 4}, {2432, 5}, {2437, 6}, + {2442, 7}, {2447, 8}, {2452, 9}, + {2457, 10}, {2462, 11}}, + .a_channels = 8, + .a = {{5180, 36}, + {5200, 40}, + {5220, 44}, + {5240, 48}, + {5260, 52, IEEE80211_CH_PASSIVE_ONLY}, + {5280, 56, IEEE80211_CH_PASSIVE_ONLY}, + {5300, 60, IEEE80211_CH_PASSIVE_ONLY}, + {5320, 64, IEEE80211_CH_PASSIVE_ONLY}}, +}; + #define MAX_HW_RESTARTS 5 static int ipw_up(struct ipw_priv *priv) { @@ -9729,6 +10363,10 @@ static int ipw_up(struct ipw_priv *priv) eeprom_parse_mac(priv, priv->mac_addr); memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN); + memcpy(priv->country, &priv->eeprom[EEPROM_COUNTRY_CODE], 3); + priv->country[3] = '\0'; + ieee80211_set_geo(priv->ieee, &ipw_geo); + if (priv->status & STATUS_RF_KILL_SW) { IPW_WARNING("Radio disabled by module parameter.\n"); return 0; @@ -9748,6 +10386,14 @@ static int ipw_up(struct ipw_priv *priv) ipw_led_radio_on(priv); priv->notif_missed_beacons = 0; priv->status |= STATUS_INIT; + + /* Set hardware WEP key if it is configured. */ + if ((priv->capability & CAP_PRIVACY_ON) && + (priv->ieee->sec.level == SEC_LEVEL_1) && + !(priv->ieee->host_encrypt || + priv->ieee->host_decrypt)) + ipw_set_hwcrypto_keys(priv); + return 0; } @@ -9846,6 +10492,7 @@ static void ipw_bg_down(void *data) up(&priv->sem); } +#if WIRELESS_EXT < 18 static int ipw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct iwreq *wrq = (struct iwreq *)rq; @@ -9861,6 +10508,7 @@ static int ipw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return -EOPNOTSUPP; } +#endif /* Called by register_netdev() */ static int ipw_net_init(struct net_device *dev) @@ -9942,6 +10590,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) void __iomem *base; u32 length, val; struct ipw_priv *priv; + int i; net_dev = alloc_ieee80211(sizeof(struct ipw_priv)); if (net_dev == NULL) { @@ -9958,6 +10607,8 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ipw_debug_level = debug; #endif spin_lock_init(&priv->lock); + for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++) + INIT_LIST_HEAD(&priv->ibss_mac_hash[i]); init_MUTEX(&priv->sem); if (pci_enable_device(pdev)) { @@ -10035,7 +10686,9 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) net_dev->open = ipw_net_open; net_dev->stop = ipw_net_stop; net_dev->init = ipw_net_init; +#if WIRELESS_EXT < 18 net_dev->do_ioctl = ipw_ioctl; +#endif net_dev->get_stats = ipw_net_get_stats; net_dev->set_multicast_list = ipw_net_set_multicast_list; net_dev->set_mac_address = ipw_net_set_mac_address; @@ -10086,13 +10739,18 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) static void ipw_pci_remove(struct pci_dev *pdev) { struct ipw_priv *priv = pci_get_drvdata(pdev); + struct list_head *p, *q; + int i; if (!priv) return; down(&priv->sem); + + priv->status |= STATUS_EXIT_PENDING; ipw_down(priv); sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group); + up(&priv->sem); unregister_netdev(priv->net_dev); @@ -10113,21 +10771,21 @@ static void ipw_pci_remove(struct pci_dev *pdev) destroy_workqueue(priv->workqueue); priv->workqueue = NULL; + /* Free MAC hash list for ADHOC */ + for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++) { + list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) { + kfree(list_entry(p, struct ipw_ibss_seq, list)); + list_del(p); + } + } + free_irq(pdev->irq, priv); iounmap(priv->hw_base); pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); free_ieee80211(priv->net_dev); - -#ifdef CONFIG_PM - if (fw_loaded) { - release_firmware(bootfw); - release_firmware(ucode); - release_firmware(firmware); - fw_loaded = 0; - } -#endif + free_firmware(); } #ifdef CONFIG_PM diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index 9dbd73a4209..915f469fa1d 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -244,7 +244,7 @@ enum connection_manager_assoc_states { #define HOST_NOTIFICATION_S36_MEASUREMENT_REFUSED 31 #define HOST_NOTIFICATION_STATUS_BEACON_MISSING 1 -#define IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT 24 +#define IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT 9 #define IPW_MB_ROAMING_THRESHOLD_DEFAULT 8 #define IPW_REAL_RATE_RX_PACKET_THRESHOLD 300 @@ -699,8 +699,8 @@ struct ipw_rx_packet { } __attribute__ ((packed)); #define IPW_RX_NOTIFICATION_SIZE sizeof(struct ipw_rx_header) + 12 -#define IPW_RX_FRAME_SIZE sizeof(struct ipw_rx_header) + \ - sizeof(struct ipw_rx_frame) +#define IPW_RX_FRAME_SIZE (unsigned int)(sizeof(struct ipw_rx_header) + \ + sizeof(struct ipw_rx_frame)) struct ipw_rx_mem_buffer { dma_addr_t dma_addr; @@ -1029,6 +1029,7 @@ struct ipw_cmd { #define STATUS_SCAN_PENDING (1<<20) #define STATUS_SCANNING (1<<21) #define STATUS_SCAN_ABORTING (1<<22) +#define STATUS_SCAN_FORCED (1<<23) #define STATUS_LED_LINK_ON (1<<24) #define STATUS_LED_ACT_ON (1<<25) @@ -1074,6 +1075,15 @@ struct average { }; #define MAX_SPEED_SCAN 100 +#define IPW_IBSS_MAC_HASH_SIZE 31 + +struct ipw_ibss_seq { + u8 mac[ETH_ALEN]; + u16 seq_num; + u16 frag_num; + unsigned long packet_time; + struct list_head list; +}; struct ipw_priv { /* ieee device used by generic ieee processing code */ @@ -1115,7 +1125,7 @@ struct ipw_priv { int rx_bufs_min; /**< minimum number of bufs in Rx queue */ int rx_pend_max; /**< maximum pending buffers for one IRQ */ u32 hcmd_seq; /**< sequence number for hcmd */ - u32 missed_beacon_threshold; + u32 disassociate_threshold; u32 roaming_threshold; struct ipw_associate assoc_request; @@ -1156,6 +1166,8 @@ struct ipw_priv { u8 mac_addr[ETH_ALEN]; u8 num_stations; u8 stations[MAX_STATIONS][ETH_ALEN]; + u8 short_retry_limit; + u8 long_retry_limit; u32 notif_missed_beacons; @@ -1176,8 +1188,14 @@ struct ipw_priv { u8 speed_scan[MAX_SPEED_SCAN]; u8 speed_scan_pos; + u16 last_seq_num; + u16 last_frag_num; + unsigned long last_packet_time; + struct list_head ibss_mac_hash[IPW_IBSS_MAC_HASH_SIZE]; + /* eeprom */ u8 eeprom[0x100]; /* 256 bytes of eeprom */ + u8 country[4]; int eeprom_delay; struct iw_statistics wstats; -- cgit v1.2.3 From a2d73e60bb018da74ba508943c79c83659f3a883 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Wed, 13 Jul 2005 12:24:51 -0500 Subject: Fix hardware encryption (both WEP and AES) doesn't work with fragmentation. Firmware sends received packets with double sized ICV/MIC. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 1b6f0277a3e..8f7e9ac37f8 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -7587,7 +7587,10 @@ static void ipw_rebuild_decrypted_skb(struct ipw_priv *priv, memmove(skb->data + IEEE80211_3ADDR_LEN, skb->data + IEEE80211_3ADDR_LEN + 8, skb->len - IEEE80211_3ADDR_LEN - 8); - skb_trim(skb, skb->len - 8); /* MIC */ + if (fc & IEEE80211_FCTL_MOREFRAGS) + skb_trim(skb, skb->len - 16); /* 2*MIC */ + else + skb_trim(skb, skb->len - 8); /* MIC */ break; case SEC_LEVEL_2: break; @@ -7596,7 +7599,10 @@ static void ipw_rebuild_decrypted_skb(struct ipw_priv *priv, memmove(skb->data + IEEE80211_3ADDR_LEN, skb->data + IEEE80211_3ADDR_LEN + 4, skb->len - IEEE80211_3ADDR_LEN - 4); - skb_trim(skb, skb->len - 4); /* ICV */ + if (fc & IEEE80211_FCTL_MOREFRAGS) + skb_trim(skb, skb->len - 8); /* 2*ICV */ + else + skb_trim(skb, skb->len - 4); /* ICV */ break; case SEC_LEVEL_0: break; -- cgit v1.2.3 From f57ce7ce9c7498fe9c4090aaf389c89f3bd70f7e Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Wed, 13 Jul 2005 12:22:15 -0500 Subject: Fix is_duplicate_packet() bug for fragmentation number setting. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 8f7e9ac37f8..93ed8718fd6 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -7754,10 +7754,10 @@ static inline int is_duplicate_packet(struct ipw_priv *priv, if (*last_frag + 1 != frag) /* out-of-order fragment */ goto drop; - *last_frag = frag; } else *last_seq = seq; + *last_frag = frag; *last_time = jiffies; return 0; -- cgit v1.2.3 From d8bad6df045249cd1cff6a0d167c8f1b9caade7e Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Wed, 13 Jul 2005 12:25:38 -0500 Subject: [bug 667] Fix the notorious "No space for Tx" bug. We send SYSTEM_CONFIG command after the TGI_KEY command if hardware encryption is enabled. It sometimes causes a firmware stall (firmware doesn't respond to any request) and finally bungs up the Tx send queue. The solution is to send SYSTEM_CONFIG command in the post association stage from a workqueue. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 46 +++++++++++++++++++++--------------------- drivers/net/wireless/ipw2200.h | 1 + 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 93ed8718fd6..f3048f8e823 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -3589,6 +3589,12 @@ static void ipw_bg_disassociate(void *data) up(&priv->sem); } +static void ipw_system_config(void *data) +{ + struct ipw_priv *priv = data; + ipw_send_system_config(priv, &priv->sys_config); +} + struct ipw_status_code { u16 status; const char *reason; @@ -4060,6 +4066,8 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, priv->status &= ~STATUS_ASSOCIATING; priv->status |= STATUS_ASSOCIATED; + queue_work(priv->workqueue, + &priv->system_config); #ifdef CONFIG_IPW_QOS #define IPW_GET_PACKET_STYPE(x) WLAN_FC_GET_STYPE( \ @@ -5553,45 +5561,36 @@ static void ipw_set_hwcrypto_keys(struct ipw_priv *priv) { switch (priv->ieee->sec.level) { case SEC_LEVEL_3: - if (!(priv->ieee->sec.flags & SEC_ACTIVE_KEY)) - break; + if (priv->ieee->sec.flags & SEC_ACTIVE_KEY) + ipw_send_tgi_tx_key(priv, + DCT_FLAG_EXT_SECURITY_CCM, + priv->ieee->sec.active_key); - ipw_send_tgi_tx_key(priv, DCT_FLAG_EXT_SECURITY_CCM, - priv->ieee->sec.active_key); ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_CCM); - priv->sys_config.disable_unicast_decryption = 0; priv->sys_config.disable_multicast_decryption = 0; priv->ieee->host_decrypt = 0; - if (ipw_send_system_config(priv, &priv->sys_config)) - IPW_ERROR("ipw_send_system_config failed\n"); - break; case SEC_LEVEL_2: - if (!(priv->ieee->sec.flags & SEC_ACTIVE_KEY)) - break; - - ipw_send_tgi_tx_key(priv, DCT_FLAG_EXT_SECURITY_TKIP, - priv->ieee->sec.active_key); + if (priv->ieee->sec.flags & SEC_ACTIVE_KEY) + ipw_send_tgi_tx_key(priv, + DCT_FLAG_EXT_SECURITY_TKIP, + priv->ieee->sec.active_key); priv->sys_config.disable_unicast_decryption = 1; priv->sys_config.disable_multicast_decryption = 1; priv->ieee->host_decrypt = 1; - if (ipw_send_system_config(priv, &priv->sys_config)) - IPW_ERROR("ipw_send_system_config failed\n"); - break; case SEC_LEVEL_1: ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_WEP); - priv->sys_config.disable_unicast_decryption = 0; priv->sys_config.disable_multicast_decryption = 0; priv->ieee->host_decrypt = 0; - if (ipw_send_system_config(priv, &priv->sys_config)) - IPW_ERROR("ipw_send_system_config failed\n"); - break; case SEC_LEVEL_0: + priv->sys_config.disable_unicast_decryption = 1; + priv->sys_config.disable_multicast_decryption = 1; + break; default: break; } @@ -10113,6 +10112,7 @@ static int ipw_setup_deferred_work(struct ipw_priv *priv) INIT_WORK(&priv->adhoc_check, ipw_bg_adhoc_check, priv); INIT_WORK(&priv->associate, ipw_bg_associate, priv); INIT_WORK(&priv->disassociate, ipw_bg_disassociate, priv); + INIT_WORK(&priv->system_config, ipw_system_config, priv); INIT_WORK(&priv->rx_replenish, ipw_bg_rx_queue_replenish, priv); INIT_WORK(&priv->adapter_restart, ipw_bg_adapter_restart, priv); INIT_WORK(&priv->rf_kill, ipw_bg_rf_kill, priv); @@ -10206,10 +10206,10 @@ static void shim__set_security(struct net_device *dev, priv->ieee->sec.level = sec->level; priv->ieee->sec.flags |= SEC_LEVEL; priv->status |= STATUS_SECURITY_UPDATED; - } - if (!priv->ieee->host_encrypt) - ipw_set_hwcrypto_keys(priv); + if (!priv->ieee->host_encrypt && (sec->flags & SEC_ENCRYPT)) + ipw_set_hwcrypto_keys(priv); + } /* To match current functionality of ipw2100 (which works well w/ * various supplicants, we don't force a disassociate if the diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index 915f469fa1d..28667d3c946 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -1205,6 +1205,7 @@ struct ipw_priv { struct work_struct adhoc_check; struct work_struct associate; struct work_struct disassociate; + struct work_struct system_config; struct work_struct rx_replenish; struct work_struct request_scan; struct work_struct adapter_restart; -- cgit v1.2.3 From 8400a1ceb445f2ace4b8d3c35c181b2b416a81ce Mon Sep 17 00:00:00 2001 From: Liu Hong Date: Wed, 13 Jul 2005 12:27:17 -0500 Subject: [Bug 637] Set tx power for A band. It uses the ieee80211-geo info to set the tx power of the a/b/g band. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index f3048f8e823..0923038ca78 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -8756,6 +8756,7 @@ static int ipw_wx_set_txpow(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); + const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); struct ipw_tx_power tx_power; int i; @@ -8785,10 +8786,15 @@ static int ipw_wx_set_txpow(struct net_device *dev, /* configure device for 'G' band */ tx_power.ieee_mode = IPW_G_MODE; - tx_power.num_channels = 11; - for (i = 0; i < 11; i++) { + tx_power.num_channels = geo->bg_channels; + for (i = 0; i < geo->bg_channels; i++) { + int max_power = geo->bg[i].max_power; + tx_power.channels_tx_power[i].channel_number = i + 1; - tx_power.channels_tx_power[i].tx_power = priv->tx_power; + if (max_power != 0 && priv->tx_power > max_power) + tx_power.channels_tx_power[i].tx_power = max_power; + else + tx_power.channels_tx_power[i].tx_power = priv->tx_power; } if (ipw_send_tx_power(priv, &tx_power)) goto error; @@ -8798,6 +8804,25 @@ static int ipw_wx_set_txpow(struct net_device *dev, if (ipw_send_tx_power(priv, &tx_power)) goto error; + /* configure device to also handle 'A' band */ + if (priv->ieee->abg_true) { + tx_power.ieee_mode = IPW_A_MODE; + tx_power.num_channels = geo->a_channels; + for (i = 0; i < geo->a_channels; i++) { + int max_power = geo->a[i].max_power; + + tx_power.channels_tx_power[i].channel_number = i + 1; + if (max_power != 0 && priv->tx_power > max_power) + tx_power.channels_tx_power[i].tx_power = + max_power; + else + tx_power.channels_tx_power[i].tx_power = + priv->tx_power; + } + if (ipw_send_tx_power(priv, &tx_power)) + goto error; + } + up(&priv->sem); return 0; -- cgit v1.2.3 From d2021cb4e28c512c395a439d65556c260b94e47e Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Thu, 14 Jul 2005 10:35:05 -0500 Subject: Changed default # of missed beacons to miss before disassociation to 24 (vs. 9 which is too low in most environments) Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index 28667d3c946..9bf8aa427d8 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -244,7 +244,7 @@ enum connection_manager_assoc_states { #define HOST_NOTIFICATION_S36_MEASUREMENT_REFUSED 31 #define HOST_NOTIFICATION_STATUS_BEACON_MISSING 1 -#define IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT 9 +#define IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT 24 #define IPW_MB_ROAMING_THRESHOLD_DEFAULT 8 #define IPW_REAL_RATE_RX_PACKET_THRESHOLD 300 -- cgit v1.2.3 From 227d2dc1f109e3348564320cf42fc56770428ed3 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Thu, 28 Jul 2005 16:25:55 -0500 Subject: Updated to support ieee80211 callback to is_queue_full for 802.11e support. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 0923038ca78..3b3a4a077c0 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -9654,8 +9654,8 @@ modify to send one tfd per fragment instead of using chunking. otherwise we need to heavily modify the ieee80211_skb_to_txb. */ -static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, - int pri) +static inline int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, + int pri) { struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *) txb->fragments[0]->data; @@ -9672,6 +9672,11 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, u16 remaining_bytes; int fc; + /* If there isn't room in the queue, we return busy and let the + * network stack requeue the packet for us */ + if (ipw_queue_space(q) < q->high_mark) + return NETDEV_TX_BUSY; + switch (priv->ieee->iw_mode) { case IW_MODE_ADHOC: hdr_len = IEEE80211_3ADDR_LEN; @@ -9837,14 +9842,28 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, q->first_empty = ipw_queue_inc_wrap(q->first_empty, q->n_bd); ipw_write32(priv, q->reg_w, q->first_empty); - if (ipw_queue_space(q) < q->high_mark) - netif_stop_queue(priv->net_dev); - - return; + return NETDEV_TX_OK; drop: IPW_DEBUG_DROP("Silently dropping Tx packet.\n"); ieee80211_txb_free(txb); + return NETDEV_TX_OK; +} + +static int ipw_net_is_queue_full(struct net_device *dev, int pri) +{ + struct ipw_priv *priv = ieee80211_priv(dev); +#ifdef CONFIG_IPW_QOS + int tx_id = ipw_get_tx_queue_number(priv, pri); + struct clx2_tx_queue *txq = &priv->txq[tx_id]; +#else + struct clx2_tx_queue *txq = &priv->txq[0]; +#endif /* CONFIG_IPW_QOS */ + + if (ipw_queue_space(&txq->q) < txq->q.high_mark) + return 1; + + return 0; } static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb, @@ -9852,6 +9871,7 @@ static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb, { struct ipw_priv *priv = ieee80211_priv(dev); unsigned long flags; + int ret; IPW_DEBUG_TX("dev->xmit(%d bytes)\n", txb->payload_size); spin_lock_irqsave(&priv->lock, flags); @@ -9863,11 +9883,12 @@ static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb, goto fail_unlock; } - ipw_tx_skb(priv, txb, pri); - __ipw_led_activity_on(priv); + ret = ipw_tx_skb(priv, txb, pri); + if (ret == NETDEV_TX_OK) + __ipw_led_activity_on(priv); spin_unlock_irqrestore(&priv->lock, flags); - return 0; + return ret; fail_unlock: spin_unlock_irqrestore(&priv->lock, flags); @@ -10706,6 +10727,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) priv->ieee->hard_start_xmit = ipw_net_hard_start_xmit; priv->ieee->set_security = shim__set_security; + priv->ieee->is_queue_full = ipw_net_is_queue_full; #ifdef CONFIG_IPW_QOS priv->ieee->handle_management_frame = ipw_handle_management_frame; -- cgit v1.2.3 From 2b184d5b5401bf87036cd0c2a0242fa5320129d7 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Wed, 3 Aug 2005 20:33:14 -0500 Subject: Fixed some compiler issues if CONFIG_IPW2200_QOS is enabled. Updated a copyright date. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 3b3a4a077c0..073721f1057 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -34,7 +34,7 @@ #define IPW2200_VERSION "1.0.5" #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation" +#define DRV_COPYRIGHT "Copyright(c) 2003-2005 Intel Corporation" #define DRV_VERSION IPW2200_VERSION #define ETH_P_80211_STATS (ETH_P_80211_RAW + 1) @@ -4077,7 +4077,7 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, == IEEE80211_STYPE_ASSOC_RESP)) { if ((sizeof (struct - ieee80211_assoc_response_frame) + ieee80211_assoc_response) <= notif->size) && (notif->size <= 2314)) { struct @@ -4095,7 +4095,7 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, ieee80211_rx_mgt(priv-> ieee, (struct - ieee80211_hdr + ieee80211_hdr_4addr *) ¬if->u.raw, &stats); } @@ -7154,9 +7154,8 @@ static void ipw_bg_qos_activate(void *data) /* * Handler for probe responce and beacon frame */ -static int ipw_handle_management_frame(struct net_device *dev, - struct ieee80211_network *network, - u16 type) +static int ipw_handle_management(struct net_device *dev, + struct ieee80211_network *network, u16 type) { struct ipw_priv *priv = ieee80211_priv(dev); int active_network; @@ -10730,7 +10729,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) priv->ieee->is_queue_full = ipw_net_is_queue_full; #ifdef CONFIG_IPW_QOS - priv->ieee->handle_management_frame = ipw_handle_management_frame; + priv->ieee->handle_management = ipw_handle_management; #endif /* CONFIG_IPW_QOS */ priv->ieee->perfect_rssi = -20; -- cgit v1.2.3 From 4f36f8088ada6c63719a970616078887f82e226c Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Wed, 3 Aug 2005 20:36:56 -0500 Subject: Added more useful geography encoding so people's experience with iwconfig matches what their hardware can actually do in regard to supported channel maps, etc. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 279 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 259 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 073721f1057..6e79ae24ee1 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -10374,28 +10374,256 @@ static int ipw_config(struct ipw_priv *priv) return -EIO; } -static const struct ieee80211_geo ipw_geo = { - "---", - .bg_channels = 11, - .bg = {{2412, 1}, {2417, 2}, {2422, 3}, - {2427, 4}, {2432, 5}, {2437, 6}, - {2442, 7}, {2447, 8}, {2452, 9}, - {2457, 10}, {2462, 11}}, - .a_channels = 8, - .a = {{5180, 36}, - {5200, 40}, - {5220, 44}, - {5240, 48}, - {5260, 52, IEEE80211_CH_PASSIVE_ONLY}, - {5280, 56, IEEE80211_CH_PASSIVE_ONLY}, - {5300, 60, IEEE80211_CH_PASSIVE_ONLY}, - {5320, 64, IEEE80211_CH_PASSIVE_ONLY}}, +/* + * NOTE: + * + * These tables have been tested in conjunction with the + * Intel PRO/Wireless 2200BG and 2915ABG Network Connection Adapters. + * + * Altering this values, using it on other hardware, or in geographies + * not intended for resale of the above mentioned Intel adapters has + * not been tested. + * + */ +static const struct ieee80211_geo ipw_geos[] = { + { /* Restricted */ + "---", + .bg_channels = 11, + .bg = {{2412, 1}, {2417, 2}, {2422, 3}, + {2427, 4}, {2432, 5}, {2437, 6}, + {2442, 7}, {2447, 8}, {2452, 9}, + {2457, 10}, {2462, 11}}, + }, + + { /* Custom US/Canada */ + "ZZF", + .bg_channels = 11, + .bg = {{2412, 1}, {2417, 2}, {2422, 3}, + {2427, 4}, {2432, 5}, {2437, 6}, + {2442, 7}, {2447, 8}, {2452, 9}, + {2457, 10}, {2462, 11}}, + .a_channels = 8, + .a = {{5180, 36}, + {5200, 40}, + {5220, 44}, + {5240, 48}, + {5260, 52, IEEE80211_CH_PASSIVE_ONLY}, + {5280, 56, IEEE80211_CH_PASSIVE_ONLY}, + {5300, 60, IEEE80211_CH_PASSIVE_ONLY}, + {5320, 64, IEEE80211_CH_PASSIVE_ONLY}}, + }, + + { /* Rest of World */ + "ZZD", + .bg_channels = 13, + .bg = {{2412, 1}, {2417, 2}, {2422, 3}, + {2427, 4}, {2432, 5}, {2437, 6}, + {2442, 7}, {2447, 8}, {2452, 9}, + {2457, 10}, {2462, 11}, {2467, 12}, + {2472, 13}}, + }, + + { /* Custom USA & Europe & High */ + "ZZA", + .bg_channels = 11, + .bg = {{2412, 1}, {2417, 2}, {2422, 3}, + {2427, 4}, {2432, 5}, {2437, 6}, + {2442, 7}, {2447, 8}, {2452, 9}, + {2457, 10}, {2462, 11}}, + .a_channels = 13, + .a = {{5180, 36}, + {5200, 40}, + {5220, 44}, + {5240, 48}, + {5260, 52, IEEE80211_CH_PASSIVE_ONLY}, + {5280, 56, IEEE80211_CH_PASSIVE_ONLY}, + {5300, 60, IEEE80211_CH_PASSIVE_ONLY}, + {5320, 64, IEEE80211_CH_PASSIVE_ONLY}, + {5745, 149}, + {5765, 153}, + {5785, 157}, + {5805, 161}, + {5825, 165}}, + }, + + { /* Custom NA & Europe */ + "ZZB", + .bg_channels = 11, + .bg = {{2412, 1}, {2417, 2}, {2422, 3}, + {2427, 4}, {2432, 5}, {2437, 6}, + {2442, 7}, {2447, 8}, {2452, 9}, + {2457, 10}, {2462, 11}}, + .a_channels = 13, + .a = {{5180, 36}, + {5200, 40}, + {5220, 44}, + {5240, 48}, + {5260, 52, IEEE80211_CH_PASSIVE_ONLY}, + {5280, 56, IEEE80211_CH_PASSIVE_ONLY}, + {5300, 60, IEEE80211_CH_PASSIVE_ONLY}, + {5320, 64, IEEE80211_CH_PASSIVE_ONLY}, + {5745, 149, IEEE80211_CH_PASSIVE_ONLY}, + {5765, 153, IEEE80211_CH_PASSIVE_ONLY}, + {5785, 157, IEEE80211_CH_PASSIVE_ONLY}, + {5805, 161, IEEE80211_CH_PASSIVE_ONLY}, + {5825, 165, IEEE80211_CH_PASSIVE_ONLY}}, + }, + + { /* Custom Japan */ + "ZZC", + .bg_channels = 11, + .bg = {{2412, 1}, {2417, 2}, {2422, 3}, + {2427, 4}, {2432, 5}, {2437, 6}, + {2442, 7}, {2447, 8}, {2452, 9}, + {2457, 10}, {2462, 11}}, + .a_channels = 4, + .a = {{5170, 34}, {5190, 38}, + {5210, 42}, {5230, 46}}, + }, + + { /* Custom */ + "ZZM", + .bg_channels = 11, + .bg = {{2412, 1}, {2417, 2}, {2422, 3}, + {2427, 4}, {2432, 5}, {2437, 6}, + {2442, 7}, {2447, 8}, {2452, 9}, + {2457, 10}, {2462, 11}}, + }, + + { /* Europe */ + "ZZE", + .bg_channels = 13, + .bg = {{2412, 1}, {2417, 2}, {2422, 3}, + {2427, 4}, {2432, 5}, {2437, 6}, + {2442, 7}, {2447, 8}, {2452, 9}, + {2457, 10}, {2462, 11}, {2467, 12}, + {2472, 13}}, + .a_channels = 19, + .a = {{5180, 36}, + {5200, 40}, + {5220, 44}, + {5240, 48}, + {5260, 52, IEEE80211_CH_PASSIVE_ONLY}, + {5280, 56, IEEE80211_CH_PASSIVE_ONLY}, + {5300, 60, IEEE80211_CH_PASSIVE_ONLY}, + {5320, 64, IEEE80211_CH_PASSIVE_ONLY}, + {5500, 100, IEEE80211_CH_PASSIVE_ONLY}, + {5520, 104, IEEE80211_CH_PASSIVE_ONLY}, + {5540, 108, IEEE80211_CH_PASSIVE_ONLY}, + {5560, 112, IEEE80211_CH_PASSIVE_ONLY}, + {5580, 116, IEEE80211_CH_PASSIVE_ONLY}, + {5600, 120, IEEE80211_CH_PASSIVE_ONLY}, + {5620, 124, IEEE80211_CH_PASSIVE_ONLY}, + {5640, 128, IEEE80211_CH_PASSIVE_ONLY}, + {5660, 132, IEEE80211_CH_PASSIVE_ONLY}, + {5680, 136, IEEE80211_CH_PASSIVE_ONLY}, + {5700, 140, IEEE80211_CH_PASSIVE_ONLY}}, + }, + + { /* Custom Japan */ + "ZZJ", + .bg_channels = 14, + .bg = {{2412, 1}, {2417, 2}, {2422, 3}, + {2427, 4}, {2432, 5}, {2437, 6}, + {2442, 7}, {2447, 8}, {2452, 9}, + {2457, 10}, {2462, 11}, {2467, 12}, + {2472, 13}, {2484, 14, IEEE80211_CH_B_ONLY}}, + .a_channels = 4, + .a = {{5170, 34}, {5190, 38}, + {5210, 42}, {5230, 46}}, + }, + + { /* High Band */ + "ZZH", + .bg_channels = 13, + .bg = {{2412, 1}, {2417, 2}, {2422, 3}, + {2427, 4}, {2432, 5}, {2437, 6}, + {2442, 7}, {2447, 8}, {2452, 9}, + {2457, 10}, {2462, 11}, + {2467, 12, IEEE80211_CH_PASSIVE_ONLY}, + {2472, 13, IEEE80211_CH_PASSIVE_ONLY}}, + .a_channels = 4, + .a = {{5745, 149}, {5765, 153}, + {5785, 157}, {5805, 161}}, + }, + + { /* Custom Europe */ + "ZZG", + .bg_channels = 13, + .bg = {{2412, 1}, {2417, 2}, {2422, 3}, + {2427, 4}, {2432, 5}, {2437, 6}, + {2442, 7}, {2447, 8}, {2452, 9}, + {2457, 10}, {2462, 11}, + {2467, 12}, {2472, 13}}, + .a_channels = 4, + .a = {{5180, 36}, {5200, 40}, + {5220, 44}, {5240, 48}}, + }, + + { /* Europe */ + "ZZK", + .bg_channels = 13, + .bg = {{2412, 1}, {2417, 2}, {2422, 3}, + {2427, 4}, {2432, 5}, {2437, 6}, + {2442, 7}, {2447, 8}, {2452, 9}, + {2457, 10}, {2462, 11}, + {2467, 12, IEEE80211_CH_PASSIVE_ONLY}, + {2472, 13, IEEE80211_CH_PASSIVE_ONLY}}, + .a_channels = 24, + .a = {{5180, 36, IEEE80211_CH_PASSIVE_ONLY}, + {5200, 40, IEEE80211_CH_PASSIVE_ONLY}, + {5220, 44, IEEE80211_CH_PASSIVE_ONLY}, + {5240, 48, IEEE80211_CH_PASSIVE_ONLY}, + {5260, 52, IEEE80211_CH_PASSIVE_ONLY}, + {5280, 56, IEEE80211_CH_PASSIVE_ONLY}, + {5300, 60, IEEE80211_CH_PASSIVE_ONLY}, + {5320, 64, IEEE80211_CH_PASSIVE_ONLY}, + {5500, 100, IEEE80211_CH_PASSIVE_ONLY}, + {5520, 104, IEEE80211_CH_PASSIVE_ONLY}, + {5540, 108, IEEE80211_CH_PASSIVE_ONLY}, + {5560, 112, IEEE80211_CH_PASSIVE_ONLY}, + {5580, 116, IEEE80211_CH_PASSIVE_ONLY}, + {5600, 120, IEEE80211_CH_PASSIVE_ONLY}, + {5620, 124, IEEE80211_CH_PASSIVE_ONLY}, + {5640, 128, IEEE80211_CH_PASSIVE_ONLY}, + {5660, 132, IEEE80211_CH_PASSIVE_ONLY}, + {5680, 136, IEEE80211_CH_PASSIVE_ONLY}, + {5700, 140, IEEE80211_CH_PASSIVE_ONLY}, + {5745, 149, IEEE80211_CH_PASSIVE_ONLY}, + {5765, 153, IEEE80211_CH_PASSIVE_ONLY}, + {5785, 157, IEEE80211_CH_PASSIVE_ONLY}, + {5805, 161, IEEE80211_CH_PASSIVE_ONLY}, + {5825, 165, IEEE80211_CH_PASSIVE_ONLY}}, + }, + + { /* Europe */ + "ZZL", + .bg_channels = 11, + .bg = {{2412, 1}, {2417, 2}, {2422, 3}, + {2427, 4}, {2432, 5}, {2437, 6}, + {2442, 7}, {2447, 8}, {2452, 9}, + {2457, 10}, {2462, 11}}, + .a_channels = 13, + .a = {{5180, 36, IEEE80211_CH_PASSIVE_ONLY}, + {5200, 40, IEEE80211_CH_PASSIVE_ONLY}, + {5220, 44, IEEE80211_CH_PASSIVE_ONLY}, + {5240, 48, IEEE80211_CH_PASSIVE_ONLY}, + {5260, 52, IEEE80211_CH_PASSIVE_ONLY}, + {5280, 56, IEEE80211_CH_PASSIVE_ONLY}, + {5300, 60, IEEE80211_CH_PASSIVE_ONLY}, + {5320, 64, IEEE80211_CH_PASSIVE_ONLY}, + {5745, 149, IEEE80211_CH_PASSIVE_ONLY}, + {5765, 153, IEEE80211_CH_PASSIVE_ONLY}, + {5785, 157, IEEE80211_CH_PASSIVE_ONLY}, + {5805, 161, IEEE80211_CH_PASSIVE_ONLY}, + {5825, 165, IEEE80211_CH_PASSIVE_ONLY}}, + } }; #define MAX_HW_RESTARTS 5 static int ipw_up(struct ipw_priv *priv) { - int rc, i; + int rc, i, j; if (priv->status & STATUS_EXIT_PENDING) return -EIO; @@ -10414,9 +10642,20 @@ static int ipw_up(struct ipw_priv *priv) eeprom_parse_mac(priv, priv->mac_addr); memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN); - memcpy(priv->country, &priv->eeprom[EEPROM_COUNTRY_CODE], 3); - priv->country[3] = '\0'; - ieee80211_set_geo(priv->ieee, &ipw_geo); + for (j = 0; j < ARRAY_SIZE(ipw_geos); j++) { + if (!memcmp(&priv->eeprom[EEPROM_COUNTRY_CODE], + ipw_geos[j].name, 3)) + break; + } + if (j == ARRAY_SIZE(ipw_geos)) + j = 0; + if (ieee80211_set_geo(priv->ieee, &ipw_geos[j])) { + IPW_WARNING("Could not set geography."); + return 0; + } + + IPW_DEBUG_INFO("Geography %03d [%s] detected.\n", + j, priv->ieee->geo.name); if (priv->status & STATUS_RF_KILL_SW) { IPW_WARNING("Radio disabled by module parameter.\n"); -- cgit v1.2.3 From 87b016cb64b267a6f791494a4cfd84e84e022ebb Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Fri, 5 Aug 2005 17:17:35 +0800 Subject: Workaround kernel BUG_ON panic caused by unexpected duplicate packets. Signed-off-by: Zhu Yi --- drivers/net/wireless/ipw2200.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 6e79ae24ee1..483993a4ca4 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -7696,7 +7696,6 @@ static inline int is_network_packet(struct ipw_priv *priv, static inline int is_duplicate_packet(struct ipw_priv *priv, struct ieee80211_hdr_4addr *header) { - u16 fc = le16_to_cpu(header->frame_ctl); u16 sc = le16_to_cpu(header->seq_ctl); u16 seq = WLAN_GET_SEQ_SEQ(sc); u16 frag = WLAN_GET_SEQ_FRAG(sc); @@ -7760,7 +7759,10 @@ static inline int is_duplicate_packet(struct ipw_priv *priv, return 0; drop: - BUG_ON(!(fc & IEEE80211_FCTL_RETRY)); + /* Comment this line now since we observed the card receives + * duplicate packets but the FCTL_RETRY bit is not set in the + * IBSS mode with fragmentation enabled. + BUG_ON(!(le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_RETRY)); */ return 1; } -- cgit v1.2.3 From e402c9374112aaf1fc5796013dc3040ebb3954ca Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Fri, 5 Aug 2005 17:20:40 +0800 Subject: Disable host fragmentation in open mode since IPW2200/2915 hardware support hardware fragmentation. Signed-off-by: Zhu Yi --- drivers/net/wireless/ipw2200.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 483993a4ca4..f8dac52df93 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -8069,6 +8069,9 @@ static int ipw_sw_reset(struct ipw_priv *priv, int init) } IPW_DEBUG_INFO("Hardware crypto [%s]\n", hwcrypto ? "on" : "off"); + /* IPW2200/2915 is abled to do hardware fragmentation. */ + priv->ieee->host_open_frag = 0; + if ((priv->pci_dev->device == 0x4223) || (priv->pci_dev->device == 0x4224)) { if (init) -- cgit v1.2.3 From 1fbfea549f07f1f7afd436f1e45b25437f0172c2 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Fri, 5 Aug 2005 17:22:56 +0800 Subject: [Bug 792] Fix WPA-PSK AES both for -Dipw and -Dwext. Signed-off-by: Zhu Yi --- drivers/net/wireless/ipw2200.c | 141 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 125 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index f8dac52df93..c6da5f53425 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -5557,6 +5557,55 @@ static void ipw_send_wep_keys(struct ipw_priv *priv, int type) } } +static void ipw_set_hw_decrypt_unicast(struct ipw_priv *priv, int level) +{ + if (priv->ieee->host_encrypt) + return; + + switch (level) { + case SEC_LEVEL_3: + priv->sys_config.disable_unicast_decryption = 0; + priv->ieee->host_decrypt = 0; + break; + case SEC_LEVEL_2: + priv->sys_config.disable_unicast_decryption = 1; + priv->ieee->host_decrypt = 1; + break; + case SEC_LEVEL_1: + priv->sys_config.disable_unicast_decryption = 0; + priv->ieee->host_decrypt = 0; + break; + case SEC_LEVEL_0: + priv->sys_config.disable_unicast_decryption = 1; + break; + default: + break; + } +} + +static void ipw_set_hw_decrypt_multicast(struct ipw_priv *priv, int level) +{ + if (priv->ieee->host_encrypt) + return; + + switch (level) { + case SEC_LEVEL_3: + priv->sys_config.disable_multicast_decryption = 0; + break; + case SEC_LEVEL_2: + priv->sys_config.disable_multicast_decryption = 1; + break; + case SEC_LEVEL_1: + priv->sys_config.disable_multicast_decryption = 0; + break; + case SEC_LEVEL_0: + priv->sys_config.disable_multicast_decryption = 1; + break; + default: + break; + } +} + static void ipw_set_hwcrypto_keys(struct ipw_priv *priv) { switch (priv->ieee->sec.level) { @@ -5567,33 +5616,23 @@ static void ipw_set_hwcrypto_keys(struct ipw_priv *priv) priv->ieee->sec.active_key); ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_CCM); - priv->sys_config.disable_unicast_decryption = 0; - priv->sys_config.disable_multicast_decryption = 0; - priv->ieee->host_decrypt = 0; break; case SEC_LEVEL_2: if (priv->ieee->sec.flags & SEC_ACTIVE_KEY) ipw_send_tgi_tx_key(priv, DCT_FLAG_EXT_SECURITY_TKIP, priv->ieee->sec.active_key); - - priv->sys_config.disable_unicast_decryption = 1; - priv->sys_config.disable_multicast_decryption = 1; - priv->ieee->host_decrypt = 1; break; case SEC_LEVEL_1: ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_WEP); - priv->sys_config.disable_unicast_decryption = 0; - priv->sys_config.disable_multicast_decryption = 0; - priv->ieee->host_decrypt = 0; break; case SEC_LEVEL_0: - priv->sys_config.disable_unicast_decryption = 1; - priv->sys_config.disable_multicast_decryption = 1; - break; default: break; } + + ipw_set_hw_decrypt_unicast(priv, priv->ieee->sec.level); + ipw_set_hw_decrypt_multicast(priv, priv->ieee->sec.level); } static void ipw_adhoc_check(void *data) @@ -6185,12 +6224,31 @@ static int ipw_wpa_mlme(struct net_device *dev, int command, int reason) return ret; } +static int ipw_wpa_ie_cipher2level(u8 cipher) +{ + switch (cipher) { + case 4: /* CCMP */ + return SEC_LEVEL_3; + case 2: /* TKIP */ + return SEC_LEVEL_2; + case 5: /* WEP104 */ + case 1: /* WEP40 */ + return SEC_LEVEL_1; + case 0: /* NONE */ + return SEC_LEVEL_0; + default: + return -1; + } +} + static int ipw_wpa_set_wpa_ie(struct net_device *dev, struct ipw_param *param, int plen) { struct ipw_priv *priv = ieee80211_priv(dev); struct ieee80211_device *ieee = priv->ieee; u8 *buf; + u8 *ptk, *gtk; + int level; if (param->u.wpa_ie.len > MAX_WPA_IE_LEN || (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL)) @@ -6209,8 +6267,35 @@ static int ipw_wpa_set_wpa_ie(struct net_device *dev, kfree(ieee->wpa_ie); ieee->wpa_ie = NULL; ieee->wpa_ie_len = 0; + goto done; + } + + if (priv->ieee->host_encrypt) + goto done; + + /* HACK: Parse wpa_ie here to get pairwise suite, otherwise + * we need to change driver_ipw.c from wpa_supplicant. This + * is OK since -Dipw is deprecated. The -Dwext driver has a + * clean way to handle this. */ + gtk = ptk = (u8 *) ieee->wpa_ie; + if (ieee->wpa_ie[0] == 0x30) { /* RSN IE */ + gtk += 4 + 3; + ptk += 4 + 4 + 2 + 3; + } else { /* WPA IE */ + gtk += 8 + 3; + ptk += 8 + 4 + 2 + 3; } + if (ptk - (u8 *) ieee->wpa_ie > ieee->wpa_ie_len) + return -EINVAL; + + level = ipw_wpa_ie_cipher2level(*gtk); + ipw_set_hw_decrypt_multicast(priv, level); + + level = ipw_wpa_ie_cipher2level(*ptk); + ipw_set_hw_decrypt_unicast(priv, level); + + done: ipw_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len); return 0; } @@ -6510,6 +6595,23 @@ static int ipw_wx_get_genie(struct net_device *dev, return err; } +static int wext_cipher2level(int cipher) +{ + switch (cipher) { + case IW_AUTH_CIPHER_NONE: + return SEC_LEVEL_0; + case IW_AUTH_CIPHER_WEP40: + case IW_AUTH_CIPHER_WEP104: + return SEC_LEVEL_1; + case IW_AUTH_CIPHER_TKIP: + return SEC_LEVEL_2; + case IW_AUTH_CIPHER_CCMP: + return SEC_LEVEL_3; + default: + return -1; + } +} + /* SIOCSIWAUTH */ static int ipw_wx_set_auth(struct net_device *dev, struct iw_request_info *info, @@ -6524,8 +6626,15 @@ static int ipw_wx_set_auth(struct net_device *dev, switch (param->flags & IW_AUTH_INDEX) { case IW_AUTH_WPA_VERSION: + break; case IW_AUTH_CIPHER_PAIRWISE: + ipw_set_hw_decrypt_unicast(priv, + wext_cipher2level(param->value)); + break; case IW_AUTH_CIPHER_GROUP: + ipw_set_hw_decrypt_multicast(priv, + wext_cipher2level(param->value)); + break; case IW_AUTH_KEY_MGMT: /* * ipw2200 does not use these parameters @@ -10256,11 +10365,11 @@ static void shim__set_security(struct net_device *dev, priv->ieee->sec.level = sec->level; priv->ieee->sec.flags |= SEC_LEVEL; priv->status |= STATUS_SECURITY_UPDATED; - - if (!priv->ieee->host_encrypt && (sec->flags & SEC_ENCRYPT)) - ipw_set_hwcrypto_keys(priv); } + if (!priv->ieee->host_encrypt && (sec->flags & SEC_ENCRYPT)) + ipw_set_hwcrypto_keys(priv); + /* To match current functionality of ipw2100 (which works well w/ * various supplicants, we don't force a disassociate if the * privacy capability changes ... */ -- cgit v1.2.3 From caeff81b4e6479884f3cd2ced526bebd4f0c5eff Mon Sep 17 00:00:00 2001 From: Hong Liu Date: Fri, 5 Aug 2005 17:25:50 +0800 Subject: Fixes the ad-hoc network WEP key list issue. If we configure the wep keys after creating the ibss network, the beacons of this network will not show correctly (it still shows "key off" in iwlist scan report). This is because we don't update the beacon info in firmware. Signed-off-by: Hong Liu Signed-off-by: Zhu Yi --- drivers/net/wireless/ipw2200.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index c6da5f53425..626e78a336e 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -9169,11 +9169,19 @@ static int ipw_wx_set_encode(struct net_device *dev, { struct ipw_priv *priv = ieee80211_priv(dev); int ret; + u32 cap = priv->capability; down(&priv->sem); ret = ieee80211_wx_set_encode(priv->ieee, info, wrqu, key); - up(&priv->sem); + /* In IBSS mode, we need to notify the firmware to update + * the beacon info after we changed the capability. */ + if (cap != priv->capability && + priv->ieee->iw_mode == IW_MODE_ADHOC && + priv->status & STATUS_ASSOCIATED) + ipw_disassociate(priv); + + up(&priv->sem); return ret; } -- cgit v1.2.3 From 0ece35b557c5097c90df9e8fbf47e4da46377df1 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Fri, 5 Aug 2005 17:26:51 +0800 Subject: [Bug 701] Fix a misuse of ieee->mode with ieee->iw_mode. Signed-off-by: Zhu Yi --- drivers/net/wireless/ipw2200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 626e78a336e..2633e0de7f7 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -8223,7 +8223,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int init) priv->power_mode = IPW_POWER_AC; priv->tx_power = IPW_TX_POWER_DEFAULT; - return old_mode == priv->ieee->mode; + return old_mode == priv->ieee->iw_mode; } /* -- cgit v1.2.3 From 22501c8ed70398178e8c8d55e65da97b7e7fb610 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 11 Aug 2005 10:49:17 +0800 Subject: Fix ipw_wx_get_txpow shows wrong disabled value. Signed-off-by: Zhu Yi --- drivers/net/wireless/ipw2200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 2633e0de7f7..105b1146f39 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -8957,7 +8957,7 @@ static int ipw_wx_get_txpow(struct net_device *dev, up(&priv->sem); IPW_DEBUG_WX("GET TX Power -> %s %d \n", - wrqu->power.disabled ? "ON" : "OFF", wrqu->power.value); + wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value); return 0; } -- cgit v1.2.3 From 6de9f7f27defe6f1a2d33d0b78af6b1a0ad18330 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 11 Aug 2005 14:39:33 +0800 Subject: Fix firmware error when setting tx_power. Signed-off-by: Zhu Yi --- drivers/net/wireless/ipw2200.c | 131 +++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 76 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 105b1146f39..f825aa462c9 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -2084,6 +2084,50 @@ static int ipw_send_tx_power(struct ipw_priv *priv, struct ipw_tx_power *power) return 0; } +static int ipw_set_tx_power(struct ipw_priv *priv) +{ + const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); + struct ipw_tx_power tx_power; + s8 max_power; + int i; + + memset(&tx_power, 0, sizeof(tx_power)); + + /* configure device for 'G' band */ + tx_power.ieee_mode = IPW_G_MODE; + tx_power.num_channels = geo->bg_channels; + for (i = 0; i < geo->bg_channels; i++) { + max_power = geo->bg[i].max_power; + tx_power.channels_tx_power[i].channel_number = + geo->bg[i].channel; + tx_power.channels_tx_power[i].tx_power = max_power ? + min(max_power, priv->tx_power) : priv->tx_power; + } + if (ipw_send_tx_power(priv, &tx_power)) + return -EIO; + + /* configure device to also handle 'B' band */ + tx_power.ieee_mode = IPW_B_MODE; + if (ipw_send_tx_power(priv, &tx_power)) + return -EIO; + + /* configure device to also handle 'A' band */ + if (priv->ieee->abg_true) { + tx_power.ieee_mode = IPW_A_MODE; + tx_power.num_channels = geo->a_channels; + for (i = 0; i < tx_power.num_channels; i++) { + max_power = geo->a[i].max_power; + tx_power.channels_tx_power[i].channel_number = + geo->a[i].channel; + tx_power.channels_tx_power[i].tx_power = max_power ? + min(max_power, priv->tx_power) : priv->tx_power; + } + if (ipw_send_tx_power(priv, &tx_power)) + return -EIO; + } + return 0; +} + static int ipw_send_rts_threshold(struct ipw_priv *priv, u16 rts) { struct ipw_rts_threshold rts_threshold = { @@ -8869,79 +8913,33 @@ static int ipw_wx_set_txpow(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); - struct ipw_tx_power tx_power; - int i; + int err = 0; down(&priv->sem); if (ipw_radio_kill_sw(priv, wrqu->power.disabled)) { - up(&priv->sem); - return -EINPROGRESS; + err = -EINPROGRESS; + goto out; } if (!wrqu->power.fixed) wrqu->power.value = IPW_TX_POWER_DEFAULT; if (wrqu->power.flags != IW_TXPOW_DBM) { - up(&priv->sem); - return -EINVAL; + err = -EINVAL; + goto out; } if ((wrqu->power.value > IPW_TX_POWER_MAX) || (wrqu->power.value < IPW_TX_POWER_MIN)) { - up(&priv->sem); - return -EINVAL; + err = -EINVAL; + goto out; } priv->tx_power = wrqu->power.value; - - memset(&tx_power, 0, sizeof(tx_power)); - - /* configure device for 'G' band */ - tx_power.ieee_mode = IPW_G_MODE; - tx_power.num_channels = geo->bg_channels; - for (i = 0; i < geo->bg_channels; i++) { - int max_power = geo->bg[i].max_power; - - tx_power.channels_tx_power[i].channel_number = i + 1; - if (max_power != 0 && priv->tx_power > max_power) - tx_power.channels_tx_power[i].tx_power = max_power; - else - tx_power.channels_tx_power[i].tx_power = priv->tx_power; - } - if (ipw_send_tx_power(priv, &tx_power)) - goto error; - - /* configure device to also handle 'B' band */ - tx_power.ieee_mode = IPW_B_MODE; - if (ipw_send_tx_power(priv, &tx_power)) - goto error; - - /* configure device to also handle 'A' band */ - if (priv->ieee->abg_true) { - tx_power.ieee_mode = IPW_A_MODE; - tx_power.num_channels = geo->a_channels; - for (i = 0; i < geo->a_channels; i++) { - int max_power = geo->a[i].max_power; - - tx_power.channels_tx_power[i].channel_number = i + 1; - if (max_power != 0 && priv->tx_power > max_power) - tx_power.channels_tx_power[i].tx_power = - max_power; - else - tx_power.channels_tx_power[i].tx_power = - priv->tx_power; - } - if (ipw_send_tx_power(priv, &tx_power)) - goto error; - } - - up(&priv->sem); - return 0; - - error: + err = ipw_set_tx_power(priv); + out: up(&priv->sem); - return -EIO; + return err; } static int ipw_wx_get_txpow(struct net_device *dev, @@ -10426,29 +10424,10 @@ static int init_supported_rates(struct ipw_priv *priv, static int ipw_config(struct ipw_priv *priv) { - int i; - struct ipw_tx_power tx_power; - - memset(&priv->sys_config, 0, sizeof(priv->sys_config)); - memset(&tx_power, 0, sizeof(tx_power)); - /* This is only called from ipw_up, which resets/reloads the firmware so, we don't need to first disable the card before we configure it */ - - /* configure device for 'G' band */ - tx_power.ieee_mode = IPW_G_MODE; - tx_power.num_channels = 11; - for (i = 0; i < 11; i++) { - tx_power.channels_tx_power[i].channel_number = i + 1; - tx_power.channels_tx_power[i].tx_power = priv->tx_power; - } - if (ipw_send_tx_power(priv, &tx_power)) - goto error; - - /* configure device to also handle 'B' band */ - tx_power.ieee_mode = IPW_B_MODE; - if (ipw_send_tx_power(priv, &tx_power)) + if (ipw_set_tx_power(priv)) goto error; /* initialize adapter address */ -- cgit v1.2.3 From e666619e232308c8ee2aba6b87f28ad26b38d905 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Fri, 12 Aug 2005 09:17:04 -0500 Subject: Modified ipw_config and STATUS_INIT setting to correct race condition with request_scan being called before initialized if invoked from insmod, resulting in no association occurring during boot until iwlist scan is run. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index f825aa462c9..6e862c2905d 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -10465,9 +10465,17 @@ static int ipw_config(struct ipw_priv *priv) if (ipw_send_host_complete(priv)) goto error; - /* If configured to try and auto-associate, kick off a scan */ - if (priv->config & CFG_ASSOCIATE) - queue_work(priv->workqueue, &priv->request_scan); + priv->status |= STATUS_INIT; + + ipw_led_init(priv); + ipw_led_radio_on(priv); + priv->notif_missed_beacons = 0; + + /* Set hardware WEP key if it is configured. */ + if ((priv->capability & CAP_PRIVACY_ON) && + (priv->ieee->sec.level == SEC_LEVEL_1) && + !(priv->ieee->host_encrypt || priv->ieee->host_decrypt)) + ipw_set_hwcrypto_keys(priv); return 0; @@ -10773,17 +10781,10 @@ static int ipw_up(struct ipw_priv *priv) rc = ipw_config(priv); if (!rc) { IPW_DEBUG_INFO("Configured device on count %i\n", i); - ipw_led_init(priv); - ipw_led_radio_on(priv); - priv->notif_missed_beacons = 0; - priv->status |= STATUS_INIT; - - /* Set hardware WEP key if it is configured. */ - if ((priv->capability & CAP_PRIVACY_ON) && - (priv->ieee->sec.level == SEC_LEVEL_1) && - !(priv->ieee->host_encrypt || - priv->ieee->host_decrypt)) - ipw_set_hwcrypto_keys(priv); + + /* If configure to try and auto-associate, kick + * off a scan. */ + queue_work(priv->workqueue, &priv->request_scan); return 0; } -- cgit v1.2.3 From b39860c60b135ef16c1c16a3e2a757ff8070c5ad Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Fri, 12 Aug 2005 09:36:32 -0500 Subject: Switched firmware error dumping so that it will capture a log available via sysfs even if debugging disabled. When a firmware error is captured, it will be dumped to the kernel log (if debug enabled) and captured in memory to be retrieved via sysfs. If an error has already been captured, subsequent errors will be dropped. The existing error can be cleared by writing to the error log entry. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 251 ++++++++++++++++++++++++++++------------- drivers/net/wireless/ipw2200.h | 30 ++++- 2 files changed, 204 insertions(+), 77 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 6e862c2905d..a3283caaa87 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -428,6 +428,7 @@ static inline void ipw_disable_interrupts(struct ipw_priv *priv) ipw_write32(priv, IPW_INTA_MASK_R, ~IPW_INTA_MASK_ALL); } +#ifdef CONFIG_IPW_DEBUG static char *ipw_error_desc(u32 val) { switch (val) { @@ -466,56 +467,35 @@ static char *ipw_error_desc(u32 val) } } -static void ipw_dump_nic_error_log(struct ipw_priv *priv) +static void ipw_dump_error_log(struct ipw_priv *priv, + struct ipw_fw_error *error) { - u32 desc, time, blink1, blink2, ilink1, ilink2, idata, i, count, base; - - base = ipw_read32(priv, IPWSTATUS_ERROR_LOG); - count = ipw_read_reg32(priv, base); + u32 i; - if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { - IPW_ERROR("Start IPW Error Log Dump:\n"); - IPW_ERROR("Status: 0x%08X, Config: %08X\n", - priv->status, priv->config); + if (!error) { + IPW_ERROR("Error allocating and capturing error log. " + "Nothing to dump.\n"); + return; } - for (i = ERROR_START_OFFSET; - i <= count * ERROR_ELEM_SIZE; i += ERROR_ELEM_SIZE) { - desc = ipw_read_reg32(priv, base + i); - time = ipw_read_reg32(priv, base + i + 1 * sizeof(u32)); - blink1 = ipw_read_reg32(priv, base + i + 2 * sizeof(u32)); - blink2 = ipw_read_reg32(priv, base + i + 3 * sizeof(u32)); - ilink1 = ipw_read_reg32(priv, base + i + 4 * sizeof(u32)); - ilink2 = ipw_read_reg32(priv, base + i + 5 * sizeof(u32)); - idata = ipw_read_reg32(priv, base + i + 6 * sizeof(u32)); + IPW_ERROR("Start IPW Error Log Dump:\n"); + IPW_ERROR("Status: 0x%08X, Config: %08X\n", + error->status, error->config); + for (i = 0; i < error->elem_len; i++) IPW_ERROR("%s %i 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", - ipw_error_desc(desc), time, blink1, blink2, - ilink1, ilink2, idata); - } + ipw_error_desc(error->elem[i].desc), + error->elem[i].time, + error->elem[i].blink1, + error->elem[i].blink2, + error->elem[i].link1, + error->elem[i].link2, error->elem[i].data); + for (i = 0; i < error->log_len; i++) + IPW_ERROR("%i\t0x%08x\t%i\n", + error->log[i].time, + error->log[i].event, error->log[i].data); } - -static void ipw_dump_nic_event_log(struct ipw_priv *priv) -{ - u32 ev, time, data, i, count, base; - - base = ipw_read32(priv, IPW_EVENT_LOG); - count = ipw_read_reg32(priv, base); - - if (EVENT_START_OFFSET <= count * EVENT_ELEM_SIZE) - IPW_ERROR("Start IPW Event Log Dump:\n"); - - for (i = EVENT_START_OFFSET; - i <= count * EVENT_ELEM_SIZE; i += EVENT_ELEM_SIZE) { - ev = ipw_read_reg32(priv, base + i); - time = ipw_read_reg32(priv, base + i + 1 * sizeof(u32)); - data = ipw_read_reg32(priv, base + i + 2 * sizeof(u32)); - -#ifdef CONFIG_IPW_DEBUG - IPW_ERROR("%i\t0x%08x\t%i\n", time, data, ev); #endif - } -} static inline int ipw_is_init(struct ipw_priv *priv) { @@ -1058,6 +1038,130 @@ static ssize_t store_debug_level(struct device_driver *d, const char *buf, static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, show_debug_level, store_debug_level); +static inline u32 ipw_get_event_log_len(struct ipw_priv *priv) +{ + return ipw_read_reg32(priv, ipw_read32(priv, IPW_EVENT_LOG)); +} + +static void ipw_capture_event_log(struct ipw_priv *priv, + u32 log_len, struct ipw_event *log) +{ + u32 base; + + if (log_len) { + base = ipw_read32(priv, IPW_EVENT_LOG); + ipw_read_indirect(priv, base + sizeof(base) + sizeof(u32), + (u8 *) log, sizeof(*log) * log_len); + } +} + +static struct ipw_fw_error *ipw_alloc_error_log(struct ipw_priv *priv) +{ + struct ipw_fw_error *error; + u32 log_len = ipw_get_event_log_len(priv); + u32 base = ipw_read32(priv, IPW_ERROR_LOG); + u32 elem_len = ipw_read_reg32(priv, base); + + error = kmalloc(sizeof(*error) + + sizeof(*error->elem) * elem_len + + sizeof(*error->log) * log_len, GFP_ATOMIC); + if (!error) { + IPW_ERROR("Memory allocation for firmware error log " + "failed.\n"); + return NULL; + } + error->status = priv->status; + error->config = priv->config; + error->elem_len = elem_len; + error->log_len = log_len; + error->elem = (struct ipw_error_elem *)error->payload; + error->log = (struct ipw_event *)(error->elem + + (sizeof(*error->elem) * elem_len)); + + ipw_capture_event_log(priv, log_len, error->log); + + if (elem_len) + ipw_read_indirect(priv, base + sizeof(base), (u8 *) error->elem, + sizeof(*error->elem) * elem_len); + + return error; +} + +static void ipw_free_error_log(struct ipw_fw_error *error) +{ + if (error) + kfree(error); +} + +static ssize_t show_event_log(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct ipw_priv *priv = dev_get_drvdata(d); + u32 log_len = ipw_get_event_log_len(priv); + struct ipw_event log[log_len]; + u32 len = 0, i; + + ipw_capture_event_log(priv, log_len, log); + + len += snprintf(buf + len, PAGE_SIZE - len, "%08X", log_len); + for (i = 0; i < log_len; i++) + len += snprintf(buf + len, PAGE_SIZE - len, + "\n%08X%08X%08X", + log[i].time, log[i].event, log[i].data); + len += snprintf(buf + len, PAGE_SIZE - len, "\n"); + return len; +} + +static DEVICE_ATTR(event_log, S_IRUGO, show_event_log, NULL); + +static ssize_t show_error(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct ipw_priv *priv = dev_get_drvdata(d); + u32 len = 0, i; + if (!priv->error) + return 0; + len += snprintf(buf + len, PAGE_SIZE - len, + "%08X%08X%08X", + priv->error->status, + priv->error->config, priv->error->elem_len); + for (i = 0; i < priv->error->elem_len; i++) + len += snprintf(buf + len, PAGE_SIZE - len, + "\n%08X%08X%08X%08X%08X%08X%08X", + priv->error->elem[i].time, + priv->error->elem[i].desc, + priv->error->elem[i].blink1, + priv->error->elem[i].blink2, + priv->error->elem[i].link1, + priv->error->elem[i].link2, + priv->error->elem[i].data); + + len += snprintf(buf + len, PAGE_SIZE - len, + "\n%08X", priv->error->log_len); + for (i = 0; i < priv->error->log_len; i++) + len += snprintf(buf + len, PAGE_SIZE - len, + "\n%08X%08X%08X", + priv->error->log[i].time, + priv->error->log[i].event, + priv->error->log[i].data); + len += snprintf(buf + len, PAGE_SIZE - len, "\n"); + return len; +} + +static ssize_t clear_error(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ipw_priv *priv = dev_get_drvdata(d); + if (priv->error) { + ipw_free_error_log(priv->error); + priv->error = NULL; + } + return count; +} + +static DEVICE_ATTR(error, S_IRUGO | S_IWUSR, show_error, clear_error); + static ssize_t show_scan_age(struct device *d, struct device_attribute *attr, char *buf) { @@ -1163,34 +1267,6 @@ static ssize_t show_nic_type(struct device *d, static DEVICE_ATTR(nic_type, S_IRUGO, show_nic_type, NULL); -static ssize_t dump_error_log(struct device *d, - struct device_attribute *attr, const char *buf, - size_t count) -{ - char *p = (char *)buf; - - if (p[0] == '1') - ipw_dump_nic_error_log((struct ipw_priv *)d->driver_data); - - return strnlen(buf, count); -} - -static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log); - -static ssize_t dump_event_log(struct device *d, - struct device_attribute *attr, const char *buf, - size_t count) -{ - char *p = (char *)buf; - - if (p[0] == '1') - ipw_dump_nic_event_log((struct ipw_priv *)d->driver_data); - - return strnlen(buf, count); -} - -static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log); - static ssize_t show_ucode_version(struct device *d, struct device_attribute *attr, char *buf) { @@ -1614,12 +1690,30 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) if (inta & IPW_INTA_BIT_FATAL_ERROR) { IPW_ERROR("Firmware error detected. Restarting.\n"); + if (priv->error) { + IPW_ERROR("Sysfs 'error' log already exists.\n"); #ifdef CONFIG_IPW_DEBUG - if (ipw_debug_level & IPW_DL_FW_ERRORS) { - ipw_dump_nic_error_log(priv); - ipw_dump_nic_event_log(priv); - } + if (ipw_debug_level & IPW_DL_FW_ERRORS) { + struct ipw_fw_error *error = + ipw_alloc_error_log(priv); + ipw_dump_error_log(priv, error); + if (error) + ipw_free_error_log(error); + } +#endif + } else { + priv->error = ipw_alloc_error_log(priv); + if (priv->error) + IPW_ERROR("Sysfs 'error' log captured.\n"); + else + IPW_ERROR("Error allocating sysfs 'error' " + "log.\n"); +#ifdef CONFIG_IPW_DEBUG + if (ipw_debug_level & IPW_DL_FW_ERRORS) + ipw_dump_error_log(priv, priv->error); #endif + } + /* XXX: If hardware encryption is for WPA/WPA2, * we have to notify the supplicant. */ if (priv->ieee->sec.encrypt) { @@ -10958,8 +11052,8 @@ static struct attribute *ipw_sysfs_entries[] = { &dev_attr_nic_type.attr, &dev_attr_status.attr, &dev_attr_cfg.attr, - &dev_attr_dump_errors.attr, - &dev_attr_dump_events.attr, + &dev_attr_error.attr, + &dev_attr_event_log.attr, &dev_attr_eeprom_delay.attr, &dev_attr_ucode_version.attr, &dev_attr_rtc.attr, @@ -11172,6 +11266,11 @@ static void ipw_pci_remove(struct pci_dev *pdev) } } + if (priv->error) { + ipw_free_error_log(priv->error); + priv->error = NULL; + } + free_irq(pdev->irq, priv); iounmap(priv->hw_base); pci_release_regions(pdev); diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index 9bf8aa427d8..9bf03ac5539 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -1085,6 +1085,32 @@ struct ipw_ibss_seq { struct list_head list; }; +struct ipw_error_elem { + u32 desc; + u32 time; + u32 blink1; + u32 blink2; + u32 link1; + u32 link2; + u32 data; +}; + +struct ipw_event { + u32 event; + u32 time; + u32 data; +} __attribute__ ((packed)); + +struct ipw_fw_error { + u32 status; + u32 config; + u32 elem_len; + u32 log_len; + struct ipw_error_elem *elem; + struct ipw_event *log; + u8 payload[0]; +} __attribute__ ((packed)); + struct ipw_priv { /* ieee device used by generic ieee processing code */ struct ieee80211_device *ieee; @@ -1245,6 +1271,8 @@ struct ipw_priv { u32 pm_state[16]; #endif + struct ipw_fw_error *error; + /* network state */ /* Used to pass the current INTA value from ISR to Tasklet */ @@ -1803,7 +1831,7 @@ enum { IPW_ORD_TABLE_7_LAST }; -#define IPWSTATUS_ERROR_LOG (IPW_SHARED_LOWER_BOUND + 0x410) +#define IPW_ERROR_LOG (IPW_SHARED_LOWER_BOUND + 0x410) #define IPW_EVENT_LOG (IPW_SHARED_LOWER_BOUND + 0x414) #define IPW_ORDINALS_TABLE_LOWER (IPW_SHARED_LOWER_BOUND + 0x500) #define IPW_ORDINALS_TABLE_0 (IPW_SHARED_LOWER_BOUND + 0x180) -- cgit v1.2.3 From 9ddf84f6f20335ce896feb459b19c3258bbf2e96 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Tue, 16 Aug 2005 17:07:11 -0500 Subject: Changed all of the ipw_send_cmd() calls to return any ipw_send_cmd error codes to the caller and changed ipw_send_cmd itself to print the error message to the syslog indicating which command failed to be sent. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 187 ++++++++--------------------------------- 1 file changed, 34 insertions(+), 153 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index a3283caaa87..ef100778503 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -1817,9 +1817,10 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) spin_lock_irqsave(&priv->lock, flags); if (priv->status & STATUS_HCMD_ACTIVE) { - IPW_ERROR("Already sending a command\n"); + IPW_ERROR("Failed to send %s: Already sending a command.\n", + get_cmd_string(cmd->cmd)); spin_unlock_irqrestore(&priv->lock, flags); - return -1; + return -EAGAIN; } priv->status |= STATUS_HCMD_ACTIVE; @@ -1832,6 +1833,8 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) rc = ipw_queue_tx_hcmd(priv, cmd->cmd, &cmd->param, cmd->len, 0); if (rc) { priv->status &= ~STATUS_HCMD_ACTIVE; + IPW_ERROR("Failed to send %s: Reason %d\n", + get_cmd_string(cmd->cmd), rc); spin_unlock_irqrestore(&priv->lock, flags); return rc; } @@ -1844,9 +1847,8 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) if (rc == 0) { spin_lock_irqsave(&priv->lock, flags); if (priv->status & STATUS_HCMD_ACTIVE) { - IPW_DEBUG_INFO("Command completion failed out after " - "%dms.\n", - 1000 * (HOST_COMPLETE_TIMEOUT / HZ)); + IPW_ERROR("Failed to send %s: Command timed out.\n", + get_cmd_string(cmd->cmd)); priv->status &= ~STATUS_HCMD_ACTIVE; spin_unlock_irqrestore(&priv->lock, flags); return -EIO; @@ -1855,7 +1857,8 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) } if (priv->status & STATUS_RF_KILL_HW) { - IPW_DEBUG_INFO("Command aborted due to RF Kill Switch\n"); + IPW_ERROR("Failed to send %s: Aborted due to RF kill switch.\n", + get_cmd_string(cmd->cmd)); return -EIO; } @@ -1874,12 +1877,7 @@ static int ipw_send_host_complete(struct ipw_priv *priv) return -1; } - if (ipw_send_cmd(priv, &cmd)) { - IPW_ERROR("failed to send HOST_COMPLETE command\n"); - return -1; - } - - return 0; + return ipw_send_cmd(priv, &cmd); } static int ipw_send_system_config(struct ipw_priv *priv, @@ -1896,12 +1894,7 @@ static int ipw_send_system_config(struct ipw_priv *priv, } memcpy(cmd.param, config, sizeof(*config)); - if (ipw_send_cmd(priv, &cmd)) { - IPW_ERROR("failed to send SYSTEM_CONFIG command\n"); - return -1; - } - - return 0; + return ipw_send_cmd(priv, &cmd); } static int ipw_send_ssid(struct ipw_priv *priv, u8 * ssid, int len) @@ -1917,12 +1910,7 @@ static int ipw_send_ssid(struct ipw_priv *priv, u8 * ssid, int len) } memcpy(cmd.param, ssid, cmd.len); - if (ipw_send_cmd(priv, &cmd)) { - IPW_ERROR("failed to send SSID command\n"); - return -1; - } - - return 0; + return ipw_send_cmd(priv, &cmd); } static int ipw_send_adapter_address(struct ipw_priv *priv, u8 * mac) @@ -1941,12 +1929,7 @@ static int ipw_send_adapter_address(struct ipw_priv *priv, u8 * mac) priv->net_dev->name, MAC_ARG(mac)); memcpy(cmd.param, mac, ETH_ALEN); - if (ipw_send_cmd(priv, &cmd)) { - IPW_ERROR("failed to send ADAPTER_ADDRESS command\n"); - return -1; - } - - return 0; + return ipw_send_cmd(priv, &cmd); } /* @@ -2011,12 +1994,7 @@ static int ipw_send_scan_request_ext(struct ipw_priv *priv, }; memcpy(cmd.param, request, sizeof(*request)); - if (ipw_send_cmd(priv, &cmd)) { - IPW_ERROR("failed to send SCAN_REQUEST_EXT command\n"); - return -1; - } - - return 0; + return ipw_send_cmd(priv, &cmd); } static int ipw_send_scan_abort(struct ipw_priv *priv) @@ -2031,12 +2009,7 @@ static int ipw_send_scan_abort(struct ipw_priv *priv) return -1; } - if (ipw_send_cmd(priv, &cmd)) { - IPW_ERROR("failed to send SCAN_ABORT command\n"); - return -1; - } - - return 0; + return ipw_send_cmd(priv, &cmd); } static int ipw_set_sensitivity(struct ipw_priv *priv, u16 sens) @@ -2048,12 +2021,7 @@ static int ipw_set_sensitivity(struct ipw_priv *priv, u16 sens) struct ipw_sensitivity_calib *calib = (struct ipw_sensitivity_calib *) &cmd.param; calib->beacon_rssi_raw = sens; - if (ipw_send_cmd(priv, &cmd)) { - IPW_ERROR("failed to send SENSITIVITY CALIB command\n"); - return -1; - } - - return 0; + return ipw_send_cmd(priv, &cmd); } static int ipw_send_associate(struct ipw_priv *priv, @@ -2083,12 +2051,7 @@ static int ipw_send_associate(struct ipw_priv *priv, } memcpy(cmd.param, &tmp_associate, sizeof(*associate)); - if (ipw_send_cmd(priv, &cmd)) { - IPW_ERROR("failed to send ASSOCIATE command\n"); - return -1; - } - - return 0; + return ipw_send_cmd(priv, &cmd); } static int ipw_send_supported_rates(struct ipw_priv *priv, @@ -2105,12 +2068,7 @@ static int ipw_send_supported_rates(struct ipw_priv *priv, } memcpy(cmd.param, rates, sizeof(*rates)); - if (ipw_send_cmd(priv, &cmd)) { - IPW_ERROR("failed to send SUPPORTED_RATES command\n"); - return -1; - } - - return 0; + return ipw_send_cmd(priv, &cmd); } static int ipw_set_random_seed(struct ipw_priv *priv) @@ -2127,12 +2085,7 @@ static int ipw_set_random_seed(struct ipw_priv *priv) get_random_bytes(&cmd.param, sizeof(u32)); - if (ipw_send_cmd(priv, &cmd)) { - IPW_ERROR("failed to send SEED_NUMBER command\n"); - return -1; - } - - return 0; + return ipw_send_cmd(priv, &cmd); } static int ipw_send_card_disable(struct ipw_priv *priv, u32 phy_off) @@ -2149,12 +2102,7 @@ static int ipw_send_card_disable(struct ipw_priv *priv, u32 phy_off) *((u32 *) & cmd.param) = phy_off; - if (ipw_send_cmd(priv, &cmd)) { - IPW_ERROR("failed to send CARD_DISABLE command\n"); - return -1; - } - - return 0; + return ipw_send_cmd(priv, &cmd); } static int ipw_send_tx_power(struct ipw_priv *priv, struct ipw_tx_power *power) @@ -2170,12 +2118,7 @@ static int ipw_send_tx_power(struct ipw_priv *priv, struct ipw_tx_power *power) } memcpy(cmd.param, power, sizeof(*power)); - if (ipw_send_cmd(priv, &cmd)) { - IPW_ERROR("failed to send TX_POWER command\n"); - return -1; - } - - return 0; + return ipw_send_cmd(priv, &cmd); } static int ipw_set_tx_power(struct ipw_priv *priv) @@ -2238,12 +2181,7 @@ static int ipw_send_rts_threshold(struct ipw_priv *priv, u16 rts) } memcpy(cmd.param, &rts_threshold, sizeof(rts_threshold)); - if (ipw_send_cmd(priv, &cmd)) { - IPW_ERROR("failed to send RTS_THRESHOLD command\n"); - return -1; - } - - return 0; + return ipw_send_cmd(priv, &cmd); } static int ipw_send_frag_threshold(struct ipw_priv *priv, u16 frag) @@ -2262,12 +2200,7 @@ static int ipw_send_frag_threshold(struct ipw_priv *priv, u16 frag) } memcpy(cmd.param, &frag_threshold, sizeof(frag_threshold)); - if (ipw_send_cmd(priv, &cmd)) { - IPW_ERROR("failed to send FRAG_THRESHOLD command\n"); - return -1; - } - - return 0; + return ipw_send_cmd(priv, &cmd); } static int ipw_send_power_mode(struct ipw_priv *priv, u32 mode) @@ -2297,12 +2230,7 @@ static int ipw_send_power_mode(struct ipw_priv *priv, u32 mode) break; } - if (ipw_send_cmd(priv, &cmd)) { - IPW_ERROR("failed to send POWER_MODE command\n"); - return -1; - } - - return 0; + return ipw_send_cmd(priv, &cmd); } static int ipw_send_retry_limit(struct ipw_priv *priv, u8 slimit, u8 llimit) @@ -2322,12 +2250,7 @@ static int ipw_send_retry_limit(struct ipw_priv *priv, u8 slimit, u8 llimit) } memcpy(cmd.param, &retry_limit, sizeof(retry_limit)); - if (ipw_send_cmd(priv, &cmd)) { - IPW_ERROR("failed to send RETRY_LIMIT command\n"); - return -1; - } - - return 0; + return ipw_send_cmd(priv, &cmd); } /* @@ -3608,20 +3531,6 @@ static void ipw_tx_queue_free(struct ipw_priv *priv) ipw_queue_tx_free(priv, &priv->txq[3]); } -static void inline __maybe_wake_tx(struct ipw_priv *priv) -{ - if (netif_running(priv->net_dev)) { - switch (priv->port_type) { - case DCR_TYPE_MU_BSS: - case DCR_TYPE_MU_IBSS: - if (!(priv->status & STATUS_ASSOCIATED)) - return; - } - netif_wake_queue(priv->net_dev); - } - -} - static inline void ipw_create_bssid(struct ipw_priv *priv, u8 * bssid) { /* First 3 bytes are manufacturer */ @@ -4713,8 +4622,10 @@ static int ipw_queue_tx_reclaim(struct ipw_priv *priv, priv->tx_packets++; } done: - if (ipw_queue_space(q) > q->low_mark && qindex >= 0) - __maybe_wake_tx(priv); + if ((ipw_queue_space(q) > q->low_mark) && + (qindex >= 0) && + (priv->status & STATUS_ASSOCIATED) && netif_running(priv->net_dev)) + netif_wake_queue(priv->net_dev); used = q->first_empty - q->last_used; if (used < 0) used += q->n_bd; @@ -5657,10 +5568,7 @@ static void ipw_send_tgi_tx_key(struct ipw_priv *priv, int type, int index) key->tx_counter[0] = 0; key->tx_counter[1] = 0; - if (ipw_send_cmd(priv, &cmd)) { - IPW_ERROR("failed to send TGI_TX_KEY command\n"); - return; - } + ipw_send_cmd(priv, &cmd); } static void ipw_send_wep_keys(struct ipw_priv *priv, int type) @@ -5688,10 +5596,7 @@ static void ipw_send_wep_keys(struct ipw_priv *priv, int type) key->key_size = priv->ieee->sec.key_sizes[i]; memcpy(key->key, priv->ieee->sec.keys[i], key->key_size); - if (ipw_send_cmd(priv, &cmd)) { - IPW_ERROR("failed to send WEP_KEY command\n"); - return; - } + ipw_send_cmd(priv, &cmd); } } @@ -6249,11 +6154,7 @@ static int ipw_set_rsn_capa(struct ipw_priv *priv, IPW_DEBUG_HC("HOST_CMD_RSN_CAPABILITIES\n"); memcpy(cmd.param, capabilities, length); - if (ipw_send_cmd(priv, &cmd)) { - IPW_ERROR("failed to send HOST_CMD_RSN_CAPABILITIES command\n"); - return -1; - } - return 0; + return ipw_send_cmd(priv, &cmd); } #if WIRELESS_EXT < 18 @@ -7435,18 +7336,8 @@ static int ipw_send_qos_params_command(struct ipw_priv *priv, struct ieee80211_q .len = (sizeof(struct ieee80211_qos_parameters) * 3) }; - if (!priv || !qos_param) { - IPW_ERROR("Invalid args\n"); - return -1; - } - memcpy(cmd.param, qos_param, sizeof(*qos_param) * 3); - if (ipw_send_cmd(priv, &cmd)) { - IPW_ERROR("failed to send IPW_CMD_QOS_PARAMETERS command\n"); - return -1; - } - - return 0; + return ipw_send_cmd(priv, &cmd); } static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos_information_element @@ -7457,18 +7348,8 @@ static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos .len = sizeof(*qos_param) }; - if (!priv || !qos_param) { - IPW_ERROR("Invalid args\n"); - return -1; - } - memcpy(cmd.param, qos_param, sizeof(*qos_param)); - if (ipw_send_cmd(priv, &cmd)) { - IPW_ERROR("failed to send CMD_QOS_INFO command\n"); - return -1; - } - - return 0; + return ipw_send_cmd(priv, &cmd); } #endif /* CONFIG_IPW_QOS */ -- cgit v1.2.3 From f6c5cb7c6f8a85045996bfc3442af963d6578d60 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Thu, 25 Aug 2005 00:39:09 -0500 Subject: Added cmdlog in non-debug systems. You can now specify via the module parameter 'cmdlog' to allocate a ring buffer for caching host commands sent to the firmware. They can then be dumped at any time via the sysfs entry 'cmd_log' Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 120 ++++++++++++++++++++++++++++++++++++----- drivers/net/wireless/ipw2200.h | 11 ++++ 2 files changed, 117 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index ef100778503..bcb5993b68b 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -44,6 +44,7 @@ MODULE_VERSION(DRV_VERSION); MODULE_AUTHOR(DRV_COPYRIGHT); MODULE_LICENSE("GPL"); +static int cmdlog = 0; static int debug = 0; static int channel = 0; static int mode = 0; @@ -148,8 +149,8 @@ static int init_supported_rates(struct ipw_priv *priv, static void ipw_set_hwcrypto_keys(struct ipw_priv *); static void ipw_send_wep_keys(struct ipw_priv *, int); -static char *snprint_line(char *buf, size_t count, - const u8 * data, u32 len, u32 ofs) +static int snprint_line(char *buf, size_t count, + const u8 * data, u32 len, u32 ofs) { int out, i, j, l; char c; @@ -180,7 +181,7 @@ static char *snprint_line(char *buf, size_t count, out += snprintf(buf + out, count - out, " "); } - return buf; + return out; } static void printk_buf(int level, const u8 * data, u32 len) @@ -191,14 +192,33 @@ static void printk_buf(int level, const u8 * data, u32 len) return; while (len) { - printk(KERN_DEBUG "%s\n", - snprint_line(line, sizeof(line), &data[ofs], - min(len, 16U), ofs)); + snprint_line(line, sizeof(line), &data[ofs], + min(len, 16U), ofs); + printk(KERN_DEBUG "%s\n", line); ofs += 16; len -= min(len, 16U); } } +static int snprintk_buf(u8 * output, size_t size, const u8 * data, size_t len) +{ + size_t out = size; + u32 ofs = 0; + int total = 0; + + while (size && len) { + out = snprint_line(output, size, &data[ofs], + min_t(size_t, len, 16U), ofs); + + ofs += 16; + output += out; + size -= out; + len -= min_t(size_t, len, 16U); + total += out; + } + return total; +} + static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg); #define ipw_read_reg32(a, b) _ipw_read_reg32(a, b) @@ -272,9 +292,15 @@ static inline u32 __ipw_read32(char *f, u32 l, struct ipw_priv *ipw, u32 ofs) #define ipw_read32(ipw, ofs) __ipw_read32(__FILE__, __LINE__, ipw, ofs) static void _ipw_read_indirect(struct ipw_priv *, u32, u8 *, int); -#define ipw_read_indirect(a, b, c, d) \ - IPW_DEBUG_IO("%s %d: read_indirect(0x%08X) %d bytes\n", __FILE__, __LINE__, (u32)(b), d); \ - _ipw_read_indirect(a, b, c, d) +static inline void __ipw_read_indirect(const char *f, int l, + struct ipw_priv *a, u32 b, u8 * c, int d) +{ + IPW_DEBUG_IO("%s %d: read_indirect(0x%08X) %d bytes\n", f, l, (u32) (b), + d); + _ipw_read_indirect(a, b, c, d); +} + +#define ipw_read_indirect(a, b, c, d) __ipw_read_indirect(__FILE__, __LINE__, a, b, c, d) static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * data, int num); @@ -1070,6 +1096,7 @@ static struct ipw_fw_error *ipw_alloc_error_log(struct ipw_priv *priv) "failed.\n"); return NULL; } + error->jiffies = jiffies; error->status = priv->status; error->config = priv->config; error->elem_len = elem_len; @@ -1122,7 +1149,8 @@ static ssize_t show_error(struct device *d, if (!priv->error) return 0; len += snprintf(buf + len, PAGE_SIZE - len, - "%08X%08X%08X", + "%08lX%08X%08X%08X", + priv->error->jiffies, priv->error->status, priv->error->config, priv->error->elem_len); for (i = 0; i < priv->error->elem_len; i++) @@ -1162,6 +1190,33 @@ static ssize_t clear_error(struct device *d, static DEVICE_ATTR(error, S_IRUGO | S_IWUSR, show_error, clear_error); +static ssize_t show_cmd_log(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct ipw_priv *priv = dev_get_drvdata(d); + u32 len = 0, i; + if (!priv->cmdlog) + return 0; + for (i = (priv->cmdlog_pos + 1) % priv->cmdlog_len; + (i != priv->cmdlog_pos) && (PAGE_SIZE - len); + i = (i + 1) % priv->cmdlog_len) { + len += + snprintf(buf + len, PAGE_SIZE - len, + "\n%08lX%08X%08X%08X\n", priv->cmdlog[i].jiffies, + priv->cmdlog[i].retcode, priv->cmdlog[i].cmd.cmd, + priv->cmdlog[i].cmd.len); + len += + snprintk_buf(buf + len, PAGE_SIZE - len, + (u8 *) priv->cmdlog[i].cmd.param, + priv->cmdlog[i].cmd.len); + len += snprintf(buf + len, PAGE_SIZE - len, "\n"); + } + len += snprintf(buf + len, PAGE_SIZE - len, "\n"); + return len; +} + +static DEVICE_ATTR(cmd_log, S_IRUGO, show_cmd_log, NULL); + static ssize_t show_scan_age(struct device *d, struct device_attribute *attr, char *buf) { @@ -1825,6 +1880,15 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) priv->status |= STATUS_HCMD_ACTIVE; + if (priv->cmdlog) { + priv->cmdlog[priv->cmdlog_pos].jiffies = jiffies; + priv->cmdlog[priv->cmdlog_pos].cmd.cmd = cmd->cmd; + priv->cmdlog[priv->cmdlog_pos].cmd.len = cmd->len; + memcpy(priv->cmdlog[priv->cmdlog_pos].cmd.param, cmd->param, + cmd->len); + priv->cmdlog[priv->cmdlog_pos].retcode = -1; + } + IPW_DEBUG_HC("%s command (#%d) %d bytes: 0x%08X\n", get_cmd_string(cmd->cmd), cmd->cmd, cmd->len, priv->status); @@ -1836,7 +1900,7 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) IPW_ERROR("Failed to send %s: Reason %d\n", get_cmd_string(cmd->cmd), rc); spin_unlock_irqrestore(&priv->lock, flags); - return rc; + goto exit; } spin_unlock_irqrestore(&priv->lock, flags); @@ -1851,7 +1915,8 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) get_cmd_string(cmd->cmd)); priv->status &= ~STATUS_HCMD_ACTIVE; spin_unlock_irqrestore(&priv->lock, flags); - return -EIO; + rc = -EIO; + goto exit; } spin_unlock_irqrestore(&priv->lock, flags); } @@ -1859,10 +1924,16 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) if (priv->status & STATUS_RF_KILL_HW) { IPW_ERROR("Failed to send %s: Aborted due to RF kill switch.\n", get_cmd_string(cmd->cmd)); - return -EIO; + rc = -EIO; + goto exit; } - return 0; + exit: + if (priv->cmdlog) { + priv->cmdlog[priv->cmdlog_pos++].retcode = rc; + priv->cmdlog_pos %= priv->cmdlog_len; + } + return rc; } static int ipw_send_host_complete(struct ipw_priv *priv) @@ -10712,6 +10783,18 @@ static int ipw_up(struct ipw_priv *priv) if (priv->status & STATUS_EXIT_PENDING) return -EIO; + if (cmdlog && !priv->cmdlog) { + priv->cmdlog = kmalloc(sizeof(*priv->cmdlog) * cmdlog, + GFP_KERNEL); + if (priv->cmdlog == NULL) { + IPW_ERROR("Error allocating %d command log entries.\n", + cmdlog); + } else { + memset(priv->cmdlog, 0, sizeof(*priv->cmdlog) * cmdlog); + priv->cmdlog_len = cmdlog; + } + } + for (i = 0; i < MAX_HW_RESTARTS; i++) { /* Load the microcode, firmware, and eeprom. * Also start the clocks. */ @@ -10935,6 +11018,7 @@ static struct attribute *ipw_sysfs_entries[] = { &dev_attr_cfg.attr, &dev_attr_error.attr, &dev_attr_event_log.attr, + &dev_attr_cmd_log.attr, &dev_attr_eeprom_delay.attr, &dev_attr_ucode_version.attr, &dev_attr_rtc.attr, @@ -11129,6 +11213,10 @@ static void ipw_pci_remove(struct pci_dev *pdev) } ipw_tx_queue_free(priv); + if (priv->cmdlog) { + kfree(priv->cmdlog); + priv->cmdlog = NULL; + } /* ipw_down will ensure that there is no more pending work * in the workqueue's, so we can safely remove them now. */ cancel_delayed_work(&priv->adhoc_check); @@ -11302,5 +11390,9 @@ MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS)"); module_param(hwcrypto, int, 0444); MODULE_PARM_DESC(hwcrypto, "enable hardware crypto (default on)"); +module_param(cmdlog, int, 0444); +MODULE_PARM_DESC(cmdlog, + "allocate a ring buffer for logging firmware commands"); + module_exit(ipw_exit); module_init(ipw_init); diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index 9bf03ac5539..255f0cb66f6 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -1102,6 +1102,7 @@ struct ipw_event { } __attribute__ ((packed)); struct ipw_fw_error { + unsigned long jiffies; u32 status; u32 config; u32 elem_len; @@ -1261,6 +1262,10 @@ struct ipw_priv { struct work_struct led_act_off; struct work_struct merge_networks; + struct ipw_cmd_log *cmdlog; + int cmdlog_len; + int cmdlog_pos; + #define IPW_2200BG 1 #define IPW_2915ABG 2 u8 adapter; @@ -1853,6 +1858,12 @@ struct host_cmd { u32 param[TFD_CMD_IMMEDIATE_PAYLOAD_LENGTH]; } __attribute__ ((packed)); +struct ipw_cmd_log { + unsigned long jiffies; + int retcode; + struct host_cmd cmd; +}; + #define CFG_BT_COEXISTENCE_MIN 0x00 #define CFG_BT_COEXISTENCE_DEFER 0x02 #define CFG_BT_COEXISTENCE_KILL 0x04 -- cgit v1.2.3 From 1fe0adb4314009362d28205bbf09f6d758e82002 Mon Sep 17 00:00:00 2001 From: Liu Hong Date: Fri, 19 Aug 2005 09:33:10 -0500 Subject: Migrated some of the channel verification code back into the driver to keep regulatory consistency in one location. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 173 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 152 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index bcb5993b68b..40759e5f3cc 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -149,6 +149,12 @@ static int init_supported_rates(struct ipw_priv *priv, static void ipw_set_hwcrypto_keys(struct ipw_priv *); static void ipw_send_wep_keys(struct ipw_priv *, int); +static int ipw_is_valid_channel(struct ieee80211_device *, u8); +static int ipw_channel_to_index(struct ieee80211_device *, u8); +static u8 ipw_freq_to_channel(struct ieee80211_device *, u32); +static int ipw_set_geo(struct ieee80211_device *, const struct ieee80211_geo *); +static const struct ieee80211_geo *ipw_get_geo(struct ieee80211_device *); + static int snprint_line(char *buf, size_t count, const u8 * data, u32 len, u32 ofs) { @@ -1596,7 +1602,7 @@ static ssize_t store_speed_scan(struct device *d, struct device_attribute *attr, break; } - if (ieee80211_is_valid_channel(priv->ieee, channel)) + if (ipw_is_valid_channel(priv->ieee, channel)) priv->speed_scan[pos++] = channel; else IPW_WARNING("Skipping invalid channel request: %d\n", @@ -2194,7 +2200,7 @@ static int ipw_send_tx_power(struct ipw_priv *priv, struct ipw_tx_power *power) static int ipw_set_tx_power(struct ipw_priv *priv) { - const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); + const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee); struct ipw_tx_power tx_power; s8 max_power; int i; @@ -5503,6 +5509,15 @@ static int ipw_best_network(struct ipw_priv *priv, return 0; } + /* Filter out invalid channel in current GEO */ + if (!ipw_is_valid_channel(priv->ieee, network->channel)) { + IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " + "because of invalid channel in current GEO\n", + escape_essid(network->ssid, network->ssid_len), + MAC_ARG(network->bssid)); + return 0; + } + /* Ensure that the rates supported by the driver are compatible with * this AP, including verification of basic rates (mandatory) */ if (!ipw_compatible_rates(priv, network, &rates)) { @@ -5540,7 +5555,7 @@ static int ipw_best_network(struct ipw_priv *priv, static void ipw_adhoc_create(struct ipw_priv *priv, struct ieee80211_network *network) { - const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); + const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee); int i; /* @@ -5555,10 +5570,10 @@ static void ipw_adhoc_create(struct ipw_priv *priv, * FW fatal error. * */ - switch (ieee80211_is_valid_channel(priv->ieee, priv->channel)) { + switch (ipw_is_valid_channel(priv->ieee, priv->channel)) { case IEEE80211_52GHZ_BAND: network->mode = IEEE_A; - i = ieee80211_channel_to_index(priv->ieee, priv->channel); + i = ipw_channel_to_index(priv->ieee, priv->channel); if (i == -1) BUG(); if (geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY) { @@ -5572,6 +5587,13 @@ static void ipw_adhoc_create(struct ipw_priv *priv, network->mode = IEEE_G; else network->mode = IEEE_B; + i = ipw_channel_to_index(priv->ieee, priv->channel); + if (i == -1) + BUG(); + if (geo->bg[i].flags & IEEE80211_CH_PASSIVE_ONLY) { + IPW_WARNING("Overriding invalid channel\n"); + priv->channel = geo->bg[0].channel; + } break; default: @@ -5899,7 +5921,7 @@ static void ipw_add_scan_channels(struct ipw_priv *priv, const struct ieee80211_geo *geo; int i; - geo = ieee80211_get_geo(priv->ieee); + geo = ipw_get_geo(priv->ieee); if (priv->ieee->freq_band & IEEE80211_52GHZ_BAND) { int start = channel_index; @@ -5909,7 +5931,11 @@ static void ipw_add_scan_channels(struct ipw_priv *priv, continue; channel_index++; scan->channels_list[channel_index] = geo->a[i].channel; - ipw_set_scan_type(scan, channel_index, scan_type); + ipw_set_scan_type(scan, channel_index, + geo->a[i]. + flags & IEEE80211_CH_PASSIVE_ONLY ? + IPW_SCAN_PASSIVE_FULL_DWELL_SCAN : + scan_type); } if (start != channel_index) { @@ -5922,6 +5948,7 @@ static void ipw_add_scan_channels(struct ipw_priv *priv, if (priv->ieee->freq_band & IEEE80211_24GHZ_BAND) { int start = channel_index; if (priv->config & CFG_SPEED_SCAN) { + int index; u8 channels[IEEE80211_24GHZ_CHANNELS] = { /* nop out the list */ [0] = 0 @@ -5953,8 +5980,14 @@ static void ipw_add_scan_channels(struct ipw_priv *priv, priv->speed_scan_pos++; channel_index++; scan->channels_list[channel_index] = channel; + index = + ipw_channel_to_index(priv->ieee, channel); ipw_set_scan_type(scan, channel_index, - scan_type); + geo->bg[index]. + flags & + IEEE80211_CH_PASSIVE_ONLY ? + IPW_SCAN_PASSIVE_FULL_DWELL_SCAN + : scan_type); } } else { for (i = 0; i < geo->bg_channels; i++) { @@ -5965,7 +5998,11 @@ static void ipw_add_scan_channels(struct ipw_priv *priv, scan->channels_list[channel_index] = geo->bg[i].channel; ipw_set_scan_type(scan, channel_index, - scan_type); + geo->bg[i]. + flags & + IEEE80211_CH_PASSIVE_ONLY ? + IPW_SCAN_PASSIVE_FULL_DWELL_SCAN + : scan_type); } } @@ -6017,7 +6054,7 @@ static int ipw_request_scan(struct ipw_priv *priv) scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] = cpu_to_le16(20); - scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(20); + scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(120); scan.full_scan_index = cpu_to_le32(ieee80211_get_scans(priv->ieee)); @@ -6026,7 +6063,7 @@ static int ipw_request_scan(struct ipw_priv *priv) u8 channel; u8 band = 0; - switch (ieee80211_is_valid_channel(priv->ieee, priv->channel)) { + switch (ipw_is_valid_channel(priv->ieee, priv->channel)) { case IEEE80211_52GHZ_BAND: band = (u8) (IPW_A_MODE << 6) | 1; channel = priv->channel; @@ -8401,10 +8438,11 @@ static int ipw_wx_set_freq(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); - const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); + const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee); struct iw_freq *fwrq = &wrqu->freq; int ret = 0, i; - u8 channel; + u8 channel, flags; + int band; if (fwrq->m == 0) { IPW_DEBUG_WX("SET Freq/Channel -> any\n"); @@ -8415,20 +8453,23 @@ static int ipw_wx_set_freq(struct net_device *dev, } /* if setting by freq convert to channel */ if (fwrq->e == 1) { - channel = ieee80211_freq_to_channel(priv->ieee, fwrq->m); + channel = ipw_freq_to_channel(priv->ieee, fwrq->m); if (channel == 0) return -EINVAL; } else channel = fwrq->m; - if (!ieee80211_is_valid_channel(priv->ieee, channel)) + if (!(band = ipw_is_valid_channel(priv->ieee, channel))) return -EINVAL; - if (priv->ieee->iw_mode == IW_MODE_ADHOC && priv->ieee->mode & IEEE_A) { - i = ieee80211_channel_to_index(priv->ieee, channel); + if (priv->ieee->iw_mode == IW_MODE_ADHOC) { + i = ipw_channel_to_index(priv->ieee, channel); if (i == -1) return -EINVAL; - if (geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY) { + + flags = (band == IEEE80211_24GHZ_BAND) ? + geo->bg[i].flags : geo->a[i].flags; + if (flags & IEEE80211_CH_PASSIVE_ONLY) { IPW_DEBUG_WX("Invalid Ad-Hoc channel for 802.11a\n"); return -EINVAL; } @@ -8546,7 +8587,7 @@ static int ipw_wx_get_range(struct net_device *dev, { struct ipw_priv *priv = ieee80211_priv(dev); struct iw_range *range = (struct iw_range *)extra; - const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); + const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee); int i = 0, j; wrqu->data.length = sizeof(*range); @@ -9147,7 +9188,7 @@ static int ipw_request_direct_scan(struct ipw_priv *priv, char *essid, scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] = cpu_to_le16(20); - scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(20); + scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(120); scan.dwell_time[IPW_SCAN_ACTIVE_DIRECT_SCAN] = cpu_to_le16(20); scan.full_scan_index = cpu_to_le32(ieee80211_get_scans(priv->ieee)); @@ -10775,6 +10816,96 @@ static const struct ieee80211_geo ipw_geos[] = { } }; +/* GEO code borrowed from ieee80211_geo.c */ +static int ipw_is_valid_channel(struct ieee80211_device *ieee, u8 channel) +{ + int i; + + /* Driver needs to initialize the geography map before using + * these helper functions */ + BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0); + + if (ieee->freq_band & IEEE80211_24GHZ_BAND) + for (i = 0; i < ieee->geo.bg_channels; i++) + /* NOTE: If G mode is currently supported but + * this is a B only channel, we don't see it + * as valid. */ + if ((ieee->geo.bg[i].channel == channel) && + (!(ieee->mode & IEEE_G) || + !(ieee->geo.bg[i].flags & IEEE80211_CH_B_ONLY))) + return IEEE80211_24GHZ_BAND; + + if (ieee->freq_band & IEEE80211_52GHZ_BAND) + for (i = 0; i < ieee->geo.a_channels; i++) + if (ieee->geo.a[i].channel == channel) + return IEEE80211_52GHZ_BAND; + + return 0; +} + +static int ipw_channel_to_index(struct ieee80211_device *ieee, u8 channel) +{ + int i; + + /* Driver needs to initialize the geography map before using + * these helper functions */ + BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0); + + if (ieee->freq_band & IEEE80211_24GHZ_BAND) + for (i = 0; i < ieee->geo.bg_channels; i++) + if (ieee->geo.bg[i].channel == channel) + return i; + + if (ieee->freq_band & IEEE80211_52GHZ_BAND) + for (i = 0; i < ieee->geo.a_channels; i++) + if (ieee->geo.a[i].channel == channel) + return i; + + return -1; +} + +static u8 ipw_freq_to_channel(struct ieee80211_device *ieee, u32 freq) +{ + int i; + + /* Driver needs to initialize the geography map before using + * these helper functions */ + BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0); + + freq /= 100000; + + if (ieee->freq_band & IEEE80211_24GHZ_BAND) + for (i = 0; i < ieee->geo.bg_channels; i++) + if (ieee->geo.bg[i].freq == freq) + return ieee->geo.bg[i].channel; + + if (ieee->freq_band & IEEE80211_52GHZ_BAND) + for (i = 0; i < ieee->geo.a_channels; i++) + if (ieee->geo.a[i].freq == freq) + return ieee->geo.a[i].channel; + + return 0; +} + +static int ipw_set_geo(struct ieee80211_device *ieee, + const struct ieee80211_geo *geo) +{ + memcpy(ieee->geo.name, geo->name, 3); + ieee->geo.name[3] = '\0'; + ieee->geo.bg_channels = geo->bg_channels; + ieee->geo.a_channels = geo->a_channels; + memcpy(ieee->geo.bg, geo->bg, geo->bg_channels * + sizeof(struct ieee80211_channel)); + memcpy(ieee->geo.a, geo->a, ieee->geo.a_channels * + sizeof(struct ieee80211_channel)); + return 0; +} + +static const struct ieee80211_geo *ipw_get_geo(struct ieee80211_device *ieee) +{ + return &ieee->geo; +} + #define MAX_HW_RESTARTS 5 static int ipw_up(struct ipw_priv *priv) { @@ -10816,7 +10947,7 @@ static int ipw_up(struct ipw_priv *priv) } if (j == ARRAY_SIZE(ipw_geos)) j = 0; - if (ieee80211_set_geo(priv->ieee, &ipw_geos[j])) { + if (ipw_set_geo(priv->ieee, &ipw_geos[j])) { IPW_WARNING("Could not set geography."); return 0; } -- cgit v1.2.3 From 3b9990cb1751d3d267c0e5c94bff0f155c944c66 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Fri, 19 Aug 2005 13:18:55 -0500 Subject: Updated ipw2200 to use the new ieee80211 callbacks (handle_probe_response, handle_beacon, handle_association_response). Fixed a problem with ipw_send_cmd() returning non-zero on success. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 61 ++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 40759e5f3cc..53a6bb2dbd4 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -1925,7 +1925,8 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) goto exit; } spin_unlock_irqrestore(&priv->lock, flags); - } + } else + rc = 0; if (priv->status & STATUS_RF_KILL_HW) { IPW_ERROR("Failed to send %s: Aborted due to RF kill switch.\n", @@ -7011,9 +7012,9 @@ u8 ipw_qos_current_mode(struct ipw_priv * priv) /* * Handle management frame beacon and probe response */ -static int ipw_qos_handle_probe_reponse(struct ipw_priv *priv, - int active_network, - struct ieee80211_network *network) +static int ipw_qos_handle_probe_response(struct ipw_priv *priv, + int active_network, + struct ieee80211_network *network) { u32 size = sizeof(struct ieee80211_qos_parameters); @@ -7407,35 +7408,41 @@ static void ipw_bg_qos_activate(void *data) up(&priv->sem); } -/* -* Handler for probe responce and beacon frame -*/ -static int ipw_handle_management(struct net_device *dev, - struct ieee80211_network *network, u16 type) +static int ipw_handle_probe_response(struct net_device *dev, + struct ieee80211_probe_response *resp, + struct ieee80211_network *network) { struct ipw_priv *priv = ieee80211_priv(dev); - int active_network; + int active_network = ((priv->status & STATUS_ASSOCIATED) && + (network == priv->assoc_network)); - if (priv->status & STATUS_ASSOCIATED && network == priv->assoc_network) - active_network = 1; - else - active_network = 0; + ipw_qos_handle_probe_response(priv, active_network, network); - switch (type) { - case IEEE80211_STYPE_PROBE_RESP: - case IEEE80211_STYPE_BEACON: - ipw_qos_handle_probe_reponse(priv, active_network, network); - break; - case IEEE80211_STYPE_ASSOC_RESP: - ipw_qos_association_resp(priv, network); - break; - default: - break; - } + return 0; +} + +static int ipw_handle_beacon(struct net_device *dev, + struct ieee80211_beacon *resp, + struct ieee80211_network *network) +{ + struct ipw_priv *priv = ieee80211_priv(dev); + int active_network = ((priv->status & STATUS_ASSOCIATED) && + (network == priv->assoc_network)); + + ipw_qos_handle_probe_response(priv, active_network, network); return 0; } +static int ipw_handle_assoc_response(struct net_device *dev, + struct ieee80211_assoc_response *resp, + struct ieee80211_network *network) +{ + struct ipw_priv *priv = ieee80211_priv(dev); + ipw_qos_association_resp(priv, network); + return 0; +} + static int ipw_send_qos_params_command(struct ipw_priv *priv, struct ieee80211_qos_parameters *qos_param) { @@ -11260,7 +11267,9 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) priv->ieee->is_queue_full = ipw_net_is_queue_full; #ifdef CONFIG_IPW_QOS - priv->ieee->handle_management = ipw_handle_management; + priv->ieee->handle_probe_response = ipw_handle_beacon; + priv->ieee->handle_beacon = ipw_handle_probe_response; + priv->ieee->handle_assoc_response = ipw_handle_assoc_response; #endif /* CONFIG_IPW_QOS */ priv->ieee->perfect_rssi = -20; -- cgit v1.2.3 From a0e04ab36048eb1c3da2524b5b0b802b6ab064f0 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Thu, 25 Aug 2005 00:49:43 -0500 Subject: Added wait_state wakeup on scan completion. Fixed copyright date in ipw2200.h Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 1 + drivers/net/wireless/ipw2200.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 53a6bb2dbd4..9ced5b778a7 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -4450,6 +4450,7 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, priv->status &= ~(STATUS_SCANNING | STATUS_SCAN_ABORTING); + wake_up_interruptible(&priv->wait_state); cancel_delayed_work(&priv->scan_check); if (priv->status & STATUS_EXIT_PENDING) diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index 255f0cb66f6..f2056b62254 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved. + Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as -- cgit v1.2.3 From 7b99659f97ca20e5f1ea56253a9449d278d825d5 Mon Sep 17 00:00:00 2001 From: Hong Liu Date: Thu, 25 Aug 2005 17:36:13 +0800 Subject: [Bug 455] Fix frequent channel change generates firmware fatal error. Because of the frequent channel change, it is possible that when we are try to associate with channel 1 (authenticated but not associated). Another channel change comes at this time, then the driver will issue disassociate command to the firmware which will cause the fatal error. It seems that the association/disassociation procedure should not be interrupted. The patch attached adds test on STATUS_ASSOCIATING | STATUS_DISASSOCIATING in ipw_send_cmd(), when ensures that commands will not be sent to firmware when we are in these two status. Signed-off-by: Hong Liu Signed-off-by: Zhu Yi --- drivers/net/wireless/ipw2200.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 9ced5b778a7..4cdb4748b76 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -1884,6 +1884,18 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) return -EAGAIN; } + if (priv->status & STATUS_ASSOCIATING) { + IPW_DEBUG_HC("abandon a command while associating\n"); + spin_unlock_irqrestore(&priv->lock, flags); + return -1; + } + + if (priv->status & STATUS_DISASSOCIATING) { + IPW_DEBUG_HC("abandon a command while disassociating\n"); + spin_unlock_irqrestore(&priv->lock, flags); + return -1; + } + priv->status |= STATUS_HCMD_ACTIVE; if (priv->cmdlog) { @@ -3671,7 +3683,13 @@ static void ipw_send_disassociate(struct ipw_priv *priv, int quiet) { int err; - if (!(priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED))) { + if (priv->status & STATUS_ASSOCIATING) { + IPW_DEBUG_ASSOC("Disassociating while associating.\n"); + queue_work(priv->workqueue, &priv->disassociate); + return; + } + + if (!(priv->status & STATUS_ASSOCIATED)) { IPW_DEBUG_ASSOC("Disassociating while not associated.\n"); return; } @@ -3681,9 +3699,6 @@ static void ipw_send_disassociate(struct ipw_priv *priv, int quiet) MAC_ARG(priv->assoc_request.bssid), priv->assoc_request.channel); - priv->status &= ~(STATUS_ASSOCIATING | STATUS_ASSOCIATED); - priv->status |= STATUS_DISASSOCIATING; - if (quiet) priv->assoc_request.assoc_type = HC_DISASSOC_QUIET; else @@ -3695,6 +3710,9 @@ static void ipw_send_disassociate(struct ipw_priv *priv, int quiet) return; } + priv->status &= ~(STATUS_ASSOCIATING | STATUS_ASSOCIATED); + priv->status |= STATUS_DISASSOCIATING; + } static int ipw_disassociate(void *data) @@ -7625,8 +7643,6 @@ static int ipw_associate_network(struct ipw_priv *priv, */ priv->channel = network->channel; memcpy(priv->bssid, network->bssid, ETH_ALEN); - priv->status |= STATUS_ASSOCIATING; - priv->status &= ~STATUS_SECURITY_UPDATED; priv->assoc_network = network; @@ -7640,6 +7656,9 @@ static int ipw_associate_network(struct ipw_priv *priv, return err; } + priv->status |= STATUS_ASSOCIATING; + priv->status &= ~STATUS_SECURITY_UPDATED; + IPW_DEBUG(IPW_DL_STATE, "associating: '%s' " MAC_FMT " \n", escape_essid(priv->essid, priv->essid_len), MAC_ARG(priv->bssid)); -- cgit v1.2.3 From 55135791819270a412dfb99f66301f02c72edadf Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 25 Aug 2005 17:43:14 +0800 Subject: [Bug 760] Fix setting WEP key in monitor mode causes IV lost. Signed-off-by: Zhu Yi --- drivers/net/wireless/ipw2200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 4cdb4748b76..bda292f7f82 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -7907,7 +7907,7 @@ static void ipw_handle_data_packet(struct ipw_priv *priv, IPW_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len); /* HW decrypt will not clear the WEP bit, MIC, PN, etc. */ - if (!priv->ieee->host_decrypt) + if (!priv->ieee->host_decrypt && priv->ieee->iw_mode != IW_MODE_MONITOR) ipw_rebuild_decrypted_skb(priv, rxb->skb); if (!ieee80211_rx(priv->ieee, rxb->skb, stats)) -- cgit v1.2.3 From 054b08d48464bfa8e5be69829b59bd599c5dcd72 Mon Sep 17 00:00:00 2001 From: Hong Liu Date: Thu, 25 Aug 2005 17:45:49 +0800 Subject: Don't set hardware WEP if we are actually using TKIP/AES. Signed-off-by: Hong Liu --- drivers/net/wireless/ipw2100.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index eaf47078ee5..83ba08c0c33 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -5443,8 +5443,11 @@ static void shim__set_security(struct net_device *dev, else memcpy(priv->ieee->sec.keys[i], sec->keys[i], sec->key_sizes[i]); - priv->ieee->sec.flags |= (1 << i); - priv->status |= STATUS_SECURITY_UPDATED; + if (sec->level == SEC_LEVEL_1) { + priv->ieee->sec.flags |= (1 << i); + priv->status |= STATUS_SECURITY_UPDATED; + } else + priv->ieee->sec.flags &= ~(1 << i); } } -- cgit v1.2.3 From a4f6bbb305123c2c42322a10a770be64089a17ca Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Fri, 26 Aug 2005 00:33:34 -0500 Subject: Make all the places the firmware fails to load showerrors (in decimal, so you can cross-reference errno.h easily). Signed-off-by: Peter Jones Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index bda292f7f82..79697e8e8d9 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -3304,7 +3304,7 @@ static int ipw_load(struct ipw_priv *priv) rc = ipw_load_firmware(priv, bootfw->data + sizeof(struct fw_header), bootfw->size - sizeof(struct fw_header)); if (rc < 0) { - IPW_ERROR("Unable to load boot firmware\n"); + IPW_ERROR("Unable to load boot firmware: %d\n", rc); goto error; } @@ -3327,7 +3327,7 @@ static int ipw_load(struct ipw_priv *priv) rc = ipw_load_ucode(priv, ucode->data + sizeof(struct fw_header), ucode->size - sizeof(struct fw_header)); if (rc < 0) { - IPW_ERROR("Unable to load ucode\n"); + IPW_ERROR("Unable to load ucode: %d\n", rc); goto error; } @@ -3339,7 +3339,7 @@ static int ipw_load(struct ipw_priv *priv) sizeof(struct fw_header), firmware->size - sizeof(struct fw_header)); if (rc < 0) { - IPW_ERROR("Unable to load firmware\n"); + IPW_ERROR("Unable to load firmware: %d\n", rc); goto error; } @@ -10958,7 +10958,7 @@ static int ipw_up(struct ipw_priv *priv) * Also start the clocks. */ rc = ipw_load(priv); if (rc) { - IPW_ERROR("Unable to load firmware: 0x%08X\n", rc); + IPW_ERROR("Unable to load firmware: %d\n", rc); return rc; } -- cgit v1.2.3 From 24a47dbd89a2738bc149de4685ae5a2a97193ae1 Mon Sep 17 00:00:00 2001 From: Mike Kershaw Date: Fri, 26 Aug 2005 00:41:54 -0500 Subject: Adds radiotap support to ipw2200 in monitor mode.. Signed-off-by: Mike Kershaw Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 185 +++++++++++++++++++++++++++++++++++++++++ drivers/net/wireless/ipw2200.h | 1 + 2 files changed, 186 insertions(+) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 79697e8e8d9..86a4c2358f9 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -7918,6 +7918,173 @@ static void ipw_handle_data_packet(struct ipw_priv *priv, } } +#ifdef CONFIG_IEEE80211_RADIOTAP +static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, + struct ipw_rx_mem_buffer *rxb, + struct ieee80211_rx_stats *stats) +{ + struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data; + struct ipw_rx_frame *frame = &pkt->u.frame; + + /* initial pull of some data */ + u16 received_channel = frame->received_channel; + u8 antennaAndPhy = frame->antennaAndPhy; + s8 antsignal = frame->rssi_dbm - IPW_RSSI_TO_DBM; /* call it signed anyhow */ + u16 pktrate = frame->rate; + + /* Magic struct that slots into the radiotap header -- no reason + * to build this manually element by element, we can write it much + * more efficiently than we can parse it. ORDER MATTERS HERE */ + struct ipw_rt_hdr { + struct ieee80211_radiotap_header rt_hdr; + u8 rt_flags; /* radiotap packet flags */ + u8 rt_rate; /* rate in 500kb/s */ + u16 rt_channel; /* channel in mhz */ + u16 rt_chbitmask; /* channel bitfield */ + s8 rt_dbmsignal; /* signal in dbM, kluged to signed */ + u8 rt_antenna; /* antenna number */ + } *ipw_rt; + + short len = le16_to_cpu(pkt->u.frame.length); + + /* We received data from the HW, so stop the watchdog */ + priv->net_dev->trans_start = jiffies; + + /* We only process data packets if the + * interface is open */ + if (unlikely((le16_to_cpu(pkt->u.frame.length) + IPW_RX_FRAME_SIZE) > + skb_tailroom(rxb->skb))) { + priv->ieee->stats.rx_errors++; + priv->wstats.discard.misc++; + IPW_DEBUG_DROP("Corruption detected! Oh no!\n"); + return; + } else if (unlikely(!netif_running(priv->net_dev))) { + priv->ieee->stats.rx_dropped++; + priv->wstats.discard.misc++; + IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); + return; + } + + /* Libpcap 0.9.3+ can handle variable length radiotap, so we'll use + * that now */ + if (len > IPW_RX_BUF_SIZE - sizeof(struct ipw_rt_hdr)) { + /* FIXME: Should alloc bigger skb instead */ + priv->ieee->stats.rx_dropped++; + priv->wstats.discard.misc++; + IPW_DEBUG_DROP("Dropping too large packet in monitor\n"); + return; + } + + /* copy the frame itself */ + memmove(rxb->skb->data + sizeof(struct ipw_rt_hdr), + rxb->skb->data + IPW_RX_FRAME_SIZE, len); + + /* Zero the radiotap static buffer ... We only need to zero the bytes NOT + * part of our real header, saves a little time. + * + * No longer necessary since we fill in all our data. Purge before merging + * patch officially. + * memset(rxb->skb->data + sizeof(struct ipw_rt_hdr), 0, + * IEEE80211_RADIOTAP_HDRLEN - sizeof(struct ipw_rt_hdr)); + */ + + ipw_rt = (struct ipw_rt_hdr *)rxb->skb->data; + + ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; + ipw_rt->rt_hdr.it_pad = 0; /* always good to zero */ + ipw_rt->rt_hdr.it_len = sizeof(struct ipw_rt_hdr); /* total header+data */ + + /* Big bitfield of all the fields we provide in radiotap */ + ipw_rt->rt_hdr.it_present = + ((1 << IEEE80211_RADIOTAP_FLAGS) | + (1 << IEEE80211_RADIOTAP_RATE) | + (1 << IEEE80211_RADIOTAP_CHANNEL) | + (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | + (1 << IEEE80211_RADIOTAP_ANTENNA)); + + /* Zero the flags, we'll add to them as we go */ + ipw_rt->rt_flags = 0; + + /* Convert signal to DBM */ + ipw_rt->rt_dbmsignal = antsignal; + + /* Convert the channel data and set the flags */ + ipw_rt->rt_channel = cpu_to_le16(ieee80211chan2mhz(received_channel)); + if (received_channel > 14) { /* 802.11a */ + ipw_rt->rt_chbitmask = + cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ)); + } else if (antennaAndPhy & 32) { /* 802.11b */ + ipw_rt->rt_chbitmask = + cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ)); + } else { /* 802.11g */ + ipw_rt->rt_chbitmask = + (IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ); + } + + /* set the rate in multiples of 500k/s */ + switch (pktrate) { + case IPW_TX_RATE_1MB: + ipw_rt->rt_rate = 2; + break; + case IPW_TX_RATE_2MB: + ipw_rt->rt_rate = 4; + break; + case IPW_TX_RATE_5MB: + ipw_rt->rt_rate = 10; + break; + case IPW_TX_RATE_6MB: + ipw_rt->rt_rate = 12; + break; + case IPW_TX_RATE_9MB: + ipw_rt->rt_rate = 18; + break; + case IPW_TX_RATE_11MB: + ipw_rt->rt_rate = 22; + break; + case IPW_TX_RATE_12MB: + ipw_rt->rt_rate = 24; + break; + case IPW_TX_RATE_18MB: + ipw_rt->rt_rate = 36; + break; + case IPW_TX_RATE_24MB: + ipw_rt->rt_rate = 48; + break; + case IPW_TX_RATE_36MB: + ipw_rt->rt_rate = 72; + break; + case IPW_TX_RATE_48MB: + ipw_rt->rt_rate = 96; + break; + case IPW_TX_RATE_54MB: + ipw_rt->rt_rate = 108; + break; + default: + ipw_rt->rt_rate = 0; + break; + } + + /* antenna number */ + ipw_rt->rt_antenna = (antennaAndPhy & 3); /* Is this right? */ + + /* set the preamble flag if we have it */ + if ((antennaAndPhy & 64)) + ipw_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; + + /* Set the size of the skb to the size of the frame */ + skb_put(rxb->skb, len + sizeof(struct ipw_rt_hdr)); + + IPW_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len); + + if (!ieee80211_rx(priv->ieee, rxb->skb, stats)) + priv->ieee->stats.rx_errors++; + else { /* ieee80211_rx succeeded, so it now owns the SKB */ + rxb->skb = NULL; + /* no LED during capture */ + } +} +#endif + static inline int is_network_packet(struct ipw_priv *priv, struct ieee80211_hdr_4addr *header) { @@ -8147,8 +8314,14 @@ static void ipw_rx(struct ipw_priv *priv) #ifdef CONFIG_IPW2200_MONITOR if (priv->ieee->iw_mode == IW_MODE_MONITOR) { +#ifdef CONFIG_IEEE80211_RADIOTAP + ipw_handle_data_packet_monitor(priv, + rxb, + &stats); +#else ipw_handle_data_packet(priv, rxb, &stats); +#endif break; } #endif @@ -8315,7 +8488,11 @@ static int ipw_sw_reset(struct ipw_priv *priv, int init) #ifdef CONFIG_IPW2200_MONITOR case 2: priv->ieee->iw_mode = IW_MODE_MONITOR; +#ifdef CONFIG_IEEE80211_RADIOTAP + priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; +#else priv->net_dev->type = ARPHRD_IEEE80211; +#endif break; #endif default: @@ -8565,7 +8742,11 @@ static int ipw_wx_set_mode(struct net_device *dev, priv->net_dev->type = ARPHRD_ETHER; if (wrqu->mode == IW_MODE_MONITOR) +#ifdef CONFIG_IEEE80211_RADIOTAP + priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; +#else priv->net_dev->type = ARPHRD_IEEE80211; +#endif #endif /* CONFIG_IPW2200_MONITOR */ /* Free the existing firmware and reset the fw_loaded @@ -9598,7 +9779,11 @@ static int ipw_wx_set_monitor(struct net_device *dev, IPW_DEBUG_WX("SET MONITOR: %d %d\n", enable, parms[1]); if (enable) { if (priv->ieee->iw_mode != IW_MODE_MONITOR) { +#ifdef CONFIG_IEEE80211_RADIOTAP + priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; +#else priv->net_dev->type = ARPHRD_IEEE80211; +#endif queue_work(priv->workqueue, &priv->adapter_restart); } diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index f2056b62254..28f1216f8ea 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -50,6 +50,7 @@ #include #include +#include #define DRV_NAME "ipw2200" -- cgit v1.2.3 From 90700fd982022f0519e7bd7595adb8084f36d1c6 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Fri, 26 Aug 2005 16:51:06 -0500 Subject: Fixed is_network_packet() to include checking for broadcast packets. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 86a4c2358f9..d417ed7af7c 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -8096,21 +8096,23 @@ static inline int is_network_packet(struct ipw_priv *priv, if (!memcmp(header->addr2, priv->net_dev->dev_addr, ETH_ALEN)) return 0; - /* multicast packets to our IBSS go through */ - if (is_multicast_ether_addr(header->addr1)) + /* {broad,multi}cast packets to our BSSID go through */ + if (is_multicast_ether_addr(header->addr1) || + is_broadcast_ether_addr(header->addr1)) return !memcmp(header->addr3, priv->bssid, ETH_ALEN); /* packets to our adapter go through */ return !memcmp(header->addr1, priv->net_dev->dev_addr, ETH_ALEN); - case IW_MODE_INFRA: /* Header: Dest. | AP{BSSID} | Source */ + case IW_MODE_INFRA: /* Header: Dest. | BSSID | Source */ /* packets from our adapter are dropped (echo) */ if (!memcmp(header->addr3, priv->net_dev->dev_addr, ETH_ALEN)) return 0; - /* {broad,multi}cast packets to our IBSS go through */ - if (is_multicast_ether_addr(header->addr1)) + /* {broad,multi}cast packets to our BSS go through */ + if (is_multicast_ether_addr(header->addr1) || + is_broadcast_ether_addr(header->addr1)) return !memcmp(header->addr2, priv->bssid, ETH_ALEN); /* packets to our adapter go through */ -- cgit v1.2.3 From 567deaf6d4a3372cd16b8719741ca3a6157c9615 Mon Sep 17 00:00:00 2001 From: Hong Liu Date: Wed, 31 Aug 2005 18:07:22 +0800 Subject: Mixed PTK/GTK CCMP/TKIP support. Signed-off-by: Hong Liu --- drivers/net/wireless/ipw2200.c | 50 +++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index d417ed7af7c..c9b306a8116 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -5771,7 +5771,8 @@ static void ipw_set_hwcrypto_keys(struct ipw_priv *priv) DCT_FLAG_EXT_SECURITY_CCM, priv->ieee->sec.active_key); - ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_CCM); + if (!priv->ieee->host_mc_decrypt) + ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_CCM); break; case SEC_LEVEL_2: if (priv->ieee->sec.flags & SEC_ACTIVE_KEY) @@ -5786,9 +5787,6 @@ static void ipw_set_hwcrypto_keys(struct ipw_priv *priv) default: break; } - - ipw_set_hw_decrypt_unicast(priv, priv->ieee->sec.level); - ipw_set_hw_decrypt_multicast(priv, priv->ieee->sec.level); } static void ipw_adhoc_check(void *data) @@ -6473,6 +6471,7 @@ static int ipw_wpa_set_encryption(struct net_device *dev, struct ipw_param *param, int param_len) { int ret = 0; + int group_key = 0; struct ipw_priv *priv = ieee80211_priv(dev); struct ieee80211_device *ieee = priv->ieee; struct ieee80211_crypto_ops *ops; @@ -6502,6 +6501,9 @@ static int ipw_wpa_set_encryption(struct net_device *dev, return -EINVAL; } + if (param->u.crypt.idx != 0) + group_key = 1; + sec.flags |= SEC_ENABLED | SEC_ENCRYPT; if (strcmp(param->u.crypt.alg, "none") == 0) { if (crypt) { @@ -6517,11 +6519,19 @@ static int ipw_wpa_set_encryption(struct net_device *dev, sec.encrypt = 1; /* IPW HW cannot build TKIP MIC, host decryption still needed. */ - if (strcmp(param->u.crypt.alg, "TKIP") == 0) - ieee->host_encrypt_msdu = 1; + if (strcmp(param->u.crypt.alg, "TKIP") == 0) { + if (group_key) + ieee->host_mc_decrypt = 1; + else + ieee->host_encrypt_msdu = 1; + } - if (!(ieee->host_encrypt || ieee->host_encrypt_msdu || - ieee->host_decrypt)) + /*if (!(ieee->host_encrypt || ieee->host_encrypt_msdu || + ieee->host_decrypt)) + goto skip_host_crypt; */ + if (group_key ? !ieee->host_mc_decrypt : + !(ieee->host_encrypt || ieee->host_decrypt || + ieee->host_encrypt_msdu)) goto skip_host_crypt; ops = ieee80211_get_crypto_ops(param->u.crypt.alg); @@ -6604,6 +6614,9 @@ static int ipw_wpa_set_encryption(struct net_device *dev, sec.flags |= SEC_LEVEL; sec.level = SEC_LEVEL_3; } + /* Don't set sec level for group keys. */ + if (group_key) + sec.flags &= ~SEC_LEVEL; } done: if (ieee->set_security) @@ -6953,15 +6966,21 @@ static int ipw_wx_set_encodeext(struct net_device *dev, struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; if (hwcrypto) { - /* IPW HW can't build TKIP MIC, host decryption still needed */ if (ext->alg == IW_ENCODE_ALG_TKIP) { - priv->ieee->host_encrypt = 0; - priv->ieee->host_encrypt_msdu = 1; - priv->ieee->host_decrypt = 1; + /* IPW HW can't build TKIP MIC, + host decryption still needed */ + if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) + priv->ieee->host_mc_decrypt = 1; + else { + priv->ieee->host_encrypt = 0; + priv->ieee->host_encrypt_msdu = 1; + priv->ieee->host_decrypt = 1; + } } else { priv->ieee->host_encrypt = 0; priv->ieee->host_encrypt_msdu = 0; priv->ieee->host_decrypt = 0; + priv->ieee->host_mc_decrypt = 0; } } @@ -7878,6 +7897,7 @@ static void ipw_handle_data_packet(struct ipw_priv *priv, struct ipw_rx_mem_buffer *rxb, struct ieee80211_rx_stats *stats) { + struct ieee80211_hdr_4addr *hdr; struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data; /* We received data from the HW, so stop the watchdog */ @@ -7907,7 +7927,10 @@ static void ipw_handle_data_packet(struct ipw_priv *priv, IPW_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len); /* HW decrypt will not clear the WEP bit, MIC, PN, etc. */ - if (!priv->ieee->host_decrypt && priv->ieee->iw_mode != IW_MODE_MONITOR) + hdr = (struct ieee80211_hdr_4addr *)rxb->skb->data; + if (priv->ieee->iw_mode != IW_MODE_MONITOR && + (is_multicast_ether_addr(hdr->addr1) ? + !priv->ieee->host_mc_decrypt : !priv->ieee->host_decrypt)) ipw_rebuild_decrypted_skb(priv, rxb->skb); if (!ieee80211_rx(priv->ieee, rxb->skb, stats)) @@ -8508,6 +8531,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int init) priv->ieee->host_encrypt = 0; priv->ieee->host_encrypt_msdu = 0; priv->ieee->host_decrypt = 0; + priv->ieee->host_mc_decrypt = 0; } IPW_DEBUG_INFO("Hardware crypto [%s]\n", hwcrypto ? "on" : "off"); -- cgit v1.2.3 From cdd1fa1e10a2231b5e24bde82550ac499aa5dcc4 Mon Sep 17 00:00:00 2001 From: Hong Liu Date: Wed, 31 Aug 2005 18:14:27 +0800 Subject: Card with WEP enabled and using shared-key auth will have firmware error when it tries to auth to a WPA ap. The patch filters out WPA networks if the card is not wpa enabled when selecting network to associate to. Signed-off-by: Hong Liu --- drivers/net/wireless/ipw2200.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index c9b306a8116..e36a1fd9eef 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -5510,6 +5510,15 @@ static int ipw_best_network(struct ipw_priv *priv, return 0; } + if (!priv->ieee->wpa_enabled && (network->wpa_ie_len > 0 || + network->rsn_ie_len > 0)) { + IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " + "because of WPA capability mismatch.\n", + escape_essid(network->ssid, network->ssid_len), + MAC_ARG(network->bssid)); + return 0; + } + if ((priv->config & CFG_STATIC_BSSID) && memcmp(network->bssid, priv->bssid, ETH_ALEN)) { IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " @@ -6228,6 +6237,7 @@ static int ipw_wpa_enable(struct ipw_priv *priv, int value) { /* This is called when wpa_supplicant loads and closes the driver * interface. */ + priv->ieee->wpa_enabled = value; return 0; } -- cgit v1.2.3 From fb7ccc9e6d1a2872ea8a07154f1689d19a7576c5 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Wed, 7 Sep 2005 18:19:08 -0500 Subject: Fixed problem with get_cmd_string not existing if CONFIG_IPW_DEBUG disabled. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index e36a1fd9eef..43dab7a5cc9 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -1809,7 +1809,6 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } -#ifdef CONFIG_IPW_DEBUG #define IPW_CMD(x) case IPW_CMD_ ## x : return #x static char *get_cmd_string(u8 cmd) { @@ -1868,7 +1867,6 @@ static char *get_cmd_string(u8 cmd) return "UNKNOWN"; } } -#endif #define HOST_COMPLETE_TIMEOUT HZ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) -- cgit v1.2.3 From 392d0f6d0752e6a3e25c3e3da95d78c53b0fd7a1 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Wed, 7 Sep 2005 18:39:03 -0500 Subject: Removed PF_SYNCTHREAD legacy. The PF_SYNCTHREAD check was introduced to try and remain compatible with SWSUSP2. This check is no longer needed with newer versions. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2100.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 83ba08c0c33..23a74accd50 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -6433,11 +6433,8 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, INIT_LIST_HEAD(&priv->fw_pend_list); INIT_STAT(&priv->fw_pend_stat); -#ifdef PF_SYNCTHREAD - priv->workqueue = create_workqueue(DRV_NAME, 0); -#else priv->workqueue = create_workqueue(DRV_NAME); -#endif + INIT_WORK(&priv->reset_work, (void (*)(void *))ipw2100_reset_adapter, priv); INIT_WORK(&priv->security_work, -- cgit v1.2.3 From 29cb843e6457c45c4a257a0d2080da3fd7fb9d1e Mon Sep 17 00:00:00 2001 From: Hong Liu Date: Mon, 12 Sep 2005 10:43:33 -0500 Subject: Fixes problem with WEP not working (association succeeds, but no Tx/Rx) Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 43dab7a5cc9..217b6579e90 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -5789,6 +5789,8 @@ static void ipw_set_hwcrypto_keys(struct ipw_priv *priv) break; case SEC_LEVEL_1: ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_WEP); + ipw_set_hw_decrypt_unicast(priv, priv->ieee->sec.level); + ipw_set_hw_decrypt_multicast(priv, priv->ieee->sec.level); break; case SEC_LEVEL_0: default: -- cgit v1.2.3 From f4ff497d45c7071166277a39590cc59b50dc893c Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 12 Sep 2005 10:48:48 -0500 Subject: [Fix bug# 771] Too many (8) bytes recieved when using AES/hwcrypto Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 217b6579e90..549f582551e 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -7877,10 +7877,7 @@ static void ipw_rebuild_decrypted_skb(struct ipw_priv *priv, memmove(skb->data + IEEE80211_3ADDR_LEN, skb->data + IEEE80211_3ADDR_LEN + 8, skb->len - IEEE80211_3ADDR_LEN - 8); - if (fc & IEEE80211_FCTL_MOREFRAGS) - skb_trim(skb, skb->len - 16); /* 2*MIC */ - else - skb_trim(skb, skb->len - 8); /* MIC */ + skb_trim(skb, skb->len - 16); /* CCMP_HDR_LEN + CCMP_MIC_LEN */ break; case SEC_LEVEL_2: break; @@ -7889,10 +7886,7 @@ static void ipw_rebuild_decrypted_skb(struct ipw_priv *priv, memmove(skb->data + IEEE80211_3ADDR_LEN, skb->data + IEEE80211_3ADDR_LEN + 4, skb->len - IEEE80211_3ADDR_LEN - 4); - if (fc & IEEE80211_FCTL_MOREFRAGS) - skb_trim(skb, skb->len - 8); /* 2*ICV */ - else - skb_trim(skb, skb->len - 4); /* ICV */ + skb_trim(skb, skb->len - 8); /* IV + ICV */ break; case SEC_LEVEL_0: break; -- cgit v1.2.3 From e63247269de722c3e753991025fb7f15c6aba9aa Mon Sep 17 00:00:00 2001 From: Hong Liu Date: Wed, 14 Sep 2005 21:04:15 -0500 Subject: Fixes WEP firmware error condition. The problem is caused by the patch in bug455 -- Channel change flood generates fatal error. The patch set the DISASSOCIATING status bit after sending the command. The process was scheduled out when waiting for the command to be sent to the card. The disassociated notification clears the DISASSOCIATING bit in the tasklet before the process set the bit. Move the bit setting code before sending the command now. Signed-off-by: Hong Liu Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 549f582551e..a7630920ace 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -1882,18 +1882,6 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) return -EAGAIN; } - if (priv->status & STATUS_ASSOCIATING) { - IPW_DEBUG_HC("abandon a command while associating\n"); - spin_unlock_irqrestore(&priv->lock, flags); - return -1; - } - - if (priv->status & STATUS_DISASSOCIATING) { - IPW_DEBUG_HC("abandon a command while disassociating\n"); - spin_unlock_irqrestore(&priv->lock, flags); - return -1; - } - priv->status |= STATUS_HCMD_ACTIVE; if (priv->cmdlog) { @@ -3697,10 +3685,14 @@ static void ipw_send_disassociate(struct ipw_priv *priv, int quiet) MAC_ARG(priv->assoc_request.bssid), priv->assoc_request.channel); + priv->status &= ~(STATUS_ASSOCIATING | STATUS_ASSOCIATED); + priv->status |= STATUS_DISASSOCIATING; + if (quiet) priv->assoc_request.assoc_type = HC_DISASSOC_QUIET; else priv->assoc_request.assoc_type = HC_DISASSOCIATE; + err = ipw_send_associate(priv, &priv->assoc_request); if (err) { IPW_DEBUG_HC("Attempt to send [dis]associate command " @@ -3708,9 +3700,6 @@ static void ipw_send_disassociate(struct ipw_priv *priv, int quiet) return; } - priv->status &= ~(STATUS_ASSOCIATING | STATUS_ASSOCIATED); - priv->status |= STATUS_DISASSOCIATING; - } static int ipw_disassociate(void *data) @@ -7672,6 +7661,8 @@ static int ipw_associate_network(struct ipw_priv *priv, */ priv->channel = network->channel; memcpy(priv->bssid, network->bssid, ETH_ALEN); + priv->status |= STATUS_ASSOCIATING; + priv->status &= ~STATUS_SECURITY_UPDATED; priv->assoc_network = network; @@ -7685,9 +7676,6 @@ static int ipw_associate_network(struct ipw_priv *priv, return err; } - priv->status |= STATUS_ASSOCIATING; - priv->status &= ~STATUS_SECURITY_UPDATED; - IPW_DEBUG(IPW_DL_STATE, "associating: '%s' " MAC_FMT " \n", escape_essid(priv->essid, priv->essid_len), MAC_ARG(priv->bssid)); @@ -7791,6 +7779,13 @@ static int ipw_associate(void *data) return 0; } + if (priv->status & STATUS_DISASSOCIATING) { + IPW_DEBUG_ASSOC("Not attempting association (in " + "disassociating)\n "); + queue_work(priv->workqueue, &priv->associate); + return 0; + } + if (!ipw_is_init(priv) || (priv->status & STATUS_SCANNING)) { IPW_DEBUG_ASSOC("Not attempting association (scanning or not " "initialized)\n"); -- cgit v1.2.3 From 9ef539d0d6fca1cd0b1f9b884be8b92cb80159c9 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Thu, 15 Sep 2005 00:42:42 -0500 Subject: Updated driver version stamps for ipw2100 (1.1.3) and ipw2200 (1.0.7) Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2100.c | 2 +- drivers/net/wireless/ipw2200.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 23a74accd50..dba1049bcf9 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -167,7 +167,7 @@ that only one external action is invoked at a time. #include "ipw2100.h" -#define IPW2100_VERSION "1.1.1" +#define IPW2100_VERSION "1.1.3" #define DRV_NAME "ipw2100" #define DRV_VERSION IPW2100_VERSION diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index a7630920ace..0b1c6fe5426 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -32,7 +32,7 @@ #include "ipw2200.h" -#define IPW2200_VERSION "1.0.5" +#define IPW2200_VERSION "1.0.7" #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 2003-2005 Intel Corporation" #define DRV_VERSION IPW2200_VERSION -- cgit v1.2.3 From 87bb5e3814572b85cf5d4650fb1f88267411845f Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Thu, 15 Sep 2005 01:00:31 -0500 Subject: Pulled out a stray KERNEL_VERSION check around the suspend handler. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2100.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index dba1049bcf9..ed4f1a5e6b0 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -6709,11 +6709,7 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev) } #ifdef CONFIG_PM -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) -static int ipw2100_suspend(struct pci_dev *pci_dev, u32 state) -#else static int ipw2100_suspend(struct pci_dev *pci_dev, pm_message_t state) -#endif { struct ipw2100_priv *priv = pci_get_drvdata(pci_dev); struct net_device *dev = priv->net_dev; -- cgit v1.2.3 From 97a78ca968b84a5e9d8854622b4760cec5058f77 Mon Sep 17 00:00:00 2001 From: Benoit Boissinot Date: Thu, 15 Sep 2005 17:30:28 +0000 Subject: Fix 'Driver using old /proc/net/wireless support, please fix driver !' message. Wireless extensions moved the get_wireless_stats handler from being in net_device into wireless_handler. Signed-off-by: Benoit Boissinot Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 19 ++++++++++++------- drivers/net/wireless/ipw2200.h | 2 ++ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 0b1c6fe5426..b89ede14419 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -125,6 +125,7 @@ static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos *qos_param); #endif /* CONFIG_IPW_QOS */ +static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev); static void ipw_remove_current_network(struct ipw_priv *priv); static void ipw_rx(struct ipw_priv *priv); static int ipw_queue_tx_reclaim(struct ipw_priv *priv, @@ -8883,6 +8884,13 @@ static int ipw_wx_get_range(struct net_device *dev, range->num_frequency = i; up(&priv->sem); + + /* Event capability (kernel + driver) */ + range->event_capa[0] = (IW_EVENT_CAPA_K_0 | + IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) | + IW_EVENT_CAPA_MASK(SIOCGIWAP)); + range->event_capa[1] = IW_EVENT_CAPA_K_1; + IPW_DEBUG_WX("GET Range\n"); return 0; } @@ -9999,10 +10007,9 @@ static struct iw_handler_def ipw_wx_handler_def = { .num_private_args = ARRAY_SIZE(ipw_priv_args), .private = ipw_priv_handler, .private_args = ipw_priv_args, + .get_wireless_stats = ipw_get_wireless_stats, }; -static struct iw_public_data ipw_wx_data; - /* * Get wireless statistics. * Called by /proc/net/wireless @@ -11487,9 +11494,6 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) SET_MODULE_OWNER(net_dev); SET_NETDEV_DEV(net_dev, &pdev->dev); - ipw_wx_data.spy_data = &priv->ieee->spy_data; - ipw_wx_data.ieee80211 = priv->ieee; - down(&priv->sem); priv->ieee->hard_start_xmit = ipw_net_hard_start_xmit; @@ -11514,8 +11518,9 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) net_dev->get_stats = ipw_net_get_stats; net_dev->set_multicast_list = ipw_net_set_multicast_list; net_dev->set_mac_address = ipw_net_set_mac_address; - net_dev->get_wireless_stats = ipw_get_wireless_stats; - net_dev->wireless_data = &ipw_wx_data; + priv->wireless_data.spy_data = &priv->ieee->spy_data; + priv->wireless_data.ieee80211 = priv->ieee; + net_dev->wireless_data = &priv->wireless_data; net_dev->wireless_handlers = &ipw_wx_handler_def; net_dev->ethtool_ops = &ipw_ethtool_ops; net_dev->irq = pdev->irq; diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index 28f1216f8ea..3e7699430c6 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -1228,6 +1228,8 @@ struct ipw_priv { struct iw_statistics wstats; + struct iw_public_data wireless_data; + struct workqueue_struct *workqueue; struct work_struct adhoc_check; -- cgit v1.2.3 From 8935f39e86e3707770e091fb58d9060307edf959 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Wed, 5 Oct 2005 15:59:08 -0500 Subject: Removed legacy WIRELESS_EXT checks from ipw2200.c Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 508 +---------------------------------------- 1 file changed, 1 insertion(+), 507 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index b89ede14419..8e17308b553 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -6159,70 +6159,6 @@ static void ipw_bg_abort_scan(void *data) up(&priv->sem); } -#if WIRELESS_EXT < 18 -/* Support for wpa_supplicant before WE-18, deprecated. */ - -/* following definitions must match definitions in driver_ipw.c */ - -#define IPW_IOCTL_WPA_SUPPLICANT SIOCIWFIRSTPRIV+30 - -#define IPW_CMD_SET_WPA_PARAM 1 -#define IPW_CMD_SET_WPA_IE 2 -#define IPW_CMD_SET_ENCRYPTION 3 -#define IPW_CMD_MLME 4 - -#define IPW_PARAM_WPA_ENABLED 1 -#define IPW_PARAM_TKIP_COUNTERMEASURES 2 -#define IPW_PARAM_DROP_UNENCRYPTED 3 -#define IPW_PARAM_PRIVACY_INVOKED 4 -#define IPW_PARAM_AUTH_ALGS 5 -#define IPW_PARAM_IEEE_802_1X 6 - -#define IPW_MLME_STA_DEAUTH 1 -#define IPW_MLME_STA_DISASSOC 2 - -#define IPW_CRYPT_ERR_UNKNOWN_ALG 2 -#define IPW_CRYPT_ERR_UNKNOWN_ADDR 3 -#define IPW_CRYPT_ERR_CRYPT_INIT_FAILED 4 -#define IPW_CRYPT_ERR_KEY_SET_FAILED 5 -#define IPW_CRYPT_ERR_TX_KEY_SET_FAILED 6 -#define IPW_CRYPT_ERR_CARD_CONF_FAILED 7 - -#define IPW_CRYPT_ALG_NAME_LEN 16 - -struct ipw_param { - u32 cmd; - u8 sta_addr[ETH_ALEN]; - union { - struct { - u8 name; - u32 value; - } wpa_param; - struct { - u32 len; - u8 reserved[32]; - u8 data[0]; - } wpa_ie; - struct { - u32 command; - u32 reason_code; - } mlme; - struct { - u8 alg[IPW_CRYPT_ALG_NAME_LEN]; - u8 set_tx; - u32 err; - u8 idx; - u8 seq[8]; /* sequence counter (set: RX, get: TX) */ - u16 key_len; - u8 key[0]; - } crypt; - - } u; -}; - -/* end of driver_ipw.c code */ -#endif - static int ipw_wpa_enable(struct ipw_priv *priv, int value) { /* This is called when wpa_supplicant loads and closes the driver @@ -6231,11 +6167,6 @@ static int ipw_wpa_enable(struct ipw_priv *priv, int value) return 0; } -#if WIRELESS_EXT < 18 -#define IW_AUTH_ALG_OPEN_SYSTEM 0x1 -#define IW_AUTH_ALG_SHARED_KEY 0x2 -#endif - static int ipw_wpa_set_auth_algs(struct ipw_priv *priv, int value) { struct ieee80211_device *ieee = priv->ieee; @@ -6283,416 +6214,6 @@ static int ipw_set_rsn_capa(struct ipw_priv *priv, return ipw_send_cmd(priv, &cmd); } -#if WIRELESS_EXT < 18 -static int ipw_wpa_set_param(struct net_device *dev, u8 name, u32 value) -{ - struct ipw_priv *priv = ieee80211_priv(dev); - struct ieee80211_crypt_data *crypt; - unsigned long flags; - int ret = 0; - - switch (name) { - case IPW_PARAM_WPA_ENABLED: - ret = ipw_wpa_enable(priv, value); - break; - - case IPW_PARAM_TKIP_COUNTERMEASURES: - crypt = priv->ieee->crypt[priv->ieee->tx_keyidx]; - if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) { - IPW_WARNING("Can't set TKIP countermeasures: " - "crypt not set!\n"); - break; - } - - flags = crypt->ops->get_flags(crypt->priv); - - if (value) - flags |= IEEE80211_CRYPTO_TKIP_COUNTERMEASURES; - else - flags &= ~IEEE80211_CRYPTO_TKIP_COUNTERMEASURES; - - crypt->ops->set_flags(flags, crypt->priv); - - break; - - case IPW_PARAM_DROP_UNENCRYPTED:{ - /* HACK: - * - * wpa_supplicant calls set_wpa_enabled when the driver - * is loaded and unloaded, regardless of if WPA is being - * used. No other calls are made which can be used to - * determine if encryption will be used or not prior to - * association being expected. If encryption is not being - * used, drop_unencrypted is set to false, else true -- we - * can use this to determine if the CAP_PRIVACY_ON bit should - * be set. - */ - struct ieee80211_security sec = { - .flags = SEC_ENABLED, - .enabled = value, - }; - priv->ieee->drop_unencrypted = value; - /* We only change SEC_LEVEL for open mode. Others - * are set by ipw_wpa_set_encryption. - */ - if (!value) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_0; - } else { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_1; - } - if (priv->ieee->set_security) - priv->ieee->set_security(priv->ieee->dev, &sec); - break; - } - - case IPW_PARAM_PRIVACY_INVOKED: - priv->ieee->privacy_invoked = value; - break; - - case IPW_PARAM_AUTH_ALGS: - ret = ipw_wpa_set_auth_algs(priv, value); - break; - - case IPW_PARAM_IEEE_802_1X: - priv->ieee->ieee802_1x = value; - break; - - default: - IPW_ERROR("%s: Unknown WPA param: %d\n", dev->name, name); - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int ipw_wpa_mlme(struct net_device *dev, int command, int reason) -{ - struct ipw_priv *priv = ieee80211_priv(dev); - int ret = 0; - - switch (command) { - case IPW_MLME_STA_DEAUTH: - // silently ignore - break; - - case IPW_MLME_STA_DISASSOC: - ipw_disassociate(priv); - break; - - default: - IPW_ERROR("%s: Unknown MLME request: %d\n", dev->name, command); - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int ipw_wpa_ie_cipher2level(u8 cipher) -{ - switch (cipher) { - case 4: /* CCMP */ - return SEC_LEVEL_3; - case 2: /* TKIP */ - return SEC_LEVEL_2; - case 5: /* WEP104 */ - case 1: /* WEP40 */ - return SEC_LEVEL_1; - case 0: /* NONE */ - return SEC_LEVEL_0; - default: - return -1; - } -} - -static int ipw_wpa_set_wpa_ie(struct net_device *dev, - struct ipw_param *param, int plen) -{ - struct ipw_priv *priv = ieee80211_priv(dev); - struct ieee80211_device *ieee = priv->ieee; - u8 *buf; - u8 *ptk, *gtk; - int level; - - if (param->u.wpa_ie.len > MAX_WPA_IE_LEN || - (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL)) - return -EINVAL; - - if (param->u.wpa_ie.len) { - buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - memcpy(buf, param->u.wpa_ie.data, param->u.wpa_ie.len); - kfree(ieee->wpa_ie); - ieee->wpa_ie = buf; - ieee->wpa_ie_len = param->u.wpa_ie.len; - } else { - kfree(ieee->wpa_ie); - ieee->wpa_ie = NULL; - ieee->wpa_ie_len = 0; - goto done; - } - - if (priv->ieee->host_encrypt) - goto done; - - /* HACK: Parse wpa_ie here to get pairwise suite, otherwise - * we need to change driver_ipw.c from wpa_supplicant. This - * is OK since -Dipw is deprecated. The -Dwext driver has a - * clean way to handle this. */ - gtk = ptk = (u8 *) ieee->wpa_ie; - if (ieee->wpa_ie[0] == 0x30) { /* RSN IE */ - gtk += 4 + 3; - ptk += 4 + 4 + 2 + 3; - } else { /* WPA IE */ - gtk += 8 + 3; - ptk += 8 + 4 + 2 + 3; - } - - if (ptk - (u8 *) ieee->wpa_ie > ieee->wpa_ie_len) - return -EINVAL; - - level = ipw_wpa_ie_cipher2level(*gtk); - ipw_set_hw_decrypt_multicast(priv, level); - - level = ipw_wpa_ie_cipher2level(*ptk); - ipw_set_hw_decrypt_unicast(priv, level); - - done: - ipw_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len); - return 0; -} - -/* implementation borrowed from hostap driver */ - -static int ipw_wpa_set_encryption(struct net_device *dev, - struct ipw_param *param, int param_len) -{ - int ret = 0; - int group_key = 0; - struct ipw_priv *priv = ieee80211_priv(dev); - struct ieee80211_device *ieee = priv->ieee; - struct ieee80211_crypto_ops *ops; - struct ieee80211_crypt_data **crypt; - - struct ieee80211_security sec = { - .flags = 0, - }; - - param->u.crypt.err = 0; - param->u.crypt.alg[IPW_CRYPT_ALG_NAME_LEN - 1] = '\0'; - - if (param_len != - (int)((char *)param->u.crypt.key - (char *)param) + - param->u.crypt.key_len) { - IPW_DEBUG_INFO("Len mismatch %d, %d\n", param_len, - param->u.crypt.key_len); - return -EINVAL; - } - if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && - param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && - param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { - if (param->u.crypt.idx >= WEP_KEYS) - return -EINVAL; - crypt = &ieee->crypt[param->u.crypt.idx]; - } else { - return -EINVAL; - } - - if (param->u.crypt.idx != 0) - group_key = 1; - - sec.flags |= SEC_ENABLED | SEC_ENCRYPT; - if (strcmp(param->u.crypt.alg, "none") == 0) { - if (crypt) { - sec.enabled = 0; - sec.encrypt = 0; - sec.level = SEC_LEVEL_0; - sec.flags |= SEC_LEVEL; - ieee80211_crypt_delayed_deinit(ieee, crypt); - } - goto done; - } - sec.enabled = 1; - sec.encrypt = 1; - - /* IPW HW cannot build TKIP MIC, host decryption still needed. */ - if (strcmp(param->u.crypt.alg, "TKIP") == 0) { - if (group_key) - ieee->host_mc_decrypt = 1; - else - ieee->host_encrypt_msdu = 1; - } - - /*if (!(ieee->host_encrypt || ieee->host_encrypt_msdu || - ieee->host_decrypt)) - goto skip_host_crypt; */ - if (group_key ? !ieee->host_mc_decrypt : - !(ieee->host_encrypt || ieee->host_decrypt || - ieee->host_encrypt_msdu)) - goto skip_host_crypt; - - ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) { - request_module("ieee80211_crypt_wep"); - ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) { - request_module("ieee80211_crypt_tkip"); - ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) { - request_module("ieee80211_crypt_ccmp"); - ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - } - if (ops == NULL) { - IPW_DEBUG_INFO("%s: unknown crypto alg '%s'\n", - dev->name, param->u.crypt.alg); - param->u.crypt.err = IPW_CRYPT_ERR_UNKNOWN_ALG; - ret = -EINVAL; - goto done; - } - - if (*crypt == NULL || (*crypt)->ops != ops) { - struct ieee80211_crypt_data *new_crypt; - - ieee80211_crypt_delayed_deinit(ieee, crypt); - - new_crypt = (struct ieee80211_crypt_data *) - kmalloc(sizeof(*new_crypt), GFP_KERNEL); - if (new_crypt == NULL) { - ret = -ENOMEM; - goto done; - } - memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data)); - new_crypt->ops = ops; - if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) - new_crypt->priv = - new_crypt->ops->init(param->u.crypt.idx); - - if (new_crypt->priv == NULL) { - kfree(new_crypt); - param->u.crypt.err = IPW_CRYPT_ERR_CRYPT_INIT_FAILED; - ret = -EINVAL; - goto done; - } - - *crypt = new_crypt; - } - - if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key && - (*crypt)->ops->set_key(param->u.crypt.key, - param->u.crypt.key_len, param->u.crypt.seq, - (*crypt)->priv) < 0) { - IPW_DEBUG_INFO("%s: key setting failed\n", dev->name); - param->u.crypt.err = IPW_CRYPT_ERR_KEY_SET_FAILED; - ret = -EINVAL; - goto done; - } - - skip_host_crypt: - if (param->u.crypt.set_tx) { - ieee->tx_keyidx = param->u.crypt.idx; - sec.active_key = param->u.crypt.idx; - sec.flags |= SEC_ACTIVE_KEY; - } else - sec.flags &= ~SEC_ACTIVE_KEY; - - if (param->u.crypt.alg != NULL) { - memcpy(sec.keys[param->u.crypt.idx], - param->u.crypt.key, param->u.crypt.key_len); - sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len; - sec.flags |= (1 << param->u.crypt.idx); - - if (strcmp(param->u.crypt.alg, "WEP") == 0) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_1; - } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_2; - } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_3; - } - /* Don't set sec level for group keys. */ - if (group_key) - sec.flags &= ~SEC_LEVEL; - } - done: - if (ieee->set_security) - ieee->set_security(ieee->dev, &sec); - - /* Do not reset port if card is in Managed mode since resetting will - * generate new IEEE 802.11 authentication which may end up in looping - * with IEEE 802.1X. If your hardware requires a reset after WEP - * configuration (for example... Prism2), implement the reset_port in - * the callbacks structures used to initialize the 802.11 stack. */ - if (ieee->reset_on_keychange && - ieee->iw_mode != IW_MODE_INFRA && - ieee->reset_port && ieee->reset_port(dev)) { - IPW_DEBUG_INFO("%s: reset_port failed\n", dev->name); - param->u.crypt.err = IPW_CRYPT_ERR_CARD_CONF_FAILED; - return -EINVAL; - } - - return ret; -} - -static int ipw_wpa_supplicant(struct net_device *dev, struct iw_point *p) -{ - struct ipw_param *param; - struct ipw_priv *priv = ieee80211_priv(dev); - int ret = 0; - - IPW_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length); - - if (p->length < sizeof(struct ipw_param) || !p->pointer) - return -EINVAL; - - param = (struct ipw_param *)kmalloc(p->length, GFP_KERNEL); - if (param == NULL) - return -ENOMEM; - - if (copy_from_user(param, p->pointer, p->length)) { - kfree(param); - return -EFAULT; - } - - down(&priv->sem); - switch (param->cmd) { - - case IPW_CMD_SET_WPA_PARAM: - ret = ipw_wpa_set_param(dev, param->u.wpa_param.name, - param->u.wpa_param.value); - break; - - case IPW_CMD_SET_WPA_IE: - ret = ipw_wpa_set_wpa_ie(dev, param, p->length); - break; - - case IPW_CMD_SET_ENCRYPTION: - ret = ipw_wpa_set_encryption(dev, param, p->length); - break; - - case IPW_CMD_MLME: - ret = ipw_wpa_mlme(dev, param->u.mlme.command, - param->u.mlme.reason_code); - break; - - default: - IPW_ERROR("%s: Unknown WPA supplicant request: %d\n", - dev->name, param->cmd); - ret = -EOPNOTSUPP; - } - - up(&priv->sem); - if (ret == 0 && copy_to_user(p->pointer, param, p->length)) - ret = -EFAULT; - - kfree(param); - return ret; -} -#else /* * WE-18 support */ @@ -7021,7 +6542,6 @@ static int ipw_wx_set_mlme(struct net_device *dev, } return 0; } -#endif #ifdef CONFIG_IPW_QOS @@ -9391,7 +8911,6 @@ static int ipw_wx_get_retry(struct net_device *dev, return 0; } -#if WIRELESS_EXT > 17 static int ipw_request_direct_scan(struct ipw_priv *priv, char *essid, int essid_len) { @@ -9455,14 +8974,12 @@ static int ipw_request_direct_scan(struct ipw_priv *priv, char *essid, up(&priv->sem); return err; } -#endif /* WIRELESS_EXT > 17 */ static int ipw_wx_set_scan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); -#if WIRELESS_EXT > 17 struct iw_scan_req *req = NULL; if (wrqu->data.length && wrqu->data.length == sizeof(struct iw_scan_req)) { @@ -9473,7 +8990,7 @@ static int ipw_wx_set_scan(struct net_device *dev, return 0; } } -#endif + IPW_DEBUG_WX("Start scan\n"); queue_work(priv->workqueue, &priv->request_scan); @@ -9923,7 +9440,6 @@ static iw_handler ipw_wx_handlers[] = { IW_IOCTL(SIOCGIWSPY) = iw_handler_get_spy, IW_IOCTL(SIOCSIWTHRSPY) = iw_handler_set_thrspy, IW_IOCTL(SIOCGIWTHRSPY) = iw_handler_get_thrspy, -#if WIRELESS_EXT > 17 IW_IOCTL(SIOCSIWGENIE) = ipw_wx_set_genie, IW_IOCTL(SIOCGIWGENIE) = ipw_wx_get_genie, IW_IOCTL(SIOCSIWMLME) = ipw_wx_set_mlme, @@ -9931,7 +9447,6 @@ static iw_handler ipw_wx_handlers[] = { IW_IOCTL(SIOCGIWAUTH) = ipw_wx_get_auth, IW_IOCTL(SIOCSIWENCODEEXT) = ipw_wx_set_encodeext, IW_IOCTL(SIOCGIWENCODEEXT) = ipw_wx_get_encodeext, -#endif }; enum { @@ -11317,24 +10832,6 @@ static void ipw_bg_down(void *data) up(&priv->sem); } -#if WIRELESS_EXT < 18 -static int ipw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct iwreq *wrq = (struct iwreq *)rq; - int ret = -1; - switch (cmd) { - case IPW_IOCTL_WPA_SUPPLICANT: - ret = ipw_wpa_supplicant(dev, &wrq->u.data); - return ret; - - default: - return -EOPNOTSUPP; - } - - return -EOPNOTSUPP; -} -#endif - /* Called by register_netdev() */ static int ipw_net_init(struct net_device *dev) { @@ -11512,9 +11009,6 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) net_dev->open = ipw_net_open; net_dev->stop = ipw_net_stop; net_dev->init = ipw_net_init; -#if WIRELESS_EXT < 18 - net_dev->do_ioctl = ipw_ioctl; -#endif net_dev->get_stats = ipw_net_get_stats; net_dev->set_multicast_list = ipw_net_set_multicast_list; net_dev->set_mac_address = ipw_net_set_mac_address; -- cgit v1.2.3 From e758256104c3c2475f7746bc1b348c99cdb207f2 Mon Sep 17 00:00:00 2001 From: Ben Cahill Date: Thu, 6 Oct 2005 15:34:41 -0500 Subject: Fixes missed beacon logic in relation to on-network AP roaming. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 27 ++++++++++++++++++++------- drivers/net/wireless/ipw2200.h | 3 +++ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 8e17308b553..894192964c0 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -4082,6 +4082,11 @@ static void ipw_bg_gather_stats(void *data) up(&priv->sem); } +/* Missed beacon behavior: + * 1st missed -> roaming_threshold, just wait, don't do any scan/roam. + * roaming_threshold -> disassociate_threshold, scan and roam for better signal. + * Above disassociate threshold, give up and stop scanning. + * Roaming is disabled if disassociate_threshold <= roaming_threshold */ static inline void ipw_handle_missed_beacon(struct ipw_priv *priv, int missed_count) { @@ -4116,9 +4121,12 @@ static inline void ipw_handle_missed_beacon(struct ipw_priv *priv, return; } - if (missed_count > priv->roaming_threshold) { + if (missed_count > priv->roaming_threshold && + missed_count <= priv->disassociate_threshold) { /* If we are not already roaming, set the ROAM - * bit in the status and kick off a scan */ + * bit in the status and kick off a scan. + * This can happen several times before we reach + * disassociate_threshold. */ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE, "Missed beacon: %d - initiate " "roaming\n", missed_count); @@ -4480,11 +4488,16 @@ static inline void ipw_rx_notification(struct ipw_priv *priv, STATUS_DISASSOCIATING))) queue_work(priv->workqueue, &priv->associate); else if (priv->status & STATUS_ROAMING) { - /* If a scan completed and we are in roam mode, then - * the scan that completed was the one requested as a - * result of entering roam... so, schedule the - * roam work */ - queue_work(priv->workqueue, &priv->roam); + if (x->status == SCAN_COMPLETED_STATUS_COMPLETE) + /* If a scan completed and we are in roam mode, then + * the scan that completed was the one requested as a + * result of entering roam... so, schedule the + * roam work */ + queue_work(priv->workqueue, + &priv->roam); + else + /* Don't schedule if we aborted the scan */ + priv->status &= ~STATUS_ROAMING; } else if (priv->status & STATUS_SCAN_PENDING) queue_work(priv->workqueue, &priv->request_scan); diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index 3e7699430c6..617ec4dba17 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -590,6 +590,9 @@ struct notif_channel_result { u8 uReserved; } __attribute__ ((packed)); +#define SCAN_COMPLETED_STATUS_COMPLETE 1 +#define SCAN_COMPLETED_STATUS_ABORTED 2 + struct notif_scan_complete { u8 scan_type; u8 num_channels; -- cgit v1.2.3 From 991d1cc5963f4926478f3139ec0b0dd26a2c888c Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Thu, 13 Oct 2005 09:26:48 +0000 Subject: Removed warning about TKIP not being configured if countermeasures are configured. Countermeasures default to being turned off when wpa_supplicant runs, regardless of if TKIP is being used. They are only turned on if a TKIP is running. The warning we were printing is therefore not needed. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2100.c | 10 ++-------- drivers/net/wireless/ipw2200.c | 10 ++-------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index ed4f1a5e6b0..76841cb8301 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -5866,11 +5866,8 @@ static int ipw2100_wpa_set_param(struct net_device *dev, u8 name, u32 value) case IPW2100_PARAM_TKIP_COUNTERMEASURES: crypt = priv->ieee->crypt[priv->ieee->tx_keyidx]; - if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) { - IPW_DEBUG_WARNING("Can't set TKIP countermeasures: " - "crypt not set!\n"); + if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) break; - } flags = crypt->ops->get_flags(crypt->priv); @@ -7935,11 +7932,8 @@ static int ipw2100_wx_set_auth(struct net_device *dev, case IW_AUTH_TKIP_COUNTERMEASURES: crypt = priv->ieee->crypt[priv->ieee->tx_keyidx]; - if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) { - IPW_DEBUG_WARNING("Can't set TKIP countermeasures: " - "crypt not set!\n"); + if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) break; - } flags = crypt->ops->get_flags(crypt->priv); diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 894192964c0..750e43e9310 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -6357,11 +6357,8 @@ static int ipw_wx_set_auth(struct net_device *dev, case IW_AUTH_TKIP_COUNTERMEASURES: crypt = priv->ieee->crypt[priv->ieee->tx_keyidx]; - if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) { - IPW_WARNING("Can't set TKIP countermeasures: " - "crypt not set!\n"); + if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) break; - } flags = crypt->ops->get_flags(crypt->priv); @@ -6453,11 +6450,8 @@ static int ipw_wx_get_auth(struct net_device *dev, case IW_AUTH_TKIP_COUNTERMEASURES: crypt = priv->ieee->crypt[priv->ieee->tx_keyidx]; - if (!crypt || !crypt->ops->get_flags) { - IPW_WARNING("Can't get TKIP countermeasures: " - "crypt not set!\n"); + if (!crypt || !crypt->ops->get_flags) break; - } param->value = (crypt->ops->get_flags(crypt->priv) & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) ? 1 : 0; -- cgit v1.2.3 From 035205760e4f28082fedb258a20c804746c84ffe Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Wed, 19 Oct 2005 16:12:31 -0500 Subject: Added channel support for ipw2200 cards identified as 'ZZR' Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 750e43e9310..081957ab119 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -10495,6 +10495,17 @@ static const struct ieee80211_geo ipw_geos[] = { {5210, 42}, {5230, 46}}, }, + { /* Rest of World */ + "ZZR", + .bg_channels = 14, + .bg = {{2412, 1}, {2417, 2}, {2422, 3}, + {2427, 4}, {2432, 5}, {2437, 6}, + {2442, 7}, {2447, 8}, {2452, 9}, + {2457, 10}, {2462, 11}, {2467, 12}, + {2472, 13}, {2484, 14, IEEE80211_CH_B_ONLY | + IEEE80211_CH_PASSIVE_ONLY}}, + }, + { /* High Band */ "ZZH", .bg_channels = 13, @@ -10711,8 +10722,13 @@ static int ipw_up(struct ipw_priv *priv) ipw_geos[j].name, 3)) break; } - if (j == ARRAY_SIZE(ipw_geos)) + if (j == ARRAY_SIZE(ipw_geos)) { + IPW_WARNING("SKU [%c%c%c] not recognized.\n", + priv->eeprom[EEPROM_COUNTRY_CODE + 0], + priv->eeprom[EEPROM_COUNTRY_CODE + 1], + priv->eeprom[EEPROM_COUNTRY_CODE + 2]); j = 0; + } if (ipw_set_geo(priv->ieee, &ipw_geos[j])) { IPW_WARNING("Could not set geography."); return 0; -- cgit v1.2.3 From 9d5b880bb8e977426d64a4caebe3fd3ae73a2862 Mon Sep 17 00:00:00 2001 From: Hong Liu Date: Wed, 19 Oct 2005 16:25:33 -0500 Subject: Fixed problem with not being able to send broadcast packets. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 081957ab119..c1ae6d4065e 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -7456,7 +7456,8 @@ static void ipw_handle_data_packet(struct ipw_priv *priv, /* HW decrypt will not clear the WEP bit, MIC, PN, etc. */ hdr = (struct ieee80211_hdr_4addr *)rxb->skb->data; if (priv->ieee->iw_mode != IW_MODE_MONITOR && - (is_multicast_ether_addr(hdr->addr1) ? + ((is_multicast_ether_addr(hdr->addr1) || + is_broadcast_ether_addr(hdr->addr1)) ? !priv->ieee->host_mc_decrypt : !priv->ieee->host_decrypt)) ipw_rebuild_decrypted_skb(priv, rxb->skb); @@ -9652,7 +9653,8 @@ static inline int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, switch (priv->ieee->iw_mode) { case IW_MODE_ADHOC: hdr_len = IEEE80211_3ADDR_LEN; - unicast = !is_multicast_ether_addr(hdr->addr1); + unicast = !(is_multicast_ether_addr(hdr->addr1) || + is_broadcast_ether_addr(hdr->addr1)); id = ipw_find_station(priv, hdr->addr1); if (id == IPW_INVALID_STATION) { id = ipw_add_station(priv, hdr->addr1); @@ -9667,7 +9669,8 @@ static inline int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, case IW_MODE_INFRA: default: - unicast = !is_multicast_ether_addr(hdr->addr3); + unicast = !(is_multicast_ether_addr(hdr->addr3) || + is_broadcast_ether_addr(hdr->addr3)); hdr_len = IEEE80211_3ADDR_LEN; id = 0; break; -- cgit v1.2.3 From 286568ab1e8f0e09a76cfa58e8ed48ddc44484b5 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Tue, 30 Aug 2005 10:34:25 -0500 Subject: Fixed parameter reordering in firmware log routine. Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index c1ae6d4065e..f49b0125375 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -526,7 +526,7 @@ static void ipw_dump_error_log(struct ipw_priv *priv, for (i = 0; i < error->log_len; i++) IPW_ERROR("%i\t0x%08x\t%i\n", error->log[i].time, - error->log[i].event, error->log[i].data); + error->log[i].data, error->log[i].event); } #endif -- cgit v1.2.3 From 81715376de909637b957f856e30880871fbd78fc Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Thu, 25 Aug 2005 01:37:28 -0500 Subject: Updated firmware version stamp to 2.4 from 2.3 so it will use the latest firmware. You can obtain the firmware at http://ipw2200.sf.net/firmware.php Signed-off-by: James Ketrenos --- drivers/net/wireless/ipw2200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index f49b0125375..56709d2921a 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -2834,7 +2834,7 @@ struct fw_chunk { }; #define IPW_FW_MAJOR_VERSION 2 -#define IPW_FW_MINOR_VERSION 3 +#define IPW_FW_MINOR_VERSION 4 #define IPW_FW_MINOR(x) ((x & 0xff) >> 8) #define IPW_FW_MAJOR(x) (x & 0xff) -- cgit v1.2.3 From cf1b479b6922c6736d9f00d90c2b78e977692c93 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Thu, 20 Oct 2005 16:35:24 -0500 Subject: Update version ipw2200 stamp to 1.0.8 --- drivers/net/wireless/ipw2200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 56709d2921a..136884cef90 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -32,7 +32,7 @@ #include "ipw2200.h" -#define IPW2200_VERSION "1.0.7" +#define IPW2200_VERSION "git-1.0.8" #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 2003-2005 Intel Corporation" #define DRV_VERSION IPW2200_VERSION -- cgit v1.2.3 From a82765b6eee3d1267ded3320ca67b39fe1844599 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 2 Nov 2005 22:34:20 +0000 Subject: [PATCH] powerpc: Fix ppc32 initrd OK, the Fedora ppc32 and ppc64 kernels should both be arch/powerpc by tomorrow. They're booting on G5, POWER5, and my powerbook. I'll test pmac SMP and Pegasos later -- but pmac smp is known broken in arch/ppc anyway, and I'll live with a potential Pegasos regression for now; it wasn't supported officially in FC4 either. I needed to fix ppc32 initrd -- we were never setting initrd_start. Signed-off-by: David Woodhouse Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/setup-common.c | 40 ++++++++++++++++++++++++++++++++++++++ arch/powerpc/kernel/setup_32.c | 1 + arch/powerpc/kernel/setup_64.c | 37 ----------------------------------- 3 files changed, 41 insertions(+), 37 deletions(-) diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index d43fa8c0e5a..e22856ecb5a 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -405,6 +405,46 @@ static int __init set_preferred_console(void) console_initcall(set_preferred_console); #endif /* CONFIG_PPC_MULTIPLATFORM */ +void __init check_for_initrd(void) +{ +#ifdef CONFIG_BLK_DEV_INITRD + unsigned long *prop; + + DBG(" -> check_for_initrd()\n"); + + if (of_chosen) { + prop = (unsigned long *)get_property(of_chosen, + "linux,initrd-start", NULL); + if (prop != NULL) { + initrd_start = (unsigned long)__va(*prop); + prop = (unsigned long *)get_property(of_chosen, + "linux,initrd-end", NULL); + if (prop != NULL) { + initrd_end = (unsigned long)__va(*prop); + initrd_below_start_ok = 1; + } else + initrd_start = 0; + } + } + + /* If we were passed an initrd, set the ROOT_DEV properly if the values + * look sensible. If not, clear initrd reference. + */ + if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE && + initrd_end > initrd_start) + ROOT_DEV = Root_RAM0; + else { + printk("Bogus initrd %08lx %08lx\n", initrd_start, initrd_end); + initrd_start = initrd_end = 0; + } + + if (initrd_start) + printk("Found initrd at 0x%lx:0x%lx\n", initrd_start, initrd_end); + + DBG(" <- check_for_initrd()\n"); +#endif /* CONFIG_BLK_DEV_INITRD */ +} + #ifdef CONFIG_SMP /** diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index b45eedbb4b3..3af2631e3fa 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -286,6 +286,7 @@ void __init setup_arch(char **cmdline_p) loops_per_jiffy = 500000000 / HZ; unflatten_device_tree(); + check_for_initrd(); finish_device_tree(); smp_setup_cpu_maps(); diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 785fd9d7b38..0471e843b6c 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -395,43 +395,6 @@ static void __init initialize_cache_info(void) DBG(" <- initialize_cache_info()\n"); } -static void __init check_for_initrd(void) -{ -#ifdef CONFIG_BLK_DEV_INITRD - u64 *prop; - - DBG(" -> check_for_initrd()\n"); - - if (of_chosen) { - prop = (u64 *)get_property(of_chosen, - "linux,initrd-start", NULL); - if (prop != NULL) { - initrd_start = (unsigned long)__va(*prop); - prop = (u64 *)get_property(of_chosen, - "linux,initrd-end", NULL); - if (prop != NULL) { - initrd_end = (unsigned long)__va(*prop); - initrd_below_start_ok = 1; - } else - initrd_start = 0; - } - } - - /* If we were passed an initrd, set the ROOT_DEV properly if the values - * look sensible. If not, clear initrd reference. - */ - if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE && - initrd_end > initrd_start) - ROOT_DEV = Root_RAM0; - else - initrd_start = initrd_end = 0; - - if (initrd_start) - printk("Found initrd at 0x%lx:0x%lx\n", initrd_start, initrd_end); - - DBG(" <- check_for_initrd()\n"); -#endif /* CONFIG_BLK_DEV_INITRD */ -} /* * Do some initial setup of the system. The parameters are those which -- cgit v1.2.3 From 4350147a816b9c5b40fa59e4fa23f17490630b79 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 7 Nov 2005 14:27:33 +1100 Subject: [PATCH] ppc64: SMU based macs cpufreq support CPU freq support using 970FX powertune facility for iMac G5 and SMU based single CPU desktop. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 8 + arch/powerpc/kernel/misc_64.S | 70 +++ arch/powerpc/platforms/powermac/Makefile | 3 +- arch/powerpc/platforms/powermac/cpufreq.c | 726 -------------------------- arch/powerpc/platforms/powermac/cpufreq_32.c | 727 +++++++++++++++++++++++++++ arch/powerpc/platforms/powermac/cpufreq_64.c | 323 ++++++++++++ arch/powerpc/platforms/powermac/setup.c | 13 - arch/ppc64/Kconfig | 10 + arch/ppc64/kernel/misc.S | 72 ++- drivers/macintosh/smu.c | 12 + include/asm-powerpc/reg.h | 9 +- include/asm-powerpc/smu.h | 60 ++- 12 files changed, 1290 insertions(+), 743 deletions(-) delete mode 100644 arch/powerpc/platforms/powermac/cpufreq.c create mode 100644 arch/powerpc/platforms/powermac/cpufreq_32.c create mode 100644 arch/powerpc/platforms/powermac/cpufreq_64.c diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 6ffae2d2b3f..3ac9195dab3 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -404,6 +404,14 @@ config CPU_FREQ_PMAC this currently includes some models of iBook & Titanium PowerBook. +config CPU_FREQ_PMAC64 + bool "Support for some Apple G5s" + depends on CPU_FREQ && PMAC_SMU && PPC64 + select CPU_FREQ_TABLE + help + This adds support for frequency switching on Apple iMac G5, + and some of the more recent desktop G5 machines as well. + config PPC601_SYNC_FIX bool "Workarounds for PPC601 bugs" depends on 6xx && (PPC_PREP || PPC_PMAC) diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index b3e95ff0dba..ae1433da09b 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -603,6 +603,76 @@ _GLOBAL(real_writeb) blr #endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */ +/* + * SCOM access functions for 970 (FX only for now) + * + * unsigned long scom970_read(unsigned int address); + * void scom970_write(unsigned int address, unsigned long value); + * + * The address passed in is the 24 bits register address. This code + * is 970 specific and will not check the status bits, so you should + * know what you are doing. + */ +_GLOBAL(scom970_read) + /* interrupts off */ + mfmsr r4 + ori r0,r4,MSR_EE + xori r0,r0,MSR_EE + mtmsrd r0,1 + + /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits + * (including parity). On current CPUs they must be 0'd, + * and finally or in RW bit + */ + rlwinm r3,r3,8,0,15 + ori r3,r3,0x8000 + + /* do the actual scom read */ + sync + mtspr SPRN_SCOMC,r3 + isync + mfspr r3,SPRN_SCOMD + isync + mfspr r0,SPRN_SCOMC + isync + + /* XXX: fixup result on some buggy 970's (ouch ! we lost a bit, bah + * that's the best we can do). Not implemented yet as we don't use + * the scom on any of the bogus CPUs yet, but may have to be done + * ultimately + */ + + /* restore interrupts */ + mtmsrd r4,1 + blr + + +_GLOBAL(scom970_write) + /* interrupts off */ + mfmsr r5 + ori r0,r5,MSR_EE + xori r0,r0,MSR_EE + mtmsrd r0,1 + + /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits + * (including parity). On current CPUs they must be 0'd. + */ + + rlwinm r3,r3,8,0,15 + + sync + mtspr SPRN_SCOMD,r4 /* write data */ + isync + mtspr SPRN_SCOMC,r3 /* write command */ + isync + mfspr 3,SPRN_SCOMC + isync + + /* restore interrupts */ + mtmsrd r5,1 + blr + + /* * Create a kernel thread * kernel_thread(fn, arg, flags) diff --git a/arch/powerpc/platforms/powermac/Makefile b/arch/powerpc/platforms/powermac/Makefile index 4369676f1d5..c9df44fcf57 100644 --- a/arch/powerpc/platforms/powermac/Makefile +++ b/arch/powerpc/platforms/powermac/Makefile @@ -1,7 +1,8 @@ obj-y += pic.o setup.o time.o feature.o pci.o \ sleep.o low_i2c.o cache.o obj-$(CONFIG_PMAC_BACKLIGHT) += backlight.o -obj-$(CONFIG_CPU_FREQ_PMAC) += cpufreq.o +obj-$(CONFIG_CPU_FREQ_PMAC) += cpufreq_32.o +obj-$(CONFIG_CPU_FREQ_PMAC64) += cpufreq_64.o obj-$(CONFIG_NVRAM) += nvram.o # ppc64 pmac doesn't define CONFIG_NVRAM but needs nvram stuff obj-$(CONFIG_PPC64) += nvram.o diff --git a/arch/powerpc/platforms/powermac/cpufreq.c b/arch/powerpc/platforms/powermac/cpufreq.c deleted file mode 100644 index c47f8b69725..00000000000 --- a/arch/powerpc/platforms/powermac/cpufreq.c +++ /dev/null @@ -1,726 +0,0 @@ -/* - * arch/ppc/platforms/pmac_cpufreq.c - * - * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt - * Copyright (C) 2004 John Steele Scott - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * TODO: Need a big cleanup here. Basically, we need to have different - * cpufreq_driver structures for the different type of HW instead of the - * current mess. We also need to better deal with the detection of the - * type of machine. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* WARNING !!! This will cause calibrate_delay() to be called, - * but this is an __init function ! So you MUST go edit - * init/main.c to make it non-init before enabling DEBUG_FREQ - */ -#undef DEBUG_FREQ - -/* - * There is a problem with the core cpufreq code on SMP kernels, - * it won't recalculate the Bogomips properly - */ -#ifdef CONFIG_SMP -#warning "WARNING, CPUFREQ not recommended on SMP kernels" -#endif - -extern void low_choose_7447a_dfs(int dfs); -extern void low_choose_750fx_pll(int pll); -extern void low_sleep_handler(void); - -/* - * Currently, PowerMac cpufreq supports only high & low frequencies - * that are set by the firmware - */ -static unsigned int low_freq; -static unsigned int hi_freq; -static unsigned int cur_freq; -static unsigned int sleep_freq; - -/* - * Different models uses different mecanisms to switch the frequency - */ -static int (*set_speed_proc)(int low_speed); -static unsigned int (*get_speed_proc)(void); - -/* - * Some definitions used by the various speedprocs - */ -static u32 voltage_gpio; -static u32 frequency_gpio; -static u32 slew_done_gpio; -static int no_schedule; -static int has_cpu_l2lve; -static int is_pmu_based; - -/* There are only two frequency states for each processor. Values - * are in kHz for the time being. - */ -#define CPUFREQ_HIGH 0 -#define CPUFREQ_LOW 1 - -static struct cpufreq_frequency_table pmac_cpu_freqs[] = { - {CPUFREQ_HIGH, 0}, - {CPUFREQ_LOW, 0}, - {0, CPUFREQ_TABLE_END}, -}; - -static struct freq_attr* pmac_cpu_freqs_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - -static inline void local_delay(unsigned long ms) -{ - if (no_schedule) - mdelay(ms); - else - msleep(ms); -} - -#ifdef DEBUG_FREQ -static inline void debug_calc_bogomips(void) -{ - /* This will cause a recalc of bogomips and display the - * result. We backup/restore the value to avoid affecting the - * core cpufreq framework's own calculation. - */ - extern void calibrate_delay(void); - - unsigned long save_lpj = loops_per_jiffy; - calibrate_delay(); - loops_per_jiffy = save_lpj; -} -#endif /* DEBUG_FREQ */ - -/* Switch CPU speed under 750FX CPU control - */ -static int cpu_750fx_cpu_speed(int low_speed) -{ - u32 hid2; - - if (low_speed == 0) { - /* ramping up, set voltage first */ - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); - /* Make sure we sleep for at least 1ms */ - local_delay(10); - - /* tweak L2 for high voltage */ - if (has_cpu_l2lve) { - hid2 = mfspr(SPRN_HID2); - hid2 &= ~0x2000; - mtspr(SPRN_HID2, hid2); - } - } -#ifdef CONFIG_6xx - low_choose_750fx_pll(low_speed); -#endif - if (low_speed == 1) { - /* tweak L2 for low voltage */ - if (has_cpu_l2lve) { - hid2 = mfspr(SPRN_HID2); - hid2 |= 0x2000; - mtspr(SPRN_HID2, hid2); - } - - /* ramping down, set voltage last */ - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); - local_delay(10); - } - - return 0; -} - -static unsigned int cpu_750fx_get_cpu_speed(void) -{ - if (mfspr(SPRN_HID1) & HID1_PS) - return low_freq; - else - return hi_freq; -} - -/* Switch CPU speed using DFS */ -static int dfs_set_cpu_speed(int low_speed) -{ - if (low_speed == 0) { - /* ramping up, set voltage first */ - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); - /* Make sure we sleep for at least 1ms */ - local_delay(1); - } - - /* set frequency */ -#ifdef CONFIG_6xx - low_choose_7447a_dfs(low_speed); -#endif - udelay(100); - - if (low_speed == 1) { - /* ramping down, set voltage last */ - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); - local_delay(1); - } - - return 0; -} - -static unsigned int dfs_get_cpu_speed(void) -{ - if (mfspr(SPRN_HID1) & HID1_DFS) - return low_freq; - else - return hi_freq; -} - - -/* Switch CPU speed using slewing GPIOs - */ -static int gpios_set_cpu_speed(int low_speed) -{ - int gpio, timeout = 0; - - /* If ramping up, set voltage first */ - if (low_speed == 0) { - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); - /* Delay is way too big but it's ok, we schedule */ - local_delay(10); - } - - /* Set frequency */ - gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0); - if (low_speed == ((gpio & 0x01) == 0)) - goto skip; - - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, frequency_gpio, - low_speed ? 0x04 : 0x05); - udelay(200); - do { - if (++timeout > 100) - break; - local_delay(1); - gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, slew_done_gpio, 0); - } while((gpio & 0x02) == 0); - skip: - /* If ramping down, set voltage last */ - if (low_speed == 1) { - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); - /* Delay is way too big but it's ok, we schedule */ - local_delay(10); - } - -#ifdef DEBUG_FREQ - debug_calc_bogomips(); -#endif - - return 0; -} - -/* Switch CPU speed under PMU control - */ -static int pmu_set_cpu_speed(int low_speed) -{ - struct adb_request req; - unsigned long save_l2cr; - unsigned long save_l3cr; - unsigned int pic_prio; - unsigned long flags; - - preempt_disable(); - -#ifdef DEBUG_FREQ - printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1)); -#endif - pmu_suspend(); - - /* Disable all interrupt sources on openpic */ - pic_prio = mpic_cpu_get_priority(); - mpic_cpu_set_priority(0xf); - - /* Make sure the decrementer won't interrupt us */ - asm volatile("mtdec %0" : : "r" (0x7fffffff)); - /* Make sure any pending DEC interrupt occuring while we did - * the above didn't re-enable the DEC */ - mb(); - asm volatile("mtdec %0" : : "r" (0x7fffffff)); - - /* We can now disable MSR_EE */ - local_irq_save(flags); - - /* Giveup the FPU & vec */ - enable_kernel_fp(); - -#ifdef CONFIG_ALTIVEC - if (cpu_has_feature(CPU_FTR_ALTIVEC)) - enable_kernel_altivec(); -#endif /* CONFIG_ALTIVEC */ - - /* Save & disable L2 and L3 caches */ - save_l3cr = _get_L3CR(); /* (returns -1 if not available) */ - save_l2cr = _get_L2CR(); /* (returns -1 if not available) */ - - /* Send the new speed command. My assumption is that this command - * will cause PLL_CFG[0..3] to be changed next time CPU goes to sleep - */ - pmu_request(&req, NULL, 6, PMU_CPU_SPEED, 'W', 'O', 'O', 'F', low_speed); - while (!req.complete) - pmu_poll(); - - /* Prepare the northbridge for the speed transition */ - pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,1); - - /* Call low level code to backup CPU state and recover from - * hardware reset - */ - low_sleep_handler(); - - /* Restore the northbridge */ - pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,0); - - /* Restore L2 cache */ - if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0) - _set_L2CR(save_l2cr); - /* Restore L3 cache */ - if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0) - _set_L3CR(save_l3cr); - - /* Restore userland MMU context */ - set_context(current->active_mm->context, current->active_mm->pgd); - -#ifdef DEBUG_FREQ - printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1)); -#endif - - /* Restore low level PMU operations */ - pmu_unlock(); - - /* Restore decrementer */ - wakeup_decrementer(); - - /* Restore interrupts */ - mpic_cpu_set_priority(pic_prio); - - /* Let interrupts flow again ... */ - local_irq_restore(flags); - -#ifdef DEBUG_FREQ - debug_calc_bogomips(); -#endif - - pmu_resume(); - - preempt_enable(); - - return 0; -} - -static int do_set_cpu_speed(int speed_mode, int notify) -{ - struct cpufreq_freqs freqs; - unsigned long l3cr; - static unsigned long prev_l3cr; - - freqs.old = cur_freq; - freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; - freqs.cpu = smp_processor_id(); - - if (freqs.old == freqs.new) - return 0; - - if (notify) - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - if (speed_mode == CPUFREQ_LOW && - cpu_has_feature(CPU_FTR_L3CR)) { - l3cr = _get_L3CR(); - if (l3cr & L3CR_L3E) { - prev_l3cr = l3cr; - _set_L3CR(0); - } - } - set_speed_proc(speed_mode == CPUFREQ_LOW); - if (speed_mode == CPUFREQ_HIGH && - cpu_has_feature(CPU_FTR_L3CR)) { - l3cr = _get_L3CR(); - if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr) - _set_L3CR(prev_l3cr); - } - if (notify) - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; - - return 0; -} - -static unsigned int pmac_cpufreq_get_speed(unsigned int cpu) -{ - return cur_freq; -} - -static int pmac_cpufreq_verify(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, pmac_cpu_freqs); -} - -static int pmac_cpufreq_target( struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - unsigned int newstate = 0; - - if (cpufreq_frequency_table_target(policy, pmac_cpu_freqs, - target_freq, relation, &newstate)) - return -EINVAL; - - return do_set_cpu_speed(newstate, 1); -} - -unsigned int pmac_get_one_cpufreq(int i) -{ - /* Supports only one CPU for now */ - return (i == 0) ? cur_freq : 0; -} - -static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy) -{ - if (policy->cpu != 0) - return -ENODEV; - - policy->governor = CPUFREQ_DEFAULT_GOVERNOR; - policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - policy->cur = cur_freq; - - cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu); - return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs); -} - -static u32 read_gpio(struct device_node *np) -{ - u32 *reg = (u32 *)get_property(np, "reg", NULL); - u32 offset; - - if (reg == NULL) - return 0; - /* That works for all keylargos but shall be fixed properly - * some day... The problem is that it seems we can't rely - * on the "reg" property of the GPIO nodes, they are either - * relative to the base of KeyLargo or to the base of the - * GPIO space, and the device-tree doesn't help. - */ - offset = *reg; - if (offset < KEYLARGO_GPIO_LEVELS0) - offset += KEYLARGO_GPIO_LEVELS0; - return offset; -} - -static int pmac_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg) -{ - /* Ok, this could be made a bit smarter, but let's be robust for now. We - * always force a speed change to high speed before sleep, to make sure - * we have appropriate voltage and/or bus speed for the wakeup process, - * and to make sure our loops_per_jiffies are "good enough", that is will - * not cause too short delays if we sleep in low speed and wake in high - * speed.. - */ - no_schedule = 1; - sleep_freq = cur_freq; - if (cur_freq == low_freq && !is_pmu_based) - do_set_cpu_speed(CPUFREQ_HIGH, 0); - return 0; -} - -static int pmac_cpufreq_resume(struct cpufreq_policy *policy) -{ - /* If we resume, first check if we have a get() function */ - if (get_speed_proc) - cur_freq = get_speed_proc(); - else - cur_freq = 0; - - /* We don't, hrm... we don't really know our speed here, best - * is that we force a switch to whatever it was, which is - * probably high speed due to our suspend() routine - */ - do_set_cpu_speed(sleep_freq == low_freq ? - CPUFREQ_LOW : CPUFREQ_HIGH, 0); - - no_schedule = 0; - return 0; -} - -static struct cpufreq_driver pmac_cpufreq_driver = { - .verify = pmac_cpufreq_verify, - .target = pmac_cpufreq_target, - .get = pmac_cpufreq_get_speed, - .init = pmac_cpufreq_cpu_init, - .suspend = pmac_cpufreq_suspend, - .resume = pmac_cpufreq_resume, - .flags = CPUFREQ_PM_NO_WARN, - .attr = pmac_cpu_freqs_attr, - .name = "powermac", - .owner = THIS_MODULE, -}; - - -static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode) -{ - struct device_node *volt_gpio_np = of_find_node_by_name(NULL, - "voltage-gpio"); - struct device_node *freq_gpio_np = of_find_node_by_name(NULL, - "frequency-gpio"); - struct device_node *slew_done_gpio_np = of_find_node_by_name(NULL, - "slewing-done"); - u32 *value; - - /* - * Check to see if it's GPIO driven or PMU only - * - * The way we extract the GPIO address is slightly hackish, but it - * works well enough for now. We need to abstract the whole GPIO - * stuff sooner or later anyway - */ - - if (volt_gpio_np) - voltage_gpio = read_gpio(volt_gpio_np); - if (freq_gpio_np) - frequency_gpio = read_gpio(freq_gpio_np); - if (slew_done_gpio_np) - slew_done_gpio = read_gpio(slew_done_gpio_np); - - /* If we use the frequency GPIOs, calculate the min/max speeds based - * on the bus frequencies - */ - if (frequency_gpio && slew_done_gpio) { - int lenp, rc; - u32 *freqs, *ratio; - - freqs = (u32 *)get_property(cpunode, "bus-frequencies", &lenp); - lenp /= sizeof(u32); - if (freqs == NULL || lenp != 2) { - printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n"); - return 1; - } - ratio = (u32 *)get_property(cpunode, "processor-to-bus-ratio*2", NULL); - if (ratio == NULL) { - printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n"); - return 1; - } - - /* Get the min/max bus frequencies */ - low_freq = min(freqs[0], freqs[1]); - hi_freq = max(freqs[0], freqs[1]); - - /* Grrrr.. It _seems_ that the device-tree is lying on the low bus - * frequency, it claims it to be around 84Mhz on some models while - * it appears to be approx. 101Mhz on all. Let's hack around here... - * fortunately, we don't need to be too precise - */ - if (low_freq < 98000000) - low_freq = 101000000; - - /* Convert those to CPU core clocks */ - low_freq = (low_freq * (*ratio)) / 2000; - hi_freq = (hi_freq * (*ratio)) / 2000; - - /* Now we get the frequencies, we read the GPIO to see what is out current - * speed - */ - rc = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0); - cur_freq = (rc & 0x01) ? hi_freq : low_freq; - - set_speed_proc = gpios_set_cpu_speed; - return 1; - } - - /* If we use the PMU, look for the min & max frequencies in the - * device-tree - */ - value = (u32 *)get_property(cpunode, "min-clock-frequency", NULL); - if (!value) - return 1; - low_freq = (*value) / 1000; - /* The PowerBook G4 12" (PowerBook6,1) has an error in the device-tree - * here */ - if (low_freq < 100000) - low_freq *= 10; - - value = (u32 *)get_property(cpunode, "max-clock-frequency", NULL); - if (!value) - return 1; - hi_freq = (*value) / 1000; - set_speed_proc = pmu_set_cpu_speed; - is_pmu_based = 1; - - return 0; -} - -static int pmac_cpufreq_init_7447A(struct device_node *cpunode) -{ - struct device_node *volt_gpio_np; - - if (get_property(cpunode, "dynamic-power-step", NULL) == NULL) - return 1; - - volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select"); - if (volt_gpio_np) - voltage_gpio = read_gpio(volt_gpio_np); - if (!voltage_gpio){ - printk(KERN_ERR "cpufreq: missing cpu-vcore-select gpio\n"); - return 1; - } - - /* OF only reports the high frequency */ - hi_freq = cur_freq; - low_freq = cur_freq/2; - - /* Read actual frequency from CPU */ - cur_freq = dfs_get_cpu_speed(); - set_speed_proc = dfs_set_cpu_speed; - get_speed_proc = dfs_get_cpu_speed; - - return 0; -} - -static int pmac_cpufreq_init_750FX(struct device_node *cpunode) -{ - struct device_node *volt_gpio_np; - u32 pvr, *value; - - if (get_property(cpunode, "dynamic-power-step", NULL) == NULL) - return 1; - - hi_freq = cur_freq; - value = (u32 *)get_property(cpunode, "reduced-clock-frequency", NULL); - if (!value) - return 1; - low_freq = (*value) / 1000; - - volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select"); - if (volt_gpio_np) - voltage_gpio = read_gpio(volt_gpio_np); - - pvr = mfspr(SPRN_PVR); - has_cpu_l2lve = !((pvr & 0xf00) == 0x100); - - set_speed_proc = cpu_750fx_cpu_speed; - get_speed_proc = cpu_750fx_get_cpu_speed; - cur_freq = cpu_750fx_get_cpu_speed(); - - return 0; -} - -/* Currently, we support the following machines: - * - * - Titanium PowerBook 1Ghz (PMU based, 667Mhz & 1Ghz) - * - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz) - * - Titanium PowerBook 400 (PMU based, 300Mhz & 400Mhz) - * - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz) - * - iBook2 500/600 (PMU based, 400Mhz & 500/600Mhz) - * - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage) - * - Recent MacRISC3 laptops - * - All new machines with 7447A CPUs - */ -static int __init pmac_cpufreq_setup(void) -{ - struct device_node *cpunode; - u32 *value; - - if (strstr(cmd_line, "nocpufreq")) - return 0; - - /* Assume only one CPU */ - cpunode = find_type_devices("cpu"); - if (!cpunode) - goto out; - - /* Get current cpu clock freq */ - value = (u32 *)get_property(cpunode, "clock-frequency", NULL); - if (!value) - goto out; - cur_freq = (*value) / 1000; - - /* Check for 7447A based MacRISC3 */ - if (machine_is_compatible("MacRISC3") && - get_property(cpunode, "dynamic-power-step", NULL) && - PVR_VER(mfspr(SPRN_PVR)) == 0x8003) { - pmac_cpufreq_init_7447A(cpunode); - /* Check for other MacRISC3 machines */ - } else if (machine_is_compatible("PowerBook3,4") || - machine_is_compatible("PowerBook3,5") || - machine_is_compatible("MacRISC3")) { - pmac_cpufreq_init_MacRISC3(cpunode); - /* Else check for iBook2 500/600 */ - } else if (machine_is_compatible("PowerBook4,1")) { - hi_freq = cur_freq; - low_freq = 400000; - set_speed_proc = pmu_set_cpu_speed; - is_pmu_based = 1; - } - /* Else check for TiPb 550 */ - else if (machine_is_compatible("PowerBook3,3") && cur_freq == 550000) { - hi_freq = cur_freq; - low_freq = 500000; - set_speed_proc = pmu_set_cpu_speed; - is_pmu_based = 1; - } - /* Else check for TiPb 400 & 500 */ - else if (machine_is_compatible("PowerBook3,2")) { - /* We only know about the 400 MHz and the 500Mhz model - * they both have 300 MHz as low frequency - */ - if (cur_freq < 350000 || cur_freq > 550000) - goto out; - hi_freq = cur_freq; - low_freq = 300000; - set_speed_proc = pmu_set_cpu_speed; - is_pmu_based = 1; - } - /* Else check for 750FX */ - else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000) - pmac_cpufreq_init_750FX(cpunode); -out: - if (set_speed_proc == NULL) - return -ENODEV; - - pmac_cpu_freqs[CPUFREQ_LOW].frequency = low_freq; - pmac_cpu_freqs[CPUFREQ_HIGH].frequency = hi_freq; - - printk(KERN_INFO "Registering PowerMac CPU frequency driver\n"); - printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Boot: %d Mhz\n", - low_freq/1000, hi_freq/1000, cur_freq/1000); - - return cpufreq_register_driver(&pmac_cpufreq_driver); -} - -module_init(pmac_cpufreq_setup); - diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c new file mode 100644 index 00000000000..7960a7bfca0 --- /dev/null +++ b/arch/powerpc/platforms/powermac/cpufreq_32.c @@ -0,0 +1,727 @@ +/* + * arch/ppc/platforms/pmac_cpufreq.c + * + * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt + * Copyright (C) 2004 John Steele Scott + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * TODO: Need a big cleanup here. Basically, we need to have different + * cpufreq_driver structures for the different type of HW instead of the + * current mess. We also need to better deal with the detection of the + * type of machine. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* WARNING !!! This will cause calibrate_delay() to be called, + * but this is an __init function ! So you MUST go edit + * init/main.c to make it non-init before enabling DEBUG_FREQ + */ +#undef DEBUG_FREQ + +/* + * There is a problem with the core cpufreq code on SMP kernels, + * it won't recalculate the Bogomips properly + */ +#ifdef CONFIG_SMP +#warning "WARNING, CPUFREQ not recommended on SMP kernels" +#endif + +extern void low_choose_7447a_dfs(int dfs); +extern void low_choose_750fx_pll(int pll); +extern void low_sleep_handler(void); + +/* + * Currently, PowerMac cpufreq supports only high & low frequencies + * that are set by the firmware + */ +static unsigned int low_freq; +static unsigned int hi_freq; +static unsigned int cur_freq; +static unsigned int sleep_freq; + +/* + * Different models uses different mecanisms to switch the frequency + */ +static int (*set_speed_proc)(int low_speed); +static unsigned int (*get_speed_proc)(void); + +/* + * Some definitions used by the various speedprocs + */ +static u32 voltage_gpio; +static u32 frequency_gpio; +static u32 slew_done_gpio; +static int no_schedule; +static int has_cpu_l2lve; +static int is_pmu_based; + +/* There are only two frequency states for each processor. Values + * are in kHz for the time being. + */ +#define CPUFREQ_HIGH 0 +#define CPUFREQ_LOW 1 + +static struct cpufreq_frequency_table pmac_cpu_freqs[] = { + {CPUFREQ_HIGH, 0}, + {CPUFREQ_LOW, 0}, + {0, CPUFREQ_TABLE_END}, +}; + +static struct freq_attr* pmac_cpu_freqs_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + +static inline void local_delay(unsigned long ms) +{ + if (no_schedule) + mdelay(ms); + else + msleep(ms); +} + +#ifdef DEBUG_FREQ +static inline void debug_calc_bogomips(void) +{ + /* This will cause a recalc of bogomips and display the + * result. We backup/restore the value to avoid affecting the + * core cpufreq framework's own calculation. + */ + extern void calibrate_delay(void); + + unsigned long save_lpj = loops_per_jiffy; + calibrate_delay(); + loops_per_jiffy = save_lpj; +} +#endif /* DEBUG_FREQ */ + +/* Switch CPU speed under 750FX CPU control + */ +static int cpu_750fx_cpu_speed(int low_speed) +{ + u32 hid2; + + if (low_speed == 0) { + /* ramping up, set voltage first */ + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); + /* Make sure we sleep for at least 1ms */ + local_delay(10); + + /* tweak L2 for high voltage */ + if (has_cpu_l2lve) { + hid2 = mfspr(SPRN_HID2); + hid2 &= ~0x2000; + mtspr(SPRN_HID2, hid2); + } + } +#ifdef CONFIG_6xx + low_choose_750fx_pll(low_speed); +#endif + if (low_speed == 1) { + /* tweak L2 for low voltage */ + if (has_cpu_l2lve) { + hid2 = mfspr(SPRN_HID2); + hid2 |= 0x2000; + mtspr(SPRN_HID2, hid2); + } + + /* ramping down, set voltage last */ + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); + local_delay(10); + } + + return 0; +} + +static unsigned int cpu_750fx_get_cpu_speed(void) +{ + if (mfspr(SPRN_HID1) & HID1_PS) + return low_freq; + else + return hi_freq; +} + +/* Switch CPU speed using DFS */ +static int dfs_set_cpu_speed(int low_speed) +{ + if (low_speed == 0) { + /* ramping up, set voltage first */ + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); + /* Make sure we sleep for at least 1ms */ + local_delay(1); + } + + /* set frequency */ +#ifdef CONFIG_6xx + low_choose_7447a_dfs(low_speed); +#endif + udelay(100); + + if (low_speed == 1) { + /* ramping down, set voltage last */ + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); + local_delay(1); + } + + return 0; +} + +static unsigned int dfs_get_cpu_speed(void) +{ + if (mfspr(SPRN_HID1) & HID1_DFS) + return low_freq; + else + return hi_freq; +} + + +/* Switch CPU speed using slewing GPIOs + */ +static int gpios_set_cpu_speed(int low_speed) +{ + int gpio, timeout = 0; + + /* If ramping up, set voltage first */ + if (low_speed == 0) { + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); + /* Delay is way too big but it's ok, we schedule */ + local_delay(10); + } + + /* Set frequency */ + gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0); + if (low_speed == ((gpio & 0x01) == 0)) + goto skip; + + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, frequency_gpio, + low_speed ? 0x04 : 0x05); + udelay(200); + do { + if (++timeout > 100) + break; + local_delay(1); + gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, slew_done_gpio, 0); + } while((gpio & 0x02) == 0); + skip: + /* If ramping down, set voltage last */ + if (low_speed == 1) { + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); + /* Delay is way too big but it's ok, we schedule */ + local_delay(10); + } + +#ifdef DEBUG_FREQ + debug_calc_bogomips(); +#endif + + return 0; +} + +/* Switch CPU speed under PMU control + */ +static int pmu_set_cpu_speed(int low_speed) +{ + struct adb_request req; + unsigned long save_l2cr; + unsigned long save_l3cr; + unsigned int pic_prio; + unsigned long flags; + + preempt_disable(); + +#ifdef DEBUG_FREQ + printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1)); +#endif + pmu_suspend(); + + /* Disable all interrupt sources on openpic */ + pic_prio = mpic_cpu_get_priority(); + mpic_cpu_set_priority(0xf); + + /* Make sure the decrementer won't interrupt us */ + asm volatile("mtdec %0" : : "r" (0x7fffffff)); + /* Make sure any pending DEC interrupt occuring while we did + * the above didn't re-enable the DEC */ + mb(); + asm volatile("mtdec %0" : : "r" (0x7fffffff)); + + /* We can now disable MSR_EE */ + local_irq_save(flags); + + /* Giveup the FPU & vec */ + enable_kernel_fp(); + +#ifdef CONFIG_ALTIVEC + if (cpu_has_feature(CPU_FTR_ALTIVEC)) + enable_kernel_altivec(); +#endif /* CONFIG_ALTIVEC */ + + /* Save & disable L2 and L3 caches */ + save_l3cr = _get_L3CR(); /* (returns -1 if not available) */ + save_l2cr = _get_L2CR(); /* (returns -1 if not available) */ + + /* Send the new speed command. My assumption is that this command + * will cause PLL_CFG[0..3] to be changed next time CPU goes to sleep + */ + pmu_request(&req, NULL, 6, PMU_CPU_SPEED, 'W', 'O', 'O', 'F', low_speed); + while (!req.complete) + pmu_poll(); + + /* Prepare the northbridge for the speed transition */ + pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,1); + + /* Call low level code to backup CPU state and recover from + * hardware reset + */ + low_sleep_handler(); + + /* Restore the northbridge */ + pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,0); + + /* Restore L2 cache */ + if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0) + _set_L2CR(save_l2cr); + /* Restore L3 cache */ + if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0) + _set_L3CR(save_l3cr); + + /* Restore userland MMU context */ + set_context(current->active_mm->context, current->active_mm->pgd); + +#ifdef DEBUG_FREQ + printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1)); +#endif + + /* Restore low level PMU operations */ + pmu_unlock(); + + /* Restore decrementer */ + wakeup_decrementer(); + + /* Restore interrupts */ + mpic_cpu_set_priority(pic_prio); + + /* Let interrupts flow again ... */ + local_irq_restore(flags); + +#ifdef DEBUG_FREQ + debug_calc_bogomips(); +#endif + + pmu_resume(); + + preempt_enable(); + + return 0; +} + +static int do_set_cpu_speed(int speed_mode, int notify) +{ + struct cpufreq_freqs freqs; + unsigned long l3cr; + static unsigned long prev_l3cr; + + freqs.old = cur_freq; + freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; + freqs.cpu = smp_processor_id(); + + if (freqs.old == freqs.new) + return 0; + + if (notify) + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + if (speed_mode == CPUFREQ_LOW && + cpu_has_feature(CPU_FTR_L3CR)) { + l3cr = _get_L3CR(); + if (l3cr & L3CR_L3E) { + prev_l3cr = l3cr; + _set_L3CR(0); + } + } + set_speed_proc(speed_mode == CPUFREQ_LOW); + if (speed_mode == CPUFREQ_HIGH && + cpu_has_feature(CPU_FTR_L3CR)) { + l3cr = _get_L3CR(); + if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr) + _set_L3CR(prev_l3cr); + } + if (notify) + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; + + return 0; +} + +static unsigned int pmac_cpufreq_get_speed(unsigned int cpu) +{ + return cur_freq; +} + +static int pmac_cpufreq_verify(struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, pmac_cpu_freqs); +} + +static int pmac_cpufreq_target( struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + unsigned int newstate = 0; + int rc; + + if (cpufreq_frequency_table_target(policy, pmac_cpu_freqs, + target_freq, relation, &newstate)) + return -EINVAL; + + rc = do_set_cpu_speed(newstate, 1); + + ppc_proc_freq = cur_freq * 1000ul; + return rc; +} + +static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy) +{ + if (policy->cpu != 0) + return -ENODEV; + + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + policy->cur = cur_freq; + + cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu); + return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs); +} + +static u32 read_gpio(struct device_node *np) +{ + u32 *reg = (u32 *)get_property(np, "reg", NULL); + u32 offset; + + if (reg == NULL) + return 0; + /* That works for all keylargos but shall be fixed properly + * some day... The problem is that it seems we can't rely + * on the "reg" property of the GPIO nodes, they are either + * relative to the base of KeyLargo or to the base of the + * GPIO space, and the device-tree doesn't help. + */ + offset = *reg; + if (offset < KEYLARGO_GPIO_LEVELS0) + offset += KEYLARGO_GPIO_LEVELS0; + return offset; +} + +static int pmac_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg) +{ + /* Ok, this could be made a bit smarter, but let's be robust for now. We + * always force a speed change to high speed before sleep, to make sure + * we have appropriate voltage and/or bus speed for the wakeup process, + * and to make sure our loops_per_jiffies are "good enough", that is will + * not cause too short delays if we sleep in low speed and wake in high + * speed.. + */ + no_schedule = 1; + sleep_freq = cur_freq; + if (cur_freq == low_freq && !is_pmu_based) + do_set_cpu_speed(CPUFREQ_HIGH, 0); + return 0; +} + +static int pmac_cpufreq_resume(struct cpufreq_policy *policy) +{ + /* If we resume, first check if we have a get() function */ + if (get_speed_proc) + cur_freq = get_speed_proc(); + else) + cur_freq = 0; + + /* We don't, hrm... we don't really know our speed here, best + * is that we force a switch to whatever it was, which is + * probably high speed due to our suspend() routine + */ + do_set_cpu_speed(sleep_freq == low_freq ? + CPUFREQ_LOW : CPUFREQ_HIGH, 0); + + ppc_proc_freq = cur_freq * 1000ul; + + no_schedule = 0; + return 0; +} + +static struct cpufreq_driver pmac_cpufreq_driver = { + .verify = pmac_cpufreq_verify, + .target = pmac_cpufreq_target, + .get = pmac_cpufreq_get_speed, + .init = pmac_cpufreq_cpu_init, + .suspend = pmac_cpufreq_suspend, + .resume = pmac_cpufreq_resume, + .flags = CPUFREQ_PM_NO_WARN, + .attr = pmac_cpu_freqs_attr, + .name = "powermac", + .owner = THIS_MODULE, +}; + + +static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode) +{ + struct device_node *volt_gpio_np = of_find_node_by_name(NULL, + "voltage-gpio"); + struct device_node *freq_gpio_np = of_find_node_by_name(NULL, + "frequency-gpio"); + struct device_node *slew_done_gpio_np = of_find_node_by_name(NULL, + "slewing-done"); + u32 *value; + + /* + * Check to see if it's GPIO driven or PMU only + * + * The way we extract the GPIO address is slightly hackish, but it + * works well enough for now. We need to abstract the whole GPIO + * stuff sooner or later anyway + */ + + if (volt_gpio_np) + voltage_gpio = read_gpio(volt_gpio_np); + if (freq_gpio_np) + frequency_gpio = read_gpio(freq_gpio_np); + if (slew_done_gpio_np) + slew_done_gpio = read_gpio(slew_done_gpio_np); + + /* If we use the frequency GPIOs, calculate the min/max speeds based + * on the bus frequencies + */ + if (frequency_gpio && slew_done_gpio) { + int lenp, rc; + u32 *freqs, *ratio; + + freqs = (u32 *)get_property(cpunode, "bus-frequencies", &lenp); + lenp /= sizeof(u32); + if (freqs == NULL || lenp != 2) { + printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n"); + return 1; + } + ratio = (u32 *)get_property(cpunode, "processor-to-bus-ratio*2", NULL); + if (ratio == NULL) { + printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n"); + return 1; + } + + /* Get the min/max bus frequencies */ + low_freq = min(freqs[0], freqs[1]); + hi_freq = max(freqs[0], freqs[1]); + + /* Grrrr.. It _seems_ that the device-tree is lying on the low bus + * frequency, it claims it to be around 84Mhz on some models while + * it appears to be approx. 101Mhz on all. Let's hack around here... + * fortunately, we don't need to be too precise + */ + if (low_freq < 98000000) + low_freq = 101000000; + + /* Convert those to CPU core clocks */ + low_freq = (low_freq * (*ratio)) / 2000; + hi_freq = (hi_freq * (*ratio)) / 2000; + + /* Now we get the frequencies, we read the GPIO to see what is out current + * speed + */ + rc = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0); + cur_freq = (rc & 0x01) ? hi_freq : low_freq; + + set_speed_proc = gpios_set_cpu_speed; + return 1; + } + + /* If we use the PMU, look for the min & max frequencies in the + * device-tree + */ + value = (u32 *)get_property(cpunode, "min-clock-frequency", NULL); + if (!value) + return 1; + low_freq = (*value) / 1000; + /* The PowerBook G4 12" (PowerBook6,1) has an error in the device-tree + * here */ + if (low_freq < 100000) + low_freq *= 10; + + value = (u32 *)get_property(cpunode, "max-clock-frequency", NULL); + if (!value) + return 1; + hi_freq = (*value) / 1000; + set_speed_proc = pmu_set_cpu_speed; + is_pmu_based = 1; + + return 0; +} + +static int pmac_cpufreq_init_7447A(struct device_node *cpunode) +{ + struct device_node *volt_gpio_np; + + if (get_property(cpunode, "dynamic-power-step", NULL) == NULL) + return 1; + + volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select"); + if (volt_gpio_np) + voltage_gpio = read_gpio(volt_gpio_np); + if (!voltage_gpio){ + printk(KERN_ERR "cpufreq: missing cpu-vcore-select gpio\n"); + return 1; + } + + /* OF only reports the high frequency */ + hi_freq = cur_freq; + low_freq = cur_freq/2; + + /* Read actual frequency from CPU */ + cur_freq = dfs_get_cpu_speed(); + set_speed_proc = dfs_set_cpu_speed; + get_speed_proc = dfs_get_cpu_speed; + + return 0; +} + +static int pmac_cpufreq_init_750FX(struct device_node *cpunode) +{ + struct device_node *volt_gpio_np; + u32 pvr, *value; + + if (get_property(cpunode, "dynamic-power-step", NULL) == NULL) + return 1; + + hi_freq = cur_freq; + value = (u32 *)get_property(cpunode, "reduced-clock-frequency", NULL); + if (!value) + return 1; + low_freq = (*value) / 1000; + + volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select"); + if (volt_gpio_np) + voltage_gpio = read_gpio(volt_gpio_np); + + pvr = mfspr(SPRN_PVR); + has_cpu_l2lve = !((pvr & 0xf00) == 0x100); + + set_speed_proc = cpu_750fx_cpu_speed; + get_speed_proc = cpu_750fx_get_cpu_speed; + cur_freq = cpu_750fx_get_cpu_speed(); + + return 0; +} + +/* Currently, we support the following machines: + * + * - Titanium PowerBook 1Ghz (PMU based, 667Mhz & 1Ghz) + * - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz) + * - Titanium PowerBook 400 (PMU based, 300Mhz & 400Mhz) + * - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz) + * - iBook2 500/600 (PMU based, 400Mhz & 500/600Mhz) + * - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage) + * - Recent MacRISC3 laptops + * - All new machines with 7447A CPUs + */ +static int __init pmac_cpufreq_setup(void) +{ + struct device_node *cpunode; + u32 *value; + + if (strstr(cmd_line, "nocpufreq")) + return 0; + + /* Assume only one CPU */ + cpunode = find_type_devices("cpu"); + if (!cpunode) + goto out; + + /* Get current cpu clock freq */ + value = (u32 *)get_property(cpunode, "clock-frequency", NULL); + if (!value) + goto out; + cur_freq = (*value) / 1000; + + /* Check for 7447A based MacRISC3 */ + if (machine_is_compatible("MacRISC3") && + get_property(cpunode, "dynamic-power-step", NULL) && + PVR_VER(mfspr(SPRN_PVR)) == 0x8003) { + pmac_cpufreq_init_7447A(cpunode); + /* Check for other MacRISC3 machines */ + } else if (machine_is_compatible("PowerBook3,4") || + machine_is_compatible("PowerBook3,5") || + machine_is_compatible("MacRISC3")) { + pmac_cpufreq_init_MacRISC3(cpunode); + /* Else check for iBook2 500/600 */ + } else if (machine_is_compatible("PowerBook4,1")) { + hi_freq = cur_freq; + low_freq = 400000; + set_speed_proc = pmu_set_cpu_speed; + is_pmu_based = 1; + } + /* Else check for TiPb 550 */ + else if (machine_is_compatible("PowerBook3,3") && cur_freq == 550000) { + hi_freq = cur_freq; + low_freq = 500000; + set_speed_proc = pmu_set_cpu_speed; + is_pmu_based = 1; + } + /* Else check for TiPb 400 & 500 */ + else if (machine_is_compatible("PowerBook3,2")) { + /* We only know about the 400 MHz and the 500Mhz model + * they both have 300 MHz as low frequency + */ + if (cur_freq < 350000 || cur_freq > 550000) + goto out; + hi_freq = cur_freq; + low_freq = 300000; + set_speed_proc = pmu_set_cpu_speed; + is_pmu_based = 1; + } + /* Else check for 750FX */ + else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000) + pmac_cpufreq_init_750FX(cpunode); +out: + if (set_speed_proc == NULL) + return -ENODEV; + + pmac_cpu_freqs[CPUFREQ_LOW].frequency = low_freq; + pmac_cpu_freqs[CPUFREQ_HIGH].frequency = hi_freq; + ppc_proc_freq = cur_freq * 1000ul; + + printk(KERN_INFO "Registering PowerMac CPU frequency driver\n"); + printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Boot: %d Mhz\n", + low_freq/1000, hi_freq/1000, cur_freq/1000); + + return cpufreq_register_driver(&pmac_cpufreq_driver); +} + +module_init(pmac_cpufreq_setup); + diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c new file mode 100644 index 00000000000..39150342c6f --- /dev/null +++ b/arch/powerpc/platforms/powermac/cpufreq_64.c @@ -0,0 +1,323 @@ +/* + * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt + * and Markus Demleitner + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This driver adds basic cpufreq support for SMU & 970FX based G5 Macs, + * that is iMac G5 and latest single CPU desktop. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG + +#ifdef DEBUG +#define DBG(fmt...) printk(fmt) +#else +#define DBG(fmt...) +#endif + +/* see 970FX user manual */ + +#define SCOM_PCR 0x0aa001 /* PCR scom addr */ + +#define PCR_HILO_SELECT 0x80000000U /* 1 = PCR, 0 = PCRH */ +#define PCR_SPEED_FULL 0x00000000U /* 1:1 speed value */ +#define PCR_SPEED_HALF 0x00020000U /* 1:2 speed value */ +#define PCR_SPEED_QUARTER 0x00040000U /* 1:4 speed value */ +#define PCR_SPEED_MASK 0x000e0000U /* speed mask */ +#define PCR_SPEED_SHIFT 17 +#define PCR_FREQ_REQ_VALID 0x00010000U /* freq request valid */ +#define PCR_VOLT_REQ_VALID 0x00008000U /* volt request valid */ +#define PCR_TARGET_TIME_MASK 0x00006000U /* target time */ +#define PCR_STATLAT_MASK 0x00001f00U /* STATLAT value */ +#define PCR_SNOOPLAT_MASK 0x000000f0U /* SNOOPLAT value */ +#define PCR_SNOOPACC_MASK 0x0000000fU /* SNOOPACC value */ + +#define SCOM_PSR 0x408001 /* PSR scom addr */ +/* warning: PSR is a 64 bits register */ +#define PSR_CMD_RECEIVED 0x2000000000000000U /* command received */ +#define PSR_CMD_COMPLETED 0x1000000000000000U /* command completed */ +#define PSR_CUR_SPEED_MASK 0x0300000000000000U /* current speed */ +#define PSR_CUR_SPEED_SHIFT (56) + +/* + * The G5 only supports two frequencies (Quarter speed is not supported) + */ +#define CPUFREQ_HIGH 0 +#define CPUFREQ_LOW 1 + +static struct cpufreq_frequency_table g5_cpu_freqs[] = { + {CPUFREQ_HIGH, 0}, + {CPUFREQ_LOW, 0}, + {0, CPUFREQ_TABLE_END}, +}; + +static struct freq_attr* g5_cpu_freqs_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + +/* Power mode data is an array of the 32 bits PCR values to use for + * the various frequencies, retreived from the device-tree + */ +static u32 *g5_pmode_data; +static int g5_pmode_max; +static int g5_pmode_cur; + +static DECLARE_MUTEX(g5_switch_mutex); + + +static struct smu_sdbp_fvt *g5_fvt_table; /* table of op. points */ +static int g5_fvt_count; /* number of op. points */ +static int g5_fvt_cur; /* current op. point */ + +/* ----------------- real hardware interface */ + +static void g5_switch_volt(int speed_mode) +{ + struct smu_simple_cmd cmd; + + DECLARE_COMPLETION(comp); + smu_queue_simple(&cmd, SMU_CMD_POWER_COMMAND, 8, smu_done_complete, + &comp, 'V', 'S', 'L', 'E', 'W', + 0xff, g5_fvt_cur+1, speed_mode); + wait_for_completion(&comp); +} + +static int g5_switch_freq(int speed_mode) +{ + struct cpufreq_freqs freqs; + int to; + + if (g5_pmode_cur == speed_mode) + return 0; + + down(&g5_switch_mutex); + + freqs.old = g5_cpu_freqs[g5_pmode_cur].frequency; + freqs.new = g5_cpu_freqs[speed_mode].frequency; + freqs.cpu = 0; + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + /* If frequency is going up, first ramp up the voltage */ + if (speed_mode < g5_pmode_cur) + g5_switch_volt(speed_mode); + + /* Clear PCR high */ + scom970_write(SCOM_PCR, 0); + /* Clear PCR low */ + scom970_write(SCOM_PCR, PCR_HILO_SELECT | 0); + /* Set PCR low */ + scom970_write(SCOM_PCR, PCR_HILO_SELECT | + g5_pmode_data[speed_mode]); + + /* Wait for completion */ + for (to = 0; to < 10; to++) { + unsigned long psr = scom970_read(SCOM_PSR); + + if ((psr & PSR_CMD_RECEIVED) == 0 && + (((psr >> PSR_CUR_SPEED_SHIFT) ^ + (g5_pmode_data[speed_mode] >> PCR_SPEED_SHIFT)) & 0x3) + == 0) + break; + if (psr & PSR_CMD_COMPLETED) + break; + udelay(100); + } + + /* If frequency is going down, last ramp the voltage */ + if (speed_mode > g5_pmode_cur) + g5_switch_volt(speed_mode); + + g5_pmode_cur = speed_mode; + ppc_proc_freq = g5_cpu_freqs[speed_mode].frequency * 1000ul; + + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + up(&g5_switch_mutex); + + return 0; +} + +static int g5_query_freq(void) +{ + unsigned long psr = scom970_read(SCOM_PSR); + int i; + + for (i = 0; i <= g5_pmode_max; i++) + if ((((psr >> PSR_CUR_SPEED_SHIFT) ^ + (g5_pmode_data[i] >> PCR_SPEED_SHIFT)) & 0x3) == 0) + break; + return i; +} + +/* ----------------- cpufreq bookkeeping */ + +static int g5_cpufreq_verify(struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, g5_cpu_freqs); +} + +static int g5_cpufreq_target(struct cpufreq_policy *policy, + unsigned int target_freq, unsigned int relation) +{ + unsigned int newstate = 0; + + if (cpufreq_frequency_table_target(policy, g5_cpu_freqs, + target_freq, relation, &newstate)) + return -EINVAL; + + return g5_switch_freq(newstate); +} + +static unsigned int g5_cpufreq_get_speed(unsigned int cpu) +{ + return g5_cpu_freqs[g5_pmode_cur].frequency; +} + +static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy) +{ + if (policy->cpu != 0) + return -ENODEV; + + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + policy->cur = g5_cpu_freqs[g5_query_freq()].frequency; + cpufreq_frequency_table_get_attr(g5_cpu_freqs, policy->cpu); + + return cpufreq_frequency_table_cpuinfo(policy, + g5_cpu_freqs); +} + + +static struct cpufreq_driver g5_cpufreq_driver = { + .name = "powermac", + .owner = THIS_MODULE, + .flags = CPUFREQ_CONST_LOOPS, + .init = g5_cpufreq_cpu_init, + .verify = g5_cpufreq_verify, + .target = g5_cpufreq_target, + .get = g5_cpufreq_get_speed, + .attr = g5_cpu_freqs_attr, +}; + + +static int __init g5_cpufreq_init(void) +{ + struct device_node *cpunode; + unsigned int psize, ssize; + struct smu_sdbp_header *shdr; + unsigned long max_freq; + u32 *valp; + int rc = -ENODEV; + + /* Look for CPU and SMU nodes */ + cpunode = of_find_node_by_type(NULL, "cpu"); + if (!cpunode) { + DBG("No CPU node !\n"); + return -ENODEV; + } + + /* Check 970FX for now */ + valp = (u32 *)get_property(cpunode, "cpu-version", NULL); + if (!valp) { + DBG("No cpu-version property !\n"); + goto bail_noprops; + } + if (((*valp) >> 16) != 0x3c) { + DBG("Wrong CPU version: %08x\n", *valp); + goto bail_noprops; + } + + /* Look for the powertune data in the device-tree */ + g5_pmode_data = (u32 *)get_property(cpunode, "power-mode-data",&psize); + if (!g5_pmode_data) { + DBG("No power-mode-data !\n"); + goto bail_noprops; + } + g5_pmode_max = psize / sizeof(u32) - 1; + + /* Look for the FVT table */ + shdr = smu_get_sdb_partition(SMU_SDB_FVT_ID, NULL); + if (!shdr) + goto bail_noprops; + g5_fvt_table = (struct smu_sdbp_fvt *)&shdr[1]; + ssize = (shdr->len * sizeof(u32)) - sizeof(struct smu_sdbp_header); + g5_fvt_count = ssize / sizeof(struct smu_sdbp_fvt); + g5_fvt_cur = 0; + + /* Sanity checking */ + if (g5_fvt_count < 1 || g5_pmode_max < 1) + goto bail_noprops; + + /* + * From what I see, clock-frequency is always the maximal frequency. + * The current driver can not slew sysclk yet, so we really only deal + * with powertune steps for now. We also only implement full freq and + * half freq in this version. So far, I haven't yet seen a machine + * supporting anything else. + */ + valp = (u32 *)get_property(cpunode, "clock-frequency", NULL); + if (!valp) + return -ENODEV; + max_freq = (*valp)/1000; + g5_cpu_freqs[0].frequency = max_freq; + g5_cpu_freqs[1].frequency = max_freq/2; + + /* Check current frequency */ + g5_pmode_cur = g5_query_freq(); + if (g5_pmode_cur > 1) + /* We don't support anything but 1:1 and 1:2, fixup ... */ + g5_pmode_cur = 1; + + /* Force apply current frequency to make sure everything is in + * sync (voltage is right for example). Firmware may leave us with + * a strange setting ... + */ + g5_switch_freq(g5_pmode_cur); + + printk(KERN_INFO "Registering G5 CPU frequency driver\n"); + printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n", + g5_cpu_freqs[1].frequency/1000, + g5_cpu_freqs[0].frequency/1000, + g5_cpu_freqs[g5_pmode_cur].frequency/1000); + + rc = cpufreq_register_driver(&g5_cpufreq_driver); + + /* We keep the CPU node on hold... hopefully, Apple G5 don't have + * hotplug CPU with a dynamic device-tree ... + */ + return rc; + + bail_noprops: + of_node_put(cpunode); + + return rc; +} + +module_init(g5_cpufreq_init); + + +MODULE_LICENSE("GPL"); diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 80b58c1ec41..7acb0546671 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -193,18 +193,6 @@ static void pmac_show_cpuinfo(struct seq_file *m) pmac_newworld ? "NewWorld" : "OldWorld"); } -static void pmac_show_percpuinfo(struct seq_file *m, int i) -{ -#ifdef CONFIG_CPU_FREQ_PMAC - extern unsigned int pmac_get_one_cpufreq(int i); - unsigned int freq = pmac_get_one_cpufreq(i); - if (freq != 0) { - seq_printf(m, "clock\t\t: %dMHz\n", freq/1000); - return; - } -#endif /* CONFIG_CPU_FREQ_PMAC */ -} - #ifndef CONFIG_ADB_CUDA int find_via_cuda(void) { @@ -767,7 +755,6 @@ struct machdep_calls __initdata pmac_md = { .setup_arch = pmac_setup_arch, .init_early = pmac_init_early, .show_cpuinfo = pmac_show_cpuinfo, - .show_percpuinfo = pmac_show_percpuinfo, .init_IRQ = pmac_pic_init, .get_irq = mpic_get_irq, /* changed later */ .pcibios_fixup = pmac_pcibios_fixup, diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig index 2130cc31595..94a81279dea 100644 --- a/arch/ppc64/Kconfig +++ b/arch/ppc64/Kconfig @@ -173,6 +173,16 @@ config KEXEC support. As of this writing the exact hardware interface is strongly in flux, so no good recommendation can be made. +source "drivers/cpufreq/Kconfig" + +config CPU_FREQ_PMAC64 + bool "Support for some Apple G5s" + depends on CPU_FREQ && PMAC_SMU && PPC64 + select CPU_FREQ_TABLE + help + This adds support for frequency switching on Apple iMac G5, + and some of the more recent desktop G5 machines as well. + config IBMVIO depends on PPC_PSERIES || PPC_ISERIES bool diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S index 077507ffbab..914632ec587 100644 --- a/arch/ppc64/kernel/misc.S +++ b/arch/ppc64/kernel/misc.S @@ -560,7 +560,7 @@ _GLOBAL(real_readb) isync blr - /* +/* * Do an IO access in real mode */ _GLOBAL(real_writeb) @@ -592,6 +592,76 @@ _GLOBAL(real_writeb) blr #endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */ +/* + * SCOM access functions for 970 (FX only for now) + * + * unsigned long scom970_read(unsigned int address); + * void scom970_write(unsigned int address, unsigned long value); + * + * The address passed in is the 24 bits register address. This code + * is 970 specific and will not check the status bits, so you should + * know what you are doing. + */ +_GLOBAL(scom970_read) + /* interrupts off */ + mfmsr r4 + ori r0,r4,MSR_EE + xori r0,r0,MSR_EE + mtmsrd r0,1 + + /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits + * (including parity). On current CPUs they must be 0'd, + * and finally or in RW bit + */ + rlwinm r3,r3,8,0,15 + ori r3,r3,0x8000 + + /* do the actual scom read */ + sync + mtspr SPRN_SCOMC,r3 + isync + mfspr r3,SPRN_SCOMD + isync + mfspr r0,SPRN_SCOMC + isync + + /* XXX: fixup result on some buggy 970's (ouch ! we lost a bit, bah + * that's the best we can do). Not implemented yet as we don't use + * the scom on any of the bogus CPUs yet, but may have to be done + * ultimately + */ + + /* restore interrupts */ + mtmsrd r4,1 + blr + + +_GLOBAL(scom970_write) + /* interrupts off */ + mfmsr r5 + ori r0,r5,MSR_EE + xori r0,r0,MSR_EE + mtmsrd r0,1 + + /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits + * (including parity). On current CPUs they must be 0'd. + */ + + rlwinm r3,r3,8,0,15 + + sync + mtspr SPRN_SCOMD,r4 /* write data */ + isync + mtspr SPRN_SCOMC,r3 /* write command */ + isync + mfspr 3,SPRN_SCOMC + isync + + /* restore interrupts */ + mtmsrd r5,1 + blr + + /* * Create a kernel thread * kernel_thread(fn, arg, flags) diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index 34f3c7e2d83..a931e508feb 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -845,6 +845,18 @@ int smu_queue_i2c(struct smu_i2c_cmd *cmd) return 0; } +struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size) +{ + char pname[32]; + + if (!smu) + return NULL; + + sprintf(pname, "sdb-partition-%02x", id); + return (struct smu_sdbp_header *)get_property(smu->of_node, + pname, size); +} +EXPORT_SYMBOL(smu_get_sdb_partition); /* diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h index da848412f11..489cf4c99c2 100644 --- a/include/asm-powerpc/reg.h +++ b/include/asm-powerpc/reg.h @@ -396,6 +396,9 @@ #define SPRN_VRSAVE 0x100 /* Vector Register Save Register */ #define SPRN_XER 0x001 /* Fixed Point Exception Register */ +#define SPRN_SCOMC 0x114 /* SCOM Access Control */ +#define SPRN_SCOMD 0x115 /* SCOM Access DATA */ + /* Performance monitor SPRs */ #ifdef CONFIG_PPC64 #define SPRN_MMCR0 795 @@ -594,7 +597,11 @@ static inline void ppc64_runlatch_off(void) mtspr(SPRN_CTRLT, ctrl); } } -#endif + +extern unsigned long scom970_read(unsigned int address); +extern void scom970_write(unsigned int address, unsigned long value); + +#endif /* CONFIG_PPC64 */ #define __get_SP() ({unsigned long sp; \ asm volatile("mr %0,1": "=r" (sp)); sp;}) diff --git a/include/asm-powerpc/smu.h b/include/asm-powerpc/smu.h index dee8eefe47b..959bad66023 100644 --- a/include/asm-powerpc/smu.h +++ b/include/asm-powerpc/smu.h @@ -144,7 +144,11 @@ * - lenght 8 ("VSLEWxyz") has 3 additional bytes appended, and is * used to set the voltage slewing point. The SMU replies with "DONE" * I yet have to figure out their exact meaning of those 3 bytes in - * both cases. + * both cases. They seem to be: + * x = processor mask + * y = op. point index + * z = processor freq. step index + * I haven't yet decyphered result codes * */ #define SMU_CMD_POWER_COMMAND 0xaa @@ -333,6 +337,60 @@ extern int smu_queue_i2c(struct smu_i2c_cmd *cmd); #endif /* __KERNEL__ */ + +/* + * - SMU "sdb" partitions informations - + */ + + +/* + * Partition header format + */ +struct smu_sdbp_header { + __u8 id; + __u8 len; + __u8 version; + __u8 flags; +}; + +/* + * 32 bits integers are usually encoded with 2x16 bits swapped, + * this demangles them + */ +#define SMU_U32_MIX(x) ((((x) << 16) & 0xffff0000u) | (((x) >> 16) & 0xffffu)) + +/* This is the definition of the SMU sdb-partition-0x12 table (called + * CPU F/V/T operating points in Darwin). The definition for all those + * SMU tables should be moved to some separate file + */ +#define SMU_SDB_FVT_ID 0x12 + +struct smu_sdbp_fvt { + __u32 sysclk; /* Base SysClk frequency in Hz for + * this operating point + */ + __u8 pad; + __u8 maxtemp; /* Max temp. supported by this + * operating point + */ + + __u16 volts[3]; /* CPU core voltage for the 3 + * PowerTune modes, a mode with + * 0V = not supported. + */ +}; + +#ifdef __KERNEL__ +/* + * This returns the pointer to an SMU "sdb" partition data or NULL + * if not found. The data format is described below + */ +extern struct smu_sdbp_header *smu_get_sdb_partition(int id, + unsigned int *size); + +#endif /* __KERNEL__ */ + + /* * - Userland interface - */ -- cgit v1.2.3 From 183d020258dfd08178a05c6793dae10409db8abb Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 7 Nov 2005 14:29:02 +1100 Subject: [PATCH] ppc64: SMU partition recovery This patch adds the ability to the SMU driver to recover missing calibration partitions from the SMU chip itself. It also adds some dynamic mecanism to /proc/device-tree so that new properties are visible to userland. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom.c | 21 +++++- arch/ppc/syslib/prom.c | 4 +- arch/ppc64/kernel/prom.c | 24 +++++-- drivers/macintosh/smu.c | 164 ++++++++++++++++++++++++++++++++++++++++++--- fs/proc/proc_devtree.c | 57 ++++++++++------ include/asm-powerpc/prom.h | 2 +- include/asm-powerpc/smu.h | 153 +++++++++++++++++++++++++++++++++++++++--- include/asm-ppc/prom.h | 2 +- include/asm-ppc64/prom.h | 2 +- include/linux/proc_fs.h | 9 +-- 10 files changed, 381 insertions(+), 57 deletions(-) diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 3675ef4bac9..f645adb5753 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1974,14 +1974,29 @@ EXPORT_SYMBOL(get_property); /* * Add a property to a node */ -void prom_add_property(struct device_node* np, struct property* prop) +int prom_add_property(struct device_node* np, struct property* prop) { - struct property **next = &np->properties; + struct property **next; prop->next = NULL; - while (*next) + write_lock(&devtree_lock); + next = &np->properties; + while (*next) { + if (strcmp(prop->name, (*next)->name) == 0) { + /* duplicate ! don't insert it */ + write_unlock(&devtree_lock); + return -1; + } next = &(*next)->next; + } *next = prop; + write_unlock(&devtree_lock); + + /* try to add to proc as well if it was initialized */ + if (np->pde) + proc_device_tree_add_prop(np->pde, prop); + + return 0; } /* I quickly hacked that one, check against spec ! */ diff --git a/arch/ppc/syslib/prom.c b/arch/ppc/syslib/prom.c index 1b9aa0d6a92..03b1fc9b950 100644 --- a/arch/ppc/syslib/prom.c +++ b/arch/ppc/syslib/prom.c @@ -1165,7 +1165,7 @@ get_property(struct device_node *np, const char *name, int *lenp) /* * Add a property to a node */ -void +int prom_add_property(struct device_node* np, struct property* prop) { struct property **next = &np->properties; @@ -1174,6 +1174,8 @@ prom_add_property(struct device_node* np, struct property* prop) while (*next) next = &(*next)->next; *next = prop; + + return 0; } /* I quickly hacked that one, check against spec ! */ diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c index 0e8961dea3b..3402fbee62c 100644 --- a/arch/ppc64/kernel/prom.c +++ b/arch/ppc64/kernel/prom.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -1865,17 +1866,32 @@ get_property(struct device_node *np, const char *name, int *lenp) EXPORT_SYMBOL(get_property); /* - * Add a property to a node + * Add a property to a node. */ -void +int prom_add_property(struct device_node* np, struct property* prop) { - struct property **next = &np->properties; + struct property **next; prop->next = NULL; - while (*next) + write_lock(&devtree_lock); + next = &np->properties; + while (*next) { + if (strcmp(prop->name, (*next)->name) == 0) { + /* duplicate ! don't insert it */ + write_unlock(&devtree_lock); + return -1; + } next = &(*next)->next; + } *next = prop; + write_unlock(&devtree_lock); + + /* try to add to proc as well if it was initialized */ + if (np->pde) + proc_device_tree_add_prop(np->pde, prop); + + return 0; } #if 0 diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index a931e508feb..a83c4acf571 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -47,13 +47,13 @@ #include #include -#define VERSION "0.6" +#define VERSION "0.7" #define AUTHOR "(c) 2005 Benjamin Herrenschmidt, IBM Corp." #undef DEBUG_SMU #ifdef DEBUG_SMU -#define DPRINTK(fmt, args...) do { printk(KERN_DEBUG fmt , ##args); } while (0) +#define DPRINTK(fmt, args...) do { udbg_printf(KERN_DEBUG fmt , ##args); } while (0) #else #define DPRINTK(fmt, args...) do { } while (0) #endif @@ -92,7 +92,7 @@ struct smu_device { * for now, just hard code that */ static struct smu_device *smu; - +static DECLARE_MUTEX(smu_part_access); /* * SMU driver low level stuff @@ -113,9 +113,11 @@ static void smu_start_cmd(void) DPRINTK("SMU: starting cmd %x, %d bytes data\n", cmd->cmd, cmd->data_len); - DPRINTK("SMU: data buffer: %02x %02x %02x %02x ...\n", + DPRINTK("SMU: data buffer: %02x %02x %02x %02x %02x %02x %02x %02x\n", ((u8 *)cmd->data_buf)[0], ((u8 *)cmd->data_buf)[1], - ((u8 *)cmd->data_buf)[2], ((u8 *)cmd->data_buf)[3]); + ((u8 *)cmd->data_buf)[2], ((u8 *)cmd->data_buf)[3], + ((u8 *)cmd->data_buf)[4], ((u8 *)cmd->data_buf)[5], + ((u8 *)cmd->data_buf)[6], ((u8 *)cmd->data_buf)[7]); /* Fill the SMU command buffer */ smu->cmd_buf->cmd = cmd->cmd; @@ -440,7 +442,7 @@ int smu_present(void) EXPORT_SYMBOL(smu_present); -int smu_init (void) +int __init smu_init (void) { struct device_node *np; u32 *data; @@ -845,16 +847,154 @@ int smu_queue_i2c(struct smu_i2c_cmd *cmd) return 0; } -struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size) +/* + * Handling of "partitions" + */ + +static int smu_read_datablock(u8 *dest, unsigned int addr, unsigned int len) +{ + DECLARE_COMPLETION(comp); + unsigned int chunk; + struct smu_cmd cmd; + int rc; + u8 params[8]; + + /* We currently use a chunk size of 0xe. We could check the + * SMU firmware version and use bigger sizes though + */ + chunk = 0xe; + + while (len) { + unsigned int clen = min(len, chunk); + + cmd.cmd = SMU_CMD_MISC_ee_COMMAND; + cmd.data_len = 7; + cmd.data_buf = params; + cmd.reply_len = chunk; + cmd.reply_buf = dest; + cmd.done = smu_done_complete; + cmd.misc = ∁ + params[0] = SMU_CMD_MISC_ee_GET_DATABLOCK_REC; + params[1] = 0x4; + *((u32 *)¶ms[2]) = addr; + params[6] = clen; + + rc = smu_queue_cmd(&cmd); + if (rc) + return rc; + wait_for_completion(&comp); + if (cmd.status != 0) + return rc; + if (cmd.reply_len != clen) { + printk(KERN_DEBUG "SMU: short read in " + "smu_read_datablock, got: %d, want: %d\n", + cmd.reply_len, clen); + return -EIO; + } + len -= clen; + addr += clen; + dest += clen; + } + return 0; +} + +static struct smu_sdbp_header *smu_create_sdb_partition(int id) +{ + DECLARE_COMPLETION(comp); + struct smu_simple_cmd cmd; + unsigned int addr, len, tlen; + struct smu_sdbp_header *hdr; + struct property *prop; + + /* First query the partition info */ + smu_queue_simple(&cmd, SMU_CMD_PARTITION_COMMAND, 2, + smu_done_complete, &comp, + SMU_CMD_PARTITION_LATEST, id); + wait_for_completion(&comp); + + /* Partition doesn't exist (or other error) */ + if (cmd.cmd.status != 0 || cmd.cmd.reply_len != 6) + return NULL; + + /* Fetch address and length from reply */ + addr = *((u16 *)cmd.buffer); + len = cmd.buffer[3] << 2; + /* Calucluate total length to allocate, including the 17 bytes + * for "sdb-partition-XX" that we append at the end of the buffer + */ + tlen = sizeof(struct property) + len + 18; + + prop = kcalloc(tlen, 1, GFP_KERNEL); + if (prop == NULL) + return NULL; + hdr = (struct smu_sdbp_header *)(prop + 1); + prop->name = ((char *)prop) + tlen - 18; + sprintf(prop->name, "sdb-partition-%02x", id); + prop->length = len; + prop->value = (unsigned char *)hdr; + prop->next = NULL; + + /* Read the datablock */ + if (smu_read_datablock((u8 *)hdr, addr, len)) { + printk(KERN_DEBUG "SMU: datablock read failed while reading " + "partition %02x !\n", id); + goto failure; + } + + /* Got it, check a few things and create the property */ + if (hdr->id != id) { + printk(KERN_DEBUG "SMU: Reading partition %02x and got " + "%02x !\n", id, hdr->id); + goto failure; + } + if (prom_add_property(smu->of_node, prop)) { + printk(KERN_DEBUG "SMU: Failed creating sdb-partition-%02x " + "property !\n", id); + goto failure; + } + + return hdr; + failure: + kfree(prop); + return NULL; +} + +/* Note: Only allowed to return error code in pointers (using ERR_PTR) + * when interruptible is 1 + */ +struct smu_sdbp_header *__smu_get_sdb_partition(int id, unsigned int *size, + int interruptible) { char pname[32]; + struct smu_sdbp_header *part; if (!smu) return NULL; sprintf(pname, "sdb-partition-%02x", id); - return (struct smu_sdbp_header *)get_property(smu->of_node, + + if (interruptible) { + int rc; + rc = down_interruptible(&smu_part_access); + if (rc) + return ERR_PTR(rc); + } else + down(&smu_part_access); + + part = (struct smu_sdbp_header *)get_property(smu->of_node, pname, size); + if (part == NULL) { + part = smu_create_sdb_partition(id); + if (part != NULL && size) + *size = part->len << 2; + } + up(&smu_part_access); + return part; +} + +struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size) +{ + return __smu_get_sdb_partition(id, size, 0); } EXPORT_SYMBOL(smu_get_sdb_partition); @@ -930,6 +1070,14 @@ static ssize_t smu_write(struct file *file, const char __user *buf, else if (hdr.cmdtype == SMU_CMDTYPE_WANTS_EVENTS) { pp->mode = smu_file_events; return 0; + } else if (hdr.cmdtype == SMU_CMDTYPE_GET_PARTITION) { + struct smu_sdbp_header *part; + part = __smu_get_sdb_partition(hdr.cmd, NULL, 1); + if (part == NULL) + return -EINVAL; + else if (IS_ERR(part)) + return PTR_ERR(part); + return 0; } else if (hdr.cmdtype != SMU_CMDTYPE_SMU) return -EINVAL; else if (pp->mode != smu_file_commands) diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c index 6fd57f15419..fb117b74809 100644 --- a/fs/proc/proc_devtree.c +++ b/fs/proc/proc_devtree.c @@ -48,6 +48,39 @@ static int property_read_proc(char *page, char **start, off_t off, * and "@10" to it. */ +/* + * Add a property to a node + */ +static struct proc_dir_entry * +__proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp) +{ + struct proc_dir_entry *ent; + + /* + * Unfortunately proc_register puts each new entry + * at the beginning of the list. So we rearrange them. + */ + ent = create_proc_read_entry(pp->name, + strncmp(pp->name, "security-", 9) + ? S_IRUGO : S_IRUSR, de, + property_read_proc, pp); + if (ent == NULL) + return NULL; + + if (!strncmp(pp->name, "security-", 9)) + ent->size = 0; /* don't leak number of password chars */ + else + ent->size = pp->length; + + return ent; +} + + +void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop) +{ + __proc_device_tree_add_prop(pde, prop); +} + /* * Process a node, adding entries for its children and its properties. */ @@ -57,11 +90,9 @@ void proc_device_tree_add_node(struct device_node *np, struct property *pp; struct proc_dir_entry *ent; struct device_node *child; - struct proc_dir_entry *list = NULL, **lastp; const char *p; set_node_proc_entry(np, de); - lastp = &list; for (child = NULL; (child = of_get_next_child(np, child));) { p = strrchr(child->full_name, '/'); if (!p) @@ -71,9 +102,6 @@ void proc_device_tree_add_node(struct device_node *np, ent = proc_mkdir(p, de); if (ent == 0) break; - *lastp = ent; - ent->next = NULL; - lastp = &ent->next; proc_device_tree_add_node(child, ent); } of_node_put(child); @@ -84,7 +112,7 @@ void proc_device_tree_add_node(struct device_node *np, * properties are quite unimportant for us though, thus we * simply "skip" them here, but we do have to check. */ - for (ent = list; ent != NULL; ent = ent->next) + for (ent = de->subdir; ent != NULL; ent = ent->next) if (!strcmp(ent->name, pp->name)) break; if (ent != NULL) { @@ -94,25 +122,10 @@ void proc_device_tree_add_node(struct device_node *np, continue; } - /* - * Unfortunately proc_register puts each new entry - * at the beginning of the list. So we rearrange them. - */ - ent = create_proc_read_entry(pp->name, - strncmp(pp->name, "security-", 9) - ? S_IRUGO : S_IRUSR, de, - property_read_proc, pp); + ent = __proc_device_tree_add_prop(de, pp); if (ent == 0) break; - if (!strncmp(pp->name, "security-", 9)) - ent->size = 0; /* don't leak number of password chars */ - else - ent->size = pp->length; - ent->next = NULL; - *lastp = ent; - lastp = &ent->next; } - de->subdir = list; } /* diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 7587bf5f38c..f999df1c5c9 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -203,7 +203,7 @@ extern int prom_n_addr_cells(struct device_node* np); extern int prom_n_size_cells(struct device_node* np); extern int prom_n_intr_cells(struct device_node* np); extern void prom_get_irq_senses(unsigned char *senses, int off, int max); -extern void prom_add_property(struct device_node* np, struct property* prop); +extern int prom_add_property(struct device_node* np, struct property* prop); #ifdef CONFIG_PPC32 /* diff --git a/include/asm-powerpc/smu.h b/include/asm-powerpc/smu.h index 959bad66023..76c29a9784d 100644 --- a/include/asm-powerpc/smu.h +++ b/include/asm-powerpc/smu.h @@ -20,16 +20,52 @@ /* * Partition info commands * - * I do not know what those are for at this point + * These commands are used to retreive the sdb-partition-XX datas from + * the SMU. The lenght is always 2. First byte is the subcommand code + * and second byte is the partition ID. + * + * The reply is 6 bytes: + * + * - 0..1 : partition address + * - 2 : a byte containing the partition ID + * - 3 : length (maybe other bits are rest of header ?) + * + * The data must then be obtained with calls to another command: + * SMU_CMD_MISC_ee_GET_DATABLOCK_REC (described below). */ #define SMU_CMD_PARTITION_COMMAND 0x3e +#define SMU_CMD_PARTITION_LATEST 0x01 +#define SMU_CMD_PARTITION_BASE 0x02 +#define SMU_CMD_PARTITION_UPDATE 0x03 /* * Fan control * - * This is a "mux" for fan control commands, first byte is the - * "sub" command. + * This is a "mux" for fan control commands. The command seem to + * act differently based on the number of arguments. With 1 byte + * of argument, this seem to be queries for fans status, setpoint, + * etc..., while with 0xe arguments, we will set the fans speeds. + * + * Queries (1 byte arg): + * --------------------- + * + * arg=0x01: read RPM fans status + * arg=0x02: read RPM fans setpoint + * arg=0x11: read PWM fans status + * arg=0x12: read PWM fans setpoint + * + * the "status" queries return the current speed while the "setpoint" ones + * return the programmed/target speed. It _seems_ that the result is a bit + * mask in the first byte of active/available fans, followed by 6 words (16 + * bits) containing the requested speed. + * + * Setpoint (14 bytes arg): + * ------------------------ + * + * first arg byte is 0 for RPM fans and 0x10 for PWM. Second arg byte is the + * mask of fans affected by the command. Followed by 6 words containing the + * setpoint value for selected fans in the mask (or 0 if mask value is 0) */ #define SMU_CMD_FAN_COMMAND 0x4a @@ -156,6 +192,14 @@ #define SMU_CMD_POWER_SHUTDOWN "SHUTDOWN" #define SMU_CMD_POWER_VOLTAGE_SLEW "VSLEW" +/* + * Read ADC sensors + * + * This command takes one byte of parameter: the sensor ID (or "reg" + * value in the device-tree) and returns a 16 bits value + */ +#define SMU_CMD_READ_ADC 0xd8 + /* Misc commands * * This command seem to be a grab bag of various things @@ -176,6 +220,25 @@ * Misc commands * * This command seem to be a grab bag of various things + * + * SMU_CMD_MISC_ee_GET_DATABLOCK_REC is used, among others, to + * transfer blocks of data from the SMU. So far, I've decrypted it's + * usage to retreive partition data. In order to do that, you have to + * break your transfer in "chunks" since that command cannot transfer + * more than a chunk at a time. The chunk size used by OF is 0xe bytes, + * but it seems that the darwin driver will let you do 0x1e bytes if + * your "PMU" version is >= 0x30. You can get the "PMU" version apparently + * either in the last 16 bits of property "smu-version-pmu" or as the 16 + * bytes at offset 1 of "smu-version-info" + * + * For each chunk, the command takes 7 bytes of arguments: + * byte 0: subcommand code (0x02) + * byte 1: 0x04 (always, I don't know what it means, maybe the address + * space to use or some other nicety. It's hard coded in OF) + * byte 2..5: SMU address of the chunk (big endian 32 bits) + * byte 6: size to transfer (up to max chunk size) + * + * The data is returned directly */ #define SMU_CMD_MISC_ee_COMMAND 0xee #define SMU_CMD_MISC_ee_GET_DATABLOCK_REC 0x02 @@ -353,21 +416,26 @@ struct smu_sdbp_header { __u8 flags; }; -/* - * 32 bits integers are usually encoded with 2x16 bits swapped, - * this demangles them + + /* + * demangle 16 and 32 bits integer in some SMU partitions + * (currently, afaik, this concerns only the FVT partition + * (0x12) */ -#define SMU_U32_MIX(x) ((((x) << 16) & 0xffff0000u) | (((x) >> 16) & 0xffffu)) +#define SMU_U16_MIX(x) le16_to_cpu(x); +#define SMU_U32_MIX(x) ((((x) & 0xff00ff00u) >> 8)|(((x) & 0x00ff00ffu) << 8)) + /* This is the definition of the SMU sdb-partition-0x12 table (called * CPU F/V/T operating points in Darwin). The definition for all those * SMU tables should be moved to some separate file */ -#define SMU_SDB_FVT_ID 0x12 +#define SMU_SDB_FVT_ID 0x12 struct smu_sdbp_fvt { __u32 sysclk; /* Base SysClk frequency in Hz for - * this operating point + * this operating point. Value need to + * be unmixed with SMU_U32_MIX() */ __u8 pad; __u8 maxtemp; /* Max temp. supported by this @@ -376,10 +444,73 @@ struct smu_sdbp_fvt { __u16 volts[3]; /* CPU core voltage for the 3 * PowerTune modes, a mode with - * 0V = not supported. + * 0V = not supported. Value need + * to be unmixed with SMU_U16_MIX() */ }; +/* This partition contains voltage & current sensor calibration + * informations + */ +#define SMU_SDB_CPUVCP_ID 0x21 + +struct smu_sdbp_cpuvcp { + __u16 volt_scale; /* u4.12 fixed point */ + __s16 volt_offset; /* s4.12 fixed point */ + __u16 curr_scale; /* u4.12 fixed point */ + __s16 curr_offset; /* s4.12 fixed point */ + __s32 power_quads[3]; /* s4.28 fixed point */ +}; + +/* This partition contains CPU thermal diode calibration + */ +#define SMU_SDB_CPUDIODE_ID 0x18 + +struct smu_sdbp_cpudiode { + __u16 m_value; /* u1.15 fixed point */ + __s16 b_value; /* s10.6 fixed point */ + +}; + +/* This partition contains Slots power calibration + */ +#define SMU_SDB_SLOTSPOW_ID 0x78 + +struct smu_sdbp_slotspow { + __u16 pow_scale; /* u4.12 fixed point */ + __s16 pow_offset; /* s4.12 fixed point */ +}; + +/* This partition contains machine specific version information about + * the sensor/control layout + */ +#define SMU_SDB_SENSORTREE_ID 0x25 + +struct smu_sdbp_sensortree { + u8 model_id; + u8 unknown[3]; +}; + +/* This partition contains CPU thermal control PID informations. So far + * only single CPU machines have been seen with an SMU, so we assume this + * carries only informations for those + */ +#define SMU_SDB_CPUPIDDATA_ID 0x17 + +struct smu_sdbp_cpupiddata { + u8 unknown1; + u8 target_temp_delta; + u8 unknown2; + u8 history_len; + s16 power_adj; + u16 max_power; + s32 gp,gr,gd; +}; + + +/* Other partitions without known structures */ +#define SMU_SDB_DEBUG_SWITCHES_ID 0x05 + #ifdef __KERNEL__ /* * This returns the pointer to an SMU "sdb" partition data or NULL @@ -423,8 +554,10 @@ struct smu_user_cmd_hdr __u32 cmdtype; #define SMU_CMDTYPE_SMU 0 /* SMU command */ #define SMU_CMDTYPE_WANTS_EVENTS 1 /* switch fd to events mode */ +#define SMU_CMDTYPE_GET_PARTITION 2 /* retreive an sdb partition */ __u8 cmd; /* SMU command byte */ + __u8 pad[3]; /* padding */ __u32 data_len; /* Lenght of data following */ }; diff --git a/include/asm-ppc/prom.h b/include/asm-ppc/prom.h index 75c0637acdc..3e39827ed56 100644 --- a/include/asm-ppc/prom.h +++ b/include/asm-ppc/prom.h @@ -93,7 +93,7 @@ extern int device_is_compatible(struct device_node *device, const char *); extern int machine_is_compatible(const char *compat); extern unsigned char *get_property(struct device_node *node, const char *name, int *lenp); -extern void prom_add_property(struct device_node* np, struct property* prop); +extern int prom_add_property(struct device_node* np, struct property* prop); extern void prom_get_irq_senses(unsigned char *, int, int); extern int prom_n_addr_cells(struct device_node* np); extern int prom_n_size_cells(struct device_node* np); diff --git a/include/asm-ppc64/prom.h b/include/asm-ppc64/prom.h index bdb47174ff0..76bb0266d67 100644 --- a/include/asm-ppc64/prom.h +++ b/include/asm-ppc64/prom.h @@ -213,6 +213,6 @@ extern int prom_n_addr_cells(struct device_node* np); extern int prom_n_size_cells(struct device_node* np); extern int prom_n_intr_cells(struct device_node* np); extern void prom_get_irq_senses(unsigned char *senses, int off, int max); -extern void prom_add_property(struct device_node* np, struct property* prop); +extern int prom_add_property(struct device_node* np, struct property* prop); #endif /* _PPC64_PROM_H */ diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 0563581e3a0..65ceeaa3065 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -139,15 +139,12 @@ extern void proc_tty_unregister_driver(struct tty_driver *driver); /* * proc_devtree.c */ +#ifdef CONFIG_PROC_DEVICETREE struct device_node; +struct property; extern void proc_device_tree_init(void); -#ifdef CONFIG_PROC_DEVICETREE extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *); -#else /* !CONFIG_PROC_DEVICETREE */ -static inline void proc_device_tree_add_node(struct device_node *np, struct proc_dir_entry *pde) -{ - return; -} +extern void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop); #endif /* CONFIG_PROC_DEVICETREE */ extern struct proc_dir_entry *proc_symlink(const char *, -- cgit v1.2.3 From c618cf19995ef00c7ab85a9734abe028de9c08d4 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 7 Nov 2005 14:32:28 +1100 Subject: [PATCH] ppc64: Update g5_defconfig for ARCH=powerpc This patch updates g5_defconfig for ARCH=powerpc in order to add the SMU support & thermal drivers to it, the pmac sound driver (works on some G5s) and replaces rivafb with nvidiafb which works better for the cards found in G5 based machines. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/configs/g5_defconfig | 261 ++++++++++++++++++++++++++++++-------- 1 file changed, 206 insertions(+), 55 deletions(-) diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig index 6323065fbf2..e76854f8c12 100644 --- a/arch/powerpc/configs/g5_defconfig +++ b/arch/powerpc/configs/g5_defconfig @@ -1,18 +1,32 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.14-rc4 -# Thu Oct 20 08:30:23 2005 +# Linux kernel version: 2.6.14 +# Mon Nov 7 13:37:59 2005 # +CONFIG_PPC64=y CONFIG_64BIT=y +CONFIG_PPC_MERGE=y CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_GENERIC_ISA_DMA=y +CONFIG_PPC=y CONFIG_EARLY_PRINTK=y CONFIG_COMPAT=y +CONFIG_SYSVIPC_COMPAT=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_ARCH_MAY_HAVE_PC_FDC=y -CONFIG_FORCE_MAX_ZONEORDER=13 + +# +# Processor support +# +CONFIG_POWER4_ONLY=y +CONFIG_POWER4=y +CONFIG_PPC_FPU=y +CONFIG_ALTIVEC=y +CONFIG_PPC_STD_MMU=y +CONFIG_SMP=y +CONFIG_NR_CPUS=2 # # Code maturity level options @@ -67,30 +81,60 @@ CONFIG_MODVERSIONS=y CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y CONFIG_STOP_MACHINE=y -CONFIG_SYSVIPC_COMPAT=y # # Platform support # -# CONFIG_PPC_ISERIES is not set CONFIG_PPC_MULTIPLATFORM=y +# CONFIG_PPC_ISERIES is not set +# CONFIG_EMBEDDED6xx is not set +# CONFIG_APUS is not set # CONFIG_PPC_PSERIES is not set -# CONFIG_PPC_BPA is not set CONFIG_PPC_PMAC=y +CONFIG_PPC_PMAC64=y # CONFIG_PPC_MAPLE is not set -CONFIG_PPC=y -CONFIG_PPC64=y +# CONFIG_PPC_CELL is not set CONFIG_PPC_OF=y -CONFIG_MPIC=y -CONFIG_ALTIVEC=y -CONFIG_KEXEC=y CONFIG_U3_DART=y -CONFIG_PPC_PMAC64=y -CONFIG_BOOTX_TEXT=y -CONFIG_POWER4_ONLY=y +CONFIG_MPIC=y +# CONFIG_PPC_RTAS is not set +# CONFIG_MMIO_NVRAM is not set +# CONFIG_PPC_MPC106 is not set +CONFIG_GENERIC_TBSYNC=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +# CONFIG_CPU_FREQ_DEBUG is not set +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_PMAC64=y +# CONFIG_WANT_EARLY_SERIAL is not set + +# +# Kernel options +# +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +# CONFIG_PREEMPT_BKL is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_FORCE_MAX_ZONEORDER=13 CONFIG_IOMMU_VMERGE=y -CONFIG_SMP=y -CONFIG_NR_CPUS=2 +# CONFIG_HOTPLUG_CPU is not set +CONFIG_KEXEC=y +CONFIG_IRQ_ALL_CPUS=y +# CONFIG_NUMA is not set CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_SELECT_MEMORY_MODEL=y @@ -100,28 +144,21 @@ CONFIG_FLATMEM_MANUAL=y CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set -# CONFIG_NUMA is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_PPC_64K_PAGES is not set # CONFIG_SCHED_SMT is not set -CONFIG_PREEMPT_NONE=y -# CONFIG_PREEMPT_VOLUNTARY is not set -# CONFIG_PREEMPT is not set -# CONFIG_PREEMPT_BKL is not set -# CONFIG_HZ_100 is not set -CONFIG_HZ_250=y -# CONFIG_HZ_1000 is not set -CONFIG_HZ=250 -CONFIG_GENERIC_HARDIRQS=y -CONFIG_SECCOMP=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -# CONFIG_HOTPLUG_CPU is not set CONFIG_PROC_DEVICETREE=y # CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +CONFIG_SECCOMP=y CONFIG_ISA_DMA_API=y # -# Bus Options +# Bus options # +CONFIG_GENERIC_ISA_DMA=y +# CONFIG_PPC_I8259 is not set +# CONFIG_PPC_INDIRECT_PCI is not set CONFIG_PCI=y CONFIG_PCI_DOMAINS=y CONFIG_PCI_LEGACY_PROC=y @@ -136,6 +173,7 @@ CONFIG_PCI_LEGACY_PROC=y # PCI Hotplug Support # # CONFIG_HOTPLUG_PCI is not set +CONFIG_KERNEL_START=0xc000000000000000 # # Networking @@ -276,6 +314,10 @@ CONFIG_LLC=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# # CONFIG_NET_SCHED is not set CONFIG_NET_CLS_ROUTE=y @@ -348,6 +390,11 @@ CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ATA_OVER_ETH is not set # @@ -449,6 +496,7 @@ CONFIG_SCSI_SPI_ATTRS=y # # SCSI low-level drivers # +# CONFIG_ISCSI_TCP is not set # CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set @@ -465,10 +513,12 @@ CONFIG_SCSI_SATA_SVW=y # CONFIG_SCSI_ATA_PIIX is not set # CONFIG_SCSI_SATA_MV is not set # CONFIG_SCSI_SATA_NV is not set -# CONFIG_SCSI_SATA_PROMISE is not set +# CONFIG_SCSI_PDC_ADMA is not set # CONFIG_SCSI_SATA_QSTOR is not set +# CONFIG_SCSI_SATA_PROMISE is not set # CONFIG_SCSI_SATA_SX4 is not set # CONFIG_SCSI_SATA_SIL is not set +# CONFIG_SCSI_SATA_SIL24 is not set # CONFIG_SCSI_SATA_SIS is not set # CONFIG_SCSI_SATA_ULI is not set # CONFIG_SCSI_SATA_VIA is not set @@ -567,6 +617,9 @@ CONFIG_IEEE1394_RAWIO=y CONFIG_ADB_PMU=y CONFIG_PMAC_SMU=y CONFIG_THERM_PM72=y +CONFIG_WINDFARM=y +CONFIG_WINDFARM_PM81=y +CONFIG_WINDFARM_PM91=y # # Network device support @@ -603,6 +656,7 @@ CONFIG_SUNGEM=y # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set # CONFIG_NET_PCI is not set +# CONFIG_FEC_8XX is not set # # Ethernet (1000 Mbit) @@ -768,6 +822,7 @@ CONFIG_MAX_RAW_DEVS=256 # TPM devices # # CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set # # I2C support @@ -820,6 +875,7 @@ CONFIG_I2C_PMAC_SMU=y # CONFIG_SENSORS_PCF8591 is not set # CONFIG_SENSORS_RTC8564 is not set # CONFIG_SENSORS_MAX6875 is not set +# CONFIG_RTC_X1205_I2C is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set @@ -876,10 +932,9 @@ CONFIG_FB_OF=y # CONFIG_FB_ASILIANT is not set # CONFIG_FB_IMSTT is not set # CONFIG_FB_VGA16 is not set -# CONFIG_FB_NVIDIA is not set -CONFIG_FB_RIVA=y -# CONFIG_FB_RIVA_I2C is not set -# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_NVIDIA=y +CONFIG_FB_NVIDIA_I2C=y +# CONFIG_FB_RIVA is not set # CONFIG_FB_MATROX is not set # CONFIG_FB_RADEON_OLD is not set CONFIG_FB_RADEON=y @@ -924,7 +979,96 @@ CONFIG_LCD_DEVICE=y # # Sound # -# CONFIG_SOUND is not set +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +# CONFIG_SND_SEQ_DUMMY is not set +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_SEQUENCER_OSS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +CONFIG_SND_GENERIC_DRIVER=y + +# +# Generic devices +# +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_VIRMIDI is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set + +# +# PCI devices +# +# CONFIG_SND_ALI5451 is not set +# CONFIG_SND_ATIIXP is not set +# CONFIG_SND_ATIIXP_MODEM is not set +# CONFIG_SND_AU8810 is not set +# CONFIG_SND_AU8820 is not set +# CONFIG_SND_AU8830 is not set +# CONFIG_SND_AZT3328 is not set +# CONFIG_SND_BT87X is not set +# CONFIG_SND_CS46XX is not set +# CONFIG_SND_CS4281 is not set +# CONFIG_SND_EMU10K1 is not set +# CONFIG_SND_EMU10K1X is not set +# CONFIG_SND_CA0106 is not set +# CONFIG_SND_KORG1212 is not set +# CONFIG_SND_MIXART is not set +# CONFIG_SND_NM256 is not set +# CONFIG_SND_RME32 is not set +# CONFIG_SND_RME96 is not set +# CONFIG_SND_RME9652 is not set +# CONFIG_SND_HDSP is not set +# CONFIG_SND_HDSPM is not set +# CONFIG_SND_TRIDENT is not set +# CONFIG_SND_YMFPCI is not set +# CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALS4000 is not set +# CONFIG_SND_CMIPCI is not set +# CONFIG_SND_ENS1370 is not set +# CONFIG_SND_ENS1371 is not set +# CONFIG_SND_ES1938 is not set +# CONFIG_SND_ES1968 is not set +# CONFIG_SND_MAESTRO3 is not set +# CONFIG_SND_FM801 is not set +# CONFIG_SND_ICE1712 is not set +# CONFIG_SND_ICE1724 is not set +# CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_INTEL8X0M is not set +# CONFIG_SND_SONICVIBES is not set +# CONFIG_SND_VIA82XX is not set +# CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VX222 is not set +# CONFIG_SND_HDA_INTEL is not set + +# +# ALSA PowerMac devices +# +CONFIG_SND_POWERMAC=m +CONFIG_SND_POWERMAC_AUTO_DRC=y + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m +# CONFIG_SND_USB_USX2Y is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set # # USB support @@ -958,12 +1102,16 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y # # USB Device Class drivers # -# CONFIG_USB_BLUETOOTH_TTY is not set +# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set CONFIG_USB_ACM=m CONFIG_USB_PRINTER=y # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information # CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set @@ -1074,6 +1222,7 @@ CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y CONFIG_USB_SERIAL_KLSI=m CONFIG_USB_SERIAL_KOBIL_SCT=m CONFIG_USB_SERIAL_MCT_U232=m +# CONFIG_USB_SERIAL_NOKIA_DKU2 is not set CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_SERIAL_HP4X is not set CONFIG_USB_SERIAL_SAFE=m @@ -1310,6 +1459,20 @@ CONFIG_NLS_ISO8859_15=y # CONFIG_NLS_KOI8_U is not set CONFIG_NLS_UTF8=y +# +# Library routines +# +CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m + # # Profiling support # @@ -1331,12 +1494,14 @@ CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_INFO is not set CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +# CONFIG_RCU_TORTURE_TEST is not set # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_KPROBES is not set # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUGGER is not set -# CONFIG_PPCDBG is not set CONFIG_IRQSTACKS=y +CONFIG_BOOTX_TEXT=y # # Security options @@ -1376,17 +1541,3 @@ CONFIG_CRYPTO_TEST=m # # Hardware crypto devices # - -# -# Library routines -# -CONFIG_CRC_CCITT=m -# CONFIG_CRC16 is not set -CONFIG_CRC32=y -CONFIG_LIBCRC32C=m -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=m -CONFIG_TEXTSEARCH=y -CONFIG_TEXTSEARCH_KMP=m -CONFIG_TEXTSEARCH_BM=m -CONFIG_TEXTSEARCH_FSM=m -- cgit v1.2.3 From 7d49697ef92bd2cf84ab53bd4cea82fefb197fb9 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 7 Nov 2005 14:36:21 +1100 Subject: [PATCH] ppc64: More U3 device-tree fixes Some more U3 revisions have the missing "interrupts" property in U3, this adds them to the fixup code in prom_init.c Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom_init.c | 2 +- arch/ppc64/kernel/prom_init.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index c758b6624d7..0d91961f943 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -1872,7 +1872,7 @@ static void __init fixup_device_tree(void) if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) == PROM_ERROR) return; - if (u3_rev != 0x35 && u3_rev != 0x37) + if (u3_rev < 0x35 || u3_rev > 0x39) return; /* does it need fixup ? */ if (prom_getproplen(i2c, "interrupts") > 0) diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c index e72b3f9061f..e4c880dab99 100644 --- a/arch/ppc64/kernel/prom_init.c +++ b/arch/ppc64/kernel/prom_init.c @@ -1824,7 +1824,7 @@ static void __init fixup_device_tree(void) if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) == PROM_ERROR) return; - if (u3_rev != 0x35 && u3_rev != 0x37) + if (u3_rev < 0x35 || u3_rev > 0x39) return; /* does it need fixup ? */ if (prom_getproplen(i2c, "interrupts") > 0) -- cgit v1.2.3 From 75722d3992f57375c0cc029dcceb2334a45ceff1 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 7 Nov 2005 16:08:17 +1100 Subject: [PATCH] ppc64: Thermal control for SMU based machines This adds a new thermal control framework for PowerMac, along with the implementation for PowerMac8,1, PowerMac8,2 (iMac G5 rev 1 and 2), and PowerMac9,1 (latest single CPU desktop). In the future, I expect to move the older G5 thermal control to the new framework as well. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- drivers/macintosh/Kconfig | 19 + drivers/macintosh/Makefile | 9 + drivers/macintosh/smu.c | 2 + drivers/macintosh/windfarm.h | 131 +++++ drivers/macintosh/windfarm_core.c | 426 ++++++++++++++ drivers/macintosh/windfarm_cpufreq_clamp.c | 105 ++++ drivers/macintosh/windfarm_lm75_sensor.c | 263 +++++++++ drivers/macintosh/windfarm_pid.c | 145 +++++ drivers/macintosh/windfarm_pid.h | 84 +++ drivers/macintosh/windfarm_pm81.c | 879 +++++++++++++++++++++++++++++ drivers/macintosh/windfarm_pm91.c | 814 ++++++++++++++++++++++++++ drivers/macintosh/windfarm_smu_controls.c | 282 +++++++++ drivers/macintosh/windfarm_smu_sensors.c | 479 ++++++++++++++++ 13 files changed, 3638 insertions(+) create mode 100644 drivers/macintosh/windfarm.h create mode 100644 drivers/macintosh/windfarm_core.c create mode 100644 drivers/macintosh/windfarm_cpufreq_clamp.c create mode 100644 drivers/macintosh/windfarm_lm75_sensor.c create mode 100644 drivers/macintosh/windfarm_pid.c create mode 100644 drivers/macintosh/windfarm_pid.h create mode 100644 drivers/macintosh/windfarm_pm81.c create mode 100644 drivers/macintosh/windfarm_pm91.c create mode 100644 drivers/macintosh/windfarm_smu_controls.c create mode 100644 drivers/macintosh/windfarm_smu_sensors.c diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig index bc3e096d84f..a0ea44c3e8b 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig @@ -169,6 +169,25 @@ config THERM_PM72 This driver provides thermostat and fan control for the desktop G5 machines. +config WINDFARM + tristate "New PowerMac thermal control infrastructure" + +config WINDFARM_PM81 + tristate "Support for thermal management on iMac G5" + depends on WINDFARM && I2C && CPU_FREQ_PMAC64 && PMAC_SMU + select I2C_PMAC_SMU + help + This driver provides thermal control for the iMacG5 + +config WINDFARM_PM91 + tristate "Support for thermal management on PowerMac9,1" + depends on WINDFARM && I2C && CPU_FREQ_PMAC64 && PMAC_SMU + select I2C_PMAC_SMU + help + This driver provides thermal control for the PowerMac9,1 + which is the recent (SMU based) single CPU desktop G5 + + config ANSLCD tristate "Support for ANS LCD display" depends on ADB_CUDA && PPC_PMAC diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile index 236291bd48a..f4657aa81fb 100644 --- a/drivers/macintosh/Makefile +++ b/drivers/macintosh/Makefile @@ -26,3 +26,12 @@ obj-$(CONFIG_ADB_MACIO) += macio-adb.o obj-$(CONFIG_THERM_PM72) += therm_pm72.o obj-$(CONFIG_THERM_WINDTUNNEL) += therm_windtunnel.o obj-$(CONFIG_THERM_ADT746X) += therm_adt746x.o +obj-$(CONFIG_WINDFARM) += windfarm_core.o +obj-$(CONFIG_WINDFARM_PM81) += windfarm_smu_controls.o \ + windfarm_smu_sensors.o \ + windfarm_lm75_sensor.o windfarm_pid.o \ + windfarm_cpufreq_clamp.o windfarm_pm81.o +obj-$(CONFIG_WINDFARM_PM91) += windfarm_smu_controls.o \ + windfarm_smu_sensors.o \ + windfarm_lm75_sensor.o windfarm_pid.o \ + windfarm_cpufreq_clamp.o windfarm_pm91.o diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index a83c4acf571..e8378274d71 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -590,6 +590,8 @@ static void smu_expose_childs(void *unused) sprintf(name, "smu-i2c-%02x", *reg); of_platform_device_create(np, name, &smu->of_dev->dev); } + if (device_is_compatible(np, "smu-sensors")) + of_platform_device_create(np, "smu-sensors", &smu->of_dev->dev); } } diff --git a/drivers/macintosh/windfarm.h b/drivers/macintosh/windfarm.h new file mode 100644 index 00000000000..3f0cb0312ea --- /dev/null +++ b/drivers/macintosh/windfarm.h @@ -0,0 +1,131 @@ +/* + * Windfarm PowerMac thermal control. + * + * (c) Copyright 2005 Benjamin Herrenschmidt, IBM Corp. + * + * + * Released under the term of the GNU GPL v2. + */ + +#ifndef __WINDFARM_H__ +#define __WINDFARM_H__ + +#include +#include +#include +#include + +/* Display a 16.16 fixed point value */ +#define FIX32TOPRINT(f) ((f) >> 16),((((f) & 0xffff) * 1000) >> 16) + +/* + * Control objects + */ + +struct wf_control; + +struct wf_control_ops { + int (*set_value)(struct wf_control *ct, s32 val); + int (*get_value)(struct wf_control *ct, s32 *val); + s32 (*get_min)(struct wf_control *ct); + s32 (*get_max)(struct wf_control *ct); + void (*release)(struct wf_control *ct); + struct module *owner; +}; + +struct wf_control { + struct list_head link; + struct wf_control_ops *ops; + char *name; + int type; + struct kref ref; +}; + +#define WF_CONTROL_TYPE_GENERIC 0 +#define WF_CONTROL_RPM_FAN 1 +#define WF_CONTROL_PWM_FAN 2 + + +/* Note about lifetime rules: wf_register_control() will initialize + * the kref and wf_unregister_control will decrement it, thus the + * object creating/disposing a given control shouldn't assume it + * still exists after wf_unregister_control has been called. + * wf_find_control will inc the refcount for you + */ +extern int wf_register_control(struct wf_control *ct); +extern void wf_unregister_control(struct wf_control *ct); +extern struct wf_control * wf_find_control(const char *name); +extern int wf_get_control(struct wf_control *ct); +extern void wf_put_control(struct wf_control *ct); + +static inline int wf_control_set_max(struct wf_control *ct) +{ + s32 vmax = ct->ops->get_max(ct); + return ct->ops->set_value(ct, vmax); +} + +static inline int wf_control_set_min(struct wf_control *ct) +{ + s32 vmin = ct->ops->get_min(ct); + return ct->ops->set_value(ct, vmin); +} + +/* + * Sensor objects + */ + +struct wf_sensor; + +struct wf_sensor_ops { + int (*get_value)(struct wf_sensor *sr, s32 *val); + void (*release)(struct wf_sensor *sr); + struct module *owner; +}; + +struct wf_sensor { + struct list_head link; + struct wf_sensor_ops *ops; + char *name; + struct kref ref; +}; + +/* Same lifetime rules as controls */ +extern int wf_register_sensor(struct wf_sensor *sr); +extern void wf_unregister_sensor(struct wf_sensor *sr); +extern struct wf_sensor * wf_find_sensor(const char *name); +extern int wf_get_sensor(struct wf_sensor *sr); +extern void wf_put_sensor(struct wf_sensor *sr); + +/* For use by clients. Note that we are a bit racy here since + * notifier_block doesn't have a module owner field. I may fix + * it one day ... + * + * LOCKING NOTE ! + * + * All "events" except WF_EVENT_TICK are called with an internal mutex + * held which will deadlock if you call basically any core routine. + * So don't ! Just take note of the event and do your actual operations + * from the ticker. + * + */ +extern int wf_register_client(struct notifier_block *nb); +extern int wf_unregister_client(struct notifier_block *nb); + +/* Overtemp conditions. Those are refcounted */ +extern void wf_set_overtemp(void); +extern void wf_clear_overtemp(void); +extern int wf_is_overtemp(void); + +#define WF_EVENT_NEW_CONTROL 0 /* param is wf_control * */ +#define WF_EVENT_NEW_SENSOR 1 /* param is wf_sensor * */ +#define WF_EVENT_OVERTEMP 2 /* no param */ +#define WF_EVENT_NORMALTEMP 3 /* overtemp condition cleared */ +#define WF_EVENT_TICK 4 /* 1 second tick */ + +/* Note: If that driver gets more broad use, we could replace the + * simplistic overtemp bits with "environmental conditions". That + * could then be used to also notify of things like fan failure, + * case open, battery conditions, ... + */ + +#endif /* __WINDFARM_H__ */ diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c new file mode 100644 index 00000000000..6c2a471ea6c --- /dev/null +++ b/drivers/macintosh/windfarm_core.c @@ -0,0 +1,426 @@ +/* + * Windfarm PowerMac thermal control. Core + * + * (c) Copyright 2005 Benjamin Herrenschmidt, IBM Corp. + * + * + * Released under the term of the GNU GPL v2. + * + * This core code tracks the list of sensors & controls, register + * clients, and holds the kernel thread used for control. + * + * TODO: + * + * Add some information about sensor/control type and data format to + * sensors/controls, and have the sysfs attribute stuff be moved + * generically here instead of hard coded in the platform specific + * driver as it us currently + * + * This however requires solving some annoying lifetime issues with + * sysfs which doesn't seem to have lifetime rules for struct attribute, + * I may have to create full features kobjects for every sensor/control + * instead which is a bit of an overkill imho + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "windfarm.h" + +#define VERSION "0.2" + +#undef DEBUG + +#ifdef DEBUG +#define DBG(args...) printk(args) +#else +#define DBG(args...) do { } while(0) +#endif + +static LIST_HEAD(wf_controls); +static LIST_HEAD(wf_sensors); +static DECLARE_MUTEX(wf_lock); +static struct notifier_block *wf_client_list; +static int wf_client_count; +static unsigned int wf_overtemp; +static unsigned int wf_overtemp_counter; +struct task_struct *wf_thread; + +/* + * Utilities & tick thread + */ + +static inline void wf_notify(int event, void *param) +{ + notifier_call_chain(&wf_client_list, event, param); +} + +int wf_critical_overtemp(void) +{ + static char * critical_overtemp_path = "/sbin/critical_overtemp"; + char *argv[] = { critical_overtemp_path, NULL }; + static char *envp[] = { "HOME=/", + "TERM=linux", + "PATH=/sbin:/usr/sbin:/bin:/usr/bin", + NULL }; + + return call_usermodehelper(critical_overtemp_path, argv, envp, 0); +} +EXPORT_SYMBOL_GPL(wf_critical_overtemp); + +static int wf_thread_func(void *data) +{ + unsigned long next, delay; + + next = jiffies; + + DBG("wf: thread started\n"); + + while(!kthread_should_stop()) { + try_to_freeze(); + + if (time_after_eq(jiffies, next)) { + wf_notify(WF_EVENT_TICK, NULL); + if (wf_overtemp) { + wf_overtemp_counter++; + /* 10 seconds overtemp, notify userland */ + if (wf_overtemp_counter > 10) + wf_critical_overtemp(); + /* 30 seconds, shutdown */ + if (wf_overtemp_counter > 30) { + printk(KERN_ERR "windfarm: Overtemp " + "for more than 30" + " seconds, shutting down\n"); + machine_power_off(); + } + } + next += HZ; + } + + delay = next - jiffies; + if (delay <= HZ) + schedule_timeout_interruptible(delay); + + /* there should be no signal, but oh well */ + if (signal_pending(current)) { + printk(KERN_WARNING "windfarm: thread got sigl !\n"); + break; + } + } + + DBG("wf: thread stopped\n"); + + return 0; +} + +static void wf_start_thread(void) +{ + wf_thread = kthread_run(wf_thread_func, NULL, "kwindfarm"); + if (IS_ERR(wf_thread)) { + printk(KERN_ERR "windfarm: failed to create thread,err %ld\n", + PTR_ERR(wf_thread)); + wf_thread = NULL; + } +} + + +static void wf_stop_thread(void) +{ + if (wf_thread) + kthread_stop(wf_thread); + wf_thread = NULL; +} + +/* + * Controls + */ + +static void wf_control_release(struct kref *kref) +{ + struct wf_control *ct = container_of(kref, struct wf_control, ref); + + DBG("wf: Deleting control %s\n", ct->name); + + if (ct->ops && ct->ops->release) + ct->ops->release(ct); + else + kfree(ct); +} + +int wf_register_control(struct wf_control *new_ct) +{ + struct wf_control *ct; + + down(&wf_lock); + list_for_each_entry(ct, &wf_controls, link) { + if (!strcmp(ct->name, new_ct->name)) { + printk(KERN_WARNING "windfarm: trying to register" + " duplicate control %s\n", ct->name); + up(&wf_lock); + return -EEXIST; + } + } + kref_init(&new_ct->ref); + list_add(&new_ct->link, &wf_controls); + + DBG("wf: Registered control %s\n", new_ct->name); + + wf_notify(WF_EVENT_NEW_CONTROL, new_ct); + up(&wf_lock); + + return 0; +} +EXPORT_SYMBOL_GPL(wf_register_control); + +void wf_unregister_control(struct wf_control *ct) +{ + down(&wf_lock); + list_del(&ct->link); + up(&wf_lock); + + DBG("wf: Unregistered control %s\n", ct->name); + + kref_put(&ct->ref, wf_control_release); +} +EXPORT_SYMBOL_GPL(wf_unregister_control); + +struct wf_control * wf_find_control(const char *name) +{ + struct wf_control *ct; + + down(&wf_lock); + list_for_each_entry(ct, &wf_controls, link) { + if (!strcmp(ct->name, name)) { + if (wf_get_control(ct)) + ct = NULL; + up(&wf_lock); + return ct; + } + } + up(&wf_lock); + return NULL; +} +EXPORT_SYMBOL_GPL(wf_find_control); + +int wf_get_control(struct wf_control *ct) +{ + if (!try_module_get(ct->ops->owner)) + return -ENODEV; + kref_get(&ct->ref); + return 0; +} +EXPORT_SYMBOL_GPL(wf_get_control); + +void wf_put_control(struct wf_control *ct) +{ + struct module *mod = ct->ops->owner; + kref_put(&ct->ref, wf_control_release); + module_put(mod); +} +EXPORT_SYMBOL_GPL(wf_put_control); + + +/* + * Sensors + */ + + +static void wf_sensor_release(struct kref *kref) +{ + struct wf_sensor *sr = container_of(kref, struct wf_sensor, ref); + + DBG("wf: Deleting sensor %s\n", sr->name); + + if (sr->ops && sr->ops->release) + sr->ops->release(sr); + else + kfree(sr); +} + +int wf_register_sensor(struct wf_sensor *new_sr) +{ + struct wf_sensor *sr; + + down(&wf_lock); + list_for_each_entry(sr, &wf_sensors, link) { + if (!strcmp(sr->name, new_sr->name)) { + printk(KERN_WARNING "windfarm: trying to register" + " duplicate sensor %s\n", sr->name); + up(&wf_lock); + return -EEXIST; + } + } + kref_init(&new_sr->ref); + list_add(&new_sr->link, &wf_sensors); + + DBG("wf: Registered sensor %s\n", new_sr->name); + + wf_notify(WF_EVENT_NEW_SENSOR, new_sr); + up(&wf_lock); + + return 0; +} +EXPORT_SYMBOL_GPL(wf_register_sensor); + +void wf_unregister_sensor(struct wf_sensor *sr) +{ + down(&wf_lock); + list_del(&sr->link); + up(&wf_lock); + + DBG("wf: Unregistered sensor %s\n", sr->name); + + wf_put_sensor(sr); +} +EXPORT_SYMBOL_GPL(wf_unregister_sensor); + +struct wf_sensor * wf_find_sensor(const char *name) +{ + struct wf_sensor *sr; + + down(&wf_lock); + list_for_each_entry(sr, &wf_sensors, link) { + if (!strcmp(sr->name, name)) { + if (wf_get_sensor(sr)) + sr = NULL; + up(&wf_lock); + return sr; + } + } + up(&wf_lock); + return NULL; +} +EXPORT_SYMBOL_GPL(wf_find_sensor); + +int wf_get_sensor(struct wf_sensor *sr) +{ + if (!try_module_get(sr->ops->owner)) + return -ENODEV; + kref_get(&sr->ref); + return 0; +} +EXPORT_SYMBOL_GPL(wf_get_sensor); + +void wf_put_sensor(struct wf_sensor *sr) +{ + struct module *mod = sr->ops->owner; + kref_put(&sr->ref, wf_sensor_release); + module_put(mod); +} +EXPORT_SYMBOL_GPL(wf_put_sensor); + + +/* + * Client & notification + */ + +int wf_register_client(struct notifier_block *nb) +{ + int rc; + struct wf_control *ct; + struct wf_sensor *sr; + + down(&wf_lock); + rc = notifier_chain_register(&wf_client_list, nb); + if (rc != 0) + goto bail; + wf_client_count++; + list_for_each_entry(ct, &wf_controls, link) + wf_notify(WF_EVENT_NEW_CONTROL, ct); + list_for_each_entry(sr, &wf_sensors, link) + wf_notify(WF_EVENT_NEW_SENSOR, sr); + if (wf_client_count == 1) + wf_start_thread(); + bail: + up(&wf_lock); + return rc; +} +EXPORT_SYMBOL_GPL(wf_register_client); + +int wf_unregister_client(struct notifier_block *nb) +{ + down(&wf_lock); + notifier_chain_unregister(&wf_client_list, nb); + wf_client_count++; + if (wf_client_count == 0) + wf_stop_thread(); + up(&wf_lock); + + return 0; +} +EXPORT_SYMBOL_GPL(wf_unregister_client); + +void wf_set_overtemp(void) +{ + down(&wf_lock); + wf_overtemp++; + if (wf_overtemp == 1) { + printk(KERN_WARNING "windfarm: Overtemp condition detected !\n"); + wf_overtemp_counter = 0; + wf_notify(WF_EVENT_OVERTEMP, NULL); + } + up(&wf_lock); +} +EXPORT_SYMBOL_GPL(wf_set_overtemp); + +void wf_clear_overtemp(void) +{ + down(&wf_lock); + WARN_ON(wf_overtemp == 0); + if (wf_overtemp == 0) { + up(&wf_lock); + return; + } + wf_overtemp--; + if (wf_overtemp == 0) { + printk(KERN_WARNING "windfarm: Overtemp condition cleared !\n"); + wf_notify(WF_EVENT_NORMALTEMP, NULL); + } + up(&wf_lock); +} +EXPORT_SYMBOL_GPL(wf_clear_overtemp); + +int wf_is_overtemp(void) +{ + return (wf_overtemp != 0); +} +EXPORT_SYMBOL_GPL(wf_is_overtemp); + +static struct platform_device wf_platform_device = { + .name = "windfarm", +}; + +static int __init windfarm_core_init(void) +{ + DBG("wf: core loaded\n"); + + platform_device_register(&wf_platform_device); + return 0; +} + +static void __exit windfarm_core_exit(void) +{ + BUG_ON(wf_client_count != 0); + + DBG("wf: core unloaded\n"); + + platform_device_unregister(&wf_platform_device); +} + + +module_init(windfarm_core_init); +module_exit(windfarm_core_exit); + +MODULE_AUTHOR("Benjamin Herrenschmidt "); +MODULE_DESCRIPTION("Core component of PowerMac thermal control"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/macintosh/windfarm_cpufreq_clamp.c b/drivers/macintosh/windfarm_cpufreq_clamp.c new file mode 100644 index 00000000000..607dbaca69c --- /dev/null +++ b/drivers/macintosh/windfarm_cpufreq_clamp.c @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "windfarm.h" + +#define VERSION "0.3" + +static int clamped; +static struct wf_control *clamp_control; + +static int clamp_notifier_call(struct notifier_block *self, + unsigned long event, void *data) +{ + struct cpufreq_policy *p = data; + unsigned long max_freq; + + if (event != CPUFREQ_ADJUST) + return 0; + + max_freq = clamped ? (p->cpuinfo.min_freq) : (p->cpuinfo.max_freq); + cpufreq_verify_within_limits(p, 0, max_freq); + + return 0; +} + +static struct notifier_block clamp_notifier = { + .notifier_call = clamp_notifier_call, +}; + +static int clamp_set(struct wf_control *ct, s32 value) +{ + if (value) + printk(KERN_INFO "windfarm: Clamping CPU frequency to " + "minimum !\n"); + else + printk(KERN_INFO "windfarm: CPU frequency unclamped !\n"); + clamped = value; + cpufreq_update_policy(0); + return 0; +} + +static int clamp_get(struct wf_control *ct, s32 *value) +{ + *value = clamped; + return 0; +} + +static s32 clamp_min(struct wf_control *ct) +{ + return 0; +} + +static s32 clamp_max(struct wf_control *ct) +{ + return 1; +} + +static struct wf_control_ops clamp_ops = { + .set_value = clamp_set, + .get_value = clamp_get, + .get_min = clamp_min, + .get_max = clamp_max, + .owner = THIS_MODULE, +}; + +static int __init wf_cpufreq_clamp_init(void) +{ + struct wf_control *clamp; + + clamp = kmalloc(sizeof(struct wf_control), GFP_KERNEL); + if (clamp == NULL) + return -ENOMEM; + cpufreq_register_notifier(&clamp_notifier, CPUFREQ_POLICY_NOTIFIER); + clamp->ops = &clamp_ops; + clamp->name = "cpufreq-clamp"; + if (wf_register_control(clamp)) + goto fail; + clamp_control = clamp; + return 0; + fail: + kfree(clamp); + return -ENODEV; +} + +static void __exit wf_cpufreq_clamp_exit(void) +{ + if (clamp_control) + wf_unregister_control(clamp_control); +} + + +module_init(wf_cpufreq_clamp_init); +module_exit(wf_cpufreq_clamp_exit); + +MODULE_AUTHOR("Benjamin Herrenschmidt "); +MODULE_DESCRIPTION("CPU frequency clamp for PowerMacs thermal control"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c new file mode 100644 index 00000000000..a0a41ad0f2b --- /dev/null +++ b/drivers/macintosh/windfarm_lm75_sensor.c @@ -0,0 +1,263 @@ +/* + * Windfarm PowerMac thermal control. LM75 sensor + * + * (c) Copyright 2005 Benjamin Herrenschmidt, IBM Corp. + * + * + * Released under the term of the GNU GPL v2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "windfarm.h" + +#define VERSION "0.1" + +#undef DEBUG + +#ifdef DEBUG +#define DBG(args...) printk(args) +#else +#define DBG(args...) do { } while(0) +#endif + +struct wf_lm75_sensor { + int ds1775 : 1; + int inited : 1; + struct i2c_client i2c; + struct wf_sensor sens; +}; +#define wf_to_lm75(c) container_of(c, struct wf_lm75_sensor, sens) +#define i2c_to_lm75(c) container_of(c, struct wf_lm75_sensor, i2c) + +static int wf_lm75_attach(struct i2c_adapter *adapter); +static int wf_lm75_detach(struct i2c_client *client); + +static struct i2c_driver wf_lm75_driver = { + .owner = THIS_MODULE, + .name = "wf_lm75", + .flags = I2C_DF_NOTIFY, + .attach_adapter = wf_lm75_attach, + .detach_client = wf_lm75_detach, +}; + +static int wf_lm75_get(struct wf_sensor *sr, s32 *value) +{ + struct wf_lm75_sensor *lm = wf_to_lm75(sr); + s32 data; + + if (lm->i2c.adapter == NULL) + return -ENODEV; + + /* Init chip if necessary */ + if (!lm->inited) { + u8 cfg_new, cfg = (u8)i2c_smbus_read_byte_data(&lm->i2c, 1); + + DBG("wf_lm75: Initializing %s, cfg was: %02x\n", + sr->name, cfg); + + /* clear shutdown bit, keep other settings as left by + * the firmware for now + */ + cfg_new = cfg & ~0x01; + i2c_smbus_write_byte_data(&lm->i2c, 1, cfg_new); + lm->inited = 1; + + /* If we just powered it up, let's wait 200 ms */ + msleep(200); + } + + /* Read temperature register */ + data = (s32)le16_to_cpu(i2c_smbus_read_word_data(&lm->i2c, 0)); + data <<= 8; + *value = data; + + return 0; +} + +static void wf_lm75_release(struct wf_sensor *sr) +{ + struct wf_lm75_sensor *lm = wf_to_lm75(sr); + + /* check if client is registered and detach from i2c */ + if (lm->i2c.adapter) { + i2c_detach_client(&lm->i2c); + lm->i2c.adapter = NULL; + } + + kfree(lm); +} + +static struct wf_sensor_ops wf_lm75_ops = { + .get_value = wf_lm75_get, + .release = wf_lm75_release, + .owner = THIS_MODULE, +}; + +static struct wf_lm75_sensor *wf_lm75_create(struct i2c_adapter *adapter, + u8 addr, int ds1775, + const char *loc) +{ + struct wf_lm75_sensor *lm; + + DBG("wf_lm75: creating %s device at address 0x%02x\n", + ds1775 ? "ds1775" : "lm75", addr); + + lm = kmalloc(sizeof(struct wf_lm75_sensor), GFP_KERNEL); + if (lm == NULL) + return NULL; + memset(lm, 0, sizeof(struct wf_lm75_sensor)); + + /* Usual rant about sensor names not beeing very consistent in + * the device-tree, oh well ... + * Add more entries below as you deal with more setups + */ + if (!strcmp(loc, "Hard drive") || !strcmp(loc, "DRIVE BAY")) + lm->sens.name = "hd-temp"; + else + goto fail; + + lm->inited = 0; + lm->sens.ops = &wf_lm75_ops; + lm->ds1775 = ds1775; + lm->i2c.addr = (addr >> 1) & 0x7f; + lm->i2c.adapter = adapter; + lm->i2c.driver = &wf_lm75_driver; + strncpy(lm->i2c.name, lm->sens.name, I2C_NAME_SIZE-1); + + if (i2c_attach_client(&lm->i2c)) { + printk(KERN_ERR "windfarm: failed to attach %s %s to i2c\n", + ds1775 ? "ds1775" : "lm75", lm->i2c.name); + goto fail; + } + + if (wf_register_sensor(&lm->sens)) { + i2c_detach_client(&lm->i2c); + goto fail; + } + + return lm; + fail: + kfree(lm); + return NULL; +} + +static int wf_lm75_attach(struct i2c_adapter *adapter) +{ + u8 bus_id; + struct device_node *smu, *bus, *dev; + + /* We currently only deal with LM75's hanging off the SMU + * i2c busses. If we extend that driver to other/older + * machines, we should split this function into SMU-i2c, + * keywest-i2c, PMU-i2c, ... + */ + + DBG("wf_lm75: adapter %s detected\n", adapter->name); + + if (strncmp(adapter->name, "smu-i2c-", 8) != 0) + return 0; + smu = of_find_node_by_type(NULL, "smu"); + if (smu == NULL) + return 0; + + /* Look for the bus in the device-tree */ + bus_id = (u8)simple_strtoul(adapter->name + 8, NULL, 16); + + DBG("wf_lm75: bus ID is %x\n", bus_id); + + /* Look for sensors subdir */ + for (bus = NULL; + (bus = of_get_next_child(smu, bus)) != NULL;) { + u32 *reg; + + if (strcmp(bus->name, "i2c")) + continue; + reg = (u32 *)get_property(bus, "reg", NULL); + if (reg == NULL) + continue; + if (bus_id == *reg) + break; + } + of_node_put(smu); + if (bus == NULL) { + printk(KERN_WARNING "windfarm: SMU i2c bus 0x%x not found" + " in device-tree !\n", bus_id); + return 0; + } + + DBG("wf_lm75: bus found, looking for device...\n"); + + /* Now look for lm75(s) in there */ + for (dev = NULL; + (dev = of_get_next_child(bus, dev)) != NULL;) { + const char *loc = + get_property(dev, "hwsensor-location", NULL); + u32 *reg = (u32 *)get_property(dev, "reg", NULL); + DBG(" dev: %s... (loc: %p, reg: %p)\n", dev->name, loc, reg); + if (loc == NULL || reg == NULL) + continue; + /* real lm75 */ + if (device_is_compatible(dev, "lm75")) + wf_lm75_create(adapter, *reg, 0, loc); + /* ds1775 (compatible, better resolution */ + else if (device_is_compatible(dev, "ds1775")) + wf_lm75_create(adapter, *reg, 1, loc); + } + + of_node_put(bus); + + return 0; +} + +static int wf_lm75_detach(struct i2c_client *client) +{ + struct wf_lm75_sensor *lm = i2c_to_lm75(client); + + DBG("wf_lm75: i2c detatch called for %s\n", lm->sens.name); + + /* Mark client detached */ + lm->i2c.adapter = NULL; + + /* release sensor */ + wf_unregister_sensor(&lm->sens); + + return 0; +} + +static int __init wf_lm75_sensor_init(void) +{ + int rc; + + rc = i2c_add_driver(&wf_lm75_driver); + if (rc < 0) + return rc; + return 0; +} + +static void __exit wf_lm75_sensor_exit(void) +{ + i2c_del_driver(&wf_lm75_driver); +} + + +module_init(wf_lm75_sensor_init); +module_exit(wf_lm75_sensor_exit); + +MODULE_AUTHOR("Benjamin Herrenschmidt "); +MODULE_DESCRIPTION("LM75 sensor objects for PowerMacs thermal control"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/macintosh/windfarm_pid.c b/drivers/macintosh/windfarm_pid.c new file mode 100644 index 00000000000..2e803b36875 --- /dev/null +++ b/drivers/macintosh/windfarm_pid.c @@ -0,0 +1,145 @@ +/* + * Windfarm PowerMac thermal control. Generic PID helpers + * + * (c) Copyright 2005 Benjamin Herrenschmidt, IBM Corp. + * + * + * Released under the term of the GNU GPL v2. + */ + +#include +#include +#include +#include +#include + +#include "windfarm_pid.h" + +#undef DEBUG + +#ifdef DEBUG +#define DBG(args...) printk(args) +#else +#define DBG(args...) do { } while(0) +#endif + +void wf_pid_init(struct wf_pid_state *st, struct wf_pid_param *param) +{ + memset(st, 0, sizeof(struct wf_pid_state)); + st->param = *param; + st->first = 1; +} +EXPORT_SYMBOL_GPL(wf_pid_init); + +s32 wf_pid_run(struct wf_pid_state *st, s32 new_sample) +{ + s64 error, integ, deriv; + s32 target; + int i, hlen = st->param.history_len; + + /* Calculate error term */ + error = new_sample - st->param.itarget; + + /* Get samples into our history buffer */ + if (st->first) { + for (i = 0; i < hlen; i++) { + st->samples[i] = new_sample; + st->errors[i] = error; + } + st->first = 0; + st->index = 0; + } else { + st->index = (st->index + 1) % hlen; + st->samples[st->index] = new_sample; + st->errors[st->index] = error; + } + + /* Calculate integral term */ + for (i = 0, integ = 0; i < hlen; i++) + integ += st->errors[(st->index + hlen - i) % hlen]; + integ *= st->param.interval; + + /* Calculate derivative term */ + deriv = st->errors[st->index] - + st->errors[(st->index + hlen - 1) % hlen]; + deriv /= st->param.interval; + + /* Calculate target */ + target = (s32)((integ * (s64)st->param.gr + deriv * (s64)st->param.gd + + error * (s64)st->param.gp) >> 36); + if (st->param.additive) + target += st->target; + target = max(target, st->param.min); + target = min(target, st->param.max); + st->target = target; + + return st->target; +} +EXPORT_SYMBOL_GPL(wf_pid_run); + +void wf_cpu_pid_init(struct wf_cpu_pid_state *st, + struct wf_cpu_pid_param *param) +{ + memset(st, 0, sizeof(struct wf_cpu_pid_state)); + st->param = *param; + st->first = 1; +} +EXPORT_SYMBOL_GPL(wf_cpu_pid_init); + +s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 new_power, s32 new_temp) +{ + s64 error, integ, deriv, prop; + s32 target, sval, adj; + int i, hlen = st->param.history_len; + + /* Calculate error term */ + error = st->param.pmaxadj - new_power; + + /* Get samples into our history buffer */ + if (st->first) { + for (i = 0; i < hlen; i++) { + st->powers[i] = new_power; + st->errors[i] = error; + } + st->temps[0] = st->temps[1] = new_temp; + st->first = 0; + st->index = st->tindex = 0; + } else { + st->index = (st->index + 1) % hlen; + st->powers[st->index] = new_power; + st->errors[st->index] = error; + st->tindex = (st->tindex + 1) % 2; + st->temps[st->tindex] = new_temp; + } + + /* Calculate integral term */ + for (i = 0, integ = 0; i < hlen; i++) + integ += st->errors[(st->index + hlen - i) % hlen]; + integ *= st->param.interval; + integ *= st->param.gr; + sval = st->param.tmax - ((integ >> 20) & 0xffffffff); + adj = min(st->param.ttarget, sval); + + DBG("integ: %lx, sval: %lx, adj: %lx\n", integ, sval, adj); + + /* Calculate derivative term */ + deriv = st->temps[st->tindex] - + st->temps[(st->tindex + 2 - 1) % 2]; + deriv /= st->param.interval; + deriv *= st->param.gd; + + /* Calculate proportional term */ + prop = (new_temp - adj); + prop *= st->param.gp; + + DBG("deriv: %lx, prop: %lx\n", deriv, prop); + + /* Calculate target */ + target = st->target + (s32)((deriv + prop) >> 36); + target = max(target, st->param.min); + target = min(target, st->param.max); + st->target = target; + + return st->target; +} +EXPORT_SYMBOL_GPL(wf_cpu_pid_run); diff --git a/drivers/macintosh/windfarm_pid.h b/drivers/macintosh/windfarm_pid.h new file mode 100644 index 00000000000..a364c2a2499 --- /dev/null +++ b/drivers/macintosh/windfarm_pid.h @@ -0,0 +1,84 @@ +/* + * Windfarm PowerMac thermal control. Generic PID helpers + * + * (c) Copyright 2005 Benjamin Herrenschmidt, IBM Corp. + * + * + * Released under the term of the GNU GPL v2. + * + * This is a pair of generic PID helpers that can be used by + * control loops. One is the basic PID implementation, the + * other one is more specifically tailored to the loops used + * for CPU control with 2 input sample types (temp and power) + */ + +/* + * *** Simple PID *** + */ + +#define WF_PID_MAX_HISTORY 32 + +/* This parameter array is passed to the PID algorithm. Currently, + * we don't support changing parameters on the fly as it's not needed + * but could be implemented (with necessary adjustment of the history + * buffer + */ +struct wf_pid_param { + int interval; /* Interval between samples in seconds */ + int history_len; /* Size of history buffer */ + int additive; /* 1: target relative to previous value */ + s32 gd, gp, gr; /* PID gains */ + s32 itarget; /* PID input target */ + s32 min,max; /* min and max target values */ +}; + +struct wf_pid_state { + int first; /* first run of the loop */ + int index; /* index of current sample */ + s32 target; /* current target value */ + s32 samples[WF_PID_MAX_HISTORY]; /* samples history buffer */ + s32 errors[WF_PID_MAX_HISTORY]; /* error history buffer */ + + struct wf_pid_param param; +}; + +extern void wf_pid_init(struct wf_pid_state *st, struct wf_pid_param *param); +extern s32 wf_pid_run(struct wf_pid_state *st, s32 sample); + + +/* + * *** CPU PID *** + */ + +#define WF_CPU_PID_MAX_HISTORY 32 + +/* This parameter array is passed to the CPU PID algorithm. Currently, + * we don't support changing parameters on the fly as it's not needed + * but could be implemented (with necessary adjustment of the history + * buffer + */ +struct wf_cpu_pid_param { + int interval; /* Interval between samples in seconds */ + int history_len; /* Size of history buffer */ + s32 gd, gp, gr; /* PID gains */ + s32 pmaxadj; /* PID max power adjust */ + s32 ttarget; /* PID input target */ + s32 tmax; /* PID input max */ + s32 min,max; /* min and max target values */ +}; + +struct wf_cpu_pid_state { + int first; /* first run of the loop */ + int index; /* index of current power */ + int tindex; /* index of current temp */ + s32 target; /* current target value */ + s32 powers[WF_PID_MAX_HISTORY]; /* power history buffer */ + s32 errors[WF_PID_MAX_HISTORY]; /* error history buffer */ + s32 temps[2]; /* temp. history buffer */ + + struct wf_cpu_pid_param param; +}; + +extern void wf_cpu_pid_init(struct wf_cpu_pid_state *st, + struct wf_cpu_pid_param *param); +extern s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 power, s32 temp); diff --git a/drivers/macintosh/windfarm_pm81.c b/drivers/macintosh/windfarm_pm81.c new file mode 100644 index 00000000000..322c74b2687 --- /dev/null +++ b/drivers/macintosh/windfarm_pm81.c @@ -0,0 +1,879 @@ +/* + * Windfarm PowerMac thermal control. iMac G5 + * + * (c) Copyright 2005 Benjamin Herrenschmidt, IBM Corp. + * + * + * Released under the term of the GNU GPL v2. + * + * The algorithm used is the PID control algorithm, used the same + * way the published Darwin code does, using the same values that + * are present in the Darwin 8.2 snapshot property lists (note however + * that none of the code has been re-used, it's a complete re-implementation + * + * The various control loops found in Darwin config file are: + * + * PowerMac8,1 and PowerMac8,2 + * =========================== + * + * System Fans control loop. Different based on models. In addition to the + * usual PID algorithm, the control loop gets 2 additional pairs of linear + * scaling factors (scale/offsets) expressed as 4.12 fixed point values + * signed offset, unsigned scale) + * + * The targets are modified such as: + * - the linked control (second control) gets the target value as-is + * (typically the drive fan) + * - the main control (first control) gets the target value scaled with + * the first pair of factors, and is then modified as below + * - the value of the target of the CPU Fan control loop is retreived, + * scaled with the second pair of factors, and the max of that and + * the scaled target is applied to the main control. + * + * # model_id: 2 + * controls : system-fan, drive-bay-fan + * sensors : hd-temp + * PID params : G_d = 0x15400000 + * G_p = 0x00200000 + * G_r = 0x000002fd + * History = 2 entries + * Input target = 0x3a0000 + * Interval = 5s + * linear-factors : offset = 0xff38 scale = 0x0ccd + * offset = 0x0208 scale = 0x07ae + * + * # model_id: 3 + * controls : system-fan, drive-bay-fan + * sensors : hd-temp + * PID params : G_d = 0x08e00000 + * G_p = 0x00566666 + * G_r = 0x0000072b + * History = 2 entries + * Input target = 0x350000 + * Interval = 5s + * linear-factors : offset = 0xff38 scale = 0x0ccd + * offset = 0x0000 scale = 0x0000 + * + * # model_id: 5 + * controls : system-fan + * sensors : hd-temp + * PID params : G_d = 0x15400000 + * G_p = 0x00233333 + * G_r = 0x000002fd + * History = 2 entries + * Input target = 0x3a0000 + * Interval = 5s + * linear-factors : offset = 0x0000 scale = 0x1000 + * offset = 0x0091 scale = 0x0bae + * + * CPU Fan control loop. The loop is identical for all models. it + * has an additional pair of scaling factor. This is used to scale the + * systems fan control loop target result (the one before it gets scaled + * by the System Fans control loop itself). Then, the max value of the + * calculated target value and system fan value is sent to the fans + * + * controls : cpu-fan + * sensors : cpu-temp cpu-power + * PID params : From SMU sdb partition + * linear-factors : offset = 0xfb50 scale = 0x1000 + * + * CPU Slew control loop. Not implemented. The cpufreq driver in linux is + * completely separate for now, though we could find a way to link it, either + * as a client reacting to overtemp notifications, or directling monitoring + * the CPU temperature + * + * WARNING ! The CPU control loop requires the CPU tmax for the current + * operating point. However, we currently are completely separated from + * the cpufreq driver and thus do not know what the current operating + * point is. Fortunately, we also do not have any hardware supporting anything + * but operating point 0 at the moment, thus we just peek that value directly + * from the SDB partition. If we ever end up with actually slewing the system + * clock and thus changing operating points, we'll have to find a way to + * communicate with the CPU freq driver; + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "windfarm.h" +#include "windfarm_pid.h" + +#define VERSION "0.4" + +#undef DEBUG + +#ifdef DEBUG +#define DBG(args...) printk(args) +#else +#define DBG(args...) do { } while(0) +#endif + +/* define this to force CPU overtemp to 74 degree, useful for testing + * the overtemp code + */ +#undef HACKED_OVERTEMP + +static int wf_smu_mach_model; /* machine model id */ + +static struct device *wf_smu_dev; + +/* Controls & sensors */ +static struct wf_sensor *sensor_cpu_power; +static struct wf_sensor *sensor_cpu_temp; +static struct wf_sensor *sensor_hd_temp; +static struct wf_control *fan_cpu_main; +static struct wf_control *fan_hd; +static struct wf_control *fan_system; +static struct wf_control *cpufreq_clamp; + +/* Set to kick the control loop into life */ +static int wf_smu_all_controls_ok, wf_smu_all_sensors_ok, wf_smu_started; + +/* Failure handling.. could be nicer */ +#define FAILURE_FAN 0x01 +#define FAILURE_SENSOR 0x02 +#define FAILURE_OVERTEMP 0x04 + +static unsigned int wf_smu_failure_state; +static int wf_smu_readjust, wf_smu_skipping; + +/* + * ****** System Fans Control Loop ****** + * + */ + +/* Parameters for the System Fans control loop. Parameters + * not in this table such as interval, history size, ... + * are common to all versions and thus hard coded for now. + */ +struct wf_smu_sys_fans_param { + int model_id; + s32 itarget; + s32 gd, gp, gr; + + s16 offset0; + u16 scale0; + s16 offset1; + u16 scale1; +}; + +#define WF_SMU_SYS_FANS_INTERVAL 5 +#define WF_SMU_SYS_FANS_HISTORY_SIZE 2 + +/* State data used by the system fans control loop + */ +struct wf_smu_sys_fans_state { + int ticks; + s32 sys_setpoint; + s32 hd_setpoint; + s16 offset0; + u16 scale0; + s16 offset1; + u16 scale1; + struct wf_pid_state pid; +}; + +/* + * Configs for SMU Sytem Fan control loop + */ +static struct wf_smu_sys_fans_param wf_smu_sys_all_params[] = { + /* Model ID 2 */ + { + .model_id = 2, + .itarget = 0x3a0000, + .gd = 0x15400000, + .gp = 0x00200000, + .gr = 0x000002fd, + .offset0 = 0xff38, + .scale0 = 0x0ccd, + .offset1 = 0x0208, + .scale1 = 0x07ae, + }, + /* Model ID 3 */ + { + .model_id = 2, + .itarget = 0x350000, + .gd = 0x08e00000, + .gp = 0x00566666, + .gr = 0x0000072b, + .offset0 = 0xff38, + .scale0 = 0x0ccd, + .offset1 = 0x0000, + .scale1 = 0x0000, + }, + /* Model ID 5 */ + { + .model_id = 2, + .itarget = 0x3a0000, + .gd = 0x15400000, + .gp = 0x00233333, + .gr = 0x000002fd, + .offset0 = 0x0000, + .scale0 = 0x1000, + .offset1 = 0x0091, + .scale1 = 0x0bae, + }, +}; +#define WF_SMU_SYS_FANS_NUM_CONFIGS ARRAY_SIZE(wf_smu_sys_all_params) + +static struct wf_smu_sys_fans_state *wf_smu_sys_fans; + +/* + * ****** CPU Fans Control Loop ****** + * + */ + + +#define WF_SMU_CPU_FANS_INTERVAL 1 +#define WF_SMU_CPU_FANS_MAX_HISTORY 16 +#define WF_SMU_CPU_FANS_SIBLING_SCALE 0x00001000 +#define WF_SMU_CPU_FANS_SIBLING_OFFSET 0xfffffb50 + +/* State data used by the cpu fans control loop + */ +struct wf_smu_cpu_fans_state { + int ticks; + s32 cpu_setpoint; + s32 scale; + s32 offset; + struct wf_cpu_pid_state pid; +}; + +static struct wf_smu_cpu_fans_state *wf_smu_cpu_fans; + + + +/* + * ***** Implementation ***** + * + */ + +static void wf_smu_create_sys_fans(void) +{ + struct wf_smu_sys_fans_param *param = NULL; + struct wf_pid_param pid_param; + int i; + + /* First, locate the params for this model */ + for (i = 0; i < WF_SMU_SYS_FANS_NUM_CONFIGS; i++) + if (wf_smu_sys_all_params[i].model_id == wf_smu_mach_model) { + param = &wf_smu_sys_all_params[i]; + break; + } + + /* No params found, put fans to max */ + if (param == NULL) { + printk(KERN_WARNING "windfarm: System fan config not found " + "for this machine model, max fan speed\n"); + goto fail; + } + + /* Alloc & initialize state */ + wf_smu_sys_fans = kmalloc(sizeof(struct wf_smu_sys_fans_state), + GFP_KERNEL); + if (wf_smu_sys_fans == NULL) { + printk(KERN_WARNING "windfarm: Memory allocation error" + " max fan speed\n"); + goto fail; + } + wf_smu_sys_fans->ticks = 1; + wf_smu_sys_fans->scale0 = param->scale0; + wf_smu_sys_fans->offset0 = param->offset0; + wf_smu_sys_fans->scale1 = param->scale1; + wf_smu_sys_fans->offset1 = param->offset1; + + /* Fill PID params */ + pid_param.gd = param->gd; + pid_param.gp = param->gp; + pid_param.gr = param->gr; + pid_param.interval = WF_SMU_SYS_FANS_INTERVAL; + pid_param.history_len = WF_SMU_SYS_FANS_HISTORY_SIZE; + pid_param.itarget = param->itarget; + pid_param.min = fan_system->ops->get_min(fan_system); + pid_param.max = fan_system->ops->get_max(fan_system); + if (fan_hd) { + pid_param.min = + max(pid_param.min,fan_hd->ops->get_min(fan_hd)); + pid_param.max = + min(pid_param.max,fan_hd->ops->get_max(fan_hd)); + } + wf_pid_init(&wf_smu_sys_fans->pid, &pid_param); + + DBG("wf: System Fan control initialized.\n"); + DBG(" itarged=%d.%03d, min=%d RPM, max=%d RPM\n", + FIX32TOPRINT(pid_param.itarget), pid_param.min, pid_param.max); + return; + + fail: + + if (fan_system) + wf_control_set_max(fan_system); + if (fan_hd) + wf_control_set_max(fan_hd); +} + +static void wf_smu_sys_fans_tick(struct wf_smu_sys_fans_state *st) +{ + s32 new_setpoint, temp, scaled, cputarget; + int rc; + + if (--st->ticks != 0) { + if (wf_smu_readjust) + goto readjust; + return; + } + st->ticks = WF_SMU_SYS_FANS_INTERVAL; + + rc = sensor_hd_temp->ops->get_value(sensor_hd_temp, &temp); + if (rc) { + printk(KERN_WARNING "windfarm: HD temp sensor error %d\n", + rc); + wf_smu_failure_state |= FAILURE_SENSOR; + return; + } + + DBG("wf_smu: System Fans tick ! HD temp: %d.%03d\n", + FIX32TOPRINT(temp)); + + if (temp > (st->pid.param.itarget + 0x50000)) + wf_smu_failure_state |= FAILURE_OVERTEMP; + + new_setpoint = wf_pid_run(&st->pid, temp); + + DBG("wf_smu: new_setpoint: %d RPM\n", (int)new_setpoint); + + scaled = ((((s64)new_setpoint) * (s64)st->scale0) >> 12) + st->offset0; + + DBG("wf_smu: scaled setpoint: %d RPM\n", (int)scaled); + + cputarget = wf_smu_cpu_fans ? wf_smu_cpu_fans->pid.target : 0; + cputarget = ((((s64)cputarget) * (s64)st->scale1) >> 12) + st->offset1; + scaled = max(scaled, cputarget); + scaled = max(scaled, st->pid.param.min); + scaled = min(scaled, st->pid.param.max); + + DBG("wf_smu: adjusted setpoint: %d RPM\n", (int)scaled); + + if (st->sys_setpoint == scaled && new_setpoint == st->hd_setpoint) + return; + st->sys_setpoint = scaled; + st->hd_setpoint = new_setpoint; + readjust: + if (fan_system && wf_smu_failure_state == 0) { + rc = fan_system->ops->set_value(fan_system, st->sys_setpoint); + if (rc) { + printk(KERN_WARNING "windfarm: Sys fan error %d\n", + rc); + wf_smu_failure_state |= FAILURE_FAN; + } + } + if (fan_hd && wf_smu_failure_state == 0) { + rc = fan_hd->ops->set_value(fan_hd, st->hd_setpoint); + if (rc) { + printk(KERN_WARNING "windfarm: HD fan error %d\n", + rc); + wf_smu_failure_state |= FAILURE_FAN; + } + } +} + +static void wf_smu_create_cpu_fans(void) +{ + struct wf_cpu_pid_param pid_param; + struct smu_sdbp_header *hdr; + struct smu_sdbp_cpupiddata *piddata; + struct smu_sdbp_fvt *fvt; + s32 tmax, tdelta, maxpow, powadj; + + /* First, locate the PID params in SMU SBD */ + hdr = smu_get_sdb_partition(SMU_SDB_CPUPIDDATA_ID, NULL); + if (hdr == 0) { + printk(KERN_WARNING "windfarm: CPU PID fan config not found " + "max fan speed\n"); + goto fail; + } + piddata = (struct smu_sdbp_cpupiddata *)&hdr[1]; + + /* Get the FVT params for operating point 0 (the only supported one + * for now) in order to get tmax + */ + hdr = smu_get_sdb_partition(SMU_SDB_FVT_ID, NULL); + if (hdr) { + fvt = (struct smu_sdbp_fvt *)&hdr[1]; + tmax = ((s32)fvt->maxtemp) << 16; + } else + tmax = 0x5e0000; /* 94 degree default */ + + /* Alloc & initialize state */ + wf_smu_cpu_fans = kmalloc(sizeof(struct wf_smu_cpu_fans_state), + GFP_KERNEL); + if (wf_smu_cpu_fans == NULL) + goto fail; + wf_smu_cpu_fans->ticks = 1; + + wf_smu_cpu_fans->scale = WF_SMU_CPU_FANS_SIBLING_SCALE; + wf_smu_cpu_fans->offset = WF_SMU_CPU_FANS_SIBLING_OFFSET; + + /* Fill PID params */ + pid_param.interval = WF_SMU_CPU_FANS_INTERVAL; + pid_param.history_len = piddata->history_len; + if (pid_param.history_len > WF_CPU_PID_MAX_HISTORY) { + printk(KERN_WARNING "windfarm: History size overflow on " + "CPU control loop (%d)\n", piddata->history_len); + pid_param.history_len = WF_CPU_PID_MAX_HISTORY; + } + pid_param.gd = piddata->gd; + pid_param.gp = piddata->gp; + pid_param.gr = piddata->gr / pid_param.history_len; + + tdelta = ((s32)piddata->target_temp_delta) << 16; + maxpow = ((s32)piddata->max_power) << 16; + powadj = ((s32)piddata->power_adj) << 16; + + pid_param.tmax = tmax; + pid_param.ttarget = tmax - tdelta; + pid_param.pmaxadj = maxpow - powadj; + + pid_param.min = fan_cpu_main->ops->get_min(fan_cpu_main); + pid_param.max = fan_cpu_main->ops->get_max(fan_cpu_main); + + wf_cpu_pid_init(&wf_smu_cpu_fans->pid, &pid_param); + + DBG("wf: CPU Fan control initialized.\n"); + DBG(" ttarged=%d.%03d, tmax=%d.%03d, min=%d RPM, max=%d RPM\n", + FIX32TOPRINT(pid_param.ttarget), FIX32TOPRINT(pid_param.tmax), + pid_param.min, pid_param.max); + + return; + + fail: + printk(KERN_WARNING "windfarm: CPU fan config not found\n" + "for this machine model, max fan speed\n"); + + if (cpufreq_clamp) + wf_control_set_max(cpufreq_clamp); + if (fan_cpu_main) + wf_control_set_max(fan_cpu_main); +} + +static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st) +{ + s32 new_setpoint, temp, power, systarget; + int rc; + + if (--st->ticks != 0) { + if (wf_smu_readjust) + goto readjust; + return; + } + st->ticks = WF_SMU_CPU_FANS_INTERVAL; + + rc = sensor_cpu_temp->ops->get_value(sensor_cpu_temp, &temp); + if (rc) { + printk(KERN_WARNING "windfarm: CPU temp sensor error %d\n", + rc); + wf_smu_failure_state |= FAILURE_SENSOR; + return; + } + + rc = sensor_cpu_power->ops->get_value(sensor_cpu_power, &power); + if (rc) { + printk(KERN_WARNING "windfarm: CPU power sensor error %d\n", + rc); + wf_smu_failure_state |= FAILURE_SENSOR; + return; + } + + DBG("wf_smu: CPU Fans tick ! CPU temp: %d.%03d, power: %d.%03d\n", + FIX32TOPRINT(temp), FIX32TOPRINT(power)); + +#ifdef HACKED_OVERTEMP + if (temp > 0x4a0000) + wf_smu_failure_state |= FAILURE_OVERTEMP; +#else + if (temp > st->pid.param.tmax) + wf_smu_failure_state |= FAILURE_OVERTEMP; +#endif + new_setpoint = wf_cpu_pid_run(&st->pid, power, temp); + + DBG("wf_smu: new_setpoint: %d RPM\n", (int)new_setpoint); + + systarget = wf_smu_sys_fans ? wf_smu_sys_fans->pid.target : 0; + systarget = ((((s64)systarget) * (s64)st->scale) >> 12) + + st->offset; + new_setpoint = max(new_setpoint, systarget); + new_setpoint = max(new_setpoint, st->pid.param.min); + new_setpoint = min(new_setpoint, st->pid.param.max); + + DBG("wf_smu: adjusted setpoint: %d RPM\n", (int)new_setpoint); + + if (st->cpu_setpoint == new_setpoint) + return; + st->cpu_setpoint = new_setpoint; + readjust: + if (fan_cpu_main && wf_smu_failure_state == 0) { + rc = fan_cpu_main->ops->set_value(fan_cpu_main, + st->cpu_setpoint); + if (rc) { + printk(KERN_WARNING "windfarm: CPU main fan" + " error %d\n", rc); + wf_smu_failure_state |= FAILURE_FAN; + } + } +} + + +/* + * ****** Attributes ****** + * + */ + +#define BUILD_SHOW_FUNC_FIX(name, data) \ +static ssize_t show_##name(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + ssize_t r; \ + s32 val = 0; \ + data->ops->get_value(data, &val); \ + r = sprintf(buf, "%d.%03d", FIX32TOPRINT(val)); \ + return r; \ +} \ +static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL); + + +#define BUILD_SHOW_FUNC_INT(name, data) \ +static ssize_t show_##name(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + s32 val = 0; \ + data->ops->get_value(data, &val); \ + return sprintf(buf, "%d", val); \ +} \ +static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL); + +BUILD_SHOW_FUNC_INT(cpu_fan, fan_cpu_main); +BUILD_SHOW_FUNC_INT(sys_fan, fan_system); +BUILD_SHOW_FUNC_INT(hd_fan, fan_hd); + +BUILD_SHOW_FUNC_FIX(cpu_temp, sensor_cpu_temp); +BUILD_SHOW_FUNC_FIX(cpu_power, sensor_cpu_power); +BUILD_SHOW_FUNC_FIX(hd_temp, sensor_hd_temp); + +/* + * ****** Setup / Init / Misc ... ****** + * + */ + +static void wf_smu_tick(void) +{ + unsigned int last_failure = wf_smu_failure_state; + unsigned int new_failure; + + if (!wf_smu_started) { + DBG("wf: creating control loops !\n"); + wf_smu_create_sys_fans(); + wf_smu_create_cpu_fans(); + wf_smu_started = 1; + } + + /* Skipping ticks */ + if (wf_smu_skipping && --wf_smu_skipping) + return; + + wf_smu_failure_state = 0; + if (wf_smu_sys_fans) + wf_smu_sys_fans_tick(wf_smu_sys_fans); + if (wf_smu_cpu_fans) + wf_smu_cpu_fans_tick(wf_smu_cpu_fans); + + wf_smu_readjust = 0; + new_failure = wf_smu_failure_state & ~last_failure; + + /* If entering failure mode, clamp cpufreq and ramp all + * fans to full speed. + */ + if (wf_smu_failure_state && !last_failure) { + if (cpufreq_clamp) + wf_control_set_max(cpufreq_clamp); + if (fan_system) + wf_control_set_max(fan_system); + if (fan_cpu_main) + wf_control_set_max(fan_cpu_main); + if (fan_hd) + wf_control_set_max(fan_hd); + } + + /* If leaving failure mode, unclamp cpufreq and readjust + * all fans on next iteration + */ + if (!wf_smu_failure_state && last_failure) { + if (cpufreq_clamp) + wf_control_set_min(cpufreq_clamp); + wf_smu_readjust = 1; + } + + /* Overtemp condition detected, notify and start skipping a couple + * ticks to let the temperature go down + */ + if (new_failure & FAILURE_OVERTEMP) { + wf_set_overtemp(); + wf_smu_skipping = 2; + } + + /* We only clear the overtemp condition if overtemp is cleared + * _and_ no other failure is present. Since a sensor error will + * clear the overtemp condition (can't measure temperature) at + * the control loop levels, but we don't want to keep it clear + * here in this case + */ + if (new_failure == 0 && last_failure & FAILURE_OVERTEMP) + wf_clear_overtemp(); +} + +static void wf_smu_new_control(struct wf_control *ct) +{ + if (wf_smu_all_controls_ok) + return; + + if (fan_cpu_main == NULL && !strcmp(ct->name, "cpu-fan")) { + if (wf_get_control(ct) == 0) { + fan_cpu_main = ct; + device_create_file(wf_smu_dev, &dev_attr_cpu_fan); + } + } + + if (fan_system == NULL && !strcmp(ct->name, "system-fan")) { + if (wf_get_control(ct) == 0) { + fan_system = ct; + device_create_file(wf_smu_dev, &dev_attr_sys_fan); + } + } + + if (cpufreq_clamp == NULL && !strcmp(ct->name, "cpufreq-clamp")) { + if (wf_get_control(ct) == 0) + cpufreq_clamp = ct; + } + + /* Darwin property list says the HD fan is only for model ID + * 0, 1, 2 and 3 + */ + + if (wf_smu_mach_model > 3) { + if (fan_system && fan_cpu_main && cpufreq_clamp) + wf_smu_all_controls_ok = 1; + return; + } + + if (fan_hd == NULL && !strcmp(ct->name, "drive-bay-fan")) { + if (wf_get_control(ct) == 0) { + fan_hd = ct; + device_create_file(wf_smu_dev, &dev_attr_hd_fan); + } + } + + if (fan_system && fan_hd && fan_cpu_main && cpufreq_clamp) + wf_smu_all_controls_ok = 1; +} + +static void wf_smu_new_sensor(struct wf_sensor *sr) +{ + if (wf_smu_all_sensors_ok) + return; + + if (sensor_cpu_power == NULL && !strcmp(sr->name, "cpu-power")) { + if (wf_get_sensor(sr) == 0) { + sensor_cpu_power = sr; + device_create_file(wf_smu_dev, &dev_attr_cpu_power); + } + } + + if (sensor_cpu_temp == NULL && !strcmp(sr->name, "cpu-temp")) { + if (wf_get_sensor(sr) == 0) { + sensor_cpu_temp = sr; + device_create_file(wf_smu_dev, &dev_attr_cpu_temp); + } + } + + if (sensor_hd_temp == NULL && !strcmp(sr->name, "hd-temp")) { + if (wf_get_sensor(sr) == 0) { + sensor_hd_temp = sr; + device_create_file(wf_smu_dev, &dev_attr_hd_temp); + } + } + + if (sensor_cpu_power && sensor_cpu_temp && sensor_hd_temp) + wf_smu_all_sensors_ok = 1; +} + + +static int wf_smu_notify(struct notifier_block *self, + unsigned long event, void *data) +{ + switch(event) { + case WF_EVENT_NEW_CONTROL: + DBG("wf: new control %s detected\n", + ((struct wf_control *)data)->name); + wf_smu_new_control(data); + wf_smu_readjust = 1; + break; + case WF_EVENT_NEW_SENSOR: + DBG("wf: new sensor %s detected\n", + ((struct wf_sensor *)data)->name); + wf_smu_new_sensor(data); + break; + case WF_EVENT_TICK: + if (wf_smu_all_controls_ok && wf_smu_all_sensors_ok) + wf_smu_tick(); + } + + return 0; +} + +static struct notifier_block wf_smu_events = { + .notifier_call = wf_smu_notify, +}; + +static int wf_init_pm(void) +{ + struct smu_sdbp_header *hdr; + + hdr = smu_get_sdb_partition(SMU_SDB_SENSORTREE_ID, NULL); + if (hdr != 0) { + struct smu_sdbp_sensortree *st = + (struct smu_sdbp_sensortree *)&hdr[1]; + wf_smu_mach_model = st->model_id; + } + + printk(KERN_INFO "windfarm: Initializing for iMacG5 model ID %d\n", + wf_smu_mach_model); + + return 0; +} + +static int wf_smu_probe(struct device *ddev) +{ + wf_smu_dev = ddev; + + wf_register_client(&wf_smu_events); + + return 0; +} + +static int wf_smu_remove(struct device *ddev) +{ + wf_unregister_client(&wf_smu_events); + + /* XXX We don't have yet a guarantee that our callback isn't + * in progress when returning from wf_unregister_client, so + * we add an arbitrary delay. I'll have to fix that in the core + */ + msleep(1000); + + /* Release all sensors */ + /* One more crappy race: I don't think we have any guarantee here + * that the attribute callback won't race with the sensor beeing + * disposed of, and I'm not 100% certain what best way to deal + * with that except by adding locks all over... I'll do that + * eventually but heh, who ever rmmod this module anyway ? + */ + if (sensor_cpu_power) { + device_remove_file(wf_smu_dev, &dev_attr_cpu_power); + wf_put_sensor(sensor_cpu_power); + } + if (sensor_cpu_temp) { + device_remove_file(wf_smu_dev, &dev_attr_cpu_temp); + wf_put_sensor(sensor_cpu_temp); + } + if (sensor_hd_temp) { + device_remove_file(wf_smu_dev, &dev_attr_hd_temp); + wf_put_sensor(sensor_hd_temp); + } + + /* Release all controls */ + if (fan_cpu_main) { + device_remove_file(wf_smu_dev, &dev_attr_cpu_fan); + wf_put_control(fan_cpu_main); + } + if (fan_hd) { + device_remove_file(wf_smu_dev, &dev_attr_hd_fan); + wf_put_control(fan_hd); + } + if (fan_system) { + device_remove_file(wf_smu_dev, &dev_attr_sys_fan); + wf_put_control(fan_system); + } + if (cpufreq_clamp) + wf_put_control(cpufreq_clamp); + + /* Destroy control loops state structures */ + if (wf_smu_sys_fans) + kfree(wf_smu_sys_fans); + if (wf_smu_cpu_fans) + kfree(wf_smu_cpu_fans); + + wf_smu_dev = NULL; + + return 0; +} + +static struct device_driver wf_smu_driver = { + .name = "windfarm", + .bus = &platform_bus_type, + .probe = wf_smu_probe, + .remove = wf_smu_remove, +}; + + +static int __init wf_smu_init(void) +{ + int rc = -ENODEV; + + if (machine_is_compatible("PowerMac8,1") || + machine_is_compatible("PowerMac8,2")) + rc = wf_init_pm(); + + if (rc == 0) { +#ifdef MODULE + request_module("windfarm_smu_controls"); + request_module("windfarm_smu_sensors"); + request_module("windfarm_lm75_sensor"); + +#endif /* MODULE */ + driver_register(&wf_smu_driver); + } + + return rc; +} + +static void __exit wf_smu_exit(void) +{ + + driver_unregister(&wf_smu_driver); +} + + +module_init(wf_smu_init); +module_exit(wf_smu_exit); + +MODULE_AUTHOR("Benjamin Herrenschmidt "); +MODULE_DESCRIPTION("Thermal control logic for iMac G5"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/macintosh/windfarm_pm91.c b/drivers/macintosh/windfarm_pm91.c new file mode 100644 index 00000000000..43243cf7410 --- /dev/null +++ b/drivers/macintosh/windfarm_pm91.c @@ -0,0 +1,814 @@ +/* + * Windfarm PowerMac thermal control. SMU based 1 CPU desktop control loops + * + * (c) Copyright 2005 Benjamin Herrenschmidt, IBM Corp. + * + * + * Released under the term of the GNU GPL v2. + * + * The algorithm used is the PID control algorithm, used the same + * way the published Darwin code does, using the same values that + * are present in the Darwin 8.2 snapshot property lists (note however + * that none of the code has been re-used, it's a complete re-implementation + * + * The various control loops found in Darwin config file are: + * + * PowerMac9,1 + * =========== + * + * Has 3 control loops: CPU fans is similar to PowerMac8,1 (though it doesn't + * try to play with other control loops fans). Drive bay is rather basic PID + * with one sensor and one fan. Slots area is a bit different as the Darwin + * driver is supposed to be capable of working in a special "AGP" mode which + * involves the presence of an AGP sensor and an AGP fan (possibly on the + * AGP card itself). I can't deal with that special mode as I don't have + * access to those additional sensor/fans for now (though ultimately, it would + * be possible to add sensor objects for them) so I'm only implementing the + * basic PCI slot control loop + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "windfarm.h" +#include "windfarm_pid.h" + +#define VERSION "0.4" + +#undef DEBUG + +#ifdef DEBUG +#define DBG(args...) printk(args) +#else +#define DBG(args...) do { } while(0) +#endif + +/* define this to force CPU overtemp to 74 degree, useful for testing + * the overtemp code + */ +#undef HACKED_OVERTEMP + +static struct device *wf_smu_dev; + +/* Controls & sensors */ +static struct wf_sensor *sensor_cpu_power; +static struct wf_sensor *sensor_cpu_temp; +static struct wf_sensor *sensor_hd_temp; +static struct wf_sensor *sensor_slots_power; +static struct wf_control *fan_cpu_main; +static struct wf_control *fan_cpu_second; +static struct wf_control *fan_cpu_third; +static struct wf_control *fan_hd; +static struct wf_control *fan_slots; +static struct wf_control *cpufreq_clamp; + +/* Set to kick the control loop into life */ +static int wf_smu_all_controls_ok, wf_smu_all_sensors_ok, wf_smu_started; + +/* Failure handling.. could be nicer */ +#define FAILURE_FAN 0x01 +#define FAILURE_SENSOR 0x02 +#define FAILURE_OVERTEMP 0x04 + +static unsigned int wf_smu_failure_state; +static int wf_smu_readjust, wf_smu_skipping; + +/* + * ****** CPU Fans Control Loop ****** + * + */ + + +#define WF_SMU_CPU_FANS_INTERVAL 1 +#define WF_SMU_CPU_FANS_MAX_HISTORY 16 + +/* State data used by the cpu fans control loop + */ +struct wf_smu_cpu_fans_state { + int ticks; + s32 cpu_setpoint; + struct wf_cpu_pid_state pid; +}; + +static struct wf_smu_cpu_fans_state *wf_smu_cpu_fans; + + + +/* + * ****** Drive Fan Control Loop ****** + * + */ + +struct wf_smu_drive_fans_state { + int ticks; + s32 setpoint; + struct wf_pid_state pid; +}; + +static struct wf_smu_drive_fans_state *wf_smu_drive_fans; + +/* + * ****** Slots Fan Control Loop ****** + * + */ + +struct wf_smu_slots_fans_state { + int ticks; + s32 setpoint; + struct wf_pid_state pid; +}; + +static struct wf_smu_slots_fans_state *wf_smu_slots_fans; + +/* + * ***** Implementation ***** + * + */ + + +static void wf_smu_create_cpu_fans(void) +{ + struct wf_cpu_pid_param pid_param; + struct smu_sdbp_header *hdr; + struct smu_sdbp_cpupiddata *piddata; + struct smu_sdbp_fvt *fvt; + s32 tmax, tdelta, maxpow, powadj; + + /* First, locate the PID params in SMU SBD */ + hdr = smu_get_sdb_partition(SMU_SDB_CPUPIDDATA_ID, NULL); + if (hdr == 0) { + printk(KERN_WARNING "windfarm: CPU PID fan config not found " + "max fan speed\n"); + goto fail; + } + piddata = (struct smu_sdbp_cpupiddata *)&hdr[1]; + + /* Get the FVT params for operating point 0 (the only supported one + * for now) in order to get tmax + */ + hdr = smu_get_sdb_partition(SMU_SDB_FVT_ID, NULL); + if (hdr) { + fvt = (struct smu_sdbp_fvt *)&hdr[1]; + tmax = ((s32)fvt->maxtemp) << 16; + } else + tmax = 0x5e0000; /* 94 degree default */ + + /* Alloc & initialize state */ + wf_smu_cpu_fans = kmalloc(sizeof(struct wf_smu_cpu_fans_state), + GFP_KERNEL); + if (wf_smu_cpu_fans == NULL) + goto fail; + wf_smu_cpu_fans->ticks = 1; + + /* Fill PID params */ + pid_param.interval = WF_SMU_CPU_FANS_INTERVAL; + pid_param.history_len = piddata->history_len; + if (pid_param.history_len > WF_CPU_PID_MAX_HISTORY) { + printk(KERN_WARNING "windfarm: History size overflow on " + "CPU control loop (%d)\n", piddata->history_len); + pid_param.history_len = WF_CPU_PID_MAX_HISTORY; + } + pid_param.gd = piddata->gd; + pid_param.gp = piddata->gp; + pid_param.gr = piddata->gr / pid_param.history_len; + + tdelta = ((s32)piddata->target_temp_delta) << 16; + maxpow = ((s32)piddata->max_power) << 16; + powadj = ((s32)piddata->power_adj) << 16; + + pid_param.tmax = tmax; + pid_param.ttarget = tmax - tdelta; + pid_param.pmaxadj = maxpow - powadj; + + pid_param.min = fan_cpu_main->ops->get_min(fan_cpu_main); + pid_param.max = fan_cpu_main->ops->get_max(fan_cpu_main); + + wf_cpu_pid_init(&wf_smu_cpu_fans->pid, &pid_param); + + DBG("wf: CPU Fan control initialized.\n"); + DBG(" ttarged=%d.%03d, tmax=%d.%03d, min=%d RPM, max=%d RPM\n", + FIX32TOPRINT(pid_param.ttarget), FIX32TOPRINT(pid_param.tmax), + pid_param.min, pid_param.max); + + return; + + fail: + printk(KERN_WARNING "windfarm: CPU fan config not found\n" + "for this machine model, max fan speed\n"); + + if (cpufreq_clamp) + wf_control_set_max(cpufreq_clamp); + if (fan_cpu_main) + wf_control_set_max(fan_cpu_main); +} + +static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st) +{ + s32 new_setpoint, temp, power; + int rc; + + if (--st->ticks != 0) { + if (wf_smu_readjust) + goto readjust; + return; + } + st->ticks = WF_SMU_CPU_FANS_INTERVAL; + + rc = sensor_cpu_temp->ops->get_value(sensor_cpu_temp, &temp); + if (rc) { + printk(KERN_WARNING "windfarm: CPU temp sensor error %d\n", + rc); + wf_smu_failure_state |= FAILURE_SENSOR; + return; + } + + rc = sensor_cpu_power->ops->get_value(sensor_cpu_power, &power); + if (rc) { + printk(KERN_WARNING "windfarm: CPU power sensor error %d\n", + rc); + wf_smu_failure_state |= FAILURE_SENSOR; + return; + } + + DBG("wf_smu: CPU Fans tick ! CPU temp: %d.%03d, power: %d.%03d\n", + FIX32TOPRINT(temp), FIX32TOPRINT(power)); + +#ifdef HACKED_OVERTEMP + if (temp > 0x4a0000) + wf_smu_failure_state |= FAILURE_OVERTEMP; +#else + if (temp > st->pid.param.tmax) + wf_smu_failure_state |= FAILURE_OVERTEMP; +#endif + new_setpoint = wf_cpu_pid_run(&st->pid, power, temp); + + DBG("wf_smu: new_setpoint: %d RPM\n", (int)new_setpoint); + + if (st->cpu_setpoint == new_setpoint) + return; + st->cpu_setpoint = new_setpoint; + readjust: + if (fan_cpu_main && wf_smu_failure_state == 0) { + rc = fan_cpu_main->ops->set_value(fan_cpu_main, + st->cpu_setpoint); + if (rc) { + printk(KERN_WARNING "windfarm: CPU main fan" + " error %d\n", rc); + wf_smu_failure_state |= FAILURE_FAN; + } + } + if (fan_cpu_second && wf_smu_failure_state == 0) { + rc = fan_cpu_second->ops->set_value(fan_cpu_second, + st->cpu_setpoint); + if (rc) { + printk(KERN_WARNING "windfarm: CPU second fan" + " error %d\n", rc); + wf_smu_failure_state |= FAILURE_FAN; + } + } + if (fan_cpu_third && wf_smu_failure_state == 0) { + rc = fan_cpu_main->ops->set_value(fan_cpu_third, + st->cpu_setpoint); + if (rc) { + printk(KERN_WARNING "windfarm: CPU third fan" + " error %d\n", rc); + wf_smu_failure_state |= FAILURE_FAN; + } + } +} + +static void wf_smu_create_drive_fans(void) +{ + struct wf_pid_param param = { + .interval = 5, + .history_len = 2, + .gd = 0x01e00000, + .gp = 0x00500000, + .gr = 0x00000000, + .itarget = 0x00200000, + }; + + /* Alloc & initialize state */ + wf_smu_drive_fans = kmalloc(sizeof(struct wf_smu_drive_fans_state), + GFP_KERNEL); + if (wf_smu_drive_fans == NULL) { + printk(KERN_WARNING "windfarm: Memory allocation error" + " max fan speed\n"); + goto fail; + } + wf_smu_drive_fans->ticks = 1; + + /* Fill PID params */ + param.additive = (fan_hd->type == WF_CONTROL_RPM_FAN); + param.min = fan_hd->ops->get_min(fan_hd); + param.max = fan_hd->ops->get_max(fan_hd); + wf_pid_init(&wf_smu_drive_fans->pid, ¶m); + + DBG("wf: Drive Fan control initialized.\n"); + DBG(" itarged=%d.%03d, min=%d RPM, max=%d RPM\n", + FIX32TOPRINT(param.itarget), param.min, param.max); + return; + + fail: + if (fan_hd) + wf_control_set_max(fan_hd); +} + +static void wf_smu_drive_fans_tick(struct wf_smu_drive_fans_state *st) +{ + s32 new_setpoint, temp; + int rc; + + if (--st->ticks != 0) { + if (wf_smu_readjust) + goto readjust; + return; + } + st->ticks = st->pid.param.interval; + + rc = sensor_hd_temp->ops->get_value(sensor_hd_temp, &temp); + if (rc) { + printk(KERN_WARNING "windfarm: HD temp sensor error %d\n", + rc); + wf_smu_failure_state |= FAILURE_SENSOR; + return; + } + + DBG("wf_smu: Drive Fans tick ! HD temp: %d.%03d\n", + FIX32TOPRINT(temp)); + + if (temp > (st->pid.param.itarget + 0x50000)) + wf_smu_failure_state |= FAILURE_OVERTEMP; + + new_setpoint = wf_pid_run(&st->pid, temp); + + DBG("wf_smu: new_setpoint: %d\n", (int)new_setpoint); + + if (st->setpoint == new_setpoint) + return; + st->setpoint = new_setpoint; + readjust: + if (fan_hd && wf_smu_failure_state == 0) { + rc = fan_hd->ops->set_value(fan_hd, st->setpoint); + if (rc) { + printk(KERN_WARNING "windfarm: HD fan error %d\n", + rc); + wf_smu_failure_state |= FAILURE_FAN; + } + } +} + +static void wf_smu_create_slots_fans(void) +{ + struct wf_pid_param param = { + .interval = 1, + .history_len = 8, + .gd = 0x00000000, + .gp = 0x00000000, + .gr = 0x00020000, + .itarget = 0x00000000 + }; + + /* Alloc & initialize state */ + wf_smu_slots_fans = kmalloc(sizeof(struct wf_smu_slots_fans_state), + GFP_KERNEL); + if (wf_smu_slots_fans == NULL) { + printk(KERN_WARNING "windfarm: Memory allocation error" + " max fan speed\n"); + goto fail; + } + wf_smu_slots_fans->ticks = 1; + + /* Fill PID params */ + param.additive = (fan_slots->type == WF_CONTROL_RPM_FAN); + param.min = fan_slots->ops->get_min(fan_slots); + param.max = fan_slots->ops->get_max(fan_slots); + wf_pid_init(&wf_smu_slots_fans->pid, ¶m); + + DBG("wf: Slots Fan control initialized.\n"); + DBG(" itarged=%d.%03d, min=%d RPM, max=%d RPM\n", + FIX32TOPRINT(param.itarget), param.min, param.max); + return; + + fail: + if (fan_slots) + wf_control_set_max(fan_slots); +} + +static void wf_smu_slots_fans_tick(struct wf_smu_slots_fans_state *st) +{ + s32 new_setpoint, power; + int rc; + + if (--st->ticks != 0) { + if (wf_smu_readjust) + goto readjust; + return; + } + st->ticks = st->pid.param.interval; + + rc = sensor_slots_power->ops->get_value(sensor_slots_power, &power); + if (rc) { + printk(KERN_WARNING "windfarm: Slots power sensor error %d\n", + rc); + wf_smu_failure_state |= FAILURE_SENSOR; + return; + } + + DBG("wf_smu: Slots Fans tick ! Slots power: %d.%03d\n", + FIX32TOPRINT(power)); + +#if 0 /* Check what makes a good overtemp condition */ + if (power > (st->pid.param.itarget + 0x50000)) + wf_smu_failure_state |= FAILURE_OVERTEMP; +#endif + + new_setpoint = wf_pid_run(&st->pid, power); + + DBG("wf_smu: new_setpoint: %d\n", (int)new_setpoint); + + if (st->setpoint == new_setpoint) + return; + st->setpoint = new_setpoint; + readjust: + if (fan_slots && wf_smu_failure_state == 0) { + rc = fan_slots->ops->set_value(fan_slots, st->setpoint); + if (rc) { + printk(KERN_WARNING "windfarm: Slots fan error %d\n", + rc); + wf_smu_failure_state |= FAILURE_FAN; + } + } +} + + +/* + * ****** Attributes ****** + * + */ + +#define BUILD_SHOW_FUNC_FIX(name, data) \ +static ssize_t show_##name(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + ssize_t r; \ + s32 val = 0; \ + data->ops->get_value(data, &val); \ + r = sprintf(buf, "%d.%03d", FIX32TOPRINT(val)); \ + return r; \ +} \ +static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL); + + +#define BUILD_SHOW_FUNC_INT(name, data) \ +static ssize_t show_##name(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + s32 val = 0; \ + data->ops->get_value(data, &val); \ + return sprintf(buf, "%d", val); \ +} \ +static DEVICE_ATTR(name,S_IRUGO,show_##name, NULL); + +BUILD_SHOW_FUNC_INT(cpu_fan, fan_cpu_main); +BUILD_SHOW_FUNC_INT(hd_fan, fan_hd); +BUILD_SHOW_FUNC_INT(slots_fan, fan_slots); + +BUILD_SHOW_FUNC_FIX(cpu_temp, sensor_cpu_temp); +BUILD_SHOW_FUNC_FIX(cpu_power, sensor_cpu_power); +BUILD_SHOW_FUNC_FIX(hd_temp, sensor_hd_temp); +BUILD_SHOW_FUNC_FIX(slots_power, sensor_slots_power); + +/* + * ****** Setup / Init / Misc ... ****** + * + */ + +static void wf_smu_tick(void) +{ + unsigned int last_failure = wf_smu_failure_state; + unsigned int new_failure; + + if (!wf_smu_started) { + DBG("wf: creating control loops !\n"); + wf_smu_create_drive_fans(); + wf_smu_create_slots_fans(); + wf_smu_create_cpu_fans(); + wf_smu_started = 1; + } + + /* Skipping ticks */ + if (wf_smu_skipping && --wf_smu_skipping) + return; + + wf_smu_failure_state = 0; + if (wf_smu_drive_fans) + wf_smu_drive_fans_tick(wf_smu_drive_fans); + if (wf_smu_slots_fans) + wf_smu_slots_fans_tick(wf_smu_slots_fans); + if (wf_smu_cpu_fans) + wf_smu_cpu_fans_tick(wf_smu_cpu_fans); + + wf_smu_readjust = 0; + new_failure = wf_smu_failure_state & ~last_failure; + + /* If entering failure mode, clamp cpufreq and ramp all + * fans to full speed. + */ + if (wf_smu_failure_state && !last_failure) { + if (cpufreq_clamp) + wf_control_set_max(cpufreq_clamp); + if (fan_cpu_main) + wf_control_set_max(fan_cpu_main); + if (fan_cpu_second) + wf_control_set_max(fan_cpu_second); + if (fan_cpu_third) + wf_control_set_max(fan_cpu_third); + if (fan_hd) + wf_control_set_max(fan_hd); + if (fan_slots) + wf_control_set_max(fan_slots); + } + + /* If leaving failure mode, unclamp cpufreq and readjust + * all fans on next iteration + */ + if (!wf_smu_failure_state && last_failure) { + if (cpufreq_clamp) + wf_control_set_min(cpufreq_clamp); + wf_smu_readjust = 1; + } + + /* Overtemp condition detected, notify and start skipping a couple + * ticks to let the temperature go down + */ + if (new_failure & FAILURE_OVERTEMP) { + wf_set_overtemp(); + wf_smu_skipping = 2; + } + + /* We only clear the overtemp condition if overtemp is cleared + * _and_ no other failure is present. Since a sensor error will + * clear the overtemp condition (can't measure temperature) at + * the control loop levels, but we don't want to keep it clear + * here in this case + */ + if (new_failure == 0 && last_failure & FAILURE_OVERTEMP) + wf_clear_overtemp(); +} + + +static void wf_smu_new_control(struct wf_control *ct) +{ + if (wf_smu_all_controls_ok) + return; + + if (fan_cpu_main == NULL && !strcmp(ct->name, "cpu-rear-fan-0")) { + if (wf_get_control(ct) == 0) { + fan_cpu_main = ct; + device_create_file(wf_smu_dev, &dev_attr_cpu_fan); + } + } + + if (fan_cpu_second == NULL && !strcmp(ct->name, "cpu-rear-fan-1")) { + if (wf_get_control(ct) == 0) + fan_cpu_second = ct; + } + + if (fan_cpu_third == NULL && !strcmp(ct->name, "cpu-front-fan-0")) { + if (wf_get_control(ct) == 0) + fan_cpu_third = ct; + } + + if (cpufreq_clamp == NULL && !strcmp(ct->name, "cpufreq-clamp")) { + if (wf_get_control(ct) == 0) + cpufreq_clamp = ct; + } + + if (fan_hd == NULL && !strcmp(ct->name, "drive-bay-fan")) { + if (wf_get_control(ct) == 0) { + fan_hd = ct; + device_create_file(wf_smu_dev, &dev_attr_hd_fan); + } + } + + if (fan_slots == NULL && !strcmp(ct->name, "slots-fan")) { + if (wf_get_control(ct) == 0) { + fan_slots = ct; + device_create_file(wf_smu_dev, &dev_attr_slots_fan); + } + } + + if (fan_cpu_main && (fan_cpu_second || fan_cpu_third) && fan_hd && + fan_slots && cpufreq_clamp) + wf_smu_all_controls_ok = 1; +} + +static void wf_smu_new_sensor(struct wf_sensor *sr) +{ + if (wf_smu_all_sensors_ok) + return; + + if (sensor_cpu_power == NULL && !strcmp(sr->name, "cpu-power")) { + if (wf_get_sensor(sr) == 0) { + sensor_cpu_power = sr; + device_create_file(wf_smu_dev, &dev_attr_cpu_power); + } + } + + if (sensor_cpu_temp == NULL && !strcmp(sr->name, "cpu-temp")) { + if (wf_get_sensor(sr) == 0) { + sensor_cpu_temp = sr; + device_create_file(wf_smu_dev, &dev_attr_cpu_temp); + } + } + + if (sensor_hd_temp == NULL && !strcmp(sr->name, "hd-temp")) { + if (wf_get_sensor(sr) == 0) { + sensor_hd_temp = sr; + device_create_file(wf_smu_dev, &dev_attr_hd_temp); + } + } + + if (sensor_slots_power == NULL && !strcmp(sr->name, "slots-power")) { + if (wf_get_sensor(sr) == 0) { + sensor_slots_power = sr; + device_create_file(wf_smu_dev, &dev_attr_slots_power); + } + } + + if (sensor_cpu_power && sensor_cpu_temp && + sensor_hd_temp && sensor_slots_power) + wf_smu_all_sensors_ok = 1; +} + + +static int wf_smu_notify(struct notifier_block *self, + unsigned long event, void *data) +{ + switch(event) { + case WF_EVENT_NEW_CONTROL: + DBG("wf: new control %s detected\n", + ((struct wf_control *)data)->name); + wf_smu_new_control(data); + wf_smu_readjust = 1; + break; + case WF_EVENT_NEW_SENSOR: + DBG("wf: new sensor %s detected\n", + ((struct wf_sensor *)data)->name); + wf_smu_new_sensor(data); + break; + case WF_EVENT_TICK: + if (wf_smu_all_controls_ok && wf_smu_all_sensors_ok) + wf_smu_tick(); + } + + return 0; +} + +static struct notifier_block wf_smu_events = { + .notifier_call = wf_smu_notify, +}; + +static int wf_init_pm(void) +{ + printk(KERN_INFO "windfarm: Initializing for Desktop G5 model\n"); + + return 0; +} + +static int wf_smu_probe(struct device *ddev) +{ + wf_smu_dev = ddev; + + wf_register_client(&wf_smu_events); + + return 0; +} + +static int wf_smu_remove(struct device *ddev) +{ + wf_unregister_client(&wf_smu_events); + + /* XXX We don't have yet a guarantee that our callback isn't + * in progress when returning from wf_unregister_client, so + * we add an arbitrary delay. I'll have to fix that in the core + */ + msleep(1000); + + /* Release all sensors */ + /* One more crappy race: I don't think we have any guarantee here + * that the attribute callback won't race with the sensor beeing + * disposed of, and I'm not 100% certain what best way to deal + * with that except by adding locks all over... I'll do that + * eventually but heh, who ever rmmod this module anyway ? + */ + if (sensor_cpu_power) { + device_remove_file(wf_smu_dev, &dev_attr_cpu_power); + wf_put_sensor(sensor_cpu_power); + } + if (sensor_cpu_temp) { + device_remove_file(wf_smu_dev, &dev_attr_cpu_temp); + wf_put_sensor(sensor_cpu_temp); + } + if (sensor_hd_temp) { + device_remove_file(wf_smu_dev, &dev_attr_hd_temp); + wf_put_sensor(sensor_hd_temp); + } + if (sensor_slots_power) { + device_remove_file(wf_smu_dev, &dev_attr_slots_power); + wf_put_sensor(sensor_slots_power); + } + + /* Release all controls */ + if (fan_cpu_main) { + device_remove_file(wf_smu_dev, &dev_attr_cpu_fan); + wf_put_control(fan_cpu_main); + } + if (fan_cpu_second) + wf_put_control(fan_cpu_second); + if (fan_cpu_third) + wf_put_control(fan_cpu_third); + if (fan_hd) { + device_remove_file(wf_smu_dev, &dev_attr_hd_fan); + wf_put_control(fan_hd); + } + if (fan_slots) { + device_remove_file(wf_smu_dev, &dev_attr_slots_fan); + wf_put_control(fan_slots); + } + if (cpufreq_clamp) + wf_put_control(cpufreq_clamp); + + /* Destroy control loops state structures */ + if (wf_smu_slots_fans) + kfree(wf_smu_cpu_fans); + if (wf_smu_drive_fans) + kfree(wf_smu_cpu_fans); + if (wf_smu_cpu_fans) + kfree(wf_smu_cpu_fans); + + wf_smu_dev = NULL; + + return 0; +} + +static struct device_driver wf_smu_driver = { + .name = "windfarm", + .bus = &platform_bus_type, + .probe = wf_smu_probe, + .remove = wf_smu_remove, +}; + + +static int __init wf_smu_init(void) +{ + int rc = -ENODEV; + + if (machine_is_compatible("PowerMac9,1")) + rc = wf_init_pm(); + + if (rc == 0) { +#ifdef MODULE + request_module("windfarm_smu_controls"); + request_module("windfarm_smu_sensors"); + request_module("windfarm_lm75_sensor"); + +#endif /* MODULE */ + driver_register(&wf_smu_driver); + } + + return rc; +} + +static void __exit wf_smu_exit(void) +{ + + driver_unregister(&wf_smu_driver); +} + + +module_init(wf_smu_init); +module_exit(wf_smu_exit); + +MODULE_AUTHOR("Benjamin Herrenschmidt "); +MODULE_DESCRIPTION("Thermal control logic for PowerMac9,1"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c new file mode 100644 index 00000000000..2c3158c81ff --- /dev/null +++ b/drivers/macintosh/windfarm_smu_controls.c @@ -0,0 +1,282 @@ +/* + * Windfarm PowerMac thermal control. SMU based controls + * + * (c) Copyright 2005 Benjamin Herrenschmidt, IBM Corp. + * + * + * Released under the term of the GNU GPL v2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "windfarm.h" + +#define VERSION "0.3" + +#undef DEBUG + +#ifdef DEBUG +#define DBG(args...) printk(args) +#else +#define DBG(args...) do { } while(0) +#endif + +/* + * SMU fans control object + */ + +static LIST_HEAD(smu_fans); + +struct smu_fan_control { + struct list_head link; + int fan_type; /* 0 = rpm, 1 = pwm */ + u32 reg; /* index in SMU */ + s32 value; /* current value */ + s32 min, max; /* min/max values */ + struct wf_control ctrl; +}; +#define to_smu_fan(c) container_of(c, struct smu_fan_control, ctrl) + +static int smu_set_fan(int pwm, u8 id, u16 value) +{ + struct smu_cmd cmd; + u8 buffer[16]; + DECLARE_COMPLETION(comp); + int rc; + + /* Fill SMU command structure */ + cmd.cmd = SMU_CMD_FAN_COMMAND; + cmd.data_len = 14; + cmd.reply_len = 16; + cmd.data_buf = cmd.reply_buf = buffer; + cmd.status = 0; + cmd.done = smu_done_complete; + cmd.misc = ∁ + + /* Fill argument buffer */ + memset(buffer, 0, 16); + buffer[0] = pwm ? 0x10 : 0x00; + buffer[1] = 0x01 << id; + *((u16 *)&buffer[2 + id * 2]) = value; + + rc = smu_queue_cmd(&cmd); + if (rc) + return rc; + wait_for_completion(&comp); + return cmd.status; +} + +static void smu_fan_release(struct wf_control *ct) +{ + struct smu_fan_control *fct = to_smu_fan(ct); + + kfree(fct); +} + +static int smu_fan_set(struct wf_control *ct, s32 value) +{ + struct smu_fan_control *fct = to_smu_fan(ct); + + if (value < fct->min) + value = fct->min; + if (value > fct->max) + value = fct->max; + fct->value = value; + + return smu_set_fan(fct->fan_type, fct->reg, value); +} + +static int smu_fan_get(struct wf_control *ct, s32 *value) +{ + struct smu_fan_control *fct = to_smu_fan(ct); + *value = fct->value; /* todo: read from SMU */ + return 0; +} + +static s32 smu_fan_min(struct wf_control *ct) +{ + struct smu_fan_control *fct = to_smu_fan(ct); + return fct->min; +} + +static s32 smu_fan_max(struct wf_control *ct) +{ + struct smu_fan_control *fct = to_smu_fan(ct); + return fct->max; +} + +static struct wf_control_ops smu_fan_ops = { + .set_value = smu_fan_set, + .get_value = smu_fan_get, + .get_min = smu_fan_min, + .get_max = smu_fan_max, + .release = smu_fan_release, + .owner = THIS_MODULE, +}; + +static struct smu_fan_control *smu_fan_create(struct device_node *node, + int pwm_fan) +{ + struct smu_fan_control *fct; + s32 *v; u32 *reg; + char *l; + + fct = kmalloc(sizeof(struct smu_fan_control), GFP_KERNEL); + if (fct == NULL) + return NULL; + fct->ctrl.ops = &smu_fan_ops; + l = (char *)get_property(node, "location", NULL); + if (l == NULL) + goto fail; + + fct->fan_type = pwm_fan; + fct->ctrl.type = pwm_fan ? WF_CONTROL_PWM_FAN : WF_CONTROL_RPM_FAN; + + /* We use the name & location here the same way we do for SMU sensors, + * see the comment in windfarm_smu_sensors.c. The locations are a bit + * less consistent here between the iMac and the desktop models, but + * that is good enough for our needs for now at least. + * + * One problem though is that Apple seem to be inconsistent with case + * and the kernel doesn't have strcasecmp =P + */ + + fct->ctrl.name = NULL; + + /* Names used on desktop models */ + if (!strcmp(l, "Rear Fan 0") || !strcmp(l, "Rear Fan") || + !strcmp(l, "Rear fan 0") || !strcmp(l, "Rear fan")) + fct->ctrl.name = "cpu-rear-fan-0"; + else if (!strcmp(l, "Rear Fan 1") || !strcmp(l, "Rear fan 1")) + fct->ctrl.name = "cpu-rear-fan-1"; + else if (!strcmp(l, "Front Fan 0") || !strcmp(l, "Front Fan") || + !strcmp(l, "Front fan 0") || !strcmp(l, "Front fan")) + fct->ctrl.name = "cpu-front-fan-0"; + else if (!strcmp(l, "Front Fan 1") || !strcmp(l, "Front fan 1")) + fct->ctrl.name = "cpu-front-fan-1"; + else if (!strcmp(l, "Slots Fan") || !strcmp(l, "Slots fan")) + fct->ctrl.name = "slots-fan"; + else if (!strcmp(l, "Drive Bay") || !strcmp(l, "Drive bay")) + fct->ctrl.name = "drive-bay-fan"; + + /* Names used on iMac models */ + if (!strcmp(l, "System Fan") || !strcmp(l, "System fan")) + fct->ctrl.name = "system-fan"; + else if (!strcmp(l, "CPU Fan") || !strcmp(l, "CPU fan")) + fct->ctrl.name = "cpu-fan"; + else if (!strcmp(l, "Hard Drive") || !strcmp(l, "Hard drive")) + fct->ctrl.name = "drive-bay-fan"; + + /* Unrecognized fan, bail out */ + if (fct->ctrl.name == NULL) + goto fail; + + /* Get min & max values*/ + v = (s32 *)get_property(node, "min-value", NULL); + if (v == NULL) + goto fail; + fct->min = *v; + v = (s32 *)get_property(node, "max-value", NULL); + if (v == NULL) + goto fail; + fct->max = *v; + + /* Get "reg" value */ + reg = (u32 *)get_property(node, "reg", NULL); + if (reg == NULL) + goto fail; + fct->reg = *reg; + + if (wf_register_control(&fct->ctrl)) + goto fail; + + return fct; + fail: + kfree(fct); + return NULL; +} + + +static int __init smu_controls_init(void) +{ + struct device_node *smu, *fans, *fan; + + if (!smu_present()) + return -ENODEV; + + smu = of_find_node_by_type(NULL, "smu"); + if (smu == NULL) + return -ENODEV; + + /* Look for RPM fans */ + for (fans = NULL; (fans = of_get_next_child(smu, fans)) != NULL;) + if (!strcmp(fans->name, "rpm-fans")) + break; + for (fan = NULL; + fans && (fan = of_get_next_child(fans, fan)) != NULL;) { + struct smu_fan_control *fct; + + fct = smu_fan_create(fan, 0); + if (fct == NULL) { + printk(KERN_WARNING "windfarm: Failed to create SMU " + "RPM fan %s\n", fan->name); + continue; + } + list_add(&fct->link, &smu_fans); + } + of_node_put(fans); + + + /* Look for PWM fans */ + for (fans = NULL; (fans = of_get_next_child(smu, fans)) != NULL;) + if (!strcmp(fans->name, "pwm-fans")) + break; + for (fan = NULL; + fans && (fan = of_get_next_child(fans, fan)) != NULL;) { + struct smu_fan_control *fct; + + fct = smu_fan_create(fan, 1); + if (fct == NULL) { + printk(KERN_WARNING "windfarm: Failed to create SMU " + "PWM fan %s\n", fan->name); + continue; + } + list_add(&fct->link, &smu_fans); + } + of_node_put(fans); + of_node_put(smu); + + return 0; +} + +static void __exit smu_controls_exit(void) +{ + struct smu_fan_control *fct; + + while (!list_empty(&smu_fans)) { + fct = list_entry(smu_fans.next, struct smu_fan_control, link); + list_del(&fct->link); + wf_unregister_control(&fct->ctrl); + } +} + + +module_init(smu_controls_init); +module_exit(smu_controls_exit); + +MODULE_AUTHOR("Benjamin Herrenschmidt "); +MODULE_DESCRIPTION("SMU control objects for PowerMacs thermal control"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/macintosh/windfarm_smu_sensors.c b/drivers/macintosh/windfarm_smu_sensors.c new file mode 100644 index 00000000000..b558cc209d4 --- /dev/null +++ b/drivers/macintosh/windfarm_smu_sensors.c @@ -0,0 +1,479 @@ +/* + * Windfarm PowerMac thermal control. SMU based sensors + * + * (c) Copyright 2005 Benjamin Herrenschmidt, IBM Corp. + * + * + * Released under the term of the GNU GPL v2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "windfarm.h" + +#define VERSION "0.2" + +#undef DEBUG + +#ifdef DEBUG +#define DBG(args...) printk(args) +#else +#define DBG(args...) do { } while(0) +#endif + +/* + * Various SMU "partitions" calibration objects for which we + * keep pointers here for use by bits & pieces of the driver + */ +static struct smu_sdbp_cpuvcp *cpuvcp; +static int cpuvcp_version; +static struct smu_sdbp_cpudiode *cpudiode; +static struct smu_sdbp_slotspow *slotspow; +static u8 *debugswitches; + +/* + * SMU basic sensors objects + */ + +static LIST_HEAD(smu_ads); + +struct smu_ad_sensor { + struct list_head link; + u32 reg; /* index in SMU */ + struct wf_sensor sens; +}; +#define to_smu_ads(c) container_of(c, struct smu_ad_sensor, sens) + +static void smu_ads_release(struct wf_sensor *sr) +{ + struct smu_ad_sensor *ads = to_smu_ads(sr); + + kfree(ads); +} + +static int smu_read_adc(u8 id, s32 *value) +{ + struct smu_simple_cmd cmd; + DECLARE_COMPLETION(comp); + int rc; + + rc = smu_queue_simple(&cmd, SMU_CMD_READ_ADC, 1, + smu_done_complete, &comp, id); + if (rc) + return rc; + wait_for_completion(&comp); + if (cmd.cmd.status != 0) + return cmd.cmd.status; + if (cmd.cmd.reply_len != 2) { + printk(KERN_ERR "winfarm: read ADC 0x%x returned %d bytes !\n", + id, cmd.cmd.reply_len); + return -EIO; + } + *value = *((u16 *)cmd.buffer); + return 0; +} + +static int smu_cputemp_get(struct wf_sensor *sr, s32 *value) +{ + struct smu_ad_sensor *ads = to_smu_ads(sr); + int rc; + s32 val; + s64 scaled; + + rc = smu_read_adc(ads->reg, &val); + if (rc) { + printk(KERN_ERR "windfarm: read CPU temp failed, err %d\n", + rc); + return rc; + } + + /* Ok, we have to scale & adjust, taking units into account */ + scaled = (s64)(((u64)val) * (u64)cpudiode->m_value); + scaled >>= 3; + scaled += ((s64)cpudiode->b_value) << 9; + *value = (s32)(scaled << 1); + + return 0; +} + +static int smu_cpuamp_get(struct wf_sensor *sr, s32 *value) +{ + struct smu_ad_sensor *ads = to_smu_ads(sr); + s32 val, scaled; + int rc; + + rc = smu_read_adc(ads->reg, &val); + if (rc) { + printk(KERN_ERR "windfarm: read CPU current failed, err %d\n", + rc); + return rc; + } + + /* Ok, we have to scale & adjust, taking units into account */ + scaled = (s32)(val * (u32)cpuvcp->curr_scale); + scaled += (s32)cpuvcp->curr_offset; + *value = scaled << 4; + + return 0; +} + +static int smu_cpuvolt_get(struct wf_sensor *sr, s32 *value) +{ + struct smu_ad_sensor *ads = to_smu_ads(sr); + s32 val, scaled; + int rc; + + rc = smu_read_adc(ads->reg, &val); + if (rc) { + printk(KERN_ERR "windfarm: read CPU voltage failed, err %d\n", + rc); + return rc; + } + + /* Ok, we have to scale & adjust, taking units into account */ + scaled = (s32)(val * (u32)cpuvcp->volt_scale); + scaled += (s32)cpuvcp->volt_offset; + *value = scaled << 4; + + return 0; +} + +static int smu_slotspow_get(struct wf_sensor *sr, s32 *value) +{ + struct smu_ad_sensor *ads = to_smu_ads(sr); + s32 val, scaled; + int rc; + + rc = smu_read_adc(ads->reg, &val); + if (rc) { + printk(KERN_ERR "windfarm: read slots power failed, err %d\n", + rc); + return rc; + } + + /* Ok, we have to scale & adjust, taking units into account */ + scaled = (s32)(val * (u32)slotspow->pow_scale); + scaled += (s32)slotspow->pow_offset; + *value = scaled << 4; + + return 0; +} + + +static struct wf_sensor_ops smu_cputemp_ops = { + .get_value = smu_cputemp_get, + .release = smu_ads_release, + .owner = THIS_MODULE, +}; +static struct wf_sensor_ops smu_cpuamp_ops = { + .get_value = smu_cpuamp_get, + .release = smu_ads_release, + .owner = THIS_MODULE, +}; +static struct wf_sensor_ops smu_cpuvolt_ops = { + .get_value = smu_cpuvolt_get, + .release = smu_ads_release, + .owner = THIS_MODULE, +}; +static struct wf_sensor_ops smu_slotspow_ops = { + .get_value = smu_slotspow_get, + .release = smu_ads_release, + .owner = THIS_MODULE, +}; + + +static struct smu_ad_sensor *smu_ads_create(struct device_node *node) +{ + struct smu_ad_sensor *ads; + char *c, *l; + u32 *v; + + ads = kmalloc(sizeof(struct smu_ad_sensor), GFP_KERNEL); + if (ads == NULL) + return NULL; + c = (char *)get_property(node, "device_type", NULL); + l = (char *)get_property(node, "location", NULL); + if (c == NULL || l == NULL) + goto fail; + + /* We currently pick the sensors based on the OF name and location + * properties, while Darwin uses the sensor-id's. + * The problem with the IDs is that they are model specific while it + * looks like apple has been doing a reasonably good job at keeping + * the names and locations consistents so I'll stick with the names + * and locations for now. + */ + if (!strcmp(c, "temp-sensor") && + !strcmp(l, "CPU T-Diode")) { + ads->sens.ops = &smu_cputemp_ops; + ads->sens.name = "cpu-temp"; + } else if (!strcmp(c, "current-sensor") && + !strcmp(l, "CPU Current")) { + ads->sens.ops = &smu_cpuamp_ops; + ads->sens.name = "cpu-current"; + } else if (!strcmp(c, "voltage-sensor") && + !strcmp(l, "CPU Voltage")) { + ads->sens.ops = &smu_cpuvolt_ops; + ads->sens.name = "cpu-voltage"; + } else if (!strcmp(c, "power-sensor") && + !strcmp(l, "Slots Power")) { + ads->sens.ops = &smu_slotspow_ops; + ads->sens.name = "slots-power"; + if (slotspow == NULL) { + DBG("wf: slotspow partition (%02x) not found\n", + SMU_SDB_SLOTSPOW_ID); + goto fail; + } + } else + goto fail; + + v = (u32 *)get_property(node, "reg", NULL); + if (v == NULL) + goto fail; + ads->reg = *v; + + if (wf_register_sensor(&ads->sens)) + goto fail; + return ads; + fail: + kfree(ads); + return NULL; +} + +/* + * SMU Power combo sensor object + */ + +struct smu_cpu_power_sensor { + struct list_head link; + struct wf_sensor *volts; + struct wf_sensor *amps; + int fake_volts : 1; + int quadratic : 1; + struct wf_sensor sens; +}; +#define to_smu_cpu_power(c) container_of(c, struct smu_cpu_power_sensor, sens) + +static struct smu_cpu_power_sensor *smu_cpu_power; + +static void smu_cpu_power_release(struct wf_sensor *sr) +{ + struct smu_cpu_power_sensor *pow = to_smu_cpu_power(sr); + + if (pow->volts) + wf_put_sensor(pow->volts); + if (pow->amps) + wf_put_sensor(pow->amps); + kfree(pow); +} + +static int smu_cpu_power_get(struct wf_sensor *sr, s32 *value) +{ + struct smu_cpu_power_sensor *pow = to_smu_cpu_power(sr); + s32 volts, amps, power; + u64 tmps, tmpa, tmpb; + int rc; + + rc = pow->amps->ops->get_value(pow->amps, &s); + if (rc) + return rc; + + if (pow->fake_volts) { + *value = amps * 12 - 0x30000; + return 0; + } + + rc = pow->volts->ops->get_value(pow->volts, &volts); + if (rc) + return rc; + + power = (s32)((((u64)volts) * ((u64)amps)) >> 16); + if (!pow->quadratic) { + *value = power; + return 0; + } + tmps = (((u64)power) * ((u64)power)) >> 16; + tmpa = ((u64)cpuvcp->power_quads[0]) * tmps; + tmpb = ((u64)cpuvcp->power_quads[1]) * ((u64)power); + *value = (tmpa >> 28) + (tmpb >> 28) + (cpuvcp->power_quads[2] >> 12); + + return 0; +} + +static struct wf_sensor_ops smu_cpu_power_ops = { + .get_value = smu_cpu_power_get, + .release = smu_cpu_power_release, + .owner = THIS_MODULE, +}; + + +static struct smu_cpu_power_sensor * +smu_cpu_power_create(struct wf_sensor *volts, struct wf_sensor *amps) +{ + struct smu_cpu_power_sensor *pow; + + pow = kmalloc(sizeof(struct smu_cpu_power_sensor), GFP_KERNEL); + if (pow == NULL) + return NULL; + pow->sens.ops = &smu_cpu_power_ops; + pow->sens.name = "cpu-power"; + + wf_get_sensor(volts); + pow->volts = volts; + wf_get_sensor(amps); + pow->amps = amps; + + /* Some early machines need a faked voltage */ + if (debugswitches && ((*debugswitches) & 0x80)) { + printk(KERN_INFO "windfarm: CPU Power sensor using faked" + " voltage !\n"); + pow->fake_volts = 1; + } else + pow->fake_volts = 0; + + /* Try to use quadratic transforms on PowerMac8,1 and 9,1 for now, + * I yet have to figure out what's up with 8,2 and will have to + * adjust for later, unless we can 100% trust the SDB partition... + */ + if ((machine_is_compatible("PowerMac8,1") || + machine_is_compatible("PowerMac8,2") || + machine_is_compatible("PowerMac9,1")) && + cpuvcp_version >= 2) { + pow->quadratic = 1; + DBG("windfarm: CPU Power using quadratic transform\n"); + } else + pow->quadratic = 0; + + if (wf_register_sensor(&pow->sens)) + goto fail; + return pow; + fail: + kfree(pow); + return NULL; +} + +static int smu_fetch_param_partitions(void) +{ + struct smu_sdbp_header *hdr; + + /* Get CPU voltage/current/power calibration data */ + hdr = smu_get_sdb_partition(SMU_SDB_CPUVCP_ID, NULL); + if (hdr == NULL) { + DBG("wf: cpuvcp partition (%02x) not found\n", + SMU_SDB_CPUVCP_ID); + return -ENODEV; + } + cpuvcp = (struct smu_sdbp_cpuvcp *)&hdr[1]; + /* Keep version around */ + cpuvcp_version = hdr->version; + + /* Get CPU diode calibration data */ + hdr = smu_get_sdb_partition(SMU_SDB_CPUDIODE_ID, NULL); + if (hdr == NULL) { + DBG("wf: cpudiode partition (%02x) not found\n", + SMU_SDB_CPUDIODE_ID); + return -ENODEV; + } + cpudiode = (struct smu_sdbp_cpudiode *)&hdr[1]; + + /* Get slots power calibration data if any */ + hdr = smu_get_sdb_partition(SMU_SDB_SLOTSPOW_ID, NULL); + if (hdr != NULL) + slotspow = (struct smu_sdbp_slotspow *)&hdr[1]; + + /* Get debug switches if any */ + hdr = smu_get_sdb_partition(SMU_SDB_DEBUG_SWITCHES_ID, NULL); + if (hdr != NULL) + debugswitches = (u8 *)&hdr[1]; + + return 0; +} + +static int __init smu_sensors_init(void) +{ + struct device_node *smu, *sensors, *s; + struct smu_ad_sensor *volt_sensor = NULL, *curr_sensor = NULL; + int rc; + + if (!smu_present()) + return -ENODEV; + + /* Get parameters partitions */ + rc = smu_fetch_param_partitions(); + if (rc) + return rc; + + smu = of_find_node_by_type(NULL, "smu"); + if (smu == NULL) + return -ENODEV; + + /* Look for sensors subdir */ + for (sensors = NULL; + (sensors = of_get_next_child(smu, sensors)) != NULL;) + if (!strcmp(sensors->name, "sensors")) + break; + + of_node_put(smu); + + /* Create basic sensors */ + for (s = NULL; + sensors && (s = of_get_next_child(sensors, s)) != NULL;) { + struct smu_ad_sensor *ads; + + ads = smu_ads_create(s); + if (ads == NULL) + continue; + list_add(&ads->link, &smu_ads); + /* keep track of cpu voltage & current */ + if (!strcmp(ads->sens.name, "cpu-voltage")) + volt_sensor = ads; + else if (!strcmp(ads->sens.name, "cpu-current")) + curr_sensor = ads; + } + + of_node_put(sensors); + + /* Create CPU power sensor if possible */ + if (volt_sensor && curr_sensor) + smu_cpu_power = smu_cpu_power_create(&volt_sensor->sens, + &curr_sensor->sens); + + return 0; +} + +static void __exit smu_sensors_exit(void) +{ + struct smu_ad_sensor *ads; + + /* dispose of power sensor */ + if (smu_cpu_power) + wf_unregister_sensor(&smu_cpu_power->sens); + + /* dispose of basic sensors */ + while (!list_empty(&smu_ads)) { + ads = list_entry(smu_ads.next, struct smu_ad_sensor, link); + list_del(&ads->link); + wf_unregister_sensor(&ads->sens); + } +} + + +module_init(smu_sensors_init); +module_exit(smu_sensors_exit); + +MODULE_AUTHOR("Benjamin Herrenschmidt "); +MODULE_DESCRIPTION("SMU sensor objects for PowerMacs thermal control"); +MODULE_LICENSE("GPL"); + -- cgit v1.2.3 From 21fe3301f11a93c4f18e8480ed08522559bf0a50 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 7 Nov 2005 16:41:59 +1100 Subject: [PATCH] ppc: fix a bunch of warnings Building a PowerMac kernel with ARCH=powerpc causes a bunch of warnings, this fixes some of them Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom_init.c | 9 +++++---- arch/powerpc/kernel/rtas.c | 3 ++- drivers/macintosh/via-pmu.c | 6 +++--- include/asm-powerpc/xmon.h | 1 + include/asm-ppc/btext.h | 22 +++++++++++----------- 5 files changed, 22 insertions(+), 19 deletions(-) diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 0d91961f943..6dc33d19fc2 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -403,19 +403,19 @@ static int __init prom_next_node(phandle *nodep) } } -static int __init prom_getprop(phandle node, const char *pname, +static int inline prom_getprop(phandle node, const char *pname, void *value, size_t valuelen) { return call_prom("getprop", 4, 1, node, ADDR(pname), (u32)(unsigned long) value, (u32) valuelen); } -static int __init prom_getproplen(phandle node, const char *pname) +static int inline prom_getproplen(phandle node, const char *pname) { return call_prom("getproplen", 2, 1, node, ADDR(pname)); } -static int __init prom_setprop(phandle node, const char *pname, +static int inline prom_setprop(phandle node, const char *pname, void *value, size_t valuelen) { return call_prom("setprop", 4, 1, node, ADDR(pname), @@ -1408,8 +1408,9 @@ static int __init prom_find_machine_type(void) struct prom_t *_prom = &RELOC(prom); char compat[256]; int len, i = 0; +#ifdef CONFIG_PPC64 phandle rtas; - +#endif len = prom_getprop(_prom->root, "compatible", compat, sizeof(compat)-1); if (len > 0) { diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 751f5ddea91..9d4e07f6f1e 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -83,7 +84,7 @@ void call_rtas_display_status_delay(unsigned char c) while (width-- > 0) call_rtas_display_status(' '); width = 16; - udelay(500000); + mdelay(500); pending_newline = 1; } else { if (pending_newline) { diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 9bc6cc6e384..7ebbc0f5342 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -2667,10 +2667,10 @@ powerbook_sleep_3400(void) asleep = 1; /* Put the CPU into sleep mode */ - asm volatile("mfspr %0,1008" : "=r" (hid0) :); + hid0 = mfspr(SPRN_HID0); hid0 = (hid0 & ~(HID0_NAP | HID0_DOZE)) | HID0_SLEEP; - asm volatile("mtspr 1008,%0" : : "r" (hid0)); - _nmask_and_or_msr(0, MSR_POW | MSR_EE); + mtspr(SPRN_HID0, hid0); + mtmsr(mfmsr() | MSR_POW | MSR_EE); udelay(10); /* OK, we're awake again, start restoring things */ diff --git a/include/asm-powerpc/xmon.h b/include/asm-powerpc/xmon.h index 43f7129984c..ace2072d4a8 100644 --- a/include/asm-powerpc/xmon.h +++ b/include/asm-powerpc/xmon.h @@ -7,6 +7,7 @@ struct pt_regs; extern int xmon(struct pt_regs *excp); extern void xmon_printf(const char *fmt, ...); extern void xmon_init(int); +extern void xmon_map_scc(void); #endif #endif diff --git a/include/asm-ppc/btext.h b/include/asm-ppc/btext.h index 36c7640d00f..ccaefabe0bf 100644 --- a/include/asm-ppc/btext.h +++ b/include/asm-ppc/btext.h @@ -17,18 +17,18 @@ extern unsigned long disp_BAT[2]; extern boot_infos_t disp_bi; extern int boot_text_mapped; -void btext_init(boot_infos_t *bi); -void btext_welcome(void); -void btext_prepare_BAT(void); -void btext_setup_display(int width, int height, int depth, int pitch, - unsigned long address); -void map_boot_text(void); -void btext_update_display(unsigned long phys, int width, int height, - int depth, int pitch); +extern void init_boot_display(void); +extern void btext_welcome(void); +extern void btext_prepare_BAT(void); +extern void btext_setup_display(int width, int height, int depth, int pitch, + unsigned long address); +extern void map_boot_text(void); +extern void btext_update_display(unsigned long phys, int width, int height, + int depth, int pitch); -void btext_drawchar(char c); -void btext_drawstring(const char *str); -void btext_drawhex(unsigned long v); +extern void btext_drawchar(char c); +extern void btext_drawstring(const char *str); +extern void btext_drawhex(unsigned long v); #endif /* __KERNEL__ */ #endif /* __PPC_BTEXT_H */ -- cgit v1.2.3 From 7b007de8a90604000329154e87d269db3427d099 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 7 Nov 2005 16:43:44 +1100 Subject: [PATCH] ppc: Fix ARCH=ppc build with xmon xmon() prototype is inconsistent between ARCH=ppc and ARCH=powerpc, thus causing ARCH=ppc build breakage. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/ppc/kernel/traps.c | 4 ++-- arch/ppc/xmon/xmon.c | 5 +++-- include/asm-ppc/kgdb.h | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 42d980e82bd..9dbc4d28fa2 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -49,7 +49,7 @@ extern int xmon_sstep(struct pt_regs *regs); extern int xmon_iabr_match(struct pt_regs *regs); extern int xmon_dabr_match(struct pt_regs *regs); -void (*debugger)(struct pt_regs *regs) = xmon; +int (*debugger)(struct pt_regs *regs) = xmon; int (*debugger_bpt)(struct pt_regs *regs) = xmon_bpt; int (*debugger_sstep)(struct pt_regs *regs) = xmon_sstep; int (*debugger_iabr_match)(struct pt_regs *regs) = xmon_iabr_match; @@ -57,7 +57,7 @@ int (*debugger_dabr_match)(struct pt_regs *regs) = xmon_dabr_match; void (*debugger_fault_handler)(struct pt_regs *regs); #else #ifdef CONFIG_KGDB -void (*debugger)(struct pt_regs *regs); +int (*debugger)(struct pt_regs *regs); int (*debugger_bpt)(struct pt_regs *regs); int (*debugger_sstep)(struct pt_regs *regs); int (*debugger_iabr_match)(struct pt_regs *regs); diff --git a/arch/ppc/xmon/xmon.c b/arch/ppc/xmon/xmon.c index 66bfaa3211a..2b483b4f160 100644 --- a/arch/ppc/xmon/xmon.c +++ b/arch/ppc/xmon/xmon.c @@ -220,8 +220,7 @@ static void get_tb(unsigned *p) p[1] = lo; } -void -xmon(struct pt_regs *excp) +int xmon(struct pt_regs *excp) { struct pt_regs regs; int msr, cmd; @@ -290,6 +289,8 @@ xmon(struct pt_regs *excp) #endif /* CONFIG_SMP */ set_msr(msr); /* restore interrupt enable */ get_tb(start_tb[smp_processor_id()]); + + return cmd != 'X'; } irqreturn_t diff --git a/include/asm-ppc/kgdb.h b/include/asm-ppc/kgdb.h index 1d3c927ce62..b617dac8296 100644 --- a/include/asm-ppc/kgdb.h +++ b/include/asm-ppc/kgdb.h @@ -31,7 +31,7 @@ extern void breakpoint(void); /* For taking exceptions * these are defined in traps.c */ -extern void (*debugger)(struct pt_regs *regs); +extern int (*debugger)(struct pt_regs *regs); extern int (*debugger_bpt)(struct pt_regs *regs); extern int (*debugger_sstep)(struct pt_regs *regs); extern int (*debugger_iabr_match)(struct pt_regs *regs); -- cgit v1.2.3 From 42596ec5edc8efb9e24397ef656df7ebb2c4f8d5 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 7 Nov 2005 16:57:33 +1100 Subject: [PATCH] ppc: Fix PowerBook HD led on ARCH=powerpc The PowerBook HD led code uses obsoletes device-tree accessors which do not work anymore for getting the root of the tree. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- drivers/ide/ppc/pmac.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index d8c3d8ebad3..b3e65a65d20 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -497,16 +497,19 @@ pmu_hd_blink_init(void) if (pmu_get_model() != PMU_KEYLARGO_BASED) return 0; - dt = find_devices("device-tree"); + dt = of_find_node_by_path("/"); if (dt == NULL) return 0; model = (const char *)get_property(dt, "model", NULL); if (model == NULL) return 0; if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 && - strncmp(model, "iBook", strlen("iBook")) != 0) + strncmp(model, "iBook", strlen("iBook")) != 0) { + of_node_put(dt); return 0; - + } + of_node_put(dt); + pmu_blink_on.complete = 1; pmu_blink_off.complete = 1; spin_lock_init(&pmu_blink_lock); -- cgit v1.2.3 From bcb3557694d4e880051795ad97d609d255bcb658 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 7 Nov 2005 17:43:07 +1100 Subject: [PATCH] ppc64: fix Memory: summary line On ppc64 we end up with a negative value for the data size in the memory boot message: Memory: 2035560k/2097152k available (5792k kernel code, 89564k reserved, 18014398509481632k data, 870k bss, 352k init) It turns out the section ordering of the linker script is different on ppc32 and ppc64, so just count data as _edata - _sdata which should work on both. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/mm/mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 7faa46b71f2..6f55efd9be9 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -358,7 +358,7 @@ void __init mem_init(void) } codesize = (unsigned long)&_sdata - (unsigned long)&_stext; - datasize = (unsigned long)&__init_begin - (unsigned long)&_sdata; + datasize = (unsigned long)&_edata - (unsigned long)&_sdata; initsize = (unsigned long)&__init_end - (unsigned long)&__init_begin; bsssize = (unsigned long)&__bss_stop - (unsigned long)&__bss_start; -- cgit v1.2.3 From cb09cff30ad22408eea9b2785555af2d2b0ac1bd Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 7 Nov 2005 18:43:56 +1100 Subject: [PATCH] ppc64: fix oprofile sample bit handling Oprofile was hardwiring the MMCRA sample bit to 1 but on newer cpus (eg POWER5) we want to vary it based on the group being sampled. Add a temporary workaround until people update their oprofile userspace. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/oprofile/op_model_power4.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c index 88644931584..c4ee5478427 100644 --- a/arch/powerpc/oprofile/op_model_power4.c +++ b/arch/powerpc/oprofile/op_model_power4.c @@ -17,6 +17,7 @@ #include #include #include +#include #define dbg(args...) @@ -81,6 +82,26 @@ static void power4_reg_setup(struct op_counter_config *ctr, extern void ppc64_enable_pmcs(void); +/* + * Older CPUs require the MMCRA sample bit to be always set, but newer + * CPUs only want it set for some groups. Eventually we will remove all + * knowledge of this bit in the kernel, oprofile userspace should be + * setting it when required. + * + * In order to keep current installations working we force the bit for + * those older CPUs. Once everyone has updated their oprofile userspace we + * can remove this hack. + */ +static inline int mmcra_must_set_sample(void) +{ + if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p) || + __is_processor(PV_970) || __is_processor(PV_970FX) || + __is_processor(PV_970MP)) + return 1; + + return 0; +} + static void power4_cpu_setup(void *unused) { unsigned int mmcr0 = mmcr0_val; @@ -98,7 +119,8 @@ static void power4_cpu_setup(void *unused) mtspr(SPRN_MMCR1, mmcr1_val); - mmcra |= MMCRA_SAMPLE_ENABLE; + if (mmcra_must_set_sample()) + mmcra |= MMCRA_SAMPLE_ENABLE; mtspr(SPRN_MMCRA, mmcra); dbg("setup on cpu %d, mmcr0 %lx\n", smp_processor_id(), -- cgit v1.2.3 From 570142ca37248291c03df9852a5a0ce97f756464 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 7 Nov 2005 19:05:31 +1100 Subject: [PATCH] ppc64: remove some direct xmon calls Even though we can enable and disable xmon at runtime now, there are a few places in the merge tree that call xmon and xmon_printf directly. In the case below we call die() which will call xmon if it is enabled. Also remove an unnecessary include of xmon.h in smp.c. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/smp.c | 1 - arch/powerpc/kernel/traps.c | 11 ----------- 2 files changed, 12 deletions(-) diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 1794a694a92..5c330c3366e 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 07e5ee40b87..32f215825e8 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #ifdef CONFIG_PPC32 #include @@ -748,22 +747,12 @@ static int check_bug_trap(struct pt_regs *regs) return 0; if (bug->line & BUG_WARNING_TRAP) { /* this is a WARN_ON rather than BUG/BUG_ON */ -#ifdef CONFIG_XMON - xmon_printf(KERN_ERR "Badness in %s at %s:%ld\n", - bug->function, bug->file, - bug->line & ~BUG_WARNING_TRAP); -#endif /* CONFIG_XMON */ printk(KERN_ERR "Badness in %s at %s:%ld\n", bug->function, bug->file, bug->line & ~BUG_WARNING_TRAP); dump_stack(); return 1; } -#ifdef CONFIG_XMON - xmon_printf(KERN_CRIT "kernel BUG in %s at %s:%ld!\n", - bug->function, bug->file, bug->line); - xmon(regs); -#endif /* CONFIG_XMON */ printk(KERN_CRIT "kernel BUG in %s at %s:%ld!\n", bug->function, bug->file, bug->line); -- cgit v1.2.3 From 0286486783a75ef991df3ee250917efb55df75b3 Mon Sep 17 00:00:00 2001 From: Mike Kravetz Date: Mon, 7 Nov 2005 13:48:59 -0800 Subject: [PATCH] Memory Add Fixes for ppc64 On Tue, Nov 08, 2005 at 08:12:56AM +1100, Benjamin Herrenschmidt wrote: > Yes, the MAX_ORDER should be different indeed. But can Kconfig do that ? > That is have the default value be different based on a Kconfig option ? > I don't see that ... We may have to do things differently here... This seems to be done in other parts of the Kconfig file. Using those as an example, this should keep the MAX_ORDER block size at 16MB. Signed-off-by: Mike Kravetz Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 1 + arch/ppc64/Kconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 3ac9195dab3..1493c7896fe 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -492,6 +492,7 @@ source "fs/Kconfig.binfmt" config FORCE_MAX_ZONEORDER int depends on PPC64 + default "9" if PPC_64K_PAGES default "13" config MATH_EMULATION diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig index 94a81279dea..29552348e58 100644 --- a/arch/ppc64/Kconfig +++ b/arch/ppc64/Kconfig @@ -56,6 +56,7 @@ config PPC_STD_MMU # max order + 1 config FORCE_MAX_ZONEORDER int + default "9" if PPC_64K_PAGES default "13" source "init/Kconfig" -- cgit v1.2.3 From 826d2abe9945372c8838398bfd88a1caa5844d41 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Mon, 7 Nov 2005 18:56:59 -0600 Subject: Updated READMEs and MAINTAINERS for the ipw2100 and ipw2200 drivers. Signed-off-by: James Ketrenos --- Documentation/networking/README.ipw2100 | 132 ++++++++++++++------- Documentation/networking/README.ipw2200 | 196 ++++++++++++++++++++++++++------ MAINTAINERS | 18 +++ 3 files changed, 272 insertions(+), 74 deletions(-) diff --git a/Documentation/networking/README.ipw2100 b/Documentation/networking/README.ipw2100 index 2046948b020..3ab40379d1c 100644 --- a/Documentation/networking/README.ipw2100 +++ b/Documentation/networking/README.ipw2100 @@ -1,27 +1,82 @@ -=========================== -Intel(R) PRO/Wireless 2100 Network Connection Driver for Linux +Intel(R) PRO/Wireless 2100 Driver for Linux in support of: + +Intel(R) PRO/Wireless 2100 Network Connection + +Copyright (C) 2003-2005, Intel Corporation + README.ipw2100 -March 14, 2005 +Version: 1.1.3 +Date : October 17, 2005 -=========================== Index ---------------------------- -0. Introduction -1. Release 1.1.0 Current Features -2. Command Line Parameters -3. Sysfs Helper Files -4. Radio Kill Switch -5. Dynamic Firmware -6. Power Management -7. Support -8. License - - -=========================== -0. Introduction ------------- ----- ----- ---- --- -- - +----------------------------------------------- +0. IMPORTANT INFORMATION BEFORE USING THIS DRIVER +1. Introduction +2. Release 1.1.3 Current Features +3. Command Line Parameters +4. Sysfs Helper Files +5. Radio Kill Switch +6. Dynamic Firmware +7. Power Management +8. Support +9. License + + +0. IMPORTANT INFORMATION BEFORE USING THIS DRIVER +----------------------------------------------- + +Important Notice FOR ALL USERS OR DISTRIBUTORS!!!! + +Intel wireless LAN adapters are engineered, manufactured, tested, and +quality checked to ensure that they meet all necessary local and +governmental regulatory agency requirements for the regions that they +are designated and/or marked to ship into. Since wireless LANs are +generally unlicensed devices that share spectrum with radars, +satellites, and other licensed and unlicensed devices, it is sometimes +necessary to dynamically detect, avoid, and limit usage to avoid +interference with these devices. In many instances Intel is required to +provide test data to prove regional and local compliance to regional and +governmental regulations before certification or approval to use the +product is granted. Intel's wireless LAN's EEPROM, firmware, and +software driver are designed to carefully control parameters that affect +radio operation and to ensure electromagnetic compliance (EMC). These +parameters include, without limitation, RF power, spectrum usage, +channel scanning, and human exposure. + +For these reasons Intel cannot permit any manipulation by third parties +of the software provided in binary format with the wireless WLAN +adapters (e.g., the EEPROM and firmware). Furthermore, if you use any +patches, utilities, or code with the Intel wireless LAN adapters that +have been manipulated by an unauthorized party (i.e., patches, +utilities, or code (including open source code modifications) which have +not been validated by Intel), (i) you will be solely responsible for +ensuring the regulatory compliance of the products, (ii) Intel will bear +no liability, under any theory of liability for any issues associated +with the modified products, including without limitation, claims under +the warranty and/or issues arising from regulatory non-compliance, and +(iii) Intel will not provide or be required to assist in providing +support to any third parties for such modified products. + +Note: Many regulatory agencies consider Wireless LAN adapters to be +modules, and accordingly, condition system-level regulatory approval +upon receipt and review of test data documenting that the antennas and +system configuration do not cause the EMC and radio operation to be +non-compliant. + +The drivers available for download from SourceForge are provided as a +part of a development project. Conformance to local regulatory +requirements is the responsibility of the individual developer. As +such, if you are interested in deploying or shipping a driver as part of +solution intended to be used for purposes other than development, please +obtain a tested driver from Intel Customer Support at: + +http://support.intel.com/support/notebook/sb/CS-006408.htm + + +1. Introduction +----------------------------------------------- This document provides a brief overview of the features supported by the IPW2100 driver project. The main project website, where the latest @@ -34,9 +89,8 @@ potential fixes and patches, as well as links to the development mailing list for the driver project. -=========================== -1. Release 1.1.0 Current Supported Features ---------------------------- +2. Release 1.1.3 Current Supported Features +----------------------------------------------- - Managed (BSS) and Ad-Hoc (IBSS) - WEP (shared key and open) - Wireless Tools support @@ -51,9 +105,8 @@ on the amount of validation and interoperability testing that has been performed on a given feature. -=========================== -2. Command Line Parameters ---------------------------- +3. Command Line Parameters +----------------------------------------------- If the driver is built as a module, the following optional parameters are used by entering them on the command line with the modprobe command using this @@ -75,9 +128,9 @@ associate boolean associate=0 /* Do NOT auto associate */ disable boolean disable=1 /* Do not power the HW */ -=========================== -3. Sysfs Helper Files +4. Sysfs Helper Files --------------------------- +----------------------------------------------- There are several ways to control the behavior of the driver. Many of the general capabilities are exposed through the Wireless Tools (iwconfig). There @@ -120,9 +173,8 @@ For the device level files, see /sys/bus/pci/drivers/ipw2100: based RF kill from ON -> OFF -> ON, the radio will NOT come back on -=========================== -4. Radio Kill Switch ---------------------------- +5. Radio Kill Switch +----------------------------------------------- Most laptops provide the ability for the user to physically disable the radio. Some vendors have implemented this as a physical switch that requires no software to turn the radio off and on. On other laptops, however, the switch @@ -134,9 +186,8 @@ See the Sysfs helper file 'rf_kill' for determining the state of the RF switch on your system. -=========================== -5. Dynamic Firmware ---------------------------- +6. Dynamic Firmware +----------------------------------------------- As the firmware is licensed under a restricted use license, it can not be included within the kernel sources. To enable the IPW2100 you will need a firmware image to load into the wireless NIC's processors. @@ -146,9 +197,8 @@ You can obtain these images from . See INSTALL for instructions on installing the firmware. -=========================== -6. Power Management ---------------------------- +7. Power Management +----------------------------------------------- The IPW2100 supports the configuration of the Power Save Protocol through a private wireless extension interface. The IPW2100 supports the following different modes: @@ -200,9 +250,8 @@ xxxx/yyyy will be replaced with 'off' -- the level reported will be the active level if `iwconfig eth1 power on` is invoked. -=========================== -7. Support ---------------------------- +8. Support +----------------------------------------------- For general development information and support, go to: @@ -218,9 +267,8 @@ For installation support on the ipw2100 1.1.0 driver on Linux kernels http://supportmail.intel.com -=========================== -8. License ---------------------------- +9. License +----------------------------------------------- Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved. diff --git a/Documentation/networking/README.ipw2200 b/Documentation/networking/README.ipw2200 index 6916080c5f0..c6492d3839f 100644 --- a/Documentation/networking/README.ipw2200 +++ b/Documentation/networking/README.ipw2200 @@ -1,33 +1,89 @@ Intel(R) PRO/Wireless 2915ABG Driver for Linux in support of: -Intel(R) PRO/Wireless 2200BG Network Connection -Intel(R) PRO/Wireless 2915ABG Network Connection +Intel(R) PRO/Wireless 2200BG Network Connection +Intel(R) PRO/Wireless 2915ABG Network Connection -Note: The Intel(R) PRO/Wireless 2915ABG Driver for Linux and Intel(R) -PRO/Wireless 2200BG Driver for Linux is a unified driver that works on -both hardware adapters listed above. In this document the Intel(R) -PRO/Wireless 2915ABG Driver for Linux will be used to reference the +Note: The Intel(R) PRO/Wireless 2915ABG Driver for Linux and Intel(R) +PRO/Wireless 2200BG Driver for Linux is a unified driver that works on +both hardware adapters listed above. In this document the Intel(R) +PRO/Wireless 2915ABG Driver for Linux will be used to reference the unified driver. Copyright (C) 2004-2005, Intel Corporation README.ipw2200 -Version: 1.0.0 -Date : January 31, 2005 +Version: 1.0.8 +Date : October 20, 2005 Index ----------------------------------------------- +0. IMPORTANT INFORMATION BEFORE USING THIS DRIVER 1. Introduction 1.1. Overview of features 1.2. Module parameters 1.3. Wireless Extension Private Methods 1.4. Sysfs Helper Files -2. About the Version Numbers -3. Support -4. License +2. Ad-Hoc Networking +3. Interacting with Wireless Tools +3.1. iwconfig mode +4. About the Version Numbers +5. Firmware installation +6. Support +7. License + + +0. IMPORTANT INFORMATION BEFORE USING THIS DRIVER +----------------------------------------------- + +Important Notice FOR ALL USERS OR DISTRIBUTORS!!!! + +Intel wireless LAN adapters are engineered, manufactured, tested, and +quality checked to ensure that they meet all necessary local and +governmental regulatory agency requirements for the regions that they +are designated and/or marked to ship into. Since wireless LANs are +generally unlicensed devices that share spectrum with radars, +satellites, and other licensed and unlicensed devices, it is sometimes +necessary to dynamically detect, avoid, and limit usage to avoid +interference with these devices. In many instances Intel is required to +provide test data to prove regional and local compliance to regional and +governmental regulations before certification or approval to use the +product is granted. Intel's wireless LAN's EEPROM, firmware, and +software driver are designed to carefully control parameters that affect +radio operation and to ensure electromagnetic compliance (EMC). These +parameters include, without limitation, RF power, spectrum usage, +channel scanning, and human exposure. + +For these reasons Intel cannot permit any manipulation by third parties +of the software provided in binary format with the wireless WLAN +adapters (e.g., the EEPROM and firmware). Furthermore, if you use any +patches, utilities, or code with the Intel wireless LAN adapters that +have been manipulated by an unauthorized party (i.e., patches, +utilities, or code (including open source code modifications) which have +not been validated by Intel), (i) you will be solely responsible for +ensuring the regulatory compliance of the products, (ii) Intel will bear +no liability, under any theory of liability for any issues associated +with the modified products, including without limitation, claims under +the warranty and/or issues arising from regulatory non-compliance, and +(iii) Intel will not provide or be required to assist in providing +support to any third parties for such modified products. + +Note: Many regulatory agencies consider Wireless LAN adapters to be +modules, and accordingly, condition system-level regulatory approval +upon receipt and review of test data documenting that the antennas and +system configuration do not cause the EMC and radio operation to be +non-compliant. + +The drivers available for download from SourceForge are provided as a +part of a development project. Conformance to local regulatory +requirements is the responsibility of the individual developer. As +such, if you are interested in deploying or shipping a driver as part of +solution intended to be used for purposes other than development, please +obtain a tested driver from Intel Customer Support at: + +http://support.intel.com/support/notebook/sb/CS-006408.htm 1. Introduction @@ -45,7 +101,7 @@ file. 1.1. Overview of Features ----------------------------------------------- -The current release (1.0.0) supports the following features: +The current release (1.0.8) supports the following features: + BSS mode (Infrastructure, Managed) + IBSS mode (Ad-Hoc) @@ -56,17 +112,27 @@ The current release (1.0.0) supports the following features: + Full A rate support (2915 only) + Transmit power control + S state support (ACPI suspend/resume) + +The following features are currently enabled, but not officially +supported: + ++ WPA + long/short preamble support ++ Monitor mode (aka RFMon) + +The distinction between officially supported and enabled is a reflection +on the amount of validation and interoperability testing that has been +performed on a given feature. 1.2. Command Line Parameters ----------------------------------------------- -Like many modules used in the Linux kernel, the Intel(R) PRO/Wireless -2915ABG Driver for Linux allows certain configuration options to be -provided as module parameters. The most common way to specify a module -parameter is via the command line. +Like many modules used in the Linux kernel, the Intel(R) PRO/Wireless +2915ABG Driver for Linux allows configuration options to be provided +as module parameters. The most common way to specify a module parameter +is via the command line. The general form is: @@ -96,14 +162,18 @@ Where the supported parameter are: debug If using a debug build, this is used to control the amount of debug - info is logged. See the 'dval' and 'load' script for more info on - how to use this (the dval and load scripts are provided as part + info is logged. See the 'dvals' and 'load' script for more info on + how to use this (the dvals and load scripts are provided as part of the ipw2200 development snapshot releases available from the SourceForge project at http://ipw2200.sf.net) + + led + Can be used to turn on experimental LED code. + 0 = Off, 1 = On. Default is 0. mode Can be used to set the default mode of the adapter. - 0 = Managed, 1 = Ad-Hoc + 0 = Managed, 1 = Ad-Hoc, 2 = Monitor 1.3. Wireless Extension Private Methods @@ -164,8 +234,8 @@ The supported private methods are: ----------------------------------------------- The Linux kernel provides a pseudo file system that can be used to -access various components of the operating system. The Intel(R) -PRO/Wireless 2915ABG Driver for Linux exposes several configuration +access various components of the operating system. The Intel(R) +PRO/Wireless 2915ABG Driver for Linux exposes several configuration parameters through this mechanism. An entry in the sysfs can support reading and/or writing. You can @@ -184,13 +254,13 @@ You can set the debug level via: Where $VALUE would be a number in the case of this sysfs entry. The input to sysfs files does not have to be a number. For example, the -firmware loader used by hotplug utilizes sysfs entries for transferring +firmware loader used by hotplug utilizes sysfs entries for transfering the firmware image from user space into the driver. The Intel(R) PRO/Wireless 2915ABG Driver for Linux exposes sysfs entries -at two levels -- driver level, which apply to all instances of the -driver (in the event that there are more than one device installed) and -device level, which applies only to the single specific instance. +at two levels -- driver level, which apply to all instances of the driver +(in the event that there are more than one device installed) and device +level, which applies only to the single specific instance. 1.4.1 Driver Level Sysfs Helper Files @@ -203,6 +273,7 @@ For the driver level files, look in /sys/bus/pci/drivers/ipw2200/ This controls the same global as the 'debug' module parameter + 1.4.2 Device Level Sysfs Helper Files ----------------------------------------------- @@ -213,7 +284,7 @@ For the device level files, look in For example: /sys/bus/pci/drivers/ipw2200/0000:02:01.0 -For the device level files, see /sys/bus/pci/[drivers/ipw2200: +For the device level files, see /sys/bus/pci/drivers/ipw2200: rf_kill read - @@ -231,8 +302,59 @@ For the device level files, see /sys/bus/pci/[drivers/ipw2200: ucode read-only access to the ucode version number + led + read - + 0 = LED code disabled + 1 = LED code enabled + write - + 0 = Disable LED code + 1 = Enable LED code + + NOTE: The LED code has been reported to hang some systems when + running ifconfig and is therefore disabled by default. + + +2. Ad-Hoc Networking +----------------------------------------------- + +When using a device in an Ad-Hoc network, it is useful to understand the +sequence and requirements for the driver to be able to create, join, or +merge networks. + +The following attempts to provide enough information so that you can +have a consistent experience while using the driver as a member of an +Ad-Hoc network. + +2.1. Joining an Ad-Hoc Network +----------------------------------------------- + +The easiest way to get onto an Ad-Hoc network is to join one that +already exists. -2. About the Version Numbers +2.2. Creating an Ad-Hoc Network +----------------------------------------------- + +An Ad-Hoc networks is created using the syntax of the Wireless tool. + +For Example: +iwconfig eth1 mode ad-hoc essid testing channel 2 + +2.3. Merging Ad-Hoc Networks +----------------------------------------------- + + +3. Interaction with Wireless Tools +----------------------------------------------- + +3.1 iwconfig mode +----------------------------------------------- + +When configuring the mode of the adapter, all run-time configured parameters +are reset to the value used when the module was loaded. This includes +channels, rates, ESSID, etc. + + +4. About the Version Numbers ----------------------------------------------- Due to the nature of open source development projects, there are @@ -259,12 +381,23 @@ available as quickly as possible, unknown anomalies should be expected. The major version number will be incremented when significant changes are made to the driver. Currently, there are no major changes planned. +5. Firmware installation +---------------------------------------------- + +The driver requires a firmware image, download it and extract the +files under /lib/firmware (or wherever your hotplug's firmware.agent +will look for firmware files) + +The firmware can be downloaded from the following URL: -3. Support + http://ipw2200.sf.net/ + + +6. Support ----------------------------------------------- -For installation support of the 1.0.0 version, you can contact -http://supportmail.intel.com, or you can use the open source project +For direct support of the 1.0.0 version, you can contact +http://supportmail.intel.com, or you can use the open source project support. For general information and support, go to: @@ -272,7 +405,7 @@ For general information and support, go to: http://ipw2200.sf.net/ -4. License +7. License ----------------------------------------------- Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved. @@ -297,4 +430,3 @@ For general information and support, go to: James P. Ketrenos Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - diff --git a/MAINTAINERS b/MAINTAINERS index d57c491212b..c051f493d0d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1310,6 +1310,24 @@ M: john.ronciak@intel.com W: http://sourceforge.net/projects/e1000/ S: Supported +INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT +P: Yi Zhu +M: yi.zhu@intel.com +P: James Ketrenos +M: jketreno@linux.intel.com +L: http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel +W: http://ipw2100.sourceforge.net +S: Supported + +INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT +P: Yi Zhu +M: yi.zhu@intel.com +P: James Ketrenos +M: jketreno@linux.intel.com +L: http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel +W: http://ipw2200.sourceforge.net +S: Supported + IOC3 DRIVER P: Ralf Baechle M: ralf@linux-mips.org -- cgit v1.2.3 From 22358ea8e1e88d65b073c3d2bb85d8c4e3bd44c1 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 8 Nov 2005 12:13:38 +1100 Subject: powerpc: Fix typo in pmac_cpufreq_resume Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/powermac/cpufreq_32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c index 7960a7bfca0..56fd4e05fed 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_32.c +++ b/arch/powerpc/platforms/powermac/cpufreq_32.c @@ -462,7 +462,7 @@ static int pmac_cpufreq_resume(struct cpufreq_policy *policy) /* If we resume, first check if we have a get() function */ if (get_speed_proc) cur_freq = get_speed_proc(); - else) + else cur_freq = 0; /* We don't, hrm... we don't really know our speed here, best -- cgit v1.2.3 From 3fb62b5148bd9df6b8a734988f5cf330251abdb4 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 8 Nov 2005 12:14:50 +1100 Subject: macintosh: Always export pmu_[un]register_sleep_notifier if CONFIG_PM set This fixes a build error when building the pmac sound driver as a module for 64-bit powermacs. Signed-off-by: Paul Mackerras --- drivers/macintosh/via-pmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 7ebbc0f5342..56404350856 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -2053,6 +2053,7 @@ pmu_register_sleep_notifier(struct pmu_sleep_notifier *n) __list_add(&n->list, list->prev, list); return 0; } +EXPORT_SYMBOL(pmu_register_sleep_notifier); int pmu_unregister_sleep_notifier(struct pmu_sleep_notifier* n) @@ -2063,6 +2064,7 @@ pmu_unregister_sleep_notifier(struct pmu_sleep_notifier* n) n->list.next = NULL; return 0; } +EXPORT_SYMBOL(pmu_unregister_sleep_notifier); #endif /* CONFIG_PM */ #if defined(CONFIG_PM) && defined(CONFIG_PPC32) @@ -3139,8 +3141,6 @@ EXPORT_SYMBOL(pmu_i2c_stdsub_write); EXPORT_SYMBOL(pmu_i2c_simple_read); EXPORT_SYMBOL(pmu_i2c_simple_write); #if defined(CONFIG_PM) && defined(CONFIG_PPC32) -EXPORT_SYMBOL(pmu_register_sleep_notifier); -EXPORT_SYMBOL(pmu_unregister_sleep_notifier); EXPORT_SYMBOL(pmu_enable_irled); EXPORT_SYMBOL(pmu_battery_count); EXPORT_SYMBOL(pmu_batteries); -- cgit v1.2.3 From 515729ece1e515546e9f49713b012cfbc41747ed Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 8 Nov 2005 12:15:36 +1100 Subject: powermac: Use a spinlock in swim3.c (floppy driver) instead of cli Signed-off-by: Paul Mackerras --- drivers/block/swim3.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index e425ad3eebb..af7cb2bfd67 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -176,6 +177,7 @@ struct swim3 { struct floppy_state { enum swim_state state; + spinlock_t lock; struct swim3 __iomem *swim3; /* hardware registers */ struct dbdma_regs __iomem *dma; /* DMA controller registers */ int swim3_intr; /* interrupt number for SWIM3 */ @@ -304,7 +306,6 @@ static void do_fd_request(request_queue_t * q) #endif /* CONFIG_PMAC_MEDIABAY */ start_request(&floppy_states[i]); } - sti(); } static void start_request(struct floppy_state *fs) @@ -370,7 +371,7 @@ static void set_timeout(struct floppy_state *fs, int nticks, { unsigned long flags; - save_flags(flags); cli(); + spin_lock_irqsave(&fs->lock, flags); if (fs->timeout_pending) del_timer(&fs->timeout); fs->timeout.expires = jiffies + nticks; @@ -378,7 +379,7 @@ static void set_timeout(struct floppy_state *fs, int nticks, fs->timeout.data = (unsigned long) fs; add_timer(&fs->timeout); fs->timeout_pending = 1; - restore_flags(flags); + spin_unlock_irqrestore(&fs->lock, flags); } static inline void scan_track(struct floppy_state *fs) @@ -790,14 +791,13 @@ static int grab_drive(struct floppy_state *fs, enum swim_state state, { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&fs->lock, flags); if (fs->state != idle) { ++fs->wanted; while (fs->state != available) { if (interruptible && signal_pending(current)) { --fs->wanted; - restore_flags(flags); + spin_unlock_irqrestore(&fs->lock, flags); return -EINTR; } interruptible_sleep_on(&fs->wait); @@ -805,7 +805,7 @@ static int grab_drive(struct floppy_state *fs, enum swim_state state, --fs->wanted; } fs->state = state; - restore_flags(flags); + spin_unlock_irqrestore(&fs->lock, flags); return 0; } @@ -813,11 +813,10 @@ static void release_drive(struct floppy_state *fs) { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&fs->lock, flags); fs->state = idle; start_request(fs); - restore_flags(flags); + spin_unlock_irqrestore(&fs->lock, flags); } static int fd_eject(struct floppy_state *fs) @@ -1109,6 +1108,7 @@ static int swim3_add_device(struct device_node *swim) pmac_call_feature(PMAC_FTR_SWIM3_ENABLE, swim, 0, 1); memset(fs, 0, sizeof(*fs)); + spin_lock_init(&fs->lock); fs->state = idle; fs->swim3 = (struct swim3 __iomem *) ioremap(swim->addrs[0].address, 0x200); -- cgit v1.2.3 From b354cab0763080df3735dcd0c64a545f266cc9e2 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 8 Nov 2005 12:20:34 +1100 Subject: powerpc: merge ide.h This is very simple with it being almost all ppc32 with just a couple of common defines. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- include/asm-powerpc/ide.h | 83 +++++++++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/ide.h | 78 -------------------------------------------- include/asm-ppc64/ide.h | 30 ----------------- 3 files changed, 83 insertions(+), 108 deletions(-) create mode 100644 include/asm-powerpc/ide.h delete mode 100644 include/asm-ppc/ide.h delete mode 100644 include/asm-ppc64/ide.h diff --git a/include/asm-powerpc/ide.h b/include/asm-powerpc/ide.h new file mode 100644 index 00000000000..da5f640480c --- /dev/null +++ b/include/asm-powerpc/ide.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 1994-1996 Linus Torvalds & authors + * + * This file contains the powerpc architecture specific IDE code. + */ +#ifndef _ASM_POWERPC_IDE_H +#define _ASM_POWERPC_IDE_H + +#ifdef __KERNEL__ + +#ifndef __powerpc64__ +#include +#include +#endif + +#ifndef MAX_HWIFS +#ifdef __powerpc64__ +#define MAX_HWIFS 10 +#else +#define MAX_HWIFS 8 +#endif +#endif + +#ifndef __powerpc64__ +#include +#include +#include +#include + +extern void __ide_mm_insw(void __iomem *port, void *addr, u32 count); +extern void __ide_mm_outsw(void __iomem *port, void *addr, u32 count); +extern void __ide_mm_insl(void __iomem *port, void *addr, u32 count); +extern void __ide_mm_outsl(void __iomem *port, void *addr, u32 count); + +struct ide_machdep_calls { + int (*default_irq)(unsigned long base); + unsigned long (*default_io_base)(int index); + void (*ide_init_hwif)(hw_regs_t *hw, + unsigned long data_port, + unsigned long ctrl_port, + int *irq); +}; + +extern struct ide_machdep_calls ppc_ide_md; + +#undef SUPPORT_SLOW_DATA_PORTS +#define SUPPORT_SLOW_DATA_PORTS 0 + +#define IDE_ARCH_OBSOLETE_DEFAULTS + +static __inline__ int ide_default_irq(unsigned long base) +{ + if (ppc_ide_md.default_irq) + return ppc_ide_md.default_irq(base); + return 0; +} + +static __inline__ unsigned long ide_default_io_base(int index) +{ + if (ppc_ide_md.default_io_base) + return ppc_ide_md.default_io_base(index); + return 0; +} + +#ifdef CONFIG_PCI +#define ide_init_default_irq(base) (0) +#else +#define ide_init_default_irq(base) ide_default_irq(base) +#endif + +#if (defined CONFIG_APUS || defined CONFIG_BLK_DEV_MPC8xx_IDE ) +#define IDE_ARCH_ACK_INTR 1 +#define ide_ack_intr(hwif) (hwif->hw.ack_intr ? hwif->hw.ack_intr(hwif) : 1) +#endif + +#endif /* __powerpc64__ */ + +#define IDE_ARCH_OBSOLETE_INIT +#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */ + +#endif /* __KERNEL__ */ + +#endif /* _ASM_POWERPC_IDE_H */ diff --git a/include/asm-ppc/ide.h b/include/asm-ppc/ide.h deleted file mode 100644 index 7d6e6599fac..00000000000 --- a/include/asm-ppc/ide.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * linux/include/asm-ppc/ide.h - * - * Copyright (C) 1994-1996 Linus Torvalds & authors */ - -/* - * This file contains the ppc architecture specific IDE code. - */ - -#ifndef __ASMPPC_IDE_H -#define __ASMPPC_IDE_H - -#ifdef __KERNEL__ - -#include -#include - -#ifndef MAX_HWIFS -#define MAX_HWIFS 8 -#endif - -#include -#include -#include -#include - -extern void __ide_mm_insw(void __iomem *port, void *addr, u32 count); -extern void __ide_mm_outsw(void __iomem *port, void *addr, u32 count); -extern void __ide_mm_insl(void __iomem *port, void *addr, u32 count); -extern void __ide_mm_outsl(void __iomem *port, void *addr, u32 count); - -struct ide_machdep_calls { - int (*default_irq)(unsigned long base); - unsigned long (*default_io_base)(int index); - void (*ide_init_hwif)(hw_regs_t *hw, - unsigned long data_port, - unsigned long ctrl_port, - int *irq); -}; - -extern struct ide_machdep_calls ppc_ide_md; - -#undef SUPPORT_SLOW_DATA_PORTS -#define SUPPORT_SLOW_DATA_PORTS 0 - -#define IDE_ARCH_OBSOLETE_DEFAULTS - -static __inline__ int ide_default_irq(unsigned long base) -{ - if (ppc_ide_md.default_irq) - return ppc_ide_md.default_irq(base); - return 0; -} - -static __inline__ unsigned long ide_default_io_base(int index) -{ - if (ppc_ide_md.default_io_base) - return ppc_ide_md.default_io_base(index); - return 0; -} - -#define IDE_ARCH_OBSOLETE_INIT -#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */ - -#ifdef CONFIG_PCI -#define ide_init_default_irq(base) (0) -#else -#define ide_init_default_irq(base) ide_default_irq(base) -#endif - -#if (defined CONFIG_APUS || defined CONFIG_BLK_DEV_MPC8xx_IDE ) -#define IDE_ARCH_ACK_INTR 1 -#define ide_ack_intr(hwif) (hwif->hw.ack_intr ? hwif->hw.ack_intr(hwif) : 1) -#endif - -#endif /* __KERNEL__ */ - -#endif /* __ASMPPC_IDE_H */ diff --git a/include/asm-ppc64/ide.h b/include/asm-ppc64/ide.h deleted file mode 100644 index 0aae1c590c0..00000000000 --- a/include/asm-ppc64/ide.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * linux/include/asm-ppc/ide.h - * - * Copyright (C) 1994-1996 Linus Torvalds & authors - * - * 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 option) any later version. - */ - -/* - * This file contains the ppc64 architecture specific IDE code. - */ - -#ifndef __ASMPPC64_IDE_H -#define __ASMPPC64_IDE_H - -#ifdef __KERNEL__ - -#ifndef MAX_HWIFS -# define MAX_HWIFS 10 -#endif - -#define IDE_ARCH_OBSOLETE_INIT -#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */ - -#endif /* __KERNEL__ */ - -#endif /* __ASMPPC64_IDE_H */ -- cgit v1.2.3 From 76c8e25b905f99be5ddbe999597ba7c2c33ec64b Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 8 Nov 2005 11:21:05 +1100 Subject: [PATCH] ppc64: Fix the lazy icache/dcache code for non-RAM pages For some stupid reason I can't explain (brown paper bag is at hand), I removed the check pfn_valid() in the code that does the icache/dcache coherency on POWER4 and later. That causes us to eventually try to access non existing struct page when hashing in IO pages. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/mm/hash_utils_64.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 3d83c3b84f0..22e47487613 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -507,6 +507,9 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap) { struct page *page; + if (!pfn_valid(pte_pfn(pte))) + return pp; + page = pte_page(pte); /* page is dirty */ -- cgit v1.2.3 From 7b7b1ace2d9d06d76bce7481a045c22ed75e35dd Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 7 Nov 2005 17:13:39 -0500 Subject: [PATCH] saner handling of auto_acct_off() and DQUOT_OFF() in umount The way we currently deal with quota and process accounting that might keep vfsmount busy at umount time is inherently broken; we try to turn them off just in case (not quite correctly, at that) and a) pray umount doesn't fail (otherwise they'll stay turned off) b) pray nobody doesn anything funny just as we turn quota off Moreover, LSM provides hooks for doing the same sort of broken logics. The proper way to deal with that is to introduce the second kind of reference to vfsmount. Semantics: - when the last normal reference is dropped, all special ones are converted to normal ones and if there had been any, cleanup is done. - normal reference can be cloned into a special one - special reference can be converted to normal one; that's a no-op if we'd already passed the point of no return (i.e. mntput() had converted special references to normal and started cleanup). The way it works: e.g. starting process accounting converts the vfsmount reference pinned by the opened file into special one and turns it back to normal when it gets shut down; acct_auto_close() is done when no normal references are left. That way it does *not* obstruct umount(2) and it silently gets turned off when the last normal reference to vfsmount is gone. Which is exactly what we want... The same should be done by LSM module that holds some internal references to vfsmount and wants to shut them down on umount - it should make them special and security_sb_umount_close() will be called exactly when the last normal reference to vfsmount is gone. quota handling is even simpler - we don't use normal file IO anymore, so there's no need to hold vfsmounts at all. DQUOT_OFF() is done from deactivate_super(), where it really belongs. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/dquot.c | 18 ++-------- fs/namespace.c | 64 ++++++++++++++++++++++------------- fs/super.c | 1 + include/linux/acct.h | 3 ++ include/linux/mount.h | 13 +++----- include/linux/quota.h | 1 - kernel/acct.c | 92 ++++++++++++++++++++++++++++++++++----------------- 7 files changed, 113 insertions(+), 79 deletions(-) diff --git a/fs/dquot.c b/fs/dquot.c index afa06a89346..05b60283c9c 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -1321,13 +1321,11 @@ int vfs_quota_off(struct super_block *sb, int type) int cnt; struct quota_info *dqopt = sb_dqopt(sb); struct inode *toputinode[MAXQUOTAS]; - struct vfsmount *toputmnt[MAXQUOTAS]; /* We need to serialize quota_off() for device */ down(&dqopt->dqonoff_sem); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { toputinode[cnt] = NULL; - toputmnt[cnt] = NULL; if (type != -1 && cnt != type) continue; if (!sb_has_quota_enabled(sb, cnt)) @@ -1348,9 +1346,7 @@ int vfs_quota_off(struct super_block *sb, int type) put_quota_format(dqopt->info[cnt].dqi_format); toputinode[cnt] = dqopt->files[cnt]; - toputmnt[cnt] = dqopt->mnt[cnt]; dqopt->files[cnt] = NULL; - dqopt->mnt[cnt] = NULL; dqopt->info[cnt].dqi_flags = 0; dqopt->info[cnt].dqi_igrace = 0; dqopt->info[cnt].dqi_bgrace = 0; @@ -1358,10 +1354,7 @@ int vfs_quota_off(struct super_block *sb, int type) } up(&dqopt->dqonoff_sem); /* Sync the superblock so that buffers with quota data are written to - * disk (and so userspace sees correct data afterwards). - * The reference to vfsmnt we are still holding protects us from - * umount (we don't have it only when quotas are turned on/off for - * journal replay but in that case we are guarded by the fs anyway). */ + * disk (and so userspace sees correct data afterwards). */ if (sb->s_op->sync_fs) sb->s_op->sync_fs(sb, 1); sync_blockdev(sb->s_bdev); @@ -1385,10 +1378,6 @@ int vfs_quota_off(struct super_block *sb, int type) iput(toputinode[cnt]); } up(&dqopt->dqonoff_sem); - /* We don't hold the reference when we turned on quotas - * just for the journal replay... */ - if (toputmnt[cnt]) - mntput(toputmnt[cnt]); } if (sb->s_bdev) invalidate_bdev(sb->s_bdev, 0); @@ -1503,11 +1492,8 @@ int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path) /* Quota file not on the same filesystem? */ if (nd.mnt->mnt_sb != sb) error = -EXDEV; - else { + else error = vfs_quota_on_inode(nd.dentry->d_inode, type, format_id); - if (!error) - sb_dqopt(sb)->mnt[type] = mntget(nd.mnt); - } out_path: path_release(&nd); return error; diff --git a/fs/namespace.c b/fs/namespace.c index 2fa9fdf7d6f..1d83302f30c 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -172,7 +172,7 @@ clone_mnt(struct vfsmount *old, struct dentry *root) return mnt; } -void __mntput(struct vfsmount *mnt) +static inline void __mntput(struct vfsmount *mnt) { struct super_block *sb = mnt->mnt_sb; dput(mnt->mnt_root); @@ -180,7 +180,46 @@ void __mntput(struct vfsmount *mnt) deactivate_super(sb); } -EXPORT_SYMBOL(__mntput); +void mntput_no_expire(struct vfsmount *mnt) +{ +repeat: + if (atomic_dec_and_lock(&mnt->mnt_count, &vfsmount_lock)) { + if (likely(!mnt->mnt_pinned)) { + spin_unlock(&vfsmount_lock); + __mntput(mnt); + return; + } + atomic_add(mnt->mnt_pinned + 1, &mnt->mnt_count); + mnt->mnt_pinned = 0; + spin_unlock(&vfsmount_lock); + acct_auto_close_mnt(mnt); + security_sb_umount_close(mnt); + goto repeat; + } +} + +EXPORT_SYMBOL(mntput_no_expire); + +void mnt_pin(struct vfsmount *mnt) +{ + spin_lock(&vfsmount_lock); + mnt->mnt_pinned++; + spin_unlock(&vfsmount_lock); +} + +EXPORT_SYMBOL(mnt_pin); + +void mnt_unpin(struct vfsmount *mnt) +{ + spin_lock(&vfsmount_lock); + if (mnt->mnt_pinned) { + atomic_inc(&mnt->mnt_count); + mnt->mnt_pinned--; + } + spin_unlock(&vfsmount_lock); +} + +EXPORT_SYMBOL(mnt_unpin); /* iterator */ static void *m_start(struct seq_file *m, loff_t *pos) @@ -435,16 +474,6 @@ static int do_umount(struct vfsmount *mnt, int flags) down_write(¤t->namespace->sem); spin_lock(&vfsmount_lock); - if (atomic_read(&sb->s_active) == 1) { - /* last instance - try to be smart */ - spin_unlock(&vfsmount_lock); - lock_kernel(); - DQUOT_OFF(sb); - acct_auto_close(sb); - unlock_kernel(); - security_sb_umount_close(mnt); - spin_lock(&vfsmount_lock); - } retval = -EBUSY; if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) { if (!list_empty(&mnt->mnt_list)) @@ -850,17 +879,6 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts) detach_mnt(mnt, &old_nd); spin_unlock(&vfsmount_lock); path_release(&old_nd); - - /* - * Now lay it to rest if this was the last ref on the superblock - */ - if (atomic_read(&mnt->mnt_sb->s_active) == 1) { - /* last instance - try to be smart */ - lock_kernel(); - DQUOT_OFF(mnt->mnt_sb); - acct_auto_close(mnt->mnt_sb); - unlock_kernel(); - } mntput(mnt); } else { /* diff --git a/fs/super.c b/fs/super.c index eed6c313290..6689dded3c8 100644 --- a/fs/super.c +++ b/fs/super.c @@ -171,6 +171,7 @@ void deactivate_super(struct super_block *s) if (atomic_dec_and_lock(&s->s_active, &sb_lock)) { s->s_count -= S_BIAS-1; spin_unlock(&sb_lock); + DQUOT_OFF(s); down_write(&s->s_umount); fs->kill_sb(s); put_filesystem(fs); diff --git a/include/linux/acct.h b/include/linux/acct.h index 19f70462b3b..93c5b3cdf95 100644 --- a/include/linux/acct.h +++ b/include/linux/acct.h @@ -117,12 +117,15 @@ struct acct_v3 #include #ifdef CONFIG_BSD_PROCESS_ACCT +struct vfsmount; struct super_block; +extern void acct_auto_close_mnt(struct vfsmount *m); extern void acct_auto_close(struct super_block *sb); extern void acct_process(long exitcode); extern void acct_update_integrals(struct task_struct *tsk); extern void acct_clear_integrals(struct task_struct *tsk); #else +#define acct_auto_close_mnt(x) do { } while (0) #define acct_auto_close(x) do { } while (0) #define acct_process(x) do { } while (0) #define acct_update_integrals(x) do { } while (0) diff --git a/include/linux/mount.h b/include/linux/mount.h index f8f39937e30..ffb0b508988 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -37,6 +37,7 @@ struct vfsmount struct list_head mnt_list; struct list_head mnt_expire; /* link in fs-specific expiry list */ struct namespace *mnt_namespace; /* containing namespace */ + int mnt_pinned; }; static inline struct vfsmount *mntget(struct vfsmount *mnt) @@ -46,15 +47,9 @@ static inline struct vfsmount *mntget(struct vfsmount *mnt) return mnt; } -extern void __mntput(struct vfsmount *mnt); - -static inline void mntput_no_expire(struct vfsmount *mnt) -{ - if (mnt) { - if (atomic_dec_and_test(&mnt->mnt_count)) - __mntput(mnt); - } -} +extern void mntput_no_expire(struct vfsmount *mnt); +extern void mnt_pin(struct vfsmount *mnt); +extern void mnt_unpin(struct vfsmount *mnt); static inline void mntput(struct vfsmount *mnt) { diff --git a/include/linux/quota.h b/include/linux/quota.h index 700ead45084..f33aeb22c26 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h @@ -289,7 +289,6 @@ struct quota_info { struct semaphore dqonoff_sem; /* Serialize quotaon & quotaoff */ struct rw_semaphore dqptr_sem; /* serialize ops using quota_info struct, pointers from inode to dquots */ struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */ - struct vfsmount *mnt[MAXQUOTAS]; /* mountpoint entries of filesystems with quota files */ struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */ struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */ }; diff --git a/kernel/acct.c b/kernel/acct.c index 2e3f4a47e7d..6312d6bd43e 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include /* sector_div */ @@ -192,6 +193,7 @@ static void acct_file_reopen(struct file *file) add_timer(&acct_globals.timer); } if (old_acct) { + mnt_unpin(old_acct->f_vfsmnt); spin_unlock(&acct_globals.lock); do_acct_process(0, old_acct); filp_close(old_acct, NULL); @@ -199,6 +201,42 @@ static void acct_file_reopen(struct file *file) } } +static int acct_on(char *name) +{ + struct file *file; + int error; + + /* Difference from BSD - they don't do O_APPEND */ + file = filp_open(name, O_WRONLY|O_APPEND|O_LARGEFILE, 0); + if (IS_ERR(file)) + return PTR_ERR(file); + + if (!S_ISREG(file->f_dentry->d_inode->i_mode)) { + filp_close(file, NULL); + return -EACCES; + } + + if (!file->f_op->write) { + filp_close(file, NULL); + return -EIO; + } + + error = security_acct(file); + if (error) { + filp_close(file, NULL); + return error; + } + + spin_lock(&acct_globals.lock); + mnt_pin(file->f_vfsmnt); + acct_file_reopen(file); + spin_unlock(&acct_globals.lock); + + mntput(file->f_vfsmnt); /* it's pinned, now give up active reference */ + + return 0; +} + /** * sys_acct - enable/disable process accounting * @name: file name for accounting records or NULL to shutdown accounting @@ -212,47 +250,41 @@ static void acct_file_reopen(struct file *file) */ asmlinkage long sys_acct(const char __user *name) { - struct file *file = NULL; - char *tmp; int error; if (!capable(CAP_SYS_PACCT)) return -EPERM; if (name) { - tmp = getname(name); - if (IS_ERR(tmp)) { + char *tmp = getname(name); + if (IS_ERR(tmp)) return (PTR_ERR(tmp)); - } - /* Difference from BSD - they don't do O_APPEND */ - file = filp_open(tmp, O_WRONLY|O_APPEND|O_LARGEFILE, 0); + error = acct_on(tmp); putname(tmp); - if (IS_ERR(file)) { - return (PTR_ERR(file)); - } - if (!S_ISREG(file->f_dentry->d_inode->i_mode)) { - filp_close(file, NULL); - return (-EACCES); - } - - if (!file->f_op->write) { - filp_close(file, NULL); - return (-EIO); + } else { + error = security_acct(NULL); + if (!error) { + spin_lock(&acct_globals.lock); + acct_file_reopen(NULL); + spin_unlock(&acct_globals.lock); } } + return error; +} - error = security_acct(file); - if (error) { - if (file) - filp_close(file, NULL); - return error; - } - +/** + * acct_auto_close - turn off a filesystem's accounting if it is on + * @m: vfsmount being shut down + * + * If the accounting is turned on for a file in the subtree pointed to + * to by m, turn accounting off. Done when m is about to die. + */ +void acct_auto_close_mnt(struct vfsmount *m) +{ spin_lock(&acct_globals.lock); - acct_file_reopen(file); + if (acct_globals.file && acct_globals.file->f_vfsmnt == m) + acct_file_reopen(NULL); spin_unlock(&acct_globals.lock); - - return (0); } /** @@ -266,8 +298,8 @@ void acct_auto_close(struct super_block *sb) { spin_lock(&acct_globals.lock); if (acct_globals.file && - acct_globals.file->f_dentry->d_inode->i_sb == sb) { - acct_file_reopen((struct file *)NULL); + acct_globals.file->f_vfsmnt->mnt_sb == sb) { + acct_file_reopen(NULL); } spin_unlock(&acct_globals.lock); } -- cgit v1.2.3 From ccd48bc7fac284caf704dcdcafd223a24f70bccf Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 7 Nov 2005 17:15:04 -0500 Subject: [PATCH] cleanups and bug fix in do_loopback() - check_mnt() on the source of binding should've been unconditional from the very beginning. My fault - as far I could've trace it, that's an old thinko made back in 2001. Kudos to Miklos for spotting it... Fixed. - code cleaned up. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 1d83302f30c..611f777bbd6 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -661,29 +661,32 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) down_write(¤t->namespace->sem); err = -EINVAL; - if (check_mnt(nd->mnt) && (!recurse || check_mnt(old_nd.mnt))) { - err = -ENOMEM; - if (recurse) - mnt = copy_tree(old_nd.mnt, old_nd.dentry); - else - mnt = clone_mnt(old_nd.mnt, old_nd.dentry); - } + if (!check_mnt(nd->mnt) || !check_mnt(old_nd.mnt)) + goto out; - if (mnt) { - /* stop bind mounts from expiring */ + err = -ENOMEM; + if (recurse) + mnt = copy_tree(old_nd.mnt, old_nd.dentry); + else + mnt = clone_mnt(old_nd.mnt, old_nd.dentry); + + if (!mnt) + goto out; + + /* stop bind mounts from expiring */ + spin_lock(&vfsmount_lock); + list_del_init(&mnt->mnt_expire); + spin_unlock(&vfsmount_lock); + + err = graft_tree(mnt, nd); + if (err) { spin_lock(&vfsmount_lock); - list_del_init(&mnt->mnt_expire); + umount_tree(mnt); spin_unlock(&vfsmount_lock); + } else + mntput(mnt); - err = graft_tree(mnt, nd); - if (err) { - spin_lock(&vfsmount_lock); - umount_tree(mnt); - spin_unlock(&vfsmount_lock); - } else - mntput(mnt); - } - +out: up_write(¤t->namespace->sem); path_release(&old_nd); return err; -- cgit v1.2.3 From 1abe77b0fc4b485927f1f798ae81a752677e1d05 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 7 Nov 2005 17:15:34 -0500 Subject: [PATCH] allow callers of seq_open do allocation themselves Allow caller of seq_open() to kmalloc() seq_file + whatever else they want and set ->private_data to it. seq_open() will then abstain from doing allocation itself. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/seq_file.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/fs/seq_file.c b/fs/seq_file.c index 38ef913767f..7c40570b71d 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -28,13 +28,17 @@ */ int seq_open(struct file *file, struct seq_operations *op) { - struct seq_file *p = kmalloc(sizeof(*p), GFP_KERNEL); - if (!p) - return -ENOMEM; + struct seq_file *p = file->private_data; + + if (!p) { + p = kmalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return -ENOMEM; + file->private_data = p; + } memset(p, 0, sizeof(*p)); sema_init(&p->sem, 1); p->op = op; - file->private_data = p; /* * Wrappers around seq_open(e.g. swaps_open) need to be -- cgit v1.2.3 From 5addc5dd8836aa061f6efc4a0d9ba6323726297a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 7 Nov 2005 17:15:49 -0500 Subject: [PATCH] make /proc/mounts pollable Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 30 ++++++++++++++++++++++- fs/proc/base.c | 62 +++++++++++++++++++++++++++++++++++------------ include/linux/namespace.h | 2 ++ 3 files changed, 78 insertions(+), 16 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 611f777bbd6..d1aca685aac 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -37,7 +37,9 @@ static inline int sysfs_init(void) #endif /* spinlock for vfsmount related operations, inplace of dcache_lock */ - __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock); +__cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock); + +static int event; static struct list_head *mount_hashtable; static int hash_mask __read_mostly, hash_bits __read_mostly; @@ -111,6 +113,22 @@ static inline int check_mnt(struct vfsmount *mnt) return mnt->mnt_namespace == current->namespace; } +static void touch_namespace(struct namespace *ns) +{ + if (ns) { + ns->event = ++event; + wake_up_interruptible(&ns->poll); + } +} + +static void __touch_namespace(struct namespace *ns) +{ + if (ns && ns->event != event) { + ns->event = event; + wake_up_interruptible(&ns->poll); + } +} + static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd) { old_nd->dentry = mnt->mnt_mountpoint; @@ -384,6 +402,7 @@ static void umount_tree(struct vfsmount *mnt) for (p = mnt; p; p = next_mnt(p, mnt)) { list_del(&p->mnt_list); list_add(&p->mnt_list, &kill); + __touch_namespace(p->mnt_namespace); p->mnt_namespace = NULL; } @@ -473,6 +492,7 @@ static int do_umount(struct vfsmount *mnt, int flags) down_write(¤t->namespace->sem); spin_lock(&vfsmount_lock); + event++; retval = -EBUSY; if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) { @@ -634,6 +654,7 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) list_splice(&head, current->namespace->list.prev); mntget(mnt); err = 0; + touch_namespace(current->namespace); } spin_unlock(&vfsmount_lock); out_unlock: @@ -771,6 +792,7 @@ static int do_move_mount(struct nameidata *nd, char *old_name) detach_mnt(old_nd.mnt, &parent_nd); attach_mnt(old_nd.mnt, nd); + touch_namespace(current->namespace); /* if the mount is moved, it should no longer be expire * automatically */ @@ -877,6 +899,7 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts) struct nameidata old_nd; /* delete from the namespace */ + touch_namespace(mnt->mnt_namespace); list_del_init(&mnt->mnt_list); mnt->mnt_namespace = NULL; detach_mnt(mnt, &old_nd); @@ -1114,6 +1137,8 @@ int copy_namespace(int flags, struct task_struct *tsk) atomic_set(&new_ns->count, 1); init_rwsem(&new_ns->sem); INIT_LIST_HEAD(&new_ns->list); + init_waitqueue_head(&new_ns->poll); + new_ns->event = 0; down_write(&tsk->namespace->sem); /* First pass: copy the tree topology */ @@ -1377,6 +1402,7 @@ asmlinkage long sys_pivot_root(const char __user *new_root, const char __user *p detach_mnt(user_nd.mnt, &root_parent); attach_mnt(user_nd.mnt, &old_nd); /* mount old root on put_old */ attach_mnt(new_nd.mnt, &root_parent); /* mount new_root on / */ + touch_namespace(current->namespace); spin_unlock(&vfsmount_lock); chroot_fs_refs(&user_nd, &new_nd); security_sb_post_pivotroot(&user_nd, &new_nd); @@ -1413,6 +1439,8 @@ static void __init init_mount_tree(void) atomic_set(&namespace->count, 1); INIT_LIST_HEAD(&namespace->list); init_rwsem(&namespace->sem); + init_waitqueue_head(&namespace->poll); + namespace->event = 0; list_add(&mnt->mnt_list, &namespace->list); namespace->root = mnt; mnt->mnt_namespace = namespace; diff --git a/fs/proc/base.c b/fs/proc/base.c index a170450aadb..634355e1698 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -70,6 +70,7 @@ #include #include #include +#include #include "internal.h" /* @@ -660,26 +661,38 @@ static struct file_operations proc_smaps_operations = { #endif extern struct seq_operations mounts_op; +struct proc_mounts { + struct seq_file m; + int event; +}; + static int mounts_open(struct inode *inode, struct file *file) { struct task_struct *task = proc_task(inode); - int ret = seq_open(file, &mounts_op); + struct namespace *namespace; + struct proc_mounts *p; + int ret = -EINVAL; - if (!ret) { - struct seq_file *m = file->private_data; - struct namespace *namespace; - task_lock(task); - namespace = task->namespace; - if (namespace) - get_namespace(namespace); - task_unlock(task); - - if (namespace) - m->private = namespace; - else { - seq_release(inode, file); - ret = -EINVAL; + task_lock(task); + namespace = task->namespace; + if (namespace) + get_namespace(namespace); + task_unlock(task); + + if (namespace) { + ret = -ENOMEM; + p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL); + if (p) { + file->private_data = &p->m; + ret = seq_open(file, &mounts_op); + if (!ret) { + p->m.private = namespace; + p->event = namespace->event; + return 0; + } + kfree(p); } + put_namespace(namespace); } return ret; } @@ -692,11 +705,30 @@ static int mounts_release(struct inode *inode, struct file *file) return seq_release(inode, file); } +static unsigned mounts_poll(struct file *file, poll_table *wait) +{ + struct proc_mounts *p = file->private_data; + struct namespace *ns = p->m.private; + unsigned res = 0; + + poll_wait(file, &ns->poll, wait); + + spin_lock(&vfsmount_lock); + if (p->event != ns->event) { + p->event = ns->event; + res = POLLERR; + } + spin_unlock(&vfsmount_lock); + + return res; +} + static struct file_operations proc_mounts_operations = { .open = mounts_open, .read = seq_read, .llseek = seq_lseek, .release = mounts_release, + .poll = mounts_poll, }; #define PROC_BLOCK_SIZE (3*1024) /* 4K page size but our output routines use some slack for overruns */ diff --git a/include/linux/namespace.h b/include/linux/namespace.h index 0e5a86f13b2..6f0f25d64c3 100644 --- a/include/linux/namespace.h +++ b/include/linux/namespace.h @@ -10,6 +10,8 @@ struct namespace { struct vfsmount * root; struct list_head list; struct rw_semaphore sem; + wait_queue_head_t poll; + int event; }; extern int copy_namespace(int, struct task_struct *); -- cgit v1.2.3 From b58fed8b1959d6b9e4c951a54adc8960e1401b18 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:16:09 -0500 Subject: [PATCH] lindent fs/namespace.c Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 97 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 48 insertions(+), 49 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index d1aca685aac..685687dccbf 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -43,29 +43,29 @@ static int event; static struct list_head *mount_hashtable; static int hash_mask __read_mostly, hash_bits __read_mostly; -static kmem_cache_t *mnt_cache; +static kmem_cache_t *mnt_cache; static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry) { - unsigned long tmp = ((unsigned long) mnt / L1_CACHE_BYTES); - tmp += ((unsigned long) dentry / L1_CACHE_BYTES); + unsigned long tmp = ((unsigned long)mnt / L1_CACHE_BYTES); + tmp += ((unsigned long)dentry / L1_CACHE_BYTES); tmp = tmp + (tmp >> hash_bits); return tmp & hash_mask; } struct vfsmount *alloc_vfsmnt(const char *name) { - struct vfsmount *mnt = kmem_cache_alloc(mnt_cache, GFP_KERNEL); + struct vfsmount *mnt = kmem_cache_alloc(mnt_cache, GFP_KERNEL); if (mnt) { memset(mnt, 0, sizeof(struct vfsmount)); - atomic_set(&mnt->mnt_count,1); + atomic_set(&mnt->mnt_count, 1); INIT_LIST_HEAD(&mnt->mnt_hash); INIT_LIST_HEAD(&mnt->mnt_child); INIT_LIST_HEAD(&mnt->mnt_mounts); INIT_LIST_HEAD(&mnt->mnt_list); INIT_LIST_HEAD(&mnt->mnt_expire); if (name) { - int size = strlen(name)+1; + int size = strlen(name) + 1; char *newname = kmalloc(size, GFP_KERNEL); if (newname) { memcpy(newname, name, size); @@ -88,8 +88,8 @@ void free_vfsmnt(struct vfsmount *mnt) */ struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry) { - struct list_head * head = mount_hashtable + hash(mnt, dentry); - struct list_head * tmp = head; + struct list_head *head = mount_hashtable + hash(mnt, dentry); + struct list_head *tmp = head; struct vfsmount *p, *found = NULL; spin_lock(&vfsmount_lock); @@ -144,7 +144,7 @@ static void attach_mnt(struct vfsmount *mnt, struct nameidata *nd) { mnt->mnt_parent = mntget(nd->mnt); mnt->mnt_mountpoint = dget(nd->dentry); - list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry)); + list_add(&mnt->mnt_hash, mount_hashtable + hash(nd->mnt, nd->dentry)); list_add_tail(&mnt->mnt_child, &nd->mnt->mnt_mounts); nd->dentry->d_mounted++; } @@ -165,8 +165,7 @@ static struct vfsmount *next_mnt(struct vfsmount *p, struct vfsmount *root) return list_entry(next, struct vfsmount, mnt_child); } -static struct vfsmount * -clone_mnt(struct vfsmount *old, struct dentry *root) +static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root) { struct super_block *sb = old->mnt_sb; struct vfsmount *mnt = alloc_vfsmnt(old->mnt_devname); @@ -258,7 +257,7 @@ static void *m_next(struct seq_file *m, void *v, loff_t *pos) struct namespace *n = m->private; struct list_head *p = ((struct vfsmount *)v)->mnt_list.next; (*pos)++; - return p==&n->list ? NULL : list_entry(p, struct vfsmount, mnt_list); + return p == &n->list ? NULL : list_entry(p, struct vfsmount, mnt_list); } static void m_stop(struct seq_file *m, void *v) @@ -344,7 +343,8 @@ repeat: next = this_parent->mnt_mounts.next; resume: while (next != &this_parent->mnt_mounts) { - struct vfsmount *p = list_entry(next, struct vfsmount, mnt_child); + struct vfsmount *p = + list_entry(next, struct vfsmount, mnt_child); next = next->next; @@ -425,7 +425,7 @@ static void umount_tree(struct vfsmount *mnt) static int do_umount(struct vfsmount *mnt, int flags) { - struct super_block * sb = mnt->mnt_sb; + struct super_block *sb = mnt->mnt_sb; int retval; retval = security_sb_umount(mnt, flags); @@ -461,7 +461,7 @@ static int do_umount(struct vfsmount *mnt, int flags) */ lock_kernel(); - if( (flags&MNT_FORCE) && sb->s_op->umount_begin) + if ((flags & MNT_FORCE) && sb->s_op->umount_begin) sb->s_op->umount_begin(sb); unlock_kernel(); @@ -543,12 +543,11 @@ out: #ifdef __ARCH_WANT_SYS_OLDUMOUNT /* - * The 2.0 compatible umount. No flags. + * The 2.0 compatible umount. No flags. */ - asmlinkage long sys_oldumount(char __user * name) { - return sys_umount(name,0); + return sys_umount(name, 0); } #endif @@ -571,8 +570,7 @@ static int mount_is_safe(struct nameidata *nd) #endif } -static int -lives_below_in_same_fs(struct dentry *d, struct dentry *dentry) +static int lives_below_in_same_fs(struct dentry *d, struct dentry *dentry) { while (1) { if (d == dentry) @@ -616,7 +614,7 @@ static struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry) } } return res; - Enomem: +Enomem: if (res) { spin_lock(&vfsmount_lock); umount_tree(res); @@ -718,12 +716,11 @@ out: * If you've mounted a non-root directory somewhere and want to do remount * on it - tough luck. */ - static int do_remount(struct nameidata *nd, int flags, int mnt_flags, void *data) { int err; - struct super_block * sb = nd->mnt->mnt_sb; + struct super_block *sb = nd->mnt->mnt_sb; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -737,7 +734,7 @@ static int do_remount(struct nameidata *nd, int flags, int mnt_flags, down_write(&sb->s_umount); err = do_remount_sb(sb, flags, data, 0); if (!err) - nd->mnt->mnt_flags=mnt_flags; + nd->mnt->mnt_flags = mnt_flags; up_write(&sb->s_umount); if (!err) security_sb_post_remount(nd->mnt, flags, data); @@ -758,7 +755,7 @@ static int do_move_mount(struct nameidata *nd, char *old_name) return err; down_write(¤t->namespace->sem); - while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) + while (d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) ; err = -EINVAL; if (!check_mnt(nd->mnt) || !check_mnt(old_nd.mnt)) @@ -785,7 +782,7 @@ static int do_move_mount(struct nameidata *nd, char *old_name) goto out2; err = -ELOOP; - for (p = nd->mnt; p->mnt_parent!=p; p = p->mnt_parent) + for (p = nd->mnt; p->mnt_parent != p; p = p->mnt_parent) if (p == old_nd.mnt) goto out2; err = 0; @@ -843,7 +840,7 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, down_write(¤t->namespace->sem); /* Something was mounted here while we slept */ - while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) + while (d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) ; err = -EINVAL; if (!check_mnt(nd->mnt)) @@ -986,8 +983,8 @@ EXPORT_SYMBOL_GPL(mark_mounts_for_expiry); * Note that this function differs from copy_from_user() in that it will oops * on bad values of `to', rather than returning a short copy. */ -static long -exact_copy_from_user(void *to, const void __user *from, unsigned long n) +static long exact_copy_from_user(void *to, const void __user * from, + unsigned long n) { char *t = to; const char __user *f = from; @@ -1008,12 +1005,12 @@ exact_copy_from_user(void *to, const void __user *from, unsigned long n) return n; } -int copy_mount_options(const void __user *data, unsigned long *where) +int copy_mount_options(const void __user * data, unsigned long *where) { int i; unsigned long page; unsigned long size; - + *where = 0; if (!data) return 0; @@ -1032,7 +1029,7 @@ int copy_mount_options(const void __user *data, unsigned long *where) i = size - exact_copy_from_user((void *)page, data, size); if (!i) { - free_page(page); + free_page(page); return -EFAULT; } if (i != PAGE_SIZE) @@ -1055,7 +1052,7 @@ int copy_mount_options(const void __user *data, unsigned long *where) * Therefore, if this magic number is present, it carries no information * and must be discarded. */ -long do_mount(char * dev_name, char * dir_name, char *type_page, +long do_mount(char *dev_name, char *dir_name, char *type_page, unsigned long flags, void *data_page) { struct nameidata nd; @@ -1083,7 +1080,7 @@ long do_mount(char * dev_name, char * dir_name, char *type_page, mnt_flags |= MNT_NODEV; if (flags & MS_NOEXEC) mnt_flags |= MNT_NOEXEC; - flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_ACTIVE); + flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE); /* ... and get the mountpoint */ retval = path_lookup(dir_name, LOOKUP_FOLLOW, &nd); @@ -1207,7 +1204,7 @@ asmlinkage long sys_mount(char __user * dev_name, char __user * dir_name, unsigned long dev_page; char *dir_page; - retval = copy_mount_options (type, &type_page); + retval = copy_mount_options(type, &type_page); if (retval < 0) return retval; @@ -1216,17 +1213,17 @@ asmlinkage long sys_mount(char __user * dev_name, char __user * dir_name, if (IS_ERR(dir_page)) goto out1; - retval = copy_mount_options (dev_name, &dev_page); + retval = copy_mount_options(dev_name, &dev_page); if (retval < 0) goto out2; - retval = copy_mount_options (data, &data_page); + retval = copy_mount_options(data, &data_page); if (retval < 0) goto out3; lock_kernel(); - retval = do_mount((char*)dev_page, dir_page, (char*)type_page, - flags, (void*)data_page); + retval = do_mount((char *)dev_page, dir_page, (char *)type_page, + flags, (void *)data_page); unlock_kernel(); free_page(data_page); @@ -1295,9 +1292,11 @@ static void chroot_fs_refs(struct nameidata *old_nd, struct nameidata *new_nd) if (fs) { atomic_inc(&fs->count); task_unlock(p); - if (fs->root==old_nd->dentry&&fs->rootmnt==old_nd->mnt) + if (fs->root == old_nd->dentry + && fs->rootmnt == old_nd->mnt) set_fs_root(fs, new_nd->mnt, new_nd->dentry); - if (fs->pwd==old_nd->dentry&&fs->pwdmnt==old_nd->mnt) + if (fs->pwd == old_nd->dentry + && fs->pwdmnt == old_nd->mnt) set_fs_pwd(fs, new_nd->mnt, new_nd->dentry); put_fs_struct(fs); } else @@ -1327,8 +1326,8 @@ static void chroot_fs_refs(struct nameidata *old_nd, struct nameidata *new_nd) * though, so you may need to say mount --bind /nfs/my_root /nfs/my_root * first. */ - -asmlinkage long sys_pivot_root(const char __user *new_root, const char __user *put_old) +asmlinkage long sys_pivot_root(const char __user * new_root, + const char __user * put_old) { struct vfsmount *tmp; struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd; @@ -1339,14 +1338,15 @@ asmlinkage long sys_pivot_root(const char __user *new_root, const char __user *p lock_kernel(); - error = __user_walk(new_root, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd); + error = __user_walk(new_root, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, + &new_nd); if (error) goto out0; error = -EINVAL; if (!check_mnt(new_nd.mnt)) goto out1; - error = __user_walk(put_old, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd); + error = __user_walk(put_old, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &old_nd); if (error) goto out1; @@ -1464,10 +1464,9 @@ void __init mnt_init(unsigned long mempages) int i; mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct vfsmount), - 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); + 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL, NULL); - mount_hashtable = (struct list_head *) - __get_free_page(GFP_ATOMIC); + mount_hashtable = (struct list_head *)__get_free_page(GFP_ATOMIC); if (!mount_hashtable) panic("Failed to allocate mount hash table\n"); @@ -1489,7 +1488,7 @@ void __init mnt_init(unsigned long mempages) * from the number of bits we can fit. */ nr_hash = 1UL << hash_bits; - hash_mask = nr_hash-1; + hash_mask = nr_hash - 1; printk("Mount-cache hash table entries: %d\n", nr_hash); -- cgit v1.2.3 From 5b83d2c5c0afcf5a3517cf00d9ceb41b8345e01b Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:16:29 -0500 Subject: [PATCH] sanitize the interface of graft_tree(). Old semantics: graft_tree() grabs a reference on the vfsmount before returning success. New one: graft_tree() leaves that to caller. All the callers of graft_tree() immediately dropped that reference anyway. Changing the interface takes care of this unnecessary overhead. Idea proposed by Al Viro. Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 685687dccbf..dfeeab964e8 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -650,7 +650,6 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) attach_mnt(mnt, nd); list_add_tail(&head, &mnt->mnt_list); list_splice(&head, current->namespace->list.prev); - mntget(mnt); err = 0; touch_namespace(current->namespace); } @@ -702,8 +701,7 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) spin_lock(&vfsmount_lock); umount_tree(mnt); spin_unlock(&vfsmount_lock); - } else - mntput(mnt); + } out: up_write(¤t->namespace->sem); @@ -857,15 +855,17 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, goto unlock; newmnt->mnt_flags = mnt_flags; - newmnt->mnt_namespace = current->namespace; - err = graft_tree(newmnt, nd); + if ((err = graft_tree(newmnt, nd))) + goto unlock; - if (err == 0 && fslist) { + if (fslist) { /* add to the specified expiration list */ spin_lock(&vfsmount_lock); list_add_tail(&newmnt->mnt_expire, fslist); spin_unlock(&vfsmount_lock); } + up_write(¤t->namespace->sem); + return 0; unlock: up_write(¤t->namespace->sem); -- cgit v1.2.3 From 70fbcdf4d252c6b17cc249cb9ac9b220cb0b863d Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:17:04 -0500 Subject: [PATCH] umount_tree() locking change umount is done under the protection of the namespace semaphore. This can lead to intresting deadlocks when the last reference to a mount is released, if filesystem code is in sufficiently nasty state. This collects all the to-be-released-mounts and releases them after releasing the namespace semaphore. That both reduces the time we are holding namespace semaphore and gets the things more robust. Idea proposed by Al Viro. Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 84 +++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 33 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index dfeeab964e8..c2ffa0f349f 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -394,32 +394,45 @@ int may_umount(struct vfsmount *mnt) EXPORT_SYMBOL(may_umount); -static void umount_tree(struct vfsmount *mnt) +static void release_mounts(struct list_head *head) +{ + struct vfsmount *mnt; + while(!list_empty(head)) { + mnt = list_entry(head->next, struct vfsmount, mnt_hash); + list_del_init(&mnt->mnt_hash); + if (mnt->mnt_parent != mnt) { + struct dentry *dentry; + struct vfsmount *m; + spin_lock(&vfsmount_lock); + dentry = mnt->mnt_mountpoint; + m = mnt->mnt_parent; + mnt->mnt_mountpoint = mnt->mnt_root; + mnt->mnt_parent = mnt; + spin_unlock(&vfsmount_lock); + dput(dentry); + mntput(m); + } + mntput(mnt); + } +} + +static void umount_tree(struct vfsmount *mnt, struct list_head *kill) { struct vfsmount *p; - LIST_HEAD(kill); for (p = mnt; p; p = next_mnt(p, mnt)) { - list_del(&p->mnt_list); - list_add(&p->mnt_list, &kill); - __touch_namespace(p->mnt_namespace); - p->mnt_namespace = NULL; + list_del(&p->mnt_hash); + list_add(&p->mnt_hash, kill); } - while (!list_empty(&kill)) { - mnt = list_entry(kill.next, struct vfsmount, mnt_list); - list_del_init(&mnt->mnt_list); - list_del_init(&mnt->mnt_expire); - if (mnt->mnt_parent == mnt) { - spin_unlock(&vfsmount_lock); - } else { - struct nameidata old_nd; - detach_mnt(mnt, &old_nd); - spin_unlock(&vfsmount_lock); - path_release(&old_nd); - } - mntput(mnt); - spin_lock(&vfsmount_lock); + list_for_each_entry(p, kill, mnt_hash) { + list_del_init(&p->mnt_expire); + list_del_init(&p->mnt_list); + __touch_namespace(p->mnt_namespace); + p->mnt_namespace = NULL; + list_del_init(&p->mnt_child); + if (p->mnt_parent != p) + mnt->mnt_mountpoint->d_mounted--; } } @@ -427,6 +440,7 @@ static int do_umount(struct vfsmount *mnt, int flags) { struct super_block *sb = mnt->mnt_sb; int retval; + LIST_HEAD(umount_list); retval = security_sb_umount(mnt, flags); if (retval) @@ -497,13 +511,14 @@ static int do_umount(struct vfsmount *mnt, int flags) retval = -EBUSY; if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) { if (!list_empty(&mnt->mnt_list)) - umount_tree(mnt); + umount_tree(mnt, &umount_list); retval = 0; } spin_unlock(&vfsmount_lock); if (retval) security_sb_umount_busy(mnt); up_write(¤t->namespace->sem); + release_mounts(&umount_list); return retval; } @@ -616,9 +631,11 @@ static struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry) return res; Enomem: if (res) { + LIST_HEAD(umount_list); spin_lock(&vfsmount_lock); - umount_tree(res); + umount_tree(res, &umount_list); spin_unlock(&vfsmount_lock); + release_mounts(&umount_list); } return NULL; } @@ -698,9 +715,11 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) err = graft_tree(mnt, nd); if (err) { + LIST_HEAD(umount_list); spin_lock(&vfsmount_lock); - umount_tree(mnt); + umount_tree(mnt, &umount_list); spin_unlock(&vfsmount_lock); + release_mounts(&umount_list); } out: @@ -875,7 +894,8 @@ unlock: EXPORT_SYMBOL_GPL(do_add_mount); -static void expire_mount(struct vfsmount *mnt, struct list_head *mounts) +static void expire_mount(struct vfsmount *mnt, struct list_head *mounts, + struct list_head *umounts) { spin_lock(&vfsmount_lock); @@ -893,16 +913,12 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts) * contributed by the vfsmount parent and the mntget above */ if (atomic_read(&mnt->mnt_count) == 2) { - struct nameidata old_nd; - /* delete from the namespace */ touch_namespace(mnt->mnt_namespace); list_del_init(&mnt->mnt_list); mnt->mnt_namespace = NULL; - detach_mnt(mnt, &old_nd); + umount_tree(mnt, umounts); spin_unlock(&vfsmount_lock); - path_release(&old_nd); - mntput(mnt); } else { /* * Someone brought it back to life whilst we didn't have any @@ -951,6 +967,7 @@ void mark_mounts_for_expiry(struct list_head *mounts) * - dispose of the corpse */ while (!list_empty(&graveyard)) { + LIST_HEAD(umounts); mnt = list_entry(graveyard.next, struct vfsmount, mnt_expire); list_del_init(&mnt->mnt_expire); @@ -963,12 +980,11 @@ void mark_mounts_for_expiry(struct list_head *mounts) spin_unlock(&vfsmount_lock); down_write(&namespace->sem); - expire_mount(mnt, mounts); + expire_mount(mnt, mounts, &umounts); up_write(&namespace->sem); - + release_mounts(&umounts); mntput(mnt); put_namespace(namespace); - spin_lock(&vfsmount_lock); } @@ -1508,12 +1524,14 @@ void __init mnt_init(unsigned long mempages) void __put_namespace(struct namespace *namespace) { struct vfsmount *root = namespace->root; + LIST_HEAD(umount_list); namespace->root = NULL; spin_unlock(&vfsmount_lock); down_write(&namespace->sem); spin_lock(&vfsmount_lock); - umount_tree(root); + umount_tree(root, &umount_list); spin_unlock(&vfsmount_lock); up_write(&namespace->sem); + release_mounts(&umount_list); kfree(namespace); } -- cgit v1.2.3 From 36341f64569b0c4572478237ec5ed318f0762510 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:17:22 -0500 Subject: [PATCH] mount expiry fixes - clean up the ugliness in may_umount_tree() - fix a bug in do_loopback(). after cloning a tree, do_loopback() unlinks only the topmost mount of the cloned tree, leaving behind the children mounts on their corresponding expiry list. Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 64 ++++++++++++++++++++-------------------------------------- 1 file changed, 22 insertions(+), 42 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index c2ffa0f349f..65f9c0ecc21 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -27,6 +27,8 @@ extern int __init init_rootfs(void); +#define CL_EXPIRE 0x01 + #ifdef CONFIG_SYSFS extern int __init sysfs_init(void); #else @@ -165,7 +167,8 @@ static struct vfsmount *next_mnt(struct vfsmount *p, struct vfsmount *root) return list_entry(next, struct vfsmount, mnt_child); } -static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root) +static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, + int flag) { struct super_block *sb = old->mnt_sb; struct vfsmount *mnt = alloc_vfsmnt(old->mnt_devname); @@ -181,10 +184,12 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root) /* stick the duplicate mount on the same expiry list * as the original if that was on one */ - spin_lock(&vfsmount_lock); - if (!list_empty(&old->mnt_expire)) - list_add(&mnt->mnt_expire, &old->mnt_expire); - spin_unlock(&vfsmount_lock); + if (flag & CL_EXPIRE) { + spin_lock(&vfsmount_lock); + if (!list_empty(&old->mnt_expire)) + list_add(&mnt->mnt_expire, &old->mnt_expire); + spin_unlock(&vfsmount_lock); + } } return mnt; } @@ -331,36 +336,14 @@ struct seq_operations mounts_op = { */ int may_umount_tree(struct vfsmount *mnt) { - struct list_head *next; - struct vfsmount *this_parent = mnt; - int actual_refs; - int minimum_refs; + int actual_refs = 0; + int minimum_refs = 0; + struct vfsmount *p; spin_lock(&vfsmount_lock); - actual_refs = atomic_read(&mnt->mnt_count); - minimum_refs = 2; -repeat: - next = this_parent->mnt_mounts.next; -resume: - while (next != &this_parent->mnt_mounts) { - struct vfsmount *p = - list_entry(next, struct vfsmount, mnt_child); - - next = next->next; - + for (p = mnt; p; p = next_mnt(p, mnt)) { actual_refs += atomic_read(&p->mnt_count); minimum_refs += 2; - - if (!list_empty(&p->mnt_mounts)) { - this_parent = p; - goto repeat; - } - } - - if (this_parent != mnt) { - next = this_parent->mnt_child.next; - this_parent = this_parent->mnt_parent; - goto resume; } spin_unlock(&vfsmount_lock); @@ -596,12 +579,13 @@ static int lives_below_in_same_fs(struct dentry *d, struct dentry *dentry) } } -static struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry) +static struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, + int flag) { struct vfsmount *res, *p, *q, *r, *s; struct nameidata nd; - res = q = clone_mnt(mnt, dentry); + res = q = clone_mnt(mnt, dentry, flag); if (!q) goto Enomem; q->mnt_mountpoint = mnt->mnt_mountpoint; @@ -619,7 +603,7 @@ static struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry) p = s; nd.mnt = q; nd.dentry = p->mnt_mountpoint; - q = clone_mnt(p, p->mnt_root); + q = clone_mnt(p, p->mnt_root, flag); if (!q) goto Enomem; spin_lock(&vfsmount_lock); @@ -701,18 +685,13 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) err = -ENOMEM; if (recurse) - mnt = copy_tree(old_nd.mnt, old_nd.dentry); + mnt = copy_tree(old_nd.mnt, old_nd.dentry, 0); else - mnt = clone_mnt(old_nd.mnt, old_nd.dentry); + mnt = clone_mnt(old_nd.mnt, old_nd.dentry, 0); if (!mnt) goto out; - /* stop bind mounts from expiring */ - spin_lock(&vfsmount_lock); - list_del_init(&mnt->mnt_expire); - spin_unlock(&vfsmount_lock); - err = graft_tree(mnt, nd); if (err) { LIST_HEAD(umount_list); @@ -1155,7 +1134,8 @@ int copy_namespace(int flags, struct task_struct *tsk) down_write(&tsk->namespace->sem); /* First pass: copy the tree topology */ - new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root); + new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root, + CL_EXPIRE); if (!new_ns->root) { up_write(&tsk->namespace->sem); kfree(new_ns); -- cgit v1.2.3 From 390c684367de37e1c2f9005cf92f7a746c69fdd3 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:17:51 -0500 Subject: [PATCH] making namespace_sem global This removes the per-namespace semaphore in favor of a global semaphore. This can have an effect on namespace scalability. Signed-off-by: Miklos Szeredi Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 46 +++++++++++++++++++++++----------------------- include/linux/namespace.h | 1 - 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 65f9c0ecc21..4abee9ab009 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -46,6 +46,7 @@ static int event; static struct list_head *mount_hashtable; static int hash_mask __read_mostly, hash_bits __read_mostly; static kmem_cache_t *mnt_cache; +static struct rw_semaphore namespace_sem; static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry) { @@ -250,7 +251,7 @@ static void *m_start(struct seq_file *m, loff_t *pos) struct list_head *p; loff_t l = *pos; - down_read(&n->sem); + down_read(&namespace_sem); list_for_each(p, &n->list) if (!l--) return list_entry(p, struct vfsmount, mnt_list); @@ -267,8 +268,7 @@ static void *m_next(struct seq_file *m, void *v, loff_t *pos) static void m_stop(struct seq_file *m, void *v) { - struct namespace *n = m->private; - up_read(&n->sem); + up_read(&namespace_sem); } static inline void mangle(struct seq_file *m, const char *s) @@ -487,7 +487,7 @@ static int do_umount(struct vfsmount *mnt, int flags) return retval; } - down_write(¤t->namespace->sem); + down_write(&namespace_sem); spin_lock(&vfsmount_lock); event++; @@ -500,7 +500,7 @@ static int do_umount(struct vfsmount *mnt, int flags) spin_unlock(&vfsmount_lock); if (retval) security_sb_umount_busy(mnt); - up_write(¤t->namespace->sem); + up_write(&namespace_sem); release_mounts(&umount_list); return retval; } @@ -678,7 +678,7 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) if (err) return err; - down_write(¤t->namespace->sem); + down_write(&namespace_sem); err = -EINVAL; if (!check_mnt(nd->mnt) || !check_mnt(old_nd.mnt)) goto out; @@ -702,7 +702,7 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) } out: - up_write(¤t->namespace->sem); + up_write(&namespace_sem); path_release(&old_nd); return err; } @@ -750,7 +750,7 @@ static int do_move_mount(struct nameidata *nd, char *old_name) if (err) return err; - down_write(¤t->namespace->sem); + down_write(&namespace_sem); while (d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) ; err = -EINVAL; @@ -795,7 +795,7 @@ out2: out1: up(&nd->dentry->d_inode->i_sem); out: - up_write(¤t->namespace->sem); + up_write(&namespace_sem); if (!err) path_release(&parent_nd); path_release(&old_nd); @@ -834,7 +834,7 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, { int err; - down_write(¤t->namespace->sem); + down_write(&namespace_sem); /* Something was mounted here while we slept */ while (d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) ; @@ -862,11 +862,11 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, list_add_tail(&newmnt->mnt_expire, fslist); spin_unlock(&vfsmount_lock); } - up_write(¤t->namespace->sem); + up_write(&namespace_sem); return 0; unlock: - up_write(¤t->namespace->sem); + up_write(&namespace_sem); mntput(newmnt); return err; } @@ -958,9 +958,9 @@ void mark_mounts_for_expiry(struct list_head *mounts) get_namespace(namespace); spin_unlock(&vfsmount_lock); - down_write(&namespace->sem); + down_write(&namespace_sem); expire_mount(mnt, mounts, &umounts); - up_write(&namespace->sem); + up_write(&namespace_sem); release_mounts(&umounts); mntput(mnt); put_namespace(namespace); @@ -1127,17 +1127,16 @@ int copy_namespace(int flags, struct task_struct *tsk) goto out; atomic_set(&new_ns->count, 1); - init_rwsem(&new_ns->sem); INIT_LIST_HEAD(&new_ns->list); init_waitqueue_head(&new_ns->poll); new_ns->event = 0; - down_write(&tsk->namespace->sem); + down_write(&namespace_sem); /* First pass: copy the tree topology */ new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root, CL_EXPIRE); if (!new_ns->root) { - up_write(&tsk->namespace->sem); + up_write(&namespace_sem); kfree(new_ns); goto out; } @@ -1171,7 +1170,7 @@ int copy_namespace(int flags, struct task_struct *tsk) p = next_mnt(p, namespace->root); q = next_mnt(q, new_ns->root); } - up_write(&tsk->namespace->sem); + up_write(&namespace_sem); tsk->namespace = new_ns; @@ -1356,7 +1355,7 @@ asmlinkage long sys_pivot_root(const char __user * new_root, user_nd.mnt = mntget(current->fs->rootmnt); user_nd.dentry = dget(current->fs->root); read_unlock(¤t->fs->lock); - down_write(¤t->namespace->sem); + down_write(&namespace_sem); down(&old_nd.dentry->d_inode->i_sem); error = -EINVAL; if (!check_mnt(user_nd.mnt)) @@ -1407,7 +1406,7 @@ asmlinkage long sys_pivot_root(const char __user * new_root, path_release(&parent_nd); out2: up(&old_nd.dentry->d_inode->i_sem); - up_write(¤t->namespace->sem); + up_write(&namespace_sem); path_release(&user_nd); path_release(&old_nd); out1: @@ -1434,7 +1433,6 @@ static void __init init_mount_tree(void) panic("Can't allocate initial namespace"); atomic_set(&namespace->count, 1); INIT_LIST_HEAD(&namespace->list); - init_rwsem(&namespace->sem); init_waitqueue_head(&namespace->poll); namespace->event = 0; list_add(&mnt->mnt_list, &namespace->list); @@ -1459,6 +1457,8 @@ void __init mnt_init(unsigned long mempages) unsigned int nr_hash; int i; + init_rwsem(&namespace_sem); + mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct vfsmount), 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL, NULL); @@ -1507,11 +1507,11 @@ void __put_namespace(struct namespace *namespace) LIST_HEAD(umount_list); namespace->root = NULL; spin_unlock(&vfsmount_lock); - down_write(&namespace->sem); + down_write(&namespace_sem); spin_lock(&vfsmount_lock); umount_tree(root, &umount_list); spin_unlock(&vfsmount_lock); - up_write(&namespace->sem); + up_write(&namespace_sem); release_mounts(&umount_list); kfree(namespace); } diff --git a/include/linux/namespace.h b/include/linux/namespace.h index 6f0f25d64c3..6731977c4c1 100644 --- a/include/linux/namespace.h +++ b/include/linux/namespace.h @@ -9,7 +9,6 @@ struct namespace { atomic_t count; struct vfsmount * root; struct list_head list; - struct rw_semaphore sem; wait_queue_head_t poll; int event; }; -- cgit v1.2.3 From 07b20889e3052c7e77d6a6a54e7e83446eb1ba84 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:19:07 -0500 Subject: [PATCH] beginning of the shared-subtree proper A private mount does not forward or receive propagation. This patch provides user the ability to convert any mount to private. Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/Makefile | 2 +- fs/namespace.c | 24 ++++++++++++++++++++++++ fs/pnode.c | 17 +++++++++++++++++ fs/pnode.h | 14 ++++++++++++++ include/linux/fs.h | 1 + include/linux/mount.h | 10 +++++----- 6 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 fs/pnode.c create mode 100644 fs/pnode.h diff --git a/fs/Makefile b/fs/Makefile index 1972da18627..4c265575907 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -10,7 +10,7 @@ obj-y := open.o read_write.o file_table.o buffer.o bio.o super.o \ ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \ attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \ seq_file.o xattr.o libfs.o fs-writeback.o mpage.o direct-io.o \ - ioprio.o + ioprio.o pnode.o obj-$(CONFIG_INOTIFY) += inotify.o obj-$(CONFIG_EPOLL) += eventpoll.o diff --git a/fs/namespace.c b/fs/namespace.c index 4abee9ab009..3782923d6d4 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -24,6 +24,7 @@ #include #include #include +#include "pnode.h" extern int __init init_rootfs(void); @@ -662,6 +663,27 @@ out_unlock: return err; } +/* + * recursively change the type of the mountpoint. + */ +static int do_change_type(struct nameidata *nd, int flag) +{ + struct vfsmount *m, *mnt = nd->mnt; + int recurse = flag & MS_REC; + int type = flag & ~MS_REC; + + if (nd->dentry != nd->mnt->mnt_root) + return -EINVAL; + + down_write(&namespace_sem); + spin_lock(&vfsmount_lock); + for (m = mnt; m; m = (recurse ? next_mnt(m, mnt) : NULL)) + change_mnt_propagation(m, type); + spin_unlock(&vfsmount_lock); + up_write(&namespace_sem); + return 0; +} + /* * do loopback mount. */ @@ -1091,6 +1113,8 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, data_page); else if (flags & MS_BIND) retval = do_loopback(&nd, dev_name, flags & MS_REC); + else if (flags & MS_PRIVATE) + retval = do_change_type(&nd, flags); else if (flags & MS_MOVE) retval = do_move_mount(&nd, dev_name); else diff --git a/fs/pnode.c b/fs/pnode.c new file mode 100644 index 00000000000..aaa0dffda12 --- /dev/null +++ b/fs/pnode.c @@ -0,0 +1,17 @@ +/* + * linux/fs/pnode.c + * + * (C) Copyright IBM Corporation 2005. + * Released under GPL v2. + * Author : Ram Pai (linuxram@us.ibm.com) + * + */ +#include +#include +#include +#include "pnode.h" + +void change_mnt_propagation(struct vfsmount *mnt, int type) +{ + mnt->mnt_flags &= ~MNT_PNODE_MASK; +} diff --git a/fs/pnode.h b/fs/pnode.h new file mode 100644 index 00000000000..33549a3a74e --- /dev/null +++ b/fs/pnode.h @@ -0,0 +1,14 @@ +/* + * linux/fs/pnode.h + * + * (C) Copyright IBM Corporation 2005. + * Released under GPL v2. + * + */ +#ifndef _LINUX_PNODE_H +#define _LINUX_PNODE_H + +#include +#include +void change_mnt_propagation(struct vfsmount *, int); +#endif /* _LINUX_PNODE_H */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 9a593ef262e..6c431086abb 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -104,6 +104,7 @@ extern int dir_notify_enable; #define MS_MOVE 8192 #define MS_REC 16384 #define MS_VERBOSE 32768 +#define MS_PRIVATE (1<<18) /* change to private */ #define MS_POSIXACL (1<<16) /* VFS does not apply the umask */ #define MS_ACTIVE (1<<30) #define MS_NOUSER (1<<31) diff --git a/include/linux/mount.h b/include/linux/mount.h index ffb0b508988..8eadd3b6589 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -17,12 +17,12 @@ #include #include -#define MNT_NOSUID 1 -#define MNT_NODEV 2 -#define MNT_NOEXEC 4 +#define MNT_NOSUID 0x01 +#define MNT_NODEV 0x02 +#define MNT_NOEXEC 0x04 +#define MNT_PNODE_MASK 0x30 /* propogation flag mask */ -struct vfsmount -{ +struct vfsmount { struct list_head mnt_hash; struct vfsmount *mnt_parent; /* fs we are mounted on */ struct dentry *mnt_mountpoint; /* dentry of mountpoint */ -- cgit v1.2.3 From 03e06e68ff76294e53ffa898cb844d2a997b043e Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:19:33 -0500 Subject: [PATCH] introduce shared mounts This creates shared mounts. A shared mount when bind-mounted to some mountpoint, propagates mount/umount events to each other. All the shared mounts that propagate events to each other belong to the same peer-group. Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 3 ++- fs/pnode.c | 13 ++++++++++++- fs/pnode.h | 4 ++++ include/linux/fs.h | 1 + include/linux/mount.h | 2 ++ 5 files changed, 21 insertions(+), 2 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 3782923d6d4..f6861a5487d 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -68,6 +68,7 @@ struct vfsmount *alloc_vfsmnt(const char *name) INIT_LIST_HEAD(&mnt->mnt_mounts); INIT_LIST_HEAD(&mnt->mnt_list); INIT_LIST_HEAD(&mnt->mnt_expire); + INIT_LIST_HEAD(&mnt->mnt_share); if (name) { int size = strlen(name) + 1; char *newname = kmalloc(size, GFP_KERNEL); @@ -1113,7 +1114,7 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, data_page); else if (flags & MS_BIND) retval = do_loopback(&nd, dev_name, flags & MS_REC); - else if (flags & MS_PRIVATE) + else if (flags & (MS_SHARED | MS_PRIVATE)) retval = do_change_type(&nd, flags); else if (flags & MS_MOVE) retval = do_move_mount(&nd, dev_name); diff --git a/fs/pnode.c b/fs/pnode.c index aaa0dffda12..1e22165ea41 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -11,7 +11,18 @@ #include #include "pnode.h" +/* return the next shared peer mount of @p */ +static inline struct vfsmount *next_peer(struct vfsmount *p) +{ + return list_entry(p->mnt_share.next, struct vfsmount, mnt_share); +} + void change_mnt_propagation(struct vfsmount *mnt, int type) { - mnt->mnt_flags &= ~MNT_PNODE_MASK; + if (type == MS_SHARED) { + mnt->mnt_flags |= MNT_SHARED; + } else { + list_del_init(&mnt->mnt_share); + mnt->mnt_flags &= ~MNT_PNODE_MASK; + } } diff --git a/fs/pnode.h b/fs/pnode.h index 33549a3a74e..ab1bdaee4e0 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -10,5 +10,9 @@ #include #include + +#define IS_MNT_SHARED(mnt) (mnt->mnt_flags & MNT_SHARED) +#define CLEAR_MNT_SHARED(mnt) (mnt->mnt_flags &= ~MNT_SHARED) + void change_mnt_propagation(struct vfsmount *, int); #endif /* _LINUX_PNODE_H */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 6c431086abb..551fba303cf 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -105,6 +105,7 @@ extern int dir_notify_enable; #define MS_REC 16384 #define MS_VERBOSE 32768 #define MS_PRIVATE (1<<18) /* change to private */ +#define MS_SHARED (1<<20) /* change to shared */ #define MS_POSIXACL (1<<16) /* VFS does not apply the umask */ #define MS_ACTIVE (1<<30) #define MS_NOUSER (1<<31) diff --git a/include/linux/mount.h b/include/linux/mount.h index 8eadd3b6589..2582559718f 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -20,6 +20,7 @@ #define MNT_NOSUID 0x01 #define MNT_NODEV 0x02 #define MNT_NOEXEC 0x04 +#define MNT_SHARED 0x10 /* if the vfsmount is a shared mount */ #define MNT_PNODE_MASK 0x30 /* propogation flag mask */ struct vfsmount { @@ -36,6 +37,7 @@ struct vfsmount { char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */ struct list_head mnt_list; struct list_head mnt_expire; /* link in fs-specific expiry list */ + struct list_head mnt_share; /* circular list of shared mounts */ struct namespace *mnt_namespace; /* containing namespace */ int mnt_pinned; }; -- cgit v1.2.3 From b90fa9ae8f51f098ee480bbaabd6867992e9fc58 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:19:50 -0500 Subject: [PATCH] shared mount handling: bind and rbind Implement handling of MS_BIND in presense of shared mounts (see Documentation/sharedsubtree.txt in the end of patch series for detailed description). Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 126 ++++++++++++++++++++++++++++++++++++++++++++--------- fs/pnode.c | 81 +++++++++++++++++++++++++++++++++- fs/pnode.h | 14 ++++++ include/linux/fs.h | 5 +++ 4 files changed, 204 insertions(+), 22 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index f6861a5487d..9f5a084b239 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -28,8 +28,6 @@ extern int __init init_rootfs(void); -#define CL_EXPIRE 0x01 - #ifdef CONFIG_SYSFS extern int __init sysfs_init(void); #else @@ -145,13 +143,43 @@ static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd) old_nd->dentry->d_mounted--; } +void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, + struct vfsmount *child_mnt) +{ + child_mnt->mnt_parent = mntget(mnt); + child_mnt->mnt_mountpoint = dget(dentry); + dentry->d_mounted++; +} + static void attach_mnt(struct vfsmount *mnt, struct nameidata *nd) { - mnt->mnt_parent = mntget(nd->mnt); - mnt->mnt_mountpoint = dget(nd->dentry); - list_add(&mnt->mnt_hash, mount_hashtable + hash(nd->mnt, nd->dentry)); + mnt_set_mountpoint(nd->mnt, nd->dentry, mnt); + list_add_tail(&mnt->mnt_hash, mount_hashtable + + hash(nd->mnt, nd->dentry)); list_add_tail(&mnt->mnt_child, &nd->mnt->mnt_mounts); - nd->dentry->d_mounted++; +} + +/* + * the caller must hold vfsmount_lock + */ +static void commit_tree(struct vfsmount *mnt) +{ + struct vfsmount *parent = mnt->mnt_parent; + struct vfsmount *m; + LIST_HEAD(head); + struct namespace *n = parent->mnt_namespace; + + BUG_ON(parent == mnt); + + list_add_tail(&head, &mnt->mnt_list); + list_for_each_entry(m, &head, mnt_list) + m->mnt_namespace = n; + list_splice(&head, n->list.prev); + + list_add_tail(&mnt->mnt_hash, mount_hashtable + + hash(parent, mnt->mnt_mountpoint)); + list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); + touch_namespace(n); } static struct vfsmount *next_mnt(struct vfsmount *p, struct vfsmount *root) @@ -183,7 +211,11 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, mnt->mnt_root = dget(root); mnt->mnt_mountpoint = mnt->mnt_root; mnt->mnt_parent = mnt; - mnt->mnt_namespace = current->namespace; + + if ((flag & CL_PROPAGATION) || IS_MNT_SHARED(old)) + list_add(&mnt->mnt_share, &old->mnt_share); + if (flag & CL_MAKE_SHARED) + set_mnt_shared(mnt); /* stick the duplicate mount on the same expiry list * as the original if that was on one */ @@ -379,7 +411,7 @@ int may_umount(struct vfsmount *mnt) EXPORT_SYMBOL(may_umount); -static void release_mounts(struct list_head *head) +void release_mounts(struct list_head *head) { struct vfsmount *mnt; while(!list_empty(head)) { @@ -401,7 +433,7 @@ static void release_mounts(struct list_head *head) } } -static void umount_tree(struct vfsmount *mnt, struct list_head *kill) +void umount_tree(struct vfsmount *mnt, struct list_head *kill) { struct vfsmount *p; @@ -581,7 +613,7 @@ static int lives_below_in_same_fs(struct dentry *d, struct dentry *dentry) } } -static struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, +struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, int flag) { struct vfsmount *res, *p, *q, *r, *s; @@ -626,6 +658,67 @@ Enomem: return NULL; } +/* + * @source_mnt : mount tree to be attached + * @nd : place the mount tree @source_mnt is attached + * + * NOTE: in the table below explains the semantics when a source mount + * of a given type is attached to a destination mount of a given type. + * --------------------------------------------- + * | BIND MOUNT OPERATION | + * |******************************************** + * | source-->| shared | private | + * | dest | | | + * | | | | | + * | v | | | + * |******************************************** + * | shared | shared (++) | shared (+) | + * | | | | + * |non-shared| shared (+) | private | + * ********************************************* + * A bind operation clones the source mount and mounts the clone on the + * destination mount. + * + * (++) the cloned mount is propagated to all the mounts in the propagation + * tree of the destination mount and the cloned mount is added to + * the peer group of the source mount. + * (+) the cloned mount is created under the destination mount and is marked + * as shared. The cloned mount is added to the peer group of the source + * mount. + * + * if the source mount is a tree, the operations explained above is + * applied to each mount in the tree. + * Must be called without spinlocks held, since this function can sleep + * in allocations. + */ +static int attach_recursive_mnt(struct vfsmount *source_mnt, + struct nameidata *nd) +{ + LIST_HEAD(tree_list); + struct vfsmount *dest_mnt = nd->mnt; + struct dentry *dest_dentry = nd->dentry; + struct vfsmount *child, *p; + + if (propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list)) + return -EINVAL; + + if (IS_MNT_SHARED(dest_mnt)) { + for (p = source_mnt; p; p = next_mnt(p, source_mnt)) + set_mnt_shared(p); + } + + spin_lock(&vfsmount_lock); + mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt); + commit_tree(source_mnt); + + list_for_each_entry_safe(child, p, &tree_list, mnt_hash) { + list_del_init(&child->mnt_hash); + commit_tree(child); + } + spin_unlock(&vfsmount_lock); + return 0; +} + static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) { int err; @@ -646,17 +739,8 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) goto out_unlock; err = -ENOENT; - spin_lock(&vfsmount_lock); - if (IS_ROOT(nd->dentry) || !d_unhashed(nd->dentry)) { - struct list_head head; - - attach_mnt(mnt, nd); - list_add_tail(&head, &mnt->mnt_list); - list_splice(&head, current->namespace->list.prev); - err = 0; - touch_namespace(current->namespace); - } - spin_unlock(&vfsmount_lock); + if (IS_ROOT(nd->dentry) || !d_unhashed(nd->dentry)) + err = attach_recursive_mnt(mnt, nd); out_unlock: up(&nd->dentry->d_inode->i_sem); if (!err) diff --git a/fs/pnode.c b/fs/pnode.c index 1e22165ea41..2d572b88e6f 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -20,9 +20,88 @@ static inline struct vfsmount *next_peer(struct vfsmount *p) void change_mnt_propagation(struct vfsmount *mnt, int type) { if (type == MS_SHARED) { - mnt->mnt_flags |= MNT_SHARED; + set_mnt_shared(mnt); } else { list_del_init(&mnt->mnt_share); mnt->mnt_flags &= ~MNT_PNODE_MASK; } } + +/* + * get the next mount in the propagation tree. + * @m: the mount seen last + * @origin: the original mount from where the tree walk initiated + */ +static struct vfsmount *propagation_next(struct vfsmount *m, + struct vfsmount *origin) +{ + m = next_peer(m); + if (m == origin) + return NULL; + return m; +} + +/* + * mount 'source_mnt' under the destination 'dest_mnt' at + * dentry 'dest_dentry'. And propagate that mount to + * all the peer and slave mounts of 'dest_mnt'. + * Link all the new mounts into a propagation tree headed at + * source_mnt. Also link all the new mounts using ->mnt_list + * headed at source_mnt's ->mnt_list + * + * @dest_mnt: destination mount. + * @dest_dentry: destination dentry. + * @source_mnt: source mount. + * @tree_list : list of heads of trees to be attached. + */ +int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry, + struct vfsmount *source_mnt, struct list_head *tree_list) +{ + struct vfsmount *m, *child; + int ret = 0; + struct vfsmount *prev_dest_mnt = dest_mnt; + struct vfsmount *prev_src_mnt = source_mnt; + LIST_HEAD(tmp_list); + LIST_HEAD(umount_list); + + for (m = propagation_next(dest_mnt, dest_mnt); m; + m = propagation_next(m, dest_mnt)) { + int type = CL_PROPAGATION; + + if (IS_MNT_NEW(m)) + continue; + + if (IS_MNT_SHARED(m)) + type |= CL_MAKE_SHARED; + + if (!(child = copy_tree(source_mnt, source_mnt->mnt_root, + type))) { + ret = -ENOMEM; + list_splice(tree_list, tmp_list.prev); + goto out; + } + + if (is_subdir(dest_dentry, m->mnt_root)) { + mnt_set_mountpoint(m, dest_dentry, child); + list_add_tail(&child->mnt_hash, tree_list); + } else { + /* + * This can happen if the parent mount was bind mounted + * on some subdirectory of a shared/slave mount. + */ + list_add_tail(&child->mnt_hash, &tmp_list); + } + prev_dest_mnt = m; + prev_src_mnt = child; + } +out: + spin_lock(&vfsmount_lock); + while (!list_empty(&tmp_list)) { + child = list_entry(tmp_list.next, struct vfsmount, mnt_hash); + list_del_init(&child->mnt_hash); + umount_tree(child, &umount_list); + } + spin_unlock(&vfsmount_lock); + release_mounts(&umount_list); + return ret; +} diff --git a/fs/pnode.h b/fs/pnode.h index ab1bdaee4e0..c62c72fad21 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -12,7 +12,21 @@ #include #define IS_MNT_SHARED(mnt) (mnt->mnt_flags & MNT_SHARED) +#define IS_MNT_NEW(mnt) (!mnt->mnt_namespace) #define CLEAR_MNT_SHARED(mnt) (mnt->mnt_flags &= ~MNT_SHARED) +#define CL_EXPIRE 0x01 +#define CL_COPY_ALL 0x04 +#define CL_MAKE_SHARED 0x08 +#define CL_PROPAGATION 0x10 + +static inline void set_mnt_shared(struct vfsmount *mnt) +{ + mnt->mnt_flags &= ~MNT_PNODE_MASK; + mnt->mnt_flags |= MNT_SHARED; +} + void change_mnt_propagation(struct vfsmount *, int); +int propagate_mnt(struct vfsmount *, struct dentry *, struct vfsmount *, + struct list_head *); #endif /* _LINUX_PNODE_H */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 551fba303cf..5e188b773e9 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1251,7 +1251,12 @@ extern int unregister_filesystem(struct file_system_type *); extern struct vfsmount *kern_mount(struct file_system_type *); extern int may_umount_tree(struct vfsmount *); extern int may_umount(struct vfsmount *); +extern void umount_tree(struct vfsmount *, struct list_head *); +extern void release_mounts(struct list_head *); extern long do_mount(char *, char *, char *, unsigned long, void *); +extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); +extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *, + struct vfsmount *); extern int vfs_statfs(struct super_block *, struct kstatfs *); -- cgit v1.2.3 From 2144440327fa01b2f3f65e355120a78211685702 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:20:03 -0500 Subject: [PATCH] shared mounts handling: move Implement handling of mount --move in presense of shared mounts (see Documentation/sharedsubtree.txt in the end of patch series for detailed description). Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 63 ++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 9f5a084b239..1487982dbc2 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -660,7 +660,10 @@ Enomem: /* * @source_mnt : mount tree to be attached - * @nd : place the mount tree @source_mnt is attached + * @nd : place the mount tree @source_mnt is attached + * @parent_nd : if non-null, detach the source_mnt from its parent and + * store the parent mount and mountpoint dentry. + * (done when source_mnt is moved) * * NOTE: in the table below explains the semantics when a source mount * of a given type is attached to a destination mount of a given type. @@ -685,6 +688,21 @@ Enomem: * (+) the cloned mount is created under the destination mount and is marked * as shared. The cloned mount is added to the peer group of the source * mount. + * --------------------------------------------- + * | MOVE MOUNT OPERATION | + * |******************************************** + * | source-->| shared | private | + * | dest | | | + * | | | | | + * | v | | | + * |******************************************** + * | shared | shared (+) | shared (+) | + * | | | | + * |non-shared| shared (+*) | private | + * ********************************************* + * (+) the mount is moved to the destination. And is then propagated to all + * the mounts in the propagation tree of the destination mount. + * (+*) the mount is moved to the destination. * * if the source mount is a tree, the operations explained above is * applied to each mount in the tree. @@ -692,7 +710,7 @@ Enomem: * in allocations. */ static int attach_recursive_mnt(struct vfsmount *source_mnt, - struct nameidata *nd) + struct nameidata *nd, struct nameidata *parent_nd) { LIST_HEAD(tree_list); struct vfsmount *dest_mnt = nd->mnt; @@ -708,8 +726,14 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, } spin_lock(&vfsmount_lock); - mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt); - commit_tree(source_mnt); + if (parent_nd) { + detach_mnt(source_mnt, parent_nd); + attach_mnt(source_mnt, nd); + touch_namespace(current->namespace); + } else { + mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt); + commit_tree(source_mnt); + } list_for_each_entry_safe(child, p, &tree_list, mnt_hash) { list_del_init(&child->mnt_hash); @@ -740,7 +764,7 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) err = -ENOENT; if (IS_ROOT(nd->dentry) || !d_unhashed(nd->dentry)) - err = attach_recursive_mnt(mnt, nd); + err = attach_recursive_mnt(mnt, nd, NULL); out_unlock: up(&nd->dentry->d_inode->i_sem); if (!err) @@ -869,35 +893,36 @@ static int do_move_mount(struct nameidata *nd, char *old_name) if (IS_DEADDIR(nd->dentry->d_inode)) goto out1; - spin_lock(&vfsmount_lock); if (!IS_ROOT(nd->dentry) && d_unhashed(nd->dentry)) - goto out2; + goto out1; err = -EINVAL; if (old_nd.dentry != old_nd.mnt->mnt_root) - goto out2; + goto out1; if (old_nd.mnt == old_nd.mnt->mnt_parent) - goto out2; + goto out1; if (S_ISDIR(nd->dentry->d_inode->i_mode) != S_ISDIR(old_nd.dentry->d_inode->i_mode)) - goto out2; - + goto out1; + /* + * Don't move a mount residing in a shared parent. + */ + if (old_nd.mnt->mnt_parent && IS_MNT_SHARED(old_nd.mnt->mnt_parent)) + goto out1; err = -ELOOP; for (p = nd->mnt; p->mnt_parent != p; p = p->mnt_parent) if (p == old_nd.mnt) - goto out2; - err = 0; + goto out1; - detach_mnt(old_nd.mnt, &parent_nd); - attach_mnt(old_nd.mnt, nd); - touch_namespace(current->namespace); + if ((err = attach_recursive_mnt(old_nd.mnt, nd, &parent_nd))) + goto out1; + spin_lock(&vfsmount_lock); /* if the mount is moved, it should no longer be expire * automatically */ list_del_init(&old_nd.mnt->mnt_expire); -out2: spin_unlock(&vfsmount_lock); out1: up(&nd->dentry->d_inode->i_sem); @@ -1467,6 +1492,10 @@ asmlinkage long sys_pivot_root(const char __user * new_root, down_write(&namespace_sem); down(&old_nd.dentry->d_inode->i_sem); error = -EINVAL; + if (IS_MNT_SHARED(old_nd.mnt) || + IS_MNT_SHARED(new_nd.mnt->mnt_parent) || + IS_MNT_SHARED(user_nd.mnt->mnt_parent)) + goto out2; if (!check_mnt(user_nd.mnt)) goto out2; error = -ENOENT; -- cgit v1.2.3 From a05964f3917c7c55368c229d7985f8e7c9977e97 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:20:17 -0500 Subject: [PATCH] shared mounts handling: umount An unmount of a mount creates a umount event on the parent. If the parent is a shared mount, it gets propagated to all mounts in the peer group. Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 56 +++++++++++++++++++++----------- fs/pnode.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++- fs/pnode.h | 2 ++ include/linux/dcache.h | 1 + include/linux/fs.h | 2 +- 5 files changed, 128 insertions(+), 20 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 1487982dbc2..4b1af01c2fb 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -86,31 +86,44 @@ void free_vfsmnt(struct vfsmount *mnt) } /* - * Now, lookup_mnt increments the ref count before returning - * the vfsmount struct. + * find the first or last mount at @dentry on vfsmount @mnt depending on + * @dir. If @dir is set return the first mount else return the last mount. */ -struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry) +struct vfsmount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry, + int dir) { struct list_head *head = mount_hashtable + hash(mnt, dentry); struct list_head *tmp = head; struct vfsmount *p, *found = NULL; - spin_lock(&vfsmount_lock); for (;;) { - tmp = tmp->next; + tmp = dir ? tmp->next : tmp->prev; p = NULL; if (tmp == head) break; p = list_entry(tmp, struct vfsmount, mnt_hash); if (p->mnt_parent == mnt && p->mnt_mountpoint == dentry) { - found = mntget(p); + found = p; break; } } - spin_unlock(&vfsmount_lock); return found; } +/* + * lookup_mnt increments the ref count before returning + * the vfsmount struct. + */ +struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry) +{ + struct vfsmount *child_mnt; + spin_lock(&vfsmount_lock); + if ((child_mnt = __lookup_mnt(mnt, dentry, 1))) + mntget(child_mnt); + spin_unlock(&vfsmount_lock); + return child_mnt; +} + static inline int check_mnt(struct vfsmount *mnt) { return mnt->mnt_namespace == current->namespace; @@ -404,9 +417,12 @@ EXPORT_SYMBOL(may_umount_tree); */ int may_umount(struct vfsmount *mnt) { - if (atomic_read(&mnt->mnt_count) > 2) - return -EBUSY; - return 0; + int ret = 0; + spin_lock(&vfsmount_lock); + if (propagate_mount_busy(mnt, 2)) + ret = -EBUSY; + spin_unlock(&vfsmount_lock); + return ret; } EXPORT_SYMBOL(may_umount); @@ -433,7 +449,7 @@ void release_mounts(struct list_head *head) } } -void umount_tree(struct vfsmount *mnt, struct list_head *kill) +void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill) { struct vfsmount *p; @@ -442,6 +458,9 @@ void umount_tree(struct vfsmount *mnt, struct list_head *kill) list_add(&p->mnt_hash, kill); } + if (propagate) + propagate_umount(kill); + list_for_each_entry(p, kill, mnt_hash) { list_del_init(&p->mnt_expire); list_del_init(&p->mnt_list); @@ -450,6 +469,7 @@ void umount_tree(struct vfsmount *mnt, struct list_head *kill) list_del_init(&p->mnt_child); if (p->mnt_parent != p) mnt->mnt_mountpoint->d_mounted--; + change_mnt_propagation(p, MS_PRIVATE); } } @@ -526,9 +546,9 @@ static int do_umount(struct vfsmount *mnt, int flags) event++; retval = -EBUSY; - if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) { + if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) { if (!list_empty(&mnt->mnt_list)) - umount_tree(mnt, &umount_list); + umount_tree(mnt, 1, &umount_list); retval = 0; } spin_unlock(&vfsmount_lock); @@ -651,7 +671,7 @@ Enomem: if (res) { LIST_HEAD(umount_list); spin_lock(&vfsmount_lock); - umount_tree(res, &umount_list); + umount_tree(res, 0, &umount_list); spin_unlock(&vfsmount_lock); release_mounts(&umount_list); } @@ -827,7 +847,7 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) if (err) { LIST_HEAD(umount_list); spin_lock(&vfsmount_lock); - umount_tree(mnt, &umount_list); + umount_tree(mnt, 0, &umount_list); spin_unlock(&vfsmount_lock); release_mounts(&umount_list); } @@ -1023,12 +1043,12 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts, * Check that it is still dead: the count should now be 2 - as * contributed by the vfsmount parent and the mntget above */ - if (atomic_read(&mnt->mnt_count) == 2) { + if (!propagate_mount_busy(mnt, 2)) { /* delete from the namespace */ touch_namespace(mnt->mnt_namespace); list_del_init(&mnt->mnt_list); mnt->mnt_namespace = NULL; - umount_tree(mnt, umounts); + umount_tree(mnt, 1, umounts); spin_unlock(&vfsmount_lock); } else { /* @@ -1647,7 +1667,7 @@ void __put_namespace(struct namespace *namespace) spin_unlock(&vfsmount_lock); down_write(&namespace_sem); spin_lock(&vfsmount_lock); - umount_tree(root, &umount_list); + umount_tree(root, 0, &umount_list); spin_unlock(&vfsmount_lock); up_write(&namespace_sem); release_mounts(&umount_list); diff --git a/fs/pnode.c b/fs/pnode.c index 2d572b88e6f..7bc942d047c 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -99,9 +99,94 @@ out: while (!list_empty(&tmp_list)) { child = list_entry(tmp_list.next, struct vfsmount, mnt_hash); list_del_init(&child->mnt_hash); - umount_tree(child, &umount_list); + umount_tree(child, 0, &umount_list); } spin_unlock(&vfsmount_lock); release_mounts(&umount_list); return ret; } + +/* + * return true if the refcount is greater than count + */ +static inline int do_refcount_check(struct vfsmount *mnt, int count) +{ + int mycount = atomic_read(&mnt->mnt_count); + return (mycount > count); +} + +/* + * check if the mount 'mnt' can be unmounted successfully. + * @mnt: the mount to be checked for unmount + * NOTE: unmounting 'mnt' would naturally propagate to all + * other mounts its parent propagates to. + * Check if any of these mounts that **do not have submounts** + * have more references than 'refcnt'. If so return busy. + */ +int propagate_mount_busy(struct vfsmount *mnt, int refcnt) +{ + struct vfsmount *m, *child; + struct vfsmount *parent = mnt->mnt_parent; + int ret = 0; + + if (mnt == parent) + return do_refcount_check(mnt, refcnt); + + /* + * quickly check if the current mount can be unmounted. + * If not, we don't have to go checking for all other + * mounts + */ + if (!list_empty(&mnt->mnt_mounts) || do_refcount_check(mnt, refcnt)) + return 1; + + for (m = propagation_next(parent, parent); m; + m = propagation_next(m, parent)) { + child = __lookup_mnt(m, mnt->mnt_mountpoint, 0); + if (child && list_empty(&child->mnt_mounts) && + (ret = do_refcount_check(child, 1))) + break; + } + return ret; +} + +/* + * NOTE: unmounting 'mnt' naturally propagates to all other mounts its + * parent propagates to. + */ +static void __propagate_umount(struct vfsmount *mnt) +{ + struct vfsmount *parent = mnt->mnt_parent; + struct vfsmount *m; + + BUG_ON(parent == mnt); + + for (m = propagation_next(parent, parent); m; + m = propagation_next(m, parent)) { + + struct vfsmount *child = __lookup_mnt(m, + mnt->mnt_mountpoint, 0); + /* + * umount the child only if the child has no + * other children + */ + if (child && list_empty(&child->mnt_mounts)) { + list_del(&child->mnt_hash); + list_add_tail(&child->mnt_hash, &mnt->mnt_hash); + } + } +} + +/* + * collect all mounts that receive propagation from the mount in @list, + * and return these additional mounts in the same list. + * @list: the list of mounts to be unmounted. + */ +int propagate_umount(struct list_head *list) +{ + struct vfsmount *mnt; + + list_for_each_entry(mnt, list, mnt_hash) + __propagate_umount(mnt); + return 0; +} diff --git a/fs/pnode.h b/fs/pnode.h index c62c72fad21..9b88ba06794 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -29,4 +29,6 @@ static inline void set_mnt_shared(struct vfsmount *mnt) void change_mnt_propagation(struct vfsmount *, int); int propagate_mnt(struct vfsmount *, struct dentry *, struct vfsmount *, struct list_head *); +int propagate_umount(struct list_head *); +int propagate_mount_busy(struct vfsmount *, int); #endif /* _LINUX_PNODE_H */ diff --git a/include/linux/dcache.h b/include/linux/dcache.h index ab04b4f9b0d..46a2ba61759 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -329,6 +329,7 @@ static inline int d_mountpoint(struct dentry *dentry) } extern struct vfsmount *lookup_mnt(struct vfsmount *, struct dentry *); +extern struct vfsmount *__lookup_mnt(struct vfsmount *, struct dentry *, int); extern struct dentry *lookup_create(struct nameidata *nd, int is_dir); extern int sysctl_vfs_cache_pressure; diff --git a/include/linux/fs.h b/include/linux/fs.h index 5e188b773e9..8bdb504be73 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1251,7 +1251,7 @@ extern int unregister_filesystem(struct file_system_type *); extern struct vfsmount *kern_mount(struct file_system_type *); extern int may_umount_tree(struct vfsmount *); extern int may_umount(struct vfsmount *); -extern void umount_tree(struct vfsmount *, struct list_head *); +extern void umount_tree(struct vfsmount *, int, struct list_head *); extern void release_mounts(struct list_head *); extern long do_mount(char *, char *, char *, unsigned long, void *); extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); -- cgit v1.2.3 From a58b0eb8e64b78d9315a5491955e78b1391d42e5 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:20:48 -0500 Subject: [PATCH] introduce slave mounts A slave mount always has a master mount from which it receives mount/umount events. Unlike shared mount the event propagation does not flow from the slave mount to the master. Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 4 +++- fs/pnode.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++--- fs/pnode.h | 2 ++ include/linux/fs.h | 1 + include/linux/mount.h | 3 +++ 5 files changed, 60 insertions(+), 4 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 4b1af01c2fb..46f99bc585b 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -67,6 +67,8 @@ struct vfsmount *alloc_vfsmnt(const char *name) INIT_LIST_HEAD(&mnt->mnt_list); INIT_LIST_HEAD(&mnt->mnt_expire); INIT_LIST_HEAD(&mnt->mnt_share); + INIT_LIST_HEAD(&mnt->mnt_slave_list); + INIT_LIST_HEAD(&mnt->mnt_slave); if (name) { int size = strlen(name) + 1; char *newname = kmalloc(size, GFP_KERNEL); @@ -1243,7 +1245,7 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, data_page); else if (flags & MS_BIND) retval = do_loopback(&nd, dev_name, flags & MS_REC); - else if (flags & (MS_SHARED | MS_PRIVATE)) + else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE)) retval = do_change_type(&nd, flags); else if (flags & MS_MOVE) retval = do_move_mount(&nd, dev_name); diff --git a/fs/pnode.c b/fs/pnode.c index 7bc942d047c..f73eba24f1d 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -17,13 +17,61 @@ static inline struct vfsmount *next_peer(struct vfsmount *p) return list_entry(p->mnt_share.next, struct vfsmount, mnt_share); } +static int do_make_slave(struct vfsmount *mnt) +{ + struct vfsmount *peer_mnt = mnt, *master = mnt->mnt_master; + struct vfsmount *slave_mnt; + + /* + * slave 'mnt' to a peer mount that has the + * same root dentry. If none is available than + * slave it to anything that is available. + */ + while ((peer_mnt = next_peer(peer_mnt)) != mnt && + peer_mnt->mnt_root != mnt->mnt_root) ; + + if (peer_mnt == mnt) { + peer_mnt = next_peer(mnt); + if (peer_mnt == mnt) + peer_mnt = NULL; + } + list_del_init(&mnt->mnt_share); + + if (peer_mnt) + master = peer_mnt; + + if (master) { + list_for_each_entry(slave_mnt, &mnt->mnt_slave_list, mnt_slave) + slave_mnt->mnt_master = master; + list_del(&mnt->mnt_slave); + list_add(&mnt->mnt_slave, &master->mnt_slave_list); + list_splice(&mnt->mnt_slave_list, master->mnt_slave_list.prev); + INIT_LIST_HEAD(&mnt->mnt_slave_list); + } else { + struct list_head *p = &mnt->mnt_slave_list; + while (!list_empty(p)) { + slave_mnt = list_entry(p->next, + struct vfsmount, mnt_slave); + list_del_init(&slave_mnt->mnt_slave); + slave_mnt->mnt_master = NULL; + } + } + mnt->mnt_master = master; + CLEAR_MNT_SHARED(mnt); + INIT_LIST_HEAD(&mnt->mnt_slave_list); + return 0; +} + void change_mnt_propagation(struct vfsmount *mnt, int type) { if (type == MS_SHARED) { set_mnt_shared(mnt); - } else { - list_del_init(&mnt->mnt_share); - mnt->mnt_flags &= ~MNT_PNODE_MASK; + return; + } + do_make_slave(mnt); + if (type != MS_SLAVE) { + list_del_init(&mnt->mnt_slave); + mnt->mnt_master = NULL; } } diff --git a/fs/pnode.h b/fs/pnode.h index 9b88ba06794..b59f0e9fe6b 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -12,10 +12,12 @@ #include #define IS_MNT_SHARED(mnt) (mnt->mnt_flags & MNT_SHARED) +#define IS_MNT_SLAVE(mnt) (mnt->mnt_master) #define IS_MNT_NEW(mnt) (!mnt->mnt_namespace) #define CLEAR_MNT_SHARED(mnt) (mnt->mnt_flags &= ~MNT_SHARED) #define CL_EXPIRE 0x01 +#define CL_SLAVE 0x02 #define CL_COPY_ALL 0x04 #define CL_MAKE_SHARED 0x08 #define CL_PROPAGATION 0x10 diff --git a/include/linux/fs.h b/include/linux/fs.h index 8bdb504be73..eef66f54c01 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -105,6 +105,7 @@ extern int dir_notify_enable; #define MS_REC 16384 #define MS_VERBOSE 32768 #define MS_PRIVATE (1<<18) /* change to private */ +#define MS_SLAVE (1<<19) /* change to slave */ #define MS_SHARED (1<<20) /* change to shared */ #define MS_POSIXACL (1<<16) /* VFS does not apply the umask */ #define MS_ACTIVE (1<<30) diff --git a/include/linux/mount.h b/include/linux/mount.h index 2582559718f..7e133ae2a94 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -38,6 +38,9 @@ struct vfsmount { struct list_head mnt_list; struct list_head mnt_expire; /* link in fs-specific expiry list */ struct list_head mnt_share; /* circular list of shared mounts */ + struct list_head mnt_slave_list;/* list of slave mounts */ + struct list_head mnt_slave; /* slave list entry */ + struct vfsmount *mnt_master; /* slave is on master->mnt_slave_list */ struct namespace *mnt_namespace; /* containing namespace */ int mnt_pinned; }; -- cgit v1.2.3 From 5afe00221389998a25d611dc7941c06580c29eb6 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:21:01 -0500 Subject: [PATCH] handling of slave mounts This makes bind, rbind, move, clone namespace and umount operations aware of the semantics of slave mount (see Documentation/sharedsubtree.txt in the last patch of the series for detailed description). Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 77 +++++++++++++++++++++++++++++++++++-------------------- fs/pnode.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 121 insertions(+), 37 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 46f99bc585b..08967036370 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -227,8 +227,17 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, mnt->mnt_mountpoint = mnt->mnt_root; mnt->mnt_parent = mnt; - if ((flag & CL_PROPAGATION) || IS_MNT_SHARED(old)) - list_add(&mnt->mnt_share, &old->mnt_share); + if (flag & CL_SLAVE) { + list_add(&mnt->mnt_slave, &old->mnt_slave_list); + mnt->mnt_master = old; + CLEAR_MNT_SHARED(mnt); + } else { + if ((flag & CL_PROPAGATION) || IS_MNT_SHARED(old)) + list_add(&mnt->mnt_share, &old->mnt_share); + if (IS_MNT_SLAVE(old)) + list_add(&mnt->mnt_slave, &old->mnt_slave); + mnt->mnt_master = old->mnt_master; + } if (flag & CL_MAKE_SHARED) set_mnt_shared(mnt); @@ -689,18 +698,18 @@ Enomem: * * NOTE: in the table below explains the semantics when a source mount * of a given type is attached to a destination mount of a given type. - * --------------------------------------------- - * | BIND MOUNT OPERATION | - * |******************************************** - * | source-->| shared | private | - * | dest | | | - * | | | | | - * | v | | | - * |******************************************** - * | shared | shared (++) | shared (+) | - * | | | | - * |non-shared| shared (+) | private | - * ********************************************* + * ------------------------------------------------------------- + * | BIND MOUNT OPERATION | + * |************************************************************* + * | source-->| shared | private | slave | + * | dest | | | | + * | | | | | | + * | v | | | | + * |************************************************************* + * | shared | shared (++) | shared (+) | shared(+++)| + * | | | | | + * |non-shared| shared (+) | private | slave (*) | + * ************************************************************** * A bind operation clones the source mount and mounts the clone on the * destination mount. * @@ -710,21 +719,33 @@ Enomem: * (+) the cloned mount is created under the destination mount and is marked * as shared. The cloned mount is added to the peer group of the source * mount. - * --------------------------------------------- - * | MOVE MOUNT OPERATION | - * |******************************************** - * | source-->| shared | private | - * | dest | | | - * | | | | | - * | v | | | - * |******************************************** - * | shared | shared (+) | shared (+) | - * | | | | - * |non-shared| shared (+*) | private | - * ********************************************* - * (+) the mount is moved to the destination. And is then propagated to all - * the mounts in the propagation tree of the destination mount. + * (+++) the mount is propagated to all the mounts in the propagation tree + * of the destination mount and the cloned mount is made slave + * of the same master as that of the source mount. The cloned mount + * is marked as 'shared and slave'. + * (*) the cloned mount is made a slave of the same master as that of the + * source mount. + * + * -------------------------------------------------------------- + * | MOVE MOUNT OPERATION | + * |************************************************************* + * | source-->| shared | private | slave | + * | dest | | | | + * | | | | | | + * | v | | | | + * |************************************************************* + * | shared | shared (+) | shared (+) | shared(+++) | + * | | | | | + * |non-shared| shared (+*) | private | slave (*) | + * ************************************************************** + * + * (+) the mount is moved to the destination. And is then propagated to + * all the mounts in the propagation tree of the destination mount. * (+*) the mount is moved to the destination. + * (+++) the mount is moved to the destination and is then propagated to + * all the mounts belonging to the destination mount's propagation tree. + * the mount is marked as 'shared and slave'. + * (*) the mount continues to be a slave at the new location. * * if the source mount is a tree, the operations explained above is * applied to each mount in the tree. diff --git a/fs/pnode.c b/fs/pnode.c index f73eba24f1d..3e266c5a307 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -17,6 +17,16 @@ static inline struct vfsmount *next_peer(struct vfsmount *p) return list_entry(p->mnt_share.next, struct vfsmount, mnt_share); } +static inline struct vfsmount *first_slave(struct vfsmount *p) +{ + return list_entry(p->mnt_slave_list.next, struct vfsmount, mnt_slave); +} + +static inline struct vfsmount *next_slave(struct vfsmount *p) +{ + return list_entry(p->mnt_slave.next, struct vfsmount, mnt_slave); +} + static int do_make_slave(struct vfsmount *mnt) { struct vfsmount *peer_mnt = mnt, *master = mnt->mnt_master; @@ -83,10 +93,64 @@ void change_mnt_propagation(struct vfsmount *mnt, int type) static struct vfsmount *propagation_next(struct vfsmount *m, struct vfsmount *origin) { - m = next_peer(m); - if (m == origin) - return NULL; - return m; + /* are there any slaves of this mount? */ + if (!IS_MNT_NEW(m) && !list_empty(&m->mnt_slave_list)) + return first_slave(m); + + while (1) { + struct vfsmount *next; + struct vfsmount *master = m->mnt_master; + + if ( master == origin->mnt_master ) { + next = next_peer(m); + return ((next == origin) ? NULL : next); + } else if (m->mnt_slave.next != &master->mnt_slave_list) + return next_slave(m); + + /* back at master */ + m = master; + } +} + +/* + * return the source mount to be used for cloning + * + * @dest the current destination mount + * @last_dest the last seen destination mount + * @last_src the last seen source mount + * @type return CL_SLAVE if the new mount has to be + * cloned as a slave. + */ +static struct vfsmount *get_source(struct vfsmount *dest, + struct vfsmount *last_dest, + struct vfsmount *last_src, + int *type) +{ + struct vfsmount *p_last_src = NULL; + struct vfsmount *p_last_dest = NULL; + *type = CL_PROPAGATION;; + + if (IS_MNT_SHARED(dest)) + *type |= CL_MAKE_SHARED; + + while (last_dest != dest->mnt_master) { + p_last_dest = last_dest; + p_last_src = last_src; + last_dest = last_dest->mnt_master; + last_src = last_src->mnt_master; + } + + if (p_last_dest) { + do { + p_last_dest = next_peer(p_last_dest); + } while (IS_MNT_NEW(p_last_dest)); + } + + if (dest != p_last_dest) { + *type |= CL_SLAVE; + return last_src; + } else + return p_last_src; } /* @@ -114,16 +178,15 @@ int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry, for (m = propagation_next(dest_mnt, dest_mnt); m; m = propagation_next(m, dest_mnt)) { - int type = CL_PROPAGATION; + int type; + struct vfsmount *source; if (IS_MNT_NEW(m)) continue; - if (IS_MNT_SHARED(m)) - type |= CL_MAKE_SHARED; + source = get_source(m, prev_dest_mnt, prev_src_mnt, &type); - if (!(child = copy_tree(source_mnt, source_mnt->mnt_root, - type))) { + if (!(child = copy_tree(source, source->mnt_root, type))) { ret = -ENOMEM; list_splice(tree_list, tmp_list.prev); goto out; -- cgit v1.2.3 From 9676f0c6389b62bd6b24d77d4b3abdbcfa32d0f2 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:21:20 -0500 Subject: [PATCH] unbindable mounts An unbindable mount does not forward or receive propagation. Also unbindable mount disallows bind mounts. The semantics is as follows. Bind semantics: It is invalid to bind mount an unbindable mount. Move semantics: It is invalid to move an unbindable mount under shared mount. Clone-namespace semantics: If a mount is unbindable in the parent namespace, the corresponding cloned mount in the child namespace becomes unbindable too. Note: there is subtle difference, unbindable mounts cannot be bind mounted but can be cloned during clone-namespace. Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 88 ++++++++++++++++++++++++++++++++++++--------------- fs/pnode.c | 2 ++ fs/pnode.h | 1 + include/linux/fs.h | 1 + include/linux/mount.h | 1 + 5 files changed, 67 insertions(+), 26 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 08967036370..caa9187f67e 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -213,6 +213,16 @@ static struct vfsmount *next_mnt(struct vfsmount *p, struct vfsmount *root) return list_entry(next, struct vfsmount, mnt_child); } +static struct vfsmount *skip_mnt_tree(struct vfsmount *p) +{ + struct list_head *prev = p->mnt_mounts.prev; + while (prev != &p->mnt_mounts) { + p = list_entry(prev, struct vfsmount, mnt_child); + prev = p->mnt_mounts.prev; + } + return p; +} + static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, int flag) { @@ -650,6 +660,9 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, struct vfsmount *res, *p, *q, *r, *s; struct nameidata nd; + if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt)) + return NULL; + res = q = clone_mnt(mnt, dentry, flag); if (!q) goto Enomem; @@ -661,6 +674,10 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, continue; for (s = r; s; s = next_mnt(s, r)) { + if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(s)) { + s = skip_mnt_tree(s); + continue; + } while (p != s->mnt_parent) { p = p->mnt_parent; q = q->mnt_parent; @@ -698,18 +715,18 @@ Enomem: * * NOTE: in the table below explains the semantics when a source mount * of a given type is attached to a destination mount of a given type. - * ------------------------------------------------------------- - * | BIND MOUNT OPERATION | - * |************************************************************* - * | source-->| shared | private | slave | - * | dest | | | | - * | | | | | | - * | v | | | | - * |************************************************************* - * | shared | shared (++) | shared (+) | shared(+++)| - * | | | | | - * |non-shared| shared (+) | private | slave (*) | - * ************************************************************** + * --------------------------------------------------------------------------- + * | BIND MOUNT OPERATION | + * |************************************************************************** + * | source-->| shared | private | slave | unbindable | + * | dest | | | | | + * | | | | | | | + * | v | | | | | + * |************************************************************************** + * | shared | shared (++) | shared (+) | shared(+++)| invalid | + * | | | | | | + * |non-shared| shared (+) | private | slave (*) | invalid | + * *************************************************************************** * A bind operation clones the source mount and mounts the clone on the * destination mount. * @@ -726,18 +743,18 @@ Enomem: * (*) the cloned mount is made a slave of the same master as that of the * source mount. * - * -------------------------------------------------------------- - * | MOVE MOUNT OPERATION | - * |************************************************************* - * | source-->| shared | private | slave | - * | dest | | | | - * | | | | | | - * | v | | | | - * |************************************************************* - * | shared | shared (+) | shared (+) | shared(+++) | - * | | | | | - * |non-shared| shared (+*) | private | slave (*) | - * ************************************************************** + * --------------------------------------------------------------------------- + * | MOVE MOUNT OPERATION | + * |************************************************************************** + * | source-->| shared | private | slave | unbindable | + * | dest | | | | | + * | | | | | | | + * | v | | | | | + * |************************************************************************** + * | shared | shared (+) | shared (+) | shared(+++) | invalid | + * | | | | | | + * |non-shared| shared (+*) | private | slave (*) | unbindable | + * *************************************************************************** * * (+) the mount is moved to the destination. And is then propagated to * all the mounts in the propagation tree of the destination mount. @@ -854,6 +871,9 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) down_write(&namespace_sem); err = -EINVAL; + if (IS_MNT_UNBINDABLE(old_nd.mnt)) + goto out; + if (!check_mnt(nd->mnt) || !check_mnt(old_nd.mnt)) goto out; @@ -911,6 +931,16 @@ static int do_remount(struct nameidata *nd, int flags, int mnt_flags, return err; } +static inline int tree_contains_unbindable(struct vfsmount *mnt) +{ + struct vfsmount *p; + for (p = mnt; p; p = next_mnt(p, mnt)) { + if (IS_MNT_UNBINDABLE(p)) + return 1; + } + return 0; +} + static int do_move_mount(struct nameidata *nd, char *old_name) { struct nameidata old_nd, parent_nd; @@ -954,6 +984,12 @@ static int do_move_mount(struct nameidata *nd, char *old_name) */ if (old_nd.mnt->mnt_parent && IS_MNT_SHARED(old_nd.mnt->mnt_parent)) goto out1; + /* + * Don't move a mount tree containing unbindable mounts to a destination + * mount which is shared. + */ + if (IS_MNT_SHARED(nd->mnt) && tree_contains_unbindable(old_nd.mnt)) + goto out1; err = -ELOOP; for (p = nd->mnt; p->mnt_parent != p; p = p->mnt_parent) if (p == old_nd.mnt) @@ -1266,7 +1302,7 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, data_page); else if (flags & MS_BIND) retval = do_loopback(&nd, dev_name, flags & MS_REC); - else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE)) + else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) retval = do_change_type(&nd, flags); else if (flags & MS_MOVE) retval = do_move_mount(&nd, dev_name); @@ -1311,7 +1347,7 @@ int copy_namespace(int flags, struct task_struct *tsk) down_write(&namespace_sem); /* First pass: copy the tree topology */ new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root, - CL_EXPIRE); + CL_COPY_ALL | CL_EXPIRE); if (!new_ns->root) { up_write(&namespace_sem); kfree(new_ns); diff --git a/fs/pnode.c b/fs/pnode.c index 3e266c5a307..aeeec8ba8dd 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -82,6 +82,8 @@ void change_mnt_propagation(struct vfsmount *mnt, int type) if (type != MS_SLAVE) { list_del_init(&mnt->mnt_slave); mnt->mnt_master = NULL; + if (type == MS_UNBINDABLE) + mnt->mnt_flags |= MNT_UNBINDABLE; } } diff --git a/fs/pnode.h b/fs/pnode.h index b59f0e9fe6b..020e1bb60fd 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -15,6 +15,7 @@ #define IS_MNT_SLAVE(mnt) (mnt->mnt_master) #define IS_MNT_NEW(mnt) (!mnt->mnt_namespace) #define CLEAR_MNT_SHARED(mnt) (mnt->mnt_flags &= ~MNT_SHARED) +#define IS_MNT_UNBINDABLE(mnt) (mnt->mnt_flags & MNT_UNBINDABLE) #define CL_EXPIRE 0x01 #define CL_SLAVE 0x02 diff --git a/include/linux/fs.h b/include/linux/fs.h index eef66f54c01..1b5f502a4b8 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -104,6 +104,7 @@ extern int dir_notify_enable; #define MS_MOVE 8192 #define MS_REC 16384 #define MS_VERBOSE 32768 +#define MS_UNBINDABLE (1<<17) /* change to unbindable */ #define MS_PRIVATE (1<<18) /* change to private */ #define MS_SLAVE (1<<19) /* change to slave */ #define MS_SHARED (1<<20) /* change to shared */ diff --git a/include/linux/mount.h b/include/linux/mount.h index 7e133ae2a94..dd4e83eba93 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -21,6 +21,7 @@ #define MNT_NODEV 0x02 #define MNT_NOEXEC 0x04 #define MNT_SHARED 0x10 /* if the vfsmount is a shared mount */ +#define MNT_UNBINDABLE 0x20 /* if the vfsmount is a unbindable mount */ #define MNT_PNODE_MASK 0x30 /* propogation flag mask */ struct vfsmount { -- cgit v1.2.3 From 9cfcceea8f7e8f5554e9c8130e568bcfa98a3a64 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:31:49 -0500 Subject: [PATCH] Complete description of shared subtrees. Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- Documentation/sharedsubtree.txt | 1060 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 1060 insertions(+) create mode 100644 Documentation/sharedsubtree.txt diff --git a/Documentation/sharedsubtree.txt b/Documentation/sharedsubtree.txt new file mode 100644 index 00000000000..2d8f403eb6e --- /dev/null +++ b/Documentation/sharedsubtree.txt @@ -0,0 +1,1060 @@ +Shared Subtrees +--------------- + +Contents: + 1) Overview + 2) Features + 3) smount command + 4) Use-case + 5) Detailed semantics + 6) Quiz + 7) FAQ + 8) Implementation + + +1) Overview +----------- + +Consider the following situation: + +A process wants to clone its own namespace, but still wants to access the CD +that got mounted recently. Shared subtree semantics provide the necessary +mechanism to accomplish the above. + +It provides the necessary building blocks for features like per-user-namespace +and versioned filesystem. + +2) Features +----------- + +Shared subtree provides four different flavors of mounts; struct vfsmount to be +precise + + a. shared mount + b. slave mount + c. private mount + d. unbindable mount + + +2a) A shared mount can be replicated to as many mountpoints and all the +replicas continue to be exactly same. + + Here is an example: + + Lets say /mnt has a mount that is shared. + mount --make-shared /mnt + + note: mount command does not yet support the --make-shared flag. + I have included a small C program which does the same by executing + 'smount /mnt shared' + + #mount --bind /mnt /tmp + The above command replicates the mount at /mnt to the mountpoint /tmp + and the contents of both the mounts remain identical. + + #ls /mnt + a b c + + #ls /tmp + a b c + + Now lets say we mount a device at /tmp/a + #mount /dev/sd0 /tmp/a + + #ls /tmp/a + t1 t2 t2 + + #ls /mnt/a + t1 t2 t2 + + Note that the mount has propagated to the mount at /mnt as well. + + And the same is true even when /dev/sd0 is mounted on /mnt/a. The + contents will be visible under /tmp/a too. + + +2b) A slave mount is like a shared mount except that mount and umount events + only propagate towards it. + + All slave mounts have a master mount which is a shared. + + Here is an example: + + Lets say /mnt has a mount which is shared. + #mount --make-shared /mnt + + Lets bind mount /mnt to /tmp + #mount --bind /mnt /tmp + + the new mount at /tmp becomes a shared mount and it is a replica of + the mount at /mnt. + + Now lets make the mount at /tmp; a slave of /mnt + #mount --make-slave /tmp + [or smount /tmp slave] + + lets mount /dev/sd0 on /mnt/a + #mount /dev/sd0 /mnt/a + + #ls /mnt/a + t1 t2 t3 + + #ls /tmp/a + t1 t2 t3 + + Note the mount event has propagated to the mount at /tmp + + However lets see what happens if we mount something on the mount at /tmp + + #mount /dev/sd1 /tmp/b + + #ls /tmp/b + s1 s2 s3 + + #ls /mnt/b + + Note how the mount event has not propagated to the mount at + /mnt + + +2c) A private mount does not forward or receive propagation. + + This is the mount we are familiar with. Its the default type. + + +2d) A unbindable mount is a unbindable private mount + + lets say we have a mount at /mnt and we make is unbindable + + #mount --make-unbindable /mnt + [ smount /mnt unbindable ] + + Lets try to bind mount this mount somewhere else. + # mount --bind /mnt /tmp + mount: wrong fs type, bad option, bad superblock on /mnt, + or too many mounted file systems + + Binding a unbindable mount is a invalid operation. + + +3) smount command + + Currently the mount command is not aware of shared subtree features. + Work is in progress to add the support in mount ( util-linux package ). + Till then use the following program. + + ------------------------------------------------------------------------ + // + //this code was developed my Miklos Szeredi + //and modified by Ram Pai + // sample usage: + // smount /tmp shared + // + #include + #include + #include + #include + #include + + #ifndef MS_REC + #define MS_REC 0x4000 /* 16384: Recursive loopback */ + #endif + + #ifndef MS_SHARED + #define MS_SHARED 1<<20 /* Shared */ + #endif + + #ifndef MS_PRIVATE + #define MS_PRIVATE 1<<18 /* Private */ + #endif + + #ifndef MS_SLAVE + #define MS_SLAVE 1<<19 /* Slave */ + #endif + + #ifndef MS_UNBINDABLE + #define MS_UNBINDABLE 1<<17 /* Unbindable */ + #endif + + int main(int argc, char *argv[]) + { + int type; + if(argc != 3) { + fprintf(stderr, "usage: %s dir " + "\n" , argv[0]); + return 1; + } + + fprintf(stdout, "%s %s %s\n", argv[0], argv[1], argv[2]); + + if (strcmp(argv[2],"rshared")==0) + type=(MS_SHARED|MS_REC); + else if (strcmp(argv[2],"rslave")==0) + type=(MS_SLAVE|MS_REC); + else if (strcmp(argv[2],"rprivate")==0) + type=(MS_PRIVATE|MS_REC); + else if (strcmp(argv[2],"runbindable")==0) + type=(MS_UNBINDABLE|MS_REC); + else if (strcmp(argv[2],"shared")==0) + type=MS_SHARED; + else if (strcmp(argv[2],"slave")==0) + type=MS_SLAVE; + else if (strcmp(argv[2],"private")==0) + type=MS_PRIVATE; + else if (strcmp(argv[2],"unbindable")==0) + type=MS_UNBINDABLE; + else { + fprintf(stderr, "invalid operation: %s\n", argv[2]); + return 1; + } + setfsuid(getuid()); + + if(mount("", argv[1], "dontcare", type, "") == -1) { + perror("mount"); + return 1; + } + return 0; + } + ----------------------------------------------------------------------- + + Copy the above code snippet into smount.c + gcc -o smount smount.c + + + (i) To mark all the mounts under /mnt as shared execute the following + command: + + smount /mnt rshared + the corresponding syntax planned for mount command is + mount --make-rshared /mnt + + just to mark a mount /mnt as shared, execute the following + command: + smount /mnt shared + the corresponding syntax planned for mount command is + mount --make-shared /mnt + + (ii) To mark all the shared mounts under /mnt as slave execute the + following + + command: + smount /mnt rslave + the corresponding syntax planned for mount command is + mount --make-rslave /mnt + + just to mark a mount /mnt as slave, execute the following + command: + smount /mnt slave + the corresponding syntax planned for mount command is + mount --make-slave /mnt + + (iii) To mark all the mounts under /mnt as private execute the + following command: + + smount /mnt rprivate + the corresponding syntax planned for mount command is + mount --make-rprivate /mnt + + just to mark a mount /mnt as private, execute the following + command: + smount /mnt private + the corresponding syntax planned for mount command is + mount --make-private /mnt + + NOTE: by default all the mounts are created as private. But if + you want to change some shared/slave/unbindable mount as + private at a later point in time, this command can help. + + (iv) To mark all the mounts under /mnt as unbindable execute the + following + + command: + smount /mnt runbindable + the corresponding syntax planned for mount command is + mount --make-runbindable /mnt + + just to mark a mount /mnt as unbindable, execute the following + command: + smount /mnt unbindable + the corresponding syntax planned for mount command is + mount --make-unbindable /mnt + + +4) Use cases +------------ + + A) A process wants to clone its own namespace, but still wants to + access the CD that got mounted recently. + + Solution: + + The system administrator can make the mount at /cdrom shared + mount --bind /cdrom /cdrom + mount --make-shared /cdrom + + Now any process that clones off a new namespace will have a + mount at /cdrom which is a replica of the same mount in the + parent namespace. + + So when a CD is inserted and mounted at /cdrom that mount gets + propagated to the other mount at /cdrom in all the other clone + namespaces. + + B) A process wants its mounts invisible to any other process, but + still be able to see the other system mounts. + + Solution: + + To begin with, the administrator can mark the entire mount tree + as shareable. + + mount --make-rshared / + + A new process can clone off a new namespace. And mark some part + of its namespace as slave + + mount --make-rslave /myprivatetree + + Hence forth any mounts within the /myprivatetree done by the + process will not show up in any other namespace. However mounts + done in the parent namespace under /myprivatetree still shows + up in the process's namespace. + + + Apart from the above semantics this feature provides the + building blocks to solve the following problems: + + C) Per-user namespace + + The above semantics allows a way to share mounts across + namespaces. But namespaces are associated with processes. If + namespaces are made first class objects with user API to + associate/disassociate a namespace with userid, then each user + could have his/her own namespace and tailor it to his/her + requirements. Offcourse its needs support from PAM. + + D) Versioned files + + If the entire mount tree is visible at multiple locations, then + a underlying versioning file system can return different + version of the file depending on the path used to access that + file. + + An example is: + + mount --make-shared / + mount --rbind / /view/v1 + mount --rbind / /view/v2 + mount --rbind / /view/v3 + mount --rbind / /view/v4 + + and if /usr has a versioning filesystem mounted, than that + mount appears at /view/v1/usr, /view/v2/usr, /view/v3/usr and + /view/v4/usr too + + A user can request v3 version of the file /usr/fs/namespace.c + by accessing /view/v3/usr/fs/namespace.c . The underlying + versioning filesystem can then decipher that v3 version of the + filesystem is being requested and return the corresponding + inode. + +5) Detailed semantics: +------------------- + The section below explains the detailed semantics of + bind, rbind, move, mount, umount and clone-namespace operations. + + Note: the word 'vfsmount' and the noun 'mount' have been used + to mean the same thing, throughout this document. + +5a) Mount states + + A given mount can be in one of the following states + 1) shared + 2) slave + 3) shared and slave + 4) private + 5) unbindable + + A 'propagation event' is defined as event generated on a vfsmount + that leads to mount or unmount actions in other vfsmounts. + + A 'peer group' is defined as a group of vfsmounts that propagate + events to each other. + + (1) Shared mounts + + A 'shared mount' is defined as a vfsmount that belongs to a + 'peer group'. + + For example: + mount --make-shared /mnt + mount --bin /mnt /tmp + + The mount at /mnt and that at /tmp are both shared and belong + to the same peer group. Anything mounted or unmounted under + /mnt or /tmp reflect in all the other mounts of its peer + group. + + + (2) Slave mounts + + A 'slave mount' is defined as a vfsmount that receives + propagation events and does not forward propagation events. + + A slave mount as the name implies has a master mount from which + mount/unmount events are received. Events do not propagate from + the slave mount to the master. Only a shared mount can be made + a slave by executing the following command + + mount --make-slave mount + + A shared mount that is made as a slave is no more shared unless + modified to become shared. + + (3) Shared and Slave + + A vfsmount can be both shared as well as slave. This state + indicates that the mount is a slave of some vfsmount, and + has its own peer group too. This vfsmount receives propagation + events from its master vfsmount, and also forwards propagation + events to its 'peer group' and to its slave vfsmounts. + + Strictly speaking, the vfsmount is shared having its own + peer group, and this peer-group is a slave of some other + peer group. + + Only a slave vfsmount can be made as 'shared and slave' by + either executing the following command + mount --make-shared mount + or by moving the slave vfsmount under a shared vfsmount. + + (4) Private mount + + A 'private mount' is defined as vfsmount that does not + receive or forward any propagation events. + + (5) Unbindable mount + + A 'unbindable mount' is defined as vfsmount that does not + receive or forward any propagation events and cannot + be bind mounted. + + + State diagram: + The state diagram below explains the state transition of a mount, + in response to various commands. + ------------------------------------------------------------------------ + | |make-shared | make-slave | make-private |make-unbindab| + --------------|------------|--------------|--------------|-------------| + |shared |shared |*slave/private| private | unbindable | + | | | | | | + |-------------|------------|--------------|--------------|-------------| + |slave |shared | **slave | private | unbindable | + | |and slave | | | | + |-------------|------------|--------------|--------------|-------------| + |shared |shared | slave | private | unbindable | + |and slave |and slave | | | | + |-------------|------------|--------------|--------------|-------------| + |private |shared | **private | private | unbindable | + |-------------|------------|--------------|--------------|-------------| + |unbindable |shared |**unbindable | private | unbindable | + ------------------------------------------------------------------------ + + * if the shared mount is the only mount in its peer group, making it + slave, makes it private automatically. Note that there is no master to + which it can be slaved to. + + ** slaving a non-shared mount has no effect on the mount. + + Apart from the commands listed below, the 'move' operation also changes + the state of a mount depending on type of the destination mount. Its + explained in section 5d. + +5b) Bind semantics + + Consider the following command + + mount --bind A/a B/b + + where 'A' is the source mount, 'a' is the dentry in the mount 'A', 'B' + is the destination mount and 'b' is the dentry in the destination mount. + + The outcome depends on the type of mount of 'A' and 'B'. The table + below contains quick reference. + --------------------------------------------------------------------------- + | BIND MOUNT OPERATION | + |************************************************************************** + |source(A)->| shared | private | slave | unbindable | + | dest(B) | | | | | + | | | | | | | + | v | | | | | + |************************************************************************** + | shared | shared | shared | shared & slave | invalid | + | | | | | | + |non-shared| shared | private | slave | invalid | + *************************************************************************** + + Details: + + 1. 'A' is a shared mount and 'B' is a shared mount. A new mount 'C' + which is clone of 'A', is created. Its root dentry is 'a' . 'C' is + mounted on mount 'B' at dentry 'b'. Also new mount 'C1', 'C2', 'C3' ... + are created and mounted at the dentry 'b' on all mounts where 'B' + propagates to. A new propagation tree containing 'C1',..,'Cn' is + created. This propagation tree is identical to the propagation tree of + 'B'. And finally the peer-group of 'C' is merged with the peer group + of 'A'. + + 2. 'A' is a private mount and 'B' is a shared mount. A new mount 'C' + which is clone of 'A', is created. Its root dentry is 'a'. 'C' is + mounted on mount 'B' at dentry 'b'. Also new mount 'C1', 'C2', 'C3' ... + are created and mounted at the dentry 'b' on all mounts where 'B' + propagates to. A new propagation tree is set containing all new mounts + 'C', 'C1', .., 'Cn' with exactly the same configuration as the + propagation tree for 'B'. + + 3. 'A' is a slave mount of mount 'Z' and 'B' is a shared mount. A new + mount 'C' which is clone of 'A', is created. Its root dentry is 'a' . + 'C' is mounted on mount 'B' at dentry 'b'. Also new mounts 'C1', 'C2', + 'C3' ... are created and mounted at the dentry 'b' on all mounts where + 'B' propagates to. A new propagation tree containing the new mounts + 'C','C1',.. 'Cn' is created. This propagation tree is identical to the + propagation tree for 'B'. And finally the mount 'C' and its peer group + is made the slave of mount 'Z'. In other words, mount 'C' is in the + state 'slave and shared'. + + 4. 'A' is a unbindable mount and 'B' is a shared mount. This is a + invalid operation. + + 5. 'A' is a private mount and 'B' is a non-shared(private or slave or + unbindable) mount. A new mount 'C' which is clone of 'A', is created. + Its root dentry is 'a'. 'C' is mounted on mount 'B' at dentry 'b'. + + 6. 'A' is a shared mount and 'B' is a non-shared mount. A new mount 'C' + which is a clone of 'A' is created. Its root dentry is 'a'. 'C' is + mounted on mount 'B' at dentry 'b'. 'C' is made a member of the + peer-group of 'A'. + + 7. 'A' is a slave mount of mount 'Z' and 'B' is a non-shared mount. A + new mount 'C' which is a clone of 'A' is created. Its root dentry is + 'a'. 'C' is mounted on mount 'B' at dentry 'b'. Also 'C' is set as a + slave mount of 'Z'. In other words 'A' and 'C' are both slave mounts of + 'Z'. All mount/unmount events on 'Z' propagates to 'A' and 'C'. But + mount/unmount on 'A' do not propagate anywhere else. Similarly + mount/unmount on 'C' do not propagate anywhere else. + + 8. 'A' is a unbindable mount and 'B' is a non-shared mount. This is a + invalid operation. A unbindable mount cannot be bind mounted. + +5c) Rbind semantics + + rbind is same as bind. Bind replicates the specified mount. Rbind + replicates all the mounts in the tree belonging to the specified mount. + Rbind mount is bind mount applied to all the mounts in the tree. + + If the source tree that is rbind has some unbindable mounts, + then the subtree under the unbindable mount is pruned in the new + location. + + eg: lets say we have the following mount tree. + + A + / \ + B C + / \ / \ + D E F G + + Lets say all the mount except the mount C in the tree are + of a type other than unbindable. + + If this tree is rbound to say Z + + We will have the following tree at the new location. + + Z + | + A' + / + B' Note how the tree under C is pruned + / \ in the new location. + D' E' + + + +5d) Move semantics + + Consider the following command + + mount --move A B/b + + where 'A' is the source mount, 'B' is the destination mount and 'b' is + the dentry in the destination mount. + + The outcome depends on the type of the mount of 'A' and 'B'. The table + below is a quick reference. + --------------------------------------------------------------------------- + | MOVE MOUNT OPERATION | + |************************************************************************** + | source(A)->| shared | private | slave | unbindable | + | dest(B) | | | | | + | | | | | | | + | v | | | | | + |************************************************************************** + | shared | shared | shared |shared and slave| invalid | + | | | | | | + |non-shared| shared | private | slave | unbindable | + *************************************************************************** + NOTE: moving a mount residing under a shared mount is invalid. + + Details follow: + + 1. 'A' is a shared mount and 'B' is a shared mount. The mount 'A' is + mounted on mount 'B' at dentry 'b'. Also new mounts 'A1', 'A2'...'An' + are created and mounted at dentry 'b' on all mounts that receive + propagation from mount 'B'. A new propagation tree is created in the + exact same configuration as that of 'B'. This new propagation tree + contains all the new mounts 'A1', 'A2'... 'An'. And this new + propagation tree is appended to the already existing propagation tree + of 'A'. + + 2. 'A' is a private mount and 'B' is a shared mount. The mount 'A' is + mounted on mount 'B' at dentry 'b'. Also new mount 'A1', 'A2'... 'An' + are created and mounted at dentry 'b' on all mounts that receive + propagation from mount 'B'. The mount 'A' becomes a shared mount and a + propagation tree is created which is identical to that of + 'B'. This new propagation tree contains all the new mounts 'A1', + 'A2'... 'An'. + + 3. 'A' is a slave mount of mount 'Z' and 'B' is a shared mount. The + mount 'A' is mounted on mount 'B' at dentry 'b'. Also new mounts 'A1', + 'A2'... 'An' are created and mounted at dentry 'b' on all mounts that + receive propagation from mount 'B'. A new propagation tree is created + in the exact same configuration as that of 'B'. This new propagation + tree contains all the new mounts 'A1', 'A2'... 'An'. And this new + propagation tree is appended to the already existing propagation tree of + 'A'. Mount 'A' continues to be the slave mount of 'Z' but it also + becomes 'shared'. + + 4. 'A' is a unbindable mount and 'B' is a shared mount. The operation + is invalid. Because mounting anything on the shared mount 'B' can + create new mounts that get mounted on the mounts that receive + propagation from 'B'. And since the mount 'A' is unbindable, cloning + it to mount at other mountpoints is not possible. + + 5. 'A' is a private mount and 'B' is a non-shared(private or slave or + unbindable) mount. The mount 'A' is mounted on mount 'B' at dentry 'b'. + + 6. 'A' is a shared mount and 'B' is a non-shared mount. The mount 'A' + is mounted on mount 'B' at dentry 'b'. Mount 'A' continues to be a + shared mount. + + 7. 'A' is a slave mount of mount 'Z' and 'B' is a non-shared mount. + The mount 'A' is mounted on mount 'B' at dentry 'b'. Mount 'A' + continues to be a slave mount of mount 'Z'. + + 8. 'A' is a unbindable mount and 'B' is a non-shared mount. The mount + 'A' is mounted on mount 'B' at dentry 'b'. Mount 'A' continues to be a + unbindable mount. + +5e) Mount semantics + + Consider the following command + + mount device B/b + + 'B' is the destination mount and 'b' is the dentry in the destination + mount. + + The above operation is the same as bind operation with the exception + that the source mount is always a private mount. + + +5f) Unmount semantics + + Consider the following command + + umount A + + where 'A' is a mount mounted on mount 'B' at dentry 'b'. + + If mount 'B' is shared, then all most-recently-mounted mounts at dentry + 'b' on mounts that receive propagation from mount 'B' and does not have + sub-mounts within them are unmounted. + + Example: Lets say 'B1', 'B2', 'B3' are shared mounts that propagate to + each other. + + lets say 'A1', 'A2', 'A3' are first mounted at dentry 'b' on mount + 'B1', 'B2' and 'B3' respectively. + + lets say 'C1', 'C2', 'C3' are next mounted at the same dentry 'b' on + mount 'B1', 'B2' and 'B3' respectively. + + if 'C1' is unmounted, all the mounts that are most-recently-mounted on + 'B1' and on the mounts that 'B1' propagates-to are unmounted. + + 'B1' propagates to 'B2' and 'B3'. And the most recently mounted mount + on 'B2' at dentry 'b' is 'C2', and that of mount 'B3' is 'C3'. + + So all 'C1', 'C2' and 'C3' should be unmounted. + + If any of 'C2' or 'C3' has some child mounts, then that mount is not + unmounted, but all other mounts are unmounted. However if 'C1' is told + to be unmounted and 'C1' has some sub-mounts, the umount operation is + failed entirely. + +5g) Clone Namespace + + A cloned namespace contains all the mounts as that of the parent + namespace. + + Lets say 'A' and 'B' are the corresponding mounts in the parent and the + child namespace. + + If 'A' is shared, then 'B' is also shared and 'A' and 'B' propagate to + each other. + + If 'A' is a slave mount of 'Z', then 'B' is also the slave mount of + 'Z'. + + If 'A' is a private mount, then 'B' is a private mount too. + + If 'A' is unbindable mount, then 'B' is a unbindable mount too. + + +6) Quiz + + A. What is the result of the following command sequence? + + mount --bind /mnt /mnt + mount --make-shared /mnt + mount --bind /mnt /tmp + mount --move /tmp /mnt/1 + + what should be the contents of /mnt /mnt/1 /mnt/1/1 should be? + Should they all be identical? or should /mnt and /mnt/1 be + identical only? + + + B. What is the result of the following command sequence? + + mount --make-rshared / + mkdir -p /v/1 + mount --rbind / /v/1 + + what should be the content of /v/1/v/1 be? + + + C. What is the result of the following command sequence? + + mount --bind /mnt /mnt + mount --make-shared /mnt + mkdir -p /mnt/1/2/3 /mnt/1/test + mount --bind /mnt/1 /tmp + mount --make-slave /mnt + mount --make-shared /mnt + mount --bind /mnt/1/2 /tmp1 + mount --make-slave /mnt + + At this point we have the first mount at /tmp and + its root dentry is 1. Lets call this mount 'A' + And then we have a second mount at /tmp1 with root + dentry 2. Lets call this mount 'B' + Next we have a third mount at /mnt with root dentry + mnt. Lets call this mount 'C' + + 'B' is the slave of 'A' and 'C' is a slave of 'B' + A -> B -> C + + at this point if we execute the following command + + mount --bind /bin /tmp/test + + The mount is attempted on 'A' + + will the mount propagate to 'B' and 'C' ? + + what would be the contents of + /mnt/1/test be? + +7) FAQ + + Q1. Why is bind mount needed? How is it different from symbolic links? + symbolic links can get stale if the destination mount gets + unmounted or moved. Bind mounts continue to exist even if the + other mount is unmounted or moved. + + Q2. Why can't the shared subtree be implemented using exportfs? + + exportfs is a heavyweight way of accomplishing part of what + shared subtree can do. I cannot imagine a way to implement the + semantics of slave mount using exportfs? + + Q3 Why is unbindable mount needed? + + Lets say we want to replicate the mount tree at multiple + locations within the same subtree. + + if one rbind mounts a tree within the same subtree 'n' times + the number of mounts created is an exponential function of 'n'. + Having unbindable mount can help prune the unneeded bind + mounts. Here is a example. + + step 1: + lets say the root tree has just two directories with + one vfsmount. + root + / \ + tmp usr + + And we want to replicate the tree at multiple + mountpoints under /root/tmp + + step2: + mount --make-shared /root + + mkdir -p /tmp/m1 + + mount --rbind /root /tmp/m1 + + the new tree now looks like this: + + root + / \ + tmp usr + / + m1 + / \ + tmp usr + / + m1 + + it has two vfsmounts + + step3: + mkdir -p /tmp/m2 + mount --rbind /root /tmp/m2 + + the new tree now looks like this: + + root + / \ + tmp usr + / \ + m1 m2 + / \ / \ + tmp usr tmp usr + / \ / + m1 m2 m1 + / \ / \ + tmp usr tmp usr + / / \ + m1 m1 m2 + / \ + tmp usr + / \ + m1 m2 + + it has 6 vfsmounts + + step 4: + mkdir -p /tmp/m3 + mount --rbind /root /tmp/m3 + + I wont' draw the tree..but it has 24 vfsmounts + + + at step i the number of vfsmounts is V[i] = i*V[i-1]. + This is an exponential function. And this tree has way more + mounts than what we really needed in the first place. + + One could use a series of umount at each step to prune + out the unneeded mounts. But there is a better solution. + Unclonable mounts come in handy here. + + step 1: + lets say the root tree has just two directories with + one vfsmount. + root + / \ + tmp usr + + How do we set up the same tree at multiple locations under + /root/tmp + + step2: + mount --bind /root/tmp /root/tmp + + mount --make-rshared /root + mount --make-unbindable /root/tmp + + mkdir -p /tmp/m1 + + mount --rbind /root /tmp/m1 + + the new tree now looks like this: + + root + / \ + tmp usr + / + m1 + / \ + tmp usr + + step3: + mkdir -p /tmp/m2 + mount --rbind /root /tmp/m2 + + the new tree now looks like this: + + root + / \ + tmp usr + / \ + m1 m2 + / \ / \ + tmp usr tmp usr + + step4: + + mkdir -p /tmp/m3 + mount --rbind /root /tmp/m3 + + the new tree now looks like this: + + root + / \ + tmp usr + / \ \ + m1 m2 m3 + / \ / \ / \ + tmp usr tmp usr tmp usr + +8) Implementation + +8A) Datastructure + + 4 new fields are introduced to struct vfsmount + ->mnt_share + ->mnt_slave_list + ->mnt_slave + ->mnt_master + + ->mnt_share links togather all the mount to/from which this vfsmount + send/receives propagation events. + + ->mnt_slave_list links all the mounts to which this vfsmount propagates + to. + + ->mnt_slave links togather all the slaves that its master vfsmount + propagates to. + + ->mnt_master points to the master vfsmount from which this vfsmount + receives propagation. + + ->mnt_flags takes two more flags to indicate the propagation status of + the vfsmount. MNT_SHARE indicates that the vfsmount is a shared + vfsmount. MNT_UNCLONABLE indicates that the vfsmount cannot be + replicated. + + All the shared vfsmounts in a peer group form a cyclic list through + ->mnt_share. + + All vfsmounts with the same ->mnt_master form on a cyclic list anchored + in ->mnt_master->mnt_slave_list and going through ->mnt_slave. + + ->mnt_master can point to arbitrary (and possibly different) members + of master peer group. To find all immediate slaves of a peer group + you need to go through _all_ ->mnt_slave_list of its members. + Conceptually it's just a single set - distribution among the + individual lists does not affect propagation or the way propagation + tree is modified by operations. + + A example propagation tree looks as shown in the figure below. + [ NOTE: Though it looks like a forest, if we consider all the shared + mounts as a conceptual entity called 'pnode', it becomes a tree] + + + A <--> B <--> C <---> D + /|\ /| |\ + / F G J K H I + / + E<-->K + /|\ + M L N + + In the above figure A,B,C and D all are shared and propagate to each + other. 'A' has got 3 slave mounts 'E' 'F' and 'G' 'C' has got 2 slave + mounts 'J' and 'K' and 'D' has got two slave mounts 'H' and 'I'. + 'E' is also shared with 'K' and they propagate to each other. And + 'K' has 3 slaves 'M', 'L' and 'N' + + A's ->mnt_share links with the ->mnt_share of 'B' 'C' and 'D' + + A's ->mnt_slave_list links with ->mnt_slave of 'E', 'K', 'F' and 'G' + + E's ->mnt_share links with ->mnt_share of K + 'E', 'K', 'F', 'G' have their ->mnt_master point to struct + vfsmount of 'A' + 'M', 'L', 'N' have their ->mnt_master point to struct vfsmount of 'K' + K's ->mnt_slave_list links with ->mnt_slave of 'M', 'L' and 'N' + + C's ->mnt_slave_list links with ->mnt_slave of 'J' and 'K' + J and K's ->mnt_master points to struct vfsmount of C + and finally D's ->mnt_slave_list links with ->mnt_slave of 'H' and 'I' + 'H' and 'I' have their ->mnt_master pointing to struct vfsmount of 'D'. + + + NOTE: The propagation tree is orthogonal to the mount tree. + + +8B Algorithm: + + The crux of the implementation resides in rbind/move operation. + + The overall algorithm breaks the operation into 3 phases: (look at + attach_recursive_mnt() and propagate_mnt()) + + 1. prepare phase. + 2. commit phases. + 3. abort phases. + + Prepare phase: + + for each mount in the source tree: + a) Create the necessary number of mount trees to + be attached to each of the mounts that receive + propagation from the destination mount. + b) Do not attach any of the trees to its destination. + However note down its ->mnt_parent and ->mnt_mountpoint + c) Link all the new mounts to form a propagation tree that + is identical to the propagation tree of the destination + mount. + + If this phase is successful, there should be 'n' new + propagation trees; where 'n' is the number of mounts in the + source tree. Go to the commit phase + + Also there should be 'm' new mount trees, where 'm' is + the number of mounts to which the destination mount + propagates to. + + if any memory allocations fail, go to the abort phase. + + Commit phase + attach each of the mount trees to their corresponding + destination mounts. + + Abort phase + delete all the newly created trees. + + NOTE: all the propagation related functionality resides in the file + pnode.c + + +------------------------------------------------------------------------ + +version 0.1 (created the initial document, Ram Pai linuxram@us.ibm.com) +version 0.2 (Incorporated comments from Al Viro) -- cgit v1.2.3 From fd7a516efbcdabf5d7b9307ca9fe48b511b7d123 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 2 Nov 2005 01:53:16 +0100 Subject: [PATCH] fix NET_RADIO=n, IEEE80211=y compile This patch fixes the following compile error with CONFIG_NET_RADIO=n and CONFIG_IEEE80211=y: LD .tmp_vmlinux1 net/built-in.o: In function `ieee80211_rx': : undefined reference to `wireless_spy_update' make: *** [.tmp_vmlinux1] Error 1 Signed-off-by: Adrian Bunk Signed-off-by: John W. Linville --- net/ieee80211/ieee80211_rx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index ce694cf5c16..00eb780836d 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c @@ -370,6 +370,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, /* Put this code here so that we avoid duplicating it in all * Rx paths. - Jean II */ #ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ +#ifdef CONFIG_NET_RADIO /* If spy monitoring on */ if (ieee->spy_data.spy_number > 0) { struct iw_quality wstats; @@ -396,6 +397,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, /* Update spy records */ wireless_spy_update(ieee->dev, hdr->addr2, &wstats); } +#endif /* CONFIG_NET_RADIO */ #endif /* IW_WIRELESS_SPY */ #ifdef NOT_YET -- cgit v1.2.3 From 8e3babcd69ec0fde874838e276eb0b211c6a5647 Mon Sep 17 00:00:00 2001 From: Jay Vosburgh Date: Fri, 4 Nov 2005 18:45:45 -0800 Subject: [PATCH] bonding: fix feature consolidation This should resolve http://bugzilla.kernel.org/show_bug.cgi?id=5519 The current feature computation loses bits that it doesn't know about, resulting in an inability to add VLANs and possibly other havoc. Rewrote function to preserve bits it doesn't know about, remove an unneeded state variable, and simplify the code. Signed-off-by: Jay Vosburgh Signed-off-by: John W. Linville --- drivers/net/bonding/bond_main.c | 32 +++++++++++--------------------- drivers/net/bonding/bonding.h | 7 ++----- 2 files changed, 13 insertions(+), 26 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 8032126fd58..94cec3cf2a1 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1604,35 +1604,27 @@ static int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_ (NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM) /* - * Compute the features available to the bonding device by - * intersection of all of the slave devices' BOND_INTERSECT_FEATURES. - * Call this after attaching or detaching a slave to update the - * bond's features. + * Compute the common dev->feature set available to all slaves. Some + * feature bits are managed elsewhere, so preserve feature bits set on + * master device that are not part of the examined set. */ static int bond_compute_features(struct bonding *bond) { - int i; + unsigned long features = BOND_INTERSECT_FEATURES; struct slave *slave; struct net_device *bond_dev = bond->dev; - int features = bond->bond_features; + int i; - bond_for_each_slave(bond, slave, i) { - struct net_device * slave_dev = slave->dev; - if (i == 0) { - features |= BOND_INTERSECT_FEATURES; - } - features &= - ~(~slave_dev->features & BOND_INTERSECT_FEATURES); - } + bond_for_each_slave(bond, slave, i) + features &= (slave->dev->features & BOND_INTERSECT_FEATURES); - /* turn off NETIF_F_SG if we need a csum and h/w can't do it */ if ((features & NETIF_F_SG) && - !(features & (NETIF_F_IP_CSUM | - NETIF_F_NO_CSUM | - NETIF_F_HW_CSUM))) { + !(features & (NETIF_F_IP_CSUM | + NETIF_F_NO_CSUM | + NETIF_F_HW_CSUM))) features &= ~NETIF_F_SG; - } + features |= (bond_dev->features & ~BOND_INTERSECT_FEATURES); bond_dev->features = features; return 0; @@ -4561,8 +4553,6 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER); - bond->bond_features = bond_dev->features; - #ifdef CONFIG_PROC_FS bond_create_proc_entry(bond); #endif diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index bbf9da8af62..1433e91db0f 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -40,8 +40,8 @@ #include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "2.6.4" -#define DRV_RELDATE "September 26, 2005" +#define DRV_VERSION "2.6.5" +#define DRV_RELDATE "November 4, 2005" #define DRV_NAME "bonding" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" @@ -211,9 +211,6 @@ struct bonding { struct bond_params params; struct list_head vlan_list; struct vlan_group *vlgrp; - /* the features the bonding device supports, independently - * of any slaves */ - int bond_features; }; /** -- cgit v1.2.3 From 48888cc6120ff945675ef79a3ba2955afa0f5124 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 5 Nov 2005 20:01:47 +0100 Subject: [PATCH] kill include/linux/eeprom.h This patch kills include/linux/eeprom.h . Rationale: - it was only used by one single driver - even this driver didn't do anything useful with it - most of this file are non-inline and non-static functions (sic) This removes include/linux/eeprom.h and cleans drivers/net/ns83820.c up. If you think eeprom.h should be used more extensively, please consider: - the code has to be moved from the header file to a .c file - the currently empty write function has to be implemented - ns83820.c or any other driver should actually use it Noone did any of these during the more than 3 years eeprom.h already exists... Signed-off-by: Adrian Bunk Signed-off-by: John W. Linville --- drivers/net/ns83820.c | 13 +---- include/linux/eeprom.h | 136 ------------------------------------------------- 2 files changed, 2 insertions(+), 147 deletions(-) delete mode 100644 include/linux/eeprom.h diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index a3c3fc9c0d8..f857ae94d26 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -110,7 +110,6 @@ #include #include /* for iph */ #include /* for IPPROTO_... */ -#include #include #include #include @@ -445,7 +444,6 @@ struct ns83820 { u32 MEAR_cache; u32 IMR_cache; - struct eeprom ee; unsigned linkstate; @@ -1558,15 +1556,13 @@ static void ns83820_getmac(struct ns83820 *dev, u8 *mac) unsigned i; for (i=0; i<3; i++) { u32 data; -#if 0 /* I've left this in as an example of how to use eeprom.h */ - data = eeprom_readw(&dev->ee, 0xa + 2 - i); -#else + /* Read from the perfect match memory: this is loaded by * the chip from the EEPROM via the EELOAD self test. */ writel(i*2, dev->base + RFCR); data = readl(dev->base + RFDR); -#endif + *mac++ = data; *mac++ = data >> 8; } @@ -1851,8 +1847,6 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ spin_lock_init(&dev->misc_lock); dev->pci_dev = pci_dev; - dev->ee.cache = &dev->MEAR_cache; - dev->ee.lock = &dev->misc_lock; SET_MODULE_OWNER(ndev); SET_NETDEV_DEV(ndev, &pci_dev->dev); @@ -1887,9 +1881,6 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ dev->IMR_cache = 0; - setup_ee_mem_bitbanger(&dev->ee, dev->base + MEAR, 3, 2, 1, 0, - 0); - err = request_irq(pci_dev->irq, ns83820_irq, SA_SHIRQ, DRV_NAME, ndev); if (err) { diff --git a/include/linux/eeprom.h b/include/linux/eeprom.h deleted file mode 100644 index 38afd9da1df..00000000000 --- a/include/linux/eeprom.h +++ /dev/null @@ -1,136 +0,0 @@ -/* credit winbond-840.c - */ -#include -struct eeprom_ops { - void (*set_cs)(void *ee); - void (*clear_cs)(void *ee); -}; - -#define EEPOL_EEDI 0x01 -#define EEPOL_EEDO 0x02 -#define EEPOL_EECLK 0x04 -#define EEPOL_EESEL 0x08 - -struct eeprom { - void *dev; - struct eeprom_ops *ops; - - void __iomem * addr; - - unsigned ee_addr_bits; - - unsigned eesel; - unsigned eeclk; - unsigned eedo; - unsigned eedi; - unsigned polarity; - unsigned ee_state; - - spinlock_t *lock; - u32 *cache; -}; - - -u8 eeprom_readb(struct eeprom *ee, unsigned address); -void eeprom_read(struct eeprom *ee, unsigned address, u8 *bytes, - unsigned count); -void eeprom_writeb(struct eeprom *ee, unsigned address, u8 data); -void eeprom_write(struct eeprom *ee, unsigned address, u8 *bytes, - unsigned count); - -/* The EEPROM commands include the alway-set leading bit. */ -enum EEPROM_Cmds { - EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6), -}; - -void setup_ee_mem_bitbanger(struct eeprom *ee, void __iomem *memaddr, int eesel_bit, int eeclk_bit, int eedo_bit, int eedi_bit, unsigned polarity) -{ - ee->addr = memaddr; - ee->eesel = 1 << eesel_bit; - ee->eeclk = 1 << eeclk_bit; - ee->eedo = 1 << eedo_bit; - ee->eedi = 1 << eedi_bit; - - ee->polarity = polarity; - - *ee->cache = readl(ee->addr); -} - -/* foo. put this in a .c file */ -static inline void eeprom_update(struct eeprom *ee, u32 mask, int pol) -{ - unsigned long flags; - u32 data; - - spin_lock_irqsave(ee->lock, flags); - data = *ee->cache; - - data &= ~mask; - if (pol) - data |= mask; - - *ee->cache = data; -//printk("update: %08x\n", data); - writel(data, ee->addr); - spin_unlock_irqrestore(ee->lock, flags); -} - -void eeprom_clk_lo(struct eeprom *ee) -{ - int pol = !!(ee->polarity & EEPOL_EECLK); - - eeprom_update(ee, ee->eeclk, pol); - udelay(2); -} - -void eeprom_clk_hi(struct eeprom *ee) -{ - int pol = !!(ee->polarity & EEPOL_EECLK); - - eeprom_update(ee, ee->eeclk, !pol); - udelay(2); -} - -void eeprom_send_addr(struct eeprom *ee, unsigned address) -{ - int pol = !!(ee->polarity & EEPOL_EEDI); - unsigned i; - address |= 6 << 6; - - /* Shift the read command bits out. */ - for (i=0; i<11; i++) { - eeprom_update(ee, ee->eedi, ((address >> 10) & 1) ^ pol); - address <<= 1; - eeprom_clk_hi(ee); - eeprom_clk_lo(ee); - } - eeprom_update(ee, ee->eedi, pol); -} - -u16 eeprom_readw(struct eeprom *ee, unsigned address) -{ - unsigned i; - u16 res = 0; - - eeprom_clk_lo(ee); - eeprom_update(ee, ee->eesel, 1 ^ !!(ee->polarity & EEPOL_EESEL)); - eeprom_send_addr(ee, address); - - for (i=0; i<16; i++) { - u32 data; - eeprom_clk_hi(ee); - res <<= 1; - data = readl(ee->addr); -//printk("eeprom_readw: %08x\n", data); - res |= !!(data & ee->eedo) ^ !!(ee->polarity & EEPOL_EEDO); - eeprom_clk_lo(ee); - } - eeprom_update(ee, ee->eesel, 0 ^ !!(ee->polarity & EEPOL_EESEL)); - - return res; -} - - -void eeprom_writeb(struct eeprom *ee, unsigned address, u8 data) -{ -} -- cgit v1.2.3 From ac1f60db6a62c8605b551497c8002ba267ea1f4a Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 6 Nov 2005 01:46:47 +0100 Subject: [PATCH] drivers/net/s2io.c: make functions static This patch makes needlessly global functions static. Signed-off-by: Adrian Bunk Signed-off-by: John W. Linville --- drivers/net/s2io.c | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 9c4935407f2..9848892643f 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -1532,7 +1532,7 @@ static int init_nic(struct s2io_nic *nic) #define LINK_UP_DOWN_INTERRUPT 1 #define MAC_RMAC_ERR_TIMER 2 -int s2io_link_fault_indication(nic_t *nic) +static int s2io_link_fault_indication(nic_t *nic) { if (nic->intr_type != INTA) return MAC_RMAC_ERR_TIMER; @@ -1864,7 +1864,7 @@ static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag) * */ -void fix_mac_address(nic_t * sp) +static void fix_mac_address(nic_t * sp) { XENA_dev_config_t __iomem *bar0 = sp->bar0; u64 val64; @@ -2162,7 +2162,7 @@ int fill_rxd_3buf(nic_t *nic, RxD_t *rxdp, struct sk_buff *skb) * SUCCESS on success or an appropriate -ve value on failure. */ -int fill_rx_buffers(struct s2io_nic *nic, int ring_no) +static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) { struct net_device *dev = nic->dev; struct sk_buff *skb; @@ -2833,7 +2833,7 @@ static void alarm_intr_handler(struct s2io_nic *nic) * SUCCESS on success and FAILURE on failure. */ -int wait_for_cmd_complete(nic_t * sp) +static int wait_for_cmd_complete(nic_t * sp) { XENA_dev_config_t __iomem *bar0 = sp->bar0; int ret = FAILURE, cnt = 0; @@ -3079,7 +3079,7 @@ int s2io_set_swapper(nic_t * sp) return SUCCESS; } -int wait_for_msix_trans(nic_t *nic, int i) +static int wait_for_msix_trans(nic_t *nic, int i) { XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0; u64 val64; @@ -3118,7 +3118,7 @@ void restore_xmsi_data(nic_t *nic) } } -void store_xmsi_data(nic_t *nic) +static void store_xmsi_data(nic_t *nic) { XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0; u64 val64, addr, data; @@ -3290,7 +3290,7 @@ int s2io_enable_msi_x(nic_t *nic) * file on failure. */ -int s2io_open(struct net_device *dev) +static int s2io_open(struct net_device *dev) { nic_t *sp = dev->priv; int err = 0; @@ -3420,7 +3420,7 @@ hw_init_failed: * file on failure. */ -int s2io_close(struct net_device *dev) +static int s2io_close(struct net_device *dev) { nic_t *sp = dev->priv; int i; @@ -3469,7 +3469,7 @@ int s2io_close(struct net_device *dev) * 0 on success & 1 on failure. */ -int s2io_xmit(struct sk_buff *skb, struct net_device *dev) +static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) { nic_t *sp = dev->priv; u16 frg_cnt, frg_len, i, queue, queue_len, put_off, get_off; @@ -3915,7 +3915,7 @@ static void s2io_updt_stats(nic_t *sp) * pointer to the updated net_device_stats structure. */ -struct net_device_stats *s2io_get_stats(struct net_device *dev) +static struct net_device_stats *s2io_get_stats(struct net_device *dev) { nic_t *sp = dev->priv; mac_info_t *mac_control; @@ -5108,19 +5108,20 @@ static void s2io_get_ethtool_stats(struct net_device *dev, tmp_stats[i++] = stat_info->sw_stat.double_ecc_errs; } -int s2io_ethtool_get_regs_len(struct net_device *dev) +static int s2io_ethtool_get_regs_len(struct net_device *dev) { return (XENA_REG_SPACE); } -u32 s2io_ethtool_get_rx_csum(struct net_device * dev) +static u32 s2io_ethtool_get_rx_csum(struct net_device * dev) { nic_t *sp = dev->priv; return (sp->rx_csum); } -int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data) + +static int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data) { nic_t *sp = dev->priv; @@ -5131,17 +5132,19 @@ int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data) return 0; } -int s2io_get_eeprom_len(struct net_device *dev) + +static int s2io_get_eeprom_len(struct net_device *dev) { return (XENA_EEPROM_SPACE); } -int s2io_ethtool_self_test_count(struct net_device *dev) +static int s2io_ethtool_self_test_count(struct net_device *dev) { return (S2IO_TEST_LEN); } -void s2io_ethtool_get_strings(struct net_device *dev, - u32 stringset, u8 * data) + +static void s2io_ethtool_get_strings(struct net_device *dev, + u32 stringset, u8 * data) { switch (stringset) { case ETH_SS_TEST: @@ -5157,7 +5160,7 @@ static int s2io_ethtool_get_stats_count(struct net_device *dev) return (S2IO_STAT_LEN); } -int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data) +static int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data) { if (data) dev->features |= NETIF_F_IP_CSUM; @@ -5210,7 +5213,7 @@ static struct ethtool_ops netdev_ethtool_ops = { * function always return EOPNOTSUPPORTED */ -int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +static int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { return -EOPNOTSUPP; } @@ -5226,7 +5229,7 @@ int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) * file on failure. */ -int s2io_change_mtu(struct net_device *dev, int new_mtu) +static int s2io_change_mtu(struct net_device *dev, int new_mtu) { nic_t *sp = dev->priv; -- cgit v1.2.3 From de7fe963b123365a27f82330689806226a48d088 Mon Sep 17 00:00:00 2001 From: Roger While Date: Mon, 7 Nov 2005 20:57:58 +0100 Subject: [PATCH] prism54 : Unused variable / extraneous udelay In isl_38xx.c : The variable "counter" is defined and incremented but never used except if the driver is hand-compiled setting VERBOSE > SHOW_ERROR_MESSAGES. Move the definition and the increment to within the #if VERBOSE .. block. Remove extraneous udelay's. These are not required when triggering the device. Signed-off-by: Roger While Signed-off-by: John W. Linville --- drivers/net/wireless/prism54/isl_38xx.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c index adc7499136d..866c476933c 100644 --- a/drivers/net/wireless/prism54/isl_38xx.c +++ b/drivers/net/wireless/prism54/isl_38xx.c @@ -112,9 +112,10 @@ isl38xx_handle_wakeup(isl38xx_control_block *control_block, void isl38xx_trigger_device(int asleep, void __iomem *device_base) { - u32 reg, counter = 0; + u32 reg; #if VERBOSE > SHOW_ERROR_MESSAGES + u32 counter = 0; struct timeval current_time; DEBUG(SHOW_FUNCTION_CALLS, "isl38xx trigger device\n"); #endif @@ -131,7 +132,6 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base) current_time.tv_sec, (long)current_time.tv_usec, readl(device_base + ISL38XX_CTRL_STAT_REG)); #endif - udelay(ISL38XX_WRITEIO_DELAY); reg = readl(device_base + ISL38XX_INT_IDENT_REG); if (reg == 0xabadface) { @@ -145,7 +145,9 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base) while (reg = readl(device_base + ISL38XX_CTRL_STAT_REG), (reg & ISL38XX_CTRL_STAT_SLEEPMODE) == 0) { udelay(ISL38XX_WRITEIO_DELAY); +#if VERBOSE > SHOW_ERROR_MESSAGES counter++; +#endif } #if VERBOSE > SHOW_ERROR_MESSAGES @@ -153,10 +155,6 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base) "%08li.%08li Device register read %08x\n", current_time.tv_sec, (long)current_time.tv_usec, readl(device_base + ISL38XX_CTRL_STAT_REG)); -#endif - udelay(ISL38XX_WRITEIO_DELAY); - -#if VERBOSE > SHOW_ERROR_MESSAGES do_gettimeofday(¤t_time); DEBUG(SHOW_TRACING, "%08li.%08li Device asleep counter %i\n", @@ -171,7 +169,6 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base) /* perform another read on the Device Status Register */ reg = readl(device_base + ISL38XX_CTRL_STAT_REG); - udelay(ISL38XX_WRITEIO_DELAY); #if VERBOSE > SHOW_ERROR_MESSAGES do_gettimeofday(¤t_time); @@ -187,7 +184,6 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base) isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_UPDATE, ISL38XX_DEV_INT_REG); - udelay(ISL38XX_WRITEIO_DELAY); } } -- cgit v1.2.3 From 0b47939fe616a5e0dd279d98d1eb372e4acc1c09 Mon Sep 17 00:00:00 2001 From: Roger While Date: Mon, 7 Nov 2005 20:58:21 +0100 Subject: [PATCH] prism54 : Transmit stats updated in wrong place Move update of the transmit statistics to the correct place. This would be just before starting transmission rather than (potentially long) afterward. Signed-off-by: Roger While Signed-off-by: John W. Linville --- drivers/net/wireless/prism54/islpci_eth.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index 3b49efa37ee..56d97833eda 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c @@ -227,17 +227,17 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev) priv->data_low_tx_full = 1; } + /* set the transmission time */ + ndev->trans_start = jiffies; + priv->statistics.tx_packets++; + priv->statistics.tx_bytes += skb->len; + /* trigger the device */ islpci_trigger(priv); /* unlock the driver code */ spin_unlock_irqrestore(&priv->slock, flags); - /* set the transmission time */ - ndev->trans_start = jiffies; - priv->statistics.tx_packets++; - priv->statistics.tx_bytes += skb->len; - return 0; drop_free: -- cgit v1.2.3 From 097688ef4710648db335c3c4fa243751f60b330a Mon Sep 17 00:00:00 2001 From: Luiz Fernando Capitulino Date: Mon, 7 Nov 2005 18:14:12 -0200 Subject: [PATCH] Fix sparse warning in e100 driver. The patch below fixes the following sparse warnings: drivers/net/e100.c:1481:13: warning: Using plain integer as NULL pointer drivers/net/e100.c:1767:27: warning: Using plain integer as NULL pointer drivers/net/e100.c:1847:27: warning: Using plain integer as NULL pointer Signed-off-by: Luiz Capitulino Signed-off-by: John W. Linville --- drivers/net/e100.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/e100.c b/drivers/net/e100.c index eb169a8e877..7a6aeae2c9f 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1478,7 +1478,7 @@ static inline int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) if(pci_dma_mapping_error(rx->dma_addr)) { dev_kfree_skb_any(rx->skb); - rx->skb = 0; + rx->skb = NULL; rx->dma_addr = 0; return -ENOMEM; } @@ -1764,7 +1764,7 @@ static int e100_up(struct nic *nic) if((err = e100_hw_init(nic))) goto err_clean_cbs; e100_set_multicast_list(nic->netdev); - e100_start_receiver(nic, 0); + e100_start_receiver(nic, NULL); mod_timer(&nic->watchdog, jiffies); if((err = request_irq(nic->pdev->irq, e100_intr, SA_SHIRQ, nic->netdev->name, nic->netdev))) @@ -1844,7 +1844,7 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, BMCR_LOOPBACK); - e100_start_receiver(nic, 0); + e100_start_receiver(nic, NULL); if(!(skb = dev_alloc_skb(ETH_DATA_LEN))) { err = -ENOMEM; -- cgit v1.2.3 From f36be62115aabd50b4eda0f06f07ab5fae2e9cfd Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 8 Nov 2005 00:41:48 +0300 Subject: [PATCH] atmel: memset correct range Specify the correct range when calling memset in atmel_get_range. Do this by specifying the size of the structure, rather than the size of the pointer. Signed-off-by: Alexey Dobriyan Signed-off-by: John W. Linville --- drivers/net/wireless/atmel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 1fbe027d26b..a3e23527fe7 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -2217,7 +2217,7 @@ static int atmel_get_range(struct net_device *dev, int k,i,j; dwrq->length = sizeof(struct iw_range); - memset(range, 0, sizeof(range)); + memset(range, 0, sizeof(struct iw_range)); range->min_nwid = 0x0000; range->max_nwid = 0x0000; range->num_channels = 0; -- cgit v1.2.3 From b69a3aa85cb7bda2eb6c5932a62c1337d0d6612c Mon Sep 17 00:00:00 2001 From: Panagiotis Issaris Date: Tue, 8 Nov 2005 00:03:15 +0100 Subject: [PATCH] wireless net: Conversions of kmalloc/memset to kzalloc More conversions of kmalloc/memset to kzalloc Signed-off-by: Panagiotis Issaris Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 36 ++++++++++++------------------------ drivers/net/wireless/airo_cs.c | 6 ++---- drivers/net/wireless/atmel_cs.c | 6 ++---- drivers/net/wireless/ipw2100.c | 4 +--- drivers/net/wireless/wavelan_cs.c | 3 +-- drivers/net/wireless/wl3501_cs.c | 3 +-- 6 files changed, 19 insertions(+), 39 deletions(-) diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 849ac88bccc..58ca585caa5 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -4533,9 +4533,8 @@ static int proc_status_open( struct inode *inode, struct file *file ) { StatusRid status_rid; int i; - if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) + if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; - memset(file->private_data, 0, sizeof(struct proc_data)); data = (struct proc_data *)file->private_data; if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) { kfree (file->private_data); @@ -4613,9 +4612,8 @@ static int proc_stats_rid_open( struct inode *inode, int i, j; u32 *vals = stats.vals; - if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) + if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; - memset(file->private_data, 0, sizeof(struct proc_data)); data = (struct proc_data *)file->private_data; if ((data->rbuffer = kmalloc( 4096, GFP_KERNEL )) == NULL) { kfree (file->private_data); @@ -4879,20 +4877,18 @@ static int proc_config_open( struct inode *inode, struct file *file ) { struct airo_info *ai = dev->priv; int i; - if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) + if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; - memset(file->private_data, 0, sizeof(struct proc_data)); data = (struct proc_data *)file->private_data; if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) { kfree (file->private_data); return -ENOMEM; } - if ((data->wbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) { + if ((data->wbuffer = kzalloc( 2048, GFP_KERNEL )) == NULL) { kfree (data->rbuffer); kfree (file->private_data); return -ENOMEM; } - memset( data->wbuffer, 0, 2048 ); data->maxwritelen = 2048; data->on_close = proc_config_on_close; @@ -5153,24 +5149,21 @@ static int proc_wepkey_open( struct inode *inode, struct file *file ) { int j=0; int rc; - if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) + if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; - memset(file->private_data, 0, sizeof(struct proc_data)); memset(&wkr, 0, sizeof(wkr)); data = (struct proc_data *)file->private_data; - if ((data->rbuffer = kmalloc( 180, GFP_KERNEL )) == NULL) { + if ((data->rbuffer = kzalloc( 180, GFP_KERNEL )) == NULL) { kfree (file->private_data); return -ENOMEM; } - memset(data->rbuffer, 0, 180); data->writelen = 0; data->maxwritelen = 80; - if ((data->wbuffer = kmalloc( 80, GFP_KERNEL )) == NULL) { + if ((data->wbuffer = kzalloc( 80, GFP_KERNEL )) == NULL) { kfree (data->rbuffer); kfree (file->private_data); return -ENOMEM; } - memset( data->wbuffer, 0, 80 ); data->on_close = proc_wepkey_on_close; ptr = data->rbuffer; @@ -5201,9 +5194,8 @@ static int proc_SSID_open( struct inode *inode, struct file *file ) { char *ptr; SsidRid SSID_rid; - if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) + if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; - memset(file->private_data, 0, sizeof(struct proc_data)); data = (struct proc_data *)file->private_data; if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) { kfree (file->private_data); @@ -5211,12 +5203,11 @@ static int proc_SSID_open( struct inode *inode, struct file *file ) { } data->writelen = 0; data->maxwritelen = 33*3; - if ((data->wbuffer = kmalloc( 33*3, GFP_KERNEL )) == NULL) { + if ((data->wbuffer = kzalloc( 33*3, GFP_KERNEL )) == NULL) { kfree (data->rbuffer); kfree (file->private_data); return -ENOMEM; } - memset( data->wbuffer, 0, 33*3 ); data->on_close = proc_SSID_on_close; readSsidRid(ai, &SSID_rid); @@ -5245,9 +5236,8 @@ static int proc_APList_open( struct inode *inode, struct file *file ) { char *ptr; APListRid APList_rid; - if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) + if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; - memset(file->private_data, 0, sizeof(struct proc_data)); data = (struct proc_data *)file->private_data; if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) { kfree (file->private_data); @@ -5255,12 +5245,11 @@ static int proc_APList_open( struct inode *inode, struct file *file ) { } data->writelen = 0; data->maxwritelen = 4*6*3; - if ((data->wbuffer = kmalloc( data->maxwritelen, GFP_KERNEL )) == NULL) { + if ((data->wbuffer = kzalloc( data->maxwritelen, GFP_KERNEL )) == NULL) { kfree (data->rbuffer); kfree (file->private_data); return -ENOMEM; } - memset( data->wbuffer, 0, data->maxwritelen ); data->on_close = proc_APList_on_close; readAPListRid(ai, &APList_rid); @@ -5295,9 +5284,8 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) { /* If doLoseSync is not 1, we won't do a Lose Sync */ int doLoseSync = -1; - if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) + if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; - memset(file->private_data, 0, sizeof(struct proc_data)); data = (struct proc_data *)file->private_data; if ((data->rbuffer = kmalloc( 1024, GFP_KERNEL )) == NULL) { kfree (file->private_data); diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index 784de910911..fee458fd7a4 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c @@ -172,12 +172,11 @@ static dev_link_t *airo_attach(void) DEBUG(0, "airo_attach()\n"); /* Initialize the dev_link_t structure */ - link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); + link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); if (!link) { printk(KERN_ERR "airo_cs: no memory for new device\n"); return NULL; } - memset(link, 0, sizeof(struct dev_link_t)); /* Interrupt setup */ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; @@ -196,13 +195,12 @@ static dev_link_t *airo_attach(void) link->conf.IntType = INT_MEMORY_AND_IO; /* Allocate space for private device-specific data */ - local = kmalloc(sizeof(local_info_t), GFP_KERNEL); + local = kzalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) { printk(KERN_ERR "airo_cs: no memory for new device\n"); kfree (link); return NULL; } - memset(local, 0, sizeof(local_info_t)); link->priv = local; /* Register with Card Services */ diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 195cb36619e..1bd13146c64 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -180,12 +180,11 @@ static dev_link_t *atmel_attach(void) DEBUG(0, "atmel_attach()\n"); /* Initialize the dev_link_t structure */ - link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); + link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); if (!link) { printk(KERN_ERR "atmel_cs: no memory for new device\n"); return NULL; } - memset(link, 0, sizeof(struct dev_link_t)); /* Interrupt setup */ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; @@ -204,13 +203,12 @@ static dev_link_t *atmel_attach(void) link->conf.IntType = INT_MEMORY_AND_IO; /* Allocate space for private device-specific data */ - local = kmalloc(sizeof(local_info_t), GFP_KERNEL); + local = kzalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) { printk(KERN_ERR "atmel_cs: no memory for new device\n"); kfree (link); return NULL; } - memset(local, 0, sizeof(local_info_t)); link->priv = local; /* Register with Card Services */ diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index ad7f8cd76db..4f19ac7d63a 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -6065,13 +6065,11 @@ static int ipw2100_wpa_set_encryption(struct net_device *dev, ieee80211_crypt_delayed_deinit(ieee, crypt); - new_crypt = (struct ieee80211_crypt_data *) - kmalloc(sizeof(struct ieee80211_crypt_data), GFP_KERNEL); + new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data), GFP_KERNEL); if (new_crypt == NULL) { ret = -ENOMEM; goto done; } - memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data)); new_crypt->ops = ops; if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) new_crypt->priv = new_crypt->ops->init(param->u.crypt.idx); diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index 4b3c98f5c56..c822cad3333 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -4608,9 +4608,8 @@ wavelan_attach(void) #endif /* Initialize the dev_link_t structure */ - link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); + link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); if (!link) return NULL; - memset(link, 0, sizeof(struct dev_link_t)); /* The io structure describes IO port mapping */ link->io.NumPorts1 = 8; diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 3f8c27f0871..978fdc60678 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -1965,10 +1965,9 @@ static dev_link_t *wl3501_attach(void) int ret; /* Initialize the dev_link_t structure */ - link = kmalloc(sizeof(*link), GFP_KERNEL); + link = kzalloc(sizeof(*link), GFP_KERNEL); if (!link) goto out; - memset(link, 0, sizeof(struct dev_link_t)); /* The io structure describes IO port mapping */ link->io.NumPorts1 = 16; -- cgit v1.2.3 From 54b79248b24610663298e122c6ba3804468271fe Mon Sep 17 00:00:00 2001 From: Mike Kravetz Date: Mon, 7 Nov 2005 16:25:48 -0800 Subject: [PATCH] revised Memory Add Fixes for ppc64 Add the create_section_mapping() routine to create hptes for memory sections dynamically added after system boot. Signed-off-by: Mike Kravetz Signed-off-by: Paul Mackerras --- arch/powerpc/mm/hash_utils_64.c | 9 +++++++++ arch/powerpc/mm/mem.c | 3 +++ include/asm-powerpc/sparsemem.h | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 22e47487613..c8c9c2df97e 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -386,6 +386,15 @@ static unsigned long __init htab_get_table_size(void) return pteg_count << 7; } +#ifdef CONFIG_MEMORY_HOTPLUG +void create_section_mapping(unsigned long start, unsigned long end) +{ + BUG_ON(htab_bolt_mapping(start, end, start, + _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX, + mmu_linear_psize)); +} +#endif /* CONFIG_MEMORY_HOTPLUG */ + void __init htab_initialize(void) { unsigned long table, htab_size_bytes; diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 6f55efd9be9..2ead0951823 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -127,6 +127,9 @@ int __devinit add_memory(u64 start, u64 size) unsigned long start_pfn = start >> PAGE_SHIFT; unsigned long nr_pages = size >> PAGE_SHIFT; + start += KERNELBASE; + create_section_mapping(start, start + size); + /* this should work for most non-highmem platforms */ zone = pgdata->node_zones; diff --git a/include/asm-powerpc/sparsemem.h b/include/asm-powerpc/sparsemem.h index 1c95ab99deb..58d2aab416f 100644 --- a/include/asm-powerpc/sparsemem.h +++ b/include/asm-powerpc/sparsemem.h @@ -11,6 +11,10 @@ #define MAX_PHYSADDR_BITS 38 #define MAX_PHYSMEM_BITS 36 +#ifdef CONFIG_MEMORY_HOTPLUG +extern void create_section_mapping(unsigned long start, unsigned long end); +#endif /* CONFIG_MEMORY_HOTPLUG */ + #endif /* CONFIG_SPARSEMEM */ #endif /* _ASM_POWERPC_SPARSEMEM_H */ -- cgit v1.2.3 From dd7ccbd3eed52a42dc8bba57717dac3ece39b58e Mon Sep 17 00:00:00 2001 From: Mike Kravetz Date: Fri, 4 Nov 2005 15:19:32 -0800 Subject: [PATCH] Memory Add Fixes for ppc64 memmap_init_zone() sets page count to 1. Before 'freeing' the page, we need to clear the count. This is the same that is done on free_all_bootmem_core() for memory discovered at boot time. Signed-off-by: Mike Kravetz Signed-off-by: Paul Mackerras --- arch/powerpc/mm/mem.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 2ead0951823..1dd3cc69a49 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -110,6 +110,7 @@ EXPORT_SYMBOL(phys_mem_access_prot); void online_page(struct page *page) { ClearPageReserved(page); + set_page_count(page, 0); free_cold_page(page); totalram_pages++; num_physpages++; -- cgit v1.2.3 From 82dd26a971848efafc6c8f12803ae012d268d2eb Mon Sep 17 00:00:00 2001 From: Mike Kravetz Date: Fri, 4 Nov 2005 15:20:24 -0800 Subject: [PATCH] Memory Add Fixes for ppc64 This is a temporary kludge that supports adding all new memory to node 0. I will provide a more complete solution similar to that used for dynamically added CPUs in a few days. Signed-off-by: Mike Kravetz Signed-off-by: Paul Mackerras --- include/asm-ppc64/mmzone.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/asm-ppc64/mmzone.h b/include/asm-ppc64/mmzone.h index 80a708e7093..15e777ce0f4 100644 --- a/include/asm-ppc64/mmzone.h +++ b/include/asm-ppc64/mmzone.h @@ -33,6 +33,9 @@ extern int numa_cpu_lookup_table[]; extern char *numa_memory_lookup_table; extern cpumask_t numa_cpumask_lookup_table[]; extern int nr_cpus_in_node[]; +#ifdef CONFIG_MEMORY_HOTPLUG +extern unsigned long max_pfn; +#endif /* 16MB regions */ #define MEMORY_INCREMENT_SHIFT 24 @@ -45,6 +48,11 @@ static inline int pa_to_nid(unsigned long pa) { int nid; +#ifdef CONFIG_MEMORY_HOTPLUG + /* kludge hot added sections default to node 0 */ + if (pa >= (max_pfn << PAGE_SHIFT)) + return 0; +#endif nid = numa_memory_lookup_table[pa >> MEMORY_INCREMENT_SHIFT]; #ifdef DEBUG_NUMA -- cgit v1.2.3 From 7e9191daf643255c24893427f966795e4167ca2c Mon Sep 17 00:00:00 2001 From: Mike Kravetz Date: Mon, 7 Nov 2005 09:39:48 -0800 Subject: [PATCH] Memory Add Fixes for ppc64 ppc64 needs a special sysfs probe file for adding new memory. Signed-off-by: Mike Kravetz Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 4 ++++ arch/ppc64/Kconfig | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 1493c7896fe..ed31062029f 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -599,6 +599,10 @@ config HAVE_ARCH_EARLY_PFN_TO_NID def_bool y depends on NEED_MULTIPLE_NODES +config ARCH_MEMORY_PROBE + def_bool y + depends on MEMORY_HOTPLUG + # Some NUMA nodes have memory ranges that span # other nodes. Even though a pfn is valid and # between a node's start and end pfns, it may not diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig index 29552348e58..c9d32db9d76 100644 --- a/arch/ppc64/Kconfig +++ b/arch/ppc64/Kconfig @@ -297,6 +297,10 @@ config HAVE_ARCH_EARLY_PFN_TO_NID def_bool y depends on NEED_MULTIPLE_NODES +config ARCH_MEMORY_PROBE + def_bool y + depends on MEMORY_HOTPLUG + # Some NUMA nodes have memory ranges that span # other nodes. Even though a pfn is valid and # between a node's start and end pfns, it may not -- cgit v1.2.3 From a852daa00ad91350fe603da47becaf3d5af4f2bd Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 2 Nov 2005 21:42:48 +0100 Subject: [PATCH] i2c: writing-client doc update complement My latest update to the writing-clients i2c documentation file was incomplete, here's the complement. Large parts of this file are still way out-of-date, but at least now the memory allocation and freeing instructions are consistent. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/i2c/writing-clients | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients index cff7b652588..d19993cc060 100644 --- a/Documentation/i2c/writing-clients +++ b/Documentation/i2c/writing-clients @@ -412,7 +412,7 @@ For now, you can ignore the `flags' parameter. It is there for future use. release_region(address,FOO_EXTENT); /* SENSORS ONLY END */ ERROR1: - kfree(new_client); + kfree(data); ERROR0: return err; } @@ -443,7 +443,7 @@ much simpler than the attachment code, fortunately! release_region(client->addr,LM78_EXTENT); /* HYBRID SENSORS CHIP ONLY END */ - kfree(data); + kfree(i2c_get_clientdata(client)); return 0; } -- cgit v1.2.3 From ef9627464490fe67235bbd5724d55345b92c0315 Mon Sep 17 00:00:00 2001 From: James Chapman Date: Sun, 6 Nov 2005 23:07:38 +0100 Subject: [PATCH] i2c: ds1337 BCD conversion fix Fix BCD value errors when month=9, moving the increment inside the BIN2BCD macro. Fix similar code for the weekday value, just for consistency. This bug was reported by Michael Burian . Signed-off-by: James Chapman Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/chips/ds1337.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c index 01b03700741..02682fb794c 100644 --- a/drivers/i2c/chips/ds1337.c +++ b/drivers/i2c/chips/ds1337.c @@ -164,9 +164,9 @@ static int ds1337_set_datetime(struct i2c_client *client, struct rtc_time *dt) buf[1] = BIN2BCD(dt->tm_sec); buf[2] = BIN2BCD(dt->tm_min); buf[3] = BIN2BCD(dt->tm_hour); - buf[4] = BIN2BCD(dt->tm_wday) + 1; + buf[4] = BIN2BCD(dt->tm_wday + 1); buf[5] = BIN2BCD(dt->tm_mday); - buf[6] = BIN2BCD(dt->tm_mon) + 1; + buf[6] = BIN2BCD(dt->tm_mon + 1); val = dt->tm_year; if (val >= 100) { val -= 100; -- cgit v1.2.3 From 4a1c4447e523003019a2bf9b972ed6fe411e84d2 Mon Sep 17 00:00:00 2001 From: Yuan Mu Date: Mon, 7 Nov 2005 22:19:04 +0100 Subject: [PATCH] hwmon: Fix two w83627hf bugs * Fix in4 reads for W83627THF and W83637HF chips. * Use the correct register for alarm flags. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/w83627hf.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 70ef926c3bd..4e9a04e1f08 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -180,11 +180,10 @@ superio_exit(void) #define W83781D_REG_BANK 0x4E #define W83781D_REG_CONFIG 0x40 -#define W83781D_REG_ALARM1 0x41 -#define W83781D_REG_ALARM2 0x42 -#define W83781D_REG_ALARM3 0x450 +#define W83781D_REG_ALARM1 0x459 +#define W83781D_REG_ALARM2 0x45A +#define W83781D_REG_ALARM3 0x45B -#define W83781D_REG_IRQ 0x4C #define W83781D_REG_BEEP_CONFIG 0x4D #define W83781D_REG_BEEP_INTS1 0x56 #define W83781D_REG_BEEP_INTS2 0x57 @@ -1370,13 +1369,6 @@ static void w83627hf_init_client(struct i2c_client *client) W83781D_REG_TEMP3_CONFIG, tmp & 0xfe); } } - - /* enable comparator mode for temp2 and temp3 so - alarm indication will work correctly */ - i = w83627hf_read_value(client, W83781D_REG_IRQ); - if (!(i & 0x40)) - w83627hf_write_value(client, W83781D_REG_IRQ, - i | 0x40); } /* Start monitoring */ @@ -1400,7 +1392,7 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) /* skip missing sensors */ if (((data->type == w83697hf) && (i == 1)) || ((data->type == w83627thf || data->type == w83637hf) - && (i == 4 || i == 5))) + && (i == 5 || i == 6))) continue; data->in[i] = w83627hf_read_value(client, W83781D_REG_IN(i)); -- cgit v1.2.3 From 8750197f0e8f5467297d72e11444cf32f29d790f Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 31 Oct 2005 18:51:21 +0100 Subject: [PATCH] i2c-viapro: Some adjustments The big i2c-viapro SMBus driver update which went into 2.6.14-git1 introduced a few minor issues. Nothing critical, but I would like a few adjustments to be merged in to fix the following problems: * VIA should not be spelled Via. * Frodo Looijaard and Philip Edelbrock did not write the i2c-viapro driver. * When debugging is disabled, half of messages would be logged. * Drop an unneeded masking. * Some port reads can be avoided now that the transaction size is passed as a parameter to vt596_transaction(). * SMBus Receive Byte transactions are used for probing too (for EEPROMs), so hide errors on these too. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/i2c/busses/i2c-viapro | 6 ++---- drivers/i2c/busses/i2c-viapro.c | 27 ++++++++++++++------------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/Documentation/i2c/busses/i2c-viapro b/Documentation/i2c/busses/i2c-viapro index 9363b8bd610..16775663b9f 100644 --- a/Documentation/i2c/busses/i2c-viapro +++ b/Documentation/i2c/busses/i2c-viapro @@ -7,12 +7,10 @@ Supported adapters: * VIA Technologies, Inc. VT82C686A/B Datasheet: Sometimes available at the VIA website - * VIA Technologies, Inc. VT8231, VT8233, VT8233A, VT8235, VT8237 - Datasheet: available on request from Via + * VIA Technologies, Inc. VT8231, VT8233, VT8233A, VT8235, VT8237R + Datasheet: available on request from VIA Authors: - Frodo Looijaard , - Philip Edelbrock , Kyösti Mälkki , Mark D. Studebaker , Jean Delvare diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index c9366b50483..a2237d4b2cf 100644 --- a/drivers/i2c/busses/i2c-viapro.c +++ b/drivers/i2c/busses/i2c-viapro.c @@ -142,19 +142,18 @@ static int vt596_transaction(u8 size) /* Make sure the SMBus host is ready to start transmitting */ if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { dev_dbg(&vt596_adapter.dev, "SMBus busy (0x%02x). " - "Resetting... ", temp); + "Resetting...\n", temp); outb_p(temp, SMBHSTSTS); if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { - printk("Failed! (0x%02x)\n", temp); + dev_err(&vt596_adapter.dev, "SMBus reset failed! " + "(0x%02x)\n", temp); return -1; - } else { - printk("Successful!\n"); } } /* Start the transaction by setting bit 6 */ - outb_p(0x40 | (size & 0x3C), SMBHSTCNT); + outb_p(0x40 | size, SMBHSTCNT); /* We will always wait for a fraction of a second */ do { @@ -171,7 +170,7 @@ static int vt596_transaction(u8 size) if (temp & 0x10) { result = -1; dev_err(&vt596_adapter.dev, "Transaction failed (0x%02x)\n", - inb_p(SMBHSTCNT) & 0x3C); + size); } if (temp & 0x08) { @@ -180,11 +179,13 @@ static int vt596_transaction(u8 size) } if (temp & 0x04) { + int read = inb_p(SMBHSTADD) & 0x01; result = -1; - /* Quick commands are used to probe for chips, so - errors are expected, and we don't want to frighten the - user. */ - if ((inb_p(SMBHSTCNT) & 0x3C) != VT596_QUICK) + /* The quick and receive byte commands are used to probe + for chips, so errors are expected, and we don't want + to frighten the user. */ + if (!((size == VT596_QUICK && !read) || + (size == VT596_BYTE && read))) dev_err(&vt596_adapter.dev, "Transaction error!\n"); } @@ -462,9 +463,9 @@ static void __exit i2c_vt596_exit(void) } } -MODULE_AUTHOR( - "Frodo Looijaard and " - "Philip Edelbrock "); +MODULE_AUTHOR("Kyosti Malkki , " + "Mark D. Studebaker and " + "Jean Delvare "); MODULE_DESCRIPTION("vt82c596 SMBus driver"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From dbebb4cbe02dc811e21bd3bc40a252490e46b949 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 8 Nov 2005 10:40:10 +0000 Subject: [ARM SMP] Add missing SMP timer handling for realview Until we have local timer support, we need to broadcast the timer interrupt to the other CPUs. Also, add the missing smp_send_timer() prototype to asm/smp.h Signed-off-by: Russell King --- arch/arm/mach-realview/core.c | 5 +++++ include/asm-arm/smp.h | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 482eb512ebe..4ea60d8b6e3 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -550,6 +550,11 @@ static irqreturn_t realview_timer_interrupt(int irq, void *dev_id, struct pt_reg timer_tick(regs); +#ifdef CONFIG_SMP + smp_send_timer(); + update_process_times(user_mode(regs)); +#endif + write_sequnlock(&xtime_lock); return IRQ_HANDLED; diff --git a/include/asm-arm/smp.h b/include/asm-arm/smp.h index 551cd3c3093..21d1723c03e 100644 --- a/include/asm-arm/smp.h +++ b/include/asm-arm/smp.h @@ -46,6 +46,11 @@ extern void smp_store_cpu_info(unsigned int cpuid); */ extern void smp_cross_call(cpumask_t callmap); +/* + * Broadcast a timer interrupt to the other CPUs. + */ +extern void smp_send_timer(void); + /* * Boot a secondary CPU, and assign it the specified idle task. * This also gives us the initial stack to use for this CPU. -- cgit v1.2.3 From 5d43045bcd296f9f269ab266bf26cd667d8d560c Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 8 Nov 2005 10:44:46 +0000 Subject: [ARM SMP] Fix some sparse warnings in SMP code Signed-off-by: Russell King --- arch/arm/kernel/smp.c | 6 +++--- arch/arm/mach-realview/platsmp.c | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index edb5a406922..f65750a3d28 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -142,7 +142,7 @@ int __cpuinit __cpu_up(unsigned int cpu) ret = -EIO; } - secondary_data.stack = 0; + secondary_data.stack = NULL; secondary_data.pgdir = 0; *pmd_offset(pgd, PHYS_OFFSET) = __pmd(0); @@ -359,8 +359,8 @@ static void send_ipi_message(cpumask_t callmap, enum ipi_msg_type msg) * You must not call this function with disabled interrupts, from a * hardware interrupt handler, nor from a bottom half handler. */ -int smp_call_function_on_cpu(void (*func)(void *info), void *info, int retry, - int wait, cpumask_t callmap) +static int smp_call_function_on_cpu(void (*func)(void *info), void *info, + int retry, int wait, cpumask_t callmap) { struct smp_call_struct data; unsigned long timeout; diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c index 9844644d0fb..09b35f62247 100644 --- a/arch/arm/mach-realview/platsmp.c +++ b/arch/arm/mach-realview/platsmp.c @@ -32,7 +32,7 @@ static unsigned int __init get_core_count(void) { unsigned int ncores; - ncores = __raw_readl(IO_ADDRESS(REALVIEW_MPCORE_SCU_BASE) + SCU_CONFIG); + ncores = __raw_readl(__io_address(REALVIEW_MPCORE_SCU_BASE) + SCU_CONFIG); return (ncores & 0x03) + 1; } @@ -133,12 +133,12 @@ static void __init poke_milo(void) #if 1 #define REALVIEW_SYS_FLAGSS_OFFSET 0x30 __raw_writel(virt_to_phys(realview_secondary_startup), - (IO_ADDRESS(REALVIEW_SYS_BASE) + - REALVIEW_SYS_FLAGSS_OFFSET)); + __io_address(REALVIEW_SYS_BASE) + + REALVIEW_SYS_FLAGSS_OFFSET); #define REALVIEW_SYS_FLAGSC_OFFSET 0x34 __raw_writel(3, - (IO_ADDRESS(REALVIEW_SYS_BASE) + - REALVIEW_SYS_FLAGSC_OFFSET)); + __io_address(REALVIEW_SYS_BASE) + + REALVIEW_SYS_FLAGSC_OFFSET); #endif mb(); -- cgit v1.2.3 From 3825ac0ee66b50cb0208ee74796fe65f3040e67c Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 8 Nov 2005 22:48:08 +1100 Subject: powerpc: Fix crash in early boot on some powermacs Some powermac machines were crashing in the quiesce firmware call in prom_init.c because we have just closed the OF stdin device; notably my 1999 G3 powerbook does this. To avoid this, don't close the OF stdin device on powermacs. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom_init.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 6dc33d19fc2..58f0917bd6b 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -2081,8 +2081,13 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, prom_printf("copying OF device tree ...\n"); flatten_device_tree(); - /* in case stdin is USB and still active on IBM machines... */ - prom_close_stdin(); + /* + * in case stdin is USB and still active on IBM machines... + * Unfortunately quiesce crashes on some powermacs if we have + * closed stdin already (in particular the powerbook 101). + */ + if (RELOC(of_platform) != PLATFORM_POWERMAC) + prom_close_stdin(); /* * Call OF "quiesce" method to shut down pending DMA's from -- cgit v1.2.3 From fca5dcd4835ed09bb1a48a355344aff7a25c76e0 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 8 Nov 2005 22:55:08 +1100 Subject: powerpc: Simplify and clean up the xmon terminal I/O This factors out the common bits of arch/powerpc/xmon/start_*.c into a new nonstdio.c, and removes some stuff that was supposed to make xmon's I/O routines somewhat stdio-like but was never used. It also makes the parsing of the xmon= command line option common, so that ppc32 can now use xmon={off,on,early} also. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/setup-common.c | 21 +++ arch/powerpc/kernel/setup_32.c | 11 +- arch/powerpc/kernel/setup_64.c | 20 --- arch/powerpc/xmon/Makefile | 2 +- arch/powerpc/xmon/nonstdio.c | 134 +++++++++++++++++++ arch/powerpc/xmon/nonstdio.h | 28 ++-- arch/powerpc/xmon/start_32.c | 235 ++++------------------------------ arch/powerpc/xmon/start_64.c | 167 +----------------------- arch/powerpc/xmon/start_8xx.c | 255 +------------------------------------ arch/powerpc/xmon/subr_prf.c | 54 -------- arch/powerpc/xmon/xmon.c | 37 ++++-- include/asm-powerpc/xmon.h | 1 - 12 files changed, 236 insertions(+), 729 deletions(-) create mode 100644 arch/powerpc/xmon/nonstdio.c delete mode 100644 arch/powerpc/xmon/subr_prf.c diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index e22856ecb5a..26bb1fe6384 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -51,6 +51,7 @@ #include #include #include +#include #undef DEBUG @@ -559,3 +560,23 @@ void __init smp_setup_cpu_maps(void) #endif /* CONFIG_PPC64 */ } #endif /* CONFIG_SMP */ + +#ifdef CONFIG_XMON +static int __init early_xmon(char *p) +{ + /* ensure xmon is enabled */ + if (p) { + if (strncmp(p, "on", 2) == 0) + xmon_init(1); + if (strncmp(p, "off", 3) == 0) + xmon_init(0); + if (strncmp(p, "early", 5) != 0) + return 0; + } + xmon_init(1); + debugger(NULL); + + return 0; +} +early_param("xmon", early_xmon); +#endif diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 3af2631e3fa..0fbc73f7f82 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -303,14 +303,9 @@ void __init setup_arch(char **cmdline_p) pmac_feature_init(); /* New cool way */ #endif -#ifdef CONFIG_XMON - xmon_map_scc(); - if (strstr(cmd_line, "xmon")) { - xmon_init(1); - debugger(NULL); - } -#endif /* CONFIG_XMON */ - if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab); +#ifdef CONFIG_XMON_DEFAULT + xmon_init(1); +#endif #if defined(CONFIG_KGDB) if (ppc_md.kgdb_map_scc) diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 0471e843b6c..54c606f680b 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -858,26 +858,6 @@ int check_legacy_ioport(unsigned long base_port) } EXPORT_SYMBOL(check_legacy_ioport); -#ifdef CONFIG_XMON -static int __init early_xmon(char *p) -{ - /* ensure xmon is enabled */ - if (p) { - if (strncmp(p, "on", 2) == 0) - xmon_init(1); - if (strncmp(p, "off", 3) == 0) - xmon_init(0); - if (strncmp(p, "early", 5) != 0) - return 0; - } - xmon_init(1); - debugger(NULL); - - return 0; -} -early_param("xmon", early_xmon); -#endif - void cpu_die(void) { if (ppc_md.cpu_die) diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile index 79a784f0e7a..b20312e5ed2 100644 --- a/arch/powerpc/xmon/Makefile +++ b/arch/powerpc/xmon/Makefile @@ -8,4 +8,4 @@ obj-$(CONFIG_8xx) += start_8xx.o obj-$(CONFIG_6xx) += start_32.o obj-$(CONFIG_4xx) += start_32.o obj-$(CONFIG_PPC64) += start_64.o -obj-y += xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o +obj-y += xmon.o ppc-dis.o ppc-opc.o setjmp.o nonstdio.o diff --git a/arch/powerpc/xmon/nonstdio.c b/arch/powerpc/xmon/nonstdio.c new file mode 100644 index 00000000000..78765833f4c --- /dev/null +++ b/arch/powerpc/xmon/nonstdio.c @@ -0,0 +1,134 @@ +/* + * Copyright (C) 1996-2005 Paul Mackerras. + * + * 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 option) any later version. + */ +#include +#include +#include "nonstdio.h" + +int xmon_putchar(int c) +{ + char ch = c; + + if (c == '\n') + xmon_putchar('\r'); + return xmon_write(&ch, 1) == 1? c: -1; +} + +static char line[256]; +static char *lineptr; +static int lineleft; + +int xmon_expect(const char *str, unsigned long timeout) +{ + int c; + unsigned long t0; + + /* assume 25MHz default timebase if tb_ticks_per_sec not set yet */ + timeout *= tb_ticks_per_sec? tb_ticks_per_sec: 25000000; + t0 = get_tbl(); + do { + lineptr = line; + for (;;) { + c = xmon_read_poll(); + if (c == -1) { + if (get_tbl() - t0 > timeout) + return 0; + continue; + } + if (c == '\n') + break; + if (c != '\r' && lineptr < &line[sizeof(line) - 1]) + *lineptr++ = c; + } + *lineptr = 0; + } while (strstr(line, str) == NULL); + return 1; +} + +int xmon_getchar(void) +{ + int c; + + if (lineleft == 0) { + lineptr = line; + for (;;) { + c = xmon_readchar(); + if (c == -1 || c == 4) + break; + if (c == '\r' || c == '\n') { + *lineptr++ = '\n'; + xmon_putchar('\n'); + break; + } + switch (c) { + case 0177: + case '\b': + if (lineptr > line) { + xmon_putchar('\b'); + xmon_putchar(' '); + xmon_putchar('\b'); + --lineptr; + } + break; + case 'U' & 0x1F: + while (lineptr > line) { + xmon_putchar('\b'); + xmon_putchar(' '); + xmon_putchar('\b'); + --lineptr; + } + break; + default: + if (lineptr >= &line[sizeof(line) - 1]) + xmon_putchar('\a'); + else { + xmon_putchar(c); + *lineptr++ = c; + } + } + } + lineleft = lineptr - line; + lineptr = line; + } + if (lineleft == 0) + return -1; + --lineleft; + return *lineptr++; +} + +char *xmon_gets(char *str, int nb) +{ + char *p; + int c; + + for (p = str; p < str + nb - 1; ) { + c = xmon_getchar(); + if (c == -1) { + if (p == str) + return NULL; + break; + } + *p++ = c; + if (c == '\n') + break; + } + *p = 0; + return str; +} + +void xmon_printf(const char *format, ...) +{ + va_list args; + int n; + static char xmon_outbuf[1024]; + + va_start(args, format); + n = vsnprintf(xmon_outbuf, sizeof(xmon_outbuf), format, args); + va_end(args); + xmon_write(xmon_outbuf, n); +} diff --git a/arch/powerpc/xmon/nonstdio.h b/arch/powerpc/xmon/nonstdio.h index 84211a21c6f..47cebbd2b1b 100644 --- a/arch/powerpc/xmon/nonstdio.h +++ b/arch/powerpc/xmon/nonstdio.h @@ -1,22 +1,14 @@ -typedef int FILE; -extern FILE *xmon_stdin, *xmon_stdout; #define EOF (-1) -#define stdin xmon_stdin -#define stdout xmon_stdout + #define printf xmon_printf -#define fprintf xmon_fprintf -#define fputs xmon_fputs -#define fgets xmon_fgets #define putchar xmon_putchar -#define getchar xmon_getchar -#define putc xmon_putc -#define getc xmon_getc -#define fopen(n, m) NULL -#define fflush(f) do {} while (0) -#define fclose(f) do {} while (0) -extern char *fgets(char *, int, void *); -extern void xmon_printf(const char *, ...); -extern void xmon_fprintf(void *, const char *, ...); -extern void xmon_sprintf(char *, const char *, ...); -#define perror(s) printf("%s: no files!\n", (s)) +extern int xmon_putchar(int c); +extern int xmon_getchar(void); +extern char *xmon_gets(char *, int); +extern void xmon_printf(const char *, ...); +extern void xmon_map_scc(void); +extern int xmon_expect(const char *str, unsigned long timeout); +extern int xmon_write(void *ptr, int nb); +extern int xmon_readchar(void); +extern int xmon_read_poll(void); diff --git a/arch/powerpc/xmon/start_32.c b/arch/powerpc/xmon/start_32.c index 69b658c0f76..c2464df4217 100644 --- a/arch/powerpc/xmon/start_32.c +++ b/arch/powerpc/xmon/start_32.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -22,10 +21,11 @@ #include #include #include +#include +#include "nonstdio.h" static volatile unsigned char __iomem *sccc, *sccd; unsigned int TXRDY, RXRDY, DLAB; -static int xmon_expect(const char *str, unsigned int timeout); static int use_serial; static int use_screen; @@ -33,16 +33,6 @@ static int via_modem; static int xmon_use_sccb; static struct device_node *channel_node; -#define TB_SPEED 25000000 - -static inline unsigned int readtb(void) -{ - unsigned int ret; - - asm volatile("mftb %0" : "=r" (ret) :); - return ret; -} - void buf_access(void) { if (DLAB) @@ -91,23 +81,7 @@ static unsigned long chrp_find_phys_io_base(void) } #endif /* CONFIG_PPC_CHRP */ -#ifdef CONFIG_MAGIC_SYSRQ -static void sysrq_handle_xmon(int key, struct pt_regs *regs, - struct tty_struct *tty) -{ - xmon(regs); -} - -static struct sysrq_key_op sysrq_xmon_op = -{ - .handler = sysrq_handle_xmon, - .help_msg = "Xmon", - .action_msg = "Entering xmon", -}; -#endif - -void -xmon_map_scc(void) +void xmon_map_scc(void) { #ifdef CONFIG_PPC_MULTIPLATFORM volatile unsigned char __iomem *base; @@ -217,8 +191,6 @@ xmon_map_scc(void) RXRDY = 1; DLAB = 0x80; #endif /* platform */ - - register_sysrq_key('x', &sysrq_xmon_op); } static int scc_initialized = 0; @@ -238,8 +210,7 @@ static inline void do_poll_adb(void) #endif /* CONFIG_ADB_CUDA */ } -int -xmon_write(void *handle, void *ptr, int nb) +int xmon_write(void *ptr, int nb) { char *p = ptr; int i, c, ct; @@ -311,8 +282,7 @@ static unsigned char xmon_shift_keytab[128] = "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */ "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */ -static int -xmon_get_adb_key(void) +static int xmon_get_adb_key(void) { int k, t, on; @@ -350,32 +320,21 @@ xmon_get_adb_key(void) } #endif /* CONFIG_BOOTX_TEXT */ -int -xmon_read(void *handle, void *ptr, int nb) +int xmon_readchar(void) { - char *p = ptr; - int i; - #ifdef CONFIG_BOOTX_TEXT - if (use_screen) { - for (i = 0; i < nb; ++i) - *p++ = xmon_get_adb_key(); - return i; - } + if (use_screen) + return xmon_get_adb_key(); #endif - if (!scc_initialized) - xmon_init_scc(); - for (i = 0; i < nb; ++i) { + if (!scc_initialized) + xmon_init_scc(); while ((*sccc & RXRDY) == 0) - do_poll_adb(); + do_poll_adb(); buf_access(); - *p++ = *sccd; - } - return i; + return *sccd; } -int -xmon_read_poll(void) +int xmon_read_poll(void) { if ((*sccc & RXRDY) == 0) { do_poll_adb(); @@ -395,8 +354,7 @@ static unsigned char scc_inittab[] = { 3, 0xc1, /* rx enable, 8 bits */ }; -void -xmon_init_scc(void) +void xmon_init_scc(void) { if ( _machine == _MACH_chrp ) { @@ -410,6 +368,7 @@ xmon_init_scc(void) else if ( _machine == _MACH_Pmac ) { int i, x; + unsigned long timeout; if (channel_node != 0) pmac_call_feature( @@ -424,8 +383,12 @@ xmon_init_scc(void) PMAC_FTR_MODEM_ENABLE, channel_node, 0, 1); printk(KERN_INFO "Modem powered up by debugger !\n"); - t0 = readtb(); - while (readtb() - t0 < 3*TB_SPEED) + t0 = get_tbl(); + timeout = 3 * tb_ticks_per_sec; + if (timeout == 0) + /* assume 25MHz if tb_ticks_per_sec not set */ + timeout = 75000000; + while (get_tbl() - t0 < timeout) eieio(); } /* use the B channel if requested */ @@ -447,164 +410,19 @@ xmon_init_scc(void) scc_initialized = 1; if (via_modem) { for (;;) { - xmon_write(NULL, "ATE1V1\r", 7); + xmon_write("ATE1V1\r", 7); if (xmon_expect("OK", 5)) { - xmon_write(NULL, "ATA\r", 4); + xmon_write("ATA\r", 4); if (xmon_expect("CONNECT", 40)) break; } - xmon_write(NULL, "+++", 3); + xmon_write("+++", 3); xmon_expect("OK", 3); } } } -void *xmon_stdin; -void *xmon_stdout; -void *xmon_stderr; - -int xmon_putc(int c, void *f) -{ - char ch = c; - - if (c == '\n') - xmon_putc('\r', f); - return xmon_write(f, &ch, 1) == 1? c: -1; -} - -int xmon_putchar(int c) -{ - return xmon_putc(c, xmon_stdout); -} - -int xmon_fputs(char *str, void *f) -{ - int n = strlen(str); - - return xmon_write(f, str, n) == n? 0: -1; -} - -int -xmon_readchar(void) -{ - char ch; - - for (;;) { - switch (xmon_read(xmon_stdin, &ch, 1)) { - case 1: - return ch; - case -1: - xmon_printf("read(stdin) returned -1\r\n", 0, 0); - return -1; - } - } -} - -static char line[256]; -static char *lineptr; -static int lineleft; - -int xmon_expect(const char *str, unsigned int timeout) -{ - int c; - unsigned int t0; - - timeout *= TB_SPEED; - t0 = readtb(); - do { - lineptr = line; - for (;;) { - c = xmon_read_poll(); - if (c == -1) { - if (readtb() - t0 > timeout) - return 0; - continue; - } - if (c == '\n') - break; - if (c != '\r' && lineptr < &line[sizeof(line) - 1]) - *lineptr++ = c; - } - *lineptr = 0; - } while (strstr(line, str) == NULL); - return 1; -} - -int -xmon_getchar(void) -{ - int c; - - if (lineleft == 0) { - lineptr = line; - for (;;) { - c = xmon_readchar(); - if (c == -1 || c == 4) - break; - if (c == '\r' || c == '\n') { - *lineptr++ = '\n'; - xmon_putchar('\n'); - break; - } - switch (c) { - case 0177: - case '\b': - if (lineptr > line) { - xmon_putchar('\b'); - xmon_putchar(' '); - xmon_putchar('\b'); - --lineptr; - } - break; - case 'U' & 0x1F: - while (lineptr > line) { - xmon_putchar('\b'); - xmon_putchar(' '); - xmon_putchar('\b'); - --lineptr; - } - break; - default: - if (lineptr >= &line[sizeof(line) - 1]) - xmon_putchar('\a'); - else { - xmon_putchar(c); - *lineptr++ = c; - } - } - } - lineleft = lineptr - line; - lineptr = line; - } - if (lineleft == 0) - return -1; - --lineleft; - return *lineptr++; -} - -char * -xmon_fgets(char *str, int nb, void *f) -{ - char *p; - int c; - - for (p = str; p < str + nb - 1; ) { - c = xmon_getchar(); - if (c == -1) { - if (p == str) - return NULL; - break; - } - *p++ = c; - if (c == '\n') - break; - } - *p = 0; - return str; -} - -void -xmon_enter(void) +void xmon_enter(void) { #ifdef CONFIG_ADB_PMU if (_machine == _MACH_Pmac) { @@ -613,8 +431,7 @@ xmon_enter(void) #endif } -void -xmon_leave(void) +void xmon_leave(void) { #ifdef CONFIG_ADB_PMU if (_machine == _MACH_Pmac) { diff --git a/arch/powerpc/xmon/start_64.c b/arch/powerpc/xmon/start_64.c index e50c158191e..712552c4f24 100644 --- a/arch/powerpc/xmon/start_64.c +++ b/arch/powerpc/xmon/start_64.c @@ -6,182 +6,29 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include #include -#include #include "nonstdio.h" -#ifdef CONFIG_MAGIC_SYSRQ - -static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs, - struct tty_struct *tty) -{ - /* ensure xmon is enabled */ - xmon_init(1); - debugger(pt_regs); -} - -static struct sysrq_key_op sysrq_xmon_op = +void xmon_map_scc(void) { - .handler = sysrq_handle_xmon, - .help_msg = "Xmon", - .action_msg = "Entering xmon", -}; - -static int __init setup_xmon_sysrq(void) -{ - register_sysrq_key('x', &sysrq_xmon_op); - return 0; } -__initcall(setup_xmon_sysrq); -#endif /* CONFIG_MAGIC_SYSRQ */ -int -xmon_write(void *handle, void *ptr, int nb) +int xmon_write(void *ptr, int nb) { return udbg_write(ptr, nb); } -int -xmon_read(void *handle, void *ptr, int nb) +int xmon_readchar(void) { - return udbg_read(ptr, nb); + if (udbg_getc) + return udbg_getc(); + return -1; } -int -xmon_read_poll(void) +int xmon_read_poll(void) { if (udbg_getc_poll) return udbg_getc_poll(); return -1; } - -FILE *xmon_stdin; -FILE *xmon_stdout; - -int -xmon_putc(int c, void *f) -{ - char ch = c; - - if (c == '\n') - xmon_putc('\r', f); - return xmon_write(f, &ch, 1) == 1? c: -1; -} - -int -xmon_putchar(int c) -{ - return xmon_putc(c, xmon_stdout); -} - -int -xmon_fputs(char *str, void *f) -{ - int n = strlen(str); - - return xmon_write(f, str, n) == n? 0: -1; -} - -int -xmon_readchar(void) -{ - char ch; - - for (;;) { - switch (xmon_read(xmon_stdin, &ch, 1)) { - case 1: - return ch; - case -1: - xmon_printf("read(stdin) returned -1\r\n", 0, 0); - return -1; - } - } -} - -static char line[256]; -static char *lineptr; -static int lineleft; - -int -xmon_getchar(void) -{ - int c; - - if (lineleft == 0) { - lineptr = line; - for (;;) { - c = xmon_readchar(); - if (c == -1 || c == 4) - break; - if (c == '\r' || c == '\n') { - *lineptr++ = '\n'; - xmon_putchar('\n'); - break; - } - switch (c) { - case 0177: - case '\b': - if (lineptr > line) { - xmon_putchar('\b'); - xmon_putchar(' '); - xmon_putchar('\b'); - --lineptr; - } - break; - case 'U' & 0x1F: - while (lineptr > line) { - xmon_putchar('\b'); - xmon_putchar(' '); - xmon_putchar('\b'); - --lineptr; - } - break; - default: - if (lineptr >= &line[sizeof(line) - 1]) - xmon_putchar('\a'); - else { - xmon_putchar(c); - *lineptr++ = c; - } - } - } - lineleft = lineptr - line; - lineptr = line; - } - if (lineleft == 0) - return -1; - --lineleft; - return *lineptr++; -} - -char * -xmon_fgets(char *str, int nb, void *f) -{ - char *p; - int c; - - for (p = str; p < str + nb - 1; ) { - c = xmon_getchar(); - if (c == -1) { - if (p == str) - return NULL; - break; - } - *p++ = c; - if (c == '\n') - break; - } - *p = 0; - return str; -} diff --git a/arch/powerpc/xmon/start_8xx.c b/arch/powerpc/xmon/start_8xx.c index a48bd594cf6..4c17b0486ad 100644 --- a/arch/powerpc/xmon/start_8xx.c +++ b/arch/powerpc/xmon/start_8xx.c @@ -15,273 +15,30 @@ #include #include #include +#include "nonstdio.h" -extern void xmon_printf(const char *fmt, ...); extern int xmon_8xx_write(char *str, int nb); extern int xmon_8xx_read_poll(void); extern int xmon_8xx_read_char(void); -void prom_drawhex(uint); -void prom_drawstring(const char *str); -static int use_screen = 1; /* default */ - -#define TB_SPEED 25000000 - -static inline unsigned int readtb(void) -{ - unsigned int ret; - - asm volatile("mftb %0" : "=r" (ret) :); - return ret; -} - -void buf_access(void) -{ -} - -void -xmon_map_scc(void) +void xmon_map_scc(void) { - cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm); - use_screen = 0; - - prom_drawstring("xmon uses serial port\n"); } -static int scc_initialized = 0; - void xmon_init_scc(void); -int -xmon_write(void *handle, void *ptr, int nb) +int xmon_write(void *ptr, int nb) { - char *p = ptr; - int i, c, ct; - - if (!scc_initialized) - xmon_init_scc(); - return(xmon_8xx_write(ptr, nb)); } -int xmon_wants_key; - -int -xmon_read(void *handle, void *ptr, int nb) +int xmon_readchar(void) { - char *p = ptr; - int i; - - if (!scc_initialized) - xmon_init_scc(); - - for (i = 0; i < nb; ++i) { - *p++ = xmon_8xx_read_char(); - } - return i; + return xmon_8xx_read_char(); } -int -xmon_read_poll(void) +int xmon_read_poll(void) { return(xmon_8xx_read_poll()); } - -void -xmon_init_scc() -{ - scc_initialized = 1; -} - -#if 0 -extern int (*prom_entry)(void *); - -int -xmon_exit(void) -{ - struct prom_args { - char *service; - } args; - - for (;;) { - args.service = "exit"; - (*prom_entry)(&args); - } -} -#endif - -void *xmon_stdin; -void *xmon_stdout; -void *xmon_stderr; - -void -xmon_init(void) -{ -} - -int -xmon_putc(int c, void *f) -{ - char ch = c; - - if (c == '\n') - xmon_putc('\r', f); - return xmon_write(f, &ch, 1) == 1? c: -1; -} - -int -xmon_putchar(int c) -{ - return xmon_putc(c, xmon_stdout); -} - -int -xmon_fputs(char *str, void *f) -{ - int n = strlen(str); - - return xmon_write(f, str, n) == n? 0: -1; -} - -int -xmon_readchar(void) -{ - char ch; - - for (;;) { - switch (xmon_read(xmon_stdin, &ch, 1)) { - case 1: - return ch; - case -1: - xmon_printf("read(stdin) returned -1\r\n", 0, 0); - return -1; - } - } -} - -static char line[256]; -static char *lineptr; -static int lineleft; - -#if 0 -int xmon_expect(const char *str, unsigned int timeout) -{ - int c; - unsigned int t0; - - timeout *= TB_SPEED; - t0 = readtb(); - do { - lineptr = line; - for (;;) { - c = xmon_read_poll(); - if (c == -1) { - if (readtb() - t0 > timeout) - return 0; - continue; - } - if (c == '\n') - break; - if (c != '\r' && lineptr < &line[sizeof(line) - 1]) - *lineptr++ = c; - } - *lineptr = 0; - } while (strstr(line, str) == NULL); - return 1; -} -#endif - -int -xmon_getchar(void) -{ - int c; - - if (lineleft == 0) { - lineptr = line; - for (;;) { - c = xmon_readchar(); - if (c == -1 || c == 4) - break; - if (c == '\r' || c == '\n') { - *lineptr++ = '\n'; - xmon_putchar('\n'); - break; - } - switch (c) { - case 0177: - case '\b': - if (lineptr > line) { - xmon_putchar('\b'); - xmon_putchar(' '); - xmon_putchar('\b'); - --lineptr; - } - break; - case 'U' & 0x1F: - while (lineptr > line) { - xmon_putchar('\b'); - xmon_putchar(' '); - xmon_putchar('\b'); - --lineptr; - } - break; - default: - if (lineptr >= &line[sizeof(line) - 1]) - xmon_putchar('\a'); - else { - xmon_putchar(c); - *lineptr++ = c; - } - } - } - lineleft = lineptr - line; - lineptr = line; - } - if (lineleft == 0) - return -1; - --lineleft; - return *lineptr++; -} - -char * -xmon_fgets(char *str, int nb, void *f) -{ - char *p; - int c; - - for (p = str; p < str + nb - 1; ) { - c = xmon_getchar(); - if (c == -1) { - if (p == str) - return 0; - break; - } - *p++ = c; - if (c == '\n') - break; - } - *p = 0; - return str; -} - -void -prom_drawhex(uint val) -{ - unsigned char buf[10]; - - int i; - for (i = 7; i >= 0; i--) - { - buf[i] = "0123456789abcdef"[val & 0x0f]; - val >>= 4; - } - buf[8] = '\0'; - xmon_fputs(buf, xmon_stdout); -} - -void -prom_drawstring(const char *str) -{ - xmon_fputs(str, xmon_stdout); -} diff --git a/arch/powerpc/xmon/subr_prf.c b/arch/powerpc/xmon/subr_prf.c deleted file mode 100644 index b48738c6dd3..00000000000 --- a/arch/powerpc/xmon/subr_prf.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Written by Cort Dougan to replace the version originally used - * by Paul Mackerras, which came from NetBSD and thus had copyright - * conflicts with Linux. - * - * This file makes liberal use of the standard linux utility - * routines to reduce the size of the binary. We assume we can - * trust some parts of Linux inside the debugger. - * -- Cort (cort@cs.nmt.edu) - * - * Copyright (C) 1999 Cort Dougan. - * - * 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 option) any later version. - */ - -#include -#include -#include -#include -#include "nonstdio.h" - -extern int xmon_write(void *, void *, int); - -void xmon_vfprintf(void *f, const char *fmt, va_list ap) -{ - static char xmon_buf[2048]; - int n; - - n = vsprintf(xmon_buf, fmt, ap); - xmon_write(f, xmon_buf, n); -} - -void xmon_printf(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - xmon_vfprintf(stdout, fmt, ap); - va_end(ap); -} -EXPORT_SYMBOL(xmon_printf); - -void xmon_fprintf(void *f, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - xmon_vfprintf(f, fmt, ap); - va_end(ap); -} - diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 1124f114620..b43a57425ea 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -1,7 +1,7 @@ /* * Routines providing a simple monitor for use on the PowerMac. * - * Copyright (C) 1996 Paul Mackerras. + * Copyright (C) 1996-2005 Paul Mackerras. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -144,15 +145,10 @@ static void xmon_print_symbol(unsigned long address, const char *mid, static const char *getvecname(unsigned long vec); extern int print_insn_powerpc(unsigned long, unsigned long, int); -extern void printf(const char *fmt, ...); -extern void xmon_vfprintf(void *f, const char *fmt, va_list ap); -extern int xmon_putc(int c, void *f); -extern int putchar(int ch); extern void xmon_enter(void); extern void xmon_leave(void); -extern int xmon_read_poll(void); extern long setjmp(long *); extern void longjmp(long *, long); extern void xmon_save_regs(struct pt_regs *); @@ -748,7 +744,6 @@ cmds(struct pt_regs *excp) printf("%x:", smp_processor_id()); #endif /* CONFIG_SMP */ printf("mon> "); - fflush(stdout); flush_input(); termch = 0; cmd = skipbl(); @@ -2151,7 +2146,6 @@ memzcan(void) ok = mread(a, &v, 1); if (ok && !ook) { printf("%.8x .. ", a); - fflush(stdout); } else if (!ok && ook) printf("%.8x\n", a - mskip); ook = ok; @@ -2372,7 +2366,7 @@ int inchar(void) { if (lineptr == NULL || *lineptr == 0) { - if (fgets(line, sizeof(line), stdin) == NULL) { + if (xmon_gets(line, sizeof(line)) == NULL) { lineptr = NULL; return EOF; } @@ -2526,4 +2520,29 @@ void xmon_init(int enable) __debugger_dabr_match = NULL; __debugger_fault_handler = NULL; } + xmon_map_scc(); } + +#ifdef CONFIG_MAGIC_SYSRQ +static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs, + struct tty_struct *tty) +{ + /* ensure xmon is enabled */ + xmon_init(1); + debugger(pt_regs); +} + +static struct sysrq_key_op sysrq_xmon_op = +{ + .handler = sysrq_handle_xmon, + .help_msg = "Xmon", + .action_msg = "Entering xmon", +}; + +static int __init setup_xmon_sysrq(void) +{ + register_sysrq_key('x', &sysrq_xmon_op); + return 0; +} +__initcall(setup_xmon_sysrq); +#endif /* CONFIG_MAGIC_SYSRQ */ diff --git a/include/asm-powerpc/xmon.h b/include/asm-powerpc/xmon.h index ace2072d4a8..43f7129984c 100644 --- a/include/asm-powerpc/xmon.h +++ b/include/asm-powerpc/xmon.h @@ -7,7 +7,6 @@ struct pt_regs; extern int xmon(struct pt_regs *excp); extern void xmon_printf(const char *fmt, ...); extern void xmon_init(int); -extern void xmon_map_scc(void); #endif #endif -- cgit v1.2.3 From 2c250134952aac06edbdce5e61f0bd8737dcf3ad Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 8 Nov 2005 14:44:15 +0000 Subject: [ARM] More sparse fixes arch/arm/kernel/irq.c:998:26: warning: Using plain integer as NULL pointer arch/arm/kernel/smp.c:145:25: warning: Using plain integer as NULL pointer arch/arm/kernel/smp.c:362:5: warning: symbol 'smp_call_function_on_cpu' was not declared. Should it be static? drivers/video/amba-clcd.c:521:12: warning: symbol 'amba_clcdfb_init' was not declared. Should it be static? Signed-off-by: Russell King --- arch/arm/kernel/irq.c | 2 +- arch/arm/kernel/smp.c | 2 +- drivers/video/amba-clcd.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 9def4404e1f..6f86d0af7c5 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -995,7 +995,7 @@ void __init init_irq_proc(void) struct proc_dir_entry *dir; int irq; - dir = proc_mkdir("irq", 0); + dir = proc_mkdir("irq", NULL); if (!dir) return; diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index f65750a3d28..f5fc57e0fe4 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -515,7 +515,7 @@ static void ipi_cpu_stop(unsigned int cpu) * * Bit 0 - Inter-processor function call */ -void do_IPI(struct pt_regs *regs) +asmlinkage void do_IPI(struct pt_regs *regs) { unsigned int cpu = smp_processor_id(); struct ipi_data *ipi = &per_cpu(ipi_data, cpu); diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index 467a1d7ebbd..a3c2c45e29e 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c @@ -518,7 +518,7 @@ static struct amba_driver clcd_driver = { .id_table = clcdfb_id_table, }; -int __init amba_clcdfb_init(void) +static int __init amba_clcdfb_init(void) { if (fb_get_options("ambafb", NULL)) return -ENODEV; -- cgit v1.2.3 From 3b6353fae0d7ba772d7eb2651727332c9e9c74ac Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 8 Nov 2005 15:35:23 +0000 Subject: [ARM] Declare asm entry points in asm/smp.h Signed-off-by: Russell King --- include/asm-arm/smp.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/asm-arm/smp.h b/include/asm-arm/smp.h index 21d1723c03e..52e7c8d830b 100644 --- a/include/asm-arm/smp.h +++ b/include/asm-arm/smp.h @@ -36,6 +36,11 @@ struct seq_file; */ extern void show_ipi_list(struct seq_file *p); +/* + * Called from assembly code, this handles an IPI. + */ +asmlinkage void do_IPI(struct pt_regs *regs); + /* * Move global data into per-processor storage. */ @@ -57,6 +62,12 @@ extern void smp_send_timer(void); */ extern int boot_secondary(unsigned int cpu, struct task_struct *); +/* + * Called from platform specific assembly code, this is the + * secondary CPU entry point. + */ +asmlinkage void secondary_start_kernel(void); + /* * Perform platform specific initialisation of the specified CPU. */ -- cgit v1.2.3 From 971f359ddcb2e7a0d577479c7561bda407febe1b Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Tue, 8 Nov 2005 09:37:56 -0800 Subject: [IPV6]: Put addr_diff() into common header for future use. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- include/net/ipv6.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ net/ipv6/ip6_fib.c | 54 ++---------------------------------------------------- 2 files changed, 50 insertions(+), 52 deletions(-) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 65ec86678a0..98661fa4fc7 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -340,6 +340,54 @@ static inline int ipv6_addr_any(const struct in6_addr *a) a->s6_addr32[2] | a->s6_addr32[3] ) == 0); } +/* + * find the first different bit between two addresses + * length of address must be a multiple of 32bits + */ +static inline int __ipv6_addr_diff(const void *token1, const void *token2, int addrlen) +{ + const __u32 *a1 = token1, *a2 = token2; + int i; + + addrlen >>= 2; + + for (i = 0; i < addrlen; i++) { + __u32 xb = a1[i] ^ a2[i]; + if (xb) { + int j = 31; + + xb = ntohl(xb); + while ((xb & (1 << j)) == 0) + j--; + + return (i * 32 + 31 - j); + } + } + + /* + * we should *never* get to this point since that + * would mean the addrs are equal + * + * However, we do get to it 8) And exacly, when + * addresses are equal 8) + * + * ip route add 1111::/128 via ... + * ip route add 1111::/64 via ... + * and we are here. + * + * Ideally, this function should stop comparison + * at prefix length. It does not, but it is still OK, + * if returned value is greater than prefix length. + * --ANK (980803) + */ + return (addrlen << 5); +} + +static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_addr *a2) +{ + return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr)); +} + /* * Prototypes exported by ipv6 */ diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 4fcc5a7acf6..1bf6d9a769e 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -127,56 +127,6 @@ static __inline__ int addr_bit_set(void *token, int fn_bit) return htonl(1 << ((~fn_bit)&0x1F)) & addr[fn_bit>>5]; } -/* - * find the first different bit between two addresses - * length of address must be a multiple of 32bits - */ - -static __inline__ int addr_diff(void *token1, void *token2, int addrlen) -{ - __u32 *a1 = token1; - __u32 *a2 = token2; - int i; - - addrlen >>= 2; - - for (i = 0; i < addrlen; i++) { - __u32 xb; - - xb = a1[i] ^ a2[i]; - - if (xb) { - int j = 31; - - xb = ntohl(xb); - - while ((xb & (1 << j)) == 0) - j--; - - return (i * 32 + 31 - j); - } - } - - /* - * we should *never* get to this point since that - * would mean the addrs are equal - * - * However, we do get to it 8) And exacly, when - * addresses are equal 8) - * - * ip route add 1111::/128 via ... - * ip route add 1111::/64 via ... - * and we are here. - * - * Ideally, this function should stop comparison - * at prefix length. It does not, but it is still OK, - * if returned value is greater than prefix length. - * --ANK (980803) - */ - - return addrlen<<5; -} - static __inline__ struct fib6_node * node_alloc(void) { struct fib6_node *fn; @@ -296,11 +246,11 @@ insert_above: /* find 1st bit in difference between the 2 addrs. - See comment in addr_diff: bit may be an invalid value, + See comment in __ipv6_addr_diff: bit may be an invalid value, but if it is >= plen, the value is ignored in any case. */ - bit = addr_diff(addr, &key->addr, addrlen); + bit = __ipv6_addr_diff(addr, &key->addr, addrlen); /* * (intermediate)[in] -- cgit v1.2.3 From b1cacb6820e0afc4aeeea67bcb5296a316862cad Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Tue, 8 Nov 2005 09:38:12 -0800 Subject: [IPV6]: Make ipv6_addr_type() more generic so that we can use it for source address selection. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- include/net/ipv6.h | 19 +++++++++-- net/ipv6/addrconf.c | 90 +++++++++++++++++++++++++++------------------------- net/ipv6/ipv6_syms.c | 2 +- 3 files changed, 64 insertions(+), 47 deletions(-) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 98661fa4fc7..6addb4d464d 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -252,12 +252,25 @@ typedef int (*inet_getfrag_t) (const void *data, char *, unsigned int, unsigned int); - -extern int ipv6_addr_type(const struct in6_addr *addr); +extern int __ipv6_addr_type(const struct in6_addr *addr); +static inline int ipv6_addr_type(const struct in6_addr *addr) +{ + return __ipv6_addr_type(addr) & 0xffff; +} static inline int ipv6_addr_scope(const struct in6_addr *addr) { - return ipv6_addr_type(addr) & IPV6_ADDR_SCOPE_MASK; + return __ipv6_addr_type(addr) & IPV6_ADDR_SCOPE_MASK; +} + +static inline int __ipv6_addr_src_scope(int type) +{ + return (type == IPV6_ADDR_ANY ? __IPV6_ADDR_SCOPE_INVALID : (type >> 16)); +} + +static inline int ipv6_addr_src_scope(const struct in6_addr *addr) +{ + return __ipv6_addr_src_scope(__ipv6_addr_type(addr)); } static inline int ipv6_addr_cmp(const struct in6_addr *a1, const struct in6_addr *a2) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 2c5f57299d6..ff895da6395 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -35,6 +35,9 @@ * YOSHIFUJI Hideaki @USAGI : ARCnet support * YOSHIFUJI Hideaki @USAGI : convert /proc/net/if_inet6 to * seq_file. + * YOSHIFUJI Hideaki @USAGI : improved source address + * selection; consider scope, + * status etc. */ #include @@ -193,46 +196,51 @@ const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; #endif const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; -int ipv6_addr_type(const struct in6_addr *addr) +#define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16) + +static inline unsigned ipv6_addr_scope2type(unsigned scope) +{ + switch(scope) { + case IPV6_ADDR_SCOPE_NODELOCAL: + return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_NODELOCAL) | + IPV6_ADDR_LOOPBACK); + case IPV6_ADDR_SCOPE_LINKLOCAL: + return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL) | + IPV6_ADDR_LINKLOCAL); + case IPV6_ADDR_SCOPE_SITELOCAL: + return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL) | + IPV6_ADDR_SITELOCAL); + } + return IPV6_ADDR_SCOPE_TYPE(scope); +} + +int __ipv6_addr_type(const struct in6_addr *addr) { - int type; u32 st; st = addr->s6_addr32[0]; - if ((st & htonl(0xFF000000)) == htonl(0xFF000000)) { - type = IPV6_ADDR_MULTICAST; - - switch((st & htonl(0x00FF0000))) { - case __constant_htonl(0x00010000): - type |= IPV6_ADDR_LOOPBACK; - break; - - case __constant_htonl(0x00020000): - type |= IPV6_ADDR_LINKLOCAL; - break; - - case __constant_htonl(0x00050000): - type |= IPV6_ADDR_SITELOCAL; - break; - }; - return type; - } - - type = IPV6_ADDR_UNICAST; - /* Consider all addresses with the first three bits different of - 000 and 111 as finished. + 000 and 111 as unicasts. */ if ((st & htonl(0xE0000000)) != htonl(0x00000000) && (st & htonl(0xE0000000)) != htonl(0xE0000000)) - return type; - - if ((st & htonl(0xFFC00000)) == htonl(0xFE800000)) - return (IPV6_ADDR_LINKLOCAL | type); + return (IPV6_ADDR_UNICAST | + IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); + if ((st & htonl(0xFF000000)) == htonl(0xFF000000)) { + /* multicast */ + /* addr-select 3.1 */ + return (IPV6_ADDR_MULTICAST | + ipv6_addr_scope2type(IPV6_ADDR_MC_SCOPE(addr))); + } + + if ((st & htonl(0xFFC00000)) == htonl(0xFE800000)) + return (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST | + IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.1 */ if ((st & htonl(0xFFC00000)) == htonl(0xFEC00000)) - return (IPV6_ADDR_SITELOCAL | type); + return (IPV6_ADDR_SITELOCAL | IPV6_ADDR_UNICAST | + IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL)); /* addr-select 3.1 */ if ((addr->s6_addr32[0] | addr->s6_addr32[1]) == 0) { if (addr->s6_addr32[2] == 0) { @@ -240,24 +248,20 @@ int ipv6_addr_type(const struct in6_addr *addr) return IPV6_ADDR_ANY; if (addr->s6_addr32[3] == htonl(0x00000001)) - return (IPV6_ADDR_LOOPBACK | type); + return (IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST | + IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.4 */ - return (IPV6_ADDR_COMPATv4 | type); + return (IPV6_ADDR_COMPATv4 | IPV6_ADDR_UNICAST | + IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */ } if (addr->s6_addr32[2] == htonl(0x0000ffff)) - return IPV6_ADDR_MAPPED; - } - - st &= htonl(0xFF000000); - if (st == 0) - return IPV6_ADDR_RESERVED; - st &= htonl(0xFE000000); - if (st == htonl(0x02000000)) - return IPV6_ADDR_RESERVED; /* for NSAP */ - if (st == htonl(0x04000000)) - return IPV6_ADDR_RESERVED; /* for IPX */ - return type; + return (IPV6_ADDR_MAPPED | + IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */ + } + + return (IPV6_ADDR_RESERVED | + IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.4 */ } static void addrconf_del_timer(struct inet6_ifaddr *ifp) diff --git a/net/ipv6/ipv6_syms.c b/net/ipv6/ipv6_syms.c index 37a4a99c9fe..16482785bdf 100644 --- a/net/ipv6/ipv6_syms.c +++ b/net/ipv6/ipv6_syms.c @@ -7,7 +7,7 @@ #include #include -EXPORT_SYMBOL(ipv6_addr_type); +EXPORT_SYMBOL(__ipv6_addr_type); EXPORT_SYMBOL(icmpv6_send); EXPORT_SYMBOL(icmpv6_statistics); EXPORT_SYMBOL(icmpv6_err_convert); -- cgit v1.2.3 From 072047e4de3800905e09d0f8ef0e1cc4e91a601e Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Tue, 8 Nov 2005 09:38:30 -0800 Subject: [IPV6]: RFC3484 compliant source address selection Choose more appropriate source address; e.g. - outgoing interface - non-deprecated - scope - matching label Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 344 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 240 insertions(+), 104 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index ff895da6395..a34d1504deb 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -809,138 +809,274 @@ out: #endif /* - * Choose an appropriate source address - * should do: - * i) get an address with an appropriate scope - * ii) see if there is a specific route for the destination and use - * an address of the attached interface - * iii) don't use deprecated addresses + * Choose an appropriate source address (RFC3484) */ -static int inline ipv6_saddr_pref(const struct inet6_ifaddr *ifp, u8 invpref) +struct ipv6_saddr_score { + int addr_type; + unsigned int attrs; + int matchlen; + unsigned int scope; + unsigned int rule; +}; + +#define IPV6_SADDR_SCORE_LOCAL 0x0001 +#define IPV6_SADDR_SCORE_PREFERRED 0x0004 +#define IPV6_SADDR_SCORE_HOA 0x0008 +#define IPV6_SADDR_SCORE_OIF 0x0010 +#define IPV6_SADDR_SCORE_LABEL 0x0020 +#define IPV6_SADDR_SCORE_PRIVACY 0x0040 + +static int inline ipv6_saddr_preferred(int type) { - int pref; - pref = ifp->flags&IFA_F_DEPRECATED ? 0 : 2; -#ifdef CONFIG_IPV6_PRIVACY - pref |= (ifp->flags^invpref)&IFA_F_TEMPORARY ? 0 : 1; -#endif - return pref; + if (type & (IPV6_ADDR_MAPPED|IPV6_ADDR_COMPATv4| + IPV6_ADDR_LOOPBACK|IPV6_ADDR_RESERVED)) + return 1; + return 0; } -#ifdef CONFIG_IPV6_PRIVACY -#define IPV6_GET_SADDR_MAXSCORE(score) ((score) == 3) -#else -#define IPV6_GET_SADDR_MAXSCORE(score) (score) -#endif +/* static matching label */ +static int inline ipv6_saddr_label(const struct in6_addr *addr, int type) +{ + /* + * prefix (longest match) label + * ----------------------------- + * ::1/128 0 + * ::/0 1 + * 2002::/16 2 + * ::/96 3 + * ::ffff:0:0/96 4 + */ + if (type & IPV6_ADDR_LOOPBACK) + return 0; + else if (type & IPV6_ADDR_COMPATv4) + return 3; + else if (type & IPV6_ADDR_MAPPED) + return 4; + else if (addr->s6_addr16[0] == htons(0x2002)) + return 2; + return 1; +} -int ipv6_dev_get_saddr(struct net_device *dev, +int ipv6_dev_get_saddr(struct net_device *daddr_dev, struct in6_addr *daddr, struct in6_addr *saddr) { - struct inet6_ifaddr *ifp = NULL; - struct inet6_ifaddr *match = NULL; - struct inet6_dev *idev; - int scope; - int err; - int hiscore = -1, score; + struct ipv6_saddr_score hiscore; + struct inet6_ifaddr *ifa_result = NULL; + int daddr_type = __ipv6_addr_type(daddr); + int daddr_scope = __ipv6_addr_src_scope(daddr_type); + u32 daddr_label = ipv6_saddr_label(daddr, daddr_type); + struct net_device *dev; - scope = ipv6_addr_scope(daddr); + memset(&hiscore, 0, sizeof(hiscore)); - /* - * known dev - * search dev and walk through dev addresses - */ + read_lock(&dev_base_lock); + read_lock(&addrconf_lock); - if (dev) { - if (dev->flags & IFF_LOOPBACK) - scope = IFA_HOST; + for (dev = dev_base; dev; dev=dev->next) { + struct inet6_dev *idev; + struct inet6_ifaddr *ifa; + + /* Rule 0: Candidate Source Address (section 4) + * - multicast and link-local destination address, + * the set of candidate source address MUST only + * include addresses assigned to interfaces + * belonging to the same link as the outgoing + * interface. + * (- For site-local destination addresses, the + * set of candidate source addresses MUST only + * include addresses assigned to interfaces + * belonging to the same site as the outgoing + * interface.) + */ + if ((daddr_type & IPV6_ADDR_MULTICAST || + daddr_scope <= IPV6_ADDR_SCOPE_LINKLOCAL) && + daddr_dev && dev != daddr_dev) + continue; - read_lock(&addrconf_lock); idev = __in6_dev_get(dev); - if (idev) { - read_lock_bh(&idev->lock); - for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { - if (ifp->scope == scope) { - if (ifp->flags&IFA_F_TENTATIVE) - continue; -#ifdef CONFIG_IPV6_PRIVACY - score = ipv6_saddr_pref(ifp, idev->cnf.use_tempaddr > 1 ? IFA_F_TEMPORARY : 0); -#else - score = ipv6_saddr_pref(ifp, 0); -#endif - if (score <= hiscore) - continue; + if (!idev) + continue; - if (match) - in6_ifa_put(match); - match = ifp; - hiscore = score; - in6_ifa_hold(ifp); + read_lock_bh(&idev->lock); + for (ifa = idev->addr_list; ifa; ifa = ifa->if_next) { + struct ipv6_saddr_score score; - if (IPV6_GET_SADDR_MAXSCORE(score)) { - read_unlock_bh(&idev->lock); - read_unlock(&addrconf_lock); - goto out; - } + score.addr_type = __ipv6_addr_type(&ifa->addr); + + /* Rule 0: Candidate Source Address (section 4) + * - In any case, anycast addresses, multicast + * addresses, and the unspecified address MUST + * NOT be included in a candidate set. + */ + if (unlikely(score.addr_type == IPV6_ADDR_ANY || + score.addr_type & IPV6_ADDR_MULTICAST)) { + LIMIT_NETDEBUG(KERN_DEBUG + "ADDRCONF: unspecified / multicast address" + "assigned as unicast address on %s", + dev->name); + continue; + } + + score.attrs = 0; + score.matchlen = 0; + score.scope = 0; + score.rule = 0; + + if (ifa_result == NULL) { + /* record it if the first available entry */ + goto record_it; + } + + /* Rule 1: Prefer same address */ + if (hiscore.rule < 1) { + if (ipv6_addr_equal(&ifa_result->addr, daddr)) + hiscore.attrs |= IPV6_SADDR_SCORE_LOCAL; + hiscore.rule++; + } + if (ipv6_addr_equal(&ifa->addr, daddr)) { + score.attrs |= IPV6_SADDR_SCORE_LOCAL; + if (!(hiscore.attrs & IPV6_SADDR_SCORE_LOCAL)) { + score.rule = 1; + goto record_it; } + } else { + if (hiscore.attrs & IPV6_SADDR_SCORE_LOCAL) + continue; } - read_unlock_bh(&idev->lock); - } - read_unlock(&addrconf_lock); - } - if (scope == IFA_LINK) - goto out; + /* Rule 2: Prefer appropriate scope */ + if (hiscore.rule < 2) { + hiscore.scope = __ipv6_addr_src_scope(hiscore.addr_type); + hiscore.rule++; + } + score.scope = __ipv6_addr_src_scope(score.addr_type); + if (hiscore.scope < score.scope) { + if (hiscore.scope < daddr_scope) { + score.rule = 2; + goto record_it; + } else + continue; + } else if (score.scope < hiscore.scope) { + if (score.scope < daddr_scope) + continue; + else { + score.rule = 2; + goto record_it; + } + } - /* - * dev == NULL or search failed for specified dev - */ + /* Rule 3: Avoid deprecated address */ + if (hiscore.rule < 3) { + if (ipv6_saddr_preferred(hiscore.addr_type) || + !(ifa_result->flags & IFA_F_DEPRECATED)) + hiscore.attrs |= IPV6_SADDR_SCORE_PREFERRED; + hiscore.rule++; + } + if (ipv6_saddr_preferred(score.addr_type) || + !(ifa->flags & IFA_F_DEPRECATED)) { + score.attrs |= IPV6_SADDR_SCORE_PREFERRED; + if (!(hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED)) { + score.rule = 3; + goto record_it; + } + } else { + if (hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED) + continue; + } - read_lock(&dev_base_lock); - read_lock(&addrconf_lock); - for (dev = dev_base; dev; dev=dev->next) { - idev = __in6_dev_get(dev); - if (idev) { - read_lock_bh(&idev->lock); - for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { - if (ifp->scope == scope) { - if (ifp->flags&IFA_F_TENTATIVE) - continue; -#ifdef CONFIG_IPV6_PRIVACY - score = ipv6_saddr_pref(ifp, idev->cnf.use_tempaddr > 1 ? IFA_F_TEMPORARY : 0); -#else - score = ipv6_saddr_pref(ifp, 0); -#endif - if (score <= hiscore) - continue; + /* Rule 4: Prefer home address -- not implemented yet */ - if (match) - in6_ifa_put(match); - match = ifp; - hiscore = score; - in6_ifa_hold(ifp); + /* Rule 5: Prefer outgoing interface */ + if (hiscore.rule < 5) { + if (daddr_dev == NULL || + daddr_dev == ifa_result->idev->dev) + hiscore.attrs |= IPV6_SADDR_SCORE_OIF; + hiscore.rule++; + } + if (daddr_dev == NULL || + daddr_dev == ifa->idev->dev) { + score.attrs |= IPV6_SADDR_SCORE_OIF; + if (!(hiscore.attrs & IPV6_SADDR_SCORE_OIF)) { + score.rule = 5; + goto record_it; + } + } else { + if (hiscore.attrs & IPV6_SADDR_SCORE_OIF) + continue; + } - if (IPV6_GET_SADDR_MAXSCORE(score)) { - read_unlock_bh(&idev->lock); - goto out_unlock_base; - } + /* Rule 6: Prefer matching label */ + if (hiscore.rule < 6) { + if (ipv6_saddr_label(&ifa_result->addr, hiscore.addr_type) == daddr_label) + hiscore.attrs |= IPV6_SADDR_SCORE_LABEL; + hiscore.rule++; + } + if (ipv6_saddr_label(&ifa->addr, score.addr_type) == daddr_label) { + score.attrs |= IPV6_SADDR_SCORE_LABEL; + if (!(hiscore.attrs & IPV6_SADDR_SCORE_LABEL)) { + score.rule = 6; + goto record_it; } + } else { + if (hiscore.attrs & IPV6_SADDR_SCORE_LABEL) + continue; } - read_unlock_bh(&idev->lock); + + /* Rule 7: Prefer public address + * Note: prefer temprary address if use_tempaddr >= 2 + */ + if (hiscore.rule < 7) { + if ((!(ifa_result->flags & IFA_F_TEMPORARY)) ^ + (ifa_result->idev->cnf.use_tempaddr >= 2)) + hiscore.attrs |= IPV6_SADDR_SCORE_PRIVACY; + hiscore.rule++; + } + if ((!(ifa->flags & IFA_F_TEMPORARY)) ^ + (ifa->idev->cnf.use_tempaddr >= 2)) { + score.attrs |= IPV6_SADDR_SCORE_PRIVACY; + if (!(hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY)) { + score.rule = 7; + goto record_it; + } + } else { + if (hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY) + continue; + } + + /* Rule 8: Use longest matching prefix */ + if (hiscore.rule < 8) + hiscore.matchlen = ipv6_addr_diff(&ifa_result->addr, daddr); + score.rule++; + score.matchlen = ipv6_addr_diff(&ifa->addr, daddr); + if (score.matchlen > hiscore.matchlen) { + score.rule = 8; + goto record_it; + } +#if 0 + else if (score.matchlen < hiscore.matchlen) + continue; +#endif + + /* Final Rule: choose first available one */ + continue; +record_it: + if (ifa_result) + in6_ifa_put(ifa_result); + in6_ifa_hold(ifa); + ifa_result = ifa; + hiscore = score; } + read_unlock_bh(&idev->lock); } - -out_unlock_base: read_unlock(&addrconf_lock); read_unlock(&dev_base_lock); -out: - err = -EADDRNOTAVAIL; - if (match) { - ipv6_addr_copy(saddr, &match->addr); - err = 0; - in6_ifa_put(match); - } - - return err; + if (!ifa_result) + return -EADDRNOTAVAIL; + + ipv6_addr_copy(saddr, &ifa_result->addr); + in6_ifa_put(ifa_result); + return 0; } -- cgit v1.2.3 From 18a0c23617a2cb1c2e55e650046c2084d823fde0 Mon Sep 17 00:00:00 2001 From: Carlo Comin Date: Tue, 8 Nov 2005 09:38:56 -0800 Subject: [CONNECTOR]: Fix documentation test module. Patch from Carlo Comin Signed-off-by: Evgeniy Polyakov Signed-off-by: David S. Miller --- Documentation/connector/cn_test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/connector/cn_test.c b/Documentation/connector/cn_test.c index b7de82e9c0e..3e73231695b 100644 --- a/Documentation/connector/cn_test.c +++ b/Documentation/connector/cn_test.c @@ -25,7 +25,7 @@ #include #include -#include "connector.h" +#include static struct cb_id cn_test_id = { 0x123, 0x456 }; static char cn_test_name[] = "cn_test"; @@ -104,7 +104,7 @@ static int cn_test_want_notify(void) req->first = cn_test_id.val + 20; req->range = 10; - NETLINK_CB(skb).dst_groups = ctl->group; + NETLINK_CB(skb).dst_group = ctl->group; //netlink_broadcast(nls, skb, 0, ctl->group, GFP_ATOMIC); netlink_unicast(nls, skb, 0, 0); -- cgit v1.2.3 From b541ca2c5a3f3f399d6f2ec9da33c1be5a8d8c19 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Tue, 8 Nov 2005 09:39:17 -0800 Subject: [PKT_SCHED]: Correctly handle empty ematch trees Fixes an invalid memory reference when the basic classifier is used without any ematches but just actions. Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- net/sched/ematch.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/sched/ematch.c b/net/sched/ematch.c index ebfe2e7d21b..64b047c6556 100644 --- a/net/sched/ematch.c +++ b/net/sched/ematch.c @@ -298,6 +298,11 @@ int tcf_em_tree_validate(struct tcf_proto *tp, struct rtattr *rta, struct tcf_ematch_tree_hdr *tree_hdr; struct tcf_ematch *em; + if (!rta) { + memset(tree, 0, sizeof(*tree)); + return 0; + } + if (rtattr_parse_nested(tb, TCA_EMATCH_TREE_MAX, rta) < 0) goto errout; -- cgit v1.2.3 From 9ee6b535af4c2c97b4e3b88f37f244bf1004ebd4 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 8 Nov 2005 09:39:42 -0800 Subject: [NET]: sk_add_backlog convert from macro to inline There is no reason for sk_add_backlog to be a macro. It can just be an inline function and get type checking. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/net/sock.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index e0498bd3600..ff13c4cc287 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -461,16 +461,16 @@ static inline void sk_stream_free_skb(struct sock *sk, struct sk_buff *skb) } /* The per-socket spinlock must be held here. */ -#define sk_add_backlog(__sk, __skb) \ -do { if (!(__sk)->sk_backlog.tail) { \ - (__sk)->sk_backlog.head = \ - (__sk)->sk_backlog.tail = (__skb); \ - } else { \ - ((__sk)->sk_backlog.tail)->next = (__skb); \ - (__sk)->sk_backlog.tail = (__skb); \ - } \ - (__skb)->next = NULL; \ -} while(0) +static inline void sk_add_backlog(struct sock *sk, struct sk_buff *skb) +{ + if (!sk->sk_backlog.tail) { + sk->sk_backlog.head = sk->sk_backlog.tail = skb; + } else { + sk->sk_backlog.tail->next = skb; + sk->sk_backlog.tail = skb; + } + skb->next = NULL; +} #define sk_wait_event(__sk, __timeo, __condition) \ ({ int rc; \ -- cgit v1.2.3 From dc8103f25fd7cfac2c2b295f33edc10f255b4c80 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Tue, 8 Nov 2005 09:40:05 -0800 Subject: [IPVS]: fix connection leak if expire_nodest_conn=1 There was a fix in 2.6.13 that changed the behaviour of ip_vs_conn_expire_now function not to put reference to connection, its callers should hold write lock or connection refcnt. But we forgot to convert one caller, when the real server for connection is unavailable caller should put the connection reference. It happens only when sysctl var expire_nodest_conn is set to 1 and such connections never expire. Thanks to Roberto Nibali who found the problem and tested a 2.4.32-rc2 patch, which is equal to this 2.6 version. Patch for 2.4 is already sent to Marcelo. Signed-off-by: Julian Anastasov Signed-off-by: Roberto Nibali Signed-off-by: David S. Miller --- net/ipv4/ipvs/ip_vs_core.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c index 981cc3244ef..1a0843cd58a 100644 --- a/net/ipv4/ipvs/ip_vs_core.c +++ b/net/ipv4/ipvs/ip_vs_core.c @@ -1009,11 +1009,10 @@ ip_vs_in(unsigned int hooknum, struct sk_buff **pskb, if (sysctl_ip_vs_expire_nodest_conn) { /* try to expire the connection immediately */ ip_vs_conn_expire_now(cp); - } else { - /* don't restart its timer, and silently - drop the packet. */ - __ip_vs_conn_put(cp); } + /* don't restart its timer, and silently + drop the packet. */ + __ip_vs_conn_put(cp); return NF_DROP; } -- cgit v1.2.3 From 6722e78c90054101e6797d5944cdc81af9897a0a Mon Sep 17 00:00:00 2001 From: Philippe De Muyter Date: Tue, 8 Nov 2005 09:40:26 -0800 Subject: [PPP]: handle misaligned accesses From: "Philippe De Muyter" This patch avoids ppp-generated kernel crashes on machines where unaligned accesses are forbidden (ie: m68000), by fixing ppp alignment setting for reused skb's. Signed-off-by: Philippe De Muyter Cc: "David S. Miller" Cc: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/ppp_async.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c index 59e8183c639..400f652282d 100644 --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c @@ -31,6 +31,7 @@ #include #include #include +#include #define PPP_VERSION "2.4.2" @@ -835,8 +836,11 @@ process_input_packet(struct asyncppp *ap) err: /* frame had an error, remember that, reset SC_TOSS & SC_ESCAPE */ ap->state = SC_PREV_ERROR; - if (skb) + if (skb) { + /* make skb appear as freshly allocated */ skb_trim(skb, 0); + skb_reserve(skb, - skb_headroom(skb)); + } } /* Called when the tty driver has data for us. Runs parallel with the @@ -889,10 +893,17 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf, skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2); if (skb == 0) goto nomem; - /* Try to get the payload 4-byte aligned */ + ap->rpkt = skb; + } + if (skb->len == 0) { + /* Try to get the payload 4-byte aligned. + * This should match the + * PPP_ALLSTATIONS/PPP_UI/compressed tests in + * process_input_packet, but we do not have + * enough chars here to test buf[1] and buf[2]. + */ if (buf[0] != PPP_ALLSTATIONS) skb_reserve(skb, 2 + (buf[0] & 1)); - ap->rpkt = skb; } if (n > skb_tailroom(skb)) { /* packet overflowed MRU */ -- cgit v1.2.3 From b3f9b92a6ec1a9a5e4b4b36e484f2f62cc73277c Mon Sep 17 00:00:00 2001 From: Matt Domsch Date: Tue, 8 Nov 2005 09:40:47 -0800 Subject: [PPP]: add PPP MPPE encryption module From: Matt Domsch The patch below implements the Microsoft Point-to-Point Encryption method as a PPP compressor/decompressor. This is necessary for Linux clients and servers to interoperate with Microsoft Point-to-Point Tunneling Protocol (PPTP) servers (either Microsoft PPTP servers or the poptop project) which use MPPE to encrypt data when creating a VPN. This patch differs from the kernel_ppp_mppe DKMS pacakge at pptpclient.sourceforge.net by utilizing the kernel crypto routines rather than providing its own SHA1 and arcfour implementations. Minor changes to ppp_generic.c try to prevent a link from disabling compression (in our case, the encryption) after it has started using compression (encryption). Feedback to please. Signed-off-by: Matt Domsch Cc: James Cameron Cc: "David S. Miller" Signed-off-by: Brice Goglin Acked-by: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/Kconfig | 13 + drivers/net/Makefile | 1 + drivers/net/ppp_generic.c | 88 ++++-- drivers/net/ppp_mppe.c | 724 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/ppp_mppe.h | 86 ++++++ include/linux/if_ppp.h | 7 +- include/linux/ppp-comp.h | 9 + 7 files changed, 902 insertions(+), 26 deletions(-) create mode 100644 drivers/net/ppp_mppe.c create mode 100644 drivers/net/ppp_mppe.h diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 1958d9e16a3..24f1691b84f 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2523,6 +2523,19 @@ config PPP_BSDCOMP module; it is called bsd_comp and will show up in the directory modules once you have said "make modules". If unsure, say N. +config PPP_MPPE + tristate "PPP MPPE compression (encryption) (EXPERIMENTAL)" + depends on PPP && EXPERIMENTAL + select CRYPTO + select CRYPTO_SHA1 + select CRYPTO_ARC4 + ---help--- + Support for the MPPE Encryption protocol, as employed by the + Microsoft Point-to-Point Tunneling Protocol. + + See http://pptpclient.sourceforge.net/ for information on + configuring PPTP clients and servers to utilize this method. + config PPPOE tristate "PPP over Ethernet (EXPERIMENTAL)" depends on EXPERIMENTAL && PPP diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 7c313cb341b..4cffd34442a 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -112,6 +112,7 @@ obj-$(CONFIG_PPP_ASYNC) += ppp_async.o obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o +obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o obj-$(CONFIG_PPPOE) += pppox.o pppoe.o obj-$(CONFIG_SLIP) += slip.o diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index d3c9958b00d..50430f79f8c 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -137,13 +137,14 @@ struct ppp { /* * Bits in flags: SC_NO_TCP_CCID, SC_CCP_OPEN, SC_CCP_UP, SC_LOOP_TRAFFIC, - * SC_MULTILINK, SC_MP_SHORTSEQ, SC_MP_XSHORTSEQ, SC_COMP_TCP, SC_REJ_COMP_TCP. + * SC_MULTILINK, SC_MP_SHORTSEQ, SC_MP_XSHORTSEQ, SC_COMP_TCP, SC_REJ_COMP_TCP, + * SC_MUST_COMP * Bits in rstate: SC_DECOMP_RUN, SC_DC_ERROR, SC_DC_FERROR. * Bits in xstate: SC_COMP_RUN */ #define SC_FLAG_BITS (SC_NO_TCP_CCID|SC_CCP_OPEN|SC_CCP_UP|SC_LOOP_TRAFFIC \ |SC_MULTILINK|SC_MP_SHORTSEQ|SC_MP_XSHORTSEQ \ - |SC_COMP_TCP|SC_REJ_COMP_TCP) + |SC_COMP_TCP|SC_REJ_COMP_TCP|SC_MUST_COMP) /* * Private data structure for each channel. @@ -1027,6 +1028,56 @@ ppp_xmit_process(struct ppp *ppp) ppp_xmit_unlock(ppp); } +static inline struct sk_buff * +pad_compress_skb(struct ppp *ppp, struct sk_buff *skb) +{ + struct sk_buff *new_skb; + int len; + int new_skb_size = ppp->dev->mtu + + ppp->xcomp->comp_extra + ppp->dev->hard_header_len; + int compressor_skb_size = ppp->dev->mtu + + ppp->xcomp->comp_extra + PPP_HDRLEN; + new_skb = alloc_skb(new_skb_size, GFP_ATOMIC); + if (!new_skb) { + if (net_ratelimit()) + printk(KERN_ERR "PPP: no memory (comp pkt)\n"); + return NULL; + } + if (ppp->dev->hard_header_len > PPP_HDRLEN) + skb_reserve(new_skb, + ppp->dev->hard_header_len - PPP_HDRLEN); + + /* compressor still expects A/C bytes in hdr */ + len = ppp->xcomp->compress(ppp->xc_state, skb->data - 2, + new_skb->data, skb->len + 2, + compressor_skb_size); + if (len > 0 && (ppp->flags & SC_CCP_UP)) { + kfree_skb(skb); + skb = new_skb; + skb_put(skb, len); + skb_pull(skb, 2); /* pull off A/C bytes */ + } else if (len == 0) { + /* didn't compress, or CCP not up yet */ + kfree_skb(new_skb); + new_skb = skb; + } else { + /* + * (len < 0) + * MPPE requires that we do not send unencrypted + * frames. The compressor will return -1 if we + * should drop the frame. We cannot simply test + * the compress_proto because MPPE and MPPC share + * the same number. + */ + if (net_ratelimit()) + printk(KERN_ERR "ppp: compressor dropped pkt\n"); + kfree_skb(skb); + kfree_skb(new_skb); + new_skb = NULL; + } + return new_skb; +} + /* * Compress and send a frame. * The caller should have locked the xmit path, @@ -1113,29 +1164,14 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) /* try to do packet compression */ if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state != 0 && proto != PPP_LCP && proto != PPP_CCP) { - new_skb = alloc_skb(ppp->dev->mtu + ppp->dev->hard_header_len, - GFP_ATOMIC); - if (new_skb == 0) { - printk(KERN_ERR "PPP: no memory (comp pkt)\n"); + if (!(ppp->flags & SC_CCP_UP) && (ppp->flags & SC_MUST_COMP)) { + if (net_ratelimit()) + printk(KERN_ERR "ppp: compression required but down - pkt dropped.\n"); goto drop; } - if (ppp->dev->hard_header_len > PPP_HDRLEN) - skb_reserve(new_skb, - ppp->dev->hard_header_len - PPP_HDRLEN); - - /* compressor still expects A/C bytes in hdr */ - len = ppp->xcomp->compress(ppp->xc_state, skb->data - 2, - new_skb->data, skb->len + 2, - ppp->dev->mtu + PPP_HDRLEN); - if (len > 0 && (ppp->flags & SC_CCP_UP)) { - kfree_skb(skb); - skb = new_skb; - skb_put(skb, len); - skb_pull(skb, 2); /* pull off A/C bytes */ - } else { - /* didn't compress, or CCP not up yet */ - kfree_skb(new_skb); - } + skb = pad_compress_skb(ppp, skb); + if (!skb) + goto drop; } /* @@ -1155,7 +1191,8 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) return; drop: - kfree_skb(skb); + if (skb) + kfree_skb(skb); ++ppp->stats.tx_errors; } @@ -1552,6 +1589,9 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) && (ppp->rstate & (SC_DC_FERROR | SC_DC_ERROR)) == 0) skb = ppp_decompress_frame(ppp, skb); + if (ppp->flags & SC_MUST_COMP && ppp->rstate & SC_DC_FERROR) + goto err; + proto = PPP_PROTO(skb); switch (proto) { case PPP_VJC_COMP: diff --git a/drivers/net/ppp_mppe.c b/drivers/net/ppp_mppe.c new file mode 100644 index 00000000000..1985d1b57c4 --- /dev/null +++ b/drivers/net/ppp_mppe.c @@ -0,0 +1,724 @@ +/* + * ppp_mppe.c - interface MPPE to the PPP code. + * This version is for use with Linux kernel 2.6.14+ + * + * By Frank Cusack . + * Copyright (c) 2002,2003,2004 Google, Inc. + * All rights reserved. + * + * License: + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. + * + * ALTERNATIVELY, provided that this notice is retained in full, this product + * may be distributed under the terms of the GNU General Public License (GPL), + * in which case the provisions of the GPL apply INSTEAD OF those given above. + * + * 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 option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * Changelog: + * 08/12/05 - Matt Domsch + * Only need extra skb padding on transmit, not receive. + * 06/18/04 - Matt Domsch , Oleg Makarenko + * Use Linux kernel 2.6 arc4 and sha1 routines rather than + * providing our own. + * 2/15/04 - TS: added #include and testing for Kernel + * version before using + * MOD_DEC_USAGE_COUNT/MOD_INC_USAGE_COUNT which are + * deprecated in 2.6 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ppp_mppe.h" + +MODULE_AUTHOR("Frank Cusack "); +MODULE_DESCRIPTION("Point-to-Point Protocol Microsoft Point-to-Point Encryption support"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS("ppp-compress-" __stringify(CI_MPPE)); +MODULE_VERSION("1.0.2"); + +static void +setup_sg(struct scatterlist *sg, const void *address, unsigned int length) +{ + sg[0].page = virt_to_page(address); + sg[0].offset = offset_in_page(address); + sg[0].length = length; +} + +#define SHA1_PAD_SIZE 40 + +/* + * kernel crypto API needs its arguments to be in kmalloc'd memory, not in the module + * static data area. That means sha_pad needs to be kmalloc'd. + */ + +struct sha_pad { + unsigned char sha_pad1[SHA1_PAD_SIZE]; + unsigned char sha_pad2[SHA1_PAD_SIZE]; +}; +static struct sha_pad *sha_pad; + +static inline void sha_pad_init(struct sha_pad *shapad) +{ + memset(shapad->sha_pad1, 0x00, sizeof(shapad->sha_pad1)); + memset(shapad->sha_pad2, 0xF2, sizeof(shapad->sha_pad2)); +} + +/* + * State for an MPPE (de)compressor. + */ +struct ppp_mppe_state { + struct crypto_tfm *arc4; + struct crypto_tfm *sha1; + unsigned char *sha1_digest; + unsigned char master_key[MPPE_MAX_KEY_LEN]; + unsigned char session_key[MPPE_MAX_KEY_LEN]; + unsigned keylen; /* key length in bytes */ + /* NB: 128-bit == 16, 40-bit == 8! */ + /* If we want to support 56-bit, */ + /* the unit has to change to bits */ + unsigned char bits; /* MPPE control bits */ + unsigned ccount; /* 12-bit coherency count (seqno) */ + unsigned stateful; /* stateful mode flag */ + int discard; /* stateful mode packet loss flag */ + int sanity_errors; /* take down LCP if too many */ + int unit; + int debug; + struct compstat stats; +}; + +/* struct ppp_mppe_state.bits definitions */ +#define MPPE_BIT_A 0x80 /* Encryption table were (re)inititalized */ +#define MPPE_BIT_B 0x40 /* MPPC only (not implemented) */ +#define MPPE_BIT_C 0x20 /* MPPC only (not implemented) */ +#define MPPE_BIT_D 0x10 /* This is an encrypted frame */ + +#define MPPE_BIT_FLUSHED MPPE_BIT_A +#define MPPE_BIT_ENCRYPTED MPPE_BIT_D + +#define MPPE_BITS(p) ((p)[4] & 0xf0) +#define MPPE_CCOUNT(p) ((((p)[4] & 0x0f) << 8) + (p)[5]) +#define MPPE_CCOUNT_SPACE 0x1000 /* The size of the ccount space */ + +#define MPPE_OVHD 2 /* MPPE overhead/packet */ +#define SANITY_MAX 1600 /* Max bogon factor we will tolerate */ + +/* + * Key Derivation, from RFC 3078, RFC 3079. + * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079. + */ +static void get_new_key_from_sha(struct ppp_mppe_state * state, unsigned char *InterimKey) +{ + struct scatterlist sg[4]; + + setup_sg(&sg[0], state->master_key, state->keylen); + setup_sg(&sg[1], sha_pad->sha_pad1, sizeof(sha_pad->sha_pad1)); + setup_sg(&sg[2], state->session_key, state->keylen); + setup_sg(&sg[3], sha_pad->sha_pad2, sizeof(sha_pad->sha_pad2)); + + crypto_digest_digest (state->sha1, sg, 4, state->sha1_digest); + + memcpy(InterimKey, state->sha1_digest, state->keylen); +} + +/* + * Perform the MPPE rekey algorithm, from RFC 3078, sec. 7.3. + * Well, not what's written there, but rather what they meant. + */ +static void mppe_rekey(struct ppp_mppe_state * state, int initial_key) +{ + unsigned char InterimKey[MPPE_MAX_KEY_LEN]; + struct scatterlist sg_in[1], sg_out[1]; + + get_new_key_from_sha(state, InterimKey); + if (!initial_key) { + crypto_cipher_setkey(state->arc4, InterimKey, state->keylen); + setup_sg(sg_in, InterimKey, state->keylen); + setup_sg(sg_out, state->session_key, state->keylen); + if (crypto_cipher_encrypt(state->arc4, sg_out, sg_in, + state->keylen) != 0) { + printk(KERN_WARNING "mppe_rekey: cipher_encrypt failed\n"); + } + } else { + memcpy(state->session_key, InterimKey, state->keylen); + } + if (state->keylen == 8) { + /* See RFC 3078 */ + state->session_key[0] = 0xd1; + state->session_key[1] = 0x26; + state->session_key[2] = 0x9e; + } + crypto_cipher_setkey(state->arc4, state->session_key, state->keylen); +} + +/* + * Allocate space for a (de)compressor. + */ +static void *mppe_alloc(unsigned char *options, int optlen) +{ + struct ppp_mppe_state *state; + unsigned int digestsize; + + if (optlen != CILEN_MPPE + sizeof(state->master_key) + || options[0] != CI_MPPE || options[1] != CILEN_MPPE) + goto out; + + state = (struct ppp_mppe_state *) kmalloc(sizeof(*state), GFP_KERNEL); + if (state == NULL) + goto out; + + memset(state, 0, sizeof(*state)); + + state->arc4 = crypto_alloc_tfm("arc4", 0); + if (!state->arc4) + goto out_free; + + state->sha1 = crypto_alloc_tfm("sha1", 0); + if (!state->sha1) + goto out_free; + + digestsize = crypto_tfm_alg_digestsize(state->sha1); + if (digestsize < MPPE_MAX_KEY_LEN) + goto out_free; + + state->sha1_digest = kmalloc(digestsize, GFP_KERNEL); + if (!state->sha1_digest) + goto out_free; + + /* Save keys. */ + memcpy(state->master_key, &options[CILEN_MPPE], + sizeof(state->master_key)); + memcpy(state->session_key, state->master_key, + sizeof(state->master_key)); + + /* + * We defer initial key generation until mppe_init(), as mppe_alloc() + * is called frequently during negotiation. + */ + + return (void *)state; + + out_free: + if (state->sha1_digest) + kfree(state->sha1_digest); + if (state->sha1) + crypto_free_tfm(state->sha1); + if (state->arc4) + crypto_free_tfm(state->arc4); + kfree(state); + out: + return NULL; +} + +/* + * Deallocate space for a (de)compressor. + */ +static void mppe_free(void *arg) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + if (state) { + if (state->sha1_digest) + kfree(state->sha1_digest); + if (state->sha1) + crypto_free_tfm(state->sha1); + if (state->arc4) + crypto_free_tfm(state->arc4); + kfree(state); + } +} + +/* + * Initialize (de)compressor state. + */ +static int +mppe_init(void *arg, unsigned char *options, int optlen, int unit, int debug, + const char *debugstr) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + unsigned char mppe_opts; + + if (optlen != CILEN_MPPE + || options[0] != CI_MPPE || options[1] != CILEN_MPPE) + return 0; + + MPPE_CI_TO_OPTS(&options[2], mppe_opts); + if (mppe_opts & MPPE_OPT_128) + state->keylen = 16; + else if (mppe_opts & MPPE_OPT_40) + state->keylen = 8; + else { + printk(KERN_WARNING "%s[%d]: unknown key length\n", debugstr, + unit); + return 0; + } + if (mppe_opts & MPPE_OPT_STATEFUL) + state->stateful = 1; + + /* Generate the initial session key. */ + mppe_rekey(state, 1); + + if (debug) { + int i; + char mkey[sizeof(state->master_key) * 2 + 1]; + char skey[sizeof(state->session_key) * 2 + 1]; + + printk(KERN_DEBUG "%s[%d]: initialized with %d-bit %s mode\n", + debugstr, unit, (state->keylen == 16) ? 128 : 40, + (state->stateful) ? "stateful" : "stateless"); + + for (i = 0; i < sizeof(state->master_key); i++) + sprintf(mkey + i * 2, "%02x", state->master_key[i]); + for (i = 0; i < sizeof(state->session_key); i++) + sprintf(skey + i * 2, "%02x", state->session_key[i]); + printk(KERN_DEBUG + "%s[%d]: keys: master: %s initial session: %s\n", + debugstr, unit, mkey, skey); + } + + /* + * Initialize the coherency count. The initial value is not specified + * in RFC 3078, but we can make a reasonable assumption that it will + * start at 0. Setting it to the max here makes the comp/decomp code + * do the right thing (determined through experiment). + */ + state->ccount = MPPE_CCOUNT_SPACE - 1; + + /* + * Note that even though we have initialized the key table, we don't + * set the FLUSHED bit. This is contrary to RFC 3078, sec. 3.1. + */ + state->bits = MPPE_BIT_ENCRYPTED; + + state->unit = unit; + state->debug = debug; + + return 1; +} + +static int +mppe_comp_init(void *arg, unsigned char *options, int optlen, int unit, + int hdrlen, int debug) +{ + /* ARGSUSED */ + return mppe_init(arg, options, optlen, unit, debug, "mppe_comp_init"); +} + +/* + * We received a CCP Reset-Request (actually, we are sending a Reset-Ack), + * tell the compressor to rekey. Note that we MUST NOT rekey for + * every CCP Reset-Request; we only rekey on the next xmit packet. + * We might get multiple CCP Reset-Requests if our CCP Reset-Ack is lost. + * So, rekeying for every CCP Reset-Request is broken as the peer will not + * know how many times we've rekeyed. (If we rekey and THEN get another + * CCP Reset-Request, we must rekey again.) + */ +static void mppe_comp_reset(void *arg) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + + state->bits |= MPPE_BIT_FLUSHED; +} + +/* + * Compress (encrypt) a packet. + * It's strange to call this a compressor, since the output is always + * MPPE_OVHD + 2 bytes larger than the input. + */ +static int +mppe_compress(void *arg, unsigned char *ibuf, unsigned char *obuf, + int isize, int osize) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + int proto; + struct scatterlist sg_in[1], sg_out[1]; + + /* + * Check that the protocol is in the range we handle. + */ + proto = PPP_PROTOCOL(ibuf); + if (proto < 0x0021 || proto > 0x00fa) + return 0; + + /* Make sure we have enough room to generate an encrypted packet. */ + if (osize < isize + MPPE_OVHD + 2) { + /* Drop the packet if we should encrypt it, but can't. */ + printk(KERN_DEBUG "mppe_compress[%d]: osize too small! " + "(have: %d need: %d)\n", state->unit, + osize, osize + MPPE_OVHD + 2); + return -1; + } + + osize = isize + MPPE_OVHD + 2; + + /* + * Copy over the PPP header and set control bits. + */ + obuf[0] = PPP_ADDRESS(ibuf); + obuf[1] = PPP_CONTROL(ibuf); + obuf[2] = PPP_COMP >> 8; /* isize + MPPE_OVHD + 1 */ + obuf[3] = PPP_COMP; /* isize + MPPE_OVHD + 2 */ + obuf += PPP_HDRLEN; + + state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; + if (state->debug >= 7) + printk(KERN_DEBUG "mppe_compress[%d]: ccount %d\n", state->unit, + state->ccount); + obuf[0] = state->ccount >> 8; + obuf[1] = state->ccount & 0xff; + + if (!state->stateful || /* stateless mode */ + ((state->ccount & 0xff) == 0xff) || /* "flag" packet */ + (state->bits & MPPE_BIT_FLUSHED)) { /* CCP Reset-Request */ + /* We must rekey */ + if (state->debug && state->stateful) + printk(KERN_DEBUG "mppe_compress[%d]: rekeying\n", + state->unit); + mppe_rekey(state, 0); + state->bits |= MPPE_BIT_FLUSHED; + } + obuf[0] |= state->bits; + state->bits &= ~MPPE_BIT_FLUSHED; /* reset for next xmit */ + + obuf += MPPE_OVHD; + ibuf += 2; /* skip to proto field */ + isize -= 2; + + /* Encrypt packet */ + setup_sg(sg_in, ibuf, isize); + setup_sg(sg_out, obuf, osize); + if (crypto_cipher_encrypt(state->arc4, sg_out, sg_in, isize) != 0) { + printk(KERN_DEBUG "crypto_cypher_encrypt failed\n"); + return -1; + } + + state->stats.unc_bytes += isize; + state->stats.unc_packets++; + state->stats.comp_bytes += osize; + state->stats.comp_packets++; + + return osize; +} + +/* + * Since every frame grows by MPPE_OVHD + 2 bytes, this is always going + * to look bad ... and the longer the link is up the worse it will get. + */ +static void mppe_comp_stats(void *arg, struct compstat *stats) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + + *stats = state->stats; +} + +static int +mppe_decomp_init(void *arg, unsigned char *options, int optlen, int unit, + int hdrlen, int mru, int debug) +{ + /* ARGSUSED */ + return mppe_init(arg, options, optlen, unit, debug, "mppe_decomp_init"); +} + +/* + * We received a CCP Reset-Ack. Just ignore it. + */ +static void mppe_decomp_reset(void *arg) +{ + /* ARGSUSED */ + return; +} + +/* + * Decompress (decrypt) an MPPE packet. + */ +static int +mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf, + int osize) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + unsigned ccount; + int flushed = MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED; + int sanity = 0; + struct scatterlist sg_in[1], sg_out[1]; + + if (isize <= PPP_HDRLEN + MPPE_OVHD) { + if (state->debug) + printk(KERN_DEBUG + "mppe_decompress[%d]: short pkt (%d)\n", + state->unit, isize); + return DECOMP_ERROR; + } + + /* + * Make sure we have enough room to decrypt the packet. + * Note that for our test we only subtract 1 byte whereas in + * mppe_compress() we added 2 bytes (+MPPE_OVHD); + * this is to account for possible PFC. + */ + if (osize < isize - MPPE_OVHD - 1) { + printk(KERN_DEBUG "mppe_decompress[%d]: osize too small! " + "(have: %d need: %d)\n", state->unit, + osize, isize - MPPE_OVHD - 1); + return DECOMP_ERROR; + } + osize = isize - MPPE_OVHD - 2; /* assume no PFC */ + + ccount = MPPE_CCOUNT(ibuf); + if (state->debug >= 7) + printk(KERN_DEBUG "mppe_decompress[%d]: ccount %d\n", + state->unit, ccount); + + /* sanity checks -- terminate with extreme prejudice */ + if (!(MPPE_BITS(ibuf) & MPPE_BIT_ENCRYPTED)) { + printk(KERN_DEBUG + "mppe_decompress[%d]: ENCRYPTED bit not set!\n", + state->unit); + state->sanity_errors += 100; + sanity = 1; + } + if (!state->stateful && !flushed) { + printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set in " + "stateless mode!\n", state->unit); + state->sanity_errors += 100; + sanity = 1; + } + if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) { + printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set on " + "flag packet!\n", state->unit); + state->sanity_errors += 100; + sanity = 1; + } + + if (sanity) { + if (state->sanity_errors < SANITY_MAX) + return DECOMP_ERROR; + else + /* + * Take LCP down if the peer is sending too many bogons. + * We don't want to do this for a single or just a few + * instances since it could just be due to packet corruption. + */ + return DECOMP_FATALERROR; + } + + /* + * Check the coherency count. + */ + + if (!state->stateful) { + /* RFC 3078, sec 8.1. Rekey for every packet. */ + while (state->ccount != ccount) { + mppe_rekey(state, 0); + state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; + } + } else { + /* RFC 3078, sec 8.2. */ + if (!state->discard) { + /* normal state */ + state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; + if (ccount != state->ccount) { + /* + * (ccount > state->ccount) + * Packet loss detected, enter the discard state. + * Signal the peer to rekey (by sending a CCP Reset-Request). + */ + state->discard = 1; + return DECOMP_ERROR; + } + } else { + /* discard state */ + if (!flushed) { + /* ccp.c will be silent (no additional CCP Reset-Requests). */ + return DECOMP_ERROR; + } else { + /* Rekey for every missed "flag" packet. */ + while ((ccount & ~0xff) != + (state->ccount & ~0xff)) { + mppe_rekey(state, 0); + state->ccount = + (state->ccount + + 256) % MPPE_CCOUNT_SPACE; + } + + /* reset */ + state->discard = 0; + state->ccount = ccount; + /* + * Another problem with RFC 3078 here. It implies that the + * peer need not send a Reset-Ack packet. But RFC 1962 + * requires it. Hopefully, M$ does send a Reset-Ack; even + * though it isn't required for MPPE synchronization, it is + * required to reset CCP state. + */ + } + } + if (flushed) + mppe_rekey(state, 0); + } + + /* + * Fill in the first part of the PPP header. The protocol field + * comes from the decrypted data. + */ + obuf[0] = PPP_ADDRESS(ibuf); /* +1 */ + obuf[1] = PPP_CONTROL(ibuf); /* +1 */ + obuf += 2; + ibuf += PPP_HDRLEN + MPPE_OVHD; + isize -= PPP_HDRLEN + MPPE_OVHD; /* -6 */ + /* net osize: isize-4 */ + + /* + * Decrypt the first byte in order to check if it is + * a compressed or uncompressed protocol field. + */ + setup_sg(sg_in, ibuf, 1); + setup_sg(sg_out, obuf, 1); + if (crypto_cipher_decrypt(state->arc4, sg_out, sg_in, 1) != 0) { + printk(KERN_DEBUG "crypto_cypher_decrypt failed\n"); + return DECOMP_ERROR; + } + + /* + * Do PFC decompression. + * This would be nicer if we were given the actual sk_buff + * instead of a char *. + */ + if ((obuf[0] & 0x01) != 0) { + obuf[1] = obuf[0]; + obuf[0] = 0; + obuf++; + osize++; + } + + /* And finally, decrypt the rest of the packet. */ + setup_sg(sg_in, ibuf + 1, isize - 1); + setup_sg(sg_out, obuf + 1, osize - 1); + if (crypto_cipher_decrypt(state->arc4, sg_out, sg_in, isize - 1) != 0) { + printk(KERN_DEBUG "crypto_cypher_decrypt failed\n"); + return DECOMP_ERROR; + } + + state->stats.unc_bytes += osize; + state->stats.unc_packets++; + state->stats.comp_bytes += isize; + state->stats.comp_packets++; + + /* good packet credit */ + state->sanity_errors >>= 1; + + return osize; +} + +/* + * Incompressible data has arrived (this should never happen!). + * We should probably drop the link if the protocol is in the range + * of what should be encrypted. At the least, we should drop this + * packet. (How to do this?) + */ +static void mppe_incomp(void *arg, unsigned char *ibuf, int icnt) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + + if (state->debug && + (PPP_PROTOCOL(ibuf) >= 0x0021 && PPP_PROTOCOL(ibuf) <= 0x00fa)) + printk(KERN_DEBUG + "mppe_incomp[%d]: incompressible (unencrypted) data! " + "(proto %04x)\n", state->unit, PPP_PROTOCOL(ibuf)); + + state->stats.inc_bytes += icnt; + state->stats.inc_packets++; + state->stats.unc_bytes += icnt; + state->stats.unc_packets++; +} + +/************************************************************* + * Module interface table + *************************************************************/ + +/* + * Procedures exported to if_ppp.c. + */ +static struct compressor ppp_mppe = { + .compress_proto = CI_MPPE, + .comp_alloc = mppe_alloc, + .comp_free = mppe_free, + .comp_init = mppe_comp_init, + .comp_reset = mppe_comp_reset, + .compress = mppe_compress, + .comp_stat = mppe_comp_stats, + .decomp_alloc = mppe_alloc, + .decomp_free = mppe_free, + .decomp_init = mppe_decomp_init, + .decomp_reset = mppe_decomp_reset, + .decompress = mppe_decompress, + .incomp = mppe_incomp, + .decomp_stat = mppe_comp_stats, + .owner = THIS_MODULE, + .comp_extra = MPPE_PAD, +}; + +/* + * ppp_mppe_init() + * + * Prior to allowing load, try to load the arc4 and sha1 crypto + * libraries. The actual use will be allocated later, but + * this way the module will fail to insmod if they aren't available. + */ + +static int __init ppp_mppe_init(void) +{ + int answer; + if (!(crypto_alg_available("arc4", 0) && + crypto_alg_available("sha1", 0))) + return -ENODEV; + + sha_pad = kmalloc(sizeof(struct sha_pad), GFP_KERNEL); + if (!sha_pad) + return -ENOMEM; + sha_pad_init(sha_pad); + + answer = ppp_register_compressor(&ppp_mppe); + + if (answer == 0) + printk(KERN_INFO "PPP MPPE Compression module registered\n"); + else + kfree(sha_pad); + + return answer; +} + +static void __exit ppp_mppe_cleanup(void) +{ + ppp_unregister_compressor(&ppp_mppe); + kfree(sha_pad); +} + +module_init(ppp_mppe_init); +module_exit(ppp_mppe_cleanup); diff --git a/drivers/net/ppp_mppe.h b/drivers/net/ppp_mppe.h new file mode 100644 index 00000000000..7a14e058c66 --- /dev/null +++ b/drivers/net/ppp_mppe.h @@ -0,0 +1,86 @@ +#define MPPE_PAD 4 /* MPPE growth per frame */ +#define MPPE_MAX_KEY_LEN 16 /* largest key length (128-bit) */ + +/* option bits for ccp_options.mppe */ +#define MPPE_OPT_40 0x01 /* 40 bit */ +#define MPPE_OPT_128 0x02 /* 128 bit */ +#define MPPE_OPT_STATEFUL 0x04 /* stateful mode */ +/* unsupported opts */ +#define MPPE_OPT_56 0x08 /* 56 bit */ +#define MPPE_OPT_MPPC 0x10 /* MPPC compression */ +#define MPPE_OPT_D 0x20 /* Unknown */ +#define MPPE_OPT_UNSUPPORTED (MPPE_OPT_56|MPPE_OPT_MPPC|MPPE_OPT_D) +#define MPPE_OPT_UNKNOWN 0x40 /* Bits !defined in RFC 3078 were set */ + +/* + * This is not nice ... the alternative is a bitfield struct though. + * And unfortunately, we cannot share the same bits for the option + * names above since C and H are the same bit. We could do a u_int32 + * but then we have to do a htonl() all the time and/or we still need + * to know which octet is which. + */ +#define MPPE_C_BIT 0x01 /* MPPC */ +#define MPPE_D_BIT 0x10 /* Obsolete, usage unknown */ +#define MPPE_L_BIT 0x20 /* 40-bit */ +#define MPPE_S_BIT 0x40 /* 128-bit */ +#define MPPE_M_BIT 0x80 /* 56-bit, not supported */ +#define MPPE_H_BIT 0x01 /* Stateless (in a different byte) */ + +/* Does not include H bit; used for least significant octet only. */ +#define MPPE_ALL_BITS (MPPE_D_BIT|MPPE_L_BIT|MPPE_S_BIT|MPPE_M_BIT|MPPE_H_BIT) + +/* Build a CI from mppe opts (see RFC 3078) */ +#define MPPE_OPTS_TO_CI(opts, ci) \ + do { \ + u_char *ptr = ci; /* u_char[4] */ \ + \ + /* H bit */ \ + if (opts & MPPE_OPT_STATEFUL) \ + *ptr++ = 0x0; \ + else \ + *ptr++ = MPPE_H_BIT; \ + *ptr++ = 0; \ + *ptr++ = 0; \ + \ + /* S,L bits */ \ + *ptr = 0; \ + if (opts & MPPE_OPT_128) \ + *ptr |= MPPE_S_BIT; \ + if (opts & MPPE_OPT_40) \ + *ptr |= MPPE_L_BIT; \ + /* M,D,C bits not supported */ \ + } while (/* CONSTCOND */ 0) + +/* The reverse of the above */ +#define MPPE_CI_TO_OPTS(ci, opts) \ + do { \ + u_char *ptr = ci; /* u_char[4] */ \ + \ + opts = 0; \ + \ + /* H bit */ \ + if (!(ptr[0] & MPPE_H_BIT)) \ + opts |= MPPE_OPT_STATEFUL; \ + \ + /* S,L bits */ \ + if (ptr[3] & MPPE_S_BIT) \ + opts |= MPPE_OPT_128; \ + if (ptr[3] & MPPE_L_BIT) \ + opts |= MPPE_OPT_40; \ + \ + /* M,D,C bits */ \ + if (ptr[3] & MPPE_M_BIT) \ + opts |= MPPE_OPT_56; \ + if (ptr[3] & MPPE_D_BIT) \ + opts |= MPPE_OPT_D; \ + if (ptr[3] & MPPE_C_BIT) \ + opts |= MPPE_OPT_MPPC; \ + \ + /* Other bits */ \ + if (ptr[0] & ~MPPE_H_BIT) \ + opts |= MPPE_OPT_UNKNOWN; \ + if (ptr[1] || ptr[2]) \ + opts |= MPPE_OPT_UNKNOWN; \ + if (ptr[3] & ~MPPE_ALL_BITS) \ + opts |= MPPE_OPT_UNKNOWN; \ + } while (/* CONSTCOND */ 0) diff --git a/include/linux/if_ppp.h b/include/linux/if_ppp.h index 572aff7daa2..768372f07ca 100644 --- a/include/linux/if_ppp.h +++ b/include/linux/if_ppp.h @@ -21,7 +21,7 @@ */ /* - * ==FILEVERSION 20000724== + * ==FILEVERSION 20050812== * * NOTE TO MAINTAINERS: * If you modify this file at all, please set the above date. @@ -35,6 +35,8 @@ #ifndef _IF_PPP_H_ #define _IF_PPP_H_ +#include + /* * Packet sizes */ @@ -70,7 +72,8 @@ #define SC_LOG_RAWIN 0x00080000 /* log all chars received */ #define SC_LOG_FLUSH 0x00100000 /* log all chars flushed */ #define SC_SYNC 0x00200000 /* synchronous serial mode */ -#define SC_MASK 0x0f200fff /* bits that user can change */ +#define SC_MUST_COMP 0x00400000 /* no uncompressed packets may be sent or received */ +#define SC_MASK 0x0f600fff /* bits that user can change */ /* state bits */ #define SC_XMIT_BUSY 0x10000000 /* (used by isdn_ppp?) */ diff --git a/include/linux/ppp-comp.h b/include/linux/ppp-comp.h index 7227e653b3b..e86a7a5cf35 100644 --- a/include/linux/ppp-comp.h +++ b/include/linux/ppp-comp.h @@ -111,6 +111,8 @@ struct compressor { /* Used in locking compressor modules */ struct module *owner; + /* Extra skb space needed by the compressor algorithm */ + unsigned int comp_extra; }; /* @@ -190,6 +192,13 @@ struct compressor { #define DEFLATE_MAKE_OPT(w) ((((w) - 8) << 4) + DEFLATE_METHOD_VAL) #define DEFLATE_CHK_SEQUENCE 0 +/* + * Definitions for MPPE. + */ + +#define CI_MPPE 18 /* config option for MPPE */ +#define CILEN_MPPE 6 /* length of config option */ + /* * Definitions for other, as yet unsupported, compression methods. */ -- cgit v1.2.3 From ac7c98eca88a854755475fcfe1b2bf5f97f90d99 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 8 Nov 2005 09:41:13 -0800 Subject: [IRDA] donauboe: locking fix From: Andrew Morton Two missing unlocks, as noted by Ted Unangst Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/irda/donauboe.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c index 0282771b1cb..3137592d60c 100644 --- a/drivers/net/irda/donauboe.c +++ b/drivers/net/irda/donauboe.c @@ -1459,8 +1459,10 @@ toshoboe_net_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) */ IRDA_DEBUG (1, "%s(BANDWIDTH), %s, (%X/%ld\n", __FUNCTION__ ,dev->name, INB (OBOE_STATUS), irq->ifr_baudrate ); - if (!in_interrupt () && !capable (CAP_NET_ADMIN)) - return -EPERM; + if (!in_interrupt () && !capable (CAP_NET_ADMIN)) { + ret = -EPERM; + goto out; + } /* self->speed=irq->ifr_baudrate; */ /* toshoboe_setbaud(self); */ @@ -1470,8 +1472,10 @@ toshoboe_net_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) case SIOCSMEDIABUSY: /* Set media busy */ IRDA_DEBUG (1, "%s(MEDIABUSY), %s, (%X/%x)\n", __FUNCTION__ ,dev->name, INB (OBOE_STATUS), capable (CAP_NET_ADMIN) ); - if (!capable (CAP_NET_ADMIN)) - return -EPERM; + if (!capable (CAP_NET_ADMIN)) { + ret = -EPERM; + goto out; + } irda_device_set_media_busy (self->netdev, TRUE); break; case SIOCGRECEIVING: /* Check if we are receiving right now */ @@ -1483,7 +1487,7 @@ toshoboe_net_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) IRDA_DEBUG (1, "%s(?), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd); ret = -EOPNOTSUPP; } - +out: spin_unlock_irqrestore(&self->spinlock, flags); return ret; -- cgit v1.2.3 From a51482bde22f99c63fbbb57d5d46cc666384e379 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Tue, 8 Nov 2005 09:41:34 -0800 Subject: [NET]: kfree cleanup From: Jesper Juhl This is the net/ part of the big kfree cleanup patch. Remove pointless checks for NULL prior to calling kfree() in net/. Signed-off-by: Jesper Juhl Cc: "David S. Miller" Cc: Arnaldo Carvalho de Melo Acked-by: Marcel Holtmann Acked-by: YOSHIFUJI Hideaki Signed-off-by: Andrew Morton --- net/802/p8023.c | 3 +-- net/ax25/af_ax25.c | 6 ++---- net/ax25/ax25_in.c | 6 ++---- net/ax25/ax25_route.c | 19 ++++++------------- net/bluetooth/hidp/core.c | 4 +--- net/core/dev_mcast.c | 3 +-- net/core/sock.c | 3 +-- net/dccp/ipv4.c | 6 ++---- net/dccp/proto.c | 3 +-- net/decnet/dn_table.c | 14 ++++++-------- net/ethernet/pe2.c | 3 +-- net/ipv4/af_inet.c | 3 +-- net/ipv4/fib_frontend.c | 3 +-- net/ipv4/ip_options.c | 3 +-- net/ipv4/ip_output.c | 12 ++++-------- net/ipv4/ip_sockglue.c | 12 ++++-------- net/ipv4/ipvs/ip_vs_app.c | 6 ++---- net/ipv4/multipath_wrandom.c | 10 +++------- net/ipv4/netfilter/ip_nat_snmp_basic.c | 3 +-- net/ipv4/tcp_ipv4.c | 3 +-- net/ipv6/addrconf.c | 3 +-- net/ipv6/ip6_output.c | 15 +++++---------- net/ipv6/ip6_tunnel.c | 6 ++---- net/ipv6/ipcomp6.c | 3 +-- net/ipv6/ipv6_sockglue.c | 3 +-- net/irda/discovery.c | 3 +-- net/irda/irias_object.c | 16 ++++++---------- net/rose/rose_route.c | 6 ++---- net/sched/cls_fw.c | 3 +-- net/sched/cls_route.c | 3 +-- net/sched/cls_rsvp.h | 3 +-- net/sched/cls_tcindex.c | 9 +++------ net/sched/cls_u32.c | 4 ++-- net/sched/em_meta.c | 3 +-- net/sctp/associola.c | 4 +--- net/sctp/sm_make_chunk.c | 6 ++---- net/sunrpc/auth_gss/gss_krb5_seal.c | 2 +- net/sunrpc/auth_gss/gss_krb5_unseal.c | 2 +- net/sunrpc/auth_gss/gss_mech_switch.c | 3 +-- net/sunrpc/auth_gss/gss_spkm3_seal.c | 3 +-- net/sunrpc/auth_gss/gss_spkm3_token.c | 3 +-- net/sunrpc/auth_gss/gss_spkm3_unseal.c | 6 ++---- net/sunrpc/svc.c | 9 +++------ net/sunrpc/xdr.c | 3 +-- net/wanrouter/af_wanpipe.c | 20 +++++++------------- net/wanrouter/wanmain.c | 12 ++++-------- net/xfrm/xfrm_state.c | 12 ++++-------- 47 files changed, 99 insertions(+), 191 deletions(-) diff --git a/net/802/p8023.c b/net/802/p8023.c index 6368d3dce44..d23e906456e 100644 --- a/net/802/p8023.c +++ b/net/802/p8023.c @@ -54,8 +54,7 @@ struct datalink_proto *make_8023_client(void) */ void destroy_8023_client(struct datalink_proto *dl) { - if (dl) - kfree(dl); + kfree(dl); } EXPORT_SYMBOL(destroy_8023_client); diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 8e37e71e34f..1b683f30265 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1138,10 +1138,8 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, sk->sk_state = TCP_CLOSE; sock->state = SS_UNCONNECTED; - if (ax25->digipeat != NULL) { - kfree(ax25->digipeat); - ax25->digipeat = NULL; - } + kfree(ax25->digipeat); + ax25->digipeat = NULL; /* * Handle digi-peaters to be used. diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c index 73cfc3411c4..4cf87540fb3 100644 --- a/net/ax25/ax25_in.c +++ b/net/ax25/ax25_in.c @@ -401,10 +401,8 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev, } if (dp.ndigi == 0) { - if (ax25->digipeat != NULL) { - kfree(ax25->digipeat); - ax25->digipeat = NULL; - } + kfree(ax25->digipeat); + ax25->digipeat = NULL; } else { /* Reverse the source SABM's path */ memcpy(ax25->digipeat, &reverse_dp, sizeof(ax25_digi)); diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c index 26b77d97222..b1e945bd6ed 100644 --- a/net/ax25/ax25_route.c +++ b/net/ax25/ax25_route.c @@ -54,15 +54,13 @@ void ax25_rt_device_down(struct net_device *dev) if (s->dev == dev) { if (ax25_route_list == s) { ax25_route_list = s->next; - if (s->digipeat != NULL) - kfree(s->digipeat); + kfree(s->digipeat); kfree(s); } else { for (t = ax25_route_list; t != NULL; t = t->next) { if (t->next == s) { t->next = s->next; - if (s->digipeat != NULL) - kfree(s->digipeat); + kfree(s->digipeat); kfree(s); break; } @@ -90,10 +88,8 @@ static int ax25_rt_add(struct ax25_routes_struct *route) while (ax25_rt != NULL) { if (ax25cmp(&ax25_rt->callsign, &route->dest_addr) == 0 && ax25_rt->dev == ax25_dev->dev) { - if (ax25_rt->digipeat != NULL) { - kfree(ax25_rt->digipeat); - ax25_rt->digipeat = NULL; - } + kfree(ax25_rt->digipeat); + ax25_rt->digipeat = NULL; if (route->digi_count != 0) { if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) { write_unlock(&ax25_route_lock); @@ -145,8 +141,7 @@ static int ax25_rt_add(struct ax25_routes_struct *route) static void ax25_rt_destroy(ax25_route *ax25_rt) { if (atomic_read(&ax25_rt->ref) == 0) { - if (ax25_rt->digipeat != NULL) - kfree(ax25_rt->digipeat); + kfree(ax25_rt->digipeat); kfree(ax25_rt); return; } @@ -530,9 +525,7 @@ void __exit ax25_rt_free(void) s = ax25_rt; ax25_rt = ax25_rt->next; - if (s->digipeat != NULL) - kfree(s->digipeat); - + kfree(s->digipeat); kfree(s); } write_unlock(&ax25_route_lock); diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 860444a7fc0..cdb9cfafd96 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -660,9 +660,7 @@ unlink: failed: up_write(&hidp_session_sem); - if (session->input) - kfree(session->input); - + kfree(session->input); kfree(session); return err; } diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c index db098ff3cd6..cb530eef0e3 100644 --- a/net/core/dev_mcast.c +++ b/net/core/dev_mcast.c @@ -194,8 +194,7 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) done: spin_unlock_bh(&dev->xmit_lock); - if (dmi1) - kfree(dmi1); + kfree(dmi1); return err; } diff --git a/net/core/sock.c b/net/core/sock.c index 9602ceb3bac..13cc3be4f05 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1242,8 +1242,7 @@ static void sock_def_write_space(struct sock *sk) static void sock_def_destruct(struct sock *sk) { - if (sk->sk_protinfo) - kfree(sk->sk_protinfo); + kfree(sk->sk_protinfo); } void sk_send_sigurg(struct sock *sk) diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 4b9bc81ae1a..ca03521112c 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -1263,10 +1263,8 @@ static int dccp_v4_destroy_sock(struct sock *sk) if (inet_csk(sk)->icsk_bind_hash != NULL) inet_put_port(&dccp_hashinfo, sk); - if (dp->dccps_service_list != NULL) { - kfree(dp->dccps_service_list); - dp->dccps_service_list = NULL; - } + kfree(dp->dccps_service_list); + dp->dccps_service_list = NULL; ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk); ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk); diff --git a/net/dccp/proto.c b/net/dccp/proto.c index a021c3422f6..e0ace7cbb99 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -238,8 +238,7 @@ static int dccp_setsockopt_service(struct sock *sk, const u32 service, lock_sock(sk); dp->dccps_service = service; - if (dp->dccps_service_list != NULL) - kfree(dp->dccps_service_list); + kfree(dp->dccps_service_list); dp->dccps_service_list = sl; release_sock(sk); diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c index eeba56f9932..6f8b5658cb4 100644 --- a/net/decnet/dn_table.c +++ b/net/decnet/dn_table.c @@ -784,16 +784,14 @@ struct dn_fib_table *dn_fib_get_table(int n, int create) static void dn_fib_del_tree(int n) { - struct dn_fib_table *t; + struct dn_fib_table *t; - write_lock(&dn_fib_tables_lock); - t = dn_fib_tables[n]; - dn_fib_tables[n] = NULL; - write_unlock(&dn_fib_tables_lock); + write_lock(&dn_fib_tables_lock); + t = dn_fib_tables[n]; + dn_fib_tables[n] = NULL; + write_unlock(&dn_fib_tables_lock); - if (t) { - kfree(t); - } + kfree(t); } struct dn_fib_table *dn_fib_empty_table(void) diff --git a/net/ethernet/pe2.c b/net/ethernet/pe2.c index 98a494be603..9d57b4fb644 100644 --- a/net/ethernet/pe2.c +++ b/net/ethernet/pe2.c @@ -32,8 +32,7 @@ struct datalink_proto *make_EII_client(void) void destroy_EII_client(struct datalink_proto *dl) { - if (dl) - kfree(dl); + kfree(dl); } EXPORT_SYMBOL(destroy_EII_client); diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index a9d84f93442..eaa150c33b0 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -147,8 +147,7 @@ void inet_sock_destruct(struct sock *sk) BUG_TRAP(!sk->sk_wmem_queued); BUG_TRAP(!sk->sk_forward_alloc); - if (inet->opt) - kfree(inet->opt); + kfree(inet->opt); dst_release(sk->sk_dst_cache); sk_refcnt_debug_dec(sk); } diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 990633c09df..2267c1fad87 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -266,8 +266,7 @@ int ip_rt_ioctl(unsigned int cmd, void __user *arg) if (tb) err = tb->tb_insert(tb, &req.rtm, &rta, &req.nlh, NULL); } - if (rta.rta_mx) - kfree(rta.rta_mx); + kfree(rta.rta_mx); } rtnl_unlock(); return err; diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index bce4e875193..dbe12da8d8b 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -510,8 +510,7 @@ static int ip_options_get_finish(struct ip_options **optp, kfree(opt); return -EINVAL; } - if (*optp) - kfree(*optp); + kfree(*optp); *optp = opt; return 0; } diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 17758234a3e..df7f20da422 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1262,10 +1262,8 @@ int ip_push_pending_frames(struct sock *sk) out: inet->cork.flags &= ~IPCORK_OPT; - if (inet->cork.opt) { - kfree(inet->cork.opt); - inet->cork.opt = NULL; - } + kfree(inet->cork.opt); + inet->cork.opt = NULL; if (inet->cork.rt) { ip_rt_put(inet->cork.rt); inet->cork.rt = NULL; @@ -1289,10 +1287,8 @@ void ip_flush_pending_frames(struct sock *sk) kfree_skb(skb); inet->cork.flags &= ~IPCORK_OPT; - if (inet->cork.opt) { - kfree(inet->cork.opt); - inet->cork.opt = NULL; - } + kfree(inet->cork.opt); + inet->cork.opt = NULL; if (inet->cork.rt) { ip_rt_put(inet->cork.rt); inet->cork.rt = NULL; diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 2f0b47da5b3..4f2d8725730 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -202,8 +202,7 @@ int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct s if (ra->sk == sk) { if (on) { write_unlock_bh(&ip_ra_lock); - if (new_ra) - kfree(new_ra); + kfree(new_ra); return -EADDRINUSE; } *rap = ra->next; @@ -446,8 +445,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, #endif } opt = xchg(&inet->opt, opt); - if (opt) - kfree(opt); + kfree(opt); break; } case IP_PKTINFO: @@ -828,10 +826,8 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, err = ip_mc_msfilter(sk, msf, ifindex); mc_msf_out: - if (msf) - kfree(msf); - if (gsf) - kfree(gsf); + kfree(msf); + kfree(gsf); break; } case IP_ROUTER_ALERT: diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c index fc6f95aaa96..d7eb680101c 100644 --- a/net/ipv4/ipvs/ip_vs_app.c +++ b/net/ipv4/ipvs/ip_vs_app.c @@ -110,8 +110,7 @@ ip_vs_app_inc_new(struct ip_vs_app *app, __u16 proto, __u16 port) return 0; out: - if (inc->timeout_table) - kfree(inc->timeout_table); + kfree(inc->timeout_table); kfree(inc); return ret; } @@ -136,8 +135,7 @@ ip_vs_app_inc_release(struct ip_vs_app *inc) list_del(&inc->a_list); - if (inc->timeout_table != NULL) - kfree(inc->timeout_table); + kfree(inc->timeout_table); kfree(inc); } diff --git a/net/ipv4/multipath_wrandom.c b/net/ipv4/multipath_wrandom.c index bd7d75b6abe..d34a9fa608e 100644 --- a/net/ipv4/multipath_wrandom.c +++ b/net/ipv4/multipath_wrandom.c @@ -207,16 +207,12 @@ static void wrandom_select_route(const struct flowi *flp, decision = mpc->rt; last_power = mpc->power; - if (last_mpc) - kfree(last_mpc); - + kfree(last_mpc); last_mpc = mpc; } - if (last_mpc) { - /* concurrent __multipath_flush may lead to !last_mpc */ - kfree(last_mpc); - } + /* concurrent __multipath_flush may lead to !last_mpc */ + kfree(last_mpc); decision->u.dst.__use++; *rp = decision; diff --git a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c index 93b2c5111bb..8acb7ed40b4 100644 --- a/net/ipv4/netfilter/ip_nat_snmp_basic.c +++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c @@ -1161,8 +1161,7 @@ static int snmp_parse_mangle(unsigned char *msg, if (!snmp_object_decode(&ctx, obj)) { if (*obj) { - if ((*obj)->id) - kfree((*obj)->id); + kfree((*obj)->id); kfree(*obj); } kfree(obj); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 49d67cd75ed..634dabb558f 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -823,8 +823,7 @@ out: */ static void tcp_v4_reqsk_destructor(struct request_sock *req) { - if (inet_rsk(req)->opt) - kfree(inet_rsk(req)->opt); + kfree(inet_rsk(req)->opt); } static inline void syn_flood_warning(struct sk_buff *skb) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index a34d1504deb..b7a5f51238b 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3090,8 +3090,7 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, nlmsg_failure: rtattr_failure: - if (array) - kfree(array); + kfree(array); skb_trim(skb, b - skb->data); return -1; } diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 614296a920c..dbd9767b32e 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -587,8 +587,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) skb->next = NULL; } - if (tmp_hdr) - kfree(tmp_hdr); + kfree(tmp_hdr); if (err == 0) { IP6_INC_STATS(IPSTATS_MIB_FRAGOKS); @@ -1186,10 +1185,8 @@ int ip6_push_pending_frames(struct sock *sk) out: inet->cork.flags &= ~IPCORK_OPT; - if (np->cork.opt) { - kfree(np->cork.opt); - np->cork.opt = NULL; - } + kfree(np->cork.opt); + np->cork.opt = NULL; if (np->cork.rt) { dst_release(&np->cork.rt->u.dst); np->cork.rt = NULL; @@ -1214,10 +1211,8 @@ void ip6_flush_pending_frames(struct sock *sk) inet->cork.flags &= ~IPCORK_OPT; - if (np->cork.opt) { - kfree(np->cork.opt); - np->cork.opt = NULL; - } + kfree(np->cork.opt); + np->cork.opt = NULL; if (np->cork.rt) { dst_release(&np->cork.rt->u.dst); np->cork.rt = NULL; diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index cf94372d1af..e6b0e3954c0 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -756,8 +756,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) } ip6_tnl_dst_store(t, dst); - if (opt) - kfree(opt); + kfree(opt); t->recursion--; return 0; @@ -766,8 +765,7 @@ tx_err_link_failure: dst_link_failure(skb); tx_err_dst_release: dst_release(dst); - if (opt) - kfree(opt); + kfree(opt); tx_err: stats->tx_errors++; stats->tx_dropped++; diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 85bfbc69b2c..55917fb1709 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -130,8 +130,7 @@ static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, s out_put_cpu: put_cpu(); out: - if (tmp_hdr) - kfree(tmp_hdr); + kfree(tmp_hdr); if (err) goto error_out; return nexthdr; diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 8567873d0dd..003fd99ff59 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -80,8 +80,7 @@ int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *)) if (ra->sk == sk) { if (sel>=0) { write_unlock_bh(&ip6_ra_lock); - if (new_ra) - kfree(new_ra); + kfree(new_ra); return -EADDRINUSE; } diff --git a/net/irda/discovery.c b/net/irda/discovery.c index c4ba5fa1446..3fefc822c1c 100644 --- a/net/irda/discovery.c +++ b/net/irda/discovery.c @@ -194,8 +194,7 @@ void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force) /* Remove it from the log */ curr = hashbin_remove_this(log, (irda_queue_t *) curr); - if (curr) - kfree(curr); + kfree(curr); } } diff --git a/net/irda/irias_object.c b/net/irda/irias_object.c index 6fec428b451..75f2666e863 100644 --- a/net/irda/irias_object.c +++ b/net/irda/irias_object.c @@ -122,8 +122,7 @@ static void __irias_delete_attrib(struct ias_attrib *attrib) IRDA_ASSERT(attrib != NULL, return;); IRDA_ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return;); - if (attrib->name) - kfree(attrib->name); + kfree(attrib->name); irias_delete_value(attrib->value); attrib->magic = ~IAS_ATTRIB_MAGIC; @@ -136,8 +135,7 @@ void __irias_delete_object(struct ias_object *obj) IRDA_ASSERT(obj != NULL, return;); IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;); - if (obj->name) - kfree(obj->name); + kfree(obj->name); hashbin_delete(obj->attribs, (FREE_FUNC) __irias_delete_attrib); @@ -562,14 +560,12 @@ void irias_delete_value(struct ias_value *value) /* No need to deallocate */ break; case IAS_STRING: - /* If string, deallocate string */ - if (value->t.string != NULL) - kfree(value->t.string); + /* Deallocate string */ + kfree(value->t.string); break; case IAS_OCT_SEQ: - /* If byte stream, deallocate byte stream */ - if (value->t.oct_seq != NULL) - kfree(value->t.oct_seq); + /* Deallocate byte stream */ + kfree(value->t.oct_seq); break; default: IRDA_DEBUG(0, "%s(), Unknown value type!\n", __FUNCTION__); diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index b18fe504301..8631b65a731 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c @@ -240,8 +240,7 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh) if ((s = rose_neigh_list) == rose_neigh) { rose_neigh_list = rose_neigh->next; spin_unlock_bh(&rose_neigh_list_lock); - if (rose_neigh->digipeat != NULL) - kfree(rose_neigh->digipeat); + kfree(rose_neigh->digipeat); kfree(rose_neigh); return; } @@ -250,8 +249,7 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh) if (s->next == rose_neigh) { s->next = rose_neigh->next; spin_unlock_bh(&rose_neigh_list_lock); - if (rose_neigh->digipeat != NULL) - kfree(rose_neigh->digipeat); + kfree(rose_neigh->digipeat); kfree(rose_neigh); return; } diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c index 29d8b9a4d16..75470486e40 100644 --- a/net/sched/cls_fw.c +++ b/net/sched/cls_fw.c @@ -298,8 +298,7 @@ static int fw_change(struct tcf_proto *tp, unsigned long base, return 0; errout: - if (f) - kfree(f); + kfree(f); return err; } diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c index 02996ac05c7..520ff716dab 100644 --- a/net/sched/cls_route.c +++ b/net/sched/cls_route.c @@ -525,8 +525,7 @@ reinsert: return 0; errout: - if (f) - kfree(f); + kfree(f); return err; } diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h index 006168d6937..572f06be3b0 100644 --- a/net/sched/cls_rsvp.h +++ b/net/sched/cls_rsvp.h @@ -555,8 +555,7 @@ insert: goto insert; errout: - if (f) - kfree(f); + kfree(f); errout2: tcf_exts_destroy(tp, &e); return err; diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index 404d9d83a7f..9f921174c8a 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c @@ -194,8 +194,7 @@ found: } tcf_unbind_filter(tp, &r->res); tcf_exts_destroy(tp, &r->exts); - if (f) - kfree(f); + kfree(f); return 0; } @@ -442,10 +441,8 @@ static void tcindex_destroy(struct tcf_proto *tp) walker.skip = 0; walker.fn = &tcindex_destroy_element; tcindex_walk(tp,&walker); - if (p->perfect) - kfree(p->perfect); - if (p->h) - kfree(p->h); + kfree(p->perfect); + kfree(p->h); kfree(p); tp->root = NULL; } diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 364b87d8645..2b670479dde 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -347,7 +347,7 @@ static int u32_destroy_key(struct tcf_proto *tp, struct tc_u_knode *n) if (n->ht_down) n->ht_down->refcnt--; #ifdef CONFIG_CLS_U32_PERF - if (n && (NULL != n->pf)) + if (n) kfree(n->pf); #endif kfree(n); @@ -680,7 +680,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle, return 0; } #ifdef CONFIG_CLS_U32_PERF - if (n && (NULL != n->pf)) + if (n) kfree(n->pf); #endif kfree(n); diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index cf68a59fdc5..700844d49d7 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c @@ -561,8 +561,7 @@ static int meta_var_change(struct meta_value *dst, struct rtattr *rta) static void meta_var_destroy(struct meta_value *v) { - if (v->val) - kfree((void *) v->val); + kfree((void *) v->val); } static void meta_var_apply_extras(struct meta_value *v, diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 12b0f582a66..8c8ddf7f9b6 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -344,9 +344,7 @@ void sctp_association_free(struct sctp_association *asoc) } /* Free peer's cached cookie. */ - if (asoc->peer.cookie) { - kfree(asoc->peer.cookie); - } + kfree(asoc->peer.cookie); /* Release the transport structures. */ list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 660c61bdf16..f9573eba5c7 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -254,8 +254,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, aiparam.adaption_ind = htonl(sp->adaption_ind); sctp_addto_chunk(retval, sizeof(aiparam), &aiparam); nodata: - if (addrs.v) - kfree(addrs.v); + kfree(addrs.v); return retval; } @@ -347,8 +346,7 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, nomem_chunk: kfree(cookie); nomem_cookie: - if (addrs.v) - kfree(addrs.v); + kfree(addrs.v); return retval; } diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c index 13f8ae97945..d0dfdfd5e79 100644 --- a/net/sunrpc/auth_gss/gss_krb5_seal.c +++ b/net/sunrpc/auth_gss/gss_krb5_seal.c @@ -143,6 +143,6 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text, return ((ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE); out_err: - if (md5cksum.data) kfree(md5cksum.data); + kfree(md5cksum.data); return GSS_S_FAILURE; } diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c index 2030475d98e..db055fd7d77 100644 --- a/net/sunrpc/auth_gss/gss_krb5_unseal.c +++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c @@ -176,6 +176,6 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx, ret = GSS_S_COMPLETE; out: - if (md5cksum.data) kfree(md5cksum.data); + kfree(md5cksum.data); return ret; } diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c index b048bf672da..f8bac6ccd52 100644 --- a/net/sunrpc/auth_gss/gss_mech_switch.c +++ b/net/sunrpc/auth_gss/gss_mech_switch.c @@ -60,8 +60,7 @@ gss_mech_free(struct gss_api_mech *gm) for (i = 0; i < gm->gm_pf_num; i++) { pf = &gm->gm_pfs[i]; - if (pf->auth_domain_name) - kfree(pf->auth_domain_name); + kfree(pf->auth_domain_name); pf->auth_domain_name = NULL; } } diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c index 148201e929d..d1e12b25d6e 100644 --- a/net/sunrpc/auth_gss/gss_spkm3_seal.c +++ b/net/sunrpc/auth_gss/gss_spkm3_seal.c @@ -122,8 +122,7 @@ spkm3_make_token(struct spkm3_ctx *ctx, return GSS_S_COMPLETE; out_err: - if (md5cksum.data) - kfree(md5cksum.data); + kfree(md5cksum.data); token->data = NULL; token->len = 0; return GSS_S_FAILURE; diff --git a/net/sunrpc/auth_gss/gss_spkm3_token.c b/net/sunrpc/auth_gss/gss_spkm3_token.c index 46c08a0710f..1f824578d77 100644 --- a/net/sunrpc/auth_gss/gss_spkm3_token.c +++ b/net/sunrpc/auth_gss/gss_spkm3_token.c @@ -259,8 +259,7 @@ spkm3_verify_mic_token(unsigned char **tokp, int *mic_hdrlen, unsigned char **ck ret = GSS_S_COMPLETE; out: - if (spkm3_ctx_id.data) - kfree(spkm3_ctx_id.data); + kfree(spkm3_ctx_id.data); return ret; } diff --git a/net/sunrpc/auth_gss/gss_spkm3_unseal.c b/net/sunrpc/auth_gss/gss_spkm3_unseal.c index c3c0d958610..241d5b30dfc 100644 --- a/net/sunrpc/auth_gss/gss_spkm3_unseal.c +++ b/net/sunrpc/auth_gss/gss_spkm3_unseal.c @@ -120,9 +120,7 @@ spkm3_read_token(struct spkm3_ctx *ctx, /* XXX: need to add expiration and sequencing */ ret = GSS_S_COMPLETE; out: - if (md5cksum.data) - kfree(md5cksum.data); - if (wire_cksum.data) - kfree(wire_cksum.data); + kfree(md5cksum.data); + kfree(wire_cksum.data); return ret; } diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 5a220b2bb37..e4296c8b861 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -196,12 +196,9 @@ svc_exit_thread(struct svc_rqst *rqstp) struct svc_serv *serv = rqstp->rq_server; svc_release_buffer(rqstp); - if (rqstp->rq_resp) - kfree(rqstp->rq_resp); - if (rqstp->rq_argp) - kfree(rqstp->rq_argp); - if (rqstp->rq_auth_data) - kfree(rqstp->rq_auth_data); + kfree(rqstp->rq_resp); + kfree(rqstp->rq_argp); + kfree(rqstp->rq_auth_data); kfree(rqstp); /* Release the server */ diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 32df43372ee..aaf08cdd19f 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -992,8 +992,7 @@ xdr_xcode_array2(struct xdr_buf *buf, unsigned int base, err = 0; out: - if (elem) - kfree(elem); + kfree(elem); if (ppages) kunmap(*ppages); return err; diff --git a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c index 596cb96e5f4..59fec59b213 100644 --- a/net/wanrouter/af_wanpipe.c +++ b/net/wanrouter/af_wanpipe.c @@ -1099,7 +1099,7 @@ static void release_driver(struct sock *sk) sock_reset_flag(sk, SOCK_ZAPPED); wp = wp_sk(sk); - if (wp && wp->mbox) { + if (wp) { kfree(wp->mbox); wp->mbox = NULL; } @@ -1186,10 +1186,8 @@ static void wanpipe_kill_sock_timer (unsigned long data) return; } - if (wp_sk(sk)) { - kfree(wp_sk(sk)); - wp_sk(sk) = NULL; - } + kfree(wp_sk(sk)); + wp_sk(sk) = NULL; if (atomic_read(&sk->sk_refcnt) != 1) { atomic_set(&sk->sk_refcnt, 1); @@ -1219,10 +1217,8 @@ static void wanpipe_kill_sock_accept (struct sock *sk) sk->sk_socket = NULL; - if (wp_sk(sk)) { - kfree(wp_sk(sk)); - wp_sk(sk) = NULL; - } + kfree(wp_sk(sk)); + wp_sk(sk) = NULL; if (atomic_read(&sk->sk_refcnt) != 1) { atomic_set(&sk->sk_refcnt, 1); @@ -1243,10 +1239,8 @@ static void wanpipe_kill_sock_irq (struct sock *sk) sk->sk_socket = NULL; - if (wp_sk(sk)) { - kfree(wp_sk(sk)); - wp_sk(sk) = NULL; - } + kfree(wp_sk(sk)); + wp_sk(sk) = NULL; if (atomic_read(&sk->sk_refcnt) != 1) { atomic_set(&sk->sk_refcnt, 1); diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c index 13b650ad22e..bcf7b3faa76 100644 --- a/net/wanrouter/wanmain.c +++ b/net/wanrouter/wanmain.c @@ -714,10 +714,8 @@ static int wanrouter_device_new_if(struct wan_device *wandev, } /* This code has moved from del_if() function */ - if (dev->priv) { - kfree(dev->priv); - dev->priv = NULL; - } + kfree(dev->priv); + dev->priv = NULL; #ifdef CONFIG_WANPIPE_MULTPPP if (cnf->config_id == WANCONFIG_MPPP) @@ -851,10 +849,8 @@ static int wanrouter_delete_interface(struct wan_device *wandev, char *name) /* Due to new interface linking method using dev->priv, * this code has moved from del_if() function.*/ - if (dev->priv){ - kfree(dev->priv); - dev->priv=NULL; - } + kfree(dev->priv); + dev->priv=NULL; unregister_netdev(dev); diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 8b9a4747417..7cf48aa6c95 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -62,14 +62,10 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) { if (del_timer(&x->timer)) BUG(); - if (x->aalg) - kfree(x->aalg); - if (x->ealg) - kfree(x->ealg); - if (x->calg) - kfree(x->calg); - if (x->encap) - kfree(x->encap); + kfree(x->aalg); + kfree(x->ealg); + kfree(x->calg); + kfree(x->encap); if (x->type) { x->type->destructor(x); xfrm_put_type(x->type); -- cgit v1.2.3 From 89f5f0aeed14ac7245f760b0b96c9269c87bcbbe Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 8 Nov 2005 09:41:56 -0800 Subject: [IPV4]: Fix ip_queue_xmit identity increment for TSO packets When ip_queue_xmit calls ip_select_ident_more for IP identity selection it gives it the wrong packet count for TSO packets. The ip_select_* functions expect one less than the number of packets, so we need to subtract one for TSO packets. This bug was diagnosed and fixed by Tom Young. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/ip_output.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index df7f20da422..11c2f68254f 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -353,7 +353,8 @@ packet_routed: ip_options_build(skb, opt, inet->daddr, rt, 0); } - ip_select_ident_more(iph, &rt->u.dst, sk, skb_shinfo(skb)->tso_segs); + ip_select_ident_more(iph, &rt->u.dst, sk, + (skb_shinfo(skb)->tso_segs ?: 1) - 1); /* Add an IP checksum. */ ip_send_check(iph); -- cgit v1.2.3 From 97835245768a638002722a36ba9a3b76d0910f68 Mon Sep 17 00:00:00 2001 From: Bob Picco Date: Sat, 29 Oct 2005 17:23:05 -0400 Subject: [IA64] fix memory less node allocation The original memory less node allocation attempted to use NODEDATA_ALIGN for alignment. The bootmem allocator only allows a power of two alignments. This causes a BUG_ON for some nodes. For cpu only nodes just allocate with a PERCPU_PAGE_SIZE alignment. Some older firmware reports SLIT distances of 0xff and results in bestnode not being computed. This is now treated correctly. The failed allocation check was removed because it's redundant. The bootmem allocator already makes this check. This fix has been boot tested on 4 node machine which has 4 cpu only nodes and 1 memory node. Thanks to Pete Keilty for reporting this and helping me test it. Signed-off-by: Bob Picco Signed-off-by: Tony Luck --- arch/ia64/mm/discontig.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index a88cdb7232f..0f776b032d3 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -350,14 +350,12 @@ static void __init initialize_pernode_data(void) * for best. * @nid: node id * @pernodesize: size of this node's pernode data - * @align: alignment to use for this node's pernode data */ -static void __init *memory_less_node_alloc(int nid, unsigned long pernodesize, - unsigned long align) +static void __init *memory_less_node_alloc(int nid, unsigned long pernodesize) { void *ptr = NULL; u8 best = 0xff; - int bestnode = -1, node; + int bestnode = -1, node, anynode = 0; for_each_online_node(node) { if (node_isset(node, memory_less_mask)) @@ -366,13 +364,15 @@ static void __init *memory_less_node_alloc(int nid, unsigned long pernodesize, best = node_distance(nid, node); bestnode = node; } + anynode = node; } - ptr = __alloc_bootmem_node(mem_data[bestnode].pgdat, - pernodesize, align, __pa(MAX_DMA_ADDRESS)); + if (bestnode == -1) + bestnode = anynode; + + ptr = __alloc_bootmem_node(mem_data[bestnode].pgdat, pernodesize, + PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS)); - if (!ptr) - panic("NO memory for memory less node\n"); return ptr; } @@ -413,8 +413,7 @@ static void __init memory_less_nodes(void) for_each_node_mask(node, memory_less_mask) { pernodesize = compute_pernodesize(node); - pernode = memory_less_node_alloc(node, pernodesize, - (node) ? (node * PERCPU_PAGE_SIZE) : (1024*1024)); + pernode = memory_less_node_alloc(node, pernodesize); fill_pernode(node, __pa(pernode), pernodesize); } -- cgit v1.2.3 From 7ef934b3b73f74aea23aa0e98affe86d7ea816a3 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 8 Nov 2005 09:57:05 -0800 Subject: [Bluetooth]: Add another ignore parameter to the HCI USB driver This patchs adds the module parameter ignore_dga to the HCI USB driver which makes it possible to prevent this driver from being loaded by some buggy Digianswer devices. Signed-off-by: Marcel Holtmann Signed-off-by: David S. Miller --- drivers/bluetooth/hci_usb.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c index f510b25b2c5..057cb2b6e6d 100644 --- a/drivers/bluetooth/hci_usb.c +++ b/drivers/bluetooth/hci_usb.c @@ -65,6 +65,7 @@ #endif static int ignore = 0; +static int ignore_dga = 0; static int ignore_csr = 0; static int ignore_sniffer = 0; static int reset = 0; @@ -841,6 +842,9 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id if (ignore || id->driver_info & HCI_IGNORE) return -ENODEV; + if (ignore_dga && id->driver_info & HCI_DIGIANSWER) + return -ENODEV; + if (ignore_csr && id->driver_info & HCI_CSR) return -ENODEV; @@ -1070,6 +1074,9 @@ module_exit(hci_usb_exit); module_param(ignore, bool, 0644); MODULE_PARM_DESC(ignore, "Ignore devices from the matching table"); +module_param(ignore_dga, bool, 0644); +MODULE_PARM_DESC(ignore_dga, "Ignore devices with id 08fd:0001"); + module_param(ignore_csr, bool, 0644); MODULE_PARM_DESC(ignore_csr, "Ignore devices with id 0a12:0001"); -- cgit v1.2.3 From 1ebb92521d0bc2d4ef772730d29333c06b807191 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 8 Nov 2005 09:57:21 -0800 Subject: [Bluetooth]: Add endian annotations to the core This patch adds the endian annotations to the Bluetooth core. Signed-off-by: Marcel Holtmann Signed-off-by: David S. Miller --- drivers/bluetooth/bpa10x.c | 4 +- include/net/bluetooth/hci.h | 116 +++++++++++++++++++-------------------- include/net/bluetooth/hci_core.h | 2 +- net/bluetooth/hci_core.c | 2 +- net/bluetooth/hci_event.c | 6 +- net/bluetooth/hci_sock.c | 2 +- 6 files changed, 66 insertions(+), 66 deletions(-) diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index ecbeb7eaba8..394796315ad 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c @@ -84,8 +84,8 @@ struct bpa10x_data { struct hci_vendor_hdr { __u8 type; - __u16 snum; - __u16 dlen; + __le16 snum; + __le16 dlen; } __attribute__ ((packed)); static void bpa10x_recv_bulk(struct bpa10x_data *data, unsigned char *buf, int count) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index fa2d12b0579..b06a2d2f63d 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -184,10 +184,10 @@ enum { struct hci_rp_read_loc_version { __u8 status; __u8 hci_ver; - __u16 hci_rev; + __le16 hci_rev; __u8 lmp_ver; - __u16 manufacturer; - __u16 lmp_subver; + __le16 manufacturer; + __le16 lmp_subver; } __attribute__ ((packed)); #define OCF_READ_LOCAL_FEATURES 0x0003 @@ -199,10 +199,10 @@ struct hci_rp_read_loc_features { #define OCF_READ_BUFFER_SIZE 0x0005 struct hci_rp_read_buffer_size { __u8 status; - __u16 acl_mtu; + __le16 acl_mtu; __u8 sco_mtu; - __u16 acl_max_pkt; - __u16 sco_max_pkt; + __le16 acl_max_pkt; + __le16 sco_max_pkt; } __attribute__ ((packed)); #define OCF_READ_BD_ADDR 0x0009 @@ -267,21 +267,21 @@ struct hci_cp_write_dev_class { #define OCF_READ_VOICE_SETTING 0x0025 struct hci_rp_read_voice_setting { - __u8 status; - __u16 voice_setting; + __u8 status; + __le16 voice_setting; } __attribute__ ((packed)); #define OCF_WRITE_VOICE_SETTING 0x0026 struct hci_cp_write_voice_setting { - __u16 voice_setting; + __le16 voice_setting; } __attribute__ ((packed)); #define OCF_HOST_BUFFER_SIZE 0x0033 struct hci_cp_host_buffer_size { - __u16 acl_mtu; + __le16 acl_mtu; __u8 sco_mtu; - __u16 acl_max_pkt; - __u16 sco_max_pkt; + __le16 acl_max_pkt; + __le16 sco_max_pkt; } __attribute__ ((packed)); /* Link Control */ @@ -289,10 +289,10 @@ struct hci_cp_host_buffer_size { #define OCF_CREATE_CONN 0x0005 struct hci_cp_create_conn { bdaddr_t bdaddr; - __u16 pkt_type; + __le16 pkt_type; __u8 pscan_rep_mode; __u8 pscan_mode; - __u16 clock_offset; + __le16 clock_offset; __u8 role_switch; } __attribute__ ((packed)); @@ -310,14 +310,14 @@ struct hci_cp_reject_conn_req { #define OCF_DISCONNECT 0x0006 struct hci_cp_disconnect { - __u16 handle; + __le16 handle; __u8 reason; } __attribute__ ((packed)); #define OCF_ADD_SCO 0x0007 struct hci_cp_add_sco { - __u16 handle; - __u16 pkt_type; + __le16 handle; + __le16 pkt_type; } __attribute__ ((packed)); #define OCF_INQUIRY 0x0001 @@ -354,56 +354,56 @@ struct hci_cp_pin_code_neg_reply { #define OCF_CHANGE_CONN_PTYPE 0x000F struct hci_cp_change_conn_ptype { - __u16 handle; - __u16 pkt_type; + __le16 handle; + __le16 pkt_type; } __attribute__ ((packed)); #define OCF_AUTH_REQUESTED 0x0011 struct hci_cp_auth_requested { - __u16 handle; + __le16 handle; } __attribute__ ((packed)); #define OCF_SET_CONN_ENCRYPT 0x0013 struct hci_cp_set_conn_encrypt { - __u16 handle; + __le16 handle; __u8 encrypt; } __attribute__ ((packed)); #define OCF_CHANGE_CONN_LINK_KEY 0x0015 struct hci_cp_change_conn_link_key { - __u16 handle; + __le16 handle; } __attribute__ ((packed)); #define OCF_READ_REMOTE_FEATURES 0x001B struct hci_cp_read_rmt_features { - __u16 handle; + __le16 handle; } __attribute__ ((packed)); #define OCF_READ_REMOTE_VERSION 0x001D struct hci_cp_read_rmt_version { - __u16 handle; + __le16 handle; } __attribute__ ((packed)); /* Link Policy */ #define OGF_LINK_POLICY 0x02 #define OCF_ROLE_DISCOVERY 0x0009 struct hci_cp_role_discovery { - __u16 handle; + __le16 handle; } __attribute__ ((packed)); struct hci_rp_role_discovery { __u8 status; - __u16 handle; + __le16 handle; __u8 role; } __attribute__ ((packed)); #define OCF_READ_LINK_POLICY 0x000C struct hci_cp_read_link_policy { - __u16 handle; + __le16 handle; } __attribute__ ((packed)); struct hci_rp_read_link_policy { __u8 status; - __u16 handle; - __u16 policy; + __le16 handle; + __le16 policy; } __attribute__ ((packed)); #define OCF_SWITCH_ROLE 0x000B @@ -414,12 +414,12 @@ struct hci_cp_switch_role { #define OCF_WRITE_LINK_POLICY 0x000D struct hci_cp_write_link_policy { - __u16 handle; - __u16 policy; + __le16 handle; + __le16 policy; } __attribute__ ((packed)); struct hci_rp_write_link_policy { __u8 status; - __u16 handle; + __le16 handle; } __attribute__ ((packed)); /* Status params */ @@ -441,7 +441,7 @@ struct inquiry_info { __u8 pscan_period_mode; __u8 pscan_mode; __u8 dev_class[3]; - __u16 clock_offset; + __le16 clock_offset; } __attribute__ ((packed)); #define HCI_EV_INQUIRY_RESULT_WITH_RSSI 0x22 @@ -450,7 +450,7 @@ struct inquiry_info_with_rssi { __u8 pscan_rep_mode; __u8 pscan_period_mode; __u8 dev_class[3]; - __u16 clock_offset; + __le16 clock_offset; __s8 rssi; } __attribute__ ((packed)); struct inquiry_info_with_rssi_and_pscan_mode { @@ -459,7 +459,7 @@ struct inquiry_info_with_rssi_and_pscan_mode { __u8 pscan_period_mode; __u8 pscan_mode; __u8 dev_class[3]; - __u16 clock_offset; + __le16 clock_offset; __s8 rssi; } __attribute__ ((packed)); @@ -469,7 +469,7 @@ struct extended_inquiry_info { __u8 pscan_rep_mode; __u8 pscan_period_mode; __u8 dev_class[3]; - __u16 clock_offset; + __le16 clock_offset; __s8 rssi; __u8 data[240]; } __attribute__ ((packed)); @@ -477,7 +477,7 @@ struct extended_inquiry_info { #define HCI_EV_CONN_COMPLETE 0x03 struct hci_ev_conn_complete { __u8 status; - __u16 handle; + __le16 handle; bdaddr_t bdaddr; __u8 link_type; __u8 encr_mode; @@ -493,27 +493,27 @@ struct hci_ev_conn_request { #define HCI_EV_DISCONN_COMPLETE 0x05 struct hci_ev_disconn_complete { __u8 status; - __u16 handle; + __le16 handle; __u8 reason; } __attribute__ ((packed)); #define HCI_EV_AUTH_COMPLETE 0x06 struct hci_ev_auth_complete { __u8 status; - __u16 handle; + __le16 handle; } __attribute__ ((packed)); #define HCI_EV_ENCRYPT_CHANGE 0x08 struct hci_ev_encrypt_change { __u8 status; - __u16 handle; + __le16 handle; __u8 encrypt; } __attribute__ ((packed)); #define HCI_EV_CHANGE_CONN_LINK_KEY_COMPLETE 0x09 struct hci_ev_change_conn_link_key_complete { __u8 status; - __u16 handle; + __le16 handle; } __attribute__ ((packed)); #define HCI_EV_QOS_SETUP_COMPLETE 0x0D @@ -526,21 +526,21 @@ struct hci_qos { } __attribute__ ((packed)); struct hci_ev_qos_setup_complete { __u8 status; - __u16 handle; + __le16 handle; struct hci_qos qos; } __attribute__ ((packed)); #define HCI_EV_CMD_COMPLETE 0x0E struct hci_ev_cmd_complete { __u8 ncmd; - __u16 opcode; + __le16 opcode; } __attribute__ ((packed)); #define HCI_EV_CMD_STATUS 0x0F struct hci_ev_cmd_status { __u8 status; __u8 ncmd; - __u16 opcode; + __le16 opcode; } __attribute__ ((packed)); #define HCI_EV_NUM_COMP_PKTS 0x13 @@ -559,9 +559,9 @@ struct hci_ev_role_change { #define HCI_EV_MODE_CHANGE 0x14 struct hci_ev_mode_change { __u8 status; - __u16 handle; + __le16 handle; __u8 mode; - __u16 interval; + __le16 interval; } __attribute__ ((packed)); #define HCI_EV_PIN_CODE_REQ 0x16 @@ -584,24 +584,24 @@ struct hci_ev_link_key_notify { #define HCI_EV_RMT_FEATURES 0x0B struct hci_ev_rmt_features { __u8 status; - __u16 handle; + __le16 handle; __u8 features[8]; } __attribute__ ((packed)); #define HCI_EV_RMT_VERSION 0x0C struct hci_ev_rmt_version { __u8 status; - __u16 handle; + __le16 handle; __u8 lmp_ver; - __u16 manufacturer; - __u16 lmp_subver; + __le16 manufacturer; + __le16 lmp_subver; } __attribute__ ((packed)); #define HCI_EV_CLOCK_OFFSET 0x01C struct hci_ev_clock_offset { __u8 status; - __u16 handle; - __u16 clock_offset; + __le16 handle; + __le16 clock_offset; } __attribute__ ((packed)); #define HCI_EV_PSCAN_REP_MODE 0x20 @@ -638,7 +638,7 @@ struct hci_ev_si_security { #define HCI_SCO_HDR_SIZE 3 struct hci_command_hdr { - __u16 opcode; /* OCF & OGF */ + __le16 opcode; /* OCF & OGF */ __u8 plen; } __attribute__ ((packed)); @@ -648,22 +648,22 @@ struct hci_event_hdr { } __attribute__ ((packed)); struct hci_acl_hdr { - __u16 handle; /* Handle & Flags(PB, BC) */ - __u16 dlen; + __le16 handle; /* Handle & Flags(PB, BC) */ + __le16 dlen; } __attribute__ ((packed)); struct hci_sco_hdr { - __u16 handle; + __le16 handle; __u8 dlen; } __attribute__ ((packed)); /* Command opcode pack/unpack */ -#define hci_opcode_pack(ogf, ocf) (__u16)((ocf & 0x03ff)|(ogf << 10)) +#define hci_opcode_pack(ogf, ocf) (__u16) ((ocf & 0x03ff)|(ogf << 10)) #define hci_opcode_ogf(op) (op >> 10) #define hci_opcode_ocf(op) (op & 0x03ff) /* ACL handle and flags pack/unpack */ -#define hci_handle_pack(h, f) (__u16)((h & 0x0fff)|(f << 12)) +#define hci_handle_pack(h, f) (__u16) ((h & 0x0fff)|(f << 12)) #define hci_handle(h) (h & 0x0fff) #define hci_flags(h) (h >> 12) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 7f933f30207..adb94508259 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -44,7 +44,7 @@ struct inquiry_data { __u8 pscan_period_mode; __u8 pscan_mode; __u8 dev_class[3]; - __u16 clock_offset; + __le16 clock_offset; __s8 rssi; }; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index cf0df1c8c93..9106354c781 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -183,7 +183,7 @@ static void hci_reset_req(struct hci_dev *hdev, unsigned long opt) static void hci_init_req(struct hci_dev *hdev, unsigned long opt) { struct sk_buff *skb; - __u16 param; + __le16 param; BT_DBG("%s %ld", hdev->name, opt); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index b61b4e8e36f..eb64555d1fb 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -242,7 +242,7 @@ static void hci_cc_host_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb break; status = *((__u8 *) skb->data); - setting = __le16_to_cpu(get_unaligned((__u16 *) sent)); + setting = __le16_to_cpu(get_unaligned((__le16 *) sent)); if (!status && hdev->voice_setting != setting) { hdev->voice_setting = setting; @@ -728,7 +728,7 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_num_comp_pkts *ev = (struct hci_ev_num_comp_pkts *) skb->data; - __u16 *ptr; + __le16 *ptr; int i; skb_pull(skb, sizeof(*ev)); @@ -742,7 +742,7 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s tasklet_disable(&hdev->tx_task); - for (i = 0, ptr = (__u16 *) skb->data; i < ev->num_hndl; i++) { + for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) { struct hci_conn *conn; __u16 handle, count; diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 799e448750a..1d6d0a15c09 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -416,7 +416,7 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, skb->dev = (void *) hdev; if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) { - u16 opcode = __le16_to_cpu(get_unaligned((u16 *)skb->data)); + u16 opcode = __le16_to_cpu(get_unaligned((__le16 *) skb->data)); u16 ogf = hci_opcode_ogf(opcode); u16 ocf = hci_opcode_ocf(opcode); -- cgit v1.2.3 From be9d122730c878baafe11e70d1436faac229f2fc Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 8 Nov 2005 09:57:38 -0800 Subject: [Bluetooth]: Remove the usage of /proc completely This patch removes all relics of the /proc usage from the Bluetooth subsystem core and its upper layers. All the previous information are now available via /sys/class/bluetooth through appropriate functions. Signed-off-by: Marcel Holtmann Signed-off-by: David S. Miller --- include/net/bluetooth/bluetooth.h | 4 +- include/net/bluetooth/hci_core.h | 7 --- include/net/bluetooth/rfcomm.h | 2 - net/bluetooth/af_bluetooth.c | 12 +--- net/bluetooth/hci_sysfs.c | 4 +- net/bluetooth/l2cap.c | 98 +++++------------------------- net/bluetooth/rfcomm/core.c | 124 ++++++-------------------------------- net/bluetooth/rfcomm/sock.c | 90 ++++----------------------- net/bluetooth/sco.c | 92 ++++------------------------ 9 files changed, 65 insertions(+), 368 deletions(-) diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index e42d728b162..911ceb5cd26 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -57,8 +57,6 @@ #define BT_DBG(fmt, arg...) printk(KERN_INFO "%s: " fmt "\n" , __FUNCTION__ , ## arg) #define BT_ERR(fmt, arg...) printk(KERN_ERR "%s: " fmt "\n" , __FUNCTION__ , ## arg) -extern struct proc_dir_entry *proc_bt; - /* Connection and socket states */ enum { BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */ @@ -177,4 +175,6 @@ extern int hci_sock_cleanup(void); extern int bt_sysfs_init(void); extern void bt_sysfs_cleanup(void); +extern struct class bt_class; + #endif /* __BLUETOOTH_H */ diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index adb94508259..bb9f81dc872 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -25,7 +25,6 @@ #ifndef __HCI_CORE_H #define __HCI_CORE_H -#include #include /* HCI upper protocols */ @@ -34,8 +33,6 @@ #define HCI_INIT_TIMEOUT (HZ * 10) -extern struct proc_dir_entry *proc_bt_hci; - /* HCI Core structures */ struct inquiry_data { @@ -126,10 +123,6 @@ struct hci_dev { atomic_t promisc; -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *proc; -#endif - struct class_device class_dev; struct module *owner; diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h index e656be7c001..bbfac86734e 100644 --- a/include/net/bluetooth/rfcomm.h +++ b/include/net/bluetooth/rfcomm.h @@ -351,6 +351,4 @@ int rfcomm_dev_ioctl(struct sock *sk, unsigned int cmd, void __user *arg); int rfcomm_init_ttys(void); void rfcomm_cleanup_ttys(void); -extern struct proc_dir_entry *proc_bt_rfcomm; - #endif /* __RFCOMM_H */ diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 03532062a46..ea616e3fc98 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #if defined(CONFIG_KMOD) @@ -50,10 +49,7 @@ #define BT_DBG(D...) #endif -#define VERSION "2.7" - -struct proc_dir_entry *proc_bt; -EXPORT_SYMBOL(proc_bt); +#define VERSION "2.8" /* Bluetooth sockets */ #define BT_MAX_PROTO 8 @@ -312,10 +308,6 @@ static int __init bt_init(void) { BT_INFO("Core ver %s", VERSION); - proc_bt = proc_mkdir("bluetooth", NULL); - if (proc_bt) - proc_bt->owner = THIS_MODULE; - sock_register(&bt_sock_family_ops); BT_INFO("HCI device and connection manager initialized"); @@ -334,8 +326,6 @@ static void __exit bt_exit(void) bt_sysfs_cleanup(); sock_unregister(PF_BLUETOOTH); - - remove_proc_entry("bluetooth", NULL); } subsys_initcall(bt_init); diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 7856bc26acc..bd7568ac87f 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -103,7 +103,7 @@ static void bt_release(struct class_device *cdev) kfree(hdev); } -static struct class bt_class = { +struct class bt_class = { .name = "bluetooth", .release = bt_release, #ifdef CONFIG_HOTPLUG @@ -111,6 +111,8 @@ static struct class bt_class = { #endif }; +EXPORT_SYMBOL_GPL(bt_class); + int hci_register_sysfs(struct hci_dev *hdev) { struct class_device *cdev = &hdev->class_dev; diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 59b2dd36baa..e3bb11ca423 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -38,9 +38,8 @@ #include #include #include -#include -#include #include +#include #include #include @@ -56,7 +55,7 @@ #define BT_DBG(D...) #endif -#define VERSION "2.7" +#define VERSION "2.8" static struct proto_ops l2cap_sock_ops; @@ -2137,94 +2136,29 @@ drop: return 0; } -/* ---- Proc fs support ---- */ -#ifdef CONFIG_PROC_FS -static void *l2cap_seq_start(struct seq_file *seq, loff_t *pos) +static ssize_t l2cap_sysfs_show(struct class *dev, char *buf) { struct sock *sk; struct hlist_node *node; - loff_t l = *pos; + char *str = buf; read_lock_bh(&l2cap_sk_list.lock); - sk_for_each(sk, node, &l2cap_sk_list.head) - if (!l--) - goto found; - sk = NULL; -found: - return sk; -} + sk_for_each(sk, node, &l2cap_sk_list.head) { + struct l2cap_pinfo *pi = l2cap_pi(sk); -static void *l2cap_seq_next(struct seq_file *seq, void *e, loff_t *pos) -{ - (*pos)++; - return sk_next(e); -} + str += sprintf(str, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d 0x%x\n", + batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), + sk->sk_state, pi->psm, pi->scid, pi->dcid, pi->imtu, + pi->omtu, pi->link_mode); + } -static void l2cap_seq_stop(struct seq_file *seq, void *e) -{ read_unlock_bh(&l2cap_sk_list.lock); -} -static int l2cap_seq_show(struct seq_file *seq, void *e) -{ - struct sock *sk = e; - struct l2cap_pinfo *pi = l2cap_pi(sk); - - seq_printf(seq, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d 0x%x\n", - batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), - sk->sk_state, pi->psm, pi->scid, pi->dcid, pi->imtu, - pi->omtu, pi->link_mode); - return 0; + return (str - buf); } -static struct seq_operations l2cap_seq_ops = { - .start = l2cap_seq_start, - .next = l2cap_seq_next, - .stop = l2cap_seq_stop, - .show = l2cap_seq_show -}; - -static int l2cap_seq_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &l2cap_seq_ops); -} - -static struct file_operations l2cap_seq_fops = { - .owner = THIS_MODULE, - .open = l2cap_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static int __init l2cap_proc_init(void) -{ - struct proc_dir_entry *p = create_proc_entry("l2cap", S_IRUGO, proc_bt); - if (!p) - return -ENOMEM; - p->owner = THIS_MODULE; - p->proc_fops = &l2cap_seq_fops; - return 0; -} - -static void __exit l2cap_proc_cleanup(void) -{ - remove_proc_entry("l2cap", proc_bt); -} - -#else /* CONFIG_PROC_FS */ - -static int __init l2cap_proc_init(void) -{ - return 0; -} - -static void __exit l2cap_proc_cleanup(void) -{ - return; -} -#endif /* CONFIG_PROC_FS */ +static CLASS_ATTR(l2cap, S_IRUGO, l2cap_sysfs_show, NULL); static struct proto_ops l2cap_sock_ops = { .family = PF_BLUETOOTH, @@ -2266,7 +2200,7 @@ static struct hci_proto l2cap_hci_proto = { static int __init l2cap_init(void) { int err; - + err = proto_register(&l2cap_proto, 0); if (err < 0) return err; @@ -2284,7 +2218,7 @@ static int __init l2cap_init(void) goto error; } - l2cap_proc_init(); + class_create_file(&bt_class, &class_attr_l2cap); BT_INFO("L2CAP ver %s", VERSION); BT_INFO("L2CAP socket layer initialized"); @@ -2298,7 +2232,7 @@ error: static void __exit l2cap_exit(void) { - l2cap_proc_cleanup(); + class_remove_file(&bt_class, &class_attr_l2cap); if (bt_sock_unregister(BTPROTO_L2CAP) < 0) BT_ERR("L2CAP socket unregistration failed"); diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index c3d56ead840..0d89d643413 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -35,9 +35,8 @@ #include #include #include +#include #include -#include -#include #include #include #include @@ -47,17 +46,13 @@ #include #include -#define VERSION "1.5" +#define VERSION "1.6" #ifndef CONFIG_BT_RFCOMM_DEBUG #undef BT_DBG #define BT_DBG(D...) #endif -#ifdef CONFIG_PROC_FS -struct proc_dir_entry *proc_bt_rfcomm; -#endif - static struct task_struct *rfcomm_thread; static DECLARE_MUTEX(rfcomm_sem); @@ -2001,117 +1996,32 @@ static struct hci_cb rfcomm_cb = { .encrypt_cfm = rfcomm_encrypt_cfm }; -/* ---- Proc fs support ---- */ -#ifdef CONFIG_PROC_FS -static void *rfcomm_seq_start(struct seq_file *seq, loff_t *pos) +static ssize_t rfcomm_dlc_sysfs_show(struct class *dev, char *buf) { struct rfcomm_session *s; struct list_head *pp, *p; - loff_t l = *pos; + char *str = buf; rfcomm_lock(); list_for_each(p, &session_list) { s = list_entry(p, struct rfcomm_session, list); - list_for_each(pp, &s->dlcs) - if (!l--) { - seq->private = s; - return pp; - } - } - return NULL; -} + list_for_each(pp, &s->dlcs) { + struct sock *sk = s->sock->sk; + struct rfcomm_dlc *d = list_entry(pp, struct rfcomm_dlc, list); -static void *rfcomm_seq_next(struct seq_file *seq, void *e, loff_t *pos) -{ - struct rfcomm_session *s = seq->private; - struct list_head *pp, *p = e; - (*pos)++; - - if (p->next != &s->dlcs) - return p->next; - - list_for_each(p, &session_list) { - s = list_entry(p, struct rfcomm_session, list); - __list_for_each(pp, &s->dlcs) { - seq->private = s; - return pp; + str += sprintf(str, "%s %s %ld %d %d %d %d\n", + batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), + d->state, d->dlci, d->mtu, d->rx_credits, d->tx_credits); } } - return NULL; -} -static void rfcomm_seq_stop(struct seq_file *seq, void *e) -{ rfcomm_unlock(); -} - -static int rfcomm_seq_show(struct seq_file *seq, void *e) -{ - struct rfcomm_session *s = seq->private; - struct sock *sk = s->sock->sk; - struct rfcomm_dlc *d = list_entry(e, struct rfcomm_dlc, list); - - seq_printf(seq, "%s %s %ld %d %d %d %d\n", - batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), - d->state, d->dlci, d->mtu, d->rx_credits, d->tx_credits); - return 0; -} - -static struct seq_operations rfcomm_seq_ops = { - .start = rfcomm_seq_start, - .next = rfcomm_seq_next, - .stop = rfcomm_seq_stop, - .show = rfcomm_seq_show -}; - -static int rfcomm_seq_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &rfcomm_seq_ops); -} - -static struct file_operations rfcomm_seq_fops = { - .owner = THIS_MODULE, - .open = rfcomm_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static int __init rfcomm_proc_init(void) -{ - struct proc_dir_entry *p; - - proc_bt_rfcomm = proc_mkdir("rfcomm", proc_bt); - if (proc_bt_rfcomm) { - proc_bt_rfcomm->owner = THIS_MODULE; - - p = create_proc_entry("dlc", S_IRUGO, proc_bt_rfcomm); - if (p) - p->proc_fops = &rfcomm_seq_fops; - } - return 0; -} - -static void __exit rfcomm_proc_cleanup(void) -{ - remove_proc_entry("dlc", proc_bt_rfcomm); - remove_proc_entry("rfcomm", proc_bt); + return (str - buf); } -#else /* CONFIG_PROC_FS */ - -static int __init rfcomm_proc_init(void) -{ - return 0; -} - -static void __exit rfcomm_proc_cleanup(void) -{ - return; -} -#endif /* CONFIG_PROC_FS */ +static CLASS_ATTR(rfcomm_dlc, S_IRUGO, rfcomm_dlc_sysfs_show, NULL); /* ---- Initialization ---- */ static int __init rfcomm_init(void) @@ -2122,9 +2032,7 @@ static int __init rfcomm_init(void) kernel_thread(rfcomm_run, NULL, CLONE_KERNEL); - BT_INFO("RFCOMM ver %s", VERSION); - - rfcomm_proc_init(); + class_create_file(&bt_class, &class_attr_rfcomm_dlc); rfcomm_init_sockets(); @@ -2132,11 +2040,15 @@ static int __init rfcomm_init(void) rfcomm_init_ttys(); #endif + BT_INFO("RFCOMM ver %s", VERSION); + return 0; } static void __exit rfcomm_exit(void) { + class_remove_file(&bt_class, &class_attr_rfcomm_dlc); + hci_unregister_cb(&rfcomm_cb); /* Terminate working thread. @@ -2153,8 +2065,6 @@ static void __exit rfcomm_exit(void) #endif rfcomm_cleanup_sockets(); - - rfcomm_proc_cleanup(); } module_init(rfcomm_init); diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index a2b30f0aedb..6c34261b232 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -42,8 +42,7 @@ #include #include #include -#include -#include +#include #include #include @@ -887,89 +886,26 @@ done: return result; } -/* ---- Proc fs support ---- */ -#ifdef CONFIG_PROC_FS -static void *rfcomm_seq_start(struct seq_file *seq, loff_t *pos) +static ssize_t rfcomm_sock_sysfs_show(struct class *dev, char *buf) { struct sock *sk; struct hlist_node *node; - loff_t l = *pos; + char *str = buf; read_lock_bh(&rfcomm_sk_list.lock); - sk_for_each(sk, node, &rfcomm_sk_list.head) - if (!l--) - return sk; - return NULL; -} - -static void *rfcomm_seq_next(struct seq_file *seq, void *e, loff_t *pos) -{ - struct sock *sk = e; - (*pos)++; - return sk_next(sk); -} + sk_for_each(sk, node, &rfcomm_sk_list.head) { + str += sprintf(str, "%s %s %d %d\n", + batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), + sk->sk_state, rfcomm_pi(sk)->channel); + } -static void rfcomm_seq_stop(struct seq_file *seq, void *e) -{ read_unlock_bh(&rfcomm_sk_list.lock); -} -static int rfcomm_seq_show(struct seq_file *seq, void *e) -{ - struct sock *sk = e; - seq_printf(seq, "%s %s %d %d\n", - batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), - sk->sk_state, rfcomm_pi(sk)->channel); - return 0; -} - -static struct seq_operations rfcomm_seq_ops = { - .start = rfcomm_seq_start, - .next = rfcomm_seq_next, - .stop = rfcomm_seq_stop, - .show = rfcomm_seq_show -}; - -static int rfcomm_seq_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &rfcomm_seq_ops); + return (str - buf); } -static struct file_operations rfcomm_seq_fops = { - .owner = THIS_MODULE, - .open = rfcomm_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static int __init rfcomm_sock_proc_init(void) -{ - struct proc_dir_entry *p = create_proc_entry("sock", S_IRUGO, proc_bt_rfcomm); - if (!p) - return -ENOMEM; - p->proc_fops = &rfcomm_seq_fops; - return 0; -} - -static void __exit rfcomm_sock_proc_cleanup(void) -{ - remove_proc_entry("sock", proc_bt_rfcomm); -} - -#else /* CONFIG_PROC_FS */ - -static int __init rfcomm_sock_proc_init(void) -{ - return 0; -} - -static void __exit rfcomm_sock_proc_cleanup(void) -{ - return; -} -#endif /* CONFIG_PROC_FS */ +static CLASS_ATTR(rfcomm, S_IRUGO, rfcomm_sock_sysfs_show, NULL); static struct proto_ops rfcomm_sock_ops = { .family = PF_BLUETOOTH, @@ -997,7 +933,7 @@ static struct net_proto_family rfcomm_sock_family_ops = { .create = rfcomm_sock_create }; -int __init rfcomm_init_sockets(void) +int __init rfcomm_init_sockets(void) { int err; @@ -1009,7 +945,7 @@ int __init rfcomm_init_sockets(void) if (err < 0) goto error; - rfcomm_sock_proc_init(); + class_create_file(&bt_class, &class_attr_rfcomm); BT_INFO("RFCOMM socket layer initialized"); @@ -1023,7 +959,7 @@ error: void __exit rfcomm_cleanup_sockets(void) { - rfcomm_sock_proc_cleanup(); + class_remove_file(&bt_class, &class_attr_rfcomm); if (bt_sock_unregister(BTPROTO_RFCOMM) < 0) BT_ERR("RFCOMM socket layer unregistration failed"); diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 997e42df115..9cb00dc6c08 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -38,8 +38,7 @@ #include #include #include -#include -#include +#include #include #include @@ -55,7 +54,7 @@ #define BT_DBG(D...) #endif -#define VERSION "0.4" +#define VERSION "0.5" static struct proto_ops sco_sock_ops; @@ -893,91 +892,26 @@ drop: return 0; } -/* ---- Proc fs support ---- */ -#ifdef CONFIG_PROC_FS -static void *sco_seq_start(struct seq_file *seq, loff_t *pos) +static ssize_t sco_sysfs_show(struct class *dev, char *buf) { struct sock *sk; struct hlist_node *node; - loff_t l = *pos; + char *str = buf; read_lock_bh(&sco_sk_list.lock); - sk_for_each(sk, node, &sco_sk_list.head) - if (!l--) - goto found; - sk = NULL; -found: - return sk; -} - -static void *sco_seq_next(struct seq_file *seq, void *e, loff_t *pos) -{ - struct sock *sk = e; - (*pos)++; - return sk_next(sk); -} + sk_for_each(sk, node, &sco_sk_list.head) { + str += sprintf(str, "%s %s %d\n", + batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), + sk->sk_state); + } -static void sco_seq_stop(struct seq_file *seq, void *e) -{ read_unlock_bh(&sco_sk_list.lock); -} - -static int sco_seq_show(struct seq_file *seq, void *e) -{ - struct sock *sk = e; - seq_printf(seq, "%s %s %d\n", - batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), sk->sk_state); - return 0; -} -static struct seq_operations sco_seq_ops = { - .start = sco_seq_start, - .next = sco_seq_next, - .stop = sco_seq_stop, - .show = sco_seq_show -}; - -static int sco_seq_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &sco_seq_ops); + return (str - buf); } -static struct file_operations sco_seq_fops = { - .owner = THIS_MODULE, - .open = sco_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static int __init sco_proc_init(void) -{ - struct proc_dir_entry *p = create_proc_entry("sco", S_IRUGO, proc_bt); - if (!p) - return -ENOMEM; - p->owner = THIS_MODULE; - p->proc_fops = &sco_seq_fops; - return 0; -} - -static void __exit sco_proc_cleanup(void) -{ - remove_proc_entry("sco", proc_bt); -} - -#else /* CONFIG_PROC_FS */ - -static int __init sco_proc_init(void) -{ - return 0; -} - -static void __exit sco_proc_cleanup(void) -{ - return; -} -#endif /* CONFIG_PROC_FS */ +static CLASS_ATTR(sco, S_IRUGO, sco_sysfs_show, NULL); static struct proto_ops sco_sock_ops = { .family = PF_BLUETOOTH, @@ -1035,7 +969,7 @@ static int __init sco_init(void) goto error; } - sco_proc_init(); + class_create_file(&bt_class, &class_attr_sco); BT_INFO("SCO (Voice Link) ver %s", VERSION); BT_INFO("SCO socket layer initialized"); @@ -1049,7 +983,7 @@ error: static void __exit sco_exit(void) { - sco_proc_cleanup(); + class_remove_file(&bt_class, &class_attr_sco); if (bt_sock_unregister(BTPROTO_SCO) < 0) BT_ERR("SCO socket unregistration failed"); -- cgit v1.2.3 From cf20d1eafb648bf395b153cbcd0cde40f88c220a Mon Sep 17 00:00:00 2001 From: David Mosberger-Tang Date: Wed, 2 Nov 2005 22:40:19 -0800 Subject: [IA64] align signal-frame even when not using alternate signal-stack At the moment, attempting to invoke a signal-handler on the normal stack is guaranteed to fail if the stack-pointer happens not to be 16-byte aligned. This is because the signal-trampoline will attempt to store fp-regs with stf.spill instructions, which will trap for misaligned addresses. This isn't terribly useful behavior. It's better to just always align the signal frame to the next lower 16-byte boundary. Signed-off-by: David Mosberger-Tang Signed-off-by: Tony Luck --- arch/ia64/kernel/signal.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c index 774f34b675c..58ce07efc56 100644 --- a/arch/ia64/kernel/signal.c +++ b/arch/ia64/kernel/signal.c @@ -387,15 +387,14 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct sigscratch *scr) { extern char __kernel_sigtramp[]; - unsigned long tramp_addr, new_rbs = 0; + unsigned long tramp_addr, new_rbs = 0, new_sp; struct sigframe __user *frame; long err; - frame = (void __user *) scr->pt.r12; + new_sp = scr->pt.r12; tramp_addr = (unsigned long) __kernel_sigtramp; - if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags((unsigned long) frame) == 0) { - frame = (void __user *) ((current->sas_ss_sp + current->sas_ss_size) - & ~(STACK_ALIGN - 1)); + if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags(new_sp) == 0) { + new_sp = current->sas_ss_sp + current->sas_ss_size; /* * We need to check for the register stack being on the signal stack * separately, because it's switched separately (memory stack is switched @@ -404,7 +403,7 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, if (!rbs_on_sig_stack(scr->pt.ar_bspstore)) new_rbs = (current->sas_ss_sp + sizeof(long) - 1) & ~(sizeof(long) - 1); } - frame = (void __user *) frame - ((sizeof(*frame) + STACK_ALIGN - 1) & ~(STACK_ALIGN - 1)); + frame = (void __user *) ((new_sp - sizeof(*frame)) & -STACK_ALIGN); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return force_sigsegv_info(sig, frame); -- cgit v1.2.3 From d5a858bc148fe97996af9cf685cc124b70519adf Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 8 Nov 2005 10:00:13 -0800 Subject: [SPARC]: Missing compat_ioctl hookup in openprom driver. Signed-off-by: David S. Miller --- drivers/sbus/char/openprom.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c index 5028ac21432..383a95f34a0 100644 --- a/drivers/sbus/char/openprom.c +++ b/drivers/sbus/char/openprom.c @@ -596,6 +596,8 @@ static long openprom_compat_ioctl(struct file *file, unsigned int cmd, lock_kernel(); break; } + + return rval; } static int openprom_open(struct inode * inode, struct file * file) @@ -623,6 +625,7 @@ static struct file_operations openprom_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .ioctl = openprom_ioctl, + .compat_ioctl = openprom_compat_ioctl, .open = openprom_open, .release = openprom_release, }; -- cgit v1.2.3 From da1605465ebdb9dc25296a354394086cd559c243 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Tue, 8 Nov 2005 10:00:55 -0800 Subject: [SPARC64] mm: update get_user_insn comment Update comment on get_user_insn to the more general "pte lock", which may or may not be the page_table_lock. Note vmtruncate handled like kswapd. Signed-off-by: Hugh Dickins Signed-off-by: David S. Miller --- arch/sparc64/mm/fault.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index 31fbc67719a..3be278d916d 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c @@ -109,7 +109,7 @@ static void bad_kernel_pc(struct pt_regs *regs) * this. Additionally, to prevent kswapd from ripping ptes from * under us, raise interrupts around the time that we look at the * pte, kswapd will have to wait to get his smp ipi response from - * us. This saves us having to get page_table_lock. + * us. vmtruncate likewise. This saves us having to get pte lock. */ static unsigned int get_user_insn(unsigned long tpc) { -- cgit v1.2.3 From a14f25a076a8e5040d6f4e93f84034c81bcddbf7 Mon Sep 17 00:00:00 2001 From: Russ Anderson Date: Fri, 4 Nov 2005 13:39:38 -0600 Subject: [IA64] MCA recovery based on PSP bits The determination of whether an MCA is recoverable or not must be based on the bits set in the PSP (Processor State Parameter). The specific bits are shown in the Intel IA-64 Architecture Software Developer's Manual, Vol 2, Table 11-6 Software Recovery Bits in Processor State Parameter. Those bits should be consistent across the entire IA-64 family of processors. Signed-off-by: Russ Anderson Signed-off-by: Tony Luck --- arch/ia64/kernel/mca_drv.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c index f081c60ab20..eb860e29341 100644 --- a/arch/ia64/kernel/mca_drv.c +++ b/arch/ia64/kernel/mca_drv.c @@ -546,9 +546,20 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, (pal_processor_state_info_t*)peidx_psp(peidx); /* - * We cannot recover errors with other than bus_check. + * Processor recovery status must key off of the PAL recovery + * status in the Processor State Parameter. */ - if (psp->cc || psp->rc || psp->uc) + + /* + * The machine check is corrected. + */ + if (psp->cm == 1) + return 1; + + /* + * The error was not contained. Software must be reset. + */ + if (psp->us || psp->ci == 0) return 0; /* @@ -569,8 +580,6 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, return 0; if (pbci->eb && pbci->bsi > 0) return 0; - if (psp->ci == 0) - return 0; /* * This is a local MCA and estimated as recoverble external bus error. -- cgit v1.2.3 From 56f87b82171245a81a5dbac5e703d3941d80da49 Mon Sep 17 00:00:00 2001 From: Russ Anderson Date: Fri, 4 Nov 2005 13:57:00 -0600 Subject: [IA64] MCA recovery: pfn_valid() needs a pfn paddr needs to be shifted by PAGE_SHIFT to be valid input for pfn_valid(). Signed-off-by: Russ Anderson Signed-off-by: Tony Luck --- arch/ia64/kernel/mca_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c index f081c60ab20..6ff32d4faf8 100644 --- a/arch/ia64/kernel/mca_drv.c +++ b/arch/ia64/kernel/mca_drv.c @@ -88,7 +88,7 @@ mca_page_isolate(unsigned long paddr) if (!ia64_phys_addr_valid(paddr)) return ISOLATE_NONE; - if (!pfn_valid(paddr)) + if (!pfn_valid(paddr >> PAGE_SHIFT)) return ISOLATE_NONE; /* convert physical address to physical page number */ -- cgit v1.2.3 From cbb921443424fb8019e52bae83e442d01f7715ef Mon Sep 17 00:00:00 2001 From: Russ Anderson Date: Fri, 4 Nov 2005 16:58:28 -0600 Subject: [IA64] MCA recovery: Bump reference count on bad pages When a page has a memory uncorrectable ECC error, the recovery code wants to prevent the page from being reused. This change bumps the reference count to prevent the page from getting back on the free list. Signed-off-by: Russ Anderson (rja@sgi.com) Signed-off-by: Tony Luck --- arch/ia64/kernel/mca_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c index 6ff32d4faf8..eb39bc9c133 100644 --- a/arch/ia64/kernel/mca_drv.c +++ b/arch/ia64/kernel/mca_drv.c @@ -108,6 +108,7 @@ mca_page_isolate(unsigned long paddr) return ISOLATE_NG; /* add attribute 'Reserved' and register the page */ + get_page(p); SetPageReserved(p); page_isolate[num_page_isolate++] = p; -- cgit v1.2.3 From 6fb93a92ec2a012fa525499c330522bbb8c18d80 Mon Sep 17 00:00:00 2001 From: Mark Maule Date: Mon, 7 Nov 2005 15:48:50 -0600 Subject: [IA64] altix: misc pci interrupt related fixes Fix a couple of altix interrupt related bugs. Signed-off-by: Mark Maule Signed-off-by: Tony Luck --- arch/ia64/sn/pci/pcibr/pcibr_provider.c | 4 ++-- arch/ia64/sn/pci/pcibr/pcibr_reg.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c index 7b03b8084ff..1f500c81002 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c @@ -212,13 +212,13 @@ void pcibr_target_interrupt(struct sn_irq_info *sn_irq_info) pdi_pcibus_info; /* Disable the device's IRQ */ - pcireg_intr_enable_bit_clr(pcibus_info, bit); + pcireg_intr_enable_bit_clr(pcibus_info, (1 << bit)); /* Change the device's IRQ */ pcireg_intr_addr_addr_set(pcibus_info, bit, xtalk_addr); /* Re-enable the device's IRQ */ - pcireg_intr_enable_bit_set(pcibus_info, bit); + pcireg_intr_enable_bit_set(pcibus_info, (1 << bit)); pcibr_force_interrupt(sn_irq_info); } diff --git a/arch/ia64/sn/pci/pcibr/pcibr_reg.c b/arch/ia64/sn/pci/pcibr/pcibr_reg.c index 4f718c3e93d..5d534091262 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_reg.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_reg.c @@ -131,7 +131,7 @@ void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits) __sn_clrq_relaxed(&ptr->tio.cp_int_enable, bits); break; case PCIBR_BRIDGETYPE_PIC: - __sn_clrq_relaxed(&ptr->pic.p_int_enable, ~bits); + __sn_clrq_relaxed(&ptr->pic.p_int_enable, bits); break; default: panic -- cgit v1.2.3 From 4f41d5a4e665d05b4e74eef164469b7d81932ef1 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 7 Nov 2005 15:13:59 -0700 Subject: [IA64] add the MMIO regions that are translated to I/O port space to /proc/iomem ia64 translates normal loads and stores to special MMIO regions into I/O port accesses. Reserve these special MMIO regions in /proc/iomem. Sample /proc/iomem: f8100000000-f81003fffff : PCI Bus 0000:80 I/O Ports 00000000-00000fff f8100400000-f81007fffff : PCI Bus 0000:8e I/O Ports 00001000-00001fff f8100800000-f8100ffffff : PCI Bus 0000:9c I/O Ports 00002000-00003fff f8101000000-f81017fffff : PCI Bus 0000:aa I/O Ports 00004000-00005fff and corresponding /proc/ioports: 00000000-00000fff : PCI Bus 0000:80 00001000-00001fff : PCI Bus 0000:8e 00002000-00003fff : PCI Bus 0000:9c 00004000-00005fff : PCI Bus 0000:aa Signed-off-by: Bjorn Helgaas Signed-off-by: Tony Luck --- arch/ia64/pci/pci.c | 106 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 82 insertions(+), 24 deletions(-) diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 017cfc3f478..20d76fae24e 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -95,7 +95,7 @@ pci_sal_write (unsigned int seg, unsigned int bus, unsigned int devfn, } static struct pci_raw_ops pci_sal_ops = { - .read = pci_sal_read, + .read = pci_sal_read, .write = pci_sal_write }; @@ -137,35 +137,98 @@ alloc_pci_controller (int seg) return controller; } -static u64 __devinit -add_io_space (struct acpi_resource_address64 *addr) +struct pci_root_info { + struct pci_controller *controller; + char *name; +}; + +static unsigned int +new_space (u64 phys_base, int sparse) { - u64 offset; - int sparse = 0; + u64 mmio_base; int i; - if (addr->address_translation_offset == 0) - return IO_SPACE_BASE(0); /* part of legacy IO space */ - - if (addr->attribute.io.translation_attribute == ACPI_SPARSE_TRANSLATION) - sparse = 1; + if (phys_base == 0) + return 0; /* legacy I/O port space */ - offset = (u64) ioremap(addr->address_translation_offset, 0); + mmio_base = (u64) ioremap(phys_base, 0); for (i = 0; i < num_io_spaces; i++) - if (io_space[i].mmio_base == offset && + if (io_space[i].mmio_base == mmio_base && io_space[i].sparse == sparse) - return IO_SPACE_BASE(i); + return i; if (num_io_spaces == MAX_IO_SPACES) { - printk("Too many IO port spaces\n"); + printk(KERN_ERR "PCI: Too many IO port spaces " + "(MAX_IO_SPACES=%lu)\n", MAX_IO_SPACES); return ~0; } i = num_io_spaces++; - io_space[i].mmio_base = offset; + io_space[i].mmio_base = mmio_base; io_space[i].sparse = sparse; - return IO_SPACE_BASE(i); + return i; +} + +static u64 __devinit +add_io_space (struct pci_root_info *info, struct acpi_resource_address64 *addr) +{ + struct resource *resource; + char *name; + u64 base, min, max, base_port; + unsigned int sparse = 0, space_nr, len; + + resource = kzalloc(sizeof(*resource), GFP_KERNEL); + if (!resource) { + printk(KERN_ERR "PCI: No memory for %s I/O port space\n", + info->name); + goto out; + } + + len = strlen(info->name) + 32; + name = kzalloc(len, GFP_KERNEL); + if (!name) { + printk(KERN_ERR "PCI: No memory for %s I/O port space name\n", + info->name); + goto free_resource; + } + + min = addr->min_address_range; + max = min + addr->address_length - 1; + if (addr->attribute.io.translation_attribute == ACPI_SPARSE_TRANSLATION) + sparse = 1; + + space_nr = new_space(addr->address_translation_offset, sparse); + if (space_nr == ~0) + goto free_name; + + base = __pa(io_space[space_nr].mmio_base); + base_port = IO_SPACE_BASE(space_nr); + snprintf(name, len, "%s I/O Ports %08lx-%08lx", info->name, + base_port + min, base_port + max); + + /* + * The SDM guarantees the legacy 0-64K space is sparse, but if the + * mapping is done by the processor (not the bridge), ACPI may not + * mark it as sparse. + */ + if (space_nr == 0) + sparse = 1; + + resource->name = name; + resource->flags = IORESOURCE_MEM; + resource->start = base + (sparse ? IO_SPACE_SPARSE_ENCODING(min) : min); + resource->end = base + (sparse ? IO_SPACE_SPARSE_ENCODING(max) : max); + insert_resource(&iomem_resource, resource); + + return base_port; + +free_name: + kfree(name); +free_resource: + kfree(resource); +out: + return ~0; } static acpi_status __devinit resource_to_window(struct acpi_resource *resource, @@ -205,11 +268,6 @@ count_window (struct acpi_resource *resource, void *data) return AE_OK; } -struct pci_root_info { - struct pci_controller *controller; - char *name; -}; - static __devinit acpi_status add_window(struct acpi_resource *res, void *data) { struct pci_root_info *info = data; @@ -231,7 +289,7 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data) } else if (addr.resource_type == ACPI_IO_RANGE) { flags = IORESOURCE_IO; root = &ioport_resource; - offset = add_io_space(&addr); + offset = add_io_space(info, &addr); if (offset == ~0) return AE_OK; } else @@ -241,7 +299,7 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data) window->resource.name = info->name; window->resource.flags = flags; window->resource.start = addr.min_address_range + offset; - window->resource.end = addr.max_address_range + offset; + window->resource.end = window->resource.start + addr.address_length - 1; window->resource.child = NULL; window->offset = offset; @@ -739,7 +797,7 @@ int pci_vector_resources(int last, int nr_released) { int count = nr_released; - count += (IA64_LAST_DEVICE_VECTOR - last); + count += (IA64_LAST_DEVICE_VECTOR - last); return count; } -- cgit v1.2.3 From 37ee16ae93a3e4ae7dd51beb81d249f5f12a55c2 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 8 Nov 2005 19:08:05 +0000 Subject: [ARM SMP] Add core ARM support for local timers Add infrastructure for supporting per-cpu local timers to update the profiling information and update system time accounting. Signed-off-by: Russell King --- arch/arm/Kconfig | 10 ++++++++++ arch/arm/kernel/entry-armv.S | 7 +++++++ arch/arm/kernel/irq.c | 1 + arch/arm/kernel/smp.c | 34 ++++++++++++++++++++++++++++++++++ include/asm-arm/hardirq.h | 1 + include/asm-arm/smp.h | 38 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 91 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 91d5ef3397b..3bfef0934c9 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -356,6 +356,16 @@ config HOTPLUG_CPU Say Y here to experiment with turning CPUs off and on. CPUs can be controlled through /sys/devices/system/cpu. +config LOCAL_TIMERS + bool "Use local timer interrupts" + depends on SMP && n + default y + help + Enable support for local timers on SMP platforms, rather then the + legacy IPI broadcast method. Local timers allows the system + accounting to be spread across the timer interval, preventing a + "thundering herd" at every timer tick. + config PREEMPT bool "Preemptible Kernel (EXPERIMENTAL)" depends on EXPERIMENTAL diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index a511ec5b11a..d9fb819bf7c 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -47,6 +47,13 @@ movne r0, sp adrne lr, 1b bne do_IPI + +#ifdef CONFIG_LOCAL_TIMERS + test_for_ltirq r0, r6, r5, lr + movne r0, sp + adrne lr, 1b + bne do_local_timer +#endif #endif .endm diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 6f86d0af7c5..d7099dbbb87 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -264,6 +264,7 @@ unlock: #endif #ifdef CONFIG_SMP show_ipi_list(p); + show_local_irqs(p); #endif seq_printf(p, "Err: %10lu\n", irq_err_count); } diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index f5fc57e0fe4..77e2e9ca89f 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -184,6 +184,11 @@ int __cpuexit __cpu_disable(void) */ migrate_irqs(); + /* + * Stop the local timer for this CPU. + */ + local_timer_stop(cpu); + /* * Flush user cache and TLB mappings, and then remove this CPU * from the vm mask set of all processes. @@ -289,6 +294,11 @@ asmlinkage void __cpuinit secondary_start_kernel(void) */ cpu_set(cpu, cpu_online_map); + /* + * Setup local timer for this CPU. + */ + local_timer_setup(cpu); + /* * OK, it's off to the idle thread for us */ @@ -454,6 +464,18 @@ void show_ipi_list(struct seq_file *p) seq_putc(p, '\n'); } +void show_local_irqs(struct seq_file *p) +{ + unsigned int cpu; + + seq_printf(p, "LOC: "); + + for_each_present_cpu(cpu) + seq_printf(p, "%10u ", irq_stat[cpu].local_timer_irqs); + + seq_putc(p, '\n'); +} + static void ipi_timer(struct pt_regs *regs) { int user = user_mode(regs); @@ -464,6 +486,18 @@ static void ipi_timer(struct pt_regs *regs) irq_exit(); } +#ifdef CONFIG_LOCAL_TIMERS +asmlinkage void do_local_timer(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + if (local_timer_ack()) { + irq_stat[cpu].local_timer_irqs++; + ipi_timer(regs); + } +} +#endif + /* * ipi_call_function - handle IPI from smp_call_function() * diff --git a/include/asm-arm/hardirq.h b/include/asm-arm/hardirq.h index e5ccb6b8ff8..1cbb173bf5b 100644 --- a/include/asm-arm/hardirq.h +++ b/include/asm-arm/hardirq.h @@ -8,6 +8,7 @@ typedef struct { unsigned int __softirq_pending; + unsigned int local_timer_irqs; } ____cacheline_aligned irq_cpustat_t; #include /* Standard mappings for irq_cpustat_t above */ diff --git a/include/asm-arm/smp.h b/include/asm-arm/smp.h index 52e7c8d830b..5a72e50ca9f 100644 --- a/include/asm-arm/smp.h +++ b/include/asm-arm/smp.h @@ -92,4 +92,42 @@ extern void platform_cpu_die(unsigned int cpu); extern int platform_cpu_kill(unsigned int cpu); extern void platform_cpu_enable(unsigned int cpu); +#ifdef CONFIG_LOCAL_TIMERS +/* + * Setup a local timer interrupt for a CPU. + */ +extern void local_timer_setup(unsigned int cpu); + +/* + * Stop a local timer interrupt. + */ +extern void local_timer_stop(unsigned int cpu); + +/* + * Platform provides this to acknowledge a local timer IRQ + */ +extern int local_timer_ack(void); + +#else + +static inline void local_timer_setup(unsigned int cpu) +{ +} + +static inline void local_timer_stop(unsigned int cpu) +{ +} + +#endif + +/* + * show local interrupt info + */ +extern void show_local_irqs(struct seq_file *); + +/* + * Called from assembly, this is the local timer IRQ handler + */ +asmlinkage void do_local_timer(struct pt_regs *); + #endif /* ifndef __ASM_ARM_SMP_H */ -- cgit v1.2.3 From a93876c16275376c4f9f1630ce24036d329fa7a0 Mon Sep 17 00:00:00 2001 From: Dirk Opfer Date: Tue, 8 Nov 2005 19:15:30 +0000 Subject: [ARM] 3123/1: Sharp SL-6000x: Add IRDA, MMC, UDC and keyboard device Patch from Dirk Opfer This patch adds MMC, IRDA and UDC support to the Sharp SL-6000x device. Also it adds a platform device for the keyboard driver. Signed-off-by: Dirk Opfer Signed-off-by: Richard Purdie Signed-off-by: Russell King --- arch/arm/mach-pxa/tosa.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 400609f8b6a..f3e01891e85 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -111,16 +111,128 @@ static struct scoop_pcmcia_dev tosa_pcmcia_scoop[] = { }, }; +/* + * USB Device Controller + */ +static void tosa_udc_command(int cmd) +{ + switch(cmd) { + case PXA2XX_UDC_CMD_CONNECT: + set_scoop_gpio(&tosascoop_jc_device.dev,TOSA_SCOOP_JC_USB_PULLUP); + break; + case PXA2XX_UDC_CMD_DISCONNECT: + reset_scoop_gpio(&tosascoop_jc_device.dev,TOSA_SCOOP_JC_USB_PULLUP); + break; + } +} + +static int tosa_udc_is_connected(void) +{ + return ((GPLR(TOSA_GPIO_USB_IN) & GPIO_bit(TOSA_GPIO_USB_IN)) == 0); +} + + +static struct pxa2xx_udc_mach_info udc_info __initdata = { + .udc_command = tosa_udc_command, + .udc_is_connected = tosa_udc_is_connected, +}; + +/* + * MMC/SD Device + */ +static struct pxamci_platform_data tosa_mci_platform_data; + +static int tosa_mci_init(struct device *dev, irqreturn_t (*tosa_detect_int)(int, void *, struct pt_regs *), void *data) +{ + int err; + + /* setup GPIO for PXA25x MMC controller */ + pxa_gpio_mode(GPIO6_MMCCLK_MD); + pxa_gpio_mode(GPIO8_MMCCS0_MD); + pxa_gpio_mode(TOSA_GPIO_nSD_DETECT | GPIO_IN); + + tosa_mci_platform_data.detect_delay = msecs_to_jiffies(250); + + err = request_irq(TOSA_IRQ_GPIO_nSD_DETECT, tosa_detect_int, SA_INTERRUPT, + "MMC/SD card detect", data); + if (err) { + printk(KERN_ERR "tosa_mci_init: MMC/SD: can't request MMC card detect IRQ\n"); + return -1; + } + + set_irq_type(TOSA_IRQ_GPIO_nSD_DETECT, IRQT_BOTHEDGE); + + return 0; +} + +static void tosa_mci_setpower(struct device *dev, unsigned int vdd) +{ + struct pxamci_platform_data* p_d = dev->platform_data; + + if (( 1 << vdd) & p_d->ocr_mask) { + set_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_PWR_ON); + } else { + reset_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_PWR_ON); + } +} + +static int tosa_mci_get_ro(struct device *dev) +{ + return (read_scoop_reg(&tosascoop_device.dev, SCOOP_GPWR)&TOSA_SCOOP_SD_WP); +} + +static void tosa_mci_exit(struct device *dev, void *data) +{ + free_irq(TOSA_IRQ_GPIO_nSD_DETECT, data); +} + +static struct pxamci_platform_data tosa_mci_platform_data = { + .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, + .init = tosa_mci_init, + .get_ro = tosa_mci_get_ro, + .setpower = tosa_mci_setpower, + .exit = tosa_mci_exit, +}; + +/* + * Irda + */ +static void tosa_irda_transceiver_mode(struct device *dev, int mode) +{ + if (mode & IR_OFF) { + reset_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_IR_POWERDWN); + pxa_gpio_mode(GPIO47_STTXD|GPIO_DFLT_LOW); + pxa_gpio_mode(GPIO47_STTXD|GPIO_OUT); + } else { + pxa_gpio_mode(GPIO47_STTXD_MD); + set_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_IR_POWERDWN); + } +} + +static struct pxaficp_platform_data tosa_ficp_platform_data = { + .transceiver_cap = IR_SIRMODE | IR_OFF, + .transceiver_mode = tosa_irda_transceiver_mode, +}; + +/* + * Tosa Keyboard + */ +static struct platform_device tosakbd_device = { + .name = "tosa-keyboard", + .id = -1, +}; static struct platform_device *devices[] __initdata = { &tosascoop_device, &tosascoop_jc_device, + &tosakbd_device, }; static void __init tosa_init(void) { pxa_gpio_mode(TOSA_GPIO_ON_RESET | GPIO_IN); pxa_gpio_mode(TOSA_GPIO_TC6393_INT | GPIO_IN); + pxa_gpio_mode(TOSA_GPIO_USB_IN | GPIO_IN); /* setup sleep mode values */ PWER = 0x00000002; @@ -131,9 +243,12 @@ static void __init tosa_init(void) PGSR2 = 0x00014000; PCFR |= PCFR_OPDE; - // enable batt_fault + /* enable batt_fault */ PMCR = 0x01; + pxa_set_mci_info(&tosa_mci_platform_data); + pxa_set_udc_info(&udc_info); + pxa_set_ficp_info(&tosa_ficp_platform_data); platform_add_devices(devices, ARRAY_SIZE(devices)); scoop_num = 2; -- cgit v1.2.3 From df1ec6deeb18097ae670bf6d001b6e95c8332640 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 8 Nov 2005 19:15:30 +0000 Subject: [ARM] 3125/2: VR1000: Fix map_decs initialiser Patch from Ben Dooks Fix the initialisation of the map_desc fields in the Thorcom VR1000 machine support to use the new .pfn initialiser. Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/mach-s3c2410/mach-vr1000.c | 56 +++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c index 46b259673c1..ae7e099bf6c 100644 --- a/arch/arm/mach-s3c2410/mach-vr1000.c +++ b/arch/arm/mach-s3c2410/mach-vr1000.c @@ -74,27 +74,47 @@ /* macros to modify the physical addresses for io space */ -#define PA_CS2(item) ((item) + S3C2410_CS2) -#define PA_CS3(item) ((item) + S3C2410_CS3) -#define PA_CS4(item) ((item) + S3C2410_CS4) -#define PA_CS5(item) ((item) + S3C2410_CS5) +#define PA_CS2(item) (__phys_to_pfn((item) + S3C2410_CS2)) +#define PA_CS3(item) (__phys_to_pfn((item) + S3C2410_CS3)) +#define PA_CS4(item) (__phys_to_pfn((item) + S3C2410_CS4)) +#define PA_CS5(item) (__phys_to_pfn((item) + S3C2410_CS5)) static struct map_desc vr1000_iodesc[] __initdata = { /* ISA IO areas */ - - { (u32)S3C24XX_VA_ISA_BYTE, PA_CS2(BAST_PA_ISAIO), SZ_16M, MT_DEVICE }, - { (u32)S3C24XX_VA_ISA_WORD, PA_CS3(BAST_PA_ISAIO), SZ_16M, MT_DEVICE }, - - /* we could possibly compress the next set down into a set of smaller tables - * pagetables, but that would mean using an L2 section, and it still means - * we cannot actually feed the same register to an LDR due to 16K spacing - */ - - /* bast CPLD control registers, and external interrupt controls */ - { (u32)VR1000_VA_CTRL1, VR1000_PA_CTRL1, SZ_1M, MT_DEVICE }, - { (u32)VR1000_VA_CTRL2, VR1000_PA_CTRL2, SZ_1M, MT_DEVICE }, - { (u32)VR1000_VA_CTRL3, VR1000_PA_CTRL3, SZ_1M, MT_DEVICE }, - { (u32)VR1000_VA_CTRL4, VR1000_PA_CTRL4, SZ_1M, MT_DEVICE }, + { + .virtual = (u32)S3C24XX_VA_ISA_BYTE, + .pfn = PA_CS2(BAST_PA_ISAIO), + .length = SZ_16M, + .type = MT_DEVICE, + }, { + .virtual = (u32)S3C24XX_VA_ISA_WORD, + .pfn = PA_CS3(BAST_PA_ISAIO), + .length = SZ_16M, + .type = MT_DEVICE, + }, + + /* CPLD control registers, and external interrupt controls */ + { + .virtual = (u32)VR1000_VA_CTRL1, + .pfn = __phys_to_pfn(VR1000_PA_CTRL1), + .length = SZ_1M, + .type = MT_DEVICE, + }, { + .virtual = (u32)VR1000_VA_CTRL2, + .pfn = __phys_to_pfn(VR1000_PA_CTRL2), + .length = SZ_1M, + .type = MT_DEVICE, + }, { + .virtual = (u32)VR1000_VA_CTRL3, + .pfn = __phys_to_pfn(VR1000_PA_CTRL3), + .length = SZ_1M, + .type = MT_DEVICE, + }, { + .virtual = (u32)VR1000_VA_CTRL4, + .pfn = __phys_to_pfn(VR1000_PA_CTRL4), + .length = SZ_1M, + .type = MT_DEVICE, + }, /* peripheral space... one for each of fast/slow/byte/16bit */ /* note, ide is only decoded in word space, even though some registers -- cgit v1.2.3 From 1d23b65de54c35844e82bdb08bc85d8142e310ea Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 8 Nov 2005 19:15:31 +0000 Subject: [ARM] 3126/1: BAST: fix map_desc initialisation Patch from Ben Dooks Fix the map_desc entries to use the new .pfn initialiser for the Simtec BAST machine support. Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/mach-s3c2410/mach-bast.c | 73 ++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 21 deletions(-) diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index 0b71c896bbd..1be2567a748 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -89,32 +89,63 @@ /* macros to modify the physical addresses for io space */ -#define PA_CS2(item) ((item) + S3C2410_CS2) -#define PA_CS3(item) ((item) + S3C2410_CS3) -#define PA_CS4(item) ((item) + S3C2410_CS4) -#define PA_CS5(item) ((item) + S3C2410_CS5) +#define PA_CS2(item) (__phys_to_pfn((item) + S3C2410_CS2)) +#define PA_CS3(item) (__phys_to_pfn((item) + S3C2410_CS3)) +#define PA_CS4(item) (__phys_to_pfn((item) + S3C2410_CS4)) +#define PA_CS5(item) (__phys_to_pfn((item) + S3C2410_CS5)) static struct map_desc bast_iodesc[] __initdata = { /* ISA IO areas */ - - { (u32)S3C24XX_VA_ISA_BYTE, PA_CS2(BAST_PA_ISAIO), SZ_16M, MT_DEVICE }, - { (u32)S3C24XX_VA_ISA_WORD, PA_CS3(BAST_PA_ISAIO), SZ_16M, MT_DEVICE }, - - /* we could possibly compress the next set down into a set of smaller tables - * pagetables, but that would mean using an L2 section, and it still means - * we cannot actually feed the same register to an LDR due to 16K spacing - */ - + { + .virtual = (u32)S3C24XX_VA_ISA_BYTE, + .pfn = PA_CS2(BAST_PA_ISAIO), + .length = SZ_16M, + .type = MT_DEVICE, + }, { + .virtual = (u32)S3C24XX_VA_ISA_WORD, + .pfn = PA_CS3(BAST_PA_ISAIO), + .length = SZ_16M, + .type = MT_DEVICE, + }, /* bast CPLD control registers, and external interrupt controls */ - { (u32)BAST_VA_CTRL1, BAST_PA_CTRL1, SZ_1M, MT_DEVICE }, - { (u32)BAST_VA_CTRL2, BAST_PA_CTRL2, SZ_1M, MT_DEVICE }, - { (u32)BAST_VA_CTRL3, BAST_PA_CTRL3, SZ_1M, MT_DEVICE }, - { (u32)BAST_VA_CTRL4, BAST_PA_CTRL4, SZ_1M, MT_DEVICE }, - + { + .virtual = (u32)BAST_VA_CTRL1, + .pfn = __phys_to_pfn(BAST_PA_CTRL1), + .length = SZ_1M, + .type = MT_DEVICE, + }, { + .virtual = (u32)BAST_VA_CTRL2, + .pfn = __phys_to_pfn(BAST_PA_CTRL2), + .length = SZ_1M, + .type = MT_DEVICE, + }, { + .virtual = (u32)BAST_VA_CTRL3, + .pfn = __phys_to_pfn(BAST_PA_CTRL3), + .length = SZ_1M, + .type = MT_DEVICE, + }, { + .virtual = (u32)BAST_VA_CTRL4, + .pfn = __phys_to_pfn(BAST_PA_CTRL4), + .length = SZ_1M, + .type = MT_DEVICE, + }, /* PC104 IRQ mux */ - { (u32)BAST_VA_PC104_IRQREQ, BAST_PA_PC104_IRQREQ, SZ_1M, MT_DEVICE }, - { (u32)BAST_VA_PC104_IRQRAW, BAST_PA_PC104_IRQRAW, SZ_1M, MT_DEVICE }, - { (u32)BAST_VA_PC104_IRQMASK, BAST_PA_PC104_IRQMASK, SZ_1M, MT_DEVICE }, + { + .virtual = (u32)BAST_VA_PC104_IRQREQ, + .pfn = __phys_to_pfn(BAST_PA_PC104_IRQREQ), + .length = SZ_1M, + .type = MT_DEVICE, + }, { + .virtual = (u32)BAST_VA_PC104_IRQRAW, + .pfn = __phys_to_pfn(BAST_PA_PC104_IRQRAW), + .length = SZ_1M, + .type = MT_DEVICE, + }, { + .virtual = (u32)BAST_VA_PC104_IRQMASK, + .pfn = __phys_to_pfn(BAST_PA_PC104_IRQMASK), + .length = SZ_1M, + .type = MT_DEVICE, + }, /* peripheral space... one for each of fast/slow/byte/16bit */ /* note, ide is only decoded in word space, even though some registers -- cgit v1.2.3 From a63ae4427c6af66d6eda26e5da8fed53f8fbede3 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Tue, 8 Nov 2005 19:15:43 +0000 Subject: [ARM] 3093/1: SharpSL PCMCIA Updates for Cxx00 models Patch from Richard Purdie The Sharp SL-Cxx00 models have a combined power control for the SD and CF slot 0. This patch adds hooks to the scoop driver to allow machines to provide a custom control function for this and such a function is added for spitz/akita/borzoi. It also moves the gpio init code into the machine files as this is machine dependent and differs between some models. A couple of warnings when compiling for collie are also fixed. Signed-off-by: Richard Purdie Signed-off-by: Russell King --- arch/arm/common/scoop.c | 6 -- arch/arm/mach-pxa/corgi.c | 48 +++++++++++--- arch/arm/mach-pxa/poodle.c | 32 ++++++++- arch/arm/mach-pxa/spitz.c | 95 ++++++++++++++++++++------ drivers/pcmcia/pxa2xx_sharpsl.c | 140 +++++++++++++++++++-------------------- include/asm-arm/hardware/scoop.h | 10 ++- 6 files changed, 220 insertions(+), 111 deletions(-) diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c index bb4eff61441..c7fdf390cef 100644 --- a/arch/arm/common/scoop.c +++ b/arch/arm/common/scoop.c @@ -19,12 +19,6 @@ #define SCOOP_REG(d,adr) (*(volatile unsigned short*)(d +(adr))) -/* PCMCIA to Scoop linkage structures for pxa2xx_sharpsl.c - There is no easy way to link multiple scoop devices into one - single entity for the pxa2xx_pcmcia device */ -int scoop_num; -struct scoop_pcmcia_dev *scoop_devs; - struct scoop_dev { void *base; spinlock_t scoop_lock; diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index eb5f6d744a4..100fb31b515 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -62,6 +62,37 @@ static struct scoop_config corgi_scoop_setup = { .io_out = CORGI_SCOOP_IO_OUT, }; +struct platform_device corgiscoop_device = { + .name = "sharp-scoop", + .id = -1, + .dev = { + .platform_data = &corgi_scoop_setup, + }, + .num_resources = ARRAY_SIZE(corgi_scoop_resources), + .resource = corgi_scoop_resources, +}; + +static void corgi_pcmcia_init(void) +{ + /* Setup default state of GPIO outputs + before we enable them as outputs. */ + GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) | + GPIO_bit(GPIO49_nPWE) | GPIO_bit(GPIO50_nPIOR) | + GPIO_bit(GPIO51_nPIOW) | GPIO_bit(GPIO52_nPCE_1) | + GPIO_bit(GPIO53_nPCE_2); + + pxa_gpio_mode(GPIO48_nPOE_MD); + pxa_gpio_mode(GPIO49_nPWE_MD); + pxa_gpio_mode(GPIO50_nPIOR_MD); + pxa_gpio_mode(GPIO51_nPIOW_MD); + pxa_gpio_mode(GPIO55_nPREG_MD); + pxa_gpio_mode(GPIO56_nPWAIT_MD); + pxa_gpio_mode(GPIO57_nIOIS16_MD); + pxa_gpio_mode(GPIO52_nPCE_1_MD); + pxa_gpio_mode(GPIO53_nPCE_2_MD); + pxa_gpio_mode(GPIO54_pSKTSEL_MD); +} + static struct scoop_pcmcia_dev corgi_pcmcia_scoop[] = { { .dev = &corgiscoop_device.dev, @@ -71,16 +102,14 @@ static struct scoop_pcmcia_dev corgi_pcmcia_scoop[] = { }, }; -struct platform_device corgiscoop_device = { - .name = "sharp-scoop", - .id = -1, - .dev = { - .platform_data = &corgi_scoop_setup, - }, - .num_resources = ARRAY_SIZE(corgi_scoop_resources), - .resource = corgi_scoop_resources, +static struct scoop_pcmcia_config corgi_pcmcia_config = { + .devs = &corgi_pcmcia_scoop[0], + .num_devs = 1, + .pcmcia_init = corgi_pcmcia_init, }; +EXPORT_SYMBOL(corgiscoop_device); + /* * Corgi SSP Device @@ -294,8 +323,7 @@ static void __init corgi_init(void) pxa_set_mci_info(&corgi_mci_platform_data); pxa_set_ficp_info(&corgi_ficp_platform_data); - scoop_num = 1; - scoop_devs = &corgi_pcmcia_scoop[0]; + platform_scoop_config = &corgi_pcmcia_config; platform_add_devices(devices, ARRAY_SIZE(devices)); } diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index ad6a13f95a6..eef3de26ad3 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -65,6 +65,27 @@ struct platform_device poodle_scoop_device = { .resource = poodle_scoop_resources, }; +static void poodle_pcmcia_init(void) +{ + /* Setup default state of GPIO outputs + before we enable them as outputs. */ + GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) | + GPIO_bit(GPIO49_nPWE) | GPIO_bit(GPIO50_nPIOR) | + GPIO_bit(GPIO51_nPIOW) | GPIO_bit(GPIO52_nPCE_1) | + GPIO_bit(GPIO53_nPCE_2); + + pxa_gpio_mode(GPIO48_nPOE_MD); + pxa_gpio_mode(GPIO49_nPWE_MD); + pxa_gpio_mode(GPIO50_nPIOR_MD); + pxa_gpio_mode(GPIO51_nPIOW_MD); + pxa_gpio_mode(GPIO55_nPREG_MD); + pxa_gpio_mode(GPIO56_nPWAIT_MD); + pxa_gpio_mode(GPIO57_nIOIS16_MD); + pxa_gpio_mode(GPIO52_nPCE_1_MD); + pxa_gpio_mode(GPIO53_nPCE_2_MD); + pxa_gpio_mode(GPIO54_pSKTSEL_MD); +} + static struct scoop_pcmcia_dev poodle_pcmcia_scoop[] = { { .dev = &poodle_scoop_device.dev, @@ -74,6 +95,14 @@ static struct scoop_pcmcia_dev poodle_pcmcia_scoop[] = { }, }; +static struct scoop_pcmcia_config poodle_pcmcia_config = { + .devs = &poodle_pcmcia_scoop[0], + .num_devs = 1, + .pcmcia_init = poodle_pcmcia_init, +}; + +EXPORT_SYMBOL(poodle_scoop_device); + /* LoCoMo device */ static struct resource locomo_resources[] = { @@ -268,8 +297,7 @@ static void __init poodle_init(void) pxa_set_mci_info(&poodle_mci_platform_data); pxa_set_ficp_info(&poodle_ficp_platform_data); - scoop_num = 1; - scoop_devs = &poodle_pcmcia_scoop[0]; + platform_scoop_config = &poodle_pcmcia_config; ret = platform_add_devices(devices, ARRAY_SIZE(devices)); if (ret) { diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 6c6878cd220..4e9a699ee42 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -104,6 +104,66 @@ struct platform_device spitzscoop2_device = { .resource = spitz_scoop2_resources, }; +#define SPITZ_PWR_SD 0x01 +#define SPITZ_PWR_CF 0x02 + +/* Power control is shared with between one of the CF slots and SD */ +static void spitz_card_pwr_ctrl(int device, unsigned short new_cpr) +{ + unsigned short cpr = read_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR); + + if (new_cpr & 0x0007) { + set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CF_POWER); + if (!(cpr & 0x0002) && !(cpr & 0x0004)) + mdelay(5); + if (device == SPITZ_PWR_CF) + cpr |= 0x0002; + if (device == SPITZ_PWR_SD) + cpr |= 0x0004; + write_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR, cpr | new_cpr); + } else { + if (device == SPITZ_PWR_CF) + cpr &= ~0x0002; + if (device == SPITZ_PWR_SD) + cpr &= ~0x0004; + write_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR, cpr | new_cpr); + if (!(cpr & 0x0002) && !(cpr & 0x0004)) { + mdelay(1); + reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CF_POWER); + } + } +} + +static void spitz_pcmcia_init(void) +{ + /* Setup default state of GPIO outputs + before we enable them as outputs. */ + GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) | + GPIO_bit(GPIO49_nPWE) | GPIO_bit(GPIO50_nPIOR) | + GPIO_bit(GPIO51_nPIOW) | GPIO_bit(GPIO54_nPCE_2); + GPSR(GPIO85_nPCE_1) = GPIO_bit(GPIO85_nPCE_1); + + pxa_gpio_mode(GPIO48_nPOE_MD); + pxa_gpio_mode(GPIO49_nPWE_MD); + pxa_gpio_mode(GPIO50_nPIOR_MD); + pxa_gpio_mode(GPIO51_nPIOW_MD); + pxa_gpio_mode(GPIO55_nPREG_MD); + pxa_gpio_mode(GPIO56_nPWAIT_MD); + pxa_gpio_mode(GPIO57_nIOIS16_MD); + pxa_gpio_mode(GPIO85_nPCE_1_MD); + pxa_gpio_mode(GPIO54_nPCE_2_MD); + pxa_gpio_mode(GPIO104_pSKTSEL_MD); +} + +static void spitz_pcmcia_pwr(struct device *scoop, unsigned short cpr, int nr) +{ + /* Only need to override behaviour for slot 0 */ + if (nr == 0) + spitz_card_pwr_ctrl(SPITZ_PWR_CF, cpr); + else + write_scoop_reg(scoop, SCOOP_CPR, cpr); +} + static struct scoop_pcmcia_dev spitz_pcmcia_scoop[] = { { .dev = &spitzscoop_device.dev, @@ -117,6 +177,16 @@ static struct scoop_pcmcia_dev spitz_pcmcia_scoop[] = { }, }; +static struct scoop_pcmcia_config spitz_pcmcia_config = { + .devs = &spitz_pcmcia_scoop[0], + .num_devs = 2, + .pcmcia_init = spitz_pcmcia_init, + .power_ctrl = spitz_pcmcia_pwr, +}; + +EXPORT_SYMBOL(spitzscoop_device); +EXPORT_SYMBOL(spitzscoop2_device); + /* * Spitz SSP Device @@ -235,27 +305,14 @@ static int spitz_mci_init(struct device *dev, irqreturn_t (*spitz_detect_int)(in return 0; } -/* Power control is shared with one of the CF slots so we have a mess */ static void spitz_mci_setpower(struct device *dev, unsigned int vdd) { struct pxamci_platform_data* p_d = dev->platform_data; - unsigned short cpr = read_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR); - - if (( 1 << vdd) & p_d->ocr_mask) { - /* printk(KERN_DEBUG "%s: on\n", __FUNCTION__); */ - set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CF_POWER); - mdelay(2); - write_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR, cpr | 0x04); - } else { - /* printk(KERN_DEBUG "%s: off\n", __FUNCTION__); */ - write_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR, cpr & ~0x04); - - if (!(cpr | 0x02)) { - mdelay(1); - reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CF_POWER); - } - } + if (( 1 << vdd) & p_d->ocr_mask) + spitz_card_pwr_ctrl(SPITZ_PWR_SD, 0x0004); + else + spitz_card_pwr_ctrl(SPITZ_PWR_SD, 0x0000); } static int spitz_mci_get_ro(struct device *dev) @@ -351,8 +408,8 @@ static void __init common_init(void) static void __init spitz_init(void) { - scoop_num = 2; - scoop_devs = &spitz_pcmcia_scoop[0]; + platform_scoop_config = &spitz_pcmcia_config; + spitz_bl_machinfo.set_bl_intensity = spitz_bl_set_intensity; common_init(); diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c index fe5ea36e7de..56c58831e80 100644 --- a/drivers/pcmcia/pxa2xx_sharpsl.c +++ b/drivers/pcmcia/pxa2xx_sharpsl.c @@ -22,16 +22,20 @@ #include #include #include -#ifdef CONFIG_SA1100_COLLIE -#include -#else -#include -#endif #include "soc_common.h" #define NO_KEEP_VS 0x0001 +/* PCMCIA to Scoop linkage + + There is no easy way to link multiple scoop devices into one + single entity for the pxa2xx_pcmcia device so this structure + is used which is setup by the platform code +*/ +struct scoop_pcmcia_config *platform_scoop_config; +#define SCOOP_DEV platform_scoop_config->devs + static void sharpsl_pcmcia_init_reset(struct scoop_pcmcia_dev *scoopdev) { reset_scoop(scoopdev->dev); @@ -43,38 +47,16 @@ static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { int ret; -#ifndef CONFIG_SA1100_COLLIE - /* - * Setup default state of GPIO outputs - * before we enable them as outputs. - */ - GPSR(GPIO48_nPOE) = - GPIO_bit(GPIO48_nPOE) | - GPIO_bit(GPIO49_nPWE) | - GPIO_bit(GPIO50_nPIOR) | - GPIO_bit(GPIO51_nPIOW) | - GPIO_bit(GPIO52_nPCE_1) | - GPIO_bit(GPIO53_nPCE_2); - - pxa_gpio_mode(GPIO48_nPOE_MD); - pxa_gpio_mode(GPIO49_nPWE_MD); - pxa_gpio_mode(GPIO50_nPIOR_MD); - pxa_gpio_mode(GPIO51_nPIOW_MD); - pxa_gpio_mode(GPIO52_nPCE_1_MD); - pxa_gpio_mode(GPIO53_nPCE_2_MD); - pxa_gpio_mode(GPIO54_pSKTSEL_MD); - pxa_gpio_mode(GPIO55_nPREG_MD); - pxa_gpio_mode(GPIO56_nPWAIT_MD); - pxa_gpio_mode(GPIO57_nIOIS16_MD); -#endif + if (platform_scoop_config->pcmcia_init) + platform_scoop_config->pcmcia_init(); /* Register interrupts */ - if (scoop_devs[skt->nr].cd_irq >= 0) { + if (SCOOP_DEV[skt->nr].cd_irq >= 0) { struct pcmcia_irqs cd_irq; cd_irq.sock = skt->nr; - cd_irq.irq = scoop_devs[skt->nr].cd_irq; - cd_irq.str = scoop_devs[skt->nr].cd_irq_str; + cd_irq.irq = SCOOP_DEV[skt->nr].cd_irq; + cd_irq.str = SCOOP_DEV[skt->nr].cd_irq_str; ret = soc_pcmcia_request_irqs(skt, &cd_irq, 1); if (ret) { @@ -83,19 +65,19 @@ static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt) } } - skt->irq = scoop_devs[skt->nr].irq; + skt->irq = SCOOP_DEV[skt->nr].irq; return 0; } static void sharpsl_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) { - if (scoop_devs[skt->nr].cd_irq >= 0) { + if (SCOOP_DEV[skt->nr].cd_irq >= 0) { struct pcmcia_irqs cd_irq; cd_irq.sock = skt->nr; - cd_irq.irq = scoop_devs[skt->nr].cd_irq; - cd_irq.str = scoop_devs[skt->nr].cd_irq_str; + cd_irq.irq = SCOOP_DEV[skt->nr].cd_irq; + cd_irq.str = SCOOP_DEV[skt->nr].cd_irq_str; soc_pcmcia_free_irqs(skt, &cd_irq, 1); } } @@ -105,9 +87,9 @@ static void sharpsl_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { unsigned short cpr, csr; - struct device *scoop = scoop_devs[skt->nr].dev; + struct device *scoop = SCOOP_DEV[skt->nr].dev; - cpr = read_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR); + cpr = read_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_CPR); write_scoop_reg(scoop, SCOOP_IRM, 0x00FF); write_scoop_reg(scoop, SCOOP_ISR, 0x0000); @@ -116,21 +98,25 @@ static void sharpsl_pcmcia_socket_state(struct soc_pcmcia_socket *skt, if (csr & 0x0004) { /* card eject */ write_scoop_reg(scoop, SCOOP_CDR, 0x0000); - scoop_devs[skt->nr].keep_vs = NO_KEEP_VS; + SCOOP_DEV[skt->nr].keep_vs = NO_KEEP_VS; } - else if (!(scoop_devs[skt->nr].keep_vs & NO_KEEP_VS)) { + else if (!(SCOOP_DEV[skt->nr].keep_vs & NO_KEEP_VS)) { /* keep vs1,vs2 */ write_scoop_reg(scoop, SCOOP_CDR, 0x0000); - csr |= scoop_devs[skt->nr].keep_vs; + csr |= SCOOP_DEV[skt->nr].keep_vs; } else if (cpr & 0x0003) { /* power on */ write_scoop_reg(scoop, SCOOP_CDR, 0x0000); - scoop_devs[skt->nr].keep_vs = (csr & 0x00C0); + SCOOP_DEV[skt->nr].keep_vs = (csr & 0x00C0); } else { /* card detect */ - write_scoop_reg(scoop, SCOOP_CDR, 0x0002); + if ((machine_is_spitz() || machine_is_borzoi()) && skt->nr == 1) { + write_scoop_reg(scoop, SCOOP_CDR, 0x0000); + } else { + write_scoop_reg(scoop, SCOOP_CDR, 0x0002); + } } state->detect = (csr & 0x0004) ? 0 : 1; @@ -144,7 +130,6 @@ static void sharpsl_pcmcia_socket_state(struct soc_pcmcia_socket *skt, if ((cpr & 0x0080) && ((cpr & 0x8040) != 0x8040)) { printk(KERN_ERR "sharpsl_pcmcia_socket_state(): CPR=%04X, Low voltage!\n", cpr); } - } @@ -152,7 +137,7 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) { unsigned long flags; - struct device *scoop = scoop_devs[skt->nr].dev; + struct device *scoop = SCOOP_DEV[skt->nr].dev; unsigned short cpr, ncpr, ccr, nccr, mcr, nmcr, imr, nimr; @@ -177,8 +162,13 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, nccr = (ccr = read_scoop_reg(scoop, SCOOP_CCR)) & ~0x0080; nimr = (imr = read_scoop_reg(scoop, SCOOP_IMR)) & ~0x003E; - ncpr |= (state->Vcc == 33) ? 0x0001 : - (state->Vcc == 50) ? 0x0002 : 0; + if ((machine_is_spitz() || machine_is_borzoi() || machine_is_akita()) && skt->nr == 0) { + ncpr |= (state->Vcc == 33) ? 0x0002 : + (state->Vcc == 50) ? 0x0002 : 0; + } else { + ncpr |= (state->Vcc == 33) ? 0x0001 : + (state->Vcc == 50) ? 0x0002 : 0; + } nmcr |= (state->flags&SS_IOCARD) ? 0x0010 : 0; ncpr |= (state->flags&SS_OUTPUT_ENA) ? 0x0080 : 0; nccr |= (state->flags&SS_RESET)? 0x0080: 0; @@ -190,18 +180,22 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, ((skt->status&SS_WRPROT) ? 0x0008 : 0); if (!(ncpr & 0x0003)) { - scoop_devs[skt->nr].keep_rd = 0; - } else if (!scoop_devs[skt->nr].keep_rd) { + SCOOP_DEV[skt->nr].keep_rd = 0; + } else if (!SCOOP_DEV[skt->nr].keep_rd) { if (nccr & 0x0080) - scoop_devs[skt->nr].keep_rd = 1; + SCOOP_DEV[skt->nr].keep_rd = 1; else nccr |= 0x0080; } if (mcr != nmcr) write_scoop_reg(scoop, SCOOP_MCR, nmcr); - if (cpr != ncpr) - write_scoop_reg(scoop, SCOOP_CPR, ncpr); + if (cpr != ncpr) { + if (platform_scoop_config->power_ctrl) + platform_scoop_config->power_ctrl(scoop, ncpr , skt->nr); + else + write_scoop_reg(scoop, SCOOP_CPR, ncpr); + } if (ccr != nccr) write_scoop_reg(scoop, SCOOP_CCR, nccr); if (imr != nimr) @@ -214,43 +208,43 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, static void sharpsl_pcmcia_socket_init(struct soc_pcmcia_socket *skt) { - sharpsl_pcmcia_init_reset(&scoop_devs[skt->nr]); + sharpsl_pcmcia_init_reset(&SCOOP_DEV[skt->nr]); /* Enable interrupt */ - write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_IMR, 0x00C0); - write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_MCR, 0x0101); - scoop_devs[skt->nr].keep_vs = NO_KEEP_VS; + write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_IMR, 0x00C0); + write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_MCR, 0x0101); + SCOOP_DEV[skt->nr].keep_vs = NO_KEEP_VS; if (machine_is_collie()) /* We need to disable SS_OUTPUT_ENA here. */ - write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR, read_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR) & ~0x0080); + write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_CPR, read_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_CPR) & ~0x0080); } static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) { /* CF_BUS_OFF */ - sharpsl_pcmcia_init_reset(&scoop_devs[skt->nr]); + sharpsl_pcmcia_init_reset(&SCOOP_DEV[skt->nr]); if (machine_is_collie()) /* We need to disable SS_OUTPUT_ENA here. */ - write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR, read_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR) & ~0x0080); + write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_CPR, read_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_CPR) & ~0x0080); } static struct pcmcia_low_level sharpsl_pcmcia_ops = { - .owner = THIS_MODULE, - .hw_init = sharpsl_pcmcia_hw_init, - .hw_shutdown = sharpsl_pcmcia_hw_shutdown, - .socket_state = sharpsl_pcmcia_socket_state, - .configure_socket = sharpsl_pcmcia_configure_socket, - .socket_init = sharpsl_pcmcia_socket_init, - .socket_suspend = sharpsl_pcmcia_socket_suspend, - .first = 0, - .nr = 0, + .owner = THIS_MODULE, + .hw_init = sharpsl_pcmcia_hw_init, + .hw_shutdown = sharpsl_pcmcia_hw_shutdown, + .socket_state = sharpsl_pcmcia_socket_state, + .configure_socket = sharpsl_pcmcia_configure_socket, + .socket_init = sharpsl_pcmcia_socket_init, + .socket_suspend = sharpsl_pcmcia_socket_suspend, + .first = 0, + .nr = 0, }; -static struct platform_device *sharpsl_pcmcia_device; - #ifdef CONFIG_SA1100_COLLIE +#include "sa11xx_base.h" + int __init pcmcia_collie_init(struct device *dev) { int ret = -ENODEV; @@ -263,11 +257,13 @@ int __init pcmcia_collie_init(struct device *dev) #else +static struct platform_device *sharpsl_pcmcia_device; + static int __init sharpsl_pcmcia_init(void) { int ret; - sharpsl_pcmcia_ops.nr=scoop_num; + sharpsl_pcmcia_ops.nr=platform_scoop_config->num_devs; sharpsl_pcmcia_device = kmalloc(sizeof(*sharpsl_pcmcia_device), GFP_KERNEL); if (!sharpsl_pcmcia_device) return -ENOMEM; @@ -275,7 +271,7 @@ static int __init sharpsl_pcmcia_init(void) memset(sharpsl_pcmcia_device, 0, sizeof(*sharpsl_pcmcia_device)); sharpsl_pcmcia_device->name = "pxa2xx-pcmcia"; sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops; - sharpsl_pcmcia_device->dev.parent=scoop_devs[0].dev; + sharpsl_pcmcia_device->dev.parent=platform_scoop_config->devs[0].dev; ret = platform_device_register(sharpsl_pcmcia_device); if (ret) diff --git a/include/asm-arm/hardware/scoop.h b/include/asm-arm/hardware/scoop.h index a8f1013930e..d37bf744326 100644 --- a/include/asm-arm/hardware/scoop.h +++ b/include/asm-arm/hardware/scoop.h @@ -52,8 +52,14 @@ struct scoop_pcmcia_dev { unsigned char keep_rd; }; -extern int scoop_num; -extern struct scoop_pcmcia_dev *scoop_devs; +struct scoop_pcmcia_config { + struct scoop_pcmcia_dev *devs; + int num_devs; + void (*pcmcia_init)(void); + void (*power_ctrl)(struct device *scoop, unsigned short cpr, int nr); +}; + +extern struct scoop_pcmcia_config *platform_scoop_config; void reset_scoop(struct device *dev); unsigned short set_scoop_gpio(struct device *dev, unsigned short bit); -- cgit v1.2.3 From 4c18ad20493c9eac6e7d0c2a05156acfc02d9b6b Mon Sep 17 00:00:00 2001 From: Dirk Opfer Date: Tue, 8 Nov 2005 19:15:50 +0000 Subject: [ARM] 3124/1: Sharp SL-6000x: SharpSL PCMCIA Updates Patch from Dirk Opfer This patch updates the tosa machine to use the new SharpSL PCMCIA layer introduced with Patch #3093/1 Depends on #3093/1 Signed-off-by: Dirk Opfer Signed-off-by: Richard Purdie Signed-off-by: Russell King --- arch/arm/mach-pxa/tosa.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index f3e01891e85..c312054dfb8 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -98,6 +98,9 @@ struct platform_device tosascoop_jc_device = { .resource = tosa_scoop_jc_resources, }; +/* + * PCMCIA + */ static struct scoop_pcmcia_dev tosa_pcmcia_scoop[] = { { .dev = &tosascoop_device.dev, @@ -111,6 +114,33 @@ static struct scoop_pcmcia_dev tosa_pcmcia_scoop[] = { }, }; +static void tosa_pcmcia_init(void) +{ + /* Setup default state of GPIO outputs + before we enable them as outputs. */ + GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) | + GPIO_bit(GPIO49_nPWE) | GPIO_bit(GPIO50_nPIOR) | + GPIO_bit(GPIO51_nPIOW) | GPIO_bit(GPIO52_nPCE_1) | + GPIO_bit(GPIO53_nPCE_2); + + pxa_gpio_mode(GPIO48_nPOE_MD); + pxa_gpio_mode(GPIO49_nPWE_MD); + pxa_gpio_mode(GPIO50_nPIOR_MD); + pxa_gpio_mode(GPIO51_nPIOW_MD); + pxa_gpio_mode(GPIO55_nPREG_MD); + pxa_gpio_mode(GPIO56_nPWAIT_MD); + pxa_gpio_mode(GPIO57_nIOIS16_MD); + pxa_gpio_mode(GPIO52_nPCE_1_MD); + pxa_gpio_mode(GPIO53_nPCE_2_MD); + pxa_gpio_mode(GPIO54_pSKTSEL_MD); +} + +static struct scoop_pcmcia_config tosa_pcmcia_config = { + .devs = &tosa_pcmcia_scoop[0], + .num_devs = 2, + .pcmcia_init = tosa_pcmcia_init, +}; + /* * USB Device Controller */ @@ -249,10 +279,9 @@ static void __init tosa_init(void) pxa_set_mci_info(&tosa_mci_platform_data); pxa_set_udc_info(&udc_info); pxa_set_ficp_info(&tosa_ficp_platform_data); - platform_add_devices(devices, ARRAY_SIZE(devices)); + platform_scoop_config = &tosa_pcmcia_config; - scoop_num = 2; - scoop_devs = &tosa_pcmcia_scoop[0]; + platform_add_devices(devices, ARRAY_SIZE(devices)); } static void __init fixup_tosa(struct machine_desc *desc, -- cgit v1.2.3 From 329f7dba5f7dc3bc9a30ad00cf373d2e83115aa1 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Mon, 7 Nov 2005 21:12:43 +0300 Subject: [PATCH] fix de_thread() vs send_group_sigqueue() race When non-leader thread does exec, de_thread calls release_task(leader) before calling exit_itimers(). If local timer interrupt happens in between, it can oops in send_group_sigqueue() while taking ->sighand->siglock == NULL. However, we can't change send_group_sigqueue() to check p->signal != NULL, because sys_timer_create() does get_task_struct() only in SIGEV_THREAD_ID case. So it is possible that this task_struct was already freed and we can't trust p->signal. This patch changes de_thread() so that leader released after exit_itimers() call. Signed-off-by: Oleg Nesterov Acked-by: Chris Wright Signed-off-by: Linus Torvalds --- fs/exec.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index cd6c574557d..5a4e3acc2e9 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -590,6 +590,7 @@ static inline int de_thread(struct task_struct *tsk) struct signal_struct *sig = tsk->signal; struct sighand_struct *newsighand, *oldsighand = tsk->sighand; spinlock_t *lock = &oldsighand->siglock; + struct task_struct *leader = NULL; int count; /* @@ -665,7 +666,7 @@ static inline int de_thread(struct task_struct *tsk) * and to assume its PID: */ if (!thread_group_leader(current)) { - struct task_struct *leader = current->group_leader, *parent; + struct task_struct *parent; struct dentry *proc_dentry1, *proc_dentry2; unsigned long exit_state, ptrace; @@ -674,6 +675,7 @@ static inline int de_thread(struct task_struct *tsk) * It should already be zombie at this point, most * of the time. */ + leader = current->group_leader; while (leader->exit_state != EXIT_ZOMBIE) yield(); @@ -733,7 +735,6 @@ static inline int de_thread(struct task_struct *tsk) proc_pid_flush(proc_dentry2); BUG_ON(exit_state != EXIT_ZOMBIE); - release_task(leader); } /* @@ -743,8 +744,11 @@ static inline int de_thread(struct task_struct *tsk) sig->flags = 0; no_thread_group: - BUG_ON(atomic_read(&sig->count) != 1); exit_itimers(sig); + if (leader) + release_task(leader); + + BUG_ON(atomic_read(&sig->count) != 1); if (atomic_read(&oldsighand->count) == 1) { /* -- cgit v1.2.3 From 88d51967f56f55a45849efe50858ea7dfa0d38dc Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Sun, 6 Nov 2005 23:35:34 -0800 Subject: [PATCH] AGP performance fixes AGP allocation/deallocation is suffering major performance issues due to the nature of global_flush_tlb() being called on every change_page_attr() call. For small allocations this isn't really seen, but when you start allocating 50000 pages of AGP space, for say, texture memory, then things can take seconds to complete. In some cases the situation is doubled or even quadrupled in the time due to SMP, or a deallocation, then a new reallocation. I've had a case of upto 20 seconds wait time to deallocate and reallocate AGP space. This patch fixes the problem by making it the caller's responsibility to call global_flush_tlb(), and so removes it from every instance of mapping a page into AGP space until the time that all change_page_attr() changes are done. Signed-off-by: Dave Jones Signed-off-by: Andrew Morton --- drivers/char/agp/backend.c | 9 +++++++-- drivers/char/agp/generic.c | 11 ++++++++--- drivers/char/agp/i460-agp.c | 9 ++++++--- drivers/char/agp/intel-agp.c | 5 ++++- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index 73f333f491b..4d5ed18dad0 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c @@ -147,6 +147,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) printk(KERN_ERR PFX "unable to get memory for scratch page.\n"); return -ENOMEM; } + global_flush_tlb(); bridge->scratch_page_real = virt_to_gart(addr); bridge->scratch_page = @@ -187,9 +188,11 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) return 0; err_out: - if (bridge->driver->needs_scratch_page) + if (bridge->driver->needs_scratch_page) { bridge->driver->agp_destroy_page( gart_to_virt(bridge->scratch_page_real)); + global_flush_tlb(); + } if (got_gatt) bridge->driver->free_gatt_table(bridge); if (got_keylist) { @@ -211,9 +214,11 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge) bridge->key_list = NULL; if (bridge->driver->agp_destroy_page && - bridge->driver->needs_scratch_page) + bridge->driver->needs_scratch_page) { bridge->driver->agp_destroy_page( gart_to_virt(bridge->scratch_page_real)); + global_flush_tlb(); + } } /* When we remove the global variable agp_bridge from all drivers diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index c4a38715c6f..19f242b5078 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -57,7 +57,8 @@ int map_page_into_agp(struct page *page) { int i; i = change_page_attr(page, 1, PAGE_KERNEL_NOCACHE); - global_flush_tlb(); + /* Caller's responsibility to call global_flush_tlb() for + * performance reasons */ return i; } EXPORT_SYMBOL_GPL(map_page_into_agp); @@ -66,7 +67,8 @@ int unmap_page_from_agp(struct page *page) { int i; i = change_page_attr(page, 1, PAGE_KERNEL); - global_flush_tlb(); + /* Caller's responsibility to call global_flush_tlb() for + * performance reasons */ return i; } EXPORT_SYMBOL_GPL(unmap_page_from_agp); @@ -153,6 +155,7 @@ void agp_free_memory(struct agp_memory *curr) for (i = 0; i < curr->page_count; i++) { curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i])); } + global_flush_tlb(); } agp_free_key(curr->key); vfree(curr->memory); @@ -210,7 +213,9 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge, new->memory[i] = virt_to_gart(addr); new->page_count++; } - new->bridge = bridge; + global_flush_tlb(); + + new->bridge = bridge; flush_agp_mappings(); diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c index 58944cd271e..be2e569ae91 100644 --- a/drivers/char/agp/i460-agp.c +++ b/drivers/char/agp/i460-agp.c @@ -514,9 +514,10 @@ static void *i460_alloc_page (struct agp_bridge_data *bridge) { void *page; - if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) + if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) { page = agp_generic_alloc_page(agp_bridge); - else + global_flush_tlb(); + } else /* Returning NULL would cause problems */ /* AK: really dubious code. */ page = (void *)~0UL; @@ -525,8 +526,10 @@ static void *i460_alloc_page (struct agp_bridge_data *bridge) static void i460_destroy_page (void *page) { - if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) + if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) { agp_generic_destroy_page(page); + global_flush_tlb(); + } } #endif /* I460_LARGE_IO_PAGES */ diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index bf4cc9ffd5b..027161ab88e 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -270,6 +270,7 @@ static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type) switch (pg_count) { case 1: addr = agp_bridge->driver->agp_alloc_page(agp_bridge); + global_flush_tlb(); break; case 4: /* kludge to get 4 physical pages for ARGB cursor */ @@ -330,9 +331,11 @@ static void intel_i810_free_by_type(struct agp_memory *curr) if(curr->type == AGP_PHYS_MEMORY) { if (curr->page_count == 4) i8xx_destroy_pages(gart_to_virt(curr->memory[0])); - else + else { agp_bridge->driver->agp_destroy_page( gart_to_virt(curr->memory[0])); + global_flush_tlb(); + } vfree(curr->memory); } kfree(curr); -- cgit v1.2.3 From 49ebd7c6bb1f70a6c5465925e6ca2f4a32d6a6cd Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 6 Nov 2005 23:35:35 -0800 Subject: [PATCH] i460-agp warning fixes drivers/char/agp/i460-agp.c: In function `i460_fetch_size': drivers/char/agp/i460-agp.c:115: warning: size_t format, long unsigned int arg (arg 2) drivers/char/agp/i460-agp.c:115: warning: size_t format, long unsigned int arg (arg 3) drivers/char/agp/i460-agp.c: In function `i460_mask_memory': drivers/char/agp/i460-agp.c:542: warning: integer constant is too large for "long" type Note that the i460_mask_memory() change is a guess. But a good one, I suspect. Signed-off-by: Dave Jones Signed-off-by: Andrew Morton --- drivers/char/agp/i460-agp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c index be2e569ae91..34a444658ff 100644 --- a/drivers/char/agp/i460-agp.c +++ b/drivers/char/agp/i460-agp.c @@ -111,8 +111,10 @@ static int i460_fetch_size (void) if (i460.io_page_shift != I460_IO_PAGE_SHIFT) { printk(KERN_ERR PFX - "I/O (GART) page-size %ZuKB doesn't match expected size %ZuKB\n", - 1UL << (i460.io_page_shift - 10), 1UL << (I460_IO_PAGE_SHIFT)); + "I/O (GART) page-size %luKB doesn't match expected " + "size %luKB\n", + 1UL << (i460.io_page_shift - 10), + 1UL << (I460_IO_PAGE_SHIFT)); return 0; } @@ -539,7 +541,7 @@ static unsigned long i460_mask_memory (struct agp_bridge_data *bridge, { /* Make sure the returned address is a valid GATT entry */ return bridge->driver->masks[0].mask - | (((addr & ~((1 << I460_IO_PAGE_SHIFT) - 1)) & 0xffffff000) >> 12); + | (((addr & ~((1 << I460_IO_PAGE_SHIFT) - 1)) & 0xfffff000) >> 12); } struct agp_bridge_driver intel_i460_driver = { -- cgit v1.2.3 From f8c905d368c757e2c96db293a472a31abcf4b147 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 8 Nov 2005 22:43:05 +0000 Subject: [ARM] 3132/1: S3C2410 - reset on decompression error Patch from Ben Dooks Force a watchdog reset if the system fails to decompress properly. Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/boot/compressed/misc.c | 6 ++++++ arch/arm/mach-s3c2410/Kconfig | 8 ++++++++ include/asm-arm/arch-s3c2410/uncompress.h | 22 ++++++++++++++++++++-- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c index 50f13eec6cd..5ab94584bae 100644 --- a/arch/arm/boot/compressed/misc.c +++ b/arch/arm/boot/compressed/misc.c @@ -283,8 +283,14 @@ void flush_window(void) putstr("."); } +#ifndef arch_error +#define arch_error(x) +#endif + static void error(char *x) { + arch_error(x); + putstr("\n\n"); putstr(x); putstr("\n\n -- System halted"); diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig index c796bcdd615..0b9d7ca49ec 100644 --- a/arch/arm/mach-s3c2410/Kconfig +++ b/arch/arm/mach-s3c2410/Kconfig @@ -121,6 +121,14 @@ config S3C2410_BOOT_WATCHDOG system resets depends on the value of PCLK. The timeout on an 200MHz s3c2410 should be about 30 seconds. +config S3C2410_BOOT_ERROR_RESET + bool "S3C2410 Reboot on decompression error" + depends on ARCH_S3C2410 + help + Say y here to use the watchdog to reset the system if the + kernel decompressor detects an error during decompression. + + comment "S3C2410 Setup" config S3C2410_DMA diff --git a/include/asm-arm/arch-s3c2410/uncompress.h b/include/asm-arm/arch-s3c2410/uncompress.h index d7a4a8354fa..ddd1578a7ee 100644 --- a/include/asm-arm/arch-s3c2410/uncompress.h +++ b/include/asm-arm/arch-s3c2410/uncompress.h @@ -116,6 +116,8 @@ putstr(const char *ptr) } } +#define __raw_writel(d,ad) do { *((volatile unsigned int *)(ad)) = (d); } while(0) + /* CONFIG_S3C2410_BOOT_WATCHDOG * * Simple boot-time watchdog setup, to reboot the system if there is @@ -126,8 +128,6 @@ putstr(const char *ptr) #define WDOG_COUNT (0xff00) -#define __raw_writel(d,ad) do { *((volatile unsigned int *)(ad)) = (d); } while(0) - static inline void arch_decomp_wdog(void) { __raw_writel(WDOG_COUNT, S3C2410_WTCNT); @@ -145,6 +145,24 @@ static void arch_decomp_wdog_start(void) #define arch_decomp_wdog() #endif +#ifdef CONFIG_S3C2410_BOOT_ERROR_RESET + +static void arch_decomp_error(const char *x) +{ + putstr("\n\n"); + putstr(x); + putstr("\n\n -- System resetting\n"); + + __raw_writel(0x4000, S3C2410_WTDAT); + __raw_writel(0x4000, S3C2410_WTCNT); + __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x40), S3C2410_WTCON); + + while(1); +} + +#define arch_error arch_decomp_error +#endif + static void error(char *err); static void -- cgit v1.2.3 From d07ad967e3c1cb955c4f9ee6a4eba4e6e1edb1e8 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 8 Nov 2005 22:43:05 +0000 Subject: [ARM] 3134/1: add missing EXPORT_SYMBOL for the ARM version of sha_transform Patch from Nicolas Pitre Noticed by Woody Suwalski . Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/kernel/armksyms.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index 7b17a87a331..7a3261f0bf7 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -9,6 +9,7 @@ */ #include #include +#include #include #include #include @@ -126,6 +127,9 @@ EXPORT_SYMBOL(__put_user_2); EXPORT_SYMBOL(__put_user_4); EXPORT_SYMBOL(__put_user_8); + /* crypto hash */ +EXPORT_SYMBOL(sha_transform); + /* gcc lib functions */ EXPORT_SYMBOL(__ashldi3); EXPORT_SYMBOL(__ashrdi3); -- cgit v1.2.3 From 5285eb57c9a20d8df2569c770ff6048c3202cc91 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 8 Nov 2005 22:43:06 +0000 Subject: [ARM] 3135/1: harden SA11x0 and PXA2xx timer init code Patch from Nicolas Pitre Make it completely deterministic and leave nothing to chance (even if it had at worst 0.001% probability of failing). Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/mach-pxa/time.c | 8 +++++--- arch/arm/mach-sa1100/time.c | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index 7dad3f1465e..b9b2057349e 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -132,11 +132,13 @@ static void __init pxa_timer_init(void) tv.tv_sec = pxa_get_rtc_time(); do_settimeofday(&tv); - OSMR0 = 0; /* set initial match at 0 */ + OIER = 0; /* disable any timer interrupts */ + OSCR = LATCH*2; /* push OSCR out of the way */ + OSMR0 = LATCH; /* set initial match */ OSSR = 0xf; /* clear status on all timers */ setup_irq(IRQ_OST0, &pxa_timer_irq); - OIER |= OIER_E0; /* enable match on timer 0 to cause interrupts */ - OSCR = 0; /* initialize free-running timer, force first match */ + OIER = OIER_E0; /* enable match on timer 0 to cause interrupts */ + OSCR = 0; /* initialize free-running timer */ } #ifdef CONFIG_NO_IDLE_HZ diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c index 47e0420623f..e4b435e634e 100644 --- a/arch/arm/mach-sa1100/time.c +++ b/arch/arm/mach-sa1100/time.c @@ -124,11 +124,13 @@ static void __init sa1100_timer_init(void) tv.tv_sec = sa1100_get_rtc_time(); do_settimeofday(&tv); - OSMR0 = 0; /* set initial match at 0 */ + OIER = 0; /* disable any timer interrupts */ + OSCR = LATCH*2; /* push OSCR out of the way */ + OSMR0 = LATCH; /* set initial match */ OSSR = 0xf; /* clear status on all timers */ setup_irq(IRQ_OST0, &sa1100_timer_irq); - OIER |= OIER_E0; /* enable match on timer 0 to cause interrupts */ - OSCR = 0; /* initialize free-running timer, force first match */ + OIER = OIER_E0; /* enable match on timer 0 to cause interrupts */ + OSCR = 0; /* initialize free-running timer */ } #ifdef CONFIG_NO_IDLE_HZ -- cgit v1.2.3 From 15a93807826a5cbffb47d6bfbeeee108d6da1dbc Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 8 Nov 2005 23:10:51 +0000 Subject: [SERIAL] IOC3: Update 8250 driver bits Update the support for the 16550 present on most IOC3 configurations to use the current API. Signed-off-by: Ralf Baechle Signed-off-by: Russell King --- drivers/net/ioc3-eth.c | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index 49e5467bdd7..6a3129bc15a 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -46,10 +46,8 @@ #include #ifdef CONFIG_SERIAL_8250 -#include -#include -#define IOC3_BAUD (22000000 / (3*16)) -#define IOC3_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) +#include +#include #endif #include @@ -1146,12 +1144,11 @@ static inline int ioc3_is_menet(struct pci_dev *pdev) * around ioc3 oddities in this respect. * * The IOC3 serials use a 22MHz clock rate with an additional divider by 3. - * (IOC3_BAUD = (22000000 / (3*16))) */ static void __devinit ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3) { - struct serial_struct req; + struct uart_port port; /* * We need to recognice and treat the fourth MENET serial as it @@ -1165,20 +1162,25 @@ static void __devinit ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3) if (ioc3_is_menet(pdev) && PCI_SLOT(pdev->devfn) == 3) return; - /* Register to interrupt zero because we share the interrupt with - the serial driver which we don't properly support yet. */ - memset(&req, 0, sizeof(req)); - req.irq = 0; - req.flags = IOC3_COM_FLAGS; - req.io_type = SERIAL_IO_MEM; - req.iomem_reg_shift = 0; - req.baud_base = IOC3_BAUD; - - req.iomem_base = (unsigned char *) &ioc3->sregs.uarta; - register_serial(&req); - - req.iomem_base = (unsigned char *) &ioc3->sregs.uartb; - register_serial(&req); + /* + * Register to interrupt zero because we share the interrupt with + * the serial driver which we don't properly support yet. + * + * Can't use UPF_IOREMAP as the whole of IOC3 resources have already + * been registered. + */ + memset(&port, 0, sizeof(port)); + port.irq = 0; + port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; + port.iotype = UPIO_MEM; + port.regshift = 0; + port.uartclk = 22000000 / 3; + + port.membase = (unsigned char *) &ioc3->sregs.uarta; + serial8250_register_port(&port); + + port.membase = (unsigned char *) &ioc3->sregs.uartb; + serial8250_register_port(&port); } #endif -- cgit v1.2.3 From 66ba135c5a398df5c3a4b43d84d9df80cbc87c61 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Wed, 9 Nov 2005 11:01:06 +1100 Subject: powerpc: create kernel/setup.h for functions defined by setup-common.c and used in setup_xx.c Signed-off-by: Stephen Rothwell --- arch/powerpc/kernel/setup-common.c | 2 ++ arch/powerpc/kernel/setup.h | 6 ++++++ arch/powerpc/kernel/setup_32.c | 2 ++ arch/powerpc/kernel/setup_64.c | 2 ++ 4 files changed, 12 insertions(+) create mode 100644 arch/powerpc/kernel/setup.h diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 26bb1fe6384..17c46a2e356 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -53,6 +53,8 @@ #include #include +#include "setup.h" + #undef DEBUG #ifdef DEBUG diff --git a/arch/powerpc/kernel/setup.h b/arch/powerpc/kernel/setup.h new file mode 100644 index 00000000000..2ebba755272 --- /dev/null +++ b/arch/powerpc/kernel/setup.h @@ -0,0 +1,6 @@ +#ifndef _POWERPC_KERNEL_SETUP_H +#define _POWERPC_KERNEL_SETUP_H + +void check_for_initrd(void); + +#endif /* _POWERPC_KERNEL_SETUP_H */ diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 0fbc73f7f82..55f485f78c0 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -40,6 +40,8 @@ #include #include +#include "setup.h" + #define DBG(fmt...) #if defined CONFIG_KGDB diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 54c606f680b..fe39aac4f24 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -61,6 +61,8 @@ #include #include +#include "setup.h" + #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) #else -- cgit v1.2.3 From 330d57fb98a916fa8e1363846540dd420e99499a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 4 Nov 2005 10:18:40 +0000 Subject: [PATCH] Fix sysctl unregistration oops (CVE-2005-2709) You could open the /proc/sys/net/ipv4/conf// file, then wait for interface to go away, try to grab as much memory as possible in hope to hit the (kfreed) ctl_table. Then fill it with pointers to your function. Then do read from file you've opened and if you are lucky, you'll get it called as ->proc_handler() in kernel mode. So this is at least an Oops and possibly more. It does depend on an interface going away though, so less of a security risk than it would otherwise be. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- arch/s390/appldata/appldata_base.c | 7 +- include/linux/proc_fs.h | 1 + include/linux/sysctl.h | 3 + kernel/sysctl.c | 136 +++++++++++++++++++++++++++++-------- 4 files changed, 116 insertions(+), 31 deletions(-) diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index c9f2f60cfa5..dee6ab54984 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c @@ -592,12 +592,15 @@ int appldata_register_ops(struct appldata_ops *ops) */ void appldata_unregister_ops(struct appldata_ops *ops) { + void *table; spin_lock(&appldata_ops_lock); - unregister_sysctl_table(ops->sysctl_header); list_del(&ops->list); - kfree(ops->ctl_table); + /* at that point any incoming access will fail */ + table = ops->ctl_table; ops->ctl_table = NULL; spin_unlock(&appldata_ops_lock); + unregister_sysctl_table(ops->sysctl_header); + kfree(table); P_INFO("%s-ops unregistered!\n", ops->name); } /********************** module-ops management **************************/ diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 65ceeaa3065..74488e49166 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -66,6 +66,7 @@ struct proc_dir_entry { write_proc_t *write_proc; atomic_t count; /* use count */ int deleted; /* delete flag */ + void *set; }; struct kcore_list { diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index fc8e367f671..fc131d6602b 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -24,6 +24,7 @@ #include struct file; +struct completion; #define CTL_MAXNAME 10 /* how many path components do we allow in a call to sysctl? In other words, what is @@ -925,6 +926,8 @@ struct ctl_table_header { ctl_table *ctl_table; struct list_head ctl_entry; + int used; + struct completion *unregistering; }; struct ctl_table_header * register_sysctl_table(ctl_table * table, diff --git a/kernel/sysctl.c b/kernel/sysctl.c index c4f35f96884..9990e10192e 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -169,7 +169,7 @@ struct file_operations proc_sys_file_operations = { extern struct proc_dir_entry *proc_sys_root; -static void register_proc_table(ctl_table *, struct proc_dir_entry *); +static void register_proc_table(ctl_table *, struct proc_dir_entry *, void *); static void unregister_proc_table(ctl_table *, struct proc_dir_entry *); #endif @@ -992,10 +992,51 @@ static ctl_table dev_table[] = { extern void init_irq_proc (void); +static DEFINE_SPINLOCK(sysctl_lock); + +/* called under sysctl_lock */ +static int use_table(struct ctl_table_header *p) +{ + if (unlikely(p->unregistering)) + return 0; + p->used++; + return 1; +} + +/* called under sysctl_lock */ +static void unuse_table(struct ctl_table_header *p) +{ + if (!--p->used) + if (unlikely(p->unregistering)) + complete(p->unregistering); +} + +/* called under sysctl_lock, will reacquire if has to wait */ +static void start_unregistering(struct ctl_table_header *p) +{ + /* + * if p->used is 0, nobody will ever touch that entry again; + * we'll eliminate all paths to it before dropping sysctl_lock + */ + if (unlikely(p->used)) { + struct completion wait; + init_completion(&wait); + p->unregistering = &wait; + spin_unlock(&sysctl_lock); + wait_for_completion(&wait); + spin_lock(&sysctl_lock); + } + /* + * do not remove from the list until nobody holds it; walking the + * list in do_sysctl() relies on that. + */ + list_del_init(&p->ctl_entry); +} + void __init sysctl_init(void) { #ifdef CONFIG_PROC_FS - register_proc_table(root_table, proc_sys_root); + register_proc_table(root_table, proc_sys_root, &root_table_header); init_irq_proc(); #endif } @@ -1004,6 +1045,7 @@ int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *ol void __user *newval, size_t newlen) { struct list_head *tmp; + int error = -ENOTDIR; if (nlen <= 0 || nlen >= CTL_MAXNAME) return -ENOTDIR; @@ -1012,20 +1054,30 @@ int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *ol if (!oldlenp || get_user(old_len, oldlenp)) return -EFAULT; } + spin_lock(&sysctl_lock); tmp = &root_table_header.ctl_entry; do { struct ctl_table_header *head = list_entry(tmp, struct ctl_table_header, ctl_entry); void *context = NULL; - int error = parse_table(name, nlen, oldval, oldlenp, + + if (!use_table(head)) + continue; + + spin_unlock(&sysctl_lock); + + error = parse_table(name, nlen, oldval, oldlenp, newval, newlen, head->ctl_table, &context); kfree(context); + + spin_lock(&sysctl_lock); + unuse_table(head); if (error != -ENOTDIR) - return error; - tmp = tmp->next; - } while (tmp != &root_table_header.ctl_entry); - return -ENOTDIR; + break; + } while ((tmp = tmp->next) != &root_table_header.ctl_entry); + spin_unlock(&sysctl_lock); + return error; } asmlinkage long sys_sysctl(struct __sysctl_args __user *args) @@ -1236,12 +1288,16 @@ struct ctl_table_header *register_sysctl_table(ctl_table * table, return NULL; tmp->ctl_table = table; INIT_LIST_HEAD(&tmp->ctl_entry); + tmp->used = 0; + tmp->unregistering = NULL; + spin_lock(&sysctl_lock); if (insert_at_head) list_add(&tmp->ctl_entry, &root_table_header.ctl_entry); else list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry); + spin_unlock(&sysctl_lock); #ifdef CONFIG_PROC_FS - register_proc_table(table, proc_sys_root); + register_proc_table(table, proc_sys_root, tmp); #endif return tmp; } @@ -1255,10 +1311,13 @@ struct ctl_table_header *register_sysctl_table(ctl_table * table, */ void unregister_sysctl_table(struct ctl_table_header * header) { - list_del(&header->ctl_entry); + might_sleep(); + spin_lock(&sysctl_lock); + start_unregistering(header); #ifdef CONFIG_PROC_FS unregister_proc_table(header->ctl_table, proc_sys_root); #endif + spin_unlock(&sysctl_lock); kfree(header); } @@ -1269,7 +1328,7 @@ void unregister_sysctl_table(struct ctl_table_header * header) #ifdef CONFIG_PROC_FS /* Scan the sysctl entries in table and add them all into /proc */ -static void register_proc_table(ctl_table * table, struct proc_dir_entry *root) +static void register_proc_table(ctl_table * table, struct proc_dir_entry *root, void *set) { struct proc_dir_entry *de; int len; @@ -1305,13 +1364,14 @@ static void register_proc_table(ctl_table * table, struct proc_dir_entry *root) de = create_proc_entry(table->procname, mode, root); if (!de) continue; + de->set = set; de->data = (void *) table; if (table->proc_handler) de->proc_fops = &proc_sys_file_operations; } table->de = de; if (de->mode & S_IFDIR) - register_proc_table(table->child, de); + register_proc_table(table->child, de, set); } } @@ -1336,6 +1396,13 @@ static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root continue; } + /* + * In any case, mark the entry as goner; we'll keep it + * around if it's busy, but we'll know to do nothing with + * its fields. We are under sysctl_lock here. + */ + de->data = NULL; + /* Don't unregister proc entries that are still being used.. */ if (atomic_read(&de->count)) continue; @@ -1349,27 +1416,38 @@ static ssize_t do_rw_proc(int write, struct file * file, char __user * buf, size_t count, loff_t *ppos) { int op; - struct proc_dir_entry *de; + struct proc_dir_entry *de = PDE(file->f_dentry->d_inode); struct ctl_table *table; size_t res; - ssize_t error; - - de = PDE(file->f_dentry->d_inode); - if (!de || !de->data) - return -ENOTDIR; - table = (struct ctl_table *) de->data; - if (!table || !table->proc_handler) - return -ENOTDIR; - op = (write ? 002 : 004); - if (ctl_perm(table, op)) - return -EPERM; + ssize_t error = -ENOTDIR; - res = count; - - error = (*table->proc_handler) (table, write, file, buf, &res, ppos); - if (error) - return error; - return res; + spin_lock(&sysctl_lock); + if (de && de->data && use_table(de->set)) { + /* + * at that point we know that sysctl was not unregistered + * and won't be until we finish + */ + spin_unlock(&sysctl_lock); + table = (struct ctl_table *) de->data; + if (!table || !table->proc_handler) + goto out; + error = -EPERM; + op = (write ? 002 : 004); + if (ctl_perm(table, op)) + goto out; + + /* careful: calling conventions are nasty here */ + res = count; + error = (*table->proc_handler)(table, write, file, + buf, &res, ppos); + if (!error) + error = res; + out: + spin_lock(&sysctl_lock); + unuse_table(de->set); + } + spin_unlock(&sysctl_lock); + return error; } static int proc_opensys(struct inode *inode, struct file *file) -- cgit v1.2.3 From b709c0832824da20a32a3119911b9f0cf6970452 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Wed, 9 Nov 2005 13:28:33 +1100 Subject: ppc64: move stack switching up in interrupt processing This will make the ppc64 multiplatform irq handling more like the generic handling. Signed-off-by: Stephen Rothwell --- arch/powerpc/kernel/misc_64.S | 8 ++++---- arch/ppc64/kernel/irq.c | 40 ++++++++++++++++++++-------------------- arch/ppc64/kernel/misc.S | 8 ++++---- include/asm-powerpc/irq.h | 4 ++-- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index ae1433da09b..9d09f0ad6ef 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -89,12 +89,12 @@ _GLOBAL(call_do_softirq) mtlr r0 blr -_GLOBAL(call_handle_IRQ_event) +_GLOBAL(call_ppc_irq_dispatch_handler) mflr r0 std r0,16(r1) - stdu r1,THREAD_SIZE-112(r6) - mr r1,r6 - bl .handle_IRQ_event + stdu r1,THREAD_SIZE-112(r5) + mr r1,r5 + bl .ppc_irq_dispatch_handler ld r1,0(r1) ld r0,16(r1) mtlr r0 diff --git a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c index 87474584033..b61497d5be2 100644 --- a/arch/ppc64/kernel/irq.c +++ b/arch/ppc64/kernel/irq.c @@ -157,9 +157,6 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) int cpu = smp_processor_id(); irq_desc_t *desc = get_irq_desc(irq); irqreturn_t action_ret; -#ifdef CONFIG_IRQSTACKS - struct thread_info *curtp, *irqtp; -#endif kstat_cpu(cpu).irqs[irq]++; @@ -227,20 +224,7 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) for (;;) { spin_unlock(&desc->lock); -#ifdef CONFIG_IRQSTACKS - /* Switch to the irq stack to handle this */ - curtp = current_thread_info(); - irqtp = hardirq_ctx[smp_processor_id()]; - if (curtp != irqtp) { - irqtp->task = curtp->task; - irqtp->flags = 0; - action_ret = call_handle_IRQ_event(irq, regs, action, irqtp); - irqtp->task = NULL; - if (irqtp->flags) - set_bits(irqtp->flags, &curtp->flags); - } else -#endif - action_ret = handle_IRQ_event(irq, regs, action); + action_ret = handle_IRQ_event(irq, regs, action); spin_lock(&desc->lock); if (!noirqdebug) @@ -310,6 +294,9 @@ void do_IRQ(struct pt_regs *regs) void do_IRQ(struct pt_regs *regs) { int irq; +#ifdef CONFIG_IRQSTACKS + struct thread_info *curtp, *irqtp; +#endif irq_enter(); @@ -330,9 +317,22 @@ void do_IRQ(struct pt_regs *regs) irq = ppc_md.get_irq(regs); - if (irq >= 0) - ppc_irq_dispatch_handler(regs, irq); - else + if (irq >= 0) { +#ifdef CONFIG_IRQSTACKS + /* Switch to the irq stack to handle this */ + curtp = current_thread_info(); + irqtp = hardirq_ctx[smp_processor_id()]; + if (curtp != irqtp) { + irqtp->task = curtp->task; + irqtp->flags = 0; + call_ppc_irq_dispatch_handler(regs, irq, irqtp); + irqtp->task = NULL; + if (irqtp->flags) + set_bits(irqtp->flags, &curtp->flags); + } else +#endif + ppc_irq_dispatch_handler(regs, irq); + } else /* That's not SMP safe ... but who cares ? */ ppc_spurious_interrupts++; diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S index 914632ec587..d82a30dc26f 100644 --- a/arch/ppc64/kernel/misc.S +++ b/arch/ppc64/kernel/misc.S @@ -78,12 +78,12 @@ _GLOBAL(call_do_softirq) mtlr r0 blr -_GLOBAL(call_handle_IRQ_event) +_GLOBAL(call_ppc_irq_dispatch_handler) mflr r0 std r0,16(r1) - stdu r1,THREAD_SIZE-112(r6) - mr r1,r6 - bl .handle_IRQ_event + stdu r1,THREAD_SIZE-112(r5) + mr r1,r5 + bl .ppc_irq_dispatch_handler ld r1,0(r1) ld r0,16(r1) mtlr r0 diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h index b3935ea28ff..2a768e09606 100644 --- a/include/asm-powerpc/irq.h +++ b/include/asm-powerpc/irq.h @@ -488,8 +488,8 @@ extern struct thread_info *softirq_ctx[NR_CPUS]; extern void irq_ctx_init(void); extern void call_do_softirq(struct thread_info *tp); -extern int call_handle_IRQ_event(int irq, struct pt_regs *regs, - struct irqaction *action, struct thread_info *tp); +extern int call_ppc_irq_dispatch_handler(struct pt_regs *regs, int irq, + struct thread_info *tp); #define __ARCH_HAS_DO_SOFTIRQ -- cgit v1.2.3 From 5a7b3ff4670be3330842558dc5ae46ec3fc448e5 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Wed, 9 Nov 2005 15:07:16 +1100 Subject: ppc64: allow iSeries to use IRQSTACKS again Signed-off-by: Stephen Rothwell --- arch/powerpc/platforms/iseries/irq.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index a06603d84a4..a0ff7d95fdf 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c @@ -103,6 +103,9 @@ static void intReceived(struct XmPciLpEvent *eventParm, struct pt_regs *regsParm) { int irq; +#ifdef CONFIG_IRQSTACKS + struct thread_info *curtp, *irqtp; +#endif ++Pci_Interrupt_Count; @@ -110,7 +113,20 @@ static void intReceived(struct XmPciLpEvent *eventParm, case XmPciLpEvent_SlotInterrupt: irq = eventParm->hvLpEvent.xCorrelationToken; /* Dispatch the interrupt handlers for this irq */ - ppc_irq_dispatch_handler(regsParm, irq); +#ifdef CONFIG_IRQSTACKS + /* Switch to the irq stack to handle this */ + curtp = current_thread_info(); + irqtp = hardirq_ctx[smp_processor_id()]; + if (curtp != irqtp) { + irqtp->task = curtp->task; + irqtp->flags = 0; + call_ppc_irq_dispatch_handler(regsParm, irq, irqtp); + irqtp->task = NULL; + if (irqtp->flags) + set_bits(irqtp->flags, &curtp->flags); + } else +#endif + ppc_irq_dispatch_handler(regsParm, irq); HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber, eventParm->eventData.slotInterrupt.subBusNumber, eventParm->eventData.slotInterrupt.deviceId); -- cgit v1.2.3 From adba9e23b4066f1d741a2076fc6ad18b6c0cea44 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 8 Nov 2005 10:33:40 -0800 Subject: [PATCH] skge: clear PCI PHY COMA mode on boot When skge is booted up, the PHY may be stuck in power down state by the previous OS. So we may need to turn it on. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 10 ++++++++++ drivers/net/skge.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 572f121b1f4..fe806dbc191 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2893,6 +2893,7 @@ static const char *skge_board_name(const struct skge_hw *hw) */ static int skge_reset(struct skge_hw *hw) { + u32 reg; u16 ctst; u8 t8, mac_cfg, pmd_type, phy_type; int i; @@ -2971,6 +2972,7 @@ static int skge_reset(struct skge_hw *hw) /* switch power to VCC (WA for VAUX problem) */ skge_write8(hw, B0_POWER_CTRL, PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON); + /* avoid boards with stuck Hardware error bits */ if ((skge_read32(hw, B0_ISRC) & IS_HW_ERR) && (skge_read32(hw, B0_HWE_ISRC) & IS_IRQ_SENSOR)) { @@ -2978,6 +2980,14 @@ static int skge_reset(struct skge_hw *hw) hw->intr_mask &= ~IS_HW_ERR; } + /* Clear PHY COMA */ + skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); + pci_read_config_dword(hw->pdev, PCI_DEV_REG1, ®); + reg &= ~PCI_PHY_COMA; + pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg); + skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); + + for (i = 0; i < hw->ports; i++) { skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET); skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR); diff --git a/drivers/net/skge.h b/drivers/net/skge.h index 72c175b87a5..ee123c15f54 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h @@ -6,6 +6,8 @@ /* PCI config registers */ #define PCI_DEV_REG1 0x40 +#define PCI_PHY_COMA 0x8000000 +#define PCI_VIO 0x2000000 #define PCI_DEV_REG2 0x44 #define PCI_REV_DESC 0x4 -- cgit v1.2.3 From 7e86306113ca9e418e49ff1c7c0984f8ffe8cf61 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 8 Nov 2005 10:33:41 -0800 Subject: [PATCH] skge: use kzalloc Can use kzalloc in skge driver. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index fe806dbc191..f411c5c8041 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -3168,14 +3168,13 @@ static int __devinit skge_probe(struct pci_dev *pdev, #endif err = -ENOMEM; - hw = kmalloc(sizeof(*hw), GFP_KERNEL); + hw = kzalloc(sizeof(*hw), GFP_KERNEL); if (!hw) { printk(KERN_ERR PFX "%s: cannot allocate hardware struct\n", pci_name(pdev)); goto err_out_free_regions; } - memset(hw, 0, sizeof(*hw)); hw->pdev = pdev; spin_lock_init(&hw->phy_lock); tasklet_init(&hw->ext_tasklet, skge_extirq, (unsigned long) hw); -- cgit v1.2.3 From 2cd8e5d36584653c62a6fdf0e7d9fbde5022b5d6 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 8 Nov 2005 10:33:42 -0800 Subject: [PATCH] skge: add mii ioctl support Basic MII ioctl support for skge driver. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 172 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 114 insertions(+), 58 deletions(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index f411c5c8041..a1cfead5827 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include "skge.h" @@ -88,8 +89,8 @@ MODULE_DEVICE_TABLE(pci, skge_id_table); static int skge_up(struct net_device *dev); static int skge_down(struct net_device *dev); static void skge_tx_clean(struct skge_port *skge); -static void xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val); -static void gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val); +static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val); +static int gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val); static void genesis_get_stats(struct skge_port *skge, u64 *data); static void yukon_get_stats(struct skge_port *skge, u64 *data); static void yukon_init(struct skge_hw *hw, int port); @@ -883,32 +884,37 @@ static void skge_link_down(struct skge_port *skge) printk(KERN_INFO PFX "%s: Link is down.\n", skge->netdev->name); } -static u16 xm_phy_read(struct skge_hw *hw, int port, u16 reg) +static int __xm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val) { int i; - u16 v; xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr); - v = xm_read16(hw, port, XM_PHY_DATA); + xm_read16(hw, port, XM_PHY_DATA); /* Need to wait for external PHY */ for (i = 0; i < PHY_RETRIES; i++) { udelay(1); - if (xm_read16(hw, port, XM_MMU_CMD) - & XM_MMU_PHY_RDY) + if (xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_RDY) goto ready; } - printk(KERN_WARNING PFX "%s: phy read timed out\n", - hw->dev[port]->name); - return 0; + return -ETIMEDOUT; ready: - v = xm_read16(hw, port, XM_PHY_DATA); + *val = xm_read16(hw, port, XM_PHY_DATA); + return 0; +} + +static u16 xm_phy_read(struct skge_hw *hw, int port, u16 reg) +{ + u16 v = 0; + if (__xm_phy_read(hw, port, reg, &v)) + printk(KERN_WARNING PFX "%s: phy read timed out\n", + hw->dev[port]->name); return v; } -static void xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val) +static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val) { int i; @@ -918,19 +924,11 @@ static void xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val) goto ready; udelay(1); } - printk(KERN_WARNING PFX "%s: phy write failed to come ready\n", - hw->dev[port]->name); - + return -EIO; ready: xm_write16(hw, port, XM_PHY_DATA, val); - for (i = 0; i < PHY_RETRIES; i++) { - udelay(1); - if (!(xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY)) - return; - } - printk(KERN_WARNING PFX "%s: phy write timed out\n", - hw->dev[port]->name); + return 0; } static void genesis_init(struct skge_hw *hw) @@ -1400,42 +1398,6 @@ static void genesis_mac_intr(struct skge_hw *hw, int port) } } -static void gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val) -{ - int i; - - gma_write16(hw, port, GM_SMI_DATA, val); - gma_write16(hw, port, GM_SMI_CTRL, - GM_SMI_CT_PHY_AD(hw->phy_addr) | GM_SMI_CT_REG_AD(reg)); - for (i = 0; i < PHY_RETRIES; i++) { - udelay(1); - - if (!(gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY)) - break; - } -} - -static u16 gm_phy_read(struct skge_hw *hw, int port, u16 reg) -{ - int i; - - gma_write16(hw, port, GM_SMI_CTRL, - GM_SMI_CT_PHY_AD(hw->phy_addr) - | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD); - - for (i = 0; i < PHY_RETRIES; i++) { - udelay(1); - if (gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL) - goto ready; - } - - printk(KERN_WARNING PFX "%s: phy read timeout\n", - hw->dev[port]->name); - return 0; - ready: - return gma_read16(hw, port, GM_SMI_DATA); -} - static void genesis_link_up(struct skge_port *skge) { struct skge_hw *hw = skge->hw; @@ -1549,6 +1511,54 @@ static inline void bcom_phy_intr(struct skge_port *skge) } +static int gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val) +{ + int i; + + gma_write16(hw, port, GM_SMI_DATA, val); + gma_write16(hw, port, GM_SMI_CTRL, + GM_SMI_CT_PHY_AD(hw->phy_addr) | GM_SMI_CT_REG_AD(reg)); + for (i = 0; i < PHY_RETRIES; i++) { + udelay(1); + + if (!(gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY)) + return 0; + } + + printk(KERN_WARNING PFX "%s: phy write timeout\n", + hw->dev[port]->name); + return -EIO; +} + +static int __gm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val) +{ + int i; + + gma_write16(hw, port, GM_SMI_CTRL, + GM_SMI_CT_PHY_AD(hw->phy_addr) + | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD); + + for (i = 0; i < PHY_RETRIES; i++) { + udelay(1); + if (gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL) + goto ready; + } + + return -ETIMEDOUT; + ready: + *val = gma_read16(hw, port, GM_SMI_DATA); + return 0; +} + +static u16 gm_phy_read(struct skge_hw *hw, int port, u16 reg) +{ + u16 v = 0; + if (__gm_phy_read(hw, port, reg, &v)) + printk(KERN_WARNING PFX "%s: phy read timeout\n", + hw->dev[port]->name); + return v; +} + /* Marvell Phy Initailization */ static void yukon_init(struct skge_hw *hw, int port) { @@ -1997,6 +2007,51 @@ static void yukon_phy_intr(struct skge_port *skge) /* XXX restart autonegotiation? */ } +/* Basic MII support */ +static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + struct mii_ioctl_data *data = if_mii(ifr); + struct skge_port *skge = netdev_priv(dev); + struct skge_hw *hw = skge->hw; + int err = -EOPNOTSUPP; + + if (!netif_running(dev)) + return -ENODEV; /* Phy still in reset */ + + switch(cmd) { + case SIOCGMIIPHY: + data->phy_id = hw->phy_addr; + + /* fallthru */ + case SIOCGMIIREG: { + u16 val = 0; + spin_lock_bh(&hw->phy_lock); + if (hw->chip_id == CHIP_ID_GENESIS) + err = __xm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val); + else + err = __gm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val); + spin_unlock_bh(&hw->phy_lock); + data->val_out = val; + break; + } + + case SIOCSMIIREG: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + spin_lock_bh(&hw->phy_lock); + if (hw->chip_id == CHIP_ID_GENESIS) + err = xm_phy_write(hw, skge->port, data->reg_num & 0x1f, + data->val_in); + else + err = gm_phy_write(hw, skge->port, data->reg_num & 0x1f, + data->val_in); + spin_unlock_bh(&hw->phy_lock); + break; + } + return err; +} + static void skge_ramset(struct skge_hw *hw, u16 q, u32 start, size_t len) { u32 end; @@ -3058,6 +3113,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, SET_NETDEV_DEV(dev, &hw->pdev->dev); dev->open = skge_up; dev->stop = skge_down; + dev->do_ioctl = skge_ioctl; dev->hard_start_xmit = skge_xmit_frame; dev->get_stats = skge_get_stats; if (hw->chip_id == CHIP_ID_GENESIS) -- cgit v1.2.3 From 355ec57243574c439a4b731fc83af6165ec2f1ec Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 8 Nov 2005 10:33:43 -0800 Subject: [PATCH] skge: goto low power mode on shutdown Go into power down mode on shutdown. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index a1cfead5827..ea68d4d3d57 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -1804,6 +1804,25 @@ static void yukon_mac_init(struct skge_hw *hw, int port) skge_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); } +/* Go into power down mode */ +static void yukon_suspend(struct skge_hw *hw, int port) +{ + u16 ctrl; + + ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); + ctrl |= PHY_M_PC_POL_R_DIS; + gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); + + ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL); + ctrl |= PHY_CT_RESET; + gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); + + /* switch IEEE compatible power down mode on */ + ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL); + ctrl |= PHY_CT_PDOWN; + gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); +} + static void yukon_stop(struct skge_port *skge) { struct skge_hw *hw = skge->hw; @@ -1817,14 +1836,7 @@ static void yukon_stop(struct skge_port *skge) & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA)); gma_read16(hw, port, GM_GP_CTRL); - if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev >= CHIP_REV_YU_LITE_A3) { - u32 io = skge_read32(hw, B2_GP_IO); - - io |= GP_DIR_9 | GP_IO_9; - skge_write32(hw, B2_GP_IO, io); - skge_read32(hw, B2_GP_IO); - } + yukon_suspend(hw, port); /* set GPHY Control reset */ skge_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); -- cgit v1.2.3 From 1631aef15193ef8a199982fa3d45db4d07786d7f Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 8 Nov 2005 10:33:44 -0800 Subject: [PATCH] skge: use prefetch on receive Use prefetch() in the interrupt path to try and look ahead at the next place will be looking at in the ring. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index ea68d4d3d57..389d0be3586 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2627,7 +2627,7 @@ static int skge_poll(struct net_device *dev, int *budget) unsigned int to_do = min(dev->quota, *budget); unsigned int work_done = 0; - for (e = ring->to_clean; work_done < to_do; e = e->next) { + for (e = ring->to_clean; prefetch(e->next), work_done < to_do; e = e->next) { struct skge_rx_desc *rd = e->desc; struct sk_buff *skb; u32 control; @@ -2660,11 +2660,11 @@ static int skge_poll(struct net_device *dev, int *budget) if (work_done >= to_do) return 1; /* not done */ - local_irq_disable(); - __netif_rx_complete(dev); + netif_rx_complete(dev); hw->intr_mask |= portirqmask[skge->port]; skge_write32(hw, B0_IMSK, hw->intr_mask); - local_irq_enable(); + skge_read32(hw, B0_IMSK); + return 0; } @@ -2676,7 +2676,7 @@ static inline void skge_tx_intr(struct net_device *dev) struct skge_element *e; spin_lock(&skge->tx_lock); - for (e = ring->to_clean; e != ring->to_use; e = e->next) { + for (e = ring->to_clean; prefetch(e->next), e != ring->to_use; e = e->next) { struct skge_tx_desc *td = e->desc; u32 control; @@ -2829,6 +2829,14 @@ static void skge_extirq(unsigned long data) local_irq_enable(); } +static inline void skge_wakeup(struct net_device *dev) +{ + struct skge_port *skge = netdev_priv(dev); + + prefetch(skge->rx_ring.to_clean); + netif_rx_schedule(dev); +} + static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs) { struct skge_hw *hw = dev_id; @@ -2840,12 +2848,12 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs) status &= hw->intr_mask; if (status & IS_R1_F) { hw->intr_mask &= ~IS_R1_F; - netif_rx_schedule(hw->dev[0]); + skge_wakeup(hw->dev[0]); } if (status & IS_R2_F) { hw->intr_mask &= ~IS_R2_F; - netif_rx_schedule(hw->dev[1]); + skge_wakeup(hw->dev[1]); } if (status & IS_XA1_F) -- cgit v1.2.3 From 8f3f8193a49e1eb0d2e01309fdef2ad4fb33293c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 8 Nov 2005 10:33:45 -0800 Subject: [PATCH] skge: spelling fixes Fix some of my bad spelling. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 389d0be3586..df30274aad1 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -130,7 +130,7 @@ static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs, regs->len - B3_RI_WTO_R1); } -/* Wake on Lan only supported on Yukon chps with rev 1 or above */ +/* Wake on Lan only supported on Yukon chips with rev 1 or above */ static int wol_supported(const struct skge_hw *hw) { return !((hw->chip_id == CHIP_ID_GENESIS || @@ -170,8 +170,8 @@ static int skge_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) return 0; } -/* Determine supported/adverised modes based on hardware. - * Note: ethtoool ADVERTISED_xxx == SUPPORTED_xxx +/* Determine supported/advertised modes based on hardware. + * Note: ethtool ADVERTISED_xxx == SUPPORTED_xxx */ static u32 skge_supported_modes(const struct skge_hw *hw) { @@ -532,13 +532,13 @@ static inline u32 hwkhz(const struct skge_hw *hw) return 78215; /* or: 78.125 MHz */ } -/* Chip hz to microseconds */ +/* Chip HZ to microseconds */ static inline u32 skge_clk2usec(const struct skge_hw *hw, u32 ticks) { return (ticks * 1000) / hwkhz(hw); } -/* Microseconds to chip hz */ +/* Microseconds to chip HZ */ static inline u32 skge_usecs2clk(const struct skge_hw *hw, u32 usec) { return hwkhz(hw) * usec / 1000; @@ -1163,7 +1163,7 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo) xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, ext); xm_phy_write(hw, port, PHY_BCOM_CTRL, ctl); - /* Use link status change interrrupt */ + /* Use link status change interrupt */ xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK); bcom_check_link(hw, port); @@ -1203,7 +1203,7 @@ static void genesis_mac_init(struct skge_hw *hw, int port) skge_write32(hw, B2_GP_IO, r); skge_read32(hw, B2_GP_IO); - /* Enable GMII interfac */ + /* Enable GMII interface */ xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD); bcom_phy_init(skge, jumbo); @@ -1254,7 +1254,7 @@ static void genesis_mac_init(struct skge_hw *hw, int port) * that jumbo frames larger than 8192 bytes will be * truncated. Disabling all bad frame filtering causes * the RX FIFO to operate in streaming mode, in which - * case the XMAC will start transfering frames out of the + * case the XMAC will start transferring frames out of the * RX FIFO as soon as the FIFO threshold is reached. */ xm_write32(hw, port, XM_MODE, XM_DEF_MODE); @@ -1321,7 +1321,7 @@ static void genesis_stop(struct skge_port *skge) port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2); /* - * If the transfer stucks at the MAC the STOP command will not + * If the transfer sticks at the MAC the STOP command will not * terminate if we don't flush the XMAC's transmit FIFO ! */ xm_write32(hw, port, XM_MODE, @@ -1559,7 +1559,7 @@ static u16 gm_phy_read(struct skge_hw *hw, int port, u16 reg) return v; } -/* Marvell Phy Initailization */ +/* Marvell Phy Initialization */ static void yukon_init(struct skge_hw *hw, int port) { struct skge_port *skge = netdev_priv(hw->dev[port]); @@ -2156,7 +2156,7 @@ static int skge_up(struct net_device *dev) hw->intr_mask |= portirqmask[port]; skge_write32(hw, B0_IMSK, hw->intr_mask); - /* Initialze MAC */ + /* Initialize MAC */ spin_lock_bh(&hw->phy_lock); if (hw->chip_id == CHIP_ID_GENESIS) genesis_mac_init(hw, port); @@ -2476,7 +2476,7 @@ static void yukon_set_multicast(struct net_device *dev) reg = gma_read16(hw, port, GM_RX_CTRL); reg |= GM_RXCR_UCF_ENA; - if (dev->flags & IFF_PROMISC) /* promiscious */ + if (dev->flags & IFF_PROMISC) /* promiscuous */ reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); else if (dev->flags & IFF_ALLMULTI) /* all multicast */ memset(filter, 0xff, sizeof(filter)); @@ -2799,7 +2799,7 @@ static void skge_error_irq(struct skge_hw *hw) } /* - * Interrrupt from PHY are handled in tasklet (soft irq) + * Interrupt from PHY are handled in tasklet (soft irq) * because accessing phy registers requires spin wait which might * cause excess interrupt latency. */ @@ -3233,7 +3233,7 @@ static int __devinit skge_probe(struct pci_dev *pdev, } #ifdef __BIG_ENDIAN - /* byte swap decriptors in hardware */ + /* byte swap descriptors in hardware */ { u32 reg; -- cgit v1.2.3 From d7eaee087a8cb850ed33ee39a3e2a0f02ecff44c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 8 Nov 2005 10:33:46 -0800 Subject: [PATCH] skge: increase version number Increase the driver version number and print version when probing. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index df30274aad1..596c93b12da 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -43,7 +43,7 @@ #include "skge.h" #define DRV_NAME "skge" -#define DRV_VERSION "1.1" +#define DRV_VERSION "1.2" #define PFX DRV_NAME " " #define DEFAULT_TX_RING_SIZE 128 @@ -3273,7 +3273,7 @@ static int __devinit skge_probe(struct pci_dev *pdev, if (err) goto err_out_free_irq; - printk(KERN_INFO PFX "addr 0x%lx irq %d chip %s rev %d\n", + printk(KERN_INFO PFX DRV_VERSION " addr 0x%lx irq %d chip %s rev %d\n", pci_resource_start(pdev, 0), pdev->irq, skge_board_name(hw), hw->chip_rev); -- cgit v1.2.3 From d4be4f37d9d2a5afc8e79a95beafbac4b83f20c5 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Wed, 9 Nov 2005 16:19:53 +1100 Subject: ppc64: remove ppc_irq_dispatch_handler Use __do_IRQ instead. The only difference is that every controller is now assumed to have an end() routine (only xics_8259 did not). Signed-off-by: Stephen Rothwell --- arch/powerpc/kernel/misc_64.S | 4 +- arch/powerpc/platforms/iseries/irq.c | 10 ++-- arch/powerpc/platforms/pseries/xics.c | 1 + arch/ppc64/kernel/irq.c | 108 +--------------------------------- arch/ppc64/kernel/misc.S | 4 +- include/asm-powerpc/hw_irq.h | 1 - include/asm-powerpc/irq.h | 2 +- 7 files changed, 12 insertions(+), 118 deletions(-) diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index 9d09f0ad6ef..ae48a002f81 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -89,12 +89,12 @@ _GLOBAL(call_do_softirq) mtlr r0 blr -_GLOBAL(call_ppc_irq_dispatch_handler) +_GLOBAL(call___do_IRQ) mflr r0 std r0,16(r1) stdu r1,THREAD_SIZE-112(r5) mr r1,r5 - bl .ppc_irq_dispatch_handler + bl .__do_IRQ ld r1,0(r1) ld r0,16(r1) mtlr r0 diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index a0ff7d95fdf..01090e9ce0c 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c @@ -120,13 +120,13 @@ static void intReceived(struct XmPciLpEvent *eventParm, if (curtp != irqtp) { irqtp->task = curtp->task; irqtp->flags = 0; - call_ppc_irq_dispatch_handler(regsParm, irq, irqtp); + call___do_IRQ(irq, regsParm, irqtp); irqtp->task = NULL; if (irqtp->flags) set_bits(irqtp->flags, &curtp->flags); } else #endif - ppc_irq_dispatch_handler(regsParm, irq); + __do_IRQ(irq, regsParm); HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber, eventParm->eventData.slotInterrupt.subBusNumber, eventParm->eventData.slotInterrupt.deviceId); @@ -326,10 +326,8 @@ static void iSeries_disable_IRQ(unsigned int irq) } /* - * Need to define this so ppc_irq_dispatch_handler will NOT call - * enable_IRQ at the end of interrupt handling. However, this does - * nothing because there is not enough information provided to do - * the EOI HvCall. This is done by XmPciLpEvent.c + * This does nothing because there is not enough information + * provided to do the EOI HvCall. This is done by XmPciLpEvent.c */ static void iSeries_end_IRQ(unsigned int irq) { diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index c72c86f05cb..405c4f3229b 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -567,6 +567,7 @@ nextnode: xics_8259_pic.enable = i8259_pic.enable; xics_8259_pic.disable = i8259_pic.disable; + xics_8259_pic.end = i8259_pic.end; for (i = 0; i < 16; ++i) get_irq_desc(i)->handler = &xics_8259_pic; for (; i < NR_IRQS; ++i) diff --git a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c index b61497d5be2..bd6a95a5914 100644 --- a/arch/ppc64/kernel/irq.c +++ b/arch/ppc64/kernel/irq.c @@ -144,110 +144,6 @@ void fixup_irqs(cpumask_t map) } #endif -extern int noirqdebug; - -/* - * Eventually, this should take an array of interrupts and an array size - * so it can dispatch multiple interrupts. - */ -void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) -{ - int status; - struct irqaction *action; - int cpu = smp_processor_id(); - irq_desc_t *desc = get_irq_desc(irq); - irqreturn_t action_ret; - - kstat_cpu(cpu).irqs[irq]++; - - if (desc->status & IRQ_PER_CPU) { - /* no locking required for CPU-local interrupts: */ - ack_irq(irq); - action_ret = handle_IRQ_event(irq, regs, desc->action); - desc->handler->end(irq); - return; - } - - spin_lock(&desc->lock); - ack_irq(irq); - /* - REPLAY is when Linux resends an IRQ that was dropped earlier - WAITING is used by probe to mark irqs that are being tested - */ - status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); - status |= IRQ_PENDING; /* we _want_ to handle it */ - - /* - * If the IRQ is disabled for whatever reason, we cannot - * use the action we have. - */ - action = NULL; - if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) { - action = desc->action; - if (!action || !action->handler) { - ppc_spurious_interrupts++; - printk(KERN_DEBUG "Unhandled interrupt %x, disabled\n", irq); - /* We can't call disable_irq here, it would deadlock */ - if (!desc->depth) - desc->depth = 1; - desc->status |= IRQ_DISABLED; - /* This is not a real spurrious interrupt, we - * have to eoi it, so we jump to out - */ - mask_irq(irq); - goto out; - } - status &= ~IRQ_PENDING; /* we commit to handling */ - status |= IRQ_INPROGRESS; /* we are handling it */ - } - desc->status = status; - - /* - * If there is no IRQ handler or it was disabled, exit early. - Since we set PENDING, if another processor is handling - a different instance of this same irq, the other processor - will take care of it. - */ - if (unlikely(!action)) - goto out; - - /* - * Edge triggered interrupts need to remember - * pending events. - * This applies to any hw interrupts that allow a second - * instance of the same irq to arrive while we are in do_IRQ - * or in the handler. But the code here only handles the _second_ - * instance of the irq, not the third or fourth. So it is mostly - * useful for irq hardware that does not mask cleanly in an - * SMP environment. - */ - for (;;) { - spin_unlock(&desc->lock); - - action_ret = handle_IRQ_event(irq, regs, action); - - spin_lock(&desc->lock); - if (!noirqdebug) - note_interrupt(irq, desc, action_ret, regs); - if (likely(!(desc->status & IRQ_PENDING))) - break; - desc->status &= ~IRQ_PENDING; - } -out: - desc->status &= ~IRQ_INPROGRESS; - /* - * The ->end() handler has to deal with interrupts which got - * disabled while the handler was running. - */ - if (desc->handler) { - if (desc->handler->end) - desc->handler->end(irq); - else if (desc->handler->enable) - desc->handler->enable(irq); - } - spin_unlock(&desc->lock); -} - #ifdef CONFIG_PPC_ISERIES void do_IRQ(struct pt_regs *regs) { @@ -325,13 +221,13 @@ void do_IRQ(struct pt_regs *regs) if (curtp != irqtp) { irqtp->task = curtp->task; irqtp->flags = 0; - call_ppc_irq_dispatch_handler(regs, irq, irqtp); + call___do_IRQ(irq, regs, irqtp); irqtp->task = NULL; if (irqtp->flags) set_bits(irqtp->flags, &curtp->flags); } else #endif - ppc_irq_dispatch_handler(regs, irq); + __do_IRQ(irq, regs); } else /* That's not SMP safe ... but who cares ? */ ppc_spurious_interrupts++; diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S index d82a30dc26f..492bca6137e 100644 --- a/arch/ppc64/kernel/misc.S +++ b/arch/ppc64/kernel/misc.S @@ -78,12 +78,12 @@ _GLOBAL(call_do_softirq) mtlr r0 blr -_GLOBAL(call_ppc_irq_dispatch_handler) +_GLOBAL(call___do_IRQ) mflr r0 std r0,16(r1) stdu r1,THREAD_SIZE-112(r5) mr r1,r5 - bl .ppc_irq_dispatch_handler + bl .__do_IRQ ld r1,0(r1) ld r0,16(r1) mtlr r0 diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h index c37b31b9633..26b89d859c5 100644 --- a/include/asm-powerpc/hw_irq.h +++ b/include/asm-powerpc/hw_irq.h @@ -12,7 +12,6 @@ #include extern void timer_interrupt(struct pt_regs *); -extern void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq); #ifdef CONFIG_PPC_ISERIES diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h index 2a768e09606..225dc182ef3 100644 --- a/include/asm-powerpc/irq.h +++ b/include/asm-powerpc/irq.h @@ -488,7 +488,7 @@ extern struct thread_info *softirq_ctx[NR_CPUS]; extern void irq_ctx_init(void); extern void call_do_softirq(struct thread_info *tp); -extern int call_ppc_irq_dispatch_handler(struct pt_regs *regs, int irq, +extern int call___do_IRQ(int irq, struct pt_regs *regs, struct thread_info *tp); #define __ARCH_HAS_DO_SOFTIRQ -- cgit v1.2.3 From c2a8fad43376b2567087358a9cc46844f742342e Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 9 Nov 2005 00:49:38 -0500 Subject: [wireless ipw2100] kill unused-var warnings for debug-disabled code --- drivers/net/wireless/ipw2100.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 877ac514aa0..a2e6214169e 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -3748,6 +3748,8 @@ static ssize_t store_memory(struct device *d, struct device_attribute *attr, struct net_device *dev = priv->net_dev; const char *p = buf; + (void) dev; /* kill unused-var warning for debug-only code */ + if (count < 1) return count; @@ -4066,6 +4068,8 @@ static ssize_t store_scan_age(struct device *d, struct device_attribute *attr, unsigned long val; char *p = buffer; + (void) dev; /* kill unused-var warning for debug-only code */ + IPW_DEBUG_INFO("enter\n"); strncpy(buffer, buf, len); -- cgit v1.2.3 From e3305626e0985faa8796f1f4e5a99c1f40bfa70e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 9 Nov 2005 01:01:04 -0500 Subject: ieee80211: cleanup crypto list handling, other minor cleanups. --- include/net/ieee80211_crypt.h | 1 + net/ieee80211/ieee80211_crypt.c | 152 +++++++++++----------------------------- 2 files changed, 42 insertions(+), 111 deletions(-) diff --git a/include/net/ieee80211_crypt.h b/include/net/ieee80211_crypt.h index 0a1c2d82ca4..225fc751d46 100644 --- a/include/net/ieee80211_crypt.h +++ b/include/net/ieee80211_crypt.h @@ -31,6 +31,7 @@ enum { struct ieee80211_crypto_ops { const char *name; + struct list_head list; /* init new crypto context (e.g., allocate private data space, * select IV, etc.); returns NULL on failure or pointer to allocated diff --git a/net/ieee80211/ieee80211_crypt.c b/net/ieee80211/ieee80211_crypt.c index 20cc580a07e..ecc9bb196ab 100644 --- a/net/ieee80211/ieee80211_crypt.c +++ b/net/ieee80211/ieee80211_crypt.c @@ -11,15 +11,14 @@ * */ -#include +#include #include #include #include -#include -#include - +#include #include + MODULE_AUTHOR("Jouni Malinen"); MODULE_DESCRIPTION("HostAP crypto"); MODULE_LICENSE("GPL"); @@ -29,32 +28,20 @@ struct ieee80211_crypto_alg { struct ieee80211_crypto_ops *ops; }; -struct ieee80211_crypto { - struct list_head algs; - spinlock_t lock; -}; - -static struct ieee80211_crypto *hcrypt; +static LIST_HEAD(ieee80211_crypto_algs); +static DEFINE_SPINLOCK(ieee80211_crypto_lock); void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force) { - struct list_head *ptr, *n; - struct ieee80211_crypt_data *entry; + struct ieee80211_crypt_data *entry, *next; unsigned long flags; spin_lock_irqsave(&ieee->lock, flags); - - if (list_empty(&ieee->crypt_deinit_list)) - goto unlock; - - for (ptr = ieee->crypt_deinit_list.next, n = ptr->next; - ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) { - entry = list_entry(ptr, struct ieee80211_crypt_data, list); - + list_for_each_entry_safe(entry, next, &ieee->crypt_deinit_list, list) { if (atomic_read(&entry->refcnt) != 0 && !force) continue; - list_del(ptr); + list_del(&entry->list); if (entry->ops) { entry->ops->deinit(entry->priv); @@ -62,7 +49,6 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force) } kfree(entry); } - unlock: spin_unlock_irqrestore(&ieee->lock, flags); } @@ -125,9 +111,6 @@ int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops) unsigned long flags; struct ieee80211_crypto_alg *alg; - if (hcrypt == NULL) - return -1; - alg = kmalloc(sizeof(*alg), GFP_KERNEL); if (alg == NULL) return -ENOMEM; @@ -135,9 +118,9 @@ int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops) memset(alg, 0, sizeof(*alg)); alg->ops = ops; - spin_lock_irqsave(&hcrypt->lock, flags); - list_add(&alg->list, &hcrypt->algs); - spin_unlock_irqrestore(&hcrypt->lock, flags); + spin_lock_irqsave(&ieee80211_crypto_lock, flags); + list_add(&alg->list, &ieee80211_crypto_algs); + spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); printk(KERN_DEBUG "ieee80211_crypt: registered algorithm '%s'\n", ops->name); @@ -147,64 +130,49 @@ int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops) int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops) { + struct ieee80211_crypto_alg *alg; unsigned long flags; - struct list_head *ptr; - struct ieee80211_crypto_alg *del_alg = NULL; - - if (hcrypt == NULL) - return -1; - - spin_lock_irqsave(&hcrypt->lock, flags); - for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) { - struct ieee80211_crypto_alg *alg = - (struct ieee80211_crypto_alg *)ptr; - if (alg->ops == ops) { - list_del(&alg->list); - del_alg = alg; - break; - } - } - spin_unlock_irqrestore(&hcrypt->lock, flags); - if (del_alg) { - printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm " - "'%s'\n", ops->name); - kfree(del_alg); + spin_lock_irqsave(&ieee80211_crypto_lock, flags); + list_for_each_entry(alg, &ieee80211_crypto_algs, list) { + if (alg->ops == ops) + goto found; } - - return del_alg ? 0 : -1; + spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); + return -EINVAL; + + found: + printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm " + "'%s'\n", ops->name); + list_del(&alg->list); + spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); + kfree(alg); + return 0; } struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name) { + struct ieee80211_crypto_alg *alg; unsigned long flags; - struct list_head *ptr; - struct ieee80211_crypto_alg *found_alg = NULL; - - if (hcrypt == NULL) - return NULL; - - spin_lock_irqsave(&hcrypt->lock, flags); - for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) { - struct ieee80211_crypto_alg *alg = - (struct ieee80211_crypto_alg *)ptr; - if (strcmp(alg->ops->name, name) == 0) { - found_alg = alg; - break; - } + + spin_lock_irqsave(&ieee80211_crypto_lock, flags); + list_for_each_entry(alg, &ieee80211_crypto_algs, list) { + if (strcmp(alg->ops->name, name) == 0) + goto found; } - spin_unlock_irqrestore(&hcrypt->lock, flags); + spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); + return NULL; - if (found_alg) - return found_alg->ops; - else - return NULL; + found: + spin_unlock_irqrestore(&ieee80211_crypto_lock, flags); + return alg->ops; } static void *ieee80211_crypt_null_init(int keyidx) { return (void *)1; } + static void ieee80211_crypt_null_deinit(void *priv) { } @@ -213,56 +181,18 @@ static struct ieee80211_crypto_ops ieee80211_crypt_null = { .name = "NULL", .init = ieee80211_crypt_null_init, .deinit = ieee80211_crypt_null_deinit, - .encrypt_mpdu = NULL, - .decrypt_mpdu = NULL, - .encrypt_msdu = NULL, - .decrypt_msdu = NULL, - .set_key = NULL, - .get_key = NULL, - .extra_mpdu_prefix_len = 0, - .extra_mpdu_postfix_len = 0, .owner = THIS_MODULE, }; static int __init ieee80211_crypto_init(void) { - int ret = -ENOMEM; - - hcrypt = kmalloc(sizeof(*hcrypt), GFP_KERNEL); - if (!hcrypt) - goto out; - - memset(hcrypt, 0, sizeof(*hcrypt)); - INIT_LIST_HEAD(&hcrypt->algs); - spin_lock_init(&hcrypt->lock); - - ret = ieee80211_register_crypto_ops(&ieee80211_crypt_null); - if (ret < 0) { - kfree(hcrypt); - hcrypt = NULL; - } - out: - return ret; + return ieee80211_register_crypto_ops(&ieee80211_crypt_null); } static void __exit ieee80211_crypto_deinit(void) { - struct list_head *ptr, *n; - - if (hcrypt == NULL) - return; - - for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs; - ptr = n, n = ptr->next) { - struct ieee80211_crypto_alg *alg = - (struct ieee80211_crypto_alg *)ptr; - list_del(ptr); - printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm " - "'%s' (deinit)\n", alg->ops->name); - kfree(alg); - } - - kfree(hcrypt); + ieee80211_unregister_crypto_ops(&ieee80211_crypt_null); + BUG_ON(!list_empty(&ieee80211_crypto_algs)); } EXPORT_SYMBOL(ieee80211_crypt_deinit_entries); -- cgit v1.2.3 From b9dcbb40f40d60c7e33a2b7ea858fcd27c35cc00 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Tue, 8 Nov 2005 23:36:20 +0100 Subject: [PATCH] b44: replace B44_FLAG_INIT_COMPLETE with netif_running() Signed-off-by: Francois Romieu Signed-off-by: Jeff Garzik --- drivers/net/b44.c | 6 ++---- drivers/net/b44.h | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/b44.c b/drivers/net/b44.c index ecc2e32c38c..f1675dcf4d5 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1392,7 +1392,6 @@ static int b44_open(struct net_device *dev) b44_init_rings(bp); b44_init_hw(bp); - bp->flags |= B44_FLAG_INIT_COMPLETE; netif_carrier_off(dev); b44_check_phy(bp); @@ -1456,7 +1455,6 @@ static int b44_close(struct net_device *dev) #endif b44_halt(bp); b44_free_rings(bp); - bp->flags &= ~B44_FLAG_INIT_COMPLETE; netif_carrier_off(bp->dev); spin_unlock_irq(&bp->lock); @@ -1608,7 +1606,7 @@ static int b44_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct b44 *bp = netdev_priv(dev); - if (!(bp->flags & B44_FLAG_INIT_COMPLETE)) + if (!netif_running(dev)) return -EAGAIN; cmd->supported = (SUPPORTED_Autoneg); cmd->supported |= (SUPPORTED_100baseT_Half | @@ -1646,7 +1644,7 @@ static int b44_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct b44 *bp = netdev_priv(dev); - if (!(bp->flags & B44_FLAG_INIT_COMPLETE)) + if (!netif_running(dev)) return -EAGAIN; /* We do not support gigabit. */ diff --git a/drivers/net/b44.h b/drivers/net/b44.h index 7afeaf60823..b178662978f 100644 --- a/drivers/net/b44.h +++ b/drivers/net/b44.h @@ -420,7 +420,6 @@ struct b44 { u32 dma_offset; u32 flags; -#define B44_FLAG_INIT_COMPLETE 0x00000001 #define B44_FLAG_BUGGY_TXPTR 0x00000002 #define B44_FLAG_REORDER_BUG 0x00000004 #define B44_FLAG_PAUSE_AUTO 0x00008000 -- cgit v1.2.3 From ba5eec9c55ec4be99d21a6ea614003b65d7f37d7 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Tue, 8 Nov 2005 23:37:12 +0100 Subject: [PATCH] b44: race on device closing Usual fix: - b44_interrupt() does not schedule NAPI polling when the device is going down; - b44_close() waits for any scheduled NAPI polling before it starts to release the private structures of the device. Signed-off-by: Francois Romieu Signed-off-by: Jeff Garzik --- drivers/net/b44.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/b44.c b/drivers/net/b44.c index f1675dcf4d5..e829beea668 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -909,6 +909,12 @@ static irqreturn_t b44_interrupt(int irq, void *dev_id, struct pt_regs *regs) istat &= imask; if (istat) { handled = 1; + + if (unlikely(!netif_running(dev))) { + printk(KERN_INFO "%s: late interrupt.\n", dev->name); + goto irq_ack; + } + if (netif_rx_schedule_prep(dev)) { /* NOTE: These writes are posted by the readback of * the ISTAT register below. @@ -921,6 +927,7 @@ static irqreturn_t b44_interrupt(int irq, void *dev_id, struct pt_regs *regs) dev->name); } +irq_ack: bw32(bp, B44_ISTAT, istat); br32(bp, B44_ISTAT); } @@ -1446,6 +1453,8 @@ static int b44_close(struct net_device *dev) netif_stop_queue(dev); + netif_poll_disable(dev); + del_timer_sync(&bp->timer); spin_lock_irq(&bp->lock); @@ -1461,6 +1470,8 @@ static int b44_close(struct net_device *dev) free_irq(dev->irq, dev); + netif_poll_enable(dev); + b44_free_consistent(bp); return 0; -- cgit v1.2.3 From eac1dfcb32fbe8b0d9135caea90b0bba9945360f Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Tue, 8 Nov 2005 23:38:01 +0100 Subject: [PATCH] b44: increase version number Signed-off-by: Francois Romieu Signed-off-by: Jeff Garzik --- drivers/net/b44.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/b44.c b/drivers/net/b44.c index e829beea668..b38fa245a60 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -29,8 +29,8 @@ #define DRV_MODULE_NAME "b44" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "0.95" -#define DRV_MODULE_RELDATE "Aug 3, 2004" +#define DRV_MODULE_VERSION "0.96" +#define DRV_MODULE_RELDATE "Nov 8, 2005" #define B44_DEF_MSG_ENABLE \ (NETIF_MSG_DRV | \ -- cgit v1.2.3 From 76f2b4d98c3d6a88a260275acbede99c23a24d60 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 06:18:57 +0100 Subject: [PATCH] cris v10 eth: use ethtool_ops Signed-off-by: Christoph Hellwig Signed-off-by: Jeff Garzik --- drivers/net/cris/eth_v10.c | 149 +++++++++++++++++++++------------------------ 1 file changed, 71 insertions(+), 78 deletions(-) diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c index b68b9cad76e..64105e4eaf3 100644 --- a/drivers/net/cris/eth_v10.c +++ b/drivers/net/cris/eth_v10.c @@ -409,7 +409,6 @@ static irqreturn_t e100nw_interrupt(int irq, void *dev_id, struct pt_regs *regs) static void e100_rx(struct net_device *dev); static int e100_close(struct net_device *dev); static int e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); -static int e100_ethtool_ioctl(struct net_device* dev, struct ifreq *ifr); static int e100_set_config(struct net_device* dev, struct ifmap* map); static void e100_tx_timeout(struct net_device *dev); static struct net_device_stats *e100_get_stats(struct net_device *dev); @@ -436,6 +435,8 @@ static void e100_reset_transceiver(struct net_device* net); static void e100_clear_network_leds(unsigned long dummy); static void e100_set_network_leds(int active); +static struct ethtool_ops e100_ethtool_ops; + static void broadcom_check_speed(struct net_device* dev); static void broadcom_check_duplex(struct net_device* dev); static void tdk_check_speed(struct net_device* dev); @@ -495,6 +496,7 @@ etrax_ethernet_init(void) dev->get_stats = e100_get_stats; dev->set_multicast_list = set_multicast_list; dev->set_mac_address = e100_set_mac_address; + dev->ethtool_ops = &e100_ethtool_ops; dev->do_ioctl = e100_ioctl; dev->set_config = e100_set_config; dev->tx_timeout = e100_tx_timeout; @@ -1448,8 +1450,6 @@ e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) spin_lock(&np->lock); /* Preempt protection */ switch (cmd) { - case SIOCETHTOOL: - return e100_ethtool_ioctl(dev,ifr); case SIOCGMIIPHY: /* Get PHY address */ data->phy_id = mdio_phy_addr; break; @@ -1486,88 +1486,81 @@ e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return 0; } -static int -e100_ethtool_ioctl(struct net_device *dev, struct ifreq *ifr) +static int e100_set_settings(struct net_device *dev, + struct ethtool_cmd *ecmd) { - struct ethtool_cmd ecmd; - - if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd))) - return -EFAULT; - - switch (ecmd.cmd) { - case ETHTOOL_GSET: - { - memset((void *) &ecmd, 0, sizeof (ecmd)); - ecmd.supported = - SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII | + ecmd->supported = SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full; - ecmd.port = PORT_TP; - ecmd.transceiver = XCVR_EXTERNAL; - ecmd.phy_address = mdio_phy_addr; - ecmd.speed = current_speed; - ecmd.duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF; - ecmd.advertising = ADVERTISED_TP; - if (current_duplex == autoneg && current_speed_selection == 0) - ecmd.advertising |= ADVERTISED_Autoneg; - else { - ecmd.advertising |= - ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full; - if (current_speed_selection == 10) - ecmd.advertising &= ~(ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full); - else if (current_speed_selection == 100) - ecmd.advertising &= ~(ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full); - if (current_duplex == half) - ecmd.advertising &= ~(ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Full); - else if (current_duplex == full) - ecmd.advertising &= ~(ADVERTISED_10baseT_Half | ADVERTISED_100baseT_Half); - } - ecmd.autoneg = AUTONEG_ENABLE; - if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd))) - return -EFAULT; - } - break; - case ETHTOOL_SSET: - { - if (!capable(CAP_NET_ADMIN)) { - return -EPERM; - } - if (ecmd.autoneg == AUTONEG_ENABLE) { - e100_set_duplex(dev, autoneg); - e100_set_speed(dev, 0); - } else { - e100_set_duplex(dev, ecmd.duplex == DUPLEX_HALF ? half : full); - e100_set_speed(dev, ecmd.speed == SPEED_10 ? 10: 100); - } - } - break; - case ETHTOOL_GDRVINFO: - { - struct ethtool_drvinfo info; - memset((void *) &info, 0, sizeof (info)); - strncpy(info.driver, "ETRAX 100LX", sizeof(info.driver) - 1); - strncpy(info.version, "$Revision: 1.31 $", sizeof(info.version) - 1); - strncpy(info.fw_version, "N/A", sizeof(info.fw_version) - 1); - strncpy(info.bus_info, "N/A", sizeof(info.bus_info) - 1); - info.regdump_len = 0; - info.eedump_len = 0; - info.testinfo_len = 0; - if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) - return -EFAULT; - } - break; - case ETHTOOL_NWAY_RST: - if (current_duplex == autoneg && current_speed_selection == 0) - e100_negotiate(dev); - break; - default: - return -EOPNOTSUPP; - break; + ecmd->port = PORT_TP; + ecmd->transceiver = XCVR_EXTERNAL; + ecmd->phy_address = mdio_phy_addr; + ecmd->speed = current_speed; + ecmd->duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF; + ecmd->advertising = ADVERTISED_TP; + + if (current_duplex == autoneg && current_speed_selection == 0) + ecmd->advertising |= ADVERTISED_Autoneg; + else { + ecmd->advertising |= + ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full; + if (current_speed_selection == 10) + ecmd->advertising &= ~(ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full); + else if (current_speed_selection == 100) + ecmd->advertising &= ~(ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full); + if (current_duplex == half) + ecmd->advertising &= ~(ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Full); + else if (current_duplex == full) + ecmd->advertising &= ~(ADVERTISED_10baseT_Half | + ADVERTISED_100baseT_Half); + } + + ecmd->autoneg = AUTONEG_ENABLE; + return 0; +} + +static int e100_set_settings(struct net_device *dev, + struct ethtool_cmd *ecmd) +{ + if (ecmd->autoneg == AUTONEG_ENABLE) { + e100_set_duplex(dev, autoneg); + e100_set_speed(dev, 0); + } else { + e100_set_duplex(dev, ecmd->duplex == DUPLEX_HALF ? half : full); + e100_set_speed(dev, ecmd->speed == SPEED_10 ? 10: 100); } + + return 0; +} + +static void e100_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + strncpy(info->driver, "ETRAX 100LX", sizeof(info->driver) - 1); + strncpy(info->version, "$Revision: 1.31 $", sizeof(info->version) - 1); + strncpy(info->fw_version, "N/A", sizeof(info->fw_version) - 1); + strncpy(info->bus_info, "N/A", sizeof(info->bus_info) - 1); +} + +static int e100_nway_reset(struct net_device *dev) +{ + if (current_duplex == autoneg && current_speed_selection == 0) + e100_negotiate(dev); return 0; } +static struct ethtool_ops e100_ethtool_ops = { + .get_settings = e100_get_settings, + .set_settings = e100_set_settings, + .get_drvinfo = e100_get_drvinfo, + .nway_reset = e100_nway_reset, + .get_link = ethtool_op_get_link, +}; + static int e100_set_config(struct net_device *dev, struct ifmap *map) { -- cgit v1.2.3 From d3757472841cddfa2f905d1de76fabf1b98cfc1a Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 06:20:36 +0100 Subject: [PATCH] xtensa platform-iss network: remove no-op ioctl handler If the driver ever wants to add ethtool support it should use ethtool_ops. Signed-off-by: Christoph Hellwig Signed-off-by: Jeff Garzik --- arch/xtensa/platform-iss/network.c | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/arch/xtensa/platform-iss/network.c b/arch/xtensa/platform-iss/network.c index 0682ffd3817..96b9bb4a478 100644 --- a/arch/xtensa/platform-iss/network.c +++ b/arch/xtensa/platform-iss/network.c @@ -611,38 +611,6 @@ static int iss_net_change_mtu(struct net_device *dev, int new_mtu) return -EINVAL; } -static int iss_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ -#if 0 - static const struct ethtool_drvinfo info = { - .cmd = ETHTOOL_GDRVINFO, - .driver = DRIVER_NAME, - .version = "42", - }; - void *useraddr; - u32 ethcmd; - - switch (cmd) { - case SIOCETHTOOL: - useraddr = ifr->ifr_data; - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - default: - return -EOPNOTSUPP; - } - default: - return -EINVAL; - } -#endif - return -EINVAL; -} - void iss_net_user_timer_expire(unsigned long _conn) { } @@ -730,7 +698,6 @@ static int iss_net_configure(int index, char *init) dev->tx_timeout = iss_net_tx_timeout; dev->set_mac_address = iss_net_set_mac; dev->change_mtu = iss_net_change_mtu; - dev->do_ioctl = iss_net_ioctl; dev->watchdog_timeo = (HZ >> 1); dev->irq = -1; -- cgit v1.2.3 From 6d3874844f3279f170dca5339b8a94d6f1868425 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 06:21:21 +0100 Subject: [PATCH] uml_net: use ethtool_ops Signed-off-by: Christoph Hellwig Signed-off-by: Jeff Garzik --- arch/um/drivers/net_kern.c | 38 +++++++++++--------------------------- 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index fe865d9a372..4cf31a2ae19 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -243,34 +243,18 @@ static int uml_net_change_mtu(struct net_device *dev, int new_mtu) return err; } -static int uml_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - static const struct ethtool_drvinfo info = { - .cmd = ETHTOOL_GDRVINFO, - .driver = DRIVER_NAME, - .version = "42", - }; - void *useraddr; - u32 ethcmd; - - switch (cmd) { - case SIOCETHTOOL: - useraddr = ifr->ifr_data; - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; - switch (ethcmd) { - case ETHTOOL_GDRVINFO: - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - default: - return -EOPNOTSUPP; - } - default: - return -EINVAL; - } +static void uml_net_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + strcpy(info->driver, DRIVER_NAME); + strcpy(info->version, "42"); } +static struct ethtool_ops uml_net_ethtool_ops = { + .get_drvinfo = uml_net_get_drvinfo, + .get_link = ethtool_op_get_link, +}; + void uml_net_user_timer_expire(unsigned long _conn) { #ifdef undef @@ -359,7 +343,7 @@ static int eth_configure(int n, void *init, char *mac, dev->tx_timeout = uml_net_tx_timeout; dev->set_mac_address = uml_net_set_mac; dev->change_mtu = uml_net_change_mtu; - dev->do_ioctl = uml_net_ioctl; + dev->ethtool_ops = ¨_net_ethtool_ops; dev->watchdog_timeo = (HZ >> 1); dev->irq = UM_ETH_IRQ; -- cgit v1.2.3 From 8e8b77dd4846b73f2e0756cf59123ee709246d11 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 1 Nov 2005 21:29:27 -0800 Subject: [PATCH] libata kernel-doc fixes Fix all reported kernel-doc errors in libata. Signed-off-by: Randy Dunlap Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 4 ++-- drivers/scsi/libata-scsi.c | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 98769a3d31a..f1942545a20 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2713,7 +2713,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) /** * ata_poll_qc_complete - turn irq back on and finish qc * @qc: Command to complete - * @drv_stat: ATA status register content + * @err_mask: ATA status register content * * LOCKING: * None. (grabs host lock) @@ -3478,7 +3478,7 @@ void ata_qc_free(struct ata_queued_cmd *qc) /** * ata_qc_complete - Complete an active ATA command * @qc: Command to complete - * @drv_stat: ATA Status register contents + * @err_mask: ATA Status register contents * * Indicate to the mid and upper layers that an ATA * command has completed, with either an ok or not-ok status. diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 38a895ebe82..bb30fcdc929 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -131,7 +131,7 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev, /** * ata_cmd_ioctl - Handler for HDIO_DRIVE_CMD ioctl - * @dev: Device to whom we are issuing command + * @scsidev: Device to which we are issuing command * @arg: User provided data for issuing command * * LOCKING: @@ -217,7 +217,7 @@ error: /** * ata_task_ioctl - Handler for HDIO_DRIVE_TASK ioctl - * @dev: Device to whom we are issuing command + * @scsidev: Device to which we are issuing command * @arg: User provided data for issuing command * * LOCKING: @@ -416,6 +416,7 @@ void ata_dump_status(unsigned id, struct ata_taskfile *tf) /** * ata_to_sense_error - convert ATA error to SCSI error + * @id: ATA device number * @drv_stat: value contained in ATA status register * @drv_err: value contained in ATA error register * @sk: the sense key we'll fill out @@ -2231,7 +2232,7 @@ ata_scsi_map_proto(u8 byte1) /** * ata_scsi_pass_thru - convert ATA pass-thru CDB to taskfile * @qc: command structure to be initialized - * @cmd: SCSI command to convert + * @scsicmd: SCSI command to convert * * Handles either 12 or 16-byte versions of the CDB. * -- cgit v1.2.3 From 7c3983357fdaef3ae71a0d7081a4b6dcfd869d39 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Wed, 9 Nov 2005 13:03:30 +0800 Subject: [PATCH] libata: if condition fix for ata_dev_identify() - if condition fix for ata_dev_identify() - ata_pio_poll() minor cleanup. Changes: - Use (dev->class == ATA_DEV_ATA) for ata_dev_identify() since "qc->tf.command" has been overwritten by the device status - Use HSM_ST_TMOUT directly in ata_pio_poll() Signed-off-by: Albert Lee ============ Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index f1942545a20..a74b4071a66 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1144,7 +1144,7 @@ retry: * ATA software reset (SRST, the default) does not appear * to have this problem. */ - if ((using_edd) && (qc->tf.command == ATA_CMD_ID_ATA)) { + if ((using_edd) && (dev->class == ATA_DEV_ATA)) { u8 err = qc->tf.feature; if (err & ATA_ABORTED) { dev->class = ATA_DEV_ATAPI; @@ -2747,7 +2747,6 @@ static unsigned long ata_pio_poll(struct ata_port *ap) u8 status; unsigned int poll_state = HSM_ST_UNKNOWN; unsigned int reg_state = HSM_ST_UNKNOWN; - const unsigned int tmout_state = HSM_ST_TMOUT; switch (ap->hsm_task_state) { case HSM_ST: @@ -2768,7 +2767,7 @@ static unsigned long ata_pio_poll(struct ata_port *ap) status = ata_chk_status(ap); if (status & ATA_BUSY) { if (time_after(jiffies, ap->pio_task_timeout)) { - ap->hsm_task_state = tmout_state; + ap->hsm_task_state = HSM_ST_TMOUT; return 0; } ap->hsm_task_state = poll_state; -- cgit v1.2.3 From 385023cb8972971540d17c92baf0132693955f5f Mon Sep 17 00:00:00 2001 From: Ashutosh Naik Date: Sun, 6 Nov 2005 23:43:22 -0800 Subject: [PATCH] dgrs: fix warnings when CONFIG_ISA and CONFIG_PCI are not enabled This patch fixes compiler warnings when CONFIG_ISA and CONFIG_PCI are not enabled in the dgrc network driver. Signed-off-by: Ashutosh Naik Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/dgrs.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c index 7809838e6c4..2a290cc397a 100644 --- a/drivers/net/dgrs.c +++ b/drivers/net/dgrs.c @@ -1549,7 +1549,7 @@ MODULE_PARM_DESC(nicmode, "Digi RightSwitch operating mode (1: switch, 2: multi- static int __init dgrs_init_module (void) { int i; - int eisacount = 0, pcicount = 0; + int cardcount = 0; /* * Command line variable overrides @@ -1591,15 +1591,13 @@ static int __init dgrs_init_module (void) * Find and configure all the cards */ #ifdef CONFIG_EISA - eisacount = eisa_driver_register(&dgrs_eisa_driver); - if (eisacount < 0) - return eisacount; -#endif -#ifdef CONFIG_PCI - pcicount = pci_register_driver(&dgrs_pci_driver); - if (pcicount) - return pcicount; + cardcount = eisa_driver_register(&dgrs_eisa_driver); + if (cardcount < 0) + return cardcount; #endif + cardcount = pci_register_driver(&dgrs_pci_driver); + if (cardcount) + return cardcount; return 0; } -- cgit v1.2.3 From f406db8cba6bbce42b96490e6d31bdec229ad994 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 8 Nov 2005 19:10:24 +0000 Subject: [PATCH] IOC: And don't mark the things as broken Cowboy. And don't mark the things as broken Cowboy. Signed-off-by: Ralf Baechle Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 1958d9e16a3..e70315a8544 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -447,7 +447,7 @@ config NET_SB1250_MAC config SGI_IOC3_ETH bool "SGI IOC3 Ethernet" - depends on NET_ETHERNET && PCI && SGI_IP27 && BROKEN + depends on NET_ETHERNET && PCI && SGI_IP27 select CRC32 select MII help -- cgit v1.2.3 From 756e7104fefc82e3ebaa5f1da5ba6659c9c1cae5 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Wed, 9 Nov 2005 18:07:45 +1100 Subject: powerpc: merge irq.c Signed-off-by: Stephen Rothwell --- arch/powerpc/kernel/Makefile | 2 +- arch/powerpc/kernel/irq.c | 478 ++++++++++++++++++++++++++++++++++ arch/powerpc/platforms/powermac/pic.c | 3 + arch/ppc/kernel/Makefile | 5 +- arch/ppc/kernel/irq.c | 165 ------------ arch/ppc/kernel/ppc_ksyms.c | 1 - arch/ppc/platforms/pmac_pic.c | 3 + arch/ppc64/kernel/Makefile | 2 +- arch/ppc64/kernel/irq.c | 415 ----------------------------- include/asm-powerpc/irq.h | 1 - 10 files changed, 488 insertions(+), 587 deletions(-) create mode 100644 arch/powerpc/kernel/irq.c delete mode 100644 arch/ppc/kernel/irq.c delete mode 100644 arch/ppc64/kernel/irq.c diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index b3ae2993efb..cbdc1426165 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -11,7 +11,7 @@ CFLAGS_btext.o += -fPIC endif obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ - signal_32.o pmc.o + irq.o signal_32.o pmc.o obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ signal_64.o ptrace32.o systbl.o obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c new file mode 100644 index 00000000000..4b7940693f3 --- /dev/null +++ b/arch/powerpc/kernel/irq.c @@ -0,0 +1,478 @@ +/* + * arch/ppc/kernel/irq.c + * + * Derived from arch/i386/kernel/irq.c + * Copyright (C) 1992 Linus Torvalds + * Adapted from arch/i386 by Gary Thomas + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * Updated and modified by Cort Dougan + * Copyright (C) 1996-2001 Cort Dougan + * Adapted for Power Macintosh by Paul Mackerras + * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). + * + * 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 option) any later version. + * + * This file contains the code used by various IRQ handling routines: + * asking for different IRQ's should be done through these routines + * instead of just grabbing them. Thus setups with different IRQ numbers + * shouldn't result in any weird surprises, and installing new handlers + * should be easier. + * + * The MPC8xx has an interrupt mask in the SIU. If a bit is set, the + * interrupt is _enabled_. As expected, IRQ0 is bit 0 in the 32-bit + * mask register (of which only 16 are defined), hence the weird shifting + * and complement of the cached_irq_mask. I want to be able to stuff + * this right into the SIU SMASK register. + * Many of the prep/chrp functions are conditional compiled on CONFIG_8xx + * to reduce code space and undefined function references. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_PPC64 +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_PPC64 +#include +#include +#endif + +static int ppc_spurious_interrupts; + +#if defined(CONFIG_PPC_ISERIES) && defined(CONFIG_SMP) +extern void iSeries_smp_message_recv(struct pt_regs *); +#endif + +#ifdef CONFIG_PPC32 +#define NR_MASK_WORDS ((NR_IRQS + 31) / 32) + +unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; +atomic_t ppc_n_lost_interrupts; + +#ifdef CONFIG_TAU_INT +extern int tau_initialized; +extern int tau_interrupts(int); +#endif + +#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_MERGE) +extern atomic_t ipi_recv; +extern atomic_t ipi_sent; +#endif +#endif /* CONFIG_PPC32 */ + +#ifdef CONFIG_PPC64 +EXPORT_SYMBOL(irq_desc); + +int distribute_irqs = 1; +int __irq_offset_value; +u64 ppc64_interrupt_controller; +#endif /* CONFIG_PPC64 */ + +int show_interrupts(struct seq_file *p, void *v) +{ + int i = *(loff_t *)v, j; + struct irqaction *action; + irq_desc_t *desc; + unsigned long flags; + + if (i == 0) { + seq_puts(p, " "); + for_each_online_cpu(j) + seq_printf(p, "CPU%d ", j); + seq_putc(p, '\n'); + } + + if (i < NR_IRQS) { + desc = get_irq_desc(i); + spin_lock_irqsave(&desc->lock, flags); + action = desc->action; + if (!action || !action->handler) + goto skip; + seq_printf(p, "%3d: ", i); +#ifdef CONFIG_SMP + for_each_online_cpu(j) + seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); +#else + seq_printf(p, "%10u ", kstat_irqs(i)); +#endif /* CONFIG_SMP */ + if (desc->handler) + seq_printf(p, " %s ", desc->handler->typename); + else + seq_puts(p, " None "); + seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge "); + seq_printf(p, " %s", action->name); + for (action = action->next; action; action = action->next) + seq_printf(p, ", %s", action->name); + seq_putc(p, '\n'); +skip: + spin_unlock_irqrestore(&desc->lock, flags); + } else if (i == NR_IRQS) { +#ifdef CONFIG_PPC32 +#ifdef CONFIG_TAU_INT + if (tau_initialized){ + seq_puts(p, "TAU: "); + for (j = 0; j < NR_CPUS; j++) + if (cpu_online(j)) + seq_printf(p, "%10u ", tau_interrupts(j)); + seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n"); + } +#endif +#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_MERGE) + /* should this be per processor send/receive? */ + seq_printf(p, "IPI (recv/sent): %10u/%u\n", + atomic_read(&ipi_recv), atomic_read(&ipi_sent)); +#endif +#endif /* CONFIG_PPC32 */ + seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); + } + return 0; +} + +#ifdef CONFIG_HOTPLUG_CPU +void fixup_irqs(cpumask_t map) +{ + unsigned int irq; + static int warned; + + for_each_irq(irq) { + cpumask_t mask; + + if (irq_desc[irq].status & IRQ_PER_CPU) + continue; + + cpus_and(mask, irq_affinity[irq], map); + if (any_online_cpu(mask) == NR_CPUS) { + printk("Breaking affinity for irq %i\n", irq); + mask = map; + } + if (irq_desc[irq].handler->set_affinity) + irq_desc[irq].handler->set_affinity(irq, mask); + else if (irq_desc[irq].action && !(warned++)) + printk("Cannot set affinity for irq %i\n", irq); + } + + local_irq_enable(); + mdelay(1); + local_irq_disable(); +} +#endif + +#ifdef CONFIG_PPC_ISERIES +void do_IRQ(struct pt_regs *regs) +{ + struct paca_struct *lpaca; + + irq_enter(); + +#ifdef CONFIG_DEBUG_STACKOVERFLOW + /* Debugging check for stack overflow: is there less than 2KB free? */ + { + long sp; + + sp = __get_SP() & (THREAD_SIZE-1); + + if (unlikely(sp < (sizeof(struct thread_info) + 2048))) { + printk("do_IRQ: stack overflow: %ld\n", + sp - sizeof(struct thread_info)); + dump_stack(); + } + } +#endif + + lpaca = get_paca(); +#ifdef CONFIG_SMP + if (lpaca->lppaca.int_dword.fields.ipi_cnt) { + lpaca->lppaca.int_dword.fields.ipi_cnt = 0; + iSeries_smp_message_recv(regs); + } +#endif /* CONFIG_SMP */ + if (hvlpevent_is_pending()) + process_hvlpevents(regs); + + irq_exit(); + + if (lpaca->lppaca.int_dword.fields.decr_int) { + lpaca->lppaca.int_dword.fields.decr_int = 0; + /* Signal a fake decrementer interrupt */ + timer_interrupt(regs); + } +} + +#else /* CONFIG_PPC_ISERIES */ + +void do_IRQ(struct pt_regs *regs) +{ + int irq; +#ifdef CONFIG_IRQSTACKS + struct thread_info *curtp, *irqtp; +#endif + + irq_enter(); + +#ifdef CONFIG_DEBUG_STACKOVERFLOW + /* Debugging check for stack overflow: is there less than 2KB free? */ + { + long sp; + + sp = __get_SP() & (THREAD_SIZE-1); + + if (unlikely(sp < (sizeof(struct thread_info) + 2048))) { + printk("do_IRQ: stack overflow: %ld\n", + sp - sizeof(struct thread_info)); + dump_stack(); + } + } +#endif + + /* + * Every platform is required to implement ppc_md.get_irq. + * This function will either return an irq number or -1 to + * indicate there are no more pending. + * The value -2 is for buggy hardware and means that this IRQ + * has already been handled. -- Tom + */ + irq = ppc_md.get_irq(regs); + + if (irq >= 0) { +#ifdef CONFIG_IRQSTACKS + /* Switch to the irq stack to handle this */ + curtp = current_thread_info(); + irqtp = hardirq_ctx[smp_processor_id()]; + if (curtp != irqtp) { + irqtp->task = curtp->task; + irqtp->flags = 0; + call___do_IRQ(irq, regs, irqtp); + irqtp->task = NULL; + if (irqtp->flags) + set_bits(irqtp->flags, &curtp->flags); + } else +#endif + __do_IRQ(irq, regs); + } else +#ifdef CONFIG_PPC32 + if (irq != -2) +#endif + /* That's not SMP safe ... but who cares ? */ + ppc_spurious_interrupts++; + irq_exit(); +} + +#endif /* CONFIG_PPC_ISERIES */ + +void __init init_IRQ(void) +{ +#ifdef CONFIG_PPC64 + static int once = 0; + + if (once) + return; + + once++; + +#endif + ppc_md.init_IRQ(); +#ifdef CONFIG_PPC64 + irq_ctx_init(); +#endif +} + +#ifdef CONFIG_PPC64 +#ifndef CONFIG_PPC_ISERIES +/* + * Virtual IRQ mapping code, used on systems with XICS interrupt controllers. + */ + +#define UNDEFINED_IRQ 0xffffffff +unsigned int virt_irq_to_real_map[NR_IRQS]; + +/* + * Don't use virtual irqs 0, 1, 2 for devices. + * The pcnet32 driver considers interrupt numbers < 2 to be invalid, + * and 2 is the XICS IPI interrupt. + * We limit virtual irqs to 17 less than NR_IRQS so that when we + * offset them by 16 (to reserve the first 16 for ISA interrupts) + * we don't end up with an interrupt number >= NR_IRQS. + */ +#define MIN_VIRT_IRQ 3 +#define MAX_VIRT_IRQ (NR_IRQS - NUM_ISA_INTERRUPTS - 1) +#define NR_VIRT_IRQS (MAX_VIRT_IRQ - MIN_VIRT_IRQ + 1) + +void +virt_irq_init(void) +{ + int i; + for (i = 0; i < NR_IRQS; i++) + virt_irq_to_real_map[i] = UNDEFINED_IRQ; +} + +/* Create a mapping for a real_irq if it doesn't already exist. + * Return the virtual irq as a convenience. + */ +int virt_irq_create_mapping(unsigned int real_irq) +{ + unsigned int virq, first_virq; + static int warned; + + if (ppc64_interrupt_controller == IC_OPEN_PIC) + return real_irq; /* no mapping for openpic (for now) */ + + if (ppc64_interrupt_controller == IC_CELL_PIC) + return real_irq; /* no mapping for iic either */ + + /* don't map interrupts < MIN_VIRT_IRQ */ + if (real_irq < MIN_VIRT_IRQ) { + virt_irq_to_real_map[real_irq] = real_irq; + return real_irq; + } + + /* map to a number between MIN_VIRT_IRQ and MAX_VIRT_IRQ */ + virq = real_irq; + if (virq > MAX_VIRT_IRQ) + virq = (virq % NR_VIRT_IRQS) + MIN_VIRT_IRQ; + + /* search for this number or a free slot */ + first_virq = virq; + while (virt_irq_to_real_map[virq] != UNDEFINED_IRQ) { + if (virt_irq_to_real_map[virq] == real_irq) + return virq; + if (++virq > MAX_VIRT_IRQ) + virq = MIN_VIRT_IRQ; + if (virq == first_virq) + goto nospace; /* oops, no free slots */ + } + + virt_irq_to_real_map[virq] = real_irq; + return virq; + + nospace: + if (!warned) { + printk(KERN_CRIT "Interrupt table is full\n"); + printk(KERN_CRIT "Increase NR_IRQS (currently %d) " + "in your kernel sources and rebuild.\n", NR_IRQS); + warned = 1; + } + return NO_IRQ; +} + +/* + * In most cases will get a hit on the very first slot checked in the + * virt_irq_to_real_map. Only when there are a large number of + * IRQs will this be expensive. + */ +unsigned int real_irq_to_virt_slowpath(unsigned int real_irq) +{ + unsigned int virq; + unsigned int first_virq; + + virq = real_irq; + + if (virq > MAX_VIRT_IRQ) + virq = (virq % NR_VIRT_IRQS) + MIN_VIRT_IRQ; + + first_virq = virq; + + do { + if (virt_irq_to_real_map[virq] == real_irq) + return virq; + + virq++; + + if (virq >= MAX_VIRT_IRQ) + virq = 0; + + } while (first_virq != virq); + + return NO_IRQ; + +} + +#endif /* CONFIG_PPC_ISERIES */ + +#ifdef CONFIG_IRQSTACKS +struct thread_info *softirq_ctx[NR_CPUS]; +struct thread_info *hardirq_ctx[NR_CPUS]; + +void irq_ctx_init(void) +{ + struct thread_info *tp; + int i; + + for_each_cpu(i) { + memset((void *)softirq_ctx[i], 0, THREAD_SIZE); + tp = softirq_ctx[i]; + tp->cpu = i; + tp->preempt_count = SOFTIRQ_OFFSET; + + memset((void *)hardirq_ctx[i], 0, THREAD_SIZE); + tp = hardirq_ctx[i]; + tp->cpu = i; + tp->preempt_count = HARDIRQ_OFFSET; + } +} + +void do_softirq(void) +{ + unsigned long flags; + struct thread_info *curtp, *irqtp; + + if (in_interrupt()) + return; + + local_irq_save(flags); + + if (local_softirq_pending()) { + curtp = current_thread_info(); + irqtp = softirq_ctx[smp_processor_id()]; + irqtp->task = curtp->task; + call_do_softirq(irqtp); + irqtp->task = NULL; + } + + local_irq_restore(flags); +} +EXPORT_SYMBOL(do_softirq); + +#endif /* CONFIG_IRQSTACKS */ + +static int __init setup_noirqdistrib(char *str) +{ + distribute_irqs = 0; + return 1; +} + +__setup("noirqdistrib", setup_noirqdistrib); +#endif /* CONFIG_PPC64 */ diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index 83a49e80ac2..90040c49494 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c @@ -74,6 +74,9 @@ static DEFINE_SPINLOCK(pmac_pic_lock); #define GATWICK_IRQ_POOL_SIZE 10 static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE]; +#define NR_MASK_WORDS ((NR_IRQS + 31) / 32) +static unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; + /* * Mark an irq as "lost". This is only used on the pmac * since it can lose interrupts (see pmac_set_irq_mask). diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index 76a55a438f2..17a4da65e27 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -12,7 +12,7 @@ extra-$(CONFIG_6xx) += idle_6xx.o extra-$(CONFIG_POWER4) += idle_power4.o extra-y += vmlinux.lds -obj-y := entry.o traps.o irq.o idle.o time.o misc.o \ +obj-y := entry.o traps.o idle.o time.o misc.o \ process.o align.o \ setup.o \ ppc_htab.o @@ -38,8 +38,7 @@ endif # These are here while we do the architecture merge else -obj-y := irq.o idle.o \ - align.o +obj-y := idle.o align.o obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o obj-$(CONFIG_MODULES) += module.o diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c deleted file mode 100644 index fbb2b9f8922..00000000000 --- a/arch/ppc/kernel/irq.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * arch/ppc/kernel/irq.c - * - * Derived from arch/i386/kernel/irq.c - * Copyright (C) 1992 Linus Torvalds - * Adapted from arch/i386 by Gary Thomas - * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) - * Updated and modified by Cort Dougan - * Copyright (C) 1996-2001 Cort Dougan - * Adapted for Power Macintosh by Paul Mackerras - * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) - * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). - * - * This file contains the code used by various IRQ handling routines: - * asking for different IRQ's should be done through these routines - * instead of just grabbing them. Thus setups with different IRQ numbers - * shouldn't result in any weird surprises, and installing new handlers - * should be easier. - * - * The MPC8xx has an interrupt mask in the SIU. If a bit is set, the - * interrupt is _enabled_. As expected, IRQ0 is bit 0 in the 32-bit - * mask register (of which only 16 are defined), hence the weird shifting - * and complement of the cached_irq_mask. I want to be able to stuff - * this right into the SIU SMASK register. - * Many of the prep/chrp functions are conditional compiled on CONFIG_8xx - * to reduce code space and undefined function references. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define NR_MASK_WORDS ((NR_IRQS + 31) / 32) - -extern atomic_t ipi_recv; -extern atomic_t ipi_sent; - -#define MAXCOUNT 10000000 - -int ppc_spurious_interrupts = 0; -struct irqaction *ppc_irq_action[NR_IRQS]; -unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; -unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; -atomic_t ppc_n_lost_interrupts; - -#ifdef CONFIG_TAU_INT -extern int tau_initialized; -extern int tau_interrupts(int); -#endif - -int show_interrupts(struct seq_file *p, void *v) -{ - int i = *(loff_t *) v, j; - struct irqaction * action; - unsigned long flags; - - if (i == 0) { - seq_puts(p, " "); - for (j=0; jhandler ) - goto skip; - seq_printf(p, "%3d: ", i); -#ifdef CONFIG_SMP - for (j = 0; j < NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "%10u ", - kstat_cpu(j).irqs[i]); -#else - seq_printf(p, "%10u ", kstat_irqs(i)); -#endif /* CONFIG_SMP */ - if (irq_desc[i].handler) - seq_printf(p, " %s ", irq_desc[i].handler->typename); - else - seq_puts(p, " None "); - seq_printf(p, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge "); - seq_printf(p, " %s", action->name); - for (action = action->next; action; action = action->next) - seq_printf(p, ", %s", action->name); - seq_putc(p, '\n'); -skip: - spin_unlock_irqrestore(&irq_desc[i].lock, flags); - } else if (i == NR_IRQS) { -#ifdef CONFIG_TAU_INT - if (tau_initialized){ - seq_puts(p, "TAU: "); - for (j = 0; j < NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "%10u ", tau_interrupts(j)); - seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n"); - } -#endif -#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_MERGE) - /* should this be per processor send/receive? */ - seq_printf(p, "IPI (recv/sent): %10u/%u\n", - atomic_read(&ipi_recv), atomic_read(&ipi_sent)); -#endif - seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); - } - return 0; -} - -void do_IRQ(struct pt_regs *regs) -{ - int irq, first = 1; - irq_enter(); - - /* - * Every platform is required to implement ppc_md.get_irq. - * This function will either return an irq number or -1 to - * indicate there are no more pending. But the first time - * through the loop this means there wasn't and IRQ pending. - * The value -2 is for buggy hardware and means that this IRQ - * has already been handled. -- Tom - */ - while ((irq = ppc_md.get_irq(regs)) >= 0) { - __do_IRQ(irq, regs); - first = 0; - } - if (irq != -2 && first) - /* That's not SMP safe ... but who cares ? */ - ppc_spurious_interrupts++; - irq_exit(); -} - -void __init init_IRQ(void) -{ - ppc_md.init_IRQ(); -} diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index e0ca61b37f4..c4d5b598843 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -78,7 +78,6 @@ EXPORT_SYMBOL(program_check_exception); EXPORT_SYMBOL(single_step_exception); EXPORT_SYMBOL(sys_sigreturn); EXPORT_SYMBOL(ppc_n_lost_interrupts); -EXPORT_SYMBOL(ppc_lost_interrupts); EXPORT_SYMBOL(ISA_DMA_THRESHOLD); EXPORT_SYMBOL(DMA_MODE_READ); diff --git a/arch/ppc/platforms/pmac_pic.c b/arch/ppc/platforms/pmac_pic.c index 9f2d95ea856..4742bf60935 100644 --- a/arch/ppc/platforms/pmac_pic.c +++ b/arch/ppc/platforms/pmac_pic.c @@ -75,6 +75,9 @@ static DEFINE_SPINLOCK(pmac_pic_lock); #define GATWICK_IRQ_POOL_SIZE 10 static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE]; +#define NR_MASK_WORDS ((NR_IRQS + 31) / 32) +static unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; + /* * Mark an irq as "lost". This is only used on the pmac * since it can lose interrupts (see pmac_set_irq_mask). diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile index c441aebe764..13e47984624 100644 --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile @@ -11,7 +11,7 @@ obj-y := misc.o prom.o endif -obj-y += irq.o idle.o dma.o \ +obj-y += idle.o dma.o \ align.o pacaData.o \ udbg.o ioctl32.o \ rtc.o \ diff --git a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c deleted file mode 100644 index bd6a95a5914..00000000000 --- a/arch/ppc64/kernel/irq.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - * arch/ppc/kernel/irq.c - * - * Derived from arch/i386/kernel/irq.c - * Copyright (C) 1992 Linus Torvalds - * Adapted from arch/i386 by Gary Thomas - * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) - * Updated and modified by Cort Dougan (cort@cs.nmt.edu) - * Copyright (C) 1996 Cort Dougan - * Adapted for Power Macintosh by Paul Mackerras - * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) - * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). - * - * 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 option) any later version. - * - * This file contains the code used by various IRQ handling routines: - * asking for different IRQ's should be done through these routines - * instead of just grabbing them. Thus setups with different IRQ numbers - * shouldn't result in any weird surprises, and installing new handlers - * should be easier. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_SMP -extern void iSeries_smp_message_recv( struct pt_regs * ); -#endif - -extern irq_desc_t irq_desc[NR_IRQS]; -EXPORT_SYMBOL(irq_desc); - -int distribute_irqs = 1; -int __irq_offset_value; -int ppc_spurious_interrupts; -u64 ppc64_interrupt_controller; - -int show_interrupts(struct seq_file *p, void *v) -{ - int i = *(loff_t *) v, j; - struct irqaction * action; - irq_desc_t *desc; - unsigned long flags; - - if (i == 0) { - seq_printf(p, " "); - for (j=0; jlock, flags); - action = desc->action; - if (!action || !action->handler) - goto skip; - seq_printf(p, "%3d: ", i); -#ifdef CONFIG_SMP - for (j = 0; j < NR_CPUS; j++) { - if (cpu_online(j)) - seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); - } -#else - seq_printf(p, "%10u ", kstat_irqs(i)); -#endif /* CONFIG_SMP */ - if (desc->handler) - seq_printf(p, " %s ", desc->handler->typename ); - else - seq_printf(p, " None "); - seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge "); - seq_printf(p, " %s",action->name); - for (action=action->next; action; action = action->next) - seq_printf(p, ", %s", action->name); - seq_putc(p, '\n'); -skip: - spin_unlock_irqrestore(&desc->lock, flags); - } else if (i == NR_IRQS) - seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); - return 0; -} - -#ifdef CONFIG_HOTPLUG_CPU -void fixup_irqs(cpumask_t map) -{ - unsigned int irq; - static int warned; - - for_each_irq(irq) { - cpumask_t mask; - - if (irq_desc[irq].status & IRQ_PER_CPU) - continue; - - cpus_and(mask, irq_affinity[irq], map); - if (any_online_cpu(mask) == NR_CPUS) { - printk("Breaking affinity for irq %i\n", irq); - mask = map; - } - if (irq_desc[irq].handler->set_affinity) - irq_desc[irq].handler->set_affinity(irq, mask); - else if (irq_desc[irq].action && !(warned++)) - printk("Cannot set affinity for irq %i\n", irq); - } - - local_irq_enable(); - mdelay(1); - local_irq_disable(); -} -#endif - -#ifdef CONFIG_PPC_ISERIES -void do_IRQ(struct pt_regs *regs) -{ - struct paca_struct *lpaca; - - irq_enter(); - -#ifdef CONFIG_DEBUG_STACKOVERFLOW - /* Debugging check for stack overflow: is there less than 2KB free? */ - { - long sp; - - sp = __get_SP() & (THREAD_SIZE-1); - - if (unlikely(sp < (sizeof(struct thread_info) + 2048))) { - printk("do_IRQ: stack overflow: %ld\n", - sp - sizeof(struct thread_info)); - dump_stack(); - } - } -#endif - - lpaca = get_paca(); -#ifdef CONFIG_SMP - if (lpaca->lppaca.int_dword.fields.ipi_cnt) { - lpaca->lppaca.int_dword.fields.ipi_cnt = 0; - iSeries_smp_message_recv(regs); - } -#endif /* CONFIG_SMP */ - if (hvlpevent_is_pending()) - process_hvlpevents(regs); - - irq_exit(); - - if (lpaca->lppaca.int_dword.fields.decr_int) { - lpaca->lppaca.int_dword.fields.decr_int = 0; - /* Signal a fake decrementer interrupt */ - timer_interrupt(regs); - } -} - -#else /* CONFIG_PPC_ISERIES */ - -void do_IRQ(struct pt_regs *regs) -{ - int irq; -#ifdef CONFIG_IRQSTACKS - struct thread_info *curtp, *irqtp; -#endif - - irq_enter(); - -#ifdef CONFIG_DEBUG_STACKOVERFLOW - /* Debugging check for stack overflow: is there less than 2KB free? */ - { - long sp; - - sp = __get_SP() & (THREAD_SIZE-1); - - if (unlikely(sp < (sizeof(struct thread_info) + 2048))) { - printk("do_IRQ: stack overflow: %ld\n", - sp - sizeof(struct thread_info)); - dump_stack(); - } - } -#endif - - irq = ppc_md.get_irq(regs); - - if (irq >= 0) { -#ifdef CONFIG_IRQSTACKS - /* Switch to the irq stack to handle this */ - curtp = current_thread_info(); - irqtp = hardirq_ctx[smp_processor_id()]; - if (curtp != irqtp) { - irqtp->task = curtp->task; - irqtp->flags = 0; - call___do_IRQ(irq, regs, irqtp); - irqtp->task = NULL; - if (irqtp->flags) - set_bits(irqtp->flags, &curtp->flags); - } else -#endif - __do_IRQ(irq, regs); - } else - /* That's not SMP safe ... but who cares ? */ - ppc_spurious_interrupts++; - - irq_exit(); -} -#endif /* CONFIG_PPC_ISERIES */ - -void __init init_IRQ(void) -{ - static int once = 0; - - if (once) - return; - - once++; - - ppc_md.init_IRQ(); - irq_ctx_init(); -} - -#ifndef CONFIG_PPC_ISERIES -/* - * Virtual IRQ mapping code, used on systems with XICS interrupt controllers. - */ - -#define UNDEFINED_IRQ 0xffffffff -unsigned int virt_irq_to_real_map[NR_IRQS]; - -/* - * Don't use virtual irqs 0, 1, 2 for devices. - * The pcnet32 driver considers interrupt numbers < 2 to be invalid, - * and 2 is the XICS IPI interrupt. - * We limit virtual irqs to 17 less than NR_IRQS so that when we - * offset them by 16 (to reserve the first 16 for ISA interrupts) - * we don't end up with an interrupt number >= NR_IRQS. - */ -#define MIN_VIRT_IRQ 3 -#define MAX_VIRT_IRQ (NR_IRQS - NUM_ISA_INTERRUPTS - 1) -#define NR_VIRT_IRQS (MAX_VIRT_IRQ - MIN_VIRT_IRQ + 1) - -void -virt_irq_init(void) -{ - int i; - for (i = 0; i < NR_IRQS; i++) - virt_irq_to_real_map[i] = UNDEFINED_IRQ; -} - -/* Create a mapping for a real_irq if it doesn't already exist. - * Return the virtual irq as a convenience. - */ -int virt_irq_create_mapping(unsigned int real_irq) -{ - unsigned int virq, first_virq; - static int warned; - - if (ppc64_interrupt_controller == IC_OPEN_PIC) - return real_irq; /* no mapping for openpic (for now) */ - - if (ppc64_interrupt_controller == IC_CELL_PIC) - return real_irq; /* no mapping for iic either */ - - /* don't map interrupts < MIN_VIRT_IRQ */ - if (real_irq < MIN_VIRT_IRQ) { - virt_irq_to_real_map[real_irq] = real_irq; - return real_irq; - } - - /* map to a number between MIN_VIRT_IRQ and MAX_VIRT_IRQ */ - virq = real_irq; - if (virq > MAX_VIRT_IRQ) - virq = (virq % NR_VIRT_IRQS) + MIN_VIRT_IRQ; - - /* search for this number or a free slot */ - first_virq = virq; - while (virt_irq_to_real_map[virq] != UNDEFINED_IRQ) { - if (virt_irq_to_real_map[virq] == real_irq) - return virq; - if (++virq > MAX_VIRT_IRQ) - virq = MIN_VIRT_IRQ; - if (virq == first_virq) - goto nospace; /* oops, no free slots */ - } - - virt_irq_to_real_map[virq] = real_irq; - return virq; - - nospace: - if (!warned) { - printk(KERN_CRIT "Interrupt table is full\n"); - printk(KERN_CRIT "Increase NR_IRQS (currently %d) " - "in your kernel sources and rebuild.\n", NR_IRQS); - warned = 1; - } - return NO_IRQ; -} - -/* - * In most cases will get a hit on the very first slot checked in the - * virt_irq_to_real_map. Only when there are a large number of - * IRQs will this be expensive. - */ -unsigned int real_irq_to_virt_slowpath(unsigned int real_irq) -{ - unsigned int virq; - unsigned int first_virq; - - virq = real_irq; - - if (virq > MAX_VIRT_IRQ) - virq = (virq % NR_VIRT_IRQS) + MIN_VIRT_IRQ; - - first_virq = virq; - - do { - if (virt_irq_to_real_map[virq] == real_irq) - return virq; - - virq++; - - if (virq >= MAX_VIRT_IRQ) - virq = 0; - - } while (first_virq != virq); - - return NO_IRQ; - -} - -#endif /* CONFIG_PPC_ISERIES */ - -#ifdef CONFIG_IRQSTACKS -struct thread_info *softirq_ctx[NR_CPUS]; -struct thread_info *hardirq_ctx[NR_CPUS]; - -void irq_ctx_init(void) -{ - struct thread_info *tp; - int i; - - for_each_cpu(i) { - memset((void *)softirq_ctx[i], 0, THREAD_SIZE); - tp = softirq_ctx[i]; - tp->cpu = i; - tp->preempt_count = SOFTIRQ_OFFSET; - - memset((void *)hardirq_ctx[i], 0, THREAD_SIZE); - tp = hardirq_ctx[i]; - tp->cpu = i; - tp->preempt_count = HARDIRQ_OFFSET; - } -} - -void do_softirq(void) -{ - unsigned long flags; - struct thread_info *curtp, *irqtp; - - if (in_interrupt()) - return; - - local_irq_save(flags); - - if (local_softirq_pending()) { - curtp = current_thread_info(); - irqtp = softirq_ctx[smp_processor_id()]; - irqtp->task = curtp->task; - call_do_softirq(irqtp); - irqtp->task = NULL; - } - - local_irq_restore(flags); -} -EXPORT_SYMBOL(do_softirq); - -#endif /* CONFIG_IRQSTACKS */ - -static int __init setup_noirqdistrib(char *str) -{ - distribute_irqs = 0; - return 1; -} - -__setup("noirqdistrib", setup_noirqdistrib); diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h index 225dc182ef3..c9fbcede0ef 100644 --- a/include/asm-powerpc/irq.h +++ b/include/asm-powerpc/irq.h @@ -429,7 +429,6 @@ extern u64 ppc64_interrupt_controller; #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) /* pedantic: these are long because they are used with set_bit --RR */ extern unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; -extern unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; extern atomic_t ppc_n_lost_interrupts; #define virt_irq_create_mapping(x) (x) -- cgit v1.2.3 From 2a98beb6390aef8fad85103ea25b3b1ace8015b5 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 9 Nov 2005 10:50:29 +0000 Subject: [ARM SMP] Add local timer support for Realview MPcore Add platform specific parts for local timer support for the Realview board. Signed-off-by: Russell King --- arch/arm/Kconfig | 2 +- arch/arm/mach-realview/Makefile | 1 + arch/arm/mach-realview/core.c | 2 +- arch/arm/mach-realview/localtimer.c | 130 ++++++++++++++++++++++++++++ arch/arm/mach-realview/platsmp.c | 5 ++ include/asm-arm/arch-realview/entry-macro.S | 11 +++ include/asm-arm/arch-realview/irqs.h | 3 + include/asm-arm/arch-realview/platform.h | 5 +- 8 files changed, 154 insertions(+), 5 deletions(-) create mode 100644 arch/arm/mach-realview/localtimer.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3bfef0934c9..ec77721507c 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -358,7 +358,7 @@ config HOTPLUG_CPU config LOCAL_TIMERS bool "Use local timer interrupts" - depends on SMP && n + depends on SMP && REALVIEW_MPCORE default y help Enable support for local timers on SMP platforms, rather then the diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile index 011a85c1062..a6a40dac26a 100644 --- a/arch/arm/mach-realview/Makefile +++ b/arch/arm/mach-realview/Makefile @@ -5,3 +5,4 @@ obj-y := core.o clock.o obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o +obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 4ea60d8b6e3..e2c6fa23d3c 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -550,7 +550,7 @@ static irqreturn_t realview_timer_interrupt(int irq, void *dev_id, struct pt_reg timer_tick(regs); -#ifdef CONFIG_SMP +#if defined(CONFIG_SMP) && !defined(CONFIG_LOCAL_TIMERS) smp_send_timer(); update_process_times(user_mode(regs)); #endif diff --git a/arch/arm/mach-realview/localtimer.c b/arch/arm/mach-realview/localtimer.c new file mode 100644 index 00000000000..5e917e37d09 --- /dev/null +++ b/arch/arm/mach-realview/localtimer.c @@ -0,0 +1,130 @@ +/* + * linux/arch/arm/mach-realview/localtimer.c + * + * Copyright (C) 2002 ARM Ltd. + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "core.h" + +#define TWD_BASE(cpu) (__io_address(REALVIEW_TWD_BASE) + \ + ((cpu) * REALVIEW_TWD_SIZE)) + +static unsigned long mpcore_timer_rate; + +/* + * local_timer_ack: checks for a local timer interrupt. + * + * If a local timer interrupt has occured, acknowledge and return 1. + * Otherwise, return 0. + */ +int local_timer_ack(void) +{ + void __iomem *base = TWD_BASE(smp_processor_id()); + + if (__raw_readl(base + TWD_TIMER_INTSTAT)) { + __raw_writel(1, base + TWD_TIMER_INTSTAT); + return 1; + } + + return 0; +} + +void __cpuinit local_timer_setup(unsigned int cpu) +{ + void __iomem *base = TWD_BASE(cpu); + unsigned int load, offset; + u64 waitjiffies; + unsigned int count; + + /* + * If this is the first time round, we need to work out how fast + * the timer ticks + */ + if (mpcore_timer_rate == 0) { + printk("Calibrating local timer... "); + + /* Wait for a tick to start */ + waitjiffies = get_jiffies_64() + 1; + + while (get_jiffies_64() < waitjiffies) + udelay(10); + + /* OK, now the tick has started, let's get the timer going */ + waitjiffies += 5; + + /* enable, no interrupt or reload */ + __raw_writel(0x1, base + TWD_TIMER_CONTROL); + + /* maximum value */ + __raw_writel(0xFFFFFFFFU, base + TWD_TIMER_COUNTER); + + while (get_jiffies_64() < waitjiffies) + udelay(10); + + count = __raw_readl(base + TWD_TIMER_COUNTER); + + mpcore_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5); + + printk("%lu.%02luMHz.\n", mpcore_timer_rate / 1000000, + (mpcore_timer_rate / 100000) % 100); + } + + load = mpcore_timer_rate / HZ; + + __raw_writel(load, base + TWD_TIMER_LOAD); + __raw_writel(0x7, base + TWD_TIMER_CONTROL); + + /* + * Now maneuver our local tick into the right part of the jiffy. + * Start by working out where within the tick our local timer + * interrupt should go. + */ + offset = ((mpcore_timer_rate / HZ) / (NR_CPUS + 1)) * (cpu + 1); + + /* + * gettimeoffset() will return a number of us since the last tick. + * Convert this number of us to a local timer tick count. + * Be careful of integer overflow whilst keeping maximum precision. + * + * with HZ=100 and 1MHz (fpga) ~ 1GHz processor: + * load = 1 ~ 10,000 + * mpcore_timer_rate/10000 = 100 ~ 100,000 + * + * so the multiply value will be less than 10^9 always. + */ + load = (system_timer->offset() * (mpcore_timer_rate / 10000)) / 100; + + /* Add on our offset to get the load value */ + load = (load + offset) % (mpcore_timer_rate / HZ); + + __raw_writel(load, base + TWD_TIMER_COUNTER); + + /* Make sure our local interrupt controller has this enabled */ + __raw_writel(1 << IRQ_LOCALTIMER, + __io_address(REALVIEW_GIC_DIST_BASE) + GIC_DIST_ENABLE_SET); +} + +/* + * take a local timer down + */ +void __cpuexit local_timer_stop(unsigned int cpu) +{ + __raw_writel(0, TWD_BASE(cpu) + TWD_TIMER_CONTROL); +} diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c index 09b35f62247..0c7d4ac9a7b 100644 --- a/arch/arm/mach-realview/platsmp.c +++ b/arch/arm/mach-realview/platsmp.c @@ -174,6 +174,11 @@ void __init smp_prepare_cpus(unsigned int max_cpus) if (max_cpus > ncores) max_cpus = ncores; + /* + * Enable the local timer for primary CPU + */ + local_timer_setup(cpu); + /* * Initialise the possible/present maps. * cpu_possible_map describes the set of CPUs which may be present diff --git a/include/asm-arm/arch-realview/entry-macro.S b/include/asm-arm/arch-realview/entry-macro.S index 4df469bf42e..6288fad0dc4 100644 --- a/include/asm-arm/arch-realview/entry-macro.S +++ b/include/asm-arm/arch-realview/entry-macro.S @@ -61,3 +61,14 @@ strcc \irqstat, [\base, #GIC_CPU_EOI] cmpcs \irqnr, \irqnr .endm + + /* As above, this assumes that irqstat and base are preserved.. */ + + .macro test_for_ltirq, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + mov \tmp, #0 + cmp \irqnr, #29 + moveq \tmp, #1 + streq \irqstat, [\base, #GIC_CPU_EOI] + cmp \tmp, #0 + .endm diff --git a/include/asm-arm/arch-realview/irqs.h b/include/asm-arm/arch-realview/irqs.h index ff376494e5b..c16223c9588 100644 --- a/include/asm-arm/arch-realview/irqs.h +++ b/include/asm-arm/arch-realview/irqs.h @@ -21,6 +21,9 @@ #include +#define IRQ_LOCALTIMER 29 +#define IRQ_LOCALWDOG 30 + /* * IRQ interrupts definitions are the same the INT definitions * held within platform.h diff --git a/include/asm-arm/arch-realview/platform.h b/include/asm-arm/arch-realview/platform.h index aef9b36b3c3..18d7c18b738 100644 --- a/include/asm-arm/arch-realview/platform.h +++ b/include/asm-arm/arch-realview/platform.h @@ -209,6 +209,8 @@ #else #define REALVIEW_MPCORE_SCU_BASE 0x10100000 /* SCU registers */ #define REALVIEW_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */ +#define REALVIEW_TWD_BASE 0x10100700 +#define REALVIEW_TWD_SIZE 0x00000100 #define REALVIEW_GIC_DIST_BASE 0x10101000 /* Generic interrupt controller distributor */ #endif #define REALVIEW_SMC_BASE 0x10080000 /* SMC */ @@ -305,9 +307,6 @@ #define INT_TSPENINT 30 /* Touchscreen pen */ #define INT_TSKPADINT 31 /* Touchscreen keypad */ #else -#define INT_LOCALTIMER 29 -#define INT_LOCALWDOG 30 - #define INT_AACI 0 #define INT_TIMERINT0_1 1 #define INT_TIMERINT2_3 2 -- cgit v1.2.3 From 97a63ecff4bd06da5d8feb8c0394a4d020f2d34d Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 9 Nov 2005 13:50:57 +0000 Subject: [ARM SMP] Add CPU hotplug support for Realview MPcore Add platform specific parts for hotplug CPU support for the Realview board. Signed-off-by: Russell King --- arch/arm/mach-realview/Makefile | 1 + arch/arm/mach-realview/hotplug.c | 138 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 arch/arm/mach-realview/hotplug.c diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile index a6a40dac26a..36e76ba937f 100644 --- a/arch/arm/mach-realview/Makefile +++ b/arch/arm/mach-realview/Makefile @@ -5,4 +5,5 @@ obj-y := core.o clock.o obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o +obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o diff --git a/arch/arm/mach-realview/hotplug.c b/arch/arm/mach-realview/hotplug.c new file mode 100644 index 00000000000..09748cbcd10 --- /dev/null +++ b/arch/arm/mach-realview/hotplug.c @@ -0,0 +1,138 @@ +/* + * linux/arch/arm/mach-realview/hotplug.c + * + * Copyright (C) 2002 ARM Ltd. + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include + +extern volatile int pen_release; + +static DECLARE_COMPLETION(cpu_killed); + +static inline void cpu_enter_lowpower(void) +{ + unsigned int v; + + asm volatile( "mcr p15, 0, %1, c7, c14, 0\n" + " mcr p15, 0, %1, c7, c5, 0\n" + " mcr p15, 0, %1, c7, c10, 4\n" + /* + * Turn off coherency + */ + " mrc p15, 0, %0, c1, c0, 1\n" + " bic %0, %0, #0x20\n" + " mcr p15, 0, %0, c1, c0, 1\n" + " mrc p15, 0, %0, c1, c0, 0\n" + " bic %0, %0, #0x04\n" + " mcr p15, 0, %0, c1, c0, 0\n" + : "=&r" (v) + : "r" (0) + : "cc"); +} + +static inline void cpu_leave_lowpower(void) +{ + unsigned int v; + + asm volatile( "mrc p15, 0, %0, c1, c0, 0\n" + " orr %0, %0, #0x04\n" + " mcr p15, 0, %0, c1, c0, 0\n" + " mrc p15, 0, %0, c1, c0, 1\n" + " orr %0, %0, #0x20\n" + " mcr p15, 0, %0, c1, c0, 1\n" + : "=&r" (v) + : + : "cc"); +} + +static inline void platform_do_lowpower(unsigned int cpu) +{ + /* + * there is no power-control hardware on this platform, so all + * we can do is put the core into WFI; this is safe as the calling + * code will have already disabled interrupts + */ + for (;;) { + /* + * here's the WFI + */ + asm(".word 0xe320f003\n" + : + : + : "memory", "cc"); + + if (pen_release == cpu) { + /* + * OK, proper wakeup, we're done + */ + break; + } + + /* + * getting here, means that we have come out of WFI without + * having been woken up - this shouldn't happen + * + * The trouble is, letting people know about this is not really + * possible, since we are currently running incoherently, and + * therefore cannot safely call printk() or anything else + */ +#ifdef DEBUG + printk("CPU%u: spurious wakeup call\n", cpu); +#endif + } +} + +int platform_cpu_kill(unsigned int cpu) +{ + return wait_for_completion_timeout(&cpu_killed, 5000); +} + +/* + * platform-specific code to shutdown a CPU + * + * Called with IRQs disabled + */ +void platform_cpu_die(unsigned int cpu) +{ +#ifdef DEBUG + unsigned int this_cpu = hard_smp_processor_id(); + + if (cpu != this_cpu) { + printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n", + this_cpu, cpu); + BUG(); + } +#endif + + printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); + complete(&cpu_killed); + + /* + * we're ready for shutdown now, so do it + */ + cpu_enter_lowpower(); + platform_do_lowpower(cpu); + + /* + * bring this CPU back into the world of cache + * coherency, and then restore interrupts + */ + cpu_leave_lowpower(); +} + +int mach_cpu_disable(unsigned int cpu) +{ + /* + * we don't allow CPU 0 to be shutdown (it is still too special + * e.g. clock tick interrupts) + */ + return cpu == 0 ? -EPERM : 0; +} -- cgit v1.2.3 From 8dd523118bfbcaca5b67923ff6ee546e04a4db64 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 9 Nov 2005 14:05:30 +0000 Subject: [ARM] 3136/1: Anubis - fix map_desc initialisers Patch from Ben Dooks Fix the map_desc initialisers for the Simtec Anubis board to match the new initialiser scheme. Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/mach-s3c2410/mach-anubis.c | 51 ++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c index 8390b685c2b..0f81fc0c2f7 100644 --- a/arch/arm/mach-s3c2410/mach-anubis.c +++ b/arch/arm/mach-s3c2410/mach-anubis.c @@ -56,8 +56,16 @@ static struct map_desc anubis_iodesc[] __initdata = { /* ISA IO areas */ - { (u32)S3C24XX_VA_ISA_BYTE, 0x0, SZ_16M, MT_DEVICE }, - { (u32)S3C24XX_VA_ISA_WORD, 0x0, SZ_16M, MT_DEVICE }, + { + .virtual = (u32)S3C24XX_VA_ISA_BYTE, + .pfn = __phys_to_pfn(0x0), + .length = SZ_4M, + .type = MT_DEVICE + }, { + .virtual = (u32)S3C24XX_VA_ISA_WORD, + .pfn = __phys_to_pfn(0x0), + .length = SZ_4M, MT_DEVICE + }, /* we could possibly compress the next set down into a set of smaller tables * pagetables, but that would mean using an L2 section, and it still means @@ -66,16 +74,41 @@ static struct map_desc anubis_iodesc[] __initdata = { /* CPLD control registers */ - { (u32)ANUBIS_VA_CTRL1, ANUBIS_PA_CTRL1, SZ_4K, MT_DEVICE }, - { (u32)ANUBIS_VA_CTRL2, ANUBIS_PA_CTRL2, SZ_4K, MT_DEVICE }, + { + .virtual = (u32)ANUBIS_VA_CTRL1, + .pfn = __phys_to_pfn(ANUBIS_PA_CTRL1), + .length = SZ_4K, + .type = MT_DEVICE + }, { + .virtual = (u32)ANUBIS_VA_CTRL2, + .pfn = __phys_to_pfn(ANUBIS_PA_CTRL2), + .length = SZ_4K, + .type =MT_DEVICE + }, /* IDE drives */ - { (u32)ANUBIS_IDEPRI, S3C2410_CS3, SZ_1M, MT_DEVICE }, - { (u32)ANUBIS_IDEPRIAUX, S3C2410_CS3+(1<<26), SZ_1M, MT_DEVICE }, - - { (u32)ANUBIS_IDESEC, S3C2410_CS4, SZ_1M, MT_DEVICE }, - { (u32)ANUBIS_IDESECAUX, S3C2410_CS4+(1<<26), SZ_1M, MT_DEVICE }, + { + .virtual = (u32)ANUBIS_IDEPRI, + .pfn = __phys_to_pfn(S3C2410_CS3), + .length = SZ_1M, + .type = MT_DEVICE + }, { + .virtual = (u32)ANUBIS_IDEPRIAUX, + .pfn = __phys_to_pfn(S3C2410_CS3+(1<<26)), + .length = SZ_1M, + .type = MT_DEVICE + }, { + .virtual = (u32)ANUBIS_IDESEC, + .pfn = __phys_to_pfn(S3C2410_CS4), + .length = SZ_1M, + .type = MT_DEVICE + }, { + .virtual = (u32)ANUBIS_IDESECAUX, + .pfn = __phys_to_pfn(S3C2410_CS4+(1<<26)), + .length = SZ_1M, + .type = MT_DEVICE + }, }; #define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK -- cgit v1.2.3 From ff6ffa82fe122ecda457bb10dbab7b0c08ee3803 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 9 Nov 2005 14:05:31 +0000 Subject: [ARM] 3137/1: RX3715 - fix map_desc initialiser Patch from Ben Dooks Change the initialiser for the map_desc for the iPAQ RX3715 to use the new pfn initialiser, and also reduce the amount of ISA space mapped (we only need to stop any ISA IO writes OOPsing the system, so do not need >1Mbyte of space) Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/mach-s3c2410/mach-rx3715.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2410/mach-rx3715.c index 24d69019a84..f8d86d1e16b 100644 --- a/arch/arm/mach-s3c2410/mach-rx3715.c +++ b/arch/arm/mach-s3c2410/mach-rx3715.c @@ -56,8 +56,17 @@ static struct map_desc rx3715_iodesc[] __initdata = { /* dump ISA space somewhere unused */ - { (u32)S3C24XX_VA_ISA_WORD, S3C2410_CS3, SZ_16M, MT_DEVICE }, - { (u32)S3C24XX_VA_ISA_BYTE, S3C2410_CS3, SZ_16M, MT_DEVICE }, + { + .virtual = (u32)S3C24XX_VA_ISA_WORD, + .pfn = __phys_to_pfn(S3C2410_CS3), + .length = SZ_1M, + .type = MT_DEVICE, + }, { + .virtual = (u32)S3C24XX_VA_ISA_BYTE, + .pfn = __phys_to_pfn(S3C2410_CS3), + .length = SZ_1M, + .type = MT_DEVICE, + }, }; -- cgit v1.2.3 From cbe69f95fa7ffc4604622cd4f7efd56ed10999fe Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 9 Nov 2005 14:05:31 +0000 Subject: [ARM] 3138/1: SMDK2440 - fix map_desc initialisation (and ISA memory space) Patch from Ben Dooks Fix the map_desc initialisers for the SMDK2440 machine to use the new .pfn method, and at the same time making the differntiation between ISA IO and Memory space accesses Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/mach-s3c2410/mach-smdk2440.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2410/mach-smdk2440.c index d666c621ad0..4e31118533e 100644 --- a/arch/arm/mach-s3c2410/mach-smdk2440.c +++ b/arch/arm/mach-s3c2410/mach-smdk2440.c @@ -58,8 +58,27 @@ static struct map_desc smdk2440_iodesc[] __initdata = { /* ISA IO Space map (memory space selected by A24) */ - { (u32)S3C24XX_VA_ISA_WORD, S3C2410_CS2, SZ_16M, MT_DEVICE }, - { (u32)S3C24XX_VA_ISA_BYTE, S3C2410_CS2, SZ_16M, MT_DEVICE }, + { + .virtual = (u32)S3C24XX_VA_ISA_WORD, + .pfn = __phys_to_pfn(S3C2410_CS2), + .length = 0x10000, + .type = MT_DEVICE, + }, { + .virtual = (u32)S3C24XX_VA_ISA_WORD + 0x10000, + .pfn = __phys_to_pfn(S3C2410_CS2 + (1<<24)), + .length = SZ_4M, + .type = MT_DEVICE, + }, { + .virtual = (u32)S3C24XX_VA_ISA_BYTE, + .pfn = __phys_to_pfn(S3C2410_CS2), + .length = 0x10000, + .type = MT_DEVICE, + }, { + .virtual = (u32)S3C24XX_VA_ISA_BYTE + 0x10000, + .pfn = __phys_to_pfn(S3C2410_CS2 + (1<<24)), + .length = SZ_4M, + .type = MT_DEVICE, + } }; #define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK -- cgit v1.2.3 From c906107bb72b7bd5ecfc98cc807bdb8f34d17501 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 9 Nov 2005 14:09:31 +0000 Subject: [ARM] 3100/1: simplify a pointer computation Patch from Nicolas Pitre Looks clearer this way. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/kernel/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index ba298277bec..07fb744f8a6 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -355,7 +355,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long stack_start, struct thread_info *thread = p->thread_info; struct pt_regs *childregs; - childregs = ((struct pt_regs *)((unsigned long)thread + THREAD_START_SP)) - 1; + childregs = (void *)thread + THREAD_START_SP - sizeof(*regs); *childregs = *regs; childregs->ARM_r0 = 0; childregs->ARM_sp = stack_start; -- cgit v1.2.3 From 59d1ff3bfb56d9b8cf3ec864857e6a4dfd9d2dba Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 9 Nov 2005 15:04:22 +0000 Subject: [ARM] Clean up save_and_disable_irqs macro and allow use of ARMv6 CPSID save_and_disable_irqs does not need to use mov + msr (which was introduced to work around a documentation bug which was propagated into binutils.) Use msr with an immediate constant, and if we're building for ARMv6 or later, use the new CPSID instruction. Signed-off-by: Russell King --- arch/arm/lib/bitops.h | 4 ++-- include/asm-arm/assembler.h | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/arch/arm/lib/bitops.h b/arch/arm/lib/bitops.h index f35d91fbe11..b8c14e93669 100644 --- a/arch/arm/lib/bitops.h +++ b/arch/arm/lib/bitops.h @@ -34,7 +34,7 @@ and r2, r0, #7 mov r3, #1 mov r3, r3, lsl r2 - save_and_disable_irqs ip, r2 + save_and_disable_irqs ip ldrb r2, [r1, r0, lsr #3] \instr r2, r2, r3 strb r2, [r1, r0, lsr #3] @@ -54,7 +54,7 @@ add r1, r1, r0, lsr #3 and r3, r0, #7 mov r0, #1 - save_and_disable_irqs ip, r2 + save_and_disable_irqs ip ldrb r2, [r1] tst r2, r0, lsl r3 \instr r2, r2, r0, lsl r3 diff --git a/include/asm-arm/assembler.h b/include/asm-arm/assembler.h index 69a28f96bee..f31ac92b6c7 100644 --- a/include/asm-arm/assembler.h +++ b/include/asm-arm/assembler.h @@ -83,10 +83,13 @@ * Save the current IRQ state and disable IRQs. Note that this macro * assumes FIQs are enabled, and that the processor is in SVC mode. */ - .macro save_and_disable_irqs, oldcpsr, temp + .macro save_and_disable_irqs, oldcpsr mrs \oldcpsr, cpsr - mov \temp, #PSR_I_BIT | MODE_SVC - msr cpsr_c, \temp +#if __LINUX_ARM_ARCH__ >= 6 + cpsid i +#else + msr cpsr_c, #PSR_I_BIT | MODE_SVC +#endif .endm /* -- cgit v1.2.3 From 861e37ad5969f764574722f4cfc0734511cbac7f Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Wed, 9 Nov 2005 15:15:10 +0000 Subject: [ARM] 3057/1: Add memory control method to support OneNAND sync burst read Patch from Kyungmin Park This patch is required for OneNAND MTD to passing the OneNAND sync. burst read Signed-off-by: Kyungmin Park Signed-off-by: Russell King --- include/asm-arm/mach/flash.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/asm-arm/mach/flash.h b/include/asm-arm/mach/flash.h index cd57436d987..05b029ef637 100644 --- a/include/asm-arm/mach/flash.h +++ b/include/asm-arm/mach/flash.h @@ -11,6 +11,7 @@ #define ASMARM_MACH_FLASH_H struct mtd_partition; +struct mtd_info; /* * map_name: the map probe function name @@ -19,6 +20,7 @@ struct mtd_partition; * init: method called at driver/device initialisation * exit: method called at driver/device removal * set_vpp: method called to enable or disable VPP + * mmcontrol: method called to enable or disable Sync. Burst Read in OneNAND * parts: optional array of mtd_partitions for static partitioning * nr_parts: number of mtd_partitions for static partitoning */ @@ -29,6 +31,7 @@ struct flash_platform_data { int (*init)(void); void (*exit)(void); void (*set_vpp)(int on); + void (*mmcontrol)(struct mtd_info *mtd, int sync_read); struct mtd_partition *parts; unsigned int nr_parts; }; -- cgit v1.2.3 From 90d45d17f3e68608ac7ba8fc3d7acce022a19c8e Mon Sep 17 00:00:00 2001 From: Ashok Raj Date: Tue, 8 Nov 2005 21:34:24 -0800 Subject: [PATCH] cpu hotplug: fix locking in cpufreq drivers When calling target drivers to set frequency, we take cpucontrol lock. When we modified the code to accomodate CPU hotplug, there was an attempt to take a double lock of cpucontrol leading to a deadlock. Since the current thread context is already holding the cpucontrol lock, we dont need to make another attempt to acquire it. Now we leave a trace in current->flags indicating current thread already is under cpucontrol lock held, so we dont attempt to do this another time. Thanks to Andrew Morton for the beating:-) From: Brice Goglin Build fix (akpm: this patch is still unpleasant. Ashok continues to look for a cleaner solution, doesn't he? ;)) Signed-off-by: Ashok Raj Signed-off-by: Brice Goglin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/cpufreq/cpufreq.c | 24 ++++++++++-------------- include/linux/cpu.h | 5 +++++ include/linux/sched.h | 1 + kernel/cpu.c | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 14 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 25acf478c9e..23a63207d74 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -38,7 +38,6 @@ static struct cpufreq_driver *cpufreq_driver; static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS]; static DEFINE_SPINLOCK(cpufreq_driver_lock); - /* internal prototypes */ static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); static void handle_update(void *data); @@ -1115,24 +1114,21 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, int retval = -EINVAL; /* - * Converted the lock_cpu_hotplug to preempt_disable() - * and preempt_enable(). This is a bit kludgy and relies on how cpu - * hotplug works. All we need is a guarantee that cpu hotplug won't make - * progress on any cpu. Once we do preempt_disable(), this would ensure - * that hotplug threads don't get onto this cpu, thereby delaying - * the cpu remove process. - * - * We removed the lock_cpu_hotplug since we need to call this function - * via cpu hotplug callbacks, which result in locking the cpu hotplug - * thread itself. Agree this is not very clean, cpufreq community - * could improve this if required. - Ashok Raj + * If we are already in context of hotplug thread, we dont need to + * acquire the hotplug lock. Otherwise acquire cpucontrol to prevent + * hotplug from removing this cpu that we are working on. */ - preempt_disable(); + if (!current_in_cpu_hotplug()) + lock_cpu_hotplug(); + dprintk("target for CPU %u: %u kHz, relation %u\n", policy->cpu, target_freq, relation); if (cpu_online(policy->cpu) && cpufreq_driver->target) retval = cpufreq_driver->target(policy, target_freq, relation); - preempt_enable(); + + if (!current_in_cpu_hotplug()) + unlock_cpu_hotplug(); + return retval; } EXPORT_SYMBOL_GPL(__cpufreq_driver_target); diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 1f7b2c09750..43c44530ef9 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -42,6 +42,7 @@ struct notifier_block; /* Need to know about CPUs going up/down? */ extern int register_cpu_notifier(struct notifier_block *nb); extern void unregister_cpu_notifier(struct notifier_block *nb); +extern int current_in_cpu_hotplug(void); int cpu_up(unsigned int cpu); @@ -54,6 +55,10 @@ static inline int register_cpu_notifier(struct notifier_block *nb) static inline void unregister_cpu_notifier(struct notifier_block *nb) { } +static inline int current_in_cpu_hotplug(void) +{ + return 0; +} #endif /* CONFIG_SMP */ extern struct sysdev_class cpu_sysdev_class; diff --git a/include/linux/sched.h b/include/linux/sched.h index 03b68a7b4b8..2bbf968b23d 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -909,6 +909,7 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0) #define PF_SYNCWRITE 0x00200000 /* I am doing a sync write */ #define PF_BORROWED_MM 0x00400000 /* I am a kthread doing use_mm */ #define PF_RANDOMIZE 0x00800000 /* randomize virtual address space */ +#define PF_HOTPLUG_CPU 0x01000000 /* Currently performing CPU hotplug */ /* * Only the _current_ task can read/write to tsk->flags, but other diff --git a/kernel/cpu.c b/kernel/cpu.c index 3619e939182..d61ba88f34e 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -21,6 +21,24 @@ EXPORT_SYMBOL_GPL(cpucontrol); static struct notifier_block *cpu_chain; +/* + * Used to check by callers if they need to acquire the cpucontrol + * or not to protect a cpu from being removed. Its sometimes required to + * call these functions both for normal operations, and in response to + * a cpu being added/removed. If the context of the call is in the same + * thread context as a CPU hotplug thread, we dont need to take the lock + * since its already protected + * check drivers/cpufreq/cpufreq.c for its usage - Ashok Raj + */ + +int current_in_cpu_hotplug(void) +{ + return (current->flags & PF_HOTPLUG_CPU); +} + +EXPORT_SYMBOL_GPL(current_in_cpu_hotplug); + + /* Need to know about CPUs going up/down? */ int register_cpu_notifier(struct notifier_block *nb) { @@ -94,6 +112,13 @@ int cpu_down(unsigned int cpu) goto out; } + /* + * Leave a trace in current->flags indicating we are already in + * process of performing CPU hotplug. Callers can check if cpucontrol + * is already acquired by current thread, and if so not cause + * a dead lock by not acquiring the lock + */ + current->flags |= PF_HOTPLUG_CPU; err = notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE, (void *)(long)cpu); if (err == NOTIFY_BAD) { @@ -146,6 +171,7 @@ out_thread: out_allowed: set_cpus_allowed(current, old_allowed); out: + current->flags &= ~PF_HOTPLUG_CPU; unlock_cpu_hotplug(); return err; } @@ -163,6 +189,12 @@ int __devinit cpu_up(unsigned int cpu) ret = -EINVAL; goto out; } + + /* + * Leave a trace in current->flags indicating we are already in + * process of performing CPU hotplug. + */ + current->flags |= PF_HOTPLUG_CPU; ret = notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu); if (ret == NOTIFY_BAD) { printk("%s: attempt to bring up CPU %u failed\n", @@ -185,6 +217,7 @@ out_notify: if (ret != 0) notifier_call_chain(&cpu_chain, CPU_UP_CANCELED, hcpu); out: + current->flags &= ~PF_HOTPLUG_CPU; up(&cpucontrol); return ret; } -- cgit v1.2.3 From 3aef1bde147a503aacb59b767826720a996aea6d Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 8 Nov 2005 21:34:25 -0800 Subject: [PATCH] quieten softlockup at boot On a large SMP box we get a lot of softlockup thread XX started lines. Signed-off-by: Anton Blanchard Acked-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/softlockup.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/kernel/softlockup.c b/kernel/softlockup.c index a2dcceb9437..c67189a25d5 100644 --- a/kernel/softlockup.c +++ b/kernel/softlockup.c @@ -73,9 +73,6 @@ void softlockup_tick(struct pt_regs *regs) static int watchdog(void * __bind_cpu) { struct sched_param param = { .sched_priority = 99 }; - int this_cpu = (long) __bind_cpu; - - printk("softlockup thread %d started up.\n", this_cpu); sched_setscheduler(current, SCHED_FIFO, ¶m); current->flags |= PF_NOFREEZE; -- cgit v1.2.3 From 409ef74a1558f4550de677957d1d136f1e5b03b3 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 8 Nov 2005 21:34:26 -0800 Subject: [PATCH] vx_hwdep.c needs vmalloc.h sound/drivers/vx/vx_hwdep.c: In function `free_fw': sound/drivers/vx/vx_hwdep.c:144: error: implicit declaration of function `vfree' sound/drivers/vx/vx_hwdep.c: In function `vx_hwdep_dsp_load': sound/drivers/vx/vx_hwdep.c:163: error: implicit declaration of function `vmalloc' Cc: Jaroslav Kysela Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- sound/drivers/vx/vx_hwdep.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c index 9a3dc3c3b3d..c4993b004c4 100644 --- a/sound/drivers/vx/vx_hwdep.c +++ b/sound/drivers/vx/vx_hwdep.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From b80b5832ffc03cb5e2af9bb12c04836190a74481 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 8 Nov 2005 21:34:27 -0800 Subject: [PATCH] mtd: rfd_ftl build fix drivers/mtd/rfd_ftl.c: In function `find_free_block': drivers/mtd/rfd_ftl.c:528: error: `jiffies' undeclared (first use in this function) drivers/mtd/rfd_ftl.c:528: error: (Each undeclared identifier is reported only once drivers/mtd/rfd_ftl.c:528: error: for each function it appears in.) Cc: Thomas Gleixner Cc: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/rfd_ftl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c index 041ee59ea77..0ab8d29caee 100644 --- a/drivers/mtd/rfd_ftl.c +++ b/drivers/mtd/rfd_ftl.c @@ -18,6 +18,7 @@ #include #include #include +#include #include -- cgit v1.2.3 From 015953d706b1b7ad61c37fe329042828a0f3b0f6 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 8 Nov 2005 21:34:28 -0800 Subject: [PATCH] mtd: onenand_base needs sched.h drivers/mtd/onenand/onenand_base.c: In function `onenand_wait': drivers/mtd/onenand/onenand_base.c:293: error: `jiffies' undeclared (first use in this function) drivers/mtd/onenand/onenand_base.c:293: error: (Each undeclared identifier is reported only once drivers/mtd/onenand/onenand_base.c:293: error: for each function it appears in.) drivers/mtd/onenand/onenand_base.c:293: error: implicit declaration of function `msecs_to_jiffies' drivers/mtd/onenand/onenand_base.c:294: error: implicit declaration of function `time_before' drivers/mtd/onenand/onenand_base.c:301: error: implicit declaration of function `cond_resched' drivers/mtd/onenand/onenand_base.c: In function `onenand_get_device': drivers/mtd/onenand/onenand_base.c:522: error: implicit declaration of function `set_current_state' drivers/mtd/onenand/onenand_base.c:522: error: `TASK_UNINTERRUPTIBLE' undeclared (first use in this function) drivers/mtd/onenand/onenand_base.c:525: error: implicit declaration of function `schedule' drivers/mtd/onenand/onenand_base.c: In function `onenand_release_device': drivers/mtd/onenand/onenand_base.c:545: error: `TASK_UNINTERRUPTIBLE' undeclared (first use in this function) drivers/mtd/onenand/onenand_base.c:545: error: `TASK_INTERRUPTIBLE' undeclared (first use in this function) Cc: Thomas Gleixner Cc: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/onenand/onenand_base.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index cc38fa0d45c..f67d5d6eb9a 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include -- cgit v1.2.3 From 08de1f0461ad40136e7373cf85e2f3c221a9ad9a Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 8 Nov 2005 21:34:29 -0800 Subject: [PATCH] Input: fix 'uniq' reporting in hotplug handler Input: fix 'uniq' reporting in hotplug handler Signed-off-by: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/input/input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/input.c b/drivers/input/input.c index 0879915b14d..c8ae2bb054e 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -669,7 +669,7 @@ static int input_dev_hotplug(struct class_device *cdev, char **envp, INPUT_ADD_HOTPLUG_VAR("NAME=\"%s\"", dev->name); if (dev->phys) INPUT_ADD_HOTPLUG_VAR("PHYS=\"%s\"", dev->phys); - if (dev->phys) + if (dev->uniq) INPUT_ADD_HOTPLUG_VAR("UNIQ=\"%s\"", dev->uniq); INPUT_ADD_HOTPLUG_BM_VAR("EV=", dev->evbit, EV_MAX); -- cgit v1.2.3 From 969e9afd489514252a680914c6d8b9322c713eb4 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Tue, 8 Nov 2005 21:34:30 -0800 Subject: [PATCH] sleep: Fix oops in enter_state If ACPI sleep is not configured, but someone still wants to run swsusp, he'd get oops in enter_state. This is regression since 2.6.14 and this fixes it. Signed-off-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/power/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/power/main.c b/kernel/power/main.c index 18d7d693fbb..6ee2cad530e 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -167,7 +167,7 @@ static int enter_state(suspend_state_t state) { int error; - if (pm_ops->valid && !pm_ops->valid(state)) + if (pm_ops && pm_ops->valid && !pm_ops->valid(state)) return -ENODEV; if (down_trylock(&pm_sem)) return -EBUSY; -- cgit v1.2.3 From d34d7ae266b23932809c43f115fda71fc5e5fcb1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 8 Nov 2005 21:34:31 -0800 Subject: [PATCH] drm fixup pci gart settings Fix the PCIGART increment and add a cpu_to_le32 for ppc (untested) Paulus was unsure if we need to cpu_to_le32 but the old code was definitely wrong, so make it consistent and let the PPC guys figure it out later. Signed-off-by: Dave Airlie Cc: Paul Mackerras Cc: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/drm/ati_pcigart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c index 6d3fec160bf..efff0eec618 100644 --- a/drivers/char/drm/ati_pcigart.c +++ b/drivers/char/drm/ati_pcigart.c @@ -203,10 +203,10 @@ int drm_ati_pcigart_init(drm_device_t * dev, drm_ati_pcigart_info * gart_info) for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { if (gart_info->is_pcie) - *pci_gart = (cpu_to_le32(page_base) >> 8) | 0xc; + *pci_gart = cpu_to_le32((page_base >> 8) | 0xc); else *pci_gart = cpu_to_le32(page_base); - *pci_gart++; + pci_gart++; page_base += ATI_PCIGART_PAGE_SIZE; } } -- cgit v1.2.3 From e517a0cd859ae0c4d9451107113fc2b076456f8f Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Tue, 8 Nov 2005 21:34:32 -0800 Subject: [PATCH] selinux: MLS compatibility This patch enables files created on a MLS-enabled SELinux system to be accessible on a non-MLS SELinux system, by skipping the MLS component of the security context in the non-MLS case. Signed-off-by: Stephen Smalley Signed-off-by: James Morris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- security/selinux/ss/mls.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index aaefac2921f..640d0bfdbc6 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -262,8 +262,11 @@ int mls_context_to_sid(char oldc, struct cat_datum *catdatum, *rngdatum; int l, rc = -EINVAL; - if (!selinux_mls_enabled) + if (!selinux_mls_enabled) { + if (def_sid != SECSID_NULL && oldc) + *scontext += strlen(*scontext); return 0; + } /* * No MLS component to the security context, try and map to -- cgit v1.2.3 From 25a74f3ba8efb394e9a30d6de37566bf03fd3de8 Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Tue, 8 Nov 2005 21:34:33 -0800 Subject: [PATCH] selinux: disable setxattr on mountpoint labeled filesystems This patch disables the setting of SELinux xattrs on files created in filesystems labeled via mountpoint labeling (mounted with the context= option). selinux_inode_setxattr already prevents explicit setxattr from userspace on such filesystems, so this provides consistent behavior for file creation. Signed-off-by: Stephen Smalley Signed-off-by: James Morris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- security/selinux/hooks.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 45c41490d52..fc774436a26 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1986,6 +1986,9 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, inode_security_set_sid(inode, newsid); + if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT) + return -EOPNOTSUPP; + if (name) { namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_KERNEL); if (!namep) -- cgit v1.2.3 From ce9982d048bb498c38ec1fe2ae59a44350882f3f Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Tue, 8 Nov 2005 21:34:33 -0800 Subject: [PATCH] selinux: extend selinuxfs context interface This patch extends the selinuxfs context interface to allow return the canonical form of the context to userspace. Signed-off-by: Stephen Smalley Signed-off-by: James Morris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- security/selinux/selinuxfs.c | 45 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index fdc38238972..0e1352a555c 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -271,46 +271,38 @@ static struct file_operations sel_load_ops = { .write = sel_write_load, }; - -static ssize_t sel_write_context(struct file * file, const char __user * buf, - size_t count, loff_t *ppos) - +static ssize_t sel_write_context(struct file * file, char *buf, size_t size) { - char *page; - u32 sid; + char *canon; + u32 sid, len; ssize_t length; length = task_has_security(current, SECURITY__CHECK_CONTEXT); if (length) return length; - if (count >= PAGE_SIZE) - return -ENOMEM; - if (*ppos != 0) { - /* No partial writes. */ - return -EINVAL; - } - page = (char*)get_zeroed_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - length = -EFAULT; - if (copy_from_user(page, buf, count)) - goto out; + length = security_context_to_sid(buf, size, &sid); + if (length < 0) + return length; - length = security_context_to_sid(page, count, &sid); + length = security_sid_to_context(sid, &canon, &len); if (length < 0) + return length; + + if (len > SIMPLE_TRANSACTION_LIMIT) { + printk(KERN_ERR "%s: context size (%u) exceeds payload " + "max\n", __FUNCTION__, len); + length = -ERANGE; goto out; + } - length = count; + memcpy(buf, canon, len); + length = len; out: - free_page((unsigned long) page); + kfree(canon); return length; } -static struct file_operations sel_context_ops = { - .write = sel_write_context, -}; - static ssize_t sel_read_checkreqprot(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { @@ -375,6 +367,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = { [SEL_RELABEL] = sel_write_relabel, [SEL_USER] = sel_write_user, [SEL_MEMBER] = sel_write_member, + [SEL_CONTEXT] = sel_write_context, }; static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) @@ -1220,7 +1213,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent) static struct tree_descr selinux_files[] = { [SEL_LOAD] = {"load", &sel_load_ops, S_IRUSR|S_IWUSR}, [SEL_ENFORCE] = {"enforce", &sel_enforce_ops, S_IRUGO|S_IWUSR}, - [SEL_CONTEXT] = {"context", &sel_context_ops, S_IRUGO|S_IWUGO}, + [SEL_CONTEXT] = {"context", &transaction_ops, S_IRUGO|S_IWUGO}, [SEL_ACCESS] = {"access", &transaction_ops, S_IRUGO|S_IWUGO}, [SEL_CREATE] = {"create", &transaction_ops, S_IRUGO|S_IWUGO}, [SEL_RELABEL] = {"relabel", &transaction_ops, S_IRUGO|S_IWUGO}, -- cgit v1.2.3 From c099af7622c8e032edcfdc057cde1015761adeac Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Tue, 8 Nov 2005 21:34:34 -0800 Subject: [PATCH] ppc32: Fix RapidIO build on 85xx Fixes mismerged Makefile that prevented the ppc85xx rapidio support from being built. Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/syslib/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index 5bd33baac24..5b7f2b80e56 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -33,7 +33,6 @@ obj-$(CONFIG_PPC4xx_DMA) += ppc4xx_dma.o obj-$(CONFIG_PPC4xx_EDMA) += ppc4xx_sgdma.o ifeq ($(CONFIG_40x),y) obj-$(CONFIG_PCI) += pci_auto.o ppc405_pci.o -obj-$(CONFIG_RAPIDIO) += ppc85xx_rio.o endif endif obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \ @@ -96,6 +95,7 @@ obj-$(CONFIG_85xx) += open_pic.o ppc85xx_common.o ppc85xx_setup.o \ ifeq ($(CONFIG_85xx),y) obj-$(CONFIG_PCI) += pci_auto.o endif +obj-$(CONFIG_RAPIDIO) += ppc85xx_rio.o obj-$(CONFIG_83xx) += ipic.o ppc83xx_setup.o ppc_sys.o \ mpc83xx_sys.o mpc83xx_devices.o ifeq ($(CONFIG_83xx),y) -- cgit v1.2.3 From 8827cc706861070f8a3a9e839b96e40231b16ce0 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Tue, 8 Nov 2005 21:34:35 -0800 Subject: [PATCH] ppc32: Fix STx GP3 build Add missing include file to fix STx GP3 build. Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/platforms/85xx/stx_gp3.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/ppc/platforms/85xx/stx_gp3.h b/arch/ppc/platforms/85xx/stx_gp3.h index 95fdf4b0680..7bcc6c35a41 100644 --- a/arch/ppc/platforms/85xx/stx_gp3.h +++ b/arch/ppc/platforms/85xx/stx_gp3.h @@ -21,6 +21,7 @@ #include #include +#include #include #define BOARD_CCSRBAR ((uint)0xe0000000) -- cgit v1.2.3 From 143dcec2f7123b630b9e2c01c31b01a383dc15ff Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Tue, 8 Nov 2005 21:34:36 -0800 Subject: [PATCH] ppc64: add MODALIAS= for vio bus A non-broken udev would autoload also the drivers for devices on the pseries vio bus, like ibmveth, ibmvscsic and hvsc. This is similar to pci, usb and ieee1394: /lib/modules/`uname -r`/modules.alias alias vio:TvscsiSIBM,v-scsi* ibmvscsic alias vio:TnetworkSIBM,l-lan* ibmveth alias vio:Tserial-serverShvterm2* hvcs /events/debug.00004.pci.add.1394:MODALIAS='pci:v00001014d00000188sv00000000sd00000000bc06sc04i0f' /events/debug.00005.pci.add.1509:MODALIAS='pci:v00008086d00001229sv00001014sd000001FFbc02sc00i00' /events/debug.00026.vio.add.1519:MODALIAS='vio:TserialShvterm1' /events/debug.00027.vio.add.1446:MODALIAS='vio:TvscsiSIBM,v-scsi' /events/debug.00028.vio.add.1451:MODALIAS='vio:TnetworkSIBM,l-lan' modprobe -v vio:TnetworkSIBM,l-lan insmod /lib/modules/2.6.14-20051030_vio-ppc64/kernel/drivers/net/ibmveth.ko Signed-off-by: Olaf Hering Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/vio.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 97082a4203a..71a6addf9f7 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -21,6 +21,7 @@ #include #include #include +#include static const struct vio_device_id *vio_match_device( const struct vio_device_id *, const struct vio_dev *); @@ -265,7 +266,33 @@ static int vio_bus_match(struct device *dev, struct device_driver *drv) return (ids != NULL) && (vio_match_device(ids, vio_dev) != NULL); } +static int vio_hotplug(struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size) +{ + const struct vio_dev *vio_dev = to_vio_dev(dev); + char *cp; + int length; + + if (!num_envp) + return -ENOMEM; + + if (!vio_dev->dev.platform_data) + return -ENODEV; + cp = (char *)get_property(vio_dev->dev.platform_data, "compatible", &length); + if (!cp) + return -ENODEV; + + envp[0] = buffer; + length = scnprintf(buffer, buffer_size, "MODALIAS=vio:T%sS%s", + vio_dev->type, cp); + if (buffer_size - length <= 0) + return -ENOMEM; + envp[1] = NULL; + return 0; +} + struct bus_type vio_bus_type = { .name = "vio", + .hotplug = vio_hotplug, .match = vio_bus_match, }; -- cgit v1.2.3 From 78b331213ec738ee4c1218034d6eec17293b3aed Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Tue, 8 Nov 2005 21:34:37 -0800 Subject: [PATCH] ppc32: Update MPC834x platform to work with new phylib MPC834x uses the gianfar network driver which now uses the new phylib. We need to update the platform code to create a gianfar platform MDIO bus and pass the right intializations to the gianfar driver to make things work again. Signed-off-by: Kumar Gala Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/configs/mpc834x_sys_defconfig | 431 ++++++++++++++++++++++++--------- arch/ppc/platforms/83xx/mpc834x_sys.c | 23 +- arch/ppc/syslib/mpc83xx_devices.c | 12 +- arch/ppc/syslib/mpc83xx_sys.c | 24 +- include/asm-ppc/mpc83xx.h | 1 + 5 files changed, 353 insertions(+), 138 deletions(-) diff --git a/arch/ppc/configs/mpc834x_sys_defconfig b/arch/ppc/configs/mpc834x_sys_defconfig index 4a5522ca820..673dc64ebcb 100644 --- a/arch/ppc/configs/mpc834x_sys_defconfig +++ b/arch/ppc/configs/mpc834x_sys_defconfig @@ -1,16 +1,17 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.11-rc4 -# Thu Feb 17 16:12:23 2005 +# Linux kernel version: 2.6.14 +# Mon Nov 7 15:38:29 2005 # CONFIG_MMU=y CONFIG_GENERIC_HARDIRQS=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_HAVE_DEC_LOCK=y CONFIG_PPC=y CONFIG_PPC32=y CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y # # Code maturity level options @@ -18,23 +19,28 @@ CONFIG_GENERIC_NVRAM=y CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 # # General setup # CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set +CONFIG_INITRAMFS_SOURCE="" CONFIG_EMBEDDED=y # CONFIG_KALLSYMS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y CONFIG_FUTEX=y # CONFIG_EPOLL is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set @@ -44,6 +50,7 @@ CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 # CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 # # Loadable module support @@ -59,44 +66,90 @@ CONFIG_6xx=y # CONFIG_POWER3 is not set # CONFIG_POWER4 is not set # CONFIG_8xx is not set +# CONFIG_E200 is not set # CONFIG_E500 is not set +CONFIG_PPC_FPU=y +# CONFIG_KEXEC is not set # CONFIG_CPU_FREQ is not set +# CONFIG_WANT_EARLY_SERIAL is not set CONFIG_PPC_GEN550=y -CONFIG_83xx=y - -# -# Freescale 83xx options -# -CONFIG_MPC834x_SYS=y -CONFIG_MPC834x=y CONFIG_PPC_STD_MMU=y # # Platform options # +# CONFIG_PPC_MULTIPLATFORM is not set +# CONFIG_APUS is not set +# CONFIG_KATANA is not set +# CONFIG_WILLOW is not set +# CONFIG_CPCI690 is not set +# CONFIG_POWERPMC250 is not set +# CONFIG_CHESTNUT is not set +# CONFIG_SPRUCE is not set +# CONFIG_HDPU is not set +# CONFIG_EV64260 is not set +# CONFIG_LOPEC is not set +# CONFIG_MVME5100 is not set +# CONFIG_PPLUS is not set +# CONFIG_PRPMC750 is not set +# CONFIG_PRPMC800 is not set +# CONFIG_SANDPOINT is not set +# CONFIG_RADSTONE_PPC7D is not set +# CONFIG_PAL4 is not set +# CONFIG_GEMINI is not set +# CONFIG_EST8260 is not set +# CONFIG_SBC82xx is not set +# CONFIG_SBS8260 is not set +# CONFIG_RPX8260 is not set +# CONFIG_TQM8260 is not set +# CONFIG_ADS8272 is not set +# CONFIG_PQ2FADS is not set +# CONFIG_LITE5200 is not set +CONFIG_MPC834x_SYS=y +# CONFIG_EV64360 is not set +CONFIG_83xx=y +CONFIG_MPC834x=y # CONFIG_SMP is not set -# CONFIG_PREEMPT is not set # CONFIG_HIGHMEM is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set # CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +# CONFIG_SOFTWARE_SUSPEND is not set +CONFIG_SECCOMP=y +CONFIG_ISA_DMA_API=y # # Bus options # CONFIG_GENERIC_ISA_DMA=y -# CONFIG_PCI is not set -# CONFIG_PCI_DOMAINS is not set +# CONFIG_PPC_I8259 is not set +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_MPC83xx_PCI2 is not set +CONFIG_PCI_LEGACY_PROC=y # # PCCARD (PCMCIA/CardBus) support # # CONFIG_PCCARD is not set -# -# PC-card bridges -# - # # Advanced setup # @@ -111,6 +164,75 @@ CONFIG_KERNEL_START=0xc0000000 CONFIG_TASK_SIZE=0x80000000 CONFIG_BOOT_LOAD=0x00800000 +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + # # Device Drivers # @@ -122,6 +244,11 @@ CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + # # Memory Technology Devices (MTD) # @@ -140,15 +267,19 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # Block devices # # CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set # CONFIG_BLK_DEV_COW_COMMON is not set CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=32768 CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set # CONFIG_CDROM_PKTCDVD is not set @@ -159,6 +290,11 @@ CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ATA_OVER_ETH is not set # @@ -169,6 +305,7 @@ CONFIG_IOSCHED_CFQ=y # # SCSI device support # +# CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # @@ -179,110 +316,116 @@ CONFIG_IOSCHED_CFQ=y # # Fusion MPT device support # +# CONFIG_FUSION is not set # # IEEE 1394 (FireWire) support # +# CONFIG_IEEE1394 is not set # # I2O device support # +# CONFIG_I2O is not set # # Macintosh device drivers # # -# Networking support +# Network device support # -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK_DEV is not set -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -CONFIG_SYN_COOKIES=y -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -CONFIG_IP_TCPDIAG=y -# CONFIG_IP_TCPDIAG_IPV6 is not set -# CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set # -# SCTP Configuration (EXPERIMENTAL) +# ARCnet devices # -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set +# CONFIG_ARCNET is not set # -# QoS and/or fair queueing +# PHY device support # -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set +CONFIG_PHYLIB=y # -# Network testing +# MII PHY device drivers # -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set +CONFIG_MARVELL_PHY=y +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=y +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set # # Ethernet (1000 Mbit) # +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +CONFIG_E1000=y +# CONFIG_E1000_NAPI is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set CONFIG_GIANFAR=y # CONFIG_GFAR_NAPI is not set # # Ethernet (10000 Mbit) # +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set # # Token Ring devices # +# CONFIG_TR is not set # # Wireless LAN (non-hamradio) @@ -293,10 +436,14 @@ CONFIG_GIANFAR=y # Wan interfaces # # CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set # # ISDN subsystem @@ -322,14 +469,6 @@ CONFIG_INPUT=y # CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -# CONFIG_SERIO is not set -# CONFIG_SERIO_I8042 is not set - # # Input Device Drivers # @@ -339,6 +478,12 @@ CONFIG_SOUND_GAMEPORT=y # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + # # Character devices # @@ -358,6 +503,7 @@ CONFIG_SERIAL_8250_NR_UARTS=4 # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -376,6 +522,7 @@ CONFIG_GEN_RTC=y # CONFIG_GEN_RTC_X is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver @@ -384,6 +531,12 @@ CONFIG_GEN_RTC=y # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + # # I2C support # @@ -400,23 +553,68 @@ CONFIG_I2C_CHARDEV=y # # I2C Hardware Bus support # -# CONFIG_I2C_ISA is not set +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set CONFIG_I2C_MPC=y +# CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_SCx200_ACB is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set # CONFIG_I2C_PCA_ISA is not set # -# Hardware Sensors Chip support +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_M41T00 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_RTC_X1205_I2C is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support # -# CONFIG_I2C_SENSOR is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set # CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set # CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set # CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set # CONFIG_SENSORS_IT87 is not set # CONFIG_SENSORS_LM63 is not set # CONFIG_SENSORS_LM75 is not set @@ -427,33 +625,26 @@ CONFIG_I2C_MPC=y # CONFIG_SENSORS_LM85 is not set # CONFIG_SENSORS_LM87 is not set # CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83792D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set # -# Other I2C Chip support -# -# CONFIG_SENSORS_EEPROM is not set -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set - -# -# Dallas's 1-wire bus +# Misc devices # -# CONFIG_W1 is not set # -# Misc devices +# Multimedia Capabilities Port drivers # # @@ -479,11 +670,12 @@ CONFIG_I2C_MPC=y # # USB support # -# CONFIG_USB_ARCH_HAS_HCD is not set -# CONFIG_USB_ARCH_HAS_OHCI is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' # # @@ -501,11 +693,16 @@ CONFIG_I2C_MPC=y # # CONFIG_INFINIBAND is not set +# +# SN Devices +# + # # File systems # CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y # CONFIG_EXT3_FS_POSIX_ACL is not set @@ -515,17 +712,16 @@ CONFIG_JBD=y CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set - -# -# XFS support -# +# CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set # # CD-ROM/DVD Filesystems @@ -546,12 +742,10 @@ CONFIG_DNOTIFY=y CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_SYSFS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y -# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set # # Miscellaneous filesystems @@ -580,6 +774,7 @@ CONFIG_NFS_FS=y # CONFIG_NFSD is not set CONFIG_ROOT_NFS=y CONFIG_LOCKD=y +CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set @@ -588,6 +783,7 @@ CONFIG_SUNRPC=y # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set # # Partition Types @@ -614,6 +810,7 @@ CONFIG_PARTITION_ADVANCED=y # Library routines # # CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set @@ -625,7 +822,9 @@ CONFIG_CRC32=y # # Kernel hacking # +# CONFIG_PRINTK_TIME is not set # CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 # CONFIG_SERIAL_TEXT_DEBUG is not set # diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c index 79b3f533d0a..98edc75f410 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.c +++ b/arch/ppc/platforms/83xx/mpc834x_sys.c @@ -51,6 +51,9 @@ #include +static const char *GFAR_PHY_0 = "phy0:0"; +static const char *GFAR_PHY_1 = "phy0:1"; + #ifndef CONFIG_PCI unsigned long isa_io_base = 0; unsigned long isa_mem_base = 0; @@ -97,6 +100,7 @@ mpc834x_sys_setup_arch(void) bd_t *binfo = (bd_t *) __res; unsigned int freq; struct gianfar_platform_data *pdata; + struct gianfar_mdio_data *mdata; /* get the core frequency */ freq = binfo->bi_intfreq; @@ -111,24 +115,27 @@ mpc834x_sys_setup_arch(void) #endif mpc83xx_early_serial_map(); + /* setup the board related info for the MDIO bus */ + mdata = (struct gianfar_mdio_data *) ppc_sys_get_pdata(MPC83xx_MDIO); + + mdata->irq[0] = MPC83xx_IRQ_EXT1; + mdata->irq[1] = MPC83xx_IRQ_EXT2; + mdata->irq[2] = -1; + mdata->irq[31] = -1; + mdata->paddr += binfo->bi_immr_base; + /* setup the board related information for the enet controllers */ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->interruptPHY = MPC83xx_IRQ_EXT1; - pdata->phyid = 0; - /* fixup phy address */ - pdata->phy_reg_addr += binfo->bi_immr_base; + pdata->bus_id = GFAR_PHY_0; memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); } pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC2); if (pdata) { pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; - pdata->interruptPHY = MPC83xx_IRQ_EXT2; - pdata->phyid = 1; - /* fixup phy address */ - pdata->phy_reg_addr += binfo->bi_immr_base; + pdata->bus_id = GFAR_PHY_1; memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); } diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c index dbf8acac507..f43fbf9a938 100644 --- a/arch/ppc/syslib/mpc83xx_devices.c +++ b/arch/ppc/syslib/mpc83xx_devices.c @@ -27,18 +27,20 @@ * what IMMRBAR is, will get fixed up by mach_mpc83xx_fixup */ +struct gianfar_mdio_data mpc83xx_mdio_pdata = { + .paddr = 0x24520, +}; + static struct gianfar_platform_data mpc83xx_tsec1_pdata = { .device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT | FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON | FSL_GIANFAR_DEV_HAS_MULTI_INTR, - .phy_reg_addr = 0x24000, }; static struct gianfar_platform_data mpc83xx_tsec2_pdata = { .device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT | FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON | FSL_GIANFAR_DEV_HAS_MULTI_INTR, - .phy_reg_addr = 0x24000, }; static struct fsl_i2c_platform_data mpc83xx_fsl_i2c1_pdata = { @@ -220,6 +222,12 @@ struct platform_device ppc_sys_platform_devices[] = { }, }, }, + [MPC83xx_MDIO] = { + .name = "fsl-gianfar_mdio", + .id = 0, + .dev.platform_data = &mpc83xx_mdio_pdata, + .num_resources = 0, + }, }; static int __init mach_mpc83xx_fixup(struct platform_device *pdev) diff --git a/arch/ppc/syslib/mpc83xx_sys.c b/arch/ppc/syslib/mpc83xx_sys.c index 29aa6335002..da743446789 100644 --- a/arch/ppc/syslib/mpc83xx_sys.c +++ b/arch/ppc/syslib/mpc83xx_sys.c @@ -24,72 +24,72 @@ struct ppc_sys_spec ppc_sys_specs[] = { .ppc_sys_name = "8349E", .mask = 0xFFFF0000, .value = 0x80500000, - .num_devices = 8, + .num_devices = 9, .device_list = (enum ppc_sys_devices[]) { MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1, MPC83xx_IIC2, MPC83xx_DUART, MPC83xx_SEC2, - MPC83xx_USB2_DR, MPC83xx_USB2_MPH + MPC83xx_USB2_DR, MPC83xx_USB2_MPH, MPC83xx_MDIO }, }, { .ppc_sys_name = "8349", .mask = 0xFFFF0000, .value = 0x80510000, - .num_devices = 7, + .num_devices = 8, .device_list = (enum ppc_sys_devices[]) { MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1, MPC83xx_IIC2, MPC83xx_DUART, - MPC83xx_USB2_DR, MPC83xx_USB2_MPH + MPC83xx_USB2_DR, MPC83xx_USB2_MPH, MPC83xx_MDIO }, }, { .ppc_sys_name = "8347E", .mask = 0xFFFF0000, .value = 0x80520000, - .num_devices = 8, + .num_devices = 9, .device_list = (enum ppc_sys_devices[]) { MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1, MPC83xx_IIC2, MPC83xx_DUART, MPC83xx_SEC2, - MPC83xx_USB2_DR, MPC83xx_USB2_MPH + MPC83xx_USB2_DR, MPC83xx_USB2_MPH, MPC83xx_MDIO }, }, { .ppc_sys_name = "8347", .mask = 0xFFFF0000, .value = 0x80530000, - .num_devices = 7, + .num_devices = 8, .device_list = (enum ppc_sys_devices[]) { MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1, MPC83xx_IIC2, MPC83xx_DUART, - MPC83xx_USB2_DR, MPC83xx_USB2_MPH + MPC83xx_USB2_DR, MPC83xx_USB2_MPH, MPC83xx_MDIO }, }, { .ppc_sys_name = "8343E", .mask = 0xFFFF0000, .value = 0x80540000, - .num_devices = 7, + .num_devices = 8, .device_list = (enum ppc_sys_devices[]) { MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1, MPC83xx_IIC2, MPC83xx_DUART, MPC83xx_SEC2, - MPC83xx_USB2_DR, + MPC83xx_USB2_DR, MPC83xx_MDIO }, }, { .ppc_sys_name = "8343", .mask = 0xFFFF0000, .value = 0x80550000, - .num_devices = 6, + .num_devices = 7, .device_list = (enum ppc_sys_devices[]) { MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1, MPC83xx_IIC2, MPC83xx_DUART, - MPC83xx_USB2_DR, + MPC83xx_USB2_DR, MPC83xx_MDIO }, }, { /* default match */ diff --git a/include/asm-ppc/mpc83xx.h b/include/asm-ppc/mpc83xx.h index bb1b0576c94..ce212201db2 100644 --- a/include/asm-ppc/mpc83xx.h +++ b/include/asm-ppc/mpc83xx.h @@ -107,6 +107,7 @@ enum ppc_sys_devices { MPC83xx_SEC2, MPC83xx_USB2_DR, MPC83xx_USB2_MPH, + MPC83xx_MDIO, }; #endif /* CONFIG_83xx */ -- cgit v1.2.3 From a31751e04ea738acc8042e5aa1a825901aa7b97f Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Tue, 8 Nov 2005 21:34:38 -0800 Subject: [PATCH] ppc32: fix perf_irq extern on e500 Fixes e500 build and cleans up traps.c by moving perf_irq extern to pmc.h. Signed-off-by: Matt Porter Cc: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/traps.c | 4 ---- include/asm-powerpc/pmc.h | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 32f215825e8..0578f838760 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -887,10 +887,6 @@ void altivec_unavailable_exception(struct pt_regs *regs) die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT); } -#ifdef CONFIG_PPC64 -extern perf_irq_t perf_irq; -#endif - #if defined(CONFIG_PPC64) || defined(CONFIG_E500) void performance_monitor_exception(struct pt_regs *regs) { diff --git a/include/asm-powerpc/pmc.h b/include/asm-powerpc/pmc.h index 2f3c3fc2b79..5f41f3a2b29 100644 --- a/include/asm-powerpc/pmc.h +++ b/include/asm-powerpc/pmc.h @@ -22,6 +22,7 @@ #include typedef void (*perf_irq_t)(struct pt_regs *); +extern perf_irq_t perf_irq; int reserve_pmc_hardware(perf_irq_t new_perf_irq); void release_pmc_hardware(void); -- cgit v1.2.3 From 054bd4c18853f3a3851bd97aa90e11022a69dc42 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 8 Nov 2005 21:34:39 -0800 Subject: [PATCH] swsusp: reduce code duplication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The changes made by this patch are necessary for the pagedir relocation simplification in the next patch.  Additionally, these changes allow us to drop check_pagedir() and make get_safe_page() be a one-line wrapper around alloc_image_page() (get_safe_page() goes to snapshot.c, because alloc_image_page() is static and it does not make sense to export it). Signed-off-by: Rafael J. Wysocki Cc: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/power/power.h | 3 ++- kernel/power/snapshot.c | 62 ++++++++++++++++++++++++++++++++++++++----------- kernel/power/swsusp.c | 57 ++------------------------------------------- 3 files changed, 52 insertions(+), 70 deletions(-) diff --git a/kernel/power/power.h b/kernel/power/power.h index d4fd96a135a..c98923e13e7 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -66,7 +66,8 @@ extern asmlinkage int swsusp_arch_suspend(void); extern asmlinkage int swsusp_arch_resume(void); extern int restore_highmem(void); -extern struct pbe * alloc_pagedir(unsigned nr_pages); +extern struct pbe *alloc_pagedir(unsigned nr_pages, gfp_t gfp_mask, int safe_needed); extern void create_pbe_list(struct pbe *pblist, unsigned nr_pages); extern void swsusp_free(void); +extern int alloc_data_pages(struct pbe *pblist, gfp_t gfp_mask, int safe_needed); extern int enough_swap(unsigned nr_pages); diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 723f5179883..96cc3e21e97 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -269,9 +269,30 @@ void create_pbe_list(struct pbe *pblist, unsigned int nr_pages) pr_debug("create_pbe_list(): initialized %d PBEs\n", num); } -static void *alloc_image_page(void) +/** + * @safe_needed - on resume, for storing the PBE list and the image, + * we can only use memory pages that do not conflict with the pages + * which had been used before suspend. + * + * The unsafe pages are marked with the PG_nosave_free flag + * + * Allocated but unusable (ie eaten) memory pages should be marked + * so that swsusp_free() can release them + */ + +static inline void *alloc_image_page(gfp_t gfp_mask, int safe_needed) { - void *res = (void *)get_zeroed_page(GFP_ATOMIC | __GFP_COLD); + void *res; + + if (safe_needed) + do { + res = (void *)get_zeroed_page(gfp_mask); + if (res && PageNosaveFree(virt_to_page(res))) + /* This is for swsusp_free() */ + SetPageNosave(virt_to_page(res)); + } while (res && PageNosaveFree(virt_to_page(res))); + else + res = (void *)get_zeroed_page(gfp_mask); if (res) { SetPageNosave(virt_to_page(res)); SetPageNosaveFree(virt_to_page(res)); @@ -279,6 +300,11 @@ static void *alloc_image_page(void) return res; } +unsigned long get_safe_page(gfp_t gfp_mask) +{ + return (unsigned long)alloc_image_page(gfp_mask, 1); +} + /** * alloc_pagedir - Allocate the page directory. * @@ -292,7 +318,7 @@ static void *alloc_image_page(void) * On each page we set up a list of struct_pbe elements. */ -struct pbe *alloc_pagedir(unsigned int nr_pages) +struct pbe *alloc_pagedir(unsigned int nr_pages, gfp_t gfp_mask, int safe_needed) { unsigned int num; struct pbe *pblist, *pbe; @@ -301,12 +327,12 @@ struct pbe *alloc_pagedir(unsigned int nr_pages) return NULL; pr_debug("alloc_pagedir(): nr_pages = %d\n", nr_pages); - pblist = alloc_image_page(); + pblist = alloc_image_page(gfp_mask, safe_needed); /* FIXME: rewrite this ugly loop */ for (pbe = pblist, num = PBES_PER_PAGE; pbe && num < nr_pages; pbe = pbe->next, num += PBES_PER_PAGE) { pbe += PB_PAGE_SKIP; - pbe->next = alloc_image_page(); + pbe->next = alloc_image_page(gfp_mask, safe_needed); } if (!pbe) { /* get_zeroed_page() failed */ free_pagedir(pblist); @@ -354,24 +380,32 @@ static int enough_free_mem(unsigned int nr_pages) (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE); } +int alloc_data_pages(struct pbe *pblist, gfp_t gfp_mask, int safe_needed) +{ + struct pbe *p; + + for_each_pbe (p, pblist) { + p->address = (unsigned long)alloc_image_page(gfp_mask, safe_needed); + if (!p->address) + return -ENOMEM; + } + return 0; +} static struct pbe *swsusp_alloc(unsigned int nr_pages) { - struct pbe *pblist, *p; + struct pbe *pblist; - if (!(pblist = alloc_pagedir(nr_pages))) { + if (!(pblist = alloc_pagedir(nr_pages, GFP_ATOMIC | __GFP_COLD, 0))) { printk(KERN_ERR "suspend: Allocating pagedir failed.\n"); return NULL; } create_pbe_list(pblist, nr_pages); - for_each_pbe (p, pblist) { - p->address = (unsigned long)alloc_image_page(); - if (!p->address) { - printk(KERN_ERR "suspend: Allocating image pages failed.\n"); - swsusp_free(); - return NULL; - } + if (alloc_data_pages(pblist, GFP_ATOMIC | __GFP_COLD, 0)) { + printk(KERN_ERR "suspend: Allocating image pages failed.\n"); + swsusp_free(); + return NULL; } return pblist; diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index e1ab28b9b21..a456ffe7a3c 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -628,59 +628,6 @@ int swsusp_resume(void) return error; } -/** - * On resume, for storing the PBE list and the image, - * we can only use memory pages that do not conflict with the pages - * which had been used before suspend. - * - * We don't know which pages are usable until we allocate them. - * - * Allocated but unusable (ie eaten) memory pages are marked so that - * swsusp_free() can release them - */ - -unsigned long get_safe_page(gfp_t gfp_mask) -{ - unsigned long m; - - do { - m = get_zeroed_page(gfp_mask); - if (m && PageNosaveFree(virt_to_page(m))) - /* This is for swsusp_free() */ - SetPageNosave(virt_to_page(m)); - } while (m && PageNosaveFree(virt_to_page(m))); - if (m) { - /* This is for swsusp_free() */ - SetPageNosave(virt_to_page(m)); - SetPageNosaveFree(virt_to_page(m)); - } - return m; -} - -/** - * check_pagedir - We ensure here that pages that the PBEs point to - * won't collide with pages where we're going to restore from the loaded - * pages later - */ - -static int check_pagedir(struct pbe *pblist) -{ - struct pbe *p; - - /* This is necessary, so that we can free allocated pages - * in case of failure - */ - for_each_pbe (p, pblist) - p->address = 0UL; - - for_each_pbe (p, pblist) { - p->address = get_safe_page(GFP_ATOMIC); - if (!p->address) - return -ENOMEM; - } - return 0; -} - /** * swsusp_pagedir_relocate - It is possible, that some memory pages * occupied by the list of PBEs collide with pages where we're going to @@ -990,7 +937,7 @@ static int read_suspend_image(void) int error = 0; struct pbe *p; - if (!(p = alloc_pagedir(nr_copy_pages))) + if (!(p = alloc_pagedir(nr_copy_pages, GFP_ATOMIC, 0))) return -ENOMEM; if ((error = read_pagedir(p))) @@ -1003,7 +950,7 @@ static int read_suspend_image(void) /* Allocate memory for the image and read the data from swap */ - error = check_pagedir(pagedir_nosave); + error = alloc_data_pages(pagedir_nosave, GFP_ATOMIC, 1); if (!error) error = data_read(pagedir_nosave); -- cgit v1.2.3 From ed14b52701e6ef5a5aaf7bdb75932d5ea5dd7387 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 8 Nov 2005 21:34:40 -0800 Subject: [PATCH] swsusp: simplify pagedir relocation This patch simplifies the relocation of the page backup list (aka pagedir) during resume. Signed-off-by: Rafael J. Wysocki Cc: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/power/power.h | 1 + kernel/power/snapshot.c | 2 +- kernel/power/swsusp.c | 78 +++++++++++++++++-------------------------------- 3 files changed, 28 insertions(+), 53 deletions(-) diff --git a/kernel/power/power.h b/kernel/power/power.h index c98923e13e7..893ee655085 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -66,6 +66,7 @@ extern asmlinkage int swsusp_arch_suspend(void); extern asmlinkage int swsusp_arch_resume(void); extern int restore_highmem(void); +extern void free_pagedir(struct pbe *pblist); extern struct pbe *alloc_pagedir(unsigned nr_pages, gfp_t gfp_mask, int safe_needed); extern void create_pbe_list(struct pbe *pblist, unsigned nr_pages); extern void swsusp_free(void); diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 96cc3e21e97..b8a2e9a6320 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -216,7 +216,7 @@ static void copy_data_pages(struct pbe *pblist) * free_pagedir - free pages allocated with alloc_pagedir() */ -static void free_pagedir(struct pbe *pblist) +void free_pagedir(struct pbe *pblist) { struct pbe *pbe; diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index a456ffe7a3c..8511c7f3386 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -629,74 +629,43 @@ int swsusp_resume(void) } /** - * swsusp_pagedir_relocate - It is possible, that some memory pages - * occupied by the list of PBEs collide with pages where we're going to - * restore from the loaded pages later. We relocate them here. + * mark_unsafe_pages - mark the pages that cannot be used for storing + * the image during resume, because they conflict with the pages that + * had been used before suspend */ -static struct pbe *swsusp_pagedir_relocate(struct pbe *pblist) +static void mark_unsafe_pages(struct pbe *pblist) { struct zone *zone; unsigned long zone_pfn; - struct pbe *pbpage, *tail, *p; - void *m; - int rel = 0; + struct pbe *p; if (!pblist) /* a sanity check */ - return NULL; - - pr_debug("swsusp: Relocating pagedir (%lu pages to check)\n", - swsusp_info.pagedir_pages); + return; /* Clear page flags */ - for_each_zone (zone) { - for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) - if (pfn_valid(zone_pfn + zone->zone_start_pfn)) - ClearPageNosaveFree(pfn_to_page(zone_pfn + + for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) + if (pfn_valid(zone_pfn + zone->zone_start_pfn)) + ClearPageNosaveFree(pfn_to_page(zone_pfn + zone->zone_start_pfn)); } /* Mark orig addresses */ - for_each_pbe (p, pblist) SetPageNosaveFree(virt_to_page(p->orig_address)); - tail = pblist + PB_PAGE_SKIP; - - /* Relocate colliding pages */ - - for_each_pb_page (pbpage, pblist) { - if (PageNosaveFree(virt_to_page((unsigned long)pbpage))) { - m = (void *)get_safe_page(GFP_ATOMIC | __GFP_COLD); - if (!m) - return NULL; - memcpy(m, (void *)pbpage, PAGE_SIZE); - if (pbpage == pblist) - pblist = (struct pbe *)m; - else - tail->next = (struct pbe *)m; - pbpage = (struct pbe *)m; - - /* We have to link the PBEs again */ - for (p = pbpage; p < pbpage + PB_PAGE_SKIP; p++) - if (p->next) /* needed to save the end */ - p->next = p + 1; - - rel++; - } - tail = pbpage + PB_PAGE_SKIP; - } +} - /* This is for swsusp_free() */ - for_each_pb_page (pbpage, pblist) { - SetPageNosave(virt_to_page(pbpage)); - SetPageNosaveFree(virt_to_page(pbpage)); +static void copy_page_backup_list(struct pbe *dst, struct pbe *src) +{ + /* We assume both lists contain the same number of elements */ + while (src) { + dst->orig_address = src->orig_address; + dst->swap_address = src->swap_address; + dst = dst->next; + src = src->next; } - - printk("swsusp: Relocated %d pages\n", rel); - - return pblist; } /* @@ -942,10 +911,15 @@ static int read_suspend_image(void) if ((error = read_pagedir(p))) return error; - create_pbe_list(p, nr_copy_pages); - - if (!(pagedir_nosave = swsusp_pagedir_relocate(p))) + mark_unsafe_pages(p); + pagedir_nosave = alloc_pagedir(nr_copy_pages, GFP_ATOMIC, 1); + if (pagedir_nosave) { + create_pbe_list(pagedir_nosave, nr_copy_pages); + copy_page_backup_list(pagedir_nosave, p); + } + free_pagedir(p); + if (!pagedir_nosave) return -ENOMEM; /* Allocate memory for the image and read the data from swap */ -- cgit v1.2.3 From 0fbeb5a45dccd493c35a68a5548e6a9d9882a791 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 8 Nov 2005 21:34:41 -0800 Subject: [PATCH] swsusp: rework swsusp_suspend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch makes only the functions in swsusp.c call functions in snapshot.c and not both ways.  It also moves the check for available swap out of swsusp_suspend() which is necessary for separating the swap-handling functions in swsusp from the core code. Signed-off-by: Rafael J. Wysocki Cc: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/power/power.h | 2 -- kernel/power/snapshot.c | 19 ++----------- kernel/power/swsusp.c | 75 +++++++++++++++++++++++++++++-------------------- 3 files changed, 47 insertions(+), 49 deletions(-) diff --git a/kernel/power/power.h b/kernel/power/power.h index 893ee655085..6c042b5ee14 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -65,10 +65,8 @@ extern suspend_pagedir_t *pagedir_save; extern asmlinkage int swsusp_arch_suspend(void); extern asmlinkage int swsusp_arch_resume(void); -extern int restore_highmem(void); extern void free_pagedir(struct pbe *pblist); extern struct pbe *alloc_pagedir(unsigned nr_pages, gfp_t gfp_mask, int safe_needed); extern void create_pbe_list(struct pbe *pblist, unsigned nr_pages); extern void swsusp_free(void); extern int alloc_data_pages(struct pbe *pblist, gfp_t gfp_mask, int safe_needed); -extern int enough_swap(unsigned nr_pages); diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index b8a2e9a6320..4a6dbcefd37 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -88,8 +88,7 @@ static int save_highmem_zone(struct zone *zone) return 0; } - -static int save_highmem(void) +int save_highmem(void) { struct zone *zone; int res = 0; @@ -120,11 +119,7 @@ int restore_highmem(void) } return 0; } -#else -static int save_highmem(void) { return 0; } -int restore_highmem(void) { return 0; } -#endif /* CONFIG_HIGHMEM */ - +#endif static int pfn_is_nosave(unsigned long pfn) { @@ -416,11 +411,6 @@ asmlinkage int swsusp_save(void) unsigned int nr_pages; pr_debug("swsusp: critical section: \n"); - if (save_highmem()) { - printk(KERN_CRIT "swsusp: Not enough free pages for highmem\n"); - restore_highmem(); - return -ENOMEM; - } drain_local_pages(); nr_pages = count_data_pages(); @@ -440,11 +430,6 @@ asmlinkage int swsusp_save(void) return -ENOMEM; } - if (!enough_swap(nr_pages)) { - printk(KERN_ERR "swsusp: Not enough free swap\n"); - return -ENOSPC; - } - pagedir_nosave = swsusp_alloc(nr_pages); if (!pagedir_nosave) return -ENOMEM; diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 8511c7f3386..c05f46e7348 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -73,6 +73,14 @@ #include "power.h" +#ifdef CONFIG_HIGHMEM +int save_highmem(void); +int restore_highmem(void); +#else +static int save_highmem(void) { return 0; } +static int restore_highmem(void) { return 0; } +#endif + #define CIPHER "aes" #define MAXKEY 32 #define MAXIV 32 @@ -499,6 +507,26 @@ static int write_pagedir(void) return error; } +/** + * enough_swap - Make sure we have enough swap to save the image. + * + * Returns TRUE or FALSE after checking the total amount of swap + * space avaiable. + * + * FIXME: si_swapinfo(&i) returns all swap devices information. + * We should only consider resume_device. + */ + +static int enough_swap(unsigned int nr_pages) +{ + struct sysinfo i; + + si_swapinfo(&i); + pr_debug("swsusp: available swap: %lu pages\n", i.freeswap); + return i.freeswap > (nr_pages + PAGES_FOR_IO + + (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE); +} + /** * write_suspend_image - Write entire image and metadata. * @@ -507,6 +535,11 @@ static int write_suspend_image(void) { int error; + if (!enough_swap(nr_copy_pages)) { + printk(KERN_ERR "swsusp: Not enough free swap\n"); + return -ENOSPC; + } + init_header(); if ((error = data_write())) goto FreeData; @@ -526,27 +559,6 @@ static int write_suspend_image(void) goto Done; } -/** - * enough_swap - Make sure we have enough swap to save the image. - * - * Returns TRUE or FALSE after checking the total amount of swap - * space avaiable. - * - * FIXME: si_swapinfo(&i) returns all swap devices information. - * We should only consider resume_device. - */ - -int enough_swap(unsigned int nr_pages) -{ - struct sysinfo i; - - si_swapinfo(&i); - pr_debug("swsusp: available swap: %lu pages\n", i.freeswap); - return i.freeswap > (nr_pages + PAGES_FOR_IO + - (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE); -} - - /* It is important _NOT_ to umount filesystems at this point. We want * them synced (in case something goes wrong) but we DO not want to mark * filesystem clean: it is not. (And it does not matter, if we resume @@ -556,12 +568,15 @@ int swsusp_write(void) { int error; + if ((error = swsusp_swap_check())) { + printk(KERN_ERR "swsusp: cannot find swap device, try swapon -a.\n"); + return error; + } lock_swapdevices(); error = write_suspend_image(); /* This will unlock ignored swap devices since writing is finished */ lock_swapdevices(); return error; - } @@ -569,6 +584,7 @@ int swsusp_write(void) int swsusp_suspend(void) { int error; + if ((error = arch_prepare_suspend())) return error; local_irq_disable(); @@ -580,15 +596,12 @@ int swsusp_suspend(void) */ if ((error = device_power_down(PMSG_FREEZE))) { printk(KERN_ERR "Some devices failed to power down, aborting suspend\n"); - local_irq_enable(); - return error; + goto Enable_irqs; } - if ((error = swsusp_swap_check())) { - printk(KERN_ERR "swsusp: cannot find swap device, try swapon -a.\n"); - device_power_up(); - local_irq_enable(); - return error; + if ((error = save_highmem())) { + printk(KERN_ERR "swsusp: Not enough free pages for highmem\n"); + goto Restore_highmem; } save_processor_state(); @@ -596,8 +609,10 @@ int swsusp_suspend(void) printk(KERN_ERR "Error %d suspending\n", error); /* Restore control flow magically appears here */ restore_processor_state(); +Restore_highmem: restore_highmem(); device_power_up(); +Enable_irqs: local_irq_enable(); return error; } @@ -804,7 +819,7 @@ static int check_sig(void) * Reset swap signature now. */ error = bio_write_page(0, &swsusp_header); - } else { + } else { return -EINVAL; } if (!error) -- cgit v1.2.3 From 4448aaf0faafff3f275d15937c28b6346760e028 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 8 Nov 2005 21:34:42 -0800 Subject: [PATCH] s390: "extern inline" -> "static inline" "extern inline" -> "static inline" Signed-off-by: Adrian Bunk Cc: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/s390/Debugging390.txt | 2 +- arch/s390/kernel/debug.c | 12 +++---- arch/s390/mm/fault.c | 2 +- drivers/s390/char/keyboard.h | 4 +-- drivers/s390/cio/qdio.h | 8 ++--- drivers/s390/net/fsm.h | 6 ++-- drivers/s390/s390mach.h | 2 +- include/asm-s390/debug.h | 16 ++++----- include/asm-s390/ebcdic.h | 2 +- include/asm-s390/io.h | 8 ++--- include/asm-s390/lowcore.h | 2 +- include/asm-s390/mmu_context.h | 2 +- include/asm-s390/pgtable.h | 68 ++++++++++++++++++------------------- include/asm-s390/sigp.h | 6 ++-- include/asm-s390/smp.h | 2 +- 15 files changed, 71 insertions(+), 71 deletions(-) diff --git a/Documentation/s390/Debugging390.txt b/Documentation/s390/Debugging390.txt index adbfe620c06..844c03fe792 100644 --- a/Documentation/s390/Debugging390.txt +++ b/Documentation/s390/Debugging390.txt @@ -871,7 +871,7 @@ by playing with the --adjust-vma parameter to objdump. -extern inline void spin_lock(spinlock_t *lp) +static inline void spin_lock(spinlock_t *lp) { a0: 18 34 lr %r3,%r4 a2: a7 3a 03 bc ahi %r3,956 diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index bc59282da76..896d39d0e4c 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c @@ -486,7 +486,7 @@ out: * - goto next entry in p_info */ -extern inline int +static inline int debug_next_entry(file_private_info_t *p_info) { debug_info_t *id; @@ -800,7 +800,7 @@ debug_set_level(debug_info_t* id, int new_level) * - set active entry to next in the ring buffer */ -extern inline void +static inline void proceed_active_entry(debug_info_t * id) { if ((id->active_entries[id->active_area] += id->entry_size) @@ -817,7 +817,7 @@ proceed_active_entry(debug_info_t * id) * - set active area to next in the ring buffer */ -extern inline void +static inline void proceed_active_area(debug_info_t * id) { id->active_area++; @@ -828,7 +828,7 @@ proceed_active_area(debug_info_t * id) * get_active_entry: */ -extern inline debug_entry_t* +static inline debug_entry_t* get_active_entry(debug_info_t * id) { return (debug_entry_t *) (((char *) id->areas[id->active_area] @@ -841,7 +841,7 @@ get_active_entry(debug_info_t * id) * - set timestamp, caller address, cpu number etc. */ -extern inline void +static inline void debug_finish_entry(debug_info_t * id, debug_entry_t* active, int level, int exception) { @@ -971,7 +971,7 @@ debug_entry_t * counts arguments in format string for sprintf view */ -extern inline int +static inline int debug_count_numargs(char *string) { int numargs=0; diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 64e32da7775..fb2607c369e 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -160,7 +160,7 @@ static void do_sigsegv(struct pt_regs *regs, unsigned long error_code, * 11 Page translation -> Not present (nullification) * 3b Region third trans. -> Not present (nullification) */ -extern inline void +static inline void do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection) { struct task_struct *tsk; diff --git a/drivers/s390/char/keyboard.h b/drivers/s390/char/keyboard.h index 3b4da5a9cf7..f7bf45c6bf0 100644 --- a/drivers/s390/char/keyboard.h +++ b/drivers/s390/char/keyboard.h @@ -41,14 +41,14 @@ int kbd_ioctl(struct kbd_data *, struct file *, unsigned int, unsigned long); /* * Helper Functions. */ -extern inline void +static inline void kbd_put_queue(struct tty_struct *tty, int ch) { tty_insert_flip_char(tty, ch, 0); tty_schedule_flip(tty); } -extern inline void +static inline void kbd_puts_queue(struct tty_struct *tty, char *cp) { while (*cp) diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 6b8aa6a852b..328e31cc685 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -265,7 +265,7 @@ QDIO_PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \ /* * Some instructions as assembly */ -extern __inline__ int +static inline int do_siga_sync(unsigned int irq, unsigned int mask1, unsigned int mask2) { int cc; @@ -300,7 +300,7 @@ do_siga_sync(unsigned int irq, unsigned int mask1, unsigned int mask2) return cc; } -extern __inline__ int +static inline int do_siga_input(unsigned int irq, unsigned int mask) { int cc; @@ -334,7 +334,7 @@ do_siga_input(unsigned int irq, unsigned int mask) return cc; } -extern __inline__ int +static inline int do_siga_output(unsigned long irq, unsigned long mask, __u32 *bb) { int cc; @@ -401,7 +401,7 @@ do_siga_output(unsigned long irq, unsigned long mask, __u32 *bb) return cc; } -extern __inline__ unsigned long +static inline unsigned long do_clear_global_summary(void) { diff --git a/drivers/s390/net/fsm.h b/drivers/s390/net/fsm.h index 1b8a7e7c34f..5b98253be7a 100644 --- a/drivers/s390/net/fsm.h +++ b/drivers/s390/net/fsm.h @@ -140,7 +140,7 @@ fsm_record_history(fsm_instance *fi, int state, int event); * 1 if current state or event is out of range * !0 if state and event in range, but no action defined. */ -extern __inline__ int +static inline int fsm_event(fsm_instance *fi, int event, void *arg) { fsm_function_t r; @@ -188,7 +188,7 @@ fsm_event(fsm_instance *fi, int event, void *arg) * @param fi Pointer to FSM * @param state The new state for this FSM. */ -extern __inline__ void +static inline void fsm_newstate(fsm_instance *fi, int newstate) { atomic_set(&fi->state,newstate); @@ -208,7 +208,7 @@ fsm_newstate(fsm_instance *fi, int newstate) * * @return The current state of the FSM. */ -extern __inline__ int +static inline int fsm_getstate(fsm_instance *fi) { return atomic_read(&fi->state); diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h index 4eaa7017918..d9ea7ed2e46 100644 --- a/drivers/s390/s390mach.h +++ b/drivers/s390/s390mach.h @@ -88,7 +88,7 @@ struct crw { #define CRW_ERC_PERRI 0x07 /* perm. error, facility init */ #define CRW_ERC_PMOD 0x08 /* installed parameters modified */ -extern __inline__ int stcrw(struct crw *pcrw ) +static inline int stcrw(struct crw *pcrw ) { int ccode; diff --git a/include/asm-s390/debug.h b/include/asm-s390/debug.h index 7127030ae16..23450ed4b57 100644 --- a/include/asm-s390/debug.h +++ b/include/asm-s390/debug.h @@ -129,7 +129,7 @@ void debug_set_level(debug_info_t* id, int new_level); void debug_stop_all(void); -extern inline debug_entry_t* +static inline debug_entry_t* debug_event(debug_info_t* id, int level, void* data, int length) { if ((!id) || (level > id->level) || (id->pages_per_area == 0)) @@ -137,7 +137,7 @@ debug_event(debug_info_t* id, int level, void* data, int length) return debug_event_common(id,level,data,length); } -extern inline debug_entry_t* +static inline debug_entry_t* debug_int_event(debug_info_t* id, int level, unsigned int tag) { unsigned int t=tag; @@ -146,7 +146,7 @@ debug_int_event(debug_info_t* id, int level, unsigned int tag) return debug_event_common(id,level,&t,sizeof(unsigned int)); } -extern inline debug_entry_t * +static inline debug_entry_t * debug_long_event (debug_info_t* id, int level, unsigned long tag) { unsigned long t=tag; @@ -155,7 +155,7 @@ debug_long_event (debug_info_t* id, int level, unsigned long tag) return debug_event_common(id,level,&t,sizeof(unsigned long)); } -extern inline debug_entry_t* +static inline debug_entry_t* debug_text_event(debug_info_t* id, int level, const char* txt) { if ((!id) || (level > id->level) || (id->pages_per_area == 0)) @@ -168,7 +168,7 @@ debug_sprintf_event(debug_info_t* id,int level,char *string,...) __attribute__ ((format(printf, 3, 4))); -extern inline debug_entry_t* +static inline debug_entry_t* debug_exception(debug_info_t* id, int level, void* data, int length) { if ((!id) || (level > id->level) || (id->pages_per_area == 0)) @@ -176,7 +176,7 @@ debug_exception(debug_info_t* id, int level, void* data, int length) return debug_exception_common(id,level,data,length); } -extern inline debug_entry_t* +static inline debug_entry_t* debug_int_exception(debug_info_t* id, int level, unsigned int tag) { unsigned int t=tag; @@ -185,7 +185,7 @@ debug_int_exception(debug_info_t* id, int level, unsigned int tag) return debug_exception_common(id,level,&t,sizeof(unsigned int)); } -extern inline debug_entry_t * +static inline debug_entry_t * debug_long_exception (debug_info_t* id, int level, unsigned long tag) { unsigned long t=tag; @@ -194,7 +194,7 @@ debug_long_exception (debug_info_t* id, int level, unsigned long tag) return debug_exception_common(id,level,&t,sizeof(unsigned long)); } -extern inline debug_entry_t* +static inline debug_entry_t* debug_text_exception(debug_info_t* id, int level, const char* txt) { if ((!id) || (level > id->level) || (id->pages_per_area == 0)) diff --git a/include/asm-s390/ebcdic.h b/include/asm-s390/ebcdic.h index 20e81e88582..4cbc336e4d6 100644 --- a/include/asm-s390/ebcdic.h +++ b/include/asm-s390/ebcdic.h @@ -21,7 +21,7 @@ extern __u8 _ebcasc[]; /* EBCDIC -> ASCII conversion table */ extern __u8 _ebc_tolower[]; /* EBCDIC -> lowercase */ extern __u8 _ebc_toupper[]; /* EBCDIC -> uppercase */ -extern __inline__ void +static inline void codepage_convert(const __u8 *codepage, volatile __u8 * addr, unsigned long nr) { if (nr-- <= 0) diff --git a/include/asm-s390/io.h b/include/asm-s390/io.h index 8188fdc9884..71f55eb2350 100644 --- a/include/asm-s390/io.h +++ b/include/asm-s390/io.h @@ -24,7 +24,7 @@ * Change virtual addresses to physical addresses and vv. * These are pretty trivial */ -extern inline unsigned long virt_to_phys(volatile void * address) +static inline unsigned long virt_to_phys(volatile void * address) { unsigned long real_address; __asm__ ( @@ -42,7 +42,7 @@ extern inline unsigned long virt_to_phys(volatile void * address) return real_address; } -extern inline void * phys_to_virt(unsigned long address) +static inline void * phys_to_virt(unsigned long address) { return __io_virt(address); } @@ -54,7 +54,7 @@ extern inline void * phys_to_virt(unsigned long address) extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags); -extern inline void * ioremap (unsigned long offset, unsigned long size) +static inline void * ioremap (unsigned long offset, unsigned long size) { return __ioremap(offset, size, 0); } @@ -64,7 +64,7 @@ extern inline void * ioremap (unsigned long offset, unsigned long size) * it's useful if some control registers are in such an area and write combining * or read caching is not desirable: */ -extern inline void * ioremap_nocache (unsigned long offset, unsigned long size) +static inline void * ioremap_nocache (unsigned long offset, unsigned long size) { return __ioremap(offset, size, 0); } diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h index c6f51c9ce3f..db0606c1abd 100644 --- a/include/asm-s390/lowcore.h +++ b/include/asm-s390/lowcore.h @@ -346,7 +346,7 @@ struct _lowcore #define S390_lowcore (*((struct _lowcore *) 0)) extern struct _lowcore *lowcore_ptr[]; -extern __inline__ void set_prefix(__u32 address) +static inline void set_prefix(__u32 address) { __asm__ __volatile__ ("spx %0" : : "m" (address) : "memory" ); } diff --git a/include/asm-s390/mmu_context.h b/include/asm-s390/mmu_context.h index 3a3bb3f2dad..bcf24a87387 100644 --- a/include/asm-s390/mmu_context.h +++ b/include/asm-s390/mmu_context.h @@ -44,7 +44,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, #define deactivate_mm(tsk,mm) do { } while (0) -extern inline void activate_mm(struct mm_struct *prev, +static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next) { switch_mm(prev, next, current); diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h index 9be741bb149..859b5e96982 100644 --- a/include/asm-s390/pgtable.h +++ b/include/asm-s390/pgtable.h @@ -319,7 +319,7 @@ extern char empty_zero_page[PAGE_SIZE]; * within a page table are directly modified. Thus, the following * hook is made available. */ -extern inline void set_pte(pte_t *pteptr, pte_t pteval) +static inline void set_pte(pte_t *pteptr, pte_t pteval) { *pteptr = pteval; } @@ -330,63 +330,63 @@ extern inline void set_pte(pte_t *pteptr, pte_t pteval) */ #ifndef __s390x__ -extern inline int pgd_present(pgd_t pgd) { return 1; } -extern inline int pgd_none(pgd_t pgd) { return 0; } -extern inline int pgd_bad(pgd_t pgd) { return 0; } +static inline int pgd_present(pgd_t pgd) { return 1; } +static inline int pgd_none(pgd_t pgd) { return 0; } +static inline int pgd_bad(pgd_t pgd) { return 0; } -extern inline int pmd_present(pmd_t pmd) { return pmd_val(pmd) & _SEG_PRESENT; } -extern inline int pmd_none(pmd_t pmd) { return pmd_val(pmd) & _PAGE_TABLE_INV; } -extern inline int pmd_bad(pmd_t pmd) +static inline int pmd_present(pmd_t pmd) { return pmd_val(pmd) & _SEG_PRESENT; } +static inline int pmd_none(pmd_t pmd) { return pmd_val(pmd) & _PAGE_TABLE_INV; } +static inline int pmd_bad(pmd_t pmd) { return (pmd_val(pmd) & (~PAGE_MASK & ~_PAGE_TABLE_INV)) != _PAGE_TABLE; } #else /* __s390x__ */ -extern inline int pgd_present(pgd_t pgd) +static inline int pgd_present(pgd_t pgd) { return (pgd_val(pgd) & ~PAGE_MASK) == _PGD_ENTRY; } -extern inline int pgd_none(pgd_t pgd) +static inline int pgd_none(pgd_t pgd) { return pgd_val(pgd) & _PGD_ENTRY_INV; } -extern inline int pgd_bad(pgd_t pgd) +static inline int pgd_bad(pgd_t pgd) { return (pgd_val(pgd) & (~PAGE_MASK & ~_PGD_ENTRY_INV)) != _PGD_ENTRY; } -extern inline int pmd_present(pmd_t pmd) +static inline int pmd_present(pmd_t pmd) { return (pmd_val(pmd) & ~PAGE_MASK) == _PMD_ENTRY; } -extern inline int pmd_none(pmd_t pmd) +static inline int pmd_none(pmd_t pmd) { return pmd_val(pmd) & _PMD_ENTRY_INV; } -extern inline int pmd_bad(pmd_t pmd) +static inline int pmd_bad(pmd_t pmd) { return (pmd_val(pmd) & (~PAGE_MASK & ~_PMD_ENTRY_INV)) != _PMD_ENTRY; } #endif /* __s390x__ */ -extern inline int pte_none(pte_t pte) +static inline int pte_none(pte_t pte) { return (pte_val(pte) & _PAGE_INVALID_MASK) == _PAGE_INVALID_EMPTY; } -extern inline int pte_present(pte_t pte) +static inline int pte_present(pte_t pte) { return !(pte_val(pte) & _PAGE_INVALID) || (pte_val(pte) & _PAGE_INVALID_MASK) == _PAGE_INVALID_NONE; } -extern inline int pte_file(pte_t pte) +static inline int pte_file(pte_t pte) { return (pte_val(pte) & _PAGE_INVALID_MASK) == _PAGE_INVALID_FILE; } @@ -397,12 +397,12 @@ extern inline int pte_file(pte_t pte) * query functions pte_write/pte_dirty/pte_young only work if * pte_present() is true. Undefined behaviour if not.. */ -extern inline int pte_write(pte_t pte) +static inline int pte_write(pte_t pte) { return (pte_val(pte) & _PAGE_RO) == 0; } -extern inline int pte_dirty(pte_t pte) +static inline int pte_dirty(pte_t pte) { /* A pte is neither clean nor dirty on s/390. The dirty bit * is in the storage key. See page_test_and_clear_dirty for @@ -411,7 +411,7 @@ extern inline int pte_dirty(pte_t pte) return 0; } -extern inline int pte_young(pte_t pte) +static inline int pte_young(pte_t pte) { /* A pte is neither young nor old on s/390. The young bit * is in the storage key. See page_test_and_clear_young for @@ -420,7 +420,7 @@ extern inline int pte_young(pte_t pte) return 0; } -extern inline int pte_read(pte_t pte) +static inline int pte_read(pte_t pte) { /* All pages are readable since we don't use the fetch * protection bit in the storage key. @@ -434,9 +434,9 @@ extern inline int pte_read(pte_t pte) #ifndef __s390x__ -extern inline void pgd_clear(pgd_t * pgdp) { } +static inline void pgd_clear(pgd_t * pgdp) { } -extern inline void pmd_clear(pmd_t * pmdp) +static inline void pmd_clear(pmd_t * pmdp) { pmd_val(pmdp[0]) = _PAGE_TABLE_INV; pmd_val(pmdp[1]) = _PAGE_TABLE_INV; @@ -446,12 +446,12 @@ extern inline void pmd_clear(pmd_t * pmdp) #else /* __s390x__ */ -extern inline void pgd_clear(pgd_t * pgdp) +static inline void pgd_clear(pgd_t * pgdp) { pgd_val(*pgdp) = _PGD_ENTRY_INV | _PGD_ENTRY; } -extern inline void pmd_clear(pmd_t * pmdp) +static inline void pmd_clear(pmd_t * pmdp) { pmd_val(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY; pmd_val1(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY; @@ -459,7 +459,7 @@ extern inline void pmd_clear(pmd_t * pmdp) #endif /* __s390x__ */ -extern inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { pte_val(*ptep) = _PAGE_INVALID_EMPTY; } @@ -468,14 +468,14 @@ extern inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt * The following pte modification functions only work if * pte_present() is true. Undefined behaviour if not.. */ -extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) +static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { pte_val(pte) &= PAGE_MASK; pte_val(pte) |= pgprot_val(newprot); return pte; } -extern inline pte_t pte_wrprotect(pte_t pte) +static inline pte_t pte_wrprotect(pte_t pte) { /* Do not clobber _PAGE_INVALID_NONE pages! */ if (!(pte_val(pte) & _PAGE_INVALID)) @@ -483,13 +483,13 @@ extern inline pte_t pte_wrprotect(pte_t pte) return pte; } -extern inline pte_t pte_mkwrite(pte_t pte) +static inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) &= ~_PAGE_RO; return pte; } -extern inline pte_t pte_mkclean(pte_t pte) +static inline pte_t pte_mkclean(pte_t pte) { /* The only user of pte_mkclean is the fork() code. We must *not* clear the *physical* page dirty bit @@ -498,7 +498,7 @@ extern inline pte_t pte_mkclean(pte_t pte) return pte; } -extern inline pte_t pte_mkdirty(pte_t pte) +static inline pte_t pte_mkdirty(pte_t pte) { /* We do not explicitly set the dirty bit because the * sske instruction is slow. It is faster to let the @@ -507,7 +507,7 @@ extern inline pte_t pte_mkdirty(pte_t pte) return pte; } -extern inline pte_t pte_mkold(pte_t pte) +static inline pte_t pte_mkold(pte_t pte) { /* S/390 doesn't keep its dirty/referenced bit in the pte. * There is no point in clearing the real referenced bit. @@ -515,7 +515,7 @@ extern inline pte_t pte_mkold(pte_t pte) return pte; } -extern inline pte_t pte_mkyoung(pte_t pte) +static inline pte_t pte_mkyoung(pte_t pte) { /* S/390 doesn't keep its dirty/referenced bit in the pte. * There is no point in setting the real referenced bit. @@ -695,7 +695,7 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot) #ifndef __s390x__ /* Find an entry in the second-level page table.. */ -extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) +static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) { return (pmd_t *) dir; } @@ -758,7 +758,7 @@ extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) #else #define __SWP_OFFSET_MASK (~0UL >> 11) #endif -extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) +static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) { pte_t pte; offset &= __SWP_OFFSET_MASK; diff --git a/include/asm-s390/sigp.h b/include/asm-s390/sigp.h index 3979bc3858e..fc56458aff6 100644 --- a/include/asm-s390/sigp.h +++ b/include/asm-s390/sigp.h @@ -67,7 +67,7 @@ typedef enum /* * Signal processor */ -extern __inline__ sigp_ccode +static inline sigp_ccode signal_processor(__u16 cpu_addr, sigp_order_code order_code) { sigp_ccode ccode; @@ -86,7 +86,7 @@ signal_processor(__u16 cpu_addr, sigp_order_code order_code) /* * Signal processor with parameter */ -extern __inline__ sigp_ccode +static inline sigp_ccode signal_processor_p(__u32 parameter, __u16 cpu_addr, sigp_order_code order_code) { @@ -107,7 +107,7 @@ signal_processor_p(__u32 parameter, __u16 cpu_addr, /* * Signal processor with parameter and return status */ -extern __inline__ sigp_ccode +static inline sigp_ccode signal_processor_ps(__u32 *statusptr, __u32 parameter, __u16 cpu_addr, sigp_order_code order_code) { diff --git a/include/asm-s390/smp.h b/include/asm-s390/smp.h index dd50e57a928..a2ae7628bba 100644 --- a/include/asm-s390/smp.h +++ b/include/asm-s390/smp.h @@ -52,7 +52,7 @@ extern int smp_call_function_on(void (*func) (void *info), void *info, extern int smp_get_cpu(cpumask_t cpu_map); extern void smp_put_cpu(int cpu); -extern __inline__ __u16 hard_smp_processor_id(void) +static inline __u16 hard_smp_processor_id(void) { __u16 cpu_address; -- cgit v1.2.3 From 88baf3e85af72f606363a85e9a60e9e61cc64a6c Mon Sep 17 00:00:00 2001 From: Jon Masters Date: Tue, 8 Nov 2005 21:34:43 -0800 Subject: [PATCH] fix floppy.c to store correct ro/rw status in underlying gendisk Evgeny Stambulchik found that doing the following always worked: # mount /dev/fd0 /mnt/floppy/ mount: block device /dev/fd0 is write-protected, mounting read-only # mount -o remount,rw /mnt/floppy # echo $? 0 This is the case because the block device /dev/fd0 is writeable but the floppy disk is marked protected. A fix is to simply have floppy_open mark the underlying gendisk policy according to reality (since the VFS doesn't provide a way for do_remount_sb to inquire as to the current device status). Signed-off-by: Jon Masters Cc: Al Viro Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/floppy.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 5eadbb9d4d7..dd1935d5542 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3714,6 +3714,12 @@ static int floppy_open(struct inode *inode, struct file *filp) USETF(FD_VERIFY); } + /* set underlying gendisk policy to reflect real ro/rw status */ + if (UTESTF(FD_DISK_WRITABLE)) + inode->i_bdev->bd_disk->policy = 0; + else + inode->i_bdev->bd_disk->policy = 1; + if (UDRS->fd_ref == -1 || (UDRS->fd_ref && (filp->f_flags & O_EXCL))) goto out2; -- cgit v1.2.3 From cecd1ca0cbd6fc5873e9bb110dacb8411be72928 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 8 Nov 2005 21:34:45 -0800 Subject: [PATCH] schedule obsolete OSS drivers for removal This patch schedules obsolete OSS drivers (with ALSA drivers that support the same hardware) for removal. Scheduling the via82cxxx driver for removal was ACK'ed by Jeff Garzik. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/feature-removal-schedule.txt | 7 +++ sound/oss/Kconfig | 73 ++++++++++++++++++------------ 2 files changed, 51 insertions(+), 29 deletions(-) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index decdf9917e0..910cc999873 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -25,6 +25,13 @@ Who: Adrian Bunk --------------------------- +What: drivers depending on OBSOLETE_OSS_DRIVER +When: January 2006 +Why: OSS drivers with ALSA replacements +Who: Adrian Bunk + +--------------------------- + What: RCU API moves to EXPORT_SYMBOL_GPL When: April 2006 Files: include/linux/rcupdate.h, kernel/rcupdate.c diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig index 953e5f3ea03..88e52dc84c0 100644 --- a/sound/oss/Kconfig +++ b/sound/oss/Kconfig @@ -4,9 +4,24 @@ # More hacking for modularisation. # # Prompt user for primary drivers. + +config OBSOLETE_OSS_DRIVER + bool "Obsolete OSS drivers" + depends on SOUND_PRIME + help + This option enables support for obsolete OSS drivers that + are scheduled for removal in the near future since there + are ALSA drivers for the same hardware. + + Please contact Adrian Bunk if you had to + say Y here because your soundcard is not properly supported + by ALSA. + + If unsure, say N. + config SOUND_BT878 tristate "BT878 audio dma" - depends on SOUND_PRIME && PCI + depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER ---help--- Audio DMA support for bt878 based grabber boards. As you might have already noticed, bt878 is listed with two functions in /proc/pci. @@ -22,7 +37,7 @@ config SOUND_BT878 config SOUND_CMPCI tristate "C-Media PCI (CMI8338/8738)" - depends on SOUND_PRIME && PCI + depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER help Say Y or M if you have a PCI sound card using the CMI8338 or the CMI8738 chipset. Data on these chips are available at @@ -61,7 +76,7 @@ config SOUND_CMPCI_JOYSTICK config SOUND_EMU10K1 tristate "Creative SBLive! (EMU10K1)" - depends on SOUND_PRIME && PCI + depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER ---help--- Say Y or M if you have a PCI sound card using the EMU10K1 chipset, such as the Creative SBLive!, SB PCI512 or Emu-APS. @@ -95,7 +110,7 @@ config SOUND_FUSION config SOUND_CS4281 tristate "Crystal Sound CS4281" - depends on SOUND_PRIME && PCI + depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER help Picture and feature list at . @@ -112,7 +127,7 @@ config SOUND_BCM_CS4297A config SOUND_ES1370 tristate "Ensoniq AudioPCI (ES1370)" - depends on SOUND_PRIME && PCI + depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER help Say Y or M if you have a PCI sound card utilizing the Ensoniq ES1370 chipset, such as Ensoniq's AudioPCI (non-97). To find @@ -125,7 +140,7 @@ config SOUND_ES1370 config SOUND_ES1371 tristate "Creative Ensoniq AudioPCI 97 (ES1371)" - depends on SOUND_PRIME && PCI + depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER help Say Y or M if you have a PCI sound card utilizing the Ensoniq ES1371 chipset, such as Ensoniq's AudioPCI97. To find out if @@ -138,7 +153,7 @@ config SOUND_ES1371 config SOUND_ESSSOLO1 tristate "ESS Technology Solo1" - depends on SOUND_PRIME && PCI + depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER help Say Y or M if you have a PCI sound card utilizing the ESS Technology Solo1 chip. To find out if your sound card uses a @@ -149,7 +164,7 @@ config SOUND_ESSSOLO1 config SOUND_MAESTRO tristate "ESS Maestro, Maestro2, Maestro2E driver" - depends on SOUND_PRIME && PCI + depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER help Say Y or M if you have a sound system driven by ESS's Maestro line of PCI sound chips. These include the Maestro 1, Maestro 2, and @@ -158,7 +173,7 @@ config SOUND_MAESTRO config SOUND_MAESTRO3 tristate "ESS Maestro3/Allegro driver (EXPERIMENTAL)" - depends on SOUND_PRIME && PCI && EXPERIMENTAL + depends on SOUND_PRIME && PCI && EXPERIMENTAL && OBSOLETE_OSS_DRIVER help Say Y or M if you have a sound system driven by ESS's Maestro 3 PCI sound chip. @@ -172,14 +187,14 @@ config SOUND_ICH config SOUND_HARMONY tristate "PA Harmony audio driver" - depends on GSC_LASI && SOUND_PRIME + depends on GSC_LASI && SOUND_PRIME && OBSOLETE_OSS_DRIVER help Say 'Y' or 'M' to include support for Harmony soundchip on HP 712, 715/new and many other GSC based machines. config SOUND_SONICVIBES tristate "S3 SonicVibes" - depends on SOUND_PRIME && PCI + depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER help Say Y or M if you have a PCI sound card utilizing the S3 SonicVibes chipset. To find out if your sound card uses a @@ -218,7 +233,7 @@ config SOUND_VRC5477 config SOUND_AU1000 tristate "Au1000 Sound" - depends on SOUND_PRIME && (SOC_AU1000 || SOC_AU1100 || SOC_AU1500) + depends on SOUND_PRIME && (SOC_AU1000 || SOC_AU1100 || SOC_AU1500) && OBSOLETE_OSS_DRIVER config SOUND_AU1550_AC97 tristate "Au1550 AC97 Sound" @@ -492,7 +507,7 @@ config MSND_FIFOSIZE config SOUND_VIA82CXXX tristate "VIA 82C686 Audio Codec" - depends on SOUND_PRIME && PCI + depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER help Say Y here to include support for the audio codec found on VIA 82Cxxx-based chips. Typically these are built into a motherboard. @@ -563,7 +578,7 @@ config SOUND_AD1889 config SOUND_SGALAXY tristate "Aztech Sound Galaxy (non-PnP) cards" - depends on SOUND_OSS + depends on SOUND_OSS && OBSOLETE_OSS_DRIVER help This module initializes the older non Plug and Play sound galaxy cards from Aztech. It supports the Waverider Pro 32 - 3D and the @@ -599,7 +614,7 @@ config SOUND_ACI_MIXER config SOUND_CS4232 tristate "Crystal CS4232 based (PnP) cards" - depends on SOUND_OSS + depends on SOUND_OSS && OBSOLETE_OSS_DRIVER help Say Y here if you have a card based on the Crystal CS4232 chip set, which uses its own Plug and Play protocol. @@ -613,7 +628,7 @@ config SOUND_CS4232 config SOUND_SSCAPE tristate "Ensoniq SoundScape support" - depends on SOUND_OSS + depends on SOUND_OSS && OBSOLETE_OSS_DRIVER help Answer Y if you have a sound card based on the Ensoniq SoundScape chipset. Such cards are being manufactured at least by Ensoniq, Spea @@ -625,7 +640,7 @@ config SOUND_SSCAPE config SOUND_GUS tristate "Gravis Ultrasound support" - depends on SOUND_OSS + depends on SOUND_OSS && OBSOLETE_OSS_DRIVER help Say Y here for any type of Gravis Ultrasound card, including the GUS or GUS MAX. See also for more @@ -727,7 +742,7 @@ config SOUND_MPU401 config SOUND_NM256 tristate "NM256AV/NM256ZX audio support" - depends on SOUND_OSS + depends on SOUND_OSS && OBSOLETE_OSS_DRIVER help Say M here to include audio support for the NeoMagic 256AV/256ZX chipsets. These are the audio chipsets found in the Sony @@ -739,7 +754,7 @@ config SOUND_NM256 config SOUND_MAD16 tristate "OPTi MAD16 and/or Mozart based cards" - depends on SOUND_OSS + depends on SOUND_OSS && OBSOLETE_OSS_DRIVER ---help--- Answer Y if your card has a Mozart (OAK OTI-601) or MAD16 (OPTi 82C928 or 82C929 or 82C931) audio interface chip. These chips are @@ -860,7 +875,7 @@ config SOUND_SB config SOUND_AWE32_SYNTH tristate "AWE32 synth" - depends on SOUND_OSS + depends on SOUND_OSS && OBSOLETE_OSS_DRIVER help Say Y here if you have a Sound Blaster SB32, AWE32-PnP, SB AWE64 or similar sound card. See , @@ -870,7 +885,7 @@ config SOUND_AWE32_SYNTH config SOUND_WAVEFRONT tristate "Full support for Turtle Beach WaveFront (Tropez Plus, Tropez, Maui) synth/soundcards" - depends on SOUND_OSS && m + depends on SOUND_OSS && m && OBSOLETE_OSS_DRIVER help Answer Y or M if you have a Tropez Plus, Tropez or Maui sound card and read the files and @@ -878,7 +893,7 @@ config SOUND_WAVEFRONT config SOUND_MAUI tristate "Limited support for Turtle Beach Wave Front (Maui, Tropez) synthesizers" - depends on SOUND_OSS + depends on SOUND_OSS && OBSOLETE_OSS_DRIVER help Say Y here if you have a Turtle Beach Wave Front, Maui, or Tropez sound card. @@ -904,7 +919,7 @@ config MAUI_BOOT_FILE config SOUND_YM3812 tristate "Yamaha FM synthesizer (YM3812/OPL-3) support" - depends on SOUND_OSS + depends on SOUND_OSS && OBSOLETE_OSS_DRIVER ---help--- Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4). Answering Y is usually a safe and recommended choice, however some @@ -920,7 +935,7 @@ config SOUND_YM3812 config SOUND_OPL3SA1 tristate "Yamaha OPL3-SA1 audio controller" - depends on SOUND_OSS + depends on SOUND_OSS && OBSOLETE_OSS_DRIVER help Say Y or M if you have a Yamaha OPL3-SA1 sound chip, which is usually built into motherboards. Read @@ -946,7 +961,7 @@ config SOUND_OPL3SA2 config SOUND_YMFPCI tristate "Yamaha YMF7xx PCI audio (native mode)" - depends on SOUND_OSS && PCI + depends on SOUND_OSS && PCI && OBSOLETE_OSS_DRIVER help Support for Yamaha cards including the YMF711, YMF715, YMF718, YMF719, YMF724, Waveforce 192XG, and Waveforce 192 Digital. @@ -1088,11 +1103,11 @@ config SOUND_KAHLUA config SOUND_ALI5455 tristate "ALi5455 audio support" - depends on SOUND_PRIME && PCI + depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER config SOUND_FORTE tristate "ForteMedia FM801 driver" - depends on SOUND_PRIME && PCI + depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER help Say Y or M if you want driver support for the ForteMedia FM801 PCI audio controller (Abit AU10, Genius Sound Maker, HP Workstation @@ -1100,7 +1115,7 @@ config SOUND_FORTE config SOUND_RME96XX tristate "RME Hammerfall (RME96XX) support" - depends on SOUND_PRIME && PCI + depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER help Say Y or M if you have a Hammerfall or Hammerfall light multichannel card from RME. If you want to access advanced @@ -1108,7 +1123,7 @@ config SOUND_RME96XX config SOUND_AD1980 tristate "AD1980 front/back switch plugin" - depends on SOUND_PRIME + depends on SOUND_PRIME && OBSOLETE_OSS_DRIVER config SOUND_SH_DAC_AUDIO tristate "SuperH DAC audio support" -- cgit v1.2.3 From 3f04e7ddf47a1c821dfaa886161d94774af583fa Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 8 Nov 2005 21:34:46 -0800 Subject: [PATCH] kconfig: Fix Kconfig performance bug When doing its recursive dependency check, scripts/kconfig/conf uses the flag SYMBOL_CHECK_DONE to avoid rechecking a symbol it has already checked. However, that flag is only set at the top level, so if a symbol is first encountered as a dependency of another symbol it will be rechecked every time it is encountered until it's encountered at the top level. This patch adjusts the flag setting so that each symbol will only be checked once, regardless of whether it is first encountered at the top level, or while recursing down from another symbol. On complex configurations, this vastly speeds up scripts/kconfig/conf. The config in the powerpc merge tree is particularly bad: this patch reduces the time for 'scripts/kconfig/conf -o arch/powerpc/Kconfig' by a factor of 40 on a G5. That's even including the time to print the config, so the speedup in the actual checking is more likely 2 or 3 orders of magnitude. Signed-off-by: David Gibson Signed-off-by: Roman Zippel Cc: Sam Ravnborg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/kconfig/expr.h | 1 - scripts/kconfig/symbol.c | 11 ++++++++--- scripts/kconfig/zconf.tab.c_shipped | 5 +---- scripts/kconfig/zconf.y | 5 +---- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h index 7d39ff43e6e..1b36ef18c48 100644 --- a/scripts/kconfig/expr.h +++ b/scripts/kconfig/expr.h @@ -93,7 +93,6 @@ struct symbol { #define SYMBOL_NEW 0x0800 #define SYMBOL_AUTO 0x1000 #define SYMBOL_CHECKED 0x2000 -#define SYMBOL_CHECK_DONE 0x4000 #define SYMBOL_WARNED 0x8000 #define SYMBOL_MAXLENGTH 256 diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index affa52f5c65..10d96c4188d 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c @@ -731,12 +731,12 @@ struct symbol *sym_check_deps(struct symbol *sym) struct symbol *sym2; struct property *prop; - if (sym->flags & SYMBOL_CHECK_DONE) - return NULL; if (sym->flags & SYMBOL_CHECK) { printf("Warning! Found recursive dependency: %s", sym->name); return sym; } + if (sym->flags & SYMBOL_CHECKED) + return NULL; sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); sym2 = sym_check_expr_deps(sym->rev_dep.expr); @@ -756,8 +756,13 @@ struct symbol *sym_check_deps(struct symbol *sym) goto out; } out: - if (sym2) + if (sym2) { printf(" %s", sym->name); + if (sym2 == sym) { + printf("\n"); + sym2 = NULL; + } + } sym->flags &= ~SYMBOL_CHECK; return sym2; } diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped index ff4fcc09720..da12f7b33be 100644 --- a/scripts/kconfig/zconf.tab.c_shipped +++ b/scripts/kconfig/zconf.tab.c_shipped @@ -1933,10 +1933,7 @@ void conf_parse(const char *name) exit(1); menu_finalize(&rootmenu); for_all_symbols(i, sym) { - if (!(sym->flags & SYMBOL_CHECKED) && sym_check_deps(sym)) - printf("\n"); - else - sym->flags |= SYMBOL_CHECK_DONE; + sym_check_deps(sym); } sym_change_count = 1; diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y index e1a0f455d4a..1e214e9c1d3 100644 --- a/scripts/kconfig/zconf.y +++ b/scripts/kconfig/zconf.y @@ -495,10 +495,7 @@ void conf_parse(const char *name) exit(1); menu_finalize(&rootmenu); for_all_symbols(i, sym) { - if (!(sym->flags & SYMBOL_CHECKED) && sym_check_deps(sym)) - printf("\n"); - else - sym->flags |= SYMBOL_CHECK_DONE; + sym_check_deps(sym); } sym_change_count = 1; -- cgit v1.2.3 From 3f23ca2b37d13a89bb6cd0421821fc9c3b8ccd47 Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Tue, 8 Nov 2005 21:34:48 -0800 Subject: [PATCH] kconfig: fix restart for choice symbols The restart check whether new symbols became visible, didn't always work for choice symbols. Even if a choice symbol itself isn't changable, the childs are. This also requires to update the new status of all choice values, once one of them is set. Signed-off-by: Roman Zippel Cc: Sam Ravnborg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/kconfig/conf.c | 7 +++---- scripts/kconfig/symbol.c | 11 +++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index bc20cab9d0d..dffbf2ea1f9 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c @@ -467,15 +467,14 @@ static void check_conf(struct menu *menu) return; sym = menu->sym; - if (sym) { - if (sym_is_changable(sym) && !sym_has_value(sym)) { + if (sym && !sym_has_value(sym)) { + if (sym_is_changable(sym) || + (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { if (!conf_cnt++) printf(_("*\n* Restart config...\n*\n")); rootEntry = menu_get_parent_menu(menu); conf(rootEntry); } - if (sym_is_choice(sym) && sym_get_tristate_value(sym) != mod) - return; } for (child = menu->list; child; child = child->next) diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index 10d96c4188d..29bff43adc5 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c @@ -380,11 +380,22 @@ bool sym_set_tristate_value(struct symbol *sym, tristate val) sym->flags &= ~SYMBOL_NEW; sym_set_changed(sym); } + /* + * setting a choice value also resets the new flag of the choice + * symbol and all other choice values. + */ if (sym_is_choice_value(sym) && val == yes) { struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); + struct property *prop; + struct expr *e; cs->user.val = sym; cs->flags &= ~SYMBOL_NEW; + prop = sym_get_choice_prop(cs); + for (e = prop->expr; e; e = e->left.expr) { + if (e->right.sym->visible != no) + e->right.sym->flags &= ~SYMBOL_NEW; + } } sym->user.tri = val; -- cgit v1.2.3 From 90389160efc2864501ced6e662f9419eb7a3e6c8 Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Tue, 8 Nov 2005 21:34:49 -0800 Subject: [PATCH] kconfig: preset config during all*config Allow to force setting of config variables during all{no,mod,yes,random}config to a specific value. For that conf first checks the KCONFIG_ALLCONFIG environment variable for a file name, otherwise it checks for all{no,mod,yes,random}.config and all.config. The file is a normal config file, which presets the config variables, but they are still subject to normal dependency checks. Signed-off-by: Roman Zippel Cc: Sam Ravnborg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/kconfig/conf.c | 30 ++++++++++++++++++++++++++++++ scripts/kconfig/confdata.c | 17 ++++++++++++++--- scripts/kconfig/lkc_proto.h | 1 + 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index dffbf2ea1f9..8ba5d29d3d4 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c @@ -82,6 +82,15 @@ static void conf_askvalue(struct symbol *sym, const char *def) } switch (input_mode) { + case set_no: + case set_mod: + case set_yes: + case set_random: + if (sym_has_value(sym)) { + printf("%s\n", def); + return; + } + break; case ask_new: case ask_silent: if (sym_has_value(sym)) { @@ -558,6 +567,27 @@ int main(int ac, char **av) case ask_new: conf_read(NULL); break; + case set_no: + case set_mod: + case set_yes: + case set_random: + name = getenv("KCONFIG_ALLCONFIG"); + if (name && !stat(name, &tmpstat)) { + conf_read_simple(name); + break; + } + switch (input_mode) { + case set_no: name = "allno.config"; break; + case set_mod: name = "allmod.config"; break; + case set_yes: name = "allyes.config"; break; + case set_random: name = "allrandom.config"; break; + default: break; + } + if (!stat(name, &tmpstat)) + conf_read_simple(name); + else if (!stat("all.config", &tmpstat)) + conf_read_simple("all.config"); + break; default: break; } diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 02f670cc6bb..4bba6202b79 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -69,15 +69,13 @@ char *conf_get_default_confname(void) return name; } -int conf_read(const char *name) +int conf_read_simple(const char *name) { FILE *in = NULL; char line[1024]; char *p, *p2; int lineno = 0; struct symbol *sym; - struct property *prop; - struct expr *e; int i; if (name) { @@ -232,6 +230,19 @@ int conf_read(const char *name) if (modules_sym) sym_calc_value(modules_sym); + return 0; +} + +int conf_read(const char *name) +{ + struct symbol *sym; + struct property *prop; + struct expr *e; + int i; + + if (conf_read_simple(name)) + return 1; + for_all_symbols(i, sym) { sym_calc_value(sym); if (sym_has_value(sym) && !sym_is_choice_value(sym)) { diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h index 6dc6d0c48e7..b6a389c5fcb 100644 --- a/scripts/kconfig/lkc_proto.h +++ b/scripts/kconfig/lkc_proto.h @@ -2,6 +2,7 @@ /* confdata.c */ P(conf_parse,void,(const char *name)); P(conf_read,int,(const char *name)); +P(conf_read_simple,int,(const char *name)); P(conf_write,int,(const char *name)); /* menu.c */ -- cgit v1.2.3 From 4cf3cbe2a9682242cd38897914b1f2a95f1db7e4 Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Tue, 8 Nov 2005 21:34:49 -0800 Subject: [PATCH] kconfig: allow variable argumnts for range This allows variable arguments in the range option for int and hex config symbols. Signed-off-by: Roman Zippel Cc: Sam Ravnborg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/kconfig/menu.c | 10 +++++++-- scripts/kconfig/symbol.c | 58 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index 5cfa6c405cf..c2a423a1c34 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c @@ -151,6 +151,12 @@ void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep) menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep); } +static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2) +{ + return sym2->type == S_INT || sym2->type == S_HEX || + (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name)); +} + void sym_check_prop(struct symbol *sym) { struct property *prop; @@ -185,8 +191,8 @@ void sym_check_prop(struct symbol *sym) if (sym->type != S_INT && sym->type != S_HEX) prop_warn(prop, "range is only allowed " "for int or hex symbols"); - if (!sym_string_valid(sym, prop->expr->left.sym->name) || - !sym_string_valid(sym, prop->expr->right.sym->name)) + if (!menu_range_valid_sym(sym, prop->expr->left.sym) || + !menu_range_valid_sym(sym, prop->expr->right.sym)) prop_warn(prop, "range is invalid"); break; default: diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index 29bff43adc5..69c2549c0ba 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c @@ -141,6 +141,55 @@ struct property *sym_get_range_prop(struct symbol *sym) return NULL; } +static int sym_get_range_val(struct symbol *sym, int base) +{ + sym_calc_value(sym); + switch (sym->type) { + case S_INT: + base = 10; + break; + case S_HEX: + base = 16; + break; + default: + break; + } + return strtol(sym->curr.val, NULL, base); +} + +static void sym_validate_range(struct symbol *sym) +{ + struct property *prop; + int base, val, val2; + char str[64]; + + switch (sym->type) { + case S_INT: + base = 10; + break; + case S_HEX: + base = 16; + break; + default: + return; + } + prop = sym_get_range_prop(sym); + if (!prop) + return; + val = strtol(sym->curr.val, NULL, base); + val2 = sym_get_range_val(prop->expr->left.sym, base); + if (val >= val2) { + val2 = sym_get_range_val(prop->expr->right.sym, base); + if (val <= val2) + return; + } + if (sym->type == S_INT) + sprintf(str, "%d", val2); + else + sprintf(str, "0x%x", val2); + sym->curr.val = strdup(str); +} + static void sym_calc_visibility(struct symbol *sym) { struct property *prop; @@ -301,6 +350,7 @@ void sym_calc_value(struct symbol *sym) sym->curr = newval; if (sym_is_choice(sym) && newval.tri == yes) sym->curr.val = sym_calc_choice(sym); + sym_validate_range(sym); if (memcmp(&oldval, &sym->curr, sizeof(oldval))) sym_set_changed(sym); @@ -489,8 +539,8 @@ bool sym_string_within_range(struct symbol *sym, const char *str) if (!prop) return true; val = strtol(str, NULL, 10); - return val >= strtol(prop->expr->left.sym->name, NULL, 10) && - val <= strtol(prop->expr->right.sym->name, NULL, 10); + return val >= sym_get_range_val(prop->expr->left.sym, 10) && + val <= sym_get_range_val(prop->expr->right.sym, 10); case S_HEX: if (!sym_string_valid(sym, str)) return false; @@ -498,8 +548,8 @@ bool sym_string_within_range(struct symbol *sym, const char *str) if (!prop) return true; val = strtol(str, NULL, 16); - return val >= strtol(prop->expr->left.sym->name, NULL, 16) && - val <= strtol(prop->expr->right.sym->name, NULL, 16); + return val >= sym_get_range_val(prop->expr->left.sym, 16) && + val <= sym_get_range_val(prop->expr->right.sym, 16); case S_BOOLEAN: case S_TRISTATE: switch (str[0]) { -- cgit v1.2.3 From 491d711035dc08071ed58cf470f15efadb67cb1c Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Tue, 8 Nov 2005 21:34:50 -0800 Subject: [PATCH] kconfig: update kconfig Makefile Remove the long obsolete zconf.tab.h and fix kconfig make rules to generate the correct output files. Setting LKC_GENPARSER will now also update the shipped files. Signed-off-by: Roman Zippel Cc: Sam Ravnborg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/kconfig/Makefile | 18 ++---- scripts/kconfig/zconf.tab.h_shipped | 125 ------------------------------------ 2 files changed, 7 insertions(+), 136 deletions(-) delete mode 100644 scripts/kconfig/zconf.tab.h_shipped diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index c65c435c492..65e3e737125 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile @@ -114,7 +114,7 @@ gconf-objs := gconf.o kconfig_load.o zconf.tab.o endif clean-files := lkc_defs.h qconf.moc .tmp_qtcheck \ - .tmp_gtkcheck zconf.tab.c zconf.tab.h lex.zconf.c + .tmp_gtkcheck zconf.tab.c lex.zconf.c # Needed for systems without gettext KBUILD_HAVE_NLS := $(shell \ @@ -136,12 +136,6 @@ HOSTLOADLIBES_gconf = `pkg-config gtk+-2.0 gmodule-2.0 libglade-2.0 --libs` HOSTCFLAGS_gconf.o = `pkg-config gtk+-2.0 gmodule-2.0 libglade-2.0 --cflags` \ -D LKC_DIRECT_LINK -$(obj)/conf.o $(obj)/mconf.o $(obj)/qconf.o $(obj)/gconf.o $(obj)/kxgettext: $(obj)/zconf.tab.h - -$(obj)/zconf.tab.h: $(src)/zconf.tab.h_shipped -$(obj)/zconf.tab.c: $(src)/zconf.tab.c_shipped -$(obj)/lex.zconf.c: $(src)/lex.zconf.c_shipped - $(obj)/qconf.o: $(obj)/.tmp_qtcheck ifeq ($(qconf-target),1) @@ -230,13 +224,15 @@ $(obj)/lkc_defs.h: $(src)/lkc_proto.h ifdef LKC_GENPARSER -$(obj)/zconf.tab.c: $(obj)/zconf.y -$(obj)/zconf.tab.h: $(obj)/zconf.tab.c +$(obj)/zconf.tab.c: $(src)/zconf.y +$(obj)/lex.zconf.c: $(src)/zconf.l %.tab.c: %.y - bison -t -d -v -b $* -p $(notdir $*) $< + bison -l -b $* -p $(notdir $*) $< + cp $@ $@_shipped lex.%.c: %.l - flex -P$(notdir $*) -o$@ $< + flex -L -P$(notdir $*) -o$@ $< + cp $@ $@_shipped endif diff --git a/scripts/kconfig/zconf.tab.h_shipped b/scripts/kconfig/zconf.tab.h_shipped deleted file mode 100644 index 3b191ef5998..00000000000 --- a/scripts/kconfig/zconf.tab.h_shipped +++ /dev/null @@ -1,125 +0,0 @@ -/* A Bison parser, made from zconf.y, by GNU bison 1.75. */ - -/* Skeleton parser for Yacc-like parsing with Bison, - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc. - - 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, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* As a special exception, when this file is copied by Bison into a - Bison output file, you may use that output file without restriction. - This special exception was added by the Free Software Foundation - in version 1.24 of Bison. */ - -#ifndef BISON_ZCONF_TAB_H -# define BISON_ZCONF_TAB_H - -/* Tokens. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - T_MAINMENU = 258, - T_MENU = 259, - T_ENDMENU = 260, - T_SOURCE = 261, - T_CHOICE = 262, - T_ENDCHOICE = 263, - T_COMMENT = 264, - T_CONFIG = 265, - T_HELP = 266, - T_HELPTEXT = 267, - T_IF = 268, - T_ENDIF = 269, - T_DEPENDS = 270, - T_REQUIRES = 271, - T_OPTIONAL = 272, - T_PROMPT = 273, - T_DEFAULT = 274, - T_TRISTATE = 275, - T_BOOLEAN = 276, - T_INT = 277, - T_HEX = 278, - T_WORD = 279, - T_STRING = 280, - T_UNEQUAL = 281, - T_EOF = 282, - T_EOL = 283, - T_CLOSE_PAREN = 284, - T_OPEN_PAREN = 285, - T_ON = 286, - T_OR = 287, - T_AND = 288, - T_EQUAL = 289, - T_NOT = 290 - }; -#endif -#define T_MAINMENU 258 -#define T_MENU 259 -#define T_ENDMENU 260 -#define T_SOURCE 261 -#define T_CHOICE 262 -#define T_ENDCHOICE 263 -#define T_COMMENT 264 -#define T_CONFIG 265 -#define T_HELP 266 -#define T_HELPTEXT 267 -#define T_IF 268 -#define T_ENDIF 269 -#define T_DEPENDS 270 -#define T_REQUIRES 271 -#define T_OPTIONAL 272 -#define T_PROMPT 273 -#define T_DEFAULT 274 -#define T_TRISTATE 275 -#define T_BOOLEAN 276 -#define T_INT 277 -#define T_HEX 278 -#define T_WORD 279 -#define T_STRING 280 -#define T_UNEQUAL 281 -#define T_EOF 282 -#define T_EOL 283 -#define T_CLOSE_PAREN 284 -#define T_OPEN_PAREN 285 -#define T_ON 286 -#define T_OR 287 -#define T_AND 288 -#define T_EQUAL 289 -#define T_NOT 290 - - - - -#ifndef YYSTYPE -#line 33 "zconf.y" -typedef union { - int token; - char *string; - struct symbol *symbol; - struct expr *expr; - struct menu *menu; -} yystype; -/* Line 1281 of /usr/share/bison/yacc.c. */ -#line 118 "zconf.tab.h" -# define YYSTYPE yystype -#endif - -extern YYSTYPE zconflval; - - -#endif /* not BISON_ZCONF_TAB_H */ - -- cgit v1.2.3 From 7a88488bbc231e48a4a88ee2569bc0cc5d706f0a Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Tue, 8 Nov 2005 21:34:51 -0800 Subject: [PATCH] kconfig: use gperf for kconfig keywords Use gperf to generate a hash for the kconfig keywords. This greatly reduces the size of the generated scanner and makes it easier to extend kconfig. Signed-off-by: Roman Zippel Cc: Sam Ravnborg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/kconfig/Makefile | 11 +- scripts/kconfig/lex.zconf.c_shipped | 1753 ++++------------------------------ scripts/kconfig/lkc.h | 10 + scripts/kconfig/zconf.gperf | 43 + scripts/kconfig/zconf.hash.c_shipped | 231 +++++ scripts/kconfig/zconf.l | 53 +- scripts/kconfig/zconf.tab.c_shipped | 455 +++++---- scripts/kconfig/zconf.y | 9 +- 8 files changed, 760 insertions(+), 1805 deletions(-) create mode 100644 scripts/kconfig/zconf.gperf create mode 100644 scripts/kconfig/zconf.hash.c_shipped diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index 65e3e737125..9d67782b812 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile @@ -114,7 +114,7 @@ gconf-objs := gconf.o kconfig_load.o zconf.tab.o endif clean-files := lkc_defs.h qconf.moc .tmp_qtcheck \ - .tmp_gtkcheck zconf.tab.c lex.zconf.c + .tmp_gtkcheck zconf.tab.c lex.zconf.c zconf.hash.c # Needed for systems without gettext KBUILD_HAVE_NLS := $(shell \ @@ -201,7 +201,7 @@ $(obj)/.tmp_gtkcheck: fi endif -$(obj)/zconf.tab.o: $(obj)/lex.zconf.c +$(obj)/zconf.tab.o: $(obj)/lex.zconf.c $(obj)/zconf.hash.c $(obj)/kconfig_load.o: $(obj)/lkc_defs.h @@ -217,7 +217,7 @@ $(obj)/lkc_defs.h: $(src)/lkc_proto.h ### -# The following requires flex/bison +# The following requires flex/bison/gperf # By default we use the _shipped versions, uncomment the following line if # you are modifying the flex/bison src. # LKC_GENPARSER := 1 @@ -226,6 +226,7 @@ ifdef LKC_GENPARSER $(obj)/zconf.tab.c: $(src)/zconf.y $(obj)/lex.zconf.c: $(src)/zconf.l +$(obj)/zconf.hash.c: $(src)/zconf.gperf %.tab.c: %.y bison -l -b $* -p $(notdir $*) $< @@ -235,4 +236,8 @@ lex.%.c: %.l flex -L -P$(notdir $*) -o$@ $< cp $@ $@_shipped +%.hash.c: %.gperf + gperf < $< > $@ + cp $@ $@_shipped + endif diff --git a/scripts/kconfig/lex.zconf.c_shipped b/scripts/kconfig/lex.zconf.c_shipped index 22dda11f758..0168141417f 100644 --- a/scripts/kconfig/lex.zconf.c_shipped +++ b/scripts/kconfig/lex.zconf.c_shipped @@ -1,5 +1,5 @@ -#line 3 "lex.zconf.c" +#line 3 "scripts/kconfig/lex.zconf.c" #define YY_INT_ALIGNED short int @@ -338,1567 +338,323 @@ int zconflineno = 1; extern char *zconftext; #define yytext_ptr zconftext -static yyconst flex_int16_t yy_nxt[][38] = +static yyconst flex_int16_t yy_nxt[][17] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 - }, - - { - 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12 - }, - - { - 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12 - }, - - { - 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 18, 16, 16, 18, 18, 19, 20, - 21, 22, 18, 18, 23, 24, 18, 25, 18, 26, - 27, 18, 28, 29, 30, 18, 18, 16 - }, - - { - 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 18, 16, 16, 18, 18, 19, 20, - 21, 22, 18, 18, 23, 24, 18, 25, 18, 26, - 27, 18, 28, 29, 30, 18, 18, 16 - - }, - - { - 11, 31, 32, 33, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31 - }, - - { - 11, 31, 32, 33, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31 - }, - - { - 11, 34, 34, 35, 34, 36, 34, 34, 36, 34, - 34, 34, 34, 34, 34, 37, 34, 34, 34, 34, - - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34 - }, - - { - 11, 34, 34, 35, 34, 36, 34, 34, 36, 34, - 34, 34, 34, 34, 34, 37, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34 - }, - - { - 11, 38, 38, 39, 40, 41, 42, 43, 41, 44, - 45, 46, 47, 47, 48, 49, 47, 47, 47, 47, - 47, 47, 47, 47, 47, 50, 47, 47, 47, 51, - 47, 47, 47, 47, 47, 47, 47, 52 - - }, - - { - 11, 38, 38, 39, 40, 41, 42, 43, 41, 44, - 45, 46, 47, 47, 48, 49, 47, 47, 47, 47, - 47, 47, 47, 47, 47, 50, 47, 47, 47, 51, - 47, 47, 47, 47, 47, 47, 47, 52 - }, - - { - -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, - -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, - -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, - -11, -11, -11, -11, -11, -11, -11, -11 - }, - - { - 11, -12, -12, -12, -12, -12, -12, -12, -12, -12, - -12, -12, -12, -12, -12, -12, -12, -12, -12, -12, - - -12, -12, -12, -12, -12, -12, -12, -12, -12, -12, - -12, -12, -12, -12, -12, -12, -12, -12 - }, - - { - 11, -13, 53, 54, -13, -13, 55, -13, -13, -13, - -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, - -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, - -13, -13, -13, -13, -13, -13, -13, -13 - }, - - { - 11, -14, -14, -14, -14, -14, -14, -14, -14, -14, - -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, - -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, - -14, -14, -14, -14, -14, -14, -14, -14 - - }, - - { - 11, 56, 56, 57, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56 - }, - - { - 11, -16, -16, -16, -16, -16, -16, -16, -16, -16, - -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, - -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, - -16, -16, -16, -16, -16, -16, -16, -16 - }, - - { - 11, -17, -17, -17, -17, -17, -17, -17, -17, -17, - -17, -17, -17, -17, -17, -17, -17, -17, -17, -17, - - -17, -17, -17, -17, -17, -17, -17, -17, -17, -17, - -17, -17, -17, -17, -17, -17, -17, -17 - }, - - { - 11, -18, -18, -18, -18, -18, -18, -18, -18, -18, - -18, -18, -18, 58, -18, -18, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -18 - }, - - { - 11, -19, -19, -19, -19, -19, -19, -19, -19, -19, - -19, -19, -19, 58, -19, -19, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 59, - 58, 58, 58, 58, 58, 58, 58, -19 - - }, - - { - 11, -20, -20, -20, -20, -20, -20, -20, -20, -20, - -20, -20, -20, 58, -20, -20, 58, 58, 58, 58, - 58, 58, 58, 58, 60, 58, 58, 58, 58, 61, - 58, 58, 58, 58, 58, 58, 58, -20 - }, - - { - 11, -21, -21, -21, -21, -21, -21, -21, -21, -21, - -21, -21, -21, 58, -21, -21, 58, 58, 58, 58, - 58, 62, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -21 - }, - - { - 11, -22, -22, -22, -22, -22, -22, -22, -22, -22, - -22, -22, -22, 58, -22, -22, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 63, 58, - 58, 58, 58, 58, 58, 58, 58, -22 - }, - - { - 11, -23, -23, -23, -23, -23, -23, -23, -23, -23, - -23, -23, -23, 58, -23, -23, 58, 58, 58, 58, - 58, 64, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -23 - }, - - { - 11, -24, -24, -24, -24, -24, -24, -24, -24, -24, - -24, -24, -24, 58, -24, -24, 58, 58, 58, 58, - 58, 58, 65, 58, 58, 58, 58, 58, 66, 58, - 58, 58, 58, 58, 58, 58, 58, -24 - - }, - - { - 11, -25, -25, -25, -25, -25, -25, -25, -25, -25, - -25, -25, -25, 58, -25, -25, 58, 67, 58, 58, - 58, 68, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -25 - }, - - { - 11, -26, -26, -26, -26, -26, -26, -26, -26, -26, - -26, -26, -26, 58, -26, -26, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 69, 58, 58, 58, 58, 58, 58, -26 - }, - - { - 11, -27, -27, -27, -27, -27, -27, -27, -27, -27, - -27, -27, -27, 58, -27, -27, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 70, 58, 58, 58, 58, -27 - }, - - { - 11, -28, -28, -28, -28, -28, -28, -28, -28, -28, - -28, -28, -28, 58, -28, -28, 58, 71, 58, 58, - 58, 72, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -28 - }, - - { - 11, -29, -29, -29, -29, -29, -29, -29, -29, -29, - -29, -29, -29, 58, -29, -29, 58, 58, 58, 58, - 58, 73, 58, 58, 58, 58, 58, 58, 58, 74, - 58, 58, 58, 58, 75, 58, 58, -29 - - }, - - { - 11, -30, -30, -30, -30, -30, -30, -30, -30, -30, - -30, -30, -30, 58, -30, -30, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 76, 58, 58, 58, 58, -30 - }, - - { - 11, 77, 77, -31, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77 - }, - - { - 11, -32, 78, 79, -32, -32, -32, -32, -32, -32, - -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, - - -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, - -32, -32, -32, -32, -32, -32, -32, -32 - }, - - { - 11, 80, -33, -33, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80 - }, - - { - 11, 81, 81, 82, 81, -34, 81, 81, -34, 81, - 81, 81, 81, 81, 81, -34, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81 - - }, - - { - 11, -35, -35, -35, -35, -35, -35, -35, -35, -35, - -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, - -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, - -35, -35, -35, -35, -35, -35, -35, -35 - }, - - { - 11, -36, -36, -36, -36, -36, -36, -36, -36, -36, - -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, - -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, - -36, -36, -36, -36, -36, -36, -36, -36 - }, - - { - 11, 83, 83, 84, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - - 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, - 83, 83, 83, 83, 83, 83, 83, 83 - }, - - { - 11, -38, -38, -38, -38, -38, -38, -38, -38, -38, - -38, -38, -38, -38, -38, -38, -38, -38, -38, -38, - -38, -38, -38, -38, -38, -38, -38, -38, -38, -38, - -38, -38, -38, -38, -38, -38, -38, -38 - }, - - { - 11, -39, -39, -39, -39, -39, -39, -39, -39, -39, - -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, - -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, - -39, -39, -39, -39, -39, -39, -39, -39 - - }, - - { - 11, -40, -40, -40, -40, -40, -40, -40, -40, -40, - -40, -40, -40, -40, 85, -40, -40, -40, -40, -40, - -40, -40, -40, -40, -40, -40, -40, -40, -40, -40, - -40, -40, -40, -40, -40, -40, -40, -40 - }, - - { - 11, -41, -41, -41, -41, -41, -41, -41, -41, -41, - -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, - -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, - -41, -41, -41, -41, -41, -41, -41, -41 - }, - - { - 11, 86, 86, -42, 86, 86, 86, 86, 86, 86, - 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, - - 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, - 86, 86, 86, 86, 86, 86, 86, 86 - }, - - { - 11, -43, -43, -43, -43, -43, -43, 87, -43, -43, - -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, - -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, - -43, -43, -43, -43, -43, -43, -43, -43 - }, - - { - 11, -44, -44, -44, -44, -44, -44, -44, -44, -44, - -44, -44, -44, -44, -44, -44, -44, -44, -44, -44, - -44, -44, -44, -44, -44, -44, -44, -44, -44, -44, - -44, -44, -44, -44, -44, -44, -44, -44 - - }, - - { - 11, -45, -45, -45, -45, -45, -45, -45, -45, -45, - -45, -45, -45, -45, -45, -45, -45, -45, -45, -45, - -45, -45, -45, -45, -45, -45, -45, -45, -45, -45, - -45, -45, -45, -45, -45, -45, -45, -45 - }, - - { - 11, -46, -46, -46, -46, -46, -46, -46, -46, -46, - -46, 88, 89, 89, -46, -46, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, -46 - }, - - { - 11, -47, -47, -47, -47, -47, -47, -47, -47, -47, - -47, 89, 89, 89, -47, -47, 89, 89, 89, 89, - - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, -47 - }, - - { - 11, -48, -48, -48, -48, -48, -48, -48, -48, -48, - -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, - -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, - -48, -48, -48, -48, -48, -48, -48, -48 - }, - - { - 11, -49, -49, 90, -49, -49, -49, -49, -49, -49, - -49, -49, -49, -49, -49, -49, -49, -49, -49, -49, - -49, -49, -49, -49, -49, -49, -49, -49, -49, -49, - -49, -49, -49, -49, -49, -49, -49, -49 - - }, - - { - 11, -50, -50, -50, -50, -50, -50, -50, -50, -50, - -50, 89, 89, 89, -50, -50, 89, 89, 89, 89, - 89, 89, 91, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, -50 - }, - - { - 11, -51, -51, -51, -51, -51, -51, -51, -51, -51, - -51, 89, 89, 89, -51, -51, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 89, 92, 89, - 89, 89, 89, 89, 89, 89, 89, -51 - }, - - { - 11, -52, -52, -52, -52, -52, -52, -52, -52, -52, - -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, - - -52, -52, -52, -52, -52, -52, -52, -52, -52, -52, - -52, -52, -52, -52, -52, -52, -52, 93 - }, - - { - 11, -53, 53, 54, -53, -53, 55, -53, -53, -53, - -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, - -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, - -53, -53, -53, -53, -53, -53, -53, -53 - }, - - { - 11, -54, -54, -54, -54, -54, -54, -54, -54, -54, - -54, -54, -54, -54, -54, -54, -54, -54, -54, -54, - -54, -54, -54, -54, -54, -54, -54, -54, -54, -54, - -54, -54, -54, -54, -54, -54, -54, -54 - - }, - - { - 11, 56, 56, 57, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56 - }, - - { - 11, 56, 56, 57, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56 - }, - - { - 11, -57, -57, -57, -57, -57, -57, -57, -57, -57, - -57, -57, -57, -57, -57, -57, -57, -57, -57, -57, - - -57, -57, -57, -57, -57, -57, -57, -57, -57, -57, - -57, -57, -57, -57, -57, -57, -57, -57 - }, - - { - 11, -58, -58, -58, -58, -58, -58, -58, -58, -58, - -58, -58, -58, 58, -58, -58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -58 - }, - - { - 11, -59, -59, -59, -59, -59, -59, -59, -59, -59, - -59, -59, -59, 58, -59, -59, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 94, - 58, 58, 58, 58, 58, 58, 58, -59 - - }, - - { - 11, -60, -60, -60, -60, -60, -60, -60, -60, -60, - -60, -60, -60, 58, -60, -60, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 95, - 58, 58, 58, 58, 58, 58, 58, -60 - }, - - { - 11, -61, -61, -61, -61, -61, -61, -61, -61, -61, - -61, -61, -61, 58, -61, -61, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 96, 97, 58, - 58, 58, 58, 58, 58, 58, 58, -61 - }, - - { - 11, -62, -62, -62, -62, -62, -62, -62, -62, -62, - -62, -62, -62, 58, -62, -62, 58, 58, 58, 58, - - 58, 58, 98, 58, 58, 58, 58, 58, 58, 58, - 99, 58, 58, 58, 58, 58, 58, -62 - }, - - { - 11, -63, -63, -63, -63, -63, -63, -63, -63, -63, - -63, -63, -63, 58, -63, -63, 58, 100, 58, 58, - 101, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -63 - }, - - { - 11, -64, -64, -64, -64, -64, -64, -64, -64, -64, - -64, -64, -64, 58, -64, -64, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 102, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 103, -64 - - }, - - { - 11, -65, -65, -65, -65, -65, -65, -65, -65, -65, - -65, -65, -65, 58, -65, -65, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -65 - }, - - { - 11, -66, -66, -66, -66, -66, -66, -66, -66, -66, - -66, -66, -66, 58, -66, -66, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 104, 58, 58, -66 - }, - - { - 11, -67, -67, -67, -67, -67, -67, -67, -67, -67, - -67, -67, -67, 58, -67, -67, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 105, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -67 - }, - - { - 11, -68, -68, -68, -68, -68, -68, -68, -68, -68, - -68, -68, -68, 58, -68, -68, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 106, 58, - 58, 58, 58, 58, 58, 58, 58, -68 - }, - - { - 11, -69, -69, -69, -69, -69, -69, -69, -69, -69, - -69, -69, -69, 58, -69, -69, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 107, 58, 58, -69 - - }, - - { - 11, -70, -70, -70, -70, -70, -70, -70, -70, -70, - -70, -70, -70, 58, -70, -70, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 108, - 58, 58, 58, 58, 58, 58, 58, -70 - }, - - { - 11, -71, -71, -71, -71, -71, -71, -71, -71, -71, - -71, -71, -71, 58, -71, -71, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 109, 58, - 58, 58, 58, 58, 58, 58, 58, -71 - }, - - { - 11, -72, -72, -72, -72, -72, -72, -72, -72, -72, - -72, -72, -72, 58, -72, -72, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 110, 58, 58, 58, 58, 58, -72 - }, - - { - 11, -73, -73, -73, -73, -73, -73, -73, -73, -73, - -73, -73, -73, 58, -73, -73, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 111, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -73 - }, - - { - 11, -74, -74, -74, -74, -74, -74, -74, -74, -74, - -74, -74, -74, 58, -74, -74, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 112, 58, -74 - - }, - - { - 11, -75, -75, -75, -75, -75, -75, -75, -75, -75, - -75, -75, -75, 58, -75, -75, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 113, 58, 58, 58, 58, -75 - }, - - { - 11, -76, -76, -76, -76, -76, -76, -76, -76, -76, - -76, -76, -76, 58, -76, -76, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 114, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -76 - }, - - { - 11, 77, 77, -77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77 - }, - - { - 11, -78, 78, 79, -78, -78, -78, -78, -78, -78, - -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, - -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, - -78, -78, -78, -78, -78, -78, -78, -78 - }, - - { - 11, 80, -79, -79, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80 - - }, - - { - 11, -80, -80, -80, -80, -80, -80, -80, -80, -80, - -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, - -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, - -80, -80, -80, -80, -80, -80, -80, -80 - }, - - { - 11, 81, 81, 82, 81, -81, 81, 81, -81, 81, - 81, 81, 81, 81, 81, -81, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 81, 81 - }, - - { - 11, -82, -82, -82, -82, -82, -82, -82, -82, -82, - -82, -82, -82, -82, -82, -82, -82, -82, -82, -82, - - -82, -82, -82, -82, -82, -82, -82, -82, -82, -82, - -82, -82, -82, -82, -82, -82, -82, -82 - }, - - { - 11, -83, -83, 84, -83, -83, -83, -83, -83, -83, - -83, -83, -83, -83, -83, -83, -83, -83, -83, -83, - -83, -83, -83, -83, -83, -83, -83, -83, -83, -83, - -83, -83, -83, -83, -83, -83, -83, -83 - }, - - { - 11, -84, -84, -84, -84, -84, -84, -84, -84, -84, - -84, -84, -84, -84, -84, -84, -84, -84, -84, -84, - -84, -84, -84, -84, -84, -84, -84, -84, -84, -84, - -84, -84, -84, -84, -84, -84, -84, -84 - - }, - - { - 11, -85, -85, -85, -85, -85, -85, -85, -85, -85, - -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, - -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, - -85, -85, -85, -85, -85, -85, -85, -85 - }, - - { - 11, 86, 86, -86, 86, 86, 86, 86, 86, 86, - 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, - 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, - 86, 86, 86, 86, 86, 86, 86, 86 - }, - - { - 11, -87, -87, -87, -87, -87, -87, -87, -87, -87, - -87, -87, -87, -87, -87, -87, -87, -87, -87, -87, - - -87, -87, -87, -87, -87, -87, -87, -87, -87, -87, - -87, -87, -87, -87, -87, -87, -87, -87 - }, - - { - 11, -88, -88, -88, -88, -88, -88, -88, -88, -88, - -88, 115, 89, 89, -88, -88, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, -88 - }, - - { - 11, -89, -89, -89, -89, -89, -89, -89, -89, -89, - -89, 89, 89, 89, -89, -89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, -89 - - }, - - { - 11, -90, -90, -90, -90, -90, -90, -90, -90, -90, - -90, -90, -90, -90, -90, -90, -90, -90, -90, -90, - -90, -90, -90, -90, -90, -90, -90, -90, -90, -90, - -90, -90, -90, -90, -90, -90, -90, -90 - }, - - { - 11, -91, -91, -91, -91, -91, -91, -91, -91, -91, - -91, 89, 89, 89, -91, -91, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, -91 - }, - - { - 11, -92, -92, -92, -92, -92, -92, -92, -92, -92, - -92, 89, 89, 89, -92, -92, 89, 89, 89, 89, - - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, -92 - }, - - { - 11, -93, -93, -93, -93, -93, -93, -93, -93, -93, - -93, -93, -93, -93, -93, -93, -93, -93, -93, -93, - -93, -93, -93, -93, -93, -93, -93, -93, -93, -93, - -93, -93, -93, -93, -93, -93, -93, -93 - }, - - { - 11, -94, -94, -94, -94, -94, -94, -94, -94, -94, - -94, -94, -94, 58, -94, -94, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 116, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -94 - - }, - - { - 11, -95, -95, -95, -95, -95, -95, -95, -95, -95, - -95, -95, -95, 58, -95, -95, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 117, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -95 - }, - - { - 11, -96, -96, -96, -96, -96, -96, -96, -96, -96, - -96, -96, -96, 58, -96, -96, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 118, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -96 - }, - - { - 11, -97, -97, -97, -97, -97, -97, -97, -97, -97, - -97, -97, -97, 58, -97, -97, 58, 58, 58, 58, - - 58, 58, 119, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -97 - }, - - { - 11, -98, -98, -98, -98, -98, -98, -98, -98, -98, - -98, -98, -98, 58, -98, -98, 120, 121, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -98 - }, - - { - 11, -99, -99, -99, -99, -99, -99, -99, -99, -99, - -99, -99, -99, 58, -99, -99, 58, 58, 58, 58, - 58, 122, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -99 - - }, - - { - 11, -100, -100, -100, -100, -100, -100, -100, -100, -100, - -100, -100, -100, 58, -100, -100, 58, 58, 123, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -100 - }, - - { - 11, -101, -101, -101, -101, -101, -101, -101, -101, -101, - -101, -101, -101, 58, -101, -101, 58, 58, 58, 124, - 58, 58, 58, 58, 58, 125, 58, 126, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -101 - }, - - { - 11, -102, -102, -102, -102, -102, -102, -102, -102, -102, - -102, -102, -102, 58, -102, -102, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 127, 58, 58, 58, 58, 58, 58, -102 - }, - - { - 11, -103, -103, -103, -103, -103, -103, -103, -103, -103, - -103, -103, -103, 58, -103, -103, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -103 - }, - - { - 11, -104, -104, -104, -104, -104, -104, -104, -104, -104, - -104, -104, -104, 58, -104, -104, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -104 - - }, - - { - 11, -105, -105, -105, -105, -105, -105, -105, -105, -105, - -105, -105, -105, 58, -105, -105, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 128, 58, - 58, 58, 58, 58, 58, 58, 58, -105 - }, - - { - 11, -106, -106, -106, -106, -106, -106, -106, -106, -106, - -106, -106, -106, 58, -106, -106, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 129, 58, -106 - }, - - { - 11, -107, -107, -107, -107, -107, -107, -107, -107, -107, - -107, -107, -107, 58, -107, -107, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 130, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -107 - }, - - { - 11, -108, -108, -108, -108, -108, -108, -108, -108, -108, - -108, -108, -108, 58, -108, -108, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 131, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -108 - }, - - { - 11, -109, -109, -109, -109, -109, -109, -109, -109, -109, - -109, -109, -109, 58, -109, -109, 58, 58, 58, 58, - 58, 58, 58, 132, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -109 - - }, - - { - 11, -110, -110, -110, -110, -110, -110, -110, -110, -110, - -110, -110, -110, 58, -110, -110, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 133, 58, -110 - }, - - { - 11, -111, -111, -111, -111, -111, -111, -111, -111, -111, - -111, -111, -111, 58, -111, -111, 58, 58, 58, 58, - 58, 134, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -111 - }, - - { - 11, -112, -112, -112, -112, -112, -112, -112, -112, -112, - -112, -112, -112, 58, -112, -112, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 135, 58, 58, 58, 58, -112 - }, - - { - 11, -113, -113, -113, -113, -113, -113, -113, -113, -113, - -113, -113, -113, 58, -113, -113, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 136, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -113 - }, - - { - 11, -114, -114, -114, -114, -114, -114, -114, -114, -114, - -114, -114, -114, 58, -114, -114, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 137, 58, 58, 58, -114 - - }, - - { - 11, -115, -115, -115, -115, -115, -115, -115, -115, -115, - -115, 89, 89, 89, -115, -115, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, -115 - }, - - { - 11, -116, -116, -116, -116, -116, -116, -116, -116, -116, - -116, -116, -116, 58, -116, -116, 58, 58, 58, 58, - 58, 138, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -116 - }, - - { - 11, -117, -117, -117, -117, -117, -117, -117, -117, -117, - -117, -117, -117, 58, -117, -117, 58, 58, 58, 139, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -117 - }, - - { - 11, -118, -118, -118, -118, -118, -118, -118, -118, -118, - -118, -118, -118, 58, -118, -118, 58, 58, 58, 58, - 58, 140, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -118 - }, - - { - 11, -119, -119, -119, -119, -119, -119, -119, -119, -119, - -119, -119, -119, 58, -119, -119, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 141, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -119 - - }, - - { - 11, -120, -120, -120, -120, -120, -120, -120, -120, -120, - -120, -120, -120, 58, -120, -120, 58, 58, 142, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 143, 58, 58, -120 - }, - - { - 11, -121, -121, -121, -121, -121, -121, -121, -121, -121, - -121, -121, -121, 58, -121, -121, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 144, 58, -121 - }, - - { - 11, -122, -122, -122, -122, -122, -122, -122, -122, -122, - -122, -122, -122, 58, -122, -122, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 145, 58, - 58, 58, 58, 58, 58, 58, 58, -122 + 0, 0, 0, 0, 0, 0, 0 }, { - 11, -123, -123, -123, -123, -123, -123, -123, -123, -123, - -123, -123, -123, 58, -123, -123, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 146, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -123 - }, - - { - 11, -124, -124, -124, -124, -124, -124, -124, -124, -124, - -124, -124, -124, 58, -124, -124, 58, 58, 58, 58, - 58, 58, 58, 58, 147, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -124 - - }, - - { - 11, -125, -125, -125, -125, -125, -125, -125, -125, -125, - -125, -125, -125, 58, -125, -125, 58, 58, 58, 58, - 58, 58, 148, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -125 - }, - - { - 11, -126, -126, -126, -126, -126, -126, -126, -126, -126, - -126, -126, -126, 58, -126, -126, 58, 58, 58, 58, - 58, 149, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -126 - }, - - { - 11, -127, -127, -127, -127, -127, -127, -127, -127, -127, - -127, -127, -127, 58, -127, -127, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -127 - }, - - { - 11, -128, -128, -128, -128, -128, -128, -128, -128, -128, - -128, -128, -128, 58, -128, -128, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 150, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -128 - }, - - { - 11, -129, -129, -129, -129, -129, -129, -129, -129, -129, - -129, -129, -129, 58, -129, -129, 58, 58, 58, 151, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -129 - - }, - - { - 11, -130, -130, -130, -130, -130, -130, -130, -130, -130, - -130, -130, -130, 58, -130, -130, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 152, - 58, 58, 58, 58, 58, 58, 58, -130 - }, - - { - 11, -131, -131, -131, -131, -131, -131, -131, -131, -131, - -131, -131, -131, 58, -131, -131, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 153, 58, 58, 58, 58, 58, 58, -131 - }, - - { - 11, -132, -132, -132, -132, -132, -132, -132, -132, -132, - -132, -132, -132, 58, -132, -132, 58, 58, 58, 58, - - 58, 154, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -132 - }, - - { - 11, -133, -133, -133, -133, -133, -133, -133, -133, -133, - -133, -133, -133, 58, -133, -133, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 155, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -133 - }, - - { - 11, -134, -134, -134, -134, -134, -134, -134, -134, -134, - -134, -134, -134, 58, -134, -134, 58, 58, 58, 156, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -134 - - }, - - { - 11, -135, -135, -135, -135, -135, -135, -135, -135, -135, - -135, -135, -135, 58, -135, -135, 58, 58, 58, 157, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -135 - }, - - { - 11, -136, -136, -136, -136, -136, -136, -136, -136, -136, - -136, -136, -136, 58, -136, -136, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 158, 58, - 58, 58, 58, 58, 58, 58, 58, -136 - }, - - { - 11, -137, -137, -137, -137, -137, -137, -137, -137, -137, - -137, -137, -137, 58, -137, -137, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 159, 58, 58, -137 - }, - - { - 11, -138, -138, -138, -138, -138, -138, -138, -138, -138, - -138, -138, -138, 58, -138, -138, 58, 160, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -138 - }, - - { - 11, -139, -139, -139, -139, -139, -139, -139, -139, -139, - -139, -139, -139, 58, -139, -139, 58, 58, 58, 58, - 58, 161, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -139 - - }, - - { - 11, -140, -140, -140, -140, -140, -140, -140, -140, -140, - -140, -140, -140, 58, -140, -140, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 162, 58, - 58, 58, 58, 58, 58, 58, 58, -140 - }, - - { - 11, -141, -141, -141, -141, -141, -141, -141, -141, -141, - -141, -141, -141, 58, -141, -141, 58, 58, 58, 58, - 58, 58, 58, 163, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -141 - }, - - { - 11, -142, -142, -142, -142, -142, -142, -142, -142, -142, - -142, -142, -142, 58, -142, -142, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 164, - 58, 58, 58, 58, 58, 58, 58, -142 - }, - - { - 11, -143, -143, -143, -143, -143, -143, -143, -143, -143, - -143, -143, -143, 58, -143, -143, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 165, 58, 58, 58, 58, -143 - }, - - { - 11, -144, -144, -144, -144, -144, -144, -144, -144, -144, - -144, -144, -144, 58, -144, -144, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 166, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -144 - - }, - - { - 11, -145, -145, -145, -145, -145, -145, -145, -145, -145, - -145, -145, -145, 58, -145, -145, 58, 58, 58, 58, - 167, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -145 - }, - - { - 11, -146, -146, -146, -146, -146, -146, -146, -146, -146, - -146, -146, -146, 58, -146, -146, 58, 58, 58, 58, - 58, 168, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -146 - }, - - { - 11, -147, -147, -147, -147, -147, -147, -147, -147, -147, - -147, -147, -147, 58, -147, -147, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 169, - 58, 58, 58, 58, 58, 58, 58, -147 - }, - - { - 11, -148, -148, -148, -148, -148, -148, -148, -148, -148, - -148, -148, -148, 58, -148, -148, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -148 - }, - - { - 11, -149, -149, -149, -149, -149, -149, -149, -149, -149, - -149, -149, -149, 58, -149, -149, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 170, 58, - 58, 58, 58, 58, 58, 58, 58, -149 - - }, - - { - 11, -150, -150, -150, -150, -150, -150, -150, -150, -150, - -150, -150, -150, 58, -150, -150, 58, 58, 58, 58, - 58, 171, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -150 - }, - - { - 11, -151, -151, -151, -151, -151, -151, -151, -151, -151, - -151, -151, -151, 58, -151, -151, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 172, - 58, 58, 58, 58, 58, 58, 58, -151 + 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12 }, { - 11, -152, -152, -152, -152, -152, -152, -152, -152, -152, - -152, -152, -152, 58, -152, -152, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 173, 58, - 58, 58, 58, 58, 58, 58, 58, -152 + 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12 }, { - 11, -153, -153, -153, -153, -153, -153, -153, -153, -153, - -153, -153, -153, 58, -153, -153, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 174, 58, 58, -153 + 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 18, 16, 16, 16 }, { - 11, -154, -154, -154, -154, -154, -154, -154, -154, -154, - -154, -154, -154, 58, -154, -154, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -154 + 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 18, 16, 16, 16 }, { - 11, -155, -155, -155, -155, -155, -155, -155, -155, -155, - -155, -155, -155, 58, -155, -155, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 175, 58, 58, 58, 58, -155 + 11, 19, 20, 21, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19 }, { - 11, -156, -156, -156, -156, -156, -156, -156, -156, -156, - -156, -156, -156, 58, -156, -156, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 176, 58, 58, -156 + 11, 19, 20, 21, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19 }, { - 11, -157, -157, -157, -157, -157, -157, -157, -157, -157, - -157, -157, -157, 58, -157, -157, 58, 58, 58, 58, - - 58, 177, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -157 + 11, 22, 22, 23, 22, 24, 22, 22, 24, 22, + 22, 22, 22, 22, 22, 25, 22 }, { - 11, -158, -158, -158, -158, -158, -158, -158, -158, -158, - -158, -158, -158, 58, -158, -158, 58, 58, 58, 58, - 58, 58, 58, 178, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -158 + 11, 22, 22, 23, 22, 24, 22, 22, 24, 22, + 22, 22, 22, 22, 22, 25, 22 }, { - 11, -159, -159, -159, -159, -159, -159, -159, -159, -159, - -159, -159, -159, 58, -159, -159, 58, 179, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -159 + 11, 26, 26, 27, 28, 29, 30, 31, 29, 32, + 33, 34, 35, 35, 36, 37, 38 }, { - 11, -160, -160, -160, -160, -160, -160, -160, -160, -160, - -160, -160, -160, 58, -160, -160, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 180, 58, - 58, 58, 58, 58, 58, 58, 58, -160 + 11, 26, 26, 27, 28, 29, 30, 31, 29, 32, + 33, 34, 35, 35, 36, 37, 38 }, { - 11, -161, -161, -161, -161, -161, -161, -161, -161, -161, - -161, -161, -161, 58, -161, -161, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -161 + -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, + -11, -11, -11, -11, -11, -11, -11 }, { - 11, -162, -162, -162, -162, -162, -162, -162, -162, -162, - -162, -162, -162, 58, -162, -162, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 181, 58, 58, -162 + 11, -12, -12, -12, -12, -12, -12, -12, -12, -12, + -12, -12, -12, -12, -12, -12, -12 }, { - 11, -163, -163, -163, -163, -163, -163, -163, -163, -163, - -163, -163, -163, 58, -163, -163, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -163 + 11, -13, 39, 40, -13, -13, 41, -13, -13, -13, + -13, -13, -13, -13, -13, -13, -13 }, { - 11, -164, -164, -164, -164, -164, -164, -164, -164, -164, - -164, -164, -164, 58, -164, -164, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 182, - 58, 58, 58, 58, 58, 58, 58, -164 + 11, -14, -14, -14, -14, -14, -14, -14, -14, -14, + -14, -14, -14, -14, -14, -14, -14 }, { - 11, -165, -165, -165, -165, -165, -165, -165, -165, -165, - -165, -165, -165, 58, -165, -165, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 183, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -165 + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 }, { - 11, -166, -166, -166, -166, -166, -166, -166, -166, -166, - -166, -166, -166, 58, -166, -166, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 184, 58, 58, -166 + 11, -16, -16, -16, -16, -16, -16, -16, -16, -16, + -16, -16, -16, -16, -16, -16, -16 }, { - 11, -167, -167, -167, -167, -167, -167, -167, -167, -167, - -167, -167, -167, 58, -167, -167, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 185, 58, 58, 58, -167 + 11, -17, -17, -17, -17, -17, -17, -17, -17, -17, + -17, -17, -17, -17, -17, -17, -17 }, { - 11, -168, -168, -168, -168, -168, -168, -168, -168, -168, - -168, -168, -168, 58, -168, -168, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -168 + 11, -18, -18, -18, -18, -18, -18, -18, -18, -18, + -18, -18, -18, 44, -18, -18, -18 }, { - 11, -169, -169, -169, -169, -169, -169, -169, -169, -169, - -169, -169, -169, 58, -169, -169, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 186, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -169 + 11, 45, 45, -19, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45 }, { - 11, -170, -170, -170, -170, -170, -170, -170, -170, -170, - -170, -170, -170, 58, -170, -170, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 187, 58, -170 + 11, -20, 46, 47, -20, -20, -20, -20, -20, -20, + -20, -20, -20, -20, -20, -20, -20 }, { - 11, -171, -171, -171, -171, -171, -171, -171, -171, -171, - -171, -171, -171, 58, -171, -171, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 188, 58, - 58, 58, 58, 58, 58, 58, 58, -171 + 11, 48, -21, -21, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48 }, { - 11, -172, -172, -172, -172, -172, -172, -172, -172, -172, - -172, -172, -172, 58, -172, -172, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 189, 58, - 58, 58, 58, 58, 58, 58, 58, -172 + 11, 49, 49, 50, 49, -22, 49, 49, -22, 49, + 49, 49, 49, 49, 49, -22, 49 }, { - 11, -173, -173, -173, -173, -173, -173, -173, -173, -173, - -173, -173, -173, 58, -173, -173, 58, 190, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -173 + 11, -23, -23, -23, -23, -23, -23, -23, -23, -23, + -23, -23, -23, -23, -23, -23, -23 }, { - 11, -174, -174, -174, -174, -174, -174, -174, -174, -174, - -174, -174, -174, 58, -174, -174, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -174 + 11, -24, -24, -24, -24, -24, -24, -24, -24, -24, + -24, -24, -24, -24, -24, -24, -24 }, { - 11, -175, -175, -175, -175, -175, -175, -175, -175, -175, - -175, -175, -175, 58, -175, -175, 58, 58, 58, 58, - 58, 191, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -175 + 11, 51, 51, 52, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51 }, { - 11, -176, -176, -176, -176, -176, -176, -176, -176, -176, - -176, -176, -176, 58, -176, -176, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -176 + 11, -26, -26, -26, -26, -26, -26, -26, -26, -26, + -26, -26, -26, -26, -26, -26, -26 }, { - 11, -177, -177, -177, -177, -177, -177, -177, -177, -177, - -177, -177, -177, 58, -177, -177, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -177 + 11, -27, -27, -27, -27, -27, -27, -27, -27, -27, + -27, -27, -27, -27, -27, -27, -27 }, { - 11, -178, -178, -178, -178, -178, -178, -178, -178, -178, - -178, -178, -178, 58, -178, -178, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -178 + 11, -28, -28, -28, -28, -28, -28, -28, -28, -28, + -28, -28, -28, -28, 53, -28, -28 }, { - 11, -179, -179, -179, -179, -179, -179, -179, -179, -179, - -179, -179, -179, 58, -179, -179, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 192, 58, 58, -179 + 11, -29, -29, -29, -29, -29, -29, -29, -29, -29, + -29, -29, -29, -29, -29, -29, -29 }, { - 11, -180, -180, -180, -180, -180, -180, -180, -180, -180, - -180, -180, -180, 58, -180, -180, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -180 + 11, 54, 54, -30, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54 }, { - 11, -181, -181, -181, -181, -181, -181, -181, -181, -181, - -181, -181, -181, 58, -181, -181, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -181 + 11, -31, -31, -31, -31, -31, -31, 55, -31, -31, + -31, -31, -31, -31, -31, -31, -31 }, { - 11, -182, -182, -182, -182, -182, -182, -182, -182, -182, - -182, -182, -182, 58, -182, -182, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 193, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -182 + 11, -32, -32, -32, -32, -32, -32, -32, -32, -32, + -32, -32, -32, -32, -32, -32, -32 }, { - 11, -183, -183, -183, -183, -183, -183, -183, -183, -183, - -183, -183, -183, 58, -183, -183, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 194, 58, 58, 58, -183 + 11, -33, -33, -33, -33, -33, -33, -33, -33, -33, + -33, -33, -33, -33, -33, -33, -33 }, { - 11, -184, -184, -184, -184, -184, -184, -184, -184, -184, - -184, -184, -184, 58, -184, -184, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -184 + 11, -34, -34, -34, -34, -34, -34, -34, -34, -34, + -34, 56, 57, 57, -34, -34, -34 }, { - 11, -185, -185, -185, -185, -185, -185, -185, -185, -185, - -185, -185, -185, 58, -185, -185, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -185 + 11, -35, -35, -35, -35, -35, -35, -35, -35, -35, + -35, 57, 57, 57, -35, -35, -35 }, { - 11, -186, -186, -186, -186, -186, -186, -186, -186, -186, - -186, -186, -186, 58, -186, -186, 58, 58, 58, 195, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -186 + 11, -36, -36, -36, -36, -36, -36, -36, -36, -36, + -36, -36, -36, -36, -36, -36, -36 }, { - 11, -187, -187, -187, -187, -187, -187, -187, -187, -187, - -187, -187, -187, 58, -187, -187, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -187 + 11, -37, -37, 58, -37, -37, -37, -37, -37, -37, + -37, -37, -37, -37, -37, -37, -37 }, { - 11, -188, -188, -188, -188, -188, -188, -188, -188, -188, - -188, -188, -188, 58, -188, -188, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 196, 58, -188 + 11, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, 59 }, { - 11, -189, -189, -189, -189, -189, -189, -189, -189, -189, - -189, -189, -189, 58, -189, -189, 58, 58, 58, 58, - 58, 58, 197, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -189 + 11, -39, 39, 40, -39, -39, 41, -39, -39, -39, + -39, -39, -39, -39, -39, -39, -39 }, { - 11, -190, -190, -190, -190, -190, -190, -190, -190, -190, - -190, -190, -190, 58, -190, -190, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 198, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -190 + 11, -40, -40, -40, -40, -40, -40, -40, -40, -40, + -40, -40, -40, -40, -40, -40, -40 }, { - 11, -191, -191, -191, -191, -191, -191, -191, -191, -191, - -191, -191, -191, 58, -191, -191, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 199, 58, 58, 58, -191 + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 }, { - 11, -192, -192, -192, -192, -192, -192, -192, -192, -192, - -192, -192, -192, 58, -192, -192, 58, 58, 58, 58, - - 58, 200, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -192 + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 }, { - 11, -193, -193, -193, -193, -193, -193, -193, -193, -193, - -193, -193, -193, 58, -193, -193, 58, 58, 58, 58, - 58, 201, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -193 + 11, -43, -43, -43, -43, -43, -43, -43, -43, -43, + -43, -43, -43, -43, -43, -43, -43 }, { - 11, -194, -194, -194, -194, -194, -194, -194, -194, -194, - -194, -194, -194, 58, -194, -194, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 202, 58, 58, -194 + 11, -44, -44, -44, -44, -44, -44, -44, -44, -44, + -44, -44, -44, 44, -44, -44, -44 }, { - 11, -195, -195, -195, -195, -195, -195, -195, -195, -195, - -195, -195, -195, 58, -195, -195, 58, 58, 58, 58, - 58, 203, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -195 + 11, 45, 45, -45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45 }, { - 11, -196, -196, -196, -196, -196, -196, -196, -196, -196, - -196, -196, -196, 58, -196, -196, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -196 + 11, -46, 46, 47, -46, -46, -46, -46, -46, -46, + -46, -46, -46, -46, -46, -46, -46 }, { - 11, -197, -197, -197, -197, -197, -197, -197, -197, -197, - -197, -197, -197, 58, -197, -197, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 204, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -197 + 11, 48, -47, -47, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48 }, { - 11, -198, -198, -198, -198, -198, -198, -198, -198, -198, - -198, -198, -198, 58, -198, -198, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -198 + 11, -48, -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48 }, { - 11, -199, -199, -199, -199, -199, -199, -199, -199, -199, - -199, -199, -199, 58, -199, -199, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -199 + 11, 49, 49, 50, 49, -49, 49, 49, -49, 49, + 49, 49, 49, 49, 49, -49, 49 }, { - 11, -200, -200, -200, -200, -200, -200, -200, -200, -200, - -200, -200, -200, 58, -200, -200, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -200 + 11, -50, -50, -50, -50, -50, -50, -50, -50, -50, + -50, -50, -50, -50, -50, -50, -50 }, { - 11, -201, -201, -201, -201, -201, -201, -201, -201, -201, - -201, -201, -201, 58, -201, -201, 58, 205, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -201 + 11, -51, -51, 52, -51, -51, -51, -51, -51, -51, + -51, -51, -51, -51, -51, -51, -51 }, { - 11, -202, -202, -202, -202, -202, -202, -202, -202, -202, - -202, -202, -202, 58, -202, -202, 58, 206, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -202 + 11, -52, -52, -52, -52, -52, -52, -52, -52, -52, + -52, -52, -52, -52, -52, -52, -52 }, { - 11, -203, -203, -203, -203, -203, -203, -203, -203, -203, - -203, -203, -203, 58, -203, -203, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -203 + 11, -53, -53, -53, -53, -53, -53, -53, -53, -53, + -53, -53, -53, -53, -53, -53, -53 }, { - 11, -204, -204, -204, -204, -204, -204, -204, -204, -204, - -204, -204, -204, 58, -204, -204, 58, 58, 58, 58, - 58, 58, 58, 207, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -204 + 11, 54, 54, -54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54 }, { - 11, -205, -205, -205, -205, -205, -205, -205, -205, -205, - -205, -205, -205, 58, -205, -205, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 208, 58, - 58, 58, 58, 58, 58, 58, 58, -205 + 11, -55, -55, -55, -55, -55, -55, -55, -55, -55, + -55, -55, -55, -55, -55, -55, -55 }, { - 11, -206, -206, -206, -206, -206, -206, -206, -206, -206, - -206, -206, -206, 58, -206, -206, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 209, 58, 58, -206 + 11, -56, -56, -56, -56, -56, -56, -56, -56, -56, + -56, 60, 57, 57, -56, -56, -56 }, { - 11, -207, -207, -207, -207, -207, -207, -207, -207, -207, - -207, -207, -207, 58, -207, -207, 58, 58, 58, 58, - - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -207 + 11, -57, -57, -57, -57, -57, -57, -57, -57, -57, + -57, 57, 57, 57, -57, -57, -57 }, { - 11, -208, -208, -208, -208, -208, -208, -208, -208, -208, - -208, -208, -208, 58, -208, -208, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -208 + 11, -58, -58, -58, -58, -58, -58, -58, -58, -58, + -58, -58, -58, -58, -58, -58, -58 }, { - 11, -209, -209, -209, -209, -209, -209, -209, -209, -209, - -209, -209, -209, 58, -209, -209, 58, 58, 58, 58, - 58, 210, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -209 + 11, -59, -59, -59, -59, -59, -59, -59, -59, -59, + -59, -59, -59, -59, -59, -59, -59 }, { - 11, -210, -210, -210, -210, -210, -210, -210, -210, -210, - -210, -210, -210, 58, -210, -210, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, -210 + 11, -60, -60, -60, -60, -60, -60, -60, -60, -60, + -60, 57, 57, 57, -60, -60, -60 }, } ; @@ -1918,8 +674,8 @@ static void yy_fatal_error (yyconst char msg[] ); *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; -#define YY_NUM_RULES 64 -#define YY_END_OF_BUFFER 65 +#define YY_NUM_RULES 33 +#define YY_END_OF_BUFFER 34 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -1927,31 +683,14 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[211] = +static yyconst flex_int16_t yy_accept[61] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 65, 5, 4, 3, 2, 36, 37, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 63, 60, 62, 55, 59, 58, 57, 53, 48, 42, - 47, 51, 53, 40, 41, 50, 50, 43, 53, 50, - 50, 53, 4, 3, 2, 2, 1, 35, 35, 35, - 35, 35, 35, 35, 16, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 63, 60, 62, 61, - 55, 54, 57, 56, 44, 51, 38, 50, 50, 52, - 45, 46, 39, 35, 35, 35, 35, 35, 35, 35, - - 35, 35, 30, 29, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 49, 25, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 15, 35, 7, 35, - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 17, 35, 35, - 35, 35, 35, 34, 35, 35, 35, 35, 35, 35, - 10, 35, 13, 35, 35, 35, 35, 33, 35, 35, - 35, 35, 35, 22, 35, 32, 9, 31, 35, 26, - 12, 35, 35, 21, 18, 35, 8, 35, 35, 35, - 35, 35, 27, 35, 35, 6, 35, 20, 19, 23, - - 35, 35, 11, 35, 35, 35, 14, 28, 35, 24 + 34, 5, 4, 3, 2, 7, 8, 6, 32, 29, + 31, 24, 28, 27, 26, 22, 17, 13, 16, 20, + 22, 11, 12, 19, 19, 14, 22, 22, 4, 3, + 2, 2, 1, 6, 32, 29, 31, 30, 24, 23, + 26, 25, 15, 20, 9, 19, 19, 21, 10, 18 } ; static yyconst flex_int32_t yy_ec[256] = @@ -1965,11 +704,11 @@ static yyconst flex_int32_t yy_ec[256] = 14, 1, 1, 1, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 1, 15, 1, 1, 16, 1, 17, 18, 19, 20, + 1, 15, 1, 1, 13, 1, 13, 13, 13, 13, - 21, 22, 23, 24, 25, 13, 13, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 13, 13, 36, - 13, 13, 1, 37, 1, 1, 1, 1, 1, 1, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 1, 16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -2014,8 +753,7 @@ char *zconftext; #define START_STRSIZE 16 -char *text; -static char *text_ptr; +static char *text; static int text_size, text_asize; struct buffer { @@ -2034,23 +772,22 @@ void new_string(void) { text = malloc(START_STRSIZE); text_asize = START_STRSIZE; - text_ptr = text; text_size = 0; - *text_ptr = 0; + *text = 0; } void append_string(const char *str, int size) { int new_size = text_size + size + 1; if (new_size > text_asize) { + new_size += START_STRSIZE - 1; + new_size &= -START_STRSIZE; text = realloc(text, new_size); text_asize = new_size; - text_ptr = text + text_size; } - memcpy(text_ptr, str, size); - text_ptr += size; + memcpy(text + text_size, str, size); text_size += size; - *text_ptr = 0; + text[text_size] = 0; } void alloc_string(const char *str, int size) @@ -2066,11 +803,13 @@ void alloc_string(const char *str, int size) #define STRING 3 #define PARAM 4 +#ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ #include +#endif #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * @@ -2282,175 +1021,56 @@ YY_RULE_SETUP case 6: YY_RULE_SETUP -BEGIN(PARAM); return T_MAINMENU; - YY_BREAK -case 7: -YY_RULE_SETUP -BEGIN(PARAM); return T_MENU; - YY_BREAK -case 8: -YY_RULE_SETUP -BEGIN(PARAM); return T_ENDMENU; - YY_BREAK -case 9: -YY_RULE_SETUP -BEGIN(PARAM); return T_SOURCE; - YY_BREAK -case 10: -YY_RULE_SETUP -BEGIN(PARAM); return T_CHOICE; - YY_BREAK -case 11: -YY_RULE_SETUP -BEGIN(PARAM); return T_ENDCHOICE; - YY_BREAK -case 12: -YY_RULE_SETUP -BEGIN(PARAM); return T_COMMENT; - YY_BREAK -case 13: -YY_RULE_SETUP -BEGIN(PARAM); return T_CONFIG; - YY_BREAK -case 14: -YY_RULE_SETUP -BEGIN(PARAM); return T_MENUCONFIG; - YY_BREAK -case 15: -YY_RULE_SETUP -BEGIN(PARAM); return T_HELP; - YY_BREAK -case 16: -YY_RULE_SETUP -BEGIN(PARAM); return T_IF; - YY_BREAK -case 17: -YY_RULE_SETUP -BEGIN(PARAM); return T_ENDIF; - YY_BREAK -case 18: -YY_RULE_SETUP -BEGIN(PARAM); return T_DEPENDS; - YY_BREAK -case 19: -YY_RULE_SETUP -BEGIN(PARAM); return T_REQUIRES; - YY_BREAK -case 20: -YY_RULE_SETUP -BEGIN(PARAM); return T_OPTIONAL; - YY_BREAK -case 21: -YY_RULE_SETUP -BEGIN(PARAM); return T_DEFAULT; - YY_BREAK -case 22: -YY_RULE_SETUP -BEGIN(PARAM); return T_PROMPT; - YY_BREAK -case 23: -YY_RULE_SETUP -BEGIN(PARAM); return T_TRISTATE; - YY_BREAK -case 24: -YY_RULE_SETUP -BEGIN(PARAM); return T_DEF_TRISTATE; - YY_BREAK -case 25: -YY_RULE_SETUP -BEGIN(PARAM); return T_BOOLEAN; - YY_BREAK -case 26: -YY_RULE_SETUP -BEGIN(PARAM); return T_BOOLEAN; - YY_BREAK -case 27: -YY_RULE_SETUP -BEGIN(PARAM); return T_DEF_BOOLEAN; - YY_BREAK -case 28: -YY_RULE_SETUP -BEGIN(PARAM); return T_DEF_BOOLEAN; - YY_BREAK -case 29: -YY_RULE_SETUP -BEGIN(PARAM); return T_INT; - YY_BREAK -case 30: -YY_RULE_SETUP -BEGIN(PARAM); return T_HEX; - YY_BREAK -case 31: -YY_RULE_SETUP -BEGIN(PARAM); return T_STRING; - YY_BREAK -case 32: -YY_RULE_SETUP -BEGIN(PARAM); return T_SELECT; - YY_BREAK -case 33: -YY_RULE_SETUP -BEGIN(PARAM); return T_SELECT; - YY_BREAK -case 34: -YY_RULE_SETUP -BEGIN(PARAM); return T_RANGE; - YY_BREAK -case 35: -YY_RULE_SETUP { + struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); + if (id && id->flags & TF_COMMAND) { + BEGIN(PARAM); + return id->token; + } alloc_string(zconftext, zconfleng); zconflval.string = text; return T_WORD; } YY_BREAK -case 36: +case 7: YY_RULE_SETUP YY_BREAK -case 37: -/* rule 37 can match eol */ +case 8: +/* rule 8 can match eol */ YY_RULE_SETUP current_file->lineno++; BEGIN(INITIAL); YY_BREAK -case 38: +case 9: YY_RULE_SETUP return T_AND; YY_BREAK -case 39: +case 10: YY_RULE_SETUP return T_OR; YY_BREAK -case 40: +case 11: YY_RULE_SETUP return T_OPEN_PAREN; YY_BREAK -case 41: +case 12: YY_RULE_SETUP return T_CLOSE_PAREN; YY_BREAK -case 42: +case 13: YY_RULE_SETUP return T_NOT; YY_BREAK -case 43: +case 14: YY_RULE_SETUP return T_EQUAL; YY_BREAK -case 44: +case 15: YY_RULE_SETUP return T_UNEQUAL; YY_BREAK -case 45: -YY_RULE_SETUP -return T_IF; - YY_BREAK -case 46: -YY_RULE_SETUP -return T_ON; - YY_BREAK -case 47: +case 16: YY_RULE_SETUP { str = zconftext[0]; @@ -2458,33 +1078,36 @@ YY_RULE_SETUP BEGIN(STRING); } YY_BREAK -case 48: -/* rule 48 can match eol */ +case 17: +/* rule 17 can match eol */ YY_RULE_SETUP BEGIN(INITIAL); current_file->lineno++; return T_EOL; YY_BREAK -case 49: +case 18: YY_RULE_SETUP /* ignore */ YY_BREAK -case 50: +case 19: YY_RULE_SETUP { + struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); + if (id && id->flags & TF_PARAM) + return id->token; alloc_string(zconftext, zconfleng); zconflval.string = text; return T_WORD; } YY_BREAK -case 51: +case 20: YY_RULE_SETUP /* comment */ YY_BREAK -case 52: -/* rule 52 can match eol */ +case 21: +/* rule 21 can match eol */ YY_RULE_SETUP current_file->lineno++; YY_BREAK -case 53: +case 22: YY_RULE_SETUP YY_BREAK @@ -2494,8 +1117,8 @@ case YY_STATE_EOF(PARAM): } YY_BREAK -case 54: -/* rule 54 can match eol */ +case 23: +/* rule 23 can match eol */ *yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ (yy_c_buf_p) = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up zconftext again */ @@ -2506,14 +1129,14 @@ YY_RULE_SETUP return T_WORD_QUOTE; } YY_BREAK -case 55: +case 24: YY_RULE_SETUP { append_string(zconftext, zconfleng); } YY_BREAK -case 56: -/* rule 56 can match eol */ +case 25: +/* rule 25 can match eol */ *yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ (yy_c_buf_p) = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up zconftext again */ @@ -2524,13 +1147,13 @@ YY_RULE_SETUP return T_WORD_QUOTE; } YY_BREAK -case 57: +case 26: YY_RULE_SETUP { append_string(zconftext + 1, zconfleng - 1); } YY_BREAK -case 58: +case 27: YY_RULE_SETUP { if (str == zconftext[0]) { @@ -2541,8 +1164,8 @@ YY_RULE_SETUP append_string(zconftext, 1); } YY_BREAK -case 59: -/* rule 59 can match eol */ +case 28: +/* rule 28 can match eol */ YY_RULE_SETUP { printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); @@ -2557,7 +1180,7 @@ case YY_STATE_EOF(STRING): } YY_BREAK -case 60: +case 29: YY_RULE_SETUP { ts = 0; @@ -2582,8 +1205,8 @@ YY_RULE_SETUP } } YY_BREAK -case 61: -/* rule 61 can match eol */ +case 30: +/* rule 30 can match eol */ *yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ (yy_c_buf_p) = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up zconftext again */ @@ -2594,15 +1217,15 @@ YY_RULE_SETUP return T_HELPTEXT; } YY_BREAK -case 62: -/* rule 62 can match eol */ +case 31: +/* rule 31 can match eol */ YY_RULE_SETUP { current_file->lineno++; append_string("\n", 1); } YY_BREAK -case 63: +case 32: YY_RULE_SETUP { append_string(zconftext, zconfleng); @@ -2628,7 +1251,7 @@ case YY_STATE_EOF(COMMAND): yyterminate(); } YY_BREAK -case 64: +case 33: YY_RULE_SETUP YY_FATAL_ERROR( "flex scanner jammed" ); YY_BREAK @@ -3338,10 +1961,10 @@ YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size ) * @note If you want to scan bytes that may contain NUL values, then use * zconf_scan_bytes() instead. */ -YY_BUFFER_STATE zconf_scan_string (yyconst char * str ) +YY_BUFFER_STATE zconf_scan_string (yyconst char * yy_str ) { - return zconf_scan_bytes(str,strlen(str) ); + return zconf_scan_bytes(yy_str,strlen(yy_str) ); } /** Setup the input buffer state to scan the given bytes. The next call to zconflex() will diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index 5fba1feff2a..6881fb08432 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h @@ -37,6 +37,16 @@ extern "C" { #define _(text) gettext(text) #define N_(text) (text) + +#define TF_COMMAND 0x0001 +#define TF_PARAM 0x0002 + +struct kconf_id { + int name; + int token; + unsigned int flags; +}; + int zconfparse(void); void zconfdump(FILE *out); diff --git a/scripts/kconfig/zconf.gperf b/scripts/kconfig/zconf.gperf new file mode 100644 index 00000000000..c9d81cf5d7f --- /dev/null +++ b/scripts/kconfig/zconf.gperf @@ -0,0 +1,43 @@ +%language=ANSI-C +%define hash-function-name kconf_id_hash +%define lookup-function-name kconf_id_lookup +%define string-pool-name kconf_id_strings +%compare-strncmp +%enum +%pic +%struct-type + +struct kconf_id; + +%% +mainmenu, T_MAINMENU, TF_COMMAND +menu, T_MENU, TF_COMMAND +endmenu, T_ENDMENU, TF_COMMAND +source, T_SOURCE, TF_COMMAND +choice, T_CHOICE, TF_COMMAND +endchoice, T_ENDCHOICE, TF_COMMAND +comment, T_COMMENT, TF_COMMAND +config, T_CONFIG, TF_COMMAND +menuconfig, T_MENUCONFIG, TF_COMMAND +help, T_HELP, TF_COMMAND +if, T_IF, TF_COMMAND|TF_PARAM +endif, T_ENDIF, TF_COMMAND +depends, T_DEPENDS, TF_COMMAND +requires, T_REQUIRES, TF_COMMAND +optional, T_OPTIONAL, TF_COMMAND +default, T_DEFAULT, TF_COMMAND +prompt, T_PROMPT, TF_COMMAND +tristate, T_TRISTATE, TF_COMMAND +def_tristate, T_DEF_TRISTATE, TF_COMMAND +bool, T_BOOLEAN, TF_COMMAND +boolean, T_BOOLEAN, TF_COMMAND +def_bool, T_DEF_BOOLEAN, TF_COMMAND +def_boolean, T_DEF_BOOLEAN, TF_COMMAND +int, T_INT, TF_COMMAND +hex, T_HEX, TF_COMMAND +string, T_STRING, TF_COMMAND +select, T_SELECT, TF_COMMAND +enable, T_SELECT, TF_COMMAND +range, T_RANGE, TF_COMMAND +on, T_ON, TF_PARAM +%% diff --git a/scripts/kconfig/zconf.hash.c_shipped b/scripts/kconfig/zconf.hash.c_shipped new file mode 100644 index 00000000000..6741cb15980 --- /dev/null +++ b/scripts/kconfig/zconf.hash.c_shipped @@ -0,0 +1,231 @@ +/* ANSI-C code produced by gperf version 3.0.1 */ +/* Command-line: gperf */ +/* Computed positions: -k'1,3' */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +#error "gperf generated tables don't work with this execution character set. Please report a bug to ." +#endif + +struct kconf_id; +/* maximum key range = 45, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static unsigned int +kconf_id_hash (register const char *str, register unsigned int len) +{ + static unsigned char asso_values[] = + { + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 25, 10, 15, + 0, 0, 5, 47, 0, 0, 47, 47, 0, 10, + 0, 20, 20, 20, 5, 0, 0, 20, 47, 47, + 20, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47 + }; + register int hval = len; + + switch (hval) + { + default: + hval += asso_values[(unsigned char)str[2]]; + /*FALLTHROUGH*/ + case 2: + case 1: + hval += asso_values[(unsigned char)str[0]]; + break; + } + return hval; +} + +struct kconf_id_strings_t + { + char kconf_id_strings_str2[sizeof("if")]; + char kconf_id_strings_str3[sizeof("int")]; + char kconf_id_strings_str4[sizeof("help")]; + char kconf_id_strings_str5[sizeof("endif")]; + char kconf_id_strings_str6[sizeof("select")]; + char kconf_id_strings_str7[sizeof("endmenu")]; + char kconf_id_strings_str8[sizeof("tristate")]; + char kconf_id_strings_str9[sizeof("endchoice")]; + char kconf_id_strings_str10[sizeof("range")]; + char kconf_id_strings_str11[sizeof("string")]; + char kconf_id_strings_str12[sizeof("default")]; + char kconf_id_strings_str13[sizeof("def_bool")]; + char kconf_id_strings_str14[sizeof("menu")]; + char kconf_id_strings_str16[sizeof("def_boolean")]; + char kconf_id_strings_str17[sizeof("def_tristate")]; + char kconf_id_strings_str18[sizeof("mainmenu")]; + char kconf_id_strings_str20[sizeof("menuconfig")]; + char kconf_id_strings_str21[sizeof("config")]; + char kconf_id_strings_str22[sizeof("on")]; + char kconf_id_strings_str23[sizeof("hex")]; + char kconf_id_strings_str26[sizeof("source")]; + char kconf_id_strings_str27[sizeof("depends")]; + char kconf_id_strings_str28[sizeof("optional")]; + char kconf_id_strings_str31[sizeof("enable")]; + char kconf_id_strings_str32[sizeof("comment")]; + char kconf_id_strings_str33[sizeof("requires")]; + char kconf_id_strings_str34[sizeof("bool")]; + char kconf_id_strings_str37[sizeof("boolean")]; + char kconf_id_strings_str41[sizeof("choice")]; + char kconf_id_strings_str46[sizeof("prompt")]; + }; +static struct kconf_id_strings_t kconf_id_strings_contents = + { + "if", + "int", + "help", + "endif", + "select", + "endmenu", + "tristate", + "endchoice", + "range", + "string", + "default", + "def_bool", + "menu", + "def_boolean", + "def_tristate", + "mainmenu", + "menuconfig", + "config", + "on", + "hex", + "source", + "depends", + "optional", + "enable", + "comment", + "requires", + "bool", + "boolean", + "choice", + "prompt" + }; +#define kconf_id_strings ((const char *) &kconf_id_strings_contents) +#ifdef __GNUC__ +__inline +#endif +struct kconf_id * +kconf_id_lookup (register const char *str, register unsigned int len) +{ + enum + { + TOTAL_KEYWORDS = 30, + MIN_WORD_LENGTH = 2, + MAX_WORD_LENGTH = 12, + MIN_HASH_VALUE = 2, + MAX_HASH_VALUE = 46 + }; + + static struct kconf_id wordlist[] = + { + {-1}, {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_IF, TF_COMMAND|TF_PARAM}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3, T_INT, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str4, T_HELP, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5, T_ENDIF, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6, T_SELECT, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_ENDMENU, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_TRISTATE, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9, T_ENDCHOICE, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str10, T_RANGE, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str11, T_STRING, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_DEF_BOOLEAN, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_MENU, TF_COMMAND}, + {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16, T_DEF_BOOLEAN, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_DEF_TRISTATE, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_MAINMENU, TF_COMMAND}, + {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str20, T_MENUCONFIG, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_CONFIG, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_ON, TF_PARAM}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_HEX, TF_COMMAND}, + {-1}, {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26, T_SOURCE, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_DEPENDS, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28, T_OPTIONAL, TF_COMMAND}, + {-1}, {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_SELECT, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_COMMENT, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_REQUIRES, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str34, T_BOOLEAN, TF_COMMAND}, + {-1}, {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37, T_BOOLEAN, TF_COMMAND}, + {-1}, {-1}, {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41, T_CHOICE, TF_COMMAND}, + {-1}, {-1}, {-1}, {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46, T_PROMPT, TF_COMMAND} + }; + + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = kconf_id_hash (str, len); + + if (key <= MAX_HASH_VALUE && key >= 0) + { + register int o = wordlist[key].name; + if (o >= 0) + { + register const char *s = o + kconf_id_strings; + + if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') + return &wordlist[key]; + } + } + } + return 0; +} + diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l index 55517b2877c..ec902091be9 100644 --- a/scripts/kconfig/zconf.l +++ b/scripts/kconfig/zconf.l @@ -18,8 +18,7 @@ #define START_STRSIZE 16 -char *text; -static char *text_ptr; +static char *text; static int text_size, text_asize; struct buffer { @@ -38,23 +37,22 @@ void new_string(void) { text = malloc(START_STRSIZE); text_asize = START_STRSIZE; - text_ptr = text; text_size = 0; - *text_ptr = 0; + *text = 0; } void append_string(const char *str, int size) { int new_size = text_size + size + 1; if (new_size > text_asize) { + new_size += START_STRSIZE - 1; + new_size &= -START_STRSIZE; text = realloc(text, new_size); text_asize = new_size; - text_ptr = text + text_size; } - memcpy(text_ptr, str, size); - text_ptr += size; + memcpy(text + text_size, str, size); text_size += size; - *text_ptr = 0; + text[text_size] = 0; } void alloc_string(const char *str, int size) @@ -88,36 +86,12 @@ n [A-Za-z0-9_] { - "mainmenu" BEGIN(PARAM); return T_MAINMENU; - "menu" BEGIN(PARAM); return T_MENU; - "endmenu" BEGIN(PARAM); return T_ENDMENU; - "source" BEGIN(PARAM); return T_SOURCE; - "choice" BEGIN(PARAM); return T_CHOICE; - "endchoice" BEGIN(PARAM); return T_ENDCHOICE; - "comment" BEGIN(PARAM); return T_COMMENT; - "config" BEGIN(PARAM); return T_CONFIG; - "menuconfig" BEGIN(PARAM); return T_MENUCONFIG; - "help" BEGIN(PARAM); return T_HELP; - "if" BEGIN(PARAM); return T_IF; - "endif" BEGIN(PARAM); return T_ENDIF; - "depends" BEGIN(PARAM); return T_DEPENDS; - "requires" BEGIN(PARAM); return T_REQUIRES; - "optional" BEGIN(PARAM); return T_OPTIONAL; - "default" BEGIN(PARAM); return T_DEFAULT; - "prompt" BEGIN(PARAM); return T_PROMPT; - "tristate" BEGIN(PARAM); return T_TRISTATE; - "def_tristate" BEGIN(PARAM); return T_DEF_TRISTATE; - "bool" BEGIN(PARAM); return T_BOOLEAN; - "boolean" BEGIN(PARAM); return T_BOOLEAN; - "def_bool" BEGIN(PARAM); return T_DEF_BOOLEAN; - "def_boolean" BEGIN(PARAM); return T_DEF_BOOLEAN; - "int" BEGIN(PARAM); return T_INT; - "hex" BEGIN(PARAM); return T_HEX; - "string" BEGIN(PARAM); return T_STRING; - "select" BEGIN(PARAM); return T_SELECT; - "enable" BEGIN(PARAM); return T_SELECT; - "range" BEGIN(PARAM); return T_RANGE; {n}+ { + struct kconf_id *id = kconf_id_lookup(yytext, yyleng); + if (id && id->flags & TF_COMMAND) { + BEGIN(PARAM); + return id->token; + } alloc_string(yytext, yyleng); zconflval.string = text; return T_WORD; @@ -134,8 +108,6 @@ n [A-Za-z0-9_] "!" return T_NOT; "=" return T_EQUAL; "!=" return T_UNEQUAL; - "if" return T_IF; - "on" return T_ON; \"|\' { str = yytext[0]; new_string(); @@ -144,6 +116,9 @@ n [A-Za-z0-9_] \n BEGIN(INITIAL); current_file->lineno++; return T_EOL; --- /* ignore */ ({n}|[-/.])+ { + struct kconf_id *id = kconf_id_lookup(yytext, yyleng); + if (id && id->flags & TF_PARAM) + return id->token; alloc_string(yytext, yyleng); zconflval.string = text; return T_WORD; diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped index da12f7b33be..07fa508d465 100644 --- a/scripts/kconfig/zconf.tab.c_shipped +++ b/scripts/kconfig/zconf.tab.c_shipped @@ -1,7 +1,7 @@ -/* A Bison parser, made by GNU Bison 1.875a. */ +/* A Bison parser, made by GNU Bison 2.0. */ /* Skeleton parser for Yacc-like parsing with Bison, - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. 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 @@ -45,8 +45,7 @@ /* Using locations. */ #define YYLSP_NEEDED 0 -/* If NAME_PREFIX is specified substitute the variables and functions - names. */ +/* Substitute the variable and function names. */ #define yyparse zconfparse #define yylex zconflex #define yyerror zconferror @@ -161,6 +160,11 @@ #include #include +#define LKC_DIRECT_LINK +#include "lkc.h" + +#include "zconf.hash.c" + #define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) #define PRINTD 0x0001 @@ -202,7 +206,7 @@ typedef union YYSTYPE { struct expr *expr; struct menu *menu; } YYSTYPE; -/* Line 191 of yacc.c. */ +/* Line 190 of yacc.c. */ # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 @@ -214,27 +218,26 @@ typedef union YYSTYPE { /* Copy the second part of user declarations. */ -#define LKC_DIRECT_LINK -#include "lkc.h" - - -/* Line 214 of yacc.c. */ +/* Line 213 of yacc.c. */ #if ! defined (yyoverflow) || YYERROR_VERBOSE +# ifndef YYFREE +# define YYFREE free +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# endif + /* The parser invokes alloca or malloc; define the necessary symbols. */ -# if YYSTACK_USE_ALLOCA -# define YYSTACK_ALLOC alloca -# else -# ifndef YYSTACK_USE_ALLOCA -# if defined (alloca) || defined (_ALLOCA_H) -# define YYSTACK_ALLOC alloca +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca # else -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# endif +# define YYSTACK_ALLOC alloca # endif # endif # endif @@ -247,20 +250,20 @@ typedef union YYSTYPE { # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # endif -# define YYSTACK_ALLOC malloc -# define YYSTACK_FREE free +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE # endif #endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ #if (! defined (yyoverflow) \ && (! defined (__cplusplus) \ - || (YYSTYPE_IS_TRIVIAL))) + || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { - short yyss; + short int yyss; YYSTYPE yyvs; }; @@ -270,13 +273,13 @@ union yyalloc /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ - ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ + ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY -# if 1 < __GNUC__ +# if defined (__GNUC__) && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else @@ -312,7 +315,7 @@ union yyalloc #if defined (__STDC__) || defined (__cplusplus) typedef signed char yysigned_char; #else - typedef short yysigned_char; + typedef short int yysigned_char; #endif /* YYFINAL -- State number of the termination state. */ @@ -374,7 +377,7 @@ static const unsigned char yytranslate[] = #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ -static const unsigned short yyprhs[] = +static const unsigned short int yyprhs[] = { 0, 0, 3, 4, 7, 9, 11, 13, 17, 19, 21, 23, 26, 28, 30, 32, 34, 36, 38, 42, @@ -427,19 +430,19 @@ static const yysigned_char yyrhs[] = }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ -static const unsigned short yyrline[] = +static const unsigned short int yyrline[] = { - 0, 94, 94, 95, 98, 99, 100, 101, 102, 103, - 104, 105, 109, 110, 111, 112, 113, 114, 120, 128, - 134, 142, 152, 154, 155, 156, 157, 160, 166, 173, - 179, 186, 192, 198, 204, 210, 216, 222, 230, 239, - 245, 254, 255, 261, 263, 264, 265, 266, 269, 275, - 281, 287, 293, 299, 301, 306, 315, 324, 325, 331, - 333, 334, 335, 340, 347, 353, 362, 363, 369, 371, - 372, 373, 374, 377, 383, 390, 397, 404, 410, 417, - 418, 419, 422, 427, 432, 440, 442, 447, 448, 451, - 452, 453, 457, 457, 459, 460, 463, 464, 465, 466, - 467, 468, 469, 472, 473 + 0, 97, 97, 98, 101, 102, 103, 104, 105, 106, + 107, 108, 112, 113, 114, 115, 116, 117, 123, 131, + 137, 145, 155, 157, 158, 159, 160, 163, 169, 176, + 182, 189, 195, 201, 207, 213, 219, 225, 233, 242, + 248, 257, 258, 264, 266, 267, 268, 269, 272, 278, + 284, 290, 296, 302, 304, 309, 318, 327, 328, 334, + 336, 337, 338, 343, 350, 356, 365, 366, 372, 374, + 375, 376, 377, 380, 386, 393, 400, 407, 413, 420, + 421, 422, 425, 430, 435, 443, 445, 450, 451, 454, + 455, 456, 460, 460, 462, 463, 466, 467, 468, 469, + 470, 471, 472, 475, 476 }; #endif @@ -448,29 +451,29 @@ static const unsigned short yyrline[] = First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { - "$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU", - "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG", - "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS", - "T_REQUIRES", "T_OPTIONAL", "T_PROMPT", "T_DEFAULT", "T_TRISTATE", - "T_DEF_TRISTATE", "T_BOOLEAN", "T_DEF_BOOLEAN", "T_STRING", "T_INT", - "T_HEX", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL", "T_EOF", "T_EOL", - "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_ON", "T_SELECT", "T_RANGE", "T_OR", - "T_AND", "T_EQUAL", "T_NOT", "$accept", "input", "block", - "common_block", "config_entry_start", "config_stmt", - "menuconfig_entry_start", "menuconfig_stmt", "config_option_list", - "config_option", "choice", "choice_entry", "choice_end", "choice_stmt", - "choice_option_list", "choice_option", "choice_block", "if", "if_end", - "if_stmt", "if_block", "menu", "menu_entry", "menu_end", "menu_stmt", - "menu_block", "source", "source_stmt", "comment", "comment_stmt", - "help_start", "help", "depends_list", "depends", "prompt_stmt_opt", - "prompt", "end", "nl_or_eof", "if_expr", "expr", "symbol", 0 + "$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU", + "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG", + "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS", + "T_REQUIRES", "T_OPTIONAL", "T_PROMPT", "T_DEFAULT", "T_TRISTATE", + "T_DEF_TRISTATE", "T_BOOLEAN", "T_DEF_BOOLEAN", "T_STRING", "T_INT", + "T_HEX", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL", "T_EOF", "T_EOL", + "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_ON", "T_SELECT", "T_RANGE", "T_OR", + "T_AND", "T_EQUAL", "T_NOT", "$accept", "input", "block", "common_block", + "config_entry_start", "config_stmt", "menuconfig_entry_start", + "menuconfig_stmt", "config_option_list", "config_option", "choice", + "choice_entry", "choice_end", "choice_stmt", "choice_option_list", + "choice_option", "choice_block", "if", "if_end", "if_stmt", "if_block", + "menu", "menu_entry", "menu_end", "menu_stmt", "menu_block", "source", + "source_stmt", "comment", "comment_stmt", "help_start", "help", + "depends_list", "depends", "prompt_stmt_opt", "prompt", "end", + "nl_or_eof", "if_expr", "expr", "symbol", 0 }; #endif # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ -static const unsigned short yytoknum[] = +static const unsigned short int yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, @@ -539,7 +542,7 @@ static const unsigned char yydefact[] = }; /* YYDEFGOTO[NTERM-NUM]. */ -static const short yydefgoto[] = +static const short int yydefgoto[] = { -1, 1, 17, 18, 19, 20, 21, 22, 52, 88, 23, 24, 105, 25, 54, 98, 55, 26, 109, 27, @@ -551,7 +554,7 @@ static const short yydefgoto[] = /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -99 -static const short yypact[] = +static const short int yypact[] = { -99, 48, -99, 38, 46, 46, -99, 46, -29, -99, 46, -17, -3, -11, -99, -99, -99, -99, -99, -99, @@ -575,7 +578,7 @@ static const short yypact[] = }; /* YYPGOTO[NTERM-NUM]. */ -static const short yypgoto[] = +static const short int yypgoto[] = { -99, -99, -99, 111, -99, -99, -99, -99, 178, -99, -99, -99, -99, 91, -99, -99, -99, -99, -99, -99, @@ -589,7 +592,7 @@ static const short yypgoto[] = number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -68 -static const short yytable[] = +static const short int yytable[] = { 66, 67, 36, 42, 39, 40, 71, 41, 123, 124, 43, 44, 74, 75, 120, 154, 72, 46, 47, 69, @@ -687,7 +690,7 @@ static const unsigned char yystos[] = #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab -#define YYERROR goto yyerrlab1 +#define YYERROR goto yyerrorlab /* Like YYERROR except do call yyerror. This remains here temporarily @@ -715,20 +718,53 @@ do \ } \ while (0) + #define YYTERROR 1 #define YYERRCODE 256 -/* YYLLOC_DEFAULT -- Compute the default location (before the actions - are run). */ +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - Current.first_line = Rhs[1].first_line; \ - Current.first_column = Rhs[1].first_column; \ - Current.last_line = Rhs[N].last_line; \ - Current.last_column = Rhs[N].last_column; +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (N) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (0) #endif + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM @@ -751,36 +787,30 @@ do { \ YYFPRINTF Args; \ } while (0) -# define YYDSYMPRINT(Args) \ -do { \ - if (yydebug) \ - yysymprint Args; \ -} while (0) - -# define YYDSYMPRINTF(Title, Token, Value, Location) \ +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yysymprint (stderr, \ - Token, Value); \ + Type, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (0) /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (cinluded). | +| TOP (included). | `------------------------------------------------------------------*/ #if defined (__STDC__) || defined (__cplusplus) static void -yy_stack_print (short *bottom, short *top) +yy_stack_print (short int *bottom, short int *top) #else static void yy_stack_print (bottom, top) - short *bottom; - short *top; + short int *bottom; + short int *top; #endif { YYFPRINTF (stderr, "Stack now"); @@ -810,9 +840,9 @@ yy_reduce_print (yyrule) #endif { int yyi; - unsigned int yylineno = yyrline[yyrule]; + unsigned int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", - yyrule - 1, yylineno); + yyrule - 1, yylno); /* Print the symbols being reduced, and their result. */ for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); @@ -830,8 +860,7 @@ do { \ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) -# define YYDSYMPRINT(Args) -# define YYDSYMPRINTF(Title, Token, Value, Location) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ @@ -849,10 +878,6 @@ int yydebug; SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ -#if YYMAXDEPTH == 0 -# undef YYMAXDEPTH -#endif - #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif @@ -934,15 +959,15 @@ yysymprint (yyoutput, yytype, yyvaluep) (void) yyvaluep; if (yytype < YYNTOKENS) - { - YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); -# ifdef YYPRINT - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# endif - } + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif switch (yytype) { default: @@ -958,10 +983,11 @@ yysymprint (yyoutput, yytype, yyvaluep) #if defined (__STDC__) || defined (__cplusplus) static void -yydestruct (int yytype, YYSTYPE *yyvaluep) +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) #else static void -yydestruct (yytype, yyvaluep) +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; int yytype; YYSTYPE *yyvaluep; #endif @@ -969,6 +995,10 @@ yydestruct (yytype, yyvaluep) /* Pacify ``unused variable'' warnings. */ (void) yyvaluep; + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + switch (yytype) { @@ -996,10 +1026,10 @@ int yyparse (); -/* The lookahead symbol. */ +/* The look-ahead symbol. */ int yychar; -/* The semantic value of the lookahead symbol. */ +/* The semantic value of the look-ahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ @@ -1035,7 +1065,7 @@ yyparse () int yyresult; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; - /* Lookahead token as an internal (translated) token number. */ + /* Look-ahead token as an internal (translated) token number. */ int yytoken = 0; /* Three stacks and their tools: @@ -1047,9 +1077,9 @@ yyparse () to reallocate them elsewhere. */ /* The state stack. */ - short yyssa[YYINITDEPTH]; - short *yyss = yyssa; - register short *yyssp; + short int yyssa[YYINITDEPTH]; + short int *yyss = yyssa; + register short int *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; @@ -1086,6 +1116,9 @@ yyparse () yyssp = yyss; yyvsp = yyvs; + + yyvsp[0] = yylval; + goto yysetstate; /*------------------------------------------------------------. @@ -1111,7 +1144,7 @@ yyparse () these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; - short *yyss1 = yyss; + short int *yyss1 = yyss; /* Each stack pointer address is followed by the size of the @@ -1139,7 +1172,7 @@ yyparse () yystacksize = YYMAXDEPTH; { - short *yyss1 = yyss; + short int *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) @@ -1175,18 +1208,18 @@ yyparse () yybackup: /* Do appropriate processing given the current state. */ -/* Read a lookahead token if we need one and don't already have one. */ +/* Read a look-ahead token if we need one and don't already have one. */ /* yyresume: */ - /* First try to decide what to do without reference to lookahead token. */ + /* First try to decide what to do without reference to look-ahead token. */ yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; - /* Not known => get a lookahead token if don't already have one. */ + /* Not known => get a look-ahead token if don't already have one. */ - /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); @@ -1201,7 +1234,7 @@ yybackup: else { yytoken = YYTRANSLATE (yychar); - YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to @@ -1221,8 +1254,8 @@ yybackup: if (yyn == YYFINAL) YYACCEPT; - /* Shift the lookahead token. */ - YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken])); + /* Shift the look-ahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the token being shifted unless it is eof. */ if (yychar != YYEOF) @@ -1294,10 +1327,10 @@ yyreduce: case 18: { - struct symbol *sym = sym_lookup(yyvsp[-1].string, 0); + struct symbol *sym = sym_lookup((yyvsp[-1].string), 0); sym->flags |= SYMBOL_OPTIONAL; menu_add_entry(sym); - printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), yyvsp[-1].string); + printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string)); ;} break; @@ -1312,10 +1345,10 @@ yyreduce: case 20: { - struct symbol *sym = sym_lookup(yyvsp[-1].string, 0); + struct symbol *sym = sym_lookup((yyvsp[-1].string), 0); sym->flags |= SYMBOL_OPTIONAL; menu_add_entry(sym); - printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), yyvsp[-1].string); + printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string)); ;} break; @@ -1342,7 +1375,7 @@ yyreduce: case 28: { - menu_add_expr(P_DEFAULT, yyvsp[-2].expr, yyvsp[-1].expr); + menu_add_expr(P_DEFAULT, (yyvsp[-2].expr), (yyvsp[-1].expr)); menu_set_type(S_TRISTATE); printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno()); ;} @@ -1359,7 +1392,7 @@ yyreduce: case 30: { - menu_add_expr(P_DEFAULT, yyvsp[-2].expr, yyvsp[-1].expr); + menu_add_expr(P_DEFAULT, (yyvsp[-2].expr), (yyvsp[-1].expr)); menu_set_type(S_BOOLEAN); printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno()); ;} @@ -1392,7 +1425,7 @@ yyreduce: case 34: { - menu_add_prompt(P_PROMPT, yyvsp[-2].string, yyvsp[-1].expr); + menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr)); printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); ;} break; @@ -1400,7 +1433,7 @@ yyreduce: case 35: { - menu_add_expr(P_DEFAULT, yyvsp[-2].expr, yyvsp[-1].expr); + menu_add_expr(P_DEFAULT, (yyvsp[-2].expr), (yyvsp[-1].expr)); printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno()); ;} break; @@ -1408,7 +1441,7 @@ yyreduce: case 36: { - menu_add_symbol(P_SELECT, sym_lookup(yyvsp[-2].string, 0), yyvsp[-1].expr); + menu_add_symbol(P_SELECT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr)); printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); ;} break; @@ -1416,7 +1449,7 @@ yyreduce: case 37: { - menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,yyvsp[-3].symbol, yyvsp[-2].symbol), yyvsp[-1].expr); + menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[-3].symbol), (yyvsp[-2].symbol)), (yyvsp[-1].expr)); printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); ;} break; @@ -1443,7 +1476,7 @@ yyreduce: case 40: { - if (zconf_endtoken(yyvsp[0].token, T_CHOICE, T_ENDCHOICE)) { + if (zconf_endtoken((yyvsp[0].token), T_CHOICE, T_ENDCHOICE)) { menu_end_menu(); printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); } @@ -1461,7 +1494,7 @@ yyreduce: case 48: { - menu_add_prompt(P_PROMPT, yyvsp[-2].string, yyvsp[-1].expr); + menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr)); printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); ;} break; @@ -1493,7 +1526,7 @@ yyreduce: case 52: { - menu_add_symbol(P_DEFAULT, sym_lookup(yyvsp[-2].string, 0), yyvsp[-1].expr); + menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr)); printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno()); ;} break; @@ -1503,7 +1536,7 @@ yyreduce: { printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); menu_add_entry(NULL); - menu_add_dep(yyvsp[-1].expr); + menu_add_dep((yyvsp[-1].expr)); menu_end_entry(); menu_add_menu(); ;} @@ -1512,7 +1545,7 @@ yyreduce: case 56: { - if (zconf_endtoken(yyvsp[0].token, T_IF, T_ENDIF)) { + if (zconf_endtoken((yyvsp[0].token), T_IF, T_ENDIF)) { menu_end_menu(); printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); } @@ -1531,7 +1564,7 @@ yyreduce: { menu_add_entry(NULL); - menu_add_prompt(P_MENU, yyvsp[-1].string, NULL); + menu_add_prompt(P_MENU, (yyvsp[-1].string), NULL); printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); ;} break; @@ -1547,7 +1580,7 @@ yyreduce: case 65: { - if (zconf_endtoken(yyvsp[0].token, T_MENU, T_ENDMENU)) { + if (zconf_endtoken((yyvsp[0].token), T_MENU, T_ENDMENU)) { menu_end_menu(); printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); } @@ -1570,15 +1603,15 @@ yyreduce: case 73: { - yyval.string = yyvsp[-1].string; - printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), yyvsp[-1].string); + (yyval.string) = (yyvsp[-1].string); + printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string)); ;} break; case 74: { - zconf_nextfile(yyvsp[0].string); + zconf_nextfile((yyvsp[0].string)); ;} break; @@ -1586,7 +1619,7 @@ yyreduce: { menu_add_entry(NULL); - menu_add_prompt(P_COMMENT, yyvsp[-1].string, NULL); + menu_add_prompt(P_COMMENT, (yyvsp[-1].string), NULL); printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); ;} break; @@ -1609,14 +1642,14 @@ yyreduce: case 78: { - current_entry->sym->help = yyvsp[0].string; + current_entry->sym->help = (yyvsp[0].string); ;} break; case 82: { - menu_add_dep(yyvsp[-1].expr); + menu_add_dep((yyvsp[-1].expr)); printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); ;} break; @@ -1624,7 +1657,7 @@ yyreduce: case 83: { - menu_add_dep(yyvsp[-1].expr); + menu_add_dep((yyvsp[-1].expr)); printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno()); ;} break; @@ -1632,7 +1665,7 @@ yyreduce: case 84: { - menu_add_dep(yyvsp[-1].expr); + menu_add_dep((yyvsp[-1].expr)); printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno()); ;} break; @@ -1640,84 +1673,84 @@ yyreduce: case 86: { - menu_add_prompt(P_PROMPT, yyvsp[-1].string, yyvsp[0].expr); + menu_add_prompt(P_PROMPT, (yyvsp[-1].string), (yyvsp[0].expr)); ;} break; case 89: - { yyval.token = T_ENDMENU; ;} + { (yyval.token) = T_ENDMENU; ;} break; case 90: - { yyval.token = T_ENDCHOICE; ;} + { (yyval.token) = T_ENDCHOICE; ;} break; case 91: - { yyval.token = T_ENDIF; ;} + { (yyval.token) = T_ENDIF; ;} break; case 94: - { yyval.expr = NULL; ;} + { (yyval.expr) = NULL; ;} break; case 95: - { yyval.expr = yyvsp[0].expr; ;} + { (yyval.expr) = (yyvsp[0].expr); ;} break; case 96: - { yyval.expr = expr_alloc_symbol(yyvsp[0].symbol); ;} + { (yyval.expr) = expr_alloc_symbol((yyvsp[0].symbol)); ;} break; case 97: - { yyval.expr = expr_alloc_comp(E_EQUAL, yyvsp[-2].symbol, yyvsp[0].symbol); ;} + { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;} break; case 98: - { yyval.expr = expr_alloc_comp(E_UNEQUAL, yyvsp[-2].symbol, yyvsp[0].symbol); ;} + { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;} break; case 99: - { yyval.expr = yyvsp[-1].expr; ;} + { (yyval.expr) = (yyvsp[-1].expr); ;} break; case 100: - { yyval.expr = expr_alloc_one(E_NOT, yyvsp[0].expr); ;} + { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[0].expr)); ;} break; case 101: - { yyval.expr = expr_alloc_two(E_OR, yyvsp[-2].expr, yyvsp[0].expr); ;} + { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} break; case 102: - { yyval.expr = expr_alloc_two(E_AND, yyvsp[-2].expr, yyvsp[0].expr); ;} + { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} break; case 103: - { yyval.symbol = sym_lookup(yyvsp[0].string, 0); free(yyvsp[0].string); ;} + { (yyval.symbol) = sym_lookup((yyvsp[0].string), 0); free((yyvsp[0].string)); ;} break; case 104: - { yyval.symbol = sym_lookup(yyvsp[0].string, 1); free(yyvsp[0].string); ;} + { (yyval.symbol) = sym_lookup((yyvsp[0].string), 1); free((yyvsp[0].string)); ;} break; } -/* Line 999 of yacc.c. */ +/* Line 1037 of yacc.c. */ yyvsp -= yylen; @@ -1759,18 +1792,33 @@ yyerrlab: { YYSIZE_T yysize = 0; int yytype = YYTRANSLATE (yychar); + const char* yyprefix; char *yymsg; - int yyx, yycount; + int yyx; - yycount = 0; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ - for (yyx = yyn < 0 ? -yyn : 0; - yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 0; + + yyprefix = ", expecting "; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - yysize += yystrlen (yytname[yyx]) + 15, yycount++; - yysize += yystrlen ("syntax error, unexpected ") + 1; - yysize += yystrlen (yytname[yytype]); + { + yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]); + yycount += 1; + if (yycount == 5) + { + yysize = 0; + break; + } + } + yysize += (sizeof ("syntax error, unexpected ") + + yystrlen (yytname[yytype])); yymsg = (char *) YYSTACK_ALLOC (yysize); if (yymsg != 0) { @@ -1779,16 +1827,13 @@ yyerrlab: if (yycount < 5) { - yycount = 0; - for (yyx = yyn < 0 ? -yyn : 0; - yyx < (int) (sizeof (yytname) / sizeof (char *)); - yyx++) + yyprefix = ", expecting "; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { - const char *yyq = ! yycount ? ", expecting " : " or "; - yyp = yystpcpy (yyp, yyq); + yyp = yystpcpy (yyp, yyprefix); yyp = yystpcpy (yyp, yytname[yyx]); - yycount++; + yyprefix = " or "; } } yyerror (yymsg); @@ -1806,38 +1851,57 @@ yyerrlab: if (yyerrstatus == 3) { - /* If just tried and failed to reuse lookahead token after an + /* If just tried and failed to reuse look-ahead token after an error, discard it. */ - /* Return failure if at end of input. */ - if (yychar == YYEOF) + if (yychar <= YYEOF) { - /* Pop the error token. */ - YYPOPSTACK; - /* Pop the rest of the stack. */ - while (yyss < yyssp) - { - YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); - yydestruct (yystos[*yyssp], yyvsp); - YYPOPSTACK; - } - YYABORT; + /* If at end of input, pop the error token, + then the rest of the stack, then return failure. */ + if (yychar == YYEOF) + for (;;) + { + + YYPOPSTACK; + if (yyssp == yyss) + YYABORT; + yydestruct ("Error: popping", + yystos[*yyssp], yyvsp); + } } - - YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc); - yydestruct (yytoken, &yylval); - yychar = YYEMPTY; - + else + { + yydestruct ("Error: discarding", yytoken, &yylval); + yychar = YYEMPTY; + } } - /* Else will try to reuse lookahead token after shifting the error + /* Else will try to reuse look-ahead token after shifting the error token. */ goto yyerrlab1; -/*----------------------------------------------------. -| yyerrlab1 -- error raised explicitly by an action. | -`----------------------------------------------------*/ +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + +#ifdef __GNUC__ + /* Pacify GCC when the user code never invokes YYERROR and the label + yyerrorlab therefore never appears in user code. */ + if (0) + goto yyerrorlab; +#endif + +yyvsp -= yylen; + yyssp -= yylen; + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ @@ -1859,22 +1923,22 @@ yyerrlab1: if (yyssp == yyss) YYABORT; - YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); - yydestruct (yystos[yystate], yyvsp); - yyvsp--; - yystate = *--yyssp; + yydestruct ("Error: popping", yystos[yystate], yyvsp); + YYPOPSTACK; + yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } if (yyn == YYFINAL) YYACCEPT; - YYDPRINTF ((stderr, "Shifting error token, ")); - *++yyvsp = yylval; + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + yystate = yyn; goto yynewstate; @@ -1890,6 +1954,9 @@ yyacceptlab: | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: + yydestruct ("Error: discarding lookahead", + yytoken, &yylval); + yychar = YYEMPTY; yyresult = 1; goto yyreturn; diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y index 1e214e9c1d3..43021d436ba 100644 --- a/scripts/kconfig/zconf.y +++ b/scripts/kconfig/zconf.y @@ -11,6 +11,11 @@ #include #include +#define LKC_DIRECT_LINK +#include "lkc.h" + +#include "zconf.hash.c" + #define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) #define PRINTD 0x0001 @@ -88,10 +93,6 @@ static struct menu *current_menu, *current_entry; %type if_expr %type end -%{ -#define LKC_DIRECT_LINK -#include "lkc.h" -%} %% input: /* empty */ | input block -- cgit v1.2.3 From 3370f9f0d9c7d14bf71aab27fa45c0537f130614 Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Tue, 8 Nov 2005 21:34:52 -0800 Subject: [PATCH] kconfig: simplify symbol type parsing This simplifies the parser a bit by merging the various symbol types into a single token and adds the type to the keyword hash. Signed-off-by: Roman Zippel Cc: Sam Ravnborg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/kconfig/lex.zconf.c_shipped | 5 +- scripts/kconfig/lkc.h | 1 + scripts/kconfig/zconf.gperf | 20 +- scripts/kconfig/zconf.hash.c_shipped | 20 +- scripts/kconfig/zconf.l | 5 +- scripts/kconfig/zconf.tab.c_shipped | 608 +++++++++++++++-------------------- scripts/kconfig/zconf.y | 130 +++----- 7 files changed, 342 insertions(+), 447 deletions(-) diff --git a/scripts/kconfig/lex.zconf.c_shipped b/scripts/kconfig/lex.zconf.c_shipped index 0168141417f..bedba89a87c 100644 --- a/scripts/kconfig/lex.zconf.c_shipped +++ b/scripts/kconfig/lex.zconf.c_shipped @@ -1025,6 +1025,7 @@ YY_RULE_SETUP struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); if (id && id->flags & TF_COMMAND) { BEGIN(PARAM); + zconflval.id = id; return id->token; } alloc_string(zconftext, zconfleng); @@ -1091,8 +1092,10 @@ case 19: YY_RULE_SETUP { struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); - if (id && id->flags & TF_PARAM) + if (id && id->flags & TF_PARAM) { + zconflval.id = id; return id->token; + } alloc_string(zconftext, zconfleng); zconflval.string = text; return T_WORD; diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index 6881fb08432..91491d0a302 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h @@ -45,6 +45,7 @@ struct kconf_id { int name; int token; unsigned int flags; + enum symbol_type stype; }; int zconfparse(void); diff --git a/scripts/kconfig/zconf.gperf b/scripts/kconfig/zconf.gperf index c9d81cf5d7f..b03220600b3 100644 --- a/scripts/kconfig/zconf.gperf +++ b/scripts/kconfig/zconf.gperf @@ -25,17 +25,17 @@ endif, T_ENDIF, TF_COMMAND depends, T_DEPENDS, TF_COMMAND requires, T_REQUIRES, TF_COMMAND optional, T_OPTIONAL, TF_COMMAND -default, T_DEFAULT, TF_COMMAND +default, T_DEFAULT, TF_COMMAND, S_UNKNOWN prompt, T_PROMPT, TF_COMMAND -tristate, T_TRISTATE, TF_COMMAND -def_tristate, T_DEF_TRISTATE, TF_COMMAND -bool, T_BOOLEAN, TF_COMMAND -boolean, T_BOOLEAN, TF_COMMAND -def_bool, T_DEF_BOOLEAN, TF_COMMAND -def_boolean, T_DEF_BOOLEAN, TF_COMMAND -int, T_INT, TF_COMMAND -hex, T_HEX, TF_COMMAND -string, T_STRING, TF_COMMAND +tristate, T_TYPE, TF_COMMAND, S_TRISTATE +def_tristate, T_DEFAULT, TF_COMMAND, S_TRISTATE +bool, T_TYPE, TF_COMMAND, S_BOOLEAN +boolean, T_TYPE, TF_COMMAND, S_BOOLEAN +def_bool, T_DEFAULT, TF_COMMAND, S_BOOLEAN +def_boolean, T_DEFAULT, TF_COMMAND, S_BOOLEAN +int, T_TYPE, TF_COMMAND, S_INT +hex, T_TYPE, TF_COMMAND, S_HEX +string, T_TYPE, TF_COMMAND, S_STRING select, T_SELECT, TF_COMMAND enable, T_SELECT, TF_COMMAND range, T_RANGE, TF_COMMAND diff --git a/scripts/kconfig/zconf.hash.c_shipped b/scripts/kconfig/zconf.hash.c_shipped index 6741cb15980..345f0fc07ca 100644 --- a/scripts/kconfig/zconf.hash.c_shipped +++ b/scripts/kconfig/zconf.hash.c_shipped @@ -172,27 +172,27 @@ kconf_id_lookup (register const char *str, register unsigned int len) { {-1}, {-1}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_IF, TF_COMMAND|TF_PARAM}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3, T_INT, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3, T_TYPE, TF_COMMAND, S_INT}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str4, T_HELP, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5, T_ENDIF, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6, T_SELECT, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_ENDMENU, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_TRISTATE, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_TYPE, TF_COMMAND, S_TRISTATE}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9, T_ENDCHOICE, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str10, T_RANGE, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str11, T_STRING, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_DEF_BOOLEAN, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str11, T_TYPE, TF_COMMAND, S_STRING}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_UNKNOWN}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_DEFAULT, TF_COMMAND, S_BOOLEAN}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_MENU, TF_COMMAND}, {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16, T_DEF_BOOLEAN, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_DEF_TRISTATE, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16, T_DEFAULT, TF_COMMAND, S_BOOLEAN}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_DEFAULT, TF_COMMAND, S_TRISTATE}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_MAINMENU, TF_COMMAND}, {-1}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str20, T_MENUCONFIG, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_CONFIG, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_ON, TF_PARAM}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_HEX, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_TYPE, TF_COMMAND, S_HEX}, {-1}, {-1}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26, T_SOURCE, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_DEPENDS, TF_COMMAND}, @@ -201,9 +201,9 @@ kconf_id_lookup (register const char *str, register unsigned int len) {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_SELECT, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_COMMENT, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_REQUIRES, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str34, T_BOOLEAN, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str34, T_TYPE, TF_COMMAND, S_BOOLEAN}, {-1}, {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37, T_BOOLEAN, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37, T_TYPE, TF_COMMAND, S_BOOLEAN}, {-1}, {-1}, {-1}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41, T_CHOICE, TF_COMMAND}, {-1}, {-1}, {-1}, {-1}, diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l index ec902091be9..cfcfabd7a06 100644 --- a/scripts/kconfig/zconf.l +++ b/scripts/kconfig/zconf.l @@ -90,6 +90,7 @@ n [A-Za-z0-9_] struct kconf_id *id = kconf_id_lookup(yytext, yyleng); if (id && id->flags & TF_COMMAND) { BEGIN(PARAM); + zconflval.id = id; return id->token; } alloc_string(yytext, yyleng); @@ -117,8 +118,10 @@ n [A-Za-z0-9_] --- /* ignore */ ({n}|[-/.])+ { struct kconf_id *id = kconf_id_lookup(yytext, yyleng); - if (id && id->flags & TF_PARAM) + if (id && id->flags & TF_PARAM) { + zconflval.id = id; return id->token; + } alloc_string(yytext, yyleng); zconflval.string = text; return T_WORD; diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped index 07fa508d465..3fc296274c9 100644 --- a/scripts/kconfig/zconf.tab.c_shipped +++ b/scripts/kconfig/zconf.tab.c_shipped @@ -78,28 +78,22 @@ T_REQUIRES = 272, T_OPTIONAL = 273, T_PROMPT = 274, - T_DEFAULT = 275, - T_TRISTATE = 276, - T_DEF_TRISTATE = 277, - T_BOOLEAN = 278, - T_DEF_BOOLEAN = 279, - T_STRING = 280, - T_INT = 281, - T_HEX = 282, - T_WORD = 283, - T_WORD_QUOTE = 284, - T_UNEQUAL = 285, + T_TYPE = 275, + T_DEFAULT = 276, + T_SELECT = 277, + T_RANGE = 278, + T_ON = 279, + T_WORD = 280, + T_WORD_QUOTE = 281, + T_UNEQUAL = 282, + T_CLOSE_PAREN = 283, + T_OPEN_PAREN = 284, + T_EOL = 285, T_EOF = 286, - T_EOL = 287, - T_CLOSE_PAREN = 288, - T_OPEN_PAREN = 289, - T_ON = 290, - T_SELECT = 291, - T_RANGE = 292, - T_OR = 293, - T_AND = 294, - T_EQUAL = 295, - T_NOT = 296 + T_OR = 287, + T_AND = 288, + T_EQUAL = 289, + T_NOT = 290 }; #endif #define T_MAINMENU 258 @@ -119,28 +113,22 @@ #define T_REQUIRES 272 #define T_OPTIONAL 273 #define T_PROMPT 274 -#define T_DEFAULT 275 -#define T_TRISTATE 276 -#define T_DEF_TRISTATE 277 -#define T_BOOLEAN 278 -#define T_DEF_BOOLEAN 279 -#define T_STRING 280 -#define T_INT 281 -#define T_HEX 282 -#define T_WORD 283 -#define T_WORD_QUOTE 284 -#define T_UNEQUAL 285 +#define T_TYPE 275 +#define T_DEFAULT 276 +#define T_SELECT 277 +#define T_RANGE 278 +#define T_ON 279 +#define T_WORD 280 +#define T_WORD_QUOTE 281 +#define T_UNEQUAL 282 +#define T_CLOSE_PAREN 283 +#define T_OPEN_PAREN 284 +#define T_EOL 285 #define T_EOF 286 -#define T_EOL 287 -#define T_CLOSE_PAREN 288 -#define T_OPEN_PAREN 289 -#define T_ON 290 -#define T_SELECT 291 -#define T_RANGE 292 -#define T_OR 293 -#define T_AND 294 -#define T_EQUAL 295 -#define T_NOT 296 +#define T_OR 287 +#define T_AND 288 +#define T_EQUAL 289 +#define T_NOT 290 @@ -205,6 +193,7 @@ typedef union YYSTYPE { struct symbol *symbol; struct expr *expr; struct menu *menu; + struct kconf_id *id; } YYSTYPE; /* Line 190 of yacc.c. */ @@ -321,20 +310,20 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 2 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 201 +#define YYLAST 179 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 42 +#define YYNTOKENS 36 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 41 /* YYNRULES -- Number of rules. */ -#define YYNRULES 104 +#define YYNRULES 97 /* YYNRULES -- Number of states. */ -#define YYNSTATES 182 +#define YYNSTATES 159 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 296 +#define YYMAXUTOK 290 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -371,7 +360,7 @@ static const unsigned char yytranslate[] = 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41 + 35 }; #if YYDEBUG @@ -382,67 +371,62 @@ static const unsigned short int yyprhs[] = 0, 0, 3, 4, 7, 9, 11, 13, 17, 19, 21, 23, 26, 28, 30, 32, 34, 36, 38, 42, 45, 49, 52, 53, 56, 59, 62, 65, 69, 74, - 78, 83, 87, 91, 95, 100, 105, 110, 116, 119, - 122, 124, 128, 131, 132, 135, 138, 141, 144, 149, - 153, 157, 160, 165, 166, 169, 173, 175, 179, 182, - 183, 186, 189, 192, 196, 199, 201, 205, 208, 209, - 212, 215, 218, 222, 226, 228, 232, 235, 238, 241, - 242, 245, 248, 253, 257, 261, 262, 265, 267, 269, - 272, 275, 278, 280, 282, 283, 286, 288, 292, 296, - 300, 303, 307, 311, 313 + 79, 84, 90, 93, 96, 98, 102, 105, 106, 109, + 112, 115, 118, 123, 127, 130, 135, 136, 139, 143, + 145, 149, 152, 153, 156, 159, 162, 166, 169, 171, + 175, 178, 179, 182, 185, 188, 192, 196, 198, 202, + 205, 208, 211, 212, 215, 218, 223, 227, 231, 232, + 235, 237, 239, 242, 245, 248, 250, 252, 253, 256, + 258, 262, 266, 270, 273, 277, 281, 283 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yysigned_char yyrhs[] = { - 43, 0, -1, -1, 43, 44, -1, 45, -1, 55, - -1, 66, -1, 3, 77, 79, -1, 5, -1, 15, - -1, 8, -1, 1, 79, -1, 61, -1, 71, -1, - 47, -1, 49, -1, 69, -1, 79, -1, 10, 28, - 32, -1, 46, 50, -1, 11, 28, 32, -1, 48, - 50, -1, -1, 50, 51, -1, 50, 75, -1, 50, - 73, -1, 50, 32, -1, 21, 76, 32, -1, 22, - 81, 80, 32, -1, 23, 76, 32, -1, 24, 81, - 80, 32, -1, 26, 76, 32, -1, 27, 76, 32, - -1, 25, 76, 32, -1, 19, 77, 80, 32, -1, - 20, 81, 80, 32, -1, 36, 28, 80, 32, -1, - 37, 82, 82, 80, 32, -1, 7, 32, -1, 52, - 56, -1, 78, -1, 53, 58, 54, -1, 53, 58, - -1, -1, 56, 57, -1, 56, 75, -1, 56, 73, - -1, 56, 32, -1, 19, 77, 80, 32, -1, 21, - 76, 32, -1, 23, 76, 32, -1, 18, 32, -1, - 20, 28, 80, 32, -1, -1, 58, 45, -1, 14, - 81, 32, -1, 78, -1, 59, 62, 60, -1, 59, - 62, -1, -1, 62, 45, -1, 62, 66, -1, 62, - 55, -1, 4, 77, 32, -1, 63, 74, -1, 78, - -1, 64, 67, 65, -1, 64, 67, -1, -1, 67, - 45, -1, 67, 66, -1, 67, 55, -1, 67, 1, - 32, -1, 6, 77, 32, -1, 68, -1, 9, 77, - 32, -1, 70, 74, -1, 12, 32, -1, 72, 13, - -1, -1, 74, 75, -1, 74, 32, -1, 16, 35, - 81, 32, -1, 16, 81, 32, -1, 17, 81, 32, - -1, -1, 77, 80, -1, 28, -1, 29, -1, 5, - 79, -1, 8, 79, -1, 15, 79, -1, 32, -1, - 31, -1, -1, 14, 81, -1, 82, -1, 82, 40, - 82, -1, 82, 30, 82, -1, 34, 81, 33, -1, - 41, 81, -1, 81, 38, 81, -1, 81, 39, 81, - -1, 28, -1, 29, -1 + 37, 0, -1, -1, 37, 38, -1, 39, -1, 49, + -1, 60, -1, 3, 71, 73, -1, 5, -1, 15, + -1, 8, -1, 1, 73, -1, 55, -1, 65, -1, + 41, -1, 43, -1, 63, -1, 73, -1, 10, 25, + 30, -1, 40, 44, -1, 11, 25, 30, -1, 42, + 44, -1, -1, 44, 45, -1, 44, 69, -1, 44, + 67, -1, 44, 30, -1, 20, 70, 30, -1, 19, + 71, 74, 30, -1, 21, 75, 74, 30, -1, 22, + 25, 74, 30, -1, 23, 76, 76, 74, 30, -1, + 7, 30, -1, 46, 50, -1, 72, -1, 47, 52, + 48, -1, 47, 52, -1, -1, 50, 51, -1, 50, + 69, -1, 50, 67, -1, 50, 30, -1, 19, 71, + 74, 30, -1, 20, 70, 30, -1, 18, 30, -1, + 21, 25, 74, 30, -1, -1, 52, 39, -1, 14, + 75, 30, -1, 72, -1, 53, 56, 54, -1, 53, + 56, -1, -1, 56, 39, -1, 56, 60, -1, 56, + 49, -1, 4, 71, 30, -1, 57, 68, -1, 72, + -1, 58, 61, 59, -1, 58, 61, -1, -1, 61, + 39, -1, 61, 60, -1, 61, 49, -1, 61, 1, + 30, -1, 6, 71, 30, -1, 62, -1, 9, 71, + 30, -1, 64, 68, -1, 12, 30, -1, 66, 13, + -1, -1, 68, 69, -1, 68, 30, -1, 16, 24, + 75, 30, -1, 16, 75, 30, -1, 17, 75, 30, + -1, -1, 71, 74, -1, 25, -1, 26, -1, 5, + 73, -1, 8, 73, -1, 15, 73, -1, 30, -1, + 31, -1, -1, 14, 75, -1, 76, -1, 76, 34, + 76, -1, 76, 27, 76, -1, 29, 75, 28, -1, + 35, 75, -1, 75, 32, 75, -1, 75, 33, 75, + -1, 25, -1, 26, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const unsigned short int yyrline[] = { - 0, 97, 97, 98, 101, 102, 103, 104, 105, 106, - 107, 108, 112, 113, 114, 115, 116, 117, 123, 131, - 137, 145, 155, 157, 158, 159, 160, 163, 169, 176, - 182, 189, 195, 201, 207, 213, 219, 225, 233, 242, - 248, 257, 258, 264, 266, 267, 268, 269, 272, 278, - 284, 290, 296, 302, 304, 309, 318, 327, 328, 334, - 336, 337, 338, 343, 350, 356, 365, 366, 372, 374, - 375, 376, 377, 380, 386, 393, 400, 407, 413, 420, - 421, 422, 425, 430, 435, 443, 445, 450, 451, 454, - 455, 456, 460, 460, 462, 463, 466, 467, 468, 469, - 470, 471, 472, 475, 476 + 0, 92, 92, 93, 96, 97, 98, 99, 100, 101, + 102, 103, 107, 108, 109, 110, 111, 112, 118, 126, + 132, 140, 150, 152, 153, 154, 155, 158, 166, 172, + 182, 188, 196, 205, 211, 220, 221, 227, 229, 230, + 231, 232, 235, 241, 252, 258, 268, 270, 275, 284, + 293, 294, 300, 302, 303, 304, 309, 316, 322, 331, + 332, 338, 340, 341, 342, 343, 346, 352, 359, 366, + 373, 379, 386, 387, 388, 391, 396, 401, 409, 411, + 416, 417, 420, 421, 422, 426, 426, 428, 429, 432, + 433, 434, 435, 436, 437, 438, 441, 442 }; #endif @@ -454,11 +438,10 @@ static const char *const yytname[] = "$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU", "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG", "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS", - "T_REQUIRES", "T_OPTIONAL", "T_PROMPT", "T_DEFAULT", "T_TRISTATE", - "T_DEF_TRISTATE", "T_BOOLEAN", "T_DEF_BOOLEAN", "T_STRING", "T_INT", - "T_HEX", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL", "T_EOF", "T_EOL", - "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_ON", "T_SELECT", "T_RANGE", "T_OR", - "T_AND", "T_EQUAL", "T_NOT", "$accept", "input", "block", "common_block", + "T_REQUIRES", "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", + "T_SELECT", "T_RANGE", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL", + "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_EOF", "T_OR", "T_AND", + "T_EQUAL", "T_NOT", "$accept", "input", "block", "common_block", "config_entry_start", "config_stmt", "menuconfig_entry_start", "menuconfig_stmt", "config_option_list", "config_option", "choice", "choice_entry", "choice_end", "choice_stmt", "choice_option_list", @@ -478,25 +461,23 @@ static const unsigned short int yytoknum[] = 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296 + 285, 286, 287, 288, 289, 290 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const unsigned char yyr1[] = { - 0, 42, 43, 43, 44, 44, 44, 44, 44, 44, - 44, 44, 45, 45, 45, 45, 45, 45, 46, 47, - 48, 49, 50, 50, 50, 50, 50, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 52, 53, - 54, 55, 55, 56, 56, 56, 56, 56, 57, 57, - 57, 57, 57, 58, 58, 59, 60, 61, 61, 62, - 62, 62, 62, 63, 64, 65, 66, 66, 67, 67, - 67, 67, 67, 68, 69, 70, 71, 72, 73, 74, - 74, 74, 75, 75, 75, 76, 76, 77, 77, 78, - 78, 78, 79, 79, 80, 80, 81, 81, 81, 81, - 81, 81, 81, 82, 82 + 0, 36, 37, 37, 38, 38, 38, 38, 38, 38, + 38, 38, 39, 39, 39, 39, 39, 39, 40, 41, + 42, 43, 44, 44, 44, 44, 44, 45, 45, 45, + 45, 45, 46, 47, 48, 49, 49, 50, 50, 50, + 50, 50, 51, 51, 51, 51, 52, 52, 53, 54, + 55, 55, 56, 56, 56, 56, 57, 58, 59, 60, + 60, 61, 61, 61, 61, 61, 62, 63, 64, 65, + 66, 67, 68, 68, 68, 69, 69, 69, 70, 70, + 71, 71, 72, 72, 72, 73, 73, 74, 74, 75, + 75, 75, 75, 75, 75, 75, 76, 76 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ @@ -504,15 +485,14 @@ static const unsigned char yyr2[] = { 0, 2, 0, 2, 1, 1, 1, 3, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 2, - 3, 2, 0, 2, 2, 2, 2, 3, 4, 3, - 4, 3, 3, 3, 4, 4, 4, 5, 2, 2, - 1, 3, 2, 0, 2, 2, 2, 2, 4, 3, - 3, 2, 4, 0, 2, 3, 1, 3, 2, 0, - 2, 2, 2, 3, 2, 1, 3, 2, 0, 2, - 2, 2, 3, 3, 1, 3, 2, 2, 2, 0, - 2, 2, 4, 3, 3, 0, 2, 1, 1, 2, - 2, 2, 1, 1, 0, 2, 1, 3, 3, 3, - 2, 3, 3, 1, 1 + 3, 2, 0, 2, 2, 2, 2, 3, 4, 4, + 4, 5, 2, 2, 1, 3, 2, 0, 2, 2, + 2, 2, 4, 3, 2, 4, 0, 2, 3, 1, + 3, 2, 0, 2, 2, 2, 3, 2, 1, 3, + 2, 0, 2, 2, 2, 3, 3, 1, 3, 2, + 2, 2, 0, 2, 2, 4, 3, 3, 0, 2, + 1, 1, 2, 2, 2, 1, 1, 0, 2, 1, + 3, 3, 3, 2, 3, 3, 1, 1 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -521,69 +501,63 @@ static const unsigned char yyr2[] = static const unsigned char yydefact[] = { 2, 0, 1, 0, 0, 0, 8, 0, 0, 10, - 0, 0, 0, 0, 9, 93, 92, 3, 4, 22, - 14, 22, 15, 43, 53, 5, 59, 12, 79, 68, - 6, 74, 16, 79, 13, 17, 11, 87, 88, 0, - 0, 0, 38, 0, 0, 0, 103, 104, 0, 0, - 0, 96, 19, 21, 39, 42, 58, 64, 0, 76, - 7, 63, 73, 75, 18, 20, 0, 100, 55, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, - 85, 0, 85, 85, 85, 26, 0, 0, 23, 0, - 25, 24, 0, 0, 0, 85, 85, 47, 44, 46, - 45, 0, 0, 0, 54, 41, 40, 60, 62, 57, - 61, 56, 81, 80, 0, 69, 71, 66, 70, 65, - 99, 101, 102, 98, 97, 77, 0, 0, 0, 94, - 94, 0, 94, 94, 0, 94, 0, 0, 0, 94, - 0, 78, 51, 94, 94, 0, 0, 89, 90, 91, - 72, 0, 83, 84, 0, 0, 0, 27, 86, 0, - 29, 0, 33, 31, 32, 0, 94, 0, 0, 49, - 50, 82, 95, 34, 35, 28, 30, 36, 0, 48, - 52, 37 + 0, 0, 0, 0, 9, 85, 86, 3, 4, 22, + 14, 22, 15, 37, 46, 5, 52, 12, 72, 61, + 6, 67, 16, 72, 13, 17, 11, 80, 81, 0, + 0, 0, 32, 0, 0, 0, 96, 97, 0, 0, + 0, 89, 19, 21, 33, 36, 51, 57, 0, 69, + 7, 56, 66, 68, 18, 20, 0, 93, 48, 0, + 0, 0, 0, 0, 0, 0, 0, 78, 0, 0, + 0, 26, 23, 0, 25, 24, 0, 0, 78, 0, + 41, 38, 40, 39, 0, 0, 0, 47, 35, 34, + 53, 55, 50, 54, 49, 74, 73, 0, 62, 64, + 59, 63, 58, 92, 94, 95, 91, 90, 70, 0, + 0, 0, 87, 0, 87, 87, 87, 0, 71, 44, + 87, 0, 87, 82, 83, 84, 65, 0, 76, 77, + 0, 0, 27, 79, 0, 0, 87, 0, 43, 0, + 75, 88, 28, 29, 30, 0, 42, 45, 31 }; /* YYDEFGOTO[NTERM-NUM]. */ static const short int yydefgoto[] = { - -1, 1, 17, 18, 19, 20, 21, 22, 52, 88, - 23, 24, 105, 25, 54, 98, 55, 26, 109, 27, - 56, 28, 29, 117, 30, 58, 31, 32, 33, 34, - 89, 90, 57, 91, 131, 132, 106, 35, 155, 50, + -1, 1, 17, 18, 19, 20, 21, 22, 52, 82, + 23, 24, 98, 25, 54, 91, 55, 26, 102, 27, + 56, 28, 29, 110, 30, 58, 31, 32, 33, 34, + 83, 84, 57, 85, 123, 124, 99, 35, 141, 50, 51 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -99 +#define YYPACT_NINF -113 static const short int yypact[] = { - -99, 48, -99, 38, 46, 46, -99, 46, -29, -99, - 46, -17, -3, -11, -99, -99, -99, -99, -99, -99, - -99, -99, -99, -99, -99, -99, -99, -99, -99, -99, - -99, -99, -99, -99, -99, -99, -99, -99, -99, 38, - 12, 15, -99, 18, 51, 62, -99, -99, -11, -11, - 4, -24, 138, 138, 160, 121, 110, -4, 81, -4, - -99, -99, -99, -99, -99, -99, -19, -99, -99, -11, - -11, 70, 70, 73, 32, -11, 46, -11, 46, -11, - 46, -11, 46, 46, 46, -99, 36, 70, -99, 95, - -99, -99, 96, 46, 106, 46, 46, -99, -99, -99, - -99, 38, 38, 38, -99, -99, -99, -99, -99, -99, - -99, -99, -99, -99, 112, -99, -99, -99, -99, -99, - -99, 117, -99, -99, -99, -99, -11, 33, 65, 131, - 1, 119, 131, 1, 136, 1, 153, 154, 155, 131, - 70, -99, -99, 131, 131, 156, 157, -99, -99, -99, - -99, 101, -99, -99, -11, 158, 159, -99, -99, 161, - -99, 162, -99, -99, -99, 163, 131, 164, 165, -99, - -99, -99, 99, -99, -99, -99, -99, -99, 166, -99, - -99, -99 + -113, 37, -113, 114, 136, 136, -113, 136, -29, -113, + 136, -19, -14, -10, -113, -113, -113, -113, -113, -113, + -113, -113, -113, -113, -113, -113, -113, -113, -113, -113, + -113, -113, -113, -113, -113, -113, -113, -113, -113, 114, + 9, 25, -113, 56, 60, 65, -113, -113, -10, -10, + 33, -1, 108, 108, 41, 103, 92, 5, 74, 5, + -113, -113, -113, -113, -113, -113, 115, -113, -113, -10, + -10, 138, 138, 80, 111, -10, 136, 136, -10, 2, + 138, -113, -113, 113, -113, -113, 85, 136, 136, 107, + -113, -113, -113, -113, 114, 114, 114, -113, -113, -113, + -113, -113, -113, -113, -113, -113, -113, 120, -113, -113, + -113, -113, -113, -113, 121, -113, -113, -113, -113, -10, + 109, 119, 16, 137, 16, 17, 16, 138, -113, -113, + 16, 139, 16, -113, -113, -113, -113, 123, -113, -113, + -10, 140, -113, -113, 141, 142, 16, 143, -113, 144, + -113, 133, -113, -113, -113, 145, -113, -113, -113 }; /* YYPGOTO[NTERM-NUM]. */ static const short int yypgoto[] = { - -99, -99, -99, 111, -99, -99, -99, -99, 178, -99, - -99, -99, -99, 91, -99, -99, -99, -99, -99, -99, - -99, -99, -99, -99, 115, -99, -99, -99, -99, -99, - -99, 146, 168, 89, 27, 0, 126, -1, -98, -48, + -113, -113, -113, 14, -113, -113, -113, -113, 147, -113, + -113, -113, -113, -2, -113, -113, -113, -113, -113, -113, + -113, -113, -113, -113, 101, -113, -113, -113, -113, -113, + -113, 122, 146, 62, 89, 0, 102, -3, -112, -46, -63 }; @@ -591,80 +565,71 @@ static const short int yypgoto[] = positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -68 +#define YYTABLE_NINF -61 static const short int yytable[] = { - 66, 67, 36, 42, 39, 40, 71, 41, 123, 124, - 43, 44, 74, 75, 120, 154, 72, 46, 47, 69, - 70, 121, 122, 48, 140, 45, 127, 128, 112, 130, - 49, 133, 156, 135, 158, 159, 68, 161, 60, 69, - 70, 165, 69, 70, 61, 167, 168, 62, 2, 3, - 63, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 46, 47, 13, 14, 139, 152, 48, 126, 178, 15, - 16, 69, 70, 49, 37, 38, 129, 166, 151, 15, - 16, -67, 114, 64, -67, 5, 101, 7, 8, 102, - 10, 11, 12, 143, 65, 13, 103, 153, 46, 47, - 147, 148, 149, 69, 70, 125, 172, 134, 141, 136, - 137, 138, 15, 16, 5, 101, 7, 8, 102, 10, - 11, 12, 145, 146, 13, 103, 101, 7, 142, 102, - 10, 11, 12, 171, 144, 13, 103, 69, 70, 69, - 70, 15, 16, 100, 150, 154, 113, 108, 113, 116, - 73, 157, 15, 16, 74, 75, 70, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 104, 107, 160, 115, - 85, 110, 73, 118, 86, 87, 74, 75, 92, 93, - 94, 95, 111, 96, 119, 162, 163, 164, 169, 170, - 173, 174, 97, 175, 176, 177, 179, 180, 181, 53, - 99, 59 + 36, 42, 66, 67, 39, 40, 44, 41, 116, 117, + 43, 45, 143, 144, 145, 46, 47, 127, 147, 48, + 149, 74, 75, 114, 115, 49, 71, 126, 120, 121, + 140, 140, 125, 72, 155, 105, 60, 2, 3, 61, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 69, + 70, 13, 14, 73, 101, 62, 109, 74, 75, 86, + 87, 88, 89, 68, 146, 69, 70, 15, 16, 97, + 100, 90, 108, 137, -60, 107, 122, -60, 5, 94, + 7, 8, 95, 10, 11, 12, 63, 130, 13, 96, + 64, 133, 134, 135, 151, 65, 5, 94, 7, 8, + 95, 10, 11, 12, 15, 16, 13, 96, 94, 7, + 118, 95, 10, 11, 12, 129, 93, 13, 96, 106, + 73, 106, 15, 16, 74, 75, 128, 76, 77, 78, + 79, 80, 132, 15, 16, 119, 46, 47, 81, 138, + 48, 69, 70, 113, 15, 16, 49, 69, 70, 139, + 136, 69, 70, 150, 70, 69, 70, 103, 104, 111, + 112, 37, 38, 46, 47, 69, 70, 142, 53, 148, + 152, 153, 154, 156, 157, 158, 92, 131, 0, 59 }; -static const unsigned char yycheck[] = +static const short int yycheck[] = { - 48, 49, 3, 32, 4, 5, 30, 7, 71, 72, - 10, 28, 16, 17, 33, 14, 40, 28, 29, 38, - 39, 69, 70, 34, 87, 28, 74, 75, 32, 77, - 41, 79, 130, 81, 132, 133, 32, 135, 39, 38, - 39, 139, 38, 39, 32, 143, 144, 32, 0, 1, - 32, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 28, 29, 14, 15, 28, 32, 34, 35, 166, 31, - 32, 38, 39, 41, 28, 29, 76, 140, 126, 31, - 32, 0, 1, 32, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 93, 32, 14, 15, 32, 28, 29, - 101, 102, 103, 38, 39, 32, 154, 80, 13, 82, - 83, 84, 31, 32, 4, 5, 6, 7, 8, 9, - 10, 11, 95, 96, 14, 15, 5, 6, 32, 8, - 9, 10, 11, 32, 28, 14, 15, 38, 39, 38, - 39, 31, 32, 54, 32, 14, 57, 56, 59, 58, - 12, 32, 31, 32, 16, 17, 39, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 55, 56, 32, 58, - 32, 56, 12, 58, 36, 37, 16, 17, 18, 19, - 20, 21, 56, 23, 58, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 21, - 54, 33 + 3, 30, 48, 49, 4, 5, 25, 7, 71, 72, + 10, 25, 124, 125, 126, 25, 26, 80, 130, 29, + 132, 16, 17, 69, 70, 35, 27, 25, 74, 75, + 14, 14, 78, 34, 146, 30, 39, 0, 1, 30, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 32, + 33, 14, 15, 12, 56, 30, 58, 16, 17, 18, + 19, 20, 21, 30, 127, 32, 33, 30, 31, 55, + 56, 30, 58, 119, 0, 1, 76, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 30, 87, 14, 15, + 30, 94, 95, 96, 140, 30, 4, 5, 6, 7, + 8, 9, 10, 11, 30, 31, 14, 15, 5, 6, + 30, 8, 9, 10, 11, 30, 54, 14, 15, 57, + 12, 59, 30, 31, 16, 17, 13, 19, 20, 21, + 22, 23, 25, 30, 31, 24, 25, 26, 30, 30, + 29, 32, 33, 28, 30, 31, 35, 32, 33, 30, + 30, 32, 33, 30, 33, 32, 33, 56, 56, 58, + 58, 25, 26, 25, 26, 32, 33, 30, 21, 30, + 30, 30, 30, 30, 30, 30, 54, 88, -1, 33 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const unsigned char yystos[] = { - 0, 43, 0, 1, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 14, 15, 31, 32, 44, 45, 46, - 47, 48, 49, 52, 53, 55, 59, 61, 63, 64, - 66, 68, 69, 70, 71, 79, 79, 28, 29, 77, - 77, 77, 32, 77, 28, 28, 28, 29, 34, 41, - 81, 82, 50, 50, 56, 58, 62, 74, 67, 74, - 79, 32, 32, 32, 32, 32, 81, 81, 32, 38, - 39, 30, 40, 12, 16, 17, 19, 20, 21, 22, - 23, 24, 25, 26, 27, 32, 36, 37, 51, 72, - 73, 75, 18, 19, 20, 21, 23, 32, 57, 73, - 75, 5, 8, 15, 45, 54, 78, 45, 55, 60, - 66, 78, 32, 75, 1, 45, 55, 65, 66, 78, - 33, 81, 81, 82, 82, 32, 35, 81, 81, 77, - 81, 76, 77, 81, 76, 81, 76, 76, 76, 28, - 82, 13, 32, 77, 28, 76, 76, 79, 79, 79, - 32, 81, 32, 32, 14, 80, 80, 32, 80, 80, - 32, 80, 32, 32, 32, 80, 82, 80, 80, 32, - 32, 32, 81, 32, 32, 32, 32, 32, 80, 32, - 32, 32 + 0, 37, 0, 1, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 14, 15, 30, 31, 38, 39, 40, + 41, 42, 43, 46, 47, 49, 53, 55, 57, 58, + 60, 62, 63, 64, 65, 73, 73, 25, 26, 71, + 71, 71, 30, 71, 25, 25, 25, 26, 29, 35, + 75, 76, 44, 44, 50, 52, 56, 68, 61, 68, + 73, 30, 30, 30, 30, 30, 75, 75, 30, 32, + 33, 27, 34, 12, 16, 17, 19, 20, 21, 22, + 23, 30, 45, 66, 67, 69, 18, 19, 20, 21, + 30, 51, 67, 69, 5, 8, 15, 39, 48, 72, + 39, 49, 54, 60, 72, 30, 69, 1, 39, 49, + 59, 60, 72, 28, 75, 75, 76, 76, 30, 24, + 75, 75, 71, 70, 71, 75, 25, 76, 13, 30, + 71, 70, 25, 73, 73, 73, 30, 75, 30, 30, + 14, 74, 30, 74, 74, 74, 76, 74, 30, 74, + 30, 75, 30, 30, 30, 74, 30, 30, 30 }; #if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) @@ -1367,78 +1332,34 @@ yyreduce: case 27: { - menu_set_type(S_TRISTATE); - printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno()); + menu_set_type((yyvsp[-2].id)->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[-2].id)->stype); ;} break; case 28: - { - menu_add_expr(P_DEFAULT, (yyvsp[-2].expr), (yyvsp[-1].expr)); - menu_set_type(S_TRISTATE); - printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno()); -;} - break; - - case 29: - - { - menu_set_type(S_BOOLEAN); - printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno()); -;} - break; - - case 30: - - { - menu_add_expr(P_DEFAULT, (yyvsp[-2].expr), (yyvsp[-1].expr)); - menu_set_type(S_BOOLEAN); - printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno()); -;} - break; - - case 31: - - { - menu_set_type(S_INT); - printd(DEBUG_PARSE, "%s:%d:int\n", zconf_curname(), zconf_lineno()); -;} - break; - - case 32: - - { - menu_set_type(S_HEX); - printd(DEBUG_PARSE, "%s:%d:hex\n", zconf_curname(), zconf_lineno()); -;} - break; - - case 33: - - { - menu_set_type(S_STRING); - printd(DEBUG_PARSE, "%s:%d:string\n", zconf_curname(), zconf_lineno()); -;} - break; - - case 34: - { menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr)); printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); ;} break; - case 35: + case 29: { menu_add_expr(P_DEFAULT, (yyvsp[-2].expr), (yyvsp[-1].expr)); - printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno()); + if ((yyvsp[-3].id)->stype != S_UNKNOWN) + menu_set_type((yyvsp[-3].id)->stype); + printd(DEBUG_PARSE, "%s:%d:default(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[-3].id)->stype); ;} break; - case 36: + case 30: { menu_add_symbol(P_SELECT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr)); @@ -1446,7 +1367,7 @@ yyreduce: ;} break; - case 37: + case 31: { menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[-3].symbol), (yyvsp[-2].symbol)), (yyvsp[-1].expr)); @@ -1454,7 +1375,7 @@ yyreduce: ;} break; - case 38: + case 32: { struct symbol *sym = sym_lookup(NULL, 0); @@ -1465,7 +1386,7 @@ yyreduce: ;} break; - case 39: + case 33: { menu_end_entry(); @@ -1473,7 +1394,7 @@ yyreduce: ;} break; - case 40: + case 34: { if (zconf_endtoken((yyvsp[0].token), T_CHOICE, T_ENDCHOICE)) { @@ -1483,7 +1404,7 @@ yyreduce: ;} break; - case 42: + case 36: { printf("%s:%d: missing 'endchoice' for this 'choice' statement\n", current_menu->file->name, current_menu->lineno); @@ -1491,7 +1412,7 @@ yyreduce: ;} break; - case 48: + case 42: { menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr)); @@ -1499,23 +1420,20 @@ yyreduce: ;} break; - case 49: - - { - menu_set_type(S_TRISTATE); - printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno()); -;} - break; - - case 50: + case 43: { - menu_set_type(S_BOOLEAN); - printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno()); + if ((yyvsp[-2].id)->stype == S_BOOLEAN || (yyvsp[-2].id)->stype == S_TRISTATE) { + menu_set_type((yyvsp[-2].id)->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[-2].id)->stype); + } else + YYERROR; ;} break; - case 51: + case 44: { current_entry->sym->flags |= SYMBOL_OPTIONAL; @@ -1523,15 +1441,19 @@ yyreduce: ;} break; - case 52: + case 45: { - menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr)); - printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno()); + if ((yyvsp[-3].id)->stype == S_UNKNOWN) { + menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr)); + printd(DEBUG_PARSE, "%s:%d:default\n", + zconf_curname(), zconf_lineno()); + } else + YYERROR; ;} break; - case 55: + case 48: { printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); @@ -1542,7 +1464,7 @@ yyreduce: ;} break; - case 56: + case 49: { if (zconf_endtoken((yyvsp[0].token), T_IF, T_ENDIF)) { @@ -1552,7 +1474,7 @@ yyreduce: ;} break; - case 58: + case 51: { printf("%s:%d: missing 'endif' for this 'if' statement\n", current_menu->file->name, current_menu->lineno); @@ -1560,7 +1482,7 @@ yyreduce: ;} break; - case 63: + case 56: { menu_add_entry(NULL); @@ -1569,7 +1491,7 @@ yyreduce: ;} break; - case 64: + case 57: { menu_end_entry(); @@ -1577,7 +1499,7 @@ yyreduce: ;} break; - case 65: + case 58: { if (zconf_endtoken((yyvsp[0].token), T_MENU, T_ENDMENU)) { @@ -1587,7 +1509,7 @@ yyreduce: ;} break; - case 67: + case 60: { printf("%s:%d: missing 'endmenu' for this 'menu' statement\n", current_menu->file->name, current_menu->lineno); @@ -1595,12 +1517,12 @@ yyreduce: ;} break; - case 72: + case 65: { zconfprint("invalid menu option"); yyerrok; ;} break; - case 73: + case 66: { (yyval.string) = (yyvsp[-1].string); @@ -1608,14 +1530,14 @@ yyreduce: ;} break; - case 74: + case 67: { zconf_nextfile((yyvsp[0].string)); ;} break; - case 75: + case 68: { menu_add_entry(NULL); @@ -1624,14 +1546,14 @@ yyreduce: ;} break; - case 76: + case 69: { menu_end_entry(); ;} break; - case 77: + case 70: { printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); @@ -1639,14 +1561,14 @@ yyreduce: ;} break; - case 78: + case 71: { current_entry->sym->help = (yyvsp[0].string); ;} break; - case 82: + case 75: { menu_add_dep((yyvsp[-1].expr)); @@ -1654,7 +1576,7 @@ yyreduce: ;} break; - case 83: + case 76: { menu_add_dep((yyvsp[-1].expr)); @@ -1662,7 +1584,7 @@ yyreduce: ;} break; - case 84: + case 77: { menu_add_dep((yyvsp[-1].expr)); @@ -1670,79 +1592,79 @@ yyreduce: ;} break; - case 86: + case 79: { menu_add_prompt(P_PROMPT, (yyvsp[-1].string), (yyvsp[0].expr)); ;} break; - case 89: + case 82: { (yyval.token) = T_ENDMENU; ;} break; - case 90: + case 83: { (yyval.token) = T_ENDCHOICE; ;} break; - case 91: + case 84: { (yyval.token) = T_ENDIF; ;} break; - case 94: + case 87: { (yyval.expr) = NULL; ;} break; - case 95: + case 88: { (yyval.expr) = (yyvsp[0].expr); ;} break; - case 96: + case 89: { (yyval.expr) = expr_alloc_symbol((yyvsp[0].symbol)); ;} break; - case 97: + case 90: { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;} break; - case 98: + case 91: { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;} break; - case 99: + case 92: { (yyval.expr) = (yyvsp[-1].expr); ;} break; - case 100: + case 93: { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[0].expr)); ;} break; - case 101: + case 94: { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} break; - case 102: + case 95: { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} break; - case 103: + case 96: { (yyval.symbol) = sym_lookup((yyvsp[0].string), 0); free((yyvsp[0].string)); ;} break; - case 104: + case 97: { (yyval.symbol) = sym_lookup((yyvsp[0].string), 1); free((yyvsp[0].string)); ;} break; diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y index 43021d436ba..1211781675b 100644 --- a/scripts/kconfig/zconf.y +++ b/scripts/kconfig/zconf.y @@ -43,43 +43,38 @@ static struct menu *current_menu, *current_entry; struct symbol *symbol; struct expr *expr; struct menu *menu; + struct kconf_id *id; } -%token T_MAINMENU -%token T_MENU -%token T_ENDMENU -%token T_SOURCE -%token T_CHOICE -%token T_ENDCHOICE -%token T_COMMENT -%token T_CONFIG -%token T_MENUCONFIG -%token T_HELP +%token T_MAINMENU +%token T_MENU +%token T_ENDMENU +%token T_SOURCE +%token T_CHOICE +%token T_ENDCHOICE +%token T_COMMENT +%token T_CONFIG +%token T_MENUCONFIG +%token T_HELP %token T_HELPTEXT -%token T_IF -%token T_ENDIF -%token T_DEPENDS -%token T_REQUIRES -%token T_OPTIONAL -%token T_PROMPT -%token T_DEFAULT -%token T_TRISTATE -%token T_DEF_TRISTATE -%token T_BOOLEAN -%token T_DEF_BOOLEAN -%token T_STRING -%token T_INT -%token T_HEX +%token T_IF +%token T_ENDIF +%token T_DEPENDS +%token T_REQUIRES +%token T_OPTIONAL +%token T_PROMPT +%token T_TYPE +%token T_DEFAULT +%token T_SELECT +%token T_RANGE +%token T_ON %token T_WORD %token T_WORD_QUOTE %token T_UNEQUAL -%token T_EOF -%token T_EOL %token T_CLOSE_PAREN %token T_OPEN_PAREN -%token T_ON -%token T_SELECT -%token T_RANGE +%token T_EOL +%token T_EOF %left T_OR %left T_AND @@ -160,48 +155,12 @@ config_option_list: | config_option_list T_EOL ; -config_option: T_TRISTATE prompt_stmt_opt T_EOL -{ - menu_set_type(S_TRISTATE); - printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno()); -}; - -config_option: T_DEF_TRISTATE expr if_expr T_EOL +config_option: T_TYPE prompt_stmt_opt T_EOL { - menu_add_expr(P_DEFAULT, $2, $3); - menu_set_type(S_TRISTATE); - printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno()); -}; - -config_option: T_BOOLEAN prompt_stmt_opt T_EOL -{ - menu_set_type(S_BOOLEAN); - printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno()); -}; - -config_option: T_DEF_BOOLEAN expr if_expr T_EOL -{ - menu_add_expr(P_DEFAULT, $2, $3); - menu_set_type(S_BOOLEAN); - printd(DEBUG_PARSE, "%s:%d:def_boolean\n", zconf_curname(), zconf_lineno()); -}; - -config_option: T_INT prompt_stmt_opt T_EOL -{ - menu_set_type(S_INT); - printd(DEBUG_PARSE, "%s:%d:int\n", zconf_curname(), zconf_lineno()); -}; - -config_option: T_HEX prompt_stmt_opt T_EOL -{ - menu_set_type(S_HEX); - printd(DEBUG_PARSE, "%s:%d:hex\n", zconf_curname(), zconf_lineno()); -}; - -config_option: T_STRING prompt_stmt_opt T_EOL -{ - menu_set_type(S_STRING); - printd(DEBUG_PARSE, "%s:%d:string\n", zconf_curname(), zconf_lineno()); + menu_set_type($1->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + $1->stype); }; config_option: T_PROMPT prompt if_expr T_EOL @@ -213,7 +172,11 @@ config_option: T_PROMPT prompt if_expr T_EOL config_option: T_DEFAULT expr if_expr T_EOL { menu_add_expr(P_DEFAULT, $2, $3); - printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno()); + if ($1->stype != S_UNKNOWN) + menu_set_type($1->stype); + printd(DEBUG_PARSE, "%s:%d:default(%u)\n", + zconf_curname(), zconf_lineno(), + $1->stype); }; config_option: T_SELECT T_WORD if_expr T_EOL @@ -275,16 +238,15 @@ choice_option: T_PROMPT prompt if_expr T_EOL printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); }; -choice_option: T_TRISTATE prompt_stmt_opt T_EOL -{ - menu_set_type(S_TRISTATE); - printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno()); -}; - -choice_option: T_BOOLEAN prompt_stmt_opt T_EOL +choice_option: T_TYPE prompt_stmt_opt T_EOL { - menu_set_type(S_BOOLEAN); - printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno()); + if ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) { + menu_set_type($1->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + $1->stype); + } else + YYERROR; }; choice_option: T_OPTIONAL T_EOL @@ -295,8 +257,12 @@ choice_option: T_OPTIONAL T_EOL choice_option: T_DEFAULT T_WORD if_expr T_EOL { - menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3); - printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno()); + if ($1->stype == S_UNKNOWN) { + menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3); + printd(DEBUG_PARSE, "%s:%d:default\n", + zconf_curname(), zconf_lineno()); + } else + YYERROR; }; choice_block: -- cgit v1.2.3 From a02f0570ae201c495ee991b959bb974af18f35cc Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Tue, 8 Nov 2005 21:34:53 -0800 Subject: [PATCH] kconfig: improve error handling in the parser Add a few error tokens to the parser to catch common errors and print more descriptive error messages. Signed-off-by: Roman Zippel Cc: Sam Ravnborg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/kconfig/lex.zconf.c_shipped | 57 ++-- scripts/kconfig/lkc.h | 2 +- scripts/kconfig/menu.c | 5 +- scripts/kconfig/zconf.l | 42 ++- scripts/kconfig/zconf.tab.c_shipped | 657 ++++++++++++++++++++---------------- scripts/kconfig/zconf.y | 173 ++++++---- 6 files changed, 515 insertions(+), 421 deletions(-) diff --git a/scripts/kconfig/lex.zconf.c_shipped b/scripts/kconfig/lex.zconf.c_shipped index bedba89a87c..24e3c8cbb7a 100644 --- a/scripts/kconfig/lex.zconf.c_shipped +++ b/scripts/kconfig/lex.zconf.c_shipped @@ -323,7 +323,7 @@ void zconffree (void * ); /* Begin user sect3 */ -#define zconfwrap(n) 1 +#define zconfwrap() 1 #define YY_SKIP_YYWRAP typedef unsigned char YY_CHAR; @@ -686,10 +686,10 @@ struct yy_trans_info static yyconst flex_int16_t yy_accept[61] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 34, 5, 4, 3, 2, 7, 8, 6, 32, 29, + 34, 5, 4, 2, 3, 7, 8, 6, 32, 29, 31, 24, 28, 27, 26, 22, 17, 13, 16, 20, - 22, 11, 12, 19, 19, 14, 22, 22, 4, 3, - 2, 2, 1, 6, 32, 29, 31, 30, 24, 23, + 22, 11, 12, 19, 19, 14, 22, 22, 4, 2, + 3, 3, 1, 6, 32, 29, 31, 30, 24, 23, 26, 25, 15, 20, 9, 19, 19, 21, 10, 18 } ; @@ -753,6 +753,11 @@ char *zconftext; #define START_STRSIZE 16 +static struct { + struct file *file; + int lineno; +} current_pos; + static char *text; static int text_size, text_asize; @@ -766,7 +771,7 @@ struct buffer *current_buf; static int last_ts, first_ts; static void zconf_endhelp(void); -static struct buffer *zconf_endfile(void); +static void zconf_endfile(void); void new_string(void) { @@ -993,17 +998,17 @@ do_action: /* This label is used only to access EOF actions. */ { /* beginning of action switch */ case 1: /* rule 1 can match eol */ -YY_RULE_SETUP -current_file->lineno++; - YY_BREAK case 2: +/* rule 2 can match eol */ YY_RULE_SETUP - +{ + current_file->lineno++; + return T_EOL; +} YY_BREAK case 3: -/* rule 3 can match eol */ YY_RULE_SETUP -current_file->lineno++; return T_EOL; + YY_BREAK case 4: YY_RULE_SETUP @@ -1023,8 +1028,10 @@ case 6: YY_RULE_SETUP { struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); + BEGIN(PARAM); + current_pos.file = current_file; + current_pos.lineno = current_file->lineno; if (id && id->flags & TF_COMMAND) { - BEGIN(PARAM); zconflval.id = id; return id->token; } @@ -1040,7 +1047,11 @@ YY_RULE_SETUP case 8: /* rule 8 can match eol */ YY_RULE_SETUP -current_file->lineno++; BEGIN(INITIAL); +{ + BEGIN(INITIAL); + current_file->lineno++; + return T_EOL; + } YY_BREAK case 9: @@ -1246,9 +1257,9 @@ case YY_STATE_EOF(HELP): case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(COMMAND): { - if (current_buf) { + if (current_file) { zconf_endfile(); - return T_EOF; + return T_EOL; } fclose(zconfin); yyterminate(); @@ -1958,7 +1969,7 @@ YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size ) /** Setup the input buffer state to scan a string. The next call to zconflex() will * scan from a @e copy of @a str. - * @param str a NUL-terminated string to scan + * @param yy_str a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use @@ -2276,7 +2287,7 @@ void zconf_nextfile(const char *name) current_file = file; } -static struct buffer *zconf_endfile(void) +static void zconf_endfile(void) { struct buffer *parent; @@ -2292,23 +2303,15 @@ static struct buffer *zconf_endfile(void) } free(current_buf); current_buf = parent; - - return parent; } int zconf_lineno(void) { - if (current_buf) - return current_file->lineno - 1; - else - return 0; + return current_pos.lineno; } char *zconf_curname(void) { - if (current_buf) - return current_file->name; - else - return ""; + return current_pos.file ? current_pos.file->name : ""; } diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index 91491d0a302..ca02eb42eeb 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h @@ -70,7 +70,7 @@ void kconfig_load(void); /* menu.c */ void menu_init(void); -void menu_add_menu(void); +struct menu *menu_add_menu(void); void menu_end_menu(void); void menu_add_entry(struct symbol *sym); void menu_end_entry(void); diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index c2a423a1c34..0fce20cb7f3 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c @@ -61,10 +61,11 @@ void menu_end_entry(void) { } -void menu_add_menu(void) +struct menu *menu_add_menu(void) { - current_menu = current_entry; + menu_end_entry(); last_entry_ptr = ¤t_entry->list; + return current_menu = current_entry; } void menu_end_menu(void) diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l index cfcfabd7a06..cfa46077c6b 100644 --- a/scripts/kconfig/zconf.l +++ b/scripts/kconfig/zconf.l @@ -18,6 +18,11 @@ #define START_STRSIZE 16 +static struct { + struct file *file; + int lineno; +} current_pos; + static char *text; static int text_size, text_asize; @@ -31,7 +36,7 @@ struct buffer *current_buf; static int last_ts, first_ts; static void zconf_endhelp(void); -static struct buffer *zconf_endfile(void); +static void zconf_endfile(void); void new_string(void) { @@ -70,10 +75,13 @@ n [A-Za-z0-9_] int str = 0; int ts, i; -[ \t]*#.*\n current_file->lineno++; +[ \t]*#.*\n | +[ \t]*\n { + current_file->lineno++; + return T_EOL; +} [ \t]*#.* -[ \t]*\n current_file->lineno++; return T_EOL; [ \t]+ { BEGIN(COMMAND); @@ -88,8 +96,10 @@ n [A-Za-z0-9_] { {n}+ { struct kconf_id *id = kconf_id_lookup(yytext, yyleng); + BEGIN(PARAM); + current_pos.file = current_file; + current_pos.lineno = current_file->lineno; if (id && id->flags & TF_COMMAND) { - BEGIN(PARAM); zconflval.id = id; return id->token; } @@ -98,7 +108,11 @@ n [A-Za-z0-9_] return T_WORD; } . - \n current_file->lineno++; BEGIN(INITIAL); + \n { + BEGIN(INITIAL); + current_file->lineno++; + return T_EOL; + } } { @@ -214,9 +228,9 @@ n [A-Za-z0-9_] } <> { - if (current_buf) { + if (current_file) { zconf_endfile(); - return T_EOF; + return T_EOL; } fclose(yyin); yyterminate(); @@ -307,7 +321,7 @@ void zconf_nextfile(const char *name) current_file = file; } -static struct buffer *zconf_endfile(void) +static void zconf_endfile(void) { struct buffer *parent; @@ -323,22 +337,14 @@ static struct buffer *zconf_endfile(void) } free(current_buf); current_buf = parent; - - return parent; } int zconf_lineno(void) { - if (current_buf) - return current_file->lineno - 1; - else - return 0; + return current_pos.lineno; } char *zconf_curname(void) { - if (current_buf) - return current_file->name; - else - return ""; + return current_pos.file ? current_pos.file->name : ""; } diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped index 3fc296274c9..ea7755da82f 100644 --- a/scripts/kconfig/zconf.tab.c_shipped +++ b/scripts/kconfig/zconf.tab.c_shipped @@ -89,11 +89,10 @@ T_CLOSE_PAREN = 283, T_OPEN_PAREN = 284, T_EOL = 285, - T_EOF = 286, - T_OR = 287, - T_AND = 288, - T_EQUAL = 289, - T_NOT = 290 + T_OR = 286, + T_AND = 287, + T_EQUAL = 288, + T_NOT = 289 }; #endif #define T_MAINMENU 258 @@ -124,11 +123,10 @@ #define T_CLOSE_PAREN 283 #define T_OPEN_PAREN 284 #define T_EOL 285 -#define T_EOF 286 -#define T_OR 287 -#define T_AND 288 -#define T_EQUAL 289 -#define T_NOT 290 +#define T_OR 286 +#define T_AND 287 +#define T_EQUAL 288 +#define T_NOT 289 @@ -162,14 +160,18 @@ int cdebug = PRINTD; extern int zconflex(void); static void zconfprint(const char *err, ...); +static void zconf_error(const char *err, ...); static void zconferror(const char *err); -static bool zconf_endtoken(int token, int starttoken, int endtoken); +static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken); struct symbol *symbol_hash[257]; static struct menu *current_menu, *current_entry; +#define YYDEBUG 0 +#if YYDEBUG #define YYERROR_VERBOSE +#endif /* Enabling traces. */ @@ -188,8 +190,8 @@ static struct menu *current_menu, *current_entry; #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) typedef union YYSTYPE { - int token; char *string; + struct file *file; struct symbol *symbol; struct expr *expr; struct menu *menu; @@ -308,22 +310,22 @@ union yyalloc #endif /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 2 +#define YYFINAL 3 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 179 +#define YYLAST 264 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 36 +#define YYNTOKENS 35 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 41 +#define YYNNTS 42 /* YYNRULES -- Number of rules. */ -#define YYNRULES 97 +#define YYNRULES 104 /* YYNRULES -- Number of states. */ -#define YYNSTATES 159 +#define YYNSTATES 175 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 290 +#define YYMAXUTOK 289 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -359,8 +361,7 @@ static const unsigned char yytranslate[] = 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35 + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34 }; #if YYDEBUG @@ -368,65 +369,70 @@ static const unsigned char yytranslate[] = YYRHS. */ static const unsigned short int yyprhs[] = { - 0, 0, 3, 4, 7, 9, 11, 13, 17, 19, - 21, 23, 26, 28, 30, 32, 34, 36, 38, 42, - 45, 49, 52, 53, 56, 59, 62, 65, 69, 74, - 79, 84, 90, 93, 96, 98, 102, 105, 106, 109, - 112, 115, 118, 123, 127, 130, 135, 136, 139, 143, - 145, 149, 152, 153, 156, 159, 162, 166, 169, 171, - 175, 178, 179, 182, 185, 188, 192, 196, 198, 202, - 205, 208, 211, 212, 215, 218, 223, 227, 231, 232, - 235, 237, 239, 242, 245, 248, 250, 252, 253, 256, - 258, 262, 266, 270, 273, 277, 281, 283 + 0, 0, 3, 5, 6, 9, 12, 15, 20, 23, + 28, 33, 37, 39, 41, 43, 45, 47, 49, 51, + 53, 55, 57, 59, 61, 63, 67, 70, 74, 77, + 81, 84, 85, 88, 91, 94, 97, 100, 104, 109, + 114, 119, 125, 128, 131, 133, 137, 138, 141, 144, + 147, 150, 153, 158, 162, 165, 170, 171, 174, 178, + 180, 184, 185, 188, 191, 194, 198, 201, 203, 207, + 208, 211, 214, 217, 221, 225, 228, 231, 234, 235, + 238, 241, 244, 249, 253, 257, 258, 261, 263, 265, + 268, 271, 274, 276, 279, 280, 283, 285, 289, 293, + 297, 300, 304, 308, 310 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yysigned_char yyrhs[] = { - 37, 0, -1, -1, 37, 38, -1, 39, -1, 49, - -1, 60, -1, 3, 71, 73, -1, 5, -1, 15, - -1, 8, -1, 1, 73, -1, 55, -1, 65, -1, - 41, -1, 43, -1, 63, -1, 73, -1, 10, 25, - 30, -1, 40, 44, -1, 11, 25, 30, -1, 42, - 44, -1, -1, 44, 45, -1, 44, 69, -1, 44, - 67, -1, 44, 30, -1, 20, 70, 30, -1, 19, - 71, 74, 30, -1, 21, 75, 74, 30, -1, 22, - 25, 74, 30, -1, 23, 76, 76, 74, 30, -1, - 7, 30, -1, 46, 50, -1, 72, -1, 47, 52, - 48, -1, 47, 52, -1, -1, 50, 51, -1, 50, - 69, -1, 50, 67, -1, 50, 30, -1, 19, 71, - 74, 30, -1, 20, 70, 30, -1, 18, 30, -1, - 21, 25, 74, 30, -1, -1, 52, 39, -1, 14, - 75, 30, -1, 72, -1, 53, 56, 54, -1, 53, - 56, -1, -1, 56, 39, -1, 56, 60, -1, 56, - 49, -1, 4, 71, 30, -1, 57, 68, -1, 72, - -1, 58, 61, 59, -1, 58, 61, -1, -1, 61, - 39, -1, 61, 60, -1, 61, 49, -1, 61, 1, - 30, -1, 6, 71, 30, -1, 62, -1, 9, 71, - 30, -1, 64, 68, -1, 12, 30, -1, 66, 13, - -1, -1, 68, 69, -1, 68, 30, -1, 16, 24, - 75, 30, -1, 16, 75, 30, -1, 17, 75, 30, - -1, -1, 71, 74, -1, 25, -1, 26, -1, 5, - 73, -1, 8, 73, -1, 15, 73, -1, 30, -1, - 31, -1, -1, 14, 75, -1, 76, -1, 76, 34, - 76, -1, 76, 27, 76, -1, 29, 75, 28, -1, - 35, 75, -1, 75, 32, 75, -1, 75, 33, 75, - -1, 25, -1, 26, -1 + 36, 0, -1, 37, -1, -1, 37, 39, -1, 37, + 50, -1, 37, 61, -1, 37, 3, 71, 73, -1, + 37, 72, -1, 37, 25, 1, 30, -1, 37, 38, + 1, 30, -1, 37, 1, 30, -1, 16, -1, 19, + -1, 20, -1, 22, -1, 18, -1, 23, -1, 21, + -1, 30, -1, 56, -1, 65, -1, 42, -1, 44, + -1, 63, -1, 25, 1, 30, -1, 1, 30, -1, + 10, 25, 30, -1, 41, 45, -1, 11, 25, 30, + -1, 43, 45, -1, -1, 45, 46, -1, 45, 69, + -1, 45, 67, -1, 45, 40, -1, 45, 30, -1, + 20, 70, 30, -1, 19, 71, 74, 30, -1, 21, + 75, 74, 30, -1, 22, 25, 74, 30, -1, 23, + 76, 76, 74, 30, -1, 7, 30, -1, 47, 51, + -1, 72, -1, 48, 53, 49, -1, -1, 51, 52, + -1, 51, 69, -1, 51, 67, -1, 51, 30, -1, + 51, 40, -1, 19, 71, 74, 30, -1, 20, 70, + 30, -1, 18, 30, -1, 21, 25, 74, 30, -1, + -1, 53, 39, -1, 14, 75, 73, -1, 72, -1, + 54, 57, 55, -1, -1, 57, 39, -1, 57, 61, + -1, 57, 50, -1, 4, 71, 30, -1, 58, 68, + -1, 72, -1, 59, 62, 60, -1, -1, 62, 39, + -1, 62, 61, -1, 62, 50, -1, 6, 71, 30, + -1, 9, 71, 30, -1, 64, 68, -1, 12, 30, + -1, 66, 13, -1, -1, 68, 69, -1, 68, 30, + -1, 68, 40, -1, 16, 24, 75, 30, -1, 16, + 75, 30, -1, 17, 75, 30, -1, -1, 71, 74, + -1, 25, -1, 26, -1, 5, 30, -1, 8, 30, + -1, 15, 30, -1, 30, -1, 73, 30, -1, -1, + 14, 75, -1, 76, -1, 76, 33, 76, -1, 76, + 27, 76, -1, 29, 75, 28, -1, 34, 75, -1, + 75, 31, 75, -1, 75, 32, 75, -1, 25, -1, + 26, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const unsigned short int yyrline[] = { - 0, 92, 92, 93, 96, 97, 98, 99, 100, 101, - 102, 103, 107, 108, 109, 110, 111, 112, 118, 126, - 132, 140, 150, 152, 153, 154, 155, 158, 166, 172, - 182, 188, 196, 205, 211, 220, 221, 227, 229, 230, - 231, 232, 235, 241, 252, 258, 268, 270, 275, 284, - 293, 294, 300, 302, 303, 304, 309, 316, 322, 331, - 332, 338, 340, 341, 342, 343, 346, 352, 359, 366, - 373, 379, 386, 387, 388, 391, 396, 401, 409, 411, - 416, 417, 420, 421, 422, 426, 426, 428, 429, 432, - 433, 434, 435, 436, 437, 438, 441, 442 + 0, 103, 103, 105, 107, 108, 109, 110, 111, 112, + 113, 117, 121, 121, 121, 121, 121, 121, 121, 125, + 126, 127, 128, 129, 130, 134, 135, 141, 149, 155, + 163, 173, 175, 176, 177, 178, 179, 182, 190, 196, + 206, 212, 220, 229, 234, 242, 245, 247, 248, 249, + 250, 251, 254, 260, 271, 277, 287, 289, 294, 302, + 310, 313, 315, 316, 317, 322, 329, 334, 342, 345, + 347, 348, 349, 352, 360, 367, 374, 380, 387, 389, + 390, 391, 394, 399, 404, 412, 414, 419, 420, 423, + 424, 425, 429, 430, 433, 434, 437, 438, 439, 440, + 441, 442, 443, 446, 447 }; #endif @@ -440,16 +446,16 @@ static const char *const yytname[] = "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS", "T_REQUIRES", "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", "T_SELECT", "T_RANGE", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL", - "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_EOF", "T_OR", "T_AND", - "T_EQUAL", "T_NOT", "$accept", "input", "block", "common_block", - "config_entry_start", "config_stmt", "menuconfig_entry_start", - "menuconfig_stmt", "config_option_list", "config_option", "choice", - "choice_entry", "choice_end", "choice_stmt", "choice_option_list", - "choice_option", "choice_block", "if", "if_end", "if_stmt", "if_block", - "menu", "menu_entry", "menu_end", "menu_stmt", "menu_block", "source", - "source_stmt", "comment", "comment_stmt", "help_start", "help", - "depends_list", "depends", "prompt_stmt_opt", "prompt", "end", - "nl_or_eof", "if_expr", "expr", "symbol", 0 + "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL", + "T_NOT", "$accept", "input", "stmt_list", "option_name", "common_stmt", + "option_error", "config_entry_start", "config_stmt", + "menuconfig_entry_start", "menuconfig_stmt", "config_option_list", + "config_option", "choice", "choice_entry", "choice_end", "choice_stmt", + "choice_option_list", "choice_option", "choice_block", "if_entry", + "if_end", "if_stmt", "if_block", "menu", "menu_entry", "menu_end", + "menu_stmt", "menu_block", "source_stmt", "comment", "comment_stmt", + "help_start", "help", "depends_list", "depends", "prompt_stmt_opt", + "prompt", "end", "nl", "if_expr", "expr", "symbol", 0 }; #endif @@ -461,38 +467,40 @@ static const unsigned short int yytoknum[] = 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290 + 285, 286, 287, 288, 289 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const unsigned char yyr1[] = { - 0, 36, 37, 37, 38, 38, 38, 38, 38, 38, - 38, 38, 39, 39, 39, 39, 39, 39, 40, 41, - 42, 43, 44, 44, 44, 44, 44, 45, 45, 45, - 45, 45, 46, 47, 48, 49, 49, 50, 50, 50, - 50, 50, 51, 51, 51, 51, 52, 52, 53, 54, - 55, 55, 56, 56, 56, 56, 57, 58, 59, 60, - 60, 61, 61, 61, 61, 61, 62, 63, 64, 65, - 66, 67, 68, 68, 68, 69, 69, 69, 70, 70, - 71, 71, 72, 72, 72, 73, 73, 74, 74, 75, - 75, 75, 75, 75, 75, 75, 76, 76 + 0, 35, 36, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 38, 38, 38, 38, 38, 38, 38, 39, + 39, 39, 39, 39, 39, 40, 40, 41, 42, 43, + 44, 45, 45, 45, 45, 45, 45, 46, 46, 46, + 46, 46, 47, 48, 49, 50, 51, 51, 51, 51, + 51, 51, 52, 52, 52, 52, 53, 53, 54, 55, + 56, 57, 57, 57, 57, 58, 59, 60, 61, 62, + 62, 62, 62, 63, 64, 65, 66, 67, 68, 68, + 68, 68, 69, 69, 69, 70, 70, 71, 71, 72, + 72, 72, 73, 73, 74, 74, 75, 75, 75, 75, + 75, 75, 75, 76, 76 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const unsigned char yyr2[] = { - 0, 2, 0, 2, 1, 1, 1, 3, 1, 1, - 1, 2, 1, 1, 1, 1, 1, 1, 3, 2, - 3, 2, 0, 2, 2, 2, 2, 3, 4, 4, - 4, 5, 2, 2, 1, 3, 2, 0, 2, 2, + 0, 2, 1, 0, 2, 2, 2, 4, 2, 4, + 4, 3, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 2, 3, 2, 3, + 2, 0, 2, 2, 2, 2, 2, 3, 4, 4, + 4, 5, 2, 2, 1, 3, 0, 2, 2, 2, 2, 2, 4, 3, 2, 4, 0, 2, 3, 1, - 3, 2, 0, 2, 2, 2, 3, 2, 1, 3, - 2, 0, 2, 2, 2, 3, 3, 1, 3, 2, - 2, 2, 0, 2, 2, 4, 3, 3, 0, 2, - 1, 1, 2, 2, 2, 1, 1, 0, 2, 1, - 3, 3, 3, 2, 3, 3, 1, 1 + 3, 0, 2, 2, 2, 3, 2, 1, 3, 0, + 2, 2, 2, 3, 3, 2, 2, 2, 0, 2, + 2, 2, 4, 3, 3, 0, 2, 1, 1, 2, + 2, 2, 1, 2, 0, 2, 1, 3, 3, 3, + 2, 3, 3, 1, 1 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -500,136 +508,160 @@ static const unsigned char yyr2[] = means the default is an error. */ static const unsigned char yydefact[] = { - 2, 0, 1, 0, 0, 0, 8, 0, 0, 10, - 0, 0, 0, 0, 9, 85, 86, 3, 4, 22, - 14, 22, 15, 37, 46, 5, 52, 12, 72, 61, - 6, 67, 16, 72, 13, 17, 11, 80, 81, 0, - 0, 0, 32, 0, 0, 0, 96, 97, 0, 0, - 0, 89, 19, 21, 33, 36, 51, 57, 0, 69, - 7, 56, 66, 68, 18, 20, 0, 93, 48, 0, - 0, 0, 0, 0, 0, 0, 0, 78, 0, 0, - 0, 26, 23, 0, 25, 24, 0, 0, 78, 0, - 41, 38, 40, 39, 0, 0, 0, 47, 35, 34, - 53, 55, 50, 54, 49, 74, 73, 0, 62, 64, - 59, 63, 58, 92, 94, 95, 91, 90, 70, 0, - 0, 0, 87, 0, 87, 87, 87, 0, 71, 44, - 87, 0, 87, 82, 83, 84, 65, 0, 76, 77, - 0, 0, 27, 79, 0, 0, 87, 0, 43, 0, - 75, 88, 28, 29, 30, 0, 42, 45, 31 + 3, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 12, 16, 13, 14, + 18, 15, 17, 0, 19, 0, 4, 31, 22, 31, + 23, 46, 56, 5, 61, 20, 78, 69, 6, 24, + 78, 21, 8, 11, 87, 88, 0, 0, 89, 0, + 42, 90, 0, 0, 0, 103, 104, 0, 0, 0, + 96, 91, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 92, 7, 65, 73, 74, 27, 29, 0, + 100, 0, 0, 58, 0, 0, 9, 10, 0, 0, + 0, 0, 0, 85, 0, 0, 0, 0, 36, 35, + 32, 0, 34, 33, 0, 0, 85, 0, 50, 51, + 47, 49, 48, 57, 45, 44, 62, 64, 60, 63, + 59, 80, 81, 79, 70, 72, 68, 71, 67, 93, + 99, 101, 102, 98, 97, 26, 76, 0, 0, 0, + 94, 0, 94, 94, 94, 0, 0, 77, 54, 94, + 0, 94, 0, 83, 84, 0, 0, 37, 86, 0, + 0, 94, 25, 0, 53, 0, 82, 95, 38, 39, + 40, 0, 52, 55, 41 }; /* YYDEFGOTO[NTERM-NUM]. */ static const short int yydefgoto[] = { - -1, 1, 17, 18, 19, 20, 21, 22, 52, 82, - 23, 24, 98, 25, 54, 91, 55, 26, 102, 27, - 56, 28, 29, 110, 30, 58, 31, 32, 33, 34, - 83, 84, 57, 85, 123, 124, 99, 35, 141, 50, - 51 + -1, 1, 2, 25, 26, 99, 27, 28, 29, 30, + 64, 100, 31, 32, 114, 33, 66, 110, 67, 34, + 118, 35, 68, 36, 37, 126, 38, 70, 39, 40, + 41, 101, 102, 69, 103, 141, 142, 42, 73, 156, + 59, 60 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -113 +#define YYPACT_NINF -78 static const short int yypact[] = { - -113, 37, -113, 114, 136, 136, -113, 136, -29, -113, - 136, -19, -14, -10, -113, -113, -113, -113, -113, -113, - -113, -113, -113, -113, -113, -113, -113, -113, -113, -113, - -113, -113, -113, -113, -113, -113, -113, -113, -113, 114, - 9, 25, -113, 56, 60, 65, -113, -113, -10, -10, - 33, -1, 108, 108, 41, 103, 92, 5, 74, 5, - -113, -113, -113, -113, -113, -113, 115, -113, -113, -10, - -10, 138, 138, 80, 111, -10, 136, 136, -10, 2, - 138, -113, -113, 113, -113, -113, 85, 136, 136, 107, - -113, -113, -113, -113, 114, 114, 114, -113, -113, -113, - -113, -113, -113, -113, -113, -113, -113, 120, -113, -113, - -113, -113, -113, -113, 121, -113, -113, -113, -113, -10, - 109, 119, 16, 137, 16, 17, 16, 138, -113, -113, - 16, 139, 16, -113, -113, -113, -113, 123, -113, -113, - -10, 140, -113, -113, 141, 142, 16, 143, -113, 144, - -113, 133, -113, -113, -113, 145, -113, -113, -113 + -78, 2, 159, -78, -21, 0, 0, -12, 0, 1, + 4, 0, 27, 38, 60, 58, -78, -78, -78, -78, + -78, -78, -78, 100, -78, 104, -78, -78, -78, -78, + -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, + -78, -78, -78, -78, -78, -78, 86, 113, -78, 114, + -78, -78, 125, 127, 128, -78, -78, 60, 60, 210, + 65, -78, 141, 142, 39, 103, 182, 200, 6, 66, + 6, 131, -78, 146, -78, -78, -78, -78, -78, 196, + -78, 60, 60, 146, 40, 40, -78, -78, 155, 156, + -2, 60, 0, 0, 60, 105, 40, 194, -78, -78, + -78, 206, -78, -78, 183, 0, 0, 195, -78, -78, + -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, + -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, + -78, 197, -78, -78, -78, -78, -78, 60, 213, 216, + 212, 203, 212, 190, 212, 40, 208, -78, -78, 212, + 222, 212, 219, -78, -78, 60, 223, -78, -78, 224, + 225, 212, -78, 226, -78, 227, -78, 47, -78, -78, + -78, 228, -78, -78, -78 }; /* YYPGOTO[NTERM-NUM]. */ static const short int yypgoto[] = { - -113, -113, -113, 14, -113, -113, -113, -113, 147, -113, - -113, -113, -113, -2, -113, -113, -113, -113, -113, -113, - -113, -113, -113, -113, 101, -113, -113, -113, -113, -113, - -113, 122, 146, 62, 89, 0, 102, -3, -112, -46, - -63 + -78, -78, -78, -78, 164, -36, -78, -78, -78, -78, + 230, -78, -78, -78, -78, 29, -78, -78, -78, -78, + -78, -78, -78, -78, -78, -78, 59, -78, -78, -78, + -78, -78, 198, 220, 24, 157, -5, 169, 202, 74, + -53, -77 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -61 +#define YYTABLE_NINF -76 static const short int yytable[] = { - 36, 42, 66, 67, 39, 40, 44, 41, 116, 117, - 43, 45, 143, 144, 145, 46, 47, 127, 147, 48, - 149, 74, 75, 114, 115, 49, 71, 126, 120, 121, - 140, 140, 125, 72, 155, 105, 60, 2, 3, 61, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 69, - 70, 13, 14, 73, 101, 62, 109, 74, 75, 86, - 87, 88, 89, 68, 146, 69, 70, 15, 16, 97, - 100, 90, 108, 137, -60, 107, 122, -60, 5, 94, - 7, 8, 95, 10, 11, 12, 63, 130, 13, 96, - 64, 133, 134, 135, 151, 65, 5, 94, 7, 8, - 95, 10, 11, 12, 15, 16, 13, 96, 94, 7, - 118, 95, 10, 11, 12, 129, 93, 13, 96, 106, - 73, 106, 15, 16, 74, 75, 128, 76, 77, 78, - 79, 80, 132, 15, 16, 119, 46, 47, 81, 138, - 48, 69, 70, 113, 15, 16, 49, 69, 70, 139, - 136, 69, 70, 150, 70, 69, 70, 103, 104, 111, - 112, 37, 38, 46, 47, 69, 70, 142, 53, 148, - 152, 153, 154, 156, 157, 158, 92, 131, 0, 59 + 46, 47, 3, 49, 79, 80, 52, 133, 134, 43, + 6, 7, 8, 9, 10, 11, 12, 13, 48, 145, + 14, 15, 137, 55, 56, 44, 45, 57, 131, 132, + 109, 50, 58, 122, 51, 122, 24, 138, 139, -28, + 88, 143, -28, -28, -28, -28, -28, -28, -28, -28, + -28, 89, 53, -28, -28, 90, 91, -28, 92, 93, + 94, 95, 96, 54, 97, 55, 56, 88, 161, 98, + -66, -66, -66, -66, -66, -66, -66, -66, 81, 82, + -66, -66, 90, 91, 152, 55, 56, 140, 61, 57, + 112, 97, 84, 123, 58, 123, 121, 117, 85, 125, + 149, 62, 167, -30, 88, 63, -30, -30, -30, -30, + -30, -30, -30, -30, -30, 89, 72, -30, -30, 90, + 91, -30, 92, 93, 94, 95, 96, 119, 97, 127, + 144, -75, 88, 98, -75, -75, -75, -75, -75, -75, + -75, -75, -75, 74, 75, -75, -75, 90, 91, -75, + -75, -75, -75, -75, -75, 76, 97, 77, 78, -2, + 4, 121, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 86, 87, 14, 15, 16, 129, 17, 18, 19, + 20, 21, 22, 88, 23, 135, 136, -43, -43, 24, + -43, -43, -43, -43, 89, 146, -43, -43, 90, 91, + 104, 105, 106, 107, 155, 7, 8, 97, 10, 11, + 12, 13, 108, 148, 14, 15, 158, 159, 160, 147, + 151, 81, 82, 163, 130, 165, 155, 81, 82, 82, + 24, 113, 116, 157, 124, 171, 115, 120, 162, 128, + 72, 81, 82, 153, 81, 82, 154, 81, 82, 166, + 81, 82, 164, 168, 169, 170, 172, 173, 174, 65, + 71, 83, 0, 150, 111 }; static const short int yycheck[] = { - 3, 30, 48, 49, 4, 5, 25, 7, 71, 72, - 10, 25, 124, 125, 126, 25, 26, 80, 130, 29, - 132, 16, 17, 69, 70, 35, 27, 25, 74, 75, - 14, 14, 78, 34, 146, 30, 39, 0, 1, 30, - 3, 4, 5, 6, 7, 8, 9, 10, 11, 32, - 33, 14, 15, 12, 56, 30, 58, 16, 17, 18, - 19, 20, 21, 30, 127, 32, 33, 30, 31, 55, - 56, 30, 58, 119, 0, 1, 76, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 30, 87, 14, 15, - 30, 94, 95, 96, 140, 30, 4, 5, 6, 7, - 8, 9, 10, 11, 30, 31, 14, 15, 5, 6, - 30, 8, 9, 10, 11, 30, 54, 14, 15, 57, - 12, 59, 30, 31, 16, 17, 13, 19, 20, 21, - 22, 23, 25, 30, 31, 24, 25, 26, 30, 30, - 29, 32, 33, 28, 30, 31, 35, 32, 33, 30, - 30, 32, 33, 30, 33, 32, 33, 56, 56, 58, - 58, 25, 26, 25, 26, 32, 33, 30, 21, 30, - 30, 30, 30, 30, 30, 30, 54, 88, -1, 33 + 5, 6, 0, 8, 57, 58, 11, 84, 85, 30, + 4, 5, 6, 7, 8, 9, 10, 11, 30, 96, + 14, 15, 24, 25, 26, 25, 26, 29, 81, 82, + 66, 30, 34, 69, 30, 71, 30, 90, 91, 0, + 1, 94, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 25, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 25, 25, 25, 26, 1, 145, 30, + 4, 5, 6, 7, 8, 9, 10, 11, 31, 32, + 14, 15, 16, 17, 137, 25, 26, 92, 30, 29, + 66, 25, 27, 69, 34, 71, 30, 68, 33, 70, + 105, 1, 155, 0, 1, 1, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 30, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 68, 25, 70, + 25, 0, 1, 30, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 30, 30, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 30, 25, 30, 30, 0, + 1, 30, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 30, 30, 14, 15, 16, 30, 18, 19, 20, + 21, 22, 23, 1, 25, 30, 30, 5, 6, 30, + 8, 9, 10, 11, 12, 1, 14, 15, 16, 17, + 18, 19, 20, 21, 14, 5, 6, 25, 8, 9, + 10, 11, 30, 30, 14, 15, 142, 143, 144, 13, + 25, 31, 32, 149, 28, 151, 14, 31, 32, 32, + 30, 67, 68, 30, 70, 161, 67, 68, 30, 70, + 30, 31, 32, 30, 31, 32, 30, 31, 32, 30, + 31, 32, 30, 30, 30, 30, 30, 30, 30, 29, + 40, 59, -1, 106, 66 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const unsigned char yystos[] = { - 0, 37, 0, 1, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 14, 15, 30, 31, 38, 39, 40, - 41, 42, 43, 46, 47, 49, 53, 55, 57, 58, - 60, 62, 63, 64, 65, 73, 73, 25, 26, 71, - 71, 71, 30, 71, 25, 25, 25, 26, 29, 35, - 75, 76, 44, 44, 50, 52, 56, 68, 61, 68, - 73, 30, 30, 30, 30, 30, 75, 75, 30, 32, - 33, 27, 34, 12, 16, 17, 19, 20, 21, 22, - 23, 30, 45, 66, 67, 69, 18, 19, 20, 21, - 30, 51, 67, 69, 5, 8, 15, 39, 48, 72, - 39, 49, 54, 60, 72, 30, 69, 1, 39, 49, - 59, 60, 72, 28, 75, 75, 76, 76, 30, 24, - 75, 75, 71, 70, 71, 75, 25, 76, 13, 30, - 71, 70, 25, 73, 73, 73, 30, 75, 30, 30, - 14, 74, 30, 74, 74, 74, 76, 74, 30, 74, - 30, 75, 30, 30, 30, 74, 30, 30, 30 + 0, 36, 37, 0, 1, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 14, 15, 16, 18, 19, 20, + 21, 22, 23, 25, 30, 38, 39, 41, 42, 43, + 44, 47, 48, 50, 54, 56, 58, 59, 61, 63, + 64, 65, 72, 30, 25, 26, 71, 71, 30, 71, + 30, 30, 71, 25, 25, 25, 26, 29, 34, 75, + 76, 30, 1, 1, 45, 45, 51, 53, 57, 68, + 62, 68, 30, 73, 30, 30, 30, 30, 30, 75, + 75, 31, 32, 73, 27, 33, 30, 30, 1, 12, + 16, 17, 19, 20, 21, 22, 23, 25, 30, 40, + 46, 66, 67, 69, 18, 19, 20, 21, 30, 40, + 52, 67, 69, 39, 49, 72, 39, 50, 55, 61, + 72, 30, 40, 69, 39, 50, 60, 61, 72, 30, + 28, 75, 75, 76, 76, 30, 30, 24, 75, 75, + 71, 70, 71, 75, 25, 76, 1, 13, 30, 71, + 70, 25, 75, 30, 30, 14, 74, 30, 74, 74, + 74, 76, 30, 74, 30, 74, 30, 75, 30, 30, + 30, 74, 30, 30, 30 }; #if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) @@ -966,6 +998,36 @@ yydestruct (yymsg, yytype, yyvaluep) switch (yytype) { + case 48: /* choice_entry */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; + case 54: /* if_entry */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; + case 59: /* menu_entry */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; default: break; @@ -1271,25 +1333,37 @@ yyreduce: { case 8: - { zconfprint("unexpected 'endmenu' statement"); ;} + { zconf_error("unexpected end statement"); ;} break; case 9: - { zconfprint("unexpected 'endif' statement"); ;} + { zconf_error("unknown statement \"%s\"", (yyvsp[-2].string)); ;} break; case 10: - { zconfprint("unexpected 'endchoice' statement"); ;} + { + zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[-2].id)->name); +;} break; case 11: - { zconfprint("syntax error"); yyerrok; ;} + { zconf_error("invalid statement"); ;} break; - case 18: + case 25: + + { zconf_error("unknown option \"%s\"", (yyvsp[-2].string)); ;} + break; + + case 26: + + { zconf_error("invalid option"); ;} + break; + + case 27: { struct symbol *sym = sym_lookup((yyvsp[-1].string), 0); @@ -1299,7 +1373,7 @@ yyreduce: ;} break; - case 19: + case 28: { menu_end_entry(); @@ -1307,7 +1381,7 @@ yyreduce: ;} break; - case 20: + case 29: { struct symbol *sym = sym_lookup((yyvsp[-1].string), 0); @@ -1317,7 +1391,7 @@ yyreduce: ;} break; - case 21: + case 30: { if (current_entry->prompt) @@ -1329,7 +1403,7 @@ yyreduce: ;} break; - case 27: + case 37: { menu_set_type((yyvsp[-2].id)->stype); @@ -1339,7 +1413,7 @@ yyreduce: ;} break; - case 28: + case 38: { menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr)); @@ -1347,7 +1421,7 @@ yyreduce: ;} break; - case 29: + case 39: { menu_add_expr(P_DEFAULT, (yyvsp[-2].expr), (yyvsp[-1].expr)); @@ -1359,7 +1433,7 @@ yyreduce: ;} break; - case 30: + case 40: { menu_add_symbol(P_SELECT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr)); @@ -1367,7 +1441,7 @@ yyreduce: ;} break; - case 31: + case 41: { menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[-3].symbol), (yyvsp[-2].symbol)), (yyvsp[-1].expr)); @@ -1375,7 +1449,7 @@ yyreduce: ;} break; - case 32: + case 42: { struct symbol *sym = sym_lookup(NULL, 0); @@ -1386,33 +1460,24 @@ yyreduce: ;} break; - case 33: + case 43: { - menu_end_entry(); - menu_add_menu(); + (yyval.menu) = menu_add_menu(); ;} break; - case 34: + case 44: { - if (zconf_endtoken((yyvsp[0].token), T_CHOICE, T_ENDCHOICE)) { + if (zconf_endtoken((yyvsp[0].id), T_CHOICE, T_ENDCHOICE)) { menu_end_menu(); printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); } ;} break; - case 36: - - { - printf("%s:%d: missing 'endchoice' for this 'choice' statement\n", current_menu->file->name, current_menu->lineno); - zconfnerrs++; -;} - break; - - case 42: + case 52: { menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr)); @@ -1420,7 +1485,7 @@ yyreduce: ;} break; - case 43: + case 53: { if ((yyvsp[-2].id)->stype == S_BOOLEAN || (yyvsp[-2].id)->stype == S_TRISTATE) { @@ -1433,7 +1498,7 @@ yyreduce: ;} break; - case 44: + case 54: { current_entry->sym->flags |= SYMBOL_OPTIONAL; @@ -1441,7 +1506,7 @@ yyreduce: ;} break; - case 45: + case 55: { if ((yyvsp[-3].id)->stype == S_UNKNOWN) { @@ -1453,36 +1518,27 @@ yyreduce: ;} break; - case 48: + case 58: { printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); menu_add_entry(NULL); menu_add_dep((yyvsp[-1].expr)); - menu_end_entry(); - menu_add_menu(); + (yyval.menu) = menu_add_menu(); ;} break; - case 49: + case 59: { - if (zconf_endtoken((yyvsp[0].token), T_IF, T_ENDIF)) { + if (zconf_endtoken((yyvsp[0].id), T_IF, T_ENDIF)) { menu_end_menu(); printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); } ;} break; - case 51: - - { - printf("%s:%d: missing 'endif' for this 'if' statement\n", current_menu->file->name, current_menu->lineno); - zconfnerrs++; -;} - break; - - case 56: + case 65: { menu_add_entry(NULL); @@ -1491,53 +1547,32 @@ yyreduce: ;} break; - case 57: + case 66: { - menu_end_entry(); - menu_add_menu(); + (yyval.menu) = menu_add_menu(); ;} break; - case 58: + case 67: { - if (zconf_endtoken((yyvsp[0].token), T_MENU, T_ENDMENU)) { + if (zconf_endtoken((yyvsp[0].id), T_MENU, T_ENDMENU)) { menu_end_menu(); printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); } ;} break; - case 60: + case 73: { - printf("%s:%d: missing 'endmenu' for this 'menu' statement\n", current_menu->file->name, current_menu->lineno); - zconfnerrs++; -;} - break; - - case 65: - - { zconfprint("invalid menu option"); yyerrok; ;} - break; - - case 66: - - { - (yyval.string) = (yyvsp[-1].string); printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string)); + zconf_nextfile((yyvsp[-1].string)); ;} break; - case 67: - - { - zconf_nextfile((yyvsp[0].string)); -;} - break; - - case 68: + case 74: { menu_add_entry(NULL); @@ -1546,14 +1581,14 @@ yyreduce: ;} break; - case 69: + case 75: { menu_end_entry(); ;} break; - case 70: + case 76: { printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); @@ -1561,14 +1596,14 @@ yyreduce: ;} break; - case 71: + case 77: { current_entry->sym->help = (yyvsp[0].string); ;} break; - case 75: + case 82: { menu_add_dep((yyvsp[-1].expr)); @@ -1576,7 +1611,7 @@ yyreduce: ;} break; - case 76: + case 83: { menu_add_dep((yyvsp[-1].expr)); @@ -1584,7 +1619,7 @@ yyreduce: ;} break; - case 77: + case 84: { menu_add_dep((yyvsp[-1].expr)); @@ -1592,79 +1627,79 @@ yyreduce: ;} break; - case 79: + case 86: { menu_add_prompt(P_PROMPT, (yyvsp[-1].string), (yyvsp[0].expr)); ;} break; - case 82: + case 89: - { (yyval.token) = T_ENDMENU; ;} + { (yyval.id) = (yyvsp[-1].id); ;} break; - case 83: + case 90: - { (yyval.token) = T_ENDCHOICE; ;} + { (yyval.id) = (yyvsp[-1].id); ;} break; - case 84: + case 91: - { (yyval.token) = T_ENDIF; ;} + { (yyval.id) = (yyvsp[-1].id); ;} break; - case 87: + case 94: { (yyval.expr) = NULL; ;} break; - case 88: + case 95: { (yyval.expr) = (yyvsp[0].expr); ;} break; - case 89: + case 96: { (yyval.expr) = expr_alloc_symbol((yyvsp[0].symbol)); ;} break; - case 90: + case 97: { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;} break; - case 91: + case 98: { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;} break; - case 92: + case 99: { (yyval.expr) = (yyvsp[-1].expr); ;} break; - case 93: + case 100: { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[0].expr)); ;} break; - case 94: + case 101: { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} break; - case 95: + case 102: { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} break; - case 96: + case 103: { (yyval.symbol) = sym_lookup((yyvsp[0].string), 0); free((yyvsp[0].string)); ;} break; - case 97: + case 104: { (yyval.symbol) = sym_lookup((yyvsp[0].string), 1); free((yyvsp[0].string)); ;} break; @@ -1916,7 +1951,10 @@ void conf_parse(const char *name) modules_sym = sym_lookup("MODULES", 0); rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL); - //zconfdebug = 1; +#if YYDEBUG + if (getenv("ZCONF_DEBUG")) + zconfdebug = 1; +#endif zconfparse(); if (zconfnerrs) exit(1); @@ -1937,20 +1975,25 @@ const char *zconf_tokenname(int token) case T_ENDCHOICE: return "endchoice"; case T_IF: return "if"; case T_ENDIF: return "endif"; + case T_DEPENDS: return "depends"; } return ""; } -static bool zconf_endtoken(int token, int starttoken, int endtoken) +static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken) { - if (token != endtoken) { - zconfprint("unexpected '%s' within %s block", zconf_tokenname(token), zconf_tokenname(starttoken)); + if (id->token != endtoken) { + zconf_error("unexpected '%s' within %s block", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); zconfnerrs++; return false; } if (current_menu->file != current_file) { - zconfprint("'%s' in different file than '%s'", zconf_tokenname(token), zconf_tokenname(starttoken)); - zconfprint("location of the '%s'", zconf_tokenname(starttoken)); + zconf_error("'%s' in different file than '%s'", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + fprintf(stderr, "%s:%d: location of the '%s'\n", + current_menu->file->name, current_menu->lineno, + zconf_tokenname(starttoken)); zconfnerrs++; return false; } @@ -1961,7 +2004,19 @@ static void zconfprint(const char *err, ...) { va_list ap; - fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno() + 1); + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconf_error(const char *err, ...) +{ + va_list ap; + + zconfnerrs++; + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); va_start(ap, err); vfprintf(stderr, err, ap); va_end(ap); @@ -1970,7 +2025,9 @@ static void zconfprint(const char *err, ...) static void zconferror(const char *err) { +#if YYDEBUG fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); +#endif } void print_quoted_string(FILE *out, const char *str) diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y index 1211781675b..1f61fba6aa2 100644 --- a/scripts/kconfig/zconf.y +++ b/scripts/kconfig/zconf.y @@ -25,21 +25,25 @@ int cdebug = PRINTD; extern int zconflex(void); static void zconfprint(const char *err, ...); +static void zconf_error(const char *err, ...); static void zconferror(const char *err); -static bool zconf_endtoken(int token, int starttoken, int endtoken); +static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken); struct symbol *symbol_hash[257]; static struct menu *current_menu, *current_entry; +#define YYDEBUG 0 +#if YYDEBUG #define YYERROR_VERBOSE +#endif %} -%expect 40 +%expect 26 %union { - int token; char *string; + struct file *file; struct symbol *symbol; struct expr *expr; struct menu *menu; @@ -74,7 +78,6 @@ static struct menu *current_menu, *current_entry; %token T_CLOSE_PAREN %token T_OPEN_PAREN %token T_EOL -%token T_EOF %left T_OR %left T_AND @@ -82,34 +85,54 @@ static struct menu *current_menu, *current_entry; %nonassoc T_NOT %type prompt -%type source %type symbol %type expr %type if_expr -%type end +%type end +%type option_name +%type if_entry menu_entry choice_entry + +%destructor { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + $$->file->name, $$->lineno); + if (current_menu == $$) + menu_end_menu(); +} if_entry menu_entry choice_entry %% -input: /* empty */ - | input block +input: stmt_list; + +stmt_list: + /* empty */ + | stmt_list common_stmt + | stmt_list choice_stmt + | stmt_list menu_stmt + | stmt_list T_MAINMENU prompt nl + | stmt_list end { zconf_error("unexpected end statement"); } + | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); } + | stmt_list option_name error T_EOL +{ + zconf_error("unexpected option \"%s\"", kconf_id_strings + $2->name); +} + | stmt_list error T_EOL { zconf_error("invalid statement"); } ; -block: common_block - | choice_stmt - | menu_stmt - | T_MAINMENU prompt nl_or_eof - | T_ENDMENU { zconfprint("unexpected 'endmenu' statement"); } - | T_ENDIF { zconfprint("unexpected 'endif' statement"); } - | T_ENDCHOICE { zconfprint("unexpected 'endchoice' statement"); } - | error nl_or_eof { zconfprint("syntax error"); yyerrok; } +option_name: + T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT ; -common_block: - if_stmt +common_stmt: + T_EOL + | if_stmt | comment_stmt | config_stmt | menuconfig_stmt | source_stmt - | nl_or_eof +; + +option_error: + T_WORD error T_EOL { zconf_error("unknown option \"%s\"", $1); } + | error T_EOL { zconf_error("invalid option"); } ; @@ -152,6 +175,7 @@ config_option_list: | config_option_list config_option | config_option_list depends | config_option_list help + | config_option_list option_error | config_option_list T_EOL ; @@ -204,8 +228,7 @@ choice: T_CHOICE T_EOL choice_entry: choice choice_option_list { - menu_end_entry(); - menu_add_menu(); + $$ = menu_add_menu(); }; choice_end: end @@ -216,13 +239,8 @@ choice_end: end } }; -choice_stmt: - choice_entry choice_block choice_end - | choice_entry choice_block -{ - printf("%s:%d: missing 'endchoice' for this 'choice' statement\n", current_menu->file->name, current_menu->lineno); - zconfnerrs++; -}; +choice_stmt: choice_entry choice_block choice_end +; choice_option_list: /* empty */ @@ -230,6 +248,7 @@ choice_option_list: | choice_option_list depends | choice_option_list help | choice_option_list T_EOL + | choice_option_list option_error ; choice_option: T_PROMPT prompt if_expr T_EOL @@ -267,18 +286,17 @@ choice_option: T_DEFAULT T_WORD if_expr T_EOL choice_block: /* empty */ - | choice_block common_block + | choice_block common_stmt ; /* if entry */ -if: T_IF expr T_EOL +if_entry: T_IF expr nl { printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); menu_add_entry(NULL); menu_add_dep($2); - menu_end_entry(); - menu_add_menu(); + $$ = menu_add_menu(); }; if_end: end @@ -289,17 +307,12 @@ if_end: end } }; -if_stmt: - if if_block if_end - | if if_block -{ - printf("%s:%d: missing 'endif' for this 'if' statement\n", current_menu->file->name, current_menu->lineno); - zconfnerrs++; -}; +if_stmt: if_entry if_block if_end +; if_block: /* empty */ - | if_block common_block + | if_block common_stmt | if_block menu_stmt | if_block choice_stmt ; @@ -315,8 +328,7 @@ menu: T_MENU prompt T_EOL menu_entry: menu depends_list { - menu_end_entry(); - menu_add_menu(); + $$ = menu_add_menu(); }; menu_end: end @@ -327,31 +339,20 @@ menu_end: end } }; -menu_stmt: - menu_entry menu_block menu_end - | menu_entry menu_block -{ - printf("%s:%d: missing 'endmenu' for this 'menu' statement\n", current_menu->file->name, current_menu->lineno); - zconfnerrs++; -}; +menu_stmt: menu_entry menu_block menu_end +; menu_block: /* empty */ - | menu_block common_block + | menu_block common_stmt | menu_block menu_stmt | menu_block choice_stmt - | menu_block error T_EOL { zconfprint("invalid menu option"); yyerrok; } ; -source: T_SOURCE prompt T_EOL +source_stmt: T_SOURCE prompt T_EOL { - $$ = $2; printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2); -}; - -source_stmt: source -{ - zconf_nextfile($1); + zconf_nextfile($2); }; /* comment entry */ @@ -383,9 +384,11 @@ help: help_start T_HELPTEXT /* depends option */ -depends_list: /* empty */ - | depends_list depends - | depends_list T_EOL +depends_list: + /* empty */ + | depends_list depends + | depends_list T_EOL + | depends_list option_error ; depends: T_DEPENDS T_ON expr T_EOL @@ -417,13 +420,15 @@ prompt: T_WORD | T_WORD_QUOTE ; -end: T_ENDMENU nl_or_eof { $$ = T_ENDMENU; } - | T_ENDCHOICE nl_or_eof { $$ = T_ENDCHOICE; } - | T_ENDIF nl_or_eof { $$ = T_ENDIF; } +end: T_ENDMENU T_EOL { $$ = $1; } + | T_ENDCHOICE T_EOL { $$ = $1; } + | T_ENDIF T_EOL { $$ = $1; } ; -nl_or_eof: - T_EOL | T_EOF; +nl: + T_EOL + | nl T_EOL +; if_expr: /* empty */ { $$ = NULL; } | T_IF expr { $$ = $2; } @@ -456,7 +461,10 @@ void conf_parse(const char *name) modules_sym = sym_lookup("MODULES", 0); rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL); - //zconfdebug = 1; +#if YYDEBUG + if (getenv("ZCONF_DEBUG")) + zconfdebug = 1; +#endif zconfparse(); if (zconfnerrs) exit(1); @@ -477,20 +485,25 @@ const char *zconf_tokenname(int token) case T_ENDCHOICE: return "endchoice"; case T_IF: return "if"; case T_ENDIF: return "endif"; + case T_DEPENDS: return "depends"; } return ""; } -static bool zconf_endtoken(int token, int starttoken, int endtoken) +static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken) { - if (token != endtoken) { - zconfprint("unexpected '%s' within %s block", zconf_tokenname(token), zconf_tokenname(starttoken)); + if (id->token != endtoken) { + zconf_error("unexpected '%s' within %s block", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); zconfnerrs++; return false; } if (current_menu->file != current_file) { - zconfprint("'%s' in different file than '%s'", zconf_tokenname(token), zconf_tokenname(starttoken)); - zconfprint("location of the '%s'", zconf_tokenname(starttoken)); + zconf_error("'%s' in different file than '%s'", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + fprintf(stderr, "%s:%d: location of the '%s'\n", + current_menu->file->name, current_menu->lineno, + zconf_tokenname(starttoken)); zconfnerrs++; return false; } @@ -501,7 +514,19 @@ static void zconfprint(const char *err, ...) { va_list ap; - fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno() + 1); + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconf_error(const char *err, ...) +{ + va_list ap; + + zconfnerrs++; + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); va_start(ap, err); vfprintf(stderr, err, ap); va_end(ap); @@ -510,7 +535,9 @@ static void zconfprint(const char *err, ...) static void zconferror(const char *err) { +#if YYDEBUG fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); +#endif } void print_quoted_string(FILE *out, const char *str) -- cgit v1.2.3 From c1a0f5e3c01d28b6782457bee5ae5ace3a9958ec Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Tue, 8 Nov 2005 21:34:54 -0800 Subject: [PATCH] kconfig: stricter error checking for .config Add some more checks during the parsing of .config, so that after parsing sym_change_count reflects the correct state whether the .config is correct and in sync with the Kconfig or if it needs saving. Signed-off-by: Roman Zippel Cc: Sam Ravnborg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/kconfig/confdata.c | 95 +++++++++++++++++++++++++++++++++++++--------- scripts/kconfig/lkc.h | 1 - 2 files changed, 77 insertions(+), 19 deletions(-) diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 4bba6202b79..ccd45130c48 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -14,6 +14,12 @@ #define LKC_DIRECT_LINK #include "lkc.h" +static void conf_warning(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); + +static const char *conf_filename; +static int conf_lineno, conf_warnings, conf_unsaved; + const char conf_def_filename[] = ".config"; const char conf_defname[] = "arch/$ARCH/defconfig"; @@ -27,6 +33,17 @@ const char *conf_confnames[] = { NULL, }; +static void conf_warning(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + conf_warnings++; +} + static char *conf_expand_value(const char *in) { struct symbol *sym; @@ -74,7 +91,6 @@ int conf_read_simple(const char *name) FILE *in = NULL; char line[1024]; char *p, *p2; - int lineno = 0; struct symbol *sym; int i; @@ -93,12 +109,18 @@ int conf_read_simple(const char *name) } } } - if (!in) return 1; + conf_filename = name; + conf_lineno = 0; + conf_warnings = 0; + conf_unsaved = 0; + for_all_symbols(i, sym) { sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED; + if (sym_is_choice(sym)) + sym->flags &= ~SYMBOL_NEW; sym->flags &= ~SYMBOL_VALID; switch (sym->type) { case S_INT: @@ -113,7 +135,7 @@ int conf_read_simple(const char *name) } while (fgets(line, sizeof(line), in)) { - lineno++; + conf_lineno++; sym = NULL; switch (line[0]) { case '#': @@ -127,7 +149,10 @@ int conf_read_simple(const char *name) continue; sym = sym_find(line + 9); if (!sym) { - fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line + 9); + conf_warning("trying to assign nonexistent symbol %s", line + 9); + break; + } else if (!(sym->flags & SYMBOL_NEW)) { + conf_warning("trying to reassign symbol %s", sym->name); break; } switch (sym->type) { @@ -141,8 +166,10 @@ int conf_read_simple(const char *name) } break; case 'C': - if (memcmp(line, "CONFIG_", 7)) + if (memcmp(line, "CONFIG_", 7)) { + conf_warning("unexpected data"); continue; + } p = strchr(line + 7, '='); if (!p) continue; @@ -152,7 +179,10 @@ int conf_read_simple(const char *name) *p2 = 0; sym = sym_find(line + 7); if (!sym) { - fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line + 7); + conf_warning("trying to assign nonexistent symbol %s", line + 7); + break; + } else if (!(sym->flags & SYMBOL_NEW)) { + conf_warning("trying to reassign symbol %s", sym->name); break; } switch (sym->type) { @@ -173,6 +203,7 @@ int conf_read_simple(const char *name) sym->flags &= ~SYMBOL_NEW; break; } + conf_warning("symbol value '%s' invalid for %s", p, sym->name); break; case S_STRING: if (*p++ != '"') @@ -185,8 +216,8 @@ int conf_read_simple(const char *name) memmove(p2, p2 + 1, strlen(p2)); } if (!p2) { - fprintf(stderr, "%s:%d: invalid string found\n", name, lineno); - exit(1); + conf_warning("invalid string found"); + continue; } case S_INT: case S_HEX: @@ -194,8 +225,8 @@ int conf_read_simple(const char *name) sym->user.val = strdup(p); sym->flags &= ~SYMBOL_NEW; } else { - fprintf(stderr, "%s:%d: symbol value '%s' invalid for %s\n", name, lineno, p, sym->name); - exit(1); + conf_warning("symbol value '%s' invalid for %s", p, sym->name); + continue; } break; default: @@ -205,6 +236,7 @@ int conf_read_simple(const char *name) case '\n': break; default: + conf_warning("unexpected data"); continue; } if (sym && sym_is_choice_value(sym)) { @@ -213,17 +245,20 @@ int conf_read_simple(const char *name) case no: break; case mod: - if (cs->user.tri == yes) - /* warn? */; + if (cs->user.tri == yes) { + conf_warning("%s creates inconsistent choice state", sym->name); + cs->flags |= SYMBOL_NEW; + } break; case yes: - if (cs->user.tri != no) - /* warn? */; - cs->user.val = sym; + if (cs->user.tri != no) { + conf_warning("%s creates inconsistent choice state", sym->name); + cs->flags |= SYMBOL_NEW; + } else + cs->user.val = sym; break; } cs->user.tri = E_OR(cs->user.tri, sym->user.tri); - cs->flags &= ~SYMBOL_NEW; } } fclose(in); @@ -245,6 +280,28 @@ int conf_read(const char *name) for_all_symbols(i, sym) { sym_calc_value(sym); + if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) + goto sym_ok; + if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { + /* check that calculated value agrees with saved value */ + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym->user.tri != sym_get_tristate_value(sym)) + break; + if (!sym_is_choice(sym)) + goto sym_ok; + default: + if (!strcmp(sym->curr.val, sym->user.val)) + goto sym_ok; + break; + } + } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) + /* no previous value and not saved */ + goto sym_ok; + conf_unsaved++; + /* maybe print value in verbose mode... */ + sym_ok: if (sym_has_value(sym) && !sym_is_choice_value(sym)) { if (sym->visible == no) sym->flags |= SYMBOL_NEW; @@ -252,8 +309,10 @@ int conf_read(const char *name) case S_STRING: case S_INT: case S_HEX: - if (!sym_string_within_range(sym, sym->user.val)) + if (!sym_string_within_range(sym, sym->user.val)) { sym->flags |= SYMBOL_NEW; + sym->flags &= ~SYMBOL_VALID; + } default: break; } @@ -266,7 +325,7 @@ int conf_read(const char *name) sym->flags |= e->right.sym->flags & SYMBOL_NEW; } - sym_change_count = 1; + sym_change_count = conf_warnings && conf_unsaved; return 0; } diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index ca02eb42eeb..527f60c99c5 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h @@ -61,7 +61,6 @@ char *zconf_curname(void); /* confdata.c */ extern const char conf_def_filename[]; -extern char conf_filename[]; char *conf_get_default_confname(void); -- cgit v1.2.3 From 733482e445ca4450cf41381b1c95e2b8c7145114 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Tue, 8 Nov 2005 21:34:55 -0800 Subject: [PATCH] changing CONFIG_LOCALVERSION rebuilds too much, for no good reason This patch removes almost all inclusions of linux/version.h. The 3 #defines are unused in most of the touched files. A few drivers use the simple KERNEL_VERSION(a,b,c) macro, which is unfortunatly in linux/version.h. There are also lots of #ifdef for long obsolete kernels, this was not touched. In a few places, the linux/version.h include was move to where the LINUX_VERSION_CODE was used. quilt vi `find * -type f -name "*.[ch]"|xargs grep -El '(UTS_RELEASE|LINUX_VERSION_CODE|KERNEL_VERSION|linux/version.h)'|grep -Ev '(/(boot|coda|drm)/|~$)'` search pattern: /UTS_RELEASE\|LINUX_VERSION_CODE\|KERNEL_VERSION\|linux\/\(utsname\|version\).h Signed-off-by: Olaf Hering Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/mach-omap1/leds-h2p2-debug.c | 1 - arch/arm/plat-omap/ocpi.c | 1 - arch/cris/arch-v10/drivers/pcf8563.c | 1 - arch/cris/arch-v10/kernel/fasttimer.c | 1 - arch/cris/arch-v32/drivers/nandflash.c | 1 - arch/cris/arch-v32/drivers/pcf8563.c | 1 - arch/mips/tx4938/toshiba_rbtx4938/irq.c | 1 - arch/parisc/kernel/asm-offsets.c | 1 - arch/ppc/syslib/prom.c | 1 - arch/ppc/syslib/prom_init.c | 1 - drivers/block/amiflop.c | 1 - drivers/char/ip2.c | 1 - drivers/char/mwave/tp3780i.c | 1 - drivers/char/mxser.c | 1 - drivers/char/specialix.c | 1 - drivers/char/tpm/tpm.h | 1 - drivers/char/viocons.c | 1 - drivers/char/viotape.c | 1 - drivers/firmware/dell_rbu.c | 1 - drivers/infiniband/ulp/srp/ib_srp.c | 1 - drivers/isdn/divert/divert_init.c | 1 - drivers/isdn/divert/divert_procfs.c | 1 - drivers/isdn/divert/isdn_divert.c | 1 - drivers/isdn/hisax/hisax_fcpcipnp.c | 1 - drivers/isdn/hisax/st5481_init.c | 1 - drivers/isdn/hysdn/hycapi.c | 1 - drivers/isdn/hysdn/hysdn_init.c | 1 - drivers/isdn/hysdn/hysdn_net.c | 1 - drivers/isdn/hysdn/hysdn_procconf.c | 1 - drivers/isdn/hysdn/hysdn_proclog.c | 1 - drivers/isdn/i4l/isdn_common.c | 1 - drivers/isdn/icn/icn.h | 1 - drivers/isdn/isdnloop/isdnloop.h | 1 - drivers/isdn/sc/includes.h | 1 - drivers/md/bitmap.c | 1 - drivers/media/video/arv.c | 1 - drivers/media/video/zr36016.c | 1 - drivers/media/video/zr36050.c | 1 - drivers/media/video/zr36060.c | 1 - drivers/message/fusion/mptbase.c | 1 - drivers/message/fusion/mptbase.h | 1 - drivers/message/fusion/mptctl.c | 1 - drivers/message/fusion/mptctl.h | 1 - drivers/message/fusion/mptlan.h | 1 - drivers/misc/hdpuftrs/hdpu_cpustate.c | 1 - drivers/misc/hdpuftrs/hdpu_nexus.c | 1 - drivers/misc/ibmasm/ibmasm.h | 1 - drivers/mtd/chips/cfi_cmdset_0020.c | 1 - drivers/mtd/devices/pmc551.c | 1 - drivers/mtd/maps/ebony.c | 1 - drivers/mtd/maps/ocotea.c | 1 - drivers/mtd/maps/walnut.c | 1 - drivers/mtd/nand/au1550nd.c | 1 + drivers/mtd/nand/autcpu12.c | 1 - drivers/net/b44.c | 1 - drivers/net/cassini.c | 1 - drivers/net/dm9000.c | 1 - drivers/net/fs_enet/fs_enet.h | 1 - drivers/net/gianfar.c | 1 - drivers/net/gianfar.h | 1 - drivers/net/gianfar_ethtool.c | 1 - drivers/net/gianfar_mii.c | 1 - drivers/net/hp100.c | 1 - drivers/net/ibmveth.c | 1 - drivers/net/iseries_veth.c | 1 - drivers/net/mac8390.c | 1 - drivers/net/mv643xx_eth.h | 1 - drivers/net/s2io.c | 1 - drivers/net/sk98lin/h/skdrv1st.h | 3 --- drivers/net/sk_mca.c | 1 - drivers/net/sk_mca.h | 2 -- drivers/net/starfire.c | 1 - drivers/net/via-velocity.c | 1 - drivers/net/wireless/hostap/hostap.c | 1 - drivers/net/wireless/hostap/hostap_hw.c | 1 - drivers/net/wireless/hostap/hostap_pci.c | 1 - drivers/net/wireless/hostap/hostap_plx.c | 1 - drivers/net/wireless/ipw2100.h | 1 - drivers/net/wireless/ipw2200.c | 1 + drivers/net/wireless/ipw2200.h | 1 - drivers/net/wireless/orinoco.h | 1 - drivers/net/wireless/prism54/isl_38xx.c | 1 - drivers/net/wireless/prism54/isl_38xx.h | 1 - drivers/net/wireless/prism54/isl_ioctl.c | 1 - drivers/net/wireless/prism54/islpci_dev.c | 1 - drivers/net/wireless/prism54/islpci_dev.h | 1 - drivers/net/wireless/prism54/islpci_eth.c | 1 - drivers/net/wireless/prism54/islpci_hotplug.c | 1 - drivers/pcmcia/au1000_pb1x00.c | 1 - drivers/pcmcia/au1000_xxs1500.c | 1 - drivers/s390/crypto/z90main.c | 1 - drivers/s390/net/claw.c | 1 - drivers/scsi/3w-xxxx.h | 1 - drivers/scsi/a2091.c | 1 - drivers/scsi/aic7xxx/aic79xx_osm.h | 1 - drivers/scsi/aic7xxx/aic7xxx_osm.h | 1 - drivers/scsi/amiga7xx.c | 1 - drivers/scsi/bvme6000.c | 1 - drivers/scsi/gvp11.c | 1 - drivers/scsi/ibmmca.c | 6 ------ drivers/scsi/ips.h | 1 + drivers/scsi/megaraid/mega_common.h | 1 - drivers/scsi/megaraid/megaraid_mm.h | 1 - drivers/scsi/megaraid/megaraid_sas.c | 1 - drivers/scsi/mvme147.c | 1 - drivers/scsi/mvme16x.c | 1 - drivers/scsi/nsp32.h | 1 + drivers/scsi/pci2000.h | 3 --- drivers/scsi/scsi_debug.c | 4 ---- drivers/scsi/sg.c | 4 ---- drivers/scsi/sgiwd93.c | 1 - drivers/scsi/wd33c93.c | 1 - drivers/telephony/ixj.h | 1 - drivers/usb/gadget/dummy_hcd.c | 1 - drivers/usb/gadget/lh7a40x_udc.h | 1 - drivers/usb/gadget/pxa2xx_udc.c | 1 - drivers/usb/gadget/rndis.c | 1 - drivers/usb/host/hc_crisv10.c | 1 - drivers/usb/media/pwc/pwc-if.c | 1 + drivers/usb/media/pwc/pwc.h | 2 -- drivers/usb/media/w9968cf.c | 1 - drivers/usb/misc/sisusbvga/sisusb.c | 1 - drivers/usb/misc/sisusbvga/sisusb.h | 1 + drivers/usb/misc/sisusbvga/sisusb_con.c | 1 - drivers/usb/misc/sisusbvga/sisusb_init.c | 1 - drivers/video/backlight/backlight.c | 1 - drivers/video/backlight/lcd.c | 1 - drivers/video/intelfb/intelfbdrv.c | 1 - drivers/video/intelfb/intelfbhw.c | 1 - fs/9p/vfs_file.c | 1 - fs/adfs/adfs.h | 1 - fs/hfs/hfs_fs.h | 1 - fs/hfs/inode.c | 1 - fs/hfsplus/bnode.c | 1 - fs/hfsplus/dir.c | 1 - fs/hfsplus/extents.c | 1 - fs/hfsplus/hfsplus_fs.h | 1 - fs/hfsplus/inode.c | 1 - fs/hfsplus/super.c | 1 - fs/hfsplus/wrapper.c | 1 - fs/hostfs/hostfs_kern.c | 1 - fs/xfs/linux-2.6/xfs_linux.h | 1 - fs/xfs/xfs.h | 7 ------- fs/xfs/xfs_dmapi.h | 1 + include/linux/fs_enet_pd.h | 1 - include/linux/if_wanpipe_common.h | 2 -- include/linux/istallion.h | 2 -- include/linux/mtd/cfi.h | 1 - include/linux/mtd/mtd.h | 1 - include/linux/phonedev.h | 1 - include/linux/stallion.h | 2 -- sound/oss/msnd.c | 1 - sound/oss/os.h | 2 -- sound/oss/rme96xx.c | 1 - sound/oss/sh_dac_audio.c | 1 - sound/ppc/pmac.h | 1 - 156 files changed, 7 insertions(+), 176 deletions(-) diff --git a/arch/arm/mach-omap1/leds-h2p2-debug.c b/arch/arm/mach-omap1/leds-h2p2-debug.c index be283cda63d..399010c1403 100644 --- a/arch/arm/mach-omap1/leds-h2p2-debug.c +++ b/arch/arm/mach-omap1/leds-h2p2-debug.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/plat-omap/ocpi.c b/arch/arm/plat-omap/ocpi.c index 1fb16f9edfd..2ede2ee8cae 100644 --- a/arch/arm/plat-omap/ocpi.c +++ b/arch/arm/plat-omap/ocpi.c @@ -25,7 +25,6 @@ #include #include -#include #include #include #include diff --git a/arch/cris/arch-v10/drivers/pcf8563.c b/arch/cris/arch-v10/drivers/pcf8563.c index 201f4c90d96..f2c55742e90 100644 --- a/arch/cris/arch-v10/drivers/pcf8563.c +++ b/arch/cris/arch-v10/drivers/pcf8563.c @@ -19,7 +19,6 @@ */ #include -#include #include #include #include diff --git a/arch/cris/arch-v10/kernel/fasttimer.c b/arch/cris/arch-v10/kernel/fasttimer.c index 094ff45ae85..cac05a5e514 100644 --- a/arch/cris/arch-v10/kernel/fasttimer.c +++ b/arch/cris/arch-v10/kernel/fasttimer.c @@ -112,7 +112,6 @@ #include #include -#include #include #include diff --git a/arch/cris/arch-v32/drivers/nandflash.c b/arch/cris/arch-v32/drivers/nandflash.c index fc2a619b035..93ddea4d956 100644 --- a/arch/cris/arch-v32/drivers/nandflash.c +++ b/arch/cris/arch-v32/drivers/nandflash.c @@ -14,7 +14,6 @@ * */ -#include #include #include #include diff --git a/arch/cris/arch-v32/drivers/pcf8563.c b/arch/cris/arch-v32/drivers/pcf8563.c index f894580b648..d788bda3578 100644 --- a/arch/cris/arch-v32/drivers/pcf8563.c +++ b/arch/cris/arch-v32/drivers/pcf8563.c @@ -18,7 +18,6 @@ */ #include -#include #include #include #include diff --git a/arch/mips/tx4938/toshiba_rbtx4938/irq.c b/arch/mips/tx4938/toshiba_rbtx4938/irq.c index 230f5a93c2e..9cd9c0fe226 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/irq.c +++ b/arch/mips/tx4938/toshiba_rbtx4938/irq.c @@ -84,7 +84,6 @@ IRQ Device #include #include #include -#include #include #include diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c index 1ad44f92d6e..e23c4e1e3a2 100644 --- a/arch/parisc/kernel/asm-offsets.c +++ b/arch/parisc/kernel/asm-offsets.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include diff --git a/arch/ppc/syslib/prom.c b/arch/ppc/syslib/prom.c index 03b1fc9b950..af4deace49e 100644 --- a/arch/ppc/syslib/prom.c +++ b/arch/ppc/syslib/prom.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/syslib/prom_init.c b/arch/ppc/syslib/prom_init.c index 7f15136830f..df14422ae1c 100644 --- a/arch/ppc/syslib/prom_init.c +++ b/arch/ppc/syslib/prom_init.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 1468e8cf712..0acbfff8ad2 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -1816,7 +1816,6 @@ out_blkdev: } #ifdef MODULE -#include int init_module(void) { diff --git a/drivers/char/ip2.c b/drivers/char/ip2.c index 6cd12f23aa5..7cadfc6ef35 100644 --- a/drivers/char/ip2.c +++ b/drivers/char/ip2.c @@ -7,7 +7,6 @@ // #include -#include #include #include diff --git a/drivers/char/mwave/tp3780i.c b/drivers/char/mwave/tp3780i.c index d6c72e0934e..cc3e54dd723 100644 --- a/drivers/char/mwave/tp3780i.c +++ b/drivers/char/mwave/tp3780i.c @@ -46,7 +46,6 @@ * First release to the public */ -#include #include #include #include diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 3b965a651da..26448f17680 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -38,7 +38,6 @@ #include #include -#include #include #include #include diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 352547eabf7..0bbfce43031 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -90,7 +90,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 99a60496ecc..9293bcc4dc6 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -19,7 +19,6 @@ * */ #include -#include #include #include #include diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c index 98601c7d04a..4d75c261f98 100644 --- a/drivers/char/viocons.c +++ b/drivers/char/viocons.c @@ -26,7 +26,6 @@ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include -#include #include #include #include diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index 867cc4e418c..60aabdb4a04 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c @@ -32,7 +32,6 @@ * iseries/vio.h */ #include -#include #include #include #include diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index ba17292eb29..6d83299e7c9 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c @@ -34,7 +34,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ -#include #include #include #include diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 2687e34aa5b..321a3a10e69 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -32,7 +32,6 @@ * $Id: ib_srp.c 3932 2005-11-01 17:19:29Z roland $ */ -#include #include #include #include diff --git a/drivers/isdn/divert/divert_init.c b/drivers/isdn/divert/divert_init.c index 434e684f5db..2f7c9fc2e89 100644 --- a/drivers/isdn/divert/divert_init.c +++ b/drivers/isdn/divert/divert_init.c @@ -10,7 +10,6 @@ */ #include -#include #include #include diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c index 0b0ea26023e..1b37d86d5ee 100644 --- a/drivers/isdn/divert/divert_procfs.c +++ b/drivers/isdn/divert/divert_procfs.c @@ -11,7 +11,6 @@ #include #include -#include #include #include #ifdef CONFIG_PROC_FS diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c index 0bfd698726a..f1a1f9a9b88 100644 --- a/drivers/isdn/divert/isdn_divert.c +++ b/drivers/isdn/divert/isdn_divert.c @@ -9,7 +9,6 @@ * */ -#include #include #include "isdn_divert.h" diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c index b4d795d4015..dc7ef957e89 100644 --- a/drivers/isdn/hisax/hisax_fcpcipnp.c +++ b/drivers/isdn/hisax/hisax_fcpcipnp.c @@ -23,7 +23,6 @@ * o tx_skb at PH_DEACTIVATE time */ -#include #include #include #include diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c index 2cf5d1a6df6..8e192a3a349 100644 --- a/drivers/isdn/hisax/st5481_init.c +++ b/drivers/isdn/hisax/st5481_init.c @@ -25,7 +25,6 @@ */ #include -#include #include #include #include diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c index 1fd3d4e5f28..acc1d3cceeb 100644 --- a/drivers/isdn/hysdn/hycapi.c +++ b/drivers/isdn/hysdn/hycapi.c @@ -11,7 +11,6 @@ */ #include -#include #include #include #include diff --git a/drivers/isdn/hysdn/hysdn_init.c b/drivers/isdn/hysdn/hysdn_init.c index 12c8137b516..cb791f8e793 100644 --- a/drivers/isdn/hysdn/hysdn_init.c +++ b/drivers/isdn/hysdn/hysdn_init.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c index babec8157ae..aa01628d74c 100644 --- a/drivers/isdn/hysdn/hysdn_net.c +++ b/drivers/isdn/hysdn/hysdn_net.c @@ -14,7 +14,6 @@ */ #include -#include #include #include #include diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c index 87f59a0e2a9..40e56143c76 100644 --- a/drivers/isdn/hysdn/hysdn_procconf.c +++ b/drivers/isdn/hysdn/hysdn_procconf.c @@ -12,7 +12,6 @@ */ #include -#include #include #include #include diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c index 4d57011c573..6c26f1efabd 100644 --- a/drivers/isdn/hysdn/hysdn_proclog.c +++ b/drivers/isdn/hysdn/hysdn_proclog.c @@ -11,7 +11,6 @@ */ #include -#include #include #include #include diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index 8a7d54a5c97..4643df097bf 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/isdn/icn/icn.h b/drivers/isdn/icn/icn.h index 9028cc3b507..7d7245fb0b3 100644 --- a/drivers/isdn/icn/icn.h +++ b/drivers/isdn/icn/icn.h @@ -35,7 +35,6 @@ typedef struct icn_cdef { #ifdef __KERNEL__ /* Kernel includes */ -#include #include #include #include diff --git a/drivers/isdn/isdnloop/isdnloop.h b/drivers/isdn/isdnloop/isdnloop.h index 8fb7bc1bfe0..d699fe53e1c 100644 --- a/drivers/isdn/isdnloop/isdnloop.h +++ b/drivers/isdn/isdnloop/isdnloop.h @@ -33,7 +33,6 @@ typedef struct isdnloop_sdef { #ifdef __KERNEL__ /* Kernel includes */ -#include #include #include #include diff --git a/drivers/isdn/sc/includes.h b/drivers/isdn/sc/includes.h index 4611da6e923..5286e0c810a 100644 --- a/drivers/isdn/sc/includes.h +++ b/drivers/isdn/sc/includes.h @@ -4,7 +4,6 @@ * */ -#include #include #include #include diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 01654fcabc5..e59694bc575 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -21,7 +21,6 @@ */ #include -#include #include #include #include diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index 0823ddaf700..881cdcb1875 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/video/zr36016.c b/drivers/media/video/zr36016.c index d4740a89cea..4ed898585c7 100644 --- a/drivers/media/video/zr36016.c +++ b/drivers/media/video/zr36016.c @@ -26,7 +26,6 @@ #define ZR016_VERSION "v0.7" -#include #include #include #include diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zr36050.c index 13b1e7b6fd6..0144576a612 100644 --- a/drivers/media/video/zr36050.c +++ b/drivers/media/video/zr36050.c @@ -26,7 +26,6 @@ #define ZR050_VERSION "v0.7.1" -#include #include #include #include diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zr36060.c index b50dc403e6d..129744a07ab 100644 --- a/drivers/media/video/zr36060.c +++ b/drivers/media/video/zr36060.c @@ -26,7 +26,6 @@ #define ZR060_VERSION "v0.7" -#include #include #include #include diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 790a2932ded..65c2ec5c421 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -47,7 +47,6 @@ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ #include -#include #include #include #include diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index e7efeb7740b..5f5b3fb5b4d 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -49,7 +49,6 @@ #define MPTBASE_H_INCLUDED /*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#include #include #include #include diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index cb2d59d5f5a..602138f8544 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -45,7 +45,6 @@ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#include #include #include #include diff --git a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h index 28754a9cb80..518996e0348 100644 --- a/drivers/message/fusion/mptctl.h +++ b/drivers/message/fusion/mptctl.h @@ -49,7 +49,6 @@ #define MPTCTL_H_INCLUDED /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#include "linux/version.h" /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptlan.h b/drivers/message/fusion/mptlan.h index 750e343eb98..3726ecba570 100644 --- a/drivers/message/fusion/mptlan.h +++ b/drivers/message/fusion/mptlan.h @@ -66,7 +66,6 @@ #include #include #include -#include #include #include // #include diff --git a/drivers/misc/hdpuftrs/hdpu_cpustate.c b/drivers/misc/hdpuftrs/hdpu_cpustate.c index 9c4dd682ac7..bc2b72b3290 100644 --- a/drivers/misc/hdpuftrs/hdpu_cpustate.c +++ b/drivers/misc/hdpuftrs/hdpu_cpustate.c @@ -14,7 +14,6 @@ * */ -#include #include #include #include diff --git a/drivers/misc/hdpuftrs/hdpu_nexus.c b/drivers/misc/hdpuftrs/hdpu_nexus.c index 165f3405df2..4bb46179385 100644 --- a/drivers/misc/hdpuftrs/hdpu_nexus.c +++ b/drivers/misc/hdpuftrs/hdpu_nexus.c @@ -14,7 +14,6 @@ * */ -#include #include #include #include diff --git a/drivers/misc/ibmasm/ibmasm.h b/drivers/misc/ibmasm/ibmasm.h index ecce4ffd3e2..d7e20a34f88 100644 --- a/drivers/misc/ibmasm/ibmasm.h +++ b/drivers/misc/ibmasm/ibmasm.h @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index c4a19d2dc67..0807c1c91e5 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c @@ -20,7 +20,6 @@ * - Plugged memory leak in cfi_staa_writev(). */ -#include #include #include #include diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c index de48b35f560..666cce1bf60 100644 --- a/drivers/mtd/devices/pmc551.c +++ b/drivers/mtd/devices/pmc551.c @@ -82,7 +82,6 @@ * * Comb the init routine. It's still a bit cludgy on a few things. */ -#include #include #include #include diff --git a/drivers/mtd/maps/ebony.c b/drivers/mtd/maps/ebony.c index c0daf58357c..60a6e51d662 100644 --- a/drivers/mtd/maps/ebony.c +++ b/drivers/mtd/maps/ebony.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mtd/maps/ocotea.c b/drivers/mtd/maps/ocotea.c index 6e559bc1463..c223514ca2e 100644 --- a/drivers/mtd/maps/ocotea.c +++ b/drivers/mtd/maps/ocotea.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mtd/maps/walnut.c b/drivers/mtd/maps/walnut.c index 5c17bca3a37..f46bec66150 100644 --- a/drivers/mtd/maps/walnut.c +++ b/drivers/mtd/maps/walnut.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 3cafcdf28ae..9c5945d6df8 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c @@ -17,6 +17,7 @@ #include #include #include +#include #include /* fixme: this is ugly */ diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c index 056dfc17a07..a3c7fea404d 100644 --- a/drivers/mtd/nand/autcpu12.c +++ b/drivers/mtd/nand/autcpu12.c @@ -27,7 +27,6 @@ * 10-06-2002 TG 128K card support added */ -#include #include #include #include diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 0ee3e27969c..819a17921cb 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 50f43dbf31a..1f7ca453bb4 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -67,7 +67,6 @@ */ #include -#include #include #include diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index c0af6fb1fbb..f8c9bcdab68 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -60,7 +60,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h index 1105543b9d8..e7ec96c964a 100644 --- a/drivers/net/fs_enet/fs_enet.h +++ b/drivers/net/fs_enet/fs_enet.h @@ -4,7 +4,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 962580f2c4a..54d294ad6df 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -90,7 +90,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index c77ca6c0d04..220084e5334 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 68e3578e761..5a2d810ce57 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c index 5a74d3d3dbe..7263395d78b 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index b71fab6e34f..e92c17f6931 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -96,7 +96,6 @@ #undef HP100_MULTICAST_FILTER /* Need to be debugged... */ -#include #include #include #include diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 94239f67f3a..be191d80ef9 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -35,7 +35,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index d86d8f055a6..77eadf84cb2 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -58,7 +58,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c index ce5761816a6..d8c99f038fa 100644 --- a/drivers/net/mac8390.c +++ b/drivers/net/mac8390.c @@ -15,7 +15,6 @@ * and fixed access to Sonic Sys card which masquerades as a Farallon * by rayk@knightsmanor.org */ -#include #include #include #include diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h index bcfda5192da..f769f9b626e 100644 --- a/drivers/net/mv643xx_eth.h +++ b/drivers/net/mv643xx_eth.h @@ -1,7 +1,6 @@ #ifndef __MV643XX_ETH_H__ #define __MV643XX_ETH_H__ -#include #include #include #include diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 0745dd9d01f..8e41f4cea27 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -55,7 +55,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h index 308440bd0e1..91b8d4f4590 100644 --- a/drivers/net/sk98lin/h/skdrv1st.h +++ b/drivers/net/sk98lin/h/skdrv1st.h @@ -39,9 +39,6 @@ #ifndef __INC_SKDRV1ST_H #define __INC_SKDRV1ST_H -/* Check kernel version */ -#include - typedef struct s_AC SK_AC; /* Set card versions */ diff --git a/drivers/net/sk_mca.c b/drivers/net/sk_mca.c index 4c56b8d8221..e5d6d95960c 100644 --- a/drivers/net/sk_mca.c +++ b/drivers/net/sk_mca.c @@ -93,7 +93,6 @@ History: #include #include #include -#include #include #include #include diff --git a/drivers/net/sk_mca.h b/drivers/net/sk_mca.h index 7e7c9958274..d6fa1823dfa 100644 --- a/drivers/net/sk_mca.h +++ b/drivers/net/sk_mca.h @@ -1,5 +1,3 @@ -#include - #ifndef _SK_MCA_INCLUDE_ #define _SK_MCA_INCLUDE_ diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 38b2b0a3ce9..d167deda9a5 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -147,7 +147,6 @@ TODO: - fix forced speed/duplexing code (broken a long time ago, when #define DRV_RELDATE "October 3, 2005" #include -#include #include #include #include diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index a368d08e7d1..82c6b757d30 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -61,7 +61,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/wireless/hostap/hostap.c b/drivers/net/wireless/hostap/hostap.c index 6a96cd9f268..3d2ea61033b 100644 --- a/drivers/net/wireless/hostap/hostap.c +++ b/drivers/net/wireless/hostap/hostap.c @@ -13,7 +13,6 @@ */ #include -#include #include #include #include diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index 59fc1557239..abfae7fedeb 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -31,7 +31,6 @@ #include -#include #include #include diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c index da0c80fb941..2e85bdced2d 100644 --- a/drivers/net/wireless/hostap/hostap_pci.c +++ b/drivers/net/wireless/hostap/hostap_pci.c @@ -5,7 +5,6 @@ * Andy Warner */ #include -#include #include #include #include diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c index 78d67b408b2..94fe2449f09 100644 --- a/drivers/net/wireless/hostap/hostap_plx.c +++ b/drivers/net/wireless/hostap/hostap_plx.c @@ -8,7 +8,6 @@ #include -#include #include #include #include diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h index c9e99ce15d6..1f23650c077 100644 --- a/drivers/net/wireless/ipw2100.h +++ b/drivers/net/wireless/ipw2100.h @@ -37,7 +37,6 @@ #include #include #include -#include #include // new driver API #include diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 3db0c32afe8..589aef8ba4e 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -31,6 +31,7 @@ ******************************************************************************/ #include "ipw2200.h" +#include #define IPW2200_VERSION "1.0.0" #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index e9cf32bf3e3..0873b758f49 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -34,7 +34,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h index 7a17bb31fc8..f5d856db92a 100644 --- a/drivers/net/wireless/orinoco.h +++ b/drivers/net/wireless/orinoco.h @@ -12,7 +12,6 @@ #include #include #include -#include #include "hermes.h" diff --git a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c index adc7499136d..aaa958798f3 100644 --- a/drivers/net/wireless/prism54/isl_38xx.c +++ b/drivers/net/wireless/prism54/isl_38xx.c @@ -18,7 +18,6 @@ * */ -#include #include #include #include diff --git a/drivers/net/wireless/prism54/isl_38xx.h b/drivers/net/wireless/prism54/isl_38xx.h index e83e4912ab6..8af20980af8 100644 --- a/drivers/net/wireless/prism54/isl_38xx.h +++ b/drivers/net/wireless/prism54/isl_38xx.h @@ -20,7 +20,6 @@ #ifndef _ISL_38XX_H #define _ISL_38XX_H -#include #include #include diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 5c1a1adf1ff..135a156db25 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -20,7 +20,6 @@ * */ -#include #include #include #include diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index 78bdb359835..5ddf2959903 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c @@ -19,7 +19,6 @@ * */ -#include #include #include diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h index efbed439795..07053165e4c 100644 --- a/drivers/net/wireless/prism54/islpci_dev.h +++ b/drivers/net/wireless/prism54/islpci_dev.h @@ -23,7 +23,6 @@ #ifndef _ISLPCI_DEV_H #define _ISLPCI_DEV_H -#include #include #include #include diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index fc1eb356483..80ae081ab4b 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c @@ -17,7 +17,6 @@ * */ -#include #include #include diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c index dc040caab7d..b41d666fea3 100644 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/drivers/net/wireless/prism54/islpci_hotplug.c @@ -18,7 +18,6 @@ * */ -#include #include #include #include diff --git a/drivers/pcmcia/au1000_pb1x00.c b/drivers/pcmcia/au1000_pb1x00.c index d414a3bb50b..86c0808d6a0 100644 --- a/drivers/pcmcia/au1000_pb1x00.c +++ b/drivers/pcmcia/au1000_pb1x00.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include diff --git a/drivers/pcmcia/au1000_xxs1500.c b/drivers/pcmcia/au1000_xxs1500.c index f113b69d699..01a895bc9a4 100644 --- a/drivers/pcmcia/au1000_xxs1500.c +++ b/drivers/pcmcia/au1000_xxs1500.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c index 04c2ef778ec..4010f2bb85a 100644 --- a/drivers/s390/crypto/z90main.c +++ b/drivers/s390/crypto/z90main.c @@ -37,7 +37,6 @@ #include #include #include -#include #include "z90crypt.h" #include "z90common.h" diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index 1a1c3decea7..6b63d21612e 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -88,7 +88,6 @@ #include #include #include -#include #include "cu3088.h" #include "claw.h" diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h index 98bad773f24..4f81fc39ec5 100644 --- a/drivers/scsi/3w-xxxx.h +++ b/drivers/scsi/3w-xxxx.h @@ -54,7 +54,6 @@ #ifndef _3W_XXXX_H #define _3W_XXXX_H -#include #include /* AEN strings */ diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c index f7a1751e892..30a14ba77a6 100644 --- a/drivers/scsi/a2091.c +++ b/drivers/scsi/a2091.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h index 052c6619acc..bc44222d6cc 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.h +++ b/drivers/scsi/aic7xxx/aic79xx_osm.h @@ -49,7 +49,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index be9edbe26db..f2a95447142 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h @@ -66,7 +66,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/amiga7xx.c b/drivers/scsi/amiga7xx.c index 5f13546d639..dea8446f536 100644 --- a/drivers/scsi/amiga7xx.c +++ b/drivers/scsi/amiga7xx.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/bvme6000.c b/drivers/scsi/bvme6000.c index 29c7ed30c09..130f30f51a9 100644 --- a/drivers/scsi/bvme6000.c +++ b/drivers/scsi/bvme6000.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c index d12342fa819..ab22387c9df 100644 --- a/drivers/scsi/gvp11.c +++ b/drivers/scsi/gvp11.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c index 887a5c3ded2..8d97999db60 100644 --- a/drivers/scsi/ibmmca.c +++ b/drivers/scsi/ibmmca.c @@ -18,12 +18,6 @@ */ #include -#ifndef LINUX_VERSION_CODE -#include -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,45) -#error "This driver works only with kernel 2.5.45 or higher!" -#endif #include #include #include diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h index 505e967013d..adc6eabbf61 100644 --- a/drivers/scsi/ips.h +++ b/drivers/scsi/ips.h @@ -50,6 +50,7 @@ #ifndef _IPS_H_ #define _IPS_H_ +#include #include #include diff --git a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h index 69df1a9b935..8e547130e97 100644 --- a/drivers/scsi/megaraid/mega_common.h +++ b/drivers/scsi/megaraid/mega_common.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/megaraid/megaraid_mm.h b/drivers/scsi/megaraid/megaraid_mm.h index 7e36c46e7c4..eb8c390a0fa 100644 --- a/drivers/scsi/megaraid/megaraid_mm.h +++ b/drivers/scsi/megaraid/megaraid_mm.h @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 4245d05e628..801a63bea8a 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c index 2fb31ee6d9f..33380cee9b7 100644 --- a/drivers/scsi/mvme147.c +++ b/drivers/scsi/mvme147.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include diff --git a/drivers/scsi/mvme16x.c b/drivers/scsi/mvme16x.c index b2d8d8ea160..29ec699e0e4 100644 --- a/drivers/scsi/mvme16x.c +++ b/drivers/scsi/mvme16x.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include diff --git a/drivers/scsi/nsp32.h b/drivers/scsi/nsp32.h index 5664398fa0a..5addf9fb1e1 100644 --- a/drivers/scsi/nsp32.h +++ b/drivers/scsi/nsp32.h @@ -16,6 +16,7 @@ #ifndef _NSP32_H #define _NSP32_H +#include //#define NSP32_DEBUG 9 /* diff --git a/drivers/scsi/pci2000.h b/drivers/scsi/pci2000.h index c65afc96412..6c962d7dca4 100644 --- a/drivers/scsi/pci2000.h +++ b/drivers/scsi/pci2000.h @@ -26,9 +26,6 @@ #ifndef PSI_EIDE_SCSIOP #define PSI_EIDE_SCSIOP 1 -#ifndef LINUX_VERSION_CODE -#include -#endif #define LINUXVERSION(v,p,s) (((v)<<16) + ((p)<<8) + (s)) /************************************************/ diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index aadf051274f..b61fb1295b8 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -48,10 +48,6 @@ #include -#ifndef LINUX_VERSION_CODE -#include -#endif - #include "scsi_logging.h" #include "scsi_debug.h" diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 62e3f340cc5..72ec59456e6 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -68,10 +68,6 @@ static int sg_proc_init(void); static void sg_proc_cleanup(void); #endif -#ifndef LINUX_VERSION_CODE -#include -#endif /* LINUX_VERSION_CODE */ - #define SG_ALLOW_DIO_DEF 0 #define SG_ALLOW_DIO_CODE /* compile out by commenting this define */ diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c index 09fd203e4b8..f37147f8f7b 100644 --- a/drivers/scsi/sgiwd93.c +++ b/drivers/scsi/sgiwd93.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index 5754445fb36..fd63add6a57 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c @@ -77,7 +77,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/telephony/ixj.h b/drivers/telephony/ixj.h index 51e3f7f6597..fbea4541c23 100644 --- a/drivers/telephony/ixj.h +++ b/drivers/telephony/ixj.h @@ -40,7 +40,6 @@ *****************************************************************************/ #define IXJ_VERSION 3031 -#include #include #include diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 975ace3f5b1..90451908533 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -49,7 +49,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/usb/gadget/lh7a40x_udc.h b/drivers/usb/gadget/lh7a40x_udc.h index 1bb455c045a..9b2e6f7cbb8 100644 --- a/drivers/usb/gadget/lh7a40x_udc.h +++ b/drivers/usb/gadget/lh7a40x_udc.h @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index ee9cd7869d9..510d28a924d 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 06b6eba925b..9689efeb364 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c index a8267cf17db..0eaabeb37ac 100644 --- a/drivers/usb/host/hc_crisv10.c +++ b/drivers/usb/host/hc_crisv10.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include diff --git a/drivers/usb/media/pwc/pwc-if.c b/drivers/usb/media/pwc/pwc-if.c index b77e65c0365..5524fd70210 100644 --- a/drivers/usb/media/pwc/pwc-if.c +++ b/drivers/usb/media/pwc/pwc-if.c @@ -62,6 +62,7 @@ #include #include #include +#include #include #include "pwc.h" diff --git a/drivers/usb/media/pwc/pwc.h b/drivers/usb/media/pwc/pwc.h index 267869dab18..6dd76bb3dff 100644 --- a/drivers/usb/media/pwc/pwc.h +++ b/drivers/usb/media/pwc/pwc.h @@ -25,8 +25,6 @@ #ifndef PWC_H #define PWC_H -#include - #include #include #include diff --git a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c index f36c0b6c6e3..67612c81cb9 100644 --- a/drivers/usb/media/w9968cf.c +++ b/drivers/usb/media/w9968cf.c @@ -25,7 +25,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * ***************************************************************************/ -#include #include #include #include diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index c946c9a538a..41ef2b60675 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -37,7 +37,6 @@ */ #include -#include #include #include #include diff --git a/drivers/usb/misc/sisusbvga/sisusb.h b/drivers/usb/misc/sisusbvga/sisusb.h index 401ff21d788..1d7a77cc7c4 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.h +++ b/drivers/usb/misc/sisusbvga/sisusb.h @@ -37,6 +37,7 @@ #ifndef _SISUSB_H_ #define _SISUSB_H_ +#include #ifdef CONFIG_COMPAT #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,10) #include diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index 24584463553..be5c1a25ae2 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/drivers/usb/misc/sisusbvga/sisusb_con.c @@ -48,7 +48,6 @@ */ #include -#include #include #include #include diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.c b/drivers/usb/misc/sisusbvga/sisusb_init.c index f28bc240f9b..044fa4482f9 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_init.c +++ b/drivers/usb/misc/sisusbvga/sisusb_init.c @@ -37,7 +37,6 @@ */ #include -#include #include #include #include diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index acc81cb01d5..9d5015e9937 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -5,7 +5,6 @@ * */ -#include #include #include #include diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 470e6f0ee4d..68c690605aa 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -5,7 +5,6 @@ * */ -#include #include #include #include diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index 0799b999b31..427689e584d 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c @@ -122,7 +122,6 @@ #include #include #include -#include #include diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index ac94c2e5ff8..624c4bc96f0 100644 --- a/drivers/video/intelfb/intelfbhw.c +++ b/drivers/video/intelfb/intelfbhw.c @@ -34,7 +34,6 @@ #include #include #include -#include #include diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index bbc3cc63854..89c849da850 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h index fd528433de4..f6cd01352cc 100644 --- a/fs/adfs/adfs.h +++ b/fs/adfs/adfs.h @@ -12,7 +12,6 @@ #define ADFS_NDA_PUBLIC_READ (1 << 5) #define ADFS_NDA_PUBLIC_WRITE (1 << 6) -#include #include "dir_f.h" struct buffer_head; diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h index aae019aadf8..cc5dcd52e23 100644 --- a/fs/hfs/hfs_fs.h +++ b/fs/hfs/hfs_fs.h @@ -9,7 +9,6 @@ #ifndef _LINUX_HFS_FS_H #define _LINUX_HFS_FS_H -#include #include #include #include diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index 3f680c5675b..d499393a8ae 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c @@ -12,7 +12,6 @@ */ #include -#include #include #include "hfs_fs.h" diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c index b85abc6e6f8..930cd9212de 100644 --- a/fs/hfsplus/bnode.c +++ b/fs/hfsplus/bnode.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "hfsplus_fs.h" #include "hfsplus_raw.h" diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index 7bda76667a4..50c8f44b6c6 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "hfsplus_fs.h" #include "hfsplus_raw.h" diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c index e7235ca79a9..e3ff56a0301 100644 --- a/fs/hfsplus/extents.c +++ b/fs/hfsplus/extents.c @@ -11,7 +11,6 @@ #include #include #include -#include #include "hfsplus_fs.h" #include "hfsplus_raw.h" diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 2bc0cdd30e5..c60e5635498 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -11,7 +11,6 @@ #define _LINUX_HFSPLUS_FS_H #include -#include #include #include "hfsplus_raw.h" diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index f205773ddfb..fc98583cf04 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include "hfsplus_fs.h" diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 452fc1fdbd3..0ce1c455ae5 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c index 0c51d6338b0..95455e83923 100644 --- a/fs/hfsplus/wrapper.c +++ b/fs/hfsplus/wrapper.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include "hfsplus_fs.h" diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index a33fb1d9137..4684eb7d48c 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -8,7 +8,6 @@ #include #include -#include #include #include #include diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 44fed10af0d..d8e21ba0ccc 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h @@ -72,7 +72,6 @@ #include #include #include -#include #include #include diff --git a/fs/xfs/xfs.h b/fs/xfs/xfs.h index 99b50d2bda9..1a48dbb902a 100644 --- a/fs/xfs/xfs.h +++ b/fs/xfs/xfs.h @@ -17,12 +17,5 @@ */ #ifndef __XFS_H__ #define __XFS_H__ - -#include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) #include -#else -#include -#endif - #endif /* __XFS_H__ */ diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h index 5a5c7a63e80..864bf695568 100644 --- a/fs/xfs/xfs_dmapi.h +++ b/fs/xfs/xfs_dmapi.h @@ -18,6 +18,7 @@ #ifndef __XFS_DMAPI_H__ #define __XFS_DMAPI_H__ +#include /* Values used to define the on-disk version of dm_attrname_t. All * on-disk attribute names start with the 8-byte string "SGI_DMI_". * diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h index bef23bbf869..783c476b867 100644 --- a/include/linux/fs_enet_pd.h +++ b/include/linux/fs_enet_pd.h @@ -16,7 +16,6 @@ #ifndef FS_ENET_PD_H #define FS_ENET_PD_H -#include #include #define FS_ENET_NAME "fs_enet" diff --git a/include/linux/if_wanpipe_common.h b/include/linux/if_wanpipe_common.h index f25fec8ee2c..6e5461d69fd 100644 --- a/include/linux/if_wanpipe_common.h +++ b/include/linux/if_wanpipe_common.h @@ -17,8 +17,6 @@ #ifndef _WANPIPE_SOCK_DRIVER_COMMON_H #define _WANPIPE_SOCK_DRIVER_COMMON_H -#include - typedef struct { struct net_device *slave; atomic_t packet_sent; diff --git a/include/linux/istallion.h b/include/linux/istallion.h index 5f4ee646c11..1f996621bc9 100644 --- a/include/linux/istallion.h +++ b/include/linux/istallion.h @@ -21,8 +21,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include - /*****************************************************************************/ #ifndef _ISTALLION_H #define _ISTALLION_H diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index 39f1430bd6d..3c9ea4b7add 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h @@ -8,7 +8,6 @@ #define __MTD_CFI_H__ #include -#include #include #include #include diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index e95d0463a3e..b6f2fdae65c 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -14,7 +14,6 @@ #endif #include -#include #include #include #include diff --git a/include/linux/phonedev.h b/include/linux/phonedev.h index d54049eed0c..a0e31adf3ab 100644 --- a/include/linux/phonedev.h +++ b/include/linux/phonedev.h @@ -2,7 +2,6 @@ #define __LINUX_PHONEDEV_H #include -#include #ifdef __KERNEL__ diff --git a/include/linux/stallion.h b/include/linux/stallion.h index e89b77b6505..13a37f137ea 100644 --- a/include/linux/stallion.h +++ b/include/linux/stallion.h @@ -21,8 +21,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include - /*****************************************************************************/ #ifndef _STALLION_H #define _STALLION_H diff --git a/sound/oss/msnd.c b/sound/oss/msnd.c index 4f1ff1bccdc..a7ad2b0a2ac 100644 --- a/sound/oss/msnd.c +++ b/sound/oss/msnd.c @@ -24,7 +24,6 @@ * ********************************************************************/ -#include #include #include #include diff --git a/sound/oss/os.h b/sound/oss/os.h index 80dce329cc3..0490562c7f7 100644 --- a/sound/oss/os.h +++ b/sound/oss/os.h @@ -5,10 +5,8 @@ #undef DO_TIMINGS #include -#include #ifdef __KERNEL__ -#include #include #include #include diff --git a/sound/oss/rme96xx.c b/sound/oss/rme96xx.c index 7609c68a89f..318dc51009f 100644 --- a/sound/oss/rme96xx.c +++ b/sound/oss/rme96xx.c @@ -44,7 +44,6 @@ TODO: #define RMEVERSION "0.8" #endif -#include #include #include #include diff --git a/sound/oss/sh_dac_audio.c b/sound/oss/sh_dac_audio.c index c09cdeedc19..8a9917c919c 100644 --- a/sound/oss/sh_dac_audio.c +++ b/sound/oss/sh_dac_audio.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include diff --git a/sound/ppc/pmac.h b/sound/ppc/pmac.h index ae3bb6c6edf..bfff788e984 100644 --- a/sound/ppc/pmac.h +++ b/sound/ppc/pmac.h @@ -22,7 +22,6 @@ #ifndef __PMAC_H #define __PMAC_H -#include #include #include #include "awacs.h" -- cgit v1.2.3 From 33096b1e735b0a36c289ced394da7a25e94bc815 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 8 Nov 2005 21:34:56 -0800 Subject: [PATCH] hpfs: remove spurious mtime update Remove mtime update in hpfs_file_write, it's done in generic_file_write already. Signed-off-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/hpfs/file.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index ab144dabd87..7c995ac4081 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c @@ -114,11 +114,8 @@ static ssize_t hpfs_file_write(struct file *file, const char __user *buf, ssize_t retval; retval = generic_file_write(file, buf, count, ppos); - if (retval > 0) { - struct inode *inode = file->f_dentry->d_inode; - inode->i_mtime = CURRENT_TIME_SEC; - hpfs_i(inode)->i_dirty = 1; - } + if (retval > 0) + hpfs_i(file->f_dentry->d_inode)->i_dirty = 1; return retval; } -- cgit v1.2.3 From 41a34a4fe1d4478b1c8b6b6ea634ab1adb156885 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 8 Nov 2005 21:34:57 -0800 Subject: [PATCH] fat: respect silent mount flag Pass down the silent flag to parse_options(). Without this fat gives warnings when mounting some non-fat rootfs with options. Signed-off-by: Christoph Hellwig Acked-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fat/inode.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/fs/fat/inode.c b/fs/fat/inode.c index e2effe2dc9b..a0f9b9fe130 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -846,7 +846,7 @@ static match_table_t vfat_tokens = { {Opt_err, NULL} }; -static int parse_options(char *options, int is_vfat, int *debug, +static int parse_options(char *options, int is_vfat, int silent, int *debug, struct fat_mount_options *opts) { char *p; @@ -1008,8 +1008,11 @@ static int parse_options(char *options, int is_vfat, int *debug, break; /* unknown option */ default: - printk(KERN_ERR "FAT: Unrecognized mount option \"%s\" " - "or missing value\n", p); + if (!silent) { + printk(KERN_ERR + "FAT: Unrecognized mount option \"%s\" " + "or missing value\n", p); + } return -EINVAL; } } @@ -1091,7 +1094,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, sb->s_export_op = &fat_export_ops; sbi->dir_ops = fs_dir_inode_ops; - error = parse_options(data, isvfat, &debug, &sbi->options); + error = parse_options(data, isvfat, silent, &debug, &sbi->options); if (error) goto out_fail; -- cgit v1.2.3 From 0ad74ffa90fb20b4132ae6e67e473f24621c6af2 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 8 Nov 2005 21:34:58 -0800 Subject: [PATCH] Fix return value in reiserfs allocator Make reiserfs correctly return EDQUOT when the allocation failed due to quotas (so far we just returned ENOSPC). Signed-off-by: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/file.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index c20babd6216..7892a865b58 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c @@ -251,12 +251,12 @@ static int reiserfs_allocate_blocks_for_region(struct reiserfs_transaction_handl blocks_to_allocate, blocks_to_allocate); if (res != CARRY_ON) { - res = -ENOSPC; + res = res == QUOTA_EXCEEDED ? -EDQUOT : -ENOSPC; pathrelse(&path); goto error_exit; } } else { - res = -ENOSPC; + res = res == QUOTA_EXCEEDED ? -EDQUOT : -ENOSPC; pathrelse(&path); goto error_exit; } -- cgit v1.2.3 From 2860b733f114e088b56c20da6145902c16b79a44 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 8 Nov 2005 21:34:59 -0800 Subject: [PATCH] remove CONFIG_EXT{2,3}_CHECK The CONFIG_EXT{2,3}_CHECK options where were never available, and all they did was to implement a subset of e2fsck in the kernel. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/filesystems/ext2.txt | 2 -- fs/ext2/balloc.c | 73 -------------------------------------- fs/ext2/ialloc.c | 40 --------------------- fs/ext2/super.c | 16 +-------- fs/ext3/balloc.c | 73 -------------------------------------- fs/ext3/ialloc.c | 41 --------------------- fs/ext3/super.c | 17 +-------- 7 files changed, 2 insertions(+), 260 deletions(-) diff --git a/Documentation/filesystems/ext2.txt b/Documentation/filesystems/ext2.txt index d16334ec48b..a8edb376b04 100644 --- a/Documentation/filesystems/ext2.txt +++ b/Documentation/filesystems/ext2.txt @@ -17,8 +17,6 @@ set using tune2fs(8). Kernel-determined defaults are indicated by (*). bsddf (*) Makes `df' act like BSD. minixdf Makes `df' act like Minix. -check Check block and inode bitmaps at mount time - (requires CONFIG_EXT2_CHECK). check=none, nocheck (*) Don't do extra checking of bitmaps on mount (check=normal and check=strict options removed) diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c index 6591abef64d..bb690806649 100644 --- a/fs/ext2/balloc.c +++ b/fs/ext2/balloc.c @@ -624,76 +624,3 @@ unsigned long ext2_bg_num_gdb(struct super_block *sb, int group) return EXT2_SB(sb)->s_gdb_count; } -#ifdef CONFIG_EXT2_CHECK -/* Called at mount-time, super-block is locked */ -void ext2_check_blocks_bitmap (struct super_block * sb) -{ - struct buffer_head *bitmap_bh = NULL; - struct ext2_super_block * es; - unsigned long desc_count, bitmap_count, x, j; - unsigned long desc_blocks; - struct ext2_group_desc * desc; - int i; - - es = EXT2_SB(sb)->s_es; - desc_count = 0; - bitmap_count = 0; - desc = NULL; - for (i = 0; i < EXT2_SB(sb)->s_groups_count; i++) { - desc = ext2_get_group_desc (sb, i, NULL); - if (!desc) - continue; - desc_count += le16_to_cpu(desc->bg_free_blocks_count); - brelse(bitmap_bh); - bitmap_bh = read_block_bitmap(sb, i); - if (!bitmap_bh) - continue; - - if (ext2_bg_has_super(sb, i) && - !ext2_test_bit(0, bitmap_bh->b_data)) - ext2_error(sb, __FUNCTION__, - "Superblock in group %d is marked free", i); - - desc_blocks = ext2_bg_num_gdb(sb, i); - for (j = 0; j < desc_blocks; j++) - if (!ext2_test_bit(j + 1, bitmap_bh->b_data)) - ext2_error(sb, __FUNCTION__, - "Descriptor block #%ld in group " - "%d is marked free", j, i); - - if (!block_in_use(le32_to_cpu(desc->bg_block_bitmap), - sb, bitmap_bh->b_data)) - ext2_error(sb, "ext2_check_blocks_bitmap", - "Block bitmap for group %d is marked free", - i); - - if (!block_in_use(le32_to_cpu(desc->bg_inode_bitmap), - sb, bitmap_bh->b_data)) - ext2_error(sb, "ext2_check_blocks_bitmap", - "Inode bitmap for group %d is marked free", - i); - - for (j = 0; j < EXT2_SB(sb)->s_itb_per_group; j++) - if (!block_in_use(le32_to_cpu(desc->bg_inode_table) + j, - sb, bitmap_bh->b_data)) - ext2_error (sb, "ext2_check_blocks_bitmap", - "Block #%ld of the inode table in " - "group %d is marked free", j, i); - - x = ext2_count_free(bitmap_bh, sb->s_blocksize); - if (le16_to_cpu(desc->bg_free_blocks_count) != x) - ext2_error (sb, "ext2_check_blocks_bitmap", - "Wrong free blocks count for group %d, " - "stored = %d, counted = %lu", i, - le16_to_cpu(desc->bg_free_blocks_count), x); - bitmap_count += x; - } - if (le32_to_cpu(es->s_free_blocks_count) != bitmap_count) - ext2_error (sb, "ext2_check_blocks_bitmap", - "Wrong free blocks count in super block, " - "stored = %lu, counted = %lu", - (unsigned long)le32_to_cpu(es->s_free_blocks_count), - bitmap_count); - brelse(bitmap_bh); -} -#endif diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index e2d6208633a..74714af4ae6 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c @@ -700,43 +700,3 @@ unsigned long ext2_count_dirs (struct super_block * sb) return count; } -#ifdef CONFIG_EXT2_CHECK -/* Called at mount-time, super-block is locked */ -void ext2_check_inodes_bitmap (struct super_block * sb) -{ - struct ext2_super_block * es = EXT2_SB(sb)->s_es; - unsigned long desc_count = 0, bitmap_count = 0; - struct buffer_head *bitmap_bh = NULL; - int i; - - for (i = 0; i < EXT2_SB(sb)->s_groups_count; i++) { - struct ext2_group_desc *desc; - unsigned x; - - desc = ext2_get_group_desc(sb, i, NULL); - if (!desc) - continue; - desc_count += le16_to_cpu(desc->bg_free_inodes_count); - brelse(bitmap_bh); - bitmap_bh = read_inode_bitmap(sb, i); - if (!bitmap_bh) - continue; - - x = ext2_count_free(bitmap_bh, EXT2_INODES_PER_GROUP(sb) / 8); - if (le16_to_cpu(desc->bg_free_inodes_count) != x) - ext2_error (sb, "ext2_check_inodes_bitmap", - "Wrong free inodes count in group %d, " - "stored = %d, counted = %lu", i, - le16_to_cpu(desc->bg_free_inodes_count), x); - bitmap_count += x; - } - brelse(bitmap_bh); - if (percpu_counter_read(&EXT2_SB(sb)->s_freeinodes_counter) != - bitmap_count) - ext2_error(sb, "ext2_check_inodes_bitmap", - "Wrong free inodes count in super block, " - "stored = %lu, counted = %lu", - (unsigned long)le32_to_cpu(es->s_free_inodes_count), - bitmap_count); -} -#endif diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 3c0c7c6a5b4..e4ed4b31a43 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -281,7 +281,7 @@ static unsigned long get_sb_block(void **data) enum { Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid, Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, - Opt_err_ro, Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug, + Opt_err_ro, Opt_nouid32, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov, Opt_nobh, Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, Opt_xip, Opt_ignore, Opt_err, Opt_quota, Opt_usrquota, Opt_grpquota @@ -303,7 +303,6 @@ static match_table_t tokens = { {Opt_nouid32, "nouid32"}, {Opt_nocheck, "check=none"}, {Opt_nocheck, "nocheck"}, - {Opt_check, "check"}, {Opt_debug, "debug"}, {Opt_oldalloc, "oldalloc"}, {Opt_orlov, "orlov"}, @@ -376,13 +375,6 @@ static int parse_options (char * options, case Opt_nouid32: set_opt (sbi->s_mount_opt, NO_UID32); break; - case Opt_check: -#ifdef CONFIG_EXT2_CHECK - set_opt (sbi->s_mount_opt, CHECK); -#else - printk("EXT2 Check option not supported\n"); -#endif - break; case Opt_nocheck: clear_opt (sbi->s_mount_opt, CHECK); break; @@ -503,12 +495,6 @@ static int ext2_setup_super (struct super_block * sb, EXT2_BLOCKS_PER_GROUP(sb), EXT2_INODES_PER_GROUP(sb), sbi->s_mount_opt); -#ifdef CONFIG_EXT2_CHECK - if (test_opt (sb, CHECK)) { - ext2_check_blocks_bitmap (sb); - ext2_check_inodes_bitmap (sb); - } -#endif return res; } diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 7992d21e0e0..ae1148c24c5 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -1517,76 +1517,3 @@ unsigned long ext3_bg_num_gdb(struct super_block *sb, int group) return EXT3_SB(sb)->s_gdb_count; } -#ifdef CONFIG_EXT3_CHECK -/* Called at mount-time, super-block is locked */ -void ext3_check_blocks_bitmap (struct super_block * sb) -{ - struct ext3_super_block *es; - unsigned long desc_count, bitmap_count, x, j; - unsigned long desc_blocks; - struct buffer_head *bitmap_bh = NULL; - struct ext3_group_desc *gdp; - int i; - - es = EXT3_SB(sb)->s_es; - desc_count = 0; - bitmap_count = 0; - gdp = NULL; - for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) { - gdp = ext3_get_group_desc (sb, i, NULL); - if (!gdp) - continue; - desc_count += le16_to_cpu(gdp->bg_free_blocks_count); - brelse(bitmap_bh); - bitmap_bh = read_block_bitmap(sb, i); - if (bitmap_bh == NULL) - continue; - - if (ext3_bg_has_super(sb, i) && - !ext3_test_bit(0, bitmap_bh->b_data)) - ext3_error(sb, __FUNCTION__, - "Superblock in group %d is marked free", i); - - desc_blocks = ext3_bg_num_gdb(sb, i); - for (j = 0; j < desc_blocks; j++) - if (!ext3_test_bit(j + 1, bitmap_bh->b_data)) - ext3_error(sb, __FUNCTION__, - "Descriptor block #%ld in group " - "%d is marked free", j, i); - - if (!block_in_use (le32_to_cpu(gdp->bg_block_bitmap), - sb, bitmap_bh->b_data)) - ext3_error (sb, "ext3_check_blocks_bitmap", - "Block bitmap for group %d is marked free", - i); - - if (!block_in_use (le32_to_cpu(gdp->bg_inode_bitmap), - sb, bitmap_bh->b_data)) - ext3_error (sb, "ext3_check_blocks_bitmap", - "Inode bitmap for group %d is marked free", - i); - - for (j = 0; j < EXT3_SB(sb)->s_itb_per_group; j++) - if (!block_in_use (le32_to_cpu(gdp->bg_inode_table) + j, - sb, bitmap_bh->b_data)) - ext3_error (sb, "ext3_check_blocks_bitmap", - "Block #%d of the inode table in " - "group %d is marked free", j, i); - - x = ext3_count_free(bitmap_bh, sb->s_blocksize); - if (le16_to_cpu(gdp->bg_free_blocks_count) != x) - ext3_error (sb, "ext3_check_blocks_bitmap", - "Wrong free blocks count for group %d, " - "stored = %d, counted = %lu", i, - le16_to_cpu(gdp->bg_free_blocks_count), x); - bitmap_count += x; - } - brelse(bitmap_bh); - if (le32_to_cpu(es->s_free_blocks_count) != bitmap_count) - ext3_error (sb, "ext3_check_blocks_bitmap", - "Wrong free blocks count in super block, " - "stored = %lu, counted = %lu", - (unsigned long)le32_to_cpu(es->s_free_blocks_count), - bitmap_count); -} -#endif diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index df3f517c54a..9e4a2437621 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c @@ -756,44 +756,3 @@ unsigned long ext3_count_dirs (struct super_block * sb) return count; } -#ifdef CONFIG_EXT3_CHECK -/* Called at mount-time, super-block is locked */ -void ext3_check_inodes_bitmap (struct super_block * sb) -{ - struct ext3_super_block * es; - unsigned long desc_count, bitmap_count, x; - struct buffer_head *bitmap_bh = NULL; - struct ext3_group_desc * gdp; - int i; - - es = EXT3_SB(sb)->s_es; - desc_count = 0; - bitmap_count = 0; - gdp = NULL; - for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) { - gdp = ext3_get_group_desc (sb, i, NULL); - if (!gdp) - continue; - desc_count += le16_to_cpu(gdp->bg_free_inodes_count); - brelse(bitmap_bh); - bitmap_bh = read_inode_bitmap(sb, i); - if (!bitmap_bh) - continue; - - x = ext3_count_free(bitmap_bh, EXT3_INODES_PER_GROUP(sb) / 8); - if (le16_to_cpu(gdp->bg_free_inodes_count) != x) - ext3_error (sb, "ext3_check_inodes_bitmap", - "Wrong free inodes count in group %d, " - "stored = %d, counted = %lu", i, - le16_to_cpu(gdp->bg_free_inodes_count), x); - bitmap_count += x; - } - brelse(bitmap_bh); - if (le32_to_cpu(es->s_free_inodes_count) != bitmap_count) - ext3_error (sb, "ext3_check_inodes_bitmap", - "Wrong free inodes count in super block, " - "stored = %lu, counted = %lu", - (unsigned long)le32_to_cpu(es->s_free_inodes_count), - bitmap_count); -} -#endif diff --git a/fs/ext3/super.c b/fs/ext3/super.c index f594989ccb7..4e6730622d9 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -625,7 +625,7 @@ static struct export_operations ext3_export_ops = { enum { Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid, Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro, - Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov, + Opt_nouid32, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov, Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_commit, Opt_journal_update, Opt_journal_inum, @@ -652,7 +652,6 @@ static match_table_t tokens = { {Opt_nouid32, "nouid32"}, {Opt_nocheck, "nocheck"}, {Opt_nocheck, "check=none"}, - {Opt_check, "check"}, {Opt_debug, "debug"}, {Opt_oldalloc, "oldalloc"}, {Opt_orlov, "orlov"}, @@ -773,14 +772,6 @@ static int parse_options (char * options, struct super_block *sb, case Opt_nouid32: set_opt (sbi->s_mount_opt, NO_UID32); break; - case Opt_check: -#ifdef CONFIG_EXT3_CHECK - set_opt (sbi->s_mount_opt, CHECK); -#else - printk(KERN_ERR - "EXT3 Check option not supported\n"); -#endif - break; case Opt_nocheck: clear_opt (sbi->s_mount_opt, CHECK); break; @@ -1115,12 +1106,6 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es, } else { printk("internal journal\n"); } -#ifdef CONFIG_EXT3_CHECK - if (test_opt (sb, CHECK)) { - ext3_check_blocks_bitmap (sb); - ext3_check_inodes_bitmap (sb); - } -#endif return res; } -- cgit v1.2.3 From 55e64b3003f03355d8e950af58d456b6314a5a62 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 8 Nov 2005 21:34:59 -0800 Subject: [PATCH] ext2: remove the ancient CHANGES file This patch removes an ancient changelog file. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext2/CHANGES | 157 -------------------------------------------------------- 1 file changed, 157 deletions(-) delete mode 100644 fs/ext2/CHANGES diff --git a/fs/ext2/CHANGES b/fs/ext2/CHANGES deleted file mode 100644 index aa5aaf0e591..00000000000 --- a/fs/ext2/CHANGES +++ /dev/null @@ -1,157 +0,0 @@ -Changes from version 0.5a to version 0.5b -========================================= - - Now that we have sysctl(), the immutable flag cannot be changed when - the system is running at security level > 0. - - Some cleanups in the code. - - More consistency checks on directories. - - The ext2.diff patch from Tom May has been - integrated. This patch replaces expensive "/" and "%" with - cheap ">>" and "&" where possible. - -Changes from version 0.5 to version 0.5a -======================================== - - Zero the partial block following the end of the file when a file - is truncated. - - Dates updated in the copyright. - - More checks when the filesystem is mounted: the count of blocks, - fragments, and inodes per group is checked against the block size. - - The buffers used by the error routines are now static variables, to - avoid using space on the kernel stack, as requested by Linus. - - Some cleanups in the error messages (some versions of syslog contain - a bug which truncates an error message if it contains '\n'). - - Check that no data can be written to a file past the 2GB limit. - - The famous readdir() bug has been fixed by Stephen Tweedie. - - Added a revision level in the superblock. - - Full support for O_SYNC flag of the open system call. - - New mount options: `resuid=#uid' and `resgid=#gid'. `resuid' causes - ext2fs to consider user #uid like root for the reserved blocks. - `resgid' acts the same way with group #gid. New fields in the - superblock contain default values for resuid and resgid and can - be modified by tune2fs. - Idea comes from Rene Cougnenc . - - New mount options: `bsddf' and `minixdf'. `bsddf' causes ext2fs - to remove the blocks used for FS structures from the total block - count in statfs. With `minixdf', ext2fs mimics Minix behavior - in statfs (i.e. it returns the total number of blocks on the - partition). This is intended to make bde happy :-) - - New file attributes: - - Immutable files cannot be modified. Data cannot be written to - these files. They cannot be removed, renamed and new links cannot - be created. Even root cannot modify the files. He has to remove - the immutable attribute first. - - Append-only files: can only be written in append-mode when writing. - They cannot be removed, renamed and new links cannot be created. - Note: files may only be added to an append-only directory. - - No-dump files: the attribute is not used by the kernel. My port - of dump uses it to avoid backing up files which are not important. - - New check in ext2_check_dir_entry: the inode number is checked. - - Support for big file systems: the copy of the FS descriptor is now - dynamically allocated (previous versions used a fixed size array). - This allows to mount 2GB+ FS. - - Reorganization of the ext2_inode structure to allow other operating - systems to create specific fields if they use ext2fs as their native - file system. Currently, ext2fs is only implemented in Linux but - will soon be part of Gnu Hurd and of Masix. - -Changes from version 0.4b to version 0.5 -======================================== - - New superblock fields: s_lastcheck and s_checkinterval added - by Uwe Ohse to implement timedependent checks - of the file system - - Real random numbers for secure rm added by Pierre del Perugia - - - The mount warnings related to the state of a fs are not printed - if the fs is mounted read-only, idea by Nick Holloway - - -Changes from version 0.4a to version 0.4b -========================================= - - Copyrights changed to include the name of my laboratory. - - Clean up of balloc.c and ialloc.c. - - More consistency checks. - - Block preallocation added by Stephen Tweedie. - - Direct reads of directories disallowed. - - Readahead implemented in readdir by Stephen Tweedie. - - Bugs in block and inodes allocation fixed. - - Readahead implemented in ext2_find_entry by Chip Salzenberg. - - New mount options: - `check=none|normal|strict' - `debug' - `errors=continue|remount-ro|panic' - `grpid', `bsdgroups' - `nocheck' - `nogrpid', `sysvgroups' - - truncate() now tries to deallocate contiguous blocks in a single call - to ext2_free_blocks(). - - lots of cosmetic changes. - -Changes from version 0.4 to version 0.4a -======================================== - - the `sync' option support is now complete. Version 0.4 was not - supporting it when truncating a file. I have tested the synchronous - writes and they work but they make the system very slow :-( I have - to work again on this to make it faster. - - when detecting an error on a mounted filesystem, version 0.4 used - to try to write a flag in the super block even if the filesystem had - been mounted read-only. This is fixed. - - the `sb=#' option now causes the kernel code to use the filesystem - descriptors located at block #+1. Version 0.4 used the superblock - backup located at block # but used the main copy of the descriptors. - - a new file attribute `S' is supported. This attribute causes - synchronous writes but is applied to a file not to the entire file - system (thanks to Michael Kraehe for - suggesting it). - - the directory cache is inhibited by default. The cache management - code seems to be buggy and I have to look at it carefully before - using it again. - - deleting a file with the `s' attribute (secure deletion) causes its - blocks to be overwritten with random values not with zeros (thanks to - Michael A. Griffith for suggesting it). - - lots of cosmetic changes have been made. - -Changes from version 0.3 to version 0.4 -======================================= - - Three new mount options are supported: `check', `sync' and `sb=#'. - `check' tells the kernel code to make more consistency checks - when the file system is mounted. Currently, the kernel code checks - that the blocks and inodes bitmaps are consistent with the free - blocks and inodes counts. More checks will be added in future - releases. - `sync' tells the kernel code to use synchronous writes when updating - an inode, a bitmap, a directory entry or an indirect block. This - can make the file system much slower but can be a big win for files - recovery in case of a crash (and we can now say to the BSD folks - that Linux also supports synchronous updates :-). - `sb=#' tells the kernel code to use an alternate super block instead - of its master copy. `#' is the number of the block (counted in - 1024 bytes blocks) which contains the alternate super block. - An ext2 file system typically contains backups of the super block - at blocks 8193, 16385, and so on. - - I have change the meaning of the valid flag used by e2fsck. it - now contains the state of the file system. If the kernel code - detects an inconsistency while the file system is mounted, it flags - it as erroneous and e2fsck will detect that on next run. - - The super block now contains a mount counter. This counter is - incremented each time the file system is mounted read/write. When - this counter becomes bigger than a maximal mount counts (also stored - in the super block), e2fsck checks the file system, even if it had - been unmounted cleanly, and resets this counter to 0. - - File attributes are now supported. One can associate a set of - attributes to a file. Three attributes are defined: - `c': the file is marked for automatic compression, - `s': the file is marked for secure deletion: when the file is - deleted, its blocks are zeroed and written back to the disk, - `u': the file is marked for undeletion: when the file is deleted, - its contents are saved to allow a future undeletion. - Currently, only the `s' attribute is implemented in the kernel - code. Support for the other attributes will be added in a future - release. - - a few bugs related to times updates have been fixed by Bruce - Evans and me. - - a bug related to the links count of deleted inodes has been fixed. - Previous versions used to keep the links count set to 1 when a file - was deleted. The new version now sets links_count to 0 when deleting - the last link. - - a race condition when deallocating an inode has been fixed by - Stephen Tweedie. - -- cgit v1.2.3 From e4a53cbabc81f04e24a5570b4aa6a6384bdbfc67 Mon Sep 17 00:00:00 2001 From: "Gabriel A. Devenyi" Date: Tue, 8 Nov 2005 21:35:00 -0800 Subject: [PATCH] drivers/block/pktcdvd.c: remove write-only variable in pkt_iosched_process_queue() Found this on Coverty's linux bug database (http://linuxbugsdb.coverity.com). The function pkt_iosched_process_queue makes a call to bdev_get_queue and stores the result but never uses it, so it looks like it can be safely removed. Signed-off-by: Gabriel A. Devenyi Signed-off-by: Adrian Bunk Acked-by: Peter Osterlund Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/pktcdvd.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index a280e679b1c..59e5982a5db 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -511,14 +511,11 @@ static void pkt_queue_bio(struct pktcdvd_device *pd, struct bio *bio) */ static void pkt_iosched_process_queue(struct pktcdvd_device *pd) { - request_queue_t *q; if (atomic_read(&pd->iosched.attention) == 0) return; atomic_set(&pd->iosched.attention, 0); - q = bdev_get_queue(pd->bdev); - for (;;) { struct bio *bio; int reads_queued, writes_queued; -- cgit v1.2.3 From e4543eddfd3bf3e0d625841377fa695a519edfd4 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 8 Nov 2005 21:35:04 -0800 Subject: [PATCH] add a vfs_permission helper Most permission() calls have a struct nameidata * available. This helper takes that as an argument and thus makes sure we pass it down for lookup intents and prepares for per-mount read-only support where we need a struct vfsmount for checking whether a file is writeable. Signed-off-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/exec.c | 4 ++-- fs/inotify.c | 2 +- fs/namei.c | 23 +++++++++++++++++++---- fs/namespace.c | 2 +- fs/open.c | 12 ++++++------ include/linux/fs.h | 1 + net/unix/af_unix.c | 2 +- 7 files changed, 31 insertions(+), 15 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 5a4e3acc2e9..7bbb781b9ac 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -135,7 +135,7 @@ asmlinkage long sys_uselib(const char __user * library) if (!S_ISREG(nd.dentry->d_inode->i_mode)) goto exit; - error = permission(nd.dentry->d_inode, MAY_READ | MAY_EXEC, &nd); + error = vfs_permission(&nd, MAY_READ | MAY_EXEC); if (error) goto exit; @@ -495,7 +495,7 @@ struct file *open_exec(const char *name) file = ERR_PTR(-EACCES); if (!(nd.mnt->mnt_flags & MNT_NOEXEC) && S_ISREG(inode->i_mode)) { - int err = permission(inode, MAY_EXEC, &nd); + int err = vfs_permission(&nd, MAY_EXEC); if (!err && !(inode->i_mode & 0111)) err = -EACCES; file = ERR_PTR(err); diff --git a/fs/inotify.c b/fs/inotify.c index 9fbaebfdf40..bf7ce1d2412 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -372,7 +372,7 @@ static int find_inode(const char __user *dirname, struct nameidata *nd) if (error) return error; /* you can only watch an inode if you have read permissions on it */ - error = permission(nd->dentry->d_inode, MAY_READ, NULL); + error = vfs_permission(nd, MAY_READ); if (error) path_release(nd); return error; diff --git a/fs/namei.c b/fs/namei.c index b3f8a1966c9..25e4ab4ce8b 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -256,6 +256,21 @@ int permission(struct inode *inode, int mask, struct nameidata *nd) return security_inode_permission(inode, mask, nd); } +/** + * vfs_permission - check for access rights to a given path + * @nd: lookup result that describes the path + * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) + * + * Used to check for read/write/execute permissions on a path. + * We use "fsuid" for this, letting us set arbitrary permissions + * for filesystem access without changing the "normal" uids which + * are used for other things. + */ +int vfs_permission(struct nameidata *nd, int mask) +{ + return permission(nd->dentry->d_inode, mask, nd); +} + /* * get_write_access() gets write permission for a file. * put_write_access() releases this write permission. @@ -765,9 +780,8 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) nd->flags |= LOOKUP_CONTINUE; err = exec_permission_lite(inode, nd); - if (err == -EAGAIN) { - err = permission(inode, MAY_EXEC, nd); - } + if (err == -EAGAIN) + err = vfs_permission(nd, MAY_EXEC); if (err) break; @@ -1407,7 +1421,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE)) return -EISDIR; - error = permission(inode, acc_mode, nd); + error = vfs_permission(nd, acc_mode); if (error) return error; @@ -2536,6 +2550,7 @@ EXPORT_SYMBOL(path_lookup); EXPORT_SYMBOL(path_release); EXPORT_SYMBOL(path_walk); EXPORT_SYMBOL(permission); +EXPORT_SYMBOL(vfs_permission); EXPORT_SYMBOL(unlock_rename); EXPORT_SYMBOL(vfs_create); EXPORT_SYMBOL(vfs_follow_link); diff --git a/fs/namespace.c b/fs/namespace.c index caa9187f67e..2019899f2ab 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -637,7 +637,7 @@ static int mount_is_safe(struct nameidata *nd) if (current->uid != nd->dentry->d_inode->i_uid) return -EPERM; } - if (permission(nd->dentry->d_inode, MAY_WRITE, nd)) + if (vfs_permission(nd, MAY_WRITE)) return -EPERM; return 0; #endif diff --git a/fs/open.c b/fs/open.c index 6e8136751e9..baffc084580 100644 --- a/fs/open.c +++ b/fs/open.c @@ -240,7 +240,7 @@ static inline long do_sys_truncate(const char __user * path, loff_t length) if (!S_ISREG(inode->i_mode)) goto dput_and_out; - error = permission(inode,MAY_WRITE,&nd); + error = vfs_permission(&nd, MAY_WRITE); if (error) goto dput_and_out; @@ -394,7 +394,7 @@ asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times) goto dput_and_out; if (current->fsuid != inode->i_uid && - (error = permission(inode,MAY_WRITE,&nd)) != 0) + (error = vfs_permission(&nd, MAY_WRITE)) != 0) goto dput_and_out; } down(&inode->i_sem); @@ -447,7 +447,7 @@ long do_utimes(char __user * filename, struct timeval * times) goto dput_and_out; if (current->fsuid != inode->i_uid && - (error = permission(inode,MAY_WRITE,&nd)) != 0) + (error = vfs_permission(&nd, MAY_WRITE)) != 0) goto dput_and_out; } down(&inode->i_sem); @@ -506,7 +506,7 @@ asmlinkage long sys_access(const char __user * filename, int mode) res = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd); if (!res) { - res = permission(nd.dentry->d_inode, mode, &nd); + res = vfs_permission(&nd, mode); /* SuS v2 requires we report a read only fs too */ if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode) && !special_file(nd.dentry->d_inode->i_mode)) @@ -530,7 +530,7 @@ asmlinkage long sys_chdir(const char __user * filename) if (error) goto out; - error = permission(nd.dentry->d_inode,MAY_EXEC,&nd); + error = vfs_permission(&nd, MAY_EXEC); if (error) goto dput_and_out; @@ -581,7 +581,7 @@ asmlinkage long sys_chroot(const char __user * filename) if (error) goto out; - error = permission(nd.dentry->d_inode,MAY_EXEC,&nd); + error = vfs_permission(&nd, MAY_EXEC); if (error) goto dput_and_out; diff --git a/include/linux/fs.h b/include/linux/fs.h index 1b5f502a4b8..c3b8c1dc7cd 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -874,6 +874,7 @@ static inline void unlock_super(struct super_block * sb) /* * VFS helper functions.. */ +extern int vfs_permission(struct nameidata *, int); extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *); extern int vfs_mkdir(struct inode *, struct dentry *, int); extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t); diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 41feca3bef8..acc73ba8bad 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -676,7 +676,7 @@ static struct sock *unix_find_other(struct sockaddr_un *sunname, int len, err = path_lookup(sunname->sun_path, LOOKUP_FOLLOW, &nd); if (err) goto fail; - err = permission(nd.dentry->d_inode,MAY_WRITE, &nd); + err = vfs_permission(&nd, MAY_WRITE); if (err) goto put_fail; -- cgit v1.2.3 From 8c744fb83da0771afa04695028e3550b798dad90 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 8 Nov 2005 21:35:04 -0800 Subject: [PATCH] add a file_permission helper A few more callers of permission() just want to check for a different access pattern on an already open file. This patch adds a wrapper for permission() that takes a file in preparation of per-mount read-only support and to clean up the callers a little. The helper is not intended for new code, everything without the interface set in stone should use vfs_permission() Signed-off-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/floppy.c | 3 +-- fs/binfmt_misc.c | 2 +- fs/exec.c | 2 +- fs/namei.c | 18 ++++++++++++++++++ fs/ncpfs/ioctl.c | 34 +++++++++++++++++++--------------- fs/open.c | 2 +- fs/udf/file.c | 2 +- include/linux/fs.h | 5 +++++ 8 files changed, 47 insertions(+), 21 deletions(-) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index dd1935d5542..28002de783b 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3776,8 +3776,7 @@ static int floppy_open(struct inode *inode, struct file *filp) /* Allow ioctls if we have write-permissions even if read-only open. * Needed so that programs such as fdrawcmd still can work on write * protected disks */ - if (filp->f_mode & 2 - || permission(filp->f_dentry->d_inode, 2, NULL) == 0) + if ((filp->f_mode & FMODE_WRITE) || !file_permission(filp, MAY_WRITE)) filp->private_data = (void *)8; if (UFDCS->rawcmd == 1) diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 8ae0db6cd69..2568eb41cb3 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -150,7 +150,7 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) /* if the binary is not readable than enforce mm->dumpable=0 regardless of the interpreter's permissions */ - if (permission(bprm->file->f_dentry->d_inode, MAY_READ, NULL)) + if (file_permission(bprm->file, MAY_READ)) bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP; allow_write_access(bprm->file); diff --git a/fs/exec.c b/fs/exec.c index 7bbb781b9ac..c466fec5de2 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -896,7 +896,7 @@ int flush_old_exec(struct linux_binprm * bprm) flush_thread(); if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || - permission(bprm->file->f_dentry->d_inode,MAY_READ, NULL) || + file_permission(bprm->file, MAY_READ) || (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) { suid_keys(current); current->mm->dumpable = suid_dumpable; diff --git a/fs/namei.c b/fs/namei.c index 25e4ab4ce8b..b69f6ebadb9 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -271,6 +271,23 @@ int vfs_permission(struct nameidata *nd, int mask) return permission(nd->dentry->d_inode, mask, nd); } +/** + * file_permission - check for additional access rights to a given file + * @file: file to check access rights for + * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) + * + * Used to check for read/write/execute permissions on an already opened + * file. + * + * Note: + * Do not use this function in new code. All access checks should + * be done using vfs_permission(). + */ +int file_permission(struct file *file, int mask) +{ + return permission(file->f_dentry->d_inode, mask, NULL); +} + /* * get_write_access() gets write permission for a file. * put_write_access() releases this write permission. @@ -2551,6 +2568,7 @@ EXPORT_SYMBOL(path_release); EXPORT_SYMBOL(path_walk); EXPORT_SYMBOL(permission); EXPORT_SYMBOL(vfs_permission); +EXPORT_SYMBOL(file_permission); EXPORT_SYMBOL(unlock_rename); EXPORT_SYMBOL(vfs_create); EXPORT_SYMBOL(vfs_follow_link); diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c index 88df79356a1..fd3efdca5ae 100644 --- a/fs/ncpfs/ioctl.c +++ b/fs/ncpfs/ioctl.c @@ -30,11 +30,13 @@ #define NCP_PACKET_SIZE_INTERNAL 65536 static int -ncp_get_fs_info(struct ncp_server* server, struct inode* inode, struct ncp_fs_info __user *arg) +ncp_get_fs_info(struct ncp_server * server, struct file *file, + struct ncp_fs_info __user *arg) { + struct inode *inode = file->f_dentry->d_inode; struct ncp_fs_info info; - if ((permission(inode, MAY_WRITE, NULL) != 0) + if ((file_permission(file, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; } @@ -58,11 +60,13 @@ ncp_get_fs_info(struct ncp_server* server, struct inode* inode, struct ncp_fs_in } static int -ncp_get_fs_info_v2(struct ncp_server* server, struct inode* inode, struct ncp_fs_info_v2 __user * arg) +ncp_get_fs_info_v2(struct ncp_server * server, struct file *file, + struct ncp_fs_info_v2 __user * arg) { + struct inode *inode = file->f_dentry->d_inode; struct ncp_fs_info_v2 info2; - if ((permission(inode, MAY_WRITE, NULL) != 0) + if ((file_permission(file, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; } @@ -190,7 +194,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, switch (cmd) { case NCP_IOC_NCPREQUEST: - if ((permission(inode, MAY_WRITE, NULL) != 0) + if ((file_permission(filp, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; } @@ -245,16 +249,16 @@ int ncp_ioctl(struct inode *inode, struct file *filp, return ncp_conn_logged_in(inode->i_sb); case NCP_IOC_GET_FS_INFO: - return ncp_get_fs_info(server, inode, argp); + return ncp_get_fs_info(server, filp, argp); case NCP_IOC_GET_FS_INFO_V2: - return ncp_get_fs_info_v2(server, inode, argp); + return ncp_get_fs_info_v2(server, filp, argp); case NCP_IOC_GETMOUNTUID2: { unsigned long tmp = server->m.mounted_uid; - if ( (permission(inode, MAY_READ, NULL) != 0) + if ((file_permission(filp, MAY_READ) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -268,7 +272,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, { struct ncp_setroot_ioctl sr; - if ( (permission(inode, MAY_READ, NULL) != 0) + if ((file_permission(filp, MAY_READ) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -343,7 +347,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, #ifdef CONFIG_NCPFS_PACKET_SIGNING case NCP_IOC_SIGN_INIT: - if ((permission(inode, MAY_WRITE, NULL) != 0) + if ((file_permission(filp, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -366,7 +370,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, return 0; case NCP_IOC_SIGN_WANTED: - if ( (permission(inode, MAY_READ, NULL) != 0) + if ((file_permission(filp, MAY_READ) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -379,7 +383,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, { int newstate; - if ( (permission(inode, MAY_WRITE, NULL) != 0) + if ((file_permission(filp, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -400,7 +404,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, #ifdef CONFIG_NCPFS_IOCTL_LOCKING case NCP_IOC_LOCKUNLOCK: - if ( (permission(inode, MAY_WRITE, NULL) != 0) + if ((file_permission(filp, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -605,7 +609,7 @@ outrel: #endif /* CONFIG_NCPFS_NLS */ case NCP_IOC_SETDENTRYTTL: - if ((permission(inode, MAY_WRITE, NULL) != 0) && + if ((file_permission(filp, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) return -EACCES; { @@ -635,7 +639,7 @@ outrel: so we have this out of switch */ if (cmd == NCP_IOC_GETMOUNTUID) { __kernel_uid_t uid = 0; - if ((permission(inode, MAY_READ, NULL) != 0) + if ((file_permission(filp, MAY_READ) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; } diff --git a/fs/open.c b/fs/open.c index baffc084580..f53a5b9ffb7 100644 --- a/fs/open.c +++ b/fs/open.c @@ -563,7 +563,7 @@ asmlinkage long sys_fchdir(unsigned int fd) if (!S_ISDIR(inode->i_mode)) goto out_putf; - error = permission(inode, MAY_EXEC, NULL); + error = file_permission(file, MAY_EXEC); if (!error) set_fs_pwd(current->fs, mnt, dentry); out_putf: diff --git a/fs/udf/file.c b/fs/udf/file.c index bb40d63f328..01f520c71dc 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -186,7 +186,7 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, { int result = -EINVAL; - if ( permission(inode, MAY_READ, NULL) != 0 ) + if ( file_permission(filp, MAY_READ) != 0 ) { udf_debug("no permission to access inode %lu\n", inode->i_ino); diff --git a/include/linux/fs.h b/include/linux/fs.h index c3b8c1dc7cd..cc35b6ac778 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -889,6 +889,11 @@ extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct de */ extern void dentry_unhash(struct dentry *dentry); +/* + * VFS file helper functions. + */ +extern int file_permission(struct file *, int); + /* * File types * -- cgit v1.2.3 From 49705b7743fd8f5632a95ec4c6547d169d27ac1f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 8 Nov 2005 21:35:06 -0800 Subject: [PATCH] sanitize lookup_hash prototype ->permission and ->lookup have a struct nameidata * argument these days to pass down lookup intents. Unfortunately some callers of lookup_hash don't actually pass this one down. For lookup_one_len() we don't have a struct nameidata to pass down, but as this function is a library function only used by filesystem code this is an acceptable limitation. All other callers should pass down the nameidata, so this patch changes the lookup_hash interface to only take a struct nameidata argument and derives the other two arguments to __lookup_hash from it. All callers already have the nameidata argument available so this is not a problem. At the same time I'd like to deprecate the lookup_hash interface as there are better exported interfaces for filesystem usage. Before it can actually be removed I need to fix up rpc_pipefs. Signed-off-by: Christoph Hellwig Cc: Ram Pai Cc: Jeff Mahoney Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/feature-removal-schedule.txt | 7 +++++++ fs/namei.c | 20 ++++++++++---------- include/linux/namei.h | 2 +- net/sunrpc/rpc_pipe.c | 6 +++--- 4 files changed, 21 insertions(+), 14 deletions(-) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 910cc999873..66e4ca28fc0 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -118,3 +118,10 @@ Why: This interface has been obsoleted by the new layer3-independent to link against API-compatible library on top of libnfnetlink_queue instead of the current 'libipq'. Who: Harald Welte + +--------------------------- + +What: EXPORT_SYMBOL(lookup_hash) +When: January 2006 +Why: Too low-level interface. Use lookup_one_len or lookup_create instead. +Who: Christoph Hellwig diff --git a/fs/namei.c b/fs/namei.c index b69f6ebadb9..f02ec0e50fc 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1204,9 +1204,9 @@ out: return dentry; } -struct dentry * lookup_hash(struct qstr *name, struct dentry * base) +struct dentry * lookup_hash(struct nameidata *nd) { - return __lookup_hash(name, base, NULL); + return __lookup_hash(&nd->last, nd->dentry, nd); } /* SMP-safe */ @@ -1230,7 +1230,7 @@ struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) } this.hash = end_name_hash(hash); - return lookup_hash(&this, base); + return __lookup_hash(&this, base, NULL); access: return ERR_PTR(-EACCES); } @@ -1563,7 +1563,7 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) dir = nd->dentry; nd->flags &= ~LOOKUP_PARENT; down(&dir->d_inode->i_sem); - path.dentry = __lookup_hash(&nd->last, nd->dentry, nd); + path.dentry = lookup_hash(nd); path.mnt = nd->mnt; do_last: @@ -1665,7 +1665,7 @@ do_link: } dir = nd->dentry; down(&dir->d_inode->i_sem); - path.dentry = __lookup_hash(&nd->last, nd->dentry, nd); + path.dentry = lookup_hash(nd); path.mnt = nd->mnt; __putname(nd->last.name); goto do_last; @@ -1697,7 +1697,7 @@ struct dentry *lookup_create(struct nameidata *nd, int is_dir) /* * Do the final lookup. */ - dentry = lookup_hash(&nd->last, nd->dentry); + dentry = lookup_hash(nd); if (IS_ERR(dentry)) goto fail; @@ -1932,7 +1932,7 @@ asmlinkage long sys_rmdir(const char __user * pathname) goto exit1; } down(&nd.dentry->d_inode->i_sem); - dentry = lookup_hash(&nd.last, nd.dentry); + dentry = lookup_hash(&nd); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { error = vfs_rmdir(nd.dentry->d_inode, dentry); @@ -2001,7 +2001,7 @@ asmlinkage long sys_unlink(const char __user * pathname) if (nd.last_type != LAST_NORM) goto exit1; down(&nd.dentry->d_inode->i_sem); - dentry = lookup_hash(&nd.last, nd.dentry); + dentry = lookup_hash(&nd); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { /* Why not before? Because we want correct error value */ @@ -2344,7 +2344,7 @@ static inline int do_rename(const char * oldname, const char * newname) trap = lock_rename(new_dir, old_dir); - old_dentry = lookup_hash(&oldnd.last, old_dir); + old_dentry = lookup_hash(&oldnd); error = PTR_ERR(old_dentry); if (IS_ERR(old_dentry)) goto exit3; @@ -2364,7 +2364,7 @@ static inline int do_rename(const char * oldname, const char * newname) error = -EINVAL; if (old_dentry == trap) goto exit4; - new_dentry = lookup_hash(&newnd.last, new_dir); + new_dentry = lookup_hash(&newnd); error = PTR_ERR(new_dentry); if (IS_ERR(new_dentry)) goto exit4; diff --git a/include/linux/namei.h b/include/linux/namei.h index 1c975d0d9e9..455660eafba 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -74,7 +74,7 @@ extern struct file *nameidata_to_filp(struct nameidata *nd, int flags); extern void release_open_intent(struct nameidata *); extern struct dentry * lookup_one_len(const char *, struct dentry *, int); -extern struct dentry * lookup_hash(struct qstr *, struct dentry *); +extern struct dentry * lookup_hash(struct nameidata *); extern int follow_down(struct vfsmount **, struct dentry **); extern int follow_up(struct vfsmount **, struct dentry **); diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 4f188d0a5d1..81e00a6c19d 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -603,7 +603,7 @@ rpc_lookup_negative(char *path, struct nameidata *nd) return ERR_PTR(error); dir = nd->dentry->d_inode; down(&dir->i_sem); - dentry = lookup_hash(&nd->last, nd->dentry); + dentry = lookup_hash(nd); if (IS_ERR(dentry)) goto out_err; if (dentry->d_inode) { @@ -665,7 +665,7 @@ rpc_rmdir(char *path) return error; dir = nd.dentry->d_inode; down(&dir->i_sem); - dentry = lookup_hash(&nd.last, nd.dentry); + dentry = lookup_hash(&nd); if (IS_ERR(dentry)) { error = PTR_ERR(dentry); goto out_release; @@ -726,7 +726,7 @@ rpc_unlink(char *path) return error; dir = nd.dentry->d_inode; down(&dir->i_sem); - dentry = lookup_hash(&nd.last, nd.dentry); + dentry = lookup_hash(&nd); if (IS_ERR(dentry)) { error = PTR_ERR(dentry); goto out_release; -- cgit v1.2.3 From 7a81e316866be8053b18fe1dffc663f1ff19bfc3 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 8 Nov 2005 21:35:07 -0800 Subject: [PATCH] re-add TIOCSTART and TIOCSTOP compat_ioctl handlers We don't implement these ioctls, but some architectures define them in the headers. Bash picks them up and issues them frequently. Add compat_ioctl handlers to silence warnings about unhandled copat ioctls. Signed-off-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/compat_ioctl.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 4909754ea84..71c9d45c062 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -3051,6 +3051,16 @@ HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl) COMPATIBLE_IOCTL(TIOCGLTC) COMPATIBLE_IOCTL(TIOCSLTC) #endif +#ifdef TIOCSTART +/* + * For these two we have defintions in ioctls.h and/or termios.h on + * some architectures but no actual implemention. Some applications + * like bash call them if they are defined in the headers, so we provide + * entries here to avoid syslog message spew. + */ +COMPATIBLE_IOCTL(TIOCSTART) +COMPATIBLE_IOCTL(TIOCSTOP) +#endif /* Usbdevfs */ HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control) HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk) -- cgit v1.2.3 From 7e4c54a2a4f1cec6a652c6014714ee51b7e1311f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 8 Nov 2005 21:35:07 -0800 Subject: [PATCH] remove ioctl32_handler_t Some architectures define and use this type in their compat_ioctl code, but all of them can easily use the identical ioctl_trans_handler_t type that is defined in common code. Signed-off-by: Christoph Hellwig Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ia64/ia32/ia32_ioctl.c | 4 +--- arch/mips/kernel/ioctl32.c | 4 +--- arch/sparc64/kernel/ioctl32.c | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/arch/ia64/ia32/ia32_ioctl.c b/arch/ia64/ia32/ia32_ioctl.c index 164b211f417..88739394f6d 100644 --- a/arch/ia64/ia32/ia32_ioctl.c +++ b/arch/ia64/ia32/ia32_ioctl.c @@ -29,10 +29,8 @@ #define CODE #include "compat_ioctl.c" -typedef int (* ioctl32_handler_t)(unsigned int, unsigned int, unsigned long, struct file *); - #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),sys_ioctl) -#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl32_handler_t)(handler), NULL }, +#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl_trans_handler_t)(handler), NULL }, #define IOCTL_TABLE_START \ struct ioctl_trans ioctl_start[] = { #define IOCTL_TABLE_END \ diff --git a/arch/mips/kernel/ioctl32.c b/arch/mips/kernel/ioctl32.c index ed9b2da510b..9ea1fc74886 100644 --- a/arch/mips/kernel/ioctl32.c +++ b/arch/mips/kernel/ioctl32.c @@ -26,10 +26,8 @@ long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); #define CODE #include "compat_ioctl.c" -typedef int (* ioctl32_handler_t)(unsigned int, unsigned int, unsigned long, struct file *); - #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),sys_ioctl) -#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl32_handler_t)(handler), NULL }, +#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl_trans_handler_t)(handler), NULL }, #define IOCTL_TABLE_START \ struct ioctl_trans ioctl_start[] = { #define IOCTL_TABLE_END \ diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index 92e26304de9..c2e96daa5ab 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -92,10 +92,8 @@ static int fbiogscursor(unsigned int fd, unsigned int cmd, unsigned long arg) return sys_ioctl (fd, FBIOSCURSOR, (unsigned long)p); } -typedef int (* ioctl32_handler_t)(unsigned int, unsigned int, unsigned long, struct file *); - #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),sys_ioctl) -#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl32_handler_t)(handler), NULL }, +#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl_trans_handler_t)(handler), NULL }, #define IOCTL_TABLE_START \ struct ioctl_trans ioctl_start[] = { #define IOCTL_TABLE_END \ -- cgit v1.2.3 From b05a581d4865d74c0e270d27156a88d2dee9494e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 8 Nov 2005 21:35:08 -0800 Subject: [PATCH] move some COMPATIBLE_IOCTL entries from x86_64 to common code Signed-off-by: Christoph Hellwig Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/ia32/ia32_ioctl.c | 6 ------ include/linux/compat_ioctl.h | 8 ++++++++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/x86_64/ia32/ia32_ioctl.c b/arch/x86_64/ia32/ia32_ioctl.c index 4ba0e293d5e..e335bd0b637 100644 --- a/arch/x86_64/ia32/ia32_ioctl.c +++ b/arch/x86_64/ia32/ia32_ioctl.c @@ -64,12 +64,6 @@ struct ioctl_trans ioctl_start[] = { #include #define DECLARES #include "compat_ioctl.c" -COMPATIBLE_IOCTL(HDIO_SET_KEEPSETTINGS) -COMPATIBLE_IOCTL(HDIO_SCAN_HWIF) -COMPATIBLE_IOCTL(BLKRASET) -COMPATIBLE_IOCTL(0x4B50) /* KDGHWCLK - not in the kernel, but don't complain */ -COMPATIBLE_IOCTL(0x4B51) /* KDSHWCLK - not in the kernel, but don't complain */ -COMPATIBLE_IOCTL(FIOQSIZE) /* And these ioctls need translation */ /* realtime device */ diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h index ecb0d39c079..4c63c296301 100644 --- a/include/linux/compat_ioctl.h +++ b/include/linux/compat_ioctl.h @@ -10,6 +10,10 @@ #define ULONG_IOCTL(cmd) HANDLE_IOCTL((cmd),(ioctl_trans_handler_t)sys_ioctl) #endif + +COMPATIBLE_IOCTL(0x4B50) /* KDGHWCLK - not in the kernel, but don't complain */ +COMPATIBLE_IOCTL(0x4B51) /* KDSHWCLK - not in the kernel, but don't complain */ + /* Big T */ COMPATIBLE_IOCTL(TCGETA) COMPATIBLE_IOCTL(TCSETA) @@ -81,6 +85,8 @@ COMPATIBLE_IOCTL(HDIO_DRIVE_CMD) COMPATIBLE_IOCTL(HDIO_DRIVE_TASK) COMPATIBLE_IOCTL(HDIO_SET_PIO_MODE) COMPATIBLE_IOCTL(HDIO_SET_NICE) +COMPATIBLE_IOCTL(HDIO_SET_KEEPSETTINGS) +COMPATIBLE_IOCTL(HDIO_SCAN_HWIF) /* 0x02 -- Floppy ioctls */ COMPATIBLE_IOCTL(FDMSGON) COMPATIBLE_IOCTL(FDMSGOFF) @@ -99,6 +105,7 @@ COMPATIBLE_IOCTL(FDTWADDLE) COMPATIBLE_IOCTL(FDFMTTRK) COMPATIBLE_IOCTL(FDRAWCMD) /* 0x12 */ +COMPATIBLE_IOCTL(BLKRASET) COMPATIBLE_IOCTL(BLKROSET) COMPATIBLE_IOCTL(BLKROGET) COMPATIBLE_IOCTL(BLKRRPART) @@ -262,6 +269,7 @@ COMPATIBLE_IOCTL(RTC_WKALM_RD) /* Little m */ COMPATIBLE_IOCTL(MTIOCTOP) /* Socket level stuff */ +COMPATIBLE_IOCTL(FIOQSIZE) COMPATIBLE_IOCTL(FIOSETOWN) COMPATIBLE_IOCTL(SIOCSPGRP) COMPATIBLE_IOCTL(FIOGETOWN) -- cgit v1.2.3 From 29b2f784da28cc8289f17a07360997093b7b0156 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 8 Nov 2005 21:35:09 -0800 Subject: [PATCH] dvb: dst: Correcty Identify Tuner and Daughterboards - Identify Tuner, Daughterboards correctly - Added partial support for VP-10320A (DVB-S), VP-20210 (DVB-C), VP-3040 (DVB-T) Signed-off-by: Manu Abraham Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/bt8xx/dst.c | 58 ++++++++++++++++++++++++++++++++++-- drivers/media/dvb/bt8xx/dst_common.h | 2 ++ 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index b3c9d7327ac..6f9e5c16803 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -690,8 +690,8 @@ struct dst_types dst_tlist[] = { .device_id = "DTT-CI", .offset = 1, .dst_type = DST_TYPE_IS_TERR, - .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2, - .dst_feature = 0 + .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE, + .dst_feature = DST_TYPE_HAS_CA }, { @@ -796,6 +796,56 @@ static int dst_get_vendor(struct dst_state *state) return 0; } +static int dst_get_tuner_info(struct dst_state *state) +{ + u8 get_tuner_1[] = { 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + u8 get_tuner_2[] = { 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + get_tuner_1[7] = dst_check_sum(get_tuner_1, 7); + get_tuner_2[7] = dst_check_sum(get_tuner_2, 7); + if (state->type_flags & DST_TYPE_HAS_MULTI_FE) { + if (dst_command(state, get_tuner_2, 8) < 0) { + dprintk(verbose, DST_INFO, 1, "Unsupported Command"); + return -1; + } + } else { + if (dst_command(state, get_tuner_1, 8) < 0) { + dprintk(verbose, DST_INFO, 1, "Unsupported Command"); + return -1; + } + } + memset(&state->board_info, '\0', 8); + memcpy(&state->board_info, &state->rxbuffer, 8); + if (state->type_flags & DST_TYPE_HAS_MULTI_FE) { + if (state->board_info[1] == 0x0b) { + if (state->type_flags & DST_TYPE_HAS_TS204) + state->type_flags &= ~DST_TYPE_HAS_TS204; + state->type_flags |= DST_TYPE_HAS_NEWTUNE; + dprintk(verbose, DST_INFO, 1, "DST type has TS=188"); + } else { + if (state->type_flags & DST_TYPE_HAS_NEWTUNE) + state->type_flags &= ~DST_TYPE_HAS_NEWTUNE; + state->type_flags |= DST_TYPE_HAS_TS204; + dprintk(verbose, DST_INFO, 1, "DST type has TS=204"); + } + } else { + if (state->board_info[0] == 0xbc) { + if (state->type_flags & DST_TYPE_HAS_TS204) + state->type_flags &= ~DST_TYPE_HAS_TS204; + state->type_flags |= DST_TYPE_HAS_NEWTUNE; + dprintk(verbose, DST_INFO, 1, "DST type has TS=188, Daughterboard=[%d]", state->board_info[1]); + + } else if (state->board_info[0] == 0xcc) { + if (state->type_flags & DST_TYPE_HAS_NEWTUNE) + state->type_flags &= ~DST_TYPE_HAS_NEWTUNE; + state->type_flags |= DST_TYPE_HAS_TS204; + dprintk(verbose, DST_INFO, 1, "DST type has TS=204 Daughterboard=[%d]", state->board_info[1]); + } + } + + return 0; +} + static int dst_get_device_id(struct dst_state *state) { u8 reply; @@ -886,6 +936,10 @@ static int dst_probe(struct dst_state *state) dprintk(verbose, DST_INFO, 1, "MAC: Unsupported command"); return 0; } + if ((state->type_flags & DST_TYPE_HAS_MULTI_FE) || (state->type_flags & DST_TYPE_HAS_FW_BUILD)) { + if (dst_get_tuner_info(state) < 0) + dprintk(verbose, DST_INFO, 1, "Tuner: Unsupported command"); + } if (state->type_flags & DST_TYPE_HAS_FW_BUILD) { if (dst_fw_ver(state) < 0) { dprintk(verbose, DST_INFO, 1, "FW: Unsupported command"); diff --git a/drivers/media/dvb/bt8xx/dst_common.h b/drivers/media/dvb/bt8xx/dst_common.h index 3281a6ca368..29b5430dbe4 100644 --- a/drivers/media/dvb/bt8xx/dst_common.h +++ b/drivers/media/dvb/bt8xx/dst_common.h @@ -49,6 +49,7 @@ #define DST_TYPE_HAS_FW_BUILD 64 #define DST_TYPE_HAS_OBS_REGS 128 #define DST_TYPE_HAS_INC_COUNT 256 +#define DST_TYPE_HAS_MULTI_FE 512 /* Card capability list */ @@ -117,6 +118,7 @@ struct dst_state { u8 fw_version[8]; u8 card_info[8]; u8 vendor[8]; + u8 board_info[8]; }; struct dst_types { -- cgit v1.2.3 From 9691bb14d9ab646868a6392e9419070c304a9590 Mon Sep 17 00:00:00 2001 From: Martin Zwickel Date: Tue, 8 Nov 2005 21:35:10 -0800 Subject: [PATCH] dvb: add support for Technotrend Budget Card S1500 This patch adds support for the Technotrend Budget Card S1500 with a BSBE1 frontend and the LNBP21. Signed-off-by: Martin Zwickel Signed-off-by: Andrew de Quincey Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/ttpci/budget.c | 118 +++++++++++++++++++++++++++++++++++---- 1 file changed, 108 insertions(+), 10 deletions(-) diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 43d6c826864..0f6ead848e4 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -226,12 +226,14 @@ static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend* fe, int arg) return 0; } -static void lnbp21_init(struct budget* budget) +static int lnbp21_init(struct budget* budget) { u8 buf = 0x00; struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = &buf, .len = sizeof(buf) }; - i2c_transfer (&budget->i2c_adap, &msg, 1); + if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; } static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) @@ -273,7 +275,7 @@ static u8 alps_bsru6_inittab[] = { 0x01, 0x15, 0x02, 0x00, 0x03, 0x00, - 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ + 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ 0x06, 0x40, /* DAC not used, set to high impendance mode */ 0x07, 0x00, /* DAC LSB */ @@ -367,6 +369,80 @@ static struct stv0299_config alps_bsru6_config = { .pll_set = alps_bsru6_pll_set, }; +static u8 alps_bsbe1_inittab[] = { + 0x01, 0x15, + 0x02, 0x30, + 0x03, 0x00, + 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ + 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ + 0x06, 0x40, /* DAC not used, set to high impendance mode */ + 0x07, 0x00, /* DAC LSB */ + 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ + 0x09, 0x00, /* FIFO */ + 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ + 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ + 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ + 0x10, 0x3f, // AGC2 0x3d + 0x11, 0x84, + 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x15, 0xc9, // lock detector threshold + 0x16, 0x00, + 0x17, 0x00, + 0x18, 0x00, + 0x19, 0x00, + 0x1a, 0x00, + 0x1f, 0x50, + 0x20, 0x00, + 0x21, 0x00, + 0x22, 0x00, + 0x23, 0x00, + 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 + 0x29, 0x1e, // 1/2 threshold + 0x2a, 0x14, // 2/3 threshold + 0x2b, 0x0f, // 3/4 threshold + 0x2c, 0x09, // 5/6 threshold + 0x2d, 0x05, // 7/8 threshold + 0x2e, 0x01, + 0x31, 0x1f, // test all FECs + 0x32, 0x19, // viterbi and synchro search + 0x33, 0xfc, // rs control + 0x34, 0x93, // error control + 0x0f, 0x92, // 0x80 = inverse AGC + 0xff, 0xff +}; + +static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params) +{ + int ret; + u8 data[4]; + u32 div; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) + return -EINVAL; + + div = (params->frequency + (125 - 1)) / 125; // round correctly + data[0] = (div >> 8) & 0x7f; + data[1] = div & 0xff; + data[2] = 0x80 | ((div & 0x18000) >> 10) | 4; + data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4; + + ret = i2c_transfer(i2c, &msg, 1); + return (ret != 1) ? -EIO : 0; +} + +static struct stv0299_config alps_bsbe1_config = { + .demod_address = 0x68, + .inittab = alps_bsbe1_inittab, + .mclk = 88000000UL, + .invert = 1, + .enhanced_tuning = 0, + .skip_reinit = 0, + .min_delay_ms = 100, + .set_symbol_rate = alps_bsru6_set_symbol_rate, + .pll_set = alps_bsbe1_pll_set, +}; + static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct budget* budget = (struct budget*) fe->dvb->priv; @@ -500,6 +576,19 @@ static u8 read_pwm(struct budget* budget) static void frontend_init(struct budget *budget) { switch(budget->dev->pci->subsystem_device) { + case 0x1017: + // try the ALPS BSBE1 now + budget->dvb_frontend = stv0299_attach(&alps_bsbe1_config, &budget->i2c_adap); + if (budget->dvb_frontend) { + budget->dvb_frontend->ops->set_voltage = lnbp21_set_voltage; + budget->dvb_frontend->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage; + if (lnbp21_init(budget)) { + printk("%s: No LNBP21 found!\n", __FUNCTION__); + goto error_out; + } + } + + break; case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659)) case 0x1013: // try the ALPS BSRV2 first of all @@ -554,7 +643,10 @@ static void frontend_init(struct budget *budget) if (budget->dvb_frontend) { budget->dvb_frontend->ops->set_voltage = lnbp21_set_voltage; budget->dvb_frontend->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage; - lnbp21_init(budget); + if (lnbp21_init(budget)) { + printk("%s: No LNBP21 found!\n", __FUNCTION__); + goto error_out; + } break; } } @@ -566,13 +658,17 @@ static void frontend_init(struct budget *budget) budget->dev->pci->subsystem_vendor, budget->dev->pci->subsystem_device); } else { - if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend)) { - printk("budget: Frontend registration failed!\n"); - if (budget->dvb_frontend->ops->release) - budget->dvb_frontend->ops->release(budget->dvb_frontend); - budget->dvb_frontend = NULL; - } + if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend)) + goto error_out; } + return; + +error_out: + printk("budget: Frontend registration failed!\n"); + if (budget->dvb_frontend->ops->release) + budget->dvb_frontend->ops->release(budget->dvb_frontend); + budget->dvb_frontend = NULL; + return; } static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) @@ -618,6 +714,7 @@ static int budget_detach (struct saa7146_dev* dev) static struct saa7146_extension budget_extension; +MAKE_BUDGET_INFO(ttbs2, "TT-Budget/WinTV-NOVA-S PCI (rev AL/alps bsbe1 lnbp21 frontend)", BUDGET_TT); MAKE_BUDGET_INFO(ttbs, "TT-Budget/WinTV-NOVA-S PCI", BUDGET_TT); MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT); MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT); @@ -630,6 +727,7 @@ static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(ttbc, 0x13c2, 0x1004), MAKE_EXTENSION_PCI(ttbt, 0x13c2, 0x1005), MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013), + MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017), MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1016), MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60), MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61), -- cgit v1.2.3 From 3765022171874d249535a1c8b8190f408fd85f21 Mon Sep 17 00:00:00 2001 From: Andrew de Quincey Date: Tue, 8 Nov 2005 21:35:11 -0800 Subject: [PATCH] dvb: stv0299: revert improper method Remove my badly thought out patch. This does need done, but in a proper way. Signed-off-by: Andrew de Quincey Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/frontends/stv0299.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c index 889d9257215..b1876618a37 100644 --- a/drivers/media/dvb/frontends/stv0299.c +++ b/drivers/media/dvb/frontends/stv0299.c @@ -64,8 +64,12 @@ struct stv0299_state { u32 tuner_frequency; u32 symbol_rate; fe_code_rate_t fec_inner; + int errmode; }; +#define STATUS_BER 0 +#define STATUS_UCBLOCKS 1 + static int debug; static int debug_legacy_dish_switch; #define dprintk(args...) \ @@ -517,8 +521,7 @@ static int stv0299_read_ber(struct dvb_frontend* fe, u32* ber) { struct stv0299_state* state = fe->demodulator_priv; - stv0299_writeregI(state, 0x34, (stv0299_readreg(state, 0x34) & 0xcf) | 0x10); - msleep(100); + if (state->errmode != STATUS_BER) return 0; *ber = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e); return 0; @@ -557,9 +560,8 @@ static int stv0299_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) { struct stv0299_state* state = fe->demodulator_priv; - stv0299_writeregI(state, 0x34, (stv0299_readreg(state, 0x34) & 0xcf) | 0x30); - msleep(100); - *ucblocks = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e); + if (state->errmode != STATUS_UCBLOCKS) *ucblocks = 0; + else *ucblocks = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e); return 0; } @@ -708,6 +710,7 @@ struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, state->tuner_frequency = 0; state->symbol_rate = 0; state->fec_inner = 0; + state->errmode = STATUS_BER; /* check if the demod is there */ stv0299_writeregI(state, 0x02, 0x34); /* standby off */ -- cgit v1.2.3 From 3cff00d91292e744a510be7256f1c80e1b0be819 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:35:12 -0800 Subject: [PATCH] dvb: Add ATSC support for DViCO FusionHDTV5 Lite Added ATSC support for DViCO FusionHDTV5 Lite. Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/bt8xx/Kconfig | 4 +- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 67 ++++++++++++++++++++++++++++++++++ drivers/media/dvb/bt8xx/dvb-bt8xx.h | 1 + drivers/media/dvb/frontends/lgdt330x.c | 1 + 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig index 1e85d16491b..2337b41714e 100644 --- a/drivers/media/dvb/bt8xx/Kconfig +++ b/drivers/media/dvb/bt8xx/Kconfig @@ -6,10 +6,12 @@ config DVB_BT8XX select DVB_NXT6000 select DVB_CX24110 select DVB_OR51211 + select DVB_LGDT330X help Support for PCI cards based on the Bt8xx PCI bridge. Examples are the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards, - the pcHDTV HD2000 cards, and certain AVerMedia cards. + the pcHDTV HD2000 cards, the DViCO FusionHDTV Lite cards, and + some AVerMedia cards. Since these cards have no MPEG decoder onboard, they transmit only compressed MPEG data over the PCI bus, so you need diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index c5c7672cd53..96ef35ecab4 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -34,6 +34,7 @@ #include "dvb_frontend.h" #include "dvb-bt8xx.h" #include "bt878.h" +#include "dvb-pll.h" static int debug; @@ -546,6 +547,55 @@ static struct mt352_config digitv_alps_tded4_config = { .pll_set = digitv_alps_tded4_pll_set, }; +static int tdvs_tua6034_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +{ + struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv; + u8 buf[4]; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; + int err; + + dvb_pll_configure(&dvb_pll_tdvs_tua6034, buf, params->frequency, 0); + dprintk("%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n", + __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]); + if ((err = i2c_transfer(card->i2c_adapter, &msg, 1)) != 1) { + printk(KERN_WARNING "dvb-bt8xx: %s error " + "(addr %02x <- %02x, err = %i)\n", + __FUNCTION__, buf[0], buf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } + + /* Set the Auxiliary Byte. */ + buf[2] &= ~0x20; + buf[2] |= 0x18; + buf[3] = 0x50; + i2c_transfer(card->i2c_adapter, &msg, 1); + + return 0; +} + +static struct lgdt330x_config tdvs_tua6034_config = { + .demod_address = 0x0e, + .demod_chip = LGDT3303, + .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ + .pll_set = tdvs_tua6034_pll_set, +}; + +static void lgdt330x_reset(struct dvb_bt8xx_card *bt) +{ + /* Set pin 27 of the lgdt3303 chip high to reset the frontend */ + + /* Pulse the reset line */ + bttv_write_gpio(bt->bttv_nr, 0x00e00007, 0x00000001); /* High */ + bttv_write_gpio(bt->bttv_nr, 0x00e00007, 0x00000000); /* Low */ + msleep(100); + + bttv_write_gpio(bt->bttv_nr, 0x00e00007, 0x00000001); /* High */ + msleep(100); +} + static void frontend_init(struct dvb_bt8xx_card *card, u32 type) { int ret; @@ -562,6 +612,15 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) break; #endif +#ifdef BTTV_DVICO_FUSIONHDTV_5_LITE + case BTTV_DVICO_FUSIONHDTV_5_LITE: + lgdt330x_reset(card); + card->fe = lgdt330x_attach(&tdvs_tua6034_config, card->i2c_adapter); + if (card->fe != NULL) + dprintk ("dvb_bt8xx: lgdt330x detected\n"); + break; +#endif + #ifdef BTTV_TWINHAN_VP3021 case BTTV_TWINHAN_VP3021: #else @@ -765,6 +824,14 @@ static int dvb_bt8xx_probe(struct device *dev) * DA_APP(parallel) */ break; +#ifdef BTTV_DVICO_FUSIONHDTV_5_LITE + case BTTV_DVICO_FUSIONHDTV_5_LITE: +#endif + card->gpio_mode = 0x0400c060; + card->op_sync_orin = BT878_RISC_SYNC_MASK; + card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR; + break; + #ifdef BTTV_TWINHAN_VP3021 case BTTV_TWINHAN_VP3021: #else diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h index 9ec8e5bd6c1..cf035a80361 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h @@ -35,6 +35,7 @@ #include "nxt6000.h" #include "cx24110.h" #include "or51211.h" +#include "lgdt330x.h" struct dvb_bt8xx_card { struct semaphore lock; diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index 7852b83b82d..145918877d2 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c @@ -26,6 +26,7 @@ * DViCO FusionHDTV 3 Gold-Q * DViCO FusionHDTV 3 Gold-T * DViCO FusionHDTV 5 Gold + * DViCO FusionHDTV 5 Lite * * TODO: * signal strength always returns 0. -- cgit v1.2.3 From 634623d3ba6146e13d06d3f36188c189c8a58a23 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 8 Nov 2005 21:35:13 -0800 Subject: [PATCH] dvb: tda1004x: pll communication fixes - leave I2C bridge open at pll_sleep to support Philips EUROPA based cards. - give an error message if the communication with the pll fails. Signed-off-by: Hartmut Hackmann Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/frontends/tda1004x.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index 3529c618f82..7968743826f 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c @@ -420,7 +420,7 @@ static void tda10046_init_plls(struct dvb_frontend* fe) struct tda1004x_state* state = fe->demodulator_priv; tda1004x_write_byteI(state, TDA10046H_CONFPLL1, 0xf0); - tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 10); // PLL M = 10 + tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x0a); // PLL M = 10 if (state->config->xtal_freq == TDA10046_XTAL_4M ) { dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __FUNCTION__); tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0 @@ -597,7 +597,10 @@ static int tda10046_init(struct dvb_frontend* fe) // Init the tuner PLL if (state->config->pll_init) { tda1004x_enable_tuner_i2c(state); - state->config->pll_init(fe); + if (state->config->pll_init(fe)) { + printk(KERN_ERR "tda1004x: pll init failed\n"); + return -EIO; + } tda1004x_disable_tuner_i2c(state); } @@ -667,7 +670,10 @@ static int tda1004x_set_fe(struct dvb_frontend* fe, // set frequency tda1004x_enable_tuner_i2c(state); - state->config->pll_set(fe, fe_params); + if (state->config->pll_set(fe, fe_params)) { + printk(KERN_ERR "tda1004x: pll set failed\n"); + return -EIO; + } tda1004x_disable_tuner_i2c(state); // Hardcoded to use auto as much as possible on the TDA10045 as it @@ -832,6 +838,8 @@ static int tda1004x_set_fe(struct dvb_frontend* fe, case TDA1004X_DEMOD_TDA10046: tda1004x_write_mask(state, TDA1004X_AUTO, 0x40, 0x40); + msleep(1); + tda1004x_write_mask(state, TDA10046H_AGC_CONF, 4, 1); break; } @@ -1129,7 +1137,12 @@ static int tda1004x_sleep(struct dvb_frontend* fe) if (state->config->pll_sleep != NULL) { tda1004x_enable_tuner_i2c(state); state->config->pll_sleep(fe); - tda1004x_disable_tuner_i2c(state); + if (state->config->if_freq != TDA10046_FREQ_052) { + /* special hack for Philips EUROPA Based boards: + * keep the I2c bridge open for tuner access in analog mode + */ + tda1004x_disable_tuner_i2c(state); + } } tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1); break; -- cgit v1.2.3 From 6573dd752d50730d44c550ad0467d15871963655 Mon Sep 17 00:00:00 2001 From: Andreas Oberritter Date: Tue, 8 Nov 2005 21:35:14 -0800 Subject: [PATCH] dvb: pluto2: Removed unavoidable error message and related code Removed unavoidable error message and related code. Signed-off-by: Andreas Oberritter Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/pluto2/pluto2.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c index 85b437bbddc..bbebd1c4cac 100644 --- a/drivers/media/dvb/pluto2/pluto2.c +++ b/drivers/media/dvb/pluto2/pluto2.c @@ -286,15 +286,10 @@ static void pluto_dma_end(struct pluto *pluto, unsigned int nbpackets) * although one packet has been transfered. */ if ((nbpackets == 0) || (nbpackets > TS_DMA_PACKETS)) { - unsigned int i = 0, valid; + unsigned int i = 0; while (pluto->dma_buf[i] == 0x47) i += 188; - valid = i / 188; - if (nbpackets != valid) { - dev_err(&pluto->pdev->dev, "nbpackets=%u valid=%u\n", - nbpackets, valid); - nbpackets = valid; - } + nbpackets = i / 188; } dvb_dmx_swfilter_packets(&pluto->demux, pluto->dma_buf, nbpackets); -- cgit v1.2.3 From a18a80b09f78178f6404b538ab09937ee9044e2e Mon Sep 17 00:00:00 2001 From: Thorsten Maerz Date: Tue, 8 Nov 2005 21:35:15 -0800 Subject: [PATCH] dvb: remove duplicate key definitions The duplicate key definitions cause misinterpretations with other keys, e.g. the "TELETEXT" key clashes with "CHANNEL_UP" and thus can not be used with LIRC. This patch removes these duplicates. Signed-off-by: Thorsten Maerz Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/dvb-usb/a800.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c index e55322ef76b..49f541d9a04 100644 --- a/drivers/media/dvb/dvb-usb/a800.c +++ b/drivers/media/dvb/dvb-usb/a800.c @@ -43,11 +43,9 @@ static struct dvb_usb_rc_key a800_rc_keys[] = { { 0x02, 0x13, KEY_RIGHT }, /* R / CH RTN */ { 0x02, 0x17, KEY_PROG2 }, /* SNAP SHOT */ { 0x02, 0x10, KEY_PROG3 }, /* 16-CH PREV */ - { 0x02, 0x03, KEY_CHANNELUP }, /* CH UP */ { 0x02, 0x1e, KEY_VOLUMEDOWN }, /* VOL DOWN */ { 0x02, 0x0c, KEY_ZOOM }, /* FULL SCREEN */ { 0x02, 0x1f, KEY_VOLUMEUP }, /* VOL UP */ - { 0x02, 0x02, KEY_CHANNELDOWN }, /* CH DOWN */ { 0x02, 0x14, KEY_MUTE }, /* MUTE */ { 0x02, 0x08, KEY_AUDIO }, /* AUDIO */ { 0x02, 0x19, KEY_RECORD }, /* RECORD */ @@ -57,8 +55,6 @@ static struct dvb_usb_rc_key a800_rc_keys[] = { { 0x02, 0x1d, KEY_BACK }, /* << / RED */ { 0x02, 0x1c, KEY_FORWARD }, /* >> / YELLOW */ { 0x02, 0x03, KEY_TEXT }, /* TELETEXT */ - { 0x02, 0x01, KEY_FIRST }, /* |<< / GREEN */ - { 0x02, 0x00, KEY_LAST }, /* >>| / BLUE */ { 0x02, 0x04, KEY_EPG }, /* EPG */ { 0x02, 0x15, KEY_MENU }, /* MENU */ -- cgit v1.2.3 From 2b70a2f55e249308c57879df5723d96406e12b27 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:35:16 -0800 Subject: [PATCH] dvb: microtune mt7202dtf: Fix charge pump setting Fix charge pump setting in microtune_mt7202dtf_pll_set(). Thanks to Jyrki Niskala for reporting. Signed-off-by: Johannes Stezenbach Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index 96ef35ecab4..1c5f1ec8535 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -280,7 +280,7 @@ static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_front data[0] = (div >> 8) & 0x7f; data[1] = div & 0xff; data[2] = ((div >> 10) & 0x60) | cfg; - data[3] = cpump | band_select; + data[3] = (cpump << 6) | band_select; i2c_transfer(card->i2c_adapter, &msg, 1); return (div * 166666 - 36000000); -- cgit v1.2.3 From 93a14f15d35cd60742220995d3413d256ebde9ee Mon Sep 17 00:00:00 2001 From: Raymond Mantchala Date: Tue, 8 Nov 2005 21:35:17 -0800 Subject: [PATCH] dvb: dst: ASN.1 length field Fix ASN.1 length field Fix Signed-off-by: Raymond Mantchala Signed-off-by: Manu Abraham Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/bt8xx/dst_ca.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c index 6776a592045..8a8a3333cb8 100644 --- a/drivers/media/dvb/bt8xx/dst_ca.c +++ b/drivers/media/dvb/bt8xx/dst_ca.c @@ -328,7 +328,8 @@ u32 asn_1_decode(u8 *asn_1_array) } else { word_count = length_field & 0x7f; for (count = 0; count < word_count; count++) { - length = (length | asn_1_array[count + 1]) << 8; + length = length << 8; + length += asn_1_array[count + 1]; dprintk(verbose, DST_CA_DEBUG, 1, " Length=[%04x]", length); } } -- cgit v1.2.3 From 174f80dfcba45677f12ba57479d03750dd9cad7b Mon Sep 17 00:00:00 2001 From: Peter Hagervall Date: Tue, 8 Nov 2005 21:35:18 -0800 Subject: [PATCH] dvb: fix sparse warnings Sparse warnings - remove address space related warnings Signed-off-by: Peter Hagervall Signed-off-by: Manu Abraham Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/bt8xx/dst_ca.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c index 8a8a3333cb8..492e829fe02 100644 --- a/drivers/media/dvb/bt8xx/dst_ca.c +++ b/drivers/media/dvb/bt8xx/dst_ca.c @@ -166,7 +166,7 @@ static int ca_get_app_info(struct dst_state *state) return 0; } -static int ca_get_slot_caps(struct dst_state *state, struct ca_caps *p_ca_caps, void *arg) +static int ca_get_slot_caps(struct dst_state *state, struct ca_caps *p_ca_caps, void __user *arg) { int i; u8 slot_cap[256]; @@ -192,20 +192,20 @@ static int ca_get_slot_caps(struct dst_state *state, struct ca_caps *p_ca_caps, p_ca_caps->descr_num = slot_cap[7]; p_ca_caps->descr_type = 1; - if (copy_to_user((struct ca_caps *)arg, p_ca_caps, sizeof (struct ca_caps))) + if (copy_to_user(arg, p_ca_caps, sizeof (struct ca_caps))) return -EFAULT; return 0; } /* Need some more work */ -static int ca_get_slot_descr(struct dst_state *state, struct ca_msg *p_ca_message, void *arg) +static int ca_get_slot_descr(struct dst_state *state, struct ca_msg *p_ca_message, void __user *arg) { return -EOPNOTSUPP; } -static int ca_get_slot_info(struct dst_state *state, struct ca_slot_info *p_ca_slot_info, void *arg) +static int ca_get_slot_info(struct dst_state *state, struct ca_slot_info *p_ca_slot_info, void __user *arg) { int i; static u8 slot_command[8] = {0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}; @@ -238,19 +238,19 @@ static int ca_get_slot_info(struct dst_state *state, struct ca_slot_info *p_ca_s } else p_ca_slot_info->flags = 0; - if (copy_to_user((struct ca_slot_info *)arg, p_ca_slot_info, sizeof (struct ca_slot_info))) + if (copy_to_user(arg, p_ca_slot_info, sizeof (struct ca_slot_info))) return -EFAULT; return 0; } -static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message, void *arg) +static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message, void __user *arg) { u8 i = 0; u32 command = 0; - if (copy_from_user(p_ca_message, (void *)arg, sizeof (struct ca_msg))) + if (copy_from_user(p_ca_message, arg, sizeof (struct ca_msg))) return -EFAULT; if (p_ca_message->msg) { @@ -266,7 +266,7 @@ static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message, switch (command) { case CA_APP_INFO: memcpy(p_ca_message->msg, state->messages, 128); - if (copy_to_user((void *)arg, p_ca_message, sizeof (struct ca_msg)) ) + if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) ) return -EFAULT; break; } @@ -315,7 +315,7 @@ static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 l return 0; } -u32 asn_1_decode(u8 *asn_1_array) +static u32 asn_1_decode(u8 *asn_1_array) { u8 length_field = 0, word_count = 0, count = 0; u32 length = 0; @@ -400,7 +400,7 @@ static int dst_check_ca_pmt(struct dst_state *state, struct ca_msg *p_ca_message return 0; } -static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, void *arg) +static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, void __user *arg) { int i = 0; unsigned int ca_message_header_len; @@ -414,7 +414,7 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, } dprintk(verbose, DST_CA_DEBUG, 1, " "); - if (copy_from_user(p_ca_message, (void *)arg, sizeof (struct ca_msg))) + if (copy_from_user(p_ca_message, arg, sizeof (struct ca_msg))) return -EFAULT; if (p_ca_message->msg) { @@ -461,13 +461,14 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, return 0; } -static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) +static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long ioctl_arg) { struct dvb_device* dvbdev = (struct dvb_device*) file->private_data; struct dst_state* state = (struct dst_state*) dvbdev->priv; struct ca_slot_info *p_ca_slot_info; struct ca_caps *p_ca_caps; struct ca_msg *p_ca_message; + void __user *arg = (void __user *)ioctl_arg; if ((p_ca_message = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) { dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure"); @@ -583,7 +584,7 @@ static int dst_ca_write(struct file *file, const char __user *buffer, size_t len static struct file_operations dst_ca_fops = { .owner = THIS_MODULE, - .ioctl = (void *)dst_ca_ioctl, + .ioctl = dst_ca_ioctl, .open = dst_ca_open, .release = dst_ca_release, .read = dst_ca_read, -- cgit v1.2.3 From f630558dfbd47301c2ce30f7e4acd2817a7455ac Mon Sep 17 00:00:00 2001 From: Perceval Anichini Date: Tue, 8 Nov 2005 21:35:19 -0800 Subject: [PATCH] dvb: dst: fix memory leaks fix memory leaks Signed-off-by: Perceval Anichini Signed-off-by: Manu Abraham Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/bt8xx/dst_ca.c | 52 ++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c index 492e829fe02..f77fda77b63 100644 --- a/drivers/media/dvb/bt8xx/dst_ca.c +++ b/drivers/media/dvb/bt8xx/dst_ca.c @@ -407,6 +407,7 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, u32 command = 0; struct ca_msg *hw_buffer; + int result = 0; if ((hw_buffer = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) { dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure"); @@ -414,8 +415,11 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, } dprintk(verbose, DST_CA_DEBUG, 1, " "); - if (copy_from_user(p_ca_message, arg, sizeof (struct ca_msg))) - return -EFAULT; + if (copy_from_user(p_ca_message, (void *)arg, sizeof (struct ca_msg))) { + result = -EFAULT; + goto free_mem_and_exit; + } + if (p_ca_message->msg) { ca_message_header_len = p_ca_message->length; /* Restore it back when you are done */ @@ -434,7 +438,8 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, dprintk(verbose, DST_CA_DEBUG, 1, "Command = SEND_CA_PMT"); if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) { // code simplification started dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT Failed !"); - return -1; + result = -1; + goto free_mem_and_exit; } dprintk(verbose, DST_CA_INFO, 1, " -->CA_PMT Success !"); break; @@ -443,7 +448,8 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, /* Have to handle the 2 basic types of cards here */ if ((dst_check_ca_pmt(state, p_ca_message, hw_buffer)) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT_REPLY Failed !"); - return -1; + result = -1; + goto free_mem_and_exit; } dprintk(verbose, DST_CA_INFO, 1, " -->CA_PMT_REPLY Success !"); break; @@ -452,13 +458,17 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, if ((ca_get_app_info(state)) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->CA_APP_INFO_ENQUIRY Failed !"); - return -1; + result = -1; + goto free_mem_and_exit; } dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !"); break; } } - return 0; +free_mem_and_exit: + kfree (hw_buffer); + + return result; } static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long ioctl_arg) @@ -469,6 +479,7 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd struct ca_caps *p_ca_caps; struct ca_msg *p_ca_message; void __user *arg = (void __user *)ioctl_arg; + int result = 0; if ((p_ca_message = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) { dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure"); @@ -488,14 +499,16 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd dprintk(verbose, DST_CA_INFO, 1, " Sending message"); if ((ca_send_message(state, p_ca_message, arg)) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SEND_MSG Failed !"); - return -1; + result = -1; + goto free_mem_and_exit; } break; case CA_GET_MSG: dprintk(verbose, DST_CA_INFO, 1, " Getting message"); if ((ca_get_message(state, p_ca_message, arg)) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_MSG Failed !"); - return -1; + result = -1; + goto free_mem_and_exit; } dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_MSG Success !"); break; @@ -508,7 +521,8 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd dprintk(verbose, DST_CA_INFO, 1, " Getting Slot info"); if ((ca_get_slot_info(state, p_ca_slot_info, arg)) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_SLOT_INFO Failed !"); - return -1; + result = -1; + goto free_mem_and_exit; } dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_SLOT_INFO Success !"); break; @@ -516,7 +530,8 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd dprintk(verbose, DST_CA_INFO, 1, " Getting Slot capabilities"); if ((ca_get_slot_caps(state, p_ca_caps, arg)) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_CAP Failed !"); - return -1; + result = -1; + goto free_mem_and_exit; } dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_CAP Success !"); break; @@ -524,7 +539,8 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd dprintk(verbose, DST_CA_INFO, 1, " Getting descrambler description"); if ((ca_get_slot_descr(state, p_ca_message, arg)) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_DESCR_INFO Failed !"); - return -1; + result = -1; + goto free_mem_and_exit; } dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_DESCR_INFO Success !"); break; @@ -532,7 +548,8 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd dprintk(verbose, DST_CA_INFO, 1, " Setting descrambler"); if ((ca_set_slot_descr()) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SET_DESCR Failed !"); - return -1; + result = -1; + goto free_mem_and_exit; } dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_DESCR Success !"); break; @@ -540,14 +557,19 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd dprintk(verbose, DST_CA_INFO, 1, " Setting PID"); if ((ca_set_pid()) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SET_PID Failed !"); - return -1; + result = -1; + goto free_mem_and_exit; } dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_PID Success !"); default: - return -EOPNOTSUPP; + result = -EOPNOTSUPP; }; + free_mem_and_exit: + kfree (p_ca_message); + kfree (p_ca_slot_info); + kfree (p_ca_caps); - return 0; + return result; } static int dst_ca_open(struct inode *inode, struct file *file) -- cgit v1.2.3 From 4c09aa72b60f30650527afb384c1b3b1cb56aeea Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 8 Nov 2005 21:35:20 -0800 Subject: [PATCH] dvb: dst: fix broken support for vp-3040 TS204 fixes broken support for vp-3040 TS204 Thanks-to: Lee Hammerton Signed-off-by: Manu Abraham Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/bt8xx/dst.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 6f9e5c16803..418ffbbef96 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -905,10 +905,6 @@ static int dst_get_device_id(struct dst_state *state) state->dst_type = use_dst_type; dst_type_flags_print(state->type_flags); - if (state->type_flags & DST_TYPE_HAS_TS204) { - dst_packsize(state, 204); - } - return 0; } @@ -940,6 +936,9 @@ static int dst_probe(struct dst_state *state) if (dst_get_tuner_info(state) < 0) dprintk(verbose, DST_INFO, 1, "Tuner: Unsupported command"); } + if (state->type_flags & DST_TYPE_HAS_TS204) { + dst_packsize(state, 204); + } if (state->type_flags & DST_TYPE_HAS_FW_BUILD) { if (dst_fw_ver(state) < 0) { dprintk(verbose, DST_INFO, 1, "FW: Unsupported command"); -- cgit v1.2.3 From f5648e8a68daec5fd1c42c1500c662967adb8f6c Mon Sep 17 00:00:00 2001 From: Tom Hughes Date: Tue, 8 Nov 2005 21:35:22 -0800 Subject: [PATCH] dvb: dst: fix DST DVB-S get_frequency fix DST DVB-S get_frequency - fixes a bug that caused the returned frequency to wrong Signed-off-by: Tom Hughes Signed-off-by: Manu Abraham Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/bt8xx/dst.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 418ffbbef96..bc833a55438 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -1092,7 +1092,13 @@ static int dst_get_tuna(struct dst_state *state) } if (state->rx_tuna[2] == 0 && state->rx_tuna[3] == 0) return 0; - state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 8) + state->rx_tuna[3]; + + if (state->dst_type == DST_TYPE_IS_SAT) { + state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 8) + state->rx_tuna[3]; + } else { + state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 16) + (state->rx_tuna[3] << 8) + state->rx_tuna[4]; + } + state->decode_freq = state->decode_freq * 1000; state->decode_lock = 1; state->diseq_flags |= HAS_LOCK; -- cgit v1.2.3 From 4fbbc7ee591ab19707d12e2f86a1ae11f7195423 Mon Sep 17 00:00:00 2001 From: Perceval Anichini Date: Tue, 8 Nov 2005 21:35:23 -0800 Subject: [PATCH] dvb: dst: remove redundant checksum calculation removes the redundant checksum calculation, which was also exported from the dst.c module Signed-off-by: Perceval Anichini Signed-off-by: Manu Abraham Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/bt8xx/dst_ca.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c index f77fda77b63..16645e06dea 100644 --- a/drivers/media/dvb/bt8xx/dst_ca.c +++ b/drivers/media/dvb/bt8xx/dst_ca.c @@ -69,26 +69,12 @@ static int ca_set_pid(void) } -static int put_checksum(u8 *check_string, int length) +static void put_checksum(u8 *check_string, int length) { - u8 i = 0, checksum = 0; - - dprintk(verbose, DST_CA_DEBUG, 1, " ========================= Checksum calculation ==========================="); - dprintk(verbose, DST_CA_DEBUG, 1, " String Length=[0x%02x]", length); - dprintk(verbose, DST_CA_DEBUG, 1, " String=["); - - while (i < length) { - dprintk(verbose, DST_CA_DEBUG, 0, " %02x", check_string[i]); - checksum += check_string[i]; - i++; - } - dprintk(verbose, DST_CA_DEBUG, 0, " ]\n"); - dprintk(verbose, DST_CA_DEBUG, 1, "Sum=[%02x]\n", checksum); - check_string[length] = ~checksum + 1; - dprintk(verbose, DST_CA_DEBUG, 1, " Checksum=[%02x]", check_string[length]); - dprintk(verbose, DST_CA_DEBUG, 1, " =========================================================================="); - - return 0; + dprintk(verbose, DST_CA_DEBUG, 1, " Computing string checksum."); + dprintk(verbose, DST_CA_DEBUG, 1, " -> string length : 0x%02x", length); + check_string[length] = dst_check_sum (check_string, length); + dprintk(verbose, DST_CA_DEBUG, 1, " -> checksum : 0x%02x", check_string[length]); } static int dst_ci_command(struct dst_state* state, u8 * data, u8 *ca_string, u8 len, int read) -- cgit v1.2.3 From 5c15c0b4fa850543b8ccfcf93686d24456cc384d Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 8 Nov 2005 21:35:24 -0800 Subject: [PATCH] dvb: dst: Fix possible buffer overflow Fixes a possible buffer overflow due to reading more than 8 bytes into an 8 byte long array Thanks to Perceval Anichini for pointing out the bug. Signed-off-by: Manu Abraham Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/bt8xx/dst_ca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c index 16645e06dea..38c728945bf 100644 --- a/drivers/media/dvb/bt8xx/dst_ca.c +++ b/drivers/media/dvb/bt8xx/dst_ca.c @@ -196,7 +196,7 @@ static int ca_get_slot_info(struct dst_state *state, struct ca_slot_info *p_ca_s int i; static u8 slot_command[8] = {0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}; - u8 *slot_info = state->rxbuffer; + u8 *slot_info = state->messages; put_checksum(&slot_command[0], 7); if ((dst_put_ci(state, slot_command, sizeof (slot_command), slot_info, GET_REPLY)) < 0) { -- cgit v1.2.3 From b90ed914e513a6ad6184f7a46a0df0888dcfc177 Mon Sep 17 00:00:00 2001 From: Johannes Stezenbach Date: Tue, 8 Nov 2005 21:35:25 -0800 Subject: [PATCH] dvb: Fix integer overflow bug Fix integer overflow bug in read_signal_strength() reported by Anthony Leclerc. Signed-off-by: Johannes Stezenbach Signed-off-by: Michael Krufky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/frontends/or51132.c | 7 ++++++- drivers/media/dvb/frontends/or51211.c | 8 ++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c index fc74c40d647..78bded861d0 100644 --- a/drivers/media/dvb/frontends/or51132.c +++ b/drivers/media/dvb/frontends/or51132.c @@ -468,6 +468,7 @@ static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength) unsigned char snd_buf[2]; u8 rcvr_stat; u16 snr_equ; + u32 signal_strength; int usK; snd_buf[0]=0x04; @@ -503,7 +504,11 @@ static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength) usK = (rcvr_stat & 0x10) ? 3 : 0; /* The value reported back from the frontend will be FFFF=100% 0000=0% */ - *strength = (((8952 - i20Log10(snr_equ) - usK*100)/3+5)*65535)/1000; + signal_strength = (((8952 - i20Log10(snr_equ) - usK*100)/3+5)*65535)/1000; + if (signal_strength > 0xffff) + *strength = 0xffff; + else + *strength = signal_strength; dprintk("read_signal_strength %i\n",*strength); return 0; diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c index 8a9db23dd1b..531f76246e5 100644 --- a/drivers/media/dvb/frontends/or51211.c +++ b/drivers/media/dvb/frontends/or51211.c @@ -339,6 +339,7 @@ static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength) u8 rec_buf[2]; u8 snd_buf[4]; u8 snr_equ; + u32 signal_strength; /* SNR after Equalizer */ snd_buf[0] = 0x04; @@ -358,8 +359,11 @@ static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength) snr_equ = rec_buf[0] & 0xff; /* The value reported back from the frontend will be FFFF=100% 0000=0% */ - *strength = (((5334 - i20Log10(snr_equ))/3+5)*65535)/1000; - + signal_strength = (((5334 - i20Log10(snr_equ))/3+5)*65535)/1000; + if (signal_strength > 0xffff) + *strength = 0xffff; + else + *strength = signal_strength; dprintk("read_signal_strength %i\n",*strength); return 0; -- cgit v1.2.3 From 83b75b049be981e579ba2cb88aa9bf3534bbbdb1 Mon Sep 17 00:00:00 2001 From: NooneImportant Date: Tue, 8 Nov 2005 21:35:27 -0800 Subject: [PATCH] dvb: let other frontends support FE_DISHNETWORK_SEND_LEGACY_CMD Add support to FE_DISHNETWORK_SEND_LEGACY_CMD code to support other frontends besides stv0299. The generic code is a fallback in the case that it doesn't work for some specific frontends (again stv0299 being a good example). Signed-off-by: NooneImportant Signed-off-by: Johannes Stezenbach Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/dvb-core/dvb_frontend.c | 97 +++++++++++++++++++++++++++++++ drivers/media/dvb/dvb-core/dvb_frontend.h | 3 + drivers/media/dvb/frontends/stv0299.c | 38 ++---------- 3 files changed, 104 insertions(+), 34 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index a8bc84240b5..e36dbd9c4cc 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -577,6 +577,49 @@ static void dvb_frontend_stop(struct dvb_frontend *fe) fepriv->thread_pid); } +s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime) +{ + return ((curtime.tv_usec < lasttime.tv_usec) ? + 1000000 - lasttime.tv_usec + curtime.tv_usec : + curtime.tv_usec - lasttime.tv_usec); +} +EXPORT_SYMBOL(timeval_usec_diff); + +static inline void timeval_usec_add(struct timeval *curtime, u32 add_usec) +{ + curtime->tv_usec += add_usec; + if (curtime->tv_usec >= 1000000) { + curtime->tv_usec -= 1000000; + curtime->tv_sec++; + } +} + +/* + * Sleep until gettimeofday() > waketime + add_usec + * This needs to be as precise as possible, but as the delay is + * usually between 2ms and 32ms, it is done using a scheduled msleep + * followed by usleep (normally a busy-wait loop) for the remainder + */ +void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec) +{ + struct timeval lasttime; + s32 delta, newdelta; + + timeval_usec_add(waketime, add_usec); + + do_gettimeofday(&lasttime); + delta = timeval_usec_diff(lasttime, *waketime); + if (delta > 2500) { + msleep((delta - 1500) / 1000); + do_gettimeofday(&lasttime); + newdelta = timeval_usec_diff(lasttime, *waketime); + delta = (newdelta > delta) ? 0 : newdelta; + } + if (delta > 0) + udelay(delta); +} +EXPORT_SYMBOL(dvb_frontend_sleep_until); + static int dvb_frontend_start(struct dvb_frontend *fe) { int ret; @@ -728,6 +771,60 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned int) parg); fepriv->state = FESTATE_DISEQC; fepriv->status = 0; + } else if (fe->ops->set_voltage) { + /* + * NOTE: This is a fallback condition. Some frontends + * (stv0299 for instance) take longer than 8msec to + * respond to a set_voltage command. Those switches + * need custom routines to switch properly. For all + * other frontends, the following shoule work ok. + * Dish network legacy switches (as used by Dish500) + * are controlled by sending 9-bit command words + * spaced 8msec apart. + * the actual command word is switch/port dependant + * so it is up to the userspace application to send + * the right command. + * The command must always start with a '0' after + * initialization, so parg is 8 bits and does not + * include the initialization or start bit + */ + unsigned int cmd = ((unsigned int) parg) << 1; + struct timeval nexttime; + struct timeval tv[10]; + int i; + u8 last = 1; + if (dvb_frontend_debug) + printk("%s switch command: 0x%04x\n", __FUNCTION__, cmd); + do_gettimeofday(&nexttime); + if (dvb_frontend_debug) + memcpy(&tv[0], &nexttime, sizeof(struct timeval)); + /* before sending a command, initialize by sending + * a 32ms 18V to the switch + */ + fe->ops->set_voltage(fe, SEC_VOLTAGE_18); + dvb_frontend_sleep_until(&nexttime, 32000); + + for (i = 0; i < 9; i++) { + if (dvb_frontend_debug) + do_gettimeofday(&tv[i + 1]); + if ((cmd & 0x01) != last) { + /* set voltage to (last ? 13V : 18V) */ + fe->ops->set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18); + last = (last) ? 0 : 1; + } + cmd = cmd >> 1; + if (i != 8) + dvb_frontend_sleep_until(&nexttime, 8000); + } + if (dvb_frontend_debug) { + printk("%s(%d): switch delay (should be 32k followed by all 8k\n", + __FUNCTION__, fe->dvb->num); + for (i = 1; i < 10; i++) + printk("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i])); + } + err = 0; + fepriv->state = FESTATE_DISEQC; + fepriv->status = 0; } break; diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index 9c2c1d1136b..348c9b0b988 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -101,4 +101,7 @@ extern int dvb_register_frontend(struct dvb_adapter* dvb, extern int dvb_unregister_frontend(struct dvb_frontend* fe); +extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec); +extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime); + #endif diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c index b1876618a37..ae00d7a40d7 100644 --- a/drivers/media/dvb/frontends/stv0299.c +++ b/drivers/media/dvb/frontends/stv0299.c @@ -387,36 +387,6 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag }; } -static inline s32 stv0299_calc_usec_delay (struct timeval lasttime, struct timeval curtime) -{ - return ((curtime.tv_usec < lasttime.tv_usec) ? - 1000000 - lasttime.tv_usec + curtime.tv_usec : - curtime.tv_usec - lasttime.tv_usec); -} - -static void stv0299_sleep_until (struct timeval *waketime, u32 add_usec) -{ - struct timeval lasttime; - s32 delta, newdelta; - - waketime->tv_usec += add_usec; - if (waketime->tv_usec >= 1000000) { - waketime->tv_usec -= 1000000; - waketime->tv_sec++; - } - - do_gettimeofday (&lasttime); - delta = stv0299_calc_usec_delay (lasttime, *waketime); - if (delta > 2500) { - msleep ((delta - 1500) / 1000); - do_gettimeofday (&lasttime); - newdelta = stv0299_calc_usec_delay (lasttime, *waketime); - delta = (newdelta > delta) ? 0 : newdelta; - } - if (delta > 0) - udelay (delta); -} - static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd) { struct stv0299_state* state = fe->demodulator_priv; @@ -444,7 +414,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd) memcpy (&tv[0], &nexttime, sizeof (struct timeval)); stv0299_writeregI (state, 0x0c, reg0x0c | 0x50); /* set LNB to 18V */ - stv0299_sleep_until (&nexttime, 32000); + dvb_frontend_sleep_until(&nexttime, 32000); for (i=0; i<9; i++) { if (debug_legacy_dish_switch) @@ -458,13 +428,13 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd) cmd = cmd >> 1; if (i != 8) - stv0299_sleep_until (&nexttime, 8000); + dvb_frontend_sleep_until(&nexttime, 8000); } if (debug_legacy_dish_switch) { printk ("%s(%d): switch delay (should be 32k followed by all 8k\n", __FUNCTION__, fe->dvb->num); - for (i=1; i < 10; i++) - printk ("%d: %d\n", i, stv0299_calc_usec_delay (tv[i-1] , tv[i])); + for (i = 1; i < 10; i++) + printk ("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i])); } return 0; -- cgit v1.2.3 From 3528cc4e731b098b5743f8f91516e2e6c01dd1ce Mon Sep 17 00:00:00 2001 From: Andrew de Quincy Date: Tue, 8 Nov 2005 21:35:28 -0800 Subject: [PATCH] dvb: Remove broken stv0299 enhanced tuning code Remove broken stv0299 enhanced tuning code Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 1 - drivers/media/dvb/frontends/stv0299.c | 53 +++++------------------ drivers/media/dvb/frontends/stv0299.h | 3 -- drivers/media/dvb/ttpci/av7110.c | 2 - drivers/media/dvb/ttpci/budget-av.c | 2 - drivers/media/dvb/ttpci/budget-ci.c | 2 - drivers/media/dvb/ttpci/budget-patch.c | 1 - drivers/media/dvb/ttpci/budget.c | 2 - drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | 1 - 9 files changed, 10 insertions(+), 57 deletions(-) diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 47e28b0ee95..bf5651b98bb 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -234,7 +234,6 @@ static struct stv0299_config samsung_tbmu24112_config = { .inittab = samsung_tbmu24112_inittab, .mclk = 88000000UL, .invert = 0, - .enhanced_tuning = 0, .skip_reinit = 0, .lock_output = STV0229_LOCKOUTPUT_LK, .volt13_op0_op1 = STV0299_VOLT13_OP1, diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c index ae00d7a40d7..35dc8439be1 100644 --- a/drivers/media/dvb/frontends/stv0299.c +++ b/drivers/media/dvb/frontends/stv0299.c @@ -553,49 +553,16 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par if (state->config->invert) invval = (~invval) & 1; stv0299_writeregI(state, 0x0c, (stv0299_readreg(state, 0x0c) & 0xfe) | invval); - if (state->config->enhanced_tuning) { - /* check if we should do a finetune */ - int frequency_delta = p->frequency - state->tuner_frequency; - int minmax = p->u.qpsk.symbol_rate / 2000; - if (minmax < 5000) minmax = 5000; - - if ((frequency_delta > -minmax) && (frequency_delta < minmax) && (frequency_delta != 0) && - (state->fec_inner == p->u.qpsk.fec_inner) && - (state->symbol_rate == p->u.qpsk.symbol_rate)) { - int Drot_freq = (frequency_delta << 16) / (state->config->mclk / 1000); - - // zap the derotator registers first - stv0299_writeregI(state, 0x22, 0x00); - stv0299_writeregI(state, 0x23, 0x00); - - // now set them as we want - stv0299_writeregI(state, 0x22, Drot_freq >> 8); - stv0299_writeregI(state, 0x23, Drot_freq); - } else { - /* A "normal" tune is requested */ - stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */ - state->config->pll_set(fe, state->i2c, p); - stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */ - - stv0299_writeregI(state, 0x32, 0x80); - stv0299_writeregI(state, 0x22, 0x00); - stv0299_writeregI(state, 0x23, 0x00); - stv0299_writeregI(state, 0x32, 0x19); - stv0299_set_symbolrate (fe, p->u.qpsk.symbol_rate); - stv0299_set_FEC (state, p->u.qpsk.fec_inner); - } - } else { - stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */ - state->config->pll_set(fe, state->i2c, p); - stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */ - - stv0299_set_FEC (state, p->u.qpsk.fec_inner); - stv0299_set_symbolrate (fe, p->u.qpsk.symbol_rate); - stv0299_writeregI(state, 0x22, 0x00); - stv0299_writeregI(state, 0x23, 0x00); - stv0299_readreg (state, 0x23); - stv0299_writeregI(state, 0x12, 0xb9); - } + stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */ + state->config->pll_set(fe, state->i2c, p); + stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */ + + stv0299_set_FEC (state, p->u.qpsk.fec_inner); + stv0299_set_symbolrate (fe, p->u.qpsk.symbol_rate); + stv0299_writeregI(state, 0x22, 0x00); + stv0299_writeregI(state, 0x23, 0x00); + stv0299_readreg (state, 0x23); + stv0299_writeregI(state, 0x12, 0xb9); state->tuner_frequency = p->frequency; state->fec_inner = p->u.qpsk.fec_inner; diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h index d0c4484861e..9af3d71c89d 100644 --- a/drivers/media/dvb/frontends/stv0299.h +++ b/drivers/media/dvb/frontends/stv0299.h @@ -73,9 +73,6 @@ struct stv0299_config /* does the inversion require inversion? */ u8 invert:1; - /* Should the enhanced tuning code be used? */ - u8 enhanced_tuning:1; - /* Skip reinitialisation? */ u8 skip_reinit:1; diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 22b203f8ff2..820eea29432 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -1644,7 +1644,6 @@ static struct stv0299_config alps_bsru6_config = { .inittab = alps_bsru6_inittab, .mclk = 88000000UL, .invert = 1, - .enhanced_tuning = 0, .skip_reinit = 0, .lock_output = STV0229_LOCKOUTPUT_1, .volt13_op0_op1 = STV0299_VOLT13_OP1, @@ -1721,7 +1720,6 @@ static struct stv0299_config alps_bsbe1_config = { .inittab = alps_bsbe1_inittab, .mclk = 88000000UL, .invert = 1, - .enhanced_tuning = 0, .skip_reinit = 0, .min_delay_ms = 100, .set_symbol_rate = alps_bsru6_set_symbol_rate, diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 7692cd23f83..ac108102b67 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -531,7 +531,6 @@ static struct stv0299_config typhoon_config = { .inittab = typhoon_cinergy1200s_inittab, .mclk = 88000000UL, .invert = 0, - .enhanced_tuning = 0, .skip_reinit = 0, .lock_output = STV0229_LOCKOUTPUT_1, .volt13_op0_op1 = STV0299_VOLT13_OP0, @@ -546,7 +545,6 @@ static struct stv0299_config cinergy_1200s_config = { .inittab = typhoon_cinergy1200s_inittab, .mclk = 88000000UL, .invert = 0, - .enhanced_tuning = 0, .skip_reinit = 0, .lock_output = STV0229_LOCKOUTPUT_0, .volt13_op0_op1 = STV0299_VOLT13_OP0, diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 51c30ba6814..9263ed686fd 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -580,7 +580,6 @@ static struct stv0299_config alps_bsru6_config = { .inittab = alps_bsru6_inittab, .mclk = 88000000UL, .invert = 1, - .enhanced_tuning = 0, .skip_reinit = 0, .lock_output = STV0229_LOCKOUTPUT_1, .volt13_op0_op1 = STV0299_VOLT13_OP1, @@ -710,7 +709,6 @@ static struct stv0299_config philips_su1278_tt_config = { .inittab = philips_su1278_tt_inittab, .mclk = 64000000UL, .invert = 0, - .enhanced_tuning = 1, .skip_reinit = 1, .lock_output = STV0229_LOCKOUTPUT_1, .volt13_op0_op1 = STV0299_VOLT13_OP1, diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c index b1f21ef0e3b..8ee4ac5b536 100644 --- a/drivers/media/dvb/ttpci/budget-patch.c +++ b/drivers/media/dvb/ttpci/budget-patch.c @@ -379,7 +379,6 @@ static struct stv0299_config alps_bsru6_config = { .inittab = alps_bsru6_inittab, .mclk = 88000000UL, .invert = 1, - .enhanced_tuning = 0, .skip_reinit = 0, .lock_output = STV0229_LOCKOUTPUT_1, .volt13_op0_op1 = STV0299_VOLT13_OP1, diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 0f6ead848e4..ba308349ac9 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -360,7 +360,6 @@ static struct stv0299_config alps_bsru6_config = { .inittab = alps_bsru6_inittab, .mclk = 88000000UL, .invert = 1, - .enhanced_tuning = 0, .skip_reinit = 0, .lock_output = STV0229_LOCKOUTPUT_1, .volt13_op0_op1 = STV0299_VOLT13_OP1, @@ -436,7 +435,6 @@ static struct stv0299_config alps_bsbe1_config = { .inittab = alps_bsbe1_inittab, .mclk = 88000000UL, .invert = 1, - .enhanced_tuning = 0, .skip_reinit = 0, .min_delay_ms = 100, .set_symbol_rate = alps_bsru6_set_symbol_rate, diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index d200ab0ad9e..2d519982ead 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -1335,7 +1335,6 @@ static struct stv0299_config alps_stv0299_config = { .inittab = alps_bsru6_inittab, .mclk = 88000000UL, .invert = 1, - .enhanced_tuning = 0, .skip_reinit = 0, .lock_output = STV0229_LOCKOUTPUT_1, .volt13_op0_op1 = STV0299_VOLT13_OP1, -- cgit v1.2.3 From f7b67195ea571b8540ac79daf27f5932ec40c098 Mon Sep 17 00:00:00 2001 From: Andrew de Quincey Date: Tue, 8 Nov 2005 21:35:29 -0800 Subject: [PATCH] dvb: Remove DEBUG_LOCKLOSS stuff Remove DEBUG_LOCKLOSS stuff - as the problem has been found and resolved Signed-off-by: Andrew de Quincey Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/dvb-core/dvb_frontend.c | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index e36dbd9c4cc..6ffa6b21636 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -42,8 +42,6 @@ #include "dvb_frontend.h" #include "dvbdev.h" -// #define DEBUG_LOCKLOSS 1 - static int dvb_frontend_debug; static int dvb_shutdown_timeout = 5; static int dvb_force_auto_inversion; @@ -438,25 +436,6 @@ static int dvb_frontend_thread(void *data) if (s & FE_HAS_LOCK) continue; else { /* if we _WERE_ tuned, but now don't have a lock */ -#ifdef DEBUG_LOCKLOSS - /* first of all try setting the tone again if it was on - this - * sometimes works around problems with noisy power supplies */ - if (fe->ops->set_tone && (fepriv->tone == SEC_TONE_ON)) { - fe->ops->set_tone(fe, fepriv->tone); - mdelay(100); - s = 0; - fe->ops->read_status(fe, &s); - if (s & FE_HAS_LOCK) { - printk("DVB%i: Lock was lost, but regained by setting " - "the tone. This may indicate your power supply " - "is noisy/slightly incompatable with this DVB-S " - "adapter\n", fe->dvb->num); - fepriv->state = FESTATE_TUNED; - continue; - } - } -#endif - /* some other reason for losing the lock - start zigzagging */ fepriv->state = FESTATE_ZIGZAG_FAST; fepriv->started_auto_step = fepriv->auto_step; check_wrapped = 0; -- cgit v1.2.3 From c0b11b914de27e0e82b5311cf9b498a1b008b591 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:35:32 -0800 Subject: [PATCH] dvb: Add support for Air2PC/AirStar 2 ATSC 3rd generation (HD5000) Added support for Air2PC/AirStar 2 ATSC 3rd generation (HD5000) Signed-off-by: Taylor Jacob Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 53 +++++++++++++++++++++++++++++++ drivers/media/dvb/b2c2/flexcop-misc.c | 1 + drivers/media/dvb/b2c2/flexcop-reg.h | 1 + drivers/media/dvb/b2c2/flexcop.c | 1 + drivers/media/dvb/frontends/dvb-pll.c | 2 +- drivers/media/dvb/frontends/lgdt330x.c | 15 +++++++-- drivers/media/dvb/frontends/lgdt330x.h | 4 +++ 7 files changed, 74 insertions(+), 3 deletions(-) diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index bf5651b98bb..a35330315f6 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -13,6 +13,8 @@ #include "bcm3510.h" #include "stv0297.h" #include "mt312.h" +#include "lgdt330x.h" +#include "dvb-pll.h" /* lnb control */ @@ -295,6 +297,52 @@ static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct fir return request_firmware(fw, name, fc->dev); } +static int lgdt3303_pll_set(struct dvb_frontend* fe, + struct dvb_frontend_parameters* params) +{ + struct flexcop_device *fc = fe->dvb->priv; + u8 buf[4]; + struct i2c_msg msg = + { .addr = 0x61, .flags = 0, .buf = buf, .len = 4 }; + int err; + + dvb_pll_configure(&dvb_pll_tdvs_tua6034,buf, params->frequency, 0); + dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n", + __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]); + if ((err = i2c_transfer(&fc->i2c_adap, &msg, 1)) != 1) { + printk(KERN_WARNING "lgdt3303: %s error " + "(addr %02x <- %02x, err = %i)\n", + __FUNCTION__, buf[0], buf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } + + buf[0] = 0x86 | 0x18; + buf[1] = 0x50; + msg.len = 2; + if ((err = i2c_transfer(&fc->i2c_adap, &msg, 1)) != 1) { + printk(KERN_WARNING "lgdt3303: %s error " + "(addr %02x <- %02x, err = %i)\n", + __FUNCTION__, buf[0], buf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } + + return 0; +} + +static struct lgdt330x_config air2pc_atsc_hd5000_config = { + .demod_address = 0x59, + .demod_chip = LGDT3303, + .serial_mpeg = 0x04, + .pll_set = lgdt3303_pll_set, + .clock_polarity_flip = 1, +}; + static struct nxt2002_config samsung_tbmv_config = { .demod_address = 0x0a, .request_firmware = flexcop_fe_request_firmware, @@ -457,6 +505,11 @@ int flexcop_frontend_init(struct flexcop_device *fc) fc->dev_type = FC_AIR_ATSC2; info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address); } else + /* try the air atsc 3nd generation (lgdt3303) */ + if ((fc->fe = lgdt330x_attach(&air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) { + fc->dev_type = FC_AIR_ATSC3; + info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address); + } else /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */ if ((fc->fe = bcm3510_attach(&air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) { fc->dev_type = FC_AIR_ATSC1; diff --git a/drivers/media/dvb/b2c2/flexcop-misc.c b/drivers/media/dvb/b2c2/flexcop-misc.c index 3a08d38b318..62282d8dbfa 100644 --- a/drivers/media/dvb/b2c2/flexcop-misc.c +++ b/drivers/media/dvb/b2c2/flexcop-misc.c @@ -51,6 +51,7 @@ const char *flexcop_device_names[] = { "Sky2PC/SkyStar 2 DVB-S", "Sky2PC/SkyStar 2 DVB-S (old version)", "Cable2PC/CableStar 2 DVB-C", + "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)", }; const char *flexcop_bus_names[] = { diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h index 4ae1eb5bfe9..23cc6431e2b 100644 --- a/drivers/media/dvb/b2c2/flexcop-reg.h +++ b/drivers/media/dvb/b2c2/flexcop-reg.h @@ -26,6 +26,7 @@ typedef enum { FC_SKY, FC_SKY_OLD, FC_CABLE, + FC_AIR_ATSC3, } flexcop_device_type_t; typedef enum { diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c index 12873d43540..123ed96f6fa 100644 --- a/drivers/media/dvb/b2c2/flexcop.c +++ b/drivers/media/dvb/b2c2/flexcop.c @@ -193,6 +193,7 @@ static void flexcop_reset(struct flexcop_device *fc) v204 = fc->read_ibi_reg(fc,misc_204); v204.misc_204.Per_reset_sig = 0; fc->write_ibi_reg(fc,misc_204,v204); + msleep(1); v204.misc_204.Per_reset_sig = 1; fc->write_ibi_reg(fc,misc_204,v204); } diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 536c35d969b..6668839f947 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -226,7 +226,7 @@ struct dvb_pll_desc dvb_pll_tua6034 = { EXPORT_SYMBOL(dvb_pll_tua6034); /* Infineon TUA6034 - * used in LG Innotek TDVS-H062F + * used in LG TDVS H061F and LG TDVS H062F */ struct dvb_pll_desc dvb_pll_tdvs_tua6034 = { .name = "LG/Infineon TUA6034", diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index 145918877d2..10fc4e7878a 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c @@ -27,6 +27,7 @@ * DViCO FusionHDTV 3 Gold-T * DViCO FusionHDTV 5 Gold * DViCO FusionHDTV 5 Lite + * Air2PC/AirStar 2 ATSC 3rd generation (HD5000) * * TODO: * signal strength always returns 0. @@ -223,6 +224,11 @@ static int lgdt330x_init(struct dvb_frontend* fe) 0x4c, 0x14 }; + static u8 flip_lgdt3303_init_data[] = { + 0x4c, 0x14, + 0x87, 0xf3 + }; + struct lgdt330x_state* state = fe->demodulator_priv; char *chip_name; int err; @@ -235,8 +241,13 @@ static int lgdt330x_init(struct dvb_frontend* fe) break; case LGDT3303: chip_name = "LGDT3303"; - err = i2c_write_demod_bytes(state, lgdt3303_init_data, - sizeof(lgdt3303_init_data)); + if (state->config->clock_polarity_flip) { + err = i2c_write_demod_bytes(state, flip_lgdt3303_init_data, + sizeof(flip_lgdt3303_init_data)); + } else { + err = i2c_write_demod_bytes(state, lgdt3303_init_data, + sizeof(lgdt3303_init_data)); + } break; default: chip_name = "undefined"; diff --git a/drivers/media/dvb/frontends/lgdt330x.h b/drivers/media/dvb/frontends/lgdt330x.h index e209ba1e47c..2a6529cccf1 100644 --- a/drivers/media/dvb/frontends/lgdt330x.h +++ b/drivers/media/dvb/frontends/lgdt330x.h @@ -47,6 +47,10 @@ struct lgdt330x_config /* Need to set device param for start_dma */ int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured); + + /* Flip the polarity of the mpeg data transfer clock using alternate init data + * This option applies ONLY to LGDT3303 - 0:disabled (default) 1:enabled */ + int clock_polarity_flip; }; extern struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config, -- cgit v1.2.3 From 28fdd7599cb9c6c620caf13bcaea41e2532cb5fd Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 8 Nov 2005 21:35:33 -0800 Subject: [PATCH] dvb: Updated Documentation Updated Documentation Signed-off-by: Manu Abraham Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/dvb/bt8xx.txt | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/Documentation/dvb/bt8xx.txt b/Documentation/dvb/bt8xx.txt index cb63b7a93c8..ac3af17f2b6 100644 --- a/Documentation/dvb/bt8xx.txt +++ b/Documentation/dvb/bt8xx.txt @@ -33,20 +33,23 @@ TwinHan (dst) are loaded automatically by the dvb-bt8xx device driver. -------------------------- $ modprobe bttv (normally bttv is being loaded automatically by kmod) - $ modprobe dvb-bt8xx (or just place dvb-bt8xx in /etc/modules for automatic loading) + $ modprobe dvb-bt8xx + +(or just place dvb-bt8xx in /etc/modules for automatic loading) 3b) TwinHan and Clones -------------------------- - $ modprobe bttv i2c_hw=1 card=0x71 + $ modprobe bttv card=0x71 $ modprobe dvb-bt8xx $ modprobe dst The value 0x71 will override the PCI type detection for dvb-bt8xx, -which is necessary for TwinHan cards. +which is necessary for TwinHan cards. Omission of this parameter might result +in a system lockup. -If you're having an older card (blue color circuit) and card=0x71 locks +If you're having an older card (blue color PCB) and card=0x71 locks up your machine, try using 0x68, too. If that does not work, ask on the mailing list. @@ -69,6 +72,38 @@ string' which you can see in your logs e.g. dst_get_device_id: Recognise [DSTMCI] +If you need to sent in bug reports on the dst, please do send in a complete +log with the verbose=4 module parameter. For general usage, the default setting +of verbose=1 is ideal. + + +4) Multiple cards +-------------------------- + +If you happen to be running multiple cards, it would be advisable to load +the bttv module with the card id. This would help to solve any module loading +problems that you might face. + +for example, if you happen to have a Twinhan and clones alongwith a FusionHDTV5 +card + + $ modprobe bttv card=0x71 card=0x87 + +Here the order of the card id is important and should be the same as that of the +physical order of the cards. Here card=0x71 represents the Twinhan and clones +and card=0x87 represents Fusion HDTV5. + +Some examples of card-id's + +Pinnacle Sat 0x5e +Nebula Digi TV 0x68 +PC HDTV 0x70 +Twinhan 0x71 +Fusion HDTV5 0x87 + +For a full list of card-id's, you can see the exported card-id's from +bttv-cards.c in linux-2.6.x/drivers/media/video/bttv.h +If you have problems with this please do ask on the mailing list. -- Authors: Richard Walker, Jamie Honan, Michael Hunold, Manu Abraham -- cgit v1.2.3 From 2cbeddc976645262dbe036d6ec0825f96af70da3 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:35:35 -0800 Subject: [PATCH] dvb: Updated documentation for FusionHDTV Lite cards - Updated documentation for FusionHDTV Lite cards. We must differentiate the bt8xx based "Lite" cards from the cx2388x based "Gold" cards. - Provide location of CARDLIST.bttv Documentation, rather than instructing users to look at bttv.h - Include card decimal id numbers. These are valid for module arguments, and might be easier for some people to remember, rather than hex. Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/dvb/bt8xx.txt | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/Documentation/dvb/bt8xx.txt b/Documentation/dvb/bt8xx.txt index ac3af17f2b6..df6c05453cb 100644 --- a/Documentation/dvb/bt8xx.txt +++ b/Documentation/dvb/bt8xx.txt @@ -1,5 +1,5 @@ -How to get the Nebula, PCTV and Twinhan DST cards working -========================================================= +How to get the Nebula, PCTV, FusionHDTV Lite and Twinhan DST cards working +========================================================================== This class of cards has a bt878a as the PCI interface, and require the bttv driver. @@ -26,11 +26,12 @@ Furthermore you need to enable In general you need to load the bttv driver, which will handle the gpio and i2c communication for us, plus the common dvb-bt8xx device driver. -The frontends for Nebula (nxt6000), Pinnacle PCTV (cx24110) and -TwinHan (dst) are loaded automatically by the dvb-bt8xx device driver. +The frontends for Nebula (nxt6000), Pinnacle PCTV (cx24110), TwinHan (dst), +FusionHDTV DVB-T Lite (mt352) and FusionHDTV5 Lite (lgdt330x) are loaded +automatically by the dvb-bt8xx device driver. -3a) Nebula / Pinnacle PCTV --------------------------- +3a) Nebula / Pinnacle PCTV / FusionHDTV Lite +--------------------------------------------- $ modprobe bttv (normally bttv is being loaded automatically by kmod) $ modprobe dvb-bt8xx @@ -67,8 +68,8 @@ verbose=0 means complete disabling of messages dst_addons takes values 0 and 0x20. A value of 0 means it is a FTA card. 0x20 means it has a Conditional Access slot. -The autodected values are determined bythe cards 'response -string' which you can see in your logs e.g. +The autodetected values are determined by the cards 'response string' +which you can see in your logs e.g. dst_get_device_id: Recognise [DSTMCI] @@ -84,25 +85,29 @@ If you happen to be running multiple cards, it would be advisable to load the bttv module with the card id. This would help to solve any module loading problems that you might face. -for example, if you happen to have a Twinhan and clones alongwith a FusionHDTV5 -card +For example, if you have a Twinhan and Clones card along with a FusionHDTV5 Lite $ modprobe bttv card=0x71 card=0x87 Here the order of the card id is important and should be the same as that of the physical order of the cards. Here card=0x71 represents the Twinhan and clones -and card=0x87 represents Fusion HDTV5. +and card=0x87 represents Fusion HDTV5 Lite. These arguments can also be +specified in decimal, rather than hex: + + $ modprobe bttv card=113 card=135 Some examples of card-id's -Pinnacle Sat 0x5e -Nebula Digi TV 0x68 -PC HDTV 0x70 -Twinhan 0x71 -Fusion HDTV5 0x87 +Pinnacle Sat 0x5e (94) +Nebula Digi TV 0x68 (104) +PC HDTV 0x70 (112) +Twinhan 0x71 (113) +FusionHDTV DVB-T Lite 0x80 (128) +FusionHDTV5 Lite 0x87 (135) + +For a full list of card-id's, see the V4L Documentation within the kernel +source: linux/Documentation/video4linux/CARDLIST.bttv -For a full list of card-id's, you can see the exported card-id's from -bttv-cards.c in linux-2.6.x/drivers/media/video/bttv.h If you have problems with this please do ask on the mailing list. -- -- cgit v1.2.3 From d28d57629ffcd30e11a6085e15ee1327fea60b60 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 8 Nov 2005 21:35:36 -0800 Subject: [PATCH] dvb: dst: protect the read/write commands with a mutex We need to protect the read/write commands with a mutex. Bug reported by Henrik Sjoberg Signed-off-by: Manu Abraham Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/bt8xx/dst.c | 34 +++++++++++++++++++++------------- drivers/media/dvb/bt8xx/dst_ca.c | 17 +++++++++++------ drivers/media/dvb/bt8xx/dst_common.h | 3 +++ 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index bc833a55438..0c718dca09c 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -910,6 +910,7 @@ static int dst_get_device_id(struct dst_state *state) static int dst_probe(struct dst_state *state) { + sema_init(&state->dst_mutex, 1); if ((rdc_8820_reset(state)) < 0) { dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed."); return -1; @@ -960,21 +961,23 @@ static int dst_probe(struct dst_state *state) int dst_command(struct dst_state *state, u8 *data, u8 len) { u8 reply; + + down(&state->dst_mutex); if ((dst_comm_init(state)) < 0) { dprintk(verbose, DST_NOTICE, 1, "DST Communication Initialization Failed."); - return -1; + goto error; } if (write_dst(state, data, len)) { dprintk(verbose, DST_INFO, 1, "Tring to recover.. "); if ((dst_error_recovery(state)) < 0) { dprintk(verbose, DST_ERROR, 1, "Recovery Failed."); - return -1; + goto error; } - return -1; + goto error; } if ((dst_pio_disable(state)) < 0) { dprintk(verbose, DST_ERROR, 1, "PIO Disable Failed."); - return -1; + goto error; } if (state->type_flags & DST_TYPE_HAS_FW_1) udelay(3000); @@ -982,36 +985,41 @@ int dst_command(struct dst_state *state, u8 *data, u8 len) dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. "); if ((dst_error_recovery(state)) < 0) { dprintk(verbose, DST_INFO, 1, "Recovery Failed."); - return -1; + goto error; } - return -1; + goto error; } if (reply != ACK) { dprintk(verbose, DST_INFO, 1, "write not acknowledged 0x%02x ", reply); - return -1; + goto error; } if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3)) - return 0; + goto error; if (state->type_flags & DST_TYPE_HAS_FW_1) udelay(3000); else udelay(2000); if (!dst_wait_dst_ready(state, NO_DELAY)) - return -1; + goto error; if (read_dst(state, state->rxbuffer, FIXED_COMM)) { dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. "); if ((dst_error_recovery(state)) < 0) { dprintk(verbose, DST_INFO, 1, "Recovery failed."); - return -1; + goto error; } - return -1; + goto error; } if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) { dprintk(verbose, DST_INFO, 1, "checksum failure"); - return -1; + goto error; } - + up(&state->dst_mutex); return 0; + +error: + up(&state->dst_mutex); + return -EIO; + } EXPORT_SYMBOL(dst_command); diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c index 38c728945bf..e6541aff399 100644 --- a/drivers/media/dvb/bt8xx/dst_ca.c +++ b/drivers/media/dvb/bt8xx/dst_ca.c @@ -81,36 +81,41 @@ static int dst_ci_command(struct dst_state* state, u8 * data, u8 *ca_string, u8 { u8 reply; + down(&state->dst_mutex); dst_comm_init(state); msleep(65); if (write_dst(state, data, len)) { dprintk(verbose, DST_CA_INFO, 1, " Write not successful, trying to recover"); dst_error_recovery(state); - return -1; + goto error; } if ((dst_pio_disable(state)) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " DST PIO disable failed."); - return -1; + goto error; } if (read_dst(state, &reply, GET_ACK) < 0) { dprintk(verbose, DST_CA_INFO, 1, " Read not successful, trying to recover"); dst_error_recovery(state); - return -1; + goto error; } if (read) { if (! dst_wait_dst_ready(state, LONG_DELAY)) { dprintk(verbose, DST_CA_NOTICE, 1, " 8820 not ready"); - return -1; + goto error; } if (read_dst(state, ca_string, 128) < 0) { /* Try to make this dynamic */ dprintk(verbose, DST_CA_INFO, 1, " Read not successful, trying to recover"); dst_error_recovery(state); - return -1; + goto error; } } - + up(&state->dst_mutex); return 0; + +error: + up(&state->dst_mutex); + return -EIO; } diff --git a/drivers/media/dvb/bt8xx/dst_common.h b/drivers/media/dvb/bt8xx/dst_common.h index 29b5430dbe4..81557f38fe3 100644 --- a/drivers/media/dvb/bt8xx/dst_common.h +++ b/drivers/media/dvb/bt8xx/dst_common.h @@ -22,6 +22,7 @@ #ifndef DST_COMMON_H #define DST_COMMON_H +#include #include #include #include "bt878.h" @@ -119,6 +120,8 @@ struct dst_state { u8 card_info[8]; u8 vendor[8]; u8 board_info[8]; + + struct semaphore dst_mutex; }; struct dst_types { -- cgit v1.2.3 From f1016dec71a4ff3cf49110137c87ab988bd316e6 Mon Sep 17 00:00:00 2001 From: Henrik Sjoberg Date: Tue, 8 Nov 2005 21:35:38 -0800 Subject: [PATCH] dvb: dst: protect dst_write_tuna from simultaneous writes dst_write_tuna needs to be protected against simultaeneous writes, just like dst_command Signed-off-by: Henrik Sjoberg Signed-off-by: Manu Abraham Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/bt8xx/dst.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 0c718dca09c..8977c7a313d 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -1077,7 +1077,7 @@ static int dst_get_tuna(struct dst_state *state) return 0; state->diseq_flags &= ~(HAS_LOCK); if (!dst_wait_dst_ready(state, NO_DELAY)) - return 0; + return -EIO; if (state->type_flags & DST_TYPE_HAS_NEWTUNE) /* how to get variable length reply ???? */ retval = read_dst(state, state->rx_tuna, 10); @@ -1085,22 +1085,21 @@ static int dst_get_tuna(struct dst_state *state) retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM); if (retval < 0) { dprintk(verbose, DST_DEBUG, 1, "read not successful"); - return 0; + return retval; } if (state->type_flags & DST_TYPE_HAS_NEWTUNE) { if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) { dprintk(verbose, DST_INFO, 1, "checksum failure ? "); - return 0; + return -EIO; } } else { if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[2], 7)) { dprintk(verbose, DST_INFO, 1, "checksum failure? "); - return 0; + return -EIO; } } if (state->rx_tuna[2] == 0 && state->rx_tuna[3] == 0) return 0; - if (state->dst_type == DST_TYPE_IS_SAT) { state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 8) + state->rx_tuna[3]; } else { @@ -1129,10 +1128,10 @@ static int dst_write_tuna(struct dvb_frontend *fe) dst_set_voltage(fe, SEC_VOLTAGE_13); } state->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE); - + down(&state->dst_mutex); if ((dst_comm_init(state)) < 0) { dprintk(verbose, DST_DEBUG, 1, "DST Communication initialization failed."); - return -1; + goto error; } if (state->type_flags & DST_TYPE_HAS_NEWTUNE) { state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9); @@ -1144,23 +1143,29 @@ static int dst_write_tuna(struct dvb_frontend *fe) if (retval < 0) { dst_pio_disable(state); dprintk(verbose, DST_DEBUG, 1, "write not successful"); - return retval; + goto werr; } if ((dst_pio_disable(state)) < 0) { dprintk(verbose, DST_DEBUG, 1, "DST PIO disable failed !"); - return -1; + goto error; } if ((read_dst(state, &reply, GET_ACK) < 0)) { dprintk(verbose, DST_DEBUG, 1, "read verify not successful."); - return -1; + goto error; } if (reply != ACK) { dprintk(verbose, DST_DEBUG, 1, "write not acknowledged 0x%02x ", reply); - return 0; + goto error; } state->diseq_flags |= ATTEMPT_TUNE; + retval = dst_get_tuna(state); +werr: + up(&state->dst_mutex); + return retval; - return dst_get_tuna(state); +error: + up(&state->dst_mutex); + return -EIO; } /* -- cgit v1.2.3 From 147418c9ca7bdffadafb0122c15b1eae167142f4 Mon Sep 17 00:00:00 2001 From: Kirk Lapray Date: Tue, 8 Nov 2005 21:35:39 -0800 Subject: [PATCH] dvb: add support for plls used by nxt200x - Added support for the following: Philips TUV1236D - ATI HDTV Wonder ALPS TDHU2 - AverTVHD MCE A180 Samsung TBMV30111IN - Air2PC ATSC - 2nd generation These will be used in a new NXT200X driver that incorporates the NXT2002 driver and adds support for a couple NXT2004 based cards. Signed-off-by: Kirk Lapray Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/frontends/dvb-pll.c | 52 +++++++++++++++++++++++++++++++++++ drivers/media/dvb/frontends/dvb-pll.h | 4 +++ 2 files changed, 56 insertions(+) diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 6668839f947..6ba7433c2aa 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -292,6 +292,58 @@ struct dvb_pll_desc dvb_pll_tded4 = { }; EXPORT_SYMBOL(dvb_pll_tded4); +/* ALPS TDHU2 + * used in AverTVHD MCE A180 + */ +struct dvb_pll_desc dvb_pll_tdhu2 = { + .name = "ALPS TDHU2", + .min = 54000000, + .max = 864000000, + .count = 4, + .entries = { + { 162000000, 44000000, 62500, 0x85, 0x01 }, + { 426000000, 44000000, 62500, 0x85, 0x02 }, + { 782000000, 44000000, 62500, 0x85, 0x08 }, + { 999999999, 44000000, 62500, 0x85, 0x88 }, + } +}; +EXPORT_SYMBOL(dvb_pll_tdhu2); + +/* Philips TUV1236D + * used in ATI HDTV Wonder + */ +struct dvb_pll_desc dvb_pll_tuv1236d = { + .name = "Philips TUV1236D", + .min = 57000000, + .max = 864000000, + .count = 3, + .entries = { + { 157250000, 44000000, 62500, 0xc6, 0x41 }, + { 454000000, 44000000, 62500, 0xc6, 0x42 }, + { 999999999, 44000000, 62500, 0xc6, 0x44 }, + }, +}; +EXPORT_SYMBOL(dvb_pll_tuv1236d); + +/* Samsung TBMV30111IN + * used in Air2PC ATSC - 2nd generation (nxt2002) + */ +struct dvb_pll_desc dvb_pll_tbmv30111in = { + .name = "Samsung TBMV30111IN", + .min = 54000000, + .max = 860000000, + .count = 4, + .entries = { + { 172000000, 44000000, 166666, 0xb4, 0x01 }, + { 214000000, 44000000, 166666, 0xb4, 0x02 }, + { 467000000, 44000000, 166666, 0xbc, 0x02 }, + { 721000000, 44000000, 166666, 0xbc, 0x08 }, + { 841000000, 44000000, 166666, 0xf4, 0x08 }, + { 999999999, 44000000, 166666, 0xfc, 0x02 }, + } +}; +EXPORT_SYMBOL(dvb_pll_tbmv30111in); + /* ----------------------------------------------------------- */ /* code */ diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index 205b2d1a885..497d31dcf41 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -36,6 +36,10 @@ extern struct dvb_pll_desc dvb_pll_tda665x; extern struct dvb_pll_desc dvb_pll_fmd1216me; extern struct dvb_pll_desc dvb_pll_tded4; +extern struct dvb_pll_desc dvb_pll_tuv1236d; +extern struct dvb_pll_desc dvb_pll_tdhu2; +extern struct dvb_pll_desc dvb_pll_tbmv30111in; + int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, u32 freq, int bandwidth); -- cgit v1.2.3 From 163d8fed1640c9a6c9f54e261ad5c755e373d04e Mon Sep 17 00:00:00 2001 From: Stuart Auchterlonie Date: Tue, 8 Nov 2005 21:35:40 -0800 Subject: [PATCH] dvb: Nebula nxt6000 requires fe reset Nebula nxt6000 requires fe reset. Signed-off-by: Stuart Auchterlonie Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index 1c5f1ec8535..05554e3949d 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -523,9 +523,7 @@ static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt) /* * Reset the frontend, must be called before trying * to initialise the MT352 or mt352_attach - * will fail. - * - * Presumably not required for the NXT6000 frontend. + * will fail. Same goes for the nxt6000 frontend. * */ @@ -632,6 +630,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) */ /* Old Nebula (marked (c)2003 on high profile pci card) has nxt6000 demod */ + digitv_alps_tded4_reset(card); card->fe = nxt6000_attach(&vp3021_alps_tded4_config, card->i2c_adapter); if (card->fe != NULL) { dprintk ("dvb_bt8xx: an nxt6000 was detected on your digitv card\n"); -- cgit v1.2.3 From ff29d06a102b35f9523ab4b6c38c9eb9948d1c80 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Tue, 8 Nov 2005 21:35:43 -0800 Subject: [PATCH] dvb: stv0299: reduce i2c xfer and set register 0x12 from inittab stv0299_set_frontend(): reduced number of i2c transfers, set register 0x12 from inittab Signed-off-by: Oliver Endriss Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/frontends/stv0299.c | 2 -- drivers/media/dvb/ttpci/av7110.c | 4 ++-- drivers/media/dvb/ttpci/budget-av.c | 2 +- drivers/media/dvb/ttpci/budget-ci.c | 2 +- drivers/media/dvb/ttpci/budget-patch.c | 2 +- drivers/media/dvb/ttpci/budget.c | 4 ++-- 6 files changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c index 35dc8439be1..29c48665e13 100644 --- a/drivers/media/dvb/frontends/stv0299.c +++ b/drivers/media/dvb/frontends/stv0299.c @@ -561,8 +561,6 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par stv0299_set_symbolrate (fe, p->u.qpsk.symbol_rate); stv0299_writeregI(state, 0x22, 0x00); stv0299_writeregI(state, 0x23, 0x00); - stv0299_readreg (state, 0x23); - stv0299_writeregI(state, 0x12, 0xb9); state->tuner_frequency = p->frequency; state->fec_inner = p->u.qpsk.fec_inner; diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 820eea29432..87ea52757a2 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -1566,7 +1566,7 @@ static u8 alps_bsru6_inittab[] = { 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ 0x10, 0x3f, // AGC2 0x3d 0x11, 0x84, - 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x12, 0xb9, 0x15, 0xc9, // lock detector threshold 0x16, 0x00, 0x17, 0x00, @@ -1668,7 +1668,7 @@ static u8 alps_bsbe1_inittab[] = { 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ 0x10, 0x3f, // AGC2 0x3d 0x11, 0x84, - 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x12, 0xb9, 0x15, 0xc9, // lock detector threshold 0x16, 0x00, 0x17, 0x00, diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index ac108102b67..aa75dc03a0b 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -499,7 +499,7 @@ static u8 typhoon_cinergy1200s_inittab[] = { 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ 0x10, 0x3f, // AGC2 0x3d 0x11, 0x84, - 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x12, 0xb9, 0x15, 0xc9, // lock detector threshold 0x16, 0x00, 0x17, 0x00, diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 9263ed686fd..75fb92d6099 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -490,7 +490,7 @@ static u8 alps_bsru6_inittab[] = { 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ 0x10, 0x3f, // AGC2 0x3d 0x11, 0x84, - 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x12, 0xb9, 0x15, 0xc9, // lock detector threshold 0x16, 0x00, 0x17, 0x00, diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c index 8ee4ac5b536..755df81cbc4 100644 --- a/drivers/media/dvb/ttpci/budget-patch.c +++ b/drivers/media/dvb/ttpci/budget-patch.c @@ -305,7 +305,7 @@ static u8 alps_bsru6_inittab[] = { 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ 0x10, 0x3f, // AGC2 0x3d 0x11, 0x84, - 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x12, 0xb9, 0x15, 0xc9, // lock detector threshold 0x16, 0x00, 0x17, 0x00, diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index ba308349ac9..4fd8bbc4703 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -286,7 +286,7 @@ static u8 alps_bsru6_inittab[] = { 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ 0x10, 0x3f, // AGC2 0x3d 0x11, 0x84, - 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x12, 0xb9, 0x15, 0xc9, // lock detector threshold 0x16, 0x00, 0x17, 0x00, @@ -383,7 +383,7 @@ static u8 alps_bsbe1_inittab[] = { 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ 0x10, 0x3f, // AGC2 0x3d 0x11, 0x84, - 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x12, 0xb9, 0x15, 0xc9, // lock detector threshold 0x16, 0x00, 0x17, 0x00, -- cgit v1.2.3 From 7f44dcda3f659ce47c1660a705802f12a2403a90 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Tue, 8 Nov 2005 21:35:44 -0800 Subject: [PATCH] dvb: fixed inittab register 0x12 for BSRU6/BSBE1 fixed inittab register 0x12 for BSRU6/BSBE1 Signed-off-by: Oliver Endriss Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index 2d519982ead..fd53d601050 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -1198,7 +1198,7 @@ static u8 alps_bsbe1_inittab[] = { 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ 0x10, 0x3f, // AGC2 0x3d 0x11, 0x84, - 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x12, 0xb9, 0x15, 0xc9, // lock detector threshold 0x16, 0x00, 0x17, 0x00, @@ -1240,7 +1240,7 @@ static u8 alps_bsru6_inittab[] = { 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ 0x10, 0x3f, // AGC2 0x3d 0x11, 0x84, - 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on + 0x12, 0xb9, 0x15, 0xc9, // lock detector threshold 0x16, 0x00, 0x17, 0x00, -- cgit v1.2.3 From 04a45929e7f00ed4fc7b1d375397f808c8a5d0eb Mon Sep 17 00:00:00 2001 From: Kirk Lapray Date: Tue, 8 Nov 2005 21:35:46 -0800 Subject: [PATCH] dvb: add nxt200x frontend module * nxt200x.c, nxt200x.h - New frontend module that supports both NXT2002 and NXT2004. So far, only tested on NXT2004. After testing on NXT2002, we should deprecate the nxt2002 module, and implement this one instead on the applicable cards. * get_dvb_firmware: - Added support for the NXT2004 firmware. This firmware works with both the ATI HDTV Wonder and the AVerTVHD MCE a180. This was originally written by Jean-Francois Thibert * dvb-pll.c - Fixed minimum frequency for tuv1236d. It seems that the data sheets are wrong. Signed-off-by: Kirk Lapray Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/dvb/get_dvb_firmware | 19 +- drivers/media/dvb/frontends/Kconfig | 8 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/dvb-pll.c | 2 +- drivers/media/dvb/frontends/nxt200x.c | 1203 +++++++++++++++++++++++++++++++++ drivers/media/dvb/frontends/nxt200x.h | 58 ++ 6 files changed, 1289 insertions(+), 2 deletions(-) create mode 100644 drivers/media/dvb/frontends/nxt200x.c create mode 100644 drivers/media/dvb/frontends/nxt200x.h diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware index a750f0101d9..be6eb4c7599 100644 --- a/Documentation/dvb/get_dvb_firmware +++ b/Documentation/dvb/get_dvb_firmware @@ -22,7 +22,7 @@ use File::Temp qw/ tempdir /; use IO::Handle; @components = ( "sp8870", "sp887x", "tda10045", "tda10046", "av7110", "dec2000t", - "dec2540t", "dec3000s", "vp7041", "dibusb", "nxt2002", + "dec2540t", "dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004", "or51211", "or51132_qam", "or51132_vsb"); # Check args @@ -252,6 +252,23 @@ sub nxt2002 { $outfile; } +sub nxt2004 { + my $sourcefile = "AVerTVHD_MCE_A180_Drv_v1.2.2.16.zip"; + my $url = "http://www.aver.com/support/Drivers/$sourcefile"; + my $hash = "111cb885b1e009188346d72acfed024c"; + my $outfile = "dvb-fe-nxt2004.fw"; + my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); + + checkstandard(); + + wgetfile($sourcefile, $url); + unzip($sourcefile, $tmpdir); + verify("$tmpdir/3xHybrid.sys", $hash); + extract("$tmpdir/3xHybrid.sys", 465304, 9584, $outfile); + + $outfile; +} + sub or51211 { my $fwfile = "dvb-fe-or51211.fw"; my $url = "http://linuxtv.org/downloads/firmware/$fwfile"; diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index a50a41f6f79..8e269e1c1f9 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -164,6 +164,14 @@ config DVB_NXT2002 help An ATSC 8VSB tuner module. Say Y when you want to support this frontend. +config DVB_NXT200X + tristate "Nextwave NXT2002/NXT2004 based" + depends on DVB_CORE + select FW_LOADER + help + An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want + to support this frontend. + config DVB_OR51211 tristate "or51211 based (pcHDTV HD2000 card)" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index ad8658ffd60..1692ee65ba5 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_DVB_TDA80XX) += tda80xx.o obj-$(CONFIG_DVB_TDA10021) += tda10021.o obj-$(CONFIG_DVB_STV0297) += stv0297.o obj-$(CONFIG_DVB_NXT2002) += nxt2002.o +obj-$(CONFIG_DVB_NXT2002) += nxt200x.o obj-$(CONFIG_DVB_OR51211) += or51211.o obj-$(CONFIG_DVB_OR51132) += or51132.o obj-$(CONFIG_DVB_BCM3510) += bcm3510.o diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 6ba7433c2aa..f857b869616 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -314,7 +314,7 @@ EXPORT_SYMBOL(dvb_pll_tdhu2); */ struct dvb_pll_desc dvb_pll_tuv1236d = { .name = "Philips TUV1236D", - .min = 57000000, + .min = 54000000, .max = 864000000, .count = 3, .entries = { diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c new file mode 100644 index 00000000000..1d729be9b75 --- /dev/null +++ b/drivers/media/dvb/frontends/nxt200x.c @@ -0,0 +1,1203 @@ +/* + * Support for NXT2002 and NXT2004 - VSB/QAM + * + * Copyright (C) 2005 Kirk Lapray (kirk.lapray@gmail.com) + * based on nxt2002 by Taylor Jacob + * and nxt2004 by Jean-Francois Thibert (jeanfrancois@sagetv.com) + * + * 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 option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * +*/ + +/* + * NOTES ABOUT THIS DRIVER + * + * This Linux driver supports: + * B2C2/BBTI Technisat Air2PC - ATSC (NXT2002) + * AverTVHD MCE A180 (NXT2004) + * ATI HDTV Wonder (NXT2004) + * + * This driver needs external firmware. Please use the command + * "/Documentation/dvb/get_dvb_firmware nxt2002" or + * "/Documentation/dvb/get_dvb_firmware nxt2004" to + * download/extract the appropriate firmware, and then copy it to + * /usr/lib/hotplug/firmware/ or /lib/firmware/ + * (depending on configuration of firmware hotplug). + */ +#define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw" +#define NXT2004_DEFAULT_FIRMWARE "dvb-fe-nxt2004.fw" +#define CRC_CCIT_MASK 0x1021 + +#include +#include +#include +#include + +#include "dvb_frontend.h" +#include "dvb-pll.h" +#include "nxt200x.h" + +struct nxt200x_state { + + struct i2c_adapter* i2c; + struct dvb_frontend_ops ops; + const struct nxt200x_config* config; + struct dvb_frontend frontend; + + /* demodulator private data */ + nxt_chip_type demod_chip; + u8 initialised:1; +}; + +static int debug; +#define dprintk(args...) \ + do { \ + if (debug) printk(KERN_DEBUG "nxt200x: " args); \ + } while (0) + +static int i2c_writebytes (struct nxt200x_state* state, u8 addr, u8 *buf, u8 len) +{ + int err; + struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = len }; + + if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { + printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n", + __FUNCTION__, addr, err); + return -EREMOTEIO; + } + return 0; +} + +static u8 i2c_readbytes (struct nxt200x_state* state, u8 addr, u8* buf, u8 len) +{ + int err; + struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = buf, .len = len }; + + if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { + printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n", + __FUNCTION__, addr, err); + return -EREMOTEIO; + } + return 0; +} + +static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg, u8 *buf, u8 len) +{ + u8 buf2 [len+1]; + int err; + struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf2, .len = len + 1 }; + + buf2[0] = reg; + memcpy(&buf2[1], buf, len); + + if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) { + printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n", + __FUNCTION__, state->config->demod_address, err); + return -EREMOTEIO; + } + return 0; +} + +static u8 nxt200x_readbytes (struct nxt200x_state* state, u8 reg, u8* buf, u8 len) +{ + u8 reg2 [] = { reg }; + + struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = reg2, .len = 1 }, + { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len } }; + + int err; + + if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) { + printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n", + __FUNCTION__, state->config->demod_address, err); + return -EREMOTEIO; + } + return 0; +} + +static u16 nxt200x_crc(u16 crc, u8 c) +{ + u8 i; + u16 input = (u16) c & 0xFF; + + input<<=8; + for(i=0; i<8; i++) { + if((crc^input) & 0x8000) + crc=(crc<<1)^CRC_CCIT_MASK; + else + crc<<=1; + input<<=1; + } + return crc; +} + +static int nxt200x_writereg_multibyte (struct nxt200x_state* state, u8 reg, u8* data, u8 len) +{ + u8 attr, len2, buf; + dprintk("%s\n", __FUNCTION__); + + /* set mutli register register */ + nxt200x_writebytes(state, 0x35, ®, 1); + + /* send the actual data */ + nxt200x_writebytes(state, 0x36, data, len); + + switch (state->demod_chip) { + case NXT2002: + len2 = len; + buf = 0x02; + break; + case NXT2004: + /* probably not right, but gives correct values */ + attr = 0x02; + if (reg & 0x80) { + attr = attr << 1; + if (reg & 0x04) + attr = attr >> 1; + } + /* set write bit */ + len2 = ((attr << 4) | 0x10) | len; + buf = 0x80; + break; + default: + return -EINVAL; + break; + } + + /* set multi register length */ + nxt200x_writebytes(state, 0x34, &len2, 1); + + /* toggle the multireg write bit */ + nxt200x_writebytes(state, 0x21, &buf, 1); + + nxt200x_readbytes(state, 0x21, &buf, 1); + + switch (state->demod_chip) { + case NXT2002: + if ((buf & 0x02) == 0) + return 0; + break; + case NXT2004: + if (buf == 0) + return 0; + break; + default: + return -EINVAL; + break; + } + + printk(KERN_WARNING "nxt200x: Error writing multireg register 0x%02X\n",reg); + + return 0; +} + +static int nxt200x_readreg_multibyte (struct nxt200x_state* state, u8 reg, u8* data, u8 len) +{ + int i; + u8 buf, len2, attr; + dprintk("%s\n", __FUNCTION__); + + /* set mutli register register */ + nxt200x_writebytes(state, 0x35, ®, 1); + + switch (state->demod_chip) { + case NXT2002: + /* set multi register length */ + len2 = len & 0x80; + nxt200x_writebytes(state, 0x34, &len2, 1); + + /* read the actual data */ + nxt200x_readbytes(state, reg, data, len); + return 0; + break; + case NXT2004: + /* probably not right, but gives correct values */ + attr = 0x02; + if (reg & 0x80) { + attr = attr << 1; + if (reg & 0x04) + attr = attr >> 1; + } + + /* set multi register length */ + len2 = (attr << 4) | len; + nxt200x_writebytes(state, 0x34, &len2, 1); + + /* toggle the multireg bit*/ + buf = 0x80; + nxt200x_writebytes(state, 0x21, &buf, 1); + + /* read status */ + nxt200x_readbytes(state, 0x21, &buf, 1); + + if (buf == 0) + { + /* read the actual data */ + for(i = 0; i < len; i++) { + nxt200x_readbytes(state, 0x36 + i, &data[i], 1); + } + return 0; + } + break; + default: + return -EINVAL; + break; + } + + printk(KERN_WARNING "nxt200x: Error reading multireg register 0x%02X\n",reg); + + return 0; +} + +static void nxt200x_microcontroller_stop (struct nxt200x_state* state) +{ + u8 buf, stopval, counter = 0; + dprintk("%s\n", __FUNCTION__); + + /* set correct stop value */ + switch (state->demod_chip) { + case NXT2002: + stopval = 0x40; + break; + case NXT2004: + stopval = 0x10; + break; + default: + stopval = 0; + break; + } + + buf = 0x80; + nxt200x_writebytes(state, 0x22, &buf, 1); + + while (counter < 20) { + nxt200x_readbytes(state, 0x31, &buf, 1); + if (buf & stopval) + return; + msleep(10); + counter++; + } + + printk(KERN_WARNING "nxt200x: Timeout waiting for nxt200x to stop. This is ok after firmware upload.\n"); + return; +} + +static void nxt200x_microcontroller_start (struct nxt200x_state* state) +{ + u8 buf; + dprintk("%s\n", __FUNCTION__); + + buf = 0x00; + nxt200x_writebytes(state, 0x22, &buf, 1); +} + +static void nxt2004_microcontroller_init (struct nxt200x_state* state) +{ + u8 buf[9]; + u8 counter = 0; + dprintk("%s\n", __FUNCTION__); + + buf[0] = 0x00; + nxt200x_writebytes(state, 0x2b, buf, 1); + buf[0] = 0x70; + nxt200x_writebytes(state, 0x34, buf, 1); + buf[0] = 0x04; + nxt200x_writebytes(state, 0x35, buf, 1); + buf[0] = 0x01; buf[1] = 0x23; buf[2] = 0x45; buf[3] = 0x67; buf[4] = 0x89; + buf[5] = 0xAB; buf[6] = 0xCD; buf[7] = 0xEF; buf[8] = 0xC0; + nxt200x_writebytes(state, 0x36, buf, 9); + buf[0] = 0x80; + nxt200x_writebytes(state, 0x21, buf, 1); + + while (counter < 20) { + nxt200x_readbytes(state, 0x21, buf, 1); + if (buf[0] == 0) + return; + msleep(10); + counter++; + } + + printk(KERN_WARNING "nxt200x: Timeout waiting for nxt2004 to init.\n"); + + return; +} + +static int nxt200x_writetuner (struct nxt200x_state* state, u8* data) +{ + u8 buf, count = 0; + + dprintk("%s\n", __FUNCTION__); + + dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[0], data[1], data[2], data[3]); + + /* if pll is a Philips TUV1236D then write directly to tuner */ + if (strcmp(state->config->pll_desc->name, "Philips TUV1236D") == 0) { + if (i2c_writebytes(state, state->config->pll_address, data, 4)) + printk(KERN_WARNING "nxt200x: error writing to tuner\n"); + /* wait until we have a lock */ + while (count < 20) { + i2c_readbytes(state, state->config->pll_address, &buf, 1); + if (buf & 0x40) + return 0; + msleep(100); + count++; + } + printk("nxt200x: timeout waiting for tuner lock\n"); + return 0; + } else { + /* set the i2c transfer speed to the tuner */ + buf = 0x03; + nxt200x_writebytes(state, 0x20, &buf, 1); + + /* setup to transfer 4 bytes via i2c */ + buf = 0x04; + nxt200x_writebytes(state, 0x34, &buf, 1); + + /* write actual tuner bytes */ + nxt200x_writebytes(state, 0x36, data, 4); + + /* set tuner i2c address */ + buf = state->config->pll_address; + nxt200x_writebytes(state, 0x35, &buf, 1); + + /* write UC Opmode to begin transfer */ + buf = 0x80; + nxt200x_writebytes(state, 0x21, &buf, 1); + + while (count < 20) { + nxt200x_readbytes(state, 0x21, &buf, 1); + if ((buf & 0x80)== 0x00) + return 0; + msleep(100); + count++; + } + printk("nxt200x: timeout error writing tuner\n"); + return 0; + } +} + +static void nxt200x_agc_reset(struct nxt200x_state* state) +{ + u8 buf; + dprintk("%s\n", __FUNCTION__); + + switch (state->demod_chip) { + case NXT2002: + buf = 0x08; + nxt200x_writebytes(state, 0x08, &buf, 1); + buf = 0x00; + nxt200x_writebytes(state, 0x08, &buf, 1); + break; + case NXT2004: + nxt200x_readreg_multibyte(state, 0x08, &buf, 1); + buf = 0x08; + nxt200x_writereg_multibyte(state, 0x08, &buf, 1); + buf = 0x00; + nxt200x_writereg_multibyte(state, 0x08, &buf, 1); + break; + default: + break; + } + return; +} + +static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware *fw) +{ + + struct nxt200x_state* state = fe->demodulator_priv; + u8 buf[3], written = 0, chunkpos = 0; + u16 rambase, position, crc = 0; + + dprintk("%s\n", __FUNCTION__); + dprintk("Firmware is %zu bytes\n", fw->size); + + /* Get the RAM base for this nxt2002 */ + nxt200x_readbytes(state, 0x10, buf, 1); + + if (buf[0] & 0x10) + rambase = 0x1000; + else + rambase = 0x0000; + + dprintk("rambase on this nxt2002 is %04X\n", rambase); + + /* Hold the micro in reset while loading firmware */ + buf[0] = 0x80; + nxt200x_writebytes(state, 0x2B, buf, 1); + + for (position = 0; position < fw->size; position++) { + if (written == 0) { + crc = 0; + chunkpos = 0x28; + buf[0] = ((rambase + position) >> 8); + buf[1] = (rambase + position) & 0xFF; + buf[2] = 0x81; + /* write starting address */ + nxt200x_writebytes(state, 0x29, buf, 3); + } + written++; + chunkpos++; + + if ((written % 4) == 0) + nxt200x_writebytes(state, chunkpos, &fw->data[position-3], 4); + + crc = nxt200x_crc(crc, fw->data[position]); + + if ((written == 255) || (position+1 == fw->size)) { + /* write remaining bytes of firmware */ + nxt200x_writebytes(state, chunkpos+4-(written %4), + &fw->data[position-(written %4) + 1], + written %4); + buf[0] = crc << 8; + buf[1] = crc & 0xFF; + + /* write crc */ + nxt200x_writebytes(state, 0x2C, buf, 2); + + /* do a read to stop things */ + nxt200x_readbytes(state, 0x2A, buf, 1); + + /* set transfer mode to complete */ + buf[0] = 0x80; + nxt200x_writebytes(state, 0x2B, buf, 1); + + written = 0; + } + } + + return 0; +}; + +static int nxt2004_load_firmware (struct dvb_frontend* fe, const struct firmware *fw) +{ + + struct nxt200x_state* state = fe->demodulator_priv; + u8 buf[3]; + u16 rambase, position, crc=0; + + dprintk("%s\n", __FUNCTION__); + dprintk("Firmware is %zu bytes\n", fw->size); + + /* set rambase */ + rambase = 0x1000; + + /* hold the micro in reset while loading firmware */ + buf[0] = 0x80; + nxt200x_writebytes(state, 0x2B, buf,1); + + /* calculate firmware CRC */ + for (position = 0; position < fw->size; position++) { + crc = nxt200x_crc(crc, fw->data[position]); + } + + buf[0] = rambase >> 8; + buf[1] = rambase & 0xFF; + buf[2] = 0x81; + /* write starting address */ + nxt200x_writebytes(state,0x29,buf,3); + + for (position = 0; position < fw->size;) { + nxt200x_writebytes(state, 0x2C, &fw->data[position], + fw->size-position > 255 ? 255 : fw->size-position); + position += (fw->size-position > 255 ? 255 : fw->size-position); + } + buf[0] = crc >> 8; + buf[1] = crc & 0xFF; + + dprintk("firmware crc is 0x%02X 0x%02X\n", buf[0], buf[1]); + + /* write crc */ + nxt200x_writebytes(state, 0x2C, buf,2); + + /* do a read to stop things */ + nxt200x_readbytes(state, 0x2C, buf, 1); + + /* set transfer mode to complete */ + buf[0] = 0x80; + nxt200x_writebytes(state, 0x2B, buf,1); + + return 0; +}; + +static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, + struct dvb_frontend_parameters *p) +{ + struct nxt200x_state* state = fe->demodulator_priv; + u8 buf[4]; + + /* stop the micro first */ + nxt200x_microcontroller_stop(state); + + if (state->demod_chip == NXT2004) { + /* make sure demod is set to digital */ + buf[0] = 0x04; + nxt200x_writebytes(state, 0x14, buf, 1); + buf[0] = 0x00; + nxt200x_writebytes(state, 0x17, buf, 1); + } + + /* get tuning information */ + dvb_pll_configure(state->config->pll_desc, buf, p->frequency, 0); + + /* set additional params */ + switch (p->u.vsb.modulation) { + case QAM_64: + case QAM_256: + /* Set punctured clock for QAM */ + /* This is just a guess since I am unable to test it */ + state->config->set_ts_params(fe, 1); + + /* set to use cable input */ + buf[3] |= 0x08; + break; + case VSB_8: + /* Set non-punctured clock for VSB */ + state->config->set_ts_params(fe, 0); + break; + default: + return -EINVAL; + break; + } + + /* write frequency information */ + nxt200x_writetuner(state, buf); + + /* reset the agc now that tuning has been completed */ + nxt200x_agc_reset(state); + + /* set target power level */ + switch (p->u.vsb.modulation) { + case QAM_64: + case QAM_256: + buf[0] = 0x74; + break; + case VSB_8: + buf[0] = 0x70; + break; + default: + return -EINVAL; + break; + } + nxt200x_writebytes(state, 0x42, buf, 1); + + /* configure sdm */ + switch (state->demod_chip) { + case NXT2002: + buf[0] = 0x87; + break; + case NXT2004: + buf[0] = 0x07; + break; + default: + return -EINVAL; + break; + } + nxt200x_writebytes(state, 0x57, buf, 1); + + /* write sdm1 input */ + buf[0] = 0x10; + buf[1] = 0x00; + nxt200x_writebytes(state, 0x58, buf, 2); + + /* write sdmx input */ + switch (p->u.vsb.modulation) { + case QAM_64: + buf[0] = 0x68; + break; + case QAM_256: + buf[0] = 0x64; + break; + case VSB_8: + buf[0] = 0x60; + break; + default: + return -EINVAL; + break; + } + buf[1] = 0x00; + nxt200x_writebytes(state, 0x5C, buf, 2); + + /* write adc power lpf fc */ + buf[0] = 0x05; + nxt200x_writebytes(state, 0x43, buf, 1); + + if (state->demod_chip == NXT2004) { + /* write ??? */ + buf[0] = 0x00; + buf[1] = 0x00; + nxt200x_writebytes(state, 0x46, buf, 2); + } + + /* write accumulator2 input */ + buf[0] = 0x80; + buf[1] = 0x00; + nxt200x_writebytes(state, 0x4B, buf, 2); + + /* write kg1 */ + buf[0] = 0x00; + nxt200x_writebytes(state, 0x4D, buf, 1); + + /* write sdm12 lpf fc */ + buf[0] = 0x44; + nxt200x_writebytes(state, 0x55, buf, 1); + + /* write agc control reg */ + buf[0] = 0x04; + nxt200x_writebytes(state, 0x41, buf, 1); + + if (state->demod_chip == NXT2004) { + nxt200x_readreg_multibyte(state, 0x80, buf, 1); + buf[0] = 0x24; + nxt200x_writereg_multibyte(state, 0x80, buf, 1); + + /* soft reset? */ + nxt200x_readreg_multibyte(state, 0x08, buf, 1); + buf[0] = 0x10; + nxt200x_writereg_multibyte(state, 0x08, buf, 1); + nxt200x_readreg_multibyte(state, 0x08, buf, 1); + buf[0] = 0x00; + nxt200x_writereg_multibyte(state, 0x08, buf, 1); + + nxt200x_readreg_multibyte(state, 0x80, buf, 1); + buf[0] = 0x04; + nxt200x_writereg_multibyte(state, 0x80, buf, 1); + buf[0] = 0x00; + nxt200x_writereg_multibyte(state, 0x81, buf, 1); + buf[0] = 0x80; buf[1] = 0x00; buf[2] = 0x00; + nxt200x_writereg_multibyte(state, 0x82, buf, 3); + nxt200x_readreg_multibyte(state, 0x88, buf, 1); + buf[0] = 0x11; + nxt200x_writereg_multibyte(state, 0x88, buf, 1); + nxt200x_readreg_multibyte(state, 0x80, buf, 1); + buf[0] = 0x44; + nxt200x_writereg_multibyte(state, 0x80, buf, 1); + } + + /* write agc ucgp0 */ + switch (p->u.vsb.modulation) { + case QAM_64: + buf[0] = 0x02; + break; + case QAM_256: + buf[0] = 0x03; + break; + case VSB_8: + buf[0] = 0x00; + break; + default: + return -EINVAL; + break; + } + nxt200x_writebytes(state, 0x30, buf, 1); + + /* write agc control reg */ + buf[0] = 0x00; + nxt200x_writebytes(state, 0x41, buf, 1); + + /* write accumulator2 input */ + buf[0] = 0x80; + buf[1] = 0x00; + nxt200x_writebytes(state, 0x49, buf,2); + nxt200x_writebytes(state, 0x4B, buf,2); + + /* write agc control reg */ + buf[0] = 0x04; + nxt200x_writebytes(state, 0x41, buf, 1); + + nxt200x_microcontroller_start(state); + + if (state->demod_chip == NXT2004) { + nxt2004_microcontroller_init(state); + + /* ???? */ + buf[0] = 0xF0; + buf[1] = 0x00; + nxt200x_writebytes(state, 0x5C, buf, 2); + } + + /* adjacent channel detection should be done here, but I don't + have any stations with this need so I cannot test it */ + + return 0; +} + +static int nxt200x_read_status(struct dvb_frontend* fe, fe_status_t* status) +{ + struct nxt200x_state* state = fe->demodulator_priv; + u8 lock; + nxt200x_readbytes(state, 0x31, &lock, 1); + + *status = 0; + if (lock & 0x20) { + *status |= FE_HAS_SIGNAL; + *status |= FE_HAS_CARRIER; + *status |= FE_HAS_VITERBI; + *status |= FE_HAS_SYNC; + *status |= FE_HAS_LOCK; + } + return 0; +} + +static int nxt200x_read_ber(struct dvb_frontend* fe, u32* ber) +{ + struct nxt200x_state* state = fe->demodulator_priv; + u8 b[3]; + + nxt200x_readreg_multibyte(state, 0xE6, b, 3); + + *ber = ((b[0] << 8) + b[1]) * 8; + + return 0; +} + +static int nxt200x_read_signal_strength(struct dvb_frontend* fe, u16* strength) +{ + struct nxt200x_state* state = fe->demodulator_priv; + u8 b[2]; + u16 temp = 0; + + /* setup to read cluster variance */ + b[0] = 0x00; + nxt200x_writebytes(state, 0xA1, b, 1); + + /* get multreg val */ + nxt200x_readreg_multibyte(state, 0xA6, b, 2); + + temp = (b[0] << 8) | b[1]; + *strength = ((0x7FFF - temp) & 0x0FFF) * 16; + + return 0; +} + +static int nxt200x_read_snr(struct dvb_frontend* fe, u16* snr) +{ + + struct nxt200x_state* state = fe->demodulator_priv; + u8 b[2]; + u16 temp = 0, temp2; + u32 snrdb = 0; + + /* setup to read cluster variance */ + b[0] = 0x00; + nxt200x_writebytes(state, 0xA1, b, 1); + + /* get multreg val from 0xA6 */ + nxt200x_readreg_multibyte(state, 0xA6, b, 2); + + temp = (b[0] << 8) | b[1]; + temp2 = 0x7FFF - temp; + + /* snr will be in db */ + if (temp2 > 0x7F00) + snrdb = 1000*24 + ( 1000*(30-24) * ( temp2 - 0x7F00 ) / ( 0x7FFF - 0x7F00 ) ); + else if (temp2 > 0x7EC0) + snrdb = 1000*18 + ( 1000*(24-18) * ( temp2 - 0x7EC0 ) / ( 0x7F00 - 0x7EC0 ) ); + else if (temp2 > 0x7C00) + snrdb = 1000*12 + ( 1000*(18-12) * ( temp2 - 0x7C00 ) / ( 0x7EC0 - 0x7C00 ) ); + else + snrdb = 1000*0 + ( 1000*(12-0) * ( temp2 - 0 ) / ( 0x7C00 - 0 ) ); + + /* the value reported back from the frontend will be FFFF=32db 0000=0db */ + *snr = snrdb * (0xFFFF/32000); + + return 0; +} + +static int nxt200x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) +{ + struct nxt200x_state* state = fe->demodulator_priv; + u8 b[3]; + + nxt200x_readreg_multibyte(state, 0xE6, b, 3); + *ucblocks = b[2]; + + return 0; +} + +static int nxt200x_sleep(struct dvb_frontend* fe) +{ + return 0; +} + +static int nxt2002_init(struct dvb_frontend* fe) +{ + struct nxt200x_state* state = fe->demodulator_priv; + const struct firmware *fw; + int ret; + u8 buf[2]; + + /* request the firmware, this will block until someone uploads it */ + printk("nxt2002: Waiting for firmware upload (%s)...\n", NXT2002_DEFAULT_FIRMWARE); + ret = request_firmware(&fw, NXT2002_DEFAULT_FIRMWARE, &state->i2c->dev); + printk("nxt2002: Waiting for firmware upload(2)...\n"); + if (ret) { + printk("nxt2002: No firmware uploaded (timeout or file not found?)\n"); + return ret; + } + + ret = nxt2002_load_firmware(fe, fw); + if (ret) { + printk("nxt2002: Writing firmware to device failed\n"); + release_firmware(fw); + return ret; + } + printk("nxt2002: Firmware upload complete\n"); + + /* Put the micro into reset */ + nxt200x_microcontroller_stop(state); + + /* ensure transfer is complete */ + buf[0]=0x00; + nxt200x_writebytes(state, 0x2B, buf, 1); + + /* Put the micro into reset for real this time */ + nxt200x_microcontroller_stop(state); + + /* soft reset everything (agc,frontend,eq,fec)*/ + buf[0] = 0x0F; + nxt200x_writebytes(state, 0x08, buf, 1); + buf[0] = 0x00; + nxt200x_writebytes(state, 0x08, buf, 1); + + /* write agc sdm configure */ + buf[0] = 0xF1; + nxt200x_writebytes(state, 0x57, buf, 1); + + /* write mod output format */ + buf[0] = 0x20; + nxt200x_writebytes(state, 0x09, buf, 1); + + /* write fec mpeg mode */ + buf[0] = 0x7E; + buf[1] = 0x00; + nxt200x_writebytes(state, 0xE9, buf, 2); + + /* write mux selection */ + buf[0] = 0x00; + nxt200x_writebytes(state, 0xCC, buf, 1); + + return 0; +} + +static int nxt2004_init(struct dvb_frontend* fe) +{ + struct nxt200x_state* state = fe->demodulator_priv; + const struct firmware *fw; + int ret; + u8 buf[3]; + + /* ??? */ + buf[0]=0x00; + nxt200x_writebytes(state, 0x1E, buf, 1); + + /* request the firmware, this will block until someone uploads it */ + printk("nxt2004: Waiting for firmware upload (%s)...\n", NXT2004_DEFAULT_FIRMWARE); + ret = request_firmware(&fw, NXT2004_DEFAULT_FIRMWARE, &state->i2c->dev); + printk("nxt2004: Waiting for firmware upload(2)...\n"); + if (ret) { + printk("nxt2004: No firmware uploaded (timeout or file not found?)\n"); + return ret; + } + + ret = nxt2004_load_firmware(fe, fw); + if (ret) { + printk("nxt2004: Writing firmware to device failed\n"); + release_firmware(fw); + return ret; + } + printk("nxt2004: Firmware upload complete\n"); + + /* ensure transfer is complete */ + buf[0] = 0x01; + nxt200x_writebytes(state, 0x19, buf, 1); + + nxt2004_microcontroller_init(state); + nxt200x_microcontroller_stop(state); + nxt200x_microcontroller_stop(state); + nxt2004_microcontroller_init(state); + nxt200x_microcontroller_stop(state); + + /* soft reset everything (agc,frontend,eq,fec)*/ + buf[0] = 0xFF; + nxt200x_writereg_multibyte(state, 0x08, buf, 1); + buf[0] = 0x00; + nxt200x_writereg_multibyte(state, 0x08, buf, 1); + + /* write agc sdm configure */ + buf[0] = 0xD7; + nxt200x_writebytes(state, 0x57, buf, 1); + + /* ???*/ + buf[0] = 0x07; + buf[1] = 0xfe; + nxt200x_writebytes(state, 0x35, buf, 2); + buf[0] = 0x12; + nxt200x_writebytes(state, 0x34, buf, 1); + buf[0] = 0x80; + nxt200x_writebytes(state, 0x21, buf, 1); + + /* ???*/ + buf[0] = 0x21; + nxt200x_writebytes(state, 0x0A, buf, 1); + + /* ???*/ + buf[0] = 0x01; + nxt200x_writereg_multibyte(state, 0x80, buf, 1); + + /* write fec mpeg mode */ + buf[0] = 0x7E; + buf[1] = 0x00; + nxt200x_writebytes(state, 0xE9, buf, 2); + + /* write mux selection */ + buf[0] = 0x00; + nxt200x_writebytes(state, 0xCC, buf, 1); + + /* ???*/ + nxt200x_readreg_multibyte(state, 0x80, buf, 1); + buf[0] = 0x00; + nxt200x_writereg_multibyte(state, 0x80, buf, 1); + + /* soft reset? */ + nxt200x_readreg_multibyte(state, 0x08, buf, 1); + buf[0] = 0x10; + nxt200x_writereg_multibyte(state, 0x08, buf, 1); + nxt200x_readreg_multibyte(state, 0x08, buf, 1); + buf[0] = 0x00; + nxt200x_writereg_multibyte(state, 0x08, buf, 1); + + /* ???*/ + nxt200x_readreg_multibyte(state, 0x80, buf, 1); + buf[0] = 0x01; + nxt200x_writereg_multibyte(state, 0x80, buf, 1); + buf[0] = 0x70; + nxt200x_writereg_multibyte(state, 0x81, buf, 1); + buf[0] = 0x31; buf[1] = 0x5E; buf[2] = 0x66; + nxt200x_writereg_multibyte(state, 0x82, buf, 3); + + nxt200x_readreg_multibyte(state, 0x88, buf, 1); + buf[0] = 0x11; + nxt200x_writereg_multibyte(state, 0x88, buf, 1); + nxt200x_readreg_multibyte(state, 0x80, buf, 1); + buf[0] = 0x40; + nxt200x_writereg_multibyte(state, 0x80, buf, 1); + + nxt200x_readbytes(state, 0x10, buf, 1); + buf[0] = 0x10; + nxt200x_writebytes(state, 0x10, buf, 1); + nxt200x_readbytes(state, 0x0A, buf, 1); + buf[0] = 0x21; + nxt200x_writebytes(state, 0x0A, buf, 1); + + nxt2004_microcontroller_init(state); + + buf[0] = 0x21; + nxt200x_writebytes(state, 0x0A, buf, 1); + buf[0] = 0x7E; + nxt200x_writebytes(state, 0xE9, buf, 1); + buf[0] = 0x00; + nxt200x_writebytes(state, 0xEA, buf, 1); + + nxt200x_readreg_multibyte(state, 0x80, buf, 1); + buf[0] = 0x00; + nxt200x_writereg_multibyte(state, 0x80, buf, 1); + nxt200x_readreg_multibyte(state, 0x80, buf, 1); + buf[0] = 0x00; + nxt200x_writereg_multibyte(state, 0x80, buf, 1); + + /* soft reset? */ + nxt200x_readreg_multibyte(state, 0x08, buf, 1); + buf[0] = 0x10; + nxt200x_writereg_multibyte(state, 0x08, buf, 1); + nxt200x_readreg_multibyte(state, 0x08, buf, 1); + buf[0] = 0x00; + nxt200x_writereg_multibyte(state, 0x08, buf, 1); + + nxt200x_readreg_multibyte(state, 0x80, buf, 1); + buf[0] = 0x04; + nxt200x_writereg_multibyte(state, 0x80, buf, 1); + buf[0] = 0x00; + nxt200x_writereg_multibyte(state, 0x81, buf, 1); + buf[0] = 0x80; buf[1] = 0x00; buf[2] = 0x00; + nxt200x_writereg_multibyte(state, 0x82, buf, 3); + + nxt200x_readreg_multibyte(state, 0x88, buf, 1); + buf[0] = 0x11; + nxt200x_writereg_multibyte(state, 0x88, buf, 1); + + nxt200x_readreg_multibyte(state, 0x80, buf, 1); + buf[0] = 0x44; + nxt200x_writereg_multibyte(state, 0x80, buf, 1); + + /* initialize tuner */ + nxt200x_readbytes(state, 0x10, buf, 1); + buf[0] = 0x12; + nxt200x_writebytes(state, 0x10, buf, 1); + buf[0] = 0x04; + nxt200x_writebytes(state, 0x13, buf, 1); + buf[0] = 0x00; + nxt200x_writebytes(state, 0x16, buf, 1); + buf[0] = 0x04; + nxt200x_writebytes(state, 0x14, buf, 1); + buf[0] = 0x00; + nxt200x_writebytes(state, 0x14, buf, 1); + nxt200x_writebytes(state, 0x17, buf, 1); + nxt200x_writebytes(state, 0x14, buf, 1); + nxt200x_writebytes(state, 0x17, buf, 1); + + return 0; +} + +static int nxt200x_init(struct dvb_frontend* fe) +{ + struct nxt200x_state* state = fe->demodulator_priv; + int ret = 0; + + if (!state->initialised) { + switch (state->demod_chip) { + case NXT2002: + ret = nxt2002_init(fe); + break; + case NXT2004: + ret = nxt2004_init(fe); + break; + default: + return -EINVAL; + break; + } + state->initialised = 1; + } + return ret; +} + +static int nxt200x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) +{ + fesettings->min_delay_ms = 500; + fesettings->step_size = 0; + fesettings->max_drift = 0; + return 0; +} + +static void nxt200x_release(struct dvb_frontend* fe) +{ + struct nxt200x_state* state = fe->demodulator_priv; + kfree(state); +} + +static struct dvb_frontend_ops nxt200x_ops; + +struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config, + struct i2c_adapter* i2c) +{ + struct nxt200x_state* state = NULL; + u8 buf [] = {0,0,0,0,0}; + + /* allocate memory for the internal state */ + state = (struct nxt200x_state*) kmalloc(sizeof(struct nxt200x_state), GFP_KERNEL); + if (state == NULL) + goto error; + memset(state,0,sizeof(*state)); + + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &nxt200x_ops, sizeof(struct dvb_frontend_ops)); + state->initialised = 0; + + /* read card id */ + nxt200x_readbytes(state, 0x00, buf, 5); + dprintk("NXT info: %02X %02X %02X %02X %02X\n", + buf[0], buf[1], buf[2], buf[3], buf[4]); + + /* set demod chip */ + switch (buf[0]) { + case 0x04: + state->demod_chip = NXT2002; + printk("nxt200x: NXT2002 Detected\n"); + break; + case 0x05: + state->demod_chip = NXT2004; + printk("nxt200x: NXT2004 Detected\n"); + break; + default: + goto error; + } + + /* make sure demod chip is supported */ + switch (state->demod_chip) { + case NXT2002: + if (buf[0] != 0x04) goto error; /* device id */ + if (buf[1] != 0x02) goto error; /* fab id */ + if (buf[2] != 0x11) goto error; /* month */ + if (buf[3] != 0x20) goto error; /* year msb */ + if (buf[4] != 0x00) goto error; /* year lsb */ + break; + case NXT2004: + if (buf[0] != 0x05) goto error; /* device id */ + break; + default: + goto error; + } + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + if (state) + kfree(state); + printk("Unknown/Unsupported NXT chip: %02X %02X %02X %02X %02X\n", + buf[0], buf[1], buf[2], buf[3], buf[4]); + return NULL; +} + +static struct dvb_frontend_ops nxt200x_ops = { + + .info = { + .name = "Nextwave NXT200X VSB/QAM frontend", + .type = FE_ATSC, + .frequency_min = 54000000, + .frequency_max = 860000000, + .frequency_stepsize = 166666, /* stepsize is just a guess */ + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_8VSB | FE_CAN_QAM_64 | FE_CAN_QAM_256 + }, + + .release = nxt200x_release, + + .init = nxt200x_init, + .sleep = nxt200x_sleep, + + .set_frontend = nxt200x_setup_frontend_parameters, + .get_tune_settings = nxt200x_get_tune_settings, + + .read_status = nxt200x_read_status, + .read_ber = nxt200x_read_ber, + .read_signal_strength = nxt200x_read_signal_strength, + .read_snr = nxt200x_read_snr, + .read_ucblocks = nxt200x_read_ucblocks, +}; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + +MODULE_DESCRIPTION("NXT200X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver"); +MODULE_AUTHOR("Kirk Lapray, Jean-Francois Thibert, and Taylor Jacob"); +MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(nxt200x_attach); + diff --git a/drivers/media/dvb/frontends/nxt200x.h b/drivers/media/dvb/frontends/nxt200x.h new file mode 100644 index 00000000000..8dc3f03ecdf --- /dev/null +++ b/drivers/media/dvb/frontends/nxt200x.h @@ -0,0 +1,58 @@ +/* + * Support for NXT2002 and NXT2004 - VSB/QAM + * + * Copyright (C) 2005 Kirk Lapray (kirk.lapray@gmail.com) + * based on nxt2002 by Taylor Jacob + * and nxt2004 by Jean-Francois Thibert (jeanfrancois@sagetv.com) + * + * 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 option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * +*/ + +#ifndef NXT200X_H +#define NXT200X_H + +#include +#include + +typedef enum nxt_chip_t { + NXTUNDEFINED, + NXT2002, + NXT2004 +}nxt_chip_type; + +struct nxt200x_config +{ + /* the demodulator's i2c address */ + u8 demod_address; + + /* tuner information */ + u8 pll_address; + struct dvb_pll_desc *pll_desc; + + /* need to set device param for start_dma */ + int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured); +}; + +extern struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config, + struct i2c_adapter* i2c); + +#endif /* NXT200X_H */ + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ -- cgit v1.2.3 From c6dd2d5d61b000509e3a7f6c06778b16a4ef10ba Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:35:47 -0800 Subject: [PATCH] dvb: nxt200x: check callback fix Check that a callback (set_ts_params) is set before calling it. Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/frontends/nxt200x.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c index 1d729be9b75..d1b9f8b9b43 100644 --- a/drivers/media/dvb/frontends/nxt200x.c +++ b/drivers/media/dvb/frontends/nxt200x.c @@ -557,14 +557,16 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, case QAM_256: /* Set punctured clock for QAM */ /* This is just a guess since I am unable to test it */ - state->config->set_ts_params(fe, 1); + if (state->config->set_ts_params) + state->config->set_ts_params(fe, 1); /* set to use cable input */ buf[3] |= 0x08; break; case VSB_8: /* Set non-punctured clock for VSB */ - state->config->set_ts_params(fe, 0); + if (state->config->set_ts_params) + state->config->set_ts_params(fe, 0); break; default: return -EINVAL; -- cgit v1.2.3 From 6d35ae3d1137c92a315b7ff10aecd45b1f37d99e Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:35:48 -0800 Subject: [PATCH] dvb: nxt200x: remove null check before kfree() Removed unnecessary null check before kfree() ...inspired by the big patch from Jesper Juhl. Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/frontends/nxt200x.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c index d1b9f8b9b43..97ee8017dac 100644 --- a/drivers/media/dvb/frontends/nxt200x.c +++ b/drivers/media/dvb/frontends/nxt200x.c @@ -1159,8 +1159,7 @@ struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config, return &state->frontend; error: - if (state) - kfree(state); + kfree(state); printk("Unknown/Unsupported NXT chip: %02X %02X %02X %02X %02X\n", buf[0], buf[1], buf[2], buf[3], buf[4]); return NULL; -- cgit v1.2.3 From f0fa86a574843264bdcbed4c84b41a2778861fde Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:35:49 -0800 Subject: [PATCH] dvb: determine tuner write method based on nxt chip - Add support for AVerTVHD MCE a180. - Instead of determining how to write to the tuner based on which NIM is being used, make this determination based on whether the chip is a NXT2002 or NXT2004. - If NXT2004, write directly to tuner. If NXT2002, write through NXT chip. Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/frontends/nxt200x.c | 82 +++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 38 deletions(-) diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c index 97ee8017dac..aee170805ca 100644 --- a/drivers/media/dvb/frontends/nxt200x.c +++ b/drivers/media/dvb/frontends/nxt200x.c @@ -342,50 +342,56 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data) dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[0], data[1], data[2], data[3]); - /* if pll is a Philips TUV1236D then write directly to tuner */ - if (strcmp(state->config->pll_desc->name, "Philips TUV1236D") == 0) { - if (i2c_writebytes(state, state->config->pll_address, data, 4)) - printk(KERN_WARNING "nxt200x: error writing to tuner\n"); - /* wait until we have a lock */ - while (count < 20) { - i2c_readbytes(state, state->config->pll_address, &buf, 1); - if (buf & 0x40) - return 0; - msleep(100); - count++; - } - printk("nxt200x: timeout waiting for tuner lock\n"); - return 0; - } else { - /* set the i2c transfer speed to the tuner */ - buf = 0x03; - nxt200x_writebytes(state, 0x20, &buf, 1); + /* if NXT2004, write directly to tuner. if NXT2002, write through NXT chip. + * direct write is required for Philips TUV1236D and ALPS TDHU2 */ + switch (state->demod_chip) { + case NXT2004: + if (i2c_writebytes(state, state->config->pll_address, data, 4)) + printk(KERN_WARNING "nxt200x: error writing to tuner\n"); + /* wait until we have a lock */ + while (count < 20) { + i2c_readbytes(state, state->config->pll_address, &buf, 1); + if (buf & 0x40) + return 0; + msleep(100); + count++; + } + printk("nxt2004: timeout waiting for tuner lock\n"); + break; + case NXT2002: + /* set the i2c transfer speed to the tuner */ + buf = 0x03; + nxt200x_writebytes(state, 0x20, &buf, 1); - /* setup to transfer 4 bytes via i2c */ - buf = 0x04; - nxt200x_writebytes(state, 0x34, &buf, 1); + /* setup to transfer 4 bytes via i2c */ + buf = 0x04; + nxt200x_writebytes(state, 0x34, &buf, 1); - /* write actual tuner bytes */ - nxt200x_writebytes(state, 0x36, data, 4); + /* write actual tuner bytes */ + nxt200x_writebytes(state, 0x36, data, 4); - /* set tuner i2c address */ - buf = state->config->pll_address; - nxt200x_writebytes(state, 0x35, &buf, 1); + /* set tuner i2c address */ + buf = state->config->pll_address; + nxt200x_writebytes(state, 0x35, &buf, 1); - /* write UC Opmode to begin transfer */ - buf = 0x80; - nxt200x_writebytes(state, 0x21, &buf, 1); + /* write UC Opmode to begin transfer */ + buf = 0x80; + nxt200x_writebytes(state, 0x21, &buf, 1); - while (count < 20) { - nxt200x_readbytes(state, 0x21, &buf, 1); - if ((buf & 0x80)== 0x00) - return 0; - msleep(100); - count++; - } - printk("nxt200x: timeout error writing tuner\n"); - return 0; + while (count < 20) { + nxt200x_readbytes(state, 0x21, &buf, 1); + if ((buf & 0x80)== 0x00) + return 0; + msleep(100); + count++; + } + printk("nxt2002: timeout error writing tuner\n"); + break; + default: + return -EINVAL; + break; } + return 0; } static void nxt200x_agc_reset(struct nxt200x_state* state) -- cgit v1.2.3 From b3967d6c251d8482fe42a1aad3cc292ee04c0a6b Mon Sep 17 00:00:00 2001 From: Mark Adams Date: Tue, 8 Nov 2005 21:35:50 -0800 Subject: [PATCH] dvb: fix bug in demux that caused lost mpeg sections Fix a bug in the software demux which causes large MPEG sections to be lost when they follow very small sections. The problem happens when two sections begin in the same transport packet. The dvb_demux code resets its buffer only before the first of these sections. This means that when the second (or subsequent) section begins, there is up to 182 bytes of buffer space already used. If the following section is close to the maximum size, it currently won't fit in the (4096-byte) buffer and is thrown away. The fix is simply to enlarge the buffer by the size of one transport packet and correct one usage of the SECFEED_SIZE definition where what is really meant is the maximum size of a section. Signed-off-by: Mark Adams Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/dvb-core/demux.h | 5 ++++- drivers/media/dvb/dvb-core/dvb_demux.c | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h index 9719a3b30f7..7d7b0067f22 100644 --- a/drivers/media/dvb/dvb-core/demux.h +++ b/drivers/media/dvb/dvb-core/demux.h @@ -48,8 +48,11 @@ * DMX_MAX_SECFEED_SIZE: Maximum length (in bytes) of a private section feed filter. */ +#ifndef DMX_MAX_SECTION_SIZE +#define DMX_MAX_SECTION_SIZE 4096 +#endif #ifndef DMX_MAX_SECFEED_SIZE -#define DMX_MAX_SECFEED_SIZE 4096 +#define DMX_MAX_SECFEED_SIZE (DMX_MAX_SECTION_SIZE + 188) #endif diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c index dc476dda2b7..b4c899b1595 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/drivers/media/dvb/dvb-core/dvb_demux.c @@ -246,7 +246,7 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, for (n = 0; sec->secbufp + 2 < limit; n++) { seclen = section_length(sec->secbuf); - if (seclen <= 0 || seclen > DMX_MAX_SECFEED_SIZE + if (seclen <= 0 || seclen > DMX_MAX_SECTION_SIZE || seclen + sec->secbufp > limit) return 0; sec->seclen = seclen; -- cgit v1.2.3 From f93cf038d5930810e7e280e70de6e0c07ad959da Mon Sep 17 00:00:00 2001 From: Kirk Lapray Date: Tue, 8 Nov 2005 21:35:51 -0800 Subject: [PATCH] dvb: Remove status check from nxt200x_readreg_multibyte Remove status check from nxt200x_readreg_multibyte, it really shouldn't be necessary. Signed-off-by: Kirk Lapray Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/frontends/nxt200x.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c index aee170805ca..4cffe7ad971 100644 --- a/drivers/media/dvb/frontends/nxt200x.c +++ b/drivers/media/dvb/frontends/nxt200x.c @@ -239,26 +239,16 @@ static int nxt200x_readreg_multibyte (struct nxt200x_state* state, u8 reg, u8* d buf = 0x80; nxt200x_writebytes(state, 0x21, &buf, 1); - /* read status */ - nxt200x_readbytes(state, 0x21, &buf, 1); - - if (buf == 0) - { - /* read the actual data */ - for(i = 0; i < len; i++) { - nxt200x_readbytes(state, 0x36 + i, &data[i], 1); - } - return 0; + /* read the actual data */ + for(i = 0; i < len; i++) { + nxt200x_readbytes(state, 0x36 + i, &data[i], 1); } + return 0; break; default: return -EINVAL; break; } - - printk(KERN_WARNING "nxt200x: Error reading multireg register 0x%02X\n",reg); - - return 0; } static void nxt200x_microcontroller_stop (struct nxt200x_state* state) -- cgit v1.2.3 From f6f4b725461d1f3e2587993b22b0c6fe524d9259 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Tue, 8 Nov 2005 21:35:52 -0800 Subject: [PATCH] dvb: Add support for the Artec T1 USB2.0 box Adding support for the Artec T1 USB2.0 box (real USB2.0) Signed-off-by: Patrick Boettcher Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/dvb-usb/dibusb-mb.c | 59 ++++++++++++++++++++++++++++++--- drivers/media/dvb/dvb-usb/dibusb.h | 4 ++- drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 5 +++ 3 files changed, 63 insertions(+), 5 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c index 0058505634a..aa271a2496d 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-mb.c +++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c @@ -82,13 +82,15 @@ static int dibusb_tuner_probe_and_attach(struct dvb_usb_device *d) static struct dvb_usb_properties dibusb1_1_properties; static struct dvb_usb_properties dibusb1_1_an2235_properties; static struct dvb_usb_properties dibusb2_0b_properties; +static struct dvb_usb_properties artec_t1_usb2_properties; static int dibusb_probe(struct usb_interface *intf, const struct usb_device_id *id) { if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE,NULL) == 0 || dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE,NULL) == 0 || - dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE,NULL) == 0) + dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE,NULL) == 0 || + dvb_usb_device_init(intf,&artec_t1_usb2_properties,THIS_MODULE,NULL) == 0) return 0; return -EINVAL; @@ -128,10 +130,13 @@ static struct usb_device_id dibusb_dib3000mb_table [] = { /* 27 */ { USB_DEVICE(USB_VID_KWORLD, USB_PID_KWORLD_VSTREAM_COLD) }, +/* 28 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) }, +/* 29 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_WARM) }, + // #define DVB_USB_DIBUSB_MB_FAULTY_USB_IDs #ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs -/* 28 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) }, +/* 30 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) }, #endif { } /* Terminating entry */ }; @@ -264,7 +269,7 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = { }, #ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs { "Artec T1 USB1.1 TVBOX with AN2235 (faulty USB IDs)", - { &dibusb_dib3000mb_table[28], NULL }, + { &dibusb_dib3000mb_table[30], NULL }, { NULL }, }, #endif @@ -273,7 +278,7 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = { static struct dvb_usb_properties dibusb2_0b_properties = { .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER, - .pid_filter_count = 32, + .pid_filter_count = 16, .usb_ctrl = CYPRESS_FX2, @@ -321,6 +326,52 @@ static struct dvb_usb_properties dibusb2_0b_properties = { } }; +static struct dvb_usb_properties artec_t1_usb2_properties = { + .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER, + .pid_filter_count = 16, + + .usb_ctrl = CYPRESS_FX2, + + .firmware = "dvb-usb-dibusb-6.0.0.8.fw", + + .size_of_priv = sizeof(struct dibusb_state), + + .streaming_ctrl = dibusb2_0_streaming_ctrl, + .pid_filter = dibusb_pid_filter, + .pid_filter_ctrl = dibusb_pid_filter_ctrl, + .power_ctrl = dibusb2_0_power_ctrl, + .frontend_attach = dibusb_dib3000mb_frontend_attach, + .tuner_attach = dibusb_tuner_probe_and_attach, + + .rc_interval = DEFAULT_RC_INTERVAL, + .rc_key_map = dibusb_rc_keys, + .rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */ + .rc_query = dibusb_rc_query, + + .i2c_algo = &dibusb_i2c_algo, + + .generic_bulk_ctrl_endpoint = 0x01, + /* parameter for the MPEG2-data transfer */ + .urb = { + .type = DVB_USB_BULK, + .count = 7, + .endpoint = 0x06, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, + + .num_device_descs = 1, + .devices = { + { "Artec T1 USB2.0", + { &dibusb_dib3000mb_table[28], NULL }, + { &dibusb_dib3000mb_table[29], NULL }, + }, + } +}; + static struct usb_driver dibusb_driver = { .owner = THIS_MODULE, .name = "dvb_usb_dibusb_mb", diff --git a/drivers/media/dvb/dvb-usb/dibusb.h b/drivers/media/dvb/dvb-usb/dibusb.h index 6611f62977c..2d99d05c7ea 100644 --- a/drivers/media/dvb/dvb-usb/dibusb.h +++ b/drivers/media/dvb/dvb-usb/dibusb.h @@ -11,7 +11,9 @@ #ifndef _DVB_USB_DIBUSB_H_ #define _DVB_USB_DIBUSB_H_ -#define DVB_USB_LOG_PREFIX "dibusb" +#ifndef DVB_USB_LOG_PREFIX + #define DVB_USB_LOG_PREFIX "dibusb" +#endif #include "dvb-usb.h" #include "dib3000.h" diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 0818996bf15..6be99e537e1 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -43,10 +43,14 @@ #define USB_PID_COMPRO_DVBU2000_WARM 0xd001 #define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d +#define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 +#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 #define USB_PID_DIBCOM_MOD3000_WARM 0x0bb9 #define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6 #define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7 +#define USB_PID_DIBCOM_STK7700 0x1e14 +#define USB_PID_DIBCOM_STK7700_REENUM 0x1e15 #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 @@ -68,6 +72,7 @@ #define USB_PID_ULTIMA_TVBOX_AN2235_WARM 0x8108 #define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD 0x2235 #define USB_PID_ULTIMA_TVBOX_USB2_COLD 0x8109 +#define USB_PID_ULTIMA_TVBOX_USB2_WARM 0x810a #define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613 #define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002 #define USB_PID_UNK_HYPER_PALTEK_COLD 0x005e -- cgit v1.2.3 From de122dfda505e693f75e73628e026e4f6250ede7 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:35:53 -0800 Subject: [PATCH] dvb: documentation updates for hybrid v4l/dvb cards Updated documentation to include "hybrid" v4l/dvb and ATSC cards. Signed-off-by: Michael Krufky Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/dvb/cards.txt | 37 +++++++++++++++++++++++++++++++++++++ Documentation/dvb/contributors.txt | 17 +++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/Documentation/dvb/cards.txt b/Documentation/dvb/cards.txt index efdc4ee9d40..19329cf7b09 100644 --- a/Documentation/dvb/cards.txt +++ b/Documentation/dvb/cards.txt @@ -41,6 +41,12 @@ o Frontends drivers: - dib3000mb : DiBcom 3000-MB demodulator DVB-S/C/T: - dst : TwinHan DST Frontend + ATSC: + - nxt200x : Nxtwave NXT2002 & NXT2004 + - or51211 : or51211 based (pcHDTV HD2000 card) + - or51132 : or51132 based (pcHDTV HD3000 card) + - bcm3510 : Broadcom BCM3510 + - lgdt330x : LG Electronics DT3302 & DT3303 o Cards based on the Phillips saa7146 multimedia PCI bridge chip: @@ -62,6 +68,10 @@ o Cards based on the Conexant Bt8xx PCI bridge: - Nebula Electronics DigiTV - TwinHan DST - Avermedia DVB-T + - ChainTech digitop DST-1000 DVB-S + - pcHDTV HD-2000 TV + - DViCO FusionHDTV DVB-T Lite + - DViCO FusionHDTV5 Lite o Technotrend / Hauppauge DVB USB devices: - Nova USB @@ -83,3 +93,30 @@ o DiBcom DVB-T USB based devices: - DiBcom USB2.0 DVB-T reference device (non-public) o Experimental support for the analog module of the Siemens DVB-C PCI card + +o Cards based on the Conexant cx2388x PCI bridge: + - ADS Tech Instant TV DVB-T PCI + - ATI HDTV Wonder + - digitalnow DNTV Live! DVB-T + - DViCO FusionHDTV DVB-T1 + - DViCO FusionHDTV DVB-T Plus + - DViCO FusionHDTV3 Gold-Q + - DViCO FusionHDTV3 Gold-T + - DViCO FusionHDTV5 Gold + - Hauppauge Nova-T DVB-T + - KWorld/VStream XPert DVB-T + - pcHDTV HD3000 HDTV + - TerraTec Cinergy 1400 DVB-T + - WinFast DTV1000-T + +o Cards based on the Phillips saa7134 PCI bridge: + - Medion 7134 + - Pinnacle PCTV 300i DVB-T + PAL + - LifeView FlyDVB-T DUO + - Typhoon DVB-T Duo Digital/Analog Cardbus + - Philips TOUGH DVB-T reference design + - Philips EUROPA V3 reference design + - Compro Videomate DVB-T300 + - Compro Videomate DVB-T200 + - AVerMedia AVerTVHD MCE A180 + diff --git a/Documentation/dvb/contributors.txt b/Documentation/dvb/contributors.txt index c9d5ce37070..2cbd2d0f6fd 100644 --- a/Documentation/dvb/contributors.txt +++ b/Documentation/dvb/contributors.txt @@ -75,5 +75,22 @@ Ernst Peinlich Peter Beutner for the IR code for the ttusb-dec driver +Wilson Michaels + for the lgdt330x frontend driver, and various bugfixes + +Michael Krufky + for maintaining v4l/dvb inter-tree dependencies + +Taylor Jacob + for the nxt2002 frontend driver + +Jean-Francois Thibert + for the nxt2004 frontend driver + +Kirk Lapray + for the or51211 and or51132 frontend drivers, and + for merging the nxt2002 and nxt2004 modules into a + single nxt200x frontend driver. + (If you think you should be in this list, but you are not, drop a line to the DVB mailing list) -- cgit v1.2.3 From d371d6a04c6b50125e8dbf9a2234cc694f6e3cdf Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 8 Nov 2005 21:35:54 -0800 Subject: [PATCH] dvb-usb-urb printk fix drivers/media/dvb/dvb-usb/dvb-usb-urb.c: In function `dvb_usb_allocate_stream_buffers': drivers/media/dvb/dvb-usb/dvb-usb-urb.c:199: warning: int format, different type arg (arg 4) Don't assume that dma_addr_t is 32-bit. (dvb has quite a few such warnings. Please compile it with a 64-bit compiler, fix them up - some are oopsable). Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/dvb-usb/dvb-usb-urb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c index f5799a4c228..36b7048c02d 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c @@ -196,7 +196,9 @@ static int dvb_usb_allocate_stream_buffers(struct dvb_usb_device *d, int num, un dvb_usb_free_stream_buffers(d); return -ENOMEM; } - deb_mem("buffer %d: %p (dma: %d)\n",d->buf_num,d->buf_list[d->buf_num],d->dma_addr[d->buf_num]); + deb_mem("buffer %d: %p (dma: %llu)\n", + d->buf_num, d->buf_list[d->buf_num], + (unsigned long long)d->dma_addr[d->buf_num]); memset(d->buf_list[d->buf_num],0,size); } deb_mem("allocation successful\n"); -- cgit v1.2.3 From 66944e998a7e1164895e9bd7cae9f841a9f46ef5 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:35:55 -0800 Subject: [PATCH] dvb: lgdt330x: Correct QAM symbol_rate_min for lgdt3302 and lgdt3303 Correct QAM symbol_rate_min for lgdt3302 and lgdt3303 Thanks to: Mac Michaels and Steve Malenfant Signed-off-by: Mac Michaels Signed-off-by: Michael Krufky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/frontends/lgdt330x.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index 10fc4e7878a..6a33f5a19a8 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c @@ -755,9 +755,8 @@ static struct dvb_frontend_ops lgdt3302_ops = { .frequency_min= 54000000, .frequency_max= 858000000, .frequency_stepsize= 62500, - /* Symbol rate is for all VSB modes need to check QAM */ - .symbol_rate_min = 10762000, - .symbol_rate_max = 10762000, + .symbol_rate_min = 5056941, /* QAM 64 */ + .symbol_rate_max = 10762000, /* VSB 8 */ .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB }, .init = lgdt330x_init, @@ -779,9 +778,8 @@ static struct dvb_frontend_ops lgdt3303_ops = { .frequency_min= 54000000, .frequency_max= 858000000, .frequency_stepsize= 62500, - /* Symbol rate is for all VSB modes need to check QAM */ - .symbol_rate_min = 10762000, - .symbol_rate_max = 10762000, + .symbol_rate_min = 5056941, /* QAM 64 */ + .symbol_rate_max = 10762000, /* VSB 8 */ .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB }, .init = lgdt330x_init, -- cgit v1.2.3 From 496157d089c3caeda35017833ea3bb895f29ed15 Mon Sep 17 00:00:00 2001 From: Kirk Lapray Date: Tue, 8 Nov 2005 21:35:55 -0800 Subject: [PATCH] dvb: nxt200x: Fix typo in Makefile for nxt200x - Fix Typo: Change CONFIG_DVB_NXT2002 to CONFIG_DVB_NXT200X for the nxt200x module. Signed-off-by: Kirk Lapray Signed-off-by: Michael Krufky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/frontends/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 1692ee65ba5..a98760fe08a 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -26,7 +26,7 @@ obj-$(CONFIG_DVB_TDA80XX) += tda80xx.o obj-$(CONFIG_DVB_TDA10021) += tda10021.o obj-$(CONFIG_DVB_STV0297) += stv0297.o obj-$(CONFIG_DVB_NXT2002) += nxt2002.o -obj-$(CONFIG_DVB_NXT2002) += nxt200x.o +obj-$(CONFIG_DVB_NXT200X) += nxt200x.o obj-$(CONFIG_DVB_OR51211) += or51211.o obj-$(CONFIG_DVB_OR51132) += or51132.o obj-$(CONFIG_DVB_BCM3510) += bcm3510.o -- cgit v1.2.3 From cc952d03c0c36ec9a4c2a683015dbb98e8a889df Mon Sep 17 00:00:00 2001 From: Kirk Lapray Date: Tue, 8 Nov 2005 21:36:02 -0800 Subject: [PATCH] dvb: nxt200x: Add function for nxt200x to change pll input - Added function for nxt200x to change pll input - For VSB set to input 0, for QAM set to input 1 - will only be set for cards that have set_pll_input defined Signed-off-by: Kirk Lapray Signed-off-by: Michael Krufky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/frontends/nxt200x.c | 9 +++++++-- drivers/media/dvb/frontends/nxt200x.h | 3 +++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c index 4cffe7ad971..bad0933eb71 100644 --- a/drivers/media/dvb/frontends/nxt200x.c +++ b/drivers/media/dvb/frontends/nxt200x.c @@ -556,13 +556,18 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, if (state->config->set_ts_params) state->config->set_ts_params(fe, 1); - /* set to use cable input */ - buf[3] |= 0x08; + /* set input */ + if (state->config->set_pll_input) + state->config->set_pll_input(buf, 1); break; case VSB_8: /* Set non-punctured clock for VSB */ if (state->config->set_ts_params) state->config->set_ts_params(fe, 0); + + /* set input */ + if (state->config->set_pll_input) + state->config->set_pll_input(buf, 0); break; default: return -EINVAL; diff --git a/drivers/media/dvb/frontends/nxt200x.h b/drivers/media/dvb/frontends/nxt200x.h index 8dc3f03ecdf..1d9d70bc37e 100644 --- a/drivers/media/dvb/frontends/nxt200x.h +++ b/drivers/media/dvb/frontends/nxt200x.h @@ -42,6 +42,9 @@ struct nxt200x_config u8 pll_address; struct dvb_pll_desc *pll_desc; + /* used to set pll input */ + int (*set_pll_input)(u8* buf, int input); + /* need to set device param for start_dma */ int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured); }; -- cgit v1.2.3 From 2d14f78e4bfa55e5a534cc4c03ddab8841a1b32e Mon Sep 17 00:00:00 2001 From: Glen Gray Date: Tue, 8 Nov 2005 21:36:12 -0800 Subject: [PATCH] v4l: 627: added support for oem version of flytv platinum mini with a - Added support for OEM version of FlyTV Platinum mini with a subvendor id of 0x4e42. - Added the OEM PCI id's to the docs/CARDLIST.saa7134 for item 39 - Modified the vmux in the SAA7134_BOARD_FLYTVPLATINUM_MINI driver data from 0 (Composite over S-Video) to 3 (Composite). Signed-off-by: Glen Gray Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.saa7134 | 2 +- drivers/media/video/saa7134/saa7134-cards.c | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index dc57225f39b..33b6cf9bc1b 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -37,7 +37,7 @@ 36 -> UPMOST PURPLE TV [12ab:0800] 37 -> Items MuchTV Plus / IT-005 38 -> Terratec Cinergy 200 TV [153B:1152] - 39 -> LifeView FlyTV Platinum Mini [5168:0212] + 39 -> LifeView FlyTV Platinum Mini [5168:0212,4e42:0212] 40 -> Compro VideoMate TV PVR/FM [185b:c100] 41 -> Compro VideoMate TV Gold+ [185b:c100] 42 -> Sabrent SBT-TVFM (saa7130) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index acc7a4335e2..a67a0a11c6d 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -191,9 +191,13 @@ struct saa7134_board saa7134_boards[] = { .amux = TV, .tv = 1, },{ - .name = name_comp1, + .name = name_comp1, /* Composite signal on S-Video input */ .vmux = 0, .amux = LINE2, + },{ + .name = name_comp2, /* Composite input */ + .vmux = 3, + .amux = LINE2, },{ .name = name_svideo, .vmux = 8, @@ -2190,6 +2194,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x5168, .subdevice = 0x0212, /* minipci, LR212 */ .driver_data = SAA7134_BOARD_FLYTVPLATINUM_MINI, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x4e42, + .subdevice = 0x0212, /* OEM minipci, LR212 */ + .driver_data = SAA7134_BOARD_FLYTVPLATINUM_MINI, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, -- cgit v1.2.3 From d45170ed6731a55885386f0e8d04578f77d3045d Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:36:15 -0800 Subject: [PATCH] v4l: 628: added new avermedia card 550 - Added new Avermedia card 550 Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.cx88 | 1 + drivers/media/video/cx88/cx88-cards.c | 31 +++++++++++++++++++++++++++++++ drivers/media/video/cx88/cx88.h | 1 + 3 files changed, 33 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 03deb0726aa..fa7e38567d8 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -30,3 +30,4 @@ card=28 - DViCO FusionHDTV 3 Gold-T card=29 - ADS Tech Instant TV DVB-T PCI card=30 - TerraTec Cinergy 1400 DVB-T card=31 - DViCO FusionHDTV 5 Gold +card=32 - AverMedia UltraTV Media Center PCI 550 diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 4da91d535a5..8d840afc745 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -776,6 +776,33 @@ struct cx88_board cx88_boards[] = { }}, .dvb = 1, }, + [CX88_BOARD_AVERMEDIA_ULTRATV_MC_550] = { + .name = "AverMedia UltraTV Media Center PCI 550", + .tuner_type = TUNER_PHILIPS_FM1236_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .blackbird = 1, + .input = {{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 0, + .gpio0 = 0x0000cd73, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 1, + .gpio0 = 0x0000cd73, + },{ + .type = CX88_VMUX_TELEVISION, + .vmux = 3, + .gpio0 = 0x0000cdb3, + }}, + .radio = { + .type = CX88_RADIO, + .vmux = 2, + .gpio0 = 0x0000cdf3, + }, + }, }; const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); @@ -907,6 +934,10 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x18ac, .subdevice = 0xd500, .card = CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD, + },{ + .subvendor = 0x1461, + .subdevice = 0x8011, + .card = CX88_BOARD_AVERMEDIA_ULTRATV_MC_550, }, }; const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index f48dd435356..88050a0043a 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -174,6 +174,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_ADSTECH_DVB_T_PCI 29 #define CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1 30 #define CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD 31 +#define CX88_BOARD_AVERMEDIA_ULTRATV_MC_550 32 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- cgit v1.2.3 From a8ff417e7310c63b890cbd94c67043ec153f8709 Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:36:16 -0800 Subject: [PATCH] v4l: 629: added behold tv 409 fm - Added Behold TV 409 FM Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 36 ++++++++++++++++++++++++++++- drivers/media/video/saa7134/saa7134-input.c | 1 + drivers/media/video/saa7134/saa7134.h | 1 + 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 33b6cf9bc1b..24a04af5d4b 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -65,3 +65,4 @@ 64 -> FlyTV mini Asus Digimatrix [1043:0210,1043:0210] 65 -> V-Stream Studio TV Terminator 66 -> Yuan TUN-900 (saa7135) + 67 -> Beholder BeholdTV 409 FM [0000:4091] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index a67a0a11c6d..9491999e632 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2113,9 +2113,36 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x01, }, }, + [SAA7134_BOARD_BEHOLD_409FM] = { + /* , Sergey */ + .name = "Beholder BeholdTV 409 FM", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + }}, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, }; - const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); /* ------------------------------------------------------------------ */ @@ -2472,6 +2499,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .driver_data = SAA7134_BOARD_FLYTV_DIGIMATRIX, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x0000, /* It shouldn't break anything, since subdevice id seems unique */ + .subdevice = 0x4091, + .driver_data = SAA7134_BOARD_BEHOLD_409FM, + },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -2562,6 +2595,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: case SAA7134_BOARD_MANLI_MTV001: case SAA7134_BOARD_MANLI_MTV002: + case SAA7134_BOARD_BEHOLD_409FM: case SAA7134_BOARD_AVACSSMARTTV: dev->has_remote = 1; break; diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 242cb235cf9..8e2cc9d75cd 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -516,6 +516,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) break; case SAA7134_BOARD_MANLI_MTV001: case SAA7134_BOARD_MANLI_MTV002: + case SAA7134_BOARD_BEHOLD_409FM: ir_codes = manli_codes; mask_keycode = 0x001f00; mask_keyup = 0x004000; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 860b89530e2..45fe6af1ecc 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -187,6 +187,7 @@ struct saa7134_format { #define SAA7134_BOARD_FLYTV_DIGIMATRIX 64 #define SAA7134_BOARD_KWORLD_TERMINATOR 65 #define SAA7134_BOARD_YUAN_TUN900 66 +#define SAA7134_BOARD_BEHOLD_409FM 67 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From 7df64e8c9cee596c2609c99b0ca1ebb6ae2d5b1d Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:36:16 -0800 Subject: [PATCH] v4l: 630: capitalized hex a f changed to lowercase in pci subsystem id constants - Capitalized hex A-F changed to lowercase in pci subsystem id constants Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.saa7134 | 8 ++++---- drivers/media/video/cx88/cx88-cards.c | 14 +++++++------- drivers/media/video/saa7134/saa7134-cards.c | 8 ++++---- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 24a04af5d4b..f31c2f8e404 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -6,10 +6,10 @@ 5 -> SKNet Monster TV [1131:4e85] 6 -> Tevion MD 9717 7 -> KNC One TV-Station RDS / Typhoon TV Tuner RDS [1131:fe01,1894:fe01] - 8 -> Terratec Cinergy 400 TV [153B:1142] + 8 -> Terratec Cinergy 400 TV [153b:1142] 9 -> Medion 5044 10 -> Kworld/KuroutoShikou SAA7130-TVPCI - 11 -> Terratec Cinergy 600 TV [153B:1143] + 11 -> Terratec Cinergy 600 TV [153b:1143] 12 -> Medion 7134 [16be:0003] 13 -> Typhoon TV+Radio 90031 14 -> ELSA EX-VISION 300TV [1048:226b] @@ -36,7 +36,7 @@ 35 -> AverMedia AverTV Studio 305 [1461:2115] 36 -> UPMOST PURPLE TV [12ab:0800] 37 -> Items MuchTV Plus / IT-005 - 38 -> Terratec Cinergy 200 TV [153B:1152] + 38 -> Terratec Cinergy 200 TV [153b:1152] 39 -> LifeView FlyTV Platinum Mini [5168:0212,4e42:0212] 40 -> Compro VideoMate TV PVR/FM [185b:c100] 41 -> Compro VideoMate TV Gold+ [185b:c100] @@ -46,7 +46,7 @@ 45 -> Avermedia AVerTV Studio 307 [1461:9715] 46 -> AVerMedia Cardbus TV/Radio (E500) [1461:d6ee] 47 -> Terratec Cinergy 400 mobile [153b:1162] - 48 -> Terratec Cinergy 600 TV MK3 [153B:1158] + 48 -> Terratec Cinergy 600 TV MK3 [153b:1158] 49 -> Compro VideoMate Gold+ Pal [185b:c200] 50 -> Pinnacle PCTV 300i DVB-T + PAL [11bd:002d] 51 -> ProVideo PV952 [1540:9524] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 8d840afc745..5a85802047f 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -879,8 +879,8 @@ struct cx88_subid cx88_subids[] = { .subdevice = 0xd820, .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T, },{ - .subvendor = 0x18AC, - .subdevice = 0xDB00, + .subvendor = 0x18ac, + .subdevice = 0xdb00, .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1, },{ .subvendor = 0x0070, @@ -895,8 +895,8 @@ struct cx88_subid cx88_subids[] = { .subdevice = 0x2580, .card = CX88_BOARD_PROVIDEO_PV259, },{ - .subvendor = 0x18AC, - .subdevice = 0xDB10, + .subvendor = 0x18ac, + .subdevice = 0xdb10, .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS, },{ .subvendor = 0x1554, @@ -907,15 +907,15 @@ struct cx88_subid cx88_subids[] = { .subdevice = 0x3000, /* HD-3000 card */ .card = CX88_BOARD_PCHDTV_HD3000, },{ - .subvendor = 0x17DE, - .subdevice = 0xA8A6, + .subvendor = 0x17de, + .subdevice = 0xa8a6, .card = CX88_BOARD_DNTV_LIVE_DVB_T, },{ .subvendor = 0x0070, .subdevice = 0x2801, .card = CX88_BOARD_HAUPPAUGE_ROSLYN, },{ - .subvendor = 0x14F1, + .subvendor = 0x14f1, .subdevice = 0x0342, .card = CX88_BOARD_DIGITALLOGIC_MEC, },{ diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 9491999e632..bca5b7038a8 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2176,19 +2176,19 @@ struct pci_device_id saa7134_pci_tbl[] = { },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x153B, + .subvendor = 0x153b, .subdevice = 0x1142, .driver_data = SAA7134_BOARD_CINERGY400, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x153B, + .subvendor = 0x153b, .subdevice = 0x1143, .driver_data = SAA7134_BOARD_CINERGY600, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x153B, + .subvendor = 0x153b, .subdevice = 0x1158, .driver_data = SAA7134_BOARD_CINERGY600_MK3, },{ @@ -2406,7 +2406,7 @@ struct pci_device_id saa7134_pci_tbl[] = { },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x153B, + .subvendor = 0x153b, .subdevice = 0x1152, .driver_data = SAA7134_BOARD_CINERGY200, },{ -- cgit v1.2.3 From 31629424132c87f7c8bd79d7ed4d014354a06427 Mon Sep 17 00:00:00 2001 From: Catalin Climov Date: Tue, 8 Nov 2005 21:36:17 -0800 Subject: [PATCH] v4l: 631: implemented the v4l2 mpeg api for blackbird cards - Implemented the v4l2 mpeg api for blackbird cards. Signed-off-by: Catalin Climov Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/cx88-blackbird.c | 638 +++++++++++++++++++++++++++--- drivers/media/video/cx88/cx88-mpeg.c | 7 +- drivers/media/video/cx88/cx88-video.c | 2 - drivers/media/video/cx88/cx88.h | 19 +- 4 files changed, 595 insertions(+), 71 deletions(-) diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 0c0c59e9477..eca36b8539f 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -38,7 +38,7 @@ MODULE_AUTHOR("Jelle Foks "); MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); -static unsigned int mpegbufs = 8; +static unsigned int mpegbufs = 32; module_param(mpegbufs,int,0644); MODULE_PARM_DESC(mpegbufs,"number of mpeg buffers, range 2-32"); @@ -683,84 +683,553 @@ DB* DVD | MPEG2 | 720x576PAL | CBR | 600 :Good | 6000 Kbps | 25fps | M ================================================================================================================= *DB: "DirectBurn" */ -static void blackbird_codec_settings(struct cx8802_dev *dev) + +static struct blackbird_dnr default_dnr_params = { + .mode = BLACKBIRD_DNR_BITS_MANUAL, + .type = BLACKBIRD_MEDIAN_FILTER_DISABLED, + .spatial = 0, + .temporal = 0 +}; +static struct v4l2_mpeg_compression default_mpeg_params = { + .st_type = V4L2_MPEG_PS_2, + .st_bitrate = { + .mode = V4L2_BITRATE_CBR, + .min = 0, + .target = 0, + .max = 0 + }, + .ts_pid_pmt = 16, + .ts_pid_audio = 260, + .ts_pid_video = 256, + .ts_pid_pcr = 259, + .ps_size = 0, + .au_type = V4L2_MPEG_AU_2_II, + .au_bitrate = { + .mode = V4L2_BITRATE_CBR, + .min = 224, + .target = 224, + .max = 224 + }, + .au_sample_rate = 44100, + .au_pesid = 0, + .vi_type = V4L2_MPEG_VI_2, + .vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3, + .vi_bitrate = { + .mode = V4L2_BITRATE_CBR, + .min = 4000, + .target = 4500, + .max = 6000 + }, + .vi_frame_rate = 25, + .vi_frames_per_gop = 15, + .vi_bframes_count = 2, + .vi_pesid = 0, + .closed_gops = 0, + .pulldown = 0 +}; + +static enum blackbird_stream_type mpeg_stream_types[] = { + [V4L2_MPEG_SS_1] = BLACKBIRD_STREAM_MPEG1, + [V4L2_MPEG_PS_2] = BLACKBIRD_STREAM_PROGRAM, + [V4L2_MPEG_TS_2] = BLACKBIRD_STREAM_TRANSPORT, + [V4L2_MPEG_PS_DVD] = BLACKBIRD_STREAM_DVD, +}; +static enum blackbird_aspect_ratio mpeg_stream_ratios[] = { + [V4L2_MPEG_ASPECT_SQUARE] = BLACKBIRD_ASPECT_RATIO_1_1_SQUARE, + [V4L2_MPEG_ASPECT_4_3] = BLACKBIRD_ASPECT_RATIO_4_3, + [V4L2_MPEG_ASPECT_16_9] = BLACKBIRD_ASPECT_RATIO_16_9, + [V4L2_MPEG_ASPECT_1_221] = BLACKBIRD_ASPECT_RATIO_221_100, +}; +static enum blackbird_video_bitrate_type mpeg_video_bitrates[] = { + [V4L2_BITRATE_NONE] = BLACKBIRD_VIDEO_CBR, + [V4L2_BITRATE_CBR] = BLACKBIRD_VIDEO_CBR, + [V4L2_BITRATE_VBR] = BLACKBIRD_VIDEO_VBR, +}; +/* find the best layer I/II bitrate to fit a given numeric value */ +struct bitrate_bits { + u32 bits; /* layer bits for the best fit */ + u32 rate; /* actual numeric value for the layer best fit */ +}; +struct bitrate_approximation { + u32 target; /* numeric value of the rate we want */ + struct bitrate_bits layer[2]; +}; +static struct bitrate_approximation mpeg_audio_bitrates[] = { + /* target layer[0].bits layer[0].rate layer[1].bits layer[1].rate */ + { 0, { { 0, 0, }, { 0, 0, }, }, }, + { 32, { { BLACKBIRD_AUDIO_BITS_LAYER_1_32 , 32, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_32 , 32, }, }, }, + { 48, { { BLACKBIRD_AUDIO_BITS_LAYER_1_64 , 64, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_48 , 48, }, }, }, + { 56, { { BLACKBIRD_AUDIO_BITS_LAYER_1_64 , 64, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_56 , 56, }, }, }, + { 64, { { BLACKBIRD_AUDIO_BITS_LAYER_1_64 , 64, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_64 , 64, }, }, }, + { 80, { { BLACKBIRD_AUDIO_BITS_LAYER_1_96 , 96, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_80 , 80, }, }, }, + { 96, { { BLACKBIRD_AUDIO_BITS_LAYER_1_96 , 96, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_96 , 96, }, }, }, + { 112, { { BLACKBIRD_AUDIO_BITS_LAYER_1_128, 128, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_112, 112, }, }, }, + { 128, { { BLACKBIRD_AUDIO_BITS_LAYER_1_128, 128, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_128, 128, }, }, }, + { 160, { { BLACKBIRD_AUDIO_BITS_LAYER_1_160, 160, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_160, 160, }, }, }, + { 192, { { BLACKBIRD_AUDIO_BITS_LAYER_1_192, 192, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_192, 192, }, }, }, + { 224, { { BLACKBIRD_AUDIO_BITS_LAYER_1_224, 224, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_224, 224, }, }, }, + { 256, { { BLACKBIRD_AUDIO_BITS_LAYER_1_256, 256, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_256, 256, }, }, }, + { 288, { { BLACKBIRD_AUDIO_BITS_LAYER_1_288, 288, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_320, 320, }, }, }, + { 320, { { BLACKBIRD_AUDIO_BITS_LAYER_1_320, 320, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_320, 320, }, }, }, + { 352, { { BLACKBIRD_AUDIO_BITS_LAYER_1_352, 352, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, }, + { 384, { { BLACKBIRD_AUDIO_BITS_LAYER_1_384, 384, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, }, + { 416, { { BLACKBIRD_AUDIO_BITS_LAYER_1_416, 416, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, }, + { 448, { { BLACKBIRD_AUDIO_BITS_LAYER_1_448, 448, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, }, +}; +static const int BITRATES_SIZE = ARRAY_SIZE(mpeg_audio_bitrates); + +static void blackbird_set_default_params(struct cx8802_dev *dev) { - int bitrate_mode = 1; - int bitrate = 7500000; - int bitrate_peak = 7500000; - bitrate_mode = BLACKBIRD_VIDEO_CBR; - bitrate = 4000*1024; - bitrate_peak = 4000*1024; + struct v4l2_mpeg_compression *params = &dev->params; /* assign stream type */ - blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, BLACKBIRD_STREAM_PROGRAM); - - /* assign output port */ - blackbird_api_cmd(dev, BLACKBIRD_API_SET_OUTPUT_PORT, 1, 0, BLACKBIRD_OUTPUT_PORT_STREAMING); /* Host */ + if( params->st_type >= ARRAY_SIZE(mpeg_stream_types) ) + params->st_type = V4L2_MPEG_PS_2; + if( params->st_type == V4L2_MPEG_SS_1 ) + params->vi_type = V4L2_MPEG_VI_1; + else + params->vi_type = V4L2_MPEG_VI_2; + blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, mpeg_stream_types[params->st_type]); /* assign framerate */ - blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_PAL_25); - - /* assign frame size */ - blackbird_api_cmd(dev, BLACKBIRD_API_SET_RESOLUTION, 2, 0, - dev->height, dev->width); + if( params->vi_frame_rate <= 25 ) + { + params->vi_frame_rate = 25; + blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_PAL_25); + } + else + { + params->vi_frame_rate = 30; + blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_NTSC_30); + } /* assign aspect ratio */ - blackbird_api_cmd(dev, BLACKBIRD_API_SET_ASPECT_RATIO, 1, 0, BLACKBIRD_ASPECT_RATIO_4_3); - - /* assign bitrates */ - blackbird_api_cmd(dev, BLACKBIRD_API_SET_VIDEO_BITRATE, 5, 0, - bitrate_mode, /* mode */ - bitrate, /* bps */ - bitrate_peak / BLACKBIRD_PEAK_RATE_DIVISOR, /* peak/400 */ - BLACKBIRD_MUX_RATE_DEFAULT /*, 0x70*/); /* encoding buffer, ckennedy */ + if( params->vi_aspect_ratio >= ARRAY_SIZE(mpeg_stream_ratios) ) + params->vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3; + blackbird_api_cmd(dev, BLACKBIRD_API_SET_ASPECT_RATIO, 1, 0, mpeg_stream_ratios[params->vi_aspect_ratio]); /* assign gop properties */ - blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_STRUCTURE, 2, 0, 15, 3); + blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_STRUCTURE, 2, 0, params->vi_frames_per_gop, params->vi_bframes_count+1); + + /* assign gop closure */ + blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_CLOSURE, 1, 0, params->closed_gops); /* assign 3 2 pulldown */ - blackbird_api_cmd(dev, BLACKBIRD_API_SET_3_2_PULLDOWN, 1, 0, BLACKBIRD_3_2_PULLDOWN_DISABLED); + blackbird_api_cmd(dev, BLACKBIRD_API_SET_3_2_PULLDOWN, 1, 0, params->pulldown); + + /* make sure the params are within bounds */ + if( params->st_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) + params->vi_bitrate.mode = V4L2_BITRATE_NONE; + if( params->vi_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) + params->vi_bitrate.mode = V4L2_BITRATE_NONE; + if( params->au_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) + params->au_bitrate.mode = V4L2_BITRATE_NONE; /* assign audio properties */ /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */ - /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, (2<<2) | (8<<4)); - blackbird_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, 0 | (2 << 2) | (14 << 4)); */ - blackbird_api_cmd(dev, BLACKBIRD_API_SET_AUDIO_PARAMS, 1, 0, - BLACKBIRD_AUDIO_BITS_44100HZ | - BLACKBIRD_AUDIO_BITS_LAYER_2 | - BLACKBIRD_AUDIO_BITS_LAYER_2_224 | - BLACKBIRD_AUDIO_BITS_STEREO | + u32 au_params = BLACKBIRD_AUDIO_BITS_STEREO | /* BLACKBIRD_AUDIO_BITS_BOUND_4 | */ BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE | BLACKBIRD_AUDIO_BITS_CRC_OFF | BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF | - BLACKBIRD_AUDIO_BITS_COPY - ); + BLACKBIRD_AUDIO_BITS_COPY | + 0; + if( params->au_sample_rate <= 32000 ) + { + params->au_sample_rate = 32000; + au_params |= BLACKBIRD_AUDIO_BITS_32000HZ; + } + else if( params->au_sample_rate <= 44100 ) + { + params->au_sample_rate = 44100; + au_params |= BLACKBIRD_AUDIO_BITS_44100HZ; + } + else + { + params->au_sample_rate = 48000; + au_params |= BLACKBIRD_AUDIO_BITS_48000HZ; + } + if( params->au_type == V4L2_MPEG_AU_2_I ) + { + au_params |= BLACKBIRD_AUDIO_BITS_LAYER_1; + } + else + { + /* TODO: try to handle the other formats more gracefully */ + params->au_type = V4L2_MPEG_AU_2_II; + au_params |= BLACKBIRD_AUDIO_BITS_LAYER_2; + } + if( params->au_bitrate.mode ) + { + if( params->au_bitrate.mode == V4L2_BITRATE_CBR ) + params->au_bitrate.max = params->vi_bitrate.target; + else + params->au_bitrate.target = params->vi_bitrate.max; + + int layer = params->au_type; + if( params->au_bitrate.target == 0 ) + { + /* TODO: use the minimum possible bitrate instead of 0 ? */ + au_params |= 0; + } + else if( params->au_bitrate.target >= + mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate ) + { + /* clamp the bitrate to the max supported by the standard */ + params->au_bitrate.target = mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate; + params->au_bitrate.max = params->au_bitrate.target; + au_params |= mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].bits; + } + else + { + /* round up to the nearest supported bitrate */ + int i; + for(i = 1; i < BITRATES_SIZE; i++) + { + if( params->au_bitrate.target > mpeg_audio_bitrates[i-1].layer[layer].rate && + params->au_bitrate.target <= mpeg_audio_bitrates[i].layer[layer].rate ) + { + params->au_bitrate.target = mpeg_audio_bitrates[i].layer[layer].rate; + params->au_bitrate.max = params->au_bitrate.target; + au_params |= mpeg_audio_bitrates[i].layer[layer].bits; + break; + } + } + } + } + else + { + /* TODO: ??? */ + params->au_bitrate.target = params->au_bitrate.max = 0; + au_params |= 0; + } + blackbird_api_cmd(dev, BLACKBIRD_API_SET_AUDIO_PARAMS, 1, 0, au_params ); + + /* assign bitrates */ + if( params->vi_bitrate.mode ) + { + /* bitrate is set, let's figure out the cbr/vbr mess */ + if( params->vi_bitrate.max < params->vi_bitrate.target ) + { + if( params->vi_bitrate.mode == V4L2_BITRATE_CBR ) + params->vi_bitrate.max = params->vi_bitrate.target; + else + params->vi_bitrate.target = params->vi_bitrate.max; + } + } + else + { + if( params->st_bitrate.max < params->st_bitrate.target ) + { + if( params->st_bitrate.mode == V4L2_BITRATE_VBR ) + params->st_bitrate.target = params->st_bitrate.max; + else + params->st_bitrate.max = params->st_bitrate.target; + } + /* calculate vi_bitrate = st_bitrate - au_bitrate */ + params->vi_bitrate.max = params->st_bitrate.max - params->au_bitrate.max; + params->vi_bitrate.target = params->st_bitrate.target - params->au_bitrate.target; + } + blackbird_api_cmd(dev, BLACKBIRD_API_SET_VIDEO_BITRATE, 4, 0, + mpeg_video_bitrates[params->vi_bitrate.mode], + params->vi_bitrate.target * 1000, /* kbps -> bps */ + params->vi_bitrate.max * 1000 / BLACKBIRD_PEAK_RATE_DIVISOR, /* peak/400 */ + BLACKBIRD_MUX_RATE_DEFAULT /*, 0x70*/); /* encoding buffer, ckennedy */ + + /* TODO: implement the stream ID stuff: + ts_pid_pmt, ts_pid_audio, ts_pid_video, ts_pid_pcr, + ps_size, au_pesid, vi_pesid + */ +} +#define CHECK_PARAM( name ) ( dev->params.name != params->name ) +#define IF_PARAM( name ) if( CHECK_PARAM( name ) ) +#define UPDATE_PARAM( name ) dev->params.name = params->name +void blackbird_set_params(struct cx8802_dev *dev, struct v4l2_mpeg_compression *params) +{ + /* assign stream type */ + if( params->st_type >= ARRAY_SIZE(mpeg_stream_types) ) + params->st_type = V4L2_MPEG_PS_2; + if( params->st_type == V4L2_MPEG_SS_1 ) + params->vi_type = V4L2_MPEG_VI_1; + else + params->vi_type = V4L2_MPEG_VI_2; + if( CHECK_PARAM( st_type ) || CHECK_PARAM( vi_type ) ) + { + UPDATE_PARAM( st_type ); + UPDATE_PARAM( vi_type ); + blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, mpeg_stream_types[params->st_type]); + } + + /* assign framerate */ + if( params->vi_frame_rate <= 25 ) + params->vi_frame_rate = 25; + else + params->vi_frame_rate = 30; + IF_PARAM( vi_frame_rate ) + { + UPDATE_PARAM( vi_frame_rate ); + if( params->vi_frame_rate == 25 ) + blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_PAL_25); + else + blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_NTSC_30); + } + + /* assign aspect ratio */ + if( params->vi_aspect_ratio >= ARRAY_SIZE(mpeg_stream_ratios) ) + params->vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3; + IF_PARAM( vi_aspect_ratio ) + { + UPDATE_PARAM( vi_aspect_ratio ); + blackbird_api_cmd(dev, BLACKBIRD_API_SET_ASPECT_RATIO, 1, 0, mpeg_stream_ratios[params->vi_aspect_ratio]); + } + + /* assign gop properties */ + if( CHECK_PARAM( vi_frames_per_gop ) || CHECK_PARAM( vi_bframes_count ) ) + { + UPDATE_PARAM( vi_frames_per_gop ); + UPDATE_PARAM( vi_bframes_count ); + blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_STRUCTURE, 2, 0, params->vi_frames_per_gop, params->vi_bframes_count+1); + } /* assign gop closure */ - blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_CLOSURE, 1, 0, BLACKBIRD_GOP_CLOSURE_OFF); + IF_PARAM( closed_gops ) + { + UPDATE_PARAM( closed_gops ); + blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_CLOSURE, 1, 0, params->closed_gops); + } + + /* assign 3 2 pulldown */ + IF_PARAM( pulldown ) + { + UPDATE_PARAM( pulldown ); + blackbird_api_cmd(dev, BLACKBIRD_API_SET_3_2_PULLDOWN, 1, 0, params->pulldown); + } + + /* make sure the params are within bounds */ + if( params->st_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) + params->vi_bitrate.mode = V4L2_BITRATE_NONE; + if( params->vi_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) + params->vi_bitrate.mode = V4L2_BITRATE_NONE; + if( params->au_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) + params->au_bitrate.mode = V4L2_BITRATE_NONE; + + /* assign audio properties */ + /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */ + u32 au_params = BLACKBIRD_AUDIO_BITS_STEREO | + /* BLACKBIRD_AUDIO_BITS_BOUND_4 | */ + BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE | + BLACKBIRD_AUDIO_BITS_CRC_OFF | + BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF | + BLACKBIRD_AUDIO_BITS_COPY | + 0; + if( params->au_sample_rate < 32000 ) + { + params->au_sample_rate = 32000; + au_params |= BLACKBIRD_AUDIO_BITS_32000HZ; + } + else if( params->au_sample_rate < 44100 ) + { + params->au_sample_rate = 44100; + au_params |= BLACKBIRD_AUDIO_BITS_44100HZ; + } + else + { + params->au_sample_rate = 48000; + au_params |= BLACKBIRD_AUDIO_BITS_48000HZ; + } + if( params->au_type == V4L2_MPEG_AU_2_I ) + { + au_params |= BLACKBIRD_AUDIO_BITS_LAYER_1; + } + else + { + /* TODO: try to handle the other formats more gracefully */ + params->au_type = V4L2_MPEG_AU_2_II; + au_params |= BLACKBIRD_AUDIO_BITS_LAYER_2; + } + if( params->au_bitrate.mode ) + { + if( params->au_bitrate.mode == V4L2_BITRATE_CBR ) + params->au_bitrate.max = params->vi_bitrate.target; + else + params->au_bitrate.target = params->vi_bitrate.max; + int layer = params->au_type; + if( params->au_bitrate.target == 0 ) + { + /* TODO: use the minimum possible bitrate instead of 0 ? */ + au_params |= 0; + } + else if( params->au_bitrate.target >= + mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate ) + { + /* clamp the bitrate to the max supported by the standard */ + params->au_bitrate.target = mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate; + params->au_bitrate.max = params->au_bitrate.target; + au_params |= mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].bits; + } + else + { + /* round up to the nearest supported bitrate */ + int i; + for(i = 1; i < BITRATES_SIZE; i++) + { + if( params->au_bitrate.target > mpeg_audio_bitrates[i-1].layer[layer].rate && + params->au_bitrate.target <= mpeg_audio_bitrates[i].layer[layer].rate ) + { + params->au_bitrate.target = mpeg_audio_bitrates[i].layer[layer].rate; + params->au_bitrate.max = params->au_bitrate.target; + au_params |= mpeg_audio_bitrates[i].layer[layer].bits; + break; + } + } + } + } + else + { + /* TODO: ??? */ + params->au_bitrate.target = params->au_bitrate.max = 0; + au_params |= 0; + } + if( CHECK_PARAM( au_type ) || CHECK_PARAM( au_sample_rate ) + || CHECK_PARAM( au_bitrate.mode ) || CHECK_PARAM( au_bitrate.max ) + || CHECK_PARAM( au_bitrate.target ) + ) + { + UPDATE_PARAM( au_type ); + UPDATE_PARAM( au_sample_rate ); + UPDATE_PARAM( au_bitrate ); + blackbird_api_cmd(dev, BLACKBIRD_API_SET_AUDIO_PARAMS, 1, 0, au_params ); + } + /* assign bitrates */ + if( params->vi_bitrate.mode ) + { + /* bitrate is set, let's figure out the cbr/vbr mess */ + if( params->vi_bitrate.max < params->vi_bitrate.target ) + { + if( params->vi_bitrate.mode == V4L2_BITRATE_CBR ) + params->vi_bitrate.max = params->vi_bitrate.target; + else + params->vi_bitrate.target = params->vi_bitrate.max; + } + } + else + { + if( params->st_bitrate.max < params->st_bitrate.target ) + { + if( params->st_bitrate.mode == V4L2_BITRATE_VBR ) + params->st_bitrate.target = params->st_bitrate.max; + else + params->st_bitrate.max = params->st_bitrate.target; + } + /* calculate vi_bitrate = st_bitrate - au_bitrate */ + params->vi_bitrate.max = params->st_bitrate.max - params->au_bitrate.max; + params->vi_bitrate.target = params->st_bitrate.target - params->au_bitrate.target; + } + UPDATE_PARAM( st_bitrate ); + if( CHECK_PARAM( vi_bitrate.mode ) || CHECK_PARAM( vi_bitrate.max ) + || CHECK_PARAM( vi_bitrate.target ) + ) + { + UPDATE_PARAM( vi_bitrate ); + blackbird_api_cmd(dev, BLACKBIRD_API_SET_VIDEO_BITRATE, 4, 0, + mpeg_video_bitrates[params->vi_bitrate.mode], + params->vi_bitrate.target * 1000, /* kbps -> bps */ + params->vi_bitrate.max * 1000 / BLACKBIRD_PEAK_RATE_DIVISOR, /* peak/400 */ + BLACKBIRD_MUX_RATE_DEFAULT /*, 0x70*/); /* encoding buffer, ckennedy */ + } + + /* TODO: implement the stream ID stuff: + ts_pid_pmt, ts_pid_audio, ts_pid_video, ts_pid_pcr, + ps_size, au_pesid, vi_pesid + */ + UPDATE_PARAM( ts_pid_pmt ); + UPDATE_PARAM( ts_pid_audio ); + UPDATE_PARAM( ts_pid_video ); + UPDATE_PARAM( ts_pid_pcr ); + UPDATE_PARAM( ps_size ); + UPDATE_PARAM( au_pesid ); + UPDATE_PARAM( vi_pesid ); +} + +static void blackbird_set_default_dnr_params(struct cx8802_dev *dev) +{ /* assign dnr filter mode */ + if( dev->dnr_params.mode > BLACKBIRD_DNR_BITS_AUTO ) + dev->dnr_params.mode = BLACKBIRD_DNR_BITS_MANUAL; + if( dev->dnr_params.type > BLACKBIRD_MEDIAN_FILTER_DIAGONAL ) + dev->dnr_params.type = BLACKBIRD_MEDIAN_FILTER_DISABLED; blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MODE, 2, 0, - BLACKBIRD_DNR_BITS_MANUAL, - BLACKBIRD_MEDIAN_FILTER_DISABLED - ); + dev->dnr_params.mode, + dev->dnr_params.type + ); + + /* assign dnr filter props*/ + if( dev->dnr_params.spatial > 15 ) + dev->dnr_params.spatial = 15; + if( dev->dnr_params.temporal > 31 ) + dev->dnr_params.temporal = 31; + blackbird_api_cmd(dev, BLACKBIRD_API_SET_MANUAL_DNR, 2, 0, + dev->dnr_params.spatial, + dev->dnr_params.temporal + ); +} +#define CHECK_DNR_PARAM( name ) ( dev->dnr_params.name != dnr_params->name ) +#define UPDATE_DNR_PARAM( name ) dev->dnr_params.name = dnr_params->name +void blackbird_set_dnr_params(struct cx8802_dev *dev, struct blackbird_dnr* dnr_params) +{ + /* assign dnr filter mode */ + /* clamp values */ + if( dnr_params->mode > BLACKBIRD_DNR_BITS_AUTO ) + dnr_params->mode = BLACKBIRD_DNR_BITS_MANUAL; + if( dnr_params->type > BLACKBIRD_MEDIAN_FILTER_DIAGONAL ) + dnr_params->type = BLACKBIRD_MEDIAN_FILTER_DISABLED; + /* check if the params actually changed */ + if( CHECK_DNR_PARAM( mode ) || CHECK_DNR_PARAM( type ) ) + { + UPDATE_DNR_PARAM( mode ); + UPDATE_DNR_PARAM( type ); + blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MODE, 2, 0, dnr_params->mode, dnr_params->type); + } /* assign dnr filter props*/ - blackbird_api_cmd(dev, BLACKBIRD_API_SET_MANUAL_DNR, 2, 0, 0, 0); + if( dnr_params->spatial > 15 ) + dnr_params->spatial = 15; + if( dnr_params->temporal > 31 ) + dnr_params->temporal = 31; + if( CHECK_DNR_PARAM( spatial ) || CHECK_DNR_PARAM( temporal ) ) + { + UPDATE_DNR_PARAM( spatial ); + UPDATE_DNR_PARAM( temporal ); + blackbird_api_cmd(dev, BLACKBIRD_API_SET_MANUAL_DNR, 2, 0, dnr_params->spatial, dnr_params->temporal); + } +} + +static void blackbird_codec_settings(struct cx8802_dev *dev) +{ + + /* assign output port */ + blackbird_api_cmd(dev, BLACKBIRD_API_SET_OUTPUT_PORT, 1, 0, BLACKBIRD_OUTPUT_PORT_STREAMING); /* Host */ + + /* assign frame size */ + blackbird_api_cmd(dev, BLACKBIRD_API_SET_RESOLUTION, 2, 0, + dev->height, dev->width); /* assign coring levels (luma_h, luma_l, chroma_h, chroma_l) */ blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MEDIAN, 4, 0, 0, 255, 0, 255); /* assign spatial filter type: luma_t: horiz_only, chroma_t: horiz_only */ blackbird_api_cmd(dev, BLACKBIRD_API_SET_SPATIAL_FILTER, 2, 0, - BLACKBIRD_SPATIAL_FILTER_LUMA_1D_HORIZ, - BLACKBIRD_SPATIAL_FILTER_CHROMA_1D_HORIZ - ); + BLACKBIRD_SPATIAL_FILTER_LUMA_1D_HORIZ, + BLACKBIRD_SPATIAL_FILTER_CHROMA_1D_HORIZ + ); /* assign frame drop rate */ /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_DROP_RATE, 1, 0, 0); */ + + blackbird_set_default_params(dev); + blackbird_set_default_dnr_params(dev); } static int blackbird_initialize_codec(struct cx8802_dev *dev) @@ -851,15 +1320,10 @@ static int bb_buf_setup(struct videobuf_queue *q, struct cx8802_fh *fh = q->priv_data; fh->dev->ts_packet_size = 188 * 4; /* was: 512 */ - fh->dev->ts_packet_count = 32; /* was: 100 */ + fh->dev->ts_packet_count = mpegbufs; /* was: 100 */ *size = fh->dev->ts_packet_size * fh->dev->ts_packet_count; - if (0 == *count) - *count = mpegbufs; - if (*count < 2) - *count = 2; - if (*count > 32) - *count = 32; + *count = fh->dev->ts_packet_count; return 0; } @@ -868,7 +1332,7 @@ bb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field) { struct cx8802_fh *fh = q->priv_data; - return cx8802_buf_prepare(fh->dev, (struct cx88_buffer*)vb); + return cx8802_buf_prepare(fh->dev, (struct cx88_buffer*)vb, field); } static void @@ -920,8 +1384,6 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file, V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | - V4L2_CAP_VBI_CAPTURE | - V4L2_CAP_VIDEO_OVERLAY | 0; if (UNSET != core->tuner_type) cap->capabilities |= V4L2_CAP_TUNER; @@ -941,27 +1403,52 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file, memset(f,0,sizeof(*f)); f->index = index; - strlcpy(f->description, "MPEG TS", sizeof(f->description)); + strlcpy(f->description, "MPEG", sizeof(f->description)); f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->pixelformat = V4L2_PIX_FMT_MPEG; return 0; } case VIDIOC_G_FMT: - case VIDIOC_S_FMT: - case VIDIOC_TRY_FMT: { - /* FIXME -- quick'n'dirty for exactly one size ... */ struct v4l2_format *f = arg; memset(f,0,sizeof(*f)); f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; + f->fmt.pix.bytesperline = 0; + f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */ + f->fmt.pix.colorspace = 0; f->fmt.pix.width = dev->width; f->fmt.pix.height = dev->height; + f->fmt.pix.field = fh->mpegq.field; + dprintk(0,"VIDIOC_G_FMT: w: %d, h: %d, f: %d\n", + dev->width, dev->height, fh->mpegq.field ); + return 0; + } + case VIDIOC_TRY_FMT: + { + struct v4l2_format *f = arg; + + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; - f->fmt.pix.field = V4L2_FIELD_NONE; f->fmt.pix.bytesperline = 0; - f->fmt.pix.sizeimage = 188 * 4 * 1024; /* 1024 * 512 */ /* FIXME: BUFFER_SIZE */; + f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */; f->fmt.pix.colorspace = 0; + dprintk(0,"VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n", + dev->width, dev->height, fh->mpegq.field ); + return 0; + } + case VIDIOC_S_FMT: + { + struct v4l2_format *f = arg; + + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; + f->fmt.pix.bytesperline = 0; + f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */; + f->fmt.pix.colorspace = 0; + dprintk(0,"VIDIOC_S_FMT: w: %d, h: %d, f: %d\n", + f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field ); return 0; } @@ -985,6 +1472,22 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_STREAMOFF: return videobuf_streamoff(&fh->mpegq); + /* --- mpeg compression -------------------------------------- */ + case VIDIOC_G_MPEGCOMP: + { + struct v4l2_mpeg_compression *f = arg; + + memcpy(f,&dev->params,sizeof(*f)); + return 0; + } + case VIDIOC_S_MPEGCOMP: + { + struct v4l2_mpeg_compression *f = arg; + + blackbird_set_params(dev, f); + return 0; + } + default: return cx88_do_ioctl( inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook ); } @@ -1034,16 +1537,17 @@ static int mpeg_open(struct inode *inode, struct file *file) file->private_data = fh; fh->dev = dev; - /* FIXME: locking against other video device */ - cx88_set_scale(dev->core, dev->width, dev->height, - V4L2_FIELD_INTERLACED); - videobuf_queue_init(&fh->mpegq, &blackbird_qops, dev->pci, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_TOP, + V4L2_FIELD_INTERLACED, sizeof(struct cx88_buffer), fh); + + /* FIXME: locking against other video device */ + cx88_set_scale(dev->core, dev->width, dev->height, + fh->mpegq.field); + return 0; } @@ -1173,6 +1677,8 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev, dev->core = core; dev->width = 720; dev->height = 576; + memcpy(&dev->params,&default_mpeg_params,sizeof(default_mpeg_params)); + memcpy(&dev->dnr_params,&default_dnr_params,sizeof(default_dnr_params)); err = cx8802_init_common(dev); if (0 != err) @@ -1257,6 +1763,8 @@ module_exit(blackbird_fini); EXPORT_SYMBOL(cx88_ioctl_hook); EXPORT_SYMBOL(cx88_ioctl_translator); +EXPORT_SYMBOL(blackbird_set_params); +EXPORT_SYMBOL(blackbird_set_dnr_params); /* ----------------------------------------------------------- */ /* diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index ee2300e1ae0..2c4fbe9258d 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -54,7 +54,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev, { struct cx88_core *core = dev->core; - dprintk(0, "cx8802_start_dma %d\n", buf->vb.width); + dprintk(0, "cx8802_start_dma w: %d, h: %d, f: %d\n", dev->width, dev->height, buf->vb.field); /* setup fifo + format */ cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], @@ -158,7 +158,8 @@ static int cx8802_restart_queue(struct cx8802_dev *dev, /* ------------------------------------------------------------------ */ -int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf) +int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf, + enum v4l2_field field) { int size = dev->ts_packet_size * dev->ts_packet_count; int rc; @@ -171,7 +172,7 @@ int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf) buf->vb.width = dev->ts_packet_size; buf->vb.height = dev->ts_packet_count; buf->vb.size = size; - buf->vb.field = V4L2_FIELD_TOP; + buf->vb.field = field /*V4L2_FIELD_TOP*/; if (0 != (rc = videobuf_iolock(dev->pci,&buf->vb,NULL))) goto fail; diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 3dbc074fb51..67630f61c47 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1258,8 +1258,6 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, if (video_debug > 1) cx88_print_ioctl(core->name,cmd); - printk( KERN_INFO "CORE IOCTL: 0x%x\n", cmd ); - cx88_print_ioctl(core->name,cmd); dprintk( 1, "CORE IOCTL: 0x%x\n", cmd ); switch (cmd) { diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 88050a0043a..b18205b3fa2 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -371,6 +371,14 @@ struct cx8802_suspend_state { int disabled; }; +/* TODO: move this to struct v4l2_mpeg_compression ? */ +struct blackbird_dnr { + u32 mode; + u32 type; + u32 spatial; + u32 temporal; +}; + struct cx8802_dev { struct cx88_core *core; spinlock_t slock; @@ -401,6 +409,10 @@ struct cx8802_dev { /* for switching modulation types */ unsigned char ts_gen_cntrl; + + /* mpeg params */ + struct v4l2_mpeg_compression params; + struct blackbird_dnr dnr_params; }; /* ----------------------------------------------------------- */ @@ -542,7 +554,8 @@ void cx88_ir_irq(struct cx88_core *core); /* ----------------------------------------------------------- */ /* cx88-mpeg.c */ -int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf); +int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf, + enum v4l2_field field); void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf); void cx8802_cancel_buffers(struct cx8802_dev *dev); @@ -563,6 +576,10 @@ extern int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, extern int (*cx88_ioctl_hook)(struct inode *inode, struct file *file, unsigned int cmd, void *arg); extern unsigned int (*cx88_ioctl_translator)(unsigned int cmd); +void blackbird_set_params(struct cx8802_dev *dev, + struct v4l2_mpeg_compression *params); +void blackbird_set_dnr_params(struct cx8802_dev *dev, + struct blackbird_dnr* dnr_params); /* * Local variables: -- cgit v1.2.3 From ccd7b6500275e34e2fb90bcf316a5a721d5cdb52 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:36:19 -0800 Subject: [PATCH] v4l: 633: climov s previous patch missing changelog entry - Fixes broken compile of cx88-dvb.c Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/cx88-dvb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 4334744652d..f3efb07a761 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -78,7 +78,7 @@ static int dvb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field) { struct cx8802_dev *dev = q->priv_data; - return cx8802_buf_prepare(dev, (struct cx88_buffer*)vb); + return cx8802_buf_prepare(dev, (struct cx88_buffer*)vb,field); } static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) -- cgit v1.2.3 From 87f0783159783a315c68a00e50706cd01aa10511 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:36:19 -0800 Subject: [PATCH] v4l: 634: implemented tuner set standby on cx88 init - Implemented TUNER_SET_STANDBY on cx88 init. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/cx88-core.c | 1 + drivers/media/video/cx88/cx88-dvb.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index dc5c5c1f346..3ce000a5b7f 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -1146,6 +1146,7 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci) /* init hardware */ cx88_reset(core); cx88_i2c_init(core,pci); + cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL); cx88_card_setup(core); cx88_ir_init(core,pci); diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index f3efb07a761..ecb12c80b38 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -403,6 +403,9 @@ static int dvb_register(struct cx8802_dev *dev) /* Put the analog decoder in standby to keep it quiet */ cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); + /* Put the analog decoder in standby to keep it quiet */ + cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); + /* register everything */ return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev); } -- cgit v1.2.3 From cc9d8d49bb13fdcea521f907e120d3a7c7ce94f8 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Tue, 8 Nov 2005 21:36:20 -0800 Subject: [PATCH] v4l: 635: add bttv card 137 conceptronic ctvfmi v2 - Add bttv card 137 - Conceptronic CTVFMi v2 Signed-off-by: Ricardo Cerqueira Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.bttv | 1 + drivers/media/video/bttv-cards.c | 15 +++++++ drivers/media/video/bttv.h | 1 + drivers/media/video/ir-kbd-gpio.c | 71 +++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index ec785f9f15a..89460a5babf 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -135,3 +135,4 @@ card=133 - Kodicom 4400R (slave) card=134 - Adlink RTV24 card=135 - DViCO FusionHDTV 5 Lite card=136 - Acorp Y878F +card=137 - Conceptronic CTVFMi v2 diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 0881a17d522..75033f06551 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -2418,6 +2418,21 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_YMEC_TVF66T5_B_DFF, .tuner_addr = 0xc1 >>1, .has_radio = 1, +},{ + /* ---- card 0x89 ---------------------------------- */ + .name = "Conceptronic CTVFMi v2", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x001c0007, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0, 1, 2, 2, 3 }, + .needs_tvaudio = 0, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .tuner_addr = ADDR_UNSET, + .has_remote = 1, }}; static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h index d254e90e3bb..dcdf9cde785 100644 --- a/drivers/media/video/bttv.h +++ b/drivers/media/video/bttv.h @@ -137,6 +137,7 @@ #define BTTV_ADLINK_RTV24 0x86 #define BTTV_DVICO_FUSIONHDTV_5_LITE 0x87 #define BTTV_ACORP_Y878F 0x88 +#define BTTV_CONCEPTRONIC_CTVFMI2 0x89 /* i2c address list */ #define I2C_TSA5522 0xc2 diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c index 234151e48ed..1861d31f11b 100644 --- a/drivers/media/video/ir-kbd-gpio.c +++ b/drivers/media/video/ir-kbd-gpio.c @@ -156,6 +156,71 @@ static IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { /* ---------------------------------------------------------------------- */ +/* Ricardo Cerqueira */ +/* Weird matching, since the remote has "uncommon" keys */ + +static IR_KEYTAB_TYPE ir_codes_conceptronic[IR_KEYTAB_SIZE] = { + + [ 30 ] = KEY_POWER, // power + [ 7 ] = KEY_SWITCHVIDEOMODE, // source + [ 28 ] = KEY_SEARCH, // scan + +/* FIXME: duplicate keycodes? + * + * These four keys seem to share the same GPIO as CH+, CH-, <<< and >>> + * The GPIO values are + * 6397fb for both "Scan <" and "CH -", + * 639ffb for "Scan >" and "CH+", + * 6384fb for "Tune <" and "<<<", + * 638cfb for "Tune >" and ">>>", regardless of the mask. + * + * [ 23 ] = KEY_BACK, // fm scan << + * [ 31 ] = KEY_FORWARD, // fm scan >> + * + * [ 4 ] = KEY_LEFT, // fm tuning < + * [ 12 ] = KEY_RIGHT, // fm tuning > + * + * For now, these four keys are disabled. Pressing them will generate + * the CH+/CH-/<<>> events + */ + + [ 3 ] = KEY_TUNER, // TV/FM + + [ 0 ] = KEY_RECORD, + [ 8 ] = KEY_STOP, + [ 17 ] = KEY_PLAY, + + [ 26 ] = KEY_PLAYPAUSE, // freeze + [ 25 ] = KEY_ZOOM, // zoom + [ 15 ] = KEY_TEXT, // min + + [ 1 ] = KEY_KP1, + [ 11 ] = KEY_KP2, + [ 27 ] = KEY_KP3, + [ 5 ] = KEY_KP4, + [ 9 ] = KEY_KP5, + [ 21 ] = KEY_KP6, + [ 6 ] = KEY_KP7, + [ 10 ] = KEY_KP8, + [ 18 ] = KEY_KP9, + [ 2 ] = KEY_KP0, + [ 16 ] = KEY_LAST, // +100 + [ 19 ] = KEY_LIST, // recall + + [ 31 ] = KEY_CHANNELUP, // chn down + [ 23 ] = KEY_CHANNELDOWN, // chn up + [ 22 ] = KEY_VOLUMEUP, // vol down + [ 20 ] = KEY_VOLUMEDOWN, // vol up + + [ 4 ] = KEY_KPMINUS, // <<< + [ 14 ] = KEY_SETUP, // function + [ 12 ] = KEY_KPPLUS, // >>> + + [ 13 ] = KEY_GOTO, // mts + [ 29 ] = KEY_REFRESH, // reset + [ 24 ] = KEY_MUTE // mute/unmute +}; + struct IR { struct bttv_sub_device *sub; struct input_dev *input; @@ -329,6 +394,12 @@ static int ir_probe(struct device *dev) ir->mask_keyup = 0x008000; ir->polling = 50; // ms break; + case BTTV_CONCEPTRONIC_CTVFMI2: + ir_codes = ir_codes_conceptronic; + ir->mask_keycode = 0x001F00; + ir->mask_keyup = 0x006000; + ir->polling = 50; // ms + break; } if (NULL == ir_codes) { kfree(ir); -- cgit v1.2.3 From 7c08fb02f1a1b86292aa144cc876a95fbe2a5606 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:36:21 -0800 Subject: [PATCH] v4l: 636: don t enable gpioirq until after card probe - Don't enable gpioirq until after card probe. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bttv-cards.c | 14 ++++++-------- drivers/media/video/bttv-driver.c | 11 +++++------ 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 75033f06551..e872cd47a64 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -1731,10 +1731,7 @@ struct tvcard bttv_tvcards[] = { .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, - .gpiomask = 0x01, - .audiomux = { 0, 0, 0, 0, 1 }, .muxsel = { 3, 0, 1, 2}, - .needs_tvaudio = 0, .pll = PLL_28, .no_gpioirq = 1, .has_dvb = 1, @@ -2808,11 +2805,12 @@ void __devinit bttv_init_card1(struct bttv *btv) break; case BTTV_TWINHAN_DST: case BTTV_AVDVBT_771: + case BTTV_PINNACLESAT: btv->use_i2c_hw = 1; break; - case BTTV_ADLINK_RTV24: - init_RTV24( btv ); - break; + case BTTV_ADLINK_RTV24: + init_RTV24( btv ); + break; } if (!bttv_tvcards[btv->c.type].has_dvb) @@ -2997,8 +2995,8 @@ void __devinit bttv_init_card2(struct bttv *btv) btv->has_radio=1; if (bttv_tvcards[btv->c.type].has_remote) btv->has_remote=1; - if (bttv_tvcards[btv->c.type].no_gpioirq) - btv->gpioirq=0; + if (!bttv_tvcards[btv->c.type].no_gpioirq) + btv->gpioirq=1; if (bttv_tvcards[btv->c.type].audio_hook) btv->audio_hook=bttv_tvcards[btv->c.type].audio_hook; diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index d538a994ff0..4826cf0d39d 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -3889,18 +3889,17 @@ static int __devinit bttv_probe(struct pci_dev *dev, btv->timeout.function = bttv_irq_timeout; btv->timeout.data = (unsigned long)btv; - btv->i2c_rc = -1; - btv->tuner_type = UNSET; - btv->pinnacle_id = UNSET; + btv->i2c_rc = -1; + btv->tuner_type = UNSET; + btv->pinnacle_id = UNSET; btv->new_input = UNSET; - btv->gpioirq = 1; btv->has_radio=radio[btv->c.nr]; /* pci stuff (init, get irq/mmio, ... */ btv->c.pci = dev; - btv->id = dev->device; + btv->id = dev->device; if (pci_enable_device(dev)) { - printk(KERN_WARNING "bttv%d: Can't enable device.\n", + printk(KERN_WARNING "bttv%d: Can't enable device.\n", btv->c.nr); return -EIO; } -- cgit v1.2.3 From 6b96144026e27b9250713f86355e83095204d5f2 Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:36:22 -0800 Subject: [PATCH] v4l: 639: added new card gotview pci 7135 - Added new card GoTView PCI 7135 Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 53 ++++++++++++++++++++++++++++- drivers/media/video/saa7134/saa7134-input.c | 49 ++++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134.h | 1 + 4 files changed, 103 insertions(+), 1 deletion(-) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index f31c2f8e404..411f842c5d1 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -66,3 +66,4 @@ 65 -> V-Stream Studio TV Terminator 66 -> Yuan TUN-900 (saa7135) 67 -> Beholder BeholdTV 409 FM [0000:4091] + 68 -> GoTView 7135 PCI [5456:7135] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index bca5b7038a8..088376d3c95 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2141,6 +2141,50 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE2, }, }, + [SAA7134_BOARD_GOTVIEW_7135] = { + /* Mike Baikov */ + /* Andrey Cvetcov */ + .name = "GoTView 7135 PCI", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00200003, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + .gpio = 0x00200003, + },{ + .name = name_tv_mono, + .vmux = 1, + .amux = LINE2, + .gpio = 0x00200003, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + .gpio = 0x00200003, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + .gpio = 0x00200003, + }}, + .radio = { + .name = name_radio, + .amux = LINE2, + .gpio = 0x00200003, + }, + .mute = { + .name = name_mute, + .amux = TV, + .gpio = 0x00200003, + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -2504,6 +2548,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x0000, /* It shouldn't break anything, since subdevice id seems unique */ .subdevice = 0x4091, .driver_data = SAA7134_BOARD_BEHOLD_409FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5456, /* GoTView */ + .subdevice = 0x7135, + .driver_data = SAA7134_BOARD_GOTVIEW_7135, },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -2597,6 +2647,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_MANLI_MTV002: case SAA7134_BOARD_BEHOLD_409FM: case SAA7134_BOARD_AVACSSMARTTV: + case SAA7134_BOARD_GOTVIEW_7135: dev->has_remote = 1; break; case SAA7134_BOARD_MD5044: @@ -2613,7 +2664,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) break; case SAA7134_BOARD_FLYDVBTDUO: case SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS: - /* turn the fan on Hac: static for the time being */ + /* turn the fan on */ saa_writeb(SAA7134_GPIO_GPMODE3, 0x08); saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x06); break; diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 8e2cc9d75cd..899abd8ba0d 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -401,6 +401,48 @@ static IR_KEYTAB_TYPE manli_codes[IR_KEYTAB_SIZE] = { // 0x1d unused ? }; + + +/* Mike Baikov Mike Baikov */ +static IR_KEYTAB_TYPE gotview7135_codes[IR_KEYTAB_SIZE] = { + + [ 33 ] = KEY_POWER, + [ 105] = KEY_TV, + [ 51 ] = KEY_KP0, + [ 81 ] = KEY_KP1, + [ 49 ] = KEY_KP2, + [ 113] = KEY_KP3, + [ 59 ] = KEY_KP4, + [ 88 ] = KEY_KP5, + [ 65 ] = KEY_KP6, + [ 72 ] = KEY_KP7, + [ 48 ] = KEY_KP8, + [ 83 ] = KEY_KP9, + [ 115] = KEY_AGAIN, /* LOOP */ + [ 10 ] = KEY_AUDIO, + [ 97 ] = KEY_PRINT, /* PREVIEW */ + [ 122] = KEY_VIDEO, + [ 32 ] = KEY_CHANNELUP, + [ 64 ] = KEY_CHANNELDOWN, + [ 24 ] = KEY_VOLUMEDOWN, + [ 80 ] = KEY_VOLUMEUP, + [ 16 ] = KEY_MUTE, + [ 74 ] = KEY_SEARCH, + [ 123] = KEY_SHUFFLE, /* SNAPSHOT */ + [ 34 ] = KEY_RECORD, + [ 98 ] = KEY_STOP, + [ 120] = KEY_PLAY, + [ 57 ] = KEY_REWIND, + [ 89 ] = KEY_PAUSE, + [ 25 ] = KEY_FORWARD, + [ 9 ] = KEY_ZOOM, + + [ 82 ] = KEY_F21, /* LIVE TIMESHIFT */ + [ 26 ] = KEY_F22, /* MIN TIMESHIFT */ + [ 58 ] = KEY_F23, /* TIMESHIFT */ + [ 112] = KEY_F24, /* NORMAL TIMESHIFT */ +}; + /* ---------------------------------------------------------------------- */ static int build_key(struct saa7134_dev *dev) @@ -523,6 +565,13 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keydown = 0x002000; polling = 50; // ms break; + case SAA7134_BOARD_GOTVIEW_7135: + ir_codes = gotview7135_codes; + mask_keycode = 0x0003EC; + mask_keyup = 0x008000; + mask_keydown = 0x000010; + polling = 50; // ms + break; case SAA7134_BOARD_VIDEOMATE_TV_PVR: case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: ir_codes = videomate_tv_pvr_codes; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 45fe6af1ecc..291c2e8d108 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -188,6 +188,7 @@ struct saa7134_format { #define SAA7134_BOARD_KWORLD_TERMINATOR 65 #define SAA7134_BOARD_YUAN_TUN900 66 #define SAA7134_BOARD_BEHOLD_409FM 67 +#define SAA7134_BOARD_GOTVIEW_7135 68 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From dcd555ece9a2228d918a439480d748c163a11d00 Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:36:23 -0800 Subject: [PATCH] v4l: 640: fixed typos - Fixed typos Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-cards.c | 2 +- drivers/media/video/saa7134/saa7134-input.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 088376d3c95..fea2188b2fa 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2142,7 +2142,7 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_GOTVIEW_7135] = { - /* Mike Baikov */ + /* Mike Baikov */ /* Andrey Cvetcov */ .name = "GoTView 7135 PCI", .audio_clock = 0x00187de7, diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 899abd8ba0d..c473ddcbd74 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -403,7 +403,7 @@ static IR_KEYTAB_TYPE manli_codes[IR_KEYTAB_SIZE] = { }; -/* Mike Baikov Mike Baikov */ +/* Mike Baikov */ static IR_KEYTAB_TYPE gotview7135_codes[IR_KEYTAB_SIZE] = { [ 33 ] = KEY_POWER, -- cgit v1.2.3 From 84cd961cab8abd764f74d27ee47feff8942fca10 Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:36:24 -0800 Subject: [PATCH] v4l: 643: use key media instead of key videomodeswitch since - Use KEY_MEDIA instead of KEY_VIDEOMODESWITCH Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/ir-kbd-gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c index 1861d31f11b..28b58976f8e 100644 --- a/drivers/media/video/ir-kbd-gpio.c +++ b/drivers/media/video/ir-kbd-gpio.c @@ -162,7 +162,7 @@ static IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { static IR_KEYTAB_TYPE ir_codes_conceptronic[IR_KEYTAB_SIZE] = { [ 30 ] = KEY_POWER, // power - [ 7 ] = KEY_SWITCHVIDEOMODE, // source + [ 7 ] = KEY_MEDIA, // source [ 28 ] = KEY_SEARCH, // scan /* FIXME: duplicate keycodes? -- cgit v1.2.3 From 6f3c343bfa61532e02b95d409455a8bab6b47a6b Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:36:24 -0800 Subject: [PATCH] v4l: 644: lower switch from vhf lo to vhf hi for philips 1216me mk3 - Lower switch from VHF_LO to VHF_HI for Philips 1216ME MK3 Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tuner-simple.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 8edd73abe1d..0ae39be3ca5 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -185,7 +185,7 @@ static struct tunertype tuners[] = { { "LG PAL (newer TAPC series)", LGINNOTEK, PAL, 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,623}, { "Philips PAL/SECAM multi (FM1216ME MK3)", Philips, PAL, - 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,623 }, + 16*158.00,16*442.00,0x01,0x02,0x04,0x8e,623 }, { "LG NTSC (newer TAPC series)", LGINNOTEK, NTSC, 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,732}, -- cgit v1.2.3 From b01bc14a2c67b0b562d8201a864d7b4aada07ab4 Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:36:25 -0800 Subject: [PATCH] v4l: 645: refine input handling for manli beholder - Refine input handling for Manli/Beholder. Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-input.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index c473ddcbd74..baf16a348f4 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -562,7 +562,6 @@ int saa7134_input_init1(struct saa7134_dev *dev) ir_codes = manli_codes; mask_keycode = 0x001f00; mask_keyup = 0x004000; - mask_keydown = 0x002000; polling = 50; // ms break; case SAA7134_BOARD_GOTVIEW_7135: -- cgit v1.2.3 From 99d6c34864342c2071e3a9820bb797374a314fb2 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:36:26 -0800 Subject: [PATCH] v4l: 646: enable dvb support for dvico fusionhdtv5 lite - Enable DVB support for DViCO FusionHDTV5 Lite. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bttv-cards.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index e872cd47a64..e94bffbedfd 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -2399,6 +2399,7 @@ struct tvcard bttv_tvcards[] = { .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, + .has_dvb = 1, },{ /* ---- card 0x88---------------------------------- */ /* Mauro Carvalho Chehab */ -- cgit v1.2.3 From c35d4b84f19d3f4b6a2fec652519e721f2cca169 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:36:27 -0800 Subject: [PATCH] v4l: 647: included cb3 structures on tda8290 that should be changed according with - Included CB3 structures on tda8290 Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tda8290.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index c65f0c7680a..61268f8a9ee 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -90,6 +90,11 @@ static unsigned char i2c_cb1_50[2] = { 0x30, 0x50 }; static unsigned char i2c_agc2_7F[2] = { 0x60, 0x7F }; static unsigned char i2c_agc3_08[2] = { 0x80, 0x08 }; +/* FIXME: European PAL/SECAM should select 9MHz Lowpass Filter, while + NTSC/M and PAL/M should be using 7MHz filter, by selecting CB3 */ +static unsigned char i2c_cb3_9MHz[2] = { 0xc0, 0x39 }; +static unsigned char i2c_cb3_7MHz[2] = { 0xc0, 0x3B }; + static struct i2c_msg i2c_msg_init[] = { { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_init_tda8275), i2c_init_tda8275 }, { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_disable_bridge), i2c_disable_bridge }, -- cgit v1.2.3 From b1706b91051e1270e0bd5134219e48732a9d6c42 Mon Sep 17 00:00:00 2001 From: Torsten Seeboth Date: Tue, 8 Nov 2005 21:36:27 -0800 Subject: [PATCH] v4l: 648: some clean up in cx88 tvaudio c - Some clean up in cx88-tvaudio.c Signed-off-by: Torsten Seeboth Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/cx88-core.c | 10 +- drivers/media/video/cx88/cx88-tvaudio.c | 643 +++++++++++++++----------------- drivers/media/video/cx88/cx88.h | 19 +- 3 files changed, 325 insertions(+), 347 deletions(-) diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 3ce000a5b7f..87212759149 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -845,19 +845,19 @@ static int set_tvaudio(struct cx88_core *core) return 0; if (V4L2_STD_PAL_BG & norm->id) { - core->tvaudio = nicam ? WW_NICAM_BGDKL : WW_A2_BG; + core->tvaudio = WW_BG; } else if (V4L2_STD_PAL_DK & norm->id) { - core->tvaudio = nicam ? WW_NICAM_BGDKL : WW_A2_DK; + core->tvaudio = WW_DK; } else if (V4L2_STD_PAL_I & norm->id) { - core->tvaudio = WW_NICAM_I; + core->tvaudio = WW_I; } else if (V4L2_STD_SECAM_L & norm->id) { - core->tvaudio = WW_SYSTEM_L_AM; + core->tvaudio = WW_L; } else if (V4L2_STD_SECAM_DK & norm->id) { - core->tvaudio = WW_A2_DK; + core->tvaudio = WW_DK; } else if ((V4L2_STD_NTSC_M & norm->id) || (V4L2_STD_PAL_M & norm->id)) { diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index 2765acee028..b6431cb78a5 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c @@ -271,248 +271,102 @@ static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap, u3 } } - -static void set_audio_standard_NICAM_L(struct cx88_core *core, int stereo) +static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode) { - /* This is probably weird.. - * Let's operate and find out. */ - - static const struct rlist nicam_l_mono[] = { - { AUD_ERRLOGPERIOD_R, 0x00000064 }, - { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF }, - { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F }, - { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F }, - - { AUD_PDF_DDS_CNST_BYTE2, 0x48 }, - { AUD_PDF_DDS_CNST_BYTE1, 0x3D }, - { AUD_QAM_MODE, 0x00 }, - { AUD_PDF_DDS_CNST_BYTE0, 0xf5 }, - { AUD_PHACC_FREQ_8MSB, 0x3a }, - { AUD_PHACC_FREQ_8LSB, 0x4a }, - - { AUD_DEEMPHGAIN_R, 0x6680 }, - { AUD_DEEMPHNUMER1_R, 0x353DE }, - { AUD_DEEMPHNUMER2_R, 0x1B1 }, - { AUD_DEEMPHDENOM1_R, 0x0F3D0 }, - { AUD_DEEMPHDENOM2_R, 0x0 }, - { AUD_FM_MODE_ENABLE, 0x7 }, - { AUD_POLYPH80SCALEFAC, 0x3 }, - { AUD_AFE_12DB_EN, 0x1 }, - { AAGC_GAIN, 0x0 }, - { AAGC_HYST, 0x18 }, - { AAGC_DEF, 0x20 }, - { AUD_DN0_FREQ, 0x0 }, - { AUD_POLY0_DDS_CONSTANT, 0x0E4DB2 }, - { AUD_DCOC_0_SRC, 0x21 }, - { AUD_IIR1_0_SEL, 0x0 }, - { AUD_IIR1_0_SHIFT, 0x7 }, - { AUD_IIR1_1_SEL, 0x2 }, - { AUD_IIR1_1_SHIFT, 0x0 }, - { AUD_DCOC_1_SRC, 0x3 }, - { AUD_DCOC1_SHIFT, 0x0 }, - { AUD_DCOC_PASS_IN, 0x0 }, - { AUD_IIR1_2_SEL, 0x23 }, - { AUD_IIR1_2_SHIFT, 0x0 }, - { AUD_IIR1_3_SEL, 0x4 }, - { AUD_IIR1_3_SHIFT, 0x7 }, - { AUD_IIR1_4_SEL, 0x5 }, - { AUD_IIR1_4_SHIFT, 0x7 }, - { AUD_IIR3_0_SEL, 0x7 }, - { AUD_IIR3_0_SHIFT, 0x0 }, - { AUD_DEEMPH0_SRC_SEL, 0x11 }, - { AUD_DEEMPH0_SHIFT, 0x0 }, - { AUD_DEEMPH0_G0, 0x7000 }, - { AUD_DEEMPH0_A0, 0x0 }, - { AUD_DEEMPH0_B0, 0x0 }, - { AUD_DEEMPH0_A1, 0x0 }, - { AUD_DEEMPH0_B1, 0x0 }, - { AUD_DEEMPH1_SRC_SEL, 0x11 }, - { AUD_DEEMPH1_SHIFT, 0x0 }, - { AUD_DEEMPH1_G0, 0x7000 }, - { AUD_DEEMPH1_A0, 0x0 }, - { AUD_DEEMPH1_B0, 0x0 }, - { AUD_DEEMPH1_A1, 0x0 }, - { AUD_DEEMPH1_B1, 0x0 }, - { AUD_OUT0_SEL, 0x3F }, - { AUD_OUT1_SEL, 0x3F }, - { AUD_DMD_RA_DDS, 0x0F5C285 }, - { AUD_PLL_INT, 0x1E }, - { AUD_PLL_DDS, 0x0 }, - { AUD_PLL_FRAC, 0x0E542 }, - - // setup QAM registers - { AUD_RATE_ADJ1, 0x00000100 }, - { AUD_RATE_ADJ2, 0x00000200 }, - { AUD_RATE_ADJ3, 0x00000300 }, - { AUD_RATE_ADJ4, 0x00000400 }, - { AUD_RATE_ADJ5, 0x00000500 }, - { AUD_RATE_THRES_DMD, 0x000000C0 }, - { /* end of list */ }, - }; - static const struct rlist nicam_l[] = { - // setup QAM registers - { AUD_RATE_ADJ1, 0x00000060 }, - { AUD_RATE_ADJ2, 0x000000F9 }, - { AUD_RATE_ADJ3, 0x000001CC }, - { AUD_RATE_ADJ4, 0x000002B3 }, - { AUD_RATE_ADJ5, 0x00000726 }, - { AUD_DEEMPHDENOM1_R, 0x0000F3D0 }, - { AUD_DEEMPHDENOM2_R, 0x00000000 }, - { AUD_ERRLOGPERIOD_R, 0x00000064 }, - { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF }, - { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F }, - { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F }, - { AUD_POLYPH80SCALEFAC, 0x00000003 }, - { AUD_DMD_RA_DDS, 0x00C00000 }, - { AUD_PLL_INT, 0x0000001E }, - { AUD_PLL_DDS, 0x00000000 }, - { AUD_PLL_FRAC, 0x0000E542 }, - { AUD_START_TIMER, 0x00000000 }, - { AUD_DEEMPHNUMER1_R, 0x000353DE }, - { AUD_DEEMPHNUMER2_R, 0x000001B1 }, - { AUD_PDF_DDS_CNST_BYTE2, 0x06 }, - { AUD_PDF_DDS_CNST_BYTE1, 0x82 }, - { AUD_QAM_MODE, 0x05 }, - { AUD_PDF_DDS_CNST_BYTE0, 0x12 }, - { AUD_PHACC_FREQ_8MSB, 0x34 }, - { AUD_PHACC_FREQ_8LSB, 0x4C }, - { AUD_DEEMPHGAIN_R, 0x00006680 }, - { AUD_RATE_THRES_DMD, 0x000000C0 }, - { /* end of list */ }, - } ; - dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo); - - if (!stereo) { - /* AM Mono */ - set_audio_start(core, SEL_A2); - set_audio_registers(core, nicam_l_mono); - set_audio_finish(core, EN_A2_FORCE_MONO1); - } else { - /* Nicam Stereo */ - set_audio_start(core, SEL_NICAM); - set_audio_registers(core, nicam_l); - set_audio_finish(core, 0x1924); /* FIXME */ - } -} - -static void set_audio_standard_PAL_I(struct cx88_core *core, int stereo) -{ - static const struct rlist pal_i_fm_mono[] = { - {AUD_ERRLOGPERIOD_R, 0x00000064}, - {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff}, - {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f}, - {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f}, - {AUD_PDF_DDS_CNST_BYTE2, 0x06}, - {AUD_PDF_DDS_CNST_BYTE1, 0x82}, - {AUD_PDF_DDS_CNST_BYTE0, 0x12}, - {AUD_QAM_MODE, 0x05}, - {AUD_PHACC_FREQ_8MSB, 0x3a}, - {AUD_PHACC_FREQ_8LSB, 0x93}, - {AUD_DMD_RA_DDS, 0x002a4f2f}, - {AUD_PLL_INT, 0x0000001e}, - {AUD_PLL_DDS, 0x00000004}, - {AUD_PLL_FRAC, 0x0000e542}, - {AUD_RATE_ADJ1, 0x00000100}, - {AUD_RATE_ADJ2, 0x00000200}, - {AUD_RATE_ADJ3, 0x00000300}, - {AUD_RATE_ADJ4, 0x00000400}, - {AUD_RATE_ADJ5, 0x00000500}, - {AUD_THR_FR, 0x00000000}, - {AUD_PILOT_BQD_1_K0, 0x0000755b}, - {AUD_PILOT_BQD_1_K1, 0x00551340}, - {AUD_PILOT_BQD_1_K2, 0x006d30be}, - {AUD_PILOT_BQD_1_K3, 0xffd394af}, - {AUD_PILOT_BQD_1_K4, 0x00400000}, - {AUD_PILOT_BQD_2_K0, 0x00040000}, - {AUD_PILOT_BQD_2_K1, 0x002a4841}, - {AUD_PILOT_BQD_2_K2, 0x00400000}, - {AUD_PILOT_BQD_2_K3, 0x00000000}, - {AUD_PILOT_BQD_2_K4, 0x00000000}, - {AUD_MODE_CHG_TIMER, 0x00000060}, - {AUD_AFE_12DB_EN, 0x00000001}, - {AAGC_HYST, 0x0000000a}, - {AUD_CORDIC_SHIFT_0, 0x00000007}, - {AUD_CORDIC_SHIFT_1, 0x00000007}, - {AUD_C1_UP_THR, 0x00007000}, - {AUD_C1_LO_THR, 0x00005400}, - {AUD_C2_UP_THR, 0x00005400}, - {AUD_C2_LO_THR, 0x00003000}, - {AUD_DCOC_0_SRC, 0x0000001a}, - {AUD_DCOC0_SHIFT, 0x00000000}, - {AUD_DCOC_0_SHIFT_IN0, 0x0000000a}, - {AUD_DCOC_0_SHIFT_IN1, 0x00000008}, - {AUD_DCOC_PASS_IN, 0x00000003}, - {AUD_IIR3_0_SEL, 0x00000021}, - {AUD_DN2_AFC, 0x00000002}, - {AUD_DCOC_1_SRC, 0x0000001b}, - {AUD_DCOC1_SHIFT, 0x00000000}, - {AUD_DCOC_1_SHIFT_IN0, 0x0000000a}, - {AUD_DCOC_1_SHIFT_IN1, 0x00000008}, - {AUD_IIR3_1_SEL, 0x00000023}, - {AUD_DN0_FREQ, 0x000035a3}, - {AUD_DN2_FREQ, 0x000029c7}, - {AUD_CRDC0_SRC_SEL, 0x00000511}, - {AUD_IIR1_0_SEL, 0x00000001}, - {AUD_IIR1_1_SEL, 0x00000000}, - {AUD_IIR3_2_SEL, 0x00000003}, - {AUD_IIR3_2_SHIFT, 0x00000000}, - {AUD_IIR3_0_SEL, 0x00000002}, - {AUD_IIR2_0_SEL, 0x00000021}, - {AUD_IIR2_0_SHIFT, 0x00000002}, - {AUD_DEEMPH0_SRC_SEL, 0x0000000b}, - {AUD_DEEMPH1_SRC_SEL, 0x0000000b}, - {AUD_POLYPH80SCALEFAC, 0x00000001}, - {AUD_START_TIMER, 0x00000000}, + { AUD_AFE_12DB_EN, 0x00000001}, + { AUD_RATE_ADJ1, 0x00000060 }, + { AUD_RATE_ADJ2, 0x000000F9 }, + { AUD_RATE_ADJ3, 0x000001CC }, + { AUD_RATE_ADJ4, 0x000002B3 }, + { AUD_RATE_ADJ5, 0x00000726 }, + { AUD_DEEMPHDENOM1_R, 0x0000F3D0 }, + { AUD_DEEMPHDENOM2_R, 0x00000000 }, + { AUD_ERRLOGPERIOD_R, 0x00000064 }, + { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF }, + { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F }, + { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F }, + { AUD_POLYPH80SCALEFAC, 0x00000003 }, + { AUD_DMD_RA_DDS, 0x00C00000 }, + { AUD_PLL_INT, 0x0000001E }, + { AUD_PLL_DDS, 0x00000000 }, + { AUD_PLL_FRAC, 0x0000E542 }, + { AUD_START_TIMER, 0x00000000 }, + { AUD_DEEMPHNUMER1_R, 0x000353DE }, + { AUD_DEEMPHNUMER2_R, 0x000001B1 }, + { AUD_PDF_DDS_CNST_BYTE2, 0x06 }, + { AUD_PDF_DDS_CNST_BYTE1, 0x82 }, + { AUD_PDF_DDS_CNST_BYTE0, 0x12 }, + { AUD_QAM_MODE, 0x05 }, + { AUD_PHACC_FREQ_8MSB, 0x34 }, + { AUD_PHACC_FREQ_8LSB, 0x4C }, + { AUD_DEEMPHGAIN_R, 0x00006680 }, + { AUD_RATE_THRES_DMD, 0x000000C0 }, { /* end of list */ }, - }; + } ; - static const struct rlist pal_i_nicam[] = { + static const struct rlist nicam_bgdki_common[] = { + { AUD_AFE_12DB_EN, 0x00000001}, { AUD_RATE_ADJ1, 0x00000010 }, { AUD_RATE_ADJ2, 0x00000040 }, { AUD_RATE_ADJ3, 0x00000100 }, { AUD_RATE_ADJ4, 0x00000400 }, { AUD_RATE_ADJ5, 0x00001000 }, - // { AUD_DMD_RA_DDS, 0x00c0d5ce }, - { AUD_DEEMPHGAIN_R, 0x000023c2 }, - { AUD_DEEMPHNUMER1_R, 0x0002a7bc }, - { AUD_DEEMPHNUMER2_R, 0x0003023e }, - { AUD_DEEMPHDENOM1_R, 0x0000f3d0 }, - { AUD_DEEMPHDENOM2_R, 0x00000000 }, - { AUD_DEEMPHDENOM2_R, 0x00000000 }, - { AUD_ERRLOGPERIOD_R, 0x00000fff }, - { AUD_ERRINTRPTTHSHLD1_R, 0x000003ff }, - { AUD_ERRINTRPTTHSHLD2_R, 0x000000ff }, - { AUD_ERRINTRPTTHSHLD3_R, 0x0000003f }, - { AUD_POLYPH80SCALEFAC, 0x00000003 }, - { AUD_PDF_DDS_CNST_BYTE2, 0x06 }, + //{ AUD_DMD_RA_DDS, 0x00c0d5ce }, + { AUD_ERRLOGPERIOD_R, 0x00000fff}, + { AUD_ERRINTRPTTHSHLD1_R, 0x000003ff}, + { AUD_ERRINTRPTTHSHLD2_R, 0x000000ff}, + { AUD_ERRINTRPTTHSHLD3_R, 0x0000003f}, + { AUD_POLYPH80SCALEFAC, 0x00000003}, + { AUD_DEEMPHGAIN_R, 0x000023c2}, + { AUD_DEEMPHNUMER1_R, 0x0002a7bc}, + { AUD_DEEMPHNUMER2_R, 0x0003023e}, + { AUD_DEEMPHDENOM1_R, 0x0000f3d0}, + { AUD_DEEMPHDENOM2_R, 0x00000000}, { AUD_PDF_DDS_CNST_BYTE1, 0x82 }, { AUD_PDF_DDS_CNST_BYTE0, 0x16 }, { AUD_QAM_MODE, 0x05 }, + { /* end of list */ }, + }; + + static const struct rlist nicam_i[] = { { AUD_PDF_DDS_CNST_BYTE0, 0x12 }, { AUD_PHACC_FREQ_8MSB, 0x3a }, { AUD_PHACC_FREQ_8LSB, 0x93 }, { /* end of list */ }, }; - dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo); + static const struct rlist nicam_default[] = { + { AUD_PDF_DDS_CNST_BYTE0, 0x16 }, + { AUD_PHACC_FREQ_8MSB, 0x34 }, + { AUD_PHACC_FREQ_8LSB, 0x4c }, + { /* end of list */ }, + }; - if (!stereo) { - /* FM Mono */ - set_audio_start(core, SEL_A2); - set_audio_registers(core, pal_i_fm_mono); - set_audio_finish(core, EN_DMTRX_SUMDIFF | EN_A2_FORCE_MONO1); - } else { - /* Nicam Stereo */ - set_audio_start(core, SEL_NICAM); - set_audio_registers(core, pal_i_nicam); - set_audio_finish(core, EN_DMTRX_LR | EN_DMTRX_BYPASS | EN_NICAM_AUTO_STEREO); - } + switch (core->tvaudio) { + case WW_L: + dprintk("%s SECAM-L NICAM (status: devel)\n",__FUNCTION__); + set_audio_registers(core, nicam_l); + break; + case WW_I: + dprintk("%s PAL-I NICAM (status: devel)\n",__FUNCTION__); + set_audio_registers(core, nicam_bgdki_common); + set_audio_registers(core, nicam_i); + break; + default: + dprintk("%s PAL-BGDK NICAM (status: unknown)\n",__FUNCTION__); + set_audio_registers(core, nicam_bgdki_common); + set_audio_registers(core, nicam_default); + break; + }; + + mode |= EN_DMTRX_LR | EN_DMTRX_BYPASS; + set_audio_finish(core, mode); } static void set_audio_standard_A2(struct cx88_core *core, u32 mode) { - static const struct rlist a2_common[] = { + static const struct rlist a2_bgdk_common[] = { {AUD_ERRLOGPERIOD_R, 0x00000064}, {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff}, {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f}, @@ -576,7 +430,7 @@ static void set_audio_standard_A2(struct cx88_core *core, u32 mode) {AUD_C1_LO_THR, 0x00005400}, {AUD_C2_UP_THR, 0x00005400}, {AUD_C2_LO_THR, 0x00003000}, - { /* end of list */ }, + { /* end of list */ }, }; static const struct rlist a2_dk[] = { @@ -587,24 +441,145 @@ static void set_audio_standard_A2(struct cx88_core *core, u32 mode) {AUD_C2_LO_THR, 0x00003000}, {AUD_DN0_FREQ, 0x00003a1c}, {AUD_DN2_FREQ, 0x0000d2e0}, - { /* end of list */ }, + { /* end of list */ }, }; -/* unknown, probably NTSC-M */ - static const struct rlist a2_m[] = { - {AUD_DMD_RA_DDS, 0x002a0425}, - {AUD_C1_UP_THR, 0x00003c00}, - {AUD_C1_LO_THR, 0x00003000}, - {AUD_C2_UP_THR, 0x00006000}, - {AUD_C2_LO_THR, 0x00003c00}, - {AUD_DEEMPH0_A0, 0x00007a80}, - {AUD_DEEMPH1_A0, 0x00007a80}, - {AUD_DEEMPH0_G0, 0x00001200}, - {AUD_DEEMPH1_G0, 0x00001200}, - {AUD_DN0_FREQ, 0x0000283b}, - {AUD_DN1_FREQ, 0x00003418}, - {AUD_DN2_FREQ, 0x000029c7}, - {AUD_POLY0_DDS_CONSTANT, 0x000a7540}, - { /* end of list */ }, + + static const struct rlist a1_i[] = { + {AUD_ERRLOGPERIOD_R, 0x00000064}, + {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff}, + {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f}, + {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f}, + {AUD_PDF_DDS_CNST_BYTE2, 0x06}, + {AUD_PDF_DDS_CNST_BYTE1, 0x82}, + {AUD_PDF_DDS_CNST_BYTE0, 0x12}, + {AUD_QAM_MODE, 0x05}, + {AUD_PHACC_FREQ_8MSB, 0x3a}, + {AUD_PHACC_FREQ_8LSB, 0x93}, + {AUD_DMD_RA_DDS, 0x002a4f2f}, + {AUD_PLL_INT, 0x0000001e}, + {AUD_PLL_DDS, 0x00000004}, + {AUD_PLL_FRAC, 0x0000e542}, + {AUD_RATE_ADJ1, 0x00000100}, + {AUD_RATE_ADJ2, 0x00000200}, + {AUD_RATE_ADJ3, 0x00000300}, + {AUD_RATE_ADJ4, 0x00000400}, + {AUD_RATE_ADJ5, 0x00000500}, + {AUD_THR_FR, 0x00000000}, + {AUD_PILOT_BQD_1_K0, 0x0000755b}, + {AUD_PILOT_BQD_1_K1, 0x00551340}, + {AUD_PILOT_BQD_1_K2, 0x006d30be}, + {AUD_PILOT_BQD_1_K3, 0xffd394af}, + {AUD_PILOT_BQD_1_K4, 0x00400000}, + {AUD_PILOT_BQD_2_K0, 0x00040000}, + {AUD_PILOT_BQD_2_K1, 0x002a4841}, + {AUD_PILOT_BQD_2_K2, 0x00400000}, + {AUD_PILOT_BQD_2_K3, 0x00000000}, + {AUD_PILOT_BQD_2_K4, 0x00000000}, + {AUD_MODE_CHG_TIMER, 0x00000060}, + {AUD_AFE_12DB_EN, 0x00000001}, + {AAGC_HYST, 0x0000000a}, + {AUD_CORDIC_SHIFT_0, 0x00000007}, + {AUD_CORDIC_SHIFT_1, 0x00000007}, + {AUD_C1_UP_THR, 0x00007000}, + {AUD_C1_LO_THR, 0x00005400}, + {AUD_C2_UP_THR, 0x00005400}, + {AUD_C2_LO_THR, 0x00003000}, + {AUD_DCOC_0_SRC, 0x0000001a}, + {AUD_DCOC0_SHIFT, 0x00000000}, + {AUD_DCOC_0_SHIFT_IN0, 0x0000000a}, + {AUD_DCOC_0_SHIFT_IN1, 0x00000008}, + {AUD_DCOC_PASS_IN, 0x00000003}, + {AUD_IIR3_0_SEL, 0x00000021}, + {AUD_DN2_AFC, 0x00000002}, + {AUD_DCOC_1_SRC, 0x0000001b}, + {AUD_DCOC1_SHIFT, 0x00000000}, + {AUD_DCOC_1_SHIFT_IN0, 0x0000000a}, + {AUD_DCOC_1_SHIFT_IN1, 0x00000008}, + {AUD_IIR3_1_SEL, 0x00000023}, + {AUD_DN0_FREQ, 0x000035a3}, + {AUD_DN2_FREQ, 0x000029c7}, + {AUD_CRDC0_SRC_SEL, 0x00000511}, + {AUD_IIR1_0_SEL, 0x00000001}, + {AUD_IIR1_1_SEL, 0x00000000}, + {AUD_IIR3_2_SEL, 0x00000003}, + {AUD_IIR3_2_SHIFT, 0x00000000}, + {AUD_IIR3_0_SEL, 0x00000002}, + {AUD_IIR2_0_SEL, 0x00000021}, + {AUD_IIR2_0_SHIFT, 0x00000002}, + {AUD_DEEMPH0_SRC_SEL, 0x0000000b}, + {AUD_DEEMPH1_SRC_SEL, 0x0000000b}, + {AUD_POLYPH80SCALEFAC, 0x00000001}, + {AUD_START_TIMER, 0x00000000}, + { /* end of list */ }, + }; + + static const struct rlist am_l[] = { + {AUD_ERRLOGPERIOD_R, 0x00000064}, + {AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF}, + {AUD_ERRINTRPTTHSHLD2_R, 0x0000001F}, + {AUD_ERRINTRPTTHSHLD3_R, 0x0000000F}, + {AUD_PDF_DDS_CNST_BYTE2, 0x48}, + {AUD_PDF_DDS_CNST_BYTE1, 0x3D}, + {AUD_QAM_MODE, 0x00}, + {AUD_PDF_DDS_CNST_BYTE0, 0xf5}, + {AUD_PHACC_FREQ_8MSB, 0x3a}, + {AUD_PHACC_FREQ_8LSB, 0x4a}, + {AUD_DEEMPHGAIN_R, 0x00006680}, + {AUD_DEEMPHNUMER1_R, 0x000353DE}, + {AUD_DEEMPHNUMER2_R, 0x000001B1}, + {AUD_DEEMPHDENOM1_R, 0x0000F3D0}, + {AUD_DEEMPHDENOM2_R, 0x00000000}, + {AUD_FM_MODE_ENABLE, 0x00000007}, + {AUD_POLYPH80SCALEFAC, 0x00000003}, + {AUD_AFE_12DB_EN, 0x00000001}, + {AAGC_GAIN, 0x00000000}, + {AAGC_HYST, 0x00000018}, + {AAGC_DEF, 0x00000020}, + {AUD_DN0_FREQ, 0x00000000}, + {AUD_POLY0_DDS_CONSTANT, 0x000E4DB2}, + {AUD_DCOC_0_SRC, 0x00000021}, + {AUD_IIR1_0_SEL, 0x00000000}, + {AUD_IIR1_0_SHIFT, 0x00000007}, + {AUD_IIR1_1_SEL, 0x00000002}, + {AUD_IIR1_1_SHIFT, 0x00000000}, + {AUD_DCOC_1_SRC, 0x00000003}, + {AUD_DCOC1_SHIFT, 0x00000000}, + {AUD_DCOC_PASS_IN, 0x00000000}, + {AUD_IIR1_2_SEL, 0x00000023}, + {AUD_IIR1_2_SHIFT, 0x00000000}, + {AUD_IIR1_3_SEL, 0x00000004}, + {AUD_IIR1_3_SHIFT, 0x00000007}, + {AUD_IIR1_4_SEL, 0x00000005}, + {AUD_IIR1_4_SHIFT, 0x00000007}, + {AUD_IIR3_0_SEL, 0x00000007}, + {AUD_IIR3_0_SHIFT, 0x00000000}, + {AUD_DEEMPH0_SRC_SEL, 0x00000011}, + {AUD_DEEMPH0_SHIFT, 0x00000000}, + {AUD_DEEMPH0_G0, 0x00007000}, + {AUD_DEEMPH0_A0, 0x00000000}, + {AUD_DEEMPH0_B0, 0x00000000}, + {AUD_DEEMPH0_A1, 0x00000000}, + {AUD_DEEMPH0_B1, 0x00000000}, + {AUD_DEEMPH1_SRC_SEL, 0x00000011}, + {AUD_DEEMPH1_SHIFT, 0x00000000}, + {AUD_DEEMPH1_G0, 0x00007000}, + {AUD_DEEMPH1_A0, 0x00000000}, + {AUD_DEEMPH1_B0, 0x00000000}, + {AUD_DEEMPH1_A1, 0x00000000}, + {AUD_DEEMPH1_B1, 0x00000000}, + {AUD_OUT0_SEL, 0x0000003F}, + {AUD_OUT1_SEL, 0x0000003F}, + {AUD_DMD_RA_DDS, 0x00F5C285}, + {AUD_PLL_INT, 0x0000001E}, + {AUD_PLL_DDS, 0x00000000}, + {AUD_PLL_FRAC, 0x0000E542}, + {AUD_RATE_ADJ1, 0x00000100}, + {AUD_RATE_ADJ2, 0x00000200}, + {AUD_RATE_ADJ3, 0x00000300}, + {AUD_RATE_ADJ4, 0x00000400}, + {AUD_RATE_ADJ5, 0x00000500}, + {AUD_RATE_THRES_DMD, 0x000000C0}, + {/* end of list */ }, }; static const struct rlist a2_deemph50[] = { @@ -616,32 +591,32 @@ static void set_audio_standard_A2(struct cx88_core *core, u32 mode) { /* end of list */ }, }; - static const struct rlist a2_deemph75[] = { - {AUD_DEEMPH0_G0, 0x00000480}, - {AUD_DEEMPH1_G0, 0x00000480}, - {AUD_DEEMPHGAIN_R, 0x00009000}, - {AUD_DEEMPHNUMER1_R, 0x000353de}, - {AUD_DEEMPHNUMER2_R, 0x000001b1}, - { /* end of list */ }, - }; - set_audio_start(core, SEL_A2); - set_audio_registers(core, a2_common); switch (core->tvaudio) { - case WW_A2_BG: - dprintk("%s PAL-BG A2 (status: known-good)\n",__FUNCTION__); - set_audio_registers(core, a2_bg); - set_audio_registers(core, a2_deemph50); + case WW_BG: + dprintk("%s PAL-BG A1/2 (status: known-good)\n",__FUNCTION__); + set_audio_registers(core, a2_bgdk_common); + set_audio_registers(core, a2_bg); + set_audio_registers(core, a2_deemph50); break; - case WW_A2_DK: - dprintk("%s PAL-DK A2 (status: known-good)\n",__FUNCTION__); - set_audio_registers(core, a2_dk); - set_audio_registers(core, a2_deemph50); + case WW_DK: + dprintk("%s PAL-DK A1/2 (status: known-good)\n",__FUNCTION__); + set_audio_registers(core, a2_bgdk_common); + set_audio_registers(core, a2_dk); + set_audio_registers(core, a2_deemph50); break; - case WW_A2_M: - dprintk("%s NTSC-M A2 (status: unknown)\n",__FUNCTION__); - set_audio_registers(core, a2_m); - set_audio_registers(core, a2_deemph75); + case WW_I: + dprintk("%s PAL-I A1 (status: known-good)\n",__FUNCTION__); + set_audio_registers(core, a1_i); + set_audio_registers(core, a2_deemph50); + break; + case WW_L: + dprintk("%s AM-L (status: devel)\n",__FUNCTION__); + set_audio_registers(core, am_l); + break; + default: + dprintk("%s Warning: wrong value\n",__FUNCTION__); + return; break; }; @@ -728,22 +703,53 @@ static void set_audio_standard_FM(struct cx88_core *core, enum cx88_deemph_type /* ----------------------------------------------------------- */ +int cx88_detect_nicam(struct cx88_core *core) +{ + int i, j=0; + + dprintk("start nicam autodetect.\n"); + + for(i=0; i<6; i++) { + /* if bit1=1 then nicam is detected */ + j+= ((cx_read(AUD_NICAM_STATUS2) & 0x02) >> 1); + + /* 3x detected: absolutly sure now */ + if(j==3) { + dprintk("nicam is detected.\n"); + return 1; + } + + /* wait a little bit for next reading status */ + msleep (10); + } + + dprintk("nicam is not detected.\n"); + return 0; +} + void cx88_set_tvaudio(struct cx88_core *core) { switch (core->tvaudio) { case WW_BTSC: set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO); break; - case WW_NICAM_BGDKL: - set_audio_standard_NICAM_L(core,0); - break; - case WW_NICAM_I: - set_audio_standard_PAL_I(core,0); - break; - case WW_A2_BG: - case WW_A2_DK: - case WW_A2_M: - set_audio_standard_A2(core, EN_A2_FORCE_MONO1); + case WW_BG: + case WW_DK: + case WW_I: + case WW_L: + /* prepare all dsp registers */ + set_audio_standard_A2(core, EN_A2_FORCE_MONO1); + + /* set nicam mode - otherwise + AUD_NICAM_STATUS2 contains wrong values */ + set_audio_standard_NICAM(core, EN_NICAM_FORCE_MONO1); + if(0 == cx88_detect_nicam(core)) { + /* fall back to fm / am mono */ + set_audio_standard_A2(core, EN_A2_FORCE_MONO1); + core->use_nicam = 0; + } else { + core->use_nicam = 1; + } break; case WW_EIAJ: set_audio_standard_EIAJ(core); @@ -751,9 +757,6 @@ void cx88_set_tvaudio(struct cx88_core *core) case WW_FM: set_audio_standard_FM(core,FM_NO_DEEMPH); break; - case WW_SYSTEM_L_AM: - set_audio_standard_NICAM_L(core, 1); - break; case WW_NONE: default: printk("%s/0: unknown tv audio mode [%d]\n", @@ -766,14 +769,6 @@ void cx88_set_tvaudio(struct cx88_core *core) void cx88_newstation(struct cx88_core *core) { core->audiomode_manual = UNSET; - - switch (core->tvaudio) { - case WW_SYSTEM_L_AM: - /* try nicam ... */ - core->audiomode_current = V4L2_TUNER_MODE_STEREO; - set_audio_standard_NICAM_L(core, 1); - break; - } } void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t) @@ -879,58 +874,42 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual) break; } break; - case WW_A2_BG: - case WW_A2_DK: - case WW_A2_M: - switch (mode) { - case V4L2_TUNER_MODE_MONO: - case V4L2_TUNER_MODE_LANG1: - set_audio_standard_A2(core, EN_A2_FORCE_MONO1); - break; - case V4L2_TUNER_MODE_LANG2: - set_audio_standard_A2(core, EN_A2_FORCE_MONO2); - break; - case V4L2_TUNER_MODE_STEREO: - set_audio_standard_A2(core, EN_A2_FORCE_STEREO); - break; - } - break; - case WW_NICAM_BGDKL: - switch (mode) { - case V4L2_TUNER_MODE_MONO: - ctl = EN_NICAM_FORCE_MONO1; - mask = 0x3f; - break; - case V4L2_TUNER_MODE_LANG1: - ctl = EN_NICAM_AUTO_MONO2; - mask = 0x3f; - break; - case V4L2_TUNER_MODE_STEREO: - ctl = EN_NICAM_FORCE_STEREO | EN_DMTRX_LR; - mask = 0x93f; - break; - } - break; - case WW_SYSTEM_L_AM: - switch (mode) { - case V4L2_TUNER_MODE_MONO: - case V4L2_TUNER_MODE_LANG1: /* FIXME */ - set_audio_standard_NICAM_L(core, 0); - break; - case V4L2_TUNER_MODE_STEREO: - set_audio_standard_NICAM_L(core, 1); - break; - } - break; - case WW_NICAM_I: - switch (mode) { - case V4L2_TUNER_MODE_MONO: - case V4L2_TUNER_MODE_LANG1: - set_audio_standard_PAL_I(core, 0); - break; - case V4L2_TUNER_MODE_STEREO: - set_audio_standard_PAL_I(core, 1); - break; + case WW_BG: + case WW_DK: + case WW_I: + case WW_L: + if(1 == core->use_nicam) { + switch (mode) { + case V4L2_TUNER_MODE_MONO: + case V4L2_TUNER_MODE_LANG1: + set_audio_standard_NICAM(core, EN_NICAM_FORCE_MONO1); + break; + case V4L2_TUNER_MODE_LANG2: + set_audio_standard_NICAM(core, EN_NICAM_FORCE_MONO2); + break; + case V4L2_TUNER_MODE_STEREO: + set_audio_standard_NICAM(core, EN_NICAM_FORCE_STEREO); + break; + } + } else { + if ( (core->tvaudio == WW_I) || (core->tvaudio == WW_L) ) { + /* fall back to fm / am mono */ + set_audio_standard_A2(core, EN_A2_FORCE_MONO1); + } else { + /* TODO: Add A2 autodection */ + switch (mode) { + case V4L2_TUNER_MODE_MONO: + case V4L2_TUNER_MODE_LANG1: + set_audio_standard_A2(core, EN_A2_FORCE_MONO1); + break; + case V4L2_TUNER_MODE_LANG2: + set_audio_standard_A2(core, EN_A2_FORCE_MONO2); + break; + case V4L2_TUNER_MODE_STEREO: + set_audio_standard_A2(core, EN_A2_FORCE_STEREO); + break; + } + } } break; case WW_FM: diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index b18205b3fa2..3d885b4025d 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -288,6 +288,7 @@ struct cx88_core { u32 audiomode_current; u32 input; u32 astat; + u32 use_nicam; /* IR remote control state */ struct cx88_IR *ir; @@ -527,22 +528,20 @@ extern void cx88_card_setup(struct cx88_core *core); #define WW_NONE 1 #define WW_BTSC 2 -#define WW_NICAM_I 3 -#define WW_NICAM_BGDKL 4 -#define WW_A1 5 -#define WW_A2_BG 6 -#define WW_A2_DK 7 -#define WW_A2_M 8 -#define WW_EIAJ 9 -#define WW_SYSTEM_L_AM 10 -#define WW_I2SPT 11 -#define WW_FM 12 +#define WW_BG 3 +#define WW_DK 4 +#define WW_I 5 +#define WW_L 6 +#define WW_EIAJ 7 +#define WW_I2SPT 8 +#define WW_FM 9 void cx88_set_tvaudio(struct cx88_core *core); void cx88_newstation(struct cx88_core *core); void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t); void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual); int cx88_audio_thread(void *data); +int cx88_detect_nicam(struct cx88_core *core); /* ----------------------------------------------------------- */ /* cx88-input.c */ -- cgit v1.2.3 From c5df599b67b5a061d28a2154a49f9704e0d1040b Mon Sep 17 00:00:00 2001 From: Catalin Climov Date: Tue, 8 Nov 2005 21:36:28 -0800 Subject: [PATCH] v4l: 649: fixed gcc 4 0 compile warnings by moving var declarations to the top of the function or block - Fixed gcc 4.0 compile warnings by moving var declarations to the top of the function or block. Signed-off-by: Catalin Climov Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/cx88-blackbird.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index eca36b8539f..fac67d98a74 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -781,6 +781,7 @@ static const int BITRATES_SIZE = ARRAY_SIZE(mpeg_audio_bitrates); static void blackbird_set_default_params(struct cx8802_dev *dev) { struct v4l2_mpeg_compression *params = &dev->params; + u32 au_params; /* assign stream type */ if( params->st_type >= ARRAY_SIZE(mpeg_stream_types) ) @@ -827,7 +828,7 @@ static void blackbird_set_default_params(struct cx8802_dev *dev) /* assign audio properties */ /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */ - u32 au_params = BLACKBIRD_AUDIO_BITS_STEREO | + au_params = BLACKBIRD_AUDIO_BITS_STEREO | /* BLACKBIRD_AUDIO_BITS_BOUND_4 | */ BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE | BLACKBIRD_AUDIO_BITS_CRC_OFF | @@ -861,12 +862,14 @@ static void blackbird_set_default_params(struct cx8802_dev *dev) } if( params->au_bitrate.mode ) { + int layer; + if( params->au_bitrate.mode == V4L2_BITRATE_CBR ) params->au_bitrate.max = params->vi_bitrate.target; else params->au_bitrate.target = params->vi_bitrate.max; - int layer = params->au_type; + layer = params->au_type; if( params->au_bitrate.target == 0 ) { /* TODO: use the minimum possible bitrate instead of 0 ? */ @@ -946,6 +949,8 @@ static void blackbird_set_default_params(struct cx8802_dev *dev) #define UPDATE_PARAM( name ) dev->params.name = params->name void blackbird_set_params(struct cx8802_dev *dev, struct v4l2_mpeg_compression *params) { + u32 au_params; + /* assign stream type */ if( params->st_type >= ARRAY_SIZE(mpeg_stream_types) ) params->st_type = V4L2_MPEG_PS_2; @@ -1015,7 +1020,7 @@ void blackbird_set_params(struct cx8802_dev *dev, struct v4l2_mpeg_compression * /* assign audio properties */ /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */ - u32 au_params = BLACKBIRD_AUDIO_BITS_STEREO | + au_params = BLACKBIRD_AUDIO_BITS_STEREO | /* BLACKBIRD_AUDIO_BITS_BOUND_4 | */ BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE | BLACKBIRD_AUDIO_BITS_CRC_OFF | @@ -1049,12 +1054,14 @@ void blackbird_set_params(struct cx8802_dev *dev, struct v4l2_mpeg_compression * } if( params->au_bitrate.mode ) { + int layer; + if( params->au_bitrate.mode == V4L2_BITRATE_CBR ) params->au_bitrate.max = params->vi_bitrate.target; else params->au_bitrate.target = params->vi_bitrate.max; - int layer = params->au_type; + layer = params->au_type; if( params->au_bitrate.target == 0 ) { /* TODO: use the minimum possible bitrate instead of 0 ? */ -- cgit v1.2.3 From f9e7a0203def0704beaf4af1ff2c772f9fa712cf Mon Sep 17 00:00:00 2001 From: Peter Hagervall Date: Tue, 8 Nov 2005 21:36:29 -0800 Subject: [PATCH] v4l: 651: fix a number of sparse warnings - Fix a number of sparse warnings. Signed-off-by: Peter Hagervall Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/cx88-core.c | 2 +- drivers/media/video/cx88/cx88-video.c | 2 +- drivers/media/video/cx88/cx88.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 87212759149..8f1c27fdae6 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -431,7 +431,7 @@ int cx88_sram_channel_setup(struct cx88_core *core, /* ------------------------------------------------------------------ */ /* debug helper code */ -int cx88_risc_decode(u32 risc) +static int cx88_risc_decode(u32 risc) { static char *instr[16] = { [ RISC_SYNC >> 28 ] = "sync", diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 67630f61c47..a29c12754ef 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -787,7 +787,7 @@ static int video_open(struct inode *inode, struct file *file) } static ssize_t -video_read(struct file *file, char *data, size_t count, loff_t *ppos) +video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) { struct cx8800_fh *fh = file->private_data; diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 3d885b4025d..bd27b56ace2 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -204,8 +204,8 @@ struct cx88_board { int tda9887_conf; struct cx88_input input[MAX_CX88_INPUT]; struct cx88_input radio; - int blackbird:1; - int dvb:1; + unsigned int blackbird:1; + unsigned int dvb:1; }; struct cx88_subid { -- cgit v1.2.3 From 3aa4f48aee93e793071e26d6807efdf6eb111614 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 8 Nov 2005 21:36:30 -0800 Subject: [PATCH] v4l: 653: ts dma buffer synchronization was inverted - TS DMA buffer synchronization was inverted Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-ts.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c index 463885601ab..cdfd69873ba 100644 --- a/drivers/media/video/saa7134/saa7134-ts.c +++ b/drivers/media/video/saa7134/saa7134-ts.c @@ -46,17 +46,11 @@ static int buffer_activate(struct saa7134_dev *dev, struct saa7134_buf *buf, struct saa7134_buf *next) { - u32 control; dprintk("buffer_activate [%p]",buf); buf->vb.state = STATE_ACTIVE; buf->top_seen = 0; - /* dma: setup channel 5 (= TS) */ - control = SAA7134_RS_CONTROL_BURST_16 | - SAA7134_RS_CONTROL_ME | - (buf->pt->dma >> 12); - if (NULL == next) next = buf; if (V4L2_FIELD_TOP == buf->vb.field) { @@ -68,8 +62,6 @@ static int buffer_activate(struct saa7134_dev *dev, saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(next)); saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(buf)); } - saa_writel(SAA7134_RS_PITCH(5),TS_PACKET_SIZE); - saa_writel(SAA7134_RS_CONTROL(5),control); /* start DMA */ saa7134_set_dmabits(dev); @@ -84,6 +76,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, struct saa7134_dev *dev = q->priv_data; struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); unsigned int lines, llength, size; + u32 control; int err; dprintk("buffer_prepare [%p,%s]\n",buf,v4l2_field_names[field]); @@ -115,6 +108,18 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, if (err) goto oops; } + + /* dma: setup channel 5 (= TS) */ + control = SAA7134_RS_CONTROL_BURST_16 | + SAA7134_RS_CONTROL_ME | + (buf->pt->dma >> 12); + + saa_writeb(SAA7134_TS_DMA0, ((lines-1)&0xff)); + saa_writeb(SAA7134_TS_DMA1, (((lines-1)>>8)&0xff)); + saa_writeb(SAA7134_TS_DMA2, ((((lines-1)>>16)&0x3f) | 0x00)); /* TSNOPIT=0, TSCOLAP=0 */ + saa_writel(SAA7134_RS_PITCH(5),TS_PACKET_SIZE); + saa_writel(SAA7134_RS_CONTROL(5),control); + buf->vb.state = STATE_PREPARED; buf->activate = buffer_activate; buf->vb.field = field; @@ -164,11 +169,11 @@ EXPORT_SYMBOL_GPL(saa7134_ts_qops); /* ----------------------------------------------------------- */ /* exported stuff */ -static unsigned int tsbufs = 4; +static unsigned int tsbufs = 8; module_param(tsbufs, int, 0444); MODULE_PARM_DESC(tsbufs,"number of ts buffers, range 2-32"); -static unsigned int ts_nr_packets = 30; +static unsigned int ts_nr_packets = 64; module_param(ts_nr_packets, int, 0444); MODULE_PARM_DESC(ts_nr_packets,"size of a ts buffers (in ts packets)"); @@ -220,10 +225,10 @@ void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status) if (dev->ts_q.curr) { field = dev->ts_q.curr->vb.field; if (field == V4L2_FIELD_TOP) { - if ((status & 0x100000) != 0x100000) + if ((status & 0x100000) != 0x000000) goto done; } else { - if ((status & 0x100000) != 0x000000) + if ((status & 0x100000) != 0x100000) goto done; } saa7134_buffer_finish(dev,&dev->ts_q,STATE_DONE); -- cgit v1.2.3 From 93df3413f1b4c437b93c5b64562632f4f0e2b3ca Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 8 Nov 2005 21:36:31 -0800 Subject: [PATCH] v4l: 655: added support for the philips td1316 tuner - Added support for the Philips TD1316 tuner Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tuner-core.c | 7 +++++++ drivers/media/video/tuner-simple.c | 2 ++ include/media/tuner.h | 1 + 3 files changed, 10 insertions(+) diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index ad85bef1c3d..949c2550fcf 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -189,6 +189,13 @@ static void set_type(struct i2c_client *c, unsigned int type, i2c_master_send(c, buffer, 4); default_tuner_init(c); break; + case TUNER_PHILIPS_TD1316: + buffer[0] = 0x0b; + buffer[1] = 0xdc; + buffer[2] = 0x86; + buffer[3] = 0xa4; + i2c_master_send(c,buffer,4); + default_tuner_init(c); default: default_tuner_init(c); break; diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 0ae39be3ca5..3af055970dd 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -248,6 +248,8 @@ static struct tunertype tuners[] = { 16*160.25,16*464.25,0x01,0x02,0x08,0x8e,623}, { "LG NTSC (TALN mini series)", LGINNOTEK, NTSC, 16*137.25,16*373.25,0x01,0x02,0x08,0x8e,732 }, + { "Philips TD1316 Hybrid Tuner", Philips, PAL, + 16*160.00,16*442.00,0xa1,0xa2,0xa4,0xc8,623 }, }; unsigned const int tuner_count = ARRAY_SIZE(tuners); diff --git a/include/media/tuner.h b/include/media/tuner.h index 4ad08e24a1a..4f47eac90ca 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -110,6 +110,7 @@ #define TUNER_LG_TDVS_H062F 64 /* DViCO FusionHDTV 5 */ #define TUNER_YMEC_TVF66T5_B_DFF 65 /* Acorp Y878F */ #define TUNER_LG_NTSC_TALN_MINI 66 +#define TUNER_PHILIPS_TD1316 67 #define NOTUNER 0 #define PAL 1 /* PAL_BG */ -- cgit v1.2.3 From 2cf36ac447308046d1c1d50b9f662bddbba56b33 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 8 Nov 2005 21:36:32 -0800 Subject: [PATCH] v4l: 656: added support for the following cards - Added support for the following cards: - Philips EUROPA reference desigh - Compro VideoMate DVB-T300 - Compro VideoMate DVB-T200 (initial) Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-cards.c | 104 ++++++++++++++++++- drivers/media/video/saa7134/saa7134-dvb.c | 152 ++++++++++++++++++++++++---- drivers/media/video/saa7134/saa7134.h | 3 + 3 files changed, 236 insertions(+), 23 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index fea2188b2fa..8291ed70973 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2185,6 +2185,72 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x00200003, }, }, + [SAA7134_BOARD_PHILIPS_EUROPA] = { + .name = "Philips EUROPA V3 reference design", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TD1316, + .radio_type = UNSET, + .tuner_addr = 0x61, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .mpeg = SAA7134_MPEG_DVB, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 0, + .amux = LINE2, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + }}, + }, + [SAA7134_BOARD_VIDEOMATE_DVBT_300] = { + .name = "Compro Videomate DVB-T300", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TD1316, + .radio_type = UNSET, + .tuner_addr = 0x61, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .mpeg = SAA7134_MPEG_DVB, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 1, + .amux = LINE2, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + }}, + }, + [SAA7134_BOARD_VIDEOMATE_DVBT_200] = { + .name = "Compro Videomate DVB-T200", + .tuner_type = TUNER_ABSENT, + .audio_clock = 0x00187de7, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .mpeg = SAA7134_MPEG_DVB, + .inputs = {{ + .name = name_comp1, + .vmux = 0, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + }}, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -2555,6 +2621,24 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0x7135, .driver_data = SAA7134_BOARD_GOTVIEW_7135, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = PCI_VENDOR_ID_PHILIPS, + .subdevice = 0x2004, + .driver_data = SAA7134_BOARD_PHILIPS_EUROPA, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x185b, + .subdevice = 0xc900, + .driver_data = SAA7134_BOARD_VIDEOMATE_DVBT_300, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7130, + .subvendor = 0x185b, + .subdevice = 0xc901, + .driver_data = SAA7134_BOARD_VIDEOMATE_DVBT_200, + },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -2708,7 +2792,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR, &tun_setup); } break; -case SAA7134_BOARD_MD7134: + case SAA7134_BOARD_MD7134: { struct tuner_setup tun_setup; u8 subaddr; @@ -2775,6 +2859,24 @@ case SAA7134_BOARD_MD7134: saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup); } break; + case SAA7134_BOARD_PHILIPS_EUROPA: + case SAA7134_BOARD_VIDEOMATE_DVBT_300: + /* The Philips EUROPA based hybrid boards have the tuner connected through + * the channel decoder. We have to make it transparent to find it + */ + { + struct tuner_setup tun_setup; + u8 data[] = { 0x07, 0x02}; + struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; + i2c_transfer(&dev->i2c_adap, &msg, 1); + + tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; + tun_setup.type = dev->tuner_type; + tun_setup.addr = dev->tuner_addr; + + saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup); + } + break; } return 0; } diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 639ae51a052..f8e01030fbc 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -151,25 +151,12 @@ static struct mt352_config pinnacle_300i = { /* ------------------------------------------------------------------ */ #ifdef HAVE_TDA1004X -static int philips_tu1216_pll_init(struct dvb_frontend *fe) -{ - struct saa7134_dev *dev = fe->dvb->priv; - static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab }; - struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) }; - - /* setup PLL configuration */ - if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) - return -EIO; - msleep(1); - - return 0; -} -static int philips_tu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int philips_tda6651_pll_set(u8 addr, struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct saa7134_dev *dev = fe->dvb->priv; u8 tuner_buf[4]; - struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf,.len = + struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tuner_buf,.len = sizeof(tuner_buf) }; int tuner_frequency = 0; u8 band, cp, filter; @@ -242,11 +229,36 @@ static int philips_tu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_p if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) return -EIO; + msleep(1); + return 0; +} + +static int philips_tda6651_pll_init(u8 addr, struct dvb_frontend *fe) +{ + struct saa7134_dev *dev = fe->dvb->priv; + static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab }; + struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) }; + /* setup PLL configuration */ + if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) + return -EIO; msleep(1); + return 0; } +/* ------------------------------------------------------------------ */ + +static int philips_tu1216_pll_60_init(struct dvb_frontend *fe) +{ + return philips_tda6651_pll_init(0x60, fe); +} + +static int philips_tu1216_pll_60_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + return philips_tda6651_pll_set(0x60, fe, params); +} + static int philips_tu1216_request_firmware(struct dvb_frontend *fe, const struct firmware **fw, char *name) { @@ -254,22 +266,108 @@ static int philips_tu1216_request_firmware(struct dvb_frontend *fe, return request_firmware(fw, name, &dev->pci->dev); } -static struct tda1004x_config philips_tu1216_config = { +static struct tda1004x_config philips_tu1216_60_config = { .demod_address = 0x8, .invert = 1, - .invert_oclk = 1, + .invert_oclk = 0, .xtal_freq = TDA10046_XTAL_4M, .agc_config = TDA10046_AGC_DEFAULT, .if_freq = TDA10046_FREQ_3617, - .pll_init = philips_tu1216_pll_init, - .pll_set = philips_tu1216_pll_set, + .pll_init = philips_tu1216_pll_60_init, + .pll_set = philips_tu1216_pll_60_set, .pll_sleep = NULL, .request_firmware = philips_tu1216_request_firmware, }; /* ------------------------------------------------------------------ */ +static int philips_tu1216_pll_61_init(struct dvb_frontend *fe) +{ + return philips_tda6651_pll_init(0x61, fe); +} + +static int philips_tu1216_pll_61_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + return philips_tda6651_pll_set(0x61, fe, params); +} + +static struct tda1004x_config philips_tu1216_61_config = { + + .demod_address = 0x8, + .invert = 1, + .invert_oclk = 0, + .xtal_freq = TDA10046_XTAL_4M, + .agc_config = TDA10046_AGC_DEFAULT, + .if_freq = TDA10046_FREQ_3617, + .pll_init = philips_tu1216_pll_61_init, + .pll_set = philips_tu1216_pll_61_set, + .pll_sleep = NULL, + .request_firmware = philips_tu1216_request_firmware, +}; + +/* ------------------------------------------------------------------ */ + +static int philips_europa_pll_init(struct dvb_frontend *fe) +{ + struct saa7134_dev *dev = fe->dvb->priv; + static u8 msg[] = { 0x0b, 0xf5, 0x86, 0xab }; + struct i2c_msg init_msg = {.addr = 0x61,.flags = 0,.buf = msg,.len = sizeof(msg) }; + + /* setup PLL configuration */ + if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) + return -EIO; + msleep(1); + + /* switch the board to dvb mode */ + init_msg.addr = 0x43; + init_msg.len = 0x02; + msg[0] = 0x00; + msg[1] = 0x40; + if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) + return -EIO; + + return 0; +} + +static int philips_td1316_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + return philips_tda6651_pll_set(0x61, fe, params); +} + +static void philips_europa_analog(struct dvb_frontend *fe) +{ + struct saa7134_dev *dev = fe->dvb->priv; + /* this message actually turns the tuner back to analog mode */ + static u8 msg[] = { 0x0b, 0xdc, 0x86, 0xa4 }; + struct i2c_msg analog_msg = {.addr = 0x61,.flags = 0,.buf = msg,.len = sizeof(msg) }; + + i2c_transfer(&dev->i2c_adap, &analog_msg, 1); + msleep(1); + + /* switch the board to analog mode */ + analog_msg.addr = 0x43; + analog_msg.len = 0x02; + msg[0] = 0x00; + msg[1] = 0x14; + i2c_transfer(&dev->i2c_adap, &analog_msg, 1); +} + +static struct tda1004x_config philips_europa_config = { + + .demod_address = 0x8, + .invert = 0, + .invert_oclk = 0, + .xtal_freq = TDA10046_XTAL_4M, + .agc_config = TDA10046_AGC_IFO_AUTO_POS, + .if_freq = TDA10046_FREQ_052, + .pll_init = philips_europa_pll_init, + .pll_set = philips_td1316_pll_set, + .pll_sleep = philips_europa_analog, + .request_firmware = NULL, +}; + +/* ------------------------------------------------------------------ */ static int philips_fmd1216_pll_init(struct dvb_frontend *fe) { @@ -382,7 +480,6 @@ static int philips_fmd1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_ return 0; } -#ifdef HAVE_TDA1004X static struct tda1004x_config medion_cardbus = { .demod_address = 0x08, .invert = 1, @@ -395,7 +492,6 @@ static struct tda1004x_config medion_cardbus = { .pll_sleep = philips_fmd1216_analog, .request_firmware = NULL, }; -#endif /* ------------------------------------------------------------------ */ @@ -558,7 +654,7 @@ static int dvb_init(struct saa7134_dev *dev) &dev->i2c_adap); break; case SAA7134_BOARD_PHILIPS_TOUGH: - dev->dvb.frontend = tda10046_attach(&philips_tu1216_config, + dev->dvb.frontend = tda10046_attach(&philips_tu1216_60_config, &dev->i2c_adap); break; case SAA7134_BOARD_FLYDVBTDUO: @@ -569,6 +665,18 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, &dev->i2c_adap); break; + case SAA7134_BOARD_PHILIPS_EUROPA: + dev->dvb.frontend = tda10046_attach(&philips_europa_config, + &dev->i2c_adap); + break; + case SAA7134_BOARD_VIDEOMATE_DVBT_300: + dev->dvb.frontend = tda10046_attach(&philips_europa_config, + &dev->i2c_adap); + break; + case SAA7134_BOARD_VIDEOMATE_DVBT_200: + dev->dvb.frontend = tda10046_attach(&philips_tu1216_61_config, + &dev->i2c_adap); + break; #endif default: printk("%s: Huh? unknown DVB card?\n",dev->name); diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 291c2e8d108..69a2cebe886 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -189,6 +189,9 @@ struct saa7134_format { #define SAA7134_BOARD_YUAN_TUN900 66 #define SAA7134_BOARD_BEHOLD_409FM 67 #define SAA7134_BOARD_GOTVIEW_7135 68 +#define SAA7134_BOARD_PHILIPS_EUROPA 69 +#define SAA7134_BOARD_VIDEOMATE_DVBT_300 70 +#define SAA7134_BOARD_VIDEOMATE_DVBT_200 71 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From 84a5e55c70d881451208ec56609ccd75053c08fa Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:36:33 -0800 Subject: [PATCH] v4l: 657: update documentation - Update tuner documentation Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.saa7134 | 3 +++ Documentation/video4linux/CARDLIST.tuner | 1 + 2 files changed, 4 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 411f842c5d1..b2643051339 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -67,3 +67,6 @@ 66 -> Yuan TUN-900 (saa7135) 67 -> Beholder BeholdTV 409 FM [0000:4091] 68 -> GoTView 7135 PCI [5456:7135] + 69 -> Philips EUROPA V3 reference design [1131:2004] + 70 -> Compro Videomate DVB-T300 [185b:c900] + 71 -> Compro Videomate DVB-T200 [185b:c901] diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index f5876be658a..84203302b27 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -65,3 +65,4 @@ tuner=63 - Philips FMD1216ME MK3 Hybrid Tuner tuner=64 - LG TDVS-H062F/TUA6034 tuner=65 - Ymec TVF66T5-B/DFF tuner=66 - LG NTSC (TALN mini series) +tuner=67 - Philips TD1316 Hybrid Tuner -- cgit v1.2.3 From fd1c388125d713b403569d96d9845470142884a2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:36:34 -0800 Subject: [PATCH] v4l: 660: small fixes - Small fixes on tuner debug message. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tuner-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 949c2550fcf..44fa1423c1a 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -695,7 +695,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } default: - tuner_dbg("Unimplemented IOCTL 0x%08x(dir=%d,tp=0x%02x,nr=%d,sz=%d)\n", + tuner_dbg("Unimplemented IOCTL 0x%08x(dir=%d,tp='%c',nr=%d,sz=%d)\n", cmd, _IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd)); break; -- cgit v1.2.3 From bb881f142465a7a70bc9a364786e39aa4aaba4d2 Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:36:35 -0800 Subject: [PATCH] v4l: 663: add new rtd cards - Add new RTD cards Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.saa7134 | 2 + drivers/media/video/saa7134/saa7134-cards.c | 91 +++++++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134-reg.h | 1 + drivers/media/video/saa7134/saa7134-video.c | 9 ++- drivers/media/video/saa7134/saa7134.h | 2 + 5 files changed, 103 insertions(+), 2 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index b2643051339..82b5f7c73c8 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -70,3 +70,5 @@ 69 -> Philips EUROPA V3 reference design [1131:2004] 70 -> Compro Videomate DVB-T300 [185b:c900] 71 -> Compro Videomate DVB-T200 [185b:c901] + 72 -> RTD Embedded Technologies VFG7350 [1435:7350] + 73 -> RTD Embedded Technologies VFG7330 [1435:7330] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 8291ed70973..8bb2faf2635 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2251,6 +2251,74 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, }}, }, + [SAA7134_BOARD_RTD_VFG7350] = { + .name = "RTD Embedded Technologies VFG7350", + .audio_clock = 0x00200000, + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = {{ + .name = "Composite 0", + .vmux = 0, + .amux = LINE1, + },{ + .name = "Composite 1", + .vmux = 1, + .amux = LINE2, + },{ + .name = "Composite 2", + .vmux = 2, + .amux = LINE1, + },{ + .name = "Composite 3", + .vmux = 3, + .amux = LINE2, + },{ + .name = "S-Video 0", + .vmux = 8, + .amux = LINE1, + },{ + .name = "S-Video 1", + .vmux = 9, + .amux = LINE2, + }}, + .mpeg = SAA7134_MPEG_EMPRESS, + .video_out = CCIR656, + }, + [SAA7134_BOARD_RTD_VFG7330] = { + .name = "RTD Embedded Technologies VFG7330", + .audio_clock = 0x00200000, + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = {{ + .name = "Composite 0", + .vmux = 0, + .amux = LINE1, + },{ + .name = "Composite 1", + .vmux = 1, + .amux = LINE2, + },{ + .name = "Composite 2", + .vmux = 2, + .amux = LINE1, + },{ + .name = "Composite 3", + .vmux = 3, + .amux = LINE2, + },{ + .name = "S-Video 0", + .vmux = 8, + .amux = LINE1, + },{ + .name = "S-Video 1", + .vmux = 9, + .amux = LINE2, + }}, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -2639,6 +2707,18 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0xc901, .driver_data = SAA7134_BOARD_VIDEOMATE_DVBT_200, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1435, + .subdevice = 0x7350, + .driver_data = SAA7134_BOARD_RTD_VFG7350, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1435, + .subdevice = 0x7330, + .driver_data = SAA7134_BOARD_RTD_VFG7330, + },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -2758,6 +2838,17 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0xffffffff); msleep(1); break; + case SAA7134_BOARD_RTD_VFG7350: + + /* + * Make sure Production Test Register at offset 0x1D1 is cleared + * to take chip out of test mode. Clearing bit 4 (TST_EN_AOUT) + * prevents pin 105 from remaining low; keeping pin 105 low + * continually resets the SAA6752 chip. + */ + + saa_writeb (SAA7134_PRODUCTION_TEST_MODE, 0x00); + break; } return 0; } diff --git a/drivers/media/video/saa7134/saa7134-reg.h b/drivers/media/video/saa7134/saa7134-reg.h index ae0c7a16539..fce4f185ef9 100644 --- a/drivers/media/video/saa7134/saa7134-reg.h +++ b/drivers/media/video/saa7134/saa7134-reg.h @@ -348,6 +348,7 @@ /* test modes */ #define SAA7134_SPECIAL_MODE 0x1d0 +#define SAA7134_PRODUCTION_TEST_MODE 0x1d1 /* audio -- saa7133 + saa7135 only */ #define SAA7135_DSP_RWSTATE 0x580 diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 35e5e85f669..d395403afe5 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -1666,6 +1666,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_QUERYCAP: { struct v4l2_capability *cap = arg; + unsigned int tuner_type = dev->tuner_type; memset(cap,0,sizeof(*cap)); strcpy(cap->driver, "saa7134"); @@ -1677,9 +1678,13 @@ static int video_do_ioctl(struct inode *inode, struct file *file, V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VBI_CAPTURE | - V4L2_CAP_TUNER | V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING; + V4L2_CAP_STREAMING | + V4L2_CAP_TUNER; + + if ((tuner_type == TUNER_ABSENT) || (tuner_type == UNSET)) + cap->capabilities &= ~V4L2_CAP_TUNER; + return 0; } diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 69a2cebe886..ad8e89d6bf5 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -192,6 +192,8 @@ struct saa7134_format { #define SAA7134_BOARD_PHILIPS_EUROPA 69 #define SAA7134_BOARD_VIDEOMATE_DVBT_300 70 #define SAA7134_BOARD_VIDEOMATE_DVBT_200 71 +#define SAA7134_BOARD_RTD_VFG7350 72 +#define SAA7134_BOARD_RTD_VFG7330 73 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From e222f83406f987c661b6da2d3fb4fc8ae8b5c660 Mon Sep 17 00:00:00 2001 From: "Hans J. Koch" Date: Tue, 8 Nov 2005 21:36:35 -0800 Subject: [PATCH] v4l: 664: improved coding style for timer settings - Improved coding style for timer settings Signed-off-by: Hans J. Koch Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa6588.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index 72b70eb5da1..31a9797bd97 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -328,7 +328,7 @@ static void saa6588_work(void *data) struct saa6588 *s = (struct saa6588 *)data; saa6588_i2c_poll(s); - mod_timer(&s->timer, jiffies + HZ / 50); /* 20 msec */ + mod_timer(&s->timer, jiffies + msecs_to_jiffies(20)); } static int saa6588_configure(struct saa6588 *s) -- cgit v1.2.3 From 17a05ef33a3c9489f659c4e40f8bfafd834e0cb9 Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:36:36 -0800 Subject: [PATCH] v4l: 665: fix for problem with audio register setup via dsp access - Fix for problem with audio register setup via DSP access Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-core.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index e5e36f3c625..109c815c5e6 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -646,14 +646,6 @@ static int saa7134_hwinit1(struct saa7134_dev *dev) saa7134_ts_init1(dev); saa7134_input_init1(dev); - switch (dev->pci->device) { - case PCI_DEVICE_ID_PHILIPS_SAA7134: - case PCI_DEVICE_ID_PHILIPS_SAA7133: - case PCI_DEVICE_ID_PHILIPS_SAA7135: - saa7134_oss_init1(dev); - break; - } - /* RAM FIFO config */ saa_writel(SAA7134_FIFO_SIZE, 0x08070503); saa_writel(SAA7134_THRESHOULD,0x02020202); @@ -668,6 +660,21 @@ static int saa7134_hwinit1(struct saa7134_dev *dev) SAA7134_MAIN_CTRL_ESFE | SAA7134_MAIN_CTRL_EBDAC); + /* + * Initialize OSS _after_ enabling audio clock PLL and audio processing. + * OSS initialization writes to registers via the audio DSP; these + * writes will fail unless the audio clock has been started. At worst, + * audio will not work. + */ + + switch (dev->pci->device) { + case PCI_DEVICE_ID_PHILIPS_SAA7134: + case PCI_DEVICE_ID_PHILIPS_SAA7133: + case PCI_DEVICE_ID_PHILIPS_SAA7135: + saa7134_oss_init1(dev); + break; + } + /* enable peripheral devices */ saa_writeb(SAA7134_SPECIAL_MODE, 0x01); -- cgit v1.2.3 From 9f95a0bf8594f59c708492d5ab6ea9a72621f0dd Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:36:37 -0800 Subject: [PATCH] v4l: 667: remove some if 0 which doesn t have any sense - Remove some #if 0 which doesn't have any sense Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/cx88-video.c | 2 +- drivers/media/video/saa7134/saa7134-video.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index a29c12754ef..4c99fc39bb2 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1256,9 +1256,9 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, { int err; + dprintk( 1, "CORE IOCTL: 0x%x\n", cmd ); if (video_debug > 1) cx88_print_ioctl(core->name,cmd); - dprintk( 1, "CORE IOCTL: 0x%x\n", cmd ); switch (cmd) { /* ---------- tv norms ---------- */ diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index d395403afe5..cd1f70fffde 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -1798,9 +1798,9 @@ static int video_do_ioctl(struct inode *inode, struct file *file, crop->c.height = b->top - crop->c.top + b->height; if (crop->c.left < b->left) - crop->c.top = b->left; + crop->c.left = b->left; if (crop->c.left > b->left + b->width) - crop->c.top = b->left + b->width; + crop->c.left = b->left + b->width; if (crop->c.width > b->left - crop->c.left + b->width) crop->c.width = b->left - crop->c.left + b->width; -- cgit v1.2.3 From 699a40690b5facb3aa1256304cd6b97691eb5fdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Miguel=20Garc=EDa?= Date: Tue, 8 Nov 2005 21:36:38 -0800 Subject: [PATCH] v4l: 669: added prolink pixelview pv bt878p rev 2e compatibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added Prolink Pixelview PV-BT878P+ (Rev.2E) compatibility Signed-off-by: Luis Miguel García Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bttv-cards.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index e94bffbedfd..5672d0ef2bf 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -2431,6 +2431,20 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, .tuner_addr = ADDR_UNSET, .has_remote = 1, +},{ + .name = "Prolink Pixelview PV-BT878P+ (Rev.2E)", + .video_inputs = 5, + .audio_inputs = 1, + .tuner = 0, + .svhs = 3, + .gpiomask = 0x01fe00, + .muxsel = { 2,3,1,1,-1 }, + .digital_mode = DIGITAL_MODE_CAMERA, + .audiomux = { 0x00400, 0x10400, 0x04400, 0x80000, 0x12400, 0x46000 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_LG_PAL_FM, + .has_remote = 1, }}; static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); -- cgit v1.2.3 From caa812e4a5d77703f4839b5d25139aa05615ddb3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:36:39 -0800 Subject: [PATCH] v4l: 670: cardlist update - Cardlist update. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.bttv | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index 89460a5babf..5deb052f307 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -136,3 +136,4 @@ card=134 - Adlink RTV24 card=135 - DViCO FusionHDTV 5 Lite card=136 - Acorp Y878F card=137 - Conceptronic CTVFMi v2 +card=138 - Prolink Pixelview PV-BT878P+ (Rev.2E) -- cgit v1.2.3 From 46a3a575bcc6a82b8538dd7a02fef634853ad31e Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:36:39 -0800 Subject: [PATCH] v4l: 672: fix build for 2.6.14 - Fix build for 2.6.14 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/ir-kbd-i2c.c | 2 -- drivers/media/video/saa6588.c | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 9703d3d351f..225fee93cfd 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -37,9 +37,7 @@ #include #include #include - #include - #include /* Mark Phalan */ diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index 31a9797bd97..5252a4ca3fd 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -434,9 +434,9 @@ static int saa6588_probe(struct i2c_adapter *adap) return i2c_probe(adap, &addr_data, saa6588_attach); #else switch (adap->id) { - case I2C_ALGO_BIT | I2C_HW_B_BT848: - case I2C_ALGO_BIT | I2C_HW_B_RIVA: - case I2C_ALGO_SAA7134: + case I2C_HW_B_BT848: + case I2C_HW_B_RIVA: + case I2C_HW_SAA7134: return i2c_probe(adap, &addr_data, saa6588_attach); break; } -- cgit v1.2.3 From cd4665c5dcf9916dc2f71d30c7e7830ee7cbf884 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:36:40 -0800 Subject: [PATCH] v4l: 673: initial code for texas instruments tvp5150a and tvp5150am1 - Initial code for Texas Instruments TVP5150A and TVP5150AM1 Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tvp5150.c | 378 ++++++++++++++++++++++++++++++++++++++ drivers/media/video/tvp5150_reg.h | 173 +++++++++++++++++ 2 files changed, 551 insertions(+) create mode 100644 drivers/media/video/tvp5150.c create mode 100644 drivers/media/video/tvp5150_reg.h diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c new file mode 100644 index 00000000000..e575877f826 --- /dev/null +++ b/drivers/media/video/tvp5150.c @@ -0,0 +1,378 @@ +/* + * tvp5150 - Texas Instruments TVP5150A(M) video decoder driver + * + * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br) + * This code is placed under the terms of the GNU General Public License + */ + +#include +#include +#include +#include + +#include "tvp5150_reg.h" + +MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver");/* standard i2c insmod options */ +MODULE_AUTHOR("Mauro Carvalho Chehab"); +MODULE_LICENSE("GPL"); + +static unsigned short normal_i2c[] = { + 0xb8 >>1, + 0xba >>1, + I2C_CLIENT_END +}; + +I2C_CLIENT_INSMOD; + +static int debug = 0; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level (0-1)"); + +#define dprintk(num, format, args...) \ + do { \ + if (debug >= num) \ + printk(format , ##args); \ + } while (0) + +struct tvp5150 { + struct i2c_client *client; +}; + +static inline int tvp5150_read(struct i2c_client *c,unsigned char addr) +{ + unsigned char buffer[1]; + int rc; +/* struct tvp5150 *core = i2c_get_clientdata(c); */ + + buffer[0] = addr; + if (1 != (rc = i2c_master_send(c, buffer, 1))) + dprintk(0,"i2c i/o error: rc == %d (should be 1)\n", rc); + + msleep(10); + + if (1 != (rc = i2c_master_recv(c, buffer, 1))) + dprintk(0,"i2c i/o error: rc == %d (should be 1)\n", rc); + + return (buffer[0]); +} + +static inline void tvp5150_write(struct i2c_client *c,unsigned char addr, unsigned char value) +{ + unsigned char buffer[2]; + int rc; +/* struct tvp5150 *core = i2c_get_clientdata(c); */ + + buffer[0] = addr; + buffer[2] = addr; + if (2 != (rc = i2c_master_send(c, buffer, 2))) + dprintk(0,"i2c i/o error: rc == %d (should be 2)\n", rc); +} + +static void dump_reg (struct i2c_client *c) +{ + dprintk (2, "tvp5150: Video input source selection #1 = 0x%02x\n", tvp5150_read(c,TVP5150_VD_IN_SRC_SEL_1)); + dprintk (2, "tvp5150: Analog channel controls = 0x%02x\n", tvp5150_read(c,TVP5150_ANAL_CHL_CTL)); + dprintk (2, "tvp5150: Operation mode controls = 0x%02x\n", tvp5150_read(c,TVP5150_OP_MODE_CTL)); + dprintk (2, "tvp5150: Miscellaneous controls = 0x%02x\n", tvp5150_read(c,TVP5150_MISC_CTL)); + dprintk (2, "tvp5150: Autoswitch mask: TVP5150A / TVP5150AM = 0x%02x\n", tvp5150_read(c,TVP5150_AUTOSW_MSK)); + dprintk (2, "tvp5150: Color killer threshold control = 0x%02x\n", tvp5150_read(c,TVP5150_COLOR_KIL_THSH_CTL)); + dprintk (2, "tvp5150: Luminance processing control #1 = 0x%02x\n", tvp5150_read(c,TVP5150_LUMA_PROC_CTL_1)); + dprintk (2, "tvp5150: Luminance processing control #2 = 0x%02x\n", tvp5150_read(c,TVP5150_LUMA_PROC_CTL_2)); + dprintk (2, "tvp5150: Brightness control = 0x%02x\n", tvp5150_read(c,TVP5150_BRIGHT_CTL)); + dprintk (2, "tvp5150: Color saturation control = 0x%02x\n", tvp5150_read(c,TVP5150_SATURATION_CTL)); + dprintk (2, "tvp5150: Hue control = 0x%02x\n", tvp5150_read(c,TVP5150_HUE_CTL)); + dprintk (2, "tvp5150: Contrast control = 0x%02x\n", tvp5150_read(c,TVP5150_CONTRAST_CTL)); + dprintk (2, "tvp5150: Outputs and data rates select = 0x%02x\n", tvp5150_read(c,TVP5150_DATA_RATE_SEL)); + dprintk (2, "tvp5150: Luminance processing control #3 = 0x%02x\n", tvp5150_read(c,TVP5150_LUMA_PROC_CTL_3)); + dprintk (2, "tvp5150: Configuration shared pins = 0x%02x\n", tvp5150_read(c,TVP5150_CONF_SHARED_PIN)); + dprintk (2, "tvp5150: Active video cropping start MSB = 0x%02x\n", tvp5150_read(c,TVP5150_ACT_VD_CROP_ST_MSB)); + dprintk (2, "tvp5150: Active video cropping start LSB = 0x%02x\n", tvp5150_read(c,TVP5150_ACT_VD_CROP_ST_LSB)); + dprintk (2, "tvp5150: Active video cropping stop MSB = 0x%02x\n", tvp5150_read(c,TVP5150_ACT_VD_CROP_STP_MSB)); + dprintk (2, "tvp5150: Active video cropping stop LSB = 0x%02x\n", tvp5150_read(c,TVP5150_ACT_VD_CROP_STP_LSB)); + dprintk (2, "tvp5150: Genlock/RTC = 0x%02x\n", tvp5150_read(c,TVP5150_GENLOCK)); + dprintk (2, "tvp5150: Horizontal sync start = 0x%02x\n", tvp5150_read(c,TVP5150_HORIZ_SYNC_START)); + dprintk (2, "tvp5150: Vertical blanking start = 0x%02x\n", tvp5150_read(c,TVP5150_VERT_BLANKING_START)); + dprintk (2, "tvp5150: Vertical blanking stop = 0x%02x\n", tvp5150_read(c,TVP5150_VERT_BLANKING_STOP)); + dprintk (2, "tvp5150: Chrominance processing control #1 = 0x%02x\n", tvp5150_read(c,TVP5150_CHROMA_PROC_CTL_1)); + dprintk (2, "tvp5150: Chrominance processing control #2 = 0x%02x\n", tvp5150_read(c,TVP5150_CHROMA_PROC_CTL_2)); + dprintk (2, "tvp5150: Interrupt reset register B = 0x%02x\n", tvp5150_read(c,TVP5150_INT_RESET_REG_B)); + dprintk (2, "tvp5150: Interrupt enable register B = 0x%02x\n", tvp5150_read(c,TVP5150_INT_ENABLE_REG_B)); + dprintk (2, "tvp5150: Interrupt configuration register B = 0x%02x\n", tvp5150_read(c,TVP5150_INTT_CONFIG_REG_B)); + dprintk (2, "tvp5150: Video standard = 0x%02x\n", tvp5150_read(c,TVP5150_VIDEO_STD)); + dprintk (2, "tvp5150: Cb gain factor = 0x%02x\n", tvp5150_read(c,TVP5150_CB_GAIN_FACT)); + dprintk (2, "tvp5150: Cr gain factor = 0x%02x\n", tvp5150_read(c,TVP5150_CR_GAIN_FACTOR)); + dprintk (2, "tvp5150: Macrovision on counter = 0x%02x\n", tvp5150_read(c,TVP5150_MACROVISION_ON_CTR)); + dprintk (2, "tvp5150: Macrovision off counter = 0x%02x\n", tvp5150_read(c,TVP5150_MACROVISION_OFF_CTR)); + dprintk (2, "tvp5150: revision select (TVP5150AM1 only) = 0x%02x\n", tvp5150_read(c,TVP5150_REV_SELECT)); + dprintk (2, "tvp5150: MSB of device ID = 0x%02x\n", tvp5150_read(c,TVP5150_MSB_DEV_ID)); + dprintk (2, "tvp5150: LSB of device ID = 0x%02x\n", tvp5150_read(c,TVP5150_LSB_DEV_ID)); + dprintk (2, "tvp5150: ROM major version = 0x%02x\n", tvp5150_read(c,TVP5150_ROM_MAJOR_VER)); + dprintk (2, "tvp5150: ROM minor version = 0x%02x\n", tvp5150_read(c,TVP5150_ROM_MINOR_VER)); + dprintk (2, "tvp5150: Vertical line count MSB = 0x%02x\n", tvp5150_read(c,TVP5150_VERT_LN_COUNT_MSB)); + dprintk (2, "tvp5150: Vertical line count LSB = 0x%02x\n", tvp5150_read(c,TVP5150_VERT_LN_COUNT_LSB)); + dprintk (2, "tvp5150: Interrupt status register B = 0x%02x\n", tvp5150_read(c,TVP5150_INT_STATUS_REG_B)); + dprintk (2, "tvp5150: Interrupt active register B = 0x%02x\n", tvp5150_read(c,TVP5150_INT_ACTIVE_REG_B)); + dprintk (2, "tvp5150: Status register #1 = 0x%02x\n", tvp5150_read(c,TVP5150_STATUS_REG_1)); + dprintk (2, "tvp5150: Status register #2 = 0x%02x\n", tvp5150_read(c,TVP5150_STATUS_REG_2)); + dprintk (2, "tvp5150: Status register #3 = 0x%02x\n", tvp5150_read(c,TVP5150_STATUS_REG_3)); + dprintk (2, "tvp5150: Status register #4 = 0x%02x\n", tvp5150_read(c,TVP5150_STATUS_REG_4)); + dprintk (2, "tvp5150: Status register #5 = 0x%02x\n", tvp5150_read(c,TVP5150_STATUS_REG_5)); + dprintk (2, "tvp5150: Closed caption data registers = 0x%02x\n", tvp5150_read(c,TVP5150_CC_DATA_REG1)); + dprintk (2, "tvp5150: Closed caption data registers = 0x%02x\n", tvp5150_read(c,TVP5150_CC_DATA_REG2)); + dprintk (2, "tvp5150: Closed caption data registers = 0x%02x\n", tvp5150_read(c,TVP5150_CC_DATA_REG3)); + dprintk (2, "tvp5150: Closed caption data registers = 0x%02x\n", tvp5150_read(c,TVP5150_CC_DATA_REG4)); + dprintk (2, "tvp5150: WSS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_WSS_DATA_REG1)); + dprintk (2, "tvp5150: WSS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_WSS_DATA_REG2)); + dprintk (2, "tvp5150: WSS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_WSS_DATA_REG3)); + dprintk (2, "tvp5150: WSS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_WSS_DATA_REG4)); + dprintk (2, "tvp5150: WSS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_WSS_DATA_REG5)); + dprintk (2, "tvp5150: WSS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_WSS_DATA_REG6)); + dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG1)); + dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG2)); + dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG3)); + dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG4)); + dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG5)); + dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG6)); + dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG7)); + dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG8)); + dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG9)); + dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG10)); + dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG11)); + dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG12)); + dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG13)); + dprintk (2, "tvp5150: VITC data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VITC_DATA_REG1)); + dprintk (2, "tvp5150: VITC data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VITC_DATA_REG2)); + dprintk (2, "tvp5150: VITC data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VITC_DATA_REG3)); + dprintk (2, "tvp5150: VITC data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VITC_DATA_REG4)); + dprintk (2, "tvp5150: VITC data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VITC_DATA_REG5)); + dprintk (2, "tvp5150: VITC data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VITC_DATA_REG6)); + dprintk (2, "tvp5150: VITC data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VITC_DATA_REG7)); + dprintk (2, "tvp5150: VITC data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VITC_DATA_REG8)); + dprintk (2, "tvp5150: VITC data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VITC_DATA_REG9)); + dprintk (2, "tvp5150: VBI FIFO read data = 0x%02x\n", tvp5150_read(c,TVP5150_VBI_FIFO_READ_DATA)); + dprintk (2, "tvp5150: Teletext filter 1 = 0x%02x\n", tvp5150_read(c,TVP5150_TELETEXT_FIL_1_1)); + dprintk (2, "tvp5150: Teletext filter 1 = 0x%02x\n", tvp5150_read(c,TVP5150_TELETEXT_FIL_1_2)); + dprintk (2, "tvp5150: Teletext filter 1 = 0x%02x\n", tvp5150_read(c,TVP5150_TELETEXT_FIL_1_3)); + dprintk (2, "tvp5150: Teletext filter 1 = 0x%02x\n", tvp5150_read(c,TVP5150_TELETEXT_FIL_1_4)); + dprintk (2, "tvp5150: Teletext filter 1 = 0x%02x\n", tvp5150_read(c,TVP5150_TELETEXT_FIL_1_5)); + dprintk (2, "tvp5150: Teletext filter 2 = 0x%02x\n", tvp5150_read(c,TVP5150_TELETEXT_FIL_2_1)); + dprintk (2, "tvp5150: Teletext filter 2 = 0x%02x\n", tvp5150_read(c,TVP5150_TELETEXT_FIL_2_2)); + dprintk (2, "tvp5150: Teletext filter 2 = 0x%02x\n", tvp5150_read(c,TVP5150_TELETEXT_FIL_2_3)); + dprintk (2, "tvp5150: Teletext filter 2 = 0x%02x\n", tvp5150_read(c,TVP5150_TELETEXT_FIL_2_4)); + dprintk (2, "tvp5150: Teletext filter 2 = 0x%02x\n", tvp5150_read(c,TVP5150_TELETEXT_FIL_2_5)); + dprintk (2, "tvp5150: Teletext filter enable = 0x%02x\n", tvp5150_read(c,TVP5150_TELETEXT_FIL_ENA)); + dprintk (2, "tvp5150: Interrupt status register A = 0x%02x\n", tvp5150_read(c,TVP5150_INT_STATUS_REG_A)); + dprintk (2, "tvp5150: Interrupt enable register A = 0x%02x\n", tvp5150_read(c,TVP5150_INT_ENABLE_REG_A)); + dprintk (2, "tvp5150: Interrupt configuration = 0x%02x\n", tvp5150_read(c,TVP5150_INT_CONF)); + dprintk (2, "tvp5150: VDP configuration RAM data = 0x%02x\n", tvp5150_read(c,TVP5150_VDP_CONF_RAM_DATA)); + dprintk (2, "tvp5150: Configuration RAM address low byte = 0x%02x\n", tvp5150_read(c,TVP5150_CONF_RAM_ADDR_LOW)); + dprintk (2, "tvp5150: Configuration RAM address high byte = 0x%02x\n", tvp5150_read(c,TVP5150_CONF_RAM_ADDR_HIGH)); + dprintk (2, "tvp5150: VDP status register = 0x%02x\n", tvp5150_read(c,TVP5150_VDP_STATUS_REG)); + dprintk (2, "tvp5150: FIFO word count = 0x%02x\n", tvp5150_read(c,TVP5150_FIFO_WORD_COUNT)); + dprintk (2, "tvp5150: FIFO interrupt threshold = 0x%02x\n", tvp5150_read(c,TVP5150_FIFO_INT_THRESHOLD)); + dprintk (2, "tvp5150: FIFO reset = 0x%02x\n", tvp5150_read(c,TVP5150_FIFO_RESET)); + dprintk (2, "tvp5150: Line number interrupt = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_NUMBER_INT)); + dprintk (2, "tvp5150: Pixel alignment register low byte = 0x%02x\n", tvp5150_read(c,TVP5150_PIX_ALIGN_REG_LOW)); + dprintk (2, "tvp5150: Pixel alignment register high byte = 0x%02x\n", tvp5150_read(c,TVP5150_PIX_ALIGN_REG_HIGH)); + dprintk (2, "tvp5150: FIFO output control = 0x%02x\n", tvp5150_read(c,TVP5150_FIFO_OUT_CTRL)); + dprintk (2, "tvp5150: Full field enable 1 = 0x%02x\n", tvp5150_read(c,TVP5150_FULL_FIELD_ENA_1)); + dprintk (2, "tvp5150: Full field enable 2 = 0x%02x\n", tvp5150_read(c,TVP5150_FULL_FIELD_ENA_2)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_1)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_2)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_3)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_4)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_5)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_6)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_7)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_8)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_9)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_10)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_11)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_12)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_13)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_14)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_15)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_16)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_17)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_18)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_19)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_20)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_21)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_22)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_23)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_24)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_25)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_27)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_28)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_29)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_30)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_31)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_32)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_33)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_34)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_35)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_36)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_37)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_38)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_39)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_40)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_41)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_42)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_43)); + dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_44)); + dprintk (2, "tvp5150: Full field mode register = 0x%02x\n", tvp5150_read(c,TVP5150_FULL_FIELD_MODE_REG)); +} + +/**************************************************************************** + Basic functions + ****************************************************************************/ +enum tvp5150_input { + TVP5150_ANALOG_CH0 = 0, + TVP5150_SVIDEO = 1, + TVP5150_ANALOG_CH1 = 2, + TVP5150_BLACK_SCREEN = 8 +}; + +static inline void tvp5150_selmux(struct i2c_client *c, enum tvp5150_input input) +{ + tvp5150_write(c,TVP5150_VD_IN_SRC_SEL_1,input); +}; + +static inline void tvp5150_reset(struct i2c_client *c) +{ + /* Automatic offset and AGC enabled*/ + tvp5150_write(c,TVP5150_ANAL_CHL_CTL,0x15); + + /* Normal Operation */ + tvp5150_write(c,TVP5150_OP_MODE_CTL,0x00); + + /* Activate YCrCb output 0x9 or 0xd ? */ + tvp5150_write(c,TVP5150_MISC_CTL,0x09); + + /* Activates video std autodetection for PAL/M and PAL/N */ + tvp5150_write(c,TVP5150_AUTOSW_MSK,0xf0); + + /* Default format: 0x47, 4:2:2: 0x40 */ + tvp5150_write(c,TVP5150_DATA_RATE_SEL,0x47); + + tvp5150_selmux(c,TVP5150_ANALOG_CH0); +}; + + +/**************************************************************************** + I2C Client & Driver + ****************************************************************************/ +static struct i2c_driver driver; + +static struct i2c_client client_template = +{ + .name = "(unset)", + .flags = I2C_CLIENT_ALLOW_USE, + .driver = &driver, +}; + +static int +tvp5150_detect_client (struct i2c_adapter *adapter, + int address, + int kind) +{ + struct i2c_client *client; + struct tvp5150 *core; + int rv; + + dprintk(1, + KERN_INFO + "tvp5150.c: detecting tvp5150 client on address 0x%x\n", + address << 1); + + client_template.adapter = adapter; + client_template.addr = address; + + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality + (adapter, + I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) + return 0; + + client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (client == 0) + return -ENOMEM; + memcpy(client,&client_template,sizeof(struct i2c_client)); + + core = kmalloc(sizeof(struct tvp5150), GFP_KERNEL); + if (core == 0) { + kfree(client); + return -ENOMEM; + } + memset(core, 0, sizeof(struct tvp5150)); + i2c_set_clientdata(client, core); + + rv = i2c_attach_client(client); + + if (rv) { + kfree(client); + kfree(core); + return rv; + } + + tvp5150_reset(client); + dump_reg (client); + + return 0; +} + +static int +tvp5150_attach_adapter (struct i2c_adapter *adapter) +{ + dprintk(1, + KERN_INFO + "tvp5150.c: starting probe for adapter %s (0x%x)\n", + adapter->name, adapter->id); + return i2c_probe(adapter, &addr_data, &tvp5150_detect_client); +} + +static int +tvp5150_detach_client (struct i2c_client *client) +{ + struct tvp5150 *decoder = i2c_get_clientdata(client); + int err; + + err = i2c_detach_client(client); + if (err) { + return err; + } + + kfree(decoder); + kfree(client); + + return 0; +} + +/* ----------------------------------------------------------------------- */ + +static struct i2c_driver driver = { + .owner = THIS_MODULE, + .name = "tvp5150", + + /* FIXME */ + .id = I2C_DRIVERID_SAA7110, + .flags = I2C_DF_NOTIFY, + + .attach_adapter = tvp5150_attach_adapter, + .detach_client = tvp5150_detach_client, +}; + +static int __init +tvp5150_init (void) +{ + return i2c_add_driver(&driver); +} + +static void __exit +tvp5150_exit (void) +{ + i2c_del_driver(&driver); +} + +module_init(tvp5150_init); +module_exit(tvp5150_exit); diff --git a/drivers/media/video/tvp5150_reg.h b/drivers/media/video/tvp5150_reg.h new file mode 100644 index 00000000000..cd45c1ded78 --- /dev/null +++ b/drivers/media/video/tvp5150_reg.h @@ -0,0 +1,173 @@ +#define TVP5150_VD_IN_SRC_SEL_1 0x00 /* Video input source selection #1 */ +#define TVP5150_ANAL_CHL_CTL 0x01 /* Analog channel controls */ +#define TVP5150_OP_MODE_CTL 0x02 /* Operation mode controls */ +#define TVP5150_MISC_CTL 0x03 /* Miscellaneous controls */ +#define TVP5150_AUTOSW_MSK 0x04 /* Autoswitch mask: TVP5150A / TVP5150AM */ + +/* Reserved 05h */ + +#define TVP5150_COLOR_KIL_THSH_CTL 0x06 /* Color killer threshold control */ +#define TVP5150_LUMA_PROC_CTL_1 0x07 /* Luminance processing control #1 */ +#define TVP5150_LUMA_PROC_CTL_2 0x08 /* Luminance processing control #2 */ +#define TVP5150_BRIGHT_CTL 0x09 /* Brightness control */ +#define TVP5150_SATURATION_CTL 0x0a /* Color saturation control */ +#define TVP5150_HUE_CTL 0x0b /* Hue control */ +#define TVP5150_CONTRAST_CTL 0x0c /* Contrast control */ +#define TVP5150_DATA_RATE_SEL 0x0d /* Outputs and data rates select */ +#define TVP5150_LUMA_PROC_CTL_3 0x0e /* Luminance processing control #3 */ +#define TVP5150_CONF_SHARED_PIN 0x0f /* Configuration shared pins */ + +/* Reserved 10h */ + +#define TVP5150_ACT_VD_CROP_ST_MSB 0x11 /* Active video cropping start MSB */ +#define TVP5150_ACT_VD_CROP_ST_LSB 0x12 /* Active video cropping start LSB */ +#define TVP5150_ACT_VD_CROP_STP_MSB 0x13 /* Active video cropping stop MSB */ +#define TVP5150_ACT_VD_CROP_STP_LSB 0x14 /* Active video cropping stop LSB */ +#define TVP5150_GENLOCK 0x15 /* Genlock/RTC */ +#define TVP5150_HORIZ_SYNC_START 0x16 /* Horizontal sync start */ + +/* Reserved 17h */ + +#define TVP5150_VERT_BLANKING_START 0x18 /* Vertical blanking start */ +#define TVP5150_VERT_BLANKING_STOP 0x19 /* Vertical blanking stop */ +#define TVP5150_CHROMA_PROC_CTL_1 0x1a /* Chrominance processing control #1 */ +#define TVP5150_CHROMA_PROC_CTL_2 0x1b /* Chrominance processing control #2 */ +#define TVP5150_INT_RESET_REG_B 0x1c /* Interrupt reset register B */ +#define TVP5150_INT_ENABLE_REG_B 0x1d /* Interrupt enable register B */ +#define TVP5150_INTT_CONFIG_REG_B 0x1e /* Interrupt configuration register B */ + +/* Reserved 1Fh-27h */ + +#define TVP5150_VIDEO_STD 0x28 /* Video standard */ + +/* Reserved 29h-2bh */ + +#define TVP5150_CB_GAIN_FACT 0x2c /* Cb gain factor */ +#define TVP5150_CR_GAIN_FACTOR 0x2d /* Cr gain factor */ +#define TVP5150_MACROVISION_ON_CTR 0x2e /* Macrovision on counter */ +#define TVP5150_MACROVISION_OFF_CTR 0x2f /* Macrovision off counter */ +#define TVP5150_REV_SELECT 0x30 /* revision select (TVP5150AM1 only) */ + +/* Reserved 31h-7Fh */ + +#define TVP5150_MSB_DEV_ID 0x80 /* MSB of device ID */ +#define TVP5150_LSB_DEV_ID 0x81 /* LSB of device ID */ +#define TVP5150_ROM_MAJOR_VER 0x82 /* ROM major version */ +#define TVP5150_ROM_MINOR_VER 0x83 /* ROM minor version */ +#define TVP5150_VERT_LN_COUNT_MSB 0x84 /* Vertical line count MSB */ +#define TVP5150_VERT_LN_COUNT_LSB 0x85 /* Vertical line count LSB */ +#define TVP5150_INT_STATUS_REG_B 0x86 /* Interrupt status register B */ +#define TVP5150_INT_ACTIVE_REG_B 0x87 /* Interrupt active register B */ +#define TVP5150_STATUS_REG_1 0x88 /* Status register #1 */ +#define TVP5150_STATUS_REG_2 0x89 /* Status register #2 */ +#define TVP5150_STATUS_REG_3 0x8a /* Status register #3 */ +#define TVP5150_STATUS_REG_4 0x8b /* Status register #4 */ +#define TVP5150_STATUS_REG_5 0x8c /* Status register #5 */ +/* Reserved 8Dh-8Fh */ +#define TVP5150_CC_DATA_REG1 0x90 /* Closed caption data registers */ +#define TVP5150_CC_DATA_REG2 0x91 /* Closed caption data registers */ +#define TVP5150_CC_DATA_REG3 0x92 /* Closed caption data registers */ +#define TVP5150_CC_DATA_REG4 0x93 /* Closed caption data registers */ +#define TVP5150_WSS_DATA_REG1 0X94 /* WSS data registers */ +#define TVP5150_WSS_DATA_REG2 0X95 /* WSS data registers */ +#define TVP5150_WSS_DATA_REG3 0X96 /* WSS data registers */ +#define TVP5150_WSS_DATA_REG4 0X97 /* WSS data registers */ +#define TVP5150_WSS_DATA_REG5 0X98 /* WSS data registers */ +#define TVP5150_WSS_DATA_REG6 0X99 /* WSS data registers */ +#define TVP5150_VPS_DATA_REG1 0x9a /* VPS data registers */ +#define TVP5150_VPS_DATA_REG2 0x9b /* VPS data registers */ +#define TVP5150_VPS_DATA_REG3 0x9c /* VPS data registers */ +#define TVP5150_VPS_DATA_REG4 0x9d /* VPS data registers */ +#define TVP5150_VPS_DATA_REG5 0x9e /* VPS data registers */ +#define TVP5150_VPS_DATA_REG6 0x9f /* VPS data registers */ +#define TVP5150_VPS_DATA_REG7 0xa0 /* VPS data registers */ +#define TVP5150_VPS_DATA_REG8 0xa1 /* VPS data registers */ +#define TVP5150_VPS_DATA_REG9 0xa2 /* VPS data registers */ +#define TVP5150_VPS_DATA_REG10 0xa3 /* VPS data registers */ +#define TVP5150_VPS_DATA_REG11 0xa4 /* VPS data registers */ +#define TVP5150_VPS_DATA_REG12 0xa5 /* VPS data registers */ +#define TVP5150_VPS_DATA_REG13 0xa6 /* VPS data registers */ +#define TVP5150_VITC_DATA_REG1 0xa7 /* VITC data registers */ +#define TVP5150_VITC_DATA_REG2 0xa8 /* VITC data registers */ +#define TVP5150_VITC_DATA_REG3 0xa9 /* VITC data registers */ +#define TVP5150_VITC_DATA_REG4 0xaa /* VITC data registers */ +#define TVP5150_VITC_DATA_REG5 0xab /* VITC data registers */ +#define TVP5150_VITC_DATA_REG6 0xac /* VITC data registers */ +#define TVP5150_VITC_DATA_REG7 0xad /* VITC data registers */ +#define TVP5150_VITC_DATA_REG8 0xae /* VITC data registers */ +#define TVP5150_VITC_DATA_REG9 0xaf /* VITC data registers */ +#define TVP5150_VBI_FIFO_READ_DATA 0xb0 /* VBI FIFO read data */ +#define TVP5150_TELETEXT_FIL_1_1 0xb1 /* Teletext filter 1 */ +#define TVP5150_TELETEXT_FIL_1_2 0xb2 /* Teletext filter 1 */ +#define TVP5150_TELETEXT_FIL_1_3 0xb3 /* Teletext filter 1 */ +#define TVP5150_TELETEXT_FIL_1_4 0xb4 /* Teletext filter 1 */ +#define TVP5150_TELETEXT_FIL_1_5 0xb5 /* Teletext filter 1 */ +#define TVP5150_TELETEXT_FIL_2_1 0xb6 /* Teletext filter 2 */ +#define TVP5150_TELETEXT_FIL_2_2 0xb7 /* Teletext filter 2 */ +#define TVP5150_TELETEXT_FIL_2_3 0xb8 /* Teletext filter 2 */ +#define TVP5150_TELETEXT_FIL_2_4 0xb9 /* Teletext filter 2 */ +#define TVP5150_TELETEXT_FIL_2_5 0xba /* Teletext filter 2 */ +#define TVP5150_TELETEXT_FIL_ENA 0xbb /* Teletext filter enable */ +/* Reserved BCh-BFh */ +#define TVP5150_INT_STATUS_REG_A 0xc0 /* Interrupt status register A */ +#define TVP5150_INT_ENABLE_REG_A 0xc1 /* Interrupt enable register A */ +#define TVP5150_INT_CONF 0xc2 /* Interrupt configuration */ +#define TVP5150_VDP_CONF_RAM_DATA 0xc3 /* VDP configuration RAM data */ +#define TVP5150_CONF_RAM_ADDR_LOW 0xc4 /* Configuration RAM address low byte */ +#define TVP5150_CONF_RAM_ADDR_HIGH 0xc5 /* Configuration RAM address high byte */ +#define TVP5150_VDP_STATUS_REG 0xc6 /* VDP status register */ +#define TVP5150_FIFO_WORD_COUNT 0xc7 /* FIFO word count */ +#define TVP5150_FIFO_INT_THRESHOLD 0xc8 /* FIFO interrupt threshold */ +#define TVP5150_FIFO_RESET 0xc9 /* FIFO reset */ +#define TVP5150_LINE_NUMBER_INT 0xca /* Line number interrupt */ +#define TVP5150_PIX_ALIGN_REG_LOW 0xcb /* Pixel alignment register low byte */ +#define TVP5150_PIX_ALIGN_REG_HIGH 0xcc /* Pixel alignment register high byte */ +#define TVP5150_FIFO_OUT_CTRL 0xcd /* FIFO output control */ +/* Reserved CEh */ +#define TVP5150_FULL_FIELD_ENA_1 0xcf /* Full field enable 1 */ +#define TVP5150_FULL_FIELD_ENA_2 0xd0 /* Full field enable 2 */ +#define TVP5150_LINE_MODE_REG_1 0xd1 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_2 0xd2 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_3 0xd3 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_4 0xd4 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_5 0xd5 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_6 0xd6 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_7 0xd7 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_8 0xd8 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_9 0xd9 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_10 0xda /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_11 0xdb /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_12 0xdc /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_13 0xdd /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_14 0xde /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_15 0xdf /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_16 0xe0 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_17 0xe1 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_18 0xe2 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_19 0xe3 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_20 0xe4 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_21 0xe5 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_22 0xe6 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_23 0xe7 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_24 0xe8 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_25 0xe9 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_27 0xea /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_28 0xeb /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_29 0xec /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_30 0xed /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_31 0xee /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_32 0xef /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_33 0xf0 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_34 0xf1 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_35 0xf2 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_36 0xf3 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_37 0xf4 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_38 0xf5 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_39 0xf6 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_40 0xf7 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_41 0xf8 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_42 0xf9 /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_43 0xfa /* Line mode registers */ +#define TVP5150_LINE_MODE_REG_44 0xfb /* Line mode registers */ +#define TVP5150_FULL_FIELD_MODE_REG 0xfc /* Full field mode register */ +/* Reserved FDh-FFh */ -- cgit v1.2.3 From 35f8d4d623953b5d868d9735a4c10e57dca6dc97 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:36:41 -0800 Subject: [PATCH] v4l: 674: move some if kernel version into compat.h - Move some #if kernel version into compat.h Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/cx88-dvb.c | 1 - drivers/media/video/saa7134/saa7134-dvb.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index ecb12c80b38..82e686135f6 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -29,7 +29,6 @@ #include #include - #include "cx88.h" #include "dvb-pll.h" diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index f8e01030fbc..87641f7e432 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -29,7 +29,6 @@ #include #include - #include "saa7134-reg.h" #include "saa7134.h" -- cgit v1.2.3 From 84486d53b7fab2cf939acd378959fc4896d3bb68 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:36:41 -0800 Subject: [PATCH] v4l: 675: tvp5150 included on makefile - Tvp5150 included on makefile. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tvp5150.c | 653 ++++++++++++++++++++++++++++++------------ 1 file changed, 472 insertions(+), 181 deletions(-) diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index e575877f826..bd1201d7adf 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -9,16 +9,17 @@ #include #include #include +#include #include "tvp5150_reg.h" -MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver");/* standard i2c insmod options */ +MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver"); /* standard i2c insmod options */ MODULE_AUTHOR("Mauro Carvalho Chehab"); MODULE_LICENSE("GPL"); static unsigned short normal_i2c[] = { - 0xb8 >>1, - 0xba >>1, + 0xb8 >> 1, + 0xba >> 1, I2C_CLIENT_END }; @@ -36,228 +37,519 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); struct tvp5150 { struct i2c_client *client; + + int norm; + int input; + int enable; + int bright; + int contrast; + int hue; + int sat; }; -static inline int tvp5150_read(struct i2c_client *c,unsigned char addr) +static inline int tvp5150_read(struct i2c_client *c, unsigned char addr) { unsigned char buffer[1]; int rc; -/* struct tvp5150 *core = i2c_get_clientdata(c); */ buffer[0] = addr; if (1 != (rc = i2c_master_send(c, buffer, 1))) - dprintk(0,"i2c i/o error: rc == %d (should be 1)\n", rc); + dprintk(0, "i2c i/o error: rc == %d (should be 1)\n", rc); msleep(10); if (1 != (rc = i2c_master_recv(c, buffer, 1))) - dprintk(0,"i2c i/o error: rc == %d (should be 1)\n", rc); + dprintk(0, "i2c i/o error: rc == %d (should be 1)\n", rc); return (buffer[0]); } -static inline void tvp5150_write(struct i2c_client *c,unsigned char addr, unsigned char value) +static inline void tvp5150_write(struct i2c_client *c, unsigned char addr, + unsigned char value) { unsigned char buffer[2]; int rc; /* struct tvp5150 *core = i2c_get_clientdata(c); */ buffer[0] = addr; - buffer[2] = addr; + buffer[1] = value; + dprintk(1,"tvp5150: writing 0x%02x 0x%02x\n",buffer[0],buffer[1]); if (2 != (rc = i2c_master_send(c, buffer, 2))) - dprintk(0,"i2c i/o error: rc == %d (should be 2)\n", rc); + dprintk(0, "i2c i/o error: rc == %d (should be 2)\n", rc); } -static void dump_reg (struct i2c_client *c) +static void dump_reg(struct i2c_client *c) { - dprintk (2, "tvp5150: Video input source selection #1 = 0x%02x\n", tvp5150_read(c,TVP5150_VD_IN_SRC_SEL_1)); - dprintk (2, "tvp5150: Analog channel controls = 0x%02x\n", tvp5150_read(c,TVP5150_ANAL_CHL_CTL)); - dprintk (2, "tvp5150: Operation mode controls = 0x%02x\n", tvp5150_read(c,TVP5150_OP_MODE_CTL)); - dprintk (2, "tvp5150: Miscellaneous controls = 0x%02x\n", tvp5150_read(c,TVP5150_MISC_CTL)); - dprintk (2, "tvp5150: Autoswitch mask: TVP5150A / TVP5150AM = 0x%02x\n", tvp5150_read(c,TVP5150_AUTOSW_MSK)); - dprintk (2, "tvp5150: Color killer threshold control = 0x%02x\n", tvp5150_read(c,TVP5150_COLOR_KIL_THSH_CTL)); - dprintk (2, "tvp5150: Luminance processing control #1 = 0x%02x\n", tvp5150_read(c,TVP5150_LUMA_PROC_CTL_1)); - dprintk (2, "tvp5150: Luminance processing control #2 = 0x%02x\n", tvp5150_read(c,TVP5150_LUMA_PROC_CTL_2)); - dprintk (2, "tvp5150: Brightness control = 0x%02x\n", tvp5150_read(c,TVP5150_BRIGHT_CTL)); - dprintk (2, "tvp5150: Color saturation control = 0x%02x\n", tvp5150_read(c,TVP5150_SATURATION_CTL)); - dprintk (2, "tvp5150: Hue control = 0x%02x\n", tvp5150_read(c,TVP5150_HUE_CTL)); - dprintk (2, "tvp5150: Contrast control = 0x%02x\n", tvp5150_read(c,TVP5150_CONTRAST_CTL)); - dprintk (2, "tvp5150: Outputs and data rates select = 0x%02x\n", tvp5150_read(c,TVP5150_DATA_RATE_SEL)); - dprintk (2, "tvp5150: Luminance processing control #3 = 0x%02x\n", tvp5150_read(c,TVP5150_LUMA_PROC_CTL_3)); - dprintk (2, "tvp5150: Configuration shared pins = 0x%02x\n", tvp5150_read(c,TVP5150_CONF_SHARED_PIN)); - dprintk (2, "tvp5150: Active video cropping start MSB = 0x%02x\n", tvp5150_read(c,TVP5150_ACT_VD_CROP_ST_MSB)); - dprintk (2, "tvp5150: Active video cropping start LSB = 0x%02x\n", tvp5150_read(c,TVP5150_ACT_VD_CROP_ST_LSB)); - dprintk (2, "tvp5150: Active video cropping stop MSB = 0x%02x\n", tvp5150_read(c,TVP5150_ACT_VD_CROP_STP_MSB)); - dprintk (2, "tvp5150: Active video cropping stop LSB = 0x%02x\n", tvp5150_read(c,TVP5150_ACT_VD_CROP_STP_LSB)); - dprintk (2, "tvp5150: Genlock/RTC = 0x%02x\n", tvp5150_read(c,TVP5150_GENLOCK)); - dprintk (2, "tvp5150: Horizontal sync start = 0x%02x\n", tvp5150_read(c,TVP5150_HORIZ_SYNC_START)); - dprintk (2, "tvp5150: Vertical blanking start = 0x%02x\n", tvp5150_read(c,TVP5150_VERT_BLANKING_START)); - dprintk (2, "tvp5150: Vertical blanking stop = 0x%02x\n", tvp5150_read(c,TVP5150_VERT_BLANKING_STOP)); - dprintk (2, "tvp5150: Chrominance processing control #1 = 0x%02x\n", tvp5150_read(c,TVP5150_CHROMA_PROC_CTL_1)); - dprintk (2, "tvp5150: Chrominance processing control #2 = 0x%02x\n", tvp5150_read(c,TVP5150_CHROMA_PROC_CTL_2)); - dprintk (2, "tvp5150: Interrupt reset register B = 0x%02x\n", tvp5150_read(c,TVP5150_INT_RESET_REG_B)); - dprintk (2, "tvp5150: Interrupt enable register B = 0x%02x\n", tvp5150_read(c,TVP5150_INT_ENABLE_REG_B)); - dprintk (2, "tvp5150: Interrupt configuration register B = 0x%02x\n", tvp5150_read(c,TVP5150_INTT_CONFIG_REG_B)); - dprintk (2, "tvp5150: Video standard = 0x%02x\n", tvp5150_read(c,TVP5150_VIDEO_STD)); - dprintk (2, "tvp5150: Cb gain factor = 0x%02x\n", tvp5150_read(c,TVP5150_CB_GAIN_FACT)); - dprintk (2, "tvp5150: Cr gain factor = 0x%02x\n", tvp5150_read(c,TVP5150_CR_GAIN_FACTOR)); - dprintk (2, "tvp5150: Macrovision on counter = 0x%02x\n", tvp5150_read(c,TVP5150_MACROVISION_ON_CTR)); - dprintk (2, "tvp5150: Macrovision off counter = 0x%02x\n", tvp5150_read(c,TVP5150_MACROVISION_OFF_CTR)); - dprintk (2, "tvp5150: revision select (TVP5150AM1 only) = 0x%02x\n", tvp5150_read(c,TVP5150_REV_SELECT)); - dprintk (2, "tvp5150: MSB of device ID = 0x%02x\n", tvp5150_read(c,TVP5150_MSB_DEV_ID)); - dprintk (2, "tvp5150: LSB of device ID = 0x%02x\n", tvp5150_read(c,TVP5150_LSB_DEV_ID)); - dprintk (2, "tvp5150: ROM major version = 0x%02x\n", tvp5150_read(c,TVP5150_ROM_MAJOR_VER)); - dprintk (2, "tvp5150: ROM minor version = 0x%02x\n", tvp5150_read(c,TVP5150_ROM_MINOR_VER)); - dprintk (2, "tvp5150: Vertical line count MSB = 0x%02x\n", tvp5150_read(c,TVP5150_VERT_LN_COUNT_MSB)); - dprintk (2, "tvp5150: Vertical line count LSB = 0x%02x\n", tvp5150_read(c,TVP5150_VERT_LN_COUNT_LSB)); - dprintk (2, "tvp5150: Interrupt status register B = 0x%02x\n", tvp5150_read(c,TVP5150_INT_STATUS_REG_B)); - dprintk (2, "tvp5150: Interrupt active register B = 0x%02x\n", tvp5150_read(c,TVP5150_INT_ACTIVE_REG_B)); - dprintk (2, "tvp5150: Status register #1 = 0x%02x\n", tvp5150_read(c,TVP5150_STATUS_REG_1)); - dprintk (2, "tvp5150: Status register #2 = 0x%02x\n", tvp5150_read(c,TVP5150_STATUS_REG_2)); - dprintk (2, "tvp5150: Status register #3 = 0x%02x\n", tvp5150_read(c,TVP5150_STATUS_REG_3)); - dprintk (2, "tvp5150: Status register #4 = 0x%02x\n", tvp5150_read(c,TVP5150_STATUS_REG_4)); - dprintk (2, "tvp5150: Status register #5 = 0x%02x\n", tvp5150_read(c,TVP5150_STATUS_REG_5)); - dprintk (2, "tvp5150: Closed caption data registers = 0x%02x\n", tvp5150_read(c,TVP5150_CC_DATA_REG1)); - dprintk (2, "tvp5150: Closed caption data registers = 0x%02x\n", tvp5150_read(c,TVP5150_CC_DATA_REG2)); - dprintk (2, "tvp5150: Closed caption data registers = 0x%02x\n", tvp5150_read(c,TVP5150_CC_DATA_REG3)); - dprintk (2, "tvp5150: Closed caption data registers = 0x%02x\n", tvp5150_read(c,TVP5150_CC_DATA_REG4)); - dprintk (2, "tvp5150: WSS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_WSS_DATA_REG1)); - dprintk (2, "tvp5150: WSS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_WSS_DATA_REG2)); - dprintk (2, "tvp5150: WSS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_WSS_DATA_REG3)); - dprintk (2, "tvp5150: WSS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_WSS_DATA_REG4)); - dprintk (2, "tvp5150: WSS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_WSS_DATA_REG5)); - dprintk (2, "tvp5150: WSS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_WSS_DATA_REG6)); - dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG1)); - dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG2)); - dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG3)); - dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG4)); - dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG5)); - dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG6)); - dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG7)); - dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG8)); - dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG9)); - dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG10)); - dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG11)); - dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG12)); - dprintk (2, "tvp5150: VPS data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VPS_DATA_REG13)); - dprintk (2, "tvp5150: VITC data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VITC_DATA_REG1)); - dprintk (2, "tvp5150: VITC data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VITC_DATA_REG2)); - dprintk (2, "tvp5150: VITC data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VITC_DATA_REG3)); - dprintk (2, "tvp5150: VITC data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VITC_DATA_REG4)); - dprintk (2, "tvp5150: VITC data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VITC_DATA_REG5)); - dprintk (2, "tvp5150: VITC data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VITC_DATA_REG6)); - dprintk (2, "tvp5150: VITC data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VITC_DATA_REG7)); - dprintk (2, "tvp5150: VITC data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VITC_DATA_REG8)); - dprintk (2, "tvp5150: VITC data registers = 0x%02x\n", tvp5150_read(c,TVP5150_VITC_DATA_REG9)); - dprintk (2, "tvp5150: VBI FIFO read data = 0x%02x\n", tvp5150_read(c,TVP5150_VBI_FIFO_READ_DATA)); - dprintk (2, "tvp5150: Teletext filter 1 = 0x%02x\n", tvp5150_read(c,TVP5150_TELETEXT_FIL_1_1)); - dprintk (2, "tvp5150: Teletext filter 1 = 0x%02x\n", tvp5150_read(c,TVP5150_TELETEXT_FIL_1_2)); - dprintk (2, "tvp5150: Teletext filter 1 = 0x%02x\n", tvp5150_read(c,TVP5150_TELETEXT_FIL_1_3)); - dprintk (2, "tvp5150: Teletext filter 1 = 0x%02x\n", tvp5150_read(c,TVP5150_TELETEXT_FIL_1_4)); - dprintk (2, "tvp5150: Teletext filter 1 = 0x%02x\n", tvp5150_read(c,TVP5150_TELETEXT_FIL_1_5)); - dprintk (2, "tvp5150: Teletext filter 2 = 0x%02x\n", tvp5150_read(c,TVP5150_TELETEXT_FIL_2_1)); - dprintk (2, "tvp5150: Teletext filter 2 = 0x%02x\n", tvp5150_read(c,TVP5150_TELETEXT_FIL_2_2)); - dprintk (2, "tvp5150: Teletext filter 2 = 0x%02x\n", tvp5150_read(c,TVP5150_TELETEXT_FIL_2_3)); - dprintk (2, "tvp5150: Teletext filter 2 = 0x%02x\n", tvp5150_read(c,TVP5150_TELETEXT_FIL_2_4)); - dprintk (2, "tvp5150: Teletext filter 2 = 0x%02x\n", tvp5150_read(c,TVP5150_TELETEXT_FIL_2_5)); - dprintk (2, "tvp5150: Teletext filter enable = 0x%02x\n", tvp5150_read(c,TVP5150_TELETEXT_FIL_ENA)); - dprintk (2, "tvp5150: Interrupt status register A = 0x%02x\n", tvp5150_read(c,TVP5150_INT_STATUS_REG_A)); - dprintk (2, "tvp5150: Interrupt enable register A = 0x%02x\n", tvp5150_read(c,TVP5150_INT_ENABLE_REG_A)); - dprintk (2, "tvp5150: Interrupt configuration = 0x%02x\n", tvp5150_read(c,TVP5150_INT_CONF)); - dprintk (2, "tvp5150: VDP configuration RAM data = 0x%02x\n", tvp5150_read(c,TVP5150_VDP_CONF_RAM_DATA)); - dprintk (2, "tvp5150: Configuration RAM address low byte = 0x%02x\n", tvp5150_read(c,TVP5150_CONF_RAM_ADDR_LOW)); - dprintk (2, "tvp5150: Configuration RAM address high byte = 0x%02x\n", tvp5150_read(c,TVP5150_CONF_RAM_ADDR_HIGH)); - dprintk (2, "tvp5150: VDP status register = 0x%02x\n", tvp5150_read(c,TVP5150_VDP_STATUS_REG)); - dprintk (2, "tvp5150: FIFO word count = 0x%02x\n", tvp5150_read(c,TVP5150_FIFO_WORD_COUNT)); - dprintk (2, "tvp5150: FIFO interrupt threshold = 0x%02x\n", tvp5150_read(c,TVP5150_FIFO_INT_THRESHOLD)); - dprintk (2, "tvp5150: FIFO reset = 0x%02x\n", tvp5150_read(c,TVP5150_FIFO_RESET)); - dprintk (2, "tvp5150: Line number interrupt = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_NUMBER_INT)); - dprintk (2, "tvp5150: Pixel alignment register low byte = 0x%02x\n", tvp5150_read(c,TVP5150_PIX_ALIGN_REG_LOW)); - dprintk (2, "tvp5150: Pixel alignment register high byte = 0x%02x\n", tvp5150_read(c,TVP5150_PIX_ALIGN_REG_HIGH)); - dprintk (2, "tvp5150: FIFO output control = 0x%02x\n", tvp5150_read(c,TVP5150_FIFO_OUT_CTRL)); - dprintk (2, "tvp5150: Full field enable 1 = 0x%02x\n", tvp5150_read(c,TVP5150_FULL_FIELD_ENA_1)); - dprintk (2, "tvp5150: Full field enable 2 = 0x%02x\n", tvp5150_read(c,TVP5150_FULL_FIELD_ENA_2)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_1)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_2)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_3)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_4)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_5)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_6)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_7)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_8)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_9)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_10)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_11)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_12)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_13)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_14)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_15)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_16)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_17)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_18)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_19)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_20)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_21)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_22)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_23)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_24)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_25)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_27)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_28)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_29)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_30)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_31)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_32)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_33)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_34)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_35)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_36)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_37)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_38)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_39)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_40)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_41)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_42)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_43)); - dprintk (2, "tvp5150: Line mode registers = 0x%02x\n", tvp5150_read(c,TVP5150_LINE_MODE_REG_44)); - dprintk (2, "tvp5150: Full field mode register = 0x%02x\n", tvp5150_read(c,TVP5150_FULL_FIELD_MODE_REG)); + printk("tvp5150: Video input source selection #1 = 0x%02x\n", + tvp5150_read(c, TVP5150_VD_IN_SRC_SEL_1)); + printk("tvp5150: Analog channel controls = 0x%02x\n", + tvp5150_read(c, TVP5150_ANAL_CHL_CTL)); + printk("tvp5150: Operation mode controls = 0x%02x\n", + tvp5150_read(c, TVP5150_OP_MODE_CTL)); + printk("tvp5150: Miscellaneous controls = 0x%02x\n", + tvp5150_read(c, TVP5150_MISC_CTL)); + printk("tvp5150: Autoswitch mask: TVP5150A / TVP5150AM = 0x%02x\n", + tvp5150_read(c, TVP5150_AUTOSW_MSK)); + printk("tvp5150: Color killer threshold control = 0x%02x\n", + tvp5150_read(c, TVP5150_COLOR_KIL_THSH_CTL)); + printk("tvp5150: Luminance processing control #1 = 0x%02x\n", + tvp5150_read(c, TVP5150_LUMA_PROC_CTL_1)); + printk("tvp5150: Luminance processing control #2 = 0x%02x\n", + tvp5150_read(c, TVP5150_LUMA_PROC_CTL_2)); + printk("tvp5150: Brightness control = 0x%02x\n", + tvp5150_read(c, TVP5150_BRIGHT_CTL)); + printk("tvp5150: Color saturation control = 0x%02x\n", + tvp5150_read(c, TVP5150_SATURATION_CTL)); + printk("tvp5150: Hue control = 0x%02x\n", + tvp5150_read(c, TVP5150_HUE_CTL)); + printk("tvp5150: Contrast control = 0x%02x\n", + tvp5150_read(c, TVP5150_CONTRAST_CTL)); + printk("tvp5150: Outputs and data rates select = 0x%02x\n", + tvp5150_read(c, TVP5150_DATA_RATE_SEL)); + printk("tvp5150: Luminance processing control #3 = 0x%02x\n", + tvp5150_read(c, TVP5150_LUMA_PROC_CTL_3)); + printk("tvp5150: Configuration shared pins = 0x%02x\n", + tvp5150_read(c, TVP5150_CONF_SHARED_PIN)); + printk("tvp5150: Active video cropping start MSB = 0x%02x\n", + tvp5150_read(c, TVP5150_ACT_VD_CROP_ST_MSB)); + printk("tvp5150: Active video cropping start LSB = 0x%02x\n", + tvp5150_read(c, TVP5150_ACT_VD_CROP_ST_LSB)); + printk("tvp5150: Active video cropping stop MSB = 0x%02x\n", + tvp5150_read(c, TVP5150_ACT_VD_CROP_STP_MSB)); + printk("tvp5150: Active video cropping stop LSB = 0x%02x\n", + tvp5150_read(c, TVP5150_ACT_VD_CROP_STP_LSB)); + printk("tvp5150: Genlock/RTC = 0x%02x\n", + tvp5150_read(c, TVP5150_GENLOCK)); + printk("tvp5150: Horizontal sync start = 0x%02x\n", + tvp5150_read(c, TVP5150_HORIZ_SYNC_START)); + printk("tvp5150: Vertical blanking start = 0x%02x\n", + tvp5150_read(c, TVP5150_VERT_BLANKING_START)); + printk("tvp5150: Vertical blanking stop = 0x%02x\n", + tvp5150_read(c, TVP5150_VERT_BLANKING_STOP)); + printk("tvp5150: Chrominance processing control #1 = 0x%02x\n", + tvp5150_read(c, TVP5150_CHROMA_PROC_CTL_1)); + printk("tvp5150: Chrominance processing control #2 = 0x%02x\n", + tvp5150_read(c, TVP5150_CHROMA_PROC_CTL_2)); + printk("tvp5150: Interrupt reset register B = 0x%02x\n", + tvp5150_read(c, TVP5150_INT_RESET_REG_B)); + printk("tvp5150: Interrupt enable register B = 0x%02x\n", + tvp5150_read(c, TVP5150_INT_ENABLE_REG_B)); + printk("tvp5150: Interrupt configuration register B = 0x%02x\n", + tvp5150_read(c, TVP5150_INTT_CONFIG_REG_B)); + printk("tvp5150: Video standard = 0x%02x\n", + tvp5150_read(c, TVP5150_VIDEO_STD)); + printk("tvp5150: Cb gain factor = 0x%02x\n", + tvp5150_read(c, TVP5150_CB_GAIN_FACT)); + printk("tvp5150: Cr gain factor = 0x%02x\n", + tvp5150_read(c, TVP5150_CR_GAIN_FACTOR)); + printk("tvp5150: Macrovision on counter = 0x%02x\n", + tvp5150_read(c, TVP5150_MACROVISION_ON_CTR)); + printk("tvp5150: Macrovision off counter = 0x%02x\n", + tvp5150_read(c, TVP5150_MACROVISION_OFF_CTR)); + printk("tvp5150: revision select (TVP5150AM1 only) = 0x%02x\n", + tvp5150_read(c, TVP5150_REV_SELECT)); + printk("tvp5150: MSB of device ID = 0x%02x\n", + tvp5150_read(c, TVP5150_MSB_DEV_ID)); + printk("tvp5150: LSB of device ID = 0x%02x\n", + tvp5150_read(c, TVP5150_LSB_DEV_ID)); + printk("tvp5150: ROM major version = 0x%02x\n", + tvp5150_read(c, TVP5150_ROM_MAJOR_VER)); + printk("tvp5150: ROM minor version = 0x%02x\n", + tvp5150_read(c, TVP5150_ROM_MINOR_VER)); + printk("tvp5150: Vertical line count MSB = 0x%02x\n", + tvp5150_read(c, TVP5150_VERT_LN_COUNT_MSB)); + printk("tvp5150: Vertical line count LSB = 0x%02x\n", + tvp5150_read(c, TVP5150_VERT_LN_COUNT_LSB)); + printk("tvp5150: Interrupt status register B = 0x%02x\n", + tvp5150_read(c, TVP5150_INT_STATUS_REG_B)); + printk("tvp5150: Interrupt active register B = 0x%02x\n", + tvp5150_read(c, TVP5150_INT_ACTIVE_REG_B)); + printk("tvp5150: Status register #1 = 0x%02x\n", + tvp5150_read(c, TVP5150_STATUS_REG_1)); + printk("tvp5150: Status register #2 = 0x%02x\n", + tvp5150_read(c, TVP5150_STATUS_REG_2)); + printk("tvp5150: Status register #3 = 0x%02x\n", + tvp5150_read(c, TVP5150_STATUS_REG_3)); + printk("tvp5150: Status register #4 = 0x%02x\n", + tvp5150_read(c, TVP5150_STATUS_REG_4)); + printk("tvp5150: Status register #5 = 0x%02x\n", + tvp5150_read(c, TVP5150_STATUS_REG_5)); + printk("tvp5150: Closed caption data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_CC_DATA_REG1)); + printk("tvp5150: Closed caption data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_CC_DATA_REG2)); + printk("tvp5150: Closed caption data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_CC_DATA_REG3)); + printk("tvp5150: Closed caption data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_CC_DATA_REG4)); + printk("tvp5150: WSS data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_WSS_DATA_REG1)); + printk("tvp5150: WSS data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_WSS_DATA_REG2)); + printk("tvp5150: WSS data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_WSS_DATA_REG3)); + printk("tvp5150: WSS data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_WSS_DATA_REG4)); + printk("tvp5150: WSS data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_WSS_DATA_REG5)); + printk("tvp5150: WSS data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_WSS_DATA_REG6)); + printk("tvp5150: VPS data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_VPS_DATA_REG1)); + printk("tvp5150: VPS data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_VPS_DATA_REG2)); + printk("tvp5150: VPS data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_VPS_DATA_REG3)); + printk("tvp5150: VPS data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_VPS_DATA_REG4)); + printk("tvp5150: VPS data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_VPS_DATA_REG5)); + printk("tvp5150: VPS data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_VPS_DATA_REG6)); + printk("tvp5150: VPS data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_VPS_DATA_REG7)); + printk("tvp5150: VPS data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_VPS_DATA_REG8)); + printk("tvp5150: VPS data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_VPS_DATA_REG9)); + printk("tvp5150: VPS data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_VPS_DATA_REG10)); + printk("tvp5150: VPS data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_VPS_DATA_REG11)); + printk("tvp5150: VPS data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_VPS_DATA_REG12)); + printk("tvp5150: VPS data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_VPS_DATA_REG13)); + printk("tvp5150: VITC data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_VITC_DATA_REG1)); + printk("tvp5150: VITC data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_VITC_DATA_REG2)); + printk("tvp5150: VITC data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_VITC_DATA_REG3)); + printk("tvp5150: VITC data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_VITC_DATA_REG4)); + printk("tvp5150: VITC data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_VITC_DATA_REG5)); + printk("tvp5150: VITC data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_VITC_DATA_REG6)); + printk("tvp5150: VITC data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_VITC_DATA_REG7)); + printk("tvp5150: VITC data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_VITC_DATA_REG8)); + printk("tvp5150: VITC data registers = 0x%02x\n", + tvp5150_read(c, TVP5150_VITC_DATA_REG9)); + printk("tvp5150: VBI FIFO read data = 0x%02x\n", + tvp5150_read(c, TVP5150_VBI_FIFO_READ_DATA)); + printk("tvp5150: Teletext filter 1 = 0x%02x\n", + tvp5150_read(c, TVP5150_TELETEXT_FIL_1_1)); + printk("tvp5150: Teletext filter 1 = 0x%02x\n", + tvp5150_read(c, TVP5150_TELETEXT_FIL_1_2)); + printk("tvp5150: Teletext filter 1 = 0x%02x\n", + tvp5150_read(c, TVP5150_TELETEXT_FIL_1_3)); + printk("tvp5150: Teletext filter 1 = 0x%02x\n", + tvp5150_read(c, TVP5150_TELETEXT_FIL_1_4)); + printk("tvp5150: Teletext filter 1 = 0x%02x\n", + tvp5150_read(c, TVP5150_TELETEXT_FIL_1_5)); + printk("tvp5150: Teletext filter 2 = 0x%02x\n", + tvp5150_read(c, TVP5150_TELETEXT_FIL_2_1)); + printk("tvp5150: Teletext filter 2 = 0x%02x\n", + tvp5150_read(c, TVP5150_TELETEXT_FIL_2_2)); + printk("tvp5150: Teletext filter 2 = 0x%02x\n", + tvp5150_read(c, TVP5150_TELETEXT_FIL_2_3)); + printk("tvp5150: Teletext filter 2 = 0x%02x\n", + tvp5150_read(c, TVP5150_TELETEXT_FIL_2_4)); + printk("tvp5150: Teletext filter 2 = 0x%02x\n", + tvp5150_read(c, TVP5150_TELETEXT_FIL_2_5)); + printk("tvp5150: Teletext filter enable = 0x%02x\n", + tvp5150_read(c, TVP5150_TELETEXT_FIL_ENA)); + printk("tvp5150: Interrupt status register A = 0x%02x\n", + tvp5150_read(c, TVP5150_INT_STATUS_REG_A)); + printk("tvp5150: Interrupt enable register A = 0x%02x\n", + tvp5150_read(c, TVP5150_INT_ENABLE_REG_A)); + printk("tvp5150: Interrupt configuration = 0x%02x\n", + tvp5150_read(c, TVP5150_INT_CONF)); + printk("tvp5150: VDP configuration RAM data = 0x%02x\n", + tvp5150_read(c, TVP5150_VDP_CONF_RAM_DATA)); + printk("tvp5150: Configuration RAM address low byte = 0x%02x\n", + tvp5150_read(c, TVP5150_CONF_RAM_ADDR_LOW)); + printk("tvp5150: Configuration RAM address high byte = 0x%02x\n", + tvp5150_read(c, TVP5150_CONF_RAM_ADDR_HIGH)); + printk("tvp5150: VDP status register = 0x%02x\n", + tvp5150_read(c, TVP5150_VDP_STATUS_REG)); + printk("tvp5150: FIFO word count = 0x%02x\n", + tvp5150_read(c, TVP5150_FIFO_WORD_COUNT)); + printk("tvp5150: FIFO interrupt threshold = 0x%02x\n", + tvp5150_read(c, TVP5150_FIFO_INT_THRESHOLD)); + printk("tvp5150: FIFO reset = 0x%02x\n", + tvp5150_read(c, TVP5150_FIFO_RESET)); + printk("tvp5150: Line number interrupt = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_NUMBER_INT)); + printk("tvp5150: Pixel alignment register low byte = 0x%02x\n", + tvp5150_read(c, TVP5150_PIX_ALIGN_REG_LOW)); + printk("tvp5150: Pixel alignment register high byte = 0x%02x\n", + tvp5150_read(c, TVP5150_PIX_ALIGN_REG_HIGH)); + printk("tvp5150: FIFO output control = 0x%02x\n", + tvp5150_read(c, TVP5150_FIFO_OUT_CTRL)); + printk("tvp5150: Full field enable 1 = 0x%02x\n", + tvp5150_read(c, TVP5150_FULL_FIELD_ENA_1)); + printk("tvp5150: Full field enable 2 = 0x%02x\n", + tvp5150_read(c, TVP5150_FULL_FIELD_ENA_2)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_1)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_2)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_3)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_4)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_5)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_6)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_7)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_8)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_9)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_10)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_11)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_12)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_13)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_14)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_15)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_16)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_17)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_18)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_19)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_20)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_21)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_22)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_23)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_24)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_25)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_27)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_28)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_29)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_30)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_31)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_32)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_33)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_34)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_35)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_36)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_37)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_38)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_39)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_40)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_41)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_42)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_43)); + printk("tvp5150: Line mode registers = 0x%02x\n", + tvp5150_read(c, TVP5150_LINE_MODE_REG_44)); + printk("tvp5150: Full field mode register = 0x%02x\n", + tvp5150_read(c, TVP5150_FULL_FIELD_MODE_REG)); } /**************************************************************************** Basic functions ****************************************************************************/ enum tvp5150_input { - TVP5150_ANALOG_CH0 = 0, - TVP5150_SVIDEO = 1, - TVP5150_ANALOG_CH1 = 2, - TVP5150_BLACK_SCREEN = 8 + TVP5150_ANALOG_CH0 = 0, + TVP5150_SVIDEO = 1, + TVP5150_ANALOG_CH1 = 2, + TVP5150_BLACK_SCREEN = 8 }; -static inline void tvp5150_selmux(struct i2c_client *c, enum tvp5150_input input) +static inline void tvp5150_selmux(struct i2c_client *c, + enum tvp5150_input input) { - tvp5150_write(c,TVP5150_VD_IN_SRC_SEL_1,input); + int tvp_input; + + /* FIXME: It is dependent of basic driver */ + switch (input) + { + case 2: + tvp_input=TVP5150_ANALOG_CH0; + break; + case 0: + tvp_input=TVP5150_ANALOG_CH1; + break; + case 1: + tvp_input=TVP5150_SVIDEO; + break; + default: + tvp_input=TVP5150_BLACK_SCREEN; + } + + tvp5150_write(c, TVP5150_VD_IN_SRC_SEL_1, tvp_input); }; static inline void tvp5150_reset(struct i2c_client *c) { - /* Automatic offset and AGC enabled*/ - tvp5150_write(c,TVP5150_ANAL_CHL_CTL,0x15); + tvp5150_write(c, TVP5150_CONF_SHARED_PIN, 2); + + /* Automatic offset and AGC enabled */ + tvp5150_write(c, TVP5150_ANAL_CHL_CTL, 0x15); /* Normal Operation */ - tvp5150_write(c,TVP5150_OP_MODE_CTL,0x00); +// tvp5150_write(c, TVP5150_OP_MODE_CTL, 0x00); /* Activate YCrCb output 0x9 or 0xd ? */ - tvp5150_write(c,TVP5150_MISC_CTL,0x09); + tvp5150_write(c, TVP5150_MISC_CTL, 0x6f); /* Activates video std autodetection for PAL/M and PAL/N */ - tvp5150_write(c,TVP5150_AUTOSW_MSK,0xf0); + tvp5150_write(c, TVP5150_AUTOSW_MSK, 0xf0); /* Default format: 0x47, 4:2:2: 0x40 */ - tvp5150_write(c,TVP5150_DATA_RATE_SEL,0x47); + tvp5150_write(c, TVP5150_DATA_RATE_SEL, 0x47); + + tvp5150_selmux(c, TVP5150_ANALOG_CH0); - tvp5150_selmux(c,TVP5150_ANALOG_CH0); + tvp5150_write(c, TVP5150_CHROMA_PROC_CTL_1, 0x0c); + tvp5150_write(c, TVP5150_CHROMA_PROC_CTL_2, 0x54); + + tvp5150_write(c, 0x27, 0x20); /* ?????????? */ + + tvp5150_write(c, TVP5150_VIDEO_STD, 0x0); /* Auto switch */ + + tvp5150_write(c, TVP5150_HUE_CTL, 0x0); }; +/**************************************************************************** + I2C Command + ****************************************************************************/ +static int tvp5150_command(struct i2c_client *client, + unsigned int cmd, void *arg) +{ + struct tvp5150 *decoder = i2c_get_clientdata(client); + + switch (cmd) { + + case 0: + case DECODER_INIT: + tvp5150_reset(client); + break; + + case DECODER_DUMP: + dump_reg(client); + break; + + case DECODER_GET_CAPABILITIES: + { + struct video_decoder_capability *cap = arg; + + cap->flags = VIDEO_DECODER_PAL | + VIDEO_DECODER_NTSC | + VIDEO_DECODER_SECAM | + VIDEO_DECODER_AUTO | VIDEO_DECODER_CCIR; + cap->inputs = 3; + cap->outputs = 1; + break; + } + case DECODER_GET_STATUS: + { + break; + } + + case DECODER_SET_GPIO: + break; + + case DECODER_SET_VBI_BYPASS: + break; + + case DECODER_SET_NORM: + { + int *iarg = arg; + + switch (*iarg) { + + case VIDEO_MODE_NTSC: + break; + + case VIDEO_MODE_PAL: + break; + + case VIDEO_MODE_SECAM: + break; + + case VIDEO_MODE_AUTO: + break; + + default: + return -EINVAL; + + } + decoder->norm = *iarg; + break; + } + case DECODER_SET_INPUT: + { + int *iarg = arg; + if (*iarg < 0 || *iarg > 3) { + return -EINVAL; + } + + tvp5150_selmux(client, *iarg); + + break; + } + case DECODER_SET_OUTPUT: + { + int *iarg = arg; + + /* not much choice of outputs */ + if (*iarg != 0) { + return -EINVAL; + } + break; + } + case DECODER_ENABLE_OUTPUT: +// int *iarg = arg; +// int enable = (*iarg != 0); + + break; + + case DECODER_SET_PICTURE: + default: + return -EINVAL; + } + + return 0; +} /**************************************************************************** I2C Client & Driver @@ -271,10 +563,8 @@ static struct i2c_client client_template = .driver = &driver, }; -static int -tvp5150_detect_client (struct i2c_adapter *adapter, - int address, - int kind) +static int tvp5150_detect_client (struct i2c_adapter *adapter, + int address, int kind) { struct i2c_client *client; struct tvp5150 *core; @@ -297,7 +587,7 @@ tvp5150_detect_client (struct i2c_adapter *adapter, client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); if (client == 0) return -ENOMEM; - memcpy(client,&client_template,sizeof(struct i2c_client)); + memcpy(client,&client_template,sizeof(struct i2c_client)); core = kmalloc(sizeof(struct tvp5150), GFP_KERNEL); if (core == 0) { @@ -315,7 +605,6 @@ tvp5150_detect_client (struct i2c_adapter *adapter, return rv; } - tvp5150_reset(client); dump_reg (client); return 0; @@ -360,6 +649,8 @@ static struct i2c_driver driver = { .attach_adapter = tvp5150_attach_adapter, .detach_client = tvp5150_detach_client, + + .command = tvp5150_command, }; static int __init -- cgit v1.2.3 From 83331624aac006b615f6853aacd28aef3111ef07 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 8 Nov 2005 21:36:42 -0800 Subject: [PATCH] v4l: 677: increased eeprom dump to 128 bytes - Increased eeprom dump to 128 bytes Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index ad8e89d6bf5..4169c2a857f 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -428,7 +428,7 @@ struct saa7134_dev { /* i2c i/o */ struct i2c_adapter i2c_adap; struct i2c_client i2c_client; - unsigned char eedata[64]; + unsigned char eedata[128]; /* video overlay */ struct v4l2_framebuffer ovbuf; -- cgit v1.2.3 From 4c86f973ba0f49af1f4c54ff3d1935093c173450 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:36:43 -0800 Subject: [PATCH] v4l: 678: fixed input selection - Fixed input selection. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tvp5150.c | 62 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index bd1201d7adf..6e3ba23104d 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -397,6 +397,7 @@ enum tvp5150_input { static inline void tvp5150_selmux(struct i2c_client *c, enum tvp5150_input input) { + struct tvp5150 *decoder = i2c_get_clientdata(c); int tvp_input; /* FIXME: It is dependent of basic driver */ @@ -415,11 +416,16 @@ static inline void tvp5150_selmux(struct i2c_client *c, tvp_input=TVP5150_BLACK_SCREEN; } + if (!decoder->enable) + tvp_input|=TVP5150_BLACK_SCREEN; + tvp5150_write(c, TVP5150_VD_IN_SRC_SEL_1, tvp_input); }; static inline void tvp5150_reset(struct i2c_client *c) { + struct tvp5150 *decoder = i2c_get_clientdata(c); + tvp5150_write(c, TVP5150_CONF_SHARED_PIN, 2); /* Automatic offset and AGC enabled */ @@ -431,13 +437,13 @@ static inline void tvp5150_reset(struct i2c_client *c) /* Activate YCrCb output 0x9 or 0xd ? */ tvp5150_write(c, TVP5150_MISC_CTL, 0x6f); - /* Activates video std autodetection for PAL/M and PAL/N */ - tvp5150_write(c, TVP5150_AUTOSW_MSK, 0xf0); + /* Activates video std autodetection for all standards */ + tvp5150_write(c, TVP5150_AUTOSW_MSK, 0x0); /* Default format: 0x47, 4:2:2: 0x40 */ tvp5150_write(c, TVP5150_DATA_RATE_SEL, 0x47); - tvp5150_selmux(c, TVP5150_ANALOG_CH0); + tvp5150_selmux(c, decoder->input); tvp5150_write(c, TVP5150_CHROMA_PROC_CTL_1, 0x0c); tvp5150_write(c, TVP5150_CHROMA_PROC_CTL_2, 0x54); @@ -446,7 +452,10 @@ static inline void tvp5150_reset(struct i2c_client *c) tvp5150_write(c, TVP5150_VIDEO_STD, 0x0); /* Auto switch */ - tvp5150_write(c, TVP5150_HUE_CTL, 0x0); + tvp5150_write(c, TVP5150_BRIGHT_CTL, decoder->bright >> 8); + tvp5150_write(c, TVP5150_CONTRAST_CTL, decoder->contrast >> 8); + tvp5150_write(c, TVP5150_SATURATION_CTL, decoder->contrast >> 8); + tvp5150_write(c, TVP5150_HUE_CTL, (decoder->hue - 32768) >> 8); }; /**************************************************************************** @@ -523,7 +532,8 @@ static int tvp5150_command(struct i2c_client *client, return -EINVAL; } - tvp5150_selmux(client, *iarg); + decoder->input=*iarg; + tvp5150_selmux(client, decoder->input); break; } @@ -538,12 +548,40 @@ static int tvp5150_command(struct i2c_client *client, break; } case DECODER_ENABLE_OUTPUT: -// int *iarg = arg; -// int enable = (*iarg != 0); + { + int *iarg = arg; - break; + decoder->enable = (*iarg != 0); + + tvp5150_selmux(client, decoder->input); + break; + } case DECODER_SET_PICTURE: + { + struct video_picture *pic = arg; + if (decoder->bright != pic->brightness) { + /* We want 0 to 255 we get 0-65535 */ + decoder->bright = pic->brightness; + tvp5150_write(client, TVP5150_BRIGHT_CTL, decoder->bright >> 8); + } + if (decoder->contrast != pic->contrast) { + /* We want 0 to 255 we get 0-65535 */ + decoder->contrast = pic->contrast; + tvp5150_write(client, TVP5150_CONTRAST_CTL, decoder->contrast >> 8); + } + if (decoder->sat != pic->colour) { + /* We want 0 to 255 we get 0-65535 */ + decoder->sat = pic->colour; + tvp5150_write(client, TVP5150_SATURATION_CTL, decoder->contrast >> 8); + } + if (decoder->hue != pic->hue) { + /* We want -128 to 127 we get 0-65535 */ + decoder->hue = pic->hue; + tvp5150_write(client, TVP5150_HUE_CTL, (decoder->hue - 32768) >> 8); + } + break; + } default: return -EINVAL; } @@ -599,6 +637,14 @@ static int tvp5150_detect_client (struct i2c_adapter *adapter, rv = i2c_attach_client(client); + core->norm = VIDEO_MODE_AUTO; + core->input = 2; + core->enable = 1; + core->bright = 32768; + core->contrast = 32768; + core->hue = 32768; + core->sat = 32768; + if (rv) { kfree(client); kfree(core); -- cgit v1.2.3 From 372dffdb4b2d23e94b657d2321c16c4c86df45d2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:36:44 -0800 Subject: [PATCH] v4l: 683: some v4l2 api calls implemented on msp3400.c - Some V4L2 API calls implemented on msp3400.c. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/msp3400.c | 95 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index e75e7948fd9..6e2b0775a74 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -382,6 +382,7 @@ static void msp3400c_setvolume(struct i2c_client *client, { int val = 0, bal = 0; +muted=0; if (!muted) { /* 0x7f instead if 0x73 here has sound quality issues, * probably due to overmodulation + clipping ... */ @@ -989,6 +990,8 @@ static int msp34xx_modus(int norm) { switch (norm) { case VIDEO_MODE_PAL: + dprintk(KERN_DEBUG "msp34xx: video mode selected to PAL\n"); + #if 1 /* experimental: not sure this works with all chip versions */ return 0x7003; @@ -997,12 +1000,16 @@ static int msp34xx_modus(int norm) return 0x1003; #endif case VIDEO_MODE_NTSC: /* BTSC */ + dprintk(KERN_DEBUG "msp34xx: video mode selected to NTSC\n"); return 0x2003; case VIDEO_MODE_SECAM: + dprintk(KERN_DEBUG "msp34xx: video mode selected to SECAM\n"); return 0x0003; case VIDEO_MODE_RADIO: + dprintk(KERN_DEBUG "msp34xx: video mode selected to Radio\n"); return 0x0003; case VIDEO_MODE_AUTO: + dprintk(KERN_DEBUG "msp34xx: video mode selected to Auto\n"); return 0x2003; default: return 0x0003; @@ -1495,6 +1502,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) dprintk("msp34xx: error while reading chip version\n"); return -1; } + printk(KERN_INFO "msp34xx: rev1=0x%04x, rev2=0x%04x\n", msp->rev1, msp->rev2); msp3400c_setvolume(c, msp->muted, msp->volume, msp->balance); @@ -1762,6 +1770,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) msp_any_set_audmode(client,mode_v4l1_to_v4l2(va->mode)); break; } + case VIDIOCSCHAN: { struct video_channel *vc = arg; @@ -1782,6 +1791,92 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) } /* --- v4l2 ioctls --- */ + case VIDIOC_S_STD: + { + v4l2_std_id *id = arg; + + /*FIXME: use V4L2 mode flags on msp3400 instead of V4L1*/ + if (*id & V4L2_STD_PAL) { + msp->norm=VIDEO_MODE_PAL; + } else if (*id & V4L2_STD_SECAM) { + msp->norm=VIDEO_MODE_SECAM; + } else { + msp->norm=VIDEO_MODE_NTSC; + } + + msp_wake_thread(client); + return 0; + } + + case VIDIOC_G_AUDIO: + { + struct v4l2_audio *a = arg; + + memset(a,0,sizeof(*a)); + + switch (a->index) { + case AUDIO_RADIO: + strcpy(a->name,"Radio"); + break; + case AUDIO_EXTERN_1: + strcpy(a->name,"Extern 1"); + break; + case AUDIO_EXTERN_2: + strcpy(a->name,"Extern 2"); + break; + case AUDIO_TUNER: + strcpy(a->name,"Television"); + break; + default: + return -EINVAL; + } + + msp_any_detect_stereo(client); + if (msp->audmode == V4L2_TUNER_MODE_STEREO) { + a->capability=V4L2_AUDCAP_STEREO; + } + + break; + } + case VIDIOC_S_AUDIO: + { + struct v4l2_audio *sarg = arg; + + switch (sarg->index) { + case AUDIO_RADIO: + /* Hauppauge uses IN2 for the radio */ + msp->mode = MSP_MODE_FM_RADIO; + scart = SCART_IN2; + break; + case AUDIO_EXTERN_1: + /* IN1 is often used for external input ... */ + msp->mode = MSP_MODE_EXTERN; + scart = SCART_IN1; + break; + case AUDIO_EXTERN_2: + /* ... sometimes it is IN2 through ;) */ + msp->mode = MSP_MODE_EXTERN; + scart = SCART_IN2; + break; + case AUDIO_TUNER: + msp->mode = -1; + break; + } + if (scart) { + msp->rxsubchans = V4L2_TUNER_SUB_STEREO; + msp->audmode = V4L2_TUNER_MODE_STEREO; + msp3400c_set_scart(client,scart,0); + msp3400c_write(client,I2C_MSP3400C_DFP,0x000d,0x1900); + } + if (sarg->capability==V4L2_AUDCAP_STEREO) { + msp->audmode = V4L2_TUNER_MODE_STEREO; + } else { + msp->audmode &= ~V4L2_TUNER_MODE_STEREO; + } + msp_any_set_audmode(client, msp->audmode); + msp_wake_thread(client); + break; + } case VIDIOC_G_TUNER: { struct v4l2_tuner *vt = arg; -- cgit v1.2.3 From 20f441f6900d786606583263d89653c48c7093a8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 8 Nov 2005 21:36:44 -0800 Subject: [PATCH] v4l: 685: update the tveeprom tuner list with the tuner - Update the tveeprom tuner list with the tuner Signed-off-by: Hans Verkuil Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tuner-simple.c | 4 ++-- drivers/media/video/tveeprom.c | 22 ++++++++++++++-------- include/media/tuner.h | 2 +- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 3af055970dd..b75ad2d4488 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -222,7 +222,7 @@ static struct tunertype tuners[] = { 16*160.00,16*454.00,0x41,0x42,0x04,0x8e,940}, /* UHF band untested */ { "tda8290+75", Philips, PAL|NTSC, /* see tda8290.c for details */ }, - { "LG PAL (TAPE series)", LGINNOTEK, PAL, + { "TCL 2002MB", TCL, PAL, 16*170.00, 16*450.00, 0x01,0x02,0x08,0xce,623}, { "Philips PAL/SECAM multi (FQ1216AME MK4)", Philips, PAL, 16*160.00,16*442.00,0x01,0x02,0x04,0xce,623 }, @@ -233,7 +233,7 @@ static struct tunertype tuners[] = { { "Ymec TVision TVF-5533MF", Philips, NTSC, 16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732}, - /* 60-66 */ + /* 60-67 */ { "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC, 16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732}, { "Tena TNF9533-D/IF/TNF9533-B/DF", Philips, PAL, diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 5344d559219..6453b71f299 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -200,15 +200,21 @@ hauppauge_tuner[] = { TUNER_ABSENT, "Philips FQ1286A MK4"}, { TUNER_ABSENT, "Philips FQ1216ME MK5"}, { TUNER_ABSENT, "Philips FQ1236 MK5"}, - { TUNER_ABSENT, "Unspecified"}, - { TUNER_LG_PAL_TAPE, "LG PAL (TAPE Series)"}, - { TUNER_ABSENT, "Unspecified"}, + { TUNER_ABSENT, "Samsung TCPG_6121P30A"}, + { TUNER_TCL_2002MB, "TCL 2002MB_3H"}, + { TUNER_ABSENT, "TCL 2002MI_3H"}, { TUNER_TCL_2002N, "TCL 2002N 5H"}, - /* 100-103 */ - { TUNER_ABSENT, "Unspecified"}, - { TUNER_TEA5767, "Philips TEA5767HN FM Radio"}, - { TUNER_ABSENT, "Unspecified"}, - { TUNER_PHILIPS_FM1236_MK3, "TCL MFNM05 4"}, + /* 100-109 */ + { TUNER_ABSENT, "Philips FMD1216ME"}, + { TUNER_TEA5767, "Philips TEA5768HL FM Radio"}, + { TUNER_ABSENT, "Panasonic ENV57H12D5"}, + { TUNER_ABSENT, "TCL MFNM05-4"}, + { TUNER_ABSENT, "TCL MNM05-4"}, + { TUNER_PHILIPS_FM1216ME_MK3, "TCL MPE05-2"}, + { TUNER_ABSENT, "TCL MQNM05-4"}, + { TUNER_ABSENT, "LG TAPC-W701D"}, + { TUNER_ABSENT, "TCL 9886P-WM"}, + { TUNER_ABSENT, "TCL 1676NM-WM"}, }; /* This list is supplied by Hauppauge. Thanks! */ diff --git a/include/media/tuner.h b/include/media/tuner.h index 4f47eac90ca..bf925702fbb 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -95,7 +95,7 @@ #define TUNER_THOMSON_DTT7610 52 #define TUNER_PHILIPS_FQ1286 53 #define TUNER_PHILIPS_TDA8290 54 -#define TUNER_LG_PAL_TAPE 55 /* Hauppauge PVR-150 PAL */ +#define TUNER_TCL_2002MB 55 /* Hauppauge PVR-150 PAL */ #define TUNER_PHILIPS_FQ1216AME_MK4 56 /* Hauppauge PVR-150 PAL */ #define TUNER_PHILIPS_FQ1236A_MK4 57 /* Hauppauge PVR-500MCE NTSC */ -- cgit v1.2.3 From 9b71521b66da26129255ade6ad71f708032bc0e0 Mon Sep 17 00:00:00 2001 From: "Robert W. Boone" Date: Tue, 8 Nov 2005 21:36:45 -0800 Subject: [PATCH] v4l: 686: change the number of lines in the input signal when the - Change the number of lines in the input signal when the video standard is changed. - Fix comments style. Signed-off-by: Robert W. Boone Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa6752hs.c | 130 +++++++++++++++++--------------- 1 file changed, 70 insertions(+), 60 deletions(-) diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index 382911c6ef2..dac720ea3b0 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c @@ -57,6 +57,7 @@ struct saa6752hs_state { struct i2c_client client; struct v4l2_mpeg_compression params; enum saa6752hs_videoformat video_format; + v4l2_std_id standard; }; enum saa6752hs_command { @@ -74,58 +75,58 @@ enum saa6752hs_command { /* ---------------------------------------------------------------------- */ static u8 PAT[] = { - 0xc2, // i2c register - 0x00, // table number for encoder + 0xc2, /* i2c register */ + 0x00, /* table number for encoder */ - 0x47, // sync - 0x40, 0x00, // transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid(0) - 0x10, // transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) + 0x47, /* sync */ + 0x40, 0x00, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid(0) */ + 0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */ - 0x00, // PSI pointer to start of table + 0x00, /* PSI pointer to start of table */ - 0x00, // tid(0) - 0xb0, 0x0d, // section_syntax_indicator(1), section_length(13) + 0x00, /* tid(0) */ + 0xb0, 0x0d, /* section_syntax_indicator(1), section_length(13) */ - 0x00, 0x01, // transport_stream_id(1) + 0x00, 0x01, /* transport_stream_id(1) */ - 0xc1, // version_number(0), current_next_indicator(1) + 0xc1, /* version_number(0), current_next_indicator(1) */ - 0x00, 0x00, // section_number(0), last_section_number(0) + 0x00, 0x00, /* section_number(0), last_section_number(0) */ - 0x00, 0x01, // program_number(1) + 0x00, 0x01, /* program_number(1) */ - 0xe0, 0x00, // PMT PID + 0xe0, 0x00, /* PMT PID */ - 0x00, 0x00, 0x00, 0x00 // CRC32 + 0x00, 0x00, 0x00, 0x00 /* CRC32 */ }; static u8 PMT[] = { - 0xc2, // i2c register - 0x01, // table number for encoder + 0xc2, /* i2c register */ + 0x01, /* table number for encoder */ - 0x47, // sync - 0x40, 0x00, // transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid - 0x10, // transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) + 0x47, /* sync */ + 0x40, 0x00, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid */ + 0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */ - 0x00, // PSI pointer to start of table + 0x00, /* PSI pointer to start of table */ - 0x02, // tid(2) - 0xb0, 0x17, // section_syntax_indicator(1), section_length(23) + 0x02, /* tid(2) */ + 0xb0, 0x17, /* section_syntax_indicator(1), section_length(23) */ - 0x00, 0x01, // program_number(1) + 0x00, 0x01, /* program_number(1) */ - 0xc1, // version_number(0), current_next_indicator(1) + 0xc1, /* version_number(0), current_next_indicator(1) */ - 0x00, 0x00, // section_number(0), last_section_number(0) + 0x00, 0x00, /* section_number(0), last_section_number(0) */ - 0xe0, 0x00, // PCR_PID + 0xe0, 0x00, /* PCR_PID */ - 0xf0, 0x00, // program_info_length(0) + 0xf0, 0x00, /* program_info_length(0) */ - 0x02, 0xe0, 0x00, 0xf0, 0x00, // video stream type(2), pid - 0x04, 0xe0, 0x00, 0xf0, 0x00, // audio stream type(4), pid + 0x02, 0xe0, 0x00, 0xf0, 0x00, /* video stream type(2), pid */ + 0x04, 0xe0, 0x00, 0xf0, 0x00, /* audio stream type(4), pid */ - 0x00, 0x00, 0x00, 0x00 // CRC32 + 0x00, 0x00, 0x00, 0x00 /* CRC32 */ }; static struct v4l2_mpeg_compression param_defaults = @@ -166,7 +167,7 @@ static int saa6752hs_chip_command(struct i2c_client* client, unsigned long timeout; int status = 0; - // execute the command + /* execute the command */ switch(command) { case SAA6752HS_COMMAND_RESET: buf[0] = 0x00; @@ -200,11 +201,11 @@ static int saa6752hs_chip_command(struct i2c_client* client, return -EINVAL; } - // set it and wait for it to be so + /* set it and wait for it to be so */ i2c_master_send(client, buf, 1); timeout = jiffies + HZ * 3; for (;;) { - // get the current status + /* get the current status */ buf[0] = 0x10; i2c_master_send(client, buf, 1); i2c_master_recv(client, buf, 1); @@ -216,14 +217,12 @@ static int saa6752hs_chip_command(struct i2c_client* client, break; } - // wait a bit msleep(10); } - // delay a bit to let encoder settle + /* delay a bit to let encoder settle */ msleep(50); - // done return status; } @@ -233,44 +232,43 @@ static int saa6752hs_set_bitrate(struct i2c_client* client, { u8 buf[3]; - // set the bitrate mode + /* set the bitrate mode */ buf[0] = 0x71; buf[1] = (params->vi_bitrate.mode == V4L2_BITRATE_VBR) ? 0 : 1; i2c_master_send(client, buf, 2); - // set the video bitrate + /* set the video bitrate */ if (params->vi_bitrate.mode == V4L2_BITRATE_VBR) { - // set the target bitrate + /* set the target bitrate */ buf[0] = 0x80; buf[1] = params->vi_bitrate.target >> 8; buf[2] = params->vi_bitrate.target & 0xff; i2c_master_send(client, buf, 3); - // set the max bitrate + /* set the max bitrate */ buf[0] = 0x81; buf[1] = params->vi_bitrate.max >> 8; buf[2] = params->vi_bitrate.max & 0xff; i2c_master_send(client, buf, 3); } else { - // set the target bitrate (no max bitrate for CBR) + /* set the target bitrate (no max bitrate for CBR) */ buf[0] = 0x81; buf[1] = params->vi_bitrate.target >> 8; buf[2] = params->vi_bitrate.target & 0xff; i2c_master_send(client, buf, 3); } - // set the audio bitrate + /* set the audio bitrate */ buf[0] = 0x94; buf[1] = (256 == params->au_bitrate.target) ? 0 : 1; i2c_master_send(client, buf, 2); - // set the total bitrate + /* set the total bitrate */ buf[0] = 0xb1; buf[1] = params->st_bitrate.target >> 8; buf[2] = params->st_bitrate.target & 0xff; i2c_master_send(client, buf, 3); - // return success return 0; } @@ -376,36 +374,43 @@ static int saa6752hs_init(struct i2c_client* client) h = i2c_get_clientdata(client); - // Set video format - must be done first as it resets other settings + /* Set video format - must be done first as it resets other settings */ buf[0] = 0x41; buf[1] = h->video_format; i2c_master_send(client, buf, 2); - // set bitrate + /* Set number of lines in input signal */ + buf[0] = 0x40; + buf[1] = 0x00; + if (h->standard & V4L2_STD_525_60) + buf[1] = 0x01; + i2c_master_send(client, buf, 2); + + /* set bitrate */ saa6752hs_set_bitrate(client, &h->params); - // Set GOP structure {3, 13} + /* Set GOP structure {3, 13} */ buf[0] = 0x72; buf[1] = 0x03; buf[2] = 0x0D; i2c_master_send(client,buf,3); - // Set minimum Q-scale {4} + /* Set minimum Q-scale {4} */ buf[0] = 0x82; buf[1] = 0x04; i2c_master_send(client,buf,2); - // Set maximum Q-scale {12} + /* Set maximum Q-scale {12} */ buf[0] = 0x83; buf[1] = 0x0C; i2c_master_send(client,buf,2); - // Set Output Protocol + /* Set Output Protocol */ buf[0] = 0xD0; buf[1] = 0x81; i2c_master_send(client,buf,2); - // Set video output stream format {TS} + /* Set video output stream format {TS} */ buf[0] = 0xB0; buf[1] = 0x05; i2c_master_send(client,buf,2); @@ -436,39 +441,39 @@ static int saa6752hs_init(struct i2c_client* client) localPMT[sizeof(PMT) - 2] = (crc >> 8) & 0xFF; localPMT[sizeof(PMT) - 1] = crc & 0xFF; - // Set Audio PID + /* Set Audio PID */ buf[0] = 0xC1; buf[1] = (h->params.ts_pid_audio >> 8) & 0xFF; buf[2] = h->params.ts_pid_audio & 0xFF; i2c_master_send(client,buf,3); - // Set Video PID + /* Set Video PID */ buf[0] = 0xC0; buf[1] = (h->params.ts_pid_video >> 8) & 0xFF; buf[2] = h->params.ts_pid_video & 0xFF; i2c_master_send(client,buf,3); - // Set PCR PID + /* Set PCR PID */ buf[0] = 0xC4; buf[1] = (h->params.ts_pid_pcr >> 8) & 0xFF; buf[2] = h->params.ts_pid_pcr & 0xFF; i2c_master_send(client,buf,3); - // Send SI tables + /* Send SI tables */ i2c_master_send(client,localPAT,sizeof(PAT)); i2c_master_send(client,localPMT,sizeof(PMT)); - // mute then unmute audio. This removes buzzing artefacts + /* mute then unmute audio. This removes buzzing artefacts */ buf[0] = 0xa4; buf[1] = 1; i2c_master_send(client, buf, 2); buf[1] = 0; i2c_master_send(client, buf, 2); - // start it going + /* start it going */ saa6752hs_chip_command(client, SAA6752HS_COMMAND_START); - // readout current state + /* readout current state */ buf[0] = 0xE1; buf[1] = 0xA7; buf[2] = 0xFE; @@ -477,7 +482,7 @@ static int saa6752hs_init(struct i2c_client* client) i2c_master_send(client, buf, 5); i2c_master_recv(client, buf2, 4); - // change aspect ratio + /* change aspect ratio */ buf[0] = 0xE0; buf[1] = 0xA7; buf[2] = 0xFE; @@ -498,7 +503,6 @@ static int saa6752hs_init(struct i2c_client* client) buf[8] = buf2[3]; i2c_master_send(client, buf, 9); - // return success return 0; } @@ -516,6 +520,9 @@ static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind) h->client.adapter = adap; h->client.addr = addr; + /* Assume 625 input lines */ + h->standard = 0; + i2c_set_clientdata(&h->client, h); i2c_attach_client(&h->client); return 0; @@ -576,6 +583,9 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) saa6752hs_set_subsampling(client, f); break; } + case VIDIOC_S_STD: + h->standard = *((v4l2_std_id *) arg); + break; default: /* nothing */ break; -- cgit v1.2.3 From 93e960ff2d94a68403f87bbd2e664509bdfefbae Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 8 Nov 2005 21:36:46 -0800 Subject: [PATCH] v4l: 687: fix source charset make symbols utf 8 - Fix source charset. Make symbols UTF-8. Signed-off-by: David Woodhouse . Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bttv-cards.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 5672d0ef2bf..c6010692746 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -1063,7 +1063,7 @@ struct tvcard bttv_tvcards[] = { },{ /* ---- card 0x34 ---------------------------------- */ - /* David Härdeman */ + /* David Härdeman */ .name = "Pinnacle PCTV Studio Pro", .video_inputs = 4, .audio_inputs = 1, @@ -3370,7 +3370,7 @@ void bttv_tda9880_setnorm(struct bttv *btv, int norm) /* * reset/enable the MSP on some Hauppauge cards - * Thanks to Kyösti Mälkki (kmalkki@cc.hut.fi)! + * Thanks to Kyösti Mälkki (kmalkki@cc.hut.fi)! * * Hauppauge: pin 5 * Voodoo: pin 20 -- cgit v1.2.3 From fea095fe4c8f7f615472ee8036fe511b47eec53d Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:36:47 -0800 Subject: [PATCH] v4l: 688: add remote for dvb t300 remote - Add remote for DVB-T300 Remote. Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-cards.c | 1 + drivers/media/video/saa7134/saa7134-input.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 8bb2faf2635..9600305771b 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2807,6 +2807,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) /* case SAA7134_BOARD_SABRENT_SBTTVFM: */ /* not finished yet */ case SAA7134_BOARD_VIDEOMATE_TV_PVR: case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: + case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_MANLI_MTV001: case SAA7134_BOARD_MANLI_MTV002: case SAA7134_BOARD_BEHOLD_409FM: diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index baf16a348f4..b69b18c5f18 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -578,6 +578,11 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keyup = 0x400000; polling = 50; // ms break; + case SAA7134_BOARD_VIDEOMATE_DVBT_300: + ir_codes = videomate_tv_pvr_codes; + mask_keycode = 0x003F00; + mask_keyup = 0x040000; + break; } if (NULL == ir_codes) { printk("%s: Oops: IR config error [card=%d]\n", -- cgit v1.2.3 From 5ea246862863d712bacf3f2c0cb43de7bf1feeba Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:36:48 -0800 Subject: [PATCH] v4l: 689: cx88 cardlist updated now it also includes pci subsystem ids - Cx88 cardlist updated. Now, it also includes PCI subsystem IDs. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.cx88 | 66 ++++++++++++++++----------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index fa7e38567d8..f0b3b49a4fd 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -1,33 +1,33 @@ -card=0 - UNKNOWN/GENERIC -card=1 - Hauppauge WinTV 34xxx models -card=2 - GDI Black Gold -card=3 - PixelView -card=4 - ATI TV Wonder Pro -card=5 - Leadtek Winfast 2000XP Expert -card=6 - AverTV Studio 303 (M126) -card=7 - MSI TV-@nywhere Master -card=8 - Leadtek Winfast DV2000 -card=9 - Leadtek PVR 2000 -card=10 - IODATA GV-VCP3/PCI -card=11 - Prolink PlayTV PVR -card=12 - ASUS PVR-416 -card=13 - MSI TV-@nywhere -card=14 - KWorld/VStream XPert DVB-T -card=15 - DViCO FusionHDTV DVB-T1 -card=16 - KWorld LTV883RF -card=17 - DViCO FusionHDTV 3 Gold-Q -card=18 - Hauppauge Nova-T DVB-T -card=19 - Conexant DVB-T reference design -card=20 - Provideo PV259 -card=21 - DViCO FusionHDTV DVB-T Plus -card=22 - digitalnow DNTV Live! DVB-T -card=23 - pcHDTV HD3000 HDTV -card=24 - Hauppauge WinTV 28xxx (Roslyn) models -card=25 - Digital-Logic MICROSPACE Entertainment Center (MEC) -card=26 - IODATA GV/BCTV7E -card=27 - PixelView PlayTV Ultra Pro (Stereo) -card=28 - DViCO FusionHDTV 3 Gold-T -card=29 - ADS Tech Instant TV DVB-T PCI -card=30 - TerraTec Cinergy 1400 DVB-T -card=31 - DViCO FusionHDTV 5 Gold -card=32 - AverMedia UltraTV Media Center PCI 550 + 0 -> UNKNOWN/GENERIC + 1 -> Hauppauge WinTV 34xxx models [0070:3400,0070:3401] + 2 -> GDI Black Gold [14c7:0106,14c7:0107] + 3 -> PixelView [1554:4811] + 4 -> ATI TV Wonder Pro [1002:00f8] + 5 -> Leadtek Winfast 2000XP Expert [107d:6611,107d:6613] + 6 -> AverTV Studio 303 (M126) [1461:000b] + 7 -> MSI TV-@nywhere Master [1462:8606] + 8 -> Leadtek Winfast DV2000 [107d:6620] + 9 -> Leadtek PVR 2000 [107d:663b,107d:663C] + 10 -> IODATA GV-VCP3/PCI [10fc:d003] + 11 -> Prolink PlayTV PVR + 12 -> ASUS PVR-416 [1043:4823] + 13 -> MSI TV-@nywhere + 14 -> KWorld/VStream XPert DVB-T [17de:08a6] + 15 -> DViCO FusionHDTV DVB-T1 [18ac:db00] + 16 -> KWorld LTV883RF + 17 -> DViCO FusionHDTV 3 Gold-Q [18ac:d810] + 18 -> Hauppauge Nova-T DVB-T [0070:9002] + 19 -> Conexant DVB-T reference design [14f1:0187] + 20 -> Provideo PV259 [1540:2580] + 21 -> DViCO FusionHDTV DVB-T Plus [18ac:db10] + 22 -> pcHDTV HD3000 HDTV [7063:3000] + 23 -> digitalnow DNTV Live! DVB-T [17de:a8a6] + 24 -> Hauppauge WinTV 28xxx (Roslyn) models [0070:2801] + 25 -> Digital-Logic MICROSPACE Entertainment Center (MEC) [14f1:0342] + 26 -> IODATA GV/BCTV7E [10fc:d035] + 27 -> PixelView PlayTV Ultra Pro (Stereo) + 28 -> DViCO FusionHDTV 3 Gold-T [18ac:d820] + 29 -> ADS Tech Instant TV DVB-T PCI [1421:0334] + 30 -> TerraTec Cinergy 1400 DVB-T [153b:1166] + 31 -> DViCO FusionHDTV 5 Gold [18ac:d500] + 32 -> AverMedia UltraTV Media Center PCI 550 [1461:8011] -- cgit v1.2.3 From 058afaf80932445fb33f957d29758479a65932ce Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:36:49 -0800 Subject: [PATCH] v4l: 690: added support for lifeview flytv platinum mini2 - Added support for LifeView FlyTV Platinum Mini2. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 33 +++++++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134.h | 1 + 3 files changed, 35 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 82b5f7c73c8..57439d08157 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -72,3 +72,4 @@ 71 -> Compro Videomate DVB-T200 [185b:c901] 72 -> RTD Embedded Technologies VFG7350 [1435:7350] 73 -> RTD Embedded Technologies VFG7330 [1435:7330] + 74 -> LifeView FlyTV Platinum Mini2 [14c0:1212] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 9600305771b..a096799dc5f 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2319,6 +2319,33 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE2, }}, }, + [SAA7134_BOARD_FLYTVPLATINUM_MINI2] = { + .name = "LifeView FlyTV Platinum Mini2", + .audio_clock = 0x00200000, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, /* Composite signal on S-Video input */ + .vmux = 0, + .amux = LINE2, + },{ + .name = name_comp2, /* Composite input */ + .vmux = 3, + .amux = LINE2, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + }}, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -2399,6 +2426,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x5168, .subdevice = 0x0212, /* minipci, LR212 */ .driver_data = SAA7134_BOARD_FLYTVPLATINUM_MINI, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x14c0, + .subdevice = 0x1212, /* minipci, LR1212 */ + .driver_data = SAA7134_BOARD_FLYTVPLATINUM_MINI2, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 4169c2a857f..e907d86da7b 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -194,6 +194,7 @@ struct saa7134_format { #define SAA7134_BOARD_VIDEOMATE_DVBT_200 71 #define SAA7134_BOARD_RTD_VFG7350 72 #define SAA7134_BOARD_RTD_VFG7330 73 +#define SAA7134_BOARD_FLYTVPLATINUM_MINI2 74 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From 70b6934a6c6b5f242a42978f3c5e4f45d476dddb Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:36:50 -0800 Subject: [PATCH] v4l: 691: set if of tda8275 according to tv norm - Set IF of tda8275 according to tv norm. Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tda8290.c | 21 ++++++++++++++------- include/media/tuner.h | 1 + 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 61268f8a9ee..1e2acc4abbe 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -181,18 +181,25 @@ static void set_audio(struct tuner *t) { t->i2c_easy_mode[0] = 0x01; - if (t->std & V4L2_STD_MN) + if (t->std & V4L2_STD_MN) { + t->sgIF = 736; t->i2c_easy_mode[1] = 0x01; - else if (t->std & V4L2_STD_B) + } else if (t->std & V4L2_STD_B) { + t->sgIF = 864; t->i2c_easy_mode[1] = 0x02; - else if (t->std & V4L2_STD_GH) + } else if (t->std & V4L2_STD_GH) { + t->sgIF = 992; t->i2c_easy_mode[1] = 0x04; - else if (t->std & V4L2_STD_PAL_I) + } else if (t->std & V4L2_STD_PAL_I) { + t->sgIF = 992; t->i2c_easy_mode[1] = 0x08; - else if (t->std & V4L2_STD_DK) + } else if (t->std & V4L2_STD_DK) { + t->sgIF = 992; t->i2c_easy_mode[1] = 0x10; - else if (t->std & V4L2_STD_SECAM_L) + } else if (t->std & V4L2_STD_SECAM_L) { + t->sgIF = 992; t->i2c_easy_mode[1] = 0x20; + } } static void set_tv_freq(struct i2c_client *c, unsigned int freq) @@ -200,7 +207,7 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) struct tuner *t = i2c_get_clientdata(c); set_audio(t); - set_frequency(t, 864, freq); + set_frequency(t, t->sgIF, freq); tda8290_tune(c); } diff --git a/include/media/tuner.h b/include/media/tuner.h index bf925702fbb..97e16bddf65 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -191,6 +191,7 @@ struct tuner { /* used by tda8290 */ unsigned char i2c_easy_mode[2]; unsigned char i2c_set_freq[8]; + unsigned int sgIF; /* function ptrs */ void (*tv_freq)(struct i2c_client *c, unsigned int freq); -- cgit v1.2.3 From 2bfa1ac6ce854a7f895d5c9d6c273ef770fad9ae Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:36:51 -0800 Subject: [PATCH] v4l: 692: bttv coding style and card ids - BTTV Boards now use the same CodingStyle as cx88 and saa7134. - Included missing card numbers Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bttv-cards.c | 4433 ++++++++++++++++++++------------------ 1 file changed, 2296 insertions(+), 2137 deletions(-) diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index c6010692746..12f38e8cd0a 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -309,2143 +309,2303 @@ static struct CARD { /* array with description for bt848 / bt878 tv/grabber cards */ struct tvcard bttv_tvcards[] = { -{ -/* ---- card 0x00 ---------------------------------- */ - .name = " *** UNKNOWN/GENERIC *** ", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .muxsel = { 2, 3, 1, 0}, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - .name = "MIRO PCTV", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 15, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 2, 0, 0, 0, 10}, - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - .name = "Hauppauge (bt848)", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 7, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0, 1, 2, 3, 4}, - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - .name = "STB, Gateway P/N 6000699 (bt848)", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 7, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 4, 0, 2, 3, 1}, - .no_msp34xx = 1, - .needs_tvaudio = 1, - .tuner_type = TUNER_PHILIPS_NTSC, - .tuner_addr = ADDR_UNSET, - .pll = PLL_28, - .has_radio = 1, -},{ - -/* ---- card 0x04 ---------------------------------- */ - .name = "Intel Create and Share PCI/ Smart Video Recorder III", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, - .svhs = 2, - .gpiomask = 0, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0 }, - .needs_tvaudio = 0, - .tuner_type = 4, - .tuner_addr = ADDR_UNSET, -},{ - .name = "Diamond DTV2000", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 3, - .muxsel = { 2, 3, 1, 0}, - .audiomux = { 0, 1, 0, 1, 3}, - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - .name = "AVerMedia TVPhone", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 3, - .muxsel = { 2, 3, 1, 1}, - .gpiomask = 0x0f, - .audiomux = { 0x0c, 0x04, 0x08, 0x04, 0}, - /* 0x04 for some cards ?? */ - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .audio_hook = avermedia_tvphone_audio, - .has_remote = 1, -},{ - .name = "MATRIX-Vision MV-Delta", - .video_inputs = 5, - .audio_inputs = 1, - .tuner = -1, - .svhs = 3, - .gpiomask = 0, - .muxsel = { 2, 3, 1, 0, 0}, - .audiomux = {0 }, - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - -/* ---- card 0x08 ---------------------------------- */ - .name = "Lifeview FlyVideo II (Bt848) LR26 / MAXI TV Video PCI2 LR26", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0xc00, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0, 0xc00, 0x800, 0x400, 0xc00, 0}, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - .name = "IMS/IXmicro TurboTV", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 3, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 1, 1, 2, 3, 0}, - .needs_tvaudio = 0, - .pll = PLL_28, - .tuner_type = TUNER_TEMIC_PAL, - .tuner_addr = ADDR_UNSET, -},{ - .name = "Hauppauge (bt878)", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x0f, /* old: 7 */ - .muxsel = { 2, 0, 1, 1}, - .audiomux = { 0, 1, 2, 3, 4}, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - .name = "MIRO PCTV pro", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x3014f, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0x20001,0x10001, 0, 0,10}, - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - -/* ---- card 0x0c ---------------------------------- */ - .name = "ADS Technologies Channel Surfer TV (bt848)", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 15, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 13, 14, 11, 7, 0, 0}, - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - .name = "AVerMedia TVCapture 98", - .video_inputs = 3, - .audio_inputs = 4, - .tuner = 0, - .svhs = 2, - .gpiomask = 15, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 13, 14, 11, 7, 0, 0}, - .needs_tvaudio = 1, - .msp34xx_alt = 1, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .audio_hook = avermedia_tv_stereo_audio, -},{ - .name = "Aimslab Video Highway Xtreme (VHX)", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 7, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0, 2, 1, 3, 4}, /* old: { 0, 1, 2, 3, 4} */ - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - .name = "Zoltrix TV-Max", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 15, - .muxsel = { 2, 3, 1, 1}, - .audiomux = {0 , 0, 1 , 0, 10}, - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - -/* ---- card 0x10 ---------------------------------- */ - .name = "Prolink Pixelview PlayTV (bt878)", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x01fe00, - .muxsel = { 2, 3, 1, 1}, - /* 2003-10-20 by "Anton A. Arapov" */ - .audiomux = { 0x001e00, 0, 0x018000, 0x014000, 0x002000, 0 }, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, -},{ - .name = "Leadtek WinView 601", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x8300f8, - .muxsel = { 2, 3, 1, 1,0}, - .audiomux = { 0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007}, - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .audio_hook = winview_audio, - .has_radio = 1, -},{ - .name = "AVEC Intercapture", - .video_inputs = 3, - .audio_inputs = 2, - .tuner = 0, - .svhs = 2, - .gpiomask = 0, - .muxsel = {2, 3, 1, 1}, - .audiomux = {1, 0, 0, 0, 0}, - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - .name = "Lifeview FlyVideo II EZ /FlyKit LR38 Bt848 (capture only)", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = -1, - .svhs = -1, - .gpiomask = 0x8dff00, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0 }, - .no_msp34xx = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - -/* ---- card 0x14 ---------------------------------- */ - .name = "CEI Raffles Card", - .video_inputs = 3, - .audio_inputs = 3, - .tuner = 0, - .svhs = 2, - .muxsel = {2, 3, 1, 1}, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - .name = "Lifeview FlyVideo 98/ Lucky Star Image World ConferenceTV LR50", - .video_inputs = 4, - .audio_inputs = 2, /* tuner, line in */ - .tuner = 0, - .svhs = 2, - .gpiomask = 0x1800, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800}, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_PAL_I, - .tuner_addr = ADDR_UNSET, -},{ - .name = "Askey CPH050/ Phoebe Tv Master + FM", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0xc00, - .muxsel = { 2, 3, 1, 1}, - .audiomux = {0, 1, 0x800, 0x400, 0xc00, 0}, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - .name = "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV, bt878", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = -1, - .gpiomask = 7, - .muxsel = { 2, 3, -1 }, - .digital_mode = DIGITAL_MODE_CAMERA, - .audiomux = { 0, 0, 0, 0, 0 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = TUNER_ALPS_TSBB5_PAL_I, - .tuner_addr = ADDR_UNSET, -},{ - -/* ---- card 0x18 ---------------------------------- */ - .name = "Askey CPH05X/06X (bt878) [many vendors]", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0xe00, - .muxsel = { 2, 3, 1, 1}, - .audiomux = {0x400, 0x400, 0x400, 0x400, 0xc00}, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .has_remote = 1, -},{ - .name = "Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x1f0fff, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0x20000, 0x30000, 0x10000, 0, 0x40000}, - .needs_tvaudio = 0, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .audio_hook = terratv_audio, -},{ - .name = "Hauppauge WinCam newer (bt878)", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 3, - .gpiomask = 7, - .muxsel = { 2, 0, 1, 1}, - .audiomux = { 0, 1, 2, 3, 4}, - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - .name = "Lifeview FlyVideo 98/ MAXI TV Video PCI2 LR50", - .video_inputs = 4, - .audio_inputs = 2, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x1800, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800}, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_SECAM, - .tuner_addr = ADDR_UNSET, -},{ - -/* ---- card 0x1c ---------------------------------- */ - .name = "Terratec TerraTV+ Version 1.1 (bt878)", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x1f0fff, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0x20000, 0x30000, 0x10000, 0x00000, 0x40000}, - .needs_tvaudio = 0, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .audio_hook = terratv_audio, - /* GPIO wiring: - External 20 pin connector (for Active Radio Upgrade board) - gpio00: i2c-sda - gpio01: i2c-scl - gpio02: om5610-data - gpio03: om5610-clk - gpio04: om5610-wre - gpio05: om5610-stereo - gpio06: rds6588-davn - gpio07: Pin 7 n.c. - gpio08: nIOW - gpio09+10: nIOR, nSEL ?? (bt878) - gpio09: nIOR (bt848) - gpio10: nSEL (bt848) - Sound Routing: - gpio16: u2-A0 (1st 4052bt) - gpio17: u2-A1 - gpio18: u2-nEN - gpio19: u4-A0 (2nd 4052) - gpio20: u4-A1 - u4-nEN - GND - Btspy: - 00000 : Cdrom (internal audio input) - 10000 : ext. Video audio input - 20000 : TV Mono - a0000 : TV Mono/2 - 1a0000 : TV Stereo - 30000 : Radio - 40000 : Mute -*/ - -},{ - /* Jannik Fritsch */ - .name = "Imagenation PXC200", - .video_inputs = 5, - .audio_inputs = 1, - .tuner = -1, - .svhs = 1, /* was: 4 */ - .gpiomask = 0, - .muxsel = { 2, 3, 1, 0, 0}, - .audiomux = { 0 }, - .needs_tvaudio = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .muxsel_hook = PXC200_muxsel, - -},{ - .name = "Lifeview FlyVideo 98 LR50", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x1800, /* 0x8dfe00 */ - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0, 0x0800, 0x1000, 0x1000, 0x1800, 0 }, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - .name = "Formac iProTV, Formac ProTV I (bt848)", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 3, - .gpiomask = 1, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 1, 0, 0, 0, 0 }, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, -},{ - -/* ---- card 0x20 ---------------------------------- */ - .name = "Intel Create and Share PCI/ Smart Video Recorder III", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, - .svhs = 2, - .gpiomask = 0, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0 }, - .needs_tvaudio = 0, - .tuner_type = 4, - .tuner_addr = ADDR_UNSET, -},{ - .name = "Terratec TerraTValue Version Bt878", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0xffff00, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0x500, 0, 0x300, 0x900, 0x900}, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, -},{ - .name = "Leadtek WinFast 2000/ WinFast 2000 XP", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .muxsel = { 2, 3, 1, 1, 0}, /* TV, CVid, SVid, CVid over SVid connector */ - /* Alexander Varakin [stereo version] */ - .gpiomask = 0xb33000, - .audiomux = { 0x122000,0x1000,0x0000,0x620000,0x800000 }, - /* Audio Routing for "WinFast 2000 XP" (no tv stereo !) - gpio23 -- hef4052:nEnable (0x800000) - gpio12 -- hef4052:A1 - gpio13 -- hef4052:A0 - 0x0000: external audio - 0x1000: FM - 0x2000: TV - 0x3000: n.c. - Note: There exists another variant "Winfast 2000" with tv stereo !? - Note: eeprom only contains FF and pci subsystem id 107d:6606 - */ - .needs_tvaudio = 0, - .pll = PLL_28, - .has_radio = 1, - .tuner_type = 5, /* default for now, gpio reads BFFF06 for Pal bg+dk */ - .tuner_addr = ADDR_UNSET, - .audio_hook = winfast2000_audio, - .has_remote = 1, -},{ - .name = "Lifeview FlyVideo 98 LR50 / Chronos Video Shuttle II", - .video_inputs = 4, - .audio_inputs = 3, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x1800, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800}, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - -/* ---- card 0x24 ---------------------------------- */ - .name = "Lifeview FlyVideo 98FM LR50 / Typhoon TView TV/FM Tuner", - .video_inputs = 4, - .audio_inputs = 3, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x1800, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 }, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .has_radio = 1, -},{ - .name = "Prolink PixelView PlayTV pro", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0xff, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - .name = "Askey CPH06X TView99", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x551e00, - .muxsel = { 2, 3, 1, 0}, - .audiomux = { 0x551400, 0x551200, 0, 0, 0x551c00, 0x551200 }, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = 1, - .tuner_addr = ADDR_UNSET, - .has_remote = 1, -},{ - .name = "Pinnacle PCTV Studio/Rave", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x03000F, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 2, 0xd0001, 0, 0, 1}, - .needs_tvaudio = 0, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - -/* ---- card 0x28 ---------------------------------- */ - .name = "STB TV PCI FM, Gateway P/N 6000704 (bt878), 3Dfx VoodooTV 100", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 7, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 4, 0, 2, 3, 1}, - .no_msp34xx = 1, - .needs_tvaudio = 1, - .tuner_type = TUNER_PHILIPS_NTSC, - .tuner_addr = ADDR_UNSET, - .pll = PLL_28, - .has_radio = 1, -},{ - .name = "AVerMedia TVPhone 98", - .video_inputs = 3, - .audio_inputs = 4, - .tuner = 0, - .svhs = 2, - .gpiomask = 15, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 13, 4, 11, 7, 0, 0}, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .has_radio = 1, - .audio_hook = avermedia_tvphone_audio, -},{ - .name = "ProVideo PV951", /* pic16c54 */ - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0, 0, 0, 0, 0}, - .needs_tvaudio = 1, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = 1, - .tuner_addr = ADDR_UNSET, -},{ - .name = "Little OnAir TV", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0xe00b, - .muxsel = {2, 3, 1, 1}, - .audiomux = {0xff9ff6, 0xff9ff6, 0xff1ff7, 0, 0xff3ffc}, - .no_msp34xx = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - -/* ---- card 0x2c ---------------------------------- */ - .name = "Sigma TVII-FM", - .video_inputs = 2, - .audio_inputs = 1, - .tuner = 0, - .svhs = -1, - .gpiomask = 3, - .muxsel = {2, 3, 1, 1}, - .audiomux = {1, 1, 0, 2, 3}, - .no_msp34xx = 1, - .pll = PLL_NONE, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - .name = "MATRIX-Vision MV-Delta 2", - .video_inputs = 5, - .audio_inputs = 1, - .tuner = -1, - .svhs = 3, - .gpiomask = 0, - .muxsel = { 2, 3, 1, 0, 0}, - .audiomux = {0 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - .name = "Zoltrix Genie TV/FM", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0xbcf03f, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0xbc803f, 0xbc903f, 0xbcb03f, 0, 0xbcb03f}, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = 21, - .tuner_addr = ADDR_UNSET, -},{ - .name = "Terratec TV/Radio+", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x70000, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0x20000, 0x30000, 0x10000, 0, 0x40000, 0x20000 }, - .needs_tvaudio = 1, - .no_msp34xx = 1, - .pll = PLL_35, - .tuner_type = 1, - .tuner_addr = ADDR_UNSET, - .has_radio = 1, -},{ - -/* ---- card 0x30 ---------------------------------- */ - .name = "Askey CPH03x/ Dynalink Magic TView", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 15, - .muxsel = { 2, 3, 1, 1}, - .audiomux = {2,0,0,0,1}, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - .name = "IODATA GV-BCTV3/PCI", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x010f00, - .muxsel = {2, 3, 0, 0}, - .audiomux = {0x10000, 0, 0x10000, 0, 0, 0}, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = TUNER_ALPS_TSHC6_NTSC, - .tuner_addr = ADDR_UNSET, - .audio_hook = gvbctv3pci_audio, -},{ - .name = "Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP", - .video_inputs = 5, - .audio_inputs = 1, - .tuner = 0, - .svhs = 3, - .gpiomask = 0xAA0000, - .muxsel = { 2,3,1,1,-1 }, - .digital_mode = DIGITAL_MODE_CAMERA, - .audiomux = { 0x20000, 0, 0x80000, 0x80000, 0xa8000, 0x46000 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_PAL_I, - .tuner_addr = ADDR_UNSET, - .has_remote = 1, - /* GPIO wiring: (different from Rev.4C !) - GPIO17: U4.A0 (first hef4052bt) - GPIO19: U4.A1 - GPIO20: U5.A1 (second hef4052bt) - GPIO21: U4.nEN - GPIO22: BT832 Reset Line - GPIO23: A5,A0, U5,nEN - Note: At i2c=0x8a is a Bt832 chip, which changes to 0x88 after being reset via GPIO22 - */ -},{ - .name = "Eagle Wireless Capricorn2 (bt878A)", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 7, - .muxsel = { 2, 0, 1, 1}, - .audiomux = { 0, 1, 2, 3, 4}, - .pll = PLL_28, - .tuner_type = -1 /* TUNER_ALPS_TMDH2_NTSC */, - .tuner_addr = ADDR_UNSET, -},{ - -/* ---- card 0x34 ---------------------------------- */ - /* David Härdeman */ - .name = "Pinnacle PCTV Studio Pro", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 3, - .gpiomask = 0x03000F, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 1, 0xd0001, 0, 0, 10}, - /* sound path (5 sources): - MUX1 (mask 0x03), Enable Pin 0x08 (0=enable, 1=disable) - 0= ext. Audio IN - 1= from MUX2 - 2= Mono TV sound from Tuner - 3= not connected - MUX2 (mask 0x30000): - 0,2,3= from MSP34xx - 1= FM stereo Radio from Tuner */ - .needs_tvaudio = 0, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - /* Claas Langbehn , - Sven Grothklags */ - .name = "Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS", - .video_inputs = 4, - .audio_inputs = 3, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x1c, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0, 0, 0x10, 8, 4 }, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .has_radio = 1, -},{ - /* Tim Röstermundt - in de.comp.os.unix.linux.hardware: - options bttv card=0 pll=1 radio=1 gpiomask=0x18e0 - audiomux=0x44c71f,0x44d71f,0,0x44d71f,0x44dfff - options tuner type=5 */ - .name = "Lifeview FlyVideo 2000 /FlyVideo A2/ Lifetec LT 9415 TV [LR90]", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x18e0, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0x0000,0x0800,0x1000,0x1000,0x18e0 }, - /* For cards with tda9820/tda9821: - 0x0000: Tuner normal stereo - 0x0080: Tuner A2 SAP (second audio program = Zweikanalton) - 0x0880: Tuner A2 stereo */ - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - /* Miguel Angel Alvarez - old Easy TV BT848 version (model CPH031) */ - .name = "Askey CPH031/ BESTBUY Easy TV", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0xF, - .muxsel = { 2, 3, 1, 0}, - .audiomux = { 2, 0, 0, 0, 10}, - .needs_tvaudio = 0, - .pll = PLL_28, - .tuner_type = TUNER_TEMIC_PAL, - .tuner_addr = ADDR_UNSET, -},{ - -/* ---- card 0x38 ---------------------------------- */ - /* Gordon Heydon */ - .name = "GrandTec 'Grand Video Capture' (Bt848)", - .video_inputs = 2, - .audio_inputs = 0, - .tuner = -1, - .svhs = 1, - .gpiomask = 0, - .muxsel = { 3, 1 }, - .audiomux = { 0 }, - .needs_tvaudio = 0, - .no_msp34xx = 1, - .pll = PLL_35, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - /* Daniel Herrington */ - .name = "Askey CPH060/ Phoebe TV Master Only (No FM)", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0xe00, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0x400, 0x400, 0x400, 0x400, 0x800, 0x400 }, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = TUNER_TEMIC_4036FY5_NTSC, - .tuner_addr = ADDR_UNSET, -},{ - /* Matti Mottus */ - .name = "Askey CPH03x TV Capturer", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x03000F, - .muxsel = { 2, 3, 1, 0}, - .audiomux = { 2,0,0,0,1 }, - .pll = PLL_28, - .tuner_type = 0, - .tuner_addr = ADDR_UNSET, -},{ - -/* ---- card 0x3c ---------------------------------- */ - /* Philip Blundell */ - .name = "Modular Technology MM100PCTV", - .video_inputs = 2, - .audio_inputs = 2, - .tuner = 0, - .svhs = -1, - .gpiomask = 11, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 2, 0, 0, 1, 8}, - .pll = PLL_35, - .tuner_type = TUNER_TEMIC_PAL, - .tuner_addr = ADDR_UNSET, -},{ - /* Adrian Cox - new Easy TV BT878 version (model CPH061) - special thanks to Informatica Mieres for providing the card */ - .name = "Askey CPH061/ BESTBUY Easy TV (bt878)", - .video_inputs = 3, - .audio_inputs = 2, - .tuner = 0, - .svhs = 2, - .gpiomask = 0xFF, - .muxsel = { 2, 3, 1, 0}, - .audiomux = { 1, 0, 4, 4, 9}, - .needs_tvaudio = 0, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, -},{ - /* Lukas Gebauer */ - .name = "ATI TV-Wonder", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0xf03f, - .muxsel = { 2, 3, 1, 0 }, - .audiomux = { 0xbffe, 0, 0xbfff, 0, 0xbffe}, - .pll = PLL_28, - .tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL, - .tuner_addr = ADDR_UNSET, -},{ - -/* ---- card 0x40 ---------------------------------- */ - /* Lukas Gebauer */ - .name = "ATI TV-Wonder VE", - .video_inputs = 2, - .audio_inputs = 1, - .tuner = 0, - .svhs = -1, - .gpiomask = 1, - .muxsel = { 2, 3, 0, 1}, - .audiomux = { 0, 0, 1, 0, 0}, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL, - .tuner_addr = ADDR_UNSET, -},{ - /* DeeJay */ - .name = "IODATA GV-BCTV4/PCI", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x010f00, - .muxsel = {2, 3, 0, 0}, - .audiomux = {0x10000, 0, 0x10000, 0, 0, 0}, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = TUNER_SHARP_2U5JF5540_NTSC, - .tuner_addr = ADDR_UNSET, - .audio_hook = gvbctv3pci_audio, -},{ - -/* ---- card 0x44 ---------------------------------- */ - .name = "3Dfx VoodooTV FM (Euro), VoodooTV 200 (USA)", - /* try "insmod msp3400 simple=0" if you have - * sound problems with this card. */ - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = -1, - .gpiomask = 0x4f8a00, - /* 0x100000: 1=MSP enabled (0=disable again) - * 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC) */ - .audiomux = {0x947fff, 0x987fff,0x947fff,0x947fff, 0x947fff}, - /* tvtuner, radio, external,internal, mute, stereo - * tuner, Composit, SVid, Composit-on-Svid-adapter */ - .muxsel = { 2, 3 ,0 ,1}, - .tuner_type = TUNER_MT2032, - .tuner_addr = ADDR_UNSET, - .pll = PLL_28, - .has_radio = 1, -},{ - /* Philip Blundell */ - .name = "Active Imaging AIMMS", - .video_inputs = 1, - .audio_inputs = 0, - .tuner = -1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .pll = PLL_28, - .muxsel = { 2 }, - .gpiomask = 0 -},{ - /* Tomasz Pyra */ - .name = "Prolink Pixelview PV-BT878P+ (Rev.4C,8E)", - .video_inputs = 3, - .audio_inputs = 4, - .tuner = 0, - .svhs = 2, - .gpiomask = 15, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0, 0, 11, 7, 13, 0}, /* TV and Radio with same GPIO ! */ - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = 25, - .tuner_addr = ADDR_UNSET, - .has_remote = 1, - /* GPIO wiring: - GPIO0: U4.A0 (hef4052bt) - GPIO1: U4.A1 - GPIO2: U4.A1 (second hef4052bt) - GPIO3: U4.nEN, U5.A0, A5.nEN - GPIO8-15: vrd866b ? - */ -},{ - .name = "Lifeview FlyVideo 98EZ (capture only) LR51", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, - .svhs = 2, - .muxsel = { 2, 3, 1, 1}, /* AV1, AV2, SVHS, CVid adapter on SVHS */ - .pll = PLL_28, - .no_msp34xx = 1, - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, -},{ - -/* ---- card 0x48 ---------------------------------- */ - /* Dariusz Kowalewski */ - .name = "Prolink Pixelview PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM)", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x3f, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0x01, 0x00, 0x03, 0x03, 0x09, 0x02 }, - .needs_tvaudio = 1, - .no_msp34xx = 1, - .no_tda9875 = 1, - .pll = PLL_28, - .tuner_type = 5, - .tuner_addr = ADDR_UNSET, - .audio_hook = pvbt878p9b_audio, /* Note: not all cards have stereo */ - .has_radio = 1, /* Note: not all cards have radio */ - .has_remote = 1, - /* GPIO wiring: - GPIO0: A0 hef4052 - GPIO1: A1 hef4052 - GPIO3: nEN hef4052 - GPIO8-15: vrd866b - GPIO20,22,23: R30,R29,R28 - */ -},{ - /* Clay Kunz */ - /* you must jumper JP5 for the card to work */ - .name = "Sensoray 311", - .video_inputs = 5, - .audio_inputs = 0, - .tuner = -1, - .svhs = 4, - .gpiomask = 0, - .muxsel = { 2, 3, 1, 0, 0}, - .audiomux = { 0 }, - .needs_tvaudio = 0, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - /* Miguel Freitas */ - .name = "RemoteVision MX (RV605)", - .video_inputs = 16, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .gpiomask = 0x00, - .gpiomask2 = 0x07ff, - .muxsel = { 0x33, 0x13, 0x23, 0x43, 0xf3, 0x73, 0xe3, 0x03, - 0xd3, 0xb3, 0xc3, 0x63, 0x93, 0x53, 0x83, 0xa3 }, - .no_msp34xx = 1, - .no_tda9875 = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .muxsel_hook = rv605_muxsel, -},{ - .name = "Powercolor MTV878/ MTV878R/ MTV878F", - .video_inputs = 3, - .audio_inputs = 2, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x1C800F, /* Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset */ - .muxsel = { 2, 1, 1, }, - .audiomux = { 0, 1, 2, 2, 4 }, - .needs_tvaudio = 0, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .pll = PLL_28, - .has_radio = 1, -},{ - -/* ---- card 0x4c ---------------------------------- */ - /* Masaki Suzuki */ - .name = "Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP)", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x140007, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 1, 2, 3, 4, 0 }, - .tuner_type = TUNER_PHILIPS_NTSC, - .tuner_addr = ADDR_UNSET, - .audio_hook = windvr_audio, -},{ - .name = "GrandTec Multi Capture Card (Bt878)", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .gpiomask = 0, - .muxsel = { 2, 3, 1, 0 }, - .audiomux = { 0 }, - .needs_tvaudio = 0, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - .name = "Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF", - .video_inputs = 4, - .audio_inputs = 3, - .tuner = 0, - .svhs = 2, - .gpiomask = 7, - .muxsel = { 2, 3, 1, 1 }, /* Tuner, SVid, SVHS, SVid to SVHS connector */ - .audiomux = { 0 ,0 ,4, 4,4,4},/* Yes, this tuner uses the same audio output for TV and FM radio! - * This card lacks external Audio In, so we mute it on Ext. & Int. - * The PCB can take a sbx1637/sbx1673, wiring unknown. - * This card lacks PCI subsystem ID, sigh. - * audiomux=1: lower volume, 2+3: mute - * btwincap uses 0x80000/0x80003 - */ - .needs_tvaudio = 0, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = 5, - .tuner_addr = ADDR_UNSET, - /* Samsung TCPA9095PC27A (BG+DK), philips compatible, w/FM, stereo and - radio signal strength indicators work fine. */ - .has_radio = 1, - /* GPIO Info: - GPIO0,1: HEF4052 A0,A1 - GPIO2: HEF4052 nENABLE - GPIO3-7: n.c. - GPIO8-13: IRDC357 data0-5 (data6 n.c. ?) [chip not present on my card] - GPIO14,15: ?? - GPIO16-21: n.c. - GPIO22,23: ?? - ?? : mtu8b56ep microcontroller for IR (GPIO wiring unknown)*/ -},{ - /* Arthur Tetzlaff-Deas, DSP Design Ltd */ - .name = "DSP Design TCVIDEO", - .video_inputs = 4, - .svhs = -1, - .muxsel = { 2, 3, 1, 0}, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - - /* ---- card 0x50 ---------------------------------- */ - .name = "Hauppauge WinTV PVR", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .muxsel = { 2, 0, 1, 1}, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - - .gpiomask = 7, - .audiomux = {7}, -},{ - .name = "IODATA GV-BCTV5/PCI", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x0f0f80, - .muxsel = {2, 3, 1, 0}, - .audiomux = {0x030000, 0x010000, 0, 0, 0x020000, 0}, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_NTSC_M, - .tuner_addr = ADDR_UNSET, - .audio_hook = gvbctv5pci_audio, - .has_radio = 1, -},{ - .name = "Osprey 100/150 (878)", /* 0x1(2|3)-45C6-C1 */ - .video_inputs = 4, /* id-inputs-clock */ - .audio_inputs = 0, - .tuner = -1, - .svhs = 3, - .muxsel = { 3, 2, 0, 1 }, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, -},{ - .name = "Osprey 100/150 (848)", /* 0x04-54C0-C1 & older boards */ - .video_inputs = 3, - .audio_inputs = 0, - .tuner = -1, - .svhs = 2, - .muxsel = { 2, 3, 1 }, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, -},{ - - /* ---- card 0x54 ---------------------------------- */ - .name = "Osprey 101 (848)", /* 0x05-40C0-C1 */ - .video_inputs = 2, - .audio_inputs = 0, - .tuner = -1, - .svhs = 1, - .muxsel = { 3, 1 }, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, -},{ - .name = "Osprey 101/151", /* 0x1(4|5)-0004-C4 */ - .video_inputs = 1, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .muxsel = { 0 }, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, -},{ - .name = "Osprey 101/151 w/ svid", /* 0x(16|17|20)-00C4-C1 */ - .video_inputs = 2, - .audio_inputs = 0, - .tuner = -1, - .svhs = 1, - .muxsel = { 0, 1 }, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, -},{ - .name = "Osprey 200/201/250/251", /* 0x1(8|9|E|F)-0004-C4 */ - .video_inputs = 1, - .audio_inputs = 1, - .tuner = -1, - .svhs = -1, - .muxsel = { 0 }, - .pll = PLL_28, - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, -},{ - - /* ---- card 0x58 ---------------------------------- */ - .name = "Osprey 200/250", /* 0x1(A|B)-00C4-C1 */ - .video_inputs = 2, - .audio_inputs = 1, - .tuner = -1, - .svhs = 1, - .muxsel = { 0, 1 }, - .pll = PLL_28, - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, -},{ - .name = "Osprey 210/220", /* 0x1(A|B)-04C0-C1 */ - .video_inputs = 2, - .audio_inputs = 1, - .tuner = -1, - .svhs = 1, - .muxsel = { 2, 3 }, - .pll = PLL_28, - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, -},{ - .name = "Osprey 500", /* 500 */ - .video_inputs = 2, - .audio_inputs = 1, - .tuner = -1, - .svhs = 1, - .muxsel = { 2, 3 }, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, -},{ - .name = "Osprey 540", /* 540 */ - .video_inputs = 4, - .audio_inputs = 1, - .tuner = -1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, -},{ - - /* ---- card 0x5C ---------------------------------- */ - .name = "Osprey 2000", /* 2000 */ - .video_inputs = 2, - .audio_inputs = 1, - .tuner = -1, - .svhs = 1, - .muxsel = { 2, 3 }, - .pll = PLL_28, - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, /* must avoid, conflicts with the bt860 */ -},{ - /* M G Berberich */ - .name = "IDS Eagle", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .svhs = -1, - .gpiomask = 0, - .muxsel = { 0, 1, 2, 3 }, - .muxsel_hook = eagle_muxsel, - .no_msp34xx = 1, - .no_tda9875 = 1, - .pll = PLL_28, -},{ - .name = "Pinnacle PCTV Sat", - .video_inputs = 2, - .audio_inputs = 0, - .svhs = 1, - .tuner = -1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .muxsel = { 3, 0, 1, 2}, - .pll = PLL_28, - .no_gpioirq = 1, - .has_dvb = 1, -},{ - .name = "Formac ProTV II (bt878)", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 3, - .gpiomask = 2, - /* TV, Comp1, Composite over SVID con, SVID */ - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 2, 2, 0, 0, 0 }, - .pll = PLL_28, - .has_radio = 1, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, -/* sound routing: - GPIO=0x00,0x01,0x03: mute (?) - 0x02: both TV and radio (tuner: FM1216/I) - The card has onboard audio connectors labeled "cdrom" and "board", - not soldered here, though unknown wiring. - Card lacks: external audio in, pci subsystem id. -*/ -},{ - - /* ---- card 0x60 ---------------------------------- */ - .name = "MachTV", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = -1, - .gpiomask = 7, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0, 1, 2, 3, 4}, - .needs_tvaudio = 1, - .tuner_type = 5, - .tuner_addr = ADDR_UNSET, - .pll = 1, -},{ - .name = "Euresys Picolo", - .video_inputs = 3, - .audio_inputs = 0, - .tuner = -1, - .svhs = 2, - .gpiomask = 0, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .muxsel = { 2, 0, 1}, - .pll = PLL_28, - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, -},{ - /* Luc Van Hoeylandt */ - .name = "ProVideo PV150", /* 0x4f */ - .video_inputs = 2, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .gpiomask = 0, - .muxsel = { 2, 3 }, - .audiomux = { 0 }, - .needs_tvaudio = 0, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, -},{ - /* Hiroshi Takekawa */ - /* This card lacks subsystem ID */ - .name = "AD-TVK503", /* 0x63 */ - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x001e8007, - .muxsel = { 2, 3, 1, 0 }, - /* Tuner, Radio, external, internal, off, on */ - .audiomux = { 0x08, 0x0f, 0x0a, 0x08, 0x0f, 0x08 }, - .needs_tvaudio = 0, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = 2, - .tuner_addr = ADDR_UNSET, - .audio_hook = adtvk503_audio, -},{ - - /* ---- card 0x64 ---------------------------------- */ - .name = "Hercules Smart TV Stereo", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x00, - .muxsel = { 2, 3, 1, 1 }, - .needs_tvaudio = 1, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = 5, - .tuner_addr = ADDR_UNSET, - /* Notes: - - card lacks subsystem ID - - stereo variant w/ daughter board with tda9874a @0xb0 - - Audio Routing: - always from tda9874 independent of GPIO (?) - external line in: unknown - - Other chips: em78p156elp @ 0x96 (probably IR remote control) - hef4053 (instead 4052) for unknown function - */ -},{ - .name = "Pace TV & Radio Card", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .muxsel = { 2, 3, 1, 1}, /* Tuner, CVid, SVid, CVid over SVid connector */ - .gpiomask = 0, - .no_tda9875 = 1, - .no_tda7432 = 1, - .tuner_type = 1, - .tuner_addr = ADDR_UNSET, - .has_radio = 1, - .pll = PLL_28, - /* Bt878, Bt832, FI1246 tuner; no pci subsystem id - only internal line out: (4pin header) RGGL - Radio must be decoded by msp3410d (not routed through)*/ - /* - .digital_mode = DIGITAL_MODE_CAMERA, todo! - */ -},{ - /* Chris Willing */ - .name = "IVC-200", - .video_inputs = 1, - .audio_inputs = 0, - .tuner = -1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .svhs = -1, - .gpiomask = 0xdf, - .muxsel = { 2 }, - .pll = PLL_28, -},{ - .name = "Grand X-Guard / Trust 814PCI", - .video_inputs = 16, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .tuner_type = 4, - .tuner_addr = ADDR_UNSET, - .gpiomask2 = 0xff, - .muxsel = { 2,2,2,2, 3,3,3,3, 1,1,1,1, 0,0,0,0 }, - .muxsel_hook = xguard_muxsel, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .pll = PLL_28, -},{ - - /* ---- card 0x68 ---------------------------------- */ - .name = "Nebula Electronics DigiTV", - .video_inputs = 1, - .tuner = -1, - .svhs = -1, - .muxsel = { 2, 3, 1, 0}, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .has_dvb = 1, - .no_gpioirq = 1, -},{ - /* Jorge Boncompte - DTI2 */ - .name = "ProVideo PV143", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .gpiomask = 0, - .muxsel = { 2, 3, 1, 0 }, - .audiomux = { 0 }, - .needs_tvaudio = 0, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - /* M.Klahr@phytec.de */ - .name = "PHYTEC VD-009-X1 MiniDIN (bt878)", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, /* card has no tuner */ - .svhs = 3, - .gpiomask = 0x00, - .muxsel = { 2, 3, 1, 0}, - .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - .name = "PHYTEC VD-009-X1 Combi (bt878)", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, /* card has no tuner */ - .svhs = 3, - .gpiomask = 0x00, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - - /* ---- card 0x6c ---------------------------------- */ - .name = "PHYTEC VD-009 MiniDIN (bt878)", - .video_inputs = 10, - .audio_inputs = 0, - .tuner = -1, /* card has no tuner */ - .svhs = 9, - .gpiomask = 0x00, - .gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio - via the upper nibble of muxsel. here: used for - xternal video-mux */ - .muxsel = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x00 }, - .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - .name = "PHYTEC VD-009 Combi (bt878)", - .video_inputs = 10, - .audio_inputs = 0, - .tuner = -1, /* card has no tuner */ - .svhs = 9, - .gpiomask = 0x00, - .gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio - via the upper nibble of muxsel. here: used for - xternal video-mux */ - .muxsel = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x01 }, - .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - .name = "IVC-100", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .svhs = -1, - .gpiomask = 0xdf, - .muxsel = { 2, 3, 1, 0 }, - .pll = PLL_28, -},{ - /* IVC-120G - Alan Garfield */ - .name = "IVC-120G", - .video_inputs = 16, - .audio_inputs = 0, /* card has no audio */ - .tuner = -1, /* card has no tuner */ - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .svhs = -1, /* card has no svhs */ - .needs_tvaudio = 0, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .gpiomask = 0x00, - .muxsel = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 }, - .muxsel_hook = ivc120_muxsel, - .pll = PLL_28, -},{ - - /* ---- card 0x70 ---------------------------------- */ - .name = "pcHDTV HD-2000 TV", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .muxsel = { 2, 3, 1, 0}, - .tuner_type = TUNER_PHILIPS_ATSC, - .tuner_addr = ADDR_UNSET, - .has_dvb = 1, -},{ - .name = "Twinhan DST + clones", - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .tuner_type = TUNER_ABSENT, - .tuner_addr = ADDR_UNSET, - .no_video = 1, - .has_dvb = 1, -},{ - .name = "Winfast VC100", - .video_inputs = 3, - .audio_inputs = 0, - .svhs = 1, - .tuner = -1, - .muxsel = { 3, 1, 1, 3}, /* Vid In, SVid In, Vid over SVid in connector */ - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .tuner_type = TUNER_ABSENT, - .tuner_addr = ADDR_UNSET, - .pll = PLL_28, -},{ - .name = "Teppro TEV-560/InterVision IV-560", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 3, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 1, 1, 1, 1, 0}, - .needs_tvaudio = 1, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .pll = PLL_35, -},{ - - /* ---- card 0x74 ---------------------------------- */ - .name = "SIMUS GVC1100", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .pll = PLL_28, - .muxsel = { 2, 2, 2, 2}, - .gpiomask = 0x3F, - .muxsel_hook = gvc1100_muxsel, -},{ - /* Carlos Silva r3pek@r3pek.homelinux.org || card 0x75 */ - .name = "NGS NGSTV+", - .video_inputs = 3, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x008007, - .muxsel = {2, 3, 0, 0}, - .audiomux = {0, 0, 0, 0, 0x000003, 0}, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .has_remote = 1, -},{ - /* http://linuxmedialabs.com */ - .name = "LMLBT4", - .video_inputs = 4, /* IN1,IN2,IN3,IN4 */ - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .muxsel = { 2, 3, 1, 0 }, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .needs_tvaudio = 0, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - /* Helmroos Harri */ - .name = "Tekram M205 PRO", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .svhs = 2, - .needs_tvaudio = 0, - .gpiomask = 0x68, - .muxsel = { 2, 3, 1}, - .audiomux = { 0x68, 0x68, 0x61, 0x61, 0x00 }, - .pll = PLL_28, -},{ - - /* ---- card 0x78 ---------------------------------- */ - /* Javier Cendan Ares */ - /* bt878 TV + FM without subsystem ID */ - .name = "Conceptronic CONTVFMi", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x008007, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 1, 2, 2, 3 }, - .needs_tvaudio = 0, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .has_remote = 1, - .has_radio = 1, -},{ - /*Eric DEBIEF */ - /*EURESYS Picolo Tetra : 4 Conexant Fusion 878A, no audio, video input set with analog multiplexers GPIO controled*/ - /* adds picolo_tetra_muxsel(), picolo_tetra_init(), the folowing declaration strucure, and #define BTTV_PICOLO_TETRA_CHIP*/ - /*0x79 in bttv.h*/ - .name = "Euresys Picolo Tetra", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .gpiomask = 0, - .gpiomask2 = 0x3C<<16,/*Set the GPIO[18]->GPIO[21] as output pin.==> drive the video inputs through analog multiplexers*/ - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .muxsel = {2,2,2,2},/*878A input is always MUX0, see above.*/ - .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ - .pll = PLL_28, - .needs_tvaudio = 0, - .muxsel_hook = picolo_tetra_muxsel,/*Required as it doesn't follow the classic input selection policy*/ - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - /* Spirit TV Tuner from http://spiritmodems.com.au */ - /* Stafford Goodsell */ - .name = "Spirit TV Tuner", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x0000000f, - .muxsel = { 2, 1, 1 }, - .audiomux = { 0x02, 0x00, 0x00, 0x00, 0x00}, - .tuner_type = TUNER_TEMIC_PAL, - .tuner_addr = ADDR_UNSET, - .no_msp34xx = 1, - .no_tda9875 = 1, -},{ - /* Wolfram Joost */ - .name = "AVerMedia AVerTV DVB-T 771", - .video_inputs = 2, - .svhs = 1, - .tuner = -1, - .tuner_type = TUNER_ABSENT, - .tuner_addr = ADDR_UNSET, - .muxsel = { 3 , 3 }, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .pll = PLL_28, - .has_dvb = 1, - .no_gpioirq = 1, - .has_remote = 1, -},{ - /* ---- card 0x7c ---------------------------------- */ - /* Matt Jesson */ - /* Based on the Nebula card data - added remote and new card number - BTTV_AVDVBT_761, see also ir-kbd-gpio.c */ - .name = "AverMedia AverTV DVB-T 761", - .video_inputs = 2, - .tuner = -1, - .svhs = 1, - .muxsel = { 3, 1, 2, 0}, /* Comp0, S-Video, ?, ? */ - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .has_dvb = 1, - .no_gpioirq = 1, - .has_remote = 1, -},{ - /* andre.schwarz@matrix-vision.de */ - .name = "MATRIX Vision Sigma-SQ", - .video_inputs = 16, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .gpiomask = 0x0, - .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3 }, - .muxsel_hook = sigmaSQ_muxsel, - .audiomux = { 0 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - /* andre.schwarz@matrix-vision.de */ - .name = "MATRIX Vision Sigma-SLC", - .video_inputs = 4, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .gpiomask = 0x0, - .muxsel = { 2, 2, 2, 2 }, - .muxsel_hook = sigmaSLC_muxsel, - .audiomux = { 0 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - /* BTTV_APAC_VIEWCOMP */ - /* Attila Kondoros */ - /* bt878 TV + FM 0x00000000 subsystem ID */ - .name = "APAC Viewcomp 878(AMAX)", - .video_inputs = 2, - .audio_inputs = 1, - .tuner = 0, - .svhs = -1, - .gpiomask = 0xFF, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 2, 0, 0, 0, 10}, - .needs_tvaudio = 0, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_PAL, - .tuner_addr = ADDR_UNSET, - .has_remote = 1, /* miniremote works, see ir-kbd-gpio.c */ - .has_radio = 1, /* not every card has radio */ -},{ - - /* ---- card 0x80 ---------------------------------- */ - /* Chris Pascoe */ - .name = "DViCO FusionHDTV DVB-T Lite", - .tuner = -1, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .pll = PLL_28, - .no_video = 1, - .has_dvb = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, -},{ - /* Steven */ - .name = "V-Gear MyVCD", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x3f, - .muxsel = {2, 3, 1, 0}, - .audiomux = {0x31, 0x31, 0x31, 0x31, 0x31, 0x31}, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_NTSC_M, - .tuner_addr = ADDR_UNSET, - .has_radio = 0, -},{ - /* Rick C */ - .name = "Super TV Tuner", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .muxsel = { 2, 3, 1, 0}, - .tuner_type = TUNER_PHILIPS_NTSC, - .tuner_addr = ADDR_UNSET, - .gpiomask = 0x008007, - .audiomux = { 0, 0x000001,0,0, 0}, - .needs_tvaudio = 1, - .has_radio = 1, -},{ - /* Chris Fanning */ - .name = "Tibet Systems 'Progress DVR' CS16", - .video_inputs = 16, - .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, - .pll = PLL_28, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .muxsel_hook = tibetCS16_muxsel, -}, -{ - /* Bill Brack */ - /* - * Note that, because of the card's wiring, the "master" - * BT878A chip (i.e. the one which controls the analog switch - * and must use this card type) is the 2nd one detected. The - * other 3 chips should use card type 0x85, whose description - * follows this one. There is a EEPROM on the card (which is - * connected to the I2C of one of those other chips), but is - * not currently handled. There is also a facility for a - * "monitor", which is also not currently implemented. + [BTTV_UNKNOWN] = { + /* ---- card 0x00 ---------------------------------- */ + .name = " *** UNKNOWN/GENERIC *** ", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .muxsel = { 2, 3, 1, 0}, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_MIRO] = { + .name = "MIRO PCTV", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 15, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 2, 0, 0, 0, 10}, + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_HAUPPAUGE] = { + .name = "Hauppauge (bt848)", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 7, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0, 1, 2, 3, 4}, + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_STB] = { + .name = "STB, Gateway P/N 6000699 (bt848)", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 7, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 4, 0, 2, 3, 1}, + .no_msp34xx = 1, + .needs_tvaudio = 1, + .tuner_type = TUNER_PHILIPS_NTSC, + .tuner_addr = ADDR_UNSET, + .pll = PLL_28, + .has_radio = 1, + }, + + /* ---- card 0x04 ---------------------------------- */ + [BTTV_INTEL] = { + .name = "Intel Create and Share PCI/ Smart Video Recorder III", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .svhs = 2, + .gpiomask = 0, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0 }, + .needs_tvaudio = 0, + .tuner_type = 4, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_DIAMOND] = { + .name = "Diamond DTV2000", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 3, + .muxsel = { 2, 3, 1, 0}, + .audiomux = { 0, 1, 0, 1, 3}, + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_AVERMEDIA] = { + .name = "AVerMedia TVPhone", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 3, + .muxsel = { 2, 3, 1, 1}, + .gpiomask = 0x0f, + .audiomux = { 0x0c, 0x04, 0x08, 0x04, 0}, + /* 0x04 for some cards ?? */ + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .audio_hook = avermedia_tvphone_audio, + .has_remote = 1, + }, + [BTTV_MATRIX_VISION] = { + .name = "MATRIX-Vision MV-Delta", + .video_inputs = 5, + .audio_inputs = 1, + .tuner = -1, + .svhs = 3, + .gpiomask = 0, + .muxsel = { 2, 3, 1, 0, 0}, + .audiomux = {0 }, + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + + /* ---- card 0x08 ---------------------------------- */ + [BTTV_FLYVIDEO] = { + .name = "Lifeview FlyVideo II (Bt848) LR26 / MAXI TV Video PCI2 LR26", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0xc00, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0, 0xc00, 0x800, 0x400, 0xc00, 0}, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_TURBOTV] = { + .name = "IMS/IXmicro TurboTV", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 3, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 1, 1, 2, 3, 0}, + .needs_tvaudio = 0, + .pll = PLL_28, + .tuner_type = TUNER_TEMIC_PAL, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_HAUPPAUGE878] = { + .name = "Hauppauge (bt878)", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x0f, /* old: 7 */ + .muxsel = { 2, 0, 1, 1}, + .audiomux = { 0, 1, 2, 3, 4}, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_MIROPRO] = { + .name = "MIRO PCTV pro", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x3014f, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0x20001,0x10001, 0, 0,10}, + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + + /* ---- card 0x0c ---------------------------------- */ + [BTTV_ADSTECH_TV] = { + .name = "ADS Technologies Channel Surfer TV (bt848)", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 15, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 13, 14, 11, 7, 0, 0}, + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_AVERMEDIA98] = { + .name = "AVerMedia TVCapture 98", + .video_inputs = 3, + .audio_inputs = 4, + .tuner = 0, + .svhs = 2, + .gpiomask = 15, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 13, 14, 11, 7, 0, 0}, + .needs_tvaudio = 1, + .msp34xx_alt = 1, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .audio_hook = avermedia_tv_stereo_audio, + }, + [BTTV_VHX] = { + .name = "Aimslab Video Highway Xtreme (VHX)", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 7, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0, 2, 1, 3, 4}, /* old: { 0, 1, 2, 3, 4} */ + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_ZOLTRIX] = { + .name = "Zoltrix TV-Max", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 15, + .muxsel = { 2, 3, 1, 1}, + .audiomux = {0 , 0, 1 , 0, 10}, + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + + /* ---- card 0x10 ---------------------------------- */ + [BTTV_PIXVIEWPLAYTV] = { + .name = "Prolink Pixelview PlayTV (bt878)", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x01fe00, + .muxsel = { 2, 3, 1, 1}, + #if 0 + /* old */ + .audiomux = { 0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 }, + #else + /* 2003-10-20 by "Anton A. Arapov" */ + .audiomux = { 0x001e00, 0, 0x018000, 0x014000, 0x002000, 0 }, + #endif + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + }, + [BTTV_WINVIEW_601] = { + .name = "Leadtek WinView 601", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x8300f8, + .muxsel = { 2, 3, 1, 1,0}, + .audiomux = { 0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007}, + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .audio_hook = winview_audio, + .has_radio = 1, + }, + [BTTV_AVEC_INTERCAP] = { + .name = "AVEC Intercapture", + .video_inputs = 3, + .audio_inputs = 2, + .tuner = 0, + .svhs = 2, + .gpiomask = 0, + .muxsel = {2, 3, 1, 1}, + .audiomux = {1, 0, 0, 0, 0}, + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_LIFE_FLYKIT] = { + .name = "Lifeview FlyVideo II EZ /FlyKit LR38 Bt848 (capture only)", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = -1, + .svhs = -1, + .gpiomask = 0x8dff00, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0 }, + .no_msp34xx = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + + /* ---- card 0x14 ---------------------------------- */ + [BTTV_CEI_RAFFLES] = { + .name = "CEI Raffles Card", + .video_inputs = 3, + .audio_inputs = 3, + .tuner = 0, + .svhs = 2, + .muxsel = {2, 3, 1, 1}, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_CONFERENCETV] = { + .name = "Lifeview FlyVideo 98/ Lucky Star Image World ConferenceTV LR50", + .video_inputs = 4, + .audio_inputs = 2, /* tuner, line in */ + .tuner = 0, + .svhs = 2, + .gpiomask = 0x1800, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800}, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_PAL_I, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_PHOEBE_TVMAS] = { + .name = "Askey CPH050/ Phoebe Tv Master + FM", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0xc00, + .muxsel = { 2, 3, 1, 1}, + .audiomux = {0, 1, 0x800, 0x400, 0xc00, 0}, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_MODTEC_205] = { + .name = "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV, bt878", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = -1, + .gpiomask = 7, + .muxsel = { 2, 3, -1 }, + .digital_mode = DIGITAL_MODE_CAMERA, + .audiomux = { 0, 0, 0, 0, 0 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_ALPS_TSBB5_PAL_I, + .tuner_addr = ADDR_UNSET, + }, + + /* ---- card 0x18 ---------------------------------- */ + [BTTV_MAGICTVIEW061] = { + .name = "Askey CPH05X/06X (bt878) [many vendors]", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0xe00, + .muxsel = { 2, 3, 1, 1}, + .audiomux = {0x400, 0x400, 0x400, 0x400, 0xc00}, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .has_remote = 1, + }, + [BTTV_VOBIS_BOOSTAR] = { + .name = "Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x1f0fff, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0x20000, 0x30000, 0x10000, 0, 0x40000}, + .needs_tvaudio = 0, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .audio_hook = terratv_audio, + }, + [BTTV_HAUPPAUG_WCAM] = { + .name = "Hauppauge WinCam newer (bt878)", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 3, + .gpiomask = 7, + .muxsel = { 2, 0, 1, 1}, + .audiomux = { 0, 1, 2, 3, 4}, + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_MAXI] = { + .name = "Lifeview FlyVideo 98/ MAXI TV Video PCI2 LR50", + .video_inputs = 4, + .audio_inputs = 2, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x1800, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800}, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_SECAM, + .tuner_addr = ADDR_UNSET, + }, + + /* ---- card 0x1c ---------------------------------- */ + [BTTV_TERRATV] = { + .name = "Terratec TerraTV+ Version 1.1 (bt878)", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x1f0fff, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0x20000, 0x30000, 0x10000, 0x00000, 0x40000}, + .needs_tvaudio = 0, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .audio_hook = terratv_audio, + /* GPIO wiring: + External 20 pin connector (for Active Radio Upgrade board) + gpio00: i2c-sda + gpio01: i2c-scl + gpio02: om5610-data + gpio03: om5610-clk + gpio04: om5610-wre + gpio05: om5610-stereo + gpio06: rds6588-davn + gpio07: Pin 7 n.c. + gpio08: nIOW + gpio09+10: nIOR, nSEL ?? (bt878) + gpio09: nIOR (bt848) + gpio10: nSEL (bt848) + Sound Routing: + gpio16: u2-A0 (1st 4052bt) + gpio17: u2-A1 + gpio18: u2-nEN + gpio19: u4-A0 (2nd 4052) + gpio20: u4-A1 + u4-nEN - GND + Btspy: + 00000 : Cdrom (internal audio input) + 10000 : ext. Video audio input + 20000 : TV Mono + a0000 : TV Mono/2 + 1a0000 : TV Stereo + 30000 : Radio + 40000 : Mute */ - .name = "Kodicom 4400R (master)", - .video_inputs = 16, - .audio_inputs = 0, - .tuner = -1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .svhs = -1, - /* GPIO bits 0-9 used for analog switch: - * 00 - 03: camera selector - * 04 - 06: channel (controller) selector - * 07: data (1->on, 0->off) - * 08: strobe - * 09: reset - * bit 16 is input from sync separator for the channel - */ - .gpiomask = 0x0003ff, - .no_gpioirq = 1, - .muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, - .pll = PLL_28, - .no_msp34xx = 1, - .no_tda7432 = 1, - .no_tda9875 = 1, - .muxsel_hook = kodicom4400r_muxsel, -}, -{ - /* Bill Brack */ - /* Note that, for reasons unknown, the "master" BT878A chip (i.e. the - * one which controls the analog switch, and must use the card type) - * is the 2nd one detected. The other 3 chips should use this card - * type + + }, + [BTTV_PXC200] = { + /* Jannik Fritsch */ + .name = "Imagenation PXC200", + .video_inputs = 5, + .audio_inputs = 1, + .tuner = -1, + .svhs = 1, /* was: 4 */ + .gpiomask = 0, + .muxsel = { 2, 3, 1, 0, 0}, + .audiomux = { 0 }, + .needs_tvaudio = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .muxsel_hook = PXC200_muxsel, + + }, + [BTTV_FLYVIDEO_98] = { + .name = "Lifeview FlyVideo 98 LR50", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x1800, /* 0x8dfe00 */ + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0, 0x0800, 0x1000, 0x1000, 0x1800, 0 }, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_IPROTV] = { + .name = "Formac iProTV, Formac ProTV I (bt848)", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 3, + .gpiomask = 1, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 1, 0, 0, 0, 0 }, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + }, + + /* ---- card 0x20 ---------------------------------- */ + [BTTV_INTEL_C_S_PCI] = { + .name = "Intel Create and Share PCI/ Smart Video Recorder III", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .svhs = 2, + .gpiomask = 0, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0 }, + .needs_tvaudio = 0, + .tuner_type = 4, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_TERRATVALUE] = { + .name = "Terratec TerraTValue Version Bt878", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0xffff00, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0x500, 0, 0x300, 0x900, 0x900}, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_WINFAST2000] = { + .name = "Leadtek WinFast 2000/ WinFast 2000 XP", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .muxsel = { 2, 3, 1, 1, 0}, /* TV, CVid, SVid, CVid over SVid connector */ + #if 0 + .gpiomask = 0xc33000, + .audiomux = { 0x422000,0x1000,0x0000,0x620000,0x800000 }, + #else + /* Alexander Varakin [stereo version] */ + .gpiomask = 0xb33000, + .audiomux = { 0x122000,0x1000,0x0000,0x620000,0x800000 }, + #endif + /* Audio Routing for "WinFast 2000 XP" (no tv stereo !) + gpio23 -- hef4052:nEnable (0x800000) + gpio12 -- hef4052:A1 + gpio13 -- hef4052:A0 + 0x0000: external audio + 0x1000: FM + 0x2000: TV + 0x3000: n.c. + Note: There exists another variant "Winfast 2000" with tv stereo !? + Note: eeprom only contains FF and pci subsystem id 107d:6606 + */ + .needs_tvaudio = 0, + .pll = PLL_28, + .has_radio = 1, + .tuner_type = 5, /* default for now, gpio reads BFFF06 for Pal bg+dk */ + .tuner_addr = ADDR_UNSET, + .audio_hook = winfast2000_audio, + .has_remote = 1, + }, + [BTTV_CHRONOS_VS2] = { + .name = "Lifeview FlyVideo 98 LR50 / Chronos Video Shuttle II", + .video_inputs = 4, + .audio_inputs = 3, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x1800, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800}, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + + /* ---- card 0x24 ---------------------------------- */ + [BTTV_TYPHOON_TVIEW] = { + .name = "Lifeview FlyVideo 98FM LR50 / Typhoon TView TV/FM Tuner", + .video_inputs = 4, + .audio_inputs = 3, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x1800, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 }, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .has_radio = 1, + }, + [BTTV_PXELVWPLTVPRO] = { + .name = "Prolink PixelView PlayTV pro", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0xff, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_MAGICTVIEW063] = { + .name = "Askey CPH06X TView99", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x551e00, + .muxsel = { 2, 3, 1, 0}, + .audiomux = { 0x551400, 0x551200, 0, 0, 0x551c00, 0x551200 }, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = 1, + .tuner_addr = ADDR_UNSET, + .has_remote = 1, + }, + [BTTV_PINNACLE] = { + .name = "Pinnacle PCTV Studio/Rave", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x03000F, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 2, 0xd0001, 0, 0, 1}, + .needs_tvaudio = 0, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + + /* ---- card 0x28 ---------------------------------- */ + [BTTV_STB2] = { + .name = "STB TV PCI FM, Gateway P/N 6000704 (bt878), 3Dfx VoodooTV 100", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 7, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 4, 0, 2, 3, 1}, + .no_msp34xx = 1, + .needs_tvaudio = 1, + .tuner_type = TUNER_PHILIPS_NTSC, + .tuner_addr = ADDR_UNSET, + .pll = PLL_28, + .has_radio = 1, + }, + [BTTV_AVPHONE98] = { + .name = "AVerMedia TVPhone 98", + .video_inputs = 3, + .audio_inputs = 4, + .tuner = 0, + .svhs = 2, + .gpiomask = 15, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 13, 4, 11, 7, 0, 0}, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .has_radio = 1, + .audio_hook = avermedia_tvphone_audio, + }, + [BTTV_PV951] = { + .name = "ProVideo PV951", /* pic16c54 */ + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0, 0, 0, 0, 0}, + .needs_tvaudio = 1, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = 1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_ONAIR_TV] = { + .name = "Little OnAir TV", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0xe00b, + .muxsel = {2, 3, 1, 1}, + .audiomux = {0xff9ff6, 0xff9ff6, 0xff1ff7, 0, 0xff3ffc}, + .no_msp34xx = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + + /* ---- card 0x2c ---------------------------------- */ + [BTTV_SIGMA_TVII_FM] = { + .name = "Sigma TVII-FM", + .video_inputs = 2, + .audio_inputs = 1, + .tuner = 0, + .svhs = -1, + .gpiomask = 3, + .muxsel = {2, 3, 1, 1}, + .audiomux = {1, 1, 0, 2, 3}, + .no_msp34xx = 1, + .pll = PLL_NONE, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_MATRIX_VISION2] = { + .name = "MATRIX-Vision MV-Delta 2", + .video_inputs = 5, + .audio_inputs = 1, + .tuner = -1, + .svhs = 3, + .gpiomask = 0, + .muxsel = { 2, 3, 1, 0, 0}, + .audiomux = {0 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_ZOLTRIX_GENIE] = { + .name = "Zoltrix Genie TV/FM", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0xbcf03f, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0xbc803f, 0xbc903f, 0xbcb03f, 0, 0xbcb03f}, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = 21, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_TERRATVRADIO] = { + .name = "Terratec TV/Radio+", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x70000, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0x20000, 0x30000, 0x10000, 0, 0x40000, 0x20000 }, + .needs_tvaudio = 1, + .no_msp34xx = 1, + .pll = PLL_35, + .tuner_type = 1, + .tuner_addr = ADDR_UNSET, + .has_radio = 1, + }, + + /* ---- card 0x30 ---------------------------------- */ + [BTTV_DYNALINK] = { + .name = "Askey CPH03x/ Dynalink Magic TView", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 15, + .muxsel = { 2, 3, 1, 1}, + .audiomux = {2,0,0,0,1}, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_GVBCTV3PCI] = { + .name = "IODATA GV-BCTV3/PCI", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x010f00, + .muxsel = {2, 3, 0, 0}, + .audiomux = {0x10000, 0, 0x10000, 0, 0, 0}, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_ALPS_TSHC6_NTSC, + .tuner_addr = ADDR_UNSET, + .audio_hook = gvbctv3pci_audio, + }, + [BTTV_PXELVWPLTVPAK] = { + .name = "Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP", + .video_inputs = 5, + .audio_inputs = 1, + .tuner = 0, + .svhs = 3, + .gpiomask = 0xAA0000, + .muxsel = { 2,3,1,1,-1 }, + .digital_mode = DIGITAL_MODE_CAMERA, + .audiomux = { 0x20000, 0, 0x80000, 0x80000, 0xa8000, 0x46000 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_PAL_I, + .tuner_addr = ADDR_UNSET, + .has_remote = 1, + /* GPIO wiring: (different from Rev.4C !) + GPIO17: U4.A0 (first hef4052bt) + GPIO19: U4.A1 + GPIO20: U5.A1 (second hef4052bt) + GPIO21: U4.nEN + GPIO22: BT832 Reset Line + GPIO23: A5,A0, U5,nEN + Note: At i2c=0x8a is a Bt832 chip, which changes to 0x88 after being reset via GPIO22 + */ + }, + [BTTV_EAGLE] = { + .name = "Eagle Wireless Capricorn2 (bt878A)", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 7, + .muxsel = { 2, 0, 1, 1}, + .audiomux = { 0, 1, 2, 3, 4}, + .pll = PLL_28, + .tuner_type = -1 /* TUNER_ALPS_TMDH2_NTSC */, + .tuner_addr = ADDR_UNSET, + }, + + /* ---- card 0x34 ---------------------------------- */ + [BTTV_PINNACLEPRO] = { + /* David Härdeman */ + .name = "Pinnacle PCTV Studio Pro", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 3, + .gpiomask = 0x03000F, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 1, 0xd0001, 0, 0, 10}, + /* sound path (5 sources): + MUX1 (mask 0x03), Enable Pin 0x08 (0=enable, 1=disable) + 0= ext. Audio IN + 1= from MUX2 + 2= Mono TV sound from Tuner + 3= not connected + MUX2 (mask 0x30000): + 0,2,3= from MSP34xx + 1= FM stereo Radio from Tuner */ + .needs_tvaudio = 0, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_TVIEW_RDS_FM] = { + /* Claas Langbehn , + Sven Grothklags */ + .name = "Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS", + .video_inputs = 4, + .audio_inputs = 3, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x1c, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0, 0, 0x10, 8, 4 }, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .has_radio = 1, + }, + [BTTV_LIFETEC_9415] = { + /* Tim Röstermundt + in de.comp.os.unix.linux.hardware: + options bttv card=0 pll=1 radio=1 gpiomask=0x18e0 + audiomux=0x44c71f,0x44d71f,0,0x44d71f,0x44dfff + options tuner type=5 */ + .name = "Lifeview FlyVideo 2000 /FlyVideo A2/ Lifetec LT 9415 TV [LR90]", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x18e0, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0x0000,0x0800,0x1000,0x1000,0x18e0 }, + /* For cards with tda9820/tda9821: + 0x0000: Tuner normal stereo + 0x0080: Tuner A2 SAP (second audio program = Zweikanalton) + 0x0880: Tuner A2 stereo */ + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_BESTBUY_EASYTV] = { + /* Miguel Angel Alvarez + old Easy TV BT848 version (model CPH031) */ + .name = "Askey CPH031/ BESTBUY Easy TV", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0xF, + .muxsel = { 2, 3, 1, 0}, + .audiomux = { 2, 0, 0, 0, 10}, + .needs_tvaudio = 0, + .pll = PLL_28, + .tuner_type = TUNER_TEMIC_PAL, + .tuner_addr = ADDR_UNSET, + }, + + /* ---- card 0x38 ---------------------------------- */ + [BTTV_FLYVIDEO_98FM] = { + /* Gordon Heydon */ + [BTTV_GRANDTEC] = { + .name = "GrandTec 'Grand Video Capture' (Bt848)", + .video_inputs = 2, + .audio_inputs = 0, + .tuner = -1, + .svhs = 1, + .gpiomask = 0, + .muxsel = { 3, 1 }, + .audiomux = { 0 }, + .needs_tvaudio = 0, + .no_msp34xx = 1, + .pll = PLL_35, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_ASKEY_CPH060] = { + /* Daniel Herrington */ + .name = "Askey CPH060/ Phoebe TV Master Only (No FM)", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0xe00, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0x400, 0x400, 0x400, 0x400, 0x800, 0x400 }, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = TUNER_TEMIC_4036FY5_NTSC, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_ASKEY_CPH03X] = { + /* Matti Mottus */ + .name = "Askey CPH03x TV Capturer", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x03000F, + .muxsel = { 2, 3, 1, 0}, + .audiomux = { 2,0,0,0,1 }, + .pll = PLL_28, + .tuner_type = 0, + .tuner_addr = ADDR_UNSET, + }, + + /* ---- card 0x3c ---------------------------------- */ + [BTTV_MM100PCTV] = { + /* Philip Blundell */ + .name = "Modular Technology MM100PCTV", + .video_inputs = 2, + .audio_inputs = 2, + .tuner = 0, + .svhs = -1, + .gpiomask = 11, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 2, 0, 0, 1, 8}, + .pll = PLL_35, + .tuner_type = TUNER_TEMIC_PAL, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_GMV1] = { + /* Adrian Cox + new Easy TV BT878 version (model CPH061) + special thanks to Informatica Mieres for providing the card */ + .name = "Askey CPH061/ BESTBUY Easy TV (bt878)", + .video_inputs = 3, + .audio_inputs = 2, + .tuner = 0, + .svhs = 2, + .gpiomask = 0xFF, + .muxsel = { 2, 3, 1, 0}, + .audiomux = { 1, 0, 4, 4, 9}, + .needs_tvaudio = 0, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_ATI_TVWONDER] = { + /* Lukas Gebauer */ + .name = "ATI TV-Wonder", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0xf03f, + .muxsel = { 2, 3, 1, 0 }, + .audiomux = { 0xbffe, 0, 0xbfff, 0, 0xbffe}, + .pll = PLL_28, + .tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL, + .tuner_addr = ADDR_UNSET, + }, + + /* ---- card 0x40 ---------------------------------- */ + [BTTV_ATI_TVWONDERVE] = { + /* Lukas Gebauer */ + .name = "ATI TV-Wonder VE", + .video_inputs = 2, + .audio_inputs = 1, + .tuner = 0, + .svhs = -1, + .gpiomask = 1, + .muxsel = { 2, 3, 0, 1}, + .audiomux = { 0, 0, 1, 0, 0}, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_FLYVIDEO2000] = { + /* DeeJay */ + .name = "IODATA GV-BCTV4/PCI", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x010f00, + .muxsel = {2, 3, 0, 0}, + .audiomux = {0x10000, 0, 0x10000, 0, 0, 0}, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_SHARP_2U5JF5540_NTSC, + .tuner_addr = ADDR_UNSET, + .audio_hook = gvbctv3pci_audio, + }, + + /* ---- card 0x44 ---------------------------------- */ + [BTTV_VOODOOTV_FM] = { + .name = "3Dfx VoodooTV FM (Euro), VoodooTV 200 (USA)", + /* try "insmod msp3400 simple=0" if you have + * sound problems with this card. */ + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = -1, + .gpiomask = 0x4f8a00, + /* 0x100000: 1=MSP enabled (0=disable again) + * 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC) */ + .audiomux = {0x947fff, 0x987fff,0x947fff,0x947fff, 0x947fff}, + /* tvtuner, radio, external,internal, mute, stereo + * tuner, Composit, SVid, Composit-on-Svid-adapter */ + .muxsel = { 2, 3 ,0 ,1}, + .tuner_type = TUNER_MT2032, + .tuner_addr = ADDR_UNSET, + .pll = PLL_28, + .has_radio = 1, + }, + [BTTV_AIMMS] = { + /* Philip Blundell */ + .name = "Active Imaging AIMMS", + .video_inputs = 1, + .audio_inputs = 0, + .tuner = -1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .pll = PLL_28, + .muxsel = { 2 }, + .gpiomask = 0 + }, + [BTTV_PV_BT878P_PLUS] = { + /* Tomasz Pyra */ + .name = "Prolink Pixelview PV-BT878P+ (Rev.4C,8E)", + .video_inputs = 3, + .audio_inputs = 4, + .tuner = 0, + .svhs = 2, + .gpiomask = 15, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0, 0, 11, 7, 13, 0}, /* TV and Radio with same GPIO ! */ + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = 25, + .tuner_addr = ADDR_UNSET, + .has_remote = 1, + /* GPIO wiring: + GPIO0: U4.A0 (hef4052bt) + GPIO1: U4.A1 + GPIO2: U4.A1 (second hef4052bt) + GPIO3: U4.nEN, U5.A0, A5.nEN + GPIO8-15: vrd866b ? + */ + }, + [BTTV_FLYVIDEO98EZ] = { + .name = "Lifeview FlyVideo 98EZ (capture only) LR51", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .svhs = 2, + .muxsel = { 2, 3, 1, 1}, /* AV1, AV2, SVHS, CVid adapter on SVHS */ + .pll = PLL_28, + .no_msp34xx = 1, + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, + }, + + /* ---- card 0x48 ---------------------------------- */ + [BTTV_PV_BT878P_9B] = { + /* Dariusz Kowalewski */ + .name = "Prolink Pixelview PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM)", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x3f, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0x01, 0x00, 0x03, 0x03, 0x09, 0x02 }, + .needs_tvaudio = 1, + .no_msp34xx = 1, + .no_tda9875 = 1, + .pll = PLL_28, + .tuner_type = 5, + .tuner_addr = ADDR_UNSET, + .audio_hook = pvbt878p9b_audio, /* Note: not all cards have stereo */ + .has_radio = 1, /* Note: not all cards have radio */ + .has_remote = 1, + /* GPIO wiring: + GPIO0: A0 hef4052 + GPIO1: A1 hef4052 + GPIO3: nEN hef4052 + GPIO8-15: vrd866b + GPIO20,22,23: R30,R29,R28 + */ + }, + [BTTV_SENSORAY311] = { + /* Clay Kunz */ + /* you must jumper JP5 for the card to work */ + .name = "Sensoray 311", + .video_inputs = 5, + .audio_inputs = 0, + .tuner = -1, + .svhs = 4, + .gpiomask = 0, + .muxsel = { 2, 3, 1, 0, 0}, + .audiomux = { 0 }, + .needs_tvaudio = 0, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_RV605] = { + /* Miguel Freitas */ + .name = "RemoteVision MX (RV605)", + .video_inputs = 16, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .gpiomask = 0x00, + .gpiomask2 = 0x07ff, + .muxsel = { 0x33, 0x13, 0x23, 0x43, 0xf3, 0x73, 0xe3, 0x03, + 0xd3, 0xb3, 0xc3, 0x63, 0x93, 0x53, 0x83, 0xa3 }, + .no_msp34xx = 1, + .no_tda9875 = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .muxsel_hook = rv605_muxsel, + }, + [BTTV_POWERCLR_MTV878] = { + .name = "Powercolor MTV878/ MTV878R/ MTV878F", + .video_inputs = 3, + .audio_inputs = 2, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x1C800F, /* Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset */ + .muxsel = { 2, 1, 1, }, + .audiomux = { 0, 1, 2, 2, 4 }, + .needs_tvaudio = 0, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .pll = PLL_28, + .has_radio = 1, + }, + + /* ---- card 0x4c ---------------------------------- */ + [BTTV_WINDVR] = { + /* Masaki Suzuki */ + .name = "Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP)", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x140007, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0, 1, 2, 3, 4, 0 }, + .tuner_type = TUNER_PHILIPS_NTSC, + .tuner_addr = ADDR_UNSET, + .audio_hook = windvr_audio, + }, + [BTTV_GRANDTEC_MULTI] = { + .name = "GrandTec Multi Capture Card (Bt878)", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .gpiomask = 0, + .muxsel = { 2, 3, 1, 0 }, + .audiomux = { 0 }, + .needs_tvaudio = 0, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_KWORLD] = { + .name = "Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF", + .video_inputs = 4, + .audio_inputs = 3, + .tuner = 0, + .svhs = 2, + .gpiomask = 7, + .muxsel = { 2, 3, 1, 1 }, /* Tuner, SVid, SVHS, SVid to SVHS connector */ + .audiomux = { 0 ,0 ,4, 4,4,4},/* Yes, this tuner uses the same audio output for TV and FM radio! + * This card lacks external Audio In, so we mute it on Ext. & Int. + * The PCB can take a sbx1637/sbx1673, wiring unknown. + * This card lacks PCI subsystem ID, sigh. + * audiomux=1: lower volume, 2+3: mute + * btwincap uses 0x80000/0x80003 + */ + .needs_tvaudio = 0, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = 5, + .tuner_addr = ADDR_UNSET, + /* Samsung TCPA9095PC27A (BG+DK), philips compatible, w/FM, stereo and + radio signal strength indicators work fine. */ + .has_radio = 1, + /* GPIO Info: + GPIO0,1: HEF4052 A0,A1 + GPIO2: HEF4052 nENABLE + GPIO3-7: n.c. + GPIO8-13: IRDC357 data0-5 (data6 n.c. ?) [chip not present on my card] + GPIO14,15: ?? + GPIO16-21: n.c. + GPIO22,23: ?? + ?? : mtu8b56ep microcontroller for IR (GPIO wiring unknown)*/ + }, + [BTTV_DSP_TCVIDEO] = { + /* Arthur Tetzlaff-Deas, DSP Design Ltd */ + .name = "DSP Design TCVIDEO", + .video_inputs = 4, + .svhs = -1, + .muxsel = { 2, 3, 1, 0}, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + + /* ---- card 0x50 ---------------------------------- */ + [BTTV_HAUPPAUGEPVR] = { + .name = "Hauppauge WinTV PVR", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .muxsel = { 2, 0, 1, 1}, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + + .gpiomask = 7, + .audiomux = {7}, + }, + [BTTV_GVBCTV5PCI] = { + .name = "IODATA GV-BCTV5/PCI", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x0f0f80, + .muxsel = {2, 3, 1, 0}, + .audiomux = {0x030000, 0x010000, 0, 0, 0x020000, 0}, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .tuner_addr = ADDR_UNSET, + .audio_hook = gvbctv5pci_audio, + .has_radio = 1, + }, + [BTTV_OSPREY1x0] = { + .name = "Osprey 100/150 (878)", /* 0x1(2|3)-45C6-C1 */ + .video_inputs = 4, /* id-inputs-clock */ + .audio_inputs = 0, + .tuner = -1, + .svhs = 3, + .muxsel = { 3, 2, 0, 1 }, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + }, + [BTTV_OSPREY1x0_848] = { + .name = "Osprey 100/150 (848)", /* 0x04-54C0-C1 & older boards */ + .video_inputs = 3, + .audio_inputs = 0, + .tuner = -1, + .svhs = 2, + .muxsel = { 2, 3, 1 }, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + }, + + /* ---- card 0x54 ---------------------------------- */ + [BTTV_OSPREY101_848] = { + .name = "Osprey 101 (848)", /* 0x05-40C0-C1 */ + .video_inputs = 2, + .audio_inputs = 0, + .tuner = -1, + .svhs = 1, + .muxsel = { 3, 1 }, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + }, + [BTTV_OSPREY1x1] = { + .name = "Osprey 101/151", /* 0x1(4|5)-0004-C4 */ + .video_inputs = 1, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .muxsel = { 0 }, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + }, + [BTTV_OSPREY1x1_SVID] = { + .name = "Osprey 101/151 w/ svid", /* 0x(16|17|20)-00C4-C1 */ + .video_inputs = 2, + .audio_inputs = 0, + .tuner = -1, + .svhs = 1, + .muxsel = { 0, 1 }, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + }, + [BTTV_OSPREY2xx] = { + .name = "Osprey 200/201/250/251", /* 0x1(8|9|E|F)-0004-C4 */ + .video_inputs = 1, + .audio_inputs = 1, + .tuner = -1, + .svhs = -1, + .muxsel = { 0 }, + .pll = PLL_28, + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + }, + + /* ---- card 0x58 ---------------------------------- */ + [BTTV_OSPREY2x0_SVID] = { + .name = "Osprey 200/250", /* 0x1(A|B)-00C4-C1 */ + .video_inputs = 2, + .audio_inputs = 1, + .tuner = -1, + .svhs = 1, + .muxsel = { 0, 1 }, + .pll = PLL_28, + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + }, + [BTTV_OSPREY2x0] = { + .name = "Osprey 210/220", /* 0x1(A|B)-04C0-C1 */ + .video_inputs = 2, + .audio_inputs = 1, + .tuner = -1, + .svhs = 1, + .muxsel = { 2, 3 }, + .pll = PLL_28, + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + }, + [BTTV_OSPREY500] = { + .name = "Osprey 500", /* 500 */ + .video_inputs = 2, + .audio_inputs = 1, + .tuner = -1, + .svhs = 1, + .muxsel = { 2, 3 }, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + }, + [BTTV_OSPREY540] = { + .name = "Osprey 540", /* 540 */ + .video_inputs = 4, + .audio_inputs = 1, + .tuner = -1, + #if 0 /* TODO ... */ + .svhs = OSPREY540_SVID_ANALOG, + .muxsel = { [OSPREY540_COMP_ANALOG] = 2, + [OSPREY540_SVID_ANALOG] = 3, }, + #endif + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + #if 0 /* TODO ... */ + .muxsel_hook = osprey_540_muxsel, + .picture_hook = osprey_540_set_picture, + #endif + }, + + /* ---- card 0x5C ---------------------------------- */ + [BTTV_OSPREY2000] = { + .name = "Osprey 2000", /* 2000 */ + .video_inputs = 2, + .audio_inputs = 1, + .tuner = -1, + .svhs = 1, + .muxsel = { 2, 3 }, + .pll = PLL_28, + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, /* must avoid, conflicts with the bt860 */ + }, + [BTTV_IDS_EAGLE] = { + /* M G Berberich */ + .name = "IDS Eagle", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .svhs = -1, + .gpiomask = 0, + .muxsel = { 0, 1, 2, 3 }, + .muxsel_hook = eagle_muxsel, + .no_msp34xx = 1, + .no_tda9875 = 1, + .pll = PLL_28, + }, + [BTTV_PINNACLESAT] = { + .name = "Pinnacle PCTV Sat", + .video_inputs = 2, + .audio_inputs = 0, + .svhs = 1, + .tuner = -1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .muxsel = { 3, 0, 1, 2}, + .pll = PLL_28, + .no_gpioirq = 1, + .has_dvb = 1, + }, + [BTTV_FORMAC_PROTV] = { + .name = "Formac ProTV II (bt878)", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 3, + .gpiomask = 2, + /* TV, Comp1, Composite over SVID con, SVID */ + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 2, 2, 0, 0, 0 }, + .pll = PLL_28, + .has_radio = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + /* sound routing: + GPIO=0x00,0x01,0x03: mute (?) + 0x02: both TV and radio (tuner: FM1216/I) + The card has onboard audio connectors labeled "cdrom" and "board", + not soldered here, though unknown wiring. + Card lacks: external audio in, pci subsystem id. */ - .name = "Kodicom 4400R (slave)", - .video_inputs = 16, - .audio_inputs = 0, - .tuner = -1, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .svhs = -1, - .gpiomask = 0x010000, - .no_gpioirq = 1, - .muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, - .pll = PLL_28, - .no_msp34xx = 1, - .no_tda7432 = 1, - .no_tda9875 = 1, - .muxsel_hook = kodicom4400r_muxsel, -}, -{ - /* ---- card 0x86---------------------------------- */ - /* Michael Henson */ - /* Adlink RTV24 with special unlock codes */ - .name = "Adlink RTV24", - .video_inputs = 4, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .muxsel = { 2, 3, 1, 0}, - .tuner_type = -1, - .tuner_addr = ADDR_UNSET, - .pll = PLL_28, -}, -{ - /* ---- card 0x87---------------------------------- */ - /* Michael Krufky */ - .name = "DViCO FusionHDTV 5 Lite", - .tuner = 0, - .tuner_type = TUNER_LG_TDVS_H062F, - .tuner_addr = ADDR_UNSET, - .video_inputs = 3, - .audio_inputs = 1, - .svhs = 2, - .muxsel = { 2, 3, 1 }, - .gpiomask = 0x00e00007, - .audiomux = { 0x00400005, 0, 0x00000001, 0, 0x00c00007, 0 }, - .no_msp34xx = 1, - .no_tda9875 = 1, - .no_tda7432 = 1, - .has_dvb = 1, -},{ - /* ---- card 0x88---------------------------------- */ - /* Mauro Carvalho Chehab */ - .name = "Acorp Y878F", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x01fe00, - .muxsel = { 2, 3, 1, 1}, - .audiomux = { 0x001e00, 0, 0x018000, 0x014000, 0x002000, 0 }, - .needs_tvaudio = 1, - .pll = PLL_28, - .tuner_type = TUNER_YMEC_TVF66T5_B_DFF, - .tuner_addr = 0xc1 >>1, - .has_radio = 1, -},{ - /* ---- card 0x89 ---------------------------------- */ - .name = "Conceptronic CTVFMi v2", - .video_inputs = 3, - .audio_inputs = 1, - .tuner = 0, - .svhs = 2, - .gpiomask = 0x001c0007, - .muxsel = { 2, 3, 1, 1 }, - .audiomux = { 0, 1, 2, 2, 3 }, - .needs_tvaudio = 0, - .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .tuner_addr = ADDR_UNSET, - .has_remote = 1, -},{ - .name = "Prolink Pixelview PV-BT878P+ (Rev.2E)", - .video_inputs = 5, - .audio_inputs = 1, - .tuner = 0, - .svhs = 3, - .gpiomask = 0x01fe00, - .muxsel = { 2,3,1,1,-1 }, - .digital_mode = DIGITAL_MODE_CAMERA, - .audiomux = { 0x00400, 0x10400, 0x04400, 0x80000, 0x12400, 0x46000 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = TUNER_LG_PAL_FM, - .has_remote = 1, -}}; + }, + + /* ---- card 0x60 ---------------------------------- */ + [BTTV_MACHTV] = { + .name = "MachTV", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = -1, + .gpiomask = 7, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0, 1, 2, 3, 4}, + .needs_tvaudio = 1, + .tuner_type = 5, + .tuner_addr = ADDR_UNSET, + .pll = 1, + }, + [BTTV_EURESYS_PICOLO] = { + .name = "Euresys Picolo", + .video_inputs = 3, + .audio_inputs = 0, + .tuner = -1, + .svhs = 2, + .gpiomask = 0, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .muxsel = { 2, 0, 1}, + .pll = PLL_28, + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_PV150] = { + /* Luc Van Hoeylandt */ + .name = "ProVideo PV150", /* 0x4f */ + .video_inputs = 2, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .gpiomask = 0, + .muxsel = { 2, 3 }, + .audiomux = { 0 }, + .needs_tvaudio = 0, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_AD_TVK503] = { + /* Hiroshi Takekawa */ + /* This card lacks subsystem ID */ + .name = "AD-TVK503", /* 0x63 */ + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x001e8007, + .muxsel = { 2, 3, 1, 0 }, + /* Tuner, Radio, external, internal, off, on */ + .audiomux = { 0x08, 0x0f, 0x0a, 0x08, 0x0f, 0x08 }, + .needs_tvaudio = 0, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = 2, + .tuner_addr = ADDR_UNSET, + .audio_hook = adtvk503_audio, + }, + + /* ---- card 0x64 ---------------------------------- */ + [BTTV_HERCULES_SM_TV] = { + .name = "Hercules Smart TV Stereo", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x00, + .muxsel = { 2, 3, 1, 1 }, + .needs_tvaudio = 1, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = 5, + .tuner_addr = ADDR_UNSET, + /* Notes: + - card lacks subsystem ID + - stereo variant w/ daughter board with tda9874a @0xb0 + - Audio Routing: + always from tda9874 independent of GPIO (?) + external line in: unknown + - Other chips: em78p156elp @ 0x96 (probably IR remote control) + hef4053 (instead 4052) for unknown function + */ + }, + [BTTV_PACETV] = { + .name = "Pace TV & Radio Card", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .muxsel = { 2, 3, 1, 1}, /* Tuner, CVid, SVid, CVid over SVid connector */ + .gpiomask = 0, + .no_tda9875 = 1, + .no_tda7432 = 1, + .tuner_type = 1, + .tuner_addr = ADDR_UNSET, + .has_radio = 1, + .pll = PLL_28, + /* Bt878, Bt832, FI1246 tuner; no pci subsystem id + only internal line out: (4pin header) RGGL + Radio must be decoded by msp3410d (not routed through)*/ + /* + .digital_mode = DIGITAL_MODE_CAMERA, todo! + */ + }, + [BTTV_IVC200] = { + /* Chris Willing */ + .name = "IVC-200", + .video_inputs = 1, + .audio_inputs = 0, + .tuner = -1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .svhs = -1, + .gpiomask = 0xdf, + .muxsel = { 2 }, + .pll = PLL_28, + }, + [BTTV_XGUARD] = { + .name = "Grand X-Guard / Trust 814PCI", + .video_inputs = 16, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .tuner_type = 4, + .tuner_addr = ADDR_UNSET, + .gpiomask2 = 0xff, + .muxsel = { 2,2,2,2, 3,3,3,3, 1,1,1,1, 0,0,0,0 }, + .muxsel_hook = xguard_muxsel, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .pll = PLL_28, + }, + + /* ---- card 0x68 ---------------------------------- */ + [BTTV_NEBULA_DIGITV] = { + .name = "Nebula Electronics DigiTV", + .video_inputs = 1, + .tuner = -1, + .svhs = -1, + .muxsel = { 2, 3, 1, 0}, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .has_dvb = 1, + .no_gpioirq = 1, + }, + [BTTV_PV143] = { + /* Jorge Boncompte - DTI2 */ + .name = "ProVideo PV143", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .gpiomask = 0, + .muxsel = { 2, 3, 1, 0 }, + .audiomux = { 0 }, + .needs_tvaudio = 0, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_VD009X1_MINIDIN] = { + /* M.Klahr@phytec.de */ + .name = "PHYTEC VD-009-X1 MiniDIN (bt878)", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, /* card has no tuner */ + .svhs = 3, + .gpiomask = 0x00, + .muxsel = { 2, 3, 1, 0}, + .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_VD009X1_COMBI] = { + .name = "PHYTEC VD-009-X1 Combi (bt878)", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, /* card has no tuner */ + .svhs = 3, + .gpiomask = 0x00, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + + /* ---- card 0x6c ---------------------------------- */ + [BTTV_VD009_MINIDIN] = { + .name = "PHYTEC VD-009 MiniDIN (bt878)", + .video_inputs = 10, + .audio_inputs = 0, + .tuner = -1, /* card has no tuner */ + .svhs = 9, + .gpiomask = 0x00, + .gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio + via the upper nibble of muxsel. here: used for + xternal video-mux */ + .muxsel = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x00 }, + .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_VD009_COMBI] = { + .name = "PHYTEC VD-009 Combi (bt878)", + .video_inputs = 10, + .audio_inputs = 0, + .tuner = -1, /* card has no tuner */ + .svhs = 9, + .gpiomask = 0x00, + .gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio + via the upper nibble of muxsel. here: used for + xternal video-mux */ + .muxsel = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x01 }, + .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_IVC100] = { + .name = "IVC-100", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .svhs = -1, + .gpiomask = 0xdf, + .muxsel = { 2, 3, 1, 0 }, + .pll = PLL_28, + }, + [BTTV_IVC120] = { + /* IVC-120G - Alan Garfield */ + .name = "IVC-120G", + .video_inputs = 16, + .audio_inputs = 0, /* card has no audio */ + .tuner = -1, /* card has no tuner */ + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .svhs = -1, /* card has no svhs */ + .needs_tvaudio = 0, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .gpiomask = 0x00, + .muxsel = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 }, + .muxsel_hook = ivc120_muxsel, + .pll = PLL_28, + }, + + /* ---- card 0x70 ---------------------------------- */ + [BTTV_PC_HDTV] = { + .name = "pcHDTV HD-2000 TV", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .muxsel = { 2, 3, 1, 0}, + .tuner_type = TUNER_PHILIPS_ATSC, + .tuner_addr = ADDR_UNSET, + .has_dvb = 1, + }, + [BTTV_TWINHAN_DST] = { + .name = "Twinhan DST + clones", + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .tuner_type = TUNER_ABSENT, + .tuner_addr = ADDR_UNSET, + .no_video = 1, + .has_dvb = 1, + }, + [BTTV_WINFASTVC100] = { + .name = "Winfast VC100", + .video_inputs = 3, + .audio_inputs = 0, + .svhs = 1, + .tuner = -1, + .muxsel = { 3, 1, 1, 3}, /* Vid In, SVid In, Vid over SVid in connector */ + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .tuner_type = TUNER_ABSENT, + .tuner_addr = ADDR_UNSET, + .pll = PLL_28, + }, + [BTTV_TEV560] = { + .name = "Teppro TEV-560/InterVision IV-560", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 3, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 1, 1, 1, 1, 0}, + .needs_tvaudio = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .pll = PLL_35, + }, + + /* ---- card 0x74 ---------------------------------- */ + [BTTV_SIMUS_GVC1100] = { + .name = "SIMUS GVC1100", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .pll = PLL_28, + .muxsel = { 2, 2, 2, 2}, + .gpiomask = 0x3F, + .muxsel_hook = gvc1100_muxsel, + }, + [BTTV_NGSTV_PLUS] = { + /* Carlos Silva r3pek@r3pek.homelinux.org || card 0x75 */ + .name = "NGS NGSTV+", + .video_inputs = 3, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x008007, + .muxsel = {2, 3, 0, 0}, + .audiomux = {0, 0, 0, 0, 0x000003, 0}, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .has_remote = 1, + }, + [BTTV_LMLBT4] = { + /* http://linuxmedialabs.com */ + .name = "LMLBT4", + .video_inputs = 4, /* IN1,IN2,IN3,IN4 */ + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .muxsel = { 2, 3, 1, 0 }, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .needs_tvaudio = 0, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_TEKRAM_M205] = { + /* Helmroos Harri */ + .name = "Tekram M205 PRO", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .svhs = 2, + .needs_tvaudio = 0, + .gpiomask = 0x68, + .muxsel = { 2, 3, 1}, + .audiomux = { 0x68, 0x68, 0x61, 0x61, 0x00 }, + .pll = PLL_28, + }, + + /* ---- card 0x78 ---------------------------------- */ + [BTTV_CONTVFMI] = { + /* Javier Cendan Ares */ + /* bt878 TV + FM without subsystem ID */ + .name = "Conceptronic CONTVFMi", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x008007, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0, 1, 2, 2, 3 }, + .needs_tvaudio = 0, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .has_remote = 1, + .has_radio = 1, + }, + [BTTV_PICOLO_TETRA_CHIP] = { + /*Eric DEBIEF */ + /*EURESYS Picolo Tetra : 4 Conexant Fusion 878A, no audio, video input set with analog multiplexers GPIO controled*/ + /* adds picolo_tetra_muxsel(), picolo_tetra_init(), the folowing declaration strucure, and #define BTTV_PICOLO_TETRA_CHIP*/ + /*0x79 in bttv.h*/ + .name = "Euresys Picolo Tetra", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .gpiomask = 0, + .gpiomask2 = 0x3C<<16,/*Set the GPIO[18]->GPIO[21] as output pin.==> drive the video inputs through analog multiplexers*/ + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .muxsel = {2,2,2,2},/*878A input is always MUX0, see above.*/ + .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ + .pll = PLL_28, + .needs_tvaudio = 0, + .muxsel_hook = picolo_tetra_muxsel,/*Required as it doesn't follow the classic input selection policy*/ + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_SPIRIT_TV] = { + /* Spirit TV Tuner from http://spiritmodems.com.au */ + /* Stafford Goodsell */ + .name = "Spirit TV Tuner", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x0000000f, + .muxsel = { 2, 1, 1 }, + .audiomux = { 0x02, 0x00, 0x00, 0x00, 0x00}, + .tuner_type = TUNER_TEMIC_PAL, + .tuner_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + }, + [BTTV_AVDVBT_771] = { + /* Wolfram Joost */ + .name = "AVerMedia AVerTV DVB-T 771", + .video_inputs = 2, + .svhs = 1, + .tuner = -1, + .tuner_type = TUNER_ABSENT, + .tuner_addr = ADDR_UNSET, + .muxsel = { 3 , 3 }, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .pll = PLL_28, + .has_dvb = 1, + .no_gpioirq = 1, + .has_remote = 1, + }, + /* ---- card 0x7c ---------------------------------- */ + [BTTV_AVDVBT_761] = { + /* Matt Jesson */ + /* Based on the Nebula card data - added remote and new card number - BTTV_AVDVBT_761, see also ir-kbd-gpio.c */ + .name = "AverMedia AverTV DVB-T 761", + .video_inputs = 2, + .tuner = -1, + .svhs = 1, + .muxsel = { 3, 1, 2, 0}, /* Comp0, S-Video, ?, ? */ + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .has_dvb = 1, + .no_gpioirq = 1, + .has_remote = 1, + }, + [BTTV_MATRIX_VISIONSQ] = { + /* andre.schwarz@matrix-vision.de */ + .name = "MATRIX Vision Sigma-SQ", + .video_inputs = 16, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .gpiomask = 0x0, + .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3 }, + .muxsel_hook = sigmaSQ_muxsel, + .audiomux = { 0 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_MATRIX_VISIONSLC] = { + /* andre.schwarz@matrix-vision.de */ + .name = "MATRIX Vision Sigma-SLC", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .gpiomask = 0x0, + .muxsel = { 2, 2, 2, 2 }, + .muxsel_hook = sigmaSLC_muxsel, + .audiomux = { 0 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + /* BTTV_APAC_VIEWCOMP */ + [BTTV_APAC_VIEWCOMP] = { + /* Attila Kondoros */ + /* bt878 TV + FM 0x00000000 subsystem ID */ + .name = "APAC Viewcomp 878(AMAX)", + .video_inputs = 2, + .audio_inputs = 1, + .tuner = 0, + .svhs = -1, + .gpiomask = 0xFF, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 2, 0, 0, 0, 10}, + .needs_tvaudio = 0, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_PAL, + .tuner_addr = ADDR_UNSET, + .has_remote = 1, /* miniremote works, see ir-kbd-gpio.c */ + .has_radio = 1, /* not every card has radio */ + }, + + /* ---- card 0x80 ---------------------------------- */ + [BTTV_DVICO_DVBT_LITE] = { + /* Chris Pascoe */ + .name = "DViCO FusionHDTV DVB-T Lite", + .tuner = -1, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .pll = PLL_28, + .no_video = 1, + .has_dvb = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + }, + [BTTV_VGEAR_MYVCD] = { + /* Steven */ + .name = "V-Gear MyVCD", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x3f, + .muxsel = {2, 3, 1, 0}, + .audiomux = {0x31, 0x31, 0x31, 0x31, 0x31, 0x31}, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .tuner_addr = ADDR_UNSET, + .has_radio = 0, + #if 0 + .has_remote = 1, + #endif + }, + [BTTV_SUPER_TV] = { + /* Rick C */ + .name = "Super TV Tuner", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .muxsel = { 2, 3, 1, 0}, + .tuner_type = TUNER_PHILIPS_NTSC, + .tuner_addr = ADDR_UNSET, + .gpiomask = 0x008007, + .audiomux = { 0, 0x000001,0,0, 0}, + .needs_tvaudio = 1, + .has_radio = 1, + }, + [BTTV_TIBET_CS16] = { + /* Chris Fanning */ + .name = "Tibet Systems 'Progress DVR' CS16", + .video_inputs = 16, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, + .pll = PLL_28, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .muxsel_hook = tibetCS16_muxsel, + }, + { + /* Bill Brack */ + /* + * Note that, because of the card's wiring, the "master" + * BT878A chip (i.e. the one which controls the analog switch + * and must use this card type) is the 2nd one detected. The + * other 3 chips should use card type 0x85, whose description + * follows this one. There is a EEPROM on the card (which is + * connected to the I2C of one of those other chips), but is + * not currently handled. There is also a facility for a + * "monitor", which is also not currently implemented. + */ + .name = "Kodicom 4400R (master)", + .video_inputs = 16, + .audio_inputs = 0, + .tuner = -1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .svhs = -1, + /* GPIO bits 0-9 used for analog switch: + * 00 - 03: camera selector + * 04 - 06: channel (controller) selector + * 07: data (1->on, 0->off) + * 08: strobe + * 09: reset + * bit 16 is input from sync separator for the channel + */ + .gpiomask = 0x0003ff, + .no_gpioirq = 1, + .muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, + .pll = PLL_28, + .no_msp34xx = 1, + .no_tda7432 = 1, + .no_tda9875 = 1, + .muxsel_hook = kodicom4400r_muxsel, + }, + { + /* Bill Brack */ + /* Note that, for reasons unknown, the "master" BT878A chip (i.e. the + * one which controls the analog switch, and must use the card type) + * is the 2nd one detected. The other 3 chips should use this card + * type + */ + .name = "Kodicom 4400R (slave)", + .video_inputs = 16, + .audio_inputs = 0, + .tuner = -1, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .svhs = -1, + .gpiomask = 0x010000, + .no_gpioirq = 1, + .muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, + .pll = PLL_28, + .no_msp34xx = 1, + .no_tda7432 = 1, + .no_tda9875 = 1, + .muxsel_hook = kodicom4400r_muxsel, + }, + { + /* ---- card 0x86---------------------------------- */ + /* Michael Henson */ + /* Adlink RTV24 with special unlock codes */ + .name = "Adlink RTV24", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .muxsel = { 2, 3, 1, 0}, + .tuner_type = -1, + .tuner_addr = ADDR_UNSET, + .pll = PLL_28, + }, + { + /* ---- card 0x87---------------------------------- */ + /* Michael Krufky */ + .name = "DViCO FusionHDTV 5 Lite", + .tuner = 0, + .tuner_type = TUNER_LG_TDVS_H062F, + .tuner_addr = ADDR_UNSET, + .video_inputs = 2, + .audio_inputs = 1, + .svhs = 2, + .muxsel = { 2, 3 }, + .gpiomask = 0x00e00007, + .audiomux = { 0x00400005, 0, 0x00000001, 0, 0x00c00007, 0 }, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .has_dvb = 1, + }, + /* ---- card 0x88---------------------------------- */ + [BTTV_KODICOM_4400R] = { + /* Mauro Carvalho Chehab */ + .name = "Acorp Y878F", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x01fe00, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 0x001e00, 0, 0x018000, 0x014000, 0x002000, 0 }, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = TUNER_YMEC_TVF66T5_B_DFF, + .tuner_addr = 0xc1 >>1, + .has_radio = 1, + }, + /* ---- card 0x89 ---------------------------------- */ + [BTTV_KODICOM_4400R_SL] = { + .name = "Conceptronic CTVFMi v2", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x001c0007, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0, 1, 2, 2, 3 }, + .needs_tvaudio = 0, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .tuner_addr = ADDR_UNSET, + .has_remote = 1, + #if 0 + .has_radio = 1, + #endif + }, + [BTTV_ADLINK_RTV24] = { + .name = "Prolink Pixelview PV-BT878P+ (Rev.2E)", + .video_inputs = 5, + .audio_inputs = 1, + .tuner = 0, + .svhs = 3, + .gpiomask = 0x01fe00, + .muxsel = { 2,3,1,1,-1 }, + .digital_mode = DIGITAL_MODE_CAMERA, + .audiomux = { 0x00400, 0x10400, 0x04400, 0x80000, 0x12400, 0x46000 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_LG_PAL_FM, + .has_remote = 1, + } +}; static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); @@ -4513,8 +4673,7 @@ void __devinit bttv_check_chipset(void) } if (UNSET != latency) printk(KERN_INFO "bttv: pci latency fixup [%d]\n",latency); - - while ((dev = pci_find_device(PCI_VENDOR_ID_INTEL, + while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, dev))) { unsigned char b; pci_read_config_byte(dev, 0x53, &b); -- cgit v1.2.3 From 5a25e84b3ca053f240dc8fa3320bc843a0a394f5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:36:52 -0800 Subject: [PATCH] vl4: 693: bttv board renaming - Boards renamed to BTTV_BOARD_xxx Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bttv-cards.c | 737 +++++++++++++++++++------------------- drivers/media/video/bttv-driver.c | 4 +- drivers/media/video/bttv.h | 259 ++++++++------ drivers/media/video/ir-kbd-gpio.c | 26 +- 4 files changed, 523 insertions(+), 503 deletions(-) diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 12f38e8cd0a..1553d4a1c20 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -145,162 +145,162 @@ static struct CARD { int cardnr; char *name; } cards[] __devinitdata = { - { 0x13eb0070, BTTV_HAUPPAUGE878, "Hauppauge WinTV" }, - { 0x39000070, BTTV_HAUPPAUGE878, "Hauppauge WinTV-D" }, - { 0x45000070, BTTV_HAUPPAUGEPVR, "Hauppauge WinTV/PVR" }, - { 0xff000070, BTTV_OSPREY1x0, "Osprey-100" }, - { 0xff010070, BTTV_OSPREY2x0_SVID,"Osprey-200" }, - { 0xff020070, BTTV_OSPREY500, "Osprey-500" }, - { 0xff030070, BTTV_OSPREY2000, "Osprey-2000" }, - { 0xff040070, BTTV_OSPREY540, "Osprey-540" }, - - { 0x00011002, BTTV_ATI_TVWONDER, "ATI TV Wonder" }, - { 0x00031002, BTTV_ATI_TVWONDERVE,"ATI TV Wonder/VE" }, - - { 0x6606107d, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" }, - { 0x6607107d, BTTV_WINFASTVC100, "Leadtek WinFast VC 100" }, - { 0x6609107d, BTTV_WINFAST2000, "Leadtek TV 2000 XP" }, - { 0x263610b4, BTTV_STB2, "STB TV PCI FM, Gateway P/N 6000704" }, - { 0x264510b4, BTTV_STB2, "STB TV PCI FM, Gateway P/N 6000704" }, - { 0x402010fc, BTTV_GVBCTV3PCI, "I-O Data Co. GV-BCTV3/PCI" }, - { 0x405010fc, BTTV_GVBCTV4PCI, "I-O Data Co. GV-BCTV4/PCI" }, - { 0x407010fc, BTTV_GVBCTV5PCI, "I-O Data Co. GV-BCTV5/PCI" }, - { 0xd01810fc, BTTV_GVBCTV5PCI, "I-O Data Co. GV-BCTV5/PCI" }, - - { 0x001211bd, BTTV_PINNACLE, "Pinnacle PCTV" }, + { 0x13eb0070, BTTV_BOARD_HAUPPAUGE878, "Hauppauge WinTV" }, + { 0x39000070, BTTV_BOARD_HAUPPAUGE878, "Hauppauge WinTV-D" }, + { 0x45000070, BTTV_BOARD_HAUPPAUGEPVR, "Hauppauge WinTV/PVR" }, + { 0xff000070, BTTV_BOARD_OSPREY1x0, "Osprey-100" }, + { 0xff010070, BTTV_BOARD_OSPREY2x0_SVID,"Osprey-200" }, + { 0xff020070, BTTV_BOARD_OSPREY500, "Osprey-500" }, + { 0xff030070, BTTV_BOARD_OSPREY2000, "Osprey-2000" }, + { 0xff040070, BTTV_BOARD_OSPREY540, "Osprey-540" }, + + { 0x00011002, BTTV_BOARD_ATI_TVWONDER, "ATI TV Wonder" }, + { 0x00031002, BTTV_BOARD_ATI_TVWONDERVE,"ATI TV Wonder/VE" }, + + { 0x6606107d, BTTV_BOARD_WINFAST2000, "Leadtek WinFast TV 2000" }, + { 0x6607107d, BTTV_BOARD_WINFASTVC100, "Leadtek WinFast VC 100" }, + { 0x6609107d, BTTV_BOARD_WINFAST2000, "Leadtek TV 2000 XP" }, + { 0x263610b4, BTTV_BOARD_STB2, "STB TV PCI FM, Gateway P/N 6000704" }, + { 0x264510b4, BTTV_BOARD_STB2, "STB TV PCI FM, Gateway P/N 6000704" }, + { 0x402010fc, BTTV_BOARD_GVBCTV3PCI, "I-O Data Co. GV-BCTV3/PCI" }, + { 0x405010fc, BTTV_BOARD_GVBCTV4PCI, "I-O Data Co. GV-BCTV4/PCI" }, + { 0x407010fc, BTTV_BOARD_GVBCTV5PCI, "I-O Data Co. GV-BCTV5/PCI" }, + { 0xd01810fc, BTTV_BOARD_GVBCTV5PCI, "I-O Data Co. GV-BCTV5/PCI" }, + + { 0x001211bd, BTTV_BOARD_PINNACLE, "Pinnacle PCTV" }, /* some cards ship with byteswapped IDs ... */ - { 0x1200bd11, BTTV_PINNACLE, "Pinnacle PCTV [bswap]" }, - { 0xff00bd11, BTTV_PINNACLE, "Pinnacle PCTV [bswap]" }, + { 0x1200bd11, BTTV_BOARD_PINNACLE, "Pinnacle PCTV [bswap]" }, + { 0xff00bd11, BTTV_BOARD_PINNACLE, "Pinnacle PCTV [bswap]" }, /* this seems to happen as well ... */ - { 0xff1211bd, BTTV_PINNACLE, "Pinnacle PCTV" }, - - { 0x3000121a, BTTV_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" }, - { 0x263710b4, BTTV_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" }, - { 0x3060121a, BTTV_STB2, "3Dfx VoodooTV 100/ STB OEM" }, - - { 0x3000144f, BTTV_MAGICTVIEW063, "(Askey Magic/others) TView99 CPH06x" }, - { 0xa005144f, BTTV_MAGICTVIEW063, "CPH06X TView99-Card" }, - { 0x3002144f, BTTV_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH05x" }, - { 0x3005144f, BTTV_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH061/06L (T1/LC)" }, - { 0x5000144f, BTTV_MAGICTVIEW061, "Askey CPH050" }, - { 0x300014ff, BTTV_MAGICTVIEW061, "TView 99 (CPH061)" }, - { 0x300214ff, BTTV_PHOEBE_TVMAS, "Phoebe TV Master (CPH060)" }, - - { 0x00011461, BTTV_AVPHONE98, "AVerMedia TVPhone98" }, - { 0x00021461, BTTV_AVERMEDIA98, "AVermedia TVCapture 98" }, - { 0x00031461, BTTV_AVPHONE98, "AVerMedia TVPhone98" }, - { 0x00041461, BTTV_AVERMEDIA98, "AVerMedia TVCapture 98" }, - { 0x03001461, BTTV_AVERMEDIA98, "VDOMATE TV TUNER CARD" }, - - { 0x1117153b, BTTV_TERRATVALUE, "Terratec TValue (Philips PAL B/G)" }, - { 0x1118153b, BTTV_TERRATVALUE, "Terratec TValue (Temic PAL B/G)" }, - { 0x1119153b, BTTV_TERRATVALUE, "Terratec TValue (Philips PAL I)" }, - { 0x111a153b, BTTV_TERRATVALUE, "Terratec TValue (Temic PAL I)" }, - - { 0x1123153b, BTTV_TERRATVRADIO, "Terratec TV Radio+" }, - { 0x1127153b, BTTV_TERRATV, "Terratec TV+ (V1.05)" }, + { 0xff1211bd, BTTV_BOARD_PINNACLE, "Pinnacle PCTV" }, + + { 0x3000121a, BTTV_BOARD_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" }, + { 0x263710b4, BTTV_BOARD_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" }, + { 0x3060121a, BTTV_BOARD_STB2, "3Dfx VoodooTV 100/ STB OEM" }, + + { 0x3000144f, BTTV_BOARD_MAGICTVIEW063, "(Askey Magic/others) TView99 CPH06x" }, + { 0xa005144f, BTTV_BOARD_MAGICTVIEW063, "CPH06X TView99-Card" }, + { 0x3002144f, BTTV_BOARD_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH05x" }, + { 0x3005144f, BTTV_BOARD_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH061/06L (T1/LC)" }, + { 0x5000144f, BTTV_BOARD_MAGICTVIEW061, "Askey CPH050" }, + { 0x300014ff, BTTV_BOARD_MAGICTVIEW061, "TView 99 (CPH061)" }, + { 0x300214ff, BTTV_BOARD_PHOEBE_TVMAS, "Phoebe TV Master (CPH060)" }, + + { 0x00011461, BTTV_BOARD_AVPHONE98, "AVerMedia TVPhone98" }, + { 0x00021461, BTTV_BOARD_AVERMEDIA98, "AVermedia TVCapture 98" }, + { 0x00031461, BTTV_BOARD_AVPHONE98, "AVerMedia TVPhone98" }, + { 0x00041461, BTTV_BOARD_AVERMEDIA98, "AVerMedia TVCapture 98" }, + { 0x03001461, BTTV_BOARD_AVERMEDIA98, "VDOMATE TV TUNER CARD" }, + + { 0x1117153b, BTTV_BOARD_TERRATVALUE, "Terratec TValue (Philips PAL B/G)" }, + { 0x1118153b, BTTV_BOARD_TERRATVALUE, "Terratec TValue (Temic PAL B/G)" }, + { 0x1119153b, BTTV_BOARD_TERRATVALUE, "Terratec TValue (Philips PAL I)" }, + { 0x111a153b, BTTV_BOARD_TERRATVALUE, "Terratec TValue (Temic PAL I)" }, + + { 0x1123153b, BTTV_BOARD_TERRATVRADIO, "Terratec TV Radio+" }, + { 0x1127153b, BTTV_BOARD_TERRATV, "Terratec TV+ (V1.05)" }, /* clashes with FlyVideo - *{ 0x18521852, BTTV_TERRATV, "Terratec TV+ (V1.10)" }, */ - { 0x1134153b, BTTV_TERRATVALUE, "Terratec TValue (LR102)" }, - { 0x1135153b, BTTV_TERRATVALUER, "Terratec TValue Radio" }, /* LR102 */ - { 0x5018153b, BTTV_TERRATVALUE, "Terratec TValue" }, /* ?? */ - { 0xff3b153b, BTTV_TERRATVALUER, "Terratec TValue Radio" }, /* ?? */ - - { 0x400015b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV" }, - { 0x400a15b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV" }, - { 0x400d15b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" }, - { 0x401015b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" }, - { 0x401615b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" }, - - { 0x1430aa00, BTTV_PV143, "Provideo PV143A" }, - { 0x1431aa00, BTTV_PV143, "Provideo PV143B" }, - { 0x1432aa00, BTTV_PV143, "Provideo PV143C" }, - { 0x1433aa00, BTTV_PV143, "Provideo PV143D" }, - { 0x1433aa03, BTTV_PV143, "Security Eyes" }, - - { 0x1460aa00, BTTV_PV150, "Provideo PV150A-1" }, - { 0x1461aa01, BTTV_PV150, "Provideo PV150A-2" }, - { 0x1462aa02, BTTV_PV150, "Provideo PV150A-3" }, - { 0x1463aa03, BTTV_PV150, "Provideo PV150A-4" }, - - { 0x1464aa04, BTTV_PV150, "Provideo PV150B-1" }, - { 0x1465aa05, BTTV_PV150, "Provideo PV150B-2" }, - { 0x1466aa06, BTTV_PV150, "Provideo PV150B-3" }, - { 0x1467aa07, BTTV_PV150, "Provideo PV150B-4" }, - - { 0xa132ff00, BTTV_IVC100, "IVC-100" }, - { 0xa1550000, BTTV_IVC200, "IVC-200" }, - { 0xa1550001, BTTV_IVC200, "IVC-200" }, - { 0xa1550002, BTTV_IVC200, "IVC-200" }, - { 0xa1550003, BTTV_IVC200, "IVC-200" }, - { 0xa1550100, BTTV_IVC200, "IVC-200G" }, - { 0xa1550101, BTTV_IVC200, "IVC-200G" }, - { 0xa1550102, BTTV_IVC200, "IVC-200G" }, - { 0xa1550103, BTTV_IVC200, "IVC-200G" }, - { 0xa182ff00, BTTV_IVC120, "IVC-120G" }, - { 0xa182ff01, BTTV_IVC120, "IVC-120G" }, - { 0xa182ff02, BTTV_IVC120, "IVC-120G" }, - { 0xa182ff03, BTTV_IVC120, "IVC-120G" }, - { 0xa182ff04, BTTV_IVC120, "IVC-120G" }, - { 0xa182ff05, BTTV_IVC120, "IVC-120G" }, - { 0xa182ff06, BTTV_IVC120, "IVC-120G" }, - { 0xa182ff07, BTTV_IVC120, "IVC-120G" }, - { 0xa182ff08, BTTV_IVC120, "IVC-120G" }, - { 0xa182ff09, BTTV_IVC120, "IVC-120G" }, - { 0xa182ff0a, BTTV_IVC120, "IVC-120G" }, - { 0xa182ff0b, BTTV_IVC120, "IVC-120G" }, - { 0xa182ff0c, BTTV_IVC120, "IVC-120G" }, - { 0xa182ff0d, BTTV_IVC120, "IVC-120G" }, - { 0xa182ff0e, BTTV_IVC120, "IVC-120G" }, - { 0xa182ff0f, BTTV_IVC120, "IVC-120G" }, - - { 0x41424344, BTTV_GRANDTEC, "GrandTec Multi Capture" }, - { 0x01020304, BTTV_XGUARD, "Grandtec Grand X-Guard" }, - - { 0x18501851, BTTV_CHRONOS_VS2, "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" }, - { 0xa0501851, BTTV_CHRONOS_VS2, "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" }, - { 0x18511851, BTTV_FLYVIDEO98EZ, "FlyVideo 98EZ (LR51)/ CyberMail AV" }, - { 0x18521852, BTTV_TYPHOON_TVIEW, "FlyVideo 98FM (LR50)/ Typhoon TView TV/FM Tuner" }, - { 0x41a0a051, BTTV_FLYVIDEO_98FM, "Lifeview FlyVideo 98 LR50 Rev Q" }, - { 0x18501f7f, BTTV_FLYVIDEO_98, "Lifeview Flyvideo 98" }, - - { 0x010115cb, BTTV_GMV1, "AG GMV1" }, - { 0x010114c7, BTTV_MODTEC_205, "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV" }, - - { 0x10b42636, BTTV_HAUPPAUGE878, "STB ???" }, - { 0x217d6606, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" }, - { 0xfff6f6ff, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" }, - { 0x03116000, BTTV_SENSORAY311, "Sensoray 311" }, - { 0x00790e11, BTTV_WINDVR, "Canopus WinDVR PCI" }, - { 0xa0fca1a0, BTTV_ZOLTRIX, "Face to Face Tvmax" }, - { 0x20007063, BTTV_PC_HDTV, "pcHDTV HD-2000 TV"}, - { 0x82b2aa6a, BTTV_SIMUS_GVC1100, "SIMUS GVC1100" }, - { 0x146caa0c, BTTV_PV951, "ituner spectra8" }, - { 0x200a1295, BTTV_PXC200, "ImageNation PXC200A" }, - - { 0x40111554, BTTV_PV_BT878P_9B, "Prolink Pixelview PV-BT" }, - { 0x17de0a01, BTTV_KWORLD, "Mecer TV/FM/Video Tuner" }, - - { 0x01051805, BTTV_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #1" }, - { 0x01061805, BTTV_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #2" }, - { 0x01071805, BTTV_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #3" }, - { 0x01081805, BTTV_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #4" }, - - { 0x15409511, BTTV_ACORP_Y878F, "Acorp Y878F" }, + *{ 0x18521852, BTTV_BOARD_TERRATV, "Terratec TV+ (V1.10)" }, */ + { 0x1134153b, BTTV_BOARD_TERRATVALUE, "Terratec TValue (LR102)" }, + { 0x1135153b, BTTV_BOARD_TERRATVALUER, "Terratec TValue Radio" }, /* LR102 */ + { 0x5018153b, BTTV_BOARD_TERRATVALUE, "Terratec TValue" }, /* ?? */ + { 0xff3b153b, BTTV_BOARD_TERRATVALUER, "Terratec TValue Radio" }, /* ?? */ + + { 0x400015b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV" }, + { 0x400a15b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV" }, + { 0x400d15b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" }, + { 0x401015b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" }, + { 0x401615b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" }, + + { 0x1430aa00, BTTV_BOARD_PV143, "Provideo PV143A" }, + { 0x1431aa00, BTTV_BOARD_PV143, "Provideo PV143B" }, + { 0x1432aa00, BTTV_BOARD_PV143, "Provideo PV143C" }, + { 0x1433aa00, BTTV_BOARD_PV143, "Provideo PV143D" }, + { 0x1433aa03, BTTV_BOARD_PV143, "Security Eyes" }, + + { 0x1460aa00, BTTV_BOARD_PV150, "Provideo PV150A-1" }, + { 0x1461aa01, BTTV_BOARD_PV150, "Provideo PV150A-2" }, + { 0x1462aa02, BTTV_BOARD_PV150, "Provideo PV150A-3" }, + { 0x1463aa03, BTTV_BOARD_PV150, "Provideo PV150A-4" }, + + { 0x1464aa04, BTTV_BOARD_PV150, "Provideo PV150B-1" }, + { 0x1465aa05, BTTV_BOARD_PV150, "Provideo PV150B-2" }, + { 0x1466aa06, BTTV_BOARD_PV150, "Provideo PV150B-3" }, + { 0x1467aa07, BTTV_BOARD_PV150, "Provideo PV150B-4" }, + + { 0xa132ff00, BTTV_BOARD_IVC100, "IVC-100" }, + { 0xa1550000, BTTV_BOARD_IVC200, "IVC-200" }, + { 0xa1550001, BTTV_BOARD_IVC200, "IVC-200" }, + { 0xa1550002, BTTV_BOARD_IVC200, "IVC-200" }, + { 0xa1550003, BTTV_BOARD_IVC200, "IVC-200" }, + { 0xa1550100, BTTV_BOARD_IVC200, "IVC-200G" }, + { 0xa1550101, BTTV_BOARD_IVC200, "IVC-200G" }, + { 0xa1550102, BTTV_BOARD_IVC200, "IVC-200G" }, + { 0xa1550103, BTTV_BOARD_IVC200, "IVC-200G" }, + { 0xa182ff00, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff01, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff02, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff03, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff04, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff05, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff06, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff07, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff08, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff09, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff0a, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff0b, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff0c, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff0d, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff0e, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xa182ff0f, BTTV_BOARD_IVC120, "IVC-120G" }, + + { 0x41424344, BTTV_BOARD_GRANDTEC, "GrandTec Multi Capture" }, + { 0x01020304, BTTV_BOARD_XGUARD, "Grandtec Grand X-Guard" }, + + { 0x18501851, BTTV_BOARD_CHRONOS_VS2, "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" }, + { 0xa0501851, BTTV_BOARD_CHRONOS_VS2, "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" }, + { 0x18511851, BTTV_BOARD_FLYVIDEO98EZ, "FlyVideo 98EZ (LR51)/ CyberMail AV" }, + { 0x18521852, BTTV_BOARD_TYPHOON_TVIEW, "FlyVideo 98FM (LR50)/ Typhoon TView TV/FM Tuner" }, + { 0x41a0a051, BTTV_BOARD_FLYVIDEO_98FM, "Lifeview FlyVideo 98 LR50 Rev Q" }, + { 0x18501f7f, BTTV_BOARD_FLYVIDEO_98, "Lifeview Flyvideo 98" }, + + { 0x010115cb, BTTV_BOARD_GMV1, "AG GMV1" }, + { 0x010114c7, BTTV_BOARD_MODTEC_205, "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV" }, + + { 0x10b42636, BTTV_BOARD_HAUPPAUGE878, "STB ???" }, + { 0x217d6606, BTTV_BOARD_WINFAST2000, "Leadtek WinFast TV 2000" }, + { 0xfff6f6ff, BTTV_BOARD_WINFAST2000, "Leadtek WinFast TV 2000" }, + { 0x03116000, BTTV_BOARD_SENSORAY311, "Sensoray 311" }, + { 0x00790e11, BTTV_BOARD_WINDVR, "Canopus WinDVR PCI" }, + { 0xa0fca1a0, BTTV_BOARD_ZOLTRIX, "Face to Face Tvmax" }, + { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV"}, + { 0x82b2aa6a, BTTV_BOARD_SIMUS_GVC1100, "SIMUS GVC1100" }, + { 0x146caa0c, BTTV_BOARD_PV951, "ituner spectra8" }, + { 0x200a1295, BTTV_BOARD_PXC200, "ImageNation PXC200A" }, + + { 0x40111554, BTTV_BOARD_PV_BT878P_9B, "Prolink Pixelview PV-BT" }, + { 0x17de0a01, BTTV_BOARD_KWORLD, "Mecer TV/FM/Video Tuner" }, + + { 0x01051805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #1" }, + { 0x01061805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #2" }, + { 0x01071805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #3" }, + { 0x01081805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #4" }, + + { 0x15409511, BTTV_BOARD_ACORP_Y878F, "Acorp Y878F" }, /* likely broken, vendor id doesn't match the other magic views ... - * { 0xa0fca04f, BTTV_MAGICTVIEW063, "Guillemot Maxi TV Video 3" }, */ + * { 0xa0fca04f, BTTV_BOARD_MAGICTVIEW063, "Guillemot Maxi TV Video 3" }, */ /* DVB cards (using pci function .1 for mpeg data xfer) */ - { 0x01010071, BTTV_NEBULA_DIGITV, "Nebula Electronics DigiTV" }, - { 0x07611461, BTTV_AVDVBT_761, "AverMedia AverTV DVB-T 761" }, - { 0x001c11bd, BTTV_PINNACLESAT, "Pinnacle PCTV Sat" }, - { 0x002611bd, BTTV_TWINHAN_DST, "Pinnacle PCTV SAT CI" }, - { 0x00011822, BTTV_TWINHAN_DST, "Twinhan VisionPlus DVB" }, - { 0xfc00270f, BTTV_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" }, - { 0x07711461, BTTV_AVDVBT_771, "AVermedia AverTV DVB-T 771" }, - { 0xdb1018ac, BTTV_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" }, - { 0xd50018ac, BTTV_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" }, + { 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" }, + { 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" }, + { 0x001c11bd, BTTV_BOARD_PINNACLESAT, "Pinnacle PCTV Sat" }, + { 0x002611bd, BTTV_BOARD_TWINHAN_DST, "Pinnacle PCTV SAT CI" }, + { 0x00011822, BTTV_BOARD_TWINHAN_DST, "Twinhan VisionPlus DVB" }, + { 0xfc00270f, BTTV_BOARD_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" }, + { 0x07711461, BTTV_BOARD_AVDVBT_771, "AVermedia AverTV DVB-T 771" }, + { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" }, + { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" }, { 0, -1, NULL } }; @@ -309,8 +309,8 @@ static struct CARD { /* array with description for bt848 / bt878 tv/grabber cards */ struct tvcard bttv_tvcards[] = { - [BTTV_UNKNOWN] = { /* ---- card 0x00 ---------------------------------- */ + [BTTV_BOARD_UNKNOWN] = { .name = " *** UNKNOWN/GENERIC *** ", .video_inputs = 4, .audio_inputs = 1, @@ -320,7 +320,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_MIRO] = { + [BTTV_BOARD_MIRO] = { .name = "MIRO PCTV", .video_inputs = 4, .audio_inputs = 1, @@ -333,7 +333,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_HAUPPAUGE] = { + [BTTV_BOARD_HAUPPAUGE] = { .name = "Hauppauge (bt848)", .video_inputs = 4, .audio_inputs = 1, @@ -346,7 +346,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_STB] = { + [BTTV_BOARD_STB] = { .name = "STB, Gateway P/N 6000699 (bt848)", .video_inputs = 3, .audio_inputs = 1, @@ -364,7 +364,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x04 ---------------------------------- */ - [BTTV_INTEL] = { + [BTTV_BOARD_INTEL] = { .name = "Intel Create and Share PCI/ Smart Video Recorder III", .video_inputs = 4, .audio_inputs = 0, @@ -377,7 +377,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = 4, .tuner_addr = ADDR_UNSET, }, - [BTTV_DIAMOND] = { + [BTTV_BOARD_DIAMOND] = { .name = "Diamond DTV2000", .video_inputs = 4, .audio_inputs = 1, @@ -390,7 +390,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_AVERMEDIA] = { + [BTTV_BOARD_AVERMEDIA] = { .name = "AVerMedia TVPhone", .video_inputs = 3, .audio_inputs = 1, @@ -406,7 +406,7 @@ struct tvcard bttv_tvcards[] = { .audio_hook = avermedia_tvphone_audio, .has_remote = 1, }, - [BTTV_MATRIX_VISION] = { + [BTTV_BOARD_MATRIX_VISION] = { .name = "MATRIX-Vision MV-Delta", .video_inputs = 5, .audio_inputs = 1, @@ -421,7 +421,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x08 ---------------------------------- */ - [BTTV_FLYVIDEO] = { + [BTTV_BOARD_FLYVIDEO] = { .name = "Lifeview FlyVideo II (Bt848) LR26 / MAXI TV Video PCI2 LR26", .video_inputs = 4, .audio_inputs = 1, @@ -435,7 +435,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_TURBOTV] = { + [BTTV_BOARD_TURBOTV] = { .name = "IMS/IXmicro TurboTV", .video_inputs = 3, .audio_inputs = 1, @@ -449,7 +449,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_TEMIC_PAL, .tuner_addr = ADDR_UNSET, }, - [BTTV_HAUPPAUGE878] = { + [BTTV_BOARD_HAUPPAUGE878] = { .name = "Hauppauge (bt878)", .video_inputs = 4, .audio_inputs = 1, @@ -463,7 +463,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_MIROPRO] = { + [BTTV_BOARD_MIROPRO] = { .name = "MIRO PCTV pro", .video_inputs = 3, .audio_inputs = 1, @@ -478,7 +478,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x0c ---------------------------------- */ - [BTTV_ADSTECH_TV] = { + [BTTV_BOARD_ADSTECH_TV] = { .name = "ADS Technologies Channel Surfer TV (bt848)", .video_inputs = 3, .audio_inputs = 1, @@ -491,7 +491,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_AVERMEDIA98] = { + [BTTV_BOARD_AVERMEDIA98] = { .name = "AVerMedia TVCapture 98", .video_inputs = 3, .audio_inputs = 4, @@ -507,7 +507,7 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .audio_hook = avermedia_tv_stereo_audio, }, - [BTTV_VHX] = { + [BTTV_BOARD_VHX] = { .name = "Aimslab Video Highway Xtreme (VHX)", .video_inputs = 3, .audio_inputs = 1, @@ -521,7 +521,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_ZOLTRIX] = { + [BTTV_BOARD_ZOLTRIX] = { .name = "Zoltrix TV-Max", .video_inputs = 3, .audio_inputs = 1, @@ -536,7 +536,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x10 ---------------------------------- */ - [BTTV_PIXVIEWPLAYTV] = { + [BTTV_BOARD_PIXVIEWPLAYTV] = { .name = "Prolink Pixelview PlayTV (bt878)", .video_inputs = 3, .audio_inputs = 1, @@ -555,7 +555,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, }, - [BTTV_WINVIEW_601] = { + [BTTV_BOARD_WINVIEW_601] = { .name = "Leadtek WinView 601", .video_inputs = 3, .audio_inputs = 1, @@ -570,7 +570,7 @@ struct tvcard bttv_tvcards[] = { .audio_hook = winview_audio, .has_radio = 1, }, - [BTTV_AVEC_INTERCAP] = { + [BTTV_BOARD_AVEC_INTERCAP] = { .name = "AVEC Intercapture", .video_inputs = 3, .audio_inputs = 2, @@ -583,7 +583,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_LIFE_FLYKIT] = { + [BTTV_BOARD_LIFE_FLYKIT] = { .name = "Lifeview FlyVideo II EZ /FlyKit LR38 Bt848 (capture only)", .video_inputs = 4, .audio_inputs = 1, @@ -598,7 +598,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x14 ---------------------------------- */ - [BTTV_CEI_RAFFLES] = { + [BTTV_BOARD_CEI_RAFFLES] = { .name = "CEI Raffles Card", .video_inputs = 3, .audio_inputs = 3, @@ -608,7 +608,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_CONFERENCETV] = { + [BTTV_BOARD_CONFERENCETV] = { .name = "Lifeview FlyVideo 98/ Lucky Star Image World ConferenceTV LR50", .video_inputs = 4, .audio_inputs = 2, /* tuner, line in */ @@ -621,7 +621,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_PHILIPS_PAL_I, .tuner_addr = ADDR_UNSET, }, - [BTTV_PHOEBE_TVMAS] = { + [BTTV_BOARD_PHOEBE_TVMAS] = { .name = "Askey CPH050/ Phoebe Tv Master + FM", .video_inputs = 3, .audio_inputs = 1, @@ -635,7 +635,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_MODTEC_205] = { + [BTTV_BOARD_MODTEC_205] = { .name = "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV, bt878", .video_inputs = 3, .audio_inputs = 1, @@ -652,7 +652,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x18 ---------------------------------- */ - [BTTV_MAGICTVIEW061] = { + [BTTV_BOARD_MAGICTVIEW061] = { .name = "Askey CPH05X/06X (bt878) [many vendors]", .video_inputs = 3, .audio_inputs = 1, @@ -667,7 +667,7 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .has_remote = 1, }, - [BTTV_VOBIS_BOOSTAR] = { + [BTTV_BOARD_VOBIS_BOOSTAR] = { .name = "Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar", .video_inputs = 3, .audio_inputs = 1, @@ -681,7 +681,7 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .audio_hook = terratv_audio, }, - [BTTV_HAUPPAUG_WCAM] = { + [BTTV_BOARD_HAUPPAUG_WCAM] = { .name = "Hauppauge WinCam newer (bt878)", .video_inputs = 4, .audio_inputs = 1, @@ -694,7 +694,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_MAXI] = { + [BTTV_BOARD_MAXI] = { .name = "Lifeview FlyVideo 98/ MAXI TV Video PCI2 LR50", .video_inputs = 4, .audio_inputs = 2, @@ -709,7 +709,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x1c ---------------------------------- */ - [BTTV_TERRATV] = { + [BTTV_BOARD_TERRATV] = { .name = "Terratec TerraTV+ Version 1.1 (bt878)", .video_inputs = 3, .audio_inputs = 1, @@ -754,7 +754,7 @@ struct tvcard bttv_tvcards[] = { */ }, - [BTTV_PXC200] = { + [BTTV_BOARD_PXC200] = { /* Jannik Fritsch */ .name = "Imagenation PXC200", .video_inputs = 5, @@ -770,7 +770,7 @@ struct tvcard bttv_tvcards[] = { .muxsel_hook = PXC200_muxsel, }, - [BTTV_FLYVIDEO_98] = { + [BTTV_BOARD_FLYVIDEO_98] = { .name = "Lifeview FlyVideo 98 LR50", .video_inputs = 4, .audio_inputs = 1, @@ -783,7 +783,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_IPROTV] = { + [BTTV_BOARD_IPROTV] = { .name = "Formac iProTV, Formac ProTV I (bt848)", .video_inputs = 4, .audio_inputs = 1, @@ -798,7 +798,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x20 ---------------------------------- */ - [BTTV_INTEL_C_S_PCI] = { + [BTTV_BOARD_INTEL_C_S_PCI] = { .name = "Intel Create and Share PCI/ Smart Video Recorder III", .video_inputs = 4, .audio_inputs = 0, @@ -811,7 +811,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = 4, .tuner_addr = ADDR_UNSET, }, - [BTTV_TERRATVALUE] = { + [BTTV_BOARD_TERRATVALUE] = { .name = "Terratec TerraTValue Version Bt878", .video_inputs = 3, .audio_inputs = 1, @@ -825,7 +825,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, }, - [BTTV_WINFAST2000] = { + [BTTV_BOARD_WINFAST2000] = { .name = "Leadtek WinFast 2000/ WinFast 2000 XP", .video_inputs = 4, .audio_inputs = 1, @@ -859,7 +859,7 @@ struct tvcard bttv_tvcards[] = { .audio_hook = winfast2000_audio, .has_remote = 1, }, - [BTTV_CHRONOS_VS2] = { + [BTTV_BOARD_CHRONOS_VS2] = { .name = "Lifeview FlyVideo 98 LR50 / Chronos Video Shuttle II", .video_inputs = 4, .audio_inputs = 3, @@ -874,7 +874,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x24 ---------------------------------- */ - [BTTV_TYPHOON_TVIEW] = { + [BTTV_BOARD_TYPHOON_TVIEW] = { .name = "Lifeview FlyVideo 98FM LR50 / Typhoon TView TV/FM Tuner", .video_inputs = 4, .audio_inputs = 3, @@ -888,7 +888,7 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .has_radio = 1, }, - [BTTV_PXELVWPLTVPRO] = { + [BTTV_BOARD_PXELVWPLTVPRO] = { .name = "Prolink PixelView PlayTV pro", .video_inputs = 3, .audio_inputs = 1, @@ -902,7 +902,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_MAGICTVIEW063] = { + [BTTV_BOARD_MAGICTVIEW063] = { .name = "Askey CPH06X TView99", .video_inputs = 4, .audio_inputs = 1, @@ -917,7 +917,7 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .has_remote = 1, }, - [BTTV_PINNACLE] = { + [BTTV_BOARD_PINNACLE] = { .name = "Pinnacle PCTV Studio/Rave", .video_inputs = 3, .audio_inputs = 1, @@ -933,7 +933,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x28 ---------------------------------- */ - [BTTV_STB2] = { + [BTTV_BOARD_STB2] = { .name = "STB TV PCI FM, Gateway P/N 6000704 (bt878), 3Dfx VoodooTV 100", .video_inputs = 3, .audio_inputs = 1, @@ -949,7 +949,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .has_radio = 1, }, - [BTTV_AVPHONE98] = { + [BTTV_BOARD_AVPHONE98] = { .name = "AVerMedia TVPhone 98", .video_inputs = 3, .audio_inputs = 4, @@ -965,7 +965,7 @@ struct tvcard bttv_tvcards[] = { .has_radio = 1, .audio_hook = avermedia_tvphone_audio, }, - [BTTV_PV951] = { + [BTTV_BOARD_PV951] = { .name = "ProVideo PV951", /* pic16c54 */ .video_inputs = 3, .audio_inputs = 1, @@ -980,7 +980,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = 1, .tuner_addr = ADDR_UNSET, }, - [BTTV_ONAIR_TV] = { + [BTTV_BOARD_ONAIR_TV] = { .name = "Little OnAir TV", .video_inputs = 3, .audio_inputs = 1, @@ -995,7 +995,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x2c ---------------------------------- */ - [BTTV_SIGMA_TVII_FM] = { + [BTTV_BOARD_SIGMA_TVII_FM] = { .name = "Sigma TVII-FM", .video_inputs = 2, .audio_inputs = 1, @@ -1009,7 +1009,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_MATRIX_VISION2] = { + [BTTV_BOARD_MATRIX_VISION2] = { .name = "MATRIX-Vision MV-Delta 2", .video_inputs = 5, .audio_inputs = 1, @@ -1023,7 +1023,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_ZOLTRIX_GENIE] = { + [BTTV_BOARD_ZOLTRIX_GENIE] = { .name = "Zoltrix Genie TV/FM", .video_inputs = 3, .audio_inputs = 1, @@ -1037,7 +1037,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = 21, .tuner_addr = ADDR_UNSET, }, - [BTTV_TERRATVRADIO] = { + [BTTV_BOARD_TERRATVRADIO] = { .name = "Terratec TV/Radio+", .video_inputs = 3, .audio_inputs = 1, @@ -1055,7 +1055,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x30 ---------------------------------- */ - [BTTV_DYNALINK] = { + [BTTV_BOARD_DYNALINK] = { .name = "Askey CPH03x/ Dynalink Magic TView", .video_inputs = 3, .audio_inputs = 1, @@ -1069,7 +1069,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_GVBCTV3PCI] = { + [BTTV_BOARD_GVBCTV3PCI] = { .name = "IODATA GV-BCTV3/PCI", .video_inputs = 3, .audio_inputs = 1, @@ -1084,7 +1084,7 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .audio_hook = gvbctv3pci_audio, }, - [BTTV_PXELVWPLTVPAK] = { + [BTTV_BOARD_PXELVWPLTVPAK] = { .name = "Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP", .video_inputs = 5, .audio_inputs = 1, @@ -1109,7 +1109,7 @@ struct tvcard bttv_tvcards[] = { Note: At i2c=0x8a is a Bt832 chip, which changes to 0x88 after being reset via GPIO22 */ }, - [BTTV_EAGLE] = { + [BTTV_BOARD_EAGLE] = { .name = "Eagle Wireless Capricorn2 (bt878A)", .video_inputs = 4, .audio_inputs = 1, @@ -1124,7 +1124,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x34 ---------------------------------- */ - [BTTV_PINNACLEPRO] = { + [BTTV_BOARD_PINNACLEPRO] = { /* David Härdeman */ .name = "Pinnacle PCTV Studio Pro", .video_inputs = 4, @@ -1148,7 +1148,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_TVIEW_RDS_FM] = { + [BTTV_BOARD_TVIEW_RDS_FM] = { /* Claas Langbehn , Sven Grothklags */ .name = "Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS", @@ -1165,7 +1165,7 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .has_radio = 1, }, - [BTTV_LIFETEC_9415] = { + [BTTV_BOARD_LIFETEC_9415] = { /* Tim Röstermundt in de.comp.os.unix.linux.hardware: options bttv card=0 pll=1 radio=1 gpiomask=0x18e0 @@ -1187,7 +1187,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_BESTBUY_EASYTV] = { + [BTTV_BOARD_BESTBUY_EASYTV] = { /* Miguel Angel Alvarez old Easy TV BT848 version (model CPH031) */ .name = "Askey CPH031/ BESTBUY Easy TV", @@ -1205,7 +1205,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x38 ---------------------------------- */ - [BTTV_FLYVIDEO_98FM] = { + [BTTV_BOARD_FLYVIDEO_98FM] = { /* Gordon Heydon */ - [BTTV_GRANDTEC] = { + [BTTV_BOARD_GRANDTEC] = { .name = "GrandTec 'Grand Video Capture' (Bt848)", .video_inputs = 2, .audio_inputs = 0, @@ -1237,7 +1237,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_ASKEY_CPH060] = { + [BTTV_BOARD_ASKEY_CPH060] = { /* Daniel Herrington */ .name = "Askey CPH060/ Phoebe TV Master Only (No FM)", .video_inputs = 3, @@ -1252,7 +1252,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_TEMIC_4036FY5_NTSC, .tuner_addr = ADDR_UNSET, }, - [BTTV_ASKEY_CPH03X] = { + [BTTV_BOARD_ASKEY_CPH03X] = { /* Matti Mottus */ .name = "Askey CPH03x TV Capturer", .video_inputs = 4, @@ -1268,7 +1268,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x3c ---------------------------------- */ - [BTTV_MM100PCTV] = { + [BTTV_BOARD_MM100PCTV] = { /* Philip Blundell */ .name = "Modular Technology MM100PCTV", .video_inputs = 2, @@ -1282,7 +1282,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_TEMIC_PAL, .tuner_addr = ADDR_UNSET, }, - [BTTV_GMV1] = { + [BTTV_BOARD_GMV1] = { /* Adrian Cox new Easy TV BT878 version (model CPH061) special thanks to Informatica Mieres for providing the card */ @@ -1315,7 +1315,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, }, - [BTTV_ATI_TVWONDER] = { + [BTTV_BOARD_ATI_TVWONDER] = { /* Lukas Gebauer */ .name = "ATI TV-Wonder", .video_inputs = 3, @@ -1331,7 +1331,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x40 ---------------------------------- */ - [BTTV_ATI_TVWONDERVE] = { + [BTTV_BOARD_ATI_TVWONDERVE] = { /* Lukas Gebauer */ .name = "ATI TV-Wonder VE", .video_inputs = 2, @@ -1346,7 +1346,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL, .tuner_addr = ADDR_UNSET, }, - [BTTV_FLYVIDEO2000] = { + [BTTV_BOARD_FLYVIDEO2000] = { /* DeeJay */ .name = "IODATA GV-BCTV4/PCI", .video_inputs = 3, @@ -1400,7 +1400,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x44 ---------------------------------- */ - [BTTV_VOODOOTV_FM] = { + [BTTV_BOARD_VOODOOTV_FM] = { .name = "3Dfx VoodooTV FM (Euro), VoodooTV 200 (USA)", /* try "insmod msp3400 simple=0" if you have * sound problems with this card. */ @@ -1420,7 +1420,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .has_radio = 1, }, - [BTTV_AIMMS] = { + [BTTV_BOARD_AIMMS] = { /* Philip Blundell */ .name = "Active Imaging AIMMS", .video_inputs = 1, @@ -1432,7 +1432,7 @@ struct tvcard bttv_tvcards[] = { .muxsel = { 2 }, .gpiomask = 0 }, - [BTTV_PV_BT878P_PLUS] = { + [BTTV_BOARD_PV_BT878P_PLUS] = { /* Tomasz Pyra */ .name = "Prolink Pixelview PV-BT878P+ (Rev.4C,8E)", .video_inputs = 3, @@ -1455,7 +1455,7 @@ struct tvcard bttv_tvcards[] = { GPIO8-15: vrd866b ? */ }, - [BTTV_FLYVIDEO98EZ] = { + [BTTV_BOARD_FLYVIDEO98EZ] = { .name = "Lifeview FlyVideo 98EZ (capture only) LR51", .video_inputs = 4, .audio_inputs = 0, @@ -1469,7 +1469,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x48 ---------------------------------- */ - [BTTV_PV_BT878P_9B] = { + [BTTV_BOARD_PV_BT878P_9B] = { /* Dariusz Kowalewski */ .name = "Prolink Pixelview PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM)", .video_inputs = 4, @@ -1496,7 +1496,7 @@ struct tvcard bttv_tvcards[] = { GPIO20,22,23: R30,R29,R28 */ }, - [BTTV_SENSORAY311] = { + [BTTV_BOARD_SENSORAY311] = { /* Clay Kunz */ /* you must jumper JP5 for the card to work */ .name = "Sensoray 311", @@ -1511,7 +1511,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_RV605] = { + [BTTV_BOARD_RV605] = { /* Miguel Freitas */ .name = "RemoteVision MX (RV605)", .video_inputs = 16, @@ -1528,7 +1528,7 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .muxsel_hook = rv605_muxsel, }, - [BTTV_POWERCLR_MTV878] = { + [BTTV_BOARD_POWERCLR_MTV878] = { .name = "Powercolor MTV878/ MTV878R/ MTV878F", .video_inputs = 3, .audio_inputs = 2, @@ -1545,7 +1545,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x4c ---------------------------------- */ - [BTTV_WINDVR] = { + [BTTV_BOARD_WINDVR] = { /* Masaki Suzuki */ .name = "Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP)", .video_inputs = 3, @@ -1559,7 +1559,7 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .audio_hook = windvr_audio, }, - [BTTV_GRANDTEC_MULTI] = { + [BTTV_BOARD_GRANDTEC_MULTI] = { .name = "GrandTec Multi Capture Card (Bt878)", .video_inputs = 4, .audio_inputs = 0, @@ -1574,7 +1574,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_KWORLD] = { + [BTTV_BOARD_KWORLD] = { .name = "Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF", .video_inputs = 4, .audio_inputs = 3, @@ -1607,7 +1607,7 @@ struct tvcard bttv_tvcards[] = { GPIO22,23: ?? ?? : mtu8b56ep microcontroller for IR (GPIO wiring unknown)*/ }, - [BTTV_DSP_TCVIDEO] = { + [BTTV_BOARD_DSP_TCVIDEO] = { /* Arthur Tetzlaff-Deas, DSP Design Ltd */ .name = "DSP Design TCVIDEO", .video_inputs = 4, @@ -1619,7 +1619,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x50 ---------------------------------- */ - [BTTV_HAUPPAUGEPVR] = { + [BTTV_BOARD_HAUPPAUGEPVR] = { .name = "Hauppauge WinTV PVR", .video_inputs = 4, .audio_inputs = 1, @@ -1634,7 +1634,7 @@ struct tvcard bttv_tvcards[] = { .gpiomask = 7, .audiomux = {7}, }, - [BTTV_GVBCTV5PCI] = { + [BTTV_BOARD_GVBCTV5PCI] = { .name = "IODATA GV-BCTV5/PCI", .video_inputs = 3, .audio_inputs = 1, @@ -1650,7 +1650,7 @@ struct tvcard bttv_tvcards[] = { .audio_hook = gvbctv5pci_audio, .has_radio = 1, }, - [BTTV_OSPREY1x0] = { + [BTTV_BOARD_OSPREY1x0] = { .name = "Osprey 100/150 (878)", /* 0x1(2|3)-45C6-C1 */ .video_inputs = 4, /* id-inputs-clock */ .audio_inputs = 0, @@ -1664,7 +1664,7 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .no_tda7432 = 1, }, - [BTTV_OSPREY1x0_848] = { + [BTTV_BOARD_OSPREY1x0_848] = { .name = "Osprey 100/150 (848)", /* 0x04-54C0-C1 & older boards */ .video_inputs = 3, .audio_inputs = 0, @@ -1680,7 +1680,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x54 ---------------------------------- */ - [BTTV_OSPREY101_848] = { + [BTTV_BOARD_OSPREY101_848] = { .name = "Osprey 101 (848)", /* 0x05-40C0-C1 */ .video_inputs = 2, .audio_inputs = 0, @@ -1694,7 +1694,7 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .no_tda7432 = 1, }, - [BTTV_OSPREY1x1] = { + [BTTV_BOARD_OSPREY1x1] = { .name = "Osprey 101/151", /* 0x1(4|5)-0004-C4 */ .video_inputs = 1, .audio_inputs = 0, @@ -1708,7 +1708,7 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .no_tda7432 = 1, }, - [BTTV_OSPREY1x1_SVID] = { + [BTTV_BOARD_OSPREY1x1_SVID] = { .name = "Osprey 101/151 w/ svid", /* 0x(16|17|20)-00C4-C1 */ .video_inputs = 2, .audio_inputs = 0, @@ -1722,7 +1722,7 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .no_tda7432 = 1, }, - [BTTV_OSPREY2xx] = { + [BTTV_BOARD_OSPREY2xx] = { .name = "Osprey 200/201/250/251", /* 0x1(8|9|E|F)-0004-C4 */ .video_inputs = 1, .audio_inputs = 1, @@ -1738,7 +1738,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x58 ---------------------------------- */ - [BTTV_OSPREY2x0_SVID] = { + [BTTV_BOARD_OSPREY2x0_SVID] = { .name = "Osprey 200/250", /* 0x1(A|B)-00C4-C1 */ .video_inputs = 2, .audio_inputs = 1, @@ -1752,7 +1752,7 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .no_tda7432 = 1, }, - [BTTV_OSPREY2x0] = { + [BTTV_BOARD_OSPREY2x0] = { .name = "Osprey 210/220", /* 0x1(A|B)-04C0-C1 */ .video_inputs = 2, .audio_inputs = 1, @@ -1766,7 +1766,7 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .no_tda7432 = 1, }, - [BTTV_OSPREY500] = { + [BTTV_BOARD_OSPREY500] = { .name = "Osprey 500", /* 500 */ .video_inputs = 2, .audio_inputs = 1, @@ -1780,7 +1780,7 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .no_tda7432 = 1, }, - [BTTV_OSPREY540] = { + [BTTV_BOARD_OSPREY540] = { .name = "Osprey 540", /* 540 */ .video_inputs = 4, .audio_inputs = 1, @@ -1803,7 +1803,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x5C ---------------------------------- */ - [BTTV_OSPREY2000] = { + [BTTV_BOARD_OSPREY2000] = { .name = "Osprey 2000", /* 2000 */ .video_inputs = 2, .audio_inputs = 1, @@ -1817,7 +1817,7 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .no_tda7432 = 1, /* must avoid, conflicts with the bt860 */ }, - [BTTV_IDS_EAGLE] = { + [BTTV_BOARD_IDS_EAGLE] = { /* M G Berberich */ .name = "IDS Eagle", .video_inputs = 4, @@ -1833,7 +1833,7 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .pll = PLL_28, }, - [BTTV_PINNACLESAT] = { + [BTTV_BOARD_PINNACLESAT] = { .name = "Pinnacle PCTV Sat", .video_inputs = 2, .audio_inputs = 0, @@ -1849,7 +1849,7 @@ struct tvcard bttv_tvcards[] = { .no_gpioirq = 1, .has_dvb = 1, }, - [BTTV_FORMAC_PROTV] = { + [BTTV_BOARD_FORMAC_PROTV] = { .name = "Formac ProTV II (bt878)", .video_inputs = 4, .audio_inputs = 1, @@ -1873,7 +1873,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x60 ---------------------------------- */ - [BTTV_MACHTV] = { + [BTTV_BOARD_MACHTV] = { .name = "MachTV", .video_inputs = 3, .audio_inputs = 1, @@ -1887,7 +1887,7 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .pll = 1, }, - [BTTV_EURESYS_PICOLO] = { + [BTTV_BOARD_EURESYS_PICOLO] = { .name = "Euresys Picolo", .video_inputs = 3, .audio_inputs = 0, @@ -1902,7 +1902,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, }, - [BTTV_PV150] = { + [BTTV_BOARD_PV150] = { /* Luc Van Hoeylandt */ .name = "ProVideo PV150", /* 0x4f */ .video_inputs = 2, @@ -1918,7 +1918,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, }, - [BTTV_AD_TVK503] = { + [BTTV_BOARD_AD_TVK503] = { /* Hiroshi Takekawa */ /* This card lacks subsystem ID */ .name = "AD-TVK503", /* 0x63 */ @@ -1939,7 +1939,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x64 ---------------------------------- */ - [BTTV_HERCULES_SM_TV] = { + [BTTV_BOARD_HERCULES_SM_TV] = { .name = "Hercules Smart TV Stereo", .video_inputs = 4, .audio_inputs = 1, @@ -1962,7 +1962,7 @@ struct tvcard bttv_tvcards[] = { hef4053 (instead 4052) for unknown function */ }, - [BTTV_PACETV] = { + [BTTV_BOARD_PACETV] = { .name = "Pace TV & Radio Card", .video_inputs = 4, .audio_inputs = 1, @@ -1983,7 +1983,7 @@ struct tvcard bttv_tvcards[] = { .digital_mode = DIGITAL_MODE_CAMERA, todo! */ }, - [BTTV_IVC200] = { + [BTTV_BOARD_IVC200] = { /* Chris Willing */ .name = "IVC-200", .video_inputs = 1, @@ -1996,7 +1996,7 @@ struct tvcard bttv_tvcards[] = { .muxsel = { 2 }, .pll = PLL_28, }, - [BTTV_XGUARD] = { + [BTTV_BOARD_XGUARD] = { .name = "Grand X-Guard / Trust 814PCI", .video_inputs = 16, .audio_inputs = 0, @@ -2014,7 +2014,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x68 ---------------------------------- */ - [BTTV_NEBULA_DIGITV] = { + [BTTV_BOARD_NEBULA_DIGITV] = { .name = "Nebula Electronics DigiTV", .video_inputs = 1, .tuner = -1, @@ -2029,7 +2029,7 @@ struct tvcard bttv_tvcards[] = { .has_dvb = 1, .no_gpioirq = 1, }, - [BTTV_PV143] = { + [BTTV_BOARD_PV143] = { /* Jorge Boncompte - DTI2 */ .name = "ProVideo PV143", .video_inputs = 4, @@ -2045,7 +2045,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_VD009X1_MINIDIN] = { + [BTTV_BOARD_VD009X1_MINIDIN] = { /* M.Klahr@phytec.de */ .name = "PHYTEC VD-009-X1 MiniDIN (bt878)", .video_inputs = 4, @@ -2060,7 +2060,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_VD009X1_COMBI] = { + [BTTV_BOARD_VD009X1_COMBI] = { .name = "PHYTEC VD-009-X1 Combi (bt878)", .video_inputs = 4, .audio_inputs = 0, @@ -2076,7 +2076,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x6c ---------------------------------- */ - [BTTV_VD009_MINIDIN] = { + [BTTV_BOARD_VD009_MINIDIN] = { .name = "PHYTEC VD-009 MiniDIN (bt878)", .video_inputs = 10, .audio_inputs = 0, @@ -2093,7 +2093,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_VD009_COMBI] = { + [BTTV_BOARD_VD009_COMBI] = { .name = "PHYTEC VD-009 Combi (bt878)", .video_inputs = 10, .audio_inputs = 0, @@ -2110,7 +2110,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_IVC100] = { + [BTTV_BOARD_IVC100] = { .name = "IVC-100", .video_inputs = 4, .audio_inputs = 0, @@ -2122,7 +2122,7 @@ struct tvcard bttv_tvcards[] = { .muxsel = { 2, 3, 1, 0 }, .pll = PLL_28, }, - [BTTV_IVC120] = { + [BTTV_BOARD_IVC120] = { /* IVC-120G - Alan Garfield */ .name = "IVC-120G", .video_inputs = 16, @@ -2143,7 +2143,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x70 ---------------------------------- */ - [BTTV_PC_HDTV] = { + [BTTV_BOARD_PC_HDTV] = { .name = "pcHDTV HD-2000 TV", .video_inputs = 4, .audio_inputs = 1, @@ -2154,7 +2154,7 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .has_dvb = 1, }, - [BTTV_TWINHAN_DST] = { + [BTTV_BOARD_TWINHAN_DST] = { .name = "Twinhan DST + clones", .no_msp34xx = 1, .no_tda9875 = 1, @@ -2164,7 +2164,7 @@ struct tvcard bttv_tvcards[] = { .no_video = 1, .has_dvb = 1, }, - [BTTV_WINFASTVC100] = { + [BTTV_BOARD_WINFASTVC100] = { .name = "Winfast VC100", .video_inputs = 3, .audio_inputs = 0, @@ -2178,7 +2178,7 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .pll = PLL_28, }, - [BTTV_TEV560] = { + [BTTV_BOARD_TEV560] = { .name = "Teppro TEV-560/InterVision IV-560", .video_inputs = 3, .audio_inputs = 1, @@ -2194,7 +2194,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x74 ---------------------------------- */ - [BTTV_SIMUS_GVC1100] = { + [BTTV_BOARD_SIMUS_GVC1100] = { .name = "SIMUS GVC1100", .video_inputs = 4, .audio_inputs = 0, @@ -2207,7 +2207,7 @@ struct tvcard bttv_tvcards[] = { .gpiomask = 0x3F, .muxsel_hook = gvc1100_muxsel, }, - [BTTV_NGSTV_PLUS] = { + [BTTV_BOARD_NGSTV_PLUS] = { /* Carlos Silva r3pek@r3pek.homelinux.org || card 0x75 */ .name = "NGS NGSTV+", .video_inputs = 3, @@ -2221,7 +2221,7 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .has_remote = 1, }, - [BTTV_LMLBT4] = { + [BTTV_BOARD_LMLBT4] = { /* http://linuxmedialabs.com */ .name = "LMLBT4", .video_inputs = 4, /* IN1,IN2,IN3,IN4 */ @@ -2236,7 +2236,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_TEKRAM_M205] = { + [BTTV_BOARD_TEKRAM_M205] = { /* Helmroos Harri */ .name = "Tekram M205 PRO", .video_inputs = 3, @@ -2253,7 +2253,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x78 ---------------------------------- */ - [BTTV_CONTVFMI] = { + [BTTV_BOARD_CONTVFMI] = { /* Javier Cendan Ares */ /* bt878 TV + FM without subsystem ID */ .name = "Conceptronic CONTVFMi", @@ -2271,10 +2271,10 @@ struct tvcard bttv_tvcards[] = { .has_remote = 1, .has_radio = 1, }, - [BTTV_PICOLO_TETRA_CHIP] = { + [BTTV_BOARD_PICOLO_TETRA_CHIP] = { /*Eric DEBIEF */ /*EURESYS Picolo Tetra : 4 Conexant Fusion 878A, no audio, video input set with analog multiplexers GPIO controled*/ - /* adds picolo_tetra_muxsel(), picolo_tetra_init(), the folowing declaration strucure, and #define BTTV_PICOLO_TETRA_CHIP*/ + /* adds picolo_tetra_muxsel(), picolo_tetra_init(), the folowing declaration strucure, and #define BTTV_BOARD_PICOLO_TETRA_CHIP*/ /*0x79 in bttv.h*/ .name = "Euresys Picolo Tetra", .video_inputs = 4, @@ -2294,7 +2294,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_SPIRIT_TV] = { + [BTTV_BOARD_SPIRIT_TV] = { /* Spirit TV Tuner from http://spiritmodems.com.au */ /* Stafford Goodsell */ .name = "Spirit TV Tuner", @@ -2310,7 +2310,7 @@ struct tvcard bttv_tvcards[] = { .no_msp34xx = 1, .no_tda9875 = 1, }, - [BTTV_AVDVBT_771] = { + [BTTV_BOARD_AVDVBT_771] = { /* Wolfram Joost */ .name = "AVerMedia AVerTV DVB-T 771", .video_inputs = 2, @@ -2328,9 +2328,9 @@ struct tvcard bttv_tvcards[] = { .has_remote = 1, }, /* ---- card 0x7c ---------------------------------- */ - [BTTV_AVDVBT_761] = { + [BTTV_BOARD_AVDVBT_761] = { /* Matt Jesson */ - /* Based on the Nebula card data - added remote and new card number - BTTV_AVDVBT_761, see also ir-kbd-gpio.c */ + /* Based on the Nebula card data - added remote and new card number - BTTV_BOARD_AVDVBT_761, see also ir-kbd-gpio.c */ .name = "AverMedia AverTV DVB-T 761", .video_inputs = 2, .tuner = -1, @@ -2346,7 +2346,7 @@ struct tvcard bttv_tvcards[] = { .no_gpioirq = 1, .has_remote = 1, }, - [BTTV_MATRIX_VISIONSQ] = { + [BTTV_BOARD_MATRIX_VISIONSQ] = { /* andre.schwarz@matrix-vision.de */ .name = "MATRIX Vision Sigma-SQ", .video_inputs = 16, @@ -2363,7 +2363,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_MATRIX_VISIONSLC] = { + [BTTV_BOARD_MATRIX_VISIONSLC] = { /* andre.schwarz@matrix-vision.de */ .name = "MATRIX Vision Sigma-SLC", .video_inputs = 4, @@ -2379,8 +2379,8 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - /* BTTV_APAC_VIEWCOMP */ - [BTTV_APAC_VIEWCOMP] = { + /* BTTV_BOARD_APAC_VIEWCOMP */ + [BTTV_BOARD_APAC_VIEWCOMP] = { /* Attila Kondoros */ /* bt878 TV + FM 0x00000000 subsystem ID */ .name = "APAC Viewcomp 878(AMAX)", @@ -2400,7 +2400,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x80 ---------------------------------- */ - [BTTV_DVICO_DVBT_LITE] = { + [BTTV_BOARD_DVICO_DVBT_LITE] = { /* Chris Pascoe */ .name = "DViCO FusionHDTV DVB-T Lite", .tuner = -1, @@ -2413,7 +2413,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = -1, .tuner_addr = ADDR_UNSET, }, - [BTTV_VGEAR_MYVCD] = { + [BTTV_BOARD_VGEAR_MYVCD] = { /* Steven */ .name = "V-Gear MyVCD", .video_inputs = 3, @@ -2432,7 +2432,7 @@ struct tvcard bttv_tvcards[] = { .has_remote = 1, #endif }, - [BTTV_SUPER_TV] = { + [BTTV_BOARD_SUPER_TV] = { /* Rick C */ .name = "Super TV Tuner", .video_inputs = 4, @@ -2447,7 +2447,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .has_radio = 1, }, - [BTTV_TIBET_CS16] = { + [BTTV_BOARD_TIBET_CS16] = { /* Chris Fanning */ .name = "Tibet Systems 'Progress DVR' CS16", .video_inputs = 16, @@ -2463,7 +2463,7 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .muxsel_hook = tibetCS16_muxsel, }, - { + [BTTV_BOARD_KODICOM_4400R] = { /* Bill Brack */ /* * Note that, because of the card's wiring, the "master" @@ -2499,7 +2499,7 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .muxsel_hook = kodicom4400r_muxsel, }, - { + [BTTV_BOARD_KODICOM_4400R_SL] = { /* Bill Brack */ /* Note that, for reasons unknown, the "master" BT878A chip (i.e. the * one which controls the analog switch, and must use the card type) @@ -2522,8 +2522,8 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .muxsel_hook = kodicom4400r_muxsel, }, - { /* ---- card 0x86---------------------------------- */ + [BTTV_BOARD_ADLINK_RTV24] = { /* Michael Henson */ /* Adlink RTV24 with special unlock codes */ .name = "Adlink RTV24", @@ -2536,8 +2536,8 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .pll = PLL_28, }, - { /* ---- card 0x87---------------------------------- */ + [BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE] = { /* Michael Krufky */ .name = "DViCO FusionHDTV 5 Lite", .tuner = 0, @@ -2555,7 +2555,7 @@ struct tvcard bttv_tvcards[] = { .has_dvb = 1, }, /* ---- card 0x88---------------------------------- */ - [BTTV_KODICOM_4400R] = { + [BTTV_BOARD_ACORP_Y878F] = { /* Mauro Carvalho Chehab */ .name = "Acorp Y878F", .video_inputs = 3, @@ -2572,7 +2572,7 @@ struct tvcard bttv_tvcards[] = { .has_radio = 1, }, /* ---- card 0x89 ---------------------------------- */ - [BTTV_KODICOM_4400R_SL] = { + [BTTV_BOARD_CONCEPTRONIC_CTVFMI2] = { .name = "Conceptronic CTVFMi v2", .video_inputs = 3, .audio_inputs = 1, @@ -2590,7 +2590,7 @@ struct tvcard bttv_tvcards[] = { .has_radio = 1, #endif }, - [BTTV_ADLINK_RTV24] = { + [BTTV_BOARD_PV_BT878P_2E] = { .name = "Prolink Pixelview PV-BT878P+ (Rev.2E)", .video_inputs = 5, .audio_inputs = 1, @@ -2604,8 +2604,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_LG_PAL_FM, .has_remote = 1, - } -}; +}}; static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); @@ -2697,11 +2696,11 @@ void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256]) int type = -1; if (0 == strncmp(eeprom_data,"GET MM20xPCTV",13)) - type = BTTV_MODTEC_205; + type = BTTV_BOARD_MODTEC_205; else if (0 == strncmp(eeprom_data+20,"Picolo",7)) - type = BTTV_EURESYS_PICOLO; + type = BTTV_BOARD_EURESYS_PICOLO; else if (eeprom_data[0] == 0x84 && eeprom_data[2]== 0) - type = BTTV_HAUPPAUGE; /* old bt848 */ + type = BTTV_BOARD_HAUPPAUGE; /* old bt848 */ if (-1 != type) { btv->c.type = type; @@ -2807,10 +2806,10 @@ static void miro_pinnacle_gpio(struct bttv *btv) btv->has_radio = 0; } if (-1 != msp) { - if (btv->c.type == BTTV_MIRO) - btv->c.type = BTTV_MIROPRO; - if (btv->c.type == BTTV_PINNACLE) - btv->c.type = BTTV_PINNACLEPRO; + if (btv->c.type == BTTV_BOARD_MIRO) + btv->c.type = BTTV_BOARD_MIROPRO; + if (btv->c.type == BTTV_BOARD_PINNACLE) + btv->c.type = BTTV_BOARD_PINNACLEPRO; } printk(KERN_INFO "bttv%d: miro: id=%d tuner=%d radio=%s stereo=%s\n", @@ -2851,7 +2850,7 @@ static void miro_pinnacle_gpio(struct bttv *btv) break; } if (-1 != msp) - btv->c.type = BTTV_PINNACLEPRO; + btv->c.type = BTTV_BOARD_PINNACLEPRO; printk(KERN_INFO "bttv%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n", btv->c.nr, id, info, btv->has_radio ? "yes" : "no"); @@ -2965,25 +2964,25 @@ static void bttv_reset_audio(struct bttv *btv) void __devinit bttv_init_card1(struct bttv *btv) { switch (btv->c.type) { - case BTTV_HAUPPAUGE: - case BTTV_HAUPPAUGE878: + case BTTV_BOARD_HAUPPAUGE: + case BTTV_BOARD_HAUPPAUGE878: boot_msp34xx(btv,5); break; - case BTTV_VOODOOTV_FM: + case BTTV_BOARD_VOODOOTV_FM: boot_msp34xx(btv,20); break; - case BTTV_AVERMEDIA98: + case BTTV_BOARD_AVERMEDIA98: boot_msp34xx(btv,11); break; - case BTTV_HAUPPAUGEPVR: + case BTTV_BOARD_HAUPPAUGEPVR: pvr_boot(btv); break; - case BTTV_TWINHAN_DST: - case BTTV_AVDVBT_771: - case BTTV_PINNACLESAT: + case BTTV_BOARD_TWINHAN_DST: + case BTTV_BOARD_AVDVBT_771: + case BTTV_BOARD_PINNACLESAT: btv->use_i2c_hw = 1; break; - case BTTV_ADLINK_RTV24: + case BTTV_BOARD_ADLINK_RTV24: init_RTV24( btv ); break; @@ -3000,51 +2999,51 @@ void __devinit bttv_init_card2(struct bttv *btv) btv->tuner_type = -1; - if (BTTV_UNKNOWN == btv->c.type) { + if (BTTV_BOARD_UNKNOWN == btv->c.type) { bttv_readee(btv,eeprom_data,0xa0); identify_by_eeprom(btv,eeprom_data); } switch (btv->c.type) { - case BTTV_MIRO: - case BTTV_MIROPRO: - case BTTV_PINNACLE: - case BTTV_PINNACLEPRO: + case BTTV_BOARD_MIRO: + case BTTV_BOARD_MIROPRO: + case BTTV_BOARD_PINNACLE: + case BTTV_BOARD_PINNACLEPRO: /* miro/pinnacle */ miro_pinnacle_gpio(btv); break; - case BTTV_FLYVIDEO_98: - case BTTV_MAXI: - case BTTV_LIFE_FLYKIT: - case BTTV_FLYVIDEO: - case BTTV_TYPHOON_TVIEW: - case BTTV_CHRONOS_VS2: - case BTTV_FLYVIDEO_98FM: - case BTTV_FLYVIDEO2000: - case BTTV_FLYVIDEO98EZ: - case BTTV_CONFERENCETV: - case BTTV_LIFETEC_9415: + case BTTV_BOARD_FLYVIDEO_98: + case BTTV_BOARD_MAXI: + case BTTV_BOARD_LIFE_FLYKIT: + case BTTV_BOARD_FLYVIDEO: + case BTTV_BOARD_TYPHOON_TVIEW: + case BTTV_BOARD_CHRONOS_VS2: + case BTTV_BOARD_FLYVIDEO_98FM: + case BTTV_BOARD_FLYVIDEO2000: + case BTTV_BOARD_FLYVIDEO98EZ: + case BTTV_BOARD_CONFERENCETV: + case BTTV_BOARD_LIFETEC_9415: flyvideo_gpio(btv); break; - case BTTV_HAUPPAUGE: - case BTTV_HAUPPAUGE878: - case BTTV_HAUPPAUGEPVR: + case BTTV_BOARD_HAUPPAUGE: + case BTTV_BOARD_HAUPPAUGE878: + case BTTV_BOARD_HAUPPAUGEPVR: /* pick up some config infos from the eeprom */ bttv_readee(btv,eeprom_data,0xa0); hauppauge_eeprom(btv); break; - case BTTV_AVERMEDIA98: - case BTTV_AVPHONE98: + case BTTV_BOARD_AVERMEDIA98: + case BTTV_BOARD_AVPHONE98: bttv_readee(btv,eeprom_data,0xa0); avermedia_eeprom(btv); break; - case BTTV_PXC200: + case BTTV_BOARD_PXC200: init_PXC200(btv); break; - case BTTV_PICOLO_TETRA_CHIP: + case BTTV_BOARD_PICOLO_TETRA_CHIP: picolo_tetra_init(btv); break; - case BTTV_VHX: + case BTTV_BOARD_VHX: btv->has_radio = 1; btv->has_matchbox = 1; btv->mbox_we = 0x20; @@ -3053,17 +3052,17 @@ void __devinit bttv_init_card2(struct bttv *btv) btv->mbox_data = 0x10; btv->mbox_mask = 0x38; break; - case BTTV_VOBIS_BOOSTAR: - case BTTV_TERRATV: + case BTTV_BOARD_VOBIS_BOOSTAR: + case BTTV_BOARD_TERRATV: terratec_active_radio_upgrade(btv); break; - case BTTV_MAGICTVIEW061: + case BTTV_BOARD_MAGICTVIEW061: if (btv->cardid == 0x3002144f) { btv->has_radio=1; printk("bttv%d: radio detected by subsystem id (CPH05x)\n",btv->c.nr); } break; - case BTTV_STB2: + case BTTV_BOARD_STB2: if (btv->cardid == 0x3060121a) { /* Fix up entry for 3DFX VoodooTV 100, which is an OEM STB card variant. */ @@ -3071,34 +3070,34 @@ void __devinit bttv_init_card2(struct bttv *btv) btv->tuner_type=TUNER_TEMIC_NTSC; } break; - case BTTV_OSPREY1x0: - case BTTV_OSPREY1x0_848: - case BTTV_OSPREY101_848: - case BTTV_OSPREY1x1: - case BTTV_OSPREY1x1_SVID: - case BTTV_OSPREY2xx: - case BTTV_OSPREY2x0_SVID: - case BTTV_OSPREY2x0: - case BTTV_OSPREY500: - case BTTV_OSPREY540: - case BTTV_OSPREY2000: + case BTTV_BOARD_OSPREY1x0: + case BTTV_BOARD_OSPREY1x0_848: + case BTTV_BOARD_OSPREY101_848: + case BTTV_BOARD_OSPREY1x1: + case BTTV_BOARD_OSPREY1x1_SVID: + case BTTV_BOARD_OSPREY2xx: + case BTTV_BOARD_OSPREY2x0_SVID: + case BTTV_BOARD_OSPREY2x0: + case BTTV_BOARD_OSPREY500: + case BTTV_BOARD_OSPREY540: + case BTTV_BOARD_OSPREY2000: bttv_readee(btv,eeprom_data,0xa0); osprey_eeprom(btv); break; - case BTTV_IDS_EAGLE: + case BTTV_BOARD_IDS_EAGLE: init_ids_eagle(btv); break; - case BTTV_MODTEC_205: + case BTTV_BOARD_MODTEC_205: bttv_readee(btv,eeprom_data,0xa0); modtec_eeprom(btv); break; - case BTTV_LMLBT4: + case BTTV_BOARD_LMLBT4: init_lmlbt4x(btv); break; - case BTTV_TIBET_CS16: + case BTTV_BOARD_TIBET_CS16: tibetCS16_init(btv); break; - case BTTV_KODICOM_4400R: + case BTTV_BOARD_KODICOM_4400R: kodicom4400r_init(btv); break; } @@ -3371,7 +3370,7 @@ static void __devinit osprey_eeprom(struct bttv *btv) checksum += ee[i]; if (checksum != ee[21]) return; - btv->c.type = BTTV_OSPREY1x0_848; + btv->c.type = BTTV_BOARD_OSPREY1x0_848; for (i = 12; i < 21; i++) serial *= 10, serial += ee[i] - '0'; } @@ -3400,47 +3399,47 @@ static void __devinit osprey_eeprom(struct bttv *btv) /* 848 based */ case 0x0004: - btv->c.type = BTTV_OSPREY1x0_848; + btv->c.type = BTTV_BOARD_OSPREY1x0_848; break; case 0x0005: - btv->c.type = BTTV_OSPREY101_848; + btv->c.type = BTTV_BOARD_OSPREY101_848; break; /* 878 based */ case 0x0012: case 0x0013: - btv->c.type = BTTV_OSPREY1x0; + btv->c.type = BTTV_BOARD_OSPREY1x0; break; case 0x0014: case 0x0015: - btv->c.type = BTTV_OSPREY1x1; + btv->c.type = BTTV_BOARD_OSPREY1x1; break; case 0x0016: case 0x0017: case 0x0020: - btv->c.type = BTTV_OSPREY1x1_SVID; + btv->c.type = BTTV_BOARD_OSPREY1x1_SVID; break; case 0x0018: case 0x0019: case 0x001E: case 0x001F: - btv->c.type = BTTV_OSPREY2xx; + btv->c.type = BTTV_BOARD_OSPREY2xx; break; case 0x001A: case 0x001B: - btv->c.type = BTTV_OSPREY2x0_SVID; + btv->c.type = BTTV_BOARD_OSPREY2x0_SVID; break; case 0x0040: - btv->c.type = BTTV_OSPREY500; + btv->c.type = BTTV_BOARD_OSPREY500; break; case 0x0050: case 0x0056: - btv->c.type = BTTV_OSPREY540; + btv->c.type = BTTV_BOARD_OSPREY540; /* bttv_osprey_540_init(btv); */ break; case 0x0060: case 0x0070: - btv->c.type = BTTV_OSPREY2x0; + btv->c.type = BTTV_BOARD_OSPREY2x0; /* enable output on select control lines */ gpio_inout(0xffffff,0x000303); break; @@ -3513,13 +3512,13 @@ void bttv_tda9880_setnorm(struct bttv *btv, int norm) { /* fix up our card entry */ if(norm==VIDEO_MODE_NTSC) { - bttv_tvcards[BTTV_VOODOOTV_FM].audiomux[0]=0x957fff; - bttv_tvcards[BTTV_VOODOOTV_FM].audiomux[4]=0x957fff; + bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[0]=0x957fff; + bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[4]=0x957fff; dprintk("bttv_tda9880_setnorm to NTSC\n"); } else { - bttv_tvcards[BTTV_VOODOOTV_FM].audiomux[0]=0x947fff; - bttv_tvcards[BTTV_VOODOOTV_FM].audiomux[4]=0x947fff; + bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[0]=0x947fff; + bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[4]=0x947fff; dprintk("bttv_tda9880_setnorm to PAL\n"); } /* set GPIO according */ diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index 4826cf0d39d..504d717b115 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -964,7 +964,7 @@ i2c_vidiocschan(struct bttv *btv) c.norm = btv->tvnorm; c.channel = btv->input; bttv_call_i2c_clients(btv,VIDIOCSCHAN,&c); - if (btv->c.type == BTTV_VOODOOTV_FM) + if (btv->c.type == BTTV_BOARD_VOODOOTV_FM) bttv_tda9880_setnorm(btv,c.norm); } @@ -988,7 +988,7 @@ set_tvnorm(struct bttv *btv, unsigned int norm) bt848A_set_timing(btv); switch (btv->c.type) { - case BTTV_VOODOOTV_FM: + case BTTV_BOARD_VOODOOTV_FM: bttv_tda9880_setnorm(btv,norm); break; } diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h index dcdf9cde785..2005ca9383d 100644 --- a/drivers/media/video/bttv.h +++ b/drivers/media/video/bttv.h @@ -20,124 +20,145 @@ /* ---------------------------------------------------------- */ /* exported by bttv-cards.c */ -#define BTTV_UNKNOWN 0x00 -#define BTTV_MIRO 0x01 -#define BTTV_HAUPPAUGE 0x02 -#define BTTV_STB 0x03 -#define BTTV_INTEL 0x04 -#define BTTV_DIAMOND 0x05 -#define BTTV_AVERMEDIA 0x06 -#define BTTV_MATRIX_VISION 0x07 -#define BTTV_FLYVIDEO 0x08 -#define BTTV_TURBOTV 0x09 -#define BTTV_HAUPPAUGE878 0x0a -#define BTTV_MIROPRO 0x0b -#define BTTV_ADSTECH_TV 0x0c -#define BTTV_AVERMEDIA98 0x0d -#define BTTV_VHX 0x0e -#define BTTV_ZOLTRIX 0x0f -#define BTTV_PIXVIEWPLAYTV 0x10 -#define BTTV_WINVIEW_601 0x11 -#define BTTV_AVEC_INTERCAP 0x12 -#define BTTV_LIFE_FLYKIT 0x13 -#define BTTV_CEI_RAFFLES 0x14 -#define BTTV_CONFERENCETV 0x15 -#define BTTV_PHOEBE_TVMAS 0x16 -#define BTTV_MODTEC_205 0x17 -#define BTTV_MAGICTVIEW061 0x18 -#define BTTV_VOBIS_BOOSTAR 0x19 -#define BTTV_HAUPPAUG_WCAM 0x1a -#define BTTV_MAXI 0x1b -#define BTTV_TERRATV 0x1c -#define BTTV_PXC200 0x1d -#define BTTV_FLYVIDEO_98 0x1e -#define BTTV_IPROTV 0x1f -#define BTTV_INTEL_C_S_PCI 0x20 -#define BTTV_TERRATVALUE 0x21 -#define BTTV_WINFAST2000 0x22 -#define BTTV_CHRONOS_VS2 0x23 -#define BTTV_TYPHOON_TVIEW 0x24 -#define BTTV_PXELVWPLTVPRO 0x25 -#define BTTV_MAGICTVIEW063 0x26 -#define BTTV_PINNACLE 0x27 -#define BTTV_STB2 0x28 -#define BTTV_AVPHONE98 0x29 -#define BTTV_PV951 0x2a -#define BTTV_ONAIR_TV 0x2b -#define BTTV_SIGMA_TVII_FM 0x2c -#define BTTV_MATRIX_VISION2 0x2d -#define BTTV_ZOLTRIX_GENIE 0x2e -#define BTTV_TERRATVRADIO 0x2f -#define BTTV_DYNALINK 0x30 -#define BTTV_GVBCTV3PCI 0x31 -#define BTTV_PXELVWPLTVPAK 0x32 -#define BTTV_EAGLE 0x33 -#define BTTV_PINNACLEPRO 0x34 -#define BTTV_TVIEW_RDS_FM 0x35 -#define BTTV_LIFETEC_9415 0x36 -#define BTTV_BESTBUY_EASYTV 0x37 -#define BTTV_FLYVIDEO_98FM 0x38 -#define BTTV_GMV1 0x3d -#define BTTV_BESTBUY_EASYTV2 0x3e -#define BTTV_ATI_TVWONDER 0x3f -#define BTTV_ATI_TVWONDERVE 0x40 -#define BTTV_FLYVIDEO2000 0x41 -#define BTTV_TERRATVALUER 0x42 -#define BTTV_GVBCTV4PCI 0x43 -#define BTTV_VOODOOTV_FM 0x44 -#define BTTV_AIMMS 0x45 -#define BTTV_PV_BT878P_PLUS 0x46 -#define BTTV_FLYVIDEO98EZ 0x47 -#define BTTV_PV_BT878P_9B 0x48 -#define BTTV_SENSORAY311 0x49 -#define BTTV_RV605 0x4a -#define BTTV_WINDVR 0x4c -#define BTTV_GRANDTEC 0x4d -#define BTTV_KWORLD 0x4e -#define BTTV_HAUPPAUGEPVR 0x50 -#define BTTV_GVBCTV5PCI 0x51 -#define BTTV_OSPREY1x0 0x52 -#define BTTV_OSPREY1x0_848 0x53 -#define BTTV_OSPREY101_848 0x54 -#define BTTV_OSPREY1x1 0x55 -#define BTTV_OSPREY1x1_SVID 0x56 -#define BTTV_OSPREY2xx 0x57 -#define BTTV_OSPREY2x0_SVID 0x58 -#define BTTV_OSPREY2x0 0x59 -#define BTTV_OSPREY500 0x5a -#define BTTV_OSPREY540 0x5b -#define BTTV_OSPREY2000 0x5c -#define BTTV_IDS_EAGLE 0x5d -#define BTTV_PINNACLESAT 0x5e -#define BTTV_FORMAC_PROTV 0x5f -#define BTTV_EURESYS_PICOLO 0x61 -#define BTTV_PV150 0x62 -#define BTTV_AD_TVK503 0x63 -#define BTTV_IVC200 0x66 -#define BTTV_XGUARD 0x67 -#define BTTV_NEBULA_DIGITV 0x68 -#define BTTV_PV143 0x69 -#define BTTV_IVC100 0x6e -#define BTTV_IVC120 0x6f -#define BTTV_PC_HDTV 0x70 -#define BTTV_TWINHAN_DST 0x71 -#define BTTV_WINFASTVC100 0x72 -#define BTTV_SIMUS_GVC1100 0x74 -#define BTTV_NGSTV_PLUS 0x75 -#define BTTV_LMLBT4 0x76 -#define BTTV_PICOLO_TETRA_CHIP 0x79 -#define BTTV_AVDVBT_771 0x7b -#define BTTV_AVDVBT_761 0x7c -#define BTTV_MATRIX_VISIONSQ 0x7d -#define BTTV_MATRIX_VISIONSLC 0x7e -#define BTTV_APAC_VIEWCOMP 0x7f -#define BTTV_DVICO_DVBT_LITE 0x80 -#define BTTV_TIBET_CS16 0x83 -#define BTTV_KODICOM_4400R 0x84 -#define BTTV_ADLINK_RTV24 0x86 -#define BTTV_DVICO_FUSIONHDTV_5_LITE 0x87 -#define BTTV_ACORP_Y878F 0x88 -#define BTTV_CONCEPTRONIC_CTVFMI2 0x89 +#define BTTV_BOARD_UNKNOWN 0x00 +#define BTTV_BOARD_MIRO 0x01 +#define BTTV_BOARD_HAUPPAUGE 0x02 +#define BTTV_BOARD_STB 0x03 +#define BTTV_BOARD_INTEL 0x04 +#define BTTV_BOARD_DIAMOND 0x05 +#define BTTV_BOARD_AVERMEDIA 0x06 +#define BTTV_BOARD_MATRIX_VISION 0x07 +#define BTTV_BOARD_FLYVIDEO 0x08 +#define BTTV_BOARD_TURBOTV 0x09 +#define BTTV_BOARD_HAUPPAUGE878 0x0a +#define BTTV_BOARD_MIROPRO 0x0b +#define BTTV_BOARD_ADSTECH_TV 0x0c +#define BTTV_BOARD_AVERMEDIA98 0x0d +#define BTTV_BOARD_VHX 0x0e +#define BTTV_BOARD_ZOLTRIX 0x0f +#define BTTV_BOARD_PIXVIEWPLAYTV 0x10 +#define BTTV_BOARD_WINVIEW_601 0x11 +#define BTTV_BOARD_AVEC_INTERCAP 0x12 +#define BTTV_BOARD_LIFE_FLYKIT 0x13 +#define BTTV_BOARD_CEI_RAFFLES 0x14 +#define BTTV_BOARD_CONFERENCETV 0x15 +#define BTTV_BOARD_PHOEBE_TVMAS 0x16 +#define BTTV_BOARD_MODTEC_205 0x17 +#define BTTV_BOARD_MAGICTVIEW061 0x18 +#define BTTV_BOARD_VOBIS_BOOSTAR 0x19 +#define BTTV_BOARD_HAUPPAUG_WCAM 0x1a +#define BTTV_BOARD_MAXI 0x1b +#define BTTV_BOARD_TERRATV 0x1c +#define BTTV_BOARD_PXC200 0x1d +#define BTTV_BOARD_FLYVIDEO_98 0x1e +#define BTTV_BOARD_IPROTV 0x1f +#define BTTV_BOARD_INTEL_C_S_PCI 0x20 +#define BTTV_BOARD_TERRATVALUE 0x21 +#define BTTV_BOARD_WINFAST2000 0x22 +#define BTTV_BOARD_CHRONOS_VS2 0x23 +#define BTTV_BOARD_TYPHOON_TVIEW 0x24 +#define BTTV_BOARD_PXELVWPLTVPRO 0x25 +#define BTTV_BOARD_MAGICTVIEW063 0x26 +#define BTTV_BOARD_PINNACLE 0x27 +#define BTTV_BOARD_STB2 0x28 +#define BTTV_BOARD_AVPHONE98 0x29 +#define BTTV_BOARD_PV951 0x2a +#define BTTV_BOARD_ONAIR_TV 0x2b +#define BTTV_BOARD_SIGMA_TVII_FM 0x2c +#define BTTV_BOARD_MATRIX_VISION2 0x2d +#define BTTV_BOARD_ZOLTRIX_GENIE 0x2e +#define BTTV_BOARD_TERRATVRADIO 0x2f +#define BTTV_BOARD_DYNALINK 0x30 +#define BTTV_BOARD_GVBCTV3PCI 0x31 +#define BTTV_BOARD_PXELVWPLTVPAK 0x32 +#define BTTV_BOARD_EAGLE 0x33 +#define BTTV_BOARD_PINNACLEPRO 0x34 +#define BTTV_BOARD_TVIEW_RDS_FM 0x35 +#define BTTV_BOARD_LIFETEC_9415 0x36 +#define BTTV_BOARD_BESTBUY_EASYTV 0x37 +#define BTTV_BOARD_FLYVIDEO_98FM 0x38 +#define BTTV_BOARD_GRANDTEC 0x39 +#define BTTV_BOARD_ASKEY_CPH060 0x3a +#define BTTV_BOARD_ASKEY_CPH03X 0x3b +#define BTTV_BOARD_MM100PCTV 0x3c +#define BTTV_BOARD_GMV1 0x3d +#define BTTV_BOARD_BESTBUY_EASYTV2 0x3e +#define BTTV_BOARD_ATI_TVWONDER 0x3f +#define BTTV_BOARD_ATI_TVWONDERVE 0x40 +#define BTTV_BOARD_FLYVIDEO2000 0x41 +#define BTTV_BOARD_TERRATVALUER 0x42 +#define BTTV_BOARD_GVBCTV4PCI 0x43 +#define BTTV_BOARD_VOODOOTV_FM 0x44 +#define BTTV_BOARD_AIMMS 0x45 +#define BTTV_BOARD_PV_BT878P_PLUS 0x46 +#define BTTV_BOARD_FLYVIDEO98EZ 0x47 +#define BTTV_BOARD_PV_BT878P_9B 0x48 +#define BTTV_BOARD_SENSORAY311 0x49 +#define BTTV_BOARD_RV605 0x4a +#define BTTV_BOARD_POWERCLR_MTV878 0x4b +#define BTTV_BOARD_WINDVR 0x4c +#define BTTV_BOARD_GRANDTEC_MULTI 0x4d +#define BTTV_BOARD_KWORLD 0x4e +#define BTTV_BOARD_DSP_TCVIDEO 0x4f +#define BTTV_BOARD_HAUPPAUGEPVR 0x50 +#define BTTV_BOARD_GVBCTV5PCI 0x51 +#define BTTV_BOARD_OSPREY1x0 0x52 +#define BTTV_BOARD_OSPREY1x0_848 0x53 +#define BTTV_BOARD_OSPREY101_848 0x54 +#define BTTV_BOARD_OSPREY1x1 0x55 +#define BTTV_BOARD_OSPREY1x1_SVID 0x56 +#define BTTV_BOARD_OSPREY2xx 0x57 +#define BTTV_BOARD_OSPREY2x0_SVID 0x58 +#define BTTV_BOARD_OSPREY2x0 0x59 +#define BTTV_BOARD_OSPREY500 0x5a +#define BTTV_BOARD_OSPREY540 0x5b +#define BTTV_BOARD_OSPREY2000 0x5c +#define BTTV_BOARD_IDS_EAGLE 0x5d +#define BTTV_BOARD_PINNACLESAT 0x5e +#define BTTV_BOARD_FORMAC_PROTV 0x5f +#define BTTV_BOARD_MACHTV 0x60 +#define BTTV_BOARD_EURESYS_PICOLO 0x61 +#define BTTV_BOARD_PV150 0x62 +#define BTTV_BOARD_AD_TVK503 0x63 +#define BTTV_BOARD_HERCULES_SM_TV 0x64 +#define BTTV_BOARD_PACETV 0x65 +#define BTTV_BOARD_IVC200 0x66 +#define BTTV_BOARD_XGUARD 0x67 +#define BTTV_BOARD_NEBULA_DIGITV 0x68 +#define BTTV_BOARD_PV143 0x69 +#define BTTV_BOARD_VD009X1_MINIDIN 0x6a +#define BTTV_BOARD_VD009X1_COMBI 0x6b +#define BTTV_BOARD_VD009_MINIDIN 0x6c +#define BTTV_BOARD_VD009_COMBI 0x6d +#define BTTV_BOARD_IVC100 0x6e +#define BTTV_BOARD_IVC120 0x6f +#define BTTV_BOARD_PC_HDTV 0x70 +#define BTTV_BOARD_TWINHAN_DST 0x71 +#define BTTV_BOARD_WINFASTVC100 0x72 +#define BTTV_BOARD_TEV560 0x73 +#define BTTV_BOARD_SIMUS_GVC1100 0x74 +#define BTTV_BOARD_NGSTV_PLUS 0x75 +#define BTTV_BOARD_LMLBT4 0x76 +#define BTTV_BOARD_TEKRAM_M205 0x77 +#define BTTV_BOARD_CONTVFMI 0x78 +#define BTTV_BOARD_PICOLO_TETRA_CHIP 0x79 +#define BTTV_BOARD_SPIRIT_TV 0x7a +#define BTTV_BOARD_AVDVBT_771 0x7b +#define BTTV_BOARD_AVDVBT_761 0x7c +#define BTTV_BOARD_MATRIX_VISIONSQ 0x7d +#define BTTV_BOARD_MATRIX_VISIONSLC 0x7e +#define BTTV_BOARD_APAC_VIEWCOMP 0x7f +#define BTTV_BOARD_DVICO_DVBT_LITE 0x80 +#define BTTV_BOARD_VGEAR_MYVCD 0x81 +#define BTTV_BOARD_SUPER_TV 0x82 +#define BTTV_BOARD_TIBET_CS16 0x83 +#define BTTV_BOARD_KODICOM_4400R 0x84 +#define BTTV_BOARD_KODICOM_4400R_SL 0x85 +#define BTTV_BOARD_ADLINK_RTV24 0x86 +#define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87 +#define BTTV_BOARD_ACORP_Y878F 0x88 +#define BTTV_BOARD_CONCEPTRONIC_CTVFMI2 0x89 +#define BTTV_BOARD_PV_BT878P_2E 0x8a /* i2c address list */ #define I2C_TSA5522 0xc2 @@ -247,7 +268,7 @@ extern int bttv_handle_chipset(struct bttv *btv); interface below for new code */ /* returns card type + card ID (for bt878-based ones) - for possible values see lines below beginning with #define BTTV_UNKNOWN + for possible values see lines below beginning with #define BTTV_BOARD_UNKNOWN returns negative value if error occurred */ extern int bttv_get_cardinfo(unsigned int card, int *type, diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c index 28b58976f8e..cc5973950c0 100644 --- a/drivers/media/video/ir-kbd-gpio.c +++ b/drivers/media/video/ir-kbd-gpio.c @@ -347,54 +347,54 @@ static int ir_probe(struct device *dev) /* detect & configure */ switch (sub->core->type) { - case BTTV_AVERMEDIA: - case BTTV_AVPHONE98: - case BTTV_AVERMEDIA98: + case BTTV_BOARD_AVERMEDIA: + case BTTV_BOARD_AVPHONE98: + case BTTV_BOARD_AVERMEDIA98: ir_codes = ir_codes_avermedia; ir->mask_keycode = 0xf88000; ir->mask_keydown = 0x010000; ir->polling = 50; // ms break; - case BTTV_AVDVBT_761: - case BTTV_AVDVBT_771: + case BTTV_BOARD_AVDVBT_761: + case BTTV_BOARD_AVDVBT_771: ir_codes = ir_codes_avermedia_dvbt; ir->mask_keycode = 0x0f00c0; ir->mask_keydown = 0x000020; ir->polling = 50; // ms break; - case BTTV_PXELVWPLTVPAK: + case BTTV_BOARD_PXELVWPLTVPAK: ir_codes = ir_codes_pixelview; ir->mask_keycode = 0x003e00; ir->mask_keyup = 0x010000; ir->polling = 50; // ms break; - case BTTV_PV_BT878P_9B: - case BTTV_PV_BT878P_PLUS: + case BTTV_BOARD_PV_BT878P_9B: + case BTTV_BOARD_PV_BT878P_PLUS: ir_codes = ir_codes_pixelview; ir->mask_keycode = 0x001f00; ir->mask_keyup = 0x008000; ir->polling = 50; // ms break; - case BTTV_WINFAST2000: + case BTTV_BOARD_WINFAST2000: ir_codes = ir_codes_winfast; ir->mask_keycode = 0x1f8; break; - case BTTV_MAGICTVIEW061: - case BTTV_MAGICTVIEW063: + case BTTV_BOARD_MAGICTVIEW061: + case BTTV_BOARD_MAGICTVIEW063: ir_codes = ir_codes_winfast; ir->mask_keycode = 0x0008e000; ir->mask_keydown = 0x00200000; break; - case BTTV_APAC_VIEWCOMP: + case BTTV_BOARD_APAC_VIEWCOMP: ir_codes = ir_codes_apac_viewcomp; ir->mask_keycode = 0x001f00; ir->mask_keyup = 0x008000; ir->polling = 50; // ms break; - case BTTV_CONCEPTRONIC_CTVFMI2: + case BTTV_BOARD_CONCEPTRONIC_CTVFMI2: ir_codes = ir_codes_conceptronic; ir->mask_keycode = 0x001F00; ir->mask_keyup = 0x006000; -- cgit v1.2.3 From da57a5d9050d83441769e275d54d88fbd768be49 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:36:53 -0800 Subject: [PATCH] v4l: 694: updated an entry to reflect changes on tuner-simple.c - Updated an entry to reflect changes on tuner-simple.c Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.bttv | 278 +++++++++++++++---------------- Documentation/video4linux/CARDLIST.tuner | 2 +- 2 files changed, 140 insertions(+), 140 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index 5deb052f307..a35465f50f9 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -1,139 +1,139 @@ -card=0 - *** UNKNOWN/GENERIC *** -card=1 - MIRO PCTV -card=2 - Hauppauge (bt848) -card=3 - STB, Gateway P/N 6000699 (bt848) -card=4 - Intel Create and Share PCI/ Smart Video Recorder III -card=5 - Diamond DTV2000 -card=6 - AVerMedia TVPhone -card=7 - MATRIX-Vision MV-Delta -card=8 - Lifeview FlyVideo II (Bt848) LR26 / MAXI TV Video PCI2 LR26 -card=9 - IMS/IXmicro TurboTV -card=10 - Hauppauge (bt878) -card=11 - MIRO PCTV pro -card=12 - ADS Technologies Channel Surfer TV (bt848) -card=13 - AVerMedia TVCapture 98 -card=14 - Aimslab Video Highway Xtreme (VHX) -card=15 - Zoltrix TV-Max -card=16 - Prolink Pixelview PlayTV (bt878) -card=17 - Leadtek WinView 601 -card=18 - AVEC Intercapture -card=19 - Lifeview FlyVideo II EZ /FlyKit LR38 Bt848 (capture only) -card=20 - CEI Raffles Card -card=21 - Lifeview FlyVideo 98/ Lucky Star Image World ConferenceTV LR50 -card=22 - Askey CPH050/ Phoebe Tv Master + FM -card=23 - Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV, bt878 -card=24 - Askey CPH05X/06X (bt878) [many vendors] -card=25 - Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar -card=26 - Hauppauge WinCam newer (bt878) -card=27 - Lifeview FlyVideo 98/ MAXI TV Video PCI2 LR50 -card=28 - Terratec TerraTV+ Version 1.1 (bt878) -card=29 - Imagenation PXC200 -card=30 - Lifeview FlyVideo 98 LR50 -card=31 - Formac iProTV, Formac ProTV I (bt848) -card=32 - Intel Create and Share PCI/ Smart Video Recorder III -card=33 - Terratec TerraTValue Version Bt878 -card=34 - Leadtek WinFast 2000/ WinFast 2000 XP -card=35 - Lifeview FlyVideo 98 LR50 / Chronos Video Shuttle II -card=36 - Lifeview FlyVideo 98FM LR50 / Typhoon TView TV/FM Tuner -card=37 - Prolink PixelView PlayTV pro -card=38 - Askey CPH06X TView99 -card=39 - Pinnacle PCTV Studio/Rave -card=40 - STB TV PCI FM, Gateway P/N 6000704 (bt878), 3Dfx VoodooTV 100 -card=41 - AVerMedia TVPhone 98 -card=42 - ProVideo PV951 -card=43 - Little OnAir TV -card=44 - Sigma TVII-FM -card=45 - MATRIX-Vision MV-Delta 2 -card=46 - Zoltrix Genie TV/FM -card=47 - Terratec TV/Radio+ -card=48 - Askey CPH03x/ Dynalink Magic TView -card=49 - IODATA GV-BCTV3/PCI -card=50 - Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP -card=51 - Eagle Wireless Capricorn2 (bt878A) -card=52 - Pinnacle PCTV Studio Pro -card=53 - Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS -card=54 - Lifeview FlyVideo 2000 /FlyVideo A2/ Lifetec LT 9415 TV [LR90] -card=55 - Askey CPH031/ BESTBUY Easy TV -card=56 - Lifeview FlyVideo 98FM LR50 -card=57 - GrandTec 'Grand Video Capture' (Bt848) -card=58 - Askey CPH060/ Phoebe TV Master Only (No FM) -card=59 - Askey CPH03x TV Capturer -card=60 - Modular Technology MM100PCTV -card=61 - AG Electronics GMV1 -card=62 - Askey CPH061/ BESTBUY Easy TV (bt878) -card=63 - ATI TV-Wonder -card=64 - ATI TV-Wonder VE -card=65 - Lifeview FlyVideo 2000S LR90 -card=66 - Terratec TValueRadio -card=67 - IODATA GV-BCTV4/PCI -card=68 - 3Dfx VoodooTV FM (Euro), VoodooTV 200 (USA) -card=69 - Active Imaging AIMMS -card=70 - Prolink Pixelview PV-BT878P+ (Rev.4C,8E) -card=71 - Lifeview FlyVideo 98EZ (capture only) LR51 -card=72 - Prolink Pixelview PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM) -card=73 - Sensoray 311 -card=74 - RemoteVision MX (RV605) -card=75 - Powercolor MTV878/ MTV878R/ MTV878F -card=76 - Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP) -card=77 - GrandTec Multi Capture Card (Bt878) -card=78 - Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF -card=79 - DSP Design TCVIDEO -card=80 - Hauppauge WinTV PVR -card=81 - IODATA GV-BCTV5/PCI -card=82 - Osprey 100/150 (878) -card=83 - Osprey 100/150 (848) -card=84 - Osprey 101 (848) -card=85 - Osprey 101/151 -card=86 - Osprey 101/151 w/ svid -card=87 - Osprey 200/201/250/251 -card=88 - Osprey 200/250 -card=89 - Osprey 210/220 -card=90 - Osprey 500 -card=91 - Osprey 540 -card=92 - Osprey 2000 -card=93 - IDS Eagle -card=94 - Pinnacle PCTV Sat -card=95 - Formac ProTV II (bt878) -card=96 - MachTV -card=97 - Euresys Picolo -card=98 - ProVideo PV150 -card=99 - AD-TVK503 -card=100 - Hercules Smart TV Stereo -card=101 - Pace TV & Radio Card -card=102 - IVC-200 -card=103 - Grand X-Guard / Trust 814PCI -card=104 - Nebula Electronics DigiTV -card=105 - ProVideo PV143 -card=106 - PHYTEC VD-009-X1 MiniDIN (bt878) -card=107 - PHYTEC VD-009-X1 Combi (bt878) -card=108 - PHYTEC VD-009 MiniDIN (bt878) -card=109 - PHYTEC VD-009 Combi (bt878) -card=110 - IVC-100 -card=111 - IVC-120G -card=112 - pcHDTV HD-2000 TV -card=113 - Twinhan DST + clones -card=114 - Winfast VC100 -card=115 - Teppro TEV-560/InterVision IV-560 -card=116 - SIMUS GVC1100 -card=117 - NGS NGSTV+ -card=118 - LMLBT4 -card=119 - Tekram M205 PRO -card=120 - Conceptronic CONTVFMi -card=121 - Euresys Picolo Tetra -card=122 - Spirit TV Tuner -card=123 - AVerMedia AVerTV DVB-T 771 -card=124 - AverMedia AverTV DVB-T 761 -card=125 - MATRIX Vision Sigma-SQ -card=126 - MATRIX Vision Sigma-SLC -card=127 - APAC Viewcomp 878(AMAX) -card=128 - DViCO FusionHDTV DVB-T Lite -card=129 - V-Gear MyVCD -card=130 - Super TV Tuner -card=131 - Tibet Systems 'Progress DVR' CS16 -card=132 - Kodicom 4400R (master) -card=133 - Kodicom 4400R (slave) -card=134 - Adlink RTV24 -card=135 - DViCO FusionHDTV 5 Lite -card=136 - Acorp Y878F -card=137 - Conceptronic CTVFMi v2 -card=138 - Prolink Pixelview PV-BT878P+ (Rev.2E) + 0 -> *** UNKNOWN/GENERIC *** + 1 -> MIRO PCTV + 2 -> Hauppauge (bt848) + 3 -> STB, Gateway P/N 6000699 (bt848) + 4 -> Intel Create and Share PCI/ Smart Video Recorder III + 5 -> Diamond DTV2000 + 6 -> AVerMedia TVPhone + 7 -> MATRIX-Vision MV-Delta + 8 -> Lifeview FlyVideo II (Bt848) LR26 / MAXI TV Video PCI2 LR26 + 9 -> IMS/IXmicro TurboTV + 10 -> Hauppauge (bt878) [0070:13eb,0070:3900,2636:10b4] + 11 -> MIRO PCTV pro + 12 -> ADS Technologies Channel Surfer TV (bt848) + 13 -> AVerMedia TVCapture 98 [1461:0002,1461:0004,1461:0300] + 14 -> Aimslab Video Highway Xtreme (VHX) + 15 -> Zoltrix TV-Max + 16 -> Prolink Pixelview PlayTV (bt878) + 17 -> Leadtek WinView 601 + 18 -> AVEC Intercapture + 19 -> Lifeview FlyVideo II EZ /FlyKit LR38 Bt848 (capture only) + 20 -> CEI Raffles Card + 21 -> Lifeview FlyVideo 98/ Lucky Star Image World ConferenceTV LR50 + 22 -> Askey CPH050/ Phoebe Tv Master + FM [14ff:3002] + 23 -> Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV, bt878 [14c7:0101] + 24 -> Askey CPH05X/06X (bt878) [many vendors] [144f:3002,144f:3005,144f:5000,14ff:3000] + 25 -> Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar + 26 -> Hauppauge WinCam newer (bt878) + 27 -> Lifeview FlyVideo 98/ MAXI TV Video PCI2 LR50 + 28 -> Terratec TerraTV+ Version 1.1 (bt878) [153b:1127,1852:1852] + 29 -> Imagenation PXC200 [1295:200a] + 30 -> Lifeview FlyVideo 98 LR50 [1f7f:1850] + 31 -> Formac iProTV, Formac ProTV I (bt848) + 32 -> Intel Create and Share PCI/ Smart Video Recorder III + 33 -> Terratec TerraTValue Version Bt878 [153b:1117,153b:1118,153b:1119,153b:111a,153b:1134,153b:5018] + 34 -> Leadtek WinFast 2000/ WinFast 2000 XP [107d:6606,107d:6609,6606:217d] + 35 -> Lifeview FlyVideo 98 LR50 / Chronos Video Shuttle II [1851:1850] + 36 -> Lifeview FlyVideo 98FM LR50 / Typhoon TView TV/FM Tuner [1852:1852] + 37 -> Prolink PixelView PlayTV pro + 38 -> Askey CPH06X TView99 [144f:3000] + 39 -> Pinnacle PCTV Studio/Rave [11bd:0012] + 40 -> STB TV PCI FM, Gateway P/N 6000704 (bt878), 3Dfx VoodooTV 100 [10b4:2636,10b4:2645,121a:3060] + 41 -> AVerMedia TVPhone 98 [1461:0001,1461:0003] + 42 -> ProVideo PV951 + 43 -> Little OnAir TV + 44 -> Sigma TVII-FM + 45 -> MATRIX-Vision MV-Delta 2 + 46 -> Zoltrix Genie TV/FM [15b0:4000,15b0:400a,15b0:400d,15b0:4010,15b0:4016] + 47 -> Terratec TV/Radio+ [153b:1123] + 48 -> Askey CPH03x/ Dynalink Magic TView + 49 -> IODATA GV-BCTV3/PCI [10fc:4020] + 50 -> Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP + 51 -> Eagle Wireless Capricorn2 (bt878A) + 52 -> Pinnacle PCTV Studio Pro + 53 -> Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS + 54 -> Lifeview FlyVideo 2000 /FlyVideo A2/ Lifetec LT 9415 TV [LR90] + 55 -> Askey CPH031/ BESTBUY Easy TV + 56 -> Lifeview FlyVideo 98FM LR50 + 57 -> GrandTec 'Grand Video Capture' (Bt848) [4344:4142] + 58 -> Askey CPH060/ Phoebe TV Master Only (No FM) + 59 -> Askey CPH03x TV Capturer + 60 -> Modular Technology MM100PCTV + 61 -> AG Electronics GMV1 [15cb:0101] + 62 -> Askey CPH061/ BESTBUY Easy TV (bt878) + 63 -> ATI TV-Wonder [1002:0001] + 64 -> ATI TV-Wonder VE [1002:0003] + 65 -> Lifeview FlyVideo 2000S LR90 + 66 -> Terratec TValueRadio [153b:1135] + 67 -> IODATA GV-BCTV4/PCI [10fc:4050] + 68 -> 3Dfx VoodooTV FM (Euro), VoodooTV 200 (USA) [121a:3000,10b4:2637] + 69 -> Active Imaging AIMMS + 70 -> Prolink Pixelview PV-BT878P+ (Rev.4C,8E) + 71 -> Lifeview FlyVideo 98EZ (capture only) LR51 [1851:1851] + 72 -> Prolink Pixelview PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM) [1554:4011] + 73 -> Sensoray 311 [6000:0311] + 74 -> RemoteVision MX (RV605) + 75 -> Powercolor MTV878/ MTV878R/ MTV878F + 76 -> Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP) [0e11:0079] + 77 -> GrandTec Multi Capture Card (Bt878) + 78 -> Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF [0a01:17de] + 79 -> DSP Design TCVIDEO + 80 -> Hauppauge WinTV PVR [0070:4500] + 81 -> IODATA GV-BCTV5/PCI [10fc:4070] + 82 -> Osprey 100/150 (878) + 83 -> Osprey 100/150 (848) + 84 -> Osprey 101 (848) + 85 -> Osprey 101/151 + 86 -> Osprey 101/151 w/ svid + 87 -> Osprey 200/201/250/251 + 88 -> Osprey 200/250 + 89 -> Osprey 210/220 + 90 -> Osprey 500 + 91 -> Osprey 540 + 92 -> Osprey 2000 + 93 -> IDS Eagle + 94 -> Pinnacle PCTV Sat [11bd:001c] + 95 -> Formac ProTV II (bt878) + 96 -> MachTV + 97 -> Euresys Picolo + 98 -> ProVideo PV150 + 99 -> AD-TVK503 +100 -> Hercules Smart TV Stereo +101 -> Pace TV & Radio Card +102 -> IVC-200 +103 -> Grand X-Guard / Trust 814PCI [0304:0102] +104 -> Nebula Electronics DigiTV [0071:0101] +105 -> ProVideo PV143 +106 -> PHYTEC VD-009-X1 MiniDIN (bt878) +107 -> PHYTEC VD-009-X1 Combi (bt878) +108 -> PHYTEC VD-009 MiniDIN (bt878) +109 -> PHYTEC VD-009 Combi (bt878) +110 -> IVC-100 +111 -> IVC-120G +112 -> pcHDTV HD-2000 TV [7063:2000] +113 -> Twinhan DST + clones [11bd:0026,1822:0001] +114 -> Winfast VC100 [107d:6607] +115 -> Teppro TEV-560/InterVision IV-560 +116 -> SIMUS GVC1100 +117 -> NGS NGSTV+ +118 -> LMLBT4 +119 -> Tekram M205 PRO +120 -> Conceptronic CONTVFMi +121 -> Euresys Picolo Tetra [1805:0105,1805:0106,1805:0107,1805:0108] +122 -> Spirit TV Tuner +123 -> AVerMedia AVerTV DVB-T 771 [1461:0771] +124 -> AverMedia AverTV DVB-T 761 [1461:0761] +125 -> MATRIX Vision Sigma-SQ +126 -> MATRIX Vision Sigma-SLC +127 -> APAC Viewcomp 878(AMAX) +128 -> DViCO FusionHDTV DVB-T Lite +129 -> V-Gear MyVCD +130 -> Super TV Tuner +131 -> Tibet Systems 'Progress DVR' CS16 +132 -> Kodicom 4400R (master) +133 -> Kodicom 4400R (slave) +134 -> Adlink RTV24 +135 -> DViCO FusionHDTV 5 Lite +136 -> Acorp Y878F [9511:1540] +137 -> Conceptronic CTVFMi v2 +138 -> Prolink Pixelview PV-BT878P+ (Rev.2E) diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index 84203302b27..0e2ea497ad7 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -53,7 +53,7 @@ tuner=51 - Philips PAL/SECAM_D (FM 1256 I-H3) tuner=52 - Thomson DDT 7610 (ATSC/NTSC) tuner=53 - Philips FQ1286 tuner=54 - tda8290+75 -tuner=55 - LG PAL (TAPE series) +tuner=55 - TCL 2002MB tuner=56 - Philips PAL/SECAM multi (FQ1216AME MK4) tuner=57 - Philips FQ1236A MK4 tuner=58 - Ymec TVision TVF-8531MF/8831MF/8731MF -- cgit v1.2.3 From 6589d36a07864aa110dd4f1065c02f5bc7cc29a1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:36:54 -0800 Subject: [PATCH] v4l: 695: added more pci id - Added more PCI ID. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.bttv | 46 ++++++++++++++++----------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index a35465f50f9..dd7b565be69 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -13,7 +13,7 @@ 12 -> ADS Technologies Channel Surfer TV (bt848) 13 -> AVerMedia TVCapture 98 [1461:0002,1461:0004,1461:0300] 14 -> Aimslab Video Highway Xtreme (VHX) - 15 -> Zoltrix TV-Max + 15 -> Zoltrix TV-Max [a1a0:a0fc] 16 -> Prolink Pixelview PlayTV (bt878) 17 -> Leadtek WinView 601 18 -> AVEC Intercapture @@ -32,15 +32,15 @@ 31 -> Formac iProTV, Formac ProTV I (bt848) 32 -> Intel Create and Share PCI/ Smart Video Recorder III 33 -> Terratec TerraTValue Version Bt878 [153b:1117,153b:1118,153b:1119,153b:111a,153b:1134,153b:5018] - 34 -> Leadtek WinFast 2000/ WinFast 2000 XP [107d:6606,107d:6609,6606:217d] - 35 -> Lifeview FlyVideo 98 LR50 / Chronos Video Shuttle II [1851:1850] + 34 -> Leadtek WinFast 2000/ WinFast 2000 XP [107d:6606,107d:6609,6606:217d,f6ff:fff6] + 35 -> Lifeview FlyVideo 98 LR50 / Chronos Video Shuttle II [1851:1850,1851:a050] 36 -> Lifeview FlyVideo 98FM LR50 / Typhoon TView TV/FM Tuner [1852:1852] 37 -> Prolink PixelView PlayTV pro - 38 -> Askey CPH06X TView99 [144f:3000] - 39 -> Pinnacle PCTV Studio/Rave [11bd:0012] + 38 -> Askey CPH06X TView99 [144f:3000,144f:a005,a04f:a0fc] + 39 -> Pinnacle PCTV Studio/Rave [11bd:0012,bd11:1200,bd11:ff00,11bd:ff12] 40 -> STB TV PCI FM, Gateway P/N 6000704 (bt878), 3Dfx VoodooTV 100 [10b4:2636,10b4:2645,121a:3060] 41 -> AVerMedia TVPhone 98 [1461:0001,1461:0003] - 42 -> ProVideo PV951 + 42 -> ProVideo PV951 [aa0c:146c] 43 -> Little OnAir TV 44 -> Sigma TVII-FM 45 -> MATRIX-Vision MV-Delta 2 @@ -54,7 +54,7 @@ 53 -> Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS 54 -> Lifeview FlyVideo 2000 /FlyVideo A2/ Lifetec LT 9415 TV [LR90] 55 -> Askey CPH031/ BESTBUY Easy TV - 56 -> Lifeview FlyVideo 98FM LR50 + 56 -> Lifeview FlyVideo 98FM LR50 [a051:41a0] 57 -> GrandTec 'Grand Video Capture' (Bt848) [4344:4142] 58 -> Askey CPH060/ Phoebe TV Master Only (No FM) 59 -> Askey CPH03x TV Capturer @@ -64,7 +64,7 @@ 63 -> ATI TV-Wonder [1002:0001] 64 -> ATI TV-Wonder VE [1002:0003] 65 -> Lifeview FlyVideo 2000S LR90 - 66 -> Terratec TValueRadio [153b:1135] + 66 -> Terratec TValueRadio [153b:1135,153b:ff3b] 67 -> IODATA GV-BCTV4/PCI [10fc:4050] 68 -> 3Dfx VoodooTV FM (Euro), VoodooTV 200 (USA) [121a:3000,10b4:2637] 69 -> Active Imaging AIMMS @@ -79,42 +79,42 @@ 78 -> Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF [0a01:17de] 79 -> DSP Design TCVIDEO 80 -> Hauppauge WinTV PVR [0070:4500] - 81 -> IODATA GV-BCTV5/PCI [10fc:4070] - 82 -> Osprey 100/150 (878) + 81 -> IODATA GV-BCTV5/PCI [10fc:4070,10fc:d018] + 82 -> Osprey 100/150 (878) [0070:ff00] 83 -> Osprey 100/150 (848) 84 -> Osprey 101 (848) 85 -> Osprey 101/151 86 -> Osprey 101/151 w/ svid 87 -> Osprey 200/201/250/251 - 88 -> Osprey 200/250 + 88 -> Osprey 200/250 [0070:ff01] 89 -> Osprey 210/220 - 90 -> Osprey 500 - 91 -> Osprey 540 - 92 -> Osprey 2000 + 90 -> Osprey 500 [0070:ff02] + 91 -> Osprey 540 [0070:ff04] + 92 -> Osprey 2000 [0070:ff03] 93 -> IDS Eagle 94 -> Pinnacle PCTV Sat [11bd:001c] 95 -> Formac ProTV II (bt878) 96 -> MachTV 97 -> Euresys Picolo - 98 -> ProVideo PV150 + 98 -> ProVideo PV150 [aa00:1460,aa01:1461,aa02:1462,aa03:1463,aa04:1464,aa05:1465,aa06:1466,aa07:1467] 99 -> AD-TVK503 100 -> Hercules Smart TV Stereo 101 -> Pace TV & Radio Card -102 -> IVC-200 +102 -> IVC-200 [0000:a155,0001:a155,0002:a155,0003:a155,0100:a155,0101:a155,0102:a155,0103:a155] 103 -> Grand X-Guard / Trust 814PCI [0304:0102] 104 -> Nebula Electronics DigiTV [0071:0101] -105 -> ProVideo PV143 +105 -> ProVideo PV143 [aa00:1430,aa00:1431,aa00:1432,aa00:1433,aa03:1433] 106 -> PHYTEC VD-009-X1 MiniDIN (bt878) 107 -> PHYTEC VD-009-X1 Combi (bt878) 108 -> PHYTEC VD-009 MiniDIN (bt878) 109 -> PHYTEC VD-009 Combi (bt878) -110 -> IVC-100 -111 -> IVC-120G +110 -> IVC-100 [ff00:a132] +111 -> IVC-120G [ff00:a182,ff01:a182,ff02:a182,ff03:a182,ff04:a182,ff05:a182,ff06:a182,ff07:a182,ff08:a182,ff09:a182,ff0a:a182,ff0b:a182,ff0c:a182,ff0d:a182,ff0e:a182,ff0f:a182] 112 -> pcHDTV HD-2000 TV [7063:2000] -113 -> Twinhan DST + clones [11bd:0026,1822:0001] +113 -> Twinhan DST + clones [11bd:0026,1822:0001,270f:fc00] 114 -> Winfast VC100 [107d:6607] 115 -> Teppro TEV-560/InterVision IV-560 -116 -> SIMUS GVC1100 +116 -> SIMUS GVC1100 [aa6a:82b2] 117 -> NGS NGSTV+ 118 -> LMLBT4 119 -> Tekram M205 PRO @@ -126,14 +126,14 @@ 125 -> MATRIX Vision Sigma-SQ 126 -> MATRIX Vision Sigma-SLC 127 -> APAC Viewcomp 878(AMAX) -128 -> DViCO FusionHDTV DVB-T Lite +128 -> DViCO FusionHDTV DVB-T Lite [18ac:db10] 129 -> V-Gear MyVCD 130 -> Super TV Tuner 131 -> Tibet Systems 'Progress DVR' CS16 132 -> Kodicom 4400R (master) 133 -> Kodicom 4400R (slave) 134 -> Adlink RTV24 -135 -> DViCO FusionHDTV 5 Lite +135 -> DViCO FusionHDTV 5 Lite [18ac:d500] 136 -> Acorp Y878F [9511:1540] 137 -> Conceptronic CTVFMi v2 138 -> Prolink Pixelview PV-BT878P+ (Rev.2E) -- cgit v1.2.3 From 6af90ab5e7a9111a861fde33726ae960d30915f0 Mon Sep 17 00:00:00 2001 From: Arnaud Patard Date: Tue, 8 Nov 2005 21:36:55 -0800 Subject: [PATCH] v4l: 700: added ir for lifeview flytv platinum mini2 - Added IR for LifeView FlyTV Platinum Mini2. Signed-off-by: Arnaud Patard Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-cards.c | 1 + drivers/media/video/saa7134/saa7134-input.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index a096799dc5f..3bb0644145b 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2823,6 +2823,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) dev->has_remote = 1; board_flyvideo(dev); break; + case SAA7134_BOARD_FLYTVPLATINUM_MINI2: case SAA7134_BOARD_FLYTVPLATINUM_FM: case SAA7134_BOARD_CINERGY400: case SAA7134_BOARD_CINERGY600: diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index b69b18c5f18..f6fe5f889a4 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -516,6 +516,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_FLYVIDEO2000: case SAA7134_BOARD_FLYVIDEO3000: case SAA7134_BOARD_FLYTVPLATINUM_FM: + case SAA7134_BOARD_FLYTVPLATINUM_MINI2: ir_codes = flyvideo_codes; mask_keycode = 0xEC00000; mask_keydown = 0x0040000; -- cgit v1.2.3 From 90a7ed47a37297bee1f4ce11484190ccac29ae7c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:36:56 -0800 Subject: [PATCH] v4l: 702: included audio chips enum - Included audio chips enum Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tveeprom.c | 432 +++++++++++++++++++++++------------------ include/media/audiochip.h | 17 ++ 2 files changed, 264 insertions(+), 185 deletions(-) diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 6453b71f299..a9bad89b4d6 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -40,6 +40,7 @@ #include #include +#include "audiochip.h" MODULE_DESCRIPTION("i2c Hauppauge eeprom decoder driver"); MODULE_AUTHOR("John Klar"); @@ -134,8 +135,8 @@ hauppauge_tuner[] = { TUNER_TEMIC_4039FR5_NTSC, "Temic 4039FR5" }, { TUNER_PHILIPS_FQ1216ME, "Philips FQ1216 ME" }, { TUNER_TEMIC_4066FY5_PAL_I, "Temic 4066FY5" }, - { TUNER_PHILIPS_NTSC, "Philips TD1536" }, - { TUNER_PHILIPS_NTSC, "Philips TD1536D" }, + { TUNER_PHILIPS_NTSC, "Philips TD1536" }, + { TUNER_PHILIPS_NTSC, "Philips TD1536D" }, { TUNER_PHILIPS_NTSC, "Philips FMR1236" }, /* mono radio */ { TUNER_ABSENT, "Philips FI1256MP" }, /* 40-49 */ @@ -189,7 +190,7 @@ hauppauge_tuner[] = { TUNER_LG_PAL_NEW_TAPC, "TCL 2002MB 3"}, { TUNER_LG_PAL_NEW_TAPC, "TCL 2002MI 3"}, { TUNER_TCL_2002N, "TCL 2002N 6A"}, - { TUNER_ABSENT, "Philips FQ1236 MK3"}, + { TUNER_PHILIPS_FM1236_MK3, "Philips FQ1236 MK3"}, { TUNER_ABSENT, "Samsung TCPN 2121P30A"}, { TUNER_ABSENT, "Samsung TCPE 4121P30A"}, { TUNER_PHILIPS_FM1216ME_MK3, "TCL MFPE05 2"}, @@ -202,93 +203,129 @@ hauppauge_tuner[] = { TUNER_ABSENT, "Philips FQ1236 MK5"}, { TUNER_ABSENT, "Samsung TCPG_6121P30A"}, { TUNER_TCL_2002MB, "TCL 2002MB_3H"}, - { TUNER_ABSENT, "TCL 2002MI_3H"}, - { TUNER_TCL_2002N, "TCL 2002N 5H"}, + { TUNER_ABSENT, "TCL 2002MI_3H"}, + { TUNER_TCL_2002N, "TCL 2002N 5H"}, /* 100-109 */ { TUNER_ABSENT, "Philips FMD1216ME"}, - { TUNER_TEA5767, "Philips TEA5768HL FM Radio"}, - { TUNER_ABSENT, "Panasonic ENV57H12D5"}, - { TUNER_ABSENT, "TCL MFNM05-4"}, - { TUNER_ABSENT, "TCL MNM05-4"}, - { TUNER_PHILIPS_FM1216ME_MK3, "TCL MPE05-2"}, - { TUNER_ABSENT, "TCL MQNM05-4"}, - { TUNER_ABSENT, "LG TAPC-W701D"}, - { TUNER_ABSENT, "TCL 9886P-WM"}, - { TUNER_ABSENT, "TCL 1676NM-WM"}, + { TUNER_TEA5767, "Philips TEA5768HL FM Radio"}, + { TUNER_ABSENT, "Panasonic ENV57H12D5"}, + { TUNER_ABSENT, "TCL MFNM05-4"}, + { TUNER_ABSENT, "TCL MNM05-4"}, + { TUNER_PHILIPS_FM1216ME_MK3, "TCL MPE05-2"}, + { TUNER_ABSENT, "TCL MQNM05-4"}, + { TUNER_ABSENT, "LG TAPC-W701D"}, + { TUNER_ABSENT, "TCL 9886P-WM"}, + { TUNER_ABSENT, "TCL 1676NM-WM"}, }; -/* This list is supplied by Hauppauge. Thanks! */ -static const char *audioIC[] = { - /* 0-4 */ - "None", "TEA6300", "TEA6320", "TDA9850", "MSP3400C", - /* 5-9 */ - "MSP3410D", "MSP3415", "MSP3430", "MSP3438", "CS5331", - /* 10-14 */ - "MSP3435", "MSP3440", "MSP3445", "MSP3411", "MSP3416", - /* 15-19 */ - "MSP3425", "MSP3451", "MSP3418", "Type 0x12", "OKI7716", - /* 20-24 */ - "MSP4410", "MSP4420", "MSP4440", "MSP4450", "MSP4408", - /* 25-29 */ - "MSP4418", "MSP4428", "MSP4448", "MSP4458", "Type 0x1d", - /* 30-34 */ - "CX880", "CX881", "CX883", "CX882", "CX25840", - /* 35-38 */ - "CX25841", "CX25842", "CX25843", "CX23418", +static struct HAUPPAUGE_AUDIOIC +{ + enum audiochip id; + char *name; +} +audioIC[] = +{ + /* 0-4 */ + {AUDIO_CHIP_NONE, "None"}, + {AUDIO_CHIP_TEA6300, "TEA6300"}, + {AUDIO_CHIP_TEA6300, "TEA6320"}, + {AUDIO_CHIP_TDA985X, "TDA9850"}, + {AUDIO_CHIP_MSP34XX, "MSP3400C"}, + /* 5-9 */ + {AUDIO_CHIP_MSP34XX, "MSP3410D"}, + {AUDIO_CHIP_MSP34XX, "MSP3415"}, + {AUDIO_CHIP_MSP34XX, "MSP3430"}, + {AUDIO_CHIP_UNKNOWN, "MSP3438"}, + {AUDIO_CHIP_UNKNOWN, "CS5331"}, + /* 10-14 */ + {AUDIO_CHIP_MSP34XX, "MSP3435"}, + {AUDIO_CHIP_MSP34XX, "MSP3440"}, + {AUDIO_CHIP_MSP34XX, "MSP3445"}, + {AUDIO_CHIP_UNKNOWN, "MSP3411"}, + {AUDIO_CHIP_UNKNOWN, "MSP3416"}, + /* 15-19 */ + {AUDIO_CHIP_MSP34XX, "MSP3425"}, + {AUDIO_CHIP_UNKNOWN, "MSP3451"}, + {AUDIO_CHIP_UNKNOWN, "MSP3418"}, + {AUDIO_CHIP_UNKNOWN, "Type 0x12"}, + {AUDIO_CHIP_UNKNOWN, "OKI7716"}, + /* 20-24 */ + {AUDIO_CHIP_UNKNOWN, "MSP4410"}, + {AUDIO_CHIP_UNKNOWN, "MSP4420"}, + {AUDIO_CHIP_UNKNOWN, "MSP4440"}, + {AUDIO_CHIP_UNKNOWN, "MSP4450"}, + {AUDIO_CHIP_UNKNOWN, "MSP4408"}, + /* 25-29 */ + {AUDIO_CHIP_UNKNOWN, "MSP4418"}, + {AUDIO_CHIP_UNKNOWN, "MSP4428"}, + {AUDIO_CHIP_UNKNOWN, "MSP4448"}, + {AUDIO_CHIP_UNKNOWN, "MSP4458"}, + {AUDIO_CHIP_UNKNOWN, "Type 0x1d"}, + /* 30-34 */ + {AUDIO_CHIP_INTERNAL, "CX880"}, + {AUDIO_CHIP_INTERNAL, "CX881"}, + {AUDIO_CHIP_INTERNAL, "CX883"}, + {AUDIO_CHIP_INTERNAL, "CX882"}, + {AUDIO_CHIP_INTERNAL, "CX25840"}, + /* 35-38 */ + {AUDIO_CHIP_INTERNAL, "CX25841"}, + {AUDIO_CHIP_INTERNAL, "CX25842"}, + {AUDIO_CHIP_INTERNAL, "CX25843"}, + {AUDIO_CHIP_INTERNAL, "CX23418"}, }; /* This list is supplied by Hauppauge. Thanks! */ static const char *decoderIC[] = { - /* 0-4 */ - "None", "BT815", "BT817", "BT819", "BT815A", - /* 5-9 */ - "BT817A", "BT819A", "BT827", "BT829", "BT848", - /* 10-14 */ - "BT848A", "BT849A", "BT829A", "BT827A", "BT878", - /* 15-19 */ - "BT879", "BT880", "VPX3226E", "SAA7114", "SAA7115", - /* 20-24 */ - "CX880", "CX881", "CX883", "SAA7111", "SAA7113", - /* 25-29 */ - "CX882", "TVP5150A", "CX25840", "CX25841", "CX25842", - /* 30-31 */ - "CX25843", "CX23418", + /* 0-4 */ + "None", "BT815", "BT817", "BT819", "BT815A", + /* 5-9 */ + "BT817A", "BT819A", "BT827", "BT829", "BT848", + /* 10-14 */ + "BT848A", "BT849A", "BT829A", "BT827A", "BT878", + /* 15-19 */ + "BT879", "BT880", "VPX3226E", "SAA7114", "SAA7115", + /* 20-24 */ + "CX880", "CX881", "CX883", "SAA7111", "SAA7113", + /* 25-29 */ + "CX882", "TVP5150A", "CX25840", "CX25841", "CX25842", + /* 30-31 */ + "CX25843", "CX23418", }; static int hasRadioTuner(int tunerType) { switch (tunerType) { - case 18: //PNPEnv_TUNER_FR1236_MK2: - case 23: //PNPEnv_TUNER_FM1236: - case 38: //PNPEnv_TUNER_FMR1236: - case 16: //PNPEnv_TUNER_FR1216_MK2: - case 19: //PNPEnv_TUNER_FR1246_MK2: - case 21: //PNPEnv_TUNER_FM1216: - case 24: //PNPEnv_TUNER_FM1246: - case 17: //PNPEnv_TUNER_FR1216MF_MK2: - case 22: //PNPEnv_TUNER_FM1216MF: - case 20: //PNPEnv_TUNER_FR1256_MK2: - case 25: //PNPEnv_TUNER_FM1256: - case 33: //PNPEnv_TUNER_4039FR5: - case 42: //PNPEnv_TUNER_4009FR5: - case 52: //PNPEnv_TUNER_4049FM5: - case 54: //PNPEnv_TUNER_4049FM5_AltI2C: - case 44: //PNPEnv_TUNER_4009FN5: - case 31: //PNPEnv_TUNER_TCPB9085P: - case 30: //PNPEnv_TUNER_TCPN9085D: - case 46: //PNPEnv_TUNER_TP18NSR01F: - case 47: //PNPEnv_TUNER_TP18PSB01D: - case 49: //PNPEnv_TUNER_TAPC_I001D: - case 60: //PNPEnv_TUNER_TAPE_S001D_MK3: - case 57: //PNPEnv_TUNER_FM1216ME_MK3: - case 59: //PNPEnv_TUNER_FM1216MP_MK3: - case 58: //PNPEnv_TUNER_FM1236_MK3: - case 68: //PNPEnv_TUNER_TAPE_H001F_MK3: - case 61: //PNPEnv_TUNER_TAPE_M001D_MK3: - case 78: //PNPEnv_TUNER_TDA8275C1_8290_FM: - case 89: //PNPEnv_TUNER_TCL_MFPE05_2: - case 92: //PNPEnv_TUNER_PHILIPS_FQ1236A_MK4: - return 1; + case 18: //PNPEnv_TUNER_FR1236_MK2: + case 23: //PNPEnv_TUNER_FM1236: + case 38: //PNPEnv_TUNER_FMR1236: + case 16: //PNPEnv_TUNER_FR1216_MK2: + case 19: //PNPEnv_TUNER_FR1246_MK2: + case 21: //PNPEnv_TUNER_FM1216: + case 24: //PNPEnv_TUNER_FM1246: + case 17: //PNPEnv_TUNER_FR1216MF_MK2: + case 22: //PNPEnv_TUNER_FM1216MF: + case 20: //PNPEnv_TUNER_FR1256_MK2: + case 25: //PNPEnv_TUNER_FM1256: + case 33: //PNPEnv_TUNER_4039FR5: + case 42: //PNPEnv_TUNER_4009FR5: + case 52: //PNPEnv_TUNER_4049FM5: + case 54: //PNPEnv_TUNER_4049FM5_AltI2C: + case 44: //PNPEnv_TUNER_4009FN5: + case 31: //PNPEnv_TUNER_TCPB9085P: + case 30: //PNPEnv_TUNER_TCPN9085D: + case 46: //PNPEnv_TUNER_TP18NSR01F: + case 47: //PNPEnv_TUNER_TP18PSB01D: + case 49: //PNPEnv_TUNER_TAPC_I001D: + case 60: //PNPEnv_TUNER_TAPE_S001D_MK3: + case 57: //PNPEnv_TUNER_FM1216ME_MK3: + case 59: //PNPEnv_TUNER_FM1216MP_MK3: + case 58: //PNPEnv_TUNER_FM1236_MK3: + case 68: //PNPEnv_TUNER_TAPE_H001F_MK3: + case 61: //PNPEnv_TUNER_TAPE_M001D_MK3: + case 78: //PNPEnv_TUNER_TDA8275C1_8290_FM: + case 89: //PNPEnv_TUNER_TCL_MFPE05_2: + case 92: //PNPEnv_TUNER_PHILIPS_FQ1236A_MK4: + return 1; } return 0; } @@ -318,19 +355,27 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, ** # of inputs/outputs ??? */ - int i, j, len, done, beenhere, tag; + int i, j, len, done, beenhere, tag,start; - int tuner1 = 0, t_format1 = 0; + int tuner1 = 0, t_format1 = 0, audioic=-1; char *t_name1 = NULL; - const char *t_fmt_name1[8] = { " none", "", "", "", "", "", "", "" }; + const char *t_fmt_name1[8] = { " none", "", "", "", "", "", "", "" }; - int tuner2 = 0, t_format2 = 0; + int tuner2 = 0, t_format2 = 0; char *t_name2 = NULL; - const char *t_fmt_name2[8] = { " none", "", "", "", "", "", "", "" }; + const char *t_fmt_name2[8] = { " none", "", "", "", "", "", "", "" }; - memset(tvee, 0, sizeof(*tvee)); + memset(tvee, 0, sizeof(*tvee)); done = len = beenhere = 0; - for (i = 0; !done && i < 256; i += len) { + + /* Hack for processing eeprom for em28xx */ + if ((eeprom_data[0]==0x1a)&&(eeprom_data[1]==0xeb)&& + (eeprom_data[2]==0x67)&&(eeprom_data[3]==0x95)) + start=0xa0; + else + start=0; + + for (i = start; !done && i < 256; i += len) { if (eeprom_data[i] == 0x84) { len = eeprom_data[i + 1] + (eeprom_data[i + 2] << 8); i += 3; @@ -344,28 +389,28 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, ++i; } else { tveeprom_warn("Encountered bad packet header [%02x]. " - "Corrupt or not a Hauppauge eeprom.\n", eeprom_data[i]); + "Corrupt or not a Hauppauge eeprom.\n", eeprom_data[i]); return; } - if (debug) { - tveeprom_info("Tag [%02x] + %d bytes:", eeprom_data[i], len - 1); - for(j = 1; j < len; j++) { - printk(" %02x", eeprom_data[i + j]); - } - printk("\n"); - } + if (debug) { + tveeprom_info("Tag [%02x] + %d bytes:", eeprom_data[i], len - 1); + for(j = 1; j < len; j++) { + printk(" %02x", eeprom_data[i + j]); + } + printk("\n"); + } /* process by tag */ tag = eeprom_data[i]; switch (tag) { case 0x00: - /* tag: 'Comprehensive' */ + /* tag: 'Comprehensive' */ tuner1 = eeprom_data[i+6]; t_format1 = eeprom_data[i+5]; tvee->has_radio = eeprom_data[i+len-1]; - /* old style tag, don't know how to detect - IR presence, mark as unknown. */ + /* old style tag, don't know how to detect + IR presence, mark as unknown. */ tvee->has_ir = 2; tvee->model = eeprom_data[i+8] + @@ -376,7 +421,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, break; case 0x01: - /* tag: 'SerialID' */ + /* tag: 'SerialID' */ tvee->serial_number = eeprom_data[i+6] + (eeprom_data[i+7] << 8) + @@ -384,17 +429,21 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, break; case 0x02: - /* tag 'AudioInfo' - Note mask with 0x7F, high bit used on some older models - to indicate 4052 mux was removed in favor of using MSP - inputs directly. */ - tvee->audio_processor = eeprom_data[i+2] & 0x7f; + /* tag 'AudioInfo' + Note mask with 0x7F, high bit used on some older models + to indicate 4052 mux was removed in favor of using MSP + inputs directly. */ + audioic = eeprom_data[i+2] & 0x7f; + if (audioic < sizeof(audioIC)/sizeof(*audioIC)) + tvee->audio_processor = audioIC[audioic].id; + else + tvee->audio_processor = AUDIO_CHIP_UNKNOWN; break; - /* case 0x03: tag 'EEInfo' */ + /* case 0x03: tag 'EEInfo' */ case 0x04: - /* tag 'SerialID2' */ + /* tag 'SerialID2' */ tvee->serial_number = eeprom_data[i+5] + (eeprom_data[i+6] << 8) + @@ -402,15 +451,20 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, break; case 0x05: - /* tag 'Audio2' - Note mask with 0x7F, high bit used on some older models - to indicate 4052 mux was removed in favor of using MSP - inputs directly. */ - tvee->audio_processor = eeprom_data[i+1] & 0x7f; + /* tag 'Audio2' + Note mask with 0x7F, high bit used on some older models + to indicate 4052 mux was removed in favor of using MSP + inputs directly. */ + audioic = eeprom_data[i+1] & 0x7f; + if (audioic < sizeof(audioIC)/sizeof(*audioIC)) + tvee->audio_processor = audioIC[audioic].id; + else + tvee->audio_processor = AUDIO_CHIP_UNKNOWN; + break; case 0x06: - /* tag 'ModelRev' */ + /* tag 'ModelRev' */ tvee->model = eeprom_data[i+1] + (eeprom_data[i+2] << 8); @@ -420,55 +474,55 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, break; case 0x07: - /* tag 'Details': according to Hauppauge not interesting - on any PCI-era or later boards. */ + /* tag 'Details': according to Hauppauge not interesting + on any PCI-era or later boards. */ break; - /* there is no tag 0x08 defined */ + /* there is no tag 0x08 defined */ case 0x09: - /* tag 'Video' */ + /* tag 'Video' */ tvee->decoder_processor = eeprom_data[i + 1]; break; case 0x0a: - /* tag 'Tuner' */ + /* tag 'Tuner' */ if (beenhere == 0) { tuner1 = eeprom_data[i+2]; t_format1 = eeprom_data[i+1]; beenhere = 1; } else { - /* a second (radio) tuner may be present */ + /* a second (radio) tuner may be present */ tuner2 = eeprom_data[i+2]; t_format2 = eeprom_data[i+1]; - if (t_format2 == 0) { /* not a TV tuner? */ - tvee->has_radio = 1; /* must be radio */ - } - } + if (t_format2 == 0) { /* not a TV tuner? */ + tvee->has_radio = 1; /* must be radio */ + } + } break; - case 0x0b: - /* tag 'Inputs': according to Hauppauge this is specific - to each driver family, so no good assumptions can be - made. */ - break; + case 0x0b: + /* tag 'Inputs': according to Hauppauge this is specific + to each driver family, so no good assumptions can be + made. */ + break; - /* case 0x0c: tag 'Balun' */ - /* case 0x0d: tag 'Teletext' */ + /* case 0x0c: tag 'Balun' */ + /* case 0x0d: tag 'Teletext' */ case 0x0e: - /* tag: 'Radio' */ + /* tag: 'Radio' */ tvee->has_radio = eeprom_data[i+1]; break; - case 0x0f: - /* tag 'IRInfo' */ - tvee->has_ir = eeprom_data[i+1]; - break; + case 0x0f: + /* tag 'IRInfo' */ + tvee->has_ir = eeprom_data[i+1]; + break; - /* case 0x10: tag 'VBIInfo' */ - /* case 0x11: tag 'QCInfo' */ - /* case 0x12: tag 'InfoBits' */ + /* case 0x10: tag 'VBIInfo' */ + /* case 0x11: tag 'QCInfo' */ + /* case 0x12: tag 'InfoBits' */ default: tveeprom_dbg("Not sure what to do with tag [%02x]\n", tag); @@ -489,11 +543,11 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, tvee->rev_str[4] = 0; } - if (hasRadioTuner(tuner1) && !tvee->has_radio) { - tveeprom_info("The eeprom says no radio is present, but the tuner type\n"); - tveeprom_info("indicates otherwise. I will assume that radio is present.\n"); - tvee->has_radio = 1; - } + if (hasRadioTuner(tuner1) && !tvee->has_radio) { + tveeprom_info("The eeprom says no radio is present, but the tuner type\n"); + tveeprom_info("indicates otherwise. I will assume that radio is present.\n"); + tvee->has_radio = 1; + } if (tuner1 < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) { tvee->tuner_type = hauppauge_tuner[tuner1].id; @@ -516,45 +570,53 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, tvee->tuner_formats |= hauppauge_tuner_fmt[i].id; t_fmt_name1[j++] = hauppauge_tuner_fmt[i].name; } - if (t_format2 & (1 << i)) { - tvee->tuner2_formats |= hauppauge_tuner_fmt[i].id; - t_fmt_name2[j++] = hauppauge_tuner_fmt[i].name; - } + if (t_format2 & (1 << i)) { + tvee->tuner2_formats |= hauppauge_tuner_fmt[i].id; + t_fmt_name2[j++] = hauppauge_tuner_fmt[i].name; + } } tveeprom_info("Hauppauge model %d, rev %s, serial# %d\n", - tvee->model, tvee->rev_str, tvee->serial_number); + tvee->model, tvee->rev_str, tvee->serial_number); tveeprom_info("tuner model is %s (idx %d, type %d)\n", - t_name1, tuner1, tvee->tuner_type); + t_name1, tuner1, tvee->tuner_type); tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n", - t_fmt_name1[0], t_fmt_name1[1], t_fmt_name1[2], t_fmt_name1[3], - t_fmt_name1[4], t_fmt_name1[5], t_fmt_name1[6], t_fmt_name1[7], - t_format1); - if (tuner2) { - tveeprom_info("second tuner model is %s (idx %d, type %d)\n", - t_name2, tuner2, tvee->tuner2_type); - } - if (t_format2) { - tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n", - t_fmt_name2[0], t_fmt_name2[1], t_fmt_name2[2], t_fmt_name2[3], - t_fmt_name2[4], t_fmt_name2[5], t_fmt_name2[6], t_fmt_name2[7], - t_format2); - } - tveeprom_info("audio processor is %s (idx %d)\n", - STRM(audioIC, tvee->audio_processor), - tvee->audio_processor); - if (tvee->decoder_processor) { - tveeprom_info("decoder processor is %s (idx %d)\n", - STRM(decoderIC, tvee->decoder_processor), - tvee->decoder_processor); - } - if (tvee->has_ir == 2) - tveeprom_info("has %sradio\n", - tvee->has_radio ? "" : "no "); - else - tveeprom_info("has %sradio, has %sIR remote\n", - tvee->has_radio ? "" : "no ", - tvee->has_ir ? "" : "no "); + t_fmt_name1[0], t_fmt_name1[1], t_fmt_name1[2], t_fmt_name1[3], + t_fmt_name1[4], t_fmt_name1[5], t_fmt_name1[6], t_fmt_name1[7], + t_format1); + if (tuner2) { + tveeprom_info("second tuner model is %s (idx %d, type %d)\n", + t_name2, tuner2, tvee->tuner2_type); + } + if (t_format2) { + tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n", + t_fmt_name2[0], t_fmt_name2[1], t_fmt_name2[2], t_fmt_name2[3], + t_fmt_name2[4], t_fmt_name2[5], t_fmt_name2[6], t_fmt_name2[7], + t_format2); + } + if (audioic<0) { + tveeprom_info("audio processor is unknown (no idx)\n"); + tvee->audio_processor=AUDIO_CHIP_UNKNOWN; + } else { + if (audioic < sizeof(audioIC)/sizeof(*audioIC)) + tveeprom_info("audio processor is %s (idx %d)\n", + audioIC[audioic].name,audioic); + else + tveeprom_info("audio processor is unknown (idx %d)\n", + audioic); + } + if (tvee->decoder_processor) { + tveeprom_info("decoder processor is %s (idx %d)\n", + STRM(decoderIC, tvee->decoder_processor), + tvee->decoder_processor); + } + if (tvee->has_ir == 2) + tveeprom_info("has %sradio\n", + tvee->has_radio ? "" : "no "); + else + tveeprom_info("has %sradio, has %sIR remote\n", + tvee->has_radio ? "" : "no ", + tvee->has_ir ? "" : "no "); } EXPORT_SYMBOL(tveeprom_hauppauge_analog); @@ -575,18 +637,18 @@ int tveeprom_read(struct i2c_client *c, unsigned char *eedata, int len) tveeprom_warn("i2c eeprom read error (err=%d)\n", err); return -1; } - if (debug) { - int i; - - tveeprom_info("full 256-byte eeprom dump:\n"); - for (i = 0; i < len; i++) { - if (0 == (i % 16)) - tveeprom_info("%02x:", i); - printk(" %02x", eedata[i]); - if (15 == (i % 16)) - printk("\n"); - } - } + if (debug) { + int i; + + tveeprom_info("full 256-byte eeprom dump:\n"); + for (i = 0; i < len; i++) { + if (0 == (i % 16)) + tveeprom_info("%02x:", i); + printk(" %02x", eedata[i]); + if (15 == (i % 16)) + printk("\n"); + } + } return 0; } EXPORT_SYMBOL(tveeprom_read); diff --git a/include/media/audiochip.h b/include/media/audiochip.h index a7ceee9fc5e..dd1e484e86d 100644 --- a/include/media/audiochip.h +++ b/include/media/audiochip.h @@ -4,6 +4,23 @@ #ifndef AUDIOCHIP_H #define AUDIOCHIP_H +enum audiochip { + AUDIO_CHIP_NONE, + AUDIO_CHIP_UNKNOWN, + /* Provided by video chip */ + AUDIO_CHIP_INTERNAL, + /* Provided by tvaudio.c */ + AUDIO_CHIP_TDA8425, + AUDIO_CHIP_TEA6300, + AUDIO_CHIP_TEA6420, + AUDIO_CHIP_TDA9840, + AUDIO_CHIP_TDA985X, + AUDIO_CHIP_TDA9874, + AUDIO_CHIP_PIC16C54, + /* Provided by msp3400.c */ + AUDIO_CHIP_MSP34XX +}; + /* ---------------------------------------------------------------------- */ /* v4l device was opened in Radio mode */ -- cgit v1.2.3 From 10c2c8b18a9cd29fc3f5faa5ad8e825dcc8b58e6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:36:56 -0800 Subject: [PATCH] v4l: 703: added new card prolink pixelview playtv mpeg2 pv m4900 - Added new card: Prolink PixelView PlayTV MPEG2 PV-M4900 Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.bttv | 1 + drivers/media/video/bttv-cards.c | 198 +++++++++++++++++++++++++++++--- drivers/media/video/bttv.h | 2 + 3 files changed, 185 insertions(+), 16 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index dd7b565be69..1fde0d70da1 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -137,3 +137,4 @@ 136 -> Acorp Y878F [9511:1540] 137 -> Conceptronic CTVFMi v2 138 -> Prolink Pixelview PV-BT878P+ (Rev.2E) +139 -> Prolink PixelView PlayTV MPEG2 PV-M4900 diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 1553d4a1c20..adccbbf63dc 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -319,6 +319,7 @@ struct tvcard bttv_tvcards[] = { .muxsel = { 2, 3, 1, 0}, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_MIRO] = { .name = "MIRO PCTV", @@ -332,6 +333,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_HAUPPAUGE] = { .name = "Hauppauge (bt848)", @@ -345,6 +347,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_STB] = { .name = "STB, Gateway P/N 6000699 (bt848)", @@ -359,6 +362,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = TUNER_PHILIPS_NTSC, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .pll = PLL_28, .has_radio = 1, }, @@ -376,6 +380,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .tuner_type = 4, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_DIAMOND] = { .name = "Diamond DTV2000", @@ -389,6 +394,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_AVERMEDIA] = { .name = "AVerMedia TVPhone", @@ -403,6 +409,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .audio_hook = avermedia_tvphone_audio, .has_remote = 1, }, @@ -418,6 +425,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, /* ---- card 0x08 ---------------------------------- */ @@ -434,6 +442,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_TURBOTV] = { .name = "IMS/IXmicro TurboTV", @@ -448,6 +457,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_TEMIC_PAL, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_HAUPPAUGE878] = { .name = "Hauppauge (bt878)", @@ -462,6 +472,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_MIROPRO] = { .name = "MIRO PCTV pro", @@ -475,6 +486,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, /* ---- card 0x0c ---------------------------------- */ @@ -490,6 +502,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_AVERMEDIA98] = { .name = "AVerMedia TVCapture 98", @@ -505,6 +518,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .audio_hook = avermedia_tv_stereo_audio, }, [BTTV_BOARD_VHX] = { @@ -520,6 +534,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_ZOLTRIX] = { .name = "Zoltrix TV-Max", @@ -533,6 +548,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, /* ---- card 0x10 ---------------------------------- */ @@ -567,6 +583,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .audio_hook = winview_audio, .has_radio = 1, }, @@ -582,6 +599,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_LIFE_FLYKIT] = { .name = "Lifeview FlyVideo II EZ /FlyKit LR38 Bt848 (capture only)", @@ -595,6 +613,7 @@ struct tvcard bttv_tvcards[] = { .no_msp34xx = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, /* ---- card 0x14 ---------------------------------- */ @@ -607,6 +626,7 @@ struct tvcard bttv_tvcards[] = { .muxsel = {2, 3, 1, 1}, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_CONFERENCETV] = { .name = "Lifeview FlyVideo 98/ Lucky Star Image World ConferenceTV LR50", @@ -620,6 +640,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL_I, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_PHOEBE_TVMAS] = { .name = "Askey CPH050/ Phoebe Tv Master + FM", @@ -634,6 +655,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_MODTEC_205] = { .name = "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV, bt878", @@ -649,6 +671,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_ALPS_TSBB5_PAL_I, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, /* ---- card 0x18 ---------------------------------- */ @@ -665,6 +688,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .has_remote = 1, }, [BTTV_BOARD_VOBIS_BOOSTAR] = { @@ -679,6 +703,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .audio_hook = terratv_audio, }, [BTTV_BOARD_HAUPPAUG_WCAM] = { @@ -693,6 +718,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_MAXI] = { .name = "Lifeview FlyVideo 98/ MAXI TV Video PCI2 LR50", @@ -706,6 +732,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_SECAM, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, /* ---- card 0x1c ---------------------------------- */ @@ -721,6 +748,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .audio_hook = terratv_audio, /* GPIO wiring: External 20 pin connector (for Active Radio Upgrade board) @@ -767,6 +795,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .muxsel_hook = PXC200_muxsel, }, @@ -782,6 +811,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_IPROTV] = { .name = "Formac iProTV, Formac ProTV I (bt848)", @@ -795,6 +825,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, /* ---- card 0x20 ---------------------------------- */ @@ -810,6 +841,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .tuner_type = 4, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_TERRATVALUE] = { .name = "Terratec TerraTValue Version Bt878", @@ -824,6 +856,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_WINFAST2000] = { .name = "Leadtek WinFast 2000/ WinFast 2000 XP", @@ -856,6 +889,7 @@ struct tvcard bttv_tvcards[] = { .has_radio = 1, .tuner_type = 5, /* default for now, gpio reads BFFF06 for Pal bg+dk */ .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .audio_hook = winfast2000_audio, .has_remote = 1, }, @@ -871,6 +905,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, /* ---- card 0x24 ---------------------------------- */ @@ -886,6 +921,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .has_radio = 1, }, [BTTV_BOARD_PXELVWPLTVPRO] = { @@ -901,6 +937,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_MAGICTVIEW063] = { .name = "Askey CPH06X TView99", @@ -915,6 +952,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = 1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .has_remote = 1, }, [BTTV_BOARD_PINNACLE] = { @@ -930,6 +968,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, /* ---- card 0x28 ---------------------------------- */ @@ -946,6 +985,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = TUNER_PHILIPS_NTSC, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .pll = PLL_28, .has_radio = 1, }, @@ -962,6 +1002,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .has_radio = 1, .audio_hook = avermedia_tvphone_audio, }, @@ -979,6 +1020,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = 1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_ONAIR_TV] = { .name = "Little OnAir TV", @@ -992,6 +1034,7 @@ struct tvcard bttv_tvcards[] = { .no_msp34xx = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, /* ---- card 0x2c ---------------------------------- */ @@ -1008,6 +1051,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_NONE, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_MATRIX_VISION2] = { .name = "MATRIX-Vision MV-Delta 2", @@ -1022,6 +1066,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_ZOLTRIX_GENIE] = { .name = "Zoltrix Genie TV/FM", @@ -1036,6 +1081,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = 21, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_TERRATVRADIO] = { .name = "Terratec TV/Radio+", @@ -1051,6 +1097,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_35, .tuner_type = 1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .has_radio = 1, }, @@ -1068,6 +1115,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_GVBCTV3PCI] = { .name = "IODATA GV-BCTV3/PCI", @@ -1082,6 +1130,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_ALPS_TSHC6_NTSC, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .audio_hook = gvbctv3pci_audio, }, [BTTV_BOARD_PXELVWPLTVPAK] = { @@ -1098,6 +1147,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL_I, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .has_remote = 1, /* GPIO wiring: (different from Rev.4C !) GPIO17: U4.A0 (first hef4052bt) @@ -1121,6 +1171,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1 /* TUNER_ALPS_TMDH2_NTSC */, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, /* ---- card 0x34 ---------------------------------- */ @@ -1147,6 +1198,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_TVIEW_RDS_FM] = { /* Claas Langbehn , @@ -1163,6 +1215,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .has_radio = 1, }, [BTTV_BOARD_LIFETEC_9415] = { @@ -1186,6 +1239,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_BESTBUY_EASYTV] = { /* Miguel Angel Alvarez @@ -1202,6 +1256,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_TEMIC_PAL, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, /* ---- card 0x38 ---------------------------------- */ @@ -1218,6 +1273,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = 5, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, /* This is the ultimate cheapo capture card * just a BT848A on a small PCB! @@ -1236,6 +1292,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_35, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_ASKEY_CPH060] = { /* Daniel Herrington */ @@ -1251,6 +1308,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_TEMIC_4036FY5_NTSC, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_ASKEY_CPH03X] = { /* Matti Mottus */ @@ -1265,6 +1323,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = 0, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, /* ---- card 0x3c ---------------------------------- */ @@ -1281,6 +1340,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_35, .tuner_type = TUNER_TEMIC_PAL, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_GMV1] = { /* Adrian Cox @@ -1314,6 +1375,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_ATI_TVWONDER] = { /* Lukas Gebauer */ @@ -1328,6 +1390,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, /* ---- card 0x40 ---------------------------------- */ @@ -1345,6 +1408,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_FLYVIDEO2000] = { /* DeeJay */ @@ -1526,6 +1599,7 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .muxsel_hook = rv605_muxsel, }, [BTTV_BOARD_POWERCLR_MTV878] = { @@ -1540,6 +1614,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .pll = PLL_28, .has_radio = 1, }, @@ -1557,6 +1632,7 @@ struct tvcard bttv_tvcards[] = { .audiomux = { 0, 1, 2, 3, 4, 0 }, .tuner_type = TUNER_PHILIPS_NTSC, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .audio_hook = windvr_audio, }, [BTTV_BOARD_GRANDTEC_MULTI] = { @@ -1573,6 +1649,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_KWORLD] = { .name = "Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF", @@ -1594,6 +1671,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = 5, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, /* Samsung TCPA9095PC27A (BG+DK), philips compatible, w/FM, stereo and radio signal strength indicators work fine. */ .has_radio = 1, @@ -1616,6 +1694,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, /* ---- card 0x50 ---------------------------------- */ @@ -1630,6 +1709,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .gpiomask = 7, .audiomux = {7}, @@ -1647,6 +1727,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_NTSC_M, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .audio_hook = gvbctv5pci_audio, .has_radio = 1, }, @@ -1660,6 +1741,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1674,6 +1756,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1690,6 +1773,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1704,6 +1788,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1718,6 +1803,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1732,6 +1818,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1748,6 +1835,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1762,6 +1850,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1776,6 +1865,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1793,6 +1883,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1813,6 +1904,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, /* must avoid, conflicts with the bt860 */ @@ -1825,6 +1917,7 @@ struct tvcard bttv_tvcards[] = { .tuner = -1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .svhs = -1, .gpiomask = 0, .muxsel = { 0, 1, 2, 3 }, @@ -1841,6 +1934,7 @@ struct tvcard bttv_tvcards[] = { .tuner = -1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1863,6 +1957,7 @@ struct tvcard bttv_tvcards[] = { .has_radio = 1, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, /* sound routing: GPIO=0x00,0x01,0x03: mute (?) 0x02: both TV and radio (tuner: FM1216/I) @@ -1885,6 +1980,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = 5, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .pll = 1, }, [BTTV_BOARD_EURESYS_PICOLO] = { @@ -1901,6 +1997,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_PV150] = { /* Luc Van Hoeylandt */ @@ -1917,6 +2014,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_AD_TVK503] = { /* Hiroshi Takekawa */ @@ -1935,6 +2033,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = 2, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .audio_hook = adtvk503_audio, }, @@ -1952,6 +2051,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = 5, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, /* Notes: - card lacks subsystem ID - stereo variant w/ daughter board with tda9874a @0xb0 @@ -1974,6 +2074,7 @@ struct tvcard bttv_tvcards[] = { .no_tda7432 = 1, .tuner_type = 1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .has_radio = 1, .pll = PLL_28, /* Bt878, Bt832, FI1246 tuner; no pci subsystem id @@ -1991,6 +2092,7 @@ struct tvcard bttv_tvcards[] = { .tuner = -1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .svhs = -1, .gpiomask = 0xdf, .muxsel = { 2 }, @@ -2004,6 +2106,7 @@ struct tvcard bttv_tvcards[] = { .svhs = -1, .tuner_type = 4, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .gpiomask2 = 0xff, .muxsel = { 2,2,2,2, 3,3,3,3, 1,1,1,1, 0,0,0,0 }, .muxsel_hook = xguard_muxsel, @@ -2026,6 +2129,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .has_dvb = 1, .no_gpioirq = 1, }, @@ -2044,6 +2148,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_VD009X1_MINIDIN] = { /* M.Klahr@phytec.de */ @@ -2059,6 +2164,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_VD009X1_COMBI] = { .name = "PHYTEC VD-009-X1 Combi (bt878)", @@ -2073,6 +2179,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, /* ---- card 0x6c ---------------------------------- */ @@ -2092,6 +2199,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_VD009_COMBI] = { .name = "PHYTEC VD-009 Combi (bt878)", @@ -2109,6 +2217,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_IVC100] = { .name = "IVC-100", @@ -2117,6 +2226,7 @@ struct tvcard bttv_tvcards[] = { .tuner = -1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .svhs = -1, .gpiomask = 0xdf, .muxsel = { 2, 3, 1, 0 }, @@ -2130,6 +2240,7 @@ struct tvcard bttv_tvcards[] = { .tuner = -1, /* card has no tuner */ .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .svhs = -1, /* card has no svhs */ .needs_tvaudio = 0, .no_msp34xx = 1, @@ -2152,6 +2263,7 @@ struct tvcard bttv_tvcards[] = { .muxsel = { 2, 3, 1, 0}, .tuner_type = TUNER_PHILIPS_ATSC, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .has_dvb = 1, }, [BTTV_BOARD_TWINHAN_DST] = { @@ -2161,6 +2273,7 @@ struct tvcard bttv_tvcards[] = { .no_tda7432 = 1, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .no_video = 1, .has_dvb = 1, }, @@ -2176,6 +2289,7 @@ struct tvcard bttv_tvcards[] = { .no_tda7432 = 1, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .pll = PLL_28, }, [BTTV_BOARD_TEV560] = { @@ -2190,6 +2304,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .pll = PLL_35, }, @@ -2202,6 +2317,7 @@ struct tvcard bttv_tvcards[] = { .svhs = -1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .pll = PLL_28, .muxsel = { 2, 2, 2, 2}, .gpiomask = 0x3F, @@ -2219,6 +2335,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .has_remote = 1, }, [BTTV_BOARD_LMLBT4] = { @@ -2235,6 +2352,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_TEKRAM_M205] = { /* Helmroos Harri */ @@ -2244,6 +2362,7 @@ struct tvcard bttv_tvcards[] = { .tuner = 0, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .svhs = 2, .needs_tvaudio = 0, .gpiomask = 0x68, @@ -2268,6 +2387,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .has_remote = 1, .has_radio = 1, }, @@ -2293,6 +2413,7 @@ struct tvcard bttv_tvcards[] = { .muxsel_hook = picolo_tetra_muxsel,/*Required as it doesn't follow the classic input selection policy*/ .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_SPIRIT_TV] = { /* Spirit TV Tuner from http://spiritmodems.com.au */ @@ -2307,6 +2428,7 @@ struct tvcard bttv_tvcards[] = { .audiomux = { 0x02, 0x00, 0x00, 0x00, 0x00}, .tuner_type = TUNER_TEMIC_PAL, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, }, @@ -2318,6 +2440,7 @@ struct tvcard bttv_tvcards[] = { .tuner = -1, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .muxsel = { 3 , 3 }, .no_msp34xx = 1, .no_tda9875 = 1, @@ -2342,6 +2465,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .has_dvb = 1, .no_gpioirq = 1, .has_remote = 1, @@ -2362,6 +2486,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_MATRIX_VISIONSLC] = { /* andre.schwarz@matrix-vision.de */ @@ -2378,6 +2503,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, /* BTTV_BOARD_APAC_VIEWCOMP */ [BTTV_BOARD_APAC_VIEWCOMP] = { @@ -2395,6 +2521,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .has_remote = 1, /* miniremote works, see ir-kbd-gpio.c */ .has_radio = 1, /* not every card has radio */ }, @@ -2412,6 +2539,7 @@ struct tvcard bttv_tvcards[] = { .has_dvb = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_VGEAR_MYVCD] = { /* Steven */ @@ -2427,6 +2555,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_NTSC_M, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .has_radio = 0, #if 0 .has_remote = 1, @@ -2442,6 +2571,7 @@ struct tvcard bttv_tvcards[] = { .muxsel = { 2, 3, 1, 0}, .tuner_type = TUNER_PHILIPS_NTSC, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .gpiomask = 0x008007, .audiomux = { 0, 0x000001,0,0, 0}, .needs_tvaudio = 1, @@ -2461,6 +2591,7 @@ struct tvcard bttv_tvcards[] = { .no_tda7432 = 1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .muxsel_hook = tibetCS16_muxsel, }, [BTTV_BOARD_KODICOM_4400R] = { @@ -2481,6 +2612,7 @@ struct tvcard bttv_tvcards[] = { .tuner = -1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .svhs = -1, /* GPIO bits 0-9 used for analog switch: * 00 - 03: camera selector @@ -2512,6 +2644,7 @@ struct tvcard bttv_tvcards[] = { .tuner = -1, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .svhs = -1, .gpiomask = 0x010000, .no_gpioirq = 1, @@ -2534,6 +2667,7 @@ struct tvcard bttv_tvcards[] = { .muxsel = { 2, 3, 1, 0}, .tuner_type = -1, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .pll = PLL_28, }, /* ---- card 0x87---------------------------------- */ @@ -2543,6 +2677,7 @@ struct tvcard bttv_tvcards[] = { .tuner = 0, .tuner_type = TUNER_LG_TDVS_H062F, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .video_inputs = 2, .audio_inputs = 1, .svhs = 2, @@ -2569,6 +2704,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_YMEC_TVF66T5_B_DFF, .tuner_addr = 0xc1 >>1, + .radio_addr = 0xc1 >>1, .has_radio = 1, }, /* ---- card 0x89 ---------------------------------- */ @@ -2585,26 +2721,50 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, .has_remote = 1, #if 0 .has_radio = 1, #endif }, + /* ---- card 0x8a ---------------------------------- */ [BTTV_BOARD_PV_BT878P_2E] = { - .name = "Prolink Pixelview PV-BT878P+ (Rev.2E)", - .video_inputs = 5, - .audio_inputs = 1, - .tuner = 0, - .svhs = 3, - .gpiomask = 0x01fe00, - .muxsel = { 2,3,1,1,-1 }, - .digital_mode = DIGITAL_MODE_CAMERA, - .audiomux = { 0x00400, 0x10400, 0x04400, 0x80000, 0x12400, 0x46000 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = TUNER_LG_PAL_FM, - .has_remote = 1, -}}; + .name = "Prolink Pixelview PV-BT878P+ (Rev.2E)", + .video_inputs = 5, + .audio_inputs = 1, + .tuner = 0, + .svhs = 3, + .gpiomask = 0x01fe00, + .muxsel = { 2,3,1,1,-1 }, + .digital_mode = DIGITAL_MODE_CAMERA, + .audiomux = { 0x00400, 0x10400, 0x04400, 0x80000, 0x12400, 0x46000 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_LG_PAL_FM, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .has_remote = 1, + }, + /* ---- card 0x8b ---------------------------------- */ + [BTTV_BOARD_PV_M4900] = { + /* Sérgio Fortier */ + .name = "Prolink PixelView PlayTV MPEG2 PV-M4900", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x3f, + .muxsel = { 2, 3, 1, 1 }, + .audiomux = { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_YMEC_TVF_5533MF, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .has_radio = 1, + .has_remote = 1, + } +}; static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); @@ -2995,7 +3155,7 @@ void __devinit bttv_init_card1(struct bttv *btv) void __devinit bttv_init_card2(struct bttv *btv) { int tda9887; - int addr=ADDR_UNSET; + int addr=ADDR_UNSET, radio_addr=ADDR_UNSET; btv->tuner_type = -1; @@ -3140,6 +3300,9 @@ void __devinit bttv_init_card2(struct bttv *btv) if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr) addr = bttv_tvcards[btv->c.type].tuner_addr; + if (ADDR_UNSET != bttv_tvcards[btv->c.type].radio_addr) + radio_addr = bttv_tvcards[btv->c.type].radio_addr; + if (UNSET != bttv_tvcards[btv->c.type].tuner_type) if(UNSET == btv->tuner_type) btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type; @@ -3152,10 +3315,13 @@ void __devinit bttv_init_card2(struct bttv *btv) if (btv->tuner_type != UNSET) { struct tuner_setup tun_setup; - tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV; + tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; tun_setup.type = btv->tuner_type; tun_setup.addr = addr; + if (addr == radio_addr) + tun_setup.mode_mask = T_RADIO; + bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup); } diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h index 2005ca9383d..a4194e1ea90 100644 --- a/drivers/media/video/bttv.h +++ b/drivers/media/video/bttv.h @@ -159,6 +159,7 @@ #define BTTV_BOARD_ACORP_Y878F 0x88 #define BTTV_BOARD_CONCEPTRONIC_CTVFMI2 0x89 #define BTTV_BOARD_PV_BT878P_2E 0x8a +#define BTTV_BOARD_PV_M4900 0x8b /* i2c address list */ #define I2C_TSA5522 0xc2 @@ -240,6 +241,7 @@ struct tvcard unsigned int tuner_type; unsigned int tuner_addr; + unsigned int radio_addr; unsigned int has_radio; void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set); -- cgit v1.2.3 From afce892f66c196989fe7d938150201d337c553e5 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:36:57 -0800 Subject: [PATCH] v4l: 704: enable support for the ir remote on compro videomate t200 - Enable support for the IR Remote on Compro Videomate T200 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-cards.c | 1 + drivers/media/video/saa7134/saa7134-input.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 3bb0644145b..c59f4d77552 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2842,6 +2842,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_VIDEOMATE_TV_PVR: case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: case SAA7134_BOARD_VIDEOMATE_DVBT_300: + case SAA7134_BOARD_VIDEOMATE_DVBT_200: case SAA7134_BOARD_MANLI_MTV001: case SAA7134_BOARD_MANLI_MTV002: case SAA7134_BOARD_BEHOLD_409FM: diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index f6fe5f889a4..8d211ba2231 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -580,6 +580,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) polling = 50; // ms break; case SAA7134_BOARD_VIDEOMATE_DVBT_300: + case SAA7134_BOARD_VIDEOMATE_DVBT_200: ir_codes = videomate_tv_pvr_codes; mask_keycode = 0x003F00; mask_keyup = 0x040000; -- cgit v1.2.3 From 0bcc37c328ac66ede45a6672f85795eee0b05b87 Mon Sep 17 00:00:00 2001 From: Alexander Wold Date: Tue, 8 Nov 2005 21:36:58 -0800 Subject: [PATCH] v4l: 705: added kworld vstream expertdvd - Added Kworld Vstream ExpertDVD. Signed-off-by: Alexander Wold Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/cx88-cards.c | 20 ++++++++++++++++++++ drivers/media/video/cx88/cx88.h | 1 + 2 files changed, 21 insertions(+) diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 5a85802047f..888d25d4841 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -803,6 +803,26 @@ struct cx88_board cx88_boards[] = { .gpio0 = 0x0000cdf3, }, }, + [CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD] = { + /* Alexander Wold */ + .name = "Kworld V-Stream Xpert DVD", + .tuner_type = UNSET, + .input = {{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x03000000, + .gpio1 = 0x01000000, + .gpio2 = 0x02000000, + .gpio3 = 0x00100000, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x03000000, + .gpio1 = 0x01000000, + .gpio2 = 0x02000000, + .gpio3 = 0x00100000, + }}, + }, }; const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index bd27b56ace2..9b629221e79 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -175,6 +175,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1 30 #define CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD 31 #define CX88_BOARD_AVERMEDIA_ULTRATV_MC_550 32 +#define CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD 33 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- cgit v1.2.3 From 7b3c6d659fc392cfd80e57840c10ccd4c6ab62c5 Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:36:59 -0800 Subject: [PATCH] v4l: 706: reindent cx88 tvaudio c to keep coding style - Reindent cx88-tvaudio.c to keep coding style. Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/cx88-tvaudio.c | 963 ++++++++++++++++---------------- 1 file changed, 484 insertions(+), 479 deletions(-) diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index b6431cb78a5..4ca1128bc76 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c @@ -57,39 +57,38 @@ #include "cx88.h" static unsigned int audio_debug = 0; -module_param(audio_debug,int,0644); -MODULE_PARM_DESC(audio_debug,"enable debug messages [audio]"); +module_param(audio_debug, int, 0644); +MODULE_PARM_DESC(audio_debug, "enable debug messages [audio]"); #define dprintk(fmt, arg...) if (audio_debug) \ printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg) /* ----------------------------------------------------------- */ -static char *aud_ctl_names[64] = -{ - [ EN_BTSC_FORCE_MONO ] = "BTSC_FORCE_MONO", - [ EN_BTSC_FORCE_STEREO ] = "BTSC_FORCE_STEREO", - [ EN_BTSC_FORCE_SAP ] = "BTSC_FORCE_SAP", - [ EN_BTSC_AUTO_STEREO ] = "BTSC_AUTO_STEREO", - [ EN_BTSC_AUTO_SAP ] = "BTSC_AUTO_SAP", - [ EN_A2_FORCE_MONO1 ] = "A2_FORCE_MONO1", - [ EN_A2_FORCE_MONO2 ] = "A2_FORCE_MONO2", - [ EN_A2_FORCE_STEREO ] = "A2_FORCE_STEREO", - [ EN_A2_AUTO_MONO2 ] = "A2_AUTO_MONO2", - [ EN_A2_AUTO_STEREO ] = "A2_AUTO_STEREO", - [ EN_EIAJ_FORCE_MONO1 ] = "EIAJ_FORCE_MONO1", - [ EN_EIAJ_FORCE_MONO2 ] = "EIAJ_FORCE_MONO2", - [ EN_EIAJ_FORCE_STEREO ] = "EIAJ_FORCE_STEREO", - [ EN_EIAJ_AUTO_MONO2 ] = "EIAJ_AUTO_MONO2", - [ EN_EIAJ_AUTO_STEREO ] = "EIAJ_AUTO_STEREO", - [ EN_NICAM_FORCE_MONO1 ] = "NICAM_FORCE_MONO1", - [ EN_NICAM_FORCE_MONO2 ] = "NICAM_FORCE_MONO2", - [ EN_NICAM_FORCE_STEREO ] = "NICAM_FORCE_STEREO", - [ EN_NICAM_AUTO_MONO2 ] = "NICAM_AUTO_MONO2", - [ EN_NICAM_AUTO_STEREO ] = "NICAM_AUTO_STEREO", - [ EN_FMRADIO_FORCE_MONO ] = "FMRADIO_FORCE_MONO", - [ EN_FMRADIO_FORCE_STEREO ] = "FMRADIO_FORCE_STEREO", - [ EN_FMRADIO_AUTO_STEREO ] = "FMRADIO_AUTO_STEREO", +static char *aud_ctl_names[64] = { + [EN_BTSC_FORCE_MONO] = "BTSC_FORCE_MONO", + [EN_BTSC_FORCE_STEREO] = "BTSC_FORCE_STEREO", + [EN_BTSC_FORCE_SAP] = "BTSC_FORCE_SAP", + [EN_BTSC_AUTO_STEREO] = "BTSC_AUTO_STEREO", + [EN_BTSC_AUTO_SAP] = "BTSC_AUTO_SAP", + [EN_A2_FORCE_MONO1] = "A2_FORCE_MONO1", + [EN_A2_FORCE_MONO2] = "A2_FORCE_MONO2", + [EN_A2_FORCE_STEREO] = "A2_FORCE_STEREO", + [EN_A2_AUTO_MONO2] = "A2_AUTO_MONO2", + [EN_A2_AUTO_STEREO] = "A2_AUTO_STEREO", + [EN_EIAJ_FORCE_MONO1] = "EIAJ_FORCE_MONO1", + [EN_EIAJ_FORCE_MONO2] = "EIAJ_FORCE_MONO2", + [EN_EIAJ_FORCE_STEREO] = "EIAJ_FORCE_STEREO", + [EN_EIAJ_AUTO_MONO2] = "EIAJ_AUTO_MONO2", + [EN_EIAJ_AUTO_STEREO] = "EIAJ_AUTO_STEREO", + [EN_NICAM_FORCE_MONO1] = "NICAM_FORCE_MONO1", + [EN_NICAM_FORCE_MONO2] = "NICAM_FORCE_MONO2", + [EN_NICAM_FORCE_STEREO] = "NICAM_FORCE_STEREO", + [EN_NICAM_AUTO_MONO2] = "NICAM_AUTO_MONO2", + [EN_NICAM_AUTO_STEREO] = "NICAM_AUTO_STEREO", + [EN_FMRADIO_FORCE_MONO] = "FMRADIO_FORCE_MONO", + [EN_FMRADIO_FORCE_STEREO] = "FMRADIO_FORCE_STEREO", + [EN_FMRADIO_AUTO_STEREO] = "FMRADIO_AUTO_STEREO", }; struct rlist { @@ -97,8 +96,7 @@ struct rlist { u32 val; }; -static void set_audio_registers(struct cx88_core *core, - const struct rlist *l) +static void set_audio_registers(struct cx88_core *core, const struct rlist *l) { int i; @@ -119,17 +117,16 @@ static void set_audio_registers(struct cx88_core *core, } } -static void set_audio_start(struct cx88_core *core, - u32 mode) +static void set_audio_start(struct cx88_core *core, u32 mode) { // mute - cx_write(AUD_VOL_CTL, (1 << 6)); + cx_write(AUD_VOL_CTL, (1 << 6)); // start programming - cx_write(AUD_CTL, 0x0000); - cx_write(AUD_INIT, mode); - cx_write(AUD_INIT_LD, 0x0001); - cx_write(AUD_SOFT_RESET, 0x0001); + cx_write(AUD_CTL, 0x0000); + cx_write(AUD_INIT, mode); + cx_write(AUD_INIT_LD, 0x0001); + cx_write(AUD_SOFT_RESET, 0x0001); } static void set_audio_finish(struct cx88_core *core, u32 ctl) @@ -148,8 +145,8 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl) cx_write(AUD_I2SCNTL, 0); //cx_write(AUD_APB_IN_RATE_ADJ, 0); } else { - ctl |= EN_DAC_ENABLE; - cx_write(AUD_CTL, ctl); + ctl |= EN_DAC_ENABLE; + cx_write(AUD_CTL, ctl); } /* finish programming */ @@ -162,110 +159,111 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl) /* ----------------------------------------------------------- */ -static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap, u32 mode) +static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap, + u32 mode) { static const struct rlist btsc[] = { - { AUD_AFE_12DB_EN, 0x00000001 }, - { AUD_OUT1_SEL, 0x00000013 }, - { AUD_OUT1_SHIFT, 0x00000000 }, - { AUD_POLY0_DDS_CONSTANT, 0x0012010c }, - { AUD_DMD_RA_DDS, 0x00c3e7aa }, - { AUD_DBX_IN_GAIN, 0x00004734 }, - { AUD_DBX_WBE_GAIN, 0x00004640 }, - { AUD_DBX_SE_GAIN, 0x00008d31 }, - { AUD_DCOC_0_SRC, 0x0000001a }, - { AUD_IIR1_4_SEL, 0x00000021 }, - { AUD_DCOC_PASS_IN, 0x00000003 }, - { AUD_DCOC_0_SHIFT_IN0, 0x0000000a }, - { AUD_DCOC_0_SHIFT_IN1, 0x00000008 }, - { AUD_DCOC_1_SHIFT_IN0, 0x0000000a }, - { AUD_DCOC_1_SHIFT_IN1, 0x00000008 }, - { AUD_DN0_FREQ, 0x0000283b }, - { AUD_DN2_SRC_SEL, 0x00000008 }, - { AUD_DN2_FREQ, 0x00003000 }, - { AUD_DN2_AFC, 0x00000002 }, - { AUD_DN2_SHFT, 0x00000000 }, - { AUD_IIR2_2_SEL, 0x00000020 }, - { AUD_IIR2_2_SHIFT, 0x00000000 }, - { AUD_IIR2_3_SEL, 0x0000001f }, - { AUD_IIR2_3_SHIFT, 0x00000000 }, - { AUD_CRDC1_SRC_SEL, 0x000003ce }, - { AUD_CRDC1_SHIFT, 0x00000000 }, - { AUD_CORDIC_SHIFT_1, 0x00000007 }, - { AUD_DCOC_1_SRC, 0x0000001b }, - { AUD_DCOC1_SHIFT, 0x00000000 }, - { AUD_RDSI_SEL, 0x00000008 }, - { AUD_RDSQ_SEL, 0x00000008 }, - { AUD_RDSI_SHIFT, 0x00000000 }, - { AUD_RDSQ_SHIFT, 0x00000000 }, - { AUD_POLYPH80SCALEFAC, 0x00000003 }, + {AUD_AFE_12DB_EN, 0x00000001}, + {AUD_OUT1_SEL, 0x00000013}, + {AUD_OUT1_SHIFT, 0x00000000}, + {AUD_POLY0_DDS_CONSTANT, 0x0012010c}, + {AUD_DMD_RA_DDS, 0x00c3e7aa}, + {AUD_DBX_IN_GAIN, 0x00004734}, + {AUD_DBX_WBE_GAIN, 0x00004640}, + {AUD_DBX_SE_GAIN, 0x00008d31}, + {AUD_DCOC_0_SRC, 0x0000001a}, + {AUD_IIR1_4_SEL, 0x00000021}, + {AUD_DCOC_PASS_IN, 0x00000003}, + {AUD_DCOC_0_SHIFT_IN0, 0x0000000a}, + {AUD_DCOC_0_SHIFT_IN1, 0x00000008}, + {AUD_DCOC_1_SHIFT_IN0, 0x0000000a}, + {AUD_DCOC_1_SHIFT_IN1, 0x00000008}, + {AUD_DN0_FREQ, 0x0000283b}, + {AUD_DN2_SRC_SEL, 0x00000008}, + {AUD_DN2_FREQ, 0x00003000}, + {AUD_DN2_AFC, 0x00000002}, + {AUD_DN2_SHFT, 0x00000000}, + {AUD_IIR2_2_SEL, 0x00000020}, + {AUD_IIR2_2_SHIFT, 0x00000000}, + {AUD_IIR2_3_SEL, 0x0000001f}, + {AUD_IIR2_3_SHIFT, 0x00000000}, + {AUD_CRDC1_SRC_SEL, 0x000003ce}, + {AUD_CRDC1_SHIFT, 0x00000000}, + {AUD_CORDIC_SHIFT_1, 0x00000007}, + {AUD_DCOC_1_SRC, 0x0000001b}, + {AUD_DCOC1_SHIFT, 0x00000000}, + {AUD_RDSI_SEL, 0x00000008}, + {AUD_RDSQ_SEL, 0x00000008}, + {AUD_RDSI_SHIFT, 0x00000000}, + {AUD_RDSQ_SHIFT, 0x00000000}, + {AUD_POLYPH80SCALEFAC, 0x00000003}, { /* end of list */ }, }; static const struct rlist btsc_sap[] = { - { AUD_AFE_12DB_EN, 0x00000001 }, - { AUD_DBX_IN_GAIN, 0x00007200 }, - { AUD_DBX_WBE_GAIN, 0x00006200 }, - { AUD_DBX_SE_GAIN, 0x00006200 }, - { AUD_IIR1_1_SEL, 0x00000000 }, - { AUD_IIR1_3_SEL, 0x00000001 }, - { AUD_DN1_SRC_SEL, 0x00000007 }, - { AUD_IIR1_4_SHIFT, 0x00000006 }, - { AUD_IIR2_1_SHIFT, 0x00000000 }, - { AUD_IIR2_2_SHIFT, 0x00000000 }, - { AUD_IIR3_0_SHIFT, 0x00000000 }, - { AUD_IIR3_1_SHIFT, 0x00000000 }, - { AUD_IIR3_0_SEL, 0x0000000d }, - { AUD_IIR3_1_SEL, 0x0000000e }, - { AUD_DEEMPH1_SRC_SEL, 0x00000014 }, - { AUD_DEEMPH1_SHIFT, 0x00000000 }, - { AUD_DEEMPH1_G0, 0x00004000 }, - { AUD_DEEMPH1_A0, 0x00000000 }, - { AUD_DEEMPH1_B0, 0x00000000 }, - { AUD_DEEMPH1_A1, 0x00000000 }, - { AUD_DEEMPH1_B1, 0x00000000 }, - { AUD_OUT0_SEL, 0x0000003f }, - { AUD_OUT1_SEL, 0x0000003f }, - { AUD_DN1_AFC, 0x00000002 }, - { AUD_DCOC_0_SHIFT_IN0, 0x0000000a }, - { AUD_DCOC_0_SHIFT_IN1, 0x00000008 }, - { AUD_DCOC_1_SHIFT_IN0, 0x0000000a }, - { AUD_DCOC_1_SHIFT_IN1, 0x00000008 }, - { AUD_IIR1_0_SEL, 0x0000001d }, - { AUD_IIR1_2_SEL, 0x0000001e }, - { AUD_IIR2_1_SEL, 0x00000002 }, - { AUD_IIR2_2_SEL, 0x00000004 }, - { AUD_IIR3_2_SEL, 0x0000000f }, - { AUD_DCOC2_SHIFT, 0x00000001 }, - { AUD_IIR3_2_SHIFT, 0x00000001 }, - { AUD_DEEMPH0_SRC_SEL, 0x00000014 }, - { AUD_CORDIC_SHIFT_1, 0x00000006 }, - { AUD_POLY0_DDS_CONSTANT, 0x000e4db2 }, - { AUD_DMD_RA_DDS, 0x00f696e6 }, - { AUD_IIR2_3_SEL, 0x00000025 }, - { AUD_IIR1_4_SEL, 0x00000021 }, - { AUD_DN1_FREQ, 0x0000c965 }, - { AUD_DCOC_PASS_IN, 0x00000003 }, - { AUD_DCOC_0_SRC, 0x0000001a }, - { AUD_DCOC_1_SRC, 0x0000001b }, - { AUD_DCOC1_SHIFT, 0x00000000 }, - { AUD_RDSI_SEL, 0x00000009 }, - { AUD_RDSQ_SEL, 0x00000009 }, - { AUD_RDSI_SHIFT, 0x00000000 }, - { AUD_RDSQ_SHIFT, 0x00000000 }, - { AUD_POLYPH80SCALEFAC, 0x00000003 }, + {AUD_AFE_12DB_EN, 0x00000001}, + {AUD_DBX_IN_GAIN, 0x00007200}, + {AUD_DBX_WBE_GAIN, 0x00006200}, + {AUD_DBX_SE_GAIN, 0x00006200}, + {AUD_IIR1_1_SEL, 0x00000000}, + {AUD_IIR1_3_SEL, 0x00000001}, + {AUD_DN1_SRC_SEL, 0x00000007}, + {AUD_IIR1_4_SHIFT, 0x00000006}, + {AUD_IIR2_1_SHIFT, 0x00000000}, + {AUD_IIR2_2_SHIFT, 0x00000000}, + {AUD_IIR3_0_SHIFT, 0x00000000}, + {AUD_IIR3_1_SHIFT, 0x00000000}, + {AUD_IIR3_0_SEL, 0x0000000d}, + {AUD_IIR3_1_SEL, 0x0000000e}, + {AUD_DEEMPH1_SRC_SEL, 0x00000014}, + {AUD_DEEMPH1_SHIFT, 0x00000000}, + {AUD_DEEMPH1_G0, 0x00004000}, + {AUD_DEEMPH1_A0, 0x00000000}, + {AUD_DEEMPH1_B0, 0x00000000}, + {AUD_DEEMPH1_A1, 0x00000000}, + {AUD_DEEMPH1_B1, 0x00000000}, + {AUD_OUT0_SEL, 0x0000003f}, + {AUD_OUT1_SEL, 0x0000003f}, + {AUD_DN1_AFC, 0x00000002}, + {AUD_DCOC_0_SHIFT_IN0, 0x0000000a}, + {AUD_DCOC_0_SHIFT_IN1, 0x00000008}, + {AUD_DCOC_1_SHIFT_IN0, 0x0000000a}, + {AUD_DCOC_1_SHIFT_IN1, 0x00000008}, + {AUD_IIR1_0_SEL, 0x0000001d}, + {AUD_IIR1_2_SEL, 0x0000001e}, + {AUD_IIR2_1_SEL, 0x00000002}, + {AUD_IIR2_2_SEL, 0x00000004}, + {AUD_IIR3_2_SEL, 0x0000000f}, + {AUD_DCOC2_SHIFT, 0x00000001}, + {AUD_IIR3_2_SHIFT, 0x00000001}, + {AUD_DEEMPH0_SRC_SEL, 0x00000014}, + {AUD_CORDIC_SHIFT_1, 0x00000006}, + {AUD_POLY0_DDS_CONSTANT, 0x000e4db2}, + {AUD_DMD_RA_DDS, 0x00f696e6}, + {AUD_IIR2_3_SEL, 0x00000025}, + {AUD_IIR1_4_SEL, 0x00000021}, + {AUD_DN1_FREQ, 0x0000c965}, + {AUD_DCOC_PASS_IN, 0x00000003}, + {AUD_DCOC_0_SRC, 0x0000001a}, + {AUD_DCOC_1_SRC, 0x0000001b}, + {AUD_DCOC1_SHIFT, 0x00000000}, + {AUD_RDSI_SEL, 0x00000009}, + {AUD_RDSQ_SEL, 0x00000009}, + {AUD_RDSI_SHIFT, 0x00000000}, + {AUD_RDSQ_SHIFT, 0x00000000}, + {AUD_POLYPH80SCALEFAC, 0x00000003}, { /* end of list */ }, }; mode |= EN_FMRADIO_EN_RDS; if (sap) { - dprintk("%s SAP (status: unknown)\n",__FUNCTION__); - set_audio_start(core, SEL_SAP); + dprintk("%s SAP (status: unknown)\n", __FUNCTION__); + set_audio_start(core, SEL_SAP); set_audio_registers(core, btsc_sap); set_audio_finish(core, mode); } else { - dprintk("%s (status: known-good)\n",__FUNCTION__); - set_audio_start(core, SEL_BTSC); + dprintk("%s (status: known-good)\n", __FUNCTION__); + set_audio_start(core, SEL_BTSC); set_audio_registers(core, btsc); set_audio_finish(core, mode); } @@ -274,87 +272,87 @@ static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap, u3 static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode) { static const struct rlist nicam_l[] = { - { AUD_AFE_12DB_EN, 0x00000001}, - { AUD_RATE_ADJ1, 0x00000060 }, - { AUD_RATE_ADJ2, 0x000000F9 }, - { AUD_RATE_ADJ3, 0x000001CC }, - { AUD_RATE_ADJ4, 0x000002B3 }, - { AUD_RATE_ADJ5, 0x00000726 }, - { AUD_DEEMPHDENOM1_R, 0x0000F3D0 }, - { AUD_DEEMPHDENOM2_R, 0x00000000 }, - { AUD_ERRLOGPERIOD_R, 0x00000064 }, - { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF }, - { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F }, - { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F }, - { AUD_POLYPH80SCALEFAC, 0x00000003 }, - { AUD_DMD_RA_DDS, 0x00C00000 }, - { AUD_PLL_INT, 0x0000001E }, - { AUD_PLL_DDS, 0x00000000 }, - { AUD_PLL_FRAC, 0x0000E542 }, - { AUD_START_TIMER, 0x00000000 }, - { AUD_DEEMPHNUMER1_R, 0x000353DE }, - { AUD_DEEMPHNUMER2_R, 0x000001B1 }, - { AUD_PDF_DDS_CNST_BYTE2, 0x06 }, - { AUD_PDF_DDS_CNST_BYTE1, 0x82 }, - { AUD_PDF_DDS_CNST_BYTE0, 0x12 }, - { AUD_QAM_MODE, 0x05 }, - { AUD_PHACC_FREQ_8MSB, 0x34 }, - { AUD_PHACC_FREQ_8LSB, 0x4C }, - { AUD_DEEMPHGAIN_R, 0x00006680 }, - { AUD_RATE_THRES_DMD, 0x000000C0 }, - { /* end of list */ }, - } ; + {AUD_AFE_12DB_EN, 0x00000001}, + {AUD_RATE_ADJ1, 0x00000060}, + {AUD_RATE_ADJ2, 0x000000F9}, + {AUD_RATE_ADJ3, 0x000001CC}, + {AUD_RATE_ADJ4, 0x000002B3}, + {AUD_RATE_ADJ5, 0x00000726}, + {AUD_DEEMPHDENOM1_R, 0x0000F3D0}, + {AUD_DEEMPHDENOM2_R, 0x00000000}, + {AUD_ERRLOGPERIOD_R, 0x00000064}, + {AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF}, + {AUD_ERRINTRPTTHSHLD2_R, 0x0000001F}, + {AUD_ERRINTRPTTHSHLD3_R, 0x0000000F}, + {AUD_POLYPH80SCALEFAC, 0x00000003}, + {AUD_DMD_RA_DDS, 0x00C00000}, + {AUD_PLL_INT, 0x0000001E}, + {AUD_PLL_DDS, 0x00000000}, + {AUD_PLL_FRAC, 0x0000E542}, + {AUD_START_TIMER, 0x00000000}, + {AUD_DEEMPHNUMER1_R, 0x000353DE}, + {AUD_DEEMPHNUMER2_R, 0x000001B1}, + {AUD_PDF_DDS_CNST_BYTE2, 0x06}, + {AUD_PDF_DDS_CNST_BYTE1, 0x82}, + {AUD_PDF_DDS_CNST_BYTE0, 0x12}, + {AUD_QAM_MODE, 0x05}, + {AUD_PHACC_FREQ_8MSB, 0x34}, + {AUD_PHACC_FREQ_8LSB, 0x4C}, + {AUD_DEEMPHGAIN_R, 0x00006680}, + {AUD_RATE_THRES_DMD, 0x000000C0}, + { /* end of list */ }, + }; static const struct rlist nicam_bgdki_common[] = { - { AUD_AFE_12DB_EN, 0x00000001}, - { AUD_RATE_ADJ1, 0x00000010 }, - { AUD_RATE_ADJ2, 0x00000040 }, - { AUD_RATE_ADJ3, 0x00000100 }, - { AUD_RATE_ADJ4, 0x00000400 }, - { AUD_RATE_ADJ5, 0x00001000 }, - //{ AUD_DMD_RA_DDS, 0x00c0d5ce }, - { AUD_ERRLOGPERIOD_R, 0x00000fff}, - { AUD_ERRINTRPTTHSHLD1_R, 0x000003ff}, - { AUD_ERRINTRPTTHSHLD2_R, 0x000000ff}, - { AUD_ERRINTRPTTHSHLD3_R, 0x0000003f}, - { AUD_POLYPH80SCALEFAC, 0x00000003}, - { AUD_DEEMPHGAIN_R, 0x000023c2}, - { AUD_DEEMPHNUMER1_R, 0x0002a7bc}, - { AUD_DEEMPHNUMER2_R, 0x0003023e}, - { AUD_DEEMPHDENOM1_R, 0x0000f3d0}, - { AUD_DEEMPHDENOM2_R, 0x00000000}, - { AUD_PDF_DDS_CNST_BYTE1, 0x82 }, - { AUD_PDF_DDS_CNST_BYTE0, 0x16 }, - { AUD_QAM_MODE, 0x05 }, - { /* end of list */ }, + {AUD_AFE_12DB_EN, 0x00000001}, + {AUD_RATE_ADJ1, 0x00000010}, + {AUD_RATE_ADJ2, 0x00000040}, + {AUD_RATE_ADJ3, 0x00000100}, + {AUD_RATE_ADJ4, 0x00000400}, + {AUD_RATE_ADJ5, 0x00001000}, + //{ AUD_DMD_RA_DDS, 0x00c0d5ce }, + {AUD_ERRLOGPERIOD_R, 0x00000fff}, + {AUD_ERRINTRPTTHSHLD1_R, 0x000003ff}, + {AUD_ERRINTRPTTHSHLD2_R, 0x000000ff}, + {AUD_ERRINTRPTTHSHLD3_R, 0x0000003f}, + {AUD_POLYPH80SCALEFAC, 0x00000003}, + {AUD_DEEMPHGAIN_R, 0x000023c2}, + {AUD_DEEMPHNUMER1_R, 0x0002a7bc}, + {AUD_DEEMPHNUMER2_R, 0x0003023e}, + {AUD_DEEMPHDENOM1_R, 0x0000f3d0}, + {AUD_DEEMPHDENOM2_R, 0x00000000}, + {AUD_PDF_DDS_CNST_BYTE1, 0x82}, + {AUD_PDF_DDS_CNST_BYTE0, 0x16}, + {AUD_QAM_MODE, 0x05}, + { /* end of list */ }, }; static const struct rlist nicam_i[] = { - { AUD_PDF_DDS_CNST_BYTE0, 0x12 }, - { AUD_PHACC_FREQ_8MSB, 0x3a }, - { AUD_PHACC_FREQ_8LSB, 0x93 }, - { /* end of list */ }, + {AUD_PDF_DDS_CNST_BYTE0, 0x12}, + {AUD_PHACC_FREQ_8MSB, 0x3a}, + {AUD_PHACC_FREQ_8LSB, 0x93}, + { /* end of list */ }, }; static const struct rlist nicam_default[] = { - { AUD_PDF_DDS_CNST_BYTE0, 0x16 }, - { AUD_PHACC_FREQ_8MSB, 0x34 }, - { AUD_PHACC_FREQ_8LSB, 0x4c }, - { /* end of list */ }, + {AUD_PDF_DDS_CNST_BYTE0, 0x16}, + {AUD_PHACC_FREQ_8MSB, 0x34}, + {AUD_PHACC_FREQ_8LSB, 0x4c}, + { /* end of list */ }, }; switch (core->tvaudio) { case WW_L: - dprintk("%s SECAM-L NICAM (status: devel)\n",__FUNCTION__); + dprintk("%s SECAM-L NICAM (status: devel)\n", __FUNCTION__); set_audio_registers(core, nicam_l); break; case WW_I: - dprintk("%s PAL-I NICAM (status: devel)\n",__FUNCTION__); + dprintk("%s PAL-I NICAM (status: devel)\n", __FUNCTION__); set_audio_registers(core, nicam_bgdki_common); set_audio_registers(core, nicam_i); break; default: - dprintk("%s PAL-BGDK NICAM (status: unknown)\n",__FUNCTION__); + dprintk("%s PAL-BGDK NICAM (status: unknown)\n", __FUNCTION__); set_audio_registers(core, nicam_bgdki_common); set_audio_registers(core, nicam_default); break; @@ -367,255 +365,255 @@ static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode) static void set_audio_standard_A2(struct cx88_core *core, u32 mode) { static const struct rlist a2_bgdk_common[] = { - {AUD_ERRLOGPERIOD_R, 0x00000064}, - {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff}, - {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f}, - {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f}, - {AUD_PDF_DDS_CNST_BYTE2, 0x06}, - {AUD_PDF_DDS_CNST_BYTE1, 0x82}, - {AUD_PDF_DDS_CNST_BYTE0, 0x12}, - {AUD_QAM_MODE, 0x05}, - {AUD_PHACC_FREQ_8MSB, 0x34}, - {AUD_PHACC_FREQ_8LSB, 0x4c}, - {AUD_RATE_ADJ1, 0x00000100}, - {AUD_RATE_ADJ2, 0x00000200}, - {AUD_RATE_ADJ3, 0x00000300}, - {AUD_RATE_ADJ4, 0x00000400}, - {AUD_RATE_ADJ5, 0x00000500}, - {AUD_THR_FR, 0x00000000}, - {AAGC_HYST, 0x0000001a}, - {AUD_PILOT_BQD_1_K0, 0x0000755b}, - {AUD_PILOT_BQD_1_K1, 0x00551340}, - {AUD_PILOT_BQD_1_K2, 0x006d30be}, - {AUD_PILOT_BQD_1_K3, 0xffd394af}, - {AUD_PILOT_BQD_1_K4, 0x00400000}, - {AUD_PILOT_BQD_2_K0, 0x00040000}, - {AUD_PILOT_BQD_2_K1, 0x002a4841}, - {AUD_PILOT_BQD_2_K2, 0x00400000}, - {AUD_PILOT_BQD_2_K3, 0x00000000}, - {AUD_PILOT_BQD_2_K4, 0x00000000}, - {AUD_MODE_CHG_TIMER, 0x00000040}, - {AUD_AFE_12DB_EN, 0x00000001}, - {AUD_CORDIC_SHIFT_0, 0x00000007}, - {AUD_CORDIC_SHIFT_1, 0x00000007}, - {AUD_DEEMPH0_G0, 0x00000380}, - {AUD_DEEMPH1_G0, 0x00000380}, - {AUD_DCOC_0_SRC, 0x0000001a}, - {AUD_DCOC0_SHIFT, 0x00000000}, - {AUD_DCOC_0_SHIFT_IN0, 0x0000000a}, - {AUD_DCOC_0_SHIFT_IN1, 0x00000008}, - {AUD_DCOC_PASS_IN, 0x00000003}, - {AUD_IIR3_0_SEL, 0x00000021}, - {AUD_DN2_AFC, 0x00000002}, - {AUD_DCOC_1_SRC, 0x0000001b}, - {AUD_DCOC1_SHIFT, 0x00000000}, - {AUD_DCOC_1_SHIFT_IN0, 0x0000000a}, - {AUD_DCOC_1_SHIFT_IN1, 0x00000008}, - {AUD_IIR3_1_SEL, 0x00000023}, - {AUD_RDSI_SEL, 0x00000017}, - {AUD_RDSI_SHIFT, 0x00000000}, - {AUD_RDSQ_SEL, 0x00000017}, - {AUD_RDSQ_SHIFT, 0x00000000}, - {AUD_PLL_INT, 0x0000001e}, - {AUD_PLL_DDS, 0x00000000}, - {AUD_PLL_FRAC, 0x0000e542}, - {AUD_POLYPH80SCALEFAC, 0x00000001}, - {AUD_START_TIMER, 0x00000000}, - { /* end of list */ }, + {AUD_ERRLOGPERIOD_R, 0x00000064}, + {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff}, + {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f}, + {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f}, + {AUD_PDF_DDS_CNST_BYTE2, 0x06}, + {AUD_PDF_DDS_CNST_BYTE1, 0x82}, + {AUD_PDF_DDS_CNST_BYTE0, 0x12}, + {AUD_QAM_MODE, 0x05}, + {AUD_PHACC_FREQ_8MSB, 0x34}, + {AUD_PHACC_FREQ_8LSB, 0x4c}, + {AUD_RATE_ADJ1, 0x00000100}, + {AUD_RATE_ADJ2, 0x00000200}, + {AUD_RATE_ADJ3, 0x00000300}, + {AUD_RATE_ADJ4, 0x00000400}, + {AUD_RATE_ADJ5, 0x00000500}, + {AUD_THR_FR, 0x00000000}, + {AAGC_HYST, 0x0000001a}, + {AUD_PILOT_BQD_1_K0, 0x0000755b}, + {AUD_PILOT_BQD_1_K1, 0x00551340}, + {AUD_PILOT_BQD_1_K2, 0x006d30be}, + {AUD_PILOT_BQD_1_K3, 0xffd394af}, + {AUD_PILOT_BQD_1_K4, 0x00400000}, + {AUD_PILOT_BQD_2_K0, 0x00040000}, + {AUD_PILOT_BQD_2_K1, 0x002a4841}, + {AUD_PILOT_BQD_2_K2, 0x00400000}, + {AUD_PILOT_BQD_2_K3, 0x00000000}, + {AUD_PILOT_BQD_2_K4, 0x00000000}, + {AUD_MODE_CHG_TIMER, 0x00000040}, + {AUD_AFE_12DB_EN, 0x00000001}, + {AUD_CORDIC_SHIFT_0, 0x00000007}, + {AUD_CORDIC_SHIFT_1, 0x00000007}, + {AUD_DEEMPH0_G0, 0x00000380}, + {AUD_DEEMPH1_G0, 0x00000380}, + {AUD_DCOC_0_SRC, 0x0000001a}, + {AUD_DCOC0_SHIFT, 0x00000000}, + {AUD_DCOC_0_SHIFT_IN0, 0x0000000a}, + {AUD_DCOC_0_SHIFT_IN1, 0x00000008}, + {AUD_DCOC_PASS_IN, 0x00000003}, + {AUD_IIR3_0_SEL, 0x00000021}, + {AUD_DN2_AFC, 0x00000002}, + {AUD_DCOC_1_SRC, 0x0000001b}, + {AUD_DCOC1_SHIFT, 0x00000000}, + {AUD_DCOC_1_SHIFT_IN0, 0x0000000a}, + {AUD_DCOC_1_SHIFT_IN1, 0x00000008}, + {AUD_IIR3_1_SEL, 0x00000023}, + {AUD_RDSI_SEL, 0x00000017}, + {AUD_RDSI_SHIFT, 0x00000000}, + {AUD_RDSQ_SEL, 0x00000017}, + {AUD_RDSQ_SHIFT, 0x00000000}, + {AUD_PLL_INT, 0x0000001e}, + {AUD_PLL_DDS, 0x00000000}, + {AUD_PLL_FRAC, 0x0000e542}, + {AUD_POLYPH80SCALEFAC, 0x00000001}, + {AUD_START_TIMER, 0x00000000}, + { /* end of list */ }, }; static const struct rlist a2_bg[] = { - {AUD_DMD_RA_DDS, 0x002a4f2f}, - {AUD_C1_UP_THR, 0x00007000}, - {AUD_C1_LO_THR, 0x00005400}, - {AUD_C2_UP_THR, 0x00005400}, - {AUD_C2_LO_THR, 0x00003000}, - { /* end of list */ }, + {AUD_DMD_RA_DDS, 0x002a4f2f}, + {AUD_C1_UP_THR, 0x00007000}, + {AUD_C1_LO_THR, 0x00005400}, + {AUD_C2_UP_THR, 0x00005400}, + {AUD_C2_LO_THR, 0x00003000}, + { /* end of list */ }, }; static const struct rlist a2_dk[] = { - {AUD_DMD_RA_DDS, 0x002a4f2f}, - {AUD_C1_UP_THR, 0x00007000}, - {AUD_C1_LO_THR, 0x00005400}, - {AUD_C2_UP_THR, 0x00005400}, - {AUD_C2_LO_THR, 0x00003000}, - {AUD_DN0_FREQ, 0x00003a1c}, - {AUD_DN2_FREQ, 0x0000d2e0}, - { /* end of list */ }, + {AUD_DMD_RA_DDS, 0x002a4f2f}, + {AUD_C1_UP_THR, 0x00007000}, + {AUD_C1_LO_THR, 0x00005400}, + {AUD_C2_UP_THR, 0x00005400}, + {AUD_C2_LO_THR, 0x00003000}, + {AUD_DN0_FREQ, 0x00003a1c}, + {AUD_DN2_FREQ, 0x0000d2e0}, + { /* end of list */ }, }; static const struct rlist a1_i[] = { - {AUD_ERRLOGPERIOD_R, 0x00000064}, - {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff}, - {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f}, - {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f}, - {AUD_PDF_DDS_CNST_BYTE2, 0x06}, - {AUD_PDF_DDS_CNST_BYTE1, 0x82}, - {AUD_PDF_DDS_CNST_BYTE0, 0x12}, - {AUD_QAM_MODE, 0x05}, - {AUD_PHACC_FREQ_8MSB, 0x3a}, - {AUD_PHACC_FREQ_8LSB, 0x93}, - {AUD_DMD_RA_DDS, 0x002a4f2f}, - {AUD_PLL_INT, 0x0000001e}, - {AUD_PLL_DDS, 0x00000004}, - {AUD_PLL_FRAC, 0x0000e542}, - {AUD_RATE_ADJ1, 0x00000100}, - {AUD_RATE_ADJ2, 0x00000200}, - {AUD_RATE_ADJ3, 0x00000300}, - {AUD_RATE_ADJ4, 0x00000400}, - {AUD_RATE_ADJ5, 0x00000500}, - {AUD_THR_FR, 0x00000000}, - {AUD_PILOT_BQD_1_K0, 0x0000755b}, - {AUD_PILOT_BQD_1_K1, 0x00551340}, - {AUD_PILOT_BQD_1_K2, 0x006d30be}, - {AUD_PILOT_BQD_1_K3, 0xffd394af}, - {AUD_PILOT_BQD_1_K4, 0x00400000}, - {AUD_PILOT_BQD_2_K0, 0x00040000}, - {AUD_PILOT_BQD_2_K1, 0x002a4841}, - {AUD_PILOT_BQD_2_K2, 0x00400000}, - {AUD_PILOT_BQD_2_K3, 0x00000000}, - {AUD_PILOT_BQD_2_K4, 0x00000000}, - {AUD_MODE_CHG_TIMER, 0x00000060}, - {AUD_AFE_12DB_EN, 0x00000001}, - {AAGC_HYST, 0x0000000a}, - {AUD_CORDIC_SHIFT_0, 0x00000007}, - {AUD_CORDIC_SHIFT_1, 0x00000007}, - {AUD_C1_UP_THR, 0x00007000}, - {AUD_C1_LO_THR, 0x00005400}, - {AUD_C2_UP_THR, 0x00005400}, - {AUD_C2_LO_THR, 0x00003000}, - {AUD_DCOC_0_SRC, 0x0000001a}, - {AUD_DCOC0_SHIFT, 0x00000000}, - {AUD_DCOC_0_SHIFT_IN0, 0x0000000a}, - {AUD_DCOC_0_SHIFT_IN1, 0x00000008}, - {AUD_DCOC_PASS_IN, 0x00000003}, - {AUD_IIR3_0_SEL, 0x00000021}, - {AUD_DN2_AFC, 0x00000002}, - {AUD_DCOC_1_SRC, 0x0000001b}, - {AUD_DCOC1_SHIFT, 0x00000000}, - {AUD_DCOC_1_SHIFT_IN0, 0x0000000a}, - {AUD_DCOC_1_SHIFT_IN1, 0x00000008}, - {AUD_IIR3_1_SEL, 0x00000023}, - {AUD_DN0_FREQ, 0x000035a3}, - {AUD_DN2_FREQ, 0x000029c7}, - {AUD_CRDC0_SRC_SEL, 0x00000511}, - {AUD_IIR1_0_SEL, 0x00000001}, - {AUD_IIR1_1_SEL, 0x00000000}, - {AUD_IIR3_2_SEL, 0x00000003}, - {AUD_IIR3_2_SHIFT, 0x00000000}, - {AUD_IIR3_0_SEL, 0x00000002}, - {AUD_IIR2_0_SEL, 0x00000021}, - {AUD_IIR2_0_SHIFT, 0x00000002}, - {AUD_DEEMPH0_SRC_SEL, 0x0000000b}, - {AUD_DEEMPH1_SRC_SEL, 0x0000000b}, - {AUD_POLYPH80SCALEFAC, 0x00000001}, - {AUD_START_TIMER, 0x00000000}, - { /* end of list */ }, + {AUD_ERRLOGPERIOD_R, 0x00000064}, + {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff}, + {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f}, + {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f}, + {AUD_PDF_DDS_CNST_BYTE2, 0x06}, + {AUD_PDF_DDS_CNST_BYTE1, 0x82}, + {AUD_PDF_DDS_CNST_BYTE0, 0x12}, + {AUD_QAM_MODE, 0x05}, + {AUD_PHACC_FREQ_8MSB, 0x3a}, + {AUD_PHACC_FREQ_8LSB, 0x93}, + {AUD_DMD_RA_DDS, 0x002a4f2f}, + {AUD_PLL_INT, 0x0000001e}, + {AUD_PLL_DDS, 0x00000004}, + {AUD_PLL_FRAC, 0x0000e542}, + {AUD_RATE_ADJ1, 0x00000100}, + {AUD_RATE_ADJ2, 0x00000200}, + {AUD_RATE_ADJ3, 0x00000300}, + {AUD_RATE_ADJ4, 0x00000400}, + {AUD_RATE_ADJ5, 0x00000500}, + {AUD_THR_FR, 0x00000000}, + {AUD_PILOT_BQD_1_K0, 0x0000755b}, + {AUD_PILOT_BQD_1_K1, 0x00551340}, + {AUD_PILOT_BQD_1_K2, 0x006d30be}, + {AUD_PILOT_BQD_1_K3, 0xffd394af}, + {AUD_PILOT_BQD_1_K4, 0x00400000}, + {AUD_PILOT_BQD_2_K0, 0x00040000}, + {AUD_PILOT_BQD_2_K1, 0x002a4841}, + {AUD_PILOT_BQD_2_K2, 0x00400000}, + {AUD_PILOT_BQD_2_K3, 0x00000000}, + {AUD_PILOT_BQD_2_K4, 0x00000000}, + {AUD_MODE_CHG_TIMER, 0x00000060}, + {AUD_AFE_12DB_EN, 0x00000001}, + {AAGC_HYST, 0x0000000a}, + {AUD_CORDIC_SHIFT_0, 0x00000007}, + {AUD_CORDIC_SHIFT_1, 0x00000007}, + {AUD_C1_UP_THR, 0x00007000}, + {AUD_C1_LO_THR, 0x00005400}, + {AUD_C2_UP_THR, 0x00005400}, + {AUD_C2_LO_THR, 0x00003000}, + {AUD_DCOC_0_SRC, 0x0000001a}, + {AUD_DCOC0_SHIFT, 0x00000000}, + {AUD_DCOC_0_SHIFT_IN0, 0x0000000a}, + {AUD_DCOC_0_SHIFT_IN1, 0x00000008}, + {AUD_DCOC_PASS_IN, 0x00000003}, + {AUD_IIR3_0_SEL, 0x00000021}, + {AUD_DN2_AFC, 0x00000002}, + {AUD_DCOC_1_SRC, 0x0000001b}, + {AUD_DCOC1_SHIFT, 0x00000000}, + {AUD_DCOC_1_SHIFT_IN0, 0x0000000a}, + {AUD_DCOC_1_SHIFT_IN1, 0x00000008}, + {AUD_IIR3_1_SEL, 0x00000023}, + {AUD_DN0_FREQ, 0x000035a3}, + {AUD_DN2_FREQ, 0x000029c7}, + {AUD_CRDC0_SRC_SEL, 0x00000511}, + {AUD_IIR1_0_SEL, 0x00000001}, + {AUD_IIR1_1_SEL, 0x00000000}, + {AUD_IIR3_2_SEL, 0x00000003}, + {AUD_IIR3_2_SHIFT, 0x00000000}, + {AUD_IIR3_0_SEL, 0x00000002}, + {AUD_IIR2_0_SEL, 0x00000021}, + {AUD_IIR2_0_SHIFT, 0x00000002}, + {AUD_DEEMPH0_SRC_SEL, 0x0000000b}, + {AUD_DEEMPH1_SRC_SEL, 0x0000000b}, + {AUD_POLYPH80SCALEFAC, 0x00000001}, + {AUD_START_TIMER, 0x00000000}, + { /* end of list */ }, }; static const struct rlist am_l[] = { - {AUD_ERRLOGPERIOD_R, 0x00000064}, - {AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF}, - {AUD_ERRINTRPTTHSHLD2_R, 0x0000001F}, - {AUD_ERRINTRPTTHSHLD3_R, 0x0000000F}, - {AUD_PDF_DDS_CNST_BYTE2, 0x48}, - {AUD_PDF_DDS_CNST_BYTE1, 0x3D}, - {AUD_QAM_MODE, 0x00}, - {AUD_PDF_DDS_CNST_BYTE0, 0xf5}, - {AUD_PHACC_FREQ_8MSB, 0x3a}, - {AUD_PHACC_FREQ_8LSB, 0x4a}, - {AUD_DEEMPHGAIN_R, 0x00006680}, - {AUD_DEEMPHNUMER1_R, 0x000353DE}, - {AUD_DEEMPHNUMER2_R, 0x000001B1}, - {AUD_DEEMPHDENOM1_R, 0x0000F3D0}, - {AUD_DEEMPHDENOM2_R, 0x00000000}, - {AUD_FM_MODE_ENABLE, 0x00000007}, - {AUD_POLYPH80SCALEFAC, 0x00000003}, - {AUD_AFE_12DB_EN, 0x00000001}, - {AAGC_GAIN, 0x00000000}, - {AAGC_HYST, 0x00000018}, - {AAGC_DEF, 0x00000020}, - {AUD_DN0_FREQ, 0x00000000}, - {AUD_POLY0_DDS_CONSTANT, 0x000E4DB2}, - {AUD_DCOC_0_SRC, 0x00000021}, - {AUD_IIR1_0_SEL, 0x00000000}, - {AUD_IIR1_0_SHIFT, 0x00000007}, - {AUD_IIR1_1_SEL, 0x00000002}, - {AUD_IIR1_1_SHIFT, 0x00000000}, - {AUD_DCOC_1_SRC, 0x00000003}, - {AUD_DCOC1_SHIFT, 0x00000000}, - {AUD_DCOC_PASS_IN, 0x00000000}, - {AUD_IIR1_2_SEL, 0x00000023}, - {AUD_IIR1_2_SHIFT, 0x00000000}, - {AUD_IIR1_3_SEL, 0x00000004}, - {AUD_IIR1_3_SHIFT, 0x00000007}, - {AUD_IIR1_4_SEL, 0x00000005}, - {AUD_IIR1_4_SHIFT, 0x00000007}, - {AUD_IIR3_0_SEL, 0x00000007}, - {AUD_IIR3_0_SHIFT, 0x00000000}, - {AUD_DEEMPH0_SRC_SEL, 0x00000011}, - {AUD_DEEMPH0_SHIFT, 0x00000000}, - {AUD_DEEMPH0_G0, 0x00007000}, - {AUD_DEEMPH0_A0, 0x00000000}, - {AUD_DEEMPH0_B0, 0x00000000}, - {AUD_DEEMPH0_A1, 0x00000000}, - {AUD_DEEMPH0_B1, 0x00000000}, - {AUD_DEEMPH1_SRC_SEL, 0x00000011}, - {AUD_DEEMPH1_SHIFT, 0x00000000}, - {AUD_DEEMPH1_G0, 0x00007000}, - {AUD_DEEMPH1_A0, 0x00000000}, - {AUD_DEEMPH1_B0, 0x00000000}, - {AUD_DEEMPH1_A1, 0x00000000}, - {AUD_DEEMPH1_B1, 0x00000000}, - {AUD_OUT0_SEL, 0x0000003F}, - {AUD_OUT1_SEL, 0x0000003F}, - {AUD_DMD_RA_DDS, 0x00F5C285}, - {AUD_PLL_INT, 0x0000001E}, - {AUD_PLL_DDS, 0x00000000}, - {AUD_PLL_FRAC, 0x0000E542}, - {AUD_RATE_ADJ1, 0x00000100}, - {AUD_RATE_ADJ2, 0x00000200}, - {AUD_RATE_ADJ3, 0x00000300}, - {AUD_RATE_ADJ4, 0x00000400}, - {AUD_RATE_ADJ5, 0x00000500}, - {AUD_RATE_THRES_DMD, 0x000000C0}, - {/* end of list */ }, + {AUD_ERRLOGPERIOD_R, 0x00000064}, + {AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF}, + {AUD_ERRINTRPTTHSHLD2_R, 0x0000001F}, + {AUD_ERRINTRPTTHSHLD3_R, 0x0000000F}, + {AUD_PDF_DDS_CNST_BYTE2, 0x48}, + {AUD_PDF_DDS_CNST_BYTE1, 0x3D}, + {AUD_QAM_MODE, 0x00}, + {AUD_PDF_DDS_CNST_BYTE0, 0xf5}, + {AUD_PHACC_FREQ_8MSB, 0x3a}, + {AUD_PHACC_FREQ_8LSB, 0x4a}, + {AUD_DEEMPHGAIN_R, 0x00006680}, + {AUD_DEEMPHNUMER1_R, 0x000353DE}, + {AUD_DEEMPHNUMER2_R, 0x000001B1}, + {AUD_DEEMPHDENOM1_R, 0x0000F3D0}, + {AUD_DEEMPHDENOM2_R, 0x00000000}, + {AUD_FM_MODE_ENABLE, 0x00000007}, + {AUD_POLYPH80SCALEFAC, 0x00000003}, + {AUD_AFE_12DB_EN, 0x00000001}, + {AAGC_GAIN, 0x00000000}, + {AAGC_HYST, 0x00000018}, + {AAGC_DEF, 0x00000020}, + {AUD_DN0_FREQ, 0x00000000}, + {AUD_POLY0_DDS_CONSTANT, 0x000E4DB2}, + {AUD_DCOC_0_SRC, 0x00000021}, + {AUD_IIR1_0_SEL, 0x00000000}, + {AUD_IIR1_0_SHIFT, 0x00000007}, + {AUD_IIR1_1_SEL, 0x00000002}, + {AUD_IIR1_1_SHIFT, 0x00000000}, + {AUD_DCOC_1_SRC, 0x00000003}, + {AUD_DCOC1_SHIFT, 0x00000000}, + {AUD_DCOC_PASS_IN, 0x00000000}, + {AUD_IIR1_2_SEL, 0x00000023}, + {AUD_IIR1_2_SHIFT, 0x00000000}, + {AUD_IIR1_3_SEL, 0x00000004}, + {AUD_IIR1_3_SHIFT, 0x00000007}, + {AUD_IIR1_4_SEL, 0x00000005}, + {AUD_IIR1_4_SHIFT, 0x00000007}, + {AUD_IIR3_0_SEL, 0x00000007}, + {AUD_IIR3_0_SHIFT, 0x00000000}, + {AUD_DEEMPH0_SRC_SEL, 0x00000011}, + {AUD_DEEMPH0_SHIFT, 0x00000000}, + {AUD_DEEMPH0_G0, 0x00007000}, + {AUD_DEEMPH0_A0, 0x00000000}, + {AUD_DEEMPH0_B0, 0x00000000}, + {AUD_DEEMPH0_A1, 0x00000000}, + {AUD_DEEMPH0_B1, 0x00000000}, + {AUD_DEEMPH1_SRC_SEL, 0x00000011}, + {AUD_DEEMPH1_SHIFT, 0x00000000}, + {AUD_DEEMPH1_G0, 0x00007000}, + {AUD_DEEMPH1_A0, 0x00000000}, + {AUD_DEEMPH1_B0, 0x00000000}, + {AUD_DEEMPH1_A1, 0x00000000}, + {AUD_DEEMPH1_B1, 0x00000000}, + {AUD_OUT0_SEL, 0x0000003F}, + {AUD_OUT1_SEL, 0x0000003F}, + {AUD_DMD_RA_DDS, 0x00F5C285}, + {AUD_PLL_INT, 0x0000001E}, + {AUD_PLL_DDS, 0x00000000}, + {AUD_PLL_FRAC, 0x0000E542}, + {AUD_RATE_ADJ1, 0x00000100}, + {AUD_RATE_ADJ2, 0x00000200}, + {AUD_RATE_ADJ3, 0x00000300}, + {AUD_RATE_ADJ4, 0x00000400}, + {AUD_RATE_ADJ5, 0x00000500}, + {AUD_RATE_THRES_DMD, 0x000000C0}, + { /* end of list */ }, }; static const struct rlist a2_deemph50[] = { - {AUD_DEEMPH0_G0, 0x00000380}, - {AUD_DEEMPH1_G0, 0x00000380}, - {AUD_DEEMPHGAIN_R, 0x000011e1}, - {AUD_DEEMPHNUMER1_R, 0x0002a7bc}, - {AUD_DEEMPHNUMER2_R, 0x0003023c}, - { /* end of list */ }, + {AUD_DEEMPH0_G0, 0x00000380}, + {AUD_DEEMPH1_G0, 0x00000380}, + {AUD_DEEMPHGAIN_R, 0x000011e1}, + {AUD_DEEMPHNUMER1_R, 0x0002a7bc}, + {AUD_DEEMPHNUMER2_R, 0x0003023c}, + { /* end of list */ }, }; set_audio_start(core, SEL_A2); switch (core->tvaudio) { case WW_BG: - dprintk("%s PAL-BG A1/2 (status: known-good)\n",__FUNCTION__); + dprintk("%s PAL-BG A1/2 (status: known-good)\n", __FUNCTION__); set_audio_registers(core, a2_bgdk_common); set_audio_registers(core, a2_bg); set_audio_registers(core, a2_deemph50); break; case WW_DK: - dprintk("%s PAL-DK A1/2 (status: known-good)\n",__FUNCTION__); + dprintk("%s PAL-DK A1/2 (status: known-good)\n", __FUNCTION__); set_audio_registers(core, a2_bgdk_common); set_audio_registers(core, a2_dk); set_audio_registers(core, a2_deemph50); break; case WW_I: - dprintk("%s PAL-I A1 (status: known-good)\n",__FUNCTION__); + dprintk("%s PAL-I A1 (status: known-good)\n", __FUNCTION__); set_audio_registers(core, a1_i); set_audio_registers(core, a2_deemph50); break; case WW_L: - dprintk("%s AM-L (status: devel)\n",__FUNCTION__); + dprintk("%s AM-L (status: devel)\n", __FUNCTION__); set_audio_registers(core, am_l); break; default: - dprintk("%s Warning: wrong value\n",__FUNCTION__); + dprintk("%s Warning: wrong value\n", __FUNCTION__); return; break; }; @@ -631,71 +629,71 @@ static void set_audio_standard_EIAJ(struct cx88_core *core) { /* end of list */ }, }; - dprintk("%s (status: unknown)\n",__FUNCTION__); + dprintk("%s (status: unknown)\n", __FUNCTION__); set_audio_start(core, SEL_EIAJ); set_audio_registers(core, eiaj); set_audio_finish(core, EN_EIAJ_AUTO_STEREO); } -static void set_audio_standard_FM(struct cx88_core *core, enum cx88_deemph_type deemph) +static void set_audio_standard_FM(struct cx88_core *core, + enum cx88_deemph_type deemph) { static const struct rlist fm_deemph_50[] = { - { AUD_DEEMPH0_G0, 0x0C45 }, - { AUD_DEEMPH0_A0, 0x6262 }, - { AUD_DEEMPH0_B0, 0x1C29 }, - { AUD_DEEMPH0_A1, 0x3FC66}, - { AUD_DEEMPH0_B1, 0x399A }, - - { AUD_DEEMPH1_G0, 0x0D80 }, - { AUD_DEEMPH1_A0, 0x6262 }, - { AUD_DEEMPH1_B0, 0x1C29 }, - { AUD_DEEMPH1_A1, 0x3FC66}, - { AUD_DEEMPH1_B1, 0x399A}, - - { AUD_POLYPH80SCALEFAC, 0x0003}, + {AUD_DEEMPH0_G0, 0x0C45}, + {AUD_DEEMPH0_A0, 0x6262}, + {AUD_DEEMPH0_B0, 0x1C29}, + {AUD_DEEMPH0_A1, 0x3FC66}, + {AUD_DEEMPH0_B1, 0x399A}, + + {AUD_DEEMPH1_G0, 0x0D80}, + {AUD_DEEMPH1_A0, 0x6262}, + {AUD_DEEMPH1_B0, 0x1C29}, + {AUD_DEEMPH1_A1, 0x3FC66}, + {AUD_DEEMPH1_B1, 0x399A}, + + {AUD_POLYPH80SCALEFAC, 0x0003}, { /* end of list */ }, }; static const struct rlist fm_deemph_75[] = { - { AUD_DEEMPH0_G0, 0x091B }, - { AUD_DEEMPH0_A0, 0x6B68 }, - { AUD_DEEMPH0_B0, 0x11EC }, - { AUD_DEEMPH0_A1, 0x3FC66}, - { AUD_DEEMPH0_B1, 0x399A }, - - { AUD_DEEMPH1_G0, 0x0AA0 }, - { AUD_DEEMPH1_A0, 0x6B68 }, - { AUD_DEEMPH1_B0, 0x11EC }, - { AUD_DEEMPH1_A1, 0x3FC66}, - { AUD_DEEMPH1_B1, 0x399A}, - - { AUD_POLYPH80SCALEFAC, 0x0003}, + {AUD_DEEMPH0_G0, 0x091B}, + {AUD_DEEMPH0_A0, 0x6B68}, + {AUD_DEEMPH0_B0, 0x11EC}, + {AUD_DEEMPH0_A1, 0x3FC66}, + {AUD_DEEMPH0_B1, 0x399A}, + + {AUD_DEEMPH1_G0, 0x0AA0}, + {AUD_DEEMPH1_A0, 0x6B68}, + {AUD_DEEMPH1_B0, 0x11EC}, + {AUD_DEEMPH1_A1, 0x3FC66}, + {AUD_DEEMPH1_B1, 0x399A}, + + {AUD_POLYPH80SCALEFAC, 0x0003}, { /* end of list */ }, }; /* It is enough to leave default values? */ static const struct rlist fm_no_deemph[] = { - { AUD_POLYPH80SCALEFAC, 0x0003}, + {AUD_POLYPH80SCALEFAC, 0x0003}, { /* end of list */ }, }; - dprintk("%s (status: unknown)\n",__FUNCTION__); + dprintk("%s (status: unknown)\n", __FUNCTION__); set_audio_start(core, SEL_FMRADIO); - switch (deemph) - { - case FM_NO_DEEMPH: - set_audio_registers(core, fm_no_deemph); - break; + switch (deemph) { + case FM_NO_DEEMPH: + set_audio_registers(core, fm_no_deemph); + break; - case FM_DEEMPH_50: - set_audio_registers(core, fm_deemph_50); - break; + case FM_DEEMPH_50: + set_audio_registers(core, fm_deemph_50); + break; - case FM_DEEMPH_75: - set_audio_registers(core, fm_deemph_75); - break; + case FM_DEEMPH_75: + set_audio_registers(core, fm_deemph_75); + break; } set_audio_finish(core, EN_FMRADIO_AUTO_STEREO); @@ -705,22 +703,22 @@ static void set_audio_standard_FM(struct cx88_core *core, enum cx88_deemph_type int cx88_detect_nicam(struct cx88_core *core) { - int i, j=0; + int i, j = 0; dprintk("start nicam autodetect.\n"); - for(i=0; i<6; i++) { - /* if bit1=1 then nicam is detected */ - j+= ((cx_read(AUD_NICAM_STATUS2) & 0x02) >> 1); + for (i = 0; i < 6; i++) { + /* if bit1=1 then nicam is detected */ + j += ((cx_read(AUD_NICAM_STATUS2) & 0x02) >> 1); /* 3x detected: absolutly sure now */ - if(j==3) { + if (j == 3) { dprintk("nicam is detected.\n"); return 1; } /* wait a little bit for next reading status */ - msleep (10); + msleep(10); } dprintk("nicam is not detected.\n"); @@ -743,24 +741,24 @@ void cx88_set_tvaudio(struct cx88_core *core) /* set nicam mode - otherwise AUD_NICAM_STATUS2 contains wrong values */ set_audio_standard_NICAM(core, EN_NICAM_FORCE_MONO1); - if(0 == cx88_detect_nicam(core)) { + if (0 == cx88_detect_nicam(core)) { /* fall back to fm / am mono */ set_audio_standard_A2(core, EN_A2_FORCE_MONO1); core->use_nicam = 0; - } else { + } else { core->use_nicam = 1; - } + } break; case WW_EIAJ: set_audio_standard_EIAJ(core); break; case WW_FM: - set_audio_standard_FM(core,FM_NO_DEEMPH); + set_audio_standard_FM(core, FM_NO_DEEMPH); break; case WW_NONE: default: printk("%s/0: unknown tv audio mode [%d]\n", - core->name, core->tvaudio); + core->name, core->tvaudio); break; } return; @@ -773,12 +771,12 @@ void cx88_newstation(struct cx88_core *core) void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t) { - static char *m[] = {"stereo", "dual mono", "mono", "sap"}; - static char *p[] = {"no pilot", "pilot c1", "pilot c2", "?"}; - u32 reg,mode,pilot; + static char *m[] = { "stereo", "dual mono", "mono", "sap" }; + static char *p[] = { "no pilot", "pilot c1", "pilot c2", "?" }; + u32 reg, mode, pilot; - reg = cx_read(AUD_STATUS); - mode = reg & 0x03; + reg = cx_read(AUD_STATUS); + mode = reg & 0x03; pilot = (reg >> 2) & 0x03; if (core->astat != reg) @@ -795,14 +793,13 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t) # if 0 t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP | - V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; + V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; t->rxsubchans = V4L2_TUNER_SUB_MONO; - t->audmode = V4L2_TUNER_MODE_MONO; + t->audmode = V4L2_TUNER_MODE_MONO; switch (core->tvaudio) { case WW_BTSC: - t->capability = V4L2_TUNER_CAP_STEREO | - V4L2_TUNER_CAP_SAP; + t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP; t->rxsubchans = V4L2_TUNER_SUB_STEREO; if (1 == pilot) { /* SAP */ @@ -814,13 +811,15 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t) case WW_A2_M: if (1 == pilot) { /* stereo */ - t->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; + t->rxsubchans = + V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; if (0 == mode) t->audmode = V4L2_TUNER_MODE_STEREO; } if (2 == pilot) { /* dual language -- FIXME */ - t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; + t->rxsubchans = + V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; t->audmode = V4L2_TUNER_MODE_LANG1; } break; @@ -835,7 +834,7 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t) t->audmode = V4L2_TUNER_MODE_STEREO; t->rxsubchans |= V4L2_TUNER_SUB_STEREO; } - break ; + break; default: /* nothing */ break; @@ -846,7 +845,7 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t) void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual) { - u32 ctl = UNSET; + u32 ctl = UNSET; u32 mask = UNSET; if (manual) { @@ -878,21 +877,24 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual) case WW_DK: case WW_I: case WW_L: - if(1 == core->use_nicam) { + if (1 == core->use_nicam) { switch (mode) { case V4L2_TUNER_MODE_MONO: case V4L2_TUNER_MODE_LANG1: - set_audio_standard_NICAM(core, EN_NICAM_FORCE_MONO1); + set_audio_standard_NICAM(core, + EN_NICAM_FORCE_MONO1); break; case V4L2_TUNER_MODE_LANG2: - set_audio_standard_NICAM(core, EN_NICAM_FORCE_MONO2); + set_audio_standard_NICAM(core, + EN_NICAM_FORCE_MONO2); break; case V4L2_TUNER_MODE_STEREO: - set_audio_standard_NICAM(core, EN_NICAM_FORCE_STEREO); + set_audio_standard_NICAM(core, + EN_NICAM_FORCE_STEREO); break; } } else { - if ( (core->tvaudio == WW_I) || (core->tvaudio == WW_L) ) { + if ((core->tvaudio == WW_I) || (core->tvaudio == WW_L)) { /* fall back to fm / am mono */ set_audio_standard_A2(core, EN_A2_FORCE_MONO1); } else { @@ -900,13 +902,16 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual) switch (mode) { case V4L2_TUNER_MODE_MONO: case V4L2_TUNER_MODE_LANG1: - set_audio_standard_A2(core, EN_A2_FORCE_MONO1); + set_audio_standard_A2(core, + EN_A2_FORCE_MONO1); break; case V4L2_TUNER_MODE_LANG2: - set_audio_standard_A2(core, EN_A2_FORCE_MONO2); + set_audio_standard_A2(core, + EN_A2_FORCE_MONO2); break; case V4L2_TUNER_MODE_STEREO: - set_audio_standard_A2(core, EN_A2_FORCE_STEREO); + set_audio_standard_A2(core, + EN_A2_FORCE_STEREO); break; } } @@ -915,11 +920,11 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual) case WW_FM: switch (mode) { case V4L2_TUNER_MODE_MONO: - ctl = EN_FMRADIO_FORCE_MONO; + ctl = EN_FMRADIO_FORCE_MONO; mask = 0x3f; break; case V4L2_TUNER_MODE_STEREO: - ctl = EN_FMRADIO_AUTO_STEREO; + ctl = EN_FMRADIO_AUTO_STEREO; mask = 0x3f; break; } @@ -949,8 +954,8 @@ int cx88_audio_thread(void *data) break; /* just monitor the audio status for now ... */ - memset(&t,0,sizeof(t)); - cx88_get_stereo(core,&t); + memset(&t, 0, sizeof(t)); + cx88_get_stereo(core, &t); if (UNSET != core->audiomode_manual) /* manually set, don't do anything. */ -- cgit v1.2.3 From dc2286cfce214c0de00571f3219a50488c58dd6b Mon Sep 17 00:00:00 2001 From: "James R. Webb" Date: Tue, 8 Nov 2005 21:37:00 -0800 Subject: [PATCH] v4l: 707: remote for kworld terminator - Remote for KWorld Terminator. Signed-off-by: James R. Webb Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-cards.c | 1 + drivers/media/video/saa7134/saa7134-input.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index c59f4d77552..7278150fb58 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2848,6 +2848,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_409FM: case SAA7134_BOARD_AVACSSMARTTV: case SAA7134_BOARD_GOTVIEW_7135: + case SAA7134_BOARD_KWORLD_TERMINATOR: dev->has_remote = 1; break; case SAA7134_BOARD_MD5044: diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 8d211ba2231..9dc41c1427a 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -557,6 +557,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPMODE0, 0x4); saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); break; + case SAA7134_BOARD_KWORLD_TERMINATOR: + ir_codes = avacssmart_codes; + mask_keycode = 0x00001f; + mask_keyup = 0x000060; + polling = 50; // ms + break; case SAA7134_BOARD_MANLI_MTV001: case SAA7134_BOARD_MANLI_MTV002: case SAA7134_BOARD_BEHOLD_409FM: -- cgit v1.2.3 From 1eaad5b113811db7fdb6d02e1c8d9ff7c8ba6919 Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:37:01 -0800 Subject: [PATCH] v4l: 708: full mute of saa7134 on mute command - Full mute of saa7134 on mute command. Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-tvaudio.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index 61a2d6b50ee..fdca6c563b9 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -207,6 +207,10 @@ static void tvaudio_setcarrier(struct saa7134_dev *dev, saa_writel(SAA7134_CARRIER2_FREQ0 >> 2, tvaudio_carr2reg(secondary)); } +#define SAA7134_MUTE_MASK 0xbb +#define SAA7134_MUTE_ANALOG 0x04 +#define SAA7134_MUTE_I2S 0x40 + static void mute_input_7134(struct saa7134_dev *dev) { unsigned int mute; @@ -241,7 +245,11 @@ static void mute_input_7134(struct saa7134_dev *dev) if (PCI_DEVICE_ID_PHILIPS_SAA7134 == dev->pci->device) /* 7134 mute */ - saa_writeb(SAA7134_AUDIO_MUTE_CTRL, mute ? 0xbf : 0xbb); + saa_writeb(SAA7134_AUDIO_MUTE_CTRL, mute ? + SAA7134_MUTE_MASK | + SAA7134_MUTE_ANALOG | + SAA7134_MUTE_I2S : + SAA7134_MUTE_MASK); /* switch internal audio mux */ switch (in->amux) { -- cgit v1.2.3 From f718e6e7a2c402195f3d2944605ef4b01e8e3347 Mon Sep 17 00:00:00 2001 From: Kenth Andersson Date: Tue, 8 Nov 2005 21:37:02 -0800 Subject: [PATCH] v4l: 709: added osprey 440 card - Added Osprey 440 card. Signed-off-by: Kenth Andersson Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bttv-cards.c | 19 ++++++++++++++++++- drivers/media/video/bttv.h | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index adccbbf63dc..85f19426892 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -153,6 +153,7 @@ static struct CARD { { 0xff020070, BTTV_BOARD_OSPREY500, "Osprey-500" }, { 0xff030070, BTTV_BOARD_OSPREY2000, "Osprey-2000" }, { 0xff040070, BTTV_BOARD_OSPREY540, "Osprey-540" }, + { 0xff070070, BTTV_BOARD_OSPREY440, "Osprey-440" }, { 0x00011002, BTTV_BOARD_ATI_TVWONDER, "ATI TV Wonder" }, { 0x00031002, BTTV_BOARD_ATI_TVWONDERVE,"ATI TV Wonder/VE" }, @@ -2763,7 +2764,23 @@ struct tvcard bttv_tvcards[] = { .radio_addr = ADDR_UNSET, .has_radio = 1, .has_remote = 1, - } + }, + /* ---- card 0x8c ---------------------------------- */ + [BTTV_BOARD_OSPREY440] = { + .name = "Osprey 440", + .video_inputs = 1, + .audio_inputs = 1, + .tuner = -1, + .svhs = 1, + .muxsel = { 2 }, + .pll = PLL_28, + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + }, }; static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h index a4194e1ea90..75d08a33b10 100644 --- a/drivers/media/video/bttv.h +++ b/drivers/media/video/bttv.h @@ -160,6 +160,7 @@ #define BTTV_BOARD_CONCEPTRONIC_CTVFMI2 0x89 #define BTTV_BOARD_PV_BT878P_2E 0x8a #define BTTV_BOARD_PV_M4900 0x8b +#define BTTV_BOARD_OSPREY440 0x8c /* i2c address list */ #define I2C_TSA5522 0xc2 -- cgit v1.2.3 From cf583ac40d06825bc850dc4f47627d7661aaa4f8 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:37:03 -0800 Subject: [PATCH] v4l: 711: changed pll 1 to pll pll 28 - Changed { .pll = 1, } to { .pll = PLL_28, } Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.bttv | 1 + Documentation/video4linux/CARDLIST.cx88 | 1 + drivers/media/video/bttv-cards.c | 4 +- drivers/media/video/bttv.h | 280 ++++++++++++++++---------------- 4 files changed, 144 insertions(+), 142 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index 1fde0d70da1..ba98ff4a79a 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -138,3 +138,4 @@ 137 -> Conceptronic CTVFMi v2 138 -> Prolink Pixelview PV-BT878P+ (Rev.2E) 139 -> Prolink PixelView PlayTV MPEG2 PV-M4900 +140 -> Osprey 440 [0070:ff07] diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index f0b3b49a4fd..8a14e3f44ca 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -31,3 +31,4 @@ 30 -> TerraTec Cinergy 1400 DVB-T [153b:1166] 31 -> DViCO FusionHDTV 5 Gold [18ac:d500] 32 -> AverMedia UltraTV Media Center PCI 550 [1461:8011] + 33 -> Kworld V-Stream Xpert DVD diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 85f19426892..1f33764bf05 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -1982,7 +1982,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = 5, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .pll = 1, + .pll = PLL_28, }, [BTTV_BOARD_EURESYS_PICOLO] = { .name = "Euresys Picolo", @@ -2765,7 +2765,7 @@ struct tvcard bttv_tvcards[] = { .has_radio = 1, .has_remote = 1, }, - /* ---- card 0x8c ---------------------------------- */ + /* ---- card 0x8c ---------------------------------- */ [BTTV_BOARD_OSPREY440] = { .name = "Osprey 440", .video_inputs = 1, diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h index 75d08a33b10..ffece3b9136 100644 --- a/drivers/media/video/bttv.h +++ b/drivers/media/video/bttv.h @@ -20,147 +20,147 @@ /* ---------------------------------------------------------- */ /* exported by bttv-cards.c */ -#define BTTV_BOARD_UNKNOWN 0x00 -#define BTTV_BOARD_MIRO 0x01 -#define BTTV_BOARD_HAUPPAUGE 0x02 -#define BTTV_BOARD_STB 0x03 -#define BTTV_BOARD_INTEL 0x04 -#define BTTV_BOARD_DIAMOND 0x05 -#define BTTV_BOARD_AVERMEDIA 0x06 -#define BTTV_BOARD_MATRIX_VISION 0x07 -#define BTTV_BOARD_FLYVIDEO 0x08 -#define BTTV_BOARD_TURBOTV 0x09 -#define BTTV_BOARD_HAUPPAUGE878 0x0a -#define BTTV_BOARD_MIROPRO 0x0b -#define BTTV_BOARD_ADSTECH_TV 0x0c -#define BTTV_BOARD_AVERMEDIA98 0x0d -#define BTTV_BOARD_VHX 0x0e -#define BTTV_BOARD_ZOLTRIX 0x0f -#define BTTV_BOARD_PIXVIEWPLAYTV 0x10 -#define BTTV_BOARD_WINVIEW_601 0x11 -#define BTTV_BOARD_AVEC_INTERCAP 0x12 -#define BTTV_BOARD_LIFE_FLYKIT 0x13 -#define BTTV_BOARD_CEI_RAFFLES 0x14 -#define BTTV_BOARD_CONFERENCETV 0x15 -#define BTTV_BOARD_PHOEBE_TVMAS 0x16 -#define BTTV_BOARD_MODTEC_205 0x17 -#define BTTV_BOARD_MAGICTVIEW061 0x18 -#define BTTV_BOARD_VOBIS_BOOSTAR 0x19 -#define BTTV_BOARD_HAUPPAUG_WCAM 0x1a -#define BTTV_BOARD_MAXI 0x1b -#define BTTV_BOARD_TERRATV 0x1c -#define BTTV_BOARD_PXC200 0x1d -#define BTTV_BOARD_FLYVIDEO_98 0x1e -#define BTTV_BOARD_IPROTV 0x1f -#define BTTV_BOARD_INTEL_C_S_PCI 0x20 -#define BTTV_BOARD_TERRATVALUE 0x21 -#define BTTV_BOARD_WINFAST2000 0x22 -#define BTTV_BOARD_CHRONOS_VS2 0x23 -#define BTTV_BOARD_TYPHOON_TVIEW 0x24 -#define BTTV_BOARD_PXELVWPLTVPRO 0x25 -#define BTTV_BOARD_MAGICTVIEW063 0x26 -#define BTTV_BOARD_PINNACLE 0x27 -#define BTTV_BOARD_STB2 0x28 -#define BTTV_BOARD_AVPHONE98 0x29 -#define BTTV_BOARD_PV951 0x2a -#define BTTV_BOARD_ONAIR_TV 0x2b -#define BTTV_BOARD_SIGMA_TVII_FM 0x2c -#define BTTV_BOARD_MATRIX_VISION2 0x2d -#define BTTV_BOARD_ZOLTRIX_GENIE 0x2e -#define BTTV_BOARD_TERRATVRADIO 0x2f -#define BTTV_BOARD_DYNALINK 0x30 -#define BTTV_BOARD_GVBCTV3PCI 0x31 -#define BTTV_BOARD_PXELVWPLTVPAK 0x32 -#define BTTV_BOARD_EAGLE 0x33 -#define BTTV_BOARD_PINNACLEPRO 0x34 -#define BTTV_BOARD_TVIEW_RDS_FM 0x35 -#define BTTV_BOARD_LIFETEC_9415 0x36 -#define BTTV_BOARD_BESTBUY_EASYTV 0x37 -#define BTTV_BOARD_FLYVIDEO_98FM 0x38 -#define BTTV_BOARD_GRANDTEC 0x39 -#define BTTV_BOARD_ASKEY_CPH060 0x3a -#define BTTV_BOARD_ASKEY_CPH03X 0x3b -#define BTTV_BOARD_MM100PCTV 0x3c -#define BTTV_BOARD_GMV1 0x3d -#define BTTV_BOARD_BESTBUY_EASYTV2 0x3e -#define BTTV_BOARD_ATI_TVWONDER 0x3f -#define BTTV_BOARD_ATI_TVWONDERVE 0x40 -#define BTTV_BOARD_FLYVIDEO2000 0x41 -#define BTTV_BOARD_TERRATVALUER 0x42 -#define BTTV_BOARD_GVBCTV4PCI 0x43 -#define BTTV_BOARD_VOODOOTV_FM 0x44 -#define BTTV_BOARD_AIMMS 0x45 -#define BTTV_BOARD_PV_BT878P_PLUS 0x46 -#define BTTV_BOARD_FLYVIDEO98EZ 0x47 -#define BTTV_BOARD_PV_BT878P_9B 0x48 -#define BTTV_BOARD_SENSORAY311 0x49 -#define BTTV_BOARD_RV605 0x4a -#define BTTV_BOARD_POWERCLR_MTV878 0x4b -#define BTTV_BOARD_WINDVR 0x4c -#define BTTV_BOARD_GRANDTEC_MULTI 0x4d -#define BTTV_BOARD_KWORLD 0x4e -#define BTTV_BOARD_DSP_TCVIDEO 0x4f -#define BTTV_BOARD_HAUPPAUGEPVR 0x50 -#define BTTV_BOARD_GVBCTV5PCI 0x51 -#define BTTV_BOARD_OSPREY1x0 0x52 -#define BTTV_BOARD_OSPREY1x0_848 0x53 -#define BTTV_BOARD_OSPREY101_848 0x54 -#define BTTV_BOARD_OSPREY1x1 0x55 -#define BTTV_BOARD_OSPREY1x1_SVID 0x56 -#define BTTV_BOARD_OSPREY2xx 0x57 -#define BTTV_BOARD_OSPREY2x0_SVID 0x58 -#define BTTV_BOARD_OSPREY2x0 0x59 -#define BTTV_BOARD_OSPREY500 0x5a -#define BTTV_BOARD_OSPREY540 0x5b -#define BTTV_BOARD_OSPREY2000 0x5c -#define BTTV_BOARD_IDS_EAGLE 0x5d -#define BTTV_BOARD_PINNACLESAT 0x5e -#define BTTV_BOARD_FORMAC_PROTV 0x5f -#define BTTV_BOARD_MACHTV 0x60 -#define BTTV_BOARD_EURESYS_PICOLO 0x61 -#define BTTV_BOARD_PV150 0x62 -#define BTTV_BOARD_AD_TVK503 0x63 -#define BTTV_BOARD_HERCULES_SM_TV 0x64 -#define BTTV_BOARD_PACETV 0x65 -#define BTTV_BOARD_IVC200 0x66 -#define BTTV_BOARD_XGUARD 0x67 -#define BTTV_BOARD_NEBULA_DIGITV 0x68 -#define BTTV_BOARD_PV143 0x69 -#define BTTV_BOARD_VD009X1_MINIDIN 0x6a -#define BTTV_BOARD_VD009X1_COMBI 0x6b -#define BTTV_BOARD_VD009_MINIDIN 0x6c -#define BTTV_BOARD_VD009_COMBI 0x6d -#define BTTV_BOARD_IVC100 0x6e -#define BTTV_BOARD_IVC120 0x6f -#define BTTV_BOARD_PC_HDTV 0x70 -#define BTTV_BOARD_TWINHAN_DST 0x71 -#define BTTV_BOARD_WINFASTVC100 0x72 -#define BTTV_BOARD_TEV560 0x73 -#define BTTV_BOARD_SIMUS_GVC1100 0x74 -#define BTTV_BOARD_NGSTV_PLUS 0x75 -#define BTTV_BOARD_LMLBT4 0x76 -#define BTTV_BOARD_TEKRAM_M205 0x77 -#define BTTV_BOARD_CONTVFMI 0x78 -#define BTTV_BOARD_PICOLO_TETRA_CHIP 0x79 -#define BTTV_BOARD_SPIRIT_TV 0x7a -#define BTTV_BOARD_AVDVBT_771 0x7b -#define BTTV_BOARD_AVDVBT_761 0x7c -#define BTTV_BOARD_MATRIX_VISIONSQ 0x7d -#define BTTV_BOARD_MATRIX_VISIONSLC 0x7e -#define BTTV_BOARD_APAC_VIEWCOMP 0x7f -#define BTTV_BOARD_DVICO_DVBT_LITE 0x80 -#define BTTV_BOARD_VGEAR_MYVCD 0x81 -#define BTTV_BOARD_SUPER_TV 0x82 -#define BTTV_BOARD_TIBET_CS16 0x83 -#define BTTV_BOARD_KODICOM_4400R 0x84 -#define BTTV_BOARD_KODICOM_4400R_SL 0x85 -#define BTTV_BOARD_ADLINK_RTV24 0x86 +#define BTTV_BOARD_UNKNOWN 0x00 +#define BTTV_BOARD_MIRO 0x01 +#define BTTV_BOARD_HAUPPAUGE 0x02 +#define BTTV_BOARD_STB 0x03 +#define BTTV_BOARD_INTEL 0x04 +#define BTTV_BOARD_DIAMOND 0x05 +#define BTTV_BOARD_AVERMEDIA 0x06 +#define BTTV_BOARD_MATRIX_VISION 0x07 +#define BTTV_BOARD_FLYVIDEO 0x08 +#define BTTV_BOARD_TURBOTV 0x09 +#define BTTV_BOARD_HAUPPAUGE878 0x0a +#define BTTV_BOARD_MIROPRO 0x0b +#define BTTV_BOARD_ADSTECH_TV 0x0c +#define BTTV_BOARD_AVERMEDIA98 0x0d +#define BTTV_BOARD_VHX 0x0e +#define BTTV_BOARD_ZOLTRIX 0x0f +#define BTTV_BOARD_PIXVIEWPLAYTV 0x10 +#define BTTV_BOARD_WINVIEW_601 0x11 +#define BTTV_BOARD_AVEC_INTERCAP 0x12 +#define BTTV_BOARD_LIFE_FLYKIT 0x13 +#define BTTV_BOARD_CEI_RAFFLES 0x14 +#define BTTV_BOARD_CONFERENCETV 0x15 +#define BTTV_BOARD_PHOEBE_TVMAS 0x16 +#define BTTV_BOARD_MODTEC_205 0x17 +#define BTTV_BOARD_MAGICTVIEW061 0x18 +#define BTTV_BOARD_VOBIS_BOOSTAR 0x19 +#define BTTV_BOARD_HAUPPAUG_WCAM 0x1a +#define BTTV_BOARD_MAXI 0x1b +#define BTTV_BOARD_TERRATV 0x1c +#define BTTV_BOARD_PXC200 0x1d +#define BTTV_BOARD_FLYVIDEO_98 0x1e +#define BTTV_BOARD_IPROTV 0x1f +#define BTTV_BOARD_INTEL_C_S_PCI 0x20 +#define BTTV_BOARD_TERRATVALUE 0x21 +#define BTTV_BOARD_WINFAST2000 0x22 +#define BTTV_BOARD_CHRONOS_VS2 0x23 +#define BTTV_BOARD_TYPHOON_TVIEW 0x24 +#define BTTV_BOARD_PXELVWPLTVPRO 0x25 +#define BTTV_BOARD_MAGICTVIEW063 0x26 +#define BTTV_BOARD_PINNACLE 0x27 +#define BTTV_BOARD_STB2 0x28 +#define BTTV_BOARD_AVPHONE98 0x29 +#define BTTV_BOARD_PV951 0x2a +#define BTTV_BOARD_ONAIR_TV 0x2b +#define BTTV_BOARD_SIGMA_TVII_FM 0x2c +#define BTTV_BOARD_MATRIX_VISION2 0x2d +#define BTTV_BOARD_ZOLTRIX_GENIE 0x2e +#define BTTV_BOARD_TERRATVRADIO 0x2f +#define BTTV_BOARD_DYNALINK 0x30 +#define BTTV_BOARD_GVBCTV3PCI 0x31 +#define BTTV_BOARD_PXELVWPLTVPAK 0x32 +#define BTTV_BOARD_EAGLE 0x33 +#define BTTV_BOARD_PINNACLEPRO 0x34 +#define BTTV_BOARD_TVIEW_RDS_FM 0x35 +#define BTTV_BOARD_LIFETEC_9415 0x36 +#define BTTV_BOARD_BESTBUY_EASYTV 0x37 +#define BTTV_BOARD_FLYVIDEO_98FM 0x38 +#define BTTV_BOARD_GRANDTEC 0x39 +#define BTTV_BOARD_ASKEY_CPH060 0x3a +#define BTTV_BOARD_ASKEY_CPH03X 0x3b +#define BTTV_BOARD_MM100PCTV 0x3c +#define BTTV_BOARD_GMV1 0x3d +#define BTTV_BOARD_BESTBUY_EASYTV2 0x3e +#define BTTV_BOARD_ATI_TVWONDER 0x3f +#define BTTV_BOARD_ATI_TVWONDERVE 0x40 +#define BTTV_BOARD_FLYVIDEO2000 0x41 +#define BTTV_BOARD_TERRATVALUER 0x42 +#define BTTV_BOARD_GVBCTV4PCI 0x43 +#define BTTV_BOARD_VOODOOTV_FM 0x44 +#define BTTV_BOARD_AIMMS 0x45 +#define BTTV_BOARD_PV_BT878P_PLUS 0x46 +#define BTTV_BOARD_FLYVIDEO98EZ 0x47 +#define BTTV_BOARD_PV_BT878P_9B 0x48 +#define BTTV_BOARD_SENSORAY311 0x49 +#define BTTV_BOARD_RV605 0x4a +#define BTTV_BOARD_POWERCLR_MTV878 0x4b +#define BTTV_BOARD_WINDVR 0x4c +#define BTTV_BOARD_GRANDTEC_MULTI 0x4d +#define BTTV_BOARD_KWORLD 0x4e +#define BTTV_BOARD_DSP_TCVIDEO 0x4f +#define BTTV_BOARD_HAUPPAUGEPVR 0x50 +#define BTTV_BOARD_GVBCTV5PCI 0x51 +#define BTTV_BOARD_OSPREY1x0 0x52 +#define BTTV_BOARD_OSPREY1x0_848 0x53 +#define BTTV_BOARD_OSPREY101_848 0x54 +#define BTTV_BOARD_OSPREY1x1 0x55 +#define BTTV_BOARD_OSPREY1x1_SVID 0x56 +#define BTTV_BOARD_OSPREY2xx 0x57 +#define BTTV_BOARD_OSPREY2x0_SVID 0x58 +#define BTTV_BOARD_OSPREY2x0 0x59 +#define BTTV_BOARD_OSPREY500 0x5a +#define BTTV_BOARD_OSPREY540 0x5b +#define BTTV_BOARD_OSPREY2000 0x5c +#define BTTV_BOARD_IDS_EAGLE 0x5d +#define BTTV_BOARD_PINNACLESAT 0x5e +#define BTTV_BOARD_FORMAC_PROTV 0x5f +#define BTTV_BOARD_MACHTV 0x60 +#define BTTV_BOARD_EURESYS_PICOLO 0x61 +#define BTTV_BOARD_PV150 0x62 +#define BTTV_BOARD_AD_TVK503 0x63 +#define BTTV_BOARD_HERCULES_SM_TV 0x64 +#define BTTV_BOARD_PACETV 0x65 +#define BTTV_BOARD_IVC200 0x66 +#define BTTV_BOARD_XGUARD 0x67 +#define BTTV_BOARD_NEBULA_DIGITV 0x68 +#define BTTV_BOARD_PV143 0x69 +#define BTTV_BOARD_VD009X1_MINIDIN 0x6a +#define BTTV_BOARD_VD009X1_COMBI 0x6b +#define BTTV_BOARD_VD009_MINIDIN 0x6c +#define BTTV_BOARD_VD009_COMBI 0x6d +#define BTTV_BOARD_IVC100 0x6e +#define BTTV_BOARD_IVC120 0x6f +#define BTTV_BOARD_PC_HDTV 0x70 +#define BTTV_BOARD_TWINHAN_DST 0x71 +#define BTTV_BOARD_WINFASTVC100 0x72 +#define BTTV_BOARD_TEV560 0x73 +#define BTTV_BOARD_SIMUS_GVC1100 0x74 +#define BTTV_BOARD_NGSTV_PLUS 0x75 +#define BTTV_BOARD_LMLBT4 0x76 +#define BTTV_BOARD_TEKRAM_M205 0x77 +#define BTTV_BOARD_CONTVFMI 0x78 +#define BTTV_BOARD_PICOLO_TETRA_CHIP 0x79 +#define BTTV_BOARD_SPIRIT_TV 0x7a +#define BTTV_BOARD_AVDVBT_771 0x7b +#define BTTV_BOARD_AVDVBT_761 0x7c +#define BTTV_BOARD_MATRIX_VISIONSQ 0x7d +#define BTTV_BOARD_MATRIX_VISIONSLC 0x7e +#define BTTV_BOARD_APAC_VIEWCOMP 0x7f +#define BTTV_BOARD_DVICO_DVBT_LITE 0x80 +#define BTTV_BOARD_VGEAR_MYVCD 0x81 +#define BTTV_BOARD_SUPER_TV 0x82 +#define BTTV_BOARD_TIBET_CS16 0x83 +#define BTTV_BOARD_KODICOM_4400R 0x84 +#define BTTV_BOARD_KODICOM_4400R_SL 0x85 +#define BTTV_BOARD_ADLINK_RTV24 0x86 #define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87 -#define BTTV_BOARD_ACORP_Y878F 0x88 -#define BTTV_BOARD_CONCEPTRONIC_CTVFMI2 0x89 -#define BTTV_BOARD_PV_BT878P_2E 0x8a -#define BTTV_BOARD_PV_M4900 0x8b -#define BTTV_BOARD_OSPREY440 0x8c +#define BTTV_BOARD_ACORP_Y878F 0x88 +#define BTTV_BOARD_CONCEPTRONIC_CTVFMI2 0x89 +#define BTTV_BOARD_PV_BT878P_2E 0x8a +#define BTTV_BOARD_PV_M4900 0x8b +#define BTTV_BOARD_OSPREY440 0x8c /* i2c address list */ #define I2C_TSA5522 0xc2 -- cgit v1.2.3 From e976f93725ce16b4a493d40a6dd3bccbd74b9a8a Mon Sep 17 00:00:00 2001 From: Kirk Lapray Date: Tue, 8 Nov 2005 21:37:04 -0800 Subject: [PATCH] v4l: 712: added analog support for ati hdtv wonder - Added analog support for ATI HDTV Wonder Signed-off-by: Kirk Lapray Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.cx88 | 1 + Documentation/video4linux/CARDLIST.tuner | 1 + drivers/media/video/cx88/cx88-cards.c | 49 ++++++++++++++++++++++++++++++++ drivers/media/video/cx88/cx88.h | 1 + drivers/media/video/tuner-simple.c | 15 +++++++++- include/media/tuner.h | 2 ++ 6 files changed, 68 insertions(+), 1 deletion(-) diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 8a14e3f44ca..ca46fbf489d 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -32,3 +32,4 @@ 31 -> DViCO FusionHDTV 5 Gold [18ac:d500] 32 -> AverMedia UltraTV Media Center PCI 550 [1461:8011] 33 -> Kworld V-Stream Xpert DVD + 34 -> ATI HDTV Wonder [1002:a101] diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index 0e2ea497ad7..ec840ca6f45 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -66,3 +66,4 @@ tuner=64 - LG TDVS-H062F/TUA6034 tuner=65 - Ymec TVF66T5-B/DFF tuner=66 - LG NTSC (TALN mini series) tuner=67 - Philips TD1316 Hybrid Tuner +tuner=68 - Philips TUV1236D ATSC/NTSC dual in diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 888d25d4841..388440789df 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -823,6 +823,35 @@ struct cx88_board cx88_boards[] = { .gpio3 = 0x00100000, }}, }, + [CX88_BOARD_ATI_HDTVWONDER] = { + .name = "ATI HDTV Wonder", + .tuner_type = TUNER_PHILIPS_TUV1236D, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x00000ff7, + .gpio1 = 0x000000ff, + .gpio2 = 0x00000001, + .gpio3 = 0x00000000, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x00000ffe, + .gpio1 = 0x000000ff, + .gpio2 = 0x00000001, + .gpio3 = 0x00000000, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x00000ffe, + .gpio1 = 0x000000ff, + .gpio2 = 0x00000001, + .gpio3 = 0x00000000, + }}, + }, }; const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); @@ -958,6 +987,10 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x1461, .subdevice = 0x8011, .card = CX88_BOARD_AVERMEDIA_ULTRATV_MC_550, + },{ + .subvendor = PCI_VENDOR_ID_ATI, + .subdevice = 0xa101, + .card = CX88_BOARD_ATI_HDTVWONDER, }, }; const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); @@ -1159,6 +1192,22 @@ void cx88_card_setup(struct cx88_core *core) cx_clear(MO_GP0_IO, 0x00000007); cx_set(MO_GP2_IO, 0x00000101); break; + case CX88_BOARD_ATI_HDTVWONDER: + if (0 == core->i2c_rc) { + /* enable tuner */ + int i; + u8 buffer[12]; + core->i2c_client.addr = 0x0a; + buffer[0] = 0x10; buffer[1] = 0x12; buffer[2] = 0x13; buffer[3] = 0x04; + buffer[4] = 0x16; buffer[5] = 0x00; buffer[6] = 0x14; buffer[7] = 0x04; + buffer[8] = 0x14; buffer[9] = 0x00; buffer[10] = 0x17; buffer[11] = 0x00; + + for (i = 0; i < 6; i++) + if (2 != i2c_master_send(&core->i2c_client,&buffer[i*2],2)) + printk(KERN_WARNING "%s: Unable to enable tuner(%i).\n", + core->name, i); + } + break; } if (cx88_boards[core->board].radio.type == CX88_RADIO) core->has_radio = 1; diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 9b629221e79..cc2197a85d0 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -176,6 +176,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD 31 #define CX88_BOARD_AVERMEDIA_ULTRATV_MC_550 32 #define CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD 33 +#define CX88_BOARD_ATI_HDTVWONDER 34 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index b75ad2d4488..e67d9e77c75 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -233,7 +233,7 @@ static struct tunertype tuners[] = { { "Ymec TVision TVF-5533MF", Philips, NTSC, 16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732}, - /* 60-67 */ + /* 60-68 */ { "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC, 16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732}, { "Tena TNF9533-D/IF/TNF9533-B/DF", Philips, PAL, @@ -250,6 +250,8 @@ static struct tunertype tuners[] = { 16*137.25,16*373.25,0x01,0x02,0x08,0x8e,732 }, { "Philips TD1316 Hybrid Tuner", Philips, PAL, 16*160.00,16*442.00,0xa1,0xa2,0xa4,0xc8,623 }, + { "Philips TUV1236D ATSC/NTSC dual in", Philips, ATSC, + 16*157.25,16*454.00,0x01,0x02,0x03,0xce,732 }, }; unsigned const int tuner_count = ARRAY_SIZE(tuners); @@ -375,6 +377,17 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) /* Set the charge pump for fast tuning */ tun->config |= TUNER_CHARGE_PUMP; break; + + case TUNER_PHILIPS_TUV1236D: + /* 0x40 -> ATSC antenna input 1 */ + /* 0x48 -> ATSC antenna input 2 */ + /* 0x00 -> NTSC antenna input 1 */ + /* 0x08 -> NTSC antenna input 2 */ + config &= ~0x40; + if (t->std & V4L2_STD_ATSC) + config |= 0x40; + /* FIXME: input */ + break; } /* diff --git a/include/media/tuner.h b/include/media/tuner.h index 97e16bddf65..7cc74b1bb6e 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -112,6 +112,8 @@ #define TUNER_LG_NTSC_TALN_MINI 66 #define TUNER_PHILIPS_TD1316 67 +#define TUNER_PHILIPS_TUV1236D 68 /* ATI HDTV Wonder */ + #define NOTUNER 0 #define PAL 1 /* PAL_BG */ #define PAL_I 2 -- cgit v1.2.3 From 5f7591c04f3797694e331a31d00317ae4acb9af0 Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:37:04 -0800 Subject: [PATCH] v4l: 713: add alsa support to saa7134 driver Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-alsa.c | 543 +++++++++++++++++++++++++++++ drivers/media/video/tda9887.c | 5 +- 2 files changed, 546 insertions(+), 2 deletions(-) create mode 100644 drivers/media/video/saa7134/saa7134-alsa.c diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c new file mode 100644 index 00000000000..d09e01f7fc3 --- /dev/null +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -0,0 +1,543 @@ +/* + * + * Support for audio capture + * PCI function #1 of the saa7134 + * + * (c) 2005 Mauro Carvalho Chehab + * (c) 2004 Gerd Knorr + * (c) 2003 Clemens Ladisch + * + * 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 option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "saa7134.h" +#include "saa7134-reg.h" + +#define dprintk(level,fmt, arg...) if (debug >= level) \ + printk(KERN_DEBUG "%s/1: " fmt, chip->core->name , ## arg) + + +/**************************************************************************** + Data type declarations - Can be moded to a header file later + ****************************************************************************/ + +#define ANALOG_CLOCK 1792000 +#define CLOCK_DIV_MIN 4 +#define CLOCK_DIV_MAX 15 +#define MAX_PCM_DEVICES 4 +#define MAX_PCM_SUBSTREAMS 16 + +enum { DEVICE_DIGITAL, DEVICE_ANALOG }; + +/* These can be replaced after done */ +#define MIXER_ADDR_LAST MAX_saa7134_INPUT + +struct saa7134_audio_dev { + struct saa7134_core *core; + struct saa7134_buffer *buf; + struct saa7134_dmaqueue q; + + /* pci i/o */ + struct pci_dev *pci; + unsigned char pci_rev,pci_lat; + + /* audio controls */ + int irq; + int dig_rate; /* Digital sampling rate */ + + snd_card_t *card; + + spinlock_t reg_lock; + + unsigned int dma_size; + unsigned int period_size; + + int mixer_volume[MIXER_ADDR_LAST+1][2]; + int capture_source[MIXER_ADDR_LAST+1][2]; + + long opened; + snd_pcm_substream_t *substream; +}; +typedef struct saa7134_audio_dev snd_saa7134_card_t; + +/**************************************************************************** + Module global static vars + ****************************************************************************/ + +static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ +static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ +static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; + +module_param_array(enable, bool, NULL, 0444); +MODULE_PARM_DESC(enable, "Enable saa7134x soundcard. default enabled."); + +/**************************************************************************** + Module macros + ****************************************************************************/ + +MODULE_DESCRIPTION("ALSA driver module for saa7134 based TV cards"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); +MODULE_LICENSE("GPL"); +MODULE_SUPPORTED_DEVICE("{{Philips, saa7131E}," + "{{Philips, saa7134}," + "{{Philips, saa7133}"); +static unsigned int debug = 0; +module_param(debug,int,0644); +MODULE_PARM_DESC(debug,"enable debug messages"); + +/**************************************************************************** + Module specific funtions + ****************************************************************************/ + +/* + * BOARD Specific: Sets audio DMA + */ + +int saa7134_start_audio_dma(snd_saa7134_card_t *chip) +{ + struct saa7134_core *core = chip->core; + + return 0; +} + +/* + * BOARD Specific: Resets audio DMA + */ +int saa7134_stop_audio_dma(snd_saa7134_card_t *chip) +{ + struct saa7134_core *core=chip->core; + return 0; +} + +#define MAX_IRQ_LOOP 10 + +static void saa713401_timeout(unsigned long data) +{ + snd_saa7134_card_t *chip = (snd_saa7134_card_t *)data; +} + +/* FIXME: Wrong values*/ +static char *saa7134_aud_irqs[32] = { + "y_risci1", "u_risci1", "v_risci1", "vbi_risc1", + "y_risci2", "u_risci2", "v_risci2", "vbi_risc2", + "y_oflow", "u_oflow", "v_oflow", "vbi_oflow", + "y_sync", "u_sync", "v_sync", "vbi_sync", + "opc_err", "par_err", "rip_err", "pci_abort", +}; + + +static void saa713401_aud_irq(snd_saa7134_card_t *chip) +{ + struct saa7134_core *core = chip->core; +} + +static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + snd_saa7134_card_t *chip = dev_id; + struct saa7134_core *core = chip->core; +} + +/**************************************************************************** + ALSA PCM Interface + ****************************************************************************/ + +/* + * Digital hardware definition + */ +static snd_pcm_hardware_t snd_saa7134_digital_hw = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = 0, /* set at runtime */ + .channels_min = 2, + .channels_max = 2, + .buffer_bytes_max = 255 * 4092, + .period_bytes_min = 32, + .period_bytes_max = 4092, + .periods_min = 2, + .periods_max = 255, +}; + +/* + * Sets board to provide digital audio + */ +static int snd_saa7134_set_digital_hw(snd_saa7134_card_t *chip, snd_pcm_runtime_t *runtime) +{ + return 0; +} + +/* + * audio open callback + */ +static int snd_saa7134_pcm_open(snd_pcm_substream_t *substream) +{ + snd_saa7134_card_t *chip = snd_pcm_substream_chip(substream); + snd_pcm_runtime_t *runtime = substream->runtime; + int err; + + if (test_and_set_bit(0, &chip->opened)) + return -EBUSY; + + err = snd_saa7134_set_digital_hw(chip, runtime); + + if (err < 0) + goto _error; + + err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) + goto _error; + + chip->substream = substream; + return 0; + +_error: + clear_bit(0, &chip->opened); + smp_mb__after_clear_bit(); + return err; +} + +/* + * audio close callback + */ +static int snd_saa7134_close(snd_pcm_substream_t *substream) +{ + snd_saa7134_card_t *chip = snd_pcm_substream_chip(substream); + + chip->substream = NULL; + clear_bit(0, &chip->opened); + smp_mb__after_clear_bit(); + return 0; +} + +/* + * hw_params callback + */ +static int snd_saa7134_hw_params(snd_pcm_substream_t * substream, + snd_pcm_hw_params_t * hw_params) +{ + return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); +} + +/* + * hw free callback + */ +static int snd_saa7134_hw_free(snd_pcm_substream_t * substream) +{ + return snd_pcm_lib_free_pages(substream); +} + +/* + * prepare callback + */ +static int snd_saa7134_prepare(snd_pcm_substream_t *substream) +{ + snd_saa7134_card_t *chip = snd_pcm_substream_chip(substream); + return 0; +} + + +/* + * trigger callback + */ +static int snd_saa7134_card_trigger(snd_pcm_substream_t *substream, int cmd) +{ + snd_saa7134_card_t *chip = snd_pcm_substream_chip(substream); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + return snd_saa7134_start(chip); + case SNDRV_PCM_TRIGGER_STOP: + return snd_saa7134_stop(chip); + default: + return -EINVAL; + } +} + +/* + * pointer callback + */ +static snd_pcm_uframes_t snd_saa7134_pointer(snd_pcm_substream_t *substream) +{ +// snd_saa7134_card_t *chip = snd_pcm_substream_chip(substream); +// snd_pcm_runtime_t *runtime = substream->runtime; + +// return (snd_pcm_uframes_t)bytes_to_frames(runtime, chip->current_line * chip->line_bytes); +} + +/* + * operators + */ +static snd_pcm_ops_t snd_saa7134_pcm_ops = { + .open = snd_saa7134_pcm_open, + .close = snd_saa7134_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = snd_saa7134_hw_params, + .hw_free = snd_saa7134_hw_free, + .prepare = snd_saa7134_prepare, + .trigger = snd_saa7134_card_trigger, + .pointer = snd_saa7134_pointer, + .page = snd_pcm_sgbuf_ops_page, +}; + +/* + * create a PCM device + */ +static int __devinit snd_saa7134_pcm(snd_saa7134_card_t *chip, int device, char *name) +{ + int err; + snd_pcm_t *pcm; + + err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm); + if (err < 0) + return err; + pcm->private_data = chip; + strcpy(pcm->name, name); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_saa7134_pcm_ops); + return snd_pcm_lib_preallocate_pages_for_all(pcm, + SNDRV_DMA_TYPE_DEV_SG, + snd_dma_pci_data(chip->pci), + 128 * 1024, + (255 * 4092 + 1023) & ~1023); +} + +/**************************************************************************** + CONTROL INTERFACE + ****************************************************************************/ +static int snd_saa7134_capture_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *info) +{ + info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + info->count = 1; + info->value.integer.min = 0; + info->value.integer.max = 0x3f; + + return 0; +} + +/* OK - TODO: test it */ +static int snd_saa7134_capture_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value) +{ + snd_saa7134_card_t *chip = snd_kcontrol_chip(kcontrol); + struct saa7134_core *core=chip->core; + + return 0; +} + +/* OK - TODO: test it */ +static int snd_saa7134_capture_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value) +{ + snd_saa7134_card_t *chip = snd_kcontrol_chip(kcontrol); + struct saa7134_core *core=chip->core; + + return 0; +} + +static snd_kcontrol_new_t snd_saa7134_capture_volume = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Capture Volume", + .info = snd_saa7134_capture_volume_info, + .get = snd_saa7134_capture_volume_get, + .put = snd_saa7134_capture_volume_put, +}; + +/* + *************************************** + */ + +/**************************************************************************** + Basic Flow for Sound Devices + ****************************************************************************/ + +/* + * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio + * Only boards with eeprom and byte 1 at eeprom=1 have it + */ + +struct pci_device_id saa7134_audio_pci_tbl[] = { + {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, + {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, + {0, } +}; +MODULE_DEVICE_TABLE(pci, saa7134_audio_pci_tbl); + +/* + * Chip-specific destructor + */ + +static int snd_saa7134_free(snd_saa7134_card_t *chip) +{ + if (chip->irq >= 0) + free_irq(chip->irq, chip); + + /* free memory */ + saa7134_core_put(chip->core,chip->pci); + + pci_release_regions(chip->pci); + pci_disable_device(chip->pci); + + kfree(chip); + return 0; +} + +/* + * Component Destructor + */ +static int snd_saa7134_dev_free(snd_device_t *device) +{ + snd_saa7134_card_t *chip = device->device_data; + return snd_saa7134_free(chip); +} + + +/* + * Alsa Constructor - Component probe + */ + +static int devno=0; +static int __devinit snd_saa7134_create(snd_card_t *card, struct pci_dev *pci, + snd_saa7134_card_t **rchip) +{ + snd_saa7134_card_t *chip; + struct saa7134_core *core; + return 0; +} + +static int __devinit saa7134_audio_initdev(struct pci_dev *pci, + const struct pci_device_id *pci_id) +{ + snd_card_t *card; + snd_saa7134_card_t *chip; + int err; + + if (devno >= SNDRV_CARDS) + return (-ENODEV); + + if (!enable[devno]) { + ++devno; + return (-ENOENT); + } + + card = snd_card_new(index[devno], id[devno], THIS_MODULE, 0); + if (!card) + return (-ENOMEM); + + err = snd_saa7134_create(card, pci, &chip); + if (err < 0) + return (err); + +/* + err = snd_saa7134_pcm(chip, DEVICE_DIGITAL, "saa7134 Digital"); + if (err < 0) + goto fail_free; +*/ + err = snd_ctl_add(card, snd_ctl_new1(&snd_saa7134_capture_volume, chip)); + if (err < 0) { + snd_card_free(card); + return (err); + } + + strcpy (card->driver, "saa7134_ALSA"); + sprintf(card->shortname, "Saa7134 %x", pci->device); + sprintf(card->longname, "%s at %#lx", + card->shortname, pci_resource_start(pci, 0)); + strcpy (card->mixername, "saa7134"); + + dprintk (0, "%s/%i: Alsa support for saa7134x boards\n", + card->driver,devno); + + err = snd_card_register(card); + if (err < 0) { + snd_card_free(card); + return (err); + } + + pci_set_drvdata(pci,card); + + devno++; + return 0; +} +/* + * ALSA destructor + */ +static void __devexit saa7134_audio_finidev(struct pci_dev *pci) +{ + snd_card_free(pci_get_drvdata(pci)); + pci_set_drvdata(pci, NULL); + + devno--; +} + +/* + * PCI driver definition + */ + +static struct pci_driver saa7134_audio_pci_driver = { + .name = "saa7134_audio", + .id_table = saa7134_audio_pci_tbl, + .probe = saa7134_audio_initdev, + .remove = saa7134_audio_finidev, + SND_PCI_PM_CALLBACKS +}; + +/**************************************************************************** + LINUX MODULE INIT + ****************************************************************************/ + +/* + * module init + */ +static int saa7134_audio_init(void) +{ + printk(KERN_INFO "saa7134x alsa driver version %d.%d.%d loaded\n", + (saa7134_VERSION_CODE >> 16) & 0xff, + (saa7134_VERSION_CODE >> 8) & 0xff, + saa7134_VERSION_CODE & 0xff); +#ifdef SNAPSHOT + printk(KERN_INFO "saa7134x: snapshot date %04d-%02d-%02d\n", + SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); +#endif + return pci_module_init(&saa7134_audio_pci_driver); +} + +/* + * module remove + */ +static void saa7134_audio_fini(void) +{ + pci_unregister_driver(&saa7134_audio_pci_driver); +} + +module_init(saa7134_audio_init); +module_exit(saa7134_audio_fini); + +/* ----------------------------------------------------------- */ +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 94053f149dd..10f14bc23ed 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -180,7 +180,8 @@ static struct tvnorm tvnorms[] = { .name = "SECAM-L", .b = ( cPositiveAmTV | cQSS ), - .e = ( cAudioIF_6_5 | + .e = ( cGaiting_36 | + cAudioIF_6_5 | cVideoIF_38_90 ), },{ .std = V4L2_STD_SECAM_DK, @@ -329,7 +330,7 @@ static void dump_write_message(unsigned char *buf) printk(PREFIX "write: byte E 0x%02x\n",buf[3]); printk(" E0-1 sound carrier : %s\n", carrier[(buf[3] & 0x03)]); - printk(" E6 l pll ganting : %s\n", + printk(" E6 l pll gaiting : %s\n", (buf[3] & 0x40) ? "36" : "13"); if (buf[1] & 0x08) { -- cgit v1.2.3 From 3375c39844b58ad8a5d9f454fa908d722a94a5a4 Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:37:05 -0800 Subject: [PATCH] v4l: 714: fix typo - Fix typo. Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tda9887.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 10f14bc23ed..ba22f12e8b3 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -180,7 +180,7 @@ static struct tvnorm tvnorms[] = { .name = "SECAM-L", .b = ( cPositiveAmTV | cQSS ), - .e = ( cGaiting_36 | + .e = ( cGating_36 | cAudioIF_6_5 | cVideoIF_38_90 ), },{ @@ -330,7 +330,7 @@ static void dump_write_message(unsigned char *buf) printk(PREFIX "write: byte E 0x%02x\n",buf[3]); printk(" E0-1 sound carrier : %s\n", carrier[(buf[3] & 0x03)]); - printk(" E6 l pll gaiting : %s\n", + printk(" E6 l pll gating : %s\n", (buf[3] & 0x40) ? "36" : "13"); if (buf[1] & 0x08) { -- cgit v1.2.3 From 4b017415fc9ab63f7c0e49aced5e403c18d55659 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:37:06 -0800 Subject: [PATCH] v4l: 715: enable s video input on dvico fusionhdtv5 lite - Enable S-Video input on DViCO FusionHDTV5 Lite Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bttv-cards.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 1f33764bf05..77f0ff8a4e4 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -2679,10 +2679,10 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_LG_TDVS_H062F, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .video_inputs = 2, + .video_inputs = 3, .audio_inputs = 1, .svhs = 2, - .muxsel = { 2, 3 }, + .muxsel = { 2, 3, 1 }, .gpiomask = 0x00e00007, .audiomux = { 0x00400005, 0, 0x00000001, 0, 0x00c00007, 0 }, .no_msp34xx = 1, -- cgit v1.2.3 From a6c2ba283565dbc9f055dcb2ecba1971460bb535 Mon Sep 17 00:00:00 2001 From: "akpm@osdl.org" Date: Tue, 8 Nov 2005 21:37:07 -0800 Subject: [PATCH] v4l: 716: support for em28xx board family - Added support for em28xx board family Signed-off-by: Ludovico Cavedon Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-cards.c | 168 +++ drivers/media/video/em28xx/em28xx-core.c | 807 +++++++++++++ drivers/media/video/em28xx/em28xx-i2c.c | 443 +++++++ drivers/media/video/em28xx/em28xx-video.c | 1815 +++++++++++++++++++++++++++++ drivers/media/video/em28xx/em28xx.h | 479 ++++++++ drivers/media/video/tvp5150.c | 337 ++++-- 6 files changed, 3938 insertions(+), 111 deletions(-) create mode 100644 drivers/media/video/em28xx/em28xx-cards.c create mode 100644 drivers/media/video/em28xx/em28xx-core.c create mode 100644 drivers/media/video/em28xx/em28xx-i2c.c create mode 100644 drivers/media/video/em28xx/em28xx-video.c create mode 100644 drivers/media/video/em28xx/em28xx.h diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c new file mode 100644 index 00000000000..b6d89decfbd --- /dev/null +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -0,0 +1,168 @@ +/* + em2820-cards.c - driver for Empia EM2820/2840 USB video capture devices + + Copyright (C) 2005 Markus Rechberger + Ludovico Cavedon + Mauro Carvalho Chehab + + Based on the em2800 driver from Sascha Sommer + + 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 option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "audiochip.h" +#include "tveeprom.h" +#include "msp3400.h" + +#include "em2820.h" + +enum em2820_board_entry { + EM2820_BOARD_TERRATEC_CINERGY_250, + EM2820_BOARD_PINNACLE_USB_2, + EM2820_BOARD_HAUPPAUGE_WINTV_USB_2, + EM2820_BOARD_MSI_VOX_USB_2 +}; + +struct em2820_board em2820_boards[] = { + [EM2820_BOARD_TERRATEC_CINERGY_250] = { + .name = "Terratec Cinergy 250 USB", + .vchannels = 3, + .norm = VIDEO_MODE_PAL, + .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .tda9887_conf = TDA9887_PRESENT, + .has_tuner = 1, + .decoder = EM2820_SAA7113, + .input = {{ + .type = EM2820_VMUX_TELEVISION, + .vmux = 2, + .amux = 0, + },{ + .type = EM2820_VMUX_COMPOSITE1, + .vmux = 0, + .amux = 1, + },{ + .type = EM2820_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, + [EM2820_BOARD_PINNACLE_USB_2] = { + .name = "Pinnacle PCTV USB 2", + .vchannels = 3, + .norm = VIDEO_MODE_PAL, + .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .tda9887_conf = TDA9887_PRESENT, + .has_tuner = 1, + .decoder = EM2820_SAA7113, + .input = {{ + .type = EM2820_VMUX_TELEVISION, + .vmux = 2, + .amux = 0, + },{ + .type = EM2820_VMUX_COMPOSITE1, + .vmux = 0, + .amux = 1, + },{ + .type = EM2820_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, + [EM2820_BOARD_HAUPPAUGE_WINTV_USB_2] = { + .name = "Hauppauge WinTV USB 2", + .vchannels = 3, + .norm = VIDEO_MODE_NTSC, + .tuner_type = TUNER_PHILIPS_FM1236_MK3, + .tda9887_conf = TDA9887_PRESENT|TDA9887_PORT1_ACTIVE|TDA9887_PORT2_ACTIVE, + .has_tuner = 1, + .decoder = EM2820_TVP5150, + .has_msp34xx = 1, + /*FIXME: S-Video not tested */ + .input = {{ + .type = EM2820_VMUX_TELEVISION, + .vmux = 0, + .amux = 0, + },{ + .type = EM2820_VMUX_SVIDEO, + .vmux = 2, + .amux = 1, + }}, + }, + [EM2820_BOARD_MSI_VOX_USB_2] = { + .name = "MSI VOX USB 2.0", + .vchannels = 3, + .norm = VIDEO_MODE_PAL, + .tuner_type = TUNER_PHILIPS_PAL, + .tda9887_conf = TDA9887_PRESENT|TDA9887_PORT1_ACTIVE|TDA9887_PORT2_ACTIVE, + .has_tuner = 1, + .decoder = EM2820_SAA7114, + .input = {{ + .type = EM2820_VMUX_TELEVISION, + .vmux = 2, + .amux = 0, + },{ + .type = EM2820_VMUX_COMPOSITE1, + .vmux = 0, + .amux = 1, + },{ + .type = EM2820_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, + { } /* Terminating entry */ +}; + +/* table of devices that work with this driver */ +struct usb_device_id em2820_id_table [] = { + /* Terratec Cinerhy 200 USB: em2800 nor supported, at the moment */ + /* { USB_DEVICE(0xeb1a, 0x2800), .driver_info = EM2800_BOARD_TERRATEC_CINERGY_200 }, */ + { USB_DEVICE(0x0ccd, 0x0036), .driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 }, + { USB_DEVICE(0x2304, 0x0208), .driver_info = EM2820_BOARD_PINNACLE_USB_2 }, + { USB_DEVICE(0x2040, 0x4200), .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, + { USB_DEVICE(0xeb1a, 0x2820), .driver_info = EM2820_BOARD_MSI_VOX_USB_2 }, + { }, +}; + +void em2820_card_setup(struct em2820 *dev) +{ + /* request some modules */ + if (dev->model == EM2820_BOARD_HAUPPAUGE_WINTV_USB_2) { + struct tveeprom tv; +#ifdef CONFIG_MODULES + request_module("tveeprom"); +#endif + /* Call first TVeeprom */ + + tveeprom_hauppauge_analog(&dev->i2c_client, &tv, dev->eedata); + + dev->tuner_type= tv.tuner_type; + if (tv.audio_processor == AUDIO_CHIP_MSP34XX) { + dev->has_msp34xx=1; + } else dev->has_msp34xx=0; + } +} + +EXPORT_SYMBOL(em2820_boards); +EXPORT_SYMBOL(em2820_id_table); + +MODULE_DEVICE_TABLE (usb, em2820_id_table); diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c new file mode 100644 index 00000000000..a75a91da70e --- /dev/null +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -0,0 +1,807 @@ +/* + em2820-core.c - driver for Empia EM2820/2840 USB video capture devices + + Copyright (C) 2005 Markus Rechberger + Ludovico Cavedon + Mauro Carvalho Chehab + + Based on the em2800 driver from Sascha Sommer + + 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 option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "em2820.h" + +/* #define ENABLE_DEBUG_ISOC_FRAMES */ + +unsigned int core_debug = 0; +module_param(core_debug,int,0644); +MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); + +#define em2820_coredbg(fmt, arg...) do {\ + if (core_debug) \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __FUNCTION__ , ##arg); } while (0) + +unsigned int reg_debug = 0; +module_param(reg_debug,int,0644); +MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); + +#define em2820_regdbg(fmt, arg...) do {\ + if (reg_debug) \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __FUNCTION__ , ##arg); } while (0) + +unsigned int isoc_debug = 0; +module_param(isoc_debug,int,0644); +MODULE_PARM_DESC(core_debug,"enable debug messages [isoc transfers]"); + +#define em2820_isocdbg(fmt, arg...) do {\ + if (isoc_debug) \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __FUNCTION__ , ##arg); } while (0) + +static int alt = EM2820_PINOUT; +module_param(alt, int, 0644); +MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint"); + +/* ------------------------------------------------------------------ */ +/* debug help functions */ + +static const char *v4l1_ioctls[] = { + "0", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT", + "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ", + "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT", + "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO", + "SMICROCODE", "GVBIFMT", "SVBIFMT" }; +#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls) + +static const char *v4l2_ioctls[] = { + "QUERYCAP", "1", "ENUM_PIXFMT", "ENUM_FBUFFMT", "G_FMT", "S_FMT", + "G_COMP", "S_COMP", "REQBUFS", "QUERYBUF", "G_FBUF", "S_FBUF", + "G_WIN", "S_WIN", "PREVIEW", "QBUF", "16", "DQBUF", "STREAMON", + "STREAMOFF", "G_PERF", "G_PARM", "S_PARM", "G_STD", "S_STD", + "ENUMSTD", "ENUMINPUT", "G_CTRL", "S_CTRL", "G_TUNER", "S_TUNER", + "G_FREQ", "S_FREQ", "G_AUDIO", "S_AUDIO", "35", "QUERYCTRL", + "QUERYMENU", "G_INPUT", "S_INPUT", "ENUMCVT", "41", "42", "43", + "44", "45", "G_OUTPUT", "S_OUTPUT", "ENUMOUTPUT", "G_AUDOUT", + "S_AUDOUT", "ENUMFX", "G_EFFECT", "S_EFFECT", "G_MODULATOR", + "S_MODULATOR" +}; +#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) + +void em2820_print_ioctl(char *name, unsigned int cmd) +{ + char *dir; + + switch (_IOC_DIR(cmd)) { + case _IOC_NONE: dir = "--"; break; + case _IOC_READ: dir = "r-"; break; + case _IOC_WRITE: dir = "-w"; break; + case _IOC_READ | _IOC_WRITE: dir = "rw"; break; + default: dir = "??"; break; + } + switch (_IOC_TYPE(cmd)) { + case 'v': + printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l1, %s, VIDIOC%s)\n", + name, cmd, dir, (_IOC_NR(cmd) < V4L1_IOCTLS) ? + v4l1_ioctls[_IOC_NR(cmd)] : "???"); + break; + case 'V': + printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l2, %s, VIDIOC_%s)\n", + name, cmd, dir, (_IOC_NR(cmd) < V4L2_IOCTLS) ? + v4l2_ioctls[_IOC_NR(cmd)] : "???"); + break; + default: + printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n", + name, cmd, dir, _IOC_NR(cmd)); + } +} + +static void *rvmalloc(size_t size) +{ + void *mem; + unsigned long adr; + + size = PAGE_ALIGN(size); + + mem = vmalloc_32((unsigned long)size); + if (!mem) + return NULL; + + memset(mem, 0, size); + + adr = (unsigned long)mem; + while (size > 0) { + SetPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + + return mem; +} + +static void rvfree(void *mem, size_t size) +{ + unsigned long adr; + + if (!mem) + return; + + size = PAGE_ALIGN(size); + + adr = (unsigned long)mem; + while (size > 0) { + ClearPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + + vfree(mem); +} + +/* + * em2820_request_buffers() + * allocate a number of buffers + */ +u32 em2820_request_buffers(struct em2820 *dev, u32 count) +{ + const size_t imagesize = PAGE_ALIGN(dev->frame_size); /*needs to be page aligned cause the buffers can be mapped individually! */ + void *buff = NULL; + u32 i; + em2820_coredbg("requested %i buffers with size %i", count, imagesize); + if (count > EM2820_NUM_FRAMES) + count = EM2820_NUM_FRAMES; + + dev->num_frames = count; + while (dev->num_frames > 0) { + if ((buff = rvmalloc(dev->num_frames * imagesize))) + break; + dev->num_frames--; + } + + for (i = 0; i < dev->num_frames; i++) { + dev->frame[i].bufmem = buff + i * imagesize; + dev->frame[i].buf.index = i; + dev->frame[i].buf.m.offset = i * imagesize; + dev->frame[i].buf.length = dev->frame_size; + dev->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + dev->frame[i].buf.sequence = 0; + dev->frame[i].buf.field = V4L2_FIELD_NONE; + dev->frame[i].buf.memory = V4L2_MEMORY_MMAP; + dev->frame[i].buf.flags = 0; + } + return dev->num_frames; +} + +/* + * em2820_queue_unusedframes() + * add all frames that are not currently in use to the inbuffer queue + */ +void em2820_queue_unusedframes(struct em2820 *dev) +{ + unsigned long lock_flags; + u32 i; + + for (i = 0; i < dev->num_frames; i++) + if (dev->frame[i].state == F_UNUSED) { + dev->frame[i].state = F_QUEUED; + spin_lock_irqsave(&dev->queue_lock, lock_flags); + list_add_tail(&dev->frame[i].frame, &dev->inqueue); + spin_unlock_irqrestore(&dev->queue_lock, lock_flags); + } +} + +/* + * em2820_release_buffers() + * free frame buffers + */ +void em2820_release_buffers(struct em2820 *dev) +{ + if (dev->num_frames) { + rvfree(dev->frame[0].bufmem, + dev->num_frames * PAGE_ALIGN(dev->frame[0].buf.length)); + dev->num_frames = 0; + } +} + +/* + * em2820_read_reg_req() + * reads data from the usb device specifying bRequest + */ +int em2820_read_reg_req_len(struct em2820 *dev, u8 req, u16 reg, + char *buf, int len) +{ + int ret, byte; + + em2820_regdbg("req=%02x, reg=%02x ", req, reg); + + ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0x0000, reg, buf, len, HZ); + + if (reg_debug){ + printk(ret < 0 ? " failed!\n" : "%02x values: ", ret); + for (byte = 0; byte < len; byte++) { + printk(" %02x", buf[byte]); + } + printk("\n"); + } + + return ret; +} + +/* + * em2820_read_reg_req() + * reads data from the usb device specifying bRequest + */ +int em2820_read_reg_req(struct em2820 *dev, u8 req, u16 reg) +{ + u8 val; + int ret; + + em2820_regdbg("req=%02x, reg=%02x:", req, reg); + + ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0x0000, reg, &val, 1, HZ); + + if (reg_debug) + printk(ret < 0 ? " failed!\n" : "%02x\n", val); + + if (ret < 0) + return ret; + + return val; +} + +int em2820_read_reg(struct em2820 *dev, u16 reg) +{ + return em2820_read_reg_req(dev, USB_REQ_GET_STATUS, reg); +} + +/* + * em2820_write_regs_req() + * sends data to the usb device, specifying bRequest + */ +int em2820_write_regs_req(struct em2820 *dev, u8 req, u16 reg, char *buf, + int len) +{ + int ret; + + /*usb_control_msg seems to expect a kmalloced buffer */ + unsigned char *bufs = kmalloc(len, GFP_KERNEL); + + em2820_regdbg("req=%02x reg=%02x:", req, reg); + + if (reg_debug) { + int i; + for (i = 0; i < len; ++i) + printk (" %02x", (unsigned char)buf[i]); + printk ("\n"); + } + + if (!bufs) + return -ENOMEM; + memcpy(bufs, buf, len); + ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0x0000, reg, bufs, len, HZ); + mdelay(5); /* FIXME: magic number */ + kfree(bufs); + return ret; +} + +int em2820_write_regs(struct em2820 *dev, u16 reg, char *buf, int len) +{ + return em2820_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len); +} + +/* + * em2820_write_reg_bits() + * sets only some bits (specified by bitmask) of a register, by first reading + * the actual value + */ +int em2820_write_reg_bits(struct em2820 *dev, u16 reg, u8 val, + u8 bitmask) +{ + int oldval; + u8 newval; + if ((oldval = em2820_read_reg(dev, reg)) < 0) + return oldval; + newval = (((u8) oldval) & ~bitmask) | (val & bitmask); + return em2820_write_regs(dev, reg, &newval, 1); +} + +/* + * em2820_write_ac97() + * write a 16 bit value to the specified AC97 address (LSB first!) + */ +int em2820_write_ac97(struct em2820 *dev, u8 reg, u8 * val) +{ + int ret; + u8 addr = reg & 0x7f; + if ((ret = em2820_write_regs(dev, AC97LSB_REG, val, 2)) < 0) + return ret; + if ((ret = em2820_write_regs(dev, AC97ADDR_REG, &addr, 1)) < 0) + return ret; + if ((ret = em2820_read_reg(dev, AC97BUSY_REG)) < 0) + return ret; + else if (((u8) ret) & 0x01) { + em2820_warn ("AC97 command still being exectuted: not handled properly!\n"); + } + return 0; +} + +int em2820_audio_analog_set(struct em2820 *dev) +{ + char s[2] = { 0x00, 0x00 }; + s[0] |= 0x1f - dev->volume; + s[1] |= 0x1f - dev->volume; + if (dev->mute) + s[1] |= 0x80; + return em2820_write_ac97(dev, MASTER_AC97, s); +} + + +int em2820_colorlevels_set_default(struct em2820 *dev) +{ + em2820_write_regs(dev, YGAIN_REG, "\x10", 1); /* contrast */ + em2820_write_regs(dev, YOFFSET_REG, "\x00", 1); /* brightness */ + em2820_write_regs(dev, UVGAIN_REG, "\x10", 1); /* saturation */ + em2820_write_regs(dev, UOFFSET_REG, "\x00", 1); + em2820_write_regs(dev, VOFFSET_REG, "\x00", 1); + em2820_write_regs(dev, SHARPNESS_REG, "\x00", 1); + + em2820_write_regs(dev, GAMMA_REG, "\x20", 1); + em2820_write_regs(dev, RGAIN_REG, "\x20", 1); + em2820_write_regs(dev, GGAIN_REG, "\x20", 1); + em2820_write_regs(dev, BGAIN_REG, "\x20", 1); + em2820_write_regs(dev, ROFFSET_REG, "\x00", 1); + em2820_write_regs(dev, GOFFSET_REG, "\x00", 1); + return em2820_write_regs(dev, BOFFSET_REG, "\x00", 1); +} + +int em2820_capture_start(struct em2820 *dev, int start) +{ + int ret; + /* FIXME: which is the best order? */ + /* video registers are sampled by VREF */ + if ((ret = em2820_write_reg_bits(dev, USBSUSP_REG, start ? 0x10 : 0x00, + 0x10)) < 0) + return ret; + /* enable video capture */ + return em2820_write_regs(dev, VINENABLE_REG, start ? "\x67" : "\x27", 1); +} + +int em2820_outfmt_set_yuv422(struct em2820 *dev) +{ + em2820_write_regs(dev, OUTFMT_REG, "\x34", 1); + em2820_write_regs(dev, VINMODE_REG, "\x10", 1); + return em2820_write_regs(dev, VINCTRL_REG, "\x11", 1); +} + +int em2820_accumulator_set(struct em2820 *dev, u8 xmin, u8 xmax, u8 ymin, + u8 ymax) +{ + em2820_coredbg("em2820 Scale: (%d,%d)-(%d,%d)\n", xmin, ymin, xmax, ymax); + + em2820_write_regs(dev, XMIN_REG, &xmin, 1); + em2820_write_regs(dev, XMAX_REG, &xmax, 1); + em2820_write_regs(dev, YMIN_REG, &ymin, 1); + return em2820_write_regs(dev, YMAX_REG, &ymax, 1); +} + +int em2820_capture_area_set(struct em2820 *dev, u8 hstart, u8 vstart, + u16 width, u16 height) +{ + u8 cwidth = width; + u8 cheight = height; + u8 overflow = (height >> 7 & 0x02) | (width >> 8 & 0x01); + + em2820_coredbg("em2820 Area Set: (%d,%d)\n", (width | (overflow & 2) << 7), + (height | (overflow & 1) << 8)); + + em2820_write_regs(dev, HSTART_REG, &hstart, 1); + em2820_write_regs(dev, VSTART_REG, &vstart, 1); + em2820_write_regs(dev, CWIDTH_REG, &cwidth, 1); + em2820_write_regs(dev, CHEIGHT_REG, &cheight, 1); + return em2820_write_regs(dev, OFLOW_REG, &overflow, 1); +} + +int em2820_scaler_set(struct em2820 *dev, u16 h, u16 v) +{ + u8 buf[2]; + buf[0] = h; + buf[1] = h >> 8; + em2820_write_regs(dev, HSCALELOW_REG, (char *)buf, 2); + buf[0] = v; + buf[1] = v >> 8; + em2820_write_regs(dev, VSCALELOW_REG, (char *)buf, 2); + /* when H and V mixershould be used? */ + /* return em2820_write_reg_bits(dev, COMPR_REG, (h ? 0x20 : 0x00) | (v ? 0x10 : 0x00), 0x30); */ + /* it seems that both H and V scalers must be active to work correctly */ + return em2820_write_reg_bits(dev, COMPR_REG, h + || v ? 0x30 : 0x00, 0x30); +} + +/* FIXME: this only function read values from dev */ +int em2820_resolution_set(struct em2820 *dev) +{ + int width, height; + width = norm_maxw(dev); + height = norm_maxh(dev) >> 1; + + em2820_outfmt_set_yuv422(dev); + em2820_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); + em2820_capture_area_set(dev, 0, 0, width >> 2, height >> 2); + return em2820_scaler_set(dev, dev->hscale, dev->vscale); +} + + +/******************* isoc transfer handling ****************************/ + +#ifdef ENABLE_DEBUG_ISOC_FRAMES +static void em2820_isoc_dump(struct urb *urb, struct pt_regs *regs) +{ + int len = 0; + int ntrans = 0; + int i; + + printk(KERN_DEBUG "isocIrq: sf=%d np=%d ec=%x\n", + urb->start_frame, urb->number_of_packets, + urb->error_count); + for (i = 0; i < urb->number_of_packets; i++) { + unsigned char *buf = + urb->transfer_buffer + + urb->iso_frame_desc[i].offset; + int alen = urb->iso_frame_desc[i].actual_length; + if (alen > 0) { + if (buf[0] == 0x88) { + ntrans++; + len += alen; + } else if (buf[0] == 0x22) { + printk(KERN_DEBUG + "= l=%d nt=%d bpp=%d\n", + len - 4 * ntrans, ntrans, + ntrans == 0 ? 0 : len / ntrans); + ntrans = 1; + len = alen; + } else + printk(KERN_DEBUG "!\n"); + } + printk(KERN_DEBUG " n=%d s=%d al=%d %x\n", i, + urb->iso_frame_desc[i].status, + urb->iso_frame_desc[i].actual_length, + (unsigned int) + *((unsigned char *)(urb->transfer_buffer + + urb->iso_frame_desc[i]. + offset))); + } +} +#endif + +static inline int em2820_isoc_video(struct em2820 *dev,struct em2820_frame_t **f, + unsigned long *lock_flags, unsigned char buf) +{ + if (!(buf & 0x01)) { + if ((*f)->state == F_GRABBING) { + /*previous frame is incomplete */ + if ((*f)->fieldbytesused < dev->field_size) { + (*f)->state = F_ERROR; + em2820_isocdbg ("dropping incomplete bottom field (%i missing bytes)", + dev->field_size-(*f)->fieldbytesused); + } else { + (*f)->state = F_DONE; + (*f)->buf.bytesused = dev->frame_size; + } + } + if ((*f)->state == F_DONE || (*f)->state == F_ERROR) { + /* move current frame to outqueue and get next free buffer from inqueue */ + spin_lock_irqsave(&dev-> queue_lock, *lock_flags); + list_move_tail(&(*f)->frame, &dev->outqueue); + if (!list_empty(&dev->inqueue)) + (*f) = list_entry(dev-> inqueue.next, + struct em2820_frame_t,frame); + else + (*f) = NULL; + spin_unlock_irqrestore(&dev->queue_lock,*lock_flags); + } + if (!(*f)) { + em2820_isocdbg ("new frame but no buffer is free"); + return -1; + } + do_gettimeofday(&(*f)->buf.timestamp); + (*f)->buf.sequence = ++dev->frame_count; + (*f)->buf.field = V4L2_FIELD_INTERLACED; + (*f)->state = F_GRABBING; + (*f)->buf.bytesused = 0; + (*f)->top_field = 1; + (*f)->fieldbytesused = 0; + } else { + /* acquiring bottom field */ + if ((*f)->state == F_GRABBING) { + if (!(*f)->top_field) { + (*f)->state = F_ERROR; + em2820_isocdbg ("unexpected begin of bottom field; discarding it"); + } else if ((*f)-> fieldbytesused < dev->field_size - 172) { + (*f)->state = F_ERROR; + em2820_isocdbg ("dropping incomplete top field (%i missing bytes)", + dev->field_size-(*f)->fieldbytesused); + } else { + (*f)->top_field = 0; + (*f)->fieldbytesused = 0; + } + } + } + return (0); +} + +static inline void em2820_isoc_video_copy(struct em2820 *dev, + struct em2820_frame_t **f, unsigned char *buf, int len) +{ + void *fieldstart, *startwrite, *startread; + int linesdone, currlinedone, offset, lencopy,remain; + + if ((*f)->fieldbytesused + len > dev->field_size) + len =dev->field_size - (*f)->fieldbytesused; + remain = len; + startread = buf + 4; + if ((*f)->top_field) + fieldstart = (*f)->bufmem; + else + fieldstart = (*f)->bufmem + dev->bytesperline; + + linesdone = (*f)->fieldbytesused / dev->bytesperline; + currlinedone = (*f)->fieldbytesused % dev->bytesperline; + offset = linesdone * dev->bytesperline * 2 + currlinedone; + startwrite = fieldstart + offset; + lencopy = dev->bytesperline - currlinedone; + lencopy = lencopy > remain ? remain : lencopy; + + memcpy(startwrite, startread, lencopy); + remain -= lencopy; + + while (remain > 0) { + startwrite += lencopy + dev->bytesperline; + startread += lencopy; + if (dev->bytesperline > remain) + lencopy = remain; + else + lencopy = dev->bytesperline; + + memcpy(startwrite, startread, lencopy); + remain -= lencopy; + } + + (*f)->fieldbytesused += len; +} + +/* + * em2820_isoIrq() + * handles the incoming isoc urbs and fills the frames from our inqueue + */ +void em2820_isocIrq(struct urb *urb, struct pt_regs *regs) +{ + struct em2820 *dev = urb->context; + int i, status; + struct em2820_frame_t **f; + unsigned long lock_flags; + + if (!dev) + return; +#ifdef ENABLE_DEBUG_ISOC_FRAMES + if (isoc_debug>1) + em2820_isoc_dump(urb, regs); +#endif + + if (urb->status == -ENOENT) + return; + + f = &dev->frame_current; + + if (dev->stream == STREAM_INTERRUPT) { + dev->stream = STREAM_OFF; + if ((*f)) + (*f)->state = F_QUEUED; + em2820_isocdbg("stream interrupted"); + wake_up_interruptible(&dev->wait_stream); + } + + if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) + return; + + if (dev->stream == STREAM_ON && !list_empty(&dev->inqueue)) { + if (!(*f)) + (*f) = list_entry(dev->inqueue.next, + struct em2820_frame_t, frame); + + for (i = 0; i < urb->number_of_packets; i++) { + unsigned char *buf = urb->transfer_buffer + + urb->iso_frame_desc[i].offset; + int len = urb->iso_frame_desc[i].actual_length - 4; + + if (urb->iso_frame_desc[i].status) { + em2820_isocdbg("data error: [%d] len=%d, status=%d", i, + urb->iso_frame_desc[i].actual_length, + urb->iso_frame_desc[i].status); + continue; + } + if (urb->iso_frame_desc[i].actual_length <= 0) { + em2820_isocdbg("packet %d is empty",i); + continue; + } + if (urb->iso_frame_desc[i].actual_length > + dev->max_pkt_size) { + em2820_isocdbg("packet bigger than packet size"); + continue; + } + /*new frame */ + if (buf[0] == 0x22 && buf[1] == 0x5a) { + em2820_isocdbg("Video frame, length=%i!",len); + + if (em2820_isoc_video(dev,f,&lock_flags,buf[2])) + break; + } else if (buf[0]==0x33 && buf[1]==0x95 && buf[2]==0x00) { + em2820_isocdbg("VBI HEADER!!!"); + } + + /* actual copying */ + if ((*f)->state == F_GRABBING) { + em2820_isoc_video_copy(dev,f,buf, len); + } + } + } + + for (i = 0; i < urb->number_of_packets; i++) { + urb->iso_frame_desc[i].status = 0; + urb->iso_frame_desc[i].actual_length = 0; + } + + urb->status = 0; + if ((status = usb_submit_urb(urb, GFP_ATOMIC))) { + em2820_errdev("resubmit of urb failed (error=%i)\n", status); + dev->state |= DEV_MISCONFIGURED; + } + wake_up_interruptible(&dev->wait_frame); + return; +} + +/* + * em2820_uninit_isoc() + * deallocates the buffers and urbs allocated during em2820_init_iosc() + */ +void em2820_uninit_isoc(struct em2820 *dev) +{ + int i; + + for (i = 0; i < EM2820_NUM_BUFS; i++) { + if (dev->urb[i]) { + usb_kill_urb(dev->urb[i]); + usb_free_urb(dev->urb[i]); + } + dev->urb[i] = NULL; + if (dev->transfer_buffer[i]) + kfree(dev->transfer_buffer[i]); + dev->transfer_buffer[i] = NULL; + } + em2820_capture_start(dev, 0); +} + +/* + * em2820_init_isoc() + * allocates transfer buffers and submits the urbs for isoc transfer + */ +int em2820_init_isoc(struct em2820 *dev) +{ + /* change interface to 3 which allowes the biggest packet sizes */ + int i, errCode; + const int sb_size = EM2820_NUM_PACKETS * dev->max_pkt_size; + + /* reset streaming vars */ + dev->frame_current = NULL; + dev->frame_count = 0; + + /* allocate urbs */ + for (i = 0; i < EM2820_NUM_BUFS; i++) { + struct urb *urb; + int j, k; + /* allocate transfer buffer */ + dev->transfer_buffer[i] = kmalloc(sb_size, GFP_KERNEL); + if (!dev->transfer_buffer[i]) { + em2820_errdev + ("unable to allocate %i bytes for transfer buffer %i\n", + sb_size, i); + em2820_uninit_isoc(dev); + return -ENOMEM; + } + memset(dev->transfer_buffer[i], 0, sb_size); + urb = usb_alloc_urb(EM2820_NUM_PACKETS, GFP_KERNEL); + if (urb) { + urb->dev = dev->udev; + urb->context = dev; + urb->pipe = usb_rcvisocpipe(dev->udev, 0x82); + urb->transfer_flags = URB_ISO_ASAP; + urb->interval = 1; + urb->transfer_buffer = dev->transfer_buffer[i]; + urb->complete = em2820_isocIrq; + urb->number_of_packets = EM2820_NUM_PACKETS; + urb->transfer_buffer_length = sb_size; + for (j = k = 0; j < EM2820_NUM_PACKETS; + j++, k += dev->max_pkt_size) { + urb->iso_frame_desc[j].offset = k; + urb->iso_frame_desc[j].length = + dev->max_pkt_size; + } + dev->urb[i] = urb; + } else { + em2820_errdev("cannot alloc urb %i\n", i); + em2820_uninit_isoc(dev); + return -ENOMEM; + } + } + + /* submit urbs */ + for (i = 0; i < EM2820_NUM_BUFS; i++) { + errCode = usb_submit_urb(dev->urb[i], GFP_KERNEL); + if (errCode) { + em2820_errdev("submit of urb %i failed (error=%i)\n", i, + errCode); + em2820_uninit_isoc(dev); + return errCode; + } + } + + return 0; +} + +int em2820_set_alternate(struct em2820 *dev) +{ + int errCode, prev_alt = dev->alt; + dev->alt = alt; + if (dev->alt == 0) { + int i; + unsigned int min_pkt_size = dev->field_size / 137; /* FIXME: empiric magic number */ + em2820_coredbg("minimum isoc packet size: %u", min_pkt_size); + dev->alt = 7; + for (i = 1; i < EM2820_MAX_ALT; i += 2) /* FIXME: skip even alternate: why do they not work? */ + if (dev->alt_max_pkt_size[i] >= min_pkt_size) { + dev->alt = i; + break; + } + } + + if (dev->alt != prev_alt) { + dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt]; + em2820_coredbg("setting alternate %d with wMaxPacketSize=%u", dev->alt, + dev->max_pkt_size); + errCode = usb_set_interface(dev->udev, 0, dev->alt); + if (errCode < 0) { + em2820_errdev + ("cannot change alternate number to %d (error=%i)\n", + dev->alt, errCode); + return errCode; + } + } + return 0; +} diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c new file mode 100644 index 00000000000..95f80a7615b --- /dev/null +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -0,0 +1,443 @@ +/* + em2820-i2c.c - driver for Empia EM2820/2840 USB video capture devices + + Copyright (C) 2005 Markus Rechberger + Ludovico Cavedon + Mauro Carvalho Chehab + + Based on the em2800 driver from Sascha Sommer + + 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 option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* To be moved to compat.h */ +#if !defined(I2C_HW_B_EM2820) +#define I2C_HW_B_EM2820 I2C_HW_B_BT848 +#endif + +#include "em2820.h" + +/* ----------------------------------------------------------- */ + +static unsigned int i2c_scan = 0; +module_param(i2c_scan, int, 0444); +MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); + +static unsigned int i2c_debug = 0; +module_param(i2c_debug, int, 0644); +MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); + +#define dprintk(fmt, args...) if (i2c_debug) do {\ + printk(KERN_DEBUG "%s: %s: " fmt "\n",\ + dev->name, __FUNCTION__ , ##args); } while (0) +#define dprintk1(fmt, args...) if (i2c_debug) do{ \ + printk(KERN_DEBUG "%s: %s: " fmt, \ + dev->name, __FUNCTION__ , ##args); } while (0) +#define dprintk2(fmt, args...) if (i2c_debug) do {\ + printk(fmt , ##args); } while (0) + +/* + * i2c_send_bytes() + * untested for more than 4 bytes + */ +static int i2c_send_bytes(void *data, unsigned char addr, char *buf, short len, + int stop) +{ + int wrcount = 0; + struct em2820 *dev = (struct em2820 *)data; + + wrcount = dev->em2820_write_regs_req(dev, stop ? 2 : 3, addr, buf, len); + + return wrcount; +} + +/* + * i2c_recv_byte() + * read a byte from the i2c device + */ +static int i2c_recv_bytes(struct em2820 *dev, unsigned char addr, char *buf, + int len) +{ + int ret; + ret = dev->em2820_read_reg_req_len(dev, 2, addr, buf, len); + if (ret < 0) { + em2820_warn("reading i2c device failed (error=%i)\n", ret); + return ret; + } + if (dev->em2820_read_reg(dev, 0x5) != 0) + return -ENODEV; + return ret; +} + +/* + * i2c_check_for_device() + * check if there is a i2c_device at the supplied address + */ +static int i2c_check_for_device(struct em2820 *dev, unsigned char addr) +{ + char msg; + int ret; + msg = addr; + + ret = dev->em2820_read_reg_req(dev, 2, addr); + if (ret < 0) { + em2820_warn("reading from i2c device failed (error=%i)\n", ret); + return ret; + } + if (dev->em2820_read_reg(dev, 0x5) != 0) + return -ENODEV; + return 0; +} + +/* + * em2820_i2c_xfer() + * the main i2c transfer function + */ +static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg msgs[], int num) +{ + struct em2820 *dev = i2c_adap->algo_data; + int addr, rc, i, byte; + + if (num <= 0) + return 0; + for (i = 0; i < num; i++) { + addr = msgs[i].addr << 1; + dprintk1("%s %s addr=%x len=%d:", + (msgs[i].flags & I2C_M_RD) ? "read" : "write", + i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); + if (!msgs[i].len) { /* no len: check only for device presence */ + rc = i2c_check_for_device(dev, addr); + if (rc < 0) { + dprintk2(" no device\n"); + return rc; + } + + } + if (msgs[i].flags & I2C_M_RD) { + /* read bytes */ + + rc = i2c_recv_bytes(dev, addr, msgs[i].buf, + msgs[i].len); + if (i2c_debug) { + for (byte = 0; byte < msgs[i].len; byte++) { + printk(" %02x", msgs[i].buf[byte]); + } + } + } else { + /* write bytes */ + if (i2c_debug) { + for (byte = 0; byte < msgs[i].len; byte++) + printk(" %02x", msgs[i].buf[byte]); + } + rc = i2c_send_bytes(dev, addr, msgs[i].buf, msgs[i].len, + i == num - 1); + if (rc < 0) + goto err; + } + if (i2c_debug) + printk("\n"); + } + + return num; + err: + dprintk2(" ERROR: %i\n", rc); + return rc; +} + +static int em2820_i2c_eeprom(struct em2820 *dev, unsigned char *eedata, int len) +{ + unsigned char buf, *p = eedata; + struct em2820_eeprom *em_eeprom = (void *)eedata; + int i, err, size = len, block; + + dev->i2c_client.addr = 0xa0 >> 1; + buf = 0; + if (1 != (err = i2c_master_send(&dev->i2c_client, &buf, 1))) { + printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n", + dev->name, err); + return -1; + } + while (size > 0) { + if (size > 16) + block = 16; + else + block = size; + + if (block != + (err = i2c_master_recv(&dev->i2c_client, p, block))) { + printk(KERN_WARNING + "%s: i2c eeprom read error (err=%d)\n", + dev->name, err); + return -1; + } + size -= block; + p += block; + } + for (i = 0; i < len; i++) { + if (0 == (i % 16)) + printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i); + printk(" %02x", eedata[i]); + if (15 == (i % 16)) + printk("\n"); + } + + printk(KERN_INFO "EEPROM ID= 0x%08x\n", em_eeprom->id); + printk(KERN_INFO "Vendor/Product ID= %04x:%04x\n", em_eeprom->vendor_ID, + em_eeprom->product_ID); + + switch (em_eeprom->chip_conf >> 4 & 0x3) { + case 0: + printk(KERN_INFO "No audio on board.\n"); + break; + case 1: + printk(KERN_INFO "AC97 audio (5 sample rates)\n"); + break; + case 2: + printk(KERN_INFO "I2S audio, sample rate=32k\n"); + break; + case 3: + printk(KERN_INFO "I2S audio, 3 sample rates\n"); + break; + } + + if (em_eeprom->chip_conf & 1 << 3) + printk(KERN_INFO "USB Remote wakeup capable\n"); + + if (em_eeprom->chip_conf & 1 << 2) + printk(KERN_INFO "USB Self power capable\n"); + + switch (em_eeprom->chip_conf & 0x3) { + case 0: + printk(KERN_INFO "500mA max power\n"); + break; + case 1: + printk(KERN_INFO "400mA max power\n"); + break; + case 2: + printk(KERN_INFO "300mA max power\n"); + break; + case 3: + printk(KERN_INFO "200mA max power\n"); + break; + } + + return 0; +} + +/* ----------------------------------------------------------- */ + +/* + * algo_control() + */ +static int algo_control(struct i2c_adapter *adapter, + unsigned int cmd, unsigned long arg) +{ + return 0; +} + +/* + * functionality() + */ +static u32 functionality(struct i2c_adapter *adap) +{ + return I2C_FUNC_SMBUS_EMUL; +} + +#ifndef I2C_PEC +static void inc_use(struct i2c_adapter *adap) +{ + MOD_INC_USE_COUNT; +} + +static void dec_use(struct i2c_adapter *adap) +{ + MOD_DEC_USE_COUNT; +} +#endif + +static int em2820_set_tuner(int check_eeprom, struct i2c_client *client) +{ + struct em2820 *dev = client->adapter->algo_data; + + struct tuner_setup tun_setup; + + /* tuner */ + if (dev->has_tuner) { + tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; + tun_setup.type = dev->tuner_type; + tun_setup.addr = dev->tuner_addr; + + em2820_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); + } + return (0); +} + +/* + * attach_inform() + * gets called when a device attaches to the i2c bus + * does some basic configuration + */ +static int attach_inform(struct i2c_client *client) +{ + struct em2820 *dev = client->adapter->algo_data; + + dprintk("address %x", client->addr << 1); + switch (client->addr << 1) { + case 0x68: + em2820_i2c_call_clients(dev, TDA9887_SET_CONFIG, &dev->tda9887_conf); + break; + case 0x4a: + dprintk1("attach_inform: saa7113 detected.\n"); + break; + case 0xa0: + dprintk1("attach_inform: eeprom detected.\n"); + break; + case 0x80: + case 0x88: + dprintk1("attach_inform: msp34xx detected.\n"); + break; + case 0xb8: + case 0xba: + dprintk1("attach_inform: tvp5150 detected.\n"); + break; + default: + dev->tuner_addr = client->addr; + em2820_set_tuner(-1, client); + } + + return 0; +} + +static struct i2c_algorithm em2820_algo = { + .name = "em2820", + .id = I2C_HW_B_EM2820, + .master_xfer = em2820_i2c_xfer, + .algo_control = algo_control, + .functionality = functionality, +}; + +static struct i2c_adapter em2820_adap_template = { +#ifdef I2C_PEC + .owner = THIS_MODULE, +#else + .inc_use = inc_use, + .dec_use = dec_use, +#endif +#ifdef I2C_CLASS_TV_ANALOG + .class = I2C_CLASS_TV_ANALOG, +#endif + .name = "em2820", + .id = I2C_HW_B_EM2820, + .algo = &em2820_algo, + .client_register = attach_inform, +}; + +static struct i2c_client em2820_client_template = { + .name = "em2820 internal", + .flags = I2C_CLIENT_ALLOW_USE, +}; + +/* ----------------------------------------------------------- */ + +/* + * i2c_devs + * incomplete list of known devices + */ +static char *i2c_devs[128] = { + [0x4a >> 1] = "saa7113h", + [0x60 >> 1] = "remote IR sensor", + [0x86 >> 1] = "tda9887", + [0x80 >> 1] = "msp34xx", + [0x88 >> 1] = "msp34xx", + [0xa0 >> 1] = "eeprom", + [0xb8 >> 1] = "tvp5150a", + [0xba >> 1] = "tvp5150a", + [0xc0 >> 1] = "tuner (analog)", + [0xc2 >> 1] = "tuner (analog)", + [0xc4 >> 1] = "tuner (analog)", + [0xc6 >> 1] = "tuner (analog)", +}; + +/* + * do_i2c_scan() + * check i2c address range for devices + */ +static void do_i2c_scan(char *name, struct i2c_client *c) +{ + unsigned char buf; + int i, rc; + + for (i = 0; i < 128; i++) { + c->addr = i; + rc = i2c_master_recv(c, &buf, 0); + if (rc < 0) + continue; + printk(KERN_INFO "%s: found device @ 0x%x [%s]", name, + i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); + } +} + +/* + * em2820_i2c_call_clients() + * send commands to all attached i2c devices + */ +void em2820_i2c_call_clients(struct em2820 *dev, unsigned int cmd, void *arg) +{ + BUG_ON(NULL == dev->i2c_adap.algo_data); + i2c_clients_command(&dev->i2c_adap, cmd, arg); +} + +/* + * em2820_i2c_register() + * register i2c bus + */ +int em2820_i2c_register(struct em2820 *dev) +{ + BUG_ON(!dev->em2820_write_regs || !dev->em2820_read_reg); + BUG_ON(!dev->em2820_write_regs_req || !dev->em2820_read_reg_req); + dev->i2c_adap = em2820_adap_template; + dev->i2c_adap.dev.parent = &dev->udev->dev; + strcpy(dev->i2c_adap.name, dev->name); + dev->i2c_adap.algo_data = dev; + i2c_add_adapter(&dev->i2c_adap); + + dev->i2c_client = em2820_client_template; + dev->i2c_client.adapter = &dev->i2c_adap; + + em2820_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata)); + + if (i2c_scan) + do_i2c_scan(dev->name, &dev->i2c_client); + return 0; +} + +/* + * em2820_i2c_unregister() + * unregister i2c_bus + */ +int em2820_i2c_unregister(struct em2820 *dev) +{ + i2c_del_adapter(&dev->i2c_adap); + return 0; +} diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c new file mode 100644 index 00000000000..a000131a8f5 --- /dev/null +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -0,0 +1,1815 @@ +/* + em2820-video.c - driver for Empia EM2820/2840 USB video capture devices + + Copyright (C) 2005 Markus Rechberger + Ludovico Cavedon + Mauro Carvalho Chehab + + Based on the em2800 driver from Sascha Sommer + + 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 option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "em2820.h" + +#define DRIVER_AUTHOR "Markus Rechberger , " \ + "Ludovico Cavedon , " \ + "Mauro Carvalho Chehab " + +#define DRIVER_NAME "em2820" +#define DRIVER_DESC "Empia em2820 based USB video device driver" +#define EM2820_VERSION_CODE KERNEL_VERSION(0, 0, 1) + +#define em2820_videodbg(fmt, arg...) do {\ + if (video_debug) \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __FUNCTION__ , ##arg); } while (0) + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + +static int tuner = -1; +module_param(tuner, int, 0444); +MODULE_PARM_DESC(tuner, "tuner type"); + +static unsigned int video_debug = 0; +module_param(video_debug,int,0644); +MODULE_PARM_DESC(video_debug,"enable debug messages [video]"); + +/* supported tv norms */ +static struct em2820_tvnorm tvnorms[] = { + { + .name = "PAL", + .id = V4L2_STD_PAL, + .mode = VIDEO_MODE_PAL, + }, { + .name = "NTSC", + .id = V4L2_STD_NTSC, + .mode = VIDEO_MODE_NTSC, + }, { + .name = "SECAM", + .id = V4L2_STD_SECAM, + .mode = VIDEO_MODE_SECAM, + }, { + .name = "PAL-M", + .id = V4L2_STD_PAL_M, + .mode = VIDEO_MODE_PAL, + } +}; + +#define TVNORMS ARRAY_SIZE(tvnorms) + +/* supported controls */ +static struct v4l2_queryctrl em2820_qctrl[] = { + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = -128, + .maximum = 127, + .step = 1, + .default_value = 0, + .flags = 0, + },{ + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Contrast", + .minimum = 0x0, + .maximum = 0x1f, + .step = 0x1, + .default_value = 0x10, + .flags = 0, + },{ + .id = V4L2_CID_SATURATION, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Saturation", + .minimum = 0x0, + .maximum = 0x1f, + .step = 0x1, + .default_value = 0x10, + .flags = 0, + },{ + .id = V4L2_CID_AUDIO_VOLUME, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Volume", + .minimum = 0x0, + .maximum = 0x1f, + .step = 0x1, + .default_value = 0x1f, + .flags = 0, + },{ + .id = V4L2_CID_AUDIO_MUTE, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Mute", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + .flags = 0, + },{ + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Red chroma balance", + .minimum = -128, + .maximum = 127, + .step = 1, + .default_value = 0, + .flags = 0, + },{ + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Blue chroma balance", + .minimum = -128, + .maximum = 127, + .step = 1, + .default_value = 0, + .flags = 0, + },{ + .id = V4L2_CID_GAMMA, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gamma", + .minimum = 0x0, + .maximum = 0x3f, + .step = 0x1, + .default_value = 0x20, + .flags = 0, + } +}; + +static struct usb_driver em2820_usb_driver; + +static DECLARE_MUTEX(em2820_sysfs_lock); +static DECLARE_RWSEM(em2820_disconnect); + +/********************* v4l2 interface ******************************************/ + +static inline unsigned long kvirt_to_pa(unsigned long adr) +{ + unsigned long kva, ret; + + kva = (unsigned long)page_address(vmalloc_to_page((void *)adr)); + kva |= adr & (PAGE_SIZE - 1); + ret = __pa(kva); + return ret; +} + +/* + * em2820_config() + * inits registers with sane defaults + */ +static int em2820_config(struct em2820 *dev) +{ + + /* Sets I2C speed to 100 KHz */ + em2820_write_regs_req(dev, 0x00, 0x06, "\x40", 1); + + /* enable vbi capturing */ + em2820_audio_usb_mute(dev, 1); + dev->mute = 1; /* maybe not the right place... */ + dev->volume = 0x1f; + em2820_audio_analog_set(dev); + em2820_audio_analog_setup(dev); + em2820_outfmt_set_yuv422(dev); + em2820_colorlevels_set_default(dev); + em2820_compression_disable(dev); + + return 0; +} + +/* + * em2820_config_i2c() + * configure i2c attached devices + */ +void em2820_config_i2c(struct em2820 *dev) +{ + struct v4l2_frequency f; + struct video_decoder_init em2820_vdi = {.data = NULL }; + + + /* configure decoder */ + em2820_i2c_call_clients(dev, DECODER_INIT, &em2820_vdi); + em2820_i2c_call_clients(dev, DECODER_SET_INPUT, &dev->ctl_input); +/* em2820_i2c_call_clients(dev,DECODER_SET_PICTURE, &dev->vpic); */ +/* em2820_i2c_call_clients(dev,DECODER_SET_NORM,&dev->tvnorm->id); */ +/* em2820_i2c_call_clients(dev,DECODER_ENABLE_OUTPUT,&output); */ +/* em2820_i2c_call_clients(dev,DECODER_DUMP, NULL); */ + + /* configure tuner */ + f.tuner = 0; + f.type = V4L2_TUNER_ANALOG_TV; + f.frequency = 9076; /* FIXME:remove magic number */ + dev->ctl_freq = f.frequency; + em2820_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f); + + /* configure tda9887 */ + + em2820_i2c_call_clients(dev, TDA9887_SET_CONFIG, &dev->tda9887_conf); + +/* em2820_i2c_call_clients(dev,VIDIOC_S_STD,&dev->tvnorm->id); */ +} + +/* + * em2820_empty_framequeues() + * prepare queues for incoming and outgoing frames + */ +static void em2820_empty_framequeues(struct em2820 *dev) +{ + u32 i; + + INIT_LIST_HEAD(&dev->inqueue); + INIT_LIST_HEAD(&dev->outqueue); + + for (i = 0; i < EM2820_NUM_FRAMES; i++) { + dev->frame[i].state = F_UNUSED; + dev->frame[i].buf.bytesused = 0; + } +} + +/* + * em2820_v4l2_open() + * inits the device and starts isoc transfer + */ +static int em2820_v4l2_open(struct inode *inode, struct file *filp) +{ + struct video_device *vdev = video_devdata(filp); + int minor = iminor(inode); + struct em2820 *dev = (struct em2820 *)video_get_drvdata(vdev); + int errCode = 0; + + em2820_videodbg("users=%d", dev->users); + + if (!down_read_trylock(&em2820_disconnect)) + return -ERESTARTSYS; + + if (dev->users) { + em2820_warn("this driver can be opened only once\n"); + up_read(&em2820_disconnect); + return -EBUSY; + } + +/* if(dev->vbi_dev->minor == minor){ + dev->type=V4L2_BUF_TYPE_VBI_CAPTURE; + }*/ + if (dev->vdev->minor == minor) { + dev->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + + init_MUTEX(&dev->fileop_lock); /* to 1 == available */ + spin_lock_init(&dev->queue_lock); + init_waitqueue_head(&dev->wait_frame); + init_waitqueue_head(&dev->wait_stream); + + down(&dev->lock); + + em2820_set_alternate(dev); + + dev->width = norm_maxw(dev); + dev->height = norm_maxh(dev); + dev->frame_size = dev->width * dev->height * 2; + dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */ + dev->bytesperline = dev->width * 2; + dev->hscale = 0; + dev->vscale = 0; + + em2820_capture_start(dev, 1); + em2820_resolution_set(dev); + + /* start the transfer */ + errCode = em2820_init_isoc(dev); + if (errCode) + goto err; + + dev->users++; + filp->private_data = dev; + dev->io = IO_NONE; + dev->stream = STREAM_OFF; + dev->num_frames = 0; + + /* prepare queues */ + em2820_empty_framequeues(dev); + + dev->state |= DEV_INITIALIZED; + + err: + up(&dev->lock); + up_read(&em2820_disconnect); + return errCode; +} + +/* + * em2820_realease_resources() + * unregisters the v4l2,i2c and usb devices + * called when the device gets disconected or at module unload +*/ +static void em2820_release_resources(struct em2820 *dev) +{ + down(&em2820_sysfs_lock); + + em2820_info("V4L2 device /dev/video%d deregistered\n", + dev->vdev->minor); + video_set_drvdata(dev->vdev, NULL); + video_unregister_device(dev->vdev); +/* video_unregister_device(dev->vbi_dev); */ + em2820_i2c_unregister(dev); + usb_put_dev(dev->udev); + up(&em2820_sysfs_lock); +} + +/* + * em2820_v4l2_close() + * stops streaming and deallocates all resources allocated by the v4l2 calls and ioctls + */ +static int em2820_v4l2_close(struct inode *inode, struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct em2820 *dev = (struct em2820 *)video_get_drvdata(vdev); + int errCode; + + em2820_videodbg("users=%d", dev->users); + + down(&dev->lock); + + em2820_uninit_isoc(dev); + + em2820_release_buffers(dev); + + /* the device is already disconnect, free the remaining resources */ + if (dev->state & DEV_DISCONNECTED) { + em2820_release_resources(dev); + up(&dev->lock); + kfree(dev); + return 0; + } + + /* set alternate 0 */ + dev->alt = 0; + em2820_videodbg("setting alternate 0"); + errCode = usb_set_interface(dev->udev, 0, 0); + if (errCode < 0) { + em2820_errdev ("cannot change alternate number to 0 (error=%i)\n", + errCode); + } + + dev->users--; + wake_up_interruptible_nr(&dev->open, 1); + up(&dev->lock); + return 0; +} + +/* + * em2820_v4l2_read() + * will allocate buffers when called for the first time + */ +static ssize_t +em2820_v4l2_read(struct file *filp, char __user * buf, size_t count, + loff_t * f_pos) +{ + struct em2820 *dev = video_get_drvdata(video_devdata(filp)); + struct em2820_frame_t *f, *i; + unsigned long lock_flags; + int ret = 0; + + if (down_interruptible(&dev->fileop_lock)) + return -ERESTARTSYS; + + if (dev->state & DEV_DISCONNECTED) { + em2820_videodbg("device not present"); + up(&dev->fileop_lock); + return -ENODEV; + } + + if (dev->state & DEV_MISCONFIGURED) { + em2820_videodbg("device misconfigured; close and open it again"); + up(&dev->fileop_lock); + return -EIO; + } + + if (dev->io == IO_MMAP) { + em2820_videodbg ("IO method is set to mmap; close and open" + " the device again to choose the read method"); + up(&dev->fileop_lock); + return -EINVAL; + } + + if (dev->io == IO_NONE) { + if (!em2820_request_buffers(dev, EM2820_NUM_READ_FRAMES)) { + em2820_errdev("read failed, not enough memory\n"); + up(&dev->fileop_lock); + return -ENOMEM; + } + dev->io = IO_READ; + dev->stream = STREAM_ON; + em2820_queue_unusedframes(dev); + } + + if (!count) { + up(&dev->fileop_lock); + return 0; + } + + if (list_empty(&dev->outqueue)) { + if (filp->f_flags & O_NONBLOCK) { + up(&dev->fileop_lock); + return -EAGAIN; + } + ret = wait_event_interruptible + (dev->wait_frame, + (!list_empty(&dev->outqueue)) || + (dev->state & DEV_DISCONNECTED)); + if (ret) { + up(&dev->fileop_lock); + return ret; + } + if (dev->state & DEV_DISCONNECTED) { + up(&dev->fileop_lock); + return -ENODEV; + } + } + + f = list_entry(dev->outqueue.prev, struct em2820_frame_t, frame); + + spin_lock_irqsave(&dev->queue_lock, lock_flags); + list_for_each_entry(i, &dev->outqueue, frame) + i->state = F_UNUSED; + INIT_LIST_HEAD(&dev->outqueue); + spin_unlock_irqrestore(&dev->queue_lock, lock_flags); + + em2820_queue_unusedframes(dev); + + if (count > f->buf.length) + count = f->buf.length; + + if (copy_to_user(buf, f->bufmem, count)) { + up(&dev->fileop_lock); + return -EFAULT; + } + *f_pos += count; + + up(&dev->fileop_lock); + + return count; +} + +/* + * em2820_v4l2_poll() + * will allocate buffers when called for the first time + */ +static unsigned int em2820_v4l2_poll(struct file *filp, poll_table * wait) +{ + struct em2820 *dev = video_get_drvdata(video_devdata(filp)); + unsigned int mask = 0; + + if (down_interruptible(&dev->fileop_lock)) + return POLLERR; + + if (dev->state & DEV_DISCONNECTED) { + em2820_videodbg("device not present"); + } else if (dev->state & DEV_MISCONFIGURED) { + em2820_videodbg("device is misconfigured; close and open it again"); + } else { + if (dev->io == IO_NONE) { + if (!em2820_request_buffers + (dev, EM2820_NUM_READ_FRAMES)) { + em2820_warn + ("poll() failed, not enough memory\n"); + } else { + dev->io = IO_READ; + dev->stream = STREAM_ON; + } + } + + if (dev->io == IO_READ) { + em2820_queue_unusedframes(dev); + poll_wait(filp, &dev->wait_frame, wait); + + if (!list_empty(&dev->outqueue)) + mask |= POLLIN | POLLRDNORM; + + up(&dev->fileop_lock); + + return mask; + } + } + + up(&dev->fileop_lock); + return POLLERR; +} + +/* + * em2820_vm_open() + */ +static void em2820_vm_open(struct vm_area_struct *vma) +{ + struct em2820_frame_t *f = vma->vm_private_data; + f->vma_use_count++; +} + +/* + * em2820_vm_close() + */ +static void em2820_vm_close(struct vm_area_struct *vma) +{ + /* NOTE: buffers are not freed here */ + struct em2820_frame_t *f = vma->vm_private_data; + f->vma_use_count--; +} + +static struct vm_operations_struct em2820_vm_ops = { + .open = em2820_vm_open, + .close = em2820_vm_close, +}; + +/* + * em2820_v4l2_mmap() + */ +static int em2820_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct em2820 *dev = video_get_drvdata(video_devdata(filp)); + unsigned long size = vma->vm_end - vma->vm_start, + start = vma->vm_start, pos, page; + u32 i; + if (down_interruptible(&dev->fileop_lock)) + return -ERESTARTSYS; + + if (dev->state & DEV_DISCONNECTED) { + em2820_videodbg("mmap: device not present"); + up(&dev->fileop_lock); + return -ENODEV; + } + + if (dev->state & DEV_MISCONFIGURED) { + em2820_videodbg ("mmap: Device is misconfigured; close and " + "open it again"); + up(&dev->fileop_lock); + return -EIO; + } + + if (dev->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || + size != PAGE_ALIGN(dev->frame[0].buf.length)) { + up(&dev->fileop_lock); + return -EINVAL; + } + + for (i = 0; i < dev->num_frames; i++) { + if ((dev->frame[i].buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff) + break; + } + if (i == dev->num_frames) { + em2820_videodbg("mmap: user supplied mapping address is out of range"); + up(&dev->fileop_lock); + return -EINVAL; + } + + /* VM_IO is eventually going to replace PageReserved altogether */ + vma->vm_flags |= VM_IO; + vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ + + pos = (unsigned long)dev->frame[i].bufmem; + while (size > 0) { /* size is page-aligned */ + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page, PAGE_SIZE, + vma->vm_page_prot)) { + em2820_videodbg("mmap: rename page map failed"); + up(&dev->fileop_lock); + return -EAGAIN; + } + start += PAGE_SIZE; + pos += PAGE_SIZE; + size -= PAGE_SIZE; + } + + vma->vm_ops = &em2820_vm_ops; + vma->vm_private_data = &dev->frame[i]; + + em2820_vm_open(vma); + up(&dev->fileop_lock); + return 0; +} + +/* + * em2820_get_ctrl() + * return the current saturation, brightness or contrast, mute state + */ +static int em2820_get_ctrl(struct em2820 *dev, struct v4l2_control *ctrl) +{ + s32 tmp; + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + ctrl->value = dev->mute; + return 0; + case V4L2_CID_AUDIO_VOLUME: + ctrl->value = dev->volume; + return 0; + case V4L2_CID_BRIGHTNESS: + if ((tmp = em2820_brightness_get(dev)) < 0) + return -EIO; + ctrl->value = (s32) ((s8) tmp); /* FIXME: clenaer way to extend sign? */ + return 0; + case V4L2_CID_CONTRAST: + if ((ctrl->value = em2820_contrast_get(dev)) < 0) + return -EIO; + return 0; + case V4L2_CID_SATURATION: + if ((ctrl->value = em2820_saturation_get(dev)) < 0) + return -EIO; + return 0; + case V4L2_CID_RED_BALANCE: + if ((tmp = em2820_v_balance_get(dev)) < 0) + return -EIO; + ctrl->value = (s32) ((s8) tmp); /* FIXME: clenaer way to extend sign? */ + return 0; + case V4L2_CID_BLUE_BALANCE: + if ((tmp = em2820_u_balance_get(dev)) < 0) + return -EIO; + ctrl->value = (s32) ((s8) tmp); /* FIXME: clenaer way to extend sign? */ + return 0; + case V4L2_CID_GAMMA: + if ((ctrl->value = em2820_gamma_get(dev)) < 0) + return -EIO; + return 0; + default: + return -EINVAL; + } +} + +/* + * em2820_set_ctrl() + * mute or set new saturation, brightness or contrast + */ +static int em2820_set_ctrl(struct em2820 *dev, const struct v4l2_control *ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + if (ctrl->value != dev->mute) { + dev->mute = ctrl->value; + em2820_audio_usb_mute(dev, ctrl->value); + return em2820_audio_analog_set(dev); + } + return 0; + case V4L2_CID_AUDIO_VOLUME: + dev->volume = ctrl->value; + return em2820_audio_analog_set(dev); + case V4L2_CID_BRIGHTNESS: + return em2820_brightness_set(dev, ctrl->value); + case V4L2_CID_CONTRAST: + return em2820_contrast_set(dev, ctrl->value); + case V4L2_CID_SATURATION: + return em2820_saturation_set(dev, ctrl->value); + case V4L2_CID_RED_BALANCE: + return em2820_v_balance_set(dev, ctrl->value); + case V4L2_CID_BLUE_BALANCE: + return em2820_u_balance_set(dev, ctrl->value); + case V4L2_CID_GAMMA: + return em2820_gamma_set(dev, ctrl->value); + default: + return -EINVAL; + } +} + +/* + * em2820_stream_interrupt() + * stops streaming + */ +static int em2820_stream_interrupt(struct em2820 *dev) +{ + int ret = 0; + + /* stop reading from the device */ + + dev->stream = STREAM_INTERRUPT; + ret = wait_event_timeout(dev->wait_stream, + (dev->stream == STREAM_OFF) || + (dev->state & DEV_DISCONNECTED), + EM2820_URB_TIMEOUT); + if (dev->state & DEV_DISCONNECTED) + return -ENODEV; + else if (ret) { + dev->state |= DEV_MISCONFIGURED; + em2820_videodbg("device is misconfigured; close and " + "open /dev/video%d again", dev->vdev->minor); + return ret; + } + + return 0; +} + +static int em2820_set_norm(struct em2820 *dev, int width, int height) +{ + unsigned int hscale, vscale; + unsigned int maxh, maxw; + + maxw = norm_maxw(dev); + maxh = norm_maxh(dev); + + /* width must even because of the YUYV format */ + /* height must be even because of interlacing */ + height &= 0xfffe; + width &= 0xfffe; + + if (height < 32) + height = 32; + if (height > maxh) + height = maxh; + if (width < 48) + width = 48; + if (width > maxw) + width = maxw; + + if ((hscale = (((unsigned long)maxw) << 12) / width - 4096L) >= 0x4000) + hscale = 0x3fff; + width = (((unsigned long)maxw) << 12) / (hscale + 4096L); + + if ((vscale = (((unsigned long)maxh) << 12) / height - 4096L) >= 0x4000) + vscale = 0x3fff; + height = (((unsigned long)maxh) << 12) / (vscale + 4096L); + + /* set new image size */ + dev->width = width; + dev->height = height; + dev->frame_size = dev->width * dev->height * 2; + dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */ + dev->bytesperline = dev->width * 2; + dev->hscale = hscale; + dev->vscale = vscale; + + em2820_resolution_set(dev); + + return 0; +} + +static void video_mux(struct em2820 *dev, int index) +{ + int input, ainput; + + input = INPUT(index)->vmux; + dev->ctl_input = index; + + em2820_i2c_call_clients(dev, DECODER_SET_INPUT, &input); + + dev->ctl_ainput = INPUT(index)->amux; + + switch (dev->ctl_ainput) { + case 0: + ainput = EM2820_AUDIO_SRC_TUNER; + break; + default: + ainput = EM2820_AUDIO_SRC_LINE; + } + + em2820_audio_source(dev, ainput); +} + +/* + * em2820_v4l2_do_ioctl() + * This function is _not_ called directly, but from + * em2820_v4l2_ioctl. Userspace + * copying is done already, arg is a kernel pointer. + */ +static int em2820_do_ioctl(struct inode *inode, struct file *filp, + struct em2820 *dev, unsigned int cmd, void *arg, + v4l2_kioctl driver_ioctl) +{ + int ret; + + switch (cmd) { + /* ---------- tv norms ---------- */ + case VIDIOC_ENUMSTD: + { + struct v4l2_standard *e = arg; + unsigned int i; + + i = e->index; + if (i >= TVNORMS) + return -EINVAL; + ret = v4l2_video_std_construct(e, tvnorms[e->index].id, + tvnorms[e->index].name); + e->index = i; + if (ret < 0) + return ret; + return 0; + } + case VIDIOC_G_STD: + { + v4l2_std_id *id = arg; + + *id = dev->tvnorm->id; + return 0; + } + case VIDIOC_S_STD: + { + v4l2_std_id *id = arg; + unsigned int i; + + for (i = 0; i < TVNORMS; i++) + if (*id == tvnorms[i].id) + break; + if (i == TVNORMS) + for (i = 0; i < TVNORMS; i++) + if (*id & tvnorms[i].id) + break; + if (i == TVNORMS) + return -EINVAL; + + down(&dev->lock); + dev->tvnorm = &tvnorms[i]; + + em2820_set_norm(dev, dev->width, dev->height); + +/* + dev->width=norm_maxw(dev); + dev->height=norm_maxh(dev); + dev->frame_size=dev->width*dev->height*2; + dev->field_size=dev->frame_size>>1; + dev->bytesperline=dev->width*2; + dev->hscale=0; + dev->vscale=0; + + em2820_resolution_set(dev); +*/ +/* + em2820_uninit_isoc(dev); + em2820_set_alternate(dev); + em2820_capture_start(dev, 1); + em2820_resolution_set(dev); + em2820_init_isoc(dev); +*/ + em2820_i2c_call_clients(dev, DECODER_SET_NORM, + &tvnorms[i].mode); + em2820_i2c_call_clients(dev, VIDIOC_S_STD, + &dev->tvnorm->id); + + up(&dev->lock); + + return 0; + } + + /* ------ input switching ---------- */ + case VIDIOC_ENUMINPUT: + { + struct v4l2_input *i = arg; + unsigned int n; + static const char *iname[] = { + [EM2820_VMUX_COMPOSITE1] = "Composite1", + [EM2820_VMUX_COMPOSITE2] = "Composite2", + [EM2820_VMUX_COMPOSITE3] = "Composite3", + [EM2820_VMUX_COMPOSITE4] = "Composite4", + [EM2820_VMUX_SVIDEO] = "S-Video", + [EM2820_VMUX_TELEVISION] = "Television", + [EM2820_VMUX_CABLE] = "Cable TV", + [EM2820_VMUX_DVB] = "DVB", + [EM2820_VMUX_DEBUG] = "for debug only", + }; + + n = i->index; + if (n >= MAX_EM2820_INPUT) + return -EINVAL; + if (0 == INPUT(n)->type) + return -EINVAL; + memset(i, 0, sizeof(*i)); + i->index = n; + i->type = V4L2_INPUT_TYPE_CAMERA; + strcpy(i->name, iname[INPUT(n)->type]); + if ((EM2820_VMUX_TELEVISION == INPUT(n)->type) || + (EM2820_VMUX_CABLE == INPUT(n)->type)) + i->type = V4L2_INPUT_TYPE_TUNER; + for (n = 0; n < ARRAY_SIZE(tvnorms); n++) + i->std |= tvnorms[n].id; + return 0; + } + + case VIDIOC_G_INPUT: + { + int *i = arg; + *i = dev->ctl_input; + + return 0; + } + + case VIDIOC_S_INPUT: + { + int *index = arg; + + if (*index >= MAX_EM2820_INPUT) + return -EINVAL; + if (0 == INPUT(*index)->type) + return -EINVAL; + + down(&dev->lock); + video_mux(dev, *index); + up(&dev->lock); + + return 0; + } + + case VIDIOC_G_AUDIO: + { + struct v4l2_audio *a = arg; + unsigned int index = a->index; + + if (a->index > 1) + return -EINVAL; + memset(a, 0, sizeof(*a)); + index = dev->ctl_ainput; + + if (index == 0) { + strcpy(a->name, "Television"); + } else { + strcpy(a->name, "Line In"); + } + a->capability = V4L2_AUDCAP_STEREO; + a->index = index; + return 0; + } + + case VIDIOC_S_AUDIO: + { + struct v4l2_audio *a = arg; + if (a->index != dev->ctl_ainput) + return -EINVAL; + + return 0; + } + + /* --- controls ---------------------------------------------- */ + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *qc = arg; + u8 i, n; + n = sizeof(em2820_qctrl) / sizeof(em2820_qctrl[0]); + for (i = 0; i < n; i++) + if (qc->id && qc->id == em2820_qctrl[i].id) { + memcpy(qc, &(em2820_qctrl[i]), + sizeof(*qc)); + return 0; + } + + return -EINVAL; + } + + case VIDIOC_G_CTRL: + { + struct v4l2_control *ctrl = arg; + + + return em2820_get_ctrl(dev, ctrl); + } + + case VIDIOC_S_CTRL_OLD: /* ??? */ + case VIDIOC_S_CTRL: + { + struct v4l2_control *ctrl = arg; + u8 i, n; + + + n = sizeof(em2820_qctrl) / sizeof(em2820_qctrl[0]); + for (i = 0; i < n; i++) + if (ctrl->id == em2820_qctrl[i].id) { + if (ctrl->value < + em2820_qctrl[i].minimum + || ctrl->value > + em2820_qctrl[i].maximum) + return -ERANGE; + + return em2820_set_ctrl(dev, ctrl); + } + return -EINVAL; + } + + /* --- tuner ioctls ------------------------------------------ */ + case VIDIOC_G_TUNER: + { + struct v4l2_tuner *t = arg; + int status = 0; + + if (0 != t->index) + return -EINVAL; + + memset(t, 0, sizeof(*t)); + strcpy(t->name, "Tuner"); + t->type = V4L2_TUNER_ANALOG_TV; + t->capability = V4L2_TUNER_CAP_NORM; + t->rangehigh = 0xffffffffUL; /* FIXME: set correct range */ +/* t->signal = 0xffff;*/ +/* em2820_i2c_call_clients(dev,VIDIOC_G_TUNER,t);*/ + /* No way to get signal strength? */ + down(&dev->lock); + em2820_i2c_call_clients(dev, DECODER_GET_STATUS, + &status); + up(&dev->lock); + t->signal = + (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0; + + em2820_videodbg("VIDIO_G_TUNER: signal=%x, afc=%x", t->signal, + t->afc); + return 0; + } + case VIDIOC_S_TUNER: + { + struct v4l2_tuner *t = arg; + int status = 0; + + if (0 != t->index) + return -EINVAL; + memset(t, 0, sizeof(*t)); + strcpy(t->name, "Tuner"); + t->type = V4L2_TUNER_ANALOG_TV; + t->capability = V4L2_TUNER_CAP_NORM; + t->rangehigh = 0xffffffffUL; /* FIXME: set correct range */ +/* t->signal = 0xffff; */ + /* No way to get signal strength? */ + down(&dev->lock); + em2820_i2c_call_clients(dev, DECODER_GET_STATUS, + &status); + up(&dev->lock); + t->signal = + (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0; + + em2820_videodbg("VIDIO_S_TUNER: signal=%x, afc=%x\n", + t->signal, t->afc); + return 0; + } + case VIDIOC_G_FREQUENCY: + { + struct v4l2_frequency *f = arg; + + memset(f, 0, sizeof(*f)); + f->type = V4L2_TUNER_ANALOG_TV; + f->frequency = dev->ctl_freq; + + return 0; + } + case VIDIOC_S_FREQUENCY: + { + struct v4l2_frequency *f = arg; + + if (0 != f->tuner) + return -EINVAL; + + if (V4L2_TUNER_ANALOG_TV != f->type) + return -EINVAL; + + down(&dev->lock); + dev->ctl_freq = f->frequency; + em2820_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f); + up(&dev->lock); + return 0; + } + + case VIDIOC_CROPCAP: + { + struct v4l2_cropcap *cc = arg; + + if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return EINVAL; + cc->bounds.left = 0; + cc->bounds.top = 0; + cc->bounds.width = dev->width; + cc->bounds.height = dev->height; + cc->defrect = cc->bounds; + cc->pixelaspect.numerator = 54; /* 4:3 FIXME: remove magic numbers */ + cc->pixelaspect.denominator = 59; + return 0; + } + case VIDIOC_STREAMON: + { + int *type = arg; + + if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE + || dev->io != IO_MMAP) + return -EINVAL; + + if (list_empty(&dev->inqueue)) + return -EINVAL; + + dev->stream = STREAM_ON; /* FIXME: Start video capture here? */ + + em2820_videodbg("VIDIOC_STREAMON: starting stream"); + + return 0; + } + case VIDIOC_STREAMOFF: + { + int *type = arg; + int ret; + + if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE + || dev->io != IO_MMAP) + return -EINVAL; + + if (dev->stream == STREAM_ON) { + em2820_videodbg ("VIDIOC_STREAMOFF: interrupting stream"); + if ((ret = em2820_stream_interrupt(dev))) + return ret; + } + em2820_empty_framequeues(dev); + + return 0; + } + default: + return v4l_compat_translate_ioctl(inode, filp, cmd, arg, + driver_ioctl); + } + return 0; +} + +/* + * em2820_v4l2_do_ioctl() + * This function is _not_ called directly, but from + * em2820_v4l2_ioctl. Userspace + * copying is done already, arg is a kernel pointer. + */ +static int em2820_video_do_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, void *arg) +{ + struct em2820 *dev = filp->private_data; + + if (!dev) + return -ENODEV; + + if (video_debug > 1) + em2820_print_ioctl(dev->name,cmd); + + switch (cmd) { + + /* --- capabilities ------------------------------------------ */ + case VIDIOC_QUERYCAP: + { + struct v4l2_capability *cap = arg; + + memset(cap, 0, sizeof(*cap)); + strlcpy(cap->driver, "em2820", sizeof(cap->driver)); + strlcpy(cap->card, em2820_boards[dev->model].name, + sizeof(cap->card)); + strlcpy(cap->bus_info, dev->udev->dev.bus_id, + sizeof(cap->bus_info)); + cap->version = EM2820_VERSION_CODE; + cap->capabilities = + V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_AUDIO | + V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; + if (dev->has_tuner) + cap->capabilities |= V4L2_CAP_TUNER; + return 0; + } + + /* --- capture ioctls ---------------------------------------- */ + case VIDIOC_ENUM_FMT: + { + struct v4l2_fmtdesc *fmtd = arg; + + if (fmtd->index != 0) + return -EINVAL; + memset(fmtd, 0, sizeof(*fmtd)); + fmtd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + strcpy(fmtd->description, "Packed YUY2"); + fmtd->pixelformat = V4L2_PIX_FMT_YUYV; + memset(fmtd->reserved, 0, sizeof(fmtd->reserved)); + return 0; + } + + case VIDIOC_G_FMT: + { + struct v4l2_format *format = arg; + + em2820_videodbg("VIDIOC_G_FMT: type=%s", + format->type == + V4L2_BUF_TYPE_VIDEO_CAPTURE ? + "V4L2_BUF_TYPE_VIDEO_CAPTURE" : format->type == + V4L2_BUF_TYPE_VBI_CAPTURE ? + "V4L2_BUF_TYPE_VBI_CAPTURE " : + "not supported"); + + if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + format->fmt.pix.width = dev->width; + format->fmt.pix.height = dev->height; + format->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; + format->fmt.pix.bytesperline = dev->bytesperline; + format->fmt.pix.sizeimage = dev->frame_size; + format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + format->fmt.pix.field = dev->interlaced ? V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */ + + em2820_videodbg("VIDIOC_G_FMT: %dx%d", dev->width, + dev->height); + return 0; + } + + case VIDIOC_TRY_FMT: + case VIDIOC_S_FMT: + { + struct v4l2_format *format = arg; + u32 i; + int ret = 0; + int width = format->fmt.pix.width; + int height = format->fmt.pix.height; + unsigned int hscale, vscale; + unsigned int maxh, maxw; + + maxw = norm_maxw(dev); + maxh = norm_maxh(dev); + +/* int both_fields; */ + + em2820_videodbg("%s: type=%s", + cmd == + VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : + "VIDIOC_S_FMT", + format->type == + V4L2_BUF_TYPE_VIDEO_CAPTURE ? + "V4L2_BUF_TYPE_VIDEO_CAPTURE" : format->type == + V4L2_BUF_TYPE_VBI_CAPTURE ? + "V4L2_BUF_TYPE_VBI_CAPTURE " : + "not supported"); + + if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + em2820_videodbg("%s: requested %dx%d", + cmd == + VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : + "VIDIOC_S_FMT", format->fmt.pix.width, + format->fmt.pix.height); + + /* FIXME: Move some code away from here */ + /* width must even because of the YUYV format */ + /* height must be even because of interlacing */ + height &= 0xfffe; + width &= 0xfffe; + + if (height < 32) + height = 32; + if (height > maxh) + height = maxh; + if (width < 48) + width = 48; + if (width > maxw) + width = maxw; + + if ((hscale = + (((unsigned long)maxw) << 12) / width - 4096L) >= + 0x4000) + hscale = 0x3fff; + width = + (((unsigned long)maxw) << 12) / (hscale + 4096L); + + if ((vscale = + (((unsigned long)maxh) << 12) / height - 4096L) >= + 0x4000) + vscale = 0x3fff; + height = + (((unsigned long)maxh) << 12) / (vscale + 4096L); + + format->fmt.pix.width = width; + format->fmt.pix.height = height; + format->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; + format->fmt.pix.bytesperline = width * 2; + format->fmt.pix.sizeimage = width * 2 * height; + format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + format->fmt.pix.field = V4L2_FIELD_INTERLACED; + + em2820_videodbg("%s: returned %dx%d (%d, %d)", + cmd == + VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : + "VIDIOC_S_FMT", format->fmt.pix.width, + format->fmt.pix.height, hscale, vscale); + + if (cmd == VIDIOC_TRY_FMT) + return 0; + + for (i = 0; i < dev->num_frames; i++) + if (dev->frame[i].vma_use_count) { + em2820_videodbg("VIDIOC_S_FMT failed. " + "Unmap the buffers first."); + return -EINVAL; + } + + /* stop io in case it is already in progress */ + if (dev->stream == STREAM_ON) { + em2820_videodbg("VIDIOC_SET_FMT: interupting stream"); + if ((ret = em2820_stream_interrupt(dev))) + return ret; + } + + em2820_release_buffers(dev); + dev->io = IO_NONE; + + /* set new image size */ + dev->width = width; + dev->height = height; + dev->frame_size = dev->width * dev->height * 2; + dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */ + dev->bytesperline = dev->width * 2; + dev->hscale = hscale; + dev->vscale = vscale; +/* dev->both_fileds = both_fileds; */ + em2820_uninit_isoc(dev); + em2820_set_alternate(dev); + em2820_capture_start(dev, 1); + em2820_resolution_set(dev); + em2820_init_isoc(dev); + + return 0; + } + + /* --- streaming capture ------------------------------------- */ + case VIDIOC_REQBUFS: + { + struct v4l2_requestbuffers *rb = arg; + u32 i; + int ret; + + if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + rb->memory != V4L2_MEMORY_MMAP) + return -EINVAL; + + if (dev->io == IO_READ) { + em2820_videodbg ("method is set to read;" + " close and open the device again to" + " choose the mmap I/O method"); + return -EINVAL; + } + + for (i = 0; i < dev->num_frames; i++) + if (dev->frame[i].vma_use_count) { + em2820_videodbg ("VIDIOC_REQBUFS failed; previous buffers are still mapped"); + return -EINVAL; + } + + if (dev->stream == STREAM_ON) { + em2820_videodbg("VIDIOC_REQBUFS: interrupting stream"); + if ((ret = em2820_stream_interrupt(dev))) + return ret; + } + + em2820_empty_framequeues(dev); + + em2820_release_buffers(dev); + if (rb->count) + rb->count = + em2820_request_buffers(dev, rb->count); + + dev->frame_current = NULL; + + em2820_videodbg ("VIDIOC_REQBUFS: setting io method to mmap: num bufs %i", + rb->count); + dev->io = rb->count ? IO_MMAP : IO_NONE; + return 0; + } + + case VIDIOC_QUERYBUF: + { + struct v4l2_buffer *b = arg; + + if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + b->index >= dev->num_frames || dev->io != IO_MMAP) + return -EINVAL; + + memcpy(b, &dev->frame[b->index].buf, sizeof(*b)); + + if (dev->frame[b->index].vma_use_count) { + b->flags |= V4L2_BUF_FLAG_MAPPED; + } + if (dev->frame[b->index].state == F_DONE) + b->flags |= V4L2_BUF_FLAG_DONE; + else if (dev->frame[b->index].state != F_UNUSED) + b->flags |= V4L2_BUF_FLAG_QUEUED; + return 0; + } + case VIDIOC_QBUF: + { + struct v4l2_buffer *b = arg; + unsigned long lock_flags; + + if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + b->index >= dev->num_frames || dev->io != IO_MMAP) { + return -EINVAL; + } + + if (dev->frame[b->index].state != F_UNUSED) { + return -EAGAIN; + } + dev->frame[b->index].state = F_QUEUED; + + /* add frame to fifo */ + spin_lock_irqsave(&dev->queue_lock, lock_flags); + list_add_tail(&dev->frame[b->index].frame, + &dev->inqueue); + spin_unlock_irqrestore(&dev->queue_lock, lock_flags); + + return 0; + } + case VIDIOC_DQBUF: + { + struct v4l2_buffer *b = arg; + struct em2820_frame_t *f; + unsigned long lock_flags; + int ret = 0; + + if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE + || dev->io != IO_MMAP) + return -EINVAL; + + if (list_empty(&dev->outqueue)) { + if (dev->stream == STREAM_OFF) + return -EINVAL; + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + ret = wait_event_interruptible + (dev->wait_frame, + (!list_empty(&dev->outqueue)) || + (dev->state & DEV_DISCONNECTED)); + if (ret) + return ret; + if (dev->state & DEV_DISCONNECTED) + return -ENODEV; + } + + spin_lock_irqsave(&dev->queue_lock, lock_flags); + f = list_entry(dev->outqueue.next, + struct em2820_frame_t, frame); + list_del(dev->outqueue.next); + spin_unlock_irqrestore(&dev->queue_lock, lock_flags); + + f->state = F_UNUSED; + memcpy(b, &f->buf, sizeof(*b)); + + if (f->vma_use_count) + b->flags |= V4L2_BUF_FLAG_MAPPED; + + return 0; + } + default: + return em2820_do_ioctl(inode, filp, dev, cmd, arg, + em2820_video_do_ioctl); + } + return 0; +} + +/* + * em2820_v4l2_ioctl() + * handle v4l2 ioctl the main action happens in em2820_v4l2_do_ioctl() + */ +static int em2820_v4l2_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + struct em2820 *dev = video_get_drvdata(video_devdata(filp)); + int ret = 0; + + if (down_interruptible(&dev->fileop_lock)) + return -ERESTARTSYS; + + if (dev->state & DEV_DISCONNECTED) { + em2820_errdev("v4l2 ioctl: device not present\n"); + up(&dev->fileop_lock); + return -ENODEV; + } + + if (dev->state & DEV_MISCONFIGURED) { + em2820_errdev + ("v4l2 ioctl: device is misconfigured; close and open it again\n"); + up(&dev->fileop_lock); + return -EIO; + } + + ret = video_usercopy(inode, filp, cmd, arg, em2820_video_do_ioctl); + + up(&dev->fileop_lock); + + return ret; +} + +static struct file_operations em2820_v4l_fops = { + .owner = THIS_MODULE, + .open = em2820_v4l2_open, + .release = em2820_v4l2_close, + .ioctl = em2820_v4l2_ioctl, + .read = em2820_v4l2_read, + .poll = em2820_v4l2_poll, + .mmap = em2820_v4l2_mmap, + .llseek = no_llseek, +}; + +/******************************** usb interface *****************************************/ + +/* + * em2820_init_dev() + * allocates and inits the device structs, registers i2c bus and v4l device + */ +static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, + int minor, int model) +{ + struct em2820 *dev; + int retval = -ENOMEM; + int errCode, i; + unsigned int maxh, maxw; + struct usb_interface *uif; + + /* allocate memory for our device state and initialize it */ + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { + em2820_err(DRIVER_NAME ": out of memory!\n"); + return -ENOMEM; + } + memset(dev, 0x00, sizeof(*dev)); + + snprintf(dev->name, 29, "em2820 #%d", minor); + dev->udev = udev; + dev->model = model; + init_MUTEX(&dev->lock); + init_waitqueue_head(&dev->open); + + dev->em2820_write_regs = em2820_write_regs; + dev->em2820_read_reg = em2820_read_reg; + dev->em2820_read_reg_req_len = em2820_read_reg_req_len; + dev->em2820_write_regs_req = em2820_write_regs_req; + dev->em2820_read_reg_req = em2820_read_reg_req; + dev->has_tuner = em2820_boards[model].has_tuner; + dev->has_msp34xx = em2820_boards[model].has_msp34xx; + dev->tda9887_conf = em2820_boards[model].tda9887_conf; + dev->decoder = em2820_boards[model].decoder; + + if (tuner >= 0) + dev->tuner_type = tuner; + else + dev->tuner_type = em2820_boards[model].tuner_type; + + dev->video_inputs = em2820_boards[model].vchannels; + + for (i = 0; i < TVNORMS; i++) + if (em2820_boards[model].norm == tvnorms[i].mode) + break; + if (i == TVNORMS) + i = 0; + + dev->tvnorm = &tvnorms[i]; /* set default norm */ + + em2820_videodbg("tvnorm=%s\n", dev->tvnorm->name); + + maxw = norm_maxw(dev); + maxh = norm_maxh(dev); + + /* set default image size */ + dev->width = maxw; + dev->height = maxh; + dev->interlaced = EM2820_INTERLACED_DEFAULT; + dev->field_size = dev->width * dev->height; + dev->frame_size = + dev->interlaced ? dev->field_size << 1 : dev->field_size; + dev->bytesperline = dev->width * 2; + dev->hscale = 0; + dev->vscale = 0; + dev->ctl_input = 2; + + /* setup video picture settings for saa7113h */ + memset(&dev->vpic, 0, sizeof(dev->vpic)); + dev->vpic.colour = 128 << 8; + dev->vpic.hue = 128 << 8; + dev->vpic.brightness = 128 << 8; + dev->vpic.contrast = 192 << 8; + dev->vpic.whiteness = 128 << 8; /* This one isn't used */ + dev->vpic.depth = 16; + dev->vpic.palette = VIDEO_PALETTE_YUV422; + + /* compute alternate max packet sizes */ + uif = dev->udev->actconfig->interface[0]; + dev->alt_max_pkt_size[0] = 0; + for (i = 1; i <= EM2820_MAX_ALT; i++) { + u16 tmp = + le16_to_cpu(uif->altsetting[i].endpoint[1].desc. + wMaxPacketSize); + dev->alt_max_pkt_size[i] = + (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); + } + +#ifdef CONFIG_MODULES + /* request some modules */ + if (dev->decoder == EM2820_SAA7113) + request_module("saa7113"); + if (dev->decoder == EM2820_SAA7114) + request_module("saa7114"); + if (dev->decoder == EM2820_TVP5150) + request_module("tvp5150"); + if (dev->has_tuner) + request_module("tuner"); + if (dev->tda9887_conf) + request_module("tda9887"); +#endif + errCode = em2820_config(dev); + if (errCode) { + em2820_errdev("error configuring device\n"); + kfree(dev); + return -ENOMEM; + } + + down(&dev->lock); + /* register i2c bus */ + em2820_i2c_register(dev); + + /* Do board specific init and eeprom reading */ + em2820_card_setup(dev); + + /* configure the device */ + em2820_config_i2c(dev); + + up(&dev->lock); + + errCode = em2820_config(dev); + +#ifdef CONFIG_MODULES + if (dev->has_msp34xx) + request_module("msp3400"); +#endif + /* allocate and fill v4l2 device struct */ + dev->vdev = video_device_alloc(); + if (NULL == dev->vdev) { + em2820_errdev("cannot allocate video_device.\n"); + kfree(dev); + return -ENOMEM; + } + + dev->vdev->owner = THIS_MODULE; + dev->vdev->type = VID_TYPE_CAPTURE; + if (dev->has_tuner) + dev->vdev->type |= VID_TYPE_TUNER; + dev->vdev->hardware = 0; + dev->vdev->fops = &em2820_v4l_fops; + dev->vdev->minor = -1; + dev->vdev->dev = &dev->udev->dev; + dev->vdev->release = video_device_release; + snprintf(dev->vdev->name, sizeof(dev->vdev->name), "%s", + "em2820 video"); + video_set_drvdata(dev->vdev, dev); + + /* register v4l2 device */ + down(&dev->lock); + if ((retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1))) { + em2820_errdev("unable to register video device (error=%i).\n", + retval); + up(&dev->lock); + video_set_drvdata(dev->vdev, NULL); + video_device_release(dev->vdev); + kfree(dev); + return -ENODEV; + } + if (dev->has_msp34xx) { + /* Send a reset to other chips via gpio */ + em2820_write_regs_req(dev, 0x00, 0x08, "\xf7", 1); + udelay(2500); + em2820_write_regs_req(dev, 0x00, 0x08, "\xff", 1); + udelay(2500); + + } + video_mux(dev, 0); + + up(&dev->lock); + + em2820_info("V4L2 device registered as /dev/video%d\n", + dev->vdev->minor); + + *devhandle = dev; + return 0; +} + +/* + * em2820_usb_probe() + * checks for supported devices + */ +static int em2820_usb_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + const struct usb_endpoint_descriptor *endpoint; + struct usb_device *udev; + struct em2820 *dev = NULL; + int retval = -ENODEV; + + udev = usb_get_dev(interface_to_usbdev(interface)); + endpoint = &interface->cur_altsetting->endpoint[1].desc; + + /* check if the the device has the iso in endpoint at the correct place */ + if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != + USB_ENDPOINT_XFER_ISOC) { +/* em2820_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n"); */ + return -ENODEV; + } + if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { +/* em2820_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n"); */ + return -ENODEV; + } + + /* allocate device struct */ + retval = em2820_init_dev(&dev, udev, interface->minor, id->driver_info); + if (retval) + return retval; + + em2820_info("Found %s\n", em2820_boards[id->driver_info].name); + + /* save our data pointer in this interface device */ + usb_set_intfdata(interface, dev); + return 0; +} + +/* + * em2820_usb_disconnect() + * called when the device gets diconencted + * video device will be unregistered on v4l2_close in case it is still open + */ +static void em2820_usb_disconnect(struct usb_interface *interface) +{ + struct em2820 *dev = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); + + if (!dev) + return; + + down_write(&em2820_disconnect); + + down(&dev->lock); + + em2820_info("disconnecting %s\n", dev->vdev->name); + + wake_up_interruptible_all(&dev->open); + + if (dev->users) { + em2820_warn + ("device /dev/video%d is open! Deregistration and memory " + "deallocation are deferred on close.\n", dev->vdev->minor); + dev->state |= DEV_MISCONFIGURED; + em2820_uninit_isoc(dev); + dev->state |= DEV_DISCONNECTED; + wake_up_interruptible(&dev->wait_frame); + wake_up_interruptible(&dev->wait_stream); + } else { + dev->state |= DEV_DISCONNECTED; + em2820_release_resources(dev); + } + + up(&dev->lock); + + if (!dev->users) + kfree(dev); + + up_write(&em2820_disconnect); + +} + +static struct usb_driver em2820_usb_driver = { + .owner = THIS_MODULE, + .name = "em2820", + .probe = em2820_usb_probe, + .disconnect = em2820_usb_disconnect, + .id_table = em2820_id_table, +}; + +static int __init em2820_module_init(void) +{ + int result; + + printk(KERN_INFO DRIVER_NAME " v4l2 driver version %d.%d.%d loaded\n", + (EM2820_VERSION_CODE >> 16) & 0xff, + (EM2820_VERSION_CODE >> 8) & 0xff, EM2820_VERSION_CODE & 0xff); +#ifdef SNAPSHOT + printk(KERN_INFO DRIVER_NAME " snapshot date %04d-%02d-%02d\n", + SNAPSHOT / 10000, (SNAPSHOT / 100) % 100, SNAPSHOT % 100); +#endif + + /* register this driver with the USB subsystem */ + result = usb_register(&em2820_usb_driver); + if (result) + em2820_err(DRIVER_NAME + " usb_register failed. Error number %d.\n", result); + + return result; +} + +static void __exit em2820_module_exit(void) +{ + /* deregister this driver with the USB subsystem */ + usb_deregister(&em2820_usb_driver); +} + +module_init(em2820_module_init); +module_exit(em2820_module_exit); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h new file mode 100644 index 00000000000..7779121a3de --- /dev/null +++ b/drivers/media/video/em28xx/em28xx.h @@ -0,0 +1,479 @@ +/* + em2820-cards.c - driver for Empia EM2820/2840 USB video capture devices + + Copyright (C) 2005 Markus Rechberger + Ludovico Cavedon + Mauro Carvalho Chehab + + Based on the em2800 driver from Sascha Sommer + + 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 option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _EM2820_H +#define _EM2820_H + +#include +#include + +/* maximum number of frames that can be queued */ +#define EM2820_NUM_FRAMES 5 +/* number of frames that get used for v4l2_read() */ +#define EM2820_NUM_READ_FRAMES 2 + +/* number of buffers for isoc transfers */ +#define EM2820_NUM_BUFS 5 + +/* number of packets for each buffer */ +// windows requests only 40 packets .. so we better do the same +// this is what I found out for all alternate numbers there! + +#define EM2820_NUM_PACKETS 40 + +/* packet size for each packet */ +/* no longer needed: read from endpoint descriptor */ +//#define EM2820_MAX_PACKET_SIZE 3072 //7 +//#define EM2820_MAX_PACKET_SIZE 2892 //6 +//#define EM2820_MAX_PACKET_SIZE 2580 //5 +//#define EM2820_MAX_PACKET_SIZE 1448 //2 + +/* default alternate; 0 means choose the best */ +#define EM2820_PINOUT 0 +#define EM2820_MAX_ALT 7 + +#define EM2820_INTERLACED_DEFAULT 1 + +/* +#define (use usbview if you want to get the other alternate number infos) +#define +#define alternate number 2 +#define Endpoint Address: 82 + Direction: in + Attribute: 1 + Type: Isoc + Max Packet Size: 1448 + Interval: 125us + + alternate number 7 + + Endpoint Address: 82 + Direction: in + Attribute: 1 + Type: Isoc + Max Packet Size: 3072 + Interval: 125us +*/ + +/* time to wait when stopping the isoc transfer */ +#define EM2820_URB_TIMEOUT msecs_to_jiffies(EM2820_NUM_BUFS * EM2820_NUM_PACKETS) + +/* the various frame states */ +enum em2820_frame_state { + F_UNUSED = 0, + F_QUEUED, + F_GRABBING, + F_DONE, + F_ERROR, +}; + +/* stream states */ +enum em2820_stream_state { + STREAM_OFF, + STREAM_INTERRUPT, + STREAM_ON, +}; + +/* frames */ +struct em2820_frame_t { + void *bufmem; + struct v4l2_buffer buf; + enum em2820_frame_state state; + struct list_head frame; + unsigned long vma_use_count; + int top_field; + int fieldbytesused; +}; + +/* io methods */ +enum em2820_io_method { + IO_NONE, + IO_READ, + IO_MMAP, +}; + +/* inputs */ + +#define MAX_EM2820_INPUT 4 +enum enum2820_itype { + EM2820_VMUX_COMPOSITE1 = 1, + EM2820_VMUX_COMPOSITE2, + EM2820_VMUX_COMPOSITE3, + EM2820_VMUX_COMPOSITE4, + EM2820_VMUX_SVIDEO, + EM2820_VMUX_TELEVISION, + EM2820_VMUX_CABLE, + EM2820_VMUX_DVB, + EM2820_VMUX_DEBUG, + EM2820_RADIO, +}; + +struct em2820_input { + enum enum2820_itype type; + unsigned int vmux; + unsigned int amux; +}; + +#define INPUT(nr) (&em2820_boards[dev->model].input[nr]) + +enum em2820_decoder { + EM2820_TVP5150, + EM2820_SAA7113, + EM2820_SAA7114 +}; + +struct em2820_board { + char *name; + + int vchannels; + int norm; + int tuner_type; + + /* i2c flags */ + unsigned int tda9887_conf; + + unsigned int has_tuner:1; + unsigned int has_msp34xx:1; + + enum em2820_decoder decoder; + + struct em2820_input input[MAX_EM2820_INPUT]; +}; + +struct em2820_eeprom { + u32 id; /* 0x9567eb1a */ + u16 vendor_ID; + u16 product_ID; + + u16 chip_conf; + + u16 board_conf; + + u16 string1, string2, string3; + + u8 string_idx_table; +}; + +/* device states */ +enum em2820_dev_state { + DEV_INITIALIZED = 0x01, + DEV_DISCONNECTED = 0x02, + DEV_MISCONFIGURED = 0x04, +}; + +/* tvnorms */ +struct em2820_tvnorm { + char *name; + v4l2_std_id id; + /* mode for saa7113h */ + int mode; +}; + +/* main device struct */ +struct em2820 { + /* generic device properties */ + char name[30]; /* name (including minor) of the device */ + int model; /* index in the device_data struct */ + int video_inputs; /* number of video inputs */ + unsigned int has_tuner:1; + unsigned int has_msp34xx:1; + unsigned int has_tda9887:1; + + enum em2820_decoder decoder; + + int tuner_type; /* type of the tuner */ + int tuner_addr; /* tuner address */ + int tda9887_conf; + /* i2c i/o */ + struct i2c_adapter i2c_adap; + struct i2c_client i2c_client; + /* video for linux */ + int users; /* user count for exclusive use */ + struct video_device *vdev; /* video for linux device struct */ + struct video_picture vpic; /* picture settings only used to init saa7113h */ + struct em2820_tvnorm *tvnorm; /* selected tv norm */ + int ctl_freq; /* selected frequency */ + unsigned int ctl_input; /* selected input */ + unsigned int ctl_ainput; /* slected audio input */ + int mute; + int volume; + /* frame properties */ + struct em2820_frame_t frame[EM2820_NUM_FRAMES]; /* list of frames */ + int num_frames; /* number of frames currently in use */ + unsigned int frame_count; /* total number of transfered frames */ + struct em2820_frame_t *frame_current; /* the frame that is being filled */ + int width; /* current frame width */ + int height; /* current frame height */ + int frame_size; /* current frame size */ + int field_size; /* current field size */ + int bytesperline; + int hscale; /* horizontal scale factor (see datasheet) */ + int vscale; /* vertical scale factor (see datasheet) */ + int interlaced; /* 1=interlace fileds, 0=just top fileds */ + int type; + + /* states */ + enum em2820_dev_state state; + enum em2820_stream_state stream; + enum em2820_io_method io; + /* locks */ + struct semaphore lock, fileop_lock; + spinlock_t queue_lock; + struct list_head inqueue, outqueue; + wait_queue_head_t open, wait_frame, wait_stream; + struct video_device *vbi_dev; + + unsigned char eedata[256]; + + /* usb transfer */ + struct usb_device *udev; /* the usb device */ + int alt; /* alternate */ + int max_pkt_size; /* max packet size of isoc transaction */ + unsigned int alt_max_pkt_size[EM2820_MAX_ALT + 1]; /* array of wMaxPacketSize */ + struct urb *urb[EM2820_NUM_BUFS]; /* urb for isoc transfers */ + char *transfer_buffer[EM2820_NUM_BUFS]; /* transfer buffers for isoc transfer */ + /* helper funcs that call usb_control_msg */ + int (*em2820_write_regs) (struct em2820 * dev, u16 reg, char *buf, + int len); + int (*em2820_read_reg) (struct em2820 * dev, u16 reg); + int (*em2820_read_reg_req_len) (struct em2820 * dev, u8 req, u16 reg, + char *buf, int len); + int (*em2820_write_regs_req) (struct em2820 * dev, u8 req, u16 reg, + char *buf, int len); + int (*em2820_read_reg_req) (struct em2820 * dev, u8 req, u16 reg); +}; + +/* Provided by em2820-i2c.c */ + +void em2820_i2c_call_clients(struct em2820 *dev, unsigned int cmd, void *arg); +int em2820_i2c_register(struct em2820 *dev); +int em2820_i2c_unregister(struct em2820 *dev); + +/* Provided by em2820-core.c */ + +void em2820_print_ioctl(char *name, unsigned int cmd); + +u32 em2820_request_buffers(struct em2820 *dev, u32 count); +void em2820_queue_unusedframes(struct em2820 *dev); +void em2820_release_buffers(struct em2820 *dev); + +int em2820_read_reg_req_len(struct em2820 *dev, u8 req, u16 reg, + char *buf, int len); +int em2820_read_reg_req(struct em2820 *dev, u8 req, u16 reg); +int em2820_read_reg(struct em2820 *dev, u16 reg); +int em2820_write_regs_req(struct em2820 *dev, u8 req, u16 reg, char *buf, + int len); +int em2820_write_regs(struct em2820 *dev, u16 reg, char *buf, int len); +int em2820_write_reg_bits(struct em2820 *dev, u16 reg, u8 val, + u8 bitmask); +int em2820_write_ac97(struct em2820 *dev, u8 reg, u8 * val); +int em2820_audio_analog_set(struct em2820 *dev); +int em2820_colorlevels_set_default(struct em2820 *dev); +int em2820_capture_start(struct em2820 *dev, int start); +int em2820_outfmt_set_yuv422(struct em2820 *dev); +int em2820_accumulator_set(struct em2820 *dev, u8 xmin, u8 xmax, u8 ymin, + u8 ymax); +int em2820_capture_area_set(struct em2820 *dev, u8 hstart, u8 vstart, + u16 width, u16 height); +int em2820_scaler_set(struct em2820 *dev, u16 h, u16 v); +int em2820_resolution_set(struct em2820 *dev); +void em2820_isocIrq(struct urb *urb, struct pt_regs *regs); +int em2820_init_isoc(struct em2820 *dev); +void em2820_uninit_isoc(struct em2820 *dev); +int em2820_set_alternate(struct em2820 *dev); + +/* Provided by em2820-cards.c */ +extern void em2820_card_setup(struct em2820 *dev); +extern struct em2820_board em2820_boards[]; +extern struct usb_device_id em2820_id_table[]; + +/* em2820 registers */ +#define USBSUSP_REG 0x0c /* */ + +#define AUDIOSRC_REG 0x0e +#define XCLK_REG 0x0f + +#define VINMODE_REG 0x10 +#define VINCTRL_REG 0x11 +#define VINENABLE_REG 0x12 /* */ + +#define GAMMA_REG 0x14 +#define RGAIN_REG 0x15 +#define GGAIN_REG 0x16 +#define BGAIN_REG 0x17 +#define ROFFSET_REG 0x18 +#define GOFFSET_REG 0x19 +#define BOFFSET_REG 0x1a + +#define OFLOW_REG 0x1b +#define HSTART_REG 0x1c +#define VSTART_REG 0x1d +#define CWIDTH_REG 0x1e +#define CHEIGHT_REG 0x1f + +#define YGAIN_REG 0x20 +#define YOFFSET_REG 0x21 +#define UVGAIN_REG 0x22 +#define UOFFSET_REG 0x23 +#define VOFFSET_REG 0x24 +#define SHARPNESS_REG 0x25 + +#define COMPR_REG 0x26 +#define OUTFMT_REG 0x27 + +#define XMIN_REG 0x28 +#define XMAX_REG 0x29 +#define YMIN_REG 0x2a +#define YMAX_REG 0x2b + +#define HSCALELOW_REG 0x30 +#define HSCALEHIGH_REG 0x31 +#define VSCALELOW_REG 0x32 +#define VSCALEHIGH_REG 0x33 + +#define AC97LSB_REG 0x40 +#define AC97MSB_REG 0x41 +#define AC97ADDR_REG 0x42 +#define AC97BUSY_REG 0x43 + +/* em202 registers */ +#define MASTER_AC97 0x02 +#define VIDEO_AC97 0x14 + +/* register settings */ +#define EM2820_AUDIO_SRC_TUNER 0xc0 +#define EM2820_AUDIO_SRC_LINE 0x80 + +/* printk macros */ + +#define em2820_err(fmt, arg...) do {\ + printk(KERN_ERR fmt , ##arg); } while (0) + +#define em2820_errdev(fmt, arg...) do {\ + printk(KERN_ERR "%s: "fmt,\ + dev->name , ##arg); } while (0) + +#define em2820_info(fmt, arg...) do {\ + printk(KERN_INFO "%s: "fmt,\ + dev->name , ##arg); } while (0) +#define em2820_warn(fmt, arg...) do {\ + printk(KERN_WARNING "%s: "fmt,\ + dev->name , ##arg); } while (0) + +inline static int em2820_audio_source(struct em2820 *dev, int input) +{ + return em2820_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0); +} + +inline static int em2820_audio_usb_mute(struct em2820 *dev, int mute) +{ + return em2820_write_reg_bits(dev, XCLK_REG, mute ? 0x00 : 0x80, 0x80); +} + +inline static int em2820_audio_analog_setup(struct em2820 *dev) +{ + /* unmute video mixer with default volume level */ + return em2820_write_ac97(dev, VIDEO_AC97, "\x08\x08"); +} + +inline static int em2820_compression_disable(struct em2820 *dev) +{ + /* side effect of disabling scaler and mixer */ + return em2820_write_regs(dev, COMPR_REG, "\x00", 1); +} + +inline static int em2820_contrast_get(struct em2820 *dev) +{ + return em2820_read_reg(dev, YGAIN_REG) & 0x1f; +} + +inline static int em2820_brightness_get(struct em2820 *dev) +{ + return em2820_read_reg(dev, YOFFSET_REG); +} + +inline static int em2820_saturation_get(struct em2820 *dev) +{ + return em2820_read_reg(dev, UVGAIN_REG) & 0x1f; +} + +inline static int em2820_u_balance_get(struct em2820 *dev) +{ + return em2820_read_reg(dev, UOFFSET_REG); +} + +inline static int em2820_v_balance_get(struct em2820 *dev) +{ + return em2820_read_reg(dev, VOFFSET_REG); +} + +inline static int em2820_gamma_get(struct em2820 *dev) +{ + return em2820_read_reg(dev, GAMMA_REG) & 0x3f; +} + +inline static int em2820_contrast_set(struct em2820 *dev, s32 val) +{ + u8 tmp = (u8) val; + return em2820_write_regs(dev, YGAIN_REG, &tmp, 1); +} + +inline static int em2820_brightness_set(struct em2820 *dev, s32 val) +{ + u8 tmp = (u8) val; + return em2820_write_regs(dev, YOFFSET_REG, &tmp, 1); +} + +inline static int em2820_saturation_set(struct em2820 *dev, s32 val) +{ + u8 tmp = (u8) val; + return em2820_write_regs(dev, UVGAIN_REG, &tmp, 1); +} + +inline static int em2820_u_balance_set(struct em2820 *dev, s32 val) +{ + u8 tmp = (u8) val; + return em2820_write_regs(dev, UOFFSET_REG, &tmp, 1); +} + +inline static int em2820_v_balance_set(struct em2820 *dev, s32 val) +{ + u8 tmp = (u8) val; + return em2820_write_regs(dev, VOFFSET_REG, &tmp, 1); +} + +inline static int em2820_gamma_set(struct em2820 *dev, s32 val) +{ + u8 tmp = (u8) val; + return em2820_write_regs(dev, GAMMA_REG, &tmp, 1); +} + +/*FIXME: maxw should be dependent of alt mode */ +#define norm_maxw(dev) 720 +inline static unsigned int norm_maxh(struct em2820 *dev) +{ + return (dev->tvnorm->id & V4L2_STD_625_50) ? 576 : 480; +} + +#endif diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 6e3ba23104d..03f360b45fd 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -35,6 +35,47 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); printk(format , ##args); \ } while (0) +/* supported controls */ +static struct v4l2_queryctrl tvp5150_qctrl[] = { + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 0, + .flags = 0, + }, { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Contrast", + .minimum = 0, + .maximum = 255, + .step = 0x1, + .default_value = 0x10, + .flags = 0, + }, { + .id = V4L2_CID_SATURATION, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Saturation", + .minimum = 0, + .maximum = 255, + .step = 0x1, + .default_value = 0x10, + .flags = 0, + }, { + .id = V4L2_CID_HUE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Hue", + .minimum = -128, + .maximum = 127, + .step = 0x1, + .default_value = 0x10, + .flags = 0, + } +}; + struct tvp5150 { struct i2c_client *client; @@ -73,7 +114,7 @@ static inline void tvp5150_write(struct i2c_client *c, unsigned char addr, buffer[0] = addr; buffer[1] = value; - dprintk(1,"tvp5150: writing 0x%02x 0x%02x\n",buffer[0],buffer[1]); + dprintk(1, "tvp5150: writing 0x%02x 0x%02x\n", buffer[0], buffer[1]); if (2 != (rc = i2c_master_send(c, buffer, 2))) dprintk(0, "i2c i/o error: rc == %d (should be 2)\n", rc); } @@ -398,28 +439,11 @@ static inline void tvp5150_selmux(struct i2c_client *c, enum tvp5150_input input) { struct tvp5150 *decoder = i2c_get_clientdata(c); - int tvp_input; - - /* FIXME: It is dependent of basic driver */ - switch (input) - { - case 2: - tvp_input=TVP5150_ANALOG_CH0; - break; - case 0: - tvp_input=TVP5150_ANALOG_CH1; - break; - case 1: - tvp_input=TVP5150_SVIDEO; - break; - default: - tvp_input=TVP5150_BLACK_SCREEN; - } if (!decoder->enable) - tvp_input|=TVP5150_BLACK_SCREEN; + input |= TVP5150_BLACK_SCREEN; - tvp5150_write(c, TVP5150_VD_IN_SRC_SEL_1, tvp_input); + tvp5150_write(c, TVP5150_VD_IN_SRC_SEL_1, input); }; static inline void tvp5150_reset(struct i2c_client *c) @@ -432,7 +456,7 @@ static inline void tvp5150_reset(struct i2c_client *c) tvp5150_write(c, TVP5150_ANAL_CHL_CTL, 0x15); /* Normal Operation */ -// tvp5150_write(c, TVP5150_OP_MODE_CTL, 0x00); +// tvp5150_write(c, TVP5150_OP_MODE_CTL, 0x00); /* Activate YCrCb output 0x9 or 0xd ? */ tvp5150_write(c, TVP5150_MISC_CTL, 0x6f); @@ -458,6 +482,50 @@ static inline void tvp5150_reset(struct i2c_client *c) tvp5150_write(c, TVP5150_HUE_CTL, (decoder->hue - 32768) >> 8); }; +static int tvp5150_get_ctrl(struct i2c_client *c, struct v4l2_control *ctrl) +{ +/* struct tvp5150 *decoder = i2c_get_clientdata(c); */ + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = tvp5150_read(c, TVP5150_BRIGHT_CTL); + return 0; + case V4L2_CID_CONTRAST: + ctrl->value = tvp5150_read(c, TVP5150_CONTRAST_CTL); + return 0; + case V4L2_CID_SATURATION: + ctrl->value = tvp5150_read(c, TVP5150_SATURATION_CTL); + return 0; + case V4L2_CID_HUE: + ctrl->value = tvp5150_read(c, TVP5150_HUE_CTL); + return 0; + default: + return -EINVAL; + } +} + +static int tvp5150_set_ctrl(struct i2c_client *c, struct v4l2_control *ctrl) +{ +/* struct tvp5150 *decoder = i2c_get_clientdata(c); */ + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + tvp5150_write(c, TVP5150_BRIGHT_CTL, ctrl->value); + return 0; + case V4L2_CID_CONTRAST: + tvp5150_write(c, TVP5150_CONTRAST_CTL, ctrl->value); + return 0; + case V4L2_CID_SATURATION: + tvp5150_write(c, TVP5150_SATURATION_CTL, ctrl->value); + return 0; + case V4L2_CID_HUE: + tvp5150_write(c, TVP5150_HUE_CTL, ctrl->value); + return 0; + default: + return -EINVAL; + } +} + /**************************************************************************** I2C Command ****************************************************************************/ @@ -478,21 +546,21 @@ static int tvp5150_command(struct i2c_client *client, break; case DECODER_GET_CAPABILITIES: - { - struct video_decoder_capability *cap = arg; - - cap->flags = VIDEO_DECODER_PAL | - VIDEO_DECODER_NTSC | - VIDEO_DECODER_SECAM | - VIDEO_DECODER_AUTO | VIDEO_DECODER_CCIR; - cap->inputs = 3; - cap->outputs = 1; - break; - } + { + struct video_decoder_capability *cap = arg; + + cap->flags = VIDEO_DECODER_PAL | + VIDEO_DECODER_NTSC | + VIDEO_DECODER_SECAM | + VIDEO_DECODER_AUTO | VIDEO_DECODER_CCIR; + cap->inputs = 3; + cap->outputs = 1; + break; + } case DECODER_GET_STATUS: - { - break; - } + { + break; + } case DECODER_SET_GPIO: break; @@ -501,87 +569,138 @@ static int tvp5150_command(struct i2c_client *client, break; case DECODER_SET_NORM: - { - int *iarg = arg; + { + int *iarg = arg; - switch (*iarg) { + switch (*iarg) { - case VIDEO_MODE_NTSC: - break; + case VIDEO_MODE_NTSC: + break; - case VIDEO_MODE_PAL: - break; + case VIDEO_MODE_PAL: + break; - case VIDEO_MODE_SECAM: - break; + case VIDEO_MODE_SECAM: + break; - case VIDEO_MODE_AUTO: - break; + case VIDEO_MODE_AUTO: + break; - default: - return -EINVAL; + default: + return -EINVAL; + } + decoder->norm = *iarg; + break; } - decoder->norm = *iarg; - break; - } case DECODER_SET_INPUT: - { - int *iarg = arg; - if (*iarg < 0 || *iarg > 3) { - return -EINVAL; - } + { + int *iarg = arg; + if (*iarg < 0 || *iarg > 3) { + return -EINVAL; + } - decoder->input=*iarg; - tvp5150_selmux(client, decoder->input); + decoder->input = *iarg; + tvp5150_selmux(client, decoder->input); - break; - } + break; + } case DECODER_SET_OUTPUT: - { - int *iarg = arg; + { + int *iarg = arg; - /* not much choice of outputs */ - if (*iarg != 0) { - return -EINVAL; + /* not much choice of outputs */ + if (*iarg != 0) { + return -EINVAL; + } + break; } - break; - } case DECODER_ENABLE_OUTPUT: - { - int *iarg = arg; + { + int *iarg = arg; - decoder->enable = (*iarg != 0); + decoder->enable = (*iarg != 0); - tvp5150_selmux(client, decoder->input); + tvp5150_selmux(client, decoder->input); - break; - } - case DECODER_SET_PICTURE: - { - struct video_picture *pic = arg; - if (decoder->bright != pic->brightness) { - /* We want 0 to 255 we get 0-65535 */ - decoder->bright = pic->brightness; - tvp5150_write(client, TVP5150_BRIGHT_CTL, decoder->bright >> 8); + break; } - if (decoder->contrast != pic->contrast) { - /* We want 0 to 255 we get 0-65535 */ - decoder->contrast = pic->contrast; - tvp5150_write(client, TVP5150_CONTRAST_CTL, decoder->contrast >> 8); + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *qc = arg; + u8 i, n; + + dprintk(1, KERN_DEBUG "VIDIOC_QUERYCTRL"); + + n = sizeof(tvp5150_qctrl) / sizeof(tvp5150_qctrl[0]); + for (i = 0; i < n; i++) + if (qc->id && qc->id == tvp5150_qctrl[i].id) { + memcpy(qc, &(tvp5150_qctrl[i]), + sizeof(*qc)); + return 0; + } + + return -EINVAL; } - if (decoder->sat != pic->colour) { - /* We want 0 to 255 we get 0-65535 */ - decoder->sat = pic->colour; - tvp5150_write(client, TVP5150_SATURATION_CTL, decoder->contrast >> 8); + case VIDIOC_G_CTRL: + { + struct v4l2_control *ctrl = arg; + dprintk(1, KERN_DEBUG "VIDIOC_G_CTRL"); + + return tvp5150_get_ctrl(client, ctrl); } - if (decoder->hue != pic->hue) { - /* We want -128 to 127 we get 0-65535 */ - decoder->hue = pic->hue; - tvp5150_write(client, TVP5150_HUE_CTL, (decoder->hue - 32768) >> 8); + case VIDIOC_S_CTRL_OLD: /* ??? */ + case VIDIOC_S_CTRL: + { + struct v4l2_control *ctrl = arg; + u8 i, n; + dprintk(1, KERN_DEBUG "VIDIOC_S_CTRL"); + n = sizeof(tvp5150_qctrl) / sizeof(tvp5150_qctrl[0]); + for (i = 0; i < n; i++) + if (ctrl->id == tvp5150_qctrl[i].id) { + if (ctrl->value < + tvp5150_qctrl[i].minimum + || ctrl->value > + tvp5150_qctrl[i].maximum) + return -ERANGE; + dprintk(1, + KERN_DEBUG + "VIDIOC_S_CTRL: id=%d, value=%d", + ctrl->id, ctrl->value); + return tvp5150_set_ctrl(client, ctrl); + } + return -EINVAL; + } + + case DECODER_SET_PICTURE: + { + struct video_picture *pic = arg; + if (decoder->bright != pic->brightness) { + /* We want 0 to 255 we get 0-65535 */ + decoder->bright = pic->brightness; + tvp5150_write(client, TVP5150_BRIGHT_CTL, + decoder->bright >> 8); + } + if (decoder->contrast != pic->contrast) { + /* We want 0 to 255 we get 0-65535 */ + decoder->contrast = pic->contrast; + tvp5150_write(client, TVP5150_CONTRAST_CTL, + decoder->contrast >> 8); + } + if (decoder->sat != pic->colour) { + /* We want 0 to 255 we get 0-65535 */ + decoder->sat = pic->colour; + tvp5150_write(client, TVP5150_SATURATION_CTL, + decoder->contrast >> 8); + } + if (decoder->hue != pic->hue) { + /* We want -128 to 127 we get 0-65535 */ + decoder->hue = pic->hue; + tvp5150_write(client, TVP5150_HUE_CTL, + (decoder->hue - 32768) >> 8); + } + break; } - break; - } default: return -EINVAL; } @@ -594,15 +713,14 @@ static int tvp5150_command(struct i2c_client *client, ****************************************************************************/ static struct i2c_driver driver; -static struct i2c_client client_template = -{ - .name = "(unset)", - .flags = I2C_CLIENT_ALLOW_USE, - .driver = &driver, +static struct i2c_client client_template = { + .name = "(unset)", + .flags = I2C_CLIENT_ALLOW_USE, + .driver = &driver, }; -static int tvp5150_detect_client (struct i2c_adapter *adapter, - int address, int kind) +static int tvp5150_detect_client(struct i2c_adapter *adapter, + int address, int kind) { struct i2c_client *client; struct tvp5150 *core; @@ -625,7 +743,7 @@ static int tvp5150_detect_client (struct i2c_adapter *adapter, client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); if (client == 0) return -ENOMEM; - memcpy(client,&client_template,sizeof(struct i2c_client)); + memcpy(client, &client_template, sizeof(struct i2c_client)); core = kmalloc(sizeof(struct tvp5150), GFP_KERNEL); if (core == 0) { @@ -651,13 +769,13 @@ static int tvp5150_detect_client (struct i2c_adapter *adapter, return rv; } - dump_reg (client); + if (debug > 1) + dump_reg(client); return 0; } -static int -tvp5150_attach_adapter (struct i2c_adapter *adapter) +static int tvp5150_attach_adapter(struct i2c_adapter *adapter) { dprintk(1, KERN_INFO @@ -666,8 +784,7 @@ tvp5150_attach_adapter (struct i2c_adapter *adapter) return i2c_probe(adapter, &addr_data, &tvp5150_detect_client); } -static int -tvp5150_detach_client (struct i2c_client *client) +static int tvp5150_detach_client(struct i2c_client *client) { struct tvp5150 *decoder = i2c_get_clientdata(client); int err; @@ -699,14 +816,12 @@ static struct i2c_driver driver = { .command = tvp5150_command, }; -static int __init -tvp5150_init (void) +static int __init tvp5150_init(void) { return i2c_add_driver(&driver); } -static void __exit -tvp5150_exit (void) +static void __exit tvp5150_exit(void) { i2c_del_driver(&driver); } -- cgit v1.2.3 From 3c1904a997153b17861bd331c9075017ba34b901 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:08 -0800 Subject: [PATCH] v4l: 717: added scripts and cardlist for em2820 - Added scripts and CARDLIST for em2820. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.em28xx | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 Documentation/video4linux/CARDLIST.em28xx diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx new file mode 100644 index 00000000000..a33ddea0b6f --- /dev/null +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -0,0 +1,4 @@ + 0 -> Terratec Cinergy 250 USB [0ccd:0036] + 1 -> Pinnacle PCTV USB 2 [2304:0208] + 2 -> Hauppauge WinTV USB 2 [2040:4200] + 3 -> MSI VOX USB 2.0 [eb1a:2820] -- cgit v1.2.3 From fd35a6b454818e01f761622e9ac5824ce2d7baf5 Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:37:09 -0800 Subject: [PATCH] v4l: 718: fixed build - Fixed build. Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-i2c.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 95f80a7615b..f1493c48656 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -279,10 +279,8 @@ static void dec_use(struct i2c_adapter *adap) static int em2820_set_tuner(int check_eeprom, struct i2c_client *client) { struct em2820 *dev = client->adapter->algo_data; - struct tuner_setup tun_setup; - /* tuner */ if (dev->has_tuner) { tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; tun_setup.type = dev->tuner_type; @@ -290,6 +288,7 @@ static int em2820_set_tuner(int check_eeprom, struct i2c_client *client) em2820_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); } + return (0); } -- cgit v1.2.3 From 2f8d4f5139fe7817f43202d8ee2f4b68ac53e58f Mon Sep 17 00:00:00 2001 From: "Robert W. Boone" Date: Tue, 8 Nov 2005 21:37:10 -0800 Subject: [PATCH] v4l: 719: implement some differences in video output port - Implement some differences in video output port Signed-off-by: Robert W. Boone Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-cards.c | 4 ++ drivers/media/video/saa7134/saa7134-video.c | 58 +++++++++++++++++++++++++++-- drivers/media/video/saa7134/saa7134.h | 9 +++++ 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 7278150fb58..3a4c59e7ca0 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2285,6 +2285,10 @@ struct saa7134_board saa7134_boards[] = { }}, .mpeg = SAA7134_MPEG_EMPRESS, .video_out = CCIR656, + .vid_port_opts = ( SET_T_CODE_POLARITY_NON_INVERTED | + SET_CLOCK_NOT_DELAYED | + SET_CLOCK_INVERTED | + SET_VSYNC_OFF ), }, [SAA7134_BOARD_RTD_VFG7330] = { .name = "RTD Embedded Technologies VFG7330", diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index cd1f70fffde..cd5545b2d60 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -47,6 +47,43 @@ MODULE_PARM_DESC(noninterlaced,"video input is noninterlaced"); #define dprintk(fmt, arg...) if (video_debug) \ printk(KERN_DEBUG "%s/video: " fmt, dev->name , ## arg) +/* ------------------------------------------------------------------ */ +/* Defines for Video Output Port Register at address 0x191 */ + +/* Bit 0: VIP code T bit polarity */ + +#define VP_T_CODE_P_NON_INVERTED 0x00 +#define VP_T_CODE_P_INVERTED 0x01 + +/* ------------------------------------------------------------------ */ +/* Defines for Video Output Port Register at address 0x195 */ + +/* Bit 2: Video output clock delay control */ + +#define VP_CLK_CTRL2_NOT_DELAYED 0x00 +#define VP_CLK_CTRL2_DELAYED 0x04 + +/* Bit 1: Video output clock invert control */ + +#define VP_CLK_CTRL1_NON_INVERTED 0x00 +#define VP_CLK_CTRL1_INVERTED 0x02 + +/* ------------------------------------------------------------------ */ +/* Defines for Video Output Port Register at address 0x196 */ + +/* Bits 2 to 0: VSYNC pin video vertical sync type */ + +#define VP_VS_TYPE_MASK 0x07 + +#define VP_VS_TYPE_OFF 0x00 +#define VP_VS_TYPE_V123 0x01 +#define VP_VS_TYPE_V_ITU 0x02 +#define VP_VS_TYPE_VGATE_L 0x03 +#define VP_VS_TYPE_RESERVED1 0x04 +#define VP_VS_TYPE_RESERVED2 0x05 +#define VP_VS_TYPE_F_ITU 0x06 +#define VP_VS_TYPE_SC_FID 0x07 + /* ------------------------------------------------------------------ */ /* data structs for video */ @@ -2294,13 +2331,28 @@ int saa7134_video_init1(struct saa7134_dev *dev) if (saa7134_boards[dev->board].video_out) { /* enable video output */ int vo = saa7134_boards[dev->board].video_out; + int video_reg; + unsigned int vid_port_opts = saa7134_boards[dev->board].vid_port_opts; saa_writeb(SAA7134_VIDEO_PORT_CTRL0, video_out[vo][0]); - saa_writeb(SAA7134_VIDEO_PORT_CTRL1, video_out[vo][1]); + video_reg = video_out[vo][1]; + if (vid_port_opts & SET_T_CODE_POLARITY_NON_INVERTED) + video_reg &= ~VP_T_CODE_P_INVERTED; + saa_writeb(SAA7134_VIDEO_PORT_CTRL1, video_reg); saa_writeb(SAA7134_VIDEO_PORT_CTRL2, video_out[vo][2]); saa_writeb(SAA7134_VIDEO_PORT_CTRL3, video_out[vo][3]); saa_writeb(SAA7134_VIDEO_PORT_CTRL4, video_out[vo][4]); - saa_writeb(SAA7134_VIDEO_PORT_CTRL5, video_out[vo][5]); - saa_writeb(SAA7134_VIDEO_PORT_CTRL6, video_out[vo][6]); + video_reg = video_out[vo][5]; + if (vid_port_opts & SET_CLOCK_NOT_DELAYED) + video_reg &= ~VP_CLK_CTRL2_DELAYED; + if (vid_port_opts & SET_CLOCK_INVERTED) + video_reg |= VP_CLK_CTRL1_INVERTED; + saa_writeb(SAA7134_VIDEO_PORT_CTRL5, video_reg); + video_reg = video_out[vo][6]; + if (vid_port_opts & SET_VSYNC_OFF) { + video_reg &= ~VP_VS_TYPE_MASK; + video_reg |= VP_VS_TYPE_OFF; + } + saa_writeb(SAA7134_VIDEO_PORT_CTRL6, video_reg); saa_writeb(SAA7134_VIDEO_PORT_CTRL7, video_out[vo][7]); saa_writeb(SAA7134_VIDEO_PORT_CTRL8, video_out[vo][8]); } diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index e907d86da7b..9dfd45bed92 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -199,6 +199,14 @@ struct saa7134_format { #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 +/* ----------------------------------------------------------- */ +/* Video Output Port Register Initialization Options */ + +#define SET_T_CODE_POLARITY_NON_INVERTED (1 << 0) +#define SET_CLOCK_NOT_DELAYED (1 << 1) +#define SET_CLOCK_INVERTED (1 << 2) +#define SET_VSYNC_OFF (1 << 3) + struct saa7134_input { char *name; unsigned int vmux; @@ -234,6 +242,7 @@ struct saa7134_board { /* peripheral I/O */ enum saa7134_video_out video_out; enum saa7134_mpeg_type mpeg; + unsigned int vid_port_opts; }; #define card_has_radio(dev) (NULL != saa7134_boards[dev->board].radio.name) -- cgit v1.2.3 From bd15eba3a0f2b175bd80c21d5fc86c02ed4c56f6 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Tue, 8 Nov 2005 21:37:11 -0800 Subject: [PATCH] v4l: 720: alsa support for saa7134 that should work wonderful - Alsa support for saa7134 that should work. Signed-off-by: Ricardo Cerqueira Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-alsa.c | 1076 +++++++++++++++++----------- drivers/media/video/saa7134/saa7134-core.c | 23 +- drivers/media/video/saa7134/saa7134-oss.c | 5 +- drivers/media/video/saa7134/saa7134-reg.h | 8 + drivers/media/video/saa7134/saa7134.h | 10 + 5 files changed, 718 insertions(+), 404 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index d09e01f7fc3..84eeeba21d7 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -1,543 +1,821 @@ /* + * SAA713x ALSA support for V4L + * Ricardo Cerqueira * - * Support for audio capture - * PCI function #1 of the saa7134 * - * (c) 2005 Mauro Carvalho Chehab - * (c) 2004 Gerd Knorr - * (c) 2003 Clemens Ladisch + * Caveats: + * I still haven't got the mixer settings right. * - * 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 option) any later version. + * - Volume doesn't work (it's always at max) + * - There's no "memory" of the capture channel. It can be changed, + * but alsamixer doesn't show it after a module restart (rmmod/insmod) * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Hotswapping DOES NOT work yet! Please remove the module before + * inserting cardbus cards. pcmcia-cs or pccardd should load it + * properly after insertion, and things will work + * + * 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, version 2 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include #include -#include -#include #include +#include +#include #include #include "saa7134.h" #include "saa7134-reg.h" -#define dprintk(level,fmt, arg...) if (debug >= level) \ - printk(KERN_DEBUG "%s/1: " fmt, chip->core->name , ## arg) - - -/**************************************************************************** - Data type declarations - Can be moded to a header file later - ****************************************************************************/ - -#define ANALOG_CLOCK 1792000 -#define CLOCK_DIV_MIN 4 -#define CLOCK_DIV_MAX 15 -#define MAX_PCM_DEVICES 4 -#define MAX_PCM_SUBSTREAMS 16 +static unsigned int alsa_debug = 0; +module_param(alsa_debug, int, 0644); +MODULE_PARM_DESC(alsa_debug,"enable debug messages [alsa]"); + +#define MAX_PCM_DEVICES 1 +#define MAX_PCM_SUBSTREAMS 1 + +/* defaults */ +#define MAX_BUFFER_SIZE (256*1024) +#define USE_FORMATS SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE +#define USE_RATE SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 +#define USE_RATE_MIN 32000 +#define USE_RATE_MAX 48000 +#define USE_CHANNELS_MIN 1 +#define USE_CHANNELS_MAX 2 +#ifndef USE_PERIODS_MIN +#define USE_PERIODS_MIN 2 +#endif +#ifndef USE_PERIODS_MAX +#define USE_PERIODS_MAX 1024 +#endif -enum { DEVICE_DIGITAL, DEVICE_ANALOG }; -/* These can be replaced after done */ -#define MIXER_ADDR_LAST MAX_saa7134_INPUT +#define dprintk(fmt, arg...) if (alsa_debug) \ + printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ## arg) -struct saa7134_audio_dev { - struct saa7134_core *core; - struct saa7134_buffer *buf; - struct saa7134_dmaqueue q; - /* pci i/o */ - struct pci_dev *pci; - unsigned char pci_rev,pci_lat; +static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ +static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ +static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; + +#define MIXER_ADDR_TVTUNER 0 +#define MIXER_ADDR_LINE1 1 +#define MIXER_ADDR_LINE2 2 +#define MIXER_ADDR_LAST 2 + +typedef struct snd_card_saa7134 { + snd_card_t *card; + spinlock_t mixer_lock; + int mixer_volume[MIXER_ADDR_LAST+1][2]; + int capture_source[MIXER_ADDR_LAST+1][2]; + struct pci_dev *pci; + struct saa7134_dev *saadev; + + unsigned long iobase; + int irq; + + spinlock_t lock; +} snd_card_saa7134_t; + +typedef struct snd_card_saa7134_pcm { + struct saa7134_dev *saadev; + + spinlock_t lock; + unsigned int pcm_size; /* buffer size */ + unsigned int pcm_count; /* bytes per period */ + unsigned int pcm_bps; /* bytes per second */ + snd_pcm_substream_t *substream; +} snd_card_saa7134_pcm_t; - /* audio controls */ - int irq; - int dig_rate; /* Digital sampling rate */ +static snd_card_t *snd_saa7134_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; - snd_card_t *card; +static void saa7134_dma_stop(struct saa7134_dev *dev) +{ + dev->oss.dma_blk = -1; + dev->oss.dma_running = 0; + saa7134_set_dmabits(dev); +} - spinlock_t reg_lock; +static void saa7134_dma_start(struct saa7134_dev *dev) +{ + dev->oss.dma_blk = 0; + dev->oss.dma_running = 1; + saa7134_set_dmabits(dev); +} - unsigned int dma_size; - unsigned int period_size; +void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) +{ + int next_blk, reg = 0; - int mixer_volume[MIXER_ADDR_LAST+1][2]; - int capture_source[MIXER_ADDR_LAST+1][2]; + spin_lock(&dev->slock); + if (UNSET == dev->oss.dma_blk) { + dprintk("irq: recording stopped\n"); + goto done; + } + if (0 != (status & 0x0f000000)) + dprintk("irq: lost %ld\n", (status >> 24) & 0x0f); + if (0 == (status & 0x10000000)) { + /* odd */ + if (0 == (dev->oss.dma_blk & 0x01)) + reg = SAA7134_RS_BA1(6); + } else { + /* even */ + if (1 == (dev->oss.dma_blk & 0x01)) + reg = SAA7134_RS_BA2(6); + } + if (0 == reg) { + dprintk("irq: field oops [%s]\n", + (status & 0x10000000) ? "even" : "odd"); + goto done; + } - long opened; - snd_pcm_substream_t *substream; -}; -typedef struct saa7134_audio_dev snd_saa7134_card_t; + if (dev->oss.read_count >= dev->oss.blksize * (dev->oss.blocks-2)) { + dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->oss.read_count, + dev->oss.bufsize, dev->oss.blocks); + saa7134_dma_stop(dev); + goto done; + } -/**************************************************************************** - Module global static vars - ****************************************************************************/ + /* next block addr */ + next_blk = (dev->oss.dma_blk + 2) % dev->oss.blocks; + saa_writel(reg,next_blk * dev->oss.blksize); + if (alsa_debug > 2) + dprintk("irq: ok, %s, next_blk=%d, addr=%x, blocks=%u, size=%u, read=%u\n", + (status & 0x10000000) ? "even" : "odd ", next_blk, + next_blk * dev->oss.blksize, dev->oss.blocks, dev->oss.blksize, dev->oss.read_count); -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable saa7134x soundcard. default enabled."); + /* update status & wake waiting readers */ + dev->oss.dma_blk = (dev->oss.dma_blk + 1) % dev->oss.blocks; + dev->oss.read_count += dev->oss.blksize; -/**************************************************************************** - Module macros - ****************************************************************************/ + dev->oss.recording_on = reg; -MODULE_DESCRIPTION("ALSA driver module for saa7134 based TV cards"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Philips, saa7131E}," - "{{Philips, saa7134}," - "{{Philips, saa7133}"); -static unsigned int debug = 0; -module_param(debug,int,0644); -MODULE_PARM_DESC(debug,"enable debug messages"); + if (dev->oss.read_count >= snd_pcm_lib_period_bytes(dev->oss.substream)) { + spin_unlock(&dev->slock); + snd_pcm_period_elapsed(dev->oss.substream); + spin_lock(&dev->slock); + } + done: + spin_unlock(&dev->slock); -/**************************************************************************** - Module specific funtions - ****************************************************************************/ +} -/* - * BOARD Specific: Sets audio DMA - */ -int saa7134_start_audio_dma(snd_saa7134_card_t *chip) +static int snd_card_saa7134_capture_trigger(snd_pcm_substream_t * substream, + int cmd) { - struct saa7134_core *core = chip->core; - return 0; } -/* - * BOARD Specific: Resets audio DMA - */ -int saa7134_stop_audio_dma(snd_saa7134_card_t *chip) +static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) { - struct saa7134_core *core=chip->core; - return 0; + if (blksize < 0x100) + blksize = 0x100; + if (blksize > 0x10000) + blksize = 0x10000; + + if (blocks < 2) + blocks = 2; + if ((blksize * blocks) > 1024*1024) + blocks = 1024*1024 / blksize; + + dev->oss.blocks = blocks; + dev->oss.blksize = blksize; + dev->oss.bufsize = blksize * blocks; + + dprintk("buffer config: %d blocks / %d bytes, %d kB total\n", + blocks,blksize,blksize * blocks / 1024); + return 0; } -#define MAX_IRQ_LOOP 10 - -static void saa713401_timeout(unsigned long data) +static int dsp_buffer_init(struct saa7134_dev *dev) { - snd_saa7134_card_t *chip = (snd_saa7134_card_t *)data; + int err; + + if (!dev->oss.bufsize) + BUG(); + videobuf_dma_init(&dev->oss.dma); + err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE, + (dev->oss.bufsize + PAGE_SIZE) >> PAGE_SHIFT); + if (0 != err) + return err; + return 0; } -/* FIXME: Wrong values*/ -static char *saa7134_aud_irqs[32] = { - "y_risci1", "u_risci1", "v_risci1", "vbi_risc1", - "y_risci2", "u_risci2", "v_risci2", "vbi_risc2", - "y_oflow", "u_oflow", "v_oflow", "vbi_oflow", - "y_sync", "u_sync", "v_sync", "vbi_sync", - "opc_err", "par_err", "rip_err", "pci_abort", -}; - -static void saa713401_aud_irq(snd_saa7134_card_t *chip) +static int snd_card_saa7134_pcm_prepare(snd_pcm_substream_t * substream) { - struct saa7134_core *core = chip->core; -} + snd_pcm_runtime_t *runtime = substream->runtime; + int err, bswap, sign; + u32 fmt, control; + unsigned long flags; + snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); + struct saa7134_dev *dev; + snd_card_saa7134_pcm_t *saapcm = runtime->private_data; + unsigned int bps; + unsigned long size; + unsigned count; + + size = snd_pcm_lib_buffer_bytes(substream); + count = snd_pcm_lib_period_bytes(substream); + + saapcm->saadev->oss.substream = substream; + bps = runtime->rate * runtime->channels; + bps *= snd_pcm_format_width(runtime->format); + bps /= 8; + if (bps <= 0) + return -EINVAL; + saapcm->pcm_bps = bps; + saapcm->pcm_size = snd_pcm_lib_buffer_bytes(substream); + saapcm->pcm_count = snd_pcm_lib_period_bytes(substream); + + + dev=saa7134->saadev; + + dsp_buffer_conf(dev,saapcm->pcm_count,(saapcm->pcm_size/saapcm->pcm_count)); + + err = dsp_buffer_init(dev); + if (0 != err) + goto fail2; + + /* prepare buffer */ + if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->oss.dma))) + return err; + if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->oss.pt))) + goto fail1; + if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->oss.pt, + dev->oss.dma.sglist, + dev->oss.dma.sglen, + 0))) + goto fail2; + + + + switch (runtime->format) { + case SNDRV_PCM_FORMAT_U8: + case SNDRV_PCM_FORMAT_S8: + fmt = 0x00; + break; + case SNDRV_PCM_FORMAT_U16_LE: + case SNDRV_PCM_FORMAT_U16_BE: + case SNDRV_PCM_FORMAT_S16_LE: + case SNDRV_PCM_FORMAT_S16_BE: + fmt = 0x01; + break; + default: + err = -EINVAL; + return 1; + } + + switch (runtime->format) { + case SNDRV_PCM_FORMAT_S8: + case SNDRV_PCM_FORMAT_S16_LE: + case SNDRV_PCM_FORMAT_S16_BE: + sign = 1; + break; + default: + sign = 0; + break; + } + + switch (runtime->format) { + case SNDRV_PCM_FORMAT_U16_BE: + case SNDRV_PCM_FORMAT_S16_BE: + bswap = 1; break; + default: + bswap = 0; break; + } + + switch (dev->pci->device) { + case PCI_DEVICE_ID_PHILIPS_SAA7134: + if (1 == runtime->channels) + fmt |= (1 << 3); + if (2 == runtime->channels) + fmt |= (3 << 3); + if (sign) + fmt |= 0x04; + + fmt |= (MIXER_ADDR_TVTUNER == dev->oss.input) ? 0xc0 : 0x80; + saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->oss.blksize - 1) & 0x0000ff)); + saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->oss.blksize - 1) & 0x00ff00) >> 8); + saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->oss.blksize - 1) & 0xff0000) >> 16); + saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt); + + break; + case PCI_DEVICE_ID_PHILIPS_SAA7133: + case PCI_DEVICE_ID_PHILIPS_SAA7135: + if (1 == runtime->channels) + fmt |= (1 << 4); + if (2 == runtime->channels) + fmt |= (2 << 4); + if (!sign) + fmt |= 0x04; + //saa_writel(SAA7133_NUM_SAMPLES, dev->oss.blksize -1); + saa_writel(SAA7133_NUM_SAMPLES, dev->oss.blksize -1); + saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24)); + //saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210); + break; + } + + dprintk("rec_start: afmt=%d ch=%d => fmt=0x%x swap=%c\n", + runtime->format, runtime->channels, fmt, + bswap ? 'b' : '-'); + /* dma: setup channel 6 (= AUDIO) */ + control = SAA7134_RS_CONTROL_BURST_16 | + SAA7134_RS_CONTROL_ME | + (dev->oss.pt.dma >> 12); + if (bswap) + control |= SAA7134_RS_CONTROL_BSWAP; + + runtime->dma_area = dev->oss.dma.vmalloc; + saa_writel(SAA7134_RS_BA1(6),0); + saa_writel(SAA7134_RS_BA2(6),dev->oss.blksize); + saa_writel(SAA7134_RS_PITCH(6),0); + saa_writel(SAA7134_RS_CONTROL(6),control); + + dev->oss.rate = runtime->rate; + /* start dma */ + spin_lock_irqsave(&dev->slock,flags); + saa7134_dma_start(dev); + spin_unlock_irqrestore(&dev->slock,flags); -static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs) -{ - snd_saa7134_card_t *chip = dev_id; - struct saa7134_core *core = chip->core; -} + return 0; + fail2: + saa7134_pgtable_free(dev->pci,&dev->oss.pt); + fail1: + videobuf_dma_pci_unmap(dev->pci,&dev->oss.dma); + return err; -/**************************************************************************** - ALSA PCM Interface - ****************************************************************************/ -/* - * Digital hardware definition - */ -static snd_pcm_hardware_t snd_saa7134_digital_hw = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = 0, /* set at runtime */ - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 255 * 4092, - .period_bytes_min = 32, - .period_bytes_max = 4092, - .periods_min = 2, - .periods_max = 255, -}; +} -/* - * Sets board to provide digital audio - */ -static int snd_saa7134_set_digital_hw(snd_saa7134_card_t *chip, snd_pcm_runtime_t *runtime) +static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) { - return 0; + return snd_card_saa7134_pcm_prepare(substream); } -/* - * audio open callback - */ -static int snd_saa7134_pcm_open(snd_pcm_substream_t *substream) +static snd_pcm_uframes_t snd_card_saa7134_pointer(snd_pcm_substream_t * substream) { - snd_saa7134_card_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; - int err; + snd_card_saa7134_pcm_t *saapcm = runtime->private_data; + struct saa7134_dev *dev=saapcm->saadev; - if (test_and_set_bit(0, &chip->opened)) - return -EBUSY; - err = snd_saa7134_set_digital_hw(chip, runtime); - if (err < 0) - goto _error; + if (dev->oss.read_count) { + dev->oss.read_count -= snd_pcm_lib_period_bytes(substream); + dev->oss.read_offset += snd_pcm_lib_period_bytes(substream); + if (dev->oss.read_offset == dev->oss.bufsize) + dev->oss.read_offset = 0; + } - err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - if (err < 0) - goto _error; + //return bytes_to_frames(runtime, saa_readl(dev->oss.recording_on)); + return bytes_to_frames(runtime, dev->oss.read_offset); +} - chip->substream = substream; - return 0; -_error: - clear_bit(0, &chip->opened); - smp_mb__after_clear_bit(); - return err; +static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * substream) +{ + return snd_card_saa7134_pointer(substream); } -/* - * audio close callback - */ -static int snd_saa7134_close(snd_pcm_substream_t *substream) +static snd_pcm_hardware_t snd_card_saa7134_capture = { - snd_saa7134_card_t *chip = snd_pcm_substream_chip(substream); + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID), + .formats = USE_FORMATS, + .rates = USE_RATE, + .rate_min = USE_RATE_MIN, + .rate_max = USE_RATE_MAX, + .channels_min = USE_CHANNELS_MIN, + .channels_max = USE_CHANNELS_MAX, + .buffer_bytes_max = MAX_BUFFER_SIZE, + .period_bytes_min = 64, + .period_bytes_max = MAX_BUFFER_SIZE, + .periods_min = USE_PERIODS_MIN, + .periods_max = USE_PERIODS_MAX, + .fifo_size = 0x08070503, +}; - chip->substream = NULL; - clear_bit(0, &chip->opened); - smp_mb__after_clear_bit(); - return 0; +static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime) +{ + snd_card_saa7134_pcm_t *saapcm = runtime->private_data; + + kfree(saapcm); } -/* - * hw_params callback - */ -static int snd_saa7134_hw_params(snd_pcm_substream_t * substream, - snd_pcm_hw_params_t * hw_params) + +static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, + snd_pcm_hw_params_t * hw_params) { + return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); + + } -/* - * hw free callback - */ -static int snd_saa7134_hw_free(snd_pcm_substream_t * substream) +static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream) { return snd_pcm_lib_free_pages(substream); } -/* - * prepare callback - */ -static int snd_saa7134_prepare(snd_pcm_substream_t *substream) +static int dsp_buffer_free(struct saa7134_dev *dev) { - snd_saa7134_card_t *chip = snd_pcm_substream_chip(substream); - return 0; -} + if (!dev->oss.blksize) + BUG(); + videobuf_dma_free(&dev->oss.dma); -/* - * trigger callback - */ -static int snd_saa7134_card_trigger(snd_pcm_substream_t *substream, int cmd) -{ - snd_saa7134_card_t *chip = snd_pcm_substream_chip(substream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - return snd_saa7134_start(chip); - case SNDRV_PCM_TRIGGER_STOP: - return snd_saa7134_stop(chip); - default: - return -EINVAL; - } + dev->oss.blocks = 0; + dev->oss.blksize = 0; + dev->oss.bufsize = 0; + + return 0; } -/* - * pointer callback - */ -static snd_pcm_uframes_t snd_saa7134_pointer(snd_pcm_substream_t *substream) + +static int saa7134_cap_close(struct saa7134_dev *dev) { -// snd_saa7134_card_t *chip = snd_pcm_substream_chip(substream); -// snd_pcm_runtime_t *runtime = substream->runtime; + unsigned long flags; + + /* stop dma */ + spin_lock_irqsave(&dev->slock,flags); + saa7134_dma_stop(dev); + spin_unlock_irqrestore(&dev->slock,flags); + + /* unlock buffer */ + saa7134_pgtable_free(dev->pci,&dev->oss.pt); + videobuf_dma_pci_unmap(dev->pci,&dev->oss.dma); -// return (snd_pcm_uframes_t)bytes_to_frames(runtime, chip->current_line * chip->line_bytes); + dsp_buffer_free(dev); + return 0; } -/* - * operators - */ -static snd_pcm_ops_t snd_saa7134_pcm_ops = { - .open = snd_saa7134_pcm_open, - .close = snd_saa7134_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_saa7134_hw_params, - .hw_free = snd_saa7134_hw_free, - .prepare = snd_saa7134_prepare, - .trigger = snd_saa7134_card_trigger, - .pointer = snd_saa7134_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; -/* - * create a PCM device - */ -static int __devinit snd_saa7134_pcm(snd_saa7134_card_t *chip, int device, char *name) -{ - int err; - snd_pcm_t *pcm; +static int saa7134_cap_open(struct saa7134_dev *dev) { - err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm); - if (err < 0) - return err; - pcm->private_data = chip; - strcpy(pcm->name, name); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_saa7134_pcm_ops); - return snd_pcm_lib_preallocate_pages_for_all(pcm, - SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(chip->pci), - 128 * 1024, - (255 * 4092 + 1023) & ~1023); -} + down(&dev->oss.lock); -/**************************************************************************** - CONTROL INTERFACE - ****************************************************************************/ -static int snd_saa7134_capture_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *info) -{ - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = 1; - info->value.integer.min = 0; - info->value.integer.max = 0x3f; + dev->oss.afmt = SNDRV_PCM_FORMAT_U8; + dev->oss.channels = 2; + dev->oss.read_count = 0; + dev->oss.read_offset = 0; + + up(&dev->oss.lock); return 0; } -/* OK - TODO: test it */ -static int snd_saa7134_capture_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value) +static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) { - snd_saa7134_card_t *chip = snd_kcontrol_chip(kcontrol); - struct saa7134_core *core=chip->core; + snd_pcm_runtime_t *runtime = substream->runtime; + snd_card_saa7134_pcm_t *saapcm; + snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); + int err; + + saa7134_cap_open(saa7134->saadev); + + saapcm = kcalloc(1, sizeof(*saapcm), GFP_KERNEL); + if (saapcm == NULL) + return -ENOMEM; + saapcm->saadev=saa7134->saadev; + + spin_lock_init(&saapcm->lock); + + saapcm->substream = substream; + runtime->private_data = saapcm; + runtime->private_free = snd_card_saa7134_runtime_free; + runtime->hw = snd_card_saa7134_capture; + + if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + return err; return 0; } -/* OK - TODO: test it */ -static int snd_saa7134_capture_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value) +static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) { - snd_saa7134_card_t *chip = snd_kcontrol_chip(kcontrol); - struct saa7134_core *core=chip->core; + snd_card_saa7134_t *chip = snd_pcm_substream_chip(substream); + saa7134_cap_close(chip->saadev); return 0; } -static snd_kcontrol_new_t snd_saa7134_capture_volume = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Volume", - .info = snd_saa7134_capture_volume_info, - .get = snd_saa7134_capture_volume_get, - .put = snd_saa7134_capture_volume_put, +static snd_pcm_ops_t snd_card_saa7134_capture_ops = { + .open = snd_card_saa7134_capture_open, + .close = snd_card_saa7134_capture_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = snd_card_saa7134_hw_params, + .hw_free = snd_card_saa7134_hw_free, + .prepare = snd_card_saa7134_capture_prepare, + .trigger = snd_card_saa7134_capture_trigger, + .pointer = snd_card_saa7134_capture_pointer, }; -/* - *************************************** - */ +static int __init snd_card_saa7134_pcm(snd_card_saa7134_t *saa7134, int device) +{ + snd_pcm_t *pcm; + int err; -/**************************************************************************** - Basic Flow for Sound Devices - ****************************************************************************/ + if ((err = snd_pcm_new(saa7134->card, "SAA7134 PCM", device, 0, 1, &pcm)) < 0) + return err; + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_saa7134_capture_ops); + pcm->private_data = saa7134; + pcm->info_flags = 0; + strcpy(pcm->name, "SAA7134 PCM"); + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, + snd_dma_pci_data(saa7134->pci), + 128*1024, 256*1024); + return 0; +} -/* - * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio - * Only boards with eeprom and byte 1 at eeprom=1 have it - */ +#define SAA713x_VOLUME(xname, xindex, addr) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ + .info = snd_saa7134_volume_info, \ + .get = snd_saa7134_volume_get, .put = snd_saa7134_volume_put, \ + .private_value = addr } -struct pci_device_id saa7134_audio_pci_tbl[] = { - {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, - {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, - {0, } -}; -MODULE_DEVICE_TABLE(pci, saa7134_audio_pci_tbl); +static int snd_saa7134_volume_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 20; + return 0; +} -/* - * Chip-specific destructor - */ +static int snd_saa7134_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +{ + snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); + unsigned long flags; + int addr = kcontrol->private_value; + + spin_lock_irqsave(&chip->mixer_lock, flags); + ucontrol->value.integer.value[0] = chip->mixer_volume[addr][0]; + ucontrol->value.integer.value[1] = chip->mixer_volume[addr][1]; + spin_unlock_irqrestore(&chip->mixer_lock, flags); + return 0; +} -static int snd_saa7134_free(snd_saa7134_card_t *chip) +static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { - if (chip->irq >= 0) - free_irq(chip->irq, chip); + snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); + unsigned long flags; + int change, addr = kcontrol->private_value; + int left, right; + + left = ucontrol->value.integer.value[0]; + if (left < 0) + left = 0; + if (left > 20) + left = 20; + right = ucontrol->value.integer.value[1]; + if (right < 0) + right = 0; + if (right > 20) + right = 20; + spin_lock_irqsave(&chip->mixer_lock, flags); + change = chip->mixer_volume[addr][0] != left || + chip->mixer_volume[addr][1] != right; + chip->mixer_volume[addr][0] = left; + chip->mixer_volume[addr][1] = right; + spin_unlock_irqrestore(&chip->mixer_lock, flags); + return change; +} - /* free memory */ - saa7134_core_put(chip->core,chip->pci); +#define SAA713x_CAPSRC(xname, xindex, addr) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ + .info = snd_saa7134_capsrc_info, \ + .get = snd_saa7134_capsrc_get, .put = snd_saa7134_capsrc_put, \ + .private_value = addr } - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); +static int snd_saa7134_capsrc_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} - kfree(chip); +static int snd_saa7134_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +{ + snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); + unsigned long flags; + int addr = kcontrol->private_value; + + spin_lock_irqsave(&chip->mixer_lock, flags); + ucontrol->value.integer.value[0] = chip->capture_source[addr][0]; + ucontrol->value.integer.value[1] = chip->capture_source[addr][1]; + spin_unlock_irqrestore(&chip->mixer_lock, flags); return 0; } -/* - * Component Destructor - */ -static int snd_saa7134_dev_free(snd_device_t *device) +static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { - snd_saa7134_card_t *chip = device->device_data; - return snd_saa7134_free(chip); + snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); + unsigned long flags; + int change, addr = kcontrol->private_value; + int left, right; + u32 anabar, xbarin; + int analog_io, rate; + struct saa7134_dev *dev; + + dev = chip->saadev; + + left = ucontrol->value.integer.value[0] & 1; + right = ucontrol->value.integer.value[1] & 1; + spin_lock_irqsave(&chip->mixer_lock, flags); + + change = chip->capture_source[addr][0] != left && + chip->capture_source[addr][1] != right; + chip->capture_source[addr][0] = left; + chip->capture_source[addr][1] = right; + dev->oss.input=addr; + spin_unlock_irqrestore(&chip->mixer_lock, flags); + + + switch (dev->pci->device) { + + case PCI_DEVICE_ID_PHILIPS_SAA7134: + switch (addr) { + case MIXER_ADDR_TVTUNER: + saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0xc0); + saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, 0x00); + break; + case MIXER_ADDR_LINE1: + case MIXER_ADDR_LINE2: + analog_io = (MIXER_ADDR_LINE1 == addr) ? 0x00 : 0x08; + rate = (32000 == dev->oss.rate) ? 0x01 : 0x03; + saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, analog_io); + saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0x80); + saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, rate); + break; + } + + case PCI_DEVICE_ID_PHILIPS_SAA7133: + case PCI_DEVICE_ID_PHILIPS_SAA7135: + xbarin = 0x03; // adc + anabar = 0; + switch (addr) { + case MIXER_ADDR_TVTUNER: + xbarin = 0; // Demodulator + anabar = 2; // DACs + break; + case MIXER_ADDR_LINE1: + anabar = 0; // aux1, aux1 + break; + case MIXER_ADDR_LINE2: + anabar = 9; // aux2, aux2 + break; + } + + /* output xbar always main channel */ + saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL1, 0xbbbb10); + + if (left || right) { // We've got data, turn the input on + //saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL2, 0x101010); + saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, xbarin); + saa_writel(SAA7133_ANALOG_IO_SELECT, anabar); + } else { + //saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL2, 0x101010); + saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, 0); + saa_writel(SAA7133_ANALOG_IO_SELECT, 0); + } + } + + return change; } +static snd_kcontrol_new_t snd_saa7134_controls[] = { +SAA713x_VOLUME("Video Volume", 0, MIXER_ADDR_TVTUNER), +SAA713x_CAPSRC("Video Capture Switch", 0, MIXER_ADDR_TVTUNER), +SAA713x_VOLUME("Line Volume", 1, MIXER_ADDR_LINE1), +SAA713x_CAPSRC("Line Capture Switch", 1, MIXER_ADDR_LINE1), +SAA713x_VOLUME("Line Volume", 2, MIXER_ADDR_LINE2), +SAA713x_CAPSRC("Line Capture Switch", 2, MIXER_ADDR_LINE2), +}; -/* - * Alsa Constructor - Component probe - */ +static int __init snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip) +{ + snd_card_t *card = chip->card; + unsigned int idx; + int err; + + snd_assert(chip != NULL, return -EINVAL); + strcpy(card->mixername, "SAA7134 Mixer"); -static int devno=0; -static int __devinit snd_saa7134_create(snd_card_t *card, struct pci_dev *pci, - snd_saa7134_card_t **rchip) + for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_controls); idx++) { + if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_saa7134_controls[idx], chip))) < 0) + return err; + } + return 0; +} + +static int snd_saa7134_free(snd_card_saa7134_t *chip) { - snd_saa7134_card_t *chip; - struct saa7134_core *core; return 0; } -static int __devinit saa7134_audio_initdev(struct pci_dev *pci, - const struct pci_device_id *pci_id) +static int snd_saa7134_dev_free(snd_device_t *device) { - snd_card_t *card; - snd_saa7134_card_t *chip; - int err; + snd_card_saa7134_t *chip = device->device_data; + return snd_saa7134_free(chip); +} - if (devno >= SNDRV_CARDS) - return (-ENODEV); +int alsa_card_saa7134_create(struct saa7134_dev *saadev) +{ + static int dev; + snd_card_t *card; + struct snd_card_saa7134 *chip; + int err; + static snd_device_ops_t ops = { + .dev_free = snd_saa7134_dev_free, + }; - if (!enable[devno]) { - ++devno; - return (-ENOENT); - } + if (dev >= SNDRV_CARDS) + return -ENODEV; + if (!enable[dev]) + return -ENODEV; + card = snd_card_new(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_card_saa7134)); + if (card == NULL) + return -ENOMEM; - card = snd_card_new(index[devno], id[devno], THIS_MODULE, 0); - if (!card) - return (-ENOMEM); + strcpy(card->driver, "SAA7134"); - err = snd_saa7134_create(card, pci, &chip); - if (err < 0) - return (err); + /* Card "creation" */ + chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); + if (chip == NULL) { + return -ENOMEM; + } -/* - err = snd_saa7134_pcm(chip, DEVICE_DIGITAL, "saa7134 Digital"); - if (err < 0) - goto fail_free; -*/ - err = snd_ctl_add(card, snd_ctl_new1(&snd_saa7134_capture_volume, chip)); - if (err < 0) { - snd_card_free(card); - return (err); - } + spin_lock_init(&chip->lock); - strcpy (card->driver, "saa7134_ALSA"); - sprintf(card->shortname, "Saa7134 %x", pci->device); - sprintf(card->longname, "%s at %#lx", - card->shortname, pci_resource_start(pci, 0)); - strcpy (card->mixername, "saa7134"); + chip->saadev = saadev; - dprintk (0, "%s/%i: Alsa support for saa7134x boards\n", - card->driver,devno); + chip->card = card; + chip->pci = saadev->pci; + chip->irq = saadev->pci->irq; + chip->iobase = pci_resource_start(saadev->pci, 0); - err = snd_card_register(card); - if (err < 0) { - snd_card_free(card); - return (err); - } + if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + snd_saa7134_free(chip); + return err; + } - pci_set_drvdata(pci,card); - devno++; - return 0; -} -/* - * ALSA destructor - */ -static void __devexit saa7134_audio_finidev(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); + if ((err = snd_card_saa7134_new_mixer(chip)) < 0) + goto __nodev; - devno--; -} + if ((err = snd_card_saa7134_pcm(chip, 0)) < 0) + goto __nodev; + spin_lock_init(&chip->mixer_lock); -/* - * PCI driver definition - */ + snd_card_set_dev(card, &chip->pci->dev); -static struct pci_driver saa7134_audio_pci_driver = { - .name = "saa7134_audio", - .id_table = saa7134_audio_pci_tbl, - .probe = saa7134_audio_initdev, - .remove = saa7134_audio_finidev, - SND_PCI_PM_CALLBACKS -}; + /* End of "creation" */ -/**************************************************************************** - LINUX MODULE INIT - ****************************************************************************/ + strcpy(card->shortname, "SAA7134"); + sprintf(card->longname, "%s at 0x%lx irq %d", + card->shortname, chip->iobase, chip->irq); -/* - * module init - */ -static int saa7134_audio_init(void) -{ - printk(KERN_INFO "saa7134x alsa driver version %d.%d.%d loaded\n", - (saa7134_VERSION_CODE >> 16) & 0xff, - (saa7134_VERSION_CODE >> 8) & 0xff, - saa7134_VERSION_CODE & 0xff); -#ifdef SNAPSHOT - printk(KERN_INFO "saa7134x: snapshot date %04d-%02d-%02d\n", - SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); -#endif - return pci_module_init(&saa7134_audio_pci_driver); + + if ((err = snd_card_register(card)) == 0) { + snd_saa7134_cards[dev] = card; + return 0; + } + +__nodev: + snd_card_free(card); + kfree(card); + return err; } -/* - * module remove - */ -static void saa7134_audio_fini(void) +void alsa_card_saa7134_exit(void) { - pci_unregister_driver(&saa7134_audio_pci_driver); + int idx; + for (idx = 0; idx < SNDRV_CARDS; idx++) { + snd_card_free(snd_saa7134_cards[idx]); + } } - -module_init(saa7134_audio_init); -module_exit(saa7134_audio_fini); - -/* ----------------------------------------------------------- */ -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 109c815c5e6..538c9ce2f2b 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -57,6 +57,10 @@ static unsigned int oss = 0; module_param(oss, int, 0444); MODULE_PARM_DESC(oss,"register oss devices (default: no)"); +static unsigned int alsa = 0; +module_param(alsa, int, 0444); +MODULE_PARM_DESC(alsa,"register alsa devices (default: no)"); + static unsigned int latency = UNSET; module_param(latency, int, 0444); MODULE_PARM_DESC(latency,"pci latency timer"); @@ -591,13 +595,19 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs) card_has_mpeg(dev)) saa7134_irq_ts_done(dev,status); - if ((report & SAA7134_IRQ_REPORT_DONE_RA3)) - saa7134_irq_oss_done(dev,status); + if ((report & SAA7134_IRQ_REPORT_DONE_RA3)) { + if (oss) { + saa7134_irq_oss_done(dev,status); + } else if (alsa) { + saa7134_irq_alsa_done(dev,status); + } + } if ((report & (SAA7134_IRQ_REPORT_GPIO16 | SAA7134_IRQ_REPORT_GPIO18)) && dev->remote) saa7134_input_irq(dev); + } if (10 == loop) { @@ -1016,6 +1026,10 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, goto fail5; printk(KERN_INFO "%s: registered device mixer%d\n", dev->name,dev->oss.minor_mixer >> 4); + } else if (alsa) { + alsa_card_saa7134_create(dev); + printk(KERN_INFO "%s: registered ALSA devices\n", + dev->name); } break; } @@ -1043,6 +1057,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, case PCI_DEVICE_ID_PHILIPS_SAA7135: if (oss) unregister_sound_dsp(dev->oss.minor_dsp); + else if (alsa) + alsa_card_saa7134_exit(); break; } fail4: @@ -1102,7 +1118,8 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) if (oss) { unregister_sound_mixer(dev->oss.minor_mixer); unregister_sound_dsp(dev->oss.minor_dsp); - } + } else if (alsa) + alsa_card_saa7134_exit(); break; } saa7134_unregister_video(dev); diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c index c20630c82f1..b1dcb4d1078 100644 --- a/drivers/media/video/saa7134/saa7134-oss.c +++ b/drivers/media/video/saa7134/saa7134-oss.c @@ -44,6 +44,7 @@ MODULE_PARM_DESC(oss_rate,"sample rate (valid are: 32000,48000)"); #define dprintk(fmt, arg...) if (oss_debug) \ printk(KERN_DEBUG "%s/oss: " fmt, dev->name , ## arg) + /* ------------------------------------------------------------------ */ static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) @@ -173,8 +174,8 @@ static int dsp_rec_start(struct saa7134_dev *dev) fmt |= (2 << 4); if (!sign) fmt |= 0x04; - saa_writel(0x588 >> 2, dev->oss.blksize -4); - saa_writel(0x58c >> 2, 0x543210 | (fmt << 24)); + saa_writel(SAA7133_NUM_SAMPLES, dev->oss.blksize -4); + saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24)); break; } dprintk("rec_start: afmt=%d ch=%d => fmt=0x%x swap=%c\n", diff --git a/drivers/media/video/saa7134/saa7134-reg.h b/drivers/media/video/saa7134/saa7134-reg.h index fce4f185ef9..58c521fade8 100644 --- a/drivers/media/video/saa7134/saa7134-reg.h +++ b/drivers/media/video/saa7134/saa7134-reg.h @@ -43,6 +43,14 @@ #define SAA7134_FIFO_SIZE (0x2a0 >> 2) #define SAA7134_THRESHOULD (0x2a4 >> 2) +#define SAA7133_NUM_SAMPLES (0x588 >> 2) +#define SAA7133_AUDIO_CHANNEL (0x58c >> 2) +#define SAA7133_AUDIO_FORMAT (0x58f >> 2) +#define SAA7133_DIGITAL_OUTPUT_SEL1 (0x46c >> 2) +#define SAA7133_DIGITAL_OUTPUT_SEL2 (0x470 >> 2) +#define SAA7133_DIGITAL_INPUT_XBAR1 (0x464 >> 2) +#define SAA7133_ANALOG_IO_SELECT (0x594 >> 2) + /* main control */ #define SAA7134_MAIN_CTRL (0x2a8 >> 2) #define SAA7134_MAIN_CTRL_VPLLE (1 << 15) diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 9dfd45bed92..7a35ef8fecb 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -45,6 +45,10 @@ #endif #define UNSET (-1U) +#include +#include +#include + /* ----------------------------------------------------------- */ /* enums */ @@ -364,6 +368,7 @@ struct saa7134_oss { unsigned int dma_blk; unsigned int read_offset; unsigned int read_count; + snd_pcm_substream_t *substream; }; /* IR input */ @@ -644,6 +649,11 @@ int saa7134_input_init1(struct saa7134_dev *dev); void saa7134_input_fini(struct saa7134_dev *dev); void saa7134_input_irq(struct saa7134_dev *dev); +int alsa_card_saa7134_create(struct saa7134_dev *saadev); +void alsa_card_saa7134_exit(void); +void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status); + + /* * Local variables: * c-basic-offset: 8 -- cgit v1.2.3 From 4d63cb45a2ee5cbf2e6d568fb2c4007a52e21bcf Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 8 Nov 2005 21:37:12 -0800 Subject: [PATCH] v4l: 721: check kthread correctly - Check ->kthread correctly Signed-off-by: Alexey Dobriyan Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/msp3400.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index 6e2b0775a74..88cc793c0bc 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -1566,7 +1566,7 @@ static int msp_detach(struct i2c_client *client) struct msp3400c *msp = i2c_get_clientdata(client); /* shutdown control thread */ - if (msp->kthread >= 0) { + if (msp->kthread) { msp->restart = 1; kthread_stop(msp->kthread); } -- cgit v1.2.3 From c06f57f55a0e499ec38fbb62812ad3fe08ad246e Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:37:13 -0800 Subject: [PATCH] v4l: 723: fix build for 2.6.14 - Fix build for 2.6.14 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-i2c.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index f1493c48656..d6ae2e397c5 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -329,8 +329,6 @@ static int attach_inform(struct i2c_client *client) } static struct i2c_algorithm em2820_algo = { - .name = "em2820", - .id = I2C_HW_B_EM2820, .master_xfer = em2820_i2c_xfer, .algo_control = algo_control, .functionality = functionality, -- cgit v1.2.3 From b2c15ea9b23c216bb49303c076bbdcef7e7ba278 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Tue, 8 Nov 2005 21:37:14 -0800 Subject: [PATCH] v4l: 725: fixed kernel oops when hotswapping pc cards - Fixed kernel oops when hotswapping PC Cards Signed-off-by: Ricardo Cerqueira Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-alsa.c | 270 ++++++++++++++++++++++------- 1 file changed, 210 insertions(+), 60 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 84eeeba21d7..cf4ee6d6ef6 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -4,15 +4,7 @@ * * * Caveats: - * I still haven't got the mixer settings right. - * * - Volume doesn't work (it's always at max) - * - There's no "memory" of the capture channel. It can be changed, - * but alsamixer doesn't show it after a module restart (rmmod/insmod) - * - * Hotswapping DOES NOT work yet! Please remove the module before - * inserting cardbus cards. pcmcia-cs or pccardd should load it - * properly after insertion, and things will work * * 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 @@ -49,6 +41,10 @@ static unsigned int alsa_debug = 0; module_param(alsa_debug, int, 0644); MODULE_PARM_DESC(alsa_debug,"enable debug messages [alsa]"); +/* + * Configuration macros + */ + #define MAX_PCM_DEVICES 1 #define MAX_PCM_SUBSTREAMS 1 @@ -67,20 +63,21 @@ MODULE_PARM_DESC(alsa_debug,"enable debug messages [alsa]"); #define USE_PERIODS_MAX 1024 #endif - -#define dprintk(fmt, arg...) if (alsa_debug) \ - printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ## arg) - +#define MIXER_ADDR_TVTUNER 0 +#define MIXER_ADDR_LINE1 1 +#define MIXER_ADDR_LINE2 2 +#define MIXER_ADDR_LAST 2 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; -#define MIXER_ADDR_TVTUNER 0 -#define MIXER_ADDR_LINE1 1 -#define MIXER_ADDR_LINE2 2 -#define MIXER_ADDR_LAST 2 +#define dprintk(fmt, arg...) if (alsa_debug) \ + printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ## arg) +/* + * Main chip structure + */ typedef struct snd_card_saa7134 { snd_card_t *card; spinlock_t mixer_lock; @@ -95,6 +92,10 @@ typedef struct snd_card_saa7134 { spinlock_t lock; } snd_card_saa7134_t; +/* + * PCM structure + */ + typedef struct snd_card_saa7134_pcm { struct saa7134_dev *saadev; @@ -107,13 +108,34 @@ typedef struct snd_card_saa7134_pcm { static snd_card_t *snd_saa7134_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; +/* + * saa7134 DMA audio stop + * + * Called when the capture device is released or the buffer overflows + * + * - Copied verbatim from saa7134-oss's dsp_dma_stop. Can be dropped + * if we just share dsp_dma_stop and use it here + * + */ + static void saa7134_dma_stop(struct saa7134_dev *dev) + { dev->oss.dma_blk = -1; dev->oss.dma_running = 0; saa7134_set_dmabits(dev); } +/* + * saa7134 DMA audio start + * + * Called when preparing the capture device for use + * + * - Copied verbatim from saa7134-oss's dsp_dma_start. Can be dropped + * if we just share dsp_dma_start and use it here + * + */ + static void saa7134_dma_start(struct saa7134_dev *dev) { dev->oss.dma_blk = 0; @@ -121,6 +143,17 @@ static void saa7134_dma_start(struct saa7134_dev *dev) saa7134_set_dmabits(dev); } +/* + * saa7134 audio DMA IRQ handler + * + * Called whenever we get an SAA7134_IRQ_REPORT_DONE_RA3 interrupt + * Handles shifting between the 2 buffers, manages the read counters, + * and notifies ALSA when periods elapse + * + * - Mostly copied from saa7134-oss's saa7134_irq_oss_done. + * + */ + void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) { int next_blk, reg = 0; @@ -179,6 +212,15 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) } +/* + * ALSA capture trigger + * + * - One of the ALSA capture callbacks. + * + * Called whenever a capture is started or stopped. Must be defined, + * but there's nothing we want to do here + * + */ static int snd_card_saa7134_capture_trigger(snd_pcm_substream_t * substream, int cmd) @@ -186,6 +228,18 @@ static int snd_card_saa7134_capture_trigger(snd_pcm_substream_t * substream, return 0; } +/* + * DMA buffer config + * + * Sets the values that will later be used as the size of the buffer, + * size of the fragments, and total number of fragments. + * Must be called during the preparation stage, before memory is + * allocated + * + * - Copied verbatim from saa7134-oss. Can be dropped + * if we just share dsp_buffer_conf from OSS. + */ + static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) { if (blksize < 0x100) @@ -207,6 +261,17 @@ static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) return 0; } +/* + * DMA buffer initialization + * + * Uses V4L functions to initialize the DMA. Shouldn't be necessary in + * ALSA, but I was unable to use ALSA's own DMA, and had to force the + * usage of V4L's + * + * - Copied verbatim from saa7134-oss. Can be dropped + * if we just share dsp_buffer_init from OSS. + */ + static int dsp_buffer_init(struct saa7134_dev *dev) { int err; @@ -221,8 +286,19 @@ static int dsp_buffer_init(struct saa7134_dev *dev) return 0; } +/* + * ALSA PCM preparation + * + * - One of the ALSA capture callbacks. + * + * Called right after the capture device is opened, this function configures + * the buffer using the previously defined functions, allocates the memory, + * sets up the hardware registers, and then starts the DMA. When this function + * returns, the audio should be flowing. + * + */ -static int snd_card_saa7134_pcm_prepare(snd_pcm_substream_t * substream) +static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) { snd_pcm_runtime_t *runtime = substream->runtime; int err, bswap, sign; @@ -329,7 +405,6 @@ static int snd_card_saa7134_pcm_prepare(snd_pcm_substream_t * substream) fmt |= (2 << 4); if (!sign) fmt |= 0x04; - //saa_writel(SAA7133_NUM_SAMPLES, dev->oss.blksize -1); saa_writel(SAA7133_NUM_SAMPLES, dev->oss.blksize -1); saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24)); //saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210); @@ -346,7 +421,12 @@ static int snd_card_saa7134_pcm_prepare(snd_pcm_substream_t * substream) if (bswap) control |= SAA7134_RS_CONTROL_BSWAP; + /* I should be able to use runtime->dma_addr in the control + byte, but it doesn't work. So I allocate the DMA using the + V4L functions, and force ALSA to use that as the DMA area */ + runtime->dma_area = dev->oss.dma.vmalloc; + saa_writel(SAA7134_RS_BA1(6),0); saa_writel(SAA7134_RS_BA2(6),dev->oss.blksize); saa_writel(SAA7134_RS_PITCH(6),0); @@ -368,12 +448,18 @@ static int snd_card_saa7134_pcm_prepare(snd_pcm_substream_t * substream) } -static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) -{ - return snd_card_saa7134_pcm_prepare(substream); -} +/* + * ALSA pointer fetching + * + * - One of the ALSA capture callbacks. + * + * Called whenever a period elapses, it must return the current hardware + * position of the buffer. + * Also resets the read counter used to prevent overruns + * + */ -static snd_pcm_uframes_t snd_card_saa7134_pointer(snd_pcm_substream_t * substream) +static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * substream) { snd_pcm_runtime_t *runtime = substream->runtime; snd_card_saa7134_pcm_t *saapcm = runtime->private_data; @@ -388,15 +474,12 @@ static snd_pcm_uframes_t snd_card_saa7134_pointer(snd_pcm_substream_t * substrea dev->oss.read_offset = 0; } - //return bytes_to_frames(runtime, saa_readl(dev->oss.recording_on)); return bytes_to_frames(runtime, dev->oss.read_offset); } - -static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * substream) -{ - return snd_card_saa7134_pointer(substream); -} +/* + * ALSA hardware capabilities definition + */ static snd_pcm_hardware_t snd_card_saa7134_capture = { @@ -425,6 +508,17 @@ static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime) } +/* + * ALSA hardware params + * + * - One of the ALSA capture callbacks. + * + * Called on initialization, right before the PCM preparation + * Usually used in ALSA to allocate the DMA, but since we don't use the + * ALSA DMA I'm almost sure this isn't necessary. + * + */ + static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, snd_pcm_hw_params_t * hw_params) { @@ -434,11 +528,29 @@ static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, } +/* + * ALSA hardware release + * + * - One of the ALSA capture callbacks. + * + * Called after closing the device, but before snd_card_saa7134_capture_close + * Usually used in ALSA to free the DMA, but since we don't use the + * ALSA DMA I'm almost sure this isn't necessary. + * + */ + static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream) { return snd_pcm_lib_free_pages(substream); } +/* + * DMA buffer release + * + * Called after closing the device, during snd_card_saa7134_capture_close + * + */ + static int dsp_buffer_free(struct saa7134_dev *dev) { if (!dev->oss.blksize) @@ -453,9 +565,20 @@ static int dsp_buffer_free(struct saa7134_dev *dev) return 0; } +/* + * ALSA capture finish + * + * - One of the ALSA capture callbacks. + * + * Called after closing the device. It stops the DMA audio and releases + * the buffers + * + */ -static int saa7134_cap_close(struct saa7134_dev *dev) +static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) { + snd_card_saa7134_t *chip = snd_pcm_substream_chip(substream); + struct saa7134_dev *dev = chip->saadev; unsigned long flags; /* stop dma */ @@ -471,8 +594,23 @@ static int saa7134_cap_close(struct saa7134_dev *dev) return 0; } +/* + * ALSA capture start + * + * - One of the ALSA capture callbacks. + * + * Called when opening the device. It creates and populates the PCM + * structure + * + */ -static int saa7134_cap_open(struct saa7134_dev *dev) { +static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) +{ + snd_pcm_runtime_t *runtime = substream->runtime; + snd_card_saa7134_pcm_t *saapcm; + snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); + struct saa7134_dev *dev = saa7134->saadev; + int err; down(&dev->oss.lock); @@ -483,18 +621,6 @@ static int saa7134_cap_open(struct saa7134_dev *dev) { up(&dev->oss.lock); - return 0; -} - -static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) -{ - snd_pcm_runtime_t *runtime = substream->runtime; - snd_card_saa7134_pcm_t *saapcm; - snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); - int err; - - saa7134_cap_open(saa7134->saadev); - saapcm = kcalloc(1, sizeof(*saapcm), GFP_KERNEL); if (saapcm == NULL) return -ENOMEM; @@ -513,13 +639,9 @@ static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) return 0; } -static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) -{ - snd_card_saa7134_t *chip = snd_pcm_substream_chip(substream); - - saa7134_cap_close(chip->saadev); - return 0; -} +/* + * ALSA capture callbacks definition + */ static snd_pcm_ops_t snd_card_saa7134_capture_ops = { .open = snd_card_saa7134_capture_open, @@ -532,7 +654,15 @@ static snd_pcm_ops_t snd_card_saa7134_capture_ops = { .pointer = snd_card_saa7134_capture_pointer, }; -static int __init snd_card_saa7134_pcm(snd_card_saa7134_t *saa7134, int device) +/* + * ALSA PCM setup + * + * Called when initializing the board. Sets up the name and hooks up + * the callbacks + * + */ + +static int snd_card_saa7134_pcm(snd_card_saa7134_t *saa7134, int device) { snd_pcm_t *pcm; int err; @@ -612,7 +742,7 @@ static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ static int snd_saa7134_capsrc_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; + uinfo->count = 2; uinfo->value.integer.min = 0; uinfo->value.integer.max = 1; return 0; @@ -647,7 +777,7 @@ static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ right = ucontrol->value.integer.value[1] & 1; spin_lock_irqsave(&chip->mixer_lock, flags); - change = chip->capture_source[addr][0] != left && + change = chip->capture_source[addr][0] != left || chip->capture_source[addr][1] != right; chip->capture_source[addr][0] = left; chip->capture_source[addr][1] = right; @@ -655,7 +785,8 @@ static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ spin_unlock_irqrestore(&chip->mixer_lock, flags); - switch (dev->pci->device) { + if (change) { + switch (dev->pci->device) { case PCI_DEVICE_ID_PHILIPS_SAA7134: switch (addr) { @@ -702,7 +833,8 @@ static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, 0); saa_writel(SAA7133_ANALOG_IO_SELECT, 0); } - } + } + } return change; } @@ -716,7 +848,15 @@ SAA713x_VOLUME("Line Volume", 2, MIXER_ADDR_LINE2), SAA713x_CAPSRC("Line Capture Switch", 2, MIXER_ADDR_LINE2), }; -static int __init snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip) +/* + * ALSA mixer setup + * + * Called when initializing the board. Sets up the name and hooks up + * the callbacks + * + */ + +static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip) { snd_card_t *card = chip->card; unsigned int idx; @@ -743,11 +883,19 @@ static int snd_saa7134_dev_free(snd_device_t *device) return snd_saa7134_free(chip); } +/* + * ALSA initialization + * + * Called by saa7134-core, it creates the basic structures and registers + * the ALSA devices + * + */ + int alsa_card_saa7134_create(struct saa7134_dev *saadev) { static int dev; snd_card_t *card; - struct snd_card_saa7134 *chip; + snd_card_saa7134_t *chip; int err; static snd_device_ops_t ops = { .dev_free = snd_saa7134_dev_free, @@ -757,14 +905,16 @@ int alsa_card_saa7134_create(struct saa7134_dev *saadev) return -ENODEV; if (!enable[dev]) return -ENODEV; + card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_saa7134)); + 0); if (card == NULL) return -ENOMEM; strcpy(card->driver, "SAA7134"); /* Card "creation" */ + chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); if (chip == NULL) { return -ENOMEM; @@ -775,6 +925,7 @@ int alsa_card_saa7134_create(struct saa7134_dev *saadev) chip->saadev = saadev; chip->card = card; + chip->pci = saadev->pci; chip->irq = saadev->pci->irq; chip->iobase = pci_resource_start(saadev->pci, 0); @@ -784,12 +935,12 @@ int alsa_card_saa7134_create(struct saa7134_dev *saadev) return err; } - if ((err = snd_card_saa7134_new_mixer(chip)) < 0) goto __nodev; if ((err = snd_card_saa7134_pcm(chip, 0)) < 0) goto __nodev; + spin_lock_init(&chip->mixer_lock); snd_card_set_dev(card, &chip->pci->dev); @@ -800,7 +951,6 @@ int alsa_card_saa7134_create(struct saa7134_dev *saadev) sprintf(card->longname, "%s at 0x%lx irq %d", card->shortname, chip->iobase, chip->irq); - if ((err = snd_card_register(card)) == 0) { snd_saa7134_cards[dev] = card; return 0; -- cgit v1.2.3 From a866623cdc94a3a800167568db24bc55b6860ef0 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Tue, 8 Nov 2005 21:37:14 -0800 Subject: [PATCH] v4l: 727: fixed a bug that caused some saa7133 code to run on saa7134 boards - Fixed a bug that caused some saa7133 code to run on saa7134 boards Signed-off-by: Ricardo Cerqueira Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-alsa.c | 16 +++++++++------- drivers/media/video/saa7134/saa7134-core.c | 2 +- drivers/media/video/saa7134/saa7134.h | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index cf4ee6d6ef6..465beac941d 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -45,9 +45,6 @@ MODULE_PARM_DESC(alsa_debug,"enable debug messages [alsa]"); * Configuration macros */ -#define MAX_PCM_DEVICES 1 -#define MAX_PCM_SUBSTREAMS 1 - /* defaults */ #define MAX_BUFFER_SIZE (256*1024) #define USE_FORMATS SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE @@ -804,6 +801,7 @@ static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ break; } + break; case PCI_DEVICE_ID_PHILIPS_SAA7133: case PCI_DEVICE_ID_PHILIPS_SAA7135: xbarin = 0x03; // adc @@ -833,6 +831,7 @@ static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, 0); saa_writel(SAA7133_ANALOG_IO_SELECT, 0); } + break; } } @@ -891,7 +890,7 @@ static int snd_saa7134_dev_free(snd_device_t *device) * */ -int alsa_card_saa7134_create(struct saa7134_dev *saadev) +int alsa_card_saa7134_create(struct saa7134_dev *saadev, unsigned int devicenum) { static int dev; snd_card_t *card; @@ -906,8 +905,11 @@ int alsa_card_saa7134_create(struct saa7134_dev *saadev) if (!enable[dev]) return -ENODEV; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - 0); + if (devicenum) { + card = snd_card_new(devicenum, id[dev], THIS_MODULE, 0); + } else { + card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); + } if (card == NULL) return -ENOMEM; @@ -949,7 +951,7 @@ int alsa_card_saa7134_create(struct saa7134_dev *saadev) strcpy(card->shortname, "SAA7134"); sprintf(card->longname, "%s at 0x%lx irq %d", - card->shortname, chip->iobase, chip->irq); + chip->saadev->name, chip->iobase, chip->irq); if ((err = snd_card_register(card)) == 0) { snd_saa7134_cards[dev] = card; diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 538c9ce2f2b..907dbd4de7c 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -1027,7 +1027,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, printk(KERN_INFO "%s: registered device mixer%d\n", dev->name,dev->oss.minor_mixer >> 4); } else if (alsa) { - alsa_card_saa7134_create(dev); + alsa_card_saa7134_create(dev,dsp_nr[dev->nr]); printk(KERN_INFO "%s: registered ALSA devices\n", dev->name); } diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 7a35ef8fecb..52fc4425b71 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -649,7 +649,7 @@ int saa7134_input_init1(struct saa7134_dev *dev); void saa7134_input_fini(struct saa7134_dev *dev); void saa7134_input_irq(struct saa7134_dev *dev); -int alsa_card_saa7134_create(struct saa7134_dev *saadev); +int alsa_card_saa7134_create(struct saa7134_dev *saadev, unsigned int devnum); void alsa_card_saa7134_exit(void); void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status); -- cgit v1.2.3 From 376f269e4731a90db41683cb72717e217d3774f5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 8 Nov 2005 21:37:15 -0800 Subject: [PATCH] v4l: 728: vidiocsfreq and vidiocgfreq expect an unsigned long as argument - VIDIOCSFREQ and VIDIOCGFREQ expect an unsigned long as argument. Signed-off-by: Hans Verkuil Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/v4l1-compat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index d679ca23ded..88beb5a3be1 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c @@ -708,7 +708,7 @@ v4l_compat_translate_ioctl(struct inode *inode, } case VIDIOCGFREQ: /* get frequency */ { - int *freq = arg; + unsigned long *freq = arg; freq2.tuner = 0; err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); @@ -720,7 +720,7 @@ v4l_compat_translate_ioctl(struct inode *inode, } case VIDIOCSFREQ: /* set frequency */ { - int *freq = arg; + unsigned long *freq = arg; freq2.tuner = 0; drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); -- cgit v1.2.3 From 1f6173ed9b48709383631e2c43eed770f15d05d1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:16 -0800 Subject: [PATCH] v4l: 729: fixed include when compiling at kernel tree - Fixed include when compiling at kernel tree Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-cards.c | 4 ++-- drivers/media/video/em28xx/em28xx-core.c | 2 +- drivers/media/video/em28xx/em28xx-video.c | 2 +- drivers/media/video/tveeprom.c | 2 +- drivers/media/video/tvp5150.c | 1 - 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index b6d89decfbd..7333bbad887 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -29,8 +29,8 @@ #include #include #include -#include "audiochip.h" -#include "tveeprom.h" +#include +#include #include "msp3400.h" #include "em2820.h" diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index a75a91da70e..7913740e672 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -26,9 +26,9 @@ #include #include #include -#include #include #include +#include #include "em2820.h" diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index a000131a8f5..3fc58c67e6c 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -27,8 +27,8 @@ #include #include #include -#include #include +#include #include #include diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index a9bad89b4d6..ee605712bf1 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -40,7 +40,7 @@ #include #include -#include "audiochip.h" +#include MODULE_DESCRIPTION("i2c Hauppauge eeprom decoder driver"); MODULE_AUTHOR("John Klar"); diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 03f360b45fd..81e6d4494e7 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -5,7 +5,6 @@ * This code is placed under the terms of the GNU General Public License */ -#include #include #include #include -- cgit v1.2.3 From 98f30ed06a0feade6250438b0bd6cc472f26b12a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:17 -0800 Subject: [PATCH] v4l: 739: created make changelog to make easier to generate patches - Created make changelog to make easier to generate patches. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/cx88-core.c | 2 +- drivers/media/video/cx88/cx88.h | 2 +- drivers/media/video/em28xx/em28xx-core.c | 1 - drivers/media/video/em28xx/em28xx-i2c.c | 1 - drivers/media/video/em28xx/em28xx-video.c | 1 - 5 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 8f1c27fdae6..d4d39c1751a 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include "cx88.h" diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index cc2197a85d0..a690569f345 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 7913740e672..e187422f6d6 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -28,7 +28,6 @@ #include #include #include -#include #include "em2820.h" diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index d6ae2e397c5..150c72bb6e4 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 3fc58c67e6c..3581fc4c874 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From 4eb0c14465a9221f040551a91238b57af301c145 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 8 Nov 2005 21:37:18 -0800 Subject: [PATCH] v4l: 754: add the adapter address prefix to the tda9887 kernel messages - Add the adapter/address prefix to the tda9887 kernel messages. Signed-off-by: Hans Verkuil Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tda9887.c | 110 ++++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 51 deletions(-) diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index ba22f12e8b3..3a7babef06f 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -44,8 +44,13 @@ MODULE_LICENSE("GPL"); /* ---------------------------------------------------------------------- */ #define UNSET (-1U) -#define PREFIX "tda9885/6/7: " -#define dprintk if (debug) printk +#define tda9887_info(fmt, arg...) do {\ + printk(KERN_INFO "%s %d-%04x: " fmt, t->client.name, \ + i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0) +#define tda9887_dbg(fmt, arg...) do {\ + if (debug) \ + printk(KERN_INFO "%s %d-%04x: " fmt, t->client.name, \ + i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0) struct tda9887 { struct i2c_client client; @@ -237,7 +242,7 @@ static struct tvnorm radio_mono = { /* ---------------------------------------------------------------------- */ -static void dump_read_message(unsigned char *buf) +static void dump_read_message(struct tda9887 *t, unsigned char *buf) { static char *afc[16] = { "- 12.5 kHz", @@ -257,15 +262,15 @@ static void dump_read_message(unsigned char *buf) "+ 37.5 kHz", "+ 12.5 kHz", }; - printk(PREFIX "read: 0x%2x\n", buf[0]); - printk(" after power on : %s\n", (buf[0] & 0x01) ? "yes" : "no"); - printk(" afc : %s\n", afc[(buf[0] >> 1) & 0x0f]); - printk(" fmif level : %s\n", (buf[0] & 0x20) ? "high" : "low"); - printk(" afc window : %s\n", (buf[0] & 0x40) ? "in" : "out"); - printk(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low"); + tda9887_info("read: 0x%2x\n", buf[0]); + tda9887_info(" after power on : %s\n", (buf[0] & 0x01) ? "yes" : "no"); + tda9887_info(" afc : %s\n", afc[(buf[0] >> 1) & 0x0f]); + tda9887_info(" fmif level : %s\n", (buf[0] & 0x20) ? "high" : "low"); + tda9887_info(" afc window : %s\n", (buf[0] & 0x40) ? "in" : "out"); + tda9887_info(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low"); } -static void dump_write_message(unsigned char *buf) +static void dump_write_message(struct tda9887 *t, unsigned char *buf) { static char *sound[4] = { "AM/TV", @@ -305,58 +310,58 @@ static void dump_write_message(unsigned char *buf) "44 MHz", }; - printk(PREFIX "write: byte B 0x%02x\n",buf[1]); - printk(" B0 video mode : %s\n", + tda9887_info("write: byte B 0x%02x\n",buf[1]); + tda9887_info(" B0 video mode : %s\n", (buf[1] & 0x01) ? "video trap" : "sound trap"); - printk(" B1 auto mute fm : %s\n", + tda9887_info(" B1 auto mute fm : %s\n", (buf[1] & 0x02) ? "yes" : "no"); - printk(" B2 carrier mode : %s\n", + tda9887_info(" B2 carrier mode : %s\n", (buf[1] & 0x04) ? "QSS" : "Intercarrier"); - printk(" B3-4 tv sound/radio : %s\n", + tda9887_info(" B3-4 tv sound/radio : %s\n", sound[(buf[1] & 0x18) >> 3]); - printk(" B5 force mute audio: %s\n", + tda9887_info(" B5 force mute audio: %s\n", (buf[1] & 0x20) ? "yes" : "no"); - printk(" B6 output port 1 : %s\n", + tda9887_info(" B6 output port 1 : %s\n", (buf[1] & 0x40) ? "high (inactive)" : "low (active)"); - printk(" B7 output port 2 : %s\n", + tda9887_info(" B7 output port 2 : %s\n", (buf[1] & 0x80) ? "high (inactive)" : "low (active)"); - printk(PREFIX "write: byte C 0x%02x\n",buf[2]); - printk(" C0-4 top adjustment : %s dB\n", adjust[buf[2] & 0x1f]); - printk(" C5-6 de-emphasis : %s\n", deemph[(buf[2] & 0x60) >> 5]); - printk(" C7 audio gain : %s\n", + tda9887_info("write: byte C 0x%02x\n",buf[2]); + tda9887_info(" C0-4 top adjustment : %s dB\n", adjust[buf[2] & 0x1f]); + tda9887_info(" C5-6 de-emphasis : %s\n", deemph[(buf[2] & 0x60) >> 5]); + tda9887_info(" C7 audio gain : %s\n", (buf[2] & 0x80) ? "-6" : "0"); - printk(PREFIX "write: byte E 0x%02x\n",buf[3]); - printk(" E0-1 sound carrier : %s\n", + tda9887_info("write: byte E 0x%02x\n",buf[3]); + tda9887_info(" E0-1 sound carrier : %s\n", carrier[(buf[3] & 0x03)]); - printk(" E6 l pll gating : %s\n", + tda9887_info(" E6 l pll gating : %s\n", (buf[3] & 0x40) ? "36" : "13"); if (buf[1] & 0x08) { /* radio */ - printk(" E2-4 video if : %s\n", + tda9887_info(" E2-4 video if : %s\n", rif[(buf[3] & 0x0c) >> 2]); - printk(" E7 vif agc output : %s\n", + tda9887_info(" E7 vif agc output : %s\n", (buf[3] & 0x80) ? ((buf[3] & 0x10) ? "fm-agc radio" : "sif-agc radio") : "fm radio carrier afc"); } else { /* video */ - printk(" E2-4 video if : %s\n", + tda9887_info(" E2-4 video if : %s\n", vif[(buf[3] & 0x1c) >> 2]); - printk(" E5 tuner gain : %s\n", + tda9887_info(" E5 tuner gain : %s\n", (buf[3] & 0x80) ? ((buf[3] & 0x20) ? "external" : "normal") : ((buf[3] & 0x20) ? "minimum" : "normal")); - printk(" E7 vif agc output : %s\n", + tda9887_info(" E7 vif agc output : %s\n", (buf[3] & 0x80) ? ((buf[3] & 0x20) ? "pin3 port, pin22 vif agc out" : "pin22 port, pin3 vif acg ext in") : "pin3+pin22 port"); } - printk("--\n"); + tda9887_info("--\n"); } /* ---------------------------------------------------------------------- */ @@ -380,11 +385,11 @@ static int tda9887_set_tvnorm(struct tda9887 *t, char *buf) } } if (NULL == norm) { - dprintk(PREFIX "Unsupported tvnorm entry - audio muted\n"); + tda9887_dbg("Unsupported tvnorm entry - audio muted\n"); return -1; } - dprintk(PREFIX "configure for: %s\n",norm->name); + tda9887_dbg("configure for: %s\n",norm->name); buf[1] = norm->b; buf[2] = norm->c; buf[3] = norm->e; @@ -506,26 +511,26 @@ static int tda9887_fixup_std(struct tda9887 *t) case 'B': case 'g': case 'G': - dprintk(PREFIX "insmod fixup: PAL => PAL-BG\n"); + tda9887_dbg("insmod fixup: PAL => PAL-BG\n"); t->std = V4L2_STD_PAL_BG; break; case 'i': case 'I': - dprintk(PREFIX "insmod fixup: PAL => PAL-I\n"); + tda9887_dbg("insmod fixup: PAL => PAL-I\n"); t->std = V4L2_STD_PAL_I; break; case 'd': case 'D': case 'k': case 'K': - dprintk(PREFIX "insmod fixup: PAL => PAL-DK\n"); + tda9887_dbg("insmod fixup: PAL => PAL-DK\n"); t->std = V4L2_STD_PAL_DK; break; case '-': /* default parameter, do nothing */ break; default: - printk(PREFIX "pal= argument not recognised\n"); + tda9887_info("pal= argument not recognised\n"); break; } } @@ -535,19 +540,19 @@ static int tda9887_fixup_std(struct tda9887 *t) case 'D': case 'k': case 'K': - dprintk(PREFIX "insmod fixup: SECAM => SECAM-DK\n"); + tda9887_dbg("insmod fixup: SECAM => SECAM-DK\n"); t->std = V4L2_STD_SECAM_DK; break; case 'l': case 'L': - dprintk(PREFIX "insmod fixup: SECAM => SECAM-L\n"); + tda9887_dbg("insmod fixup: SECAM => SECAM-L\n"); t->std = V4L2_STD_SECAM_L; break; case '-': /* default parameter, do nothing */ break; default: - printk(PREFIX "secam= argument not recognised\n"); + tda9887_info("secam= argument not recognised\n"); break; } } @@ -561,8 +566,8 @@ static int tda9887_status(struct tda9887 *t) memset(buf,0,sizeof(buf)); if (1 != (rc = i2c_master_recv(&t->client,buf,1))) - printk(PREFIX "i2c i/o error: rc == %d (should be 1)\n",rc); - dump_read_message(buf); + tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc); + dump_read_message(t, buf); return 0; } @@ -588,13 +593,13 @@ static int tda9887_configure(struct tda9887 *t) } - dprintk(PREFIX "writing: b=0x%02x c=0x%02x e=0x%02x\n", + tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", buf[1],buf[2],buf[3]); if (debug > 1) - dump_write_message(buf); + dump_write_message(t, buf); if (4 != (rc = i2c_master_send(&t->client,buf,4))) - printk(PREFIX "i2c i/o error: rc == %d (should be 4)\n",rc); + tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); if (debug > 2) { msleep_interruptible(1000); @@ -612,8 +617,6 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind) client_template.adapter = adap; client_template.addr = addr; - printk(PREFIX "chip found @ 0x%x\n", addr<<1); - if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL))) return -ENOMEM; memset(t,0,sizeof(*t)); @@ -623,6 +626,8 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind) t->pinnacle_id = UNSET; t->radio_mode = V4L2_TUNER_MODE_STEREO; + tda9887_info("chip found @ 0x%x (%s)\n", addr<<1, adap->name); + i2c_set_clientdata(&t->client, t); i2c_attach_client(&t->client); @@ -656,10 +661,10 @@ static int tda9887_detach(struct i2c_client *client) } #define SWITCH_V4L2 if (!t->using_v4l2 && debug) \ - printk(PREFIX "switching to v4l2\n"); \ + tda9887_info("switching to v4l2\n"); \ t->using_v4l2 = 1; #define CHECK_V4L2 if (t->using_v4l2) { if (debug) \ - printk(PREFIX "ignore v4l1 call\n"); \ + tda9887_info("ignore v4l1 call\n"); \ return 0; } static int @@ -787,7 +792,10 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) static int tda9887_suspend(struct device * dev, pm_message_t state) { - dprintk("tda9887: suspend\n"); + struct i2c_client *c = container_of(dev, struct i2c_client, dev); + struct tda9887 *t = i2c_get_clientdata(c); + + tda9887_dbg("suspend\n"); return 0; } @@ -796,7 +804,7 @@ static int tda9887_resume(struct device * dev) struct i2c_client *c = container_of(dev, struct i2c_client, dev); struct tda9887 *t = i2c_get_clientdata(c); - dprintk("tda9887: resume\n"); + tda9887_dbg("resume\n"); tda9887_configure(t); return 0; } -- cgit v1.2.3 From 6df840f20d1ff63fd13ed1bb3e186395ee800794 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:18 -0800 Subject: [PATCH] v4l: 758: some improvements at msp3400 c from ivtv code - Some improvements at msp3400.c from ivtv code. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/msp3400.c | 440 +++++++++++++++++++++++------------------- 1 file changed, 245 insertions(+), 195 deletions(-) diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index 88cc793c0bc..4689dee882f 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -73,13 +73,22 @@ static int dolby = 0; static int stereo_threshold = 0x190; /* a2 threshold for stereo/bilingual (msp34xxg only) 0x00a0-0x03c0 */ +#define DFP_COUNT 0x41 +static const int bl_dfp[] = { + 0x00, 0x01, 0x02, 0x03, 0x06, 0x08, 0x09, 0x0a, + 0x0b, 0x0d, 0x0e, 0x10 +}; + +#define IS_MSP34XX_G(msp) ((msp)->opmode==2) struct msp3400c { int rev1,rev2; int opmode; + int nicam; int mode; int norm; + int stereo; int nicam_on; int acb; int main, second; /* sound carrier */ @@ -91,9 +100,12 @@ struct msp3400c { int rxsubchans; int muted; - int volume, balance; + int left, right; /* volume */ int bass, treble; + /* shadow register set */ + int dfp_regs[DFP_COUNT]; + /* thread */ struct task_struct *kthread; wait_queue_head_t wq; @@ -101,6 +113,8 @@ struct msp3400c { int watch_stereo:1; }; +#define MIN(a,b) (((a)>(b))?(b):(a)) +#define MAX(a,b) (((a)>(b))?(a):(b)) #define HAVE_NICAM(msp) (((msp->rev2>>8) & 0xff) != 00) #define HAVE_SIMPLE(msp) ((msp->rev1 & 0xff) >= 'D'-'@') #define HAVE_SIMPLER(msp) ((msp->rev1 & 0xff) >= 'G'-'@') @@ -112,6 +126,7 @@ struct msp3400c { #define dprintk if (debug >= 1) printk #define d2printk if (debug >= 2) printk +#define dprintk_trace if (debug>=16) printk /* read-only */ module_param(opmode, int, 0444); @@ -132,11 +147,6 @@ MODULE_PARM_DESC(standard, "Specify audio standard: 32 = NTSC, 64 = radio, Defau MODULE_PARM_DESC(amsound, "Hardwire AM sound at 6.5Hz (France), FM can autoscan"); MODULE_PARM_DESC(dolby, "Activates Dolby processsing"); - -MODULE_DESCRIPTION("device driver for msp34xx TV sound processor"); -MODULE_AUTHOR("Gerd Knorr"); -MODULE_LICENSE("Dual BSD/GPL"); /* FreeBSD uses this too */ - /* ---------------------------------------------------------------------- */ #define I2C_MSP3400C 0x80 @@ -153,6 +163,10 @@ static unsigned short normal_i2c[] = { }; I2C_CLIENT_INSMOD; +MODULE_DESCRIPTION("device driver for msp34xx TV sound processor"); +MODULE_AUTHOR("Gerd Knorr"); +MODULE_LICENSE("GPL"); + /* ----------------------------------------------------------------------- */ /* functions for talking to the MSP3400C Sound processor */ @@ -172,6 +186,7 @@ static int msp3400c_reset(struct i2c_client *client) { client->addr, I2C_M_RD, 2, read }, }; + dprintk_trace("trace: msp3400c_reset\n"); if ( (1 != i2c_transfer(client->adapter,&reset[0],1)) || (1 != i2c_transfer(client->adapter,&reset[1],1)) || (2 != i2c_transfer(client->adapter,test,2)) ) { @@ -181,10 +196,9 @@ static int msp3400c_reset(struct i2c_client *client) return 0; } -static int -msp3400c_read(struct i2c_client *client, int dev, int addr) +static int msp3400c_read(struct i2c_client *client, int dev, int addr) { - int err; + int err,retval; unsigned char write[3]; unsigned char read[2]; @@ -192,6 +206,7 @@ msp3400c_read(struct i2c_client *client, int dev, int addr) { client->addr, 0, 3, write }, { client->addr, I2C_M_RD, 2, read } }; + write[0] = dev+1; write[1] = addr >> 8; write[2] = addr & 0xff; @@ -200,20 +215,25 @@ msp3400c_read(struct i2c_client *client, int dev, int addr) if (2 == i2c_transfer(client->adapter,msgs,2)) break; err++; - printk(KERN_WARNING "msp34xx: I/O error #%d (read 0x%02x/0x%02x)\n", - err, dev, addr); - msleep(10); + printk(KERN_WARNING + "msp34xx: I/O error #%d (read 0x%02x/0x%02x)\n", err, + dev, addr); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(msecs_to_jiffies(10)); } if (3 == err) { - printk(KERN_WARNING "msp34xx: giving up, reseting chip. Sound will go off, sorry folks :-|\n"); + printk(KERN_WARNING + "msp34xx: giving up, reseting chip. Sound will go off, sorry folks :-|\n"); msp3400c_reset(client); return -1; } - return read[0] << 8 | read[1]; + retval = read[0] << 8 | read[1]; + dprintk_trace("trace: msp3400c_read(0x%x, 0x%x): 0x%x\n", dev, addr, + retval); + return retval; } -static int -msp3400c_write(struct i2c_client *client, int dev, int addr, int val) +static int msp3400c_write(struct i2c_client *client, int dev, int addr, int val) { int err; unsigned char buffer[5]; @@ -224,16 +244,21 @@ msp3400c_write(struct i2c_client *client, int dev, int addr, int val) buffer[3] = val >> 8; buffer[4] = val & 0xff; + dprintk_trace("trace: msp3400c_write(0x%x, 0x%x, 0x%x)\n", dev, addr, + val); for (err = 0; err < 3;) { if (5 == i2c_master_send(client, buffer, 5)) break; err++; - printk(KERN_WARNING "msp34xx: I/O error #%d (write 0x%02x/0x%02x)\n", - err, dev, addr); - msleep(10); + printk(KERN_WARNING + "msp34xx: I/O error #%d (write 0x%02x/0x%02x)\n", err, + dev, addr); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(msecs_to_jiffies(10)); } if (3 == err) { - printk(KERN_WARNING "msp34xx: giving up, reseting chip. Sound will go off, sorry folks :-|\n"); + printk(KERN_WARNING + "msp34xx: giving up, reseting chip. Sound will go off, sorry folks :-|\n"); msp3400c_reset(client); return -1; } @@ -266,45 +291,47 @@ static struct MSP_INIT_DATA_DEM { int dfp_src; int dfp_matrix; } msp_init_data[] = { - /* AM (for carrier detect / msp3400) */ - { { 75, 19, 36, 35, 39, 40 }, { 75, 19, 36, 35, 39, 40 }, - MSP_CARRIER(5.5), MSP_CARRIER(5.5), - 0x00d0, 0x0500, 0x0020, 0x3000}, - - /* AM (for carrier detect / msp3410) */ - { { -1, -1, -8, 2, 59, 126 }, { -1, -1, -8, 2, 59, 126 }, - MSP_CARRIER(5.5), MSP_CARRIER(5.5), - 0x00d0, 0x0100, 0x0020, 0x3000}, - - /* FM Radio */ - { { -8, -8, 4, 6, 78, 107 }, { -8, -8, 4, 6, 78, 107 }, - MSP_CARRIER(10.7), MSP_CARRIER(10.7), - 0x00d0, 0x0480, 0x0020, 0x3000 }, - - /* Terrestial FM-mono + FM-stereo */ - { { 3, 18, 27, 48, 66, 72 }, { 3, 18, 27, 48, 66, 72 }, - MSP_CARRIER(5.5), MSP_CARRIER(5.5), - 0x00d0, 0x0480, 0x0030, 0x3000}, - - /* Sat FM-mono */ - { { 1, 9, 14, 24, 33, 37 }, { 3, 18, 27, 48, 66, 72 }, - MSP_CARRIER(6.5), MSP_CARRIER(6.5), - 0x00c6, 0x0480, 0x0000, 0x3000}, - - /* NICAM/FM -- B/G (5.5/5.85), D/K (6.5/5.85) */ - { { -2, -8, -10, 10, 50, 86 }, { 3, 18, 27, 48, 66, 72 }, - MSP_CARRIER(5.5), MSP_CARRIER(5.5), - 0x00d0, 0x0040, 0x0120, 0x3000}, - - /* NICAM/FM -- I (6.0/6.552) */ - { { 2, 4, -6, -4, 40, 94 }, { 3, 18, 27, 48, 66, 72 }, - MSP_CARRIER(6.0), MSP_CARRIER(6.0), - 0x00d0, 0x0040, 0x0120, 0x3000}, - - /* NICAM/AM -- L (6.5/5.85) */ - { { -2, -8, -10, 10, 50, 86 }, { -4, -12, -9, 23, 79, 126 }, - MSP_CARRIER(6.5), MSP_CARRIER(6.5), - 0x00c6, 0x0140, 0x0120, 0x7c03}, + { /* AM (for carrier detect / msp3400) */ + {75, 19, 36, 35, 39, 40}, + {75, 19, 36, 35, 39, 40}, + MSP_CARRIER(5.5), MSP_CARRIER(5.5), + 0x00d0, 0x0500, 0x0020, 0x3000 + },{ /* AM (for carrier detect / msp3410) */ + {-1, -1, -8, 2, 59, 126}, + {-1, -1, -8, 2, 59, 126}, + MSP_CARRIER(5.5), MSP_CARRIER(5.5), + 0x00d0, 0x0100, 0x0020, 0x3000 + },{ /* FM Radio */ + {-8, -8, 4, 6, 78, 107}, + {-8, -8, 4, 6, 78, 107}, + MSP_CARRIER(10.7), MSP_CARRIER(10.7), + 0x00d0, 0x0480, 0x0020, 0x3000 + },{ /* Terrestial FM-mono + FM-stereo */ + {3, 18, 27, 48, 66, 72}, + {3, 18, 27, 48, 66, 72}, + MSP_CARRIER(5.5), MSP_CARRIER(5.5), + 0x00d0, 0x0480, 0x0030, 0x3000 + },{ /* Sat FM-mono */ + { 1, 9, 14, 24, 33, 37}, + { 3, 18, 27, 48, 66, 72}, + MSP_CARRIER(6.5), MSP_CARRIER(6.5), + 0x00c6, 0x0480, 0x0000, 0x3000 + },{ /* NICAM/FM -- B/G (5.5/5.85), D/K (6.5/5.85) */ + {-2, -8, -10, 10, 50, 86}, + {3, 18, 27, 48, 66, 72}, + MSP_CARRIER(5.5), MSP_CARRIER(5.5), + 0x00d0, 0x0040, 0x0120, 0x3000 + },{ /* NICAM/FM -- I (6.0/6.552) */ + {2, 4, -6, -4, 40, 94}, + {3, 18, 27, 48, 66, 72}, + MSP_CARRIER(6.0), MSP_CARRIER(6.0), + 0x00d0, 0x0040, 0x0120, 0x3000 + },{ /* NICAM/AM -- L (6.5/5.85) */ + {-2, -8, -10, 10, 50, 86}, + {-4, -12, -9, 23, 79, 126}, + MSP_CARRIER(6.5), MSP_CARRIER(6.5), + 0x00c6, 0x0140, 0x0120, 0x7c03 + }, }; struct CARRIER_DETECT { @@ -341,26 +368,24 @@ static struct CARRIER_DETECT carrier_detect_65[] = { /* ----------------------------------------------------------------------- */ static int scarts[3][9] = { - /* MASK IN1 IN2 IN1_DA IN2_DA IN3 IN4 MONO MUTE */ - { 0x0320, 0x0000, 0x0200, -1, -1, 0x0300, 0x0020, 0x0100, 0x0320 }, - { 0x0c40, 0x0440, 0x0400, 0x0c00, 0x0040, 0x0000, 0x0840, 0x0800, 0x0c40 }, - { 0x3080, 0x1000, 0x1080, 0x0000, 0x0080, 0x2080, 0x3080, 0x2000, 0x3000 }, + /* MASK IN1 IN2 IN1_DA IN2_DA IN3 IN4 MONO MUTE */ + { 0x0320, 0x0000, 0x0200, -1, -1, 0x0300, 0x0020, 0x0100, 0x0320 }, + { 0x0c40, 0x0440, 0x0400, 0x0c00, 0x0040, 0x0000, 0x0840, 0x0800, 0x0c40 }, + { 0x3080, 0x1000, 0x1080, 0x0000, 0x0080, 0x2080, 0x3080, 0x2000, 0x3000 }, }; static char *scart_names[] = { - "mask", "in1", "in2", "in1 da", "in2 da", "in3", "in4", "mono", "mute" + "mask", "in1", "in2", "in1 da", "in2 da", "in3", "in4", "mono", "mute" }; -static void -msp3400c_set_scart(struct i2c_client *client, int in, int out) +static void msp3400c_set_scart(struct i2c_client *client, int in, int out) { struct msp3400c *msp = i2c_get_clientdata(client); if (-1 == scarts[out][in]) return; - dprintk(KERN_DEBUG - "msp34xx: scart switch: %s => %d\n",scart_names[in],out); + dprintk("msp34xx: scart switch: %s => %d\n", scart_names[in], out); msp->acb &= ~scarts[out][SCART_MASK]; msp->acb |= scarts[out][in]; msp3400c_write(client,I2C_MSP3400C_DFP, 0x0013, msp->acb); @@ -378,34 +403,34 @@ static void msp3400c_setcarrier(struct i2c_client *client, int cdo1, int cdo2) } static void msp3400c_setvolume(struct i2c_client *client, - int muted, int volume, int balance) -{ - int val = 0, bal = 0; + int muted, int left, int right) + { + int vol = 0, val = 0, balance = 0; -muted=0; if (!muted) { /* 0x7f instead if 0x73 here has sound quality issues, * probably due to overmodulation + clipping ... */ - val = (volume * 0x73 / 65535) << 8; + vol = (left > right) ? left : right; + val = (vol * 0x73 / 65535) << 8; } - if (val) { - bal = (balance / 256) - 128; + if (vol > 0) { + balance = ((right - left) * 127) / vol; } - dprintk(KERN_DEBUG - "msp34xx: setvolume: mute=%s %d:%d v=0x%02x b=0x%02x\n", - muted ? "on" : "off", volume, balance, val>>8, bal); + + dprintk("msp34xx: setvolume: mute=%s %d:%d v=0x%02x b=0x%02x\n", + muted ? "on" : "off", left, right, val >> 8, balance); msp3400c_write(client,I2C_MSP3400C_DFP, 0x0000, val); /* loudspeaker */ msp3400c_write(client,I2C_MSP3400C_DFP, 0x0006, val); /* headphones */ msp3400c_write(client,I2C_MSP3400C_DFP, 0x0007, - muted ? 0x01 : (val | 0x01)); - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0001, bal << 8); + muted ? 0x1 : (val | 0x1)); + msp3400c_write(client, I2C_MSP3400C_DFP, 0x0001, balance << 8); } static void msp3400c_setbass(struct i2c_client *client, int bass) { int val = ((bass-32768) * 0x60 / 65535) << 8; - dprintk(KERN_DEBUG "msp34xx: setbass: %d 0x%02x\n",bass, val>>8); + dprintk("msp34xx: setbass: %d 0x%02x\n", bass, val >> 8); msp3400c_write(client,I2C_MSP3400C_DFP, 0x0002, val); /* loudspeaker */ } @@ -413,7 +438,7 @@ static void msp3400c_settreble(struct i2c_client *client, int treble) { int val = ((treble-32768) * 0x60 / 65535) << 8; - dprintk(KERN_DEBUG "msp34xx: settreble: %d 0x%02x\n",treble, val>>8); + dprintk("msp34xx: settreble: %d 0x%02x\n",treble, val>>8); msp3400c_write(client,I2C_MSP3400C_DFP, 0x0003, val); /* loudspeaker */ } @@ -422,7 +447,7 @@ static void msp3400c_setmode(struct i2c_client *client, int type) struct msp3400c *msp = i2c_get_clientdata(client); int i; - dprintk(KERN_DEBUG "msp3400: setmode: %d\n",type); + dprintk("msp3400: setmode: %d\n",type); msp->mode = type; msp->audmode = V4L2_TUNER_MODE_MONO; msp->rxsubchans = V4L2_TUNER_SUB_MONO; @@ -475,7 +500,8 @@ static void msp3400c_setmode(struct i2c_client *client, int type) } } -static int best_audio_mode(int rxsubchans) +/* given a bitmask of VIDEO_SOUND_XXX returns the "best" in the bitmask */ +static int best_video_sound(int rxsubchans) { if (rxsubchans & V4L2_TUNER_SUB_STEREO) return V4L2_TUNER_MODE_STEREO; @@ -487,31 +513,32 @@ static int best_audio_mode(int rxsubchans) } /* turn on/off nicam + stereo */ -static void msp3400c_set_audmode(struct i2c_client *client, int audmode) +static void msp3400c_setstereo(struct i2c_client *client, int mode) { - static char *strmode[16] = { -#if __GNUC__ >= 3 - [ 0 ... 15 ] = "invalid", -#endif - [ V4L2_TUNER_MODE_MONO ] = "mono", - [ V4L2_TUNER_MODE_STEREO ] = "stereo", - [ V4L2_TUNER_MODE_LANG1 ] = "lang1", - [ V4L2_TUNER_MODE_LANG2 ] = "lang2", + static char *strmode[] = { "0", "mono", "stereo", "3", + "lang1", "5", "6", "7", "lang2" }; struct msp3400c *msp = i2c_get_clientdata(client); - int nicam=0; /* channel source: FM/AM or nicam */ - int src=0; + int nicam = 0; /* channel source: FM/AM or nicam */ + int src = 0; - BUG_ON(msp->opmode == OPMODE_SIMPLER); - msp->audmode = audmode; + if (IS_MSP34XX_G(msp)) { + /* this method would break everything, let's make sure + * it's never called + */ + dprintk + ("msp34xxg: DEBUG WARNING setstereo called with mode=%d instead of set_source (ignored)\n", + mode); + return; + } /* switch demodulator */ switch (msp->mode) { case MSP_MODE_FM_TERRA: - dprintk(KERN_DEBUG "msp3400: FM setstereo: %s\n", - strmode[audmode]); + dprintk("msp3400: FM setstereo: %s\n", + strmode[mode]); msp3400c_setcarrier(client,msp->second,msp->main); - switch (audmode) { + switch (mode) { case V4L2_TUNER_MODE_STEREO: msp3400c_write(client,I2C_MSP3400C_DFP, 0x000e, 0x3001); break; @@ -523,9 +550,8 @@ static void msp3400c_set_audmode(struct i2c_client *client, int audmode) } break; case MSP_MODE_FM_SAT: - dprintk(KERN_DEBUG "msp3400: SAT setstereo: %s\n", - strmode[audmode]); - switch (audmode) { + dprintk("msp3400: SAT setstereo: %s\n", strmode[mode]); + switch (mode) { case V4L2_TUNER_MODE_MONO: msp3400c_setcarrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5)); break; @@ -543,33 +569,29 @@ static void msp3400c_set_audmode(struct i2c_client *client, int audmode) case MSP_MODE_FM_NICAM1: case MSP_MODE_FM_NICAM2: case MSP_MODE_AM_NICAM: - dprintk(KERN_DEBUG "msp3400: NICAM setstereo: %s\n", - strmode[audmode]); + dprintk("msp3400: NICAM setstereo: %s\n",strmode[mode]); msp3400c_setcarrier(client,msp->second,msp->main); if (msp->nicam_on) nicam=0x0100; break; case MSP_MODE_BTSC: - dprintk(KERN_DEBUG "msp3400: BTSC setstereo: %s\n", - strmode[audmode]); + dprintk("msp3400: BTSC setstereo: %s\n",strmode[mode]); nicam=0x0300; break; case MSP_MODE_EXTERN: - dprintk(KERN_DEBUG "msp3400: extern setstereo: %s\n", - strmode[audmode]); + dprintk("msp3400: extern setstereo: %s\n",strmode[mode]); nicam = 0x0200; break; case MSP_MODE_FM_RADIO: - dprintk(KERN_DEBUG "msp3400: FM-Radio setstereo: %s\n", - strmode[audmode]); + dprintk("msp3400: FM-Radio setstereo: %s\n",strmode[mode]); break; default: - dprintk(KERN_DEBUG "msp3400: mono setstereo\n"); + dprintk("msp3400: mono setstereo\n"); return; } /* switch audio */ - switch (audmode) { + switch (best_video_sound(mode)) { case V4L2_TUNER_MODE_STEREO: src = 0x0020 | nicam; break; @@ -589,8 +611,7 @@ static void msp3400c_set_audmode(struct i2c_client *client, int audmode) src = 0x0010 | nicam; break; } - dprintk(KERN_DEBUG - "msp3400: setstereo final source/matrix = 0x%x\n", src); + dprintk("msp3400: setstereo final source/matrix = 0x%x\n", src); if (dolby) { msp3400c_write(client,I2C_MSP3400C_DFP, 0x0008,0x0520); @@ -609,26 +630,26 @@ static void msp3400c_print_mode(struct msp3400c *msp) { if (msp->main == msp->second) { - printk(KERN_DEBUG "msp3400: mono sound carrier: %d.%03d MHz\n", + dprintk("msp3400: mono sound carrier: %d.%03d MHz\n", msp->main/910000,(msp->main/910)%1000); } else { - printk(KERN_DEBUG "msp3400: main sound carrier: %d.%03d MHz\n", + dprintk("msp3400: main sound carrier: %d.%03d MHz\n", msp->main/910000,(msp->main/910)%1000); } - if (msp->mode == MSP_MODE_FM_NICAM1 || - msp->mode == MSP_MODE_FM_NICAM2) - printk(KERN_DEBUG "msp3400: NICAM/FM carrier : %d.%03d MHz\n", + if (msp->mode == MSP_MODE_FM_NICAM1 || msp->mode == MSP_MODE_FM_NICAM2) + dprintk("msp3400: NICAM/FM carrier : %d.%03d MHz\n", msp->second/910000,(msp->second/910)%1000); if (msp->mode == MSP_MODE_AM_NICAM) - printk(KERN_DEBUG "msp3400: NICAM/AM carrier : %d.%03d MHz\n", + dprintk("msp3400: NICAM/AM carrier : %d.%03d MHz\n", msp->second/910000,(msp->second/910)%1000); if (msp->mode == MSP_MODE_FM_TERRA && msp->main != msp->second) { - printk(KERN_DEBUG "msp3400: FM-stereo carrier : %d.%03d MHz\n", + dprintk("msp3400: FM-stereo carrier : %d.%03d MHz\n", msp->second/910000,(msp->second/910)%1000); } } + /* ----------------------------------------------------------------------- */ struct REGISTER_DUMP { @@ -636,8 +657,15 @@ struct REGISTER_DUMP { char *name; }; -static int -autodetect_stereo(struct i2c_client *client) +struct REGISTER_DUMP d1[] = { + {0x007e, "autodetect"}, + {0x0023, "C_AD_BITS "}, + {0x0038, "ADD_BITS "}, + {0x003e, "CIB_BITS "}, + {0x0057, "ERROR_RATE"}, +}; + +static int autodetect_stereo(struct i2c_client *client) { struct msp3400c *msp = i2c_get_clientdata(client); int val; @@ -650,8 +678,7 @@ autodetect_stereo(struct i2c_client *client) val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x18); if (val > 32767) val -= 65536; - dprintk(KERN_DEBUG - "msp34xx: stereo detect register: %d\n",val); + dprintk("msp34xx: stereo detect register: %d\n",val); if (val > 4096) { rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; } else if (val < -4096) { @@ -665,8 +692,7 @@ autodetect_stereo(struct i2c_client *client) case MSP_MODE_FM_NICAM2: case MSP_MODE_AM_NICAM: val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x23); - dprintk(KERN_DEBUG - "msp34xx: nicam sync=%d, mode=%d\n", + dprintk("msp34xx: nicam sync=%d, mode=%d\n", val & 1, (val & 0x1e) >> 1); if (val & 1) { @@ -699,8 +725,7 @@ autodetect_stereo(struct i2c_client *client) break; case MSP_MODE_BTSC: val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x200); - dprintk(KERN_DEBUG - "msp3410: status=0x%x (pri=%s, sec=%s, %s%s%s)\n", + dprintk("msp3410: status=0x%x (pri=%s, sec=%s, %s%s%s)\n", val, (val & 0x0002) ? "no" : "yes", (val & 0x0004) ? "no" : "yes", @@ -714,13 +739,13 @@ autodetect_stereo(struct i2c_client *client) } if (rxsubchans != msp->rxsubchans) { update = 1; - dprintk(KERN_DEBUG "msp34xx: watch: rxsubchans %d => %d\n", + dprintk("msp34xx: watch: rxsubchans %d => %d\n", msp->rxsubchans,rxsubchans); msp->rxsubchans = rxsubchans; } if (newnicam != msp->nicam_on) { update = 1; - dprintk(KERN_DEBUG "msp34xx: watch: nicam %d => %d\n", + dprintk("msp34xx: watch: nicam %d => %d\n", msp->nicam_on,newnicam); msp->nicam_on = newnicam; } @@ -757,8 +782,15 @@ static void watch_stereo(struct i2c_client *client) { struct msp3400c *msp = i2c_get_clientdata(client); - if (autodetect_stereo(client)) - msp3400c_set_audmode(client,best_audio_mode(msp->rxsubchans)); + if (autodetect_stereo(client)) { + if (msp->stereo & V4L2_TUNER_MODE_STEREO) + msp3400c_setstereo(client, V4L2_TUNER_MODE_STEREO); + else if (msp->stereo & VIDEO_SOUND_LANG1) + msp3400c_setstereo(client, V4L2_TUNER_MODE_LANG1); + else + msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); + } + if (once) msp->watch_stereo = 0; } @@ -786,8 +818,7 @@ static int msp3400c_thread(void *data) MSP_MODE_EXTERN == msp->mode) { /* no carrier scan, just unmute */ printk("msp3400: thread: no carrier scan\n"); - msp3400c_setvolume(client, msp->muted, - msp->volume, msp->balance); + msp3400c_setvolume(client, msp->muted, msp->left, msp->right); continue; } @@ -866,7 +897,7 @@ static int msp3400c_thread(void *data) msp->second = carrier_detect_55[max2].cdo; msp3400c_setmode(client, MSP_MODE_FM_TERRA); msp->nicam_on = 0; - msp3400c_set_audmode(client, V4L2_TUNER_MODE_MONO); + msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); msp->watch_stereo = 1; } else if (max2 == 1 && HAVE_NICAM(msp)) { /* B/G NICAM */ @@ -893,7 +924,7 @@ static int msp3400c_thread(void *data) msp->second = carrier_detect_65[max2].cdo; msp3400c_setmode(client, MSP_MODE_FM_TERRA); msp->nicam_on = 0; - msp3400c_set_audmode(client, V4L2_TUNER_MODE_MONO); + msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); msp->watch_stereo = 1; } else if (max2 == 0 && msp->norm == VIDEO_MODE_SECAM) { @@ -901,7 +932,7 @@ static int msp3400c_thread(void *data) msp->second = carrier_detect_65[max2].cdo; msp3400c_setmode(client, MSP_MODE_AM_NICAM); msp->nicam_on = 0; - msp3400c_set_audmode(client, V4L2_TUNER_MODE_MONO); + msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); msp3400c_setcarrier(client, msp->second, msp->main); /* volume prescale for SCART (AM mono input) */ msp3400c_write(client,I2C_MSP3400C_DFP, 0x000d, 0x1900); @@ -925,13 +956,12 @@ static int msp3400c_thread(void *data) msp->nicam_on = 0; msp3400c_setcarrier(client, msp->second, msp->main); msp->rxsubchans = V4L2_TUNER_SUB_MONO; - msp3400c_set_audmode(client, V4L2_TUNER_MODE_MONO); + msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); break; } /* unmute */ - msp3400c_setvolume(client, msp->muted, - msp->volume, msp->balance); + msp3400c_setvolume(client, msp->muted, msp->left, msp->right); if (debug) msp3400c_print_mode(msp); @@ -942,7 +972,7 @@ static int msp3400c_thread(void *data) watch_stereo(client); } } - dprintk(KERN_DEBUG "msp3400: thread: exit\n"); + dprintk("msp3400: thread: exit\n"); return 0; } @@ -990,7 +1020,7 @@ static int msp34xx_modus(int norm) { switch (norm) { case VIDEO_MODE_PAL: - dprintk(KERN_DEBUG "msp34xx: video mode selected to PAL\n"); + dprintk("msp34xx: video mode selected to PAL\n"); #if 1 /* experimental: not sure this works with all chip versions */ @@ -1000,16 +1030,16 @@ static int msp34xx_modus(int norm) return 0x1003; #endif case VIDEO_MODE_NTSC: /* BTSC */ - dprintk(KERN_DEBUG "msp34xx: video mode selected to NTSC\n"); + dprintk("msp34xx: video mode selected to NTSC\n"); return 0x2003; case VIDEO_MODE_SECAM: - dprintk(KERN_DEBUG "msp34xx: video mode selected to SECAM\n"); + dprintk("msp34xx: video mode selected to SECAM\n"); return 0x0003; case VIDEO_MODE_RADIO: - dprintk(KERN_DEBUG "msp34xx: video mode selected to Radio\n"); + dprintk("msp34xx: video mode selected to Radio\n"); return 0x0003; case VIDEO_MODE_AUTO: - dprintk(KERN_DEBUG "msp34xx: video mode selected to Auto\n"); + dprintk("msp34xx: video mode selected to Auto\n"); return 0x2003; default: return 0x0003; @@ -1040,9 +1070,9 @@ static int msp3410d_thread(void *data) printk("msp3410: daemon started\n"); for (;;) { - d2printk(KERN_DEBUG "msp3410: thread: sleep\n"); + d2printk("msp3410: thread: sleep\n"); msp34xx_sleep(msp,-1); - d2printk(KERN_DEBUG "msp3410: thread: wakeup\n"); + d2printk("msp3410: thread: wakeup\n"); restart: dprintk("msp3410: thread: restart scan\n"); @@ -1052,9 +1082,8 @@ static int msp3410d_thread(void *data) if (msp->mode == MSP_MODE_EXTERN) { /* no carrier scan needed, just unmute */ - dprintk(KERN_DEBUG "msp3410: thread: no carrier scan\n"); - msp3400c_setvolume(client, msp->muted, - msp->volume, msp->balance); + dprintk("msp3410: thread: no carrier scan\n"); + msp3400c_setvolume(client, msp->muted, msp->left, msp->right); continue; } @@ -1073,7 +1102,7 @@ static int msp3410d_thread(void *data) msp->watch_stereo = 0; if (debug) - printk(KERN_DEBUG "msp3410: setting mode: %s (0x%04x)\n", + dprintk("msp3410: setting mode: %s (0x%04x)\n", msp34xx_standard_mode_name(std) ,std); if (std != 1) { @@ -1089,13 +1118,13 @@ static int msp3410d_thread(void *data) val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x7e); if (val < 0x07ff) break; - dprintk(KERN_DEBUG "msp3410: detection still in progress\n"); + dprintk("msp3410: detection still in progress\n"); } } for (i = 0; modelist[i].name != NULL; i++) if (modelist[i].retval == val) break; - dprintk(KERN_DEBUG "msp3410: current mode: %s (0x%04x)\n", + dprintk("msp3410: current mode: %s (0x%04x)\n", modelist[i].name ? modelist[i].name : "unknown", val); msp->main = modelist[i].main; @@ -1103,7 +1132,7 @@ static int msp3410d_thread(void *data) if (amsound && (msp->norm == VIDEO_MODE_SECAM) && (val != 0x0009)) { /* autodetection has failed, let backup */ - dprintk(KERN_DEBUG "msp3410: autodetection failed," + dprintk("msp3410: autodetection failed," " switching to backup mode: %s (0x%04x)\n", modelist[8].name ? modelist[8].name : "unknown",val); val = 0x0009; @@ -1127,13 +1156,13 @@ static int msp3410d_thread(void *data) msp->rxsubchans = V4L2_TUNER_SUB_STEREO; msp->nicam_on = 1; msp->watch_stereo = 1; - msp3400c_set_audmode(client,V4L2_TUNER_MODE_STEREO); + msp3400c_setstereo(client,V4L2_TUNER_MODE_STEREO); break; case 0x0009: msp->mode = MSP_MODE_AM_NICAM; msp->rxsubchans = V4L2_TUNER_SUB_MONO; msp->nicam_on = 1; - msp3400c_set_audmode(client,V4L2_TUNER_MODE_MONO); + msp3400c_setstereo(client,V4L2_TUNER_MODE_MONO); msp->watch_stereo = 1; break; case 0x0020: /* BTSC */ @@ -1142,7 +1171,7 @@ static int msp3410d_thread(void *data) msp->rxsubchans = V4L2_TUNER_SUB_STEREO; msp->nicam_on = 0; msp->watch_stereo = 1; - msp3400c_set_audmode(client,V4L2_TUNER_MODE_STEREO); + msp3400c_setstereo(client,V4L2_TUNER_MODE_STEREO); break; case 0x0040: /* FM radio */ msp->mode = MSP_MODE_FM_RADIO; @@ -1176,8 +1205,7 @@ static int msp3410d_thread(void *data) /* unmute, restore misc registers */ msp3400c_setbass(client, msp->bass); msp3400c_settreble(client, msp->treble); - msp3400c_setvolume(client, msp->muted, - msp->volume, msp->balance); + msp3400c_setvolume(client, msp->muted, msp->left, msp->right); msp3400c_write(client, I2C_MSP3400C_DFP, 0x0013, msp->acb); /* monitor tv audio mode */ @@ -1187,7 +1215,7 @@ static int msp3410d_thread(void *data) watch_stereo(client); } } - dprintk(KERN_DEBUG "msp3410: thread: exit\n"); + dprintk("msp3410: thread: exit\n"); return 0; } @@ -1264,9 +1292,9 @@ static int msp34xxg_thread(void *data) printk("msp34xxg: daemon started\n"); msp->source = 1; /* default */ for (;;) { - d2printk(KERN_DEBUG "msp34xxg: thread: sleep\n"); + d2printk("msp34xxg: thread: sleep\n"); msp34xx_sleep(msp,-1); - d2printk(KERN_DEBUG "msp34xxg: thread: wakeup\n"); + d2printk("msp34xxg: thread: wakeup\n"); restart: dprintk("msp34xxg: thread: restart scan\n"); @@ -1308,7 +1336,7 @@ static int msp34xxg_thread(void *data) msp3400c_setbass(client, msp->bass); msp3400c_settreble(client, msp->treble); - msp3400c_setvolume(client, msp->muted, msp->volume, msp->balance); + msp3400c_setvolume(client, msp->muted, msp->left, msp->right); /* restore ACB */ if (msp3400c_write(client, @@ -1317,7 +1345,7 @@ static int msp34xxg_thread(void *data) msp->acb)) return -1; } - dprintk(KERN_DEBUG "msp34xxg: thread: exit\n"); + dprintk("msp34xxg: thread: exit\n"); return 0; } @@ -1476,12 +1504,12 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) } memset(msp,0,sizeof(struct msp3400c)); - msp->volume = 58880; /* 0db gain */ - msp->balance = 32768; - msp->bass = 32768; - msp->treble = 32768; - msp->input = -1; - msp->muted = 1; + msp->left = 58880; /* 0db gain */ + msp->right = 58880; /* 0db gain */ + msp->bass = 32768; + msp->treble = 32768; + msp->input = -1; + msp->muted = 0; i2c_set_clientdata(c, msp); init_waitqueue_head(&msp->wq); @@ -1504,7 +1532,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) } printk(KERN_INFO "msp34xx: rev1=0x%04x, rev2=0x%04x\n", msp->rev1, msp->rev2); - msp3400c_setvolume(c, msp->muted, msp->volume, msp->balance); + msp3400c_setvolume(c, msp->muted, msp->left, msp->right); snprintf(c->name, sizeof(c->name), "MSP34%02d%c-%c%d", (msp->rev2>>8)&0xff, (msp->rev1&0xff)+'@', @@ -1558,6 +1586,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) /* done */ i2c_attach_client(c); + return 0; } @@ -1648,7 +1677,7 @@ static void msp_any_set_audmode(struct i2c_client *client, int audmode) case OPMODE_MANUAL: case OPMODE_SIMPLE: msp->watch_stereo = 0; - msp3400c_set_audmode(client, audmode); + msp3400c_setstereo(client, audmode); break; case OPMODE_SIMPLER: msp34xxg_set_audmode(client, audmode); @@ -1665,7 +1694,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) switch (cmd) { case AUDC_SET_INPUT: - dprintk(KERN_DEBUG "msp34xx: AUDC_SET_INPUT(%d)\n",*sarg); + dprintk("msp34xx: AUDC_SET_INPUT(%d)\n",*sarg); if (*sarg == msp->input) break; msp->input = *sarg; @@ -1699,15 +1728,15 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) msp3400c_set_scart(client,scart,0); msp3400c_write(client,I2C_MSP3400C_DFP,0x000d,0x1900); if (msp->opmode != OPMODE_SIMPLER) - msp3400c_set_audmode(client, msp->audmode); + msp3400c_setstereo(client, msp->audmode); } msp_wake_thread(client); break; case AUDC_SET_RADIO: - dprintk(KERN_DEBUG "msp34xx: AUDC_SET_RADIO\n"); + dprintk("msp34xx: AUDC_SET_RADIO\n"); msp->norm = VIDEO_MODE_RADIO; - dprintk(KERN_DEBUG "msp34xx: switching to radio mode\n"); + dprintk("msp34xx: switching to radio mode\n"); msp->watch_stereo = 0; switch (msp->opmode) { case OPMODE_MANUAL: @@ -1715,8 +1744,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) msp3400c_setmode(client,MSP_MODE_FM_RADIO); msp3400c_setcarrier(client, MSP_CARRIER(10.7), MSP_CARRIER(10.7)); - msp3400c_setvolume(client, msp->muted, - msp->volume, msp->balance); + msp3400c_setvolume(client, msp->muted, msp->left, msp->right); break; case OPMODE_SIMPLE: case OPMODE_SIMPLER: @@ -1733,7 +1761,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct video_audio *va = arg; - dprintk(KERN_DEBUG "msp34xx: VIDIOCGAUDIO\n"); + dprintk("msp34xx: VIDIOCGAUDIO\n"); va->flags |= VIDEO_AUDIO_VOLUME | VIDEO_AUDIO_BASS | VIDEO_AUDIO_TREBLE | @@ -1741,8 +1769,15 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) if (msp->muted) va->flags |= VIDEO_AUDIO_MUTE; - va->volume = msp->volume; - va->balance = (va->volume) ? msp->balance : 32768; + if (msp->muted) + va->flags |= VIDEO_AUDIO_MUTE; + va->volume = MAX(msp->left, msp->right); + va->balance = (32768 * MIN(msp->left, msp->right)) / + (va->volume ? va->volume : 1); + va->balance = (msp->left < msp->right) ? + (65535 - va->balance) : va->balance; + if (0 == va->volume) + va->balance = 32768; va->bass = msp->bass; va->treble = msp->treble; @@ -1754,17 +1789,32 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct video_audio *va = arg; - dprintk(KERN_DEBUG "msp34xx: VIDIOCSAUDIO\n"); + dprintk("msp34xx: VIDIOCSAUDIO\n"); msp->muted = (va->flags & VIDEO_AUDIO_MUTE); - msp->volume = va->volume; - msp->balance = va->balance; + msp->left = (MIN(65536 - va->balance, 32768) * + va->volume) / 32768; + msp->right = (MIN(va->balance, 32768) * va->volume) / 32768; msp->bass = va->bass; msp->treble = va->treble; - - msp3400c_setvolume(client, msp->muted, - msp->volume, msp->balance); - msp3400c_setbass(client,msp->bass); - msp3400c_settreble(client,msp->treble); + dprintk("msp34xx: VIDIOCSAUDIO setting va->volume to %d\n", + va->volume); + dprintk("msp34xx: VIDIOCSAUDIO setting va->balance to %d\n", + va->balance); + dprintk("msp34xx: VIDIOCSAUDIO setting va->flags to %d\n", + va->flags); + dprintk("msp34xx: VIDIOCSAUDIO setting msp->left to %d\n", + msp->left); + dprintk("msp34xx: VIDIOCSAUDIO setting msp->right to %d\n", + msp->right); + dprintk("msp34xx: VIDIOCSAUDIO setting msp->bass to %d\n", + msp->bass); + dprintk("msp34xx: VIDIOCSAUDIO setting msp->treble to %d\n", + msp->treble); + dprintk("msp34xx: VIDIOCSAUDIO setting msp->mode to %d\n", + msp->mode); + msp3400c_setvolume(client, msp->muted, msp->left, msp->right); + msp3400c_setbass(client, msp->bass); + msp3400c_settreble(client, msp->treble); if (va->mode != 0 && msp->norm != VIDEO_MODE_RADIO) msp_any_set_audmode(client,mode_v4l1_to_v4l2(va->mode)); @@ -1775,7 +1825,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct video_channel *vc = arg; - dprintk(KERN_DEBUG "msp34xx: VIDIOCSCHAN (norm=%d)\n",vc->norm); + dprintk("msp34xx: VIDIOCSCHAN (norm=%d)\n",vc->norm); msp->norm = vc->norm; msp_wake_thread(client); break; @@ -1785,7 +1835,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) case VIDIOC_S_FREQUENCY: { /* new channel -- kick audio carrier scan */ - dprintk(KERN_DEBUG "msp34xx: VIDIOCSFREQ\n"); + dprintk("msp34xx: VIDIOCSFREQ\n"); msp_wake_thread(client); break; } @@ -1904,7 +1954,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct msp_matrix *mspm = arg; - dprintk(KERN_DEBUG "msp34xx: MSP_SET_MATRIX\n"); + dprintk("msp34xx: MSP_SET_MATRIX\n"); msp3400c_set_scart(client, mspm->input, mspm->output); break; } -- cgit v1.2.3 From 18f47d10bc8076bb126a1a369b782e29cc91c824 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:19 -0800 Subject: [PATCH] v4l: 759: more improvements at msp3400 c from ivtv code - More improvements at msp3400.c from ivtv code. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/msp3400.c | 111 +++++++++++++++++++++++++++++++++++------- 1 file changed, 93 insertions(+), 18 deletions(-) diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index 4689dee882f..117d124657d 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -649,6 +649,30 @@ msp3400c_print_mode(struct msp3400c *msp) } } +#define MSP3400_MAX 4 +static struct i2c_client *msps[MSP3400_MAX]; +static void msp3400c_restore_dfp(struct i2c_client *client) +{ + struct msp3400c *msp = i2c_get_clientdata(client); + int i; + + for (i = 0; i < DFP_COUNT; i++) { + if (-1 == msp->dfp_regs[i]) + continue; + msp3400c_write(client, I2C_MSP3400C_DFP, i, msp->dfp_regs[i]); + } +} + +/* if the dfp_regs is set, set what's in there. Otherwise, set the default value */ +static int msp3400c_write_dfp_with_default(struct i2c_client *client, + int addr, int default_value) +{ + struct msp3400c *msp = i2c_get_clientdata(client); + int value = default_value; + if (addr < DFP_COUNT && -1 != msp->dfp_regs[addr]) + value = msp->dfp_regs[addr]; + return msp3400c_write(client, I2C_MSP3400C_DFP, addr, value); +} /* ----------------------------------------------------------------------- */ @@ -834,7 +858,8 @@ static int msp3400c_thread(void *data) goto restart; /* carrier detect pass #1 -- main carrier */ - cd = carrier_detect_main; count = CARRIER_COUNT(carrier_detect_main); + cd = carrier_detect_main; + count = CARRIER_COUNT(carrier_detect_main); if (amsound && (msp->norm == VIDEO_MODE_SECAM)) { /* autodetect doesn't work well with AM ... */ @@ -868,13 +893,16 @@ static int msp3400c_thread(void *data) case 0: /* 4.5 */ case 2: /* 6.0 */ default: - cd = NULL; count = 0; + cd = NULL; + count = 0; break; } if (amsound && (msp->norm == VIDEO_MODE_SECAM)) { /* autodetect doesn't work well with AM ... */ - cd = NULL; count = 0; max2 = 0; + cd = NULL; + count = 0; + max2 = 0; } for (this = 0; this < count; this++) { msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo); @@ -962,6 +990,8 @@ static int msp3400c_thread(void *data) /* unmute */ msp3400c_setvolume(client, msp->muted, msp->left, msp->right); + msp3400c_restore_dfp(client); + if (debug) msp3400c_print_mode(msp); @@ -1207,6 +1237,7 @@ static int msp3410d_thread(void *data) msp3400c_settreble(client, msp->treble); msp3400c_setvolume(client, msp->muted, msp->left, msp->right); msp3400c_write(client, I2C_MSP3400C_DFP, 0x0013, msp->acb); + msp3400c_restore_dfp(client); /* monitor tv audio mode */ while (msp->watch_stereo) { @@ -1230,7 +1261,7 @@ static void msp34xxg_set_source(struct i2c_client *client, int source); /* (re-)initialize the msp34xxg, according to the current norm in msp->norm * return 0 if it worked, -1 if it failed */ -static int msp34xxg_init(struct i2c_client *client) +static int msp34xxg_reset(struct i2c_client *client) { struct msp3400c *msp = i2c_get_clientdata(client); int modus,std; @@ -1257,7 +1288,7 @@ static int msp34xxg_init(struct i2c_client *client) return -1; if (msp3400c_write(client, I2C_MSP3400C_DEM, - 0x20/*stanard*/, + 0x20/*standard*/, std)) return -1; @@ -1265,21 +1296,18 @@ static int msp34xxg_init(struct i2c_client *client) standard/audio autodetection right now */ msp34xxg_set_source(client, msp->source); - if (msp3400c_write(client, I2C_MSP3400C_DFP, - 0x0e, /* AM/FM Prescale */ - 0x3000 /* default: [15:8] 75khz deviation */)) + if (msp3400c_write_dfp_with_default(client, 0x0e, /* AM/FM Prescale */ + 0x3000 + /* default: [15:8] 75khz deviation */ + )) return -1; - if (msp3400c_write(client, I2C_MSP3400C_DFP, - 0x10, /* NICAM Prescale */ - 0x5a00 /* default: 9db gain (as recommended) */)) + if (msp3400c_write_dfp_with_default(client, 0x10, /* NICAM Prescale */ + 0x5a00 + /* default: 9db gain (as recommended) */ + )) return -1; - if (msp3400c_write(client, - I2C_MSP3400C_DEM, - 0x20, /* STANDARD SELECT */ - standard /* default: 0x01 for automatic standard select*/)) - return -1; return 0; } @@ -1303,7 +1331,7 @@ static int msp34xxg_thread(void *data) break; /* setup the chip*/ - msp34xxg_init(client); + msp34xxg_reset(client); std = standard; if (std != 0x01) goto unmute; @@ -1486,6 +1514,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) struct msp3400c *msp; struct i2c_client *c; int (*thread_func)(void *data) = NULL; + int i; client_template.adapter = adap; client_template.addr = addr; @@ -1504,12 +1533,15 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) } memset(msp,0,sizeof(struct msp3400c)); + msp->norm = VIDEO_MODE_NTSC; msp->left = 58880; /* 0db gain */ msp->right = 58880; /* 0db gain */ msp->bass = 32768; msp->treble = 32768; msp->input = -1; msp->muted = 0; + for (i = 0; i < DFP_COUNT; i++) + msp->dfp_regs[i] = -1; i2c_set_clientdata(c, msp); init_waitqueue_head(&msp->wq); @@ -1579,6 +1611,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) /* startup control thread if needed */ if (thread_func) { msp->kthread = kthread_run(thread_func, c, "msp34xx"); + if (NULL == msp->kthread) printk(KERN_WARNING "msp34xx: kernel_thread() failed\n"); msp_wake_thread(c); @@ -1587,21 +1620,39 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) /* done */ i2c_attach_client(c); + /* update our own array */ + for (i = 0; i < MSP3400_MAX; i++) { + if (NULL == msps[i]) { + msps[i] = c; + break; + } + } + return 0; } static int msp_detach(struct i2c_client *client) { struct msp3400c *msp = i2c_get_clientdata(client); + int i; /* shutdown control thread */ if (msp->kthread) { msp->restart = 1; kthread_stop(msp->kthread); } - msp3400c_reset(client); + msp3400c_reset(client); + + /* update our own array */ + for (i = 0; i < MSP3400_MAX; i++) { + if (client == msps[i]) { + msps[i] = NULL; + break; + } + } i2c_detach_client(client); + kfree(msp); kfree(client); return 0; @@ -1753,6 +1804,30 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } break; + /* work-in-progress: hook to control the DFP registers */ + case MSP_SET_DFPREG: + { + struct msp_dfpreg *r = arg; + int i; + + if (r->reg < 0 || r->reg >= DFP_COUNT) + return -EINVAL; + for (i = 0; i < sizeof(bl_dfp) / sizeof(int); i++) + if (r->reg == bl_dfp[i]) + return -EINVAL; + msp->dfp_regs[r->reg] = r->value; + msp3400c_write(client, I2C_MSP3400C_DFP, r->reg, r->value); + return 0; + } + case MSP_GET_DFPREG: + { + struct msp_dfpreg *r = arg; + + if (r->reg < 0 || r->reg >= DFP_COUNT) + return -EINVAL; + r->value = msp3400c_read(client, I2C_MSP3400C_DFP, r->reg); + return 0; + } /* --- v4l ioctls --- */ /* take care: bttv does userspace copying, we'll get a -- cgit v1.2.3 From a9ae9fb17bdcb22ae0c1abc6ebd97704dd80d9d1 Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Tue, 8 Nov 2005 21:37:20 -0800 Subject: [PATCH] v4l: 761: fixed registry value in em2820 - Fixed registry value in em2820-i2c.c which corrects a tuner setting (also removed that call from em2820-video.c) Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-i2c.c | 40 +++++++++++++++---------------- drivers/media/video/em28xx/em28xx-video.c | 1 - 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 150c72bb6e4..8551998dbae 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -302,26 +302,26 @@ static int attach_inform(struct i2c_client *client) dprintk("address %x", client->addr << 1); switch (client->addr << 1) { - case 0x68: - em2820_i2c_call_clients(dev, TDA9887_SET_CONFIG, &dev->tda9887_conf); - break; - case 0x4a: - dprintk1("attach_inform: saa7113 detected.\n"); - break; - case 0xa0: - dprintk1("attach_inform: eeprom detected.\n"); - break; - case 0x80: - case 0x88: - dprintk1("attach_inform: msp34xx detected.\n"); - break; - case 0xb8: - case 0xba: - dprintk1("attach_inform: tvp5150 detected.\n"); - break; - default: - dev->tuner_addr = client->addr; - em2820_set_tuner(-1, client); + case 0x86: + em2820_i2c_call_clients(dev, TDA9887_SET_CONFIG, &dev->tda9887_conf); + break; + case 0x4a: + dprintk1("attach_inform: saa7113 detected.\n"); + break; + case 0xa0: + dprintk1("attach_inform: eeprom detected.\n"); + break; + case 0x80: + case 0x88: + dprintk1("attach_inform: msp34xx detected.\n"); + break; + case 0xb8: + case 0xba: + dprintk1("attach_inform: tvp5150 detected.\n"); + break; + default: + dev->tuner_addr = client->addr; + em2820_set_tuner(-1, client); } return 0; diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 3581fc4c874..7e4114ea15f 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -225,7 +225,6 @@ void em2820_config_i2c(struct em2820 *dev) /* configure tda9887 */ - em2820_i2c_call_clients(dev, TDA9887_SET_CONFIG, &dev->tda9887_conf); /* em2820_i2c_call_clients(dev,VIDIOC_S_STD,&dev->tvnorm->id); */ } -- cgit v1.2.3 From c365864faf8c68db9d1a64d4356758da9f206ff1 Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Tue, 8 Nov 2005 21:37:21 -0800 Subject: [PATCH] v4l: 762: added support for the terratec cinergy 250 usb tv remote - Added support for the terratec cinergy 250 usb tv remote Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-i2c.c | 2 +- drivers/media/video/ir-kbd-i2c.c | 45 +++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 8551998dbae..3065ddb4b36 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -31,7 +31,7 @@ /* To be moved to compat.h */ #if !defined(I2C_HW_B_EM2820) -#define I2C_HW_B_EM2820 I2C_HW_B_BT848 +#define I2C_HW_B_EM2820 0x99 #endif #include "em2820.h" diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 225fee93cfd..061dda10721 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -8,6 +8,8 @@ * Christoph Bartelmus * modified for KNC ONE TV Station/Anubis Typhoon TView Tuner by * Ulrich Mueller + * modified for em2820 based USB TV tuners by + * Markus Rechberger * * 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 @@ -40,6 +42,38 @@ #include #include +static IR_KEYTAB_TYPE ir_codes_em2820[IR_KEYTAB_SIZE] = { + [ 0 ] = KEY_CHANNEL, + [ 1 ] = KEY_SELECT, + [ 2 ] = KEY_MUTE, + [ 3 ] = KEY_POWER, + [ 4 ] = KEY_KP1, + [ 5 ] = KEY_KP2, + [ 6 ] = KEY_KP3, + [ 7 ] = KEY_CHANNELUP, + [ 8 ] = KEY_KP4, + [ 9 ] = KEY_KP5, + [ 10 ] = KEY_KP6, + + [ 11 ] = KEY_CHANNELDOWN, + [ 12 ] = KEY_KP7, + [ 13 ] = KEY_KP8, + [ 14 ] = KEY_KP9, + [ 15 ] = KEY_VOLUMEUP, + [ 16 ] = KEY_KP0, + [ 17 ] = KEY_MENU, + [ 18 ] = KEY_PRINT, + + [ 19 ] = KEY_VOLUMEDOWN, + [ 21 ] = KEY_PAUSE, + [ 23 ] = KEY_RECORD, + [ 24 ] = KEY_REWIND, + [ 25 ] = KEY_PLAY, + [ 27 ] = KEY_BACKSPACE, + [ 29 ] = KEY_STOP, + [ 31 ] = KEY_ZOOM, +}; + /* Mark Phalan */ static IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE] = { [ 0 ] = KEY_KP0, @@ -352,6 +386,13 @@ static int ir_attach(struct i2c_adapter *adap, int addr, ir_type = IR_TYPE_RC5; ir_codes = ir_codes_rc5_tv; break; + case 0x60: + name = "em2820"; + ir->get_key = get_key_knc1; + ir->c.addr = addr>>1; + ir_type = IR_TYPE_OTHER; + ir_codes = ir_codes_em2820; + break; case 0x30: name = "KNC One"; ir->get_key = get_key_knc1; @@ -427,6 +468,7 @@ static int ir_probe(struct i2c_adapter *adap) static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1}; static const int probe_saa7134[] = { 0x7a, -1 }; + static const int probe_em2820[] = { 0x60, -1 }; const int *probe = NULL; struct i2c_client c; char buf; int i,rc; @@ -437,6 +479,9 @@ static int ir_probe(struct i2c_adapter *adap) case I2C_HW_SAA7134: probe = probe_saa7134; break; + case I2C_HW_B_EM2820: + probe = probe_em2820; + break; } if (NULL == probe) return 0; -- cgit v1.2.3 From 40c717ff48b2c91091a69de0e28c02a43e9b0c7c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 8 Nov 2005 21:37:21 -0800 Subject: [PATCH] v4l: 763: include newer i2c id at linux include media id h - Include newer I2C ID at ../linux/include/media/id.h: Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/media/id.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/media/id.h b/include/media/id.h index 6d02c94cdc0..4f58d73e702 100644 --- a/include/media/id.h +++ b/include/media/id.h @@ -33,3 +33,18 @@ #ifndef I2C_DRIVERID_SAA6752HS # define I2C_DRIVERID_SAA6752HS I2C_DRIVERID_EXP0+8 #endif +#ifndef I2C_DRIVERID_WM8775 +#define I2C_DRIVERID_WM8775 I2C_DRIVERID_EXP0+9 +#endif +#ifndef I2C_DRIVERID_CS53L32A +#define I2C_DRIVERID_CS53L32A I2C_DRIVERID_EXP0+10 +#endif +#ifndef I2C_DRIVERID_CX25840 +#define I2C_DRIVERID_CX25840 I2C_DRIVERID_EXP0+11 +#endif +#ifndef I2C_DRIVERID_SAA7115 +#define I2C_DRIVERID_SAA7115 I2C_DRIVERID_EXP0+12 +#endif +#ifndef I2C_DRIVERID_SAA7127 +#define I2C_DRIVERID_SAA7127 I2C_DRIVERID_EXP0+13 +#endif -- cgit v1.2.3 From 2b5200a7b19a53969db68c97d379339592ca6a4f Mon Sep 17 00:00:00 2001 From: David Shirley Date: Tue, 8 Nov 2005 21:37:22 -0800 Subject: [PATCH] v4l: 766: add dvb card winfast dtv1000-t - Add DVB card WinFast DTV1000-T Signed-off-by: David Shirley Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.cx88 | 1 + drivers/media/video/cx88/cx88-cards.c | 16 ++++++++++++++++ drivers/media/video/cx88/cx88-dvb.c | 1 + drivers/media/video/cx88/cx88.h | 1 + 4 files changed, 19 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index ca46fbf489d..12e9e393868 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -33,3 +33,4 @@ 32 -> AverMedia UltraTV Media Center PCI 550 [1461:8011] 33 -> Kworld V-Stream Xpert DVD 34 -> ATI HDTV Wonder [1002:a101] + 35 -> WinFast DTV1000-T [107d:665f] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 388440789df..6a85ba111fb 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -852,6 +852,18 @@ struct cx88_board cx88_boards[] = { .gpio3 = 0x00000000, }}, }, + [CX88_BOARD_WINFAST_DTV1000] = { + .name = "WinFast DTV1000-T", + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_DVB, + .vmux = 0, + }}, + .dvb = 1, + }, }; const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); @@ -991,6 +1003,10 @@ struct cx88_subid cx88_subids[] = { .subvendor = PCI_VENDOR_ID_ATI, .subdevice = 0xa101, .card = CX88_BOARD_ATI_HDTVWONDER, + },{ + .subvendor = 0x107d, + .subdevice = 0x665f, + .card = CX88_BOARD_WINFAST_DTV1000, }, }; const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 82e686135f6..579de88e308 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -299,6 +299,7 @@ static int dvb_register(struct cx8802_dev *dev) break; case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: case CX88_BOARD_CONEXANT_DVB_T1: + case CX88_BOARD_WINFAST_DTV1000: dev->dvb.frontend = cx22702_attach(&connexant_refboard_config, &dev->core->i2c_adap); break; diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index a690569f345..ea5c092a779 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -177,6 +177,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_AVERMEDIA_ULTRATV_MC_550 32 #define CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD 33 #define CX88_BOARD_ATI_HDTVWONDER 34 +#define CX88_BOARD_WINFAST_DTV1000 35 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- cgit v1.2.3 From 596d92d5128d308b5a79f21c3e72c87f5fc7e58b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:24 -0800 Subject: [PATCH] v4l: 767: included support for em2800 - Included support for em2800. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.em28xx | 13 ++- drivers/media/video/em28xx/em28xx-cards.c | 125 ++++++++++++++++++-- drivers/media/video/em28xx/em28xx-core.c | 13 ++- drivers/media/video/em28xx/em28xx-i2c.c | 182 ++++++++++++++++++++++++++---- drivers/media/video/em28xx/em28xx-video.c | 73 +++++++++--- drivers/media/video/em28xx/em28xx.h | 29 ++++- 6 files changed, 375 insertions(+), 60 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index a33ddea0b6f..d86aae09450 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -1,4 +1,9 @@ - 0 -> Terratec Cinergy 250 USB [0ccd:0036] - 1 -> Pinnacle PCTV USB 2 [2304:0208] - 2 -> Hauppauge WinTV USB 2 [2040:4200] - 3 -> MSI VOX USB 2.0 [eb1a:2820] + 0 -> Unknown EM2800 video grabber (em2800) [eb1a:2800] + 1 -> Unknown EM2820/2840 video grabber (em2820/em2840) [eb1a:2820] + 2 -> Terratec Cinergy 250 USB (em2820/em2840) [0ccd:0036] + 3 -> Pinnacle PCTV USB 2 (em2820/em2840) [2304:0208] + 4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200] + 5 -> MSI VOX USB 2.0 (em2820/em2840) + 6 -> Terratec Cinergy 200 USB (em2800) + 7 -> Leadtek Winfast USB II (em2800) + 8 -> Kworld USB2800 (em2800) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 7333bbad887..91c70ebd0ea 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -1,5 +1,5 @@ /* - em2820-cards.c - driver for Empia EM2820/2840 USB video capture devices + em2820-cards.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger Ludovico Cavedon @@ -35,14 +35,43 @@ #include "em2820.h" -enum em2820_board_entry { - EM2820_BOARD_TERRATEC_CINERGY_250, - EM2820_BOARD_PINNACLE_USB_2, - EM2820_BOARD_HAUPPAUGE_WINTV_USB_2, - EM2820_BOARD_MSI_VOX_USB_2 -}; - struct em2820_board em2820_boards[] = { + [EM2800_BOARD_UNKNOWN] = { + .name = "Unknown EM2800 video grabber", + .is_em2800 = 1, + .vchannels = 2, + .norm = VIDEO_MODE_PAL, + .tda9887_conf = TDA9887_PRESENT, + .has_tuner = 1, + .decoder = EM2820_SAA7113, + .input = {{ + .type = EM2820_VMUX_COMPOSITE1, + .vmux = 0, + .amux = 1, + },{ + .type = EM2820_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, + [EM2820_BOARD_UNKNOWN] = { + .name = "Unknown EM2820/2840 video grabber", + .is_em2800 = 0, + .vchannels = 2, + .norm = VIDEO_MODE_PAL, + .tda9887_conf = TDA9887_PRESENT, + .has_tuner = 1, + .decoder = EM2820_SAA7113, + .input = {{ + .type = EM2820_VMUX_COMPOSITE1, + .vmux = 0, + .amux = 1, + },{ + .type = EM2820_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, [EM2820_BOARD_TERRATEC_CINERGY_250] = { .name = "Terratec Cinergy 250 USB", .vchannels = 3, @@ -129,17 +158,88 @@ struct em2820_board em2820_boards[] = { .amux = 1, }}, }, - { } /* Terminating entry */ + [EM2800_BOARD_TERRATEC_CINERGY_200] = { + .name = "Terratec Cinergy 200 USB", + .chip_id = 0x4, + .is_em2800 = 1, + .vchannels = 3, + .norm = VIDEO_MODE_PAL, + .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .tda9887_conf = TDA9887_PRESENT, + .has_tuner = 1, + .decoder = EM2820_SAA7113, + .input = {{ + .type = EM2820_VMUX_TELEVISION, + .vmux = 2, + .amux = 0, + },{ + .type = EM2820_VMUX_COMPOSITE1, + .vmux = 0, + .amux = 1, + },{ + .type = EM2820_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, + [EM2800_BOARD_LEADTEK_WINFAST_USBII] = { + .name = "Leadtek Winfast USB II", + .chip_id = 0x2, + .is_em2800 = 1, + .vchannels = 3, + .norm = VIDEO_MODE_PAL, + .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .tda9887_conf = TDA9887_PRESENT, + .has_tuner = 1, + .decoder = EM2820_SAA7113, + .input = {{ + .type = EM2820_VMUX_TELEVISION, + .vmux = 2, + .amux = 0, + },{ + .type = EM2820_VMUX_COMPOSITE1, + .vmux = 0, + .amux = 1, + },{ + .type = EM2820_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, + [EM2800_BOARD_KWORLD_USB2800] = { + .name = "Kworld USB2800", + .chip_id = 0x7, + .is_em2800 = 1, + .vchannels = 3, + .norm = VIDEO_MODE_PAL, + .tuner_type = TUNER_PHILIPS_ATSC, + .tda9887_conf = TDA9887_PRESENT, + .has_tuner = 1, + .decoder = EM2820_SAA7113, + .input = {{ + .type = EM2820_VMUX_TELEVISION, + .vmux = 2, + .amux = 0, + },{ + .type = EM2820_VMUX_COMPOSITE1, + .vmux = 0, + .amux = 1, + },{ + .type = EM2820_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, }; +const unsigned int em2820_bcount = ARRAY_SIZE(em2820_boards); /* table of devices that work with this driver */ struct usb_device_id em2820_id_table [] = { - /* Terratec Cinerhy 200 USB: em2800 nor supported, at the moment */ - /* { USB_DEVICE(0xeb1a, 0x2800), .driver_info = EM2800_BOARD_TERRATEC_CINERGY_200 }, */ + { USB_DEVICE(0xeb1a, 0x2800), .driver_info = EM2800_BOARD_UNKNOWN }, + { USB_DEVICE(0xeb1a, 0x2820), .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0x0ccd, 0x0036), .driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 }, { USB_DEVICE(0x2304, 0x0208), .driver_info = EM2820_BOARD_PINNACLE_USB_2 }, { USB_DEVICE(0x2040, 0x4200), .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, - { USB_DEVICE(0xeb1a, 0x2820), .driver_info = EM2820_BOARD_MSI_VOX_USB_2 }, { }, }; @@ -163,6 +263,7 @@ void em2820_card_setup(struct em2820 *dev) } EXPORT_SYMBOL(em2820_boards); +EXPORT_SYMBOL(em2820_bcount); EXPORT_SYMBOL(em2820_id_table); MODULE_DEVICE_TABLE (usb, em2820_id_table); diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index e187422f6d6..594e6d681ba 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -1,5 +1,5 @@ /* - em2820-core.c - driver for Empia EM2820/2840 USB video capture devices + em2820-core.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger Ludovico Cavedon @@ -562,6 +562,11 @@ static inline void em2820_isoc_video_copy(struct em2820 *dev, void *fieldstart, *startwrite, *startread; int linesdone, currlinedone, offset, lencopy,remain; + if(dev->frame_size != (*f)->buf.length){ + em2820_err("frame_size %i and buf.length %i are different!!!\n",dev->frame_size,(*f)->buf.length); + return; + } + if ((*f)->fieldbytesused + len > dev->field_size) len =dev->field_size - (*f)->fieldbytesused; remain = len; @@ -780,6 +785,11 @@ int em2820_set_alternate(struct em2820 *dev) dev->alt = alt; if (dev->alt == 0) { int i; + if(dev->is_em2800){ /* always use the max packet size for em2800 based devices */ + for(i=0;i< EM2820_MAX_ALT; i++) + if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->alt]) + dev->alt=i; + }else{ unsigned int min_pkt_size = dev->field_size / 137; /* FIXME: empiric magic number */ em2820_coredbg("minimum isoc packet size: %u", min_pkt_size); dev->alt = 7; @@ -788,6 +798,7 @@ int em2820_set_alternate(struct em2820 *dev) dev->alt = i; break; } + } } if (dev->alt != prev_alt) { diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 3065ddb4b36..b7360d579a8 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -1,5 +1,5 @@ /* - em2820-i2c.c - driver for Empia EM2820/2840 USB video capture devices + em2820-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger Ludovico Cavedon @@ -29,11 +29,6 @@ #include #include -/* To be moved to compat.h */ -#if !defined(I2C_HW_B_EM2820) -#define I2C_HW_B_EM2820 0x99 -#endif - #include "em2820.h" /* ----------------------------------------------------------- */ @@ -56,11 +51,132 @@ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); printk(fmt , ##args); } while (0) /* - * i2c_send_bytes() + * em2800_i2c_send_max4() + * send up to 4 bytes to the i2c device + */ +static int em2800_i2c_send_max4(struct em2820 *dev, unsigned char addr, + char *buf, int len) +{ + int ret; + int write_timeout; + unsigned char b2[6]; + BUG_ON(len < 1 || len > 4); + b2[5] = 0x80 + len - 1; + b2[4] = addr; + b2[3] = buf[0]; + if (len > 1) + b2[2] = buf[1]; + if (len > 2) + b2[1] = buf[2]; + if (len > 3) + b2[0] = buf[3]; + + ret = dev->em2820_write_regs(dev, 4 - len, &b2[4 - len], 2 + len); + if (ret != 2 + len) { + em2820_warn("writting to i2c device failed (error=%i)\n", ret); + return -EIO; + } + for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; + write_timeout -= 5) { + ret = dev->em2820_read_reg(dev, 0x05); + if (ret == 0x80 + len - 1) + return len; + mdelay(5); + } + em2820_warn("i2c write timed out\n"); + return -EIO; +} + +/* + * em2800_i2c_send_bytes() + */ +static int em2800_i2c_send_bytes(void *data, unsigned char addr, char *buf, + short len) +{ + char *bufPtr = buf; + int ret; + int wrcount = 0; + int count; + int maxLen = 4; + struct em2820 *dev = (struct em2820 *)data; + while (len > 0) { + count = (len > maxLen) ? maxLen : len; + ret = em2800_i2c_send_max4(dev, addr, bufPtr, count); + if (ret > 0) { + len -= count; + bufPtr += count; + wrcount += count; + } else + return (ret < 0) ? ret : -EFAULT; + } + return wrcount; +} + +/* + * em2800_i2c_check_for_device() + * check if there is a i2c_device at the supplied address + */ +static int em2800_i2c_check_for_device(struct em2820 *dev, unsigned char addr) +{ + char msg; + int ret; + int write_timeout; + msg = addr; + ret = dev->em2820_write_regs(dev, 0x04, &msg, 1); + if (ret < 0) { + em2820_warn("setting i2c device address failed (error=%i)\n", + ret); + return ret; + } + msg = 0x84; + ret = dev->em2820_write_regs(dev, 0x05, &msg, 1); + if (ret < 0) { + em2820_warn("preparing i2c read failed (error=%i)\n", ret); + return ret; + } + for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; + write_timeout -= 5) { + unsigned msg = dev->em2820_read_reg(dev, 0x5); + if (msg == 0x94) + return -ENODEV; + else if (msg == 0x84) + return 0; + mdelay(5); + } + return -ENODEV; +} + +/* + * em2800_i2c_recv_bytes() + * read from the i2c device + */ +static int em2800_i2c_recv_bytes(struct em2820 *dev, unsigned char addr, + char *buf, int len) +{ + int ret; + /* check for the device and set i2c read address */ + ret = em2800_i2c_check_for_device(dev, addr); + if (ret) { + em2820_warn + ("preparing read at i2c address 0x%x failed (error=%i)\n", + addr, ret); + return ret; + } + ret = dev->em2820_read_reg_req_len(dev, 0x0, 0x3, buf, len); + if (ret < 0) { + em2820_warn("reading from i2c device at 0x%x failed (error=%i)", + addr, ret); + return ret; + } + return ret; +} + +/* + * em2820_i2c_send_bytes() * untested for more than 4 bytes */ -static int i2c_send_bytes(void *data, unsigned char addr, char *buf, short len, - int stop) +static int em2820_i2c_send_bytes(void *data, unsigned char addr, char *buf, + short len, int stop) { int wrcount = 0; struct em2820 *dev = (struct em2820 *)data; @@ -71,11 +187,11 @@ static int i2c_send_bytes(void *data, unsigned char addr, char *buf, short len, } /* - * i2c_recv_byte() + * em2820_i2c_recv_bytes() * read a byte from the i2c device */ -static int i2c_recv_bytes(struct em2820 *dev, unsigned char addr, char *buf, - int len) +static int em2820_i2c_recv_bytes(struct em2820 *dev, unsigned char addr, + char *buf, int len) { int ret; ret = dev->em2820_read_reg_req_len(dev, 2, addr, buf, len); @@ -89,10 +205,10 @@ static int i2c_recv_bytes(struct em2820 *dev, unsigned char addr, char *buf, } /* - * i2c_check_for_device() + * em2820_i2c_check_for_device() * check if there is a i2c_device at the supplied address */ -static int i2c_check_for_device(struct em2820 *dev, unsigned char addr) +static int em2820_i2c_check_for_device(struct em2820 *dev, unsigned char addr) { char msg; int ret; @@ -126,18 +242,25 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap, (msgs[i].flags & I2C_M_RD) ? "read" : "write", i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); if (!msgs[i].len) { /* no len: check only for device presence */ - rc = i2c_check_for_device(dev, addr); + if (dev->is_em2800) + rc = em2800_i2c_check_for_device(dev, addr); + else + rc = em2820_i2c_check_for_device(dev, addr); if (rc < 0) { dprintk2(" no device\n"); return rc; } - } - if (msgs[i].flags & I2C_M_RD) { + } else if (msgs[i].flags & I2C_M_RD) { /* read bytes */ - - rc = i2c_recv_bytes(dev, addr, msgs[i].buf, - msgs[i].len); + if (dev->is_em2800) + rc = em2800_i2c_recv_bytes(dev, addr, + msgs[i].buf, + msgs[i].len); + else + rc = em2820_i2c_recv_bytes(dev, addr, + msgs[i].buf, + msgs[i].len); if (i2c_debug) { for (byte = 0; byte < msgs[i].len; byte++) { printk(" %02x", msgs[i].buf[byte]); @@ -149,8 +272,15 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap, for (byte = 0; byte < msgs[i].len; byte++) printk(" %02x", msgs[i].buf[byte]); } - rc = i2c_send_bytes(dev, addr, msgs[i].buf, msgs[i].len, - i == num - 1); + if (dev->is_em2800) + rc = em2800_i2c_send_bytes(dev, addr, + msgs[i].buf, + msgs[i].len); + else + rc = em2820_i2c_send_bytes(dev, addr, + msgs[i].buf, + msgs[i].len, + i == num - 1); if (rc < 0) goto err; } @@ -171,6 +301,12 @@ static int em2820_i2c_eeprom(struct em2820 *dev, unsigned char *eedata, int len) int i, err, size = len, block; dev->i2c_client.addr = 0xa0 >> 1; + + /* Check if board has eeprom */ + err = i2c_master_recv(&dev->i2c_client, &buf, 0); + if (err < 0) + return -1; + buf = 0; if (1 != (err = i2c_master_send(&dev->i2c_client, &buf, 1))) { printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n", @@ -389,7 +525,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c) rc = i2c_master_recv(c, &buf, 0); if (rc < 0) continue; - printk(KERN_INFO "%s: found device @ 0x%x [%s]", name, + printk(KERN_INFO "%s: found i2c device @ 0x%x [%s]\n", name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); } } diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 7e4114ea15f..d3a959b9ee6 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1,5 +1,5 @@ /* - em2820-video.c - driver for Empia EM2820/2840 USB video capture devices + em2820-video.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger Ludovico Cavedon @@ -50,6 +50,11 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); +static unsigned int card[] = {[0 ... (EM2820_MAXBOARDS - 1)] = UNSET }; + +module_param_array(card, int, NULL, 0444); +MODULE_PARM_DESC(card,"card type"); + static int tuner = -1; module_param(tuner, int, 0444); MODULE_PARM_DESC(tuner, "tuner type"); @@ -1081,7 +1086,7 @@ static int em2820_do_ioctl(struct inode *inode, struct file *filp, struct v4l2_cropcap *cc = arg; if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return EINVAL; + return -EINVAL; cc->bounds.left = 0; cc->bounds.top = 0; cc->bounds.width = dev->width; @@ -1520,21 +1525,12 @@ static struct file_operations em2820_v4l_fops = { static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, int minor, int model) { - struct em2820 *dev; + struct em2820 *dev = *devhandle; int retval = -ENOMEM; int errCode, i; unsigned int maxh, maxw; struct usb_interface *uif; - /* allocate memory for our device state and initialize it */ - dev = kmalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) { - em2820_err(DRIVER_NAME ": out of memory!\n"); - return -ENOMEM; - } - memset(dev, 0x00, sizeof(*dev)); - - snprintf(dev->name, 29, "em2820 #%d", minor); dev->udev = udev; dev->model = model; init_MUTEX(&dev->lock); @@ -1545,6 +1541,7 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, dev->em2820_read_reg_req_len = em2820_read_reg_req_len; dev->em2820_write_regs_req = em2820_write_regs_req; dev->em2820_read_reg_req = em2820_read_reg_req; + dev->is_em2800 = em2820_boards[model].is_em2800; dev->has_tuner = em2820_boards[model].has_tuner; dev->has_msp34xx = em2820_boards[model].has_msp34xx; dev->tda9887_conf = em2820_boards[model].tda9887_conf; @@ -1595,7 +1592,7 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, /* compute alternate max packet sizes */ uif = dev->udev->actconfig->interface[0]; dev->alt_max_pkt_size[0] = 0; - for (i = 1; i <= EM2820_MAX_ALT; i++) { + for (i = 1; i <= EM2820_MAX_ALT && i < uif->num_altsetting ; i++) { u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc. wMaxPacketSize); @@ -1688,7 +1685,6 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, em2820_info("V4L2 device registered as /dev/video%d\n", dev->vdev->minor); - *devhandle = dev; return 0; } @@ -1703,27 +1699,68 @@ static int em2820_usb_probe(struct usb_interface *interface, struct usb_device *udev; struct em2820 *dev = NULL; int retval = -ENODEV; + int model,i,nr; udev = usb_get_dev(interface_to_usbdev(interface)); endpoint = &interface->cur_altsetting->endpoint[1].desc; + /* Don't register audio interfaces */ + if (interface->altsetting[1].desc.bInterfaceClass == USB_CLASS_AUDIO) + return -ENODEV; + /* check if the the device has the iso in endpoint at the correct place */ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) { -/* em2820_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n"); */ + em2820_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n"); return -ENODEV; } if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { -/* em2820_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n"); */ + em2820_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n"); return -ENODEV; } + model=id->driver_info; + nr=interface->minor; + + if (nr>EM2820_MAXBOARDS) { + printk ("em2820: Supports only %i em28xx boards.\n",EM2820_MAXBOARDS); + return -ENOMEM; + } + + /* allocate memory for our device state and initialize it */ + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { + em2820_err(DRIVER_NAME ": out of memory!\n"); + return -ENOMEM; + } + memset(dev, 0, sizeof(*dev)); + + snprintf(dev->name, 29, "em2820 #%d", nr); + + if ((card[nr]>=0)&&(card[nr] insmod option to\n" + "%s: workaround that. Redirect complaints to the vendor of\n" + "%s: the TV card. Best regards,\n" + "%s: -- tux\n", + dev->name,dev->name,dev->name,dev->name,dev->name); + printk("%s: Here is a list of valid choices for the card= insmod option:\n", + dev->name); + for (i = 0; i < em2820_bcount; i++) { + printk("%s: card=%d -> %s\n", + dev->name, i, em2820_boards[i].name); + } + } + /* allocate device struct */ - retval = em2820_init_dev(&dev, udev, interface->minor, id->driver_info); + retval = em2820_init_dev(&dev, udev, nr, model); if (retval) return retval; - em2820_info("Found %s\n", em2820_boards[id->driver_info].name); + em2820_info("Found %s\n", em2820_boards[model].name); /* save our data pointer in this interface device */ usb_set_intfdata(interface, dev); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 7779121a3de..4115938a173 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -1,5 +1,5 @@ /* - em2820-cards.c - driver for Empia EM2820/2840 USB video capture devices + em2820-cards.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger Ludovico Cavedon @@ -28,6 +28,23 @@ #include #include +/* Boards supported by driver */ + +#define EM2800_BOARD_UNKNOWN 0 +#define EM2820_BOARD_UNKNOWN 1 +#define EM2820_BOARD_TERRATEC_CINERGY_250 2 +#define EM2820_BOARD_PINNACLE_USB_2 3 +#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 4 +#define EM2820_BOARD_MSI_VOX_USB_2 5 +#define EM2800_BOARD_TERRATEC_CINERGY_200 6 +#define EM2800_BOARD_LEADTEK_WINFAST_USBII 7 +#define EM2800_BOARD_KWORLD_USB2800 8 + +#define UNSET -1 + +/* maximum number of em28xx boards */ +#define EM2820_MAXBOARDS 1 /*FIXME: should be bigger */ + /* maximum number of frames that can be queued */ #define EM2820_NUM_FRAMES 5 /* number of frames that get used for v4l2_read() */ @@ -79,6 +96,9 @@ /* time to wait when stopping the isoc transfer */ #define EM2820_URB_TIMEOUT msecs_to_jiffies(EM2820_NUM_BUFS * EM2820_NUM_PACKETS) +/* time in msecs to wait for i2c writes to finish */ +#define EM2800_I2C_WRITE_TIMEOUT 20 + /* the various frame states */ enum em2820_frame_state { F_UNUSED = 0, @@ -145,12 +165,13 @@ enum em2820_decoder { struct em2820_board { char *name; - + unsigned char chip_id; int vchannels; int norm; int tuner_type; /* i2c flags */ + unsigned int is_em2800; unsigned int tda9887_conf; unsigned int has_tuner:1; @@ -195,6 +216,7 @@ struct em2820 { /* generic device properties */ char name[30]; /* name (including minor) of the device */ int model; /* index in the device_data struct */ + unsigned int is_em2800; int video_inputs; /* number of video inputs */ unsigned int has_tuner:1; unsigned int has_msp34xx:1; @@ -304,11 +326,14 @@ void em2820_uninit_isoc(struct em2820 *dev); int em2820_set_alternate(struct em2820 *dev); /* Provided by em2820-cards.c */ +extern int em2800_variant_detect(struct usb_device* udev,int model); extern void em2820_card_setup(struct em2820 *dev); extern struct em2820_board em2820_boards[]; extern struct usb_device_id em2820_id_table[]; +extern const unsigned int em2820_bcount; /* em2820 registers */ +#define CHIPID_REG 0x0a #define USBSUSP_REG 0x0c /* */ #define AUDIOSRC_REG 0x0e -- cgit v1.2.3 From 2a2d857c005399fdf4e0913cb43cca9beb9941a7 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:37:24 -0800 Subject: [PATCH] v4l: 768: don t bother gerd with bttv cards patches - Don't bother Gerd with bttv-cards patches. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bttv-cards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 77f0ff8a4e4..2b19de386dc 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -2824,7 +2824,7 @@ void __devinit bttv_idcard(struct bttv *btv) btv->c.nr, btv->cardid & 0xffff, (btv->cardid >> 16) & 0xffff); printk(KERN_DEBUG "please mail id, board name and " - "the correct card= insmod option to kraxel@bytesex.org\n"); + "the correct card= insmod option to video4linux-list@redhat.com\n"); } } -- cgit v1.2.3 From 0edeea4f917ab6f0b806c496822267cef2218500 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 8 Nov 2005 21:37:25 -0800 Subject: [PATCH] v4l: 771: the wm8775 is a wolfson microelectronics 24 bit 96khz adc with 4 - Support for Wolfson Microelectronics wm8775 audio processor Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/wm8775.c | 253 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 drivers/media/video/wm8775.c diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c new file mode 100644 index 00000000000..8200f3dad0c --- /dev/null +++ b/drivers/media/video/wm8775.c @@ -0,0 +1,253 @@ +/* + * wm8775 - driver version 0.0.1 + * + * Copyright (C) 2004 Ulf Eklund + * + * Based on saa7115 driver + * + * 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 option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_DESCRIPTION("wm8775 driver"); +MODULE_AUTHOR("Ulf Eklund"); +MODULE_LICENSE("GPL"); + +#define wm8775_err(fmt, arg...) do { \ + printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \ + i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) +#define wm8775_info(fmt, arg...) do { \ + printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \ + i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) + + +static unsigned short normal_i2c[] = { 0x36 >> 1, I2C_CLIENT_END }; + + +I2C_CLIENT_INSMOD; + +/* ----------------------------------------------------------------------- */ + +enum { + R7 = 7, R11 = 11, + R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R23 = 23, + TOT_REGS +}; + +struct wm8775_state { + u8 input; /* Last selected input (0-0xf) */ + u8 muted; +}; + +static int wm8775_write(struct i2c_client *client, int reg, u16 val) +{ + int i; + + if (reg < 0 || reg >= TOT_REGS) { + wm8775_err("Invalid register R%d\n", reg); + return -1; + } + + for (i = 0; i < 3; i++) { + if (i2c_smbus_write_byte_data(client, (reg << 1) | + (val >> 8), val & 0xff) == 0) { + return 0; + } + } + wm8775_err("I2C: cannot write %03x to register R%d\n", val, reg); + return -1; +} + +static int wm8775_command(struct i2c_client *client, unsigned int cmd, + void *arg) +{ + struct wm8775_state *state = i2c_get_clientdata(client); + int *input = arg; + + switch (cmd) { + case AUDC_SET_INPUT: + wm8775_write(client, R21, 0x0c0); + wm8775_write(client, R14, 0x1d4); + wm8775_write(client, R15, 0x1d4); + + if (*input == AUDIO_RADIO) { + wm8775_write(client, R21, 0x108); + state->input = 8; + state->muted = 0; + break; + } + if (*input == AUDIO_MUTE) { + state->muted = 1; + break; + } + if (*input == AUDIO_UNMUTE) { + wm8775_write(client, R21, 0x100 + state->input); + state->muted = 0; + break; + } + /* All other inputs... */ + wm8775_write(client, R21, 0x102); + state->input = 2; + state->muted = 0; + break; + + + case VIDIOCSFREQ: + /* If I remove this, then it can happen that I have no + sound the first time I tune from static to a valid channel. + It's difficult to reproduce and is almost certainly related + to the zero cross detect circuit. */ + wm8775_write(client, R21, 0x0c0); + wm8775_write(client, R14, 0x1d4); + wm8775_write(client, R15, 0x1d4); + wm8775_write(client, R21, 0x100 + state->input); + break; + + default: + return -EINVAL; + } + return 0; +} + +/* ----------------------------------------------------------------------- */ + +/* i2c implementation */ + +/* + * Generic i2c probe + * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' + */ + +static struct i2c_driver i2c_driver; + +static int wm8775_attach(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + struct wm8775_state *state; + + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return 0; + + client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (client == 0) + return -ENOMEM; + + memset(client, 0, sizeof(struct i2c_client)); + client->addr = address; + client->adapter = adapter; + client->driver = &i2c_driver; + client->flags = I2C_CLIENT_ALLOW_USE; + snprintf(client->name, sizeof(client->name) - 1, "wm8775"); + + wm8775_info("chip found @ 0x%x (%s)\n", address << 1, adapter->name); + + state = kmalloc(sizeof(struct wm8775_state), GFP_KERNEL); + if (state == NULL) { + kfree(client); + return -ENOMEM; + } + state->input = 2; + state->muted = 0; + i2c_set_clientdata(client, state); + + /* initialize wm8775 */ + wm8775_write(client, R23, 0x000); /* RESET */ + wm8775_write(client, R7, 0x000); /* Disable zero cross detect timeout */ + wm8775_write(client, R11, 0x021); /* Left justified, 24-bit mode */ + wm8775_write(client, R12, 0x102); /* Master mode, clock ratio 256fs */ + wm8775_write(client, R13, 0x000); /* Powered up */ + wm8775_write(client, R14, 0x1d4); /* ADC gain +2.5dB, enable zero cross */ + wm8775_write(client, R15, 0x1d4); /* ADC gain +2.5dB, enable zero cross */ + wm8775_write(client, R16, 0x1bf); /* ALC Stereo, ALC target level -1dB FS */ + /* max gain +8dB */ + wm8775_write(client, R17, 0x185); /* Enable gain control, use zero cross */ + /* detection, ALC hold time 42.6 ms */ + wm8775_write(client, R18, 0x0a2); /* ALC gain ramp up delay 34 s, */ + /* ALC gain ramp down delay 33 ms */ + wm8775_write(client, R19, 0x005); /* Enable noise gate, threshold -72dBfs */ + wm8775_write(client, R20, 0x07a); /* Transient window 4ms, lower PGA gain */ + /* limit -1dB */ + wm8775_write(client, R21, 0x102); /* LRBOTH = 1, use input 2. */ + i2c_attach_client(client); + + return 0; +} + +static int wm8775_probe(struct i2c_adapter *adapter) +{ +#ifdef I2C_CLASS_TV_ANALOG + if (adapter->class & I2C_CLASS_TV_ANALOG) + return i2c_probe(adapter, &addr_data, wm8775_attach); +#else + switch (adapter->id) { + case I2C_HW_B_BT848: + return i2c_probe(adapter, &addr_data, tda9887_attach); + } +#endif /* I2C_CLASS_TV_ANALOG */ + + return 0; +} + +static int wm8775_detach(struct i2c_client *client) +{ + int err; + + err = i2c_detach_client(client); + if (err) { + return err; + } + kfree(client); + + return 0; +} + +/* ----------------------------------------------------------------------- */ + +/* i2c implementation */ +static struct i2c_driver i2c_driver = { + .name = "wm8775", + + .id = I2C_DRIVERID_WM8775, + .flags = I2C_DF_NOTIFY, + + .attach_adapter = wm8775_probe, + .detach_client = wm8775_detach, + .command = wm8775_command, + .owner = THIS_MODULE, +}; + + +static int __init wm8775_init_module(void) +{ + return i2c_add_driver(&i2c_driver); +} + +static void __exit wm8775_cleanup_module(void) +{ + i2c_del_driver(&i2c_driver); +} + +module_init(wm8775_init_module); +module_exit(wm8775_cleanup_module); -- cgit v1.2.3 From 47028d62f9aef032ed4e9645ea0c9eb451312dd9 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:37:26 -0800 Subject: [PATCH] v4l: 773: be sure to enable video buf dvb in kernel build - Be sure to enable video-buf-dvb in kernel build. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/Makefile | 3 +++ drivers/media/video/saa7134/Makefile | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile index 107e48645e3..be1dc66e065 100644 --- a/drivers/media/video/cx88/Makefile +++ b/drivers/media/video/cx88/Makefile @@ -9,6 +9,9 @@ obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o EXTRA_CFLAGS += -I$(src)/.. EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/frontends +ifneq ($(CONFIG_VIDEO_BUF_DVB),n) + EXTRA_CFLAGS += -DHAVE_VIDEO_BUF_DVB=1 +endif ifneq ($(CONFIG_DVB_CX22702),n) EXTRA_CFLAGS += -DHAVE_CX22702=1 endif diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile index b778ffd94e6..1418f9f88d2 100644 --- a/drivers/media/video/saa7134/Makefile +++ b/drivers/media/video/saa7134/Makefile @@ -9,6 +9,9 @@ obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o EXTRA_CFLAGS += -I$(src)/.. EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/frontends +ifneq ($(CONFIG_VIDEO_BUF_DVB),n) + EXTRA_CFLAGS += -DHAVE_VIDEO_BUF_DVB=1 +endif ifneq ($(CONFIG_DVB_MT352),n) EXTRA_CFLAGS += -DHAVE_MT352=1 endif -- cgit v1.2.3 From 67081a46116e6d9a47f4621ccd63b2fdcd1f45f1 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:37:27 -0800 Subject: [PATCH] v4l: 775: fix build warnings - Fix build warnings Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 52fc4425b71..93038c32a03 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include -- cgit v1.2.3 From 76bc3a3933de50559fdd4081f26867f1d25cd5a6 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:37:27 -0800 Subject: [PATCH] v4l: 776: added card 75 avermedia avertvhd mce a180 - Added card 75 AVerMedia AVerTVHD MCE A180 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 24 ++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134.h | 1 + 3 files changed, 26 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 57439d08157..3bcfd88920d 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -73,3 +73,4 @@ 72 -> RTD Embedded Technologies VFG7350 [1435:7350] 73 -> RTD Embedded Technologies VFG7330 [1435:7330] 74 -> LifeView FlyTV Platinum Mini2 [14c0:1212] + 75 -> AVerMedia AVerTVHD MCE A180 [1461:1044] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 3a4c59e7ca0..e6e50c0a80c 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2350,6 +2350,24 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE2, }}, }, + [SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180] = { + /* FIXME: uses Alps Electric TDHU2, containing ATI NXT2004 ATSC Decoder */ + .name = "AVerMedia AVerTVHD MCE A180", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = {{ + .name = name_comp1, + .vmux = 3, + .amux = LINE2, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + }}, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -2755,6 +2773,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x1435, .subdevice = 0x7330, .driver_data = SAA7134_BOARD_RTD_VFG7330, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, + .subdevice = 0x1044, + .driver_data = SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180, },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 93038c32a03..473c5dbb9b5 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -201,6 +201,7 @@ struct saa7134_format { #define SAA7134_BOARD_RTD_VFG7350 72 #define SAA7134_BOARD_RTD_VFG7330 73 #define SAA7134_BOARD_FLYTVPLATINUM_MINI2 74 +#define SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180 75 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From 994914ea7aecea3d8bc30e6283dacea1f157353c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:37:28 -0800 Subject: [PATCH] v4l: 777: updated script to function in new tree layout - Whitespace cleanups Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/README.cx88 | 2 +- Documentation/video4linux/README.saa7134 | 2 +- Documentation/video4linux/bttv/Sound-FAQ | 6 +++--- Documentation/video4linux/bttv/Tuners | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Documentation/video4linux/README.cx88 b/Documentation/video4linux/README.cx88 index 897ab834839..0b93455bbc1 100644 --- a/Documentation/video4linux/README.cx88 +++ b/Documentation/video4linux/README.cx88 @@ -65,5 +65,5 @@ Have fun, Gerd --- +-- Gerd Knorr [SuSE Labs] diff --git a/Documentation/video4linux/README.saa7134 b/Documentation/video4linux/README.saa7134 index 1f788e498ef..b911f087187 100644 --- a/Documentation/video4linux/README.saa7134 +++ b/Documentation/video4linux/README.saa7134 @@ -78,5 +78,5 @@ Have fun, Gerd --- +-- Gerd Knorr [SuSE Labs] diff --git a/Documentation/video4linux/bttv/Sound-FAQ b/Documentation/video4linux/bttv/Sound-FAQ index b8c9c2605ce..5c982249203 100644 --- a/Documentation/video4linux/bttv/Sound-FAQ +++ b/Documentation/video4linux/bttv/Sound-FAQ @@ -129,8 +129,8 @@ tuner_type - same as tuner= insmod option module loaded to work properly. has_radio - whenever this TV card has a radio tuner. no_msp34xx - "1" disables loading of msp3400.o module -no_tda9875 - "1" disables loading of tda9875.o module -needs_tvaudio - set to "1" to load tvaudio.o module +no_tda9875 - "1" disables loading of tda9875.o module +needs_tvaudio - set to "1" to load tvaudio.o module If some config item is specified both from the tvcards array and as insmod option, the insmod option takes precedence. @@ -144,5 +144,5 @@ Good luck, PS: If you have a new working entry, mail it to me. --- +-- Gerd Knorr diff --git a/Documentation/video4linux/bttv/Tuners b/Documentation/video4linux/bttv/Tuners index d18fbc70c0e..0a371d34954 100644 --- a/Documentation/video4linux/bttv/Tuners +++ b/Documentation/video4linux/bttv/Tuners @@ -21,7 +21,7 @@ SAMSUNG Tuner identification: (e.g. TCPM9091PD27) J= NTSC-Japan L= Secam LL M= BG+I+DK - N= NTSC + N= NTSC Q= BG+I+DK+LL [89]: ? [125]: @@ -96,7 +96,7 @@ LG Innotek Tuner: TADC-H002F: NTSC (L,175/410?; 2-B, C-W+11, W+12-69) TADC-M201D: PAL D/K+B/G+I (L,143/425) (sound control at I2C address 0xc8) TADC-T003F: NTSC Taiwan (L,175/410?; 2-B, C-W+11, W+12-69) - Suffix: + Suffix: P= Standard phono female socket D= IEC female socket F= F-connector -- cgit v1.2.3 From 55b8b2d173adea54a9e8407f26630c19274fa0b6 Mon Sep 17 00:00:00 2001 From: Paul Vriens Date: Tue, 8 Nov 2005 21:37:29 -0800 Subject: [PATCH] v4l: 780: fixed typo in module param description - Fixed typo in module param description Signed-off-by: Paul Vriens Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 594e6d681ba..f5e22154a97 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -53,7 +53,7 @@ MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); unsigned int isoc_debug = 0; module_param(isoc_debug,int,0644); -MODULE_PARM_DESC(core_debug,"enable debug messages [isoc transfers]"); +MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]"); #define em2820_isocdbg(fmt, arg...) do {\ if (isoc_debug) \ -- cgit v1.2.3 From 2f4710b1b1c62da3050c4eac08a5f08227e0e0f0 Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Tue, 8 Nov 2005 21:37:30 -0800 Subject: [PATCH] v4l: 782: ir-kbd-i2c.c updates - fixed probe function - em2820 remote layout - disabled em2820 pinnacle ir support - whitespace cleanups Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/ir-kbd-i2c.c | 222 ++++++++++++++++++++++----------------- 1 file changed, 126 insertions(+), 96 deletions(-) diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 061dda10721..fbb78b659a8 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -43,100 +43,100 @@ #include static IR_KEYTAB_TYPE ir_codes_em2820[IR_KEYTAB_SIZE] = { - [ 0 ] = KEY_CHANNEL, - [ 1 ] = KEY_SELECT, - [ 2 ] = KEY_MUTE, - [ 3 ] = KEY_POWER, - [ 4 ] = KEY_KP1, - [ 5 ] = KEY_KP2, - [ 6 ] = KEY_KP3, - [ 7 ] = KEY_CHANNELUP, - [ 8 ] = KEY_KP4, - [ 9 ] = KEY_KP5, - [ 10 ] = KEY_KP6, - - [ 11 ] = KEY_CHANNELDOWN, - [ 12 ] = KEY_KP7, - [ 13 ] = KEY_KP8, - [ 14 ] = KEY_KP9, - [ 15 ] = KEY_VOLUMEUP, - [ 16 ] = KEY_KP0, - [ 17 ] = KEY_MENU, - [ 18 ] = KEY_PRINT, - - [ 19 ] = KEY_VOLUMEDOWN, - [ 21 ] = KEY_PAUSE, - [ 23 ] = KEY_RECORD, - [ 24 ] = KEY_REWIND, - [ 25 ] = KEY_PLAY, - [ 27 ] = KEY_BACKSPACE, - [ 29 ] = KEY_STOP, - [ 31 ] = KEY_ZOOM, + [ 0x00 ] = KEY_CHANNEL, + [ 0x01 ] = KEY_SELECT, + [ 0x02 ] = KEY_MUTE, + [ 0x03 ] = KEY_POWER, + [ 0x04 ] = KEY_KP1, + [ 0x05 ] = KEY_KP2, + [ 0x06 ] = KEY_KP3, + [ 0x07 ] = KEY_CHANNELUP, + [ 0x08 ] = KEY_KP4, + [ 0x09 ] = KEY_KP5, + [ 0x0a ] = KEY_KP6, + + [ 0x0b ] = KEY_CHANNELDOWN, + [ 0x0c ] = KEY_KP7, + [ 0x0d ] = KEY_KP8, + [ 0x0e ] = KEY_KP9, + [ 0x0f ] = KEY_VOLUMEUP, + [ 0x10 ] = KEY_KP0, + [ 0x11 ] = KEY_MENU, + [ 0x12 ] = KEY_PRINT, + + [ 0x13 ] = KEY_VOLUMEDOWN, + [ 0x15 ] = KEY_PAUSE, + [ 0x17 ] = KEY_RECORD, + [ 0x18 ] = KEY_REWIND, + [ 0x19 ] = KEY_PLAY, + [ 0x1b ] = KEY_BACKSPACE, + [ 0x1d ] = KEY_STOP, + [ 0x40 ] = KEY_ZOOM, }; /* Mark Phalan */ static IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE] = { - [ 0 ] = KEY_KP0, - [ 1 ] = KEY_KP1, - [ 2 ] = KEY_KP2, - [ 3 ] = KEY_KP3, - [ 4 ] = KEY_KP4, - [ 5 ] = KEY_KP5, - [ 6 ] = KEY_KP6, - [ 7 ] = KEY_KP7, - [ 8 ] = KEY_KP8, - [ 9 ] = KEY_KP9, - - [ 18 ] = KEY_POWER, - [ 16 ] = KEY_MUTE, - [ 31 ] = KEY_VOLUMEDOWN, - [ 27 ] = KEY_VOLUMEUP, - [ 26 ] = KEY_CHANNELUP, - [ 30 ] = KEY_CHANNELDOWN, - [ 14 ] = KEY_PAGEUP, - [ 29 ] = KEY_PAGEDOWN, - [ 19 ] = KEY_SOUND, - - [ 24 ] = KEY_KPPLUSMINUS, /* CH +/- */ - [ 22 ] = KEY_SUBTITLE, /* CC */ - [ 13 ] = KEY_TEXT, /* TTX */ - [ 11 ] = KEY_TV, /* AIR/CBL */ - [ 17 ] = KEY_PC, /* PC/TV */ - [ 23 ] = KEY_OK, /* CH RTN */ - [ 25 ] = KEY_MODE, /* FUNC */ - [ 12 ] = KEY_SEARCH, /* AUTOSCAN */ + [ 0x00 ] = KEY_KP0, + [ 0x01 ] = KEY_KP1, + [ 0x02 ] = KEY_KP2, + [ 0x03 ] = KEY_KP3, + [ 0x04 ] = KEY_KP4, + [ 0x05 ] = KEY_KP5, + [ 0x06 ] = KEY_KP6, + [ 0x07 ] = KEY_KP7, + [ 0x08 ] = KEY_KP8, + [ 0x09 ] = KEY_KP9, + + [ 0x12 ] = KEY_POWER, + [ 0x10 ] = KEY_MUTE, + [ 0x1f ] = KEY_VOLUMEDOWN, + [ 0x1b ] = KEY_VOLUMEUP, + [ 0x1a ] = KEY_CHANNELUP, + [ 0x1e ] = KEY_CHANNELDOWN, + [ 0x0e ] = KEY_PAGEUP, + [ 0x1d ] = KEY_PAGEDOWN, + [ 0x13 ] = KEY_SOUND, + + [ 0x18 ] = KEY_KPPLUSMINUS, /* CH +/- */ + [ 0x16 ] = KEY_SUBTITLE, /* CC */ + [ 0x0d ] = KEY_TEXT, /* TTX */ + [ 0x0b ] = KEY_TV, /* AIR/CBL */ + [ 0x11 ] = KEY_PC, /* PC/TV */ + [ 0x17 ] = KEY_OK, /* CH RTN */ + [ 0x19 ] = KEY_MODE, /* FUNC */ + [ 0x0c ] = KEY_SEARCH, /* AUTOSCAN */ /* Not sure what to do with these ones! */ - [ 15 ] = KEY_SELECT, /* SOURCE */ - [ 10 ] = KEY_KPPLUS, /* +100 */ - [ 20 ] = KEY_KPEQUAL, /* SYNC */ - [ 28 ] = KEY_MEDIA, /* PC/TV */ + [ 0x0f ] = KEY_SELECT, /* SOURCE */ + [ 0x0a ] = KEY_KPPLUS, /* +100 */ + [ 0x14 ] = KEY_KPEQUAL, /* SYNC */ + [ 0x1c ] = KEY_MEDIA, /* PC/TV */ }; static IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { - [ 0x3 ] = KEY_POWER, + [ 0x03 ] = KEY_POWER, [ 0x6f ] = KEY_MUTE, [ 0x10 ] = KEY_BACKSPACE, /* Recall */ [ 0x11 ] = KEY_KP0, - [ 0x4 ] = KEY_KP1, - [ 0x5 ] = KEY_KP2, - [ 0x6 ] = KEY_KP3, - [ 0x8 ] = KEY_KP4, - [ 0x9 ] = KEY_KP5, - [ 0xa ] = KEY_KP6, - [ 0xc ] = KEY_KP7, - [ 0xd ] = KEY_KP8, - [ 0xe ] = KEY_KP9, + [ 0x04 ] = KEY_KP1, + [ 0x05 ] = KEY_KP2, + [ 0x06 ] = KEY_KP3, + [ 0x08 ] = KEY_KP4, + [ 0x09 ] = KEY_KP5, + [ 0x0a ] = KEY_KP6, + [ 0x0c ] = KEY_KP7, + [ 0x0d ] = KEY_KP8, + [ 0x0e ] = KEY_KP9, [ 0x12 ] = KEY_KPDOT, /* 100+ */ - [ 0x7 ] = KEY_VOLUMEUP, - [ 0xb ] = KEY_VOLUMEDOWN, + [ 0x07 ] = KEY_VOLUMEUP, + [ 0x0b ] = KEY_VOLUMEDOWN, [ 0x1a ] = KEY_KPPLUS, [ 0x18 ] = KEY_KPMINUS, [ 0x15 ] = KEY_UP, [ 0x1d ] = KEY_DOWN, - [ 0xf ] = KEY_CHANNELUP, + [ 0x0f ] = KEY_CHANNELUP, [ 0x13 ] = KEY_CHANNELDOWN, [ 0x48 ] = KEY_ZOOM, @@ -174,6 +174,9 @@ module_param(debug, int, 0644); /* debug level (0,1,2) */ #define dprintk(level, fmt, arg...) if (debug >= level) \ printk(KERN_DEBUG DEVNAME ": " fmt , ## arg) +#define IR_PINNACLE_REMOTE 0x01 +#define IR_TERRATEC_REMOTE 0x02 + /* ----------------------------------------------------------------------- */ static int get_key_haup(struct IR *ir, u32 *ir_key, u32 *ir_raw) @@ -287,6 +290,7 @@ static int get_key_purpletv(struct IR *ir, u32 *ir_key, u32 *ir_raw) *ir_raw = b; return 1; } + /* ----------------------------------------------------------------------- */ static void ir_key_poll(struct IR *ir) @@ -386,24 +390,36 @@ static int ir_attach(struct i2c_adapter *adap, int addr, ir_type = IR_TYPE_RC5; ir_codes = ir_codes_rc5_tv; break; - case 0x60: - name = "em2820"; - ir->get_key = get_key_knc1; - ir->c.addr = addr>>1; - ir_type = IR_TYPE_OTHER; - ir_codes = ir_codes_em2820; - break; case 0x30: - name = "KNC One"; - ir->get_key = get_key_knc1; - ir_type = IR_TYPE_OTHER; - ir_codes = ir_codes_empty; + switch(kind){ + case IR_TERRATEC_REMOTE: + name = "Terratec IR"; + ir->get_key = get_key_knc1; + ir_type = IR_TYPE_OTHER; + ir_codes = ir_codes_em2820; + break; + default: + name = "KNC One"; + ir->get_key = get_key_knc1; + ir_type = IR_TYPE_OTHER; + ir_codes = ir_codes_em2820; + } break; + case 0x47: case 0x7a: - name = "Purple TV"; - ir->get_key = get_key_purpletv; - ir_type = IR_TYPE_OTHER; - ir_codes = ir_codes_purpletv; + switch(kind){ + case IR_PINNACLE_REMOTE: + name = "Pinnacle IR Remote"; + ir->get_key = get_key_purpletv; + ir_type = IR_TYPE_OTHER; + ir_codes = ir_codes_em2820; + break; + default: + name = "Purple TV"; + ir->get_key = get_key_purpletv; + ir_type = IR_TYPE_OTHER; + ir_codes = ir_codes_empty; + } break; default: /* shouldn't happen */ @@ -468,9 +484,11 @@ static int ir_probe(struct i2c_adapter *adap) static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1}; static const int probe_saa7134[] = { 0x7a, -1 }; - static const int probe_em2820[] = { 0x60, -1 }; + static const int probe_em2820[] = { 0x47, 0x30, -1 }; const int *probe = NULL; - struct i2c_client c; char buf; int i,rc; + int attached = 0; + + struct i2c_client c; unsigned char buf; int i,rc; switch (adap->id) { case I2C_HW_B_BT848: @@ -488,15 +506,27 @@ static int ir_probe(struct i2c_adapter *adap) memset(&c,0,sizeof(c)); c.adapter = adap; - for (i = 0; -1 != probe[i]; i++) { + for (i = 0; -1 != probe[i] && attached != 1; i++) { c.addr = probe[i]; rc = i2c_master_recv(&c,&buf,1); dprintk(1,"probe 0x%02x @ %s: %s\n", probe[i], adap->name, (1 == rc) ? "yes" : "no"); - if (1 == rc) { - ir_attach(adap,probe[i],0,0); - break; + switch(adap->id){ + case I2C_HW_B_BT848: + case I2C_HW_SAA7134: + if (1 == rc) { + ir_attach(adap,probe[i],0,0); + attached=1; + break; + } + case I2C_HW_B_EM2820: + /* windows logs are needed for fixing the pinnacle device */ + if (1 == rc && 0xff == buf){ + ir_attach(adap,probe[i],0,IR_TERRATEC_REMOTE); + attached=1; + } + break; } } return 0; -- cgit v1.2.3 From da45a2a5b96afd7188c058a55eb2917d6524c0cf Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Tue, 8 Nov 2005 21:37:31 -0800 Subject: [PATCH] v4l: 783: fixed bad em2820 remote layout values - Fixed bad em2820 remote layout values - set KNC One and Purple TV layouts back to default - added pinnacle ir remote i2c address to the i2c scanner Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-i2c.c | 1 + drivers/media/video/ir-kbd-i2c.c | 61 ++++++++++++++++----------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index b7360d579a8..a7b6f678f97 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -499,6 +499,7 @@ static struct i2c_client em2820_client_template = { static char *i2c_devs[128] = { [0x4a >> 1] = "saa7113h", [0x60 >> 1] = "remote IR sensor", + [0x8e >> 1] = "remote IR sensor", [0x86 >> 1] = "tda9887", [0x80 >> 1] = "msp34xx", [0x88 >> 1] = "msp34xx", diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index fbb78b659a8..aec710f4eff 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -43,35 +43,34 @@ #include static IR_KEYTAB_TYPE ir_codes_em2820[IR_KEYTAB_SIZE] = { - [ 0x00 ] = KEY_CHANNEL, - [ 0x01 ] = KEY_SELECT, - [ 0x02 ] = KEY_MUTE, - [ 0x03 ] = KEY_POWER, - [ 0x04 ] = KEY_KP1, - [ 0x05 ] = KEY_KP2, - [ 0x06 ] = KEY_KP3, - [ 0x07 ] = KEY_CHANNELUP, - [ 0x08 ] = KEY_KP4, - [ 0x09 ] = KEY_KP5, - [ 0x0a ] = KEY_KP6, - - [ 0x0b ] = KEY_CHANNELDOWN, - [ 0x0c ] = KEY_KP7, - [ 0x0d ] = KEY_KP8, - [ 0x0e ] = KEY_KP9, - [ 0x0f ] = KEY_VOLUMEUP, - [ 0x10 ] = KEY_KP0, - [ 0x11 ] = KEY_MENU, - [ 0x12 ] = KEY_PRINT, - - [ 0x13 ] = KEY_VOLUMEDOWN, - [ 0x15 ] = KEY_PAUSE, - [ 0x17 ] = KEY_RECORD, - [ 0x18 ] = KEY_REWIND, - [ 0x19 ] = KEY_PLAY, - [ 0x1b ] = KEY_BACKSPACE, - [ 0x1d ] = KEY_STOP, - [ 0x40 ] = KEY_ZOOM, + [ 0x01 ] = KEY_CHANNEL, + [ 0x02 ] = KEY_SELECT, + [ 0x03 ] = KEY_MUTE, + [ 0x04 ] = KEY_POWER, + [ 0x05 ] = KEY_KP1, + [ 0x06 ] = KEY_KP2, + [ 0x07 ] = KEY_KP3, + [ 0x08 ] = KEY_CHANNELUP, + [ 0x09 ] = KEY_KP4, + [ 0x0a ] = KEY_KP5, + [ 0x0b ] = KEY_KP6, + [ 0x0c ] = KEY_CHANNELDOWN, + [ 0x0d ] = KEY_KP7, + [ 0x0e ] = KEY_KP8, + [ 0x0f ] = KEY_KP9, + [ 0x10 ] = KEY_VOLUMEUP, + [ 0x11 ] = KEY_KP0, + [ 0x12 ] = KEY_MENU, + [ 0x13 ] = KEY_PRINT, + [ 0x14 ] = KEY_VOLUMEDOWN, + [ 0x16 ] = KEY_PAUSE, + [ 0x18 ] = KEY_RECORD, + [ 0x19 ] = KEY_REWIND, + [ 0x1a ] = KEY_PLAY, + [ 0x1b ] = KEY_FORWARD, + [ 0x1c ] = KEY_BACKSPACE, + [ 0x1e ] = KEY_STOP, + [ 0x40 ] = KEY_ZOOM, }; /* Mark Phalan */ @@ -402,7 +401,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr, name = "KNC One"; ir->get_key = get_key_knc1; ir_type = IR_TYPE_OTHER; - ir_codes = ir_codes_em2820; + ir_codes = ir_codes_empty; } break; case 0x47: @@ -418,7 +417,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr, name = "Purple TV"; ir->get_key = get_key_purpletv; ir_type = IR_TYPE_OTHER; - ir_codes = ir_codes_empty; + ir_codes = ir_codes_purpletv; } break; default: -- cgit v1.2.3 From d5e5265315770bda46c50ecaa64e2b9790f2064c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:32 -0800 Subject: [PATCH] v4l: 784: several improvement on i2c ir handling for em2820 - Several Improvement on I2C IR handling for em2820: - moved Pinnacle IR table (ir_codes_em2820) to em2820-input.c - IR struct renamed and moved to a header file. - New file to handle em2820-specific IR. - Some cleanups. - attach now detects I2C IR and calls em2820-specific IR code - IR compat code moved to compat.h - New header with struct IR_i2c there, to allow it to be used by board-specific input handlers. - Some improvements at em28xx board detection: - Board detection message improved to show interface and class. - Now it doesn't touch audio interfaces. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-cards.c | 3 +- drivers/media/video/em28xx/em28xx-i2c.c | 43 +++--- drivers/media/video/em28xx/em28xx-input.c | 150 +++++++++++++++++++ drivers/media/video/em28xx/em28xx-video.c | 15 +- drivers/media/video/em28xx/em28xx.h | 20 ++- drivers/media/video/ir-kbd-i2c.c | 238 +++++++++++------------------- include/media/ir-common.h | 6 +- include/media/ir-kbd-i2c.h | 22 +++ 8 files changed, 307 insertions(+), 190 deletions(-) create mode 100644 drivers/media/video/em28xx/em28xx-input.c create mode 100644 include/media/ir-kbd-i2c.h diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 91c70ebd0ea..919520f8997 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -143,7 +143,7 @@ struct em2820_board em2820_boards[] = { .tuner_type = TUNER_PHILIPS_PAL, .tda9887_conf = TDA9887_PRESENT|TDA9887_PORT1_ACTIVE|TDA9887_PORT2_ACTIVE, .has_tuner = 1, - .decoder = EM2820_SAA7114, + .decoder = EM2820_SAA7114, .input = {{ .type = EM2820_VMUX_TELEVISION, .vmux = 2, @@ -250,6 +250,7 @@ void em2820_card_setup(struct em2820 *dev) struct tveeprom tv; #ifdef CONFIG_MODULES request_module("tveeprom"); + request_module("ir-kbd-i2c"); #endif /* Call first TVeeprom */ diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index a7b6f678f97..f6bfc038777 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -26,10 +26,10 @@ #include #include #include -#include #include #include "em2820.h" +#include /* ----------------------------------------------------------- */ @@ -41,14 +41,11 @@ static unsigned int i2c_debug = 0; module_param(i2c_debug, int, 0644); MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); -#define dprintk(fmt, args...) if (i2c_debug) do {\ - printk(KERN_DEBUG "%s: %s: " fmt "\n",\ - dev->name, __FUNCTION__ , ##args); } while (0) -#define dprintk1(fmt, args...) if (i2c_debug) do{ \ - printk(KERN_DEBUG "%s: %s: " fmt, \ - dev->name, __FUNCTION__ , ##args); } while (0) -#define dprintk2(fmt, args...) if (i2c_debug) do {\ +#define dprintk1(lvl,fmt, args...) if (i2c_debug>=lvl) do {\ printk(fmt , ##args); } while (0) +#define dprintk2(lvl,fmt, args...) if (i2c_debug>=lvl) do{ \ + printk(KERN_DEBUG "%s at %s: " fmt, \ + dev->name, __FUNCTION__ , ##args); } while (0) /* * em2800_i2c_send_max4() @@ -238,7 +235,7 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap, return 0; for (i = 0; i < num; i++) { addr = msgs[i].addr << 1; - dprintk1("%s %s addr=%x len=%d:", + dprintk2(2,"%s %s addr=%x len=%d:", (msgs[i].flags & I2C_M_RD) ? "read" : "write", i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); if (!msgs[i].len) { /* no len: check only for device presence */ @@ -247,7 +244,7 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap, else rc = em2820_i2c_check_for_device(dev, addr); if (rc < 0) { - dprintk2(" no device\n"); + dprintk2(2," no device\n"); return rc; } @@ -261,14 +258,14 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap, rc = em2820_i2c_recv_bytes(dev, addr, msgs[i].buf, msgs[i].len); - if (i2c_debug) { + if (i2c_debug>=2) { for (byte = 0; byte < msgs[i].len; byte++) { printk(" %02x", msgs[i].buf[byte]); } } } else { /* write bytes */ - if (i2c_debug) { + if (i2c_debug>=2) { for (byte = 0; byte < msgs[i].len; byte++) printk(" %02x", msgs[i].buf[byte]); } @@ -284,13 +281,13 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap, if (rc < 0) goto err; } - if (i2c_debug) + if (i2c_debug>=2) printk("\n"); } return num; err: - dprintk2(" ERROR: %i\n", rc); + dprintk2(2," ERROR: %i\n", rc); return rc; } @@ -436,26 +433,34 @@ static int attach_inform(struct i2c_client *client) { struct em2820 *dev = client->adapter->algo_data; - dprintk("address %x", client->addr << 1); switch (client->addr << 1) { case 0x86: em2820_i2c_call_clients(dev, TDA9887_SET_CONFIG, &dev->tda9887_conf); break; case 0x4a: - dprintk1("attach_inform: saa7113 detected.\n"); + dprintk1(1,"attach_inform: saa7113 detected.\n"); break; case 0xa0: - dprintk1("attach_inform: eeprom detected.\n"); + dprintk1(1,"attach_inform: eeprom detected.\n"); + break; + case 0x60: + case 0x8e: + { + struct IR_i2c *ir = i2c_get_clientdata(client); + dprintk1(1,"attach_inform: IR detected (%s).\n",ir->phys); + em2820_set_ir(dev,ir); break; + } case 0x80: case 0x88: - dprintk1("attach_inform: msp34xx detected.\n"); + dprintk1(1,"attach_inform: msp34xx detected.\n"); break; case 0xb8: case 0xba: - dprintk1("attach_inform: tvp5150 detected.\n"); + dprintk1(1,"attach_inform: tvp5150 detected.\n"); break; default: + dprintk1(1,"attach inform: detected I2C address %x\n", client->addr << 1); dev->tuner_addr = client->addr; em2820_set_tuner(-1, client); } diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c new file mode 100644 index 00000000000..d6b3e15a035 --- /dev/null +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -0,0 +1,150 @@ +/* + * + * handle saa7134 IR remotes via linux kernel input layer. + * + * 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 option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "em2820.h" + +static unsigned int disable_ir = 0; +module_param(disable_ir, int, 0444); +MODULE_PARM_DESC(disable_ir,"disable infrared remote support"); + +static unsigned int ir_debug = 0; +module_param(ir_debug, int, 0644); +MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); + +#define dprintk(fmt, arg...) if (ir_debug) \ + printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg) + +/* ---------------------------------------------------------------------- */ + +static IR_KEYTAB_TYPE ir_codes_em_pinnacle[IR_KEYTAB_SIZE] = { + [ 0 ] = KEY_CHANNEL, + [ 1 ] = KEY_SELECT, + [ 2 ] = KEY_MUTE, + [ 3 ] = KEY_POWER, + [ 4 ] = KEY_KP1, + [ 5 ] = KEY_KP2, + [ 6 ] = KEY_KP3, + [ 7 ] = KEY_CHANNELUP, + [ 8 ] = KEY_KP4, + [ 9 ] = KEY_KP5, + [ 10 ] = KEY_KP6, + + [ 11 ] = KEY_CHANNELDOWN, + [ 12 ] = KEY_KP7, + [ 13 ] = KEY_KP8, + [ 14 ] = KEY_KP9, + [ 15 ] = KEY_VOLUMEUP, + [ 16 ] = KEY_KP0, + [ 17 ] = KEY_MENU, + [ 18 ] = KEY_PRINT, + + [ 19 ] = KEY_VOLUMEDOWN, + [ 21 ] = KEY_PAUSE, + [ 23 ] = KEY_RECORD, + [ 24 ] = KEY_REWIND, + [ 25 ] = KEY_PLAY, + [ 27 ] = KEY_BACKSPACE, + [ 29 ] = KEY_STOP, + [ 31 ] = KEY_ZOOM, +}; + +/* ----------------------------------------------------------------------- */ + +static int get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +{ + unsigned char buf[2]; + unsigned char code; + + /* poll IR chip */ + if (2 != i2c_master_recv(&ir->c,buf,2)) + return -EIO; + + /* Does eliminate repeated parity code */ + if (buf[1]==0xff) + return 0; + + /* avoid fast reapeating */ + if (buf[1]==ir->old) + return 0; + ir->old=buf[1]; + + /* Rearranges bits to the right order */ + code= ((buf[0]&0x01)<<5) | /* 0010 0000 */ + ((buf[0]&0x02)<<3) | /* 0001 0000 */ + ((buf[0]&0x04)<<1) | /* 0000 1000 */ + ((buf[0]&0x08)>>1) | /* 0000 0100 */ + ((buf[0]&0x10)>>3) | /* 0000 0010 */ + ((buf[0]&0x20)>>5); /* 0000 0001 */ + + dprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x)\n",code,buf[0]); + + /* return key */ + *ir_key = code; + *ir_raw = code; + return 1; +} + +/* ----------------------------------------------------------------------- */ +void em2820_set_ir(struct em2820 * dev,struct IR_i2c *ir) +{ + if (disable_ir) + return ; + + /* detect & configure */ + switch (dev->model) { + case (EM2800_BOARD_UNKNOWN): + break; + case (EM2820_BOARD_UNKNOWN): + break; + case (EM2820_BOARD_TERRATEC_CINERGY_250): + break; + case (EM2820_BOARD_PINNACLE_USB_2): + ir->ir_codes = ir_codes_em_pinnacle; + break; + case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): + ir->ir_codes = ir_codes_hauppauge_new; + ir->get_key = get_key_em_haup; + snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM2840 Hauppage)"); + break; + case (EM2820_BOARD_MSI_VOX_USB_2): + break; + case (EM2800_BOARD_TERRATEC_CINERGY_200): + break; + case (EM2800_BOARD_LEADTEK_WINFAST_USBII): + break; + case (EM2800_BOARD_KWORLD_USB2800): + break; + } +} + +/* ---------------------------------------------------------------------- + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index d3a959b9ee6..f3fc44b352b 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -28,10 +28,10 @@ #include #include #include -#include #include #include "em2820.h" +#include #define DRIVER_AUTHOR "Markus Rechberger , " \ "Ludovico Cavedon , " \ @@ -1699,15 +1699,22 @@ static int em2820_usb_probe(struct usb_interface *interface, struct usb_device *udev; struct em2820 *dev = NULL; int retval = -ENODEV; - int model,i,nr; + int model,i,nr,ifnum; udev = usb_get_dev(interface_to_usbdev(interface)); - endpoint = &interface->cur_altsetting->endpoint[1].desc; + ifnum = interface->altsetting[0].desc.bInterfaceNumber; + + em2820_err(DRIVER_NAME " new device (%04x:%04x): interface %i, class %i\n", + udev->descriptor.idVendor,udev->descriptor.idProduct, + ifnum, + interface->altsetting[0].desc.bInterfaceClass); /* Don't register audio interfaces */ - if (interface->altsetting[1].desc.bInterfaceClass == USB_CLASS_AUDIO) + if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) return -ENODEV; + endpoint = &interface->cur_altsetting->endpoint[1].desc; + /* check if the the device has the iso in endpoint at the correct place */ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) { diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 4115938a173..31b23f0db05 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -27,6 +27,7 @@ #include #include +#include /* Boards supported by driver */ @@ -53,19 +54,12 @@ /* number of buffers for isoc transfers */ #define EM2820_NUM_BUFS 5 -/* number of packets for each buffer */ -// windows requests only 40 packets .. so we better do the same -// this is what I found out for all alternate numbers there! - +/* number of packets for each buffer + windows requests only 40 packets .. so we better do the same + this is what I found out for all alternate numbers there! + */ #define EM2820_NUM_PACKETS 40 -/* packet size for each packet */ -/* no longer needed: read from endpoint descriptor */ -//#define EM2820_MAX_PACKET_SIZE 3072 //7 -//#define EM2820_MAX_PACKET_SIZE 2892 //6 -//#define EM2820_MAX_PACKET_SIZE 2580 //5 -//#define EM2820_MAX_PACKET_SIZE 1448 //2 - /* default alternate; 0 means choose the best */ #define EM2820_PINOUT 0 #define EM2820_MAX_ALT 7 @@ -292,6 +286,10 @@ void em2820_i2c_call_clients(struct em2820 *dev, unsigned int cmd, void *arg); int em2820_i2c_register(struct em2820 *dev); int em2820_i2c_unregister(struct em2820 *dev); +/* Provided by em2820-input.c */ + +void em2820_set_ir(struct em2820 * dev,struct IR_i2c *ir); + /* Provided by em2820-core.c */ void em2820_print_ioctl(char *name, unsigned int cmd); diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index aec710f4eff..8cc3f8ab2f3 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -41,101 +41,71 @@ #include #include #include - -static IR_KEYTAB_TYPE ir_codes_em2820[IR_KEYTAB_SIZE] = { - [ 0x01 ] = KEY_CHANNEL, - [ 0x02 ] = KEY_SELECT, - [ 0x03 ] = KEY_MUTE, - [ 0x04 ] = KEY_POWER, - [ 0x05 ] = KEY_KP1, - [ 0x06 ] = KEY_KP2, - [ 0x07 ] = KEY_KP3, - [ 0x08 ] = KEY_CHANNELUP, - [ 0x09 ] = KEY_KP4, - [ 0x0a ] = KEY_KP5, - [ 0x0b ] = KEY_KP6, - [ 0x0c ] = KEY_CHANNELDOWN, - [ 0x0d ] = KEY_KP7, - [ 0x0e ] = KEY_KP8, - [ 0x0f ] = KEY_KP9, - [ 0x10 ] = KEY_VOLUMEUP, - [ 0x11 ] = KEY_KP0, - [ 0x12 ] = KEY_MENU, - [ 0x13 ] = KEY_PRINT, - [ 0x14 ] = KEY_VOLUMEDOWN, - [ 0x16 ] = KEY_PAUSE, - [ 0x18 ] = KEY_RECORD, - [ 0x19 ] = KEY_REWIND, - [ 0x1a ] = KEY_PLAY, - [ 0x1b ] = KEY_FORWARD, - [ 0x1c ] = KEY_BACKSPACE, - [ 0x1e ] = KEY_STOP, - [ 0x40 ] = KEY_ZOOM, -}; +#include /* Mark Phalan */ static IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE] = { - [ 0x00 ] = KEY_KP0, - [ 0x01 ] = KEY_KP1, - [ 0x02 ] = KEY_KP2, - [ 0x03 ] = KEY_KP3, - [ 0x04 ] = KEY_KP4, - [ 0x05 ] = KEY_KP5, - [ 0x06 ] = KEY_KP6, - [ 0x07 ] = KEY_KP7, - [ 0x08 ] = KEY_KP8, - [ 0x09 ] = KEY_KP9, - - [ 0x12 ] = KEY_POWER, - [ 0x10 ] = KEY_MUTE, - [ 0x1f ] = KEY_VOLUMEDOWN, - [ 0x1b ] = KEY_VOLUMEUP, - [ 0x1a ] = KEY_CHANNELUP, - [ 0x1e ] = KEY_CHANNELDOWN, - [ 0x0e ] = KEY_PAGEUP, - [ 0x1d ] = KEY_PAGEDOWN, - [ 0x13 ] = KEY_SOUND, - - [ 0x18 ] = KEY_KPPLUSMINUS, /* CH +/- */ - [ 0x16 ] = KEY_SUBTITLE, /* CC */ - [ 0x0d ] = KEY_TEXT, /* TTX */ - [ 0x0b ] = KEY_TV, /* AIR/CBL */ - [ 0x11 ] = KEY_PC, /* PC/TV */ - [ 0x17 ] = KEY_OK, /* CH RTN */ - [ 0x19 ] = KEY_MODE, /* FUNC */ - [ 0x0c ] = KEY_SEARCH, /* AUTOSCAN */ + [ 0 ] = KEY_KP0, + [ 1 ] = KEY_KP1, + [ 2 ] = KEY_KP2, + [ 3 ] = KEY_KP3, + [ 4 ] = KEY_KP4, + [ 5 ] = KEY_KP5, + [ 6 ] = KEY_KP6, + [ 7 ] = KEY_KP7, + [ 8 ] = KEY_KP8, + [ 9 ] = KEY_KP9, + + [ 18 ] = KEY_POWER, + [ 16 ] = KEY_MUTE, + [ 31 ] = KEY_VOLUMEDOWN, + [ 27 ] = KEY_VOLUMEUP, + [ 26 ] = KEY_CHANNELUP, + [ 30 ] = KEY_CHANNELDOWN, + [ 14 ] = KEY_PAGEUP, + [ 29 ] = KEY_PAGEDOWN, + [ 19 ] = KEY_SOUND, + + [ 24 ] = KEY_KPPLUSMINUS, /* CH +/- */ + [ 22 ] = KEY_SUBTITLE, /* CC */ + [ 13 ] = KEY_TEXT, /* TTX */ + [ 11 ] = KEY_TV, /* AIR/CBL */ + [ 17 ] = KEY_PC, /* PC/TV */ + [ 23 ] = KEY_OK, /* CH RTN */ + [ 25 ] = KEY_MODE, /* FUNC */ + [ 12 ] = KEY_SEARCH, /* AUTOSCAN */ /* Not sure what to do with these ones! */ - [ 0x0f ] = KEY_SELECT, /* SOURCE */ - [ 0x0a ] = KEY_KPPLUS, /* +100 */ - [ 0x14 ] = KEY_KPEQUAL, /* SYNC */ - [ 0x1c ] = KEY_MEDIA, /* PC/TV */ + [ 15 ] = KEY_SELECT, /* SOURCE */ + [ 10 ] = KEY_KPPLUS, /* +100 */ + [ 20 ] = KEY_KPEQUAL, /* SYNC */ + [ 28 ] = KEY_MEDIA, /* PC/TV */ }; static IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { - [ 0x03 ] = KEY_POWER, + [ 0x3 ] = KEY_POWER, [ 0x6f ] = KEY_MUTE, [ 0x10 ] = KEY_BACKSPACE, /* Recall */ [ 0x11 ] = KEY_KP0, - [ 0x04 ] = KEY_KP1, - [ 0x05 ] = KEY_KP2, - [ 0x06 ] = KEY_KP3, - [ 0x08 ] = KEY_KP4, - [ 0x09 ] = KEY_KP5, - [ 0x0a ] = KEY_KP6, - [ 0x0c ] = KEY_KP7, - [ 0x0d ] = KEY_KP8, - [ 0x0e ] = KEY_KP9, + [ 0x4 ] = KEY_KP1, + [ 0x5 ] = KEY_KP2, + [ 0x6 ] = KEY_KP3, + [ 0x8 ] = KEY_KP4, + [ 0x9 ] = KEY_KP5, + [ 0xa ] = KEY_KP6, + [ 0xc ] = KEY_KP7, + [ 0xd ] = KEY_KP8, + [ 0xe ] = KEY_KP9, [ 0x12 ] = KEY_KPDOT, /* 100+ */ - [ 0x07 ] = KEY_VOLUMEUP, - [ 0x0b ] = KEY_VOLUMEDOWN, + [ 0x7 ] = KEY_VOLUMEUP, + [ 0xb ] = KEY_VOLUMEDOWN, [ 0x1a ] = KEY_KPPLUS, [ 0x18 ] = KEY_KPMINUS, [ 0x15 ] = KEY_UP, [ 0x1d ] = KEY_DOWN, - [ 0x0f ] = KEY_CHANNELUP, + [ 0xf ] = KEY_CHANNELUP, [ 0x13 ] = KEY_CHANNELDOWN, [ 0x48 ] = KEY_ZOOM, @@ -152,17 +122,6 @@ static IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { }; -struct IR { - struct i2c_client c; - struct input_dev *input; - struct ir_input_state ir; - - struct work_struct work; - struct timer_list timer; - char phys[32]; - int (*get_key)(struct IR*, u32*, u32*); -}; - /* ----------------------------------------------------------------------- */ /* insmod parameters */ @@ -173,12 +132,9 @@ module_param(debug, int, 0644); /* debug level (0,1,2) */ #define dprintk(level, fmt, arg...) if (debug >= level) \ printk(KERN_DEBUG DEVNAME ": " fmt , ## arg) -#define IR_PINNACLE_REMOTE 0x01 -#define IR_TERRATEC_REMOTE 0x02 - /* ----------------------------------------------------------------------- */ -static int get_key_haup(struct IR *ir, u32 *ir_key, u32 *ir_raw) +static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { unsigned char buf[3]; int start, toggle, dev, code; @@ -205,7 +161,7 @@ static int get_key_haup(struct IR *ir, u32 *ir_key, u32 *ir_raw) return 1; } -static int get_key_pixelview(struct IR *ir, u32 *ir_key, u32 *ir_raw) +static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { unsigned char b; @@ -219,7 +175,7 @@ static int get_key_pixelview(struct IR *ir, u32 *ir_key, u32 *ir_raw) return 1; } -static int get_key_pv951(struct IR *ir, u32 *ir_key, u32 *ir_raw) +static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { unsigned char b; @@ -239,7 +195,7 @@ static int get_key_pv951(struct IR *ir, u32 *ir_key, u32 *ir_raw) return 1; } -static int get_key_knc1(struct IR *ir, u32 *ir_key, u32 *ir_raw) +static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { unsigned char b; @@ -267,7 +223,7 @@ static int get_key_knc1(struct IR *ir, u32 *ir_key, u32 *ir_raw) return 1; } -static int get_key_purpletv(struct IR *ir, u32 *ir_key, u32 *ir_raw) +static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { unsigned char b; @@ -289,10 +245,9 @@ static int get_key_purpletv(struct IR *ir, u32 *ir_key, u32 *ir_raw) *ir_raw = b; return 1; } - /* ----------------------------------------------------------------------- */ -static void ir_key_poll(struct IR *ir) +static void ir_key_poll(struct IR_i2c *ir) { static u32 ir_key, ir_raw; int rc; @@ -313,13 +268,13 @@ static void ir_key_poll(struct IR *ir) static void ir_timer(unsigned long data) { - struct IR *ir = (struct IR*)data; + struct IR_i2c *ir = (struct IR_i2c*)data; schedule_work(&ir->work); } static void ir_work(void *data) { - struct IR *ir = data; + struct IR_i2c *ir = data; ir_key_poll(ir); mod_timer(&ir->timer, jiffies+HZ/10); } @@ -351,10 +306,10 @@ static int ir_attach(struct i2c_adapter *adap, int addr, IR_KEYTAB_TYPE *ir_codes = NULL; char *name; int ir_type; - struct IR *ir; + struct IR_i2c *ir; struct input_dev *input_dev; - ir = kzalloc(sizeof(struct IR), GFP_KERNEL); + ir = kzalloc(sizeof(struct IR_i2c), GFP_KERNEL); input_dev = input_allocate_device(); if (!ir || !input_dev) { kfree(ir); @@ -390,36 +345,18 @@ static int ir_attach(struct i2c_adapter *adap, int addr, ir_codes = ir_codes_rc5_tv; break; case 0x30: - switch(kind){ - case IR_TERRATEC_REMOTE: - name = "Terratec IR"; - ir->get_key = get_key_knc1; - ir_type = IR_TYPE_OTHER; - ir_codes = ir_codes_em2820; - break; - default: - name = "KNC One"; - ir->get_key = get_key_knc1; - ir_type = IR_TYPE_OTHER; - ir_codes = ir_codes_empty; - } + name = "KNC One"; + ir->get_key = get_key_knc1; + ir_type = IR_TYPE_OTHER; + ir_codes = ir_codes_empty; break; - case 0x47: case 0x7a: - switch(kind){ - case IR_PINNACLE_REMOTE: - name = "Pinnacle IR Remote"; - ir->get_key = get_key_purpletv; - ir_type = IR_TYPE_OTHER; - ir_codes = ir_codes_em2820; - break; - default: - name = "Purple TV"; - ir->get_key = get_key_purpletv; - ir_type = IR_TYPE_OTHER; - ir_codes = ir_codes_purpletv; - } + name = "Purple TV"; + ir->get_key = get_key_purpletv; + ir_type = IR_TYPE_OTHER; + ir_codes = ir_codes_purpletv; break; + default: /* shouldn't happen */ printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n",addr); @@ -427,12 +364,18 @@ static int ir_attach(struct i2c_adapter *adap, int addr, return -1; } - /* register i2c device */ - i2c_attach_client(&ir->c); + /* Sets name and its physical addr */ snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name); snprintf(ir->phys, sizeof(ir->phys), "%s/%s/ir0", ir->c.adapter->dev.bus_id, ir->c.dev.bus_id); + ir->ir_codes=ir_codes; + + /* register i2c device + * At device register, IR codes may be changed to be + * board dependent. + */ + i2c_attach_client(&ir->c); /* init + register input device */ ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); @@ -440,6 +383,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr, input_dev->name = ir->c.name; input_dev->phys = ir->phys; + /* register event device */ input_register_device(ir->input); /* start polling via eventd */ @@ -454,7 +398,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr, static int ir_detach(struct i2c_client *client) { - struct IR *ir = i2c_get_clientdata(client); + struct IR_i2c *ir = i2c_get_clientdata(client); /* kill outstanding polls */ del_timer(&ir->timer); @@ -483,11 +427,9 @@ static int ir_probe(struct i2c_adapter *adap) static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1}; static const int probe_saa7134[] = { 0x7a, -1 }; - static const int probe_em2820[] = { 0x47, 0x30, -1 }; + static const int probe_em2820[] = { 0x30, 0x47, -1 }; const int *probe = NULL; - int attached = 0; - - struct i2c_client c; unsigned char buf; int i,rc; + struct i2c_client c; char buf; int i,rc; switch (adap->id) { case I2C_HW_B_BT848: @@ -505,27 +447,15 @@ static int ir_probe(struct i2c_adapter *adap) memset(&c,0,sizeof(c)); c.adapter = adap; - for (i = 0; -1 != probe[i] && attached != 1; i++) { + for (i = 0; -1 != probe[i]; i++) { c.addr = probe[i]; - rc = i2c_master_recv(&c,&buf,1); + rc = i2c_master_recv(&c,&buf,0); dprintk(1,"probe 0x%02x @ %s: %s\n", probe[i], adap->name, - (1 == rc) ? "yes" : "no"); - switch(adap->id){ - case I2C_HW_B_BT848: - case I2C_HW_SAA7134: - if (1 == rc) { - ir_attach(adap,probe[i],0,0); - attached=1; - break; - } - case I2C_HW_B_EM2820: - /* windows logs are needed for fixing the pinnacle device */ - if (1 == rc && 0xff == buf){ - ir_attach(adap,probe[i],0,IR_TERRATEC_REMOTE); - attached=1; - } - break; + (0 == rc) ? "yes" : "no"); + if (0 == rc) { + ir_attach(adap,probe[i],0,0); + break; } } return 0; diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 01b56822df4..0f1ba95ec8d 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -20,8 +20,10 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include +#ifndef _IR_COMMON +#define _IR_COMMON +#include #define IR_TYPE_RC5 1 #define IR_TYPE_PD 2 /* Pulse distance encoded IR */ @@ -61,6 +63,8 @@ int ir_dump_samples(u32 *samples, int count); int ir_decode_biphase(u32 *samples, int count, int low, int high); int ir_decode_pulsedistance(u32 *samples, int count, int low, int high); +#endif + /* * Local variables: * c-basic-offset: 8 diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h new file mode 100644 index 00000000000..00fa57eb9fd --- /dev/null +++ b/include/media/ir-kbd-i2c.h @@ -0,0 +1,22 @@ +#ifndef _IR_I2C +#define _IR_I2C + +#include + +struct IR_i2c; + +struct IR_i2c { + IR_KEYTAB_TYPE *ir_codes; + struct i2c_client c; + struct input_dev *input; + struct ir_input_state ir; + + /* Used to avoid fast repeating */ + unsigned char old; + + struct work_struct work; + struct timer_list timer; + char phys[32]; + int (*get_key)(struct IR_i2c*, u32*, u32*); +}; +#endif -- cgit v1.2.3 From 74458e6c1aea9e422e46030e7bc61e9b0984be5b Mon Sep 17 00:00:00 2001 From: Sascha Sommer Date: Tue, 8 Nov 2005 21:37:33 -0800 Subject: [PATCH] v4l: 786: chip id removed since it isn t required anymore - Chip_id removed since it isn't required anymore. Signed-off-by: Sascha Sommer Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-cards.c | 3 --- drivers/media/video/em28xx/em28xx-core.c | 12 ++++++++++++ drivers/media/video/em28xx/em28xx-video.c | 12 ++++++++++++ drivers/media/video/em28xx/em28xx.h | 1 - 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 919520f8997..59f8fa0bea6 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -160,7 +160,6 @@ struct em2820_board em2820_boards[] = { }, [EM2800_BOARD_TERRATEC_CINERGY_200] = { .name = "Terratec Cinergy 200 USB", - .chip_id = 0x4, .is_em2800 = 1, .vchannels = 3, .norm = VIDEO_MODE_PAL, @@ -184,7 +183,6 @@ struct em2820_board em2820_boards[] = { }, [EM2800_BOARD_LEADTEK_WINFAST_USBII] = { .name = "Leadtek Winfast USB II", - .chip_id = 0x2, .is_em2800 = 1, .vchannels = 3, .norm = VIDEO_MODE_PAL, @@ -208,7 +206,6 @@ struct em2820_board em2820_boards[] = { }, [EM2800_BOARD_KWORLD_USB2800] = { .name = "Kworld USB2800", - .chip_id = 0x7, .is_em2800 = 1, .vchannels = 3, .norm = VIDEO_MODE_PAL, diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index f5e22154a97..f7b8fb035c9 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -437,6 +437,18 @@ int em2820_scaler_set(struct em2820 *dev, u16 h, u16 v) buf[0] = v; buf[1] = v >> 8; em2820_write_regs(dev, VSCALELOW_REG, (char *)buf, 2); + if(dev->is_em2800){ + /* FIXME */ + /* random ratio scaling and 720x567 doesn't seem to work */ + /* the maximum we can get is 640x480 with disabled scaler */ + /* and norm_maxw set to 640 */ + if(dev->width == 640 && dev->height == 480) + return em2820_write_regs(dev, COMPR_REG,"\x00",1); + if(dev->height > 288) + return em2820_write_regs(dev, COMPR_REG,"\x10",1); + if(dev->width > 360) + return em2820_write_regs(dev, COMPR_REG,"\x20",1); + } /* when H and V mixershould be used? */ /* return em2820_write_reg_bits(dev, COMPR_REG, (h ? 0x20 : 0x00) | (v ? 0x10 : 0x00), 0x30); */ /* it seems that both H and V scalers must be active to work correctly */ diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index f3fc44b352b..048ad1d77ba 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1272,6 +1272,18 @@ static int em2820_video_do_ioctl(struct inode *inode, struct file *filp, if (width > maxw) width = maxw; + /* FIXME*/ + if(dev->is_em2800){ + /* we only know how to scale to 50% */ + if(height % (maxh / 2)) + height=maxh; + if(width % (maxw / 2)) + width=maxw; + /* larger resoltion don't seem to work either */ + if(width == maxw && height == maxh) + width /= 2; + } + if ((hscale = (((unsigned long)maxw) << 12) / width - 4096L) >= 0x4000) diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 31b23f0db05..a11df04a8c3 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -159,7 +159,6 @@ enum em2820_decoder { struct em2820_board { char *name; - unsigned char chip_id; int vchannels; int norm; int tuner_type; -- cgit v1.2.3 From 78f82405ace9415e72a87b16c195675f053381f1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 8 Nov 2005 21:37:34 -0800 Subject: [PATCH] v4l: 788: log message - This fixes dual language detection on the msp3400. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/msp3400.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index 117d124657d..5573f68ce45 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -1788,6 +1788,10 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) dprintk("msp34xx: AUDC_SET_RADIO\n"); msp->norm = VIDEO_MODE_RADIO; dprintk("msp34xx: switching to radio mode\n"); + if (IS_MSP34XX_G(msp)) { + msp34xxg_reset(client); + break; + } msp->watch_stereo = 0; switch (msp->opmode) { case OPMODE_MANUAL: @@ -1902,6 +1906,10 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) dprintk("msp34xx: VIDIOCSCHAN (norm=%d)\n",vc->norm); msp->norm = vc->norm; + if (IS_MSP34XX_G(msp)) { + msp34xxg_reset(client); + break; + } msp_wake_thread(client); break; } @@ -1911,6 +1919,10 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { /* new channel -- kick audio carrier scan */ dprintk("msp34xx: VIDIOCSFREQ\n"); + if (IS_MSP34XX_G(msp)) { + msp34xxg_reset(client); + break; + } msp_wake_thread(client); break; } -- cgit v1.2.3 From 340622c5a9028d70b1238ecafb463125277a30eb Mon Sep 17 00:00:00 2001 From: Dwaine Garden Date: Tue, 8 Nov 2005 21:37:34 -0800 Subject: [PATCH] v4l: 789: added support for saa7113 - Added support for saa7113. Signed-off-by: Dwaine Garden Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa711x.c | 597 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 597 insertions(+) create mode 100644 drivers/media/video/saa711x.c diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c new file mode 100644 index 00000000000..37653ee8723 --- /dev/null +++ b/drivers/media/video/saa711x.c @@ -0,0 +1,597 @@ +/* + * saa7111 - Philips SAA7113A video decoder driver version 0.0.3 + * + * Copyright (C) 1998 Dave Perks + * + * Slight changes for video timing and attachment output by + * Wolfgang Scherr + * + * Changes by Ronald Bultje + * - moved over to linux>=2.4.x i2c protocol (1/1/2003) + * + * Changes by Michael Hunold + * - implemented DECODER_SET_GPIO, DECODER_INIT, DECODER_SET_VBI_BYPASS + * + * 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 option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_DESCRIPTION("Philips SAA7113 video decoder driver"); +MODULE_AUTHOR("Dave Perks, Jose Ignacio Gijon, Joerg Heckenbach, Mark McClelland, Dwaine Garden"); +MODULE_LICENSE("GPL"); + +#include +#include + +#define I2C_NAME(s) (s)->name + +#include + +static int debug = 0; +MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(debug, " Set the default Debug level. Default: 0 (Off) - (0-1)"); + + +#define dprintk(num, format, args...) \ + do { \ + if (debug >= num) \ + printk(format , ##args); \ + } while (0) + +/* ----------------------------------------------------------------------- */ + +struct saa7113 { + unsigned char reg[32]; + + int norm; + int input; + int enable; + int bright; + int contrast; + int hue; + int sat; +}; + +#define I2C_SAA7113 0x4A + +/* ----------------------------------------------------------------------- */ + +static inline int +saa7113_write (struct i2c_client *client, + u8 reg, + u8 value) +{ + struct saa7113 *decoder = i2c_get_clientdata(client); + + decoder->reg[reg] = value; + return i2c_smbus_write_byte_data(client, reg, value); +} + +static int +saa7113_write_block (struct i2c_client *client, + const u8 *data, + unsigned int len) +{ + int ret = -1; + u8 reg; + + /* the saa7113 has an autoincrement function, use it if + * the adapter understands raw I2C */ + if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + /* do raw I2C, not smbus compatible */ + struct saa7113 *decoder = i2c_get_clientdata(client); + struct i2c_msg msg; + u8 block_data[32]; + + msg.addr = client->addr; + msg.flags = 0; + while (len >= 2) { + msg.buf = (char *) block_data; + msg.len = 0; + block_data[msg.len++] = reg = data[0]; + do { + block_data[msg.len++] = + decoder->reg[reg++] = data[1]; + len -= 2; + data += 2; + } while (len >= 2 && data[0] == reg && + msg.len < 32); + if ((ret = i2c_transfer(client->adapter, + &msg, 1)) < 0) + break; + } + } else { + /* do some slow I2C emulation kind of thing */ + while (len >= 2) { + reg = *data++; + if ((ret = saa7113_write(client, reg, + *data++)) < 0) + break; + len -= 2; + } + } + + return ret; +} + +static int +saa7113_init_decoder (struct i2c_client *client, + struct video_decoder_init *init) +{ + return saa7113_write_block(client, init->data, init->len); +} + +static inline int +saa7113_read (struct i2c_client *client, + u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +/* ----------------------------------------------------------------------- */ + +static const unsigned char saa7113_i2c_init[] = { + 0x00, 0x00, /* PH7113_CHIP_VERSION 00 - ID byte */ + 0x01, 0x08, /* PH7113_INCREMENT_DELAY - (1) (1) (1) (1) IDEL3 IDEL2 IDELL1 IDEL0 */ + 0x02, 0xc0, /* PH7113_ANALOG_INPUT_CONTR_1 - FUSE1 FUSE0 GUDL1 GUDL0 MODE3 MODE2 MODE1 MODE0 */ + 0x03, 0x23, /* PH7113_ANALOG_INPUT_CONTR_2 - (1) HLNRS VBSL WPOFF HOLDG GAFIX GAI28 GAI18 */ + 0x04, 0x00, /* PH7113_ANALOG_INPUT_CONTR_3 - GAI17 GAI16 GAI15 GAI14 GAI13 GAI12 GAI11 GAI10 */ + 0x05, 0x00, /* PH7113_ANALOG_INPUT_CONTR_4 - GAI27 GAI26 GAI25 GAI24 GAI23 GAI22 GAI21 GAI20 */ + 0x06, 0xeb, /* PH7113_HORIZONTAL_SYNC_START - HSB7 HSB6 HSB5 HSB4 HSB3 HSB2 HSB1 HSB0 */ + 0x07, 0xe0, /* PH7113_HORIZONTAL_SYNC_STOP - HSS7 HSS6 HSS5 HSS4 HSS3 HSS2 HSS1 HSS0 */ + 0x08, 0x88, /* PH7113_SYNC_CONTROL - AUFD FSEL FOET HTC1 HTC0 HPLL VNOI1 VNOI0 */ + 0x09, 0x00, /* PH7113_LUMINANCE_CONTROL - BYPS PREF BPSS1 BPSS0 VBLB UPTCV APER1 APER0 */ + 0x0a, 0x80, /* PH7113_LUMINANCE_BRIGHTNESS - BRIG7 BRIG6 BRIG5 BRIG4 BRIG3 BRIG2 BRIG1 BRIG0 */ + 0x0b, 0x47, /* PH7113_LUMINANCE_CONTRAST - CONT7 CONT6 CONT5 CONT4 CONT3 CONT2 CONT1 CONT0 */ + 0x0c, 0x40, /* PH7113_CHROMA_SATURATION - SATN7 SATN6 SATN5 SATN4 SATN3 SATN2 SATN1 SATN0 */ + 0x0d, 0x00, /* PH7113_CHROMA_HUE_CONTROL - HUEC7 HUEC6 HUEC5 HUEC4 HUEC3 HUEC2 HUEC1 HUEC0 */ + 0x0e, 0x01, /* PH7113_CHROMA_CONTROL - CDTO CSTD2 CSTD1 CSTD0 DCCF FCTC CHBW1 CHBW0 */ + 0x0f, 0xaa, /* PH7113_CHROMA_GAIN_CONTROL - ACGC CGAIN6 CGAIN5 CGAIN4 CGAIN3 CGAIN2 CGAIN1 CGAIN0 */ + 0x10, 0x00, /* PH7113_FORMAT_DELAY_CONTROL - OFTS1 OFTS0 HDEL1 HDEL0 VRLN YDEL2 YDEL1 YDEL0 */ + 0x11, 0x1C, /* PH7113_OUTPUT_CONTROL_1 - GPSW1 CM99 GPSW0 HLSEL OEYC OERT VIPB COLO */ + 0x12, 0x01, /* PH7113_OUTPUT_CONTROL_2 - RTSE13 RTSE12 RTSE11 RTSE10 RTSE03 RTSE02 RTSE01 RTSE00 */ + 0x13, 0x00, /* PH7113_OUTPUT_CONTROL_3 - ADLSB (1) (1) OLDSB FIDP (1) AOSL1 AOSL0 */ + 0x14, 0x00, /* RESERVED 14 - (1) (1) (1) (1) (1) (1) (1) (1) */ + 0x15, 0x00, /* PH7113_V_GATE1_START - VSTA7 VSTA6 VSTA5 VSTA4 VSTA3 VSTA2 VSTA1 VSTA0 */ + 0x16, 0x00, /* PH7113_V_GATE1_STOP - VSTO7 VSTO6 VSTO5 VSTO4 VSTO3 VSTO2 VSTO1 VSTO0 */ + 0x17, 0x00, /* PH7113_V_GATE1_MSB - (1) (1) (1) (1) (1) (1) VSTO8 VSTA8 */ +}; + +static int +saa7113_command (struct i2c_client *client, + unsigned int cmd, + void *arg) +{ + struct saa7113 *decoder = i2c_get_clientdata(client); + + switch (cmd) { + + case 0: + case DECODER_INIT: + { + struct video_decoder_init *init = arg; + if (NULL != init) + return saa7113_init_decoder(client, init); + else { + struct video_decoder_init vdi; + vdi.data = saa7113_i2c_init; + vdi.len = sizeof(saa7113_i2c_init); + return saa7113_init_decoder(client, &vdi); + } + } + + case DECODER_DUMP: + { + int i; + + for (i = 0; i < 32; i += 16) { + int j; + + printk(KERN_DEBUG "%s: %03x", I2C_NAME(client), i); + for (j = 0; j < 16; ++j) { + printk(" %02x", + saa7113_read(client, i + j)); + } + printk("\n"); + } + } + break; + + case DECODER_GET_CAPABILITIES: + { + struct video_decoder_capability *cap = arg; + + cap->flags = VIDEO_DECODER_PAL | + VIDEO_DECODER_NTSC | + VIDEO_DECODER_SECAM | + VIDEO_DECODER_AUTO | + VIDEO_DECODER_CCIR; + cap->inputs = 8; + cap->outputs = 1; + } + break; + + case DECODER_GET_STATUS: + { + int *iarg = arg; + int status; + int res; + + status = saa7113_read(client, 0x1f); + dprintk(1, KERN_DEBUG "%s status: 0x%02x\n", I2C_NAME(client), + status); + res = 0; + if ((status & (1 << 6)) == 0) { + res |= DECODER_STATUS_GOOD; + } + switch (decoder->norm) { + case VIDEO_MODE_NTSC: + res |= DECODER_STATUS_NTSC; + break; + case VIDEO_MODE_PAL: + res |= DECODER_STATUS_PAL; + break; + case VIDEO_MODE_SECAM: + res |= DECODER_STATUS_SECAM; + break; + default: + case VIDEO_MODE_AUTO: + if ((status & (1 << 5)) != 0) { + res |= DECODER_STATUS_NTSC; + } else { + res |= DECODER_STATUS_PAL; + } + break; + } + if ((status & (1 << 0)) != 0) { + res |= DECODER_STATUS_COLOR; + } + *iarg = res; + } + break; + + case DECODER_SET_GPIO: + { + int *iarg = arg; + if (0 != *iarg) { + saa7113_write(client, 0x11, + (decoder->reg[0x11] | 0x80)); + } else { + saa7113_write(client, 0x11, + (decoder->reg[0x11] & 0x7f)); + } + break; + } + + case DECODER_SET_VBI_BYPASS: + { + int *iarg = arg; + if (0 != *iarg) { + saa7113_write(client, 0x13, + (decoder->reg[0x13] & 0xf0) | 0x0a); + } else { + saa7113_write(client, 0x13, + (decoder->reg[0x13] & 0xf0)); + } + break; + } + + case DECODER_SET_NORM: + { + int *iarg = arg; + + switch (*iarg) { + + case VIDEO_MODE_NTSC: + saa7113_write(client, 0x08, + (decoder->reg[0x08] & 0x3f) | 0x40); + saa7113_write(client, 0x0e, + (decoder->reg[0x0e] & 0x8f)); + break; + + case VIDEO_MODE_PAL: + saa7113_write(client, 0x08, + (decoder->reg[0x08] & 0x3f) | 0x00); + saa7113_write(client, 0x0e, + (decoder->reg[0x0e] & 0x8f)); + break; + + case VIDEO_MODE_SECAM: + saa7113_write(client, 0x08, + (decoder->reg[0x0e] & 0x3f) | 0x00); + saa7113_write(client, 0x0e, + (decoder->reg[0x0e] & 0x8f) | 0x50); + break; + + case VIDEO_MODE_AUTO: + saa7113_write(client, 0x08, + (decoder->reg[0x08] & 0x3f) | 0x80); + saa7113_write(client, 0x0e, + (decoder->reg[0x0e] & 0x8f)); + break; + + default: + return -EINVAL; + + } + decoder->norm = *iarg; + } + break; + + case DECODER_SET_INPUT: + { + int *iarg = arg; + if (*iarg < 0 || *iarg > 9) { + return -EINVAL; + } + if (decoder->input != *iarg) { + decoder->input = *iarg; + /* select mode */ + saa7113_write(client, 0x02, + (decoder->reg[0x02] & 0xf0) | decoder->input); + /* bypass chrominance trap for modes 4..7 */ + saa7113_write(client, 0x09, + (decoder->reg[0x09] & 0x7f) | ((decoder->input > 3) ? 0x80 : 0)); + } + } + break; + + case DECODER_SET_OUTPUT: + { + int *iarg = arg; + + /* not much choice of outputs */ + if (*iarg != 0) { + return -EINVAL; + } + } + break; + + case DECODER_ENABLE_OUTPUT: + { + int *iarg = arg; + int enable = (*iarg != 0); + + if (decoder->enable != enable) { + decoder->enable = enable; + + /* RJ: If output should be disabled (for + * playing videos), we also need a open PLL. + * The input is set to 0 (where no input + * source is connected), although this + * is not necessary. + * + * If output should be enabled, we have to + * reverse the above. + */ + + if (decoder->enable) { + saa7113_write(client, 0x02, + (decoder-> + reg[0x02] & 0xf8) | + decoder->input); + saa7113_write(client, 0x08, + (decoder->reg[0x08] & 0xfb)); + saa7113_write(client, 0x11, + (decoder-> + reg[0x11] & 0xf3) | 0x0c); + } else { + saa7113_write(client, 0x02, + (decoder->reg[0x02] & 0xf8)); + saa7113_write(client, 0x08, + (decoder-> + reg[0x08] & 0xfb) | 0x04); + saa7113_write(client, 0x11, + (decoder->reg[0x11] & 0xf3)); + } + } + } + break; + + case DECODER_SET_PICTURE: + { + struct video_picture *pic = arg; + + if (decoder->bright != pic->brightness) { + /* We want 0 to 255 we get 0-65535 */ + decoder->bright = pic->brightness; + saa7113_write(client, 0x0a, decoder->bright >> 8); + } + if (decoder->contrast != pic->contrast) { + /* We want 0 to 127 we get 0-65535 */ + decoder->contrast = pic->contrast; + saa7113_write(client, 0x0b, + decoder->contrast >> 9); + } + if (decoder->sat != pic->colour) { + /* We want 0 to 127 we get 0-65535 */ + decoder->sat = pic->colour; + saa7113_write(client, 0x0c, decoder->sat >> 9); + } + if (decoder->hue != pic->hue) { + /* We want -128 to 127 we get 0-65535 */ + decoder->hue = pic->hue; + saa7113_write(client, 0x0d, + (decoder->hue - 32768) >> 8); + } + } + break; + + default: + return -EINVAL; + } + + return 0; +} + +/* ----------------------------------------------------------------------- */ + +/* + * Generic i2c probe + * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' + */ + +/* standard i2c insmod options */ +static unsigned short normal_i2c[] = { + I2C_SAA7113>>1, /* saa7113 */ + I2C_CLIENT_END +}; + +I2C_CLIENT_INSMOD; + + +static struct i2c_driver i2c_driver_saa7113; + +static int +saa7113_detect_client (struct i2c_adapter *adapter, + int address, + int kind) +{ + int i; + struct i2c_client *client; + struct saa7113 *decoder; + struct video_decoder_init vdi; + + dprintk(1, + KERN_INFO + "saa7113.c: detecting saa7113 client on address 0x%x\n", + address << 1); + + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return 0; + + client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (client == 0) + return -ENOMEM; + memset(client, 0, sizeof(struct i2c_client)); + client->addr = address; + client->adapter = adapter; + client->driver = &i2c_driver_saa7113; + client->flags = I2C_CLIENT_ALLOW_USE; + strlcpy(I2C_NAME(client), "saa7113", sizeof(I2C_NAME(client))); + decoder = kmalloc(sizeof(struct saa7113), GFP_KERNEL); + if (decoder == NULL) { + kfree(client); + return -ENOMEM; + } + memset(decoder, 0, sizeof(struct saa7113)); + decoder->norm = VIDEO_MODE_NTSC; + decoder->input = 0; + decoder->enable = 1; + decoder->bright = 32768; + decoder->contrast = 32768; + decoder->hue = 32768; + decoder->sat = 32768; + i2c_set_clientdata(client, decoder); + + i = i2c_attach_client(client); + if (i) { + kfree(client); + kfree(decoder); + return i; + } + + vdi.data = saa7113_i2c_init; + vdi.len = sizeof(saa7113_i2c_init); + i = saa7113_init_decoder(client, &vdi); + if (i < 0) { + dprintk(1, KERN_ERR "%s_attach error: init status %d\n", + I2C_NAME(client), i); + } else { + dprintk(1, + KERN_INFO + "%s_attach: chip version %x at address 0x%x\n", + I2C_NAME(client), saa7113_read(client, 0x00) >> 4, + client->addr << 1); + } + + return 0; +} + +static int +saa7113_attach_adapter (struct i2c_adapter *adapter) +{ + dprintk(1, + KERN_INFO + "saa7113.c: starting probe for adapter %s (0x%x)\n", + I2C_NAME(adapter), adapter->id); + return i2c_probe(adapter, &addr_data, &saa7113_detect_client); +} + +static int +saa7113_detach_client (struct i2c_client *client) +{ + struct saa7113 *decoder = i2c_get_clientdata(client); + int err; + + err = i2c_detach_client(client); + if (err) { + return err; + } + + kfree(decoder); + kfree(client); + + return 0; +} + +/* ----------------------------------------------------------------------- */ + +static struct i2c_driver i2c_driver_saa7113 = { + .owner = THIS_MODULE, + .name = "saa7113", + + .id = I2C_DRIVERID_SAA7113, + .flags = I2C_DF_NOTIFY, + + .attach_adapter = saa7113_attach_adapter, + .detach_client = saa7113_detach_client, + .command = saa7113_command, +}; + +static int __init +saa7113_init (void) +{ + return i2c_add_driver(&i2c_driver_saa7113); +} + +static void __exit +saa7113_exit (void) +{ + i2c_del_driver(&i2c_driver_saa7113); +} + +module_init(saa7113_init); +module_exit(saa7113_exit); -- cgit v1.2.3 From e43f14af143921ac6680aa3ddfff111bef4e034a Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Tue, 8 Nov 2005 21:37:35 -0800 Subject: [PATCH] v4l: 790: added support for terratec cinergy 250 usb - Added support for Terratec Cinergy 250 USB Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-input.c | 94 ++++++++++++++++++++----------- drivers/media/video/ir-kbd-i2c.c | 2 +- 2 files changed, 63 insertions(+), 33 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index d6b3e15a035..3800b99e4b8 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -42,40 +42,68 @@ MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); /* ---------------------------------------------------------------------- */ -static IR_KEYTAB_TYPE ir_codes_em_pinnacle[IR_KEYTAB_SIZE] = { - [ 0 ] = KEY_CHANNEL, - [ 1 ] = KEY_SELECT, - [ 2 ] = KEY_MUTE, - [ 3 ] = KEY_POWER, - [ 4 ] = KEY_KP1, - [ 5 ] = KEY_KP2, - [ 6 ] = KEY_KP3, - [ 7 ] = KEY_CHANNELUP, - [ 8 ] = KEY_KP4, - [ 9 ] = KEY_KP5, - [ 10 ] = KEY_KP6, - - [ 11 ] = KEY_CHANNELDOWN, - [ 12 ] = KEY_KP7, - [ 13 ] = KEY_KP8, - [ 14 ] = KEY_KP9, - [ 15 ] = KEY_VOLUMEUP, - [ 16 ] = KEY_KP0, - [ 17 ] = KEY_MENU, - [ 18 ] = KEY_PRINT, - - [ 19 ] = KEY_VOLUMEDOWN, - [ 21 ] = KEY_PAUSE, - [ 23 ] = KEY_RECORD, - [ 24 ] = KEY_REWIND, - [ 25 ] = KEY_PLAY, - [ 27 ] = KEY_BACKSPACE, - [ 29 ] = KEY_STOP, - [ 31 ] = KEY_ZOOM, +static IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = { + [ 0x01 ] = KEY_CHANNEL, + [ 0x02 ] = KEY_SELECT, + [ 0x03 ] = KEY_MUTE, + [ 0x04 ] = KEY_POWER, + [ 0x05 ] = KEY_KP1, + [ 0x06 ] = KEY_KP2, + [ 0x07 ] = KEY_KP3, + [ 0x08 ] = KEY_CHANNELUP, + [ 0x09 ] = KEY_KP4, + [ 0x0a ] = KEY_KP5, + [ 0x0b ] = KEY_KP6, + [ 0x0c ] = KEY_CHANNELDOWN, + [ 0x0d ] = KEY_KP7, + [ 0x0e ] = KEY_KP8, + [ 0x0f ] = KEY_KP9, + [ 0x10 ] = KEY_VOLUMEUP, + [ 0x11 ] = KEY_KP0, + [ 0x12 ] = KEY_MENU, + [ 0x13 ] = KEY_PRINT, + [ 0x14 ] = KEY_VOLUMEDOWN, + [ 0x16 ] = KEY_PAUSE, + [ 0x18 ] = KEY_RECORD, + [ 0x19 ] = KEY_REWIND, + [ 0x1a ] = KEY_PLAY, + [ 0x1b ] = KEY_FORWARD, + [ 0x1c ] = KEY_BACKSPACE, + [ 0x1e ] = KEY_STOP, + [ 0x40 ] = KEY_ZOOM, }; /* ----------------------------------------------------------------------- */ +static int get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +{ + unsigned char b; + + /* poll IR chip */ + if (1 != i2c_master_recv(&ir->c,&b,1)) { + dprintk("read error\n"); + return -EIO; + } + + /* it seems that 0xFE indicates that a button is still hold + down, while 0xFF indicates that no button is hold + down. 0xFE sequences are sometimes interrupted by 0xFF */ + + dprintk("key %02x\n", b); + + if (b == 0xFF) + return 0; + + if (b == 0xFE) + /* keep old data */ + return 1; + + *ir_key = b; + *ir_raw = b; + return 1; +} + + static int get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { unsigned char buf[2]; @@ -123,14 +151,16 @@ void em2820_set_ir(struct em2820 * dev,struct IR_i2c *ir) case (EM2820_BOARD_UNKNOWN): break; case (EM2820_BOARD_TERRATEC_CINERGY_250): + ir->ir_codes = ir_codes_em_terratec; + ir->get_key = get_key_terratec; + snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM2820 Terratec)"); break; case (EM2820_BOARD_PINNACLE_USB_2): - ir->ir_codes = ir_codes_em_pinnacle; break; case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): ir->ir_codes = ir_codes_hauppauge_new; ir->get_key = get_key_em_haup; - snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM2840 Hauppage)"); + snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM2840 Hauppauge)"); break; case (EM2820_BOARD_MSI_VOX_USB_2): break; diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 8cc3f8ab2f3..c4701035ca2 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -429,7 +429,7 @@ static int ir_probe(struct i2c_adapter *adap) static const int probe_saa7134[] = { 0x7a, -1 }; static const int probe_em2820[] = { 0x30, 0x47, -1 }; const int *probe = NULL; - struct i2c_client c; char buf; int i,rc; + struct i2c_client c; unsigned char buf; int i,rc; switch (adap->id) { case I2C_HW_B_BT848: -- cgit v1.2.3 From 4f9c05aa727a3b27e28972f2f3938b29ad81b833 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:36 -0800 Subject: [PATCH] v4l: 791: codingstyle fixes - CodingStyle fixes Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Markus Rechberger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-input.c | 8 ++++---- drivers/media/video/ir-kbd-i2c.c | 12 +++++++----- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 3800b99e4b8..0576ad6c42b 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -86,15 +86,15 @@ static int get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) } /* it seems that 0xFE indicates that a button is still hold - down, while 0xFF indicates that no button is hold - down. 0xFE sequences are sometimes interrupted by 0xFF */ + down, while 0xff indicates that no button is hold + down. 0xfe sequences are sometimes interrupted by 0xFF */ dprintk("key %02x\n", b); - if (b == 0xFF) + if (b == 0xff) return 0; - if (b == 0xFE) + if (b == 0xfe) /* keep old data */ return 1; diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index c4701035ca2..b0facaa40b2 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -206,15 +206,15 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) } /* it seems that 0xFE indicates that a button is still hold - down, while 0xFF indicates that no button is hold - down. 0xFE sequences are sometimes interrupted by 0xFF */ + down, while 0xff indicates that no button is hold + down. 0xfe sequences are sometimes interrupted by 0xFF */ dprintk(2,"key %02x\n", b); - if (b == 0xFF) + if (b == 0xff) return 0; - if (b == 0xFE) + if (b == 0xfe) /* keep old data */ return 1; @@ -429,7 +429,9 @@ static int ir_probe(struct i2c_adapter *adap) static const int probe_saa7134[] = { 0x7a, -1 }; static const int probe_em2820[] = { 0x30, 0x47, -1 }; const int *probe = NULL; - struct i2c_client c; unsigned char buf; int i,rc; + struct i2c_client c; + unsigned char buf; + int i,rc; switch (adap->id) { case I2C_HW_B_BT848: -- cgit v1.2.3 From 16f2e6229f6f7b89cb42f4942cb46dc645faae2a Mon Sep 17 00:00:00 2001 From: Sascha Sommer Date: Tue, 8 Nov 2005 21:37:37 -0800 Subject: [PATCH] v4l: 793: remotes for the cinergy 200 usb and cinergy 250 usb are the same - Remotes for the Cinergy 200 USB and Cinergy 250 USB are the same. Signed-off-by: Sascha Sommer Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-input.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 0576ad6c42b..ba367a9796e 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -150,6 +150,7 @@ void em2820_set_ir(struct em2820 * dev,struct IR_i2c *ir) break; case (EM2820_BOARD_UNKNOWN): break; + case (EM2800_BOARD_TERRATEC_CINERGY_200): case (EM2820_BOARD_TERRATEC_CINERGY_250): ir->ir_codes = ir_codes_em_terratec; ir->get_key = get_key_terratec; @@ -164,8 +165,6 @@ void em2820_set_ir(struct em2820 * dev,struct IR_i2c *ir) break; case (EM2820_BOARD_MSI_VOX_USB_2): break; - case (EM2800_BOARD_TERRATEC_CINERGY_200): - break; case (EM2800_BOARD_LEADTEK_WINFAST_USBII): break; case (EM2800_BOARD_KWORLD_USB2800): -- cgit v1.2.3 From 71633c05724d85f1afb87629bb96fdf2ef18b41f Mon Sep 17 00:00:00 2001 From: "nshmyrev@yandex.ru" Date: Tue, 8 Nov 2005 21:37:38 -0800 Subject: [PATCH] v4l: 794: added asound skyeye bttv card - Added Asound Skyeye bttv card. Signed-off-by: Nickolay V. Shmyrev <> Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.bttv | 1 + drivers/media/video/bttv-cards.c | 17 +++++++++++++++++ drivers/media/video/bttv.h | 1 + 3 files changed, 19 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index ba98ff4a79a..2404099996a 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -139,3 +139,4 @@ 138 -> Prolink Pixelview PV-BT878P+ (Rev.2E) 139 -> Prolink PixelView PlayTV MPEG2 PV-M4900 140 -> Osprey 440 [0070:ff07] +141 -> Asound Skyeye PCTV diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 2b19de386dc..8544a8fa2a5 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -2781,6 +2781,23 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .no_tda7432 = 1, }, + /* ---- card 0x8d ---------------------------------- */ + [BTTV_BOARD_ASOUND_SKYEYE] = { + .name = "Asound Skyeye PCTV", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 15, + .muxsel = { 2, 3, 1, 1}, + .audiomux = {2,0,0,0,1}, + .needs_tvaudio = 1, + .pll = PLL_28, + .tuner_type = 2, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, + }; static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h index ffece3b9136..26cd117a6df 100644 --- a/drivers/media/video/bttv.h +++ b/drivers/media/video/bttv.h @@ -161,6 +161,7 @@ #define BTTV_BOARD_PV_BT878P_2E 0x8a #define BTTV_BOARD_PV_M4900 0x8b #define BTTV_BOARD_OSPREY440 0x8c +#define BTTV_BOARD_ASOUND_SKYEYE 0x8d /* i2c address list */ #define I2C_TSA5522 0xc2 -- cgit v1.2.3 From 3ae1adc6ed93d55a27523f395284940fbe056401 Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:37:39 -0800 Subject: [PATCH] v4l: 795: new config option for tda9887 to specifically set intercarrier - New config option for tda9887 to specifically set intercarrier Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/cx88-cards.c | 2 +- drivers/media/video/tda9887.c | 2 ++ include/media/tuner.h | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 6a85ba111fb..cf17da83691 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -206,7 +206,7 @@ struct cx88_board cx88_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, + .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER_NTSC, .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 3a7babef06f..796110d4ff7 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -464,6 +464,8 @@ static int tda9887_set_config(struct tda9887 *t, char *buf) break; } } + if ((t->config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC)) + buf[1] &= ~cQSS; return 0; } diff --git a/include/media/tuner.h b/include/media/tuner.h index 7cc74b1bb6e..81025323267 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -148,6 +148,7 @@ # define TDA9887_INTERCARRIER (1<<4) # define TDA9887_PORT1_ACTIVE (1<<5) # define TDA9887_PORT2_ACTIVE (1<<6) +# define TDA9887_INTERCARRIER_NTSC (1<<7) /* config options */ # define TDA9887_DEEMPHASIS_MASK (3<<16) # define TDA9887_DEEMPHASIS_NONE (1<<16) -- cgit v1.2.3 From cf1c5d1d58793bb9320467226ffc850c75c20902 Mon Sep 17 00:00:00 2001 From: Pieter Palmers Date: Tue, 8 Nov 2005 21:37:40 -0800 Subject: [PATCH] v4l: 796: add sknet monster tv mobile card - Add SKNet Monster TV Mobile card. Signed-off-by: Pieter Palmers Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 36 +++++++++++++++++++++++++++-- drivers/media/video/saa7134/saa7134.h | 1 + 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 3bcfd88920d..c5ae8a32f75 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -74,3 +74,4 @@ 73 -> RTD Embedded Technologies VFG7330 [1435:7330] 74 -> LifeView FlyTV Platinum Mini2 [14c0:1212] 75 -> AVerMedia AVerTVHD MCE A180 [1461:1044] + 76 -> SKNet MonsterTV Mobile [1131:4ee9] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index e6e50c0a80c..17b0549f2e1 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2368,6 +2368,29 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE2, }}, }, + [SAA7134_BOARD_MONSTERTV_MOBILE] = { + .name = "SKNet MonsterTV Mobile", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 6, + .amux = LINE1, + }}, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -2773,12 +2796,18 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x1435, .subdevice = 0x7330, .driver_data = SAA7134_BOARD_RTD_VFG7330, - },{ + },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x1461, .subdevice = 0x1044, .driver_data = SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1131, + .subdevice = 0x4ee9, + .driver_data = SAA7134_BOARD_MONSTERTV_MOBILE, },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -2889,7 +2918,10 @@ int saa7134_board_init1(struct saa7134_dev *dev) /* power-up tuner chip */ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000000); - msleep(1); + case SAA7134_BOARD_MONSTERTV_MOBILE: + /* power-up tuner chip */ + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000004); break; case SAA7134_BOARD_FLYDVBTDUO: case SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS: diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 473c5dbb9b5..99bbdcf727c 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -202,6 +202,7 @@ struct saa7134_format { #define SAA7134_BOARD_RTD_VFG7330 73 #define SAA7134_BOARD_FLYTVPLATINUM_MINI2 74 #define SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180 75 +#define SAA7134_BOARD_MONSTERTV_MOBILE 76 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From c58c21c7a2ef7d1eb45231d5c1bb24d88a9666b8 Mon Sep 17 00:00:00 2001 From: "nshmyrev@yandex.ru" Date: Tue, 8 Nov 2005 21:37:41 -0800 Subject: [PATCH] v4l: 797: more intellect on clearing in bits on irq lock - More intellect on clearing in bits on irq lock. Signed-off-by: Nickolay V. Shmyrev <> Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bttv-driver.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index 504d717b115..058b923b4b1 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -3736,10 +3736,22 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) count++; if (count > 4) { - btwrite(0, BT848_INT_MASK); - printk(KERN_ERR - "bttv%d: IRQ lockup, cleared int mask [", btv->c.nr); + + if (count > 8 || !(astat & BT848_INT_GPINT)) { + btwrite(0, BT848_INT_MASK); + + printk(KERN_ERR + "bttv%d: IRQ lockup, cleared int mask [", btv->c.nr); + } else { + printk(KERN_ERR + "bttv%d: IRQ lockup, clearing GPINT from int mask [", btv->c.nr); + + btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT), + BT848_INT_MASK); + }; + bttv_print_irqbits(stat,astat); + printk("]\n"); } } -- cgit v1.2.3 From 299392bf2040fc53ebfc94363ac0abdd0f0bf619 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 8 Nov 2005 21:37:42 -0800 Subject: [PATCH] v4l: 798: this patch adds the vidioc log status to videodev2 h and adds - This patch adds the VIDIOC_LOG_STATUS to videodev2.h and adds LOG_STATUS support to tda9887.c and bttv-driver.c. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bttv-driver.c | 6 ++++++ drivers/media/video/tda9887.c | 29 +++++++++++++++++------------ include/linux/videodev2.h | 1 + 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index 058b923b4b1..f8307407e32 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -1851,6 +1851,11 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) up(&btv->lock); return 0; } + case VIDIOC_LOG_STATUS: + { + bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, 0); + return 0; + } default: return -ENOIOCTLCMD; @@ -2856,6 +2861,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_S_TUNER: case VIDIOC_G_FREQUENCY: case VIDIOC_S_FREQUENCY: + case VIDIOC_LOG_STATUS: return bttv_common_ioctls(btv,cmd,arg); default: diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 796110d4ff7..6d2914f738f 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -60,6 +60,7 @@ struct tda9887 { unsigned int pinnacle_id; unsigned int using_v4l2; unsigned int radio_mode; + unsigned char data[4]; }; struct tvnorm { @@ -575,32 +576,31 @@ static int tda9887_status(struct tda9887 *t) static int tda9887_configure(struct tda9887 *t) { - unsigned char buf[4]; int rc; - memset(buf,0,sizeof(buf)); - tda9887_set_tvnorm(t,buf); + memset(t->data,0,sizeof(t->data)); + tda9887_set_tvnorm(t,t->data); - buf[1] |= cOutputPort1Inactive; - buf[1] |= cOutputPort2Inactive; + t->data[1] |= cOutputPort1Inactive; + t->data[1] |= cOutputPort2Inactive; if (UNSET != t->pinnacle_id) { - tda9887_set_pinnacle(t,buf); + tda9887_set_pinnacle(t,t->data); } - tda9887_set_config(t,buf); - tda9887_set_insmod(t,buf); + tda9887_set_config(t,t->data); + tda9887_set_insmod(t,t->data); if (t->mode == T_STANDBY) { - buf[1] |= cForcedMuteAudioON; + t->data[1] |= cForcedMuteAudioON; } tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", - buf[1],buf[2],buf[3]); + t->data[1],t->data[2],t->data[3]); if (debug > 1) - dump_write_message(t, buf); + dump_write_message(t, t->data); - if (4 != (rc = i2c_master_send(&t->client,buf,4))) + if (4 != (rc = i2c_master_send(&t->client,t->data,4))) tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); if (debug > 2) { @@ -785,6 +785,11 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) } break; } + case VIDIOC_LOG_STATUS: + { + tda9887_info("Data bytes: b=%02x c=%02x e=%02x\n", t->data[1], t->data[2], t->data[3]); + break; + } default: /* nothing */ break; diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 89a055761be..27979003db4 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -981,6 +981,7 @@ struct v4l2_streamparm #if 1 #define VIDIOC_G_SLICED_VBI_CAP _IOR ('V', 69, struct v4l2_sliced_vbi_cap) #endif +#define VIDIOC_LOG_STATUS _IO ('V', 70) /* for compatibility, will go away some day */ #define VIDIOC_OVERLAY_OLD _IOWR ('V', 14, int) -- cgit v1.2.3 From a8900fc242406f25f315190a6d650f1d54617c2f Mon Sep 17 00:00:00 2001 From: Ray Cole Date: Tue, 8 Nov 2005 21:37:43 -0800 Subject: [PATCH] v4l: 799: don t request gpint on avermedia tv capture 98 - Don't request GPINT on Avermedia TV Capture 98. Signed-off-by: Ray Cole . Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bttv-cards.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 8544a8fa2a5..3937da065e4 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -521,6 +521,7 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .audio_hook = avermedia_tv_stereo_audio, + .no_gpioirq = 1, }, [BTTV_BOARD_VHX] = { .name = "Aimslab Video Highway Xtreme (VHX)", -- cgit v1.2.3 From 4ac97914c6c35f6bf132071c718e034d0846b9f5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:43 -0800 Subject: [PATCH] v4l: 800: whitespace cleanups - Whitespace Cleanups. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/README.cx88 | 6 +- Documentation/video4linux/bttv/Cards | 18 +- Documentation/video4linux/bttv/README | 6 +- Documentation/video4linux/bttv/Sound-FAQ | 6 +- Documentation/video4linux/lifeview.txt | 58 +-- drivers/media/common/ir-common.c | 4 +- drivers/media/video/bt832.c | 88 ++--- drivers/media/video/bt832.h | 4 +- drivers/media/video/bttv-cards.c | 260 ++++++------- drivers/media/video/bttv-driver.c | 342 ++++++++--------- drivers/media/video/bttv-gpio.c | 2 +- drivers/media/video/bttv-i2c.c | 42 +-- drivers/media/video/bttv-if.c | 4 +- drivers/media/video/bttv-risc.c | 110 +++--- drivers/media/video/bttv.h | 20 +- drivers/media/video/bttvp.h | 14 +- drivers/media/video/cx88/cx88-blackbird.c | 40 +- drivers/media/video/cx88/cx88-cards.c | 340 ++++++++--------- drivers/media/video/cx88/cx88-core.c | 40 +- drivers/media/video/cx88/cx88-dvb.c | 16 +- drivers/media/video/cx88/cx88-i2c.c | 22 +- drivers/media/video/cx88/cx88-input.c | 2 +- drivers/media/video/cx88/cx88-mpeg.c | 18 +- drivers/media/video/cx88/cx88-reg.h | 12 +- drivers/media/video/cx88/cx88-video.c | 22 +- drivers/media/video/cx88/cx88.h | 4 +- drivers/media/video/em28xx/em28xx-cards.c | 4 +- drivers/media/video/em28xx/em28xx-core.c | 28 +- drivers/media/video/em28xx/em28xx-i2c.c | 4 +- drivers/media/video/em28xx/em28xx-input.c | 52 +-- drivers/media/video/em28xx/em28xx-video.c | 10 +- drivers/media/video/em28xx/em28xx.h | 12 +- drivers/media/video/ir-kbd-gpio.c | 4 +- drivers/media/video/ir-kbd-i2c.c | 22 +- drivers/media/video/msp3400.c | 62 ++-- drivers/media/video/mt20xx.c | 204 +++++------ drivers/media/video/saa711x.c | 4 +- drivers/media/video/saa7134/saa6752hs.c | 62 ++-- drivers/media/video/saa7134/saa7134-alsa.c | 504 +++++++++++++------------- drivers/media/video/saa7134/saa7134-cards.c | 314 ++++++++-------- drivers/media/video/saa7134/saa7134-core.c | 38 +- drivers/media/video/saa7134/saa7134-dvb.c | 4 +- drivers/media/video/saa7134/saa7134-empress.c | 6 +- drivers/media/video/saa7134/saa7134-i2c.c | 14 +- drivers/media/video/saa7134/saa7134-input.c | 100 ++--- drivers/media/video/saa7134/saa7134-oss.c | 68 ++-- drivers/media/video/saa7134/saa7134-reg.h | 18 +- drivers/media/video/saa7134/saa7134-ts.c | 4 +- drivers/media/video/saa7134/saa7134-tvaudio.c | 12 +- drivers/media/video/saa7134/saa7134-video.c | 106 +++--- drivers/media/video/saa7134/saa7134.h | 12 +- drivers/media/video/tda7432.c | 16 +- drivers/media/video/tda8290.c | 2 +- drivers/media/video/tda9875.c | 56 +-- drivers/media/video/tda9887.c | 36 +- drivers/media/video/tea5767.c | 8 +- drivers/media/video/tuner-core.c | 30 +- drivers/media/video/tuner-simple.c | 106 +++--- drivers/media/video/tvaudio.c | 20 +- drivers/media/video/tveeprom.c | 20 +- drivers/media/video/tvmixer.c | 54 +-- drivers/media/video/v4l1-compat.c | 2 +- drivers/media/video/video-buf.c | 18 +- drivers/media/video/wm8775.c | 4 +- include/linux/videodev.h | 6 +- include/linux/videodev2.h | 118 +++--- include/media/audiochip.h | 14 +- include/media/tuner.h | 8 +- include/media/video-buf.h | 2 +- 69 files changed, 1844 insertions(+), 1844 deletions(-) diff --git a/Documentation/video4linux/README.cx88 b/Documentation/video4linux/README.cx88 index 0b93455bbc1..06a33a4f52f 100644 --- a/Documentation/video4linux/README.cx88 +++ b/Documentation/video4linux/README.cx88 @@ -17,9 +17,9 @@ audio - The chip specs for the on-chip TV sound decoder are next to useless :-/ - Neverless the builtin TV sound decoder starts working now, - at least for PAL-BG. Other TV norms need other code ... - FOR ANY REPORTS ON THIS PLEASE MENTION THE TV NORM YOU ARE - USING. + at least for PAL-BG. Other TV norms need other code ... + FOR ANY REPORTS ON THIS PLEASE MENTION THE TV NORM YOU ARE + USING. - Most tuner chips do provide mono sound, which may or may not be useable depending on the board design. With the Hauppauge cards it works, so there is mono sound available as fallback. diff --git a/Documentation/video4linux/bttv/Cards b/Documentation/video4linux/bttv/Cards index 8f1941ede4d..d3389655ad9 100644 --- a/Documentation/video4linux/bttv/Cards +++ b/Documentation/video4linux/bttv/Cards @@ -149,11 +149,11 @@ Lifeview Flyvideo Series: 2) There is a print on the PCB: LR25 = Flyvideo (Zoran ZR36120, SAA7110A) LR26 Rev.N = Flyvideo II (Bt848) - Rev.O = Flyvideo II (Bt878) + Rev.O = Flyvideo II (Bt878) LR37 Rev.C = Flyvideo EZ (Capture only, ZR36120 + SAA7110) LR38 Rev.A1= Flyvideo II EZ (Bt848 capture only) LR50 Rev.Q = Flyvideo 98 (w/eeprom and PCI subsystem ID) - Rev.W = Flyvideo 98 (no eeprom) + Rev.W = Flyvideo 98 (no eeprom) LR51 Rev.E = Flyvideo 98 EZ (capture only) LR90 = Flyvideo 2000 (Bt878) Flyvideo 2000S (Bt878) w/Stereo TV (Package incl. LR91 daughterboard) @@ -163,7 +163,7 @@ Lifeview Flyvideo Series: LR136 = Flyvideo 2100/3100 (Low profile, SAA7130/SAA7134) LR137 = Flyvideo DV2000/DV3000 (SAA7130/SAA7134 + IEEE1394) LR138 Rev.C= Flyvideo 2000 (SAA7130) - or Flyvideo 3000 (SAA7134) w/Stereo TV + or Flyvideo 3000 (SAA7134) w/Stereo TV These exist in variations w/FM and w/Remote sometimes denoted by suffixes "FM" and "R". 3) You have a laptop (miniPCI card): @@ -197,7 +197,7 @@ Typhoon TV card series: 50680 "TV Tuner Pal BG" (blue package)= Pixelview PV-BT878P+ (Rev 9B) 50681 "TV Tuner PCI Pal I" (variant of 50680) 50682 "TView TV/FM Tuner Pal BG" = Flyvideo 98FM (LR50 Rev.Q) - Note: The package has a picture of CPH05x (which would be a real TView) + Note: The package has a picture of CPH05x (which would be a real TView) 50683 "TV Tuner PCI SECAM" (variant of 50680) 50684 "TV Tuner Pal BG" = Pixelview 878TV(Rev.3D) 50686 "TV Tuner" = KNC1 TV Station @@ -418,9 +418,9 @@ Lifetec/Medion/Tevion/Aldi -------------------------- LT9306/MD9306 = CPH061 LT9415/MD9415 = LR90 Rev.F or Rev.G - MD9592 = Avermedia TVphone98 (PCI_ID=1461:0003), PCB-Rev=M168II-B (w/TDA9873H) - MD9717 = KNC One (Rev D4, saa7134, FM1216 MK2 tuner) - MD5044 = KNC One (Rev D4, saa7134, FM1216ME MK3 tuner) + MD9592 = Avermedia TVphone98 (PCI_ID=1461:0003), PCB-Rev=M168II-B (w/TDA9873H) + MD9717 = KNC One (Rev D4, saa7134, FM1216 MK2 tuner) + MD5044 = KNC One (Rev D4, saa7134, FM1216ME MK3 tuner) Modular Technologies (www.modulartech.com) UK --------------------------------------------- @@ -453,10 +453,10 @@ Technisat Discos ADR PC-Karte ISA (no TV!) Discos ADR PC-Karte PCI (probably no TV?) Techni-PC-Sat (Sat. analog) - Rev 1.2 (zr36120, vpx3220, stv0030, saa5246, BSJE3-494A) + Rev 1.2 (zr36120, vpx3220, stv0030, saa5246, BSJE3-494A) Mediafocus I (zr36120/zr36125, drp3510, Sat. analog + ADR Radio) Mediafocus II (saa7146, Sat. analog) - SatADR Rev 2.1 (saa7146a, saa7113h, stv0056a, msp3400c, drp3510a, BSKE3-307A) + SatADR Rev 2.1 (saa7146a, saa7113h, stv0056a, msp3400c, drp3510a, BSKE3-307A) SkyStar 1 DVB (AV7110) = Technotrend Premium SkyStar 2 DVB (B2C2) (=Sky2PC) diff --git a/Documentation/video4linux/bttv/README b/Documentation/video4linux/bttv/README index a72f4c94fb0..7ca2154c2bf 100644 --- a/Documentation/video4linux/bttv/README +++ b/Documentation/video4linux/bttv/README @@ -42,9 +42,9 @@ bttv uses the PCI Subsystem ID to autodetect the card type. lspci lists the Subsystem ID in the second line, looks like this: 00:0a.0 Multimedia video controller: Brooktree Corporation Bt878 (rev 02) - Subsystem: Hauppauge computer works Inc. WinTV/GO - Flags: bus master, medium devsel, latency 32, IRQ 5 - Memory at e2000000 (32-bit, prefetchable) [size=4K] + Subsystem: Hauppauge computer works Inc. WinTV/GO + Flags: bus master, medium devsel, latency 32, IRQ 5 + Memory at e2000000 (32-bit, prefetchable) [size=4K] only bt878-based cards can have a subsystem ID (which does not mean that every card really has one). bt848 cards can't have a Subsystem diff --git a/Documentation/video4linux/bttv/Sound-FAQ b/Documentation/video4linux/bttv/Sound-FAQ index 5c982249203..1e6328f9108 100644 --- a/Documentation/video4linux/bttv/Sound-FAQ +++ b/Documentation/video4linux/bttv/Sound-FAQ @@ -61,8 +61,8 @@ line for your board. The important fields are these two: struct tvcard { [ ... ] - u32 gpiomask; - u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */ + u32 gpiomask; + u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */ }; gpiomask specifies which pins are used to control the audio mux chip. @@ -126,7 +126,7 @@ muxsel - video mux, input->registervalue mapping pll - same as pll= insmod option tuner_type - same as tuner= insmod option *_modulename - hint whenever some card needs this or that audio - module loaded to work properly. + module loaded to work properly. has_radio - whenever this TV card has a radio tuner. no_msp34xx - "1" disables loading of msp3400.o module no_tda9875 - "1" disables loading of tda9875.o module diff --git a/Documentation/video4linux/lifeview.txt b/Documentation/video4linux/lifeview.txt index b07ea79c2b7..f66320bd7b6 100644 --- a/Documentation/video4linux/lifeview.txt +++ b/Documentation/video4linux/lifeview.txt @@ -10,33 +10,33 @@ bt878: ------------------------------------------------------------------------------ saa7134: - /* LifeView FlyTV Platinum FM (LR214WF) */ - /* "Peter Missel */ - .name = "LifeView FlyTV Platinum FM", - /* GP27 MDT2005 PB4 pin 10 */ - /* GP26 MDT2005 PB3 pin 9 */ - /* GP25 MDT2005 PB2 pin 8 */ - /* GP23 MDT2005 PB1 pin 7 */ - /* GP22 MDT2005 PB0 pin 6 */ - /* GP21 MDT2005 PB5 pin 11 */ - /* GP20 MDT2005 PB6 pin 12 */ - /* GP19 MDT2005 PB7 pin 13 */ - /* nc MDT2005 PA3 pin 2 */ - /* Remote MDT2005 PA2 pin 1 */ - /* GP18 MDT2005 PA1 pin 18 */ - /* nc MDT2005 PA0 pin 17 strap low */ + /* LifeView FlyTV Platinum FM (LR214WF) */ + /* "Peter Missel */ + .name = "LifeView FlyTV Platinum FM", + /* GP27 MDT2005 PB4 pin 10 */ + /* GP26 MDT2005 PB3 pin 9 */ + /* GP25 MDT2005 PB2 pin 8 */ + /* GP23 MDT2005 PB1 pin 7 */ + /* GP22 MDT2005 PB0 pin 6 */ + /* GP21 MDT2005 PB5 pin 11 */ + /* GP20 MDT2005 PB6 pin 12 */ + /* GP19 MDT2005 PB7 pin 13 */ + /* nc MDT2005 PA3 pin 2 */ + /* Remote MDT2005 PA2 pin 1 */ + /* GP18 MDT2005 PA1 pin 18 */ + /* nc MDT2005 PA0 pin 17 strap low */ - /* GP17 Strap "GP7"=High */ - /* GP16 Strap "GP6"=High - 0=Radio 1=TV - Drives SA630D ENCH1 and HEF4052 A1 pins - to do FM radio through SIF input */ - /* GP15 nc */ - /* GP14 nc */ - /* GP13 nc */ - /* GP12 Strap "GP5" = High */ - /* GP11 Strap "GP4" = High */ - /* GP10 Strap "GP3" = High */ - /* GP09 Strap "GP2" = Low */ - /* GP08 Strap "GP1" = Low */ - /* GP07.00 nc */ + /* GP17 Strap "GP7"=High */ + /* GP16 Strap "GP6"=High + 0=Radio 1=TV + Drives SA630D ENCH1 and HEF4052 A1 pins + to do FM radio through SIF input */ + /* GP15 nc */ + /* GP14 nc */ + /* GP13 nc */ + /* GP12 Strap "GP5" = High */ + /* GP11 Strap "GP4" = High */ + /* GP10 Strap "GP3" = High */ + /* GP09 Strap "GP2" = Low */ + /* GP08 Strap "GP1" = Low */ + /* GP07.00 nc */ diff --git a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c index 31fccb4f05d..4b71fd6f7ae 100644 --- a/drivers/media/common/ir-common.c +++ b/drivers/media/common/ir-common.c @@ -116,7 +116,7 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { [ 46 ] = KEY_BLUE, [ 24 ] = KEY_KPPLUS, /* fine tune + */ [ 25 ] = KEY_KPMINUS, /* fine tune - */ - [ 33 ] = KEY_KPDOT, + [ 33 ] = KEY_KPDOT, [ 19 ] = KEY_KPENTER, [ 34 ] = KEY_BACK, [ 35 ] = KEY_PLAYPAUSE, @@ -239,7 +239,7 @@ static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) dprintk(1,"%s: key event code=%d down=%d\n", dev->name,ir->keycode,ir->keypressed); input_report_key(dev,ir->keycode,ir->keypressed); - input_sync(dev); + input_sync(dev); } /* -------------------------------------------------------------------------- */ diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c index 76c1b63ebdf..3e42493a4e0 100644 --- a/drivers/media/video/bt832.c +++ b/drivers/media/video/bt832.c @@ -54,36 +54,36 @@ static struct i2c_driver driver; static struct i2c_client client_template; struct bt832 { - struct i2c_client client; + struct i2c_client client; }; int bt832_hexdump(struct i2c_client *i2c_client_s, unsigned char *buf) { int i,rc; buf[0]=0x80; // start at register 0 with auto-increment - if (1 != (rc = i2c_master_send(i2c_client_s,buf,1))) - printk("bt832: i2c i/o error: rc == %d (should be 1)\n",rc); + if (1 != (rc = i2c_master_send(i2c_client_s,buf,1))) + printk("bt832: i2c i/o error: rc == %d (should be 1)\n",rc); - for(i=0;i<65;i++) - buf[i]=0; - if (65 != (rc=i2c_master_recv(i2c_client_s,buf,65))) - printk("bt832: i2c i/o error: rc == %d (should be 65)\n",rc); + for(i=0;i<65;i++) + buf[i]=0; + if (65 != (rc=i2c_master_recv(i2c_client_s,buf,65))) + printk("bt832: i2c i/o error: rc == %d (should be 65)\n",rc); - // Note: On READ the first byte is the current index - // (e.g. 0x80, what we just wrote) + // Note: On READ the first byte is the current index + // (e.g. 0x80, what we just wrote) - if(1) { - int i; - printk("BT832 hexdump:\n"); - for(i=1;i<65;i++) { + if(1) { + int i; + printk("BT832 hexdump:\n"); + for(i=1;i<65;i++) { if(i!=1) { if(((i-1)%8)==0) printk(" "); - if(((i-1)%16)==0) printk("\n"); + if(((i-1)%16)==0) printk("\n"); } - printk(" %02x",buf[i]); - } - printk("\n"); - } + printk(" %02x",buf[i]); + } + printk("\n"); + } return 0; } @@ -102,13 +102,13 @@ int bt832_init(struct i2c_client *i2c_client_s) return 0; } - printk("Write 0 tp VPSTATUS\n"); - buf[0]=BT832_VP_STATUS; // Reg.52 - buf[1]= 0x00; - if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - printk("bt832: i2c i/o error VPS: rc == %d (should be 2)\n",rc); + printk("Write 0 tp VPSTATUS\n"); + buf[0]=BT832_VP_STATUS; // Reg.52 + buf[1]= 0x00; + if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) + printk("bt832: i2c i/o error VPS: rc == %d (should be 2)\n",rc); - bt832_hexdump(i2c_client_s,buf); + bt832_hexdump(i2c_client_s,buf); // Leave low power mode: @@ -116,17 +116,17 @@ int bt832_init(struct i2c_client *i2c_client_s) buf[0]=BT832_CAM_SETUP0; //0x39 57 buf[1]=0x08; if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - printk("bt832: i2c i/o error LLPM: rc == %d (should be 2)\n",rc); + printk("bt832: i2c i/o error LLPM: rc == %d (should be 2)\n",rc); - bt832_hexdump(i2c_client_s,buf); + bt832_hexdump(i2c_client_s,buf); printk("Write 0 tp VPSTATUS\n"); - buf[0]=BT832_VP_STATUS; // Reg.52 - buf[1]= 0x00; - if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - printk("bt832: i2c i/o error VPS: rc == %d (should be 2)\n",rc); + buf[0]=BT832_VP_STATUS; // Reg.52 + buf[1]= 0x00; + if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) + printk("bt832: i2c i/o error VPS: rc == %d (should be 2)\n",rc); - bt832_hexdump(i2c_client_s,buf); + bt832_hexdump(i2c_client_s,buf); // Enable Output @@ -134,22 +134,22 @@ int bt832_init(struct i2c_client *i2c_client_s) buf[0]=BT832_VP_CONTROL1; // Reg.40 buf[1]= 0x27 & (~0x01); // Default | !skip if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - printk("bt832: i2c i/o error EO: rc == %d (should be 2)\n",rc); + printk("bt832: i2c i/o error EO: rc == %d (should be 2)\n",rc); - bt832_hexdump(i2c_client_s,buf); + bt832_hexdump(i2c_client_s,buf); // for testing (even works when no camera attached) printk("bt832: *** Generate NTSC M Bars *****\n"); buf[0]=BT832_VP_TESTCONTROL0; // Reg. 42 buf[1]=3; // Generate NTSC System M bars, Generate Frame timing internally - if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - printk("bt832: i2c i/o error MBAR: rc == %d (should be 2)\n",rc); + if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) + printk("bt832: i2c i/o error MBAR: rc == %d (should be 2)\n",rc); printk("Bt832: Camera Present: %s\n", (buf[1+BT832_CAM_STATUS] & BT832_56_CAMERA_PRESENT) ? "yes":"no"); - bt832_hexdump(i2c_client_s,buf); + bt832_hexdump(i2c_client_s,buf); kfree(buf); return 1; } @@ -162,17 +162,17 @@ static int bt832_attach(struct i2c_adapter *adap, int addr, int kind) printk("bt832_attach\n"); - client_template.adapter = adap; - client_template.addr = addr; + client_template.adapter = adap; + client_template.addr = addr; - printk("bt832: chip found @ 0x%x\n", addr<<1); + printk("bt832: chip found @ 0x%x\n", addr<<1); - if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL))) - return -ENOMEM; + if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL))) + return -ENOMEM; memset(t,0,sizeof(*t)); t->client = client_template; - i2c_set_clientdata(&t->client, t); - i2c_attach_client(&t->client); + i2c_set_clientdata(&t->client, t); + i2c_attach_client(&t->client); if(! bt832_init(&t->client)) { bt832_detach(&t->client); @@ -211,7 +211,7 @@ bt832_command(struct i2c_client *client, unsigned int cmd, void *arg) printk("bt832: command %x\n",cmd); - switch (cmd) { + switch (cmd) { case BT832_HEXDUMP: { unsigned char *buf; buf=kmalloc(65,GFP_KERNEL); diff --git a/drivers/media/video/bt832.h b/drivers/media/video/bt832.h index 9b6a8d2c96b..1ce8fa71f7d 100644 --- a/drivers/media/video/bt832.h +++ b/drivers/media/video/bt832.h @@ -233,8 +233,8 @@ SetInterlaceMode( spec.interlace ); /* from web: Video Sampling Digital video is a sampled form of analog video. The most common sampling schemes in use today are: - Pixel Clock Horiz Horiz Vert - Rate Total Active + Pixel Clock Horiz Horiz Vert + Rate Total Active NTSC square pixel 12.27 MHz 780 640 525 NTSC CCIR-601 13.5 MHz 858 720 525 NTSC 4FSc 14.32 MHz 910 768 525 diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 3937da065e4..92bb515fbe4 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -6,7 +6,7 @@ like the big tvcards array for the most part Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) (c) 1999-2001 Gerd Knorr This program is free software; you can redistribute it and/or modify @@ -163,10 +163,10 @@ static struct CARD { { 0x6609107d, BTTV_BOARD_WINFAST2000, "Leadtek TV 2000 XP" }, { 0x263610b4, BTTV_BOARD_STB2, "STB TV PCI FM, Gateway P/N 6000704" }, { 0x264510b4, BTTV_BOARD_STB2, "STB TV PCI FM, Gateway P/N 6000704" }, - { 0x402010fc, BTTV_BOARD_GVBCTV3PCI, "I-O Data Co. GV-BCTV3/PCI" }, + { 0x402010fc, BTTV_BOARD_GVBCTV3PCI, "I-O Data Co. GV-BCTV3/PCI" }, { 0x405010fc, BTTV_BOARD_GVBCTV4PCI, "I-O Data Co. GV-BCTV4/PCI" }, { 0x407010fc, BTTV_BOARD_GVBCTV5PCI, "I-O Data Co. GV-BCTV5/PCI" }, - { 0xd01810fc, BTTV_BOARD_GVBCTV5PCI, "I-O Data Co. GV-BCTV5/PCI" }, + { 0xd01810fc, BTTV_BOARD_GVBCTV5PCI, "I-O Data Co. GV-BCTV5/PCI" }, { 0x001211bd, BTTV_BOARD_PINNACLE, "Pinnacle PCTV" }, /* some cards ship with byteswapped IDs ... */ @@ -277,7 +277,7 @@ static struct CARD { { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV"}, { 0x82b2aa6a, BTTV_BOARD_SIMUS_GVC1100, "SIMUS GVC1100" }, { 0x146caa0c, BTTV_BOARD_PV951, "ituner spectra8" }, - { 0x200a1295, BTTV_BOARD_PXC200, "ImageNation PXC200A" }, + { 0x200a1295, BTTV_BOARD_PXC200, "ImageNation PXC200A" }, { 0x40111554, BTTV_BOARD_PV_BT878P_9B, "Prolink Pixelview PV-BT" }, { 0x17de0a01, BTTV_BOARD_KWORLD, "Mecer TV/FM/Video Tuner" }, @@ -1346,17 +1346,17 @@ struct tvcard bttv_tvcards[] = { }, [BTTV_BOARD_GMV1] = { /* Adrian Cox c.type = type; @@ -2929,7 +2929,7 @@ static void flyvideo_gpio(struct bttv *btv) switch(ttype) { case 0x0: tuner=2; /* NTSC, e.g. TPI8NSR11P */ break; - case 0x2: tuner=39;/* LG NTSC (newer TAPC series) TAPC-H701P */ + case 0x2: tuner=39;/* LG NTSC (newer TAPC series) TAPC-H701P */ break; case 0x4: tuner=5; /* Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216 */ break; @@ -2945,7 +2945,7 @@ static void flyvideo_gpio(struct bttv *btv) has_radio = gpio & 0x400000; /* unknown 0x200000; * unknown2 0x100000; */ - is_capture_only = !(gpio & 0x008000); /* GPIO15 */ + is_capture_only = !(gpio & 0x008000); /* GPIO15 */ has_tda9820_tda9821 = !(gpio & 0x004000); is_lr90 = !(gpio & 0x002000); /* else LR26/LR50 (LR38/LR51 f. capture only) */ /* @@ -2982,7 +2982,7 @@ static void miro_pinnacle_gpio(struct bttv *btv) char *info; gpio_inout(0xffffff, 0); - gpio = gpio_read(); + gpio = gpio_read(); id = ((gpio>>10) & 63) -1; msp = bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx"); if (id < 32) { @@ -3093,7 +3093,7 @@ static void eagle_muxsel(struct bttv *btv, unsigned int input) static void gvc1100_muxsel(struct bttv *btv, unsigned int input) { - static const int masks[] = {0x30, 0x01, 0x12, 0x23}; + static const int masks[] = {0x30, 0x01, 0x12, 0x23}; gpio_write(masks[input%4]); } @@ -3161,10 +3161,10 @@ void __devinit bttv_init_card1(struct bttv *btv) switch (btv->c.type) { case BTTV_BOARD_HAUPPAUGE: case BTTV_BOARD_HAUPPAUGE878: - boot_msp34xx(btv,5); + boot_msp34xx(btv,5); break; case BTTV_BOARD_VOODOOTV_FM: - boot_msp34xx(btv,20); + boot_msp34xx(btv,20); break; case BTTV_BOARD_AVERMEDIA98: boot_msp34xx(btv,11); @@ -3192,7 +3192,7 @@ void __devinit bttv_init_card2(struct bttv *btv) int tda9887; int addr=ADDR_UNSET, radio_addr=ADDR_UNSET; - btv->tuner_type = -1; + btv->tuner_type = -1; if (BTTV_BOARD_UNKNOWN == btv->c.type) { bttv_readee(btv,eeprom_data,0xa0); @@ -3225,7 +3225,7 @@ void __devinit bttv_init_card2(struct bttv *btv) case BTTV_BOARD_HAUPPAUGEPVR: /* pick up some config infos from the eeprom */ bttv_readee(btv,eeprom_data,0xa0); - hauppauge_eeprom(btv); + hauppauge_eeprom(btv); break; case BTTV_BOARD_AVERMEDIA98: case BTTV_BOARD_AVPHONE98: @@ -3258,7 +3258,7 @@ void __devinit bttv_init_card2(struct bttv *btv) } break; case BTTV_BOARD_STB2: - if (btv->cardid == 0x3060121a) { + if (btv->cardid == 0x3060121a) { /* Fix up entry for 3DFX VoodooTV 100, which is an OEM STB card variant. */ btv->has_radio=0; @@ -3277,7 +3277,7 @@ void __devinit bttv_init_card2(struct bttv *btv) case BTTV_BOARD_OSPREY540: case BTTV_BOARD_OSPREY2000: bttv_readee(btv,eeprom_data,0xa0); - osprey_eeprom(btv); + osprey_eeprom(btv); break; case BTTV_BOARD_IDS_EAGLE: init_ids_eagle(btv); @@ -3298,7 +3298,7 @@ void __devinit bttv_init_card2(struct bttv *btv) } /* pll configuration */ - if (!(btv->id==848 && btv->revision==0x11)) { + if (!(btv->id==848 && btv->revision==0x11)) { /* defaults from card list */ if (PLL_28 == bttv_tvcards[btv->c.type].pll) { btv->pll.pll_ifreq=28636363; @@ -3309,26 +3309,26 @@ void __devinit bttv_init_card2(struct bttv *btv) btv->pll.pll_crystal=BT848_IFORM_XT1; } /* insmod options can override */ - switch (pll[btv->c.nr]) { - case 0: /* none */ + switch (pll[btv->c.nr]) { + case 0: /* none */ btv->pll.pll_crystal = 0; btv->pll.pll_ifreq = 0; btv->pll.pll_ofreq = 0; - break; - case 1: /* 28 MHz */ + break; + case 1: /* 28 MHz */ case 28: - btv->pll.pll_ifreq = 28636363; + btv->pll.pll_ifreq = 28636363; btv->pll.pll_ofreq = 0; - btv->pll.pll_crystal = BT848_IFORM_XT0; - break; - case 2: /* 35 MHz */ + btv->pll.pll_crystal = BT848_IFORM_XT0; + break; + case 2: /* 35 MHz */ case 35: - btv->pll.pll_ifreq = 35468950; + btv->pll.pll_ifreq = 35468950; btv->pll.pll_ofreq = 0; - btv->pll.pll_crystal = BT848_IFORM_XT1; - break; - } - } + btv->pll.pll_crystal = BT848_IFORM_XT1; + break; + } + } btv->pll.pll_current = -1; /* tuner configuration (from card list / autodetect / insmod option) */ @@ -3340,7 +3340,7 @@ void __devinit bttv_init_card2(struct bttv *btv) if (UNSET != bttv_tvcards[btv->c.type].tuner_type) if(UNSET == btv->tuner_type) - btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type; + btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type; if (UNSET != tuner[btv->c.nr]) btv->tuner_type = tuner[btv->c.nr]; printk("bttv%d: using tuner=%d\n",btv->c.nr,btv->tuner_type); @@ -3348,14 +3348,14 @@ void __devinit bttv_init_card2(struct bttv *btv) bttv_call_i2c_clients(btv, AUDC_CONFIG_PINNACLE, &btv->pinnacle_id); if (btv->tuner_type != UNSET) { - struct tuner_setup tun_setup; + struct tuner_setup tun_setup; - tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; + tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; tun_setup.type = btv->tuner_type; tun_setup.addr = addr; if (addr == radio_addr) - tun_setup.mode_mask = T_RADIO; + tun_setup.mode_mask = T_RADIO; bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup); } @@ -3433,11 +3433,11 @@ static void modtec_eeprom(struct bttv *btv) } else if (strncmp(&(eeprom_data[0x1e]),"Alps TSBB5",10) ==0) { btv->tuner_type=TUNER_ALPS_TSBB5_PAL_I; printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n", - btv->c.nr,&eeprom_data[0x1e]); - } else if (strncmp(&(eeprom_data[0x1e]),"Philips FM1246",14) ==0) { - btv->tuner_type=TUNER_PHILIPS_NTSC; - printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n", - btv->c.nr,&eeprom_data[0x1e]); + btv->c.nr,&eeprom_data[0x1e]); + } else if (strncmp(&(eeprom_data[0x1e]),"Philips FM1246",14) ==0) { + btv->tuner_type=TUNER_PHILIPS_NTSC; + printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n", + btv->c.nr,&eeprom_data[0x1e]); } else { printk("bttv%d: Modtec: Unknown TunerString: %s\n", btv->c.nr,&eeprom_data[0x1e]); @@ -3502,7 +3502,7 @@ static int terratec_active_radio_upgrade(struct bttv *btv) static int __devinit pvr_altera_load(struct bttv *btv, u8 *micro, u32 microlen) { u32 n; - u8 bits; + u8 bits; int i; gpio_inout(0xffffff,BTTV_ALT_DATA|BTTV_ALT_DCLK|BTTV_ALT_NCONFIG); @@ -3538,19 +3538,19 @@ static int __devinit pvr_altera_load(struct bttv *btv, u8 *micro, u32 microlen) static int __devinit pvr_boot(struct bttv *btv) { - const struct firmware *fw_entry; + const struct firmware *fw_entry; int rc; rc = request_firmware(&fw_entry, "hcwamc.rbf", &btv->c.pci->dev); if (rc != 0) { printk(KERN_WARNING "bttv%d: no altera firmware [via hotplug]\n", btv->c.nr); - return rc; - } + return rc; + } rc = pvr_altera_load(btv, fw_entry->data, fw_entry->size); printk(KERN_INFO "bttv%d: altera firmware upload %s\n", btv->c.nr, (rc < 0) ? "failed" : "ok"); - release_firmware(fw_entry); + release_firmware(fw_entry); return rc; } @@ -3564,33 +3564,33 @@ static void __devinit osprey_eeprom(struct bttv *btv) unsigned long serial = 0; if (btv->c.type == 0) { - /* this might be an antique... check for MMAC label in eeprom */ - if ((ee[0]=='M') && (ee[1]=='M') && (ee[2]=='A') && (ee[3]=='C')) { - unsigned char checksum = 0; - for (i =0; i<21; i++) + /* this might be an antique... check for MMAC label in eeprom */ + if ((ee[0]=='M') && (ee[1]=='M') && (ee[2]=='A') && (ee[3]=='C')) { + unsigned char checksum = 0; + for (i =0; i<21; i++) checksum += ee[i]; - if (checksum != ee[21]) + if (checksum != ee[21]) return; btv->c.type = BTTV_BOARD_OSPREY1x0_848; for (i = 12; i < 21; i++) serial *= 10, serial += ee[i] - '0'; - } + } } else { unsigned short type; - int offset = 4*16; - - for(; offset < 8*16; offset += 16) { - unsigned short checksum = 0; - /* verify the checksum */ - for(i = 0; i<14; i++) checksum += ee[i+offset]; - checksum = ~checksum; /* no idea why */ - if ((((checksum>>8)&0x0FF) == ee[offset+14]) && - ((checksum & 0x0FF) == ee[offset+15])) { - break; - } - } - - if (offset >= 8*16) + int offset = 4*16; + + for(; offset < 8*16; offset += 16) { + unsigned short checksum = 0; + /* verify the checksum */ + for(i = 0; i<14; i++) checksum += ee[i+offset]; + checksum = ~checksum; /* no idea why */ + if ((((checksum>>8)&0x0FF) == ee[offset+14]) && + ((checksum & 0x0FF) == ee[offset+15])) { + break; + } + } + + if (offset >= 8*16) return; /* found a valid descriptor */ @@ -3606,7 +3606,7 @@ static void __devinit osprey_eeprom(struct bttv *btv) btv->c.type = BTTV_BOARD_OSPREY101_848; break; - /* 878 based */ + /* 878 based */ case 0x0012: case 0x0013: btv->c.type = BTTV_BOARD_OSPREY1x0; @@ -3662,27 +3662,27 @@ static void __devinit osprey_eeprom(struct bttv *btv) /* AVermedia specific stuff, from bktr_card.c */ static int tuner_0_table[] = { - TUNER_PHILIPS_NTSC, TUNER_PHILIPS_PAL /* PAL-BG*/, - TUNER_PHILIPS_PAL, TUNER_PHILIPS_PAL /* PAL-I*/, - TUNER_PHILIPS_PAL, TUNER_PHILIPS_PAL, - TUNER_PHILIPS_SECAM, TUNER_PHILIPS_SECAM, - TUNER_PHILIPS_SECAM, TUNER_PHILIPS_PAL, + TUNER_PHILIPS_NTSC, TUNER_PHILIPS_PAL /* PAL-BG*/, + TUNER_PHILIPS_PAL, TUNER_PHILIPS_PAL /* PAL-I*/, + TUNER_PHILIPS_PAL, TUNER_PHILIPS_PAL, + TUNER_PHILIPS_SECAM, TUNER_PHILIPS_SECAM, + TUNER_PHILIPS_SECAM, TUNER_PHILIPS_PAL, TUNER_PHILIPS_FM1216ME_MK3 }; static int tuner_1_table[] = { - TUNER_TEMIC_NTSC, TUNER_TEMIC_PAL, + TUNER_TEMIC_NTSC, TUNER_TEMIC_PAL, TUNER_TEMIC_PAL, TUNER_TEMIC_PAL, TUNER_TEMIC_PAL, TUNER_TEMIC_PAL, - TUNER_TEMIC_4012FY5, TUNER_TEMIC_4012FY5, /* TUNER_TEMIC_SECAM */ - TUNER_TEMIC_4012FY5, TUNER_TEMIC_PAL}; + TUNER_TEMIC_4012FY5, TUNER_TEMIC_4012FY5, /* TUNER_TEMIC_SECAM */ + TUNER_TEMIC_4012FY5, TUNER_TEMIC_PAL}; static void __devinit avermedia_eeprom(struct bttv *btv) { - int tuner_make,tuner_tv_fm,tuner_format,tuner=0; + int tuner_make,tuner_tv_fm,tuner_format,tuner=0; tuner_make = (eeprom_data[0x41] & 0x7); - tuner_tv_fm = (eeprom_data[0x41] & 0x18) >> 3; - tuner_format = (eeprom_data[0x42] & 0xf0) >> 4; + tuner_tv_fm = (eeprom_data[0x41] & 0x18) >> 3; + tuner_format = (eeprom_data[0x42] & 0xf0) >> 4; btv->has_remote = (eeprom_data[0x42] & 0x01); if (tuner_make == 0 || tuner_make == 2) @@ -3718,8 +3718,8 @@ void bttv_tda9880_setnorm(struct bttv *btv, int norm) dprintk("bttv_tda9880_setnorm to NTSC\n"); } else { - bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[0]=0x947fff; - bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[4]=0x947fff; + bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[0]=0x947fff; + bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[4]=0x947fff; dprintk("bttv_tda9880_setnorm to PAL\n"); } /* set GPIO according */ @@ -3741,7 +3741,7 @@ static void __devinit boot_msp34xx(struct bttv *btv, int pin) gpio_inout(mask,mask); gpio_bits(mask,0); - udelay(2500); + udelay(2500); gpio_bits(mask,mask); if (bttv_gpio) @@ -3817,7 +3817,7 @@ static void __devinit init_PXC200(struct bttv *btv) udelay(10); gpio_write(1<<2); - for (i = 0; i < ARRAY_SIZE(vals); i++) { + for (i = 0; i < ARRAY_SIZE(vals); i++) { tmp=bttv_I2CWrite(btv,0x1E,0,vals[i],1); if (tmp != -1) { printk(KERN_INFO @@ -4260,30 +4260,30 @@ avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v, int set) static void lt9415_audio(struct bttv *btv, struct video_audio *v, int set) { - int val = 0; + int val = 0; - if (gpio_read() & 0x4000) { + if (gpio_read() & 0x4000) { v->mode = VIDEO_SOUND_MONO; return; } - if (set) { - if (v->mode & VIDEO_SOUND_LANG2) /* A2 SAP */ - val = 0x0080; + if (set) { + if (v->mode & VIDEO_SOUND_LANG2) /* A2 SAP */ + val = 0x0080; if (v->mode & VIDEO_SOUND_STEREO) /* A2 stereo */ - val = 0x0880; - if ((v->mode & VIDEO_SOUND_LANG1) || + val = 0x0880; + if ((v->mode & VIDEO_SOUND_LANG1) || (v->mode & VIDEO_SOUND_MONO)) val = 0; gpio_bits(0x0880, val); - if (bttv_gpio) - bttv_gpio_tracking(btv,"lt9415"); - } else { + if (bttv_gpio) + bttv_gpio_tracking(btv,"lt9415"); + } else { /* autodetect doesn't work with this card :-( */ - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - return; - } + return; + } } /* TDA9821 on TerraTV+ Bt848, Bt878 */ @@ -4406,26 +4406,26 @@ fv2000s_audio(struct bttv *btv, struct video_audio *v, int set) static void windvr_audio(struct bttv *btv, struct video_audio *v, int set) { - unsigned long val = 0; - - if (set) { - if (v->mode & VIDEO_SOUND_MONO) - val = 0x040000; - if (v->mode & VIDEO_SOUND_LANG1) - val = 0; - if (v->mode & VIDEO_SOUND_LANG2) - val = 0x100000; - if (v->mode & VIDEO_SOUND_STEREO) - val = 0; - if (val) { + unsigned long val = 0; + + if (set) { + if (v->mode & VIDEO_SOUND_MONO) + val = 0x040000; + if (v->mode & VIDEO_SOUND_LANG1) + val = 0; + if (v->mode & VIDEO_SOUND_LANG2) + val = 0x100000; + if (v->mode & VIDEO_SOUND_STEREO) + val = 0; + if (val) { gpio_bits(0x140000, val); - if (bttv_gpio) - bttv_gpio_tracking(btv,"windvr"); - } - } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - } + if (bttv_gpio) + bttv_gpio_tracking(btv,"windvr"); + } + } else { + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + } } /* @@ -4668,10 +4668,10 @@ static void kodicom4400r_init(struct bttv *btv) static void xguard_muxsel(struct bttv *btv, unsigned int input) { static const int masks[] = { - ENB0, ENB0|IN00, ENB0|IN10, ENB0|IN00|IN10, - ENA0, ENA0|IN00, ENA0|IN10, ENA0|IN00|IN10, - ENB1, ENB1|IN01, ENB1|IN11, ENB1|IN01|IN11, - ENA1, ENA1|IN01, ENA1|IN11, ENA1|IN01|IN11, + ENB0, ENB0|IN00, ENB0|IN10, ENB0|IN00|IN10, + ENA0, ENA0|IN00, ENA0|IN10, ENA0|IN00|IN10, + ENB1, ENB1|IN01, ENB1|IN11, ENB1|IN01|IN11, + ENA1, ENA1|IN01, ENA1|IN11, ENA1|IN01|IN11, }; gpio_write(masks[input%16]); } @@ -4776,10 +4776,10 @@ static void ivc120_muxsel(struct bttv *btv, unsigned int input) static void PXC200_muxsel(struct bttv *btv, unsigned int input) { - int rc; + int rc; long mux; int bitmask; - unsigned char buf[2]; + unsigned char buf[2]; /* Read PIC config to determine if this is a PXC200F */ /* PX_I2C_CMD_CFG*/ @@ -4809,14 +4809,14 @@ static void PXC200_muxsel(struct bttv *btv, unsigned int input) /* bitmask=0x30f; */ bitmask=0x302; /* check whether we have a PXC200A */ - if (btv->cardid == PX_PXC200A_CARDID) { + if (btv->cardid == PX_PXC200A_CARDID) { bitmask ^= 0x180; /* use 7 and 9, not 8 and 9 */ bitmask |= 7<<4; /* the DAC */ } btwrite(bitmask, BT848_GPIO_OUT_EN); bitmask = btread(BT848_GPIO_DATA); - if (btv->cardid == PX_PXC200A_CARDID) + if (btv->cardid == PX_PXC200A_CARDID) bitmask = (bitmask & ~0x280) | ((mux & 2) << 8) | ((mux & 1) << 7); else /* older device */ bitmask = (bitmask & ~0x300) | ((mux & 3) << 8); @@ -4829,7 +4829,7 @@ static void PXC200_muxsel(struct bttv *btv, unsigned int input) * * needed because bttv-driver sets mux before calling this function */ - if (btv->cardid == PX_PXC200A_CARDID) + if (btv->cardid == PX_PXC200A_CARDID) btaor(2<<5, ~BT848_IFORM_MUXSEL, BT848_IFORM); else /* older device */ btand(~BT848_IFORM_MUXSEL,BT848_IFORM); @@ -4875,7 +4875,7 @@ void __devinit bttv_check_chipset(void) printk(KERN_INFO "bttv: pci latency fixup [%d]\n",latency); while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, dev))) { - unsigned char b; + unsigned char b; pci_read_config_byte(dev, 0x53, &b); if (bttv_debug) printk(KERN_INFO "bttv: Host bridge: 82441FX Natoma, " @@ -4885,7 +4885,7 @@ void __devinit bttv_check_chipset(void) int __devinit bttv_handle_chipset(struct bttv *btv) { - unsigned char command; + unsigned char command; if (!triton1 && !vsfx && UNSET == latency) return 0; @@ -4906,13 +4906,13 @@ int __devinit bttv_handle_chipset(struct bttv *btv) btv->triton1 = BT848_INT_ETBF; } else { /* bt878 has a bit in the pci config space for it */ - pci_read_config_byte(btv->c.pci, BT878_DEVCTRL, &command); + pci_read_config_byte(btv->c.pci, BT878_DEVCTRL, &command); if (triton1) command |= BT878_EN_TBFX; if (vsfx) command |= BT878_EN_VSFX; - pci_write_config_byte(btv->c.pci, BT878_DEVCTRL, command); - } + pci_write_config_byte(btv->c.pci, BT878_DEVCTRL, command); + } if (UNSET != latency) pci_write_config_byte(btv->c.pci, PCI_LATENCY_TIMER, latency); return 0; diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index f8307407e32..0005741d551 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -3,7 +3,7 @@ bttv - Bt848 frame grabber driver Copyright (C) 1996,97,98 Ralph Metzler - & Marcus Metzler + & Marcus Metzler (c) 1999-2002 Gerd Knorr some v4l2 code lines are taken from Justin's bttv2 driver which is @@ -192,8 +192,8 @@ static u8 SRAM_Table[][60] = const struct bttv_tvnorm bttv_tvnorms[] = { /* PAL-BDGHI */ - /* max. active video is actually 922, but 924 is divisible by 4 and 3! */ - /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */ + /* max. active video is actually 922, but 924 is divisible by 4 and 3! */ + /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */ { .v4l2_id = V4L2_STD_PAL, .name = "PAL", @@ -806,9 +806,9 @@ static void bt848A_set_timing(struct bttv *btv) btv->c.nr,table_idx); /* timing change...reset timing generator address */ - btwrite(0x00, BT848_TGCTRL); - btwrite(0x02, BT848_TGCTRL); - btwrite(0x00, BT848_TGCTRL); + btwrite(0x00, BT848_TGCTRL); + btwrite(0x02, BT848_TGCTRL); + btwrite(0x00, BT848_TGCTRL); len=SRAM_Table[table_idx][0]; for(i = 1; i <= len; i++) @@ -847,7 +847,7 @@ static void bt848_hue(struct bttv *btv, int hue) /* -128 to 127 */ value = (hue >> 8) - 128; - btwrite(value & 0xff, BT848_HUE); + btwrite(value & 0xff, BT848_HUE); } static void bt848_contrast(struct bttv *btv, int cont) @@ -859,9 +859,9 @@ static void bt848_contrast(struct bttv *btv, int cont) /* 0-511 */ value = (cont >> 7); hibit = (value >> 6) & 4; - btwrite(value & 0xff, BT848_CONTRAST_LO); - btaor(hibit, ~4, BT848_E_CONTROL); - btaor(hibit, ~4, BT848_O_CONTROL); + btwrite(value & 0xff, BT848_CONTRAST_LO); + btaor(hibit, ~4, BT848_E_CONTROL); + btaor(hibit, ~4, BT848_O_CONTROL); } static void bt848_sat(struct bttv *btv, int color) @@ -873,12 +873,12 @@ static void bt848_sat(struct bttv *btv, int color) /* 0-511 for the color */ val_u = ((color * btv->opt_uv_ratio) / 50) >> 7; val_v = (((color * (100 - btv->opt_uv_ratio) / 50) >>7)*180L)/254; - hibits = (val_u >> 7) & 2; + hibits = (val_u >> 7) & 2; hibits |= (val_v >> 8) & 1; - btwrite(val_u & 0xff, BT848_SAT_U_LO); - btwrite(val_v & 0xff, BT848_SAT_V_LO); - btaor(hibits, ~3, BT848_E_CONTROL); - btaor(hibits, ~3, BT848_O_CONTROL); + btwrite(val_u & 0xff, BT848_SAT_U_LO); + btwrite(val_v & 0xff, BT848_SAT_V_LO); + btaor(hibits, ~3, BT848_E_CONTROL); + btaor(hibits, ~3, BT848_O_CONTROL); } /* ----------------------------------------------------------------------- */ @@ -891,7 +891,7 @@ video_mux(struct bttv *btv, unsigned int input) if (input >= bttv_tvcards[btv->c.type].video_inputs) return -EINVAL; - /* needed by RemoteVideo MX */ + /* needed by RemoteVideo MX */ mask2 = bttv_tvcards[btv->c.type].gpiomask2; if (mask2) gpio_inout(mask2,mask2); @@ -1055,22 +1055,22 @@ static void init_bt848(struct bttv *btv) btwrite(BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL); btwrite(BT848_IFORM_XTAUTO | BT848_IFORM_AUTO, BT848_IFORM); - /* set planar and packed mode trigger points and */ - /* set rising edge of inverted GPINTR pin as irq trigger */ - btwrite(BT848_GPIO_DMA_CTL_PKTP_32| - BT848_GPIO_DMA_CTL_PLTP1_16| - BT848_GPIO_DMA_CTL_PLTP23_16| - BT848_GPIO_DMA_CTL_GPINTC| - BT848_GPIO_DMA_CTL_GPINTI, - BT848_GPIO_DMA_CTL); + /* set planar and packed mode trigger points and */ + /* set rising edge of inverted GPINTR pin as irq trigger */ + btwrite(BT848_GPIO_DMA_CTL_PKTP_32| + BT848_GPIO_DMA_CTL_PLTP1_16| + BT848_GPIO_DMA_CTL_PLTP23_16| + BT848_GPIO_DMA_CTL_GPINTC| + BT848_GPIO_DMA_CTL_GPINTI, + BT848_GPIO_DMA_CTL); val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0; - btwrite(val, BT848_E_SCLOOP); - btwrite(val, BT848_O_SCLOOP); + btwrite(val, BT848_E_SCLOOP); + btwrite(val, BT848_O_SCLOOP); - btwrite(0x20, BT848_E_VSCALE_HI); - btwrite(0x20, BT848_O_VSCALE_HI); - btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0), + btwrite(0x20, BT848_E_VSCALE_HI); + btwrite(0x20, BT848_O_VSCALE_HI); + btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0), BT848_ADC); btwrite(whitecrush_upper, BT848_WC_UP); @@ -1089,7 +1089,7 @@ static void init_bt848(struct bttv *btv) bt848_contrast(btv, btv->contrast); bt848_sat(btv, btv->saturation); - /* interrupt */ + /* interrupt */ init_irqreg(btv); } @@ -1105,7 +1105,7 @@ static void bttv_reinit_bt848(struct bttv *btv) spin_unlock_irqrestore(&btv->s_lock,flags); init_bt848(btv); - btv->pll.pll_current = -1; + btv->pll.pll_current = -1; set_input(btv,btv->input); } @@ -1398,7 +1398,7 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh, /* video4linux (1) interface */ static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf, - const struct bttv_format *fmt, + const struct bttv_format *fmt, unsigned int width, unsigned int height, enum v4l2_field field) { @@ -1521,8 +1521,8 @@ static const char *v4l1_ioctls[] = { static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) { switch (cmd) { - case BTTV_VERSION: - return BTTV_VERSION_CODE; + case BTTV_VERSION: + return BTTV_VERSION_CODE; /* *** v4l1 *** ************************************************ */ case VIDIOCGFREQ: @@ -1576,32 +1576,32 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) return 0; } - case VIDIOCGCHAN: - { - struct video_channel *v = arg; + case VIDIOCGCHAN: + { + struct video_channel *v = arg; unsigned int channel = v->channel; - if (channel >= bttv_tvcards[btv->c.type].video_inputs) - return -EINVAL; - v->tuners=0; - v->flags = VIDEO_VC_AUDIO; - v->type = VIDEO_TYPE_CAMERA; - v->norm = btv->tvnorm; + if (channel >= bttv_tvcards[btv->c.type].video_inputs) + return -EINVAL; + v->tuners=0; + v->flags = VIDEO_VC_AUDIO; + v->type = VIDEO_TYPE_CAMERA; + v->norm = btv->tvnorm; if (channel == bttv_tvcards[btv->c.type].tuner) { - strcpy(v->name,"Television"); - v->flags|=VIDEO_VC_TUNER; - v->type=VIDEO_TYPE_TV; - v->tuners=1; - } else if (channel == btv->svhs) { - strcpy(v->name,"S-Video"); - } else { - sprintf(v->name,"Composite%d",channel); + strcpy(v->name,"Television"); + v->flags|=VIDEO_VC_TUNER; + v->type=VIDEO_TYPE_TV; + v->tuners=1; + } else if (channel == btv->svhs) { + strcpy(v->name,"S-Video"); + } else { + sprintf(v->name,"Composite%d",channel); } return 0; - } - case VIDIOCSCHAN: - { - struct video_channel *v = arg; + } + case VIDIOCSCHAN: + { + struct video_channel *v = arg; unsigned int channel = v->channel; if (channel >= bttv_tvcards[btv->c.type].video_inputs) @@ -1623,7 +1623,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) return 0; } - case VIDIOCGAUDIO: + case VIDIOCGAUDIO: { struct video_audio *v = arg; @@ -1728,7 +1728,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) } else if (i->index == btv->svhs) { sprintf(i->name, "S-Video"); } else { - sprintf(i->name,"Composite%d",i->index); + sprintf(i->name,"Composite%d",i->index); } if (i->index == btv->input) { __u32 dstatus = btread(BT848_DSTATUS); @@ -2168,7 +2168,7 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv, if (0 != retval) return retval; if (locked_btres(fh->btv, RESOURCE_VBI)) - return -EBUSY; + return -EBUSY; bttv_vbi_try_fmt(fh,f); bttv_vbi_setlines(fh,btv,f->fmt.vbi.count[0]); bttv_vbi_get_fmt(fh,f); @@ -2206,9 +2206,9 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, bttv_reinit_bt848(btv); switch (cmd) { - case VIDIOCSFREQ: - case VIDIOCSTUNER: - case VIDIOCSCHAN: + case VIDIOCSFREQ: + case VIDIOCSTUNER: + case VIDIOCSCHAN: case VIDIOC_S_CTRL: case VIDIOC_S_STD: case VIDIOC_S_INPUT: @@ -2224,10 +2224,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, /* *** v4l1 *** ************************************************ */ case VIDIOCGCAP: { - struct video_capability *cap = arg; + struct video_capability *cap = arg; memset(cap,0,sizeof(*cap)); - strcpy(cap->name,btv->video_dev->name); + strcpy(cap->name,btv->video_dev->name); if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) { /* vbi */ cap->type = VID_TYPE_TUNER|VID_TYPE_TELETEXT; @@ -2247,7 +2247,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, } cap->channels = bttv_tvcards[btv->c.type].video_inputs; cap->audios = bttv_tvcards[btv->c.type].audio_inputs; - return 0; + return 0; } case VIDIOCGPICT: @@ -2296,7 +2296,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, bt848_hue(btv,pic->hue); bt848_sat(btv,pic->colour); up(&fh->cap.lock); - return 0; + return 0; } case VIDIOCGWIN: @@ -2357,8 +2357,8 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, unsigned long end; if(!capable(CAP_SYS_ADMIN) && - !capable(CAP_SYS_RAWIO)) - return -EPERM; + !capable(CAP_SYS_RAWIO)) + return -EPERM; end = (unsigned long)fbuf->base + fbuf->height * fbuf->bytesperline; down(&fh->cap.lock); @@ -2432,7 +2432,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, } /* switch over */ - retval = bttv_switch_overlay(btv,fh,new); + retval = bttv_switch_overlay(btv,fh,new); up(&fh->cap.lock); return retval; } @@ -2571,13 +2571,13 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, return 0; } - case BTTV_VERSION: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - case VIDIOCGTUNER: - case VIDIOCSTUNER: - case VIDIOCGCHAN: - case VIDIOCSCHAN: + case BTTV_VERSION: + case VIDIOCGFREQ: + case VIDIOCSFREQ: + case VIDIOCGTUNER: + case VIDIOCSTUNER: + case VIDIOCGCHAN: + case VIDIOCSCHAN: case VIDIOCGAUDIO: case VIDIOCSAUDIO: return bttv_common_ioctls(btv,cmd,arg); @@ -2589,8 +2589,8 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, if (0 == v4l2) return -EINVAL; - strcpy(cap->driver,"bttv"); - strlcpy(cap->card,btv->video_dev->name,sizeof(cap->card)); + strcpy(cap->driver,"bttv"); + strlcpy(cap->card,btv->video_dev->name,sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s",pci_name(btv->c.pci)); cap->version = BTTV_VERSION_CODE; cap->capabilities = @@ -3097,7 +3097,7 @@ static struct video_device bttv_video_template = { .name = "UNSET", .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER| - VID_TYPE_CLIPPING|VID_TYPE_SCALES, + VID_TYPE_CLIPPING|VID_TYPE_SCALES, .hardware = VID_HARDWARE_BT848, .fops = &bttv_fops, .minor = -1, @@ -3143,7 +3143,7 @@ static int radio_open(struct inode *inode, struct file *file) audio_mux(btv,AUDIO_RADIO); up(&btv->lock); - return 0; + return 0; } static int radio_release(struct inode *inode, struct file *file) @@ -3166,34 +3166,34 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, switch (cmd) { case VIDIOCGCAP: { - struct video_capability *cap = arg; + struct video_capability *cap = arg; memset(cap,0,sizeof(*cap)); - strcpy(cap->name,btv->radio_dev->name); - cap->type = VID_TYPE_TUNER; + strcpy(cap->name,btv->radio_dev->name); + cap->type = VID_TYPE_TUNER; cap->channels = 1; cap->audios = 1; - return 0; + return 0; } - case VIDIOCGTUNER: - { - struct video_tuner *v = arg; + case VIDIOCGTUNER: + { + struct video_tuner *v = arg; - if(v->tuner) - return -EINVAL; + if(v->tuner) + return -EINVAL; memset(v,0,sizeof(*v)); - strcpy(v->name, "Radio"); - bttv_call_i2c_clients(btv,cmd,v); - return 0; - } - case VIDIOCSTUNER: + strcpy(v->name, "Radio"); + bttv_call_i2c_clients(btv,cmd,v); + return 0; + } + case VIDIOCSTUNER: /* nothing to do */ return 0; case BTTV_VERSION: - case VIDIOCGFREQ: - case VIDIOCSFREQ: + case VIDIOCGFREQ: + case VIDIOCSFREQ: case VIDIOCGAUDIO: case VIDIOCSAUDIO: return bttv_common_ioctls(btv,cmd,arg); @@ -3699,7 +3699,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) } if (astat&BT848_INT_VSYNC) - btv->field_count++; + btv->field_count++; if (astat & BT848_INT_GPINT) { wake_up(&btv->gpioq); @@ -3711,13 +3711,13 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) wake_up(&btv->i2c_queue); } - if ((astat & BT848_INT_RISCI) && (stat & (4<<28))) + if ((astat & BT848_INT_RISCI) && (stat & (4<<28))) bttv_irq_switch_vbi(btv); - if ((astat & BT848_INT_RISCI) && (stat & (2<<28))) + if ((astat & BT848_INT_RISCI) && (stat & (2<<28))) bttv_irq_wakeup_top(btv); - if ((astat & BT848_INT_RISCI) && (stat & (1<<28))) + if ((astat & BT848_INT_RISCI) && (stat & (1<<28))) bttv_irq_switch_video(btv); if ((astat & BT848_INT_HLOCK) && btv->opt_automute) @@ -3744,7 +3744,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) if (count > 4) { if (count > 8 || !(astat & BT848_INT_GPINT)) { - btwrite(0, BT848_INT_MASK); + btwrite(0, BT848_INT_MASK); printk(KERN_ERR "bttv%d: IRQ lockup, cleared int mask [", btv->c.nr); @@ -3826,7 +3826,7 @@ static int __devinit bttv_register_video(struct bttv *btv) /* video */ btv->video_dev = vdev_init(btv, &bttv_video_template, "video"); - if (NULL == btv->video_dev) + if (NULL == btv->video_dev) goto err; if (video_register_device(btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0) goto err; @@ -3836,18 +3836,18 @@ static int __devinit bttv_register_video(struct bttv *btv) /* vbi */ btv->vbi_dev = vdev_init(btv, &bttv_vbi_template, "vbi"); - if (NULL == btv->vbi_dev) + if (NULL == btv->vbi_dev) goto err; - if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0) + if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0) goto err; printk(KERN_INFO "bttv%d: registered device vbi%d\n", btv->c.nr,btv->vbi_dev->minor & 0x1f); - if (!btv->has_radio) + if (!btv->has_radio) return 0; /* radio */ btv->radio_dev = vdev_init(btv, &radio_template, "radio"); - if (NULL == btv->radio_dev) + if (NULL == btv->radio_dev) goto err; if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0) goto err; @@ -3868,11 +3868,11 @@ static int __devinit bttv_register_video(struct bttv *btv) static void pci_set_command(struct pci_dev *dev) { #if defined(__powerpc__) - unsigned int cmd; + unsigned int cmd; - pci_read_config_dword(dev, PCI_COMMAND, &cmd); - cmd = (cmd | PCI_COMMAND_MEMORY ); - pci_write_config_dword(dev, PCI_COMMAND, cmd); + pci_read_config_dword(dev, PCI_COMMAND, &cmd); + cmd = (cmd | PCI_COMMAND_MEMORY ); + pci_write_config_dword(dev, PCI_COMMAND, cmd); #endif } @@ -3886,21 +3886,21 @@ static int __devinit bttv_probe(struct pci_dev *dev, if (bttv_num == BTTV_MAX) return -ENOMEM; printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num); - btv=&bttvs[bttv_num]; + btv=&bttvs[bttv_num]; memset(btv,0,sizeof(*btv)); btv->c.nr = bttv_num; sprintf(btv->c.name,"bttv%d",btv->c.nr); /* initialize structs / fill in defaults */ - init_MUTEX(&btv->lock); - init_MUTEX(&btv->reslock); - spin_lock_init(&btv->s_lock); - spin_lock_init(&btv->gpio_lock); - init_waitqueue_head(&btv->gpioq); - init_waitqueue_head(&btv->i2c_queue); - INIT_LIST_HEAD(&btv->c.subs); - INIT_LIST_HEAD(&btv->capture); - INIT_LIST_HEAD(&btv->vcapture); + init_MUTEX(&btv->lock); + init_MUTEX(&btv->reslock); + spin_lock_init(&btv->s_lock); + spin_lock_init(&btv->gpio_lock); + init_waitqueue_head(&btv->gpioq); + init_waitqueue_head(&btv->i2c_queue); + INIT_LIST_HEAD(&btv->c.subs); + INIT_LIST_HEAD(&btv->capture); + INIT_LIST_HEAD(&btv->vcapture); v4l2_prio_init(&btv->prio); init_timer(&btv->timeout); @@ -3921,27 +3921,27 @@ static int __devinit bttv_probe(struct pci_dev *dev, btv->c.nr); return -EIO; } - if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) { - printk(KERN_WARNING "bttv%d: No suitable DMA available.\n", + if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) { + printk(KERN_WARNING "bttv%d: No suitable DMA available.\n", btv->c.nr); return -EIO; - } + } if (!request_mem_region(pci_resource_start(dev,0), pci_resource_len(dev,0), btv->c.name)) { - printk(KERN_WARNING "bttv%d: can't request iomem (0x%lx).\n", + printk(KERN_WARNING "bttv%d: can't request iomem (0x%lx).\n", btv->c.nr, pci_resource_start(dev,0)); return -EBUSY; } - pci_set_master(dev); + pci_set_master(dev); pci_set_command(dev); pci_set_drvdata(dev,btv); - pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); - printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %s, ", - bttv_num,btv->id, btv->revision, pci_name(dev)); - printk("irq: %d, latency: %d, mmio: 0x%lx\n", + pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); + printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %s, ", + bttv_num,btv->id, btv->revision, pci_name(dev)); + printk("irq: %d, latency: %d, mmio: 0x%lx\n", btv->c.pci->irq, lat, pci_resource_start(dev,0)); schedule(); @@ -3952,23 +3952,23 @@ static int __devinit bttv_probe(struct pci_dev *dev, goto fail1; } - /* identify card */ + /* identify card */ bttv_idcard(btv); - /* disable irqs, register irq handler */ + /* disable irqs, register irq handler */ btwrite(0, BT848_INT_MASK); - result = request_irq(btv->c.pci->irq, bttv_irq, - SA_SHIRQ | SA_INTERRUPT,btv->c.name,(void *)btv); - if (result < 0) { - printk(KERN_ERR "bttv%d: can't get IRQ %d\n", + result = request_irq(btv->c.pci->irq, bttv_irq, + SA_SHIRQ | SA_INTERRUPT,btv->c.name,(void *)btv); + if (result < 0) { + printk(KERN_ERR "bttv%d: can't get IRQ %d\n", bttv_num,btv->c.pci->irq); goto fail1; - } + } if (0 != bttv_handle_chipset(btv)) { result = -EIO; goto fail2; - } + } /* init options from insmod args */ btv->opt_combfilter = combfilter; @@ -3994,29 +3994,29 @@ static int __devinit bttv_probe(struct pci_dev *dev, btv->input = 0; /* initialize hardware */ - if (bttv_gpio) - bttv_gpio_tracking(btv,"pre-init"); + if (bttv_gpio) + bttv_gpio_tracking(btv,"pre-init"); bttv_risc_init_main(btv); init_bt848(btv); /* gpio */ - btwrite(0x00, BT848_GPIO_REG_INP); - btwrite(0x00, BT848_GPIO_OUT_EN); - if (bttv_verbose) - bttv_gpio_tracking(btv,"init"); + btwrite(0x00, BT848_GPIO_REG_INP); + btwrite(0x00, BT848_GPIO_OUT_EN); + if (bttv_verbose) + bttv_gpio_tracking(btv,"init"); - /* needs to be done before i2c is registered */ - bttv_init_card1(btv); + /* needs to be done before i2c is registered */ + bttv_init_card1(btv); - /* register i2c + gpio */ - init_bttv_i2c(btv); + /* register i2c + gpio */ + init_bttv_i2c(btv); - /* some card-specific stuff (needs working i2c) */ - bttv_init_card2(btv); + /* some card-specific stuff (needs working i2c) */ + bttv_init_card2(btv); init_irqreg(btv); - /* register video4linux + input */ + /* register video4linux + input */ if (!bttv_tvcards[btv->c.type].no_video) { bttv_register_video(btv); bt848_bright(btv,32768); @@ -4035,10 +4035,10 @@ static int __devinit bttv_probe(struct pci_dev *dev, /* everything is fine */ bttv_num++; - return 0; + return 0; fail2: - free_irq(btv->c.pci->irq,btv); + free_irq(btv->c.pci->irq,btv); fail1: if (btv->bt848_mmio) @@ -4051,12 +4051,12 @@ static int __devinit bttv_probe(struct pci_dev *dev, static void __devexit bttv_remove(struct pci_dev *pci_dev) { - struct bttv *btv = pci_get_drvdata(pci_dev); + struct bttv *btv = pci_get_drvdata(pci_dev); if (bttv_verbose) printk("bttv%d: unloading\n",btv->c.nr); - /* shutdown everything (DMA+IRQs) */ + /* shutdown everything (DMA+IRQs) */ btand(~15, BT848_GPIO_DMA_CTL); btwrite(0, BT848_INT_MASK); btwrite(~0x0, BT848_INT_STAT); @@ -4069,7 +4069,7 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev) wake_up(&btv->gpioq); bttv_sub_del_devices(&btv->c); - /* unregister i2c_bus + input */ + /* unregister i2c_bus + input */ fini_bttv_i2c(btv); /* unregister video4linux */ @@ -4079,18 +4079,18 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev) btcx_riscmem_free(btv->c.pci,&btv->main); /* free ressources */ - free_irq(btv->c.pci->irq,btv); + free_irq(btv->c.pci->irq,btv); iounmap(btv->bt848_mmio); - release_mem_region(pci_resource_start(btv->c.pci,0), - pci_resource_len(btv->c.pci,0)); + release_mem_region(pci_resource_start(btv->c.pci,0), + pci_resource_len(btv->c.pci,0)); pci_set_drvdata(pci_dev, NULL); - return; + return; } static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state) { - struct bttv *btv = pci_get_drvdata(pci_dev); + struct bttv *btv = pci_get_drvdata(pci_dev); struct bttv_buffer_set idle; unsigned long flags; @@ -4125,7 +4125,7 @@ static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state) static int bttv_resume(struct pci_dev *pci_dev) { - struct bttv *btv = pci_get_drvdata(pci_dev); + struct bttv *btv = pci_get_drvdata(pci_dev); unsigned long flags; int err; @@ -4170,24 +4170,24 @@ static int bttv_resume(struct pci_dev *pci_dev) } static struct pci_device_id bttv_pci_tbl[] = { - {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0,} + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0,} }; MODULE_DEVICE_TABLE(pci, bttv_pci_tbl); static struct pci_driver bttv_pci_driver = { - .name = "bttv", - .id_table = bttv_pci_tbl, - .probe = bttv_probe, - .remove = __devexit_p(bttv_remove), + .name = "bttv", + .id_table = bttv_pci_tbl, + .probe = bttv_probe, + .remove = __devexit_p(bttv_remove), .suspend = bttv_suspend, .resume = bttv_resume, }; diff --git a/drivers/media/video/bttv-gpio.c b/drivers/media/video/bttv-gpio.c index 6b280c03e39..575ce8b8e71 100644 --- a/drivers/media/video/bttv-gpio.c +++ b/drivers/media/video/bttv-gpio.c @@ -7,7 +7,7 @@ Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) (c) 1999-2003 Gerd Knorr This program is free software; you can redistribute it and/or modify diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c index e684df37eb0..06c5965b561 100644 --- a/drivers/media/video/bttv-i2c.c +++ b/drivers/media/video/bttv-i2c.c @@ -5,7 +5,7 @@ bttv - Bt848 frame grabber driver Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) (c) 1999-2003 Gerd Knorr This program is free software; you can redistribute it and/or modify @@ -237,7 +237,7 @@ bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last) err: if (i2c_debug) printk(" ERR: %d\n",retval); - return retval; + return retval; } static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) @@ -290,7 +290,7 @@ static struct i2c_adapter bttv_i2c_adap_hw_template = { static int attach_inform(struct i2c_client *client) { - struct bttv *btv = i2c_get_adapdata(client->adapter); + struct bttv *btv = i2c_get_adapdata(client->adapter); if (bttv_debug) printk(KERN_DEBUG "bttv%d: %s i2c attach [addr=0x%x,client=%s]\n", @@ -300,9 +300,9 @@ static int attach_inform(struct i2c_client *client) return 0; if (btv->tuner_type != UNSET) { - struct tuner_setup tun_setup; + struct tuner_setup tun_setup; - tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV; + tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV; tun_setup.type = btv->tuner_type; tun_setup.addr = ADDR_UNSET; @@ -312,7 +312,7 @@ static int attach_inform(struct i2c_client *client) if (btv->pinnacle_id != UNSET) client->driver->command(client,AUDC_CONFIG_PINNACLE, &btv->pinnacle_id); - return 0; + return 0; } void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg) @@ -330,43 +330,43 @@ static struct i2c_client bttv_i2c_client_template = { /* read I2C */ int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) { - unsigned char buffer = 0; + unsigned char buffer = 0; if (0 != btv->i2c_rc) return -1; if (bttv_verbose && NULL != probe_for) printk(KERN_INFO "bttv%d: i2c: checking for %s @ 0x%02x... ", btv->c.nr,probe_for,addr); - btv->i2c_client.addr = addr >> 1; - if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) { + btv->i2c_client.addr = addr >> 1; + if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) { if (NULL != probe_for) { if (bttv_verbose) printk("not found\n"); } else printk(KERN_WARNING "bttv%d: i2c read 0x%x: error\n", btv->c.nr,addr); - return -1; + return -1; } if (bttv_verbose && NULL != probe_for) printk("found\n"); - return buffer; + return buffer; } /* write I2C */ int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, - unsigned char b2, int both) + unsigned char b2, int both) { - unsigned char buffer[2]; - int bytes = both ? 2 : 1; + unsigned char buffer[2]; + int bytes = both ? 2 : 1; if (0 != btv->i2c_rc) return -1; - btv->i2c_client.addr = addr >> 1; - buffer[0] = b1; - buffer[1] = b2; - if (bytes != i2c_master_send(&btv->i2c_client, buffer, bytes)) + btv->i2c_client.addr = addr >> 1; + buffer[0] = b1; + buffer[1] = b2; + if (bytes != i2c_master_send(&btv->i2c_client, buffer, bytes)) return -1; - return 0; + return 0; } /* read EEPROM content */ @@ -431,8 +431,8 @@ int __devinit init_bttv_i2c(struct bttv *btv) "bt%d #%d [%s]", btv->id, btv->c.nr, btv->use_i2c_hw ? "hw" : "sw"); - i2c_set_adapdata(&btv->c.i2c_adap, btv); - btv->i2c_client.adapter = &btv->c.i2c_adap; + i2c_set_adapdata(&btv->c.i2c_adap, btv); + btv->i2c_client.adapter = &btv->c.i2c_adap; #ifdef I2C_CLASS_TV_ANALOG if (bttv_tvcards[btv->c.type].no_video) diff --git a/drivers/media/video/bttv-if.c b/drivers/media/video/bttv-if.c index e8aada772b8..19b564ab0e9 100644 --- a/drivers/media/video/bttv-if.c +++ b/drivers/media/video/bttv-if.c @@ -1,13 +1,13 @@ /* bttv-if.c -- old gpio interface to other kernel modules - don't use in new code, will go away in 2.7 + don't use in new code, will go away in 2.7 have a look at bttv-gpio.c instead. bttv - Bt848 frame grabber driver Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) (c) 1999-2003 Gerd Knorr This program is free software; you can redistribute it and/or modify diff --git a/drivers/media/video/bttv-risc.c b/drivers/media/video/bttv-risc.c index a5ed99b8944..3028862934d 100644 --- a/drivers/media/video/bttv-risc.c +++ b/drivers/media/video/bttv-risc.c @@ -74,27 +74,27 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, } if (bpl <= sg_dma_len(sg)-offset) { /* fits into current chunk */ - *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| + *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| BT848_RISC_EOL|bpl); - *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); - offset+=bpl; + *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); + offset+=bpl; } else { /* scanline needs to be splitted */ - todo = bpl; - *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| + todo = bpl; + *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| (sg_dma_len(sg)-offset)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); - todo -= (sg_dma_len(sg)-offset); - offset = 0; - sg++; - while (todo > sg_dma_len(sg)) { - *(rp++)=cpu_to_le32(BT848_RISC_WRITE| + *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); + todo -= (sg_dma_len(sg)-offset); + offset = 0; + sg++; + while (todo > sg_dma_len(sg)) { + *(rp++)=cpu_to_le32(BT848_RISC_WRITE| sg_dma_len(sg)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)); + *(rp++)=cpu_to_le32(sg_dma_address(sg)); todo -= sg_dma_len(sg); sg++; } - *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL| + *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL| todo); *(rp++)=cpu_to_le32(sg_dma_address(sg)); offset += todo; @@ -201,8 +201,8 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc, ri |= BT848_RISC_EOL; /* write risc instruction */ - *(rp++)=cpu_to_le32(ri | ylen); - *(rp++)=cpu_to_le32(((ylen >> hshift) << 16) | + *(rp++)=cpu_to_le32(ri | ylen); + *(rp++)=cpu_to_le32(((ylen >> hshift) << 16) | (ylen >> hshift)); *(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset); yoffset += ylen; @@ -319,7 +319,7 @@ bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo, int width, int height, int interleaved, int norm) { const struct bttv_tvnorm *tvnorm = &bttv_tvnorms[norm]; - u32 xsf, sr; + u32 xsf, sr; int vdelay; int swidth = tvnorm->swidth; @@ -334,52 +334,52 @@ bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo, vdelay = tvnorm->vdelay; - xsf = (width*scaledtwidth)/swidth; - geo->hscale = ((totalwidth*4096UL)/xsf-4096); - geo->hdelay = tvnorm->hdelayx1; - geo->hdelay = (geo->hdelay*width)/swidth; - geo->hdelay &= 0x3fe; - sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512; - geo->vscale = (0x10000UL-sr) & 0x1fff; - geo->crop = ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) | - ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0); - geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0; - geo->vdelay = vdelay; - geo->width = width; - geo->sheight = tvnorm->sheight; + xsf = (width*scaledtwidth)/swidth; + geo->hscale = ((totalwidth*4096UL)/xsf-4096); + geo->hdelay = tvnorm->hdelayx1; + geo->hdelay = (geo->hdelay*width)/swidth; + geo->hdelay &= 0x3fe; + sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512; + geo->vscale = (0x10000UL-sr) & 0x1fff; + geo->crop = ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) | + ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0); + geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0; + geo->vdelay = vdelay; + geo->width = width; + geo->sheight = tvnorm->sheight; geo->vtotal = tvnorm->vtotal; - if (btv->opt_combfilter) { - geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0); - geo->comb = (width < 769) ? 1 : 0; - } else { - geo->vtc = 0; - geo->comb = 0; - } + if (btv->opt_combfilter) { + geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0); + geo->comb = (width < 769) ? 1 : 0; + } else { + geo->vtc = 0; + geo->comb = 0; + } } static void bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd) { - int off = odd ? 0x80 : 0x00; + int off = odd ? 0x80 : 0x00; if (geo->comb) btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); else btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); - btwrite(geo->vtc, BT848_E_VTC+off); - btwrite(geo->hscale >> 8, BT848_E_HSCALE_HI+off); - btwrite(geo->hscale & 0xff, BT848_E_HSCALE_LO+off); - btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off); - btwrite(geo->vscale & 0xff, BT848_E_VSCALE_LO+off); - btwrite(geo->width & 0xff, BT848_E_HACTIVE_LO+off); - btwrite(geo->hdelay & 0xff, BT848_E_HDELAY_LO+off); - btwrite(geo->sheight & 0xff, BT848_E_VACTIVE_LO+off); - btwrite(geo->vdelay & 0xff, BT848_E_VDELAY_LO+off); - btwrite(geo->crop, BT848_E_CROP+off); + btwrite(geo->vtc, BT848_E_VTC+off); + btwrite(geo->hscale >> 8, BT848_E_HSCALE_HI+off); + btwrite(geo->hscale & 0xff, BT848_E_HSCALE_LO+off); + btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off); + btwrite(geo->vscale & 0xff, BT848_E_VSCALE_LO+off); + btwrite(geo->width & 0xff, BT848_E_HACTIVE_LO+off); + btwrite(geo->hdelay & 0xff, BT848_E_HDELAY_LO+off); + btwrite(geo->sheight & 0xff, BT848_E_VACTIVE_LO+off); + btwrite(geo->vdelay & 0xff, BT848_E_VDELAY_LO+off); + btwrite(geo->crop, BT848_E_CROP+off); btwrite(geo->vtotal>>8, BT848_VTOTAL_HI); - btwrite(geo->vtotal & 0xff, BT848_VTOTAL_LO); + btwrite(geo->vtotal & 0xff, BT848_VTOTAL_LO); } /* ---------------------------------------------------------- */ @@ -420,7 +420,7 @@ bttv_set_dma(struct bttv *btv, int override) } else { del_timer(&btv->timeout); } - btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd); + btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd); btaor(capctl, ~0x0f, BT848_CAP_CTL); if (capctl) { @@ -432,7 +432,7 @@ bttv_set_dma(struct bttv *btv, int override) } else { if (!btv->dma_on) return; - btand(~3, BT848_GPIO_DMA_CTL); + btand(~3, BT848_GPIO_DMA_CTL); btv->dma_on = 0; } return; @@ -460,19 +460,19 @@ bttv_risc_init_main(struct bttv *btv) btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP); btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2)); - btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC | + btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC | BT848_FIFO_STATUS_VRO); - btv->main.cpu[9] = cpu_to_le32(0); + btv->main.cpu[9] = cpu_to_le32(0); /* bottom field */ - btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP); + btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP); btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2)); - btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP); + btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP); btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2)); /* jump back to top field */ btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP); - btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2)); + btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2)); return 0; } diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h index 26cd117a6df..124ea41dada 100644 --- a/drivers/media/video/bttv.h +++ b/drivers/media/video/bttv.h @@ -202,7 +202,7 @@ struct bttv_core { struct list_head subs; /* struct bttv_sub_device */ /* device config */ - unsigned int nr; /* dev nr (for printk("bttv%d: ..."); */ + unsigned int nr; /* dev nr (for printk("bttv%d: ..."); */ unsigned int type; /* card type (pointer into tvcards[]) */ char name[8]; /* dev name */ }; @@ -211,16 +211,16 @@ struct bttv; struct tvcard { - char *name; - unsigned int video_inputs; - unsigned int audio_inputs; - unsigned int tuner; - unsigned int svhs; + char *name; + unsigned int video_inputs; + unsigned int audio_inputs; + unsigned int tuner; + unsigned int svhs; unsigned int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO - u32 gpiomask; - u32 muxsel[16]; - u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */ - u32 gpiomask2; /* GPIO MUX mask */ + u32 gpiomask; + u32 muxsel[16]; + u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */ + u32 gpiomask2; /* GPIO MUX mask */ /* i2c audio flags */ unsigned int no_msp34xx:1; diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h index e0e7c7a84bc..386f546f7d1 100644 --- a/drivers/media/video/bttvp.h +++ b/drivers/media/video/bttvp.h @@ -77,14 +77,14 @@ struct bttv_tvnorm { int v4l2_id; char *name; - u32 Fsc; - u16 swidth, sheight; /* scaled standard width, height */ + u32 Fsc; + u16 swidth, sheight; /* scaled standard width, height */ u16 totalwidth; u8 adelay, bdelay, iform; u32 scaledtwidth; u16 hdelayx1, hactivex1; u16 vdelay; - u8 vbipack; + u8 vbipack; u16 vtotal; int sram; }; @@ -267,8 +267,8 @@ struct bttv { /* card configuration info */ unsigned int cardid; /* pci subsystem id (bt878 based ones) */ - unsigned int tuner_type; /* tuner chip type */ - unsigned int pinnacle_id; + unsigned int tuner_type; /* tuner chip type */ + unsigned int pinnacle_id; unsigned int svhs; struct bttv_pll_info pll; int triton1; @@ -301,9 +301,9 @@ struct bttv { /* locking */ spinlock_t s_lock; - struct semaphore lock; + struct semaphore lock; int resources; - struct semaphore reslock; + struct semaphore reslock; #ifdef VIDIOC_G_PRIORITY struct v4l2_prio_state prio; #endif diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index fac67d98a74..4ae3f78cccf 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -436,7 +436,7 @@ static int memory_write(struct cx88_core *core, u32 address, u32 value) static int memory_read(struct cx88_core *core, u32 address, u32 *value) { - int retval; + int retval; u32 val; /* Warning: address is dword address (4 bytes) */ @@ -605,11 +605,11 @@ static int blackbird_load_firmware(struct cx8802_dev *dev) u32 *dataptr; retval = register_write(dev->core, IVTV_REG_VPU, 0xFFFFFFED); - retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); - retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_REFRESH, 0x80000640); - retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A); + retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); + retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_REFRESH, 0x80000640); + retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A); msleep(1); - retval |= register_write(dev->core, IVTV_REG_APU, 0); + retval |= register_write(dev->core, IVTV_REG_APU, 0); if (retval < 0) dprintk(0, "Error with register_write\n"); @@ -657,13 +657,13 @@ static int blackbird_load_firmware(struct cx8802_dev *dev) release_firmware(firmware); dprintk(0, "Firmware upload successful.\n"); - retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); - retval |= register_read(dev->core, IVTV_REG_SPU, &value); - retval |= register_write(dev->core, IVTV_REG_SPU, value & 0xFFFFFFFE); + retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); + retval |= register_read(dev->core, IVTV_REG_SPU, &value); + retval |= register_write(dev->core, IVTV_REG_SPU, value & 0xFFFFFFFE); msleep(1); retval |= register_read(dev->core, IVTV_REG_VPU, &value); - retval |= register_write(dev->core, IVTV_REG_VPU, value & 0xFFFFFFE8); + retval |= register_write(dev->core, IVTV_REG_VPU, value & 0xFFFFFFE8); if (retval < 0) dprintk(0, "Error with register_write\n"); @@ -876,7 +876,7 @@ static void blackbird_set_default_params(struct cx8802_dev *dev) au_params |= 0; } else if( params->au_bitrate.target >= - mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate ) + mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate ) { /* clamp the bitrate to the max supported by the standard */ params->au_bitrate.target = mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate; @@ -942,7 +942,7 @@ static void blackbird_set_default_params(struct cx8802_dev *dev) /* TODO: implement the stream ID stuff: ts_pid_pmt, ts_pid_audio, ts_pid_video, ts_pid_pcr, ps_size, au_pesid, vi_pesid - */ + */ } #define CHECK_PARAM( name ) ( dev->params.name != params->name ) #define IF_PARAM( name ) if( CHECK_PARAM( name ) ) @@ -1068,7 +1068,7 @@ void blackbird_set_params(struct cx8802_dev *dev, struct v4l2_mpeg_compression * au_params |= 0; } else if( params->au_bitrate.target >= - mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate ) + mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate ) { /* clamp the bitrate to the max supported by the standard */ params->au_bitrate.target = mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate; @@ -1150,7 +1150,7 @@ void blackbird_set_params(struct cx8802_dev *dev, struct v4l2_mpeg_compression * /* TODO: implement the stream ID stuff: ts_pid_pmt, ts_pid_audio, ts_pid_video, ts_pid_pcr, ps_size, au_pesid, vi_pesid - */ + */ UPDATE_PARAM( ts_pid_pmt ); UPDATE_PARAM( ts_pid_audio ); UPDATE_PARAM( ts_pid_video ); @@ -1712,7 +1712,7 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev, static void __devexit blackbird_remove(struct pci_dev *pci_dev) { - struct cx8802_dev *dev = pci_get_drvdata(pci_dev); + struct cx8802_dev *dev = pci_get_drvdata(pci_dev); /* blackbird */ blackbird_unregister_video(dev); @@ -1728,8 +1728,8 @@ static struct pci_device_id cx8802_pci_tbl[] = { { .vendor = 0x14f1, .device = 0x8802, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, },{ /* --- end of list --- */ } @@ -1737,10 +1737,10 @@ static struct pci_device_id cx8802_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); static struct pci_driver blackbird_pci_driver = { - .name = "cx88-blackbird", - .id_table = cx8802_pci_tbl, - .probe = blackbird_probe, - .remove = __devexit_p(blackbird_remove), + .name = "cx88-blackbird", + .id_table = cx8802_pci_tbl, + .probe = blackbird_probe, + .remove = __devexit_p(blackbird_remove), .suspend = cx8802_suspend_common, .resume = cx8802_resume_common, }; diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index cf17da83691..50491776879 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -126,27 +126,27 @@ struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, - .gpio0 = 0x03ff, + .gpio0 = 0x03ff, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, - .gpio0 = 0x03fe, + .gpio0 = 0x03fe, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, - .gpio0 = 0x03fe, + .gpio0 = 0x03fe, }}, }, - [CX88_BOARD_WINFAST2000XP_EXPERT] = { - .name = "Leadtek Winfast 2000XP Expert", - .tuner_type = TUNER_PHILIPS_4IN1, + [CX88_BOARD_WINFAST2000XP_EXPERT] = { + .name = "Leadtek Winfast 2000XP Expert", + .tuner_type = TUNER_PHILIPS_4IN1, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, .gpio0 = 0x00F5e700, .gpio1 = 0x00003004, .gpio2 = 0x00F5e700, @@ -165,15 +165,15 @@ struct cx88_board cx88_boards[] = { .gpio1 = 0x00003004, .gpio2 = 0x00F5c700, .gpio3 = 0x02000000, - }}, - .radio = { - .type = CX88_RADIO, + }}, + .radio = { + .type = CX88_RADIO, .gpio0 = 0x00F5d700, .gpio1 = 0x00003004, .gpio2 = 0x00F5d700, .gpio3 = 0x02000000, - }, - }, + }, + }, [CX88_BOARD_AVERTV_303] = { .name = "AverTV Studio 303 (M126)", .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -214,32 +214,32 @@ struct cx88_board cx88_boards[] = { .gpio1 = 0x000080c0, .gpio2 = 0x0000ff40, },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, .gpio0 = 0x000040bf, .gpio1 = 0x000080c0, .gpio2 = 0x0000ff40, },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, + .type = CX88_VMUX_SVIDEO, + .vmux = 2, .gpio0 = 0x000040bf, .gpio1 = 0x000080c0, .gpio2 = 0x0000ff40, - }}, - .radio = { + }}, + .radio = { .type = CX88_RADIO, - }, + }, }, [CX88_BOARD_WINFAST_DV2000] = { - .name = "Leadtek Winfast DV2000", - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .name = "Leadtek Winfast DV2000", + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, .gpio0 = 0x0035e700, .gpio1 = 0x00003004, .gpio2 = 0x0035e700, @@ -260,14 +260,14 @@ struct cx88_board cx88_boards[] = { .gpio2 = 0x02000000, .gpio3 = 0x02000000, }}, - .radio = { + .radio = { .type = CX88_RADIO, .gpio0 = 0x0035d700, .gpio1 = 0x00007004, .gpio2 = 0x0035d700, .gpio3 = 0x02000000, }, - }, + }, [CX88_BOARD_LEADTEK_PVR2000] = { // gpio values for PAL version from regspy by DScaler .name = "Leadtek PVR 2000", @@ -296,25 +296,25 @@ struct cx88_board cx88_boards[] = { .blackbird = 1, }, [CX88_BOARD_IODATA_GVVCP3PCI] = { - .name = "IODATA GV-VCP3/PCI", + .name = "IODATA GV-VCP3/PCI", .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, + .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 0, - },{ - .type = CX88_VMUX_COMPOSITE2, - .vmux = 1, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - }}, - }, + .type = CX88_VMUX_COMPOSITE1, + .vmux = 0, + },{ + .type = CX88_VMUX_COMPOSITE2, + .vmux = 1, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + }}, + }, [CX88_BOARD_PROLINK_PLAYTVPVR] = { - .name = "Prolink PlayTV PVR", - .tuner_type = TUNER_PHILIPS_FM1236_MK3, + .name = "Prolink PlayTV PVR", + .tuner_type = TUNER_PHILIPS_FM1236_MK3, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, @@ -348,15 +348,15 @@ struct cx88_board cx88_boards[] = { .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0x0000fde6, - },{ + },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in? }}, - .radio = { - .type = CX88_RADIO, + .radio = { + .type = CX88_RADIO, .gpio0 = 0x0000fde2, - }, + }, .blackbird = 1, }, [CX88_BOARD_MSI_TVANYWHERE] = { @@ -372,34 +372,34 @@ struct cx88_board cx88_boards[] = { .gpio0 = 0x00000fbf, .gpio2 = 0x0000fc08, },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, .gpio0 = 0x00000fbf, .gpio2 = 0x0000fc68, },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, + .type = CX88_VMUX_SVIDEO, + .vmux = 2, .gpio0 = 0x00000fbf, .gpio2 = 0x0000fc68, - }}, + }}, }, - [CX88_BOARD_KWORLD_DVB_T] = { - .name = "KWorld/VStream XPert DVB-T", + [CX88_BOARD_KWORLD_DVB_T] = { + .name = "KWorld/VStream XPert DVB-T", .tuner_type = TUNER_ABSENT, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, + .input = {{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, .gpio0 = 0x0700, .gpio2 = 0x0101, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, .gpio0 = 0x0700, .gpio2 = 0x0101, - }}, + }}, .dvb = 1, }, [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = { @@ -425,27 +425,27 @@ struct cx88_board cx88_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x07f8, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x07f8, },{ .type = CX88_VMUX_DEBUG, .vmux = 0, .gpio0 = 0x07f9, // mono from tuner chip - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x000007fa, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x000007fa, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x000007f8, - }, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x000007fa, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x000007fa, + }}, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x000007f8, + }, }, [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q] = { .name = "DViCO FusionHDTV 3 Gold-Q", @@ -489,28 +489,28 @@ struct cx88_board cx88_boards[] = { }}, .dvb = 1, }, - [CX88_BOARD_HAUPPAUGE_DVB_T1] = { + [CX88_BOARD_HAUPPAUGE_DVB_T1] = { .name = "Hauppauge Nova-T DVB-T", .tuner_type = TUNER_ABSENT, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - }}, + .type = CX88_VMUX_DVB, + .vmux = 0, + }}, .dvb = 1, }, - [CX88_BOARD_CONEXANT_DVB_T1] = { + [CX88_BOARD_CONEXANT_DVB_T1] = { .name = "Conexant DVB-T reference design", .tuner_type = TUNER_ABSENT, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - }}, + .input = {{ + .type = CX88_VMUX_DVB, + .vmux = 0, + }}, .dvb = 1, }, [CX88_BOARD_PROVIDEO_PV259] = { @@ -543,12 +543,12 @@ struct cx88_board cx88_boards[] = { .dvb = 1, }, [CX88_BOARD_DNTV_LIVE_DVB_T] = { - .name = "digitalnow DNTV Live! DVB-T", + .name = "digitalnow DNTV Live! DVB-T", .tuner_type = TUNER_ABSENT, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .input = {{ + .input = {{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0x00000700, @@ -705,44 +705,44 @@ struct cx88_board cx88_boards[] = { .gpio0 = 0xbf60, }, }, - [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T] = { + [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T] = { .name = "DViCO FusionHDTV 3 Gold-T", .tuner_type = TUNER_THOMSON_DTT7611, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x97ed, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x97e9, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x97e9, - }}, + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x97ed, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x97e9, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x97e9, + }}, .dvb = 1, - }, - [CX88_BOARD_ADSTECH_DVB_T_PCI] = { - .name = "ADS Tech Instant TV DVB-T PCI", + }, + [CX88_BOARD_ADSTECH_DVB_T_PCI] = { + .name = "ADS Tech Instant TV DVB-T PCI", .tuner_type = TUNER_ABSENT, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, .gpio0 = 0x0700, .gpio2 = 0x0101, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, .gpio0 = 0x0700, .gpio2 = 0x0101, - }}, + }}, .dvb = 1, }, [CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1] = { @@ -762,18 +762,18 @@ struct cx88_board cx88_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x87fd, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x87f9, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x87f9, - }}, + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x87fd, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x87f9, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x87f9, + }}, .dvb = 1, }, [CX88_BOARD_AVERMEDIA_ULTRATV_MC_550] = { @@ -805,23 +805,23 @@ struct cx88_board cx88_boards[] = { }, [CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD] = { /* Alexander Wold */ - .name = "Kworld V-Stream Xpert DVD", - .tuner_type = UNSET, - .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x03000000, - .gpio1 = 0x01000000, - .gpio2 = 0x02000000, - .gpio3 = 0x00100000, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x03000000, + .name = "Kworld V-Stream Xpert DVD", + .tuner_type = UNSET, + .input = {{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x03000000, .gpio1 = 0x01000000, .gpio2 = 0x02000000, .gpio3 = 0x00100000, - }}, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x03000000, + .gpio1 = 0x01000000, + .gpio2 = 0x02000000, + .gpio3 = 0x00100000, + }}, }, [CX88_BOARD_ATI_HDTVWONDER] = { .name = "ATI HDTV Wonder", @@ -892,26 +892,26 @@ struct cx88_subid cx88_subids[] = { .subdevice = 0x00f8, .card = CX88_BOARD_ATI_WONDER_PRO, },{ - .subvendor = 0x107d, - .subdevice = 0x6611, - .card = CX88_BOARD_WINFAST2000XP_EXPERT, + .subvendor = 0x107d, + .subdevice = 0x6611, + .card = CX88_BOARD_WINFAST2000XP_EXPERT, + },{ + .subvendor = 0x107d, + .subdevice = 0x6613, /* NTSC */ + .card = CX88_BOARD_WINFAST2000XP_EXPERT, + },{ + .subvendor = 0x107d, + .subdevice = 0x6620, + .card = CX88_BOARD_WINFAST_DV2000, },{ - .subvendor = 0x107d, - .subdevice = 0x6613, /* NTSC */ - .card = CX88_BOARD_WINFAST2000XP_EXPERT, + .subvendor = 0x107d, + .subdevice = 0x663b, + .card = CX88_BOARD_LEADTEK_PVR2000, },{ .subvendor = 0x107d, - .subdevice = 0x6620, - .card = CX88_BOARD_WINFAST_DV2000, - },{ - .subvendor = 0x107d, - .subdevice = 0x663b, - .card = CX88_BOARD_LEADTEK_PVR2000, - },{ - .subvendor = 0x107d, - .subdevice = 0x663C, - .card = CX88_BOARD_LEADTEK_PVR2000, - },{ + .subdevice = 0x663C, + .card = CX88_BOARD_LEADTEK_PVR2000, + },{ .subvendor = 0x1461, .subdevice = 0x000b, .card = CX88_BOARD_AVERTV_303, @@ -920,13 +920,13 @@ struct cx88_subid cx88_subids[] = { .subdevice = 0x8606, .card = CX88_BOARD_MSI_TVANYWHERE_MASTER, },{ - .subvendor = 0x10fc, - .subdevice = 0xd003, - .card = CX88_BOARD_IODATA_GVVCP3PCI, + .subvendor = 0x10fc, + .subdevice = 0xd003, + .card = CX88_BOARD_IODATA_GVVCP3PCI, },{ - .subvendor = 0x1043, - .subdevice = 0x4823, /* with mpeg encoder */ - .card = CX88_BOARD_ASUS_PVR_416, + .subvendor = 0x1043, + .subdevice = 0x4823, /* with mpeg encoder */ + .card = CX88_BOARD_ASUS_PVR_416, },{ .subvendor = 0x17de, .subdevice = 0x08a6, @@ -943,15 +943,15 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x18ac, .subdevice = 0xdb00, .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1, - },{ + },{ .subvendor = 0x0070, .subdevice = 0x9002, .card = CX88_BOARD_HAUPPAUGE_DVB_T1, - },{ + },{ .subvendor = 0x14f1, .subdevice = 0x0187, .card = CX88_BOARD_CONEXANT_DVB_T1, - },{ + },{ .subvendor = 0x1540, .subdevice = 0x2580, .card = CX88_BOARD_PROVIDEO_PV259, @@ -960,9 +960,9 @@ struct cx88_subid cx88_subids[] = { .subdevice = 0xdb10, .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS, },{ - .subvendor = 0x1554, - .subdevice = 0x4811, - .card = CX88_BOARD_PIXELVIEW, + .subvendor = 0x1554, + .subdevice = 0x4811, + .card = CX88_BOARD_PIXELVIEW, },{ .subvendor = 0x7063, .subdevice = 0x3000, /* HD-3000 card */ @@ -987,23 +987,23 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x1421, .subdevice = 0x0334, .card = CX88_BOARD_ADSTECH_DVB_T_PCI, - },{ + },{ .subvendor = 0x153b, .subdevice = 0x1166, .card = CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1, - },{ + },{ .subvendor = 0x18ac, .subdevice = 0xd500, .card = CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD, - },{ + },{ .subvendor = 0x1461, .subdevice = 0x8011, .card = CX88_BOARD_AVERMEDIA_ULTRATV_MC_550, - },{ + },{ .subvendor = PCI_VENDOR_ID_ATI, .subdevice = 0xa101, .card = CX88_BOARD_ATI_HDTVWONDER, - },{ + },{ .subvendor = 0x107d, .subdevice = 0x665f, .card = CX88_BOARD_WINFAST_DTV1000, diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index d4d39c1751a..f01a631d0c0 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -153,26 +153,26 @@ static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist, } if (bpl <= sg_dma_len(sg)-offset) { /* fits into current chunk */ - *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl); - *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); - offset+=bpl; + *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl); + *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); + offset+=bpl; } else { /* scanline needs to be splitted */ - todo = bpl; - *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL| + todo = bpl; + *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL| (sg_dma_len(sg)-offset)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); - todo -= (sg_dma_len(sg)-offset); - offset = 0; - sg++; - while (todo > sg_dma_len(sg)) { - *(rp++)=cpu_to_le32(RISC_WRITE| + *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); + todo -= (sg_dma_len(sg)-offset); + offset = 0; + sg++; + while (todo > sg_dma_len(sg)) { + *(rp++)=cpu_to_le32(RISC_WRITE| sg_dma_len(sg)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)); + *(rp++)=cpu_to_le32(sg_dma_address(sg)); todo -= sg_dma_len(sg); sg++; } - *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo); + *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo); *(rp++)=cpu_to_le32(sg_dma_address(sg)); offset += todo; } @@ -309,7 +309,7 @@ struct sram_channel cx88_sram_channels[] = { .name = "video y / packed", .cmds_start = 0x180040, .ctrl_start = 0x180400, - .cdt = 0x180400 + 64, + .cdt = 0x180400 + 64, .fifo_start = 0x180c00, .fifo_size = 0x002800, .ptr1_reg = MO_DMA21_PTR1, @@ -321,7 +321,7 @@ struct sram_channel cx88_sram_channels[] = { .name = "video u", .cmds_start = 0x180080, .ctrl_start = 0x1804a0, - .cdt = 0x1804a0 + 64, + .cdt = 0x1804a0 + 64, .fifo_start = 0x183400, .fifo_size = 0x000800, .ptr1_reg = MO_DMA22_PTR1, @@ -333,7 +333,7 @@ struct sram_channel cx88_sram_channels[] = { .name = "video v", .cmds_start = 0x1800c0, .ctrl_start = 0x180540, - .cdt = 0x180540 + 64, + .cdt = 0x180540 + 64, .fifo_start = 0x183c00, .fifo_size = 0x000800, .ptr1_reg = MO_DMA23_PTR1, @@ -345,7 +345,7 @@ struct sram_channel cx88_sram_channels[] = { .name = "vbi", .cmds_start = 0x180100, .ctrl_start = 0x1805e0, - .cdt = 0x1805e0 + 64, + .cdt = 0x1805e0 + 64, .fifo_start = 0x184400, .fifo_size = 0x001000, .ptr1_reg = MO_DMA24_PTR1, @@ -357,7 +357,7 @@ struct sram_channel cx88_sram_channels[] = { .name = "audio from", .cmds_start = 0x180140, .ctrl_start = 0x180680, - .cdt = 0x180680 + 64, + .cdt = 0x180680 + 64, .fifo_start = 0x185400, .fifo_size = 0x000200, .ptr1_reg = MO_DMA25_PTR1, @@ -369,7 +369,7 @@ struct sram_channel cx88_sram_channels[] = { .name = "audio to", .cmds_start = 0x180180, .ctrl_start = 0x180720, - .cdt = 0x180680 + 64, /* same as audio IN */ + .cdt = 0x180680 + 64, /* same as audio IN */ .fifo_start = 0x185400, /* same as audio IN */ .fifo_size = 0x000200, /* same as audio IN */ .ptr1_reg = MO_DMA26_PTR1, @@ -1137,7 +1137,7 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci) if (!core->radio_addr) core->radio_addr = cx88_boards[core->board].radio_addr; - printk(KERN_INFO "TV tuner %d at 0x%02x, Radio tuner %d at 0x%02x\n", + printk(KERN_INFO "TV tuner %d at 0x%02x, Radio tuner %d at 0x%02x\n", core->tuner_type, core->tuner_addr<<1, core->radio_type, core->radio_addr<<1); diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 579de88e308..3be601cfc99 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -128,7 +128,7 @@ static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe) static u8 reset [] = { 0x50, 0x80 }; static u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 }; static u8 agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF, - 0x00, 0xFF, 0x00, 0x40, 0x40 }; + 0x00, 0xFF, 0x00, 0x40, 0x40 }; static u8 dntv_extra[] = { 0xB5, 0x7A }; static u8 capt_range_cfg[] = { 0x75, 0x32 }; @@ -464,7 +464,7 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev, static void __devexit dvb_remove(struct pci_dev *pci_dev) { - struct cx8802_dev *dev = pci_get_drvdata(pci_dev); + struct cx8802_dev *dev = pci_get_drvdata(pci_dev); /* dvb */ videobuf_dvb_unregister(&dev->dvb); @@ -479,8 +479,8 @@ static struct pci_device_id cx8802_pci_tbl[] = { { .vendor = 0x14f1, .device = 0x8802, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, },{ /* --- end of list --- */ } @@ -488,10 +488,10 @@ static struct pci_device_id cx8802_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); static struct pci_driver dvb_pci_driver = { - .name = "cx88-dvb", - .id_table = cx8802_pci_tbl, - .probe = dvb_probe, - .remove = __devexit_p(dvb_remove), + .name = "cx88-dvb", + .id_table = cx8802_pci_tbl, + .probe = dvb_probe, + .remove = __devexit_p(dvb_remove), .suspend = cx8802_suspend_common, .resume = cx8802_resume_common, }; diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index 761cebd40db..9790d412f19 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -3,7 +3,7 @@ cx88-i2c.c -- all the i2c code is here Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) (c) 2002 Yurij Sysoev (c) 1999-2003 Gerd Knorr @@ -90,7 +90,7 @@ static int cx8800_bit_getsda(void *data) static int attach_inform(struct i2c_client *client) { - struct tuner_setup tun_setup; + struct tuner_setup tun_setup; struct cx88_core *core = i2c_get_adapdata(client->adapter); dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", @@ -98,7 +98,7 @@ static int attach_inform(struct i2c_client *client) if (!client->driver->command) return 0; - if (core->radio_type != UNSET) { + if (core->radio_type != UNSET) { if ((core->radio_addr==ADDR_UNSET)||(core->radio_addr==client->addr)) { tun_setup.mode_mask = T_RADIO; tun_setup.type = core->radio_type; @@ -106,8 +106,8 @@ static int attach_inform(struct i2c_client *client) client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup); } - } - if (core->tuner_type != UNSET) { + } + if (core->tuner_type != UNSET) { if ((core->tuner_addr==ADDR_UNSET)||(core->tuner_addr==client->addr)) { tun_setup.mode_mask = T_ANALOG_TV; @@ -116,7 +116,7 @@ static int attach_inform(struct i2c_client *client) client->driver->command (client,TUNER_SET_TYPE_ADDR, &tun_setup); } - } + } if (core->tda9887_conf) client->driver->command(client, TDA9887_SET_CONFIG, &core->tda9887_conf); @@ -159,7 +159,7 @@ static struct i2c_adapter cx8800_i2c_adap_template = { }; static struct i2c_client cx8800_i2c_client_template = { - .name = "cx88xx internal", + .name = "cx88xx internal", }; static char *i2c_devs[128] = { @@ -202,10 +202,10 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) core->i2c_adap.dev.parent = &pci->dev; strlcpy(core->i2c_adap.name,core->name,sizeof(core->i2c_adap.name)); - core->i2c_algo.data = core; - i2c_set_adapdata(&core->i2c_adap,core); - core->i2c_adap.algo_data = &core->i2c_algo; - core->i2c_client.adapter = &core->i2c_adap; + core->i2c_algo.data = core; + i2c_set_adapdata(&core->i2c_adap,core); + core->i2c_adap.algo_data = &core->i2c_algo; + core->i2c_client.adapter = &core->i2c_adap; cx8800_bit_setscl(core,1); cx8800_bit_setsda(core,1); diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index c27fe4c36f6..38b12ebaa49 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -553,7 +553,7 @@ void cx88_ir_irq(struct cx88_core *core) if ((ircode & 0xffff) != 0xeb04) { /* wrong address */ ir_dprintk("pulse distance decoded wrong address\n"); - break; + break; } if (((~ircode >> 24) & 0xff) != ((ircode >> 16) & 0xff)) { /* wrong checksum */ diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 2c4fbe9258d..35e6d0c2b87 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -316,14 +316,14 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev) spin_unlock(&dev->slock); } - /* other general errors */ - if (status & 0x1f0100) { + /* other general errors */ + if (status & 0x1f0100) { dprintk( 0, "general errors: 0x%08x\n", status & 0x1f0100 ); - spin_lock(&dev->slock); + spin_lock(&dev->slock); cx8802_stop_dma(dev); - cx8802_restart_queue(dev,&dev->mpegq); - spin_unlock(&dev->slock); - } + cx8802_restart_queue(dev,&dev->mpegq); + spin_unlock(&dev->slock); + } } #define MAX_IRQ_LOOP 10 @@ -379,8 +379,8 @@ int cx8802_init_common(struct cx8802_dev *dev) } pci_read_config_byte(dev->pci, PCI_CLASS_REVISION, &dev->pci_rev); - pci_read_config_byte(dev->pci, PCI_LATENCY_TIMER, &dev->pci_lat); - printk(KERN_INFO "%s/2: found at %s, rev: %d, irq: %d, " + pci_read_config_byte(dev->pci, PCI_LATENCY_TIMER, &dev->pci_lat); + printk(KERN_INFO "%s/2: found at %s, rev: %d, irq: %d, " "latency: %d, mmio: 0x%lx\n", dev->core->name, pci_name(dev->pci), dev->pci_rev, dev->pci->irq, dev->pci_lat,pci_resource_start(dev->pci,0)); @@ -430,7 +430,7 @@ void cx8802_fini_common(struct cx8802_dev *dev) int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state) { - struct cx8802_dev *dev = pci_get_drvdata(pci_dev); + struct cx8802_dev *dev = pci_get_drvdata(pci_dev); struct cx88_core *core = dev->core; /* stop mpeg dma */ diff --git a/drivers/media/video/cx88/cx88-reg.h b/drivers/media/video/cx88/cx88-reg.h index 0a3a62fc9bb..d3bf5b17b1d 100644 --- a/drivers/media/video/cx88/cx88-reg.h +++ b/drivers/media/video/cx88/cx88-reg.h @@ -3,9 +3,9 @@ cx88x-hw.h - CX2388x register offsets Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - 2001 Michael Eskin - 2002 Yurij Sysoev - 2003 Gerd Knorr + 2001 Michael Eskin + 2002 Yurij Sysoev + 2003 Gerd Knorr 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 @@ -728,13 +728,13 @@ #define ColorFormatGamma 0x1000 #define Interlaced 0x1 -#define NonInterlaced 0x0 +#define NonInterlaced 0x0 #define FieldEven 0x1 #define FieldOdd 0x0 -#define TGReadWriteMode 0x0 -#define TGEnableMode 0x1 +#define TGReadWriteMode 0x0 +#define TGEnableMode 0x1 #define DV_CbAlign 0x0 #define DV_Y0Align 0x1 diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 4c99fc39bb2..f22ccb65de1 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -100,7 +100,7 @@ static struct cx88_tvnorm tvnorms[] = { .id = V4L2_STD_PAL_I, .cxiformat = VideoFormatPAL, .cxoformat = 0x181f0008, - },{ + },{ .name = "PAL-M", .id = V4L2_STD_PAL_M, .cxiformat = VideoFormatPALM, @@ -470,7 +470,7 @@ static int restart_video_queue(struct cx8800_dev *dev, struct list_head *item; if (!list_empty(&q->active)) { - buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); + buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); dprintk(2,"restart_queue [%p/%d]: restart dma\n", buf, buf->vb.i); start_video_dma(dev, q, buf); @@ -486,7 +486,7 @@ static int restart_video_queue(struct cx8800_dev *dev, for (;;) { if (list_empty(&q->queued)) return 0; - buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue); + buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue); if (NULL == prev) { list_del(&buf->vb.queue); list_add_tail(&buf->vb.queue,&q->active); @@ -783,7 +783,7 @@ static int video_open(struct inode *inode, struct file *file) cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL); } - return 0; + return 0; } static ssize_t @@ -922,7 +922,7 @@ static int set_control(struct cx88_core *core, struct v4l2_control *ctl) { /* struct cx88_core *core = dev->core; */ struct cx88_ctrl *c = NULL; - u32 v_sat_value; + u32 v_sat_value; u32 value; int i; @@ -1252,7 +1252,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, } int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, - struct cx88_core *core, unsigned int cmd, void *arg, v4l2_kioctl driver_ioctl) + struct cx88_core *core, unsigned int cmd, void *arg, v4l2_kioctl driver_ioctl) { int err; @@ -1399,7 +1399,7 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, cx88_get_stereo(core ,t); reg = cx_read(MO_DEVICE_STATUS); - t->signal = (reg & (1<<5)) ? 0xffff : 0x0000; + t->signal = (reg & (1<<5)) ? 0xffff : 0x0000; return 0; } case VIDIOC_S_TUNER: @@ -1486,7 +1486,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, struct v4l2_capability *cap = arg; memset(cap,0,sizeof(*cap)); - strcpy(cap->driver, "cx8800"); + strcpy(cap->driver, "cx8800"); strlcpy(cap->card, cx88_boards[core->board].name, sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci)); @@ -1827,8 +1827,8 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, /* print pci info */ pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); - pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); - printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " + pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); + printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " "latency: %d, mmio: 0x%lx\n", core->name, pci_name(pci_dev), dev->pci_rev, pci_dev->irq, dev->pci_lat,pci_resource_start(pci_dev,0)); @@ -1944,7 +1944,7 @@ fail_free: static void __devexit cx8800_finidev(struct pci_dev *pci_dev) { - struct cx8800_dev *dev = pci_get_drvdata(pci_dev); + struct cx8800_dev *dev = pci_get_drvdata(pci_dev); struct cx88_core *core = dev->core; /* stop thread */ diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index ea5c092a779..baeae1ac992 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -259,8 +259,8 @@ struct cx88_core { /* pci stuff */ int pci_bus; int pci_slot; - u32 __iomem *lmmio; - u8 __iomem *bmmio; + u32 __iomem *lmmio; + u8 __iomem *bmmio; u32 shadow[SHADOW_MAX]; int pci_irqmask; diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 59f8fa0bea6..f0860532575 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -2,8 +2,8 @@ em2820-cards.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger - Ludovico Cavedon - Mauro Carvalho Chehab + Ludovico Cavedon + Mauro Carvalho Chehab Based on the em2800 driver from Sascha Sommer diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index f7b8fb035c9..227a47d6e4b 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -2,8 +2,8 @@ em2820-core.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger - Ludovico Cavedon - Mauro Carvalho Chehab + Ludovico Cavedon + Mauro Carvalho Chehab Based on the em2800 driver from Sascha Sommer @@ -33,32 +33,32 @@ /* #define ENABLE_DEBUG_ISOC_FRAMES */ -unsigned int core_debug = 0; +unsigned int core_debug; module_param(core_debug,int,0644); MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); #define em2820_coredbg(fmt, arg...) do {\ - if (core_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __FUNCTION__ , ##arg); } while (0) + if (core_debug) \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __FUNCTION__ , ##arg); } while (0) -unsigned int reg_debug = 0; +unsigned int reg_debug; module_param(reg_debug,int,0644); MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); #define em2820_regdbg(fmt, arg...) do {\ - if (reg_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __FUNCTION__ , ##arg); } while (0) + if (reg_debug) \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __FUNCTION__ , ##arg); } while (0) -unsigned int isoc_debug = 0; +unsigned int isoc_debug; module_param(isoc_debug,int,0644); MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]"); #define em2820_isocdbg(fmt, arg...) do {\ - if (isoc_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __FUNCTION__ , ##arg); } while (0) + if (isoc_debug) \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __FUNCTION__ , ##arg); } while (0) static int alt = EM2820_PINOUT; module_param(alt, int, 0644); diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index f6bfc038777..bfe0d8795b6 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -2,8 +2,8 @@ em2820-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger - Ludovico Cavedon - Mauro Carvalho Chehab + Ludovico Cavedon + Mauro Carvalho Chehab Based on the em2800 driver from Sascha Sommer diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index ba367a9796e..8681a793a0b 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -43,34 +43,34 @@ MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); /* ---------------------------------------------------------------------- */ static IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = { - [ 0x01 ] = KEY_CHANNEL, - [ 0x02 ] = KEY_SELECT, - [ 0x03 ] = KEY_MUTE, - [ 0x04 ] = KEY_POWER, - [ 0x05 ] = KEY_KP1, - [ 0x06 ] = KEY_KP2, - [ 0x07 ] = KEY_KP3, - [ 0x08 ] = KEY_CHANNELUP, - [ 0x09 ] = KEY_KP4, - [ 0x0a ] = KEY_KP5, - [ 0x0b ] = KEY_KP6, - [ 0x0c ] = KEY_CHANNELDOWN, - [ 0x0d ] = KEY_KP7, - [ 0x0e ] = KEY_KP8, - [ 0x0f ] = KEY_KP9, - [ 0x10 ] = KEY_VOLUMEUP, - [ 0x11 ] = KEY_KP0, - [ 0x12 ] = KEY_MENU, - [ 0x13 ] = KEY_PRINT, - [ 0x14 ] = KEY_VOLUMEDOWN, - [ 0x16 ] = KEY_PAUSE, - [ 0x18 ] = KEY_RECORD, - [ 0x19 ] = KEY_REWIND, - [ 0x1a ] = KEY_PLAY, + [ 0x01 ] = KEY_CHANNEL, + [ 0x02 ] = KEY_SELECT, + [ 0x03 ] = KEY_MUTE, + [ 0x04 ] = KEY_POWER, + [ 0x05 ] = KEY_KP1, + [ 0x06 ] = KEY_KP2, + [ 0x07 ] = KEY_KP3, + [ 0x08 ] = KEY_CHANNELUP, + [ 0x09 ] = KEY_KP4, + [ 0x0a ] = KEY_KP5, + [ 0x0b ] = KEY_KP6, + [ 0x0c ] = KEY_CHANNELDOWN, + [ 0x0d ] = KEY_KP7, + [ 0x0e ] = KEY_KP8, + [ 0x0f ] = KEY_KP9, + [ 0x10 ] = KEY_VOLUMEUP, + [ 0x11 ] = KEY_KP0, + [ 0x12 ] = KEY_MENU, + [ 0x13 ] = KEY_PRINT, + [ 0x14 ] = KEY_VOLUMEDOWN, + [ 0x16 ] = KEY_PAUSE, + [ 0x18 ] = KEY_RECORD, + [ 0x19 ] = KEY_REWIND, + [ 0x1a ] = KEY_PLAY, [ 0x1b ] = KEY_FORWARD, [ 0x1c ] = KEY_BACKSPACE, - [ 0x1e ] = KEY_STOP, - [ 0x40 ] = KEY_ZOOM, + [ 0x1e ] = KEY_STOP, + [ 0x40 ] = KEY_ZOOM, }; /* ----------------------------------------------------------------------- */ diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 048ad1d77ba..e5066d05697 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -2,8 +2,8 @@ em2820-video.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger - Ludovico Cavedon - Mauro Carvalho Chehab + Ludovico Cavedon + Mauro Carvalho Chehab Based on the em2800 driver from Sascha Sommer @@ -42,9 +42,9 @@ #define EM2820_VERSION_CODE KERNEL_VERSION(0, 0, 1) #define em2820_videodbg(fmt, arg...) do {\ - if (video_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __FUNCTION__ , ##arg); } while (0) + if (video_debug) \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __FUNCTION__ , ##arg); } while (0) MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index a11df04a8c3..c48354062eb 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -2,8 +2,8 @@ em2820-cards.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger - Ludovico Cavedon - Mauro Carvalho Chehab + Ludovico Cavedon + Mauro Carvalho Chehab Based on the em2800 driver from Sascha Sommer @@ -390,17 +390,17 @@ extern const unsigned int em2820_bcount; /* printk macros */ #define em2820_err(fmt, arg...) do {\ - printk(KERN_ERR fmt , ##arg); } while (0) + printk(KERN_ERR fmt , ##arg); } while (0) #define em2820_errdev(fmt, arg...) do {\ - printk(KERN_ERR "%s: "fmt,\ + printk(KERN_ERR "%s: "fmt,\ dev->name , ##arg); } while (0) #define em2820_info(fmt, arg...) do {\ - printk(KERN_INFO "%s: "fmt,\ + printk(KERN_INFO "%s: "fmt,\ dev->name , ##arg); } while (0) #define em2820_warn(fmt, arg...) do {\ - printk(KERN_WARNING "%s: "fmt,\ + printk(KERN_WARNING "%s: "fmt,\ dev->name , ##arg); } while (0) inline static int em2820_audio_source(struct em2820 *dev, int input) diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c index cc5973950c0..ed81934ef3c 100644 --- a/drivers/media/video/ir-kbd-gpio.c +++ b/drivers/media/video/ir-kbd-gpio.c @@ -369,14 +369,14 @@ static int ir_probe(struct device *dev) ir->mask_keycode = 0x003e00; ir->mask_keyup = 0x010000; ir->polling = 50; // ms - break; + break; case BTTV_BOARD_PV_BT878P_9B: case BTTV_BOARD_PV_BT878P_PLUS: ir_codes = ir_codes_pixelview; ir->mask_keycode = 0x001f00; ir->mask_keyup = 0x008000; ir->polling = 50; // ms - break; + break; case BTTV_BOARD_WINFAST2000: ir_codes = ir_codes_winfast; diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index b0facaa40b2..12f1053137d 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -163,7 +163,7 @@ static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { - unsigned char b; + unsigned char b; /* poll IR chip */ if (1 != i2c_master_recv(&ir->c,&b,1)) { @@ -177,7 +177,7 @@ static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { - unsigned char b; + unsigned char b; /* poll IR chip */ if (1 != i2c_master_recv(&ir->c,&b,1)) { @@ -225,7 +225,7 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { - unsigned char b; + unsigned char b; /* poll IR chip */ if (1 != i2c_master_recv(&ir->c,&b,1)) { @@ -287,17 +287,17 @@ static int ir_detach(struct i2c_client *client); static int ir_probe(struct i2c_adapter *adap); static struct i2c_driver driver = { - .name = "ir remote kbd driver", - .id = I2C_DRIVERID_EXP3, /* FIXME */ - .flags = I2C_DF_NOTIFY, - .attach_adapter = ir_probe, - .detach_client = ir_detach, + .name = "ir remote kbd driver", + .id = I2C_DRIVERID_EXP3, /* FIXME */ + .flags = I2C_DF_NOTIFY, + .attach_adapter = ir_probe, + .detach_client = ir_detach, }; static struct i2c_client client_template = { - .name = "unset", - .driver = &driver + .name = "unset", + .driver = &driver }; static int ir_attach(struct i2c_adapter *adap, int addr, @@ -398,7 +398,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr, static int ir_detach(struct i2c_client *client) { - struct IR_i2c *ir = i2c_get_clientdata(client); + struct IR_i2c *ir = i2c_get_clientdata(client); /* kill outstanding polls */ del_timer(&ir->timer); diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index 5573f68ce45..699cea2cc64 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -192,7 +192,7 @@ static int msp3400c_reset(struct i2c_client *client) (2 != i2c_transfer(client->adapter,test,2)) ) { printk(KERN_ERR "msp3400: chip reset failed\n"); return -1; - } + } return 0; } @@ -200,16 +200,16 @@ static int msp3400c_read(struct i2c_client *client, int dev, int addr) { int err,retval; - unsigned char write[3]; - unsigned char read[2]; - struct i2c_msg msgs[2] = { - { client->addr, 0, 3, write }, - { client->addr, I2C_M_RD, 2, read } - }; + unsigned char write[3]; + unsigned char read[2]; + struct i2c_msg msgs[2] = { + { client->addr, 0, 3, write }, + { client->addr, I2C_M_RD, 2, read } + }; - write[0] = dev+1; - write[1] = addr >> 8; - write[2] = addr & 0xff; + write[0] = dev+1; + write[1] = addr >> 8; + write[2] = addr & 0xff; for (err = 0; err < 3;) { if (2 == i2c_transfer(client->adapter,msgs,2)) @@ -236,13 +236,13 @@ static int msp3400c_read(struct i2c_client *client, int dev, int addr) static int msp3400c_write(struct i2c_client *client, int dev, int addr, int val) { int err; - unsigned char buffer[5]; + unsigned char buffer[5]; - buffer[0] = dev; - buffer[1] = addr >> 8; - buffer[2] = addr & 0xff; - buffer[3] = val >> 8; - buffer[4] = val & 0xff; + buffer[0] = dev; + buffer[1] = addr >> 8; + buffer[2] = addr & 0xff; + buffer[3] = val >> 8; + buffer[4] = val & 0xff; dprintk_trace("trace: msp3400c_write(0x%x, 0x%x, 0x%x)\n", dev, addr, val); @@ -812,7 +812,7 @@ static void watch_stereo(struct i2c_client *client) else if (msp->stereo & VIDEO_SOUND_LANG1) msp3400c_setstereo(client, V4L2_TUNER_MODE_LANG1); else - msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); + msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); } if (once) @@ -1512,21 +1512,21 @@ static struct i2c_client client_template = static int msp_attach(struct i2c_adapter *adap, int addr, int kind) { struct msp3400c *msp; - struct i2c_client *c; + struct i2c_client *c; int (*thread_func)(void *data) = NULL; int i; - client_template.adapter = adap; - client_template.addr = addr; + client_template.adapter = adap; + client_template.addr = addr; - if (-1 == msp3400c_reset(&client_template)) { - dprintk("msp34xx: no chip found\n"); - return -1; - } + if (-1 == msp3400c_reset(&client_template)) { + dprintk("msp34xx: no chip found\n"); + return -1; + } - if (NULL == (c = kmalloc(sizeof(struct i2c_client),GFP_KERNEL))) - return -ENOMEM; - memcpy(c,&client_template,sizeof(struct i2c_client)); + if (NULL == (c = kmalloc(sizeof(struct i2c_client),GFP_KERNEL))) + return -ENOMEM; + memcpy(c,&client_template,sizeof(struct i2c_client)); if (NULL == (msp = kmalloc(sizeof(struct msp3400c),GFP_KERNEL))) { kfree(c); return -ENOMEM; @@ -1618,7 +1618,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) } /* done */ - i2c_attach_client(c); + i2c_attach_client(c); /* update our own array */ for (i = 0; i < MSP3400_MAX; i++) { @@ -1739,7 +1739,7 @@ static void msp_any_set_audmode(struct i2c_client *client, int audmode) static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct msp3400c *msp = i2c_get_clientdata(client); - __u16 *sarg = arg; + __u16 *sarg = arg; int scart = 0; switch (cmd) { @@ -1969,7 +1969,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) } msp_any_detect_stereo(client); - if (msp->audmode == V4L2_TUNER_MODE_STEREO) { + if (msp->audmode == V4L2_TUNER_MODE_STEREO) { a->capability=V4L2_AUDCAP_STEREO; } @@ -2005,7 +2005,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) msp3400c_set_scart(client,scart,0); msp3400c_write(client,I2C_MSP3400C_DFP,0x000d,0x1900); } - if (sarg->capability==V4L2_AUDCAP_STEREO) { + if (sarg->capability==V4L2_AUDCAP_STEREO) { msp->audmode = V4L2_TUNER_MODE_STEREO; } else { msp->audmode &= ~V4L2_TUNER_MODE_STEREO; diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c index 972aa5e0aee..13b61c4dcbf 100644 --- a/drivers/media/video/mt20xx.c +++ b/drivers/media/video/mt20xx.c @@ -76,17 +76,17 @@ static int mt2032_compute_freq(struct i2c_client *c, unsigned int xogc) //all in Hz { struct tuner *t = i2c_get_clientdata(c); - unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1, + unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1, desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq; - fref= 5250 *1000; //5.25MHz + fref= 5250 *1000; //5.25MHz desired_lo1=rfin+if1; lo1=(2*(desired_lo1/1000)+(fref/1000)) / (2*fref/1000); - lo1n=lo1/8; - lo1a=lo1-(lo1n*8); + lo1n=lo1/8; + lo1a=lo1-(lo1n*8); - s=rfin/1000/1000+1090; + s=rfin/1000/1000+1090; if(optimize_vco) { if(s>1890) sel=0; @@ -96,34 +96,34 @@ static int mt2032_compute_freq(struct i2c_client *c, else sel=4; // >1090 } else { - if(s>1790) sel=0; // <1958 - else if(s>1617) sel=1; - else if(s>1449) sel=2; - else if(s>1291) sel=3; - else sel=4; // >1090 + if(s>1790) sel=0; // <1958 + else if(s>1617) sel=1; + else if(s>1449) sel=2; + else if(s>1291) sel=3; + else sel=4; // >1090 } *ret_sel=sel; - lo1freq=(lo1a+8*lo1n)*fref; + lo1freq=(lo1a+8*lo1n)*fref; tuner_dbg("mt2032: rfin=%d lo1=%d lo1n=%d lo1a=%d sel=%d, lo1freq=%d\n", rfin,lo1,lo1n,lo1a,sel,lo1freq); - desired_lo2=lo1freq-rfin-if2; - lo2=(desired_lo2)/fref; - lo2n=lo2/8; - lo2a=lo2-(lo2n*8); - lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith - lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000; + desired_lo2=lo1freq-rfin-if2; + lo2=(desired_lo2)/fref; + lo2n=lo2/8; + lo2a=lo2-(lo2n*8); + lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith + lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000; tuner_dbg("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n", rfin,lo2,lo2n,lo2a,lo2num,lo2freq); - if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) { + if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) { tuner_info("mt2032: frequency parameters out of range: %d %d %d %d\n", lo1a, lo1n, lo2a,lo2n); - return(-1); - } + return(-1); + } mt2032_spurcheck(c, lo1freq, desired_lo2, spectrum_from, spectrum_to); // should recalculate lo1 (one step up/down) @@ -135,10 +135,10 @@ static int mt2032_compute_freq(struct i2c_client *c, buf[3]=0x0f; //reserved buf[4]=0x1f; buf[5]=(lo2n-1) | (lo2a<<5); - if(rfin >400*1000*1000) - buf[6]=0xe4; - else - buf[6]=0xf4; // set PKEN per rev 1.2 + if(rfin >400*1000*1000) + buf[6]=0xe4; + else + buf[6]=0xf4; // set PKEN per rev 1.2 buf[7]=8+xogc; buf[8]=0xc3; //reserved buf[9]=0x4e; //reserved @@ -168,7 +168,7 @@ static int mt2032_check_lo_lock(struct i2c_client *c) tuner_dbg("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]); udelay(1000); } - return lock; + return lock; } static int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock) @@ -202,7 +202,7 @@ static int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock) buf[0]=0x0f; buf[1]=sel; - i2c_master_send(c,buf,2); + i2c_master_send(c,buf,2); lock=mt2032_check_lo_lock(c); return lock; } @@ -219,23 +219,23 @@ static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin, tuner_dbg("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n", rfin,if1,if2,from,to); - buf[0]=0; - ret=i2c_master_send(c,buf,1); - i2c_master_recv(c,buf,21); + buf[0]=0; + ret=i2c_master_send(c,buf,1); + i2c_master_recv(c,buf,21); buf[0]=0; ret=mt2032_compute_freq(c,rfin,if1,if2,from,to,&buf[1],&sel,t->xogc); if (ret<0) return; - // send only the relevant registers per Rev. 1.2 - buf[0]=0; - ret=i2c_master_send(c,buf,4); - buf[5]=5; - ret=i2c_master_send(c,buf+5,4); - buf[11]=11; - ret=i2c_master_send(c,buf+11,3); - if(ret!=3) + // send only the relevant registers per Rev. 1.2 + buf[0]=0; + ret=i2c_master_send(c,buf,4); + buf[5]=5; + ret=i2c_master_send(c,buf+5,4); + buf[11]=11; + ret=i2c_master_send(c,buf+11,3); + if(ret!=3) tuner_warn("i2c i/o error: rc == %d (should be 3)\n",ret); // wait for PLLs to lock (per manual), retry LINT if not. @@ -253,7 +253,7 @@ static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin, mdelay(10); buf[1]=8+t->xogc; i2c_master_send(c,buf,2); - } + } if (lock!=6) tuner_warn("MT2032 Fatal Error: PLLs didn't lock.\n"); @@ -284,7 +284,7 @@ static void mt2032_set_tv_freq(struct i2c_client *c, unsigned int freq) if2 = 38900*1000; } - mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */, + mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */, 1090*1000*1000, if2, from, to); } @@ -294,7 +294,7 @@ static void mt2032_set_radio_freq(struct i2c_client *c, unsigned int freq) int if2 = t->radio_if2; // per Manual for FM tuning: first if center freq. 1085 MHz - mt2032_set_if_freq(c, freq * 1000 / 16, + mt2032_set_if_freq(c, freq * 1000 / 16, 1085*1000*1000,if2,if2,if2); } @@ -302,57 +302,57 @@ static void mt2032_set_radio_freq(struct i2c_client *c, unsigned int freq) static int mt2032_init(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); - unsigned char buf[21]; - int ret,xogc,xok=0; + unsigned char buf[21]; + int ret,xogc,xok=0; // Initialize Registers per spec. - buf[1]=2; // Index to register 2 - buf[2]=0xff; - buf[3]=0x0f; - buf[4]=0x1f; - ret=i2c_master_send(c,buf+1,4); - - buf[5]=6; // Index register 6 - buf[6]=0xe4; - buf[7]=0x8f; - buf[8]=0xc3; - buf[9]=0x4e; - buf[10]=0xec; - ret=i2c_master_send(c,buf+5,6); - - buf[12]=13; // Index register 13 - buf[13]=0x32; - ret=i2c_master_send(c,buf+12,2); - - // Adjust XOGC (register 7), wait for XOK - xogc=7; - do { + buf[1]=2; // Index to register 2 + buf[2]=0xff; + buf[3]=0x0f; + buf[4]=0x1f; + ret=i2c_master_send(c,buf+1,4); + + buf[5]=6; // Index register 6 + buf[6]=0xe4; + buf[7]=0x8f; + buf[8]=0xc3; + buf[9]=0x4e; + buf[10]=0xec; + ret=i2c_master_send(c,buf+5,6); + + buf[12]=13; // Index register 13 + buf[13]=0x32; + ret=i2c_master_send(c,buf+12,2); + + // Adjust XOGC (register 7), wait for XOK + xogc=7; + do { + tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07); + mdelay(10); + buf[0]=0x0e; + i2c_master_send(c,buf,1); + i2c_master_recv(c,buf,1); + xok=buf[0]&0x01; + tuner_dbg("mt2032: xok = 0x%02x\n",xok); + if (xok == 1) break; + + xogc--; tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07); - mdelay(10); - buf[0]=0x0e; - i2c_master_send(c,buf,1); - i2c_master_recv(c,buf,1); - xok=buf[0]&0x01; - tuner_dbg("mt2032: xok = 0x%02x\n",xok); - if (xok == 1) break; - - xogc--; - tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07); - if (xogc == 3) { - xogc=4; // min. 4 per spec - break; - } - buf[0]=0x07; - buf[1]=0x88 + xogc; - ret=i2c_master_send(c,buf,2); - if (ret!=2) + if (xogc == 3) { + xogc=4; // min. 4 per spec + break; + } + buf[0]=0x07; + buf[1]=0x88 + xogc; + ret=i2c_master_send(c,buf,2); + if (ret!=2) tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret); - } while (xok != 1 ); + } while (xok != 1 ); t->xogc=xogc; t->tv_freq = mt2032_set_tv_freq; t->radio_freq = mt2032_set_radio_freq; - return(1); + return(1); } static void mt2050_set_antenna(struct i2c_client *c, unsigned char antenna) @@ -426,7 +426,7 @@ static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned } ret=i2c_master_send(c,buf,6); - if (ret!=6) + if (ret!=6) tuner_warn("i2c i/o error: rc == %d (should be 6)\n",ret); } @@ -437,11 +437,11 @@ static void mt2050_set_tv_freq(struct i2c_client *c, unsigned int freq) if (t->std & V4L2_STD_525_60) { // NTSC - if2 = 45750*1000; - } else { - // PAL - if2 = 38900*1000; - } + if2 = 45750*1000; + } else { + // PAL + if2 = 38900*1000; + } if (V4L2_TUNER_DIGITAL_TV == t->mode) { // DVB (pinnacle 300i) if2 = 36150*1000; @@ -487,7 +487,7 @@ int microtune_init(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); char *name; - unsigned char buf[21]; + unsigned char buf[21]; int company_code; memset(buf,0,sizeof(buf)); @@ -496,17 +496,17 @@ int microtune_init(struct i2c_client *c) t->standby = NULL; name = "unknown"; - i2c_master_send(c,buf,1); - i2c_master_recv(c,buf,21); - if (tuner_debug) { - int i; + i2c_master_send(c,buf,1); + i2c_master_recv(c,buf,21); + if (tuner_debug) { + int i; tuner_dbg("MT20xx hexdump:"); - for(i=0;i<21;i++) { - printk(" %02x",buf[i]); - if(((i+1)%8)==0) printk(" "); - } - printk("\n"); - } + for(i=0;i<21;i++) { + printk(" %02x",buf[i]); + if(((i+1)%8)==0) printk(" "); + } + printk("\n"); + } company_code = buf[0x11] << 8 | buf[0x12]; tuner_info("microtune: companycode=%04x part=%02x rev=%02x\n", company_code,buf[0x13],buf[0x14]); @@ -525,8 +525,8 @@ int microtune_init(struct i2c_client *c) default: tuner_info("microtune %s found, not (yet?) supported, sorry :-/\n", name); - return 0; - } + return 0; + } strlcpy(c->name, name, sizeof(c->name)); tuner_info("microtune %s found, OK\n",name); diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c index 37653ee8723..ed16282fca5 100644 --- a/drivers/media/video/saa711x.c +++ b/drivers/media/video/saa711x.c @@ -464,8 +464,8 @@ saa7113_command (struct i2c_client *client, /* standard i2c insmod options */ static unsigned short normal_i2c[] = { - I2C_SAA7113>>1, /* saa7113 */ - I2C_CLIENT_END + I2C_SAA7113>>1, /* saa7113 */ + I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index dac720ea3b0..2bf5cf79eec 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c @@ -169,31 +169,31 @@ static int saa6752hs_chip_command(struct i2c_client* client, /* execute the command */ switch(command) { - case SAA6752HS_COMMAND_RESET: - buf[0] = 0x00; + case SAA6752HS_COMMAND_RESET: + buf[0] = 0x00; break; case SAA6752HS_COMMAND_STOP: - buf[0] = 0x03; + buf[0] = 0x03; break; case SAA6752HS_COMMAND_START: - buf[0] = 0x02; + buf[0] = 0x02; break; case SAA6752HS_COMMAND_PAUSE: - buf[0] = 0x04; + buf[0] = 0x04; break; case SAA6752HS_COMMAND_RECONFIGURE: buf[0] = 0x05; break; - case SAA6752HS_COMMAND_SLEEP: - buf[0] = 0x06; + case SAA6752HS_COMMAND_SLEEP: + buf[0] = 0x06; break; - case SAA6752HS_COMMAND_RECONFIGURE_FORCE: + case SAA6752HS_COMMAND_RECONFIGURE_FORCE: buf[0] = 0x07; break; @@ -201,13 +201,13 @@ static int saa6752hs_chip_command(struct i2c_client* client, return -EINVAL; } - /* set it and wait for it to be so */ + /* set it and wait for it to be so */ i2c_master_send(client, buf, 1); timeout = jiffies + HZ * 3; for (;;) { /* get the current status */ buf[0] = 0x10; - i2c_master_send(client, buf, 1); + i2c_master_send(client, buf, 1); i2c_master_recv(client, buf, 1); if (!(buf[0] & 0x20)) @@ -223,14 +223,14 @@ static int saa6752hs_chip_command(struct i2c_client* client, /* delay a bit to let encoder settle */ msleep(50); - return status; + return status; } static int saa6752hs_set_bitrate(struct i2c_client* client, struct v4l2_mpeg_compression* params) { - u8 buf[3]; + u8 buf[3]; /* set the bitrate mode */ buf[0] = 0x71; @@ -242,31 +242,31 @@ static int saa6752hs_set_bitrate(struct i2c_client* client, /* set the target bitrate */ buf[0] = 0x80; buf[1] = params->vi_bitrate.target >> 8; - buf[2] = params->vi_bitrate.target & 0xff; + buf[2] = params->vi_bitrate.target & 0xff; i2c_master_send(client, buf, 3); /* set the max bitrate */ buf[0] = 0x81; buf[1] = params->vi_bitrate.max >> 8; - buf[2] = params->vi_bitrate.max & 0xff; + buf[2] = params->vi_bitrate.max & 0xff; i2c_master_send(client, buf, 3); } else { /* set the target bitrate (no max bitrate for CBR) */ - buf[0] = 0x81; + buf[0] = 0x81; buf[1] = params->vi_bitrate.target >> 8; - buf[2] = params->vi_bitrate.target & 0xff; + buf[2] = params->vi_bitrate.target & 0xff; i2c_master_send(client, buf, 3); } /* set the audio bitrate */ - buf[0] = 0x94; + buf[0] = 0x94; buf[1] = (256 == params->au_bitrate.target) ? 0 : 1; i2c_master_send(client, buf, 2); /* set the total bitrate */ buf[0] = 0xb1; - buf[1] = params->st_bitrate.target >> 8; - buf[2] = params->st_bitrate.target & 0xff; + buf[1] = params->st_bitrate.target >> 8; + buf[2] = params->st_bitrate.target & 0xff; i2c_master_send(client, buf, 3); return 0; @@ -386,8 +386,8 @@ static int saa6752hs_init(struct i2c_client* client) buf[1] = 0x01; i2c_master_send(client, buf, 2); - /* set bitrate */ - saa6752hs_set_bitrate(client, &h->params); + /* set bitrate */ + saa6752hs_set_bitrate(client, &h->params); /* Set GOP structure {3, 13} */ buf[0] = 0x72; @@ -426,9 +426,9 @@ static int saa6752hs_init(struct i2c_client* client) localPAT[sizeof(PAT) - 1] = crc & 0xFF; /* compute PMT */ - memcpy(localPMT, PMT, sizeof(PMT)); - localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f); - localPMT[4] = h->params.ts_pid_pmt & 0xff; + memcpy(localPMT, PMT, sizeof(PMT)); + localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f); + localPMT[4] = h->params.ts_pid_pmt & 0xff; localPMT[15] = 0xE0 | ((h->params.ts_pid_pcr >> 8) & 0x0F); localPMT[16] = h->params.ts_pid_pcr & 0xFF; localPMT[20] = 0xE0 | ((h->params.ts_pid_video >> 8) & 0x0F); @@ -453,7 +453,7 @@ static int saa6752hs_init(struct i2c_client* client) buf[2] = h->params.ts_pid_video & 0xFF; i2c_master_send(client,buf,3); - /* Set PCR PID */ + /* Set PCR PID */ buf[0] = 0xC4; buf[1] = (h->params.ts_pid_pcr >> 8) & 0xFF; buf[2] = h->params.ts_pid_pcr & 0xFF; @@ -467,7 +467,7 @@ static int saa6752hs_init(struct i2c_client* client) buf[0] = 0xa4; buf[1] = 1; i2c_master_send(client, buf, 2); - buf[1] = 0; + buf[1] = 0; i2c_master_send(client, buf, 2); /* start it going */ @@ -510,10 +510,10 @@ static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind) { struct saa6752hs_state *h; - printk("saa6752hs: chip found @ 0x%x\n", addr<<1); + printk("saa6752hs: chip found @ 0x%x\n", addr<<1); - if (NULL == (h = kmalloc(sizeof(*h), GFP_KERNEL))) - return -ENOMEM; + if (NULL == (h = kmalloc(sizeof(*h), GFP_KERNEL))) + return -ENOMEM; memset(h,0,sizeof(*h)); h->client = client_template; h->params = param_defaults; @@ -552,7 +552,7 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) struct v4l2_mpeg_compression *params = arg; int err = 0; - switch (cmd) { + switch (cmd) { case VIDIOC_S_MPEGCOMP: if (NULL == params) { /* apply settings and start encoder */ @@ -566,7 +566,7 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) break; case VIDIOC_G_FMT: { - struct v4l2_format *f = arg; + struct v4l2_format *f = arg; if (h->video_format == SAA6752HS_VF_UNKNOWN) h->video_format = SAA6752HS_VF_D1; diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 465beac941d..e9ffe8f144a 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -80,11 +80,11 @@ typedef struct snd_card_saa7134 { spinlock_t mixer_lock; int mixer_volume[MIXER_ADDR_LAST+1][2]; int capture_source[MIXER_ADDR_LAST+1][2]; - struct pci_dev *pci; - struct saa7134_dev *saadev; + struct pci_dev *pci; + struct saa7134_dev *saadev; - unsigned long iobase; - int irq; + unsigned long iobase; + int irq; spinlock_t lock; } snd_card_saa7134_t; @@ -94,7 +94,7 @@ typedef struct snd_card_saa7134 { */ typedef struct snd_card_saa7134_pcm { - struct saa7134_dev *saadev; + struct saa7134_dev *saadev; spinlock_t lock; unsigned int pcm_size; /* buffer size */ @@ -118,9 +118,9 @@ static snd_card_t *snd_saa7134_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; static void saa7134_dma_stop(struct saa7134_dev *dev) { - dev->oss.dma_blk = -1; - dev->oss.dma_running = 0; - saa7134_set_dmabits(dev); + dev->oss.dma_blk = -1; + dev->oss.dma_running = 0; + saa7134_set_dmabits(dev); } /* @@ -135,9 +135,9 @@ static void saa7134_dma_stop(struct saa7134_dev *dev) static void saa7134_dma_start(struct saa7134_dev *dev) { - dev->oss.dma_blk = 0; - dev->oss.dma_running = 1; - saa7134_set_dmabits(dev); + dev->oss.dma_blk = 0; + dev->oss.dma_running = 1; + saa7134_set_dmabits(dev); } /* @@ -184,28 +184,28 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) goto done; } - /* next block addr */ - next_blk = (dev->oss.dma_blk + 2) % dev->oss.blocks; - saa_writel(reg,next_blk * dev->oss.blksize); - if (alsa_debug > 2) - dprintk("irq: ok, %s, next_blk=%d, addr=%x, blocks=%u, size=%u, read=%u\n", - (status & 0x10000000) ? "even" : "odd ", next_blk, - next_blk * dev->oss.blksize, dev->oss.blocks, dev->oss.blksize, dev->oss.read_count); + /* next block addr */ + next_blk = (dev->oss.dma_blk + 2) % dev->oss.blocks; + saa_writel(reg,next_blk * dev->oss.blksize); + if (alsa_debug > 2) + dprintk("irq: ok, %s, next_blk=%d, addr=%x, blocks=%u, size=%u, read=%u\n", + (status & 0x10000000) ? "even" : "odd ", next_blk, + next_blk * dev->oss.blksize, dev->oss.blocks, dev->oss.blksize, dev->oss.read_count); - /* update status & wake waiting readers */ - dev->oss.dma_blk = (dev->oss.dma_blk + 1) % dev->oss.blocks; - dev->oss.read_count += dev->oss.blksize; + /* update status & wake waiting readers */ + dev->oss.dma_blk = (dev->oss.dma_blk + 1) % dev->oss.blocks; + dev->oss.read_count += dev->oss.blksize; - dev->oss.recording_on = reg; + dev->oss.recording_on = reg; if (dev->oss.read_count >= snd_pcm_lib_period_bytes(dev->oss.substream)) { - spin_unlock(&dev->slock); - snd_pcm_period_elapsed(dev->oss.substream); - spin_lock(&dev->slock); + spin_unlock(&dev->slock); + snd_pcm_period_elapsed(dev->oss.substream); + spin_lock(&dev->slock); } done: - spin_unlock(&dev->slock); + spin_unlock(&dev->slock); } @@ -239,23 +239,23 @@ static int snd_card_saa7134_capture_trigger(snd_pcm_substream_t * substream, static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) { - if (blksize < 0x100) - blksize = 0x100; - if (blksize > 0x10000) - blksize = 0x10000; - - if (blocks < 2) - blocks = 2; - if ((blksize * blocks) > 1024*1024) - blocks = 1024*1024 / blksize; - - dev->oss.blocks = blocks; - dev->oss.blksize = blksize; - dev->oss.bufsize = blksize * blocks; - - dprintk("buffer config: %d blocks / %d bytes, %d kB total\n", - blocks,blksize,blksize * blocks / 1024); - return 0; + if (blksize < 0x100) + blksize = 0x100; + if (blksize > 0x10000) + blksize = 0x10000; + + if (blocks < 2) + blocks = 2; + if ((blksize * blocks) > 1024*1024) + blocks = 1024*1024 / blksize; + + dev->oss.blocks = blocks; + dev->oss.blksize = blksize; + dev->oss.bufsize = blksize * blocks; + + dprintk("buffer config: %d blocks / %d bytes, %d kB total\n", + blocks,blksize,blksize * blocks / 1024); + return 0; } /* @@ -271,16 +271,16 @@ static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) static int dsp_buffer_init(struct saa7134_dev *dev) { - int err; - - if (!dev->oss.bufsize) - BUG(); - videobuf_dma_init(&dev->oss.dma); - err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE, - (dev->oss.bufsize + PAGE_SIZE) >> PAGE_SHIFT); - if (0 != err) - return err; - return 0; + int err; + + if (!dev->oss.bufsize) + BUG(); + videobuf_dma_init(&dev->oss.dma); + err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE, + (dev->oss.bufsize + PAGE_SIZE) >> PAGE_SHIFT); + if (0 != err) + return err; + return 0; } /* @@ -298,18 +298,18 @@ static int dsp_buffer_init(struct saa7134_dev *dev) static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) { snd_pcm_runtime_t *runtime = substream->runtime; - int err, bswap, sign; - u32 fmt, control; - unsigned long flags; + int err, bswap, sign; + u32 fmt, control; + unsigned long flags; snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); - struct saa7134_dev *dev; + struct saa7134_dev *dev; snd_card_saa7134_pcm_t *saapcm = runtime->private_data; unsigned int bps; - unsigned long size; - unsigned count; + unsigned long size; + unsigned count; - size = snd_pcm_lib_buffer_bytes(substream); - count = snd_pcm_lib_period_bytes(substream); + size = snd_pcm_lib_buffer_bytes(substream); + count = snd_pcm_lib_period_bytes(substream); saapcm->saadev->oss.substream = substream; bps = runtime->rate * runtime->channels; @@ -324,123 +324,123 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) dev=saa7134->saadev; - dsp_buffer_conf(dev,saapcm->pcm_count,(saapcm->pcm_size/saapcm->pcm_count)); + dsp_buffer_conf(dev,saapcm->pcm_count,(saapcm->pcm_size/saapcm->pcm_count)); - err = dsp_buffer_init(dev); - if (0 != err) - goto fail2; + err = dsp_buffer_init(dev); + if (0 != err) + goto fail2; - /* prepare buffer */ - if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->oss.dma))) - return err; - if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->oss.pt))) - goto fail1; - if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->oss.pt, - dev->oss.dma.sglist, - dev->oss.dma.sglen, - 0))) - goto fail2; + /* prepare buffer */ + if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->oss.dma))) + return err; + if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->oss.pt))) + goto fail1; + if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->oss.pt, + dev->oss.dma.sglist, + dev->oss.dma.sglen, + 0))) + goto fail2; - switch (runtime->format) { - case SNDRV_PCM_FORMAT_U8: - case SNDRV_PCM_FORMAT_S8: + switch (runtime->format) { + case SNDRV_PCM_FORMAT_U8: + case SNDRV_PCM_FORMAT_S8: fmt = 0x00; break; - case SNDRV_PCM_FORMAT_U16_LE: - case SNDRV_PCM_FORMAT_U16_BE: - case SNDRV_PCM_FORMAT_S16_LE: - case SNDRV_PCM_FORMAT_S16_BE: + case SNDRV_PCM_FORMAT_U16_LE: + case SNDRV_PCM_FORMAT_U16_BE: + case SNDRV_PCM_FORMAT_S16_LE: + case SNDRV_PCM_FORMAT_S16_BE: fmt = 0x01; break; - default: - err = -EINVAL; - return 1; - } - - switch (runtime->format) { - case SNDRV_PCM_FORMAT_S8: - case SNDRV_PCM_FORMAT_S16_LE: - case SNDRV_PCM_FORMAT_S16_BE: + default: + err = -EINVAL; + return 1; + } + + switch (runtime->format) { + case SNDRV_PCM_FORMAT_S8: + case SNDRV_PCM_FORMAT_S16_LE: + case SNDRV_PCM_FORMAT_S16_BE: sign = 1; break; - default: + default: sign = 0; break; - } + } - switch (runtime->format) { - case SNDRV_PCM_FORMAT_U16_BE: - case SNDRV_PCM_FORMAT_S16_BE: + switch (runtime->format) { + case SNDRV_PCM_FORMAT_U16_BE: + case SNDRV_PCM_FORMAT_S16_BE: bswap = 1; break; - default: + default: bswap = 0; break; - } - - switch (dev->pci->device) { - case PCI_DEVICE_ID_PHILIPS_SAA7134: - if (1 == runtime->channels) - fmt |= (1 << 3); - if (2 == runtime->channels) - fmt |= (3 << 3); - if (sign) - fmt |= 0x04; - - fmt |= (MIXER_ADDR_TVTUNER == dev->oss.input) ? 0xc0 : 0x80; - saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->oss.blksize - 1) & 0x0000ff)); - saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->oss.blksize - 1) & 0x00ff00) >> 8); - saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->oss.blksize - 1) & 0xff0000) >> 16); - saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt); - - break; - case PCI_DEVICE_ID_PHILIPS_SAA7133: - case PCI_DEVICE_ID_PHILIPS_SAA7135: - if (1 == runtime->channels) - fmt |= (1 << 4); - if (2 == runtime->channels) - fmt |= (2 << 4); - if (!sign) - fmt |= 0x04; - saa_writel(SAA7133_NUM_SAMPLES, dev->oss.blksize -1); - saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24)); - //saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210); - break; - } - - dprintk("rec_start: afmt=%d ch=%d => fmt=0x%x swap=%c\n", - runtime->format, runtime->channels, fmt, - bswap ? 'b' : '-'); - /* dma: setup channel 6 (= AUDIO) */ - control = SAA7134_RS_CONTROL_BURST_16 | - SAA7134_RS_CONTROL_ME | - (dev->oss.pt.dma >> 12); - if (bswap) - control |= SAA7134_RS_CONTROL_BSWAP; + } + + switch (dev->pci->device) { + case PCI_DEVICE_ID_PHILIPS_SAA7134: + if (1 == runtime->channels) + fmt |= (1 << 3); + if (2 == runtime->channels) + fmt |= (3 << 3); + if (sign) + fmt |= 0x04; + + fmt |= (MIXER_ADDR_TVTUNER == dev->oss.input) ? 0xc0 : 0x80; + saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->oss.blksize - 1) & 0x0000ff)); + saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->oss.blksize - 1) & 0x00ff00) >> 8); + saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->oss.blksize - 1) & 0xff0000) >> 16); + saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt); + + break; + case PCI_DEVICE_ID_PHILIPS_SAA7133: + case PCI_DEVICE_ID_PHILIPS_SAA7135: + if (1 == runtime->channels) + fmt |= (1 << 4); + if (2 == runtime->channels) + fmt |= (2 << 4); + if (!sign) + fmt |= 0x04; + saa_writel(SAA7133_NUM_SAMPLES, dev->oss.blksize -1); + saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24)); + //saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210); + break; + } + + dprintk("rec_start: afmt=%d ch=%d => fmt=0x%x swap=%c\n", + runtime->format, runtime->channels, fmt, + bswap ? 'b' : '-'); + /* dma: setup channel 6 (= AUDIO) */ + control = SAA7134_RS_CONTROL_BURST_16 | + SAA7134_RS_CONTROL_ME | + (dev->oss.pt.dma >> 12); + if (bswap) + control |= SAA7134_RS_CONTROL_BSWAP; /* I should be able to use runtime->dma_addr in the control - byte, but it doesn't work. So I allocate the DMA using the - V4L functions, and force ALSA to use that as the DMA area */ + byte, but it doesn't work. So I allocate the DMA using the + V4L functions, and force ALSA to use that as the DMA area */ runtime->dma_area = dev->oss.dma.vmalloc; - saa_writel(SAA7134_RS_BA1(6),0); - saa_writel(SAA7134_RS_BA2(6),dev->oss.blksize); - saa_writel(SAA7134_RS_PITCH(6),0); - saa_writel(SAA7134_RS_CONTROL(6),control); + saa_writel(SAA7134_RS_BA1(6),0); + saa_writel(SAA7134_RS_BA2(6),dev->oss.blksize); + saa_writel(SAA7134_RS_PITCH(6),0); + saa_writel(SAA7134_RS_CONTROL(6),control); dev->oss.rate = runtime->rate; - /* start dma */ - spin_lock_irqsave(&dev->slock,flags); - saa7134_dma_start(dev); - spin_unlock_irqrestore(&dev->slock,flags); + /* start dma */ + spin_lock_irqsave(&dev->slock,flags); + saa7134_dma_start(dev); + spin_unlock_irqrestore(&dev->slock,flags); return 0; fail2: - saa7134_pgtable_free(dev->pci,&dev->oss.pt); + saa7134_pgtable_free(dev->pci,&dev->oss.pt); fail1: - videobuf_dma_pci_unmap(dev->pci,&dev->oss.dma); - return err; + videobuf_dma_pci_unmap(dev->pci,&dev->oss.dma); + return err; } @@ -465,10 +465,10 @@ static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * if (dev->oss.read_count) { - dev->oss.read_count -= snd_pcm_lib_period_bytes(substream); - dev->oss.read_offset += snd_pcm_lib_period_bytes(substream); - if (dev->oss.read_offset == dev->oss.bufsize) - dev->oss.read_offset = 0; + dev->oss.read_count -= snd_pcm_lib_period_bytes(substream); + dev->oss.read_offset += snd_pcm_lib_period_bytes(substream); + if (dev->oss.read_offset == dev->oss.bufsize) + dev->oss.read_offset = 0; } return bytes_to_frames(runtime, dev->oss.read_offset); @@ -480,9 +480,9 @@ static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * static snd_pcm_hardware_t snd_card_saa7134_capture = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID), .formats = USE_FORMATS, .rates = USE_RATE, .rate_min = USE_RATE_MIN, @@ -550,16 +550,16 @@ static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream) static int dsp_buffer_free(struct saa7134_dev *dev) { - if (!dev->oss.blksize) - BUG(); + if (!dev->oss.blksize) + BUG(); - videobuf_dma_free(&dev->oss.dma); + videobuf_dma_free(&dev->oss.dma); - dev->oss.blocks = 0; - dev->oss.blksize = 0; - dev->oss.bufsize = 0; + dev->oss.blocks = 0; + dev->oss.blksize = 0; + dev->oss.bufsize = 0; - return 0; + return 0; } /* @@ -574,21 +574,21 @@ static int dsp_buffer_free(struct saa7134_dev *dev) static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) { - snd_card_saa7134_t *chip = snd_pcm_substream_chip(substream); + snd_card_saa7134_t *chip = snd_pcm_substream_chip(substream); struct saa7134_dev *dev = chip->saadev; - unsigned long flags; + unsigned long flags; - /* stop dma */ - spin_lock_irqsave(&dev->slock,flags); - saa7134_dma_stop(dev); - spin_unlock_irqrestore(&dev->slock,flags); + /* stop dma */ + spin_lock_irqsave(&dev->slock,flags); + saa7134_dma_stop(dev); + spin_unlock_irqrestore(&dev->slock,flags); - /* unlock buffer */ - saa7134_pgtable_free(dev->pci,&dev->oss.pt); - videobuf_dma_pci_unmap(dev->pci,&dev->oss.dma); + /* unlock buffer */ + saa7134_pgtable_free(dev->pci,&dev->oss.pt); + videobuf_dma_pci_unmap(dev->pci,&dev->oss.dma); - dsp_buffer_free(dev); - return 0; + dsp_buffer_free(dev); + return 0; } /* @@ -605,18 +605,18 @@ static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) { snd_pcm_runtime_t *runtime = substream->runtime; snd_card_saa7134_pcm_t *saapcm; - snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); - struct saa7134_dev *dev = saa7134->saadev; + snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); + struct saa7134_dev *dev = saa7134->saadev; int err; down(&dev->oss.lock); - dev->oss.afmt = SNDRV_PCM_FORMAT_U8; - dev->oss.channels = 2; - dev->oss.read_count = 0; - dev->oss.read_offset = 0; + dev->oss.afmt = SNDRV_PCM_FORMAT_U8; + dev->oss.channels = 2; + dev->oss.read_count = 0; + dev->oss.read_offset = 0; - up(&dev->oss.lock); + up(&dev->oss.lock); saapcm = kcalloc(1, sizeof(*saapcm), GFP_KERNEL); if (saapcm == NULL) @@ -630,8 +630,8 @@ static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) runtime->private_free = snd_card_saa7134_runtime_free; runtime->hw = snd_card_saa7134_capture; - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; + if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + return err; return 0; } @@ -723,7 +723,7 @@ static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ right = 20; spin_lock_irqsave(&chip->mixer_lock, flags); change = chip->mixer_volume[addr][0] != left || - chip->mixer_volume[addr][1] != right; + chip->mixer_volume[addr][1] != right; chip->mixer_volume[addr][0] = left; chip->mixer_volume[addr][1] = right; spin_unlock_irqrestore(&chip->mixer_lock, flags); @@ -764,7 +764,7 @@ static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ unsigned long flags; int change, addr = kcontrol->private_value; int left, right; - u32 anabar, xbarin; + u32 anabar, xbarin; int analog_io, rate; struct saa7134_dev *dev; @@ -775,7 +775,7 @@ static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ spin_lock_irqsave(&chip->mixer_lock, flags); change = chip->capture_source[addr][0] != left || - chip->capture_source[addr][1] != right; + chip->capture_source[addr][1] != right; chip->capture_source[addr][0] = left; chip->capture_source[addr][1] = right; dev->oss.input=addr; @@ -783,57 +783,57 @@ static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ if (change) { - switch (dev->pci->device) { + switch (dev->pci->device) { case PCI_DEVICE_ID_PHILIPS_SAA7134: - switch (addr) { - case MIXER_ADDR_TVTUNER: - saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0xc0); - saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, 0x00); - break; - case MIXER_ADDR_LINE1: - case MIXER_ADDR_LINE2: - analog_io = (MIXER_ADDR_LINE1 == addr) ? 0x00 : 0x08; - rate = (32000 == dev->oss.rate) ? 0x01 : 0x03; - saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, analog_io); - saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0x80); - saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, rate); - break; - } - - break; + switch (addr) { + case MIXER_ADDR_TVTUNER: + saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0xc0); + saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, 0x00); + break; + case MIXER_ADDR_LINE1: + case MIXER_ADDR_LINE2: + analog_io = (MIXER_ADDR_LINE1 == addr) ? 0x00 : 0x08; + rate = (32000 == dev->oss.rate) ? 0x01 : 0x03; + saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, analog_io); + saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0x80); + saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, rate); + break; + } + + break; case PCI_DEVICE_ID_PHILIPS_SAA7133: case PCI_DEVICE_ID_PHILIPS_SAA7135: - xbarin = 0x03; // adc + xbarin = 0x03; // adc anabar = 0; - switch (addr) { - case MIXER_ADDR_TVTUNER: - xbarin = 0; // Demodulator - anabar = 2; // DACs - break; - case MIXER_ADDR_LINE1: - anabar = 0; // aux1, aux1 - break; - case MIXER_ADDR_LINE2: - anabar = 9; // aux2, aux2 - break; - } + switch (addr) { + case MIXER_ADDR_TVTUNER: + xbarin = 0; // Demodulator + anabar = 2; // DACs + break; + case MIXER_ADDR_LINE1: + anabar = 0; // aux1, aux1 + break; + case MIXER_ADDR_LINE2: + anabar = 9; // aux2, aux2 + break; + } /* output xbar always main channel */ - saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL1, 0xbbbb10); + saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL1, 0xbbbb10); if (left || right) { // We've got data, turn the input on - //saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL2, 0x101010); - saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, xbarin); - saa_writel(SAA7133_ANALOG_IO_SELECT, anabar); + //saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL2, 0x101010); + saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, xbarin); + saa_writel(SAA7133_ANALOG_IO_SELECT, anabar); } else { - //saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL2, 0x101010); - saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, 0); - saa_writel(SAA7133_ANALOG_IO_SELECT, 0); + //saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL2, 0x101010); + saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, 0); + saa_writel(SAA7133_ANALOG_IO_SELECT, 0); } break; } - } + } return change; } @@ -878,8 +878,8 @@ static int snd_saa7134_free(snd_card_saa7134_t *chip) static int snd_saa7134_dev_free(snd_device_t *device) { - snd_card_saa7134_t *chip = device->device_data; - return snd_saa7134_free(chip); + snd_card_saa7134_t *chip = device->device_data; + return snd_saa7134_free(chip); } /* @@ -896,12 +896,12 @@ int alsa_card_saa7134_create(struct saa7134_dev *saadev, unsigned int devicenum) snd_card_t *card; snd_card_saa7134_t *chip; int err; - static snd_device_ops_t ops = { - .dev_free = snd_saa7134_dev_free, - }; + static snd_device_ops_t ops = { + .dev_free = snd_saa7134_dev_free, + }; - if (dev >= SNDRV_CARDS) - return -ENODEV; + if (dev >= SNDRV_CARDS) + return -ENODEV; if (!enable[dev]) return -ENODEV; @@ -918,24 +918,24 @@ int alsa_card_saa7134_create(struct saa7134_dev *saadev, unsigned int devicenum) /* Card "creation" */ chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - return -ENOMEM; - } + if (chip == NULL) { + return -ENOMEM; + } - spin_lock_init(&chip->lock); + spin_lock_init(&chip->lock); - chip->saadev = saadev; + chip->saadev = saadev; - chip->card = card; + chip->card = card; - chip->pci = saadev->pci; - chip->irq = saadev->pci->irq; - chip->iobase = pci_resource_start(saadev->pci, 0); + chip->pci = saadev->pci; + chip->irq = saadev->pci->irq; + chip->iobase = pci_resource_start(saadev->pci, 0); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_saa7134_free(chip); - return err; - } + if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + snd_saa7134_free(chip); + return err; + } if ((err = snd_card_saa7134_new_mixer(chip)) < 0) goto __nodev; @@ -943,15 +943,15 @@ int alsa_card_saa7134_create(struct saa7134_dev *saadev, unsigned int devicenum) if ((err = snd_card_saa7134_pcm(chip, 0)) < 0) goto __nodev; - spin_lock_init(&chip->mixer_lock); + spin_lock_init(&chip->mixer_lock); snd_card_set_dev(card, &chip->pci->dev); /* End of "creation" */ strcpy(card->shortname, "SAA7134"); - sprintf(card->longname, "%s at 0x%lx irq %d", - chip->saadev->name, chip->iobase, chip->irq); + sprintf(card->longname, "%s at 0x%lx irq %d", + chip->saadev->name, chip->iobase, chip->irq); if ((err = snd_card_register(card)) == 0) { snd_saa7134_cards[dev] = card; @@ -966,8 +966,8 @@ __nodev: void alsa_card_saa7134_exit(void) { - int idx; - for (idx = 0; idx < SNDRV_CARDS; idx++) { - snd_card_free(snd_saa7134_cards[idx]); + int idx; + for (idx = 0; idx < SNDRV_CARDS; idx++) { + snd_card_free(snd_saa7134_cards[idx]); } } diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 17b0549f2e1..a60d49af341 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2114,16 +2114,16 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_BEHOLD_409FM] = { - /* , Sergey */ - .name = "Beholder BeholdTV 409 FM", - .audio_clock = 0x00187de7, - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .inputs = {{ - .name = name_tv, + /* , Sergey */ + .name = "Beholder BeholdTV 409 FM", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, .vmux = 3, .amux = TV, .tv = 1, @@ -2131,60 +2131,60 @@ struct saa7134_board saa7134_boards[] = { .name = name_comp1, .vmux = 1, .amux = LINE1, - },{ - .name = name_svideo, + },{ + .name = name_svideo, .vmux = 8, .amux = LINE1, - }}, - .radio = { - .name = name_radio, + }}, + .radio = { + .name = name_radio, .amux = LINE2, - }, - }, - [SAA7134_BOARD_GOTVIEW_7135] = { + }, + }, + [SAA7134_BOARD_GOTVIEW_7135] = { /* Mike Baikov */ /* Andrey Cvetcov */ - .name = "GoTView 7135 PCI", - .audio_clock = 0x00187de7, - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .gpiomask = 0x00200003, - .inputs = {{ - .name = name_tv, - .vmux = 1, - .amux = TV, - .tv = 1, - .gpio = 0x00200003, - },{ - .name = name_tv_mono, - .vmux = 1, - .amux = LINE2, - .gpio = 0x00200003, - },{ - .name = name_comp1, - .vmux = 3, - .amux = LINE1, - .gpio = 0x00200003, - },{ - .name = name_svideo, - .vmux = 8, - .amux = LINE1, - .gpio = 0x00200003, - }}, - .radio = { - .name = name_radio, - .amux = LINE2, - .gpio = 0x00200003, - }, - .mute = { - .name = name_mute, - .amux = TV, - .gpio = 0x00200003, - }, - }, + .name = "GoTView 7135 PCI", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00200003, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + .gpio = 0x00200003, + },{ + .name = name_tv_mono, + .vmux = 1, + .amux = LINE2, + .gpio = 0x00200003, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + .gpio = 0x00200003, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + .gpio = 0x00200003, + }}, + .radio = { + .name = name_radio, + .amux = LINE2, + .gpio = 0x00200003, + }, + .mute = { + .name = name_mute, + .amux = TV, + .gpio = 0x00200003, + }, + }, [SAA7134_BOARD_PHILIPS_EUROPA] = { .name = "Philips EUROPA V3 reference design", .audio_clock = 0x00187de7, @@ -2251,78 +2251,78 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, }}, }, - [SAA7134_BOARD_RTD_VFG7350] = { - .name = "RTD Embedded Technologies VFG7350", - .audio_clock = 0x00200000, - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .inputs = {{ - .name = "Composite 0", - .vmux = 0, - .amux = LINE1, - },{ - .name = "Composite 1", - .vmux = 1, - .amux = LINE2, - },{ - .name = "Composite 2", - .vmux = 2, - .amux = LINE1, - },{ - .name = "Composite 3", - .vmux = 3, - .amux = LINE2, - },{ - .name = "S-Video 0", - .vmux = 8, - .amux = LINE1, - },{ - .name = "S-Video 1", - .vmux = 9, - .amux = LINE2, - }}, - .mpeg = SAA7134_MPEG_EMPRESS, - .video_out = CCIR656, + [SAA7134_BOARD_RTD_VFG7350] = { + .name = "RTD Embedded Technologies VFG7350", + .audio_clock = 0x00200000, + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = {{ + .name = "Composite 0", + .vmux = 0, + .amux = LINE1, + },{ + .name = "Composite 1", + .vmux = 1, + .amux = LINE2, + },{ + .name = "Composite 2", + .vmux = 2, + .amux = LINE1, + },{ + .name = "Composite 3", + .vmux = 3, + .amux = LINE2, + },{ + .name = "S-Video 0", + .vmux = 8, + .amux = LINE1, + },{ + .name = "S-Video 1", + .vmux = 9, + .amux = LINE2, + }}, + .mpeg = SAA7134_MPEG_EMPRESS, + .video_out = CCIR656, .vid_port_opts = ( SET_T_CODE_POLARITY_NON_INVERTED | SET_CLOCK_NOT_DELAYED | SET_CLOCK_INVERTED | SET_VSYNC_OFF ), - }, - [SAA7134_BOARD_RTD_VFG7330] = { - .name = "RTD Embedded Technologies VFG7330", - .audio_clock = 0x00200000, - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .inputs = {{ - .name = "Composite 0", - .vmux = 0, - .amux = LINE1, - },{ - .name = "Composite 1", - .vmux = 1, - .amux = LINE2, - },{ - .name = "Composite 2", - .vmux = 2, - .amux = LINE1, - },{ - .name = "Composite 3", - .vmux = 3, - .amux = LINE2, - },{ - .name = "S-Video 0", - .vmux = 8, - .amux = LINE1, - },{ - .name = "S-Video 1", - .vmux = 9, - .amux = LINE2, - }}, - }, + }, + [SAA7134_BOARD_RTD_VFG7330] = { + .name = "RTD Embedded Technologies VFG7330", + .audio_clock = 0x00200000, + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = {{ + .name = "Composite 0", + .vmux = 0, + .amux = LINE1, + },{ + .name = "Composite 1", + .vmux = 1, + .amux = LINE2, + },{ + .name = "Composite 2", + .vmux = 2, + .amux = LINE1, + },{ + .name = "Composite 3", + .vmux = 3, + .amux = LINE2, + },{ + .name = "S-Video 0", + .vmux = 8, + .amux = LINE1, + },{ + .name = "S-Video 1", + .vmux = 9, + .amux = LINE2, + }}, + }, [SAA7134_BOARD_FLYTVPLATINUM_MINI2] = { .name = "LifeView FlyTV Platinum Mini2", .audio_clock = 0x00200000, @@ -2760,55 +2760,55 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x0000, /* It shouldn't break anything, since subdevice id seems unique */ .subdevice = 0x4091, .driver_data = SAA7134_BOARD_BEHOLD_409FM, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5456, /* GoTView */ - .subdevice = 0x7135, - .driver_data = SAA7134_BOARD_GOTVIEW_7135, - },{ + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5456, /* GoTView */ + .subdevice = 0x7135, + .driver_data = SAA7134_BOARD_GOTVIEW_7135, + },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, .subvendor = PCI_VENDOR_ID_PHILIPS, .subdevice = 0x2004, .driver_data = SAA7134_BOARD_PHILIPS_EUROPA, - },{ + },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, .subvendor = 0x185b, .subdevice = 0xc900, .driver_data = SAA7134_BOARD_VIDEOMATE_DVBT_300, - },{ + },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, .subvendor = 0x185b, .subdevice = 0xc901, .driver_data = SAA7134_BOARD_VIDEOMATE_DVBT_200, },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1435, - .subdevice = 0x7350, - .driver_data = SAA7134_BOARD_RTD_VFG7350, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1435, - .subdevice = 0x7330, - .driver_data = SAA7134_BOARD_RTD_VFG7330, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, - .subdevice = 0x1044, - .driver_data = SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180, - },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1435, + .subdevice = 0x7350, + .driver_data = SAA7134_BOARD_RTD_VFG7350, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1435, + .subdevice = 0x7330, + .driver_data = SAA7134_BOARD_RTD_VFG7330, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, + .subdevice = 0x1044, + .driver_data = SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180, + },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x1131, .subdevice = 0x4ee9, .driver_data = SAA7134_BOARD_MONSTERTV_MOBILE, - },{ + },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -3051,7 +3051,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) case SAA7134_BOARD_VIDEOMATE_DVBT_300: /* The Philips EUROPA based hybrid boards have the tuner connected through * the channel decoder. We have to make it transparent to find it - */ + */ { struct tuner_setup tun_setup; u8 data[] = { 0x07, 0x02}; @@ -3063,7 +3063,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) tun_setup.addr = dev->tuner_addr; saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup); - } + } break; } return 0; diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 907dbd4de7c..afa0cfce657 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -201,10 +201,10 @@ static int pending_call(struct notifier_block *self, unsigned long state, if (module != THIS_MODULE || state != MODULE_STATE_LIVE) return NOTIFY_DONE; - if (need_empress) - request_module("saa7134-empress"); - if (need_dvb) - request_module("saa7134-dvb"); + if (need_empress) + request_module("saa7134-empress"); + if (need_dvb) + request_module("saa7134-dvb"); return NOTIFY_DONE; } @@ -279,8 +279,8 @@ unsigned long saa7134_buffer_base(struct saa7134_buf *buf) int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt) { - __le32 *cpu; - dma_addr_t dma_addr; + __le32 *cpu; + dma_addr_t dma_addr; cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr); if (NULL == cpu) @@ -440,7 +440,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev) ctrl |= SAA7134_MAIN_CTRL_TE0; irq |= SAA7134_IRQ1_INTE_RA0_1 | SAA7134_IRQ1_INTE_RA0_0; - cap = dev->video_q.curr->vb.field; + cap = dev->video_q.curr->vb.field; } /* video capture -- dma 1+2 (planar modes) */ @@ -646,7 +646,7 @@ static int saa7134_hwinit1(struct saa7134_dev *dev) saa_writel(SAA7134_IRQ1, 0); saa_writel(SAA7134_IRQ2, 0); - init_MUTEX(&dev->lock); + init_MUTEX(&dev->lock); spin_lock_init(&dev->slock); saa7134_track_gpio(dev,"pre-init"); @@ -704,7 +704,7 @@ static int saa7134_hwinit2(struct saa7134_dev *dev) saa7134_tvaudio_init2(dev); /* enable IRQ's */ - irq2_mask = + irq2_mask = SAA7134_IRQ2_INTE_DEC3 | SAA7134_IRQ2_INTE_DEC2 | SAA7134_IRQ2_INTE_DEC1 | @@ -889,8 +889,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, /* print pci info */ pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); - pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); - printk(KERN_INFO "%s: found at %s, rev: %d, irq: %d, " + pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); + printk(KERN_INFO "%s: found at %s, rev: %d, irq: %d, " "latency: %d, mmio: 0x%lx\n", dev->name, pci_name(pci_dev), dev->pci_rev, pci_dev->irq, dev->pci_lat,pci_resource_start(pci_dev,0)); @@ -914,7 +914,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf; if (UNSET != tuner[dev->nr]) dev->tuner_type = tuner[dev->nr]; - printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", + printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", dev->name,pci_dev->subsystem_vendor, pci_dev->subsystem_device,saa7134_boards[dev->board].name, dev->board, card[dev->nr] == dev->board ? @@ -964,12 +964,12 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, request_module("tuner"); if (dev->tda9887_conf) request_module("tda9887"); - if (card_is_empress(dev)) { + if (card_is_empress(dev)) { request_module("saa6752hs"); request_module_depend("saa7134-empress",&need_empress); } - if (card_is_dvb(dev)) + if (card_is_dvb(dev)) request_module_depend("saa7134-dvb",&need_dvb); v4l2_prio_init(&dev->prio); @@ -1078,7 +1078,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, static void __devexit saa7134_finidev(struct pci_dev *pci_dev) { - struct saa7134_dev *dev = pci_get_drvdata(pci_dev); + struct saa7134_dev *dev = pci_get_drvdata(pci_dev); struct list_head *item; struct saa7134_mpeg_ops *mops; @@ -1173,10 +1173,10 @@ EXPORT_SYMBOL(saa7134_ts_unregister); /* ----------------------------------------------------------- */ static struct pci_driver saa7134_pci_driver = { - .name = "saa7134", - .id_table = saa7134_pci_tbl, - .probe = saa7134_initdev, - .remove = __devexit_p(saa7134_finidev), + .name = "saa7134", + .id_table = saa7134_pci_tbl, + .probe = saa7134_initdev, + .remove = __devexit_p(saa7134_finidev), }; static int saa7134_init(void) diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 87641f7e432..5aadd44c2fa 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -547,7 +547,7 @@ static int philips_tda827x_pll_set(struct dvb_frontend *fe, struct dvb_frontend_ u8 tuner_buf[14]; struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf, - .len = sizeof(tuner_buf) }; + .len = sizeof(tuner_buf) }; int i, tuner_freq, if_freq; u32 N; switch (params->u.ofdm.bandwidth) { @@ -606,7 +606,7 @@ static void philips_tda827x_pll_sleep(struct dvb_frontend *fe) struct saa7134_dev *dev = fe->dvb->priv; static u8 tda827x_sleep[] = { 0x30, 0xd0}; struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tda827x_sleep, - .len = sizeof(tda827x_sleep) }; + .len = sizeof(tda827x_sleep) }; i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); } diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 77b627eb648..e9ec69efb4c 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -55,7 +55,7 @@ static void ts_reset_encoder(struct saa7134_dev* dev) saa_writeb(SAA7134_SPECIAL_MODE, 0x00); msleep(10); - saa_writeb(SAA7134_SPECIAL_MODE, 0x01); + saa_writeb(SAA7134_SPECIAL_MODE, 0x01); msleep(100); dev->empress_started = 0; } @@ -65,7 +65,7 @@ static int ts_init_encoder(struct saa7134_dev* dev) ts_reset_encoder(dev); saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, NULL); dev->empress_started = 1; - return 0; + return 0; } /* ------------------------------------------------------------------ */ @@ -169,7 +169,7 @@ static int ts_do_ioctl(struct inode *inode, struct file *file, struct v4l2_capability *cap = arg; memset(cap,0,sizeof(*cap)); - strcpy(cap->driver, "saa7134"); + strcpy(cap->driver, "saa7134"); strlcpy(cap->card, saa7134_boards[dev->board].name, sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index 711aa8e85fa..2577d03485b 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c @@ -239,7 +239,7 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap, unsigned char data; int addr,rc,i,byte; - status = i2c_get_status(dev); + status = i2c_get_status(dev); if (!i2c_is_idle(status)) if (!i2c_reset(dev)) return -EIO; @@ -296,7 +296,7 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap, rc = -EIO; if (!i2c_is_busy_wait(dev)) goto err; - status = i2c_get_status(dev); + status = i2c_get_status(dev); if (i2c_is_error(status)) goto err; /* ensure that the bus is idle for at least one bit slot */ @@ -348,12 +348,12 @@ static int attach_inform(struct i2c_client *client) client->driver->command(client, TUNER_SET_TYPE_ADDR, &tun_setup); } - } + } if (tuner != UNSET) { - tun_setup.type = tuner; - tun_setup.addr = saa7134_boards[dev->board].tuner_addr; + tun_setup.type = tuner; + tun_setup.addr = saa7134_boards[dev->board].tuner_addr; if ((tun_setup.addr == ADDR_UNSET)||(tun_setup.addr == client->addr)) { @@ -361,11 +361,11 @@ static int attach_inform(struct i2c_client *client) client->driver->command(client,TUNER_SET_TYPE_ADDR, &tun_setup); } - } + } client->driver->command(client, TDA9887_SET_CONFIG, &conf); - return 0; + return 0; } static struct i2c_algorithm saa7134_algo = { diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 9dc41c1427a..7ce0459989b 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -114,24 +114,24 @@ static IR_KEYTAB_TYPE cinergy_codes[IR_KEYTAB_SIZE] = { /* Alfons Geser * updates from Job D. R. Borges */ static IR_KEYTAB_TYPE eztv_codes[IR_KEYTAB_SIZE] = { - [ 18 ] = KEY_POWER, - [ 1 ] = KEY_TV, // DVR - [ 21 ] = KEY_DVD, // DVD - [ 23 ] = KEY_AUDIO, // music - // DVR mode / DVD mode / music mode - - [ 27 ] = KEY_MUTE, // mute - [ 2 ] = KEY_LANGUAGE, // MTS/SAP / audio / autoseek - [ 30 ] = KEY_SUBTITLE, // closed captioning / subtitle / seek - [ 22 ] = KEY_ZOOM, // full screen - [ 28 ] = KEY_VIDEO, // video source / eject / delall - [ 29 ] = KEY_RESTART, // playback / angle / del - [ 47 ] = KEY_SEARCH, // scan / menu / playlist - [ 48 ] = KEY_CHANNEL, // CH surfing / bookmark / memo - - [ 49 ] = KEY_HELP, // help - [ 50 ] = KEY_MODE, // num/memo - [ 51 ] = KEY_ESC, // cancel + [ 18 ] = KEY_POWER, + [ 1 ] = KEY_TV, // DVR + [ 21 ] = KEY_DVD, // DVD + [ 23 ] = KEY_AUDIO, // music + // DVR mode / DVD mode / music mode + + [ 27 ] = KEY_MUTE, // mute + [ 2 ] = KEY_LANGUAGE, // MTS/SAP / audio / autoseek + [ 30 ] = KEY_SUBTITLE, // closed captioning / subtitle / seek + [ 22 ] = KEY_ZOOM, // full screen + [ 28 ] = KEY_VIDEO, // video source / eject / delall + [ 29 ] = KEY_RESTART, // playback / angle / del + [ 47 ] = KEY_SEARCH, // scan / menu / playlist + [ 48 ] = KEY_CHANNEL, // CH surfing / bookmark / memo + + [ 49 ] = KEY_HELP, // help + [ 50 ] = KEY_MODE, // num/memo + [ 51 ] = KEY_ESC, // cancel [ 12 ] = KEY_UP, // up [ 16 ] = KEY_DOWN, // down @@ -148,24 +148,24 @@ static IR_KEYTAB_TYPE eztv_codes[IR_KEYTAB_SIZE] = { [ 45 ] = KEY_PLAY, // play [ 46 ] = KEY_SHUFFLE, // snapshot / shuffle - [ 0 ] = KEY_KP0, - [ 5 ] = KEY_KP1, - [ 6 ] = KEY_KP2, - [ 7 ] = KEY_KP3, - [ 9 ] = KEY_KP4, - [ 10 ] = KEY_KP5, - [ 11 ] = KEY_KP6, - [ 13 ] = KEY_KP7, - [ 14 ] = KEY_KP8, - [ 15 ] = KEY_KP9, - - [ 42 ] = KEY_VOLUMEUP, - [ 17 ] = KEY_VOLUMEDOWN, - [ 24 ] = KEY_CHANNELUP, // CH.tracking up - [ 25 ] = KEY_CHANNELDOWN, // CH.tracking down - - [ 19 ] = KEY_KPENTER, // enter - [ 33 ] = KEY_KPDOT, // . (decimal dot) + [ 0 ] = KEY_KP0, + [ 5 ] = KEY_KP1, + [ 6 ] = KEY_KP2, + [ 7 ] = KEY_KP3, + [ 9 ] = KEY_KP4, + [ 10 ] = KEY_KP5, + [ 11 ] = KEY_KP6, + [ 13 ] = KEY_KP7, + [ 14 ] = KEY_KP8, + [ 15 ] = KEY_KP9, + + [ 42 ] = KEY_VOLUMEUP, + [ 17 ] = KEY_VOLUMEDOWN, + [ 24 ] = KEY_CHANNELUP, // CH.tracking up + [ 25 ] = KEY_CHANNELDOWN, // CH.tracking down + + [ 19 ] = KEY_KPENTER, // enter + [ 33 ] = KEY_KPDOT, // . (decimal dot) }; static IR_KEYTAB_TYPE avacssmart_codes[IR_KEYTAB_SIZE] = { @@ -455,13 +455,13 @@ static int build_key(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN); gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); - if (ir->polling) { - if (ir->last_gpio == gpio) - return 0; - ir->last_gpio = gpio; - } + if (ir->polling) { + if (ir->last_gpio == gpio) + return 0; + ir->last_gpio = gpio; + } - data = ir_extract_bits(gpio, ir->mask_keycode); + data = ir_extract_bits(gpio, ir->mask_keycode); dprintk("build_key gpio=0x%x mask=0x%x data=%d\n", gpio, ir->mask_keycode, data); @@ -478,9 +478,9 @@ static int build_key(struct saa7134_dev *dev) void saa7134_input_irq(struct saa7134_dev *dev) { - struct saa7134_ir *ir = dev->remote; + struct saa7134_ir *ir = dev->remote; - if (!ir->polling) + if (!ir->polling) build_key(dev); } @@ -515,7 +515,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) switch (dev->board) { case SAA7134_BOARD_FLYVIDEO2000: case SAA7134_BOARD_FLYVIDEO3000: - case SAA7134_BOARD_FLYTVPLATINUM_FM: + case SAA7134_BOARD_FLYTVPLATINUM_FM: case SAA7134_BOARD_FLYTVPLATINUM_MINI2: ir_codes = flyvideo_codes; mask_keycode = 0xEC00000; @@ -557,7 +557,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPMODE0, 0x4); saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); break; - case SAA7134_BOARD_KWORLD_TERMINATOR: + case SAA7134_BOARD_KWORLD_TERMINATOR: ir_codes = avacssmart_codes; mask_keycode = 0x00001f; mask_keyup = 0x000060; @@ -571,7 +571,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keyup = 0x004000; polling = 50; // ms break; - case SAA7134_BOARD_GOTVIEW_7135: + case SAA7134_BOARD_GOTVIEW_7135: ir_codes = gotview7135_codes; mask_keycode = 0x0003EC; mask_keyup = 0x008000; @@ -585,8 +585,8 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keyup = 0x400000; polling = 50; // ms break; - case SAA7134_BOARD_VIDEOMATE_DVBT_300: - case SAA7134_BOARD_VIDEOMATE_DVBT_200: + case SAA7134_BOARD_VIDEOMATE_DVBT_300: + case SAA7134_BOARD_VIDEOMATE_DVBT_200: ir_codes = videomate_tv_pvr_codes; mask_keycode = 0x003F00; mask_keyup = 0x040000; @@ -610,7 +610,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) ir->mask_keycode = mask_keycode; ir->mask_keydown = mask_keydown; ir->mask_keyup = mask_keyup; - ir->polling = polling; + ir->polling = polling; /* init input device */ snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c index b1dcb4d1078..f1b0e0d93d7 100644 --- a/drivers/media/video/saa7134/saa7134-oss.c +++ b/drivers/media/video/saa7134/saa7134-oss.c @@ -64,7 +64,7 @@ static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) dev->oss.bufsize = blksize * blocks; dprintk("buffer config: %d blocks / %d bytes, %d kB total\n", - blocks,blksize,blksize * blocks / 1024); + blocks,blksize,blksize * blocks / 1024); return 0; } @@ -371,20 +371,20 @@ static int dsp_ioctl(struct inode *inode, struct file *file, if (oss_debug > 1) saa7134_print_ioctl(dev->name,cmd); - switch (cmd) { - case OSS_GETVERSION: - return put_user(SOUND_VERSION, p); - case SNDCTL_DSP_GETCAPS: + switch (cmd) { + case OSS_GETVERSION: + return put_user(SOUND_VERSION, p); + case SNDCTL_DSP_GETCAPS: return 0; - case SNDCTL_DSP_SPEED: + case SNDCTL_DSP_SPEED: if (get_user(val, p)) return -EFAULT; /* fall through */ - case SOUND_PCM_READ_RATE: + case SOUND_PCM_READ_RATE: return put_user(dev->oss.rate, p); - case SNDCTL_DSP_STEREO: + case SNDCTL_DSP_STEREO: if (get_user(val, p)) return -EFAULT; down(&dev->oss.lock); @@ -396,7 +396,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file, up(&dev->oss.lock); return put_user(dev->oss.channels-1, p); - case SNDCTL_DSP_CHANNELS: + case SNDCTL_DSP_CHANNELS: if (get_user(val, p)) return -EFAULT; if (val != 1 && val != 2) @@ -409,15 +409,15 @@ static int dsp_ioctl(struct inode *inode, struct file *file, } up(&dev->oss.lock); /* fall through */ - case SOUND_PCM_READ_CHANNELS: + case SOUND_PCM_READ_CHANNELS: return put_user(dev->oss.channels, p); - case SNDCTL_DSP_GETFMTS: /* Returns a mask */ + case SNDCTL_DSP_GETFMTS: /* Returns a mask */ return put_user(AFMT_U8 | AFMT_S8 | AFMT_U16_LE | AFMT_U16_BE | AFMT_S16_LE | AFMT_S16_BE, p); - case SNDCTL_DSP_SETFMT: /* Selects ONE fmt */ + case SNDCTL_DSP_SETFMT: /* Selects ONE fmt */ if (get_user(val, p)) return -EFAULT; switch (val) { @@ -442,7 +442,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file, return -EINVAL; } - case SOUND_PCM_READ_BITS: + case SOUND_PCM_READ_BITS: switch (dev->oss.afmt) { case AFMT_U8: case AFMT_S8: @@ -456,20 +456,20 @@ static int dsp_ioctl(struct inode *inode, struct file *file, return -EINVAL; } - case SNDCTL_DSP_NONBLOCK: - file->f_flags |= O_NONBLOCK; - return 0; + case SNDCTL_DSP_NONBLOCK: + file->f_flags |= O_NONBLOCK; + return 0; - case SNDCTL_DSP_RESET: + case SNDCTL_DSP_RESET: down(&dev->oss.lock); if (dev->oss.recording_on) dsp_rec_stop(dev); up(&dev->oss.lock); return 0; - case SNDCTL_DSP_GETBLKSIZE: + case SNDCTL_DSP_GETBLKSIZE: return put_user(dev->oss.blksize, p); - case SNDCTL_DSP_SETFRAGMENT: + case SNDCTL_DSP_SETFRAGMENT: if (get_user(val, p)) return -EFAULT; if (dev->oss.recording_on) @@ -480,7 +480,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file, dsp_buffer_init(dev); return 0; - case SNDCTL_DSP_SYNC: + case SNDCTL_DSP_SYNC: /* NOP */ return 0; @@ -563,7 +563,7 @@ mixer_recsrc_7133(struct saa7134_dev *dev) switch (dev->oss.input) { case TV: xbarin = 0; // Demodulator - anabar = 2; // DACs + anabar = 2; // DACs break; case LINE1: anabar = 0; // aux1, aux1 @@ -667,28 +667,28 @@ static int mixer_ioctl(struct inode *inode, struct file *file, if (oss_debug > 1) saa7134_print_ioctl(dev->name,cmd); - switch (cmd) { - case OSS_GETVERSION: - return put_user(SOUND_VERSION, p); + switch (cmd) { + case OSS_GETVERSION: + return put_user(SOUND_VERSION, p); case SOUND_MIXER_INFO: { mixer_info info; memset(&info,0,sizeof(info)); - strlcpy(info.id, "TV audio", sizeof(info.id)); - strlcpy(info.name, dev->name, sizeof(info.name)); - info.modify_counter = dev->oss.count; - if (copy_to_user(argp, &info, sizeof(info))) - return -EFAULT; + strlcpy(info.id, "TV audio", sizeof(info.id)); + strlcpy(info.name, dev->name, sizeof(info.name)); + info.modify_counter = dev->oss.count; + if (copy_to_user(argp, &info, sizeof(info))) + return -EFAULT; return 0; } case SOUND_OLD_MIXER_INFO: { _old_mixer_info info; memset(&info,0,sizeof(info)); - strlcpy(info.id, "TV audio", sizeof(info.id)); - strlcpy(info.name, dev->name, sizeof(info.name)); - if (copy_to_user(argp, &info, sizeof(info))) - return -EFAULT; + strlcpy(info.id, "TV audio", sizeof(info.id)); + strlcpy(info.name, dev->name, sizeof(info.name)); + if (copy_to_user(argp, &info, sizeof(info))) + return -EFAULT; return 0; } case MIXER_READ(SOUND_MIXER_CAPS): @@ -771,7 +771,7 @@ struct file_operations saa7134_mixer_fops = { int saa7134_oss_init1(struct saa7134_dev *dev) { /* general */ - init_MUTEX(&dev->oss.lock); + init_MUTEX(&dev->oss.lock); init_waitqueue_head(&dev->oss.wq); switch (dev->pci->device) { diff --git a/drivers/media/video/saa7134/saa7134-reg.h b/drivers/media/video/saa7134/saa7134-reg.h index 58c521fade8..ac6431ba4fc 100644 --- a/drivers/media/video/saa7134/saa7134-reg.h +++ b/drivers/media/video/saa7134/saa7134-reg.h @@ -27,7 +27,7 @@ /* DMA channels, n = 0 ... 6 */ #define SAA7134_RS_BA1(n) ((0x200 >> 2) + 4*n) -#define SAA7134_RS_BA2(n) ((0x204 >> 2) + 4*n) +#define SAA7134_RS_BA2(n) ((0x204 >> 2) + 4*n) #define SAA7134_RS_PITCH(n) ((0x208 >> 2) + 4*n) #define SAA7134_RS_CONTROL(n) ((0x20c >> 2) + 4*n) #define SAA7134_RS_CONTROL_WSWAP (0x01 << 25) @@ -53,14 +53,14 @@ /* main control */ #define SAA7134_MAIN_CTRL (0x2a8 >> 2) -#define SAA7134_MAIN_CTRL_VPLLE (1 << 15) -#define SAA7134_MAIN_CTRL_APLLE (1 << 14) -#define SAA7134_MAIN_CTRL_EXOSC (1 << 13) -#define SAA7134_MAIN_CTRL_EVFE1 (1 << 12) -#define SAA7134_MAIN_CTRL_EVFE2 (1 << 11) -#define SAA7134_MAIN_CTRL_ESFE (1 << 10) -#define SAA7134_MAIN_CTRL_EBADC (1 << 9) -#define SAA7134_MAIN_CTRL_EBDAC (1 << 8) +#define SAA7134_MAIN_CTRL_VPLLE (1 << 15) +#define SAA7134_MAIN_CTRL_APLLE (1 << 14) +#define SAA7134_MAIN_CTRL_EXOSC (1 << 13) +#define SAA7134_MAIN_CTRL_EVFE1 (1 << 12) +#define SAA7134_MAIN_CTRL_EVFE2 (1 << 11) +#define SAA7134_MAIN_CTRL_ESFE (1 << 10) +#define SAA7134_MAIN_CTRL_EBADC (1 << 9) +#define SAA7134_MAIN_CTRL_EBDAC (1 << 8) #define SAA7134_MAIN_CTRL_TE6 (1 << 6) #define SAA7134_MAIN_CTRL_TE5 (1 << 5) #define SAA7134_MAIN_CTRL_TE4 (1 << 4) diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c index cdfd69873ba..470903e2f5e 100644 --- a/drivers/media/video/saa7134/saa7134-ts.c +++ b/drivers/media/video/saa7134/saa7134-ts.c @@ -111,8 +111,8 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, /* dma: setup channel 5 (= TS) */ control = SAA7134_RS_CONTROL_BURST_16 | - SAA7134_RS_CONTROL_ME | - (buf->pt->dma >> 12); + SAA7134_RS_CONTROL_ME | + (buf->pt->dma >> 12); saa_writeb(SAA7134_TS_DMA0, ((lines-1)&0xff)); saa_writeb(SAA7134_TS_DMA1, (((lines-1)>>8)&0xff)); diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index fdca6c563b9..3daf1b59795 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -246,7 +246,7 @@ static void mute_input_7134(struct saa7134_dev *dev) if (PCI_DEVICE_ID_PHILIPS_SAA7134 == dev->pci->device) /* 7134 mute */ saa_writeb(SAA7134_AUDIO_MUTE_CTRL, mute ? - SAA7134_MUTE_MASK | + SAA7134_MUTE_MASK | SAA7134_MUTE_ANALOG | SAA7134_MUTE_I2S : SAA7134_MUTE_MASK); @@ -761,17 +761,17 @@ static int mute_input_7133(struct saa7134_dev *dev) /* switch gpio-connected external audio mux */ - if (0 != card(dev).gpiomask) { - mask = card(dev).gpiomask; + if (0 != card(dev).gpiomask) { + mask = card(dev).gpiomask; if (card(dev).mute.name && dev->ctl_mute) in = &card(dev).mute; else in = dev->input; - saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, mask, mask); - saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, in->gpio); - saa7134_track_gpio(dev,in->name); + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, mask, mask); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, in->gpio); + saa7134_track_gpio(dev,in->name); } return 0; diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index cd5545b2d60..86db7fb96ef 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -310,12 +310,12 @@ static struct saa7134_tvnorm tvnorms[] = { .h_start = 0, .h_stop = 719, - .video_v_start = 23, - .video_v_stop = 262, - .vbi_v_start_0 = 10, - .vbi_v_stop_0 = 21, - .vbi_v_start_1 = 273, - .src_timing = 7, + .video_v_start = 23, + .video_v_stop = 262, + .vbi_v_start_0 = 10, + .vbi_v_stop_0 = 21, + .vbi_v_start_1 = 273, + .src_timing = 7, .sync_control = 0x18, .luma_control = 0x40, @@ -659,7 +659,7 @@ static void set_size(struct saa7134_dev *dev, int task, prescale = 1; xscale = 1024 * dev->crop_current.width / prescale / width; yscale = 512 * div * dev->crop_current.height / height; - dprintk("prescale=%d xscale=%d yscale=%d\n",prescale,xscale,yscale); + dprintk("prescale=%d xscale=%d yscale=%d\n",prescale,xscale,yscale); set_h_prescale(dev,task,prescale); saa_writeb(SAA7134_H_SCALE_INC1(task), xscale & 0xff); saa_writeb(SAA7134_H_SCALE_INC2(task), xscale >> 8); @@ -789,20 +789,20 @@ static int verify_preview(struct saa7134_dev *dev, struct v4l2_window *win) maxh = dev->crop_current.height; if (V4L2_FIELD_ANY == field) { - field = (win->w.height > maxh/2) - ? V4L2_FIELD_INTERLACED - : V4L2_FIELD_TOP; - } - switch (field) { - case V4L2_FIELD_TOP: - case V4L2_FIELD_BOTTOM: - maxh = maxh / 2; - break; - case V4L2_FIELD_INTERLACED: - break; - default: - return -EINVAL; - } + field = (win->w.height > maxh/2) + ? V4L2_FIELD_INTERLACED + : V4L2_FIELD_TOP; + } + switch (field) { + case V4L2_FIELD_TOP: + case V4L2_FIELD_BOTTOM: + maxh = maxh / 2; + break; + case V4L2_FIELD_INTERLACED: + break; + default: + return -EINVAL; + } win->field = field; if (win->w.width > maxw) @@ -1343,13 +1343,13 @@ video_poll(struct file *file, struct poll_table_struct *wait) if (res_locked(fh->dev,RESOURCE_VIDEO)) { up(&fh->cap.lock); return POLLERR; - } - if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field)) { - up(&fh->cap.lock); - return POLLERR; - } - fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); - fh->cap.read_off = 0; + } + if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field)) { + up(&fh->cap.lock); + return POLLERR; + } + fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); + fh->cap.read_off = 0; } up(&fh->cap.lock); buf = fh->cap.read_buf; @@ -1706,7 +1706,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, unsigned int tuner_type = dev->tuner_type; memset(cap,0,sizeof(*cap)); - strcpy(cap->driver, "saa7134"); + strcpy(cap->driver, "saa7134"); strlcpy(cap->card, saa7134_boards[dev->board].name, sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); @@ -1934,26 +1934,26 @@ static int video_do_ioctl(struct inode *inode, struct file *file, } case VIDIOC_S_AUDIO: return 0; - case VIDIOC_G_PARM: - { - struct v4l2_captureparm *parm = arg; - memset(parm,0,sizeof(*parm)); - return 0; - } - - case VIDIOC_G_PRIORITY: - { - enum v4l2_priority *p = arg; - - *p = v4l2_prio_max(&dev->prio); - return 0; - } - case VIDIOC_S_PRIORITY: - { - enum v4l2_priority *prio = arg; - - return v4l2_prio_change(&dev->prio, &fh->prio, *prio); - } + case VIDIOC_G_PARM: + { + struct v4l2_captureparm *parm = arg; + memset(parm,0,sizeof(*parm)); + return 0; + } + + case VIDIOC_G_PRIORITY: + { + enum v4l2_priority *p = arg; + + *p = v4l2_prio_max(&dev->prio); + return 0; + } + case VIDIOC_S_PRIORITY: + { + enum v4l2_priority *prio = arg; + + return v4l2_prio_change(&dev->prio, &fh->prio, *prio); + } /* --- preview ioctls ---------------------------------------- */ case VIDIOC_ENUM_FMT: @@ -2102,7 +2102,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, { int res = saa7134_resource(fh); - if (!res_get(dev,fh,res)) + if (!res_get(dev,fh,res)) return -EBUSY; return videobuf_streamon(saa7134_queue(fh)); } @@ -2144,7 +2144,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, struct v4l2_capability *cap = arg; memset(cap,0,sizeof(*cap)); - strcpy(cap->driver, "saa7134"); + strcpy(cap->driver, "saa7134"); strlcpy(cap->card, saa7134_boards[dev->board].name, sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); @@ -2275,7 +2275,7 @@ struct video_device saa7134_video_template = { .name = "saa7134-video", .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_OVERLAY| - VID_TYPE_CLIPPING|VID_TYPE_SCALES, + VID_TYPE_CLIPPING|VID_TYPE_SCALES, .hardware = 0, .fops = &video_fops, .minor = -1, @@ -2322,7 +2322,7 @@ int saa7134_video_init1(struct saa7134_dev *dev) dev->tda9887_conf |= TDA9887_AUTOMUTE; dev->automute = 0; - INIT_LIST_HEAD(&dev->video_q.queue); + INIT_LIST_HEAD(&dev->video_q.queue); init_timer(&dev->video_q.timeout); dev->video_q.timeout.function = saa7134_buffer_timeout; dev->video_q.timeout.data = (unsigned long)(&dev->video_q); diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 99bbdcf727c..064c2f7a8c1 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -346,7 +346,7 @@ struct saa7134_fh { /* oss dsp status */ struct saa7134_oss { - struct semaphore lock; + struct semaphore lock; int minor_mixer; int minor_dsp; unsigned int users_dsp; @@ -384,9 +384,9 @@ struct saa7134_ir { u32 mask_keycode; u32 mask_keydown; u32 mask_keyup; - int polling; - u32 last_gpio; - struct timer_list timer; + int polling; + u32 last_gpio; + struct timer_list timer; }; /* ts/mpeg status */ @@ -409,8 +409,8 @@ struct saa7134_mpeg_ops { /* global device status */ struct saa7134_dev { struct list_head devlist; - struct semaphore lock; - spinlock_t slock; + struct semaphore lock; + spinlock_t slock; #ifdef VIDIOC_G_PRIORITY struct v4l2_prio_state prio; #endif diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c index 255b6088ebf..14cf1d357c3 100644 --- a/drivers/media/video/tda7432.c +++ b/drivers/media/video/tda7432.c @@ -310,9 +310,9 @@ static int tda7432_attach(struct i2c_adapter *adap, int addr, int kind) memset(t,0,sizeof *t); client = &t->c; - memcpy(client,&client_template,sizeof(struct i2c_client)); - client->adapter = adap; - client->addr = addr; + memcpy(client,&client_template,sizeof(struct i2c_client)); + client->adapter = adap; + client->addr = addr; i2c_set_clientdata(client, t); do_tda7432_init(client); @@ -472,7 +472,7 @@ static int tda7432_command(struct i2c_client *client, } } - t->muted=(va->flags & VIDEO_AUDIO_MUTE); + t->muted=(va->flags & VIDEO_AUDIO_MUTE); if (t->muted) { /* Mute & update balance*/ @@ -503,12 +503,12 @@ static int tda7432_command(struct i2c_client *client, static struct i2c_driver driver = { .owner = THIS_MODULE, - .name = "i2c tda7432 driver", + .name = "i2c tda7432 driver", .id = I2C_DRIVERID_TDA7432, - .flags = I2C_DF_NOTIFY, + .flags = I2C_DF_NOTIFY, .attach_adapter = tda7432_probe, - .detach_client = tda7432_detach, - .command = tda7432_command, + .detach_client = tda7432_detach, + .command = tda7432_command, }; static struct i2c_client client_template = diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 1e2acc4abbe..e2027dada5d 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -48,7 +48,7 @@ static struct freq_entry div_table[] = { { 0x1C34, 3 }, { 0x0D34, 2 }, { 0x067B, 1 }, - { 0x0000, 0 }, + { 0x0000, 0 }, }; static struct freq_entry agc_table[] = { diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c index 7e3dcdb262b..5a9faefc364 100644 --- a/drivers/media/video/tda9875.c +++ b/drivers/media/video/tda9875.c @@ -126,20 +126,20 @@ static int tda9875_write(struct i2c_client *client, int subaddr, unsigned char v static int i2c_read_register(struct i2c_adapter *adap, int addr, int reg) { - unsigned char write[1]; - unsigned char read[1]; - struct i2c_msg msgs[2] = { - { addr, 0, 1, write }, - { addr, I2C_M_RD, 1, read } - }; - write[0] = reg; - - if (2 != i2c_transfer(adap,msgs,2)) { - printk(KERN_WARNING "tda9875: I/O error (read2)\n"); - return -1; - } - dprintk("tda9875: chip_read2: reg%d=0x%x\n",reg,read[0]); - return read[0]; + unsigned char write[1]; + unsigned char read[1]; + struct i2c_msg msgs[2] = { + { addr, 0, 1, write }, + { addr, I2C_M_RD, 1, read } + }; + write[0] = reg; + + if (2 != i2c_transfer(adap,msgs,2)) { + printk(KERN_WARNING "tda9875: I/O error (read2)\n"); + return -1; + } + dprintk("tda9875: chip_read2: reg%d=0x%x\n",reg,read[0]); + return read[0]; } static void tda9875_set(struct i2c_client *client) @@ -184,7 +184,7 @@ static void do_tda9875_init(struct i2c_client *client) tda9875_write(client, TDA9875_DACOS, 0x02 ); /* sig DAC i/o(in:nicam)*/ tda9875_write(client, TDA9875_ADCIS, 0x6f ); /* sig ADC input(in:mono)*/ tda9875_write(client, TDA9875_LOSR, 0x00 ); /* line out (in:mono)*/ - tda9875_write(client, TDA9875_AER, 0x00 ); /*06 Effect (AVL+PSEUDO) */ + tda9875_write(client, TDA9875_AER, 0x00 ); /*06 Effect (AVL+PSEUDO) */ tda9875_write(client, TDA9875_MCS, 0x44 ); /* Main ch select (DAC) */ tda9875_write(client, TDA9875_MVL, 0x03 ); /* Vol Main left 10dB */ tda9875_write(client, TDA9875_MVR, 0x03 ); /* Vol Main right 10dB*/ @@ -200,7 +200,7 @@ static void do_tda9875_init(struct i2c_client *client) t->mode=AUDIO_UNMUTE; t->lvol=t->rvol =0; /* 0dB */ - t->bass=0; /* 0dB */ + t->bass=0; /* 0dB */ t->treble=0; /* 0dB */ tda9875_set(client); @@ -239,9 +239,9 @@ static int tda9875_attach(struct i2c_adapter *adap, int addr, int kind) memset(t,0,sizeof *t); client = &t->c; - memcpy(client,&client_template,sizeof(struct i2c_client)); - client->adapter = adap; - client->addr = addr; + memcpy(client,&client_template,sizeof(struct i2c_client)); + client->adapter = adap; + client->addr = addr; i2c_set_clientdata(client, t); if(!tda9875_checkit(adap,addr)) { @@ -287,7 +287,7 @@ static int tda9875_command(struct i2c_client *client, dprintk("In tda9875_command...\n"); switch (cmd) { - /* --- v4l ioctls --- */ + /* --- v4l ioctls --- */ /* take care: bttv does userspace copying, we'll get a kernel pointer here... */ case VIDIOCGAUDIO: @@ -355,7 +355,7 @@ static int tda9875_command(struct i2c_client *client, //printk("tda9875 bal:%04x vol:%04x bass:%04x treble:%04x\n",va->balance,va->volume,va->bass,va->treble); - tda9875_set(client); + tda9875_set(client); break; @@ -374,18 +374,18 @@ static int tda9875_command(struct i2c_client *client, static struct i2c_driver driver = { .owner = THIS_MODULE, - .name = "i2c tda9875 driver", - .id = I2C_DRIVERID_TDA9875, - .flags = I2C_DF_NOTIFY, + .name = "i2c tda9875 driver", + .id = I2C_DRIVERID_TDA9875, + .flags = I2C_DF_NOTIFY, .attach_adapter = tda9875_probe, - .detach_client = tda9875_detach, - .command = tda9875_command, + .detach_client = tda9875_detach, + .command = tda9875_command, }; static struct i2c_client client_template = { - .name = "tda9875", - .driver = &driver, + .name = "tda9875", + .driver = &driver, }; static int __init tda9875_init(void) diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 6d2914f738f..9d6b6f57abc 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -46,11 +46,11 @@ MODULE_LICENSE("GPL"); #define UNSET (-1U) #define tda9887_info(fmt, arg...) do {\ printk(KERN_INFO "%s %d-%04x: " fmt, t->client.name, \ - i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0) + i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0) #define tda9887_dbg(fmt, arg...) do {\ if (debug) \ - printk(KERN_INFO "%s %d-%04x: " fmt, t->client.name, \ - i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0) + printk(KERN_INFO "%s %d-%04x: " fmt, t->client.name, \ + i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0) struct tda9887 { struct i2c_client client; @@ -484,11 +484,11 @@ static int tda9887_set_pinnacle(struct tda9887 *t, char *buf) } } if (t->std & V4L2_STD_525_60) { - if ((5 == t->pinnacle_id) || (6 == t->pinnacle_id)) { + if ((5 == t->pinnacle_id) || (6 == t->pinnacle_id)) { bCarrierMode = cIntercarrier; } else { bCarrierMode = cQSS; - } + } } if (bCarrierMode != UNSET) { @@ -568,8 +568,8 @@ static int tda9887_status(struct tda9887 *t) int rc; memset(buf,0,sizeof(buf)); - if (1 != (rc = i2c_master_recv(&t->client,buf,1))) - tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc); + if (1 != (rc = i2c_master_recv(&t->client,buf,1))) + tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc); dump_read_message(t, buf); return 0; } @@ -600,8 +600,8 @@ static int tda9887_configure(struct tda9887 *t) if (debug > 1) dump_write_message(t, t->data); - if (4 != (rc = i2c_master_send(&t->client,t->data,4))) - tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); + if (4 != (rc = i2c_master_send(&t->client,t->data,4))) + tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); if (debug > 2) { msleep_interruptible(1000); @@ -616,11 +616,11 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind) { struct tda9887 *t; - client_template.adapter = adap; - client_template.addr = addr; + client_template.adapter = adap; + client_template.addr = addr; - if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL))) - return -ENOMEM; + if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL))) + return -ENOMEM; memset(t,0,sizeof(*t)); t->client = client_template; @@ -628,7 +628,7 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind) t->pinnacle_id = UNSET; t->radio_mode = V4L2_TUNER_MODE_STEREO; - tda9887_info("chip found @ 0x%x (%s)\n", addr<<1, adap->name); + tda9887_info("chip found @ 0x%x (%s)\n", addr<<1, adap->name); i2c_set_clientdata(&t->client, t); i2c_attach_client(&t->client); @@ -663,18 +663,18 @@ static int tda9887_detach(struct i2c_client *client) } #define SWITCH_V4L2 if (!t->using_v4l2 && debug) \ - tda9887_info("switching to v4l2\n"); \ - t->using_v4l2 = 1; + tda9887_info("switching to v4l2\n"); \ + t->using_v4l2 = 1; #define CHECK_V4L2 if (t->using_v4l2) { if (debug) \ tda9887_info("ignore v4l1 call\n"); \ - return 0; } + return 0; } static int tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct tda9887 *t = i2c_get_clientdata(client); - switch (cmd) { + switch (cmd) { /* --- configuration --- */ case AUDC_SET_RADIO: diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index 38bf5094379..a9375ef05de 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c @@ -117,10 +117,10 @@ #define TEA5767_RESERVED_MASK 0xff enum tea5767_xtal_freq { - TEA5767_LOW_LO_32768 = 0, - TEA5767_HIGH_LO_32768 = 1, - TEA5767_LOW_LO_13MHz = 2, - TEA5767_HIGH_LO_13MHz = 3, + TEA5767_LOW_LO_32768 = 0, + TEA5767_HIGH_LO_32768 = 1, + TEA5767_LOW_LO_13MHz = 2, + TEA5767_HIGH_LO_13MHz = 3, }; diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 44fa1423c1a..e677869afcf 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -432,23 +432,23 @@ static int tuner_detach(struct i2c_client *client) static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, char *cmd) { - if (mode == t->mode) - return 0; - - t->mode = mode; - - if (check_mode(t, cmd) == EINVAL) { - t->mode = T_STANDBY; - if (t->standby) - t->standby (client); - return EINVAL; - } - return 0; + if (mode == t->mode) + return 0; + + t->mode = mode; + + if (check_mode(t, cmd) == EINVAL) { + t->mode = T_STANDBY; + if (t->standby) + t->standby (client); + return EINVAL; + } + return 0; } #define switch_v4l2() if (!t->using_v4l2) \ - tuner_dbg("switching to v4l2\n"); \ - t->using_v4l2 = 1; + tuner_dbg("switching to v4l2\n"); \ + t->using_v4l2 = 1; static inline int check_v4l2(struct tuner *t) { @@ -623,7 +623,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) switch_v4l2(); if (V4L2_TUNER_RADIO == f->type && V4L2_TUNER_RADIO != t->mode) { - if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY") + if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY") == EINVAL) return 0; } diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index e67d9e77c75..84338f1e303 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -102,7 +102,7 @@ struct tunertype */ static struct tunertype tuners[] = { /* 0-9 */ - { "Temic PAL (4002 FH5)", TEMIC, PAL, + { "Temic PAL (4002 FH5)", TEMIC, PAL, 16*140.25,16*463.25,0x02,0x04,0x01,0x8e,623}, { "Philips PAL_I (FI1246 and compatibles)", Philips, PAL_I, 16*140.25,16*463.25,0xa0,0x90,0x30,0x8e,623}, @@ -118,41 +118,41 @@ static struct tunertype tuners[] = { 16*157.25,16*463.25,0x02,0x04,0x01,0x8e,732}, { "Temic PAL_I (4062 FY5)", TEMIC, PAL_I, 16*170.00,16*450.00,0x02,0x04,0x01,0x8e,623}, - { "Temic NTSC (4036 FY5)", TEMIC, NTSC, + { "Temic NTSC (4036 FY5)", TEMIC, NTSC, 16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,732}, - { "Alps HSBH1", TEMIC, NTSC, + { "Alps HSBH1", TEMIC, NTSC, 16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732}, /* 10-19 */ - { "Alps TSBE1", TEMIC, PAL, + { "Alps TSBE1", TEMIC, PAL, 16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732}, - { "Alps TSBB5", Alps, PAL_I, /* tested (UK UHF) with Modulartech MM205 */ + { "Alps TSBB5", Alps, PAL_I, /* tested (UK UHF) with Modulartech MM205 */ 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,632}, - { "Alps TSBE5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */ + { "Alps TSBE5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */ 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,622}, - { "Alps TSBC5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */ + { "Alps TSBC5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */ 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,608}, { "Temic PAL_BG (4006FH5)", TEMIC, PAL, 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, - { "Alps TSCH6", Alps, NTSC, - 16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732}, - { "Temic PAL_DK (4016 FY5)", TEMIC, PAL, - 16*168.25,16*456.25,0xa0,0x90,0x30,0x8e,623}, - { "Philips NTSC_M (MK2)", Philips, NTSC, - 16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732}, - { "Temic PAL_I (4066 FY5)", TEMIC, PAL_I, - 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, - { "Temic PAL* auto (4006 FN5)", TEMIC, PAL, - 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, + { "Alps TSCH6", Alps, NTSC, + 16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732}, + { "Temic PAL_DK (4016 FY5)", TEMIC, PAL, + 16*168.25,16*456.25,0xa0,0x90,0x30,0x8e,623}, + { "Philips NTSC_M (MK2)", Philips, NTSC, + 16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732}, + { "Temic PAL_I (4066 FY5)", TEMIC, PAL_I, + 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, + { "Temic PAL* auto (4006 FN5)", TEMIC, PAL, + 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, /* 20-29 */ - { "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)", TEMIC, PAL, - 16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623}, - { "Temic NTSC (4039 FR5)", TEMIC, NTSC, - 16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732}, - { "Temic PAL/SECAM multi (4046 FM5)", TEMIC, PAL, - 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, - { "Philips PAL_DK (FI1256 and compatibles)", Philips, PAL, + { "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)", TEMIC, PAL, + 16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623}, + { "Temic NTSC (4039 FR5)", TEMIC, NTSC, + 16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732}, + { "Temic PAL/SECAM multi (4046 FM5)", TEMIC, PAL, + 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, + { "Philips PAL_DK (FI1256 and compatibles)", Philips, PAL, 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, { "Philips PAL/SECAM multi (FQ1216ME)", Philips, PAL, 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, @@ -173,21 +173,21 @@ static struct tunertype tuners[] = { { "SHARP NTSC_JP (2U5JF5540)", SHARP, NTSC, /* 940=16*58.75 NTSC@Japan */ 16*137.25,16*317.25,0x01,0x02,0x08,0x8e,940 }, { "Samsung PAL TCPM9091PD27", Samsung, PAL, /* from sourceforge v3tv */ - 16*169,16*464,0xA0,0x90,0x30,0x8e,623}, + 16*169,16*464,0xA0,0x90,0x30,0x8e,623}, { "MT20xx universal", Microtune, PAL|NTSC, /* see mt20xx.c for details */ }, { "Temic PAL_BG (4106 FH5)", TEMIC, PAL, - 16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623}, + 16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623}, { "Temic PAL_DK/SECAM_L (4012 FY5)", TEMIC, PAL, - 16*140.25, 16*463.25, 0x02,0x04,0x01,0x8e,623}, + 16*140.25, 16*463.25, 0x02,0x04,0x01,0x8e,623}, { "Temic NTSC (4136 FY5)", TEMIC, NTSC, - 16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732}, - { "LG PAL (newer TAPC series)", LGINNOTEK, PAL, - 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,623}, + 16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732}, + { "LG PAL (newer TAPC series)", LGINNOTEK, PAL, + 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,623}, { "Philips PAL/SECAM multi (FM1216ME MK3)", Philips, PAL, 16*158.00,16*442.00,0x01,0x02,0x04,0x8e,623 }, { "LG NTSC (newer TAPC series)", LGINNOTEK, NTSC, - 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,732}, + 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,732}, /* 40-49 */ { "HITACHI V7-J180AT", HITACHI, NTSC, @@ -196,24 +196,24 @@ static struct tunertype tuners[] = { 16*140.25,16*463.25,0x01,0xc2,0xcf,0x8e,623}, { "Philips 1236D ATSC/NTSC daul in", Philips, ATSC, 16*157.25,16*454.00,0xa0,0x90,0x30,0x8e,732}, - { "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", Philips, NTSC, - 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732}, - { "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)", Philips, NTSC, - 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732}, + { "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", Philips, NTSC, + 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732}, + { "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)", Philips, NTSC, + 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732}, { "Microtune 4049 FM5", Microtune, PAL, 16*141.00,16*464.00,0xa0,0x90,0x30,0x8e,623}, { "Panasonic VP27s/ENGE4324D", Panasonic, NTSC, 16*160.00,16*454.00,0x01,0x02,0x08,0xce,940}, - { "LG NTSC (TAPE series)", LGINNOTEK, NTSC, - 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 }, - { "Tenna TNF 8831 BGFF)", Philips, PAL, - 16*161.25,16*463.25,0xa0,0x90,0x30,0x8e,623}, + { "LG NTSC (TAPE series)", LGINNOTEK, NTSC, + 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 }, + { "Tenna TNF 8831 BGFF)", Philips, PAL, + 16*161.25,16*463.25,0xa0,0x90,0x30,0x8e,623}, { "Microtune 4042 FI5 ATSC/NTSC dual in", Microtune, NTSC, 16*162.00,16*457.00,0xa2,0x94,0x31,0x8e,732}, /* 50-59 */ - { "TCL 2002N", TCL, NTSC, - 16*172.00,16*448.00,0x01,0x02,0x08,0x8e,732}, + { "TCL 2002N", TCL, NTSC, + 16*172.00,16*448.00,0x01,0x02,0x08,0x8e,732}, { "Philips PAL/SECAM_D (FM 1256 I-H3)", Philips, PAL, 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,623 }, { "Thomson DDT 7610 (ATSC/NTSC)", THOMSON, ATSC, @@ -223,7 +223,7 @@ static struct tunertype tuners[] = { { "tda8290+75", Philips, PAL|NTSC, /* see tda8290.c for details */ }, { "TCL 2002MB", TCL, PAL, - 16*170.00, 16*450.00, 0x01,0x02,0x08,0xce,623}, + 16*170.00, 16*450.00, 0x01,0x02,0x08,0xce,623}, { "Philips PAL/SECAM multi (FQ1216AME MK4)", Philips, PAL, 16*160.00,16*442.00,0x01,0x02,0x04,0xce,623 }, { "Philips FQ1236A MK4", Philips, NTSC, @@ -237,16 +237,16 @@ static struct tunertype tuners[] = { { "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC, 16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732}, { "Tena TNF9533-D/IF/TNF9533-B/DF", Philips, PAL, - 16*160.25,16*464.25,0x01,0x02,0x04,0x8e,623}, + 16*160.25,16*464.25,0x01,0x02,0x04,0x8e,623}, { "Philips TEA5767HN FM Radio", Philips, RADIO, - /* see tea5767.c for details */}, + /* see tea5767.c for details */}, { "Philips FMD1216ME MK3 Hybrid Tuner", Philips, PAL, 16*160.00,16*442.00,0x51,0x52,0x54,0x86,623 }, { "LG TDVS-H062F/TUA6034", LGINNOTEK, ATSC, 16*160.00,16*455.00,0x01,0x02,0x04,0x8e,732}, { "Ymec TVF66T5-B/DFF", Philips, PAL, - 16*160.25,16*464.25,0x01,0x02,0x08,0x8e,623}, - { "LG NTSC (TALN mini series)", LGINNOTEK, NTSC, + 16*160.25,16*464.25,0x01,0x02,0x08,0x8e,623}, + { "LG NTSC (TALN mini series)", LGINNOTEK, NTSC, 16*137.25,16*373.25,0x01,0x02,0x08,0x8e,732 }, { "Philips TD1316 Hybrid Tuner", Philips, PAL, 16*160.00,16*442.00,0xa1,0xa2,0xa4,0xc8,623 }, @@ -281,7 +281,7 @@ static int tuner_stereo(struct i2c_client *c) status = tuner_getstatus (c); switch (t->type) { - case TUNER_PHILIPS_FM1216ME_MK3: + case TUNER_PHILIPS_FM1216ME_MK3: case TUNER_PHILIPS_FM1236_MK3: case TUNER_PHILIPS_FM1256_IH3: stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); @@ -302,7 +302,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) u8 config; u16 div; struct tunertype *tun; - unsigned char buffer[4]; + unsigned char buffer[4]; int rc; tun = &tuners[t->type]; @@ -419,7 +419,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", buffer[0],buffer[1],buffer[2],buffer[3]); - if (4 != (rc = i2c_master_send(c,buffer,4))) + if (4 != (rc = i2c_master_send(c,buffer,4))) tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); if (t->type == TUNER_MICROTUNE_4042FI5) { @@ -458,7 +458,7 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) { struct tunertype *tun; struct tuner *t = i2c_get_clientdata(c); - unsigned char buffer[4]; + unsigned char buffer[4]; unsigned div; int rc; @@ -491,13 +491,13 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) buffer[3] = 0xa4; break; } - buffer[0] = (div>>8) & 0x7f; - buffer[1] = div & 0xff; + buffer[0] = (div>>8) & 0x7f; + buffer[1] = div & 0xff; tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n", buffer[0],buffer[1],buffer[2],buffer[3]); - if (4 != (rc = i2c_master_send(c,buffer,4))) + if (4 != (rc = i2c_master_send(c,buffer,4))) tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); } diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 1c31ef52f86..e1639a24f77 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -458,8 +458,8 @@ static void tda9840_setmode(struct CHIPSTATE *chip, int mode) #define TDA9855_LOUD 1<<5 /* Loudness, 1==off */ #define TDA9855_SUR 1<<3 /* Surround / Subwoofer 1==.5(L-R) 0==.5(L+R) */ /* Bits 0 to 3 select various combinations - * of line in and line out, only the - * interesting ones are defined */ + * of line in and line out, only the + * interesting ones are defined */ #define TDA9855_EXT 1<<2 /* Selects inputs LIR and LIL. Pins 41 & 12 */ #define TDA9855_INT 0 /* Selects inputs LOR and LOL. (internal) */ @@ -1028,7 +1028,7 @@ static int tda9874a_initialize(struct CHIPSTATE *chip) #define TEA6300_TR 0x03 /* treble */ #define TEA6300_FA 0x04 /* fader control */ #define TEA6300_S 0x05 /* switch register */ - /* values for those registers: */ + /* values for those registers: */ #define TEA6300_S_SA 0x01 /* stereo A input */ #define TEA6300_S_SB 0x02 /* stereo B */ #define TEA6300_S_SC 0x04 /* stereo C */ @@ -1042,7 +1042,7 @@ static int tda9874a_initialize(struct CHIPSTATE *chip) #define TEA6320_BA 0x05 /* bass (0-4) */ #define TEA6320_TR 0x06 /* treble (0-4) */ #define TEA6320_S 0x07 /* switch register */ - /* values for those registers: */ + /* values for those registers: */ #define TEA6320_S_SA 0x07 /* stereo A input */ #define TEA6320_S_SB 0x06 /* stereo B */ #define TEA6320_S_SC 0x05 /* stereo C */ @@ -1082,7 +1082,7 @@ static int tea6320_initialize(struct CHIPSTATE * chip) #define TDA8425_BA 0x02 /* bass */ #define TDA8425_TR 0x03 /* treble */ #define TDA8425_S1 0x08 /* switch functions */ - /* values for those registers: */ + /* values for those registers: */ #define TDA8425_S1_OFF 0xEE /* audio off (mute on) */ #define TDA8425_S1_CH1 0xCE /* audio channel 1 (mute off) - "linear stereo" mode */ #define TDA8425_S1_CH2 0xCF /* audio channel 2 (mute off) - "linear stereo" mode */ @@ -1148,7 +1148,7 @@ static void tda8425_setmode(struct CHIPSTATE *chip, int mode) /* bit definition of the RESET register, I2C data. */ #define PIC16C54_MISC_RESET_REMOTE_CTL 0x01 /* bit 0, Reset to receive the key */ - /* code of remote controller */ + /* code of remote controller */ #define PIC16C54_MISC_MTS_MAIN 0x02 /* bit 1 */ #define PIC16C54_MISC_MTS_SAP 0x04 /* bit 2 */ #define PIC16C54_MISC_MTS_BOTH 0x08 /* bit 3 */ @@ -1281,7 +1281,7 @@ static struct CHIPDESC chiplist[] = { .setmode = tda9840_setmode, .checkmode = generic_checkmode, - .init = { 2, { TDA9840_TEST, TDA9840_TEST_INT1SN + .init = { 2, { TDA9840_TEST, TDA9840_TEST_INT1SN /* ,TDA9840_SW, TDA9840_MONO */} } }, { @@ -1467,7 +1467,7 @@ static struct CHIPDESC chiplist[] = { .setmode = ta8874z_setmode, .checkmode = generic_checkmode, - .init = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}}, + .init = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}}, }, { .name = NULL } /* EOF */ }; @@ -1486,8 +1486,8 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind) return -ENOMEM; memset(chip,0,sizeof(*chip)); memcpy(&chip->c,&client_template,sizeof(struct i2c_client)); - chip->c.adapter = adap; - chip->c.addr = addr; + chip->c.adapter = adap; + chip->c.addr = addr; i2c_set_clientdata(&chip->c, chip); /* find description for the chip */ diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index ee605712bf1..68128e04dac 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -6,12 +6,12 @@ * which are: Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) (c) 1999-2001 Gerd Knorr * Adjustments to fit a more general model and all bugs: - Copyright (C) 2003 John Klar + Copyright (C) 2003 John Klar * 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 @@ -54,14 +54,14 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); #define tveeprom_info(fmt, arg...) do {\ printk(KERN_INFO "tveeprom %d-%04x: " fmt, \ - c->adapter->nr, c->addr , ##arg); } while (0) + c->adapter->nr, c->addr , ##arg); } while (0) #define tveeprom_warn(fmt, arg...) do {\ printk(KERN_WARNING "tveeprom %d-%04x: " fmt, \ - c->adapter->nr, c->addr , ##arg); } while (0) + c->adapter->nr, c->addr , ##arg); } while (0) #define tveeprom_dbg(fmt, arg...) do {\ if (debug) \ - printk(KERN_INFO "tveeprom %d-%04x: " fmt, \ - c->adapter->nr, c->addr , ##arg); } while (0) + printk(KERN_INFO "tveeprom %d-%04x: " fmt, \ + c->adapter->nr, c->addr , ##arg); } while (0) /* ----------------------------------------------------------------------- */ @@ -294,7 +294,7 @@ static const char *decoderIC[] = { static int hasRadioTuner(int tunerType) { - switch (tunerType) { + switch (tunerType) { case 18: //PNPEnv_TUNER_FR1236_MK2: case 23: //PNPEnv_TUNER_FM1236: case 38: //PNPEnv_TUNER_FMR1236: @@ -326,12 +326,12 @@ static int hasRadioTuner(int tunerType) case 89: //PNPEnv_TUNER_TCL_MFPE05_2: case 92: //PNPEnv_TUNER_PHILIPS_FQ1236A_MK4: return 1; - } - return 0; + } + return 0; } void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, - unsigned char *eeprom_data) + unsigned char *eeprom_data) { /* ---------------------------------------------- ** The hauppauge eeprom format is tagged diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c index d86e08ebddf..8318bd1aad0 100644 --- a/drivers/media/video/tvmixer.c +++ b/drivers/media/video/tvmixer.c @@ -79,7 +79,7 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm { struct video_audio va; int left,right,ret,val = 0; - struct TVMIXER *mix = file->private_data; + struct TVMIXER *mix = file->private_data; struct i2c_client *client = mix->dev; void __user *argp = (void __user *)arg; int __user *p = argp; @@ -87,25 +87,25 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm if (NULL == client) return -ENODEV; - if (cmd == SOUND_MIXER_INFO) { - mixer_info info; - strlcpy(info.id, "tv card", sizeof(info.id)); - strlcpy(info.name, client->name, sizeof(info.name)); - info.modify_counter = 42 /* FIXME */; - if (copy_to_user(argp, &info, sizeof(info))) - return -EFAULT; - return 0; - } - if (cmd == SOUND_OLD_MIXER_INFO) { - _old_mixer_info info; - strlcpy(info.id, "tv card", sizeof(info.id)); - strlcpy(info.name, client->name, sizeof(info.name)); - if (copy_to_user(argp, &info, sizeof(info))) - return -EFAULT; - return 0; - } - if (cmd == OSS_GETVERSION) - return put_user(SOUND_VERSION, p); + if (cmd == SOUND_MIXER_INFO) { + mixer_info info; + strlcpy(info.id, "tv card", sizeof(info.id)); + strlcpy(info.name, client->name, sizeof(info.name)); + info.modify_counter = 42 /* FIXME */; + if (copy_to_user(argp, &info, sizeof(info))) + return -EFAULT; + return 0; + } + if (cmd == SOUND_OLD_MIXER_INFO) { + _old_mixer_info info; + strlcpy(info.id, "tv card", sizeof(info.id)); + strlcpy(info.name, client->name, sizeof(info.name)); + if (copy_to_user(argp, &info, sizeof(info))) + return -EFAULT; + return 0; + } + if (cmd == OSS_GETVERSION) + return put_user(SOUND_VERSION, p); if (_SIOC_DIR(cmd) & _SIOC_WRITE) if (get_user(val, p)) @@ -181,8 +181,8 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm static int tvmixer_open(struct inode *inode, struct file *file) { - int i, minor = iminor(inode); - struct TVMIXER *mix = NULL; + int i, minor = iminor(inode); + struct TVMIXER *mix = NULL; struct i2c_client *client = NULL; for (i = 0; i < DEV_MAX; i++) { @@ -204,7 +204,7 @@ static int tvmixer_open(struct inode *inode, struct file *file) #endif if (client->adapter->owner) try_module_get(client->adapter->owner); - return 0; + return 0; } static int tvmixer_release(struct inode *inode, struct file *file) @@ -231,15 +231,15 @@ static struct i2c_driver driver = { .owner = THIS_MODULE, #endif .name = "tv card mixer driver", - .id = I2C_DRIVERID_TVMIXER, + .id = I2C_DRIVERID_TVMIXER, #ifdef I2C_DF_DUMMY .flags = I2C_DF_DUMMY, #else .flags = I2C_DF_NOTIFY, - .detach_adapter = tvmixer_adapters, + .detach_adapter = tvmixer_adapters, #endif - .attach_adapter = tvmixer_adapters, - .detach_client = tvmixer_clients, + .attach_adapter = tvmixer_adapters, + .detach_client = tvmixer_clients, }; static struct file_operations tvmixer_fops = { diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index 88beb5a3be1..4134549d11a 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c @@ -960,7 +960,7 @@ v4l_compat_translate_ioctl(struct inode *inode, fmt->start[1] = fmt2->fmt.vbi.start[1]; fmt->count[1] = fmt2->fmt.vbi.count[1]; fmt->flags = fmt2->fmt.vbi.flags & 0x03; - break; + break; } case VIDIOCSVBIFMT: { diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c index 574b8e36f3c..acfd3a103f3 100644 --- a/drivers/media/video/video-buf.c +++ b/drivers/media/video/video-buf.c @@ -147,7 +147,7 @@ int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction, data,size,dma->nr_pages); down_read(¤t->mm->mmap_sem); - err = get_user_pages(current,current->mm, + err = get_user_pages(current,current->mm, data & PAGE_MASK, dma->nr_pages, rw == READ, 1, /* force */ dma->pages, NULL); @@ -750,9 +750,9 @@ videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data, { enum v4l2_field field; unsigned long flags; - int retval; + int retval; - /* setup stuff */ + /* setup stuff */ retval = -ENOMEM; q->read_buf = videobuf_alloc(q->msize); if (NULL == q->read_buf) @@ -760,18 +760,18 @@ videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data, q->read_buf->memory = V4L2_MEMORY_USERPTR; q->read_buf->baddr = (unsigned long)data; - q->read_buf->bsize = count; + q->read_buf->bsize = count; field = videobuf_next_field(q); retval = q->ops->buf_prepare(q,q->read_buf,field); if (0 != retval) goto done; - /* start capture & wait */ + /* start capture & wait */ spin_lock_irqsave(q->irqlock,flags); q->ops->buf_queue(q,q->read_buf); spin_unlock_irqrestore(q->irqlock,flags); - retval = videobuf_waiton(q->read_buf,0,0); - if (0 == retval) { + retval = videobuf_waiton(q->read_buf,0,0); + if (0 == retval) { videobuf_dma_pci_sync(q->pci,&q->read_buf->dma); if (STATE_ERROR == q->read_buf->state) retval = -EIO; @@ -828,7 +828,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, } /* wait until capture is done */ - retval = videobuf_waiton(q->read_buf, nonblocking, 1); + retval = videobuf_waiton(q->read_buf, nonblocking, 1); if (0 != retval) goto done; videobuf_dma_pci_sync(q->pci,&q->read_buf->dma); @@ -1096,7 +1096,7 @@ videobuf_vm_nopage(struct vm_area_struct *vma, unsigned long vaddr, dprintk(3,"nopage: fault @ %08lx [vma %08lx-%08lx]\n", vaddr,vma->vm_start,vma->vm_end); - if (vaddr > vma->vm_end) + if (vaddr > vma->vm_end) return NOPAGE_SIGBUS; page = alloc_page(GFP_USER); if (!page) diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c index 8200f3dad0c..5bd592673b9 100644 --- a/drivers/media/video/wm8775.c +++ b/drivers/media/video/wm8775.c @@ -36,10 +36,10 @@ MODULE_LICENSE("GPL"); #define wm8775_err(fmt, arg...) do { \ printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) + i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) #define wm8775_info(fmt, arg...) do { \ printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) + i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) static unsigned short normal_i2c[] = { 0x36 >> 1, I2C_CLIENT_END }; diff --git a/include/linux/videodev.h b/include/linux/videodev.h index 1cc8c31b798..22e6e4bad7b 100644 --- a/include/linux/videodev.h +++ b/include/linux/videodev.h @@ -202,9 +202,9 @@ struct video_audio #define VIDEO_SOUND_STEREO 2 #define VIDEO_SOUND_LANG1 4 #define VIDEO_SOUND_LANG2 8 - __u16 mode; - __u16 balance; /* Stereo balance */ - __u16 step; /* Step actual volume uses */ + __u16 mode; + __u16 balance; /* Stereo balance */ + __u16 step; /* Step actual volume uses */ }; struct video_clip diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 27979003db4..a9a0999be70 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -24,7 +24,7 @@ /* Four-character-code (FOURCC) */ #define v4l2_fourcc(a,b,c,d)\ - (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24)) + (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24)) /* * E N U M S @@ -154,20 +154,20 @@ struct v4l2_capability }; /* Values for 'capabilities' field */ -#define V4L2_CAP_VIDEO_CAPTURE 0x00000001 /* Is a video capture device */ -#define V4L2_CAP_VIDEO_OUTPUT 0x00000002 /* Is a video output device */ -#define V4L2_CAP_VIDEO_OVERLAY 0x00000004 /* Can do video overlay */ -#define V4L2_CAP_VBI_CAPTURE 0x00000010 /* Is a raw VBI capture device */ -#define V4L2_CAP_VBI_OUTPUT 0x00000020 /* Is a raw VBI output device */ +#define V4L2_CAP_VIDEO_CAPTURE 0x00000001 /* Is a video capture device */ +#define V4L2_CAP_VIDEO_OUTPUT 0x00000002 /* Is a video output device */ +#define V4L2_CAP_VIDEO_OVERLAY 0x00000004 /* Can do video overlay */ +#define V4L2_CAP_VBI_CAPTURE 0x00000010 /* Is a raw VBI capture device */ +#define V4L2_CAP_VBI_OUTPUT 0x00000020 /* Is a raw VBI output device */ #if 1 #define V4L2_CAP_SLICED_VBI_CAPTURE 0x00000040 /* Is a sliced VBI capture device */ #define V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080 /* Is a sliced VBI output device */ #endif -#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */ +#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */ -#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */ -#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */ -#define V4L2_CAP_RADIO 0x00040000 /* is a radio device */ +#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */ +#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */ +#define V4L2_CAP_RADIO 0x00040000 /* is a radio device */ #define V4L2_CAP_READWRITE 0x01000000 /* read/write systemcalls */ #define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */ @@ -179,13 +179,13 @@ struct v4l2_capability struct v4l2_pix_format { - __u32 width; - __u32 height; - __u32 pixelformat; + __u32 width; + __u32 height; + __u32 pixelformat; enum v4l2_field field; __u32 bytesperline; /* for padding, zero if unused */ - __u32 sizeimage; - enum v4l2_colorspace colorspace; + __u32 sizeimage; + enum v4l2_colorspace colorspace; __u32 priv; /* private data, depends on pixelformat */ }; @@ -238,12 +238,12 @@ struct v4l2_pix_format */ struct v4l2_fmtdesc { - __u32 index; /* Format number */ + __u32 index; /* Format number */ enum v4l2_buf_type type; /* buffer type */ __u32 flags; - __u8 description[32]; /* Description string */ - __u32 pixelformat; /* Format fourcc */ - __u32 reserved[4]; + __u8 description[32]; /* Description string */ + __u32 pixelformat; /* Format fourcc */ + __u32 reserved[4]; }; #define V4L2_FMT_FLAG_COMPRESSED 0x0001 @@ -393,7 +393,7 @@ struct v4l2_jpegcompression #define V4L2_JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ #define V4L2_JPEG_MARKER_COM (1<<6) /* Comment segment */ #define V4L2_JPEG_MARKER_APP (1<<7) /* App segment, driver will - * allways use APP0 */ + * allways use APP0 */ }; @@ -402,10 +402,10 @@ struct v4l2_jpegcompression */ struct v4l2_requestbuffers { - __u32 count; + __u32 count; enum v4l2_buf_type type; enum v4l2_memory memory; - __u32 reserved[2]; + __u32 reserved[2]; }; struct v4l2_buffer @@ -511,9 +511,9 @@ struct v4l2_outputparm struct v4l2_cropcap { enum v4l2_buf_type type; - struct v4l2_rect bounds; - struct v4l2_rect defrect; - struct v4l2_fract pixelaspect; + struct v4l2_rect bounds; + struct v4l2_rect defrect; + struct v4l2_fract pixelaspect; }; struct v4l2_crop { @@ -587,7 +587,7 @@ typedef __u64 v4l2_std_id; V4L2_STD_PAL_Nc |\ V4L2_STD_SECAM) #define V4L2_STD_ATSC (V4L2_STD_ATSC_8_VSB |\ - V4L2_STD_ATSC_16_VSB) + V4L2_STD_ATSC_16_VSB) #define V4L2_STD_UNKNOWN 0 #define V4L2_STD_ALL (V4L2_STD_525_60 |\ @@ -595,7 +595,7 @@ typedef __u64 v4l2_std_id; struct v4l2_standard { - __u32 index; + __u32 index; v4l2_std_id id; __u8 name[24]; struct v4l2_fract frameperiod; /* Frames, not fields */ @@ -610,9 +610,9 @@ struct v4l2_standard struct v4l2_input { __u32 index; /* Which input */ - __u8 name[32]; /* Label */ + __u8 name[32]; /* Label */ __u32 type; /* Type of input */ - __u32 audioset; /* Associated audios (bitfield) */ + __u32 audioset; /* Associated audios (bitfield) */ __u32 tuner; /* Associated tuner */ v4l2_std_id std; __u32 status; @@ -647,9 +647,9 @@ struct v4l2_input struct v4l2_output { __u32 index; /* Which output */ - __u8 name[32]; /* Label */ + __u8 name[32]; /* Label */ __u32 type; /* Type of output */ - __u32 audioset; /* Associated audios (bitfield) */ + __u32 audioset; /* Associated audios (bitfield) */ __u32 modulator; /* Associated modulator */ v4l2_std_id std; __u32 reserved[4]; @@ -671,12 +671,12 @@ struct v4l2_control /* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */ struct v4l2_queryctrl { - __u32 id; + __u32 id; enum v4l2_ctrl_type type; __u8 name[32]; /* Whatever */ __s32 minimum; /* Note signedness */ __s32 maximum; - __s32 step; + __s32 step; __s32 default_value; __u32 flags; __u32 reserved[2]; @@ -779,10 +779,10 @@ struct v4l2_modulator struct v4l2_frequency { - __u32 tuner; + __u32 tuner; enum v4l2_tuner_type type; - __u32 frequency; - __u32 reserved[8]; + __u32 frequency; + __u32 reserved[8]; }; /* @@ -846,14 +846,14 @@ struct v4l2_vbi_format struct v4l2_sliced_vbi_format { - __u16 service_set; - /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field - service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field - (equals frame lines 313-336 for 625 line video - standards, 263-286 for 525 line standards) */ - __u16 service_lines[2][24]; - __u32 io_size; - __u32 reserved[2]; /* must be zero */ + __u16 service_set; + /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field + service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field + (equals frame lines 313-336 for 625 line video + standards, 263-286 for 525 line standards) */ + __u16 service_lines[2][24]; + __u32 io_size; + __u32 reserved[2]; /* must be zero */ }; #define V4L2_SLICED_TELETEXT_B (0x0001) @@ -866,22 +866,22 @@ struct v4l2_sliced_vbi_format struct v4l2_sliced_vbi_cap { - __u16 service_set; - /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field - service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field - (equals frame lines 313-336 for 625 line video - standards, 263-286 for 525 line standards) */ - __u16 service_lines[2][24]; - __u32 reserved[4]; /* must be 0 */ + __u16 service_set; + /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field + service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field + (equals frame lines 313-336 for 625 line video + standards, 263-286 for 525 line standards) */ + __u16 service_lines[2][24]; + __u32 reserved[4]; /* must be 0 */ }; struct v4l2_sliced_vbi_data { - __u32 id; - __u32 field; /* 0: first field, 1: second field */ - __u32 line; /* 1-23 */ - __u32 reserved; /* must be 0 */ - __u8 data[48]; + __u32 id; + __u32 field; /* 0: first field, 1: second field */ + __u32 line; /* 1-23 */ + __u32 reserved; /* must be 0 */ + __u8 data[48]; }; #endif @@ -896,9 +896,9 @@ struct v4l2_format enum v4l2_buf_type type; union { - struct v4l2_pix_format pix; // V4L2_BUF_TYPE_VIDEO_CAPTURE - struct v4l2_window win; // V4L2_BUF_TYPE_VIDEO_OVERLAY - struct v4l2_vbi_format vbi; // V4L2_BUF_TYPE_VBI_CAPTURE + struct v4l2_pix_format pix; // V4L2_BUF_TYPE_VIDEO_CAPTURE + struct v4l2_window win; // V4L2_BUF_TYPE_VIDEO_OVERLAY + struct v4l2_vbi_format vbi; // V4L2_BUF_TYPE_VBI_CAPTURE #if 1 struct v4l2_sliced_vbi_format sliced; // V4L2_BUF_TYPE_SLICED_VBI_CAPTURE #endif diff --git a/include/media/audiochip.h b/include/media/audiochip.h index dd1e484e86d..b7d4b093040 100644 --- a/include/media/audiochip.h +++ b/include/media/audiochip.h @@ -10,13 +10,13 @@ enum audiochip { /* Provided by video chip */ AUDIO_CHIP_INTERNAL, /* Provided by tvaudio.c */ - AUDIO_CHIP_TDA8425, - AUDIO_CHIP_TEA6300, - AUDIO_CHIP_TEA6420, - AUDIO_CHIP_TDA9840, - AUDIO_CHIP_TDA985X, - AUDIO_CHIP_TDA9874, - AUDIO_CHIP_PIC16C54, + AUDIO_CHIP_TDA8425, + AUDIO_CHIP_TEA6300, + AUDIO_CHIP_TEA6420, + AUDIO_CHIP_TDA9840, + AUDIO_CHIP_TDA985X, + AUDIO_CHIP_TDA9874, + AUDIO_CHIP_PIC16C54, /* Provided by msp3400.c */ AUDIO_CHIP_MSP34XX }; diff --git a/include/media/tuner.h b/include/media/tuner.h index 81025323267..94a9511479a 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -215,14 +215,14 @@ extern int tea5767_autodetection(struct i2c_client *c); #define tuner_warn(fmt, arg...) do {\ printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c.driver->name, \ - t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0) + t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0) #define tuner_info(fmt, arg...) do {\ printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.driver->name, \ - t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0) + t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0) #define tuner_dbg(fmt, arg...) do {\ if (tuner_debug) \ - printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c.driver->name, \ - t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0) + printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c.driver->name, \ + t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0) #endif /* __KERNEL__ */ diff --git a/include/media/video-buf.h b/include/media/video-buf.h index ae8d7a00044..ee8eb15c0ea 100644 --- a/include/media/video-buf.h +++ b/include/media/video-buf.h @@ -177,7 +177,7 @@ struct videobuf_queue_ops { }; struct videobuf_queue { - struct semaphore lock; + struct semaphore lock; spinlock_t *irqlock; struct pci_dev *pci; -- cgit v1.2.3 From f2421ca3383ed35bc634aa29416a3229dc603fa4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:45 -0800 Subject: [PATCH] v4l: 801: whitespaces cleanups - Whitespaces Cleanups. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/lifeview.txt | 6 +++--- drivers/media/video/bttv-cards.c | 4 ++-- drivers/media/video/bttv-risc.c | 4 ++-- drivers/media/video/cx88/cx88-core.c | 4 ++-- drivers/media/video/cx88/cx88-dvb.c | 2 +- drivers/media/video/saa7134/saa7134-alsa.c | 12 ++++++------ drivers/media/video/saa7134/saa7134-dvb.c | 4 ++-- drivers/media/video/saa7134/saa7134-input.c | 2 +- drivers/media/video/saa7134/saa7134-video.c | 4 ++-- drivers/media/video/tvaudio.c | 8 ++++---- drivers/media/video/tveeprom.c | 2 +- include/linux/videodev2.h | 10 +++++----- 12 files changed, 31 insertions(+), 31 deletions(-) diff --git a/Documentation/video4linux/lifeview.txt b/Documentation/video4linux/lifeview.txt index f66320bd7b6..05f9eb57aac 100644 --- a/Documentation/video4linux/lifeview.txt +++ b/Documentation/video4linux/lifeview.txt @@ -28,9 +28,9 @@ saa7134: /* GP17 Strap "GP7"=High */ /* GP16 Strap "GP6"=High - 0=Radio 1=TV - Drives SA630D ENCH1 and HEF4052 A1 pins - to do FM radio through SIF input */ + 0=Radio 1=TV + Drives SA630D ENCH1 and HEF4052 A1 pins + to do FM radio through SIF input */ /* GP15 nc */ /* GP14 nc */ /* GP13 nc */ diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 92bb515fbe4..695a67e9edd 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -3585,7 +3585,7 @@ static void __devinit osprey_eeprom(struct bttv *btv) for(i = 0; i<14; i++) checksum += ee[i+offset]; checksum = ~checksum; /* no idea why */ if ((((checksum>>8)&0x0FF) == ee[offset+14]) && - ((checksum & 0x0FF) == ee[offset+15])) { + ((checksum & 0x0FF) == ee[offset+15])) { break; } } @@ -4420,7 +4420,7 @@ windvr_audio(struct bttv *btv, struct video_audio *v, int set) if (val) { gpio_bits(0x140000, val); if (bttv_gpio) - bttv_gpio_tracking(btv,"windvr"); + bttv_gpio_tracking(btv,"windvr"); } } else { v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | diff --git a/drivers/media/video/bttv-risc.c b/drivers/media/video/bttv-risc.c index 3028862934d..b40e9734bf0 100644 --- a/drivers/media/video/bttv-risc.c +++ b/drivers/media/video/bttv-risc.c @@ -88,9 +88,9 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, offset = 0; sg++; while (todo > sg_dma_len(sg)) { - *(rp++)=cpu_to_le32(BT848_RISC_WRITE| + *(rp++)=cpu_to_le32(BT848_RISC_WRITE| sg_dma_len(sg)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)); + *(rp++)=cpu_to_le32(sg_dma_address(sg)); todo -= sg_dma_len(sg); sg++; } diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index f01a631d0c0..eb806af1718 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -166,9 +166,9 @@ static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist, offset = 0; sg++; while (todo > sg_dma_len(sg)) { - *(rp++)=cpu_to_le32(RISC_WRITE| + *(rp++)=cpu_to_le32(RISC_WRITE| sg_dma_len(sg)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)); + *(rp++)=cpu_to_le32(sg_dma_address(sg)); todo -= sg_dma_len(sg); sg++; } diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 3be601cfc99..a7a077196fc 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -128,7 +128,7 @@ static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe) static u8 reset [] = { 0x50, 0x80 }; static u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 }; static u8 agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF, - 0x00, 0xFF, 0x00, 0x40, 0x40 }; + 0x00, 0xFF, 0x00, 0x40, 0x40 }; static u8 dntv_extra[] = { 0xB5, 0x7A }; static u8 capt_range_cfg[] = { 0x75, 0x32 }; diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index e9ffe8f144a..e7c3691fc50 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -277,7 +277,7 @@ static int dsp_buffer_init(struct saa7134_dev *dev) BUG(); videobuf_dma_init(&dev->oss.dma); err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE, - (dev->oss.bufsize + PAGE_SIZE) >> PAGE_SHIFT); + (dev->oss.bufsize + PAGE_SIZE) >> PAGE_SHIFT); if (0 != err) return err; return 0; @@ -336,9 +336,9 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->oss.pt))) goto fail1; if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->oss.pt, - dev->oss.dma.sglist, - dev->oss.dma.sglen, - 0))) + dev->oss.dma.sglist, + dev->oss.dma.sglen, + 0))) goto fail2; @@ -481,8 +481,8 @@ static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * static snd_pcm_hardware_t snd_card_saa7134_capture = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID), .formats = USE_FORMATS, .rates = USE_RATE, .rate_min = USE_RATE_MIN, diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 5aadd44c2fa..342891d431a 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -547,7 +547,7 @@ static int philips_tda827x_pll_set(struct dvb_frontend *fe, struct dvb_frontend_ u8 tuner_buf[14]; struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf, - .len = sizeof(tuner_buf) }; + .len = sizeof(tuner_buf) }; int i, tuner_freq, if_freq; u32 N; switch (params->u.ofdm.bandwidth) { @@ -606,7 +606,7 @@ static void philips_tda827x_pll_sleep(struct dvb_frontend *fe) struct saa7134_dev *dev = fe->dvb->priv; static u8 tda827x_sleep[] = { 0x30, 0xd0}; struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tda827x_sleep, - .len = sizeof(tda827x_sleep) }; + .len = sizeof(tda827x_sleep) }; i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); } diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 7ce0459989b..f99dbb72955 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -118,7 +118,7 @@ static IR_KEYTAB_TYPE eztv_codes[IR_KEYTAB_SIZE] = { [ 1 ] = KEY_TV, // DVR [ 21 ] = KEY_DVD, // DVD [ 23 ] = KEY_AUDIO, // music - // DVR mode / DVD mode / music mode + // DVR mode / DVD mode / music mode [ 27 ] = KEY_MUTE, // mute [ 2 ] = KEY_LANGUAGE, // MTS/SAP / audio / autoseek diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 86db7fb96ef..caeb47c68b8 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -1345,8 +1345,8 @@ video_poll(struct file *file, struct poll_table_struct *wait) return POLLERR; } if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field)) { - up(&fh->cap.lock); - return POLLERR; + up(&fh->cap.lock); + return POLLERR; } fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); fh->cap.read_off = 0; diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index e1639a24f77..75901b03073 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -1028,7 +1028,7 @@ static int tda9874a_initialize(struct CHIPSTATE *chip) #define TEA6300_TR 0x03 /* treble */ #define TEA6300_FA 0x04 /* fader control */ #define TEA6300_S 0x05 /* switch register */ - /* values for those registers: */ + /* values for those registers: */ #define TEA6300_S_SA 0x01 /* stereo A input */ #define TEA6300_S_SB 0x02 /* stereo B */ #define TEA6300_S_SC 0x04 /* stereo C */ @@ -1042,7 +1042,7 @@ static int tda9874a_initialize(struct CHIPSTATE *chip) #define TEA6320_BA 0x05 /* bass (0-4) */ #define TEA6320_TR 0x06 /* treble (0-4) */ #define TEA6320_S 0x07 /* switch register */ - /* values for those registers: */ + /* values for those registers: */ #define TEA6320_S_SA 0x07 /* stereo A input */ #define TEA6320_S_SB 0x06 /* stereo B */ #define TEA6320_S_SC 0x05 /* stereo C */ @@ -1082,7 +1082,7 @@ static int tea6320_initialize(struct CHIPSTATE * chip) #define TDA8425_BA 0x02 /* bass */ #define TDA8425_TR 0x03 /* treble */ #define TDA8425_S1 0x08 /* switch functions */ - /* values for those registers: */ + /* values for those registers: */ #define TDA8425_S1_OFF 0xEE /* audio off (mute on) */ #define TDA8425_S1_CH1 0xCE /* audio channel 1 (mute off) - "linear stereo" mode */ #define TDA8425_S1_CH2 0xCF /* audio channel 2 (mute off) - "linear stereo" mode */ @@ -1148,7 +1148,7 @@ static void tda8425_setmode(struct CHIPSTATE *chip, int mode) /* bit definition of the RESET register, I2C data. */ #define PIC16C54_MISC_RESET_REMOTE_CTL 0x01 /* bit 0, Reset to receive the key */ - /* code of remote controller */ + /* code of remote controller */ #define PIC16C54_MISC_MTS_MAIN 0x02 /* bit 1 */ #define PIC16C54_MISC_MTS_SAP 0x04 /* bit 2 */ #define PIC16C54_MISC_MTS_BOTH 0x08 /* bit 3 */ diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 68128e04dac..d83a3361811 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -331,7 +331,7 @@ static int hasRadioTuner(int tunerType) } void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, - unsigned char *eeprom_data) + unsigned char *eeprom_data) { /* ---------------------------------------------- ** The hauppauge eeprom format is tagged diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index a9a0999be70..090091560c3 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -393,7 +393,7 @@ struct v4l2_jpegcompression #define V4L2_JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ #define V4L2_JPEG_MARKER_COM (1<<6) /* Comment segment */ #define V4L2_JPEG_MARKER_APP (1<<7) /* App segment, driver will - * allways use APP0 */ + * allways use APP0 */ }; @@ -849,8 +849,8 @@ struct v4l2_sliced_vbi_format __u16 service_set; /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field - (equals frame lines 313-336 for 625 line video - standards, 263-286 for 525 line standards) */ + (equals frame lines 313-336 for 625 line video + standards, 263-286 for 525 line standards) */ __u16 service_lines[2][24]; __u32 io_size; __u32 reserved[2]; /* must be zero */ @@ -869,8 +869,8 @@ struct v4l2_sliced_vbi_cap __u16 service_set; /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field - (equals frame lines 313-336 for 625 line video - standards, 263-286 for 525 line standards) */ + (equals frame lines 313-336 for 625 line video + standards, 263-286 for 525 line standards) */ __u16 service_lines[2][24]; __u32 reserved[4]; /* must be 0 */ }; -- cgit v1.2.3 From 02f7427333c5784a937314a305132ed31cc6b9d1 Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Tue, 8 Nov 2005 21:37:46 -0800 Subject: [PATCH] v4l: 802: replaced kmalloc kfree with usb buffer alloc usb buffer free to get - Replaced kmalloc/kfree with usb_buffer_alloc/usb_buffer_free to get Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-core.c | 50 ++++++++++++++++---------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 227a47d6e4b..ba2d986c6df 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -714,11 +714,12 @@ void em2820_uninit_isoc(struct em2820 *dev) for (i = 0; i < EM2820_NUM_BUFS; i++) { if (dev->urb[i]) { usb_kill_urb(dev->urb[i]); + if (dev->transfer_buffer[i]){ + usb_buffer_free(dev->udev,(EM2820_NUM_PACKETS*dev->max_pkt_size),dev->transfer_buffer[i],dev->urb[i]->transfer_dma); + } usb_free_urb(dev->urb[i]); } dev->urb[i] = NULL; - if (dev->transfer_buffer[i]) - kfree(dev->transfer_buffer[i]); dev->transfer_buffer[i] = NULL; } em2820_capture_start(dev, 0); @@ -743,7 +744,13 @@ int em2820_init_isoc(struct em2820 *dev) struct urb *urb; int j, k; /* allocate transfer buffer */ - dev->transfer_buffer[i] = kmalloc(sb_size, GFP_KERNEL); + urb = usb_alloc_urb(EM2820_NUM_PACKETS, GFP_KERNEL); + if (!urb){ + em2820_errdev("cannot alloc urb %i\n", i); + em2820_uninit_isoc(dev); + return -ENOMEM; + } + dev->transfer_buffer[i] = usb_buffer_alloc(dev->udev, sb_size, GFP_KERNEL,&urb->transfer_dma); if (!dev->transfer_buffer[i]) { em2820_errdev ("unable to allocate %i bytes for transfer buffer %i\n", @@ -752,29 +759,22 @@ int em2820_init_isoc(struct em2820 *dev) return -ENOMEM; } memset(dev->transfer_buffer[i], 0, sb_size); - urb = usb_alloc_urb(EM2820_NUM_PACKETS, GFP_KERNEL); - if (urb) { - urb->dev = dev->udev; - urb->context = dev; - urb->pipe = usb_rcvisocpipe(dev->udev, 0x82); - urb->transfer_flags = URB_ISO_ASAP; - urb->interval = 1; - urb->transfer_buffer = dev->transfer_buffer[i]; - urb->complete = em2820_isocIrq; - urb->number_of_packets = EM2820_NUM_PACKETS; - urb->transfer_buffer_length = sb_size; - for (j = k = 0; j < EM2820_NUM_PACKETS; - j++, k += dev->max_pkt_size) { - urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = - dev->max_pkt_size; - } - dev->urb[i] = urb; - } else { - em2820_errdev("cannot alloc urb %i\n", i); - em2820_uninit_isoc(dev); - return -ENOMEM; + urb->dev = dev->udev; + urb->context = dev; + urb->pipe = usb_rcvisocpipe(dev->udev, 0x82); + urb->transfer_flags = URB_ISO_ASAP; + urb->interval = 1; + urb->transfer_buffer = dev->transfer_buffer[i]; + urb->complete = em2820_isocIrq; + urb->number_of_packets = EM2820_NUM_PACKETS; + urb->transfer_buffer_length = sb_size; + for (j = k = 0; j < EM2820_NUM_PACKETS; + j++, k += dev->max_pkt_size) { + urb->iso_frame_desc[j].offset = k; + urb->iso_frame_desc[j].length = + dev->max_pkt_size; } + dev->urb[i] = urb; } /* submit urbs */ -- cgit v1.2.3 From 4c0772a9e1fdd5972751993c58d0ac2a427ceb24 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:47 -0800 Subject: [PATCH] v4l: 803: after msp34xxg reset msp wake thread should be called - After msp34xxg_reset, msp_wake_thread should be called to wake again. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/msp3400.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index 699cea2cc64..ba2c95842fb 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -1788,10 +1788,9 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) dprintk("msp34xx: AUDC_SET_RADIO\n"); msp->norm = VIDEO_MODE_RADIO; dprintk("msp34xx: switching to radio mode\n"); - if (IS_MSP34XX_G(msp)) { + if (IS_MSP34XX_G(msp)) msp34xxg_reset(client); - break; - } + msp->watch_stereo = 0; switch (msp->opmode) { case OPMODE_MANUAL: @@ -1906,10 +1905,9 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) dprintk("msp34xx: VIDIOCSCHAN (norm=%d)\n",vc->norm); msp->norm = vc->norm; - if (IS_MSP34XX_G(msp)) { + if (IS_MSP34XX_G(msp)) msp34xxg_reset(client); - break; - } + msp_wake_thread(client); break; } @@ -1919,10 +1917,9 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { /* new channel -- kick audio carrier scan */ dprintk("msp34xx: VIDIOCSFREQ\n"); - if (IS_MSP34XX_G(msp)) { + if (IS_MSP34XX_G(msp)) msp34xxg_reset(client); - break; - } + msp_wake_thread(client); break; } -- cgit v1.2.3 From de48eebce8b63dbae7272ee80f4fe0eaddb61278 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 8 Nov 2005 21:37:48 -0800 Subject: [PATCH] v4l: 806: add support for tda8275a - Add support for tda8275a Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tda8290.c | 638 +++++++++++++++++++++++++++++---------- drivers/media/video/tuner-core.c | 2 +- include/media/tuner.h | 8 +- 3 files changed, 484 insertions(+), 164 deletions(-) diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index e2027dada5d..47d3d2ce977 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -1,177 +1,402 @@ /* - * - * i2c tv tuner chip device driver - * controls the philips tda8290+75 tuner chip combo. - */ + + i2c tv tuner chip device driver + controls the philips tda8290+75 tuner chip combo. + + 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 option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #include #include #include #include -#define I2C_ADDR_TDA8290 0x4b -#define I2C_ADDR_TDA8275 0x61 - /* ---------------------------------------------------------------------- */ -struct freq_entry { - u16 freq; - u8 value; +struct tda827x_data { + u32 lomax; + u8 spd; + u8 bs; + u8 bp; + u8 cp; + u8 gc3; + u8 div1p5; }; -static struct freq_entry band_table[] = { - { 0x2DF4, 0x1C }, - { 0x2574, 0x14 }, - { 0x22B4, 0x0C }, - { 0x20D4, 0x0B }, - { 0x1E74, 0x3B }, - { 0x1C34, 0x33 }, - { 0x16F4, 0x5B }, - { 0x1454, 0x53 }, - { 0x12D4, 0x52 }, - { 0x1034, 0x4A }, - { 0x0EE4, 0x7A }, - { 0x0D34, 0x72 }, - { 0x0B54, 0x9A }, - { 0x0914, 0x91 }, - { 0x07F4, 0x89 }, - { 0x0774, 0xB9 }, - { 0x067B, 0xB1 }, - { 0x0634, 0xD9 }, - { 0x05A4, 0xD8 }, // FM radio - { 0x0494, 0xD0 }, - { 0x03BC, 0xC8 }, - { 0x0394, 0xF8 }, // 57250000 Hz - { 0x0000, 0xF0 }, // 0 + /* Note lomax entry is lo / 62500 */ + +static struct tda827x_data tda827x_analog[] = { + { .lomax = 992, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1}, /* 62 MHz */ + { .lomax = 1056, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1}, /* 66 MHz */ + { .lomax = 1216, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0}, /* 76 MHz */ + { .lomax = 1344, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0}, /* 84 MHz */ + { .lomax = 1488, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 93 MHz */ + { .lomax = 1568, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 98 MHz */ + { .lomax = 1744, .spd = 3, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 109 MHz */ + { .lomax = 1968, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 123 MHz */ + { .lomax = 2128, .spd = 2, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 133 MHz */ + { .lomax = 2416, .spd = 2, .bs = 1, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 151 MHz */ + { .lomax = 2464, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 154 MHz */ + { .lomax = 2896, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 0, .div1p5 = 0}, /* 181 MHz */ + { .lomax = 2960, .spd = 2, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 185 MHz */ + { .lomax = 3472, .spd = 2, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 217 MHz */ + { .lomax = 3904, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 244 MHz */ + { .lomax = 4240, .spd = 1, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 265 MHz */ + { .lomax = 4832, .spd = 1, .bs = 1, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 302 MHz */ + { .lomax = 5184, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 324 MHz */ + { .lomax = 5920, .spd = 1, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 370 MHz */ + { .lomax = 7264, .spd = 1, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 454 MHz */ + { .lomax = 7888, .spd = 0, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 493 MHz */ + { .lomax = 8480, .spd = 0, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 530 MHz */ + { .lomax = 8864, .spd = 0, .bs = 1, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 554 MHz */ + { .lomax = 9664, .spd = 0, .bs = 1, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, /* 604 MHz */ + { .lomax = 11088, .spd = 0, .bs = 2, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, /* 696 MHz */ + { .lomax = 11840, .spd = 0, .bs = 2, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0}, /* 740 MHz */ + { .lomax = 13120, .spd = 0, .bs = 3, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, /* 820 MHz */ + { .lomax = 13840, .spd = 0, .bs = 3, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0}, /* 865 MHz */ + { .lomax = 0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0} /* End */ }; -static struct freq_entry div_table[] = { - { 0x1C34, 3 }, - { 0x0D34, 2 }, - { 0x067B, 1 }, - { 0x0000, 0 }, -}; +static void tda827x_tune(struct i2c_client *c, u16 ifc, unsigned int freq) +{ + unsigned char tuner_reg[8]; + unsigned char reg2[2]; + u32 N; + int i; + struct tuner *t = i2c_get_clientdata(c); + struct i2c_msg msg = {.addr = t->tda827x_addr, .flags = 0}; -static struct freq_entry agc_table[] = { - { 0x22B4, 0x8F }, - { 0x0B54, 0x9F }, - { 0x09A4, 0x8F }, - { 0x0554, 0x9F }, - { 0x0000, 0xBF }, -}; + if (t->mode == V4L2_TUNER_RADIO) + freq = freq / 1000; + + N = freq + ifc; + i = 0; + while (tda827x_analog[i].lomax < N) { + if(tda827x_analog[i + 1].lomax == 0) + break; + i++; + } + + N = N << tda827x_analog[i].spd; + + tuner_reg[0] = 0; + tuner_reg[1] = (unsigned char)(N>>8); + tuner_reg[2] = (unsigned char) N; + tuner_reg[3] = 0x40; + tuner_reg[4] = 0x52 + (t->tda827x_lpsel << 5); + tuner_reg[5] = (tda827x_analog[i].spd << 6) + (tda827x_analog[i].div1p5 <<5) + + (tda827x_analog[i].bs <<3) + tda827x_analog[i].bp; + tuner_reg[6] = 0x8f + (tda827x_analog[i].gc3 << 4); + tuner_reg[7] = 0x8f; + + msg.buf = tuner_reg; + msg.len = 8; + i2c_transfer(c->adapter, &msg, 1); + + msg.buf= reg2; + msg.len = 2; + reg2[0] = 0x80; + reg2[1] = 0; + i2c_transfer(c->adapter, &msg, 1); + + reg2[0] = 0x60; + reg2[1] = 0xbf; + i2c_transfer(c->adapter, &msg, 1); + + reg2[0] = 0x30; + reg2[1] = tuner_reg[4] + 0x80; + i2c_transfer(c->adapter, &msg, 1); + + msleep(1); + reg2[0] = 0x30; + reg2[1] = tuner_reg[4] + 4; + i2c_transfer(c->adapter, &msg, 1); + + msleep(1); + reg2[0] = 0x30; + reg2[1] = tuner_reg[4]; + i2c_transfer(c->adapter, &msg, 1); + + msleep(550); + reg2[0] = 0x30; + reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_analog[i].cp ; + i2c_transfer(c->adapter, &msg, 1); -static __u8 get_freq_entry( struct freq_entry* table, __u16 freq) + reg2[0] = 0x60; + reg2[1] = 0x7f; + i2c_transfer(c->adapter, &msg, 1); + + reg2[0] = 0x80; + reg2[1] = 0x08; // Vsync en + i2c_transfer(c->adapter, &msg, 1); +} + +static void tda827x_agcf(struct i2c_client *c) { - while(table->freq && table->freq > freq) - table++; - return table->value; + struct tuner *t = i2c_get_clientdata(c); + unsigned char data[] = {0x80, 0x0c}; + struct i2c_msg msg = {.addr = t->tda827x_addr, .buf = data, + .flags = 0, .len = 2}; + i2c_transfer(c->adapter, &msg, 1); } /* ---------------------------------------------------------------------- */ -static unsigned char i2c_enable_bridge[2] = { 0x21, 0xC0 }; -static unsigned char i2c_disable_bridge[2] = { 0x21, 0x80 }; -static unsigned char i2c_init_tda8275[14] = { 0x00, 0x00, 0x00, 0x00, - 0xfC, 0x04, 0xA3, 0x3F, - 0x2A, 0x04, 0xFF, 0x00, - 0x00, 0x40 }; -static unsigned char i2c_set_VS[2] = { 0x30, 0x6F }; -static unsigned char i2c_set_GP01_CF[2] = { 0x20, 0x0B }; -static unsigned char i2c_tda8290_reset[2] = { 0x00, 0x00 }; -static unsigned char i2c_tda8290_standby[2] = { 0x00, 0x02 }; -static unsigned char i2c_gainset_off[2] = { 0x28, 0x14 }; -static unsigned char i2c_gainset_on[2] = { 0x28, 0x54 }; -static unsigned char i2c_agc3_00[2] = { 0x80, 0x00 }; -static unsigned char i2c_agc2_BF[2] = { 0x60, 0xBF }; -static unsigned char i2c_cb1_D0[2] = { 0x30, 0xD0 }; -static unsigned char i2c_cb1_D2[2] = { 0x30, 0xD2 }; -static unsigned char i2c_cb1_56[2] = { 0x30, 0x56 }; -static unsigned char i2c_cb1_52[2] = { 0x30, 0x52 }; -static unsigned char i2c_cb1_50[2] = { 0x30, 0x50 }; -static unsigned char i2c_agc2_7F[2] = { 0x60, 0x7F }; -static unsigned char i2c_agc3_08[2] = { 0x80, 0x08 }; - -/* FIXME: European PAL/SECAM should select 9MHz Lowpass Filter, while - NTSC/M and PAL/M should be using 7MHz filter, by selecting CB3 */ -static unsigned char i2c_cb3_9MHz[2] = { 0xc0, 0x39 }; -static unsigned char i2c_cb3_7MHz[2] = { 0xc0, 0x3B }; - -static struct i2c_msg i2c_msg_init[] = { - { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_init_tda8275), i2c_init_tda8275 }, - { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_disable_bridge), i2c_disable_bridge }, - { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_set_VS), i2c_set_VS }, - { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_set_GP01_CF), i2c_set_GP01_CF }, +struct tda827xa_data { + u32 lomax; + u8 svco; + u8 spd; + u8 scr; + u8 sbs; + u8 gc3; }; -static struct i2c_msg i2c_msg_prolog[] = { -// { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_easy_mode), i2c_easy_mode }, - { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_gainset_off), i2c_gainset_off }, - { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_tda8290_reset), i2c_tda8290_reset }, - { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_enable_bridge), i2c_enable_bridge }, +static struct tda827xa_data tda827xa_analog[] = { + { .lomax = 910, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 3}, /* 56.875 MHz */ + { .lomax = 1076, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3}, /* 67.25 MHz */ + { .lomax = 1300, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3}, /* 81.25 MHz */ + { .lomax = 1560, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3}, /* 97.5 MHz */ + { .lomax = 1820, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1}, /* 113.75 MHz */ + { .lomax = 2152, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, /* 134.5 MHz */ + { .lomax = 2464, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, /* 154 MHz */ + { .lomax = 2600, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, /* 162.5 MHz */ + { .lomax = 2928, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, /* 183 MHz */ + { .lomax = 3120, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1}, /* 195 MHz */ + { .lomax = 3640, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 3}, /* 227.5 MHz */ + { .lomax = 4304, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 3}, /* 269 MHz */ + { .lomax = 5200, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1}, /* 325 MHz */ + { .lomax = 6240, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3}, /* 390 MHz */ + { .lomax = 7280, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3}, /* 455 MHz */ + { .lomax = 8320, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, /* 520 MHz */ + { .lomax = 8608, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1}, /* 538 MHz */ + { .lomax = 8864, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, /* 554 MHz */ + { .lomax = 9920, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, /* 620 MHz */ + { .lomax = 10400, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, /* 650 MHz */ + { .lomax = 11200, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, /* 700 MHz */ + { .lomax = 12480, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, /* 780 MHz */ + { .lomax = 13120, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, /* 820 MHz */ + { .lomax = 13920, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, /* 870 MHz */ + { .lomax = 14576, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0}, /* 911 MHz */ + { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0} /* End */ }; -static struct i2c_msg i2c_msg_config[] = { -// { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_set_freq), i2c_set_freq }, - { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_agc3_00), i2c_agc3_00 }, - { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_agc2_BF), i2c_agc2_BF }, - { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_D2), i2c_cb1_D2 }, - { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_56), i2c_cb1_56 }, - { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_52), i2c_cb1_52 }, -}; +static void tda827xa_tune(struct i2c_client *c, u16 ifc, unsigned int freq) +{ + unsigned char tuner_reg[14]; + unsigned char reg2[2]; + u32 N; + int i; + struct tuner *t = i2c_get_clientdata(c); + struct i2c_msg msg = {.addr = t->tda827x_addr, .flags = 0}; -static struct i2c_msg i2c_msg_epilog[] = { - { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_50), i2c_cb1_50 }, - { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_agc2_7F), i2c_agc2_7F }, - { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_agc3_08), i2c_agc3_08 }, - { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_disable_bridge), i2c_disable_bridge }, - { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_gainset_on), i2c_gainset_on }, -}; + if (t->mode == V4L2_TUNER_RADIO) + freq = freq / 1000; -static struct i2c_msg i2c_msg_standby[] = { - { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_enable_bridge), i2c_enable_bridge }, - { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_D0), i2c_cb1_D0 }, - { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_disable_bridge), i2c_disable_bridge }, - { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_tda8290_standby), i2c_tda8290_standby }, -}; + N = freq + ifc; + i = 0; + while (tda827xa_analog[i].lomax < N) { + if(tda827xa_analog[i + 1].lomax == 0) + break; + i++; + } + + N = N << tda827xa_analog[i].spd; + + tuner_reg[0] = 0; + tuner_reg[1] = (unsigned char)(N>>8); + tuner_reg[2] = (unsigned char) N; + tuner_reg[3] = 0; + tuner_reg[4] = 0x16; + tuner_reg[5] = (tda827xa_analog[i].spd << 5) + (tda827xa_analog[i].svco << 3) + + tda827xa_analog[i].sbs; + tuner_reg[6] = 0x8b + (tda827xa_analog[i].gc3 << 4); + tuner_reg[7] = 0x0c; + tuner_reg[8] = 4; + tuner_reg[9] = 0x20; + tuner_reg[10] = 0xff; + tuner_reg[11] = 0xe0; + tuner_reg[12] = 0; + tuner_reg[13] = 0x39 + (t->tda827x_lpsel << 1); + + msg.buf = tuner_reg; + msg.len = 14; + i2c_transfer(c->adapter, &msg, 1); + + msg.buf= reg2; + msg.len = 2; + reg2[0] = 0x60; + reg2[1] = 0x3c; + i2c_transfer(c->adapter, &msg, 1); + + reg2[0] = 0xa0; + reg2[1] = 0xc0; + i2c_transfer(c->adapter, &msg, 1); + + msleep(2); + reg2[0] = 0x30; + reg2[1] = 0x10 + tda827xa_analog[i].scr; + i2c_transfer(c->adapter, &msg, 1); + + msleep(550); + reg2[0] = 0x50; + reg2[1] = 0x8f + (tda827xa_analog[i].gc3 << 4); + i2c_transfer(c->adapter, &msg, 1); + + reg2[0] = 0x80; + reg2[1] = 0x28; + i2c_transfer(c->adapter, &msg, 1); + + reg2[0] = 0xb0; + reg2[1] = 0x01; + i2c_transfer(c->adapter, &msg, 1); -static int tda8290_tune(struct i2c_client *c) + reg2[0] = 0xc0; + reg2[1] = 0x19 + (t->tda827x_lpsel << 1); + i2c_transfer(c->adapter, &msg, 1); +} + +static void tda827xa_agcf(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); - struct i2c_msg easy_mode = - { I2C_ADDR_TDA8290, 0, 2, t->i2c_easy_mode }; - struct i2c_msg set_freq = - { I2C_ADDR_TDA8275, 0, 8, t->i2c_set_freq }; - - i2c_transfer(c->adapter, &easy_mode, 1); - i2c_transfer(c->adapter, i2c_msg_prolog, ARRAY_SIZE(i2c_msg_prolog)); + unsigned char data[] = {0x80, 0x2c}; + struct i2c_msg msg = {.addr = t->tda827x_addr, .buf = data, + .flags = 0, .len = 2}; + i2c_transfer(c->adapter, &msg, 1); +} - i2c_transfer(c->adapter, &set_freq, 1); - i2c_transfer(c->adapter, i2c_msg_config, ARRAY_SIZE(i2c_msg_config)); +/*---------------------------------------------------------------------*/ - msleep(550); - i2c_transfer(c->adapter, i2c_msg_epilog, ARRAY_SIZE(i2c_msg_epilog)); - return 0; +static void tda8290_i2c_bridge(struct i2c_client *c, int close) +{ + unsigned char enable[2] = { 0x21, 0xC0 }; + unsigned char disable[2] = { 0x21, 0x80 }; + unsigned char *msg; + if(close) { + msg = enable; + i2c_master_send(c, msg, 2); + /* let the bridge stabilize */ + msleep(20); + } else { + msg = disable; + i2c_master_send(c, msg, 2); + } } -static void set_frequency(struct tuner *t, u16 ifc, unsigned int freq) +/*---------------------------------------------------------------------*/ + +static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq) { - u32 N; + struct tuner *t = i2c_get_clientdata(c); + unsigned char soft_reset[] = { 0x00, 0x00 }; + unsigned char easy_mode[] = { 0x01, t->tda8290_easy_mode }; + unsigned char expert_mode[] = { 0x01, 0x80 }; + unsigned char gainset_off[] = { 0x28, 0x14 }; + unsigned char if_agc_spd[] = { 0x0f, 0x88 }; + unsigned char adc_head_6[] = { 0x05, 0x04 }; + unsigned char adc_head_9[] = { 0x05, 0x02 }; + unsigned char adc_head_12[] = { 0x05, 0x01 }; + unsigned char pll_bw_nom[] = { 0x0d, 0x47 }; + unsigned char pll_bw_low[] = { 0x0d, 0x27 }; + unsigned char gainset_2[] = { 0x28, 0x64 }; + unsigned char agc_rst_on[] = { 0x0e, 0x0b }; + unsigned char agc_rst_off[] = { 0x0e, 0x09 }; + unsigned char if_agc_set[] = { 0x0f, 0x81 }; + unsigned char addr_adc_sat = 0x1a; + unsigned char addr_agc_stat = 0x1d; + unsigned char addr_pll_stat = 0x1b; + unsigned char adc_sat, agc_stat, + pll_stat; + + i2c_master_send(c, easy_mode, 2); + i2c_master_send(c, soft_reset, 2); + msleep(1); + + i2c_master_send(c, expert_mode, 2); + i2c_master_send(c, gainset_off, 2); + i2c_master_send(c, if_agc_spd, 2); + if (t->tda8290_easy_mode & 0x60) + i2c_master_send(c, adc_head_9, 2); + else + i2c_master_send(c, adc_head_6, 2); + i2c_master_send(c, pll_bw_nom, 2); + + tda8290_i2c_bridge(c, 1); + if (t->tda827x_ver != 0) + tda827xa_tune(c, ifc, freq); + else + tda827x_tune(c, ifc, freq); + /* adjust headroom resp. gain */ + i2c_master_send(c, &addr_adc_sat, 1); + i2c_master_recv(c, &adc_sat, 1); + i2c_master_send(c, &addr_agc_stat, 1); + i2c_master_recv(c, &agc_stat, 1); + i2c_master_send(c, &addr_pll_stat, 1); + i2c_master_recv(c, &pll_stat, 1); + if (pll_stat & 0x80) + tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat); + else + tuner_dbg("tda8290 not locked, no signal?\n"); + if ((agc_stat > 115) || (!(pll_stat & 0x80) && (adc_sat <20))) { + tuner_dbg("adjust gain, step 1. Agc: %d\n", agc_stat); + i2c_master_send(c, gainset_2, 2); + msleep(100); + i2c_master_send(c, &addr_agc_stat, 1); + i2c_master_recv(c, &agc_stat, 1); + i2c_master_send(c, &addr_pll_stat, 1); + i2c_master_recv(c, &pll_stat, 1); + if ((agc_stat > 115) || !(pll_stat & 0x80)) { + tuner_dbg("adjust gain, step 2. Agc: %d\n", agc_stat); + if (t->tda827x_ver != 0) + tda827xa_agcf(c); + else + tda827x_agcf(c); + msleep(100); + i2c_master_send(c, &addr_agc_stat, 1); + i2c_master_recv(c, &agc_stat, 1); + i2c_master_send(c, &addr_pll_stat, 1); + i2c_master_recv(c, &pll_stat, 1); + if((agc_stat > 115) || !(pll_stat & 0x80)) { + tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat); + i2c_master_send(c, adc_head_12, 2); + i2c_master_send(c, pll_bw_low, 2); + msleep(100); + } + } + } - if (t->mode == V4L2_TUNER_RADIO) - freq = freq / 1000; + /* l/ l' deadlock? */ + if(t->tda8290_easy_mode & 0x60) { + i2c_master_send(c, &addr_adc_sat, 1); + i2c_master_recv(c, &adc_sat, 1); + i2c_master_send(c, &addr_pll_stat, 1); + i2c_master_recv(c, &pll_stat, 1); + if ((adc_sat > 20) || !(pll_stat & 0x80)) { + i2c_master_send(c, agc_rst_on, 2); + msleep(40); + i2c_master_send(c, agc_rst_off, 2); + } + } - N = (((freq<<3)+ifc)&0x3fffc); - - N = N >> get_freq_entry(div_table, freq); - t->i2c_set_freq[0] = 0; - t->i2c_set_freq[1] = (unsigned char)(N>>8); - t->i2c_set_freq[2] = (unsigned char) N; - t->i2c_set_freq[3] = 0x40; - t->i2c_set_freq[4] = 0x52; - t->i2c_set_freq[5] = get_freq_entry(band_table, freq); - t->i2c_set_freq[6] = get_freq_entry(agc_table, freq); - t->i2c_set_freq[7] = 0x8f; + tda8290_i2c_bridge(c, 0); + i2c_master_send(c, if_agc_set, 2); + return 0; } + +/*---------------------------------------------------------------------*/ + #define V4L2_STD_MN (V4L2_STD_PAL_M|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc|V4L2_STD_NTSC) #define V4L2_STD_B (V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_SECAM_B) #define V4L2_STD_GH (V4L2_STD_PAL_G|V4L2_STD_PAL_H|V4L2_STD_SECAM_G|V4L2_STD_SECAM_H) @@ -179,26 +404,27 @@ static void set_frequency(struct tuner *t, u16 ifc, unsigned int freq) static void set_audio(struct tuner *t) { - t->i2c_easy_mode[0] = 0x01; + t->tda827x_lpsel = 0; if (t->std & V4L2_STD_MN) { - t->sgIF = 736; - t->i2c_easy_mode[1] = 0x01; + t->sgIF = 92; + t->tda8290_easy_mode = 0x01; + t->tda827x_lpsel = 1; } else if (t->std & V4L2_STD_B) { - t->sgIF = 864; - t->i2c_easy_mode[1] = 0x02; + t->sgIF = 108; + t->tda8290_easy_mode = 0x02; } else if (t->std & V4L2_STD_GH) { - t->sgIF = 992; - t->i2c_easy_mode[1] = 0x04; + t->sgIF = 124; + t->tda8290_easy_mode = 0x04; } else if (t->std & V4L2_STD_PAL_I) { - t->sgIF = 992; - t->i2c_easy_mode[1] = 0x08; + t->sgIF = 124; + t->tda8290_easy_mode = 0x08; } else if (t->std & V4L2_STD_DK) { - t->sgIF = 992; - t->i2c_easy_mode[1] = 0x10; + t->sgIF = 124; + t->tda8290_easy_mode = 0x10; } else if (t->std & V4L2_STD_SECAM_L) { - t->sgIF = 992; - t->i2c_easy_mode[1] = 0x20; + t->sgIF = 124; + t->tda8290_easy_mode = 0x20; } } @@ -207,15 +433,13 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) struct tuner *t = i2c_get_clientdata(c); set_audio(t); - set_frequency(t, t->sgIF, freq); - tda8290_tune(c); + tda8290_tune(c, t->sgIF, freq); } static void set_radio_freq(struct i2c_client *c, unsigned int freq) { - struct tuner *t = i2c_get_clientdata(c); - set_frequency(t, 704, freq); - tda8290_tune(c); + /* if frequency is 5.5 MHz */ + tda8290_tune(c, 88, freq); } static int has_signal(struct i2c_client *c) @@ -228,24 +452,118 @@ static int has_signal(struct i2c_client *c) return (afc & 0x80)? 65535:0; } +/*---------------------------------------------------------------------*/ + static void standby(struct i2c_client *c) { - i2c_transfer(c->adapter, i2c_msg_standby, ARRAY_SIZE(i2c_msg_standby)); + struct tuner *t = i2c_get_clientdata(c); + unsigned char cb1[] = { 0x30, 0xD0 }; + unsigned char tda8290_standby[] = { 0x00, 0x02 }; + struct i2c_msg msg = {.addr = t->tda827x_addr, .flags=0, .buf=cb1, .len = 2}; + + tda8290_i2c_bridge(c, 1); + if (t->tda827x_ver != 0) + cb1[1] = 0x90; + i2c_transfer(c->adapter, &msg, 1); + tda8290_i2c_bridge(c, 0); + i2c_master_send(c, tda8290_standby, 2); } -int tda8290_init(struct i2c_client *c) + +static void tda8290_init_if(struct i2c_client *c) +{ + unsigned char set_VS[] = { 0x30, 0x6F }; + unsigned char set_GP01_CF[] = { 0x20, 0x0B }; + + i2c_master_send(c, set_VS, 2); + i2c_master_send(c, set_GP01_CF, 2); +} + +static void tda8290_init_tuner(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); + unsigned char tda8275_init[] = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf, + 0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 }; + unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b, + 0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b }; + struct i2c_msg msg = {.addr = t->tda827x_addr, .flags=0, + .buf=tda8275_init, .len = 14}; + if (t->tda827x_ver != 0) + msg.buf = tda8275a_init; + + tda8290_i2c_bridge(c, 1); + i2c_transfer(c->adapter, &msg, 1); + tda8290_i2c_bridge(c, 0); +} + +/*---------------------------------------------------------------------*/ - strlcpy(c->name, "tda8290+75", sizeof(c->name)); +int tda8290_init(struct i2c_client *c) +{ + struct tuner *t = i2c_get_clientdata(c); + u8 data; + int i, ret, tuners_found; + u32 tuner_addrs; + struct i2c_msg msg = {.flags=I2C_M_RD, .buf=&data, .len = 1}; + + tda8290_i2c_bridge(c, 1); + /* probe for tuner chip */ + tuners_found = 0; + tuner_addrs = 0; + for (i=0x60; i<= 0x63; i++) { + msg.addr = i; + ret = i2c_transfer(c->adapter, &msg, 1); + if (ret == 1) { + tuners_found++; + tuner_addrs = (tuner_addrs << 8) + i; + } + } + /* if there is more than one tuner, we expect the right one is + behind the bridge and we choose the highest address that doesn't + give a response now + */ + tda8290_i2c_bridge(c, 0); + if(tuners_found > 1) + for (i = 0; i < tuners_found; i++) { + msg.addr = tuner_addrs & 0xff; + ret = i2c_transfer(c->adapter, &msg, 1); + if(ret == 1) + tuner_addrs = tuner_addrs >> 8; + else + break; + } + if (tuner_addrs == 0) { + tuner_addrs = 0x61; + tuner_info ("could not clearly identify tuner address, defaulting to %x\n", + tuner_addrs); + } else { + tuner_addrs = tuner_addrs & 0xff; + tuner_info ("setting tuner address to %x\n", tuner_addrs); + } + t->tda827x_addr = tuner_addrs; + msg.addr = tuner_addrs; + + tda8290_i2c_bridge(c, 1); + ret = i2c_transfer(c->adapter, &msg, 1); + if( ret != 1) + tuner_warn ("TDA827x access failed!\n"); + if ((data & 0x3c) == 0) { + strlcpy(c->name, "tda8290+75", sizeof(c->name)); + t->tda827x_ver = 0; + } else { + strlcpy(c->name, "tda8290+75a", sizeof(c->name)); + t->tda827x_ver = 2; + } tuner_info("tuner: type set to %s\n", c->name); + t->tv_freq = set_tv_freq; t->radio_freq = set_radio_freq; t->has_signal = has_signal; t->standby = standby; + t->tda827x_lpsel = 0; - i2c_master_send(c, i2c_enable_bridge, ARRAY_SIZE(i2c_enable_bridge)); - i2c_transfer(c->adapter, i2c_msg_init, ARRAY_SIZE(i2c_msg_init)); + tda8290_init_tuner(c); + tda8290_init_if(c); return 0; } diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index e677869afcf..b9f1acf30ca 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -28,7 +28,7 @@ /* standard i2c insmod options */ static unsigned short normal_i2c[] = { - 0x4b, /* tda8290 */ + 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, I2C_CLIENT_END diff --git a/include/media/tuner.h b/include/media/tuner.h index 94a9511479a..8058be63ad0 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -192,9 +192,11 @@ struct tuner { unsigned int radio_if2; /* used by tda8290 */ - unsigned char i2c_easy_mode[2]; - unsigned char i2c_set_freq[8]; - unsigned int sgIF; + unsigned char tda8290_easy_mode; + unsigned char tda827x_lpsel; + unsigned char tda827x_addr; + unsigned char tda827x_ver; + unsigned int sgIF; /* function ptrs */ void (*tv_freq)(struct i2c_client *c, unsigned int freq); -- cgit v1.2.3 From 79436633dbced18aa348f8669ef507109f851303 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:49 -0800 Subject: [PATCH] v4l: 809: some changes to allow compiling cx88 and saa7134 - Some changes to allow compiling cx88 and saa7134 without V4L1 support. - This patch will help obsoleting V4L1 API. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/cx88-video.c | 9 +++- drivers/media/video/saa7134/saa7134-video.c | 6 ++- drivers/media/video/saa7134/saa7134.h | 2 +- include/linux/videodev.h | 74 +--------------------------- include/linux/videodev2.h | 76 +++++++++++++++++++++++++++++ include/media/video-buf.h | 2 +- 6 files changed, 92 insertions(+), 77 deletions(-) diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index f22ccb65de1..cedd1d79ac1 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -34,6 +34,9 @@ #include "cx88.h" +/* Include V4L1 specific functions. Should be removed soon */ +#include + MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards"); MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); @@ -1187,7 +1190,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, struct v4l2_format *f = arg; return cx8800_try_fmt(dev,fh,f); } - +#ifdef HAVE_V4L1 /* --- streaming capture ------------------------------------- */ case VIDIOCGMBUF: { @@ -1213,6 +1216,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, } return 0; } +#endif case VIDIOC_REQBUFS: return videobuf_reqbufs(get_queue(fh), arg); @@ -1244,7 +1248,6 @@ static int video_do_ioctl(struct inode *inode, struct file *file, res_free(dev,fh,res); return 0; } - default: return cx88_do_ioctl( inode, file, fh->radio, core, cmd, arg, video_do_ioctl ); } @@ -1537,6 +1540,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, *id = 0; return 0; } +#ifdef HAVE_V4L1 case VIDIOCSTUNER: { struct video_tuner *v = arg; @@ -1547,6 +1551,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, cx88_call_i2c_clients(core,VIDIOCSTUNER,v); return 0; } +#endif case VIDIOC_S_TUNER: { struct v4l2_tuner *t = arg; diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index caeb47c68b8..632ebe8724e 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -30,6 +30,9 @@ #include "saa7134-reg.h" #include "saa7134.h" +/* Include V4L1 specific functions. Should be removed soon */ +#include + /* ------------------------------------------------------------------ */ static unsigned int video_debug = 0; @@ -2060,7 +2063,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, struct v4l2_format *f = arg; return saa7134_try_fmt(dev,fh,f); } - +#ifdef HAVE_V4L1 case VIDIOCGMBUF: { struct video_mbuf *mbuf = arg; @@ -2085,6 +2088,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, } return 0; } +#endif case VIDIOC_REQBUFS: return videobuf_reqbufs(saa7134_queue(fh),arg); diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 064c2f7a8c1..cd28a6a7b97 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/linux/videodev.h b/include/linux/videodev.h index 22e6e4bad7b..23276cede54 100644 --- a/include/linux/videodev.h +++ b/include/linux/videodev.h @@ -1,57 +1,16 @@ #ifndef __LINUX_VIDEODEV_H #define __LINUX_VIDEODEV_H -#include #include -#define HAVE_V4L2 1 +#define HAVE_V4L1 1 + #include #ifdef __KERNEL__ -#include #include -#include - -struct video_device -{ - /* device info */ - struct device *dev; - char name[32]; - int type; /* v4l1 */ - int type2; /* v4l2 */ - int hardware; - int minor; - - /* device ops + callbacks */ - struct file_operations *fops; - void (*release)(struct video_device *vfd); - - - /* obsolete -- fops->owner is used instead */ - struct module *owner; - /* dev->driver_data will be used instead some day. - * Use the video_{get|set}_drvdata() helper functions, - * so the switch over will be transparent for you. - * Or use {pci|usb}_{get|set}_drvdata() directly. */ - void *priv; - - /* for videodev.c intenal usage -- please don't touch */ - int users; /* video_exclusive_{open|close} ... */ - struct semaphore lock; /* ... helper function uses these */ - char devfs_name[64]; /* devfs */ - struct class_device class_dev; /* sysfs */ -}; - -#define VIDEO_MAJOR 81 - -#define VFL_TYPE_GRABBER 0 -#define VFL_TYPE_VBI 1 -#define VFL_TYPE_RADIO 2 -#define VFL_TYPE_VTX 3 -extern int video_register_device(struct video_device *, int type, int nr); -extern void video_unregister_device(struct video_device *); extern struct video_device* video_devdata(struct file*); #define to_video_device(cd) container_of(cd, struct video_device, class_dev) @@ -68,11 +27,6 @@ video_device_remove_file(struct video_device *vfd, class_device_remove_file(&vfd->class_dev, attr); } -/* helper functions to alloc / release struct video_device, the - later can be used for video_device->release() */ -struct video_device *video_device_alloc(void); -void video_device_release(struct video_device *vfd); - /* helper functions to access driver private data. */ static inline void *video_get_drvdata(struct video_device *dev) { @@ -86,27 +40,8 @@ static inline void video_set_drvdata(struct video_device *dev, void *data) extern int video_exclusive_open(struct inode *inode, struct file *file); extern int video_exclusive_release(struct inode *inode, struct file *file); -extern int video_usercopy(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, - int (*func)(struct inode *inode, struct file *file, - unsigned int cmd, void *arg)); #endif /* __KERNEL__ */ -#define VID_TYPE_CAPTURE 1 /* Can capture */ -#define VID_TYPE_TUNER 2 /* Can tune */ -#define VID_TYPE_TELETEXT 4 /* Does teletext */ -#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */ -#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */ -#define VID_TYPE_CLIPPING 32 /* Can clip */ -#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ -#define VID_TYPE_SCALES 128 /* Scalable */ -#define VID_TYPE_MONOCHROME 256 /* Monochrome only */ -#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ -#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */ -#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */ -#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */ -#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */ - struct video_capability { char name[32]; @@ -260,9 +195,6 @@ struct video_key __u32 flags; }; - -#define VIDEO_MAX_FRAME 32 - struct video_mbuf { int size; /* Total memory to map */ @@ -270,10 +202,8 @@ struct video_mbuf int offsets[VIDEO_MAX_FRAME]; }; - #define VIDEO_NO_UNIT (-1) - struct video_unit { int video; /* Video minor */ diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 090091560c3..df0f9a24944 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -18,6 +18,82 @@ #endif #include /* need __user */ +#include +#include + +#define HAVE_V4L2 1 + +/* + * Common stuff for both V4L1 and V4L2 + * Moved from videodev.h + */ + +#define VIDEO_MAX_FRAME 32 + +#define VFL_TYPE_GRABBER 0 +#define VFL_TYPE_VBI 1 +#define VFL_TYPE_RADIO 2 +#define VFL_TYPE_VTX 3 + +struct video_device +{ + /* device info */ + struct device *dev; + char name[32]; + int type; /* v4l1 */ + int type2; /* v4l2 */ + int hardware; + int minor; + + /* device ops + callbacks */ + struct file_operations *fops; + void (*release)(struct video_device *vfd); + + + /* obsolete -- fops->owner is used instead */ + struct module *owner; + /* dev->driver_data will be used instead some day. + * Use the video_{get|set}_drvdata() helper functions, + * so the switch over will be transparent for you. + * Or use {pci|usb}_{get|set}_drvdata() directly. */ + void *priv; + + /* for videodev.c intenal usage -- please don't touch */ + int users; /* video_exclusive_{open|close} ... */ + struct semaphore lock; /* ... helper function uses these */ + char devfs_name[64]; /* devfs */ + struct class_device class_dev; /* sysfs */ +}; + +#define VIDEO_MAJOR 81 + +#define VID_TYPE_CAPTURE 1 /* Can capture */ +#define VID_TYPE_TUNER 2 /* Can tune */ +#define VID_TYPE_TELETEXT 4 /* Does teletext */ +#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */ +#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */ +#define VID_TYPE_CLIPPING 32 /* Can clip */ +#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ +#define VID_TYPE_SCALES 128 /* Scalable */ +#define VID_TYPE_MONOCHROME 256 /* Monochrome only */ +#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ +#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */ +#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */ +#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */ +#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */ + +extern int video_register_device(struct video_device *, int type, int nr); +extern void video_unregister_device(struct video_device *); +extern int video_usercopy(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + int (*func)(struct inode *inode, struct file *file, + unsigned int cmd, void *arg)); + +/* helper functions to alloc / release struct video_device, the + later can be used for video_device->release() */ +struct video_device *video_device_alloc(void); +void video_device_release(struct video_device *vfd); + /* * M I S C E L L A N E O U S */ diff --git a/include/media/video-buf.h b/include/media/video-buf.h index ee8eb15c0ea..8ecfd78e002 100644 --- a/include/media/video-buf.h +++ b/include/media/video-buf.h @@ -17,7 +17,7 @@ * (at your option) any later version. */ -#include +#include #define UNSET (-1U) -- cgit v1.2.3 From bf7e26ee5fce3eb1074ba3e1c8f265cb37c8451c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 8 Nov 2005 21:37:50 -0800 Subject: [PATCH] v4l: 810: vidioc log status is added to videodev2.h - VIDIOC_LOG_STATUS is added to videodev2.h this can be enabled again in wm8775.c. Also use the v4l2 VIDIOC_S_FREQUENCY instead of VIDIOCSFREQ. Signed-off-by: Hans Verkuil Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/wm8775.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c index 5bd592673b9..7d90ae5a99b 100644 --- a/drivers/media/video/wm8775.c +++ b/drivers/media/video/wm8775.c @@ -112,8 +112,13 @@ static int wm8775_command(struct i2c_client *client, unsigned int cmd, state->muted = 0; break; + case VIDIOC_LOG_STATUS: + wm8775_info("Input: %s%s\n", + state->input == 8 ? "radio" : "default", + state->muted ? " (muted)" : ""); + break; - case VIDIOCSFREQ: + case VIDIOC_S_FREQUENCY: /* If I remove this, then it can happen that I have no sound the first time I tune from static to a valid channel. It's difficult to reproduce and is almost certainly related -- cgit v1.2.3 From 9a741ec9b87ac13f13a1dfcb05979d7c785d0755 Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:37:50 -0800 Subject: [PATCH] v4l: 811: strip trailing whitespaces - Strip trailing whitespaces. Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tda8290.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 47d3d2ce977..8f9d7d1fd3f 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -97,7 +97,7 @@ static void tda827x_tune(struct i2c_client *c, u16 ifc, unsigned int freq) tuner_reg[3] = 0x40; tuner_reg[4] = 0x52 + (t->tda827x_lpsel << 5); tuner_reg[5] = (tda827x_analog[i].spd << 6) + (tda827x_analog[i].div1p5 <<5) + - (tda827x_analog[i].bs <<3) + tda827x_analog[i].bp; + (tda827x_analog[i].bs <<3) + tda827x_analog[i].bp; tuner_reg[6] = 0x8f + (tda827x_analog[i].gc3 << 4); tuner_reg[7] = 0x8f; @@ -220,7 +220,7 @@ static void tda827xa_tune(struct i2c_client *c, u16 ifc, unsigned int freq) tuner_reg[3] = 0; tuner_reg[4] = 0x16; tuner_reg[5] = (tda827xa_analog[i].spd << 5) + (tda827xa_analog[i].svco << 3) + - tda827xa_analog[i].sbs; + tda827xa_analog[i].sbs; tuner_reg[6] = 0x8b + (tda827xa_analog[i].gc3 << 4); tuner_reg[7] = 0x0c; tuner_reg[8] = 4; @@ -317,7 +317,7 @@ static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq) unsigned char addr_agc_stat = 0x1d; unsigned char addr_pll_stat = 0x1b; unsigned char adc_sat, agc_stat, - pll_stat; + pll_stat; i2c_master_send(c, easy_mode, 2); i2c_master_send(c, soft_reset, 2); @@ -483,11 +483,11 @@ static void tda8290_init_tuner(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); unsigned char tda8275_init[] = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf, - 0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 }; + 0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 }; unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b, - 0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b }; + 0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b }; struct i2c_msg msg = {.addr = t->tda827x_addr, .flags=0, - .buf=tda8275_init, .len = 14}; + .buf=tda8275_init, .len = 14}; if (t->tda827x_ver != 0) msg.buf = tda8275a_init; @@ -535,7 +535,7 @@ int tda8290_init(struct i2c_client *c) if (tuner_addrs == 0) { tuner_addrs = 0x61; tuner_info ("could not clearly identify tuner address, defaulting to %x\n", - tuner_addrs); + tuner_addrs); } else { tuner_addrs = tuner_addrs & 0xff; tuner_info ("setting tuner address to %x\n", tuner_addrs); -- cgit v1.2.3 From c2f6f9d866d3ea25eebe32c6c51e47e5141669cf Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Tue, 8 Nov 2005 21:37:51 -0800 Subject: [PATCH] v4l: 812: supports the pinnacle pctv 110i board video inputs and remote - Supports the Pinnacle PCTV 110i board, video inputs, and remote. Signed-off-by: Ricardo Cerqueira Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/ir-kbd-i2c.c | 118 +++++++++++++++++++++++++++- drivers/media/video/saa7134/saa7134-cards.c | 33 ++++++++ drivers/media/video/saa7134/saa7134.h | 1 + drivers/media/video/tda8290.c | 2 +- 5 files changed, 153 insertions(+), 2 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index c5ae8a32f75..9b3ef0031ef 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -75,3 +75,4 @@ 74 -> LifeView FlyTV Platinum Mini2 [14c0:1212] 75 -> AVerMedia AVerTVHD MCE A180 [1461:1044] 76 -> SKNet MonsterTV Mobile [1131:4ee9] + 77 -> Pinnacle PCTV 110i (saa7133) [11bd:002e] diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 12f1053137d..0cd1fc89b2d 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -122,6 +122,64 @@ static IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { }; +static IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = { + [ 0x59 ] = KEY_MUTE, + [ 0x4a ] = KEY_POWER, + + [ 0x18 ] = KEY_TEXT, + [ 0x26 ] = KEY_TV, + [ 0x3d ] = KEY_PRINT, + + [ 0x48 ] = KEY_RED, + [ 0x04 ] = KEY_GREEN, + [ 0x11 ] = KEY_YELLOW, + [ 0x00 ] = KEY_BLUE, + + [ 0x2d ] = KEY_VOLUMEUP, + [ 0x1e ] = KEY_VOLUMEDOWN, + + [ 0x49 ] = KEY_MENU, + + [ 0x16 ] = KEY_CHANNELUP, + [ 0x17 ] = KEY_CHANNELDOWN, + + [ 0x20 ] = KEY_UP, + [ 0x21 ] = KEY_DOWN, + [ 0x22 ] = KEY_LEFT, + [ 0x23 ] = KEY_RIGHT, + [ 0x0d ] = KEY_SELECT, + + + + [ 0x08 ] = KEY_BACK, + [ 0x07 ] = KEY_REFRESH, + + [ 0x2f ] = KEY_ZOOM, + [ 0x29 ] = KEY_RECORD, + + [ 0x4b ] = KEY_PAUSE, + [ 0x4d ] = KEY_REWIND, + [ 0x2e ] = KEY_PLAY, + [ 0x4e ] = KEY_FORWARD, + [ 0x53 ] = KEY_PREVIOUS, + [ 0x4c ] = KEY_STOP, + [ 0x54 ] = KEY_NEXT, + + [ 0x69 ] = KEY_KP0, + [ 0x6a ] = KEY_KP1, + [ 0x6b ] = KEY_KP2, + [ 0x6c ] = KEY_KP3, + [ 0x6d ] = KEY_KP4, + [ 0x6e ] = KEY_KP5, + [ 0x6f ] = KEY_KP6, + [ 0x70 ] = KEY_KP7, + [ 0x71 ] = KEY_KP8, + [ 0x72 ] = KEY_KP9, + + [ 0x74 ] = KEY_CHANNEL, + [ 0x0a ] = KEY_BACKSPACE, +}; + /* ----------------------------------------------------------------------- */ /* insmod parameters */ @@ -245,6 +303,58 @@ static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) *ir_raw = b; return 1; } + +/* The new pinnacle PCTV remote (with the colored buttons) + * + * Ricardo Cerqueira + */ + +static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +{ + unsigned char b[4]; + unsigned int start = 0,parity = 0,code = 0; + + /* poll IR chip */ + if (4 != i2c_master_recv(&ir->c,b,4)) { + dprintk(1,"read error\n"); + return -EIO; + } + + for (start = 0; start<4; start++) { + if (b[start] == 0x80) { + code=b[(start+3)%4]; + parity=b[(start+2)%4]; + } + } + + /* Empty Request */ + if (parity==0) + return 0; + + /* Repeating... */ + if (ir->old == parity) + return 0; + + + ir->old = parity; + + /* Reduce code value to fit inside IR_KEYTAB_SIZE + * + * this is the only value that results in 42 unique + * codes < 128 + */ + + code %= 0x88; + + *ir_raw = code; + *ir_key = code; + + dprintk(1,"Pinnacle PCTV key %02x\n", code); + + return 1; +} + + /* ----------------------------------------------------------------------- */ static void ir_key_poll(struct IR_i2c *ir) @@ -350,6 +460,12 @@ static int ir_attach(struct i2c_adapter *adap, int addr, ir_type = IR_TYPE_OTHER; ir_codes = ir_codes_empty; break; + case 0x47: + name = "Pinnacle PCTV"; + ir->get_key = get_key_pinnacle; + ir_type = IR_TYPE_OTHER; + ir_codes = ir_codes_pinnacle; + break; case 0x7a: name = "Purple TV"; ir->get_key = get_key_purpletv; @@ -426,7 +542,7 @@ static int ir_probe(struct i2c_adapter *adap) */ static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1}; - static const int probe_saa7134[] = { 0x7a, -1 }; + static const int probe_saa7134[] = { 0x7a, 0x47, -1 }; static const int probe_em2820[] = { 0x30, 0x47, -1 }; const int *probe = NULL; struct i2c_client c; diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index a60d49af341..0147d8342f8 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2391,6 +2391,33 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, }}, }, + [SAA7134_BOARD_PINNACLE_PCTV_110i] = { + .name = "Pinnacle PCTV 110i (saa7133)", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .gpiomask = 0x080200000, + .inputs = {{ + .name = name_tv, + .vmux = 4, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 1, + .amux = LINE2, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + }}, + .radio = { + .name = name_radio, + .amux = LINE1, + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -2808,6 +2835,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x1131, .subdevice = 0x4ee9, .driver_data = SAA7134_BOARD_MONSTERTV_MOBILE, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x11bd, + .subdevice = 0x002e, + .driver_data = SAA7134_BOARD_PINNACLE_PCTV_110i, },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index cd28a6a7b97..d497fea5425 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -203,6 +203,7 @@ struct saa7134_format { #define SAA7134_BOARD_FLYTVPLATINUM_MINI2 74 #define SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180 75 #define SAA7134_BOARD_MONSTERTV_MOBILE 76 +#define SAA7134_BOARD_PINNACLE_PCTV_110i 77 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 8f9d7d1fd3f..fa9b4b898f6 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -487,7 +487,7 @@ static void tda8290_init_tuner(struct i2c_client *c) unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b, 0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b }; struct i2c_msg msg = {.addr = t->tda827x_addr, .flags=0, - .buf=tda8275_init, .len = 14}; + .buf=tda8275_init, .len = 14}; if (t->tda827x_ver != 0) msg.buf = tda8275a_init; -- cgit v1.2.3 From 9c75541fc97252e605b7bc8f9b09f816483e22fb Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Tue, 8 Nov 2005 21:37:52 -0800 Subject: [PATCH] v4l: 813: replaced obsolete video get drvdata and video set drvdata - Replaced obsolete video_get_drvdata and video_set_drvdata Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-video.c | 45 +++++++++++++++++++++++-------- drivers/media/video/em28xx/em28xx.h | 1 + 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index e5066d05697..daa4387a229 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -50,6 +50,8 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); +static LIST_HEAD(em2820_devlist); + static unsigned int card[] = {[0 ... (EM2820_MAXBOARDS - 1)] = UNSET }; module_param_array(card, int, NULL, 0444); @@ -257,10 +259,20 @@ static void em2820_empty_framequeues(struct em2820 *dev) */ static int em2820_v4l2_open(struct inode *inode, struct file *filp) { - struct video_device *vdev = video_devdata(filp); int minor = iminor(inode); - struct em2820 *dev = (struct em2820 *)video_get_drvdata(vdev); int errCode = 0; + struct em2820 *h,*dev = NULL; + struct list_head *list; + + list_for_each(list,&em2820_devlist) { + h = list_entry(list, struct em2820, devlist); + if (h->vdev->minor == minor) { + dev = h; + } + } + + filp->private_data=dev; + em2820_videodbg("users=%d", dev->users); @@ -333,7 +345,7 @@ static void em2820_release_resources(struct em2820 *dev) em2820_info("V4L2 device /dev/video%d deregistered\n", dev->vdev->minor); - video_set_drvdata(dev->vdev, NULL); + list_del(&dev->devlist); video_unregister_device(dev->vdev); /* video_unregister_device(dev->vbi_dev); */ em2820_i2c_unregister(dev); @@ -347,9 +359,18 @@ static void em2820_release_resources(struct em2820 *dev) */ static int em2820_v4l2_close(struct inode *inode, struct file *file) { - struct video_device *vdev = video_devdata(file); - struct em2820 *dev = (struct em2820 *)video_get_drvdata(vdev); int errCode; + int minor = iminor(inode); + struct em2820 *h,*dev = NULL; + struct list_head *list; + + list_for_each(list,&em2820_devlist) { + h = list_entry(list, struct em2820, devlist); + if (h->vdev->minor == minor) { + dev = h; + } + } + em2820_videodbg("users=%d", dev->users); @@ -390,10 +411,10 @@ static ssize_t em2820_v4l2_read(struct file *filp, char __user * buf, size_t count, loff_t * f_pos) { - struct em2820 *dev = video_get_drvdata(video_devdata(filp)); struct em2820_frame_t *f, *i; unsigned long lock_flags; int ret = 0; + struct em2820 *dev = filp->private_data; if (down_interruptible(&dev->fileop_lock)) return -ERESTARTSYS; @@ -482,8 +503,8 @@ em2820_v4l2_read(struct file *filp, char __user * buf, size_t count, */ static unsigned int em2820_v4l2_poll(struct file *filp, poll_table * wait) { - struct em2820 *dev = video_get_drvdata(video_devdata(filp)); unsigned int mask = 0; + struct em2820 *dev = filp->private_data; if (down_interruptible(&dev->fileop_lock)) return POLLERR; @@ -550,10 +571,12 @@ static struct vm_operations_struct em2820_vm_ops = { */ static int em2820_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) { - struct em2820 *dev = video_get_drvdata(video_devdata(filp)); unsigned long size = vma->vm_end - vma->vm_start, start = vma->vm_start, pos, page; u32 i; + + struct em2820 *dev = filp->private_data; + if (down_interruptible(&dev->fileop_lock)) return -ERESTARTSYS; @@ -1491,8 +1514,8 @@ static int em2820_video_do_ioctl(struct inode *inode, struct file *filp, static int em2820_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { - struct em2820 *dev = video_get_drvdata(video_devdata(filp)); int ret = 0; + struct em2820 *dev = filp->private_data; if (down_interruptible(&dev->fileop_lock)) return -ERESTARTSYS; @@ -1669,7 +1692,7 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, dev->vdev->release = video_device_release; snprintf(dev->vdev->name, sizeof(dev->vdev->name), "%s", "em2820 video"); - video_set_drvdata(dev->vdev, dev); + list_add_tail(&dev->devlist,&em2820_devlist); /* register v4l2 device */ down(&dev->lock); @@ -1677,7 +1700,7 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, em2820_errdev("unable to register video device (error=%i).\n", retval); up(&dev->lock); - video_set_drvdata(dev->vdev, NULL); + list_del(&dev->devlist); video_device_release(dev->vdev); kfree(dev); return -ENODEV; diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index c48354062eb..5ff308261a7 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -211,6 +211,7 @@ struct em2820 { int model; /* index in the device_data struct */ unsigned int is_em2800; int video_inputs; /* number of video inputs */ + struct list_head devlist; unsigned int has_tuner:1; unsigned int has_msp34xx:1; unsigned int has_tda9887:1; -- cgit v1.2.3 From 86bb4a215d152111f20daeb2a530f064afee8542 Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Tue, 8 Nov 2005 21:37:53 -0800 Subject: [PATCH] v4l: 814: cleanup dev assignment - Cleanup dev assignment Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-video.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index daa4387a229..16a6d2da739 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -357,20 +357,10 @@ static void em2820_release_resources(struct em2820 *dev) * em2820_v4l2_close() * stops streaming and deallocates all resources allocated by the v4l2 calls and ioctls */ -static int em2820_v4l2_close(struct inode *inode, struct file *file) +static int em2820_v4l2_close(struct inode *inode, struct file *filp) { int errCode; - int minor = iminor(inode); - struct em2820 *h,*dev = NULL; - struct list_head *list; - - list_for_each(list,&em2820_devlist) { - h = list_entry(list, struct em2820, devlist); - if (h->vdev->minor == minor) { - dev = h; - } - } - + struct em2820 *dev=filp->private_data; em2820_videodbg("users=%d", dev->users); -- cgit v1.2.3 From 1a9ca74d22065355d61bb6395590378040e7366d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:54 -0800 Subject: [PATCH] v4l: 815: commented obsoleted stuff at videodev headers - Commented obsoleted stuff at videodev headers. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-video.c | 1 - include/linux/videodev.h | 10 ---------- include/linux/videodev2.h | 7 ------- 3 files changed, 18 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 16a6d2da739..06644e230b4 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1671,7 +1671,6 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, return -ENOMEM; } - dev->vdev->owner = THIS_MODULE; dev->vdev->type = VID_TYPE_CAPTURE; if (dev->has_tuner) dev->vdev->type |= VID_TYPE_TUNER; diff --git a/include/linux/videodev.h b/include/linux/videodev.h index 23276cede54..392592a040c 100644 --- a/include/linux/videodev.h +++ b/include/linux/videodev.h @@ -27,16 +27,6 @@ video_device_remove_file(struct video_device *vfd, class_device_remove_file(&vfd->class_dev, attr); } -/* helper functions to access driver private data. */ -static inline void *video_get_drvdata(struct video_device *dev) -{ - return dev->priv; -} - -static inline void video_set_drvdata(struct video_device *dev, void *data) -{ - dev->priv = data; -} extern int video_exclusive_open(struct inode *inode, struct file *file); extern int video_exclusive_release(struct inode *inode, struct file *file); diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index df0f9a24944..65829a510ac 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -50,13 +50,6 @@ struct video_device void (*release)(struct video_device *vfd); - /* obsolete -- fops->owner is used instead */ - struct module *owner; - /* dev->driver_data will be used instead some day. - * Use the video_{get|set}_drvdata() helper functions, - * so the switch over will be transparent for you. - * Or use {pci|usb}_{get|set}_drvdata() directly. */ - void *priv; /* for videodev.c intenal usage -- please don't touch */ int users; /* video_exclusive_{open|close} ... */ -- cgit v1.2.3 From f4067fd46aa330d6df0a79b9dd0eb9555809c440 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 8 Nov 2005 21:37:55 -0800 Subject: [PATCH] v4l: 816: added driver for cirrus logic low voltage stereo a-d converter - Added driver for Cirrus Logic Low Voltage Stereo A/D Converter. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cs53l32a.c | 234 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 drivers/media/video/cs53l32a.c diff --git a/drivers/media/video/cs53l32a.c b/drivers/media/video/cs53l32a.c new file mode 100644 index 00000000000..7434e5e66d5 --- /dev/null +++ b/drivers/media/video/cs53l32a.c @@ -0,0 +1,234 @@ +/* + * cs53l32a (Adaptec AVC-2010 and AVC-2410) i2c ivtv driver. + * Copyright (C) 2005 Martin Vaughan + * + * Audio source switching for Adaptec AVC-2410 added by Trev Jackson + * + * 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 option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC"); +MODULE_AUTHOR("Martin Vaughan"); +MODULE_LICENSE("GPL"); + +static int debug = 0; + +module_param(debug, bool, 0644); + +MODULE_PARM_DESC(debug, "Debugging messages\n\t\t\t0=Off (default), 1=On"); + +#define cs53l32a_dbg(fmt, arg...) \ + do { \ + if (debug) \ + printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \ + i2c_adapter_id(client->adapter), client->addr , ## arg); \ + } while (0) + +#define cs53l32a_err(fmt, arg...) do { \ + printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \ + i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) +#define cs53l32a_info(fmt, arg...) do { \ + printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \ + i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) + +static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END }; + + +I2C_CLIENT_INSMOD; + +/* ----------------------------------------------------------------------- */ + +static int cs53l32a_write(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +static int cs53l32a_read(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int cs53l32a_command(struct i2c_client *client, unsigned int cmd, + void *arg) +{ + int *input = arg; + + switch (cmd) { + case AUDC_SET_INPUT: + switch (*input) { + case AUDIO_TUNER: + cs53l32a_write(client, 0x01, 0x01); + break; + case AUDIO_EXTERN: + cs53l32a_write(client, 0x01, 0x21); + break; + case AUDIO_MUTE: + cs53l32a_write(client, 0x03, 0xF0); + break; + case AUDIO_UNMUTE: + cs53l32a_write(client, 0x03, 0x30); + break; + default: + cs53l32a_err("Invalid input %d.\n", *input); + return -EINVAL; + } + break; + + case VIDIOC_S_CTRL: + { + struct v4l2_control *ctrl = arg; + + if (ctrl->id != V4L2_CID_AUDIO_VOLUME) + return -EINVAL; + if (ctrl->value > 12 || ctrl->value < -90) + return -EINVAL; + cs53l32a_write(client, 0x04, (u8) ctrl->value); + cs53l32a_write(client, 0x05, (u8) ctrl->value); + break; + } + + case VIDIOC_LOG_STATUS: + { + u8 v = cs53l32a_read(client, 0x01); + u8 m = cs53l32a_read(client, 0x03); + + cs53l32a_info("Input: %s%s\n", + v == 0x21 ? "external line in" : "tuner", + (m & 0xC0) ? " (muted)" : ""); + break; + } + + default: + return -EINVAL; + } + return 0; +} + +/* ----------------------------------------------------------------------- */ + +/* i2c implementation */ + +/* + * Generic i2c probe + * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' + */ + +static struct i2c_driver i2c_driver; + +static int cs53l32a_attach(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + int i; + + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return 0; + + client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (client == 0) + return -ENOMEM; + + memset(client, 0, sizeof(struct i2c_client)); + client->addr = address; + client->adapter = adapter; + client->driver = &i2c_driver; + client->flags = I2C_CLIENT_ALLOW_USE; + snprintf(client->name, sizeof(client->name) - 1, "cs53l32a"); + + cs53l32a_info("chip found @ 0x%x (%s)\n", address << 1, adapter->name); + + for (i = 1; i <= 7; i++) { + u8 v = cs53l32a_read(client, i); + + cs53l32a_dbg("Read Reg %d %02x\n", i, v); + } + + /* Set cs53l32a internal register for Adaptec 2010/2410 setup */ + + cs53l32a_write(client, 0x01, (u8) 0x21); + cs53l32a_write(client, 0x02, (u8) 0x29); + cs53l32a_write(client, 0x03, (u8) 0x30); + cs53l32a_write(client, 0x04, (u8) 0x00); + cs53l32a_write(client, 0x05, (u8) 0x00); + cs53l32a_write(client, 0x06, (u8) 0x00); + cs53l32a_write(client, 0x07, (u8) 0x00); + + /* Display results, should be 0x21,0x29,0x30,0x00,0x00,0x00,0x00 */ + + for (i = 1; i <= 7; i++) { + u8 v = cs53l32a_read(client, i); + + cs53l32a_dbg("Read Reg %d %02x\n", i, v); + } + + i2c_attach_client(client); + + return 0; +} + +static int cs53l32a_probe(struct i2c_adapter *adapter) +{ + return i2c_probe(adapter, &addr_data, cs53l32a_attach); +} + +static int cs53l32a_detach(struct i2c_client *client) +{ + int err; + + err = i2c_detach_client(client); + if (err) { + return err; + } + kfree(client); + + return 0; +} + +/* ----------------------------------------------------------------------- */ + +/* i2c implementation */ +static struct i2c_driver i2c_driver = { + .name = "cs53l32a", + .id = I2C_DRIVERID_CS53L32A, + .flags = I2C_DF_NOTIFY, + .attach_adapter = cs53l32a_probe, + .detach_client = cs53l32a_detach, + .command = cs53l32a_command, + .owner = THIS_MODULE, +}; + + +static int __init cs53l32a_init_module(void) +{ + return i2c_add_driver(&i2c_driver); +} + +static void __exit cs53l32a_cleanup_module(void) +{ + i2c_del_driver(&i2c_driver); +} + +module_init(cs53l32a_init_module); +module_exit(cs53l32a_cleanup_module); -- cgit v1.2.3 From ac9cd97640a8bcad75dc7305761365c3e339bbc5 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Tue, 8 Nov 2005 21:37:56 -0800 Subject: [PATCH] v4l: 817: saa713x keymaps and key builders were moved from ir kbd i2c c - SAA713x keymaps and key builders were moved from ir-kbd-i2c.c Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-input.c | 4 +- drivers/media/video/ir-kbd-i2c.c | 202 +++------------------------- drivers/media/video/saa7134/saa7134-i2c.c | 14 ++ drivers/media/video/saa7134/saa7134-input.c | 202 +++++++++++++++++++++++++++- drivers/media/video/saa7134/saa7134.h | 5 + 5 files changed, 238 insertions(+), 189 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 8681a793a0b..e13585898f5 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -141,8 +141,10 @@ static int get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) /* ----------------------------------------------------------------------- */ void em2820_set_ir(struct em2820 * dev,struct IR_i2c *ir) { - if (disable_ir) + if (disable_ir) { + ir->get_key=NULL; return ; + } /* detect & configure */ switch (dev->model) { diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 0cd1fc89b2d..bdb3ba55136 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -82,104 +82,6 @@ static IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE] = { [ 28 ] = KEY_MEDIA, /* PC/TV */ }; -static IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { - [ 0x3 ] = KEY_POWER, - [ 0x6f ] = KEY_MUTE, - [ 0x10 ] = KEY_BACKSPACE, /* Recall */ - - [ 0x11 ] = KEY_KP0, - [ 0x4 ] = KEY_KP1, - [ 0x5 ] = KEY_KP2, - [ 0x6 ] = KEY_KP3, - [ 0x8 ] = KEY_KP4, - [ 0x9 ] = KEY_KP5, - [ 0xa ] = KEY_KP6, - [ 0xc ] = KEY_KP7, - [ 0xd ] = KEY_KP8, - [ 0xe ] = KEY_KP9, - [ 0x12 ] = KEY_KPDOT, /* 100+ */ - - [ 0x7 ] = KEY_VOLUMEUP, - [ 0xb ] = KEY_VOLUMEDOWN, - [ 0x1a ] = KEY_KPPLUS, - [ 0x18 ] = KEY_KPMINUS, - [ 0x15 ] = KEY_UP, - [ 0x1d ] = KEY_DOWN, - [ 0xf ] = KEY_CHANNELUP, - [ 0x13 ] = KEY_CHANNELDOWN, - [ 0x48 ] = KEY_ZOOM, - - [ 0x1b ] = KEY_VIDEO, /* Video source */ - [ 0x49 ] = KEY_LANGUAGE, /* MTS Select */ - [ 0x19 ] = KEY_SEARCH, /* Auto Scan */ - - [ 0x4b ] = KEY_RECORD, - [ 0x46 ] = KEY_PLAY, - [ 0x45 ] = KEY_PAUSE, /* Pause */ - [ 0x44 ] = KEY_STOP, - [ 0x40 ] = KEY_FORWARD, /* Forward ? */ - [ 0x42 ] = KEY_REWIND, /* Backward ? */ - -}; - -static IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = { - [ 0x59 ] = KEY_MUTE, - [ 0x4a ] = KEY_POWER, - - [ 0x18 ] = KEY_TEXT, - [ 0x26 ] = KEY_TV, - [ 0x3d ] = KEY_PRINT, - - [ 0x48 ] = KEY_RED, - [ 0x04 ] = KEY_GREEN, - [ 0x11 ] = KEY_YELLOW, - [ 0x00 ] = KEY_BLUE, - - [ 0x2d ] = KEY_VOLUMEUP, - [ 0x1e ] = KEY_VOLUMEDOWN, - - [ 0x49 ] = KEY_MENU, - - [ 0x16 ] = KEY_CHANNELUP, - [ 0x17 ] = KEY_CHANNELDOWN, - - [ 0x20 ] = KEY_UP, - [ 0x21 ] = KEY_DOWN, - [ 0x22 ] = KEY_LEFT, - [ 0x23 ] = KEY_RIGHT, - [ 0x0d ] = KEY_SELECT, - - - - [ 0x08 ] = KEY_BACK, - [ 0x07 ] = KEY_REFRESH, - - [ 0x2f ] = KEY_ZOOM, - [ 0x29 ] = KEY_RECORD, - - [ 0x4b ] = KEY_PAUSE, - [ 0x4d ] = KEY_REWIND, - [ 0x2e ] = KEY_PLAY, - [ 0x4e ] = KEY_FORWARD, - [ 0x53 ] = KEY_PREVIOUS, - [ 0x4c ] = KEY_STOP, - [ 0x54 ] = KEY_NEXT, - - [ 0x69 ] = KEY_KP0, - [ 0x6a ] = KEY_KP1, - [ 0x6b ] = KEY_KP2, - [ 0x6c ] = KEY_KP3, - [ 0x6d ] = KEY_KP4, - [ 0x6e ] = KEY_KP5, - [ 0x6f ] = KEY_KP6, - [ 0x70 ] = KEY_KP7, - [ 0x71 ] = KEY_KP8, - [ 0x72 ] = KEY_KP9, - - [ 0x74 ] = KEY_CHANNEL, - [ 0x0a ] = KEY_BACKSPACE, -}; - /* ----------------------------------------------------------------------- */ /* insmod parameters */ @@ -281,80 +183,6 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) return 1; } -static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) -{ - unsigned char b; - - /* poll IR chip */ - if (1 != i2c_master_recv(&ir->c,&b,1)) { - dprintk(1,"read error\n"); - return -EIO; - } - - /* no button press */ - if (b==0) - return 0; - - /* repeating */ - if (b & 0x80) - return 1; - - *ir_key = b; - *ir_raw = b; - return 1; -} - -/* The new pinnacle PCTV remote (with the colored buttons) - * - * Ricardo Cerqueira - */ - -static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) -{ - unsigned char b[4]; - unsigned int start = 0,parity = 0,code = 0; - - /* poll IR chip */ - if (4 != i2c_master_recv(&ir->c,b,4)) { - dprintk(1,"read error\n"); - return -EIO; - } - - for (start = 0; start<4; start++) { - if (b[start] == 0x80) { - code=b[(start+3)%4]; - parity=b[(start+2)%4]; - } - } - - /* Empty Request */ - if (parity==0) - return 0; - - /* Repeating... */ - if (ir->old == parity) - return 0; - - - ir->old = parity; - - /* Reduce code value to fit inside IR_KEYTAB_SIZE - * - * this is the only value that results in 42 unique - * codes < 128 - */ - - code %= 0x88; - - *ir_raw = code; - *ir_key = code; - - dprintk(1,"Pinnacle PCTV key %02x\n", code); - - return 1; -} - - /* ----------------------------------------------------------------------- */ static void ir_key_poll(struct IR_i2c *ir) @@ -460,19 +288,12 @@ static int ir_attach(struct i2c_adapter *adap, int addr, ir_type = IR_TYPE_OTHER; ir_codes = ir_codes_empty; break; - case 0x47: - name = "Pinnacle PCTV"; - ir->get_key = get_key_pinnacle; - ir_type = IR_TYPE_OTHER; - ir_codes = ir_codes_pinnacle; - break; case 0x7a: - name = "Purple TV"; - ir->get_key = get_key_purpletv; + case 0x47: + /* Handled by saa7134-input */ + name = "SAA713x remote"; ir_type = IR_TYPE_OTHER; - ir_codes = ir_codes_purpletv; break; - default: /* shouldn't happen */ printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n",addr); @@ -480,11 +301,8 @@ static int ir_attach(struct i2c_adapter *adap, int addr, return -1; } - /* Sets name and its physical addr */ + /* Sets name */ snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name); - snprintf(ir->phys, sizeof(ir->phys), "%s/%s/ir0", - ir->c.adapter->dev.bus_id, - ir->c.dev.bus_id); ir->ir_codes=ir_codes; /* register i2c device @@ -493,6 +311,18 @@ static int ir_attach(struct i2c_adapter *adap, int addr, */ i2c_attach_client(&ir->c); + /* If IR not supported or disabled, unregisters driver */ + if (ir->get_key == NULL) { + i2c_detach_client(&ir->c); + kfree(ir); + return -1; + } + + /* Phys addr can only be set after attaching (for ir->c.dev.bus_id) */ + snprintf(ir->phys, sizeof(ir->phys), "%s/%s/ir0", + ir->c.adapter->dev.bus_id, + ir->c.dev.bus_id); + /* init + register input device */ ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); input_dev->id.bustype = BUS_I2C; diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index 2577d03485b..7575043f087 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c @@ -335,6 +335,20 @@ static int attach_inform(struct i2c_client *client) d1printk( "%s i2c attach [addr=0x%x,client=%s]\n", client->driver->name, client->addr, client->name); + /* Am I an i2c remote control? */ + + switch (client->addr) { + case 0x7a: + case 0x47: + { + struct IR_i2c *ir = i2c_get_clientdata(client); + d1printk("%s i2c IR detected (%s).\n", + client->driver->name,ir->phys); + saa7134_set_i2c_ir(dev,ir); + break; + } + } + if (!client->driver->command) return 0; diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index f99dbb72955..6413a6e0987 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -39,6 +39,8 @@ MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); #define dprintk(fmt, arg...) if (ir_debug) \ printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg) +#define i2cdprintk(fmt, arg...) if (ir_debug) \ + printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg) /* ---------------------------------------------------------------------- */ @@ -443,7 +445,105 @@ static IR_KEYTAB_TYPE gotview7135_codes[IR_KEYTAB_SIZE] = { [ 112] = KEY_F24, /* NORMAL TIMESHIFT */ }; -/* ---------------------------------------------------------------------- */ +static IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { + [ 0x3 ] = KEY_POWER, + [ 0x6f ] = KEY_MUTE, + [ 0x10 ] = KEY_BACKSPACE, /* Recall */ + + [ 0x11 ] = KEY_KP0, + [ 0x4 ] = KEY_KP1, + [ 0x5 ] = KEY_KP2, + [ 0x6 ] = KEY_KP3, + [ 0x8 ] = KEY_KP4, + [ 0x9 ] = KEY_KP5, + [ 0xa ] = KEY_KP6, + [ 0xc ] = KEY_KP7, + [ 0xd ] = KEY_KP8, + [ 0xe ] = KEY_KP9, + [ 0x12 ] = KEY_KPDOT, /* 100+ */ + + [ 0x7 ] = KEY_VOLUMEUP, + [ 0xb ] = KEY_VOLUMEDOWN, + [ 0x1a ] = KEY_KPPLUS, + [ 0x18 ] = KEY_KPMINUS, + [ 0x15 ] = KEY_UP, + [ 0x1d ] = KEY_DOWN, + [ 0xf ] = KEY_CHANNELUP, + [ 0x13 ] = KEY_CHANNELDOWN, + [ 0x48 ] = KEY_ZOOM, + + [ 0x1b ] = KEY_VIDEO, /* Video source */ + [ 0x49 ] = KEY_LANGUAGE, /* MTS Select */ + [ 0x19 ] = KEY_SEARCH, /* Auto Scan */ + + [ 0x4b ] = KEY_RECORD, + [ 0x46 ] = KEY_PLAY, + [ 0x45 ] = KEY_PAUSE, /* Pause */ + [ 0x44 ] = KEY_STOP, + [ 0x40 ] = KEY_FORWARD, /* Forward ? */ + [ 0x42 ] = KEY_REWIND, /* Backward ? */ + +}; + +static IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = { + [ 0x59 ] = KEY_MUTE, + [ 0x4a ] = KEY_POWER, + + [ 0x18 ] = KEY_TEXT, + [ 0x26 ] = KEY_TV, + [ 0x3d ] = KEY_PRINT, + + [ 0x48 ] = KEY_RED, + [ 0x04 ] = KEY_GREEN, + [ 0x11 ] = KEY_YELLOW, + [ 0x00 ] = KEY_BLUE, + + [ 0x2d ] = KEY_VOLUMEUP, + [ 0x1e ] = KEY_VOLUMEDOWN, + + [ 0x49 ] = KEY_MENU, + + [ 0x16 ] = KEY_CHANNELUP, + [ 0x17 ] = KEY_CHANNELDOWN, + + [ 0x20 ] = KEY_UP, + [ 0x21 ] = KEY_DOWN, + [ 0x22 ] = KEY_LEFT, + [ 0x23 ] = KEY_RIGHT, + [ 0x0d ] = KEY_SELECT, + + + + [ 0x08 ] = KEY_BACK, + [ 0x07 ] = KEY_REFRESH, + + [ 0x2f ] = KEY_ZOOM, + [ 0x29 ] = KEY_RECORD, + + [ 0x4b ] = KEY_PAUSE, + [ 0x4d ] = KEY_REWIND, + [ 0x2e ] = KEY_PLAY, + [ 0x4e ] = KEY_FORWARD, + [ 0x53 ] = KEY_PREVIOUS, + [ 0x4c ] = KEY_STOP, + [ 0x54 ] = KEY_NEXT, + + [ 0x69 ] = KEY_KP0, + [ 0x6a ] = KEY_KP1, + [ 0x6b ] = KEY_KP2, + [ 0x6c ] = KEY_KP3, + [ 0x6d ] = KEY_KP4, + [ 0x6e ] = KEY_KP5, + [ 0x6f ] = KEY_KP6, + [ 0x70 ] = KEY_KP7, + [ 0x71 ] = KEY_KP8, + [ 0x72 ] = KEY_KP9, + + [ 0x74 ] = KEY_CHANNEL, + [ 0x0a ] = KEY_BACKSPACE, +}; + +/* -------------------- GPIO generic keycode builder -------------------- */ static int build_key(struct saa7134_dev *dev) { @@ -474,7 +574,81 @@ static int build_key(struct saa7134_dev *dev) return 0; } -/* ---------------------------------------------------------------------- */ +/* --------------------- Chip specific I2C key builders ----------------- */ + +static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +{ + unsigned char b; + + /* poll IR chip */ + if (1 != i2c_master_recv(&ir->c,&b,1)) { + i2cdprintk("read error\n"); + return -EIO; + } + + /* no button press */ + if (b==0) + return 0; + + /* repeating */ + if (b & 0x80) + return 1; + + *ir_key = b; + *ir_raw = b; + return 1; +} + +/* The new pinnacle PCTV remote (with the colored buttons) + * + * Ricardo Cerqueira + */ + +static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +{ + unsigned char b[4]; + unsigned int start = 0,parity = 0,code = 0; + + /* poll IR chip */ + if (4 != i2c_master_recv(&ir->c,b,4)) { + i2cdprintk("read error\n"); + return -EIO; + } + + for (start = 0; start<4; start++) { + if (b[start] == 0x80) { + code=b[(start+3)%4]; + parity=b[(start+2)%4]; + } + } + + /* Empty Request */ + if (parity==0) + return 0; + + /* Repeating... */ + if (ir->old == parity) + return 0; + + + ir->old = parity; + + /* Reduce code value to fit inside IR_KEYTAB_SIZE + * + * this is the only value that results in 42 unique + * codes < 128 + */ + + code %= 0x88; + + *ir_raw = code; + *ir_key = code; + + i2cdprintk("Pinnacle PCTV key %02x\n", code); + + return 1; +} + void saa7134_input_irq(struct saa7134_dev *dev) { @@ -658,6 +832,30 @@ void saa7134_input_fini(struct saa7134_dev *dev) dev->remote = NULL; } +void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) +{ + if (disable_ir) { + ir->get_key=NULL; + return; + } + + switch (dev->board) { + case SAA7134_BOARD_PINNACLE_PCTV_110i: + snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV"); + ir->get_key = get_key_pinnacle; + ir->ir_codes = ir_codes_pinnacle; + break; + case SAA7134_BOARD_UPMOST_PURPLE_TV: + snprintf(ir->c.name, sizeof(ir->c.name), "Purple TV"); + ir->get_key = get_key_purpletv; + ir->ir_codes = ir_codes_purpletv; + break; + default: + dprintk("Shouldn't get here: Unknown board %x for I2C IR?\n",dev->board); + break; + } + +} /* ---------------------------------------------------------------------- * Local variables: * c-basic-offset: 8 diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index d497fea5425..99d000be095 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -653,6 +654,10 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status); int saa7134_input_init1(struct saa7134_dev *dev); void saa7134_input_fini(struct saa7134_dev *dev); void saa7134_input_irq(struct saa7134_dev *dev); +void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir); + +/* ----------------------------------------------------------- */ +/* saa7134-alsa.c */ int alsa_card_saa7134_create(struct saa7134_dev *saadev, unsigned int devnum); void alsa_card_saa7134_exit(void); -- cgit v1.2.3 From e8b23c0238887e1987d82ec0014a7a1fe010e724 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Tue, 8 Nov 2005 21:37:56 -0800 Subject: [PATCH] v4l: 818: cleanup some unnecessary alsa memory (de/)allocations - Cleanup some unnecessary ALSA memory (de/)allocations Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-alsa.c | 9 +++------ drivers/media/video/saa7134/saa7134-input.c | 4 ++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index e7c3691fc50..fb6334a7ee8 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -512,7 +512,7 @@ static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime) * * Called on initialization, right before the PCM preparation * Usually used in ALSA to allocate the DMA, but since we don't use the - * ALSA DMA I'm almost sure this isn't necessary. + * ALSA DMA it does nothing * */ @@ -520,7 +520,7 @@ static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, snd_pcm_hw_params_t * hw_params) { - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); + return 0; } @@ -538,7 +538,7 @@ static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream) { - return snd_pcm_lib_free_pages(substream); + return 0; } /* @@ -670,9 +670,6 @@ static int snd_card_saa7134_pcm(snd_card_saa7134_t *saa7134, int device) pcm->private_data = saa7134; pcm->info_flags = 0; strcpy(pcm->name, "SAA7134 PCM"); - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(saa7134->pci), - 128*1024, 256*1024); return 0; } diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 6413a6e0987..0c74c2f5eda 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -617,8 +617,8 @@ static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) for (start = 0; start<4; start++) { if (b[start] == 0x80) { - code=b[(start+3)%4]; - parity=b[(start+2)%4]; + code=b[(start+3)%4]; + parity=b[(start+2)%4]; } } -- cgit v1.2.3 From 13dd38d0814f36fce3a7ec9cb29a5ce6b0fc2522 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:57 -0800 Subject: [PATCH] v4l: 819: added autodetection code to tda8290 to avoid conflicts - Added autodetection code to tda8290, to avoid conflicts with tda9887. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tda8290.c | 4 ++-- drivers/media/video/tuner-core.c | 13 ++++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index fa9b4b898f6..abad3d5b04f 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -534,8 +534,8 @@ int tda8290_init(struct i2c_client *c) } if (tuner_addrs == 0) { tuner_addrs = 0x61; - tuner_info ("could not clearly identify tuner address, defaulting to %x\n", - tuner_addrs); + tuner_info ("Could not clearly identify tda8290/8275 tuner address.\n"); + return -1; } else { tuner_addrs = tuner_addrs & 0xff; tuner_info ("setting tuner address to %x\n", tuner_addrs); diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index b9f1acf30ca..d4786b33146 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -364,7 +364,8 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) } /* TEA5767 autodetection code - only for addr = 0xc0 */ if (!no_autodetect) { - if (addr == 0x60) { + switch (addr) { + case 0x60: if (tea5767_autodetection(&t->i2c) != EINVAL) { t->type = TUNER_TEA5767; t->mode_mask = T_RADIO; @@ -376,7 +377,17 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) set_type(&t->i2c,t->type, t->mode_mask); return 0; } + case 0x42: + case 0x43: + case 0x4a: + case 0x44: + if (tda8290_init(&t->i2c)<0) { + kfree(t); + return 0; + } + } + } /* Initializes only the first adapter found */ -- cgit v1.2.3 From f59ab27b7a6fd760268f695078c739f3036b4edf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:58 -0800 Subject: [PATCH] v4l: 820: fixed log for tveeprom on em28xx cards - Fixed log for tveeprom on em28xx cards. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-cards.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index f0860532575..e6dd6eaa8d6 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -251,6 +251,7 @@ void em2820_card_setup(struct em2820 *dev) #endif /* Call first TVeeprom */ + dev->i2c_client.addr = 0xa0 >> 1; tveeprom_hauppauge_analog(&dev->i2c_client, &tv, dev->eedata); dev->tuner_type= tv.tuner_type; -- cgit v1.2.3 From 48c425965ecbd3472133adb857c2fe0608c053a0 Mon Sep 17 00:00:00 2001 From: Elad Lahav Date: Tue, 8 Nov 2005 21:37:59 -0800 Subject: [PATCH] v4l: 821: set tuner type in vidioc_g_tuner - Set tuner type in VIDIOC_G_TUNER. Signed-off-by: Elad Lahav Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/cx88-video.c | 1 + drivers/media/video/saa7134/saa7134-video.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index cedd1d79ac1..24a48f8a48c 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1506,6 +1506,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, memset(t,0,sizeof(*t)); strcpy(t->name, "Radio"); + t->type = V4L2_TUNER_RADIO; cx88_call_i2c_clients(core,VIDIOC_G_TUNER,t); return 0; diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 632ebe8724e..45c852df13e 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -1862,6 +1862,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, break; if (NULL != card_in(dev,n).name) { strcpy(t->name, "Television"); + t->type = V4L2_TUNER_ANALOG_TV; t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | @@ -2165,6 +2166,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, memset(t,0,sizeof(*t)); strcpy(t->name, "Radio"); + t->type = V4L2_TUNER_RADIO; saa7134_i2c_call_clients(dev, VIDIOC_G_TUNER, t); -- cgit v1.2.3 From 95736034df751631657140aebe677e67d7522867 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 8 Nov 2005 21:38:00 -0800 Subject: [PATCH] v4l: 823: corrected probing code for tda8290 - Corrected probing code for tda8290 Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tda8290.c | 30 +++++++++++++++++++++++++++--- drivers/media/video/tuner-core.c | 4 ++-- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index abad3d5b04f..2aeae864edc 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -135,7 +135,7 @@ static void tda827x_tune(struct i2c_client *c, u16 ifc, unsigned int freq) i2c_transfer(c->adapter, &msg, 1); reg2[0] = 0x60; - reg2[1] = 0x7f; + reg2[1] = 0x3f; i2c_transfer(c->adapter, &msg, 1); reg2[0] = 0x80; @@ -534,8 +534,8 @@ int tda8290_init(struct i2c_client *c) } if (tuner_addrs == 0) { tuner_addrs = 0x61; - tuner_info ("Could not clearly identify tda8290/8275 tuner address.\n"); - return -1; + tuner_info ("could not clearly identify tuner address, defaulting to %x\n", + tuner_addrs); } else { tuner_addrs = tuner_addrs & 0xff; tuner_info ("setting tuner address to %x\n", tuner_addrs); @@ -567,6 +567,30 @@ int tda8290_init(struct i2c_client *c) return 0; } +int tda8290_probe(struct i2c_client *c) +{ + unsigned char soft_reset[] = { 0x00, 0x00 }; + unsigned char easy_mode_b[] = { 0x01, 0x02 }; + unsigned char easy_mode_g[] = { 0x01, 0x04 }; + unsigned char addr_dto_lsb = 0x07; + unsigned char data; + + i2c_master_send(c, easy_mode_b, 2); + i2c_master_send(c, soft_reset, 2); + i2c_master_send(c, &addr_dto_lsb, 1); + i2c_master_recv(c, &data, 1); + if (data == 0) { + i2c_master_send(c, easy_mode_g, 2); + i2c_master_send(c, soft_reset, 2); + i2c_master_send(c, &addr_dto_lsb, 1); + i2c_master_recv(c, &data, 1); + if (data == 0x7b) { + return 0; + } + } + return -1; +} + /* * Overrides for Emacs so that we follow Linus's tabbing style. * --------------------------------------------------------------------------- diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index d4786b33146..ee83deb389d 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -380,8 +380,8 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) case 0x42: case 0x43: case 0x4a: - case 0x44: - if (tda8290_init(&t->i2c)<0) { + case 0x4b: + if (tda8290_probe(&t->i2c) != 0) { kfree(t); return 0; } -- cgit v1.2.3 From 01cb9633e1b294c604c2dfa01dcac95daf775213 Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:38:00 -0800 Subject: [PATCH] v4l: 826: unify whitespaces - Unify whitespaces. Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tda8290.c | 2 +- include/media/tuner.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 2aeae864edc..0dde6af251d 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -535,7 +535,7 @@ int tda8290_init(struct i2c_client *c) if (tuner_addrs == 0) { tuner_addrs = 0x61; tuner_info ("could not clearly identify tuner address, defaulting to %x\n", - tuner_addrs); + tuner_addrs); } else { tuner_addrs = tuner_addrs & 0xff; tuner_info ("setting tuner address to %x\n", tuner_addrs); diff --git a/include/media/tuner.h b/include/media/tuner.h index 8058be63ad0..5196d9eac44 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -214,6 +214,7 @@ extern int tda8290_init(struct i2c_client *c); extern int tea5767_tuner_init(struct i2c_client *c); extern int default_tuner_init(struct i2c_client *c); extern int tea5767_autodetection(struct i2c_client *c); +extern int tda8290_probe(struct i2c_client *c); #define tuner_warn(fmt, arg...) do {\ printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c.driver->name, \ -- cgit v1.2.3 From f958b68d40b870f5a0d1582f094bc93a53af7cd7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:01 -0800 Subject: [PATCH] v4l: 829: fixed user mode compiling - Fixed user mode compiling. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/videodev.h | 12 ++++++++++++ include/linux/videodev2.h | 18 ++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/include/linux/videodev.h b/include/linux/videodev.h index 392592a040c..91140091ced 100644 --- a/include/linux/videodev.h +++ b/include/linux/videodev.h @@ -27,6 +27,18 @@ video_device_remove_file(struct video_device *vfd, class_device_remove_file(&vfd->class_dev, attr); } +#if OBSOLETE_OWNER /* to be removed in 2.6.15 */ +/* helper functions to access driver private data. */ +static inline void *video_get_drvdata(struct video_device *dev) +{ + return dev->priv; +} + +static inline void video_set_drvdata(struct video_device *dev, void *data) +{ + dev->priv = data; +} +#endif extern int video_exclusive_open(struct inode *inode, struct file *file); extern int video_exclusive_release(struct inode *inode, struct file *file); diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 65829a510ac..cbe15edbe66 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -15,12 +15,13 @@ */ #ifdef __KERNEL__ #include /* need struct timeval */ +#include +#include #endif #include /* need __user */ -#include -#include +#define OBSOLETE_OWNER 1 /* It will be removed for 2.6.15 */ #define HAVE_V4L2 1 /* @@ -30,6 +31,8 @@ #define VIDEO_MAX_FRAME 32 +#ifdef __KERNEL__ + #define VFL_TYPE_GRABBER 0 #define VFL_TYPE_VBI 1 #define VFL_TYPE_RADIO 2 @@ -50,6 +53,15 @@ struct video_device void (*release)(struct video_device *vfd); +#if OBSOLETE_OWNER /* to be removed in 2.6.15 */ + /* obsolete -- fops->owner is used instead */ + struct module *owner; + /* dev->driver_data will be used instead some day. + * Use the video_{get|set}_drvdata() helper functions, + * so the switch over will be transparent for you. + * Or use {pci|usb}_{get|set}_drvdata() directly. */ + void *priv; +#endif /* for videodev.c intenal usage -- please don't touch */ int users; /* video_exclusive_{open|close} ... */ @@ -87,6 +99,8 @@ extern int video_usercopy(struct inode *inode, struct file *file, struct video_device *video_device_alloc(void); void video_device_release(struct video_device *vfd); +#endif + /* * M I S C E L L A N E O U S */ -- cgit v1.2.3 From 67678360c8b8b15b05d730eb8f1b02411891417f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:02 -0800 Subject: [PATCH] v4l: 830: rearranged print order to present a correct answer - Rearranged print order to present a correct answer. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tuner-core.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index ee83deb389d..6fd59be1918 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -348,16 +348,13 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) t->audmode = V4L2_TUNER_MODE_STEREO; t->mode_mask = T_UNINITIALIZED; - - tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name); - if (show_i2c) { unsigned char buffer[16]; int i,rc; memset(buffer, 0, sizeof(buffer)); rc = i2c_master_recv(&t->i2c, buffer, sizeof(buffer)); - printk("tuner-%04x I2C RECV = ",addr); + tuner_info("I2C RECV = "); for (i=0;ifreq = 87.5 * 16; /* Sets freq to FM range */ default_mode_mask &= ~T_RADIO; - i2c_attach_client (&t->i2c); - set_type(&t->i2c,t->type, t->mode_mask); - return 0; + goto register_client; } case 0x42: case 0x43: case 0x4a: case 0x4b: + /* If chip is not tda8290, don't register. + since it can be tda9887*/ if (tda8290_probe(&t->i2c) != 0) { kfree(t); return 0; @@ -399,6 +396,8 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) } /* Should be just before return */ +register_client: + tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name); i2c_attach_client (&t->i2c); set_type (&t->i2c,t->type, t->mode_mask); return 0; -- cgit v1.2.3 From 28f0224170c4d8115383f56985575a42ed8b4dc1 Mon Sep 17 00:00:00 2001 From: Hermann Pitton Date: Tue, 8 Nov 2005 21:38:03 -0800 Subject: [PATCH] v4l: 833: analog support for asus p7131 dual tda8275a - Analog support for Asus P7131 Dual - TDA8275A Signed-off-by: Hermann Pitton Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 34 +++++++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134.h | 1 + 3 files changed, 36 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 9b3ef0031ef..d476f8e15ba 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -76,3 +76,4 @@ 75 -> AVerMedia AVerTVHD MCE A180 [1461:1044] 76 -> SKNet MonsterTV Mobile [1131:4ee9] 77 -> Pinnacle PCTV 110i (saa7133) [11bd:002e] + 78 -> ASUSTeK P7131 Dual [1043:4862] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 0147d8342f8..155a66b3a2d 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2418,6 +2418,34 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, }, }, + [SAA7134_BOARD_ASUSTeK_P7131_DUAL] = { + .name = "ASUSTeK P7131 Dual", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .gpiomask = 1 << 21, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE2, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + }}, + .radio = { + .name = name_radio, + .amux = TV, + .gpio = 0x0200000, + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -2841,6 +2869,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x11bd, .subdevice = 0x002e, .driver_data = SAA7134_BOARD_PINNACLE_PCTV_110i, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1043, + .subdevice = 0x4862, + .driver_data = SAA7134_BOARD_ASUSTeK_P7131_DUAL, },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 99d000be095..ae89a3368ff 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -205,6 +205,7 @@ struct saa7134_format { #define SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180 75 #define SAA7134_BOARD_MONSTERTV_MOBILE 76 #define SAA7134_BOARD_PINNACLE_PCTV_110i 77 +#define SAA7134_BOARD_ASUSTeK_P7131_DUAL 78 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From fe2e36c8cdc81bea8edf7d0408a1f49da01e16ee Mon Sep 17 00:00:00 2001 From: Paul T Zalac Date: Tue, 8 Nov 2005 21:38:04 -0800 Subject: [PATCH] v4l: 834: add card pctv cardbus tv radio ito25 rev 2b - Add card: PCTV Cardbus TV/Radio (ITO25 Rev:2B) Signed-off-by: Paul T Zalac Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 16 ++++++++++++++++ drivers/media/video/saa7134/saa7134.h | 1 + 3 files changed, 18 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index d476f8e15ba..d2688c71c65 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -77,3 +77,4 @@ 76 -> SKNet MonsterTV Mobile [1131:4ee9] 77 -> Pinnacle PCTV 110i (saa7133) [11bd:002e] 78 -> ASUSTeK P7131 Dual [1043:4862] + 79 -> PCTV Cardbus TV/Radio (ITO25 Rev:2B) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 155a66b3a2d..d16d7c4cd85 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2446,6 +2446,21 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x0200000, }, }, + [SAA7134_BOARD_PCTV_CARDBUS] = { + /* Paul Tom Zalac */ + /* tda8275a tuner doesnt work yet */ + .name = "PCTV Cardbus TV/Radio (ITO25 Rev:2B)", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = {{ + .name = name_comp1, + .vmux = 1, + .amux = LINE2, + }}, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -2973,6 +2988,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVACSSMARTTV: case SAA7134_BOARD_GOTVIEW_7135: case SAA7134_BOARD_KWORLD_TERMINATOR: + case SAA7134_BOARD_PCTV_CARDBUS: dev->has_remote = 1; break; case SAA7134_BOARD_MD5044: diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index ae89a3368ff..76837004106 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -206,6 +206,7 @@ struct saa7134_format { #define SAA7134_BOARD_MONSTERTV_MOBILE 76 #define SAA7134_BOARD_PINNACLE_PCTV_110i 77 #define SAA7134_BOARD_ASUSTeK_P7131_DUAL 78 +#define SAA7134_BOARD_PCTV_CARDBUS 79 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From 08eca13dc407c389f04ce295144bb3fcd996a10d Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Tue, 8 Nov 2005 21:38:05 -0800 Subject: [PATCH] v4l: 838: modified settings for msi vox usb 2.0 - Modified settings for MSI VOX USB 2.0 Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.em28xx | 4 ++-- drivers/media/video/em28xx/em28xx-cards.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index d86aae09450..4fa58de4b86 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -1,9 +1,9 @@ 0 -> Unknown EM2800 video grabber (em2800) [eb1a:2800] - 1 -> Unknown EM2820/2840 video grabber (em2820/em2840) [eb1a:2820] + 1 -> Unknown EM2820/2840 video grabber (em2820/em2840) 2 -> Terratec Cinergy 250 USB (em2820/em2840) [0ccd:0036] 3 -> Pinnacle PCTV USB 2 (em2820/em2840) [2304:0208] 4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200] - 5 -> MSI VOX USB 2.0 (em2820/em2840) + 5 -> MSI VOX USB 2.0 (em2820/em2840) [eb1a:2820] 6 -> Terratec Cinergy 200 USB (em2800) 7 -> Leadtek Winfast USB II (em2800) 8 -> Kworld USB2800 (em2800) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index e6dd6eaa8d6..27db6d956c3 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -140,7 +140,7 @@ struct em2820_board em2820_boards[] = { .name = "MSI VOX USB 2.0", .vchannels = 3, .norm = VIDEO_MODE_PAL, - .tuner_type = TUNER_PHILIPS_PAL, + .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT|TDA9887_PORT1_ACTIVE|TDA9887_PORT2_ACTIVE, .has_tuner = 1, .decoder = EM2820_SAA7114, @@ -233,7 +233,7 @@ const unsigned int em2820_bcount = ARRAY_SIZE(em2820_boards); /* table of devices that work with this driver */ struct usb_device_id em2820_id_table [] = { { USB_DEVICE(0xeb1a, 0x2800), .driver_info = EM2800_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2820), .driver_info = EM2820_BOARD_UNKNOWN }, + { USB_DEVICE(0xeb1a, 0x2820), .driver_info = EM2820_BOARD_MSI_VOX_USB_2 }, { USB_DEVICE(0x0ccd, 0x0036), .driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 }, { USB_DEVICE(0x2304, 0x0208), .driver_info = EM2820_BOARD_PINNACLE_USB_2 }, { USB_DEVICE(0x2040, 0x4200), .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, -- cgit v1.2.3 From 30556b23f31973ca311341277c4e4b128c0528bb Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Tue, 8 Nov 2005 21:38:05 -0800 Subject: [PATCH] v4l: 840: fixed settings for msi vox usb 2.0 saa7114 is missing atm - Fixed settings for MSI Vox USB 2.0 (saa7114 is missing atm) Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-cards.c | 2 +- drivers/media/video/em28xx/em28xx-i2c.c | 3 +++ drivers/media/video/em28xx/em28xx.h | 14 ++++++++++++-- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 27db6d956c3..4ab30476807 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -146,7 +146,7 @@ struct em2820_board em2820_boards[] = { .decoder = EM2820_SAA7114, .input = {{ .type = EM2820_VMUX_TELEVISION, - .vmux = 2, + .vmux = 4, .amux = 0, },{ .type = EM2820_VMUX_COMPOSITE1, diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index bfe0d8795b6..20728882e33 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -437,6 +437,9 @@ static int attach_inform(struct i2c_client *client) case 0x86: em2820_i2c_call_clients(dev, TDA9887_SET_CONFIG, &dev->tda9887_conf); break; + case 0x42: + dprintk1(1,"attach_inform: saa7114 detected.\n"); + break; case 0x4a: dprintk1(1,"attach_inform: saa7113 detected.\n"); break; diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 5ff308261a7..15760d3d753 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -493,10 +493,20 @@ inline static int em2820_gamma_set(struct em2820 *dev, s32 val) } /*FIXME: maxw should be dependent of alt mode */ -#define norm_maxw(dev) 720 +inline static unsigned int norm_maxw(struct em2820 *dev) +{ + switch(dev->model){ + case (EM2820_BOARD_MSI_VOX_USB_2): return(640); + default: return(720); + } +} + inline static unsigned int norm_maxh(struct em2820 *dev) { - return (dev->tvnorm->id & V4L2_STD_625_50) ? 576 : 480; + switch(dev->model){ + case (EM2820_BOARD_MSI_VOX_USB_2): return(480); + default: return (dev->tvnorm->id & V4L2_STD_625_50) ? 576 : 480; + } } #endif -- cgit v1.2.3 From a38a7d4ff8539817691a335149cac903be4250f8 Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Tue, 8 Nov 2005 21:38:06 -0800 Subject: [PATCH] v4l: 841: added saa7114 initcode for msi vox usb 2.0 - Added saa7114 initcode for MSI Vox USB 2.0 Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-video.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 06644e230b4..9f79c39349f 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -86,6 +86,23 @@ static struct em2820_tvnorm tvnorms[] = { } }; +static const unsigned char saa7114_i2c_init[] = { + 0x00,0x00,0x01,0x08,0x02,0xc4,0x03,0x30,0x04,0x90,0x05,0x90,0x06,0xeb,0x07,0xe0, + 0x08,0x88,0x09,0x40,0x0a,0x80,0x0b,0x44,0x0c,0x40,0x0d,0x00,0x0e,0x81,0x0f,0x2a, + 0x10,0x06,0x11,0x00,0x12,0xc8,0x13,0x80,0x14,0x00,0x15,0x11,0x16,0x01,0x17,0x42, + 0x18,0x40,0x19,0x80,0x40,0x00,0x41,0xff,0x42,0xff,0x43,0xff,0x44,0xff,0x45,0xff, + 0x46,0xff,0x47,0xff,0x48,0xff,0x49,0xff,0x4a,0xff,0x4b,0xff,0x4c,0xff,0x4d,0xff, + 0x4e,0xff,0x4f,0xff,0x50,0xff,0x51,0xff,0x52,0xff,0x53,0xff,0x54,0x5f,0x55,0xff, + 0x56,0xff,0x57,0xff,0x58,0x00,0x59,0x47,0x5a,0x03,0x5b,0x03,0x5d,0x3e,0x5e,0x00, + 0x80,0x1c,0x83,0x01,0x84,0xa5,0x85,0x10,0x86,0x45,0x87,0x41,0x88,0xf0,0x88,0x00, + 0x88,0xf0,0x90,0x00,0x91,0x08,0x92,0x00,0x93,0x80,0x94,0x08,0x95,0x00,0x96,0xc0, + 0x97,0x02,0x98,0x13,0x99,0x00,0x9a,0x38,0x9b,0x01,0x9c,0x80,0x9d,0x02,0x9e,0x06, + 0x9f,0x01,0xa0,0x01,0xa1,0x00,0xa2,0x00,0xa4,0x80,0xa5,0x36,0xa6,0x36,0xa8,0x67, + 0xa9,0x04,0xaa,0x00,0xac,0x33,0xad,0x02,0xae,0x00,0xb0,0xcd,0xb1,0x04,0xb2,0xcd, + 0xb3,0x04,0xb4,0x01,0xb8,0x00,0xb9,0x00,0xba,0x00,0xbb,0x00,0xbc,0x00,0xbd,0x00, + 0xbe,0x00,0xbf,0x00 +}; + #define TVNORMS ARRAY_SIZE(tvnorms) /* supported controls */ @@ -216,6 +233,12 @@ void em2820_config_i2c(struct em2820 *dev) /* configure decoder */ + if(dev->model == EM2820_BOARD_MSI_VOX_USB_2){ + em2820_vdi.data=saa7114_i2c_init; + em2820_vdi.len=sizeof(saa7114_i2c_init); + } + + em2820_i2c_call_clients(dev, DECODER_INIT, &em2820_vdi); em2820_i2c_call_clients(dev, DECODER_SET_INPUT, &dev->ctl_input); /* em2820_i2c_call_clients(dev,DECODER_SET_PICTURE, &dev->vpic); */ @@ -1627,10 +1650,8 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, #ifdef CONFIG_MODULES /* request some modules */ - if (dev->decoder == EM2820_SAA7113) + if (dev->decoder == EM2820_SAA7113 || dev->decoder == EM2820_SAA7114) request_module("saa7113"); - if (dev->decoder == EM2820_SAA7114) - request_module("saa7114"); if (dev->decoder == EM2820_TVP5150) request_module("tvp5150"); if (dev->has_tuner) -- cgit v1.2.3 From f6d6e6dbdfcfc9d56550744068c2a9918798b773 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:38:07 -0800 Subject: [PATCH] v4l: 842: create kconfig files for cx88 and saa7134 directories - Create Kconfig files for cx88 and saa7134 directories. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/Kconfig | 81 +++++++++++++++++++++++++++++++++++++ drivers/media/video/saa7134/Kconfig | 58 ++++++++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 drivers/media/video/cx88/Kconfig create mode 100644 drivers/media/video/saa7134/Kconfig diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig new file mode 100644 index 00000000000..3c912152121 --- /dev/null +++ b/drivers/media/video/cx88/Kconfig @@ -0,0 +1,81 @@ +config VIDEO_CX88 + tristate "Conexant 2388x (bt878 successor) support" + depends on VIDEO_DEV && PCI && I2C && EXPERIMENTAL + select I2C_ALGOBIT + select FW_LOADER + select VIDEO_BTCX + select VIDEO_BUF + select VIDEO_TUNER + select VIDEO_TVEEPROM + select VIDEO_IR + ---help--- + This is a video4linux driver for Conexant 2388x based + TV cards. + + To compile this driver as a module, choose M here: the + module will be called cx8800 + +config VIDEO_CX88_DVB + tristate "DVB/ATSC Support for cx2388x based TV cards" + depends on VIDEO_CX88 && DVB_CORE + select VIDEO_BUF_DVB + ---help--- + This adds support for DVB/ATSC cards based on the + Connexant 2388x chip. + + To compile this driver as a module, choose M here: the + module will be called cx88-dvb. + + You must also select one or more DVB/ATSC demodulators. + If you are unsure which you need, choose all of them. + +config VIDEO_CX88_DVB_ALL_FRONTENDS + bool "Build all supported frontends for cx2388x based TV cards" + default y + depends on VIDEO_CX88_DVB + select DVB_MT352 + select DVB_OR51132 + select DVB_CX22702 + select DVB_LGDT330X + ---help--- + This builds cx88-dvb with all currently supported frontend + demodulators. If you wish to tweak your configuration, and + only include support for the hardware that you need, choose N here. + + If you are unsure, choose Y. + +config VIDEO_CX88_DVB_MT352 + tristate "Zarlink MT352 DVB-T Support" + default m + depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS + select DVB_MT352 + ---help--- + This adds DVB-T support for cards based on the + Connexant 2388x chip and the MT352 demodulator. + +config VIDEO_CX88_DVB_OR51132 + tristate "OR51132 ATSC Support" + default m + depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS + select DVB_OR51132 + ---help--- + This adds ATSC 8VSB and QAM64/256 support for cards based on the + Connexant 2388x chip and the OR51132 demodulator. + +config VIDEO_CX88_DVB_CX22702 + tristate "Conexant CX22702 DVB-T Support" + default m + depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS + select DVB_CX22702 + ---help--- + This adds DVB-T support for cards based on the + Connexant 2388x chip and the CX22702 demodulator. + +config VIDEO_CX88_DVB_LGDT330X + tristate "LG Electronics DT3302/DT3303 ATSC Support" + default m + depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS + select DVB_LGDT330X + ---help--- + This adds ATSC 8VSB and QAM64/256 support for cards based on the + Connexant 2388x chip and the LGDT3302/LGDT3303 demodulator. diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig new file mode 100644 index 00000000000..e8c89b4828f --- /dev/null +++ b/drivers/media/video/saa7134/Kconfig @@ -0,0 +1,58 @@ +config VIDEO_SAA7134 + tristate "Philips SAA7134 support" + depends on VIDEO_DEV && PCI && I2C && SOUND + select VIDEO_BUF + select VIDEO_IR + select VIDEO_TUNER + select CRC32 + ---help--- + This is a video4linux driver for Philips SAA713x based + TV cards. + + To compile this driver as a module, choose M here: the + module will be called saa7134. + +config VIDEO_SAA7134_DVB + tristate "DVB Support for saa7134 based TV cards" + depends on VIDEO_SAA7134 && DVB_CORE + select VIDEO_BUF_DVB + ---help--- + This adds support for DVB cards based on the + Philips saa7134 chip. + + To compile this driver as a module, choose M here: the + module will be called saa7134-dvb. + + You must also select one or more DVB demodulators. + If you are unsure which you need, choose all of them. + +config VIDEO_SAA7134_DVB_ALL_FRONTENDS + bool "Build all supported frontends for saa7134 based TV cards" + default y + depends on VIDEO_SAA7134_DVB + select DVB_MT352 + select DVB_TDA1004X + ---help--- + This builds saa7134-dvb with all currently supported frontend + demodulators. If you wish to tweak your configuration, and + only include support for the hardware that you need, choose N here. + + If you are unsure, choose Y. + +config VIDEO_SAA7134_DVB_MT352 + tristate "Zarlink MT352 DVB-T Support" + default m + depends on VIDEO_SAA7134_DVB && !VIDEO_SAA7134_DVB_ALL_FRONTENDS + select DVB_MT352 + ---help--- + This adds DVB-T support for cards based on the + Philips saa7134 chip and the MT352 demodulator. + +config VIDEO_SAA7134_DVB_TDA1004X + tristate "Phillips TDA10045H/TDA10046H DVB-T Support" + default m + depends on VIDEO_SAA7134_DVB && !VIDEO_SAA7134_DVB_ALL_FRONTENDS + select DVB_TDA1004X + ---help--- + This adds DVB-T support for cards based on the + Philips saa7134 chip and the TDA10045H/TDA10046H demodulator. -- cgit v1.2.3 From 791b403f5f8b2bb9ecaefc6dacfd4b96cb282274 Mon Sep 17 00:00:00 2001 From: Markus Rechberger Date: Tue, 8 Nov 2005 21:38:08 -0800 Subject: [PATCH] v4l: 843: added saa7114 support on i2c address 0x42 - Added saa7114 support on i2c address 0x42 Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa711x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c index ed16282fca5..85f3403f740 100644 --- a/drivers/media/video/saa711x.c +++ b/drivers/media/video/saa711x.c @@ -84,6 +84,7 @@ struct saa7113 { }; #define I2C_SAA7113 0x4A +#define I2C_SAA7114 0x42 /* ----------------------------------------------------------------------- */ @@ -465,6 +466,7 @@ saa7113_command (struct i2c_client *client, /* standard i2c insmod options */ static unsigned short normal_i2c[] = { I2C_SAA7113>>1, /* saa7113 */ + I2C_SAA7114>>1, /* saa7114 */ I2C_CLIENT_END }; -- cgit v1.2.3 From 5d5c9904e56ae39ff71b86dc5046e24601bff00f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:38:08 -0800 Subject: [PATCH] v4l: 847: fix bug 5484 asus digimatrix card doesnt work with pal tuner - Fix bug 5484: ASUS digimatrix card doesnt work with PAL tuner Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.saa7134 | 3 ++- drivers/media/video/saa7134/saa7134-cards.c | 26 +++++++++++++++++++++++++- drivers/media/video/saa7134/saa7134.h | 1 + 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index d2688c71c65..51252ff034e 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -62,7 +62,7 @@ 61 -> Philips TOUGH DVB-T reference design [1131:2004] 62 -> Compro VideoMate TV Gold+II 63 -> Kworld Xpert TV PVR7134 - 64 -> FlyTV mini Asus Digimatrix [1043:0210,1043:0210] + 64 -> FlyTV mini Asus Digimatrix [1043:0210] 65 -> V-Stream Studio TV Terminator 66 -> Yuan TUN-900 (saa7135) 67 -> Beholder BeholdTV 409 FM [0000:4091] @@ -78,3 +78,4 @@ 77 -> Pinnacle PCTV 110i (saa7133) [11bd:002e] 78 -> ASUSTeK P7131 Dual [1043:4862] 79 -> PCTV Cardbus TV/Radio (ITO25 Rev:2B) + 80 -> ASUS Digimatrix TV [1043:0210] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index d16d7c4cd85..6650efa44ca 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2461,6 +2461,30 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE2, }}, }, + [SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV] = { + /* "Cyril Lacoux (Yack)" */ + .name = "ASUS Digimatrix TV", + .audio_clock = 0x00200000, + .tuner_type = TUNER_PHILIPS_FQ1216ME, + .tda9887_conf = TDA9887_PRESENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + }}, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -2822,7 +2846,7 @@ struct pci_device_id saa7134_pci_tbl[] = { .device = PCI_DEVICE_ID_PHILIPS_SAA7134, .subvendor = 0x1043, .subdevice = 0x0210, /* mini pci PAL/SECAM version */ - .driver_data = SAA7134_BOARD_FLYTV_DIGIMATRIX, + .driver_data = SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV, },{ .vendor = PCI_VENDOR_ID_PHILIPS, diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 76837004106..1365f1f32fe 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -207,6 +207,7 @@ struct saa7134_format { #define SAA7134_BOARD_PINNACLE_PCTV_110i 77 #define SAA7134_BOARD_ASUSTeK_P7131_DUAL 78 #define SAA7134_BOARD_PCTV_CARDBUS 79 +#define SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV 80 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From 07345f5d6a92bc1184ca8b05069ec1cd3514fe11 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 8 Nov 2005 21:38:09 -0800 Subject: [PATCH] v4l: 848: fixed tda8290 autodetection - Fixed tda8290 autodetection Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tuner-core.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 6fd59be1918..77d25cc9cdb 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -362,16 +362,6 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) /* TEA5767 autodetection code - only for addr = 0xc0 */ if (!no_autodetect) { switch (addr) { - case 0x60: - if (tea5767_autodetection(&t->i2c) != EINVAL) { - t->type = TUNER_TEA5767; - t->mode_mask = T_RADIO; - t->mode = T_STANDBY; - t->freq = 87.5 * 16; /* Sets freq to FM range */ - default_mode_mask &= ~T_RADIO; - - goto register_client; - } case 0x42: case 0x43: case 0x4a: @@ -379,12 +369,23 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) /* If chip is not tda8290, don't register. since it can be tda9887*/ if (tda8290_probe(&t->i2c) != 0) { + tuner_dbg("chip at addr %x is not a tda8290\n", addr); kfree(t); return 0; } + break; + case 0x60: + if (tea5767_autodetection(&t->i2c) != EINVAL) { + t->type = TUNER_TEA5767; + t->mode_mask = T_RADIO; + t->mode = T_STANDBY; + t->freq = 87.5 * 16; /* Sets freq to FM range */ + default_mode_mask &= ~T_RADIO; + goto register_client; + } + break; } - } /* Initializes only the first adapter found */ -- cgit v1.2.3 From 52c02fcd00cf6fb6f5b2c8beae3b283c63cf1210 Mon Sep 17 00:00:00 2001 From: Sascha Sommer Date: Tue, 8 Nov 2005 21:38:10 -0800 Subject: [PATCH] v4l: 850: update em2800 scaler code and comments based on info from empiatech - Update em2800 scaler code and comments based on info from empiatech Signed-off-by: Sascha Sommer Signed-off-by: Markus Rechberger Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-core.c | 38 ++++++++++++------------------- drivers/media/video/em28xx/em28xx-video.c | 10 +++++--- drivers/media/video/tuner-core.c | 2 +- 3 files changed, 23 insertions(+), 27 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index ba2d986c6df..263b6c91adb 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -430,30 +430,22 @@ int em2820_capture_area_set(struct em2820 *dev, u8 hstart, u8 vstart, int em2820_scaler_set(struct em2820 *dev, u16 h, u16 v) { - u8 buf[2]; - buf[0] = h; - buf[1] = h >> 8; - em2820_write_regs(dev, HSCALELOW_REG, (char *)buf, 2); - buf[0] = v; - buf[1] = v >> 8; - em2820_write_regs(dev, VSCALELOW_REG, (char *)buf, 2); - if(dev->is_em2800){ - /* FIXME */ - /* random ratio scaling and 720x567 doesn't seem to work */ - /* the maximum we can get is 640x480 with disabled scaler */ - /* and norm_maxw set to 640 */ - if(dev->width == 640 && dev->height == 480) - return em2820_write_regs(dev, COMPR_REG,"\x00",1); - if(dev->height > 288) - return em2820_write_regs(dev, COMPR_REG,"\x10",1); - if(dev->width > 360) - return em2820_write_regs(dev, COMPR_REG,"\x20",1); + u8 mode; + /* the em2800 scaler only supports scaling down to 50% */ + if(dev->is_em2800) + mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00); + else { + u8 buf[2]; + buf[0] = h; + buf[1] = h >> 8; + em2820_write_regs(dev, HSCALELOW_REG, (char *)buf, 2); + buf[0] = v; + buf[1] = v >> 8; + em2820_write_regs(dev, VSCALELOW_REG, (char *)buf, 2); + /* it seems that both H and V scalers must be active to work correctly */ + mode = (h || v)? 0x30: 0x00; } - /* when H and V mixershould be used? */ - /* return em2820_write_reg_bits(dev, COMPR_REG, (h ? 0x20 : 0x00) | (v ? 0x10 : 0x00), 0x30); */ - /* it seems that both H and V scalers must be active to work correctly */ - return em2820_write_reg_bits(dev, COMPR_REG, h - || v ? 0x30 : 0x00, 0x30); + return em2820_write_reg_bits(dev, COMPR_REG, mode, 0x30); } /* FIXME: this only function read values from dev */ diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 9f79c39349f..a569be3e2f2 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1308,14 +1308,18 @@ static int em2820_video_do_ioctl(struct inode *inode, struct file *filp, if (width > maxw) width = maxw; - /* FIXME*/ if(dev->is_em2800){ - /* we only know how to scale to 50% */ + /* the em2800 can only scale down to 50% */ if(height % (maxh / 2)) height=maxh; if(width % (maxw / 2)) width=maxw; - /* larger resoltion don't seem to work either */ + /* according to empiatech support */ + /* the MaxPacketSize is to small to support */ + /* framesizes larger than 640x480 @ 30 fps */ + /* or 640x576 @ 25 fps. As this would cut */ + /* of a part of the image we prefer */ + /* 360x576 or 360x480 for now */ if(width == maxw && height == maxh) width /= 2; } diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 77d25cc9cdb..fce18638134 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -369,7 +369,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) /* If chip is not tda8290, don't register. since it can be tda9887*/ if (tda8290_probe(&t->i2c) != 0) { - tuner_dbg("chip at addr %x is not a tda8290\n", addr); + tuner_dbg("chip at addr %x is not a tda8290\n", addr); kfree(t); return 0; } -- cgit v1.2.3 From b228ede44c1cded7f3dadbb8bfaeaec97f7885e8 Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:38:11 -0800 Subject: [PATCH] v4l: 851: fixed broken api link and indentation - Fixed broken API link and indentation. Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/API.html | 2 +- drivers/media/video/tuner-core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/video4linux/API.html b/Documentation/video4linux/API.html index 441407b12a9..afbe9ae7ee9 100644 --- a/Documentation/video4linux/API.html +++ b/Documentation/video4linux/API.html @@ -8,7 +8,7 @@ V4L original API Obsoleted by V4L2 API - + V4L2 API Should be used for new projects diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index fce18638134..735b62b3c08 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -369,7 +369,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) /* If chip is not tda8290, don't register. since it can be tda9887*/ if (tda8290_probe(&t->i2c) != 0) { - tuner_dbg("chip at addr %x is not a tda8290\n", addr); + tuner_dbg("chip at addr %x is not a tda8290\n", addr); kfree(t); return 0; } -- cgit v1.2.3 From d5f69daf91edda79e97fbb702e6a15cdf3e496a1 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:38:12 -0800 Subject: [PATCH] v4l: 854: move cx88 and saa7134 configuration - Move cx88 and saa7134 configuration out of drivers/media/video/Kconfig and instead, use new Kconfig files in each respective directory. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/Kconfig | 53 ++------------------------------------------- 1 file changed, 2 insertions(+), 51 deletions(-) diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index bbb989df4cf..882791b14ef 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -243,29 +243,7 @@ config VIDEO_MEYE To compile this driver as a module, choose M here: the module will be called meye. -config VIDEO_SAA7134 - tristate "Philips SAA7134 support" - depends on VIDEO_DEV && PCI && I2C && SOUND - select VIDEO_BUF - select VIDEO_IR - select VIDEO_TUNER - select CRC32 - ---help--- - This is a video4linux driver for Philips SAA7130/7134 based - TV cards. - - To compile this driver as a module, choose M here: the - module will be called saa7134. - -config VIDEO_SAA7134_DVB - tristate "DVB Support for saa7134 based TV cards" - depends on VIDEO_SAA7134 && DVB_CORE - select VIDEO_BUF_DVB - select DVB_MT352 - select DVB_TDA1004X - ---help--- - This adds support for DVB cards based on the - Philips saa7134 chip. +source "drivers/media/video/saa7134/Kconfig" config VIDEO_MXB tristate "Siemens-Nixdorf 'Multimedia eXtension Board'" @@ -316,34 +294,7 @@ config VIDEO_HEXIUM_GEMINI To compile this driver as a module, choose M here: the module will be called hexium_gemini. -config VIDEO_CX88 - tristate "Conexant 2388x (bt878 successor) support" - depends on VIDEO_DEV && PCI && I2C && EXPERIMENTAL - select I2C_ALGOBIT - select FW_LOADER - select VIDEO_BTCX - select VIDEO_BUF - select VIDEO_TUNER - select VIDEO_TVEEPROM - select VIDEO_IR - ---help--- - This is a video4linux driver for Conexant 2388x based - TV cards. - - To compile this driver as a module, choose M here: the - module will be called cx8800 - -config VIDEO_CX88_DVB - tristate "DVB Support for cx2388x based TV cards" - depends on VIDEO_CX88 && DVB_CORE - select VIDEO_BUF_DVB - select DVB_MT352 - select DVB_OR51132 - select DVB_CX22702 - select DVB_LGDT330X - ---help--- - This adds support for DVB/ATSC cards based on the - Connexant 2388x chip. +source "drivers/media/video/cx88/Kconfig" config VIDEO_OVCAMCHIP tristate "OmniVision Camera Chip support" -- cgit v1.2.3 From 141a877949ffc22f33dc467dc256259c547ad52e Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:38:13 -0800 Subject: [PATCH] v4l: 855: improve kconfig user friendliness for hybrid dvb v4l boards - Improve Kconfig user-friendliness for hybrid dvb/v4l boards. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/Kconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 882791b14ef..f3b077ec0c3 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -25,6 +25,16 @@ config VIDEO_BT848 To compile this driver as a module, choose M here: the module will be called bttv. +config VIDEO_BT848_DVB + tristate "DVB/ATSC Support for bt878 based TV cards" + depends on VIDEO_BT848 && DVB_CORE + select DVB_BT8XX + ---help--- + This adds support for DVB/ATSC cards based on the BT878 chip. + + To compile this driver as a module, choose M here: the + module will be called dvb-bt8xx. + config VIDEO_SAA6588 tristate "SAA6588 Radio Chip RDS decoder support on BT848 cards" depends on VIDEO_DEV && I2C && VIDEO_BT848 -- cgit v1.2.3 From 91cad0f2bda7cd254efcbbff0e53f86941ca7764 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:13 -0800 Subject: [PATCH] v4l: 856: some module rename and small fixes - Some module rename and small fixes Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-i2c.c | 3 +++ drivers/media/video/em28xx/em28xx-video.c | 18 ++++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 20728882e33..f0b386b4eb8 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -373,6 +373,9 @@ static int em2820_i2c_eeprom(struct em2820 *dev, unsigned char *eedata, int len) printk(KERN_INFO "200mA max power\n"); break; } + printk(KERN_INFO "Table at 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n", + em_eeprom->string_idx_table,em_eeprom->string1, + em_eeprom->string2,em_eeprom->string3); return 0; } diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index a569be3e2f2..d385149edd4 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1655,7 +1655,7 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, #ifdef CONFIG_MODULES /* request some modules */ if (dev->decoder == EM2820_SAA7113 || dev->decoder == EM2820_SAA7114) - request_module("saa7113"); + request_module("saa711x"); if (dev->decoder == EM2820_TVP5150) request_module("tvp5150"); if (dev->has_tuner) @@ -1753,14 +1753,20 @@ static int em2820_usb_probe(struct usb_interface *interface, udev = usb_get_dev(interface_to_usbdev(interface)); ifnum = interface->altsetting[0].desc.bInterfaceNumber; - em2820_err(DRIVER_NAME " new device (%04x:%04x): interface %i, class %i\n", - udev->descriptor.idVendor,udev->descriptor.idProduct, - ifnum, - interface->altsetting[0].desc.bInterfaceClass); /* Don't register audio interfaces */ - if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) + if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { + em2820_err(DRIVER_NAME " audio device (%04x:%04x): interface %i, class %i\n", + udev->descriptor.idVendor,udev->descriptor.idProduct, + ifnum, + interface->altsetting[0].desc.bInterfaceClass); return -ENODEV; + } + + em2820_err(DRIVER_NAME " new video device (%04x:%04x): interface %i, class %i\n", + udev->descriptor.idVendor,udev->descriptor.idProduct, + ifnum, + interface->altsetting[0].desc.bInterfaceClass); endpoint = &interface->cur_altsetting->endpoint[1].desc; -- cgit v1.2.3 From 07eef6ce1558b21ebed9c95ad9c2b4879decf2a8 Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:38:14 -0800 Subject: [PATCH] v4l: 859: fix compilation with 2.6.8 - Fix compilation with 2.6.8. Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-alsa.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index fb6334a7ee8..bf454437b77 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -89,6 +89,8 @@ typedef struct snd_card_saa7134 { spinlock_t lock; } snd_card_saa7134_t; + + /* * PCM structure */ -- cgit v1.2.3 From 45632c4f835e74f937d8632f7ba2dd49aa39c476 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:15 -0800 Subject: [PATCH] v4l: 863: added pinnacle dazzle dvc 90 - Added Pinnacle Dazzle DVC 90 Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.em28xx | 1 + drivers/media/video/em28xx/em28xx-cards.c | 20 ++++++++++++++++++++ drivers/media/video/em28xx/em28xx.h | 1 + 3 files changed, 22 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index 4fa58de4b86..a0c7cad2097 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -7,3 +7,4 @@ 6 -> Terratec Cinergy 200 USB (em2800) 7 -> Leadtek Winfast USB II (em2800) 8 -> Kworld USB2800 (em2800) + 9 -> Pinnacle Dazzle DVC 90 (em2820/em2840) [2304:0207] diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 4ab30476807..32c2c7fdad2 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -227,6 +227,22 @@ struct em2820_board em2820_boards[] = { .amux = 1, }}, }, + [EM2820_BOARD_PINNACLE_DVC_90] = { + .name = "Pinnacle Dazzle DVC 90", + .vchannels = 3, + .norm = VIDEO_MODE_PAL, + .has_tuner = 0, + .decoder = EM2820_SAA7113, + .input = {{ + .type = EM2820_VMUX_COMPOSITE1, + .vmux = 0, + .amux = 1, + },{ + .type = EM2820_VMUX_SVIDEO, + .vmux = 9, + .amux = 1, + }}, + }, }; const unsigned int em2820_bcount = ARRAY_SIZE(em2820_boards); @@ -237,6 +253,7 @@ struct usb_device_id em2820_id_table [] = { { USB_DEVICE(0x0ccd, 0x0036), .driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 }, { USB_DEVICE(0x2304, 0x0208), .driver_info = EM2820_BOARD_PINNACLE_USB_2 }, { USB_DEVICE(0x2040, 0x4200), .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, + { USB_DEVICE(0x2304, 0x0207), .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, { }, }; @@ -258,6 +275,9 @@ void em2820_card_setup(struct em2820 *dev) if (tv.audio_processor == AUDIO_CHIP_MSP34XX) { dev->has_msp34xx=1; } else dev->has_msp34xx=0; + em2820_write_regs_req(dev,0x06,0x00,"\x40",1);// Serial Bus Frequency Select Register + em2820_write_regs_req(dev,0x0f,0x00,"\x87",1);// XCLK Frequency Select Register + em2820_write_regs_req(dev,0x88,0x0d,"\xd0",1); } } diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 15760d3d753..8c58c5b5fa3 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -40,6 +40,7 @@ #define EM2800_BOARD_TERRATEC_CINERGY_200 6 #define EM2800_BOARD_LEADTEK_WINFAST_USBII 7 #define EM2800_BOARD_KWORLD_USB2800 8 +#define EM2820_BOARD_PINNACLE_DVC_90 9 #define UNSET -1 -- cgit v1.2.3 From feff0485ebcf05b5af8a3c82aa5c361d9f8b6e75 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:16 -0800 Subject: [PATCH] v4l: 864: improved isoc error detection - Improved isoc error detection. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-core.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 263b6c91adb..442d50d7f32 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -573,8 +573,16 @@ static inline void em2820_isoc_video_copy(struct em2820 *dev, if ((*f)->fieldbytesused + len > dev->field_size) len =dev->field_size - (*f)->fieldbytesused; + + if (buf[0] != 0x88 && buf[0] != 0x22) { + em2820_isocdbg("frame is not complete\n"); + startread = buf; + len+=4; + } else + startread = buf + 4; + remain = len; - startread = buf + 4; + if ((*f)->top_field) fieldstart = (*f)->bufmem; else @@ -653,7 +661,8 @@ void em2820_isocIrq(struct urb *urb, struct pt_regs *regs) em2820_isocdbg("data error: [%d] len=%d, status=%d", i, urb->iso_frame_desc[i].actual_length, urb->iso_frame_desc[i].status); - continue; + if (urb->iso_frame_desc[i].status != -EPROTO) + continue; } if (urb->iso_frame_desc[i].actual_length <= 0) { em2820_isocdbg("packet %d is empty",i); -- cgit v1.2.3 From aa8d5e72c3b2dbd18e494564345e84a0b890dd7b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:16 -0800 Subject: [PATCH] v4l: 865: fixed bttv to accept radio devices like tea5767 - Fixed bttv to accept radio devices like tea5767. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bttv-i2c.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c index 06c5965b561..d6cccce4804 100644 --- a/drivers/media/video/bttv-i2c.c +++ b/drivers/media/video/bttv-i2c.c @@ -291,6 +291,10 @@ static struct i2c_adapter bttv_i2c_adap_hw_template = { static int attach_inform(struct i2c_client *client) { struct bttv *btv = i2c_get_adapdata(client->adapter); + int radio_addr=ADDR_UNSET; + + if (ADDR_UNSET != bttv_tvcards[btv->c.type].radio_addr) + radio_addr = bttv_tvcards[btv->c.type].radio_addr; if (bttv_debug) printk(KERN_DEBUG "bttv%d: %s i2c attach [addr=0x%x,client=%s]\n", @@ -302,10 +306,13 @@ static int attach_inform(struct i2c_client *client) if (btv->tuner_type != UNSET) { struct tuner_setup tun_setup; - tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV; + tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; tun_setup.type = btv->tuner_type; tun_setup.addr = ADDR_UNSET; + if (client->addr == radio_addr) + tun_setup.mode_mask = T_RADIO; + client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup); } -- cgit v1.2.3 From e9d096dc52493228ce1ae0fbed1d2fe0271fbe16 Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:38:17 -0800 Subject: [PATCH] v4l: 866: fix bug with setting mt2050 radio frequency - Fix bug with setting mt2050 radio frequency Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/mt20xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c index 13b61c4dcbf..2180018f06d 100644 --- a/drivers/media/video/mt20xx.c +++ b/drivers/media/video/mt20xx.c @@ -455,7 +455,7 @@ static void mt2050_set_radio_freq(struct i2c_client *c, unsigned int freq) struct tuner *t = i2c_get_clientdata(c); int if2 = t->radio_if2; - mt2050_set_if_freq(c, freq*62500, if2); + mt2050_set_if_freq(c, freq * 1000 / 16, if2); mt2050_set_antenna(c, radio_antenna); } -- cgit v1.2.3 From 85a2eb07e1a83a9569cdaddcef2db8d70e4fbea9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:18 -0800 Subject: [PATCH] v4l: 867: correcting fixes to accept radio devices like tea5767 - Correcting fixes to accept radio devices like tea5767. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bttv-i2c.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c index d6cccce4804..e509ed91a29 100644 --- a/drivers/media/video/bttv-i2c.c +++ b/drivers/media/video/bttv-i2c.c @@ -291,11 +291,14 @@ static struct i2c_adapter bttv_i2c_adap_hw_template = { static int attach_inform(struct i2c_client *client) { struct bttv *btv = i2c_get_adapdata(client->adapter); - int radio_addr=ADDR_UNSET; + int radio_addr=ADDR_UNSET, addr=ADDR_UNSET; if (ADDR_UNSET != bttv_tvcards[btv->c.type].radio_addr) radio_addr = bttv_tvcards[btv->c.type].radio_addr; + if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr) + addr = bttv_tvcards[btv->c.type].tuner_addr; + if (bttv_debug) printk(KERN_DEBUG "bttv%d: %s i2c attach [addr=0x%x,client=%s]\n", btv->c.nr,client->driver->name,client->addr, @@ -306,14 +309,20 @@ static int attach_inform(struct i2c_client *client) if (btv->tuner_type != UNSET) { struct tuner_setup tun_setup; - tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; - tun_setup.type = btv->tuner_type; - tun_setup.addr = ADDR_UNSET; + if ((addr==ADDR_UNSET)||(addr==client->addr)) { + tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; + tun_setup.type = btv->tuner_type; + tun_setup.addr = ADDR_UNSET; - if (client->addr == radio_addr) - tun_setup.mode_mask = T_RADIO; + client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup); + } + if ((radio_addr==ADDR_UNSET)||(radio_addr==client->addr)) { + tun_setup.mode_mask = T_RADIO; + tun_setup.type = btv->tuner_type; + tun_setup.addr = ADDR_UNSET; - client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup); + client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup); + } } if (btv->pinnacle_id != UNSET) -- cgit v1.2.3 From fde6d31e19addca8be17dee7f47ad0a7fcaa79ca Mon Sep 17 00:00:00 2001 From: Kirk Lapray Date: Tue, 8 Nov 2005 21:38:18 -0800 Subject: [PATCH] v4l: 868: added support for nxt200x based cards ati hdtv wonder - Added support for NXT200X based cards (ATI HDTV Wonder) Signed-off-by: Kirk Lapray Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/Kconfig | 10 ++++++++++ drivers/media/video/cx88/Makefile | 3 +++ drivers/media/video/cx88/cx88-cards.c | 8 +++----- drivers/media/video/cx88/cx88-dvb.c | 26 ++++++++++++++++++++++++++ drivers/media/video/tuner-simple.c | 19 +++++++++++++++++-- 5 files changed, 59 insertions(+), 7 deletions(-) diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 3c912152121..1c9009589d1 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -37,6 +37,7 @@ config VIDEO_CX88_DVB_ALL_FRONTENDS select DVB_OR51132 select DVB_CX22702 select DVB_LGDT330X + select DVB_NXT200X ---help--- This builds cx88-dvb with all currently supported frontend demodulators. If you wish to tweak your configuration, and @@ -79,3 +80,12 @@ config VIDEO_CX88_DVB_LGDT330X ---help--- This adds ATSC 8VSB and QAM64/256 support for cards based on the Connexant 2388x chip and the LGDT3302/LGDT3303 demodulator. + +config VIDEO_CX88_DVB_NXT200X + tristate "NXT2002/NXT2004 ATSC Support" + default m + depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS + select DVB_NXT200X + ---help--- + This adds ATSC 8VSB and QAM64/256 support for cards based on the + Connexant 2388x chip and the NXT2002/NXT2004 demodulator. diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile index be1dc66e065..0df40b77345 100644 --- a/drivers/media/video/cx88/Makefile +++ b/drivers/media/video/cx88/Makefile @@ -24,3 +24,6 @@ endif ifneq ($(CONFIG_DVB_MT352),n) EXTRA_CFLAGS += -DHAVE_MT352=1 endif +ifneq ($(CONFIG_DVB_NXT200X),n) + EXTRA_CFLAGS += -DHAVE_NXT200X=1 +endif diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 50491776879..f20984eb553 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -851,6 +851,7 @@ struct cx88_board cx88_boards[] = { .gpio2 = 0x00000001, .gpio3 = 0x00000000, }}, + .dvb = 1, }, [CX88_BOARD_WINFAST_DTV1000] = { .name = "WinFast DTV1000-T", @@ -1212,13 +1213,10 @@ void cx88_card_setup(struct cx88_core *core) if (0 == core->i2c_rc) { /* enable tuner */ int i; - u8 buffer[12]; + u8 buffer [] = { 0x10,0x12,0x13,0x04,0x16,0x00,0x14,0x04,0x017,0x00 }; core->i2c_client.addr = 0x0a; - buffer[0] = 0x10; buffer[1] = 0x12; buffer[2] = 0x13; buffer[3] = 0x04; - buffer[4] = 0x16; buffer[5] = 0x00; buffer[6] = 0x14; buffer[7] = 0x04; - buffer[8] = 0x14; buffer[9] = 0x00; buffer[10] = 0x17; buffer[11] = 0x00; - for (i = 0; i < 6; i++) + for (i = 0; i < 5; i++) if (2 != i2c_master_send(&core->i2c_client,&buffer[i*2],2)) printk(KERN_WARNING "%s: Unable to enable tuner(%i).\n", core->name, i); diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index a7a077196fc..1236cb11d83 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -45,6 +45,9 @@ #ifdef HAVE_LGDT330X # include "lgdt330x.h" #endif +#ifdef HAVE_NXT200X +# include "nxt200x.h" +#endif MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); MODULE_AUTHOR("Chris Pascoe "); @@ -284,6 +287,23 @@ static struct lgdt330x_config fusionhdtv_5_gold = { }; #endif +#ifdef HAVE_NXT200X +static int nxt200x_set_ts_param(struct dvb_frontend* fe, + int is_punctured) +{ + struct cx8802_dev *dev= fe->dvb->priv; + dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; + return 0; +} + +static struct nxt200x_config ati_hdtvwonder = { + .demod_address = 0x0a, + .pll_address = 0x61, + .pll_desc = &dvb_pll_tuv1236d, + .set_ts_params = nxt200x_set_ts_param, +}; +#endif + static int dvb_register(struct cx8802_dev *dev) { /* init struct videobuf_dvb */ @@ -384,6 +404,12 @@ static int dvb_register(struct cx8802_dev *dev) &dev->core->i2c_adap); } break; +#endif +#ifdef HAVE_NXT200X + case CX88_BOARD_ATI_HDTVWONDER: + dev->dvb.frontend = nxt200x_attach(&ati_hdtvwonder, + &dev->core->i2c_adap); + break; #endif default: printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 84338f1e303..34ba6d13b58 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -251,7 +251,7 @@ static struct tunertype tuners[] = { { "Philips TD1316 Hybrid Tuner", Philips, PAL, 16*160.00,16*442.00,0xa1,0xa2,0xa4,0xc8,623 }, { "Philips TUV1236D ATSC/NTSC dual in", Philips, ATSC, - 16*157.25,16*454.00,0x01,0x02,0x03,0xce,732 }, + 16*157.25,16*454.00,0x01,0x02,0x04,0xce,732 }, }; unsigned const int tuner_count = ARRAY_SIZE(tuners); @@ -383,9 +383,24 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) /* 0x48 -> ATSC antenna input 2 */ /* 0x00 -> NTSC antenna input 1 */ /* 0x08 -> NTSC antenna input 2 */ + buffer[0] = 0x14; + buffer[1] = 0x00; + buffer[2] = 0x17; + buffer[3] = 0x00; config &= ~0x40; - if (t->std & V4L2_STD_ATSC) + if (t->std & V4L2_STD_ATSC) { config |= 0x40; + buffer[1] = 0x04; + } + /* set to the correct mode (analog or digital) */ + u8 tuneraddr; + tuneraddr = c->addr; + c->addr = 0x0a; + if (2 != (rc = i2c_master_send(c,&buffer[0],2))) + tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc); + if (2 != (rc = i2c_master_send(c,&buffer[2],2))) + tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc); + c->addr = tuneraddr; /* FIXME: input */ break; } -- cgit v1.2.3 From f4372beb84874ab33f2b06bd6a66ff6d07427081 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:38:19 -0800 Subject: [PATCH] v4l: 869: iso c90 forbids mixed declarations and code - ISO C90 forbids mixed declarations and code Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tuner-simple.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 34ba6d13b58..d832205818f 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -299,7 +299,7 @@ static int tuner_stereo(struct i2c_client *c) static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) { struct tuner *t = i2c_get_clientdata(c); - u8 config; + u8 config, tuneraddr; u16 div; struct tunertype *tun; unsigned char buffer[4]; @@ -393,7 +393,6 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) buffer[1] = 0x04; } /* set to the correct mode (analog or digital) */ - u8 tuneraddr; tuneraddr = c->addr; c->addr = 0x0a; if (2 != (rc = i2c_master_send(c,&buffer[0],2))) -- cgit v1.2.3 From 3b64e8e238217ebd3d847ca19ead631124a2ed14 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:38:20 -0800 Subject: [PATCH] v4l: 870: added dvb support for avermedia avertvhd mce a180 - Added DVB support for AVerMedia AVerTVHD MCE A180 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/Kconfig | 12 +++++++++++- drivers/media/video/saa7134/Makefile | 3 +++ drivers/media/video/saa7134/saa7134-cards.c | 1 + drivers/media/video/saa7134/saa7134-dvb.c | 17 +++++++++++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index e8c89b4828f..624e8808a51 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig @@ -13,7 +13,7 @@ config VIDEO_SAA7134 module will be called saa7134. config VIDEO_SAA7134_DVB - tristate "DVB Support for saa7134 based TV cards" + tristate "DVB/ATSC Support for saa7134 based TV cards" depends on VIDEO_SAA7134 && DVB_CORE select VIDEO_BUF_DVB ---help--- @@ -32,6 +32,7 @@ config VIDEO_SAA7134_DVB_ALL_FRONTENDS depends on VIDEO_SAA7134_DVB select DVB_MT352 select DVB_TDA1004X + select DVB_NXT200X ---help--- This builds saa7134-dvb with all currently supported frontend demodulators. If you wish to tweak your configuration, and @@ -56,3 +57,12 @@ config VIDEO_SAA7134_DVB_TDA1004X ---help--- This adds DVB-T support for cards based on the Philips saa7134 chip and the TDA10045H/TDA10046H demodulator. + +config VIDEO_SAA7134_DVB_NXT200X + tristate "NXT2002/NXT2004 ATSC Support" + default m + depends on VIDEO_SAA7134_DVB && !VIDEO_SAA7134_DVB_ALL_FRONTENDS + select DVB_NXT200X + ---help--- + This adds ATSC 8VSB and QAM64/256 support for cards based on the + Philips saa7134 chip and the NXT2002/NXT2004 demodulator. diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile index 1418f9f88d2..937dff8d561 100644 --- a/drivers/media/video/saa7134/Makefile +++ b/drivers/media/video/saa7134/Makefile @@ -18,3 +18,6 @@ endif ifneq ($(CONFIG_DVB_TDA1004X),n) EXTRA_CFLAGS += -DHAVE_TDA1004X=1 endif +ifneq ($(CONFIG_DVB_NXT200X),n) + EXTRA_CFLAGS += -DHAVE_NXT200X=1 +endif diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 6650efa44ca..2f201520245 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2358,6 +2358,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .mpeg = SAA7134_MPEG_DVB, .inputs = {{ .name = name_comp1, .vmux = 3, diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 342891d431a..aaac12e8adb 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -39,6 +39,10 @@ #ifdef HAVE_TDA1004X # include "tda1004x.h" #endif +#ifdef HAVE_NXT200X +# include "nxt200x.h" +# include "dvb-pll.h" +#endif MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); @@ -624,6 +628,14 @@ static struct tda1004x_config tda827x_lifeview_config = { }; #endif +#ifdef HAVE_NXT200X +static struct nxt200x_config avertvhda180 = { + .demod_address = 0x0a, + .pll_address = 0x61, + .pll_desc = &dvb_pll_tdhu2, +}; +#endif + /* ------------------------------------------------------------------ */ static int dvb_init(struct saa7134_dev *dev) @@ -676,6 +688,11 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend = tda10046_attach(&philips_tu1216_61_config, &dev->i2c_adap); break; +#endif +#ifdef HAVE_NXT200X + case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180: + dev->dvb.frontend = nxt200x_attach(&avertvhda180, &dev->i2c_adap); + break; #endif default: printk("%s: Huh? unknown DVB card?\n",dev->name); -- cgit v1.2.3 From 24d412289d5508f033d11154f981b478f8831c0d Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Tue, 8 Nov 2005 21:38:21 -0800 Subject: [PATCH] v4l: 871: fixed bttv to accept radio devices like tea5767 - Fixed bttv to accept radio devices like tea5767 Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bttv-cards.c | 4 +--- drivers/media/video/bttv-i2c.c | 11 ++++++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 695a67e9edd..89aa5cbb8b9 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -2721,13 +2721,11 @@ struct tvcard bttv_tvcards[] = { .audiomux = { 0, 1, 2, 2, 3 }, .needs_tvaudio = 0, .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .tuner_type = TUNER_TENA_9533_DI, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .has_remote = 1, - #if 0 .has_radio = 1, - #endif }, /* ---- card 0x8a ---------------------------------- */ [BTTV_BOARD_PV_BT878P_2E] = { diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c index e509ed91a29..5ad335705e1 100644 --- a/drivers/media/video/bttv-i2c.c +++ b/drivers/media/video/bttv-i2c.c @@ -308,21 +308,22 @@ static int attach_inform(struct i2c_client *client) if (btv->tuner_type != UNSET) { struct tuner_setup tun_setup; + struct tuner *t = i2c_get_clientdata(client); if ((addr==ADDR_UNSET)||(addr==client->addr)) { tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; tun_setup.type = btv->tuner_type; tun_setup.addr = ADDR_UNSET; - client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup); } - if ((radio_addr==ADDR_UNSET)||(radio_addr==client->addr)) { + + if (t->type != UNSET && t->mode_mask == T_RADIO) { + tun_setup.type = t->type; tun_setup.mode_mask = T_RADIO; - tun_setup.type = btv->tuner_type; tun_setup.addr = ADDR_UNSET; - - client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup); } + + client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup); } if (btv->pinnacle_id != UNSET) -- cgit v1.2.3 From ac113d15a9d1a85f57969244301850379b5f17dd Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:38:21 -0800 Subject: [PATCH] v4l: 873: updated comments for avertvhd a180 - Updated comments for AVerTVHD A180 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-cards.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 2f201520245..9e1c51c08f2 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2351,7 +2351,11 @@ struct saa7134_board saa7134_boards[] = { }}, }, [SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180] = { - /* FIXME: uses Alps Electric TDHU2, containing ATI NXT2004 ATSC Decoder */ + /* Michael Krufky + * Uses Alps Electric TDHU2, containing NXT2004 ATSC Decoder + * AFAIK, there is no analog demod, thus, + * no support for analog television. + */ .name = "AVerMedia AVerTVHD MCE A180", .audio_clock = 0x00187de7, .tuner_type = TUNER_ABSENT, -- cgit v1.2.3 From 50c8640725453f2487da9267844a962108c8418e Mon Sep 17 00:00:00 2001 From: "Nickolay V. Shmyrev" Date: Tue, 8 Nov 2005 21:38:22 -0800 Subject: [PATCH] v4l: 874: quick and dirty fix for audc config pinnacle - Quick and dirty fix for AUDC_CONFIG_PINNACLE. Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tuner-core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 735b62b3c08..3fde4f90425 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -497,8 +497,6 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } case AUDC_CONFIG_PINNACLE: - if (check_mode(t, "AUDC_CONFIG_PINNACLE") == EINVAL) - return 0; switch (*iarg) { case 2: tuner_dbg("pinnacle pal\n"); -- cgit v1.2.3 From f3b512fd42b4ed6ff47a8afb4f42ac3cc325ddad Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:23 -0800 Subject: [PATCH] v4l: 875: some cleanups at i2c stuff and fixing when tuner addr is set - Some cleanups at I2C stuff and fixing when tuner addr is set. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bttv-cards.c | 19 ++++++++----------- drivers/media/video/bttv-i2c.c | 20 +++----------------- 2 files changed, 11 insertions(+), 28 deletions(-) diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 89aa5cbb8b9..d81672acdaa 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -3188,7 +3188,7 @@ void __devinit bttv_init_card1(struct bttv *btv) void __devinit bttv_init_card2(struct bttv *btv) { int tda9887; - int addr=ADDR_UNSET, radio_addr=ADDR_UNSET; + int addr=ADDR_UNSET; btv->tuner_type = -1; @@ -3333,31 +3333,28 @@ void __devinit bttv_init_card2(struct bttv *btv) if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr) addr = bttv_tvcards[btv->c.type].tuner_addr; - if (ADDR_UNSET != bttv_tvcards[btv->c.type].radio_addr) - radio_addr = bttv_tvcards[btv->c.type].radio_addr; - if (UNSET != bttv_tvcards[btv->c.type].tuner_type) if(UNSET == btv->tuner_type) btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type; if (UNSET != tuner[btv->c.nr]) btv->tuner_type = tuner[btv->c.nr]; printk("bttv%d: using tuner=%d\n",btv->c.nr,btv->tuner_type); - if (btv->pinnacle_id != UNSET) - bttv_call_i2c_clients(btv, AUDC_CONFIG_PINNACLE, - &btv->pinnacle_id); + if (btv->tuner_type != UNSET) { struct tuner_setup tun_setup; - tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; + tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; tun_setup.type = btv->tuner_type; tun_setup.addr = addr; - if (addr == radio_addr) - tun_setup.mode_mask = T_RADIO; - bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup); } + if (btv->pinnacle_id != UNSET) { + bttv_call_i2c_clients(btv, AUDC_CONFIG_PINNACLE, + &btv->pinnacle_id); + } + btv->svhs = bttv_tvcards[btv->c.type].svhs; if (svhs[btv->c.nr] != UNSET) btv->svhs = svhs[btv->c.nr]; diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c index 5ad335705e1..aaabef26105 100644 --- a/drivers/media/video/bttv-i2c.c +++ b/drivers/media/video/bttv-i2c.c @@ -291,14 +291,11 @@ static struct i2c_adapter bttv_i2c_adap_hw_template = { static int attach_inform(struct i2c_client *client) { struct bttv *btv = i2c_get_adapdata(client->adapter); - int radio_addr=ADDR_UNSET, addr=ADDR_UNSET; + int radio_addr=ADDR_UNSET; if (ADDR_UNSET != bttv_tvcards[btv->c.type].radio_addr) radio_addr = bttv_tvcards[btv->c.type].radio_addr; - if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr) - addr = bttv_tvcards[btv->c.type].tuner_addr; - if (bttv_debug) printk(KERN_DEBUG "bttv%d: %s i2c attach [addr=0x%x,client=%s]\n", btv->c.nr,client->driver->name,client->addr, @@ -310,25 +307,14 @@ static int attach_inform(struct i2c_client *client) struct tuner_setup tun_setup; struct tuner *t = i2c_get_clientdata(client); - if ((addr==ADDR_UNSET)||(addr==client->addr)) { - tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; - tun_setup.type = btv->tuner_type; - tun_setup.addr = ADDR_UNSET; - - } - if (t->type != UNSET && t->mode_mask == T_RADIO) { tun_setup.type = t->type; tun_setup.mode_mask = T_RADIO; - tun_setup.addr = ADDR_UNSET; + tun_setup.addr = radio_addr; + client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup); } - - client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup); } - if (btv->pinnacle_id != UNSET) - client->driver->command(client,AUDC_CONFIG_PINNACLE, - &btv->pinnacle_id); return 0; } -- cgit v1.2.3 From c12097fd9adb07810fb28f70df5462c0603463cc Mon Sep 17 00:00:00 2001 From: Michael Schimek Date: Tue, 8 Nov 2005 21:38:24 -0800 Subject: [PATCH] v4l: 876: moved some user defines to be out of kernel define - Moved some user defines to be out of __KERNEL__ define. Signed-off-by: Michael Schimek Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/videodev2.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index cbe15edbe66..e8a0d22df54 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -31,6 +31,21 @@ #define VIDEO_MAX_FRAME 32 +#define VID_TYPE_CAPTURE 1 /* Can capture */ +#define VID_TYPE_TUNER 2 /* Can tune */ +#define VID_TYPE_TELETEXT 4 /* Does teletext */ +#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */ +#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */ +#define VID_TYPE_CLIPPING 32 /* Can clip */ +#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ +#define VID_TYPE_SCALES 128 /* Scalable */ +#define VID_TYPE_MONOCHROME 256 /* Monochrome only */ +#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ +#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */ +#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */ +#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */ +#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */ + #ifdef __KERNEL__ #define VFL_TYPE_GRABBER 0 @@ -72,21 +87,6 @@ struct video_device #define VIDEO_MAJOR 81 -#define VID_TYPE_CAPTURE 1 /* Can capture */ -#define VID_TYPE_TUNER 2 /* Can tune */ -#define VID_TYPE_TELETEXT 4 /* Does teletext */ -#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */ -#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */ -#define VID_TYPE_CLIPPING 32 /* Can clip */ -#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ -#define VID_TYPE_SCALES 128 /* Scalable */ -#define VID_TYPE_MONOCHROME 256 /* Monochrome only */ -#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ -#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */ -#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */ -#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */ -#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */ - extern int video_register_device(struct video_device *, int type, int nr); extern void video_unregister_device(struct video_device *); extern int video_usercopy(struct inode *inode, struct file *file, -- cgit v1.2.3 From f7abcd385cc8a5a2f75b07c8325067ea2785ba1e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:25 -0800 Subject: [PATCH] v4l: 877: module em2820 renamed to em28xx and moved to v4l dir - Module em2820 renamed to em28xx and moved to V4L dir. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-cards.c | 11 ++++----- drivers/media/video/em28xx/em28xx-core.c | 9 ++++--- drivers/media/video/em28xx/em28xx-i2c.c | 11 ++++----- drivers/media/video/em28xx/em28xx-input.c | 39 +++++++++++++++++-------------- drivers/media/video/em28xx/em28xx-video.c | 22 ++++++++--------- 5 files changed, 46 insertions(+), 46 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 32c2c7fdad2..ecfc8a3374d 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -1,11 +1,10 @@ /* - em2820-cards.c - driver for Empia EM2800/EM2820/2840 USB video capture devices + em28xx-cards.c - driver for Empia EM2800/EM2820/2840 USB video capture devices - Copyright (C) 2005 Markus Rechberger - Ludovico Cavedon + Copyright (C) 2005 Ludovico Cavedon + Markus Rechberger Mauro Carvalho Chehab - - Based on the em2800 driver from Sascha Sommer + Sascha Sommer 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 @@ -33,7 +32,7 @@ #include #include "msp3400.h" -#include "em2820.h" +#include "em28xx.h" struct em2820_board em2820_boards[] = { [EM2800_BOARD_UNKNOWN] = { diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 442d50d7f32..e5aae4fa818 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -1,11 +1,10 @@ /* em2820-core.c - driver for Empia EM2800/EM2820/2840 USB video capture devices - Copyright (C) 2005 Markus Rechberger - Ludovico Cavedon + Copyright (C) 2005 Ludovico Cavedon + Markus Rechberger Mauro Carvalho Chehab - - Based on the em2800 driver from Sascha Sommer + Sascha Sommer 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 @@ -29,7 +28,7 @@ #include #include -#include "em2820.h" +#include "em28xx.h" /* #define ENABLE_DEBUG_ISOC_FRAMES */ diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index f0b386b4eb8..a62e66bd65f 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -1,11 +1,10 @@ /* - em2820-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices + em28xx-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices - Copyright (C) 2005 Markus Rechberger - Ludovico Cavedon + Copyright (C) 2005 Ludovico Cavedon + Markus Rechberger Mauro Carvalho Chehab - - Based on the em2800 driver from Sascha Sommer + Sascha Sommer 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 @@ -28,7 +27,7 @@ #include #include -#include "em2820.h" +#include "em28xx.h" #include /* ----------------------------------------------------------- */ diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index e13585898f5..be7ba9b24d0 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -1,21 +1,24 @@ /* - * - * handle saa7134 IR remotes via linux kernel input layer. - * - * 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 option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + handle em28xx IR remotes via linux kernel input layer. + + Copyright (C) 2005 Ludovico Cavedon + Markus Rechberger + Mauro Carvalho Chehab + Sascha Sommer + + 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 option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include @@ -27,7 +30,7 @@ #include #include -#include "em2820.h" +#include "em28xx.h" static unsigned int disable_ir = 0; module_param(disable_ir, int, 0444); diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index d385149edd4..5ae896a1dcf 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1,11 +1,10 @@ /* - em2820-video.c - driver for Empia EM2800/EM2820/2840 USB video capture devices + em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB video capture devices - Copyright (C) 2005 Markus Rechberger - Ludovico Cavedon + Copyright (C) 2005 Ludovico Cavedon + Markus Rechberger Mauro Carvalho Chehab - - Based on the em2800 driver from Sascha Sommer + Sascha Sommer 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 @@ -30,15 +29,16 @@ #include #include -#include "em2820.h" +#include "em28xx.h" #include -#define DRIVER_AUTHOR "Markus Rechberger , " \ - "Ludovico Cavedon , " \ - "Mauro Carvalho Chehab " +#define DRIVER_AUTHOR "Ludovico Cavedon , " \ + "Markus Rechberger , " \ + "Mauro Carvalho Chehab , " \ + "Sascha Sommer " -#define DRIVER_NAME "em2820" -#define DRIVER_DESC "Empia em2820 based USB video device driver" +#define DRIVER_NAME "em28xx" +#define DRIVER_DESC "Empia em28xx based USB video device driver" #define EM2820_VERSION_CODE KERNEL_VERSION(0, 0, 1) #define em2820_videodbg(fmt, arg...) do {\ -- cgit v1.2.3 From 710a72589a6727973405fd3580d7c724ba709296 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:38:25 -0800 Subject: [PATCH] v4l: 881: video cx88 need not depend on experimental - VIDEO_CX88 need not depend on EXPERIMENTAL Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 1c9009589d1..41818b6205b 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -1,6 +1,6 @@ config VIDEO_CX88 tristate "Conexant 2388x (bt878 successor) support" - depends on VIDEO_DEV && PCI && I2C && EXPERIMENTAL + depends on VIDEO_DEV && PCI && I2C select I2C_ALGOBIT select FW_LOADER select VIDEO_BTCX -- cgit v1.2.3 From e0ec29b7e5aa1f4f1ff73ebd3003336dbe83e174 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 8 Nov 2005 21:38:26 -0800 Subject: [PATCH] v4l: 885: second round of i2c ids redefinition cleanup - Second round of i2c IDs redefinition cleanup. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bt832.c | 1 - drivers/media/video/msp3400.c | 1 - drivers/media/video/saa6588.c | 1 - drivers/media/video/saa7134/saa6752hs.c | 1 - drivers/media/video/saa7134/saa7134.h | 1 - drivers/media/video/tda7432.c | 1 - drivers/media/video/tda9875.c | 1 - drivers/media/video/tda9887.c | 1 - drivers/media/video/tvaudio.c | 3 +-- drivers/media/video/tveeprom.c | 4 ---- include/linux/i2c-id.h | 11 +++++++---- 11 files changed, 8 insertions(+), 18 deletions(-) diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c index 3e42493a4e0..e4063950ae5 100644 --- a/drivers/media/video/bt832.c +++ b/drivers/media/video/bt832.c @@ -32,7 +32,6 @@ #include #include -#include #include "bttv.h" #include "bt832.h" diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index ba2c95842fb..d603229c9f2 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -54,7 +54,6 @@ #include #include -#include #include "msp3400.h" #define OPMODE_AUTO -1 diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index 5252a4ca3fd..23ea548a71e 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -31,7 +31,6 @@ #include #include -#include #include "rds.h" diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index 2bf5cf79eec..cdd1ed9c806 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c @@ -13,7 +13,6 @@ #include #include -#include #define MPEG_VIDEO_TARGET_BITRATE_MAX 27000 #define MPEG_VIDEO_MAX_BITRATE_MAX 27000 diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 1365f1f32fe..4273ded9d17 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -34,7 +34,6 @@ #include #include -#include #include #include #include diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c index 14cf1d357c3..d32737dd214 100644 --- a/drivers/media/video/tda7432.c +++ b/drivers/media/video/tda7432.c @@ -50,7 +50,6 @@ #include "bttv.h" #include -#include #ifndef VIDEO_AUDIO_BALANCE # define VIDEO_AUDIO_BALANCE 32 diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c index 5a9faefc364..a5e37dc91f3 100644 --- a/drivers/media/video/tda9875.c +++ b/drivers/media/video/tda9875.c @@ -32,7 +32,6 @@ #include "bttv.h" #include -#include static int debug; /* insmod parameter */ module_param(debug, int, S_IRUGO | S_IWUSR); diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 9d6b6f57abc..4249127c0a1 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -11,7 +11,6 @@ #include #include -#include /* Chips: TDA9885 (PAL, NTSC) diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 75901b03073..c31bf28b73f 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -31,7 +31,6 @@ #include #include -#include #include "tvaudio.h" @@ -1438,7 +1437,7 @@ static struct CHIPDESC chiplist[] = { }, { .name = "pic16c54 (PV951)", - .id = I2C_DRIVERID_PIC16C54_PV951, + .id = I2C_DRIVERID_PIC16C54_PV9, .insmodopt = &pic16c54, .addr_lo = I2C_PIC16C54 >> 1, .addr_hi = I2C_PIC16C54>> 1, diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index d83a3361811..72e8741e8b5 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -658,10 +658,6 @@ EXPORT_SYMBOL(tveeprom_read); /* run, just call the exported tveeprom_* directly, there is no point in */ /* using the indirect way via i2c_driver->command() */ -#ifndef I2C_DRIVERID_TVEEPROM -# define I2C_DRIVERID_TVEEPROM I2C_DRIVERID_EXP2 -#endif - static unsigned short normal_i2c[] = { 0xa0 >> 1, I2C_CLIENT_END, diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index 1ce4b54caa2..815675f1e34 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -27,10 +27,10 @@ * ---- Driver types ----------------------------------------------------- * device id name + number function description, i2c address(es) * - * Range 1000-1999 range is defined in sensors/sensors.h - * Range 0x100 - 0x1ff is for V4L2 Common Components + * Range 1000-1999 range is defined in sensors/sensors.h + * Range 0x100 - 0x1ff is for V4L2 Common Components * Range 0xf000 - 0xffff is reserved for local experimentation, and should - * never be used in official drivers + * never be used in official drivers */ #define I2C_DRIVERID_MSP3400 1 @@ -99,6 +99,9 @@ #define I2C_DRIVERID_MAX6900 63 /* MAX6900 real-time clock */ #define I2C_DRIVERID_SAA7114H 64 /* video decoder */ #define I2C_DRIVERID_DS1374 65 /* DS1374 real time clock */ +#define I2C_DRIVERID_TDA9874 66 /* TV sound decoder */ +#define I2C_DRIVERID_SAA6752HS 67 /* MPEG2 encoder */ +#define I2C_DRIVERID_TVEEPROM 68 /* TV EEPROM */ #define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */ @@ -111,7 +114,7 @@ #define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */ #define I2C_DRIVERID_ALERT 903 /* SMBus Alert Responder Client */ -/* IDs -- Use DRIVERIDs 1000-1999 for sensors. +/* IDs -- Use DRIVERIDs 1000-1999 for sensors. These were originally in sensors.h in the lm_sensors package */ #define I2C_DRIVERID_LM78 1002 #define I2C_DRIVERID_LM75 1003 -- cgit v1.2.3 From 3acf28095009509c9ca1e283de821b5be9ddede6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:27 -0800 Subject: [PATCH] v4l: 886: renamed common structures to em28xx - Renamed common structures to em28xx Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-cards.c | 94 ++--- drivers/media/video/em28xx/em28xx-core.c | 274 +++++++------- drivers/media/video/em28xx/em28xx-i2c.c | 128 +++---- drivers/media/video/em28xx/em28xx-input.c | 4 +- drivers/media/video/em28xx/em28xx-video.c | 601 +++++++++++++++--------------- drivers/media/video/em28xx/em28xx.h | 270 +++++++------- 6 files changed, 686 insertions(+), 685 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index ecfc8a3374d..49107fd0c0d 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -34,7 +34,7 @@ #include "em28xx.h" -struct em2820_board em2820_boards[] = { +struct em28xx_board em28xx_boards[] = { [EM2800_BOARD_UNKNOWN] = { .name = "Unknown EM2800 video grabber", .is_em2800 = 1, @@ -42,13 +42,13 @@ struct em2820_board em2820_boards[] = { .norm = VIDEO_MODE_PAL, .tda9887_conf = TDA9887_PRESENT, .has_tuner = 1, - .decoder = EM2820_SAA7113, + .decoder = EM28XX_SAA7113, .input = {{ - .type = EM2820_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, .amux = 1, },{ - .type = EM2820_VMUX_SVIDEO, + .type = EM28XX_VMUX_SVIDEO, .vmux = 9, .amux = 1, }}, @@ -60,13 +60,13 @@ struct em2820_board em2820_boards[] = { .norm = VIDEO_MODE_PAL, .tda9887_conf = TDA9887_PRESENT, .has_tuner = 1, - .decoder = EM2820_SAA7113, + .decoder = EM28XX_SAA7113, .input = {{ - .type = EM2820_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, .amux = 1, },{ - .type = EM2820_VMUX_SVIDEO, + .type = EM28XX_VMUX_SVIDEO, .vmux = 9, .amux = 1, }}, @@ -78,17 +78,17 @@ struct em2820_board em2820_boards[] = { .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, .has_tuner = 1, - .decoder = EM2820_SAA7113, + .decoder = EM28XX_SAA7113, .input = {{ - .type = EM2820_VMUX_TELEVISION, + .type = EM28XX_VMUX_TELEVISION, .vmux = 2, .amux = 0, },{ - .type = EM2820_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, .amux = 1, },{ - .type = EM2820_VMUX_SVIDEO, + .type = EM28XX_VMUX_SVIDEO, .vmux = 9, .amux = 1, }}, @@ -100,17 +100,17 @@ struct em2820_board em2820_boards[] = { .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, .has_tuner = 1, - .decoder = EM2820_SAA7113, + .decoder = EM28XX_SAA7113, .input = {{ - .type = EM2820_VMUX_TELEVISION, + .type = EM28XX_VMUX_TELEVISION, .vmux = 2, .amux = 0, },{ - .type = EM2820_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, .amux = 1, },{ - .type = EM2820_VMUX_SVIDEO, + .type = EM28XX_VMUX_SVIDEO, .vmux = 9, .amux = 1, }}, @@ -122,15 +122,15 @@ struct em2820_board em2820_boards[] = { .tuner_type = TUNER_PHILIPS_FM1236_MK3, .tda9887_conf = TDA9887_PRESENT|TDA9887_PORT1_ACTIVE|TDA9887_PORT2_ACTIVE, .has_tuner = 1, - .decoder = EM2820_TVP5150, + .decoder = EM28XX_TVP5150, .has_msp34xx = 1, /*FIXME: S-Video not tested */ .input = {{ - .type = EM2820_VMUX_TELEVISION, + .type = EM28XX_VMUX_TELEVISION, .vmux = 0, .amux = 0, },{ - .type = EM2820_VMUX_SVIDEO, + .type = EM28XX_VMUX_SVIDEO, .vmux = 2, .amux = 1, }}, @@ -142,17 +142,17 @@ struct em2820_board em2820_boards[] = { .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT|TDA9887_PORT1_ACTIVE|TDA9887_PORT2_ACTIVE, .has_tuner = 1, - .decoder = EM2820_SAA7114, + .decoder = EM28XX_SAA7114, .input = {{ - .type = EM2820_VMUX_TELEVISION, + .type = EM28XX_VMUX_TELEVISION, .vmux = 4, .amux = 0, },{ - .type = EM2820_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, .amux = 1, },{ - .type = EM2820_VMUX_SVIDEO, + .type = EM28XX_VMUX_SVIDEO, .vmux = 9, .amux = 1, }}, @@ -165,17 +165,17 @@ struct em2820_board em2820_boards[] = { .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, .has_tuner = 1, - .decoder = EM2820_SAA7113, + .decoder = EM28XX_SAA7113, .input = {{ - .type = EM2820_VMUX_TELEVISION, + .type = EM28XX_VMUX_TELEVISION, .vmux = 2, .amux = 0, },{ - .type = EM2820_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, .amux = 1, },{ - .type = EM2820_VMUX_SVIDEO, + .type = EM28XX_VMUX_SVIDEO, .vmux = 9, .amux = 1, }}, @@ -188,17 +188,17 @@ struct em2820_board em2820_boards[] = { .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, .has_tuner = 1, - .decoder = EM2820_SAA7113, + .decoder = EM28XX_SAA7113, .input = {{ - .type = EM2820_VMUX_TELEVISION, + .type = EM28XX_VMUX_TELEVISION, .vmux = 2, .amux = 0, },{ - .type = EM2820_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, .amux = 1, },{ - .type = EM2820_VMUX_SVIDEO, + .type = EM28XX_VMUX_SVIDEO, .vmux = 9, .amux = 1, }}, @@ -211,17 +211,17 @@ struct em2820_board em2820_boards[] = { .tuner_type = TUNER_PHILIPS_ATSC, .tda9887_conf = TDA9887_PRESENT, .has_tuner = 1, - .decoder = EM2820_SAA7113, + .decoder = EM28XX_SAA7113, .input = {{ - .type = EM2820_VMUX_TELEVISION, + .type = EM28XX_VMUX_TELEVISION, .vmux = 2, .amux = 0, },{ - .type = EM2820_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, .amux = 1, },{ - .type = EM2820_VMUX_SVIDEO, + .type = EM28XX_VMUX_SVIDEO, .vmux = 9, .amux = 1, }}, @@ -231,22 +231,22 @@ struct em2820_board em2820_boards[] = { .vchannels = 3, .norm = VIDEO_MODE_PAL, .has_tuner = 0, - .decoder = EM2820_SAA7113, + .decoder = EM28XX_SAA7113, .input = {{ - .type = EM2820_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, .amux = 1, },{ - .type = EM2820_VMUX_SVIDEO, + .type = EM28XX_VMUX_SVIDEO, .vmux = 9, .amux = 1, }}, }, }; -const unsigned int em2820_bcount = ARRAY_SIZE(em2820_boards); +const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); /* table of devices that work with this driver */ -struct usb_device_id em2820_id_table [] = { +struct usb_device_id em28xx_id_table [] = { { USB_DEVICE(0xeb1a, 0x2800), .driver_info = EM2800_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2820), .driver_info = EM2820_BOARD_MSI_VOX_USB_2 }, { USB_DEVICE(0x0ccd, 0x0036), .driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 }, @@ -256,7 +256,7 @@ struct usb_device_id em2820_id_table [] = { { }, }; -void em2820_card_setup(struct em2820 *dev) +void em28xx_card_setup(struct em28xx *dev) { /* request some modules */ if (dev->model == EM2820_BOARD_HAUPPAUGE_WINTV_USB_2) { @@ -274,14 +274,14 @@ void em2820_card_setup(struct em2820 *dev) if (tv.audio_processor == AUDIO_CHIP_MSP34XX) { dev->has_msp34xx=1; } else dev->has_msp34xx=0; - em2820_write_regs_req(dev,0x06,0x00,"\x40",1);// Serial Bus Frequency Select Register - em2820_write_regs_req(dev,0x0f,0x00,"\x87",1);// XCLK Frequency Select Register - em2820_write_regs_req(dev,0x88,0x0d,"\xd0",1); + em28xx_write_regs_req(dev,0x06,0x00,"\x40",1);// Serial Bus Frequency Select Register + em28xx_write_regs_req(dev,0x0f,0x00,"\x87",1);// XCLK Frequency Select Register + em28xx_write_regs_req(dev,0x88,0x0d,"\xd0",1); } } -EXPORT_SYMBOL(em2820_boards); -EXPORT_SYMBOL(em2820_bcount); -EXPORT_SYMBOL(em2820_id_table); +EXPORT_SYMBOL(em28xx_boards); +EXPORT_SYMBOL(em28xx_bcount); +EXPORT_SYMBOL(em28xx_id_table); -MODULE_DEVICE_TABLE (usb, em2820_id_table); +MODULE_DEVICE_TABLE (usb, em28xx_id_table); diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index e5aae4fa818..045547e1765 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -1,5 +1,5 @@ /* - em2820-core.c - driver for Empia EM2800/EM2820/2840 USB video capture devices + em28xx-core.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Ludovico Cavedon Markus Rechberger @@ -36,7 +36,7 @@ unsigned int core_debug; module_param(core_debug,int,0644); MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); -#define em2820_coredbg(fmt, arg...) do {\ +#define em28xx_coredbg(fmt, arg...) do {\ if (core_debug) \ printk(KERN_INFO "%s %s :"fmt, \ dev->name, __FUNCTION__ , ##arg); } while (0) @@ -45,7 +45,7 @@ unsigned int reg_debug; module_param(reg_debug,int,0644); MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); -#define em2820_regdbg(fmt, arg...) do {\ +#define em28xx_regdbg(fmt, arg...) do {\ if (reg_debug) \ printk(KERN_INFO "%s %s :"fmt, \ dev->name, __FUNCTION__ , ##arg); } while (0) @@ -54,12 +54,12 @@ unsigned int isoc_debug; module_param(isoc_debug,int,0644); MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]"); -#define em2820_isocdbg(fmt, arg...) do {\ +#define em28xx_isocdbg(fmt, arg...) do {\ if (isoc_debug) \ printk(KERN_INFO "%s %s :"fmt, \ dev->name, __FUNCTION__ , ##arg); } while (0) -static int alt = EM2820_PINOUT; +static int alt = EM28XX_PINOUT; module_param(alt, int, 0644); MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint"); @@ -88,7 +88,7 @@ static const char *v4l2_ioctls[] = { }; #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) -void em2820_print_ioctl(char *name, unsigned int cmd) +void em28xx_print_ioctl(char *name, unsigned int cmd) { char *dir; @@ -159,17 +159,17 @@ static void rvfree(void *mem, size_t size) } /* - * em2820_request_buffers() + * em28xx_request_buffers() * allocate a number of buffers */ -u32 em2820_request_buffers(struct em2820 *dev, u32 count) +u32 em28xx_request_buffers(struct em28xx *dev, u32 count) { const size_t imagesize = PAGE_ALIGN(dev->frame_size); /*needs to be page aligned cause the buffers can be mapped individually! */ void *buff = NULL; u32 i; - em2820_coredbg("requested %i buffers with size %i", count, imagesize); - if (count > EM2820_NUM_FRAMES) - count = EM2820_NUM_FRAMES; + em28xx_coredbg("requested %i buffers with size %i", count, imagesize); + if (count > EM28XX_NUM_FRAMES) + count = EM28XX_NUM_FRAMES; dev->num_frames = count; while (dev->num_frames > 0) { @@ -193,10 +193,10 @@ u32 em2820_request_buffers(struct em2820 *dev, u32 count) } /* - * em2820_queue_unusedframes() + * em28xx_queue_unusedframes() * add all frames that are not currently in use to the inbuffer queue */ -void em2820_queue_unusedframes(struct em2820 *dev) +void em28xx_queue_unusedframes(struct em28xx *dev) { unsigned long lock_flags; u32 i; @@ -211,10 +211,10 @@ void em2820_queue_unusedframes(struct em2820 *dev) } /* - * em2820_release_buffers() + * em28xx_release_buffers() * free frame buffers */ -void em2820_release_buffers(struct em2820 *dev) +void em28xx_release_buffers(struct em28xx *dev) { if (dev->num_frames) { rvfree(dev->frame[0].bufmem, @@ -224,15 +224,15 @@ void em2820_release_buffers(struct em2820 *dev) } /* - * em2820_read_reg_req() + * em28xx_read_reg_req() * reads data from the usb device specifying bRequest */ -int em2820_read_reg_req_len(struct em2820 *dev, u8 req, u16 reg, +int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, char *buf, int len) { int ret, byte; - em2820_regdbg("req=%02x, reg=%02x ", req, reg); + em28xx_regdbg("req=%02x, reg=%02x ", req, reg); ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, @@ -250,15 +250,15 @@ int em2820_read_reg_req_len(struct em2820 *dev, u8 req, u16 reg, } /* - * em2820_read_reg_req() + * em28xx_read_reg_req() * reads data from the usb device specifying bRequest */ -int em2820_read_reg_req(struct em2820 *dev, u8 req, u16 reg) +int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg) { u8 val; int ret; - em2820_regdbg("req=%02x, reg=%02x:", req, reg); + em28xx_regdbg("req=%02x, reg=%02x:", req, reg); ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, @@ -273,16 +273,16 @@ int em2820_read_reg_req(struct em2820 *dev, u8 req, u16 reg) return val; } -int em2820_read_reg(struct em2820 *dev, u16 reg) +int em28xx_read_reg(struct em28xx *dev, u16 reg) { - return em2820_read_reg_req(dev, USB_REQ_GET_STATUS, reg); + return em28xx_read_reg_req(dev, USB_REQ_GET_STATUS, reg); } /* - * em2820_write_regs_req() + * em28xx_write_regs_req() * sends data to the usb device, specifying bRequest */ -int em2820_write_regs_req(struct em2820 *dev, u8 req, u16 reg, char *buf, +int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, int len) { int ret; @@ -290,7 +290,7 @@ int em2820_write_regs_req(struct em2820 *dev, u8 req, u16 reg, char *buf, /*usb_control_msg seems to expect a kmalloced buffer */ unsigned char *bufs = kmalloc(len, GFP_KERNEL); - em2820_regdbg("req=%02x reg=%02x:", req, reg); + em28xx_regdbg("req=%02x reg=%02x:", req, reg); if (reg_debug) { int i; @@ -310,124 +310,124 @@ int em2820_write_regs_req(struct em2820 *dev, u8 req, u16 reg, char *buf, return ret; } -int em2820_write_regs(struct em2820 *dev, u16 reg, char *buf, int len) +int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len) { - return em2820_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len); + return em28xx_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len); } /* - * em2820_write_reg_bits() + * em28xx_write_reg_bits() * sets only some bits (specified by bitmask) of a register, by first reading * the actual value */ -int em2820_write_reg_bits(struct em2820 *dev, u16 reg, u8 val, +int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, u8 bitmask) { int oldval; u8 newval; - if ((oldval = em2820_read_reg(dev, reg)) < 0) + if ((oldval = em28xx_read_reg(dev, reg)) < 0) return oldval; newval = (((u8) oldval) & ~bitmask) | (val & bitmask); - return em2820_write_regs(dev, reg, &newval, 1); + return em28xx_write_regs(dev, reg, &newval, 1); } /* - * em2820_write_ac97() + * em28xx_write_ac97() * write a 16 bit value to the specified AC97 address (LSB first!) */ -int em2820_write_ac97(struct em2820 *dev, u8 reg, u8 * val) +int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 * val) { int ret; u8 addr = reg & 0x7f; - if ((ret = em2820_write_regs(dev, AC97LSB_REG, val, 2)) < 0) + if ((ret = em28xx_write_regs(dev, AC97LSB_REG, val, 2)) < 0) return ret; - if ((ret = em2820_write_regs(dev, AC97ADDR_REG, &addr, 1)) < 0) + if ((ret = em28xx_write_regs(dev, AC97ADDR_REG, &addr, 1)) < 0) return ret; - if ((ret = em2820_read_reg(dev, AC97BUSY_REG)) < 0) + if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0) return ret; else if (((u8) ret) & 0x01) { - em2820_warn ("AC97 command still being exectuted: not handled properly!\n"); + em28xx_warn ("AC97 command still being exectuted: not handled properly!\n"); } return 0; } -int em2820_audio_analog_set(struct em2820 *dev) +int em28xx_audio_analog_set(struct em28xx *dev) { char s[2] = { 0x00, 0x00 }; s[0] |= 0x1f - dev->volume; s[1] |= 0x1f - dev->volume; if (dev->mute) s[1] |= 0x80; - return em2820_write_ac97(dev, MASTER_AC97, s); + return em28xx_write_ac97(dev, MASTER_AC97, s); } -int em2820_colorlevels_set_default(struct em2820 *dev) +int em28xx_colorlevels_set_default(struct em28xx *dev) { - em2820_write_regs(dev, YGAIN_REG, "\x10", 1); /* contrast */ - em2820_write_regs(dev, YOFFSET_REG, "\x00", 1); /* brightness */ - em2820_write_regs(dev, UVGAIN_REG, "\x10", 1); /* saturation */ - em2820_write_regs(dev, UOFFSET_REG, "\x00", 1); - em2820_write_regs(dev, VOFFSET_REG, "\x00", 1); - em2820_write_regs(dev, SHARPNESS_REG, "\x00", 1); - - em2820_write_regs(dev, GAMMA_REG, "\x20", 1); - em2820_write_regs(dev, RGAIN_REG, "\x20", 1); - em2820_write_regs(dev, GGAIN_REG, "\x20", 1); - em2820_write_regs(dev, BGAIN_REG, "\x20", 1); - em2820_write_regs(dev, ROFFSET_REG, "\x00", 1); - em2820_write_regs(dev, GOFFSET_REG, "\x00", 1); - return em2820_write_regs(dev, BOFFSET_REG, "\x00", 1); + em28xx_write_regs(dev, YGAIN_REG, "\x10", 1); /* contrast */ + em28xx_write_regs(dev, YOFFSET_REG, "\x00", 1); /* brightness */ + em28xx_write_regs(dev, UVGAIN_REG, "\x10", 1); /* saturation */ + em28xx_write_regs(dev, UOFFSET_REG, "\x00", 1); + em28xx_write_regs(dev, VOFFSET_REG, "\x00", 1); + em28xx_write_regs(dev, SHARPNESS_REG, "\x00", 1); + + em28xx_write_regs(dev, GAMMA_REG, "\x20", 1); + em28xx_write_regs(dev, RGAIN_REG, "\x20", 1); + em28xx_write_regs(dev, GGAIN_REG, "\x20", 1); + em28xx_write_regs(dev, BGAIN_REG, "\x20", 1); + em28xx_write_regs(dev, ROFFSET_REG, "\x00", 1); + em28xx_write_regs(dev, GOFFSET_REG, "\x00", 1); + return em28xx_write_regs(dev, BOFFSET_REG, "\x00", 1); } -int em2820_capture_start(struct em2820 *dev, int start) +int em28xx_capture_start(struct em28xx *dev, int start) { int ret; /* FIXME: which is the best order? */ /* video registers are sampled by VREF */ - if ((ret = em2820_write_reg_bits(dev, USBSUSP_REG, start ? 0x10 : 0x00, + if ((ret = em28xx_write_reg_bits(dev, USBSUSP_REG, start ? 0x10 : 0x00, 0x10)) < 0) return ret; /* enable video capture */ - return em2820_write_regs(dev, VINENABLE_REG, start ? "\x67" : "\x27", 1); + return em28xx_write_regs(dev, VINENABLE_REG, start ? "\x67" : "\x27", 1); } -int em2820_outfmt_set_yuv422(struct em2820 *dev) +int em28xx_outfmt_set_yuv422(struct em28xx *dev) { - em2820_write_regs(dev, OUTFMT_REG, "\x34", 1); - em2820_write_regs(dev, VINMODE_REG, "\x10", 1); - return em2820_write_regs(dev, VINCTRL_REG, "\x11", 1); + em28xx_write_regs(dev, OUTFMT_REG, "\x34", 1); + em28xx_write_regs(dev, VINMODE_REG, "\x10", 1); + return em28xx_write_regs(dev, VINCTRL_REG, "\x11", 1); } -int em2820_accumulator_set(struct em2820 *dev, u8 xmin, u8 xmax, u8 ymin, +int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, u8 ymin, u8 ymax) { - em2820_coredbg("em2820 Scale: (%d,%d)-(%d,%d)\n", xmin, ymin, xmax, ymax); + em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n", xmin, ymin, xmax, ymax); - em2820_write_regs(dev, XMIN_REG, &xmin, 1); - em2820_write_regs(dev, XMAX_REG, &xmax, 1); - em2820_write_regs(dev, YMIN_REG, &ymin, 1); - return em2820_write_regs(dev, YMAX_REG, &ymax, 1); + em28xx_write_regs(dev, XMIN_REG, &xmin, 1); + em28xx_write_regs(dev, XMAX_REG, &xmax, 1); + em28xx_write_regs(dev, YMIN_REG, &ymin, 1); + return em28xx_write_regs(dev, YMAX_REG, &ymax, 1); } -int em2820_capture_area_set(struct em2820 *dev, u8 hstart, u8 vstart, +int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart, u16 width, u16 height) { u8 cwidth = width; u8 cheight = height; u8 overflow = (height >> 7 & 0x02) | (width >> 8 & 0x01); - em2820_coredbg("em2820 Area Set: (%d,%d)\n", (width | (overflow & 2) << 7), + em28xx_coredbg("em28xx Area Set: (%d,%d)\n", (width | (overflow & 2) << 7), (height | (overflow & 1) << 8)); - em2820_write_regs(dev, HSTART_REG, &hstart, 1); - em2820_write_regs(dev, VSTART_REG, &vstart, 1); - em2820_write_regs(dev, CWIDTH_REG, &cwidth, 1); - em2820_write_regs(dev, CHEIGHT_REG, &cheight, 1); - return em2820_write_regs(dev, OFLOW_REG, &overflow, 1); + em28xx_write_regs(dev, HSTART_REG, &hstart, 1); + em28xx_write_regs(dev, VSTART_REG, &vstart, 1); + em28xx_write_regs(dev, CWIDTH_REG, &cwidth, 1); + em28xx_write_regs(dev, CHEIGHT_REG, &cheight, 1); + return em28xx_write_regs(dev, OFLOW_REG, &overflow, 1); } -int em2820_scaler_set(struct em2820 *dev, u16 h, u16 v) +int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) { u8 mode; /* the em2800 scaler only supports scaling down to 50% */ @@ -437,34 +437,34 @@ int em2820_scaler_set(struct em2820 *dev, u16 h, u16 v) u8 buf[2]; buf[0] = h; buf[1] = h >> 8; - em2820_write_regs(dev, HSCALELOW_REG, (char *)buf, 2); + em28xx_write_regs(dev, HSCALELOW_REG, (char *)buf, 2); buf[0] = v; buf[1] = v >> 8; - em2820_write_regs(dev, VSCALELOW_REG, (char *)buf, 2); + em28xx_write_regs(dev, VSCALELOW_REG, (char *)buf, 2); /* it seems that both H and V scalers must be active to work correctly */ mode = (h || v)? 0x30: 0x00; } - return em2820_write_reg_bits(dev, COMPR_REG, mode, 0x30); + return em28xx_write_reg_bits(dev, COMPR_REG, mode, 0x30); } /* FIXME: this only function read values from dev */ -int em2820_resolution_set(struct em2820 *dev) +int em28xx_resolution_set(struct em28xx *dev) { int width, height; width = norm_maxw(dev); height = norm_maxh(dev) >> 1; - em2820_outfmt_set_yuv422(dev); - em2820_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); - em2820_capture_area_set(dev, 0, 0, width >> 2, height >> 2); - return em2820_scaler_set(dev, dev->hscale, dev->vscale); + em28xx_outfmt_set_yuv422(dev); + em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); + em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2); + return em28xx_scaler_set(dev, dev->hscale, dev->vscale); } /******************* isoc transfer handling ****************************/ #ifdef ENABLE_DEBUG_ISOC_FRAMES -static void em2820_isoc_dump(struct urb *urb, struct pt_regs *regs) +static void em28xx_isoc_dump(struct urb *urb, struct pt_regs *regs) { int len = 0; int ntrans = 0; @@ -503,7 +503,7 @@ static void em2820_isoc_dump(struct urb *urb, struct pt_regs *regs) } #endif -static inline int em2820_isoc_video(struct em2820 *dev,struct em2820_frame_t **f, +static inline int em28xx_isoc_video(struct em28xx *dev,struct em28xx_frame_t **f, unsigned long *lock_flags, unsigned char buf) { if (!(buf & 0x01)) { @@ -511,7 +511,7 @@ static inline int em2820_isoc_video(struct em2820 *dev,struct em2820_frame_t **f /*previous frame is incomplete */ if ((*f)->fieldbytesused < dev->field_size) { (*f)->state = F_ERROR; - em2820_isocdbg ("dropping incomplete bottom field (%i missing bytes)", + em28xx_isocdbg ("dropping incomplete bottom field (%i missing bytes)", dev->field_size-(*f)->fieldbytesused); } else { (*f)->state = F_DONE; @@ -524,13 +524,13 @@ static inline int em2820_isoc_video(struct em2820 *dev,struct em2820_frame_t **f list_move_tail(&(*f)->frame, &dev->outqueue); if (!list_empty(&dev->inqueue)) (*f) = list_entry(dev-> inqueue.next, - struct em2820_frame_t,frame); + struct em28xx_frame_t,frame); else (*f) = NULL; spin_unlock_irqrestore(&dev->queue_lock,*lock_flags); } if (!(*f)) { - em2820_isocdbg ("new frame but no buffer is free"); + em28xx_isocdbg ("new frame but no buffer is free"); return -1; } do_gettimeofday(&(*f)->buf.timestamp); @@ -545,10 +545,10 @@ static inline int em2820_isoc_video(struct em2820 *dev,struct em2820_frame_t **f if ((*f)->state == F_GRABBING) { if (!(*f)->top_field) { (*f)->state = F_ERROR; - em2820_isocdbg ("unexpected begin of bottom field; discarding it"); + em28xx_isocdbg ("unexpected begin of bottom field; discarding it"); } else if ((*f)-> fieldbytesused < dev->field_size - 172) { (*f)->state = F_ERROR; - em2820_isocdbg ("dropping incomplete top field (%i missing bytes)", + em28xx_isocdbg ("dropping incomplete top field (%i missing bytes)", dev->field_size-(*f)->fieldbytesused); } else { (*f)->top_field = 0; @@ -559,14 +559,14 @@ static inline int em2820_isoc_video(struct em2820 *dev,struct em2820_frame_t **f return (0); } -static inline void em2820_isoc_video_copy(struct em2820 *dev, - struct em2820_frame_t **f, unsigned char *buf, int len) +static inline void em28xx_isoc_video_copy(struct em28xx *dev, + struct em28xx_frame_t **f, unsigned char *buf, int len) { void *fieldstart, *startwrite, *startread; int linesdone, currlinedone, offset, lencopy,remain; if(dev->frame_size != (*f)->buf.length){ - em2820_err("frame_size %i and buf.length %i are different!!!\n",dev->frame_size,(*f)->buf.length); + em28xx_err("frame_size %i and buf.length %i are different!!!\n",dev->frame_size,(*f)->buf.length); return; } @@ -574,7 +574,7 @@ static inline void em2820_isoc_video_copy(struct em2820 *dev, len =dev->field_size - (*f)->fieldbytesused; if (buf[0] != 0x88 && buf[0] != 0x22) { - em2820_isocdbg("frame is not complete\n"); + em28xx_isocdbg("frame is not complete\n"); startread = buf; len+=4; } else @@ -613,21 +613,21 @@ static inline void em2820_isoc_video_copy(struct em2820 *dev, } /* - * em2820_isoIrq() + * em28xx_isoIrq() * handles the incoming isoc urbs and fills the frames from our inqueue */ -void em2820_isocIrq(struct urb *urb, struct pt_regs *regs) +void em28xx_isocIrq(struct urb *urb, struct pt_regs *regs) { - struct em2820 *dev = urb->context; + struct em28xx *dev = urb->context; int i, status; - struct em2820_frame_t **f; + struct em28xx_frame_t **f; unsigned long lock_flags; if (!dev) return; #ifdef ENABLE_DEBUG_ISOC_FRAMES if (isoc_debug>1) - em2820_isoc_dump(urb, regs); + em28xx_isoc_dump(urb, regs); #endif if (urb->status == -ENOENT) @@ -639,7 +639,7 @@ void em2820_isocIrq(struct urb *urb, struct pt_regs *regs) dev->stream = STREAM_OFF; if ((*f)) (*f)->state = F_QUEUED; - em2820_isocdbg("stream interrupted"); + em28xx_isocdbg("stream interrupted"); wake_up_interruptible(&dev->wait_stream); } @@ -649,7 +649,7 @@ void em2820_isocIrq(struct urb *urb, struct pt_regs *regs) if (dev->stream == STREAM_ON && !list_empty(&dev->inqueue)) { if (!(*f)) (*f) = list_entry(dev->inqueue.next, - struct em2820_frame_t, frame); + struct em28xx_frame_t, frame); for (i = 0; i < urb->number_of_packets; i++) { unsigned char *buf = urb->transfer_buffer + @@ -657,34 +657,34 @@ void em2820_isocIrq(struct urb *urb, struct pt_regs *regs) int len = urb->iso_frame_desc[i].actual_length - 4; if (urb->iso_frame_desc[i].status) { - em2820_isocdbg("data error: [%d] len=%d, status=%d", i, + em28xx_isocdbg("data error: [%d] len=%d, status=%d", i, urb->iso_frame_desc[i].actual_length, urb->iso_frame_desc[i].status); if (urb->iso_frame_desc[i].status != -EPROTO) continue; } if (urb->iso_frame_desc[i].actual_length <= 0) { - em2820_isocdbg("packet %d is empty",i); + em28xx_isocdbg("packet %d is empty",i); continue; } if (urb->iso_frame_desc[i].actual_length > dev->max_pkt_size) { - em2820_isocdbg("packet bigger than packet size"); + em28xx_isocdbg("packet bigger than packet size"); continue; } /*new frame */ if (buf[0] == 0x22 && buf[1] == 0x5a) { - em2820_isocdbg("Video frame, length=%i!",len); + em28xx_isocdbg("Video frame, length=%i!",len); - if (em2820_isoc_video(dev,f,&lock_flags,buf[2])) + if (em28xx_isoc_video(dev,f,&lock_flags,buf[2])) break; } else if (buf[0]==0x33 && buf[1]==0x95 && buf[2]==0x00) { - em2820_isocdbg("VBI HEADER!!!"); + em28xx_isocdbg("VBI HEADER!!!"); } /* actual copying */ if ((*f)->state == F_GRABBING) { - em2820_isoc_video_copy(dev,f,buf, len); + em28xx_isoc_video_copy(dev,f,buf, len); } } } @@ -696,7 +696,7 @@ void em2820_isocIrq(struct urb *urb, struct pt_regs *regs) urb->status = 0; if ((status = usb_submit_urb(urb, GFP_ATOMIC))) { - em2820_errdev("resubmit of urb failed (error=%i)\n", status); + em28xx_errdev("resubmit of urb failed (error=%i)\n", status); dev->state |= DEV_MISCONFIGURED; } wake_up_interruptible(&dev->wait_frame); @@ -704,58 +704,58 @@ void em2820_isocIrq(struct urb *urb, struct pt_regs *regs) } /* - * em2820_uninit_isoc() - * deallocates the buffers and urbs allocated during em2820_init_iosc() + * em28xx_uninit_isoc() + * deallocates the buffers and urbs allocated during em28xx_init_iosc() */ -void em2820_uninit_isoc(struct em2820 *dev) +void em28xx_uninit_isoc(struct em28xx *dev) { int i; - for (i = 0; i < EM2820_NUM_BUFS; i++) { + for (i = 0; i < EM28XX_NUM_BUFS; i++) { if (dev->urb[i]) { usb_kill_urb(dev->urb[i]); if (dev->transfer_buffer[i]){ - usb_buffer_free(dev->udev,(EM2820_NUM_PACKETS*dev->max_pkt_size),dev->transfer_buffer[i],dev->urb[i]->transfer_dma); + usb_buffer_free(dev->udev,(EM28XX_NUM_PACKETS*dev->max_pkt_size),dev->transfer_buffer[i],dev->urb[i]->transfer_dma); } usb_free_urb(dev->urb[i]); } dev->urb[i] = NULL; dev->transfer_buffer[i] = NULL; } - em2820_capture_start(dev, 0); + em28xx_capture_start(dev, 0); } /* - * em2820_init_isoc() + * em28xx_init_isoc() * allocates transfer buffers and submits the urbs for isoc transfer */ -int em2820_init_isoc(struct em2820 *dev) +int em28xx_init_isoc(struct em28xx *dev) { /* change interface to 3 which allowes the biggest packet sizes */ int i, errCode; - const int sb_size = EM2820_NUM_PACKETS * dev->max_pkt_size; + const int sb_size = EM28XX_NUM_PACKETS * dev->max_pkt_size; /* reset streaming vars */ dev->frame_current = NULL; dev->frame_count = 0; /* allocate urbs */ - for (i = 0; i < EM2820_NUM_BUFS; i++) { + for (i = 0; i < EM28XX_NUM_BUFS; i++) { struct urb *urb; int j, k; /* allocate transfer buffer */ - urb = usb_alloc_urb(EM2820_NUM_PACKETS, GFP_KERNEL); + urb = usb_alloc_urb(EM28XX_NUM_PACKETS, GFP_KERNEL); if (!urb){ - em2820_errdev("cannot alloc urb %i\n", i); - em2820_uninit_isoc(dev); + em28xx_errdev("cannot alloc urb %i\n", i); + em28xx_uninit_isoc(dev); return -ENOMEM; } dev->transfer_buffer[i] = usb_buffer_alloc(dev->udev, sb_size, GFP_KERNEL,&urb->transfer_dma); if (!dev->transfer_buffer[i]) { - em2820_errdev + em28xx_errdev ("unable to allocate %i bytes for transfer buffer %i\n", sb_size, i); - em2820_uninit_isoc(dev); + em28xx_uninit_isoc(dev); return -ENOMEM; } memset(dev->transfer_buffer[i], 0, sb_size); @@ -765,10 +765,10 @@ int em2820_init_isoc(struct em2820 *dev) urb->transfer_flags = URB_ISO_ASAP; urb->interval = 1; urb->transfer_buffer = dev->transfer_buffer[i]; - urb->complete = em2820_isocIrq; - urb->number_of_packets = EM2820_NUM_PACKETS; + urb->complete = em28xx_isocIrq; + urb->number_of_packets = EM28XX_NUM_PACKETS; urb->transfer_buffer_length = sb_size; - for (j = k = 0; j < EM2820_NUM_PACKETS; + for (j = k = 0; j < EM28XX_NUM_PACKETS; j++, k += dev->max_pkt_size) { urb->iso_frame_desc[j].offset = k; urb->iso_frame_desc[j].length = @@ -778,12 +778,12 @@ int em2820_init_isoc(struct em2820 *dev) } /* submit urbs */ - for (i = 0; i < EM2820_NUM_BUFS; i++) { + for (i = 0; i < EM28XX_NUM_BUFS; i++) { errCode = usb_submit_urb(dev->urb[i], GFP_KERNEL); if (errCode) { - em2820_errdev("submit of urb %i failed (error=%i)\n", i, + em28xx_errdev("submit of urb %i failed (error=%i)\n", i, errCode); - em2820_uninit_isoc(dev); + em28xx_uninit_isoc(dev); return errCode; } } @@ -791,21 +791,21 @@ int em2820_init_isoc(struct em2820 *dev) return 0; } -int em2820_set_alternate(struct em2820 *dev) +int em28xx_set_alternate(struct em28xx *dev) { int errCode, prev_alt = dev->alt; dev->alt = alt; if (dev->alt == 0) { int i; if(dev->is_em2800){ /* always use the max packet size for em2800 based devices */ - for(i=0;i< EM2820_MAX_ALT; i++) + for(i=0;i< EM28XX_MAX_ALT; i++) if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->alt]) dev->alt=i; }else{ unsigned int min_pkt_size = dev->field_size / 137; /* FIXME: empiric magic number */ - em2820_coredbg("minimum isoc packet size: %u", min_pkt_size); + em28xx_coredbg("minimum isoc packet size: %u", min_pkt_size); dev->alt = 7; - for (i = 1; i < EM2820_MAX_ALT; i += 2) /* FIXME: skip even alternate: why do they not work? */ + for (i = 1; i < EM28XX_MAX_ALT; i += 2) /* FIXME: skip even alternate: why do they not work? */ if (dev->alt_max_pkt_size[i] >= min_pkt_size) { dev->alt = i; break; @@ -815,11 +815,11 @@ int em2820_set_alternate(struct em2820 *dev) if (dev->alt != prev_alt) { dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt]; - em2820_coredbg("setting alternate %d with wMaxPacketSize=%u", dev->alt, + em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u", dev->alt, dev->max_pkt_size); errCode = usb_set_interface(dev->udev, 0, dev->alt); if (errCode < 0) { - em2820_errdev + em28xx_errdev ("cannot change alternate number to %d (error=%i)\n", dev->alt, errCode); return errCode; diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index a62e66bd65f..b32d9852f34 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -50,7 +50,7 @@ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); * em2800_i2c_send_max4() * send up to 4 bytes to the i2c device */ -static int em2800_i2c_send_max4(struct em2820 *dev, unsigned char addr, +static int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr, char *buf, int len) { int ret; @@ -67,19 +67,19 @@ static int em2800_i2c_send_max4(struct em2820 *dev, unsigned char addr, if (len > 3) b2[0] = buf[3]; - ret = dev->em2820_write_regs(dev, 4 - len, &b2[4 - len], 2 + len); + ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len); if (ret != 2 + len) { - em2820_warn("writting to i2c device failed (error=%i)\n", ret); + em28xx_warn("writting to i2c device failed (error=%i)\n", ret); return -EIO; } for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; write_timeout -= 5) { - ret = dev->em2820_read_reg(dev, 0x05); + ret = dev->em28xx_read_reg(dev, 0x05); if (ret == 0x80 + len - 1) return len; mdelay(5); } - em2820_warn("i2c write timed out\n"); + em28xx_warn("i2c write timed out\n"); return -EIO; } @@ -94,7 +94,7 @@ static int em2800_i2c_send_bytes(void *data, unsigned char addr, char *buf, int wrcount = 0; int count; int maxLen = 4; - struct em2820 *dev = (struct em2820 *)data; + struct em28xx *dev = (struct em28xx *)data; while (len > 0) { count = (len > maxLen) ? maxLen : len; ret = em2800_i2c_send_max4(dev, addr, bufPtr, count); @@ -112,27 +112,27 @@ static int em2800_i2c_send_bytes(void *data, unsigned char addr, char *buf, * em2800_i2c_check_for_device() * check if there is a i2c_device at the supplied address */ -static int em2800_i2c_check_for_device(struct em2820 *dev, unsigned char addr) +static int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr) { char msg; int ret; int write_timeout; msg = addr; - ret = dev->em2820_write_regs(dev, 0x04, &msg, 1); + ret = dev->em28xx_write_regs(dev, 0x04, &msg, 1); if (ret < 0) { - em2820_warn("setting i2c device address failed (error=%i)\n", + em28xx_warn("setting i2c device address failed (error=%i)\n", ret); return ret; } msg = 0x84; - ret = dev->em2820_write_regs(dev, 0x05, &msg, 1); + ret = dev->em28xx_write_regs(dev, 0x05, &msg, 1); if (ret < 0) { - em2820_warn("preparing i2c read failed (error=%i)\n", ret); + em28xx_warn("preparing i2c read failed (error=%i)\n", ret); return ret; } for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; write_timeout -= 5) { - unsigned msg = dev->em2820_read_reg(dev, 0x5); + unsigned msg = dev->em28xx_read_reg(dev, 0x5); if (msg == 0x94) return -ENODEV; else if (msg == 0x84) @@ -146,21 +146,21 @@ static int em2800_i2c_check_for_device(struct em2820 *dev, unsigned char addr) * em2800_i2c_recv_bytes() * read from the i2c device */ -static int em2800_i2c_recv_bytes(struct em2820 *dev, unsigned char addr, +static int em2800_i2c_recv_bytes(struct em28xx *dev, unsigned char addr, char *buf, int len) { int ret; /* check for the device and set i2c read address */ ret = em2800_i2c_check_for_device(dev, addr); if (ret) { - em2820_warn + em28xx_warn ("preparing read at i2c address 0x%x failed (error=%i)\n", addr, ret); return ret; } - ret = dev->em2820_read_reg_req_len(dev, 0x0, 0x3, buf, len); + ret = dev->em28xx_read_reg_req_len(dev, 0x0, 0x3, buf, len); if (ret < 0) { - em2820_warn("reading from i2c device at 0x%x failed (error=%i)", + em28xx_warn("reading from i2c device at 0x%x failed (error=%i)", addr, ret); return ret; } @@ -168,66 +168,66 @@ static int em2800_i2c_recv_bytes(struct em2820 *dev, unsigned char addr, } /* - * em2820_i2c_send_bytes() + * em28xx_i2c_send_bytes() * untested for more than 4 bytes */ -static int em2820_i2c_send_bytes(void *data, unsigned char addr, char *buf, +static int em28xx_i2c_send_bytes(void *data, unsigned char addr, char *buf, short len, int stop) { int wrcount = 0; - struct em2820 *dev = (struct em2820 *)data; + struct em28xx *dev = (struct em28xx *)data; - wrcount = dev->em2820_write_regs_req(dev, stop ? 2 : 3, addr, buf, len); + wrcount = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len); return wrcount; } /* - * em2820_i2c_recv_bytes() + * em28xx_i2c_recv_bytes() * read a byte from the i2c device */ -static int em2820_i2c_recv_bytes(struct em2820 *dev, unsigned char addr, +static int em28xx_i2c_recv_bytes(struct em28xx *dev, unsigned char addr, char *buf, int len) { int ret; - ret = dev->em2820_read_reg_req_len(dev, 2, addr, buf, len); + ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len); if (ret < 0) { - em2820_warn("reading i2c device failed (error=%i)\n", ret); + em28xx_warn("reading i2c device failed (error=%i)\n", ret); return ret; } - if (dev->em2820_read_reg(dev, 0x5) != 0) + if (dev->em28xx_read_reg(dev, 0x5) != 0) return -ENODEV; return ret; } /* - * em2820_i2c_check_for_device() + * em28xx_i2c_check_for_device() * check if there is a i2c_device at the supplied address */ -static int em2820_i2c_check_for_device(struct em2820 *dev, unsigned char addr) +static int em28xx_i2c_check_for_device(struct em28xx *dev, unsigned char addr) { char msg; int ret; msg = addr; - ret = dev->em2820_read_reg_req(dev, 2, addr); + ret = dev->em28xx_read_reg_req(dev, 2, addr); if (ret < 0) { - em2820_warn("reading from i2c device failed (error=%i)\n", ret); + em28xx_warn("reading from i2c device failed (error=%i)\n", ret); return ret; } - if (dev->em2820_read_reg(dev, 0x5) != 0) + if (dev->em28xx_read_reg(dev, 0x5) != 0) return -ENODEV; return 0; } /* - * em2820_i2c_xfer() + * em28xx_i2c_xfer() * the main i2c transfer function */ -static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap, +static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) { - struct em2820 *dev = i2c_adap->algo_data; + struct em28xx *dev = i2c_adap->algo_data; int addr, rc, i, byte; if (num <= 0) @@ -241,7 +241,7 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap, if (dev->is_em2800) rc = em2800_i2c_check_for_device(dev, addr); else - rc = em2820_i2c_check_for_device(dev, addr); + rc = em28xx_i2c_check_for_device(dev, addr); if (rc < 0) { dprintk2(2," no device\n"); return rc; @@ -254,7 +254,7 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap, msgs[i].buf, msgs[i].len); else - rc = em2820_i2c_recv_bytes(dev, addr, + rc = em28xx_i2c_recv_bytes(dev, addr, msgs[i].buf, msgs[i].len); if (i2c_debug>=2) { @@ -273,7 +273,7 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap, msgs[i].buf, msgs[i].len); else - rc = em2820_i2c_send_bytes(dev, addr, + rc = em28xx_i2c_send_bytes(dev, addr, msgs[i].buf, msgs[i].len, i == num - 1); @@ -290,10 +290,10 @@ static int em2820_i2c_xfer(struct i2c_adapter *i2c_adap, return rc; } -static int em2820_i2c_eeprom(struct em2820 *dev, unsigned char *eedata, int len) +static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) { unsigned char buf, *p = eedata; - struct em2820_eeprom *em_eeprom = (void *)eedata; + struct em28xx_eeprom *em_eeprom = (void *)eedata; int i, err, size = len, block; dev->i2c_client.addr = 0xa0 >> 1; @@ -410,9 +410,9 @@ static void dec_use(struct i2c_adapter *adap) } #endif -static int em2820_set_tuner(int check_eeprom, struct i2c_client *client) +static int em28xx_set_tuner(int check_eeprom, struct i2c_client *client) { - struct em2820 *dev = client->adapter->algo_data; + struct em28xx *dev = client->adapter->algo_data; struct tuner_setup tun_setup; if (dev->has_tuner) { @@ -420,7 +420,7 @@ static int em2820_set_tuner(int check_eeprom, struct i2c_client *client) tun_setup.type = dev->tuner_type; tun_setup.addr = dev->tuner_addr; - em2820_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); + em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); } return (0); @@ -433,11 +433,11 @@ static int em2820_set_tuner(int check_eeprom, struct i2c_client *client) */ static int attach_inform(struct i2c_client *client) { - struct em2820 *dev = client->adapter->algo_data; + struct em28xx *dev = client->adapter->algo_data; switch (client->addr << 1) { case 0x86: - em2820_i2c_call_clients(dev, TDA9887_SET_CONFIG, &dev->tda9887_conf); + em28xx_i2c_call_clients(dev, TDA9887_SET_CONFIG, &dev->tda9887_conf); break; case 0x42: dprintk1(1,"attach_inform: saa7114 detected.\n"); @@ -453,7 +453,7 @@ static int attach_inform(struct i2c_client *client) { struct IR_i2c *ir = i2c_get_clientdata(client); dprintk1(1,"attach_inform: IR detected (%s).\n",ir->phys); - em2820_set_ir(dev,ir); + em28xx_set_ir(dev,ir); break; } case 0x80: @@ -467,19 +467,19 @@ static int attach_inform(struct i2c_client *client) default: dprintk1(1,"attach inform: detected I2C address %x\n", client->addr << 1); dev->tuner_addr = client->addr; - em2820_set_tuner(-1, client); + em28xx_set_tuner(-1, client); } return 0; } -static struct i2c_algorithm em2820_algo = { - .master_xfer = em2820_i2c_xfer, +static struct i2c_algorithm em28xx_algo = { + .master_xfer = em28xx_i2c_xfer, .algo_control = algo_control, .functionality = functionality, }; -static struct i2c_adapter em2820_adap_template = { +static struct i2c_adapter em28xx_adap_template = { #ifdef I2C_PEC .owner = THIS_MODULE, #else @@ -489,14 +489,14 @@ static struct i2c_adapter em2820_adap_template = { #ifdef I2C_CLASS_TV_ANALOG .class = I2C_CLASS_TV_ANALOG, #endif - .name = "em2820", - .id = I2C_HW_B_EM2820, - .algo = &em2820_algo, + .name = "em28xx", + .id = I2C_HW_B_EM28XX, + .algo = &em28xx_algo, .client_register = attach_inform, }; -static struct i2c_client em2820_client_template = { - .name = "em2820 internal", +static struct i2c_client em28xx_client_template = { + .name = "em28xx internal", .flags = I2C_CLIENT_ALLOW_USE, }; @@ -542,33 +542,33 @@ static void do_i2c_scan(char *name, struct i2c_client *c) } /* - * em2820_i2c_call_clients() + * em28xx_i2c_call_clients() * send commands to all attached i2c devices */ -void em2820_i2c_call_clients(struct em2820 *dev, unsigned int cmd, void *arg) +void em28xx_i2c_call_clients(struct em28xx *dev, unsigned int cmd, void *arg) { BUG_ON(NULL == dev->i2c_adap.algo_data); i2c_clients_command(&dev->i2c_adap, cmd, arg); } /* - * em2820_i2c_register() + * em28xx_i2c_register() * register i2c bus */ -int em2820_i2c_register(struct em2820 *dev) +int em28xx_i2c_register(struct em28xx *dev) { - BUG_ON(!dev->em2820_write_regs || !dev->em2820_read_reg); - BUG_ON(!dev->em2820_write_regs_req || !dev->em2820_read_reg_req); - dev->i2c_adap = em2820_adap_template; + BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg); + BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req); + dev->i2c_adap = em28xx_adap_template; dev->i2c_adap.dev.parent = &dev->udev->dev; strcpy(dev->i2c_adap.name, dev->name); dev->i2c_adap.algo_data = dev; i2c_add_adapter(&dev->i2c_adap); - dev->i2c_client = em2820_client_template; + dev->i2c_client = em28xx_client_template; dev->i2c_client.adapter = &dev->i2c_adap; - em2820_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata)); + em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata)); if (i2c_scan) do_i2c_scan(dev->name, &dev->i2c_client); @@ -576,10 +576,10 @@ int em2820_i2c_register(struct em2820 *dev) } /* - * em2820_i2c_unregister() + * em28xx_i2c_unregister() * unregister i2c_bus */ -int em2820_i2c_unregister(struct em2820 *dev) +int em28xx_i2c_unregister(struct em28xx *dev) { i2c_del_adapter(&dev->i2c_adap); return 0; diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index be7ba9b24d0..32c49df58ad 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -142,7 +142,7 @@ static int get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) } /* ----------------------------------------------------------------------- */ -void em2820_set_ir(struct em2820 * dev,struct IR_i2c *ir) +void em28xx_set_ir(struct em28xx * dev,struct IR_i2c *ir) { if (disable_ir) { ir->get_key=NULL; @@ -159,7 +159,7 @@ void em2820_set_ir(struct em2820 * dev,struct IR_i2c *ir) case (EM2820_BOARD_TERRATEC_CINERGY_250): ir->ir_codes = ir_codes_em_terratec; ir->get_key = get_key_terratec; - snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM2820 Terratec)"); + snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Terratec)"); break; case (EM2820_BOARD_PINNACLE_USB_2): break; diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 5ae896a1dcf..f6acce82079 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "em28xx.h" #include @@ -39,9 +40,9 @@ #define DRIVER_NAME "em28xx" #define DRIVER_DESC "Empia em28xx based USB video device driver" -#define EM2820_VERSION_CODE KERNEL_VERSION(0, 0, 1) +#define EM28XX_VERSION_CODE KERNEL_VERSION(0, 0, 1) -#define em2820_videodbg(fmt, arg...) do {\ +#define em28xx_videodbg(fmt, arg...) do {\ if (video_debug) \ printk(KERN_INFO "%s %s :"fmt, \ dev->name, __FUNCTION__ , ##arg); } while (0) @@ -50,9 +51,9 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -static LIST_HEAD(em2820_devlist); +static LIST_HEAD(em28xx_devlist); -static unsigned int card[] = {[0 ... (EM2820_MAXBOARDS - 1)] = UNSET }; +static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; module_param_array(card, int, NULL, 0444); MODULE_PARM_DESC(card,"card type"); @@ -66,7 +67,7 @@ module_param(video_debug,int,0644); MODULE_PARM_DESC(video_debug,"enable debug messages [video]"); /* supported tv norms */ -static struct em2820_tvnorm tvnorms[] = { +static struct em28xx_tvnorm tvnorms[] = { { .name = "PAL", .id = V4L2_STD_PAL, @@ -106,7 +107,7 @@ static const unsigned char saa7114_i2c_init[] = { #define TVNORMS ARRAY_SIZE(tvnorms) /* supported controls */ -static struct v4l2_queryctrl em2820_qctrl[] = { +static struct v4l2_queryctrl em28xx_qctrl[] = { { .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, @@ -182,10 +183,10 @@ static struct v4l2_queryctrl em2820_qctrl[] = { } }; -static struct usb_driver em2820_usb_driver; +static struct usb_driver em28xx_usb_driver; -static DECLARE_MUTEX(em2820_sysfs_lock); -static DECLARE_RWSEM(em2820_disconnect); +static DECLARE_MUTEX(em28xx_sysfs_lock); +static DECLARE_RWSEM(em28xx_disconnect); /********************* v4l2 interface ******************************************/ @@ -200,95 +201,95 @@ static inline unsigned long kvirt_to_pa(unsigned long adr) } /* - * em2820_config() + * em28xx_config() * inits registers with sane defaults */ -static int em2820_config(struct em2820 *dev) +static int em28xx_config(struct em28xx *dev) { /* Sets I2C speed to 100 KHz */ - em2820_write_regs_req(dev, 0x00, 0x06, "\x40", 1); + em28xx_write_regs_req(dev, 0x00, 0x06, "\x40", 1); /* enable vbi capturing */ - em2820_audio_usb_mute(dev, 1); + em28xx_audio_usb_mute(dev, 1); dev->mute = 1; /* maybe not the right place... */ dev->volume = 0x1f; - em2820_audio_analog_set(dev); - em2820_audio_analog_setup(dev); - em2820_outfmt_set_yuv422(dev); - em2820_colorlevels_set_default(dev); - em2820_compression_disable(dev); + em28xx_audio_analog_set(dev); + em28xx_audio_analog_setup(dev); + em28xx_outfmt_set_yuv422(dev); + em28xx_colorlevels_set_default(dev); + em28xx_compression_disable(dev); return 0; } /* - * em2820_config_i2c() + * em28xx_config_i2c() * configure i2c attached devices */ -void em2820_config_i2c(struct em2820 *dev) +void em28xx_config_i2c(struct em28xx *dev) { struct v4l2_frequency f; - struct video_decoder_init em2820_vdi = {.data = NULL }; + struct video_decoder_init em28xx_vdi = {.data = NULL }; /* configure decoder */ if(dev->model == EM2820_BOARD_MSI_VOX_USB_2){ - em2820_vdi.data=saa7114_i2c_init; - em2820_vdi.len=sizeof(saa7114_i2c_init); + em28xx_vdi.data=saa7114_i2c_init; + em28xx_vdi.len=sizeof(saa7114_i2c_init); } - em2820_i2c_call_clients(dev, DECODER_INIT, &em2820_vdi); - em2820_i2c_call_clients(dev, DECODER_SET_INPUT, &dev->ctl_input); -/* em2820_i2c_call_clients(dev,DECODER_SET_PICTURE, &dev->vpic); */ -/* em2820_i2c_call_clients(dev,DECODER_SET_NORM,&dev->tvnorm->id); */ -/* em2820_i2c_call_clients(dev,DECODER_ENABLE_OUTPUT,&output); */ -/* em2820_i2c_call_clients(dev,DECODER_DUMP, NULL); */ + em28xx_i2c_call_clients(dev, DECODER_INIT, &em28xx_vdi); + em28xx_i2c_call_clients(dev, DECODER_SET_INPUT, &dev->ctl_input); +/* em28xx_i2c_call_clients(dev,DECODER_SET_PICTURE, &dev->vpic); */ +/* em28xx_i2c_call_clients(dev,DECODER_SET_NORM,&dev->tvnorm->id); */ +/* em28xx_i2c_call_clients(dev,DECODER_ENABLE_OUTPUT,&output); */ +/* em28xx_i2c_call_clients(dev,DECODER_DUMP, NULL); */ /* configure tuner */ f.tuner = 0; f.type = V4L2_TUNER_ANALOG_TV; f.frequency = 9076; /* FIXME:remove magic number */ dev->ctl_freq = f.frequency; - em2820_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f); + em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f); /* configure tda9887 */ -/* em2820_i2c_call_clients(dev,VIDIOC_S_STD,&dev->tvnorm->id); */ +/* em28xx_i2c_call_clients(dev,VIDIOC_S_STD,&dev->tvnorm->id); */ } /* - * em2820_empty_framequeues() + * em28xx_empty_framequeues() * prepare queues for incoming and outgoing frames */ -static void em2820_empty_framequeues(struct em2820 *dev) +static void em28xx_empty_framequeues(struct em28xx *dev) { u32 i; INIT_LIST_HEAD(&dev->inqueue); INIT_LIST_HEAD(&dev->outqueue); - for (i = 0; i < EM2820_NUM_FRAMES; i++) { + for (i = 0; i < EM28XX_NUM_FRAMES; i++) { dev->frame[i].state = F_UNUSED; dev->frame[i].buf.bytesused = 0; } } /* - * em2820_v4l2_open() + * em28xx_v4l2_open() * inits the device and starts isoc transfer */ -static int em2820_v4l2_open(struct inode *inode, struct file *filp) +static int em28xx_v4l2_open(struct inode *inode, struct file *filp) { int minor = iminor(inode); int errCode = 0; - struct em2820 *h,*dev = NULL; + struct em28xx *h,*dev = NULL; struct list_head *list; - list_for_each(list,&em2820_devlist) { - h = list_entry(list, struct em2820, devlist); + list_for_each(list,&em28xx_devlist) { + h = list_entry(list, struct em28xx, devlist); if (h->vdev->minor == minor) { dev = h; } @@ -297,14 +298,14 @@ static int em2820_v4l2_open(struct inode *inode, struct file *filp) filp->private_data=dev; - em2820_videodbg("users=%d", dev->users); + em28xx_videodbg("users=%d", dev->users); - if (!down_read_trylock(&em2820_disconnect)) + if (!down_read_trylock(&em28xx_disconnect)) return -ERESTARTSYS; if (dev->users) { - em2820_warn("this driver can be opened only once\n"); - up_read(&em2820_disconnect); + em28xx_warn("this driver can be opened only once\n"); + up_read(&em28xx_disconnect); return -EBUSY; } @@ -322,7 +323,7 @@ static int em2820_v4l2_open(struct inode *inode, struct file *filp) down(&dev->lock); - em2820_set_alternate(dev); + em28xx_set_alternate(dev); dev->width = norm_maxw(dev); dev->height = norm_maxh(dev); @@ -332,11 +333,11 @@ static int em2820_v4l2_open(struct inode *inode, struct file *filp) dev->hscale = 0; dev->vscale = 0; - em2820_capture_start(dev, 1); - em2820_resolution_set(dev); + em28xx_capture_start(dev, 1); + em28xx_resolution_set(dev); /* start the transfer */ - errCode = em2820_init_isoc(dev); + errCode = em28xx_init_isoc(dev); if (errCode) goto err; @@ -347,55 +348,55 @@ static int em2820_v4l2_open(struct inode *inode, struct file *filp) dev->num_frames = 0; /* prepare queues */ - em2820_empty_framequeues(dev); + em28xx_empty_framequeues(dev); dev->state |= DEV_INITIALIZED; err: up(&dev->lock); - up_read(&em2820_disconnect); + up_read(&em28xx_disconnect); return errCode; } /* - * em2820_realease_resources() + * em28xx_realease_resources() * unregisters the v4l2,i2c and usb devices * called when the device gets disconected or at module unload */ -static void em2820_release_resources(struct em2820 *dev) +static void em28xx_release_resources(struct em28xx *dev) { - down(&em2820_sysfs_lock); + down(&em28xx_sysfs_lock); - em2820_info("V4L2 device /dev/video%d deregistered\n", + em28xx_info("V4L2 device /dev/video%d deregistered\n", dev->vdev->minor); list_del(&dev->devlist); video_unregister_device(dev->vdev); /* video_unregister_device(dev->vbi_dev); */ - em2820_i2c_unregister(dev); + em28xx_i2c_unregister(dev); usb_put_dev(dev->udev); - up(&em2820_sysfs_lock); + up(&em28xx_sysfs_lock); } /* - * em2820_v4l2_close() + * em28xx_v4l2_close() * stops streaming and deallocates all resources allocated by the v4l2 calls and ioctls */ -static int em2820_v4l2_close(struct inode *inode, struct file *filp) +static int em28xx_v4l2_close(struct inode *inode, struct file *filp) { int errCode; - struct em2820 *dev=filp->private_data; + struct em28xx *dev=filp->private_data; - em2820_videodbg("users=%d", dev->users); + em28xx_videodbg("users=%d", dev->users); down(&dev->lock); - em2820_uninit_isoc(dev); + em28xx_uninit_isoc(dev); - em2820_release_buffers(dev); + em28xx_release_buffers(dev); /* the device is already disconnect, free the remaining resources */ if (dev->state & DEV_DISCONNECTED) { - em2820_release_resources(dev); + em28xx_release_resources(dev); up(&dev->lock); kfree(dev); return 0; @@ -403,10 +404,10 @@ static int em2820_v4l2_close(struct inode *inode, struct file *filp) /* set alternate 0 */ dev->alt = 0; - em2820_videodbg("setting alternate 0"); + em28xx_videodbg("setting alternate 0"); errCode = usb_set_interface(dev->udev, 0, 0); if (errCode < 0) { - em2820_errdev ("cannot change alternate number to 0 (error=%i)\n", + em28xx_errdev ("cannot change alternate number to 0 (error=%i)\n", errCode); } @@ -417,49 +418,49 @@ static int em2820_v4l2_close(struct inode *inode, struct file *filp) } /* - * em2820_v4l2_read() + * em28xx_v4l2_read() * will allocate buffers when called for the first time */ static ssize_t -em2820_v4l2_read(struct file *filp, char __user * buf, size_t count, +em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count, loff_t * f_pos) { - struct em2820_frame_t *f, *i; + struct em28xx_frame_t *f, *i; unsigned long lock_flags; int ret = 0; - struct em2820 *dev = filp->private_data; + struct em28xx *dev = filp->private_data; if (down_interruptible(&dev->fileop_lock)) return -ERESTARTSYS; if (dev->state & DEV_DISCONNECTED) { - em2820_videodbg("device not present"); + em28xx_videodbg("device not present"); up(&dev->fileop_lock); return -ENODEV; } if (dev->state & DEV_MISCONFIGURED) { - em2820_videodbg("device misconfigured; close and open it again"); + em28xx_videodbg("device misconfigured; close and open it again"); up(&dev->fileop_lock); return -EIO; } if (dev->io == IO_MMAP) { - em2820_videodbg ("IO method is set to mmap; close and open" + em28xx_videodbg ("IO method is set to mmap; close and open" " the device again to choose the read method"); up(&dev->fileop_lock); return -EINVAL; } if (dev->io == IO_NONE) { - if (!em2820_request_buffers(dev, EM2820_NUM_READ_FRAMES)) { - em2820_errdev("read failed, not enough memory\n"); + if (!em28xx_request_buffers(dev, EM28XX_NUM_READ_FRAMES)) { + em28xx_errdev("read failed, not enough memory\n"); up(&dev->fileop_lock); return -ENOMEM; } dev->io = IO_READ; dev->stream = STREAM_ON; - em2820_queue_unusedframes(dev); + em28xx_queue_unusedframes(dev); } if (!count) { @@ -486,7 +487,7 @@ em2820_v4l2_read(struct file *filp, char __user * buf, size_t count, } } - f = list_entry(dev->outqueue.prev, struct em2820_frame_t, frame); + f = list_entry(dev->outqueue.prev, struct em28xx_frame_t, frame); spin_lock_irqsave(&dev->queue_lock, lock_flags); list_for_each_entry(i, &dev->outqueue, frame) @@ -494,7 +495,7 @@ em2820_v4l2_read(struct file *filp, char __user * buf, size_t count, INIT_LIST_HEAD(&dev->outqueue); spin_unlock_irqrestore(&dev->queue_lock, lock_flags); - em2820_queue_unusedframes(dev); + em28xx_queue_unusedframes(dev); if (count > f->buf.length) count = f->buf.length; @@ -511,26 +512,26 @@ em2820_v4l2_read(struct file *filp, char __user * buf, size_t count, } /* - * em2820_v4l2_poll() + * em28xx_v4l2_poll() * will allocate buffers when called for the first time */ -static unsigned int em2820_v4l2_poll(struct file *filp, poll_table * wait) +static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait) { unsigned int mask = 0; - struct em2820 *dev = filp->private_data; + struct em28xx *dev = filp->private_data; if (down_interruptible(&dev->fileop_lock)) return POLLERR; if (dev->state & DEV_DISCONNECTED) { - em2820_videodbg("device not present"); + em28xx_videodbg("device not present"); } else if (dev->state & DEV_MISCONFIGURED) { - em2820_videodbg("device is misconfigured; close and open it again"); + em28xx_videodbg("device is misconfigured; close and open it again"); } else { if (dev->io == IO_NONE) { - if (!em2820_request_buffers - (dev, EM2820_NUM_READ_FRAMES)) { - em2820_warn + if (!em28xx_request_buffers + (dev, EM28XX_NUM_READ_FRAMES)) { + em28xx_warn ("poll() failed, not enough memory\n"); } else { dev->io = IO_READ; @@ -539,7 +540,7 @@ static unsigned int em2820_v4l2_poll(struct file *filp, poll_table * wait) } if (dev->io == IO_READ) { - em2820_queue_unusedframes(dev); + em28xx_queue_unusedframes(dev); poll_wait(filp, &dev->wait_frame, wait); if (!list_empty(&dev->outqueue)) @@ -556,51 +557,51 @@ static unsigned int em2820_v4l2_poll(struct file *filp, poll_table * wait) } /* - * em2820_vm_open() + * em28xx_vm_open() */ -static void em2820_vm_open(struct vm_area_struct *vma) +static void em28xx_vm_open(struct vm_area_struct *vma) { - struct em2820_frame_t *f = vma->vm_private_data; + struct em28xx_frame_t *f = vma->vm_private_data; f->vma_use_count++; } /* - * em2820_vm_close() + * em28xx_vm_close() */ -static void em2820_vm_close(struct vm_area_struct *vma) +static void em28xx_vm_close(struct vm_area_struct *vma) { /* NOTE: buffers are not freed here */ - struct em2820_frame_t *f = vma->vm_private_data; + struct em28xx_frame_t *f = vma->vm_private_data; f->vma_use_count--; } -static struct vm_operations_struct em2820_vm_ops = { - .open = em2820_vm_open, - .close = em2820_vm_close, +static struct vm_operations_struct em28xx_vm_ops = { + .open = em28xx_vm_open, + .close = em28xx_vm_close, }; /* - * em2820_v4l2_mmap() + * em28xx_v4l2_mmap() */ -static int em2820_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) +static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) { unsigned long size = vma->vm_end - vma->vm_start, start = vma->vm_start, pos, page; u32 i; - struct em2820 *dev = filp->private_data; + struct em28xx *dev = filp->private_data; if (down_interruptible(&dev->fileop_lock)) return -ERESTARTSYS; if (dev->state & DEV_DISCONNECTED) { - em2820_videodbg("mmap: device not present"); + em28xx_videodbg("mmap: device not present"); up(&dev->fileop_lock); return -ENODEV; } if (dev->state & DEV_MISCONFIGURED) { - em2820_videodbg ("mmap: Device is misconfigured; close and " + em28xx_videodbg ("mmap: Device is misconfigured; close and " "open it again"); up(&dev->fileop_lock); return -EIO; @@ -617,7 +618,7 @@ static int em2820_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) break; } if (i == dev->num_frames) { - em2820_videodbg("mmap: user supplied mapping address is out of range"); + em28xx_videodbg("mmap: user supplied mapping address is out of range"); up(&dev->fileop_lock); return -EINVAL; } @@ -631,7 +632,7 @@ static int em2820_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) page = vmalloc_to_pfn((void *)pos); if (remap_pfn_range(vma, start, page, PAGE_SIZE, vma->vm_page_prot)) { - em2820_videodbg("mmap: rename page map failed"); + em28xx_videodbg("mmap: rename page map failed"); up(&dev->fileop_lock); return -EAGAIN; } @@ -640,19 +641,19 @@ static int em2820_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) size -= PAGE_SIZE; } - vma->vm_ops = &em2820_vm_ops; + vma->vm_ops = &em28xx_vm_ops; vma->vm_private_data = &dev->frame[i]; - em2820_vm_open(vma); + em28xx_vm_open(vma); up(&dev->fileop_lock); return 0; } /* - * em2820_get_ctrl() + * em28xx_get_ctrl() * return the current saturation, brightness or contrast, mute state */ -static int em2820_get_ctrl(struct em2820 *dev, struct v4l2_control *ctrl) +static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) { s32 tmp; switch (ctrl->id) { @@ -663,30 +664,30 @@ static int em2820_get_ctrl(struct em2820 *dev, struct v4l2_control *ctrl) ctrl->value = dev->volume; return 0; case V4L2_CID_BRIGHTNESS: - if ((tmp = em2820_brightness_get(dev)) < 0) + if ((tmp = em28xx_brightness_get(dev)) < 0) return -EIO; ctrl->value = (s32) ((s8) tmp); /* FIXME: clenaer way to extend sign? */ return 0; case V4L2_CID_CONTRAST: - if ((ctrl->value = em2820_contrast_get(dev)) < 0) + if ((ctrl->value = em28xx_contrast_get(dev)) < 0) return -EIO; return 0; case V4L2_CID_SATURATION: - if ((ctrl->value = em2820_saturation_get(dev)) < 0) + if ((ctrl->value = em28xx_saturation_get(dev)) < 0) return -EIO; return 0; case V4L2_CID_RED_BALANCE: - if ((tmp = em2820_v_balance_get(dev)) < 0) + if ((tmp = em28xx_v_balance_get(dev)) < 0) return -EIO; ctrl->value = (s32) ((s8) tmp); /* FIXME: clenaer way to extend sign? */ return 0; case V4L2_CID_BLUE_BALANCE: - if ((tmp = em2820_u_balance_get(dev)) < 0) + if ((tmp = em28xx_u_balance_get(dev)) < 0) return -EIO; ctrl->value = (s32) ((s8) tmp); /* FIXME: clenaer way to extend sign? */ return 0; case V4L2_CID_GAMMA: - if ((ctrl->value = em2820_gamma_get(dev)) < 0) + if ((ctrl->value = em28xx_gamma_get(dev)) < 0) return -EIO; return 0; default: @@ -695,44 +696,44 @@ static int em2820_get_ctrl(struct em2820 *dev, struct v4l2_control *ctrl) } /* - * em2820_set_ctrl() + * em28xx_set_ctrl() * mute or set new saturation, brightness or contrast */ -static int em2820_set_ctrl(struct em2820 *dev, const struct v4l2_control *ctrl) +static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl) { switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: if (ctrl->value != dev->mute) { dev->mute = ctrl->value; - em2820_audio_usb_mute(dev, ctrl->value); - return em2820_audio_analog_set(dev); + em28xx_audio_usb_mute(dev, ctrl->value); + return em28xx_audio_analog_set(dev); } return 0; case V4L2_CID_AUDIO_VOLUME: dev->volume = ctrl->value; - return em2820_audio_analog_set(dev); + return em28xx_audio_analog_set(dev); case V4L2_CID_BRIGHTNESS: - return em2820_brightness_set(dev, ctrl->value); + return em28xx_brightness_set(dev, ctrl->value); case V4L2_CID_CONTRAST: - return em2820_contrast_set(dev, ctrl->value); + return em28xx_contrast_set(dev, ctrl->value); case V4L2_CID_SATURATION: - return em2820_saturation_set(dev, ctrl->value); + return em28xx_saturation_set(dev, ctrl->value); case V4L2_CID_RED_BALANCE: - return em2820_v_balance_set(dev, ctrl->value); + return em28xx_v_balance_set(dev, ctrl->value); case V4L2_CID_BLUE_BALANCE: - return em2820_u_balance_set(dev, ctrl->value); + return em28xx_u_balance_set(dev, ctrl->value); case V4L2_CID_GAMMA: - return em2820_gamma_set(dev, ctrl->value); + return em28xx_gamma_set(dev, ctrl->value); default: return -EINVAL; } } /* - * em2820_stream_interrupt() + * em28xx_stream_interrupt() * stops streaming */ -static int em2820_stream_interrupt(struct em2820 *dev) +static int em28xx_stream_interrupt(struct em28xx *dev) { int ret = 0; @@ -742,12 +743,12 @@ static int em2820_stream_interrupt(struct em2820 *dev) ret = wait_event_timeout(dev->wait_stream, (dev->stream == STREAM_OFF) || (dev->state & DEV_DISCONNECTED), - EM2820_URB_TIMEOUT); + EM28XX_URB_TIMEOUT); if (dev->state & DEV_DISCONNECTED) return -ENODEV; else if (ret) { dev->state |= DEV_MISCONFIGURED; - em2820_videodbg("device is misconfigured; close and " + em28xx_videodbg("device is misconfigured; close and " "open /dev/video%d again", dev->vdev->minor); return ret; } @@ -755,7 +756,7 @@ static int em2820_stream_interrupt(struct em2820 *dev) return 0; } -static int em2820_set_norm(struct em2820 *dev, int width, int height) +static int em28xx_set_norm(struct em28xx *dev, int width, int height) { unsigned int hscale, vscale; unsigned int maxh, maxw; @@ -794,41 +795,41 @@ static int em2820_set_norm(struct em2820 *dev, int width, int height) dev->hscale = hscale; dev->vscale = vscale; - em2820_resolution_set(dev); + em28xx_resolution_set(dev); return 0; } -static void video_mux(struct em2820 *dev, int index) +static void video_mux(struct em28xx *dev, int index) { int input, ainput; input = INPUT(index)->vmux; dev->ctl_input = index; - em2820_i2c_call_clients(dev, DECODER_SET_INPUT, &input); + em28xx_i2c_call_clients(dev, DECODER_SET_INPUT, &input); dev->ctl_ainput = INPUT(index)->amux; switch (dev->ctl_ainput) { case 0: - ainput = EM2820_AUDIO_SRC_TUNER; + ainput = EM28XX_AUDIO_SRC_TUNER; break; default: - ainput = EM2820_AUDIO_SRC_LINE; + ainput = EM28XX_AUDIO_SRC_LINE; } - em2820_audio_source(dev, ainput); + em28xx_audio_source(dev, ainput); } /* - * em2820_v4l2_do_ioctl() + * em28xx_v4l2_do_ioctl() * This function is _not_ called directly, but from - * em2820_v4l2_ioctl. Userspace + * em28xx_v4l2_ioctl. Userspace * copying is done already, arg is a kernel pointer. */ -static int em2820_do_ioctl(struct inode *inode, struct file *filp, - struct em2820 *dev, unsigned int cmd, void *arg, +static int em28xx_do_ioctl(struct inode *inode, struct file *filp, + struct em28xx *dev, unsigned int cmd, void *arg, v4l2_kioctl driver_ioctl) { int ret; @@ -875,7 +876,7 @@ static int em2820_do_ioctl(struct inode *inode, struct file *filp, down(&dev->lock); dev->tvnorm = &tvnorms[i]; - em2820_set_norm(dev, dev->width, dev->height); + em28xx_set_norm(dev, dev->width, dev->height); /* dev->width=norm_maxw(dev); @@ -886,18 +887,18 @@ static int em2820_do_ioctl(struct inode *inode, struct file *filp, dev->hscale=0; dev->vscale=0; - em2820_resolution_set(dev); + em28xx_resolution_set(dev); */ /* - em2820_uninit_isoc(dev); - em2820_set_alternate(dev); - em2820_capture_start(dev, 1); - em2820_resolution_set(dev); - em2820_init_isoc(dev); + em28xx_uninit_isoc(dev); + em28xx_set_alternate(dev); + em28xx_capture_start(dev, 1); + em28xx_resolution_set(dev); + em28xx_init_isoc(dev); */ - em2820_i2c_call_clients(dev, DECODER_SET_NORM, + em28xx_i2c_call_clients(dev, DECODER_SET_NORM, &tvnorms[i].mode); - em2820_i2c_call_clients(dev, VIDIOC_S_STD, + em28xx_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id); up(&dev->lock); @@ -911,19 +912,19 @@ static int em2820_do_ioctl(struct inode *inode, struct file *filp, struct v4l2_input *i = arg; unsigned int n; static const char *iname[] = { - [EM2820_VMUX_COMPOSITE1] = "Composite1", - [EM2820_VMUX_COMPOSITE2] = "Composite2", - [EM2820_VMUX_COMPOSITE3] = "Composite3", - [EM2820_VMUX_COMPOSITE4] = "Composite4", - [EM2820_VMUX_SVIDEO] = "S-Video", - [EM2820_VMUX_TELEVISION] = "Television", - [EM2820_VMUX_CABLE] = "Cable TV", - [EM2820_VMUX_DVB] = "DVB", - [EM2820_VMUX_DEBUG] = "for debug only", + [EM28XX_VMUX_COMPOSITE1] = "Composite1", + [EM28XX_VMUX_COMPOSITE2] = "Composite2", + [EM28XX_VMUX_COMPOSITE3] = "Composite3", + [EM28XX_VMUX_COMPOSITE4] = "Composite4", + [EM28XX_VMUX_SVIDEO] = "S-Video", + [EM28XX_VMUX_TELEVISION] = "Television", + [EM28XX_VMUX_CABLE] = "Cable TV", + [EM28XX_VMUX_DVB] = "DVB", + [EM28XX_VMUX_DEBUG] = "for debug only", }; n = i->index; - if (n >= MAX_EM2820_INPUT) + if (n >= MAX_EM28XX_INPUT) return -EINVAL; if (0 == INPUT(n)->type) return -EINVAL; @@ -931,8 +932,8 @@ static int em2820_do_ioctl(struct inode *inode, struct file *filp, i->index = n; i->type = V4L2_INPUT_TYPE_CAMERA; strcpy(i->name, iname[INPUT(n)->type]); - if ((EM2820_VMUX_TELEVISION == INPUT(n)->type) || - (EM2820_VMUX_CABLE == INPUT(n)->type)) + if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) || + (EM28XX_VMUX_CABLE == INPUT(n)->type)) i->type = V4L2_INPUT_TYPE_TUNER; for (n = 0; n < ARRAY_SIZE(tvnorms); n++) i->std |= tvnorms[n].id; @@ -951,7 +952,7 @@ static int em2820_do_ioctl(struct inode *inode, struct file *filp, { int *index = arg; - if (*index >= MAX_EM2820_INPUT) + if (*index >= MAX_EM28XX_INPUT) return -EINVAL; if (0 == INPUT(*index)->type) return -EINVAL; @@ -997,10 +998,10 @@ static int em2820_do_ioctl(struct inode *inode, struct file *filp, { struct v4l2_queryctrl *qc = arg; u8 i, n; - n = sizeof(em2820_qctrl) / sizeof(em2820_qctrl[0]); + n = sizeof(em28xx_qctrl) / sizeof(em28xx_qctrl[0]); for (i = 0; i < n; i++) - if (qc->id && qc->id == em2820_qctrl[i].id) { - memcpy(qc, &(em2820_qctrl[i]), + if (qc->id && qc->id == em28xx_qctrl[i].id) { + memcpy(qc, &(em28xx_qctrl[i]), sizeof(*qc)); return 0; } @@ -1013,7 +1014,7 @@ static int em2820_do_ioctl(struct inode *inode, struct file *filp, struct v4l2_control *ctrl = arg; - return em2820_get_ctrl(dev, ctrl); + return em28xx_get_ctrl(dev, ctrl); } case VIDIOC_S_CTRL_OLD: /* ??? */ @@ -1023,16 +1024,16 @@ static int em2820_do_ioctl(struct inode *inode, struct file *filp, u8 i, n; - n = sizeof(em2820_qctrl) / sizeof(em2820_qctrl[0]); + n = sizeof(em28xx_qctrl) / sizeof(em28xx_qctrl[0]); for (i = 0; i < n; i++) - if (ctrl->id == em2820_qctrl[i].id) { + if (ctrl->id == em28xx_qctrl[i].id) { if (ctrl->value < - em2820_qctrl[i].minimum + em28xx_qctrl[i].minimum || ctrl->value > - em2820_qctrl[i].maximum) + em28xx_qctrl[i].maximum) return -ERANGE; - return em2820_set_ctrl(dev, ctrl); + return em28xx_set_ctrl(dev, ctrl); } return -EINVAL; } @@ -1052,16 +1053,16 @@ static int em2820_do_ioctl(struct inode *inode, struct file *filp, t->capability = V4L2_TUNER_CAP_NORM; t->rangehigh = 0xffffffffUL; /* FIXME: set correct range */ /* t->signal = 0xffff;*/ -/* em2820_i2c_call_clients(dev,VIDIOC_G_TUNER,t);*/ +/* em28xx_i2c_call_clients(dev,VIDIOC_G_TUNER,t);*/ /* No way to get signal strength? */ down(&dev->lock); - em2820_i2c_call_clients(dev, DECODER_GET_STATUS, + em28xx_i2c_call_clients(dev, DECODER_GET_STATUS, &status); up(&dev->lock); t->signal = (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0; - em2820_videodbg("VIDIO_G_TUNER: signal=%x, afc=%x", t->signal, + em28xx_videodbg("VIDIO_G_TUNER: signal=%x, afc=%x", t->signal, t->afc); return 0; } @@ -1080,13 +1081,13 @@ static int em2820_do_ioctl(struct inode *inode, struct file *filp, /* t->signal = 0xffff; */ /* No way to get signal strength? */ down(&dev->lock); - em2820_i2c_call_clients(dev, DECODER_GET_STATUS, + em28xx_i2c_call_clients(dev, DECODER_GET_STATUS, &status); up(&dev->lock); t->signal = (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0; - em2820_videodbg("VIDIO_S_TUNER: signal=%x, afc=%x\n", + em28xx_videodbg("VIDIO_S_TUNER: signal=%x, afc=%x\n", t->signal, t->afc); return 0; } @@ -1112,7 +1113,7 @@ static int em2820_do_ioctl(struct inode *inode, struct file *filp, down(&dev->lock); dev->ctl_freq = f->frequency; - em2820_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f); + em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f); up(&dev->lock); return 0; } @@ -1145,7 +1146,7 @@ static int em2820_do_ioctl(struct inode *inode, struct file *filp, dev->stream = STREAM_ON; /* FIXME: Start video capture here? */ - em2820_videodbg("VIDIOC_STREAMON: starting stream"); + em28xx_videodbg("VIDIOC_STREAMON: starting stream"); return 0; } @@ -1159,11 +1160,11 @@ static int em2820_do_ioctl(struct inode *inode, struct file *filp, return -EINVAL; if (dev->stream == STREAM_ON) { - em2820_videodbg ("VIDIOC_STREAMOFF: interrupting stream"); - if ((ret = em2820_stream_interrupt(dev))) + em28xx_videodbg ("VIDIOC_STREAMOFF: interrupting stream"); + if ((ret = em28xx_stream_interrupt(dev))) return ret; } - em2820_empty_framequeues(dev); + em28xx_empty_framequeues(dev); return 0; } @@ -1175,21 +1176,21 @@ static int em2820_do_ioctl(struct inode *inode, struct file *filp, } /* - * em2820_v4l2_do_ioctl() + * em28xx_v4l2_do_ioctl() * This function is _not_ called directly, but from - * em2820_v4l2_ioctl. Userspace + * em28xx_v4l2_ioctl. Userspace * copying is done already, arg is a kernel pointer. */ -static int em2820_video_do_ioctl(struct inode *inode, struct file *filp, +static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, void *arg) { - struct em2820 *dev = filp->private_data; + struct em28xx *dev = filp->private_data; if (!dev) return -ENODEV; if (video_debug > 1) - em2820_print_ioctl(dev->name,cmd); + em28xx_print_ioctl(dev->name,cmd); switch (cmd) { @@ -1199,12 +1200,12 @@ static int em2820_video_do_ioctl(struct inode *inode, struct file *filp, struct v4l2_capability *cap = arg; memset(cap, 0, sizeof(*cap)); - strlcpy(cap->driver, "em2820", sizeof(cap->driver)); - strlcpy(cap->card, em2820_boards[dev->model].name, + strlcpy(cap->driver, "em28xx", sizeof(cap->driver)); + strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card)); strlcpy(cap->bus_info, dev->udev->dev.bus_id, sizeof(cap->bus_info)); - cap->version = EM2820_VERSION_CODE; + cap->version = EM28XX_VERSION_CODE; cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_AUDIO | @@ -1233,7 +1234,7 @@ static int em2820_video_do_ioctl(struct inode *inode, struct file *filp, { struct v4l2_format *format = arg; - em2820_videodbg("VIDIOC_G_FMT: type=%s", + em28xx_videodbg("VIDIOC_G_FMT: type=%s", format->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? "V4L2_BUF_TYPE_VIDEO_CAPTURE" : format->type == @@ -1252,7 +1253,7 @@ static int em2820_video_do_ioctl(struct inode *inode, struct file *filp, format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; format->fmt.pix.field = dev->interlaced ? V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */ - em2820_videodbg("VIDIOC_G_FMT: %dx%d", dev->width, + em28xx_videodbg("VIDIOC_G_FMT: %dx%d", dev->width, dev->height); return 0; } @@ -1273,7 +1274,7 @@ static int em2820_video_do_ioctl(struct inode *inode, struct file *filp, /* int both_fields; */ - em2820_videodbg("%s: type=%s", + em28xx_videodbg("%s: type=%s", cmd == VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : "VIDIOC_S_FMT", @@ -1287,7 +1288,7 @@ static int em2820_video_do_ioctl(struct inode *inode, struct file *filp, if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - em2820_videodbg("%s: requested %dx%d", + em28xx_videodbg("%s: requested %dx%d", cmd == VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : "VIDIOC_S_FMT", format->fmt.pix.width, @@ -1346,7 +1347,7 @@ static int em2820_video_do_ioctl(struct inode *inode, struct file *filp, format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; format->fmt.pix.field = V4L2_FIELD_INTERLACED; - em2820_videodbg("%s: returned %dx%d (%d, %d)", + em28xx_videodbg("%s: returned %dx%d (%d, %d)", cmd == VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : "VIDIOC_S_FMT", format->fmt.pix.width, @@ -1357,19 +1358,19 @@ static int em2820_video_do_ioctl(struct inode *inode, struct file *filp, for (i = 0; i < dev->num_frames; i++) if (dev->frame[i].vma_use_count) { - em2820_videodbg("VIDIOC_S_FMT failed. " + em28xx_videodbg("VIDIOC_S_FMT failed. " "Unmap the buffers first."); return -EINVAL; } /* stop io in case it is already in progress */ if (dev->stream == STREAM_ON) { - em2820_videodbg("VIDIOC_SET_FMT: interupting stream"); - if ((ret = em2820_stream_interrupt(dev))) + em28xx_videodbg("VIDIOC_SET_FMT: interupting stream"); + if ((ret = em28xx_stream_interrupt(dev))) return ret; } - em2820_release_buffers(dev); + em28xx_release_buffers(dev); dev->io = IO_NONE; /* set new image size */ @@ -1381,11 +1382,11 @@ static int em2820_video_do_ioctl(struct inode *inode, struct file *filp, dev->hscale = hscale; dev->vscale = vscale; /* dev->both_fileds = both_fileds; */ - em2820_uninit_isoc(dev); - em2820_set_alternate(dev); - em2820_capture_start(dev, 1); - em2820_resolution_set(dev); - em2820_init_isoc(dev); + em28xx_uninit_isoc(dev); + em28xx_set_alternate(dev); + em28xx_capture_start(dev, 1); + em28xx_resolution_set(dev); + em28xx_init_isoc(dev); return 0; } @@ -1402,7 +1403,7 @@ static int em2820_video_do_ioctl(struct inode *inode, struct file *filp, return -EINVAL; if (dev->io == IO_READ) { - em2820_videodbg ("method is set to read;" + em28xx_videodbg ("method is set to read;" " close and open the device again to" " choose the mmap I/O method"); return -EINVAL; @@ -1410,26 +1411,26 @@ static int em2820_video_do_ioctl(struct inode *inode, struct file *filp, for (i = 0; i < dev->num_frames; i++) if (dev->frame[i].vma_use_count) { - em2820_videodbg ("VIDIOC_REQBUFS failed; previous buffers are still mapped"); + em28xx_videodbg ("VIDIOC_REQBUFS failed; previous buffers are still mapped"); return -EINVAL; } if (dev->stream == STREAM_ON) { - em2820_videodbg("VIDIOC_REQBUFS: interrupting stream"); - if ((ret = em2820_stream_interrupt(dev))) + em28xx_videodbg("VIDIOC_REQBUFS: interrupting stream"); + if ((ret = em28xx_stream_interrupt(dev))) return ret; } - em2820_empty_framequeues(dev); + em28xx_empty_framequeues(dev); - em2820_release_buffers(dev); + em28xx_release_buffers(dev); if (rb->count) rb->count = - em2820_request_buffers(dev, rb->count); + em28xx_request_buffers(dev, rb->count); dev->frame_current = NULL; - em2820_videodbg ("VIDIOC_REQBUFS: setting io method to mmap: num bufs %i", + em28xx_videodbg ("VIDIOC_REQBUFS: setting io method to mmap: num bufs %i", rb->count); dev->io = rb->count ? IO_MMAP : IO_NONE; return 0; @@ -1480,7 +1481,7 @@ static int em2820_video_do_ioctl(struct inode *inode, struct file *filp, case VIDIOC_DQBUF: { struct v4l2_buffer *b = arg; - struct em2820_frame_t *f; + struct em28xx_frame_t *f; unsigned long lock_flags; int ret = 0; @@ -1505,7 +1506,7 @@ static int em2820_video_do_ioctl(struct inode *inode, struct file *filp, spin_lock_irqsave(&dev->queue_lock, lock_flags); f = list_entry(dev->outqueue.next, - struct em2820_frame_t, frame); + struct em28xx_frame_t, frame); list_del(dev->outqueue.next); spin_unlock_irqrestore(&dev->queue_lock, lock_flags); @@ -1518,66 +1519,66 @@ static int em2820_video_do_ioctl(struct inode *inode, struct file *filp, return 0; } default: - return em2820_do_ioctl(inode, filp, dev, cmd, arg, - em2820_video_do_ioctl); + return em28xx_do_ioctl(inode, filp, dev, cmd, arg, + em28xx_video_do_ioctl); } return 0; } /* - * em2820_v4l2_ioctl() - * handle v4l2 ioctl the main action happens in em2820_v4l2_do_ioctl() + * em28xx_v4l2_ioctl() + * handle v4l2 ioctl the main action happens in em28xx_v4l2_do_ioctl() */ -static int em2820_v4l2_ioctl(struct inode *inode, struct file *filp, +static int em28xx_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { int ret = 0; - struct em2820 *dev = filp->private_data; + struct em28xx *dev = filp->private_data; if (down_interruptible(&dev->fileop_lock)) return -ERESTARTSYS; if (dev->state & DEV_DISCONNECTED) { - em2820_errdev("v4l2 ioctl: device not present\n"); + em28xx_errdev("v4l2 ioctl: device not present\n"); up(&dev->fileop_lock); return -ENODEV; } if (dev->state & DEV_MISCONFIGURED) { - em2820_errdev + em28xx_errdev ("v4l2 ioctl: device is misconfigured; close and open it again\n"); up(&dev->fileop_lock); return -EIO; } - ret = video_usercopy(inode, filp, cmd, arg, em2820_video_do_ioctl); + ret = video_usercopy(inode, filp, cmd, arg, em28xx_video_do_ioctl); up(&dev->fileop_lock); return ret; } -static struct file_operations em2820_v4l_fops = { +static struct file_operations em28xx_v4l_fops = { .owner = THIS_MODULE, - .open = em2820_v4l2_open, - .release = em2820_v4l2_close, - .ioctl = em2820_v4l2_ioctl, - .read = em2820_v4l2_read, - .poll = em2820_v4l2_poll, - .mmap = em2820_v4l2_mmap, + .open = em28xx_v4l2_open, + .release = em28xx_v4l2_close, + .ioctl = em28xx_v4l2_ioctl, + .read = em28xx_v4l2_read, + .poll = em28xx_v4l2_poll, + .mmap = em28xx_v4l2_mmap, .llseek = no_llseek, }; /******************************** usb interface *****************************************/ /* - * em2820_init_dev() + * em28xx_init_dev() * allocates and inits the device structs, registers i2c bus and v4l device */ -static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, +static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, int minor, int model) { - struct em2820 *dev = *devhandle; + struct em28xx *dev = *devhandle; int retval = -ENOMEM; int errCode, i; unsigned int maxh, maxw; @@ -1588,33 +1589,33 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, init_MUTEX(&dev->lock); init_waitqueue_head(&dev->open); - dev->em2820_write_regs = em2820_write_regs; - dev->em2820_read_reg = em2820_read_reg; - dev->em2820_read_reg_req_len = em2820_read_reg_req_len; - dev->em2820_write_regs_req = em2820_write_regs_req; - dev->em2820_read_reg_req = em2820_read_reg_req; - dev->is_em2800 = em2820_boards[model].is_em2800; - dev->has_tuner = em2820_boards[model].has_tuner; - dev->has_msp34xx = em2820_boards[model].has_msp34xx; - dev->tda9887_conf = em2820_boards[model].tda9887_conf; - dev->decoder = em2820_boards[model].decoder; + dev->em28xx_write_regs = em28xx_write_regs; + dev->em28xx_read_reg = em28xx_read_reg; + dev->em28xx_read_reg_req_len = em28xx_read_reg_req_len; + dev->em28xx_write_regs_req = em28xx_write_regs_req; + dev->em28xx_read_reg_req = em28xx_read_reg_req; + dev->is_em2800 = em28xx_boards[model].is_em2800; + dev->has_tuner = em28xx_boards[model].has_tuner; + dev->has_msp34xx = em28xx_boards[model].has_msp34xx; + dev->tda9887_conf = em28xx_boards[model].tda9887_conf; + dev->decoder = em28xx_boards[model].decoder; if (tuner >= 0) dev->tuner_type = tuner; else - dev->tuner_type = em2820_boards[model].tuner_type; + dev->tuner_type = em28xx_boards[model].tuner_type; - dev->video_inputs = em2820_boards[model].vchannels; + dev->video_inputs = em28xx_boards[model].vchannels; for (i = 0; i < TVNORMS; i++) - if (em2820_boards[model].norm == tvnorms[i].mode) + if (em28xx_boards[model].norm == tvnorms[i].mode) break; if (i == TVNORMS) i = 0; dev->tvnorm = &tvnorms[i]; /* set default norm */ - em2820_videodbg("tvnorm=%s\n", dev->tvnorm->name); + em28xx_videodbg("tvnorm=%s\n", dev->tvnorm->name); maxw = norm_maxw(dev); maxh = norm_maxh(dev); @@ -1622,7 +1623,7 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, /* set default image size */ dev->width = maxw; dev->height = maxh; - dev->interlaced = EM2820_INTERLACED_DEFAULT; + dev->interlaced = EM28XX_INTERLACED_DEFAULT; dev->field_size = dev->width * dev->height; dev->frame_size = dev->interlaced ? dev->field_size << 1 : dev->field_size; @@ -1644,7 +1645,7 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, /* compute alternate max packet sizes */ uif = dev->udev->actconfig->interface[0]; dev->alt_max_pkt_size[0] = 0; - for (i = 1; i <= EM2820_MAX_ALT && i < uif->num_altsetting ; i++) { + for (i = 1; i <= EM28XX_MAX_ALT && i < uif->num_altsetting ; i++) { u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc. wMaxPacketSize); @@ -1654,35 +1655,35 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, #ifdef CONFIG_MODULES /* request some modules */ - if (dev->decoder == EM2820_SAA7113 || dev->decoder == EM2820_SAA7114) + if (dev->decoder == EM28XX_SAA7113 || dev->decoder == EM28XX_SAA7114) request_module("saa711x"); - if (dev->decoder == EM2820_TVP5150) + if (dev->decoder == EM28XX_TVP5150) request_module("tvp5150"); if (dev->has_tuner) request_module("tuner"); if (dev->tda9887_conf) request_module("tda9887"); #endif - errCode = em2820_config(dev); + errCode = em28xx_config(dev); if (errCode) { - em2820_errdev("error configuring device\n"); + em28xx_errdev("error configuring device\n"); kfree(dev); return -ENOMEM; } down(&dev->lock); /* register i2c bus */ - em2820_i2c_register(dev); + em28xx_i2c_register(dev); /* Do board specific init and eeprom reading */ - em2820_card_setup(dev); + em28xx_card_setup(dev); /* configure the device */ - em2820_config_i2c(dev); + em28xx_config_i2c(dev); up(&dev->lock); - errCode = em2820_config(dev); + errCode = em28xx_config(dev); #ifdef CONFIG_MODULES if (dev->has_msp34xx) @@ -1691,7 +1692,7 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, /* allocate and fill v4l2 device struct */ dev->vdev = video_device_alloc(); if (NULL == dev->vdev) { - em2820_errdev("cannot allocate video_device.\n"); + em28xx_errdev("cannot allocate video_device.\n"); kfree(dev); return -ENOMEM; } @@ -1700,18 +1701,18 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, if (dev->has_tuner) dev->vdev->type |= VID_TYPE_TUNER; dev->vdev->hardware = 0; - dev->vdev->fops = &em2820_v4l_fops; + dev->vdev->fops = &em28xx_v4l_fops; dev->vdev->minor = -1; dev->vdev->dev = &dev->udev->dev; dev->vdev->release = video_device_release; snprintf(dev->vdev->name, sizeof(dev->vdev->name), "%s", - "em2820 video"); - list_add_tail(&dev->devlist,&em2820_devlist); + "em28xx video"); + list_add_tail(&dev->devlist,&em28xx_devlist); /* register v4l2 device */ down(&dev->lock); if ((retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1))) { - em2820_errdev("unable to register video device (error=%i).\n", + em28xx_errdev("unable to register video device (error=%i).\n", retval); up(&dev->lock); list_del(&dev->devlist); @@ -1721,9 +1722,9 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, } if (dev->has_msp34xx) { /* Send a reset to other chips via gpio */ - em2820_write_regs_req(dev, 0x00, 0x08, "\xf7", 1); + em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1); udelay(2500); - em2820_write_regs_req(dev, 0x00, 0x08, "\xff", 1); + em28xx_write_regs_req(dev, 0x00, 0x08, "\xff", 1); udelay(2500); } @@ -1731,22 +1732,22 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, up(&dev->lock); - em2820_info("V4L2 device registered as /dev/video%d\n", + em28xx_info("V4L2 device registered as /dev/video%d\n", dev->vdev->minor); return 0; } /* - * em2820_usb_probe() + * em28xx_usb_probe() * checks for supported devices */ -static int em2820_usb_probe(struct usb_interface *interface, +static int em28xx_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { const struct usb_endpoint_descriptor *endpoint; struct usb_device *udev; - struct em2820 *dev = NULL; + struct em28xx *dev = NULL; int retval = -ENODEV; int model,i,nr,ifnum; @@ -1756,14 +1757,14 @@ static int em2820_usb_probe(struct usb_interface *interface, /* Don't register audio interfaces */ if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { - em2820_err(DRIVER_NAME " audio device (%04x:%04x): interface %i, class %i\n", + em28xx_err(DRIVER_NAME " audio device (%04x:%04x): interface %i, class %i\n", udev->descriptor.idVendor,udev->descriptor.idProduct, ifnum, interface->altsetting[0].desc.bInterfaceClass); return -ENODEV; } - em2820_err(DRIVER_NAME " new video device (%04x:%04x): interface %i, class %i\n", + em28xx_err(DRIVER_NAME " new video device (%04x:%04x): interface %i, class %i\n", udev->descriptor.idVendor,udev->descriptor.idProduct, ifnum, interface->altsetting[0].desc.bInterfaceClass); @@ -1773,33 +1774,33 @@ static int em2820_usb_probe(struct usb_interface *interface, /* check if the the device has the iso in endpoint at the correct place */ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) { - em2820_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n"); + em28xx_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n"); return -ENODEV; } if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { - em2820_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n"); + em28xx_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n"); return -ENODEV; } model=id->driver_info; nr=interface->minor; - if (nr>EM2820_MAXBOARDS) { - printk ("em2820: Supports only %i em28xx boards.\n",EM2820_MAXBOARDS); + if (nr>EM28XX_MAXBOARDS) { + printk ("em28xx: Supports only %i em28xx boards.\n",EM28XX_MAXBOARDS); return -ENOMEM; } /* allocate memory for our device state and initialize it */ dev = kmalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { - em2820_err(DRIVER_NAME ": out of memory!\n"); + em28xx_err(DRIVER_NAME ": out of memory!\n"); return -ENOMEM; } memset(dev, 0, sizeof(*dev)); - snprintf(dev->name, 29, "em2820 #%d", nr); + snprintf(dev->name, 29, "em28xx #%d", nr); - if ((card[nr]>=0)&&(card[nr]=0)&&(card[nr]name,dev->name,dev->name,dev->name,dev->name); printk("%s: Here is a list of valid choices for the card= insmod option:\n", dev->name); - for (i = 0; i < em2820_bcount; i++) { + for (i = 0; i < em28xx_bcount; i++) { printk("%s: card=%d -> %s\n", - dev->name, i, em2820_boards[i].name); + dev->name, i, em28xx_boards[i].name); } } /* allocate device struct */ - retval = em2820_init_dev(&dev, udev, nr, model); + retval = em28xx_init_dev(&dev, udev, nr, model); if (retval) return retval; - em2820_info("Found %s\n", em2820_boards[model].name); + em28xx_info("Found %s\n", em28xx_boards[model].name); /* save our data pointer in this interface device */ usb_set_intfdata(interface, dev); @@ -1830,38 +1831,38 @@ static int em2820_usb_probe(struct usb_interface *interface, } /* - * em2820_usb_disconnect() + * em28xx_usb_disconnect() * called when the device gets diconencted * video device will be unregistered on v4l2_close in case it is still open */ -static void em2820_usb_disconnect(struct usb_interface *interface) +static void em28xx_usb_disconnect(struct usb_interface *interface) { - struct em2820 *dev = usb_get_intfdata(interface); + struct em28xx *dev = usb_get_intfdata(interface); usb_set_intfdata(interface, NULL); if (!dev) return; - down_write(&em2820_disconnect); + down_write(&em28xx_disconnect); down(&dev->lock); - em2820_info("disconnecting %s\n", dev->vdev->name); + em28xx_info("disconnecting %s\n", dev->vdev->name); wake_up_interruptible_all(&dev->open); if (dev->users) { - em2820_warn + em28xx_warn ("device /dev/video%d is open! Deregistration and memory " "deallocation are deferred on close.\n", dev->vdev->minor); dev->state |= DEV_MISCONFIGURED; - em2820_uninit_isoc(dev); + em28xx_uninit_isoc(dev); dev->state |= DEV_DISCONNECTED; wake_up_interruptible(&dev->wait_frame); wake_up_interruptible(&dev->wait_stream); } else { dev->state |= DEV_DISCONNECTED; - em2820_release_resources(dev); + em28xx_release_resources(dev); } up(&dev->lock); @@ -1869,44 +1870,44 @@ static void em2820_usb_disconnect(struct usb_interface *interface) if (!dev->users) kfree(dev); - up_write(&em2820_disconnect); + up_write(&em28xx_disconnect); } -static struct usb_driver em2820_usb_driver = { +static struct usb_driver em28xx_usb_driver = { .owner = THIS_MODULE, - .name = "em2820", - .probe = em2820_usb_probe, - .disconnect = em2820_usb_disconnect, - .id_table = em2820_id_table, + .name = "em28xx", + .probe = em28xx_usb_probe, + .disconnect = em28xx_usb_disconnect, + .id_table = em28xx_id_table, }; -static int __init em2820_module_init(void) +static int __init em28xx_module_init(void) { int result; printk(KERN_INFO DRIVER_NAME " v4l2 driver version %d.%d.%d loaded\n", - (EM2820_VERSION_CODE >> 16) & 0xff, - (EM2820_VERSION_CODE >> 8) & 0xff, EM2820_VERSION_CODE & 0xff); + (EM28XX_VERSION_CODE >> 16) & 0xff, + (EM28XX_VERSION_CODE >> 8) & 0xff, EM28XX_VERSION_CODE & 0xff); #ifdef SNAPSHOT printk(KERN_INFO DRIVER_NAME " snapshot date %04d-%02d-%02d\n", SNAPSHOT / 10000, (SNAPSHOT / 100) % 100, SNAPSHOT % 100); #endif /* register this driver with the USB subsystem */ - result = usb_register(&em2820_usb_driver); + result = usb_register(&em28xx_usb_driver); if (result) - em2820_err(DRIVER_NAME + em28xx_err(DRIVER_NAME " usb_register failed. Error number %d.\n", result); return result; } -static void __exit em2820_module_exit(void) +static void __exit em28xx_module_exit(void) { /* deregister this driver with the USB subsystem */ - usb_deregister(&em2820_usb_driver); + usb_deregister(&em28xx_usb_driver); } -module_init(em2820_module_init); -module_exit(em2820_module_exit); +module_init(em28xx_module_init); +module_exit(em28xx_module_exit); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 8c58c5b5fa3..d51f8c63bcf 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -1,5 +1,5 @@ /* - em2820-cards.c - driver for Empia EM2800/EM2820/2840 USB video capture devices + em28xx-cards.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger Ludovico Cavedon @@ -22,8 +22,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _EM2820_H -#define _EM2820_H +#ifndef _EM28XX_H +#define _EM28XX_H #include #include @@ -45,27 +45,27 @@ #define UNSET -1 /* maximum number of em28xx boards */ -#define EM2820_MAXBOARDS 1 /*FIXME: should be bigger */ +#define EM28XX_MAXBOARDS 1 /*FIXME: should be bigger */ /* maximum number of frames that can be queued */ -#define EM2820_NUM_FRAMES 5 +#define EM28XX_NUM_FRAMES 5 /* number of frames that get used for v4l2_read() */ -#define EM2820_NUM_READ_FRAMES 2 +#define EM28XX_NUM_READ_FRAMES 2 /* number of buffers for isoc transfers */ -#define EM2820_NUM_BUFS 5 +#define EM28XX_NUM_BUFS 5 /* number of packets for each buffer windows requests only 40 packets .. so we better do the same this is what I found out for all alternate numbers there! */ -#define EM2820_NUM_PACKETS 40 +#define EM28XX_NUM_PACKETS 40 /* default alternate; 0 means choose the best */ -#define EM2820_PINOUT 0 -#define EM2820_MAX_ALT 7 +#define EM28XX_PINOUT 0 +#define EM28XX_MAX_ALT 7 -#define EM2820_INTERLACED_DEFAULT 1 +#define EM28XX_INTERLACED_DEFAULT 1 /* #define (use usbview if you want to get the other alternate number infos) @@ -89,13 +89,13 @@ */ /* time to wait when stopping the isoc transfer */ -#define EM2820_URB_TIMEOUT msecs_to_jiffies(EM2820_NUM_BUFS * EM2820_NUM_PACKETS) +#define EM28XX_URB_TIMEOUT msecs_to_jiffies(EM28XX_NUM_BUFS * EM28XX_NUM_PACKETS) /* time in msecs to wait for i2c writes to finish */ #define EM2800_I2C_WRITE_TIMEOUT 20 /* the various frame states */ -enum em2820_frame_state { +enum em28xx_frame_state { F_UNUSED = 0, F_QUEUED, F_GRABBING, @@ -104,17 +104,17 @@ enum em2820_frame_state { }; /* stream states */ -enum em2820_stream_state { +enum em28xx_stream_state { STREAM_OFF, STREAM_INTERRUPT, STREAM_ON, }; /* frames */ -struct em2820_frame_t { +struct em28xx_frame_t { void *bufmem; struct v4l2_buffer buf; - enum em2820_frame_state state; + enum em28xx_frame_state state; struct list_head frame; unsigned long vma_use_count; int top_field; @@ -122,7 +122,7 @@ struct em2820_frame_t { }; /* io methods */ -enum em2820_io_method { +enum em28xx_io_method { IO_NONE, IO_READ, IO_MMAP, @@ -130,35 +130,35 @@ enum em2820_io_method { /* inputs */ -#define MAX_EM2820_INPUT 4 -enum enum2820_itype { - EM2820_VMUX_COMPOSITE1 = 1, - EM2820_VMUX_COMPOSITE2, - EM2820_VMUX_COMPOSITE3, - EM2820_VMUX_COMPOSITE4, - EM2820_VMUX_SVIDEO, - EM2820_VMUX_TELEVISION, - EM2820_VMUX_CABLE, - EM2820_VMUX_DVB, - EM2820_VMUX_DEBUG, - EM2820_RADIO, +#define MAX_EM28XX_INPUT 4 +enum enum28xx_itype { + EM28XX_VMUX_COMPOSITE1 = 1, + EM28XX_VMUX_COMPOSITE2, + EM28XX_VMUX_COMPOSITE3, + EM28XX_VMUX_COMPOSITE4, + EM28XX_VMUX_SVIDEO, + EM28XX_VMUX_TELEVISION, + EM28XX_VMUX_CABLE, + EM28XX_VMUX_DVB, + EM28XX_VMUX_DEBUG, + EM28XX_RADIO, }; -struct em2820_input { - enum enum2820_itype type; +struct em28xx_input { + enum enum28xx_itype type; unsigned int vmux; unsigned int amux; }; -#define INPUT(nr) (&em2820_boards[dev->model].input[nr]) +#define INPUT(nr) (&em28xx_boards[dev->model].input[nr]) -enum em2820_decoder { - EM2820_TVP5150, - EM2820_SAA7113, - EM2820_SAA7114 +enum em28xx_decoder { + EM28XX_TVP5150, + EM28XX_SAA7113, + EM28XX_SAA7114 }; -struct em2820_board { +struct em28xx_board { char *name; int vchannels; int norm; @@ -171,12 +171,12 @@ struct em2820_board { unsigned int has_tuner:1; unsigned int has_msp34xx:1; - enum em2820_decoder decoder; + enum em28xx_decoder decoder; - struct em2820_input input[MAX_EM2820_INPUT]; + struct em28xx_input input[MAX_EM28XX_INPUT]; }; -struct em2820_eeprom { +struct em28xx_eeprom { u32 id; /* 0x9567eb1a */ u16 vendor_ID; u16 product_ID; @@ -191,14 +191,14 @@ struct em2820_eeprom { }; /* device states */ -enum em2820_dev_state { +enum em28xx_dev_state { DEV_INITIALIZED = 0x01, DEV_DISCONNECTED = 0x02, DEV_MISCONFIGURED = 0x04, }; /* tvnorms */ -struct em2820_tvnorm { +struct em28xx_tvnorm { char *name; v4l2_std_id id; /* mode for saa7113h */ @@ -206,7 +206,7 @@ struct em2820_tvnorm { }; /* main device struct */ -struct em2820 { +struct em28xx { /* generic device properties */ char name[30]; /* name (including minor) of the device */ int model; /* index in the device_data struct */ @@ -217,7 +217,7 @@ struct em2820 { unsigned int has_msp34xx:1; unsigned int has_tda9887:1; - enum em2820_decoder decoder; + enum em28xx_decoder decoder; int tuner_type; /* type of the tuner */ int tuner_addr; /* tuner address */ @@ -229,17 +229,17 @@ struct em2820 { int users; /* user count for exclusive use */ struct video_device *vdev; /* video for linux device struct */ struct video_picture vpic; /* picture settings only used to init saa7113h */ - struct em2820_tvnorm *tvnorm; /* selected tv norm */ + struct em28xx_tvnorm *tvnorm; /* selected tv norm */ int ctl_freq; /* selected frequency */ unsigned int ctl_input; /* selected input */ unsigned int ctl_ainput; /* slected audio input */ int mute; int volume; /* frame properties */ - struct em2820_frame_t frame[EM2820_NUM_FRAMES]; /* list of frames */ + struct em28xx_frame_t frame[EM28XX_NUM_FRAMES]; /* list of frames */ int num_frames; /* number of frames currently in use */ unsigned int frame_count; /* total number of transfered frames */ - struct em2820_frame_t *frame_current; /* the frame that is being filled */ + struct em28xx_frame_t *frame_current; /* the frame that is being filled */ int width; /* current frame width */ int height; /* current frame height */ int frame_size; /* current frame size */ @@ -251,9 +251,9 @@ struct em2820 { int type; /* states */ - enum em2820_dev_state state; - enum em2820_stream_state stream; - enum em2820_io_method io; + enum em28xx_dev_state state; + enum em28xx_stream_state stream; + enum em28xx_io_method io; /* locks */ struct semaphore lock, fileop_lock; spinlock_t queue_lock; @@ -267,71 +267,71 @@ struct em2820 { struct usb_device *udev; /* the usb device */ int alt; /* alternate */ int max_pkt_size; /* max packet size of isoc transaction */ - unsigned int alt_max_pkt_size[EM2820_MAX_ALT + 1]; /* array of wMaxPacketSize */ - struct urb *urb[EM2820_NUM_BUFS]; /* urb for isoc transfers */ - char *transfer_buffer[EM2820_NUM_BUFS]; /* transfer buffers for isoc transfer */ + unsigned int alt_max_pkt_size[EM28XX_MAX_ALT + 1]; /* array of wMaxPacketSize */ + struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ + char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc transfer */ /* helper funcs that call usb_control_msg */ - int (*em2820_write_regs) (struct em2820 * dev, u16 reg, char *buf, + int (*em28xx_write_regs) (struct em28xx * dev, u16 reg, char *buf, int len); - int (*em2820_read_reg) (struct em2820 * dev, u16 reg); - int (*em2820_read_reg_req_len) (struct em2820 * dev, u8 req, u16 reg, + int (*em28xx_read_reg) (struct em28xx * dev, u16 reg); + int (*em28xx_read_reg_req_len) (struct em28xx * dev, u8 req, u16 reg, char *buf, int len); - int (*em2820_write_regs_req) (struct em2820 * dev, u8 req, u16 reg, + int (*em28xx_write_regs_req) (struct em28xx * dev, u8 req, u16 reg, char *buf, int len); - int (*em2820_read_reg_req) (struct em2820 * dev, u8 req, u16 reg); + int (*em28xx_read_reg_req) (struct em28xx * dev, u8 req, u16 reg); }; -/* Provided by em2820-i2c.c */ +/* Provided by em28xx-i2c.c */ -void em2820_i2c_call_clients(struct em2820 *dev, unsigned int cmd, void *arg); -int em2820_i2c_register(struct em2820 *dev); -int em2820_i2c_unregister(struct em2820 *dev); +void em28xx_i2c_call_clients(struct em28xx *dev, unsigned int cmd, void *arg); +int em28xx_i2c_register(struct em28xx *dev); +int em28xx_i2c_unregister(struct em28xx *dev); -/* Provided by em2820-input.c */ +/* Provided by em28xx-input.c */ -void em2820_set_ir(struct em2820 * dev,struct IR_i2c *ir); +void em28xx_set_ir(struct em28xx * dev,struct IR_i2c *ir); -/* Provided by em2820-core.c */ +/* Provided by em28xx-core.c */ -void em2820_print_ioctl(char *name, unsigned int cmd); +void em28xx_print_ioctl(char *name, unsigned int cmd); -u32 em2820_request_buffers(struct em2820 *dev, u32 count); -void em2820_queue_unusedframes(struct em2820 *dev); -void em2820_release_buffers(struct em2820 *dev); +u32 em28xx_request_buffers(struct em28xx *dev, u32 count); +void em28xx_queue_unusedframes(struct em28xx *dev); +void em28xx_release_buffers(struct em28xx *dev); -int em2820_read_reg_req_len(struct em2820 *dev, u8 req, u16 reg, +int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, char *buf, int len); -int em2820_read_reg_req(struct em2820 *dev, u8 req, u16 reg); -int em2820_read_reg(struct em2820 *dev, u16 reg); -int em2820_write_regs_req(struct em2820 *dev, u8 req, u16 reg, char *buf, +int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg); +int em28xx_read_reg(struct em28xx *dev, u16 reg); +int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, int len); -int em2820_write_regs(struct em2820 *dev, u16 reg, char *buf, int len); -int em2820_write_reg_bits(struct em2820 *dev, u16 reg, u8 val, +int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len); +int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, u8 bitmask); -int em2820_write_ac97(struct em2820 *dev, u8 reg, u8 * val); -int em2820_audio_analog_set(struct em2820 *dev); -int em2820_colorlevels_set_default(struct em2820 *dev); -int em2820_capture_start(struct em2820 *dev, int start); -int em2820_outfmt_set_yuv422(struct em2820 *dev); -int em2820_accumulator_set(struct em2820 *dev, u8 xmin, u8 xmax, u8 ymin, +int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 * val); +int em28xx_audio_analog_set(struct em28xx *dev); +int em28xx_colorlevels_set_default(struct em28xx *dev); +int em28xx_capture_start(struct em28xx *dev, int start); +int em28xx_outfmt_set_yuv422(struct em28xx *dev); +int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, u8 ymin, u8 ymax); -int em2820_capture_area_set(struct em2820 *dev, u8 hstart, u8 vstart, +int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart, u16 width, u16 height); -int em2820_scaler_set(struct em2820 *dev, u16 h, u16 v); -int em2820_resolution_set(struct em2820 *dev); -void em2820_isocIrq(struct urb *urb, struct pt_regs *regs); -int em2820_init_isoc(struct em2820 *dev); -void em2820_uninit_isoc(struct em2820 *dev); -int em2820_set_alternate(struct em2820 *dev); - -/* Provided by em2820-cards.c */ +int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v); +int em28xx_resolution_set(struct em28xx *dev); +void em28xx_isocIrq(struct urb *urb, struct pt_regs *regs); +int em28xx_init_isoc(struct em28xx *dev); +void em28xx_uninit_isoc(struct em28xx *dev); +int em28xx_set_alternate(struct em28xx *dev); + +/* Provided by em28xx-cards.c */ extern int em2800_variant_detect(struct usb_device* udev,int model); -extern void em2820_card_setup(struct em2820 *dev); -extern struct em2820_board em2820_boards[]; -extern struct usb_device_id em2820_id_table[]; -extern const unsigned int em2820_bcount; +extern void em28xx_card_setup(struct em28xx *dev); +extern struct em28xx_board em28xx_boards[]; +extern struct usb_device_id em28xx_id_table[]; +extern const unsigned int em28xx_bcount; -/* em2820 registers */ +/* em28xx registers */ #define CHIPID_REG 0x0a #define USBSUSP_REG 0x0c /* */ @@ -386,115 +386,115 @@ extern const unsigned int em2820_bcount; #define VIDEO_AC97 0x14 /* register settings */ -#define EM2820_AUDIO_SRC_TUNER 0xc0 -#define EM2820_AUDIO_SRC_LINE 0x80 +#define EM28XX_AUDIO_SRC_TUNER 0xc0 +#define EM28XX_AUDIO_SRC_LINE 0x80 /* printk macros */ -#define em2820_err(fmt, arg...) do {\ +#define em28xx_err(fmt, arg...) do {\ printk(KERN_ERR fmt , ##arg); } while (0) -#define em2820_errdev(fmt, arg...) do {\ +#define em28xx_errdev(fmt, arg...) do {\ printk(KERN_ERR "%s: "fmt,\ dev->name , ##arg); } while (0) -#define em2820_info(fmt, arg...) do {\ +#define em28xx_info(fmt, arg...) do {\ printk(KERN_INFO "%s: "fmt,\ dev->name , ##arg); } while (0) -#define em2820_warn(fmt, arg...) do {\ +#define em28xx_warn(fmt, arg...) do {\ printk(KERN_WARNING "%s: "fmt,\ dev->name , ##arg); } while (0) -inline static int em2820_audio_source(struct em2820 *dev, int input) +inline static int em28xx_audio_source(struct em28xx *dev, int input) { - return em2820_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0); + return em28xx_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0); } -inline static int em2820_audio_usb_mute(struct em2820 *dev, int mute) +inline static int em28xx_audio_usb_mute(struct em28xx *dev, int mute) { - return em2820_write_reg_bits(dev, XCLK_REG, mute ? 0x00 : 0x80, 0x80); + return em28xx_write_reg_bits(dev, XCLK_REG, mute ? 0x00 : 0x80, 0x80); } -inline static int em2820_audio_analog_setup(struct em2820 *dev) +inline static int em28xx_audio_analog_setup(struct em28xx *dev) { /* unmute video mixer with default volume level */ - return em2820_write_ac97(dev, VIDEO_AC97, "\x08\x08"); + return em28xx_write_ac97(dev, VIDEO_AC97, "\x08\x08"); } -inline static int em2820_compression_disable(struct em2820 *dev) +inline static int em28xx_compression_disable(struct em28xx *dev) { /* side effect of disabling scaler and mixer */ - return em2820_write_regs(dev, COMPR_REG, "\x00", 1); + return em28xx_write_regs(dev, COMPR_REG, "\x00", 1); } -inline static int em2820_contrast_get(struct em2820 *dev) +inline static int em28xx_contrast_get(struct em28xx *dev) { - return em2820_read_reg(dev, YGAIN_REG) & 0x1f; + return em28xx_read_reg(dev, YGAIN_REG) & 0x1f; } -inline static int em2820_brightness_get(struct em2820 *dev) +inline static int em28xx_brightness_get(struct em28xx *dev) { - return em2820_read_reg(dev, YOFFSET_REG); + return em28xx_read_reg(dev, YOFFSET_REG); } -inline static int em2820_saturation_get(struct em2820 *dev) +inline static int em28xx_saturation_get(struct em28xx *dev) { - return em2820_read_reg(dev, UVGAIN_REG) & 0x1f; + return em28xx_read_reg(dev, UVGAIN_REG) & 0x1f; } -inline static int em2820_u_balance_get(struct em2820 *dev) +inline static int em28xx_u_balance_get(struct em28xx *dev) { - return em2820_read_reg(dev, UOFFSET_REG); + return em28xx_read_reg(dev, UOFFSET_REG); } -inline static int em2820_v_balance_get(struct em2820 *dev) +inline static int em28xx_v_balance_get(struct em28xx *dev) { - return em2820_read_reg(dev, VOFFSET_REG); + return em28xx_read_reg(dev, VOFFSET_REG); } -inline static int em2820_gamma_get(struct em2820 *dev) +inline static int em28xx_gamma_get(struct em28xx *dev) { - return em2820_read_reg(dev, GAMMA_REG) & 0x3f; + return em28xx_read_reg(dev, GAMMA_REG) & 0x3f; } -inline static int em2820_contrast_set(struct em2820 *dev, s32 val) +inline static int em28xx_contrast_set(struct em28xx *dev, s32 val) { u8 tmp = (u8) val; - return em2820_write_regs(dev, YGAIN_REG, &tmp, 1); + return em28xx_write_regs(dev, YGAIN_REG, &tmp, 1); } -inline static int em2820_brightness_set(struct em2820 *dev, s32 val) +inline static int em28xx_brightness_set(struct em28xx *dev, s32 val) { u8 tmp = (u8) val; - return em2820_write_regs(dev, YOFFSET_REG, &tmp, 1); + return em28xx_write_regs(dev, YOFFSET_REG, &tmp, 1); } -inline static int em2820_saturation_set(struct em2820 *dev, s32 val) +inline static int em28xx_saturation_set(struct em28xx *dev, s32 val) { u8 tmp = (u8) val; - return em2820_write_regs(dev, UVGAIN_REG, &tmp, 1); + return em28xx_write_regs(dev, UVGAIN_REG, &tmp, 1); } -inline static int em2820_u_balance_set(struct em2820 *dev, s32 val) +inline static int em28xx_u_balance_set(struct em28xx *dev, s32 val) { u8 tmp = (u8) val; - return em2820_write_regs(dev, UOFFSET_REG, &tmp, 1); + return em28xx_write_regs(dev, UOFFSET_REG, &tmp, 1); } -inline static int em2820_v_balance_set(struct em2820 *dev, s32 val) +inline static int em28xx_v_balance_set(struct em28xx *dev, s32 val) { u8 tmp = (u8) val; - return em2820_write_regs(dev, VOFFSET_REG, &tmp, 1); + return em28xx_write_regs(dev, VOFFSET_REG, &tmp, 1); } -inline static int em2820_gamma_set(struct em2820 *dev, s32 val) +inline static int em28xx_gamma_set(struct em28xx *dev, s32 val) { u8 tmp = (u8) val; - return em2820_write_regs(dev, GAMMA_REG, &tmp, 1); + return em28xx_write_regs(dev, GAMMA_REG, &tmp, 1); } /*FIXME: maxw should be dependent of alt mode */ -inline static unsigned int norm_maxw(struct em2820 *dev) +inline static unsigned int norm_maxw(struct em28xx *dev) { switch(dev->model){ case (EM2820_BOARD_MSI_VOX_USB_2): return(640); @@ -502,7 +502,7 @@ inline static unsigned int norm_maxw(struct em2820 *dev) } } -inline static unsigned int norm_maxh(struct em2820 *dev) +inline static unsigned int norm_maxh(struct em28xx *dev) { switch(dev->model){ case (EM2820_BOARD_MSI_VOX_USB_2): return(480); -- cgit v1.2.3 From c3b3924ea0843d6956e5f87c3a4be09f460fe923 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:29 -0800 Subject: [PATCH] v4l: 887: i2c id h updated to reflect the newer drivers - I2c-id.h Updated to reflect the newer drivers. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/i2c-id.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index 815675f1e34..74abaecdb57 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -102,7 +102,11 @@ #define I2C_DRIVERID_TDA9874 66 /* TV sound decoder */ #define I2C_DRIVERID_SAA6752HS 67 /* MPEG2 encoder */ #define I2C_DRIVERID_TVEEPROM 68 /* TV EEPROM */ - +#define I2C_DRIVERID_WM8775 69 /* wm8775 audio processor */ +#define I2C_DRIVERID_CS53L32A 70 /* cs53l32a audio processor */ +#define I2C_DRIVERID_CX25840 71 /* cx2584x video encoder */ +#define I2C_DRIVERID_SAA7127 72 /* saa7124 video encoder */ +#define I2C_DRIVERID_SAA711X 73 /* saa711x video encoders */ #define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */ #define I2C_DRIVERID_EXP1 0xF1 @@ -193,6 +197,7 @@ #define I2C_HW_B_NVIDIA 0x01001c /* nvidia framebuffer driver */ #define I2C_HW_B_SAVAGE 0x01001d /* savage framebuffer driver */ #define I2C_HW_B_RADEON 0x01001e /* radeon framebuffer driver */ +#define I2C_HW_B_EM28XX 0x01001f /* em28xx video capture cards */ /* --- PCF 8584 based algorithms */ #define I2C_HW_P_LP 0x020000 /* Parallel port interface */ -- cgit v1.2.3 From 404b32fb3d93c17f994ad4b1d852ce4ca682ff8b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:29 -0800 Subject: [PATCH] v4l: 888: saa7113 renamed to saa711x - Saa7113 renamed to saa711x Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa711x.c | 206 ++++++++++++++++++++---------------------- 1 file changed, 100 insertions(+), 106 deletions(-) diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c index 85f3403f740..9aa8827de2c 100644 --- a/drivers/media/video/saa711x.c +++ b/drivers/media/video/saa711x.c @@ -1,16 +1,10 @@ /* - * saa7111 - Philips SAA7113A video decoder driver version 0.0.3 + * saa711x - Philips SAA711x video decoder driver version 0.0.1 * - * Copyright (C) 1998 Dave Perks + * To do: Now, it handles only saa7113/7114. Should be improved to + * handle all Philips saa711x devices. * - * Slight changes for video timing and attachment output by - * Wolfgang Scherr - * - * Changes by Ronald Bultje - * - moved over to linux>=2.4.x i2c protocol (1/1/2003) - * - * Changes by Michael Hunold - * - implemented DECODER_SET_GPIO, DECODER_INIT, DECODER_SET_VBI_BYPASS + * Based on saa7113 driver from Dave Perks * * 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 @@ -47,7 +41,7 @@ #include #include -MODULE_DESCRIPTION("Philips SAA7113 video decoder driver"); +MODULE_DESCRIPTION("Philips SAA711x video decoder driver"); MODULE_AUTHOR("Dave Perks, Jose Ignacio Gijon, Joerg Heckenbach, Mark McClelland, Dwaine Garden"); MODULE_LICENSE("GPL"); @@ -71,7 +65,7 @@ MODULE_PARM_DESC(debug, " Set the default Debug level. Default: 0 (Off) - (0-1) /* ----------------------------------------------------------------------- */ -struct saa7113 { +struct saa711x { unsigned char reg[32]; int norm; @@ -89,29 +83,29 @@ struct saa7113 { /* ----------------------------------------------------------------------- */ static inline int -saa7113_write (struct i2c_client *client, +saa711x_write (struct i2c_client *client, u8 reg, u8 value) { - struct saa7113 *decoder = i2c_get_clientdata(client); + struct saa711x *decoder = i2c_get_clientdata(client); decoder->reg[reg] = value; return i2c_smbus_write_byte_data(client, reg, value); } static int -saa7113_write_block (struct i2c_client *client, +saa711x_write_block (struct i2c_client *client, const u8 *data, unsigned int len) { int ret = -1; u8 reg; - /* the saa7113 has an autoincrement function, use it if + /* the saa711x has an autoincrement function, use it if * the adapter understands raw I2C */ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ - struct saa7113 *decoder = i2c_get_clientdata(client); + struct saa711x *decoder = i2c_get_clientdata(client); struct i2c_msg msg; u8 block_data[32]; @@ -136,7 +130,7 @@ saa7113_write_block (struct i2c_client *client, /* do some slow I2C emulation kind of thing */ while (len >= 2) { reg = *data++; - if ((ret = saa7113_write(client, reg, + if ((ret = saa711x_write(client, reg, *data++)) < 0) break; len -= 2; @@ -147,14 +141,14 @@ saa7113_write_block (struct i2c_client *client, } static int -saa7113_init_decoder (struct i2c_client *client, +saa711x_init_decoder (struct i2c_client *client, struct video_decoder_init *init) { - return saa7113_write_block(client, init->data, init->len); + return saa711x_write_block(client, init->data, init->len); } static inline int -saa7113_read (struct i2c_client *client, +saa711x_read (struct i2c_client *client, u8 reg) { return i2c_smbus_read_byte_data(client, reg); @@ -162,39 +156,39 @@ saa7113_read (struct i2c_client *client, /* ----------------------------------------------------------------------- */ -static const unsigned char saa7113_i2c_init[] = { - 0x00, 0x00, /* PH7113_CHIP_VERSION 00 - ID byte */ - 0x01, 0x08, /* PH7113_INCREMENT_DELAY - (1) (1) (1) (1) IDEL3 IDEL2 IDELL1 IDEL0 */ - 0x02, 0xc0, /* PH7113_ANALOG_INPUT_CONTR_1 - FUSE1 FUSE0 GUDL1 GUDL0 MODE3 MODE2 MODE1 MODE0 */ - 0x03, 0x23, /* PH7113_ANALOG_INPUT_CONTR_2 - (1) HLNRS VBSL WPOFF HOLDG GAFIX GAI28 GAI18 */ - 0x04, 0x00, /* PH7113_ANALOG_INPUT_CONTR_3 - GAI17 GAI16 GAI15 GAI14 GAI13 GAI12 GAI11 GAI10 */ - 0x05, 0x00, /* PH7113_ANALOG_INPUT_CONTR_4 - GAI27 GAI26 GAI25 GAI24 GAI23 GAI22 GAI21 GAI20 */ - 0x06, 0xeb, /* PH7113_HORIZONTAL_SYNC_START - HSB7 HSB6 HSB5 HSB4 HSB3 HSB2 HSB1 HSB0 */ - 0x07, 0xe0, /* PH7113_HORIZONTAL_SYNC_STOP - HSS7 HSS6 HSS5 HSS4 HSS3 HSS2 HSS1 HSS0 */ - 0x08, 0x88, /* PH7113_SYNC_CONTROL - AUFD FSEL FOET HTC1 HTC0 HPLL VNOI1 VNOI0 */ - 0x09, 0x00, /* PH7113_LUMINANCE_CONTROL - BYPS PREF BPSS1 BPSS0 VBLB UPTCV APER1 APER0 */ - 0x0a, 0x80, /* PH7113_LUMINANCE_BRIGHTNESS - BRIG7 BRIG6 BRIG5 BRIG4 BRIG3 BRIG2 BRIG1 BRIG0 */ - 0x0b, 0x47, /* PH7113_LUMINANCE_CONTRAST - CONT7 CONT6 CONT5 CONT4 CONT3 CONT2 CONT1 CONT0 */ - 0x0c, 0x40, /* PH7113_CHROMA_SATURATION - SATN7 SATN6 SATN5 SATN4 SATN3 SATN2 SATN1 SATN0 */ - 0x0d, 0x00, /* PH7113_CHROMA_HUE_CONTROL - HUEC7 HUEC6 HUEC5 HUEC4 HUEC3 HUEC2 HUEC1 HUEC0 */ - 0x0e, 0x01, /* PH7113_CHROMA_CONTROL - CDTO CSTD2 CSTD1 CSTD0 DCCF FCTC CHBW1 CHBW0 */ - 0x0f, 0xaa, /* PH7113_CHROMA_GAIN_CONTROL - ACGC CGAIN6 CGAIN5 CGAIN4 CGAIN3 CGAIN2 CGAIN1 CGAIN0 */ - 0x10, 0x00, /* PH7113_FORMAT_DELAY_CONTROL - OFTS1 OFTS0 HDEL1 HDEL0 VRLN YDEL2 YDEL1 YDEL0 */ - 0x11, 0x1C, /* PH7113_OUTPUT_CONTROL_1 - GPSW1 CM99 GPSW0 HLSEL OEYC OERT VIPB COLO */ - 0x12, 0x01, /* PH7113_OUTPUT_CONTROL_2 - RTSE13 RTSE12 RTSE11 RTSE10 RTSE03 RTSE02 RTSE01 RTSE00 */ - 0x13, 0x00, /* PH7113_OUTPUT_CONTROL_3 - ADLSB (1) (1) OLDSB FIDP (1) AOSL1 AOSL0 */ +static const unsigned char saa711x_i2c_init[] = { + 0x00, 0x00, /* PH711x_CHIP_VERSION 00 - ID byte */ + 0x01, 0x08, /* PH711x_INCREMENT_DELAY - (1) (1) (1) (1) IDEL3 IDEL2 IDELL1 IDEL0 */ + 0x02, 0xc0, /* PH711x_ANALOG_INPUT_CONTR_1 - FUSE1 FUSE0 GUDL1 GUDL0 MODE3 MODE2 MODE1 MODE0 */ + 0x03, 0x23, /* PH711x_ANALOG_INPUT_CONTR_2 - (1) HLNRS VBSL WPOFF HOLDG GAFIX GAI28 GAI18 */ + 0x04, 0x00, /* PH711x_ANALOG_INPUT_CONTR_3 - GAI17 GAI16 GAI15 GAI14 GAI13 GAI12 GAI11 GAI10 */ + 0x05, 0x00, /* PH711x_ANALOG_INPUT_CONTR_4 - GAI27 GAI26 GAI25 GAI24 GAI23 GAI22 GAI21 GAI20 */ + 0x06, 0xeb, /* PH711x_HORIZONTAL_SYNC_START - HSB7 HSB6 HSB5 HSB4 HSB3 HSB2 HSB1 HSB0 */ + 0x07, 0xe0, /* PH711x_HORIZONTAL_SYNC_STOP - HSS7 HSS6 HSS5 HSS4 HSS3 HSS2 HSS1 HSS0 */ + 0x08, 0x88, /* PH711x_SYNC_CONTROL - AUFD FSEL FOET HTC1 HTC0 HPLL VNOI1 VNOI0 */ + 0x09, 0x00, /* PH711x_LUMINANCE_CONTROL - BYPS PREF BPSS1 BPSS0 VBLB UPTCV APER1 APER0 */ + 0x0a, 0x80, /* PH711x_LUMINANCE_BRIGHTNESS - BRIG7 BRIG6 BRIG5 BRIG4 BRIG3 BRIG2 BRIG1 BRIG0 */ + 0x0b, 0x47, /* PH711x_LUMINANCE_CONTRAST - CONT7 CONT6 CONT5 CONT4 CONT3 CONT2 CONT1 CONT0 */ + 0x0c, 0x40, /* PH711x_CHROMA_SATURATION - SATN7 SATN6 SATN5 SATN4 SATN3 SATN2 SATN1 SATN0 */ + 0x0d, 0x00, /* PH711x_CHROMA_HUE_CONTROL - HUEC7 HUEC6 HUEC5 HUEC4 HUEC3 HUEC2 HUEC1 HUEC0 */ + 0x0e, 0x01, /* PH711x_CHROMA_CONTROL - CDTO CSTD2 CSTD1 CSTD0 DCCF FCTC CHBW1 CHBW0 */ + 0x0f, 0xaa, /* PH711x_CHROMA_GAIN_CONTROL - ACGC CGAIN6 CGAIN5 CGAIN4 CGAIN3 CGAIN2 CGAIN1 CGAIN0 */ + 0x10, 0x00, /* PH711x_FORMAT_DELAY_CONTROL - OFTS1 OFTS0 HDEL1 HDEL0 VRLN YDEL2 YDEL1 YDEL0 */ + 0x11, 0x1C, /* PH711x_OUTPUT_CONTROL_1 - GPSW1 CM99 GPSW0 HLSEL OEYC OERT VIPB COLO */ + 0x12, 0x01, /* PH711x_OUTPUT_CONTROL_2 - RTSE13 RTSE12 RTSE11 RTSE10 RTSE03 RTSE02 RTSE01 RTSE00 */ + 0x13, 0x00, /* PH711x_OUTPUT_CONTROL_3 - ADLSB (1) (1) OLDSB FIDP (1) AOSL1 AOSL0 */ 0x14, 0x00, /* RESERVED 14 - (1) (1) (1) (1) (1) (1) (1) (1) */ - 0x15, 0x00, /* PH7113_V_GATE1_START - VSTA7 VSTA6 VSTA5 VSTA4 VSTA3 VSTA2 VSTA1 VSTA0 */ - 0x16, 0x00, /* PH7113_V_GATE1_STOP - VSTO7 VSTO6 VSTO5 VSTO4 VSTO3 VSTO2 VSTO1 VSTO0 */ - 0x17, 0x00, /* PH7113_V_GATE1_MSB - (1) (1) (1) (1) (1) (1) VSTO8 VSTA8 */ + 0x15, 0x00, /* PH711x_V_GATE1_START - VSTA7 VSTA6 VSTA5 VSTA4 VSTA3 VSTA2 VSTA1 VSTA0 */ + 0x16, 0x00, /* PH711x_V_GATE1_STOP - VSTO7 VSTO6 VSTO5 VSTO4 VSTO3 VSTO2 VSTO1 VSTO0 */ + 0x17, 0x00, /* PH711x_V_GATE1_MSB - (1) (1) (1) (1) (1) (1) VSTO8 VSTA8 */ }; static int -saa7113_command (struct i2c_client *client, +saa711x_command (struct i2c_client *client, unsigned int cmd, void *arg) { - struct saa7113 *decoder = i2c_get_clientdata(client); + struct saa711x *decoder = i2c_get_clientdata(client); switch (cmd) { @@ -203,12 +197,12 @@ saa7113_command (struct i2c_client *client, { struct video_decoder_init *init = arg; if (NULL != init) - return saa7113_init_decoder(client, init); + return saa711x_init_decoder(client, init); else { struct video_decoder_init vdi; - vdi.data = saa7113_i2c_init; - vdi.len = sizeof(saa7113_i2c_init); - return saa7113_init_decoder(client, &vdi); + vdi.data = saa711x_i2c_init; + vdi.len = sizeof(saa711x_i2c_init); + return saa711x_init_decoder(client, &vdi); } } @@ -222,7 +216,7 @@ saa7113_command (struct i2c_client *client, printk(KERN_DEBUG "%s: %03x", I2C_NAME(client), i); for (j = 0; j < 16; ++j) { printk(" %02x", - saa7113_read(client, i + j)); + saa711x_read(client, i + j)); } printk("\n"); } @@ -249,7 +243,7 @@ saa7113_command (struct i2c_client *client, int status; int res; - status = saa7113_read(client, 0x1f); + status = saa711x_read(client, 0x1f); dprintk(1, KERN_DEBUG "%s status: 0x%02x\n", I2C_NAME(client), status); res = 0; @@ -286,10 +280,10 @@ saa7113_command (struct i2c_client *client, { int *iarg = arg; if (0 != *iarg) { - saa7113_write(client, 0x11, + saa711x_write(client, 0x11, (decoder->reg[0x11] | 0x80)); } else { - saa7113_write(client, 0x11, + saa711x_write(client, 0x11, (decoder->reg[0x11] & 0x7f)); } break; @@ -299,10 +293,10 @@ saa7113_command (struct i2c_client *client, { int *iarg = arg; if (0 != *iarg) { - saa7113_write(client, 0x13, + saa711x_write(client, 0x13, (decoder->reg[0x13] & 0xf0) | 0x0a); } else { - saa7113_write(client, 0x13, + saa711x_write(client, 0x13, (decoder->reg[0x13] & 0xf0)); } break; @@ -315,30 +309,30 @@ saa7113_command (struct i2c_client *client, switch (*iarg) { case VIDEO_MODE_NTSC: - saa7113_write(client, 0x08, + saa711x_write(client, 0x08, (decoder->reg[0x08] & 0x3f) | 0x40); - saa7113_write(client, 0x0e, + saa711x_write(client, 0x0e, (decoder->reg[0x0e] & 0x8f)); break; case VIDEO_MODE_PAL: - saa7113_write(client, 0x08, + saa711x_write(client, 0x08, (decoder->reg[0x08] & 0x3f) | 0x00); - saa7113_write(client, 0x0e, + saa711x_write(client, 0x0e, (decoder->reg[0x0e] & 0x8f)); break; case VIDEO_MODE_SECAM: - saa7113_write(client, 0x08, + saa711x_write(client, 0x08, (decoder->reg[0x0e] & 0x3f) | 0x00); - saa7113_write(client, 0x0e, + saa711x_write(client, 0x0e, (decoder->reg[0x0e] & 0x8f) | 0x50); break; case VIDEO_MODE_AUTO: - saa7113_write(client, 0x08, + saa711x_write(client, 0x08, (decoder->reg[0x08] & 0x3f) | 0x80); - saa7113_write(client, 0x0e, + saa711x_write(client, 0x0e, (decoder->reg[0x0e] & 0x8f)); break; @@ -359,10 +353,10 @@ saa7113_command (struct i2c_client *client, if (decoder->input != *iarg) { decoder->input = *iarg; /* select mode */ - saa7113_write(client, 0x02, + saa711x_write(client, 0x02, (decoder->reg[0x02] & 0xf0) | decoder->input); /* bypass chrominance trap for modes 4..7 */ - saa7113_write(client, 0x09, + saa711x_write(client, 0x09, (decoder->reg[0x09] & 0x7f) | ((decoder->input > 3) ? 0x80 : 0)); } } @@ -398,22 +392,22 @@ saa7113_command (struct i2c_client *client, */ if (decoder->enable) { - saa7113_write(client, 0x02, + saa711x_write(client, 0x02, (decoder-> reg[0x02] & 0xf8) | decoder->input); - saa7113_write(client, 0x08, + saa711x_write(client, 0x08, (decoder->reg[0x08] & 0xfb)); - saa7113_write(client, 0x11, + saa711x_write(client, 0x11, (decoder-> reg[0x11] & 0xf3) | 0x0c); } else { - saa7113_write(client, 0x02, + saa711x_write(client, 0x02, (decoder->reg[0x02] & 0xf8)); - saa7113_write(client, 0x08, + saa711x_write(client, 0x08, (decoder-> reg[0x08] & 0xfb) | 0x04); - saa7113_write(client, 0x11, + saa711x_write(client, 0x11, (decoder->reg[0x11] & 0xf3)); } } @@ -427,23 +421,23 @@ saa7113_command (struct i2c_client *client, if (decoder->bright != pic->brightness) { /* We want 0 to 255 we get 0-65535 */ decoder->bright = pic->brightness; - saa7113_write(client, 0x0a, decoder->bright >> 8); + saa711x_write(client, 0x0a, decoder->bright >> 8); } if (decoder->contrast != pic->contrast) { /* We want 0 to 127 we get 0-65535 */ decoder->contrast = pic->contrast; - saa7113_write(client, 0x0b, + saa711x_write(client, 0x0b, decoder->contrast >> 9); } if (decoder->sat != pic->colour) { /* We want 0 to 127 we get 0-65535 */ decoder->sat = pic->colour; - saa7113_write(client, 0x0c, decoder->sat >> 9); + saa711x_write(client, 0x0c, decoder->sat >> 9); } if (decoder->hue != pic->hue) { /* We want -128 to 127 we get 0-65535 */ decoder->hue = pic->hue; - saa7113_write(client, 0x0d, + saa711x_write(client, 0x0d, (decoder->hue - 32768) >> 8); } } @@ -473,21 +467,21 @@ static unsigned short normal_i2c[] = { I2C_CLIENT_INSMOD; -static struct i2c_driver i2c_driver_saa7113; +static struct i2c_driver i2c_driver_saa711x; static int -saa7113_detect_client (struct i2c_adapter *adapter, +saa711x_detect_client (struct i2c_adapter *adapter, int address, int kind) { int i; struct i2c_client *client; - struct saa7113 *decoder; + struct saa711x *decoder; struct video_decoder_init vdi; dprintk(1, KERN_INFO - "saa7113.c: detecting saa7113 client on address 0x%x\n", + "saa711x.c: detecting saa711x client on address 0x%x\n", address << 1); /* Check if the adapter supports the needed features */ @@ -500,15 +494,15 @@ saa7113_detect_client (struct i2c_adapter *adapter, memset(client, 0, sizeof(struct i2c_client)); client->addr = address; client->adapter = adapter; - client->driver = &i2c_driver_saa7113; + client->driver = &i2c_driver_saa711x; client->flags = I2C_CLIENT_ALLOW_USE; - strlcpy(I2C_NAME(client), "saa7113", sizeof(I2C_NAME(client))); - decoder = kmalloc(sizeof(struct saa7113), GFP_KERNEL); + strlcpy(I2C_NAME(client), "saa711x", sizeof(I2C_NAME(client))); + decoder = kmalloc(sizeof(struct saa711x), GFP_KERNEL); if (decoder == NULL) { kfree(client); return -ENOMEM; } - memset(decoder, 0, sizeof(struct saa7113)); + memset(decoder, 0, sizeof(struct saa711x)); decoder->norm = VIDEO_MODE_NTSC; decoder->input = 0; decoder->enable = 1; @@ -525,9 +519,9 @@ saa7113_detect_client (struct i2c_adapter *adapter, return i; } - vdi.data = saa7113_i2c_init; - vdi.len = sizeof(saa7113_i2c_init); - i = saa7113_init_decoder(client, &vdi); + vdi.data = saa711x_i2c_init; + vdi.len = sizeof(saa711x_i2c_init); + i = saa711x_init_decoder(client, &vdi); if (i < 0) { dprintk(1, KERN_ERR "%s_attach error: init status %d\n", I2C_NAME(client), i); @@ -535,7 +529,7 @@ saa7113_detect_client (struct i2c_adapter *adapter, dprintk(1, KERN_INFO "%s_attach: chip version %x at address 0x%x\n", - I2C_NAME(client), saa7113_read(client, 0x00) >> 4, + I2C_NAME(client), saa711x_read(client, 0x00) >> 4, client->addr << 1); } @@ -543,19 +537,19 @@ saa7113_detect_client (struct i2c_adapter *adapter, } static int -saa7113_attach_adapter (struct i2c_adapter *adapter) +saa711x_attach_adapter (struct i2c_adapter *adapter) { dprintk(1, KERN_INFO - "saa7113.c: starting probe for adapter %s (0x%x)\n", + "saa711x.c: starting probe for adapter %s (0x%x)\n", I2C_NAME(adapter), adapter->id); - return i2c_probe(adapter, &addr_data, &saa7113_detect_client); + return i2c_probe(adapter, &addr_data, &saa711x_detect_client); } static int -saa7113_detach_client (struct i2c_client *client) +saa711x_detach_client (struct i2c_client *client) { - struct saa7113 *decoder = i2c_get_clientdata(client); + struct saa711x *decoder = i2c_get_clientdata(client); int err; err = i2c_detach_client(client); @@ -571,29 +565,29 @@ saa7113_detach_client (struct i2c_client *client) /* ----------------------------------------------------------------------- */ -static struct i2c_driver i2c_driver_saa7113 = { +static struct i2c_driver i2c_driver_saa711x = { .owner = THIS_MODULE, - .name = "saa7113", + .name = "saa711x", - .id = I2C_DRIVERID_SAA7113, + .id = I2C_DRIVERID_SAA711X, .flags = I2C_DF_NOTIFY, - .attach_adapter = saa7113_attach_adapter, - .detach_client = saa7113_detach_client, - .command = saa7113_command, + .attach_adapter = saa711x_attach_adapter, + .detach_client = saa711x_detach_client, + .command = saa711x_command, }; static int __init -saa7113_init (void) +saa711x_init (void) { - return i2c_add_driver(&i2c_driver_saa7113); + return i2c_add_driver(&i2c_driver_saa711x); } static void __exit -saa7113_exit (void) +saa711x_exit (void) { - i2c_del_driver(&i2c_driver_saa7113); + i2c_del_driver(&i2c_driver_saa711x); } -module_init(saa7113_init); -module_exit(saa7113_exit); +module_init(saa711x_init); +module_exit(saa711x_exit); -- cgit v1.2.3 From 15871a2905b84d6dba9013dbcbd9c79ace694ffb Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:38:30 -0800 Subject: [PATCH] v4l: 889: add em28xx to kernel build - Add em28xx to kernel build. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/Kconfig | 2 ++ drivers/media/video/Makefile | 1 + drivers/media/video/em28xx/Kconfig | 12 ++++++++++++ drivers/media/video/em28xx/Makefile | 7 +++++++ 4 files changed, 22 insertions(+) create mode 100644 drivers/media/video/em28xx/Kconfig create mode 100644 drivers/media/video/em28xx/Makefile diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index f3b077ec0c3..199b0118885 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -306,6 +306,8 @@ config VIDEO_HEXIUM_GEMINI source "drivers/media/video/cx88/Kconfig" +source "drivers/media/video/em28xx/Kconfig" + config VIDEO_OVCAMCHIP tristate "OmniVision Camera Chip support" depends on VIDEO_DEV && I2C diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 046b82de928..123c0a6ed20 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o obj-$(CONFIG_VIDEO_MEYE) += meye.o obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ obj-$(CONFIG_VIDEO_CX88) += cx88/ +obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ obj-$(CONFIG_VIDEO_MXB) += saa7111.o tuner.o tda9840.o tea6415c.o tea6420.o mxb.o obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig new file mode 100644 index 00000000000..46763be711f --- /dev/null +++ b/drivers/media/video/em28xx/Kconfig @@ -0,0 +1,12 @@ +config VIDEO_EM28XX + tristate "Empia EM2800/EM2820/2840 USB video capture support" + depends on VIDEO_DEV && USB && I2C + select VIDEO_BUF + select VIDEO_TUNER + select VIDEO_TVEEPROM + select VIDEO_IR + ---help--- + This is a video4linux driver for Empia 28xx based TV cards. + + To compile this driver as a module, choose M here: the + module will be called em28xx diff --git a/drivers/media/video/em28xx/Makefile b/drivers/media/video/em28xx/Makefile new file mode 100644 index 00000000000..573d2b87844 --- /dev/null +++ b/drivers/media/video/em28xx/Makefile @@ -0,0 +1,7 @@ +em28xx-objs := em28xx-video.o em28xx-i2c.o em28xx-cards.o em28xx-core.o \ + em28xx-input.o + +obj-$(CONFIG_EM28XX) += em28xx.o +obj-$(CONFIG_EM28XX) += saa711x.o tvp5150.o + +EXTRA_CFLAGS += -I$(src)/.. -- cgit v1.2.3 From c2e0b62e050374ddbf3221e7b78e1d0f26e148cb Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:38:31 -0800 Subject: [PATCH] v4l: 890: fixed typo - Fixed typo. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index 46763be711f..885fd017008 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig @@ -1,5 +1,5 @@ config VIDEO_EM28XX - tristate "Empia EM2800/EM2820/2840 USB video capture support" + tristate "Empia EM2800/2820/2840 USB video capture support" depends on VIDEO_DEV && USB && I2C select VIDEO_BUF select VIDEO_TUNER -- cgit v1.2.3 From 2ea55ad3897d8abac07435190c851f804433801f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:38:31 -0800 Subject: [PATCH] v4l: 891: change config em28xx to config video em28xx - Change CONFIG_EM28XX to CONFIG_VIDEO_EM28XX Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/em28xx/Makefile b/drivers/media/video/em28xx/Makefile index 573d2b87844..a5ea678b8c2 100644 --- a/drivers/media/video/em28xx/Makefile +++ b/drivers/media/video/em28xx/Makefile @@ -1,7 +1,7 @@ em28xx-objs := em28xx-video.o em28xx-i2c.o em28xx-cards.o em28xx-core.o \ em28xx-input.o -obj-$(CONFIG_EM28XX) += em28xx.o -obj-$(CONFIG_EM28XX) += saa711x.o tvp5150.o +obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o +obj-$(CONFIG_VIDEO_EM28XX) += saa711x.o tvp5150.o EXTRA_CFLAGS += -I$(src)/.. -- cgit v1.2.3 From d0fcdd7815e26f2e4a4ad239e2b464402a185f66 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:38:32 -0800 Subject: [PATCH] v4l: 892: correct nicam audio settings to match dscaler - Correct nicam audio settings to match dscaler Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/cx88-tvaudio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index 4ca1128bc76..7815f332062 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c @@ -321,8 +321,8 @@ static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode) {AUD_DEEMPHNUMER2_R, 0x0003023e}, {AUD_DEEMPHDENOM1_R, 0x0000f3d0}, {AUD_DEEMPHDENOM2_R, 0x00000000}, + {AUD_PDF_DDS_CNST_BYTE2, 0x06}, {AUD_PDF_DDS_CNST_BYTE1, 0x82}, - {AUD_PDF_DDS_CNST_BYTE0, 0x16}, {AUD_QAM_MODE, 0x05}, { /* end of list */ }, }; -- cgit v1.2.3 From 291d1d7356a2cf1da4934a06c4a4e3bca440fbc6 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Tue, 8 Nov 2005 21:38:33 -0800 Subject: [PATCH] v4l: 893: rollback recent i2c change to solve tuner detection breakage - Rollback recent i2c change to solve tuner detection breakage Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bttv-i2c.c | 22 +++++++++++++--------- drivers/media/video/tuner-core.c | 4 ++-- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c index aaabef26105..1b3e0a76951 100644 --- a/drivers/media/video/bttv-i2c.c +++ b/drivers/media/video/bttv-i2c.c @@ -291,10 +291,12 @@ static struct i2c_adapter bttv_i2c_adap_hw_template = { static int attach_inform(struct i2c_client *client) { struct bttv *btv = i2c_get_adapdata(client->adapter); - int radio_addr=ADDR_UNSET; + int addr=ADDR_UNSET; + + + if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr) + addr = bttv_tvcards[btv->c.type].tuner_addr; - if (ADDR_UNSET != bttv_tvcards[btv->c.type].radio_addr) - radio_addr = bttv_tvcards[btv->c.type].radio_addr; if (bttv_debug) printk(KERN_DEBUG "bttv%d: %s i2c attach [addr=0x%x,client=%s]\n", @@ -305,14 +307,16 @@ static int attach_inform(struct i2c_client *client) if (btv->tuner_type != UNSET) { struct tuner_setup tun_setup; - struct tuner *t = i2c_get_clientdata(client); - if (t->type != UNSET && t->mode_mask == T_RADIO) { - tun_setup.type = t->type; - tun_setup.mode_mask = T_RADIO; - tun_setup.addr = radio_addr; - client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup); + if ((addr==ADDR_UNSET) || + (addr==client->addr)) { + + tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV | T_RADIO; + tun_setup.type = btv->tuner_type; + tun_setup.addr = addr; + bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup); } + } return 0; diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 3fde4f90425..73c4041c35d 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -222,9 +222,9 @@ static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup) { struct tuner *t = i2c_get_clientdata(c); - if ((tun_setup->addr == ADDR_UNSET && + if ( t->type == UNSET && ((tun_setup->addr == ADDR_UNSET && (t->mode_mask & tun_setup->mode_mask)) || - tun_setup->addr == c->addr) { + tun_setup->addr == c->addr)) { set_type(c, tun_setup->type, tun_setup->mode_mask); } } -- cgit v1.2.3 From 6e45f5d8d27cb619cf7e94c78a67fb61a4f3dd5e Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Tue, 8 Nov 2005 21:38:34 -0800 Subject: [PATCH] v4l: 894: work around to allow hybrid dvb card to autoload the tda9887 - Work-around to allow hybrid DVB card to autoload the tda9887 Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bttv-cards.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index d81672acdaa..3413bace443 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -3407,6 +3407,9 @@ void __devinit bttv_init_card2(struct bttv *btv) if (0 == tda9887 && 0 == bttv_tvcards[btv->c.type].has_dvb && bttv_I2CRead(btv, I2C_TDA9887, "TDA9887") >=0) tda9887 = 1; + /* Hybrid DVB card, DOES have a tda9887 */ + if (btv->c.type == BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE) + tda9887 = 1; if((btv->tuner_type == TUNER_PHILIPS_FM1216ME_MK3) || (btv->tuner_type == TUNER_PHILIPS_FM1236_MK3) || (btv->tuner_type == TUNER_PHILIPS_FM1256_IH3) || -- cgit v1.2.3 From 7418f3462aedf6fb962a44c8fa7259dd94530ff5 Mon Sep 17 00:00:00 2001 From: Lubomir Bulej Date: Tue, 8 Nov 2005 21:38:34 -0800 Subject: [PATCH] v4l: 895: new avermedia 303 card without radio - New Avermedia 303 card (without radio). Signed-off-by: Lubomir Bulej Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.cx88 | 1 + drivers/media/video/bttv-i2c.c | 10 ++++----- drivers/media/video/cx88/cx88-cards.c | 38 +++++++++++++++++++++++++++++++-- drivers/media/video/cx88/cx88.h | 3 ++- 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 12e9e393868..a1017d1a85d 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -34,3 +34,4 @@ 33 -> Kworld V-Stream Xpert DVD 34 -> ATI HDTV Wonder [1002:a101] 35 -> WinFast DTV1000-T [107d:665f] + 36 -> AVerTV 303 (M126) [1461:000a] diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c index 1b3e0a76951..77619eb131f 100644 --- a/drivers/media/video/bttv-i2c.c +++ b/drivers/media/video/bttv-i2c.c @@ -294,8 +294,8 @@ static int attach_inform(struct i2c_client *client) int addr=ADDR_UNSET; - if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr) - addr = bttv_tvcards[btv->c.type].tuner_addr; + if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr) + addr = bttv_tvcards[btv->c.type].tuner_addr; if (bttv_debug) @@ -311,10 +311,10 @@ static int attach_inform(struct i2c_client *client) if ((addr==ADDR_UNSET) || (addr==client->addr)) { - tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV | T_RADIO; - tun_setup.type = btv->tuner_type; + tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV | T_RADIO; + tun_setup.type = btv->tuner_type; tun_setup.addr = addr; - bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup); + bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup); } } diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index f20984eb553..f2268631b7c 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -174,7 +174,7 @@ struct cx88_board cx88_boards[] = { .gpio3 = 0x02000000, }, }, - [CX88_BOARD_AVERTV_303] = { + [CX88_BOARD_AVERTV_STUDIO_303] = { .name = "AverTV Studio 303 (M126)", .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, .radio_type = UNSET, @@ -865,6 +865,36 @@ struct cx88_board cx88_boards[] = { }}, .dvb = 1, }, + [CX88_BOARD_AVERTV_303] = { + .name = "AVerTV 303 (M126)", + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x00ff, + .gpio1 = 0xe09f, + .gpio2 = 0x0010, + .gpio3 = 0x0000, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x00ff, + .gpio1 = 0xe05f, + .gpio2 = 0x0010, + .gpio3 = 0x0000, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x00ff, + .gpio1 = 0xe05f, + .gpio2 = 0x0010, + .gpio3 = 0x0000, + }}, + }, }; const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); @@ -915,7 +945,7 @@ struct cx88_subid cx88_subids[] = { },{ .subvendor = 0x1461, .subdevice = 0x000b, - .card = CX88_BOARD_AVERTV_303, + .card = CX88_BOARD_AVERTV_STUDIO_303, },{ .subvendor = 0x1462, .subdevice = 0x8606, @@ -1008,6 +1038,10 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x107d, .subdevice = 0x665f, .card = CX88_BOARD_WINFAST_DTV1000, + },{ + .subvendor = 0x1461, + .subdevice = 0x000a, + .card = CX88_BOARD_AVERTV_303, }, }; const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index baeae1ac992..b19d3a9e229 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -148,7 +148,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_PIXELVIEW 3 #define CX88_BOARD_ATI_WONDER_PRO 4 #define CX88_BOARD_WINFAST2000XP_EXPERT 5 -#define CX88_BOARD_AVERTV_303 6 +#define CX88_BOARD_AVERTV_STUDIO_303 6 #define CX88_BOARD_MSI_TVANYWHERE_MASTER 7 #define CX88_BOARD_WINFAST_DV2000 8 #define CX88_BOARD_LEADTEK_PVR2000 9 @@ -178,6 +178,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD 33 #define CX88_BOARD_ATI_HDTVWONDER 34 #define CX88_BOARD_WINFAST_DTV1000 35 +#define CX88_BOARD_AVERTV_303 36 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- cgit v1.2.3 From 6cffcc23d2837295604033d884d1ad259d0aed57 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:38:36 -0800 Subject: [PATCH] v4l: 896: rename BTTV_FOO --> BTTV_BOARD_FOO Adapt to changes in v4l tree: rename BTTV_FOO --> BTTV_BOARD_FOO Signed-off-by: Michael Krufky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 48 ++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index 05554e3949d..2e398090cf6 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -600,8 +600,8 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) struct dst_state* state = NULL; switch(type) { -#ifdef BTTV_DVICO_DVBT_LITE - case BTTV_DVICO_DVBT_LITE: +#ifdef BTTV_BOARD_DVICO_DVBT_LITE + case BTTV_BOARD_DVICO_DVBT_LITE: card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter); if (card->fe != NULL) { card->fe->ops->info.frequency_min = 174000000; @@ -610,8 +610,8 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) break; #endif -#ifdef BTTV_DVICO_FUSIONHDTV_5_LITE - case BTTV_DVICO_FUSIONHDTV_5_LITE: +#ifdef BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE + case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE: lgdt330x_reset(card); card->fe = lgdt330x_attach(&tdvs_tua6034_config, card->i2c_adapter); if (card->fe != NULL) @@ -619,10 +619,10 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) break; #endif -#ifdef BTTV_TWINHAN_VP3021 - case BTTV_TWINHAN_VP3021: +#ifdef BTTV_BOARD_TWINHAN_VP3021 + case BTTV_BOARD_TWINHAN_VP3021: #else - case BTTV_NEBULA_DIGITV: + case BTTV_BOARD_NEBULA_DIGITV: #endif /* * It is possible to determine the correct frontend using the I2C bus (see the Nebula SDK); @@ -645,11 +645,11 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) dprintk ("dvb_bt8xx: an mt352 was detected on your digitv card\n"); break; - case BTTV_AVDVBT_761: + case BTTV_BOARD_AVDVBT_761: card->fe = sp887x_attach(µtune_mt7202dtf_config, card->i2c_adapter); break; - case BTTV_AVDVBT_771: + case BTTV_BOARD_AVDVBT_771: card->fe = mt352_attach(&advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter); if (card->fe != NULL) { card->fe->ops->info.frequency_min = 174000000; @@ -657,7 +657,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) } break; - case BTTV_TWINHAN_DST: + case BTTV_BOARD_TWINHAN_DST: /* DST is not a frontend driver !!! */ state = (struct dst_state *) kmalloc(sizeof (struct dst_state), GFP_KERNEL); /* Setup the Card */ @@ -678,11 +678,11 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) ret = dst_ca_attach(state, &card->dvb_adapter); break; - case BTTV_PINNACLESAT: + case BTTV_BOARD_PINNACLESAT: card->fe = cx24110_attach(&pctvsat_config, card->i2c_adapter); break; - case BTTV_PC_HDTV: + case BTTV_BOARD_PC_HDTV: card->fe = or51211_attach(&or51211_config, card->i2c_adapter); break; } @@ -804,7 +804,7 @@ static int dvb_bt8xx_probe(struct device *dev) card->i2c_adapter = &sub->core->i2c_adap; switch(sub->core->type) { - case BTTV_PINNACLESAT: + case BTTV_BOARD_PINNACLESAT: card->gpio_mode = 0x0400c060; /* should be: BT878_A_GAIN=0,BT878_A_PWRDN,BT878_DA_DPM,BT878_DA_SBR, BT878_DA_IOM=1,BT878_DA_APP to enable serial highspeed mode. */ @@ -812,8 +812,8 @@ static int dvb_bt8xx_probe(struct device *dev) card->irq_err_ignore = 0; break; -#ifdef BTTV_DVICO_DVBT_LITE - case BTTV_DVICO_DVBT_LITE: +#ifdef BTTV_BOARD_DVICO_DVBT_LITE + case BTTV_BOARD_DVICO_DVBT_LITE: #endif card->gpio_mode = 0x0400C060; card->op_sync_orin = 0; @@ -823,34 +823,34 @@ static int dvb_bt8xx_probe(struct device *dev) * DA_APP(parallel) */ break; -#ifdef BTTV_DVICO_FUSIONHDTV_5_LITE - case BTTV_DVICO_FUSIONHDTV_5_LITE: +#ifdef BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE + case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE: #endif card->gpio_mode = 0x0400c060; card->op_sync_orin = BT878_RISC_SYNC_MASK; card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR; break; -#ifdef BTTV_TWINHAN_VP3021 - case BTTV_TWINHAN_VP3021: +#ifdef BTTV_BOARD_TWINHAN_VP3021 + case BTTV_BOARD_TWINHAN_VP3021: #else - case BTTV_NEBULA_DIGITV: + case BTTV_BOARD_NEBULA_DIGITV: #endif - case BTTV_AVDVBT_761: + case BTTV_BOARD_AVDVBT_761: card->gpio_mode = (1 << 26) | (1 << 14) | (1 << 5); card->op_sync_orin = 0; card->irq_err_ignore = 0; /* A_PWRDN DA_SBR DA_APP (high speed serial) */ break; - case BTTV_AVDVBT_771: //case 0x07711461: + case BTTV_BOARD_AVDVBT_771: //case 0x07711461: card->gpio_mode = 0x0400402B; card->op_sync_orin = BT878_RISC_SYNC_MASK; card->irq_err_ignore = 0; /* A_PWRDN DA_SBR DA_APP[0] PKTP=10 RISC_ENABLE FIFO_ENABLE*/ break; - case BTTV_TWINHAN_DST: + case BTTV_BOARD_TWINHAN_DST: card->gpio_mode = 0x2204f2c; card->op_sync_orin = BT878_RISC_SYNC_MASK; card->irq_err_ignore = BT878_APABORT | BT878_ARIPERR | @@ -868,7 +868,7 @@ static int dvb_bt8xx_probe(struct device *dev) * RISC+FIFO ENABLE */ break; - case BTTV_PC_HDTV: + case BTTV_BOARD_PC_HDTV: card->gpio_mode = 0x0100EC7B; card->op_sync_orin = 0; card->irq_err_ignore = 0; -- cgit v1.2.3 From ad07d93ae7884a72a293eb4efb61a872f109ebd5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:36 -0800 Subject: [PATCH] v4l: 897: saa7146 fix - Fixing headers to compile cleanly. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-video.c | 1 - include/media/saa7146_vv.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index f6acce82079..5b09f52dd66 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -28,7 +28,6 @@ #include #include #include -#include #include "em28xx.h" #include diff --git a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h index f3aa24f8131..64691753721 100644 --- a/include/media/saa7146_vv.h +++ b/include/media/saa7146_vv.h @@ -1,7 +1,7 @@ #ifndef __SAA7146_VV__ #define __SAA7146_VV__ -#include +#include #include #include -- cgit v1.2.3 From b296fc6017e0ec6bc6cd0f40275f268035eb6b8b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:37 -0800 Subject: [PATCH] v4l: 898: em2820 i2c fix - Miscelaneous fixes for em28xx - I2C hardware named changed to wright value. - utsname included to em28xx-video.c - Makefile fixes. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/Makefile | 1 + drivers/media/video/em28xx/Makefile | 1 - drivers/media/video/em28xx/em28xx-video.c | 1 + drivers/media/video/ir-kbd-i2c.c | 6 +++--- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 123c0a6ed20..351ce5be2ad 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_VIDEO_MEYE) += meye.o obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ obj-$(CONFIG_VIDEO_CX88) += cx88/ obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ +obj-$(CONFIG_VIDEO_EM28XX) += saa711x.o tvp5150.o obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ obj-$(CONFIG_VIDEO_MXB) += saa7111.o tuner.o tda9840.o tea6415c.o tea6420.o mxb.o obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o diff --git a/drivers/media/video/em28xx/Makefile b/drivers/media/video/em28xx/Makefile index a5ea678b8c2..da457a05b0d 100644 --- a/drivers/media/video/em28xx/Makefile +++ b/drivers/media/video/em28xx/Makefile @@ -2,6 +2,5 @@ em28xx-objs := em28xx-video.o em28xx-i2c.o em28xx-cards.o em28xx-core.o \ em28xx-input.o obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o -obj-$(CONFIG_VIDEO_EM28XX) += saa711x.o tvp5150.o EXTRA_CFLAGS += -I$(src)/.. diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 5b09f52dd66..54f21242ccb 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "em28xx.h" diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index bdb3ba55136..0085567a142 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -373,7 +373,7 @@ static int ir_probe(struct i2c_adapter *adap) static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1}; static const int probe_saa7134[] = { 0x7a, 0x47, -1 }; - static const int probe_em2820[] = { 0x30, 0x47, -1 }; + static const int probe_em28XX[] = { 0x30, 0x47, -1 }; const int *probe = NULL; struct i2c_client c; unsigned char buf; @@ -386,8 +386,8 @@ static int ir_probe(struct i2c_adapter *adap) case I2C_HW_SAA7134: probe = probe_saa7134; break; - case I2C_HW_B_EM2820: - probe = probe_em2820; + case I2C_HW_B_EM28XX: + probe = probe_em28XX; break; } if (NULL == probe) -- cgit v1.2.3 From 22ae2550f65bc322e6bdeff9d3948bbb5e0a9b67 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:38 -0800 Subject: [PATCH] v4l: 899: remove media id.h - Removed media id.h file Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/media/id.h | 50 -------------------------------------------------- 1 file changed, 50 deletions(-) delete mode 100644 include/media/id.h diff --git a/include/media/id.h b/include/media/id.h deleted file mode 100644 index 4f58d73e702..00000000000 --- a/include/media/id.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - */ - -/* FIXME: this temporarely, until these are included in linux/i2c-id.h */ - -/* drivers */ -#ifndef I2C_DRIVERID_TVMIXER -# define I2C_DRIVERID_TVMIXER I2C_DRIVERID_EXP0 -#endif -#ifndef I2C_DRIVERID_TVAUDIO -# define I2C_DRIVERID_TVAUDIO I2C_DRIVERID_EXP1 -#endif - -/* chips */ -#ifndef I2C_DRIVERID_DPL3518 -# define I2C_DRIVERID_DPL3518 I2C_DRIVERID_EXP2 -#endif -#ifndef I2C_DRIVERID_TDA9873 -# define I2C_DRIVERID_TDA9873 I2C_DRIVERID_EXP3 -#endif -#ifndef I2C_DRIVERID_TDA9875 -# define I2C_DRIVERID_TDA9875 I2C_DRIVERID_EXP0+4 -#endif -#ifndef I2C_DRIVERID_PIC16C54_PV951 -# define I2C_DRIVERID_PIC16C54_PV951 I2C_DRIVERID_EXP0+5 -#endif -#ifndef I2C_DRIVERID_TDA7432 -# define I2C_DRIVERID_TDA7432 I2C_DRIVERID_EXP0+6 -#endif -#ifndef I2C_DRIVERID_TDA9874 -# define I2C_DRIVERID_TDA9874 I2C_DRIVERID_EXP0+7 -#endif -#ifndef I2C_DRIVERID_SAA6752HS -# define I2C_DRIVERID_SAA6752HS I2C_DRIVERID_EXP0+8 -#endif -#ifndef I2C_DRIVERID_WM8775 -#define I2C_DRIVERID_WM8775 I2C_DRIVERID_EXP0+9 -#endif -#ifndef I2C_DRIVERID_CS53L32A -#define I2C_DRIVERID_CS53L32A I2C_DRIVERID_EXP0+10 -#endif -#ifndef I2C_DRIVERID_CX25840 -#define I2C_DRIVERID_CX25840 I2C_DRIVERID_EXP0+11 -#endif -#ifndef I2C_DRIVERID_SAA7115 -#define I2C_DRIVERID_SAA7115 I2C_DRIVERID_EXP0+12 -#endif -#ifndef I2C_DRIVERID_SAA7127 -#define I2C_DRIVERID_SAA7127 I2C_DRIVERID_EXP0+13 -#endif -- cgit v1.2.3 From 4ac95af9a0bdc33f18e6a7532ac5319b2d4ab8c2 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 8 Nov 2005 21:38:38 -0800 Subject: [PATCH] V4L: 896: fixed tda8290 secam l Fixed tda8290 SECAM-L Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tda8290.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 0dde6af251d..b2dfe07e9f9 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -323,6 +323,7 @@ static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq) i2c_master_send(c, soft_reset, 2); msleep(1); + expert_mode[1] = t->tda8290_easy_mode + 0x80; i2c_master_send(c, expert_mode, 2); i2c_master_send(c, gainset_off, 2); i2c_master_send(c, if_agc_spd, 2); @@ -348,8 +349,9 @@ static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq) tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat); else tuner_dbg("tda8290 not locked, no signal?\n"); - if ((agc_stat > 115) || (!(pll_stat & 0x80) && (adc_sat <20))) { - tuner_dbg("adjust gain, step 1. Agc: %d\n", agc_stat); + if ((agc_stat > 115) || (!(pll_stat & 0x80) && (adc_sat < 20))) { + tuner_dbg("adjust gain, step 1. Agc: %d, ADC stat: %d, lock: %d\n", + agc_stat, adc_sat, pll_stat & 0x80); i2c_master_send(c, gainset_2, 2); msleep(100); i2c_master_send(c, &addr_agc_stat, 1); @@ -357,7 +359,8 @@ static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq) i2c_master_send(c, &addr_pll_stat, 1); i2c_master_recv(c, &pll_stat, 1); if ((agc_stat > 115) || !(pll_stat & 0x80)) { - tuner_dbg("adjust gain, step 2. Agc: %d\n", agc_stat); + tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n", + agc_stat, pll_stat & 0x80); if (t->tda827x_ver != 0) tda827xa_agcf(c); else @@ -383,6 +386,7 @@ static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq) i2c_master_send(c, &addr_pll_stat, 1); i2c_master_recv(c, &pll_stat, 1); if ((adc_sat > 20) || !(pll_stat & 0x80)) { + tuner_dbg("trying to resolve SECAM L deadlock\n"); i2c_master_send(c, agc_rst_on, 2); msleep(40); i2c_master_send(c, agc_rst_off, 2); @@ -404,28 +408,37 @@ static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq) static void set_audio(struct tuner *t) { - t->tda827x_lpsel = 0; + char* mode; + t->tda827x_lpsel = 0; + mode = "xx"; if (t->std & V4L2_STD_MN) { t->sgIF = 92; t->tda8290_easy_mode = 0x01; t->tda827x_lpsel = 1; + mode = "MN"; } else if (t->std & V4L2_STD_B) { t->sgIF = 108; t->tda8290_easy_mode = 0x02; + mode = "B"; } else if (t->std & V4L2_STD_GH) { t->sgIF = 124; t->tda8290_easy_mode = 0x04; + mode = "GH"; } else if (t->std & V4L2_STD_PAL_I) { t->sgIF = 124; t->tda8290_easy_mode = 0x08; + mode = "I"; } else if (t->std & V4L2_STD_DK) { t->sgIF = 124; t->tda8290_easy_mode = 0x10; + mode = "DK"; } else if (t->std & V4L2_STD_SECAM_L) { t->sgIF = 124; t->tda8290_easy_mode = 0x20; + mode = "L"; } + tuner_dbg("setting tda8290 to system %s\n", mode); } static void set_tv_freq(struct i2c_client *c, unsigned int freq) -- cgit v1.2.3 From 6c3d67abdb79ff3e22cd19476c05294274434143 Mon Sep 17 00:00:00 2001 From: "Hans J. Koch" Date: Tue, 8 Nov 2005 21:38:39 -0800 Subject: [PATCH] V4L: 899: fix rds raw data buffer handling bug which caused Fix RDS raw data buffer handling bug, which caused decoding delays and sometimes wrong data. Signed-off-by: Hans J. Koch Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa6588.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index 23ea548a71e..dca3ddfd510 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -245,7 +245,7 @@ static void block_to_buf(struct saa6588 *s, unsigned char *blockbuf) s->wr_index = 0; if (s->wr_index == s->rd_index) { - s->rd_index++; + s->rd_index += 3; if (s->rd_index >= s->buf_size) s->rd_index = 0; } else -- cgit v1.2.3 From d4c34aa024aef2be3f3deca751c335f72c3e32b6 Mon Sep 17 00:00:00 2001 From: Kirk Lapray Date: Tue, 8 Nov 2005 21:38:40 -0800 Subject: [PATCH] V4L: 901: added function for nxt200x to change pll input Added function for nxt200x to change pll input Signed-off-by: Kirk Lapray Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/cx88-dvb.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 1236cb11d83..9cce91ec334 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -296,10 +296,20 @@ static int nxt200x_set_ts_param(struct dvb_frontend* fe, return 0; } +static int nxt200x_set_pll_input(u8* buf, int input) +{ + if (input) + buf[3] |= 0x08; + else + buf[3] &= ~0x08; + return 0; +} + static struct nxt200x_config ati_hdtvwonder = { .demod_address = 0x0a, .pll_address = 0x61, .pll_desc = &dvb_pll_tuv1236d, + .set_pll_input = nxt200x_set_pll_input, .set_ts_params = nxt200x_set_ts_param, }; #endif -- cgit v1.2.3 From 12b0e1df5c10a094a4475439a484307478c4c607 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:38:41 -0800 Subject: [PATCH] V4L: 902: saa6588.c should build saa6588.ko rather than rds.ko Saa6588.c should build saa6588.ko, rather than rds.ko Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 351ce5be2ad..3ac46599240 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -5,7 +5,6 @@ bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \ bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o -rds-objs := saa6588.o zr36067-objs := zoran_procfs.o zoran_device.o \ zoran_driver.o zoran_card.o tuner-objs := tuner-core.o tuner-simple.o mt20xx.o tda8290.o tea5767.o @@ -16,7 +15,7 @@ obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tvaudio.o \ obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o obj-$(CONFIG_VIDEO_ZR36120) += zoran.o -obj-$(CONFIG_VIDEO_SAA6588) += rds.o +obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o -- cgit v1.2.3 From 90e9df7f186876584b938e01fcf7f40a50c950b9 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 8 Nov 2005 21:38:42 -0800 Subject: [PATCH] V4L: 904: added dvb support for tda8275a philips tiger reference design Added dvb support for tda8275a (Philips Tiger reference design) Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-cards.c | 37 ++++++ drivers/media/video/saa7134/saa7134-dvb.c | 192 ++++++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134.h | 1 + include/media/tuner.h | 2 +- 4 files changed, 231 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 9e1c51c08f2..d9b3fb0f3ef 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2490,6 +2490,29 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, }}, }, + [SAA7134_BOARD_PHILIPS_TIGER] = { + .name = "Philips Tiger reference design", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .mpeg = SAA7134_MPEG_DVB, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + }}, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -2919,6 +2942,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x1043, .subdevice = 0x4862, .driver_data = SAA7134_BOARD_ASUSTeK_P7131_DUAL, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = PCI_VENDOR_ID_PHILIPS, + .subdevice = 0x2018, + .driver_data = SAA7134_BOARD_PHILIPS_TIGER, },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -3177,6 +3206,14 @@ int saa7134_board_init2(struct saa7134_dev *dev) saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup); } break; + case SAA7134_BOARD_PHILIPS_TIGER: + /* this is a hybrid board, initialize to analog mode */ + { + u8 data[] = { 0x3c, 0x33, 0x68}; + struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; + i2c_transfer(&dev->i2c_adap, &msg, 1); + } + break; } return 0; } diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index aaac12e8adb..d1d1abc5571 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -626,8 +626,196 @@ static struct tda1004x_config tda827x_lifeview_config = { .pll_sleep = philips_tda827x_pll_sleep, .request_firmware = NULL, }; + +/* ------------------------------------------------------------------ */ + +struct tda827xa_data { + u32 lomax; + u8 svco; + u8 spd; + u8 scr; + u8 sbs; + u8 gc3; +}; + +static struct tda827xa_data tda827xa_dvbt[] = { + { .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 1}, + { .lomax = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1}, + { .lomax = 81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1}, + { .lomax = 97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1}, + { .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1}, + { .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, + { .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, + { .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, + { .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, + { .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1}, + { .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1}, + { .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1}, + { .lomax = 290000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1}, + { .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1}, + { .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1}, + { .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1}, + { .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, + { .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1}, + { .lomax = 550000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, + { .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, + { .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, + { .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, + { .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, + { .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, + { .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, + { .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0}, + { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}}; + + +static int philips_tda827xa_pll_set(u8 addr, struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct saa7134_dev *dev = fe->dvb->priv; + u8 tuner_buf[14]; + unsigned char reg2[2]; + + struct i2c_msg msg = {.addr = addr,.flags = 0,.buf = tuner_buf}; + int i, tuner_freq, if_freq; + u32 N; + + switch (params->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + if_freq = 4000000; + break; + case BANDWIDTH_7_MHZ: + if_freq = 4500000; + break; + default: /* 8 MHz or Auto */ + if_freq = 5000000; + break; + } + tuner_freq = params->frequency + if_freq; + + i = 0; + while (tda827xa_dvbt[i].lomax < tuner_freq) { + if(tda827xa_dvbt[i + 1].lomax == 0) + break; + i++; + } + + N = ((tuner_freq + 31250) / 62500) << tda827xa_dvbt[i].spd; + tuner_buf[0] = 0; // subaddress + tuner_buf[1] = N >> 8; + tuner_buf[2] = N & 0xff; + tuner_buf[3] = 0; + tuner_buf[4] = 0x16; + tuner_buf[5] = (tda827xa_dvbt[i].spd << 5) + (tda827xa_dvbt[i].svco << 3) + + tda827xa_dvbt[i].sbs; + tuner_buf[6] = 0x4b + (tda827xa_dvbt[i].gc3 << 4); + tuner_buf[7] = 0x0c; + tuner_buf[8] = 0x06; + tuner_buf[9] = 0x24; + tuner_buf[10] = 0xff; + tuner_buf[11] = 0x60; + tuner_buf[12] = 0x00; + tuner_buf[13] = 0x39; // lpsel + msg.len = 14; + if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) + return -EIO; + + msg.buf= reg2; + msg.len = 2; + reg2[0] = 0x60; + reg2[1] = 0x3c; + i2c_transfer(&dev->i2c_adap, &msg, 1); + + reg2[0] = 0xa0; + reg2[1] = 0x40; + i2c_transfer(&dev->i2c_adap, &msg, 1); + + msleep(2); + /* correct CP value */ + reg2[0] = 0x30; + reg2[1] = 0x10 + tda827xa_dvbt[i].scr; + msg.len = 2; + i2c_transfer(&dev->i2c_adap, &msg, 1); + + msleep(550); + reg2[0] = 0x50; + reg2[1] = 0x4f + (tda827xa_dvbt[i].gc3 << 4); + i2c_transfer(&dev->i2c_adap, &msg, 1); + + return 0; + +} + +static void philips_tda827xa_pll_sleep(u8 addr, struct dvb_frontend *fe) +{ + struct saa7134_dev *dev = fe->dvb->priv; + static u8 tda827xa_sleep[] = { 0x30, 0x90}; + struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tda827xa_sleep, + .len = sizeof(tda827xa_sleep) }; + i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); + +} + +/* ------------------------------------------------------------------ */ + +static int philips_tiger_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + int ret; + struct saa7134_dev *dev = fe->dvb->priv; + static u8 tda8290_close[] = { 0x21, 0xc0}; + static u8 tda8290_open[] = { 0x21, 0x80}; + struct i2c_msg tda8290_msg = {.addr = 0x4b,.flags = 0, .len = 2}; + /* close tda8290 i2c bridge */ + tda8290_msg.buf = tda8290_close; + ret = i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1); + if (ret != 1) + return -EIO; + msleep(20); + ret = philips_tda827xa_pll_set(0x61, fe, params); + if (ret != 0) + return ret; + /* open tda8290 i2c bridge */ + tda8290_msg.buf = tda8290_open; + i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1); + return ret; +}; + +static int philips_tiger_dvb_mode(struct dvb_frontend *fe) +{ + struct saa7134_dev *dev = fe->dvb->priv; + static u8 data[] = { 0x3c, 0x33, 0x6a}; + struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; + + if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) + return -EIO; + return 0; +} + +static void philips_tiger_analog_mode(struct dvb_frontend *fe) +{ + struct saa7134_dev *dev = fe->dvb->priv; + static u8 data[] = { 0x3c, 0x33, 0x68}; + struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; + + i2c_transfer(&dev->i2c_adap, &msg, 1); + philips_tda827xa_pll_sleep( 0x61, fe); +} + +static struct tda1004x_config philips_tiger_config = { + .demod_address = 0x08, + .invert = 1, + .invert_oclk = 0, + .xtal_freq = TDA10046_XTAL_16M, + .agc_config = TDA10046_AGC_TDA827X, + .if_freq = TDA10046_FREQ_045, + .pll_init = philips_tiger_dvb_mode, + .pll_set = philips_tiger_pll_set, + .pll_sleep = philips_tiger_analog_mode, + .request_firmware = NULL, +}; + #endif +/* ------------------------------------------------------------------ */ + #ifdef HAVE_NXT200X static struct nxt200x_config avertvhda180 = { .demod_address = 0x0a, @@ -688,6 +876,10 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend = tda10046_attach(&philips_tu1216_61_config, &dev->i2c_adap); break; + case SAA7134_BOARD_PHILIPS_TIGER: + dev->dvb.frontend = tda10046_attach(&philips_tiger_config, + &dev->i2c_adap); + break; #endif #ifdef HAVE_NXT200X case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180: diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 4273ded9d17..a82468a0767 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -207,6 +207,7 @@ struct saa7134_format { #define SAA7134_BOARD_ASUSTeK_P7131_DUAL 78 #define SAA7134_BOARD_PCTV_CARDBUS 79 #define SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV 80 +#define SAA7134_BOARD_PHILIPS_TIGER 81 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 diff --git a/include/media/tuner.h b/include/media/tuner.h index 5196d9eac44..9184e534b7e 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -211,10 +211,10 @@ extern unsigned const int tuner_count; extern int microtune_init(struct i2c_client *c); extern int tda8290_init(struct i2c_client *c); +extern int tda8290_probe(struct i2c_client *c); extern int tea5767_tuner_init(struct i2c_client *c); extern int default_tuner_init(struct i2c_client *c); extern int tea5767_autodetection(struct i2c_client *c); -extern int tda8290_probe(struct i2c_client *c); #define tuner_warn(fmt, arg...) do {\ printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c.driver->name, \ -- cgit v1.2.3 From c3d931929f1d11f9d198567850247ae1754dfc06 Mon Sep 17 00:00:00 2001 From: Pavel Mihaylov Date: Tue, 8 Nov 2005 21:38:43 -0800 Subject: [PATCH] V4L: 906: remote and more info for pctv cardbus whitespace cleanup Remote and more info for PCTV Cardbus. Whitespace cleanup. Signed-off-by: Pavel Mihaylov Signed-off-by: Nickolay V. Shmyrev Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 23 +++++++++++++--- drivers/media/video/saa7134/saa7134-dvb.c | 2 +- drivers/media/video/saa7134/saa7134-input.c | 42 +++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 5 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 51252ff034e..997a57db257 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -79,3 +79,4 @@ 78 -> ASUSTeK P7131 Dual [1043:4862] 79 -> PCTV Cardbus TV/Radio (ITO25 Rev:2B) 80 -> ASUS Digimatrix TV [1043:0210] + 81 -> Philips Tiger reference design [1131:2018] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index d9b3fb0f3ef..e3fe15a14ae 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2453,18 +2453,33 @@ struct saa7134_board saa7134_boards[] = { }, [SAA7134_BOARD_PCTV_CARDBUS] = { /* Paul Tom Zalac */ - /* tda8275a tuner doesnt work yet */ + /* Pavel Mihaylov */ .name = "PCTV Cardbus TV/Radio (ITO25 Rev:2B)", + /* Sedna Cardbus TV Tuner */ .audio_clock = 0x00187de7, - .tuner_type = TUNER_ABSENT, + .tuner_type = TUNER_PHILIPS_TDA8290, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .gpiomask = 0xe880c0, .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + },{ .name = name_comp1, .vmux = 1, - .amux = LINE2, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 6, + .amux = LINE1, }}, + .radio = { + .name = name_radio, + .amux = LINE2, + }, }, [SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV] = { /* "Cyril Lacoux (Yack)" */ @@ -2942,7 +2957,7 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x1043, .subdevice = 0x4862, .driver_data = SAA7134_BOARD_ASUSTeK_P7131_DUAL, - },{ + },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = PCI_VENDOR_ID_PHILIPS, diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index d1d1abc5571..c0337cf9195 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -749,7 +749,7 @@ static void philips_tda827xa_pll_sleep(u8 addr, struct dvb_frontend *fe) struct saa7134_dev *dev = fe->dvb->priv; static u8 tda827xa_sleep[] = { 0x30, 0x90}; struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tda827xa_sleep, - .len = sizeof(tda827xa_sleep) }; + .len = sizeof(tda827xa_sleep) }; i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); } diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 0c74c2f5eda..2aba72de55d 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -543,6 +543,42 @@ static IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = { [ 0x0a ] = KEY_BACKSPACE, }; +/* Mapping for the 28 key remote control as seen at + http://www.sednacomputer.com/photo/cardbus-tv.jpg + Pavel Mihaylov */ +static IR_KEYTAB_TYPE pctv_cardbus_codes[IR_KEYTAB_SIZE] = { + [ 0 ] = KEY_KP0, + [ 1 ] = KEY_KP1, + [ 2 ] = KEY_KP2, + [ 3 ] = KEY_KP3, + [ 4 ] = KEY_KP4, + [ 5 ] = KEY_KP5, + [ 6 ] = KEY_KP6, + [ 7 ] = KEY_KP7, + [ 8 ] = KEY_KP8, + [ 9 ] = KEY_KP9, + + [ 0x0a ] = KEY_AGAIN, /* Recall */ + [ 0x0b ] = KEY_CHANNELUP, + [ 0x0c ] = KEY_VOLUMEUP, + [ 0x0d ] = KEY_MODE, /* Stereo */ + [ 0x0e ] = KEY_STOP, + [ 0x0f ] = KEY_PREVIOUSSONG, + [ 0x10 ] = KEY_ZOOM, + [ 0x11 ] = KEY_TUNER, /* Source */ + [ 0x12 ] = KEY_POWER, + [ 0x13 ] = KEY_MUTE, + [ 0x15 ] = KEY_CHANNELDOWN, + [ 0x18 ] = KEY_VOLUMEDOWN, + [ 0x19 ] = KEY_SHUFFLE, /* Snapshot */ + [ 0x1a ] = KEY_NEXTSONG, + [ 0x1b ] = KEY_TEXT, /* Time Shift */ + [ 0x1c ] = KEY_RADIO, /* FM Radio */ + [ 0x1d ] = KEY_RECORD, + [ 0x1e ] = KEY_PAUSE, +}; + + /* -------------------- GPIO generic keycode builder -------------------- */ static int build_key(struct saa7134_dev *dev) @@ -745,6 +781,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keyup = 0x004000; polling = 50; // ms break; + case SAA7134_BOARD_PCTV_CARDBUS: + ir_codes = pctv_cardbus_codes; + mask_keycode = 0x001f00; + mask_keyup = 0x004000; + polling = 50; // ms + break; case SAA7134_BOARD_GOTVIEW_7135: ir_codes = gotview7135_codes; mask_keycode = 0x0003EC; -- cgit v1.2.3 From eac94356c8f9f7d3854ed0290a406b13bfe8df4c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:43 -0800 Subject: [PATCH] V4L: 907: em28xx cleanups and fixes - Em28xx cleanups and fixes. - Some cleanups and audio amux adjust. - em28xx will allways try, by default, the biggest size alt. - Fixes audio mux code. - Fixes some logs. - Adds support for digital output for WinTV USB2 board. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-cards.c | 15 ++-- drivers/media/video/em28xx/em28xx-core.c | 17 +--- drivers/media/video/em28xx/em28xx-video.c | 107 +++++++++++----------- drivers/media/video/msp3400.c | 142 +++++++++++++++++++++++++++--- include/linux/videodev2.h | 1 + 5 files changed, 201 insertions(+), 81 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 49107fd0c0d..57779e63f35 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -128,7 +128,7 @@ struct em28xx_board em28xx_boards[] = { .input = {{ .type = EM28XX_VMUX_TELEVISION, .vmux = 0, - .amux = 0, + .amux = 6, },{ .type = EM28XX_VMUX_SVIDEO, .vmux = 2, @@ -261,9 +261,11 @@ void em28xx_card_setup(struct em28xx *dev) /* request some modules */ if (dev->model == EM2820_BOARD_HAUPPAUGE_WINTV_USB_2) { struct tveeprom tv; + struct v4l2_audioout ao; #ifdef CONFIG_MODULES request_module("tveeprom"); request_module("ir-kbd-i2c"); + request_module("msp3400"); #endif /* Call first TVeeprom */ @@ -273,10 +275,13 @@ void em28xx_card_setup(struct em28xx *dev) dev->tuner_type= tv.tuner_type; if (tv.audio_processor == AUDIO_CHIP_MSP34XX) { dev->has_msp34xx=1; - } else dev->has_msp34xx=0; - em28xx_write_regs_req(dev,0x06,0x00,"\x40",1);// Serial Bus Frequency Select Register - em28xx_write_regs_req(dev,0x0f,0x00,"\x87",1);// XCLK Frequency Select Register - em28xx_write_regs_req(dev,0x88,0x0d,"\xd0",1); + memset (&ao,0,sizeof(ao)); + + ao.index=2; + ao.mode=V4L2_AUDMODE_32BITS; + em28xx_i2c_call_clients(dev, VIDIOC_S_AUDOUT, &ao); + } else + dev->has_msp34xx=0; } } diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 045547e1765..5cc850666fd 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -797,20 +797,9 @@ int em28xx_set_alternate(struct em28xx *dev) dev->alt = alt; if (dev->alt == 0) { int i; - if(dev->is_em2800){ /* always use the max packet size for em2800 based devices */ - for(i=0;i< EM28XX_MAX_ALT; i++) - if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->alt]) - dev->alt=i; - }else{ - unsigned int min_pkt_size = dev->field_size / 137; /* FIXME: empiric magic number */ - em28xx_coredbg("minimum isoc packet size: %u", min_pkt_size); - dev->alt = 7; - for (i = 1; i < EM28XX_MAX_ALT; i += 2) /* FIXME: skip even alternate: why do they not work? */ - if (dev->alt_max_pkt_size[i] >= min_pkt_size) { - dev->alt = i; - break; - } - } + for(i=0;i< EM28XX_MAX_ALT; i++) + if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->alt]) + dev->alt=i; } if (dev->alt != prev_alt) { diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 54f21242ccb..0bbfce03172 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -277,6 +277,35 @@ static void em28xx_empty_framequeues(struct em28xx *dev) } } +static void video_mux(struct em28xx *dev, int index) +{ + int input, ainput; + + input = INPUT(index)->vmux; + dev->ctl_input = index; + dev->ctl_ainput = INPUT(index)->amux; + + em28xx_i2c_call_clients(dev, DECODER_SET_INPUT, &input); + + + em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,input,dev->ctl_ainput); + + if (dev->has_msp34xx) { + em28xx_i2c_call_clients(dev, VIDIOC_S_AUDIO, &dev->ctl_ainput); + ainput = EM28XX_AUDIO_SRC_TUNER; + em28xx_audio_source(dev, ainput); + } else { + switch (dev->ctl_ainput) { + case 0: + ainput = EM28XX_AUDIO_SRC_TUNER; + break; + default: + ainput = EM28XX_AUDIO_SRC_LINE; + } + em28xx_audio_source(dev, ainput); + } +} + /* * em28xx_v4l2_open() * inits the device and starts isoc transfer @@ -298,7 +327,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) filp->private_data=dev; - em28xx_videodbg("users=%d", dev->users); + em28xx_videodbg("users=%d\n", dev->users); if (!down_read_trylock(&em28xx_disconnect)) return -ERESTARTSYS; @@ -352,6 +381,8 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) dev->state |= DEV_INITIALIZED; + video_mux(dev, 0); + err: up(&dev->lock); up_read(&em28xx_disconnect); @@ -386,7 +417,7 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) int errCode; struct em28xx *dev=filp->private_data; - em28xx_videodbg("users=%d", dev->users); + em28xx_videodbg("users=%d\n", dev->users); down(&dev->lock); @@ -404,7 +435,7 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) /* set alternate 0 */ dev->alt = 0; - em28xx_videodbg("setting alternate 0"); + em28xx_videodbg("setting alternate 0\n"); errCode = usb_set_interface(dev->udev, 0, 0); if (errCode < 0) { em28xx_errdev ("cannot change alternate number to 0 (error=%i)\n", @@ -434,20 +465,20 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count, return -ERESTARTSYS; if (dev->state & DEV_DISCONNECTED) { - em28xx_videodbg("device not present"); + em28xx_videodbg("device not present\n"); up(&dev->fileop_lock); return -ENODEV; } if (dev->state & DEV_MISCONFIGURED) { - em28xx_videodbg("device misconfigured; close and open it again"); + em28xx_videodbg("device misconfigured; close and open it again\n"); up(&dev->fileop_lock); return -EIO; } if (dev->io == IO_MMAP) { em28xx_videodbg ("IO method is set to mmap; close and open" - " the device again to choose the read method"); + " the device again to choose the read method\n"); up(&dev->fileop_lock); return -EINVAL; } @@ -524,9 +555,9 @@ static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait) return POLLERR; if (dev->state & DEV_DISCONNECTED) { - em28xx_videodbg("device not present"); + em28xx_videodbg("device not present\n"); } else if (dev->state & DEV_MISCONFIGURED) { - em28xx_videodbg("device is misconfigured; close and open it again"); + em28xx_videodbg("device is misconfigured; close and open it again\n"); } else { if (dev->io == IO_NONE) { if (!em28xx_request_buffers @@ -595,14 +626,14 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) return -ERESTARTSYS; if (dev->state & DEV_DISCONNECTED) { - em28xx_videodbg("mmap: device not present"); + em28xx_videodbg("mmap: device not present\n"); up(&dev->fileop_lock); return -ENODEV; } if (dev->state & DEV_MISCONFIGURED) { em28xx_videodbg ("mmap: Device is misconfigured; close and " - "open it again"); + "open it again\n"); up(&dev->fileop_lock); return -EIO; } @@ -618,7 +649,7 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) break; } if (i == dev->num_frames) { - em28xx_videodbg("mmap: user supplied mapping address is out of range"); + em28xx_videodbg("mmap: user supplied mapping address is out of range\n"); up(&dev->fileop_lock); return -EINVAL; } @@ -632,7 +663,7 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) page = vmalloc_to_pfn((void *)pos); if (remap_pfn_range(vma, start, page, PAGE_SIZE, vma->vm_page_prot)) { - em28xx_videodbg("mmap: rename page map failed"); + em28xx_videodbg("mmap: rename page map failed\n"); up(&dev->fileop_lock); return -EAGAIN; } @@ -749,7 +780,7 @@ static int em28xx_stream_interrupt(struct em28xx *dev) else if (ret) { dev->state |= DEV_MISCONFIGURED; em28xx_videodbg("device is misconfigured; close and " - "open /dev/video%d again", dev->vdev->minor); + "open /dev/video%d again\n", dev->vdev->minor); return ret; } @@ -800,28 +831,6 @@ static int em28xx_set_norm(struct em28xx *dev, int width, int height) return 0; } -static void video_mux(struct em28xx *dev, int index) -{ - int input, ainput; - - input = INPUT(index)->vmux; - dev->ctl_input = index; - - em28xx_i2c_call_clients(dev, DECODER_SET_INPUT, &input); - - dev->ctl_ainput = INPUT(index)->amux; - - switch (dev->ctl_ainput) { - case 0: - ainput = EM28XX_AUDIO_SRC_TUNER; - break; - default: - ainput = EM28XX_AUDIO_SRC_LINE; - } - - em28xx_audio_source(dev, ainput); -} - /* * em28xx_v4l2_do_ioctl() * This function is _not_ called directly, but from @@ -1062,7 +1071,7 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, t->signal = (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0; - em28xx_videodbg("VIDIO_G_TUNER: signal=%x, afc=%x", t->signal, + em28xx_videodbg("VIDIO_G_TUNER: signal=%x, afc=%x\n", t->signal, t->afc); return 0; } @@ -1146,7 +1155,7 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, dev->stream = STREAM_ON; /* FIXME: Start video capture here? */ - em28xx_videodbg("VIDIOC_STREAMON: starting stream"); + em28xx_videodbg("VIDIOC_STREAMON: starting stream\n"); return 0; } @@ -1160,7 +1169,7 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, return -EINVAL; if (dev->stream == STREAM_ON) { - em28xx_videodbg ("VIDIOC_STREAMOFF: interrupting stream"); + em28xx_videodbg ("VIDIOC_STREAMOFF: interrupting stream\n"); if ((ret = em28xx_stream_interrupt(dev))) return ret; } @@ -1234,7 +1243,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, { struct v4l2_format *format = arg; - em28xx_videodbg("VIDIOC_G_FMT: type=%s", + em28xx_videodbg("VIDIOC_G_FMT: type=%s\n", format->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? "V4L2_BUF_TYPE_VIDEO_CAPTURE" : format->type == @@ -1253,7 +1262,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; format->fmt.pix.field = dev->interlaced ? V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */ - em28xx_videodbg("VIDIOC_G_FMT: %dx%d", dev->width, + em28xx_videodbg("VIDIOC_G_FMT: %dx%d\n", dev->width, dev->height); return 0; } @@ -1274,7 +1283,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, /* int both_fields; */ - em28xx_videodbg("%s: type=%s", + em28xx_videodbg("%s: type=%s\n", cmd == VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : "VIDIOC_S_FMT", @@ -1288,7 +1297,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - em28xx_videodbg("%s: requested %dx%d", + em28xx_videodbg("%s: requested %dx%d\n", cmd == VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : "VIDIOC_S_FMT", format->fmt.pix.width, @@ -1347,7 +1356,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; format->fmt.pix.field = V4L2_FIELD_INTERLACED; - em28xx_videodbg("%s: returned %dx%d (%d, %d)", + em28xx_videodbg("%s: returned %dx%d (%d, %d)\n", cmd == VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : "VIDIOC_S_FMT", format->fmt.pix.width, @@ -1359,13 +1368,13 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, for (i = 0; i < dev->num_frames; i++) if (dev->frame[i].vma_use_count) { em28xx_videodbg("VIDIOC_S_FMT failed. " - "Unmap the buffers first."); + "Unmap the buffers first.\n"); return -EINVAL; } /* stop io in case it is already in progress */ if (dev->stream == STREAM_ON) { - em28xx_videodbg("VIDIOC_SET_FMT: interupting stream"); + em28xx_videodbg("VIDIOC_SET_FMT: interupting stream\n"); if ((ret = em28xx_stream_interrupt(dev))) return ret; } @@ -1405,18 +1414,18 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, if (dev->io == IO_READ) { em28xx_videodbg ("method is set to read;" " close and open the device again to" - " choose the mmap I/O method"); + " choose the mmap I/O method\n"); return -EINVAL; } for (i = 0; i < dev->num_frames; i++) if (dev->frame[i].vma_use_count) { - em28xx_videodbg ("VIDIOC_REQBUFS failed; previous buffers are still mapped"); + em28xx_videodbg ("VIDIOC_REQBUFS failed; previous buffers are still mapped\n"); return -EINVAL; } if (dev->stream == STREAM_ON) { - em28xx_videodbg("VIDIOC_REQBUFS: interrupting stream"); + em28xx_videodbg("VIDIOC_REQBUFS: interrupting stream\n"); if ((ret = em28xx_stream_interrupt(dev))) return ret; } @@ -1430,7 +1439,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, dev->frame_current = NULL; - em28xx_videodbg ("VIDIOC_REQBUFS: setting io method to mmap: num bufs %i", + em28xx_videodbg ("VIDIOC_REQBUFS: setting io method to mmap: num bufs %i\n", rb->count); dev->io = rb->count ? IO_MMAP : IO_NONE; return 0; diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index d603229c9f2..b599f0554fb 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -90,6 +90,8 @@ struct msp3400c { int stereo; int nicam_on; int acb; + int in_scart; + int i2s_mode; int main, second; /* sound carrier */ int input; int source; /* see msp34xxg_set_source */ @@ -364,12 +366,40 @@ static struct CARRIER_DETECT carrier_detect_65[] = { #define CARRIER_COUNT(x) (sizeof(x)/sizeof(struct CARRIER_DETECT)) -/* ----------------------------------------------------------------------- */ +/* ----------------------------------------------------------------------- * + * bits 9 8 5 - SCART DSP input Select: + * 0 0 0 - SCART 1 to DSP input (reset position) + * 0 1 0 - MONO to DSP input + * 1 0 0 - SCART 2 to DSP input + * 1 1 1 - Mute DSP input + * + * bits 11 10 6 - SCART 1 Output Select: + * 0 0 0 - undefined (reset position) + * 0 1 0 - SCART 2 Input to SCART 1 Output (for devices with 2 SCARTS) + * 1 0 0 - MONO input to SCART 1 Output + * 1 1 0 - SCART 1 DA to SCART 1 Output + * 0 0 1 - SCART 2 DA to SCART 1 Output + * 0 1 1 - SCART 1 Input to SCART 1 Output + * 1 1 1 - Mute SCART 1 Output + * + * bits 13 12 7 - SCART 2 Output Select (for devices with 2 Output SCART): + * 0 0 0 - SCART 1 DA to SCART 2 Output (reset position) + * 0 1 0 - SCART 1 Input to SCART 2 Output + * 1 0 0 - MONO input to SCART 2 Output + * 0 0 1 - SCART 2 DA to SCART 2 Output + * 0 1 1 - SCART 2 Input to SCART 2 Output + * 1 1 0 - Mute SCART 2 Output + * + * Bits 4 to 0 should be zero. + * ----------------------------------------------------------------------- */ static int scarts[3][9] = { /* MASK IN1 IN2 IN1_DA IN2_DA IN3 IN4 MONO MUTE */ + /* SCART DSP Input select */ { 0x0320, 0x0000, 0x0200, -1, -1, 0x0300, 0x0020, 0x0100, 0x0320 }, + /* SCART1 Output select */ { 0x0c40, 0x0440, 0x0400, 0x0c00, 0x0040, 0x0000, 0x0840, 0x0800, 0x0c40 }, + /* SCART2 Output select */ { 0x3080, 0x1000, 0x1080, 0x0000, 0x0080, 0x2080, 0x3080, 0x2000, 0x3000 }, }; @@ -381,13 +411,23 @@ static void msp3400c_set_scart(struct i2c_client *client, int in, int out) { struct msp3400c *msp = i2c_get_clientdata(client); - if (-1 == scarts[out][in]) - return; + msp->in_scart=in; + + if (in<=2) { + if (-1 == scarts[out][in]) + return; + + msp->acb &= ~scarts[out][SCART_MASK]; + msp->acb |= scarts[out][in]; + } else + msp->acb = 0xf60; /* Mute Input and SCART 1 Output */ + + dprintk("msp34xx: scart switch: %s => %d (ACB=0x%04x)\n", + scart_names[in], out, msp->acb); + msp3400c_write(client,I2C_MSP3400C_DFP, 0x13, msp->acb); - dprintk("msp34xx: scart switch: %s => %d\n", scart_names[in], out); - msp->acb &= ~scarts[out][SCART_MASK]; - msp->acb |= scarts[out][in]; - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0013, msp->acb); + /* Sets I2S speed 0 = 1.024 Mbps, 1 = 2.048 Mbps */ + msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode); } /* ------------------------------------------------------------------------ */ @@ -1235,7 +1275,8 @@ static int msp3410d_thread(void *data) msp3400c_setbass(client, msp->bass); msp3400c_settreble(client, msp->treble); msp3400c_setvolume(client, msp->muted, msp->left, msp->right); - msp3400c_write(client, I2C_MSP3400C_DFP, 0x0013, msp->acb); + msp3400c_write(client, I2C_MSP3400C_DFP, 0x13, msp->acb); + msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode); msp3400c_restore_dfp(client); /* monitor tv audio mode */ @@ -1275,6 +1316,8 @@ static int msp34xxg_reset(struct i2c_client *client) 0x0f20 /* mute DSP input, mute SCART 1 */)) return -1; + msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode); + /* step-by-step initialisation, as described in the manual */ modus = msp34xx_modus(msp->norm); std = msp34xx_standard(msp->norm); @@ -1371,6 +1414,8 @@ static int msp34xxg_thread(void *data) 0x13, /* ACB */ msp->acb)) return -1; + + msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode); } dprintk("msp34xxg: thread: exit\n"); return 0; @@ -1539,6 +1584,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) msp->treble = 32768; msp->input = -1; msp->muted = 0; + msp->i2s_mode = 0; for (i = 0; i < DFP_COUNT; i++) msp->dfp_regs[i] = -1; @@ -1735,6 +1781,7 @@ static void msp_any_set_audmode(struct i2c_client *client, int audmode) } } + static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct msp3400c *msp = i2c_get_clientdata(client); @@ -1745,6 +1792,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) case AUDC_SET_INPUT: dprintk("msp34xx: AUDC_SET_INPUT(%d)\n",*sarg); + if (*sarg == msp->input) break; msp->input = *sarg; @@ -1923,6 +1971,16 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } + /* msp34xx specific */ + case MSP_SET_MATRIX: + { + struct msp_matrix *mspm = arg; + + dprintk("msp34xx: MSP_SET_MATRIX\n"); + msp3400c_set_scart(client, mspm->input, mspm->output); + break; + } + /* --- v4l2 ioctls --- */ case VIDIOC_S_STD: { @@ -1941,6 +1999,33 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; } + case VIDIOC_ENUMINPUT: + { + struct v4l2_input *i = arg; + + if (i->index != 0) + return -EINVAL; + + i->type = V4L2_INPUT_TYPE_TUNER; + switch (i->index) { + case AUDIO_RADIO: + strcpy(i->name,"Radio"); + break; + case AUDIO_EXTERN_1: + strcpy(i->name,"Extern 1"); + break; + case AUDIO_EXTERN_2: + strcpy(i->name,"Extern 2"); + break; + case AUDIO_TUNER: + strcpy(i->name,"Television"); + break; + default: + return -EINVAL; + } + return 0; + } + case VIDIOC_G_AUDIO: { struct v4l2_audio *a = arg; @@ -2032,13 +2117,44 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } - /* msp34xx specific */ - case MSP_SET_MATRIX: + case VIDIOC_G_AUDOUT: { - struct msp_matrix *mspm = arg; + struct v4l2_audioout *a=(struct v4l2_audioout *)arg; + + memset(a,0,sizeof(*a)); + + switch (a->index) { + case 0: + strcpy(a->name,"Scart1 Out"); + break; + case 1: + strcpy(a->name,"Scart2 Out"); + break; + case 2: + strcpy(a->name,"I2S Out"); + break; + default: + return -EINVAL; + } + break; + + } + case VIDIOC_S_AUDOUT: + { + struct v4l2_audioout *a=(struct v4l2_audioout *)arg; + + if (a->index<0||a->index>2) + return -EINVAL; + + if (a->index==2) { + if (a->mode == V4L2_AUDMODE_32BITS) + msp->i2s_mode=1; + else + msp->i2s_mode=0; + } +printk("Setting audio out on msp34xx to input %i, mode %i\n",a->index,msp->i2s_mode); + msp3400c_set_scart(client,msp->in_scart,a->index); - dprintk("msp34xx: MSP_SET_MATRIX\n"); - msp3400c_set_scart(client, mspm->input, mspm->output); break; } diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index e8a0d22df54..67c61b4bf2e 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -885,6 +885,7 @@ struct v4l2_audio /* Flags for the 'mode' field */ #define V4L2_AUDMODE_AVL 0x00001 +#define V4L2_AUDMODE_32BITS 0x00002 struct v4l2_audioout { -- cgit v1.2.3 From d4b0aba47d48a339572744cb23ba925f04e3cda9 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 8 Nov 2005 21:38:44 -0800 Subject: [PATCH] V4L: 908: added dvb-t support for asus p7134 dual - Added dvb-t support for Asus P7134 Dual - added pci id for ADS Tech Instant TV cardbus variant Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-cards.c | 9 ++++++++- drivers/media/video/saa7134/saa7134-dvb.c | 4 ++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index e3fe15a14ae..ac361858901 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2431,6 +2431,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .gpiomask = 1 << 21, + .mpeg = SAA7134_MPEG_DVB, .inputs = {{ .name = name_tv, .vmux = 1, @@ -2864,13 +2865,18 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x1421, .subdevice = 0x0350, /* PCI version */ .driver_data = SAA7134_BOARD_ADS_INSTANT_TV, - },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x1421, .subdevice = 0x0370, /* cardbus version */ .driver_data = SAA7134_BOARD_ADS_INSTANT_TV, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1421, + .subdevice = 0x1370, /* cardbus version */ + .driver_data = SAA7134_BOARD_ADS_INSTANT_TV, },{ /* Typhoon DVB-T Duo Digital/Analog Cardbus */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -3222,6 +3228,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) } break; case SAA7134_BOARD_PHILIPS_TIGER: + case SAA7134_BOARD_ASUSTeK_P7131_DUAL: /* this is a hybrid board, initialize to analog mode */ { u8 data[] = { 0x3c, 0x33, 0x68}; diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index c0337cf9195..8545d30d9f7 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -880,6 +880,10 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend = tda10046_attach(&philips_tiger_config, &dev->i2c_adap); break; + case SAA7134_BOARD_ASUSTeK_P7131_DUAL: + dev->dvb.frontend = tda10046_attach(&philips_tiger_config, + &dev->i2c_adap); + break; #endif #ifdef HAVE_NXT200X case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180: -- cgit v1.2.3 From 247b661f83ad9be317da2e3b0c254ba283f874ef Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 8 Nov 2005 21:38:45 -0800 Subject: [PATCH] V4L: 909: updated cardlist and strip trailing whitespace Updated CARDLIST and strip trailing whitespace. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.saa7134 | 2 +- drivers/media/video/saa7134/saa7134-dvb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 997a57db257..62076d2976a 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -56,7 +56,7 @@ 55 -> LifeView FlyDVB-T DUO [5168:0502,5168:0306] 56 -> Avermedia AVerTV 307 [1461:a70a] 57 -> Avermedia AVerTV GO 007 FM [1461:f31f] - 58 -> ADS Tech Instant TV (saa7135) [1421:0350,1421:0370] + 58 -> ADS Tech Instant TV (saa7135) [1421:0350,1421:0370,1421:1370] 59 -> Kworld/Tevion V-Stream Xpert TV PVR7134 60 -> Typhoon DVB-T Duo Digital/Analog Cardbus [4e42:0502] 61 -> Philips TOUGH DVB-T reference design [1131:2004] diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 8545d30d9f7..4cd3db49245 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -749,7 +749,7 @@ static void philips_tda827xa_pll_sleep(u8 addr, struct dvb_frontend *fe) struct saa7134_dev *dev = fe->dvb->priv; static u8 tda827xa_sleep[] = { 0x30, 0x90}; struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tda827xa_sleep, - .len = sizeof(tda827xa_sleep) }; + .len = sizeof(tda827xa_sleep) }; i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); } -- cgit v1.2.3 From f1bcef8874ab33b1e517b79a9b9df7309a996877 Mon Sep 17 00:00:00 2001 From: Tyler Trafford Date: Tue, 8 Nov 2005 21:38:46 -0800 Subject: [PATCH] V4L: 911: added support for ntsc 4.43 video standard Added support for NTSC 4.43 video standard. Signed-off-by: Tyler Trafford Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-dvb.c | 2 +- include/linux/videodev2.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 4cd3db49245..e016480c346 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -749,7 +749,7 @@ static void philips_tda827xa_pll_sleep(u8 addr, struct dvb_frontend *fe) struct saa7134_dev *dev = fe->dvb->priv; static u8 tda827xa_sleep[] = { 0x30, 0x90}; struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tda827xa_sleep, - .len = sizeof(tda827xa_sleep) }; + .len = sizeof(tda827xa_sleep) }; i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); } diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 67c61b4bf2e..a114fff6568 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -627,6 +627,7 @@ typedef __u64 v4l2_std_id; #define V4L2_STD_NTSC_M ((v4l2_std_id)0x00001000) #define V4L2_STD_NTSC_M_JP ((v4l2_std_id)0x00002000) +#define V4L2_STD_NTSC_443 ((v4l2_std_id)0x00004000) #define V4L2_STD_SECAM_B ((v4l2_std_id)0x00010000) #define V4L2_STD_SECAM_D ((v4l2_std_id)0x00020000) @@ -664,7 +665,8 @@ typedef __u64 v4l2_std_id; #define V4L2_STD_525_60 (V4L2_STD_PAL_M |\ V4L2_STD_PAL_60 |\ - V4L2_STD_NTSC) + V4L2_STD_NTSC |\ + V4L2_STD_NTSC_443) #define V4L2_STD_625_50 (V4L2_STD_PAL |\ V4L2_STD_PAL_N |\ V4L2_STD_PAL_Nc |\ -- cgit v1.2.3 From cb2444dfa203b5b5c76d63c0ce8593e4e0385719 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Tue, 8 Nov 2005 21:38:47 -0800 Subject: [PATCH] V4L: 913: saa713x cards with i2c remotes now autoload ir-kbd-i2c SAA713x cards with i2c remotes now autoload ir-kbd-i2c (disable_ir works, as it does for GPIO remotes) Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-cards.c | 9 +++++++-- drivers/media/video/saa7134/saa7134-core.c | 4 +++- drivers/media/video/saa7134/saa7134-input.c | 3 ++- drivers/media/video/saa7134/saa7134.h | 6 ++++++ 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index ac361858901..135fd59a6b2 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -3038,7 +3038,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) switch (dev->board) { case SAA7134_BOARD_FLYVIDEO2000: case SAA7134_BOARD_FLYVIDEO3000: - dev->has_remote = 1; + dev->has_remote = SAA7134_REMOTE_GPIO; board_flyvideo(dev); break; case SAA7134_BOARD_FLYTVPLATINUM_MINI2: @@ -3068,7 +3068,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_GOTVIEW_7135: case SAA7134_BOARD_KWORLD_TERMINATOR: case SAA7134_BOARD_PCTV_CARDBUS: - dev->has_remote = 1; + dev->has_remote = SAA7134_REMOTE_GPIO; break; case SAA7134_BOARD_MD5044: printk("%s: seems there are two different versions of the MD5044\n" @@ -3108,6 +3108,11 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_writeb (SAA7134_PRODUCTION_TEST_MODE, 0x00); break; + /* i2c remotes */ + case SAA7134_BOARD_PINNACLE_PCTV_110i: + case SAA7134_BOARD_UPMOST_PURPLE_TV: + dev->has_remote = SAA7134_REMOTE_I2C; + break; } return 0; } diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index afa0cfce657..454b8a86c83 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -712,10 +712,12 @@ static int saa7134_hwinit2(struct saa7134_dev *dev) SAA7134_IRQ2_INTE_PE | SAA7134_IRQ2_INTE_AR; - if (dev->has_remote) + if (dev->has_remote == SAA7134_REMOTE_GPIO) irq2_mask |= (SAA7134_IRQ2_INTE_GPIO18 | SAA7134_IRQ2_INTE_GPIO18A | SAA7134_IRQ2_INTE_GPIO16 ); + else if (dev->has_remote == SAA7134_REMOTE_I2C) + request_module("ir-kbd-i2c"); saa_writel(SAA7134_IRQ1, 0); saa_writel(SAA7134_IRQ2, irq2_mask); diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 2aba72de55d..b792401712b 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -716,7 +716,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) int polling = 0; int ir_type = IR_TYPE_OTHER; - if (!dev->has_remote) + if (dev->has_remote != SAA7134_REMOTE_GPIO) return -ENODEV; if (disable_ir) return -ENODEV; @@ -877,6 +877,7 @@ void saa7134_input_fini(struct saa7134_dev *dev) void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) { if (disable_ir) { + dprintk("Found supported i2c remote, but IR has been disabled\n"); ir->get_key=NULL; return; } diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index a82468a0767..14a83b82ab2 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -212,6 +212,12 @@ struct saa7134_format { #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 +/* ----------------------------------------------------------- */ +/* Since we support 2 remote types, lets tell them apart */ + +#define SAA7134_REMOTE_GPIO 1 +#define SAA7134_REMOTE_I2C 2 + /* ----------------------------------------------------------- */ /* Video Output Port Register Initialization Options */ -- cgit v1.2.3 From 17ce1ff9cfd90ab3ecffaa5ebfb4abbf8216f2cc Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Tue, 8 Nov 2005 21:38:47 -0800 Subject: [PATCH] V4L: 914: use less generic name for saa7134 card 79 Use less-generic name for saa7134 card #79 Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-cards.c | 8 ++++---- drivers/media/video/saa7134/saa7134-input.c | 6 +++--- drivers/media/video/saa7134/saa7134.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 135fd59a6b2..663d03e5bc6 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2452,11 +2452,11 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x0200000, }, }, - [SAA7134_BOARD_PCTV_CARDBUS] = { + [SAA7134_BOARD_SEDNA_PC_TV_CARDBUS] = { /* Paul Tom Zalac */ /* Pavel Mihaylov */ - .name = "PCTV Cardbus TV/Radio (ITO25 Rev:2B)", - /* Sedna Cardbus TV Tuner */ + .name = "Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B)", + /* Sedna/MuchTV (OEM) Cardbus TV Tuner */ .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_TDA8290, .radio_type = UNSET, @@ -3067,7 +3067,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVACSSMARTTV: case SAA7134_BOARD_GOTVIEW_7135: case SAA7134_BOARD_KWORLD_TERMINATOR: - case SAA7134_BOARD_PCTV_CARDBUS: + case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS: dev->has_remote = SAA7134_REMOTE_GPIO; break; case SAA7134_BOARD_MD5044: diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index b792401712b..329accda6d4 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -546,7 +546,7 @@ static IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = { /* Mapping for the 28 key remote control as seen at http://www.sednacomputer.com/photo/cardbus-tv.jpg Pavel Mihaylov */ -static IR_KEYTAB_TYPE pctv_cardbus_codes[IR_KEYTAB_SIZE] = { +static IR_KEYTAB_TYPE pctv_sedna_codes[IR_KEYTAB_SIZE] = { [ 0 ] = KEY_KP0, [ 1 ] = KEY_KP1, [ 2 ] = KEY_KP2, @@ -781,8 +781,8 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keyup = 0x004000; polling = 50; // ms break; - case SAA7134_BOARD_PCTV_CARDBUS: - ir_codes = pctv_cardbus_codes; + case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS: + ir_codes = pctv_sedna_codes; mask_keycode = 0x001f00; mask_keyup = 0x004000; polling = 50; // ms diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 14a83b82ab2..d993344d37e 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -205,7 +205,7 @@ struct saa7134_format { #define SAA7134_BOARD_MONSTERTV_MOBILE 76 #define SAA7134_BOARD_PINNACLE_PCTV_110i 77 #define SAA7134_BOARD_ASUSTeK_P7131_DUAL 78 -#define SAA7134_BOARD_PCTV_CARDBUS 79 +#define SAA7134_BOARD_SEDNA_PC_TV_CARDBUS 79 #define SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV 80 #define SAA7134_BOARD_PHILIPS_TIGER 81 -- cgit v1.2.3 From d6242f209984795644fb08b5410f405406c7104a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:48 -0800 Subject: [PATCH] V4L: SAA7134 alsa build fix Fixes saa7134-alsa build inside saa7134 driver. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile index 937dff8d561..e0b28f0533a 100644 --- a/drivers/media/video/saa7134/Makefile +++ b/drivers/media/video/saa7134/Makefile @@ -3,7 +3,8 @@ saa7134-objs := saa7134-cards.o saa7134-core.o saa7134-i2c.o \ saa7134-oss.o saa7134-ts.o saa7134-tvaudio.o \ saa7134-vbi.o saa7134-video.o saa7134-input.o -obj-$(CONFIG_VIDEO_SAA7134) += saa7134.o saa7134-empress.o saa6752hs.o +obj-$(CONFIG_VIDEO_SAA7134) += saa7134.o saa7134-empress.o \ + saa6752hs.o saa7134-alsa.o obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o EXTRA_CFLAGS += -I$(src)/.. -- cgit v1.2.3 From e2998e10a9ed47cb70a5be6207aa34b2f2f22c17 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 8 Nov 2005 21:38:49 -0800 Subject: [PATCH] V4L: 915: fixes compilation problems due removal of media/id.h and i2c-algo-bit Fixes compilation problems due removal of media/id.h and I2C_ALGO_BIT Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.saa7134 | 2 +- drivers/media/video/cs53l32a.c | 10 ++++++++-- drivers/media/video/wm8775.c | 12 ++++-------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 62076d2976a..57c9d631db5 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -77,6 +77,6 @@ 76 -> SKNet MonsterTV Mobile [1131:4ee9] 77 -> Pinnacle PCTV 110i (saa7133) [11bd:002e] 78 -> ASUSTeK P7131 Dual [1043:4862] - 79 -> PCTV Cardbus TV/Radio (ITO25 Rev:2B) + 79 -> Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B) 80 -> ASUS Digimatrix TV [1043:0210] 81 -> Philips Tiger reference design [1131:2018] diff --git a/drivers/media/video/cs53l32a.c b/drivers/media/video/cs53l32a.c index 7434e5e66d5..780b352ec11 100644 --- a/drivers/media/video/cs53l32a.c +++ b/drivers/media/video/cs53l32a.c @@ -25,9 +25,9 @@ #include #include #include +#include #include #include -#include MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC"); MODULE_AUTHOR("Martin Vaughan"); @@ -190,7 +190,13 @@ static int cs53l32a_attach(struct i2c_adapter *adapter, int address, int kind) static int cs53l32a_probe(struct i2c_adapter *adapter) { - return i2c_probe(adapter, &addr_data, cs53l32a_attach); +#ifdef I2C_CLASS_TV_ANALOG + if (adapter->class & I2C_CLASS_TV_ANALOG) +#else + if (adapter->id == I2C_HW_B_BT848) +#endif + return i2c_probe(adapter, &addr_data, cs53l32a_attach); + return 0; } static int cs53l32a_detach(struct i2c_client *client) diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c index 7d90ae5a99b..22f28622200 100644 --- a/drivers/media/video/wm8775.c +++ b/drivers/media/video/wm8775.c @@ -26,9 +26,9 @@ #include #include #include +#include #include #include -#include MODULE_DESCRIPTION("wm8775 driver"); MODULE_AUTHOR("Ulf Eklund"); @@ -204,14 +204,10 @@ static int wm8775_probe(struct i2c_adapter *adapter) { #ifdef I2C_CLASS_TV_ANALOG if (adapter->class & I2C_CLASS_TV_ANALOG) - return i2c_probe(adapter, &addr_data, wm8775_attach); #else - switch (adapter->id) { - case I2C_HW_B_BT848: - return i2c_probe(adapter, &addr_data, tda9887_attach); - } -#endif /* I2C_CLASS_TV_ANALOG */ - + if (adapter->id == I2C_HW_B_BT848) +#endif + return i2c_probe(adapter, &addr_data, wm8775_attach); return 0; } -- cgit v1.2.3 From c5d4a70ff82aab638b871debc9c8b27216cf1ecd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:50 -0800 Subject: [PATCH] V4L: 916: fixes set scart parameter definitions and audout ioctl Fixes set_scart parameter definitions and AUDOUT ioctl Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/msp3400.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index b599f0554fb..035dee4ce3f 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -413,7 +413,7 @@ static void msp3400c_set_scart(struct i2c_client *client, int in, int out) msp->in_scart=in; - if (in<=2) { + if (in >= 1 && in <= 8 && out >= 0 && out <= 2) { if (-1 == scarts[out][in]) return; @@ -2120,10 +2120,11 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) case VIDIOC_G_AUDOUT: { struct v4l2_audioout *a=(struct v4l2_audioout *)arg; + int idx=a->index; memset(a,0,sizeof(*a)); - switch (a->index) { + switch (idx) { case 0: strcpy(a->name,"Scart1 Out"); break; @@ -2152,8 +2153,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) else msp->i2s_mode=0; } -printk("Setting audio out on msp34xx to input %i, mode %i\n",a->index,msp->i2s_mode); - msp3400c_set_scart(client,msp->in_scart,a->index); + dprintk("Setting audio out on msp34xx to input %i, mode %i\n",a->index,msp->i2s_mode); + msp3400c_set_scart(client,msp->in_scart,a->index+1); break; } -- cgit v1.2.3 From 7bde80769ddf76a2c2e3672f2a932cfc029a1d35 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 8 Nov 2005 21:38:50 -0800 Subject: [PATCH] V4L: 917: fixes some bugs in msp3400 - Adds missing msp34xxg_reset to VIDIOC_S_STD (just like VIDIOCSCHAN). - Improves msp3400 debug messages. Now, all kernel message in msp3400.c use the same prefix and include the I2C bus to differentiate between multiple msp3400 I2C chips. - Correctly prints the chip identifier for the msp44xx chips. - msp34xxg cleanups. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/msp3400.c | 301 ++++++++++++++++++++++-------------------- 1 file changed, 159 insertions(+), 142 deletions(-) diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index 035dee4ce3f..a23fb033898 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -56,6 +56,39 @@ #include #include "msp3400.h" +#define msp3400_dbg(fmt, arg...) \ + do { \ + if (debug) \ + printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \ + i2c_adapter_id(client->adapter), client->addr , ## arg); \ + } while (0) + +/* Medium volume debug. */ +#define msp3400_dbg_mediumvol(fmt, arg...) \ + do { \ + if (debug >= 2) \ + printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \ + i2c_adapter_id(client->adapter), client->addr , ## arg); \ + } while (0) + +/* High volume debug. Use with care. */ +#define msp3400_dbg_highvol(fmt, arg...) \ + do { \ + if (debug >= 16) \ + printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \ + i2c_adapter_id(client->adapter), client->addr , ## arg); \ + } while (0) + +#define msp3400_err(fmt, arg...) do { \ + printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \ + i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) +#define msp3400_warn(fmt, arg...) do { \ + printk(KERN_WARNING "%s %d-%04x: " fmt, client->driver->name, \ + i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) +#define msp3400_info(fmt, arg...) do { \ + printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \ + i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) + #define OPMODE_AUTO -1 #define OPMODE_MANUAL 0 #define OPMODE_SIMPLE 1 /* use short programming (>= msp3410 only) */ @@ -125,10 +158,6 @@ struct msp3400c { /* ---------------------------------------------------------------------- */ -#define dprintk if (debug >= 1) printk -#define d2printk if (debug >= 2) printk -#define dprintk_trace if (debug>=16) printk - /* read-only */ module_param(opmode, int, 0444); @@ -187,11 +216,11 @@ static int msp3400c_reset(struct i2c_client *client) { client->addr, I2C_M_RD, 2, read }, }; - dprintk_trace("trace: msp3400c_reset\n"); + msp3400_dbg_highvol("msp3400c_reset\n"); if ( (1 != i2c_transfer(client->adapter,&reset[0],1)) || (1 != i2c_transfer(client->adapter,&reset[1],1)) || (2 != i2c_transfer(client->adapter,test,2)) ) { - printk(KERN_ERR "msp3400: chip reset failed\n"); + msp3400_err("chip reset failed\n"); return -1; } return 0; @@ -216,21 +245,18 @@ static int msp3400c_read(struct i2c_client *client, int dev, int addr) if (2 == i2c_transfer(client->adapter,msgs,2)) break; err++; - printk(KERN_WARNING - "msp34xx: I/O error #%d (read 0x%02x/0x%02x)\n", err, + msp3400_warn("I/O error #%d (read 0x%02x/0x%02x)\n", err, dev, addr); current->state = TASK_INTERRUPTIBLE; schedule_timeout(msecs_to_jiffies(10)); } if (3 == err) { - printk(KERN_WARNING - "msp34xx: giving up, reseting chip. Sound will go off, sorry folks :-|\n"); + msp3400_warn("giving up, resetting chip. Sound will go off, sorry folks :-|\n"); msp3400c_reset(client); return -1; } retval = read[0] << 8 | read[1]; - dprintk_trace("trace: msp3400c_read(0x%x, 0x%x): 0x%x\n", dev, addr, - retval); + msp3400_dbg_highvol("msp3400c_read(0x%x, 0x%x): 0x%x\n", dev, addr, retval); return retval; } @@ -245,21 +271,18 @@ static int msp3400c_write(struct i2c_client *client, int dev, int addr, int val) buffer[3] = val >> 8; buffer[4] = val & 0xff; - dprintk_trace("trace: msp3400c_write(0x%x, 0x%x, 0x%x)\n", dev, addr, - val); + msp3400_dbg_highvol("msp3400c_write(0x%x, 0x%x, 0x%x)\n", dev, addr, val); for (err = 0; err < 3;) { if (5 == i2c_master_send(client, buffer, 5)) break; err++; - printk(KERN_WARNING - "msp34xx: I/O error #%d (write 0x%02x/0x%02x)\n", err, + msp3400_warn("I/O error #%d (write 0x%02x/0x%02x)\n", err, dev, addr); current->state = TASK_INTERRUPTIBLE; schedule_timeout(msecs_to_jiffies(10)); } if (3 == err) { - printk(KERN_WARNING - "msp34xx: giving up, reseting chip. Sound will go off, sorry folks :-|\n"); + msp3400_warn("giving up, reseting chip. Sound will go off, sorry folks :-|\n"); msp3400c_reset(client); return -1; } @@ -422,7 +445,7 @@ static void msp3400c_set_scart(struct i2c_client *client, int in, int out) } else msp->acb = 0xf60; /* Mute Input and SCART 1 Output */ - dprintk("msp34xx: scart switch: %s => %d (ACB=0x%04x)\n", + msp3400_dbg("scart switch: %s => %d (ACB=0x%04x)\n", scart_names[in], out, msp->acb); msp3400c_write(client,I2C_MSP3400C_DFP, 0x13, msp->acb); @@ -456,7 +479,7 @@ static void msp3400c_setvolume(struct i2c_client *client, balance = ((right - left) * 127) / vol; } - dprintk("msp34xx: setvolume: mute=%s %d:%d v=0x%02x b=0x%02x\n", + msp3400_dbg("setvolume: mute=%s %d:%d v=0x%02x b=0x%02x\n", muted ? "on" : "off", left, right, val >> 8, balance); msp3400c_write(client,I2C_MSP3400C_DFP, 0x0000, val); /* loudspeaker */ msp3400c_write(client,I2C_MSP3400C_DFP, 0x0006, val); /* headphones */ @@ -469,7 +492,7 @@ static void msp3400c_setbass(struct i2c_client *client, int bass) { int val = ((bass-32768) * 0x60 / 65535) << 8; - dprintk("msp34xx: setbass: %d 0x%02x\n", bass, val >> 8); + msp3400_dbg("setbass: %d 0x%02x\n", bass, val >> 8); msp3400c_write(client,I2C_MSP3400C_DFP, 0x0002, val); /* loudspeaker */ } @@ -477,7 +500,7 @@ static void msp3400c_settreble(struct i2c_client *client, int treble) { int val = ((treble-32768) * 0x60 / 65535) << 8; - dprintk("msp34xx: settreble: %d 0x%02x\n",treble, val>>8); + msp3400_dbg("settreble: %d 0x%02x\n",treble, val>>8); msp3400c_write(client,I2C_MSP3400C_DFP, 0x0003, val); /* loudspeaker */ } @@ -486,7 +509,7 @@ static void msp3400c_setmode(struct i2c_client *client, int type) struct msp3400c *msp = i2c_get_clientdata(client); int i; - dprintk("msp3400: setmode: %d\n",type); + msp3400_dbg("setmode: %d\n",type); msp->mode = type; msp->audmode = V4L2_TUNER_MODE_MONO; msp->rxsubchans = V4L2_TUNER_SUB_MONO; @@ -565,8 +588,8 @@ static void msp3400c_setstereo(struct i2c_client *client, int mode) /* this method would break everything, let's make sure * it's never called */ - dprintk - ("msp34xxg: DEBUG WARNING setstereo called with mode=%d instead of set_source (ignored)\n", + msp3400_dbg + ("DEBUG WARNING setstereo called with mode=%d instead of set_source (ignored)\n", mode); return; } @@ -574,8 +597,7 @@ static void msp3400c_setstereo(struct i2c_client *client, int mode) /* switch demodulator */ switch (msp->mode) { case MSP_MODE_FM_TERRA: - dprintk("msp3400: FM setstereo: %s\n", - strmode[mode]); + msp3400_dbg("FM setstereo: %s\n", strmode[mode]); msp3400c_setcarrier(client,msp->second,msp->main); switch (mode) { case V4L2_TUNER_MODE_STEREO: @@ -589,7 +611,7 @@ static void msp3400c_setstereo(struct i2c_client *client, int mode) } break; case MSP_MODE_FM_SAT: - dprintk("msp3400: SAT setstereo: %s\n", strmode[mode]); + msp3400_dbg("SAT setstereo: %s\n", strmode[mode]); switch (mode) { case V4L2_TUNER_MODE_MONO: msp3400c_setcarrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5)); @@ -608,24 +630,24 @@ static void msp3400c_setstereo(struct i2c_client *client, int mode) case MSP_MODE_FM_NICAM1: case MSP_MODE_FM_NICAM2: case MSP_MODE_AM_NICAM: - dprintk("msp3400: NICAM setstereo: %s\n",strmode[mode]); + msp3400_dbg("NICAM setstereo: %s\n",strmode[mode]); msp3400c_setcarrier(client,msp->second,msp->main); if (msp->nicam_on) nicam=0x0100; break; case MSP_MODE_BTSC: - dprintk("msp3400: BTSC setstereo: %s\n",strmode[mode]); + msp3400_dbg("BTSC setstereo: %s\n",strmode[mode]); nicam=0x0300; break; case MSP_MODE_EXTERN: - dprintk("msp3400: extern setstereo: %s\n",strmode[mode]); + msp3400_dbg("extern setstereo: %s\n",strmode[mode]); nicam = 0x0200; break; case MSP_MODE_FM_RADIO: - dprintk("msp3400: FM-Radio setstereo: %s\n",strmode[mode]); + msp3400_dbg("FM-Radio setstereo: %s\n",strmode[mode]); break; default: - dprintk("msp3400: mono setstereo\n"); + msp3400_dbg("mono setstereo\n"); return; } @@ -636,7 +658,7 @@ static void msp3400c_setstereo(struct i2c_client *client, int mode) break; case V4L2_TUNER_MODE_MONO: if (msp->mode == MSP_MODE_AM_NICAM) { - dprintk("msp3400: switching to AM mono\n"); + msp3400_dbg("switching to AM mono\n"); /* AM mono decoding is handled by tuner, not MSP chip */ /* SCART switching control register */ msp3400c_set_scart(client,SCART_MONO,0); @@ -650,7 +672,7 @@ static void msp3400c_setstereo(struct i2c_client *client, int mode) src = 0x0010 | nicam; break; } - dprintk("msp3400: setstereo final source/matrix = 0x%x\n", src); + msp3400_dbg("setstereo final source/matrix = 0x%x\n", src); if (dolby) { msp3400c_write(client,I2C_MSP3400C_DFP, 0x0008,0x0520); @@ -666,24 +688,26 @@ static void msp3400c_setstereo(struct i2c_client *client, int mode) } static void -msp3400c_print_mode(struct msp3400c *msp) +msp3400c_print_mode(struct i2c_client *client) { + struct msp3400c *msp = i2c_get_clientdata(client); + if (msp->main == msp->second) { - dprintk("msp3400: mono sound carrier: %d.%03d MHz\n", + msp3400_dbg("mono sound carrier: %d.%03d MHz\n", msp->main/910000,(msp->main/910)%1000); } else { - dprintk("msp3400: main sound carrier: %d.%03d MHz\n", + msp3400_dbg("main sound carrier: %d.%03d MHz\n", msp->main/910000,(msp->main/910)%1000); } if (msp->mode == MSP_MODE_FM_NICAM1 || msp->mode == MSP_MODE_FM_NICAM2) - dprintk("msp3400: NICAM/FM carrier : %d.%03d MHz\n", + msp3400_dbg("NICAM/FM carrier : %d.%03d MHz\n", msp->second/910000,(msp->second/910)%1000); if (msp->mode == MSP_MODE_AM_NICAM) - dprintk("msp3400: NICAM/AM carrier : %d.%03d MHz\n", + msp3400_dbg("NICAM/AM carrier : %d.%03d MHz\n", msp->second/910000,(msp->second/910)%1000); if (msp->mode == MSP_MODE_FM_TERRA && msp->main != msp->second) { - dprintk("msp3400: FM-stereo carrier : %d.%03d MHz\n", + msp3400_dbg("FM-stereo carrier : %d.%03d MHz\n", msp->second/910000,(msp->second/910)%1000); } } @@ -741,7 +765,7 @@ static int autodetect_stereo(struct i2c_client *client) val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x18); if (val > 32767) val -= 65536; - dprintk("msp34xx: stereo detect register: %d\n",val); + msp3400_dbg("stereo detect register: %d\n",val); if (val > 4096) { rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; } else if (val < -4096) { @@ -755,7 +779,7 @@ static int autodetect_stereo(struct i2c_client *client) case MSP_MODE_FM_NICAM2: case MSP_MODE_AM_NICAM: val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x23); - dprintk("msp34xx: nicam sync=%d, mode=%d\n", + msp3400_dbg("nicam sync=%d, mode=%d\n", val & 1, (val & 0x1e) >> 1); if (val & 1) { @@ -788,7 +812,7 @@ static int autodetect_stereo(struct i2c_client *client) break; case MSP_MODE_BTSC: val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x200); - dprintk("msp3410: status=0x%x (pri=%s, sec=%s, %s%s%s)\n", + msp3400_dbg("status=0x%x (pri=%s, sec=%s, %s%s%s)\n", val, (val & 0x0002) ? "no" : "yes", (val & 0x0004) ? "no" : "yes", @@ -802,13 +826,13 @@ static int autodetect_stereo(struct i2c_client *client) } if (rxsubchans != msp->rxsubchans) { update = 1; - dprintk("msp34xx: watch: rxsubchans %d => %d\n", + msp3400_dbg("watch: rxsubchans %d => %d\n", msp->rxsubchans,rxsubchans); msp->rxsubchans = rxsubchans; } if (newnicam != msp->nicam_on) { update = 1; - dprintk("msp34xx: watch: nicam %d => %d\n", + msp3400_dbg("watch: nicam %d => %d\n", msp->nicam_on,newnicam); msp->nicam_on = newnicam; } @@ -865,14 +889,14 @@ static int msp3400c_thread(void *data) struct CARRIER_DETECT *cd; int count, max1,max2,val1,val2, val,this; - printk("msp3400: kthread started\n"); + msp3400_info("msp3400 daemon started\n"); for (;;) { - d2printk("msp3400: thread: sleep\n"); + msp3400_dbg_mediumvol("msp3400 thread: sleep\n"); msp34xx_sleep(msp,-1); - d2printk("msp3400: thread: wakeup\n"); + msp3400_dbg_mediumvol("msp3400 thread: wakeup\n"); restart: - dprintk("msp3410: thread: restart scan\n"); + msp3400_dbg("thread: restart scan\n"); msp->restart = 0; if (kthread_should_stop()) break; @@ -880,7 +904,7 @@ static int msp3400c_thread(void *data) if (VIDEO_MODE_RADIO == msp->norm || MSP_MODE_EXTERN == msp->mode) { /* no carrier scan, just unmute */ - printk("msp3400: thread: no carrier scan\n"); + msp3400_info("thread: no carrier scan\n"); msp3400c_setvolume(client, msp->muted, msp->left, msp->right); continue; } @@ -904,7 +928,7 @@ static int msp3400c_thread(void *data) /* autodetect doesn't work well with AM ... */ max1 = 3; count = 0; - dprintk("msp3400: AM sound override\n"); + msp3400_dbg("AM sound override\n"); } for (this = 0; this < count; this++) { @@ -916,7 +940,7 @@ static int msp3400c_thread(void *data) val -= 65536; if (val1 < val) val1 = val, max1 = this; - dprintk("msp3400: carrier1 val: %5d / %s\n", val,cd[this].name); + msp3400_dbg("carrier1 val: %5d / %s\n", val,cd[this].name); } /* carrier detect pass #2 -- second (stereo) carrier */ @@ -952,7 +976,7 @@ static int msp3400c_thread(void *data) val -= 65536; if (val2 < val) val2 = val, max2 = this; - dprintk("msp3400: carrier2 val: %5d / %s\n", val,cd[this].name); + msp3400_dbg("carrier2 val: %5d / %s\n", val,cd[this].name); } /* programm the msp3400 according to the results */ @@ -1032,7 +1056,7 @@ static int msp3400c_thread(void *data) msp3400c_restore_dfp(client); if (debug) - msp3400c_print_mode(msp); + msp3400c_print_mode(client); /* monitor tv audio mode */ while (msp->watch_stereo) { @@ -1041,7 +1065,7 @@ static int msp3400c_thread(void *data) watch_stereo(client); } } - dprintk("msp3400: thread: exit\n"); + msp3400_dbg("thread: exit\n"); return 0; } @@ -1085,11 +1109,11 @@ static inline const char *msp34xx_standard_mode_name(int mode) return "unknown"; } -static int msp34xx_modus(int norm) +static int msp34xx_modus(struct i2c_client *client, int norm) { switch (norm) { case VIDEO_MODE_PAL: - dprintk("msp34xx: video mode selected to PAL\n"); + msp3400_dbg("video mode selected to PAL\n"); #if 1 /* experimental: not sure this works with all chip versions */ @@ -1099,16 +1123,16 @@ static int msp34xx_modus(int norm) return 0x1003; #endif case VIDEO_MODE_NTSC: /* BTSC */ - dprintk("msp34xx: video mode selected to NTSC\n"); + msp3400_dbg("video mode selected to NTSC\n"); return 0x2003; case VIDEO_MODE_SECAM: - dprintk("msp34xx: video mode selected to SECAM\n"); + msp3400_dbg("video mode selected to SECAM\n"); return 0x0003; case VIDEO_MODE_RADIO: - dprintk("msp34xx: video mode selected to Radio\n"); + msp3400_dbg("video mode selected to Radio\n"); return 0x0003; case VIDEO_MODE_AUTO: - dprintk("msp34xx: video mode selected to Auto\n"); + msp3400_dbg("video mode selected to Auto\n"); return 0x2003; default: return 0x0003; @@ -1137,21 +1161,21 @@ static int msp3410d_thread(void *data) struct msp3400c *msp = i2c_get_clientdata(client); int mode,val,i,std; - printk("msp3410: daemon started\n"); + msp3400_info("msp3410 daemon started\n"); for (;;) { - d2printk("msp3410: thread: sleep\n"); + msp3400_dbg_mediumvol("msp3410 thread: sleep\n"); msp34xx_sleep(msp,-1); - d2printk("msp3410: thread: wakeup\n"); + msp3400_dbg_mediumvol("msp3410 thread: wakeup\n"); restart: - dprintk("msp3410: thread: restart scan\n"); + msp3400_dbg("thread: restart scan\n"); msp->restart = 0; if (kthread_should_stop()) break; if (msp->mode == MSP_MODE_EXTERN) { /* no carrier scan needed, just unmute */ - dprintk("msp3410: thread: no carrier scan\n"); + msp3400_dbg("thread: no carrier scan\n"); msp3400c_setvolume(client, msp->muted, msp->left, msp->right); continue; } @@ -1164,14 +1188,14 @@ static int msp3410d_thread(void *data) goto restart; /* start autodetect */ - mode = msp34xx_modus(msp->norm); + mode = msp34xx_modus(client, msp->norm); std = msp34xx_standard(msp->norm); msp3400c_write(client, I2C_MSP3400C_DEM, 0x30, mode); msp3400c_write(client, I2C_MSP3400C_DEM, 0x20, std); msp->watch_stereo = 0; if (debug) - dprintk("msp3410: setting mode: %s (0x%04x)\n", + msp3400_dbg("setting mode: %s (0x%04x)\n", msp34xx_standard_mode_name(std) ,std); if (std != 1) { @@ -1187,13 +1211,13 @@ static int msp3410d_thread(void *data) val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x7e); if (val < 0x07ff) break; - dprintk("msp3410: detection still in progress\n"); + msp3400_dbg("detection still in progress\n"); } } for (i = 0; modelist[i].name != NULL; i++) if (modelist[i].retval == val) break; - dprintk("msp3410: current mode: %s (0x%04x)\n", + msp3400_dbg("current mode: %s (0x%04x)\n", modelist[i].name ? modelist[i].name : "unknown", val); msp->main = modelist[i].main; @@ -1201,7 +1225,7 @@ static int msp3410d_thread(void *data) if (amsound && (msp->norm == VIDEO_MODE_SECAM) && (val != 0x0009)) { /* autodetection has failed, let backup */ - dprintk("msp3410: autodetection failed," + msp3400_dbg("autodetection failed," " switching to backup mode: %s (0x%04x)\n", modelist[8].name ? modelist[8].name : "unknown",val); val = 0x0009; @@ -1286,7 +1310,7 @@ static int msp3410d_thread(void *data) watch_stereo(client); } } - dprintk("msp3410: thread: exit\n"); + msp3400_dbg("thread: exit\n"); return 0; } @@ -1319,7 +1343,7 @@ static int msp34xxg_reset(struct i2c_client *client) msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode); /* step-by-step initialisation, as described in the manual */ - modus = msp34xx_modus(msp->norm); + modus = msp34xx_modus(client, msp->norm); std = msp34xx_standard(msp->norm); modus &= ~0x03; /* STATUS_CHANGE=0 */ modus |= 0x01; /* AUTOMATIC_SOUND_DETECTION=1 */ @@ -1359,15 +1383,15 @@ static int msp34xxg_thread(void *data) struct msp3400c *msp = i2c_get_clientdata(client); int val, std, i; - printk("msp34xxg: daemon started\n"); + msp3400_info("msp34xxg daemon started\n"); msp->source = 1; /* default */ for (;;) { - d2printk("msp34xxg: thread: sleep\n"); + msp3400_dbg_mediumvol("msp34xxg thread: sleep\n"); msp34xx_sleep(msp,-1); - d2printk("msp34xxg: thread: wakeup\n"); + msp3400_dbg_mediumvol("msp34xxg thread: wakeup\n"); restart: - dprintk("msp34xxg: thread: restart scan\n"); + msp3400_dbg("thread: restart scan\n"); msp->restart = 0; if (kthread_should_stop()) break; @@ -1379,7 +1403,7 @@ static int msp34xxg_thread(void *data) goto unmute; /* watch autodetect */ - dprintk("msp34xxg: triggered autodetect, waiting for result\n"); + msp3400_dbg("triggered autodetect, waiting for result\n"); for (i = 0; i < 10; i++) { if (msp34xx_sleep(msp,100)) goto restart; @@ -1390,19 +1414,19 @@ static int msp34xxg_thread(void *data) std = val; break; } - dprintk("msp34xxg: detection still in progress\n"); + msp3400_dbg("detection still in progress\n"); } if (0x01 == std) { - dprintk("msp34xxg: detection still in progress after 10 tries. giving up.\n"); + msp3400_dbg("detection still in progress after 10 tries. giving up.\n"); continue; } unmute: - dprintk("msp34xxg: current mode: %s (0x%04x)\n", + msp3400_dbg("current mode: %s (0x%04x)\n", msp34xx_standard_mode_name(std), std); /* unmute: dispatch sound to scart output, set scart volume */ - dprintk("msp34xxg: unmute\n"); + msp3400_dbg("unmute\n"); msp3400c_setbass(client, msp->bass); msp3400c_settreble(client, msp->treble); @@ -1417,7 +1441,7 @@ static int msp34xxg_thread(void *data) msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode); } - dprintk("msp34xxg: thread: exit\n"); + msp3400_dbg("thread: exit\n"); return 0; } @@ -1436,7 +1460,7 @@ static void msp34xxg_set_source(struct i2c_client *client, int source) * for MONO (source==0) downmixing set bit[7:0] to 0x30 */ int value = (source&0x07)<<8|(source==0 ? 0x30:0x20); - dprintk("msp34xxg: set source to %d (0x%x)\n", source, value); + msp3400_dbg("set source to %d (0x%x)\n", source, value); msp3400c_write(client, I2C_MSP3400C_DFP, 0x08, /* Loudspeaker Output */ @@ -1487,7 +1511,7 @@ static void msp34xxg_detect_stereo(struct i2c_client *client) * this is a problem, I'll handle SAP just like lang1/lang2. */ } - dprintk("msp34xxg: status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n", + msp3400_dbg("status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n", status, is_stereo, is_bilingual, msp->rxsubchans); } @@ -1534,7 +1558,7 @@ static void msp_wake_thread(struct i2c_client *client); static struct i2c_driver driver = { .owner = THIS_MODULE, - .name = "i2c msp3400 driver", + .name = "msp3400", .id = I2C_DRIVERID_MSP3400, .flags = I2C_DF_NOTIFY, .attach_adapter = msp_probe, @@ -1556,7 +1580,7 @@ static struct i2c_client client_template = static int msp_attach(struct i2c_adapter *adap, int addr, int kind) { struct msp3400c *msp; - struct i2c_client *c; + struct i2c_client *client = &client_template; int (*thread_func)(void *data) = NULL; int i; @@ -1564,15 +1588,15 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) client_template.addr = addr; if (-1 == msp3400c_reset(&client_template)) { - dprintk("msp34xx: no chip found\n"); + msp3400_dbg("no chip found\n"); return -1; } - if (NULL == (c = kmalloc(sizeof(struct i2c_client),GFP_KERNEL))) + if (NULL == (client = kmalloc(sizeof(struct i2c_client),GFP_KERNEL))) return -ENOMEM; - memcpy(c,&client_template,sizeof(struct i2c_client)); + memcpy(client,&client_template,sizeof(struct i2c_client)); if (NULL == (msp = kmalloc(sizeof(struct msp3400c),GFP_KERNEL))) { - kfree(c); + kfree(client); return -ENOMEM; } @@ -1588,31 +1612,32 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) for (i = 0; i < DFP_COUNT; i++) msp->dfp_regs[i] = -1; - i2c_set_clientdata(c, msp); + i2c_set_clientdata(client, msp); init_waitqueue_head(&msp->wq); - if (-1 == msp3400c_reset(c)) { + if (-1 == msp3400c_reset(client)) { kfree(msp); - kfree(c); - dprintk("msp34xx: no chip found\n"); + kfree(client); + msp3400_dbg("no chip found\n"); return -1; } - msp->rev1 = msp3400c_read(c, I2C_MSP3400C_DFP, 0x1e); + msp->rev1 = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1e); if (-1 != msp->rev1) - msp->rev2 = msp3400c_read(c, I2C_MSP3400C_DFP, 0x1f); + msp->rev2 = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1f); if ((-1 == msp->rev1) || (0 == msp->rev1 && 0 == msp->rev2)) { kfree(msp); - kfree(c); - dprintk("msp34xx: error while reading chip version\n"); + kfree(client); + msp3400_dbg("error while reading chip version\n"); return -1; } - printk(KERN_INFO "msp34xx: rev1=0x%04x, rev2=0x%04x\n", msp->rev1, msp->rev2); + msp3400_dbg("rev1=0x%04x, rev2=0x%04x\n", msp->rev1, msp->rev2); - msp3400c_setvolume(c, msp->muted, msp->left, msp->right); + msp3400c_setvolume(client, msp->muted, msp->left, msp->right); - snprintf(c->name, sizeof(c->name), "MSP34%02d%c-%c%d", - (msp->rev2>>8)&0xff, (msp->rev1&0xff)+'@', + snprintf(client->name, sizeof(client->name), "MSP%c4%02d%c-%c%d", + ((msp->rev1>>4)&0x0f) + '3', + (msp->rev2>>8)&0xff, (msp->rev1&0x0f)+'@', ((msp->rev1>>8)&0xff)+'@', msp->rev2&0x1f); msp->opmode = opmode; @@ -1626,7 +1651,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) } /* hello world :-) */ - printk(KERN_INFO "msp34xx: init: chip=%s", c->name); + msp3400_info("chip=%s", client->name); if (HAVE_NICAM(msp)) printk(" +nicam"); if (HAVE_SIMPLE(msp)) @@ -1655,20 +1680,20 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) /* startup control thread if needed */ if (thread_func) { - msp->kthread = kthread_run(thread_func, c, "msp34xx"); + msp->kthread = kthread_run(thread_func, client, "msp34xx"); if (NULL == msp->kthread) - printk(KERN_WARNING "msp34xx: kernel_thread() failed\n"); - msp_wake_thread(c); + msp3400_warn("kernel_thread() failed\n"); + msp_wake_thread(client); } /* done */ - i2c_attach_client(c); + i2c_attach_client(client); /* update our own array */ for (i = 0; i < MSP3400_MAX; i++) { if (NULL == msps[i]) { - msps[i] = c; + msps[i] = client; break; } } @@ -1791,7 +1816,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) switch (cmd) { case AUDC_SET_INPUT: - dprintk("msp34xx: AUDC_SET_INPUT(%d)\n",*sarg); + msp3400_dbg("AUDC_SET_INPUT(%d)\n",*sarg); if (*sarg == msp->input) break; @@ -1832,12 +1857,9 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) break; case AUDC_SET_RADIO: - dprintk("msp34xx: AUDC_SET_RADIO\n"); + msp3400_dbg("AUDC_SET_RADIO\n"); msp->norm = VIDEO_MODE_RADIO; - dprintk("msp34xx: switching to radio mode\n"); - if (IS_MSP34XX_G(msp)) - msp34xxg_reset(client); - + msp3400_dbg("switching to radio mode\n"); msp->watch_stereo = 0; switch (msp->opmode) { case OPMODE_MANUAL: @@ -1886,7 +1908,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct video_audio *va = arg; - dprintk("msp34xx: VIDIOCGAUDIO\n"); + msp3400_dbg("VIDIOCGAUDIO\n"); va->flags |= VIDEO_AUDIO_VOLUME | VIDEO_AUDIO_BASS | VIDEO_AUDIO_TREBLE | @@ -1914,28 +1936,28 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct video_audio *va = arg; - dprintk("msp34xx: VIDIOCSAUDIO\n"); + msp3400_dbg("VIDIOCSAUDIO\n"); msp->muted = (va->flags & VIDEO_AUDIO_MUTE); msp->left = (MIN(65536 - va->balance, 32768) * va->volume) / 32768; msp->right = (MIN(va->balance, 32768) * va->volume) / 32768; msp->bass = va->bass; msp->treble = va->treble; - dprintk("msp34xx: VIDIOCSAUDIO setting va->volume to %d\n", + msp3400_dbg("VIDIOCSAUDIO setting va->volume to %d\n", va->volume); - dprintk("msp34xx: VIDIOCSAUDIO setting va->balance to %d\n", + msp3400_dbg("VIDIOCSAUDIO setting va->balance to %d\n", va->balance); - dprintk("msp34xx: VIDIOCSAUDIO setting va->flags to %d\n", + msp3400_dbg("VIDIOCSAUDIO setting va->flags to %d\n", va->flags); - dprintk("msp34xx: VIDIOCSAUDIO setting msp->left to %d\n", + msp3400_dbg("VIDIOCSAUDIO setting msp->left to %d\n", msp->left); - dprintk("msp34xx: VIDIOCSAUDIO setting msp->right to %d\n", + msp3400_dbg("VIDIOCSAUDIO setting msp->right to %d\n", msp->right); - dprintk("msp34xx: VIDIOCSAUDIO setting msp->bass to %d\n", + msp3400_dbg("VIDIOCSAUDIO setting msp->bass to %d\n", msp->bass); - dprintk("msp34xx: VIDIOCSAUDIO setting msp->treble to %d\n", + msp3400_dbg("VIDIOCSAUDIO setting msp->treble to %d\n", msp->treble); - dprintk("msp34xx: VIDIOCSAUDIO setting msp->mode to %d\n", + msp3400_dbg("VIDIOCSAUDIO setting msp->mode to %d\n", msp->mode); msp3400c_setvolume(client, msp->muted, msp->left, msp->right); msp3400c_setbass(client, msp->bass); @@ -1950,11 +1972,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct video_channel *vc = arg; - dprintk("msp34xx: VIDIOCSCHAN (norm=%d)\n",vc->norm); + msp3400_dbg("VIDIOCSCHAN (norm=%d)\n",vc->norm); msp->norm = vc->norm; - if (IS_MSP34XX_G(msp)) - msp34xxg_reset(client); - msp_wake_thread(client); break; } @@ -1963,10 +1982,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) case VIDIOC_S_FREQUENCY: { /* new channel -- kick audio carrier scan */ - dprintk("msp34xx: VIDIOCSFREQ\n"); - if (IS_MSP34XX_G(msp)) - msp34xxg_reset(client); - + msp3400_dbg("VIDIOCSFREQ\n"); msp_wake_thread(client); break; } @@ -1976,7 +1992,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct msp_matrix *mspm = arg; - dprintk("msp34xx: MSP_SET_MATRIX\n"); + msp3400_dbg("MSP_SET_MATRIX\n"); msp3400c_set_scart(client, mspm->input, mspm->output); break; } @@ -2153,7 +2169,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) else msp->i2s_mode=0; } - dprintk("Setting audio out on msp34xx to input %i, mode %i\n",a->index,msp->i2s_mode); + msp3400_dbg("Setting audio out on msp34xx to input %i, mode %i\n", + a->index,msp->i2s_mode); msp3400c_set_scart(client,msp->in_scart,a->index+1); break; @@ -2168,19 +2185,19 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) static int msp_suspend(struct device * dev, pm_message_t state) { - struct i2c_client *c = container_of(dev, struct i2c_client, dev); + struct i2c_client *client = container_of(dev, struct i2c_client, dev); - dprintk("msp34xx: suspend\n"); - msp3400c_reset(c); + msp3400_dbg("msp34xx: suspend\n"); + msp3400c_reset(client); return 0; } static int msp_resume(struct device * dev) { - struct i2c_client *c = container_of(dev, struct i2c_client, dev); + struct i2c_client *client = container_of(dev, struct i2c_client, dev); - dprintk("msp34xx: resume\n"); - msp_wake_thread(c); + msp3400_dbg("msp34xx: resume\n"); + msp_wake_thread(client); return 0; } -- cgit v1.2.3 From 7f7e846ca552c4cf2e04b4666cea18dc26b36b59 Mon Sep 17 00:00:00 2001 From: Torsten Seeboth Date: Tue, 8 Nov 2005 21:38:51 -0800 Subject: [PATCH] V4L: 919: improves the audio handling for nicam on cx88-audio Improves the audio handling for NICAM on cx88 audio. Signed-off-by: Torsten Seeboth Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/cx88-tvaudio.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index 7815f332062..6d9bec1c583 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c @@ -123,7 +123,9 @@ static void set_audio_start(struct cx88_core *core, u32 mode) cx_write(AUD_VOL_CTL, (1 << 6)); // start programming - cx_write(AUD_CTL, 0x0000); + cx_write(MO_AUD_DMACNTRL, 0x0000); + msleep(100); + //cx_write(AUD_CTL, 0x0000); cx_write(AUD_INIT, mode); cx_write(AUD_INIT_LD, 0x0001); cx_write(AUD_SOFT_RESET, 0x0001); @@ -151,6 +153,7 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl) /* finish programming */ cx_write(AUD_SOFT_RESET, 0x0000); + cx_write(MO_AUD_DMACNTRL, 0x0003); /* unmute */ volume = cx_sread(SHADOW_AUD_VOL_CTL); @@ -341,6 +344,7 @@ static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode) { /* end of list */ }, }; + set_audio_start(core,SEL_NICAM); switch (core->tvaudio) { case WW_L: dprintk("%s SECAM-L NICAM (status: devel)\n", __FUNCTION__); @@ -740,7 +744,7 @@ void cx88_set_tvaudio(struct cx88_core *core) /* set nicam mode - otherwise AUD_NICAM_STATUS2 contains wrong values */ - set_audio_standard_NICAM(core, EN_NICAM_FORCE_MONO1); + set_audio_standard_NICAM(core, EN_NICAM_AUTO_STEREO); if (0 == cx88_detect_nicam(core)) { /* fall back to fm / am mono */ set_audio_standard_A2(core, EN_A2_FORCE_MONO1); -- cgit v1.2.3 From 9d4d9c05c807ab8a49ac0024987b223bb32c022d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:52 -0800 Subject: [PATCH] V4L: 920: fixed autodetection of max size by if alternate setting - Fixed autodetection of max size by if alternate setting - Fixed some debug messages Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-core.c | 9 +++---- drivers/media/video/em28xx/em28xx-video.c | 45 +++++++++++++++++++------------ drivers/media/video/em28xx/em28xx.h | 4 +-- 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 5cc850666fd..d54bc012748 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -797,20 +797,19 @@ int em28xx_set_alternate(struct em28xx *dev) dev->alt = alt; if (dev->alt == 0) { int i; - for(i=0;i< EM28XX_MAX_ALT; i++) + for(i=0;i< dev->num_alt; i++) if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->alt]) dev->alt=i; } if (dev->alt != prev_alt) { dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt]; - em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u", dev->alt, + em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n", dev->alt, dev->max_pkt_size); errCode = usb_set_interface(dev->udev, 0, dev->alt); if (errCode < 0) { - em28xx_errdev - ("cannot change alternate number to %d (error=%i)\n", - dev->alt, errCode); + em28xx_errdev ("cannot change alternate number to %d (error=%i)\n", + dev->alt, errCode); return errCode; } } diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 0bbfce03172..57c1826b928 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -53,8 +53,7 @@ MODULE_LICENSE("GPL"); static LIST_HEAD(em28xx_devlist); -static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; - +static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; module_param_array(card, int, NULL, 0444); MODULE_PARM_DESC(card,"card type"); @@ -1591,7 +1590,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, int retval = -ENOMEM; int errCode, i; unsigned int maxh, maxw; - struct usb_interface *uif; dev->udev = udev; dev->model = model; @@ -1651,17 +1649,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, dev->vpic.depth = 16; dev->vpic.palette = VIDEO_PALETTE_YUV422; - /* compute alternate max packet sizes */ - uif = dev->udev->actconfig->interface[0]; - dev->alt_max_pkt_size[0] = 0; - for (i = 1; i <= EM28XX_MAX_ALT && i < uif->num_altsetting ; i++) { - u16 tmp = - le16_to_cpu(uif->altsetting[i].endpoint[1].desc. - wMaxPacketSize); - dev->alt_max_pkt_size[i] = - (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - } - #ifdef CONFIG_MODULES /* request some modules */ if (dev->decoder == EM28XX_SAA7113 || dev->decoder == EM28XX_SAA7114) @@ -1756,6 +1743,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, { const struct usb_endpoint_descriptor *endpoint; struct usb_device *udev; + struct usb_interface *uif; struct em28xx *dev = NULL; int retval = -ENODEV; int model,i,nr,ifnum; @@ -1795,7 +1783,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, nr=interface->minor; if (nr>EM28XX_MAXBOARDS) { - printk ("em28xx: Supports only %i em28xx boards.\n",EM28XX_MAXBOARDS); + printk (DRIVER_NAME ": Supports only %i em28xx boards.\n",EM28XX_MAXBOARDS); return -ENOMEM; } @@ -1807,6 +1795,28 @@ static int em28xx_usb_probe(struct usb_interface *interface, } memset(dev, 0, sizeof(*dev)); + /* compute alternate max packet sizes */ + uif = udev->actconfig->interface[0]; + + dev->num_alt=uif->num_altsetting; + printk(DRIVER_NAME ": Alternate settings: %i\n",dev->num_alt); +// dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)* + dev->alt_max_pkt_size = kmalloc(32* + dev->num_alt,GFP_KERNEL); + if (dev->alt_max_pkt_size == NULL) { + em28xx_err(DRIVER_NAME ": out of memory!\n"); + return -ENOMEM; + } + + for (i = 0; i < dev->num_alt ; i++) { + u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc. + wMaxPacketSize); + dev->alt_max_pkt_size[i] = + (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); + printk(DRIVER_NAME ": Alternate setting %i, max size= %i\n",i, + dev->alt_max_pkt_size[i]); + } + snprintf(dev->name, 29, "em28xx #%d", nr); if ((card[nr]>=0)&&(card[nr]lock); - if (!dev->users) + if (!dev->users) { + kfree(dev->alt_max_pkt_size); kfree(dev); + } up_write(&em28xx_disconnect); - } static struct usb_driver em28xx_usb_driver = { diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index d51f8c63bcf..5c7a41ce69f 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -63,7 +63,6 @@ /* default alternate; 0 means choose the best */ #define EM28XX_PINOUT 0 -#define EM28XX_MAX_ALT 7 #define EM28XX_INTERLACED_DEFAULT 1 @@ -267,7 +266,8 @@ struct em28xx { struct usb_device *udev; /* the usb device */ int alt; /* alternate */ int max_pkt_size; /* max packet size of isoc transaction */ - unsigned int alt_max_pkt_size[EM28XX_MAX_ALT + 1]; /* array of wMaxPacketSize */ + int num_alt; /* Number of alternative settings */ + unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc transfer */ /* helper funcs that call usb_control_msg */ -- cgit v1.2.3 From 875c296b8ef42a796dc8db57a40b5e2228240c33 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:53 -0800 Subject: [PATCH] V4L: removal schedule for V4L1 API States a date for removing V4L1 API Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/feature-removal-schedule.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 66e4ca28fc0..429db4bf98e 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -67,6 +67,21 @@ Who: Jody McIntyre --------------------------- +What: Video4Linux API 1 ioctls and video_decoder.h from Video devices. +When: July 2006 +Why: V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6 + series. The old API have lots of drawbacks and don't provide enough + means to work with all video and audio standards. The newer API is + already available on the main drivers and should be used instead. + Newer drivers should use v4l_compat_translate_ioctl function to handle + old calls, replacing to newer ones. + Decoder iocts are using internally to allow video drivers to + communicate with video decoders. This should also be improved to allow + V4L2 calls being translated into compatible internal ioctls. +Who: Mauro Carvalho Chehab + +--------------------------- + What: i2c sysfs name change: in1_ref, vid deprecated in favour of cpu0_vid When: November 2005 Files: drivers/i2c/chips/adm1025.c, drivers/i2c/chips/adm1026.c -- cgit v1.2.3 From 79dd0c69f05fccb0396bdcd861ad4686ce888cda Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Tue, 8 Nov 2005 21:38:53 -0800 Subject: [PATCH] V4L: 925: saa7134 alsa is now a standalone module Saa7134-alsa is now a standalone module Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-alsa.c | 110 +++++++++++++++++++++++--- drivers/media/video/saa7134/saa7134-core.c | 29 ++++--- drivers/media/video/saa7134/saa7134-tvaudio.c | 3 + drivers/media/video/saa7134/saa7134.h | 8 -- 4 files changed, 121 insertions(+), 29 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index bf454437b77..7972939cb46 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -1,6 +1,5 @@ /* * SAA713x ALSA support for V4L - * Ricardo Cerqueira * * * Caveats: @@ -37,9 +36,13 @@ #include "saa7134.h" #include "saa7134-reg.h" -static unsigned int alsa_debug = 0; -module_param(alsa_debug, int, 0644); -MODULE_PARM_DESC(alsa_debug,"enable debug messages [alsa]"); +static unsigned int debug = 0; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug,"enable debug messages [alsa]"); + +unsigned int dsp_nr = 0; +module_param(dsp_nr, int, 0444); +MODULE_PARM_DESC(dsp_nr, "alsa device number"); /* * Configuration macros @@ -69,7 +72,7 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; -#define dprintk(fmt, arg...) if (alsa_debug) \ +#define dprintk(fmt, arg...) if (debug) \ printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ## arg) /* @@ -107,6 +110,7 @@ typedef struct snd_card_saa7134_pcm { static snd_card_t *snd_saa7134_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; + /* * saa7134 DMA audio stop * @@ -189,12 +193,11 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) /* next block addr */ next_blk = (dev->oss.dma_blk + 2) % dev->oss.blocks; saa_writel(reg,next_blk * dev->oss.blksize); - if (alsa_debug > 2) + if (debug > 2) dprintk("irq: ok, %s, next_blk=%d, addr=%x, blocks=%u, size=%u, read=%u\n", (status & 0x10000000) ? "even" : "odd ", next_blk, next_blk * dev->oss.blksize, dev->oss.blocks, dev->oss.blksize, dev->oss.read_count); - /* update status & wake waiting readers */ dev->oss.dma_blk = (dev->oss.dma_blk + 1) % dev->oss.blocks; dev->oss.read_count += dev->oss.blksize; @@ -211,6 +214,41 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) } +/* + * IRQ request handler + * + * Runs along with saa7134's IRQ handler, discards anything that isn't + * DMA sound + * + */ + +static irqreturn_t saa7134_alsa_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + struct saa7134_dev *dev = (struct saa7134_dev*) dev_id; + unsigned long report, status; + int loop, handled = 0; + + for (loop = 0; loop < 10; loop++) { + report = saa_readl(SAA7134_IRQ_REPORT); + status = saa_readl(SAA7134_IRQ_STATUS); + + if (report & SAA7134_IRQ_REPORT_DONE_RA3) { + handled = 1; + saa_writel(SAA7134_IRQ_REPORT,report); + saa7134_irq_alsa_done(dev, status); + } else { + goto out; + } + } + + if (loop == 10) { + dprintk("error! looping IRQ!"); + } + +out: + return IRQ_RETVAL(handled); +} + /* * ALSA capture trigger * @@ -822,11 +860,9 @@ static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL1, 0xbbbb10); if (left || right) { // We've got data, turn the input on - //saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL2, 0x101010); saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, xbarin); saa_writel(SAA7133_ANALOG_IO_SELECT, anabar); } else { - //saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL2, 0x101010); saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, 0); saa_writel(SAA7133_ANALOG_IO_SELECT, 0); } @@ -889,9 +925,10 @@ static int snd_saa7134_dev_free(snd_device_t *device) * */ -int alsa_card_saa7134_create(struct saa7134_dev *saadev, unsigned int devicenum) +int alsa_card_saa7134_create (struct saa7134_dev *saadev, unsigned int devicenum) { static int dev; + snd_card_t *card; snd_card_saa7134_t *chip; int err; @@ -899,6 +936,7 @@ int alsa_card_saa7134_create(struct saa7134_dev *saadev, unsigned int devicenum) .dev_free = snd_saa7134_dev_free, }; + if (dev >= SNDRV_CARDS) return -ENODEV; if (!enable[dev]) @@ -906,6 +944,7 @@ int alsa_card_saa7134_create(struct saa7134_dev *saadev, unsigned int devicenum) if (devicenum) { card = snd_card_new(devicenum, id[dev], THIS_MODULE, 0); + dsp_nr++; } else { card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); } @@ -931,6 +970,15 @@ int alsa_card_saa7134_create(struct saa7134_dev *saadev, unsigned int devicenum) chip->irq = saadev->pci->irq; chip->iobase = pci_resource_start(saadev->pci, 0); + err = request_irq(chip->pci->irq, saa7134_alsa_irq, + SA_SHIRQ | SA_INTERRUPT, saadev->name, saadev); + + if (err < 0) { + printk(KERN_ERR "%s: can't get IRQ %d for ALSA\n", + saadev->name, saadev->pci->irq); + return err; + } + if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { snd_saa7134_free(chip); return err; @@ -963,10 +1011,48 @@ __nodev: return err; } -void alsa_card_saa7134_exit(void) +/* + * Module initializer + * + * Loops through present saa7134 cards, and assigns an ALSA device + * to each one + * + */ + +static int saa7134_alsa_init(void) +{ + struct saa7134_dev *saadev = NULL; + struct list_head *list; + + printk(KERN_INFO "saa7134 ALSA driver for DMA sound loaded\n"); + + list_for_each(list,&saa7134_devlist) { + saadev = list_entry(list, struct saa7134_dev, devlist); + alsa_card_saa7134_create(saadev,dsp_nr); + } + + if (saadev == NULL) + printk(KERN_INFO "saa7134 ALSA: no saa7134 cards found\n"); + + return 0; + +} + +/* + * Module destructor + */ + +void saa7134_alsa_exit(void) { int idx; - for (idx = 0; idx < SNDRV_CARDS; idx++) { + for (idx = 0; idx < SNDRV_CARDS; idx++) { snd_card_free(snd_saa7134_cards[idx]); } + printk(KERN_INFO "saa7134 ALSA driver for DMA sound unloaded\n"); + return; } + +module_init(saa7134_alsa_init); +module_exit(saa7134_alsa_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ricardo Cerqueira"); diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 454b8a86c83..6c329c44057 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -574,6 +574,17 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs) dev->name); goto out; } + + /* If alsa support is active and we get a sound report, exit + and let the saa7134-alsa module deal with it */ + + if ((report & SAA7134_IRQ_REPORT_DONE_RA3) && alsa) { + if (irq_debug > 1) + printk(KERN_DEBUG "%s/irq: ignoring interrupt for ALSA\n", + dev->name); + goto out; + } + handled = 1; saa_writel(SAA7134_IRQ_REPORT,report); if (irq_debug) @@ -598,8 +609,6 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs) if ((report & SAA7134_IRQ_REPORT_DONE_RA3)) { if (oss) { saa7134_irq_oss_done(dev,status); - } else if (alsa) { - saa7134_irq_alsa_done(dev,status); } } @@ -1029,9 +1038,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, printk(KERN_INFO "%s: registered device mixer%d\n", dev->name,dev->oss.minor_mixer >> 4); } else if (alsa) { - alsa_card_saa7134_create(dev,dsp_nr[dev->nr]); - printk(KERN_INFO "%s: registered ALSA devices\n", - dev->name); + request_module("saa7134-alsa"); } break; } @@ -1059,8 +1066,6 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, case PCI_DEVICE_ID_PHILIPS_SAA7135: if (oss) unregister_sound_dsp(dev->oss.minor_dsp); - else if (alsa) - alsa_card_saa7134_exit(); break; } fail4: @@ -1120,8 +1125,7 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) if (oss) { unregister_sound_mixer(dev->oss.minor_mixer); unregister_sound_dsp(dev->oss.minor_dsp); - } else if (alsa) - alsa_card_saa7134_exit(); + } break; } saa7134_unregister_video(dev); @@ -1214,6 +1218,13 @@ EXPORT_SYMBOL(saa7134_i2c_call_clients); EXPORT_SYMBOL(saa7134_devlist); EXPORT_SYMBOL(saa7134_boards); +/* ----------------- For ALSA -------------------------------- */ + +EXPORT_SYMBOL(saa7134_pgtable_free); +EXPORT_SYMBOL(saa7134_pgtable_build); +EXPORT_SYMBOL(saa7134_pgtable_alloc); +EXPORT_SYMBOL(saa7134_set_dmabits); + /* ----------------------------------------------------------- */ /* * Local variables: diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index 3daf1b59795..93268427750 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -1024,9 +1024,12 @@ int saa7134_tvaudio_do_scan(struct saa7134_dev *dev) return 0; } +EXPORT_SYMBOL(saa_dsp_writel); + /* ----------------------------------------------------------- */ /* * Local variables: * c-basic-offset: 8 * End: */ + diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index d993344d37e..1fdc9e147f8 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -665,14 +665,6 @@ void saa7134_input_fini(struct saa7134_dev *dev); void saa7134_input_irq(struct saa7134_dev *dev); void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir); -/* ----------------------------------------------------------- */ -/* saa7134-alsa.c */ - -int alsa_card_saa7134_create(struct saa7134_dev *saadev, unsigned int devnum); -void alsa_card_saa7134_exit(void); -void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status); - - /* * Local variables: * c-basic-offset: 8 -- cgit v1.2.3 From b54134be53be720da423692665ec215eb14a678b Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Tue, 8 Nov 2005 21:38:54 -0800 Subject: [PATCH] V4L: 926: Saa7134 alsa can only be autoloaded after saa7134 is active - Saa7134-alsa can only be autoloaded after saa7134 is active - Applied pertinent changes proposed by the ALSA team - dsp_nr replaced by ALSA's index[] Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-alsa.c | 239 +++++++++++----------- drivers/media/video/saa7134/saa7134-core.c | 27 ++- drivers/media/video/saa7134/saa7134-oss.c | 308 ++++++++++++++--------------- drivers/media/video/saa7134/saa7134.h | 6 +- 4 files changed, 288 insertions(+), 292 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 7972939cb46..4f3c4235432 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include "saa7134.h" @@ -40,29 +39,11 @@ static unsigned int debug = 0; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"enable debug messages [alsa]"); -unsigned int dsp_nr = 0; -module_param(dsp_nr, int, 0444); -MODULE_PARM_DESC(dsp_nr, "alsa device number"); - /* * Configuration macros */ /* defaults */ -#define MAX_BUFFER_SIZE (256*1024) -#define USE_FORMATS SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE -#define USE_RATE SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 -#define USE_RATE_MIN 32000 -#define USE_RATE_MAX 48000 -#define USE_CHANNELS_MIN 1 -#define USE_CHANNELS_MAX 2 -#ifndef USE_PERIODS_MIN -#define USE_PERIODS_MIN 2 -#endif -#ifndef USE_PERIODS_MAX -#define USE_PERIODS_MAX 1024 -#endif - #define MIXER_ADDR_TVTUNER 0 #define MIXER_ADDR_LINE1 1 #define MIXER_ADDR_LINE2 2 @@ -72,6 +53,9 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; +module_param_array(index, int, NULL, 0444); +MODULE_PARM_DESC(index, "Index value for SAA7134 capture interface(s)."); + #define dprintk(fmt, arg...) if (debug) \ printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ## arg) @@ -108,7 +92,7 @@ typedef struct snd_card_saa7134_pcm { snd_pcm_substream_t *substream; } snd_card_saa7134_pcm_t; -static snd_card_t *snd_saa7134_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; +static snd_card_t *snd_saa7134_cards[SNDRV_CARDS]; /* @@ -124,8 +108,8 @@ static snd_card_t *snd_saa7134_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; static void saa7134_dma_stop(struct saa7134_dev *dev) { - dev->oss.dma_blk = -1; - dev->oss.dma_running = 0; + dev->dmasound.dma_blk = -1; + dev->dmasound.dma_running = 0; saa7134_set_dmabits(dev); } @@ -141,8 +125,8 @@ static void saa7134_dma_stop(struct saa7134_dev *dev) static void saa7134_dma_start(struct saa7134_dev *dev) { - dev->oss.dma_blk = 0; - dev->oss.dma_running = 1; + dev->dmasound.dma_blk = 0; + dev->dmasound.dma_running = 1; saa7134_set_dmabits(dev); } @@ -162,7 +146,7 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) int next_blk, reg = 0; spin_lock(&dev->slock); - if (UNSET == dev->oss.dma_blk) { + if (UNSET == dev->dmasound.dma_blk) { dprintk("irq: recording stopped\n"); goto done; } @@ -170,11 +154,11 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) dprintk("irq: lost %ld\n", (status >> 24) & 0x0f); if (0 == (status & 0x10000000)) { /* odd */ - if (0 == (dev->oss.dma_blk & 0x01)) + if (0 == (dev->dmasound.dma_blk & 0x01)) reg = SAA7134_RS_BA1(6); } else { /* even */ - if (1 == (dev->oss.dma_blk & 0x01)) + if (1 == (dev->dmasound.dma_blk & 0x01)) reg = SAA7134_RS_BA2(6); } if (0 == reg) { @@ -183,30 +167,31 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) goto done; } - if (dev->oss.read_count >= dev->oss.blksize * (dev->oss.blocks-2)) { - dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->oss.read_count, - dev->oss.bufsize, dev->oss.blocks); + if (dev->dmasound.read_count >= dev->dmasound.blksize * (dev->dmasound.blocks-2)) { + dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->dmasound.read_count, + dev->dmasound.bufsize, dev->dmasound.blocks); + snd_pcm_stop(dev->dmasound.substream,SNDRV_PCM_STATE_XRUN); saa7134_dma_stop(dev); goto done; } /* next block addr */ - next_blk = (dev->oss.dma_blk + 2) % dev->oss.blocks; - saa_writel(reg,next_blk * dev->oss.blksize); + next_blk = (dev->dmasound.dma_blk + 2) % dev->dmasound.blocks; + saa_writel(reg,next_blk * dev->dmasound.blksize); if (debug > 2) dprintk("irq: ok, %s, next_blk=%d, addr=%x, blocks=%u, size=%u, read=%u\n", (status & 0x10000000) ? "even" : "odd ", next_blk, - next_blk * dev->oss.blksize, dev->oss.blocks, dev->oss.blksize, dev->oss.read_count); + next_blk * dev->dmasound.blksize, dev->dmasound.blocks, dev->dmasound.blksize, dev->dmasound.read_count); /* update status & wake waiting readers */ - dev->oss.dma_blk = (dev->oss.dma_blk + 1) % dev->oss.blocks; - dev->oss.read_count += dev->oss.blksize; + dev->dmasound.dma_blk = (dev->dmasound.dma_blk + 1) % dev->dmasound.blocks; + dev->dmasound.read_count += dev->dmasound.blksize; - dev->oss.recording_on = reg; + dev->dmasound.recording_on = reg; - if (dev->oss.read_count >= snd_pcm_lib_period_bytes(dev->oss.substream)) { + if (dev->dmasound.read_count >= snd_pcm_lib_period_bytes(dev->dmasound.substream)) { spin_unlock(&dev->slock); - snd_pcm_period_elapsed(dev->oss.substream); + snd_pcm_period_elapsed(dev->dmasound.substream); spin_lock(&dev->slock); } done: @@ -262,7 +247,24 @@ out: static int snd_card_saa7134_capture_trigger(snd_pcm_substream_t * substream, int cmd) { - return 0; + snd_pcm_runtime_t *runtime = substream->runtime; + snd_card_saa7134_pcm_t *saapcm = runtime->private_data; + struct saa7134_dev *dev=saapcm->saadev; + int err = 0; + + spin_lock_irq(&dev->slock); + if (cmd == SNDRV_PCM_TRIGGER_START) { + /* start dma */ + saa7134_dma_start(dev); + } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { + /* stop dma */ + saa7134_dma_stop(dev); + } else { + err = -EINVAL; + } + spin_unlock_irq(&dev->slock); + + return err; } /* @@ -289,9 +291,9 @@ static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) if ((blksize * blocks) > 1024*1024) blocks = 1024*1024 / blksize; - dev->oss.blocks = blocks; - dev->oss.blksize = blksize; - dev->oss.bufsize = blksize * blocks; + dev->dmasound.blocks = blocks; + dev->dmasound.blksize = blksize; + dev->dmasound.bufsize = blksize * blocks; dprintk("buffer config: %d blocks / %d bytes, %d kB total\n", blocks,blksize,blksize * blocks / 1024); @@ -313,11 +315,11 @@ static int dsp_buffer_init(struct saa7134_dev *dev) { int err; - if (!dev->oss.bufsize) + if (!dev->dmasound.bufsize) BUG(); - videobuf_dma_init(&dev->oss.dma); - err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE, - (dev->oss.bufsize + PAGE_SIZE) >> PAGE_SHIFT); + videobuf_dma_init(&dev->dmasound.dma); + err = videobuf_dma_init_kernel(&dev->dmasound.dma, PCI_DMA_FROMDEVICE, + (dev->dmasound.bufsize + PAGE_SIZE) >> PAGE_SHIFT); if (0 != err) return err; return 0; @@ -340,7 +342,6 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) snd_pcm_runtime_t *runtime = substream->runtime; int err, bswap, sign; u32 fmt, control; - unsigned long flags; snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); struct saa7134_dev *dev; snd_card_saa7134_pcm_t *saapcm = runtime->private_data; @@ -351,7 +352,7 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) size = snd_pcm_lib_buffer_bytes(substream); count = snd_pcm_lib_period_bytes(substream); - saapcm->saadev->oss.substream = substream; + saapcm->saadev->dmasound.substream = substream; bps = runtime->rate * runtime->channels; bps *= snd_pcm_format_width(runtime->format); bps /= 8; @@ -371,13 +372,13 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) goto fail2; /* prepare buffer */ - if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->oss.dma))) + if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->dmasound.dma))) return err; - if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->oss.pt))) + if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) goto fail1; - if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->oss.pt, - dev->oss.dma.sglist, - dev->oss.dma.sglen, + if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->dmasound.pt, + dev->dmasound.dma.sglist, + dev->dmasound.dma.sglen, 0))) goto fail2; @@ -427,10 +428,10 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) if (sign) fmt |= 0x04; - fmt |= (MIXER_ADDR_TVTUNER == dev->oss.input) ? 0xc0 : 0x80; - saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->oss.blksize - 1) & 0x0000ff)); - saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->oss.blksize - 1) & 0x00ff00) >> 8); - saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->oss.blksize - 1) & 0xff0000) >> 16); + fmt |= (MIXER_ADDR_TVTUNER == dev->dmasound.input) ? 0xc0 : 0x80; + saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->dmasound.blksize - 1) & 0x0000ff)); + saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->dmasound.blksize - 1) & 0x00ff00) >> 8); + saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->dmasound.blksize - 1) & 0xff0000) >> 16); saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt); break; @@ -442,7 +443,7 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) fmt |= (2 << 4); if (!sign) fmt |= 0x04; - saa_writel(SAA7133_NUM_SAMPLES, dev->oss.blksize -1); + saa_writel(SAA7133_NUM_SAMPLES, dev->dmasound.blksize -1); saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24)); //saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210); break; @@ -454,7 +455,7 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) /* dma: setup channel 6 (= AUDIO) */ control = SAA7134_RS_CONTROL_BURST_16 | SAA7134_RS_CONTROL_ME | - (dev->oss.pt.dma >> 12); + (dev->dmasound.pt.dma >> 12); if (bswap) control |= SAA7134_RS_CONTROL_BSWAP; @@ -462,24 +463,20 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) byte, but it doesn't work. So I allocate the DMA using the V4L functions, and force ALSA to use that as the DMA area */ - runtime->dma_area = dev->oss.dma.vmalloc; + runtime->dma_area = dev->dmasound.dma.vmalloc; saa_writel(SAA7134_RS_BA1(6),0); - saa_writel(SAA7134_RS_BA2(6),dev->oss.blksize); + saa_writel(SAA7134_RS_BA2(6),dev->dmasound.blksize); saa_writel(SAA7134_RS_PITCH(6),0); saa_writel(SAA7134_RS_CONTROL(6),control); - dev->oss.rate = runtime->rate; - /* start dma */ - spin_lock_irqsave(&dev->slock,flags); - saa7134_dma_start(dev); - spin_unlock_irqrestore(&dev->slock,flags); + dev->dmasound.rate = runtime->rate; return 0; fail2: - saa7134_pgtable_free(dev->pci,&dev->oss.pt); + saa7134_pgtable_free(dev->pci,&dev->dmasound.pt); fail1: - videobuf_dma_pci_unmap(dev->pci,&dev->oss.dma); + videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma); return err; @@ -504,14 +501,14 @@ static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * - if (dev->oss.read_count) { - dev->oss.read_count -= snd_pcm_lib_period_bytes(substream); - dev->oss.read_offset += snd_pcm_lib_period_bytes(substream); - if (dev->oss.read_offset == dev->oss.bufsize) - dev->oss.read_offset = 0; + if (dev->dmasound.read_count) { + dev->dmasound.read_count -= snd_pcm_lib_period_bytes(substream); + dev->dmasound.read_offset += snd_pcm_lib_period_bytes(substream); + if (dev->dmasound.read_offset == dev->dmasound.bufsize) + dev->dmasound.read_offset = 0; } - return bytes_to_frames(runtime, dev->oss.read_offset); + return bytes_to_frames(runtime, dev->dmasound.read_offset); } /* @@ -523,18 +520,22 @@ static snd_pcm_hardware_t snd_card_saa7134_capture = .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID), - .formats = USE_FORMATS, - .rates = USE_RATE, - .rate_min = USE_RATE_MIN, - .rate_max = USE_RATE_MAX, - .channels_min = USE_CHANNELS_MIN, - .channels_max = USE_CHANNELS_MAX, - .buffer_bytes_max = MAX_BUFFER_SIZE, + .formats = SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S16_BE | \ + SNDRV_PCM_FMTBIT_S8 | \ + SNDRV_PCM_FMTBIT_U8 | \ + SNDRV_PCM_FMTBIT_U16_LE | \ + SNDRV_PCM_FMTBIT_U16_BE, + .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + .rate_min = 32000, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 2, + .buffer_bytes_max = (256*1024), .period_bytes_min = 64, - .period_bytes_max = MAX_BUFFER_SIZE, - .periods_min = USE_PERIODS_MIN, - .periods_max = USE_PERIODS_MAX, - .fifo_size = 0x08070503, + .period_bytes_max = (256*1024), + .periods_min = 2, + .periods_max = 1024, }; static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime) @@ -590,14 +591,14 @@ static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream) static int dsp_buffer_free(struct saa7134_dev *dev) { - if (!dev->oss.blksize) + if (!dev->dmasound.blksize) BUG(); - videobuf_dma_free(&dev->oss.dma); + videobuf_dma_free(&dev->dmasound.dma); - dev->oss.blocks = 0; - dev->oss.blksize = 0; - dev->oss.bufsize = 0; + dev->dmasound.blocks = 0; + dev->dmasound.blksize = 0; + dev->dmasound.bufsize = 0; return 0; } @@ -616,16 +617,10 @@ static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) { snd_card_saa7134_t *chip = snd_pcm_substream_chip(substream); struct saa7134_dev *dev = chip->saadev; - unsigned long flags; - - /* stop dma */ - spin_lock_irqsave(&dev->slock,flags); - saa7134_dma_stop(dev); - spin_unlock_irqrestore(&dev->slock,flags); /* unlock buffer */ - saa7134_pgtable_free(dev->pci,&dev->oss.pt); - videobuf_dma_pci_unmap(dev->pci,&dev->oss.dma); + saa7134_pgtable_free(dev->pci,&dev->dmasound.pt); + videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma); dsp_buffer_free(dev); return 0; @@ -649,16 +644,16 @@ static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) struct saa7134_dev *dev = saa7134->saadev; int err; - down(&dev->oss.lock); + down(&dev->dmasound.lock); - dev->oss.afmt = SNDRV_PCM_FORMAT_U8; - dev->oss.channels = 2; - dev->oss.read_count = 0; - dev->oss.read_offset = 0; + dev->dmasound.afmt = SNDRV_PCM_FORMAT_U8; + dev->dmasound.channels = 2; + dev->dmasound.read_count = 0; + dev->dmasound.read_offset = 0; - up(&dev->oss.lock); + up(&dev->dmasound.lock); - saapcm = kcalloc(1, sizeof(*saapcm), GFP_KERNEL); + saapcm = kzalloc(sizeof(*saapcm), GFP_KERNEL); if (saapcm == NULL) return -ENOMEM; saapcm->saadev=saa7134->saadev; @@ -731,13 +726,10 @@ static int snd_saa7134_volume_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_ static int snd_saa7134_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) { snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; int addr = kcontrol->private_value; - spin_lock_irqsave(&chip->mixer_lock, flags); ucontrol->value.integer.value[0] = chip->mixer_volume[addr][0]; ucontrol->value.integer.value[1] = chip->mixer_volume[addr][1]; - spin_unlock_irqrestore(&chip->mixer_lock, flags); return 0; } @@ -815,7 +807,7 @@ static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ chip->capture_source[addr][1] != right; chip->capture_source[addr][0] = left; chip->capture_source[addr][1] = right; - dev->oss.input=addr; + dev->dmasound.input=addr; spin_unlock_irqrestore(&chip->mixer_lock, flags); @@ -831,7 +823,7 @@ static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ case MIXER_ADDR_LINE1: case MIXER_ADDR_LINE2: analog_io = (MIXER_ADDR_LINE1 == addr) ? 0x00 : 0x08; - rate = (32000 == dev->oss.rate) ? 0x01 : 0x03; + rate = (32000 == dev->dmasound.rate) ? 0x01 : 0x03; saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, analog_io); saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0x80); saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, rate); @@ -925,7 +917,7 @@ static int snd_saa7134_dev_free(snd_device_t *device) * */ -int alsa_card_saa7134_create (struct saa7134_dev *saadev, unsigned int devicenum) +int alsa_card_saa7134_create (struct saa7134_dev *saadev) { static int dev; @@ -942,12 +934,8 @@ int alsa_card_saa7134_create (struct saa7134_dev *saadev, unsigned int devicenum if (!enable[dev]) return -ENODEV; - if (devicenum) { - card = snd_card_new(devicenum, id[dev], THIS_MODULE, 0); - dsp_nr++; - } else { - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - } + card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); + if (card == NULL) return -ENOMEM; @@ -961,6 +949,7 @@ int alsa_card_saa7134_create (struct saa7134_dev *saadev, unsigned int devicenum } spin_lock_init(&chip->lock); + spin_lock_init(&chip->mixer_lock); chip->saadev = saadev; @@ -970,18 +959,17 @@ int alsa_card_saa7134_create (struct saa7134_dev *saadev, unsigned int devicenum chip->irq = saadev->pci->irq; chip->iobase = pci_resource_start(saadev->pci, 0); - err = request_irq(chip->pci->irq, saa7134_alsa_irq, + err = request_irq(saadev->pci->irq, saa7134_alsa_irq, SA_SHIRQ | SA_INTERRUPT, saadev->name, saadev); if (err < 0) { printk(KERN_ERR "%s: can't get IRQ %d for ALSA\n", saadev->name, saadev->pci->irq); - return err; + goto __nodev; } if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_saa7134_free(chip); - return err; + goto __nodev; } if ((err = snd_card_saa7134_new_mixer(chip)) < 0) @@ -990,8 +978,6 @@ int alsa_card_saa7134_create (struct saa7134_dev *saadev, unsigned int devicenum if ((err = snd_card_saa7134_pcm(chip, 0)) < 0) goto __nodev; - spin_lock_init(&chip->mixer_lock); - snd_card_set_dev(card, &chip->pci->dev); /* End of "creation" */ @@ -1007,7 +993,7 @@ int alsa_card_saa7134_create (struct saa7134_dev *saadev, unsigned int devicenum __nodev: snd_card_free(card); - kfree(card); + kfree(chip); return err; } @@ -1028,7 +1014,7 @@ static int saa7134_alsa_init(void) list_for_each(list,&saa7134_devlist) { saadev = list_entry(list, struct saa7134_dev, devlist); - alsa_card_saa7134_create(saadev,dsp_nr); + alsa_card_saa7134_create(saadev); } if (saadev == NULL) @@ -1045,10 +1031,13 @@ static int saa7134_alsa_init(void) void saa7134_alsa_exit(void) { int idx; + for (idx = 0; idx < SNDRV_CARDS; idx++) { snd_card_free(snd_saa7134_cards[idx]); } + printk(KERN_INFO "saa7134 ALSA driver for DMA sound unloaded\n"); + return; } diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 6c329c44057..19b88744fb3 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -194,6 +194,7 @@ void saa7134_track_gpio(struct saa7134_dev *dev, char *msg) static int need_empress; static int need_dvb; +static int need_alsa; static int pending_call(struct notifier_block *self, unsigned long state, void *module) @@ -205,6 +206,8 @@ static int pending_call(struct notifier_block *self, unsigned long state, request_module("saa7134-empress"); if (need_dvb) request_module("saa7134-dvb"); + if (need_alsa) + request_module("saa7134-alsa"); return NOTIFY_DONE; } @@ -469,7 +472,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev) } /* audio capture -- dma 3 */ - if (dev->oss.dma_running) { + if (dev->dmasound.dma_running) { ctrl |= SAA7134_MAIN_CTRL_TE6; irq |= SAA7134_IRQ1_INTE_RA3_1 | SAA7134_IRQ1_INTE_RA3_0; @@ -983,6 +986,12 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, if (card_is_dvb(dev)) request_module_depend("saa7134-dvb",&need_dvb); + if (!oss && alsa) { + dprintk("Requesting ALSA module\n"); + request_module_depend("saa7134-alsa",&need_alsa); + } + + v4l2_prio_init(&dev->prio); /* register v4l devices */ @@ -1021,24 +1030,22 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, case PCI_DEVICE_ID_PHILIPS_SAA7133: case PCI_DEVICE_ID_PHILIPS_SAA7135: if (oss) { - err = dev->oss.minor_dsp = + err = dev->dmasound.minor_dsp = register_sound_dsp(&saa7134_dsp_fops, dsp_nr[dev->nr]); if (err < 0) { goto fail4; } printk(KERN_INFO "%s: registered device dsp%d\n", - dev->name,dev->oss.minor_dsp >> 4); + dev->name,dev->dmasound.minor_dsp >> 4); - err = dev->oss.minor_mixer = + err = dev->dmasound.minor_mixer = register_sound_mixer(&saa7134_mixer_fops, mixer_nr[dev->nr]); if (err < 0) goto fail5; printk(KERN_INFO "%s: registered device mixer%d\n", - dev->name,dev->oss.minor_mixer >> 4); - } else if (alsa) { - request_module("saa7134-alsa"); + dev->name,dev->dmasound.minor_mixer >> 4); } break; } @@ -1065,7 +1072,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, case PCI_DEVICE_ID_PHILIPS_SAA7133: case PCI_DEVICE_ID_PHILIPS_SAA7135: if (oss) - unregister_sound_dsp(dev->oss.minor_dsp); + unregister_sound_dsp(dev->dmasound.minor_dsp); break; } fail4: @@ -1123,8 +1130,8 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) case PCI_DEVICE_ID_PHILIPS_SAA7133: case PCI_DEVICE_ID_PHILIPS_SAA7135: if (oss) { - unregister_sound_mixer(dev->oss.minor_mixer); - unregister_sound_dsp(dev->oss.minor_dsp); + unregister_sound_mixer(dev->dmasound.minor_mixer); + unregister_sound_dsp(dev->dmasound.minor_dsp); } break; } diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c index f1b0e0d93d7..fd53dfcc164 100644 --- a/drivers/media/video/saa7134/saa7134-oss.c +++ b/drivers/media/video/saa7134/saa7134-oss.c @@ -59,9 +59,9 @@ static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) if ((blksize * blocks) > 1024*1024) blocks = 1024*1024 / blksize; - dev->oss.blocks = blocks; - dev->oss.blksize = blksize; - dev->oss.bufsize = blksize * blocks; + dev->dmasound.blocks = blocks; + dev->dmasound.blksize = blksize; + dev->dmasound.bufsize = blksize * blocks; dprintk("buffer config: %d blocks / %d bytes, %d kB total\n", blocks,blksize,blksize * blocks / 1024); @@ -72,11 +72,11 @@ static int dsp_buffer_init(struct saa7134_dev *dev) { int err; - if (!dev->oss.bufsize) + if (!dev->dmasound.bufsize) BUG(); - videobuf_dma_init(&dev->oss.dma); - err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE, - (dev->oss.bufsize + PAGE_SIZE) >> PAGE_SHIFT); + videobuf_dma_init(&dev->dmasound.dma); + err = videobuf_dma_init_kernel(&dev->dmasound.dma, PCI_DMA_FROMDEVICE, + (dev->dmasound.bufsize + PAGE_SIZE) >> PAGE_SHIFT); if (0 != err) return err; return 0; @@ -84,26 +84,26 @@ static int dsp_buffer_init(struct saa7134_dev *dev) static int dsp_buffer_free(struct saa7134_dev *dev) { - if (!dev->oss.blksize) + if (!dev->dmasound.blksize) BUG(); - videobuf_dma_free(&dev->oss.dma); - dev->oss.blocks = 0; - dev->oss.blksize = 0; - dev->oss.bufsize = 0; + videobuf_dma_free(&dev->dmasound.dma); + dev->dmasound.blocks = 0; + dev->dmasound.blksize = 0; + dev->dmasound.bufsize = 0; return 0; } static void dsp_dma_start(struct saa7134_dev *dev) { - dev->oss.dma_blk = 0; - dev->oss.dma_running = 1; + dev->dmasound.dma_blk = 0; + dev->dmasound.dma_running = 1; saa7134_set_dmabits(dev); } static void dsp_dma_stop(struct saa7134_dev *dev) { - dev->oss.dma_blk = -1; - dev->oss.dma_running = 0; + dev->dmasound.dma_blk = -1; + dev->dmasound.dma_running = 0; saa7134_set_dmabits(dev); } @@ -114,18 +114,18 @@ static int dsp_rec_start(struct saa7134_dev *dev) unsigned long flags; /* prepare buffer */ - if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->oss.dma))) + if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->dmasound.dma))) return err; - if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->oss.pt))) + if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) goto fail1; - if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->oss.pt, - dev->oss.dma.sglist, - dev->oss.dma.sglen, + if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->dmasound.pt, + dev->dmasound.dma.sglist, + dev->dmasound.dma.sglen, 0))) goto fail2; /* sample format */ - switch (dev->oss.afmt) { + switch (dev->dmasound.afmt) { case AFMT_U8: case AFMT_S8: fmt = 0x00; break; case AFMT_U16_LE: @@ -137,14 +137,14 @@ static int dsp_rec_start(struct saa7134_dev *dev) goto fail2; } - switch (dev->oss.afmt) { + switch (dev->dmasound.afmt) { case AFMT_S8: case AFMT_S16_LE: case AFMT_S16_BE: sign = 1; break; default: sign = 0; break; } - switch (dev->oss.afmt) { + switch (dev->dmasound.afmt) { case AFMT_U16_BE: case AFMT_S16_BE: bswap = 1; break; default: bswap = 0; break; @@ -152,58 +152,58 @@ static int dsp_rec_start(struct saa7134_dev *dev) switch (dev->pci->device) { case PCI_DEVICE_ID_PHILIPS_SAA7134: - if (1 == dev->oss.channels) + if (1 == dev->dmasound.channels) fmt |= (1 << 3); - if (2 == dev->oss.channels) + if (2 == dev->dmasound.channels) fmt |= (3 << 3); if (sign) fmt |= 0x04; - fmt |= (TV == dev->oss.input) ? 0xc0 : 0x80; + fmt |= (TV == dev->dmasound.input) ? 0xc0 : 0x80; - saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->oss.blksize - 1) & 0x0000ff)); - saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->oss.blksize - 1) & 0x00ff00) >> 8); - saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->oss.blksize - 1) & 0xff0000) >> 16); + saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->dmasound.blksize - 1) & 0x0000ff)); + saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->dmasound.blksize - 1) & 0x00ff00) >> 8); + saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->dmasound.blksize - 1) & 0xff0000) >> 16); saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt); break; case PCI_DEVICE_ID_PHILIPS_SAA7133: case PCI_DEVICE_ID_PHILIPS_SAA7135: - if (1 == dev->oss.channels) + if (1 == dev->dmasound.channels) fmt |= (1 << 4); - if (2 == dev->oss.channels) + if (2 == dev->dmasound.channels) fmt |= (2 << 4); if (!sign) fmt |= 0x04; - saa_writel(SAA7133_NUM_SAMPLES, dev->oss.blksize -4); + saa_writel(SAA7133_NUM_SAMPLES, dev->dmasound.blksize -4); saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24)); break; } dprintk("rec_start: afmt=%d ch=%d => fmt=0x%x swap=%c\n", - dev->oss.afmt, dev->oss.channels, fmt, + dev->dmasound.afmt, dev->dmasound.channels, fmt, bswap ? 'b' : '-'); /* dma: setup channel 6 (= AUDIO) */ control = SAA7134_RS_CONTROL_BURST_16 | SAA7134_RS_CONTROL_ME | - (dev->oss.pt.dma >> 12); + (dev->dmasound.pt.dma >> 12); if (bswap) control |= SAA7134_RS_CONTROL_BSWAP; saa_writel(SAA7134_RS_BA1(6),0); - saa_writel(SAA7134_RS_BA2(6),dev->oss.blksize); + saa_writel(SAA7134_RS_BA2(6),dev->dmasound.blksize); saa_writel(SAA7134_RS_PITCH(6),0); saa_writel(SAA7134_RS_CONTROL(6),control); /* start dma */ - dev->oss.recording_on = 1; + dev->dmasound.recording_on = 1; spin_lock_irqsave(&dev->slock,flags); dsp_dma_start(dev); spin_unlock_irqrestore(&dev->slock,flags); return 0; fail2: - saa7134_pgtable_free(dev->pci,&dev->oss.pt); + saa7134_pgtable_free(dev->pci,&dev->dmasound.pt); fail1: - videobuf_dma_pci_unmap(dev->pci,&dev->oss.dma); + videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma); return err; } @@ -211,17 +211,17 @@ static int dsp_rec_stop(struct saa7134_dev *dev) { unsigned long flags; - dprintk("rec_stop dma_blk=%d\n",dev->oss.dma_blk); + dprintk("rec_stop dma_blk=%d\n",dev->dmasound.dma_blk); /* stop dma */ - dev->oss.recording_on = 0; + dev->dmasound.recording_on = 0; spin_lock_irqsave(&dev->slock,flags); dsp_dma_stop(dev); spin_unlock_irqrestore(&dev->slock,flags); /* unlock buffer */ - saa7134_pgtable_free(dev->pci,&dev->oss.pt); - videobuf_dma_pci_unmap(dev->pci,&dev->oss.dma); + saa7134_pgtable_free(dev->pci,&dev->dmasound.pt); + videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma); return 0; } @@ -236,35 +236,35 @@ static int dsp_open(struct inode *inode, struct file *file) list_for_each(list,&saa7134_devlist) { h = list_entry(list, struct saa7134_dev, devlist); - if (h->oss.minor_dsp == minor) + if (h->dmasound.minor_dsp == minor) dev = h; } if (NULL == dev) return -ENODEV; - down(&dev->oss.lock); + down(&dev->dmasound.lock); err = -EBUSY; - if (dev->oss.users_dsp) + if (dev->dmasound.users_dsp) goto fail1; - dev->oss.users_dsp++; + dev->dmasound.users_dsp++; file->private_data = dev; - dev->oss.afmt = AFMT_U8; - dev->oss.channels = 1; - dev->oss.read_count = 0; - dev->oss.read_offset = 0; + dev->dmasound.afmt = AFMT_U8; + dev->dmasound.channels = 1; + dev->dmasound.read_count = 0; + dev->dmasound.read_offset = 0; dsp_buffer_conf(dev,PAGE_SIZE,64); err = dsp_buffer_init(dev); if (0 != err) goto fail2; - up(&dev->oss.lock); + up(&dev->dmasound.lock); return 0; fail2: - dev->oss.users_dsp--; + dev->dmasound.users_dsp--; fail1: - up(&dev->oss.lock); + up(&dev->dmasound.lock); return err; } @@ -272,13 +272,13 @@ static int dsp_release(struct inode *inode, struct file *file) { struct saa7134_dev *dev = file->private_data; - down(&dev->oss.lock); - if (dev->oss.recording_on) + down(&dev->dmasound.lock); + if (dev->dmasound.recording_on) dsp_rec_stop(dev); dsp_buffer_free(dev); - dev->oss.users_dsp--; + dev->dmasound.users_dsp--; file->private_data = NULL; - up(&dev->oss.lock); + up(&dev->dmasound.lock); return 0; } @@ -291,12 +291,12 @@ static ssize_t dsp_read(struct file *file, char __user *buffer, unsigned long flags; int err,ret = 0; - add_wait_queue(&dev->oss.wq, &wait); - down(&dev->oss.lock); + add_wait_queue(&dev->dmasound.wq, &wait); + down(&dev->dmasound.lock); while (count > 0) { /* wait for data if needed */ - if (0 == dev->oss.read_count) { - if (!dev->oss.recording_on) { + if (0 == dev->dmasound.read_count) { + if (!dev->dmasound.recording_on) { err = dsp_rec_start(dev); if (err < 0) { if (0 == ret) @@ -304,8 +304,8 @@ static ssize_t dsp_read(struct file *file, char __user *buffer, break; } } - if (dev->oss.recording_on && - !dev->oss.dma_running) { + if (dev->dmasound.recording_on && + !dev->dmasound.dma_running) { /* recover from overruns */ spin_lock_irqsave(&dev->slock,flags); dsp_dma_start(dev); @@ -316,12 +316,12 @@ static ssize_t dsp_read(struct file *file, char __user *buffer, ret = -EAGAIN; break; } - up(&dev->oss.lock); + up(&dev->dmasound.lock); set_current_state(TASK_INTERRUPTIBLE); - if (0 == dev->oss.read_count) + if (0 == dev->dmasound.read_count) schedule(); set_current_state(TASK_RUNNING); - down(&dev->oss.lock); + down(&dev->dmasound.lock); if (signal_pending(current)) { if (0 == ret) ret = -EINTR; @@ -331,12 +331,12 @@ static ssize_t dsp_read(struct file *file, char __user *buffer, /* copy data to userspace */ bytes = count; - if (bytes > dev->oss.read_count) - bytes = dev->oss.read_count; - if (bytes > dev->oss.bufsize - dev->oss.read_offset) - bytes = dev->oss.bufsize - dev->oss.read_offset; + if (bytes > dev->dmasound.read_count) + bytes = dev->dmasound.read_count; + if (bytes > dev->dmasound.bufsize - dev->dmasound.read_offset) + bytes = dev->dmasound.bufsize - dev->dmasound.read_offset; if (copy_to_user(buffer + ret, - dev->oss.dma.vmalloc + dev->oss.read_offset, + dev->dmasound.dma.vmalloc + dev->dmasound.read_offset, bytes)) { if (0 == ret) ret = -EFAULT; @@ -345,13 +345,13 @@ static ssize_t dsp_read(struct file *file, char __user *buffer, ret += bytes; count -= bytes; - dev->oss.read_count -= bytes; - dev->oss.read_offset += bytes; - if (dev->oss.read_offset == dev->oss.bufsize) - dev->oss.read_offset = 0; + dev->dmasound.read_count -= bytes; + dev->dmasound.read_offset += bytes; + if (dev->dmasound.read_offset == dev->dmasound.bufsize) + dev->dmasound.read_offset = 0; } - up(&dev->oss.lock); - remove_wait_queue(&dev->oss.wq, &wait); + up(&dev->dmasound.lock); + remove_wait_queue(&dev->dmasound.wq, &wait); return ret; } @@ -382,35 +382,35 @@ static int dsp_ioctl(struct inode *inode, struct file *file, return -EFAULT; /* fall through */ case SOUND_PCM_READ_RATE: - return put_user(dev->oss.rate, p); + return put_user(dev->dmasound.rate, p); case SNDCTL_DSP_STEREO: if (get_user(val, p)) return -EFAULT; - down(&dev->oss.lock); - dev->oss.channels = val ? 2 : 1; - if (dev->oss.recording_on) { + down(&dev->dmasound.lock); + dev->dmasound.channels = val ? 2 : 1; + if (dev->dmasound.recording_on) { dsp_rec_stop(dev); dsp_rec_start(dev); } - up(&dev->oss.lock); - return put_user(dev->oss.channels-1, p); + up(&dev->dmasound.lock); + return put_user(dev->dmasound.channels-1, p); case SNDCTL_DSP_CHANNELS: if (get_user(val, p)) return -EFAULT; if (val != 1 && val != 2) return -EINVAL; - down(&dev->oss.lock); - dev->oss.channels = val; - if (dev->oss.recording_on) { + down(&dev->dmasound.lock); + dev->dmasound.channels = val; + if (dev->dmasound.recording_on) { dsp_rec_stop(dev); dsp_rec_start(dev); } - up(&dev->oss.lock); + up(&dev->dmasound.lock); /* fall through */ case SOUND_PCM_READ_CHANNELS: - return put_user(dev->oss.channels, p); + return put_user(dev->dmasound.channels, p); case SNDCTL_DSP_GETFMTS: /* Returns a mask */ return put_user(AFMT_U8 | AFMT_S8 | @@ -430,20 +430,20 @@ static int dsp_ioctl(struct inode *inode, struct file *file, case AFMT_U16_BE: case AFMT_S16_LE: case AFMT_S16_BE: - down(&dev->oss.lock); - dev->oss.afmt = val; - if (dev->oss.recording_on) { + down(&dev->dmasound.lock); + dev->dmasound.afmt = val; + if (dev->dmasound.recording_on) { dsp_rec_stop(dev); dsp_rec_start(dev); } - up(&dev->oss.lock); - return put_user(dev->oss.afmt, p); + up(&dev->dmasound.lock); + return put_user(dev->dmasound.afmt, p); default: return -EINVAL; } case SOUND_PCM_READ_BITS: - switch (dev->oss.afmt) { + switch (dev->dmasound.afmt) { case AFMT_U8: case AFMT_S8: return put_user(8, p); @@ -461,18 +461,18 @@ static int dsp_ioctl(struct inode *inode, struct file *file, return 0; case SNDCTL_DSP_RESET: - down(&dev->oss.lock); - if (dev->oss.recording_on) + down(&dev->dmasound.lock); + if (dev->dmasound.recording_on) dsp_rec_stop(dev); - up(&dev->oss.lock); + up(&dev->dmasound.lock); return 0; case SNDCTL_DSP_GETBLKSIZE: - return put_user(dev->oss.blksize, p); + return put_user(dev->dmasound.blksize, p); case SNDCTL_DSP_SETFRAGMENT: if (get_user(val, p)) return -EFAULT; - if (dev->oss.recording_on) + if (dev->dmasound.recording_on) return -EBUSY; dsp_buffer_free(dev); /* used to be arg >> 16 instead of val >> 16; fixed */ @@ -487,9 +487,9 @@ static int dsp_ioctl(struct inode *inode, struct file *file, case SNDCTL_DSP_GETISPACE: { audio_buf_info info; - info.fragsize = dev->oss.blksize; - info.fragstotal = dev->oss.blocks; - info.bytes = dev->oss.read_count; + info.fragsize = dev->dmasound.blksize; + info.fragstotal = dev->dmasound.blocks; + info.bytes = dev->dmasound.read_count; info.fragments = info.bytes / info.fragsize; if (copy_to_user(argp, &info, sizeof(info))) return -EFAULT; @@ -505,13 +505,13 @@ static unsigned int dsp_poll(struct file *file, struct poll_table_struct *wait) struct saa7134_dev *dev = file->private_data; unsigned int mask = 0; - poll_wait(file, &dev->oss.wq, wait); + poll_wait(file, &dev->dmasound.wq, wait); - if (0 == dev->oss.read_count) { - down(&dev->oss.lock); - if (!dev->oss.recording_on) + if (0 == dev->dmasound.read_count) { + down(&dev->dmasound.lock); + if (!dev->dmasound.recording_on) dsp_rec_start(dev); - up(&dev->oss.lock); + up(&dev->dmasound.lock); } else mask |= (POLLIN | POLLRDNORM); return mask; @@ -535,7 +535,7 @@ mixer_recsrc_7134(struct saa7134_dev *dev) { int analog_io,rate; - switch (dev->oss.input) { + switch (dev->dmasound.input) { case TV: saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0xc0); saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, 0x00); @@ -543,8 +543,8 @@ mixer_recsrc_7134(struct saa7134_dev *dev) case LINE1: case LINE2: case LINE2_LEFT: - analog_io = (LINE1 == dev->oss.input) ? 0x00 : 0x08; - rate = (32000 == dev->oss.rate) ? 0x01 : 0x03; + analog_io = (LINE1 == dev->dmasound.input) ? 0x00 : 0x08; + rate = (32000 == dev->dmasound.rate) ? 0x01 : 0x03; saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, analog_io); saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0x80); saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, rate); @@ -560,7 +560,7 @@ mixer_recsrc_7133(struct saa7134_dev *dev) xbarin = 0x03; // adc anabar = 0; - switch (dev->oss.input) { + switch (dev->dmasound.input) { case TV: xbarin = 0; // Demodulator anabar = 2; // DACs @@ -586,9 +586,9 @@ mixer_recsrc(struct saa7134_dev *dev, enum saa7134_audio_in src) { static const char *iname[] = { "Oops", "TV", "LINE1", "LINE2" }; - dev->oss.count++; - dev->oss.input = src; - dprintk("mixer input = %s\n",iname[dev->oss.input]); + dev->dmasound.count++; + dev->dmasound.input = src; + dprintk("mixer input = %s\n",iname[dev->dmasound.input]); switch (dev->pci->device) { case PCI_DEVICE_ID_PHILIPS_SAA7134: @@ -640,7 +640,7 @@ static int mixer_open(struct inode *inode, struct file *file) list_for_each(list,&saa7134_devlist) { h = list_entry(list, struct saa7134_dev, devlist); - if (h->oss.minor_mixer == minor) + if (h->dmasound.minor_mixer == minor) dev = h; } if (NULL == dev) @@ -676,7 +676,7 @@ static int mixer_ioctl(struct inode *inode, struct file *file, memset(&info,0,sizeof(info)); strlcpy(info.id, "TV audio", sizeof(info.id)); strlcpy(info.name, dev->name, sizeof(info.name)); - info.modify_counter = dev->oss.count; + info.modify_counter = dev->dmasound.count; if (copy_to_user(argp, &info, sizeof(info))) return -EFAULT; return 0; @@ -698,26 +698,26 @@ static int mixer_ioctl(struct inode *inode, struct file *file, case MIXER_READ(SOUND_MIXER_RECMASK): case MIXER_READ(SOUND_MIXER_DEVMASK): val = SOUND_MASK_LINE1 | SOUND_MASK_LINE2; - if (32000 == dev->oss.rate) + if (32000 == dev->dmasound.rate) val |= SOUND_MASK_VIDEO; return put_user(val, p); case MIXER_WRITE(SOUND_MIXER_RECSRC): if (get_user(val, p)) return -EFAULT; - input = dev->oss.input; - if (32000 == dev->oss.rate && - val & SOUND_MASK_VIDEO && dev->oss.input != TV) + input = dev->dmasound.input; + if (32000 == dev->dmasound.rate && + val & SOUND_MASK_VIDEO && dev->dmasound.input != TV) input = TV; - if (val & SOUND_MASK_LINE1 && dev->oss.input != LINE1) + if (val & SOUND_MASK_LINE1 && dev->dmasound.input != LINE1) input = LINE1; - if (val & SOUND_MASK_LINE2 && dev->oss.input != LINE2) + if (val & SOUND_MASK_LINE2 && dev->dmasound.input != LINE2) input = LINE2; - if (input != dev->oss.input) + if (input != dev->dmasound.input) mixer_recsrc(dev,input); /* fall throuth */ case MIXER_READ(SOUND_MIXER_RECSRC): - switch (dev->oss.input) { + switch (dev->dmasound.input) { case TV: ret = SOUND_MASK_VIDEO; break; case LINE1: ret = SOUND_MASK_LINE1; break; case LINE2: ret = SOUND_MASK_LINE2; break; @@ -727,7 +727,7 @@ static int mixer_ioctl(struct inode *inode, struct file *file, case MIXER_WRITE(SOUND_MIXER_VIDEO): case MIXER_READ(SOUND_MIXER_VIDEO): - if (32000 != dev->oss.rate) + if (32000 != dev->dmasound.rate) return -EINVAL; return put_user(100 | 100 << 8, p); @@ -736,22 +736,22 @@ static int mixer_ioctl(struct inode *inode, struct file *file, return -EFAULT; val &= 0xff; val = (val <= 50) ? 50 : 100; - dev->oss.line1 = val; - mixer_level(dev,LINE1,dev->oss.line1); + dev->dmasound.line1 = val; + mixer_level(dev,LINE1,dev->dmasound.line1); /* fall throuth */ case MIXER_READ(SOUND_MIXER_LINE1): - return put_user(dev->oss.line1 | dev->oss.line1 << 8, p); + return put_user(dev->dmasound.line1 | dev->dmasound.line1 << 8, p); case MIXER_WRITE(SOUND_MIXER_LINE2): if (get_user(val, p)) return -EFAULT; val &= 0xff; val = (val <= 50) ? 50 : 100; - dev->oss.line2 = val; - mixer_level(dev,LINE2,dev->oss.line2); + dev->dmasound.line2 = val; + mixer_level(dev,LINE2,dev->dmasound.line2); /* fall throuth */ case MIXER_READ(SOUND_MIXER_LINE2): - return put_user(dev->oss.line2 | dev->oss.line2 << 8, p); + return put_user(dev->dmasound.line2 | dev->dmasound.line2 << 8, p); default: return -EINVAL; @@ -771,8 +771,8 @@ struct file_operations saa7134_mixer_fops = { int saa7134_oss_init1(struct saa7134_dev *dev) { /* general */ - init_MUTEX(&dev->oss.lock); - init_waitqueue_head(&dev->oss.wq); + init_MUTEX(&dev->dmasound.lock); + init_waitqueue_head(&dev->dmasound.wq); switch (dev->pci->device) { case PCI_DEVICE_ID_PHILIPS_SAA7133: @@ -784,17 +784,17 @@ int saa7134_oss_init1(struct saa7134_dev *dev) } /* dsp */ - dev->oss.rate = 32000; + dev->dmasound.rate = 32000; if (oss_rate) - dev->oss.rate = oss_rate; - dev->oss.rate = (dev->oss.rate > 40000) ? 48000 : 32000; + dev->dmasound.rate = oss_rate; + dev->dmasound.rate = (dev->dmasound.rate > 40000) ? 48000 : 32000; /* mixer */ - dev->oss.line1 = 50; - dev->oss.line2 = 50; - mixer_level(dev,LINE1,dev->oss.line1); - mixer_level(dev,LINE2,dev->oss.line2); - mixer_recsrc(dev, (dev->oss.rate == 32000) ? TV : LINE2); + dev->dmasound.line1 = 50; + dev->dmasound.line2 = 50; + mixer_level(dev,LINE1,dev->dmasound.line1); + mixer_level(dev,LINE2,dev->dmasound.line2); + mixer_recsrc(dev, (dev->dmasound.rate == 32000) ? TV : LINE2); return 0; } @@ -810,7 +810,7 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status) int next_blk, reg = 0; spin_lock(&dev->slock); - if (UNSET == dev->oss.dma_blk) { + if (UNSET == dev->dmasound.dma_blk) { dprintk("irq: recording stopped\n"); goto done; } @@ -818,11 +818,11 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status) dprintk("irq: lost %ld\n", (status >> 24) & 0x0f); if (0 == (status & 0x10000000)) { /* odd */ - if (0 == (dev->oss.dma_blk & 0x01)) + if (0 == (dev->dmasound.dma_blk & 0x01)) reg = SAA7134_RS_BA1(6); } else { /* even */ - if (1 == (dev->oss.dma_blk & 0x01)) + if (1 == (dev->dmasound.dma_blk & 0x01)) reg = SAA7134_RS_BA2(6); } if (0 == reg) { @@ -830,25 +830,25 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status) (status & 0x10000000) ? "even" : "odd"); goto done; } - if (dev->oss.read_count >= dev->oss.blksize * (dev->oss.blocks-2)) { - dprintk("irq: overrun [full=%d/%d]\n",dev->oss.read_count, - dev->oss.bufsize); + if (dev->dmasound.read_count >= dev->dmasound.blksize * (dev->dmasound.blocks-2)) { + dprintk("irq: overrun [full=%d/%d]\n",dev->dmasound.read_count, + dev->dmasound.bufsize); dsp_dma_stop(dev); goto done; } /* next block addr */ - next_blk = (dev->oss.dma_blk + 2) % dev->oss.blocks; - saa_writel(reg,next_blk * dev->oss.blksize); + next_blk = (dev->dmasound.dma_blk + 2) % dev->dmasound.blocks; + saa_writel(reg,next_blk * dev->dmasound.blksize); if (oss_debug > 2) dprintk("irq: ok, %s, next_blk=%d, addr=%x\n", (status & 0x10000000) ? "even" : "odd ", next_blk, - next_blk * dev->oss.blksize); + next_blk * dev->dmasound.blksize); /* update status & wake waiting readers */ - dev->oss.dma_blk = (dev->oss.dma_blk + 1) % dev->oss.blocks; - dev->oss.read_count += dev->oss.blksize; - wake_up(&dev->oss.wq); + dev->dmasound.dma_blk = (dev->dmasound.dma_blk + 1) % dev->dmasound.blocks; + dev->dmasound.read_count += dev->dmasound.blksize; + wake_up(&dev->dmasound.wq); done: spin_unlock(&dev->slock); diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 1fdc9e147f8..fb972747166 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -355,8 +355,8 @@ struct saa7134_fh { struct saa7134_pgtable pt_vbi; }; -/* oss dsp status */ -struct saa7134_oss { +/* dmasound dsp status */ +struct saa7134_dmasound { struct semaphore lock; int minor_mixer; int minor_dsp; @@ -431,7 +431,7 @@ struct saa7134_dev { struct video_device *video_dev; struct video_device *radio_dev; struct video_device *vbi_dev; - struct saa7134_oss oss; + struct saa7134_dmasound dmasound; /* infrared remote */ int has_remote; -- cgit v1.2.3 From b910472dd3b7c1d51af9a594a759f642520c33e1 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 8 Nov 2005 21:38:55 -0800 Subject: [PATCH] sched: implement nice support across physical cpus on SMP This patch implements 'nice' support across physical cpus on SMP. It introduces an extra runqueue variable prio_bias which is the sum of the (inverted) static priorities of all the tasks on the runqueue. This is then used to bias busy rebalancing between runqueues to obtain good distribution of tasks of different nice values. By biasing the balancing only during busy rebalancing we can avoid having any significant loss of throughput by not affecting the carefully tuned idle balancing already in place. If all tasks are running at the same nice level this code should also have minimal effect. The code is optimised out in the !CONFIG_SMP case. Signed-off-by: Con Kolivas Cc: Ingo Molnar Cc: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/sched.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 83 insertions(+), 18 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 3ce26954be1..c6827f94e15 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -206,6 +206,7 @@ struct runqueue { */ unsigned long nr_running; #ifdef CONFIG_SMP + unsigned long prio_bias; unsigned long cpu_load[3]; #endif unsigned long long nr_switches; @@ -659,13 +660,45 @@ static int effective_prio(task_t *p) return prio; } +#ifdef CONFIG_SMP +static inline void inc_prio_bias(runqueue_t *rq, int static_prio) +{ + rq->prio_bias += MAX_PRIO - static_prio; +} + +static inline void dec_prio_bias(runqueue_t *rq, int static_prio) +{ + rq->prio_bias -= MAX_PRIO - static_prio; +} +#else +static inline void inc_prio_bias(runqueue_t *rq, int static_prio) +{ +} + +static inline void dec_prio_bias(runqueue_t *rq, int static_prio) +{ +} +#endif + +static inline void inc_nr_running(task_t *p, runqueue_t *rq) +{ + rq->nr_running++; + inc_prio_bias(rq, p->static_prio); +} + +static inline void dec_nr_running(task_t *p, runqueue_t *rq) +{ + rq->nr_running--; + dec_prio_bias(rq, p->static_prio); +} + /* * __activate_task - move a task to the runqueue. */ static inline void __activate_task(task_t *p, runqueue_t *rq) { enqueue_task(p, rq->active); - rq->nr_running++; + inc_nr_running(p, rq); } /* @@ -674,7 +707,7 @@ static inline void __activate_task(task_t *p, runqueue_t *rq) static inline void __activate_idle_task(task_t *p, runqueue_t *rq) { enqueue_task_head(p, rq->active); - rq->nr_running++; + inc_nr_running(p, rq); } static int recalc_task_prio(task_t *p, unsigned long long now) @@ -793,7 +826,7 @@ static void activate_task(task_t *p, runqueue_t *rq, int local) */ static void deactivate_task(struct task_struct *p, runqueue_t *rq) { - rq->nr_running--; + dec_nr_running(p, rq); dequeue_task(p, p->array); p->array = NULL; } @@ -930,27 +963,54 @@ void kick_process(task_t *p) * We want to under-estimate the load of migration sources, to * balance conservatively. */ -static inline unsigned long source_load(int cpu, int type) +static inline unsigned long __source_load(int cpu, int type, enum idle_type idle) { runqueue_t *rq = cpu_rq(cpu); - unsigned long load_now = rq->nr_running * SCHED_LOAD_SCALE; + unsigned long cpu_load = rq->cpu_load[type-1], + load_now = rq->nr_running * SCHED_LOAD_SCALE; + + if (idle == NOT_IDLE) { + /* + * If we are balancing busy runqueues the load is biased by + * priority to create 'nice' support across cpus. + */ + cpu_load *= rq->prio_bias; + load_now *= rq->prio_bias; + } + if (type == 0) return load_now; - return min(rq->cpu_load[type-1], load_now); + return min(cpu_load, load_now); +} + +static inline unsigned long source_load(int cpu, int type) +{ + return __source_load(cpu, type, NOT_IDLE); } /* * Return a high guess at the load of a migration-target cpu */ -static inline unsigned long target_load(int cpu, int type) +static inline unsigned long __target_load(int cpu, int type, enum idle_type idle) { runqueue_t *rq = cpu_rq(cpu); - unsigned long load_now = rq->nr_running * SCHED_LOAD_SCALE; + unsigned long cpu_load = rq->cpu_load[type-1], + load_now = rq->nr_running * SCHED_LOAD_SCALE; + if (type == 0) return load_now; - return max(rq->cpu_load[type-1], load_now); + if (idle == NOT_IDLE) { + cpu_load *= rq->prio_bias; + load_now *= rq->prio_bias; + } + return max(cpu_load, load_now); +} + +static inline unsigned long target_load(int cpu, int type) +{ + return __target_load(cpu, type, NOT_IDLE); } /* @@ -1411,7 +1471,7 @@ void fastcall wake_up_new_task(task_t *p, unsigned long clone_flags) list_add_tail(&p->run_list, ¤t->run_list); p->array = current->array; p->array->nr_active++; - rq->nr_running++; + inc_nr_running(p, rq); } set_need_resched(); } else @@ -1756,9 +1816,9 @@ void pull_task(runqueue_t *src_rq, prio_array_t *src_array, task_t *p, runqueue_t *this_rq, prio_array_t *this_array, int this_cpu) { dequeue_task(p, src_array); - src_rq->nr_running--; + dec_nr_running(p, src_rq); set_task_cpu(p, this_cpu); - this_rq->nr_running++; + inc_nr_running(p, this_rq); enqueue_task(p, this_array); p->timestamp = (p->timestamp - src_rq->timestamp_last_tick) + this_rq->timestamp_last_tick; @@ -1937,9 +1997,9 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, /* Bias balancing toward cpus of our domain */ if (local_group) - load = target_load(i, load_idx); + load = __target_load(i, load_idx, idle); else - load = source_load(i, load_idx); + load = __source_load(i, load_idx, idle); avg_load += load; } @@ -2044,14 +2104,15 @@ out_balanced: /* * find_busiest_queue - find the busiest runqueue among the cpus in group. */ -static runqueue_t *find_busiest_queue(struct sched_group *group) +static runqueue_t *find_busiest_queue(struct sched_group *group, + enum idle_type idle) { unsigned long load, max_load = 0; runqueue_t *busiest = NULL; int i; for_each_cpu_mask(i, group->cpumask) { - load = source_load(i, 0); + load = __source_load(i, 0, idle); if (load > max_load) { max_load = load; @@ -2095,7 +2156,7 @@ static int load_balance(int this_cpu, runqueue_t *this_rq, goto out_balanced; } - busiest = find_busiest_queue(group); + busiest = find_busiest_queue(group, idle); if (!busiest) { schedstat_inc(sd, lb_nobusyq[idle]); goto out_balanced; @@ -2218,7 +2279,7 @@ static int load_balance_newidle(int this_cpu, runqueue_t *this_rq, goto out_balanced; } - busiest = find_busiest_queue(group); + busiest = find_busiest_queue(group, NEWLY_IDLE); if (!busiest) { schedstat_inc(sd, lb_nobusyq[NEWLY_IDLE]); goto out_balanced; @@ -3447,7 +3508,9 @@ void set_user_nice(task_t *p, long nice) * not SCHED_NORMAL: */ if (rt_task(p)) { + dec_prio_bias(rq, p->static_prio); p->static_prio = NICE_TO_PRIO(nice); + inc_prio_bias(rq, p->static_prio); goto out_unlock; } array = p->array; @@ -3457,7 +3520,9 @@ void set_user_nice(task_t *p, long nice) old_prio = p->prio; new_prio = NICE_TO_PRIO(nice); delta = new_prio - old_prio; + dec_prio_bias(rq, p->static_prio); p->static_prio = NICE_TO_PRIO(nice); + inc_prio_bias(rq, p->static_prio); p->prio += delta; if (array) { -- cgit v1.2.3 From 738a2ccbcf8c2c1b039f1e76662dce60b22b694b Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 8 Nov 2005 21:38:56 -0800 Subject: [PATCH] sched: change prio bias only if queued prio_bias should only be adjusted in set_user_nice if p is actually currently queued. Signed-off-by: Con Kolivas Cc: Ingo Molnar Cc: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/sched.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index c6827f94e15..e1f57bd5aaa 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3508,25 +3508,24 @@ void set_user_nice(task_t *p, long nice) * not SCHED_NORMAL: */ if (rt_task(p)) { - dec_prio_bias(rq, p->static_prio); p->static_prio = NICE_TO_PRIO(nice); - inc_prio_bias(rq, p->static_prio); goto out_unlock; } array = p->array; - if (array) + if (array) { dequeue_task(p, array); + dec_prio_bias(rq, p->static_prio); + } old_prio = p->prio; new_prio = NICE_TO_PRIO(nice); delta = new_prio - old_prio; - dec_prio_bias(rq, p->static_prio); p->static_prio = NICE_TO_PRIO(nice); - inc_prio_bias(rq, p->static_prio); p->prio += delta; if (array) { enqueue_task(p, array); + inc_prio_bias(rq, p->static_prio); /* * If the task increased its priority or is running and * lowered its priority, then reschedule its CPU: -- cgit v1.2.3 From dad1c65c8000f4485d8602e1875ded77e0d72133 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 8 Nov 2005 21:38:57 -0800 Subject: [PATCH] sched: account rt tasks in prio_bias() Real time tasks' effect on prio_bias should be based on their real time priority level instead of their static_prio which is based on nice. Signed-off-by: Con Kolivas Cc: Ingo Molnar Cc: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/sched.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index e1f57bd5aaa..d9dbf8ee6ca 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -661,21 +661,21 @@ static int effective_prio(task_t *p) } #ifdef CONFIG_SMP -static inline void inc_prio_bias(runqueue_t *rq, int static_prio) +static inline void inc_prio_bias(runqueue_t *rq, int prio) { - rq->prio_bias += MAX_PRIO - static_prio; + rq->prio_bias += MAX_PRIO - prio; } -static inline void dec_prio_bias(runqueue_t *rq, int static_prio) +static inline void dec_prio_bias(runqueue_t *rq, int prio) { - rq->prio_bias -= MAX_PRIO - static_prio; + rq->prio_bias -= MAX_PRIO - prio; } #else -static inline void inc_prio_bias(runqueue_t *rq, int static_prio) +static inline void inc_prio_bias(runqueue_t *rq, int prio) { } -static inline void dec_prio_bias(runqueue_t *rq, int static_prio) +static inline void dec_prio_bias(runqueue_t *rq, int prio) { } #endif @@ -683,13 +683,19 @@ static inline void dec_prio_bias(runqueue_t *rq, int static_prio) static inline void inc_nr_running(task_t *p, runqueue_t *rq) { rq->nr_running++; - inc_prio_bias(rq, p->static_prio); + if (rt_task(p)) + inc_prio_bias(rq, p->prio); + else + inc_prio_bias(rq, p->static_prio); } static inline void dec_nr_running(task_t *p, runqueue_t *rq) { rq->nr_running--; - dec_prio_bias(rq, p->static_prio); + if (rt_task(p)) + dec_prio_bias(rq, p->prio); + else + dec_prio_bias(rq, p->static_prio); } /* -- cgit v1.2.3 From 3b0bd9bc6f3b8a47853d1b1de4520de3878e8941 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 8 Nov 2005 21:38:58 -0800 Subject: [PATCH] sched: smp nice bias busy queues on idle rebalance To intensify the 'nice' support across physical cpus on SMP we can bias the loads on idle rebalancing. To prevent idle rebalance from trying to pull tasks from queues that appear heavily loaded we only bias the load if there is more than one task running. Add some minor micro-optimisations and have only one return from __source_load and __target_load functions. Fix the fact that target_load was not biased by priority when type == 0. Signed-off-by: Con Kolivas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/sched.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index d9dbf8ee6ca..ec9ea9119b9 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -972,22 +972,26 @@ void kick_process(task_t *p) static inline unsigned long __source_load(int cpu, int type, enum idle_type idle) { runqueue_t *rq = cpu_rq(cpu); - unsigned long cpu_load = rq->cpu_load[type-1], + unsigned long source_load, cpu_load = rq->cpu_load[type-1], load_now = rq->nr_running * SCHED_LOAD_SCALE; - if (idle == NOT_IDLE) { + if (type == 0) + source_load = load_now; + else + source_load = min(cpu_load, load_now); + + if (idle == NOT_IDLE || rq->nr_running > 1) /* - * If we are balancing busy runqueues the load is biased by - * priority to create 'nice' support across cpus. + * If we are busy rebalancing the load is biased by + * priority to create 'nice' support across cpus. When + * idle rebalancing we should only bias the source_load if + * there is more than one task running on that queue to + * prevent idle rebalance from trying to pull tasks from a + * queue with only one running task. */ - cpu_load *= rq->prio_bias; - load_now *= rq->prio_bias; - } + source_load *= rq->prio_bias; - if (type == 0) - return load_now; - - return min(cpu_load, load_now); + return source_load; } static inline unsigned long source_load(int cpu, int type) @@ -1001,17 +1005,18 @@ static inline unsigned long source_load(int cpu, int type) static inline unsigned long __target_load(int cpu, int type, enum idle_type idle) { runqueue_t *rq = cpu_rq(cpu); - unsigned long cpu_load = rq->cpu_load[type-1], + unsigned long target_load, cpu_load = rq->cpu_load[type-1], load_now = rq->nr_running * SCHED_LOAD_SCALE; if (type == 0) - return load_now; + target_load = load_now; + else + target_load = max(cpu_load, load_now); - if (idle == NOT_IDLE) { - cpu_load *= rq->prio_bias; - load_now *= rq->prio_bias; - } - return max(cpu_load, load_now); + if (idle == NOT_IDLE || rq->nr_running > 1) + target_load *= rq->prio_bias; + + return target_load; } static inline unsigned long target_load(int cpu, int type) -- cgit v1.2.3 From 6dd4a85bb3ee0715415892c8b0f2a9bd08d31ca4 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 8 Nov 2005 21:38:59 -0800 Subject: [PATCH] sched: correct smp_nice_bias The priority biasing was off by mutliplying the total load by the total priority bias and this ruins the ratio of loads between runqueues. This patch should correct the ratios of loads between runqueues to be proportional to overall load. -2nd attempt. From: Dave Kleikamp This patch fixes a divide-by-zero error that I hit on a two-way i386 machine. rq->nr_running is tested to be non-zero, but may change by the time it is used in the division. Saving the value to a local variable ensures that the same value that is checked is used in the division. Signed-off-by: Con Kolivas Signed-off-by: Dave Kleikamp Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/sched.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index ec9ea9119b9..502d47c883b 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -972,15 +972,16 @@ void kick_process(task_t *p) static inline unsigned long __source_load(int cpu, int type, enum idle_type idle) { runqueue_t *rq = cpu_rq(cpu); + unsigned long running = rq->nr_running; unsigned long source_load, cpu_load = rq->cpu_load[type-1], - load_now = rq->nr_running * SCHED_LOAD_SCALE; + load_now = running * SCHED_LOAD_SCALE; if (type == 0) source_load = load_now; else source_load = min(cpu_load, load_now); - if (idle == NOT_IDLE || rq->nr_running > 1) + if (running > 1 || (idle == NOT_IDLE && running)) /* * If we are busy rebalancing the load is biased by * priority to create 'nice' support across cpus. When @@ -989,7 +990,7 @@ static inline unsigned long __source_load(int cpu, int type, enum idle_type idle * prevent idle rebalance from trying to pull tasks from a * queue with only one running task. */ - source_load *= rq->prio_bias; + source_load = source_load * rq->prio_bias / running; return source_load; } @@ -1005,16 +1006,17 @@ static inline unsigned long source_load(int cpu, int type) static inline unsigned long __target_load(int cpu, int type, enum idle_type idle) { runqueue_t *rq = cpu_rq(cpu); + unsigned long running = rq->nr_running; unsigned long target_load, cpu_load = rq->cpu_load[type-1], - load_now = rq->nr_running * SCHED_LOAD_SCALE; + load_now = running * SCHED_LOAD_SCALE; if (type == 0) target_load = load_now; else target_load = max(cpu_load, load_now); - if (idle == NOT_IDLE || rq->nr_running > 1) - target_load *= rq->prio_bias; + if (running > 1 || (idle == NOT_IDLE && running)) + target_load = target_load * rq->prio_bias / running; return target_load; } -- cgit v1.2.3 From ede3d0fba99520f268067917b50858d788bc41da Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 8 Nov 2005 21:39:00 -0800 Subject: [PATCH] sched: consider migration thread with smp nice The intermittent scheduling of the migration thread at ultra high priority makes the smp nice handling see that runqueue as being heavily loaded. The migration thread itself actually handles the balancing so its influence on priority balancing should be ignored. Signed-off-by: Con Kolivas Cc: Ingo Molnar Cc: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/sched.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 502d47c883b..0f2def82229 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -670,6 +670,31 @@ static inline void dec_prio_bias(runqueue_t *rq, int prio) { rq->prio_bias -= MAX_PRIO - prio; } + +static inline void inc_nr_running(task_t *p, runqueue_t *rq) +{ + rq->nr_running++; + if (rt_task(p)) { + if (p != rq->migration_thread) + /* + * The migration thread does the actual balancing. Do + * not bias by its priority as the ultra high priority + * will skew balancing adversely. + */ + inc_prio_bias(rq, p->prio); + } else + inc_prio_bias(rq, p->static_prio); +} + +static inline void dec_nr_running(task_t *p, runqueue_t *rq) +{ + rq->nr_running--; + if (rt_task(p)) { + if (p != rq->migration_thread) + dec_prio_bias(rq, p->prio); + } else + dec_prio_bias(rq, p->static_prio); +} #else static inline void inc_prio_bias(runqueue_t *rq, int prio) { @@ -678,25 +703,17 @@ static inline void inc_prio_bias(runqueue_t *rq, int prio) static inline void dec_prio_bias(runqueue_t *rq, int prio) { } -#endif static inline void inc_nr_running(task_t *p, runqueue_t *rq) { rq->nr_running++; - if (rt_task(p)) - inc_prio_bias(rq, p->prio); - else - inc_prio_bias(rq, p->static_prio); } static inline void dec_nr_running(task_t *p, runqueue_t *rq) { rq->nr_running--; - if (rt_task(p)) - dec_prio_bias(rq, p->prio); - else - dec_prio_bias(rq, p->static_prio); } +#endif /* * __activate_task - move a task to the runqueue. -- cgit v1.2.3 From 5bfb5d690f36d316a5f3b4f7775fda996faa6b12 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Tue, 8 Nov 2005 21:39:01 -0800 Subject: [PATCH] sched: disable preempt in idle tasks Run idle threads with preempt disabled. Also corrected a bugs in arm26's cpu_idle (make it actually call schedule()). How did it ever work before? Might fix the CPU hotplugging hang which Nigel Cunningham noted. We think the bug hits if the idle thread is preempted after checking need_resched() and before going to sleep, then the CPU offlined. After calling stop_machine_run, the CPU eventually returns from preemption and into the idle thread and goes to sleep. The CPU will continue executing previous idle and have no chance to call play_dead. By disabling preemption until we are ready to explicitly schedule, this bug is fixed and the idle threads generally become more robust. From: alexs PPC build fix From: Yoichi Yuasa MIPS build fix Signed-off-by: Nick Piggin Signed-off-by: Yoichi Yuasa Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/kernel/process.c | 4 ++-- arch/arm/kernel/smp.c | 5 ++++- arch/arm26/kernel/process.c | 12 +++++------- arch/cris/arch-v32/kernel/smp.c | 1 + arch/cris/kernel/process.c | 2 ++ arch/frv/kernel/process.c | 6 +++++- arch/h8300/kernel/process.c | 28 +++++++++++++++------------- arch/i386/kernel/process.c | 4 +++- arch/i386/kernel/smpboot.c | 1 + arch/ia64/kernel/process.c | 2 ++ arch/ia64/kernel/smpboot.c | 1 + arch/m32r/kernel/process.c | 2 ++ arch/m32r/kernel/smpboot.c | 1 + arch/m68k/kernel/process.c | 2 ++ arch/mips/kernel/process.c | 2 ++ arch/mips/kernel/smp.c | 4 +++- arch/parisc/kernel/process.c | 2 ++ arch/parisc/kernel/smp.c | 1 + arch/powerpc/platforms/iseries/setup.c | 4 ++++ arch/powerpc/platforms/pseries/setup.c | 4 ++++ arch/ppc/kernel/idle.c | 17 ++++++++++++----- arch/ppc/kernel/smp.c | 1 + arch/ppc64/kernel/idle.c | 4 ++++ arch/s390/kernel/process.c | 11 ++++++++--- arch/s390/kernel/smp.c | 1 + arch/sh/kernel/process.c | 2 ++ arch/sh/kernel/smp.c | 5 ++++- arch/sh64/kernel/process.c | 2 ++ arch/sparc/kernel/process.c | 4 ++++ arch/sparc64/kernel/process.c | 4 ++++ arch/sparc64/kernel/smp.c | 3 +++ arch/v850/kernel/process.c | 16 ++++++++++------ arch/x86_64/kernel/process.c | 2 ++ arch/x86_64/kernel/smpboot.c | 1 + arch/xtensa/kernel/process.c | 3 ++- init/main.c | 4 +++- 36 files changed, 125 insertions(+), 43 deletions(-) diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index ba298277bec..93dd92cc12f 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -116,13 +116,13 @@ void cpu_idle(void) if (!idle) idle = default_idle; - preempt_disable(); leds_event(led_idle_start); while (!need_resched()) idle(); leds_event(led_idle_end); - preempt_enable(); + preempt_enable_no_resched(); schedule(); + preempt_disable(); } } diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 77e2e9ca89f..e55ea952f7a 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -256,7 +256,9 @@ void __cpuexit cpu_die(void) asmlinkage void __cpuinit secondary_start_kernel(void) { struct mm_struct *mm = &init_mm; - unsigned int cpu = smp_processor_id(); + unsigned int cpu; + + cpu = smp_processor_id(); printk("CPU%u: Booted secondary processor\n", cpu); @@ -273,6 +275,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void) local_flush_tlb_all(); cpu_init(); + preempt_disable(); /* * Give the platform a chance to do its own initialisation. diff --git a/arch/arm26/kernel/process.c b/arch/arm26/kernel/process.c index 9eb9964d32a..15833a0057d 100644 --- a/arch/arm26/kernel/process.c +++ b/arch/arm26/kernel/process.c @@ -74,15 +74,13 @@ __setup("hlt", hlt_setup); void cpu_idle(void) { /* endless idle loop with no priority at all */ - preempt_disable(); while (1) { - while (!need_resched()) { - local_irq_disable(); - if (!need_resched() && !hlt_counter) - local_irq_enable(); - } + while (!need_resched()) + cpu_relax(); + preempt_enable_no_resched(); + schedule(); + preempt_disable(); } - schedule(); } static char reboot_mode = 'h'; diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c index 957f551ba5c..13867f4fad1 100644 --- a/arch/cris/arch-v32/kernel/smp.c +++ b/arch/cris/arch-v32/kernel/smp.c @@ -161,6 +161,7 @@ void __init smp_callin(void) REG_WR(intr_vect, irq_regs[cpu], rw_mask, vect_mask); unmask_irq(IPI_INTR_VECT); unmask_irq(TIMER_INTR_VECT); + preempt_disable(); local_irq_enable(); cpu_set(cpu, cpu_online_map); diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c index 949a0e40e03..7c80afb1046 100644 --- a/arch/cris/kernel/process.c +++ b/arch/cris/kernel/process.c @@ -218,7 +218,9 @@ void cpu_idle (void) idle = default_idle; idle(); } + preempt_enable_no_resched(); schedule(); + preempt_disable(); } } diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c index 3001b82b151..54a452136f0 100644 --- a/arch/frv/kernel/process.c +++ b/arch/frv/kernel/process.c @@ -77,16 +77,20 @@ void (*idle)(void) = core_sleep_idle; */ void cpu_idle(void) { + int cpu = smp_processor_id(); + /* endless idle loop with no priority at all */ while (1) { while (!need_resched()) { - irq_stat[smp_processor_id()].idle_timestamp = jiffies; + irq_stat[cpu].idle_timestamp = jiffies; if (!frv_dma_inprogress && idle) idle(); } + preempt_enable_no_resched(); schedule(); + preempt_disable(); } } diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c index 27f1fce64ce..fe21adf3e75 100644 --- a/arch/h8300/kernel/process.c +++ b/arch/h8300/kernel/process.c @@ -53,22 +53,18 @@ asmlinkage void ret_from_fork(void); #if !defined(CONFIG_H8300H_SIM) && !defined(CONFIG_H8S_SIM) void default_idle(void) { - while(1) { - if (!need_resched()) { - local_irq_enable(); - __asm__("sleep"); - local_irq_disable(); - } - schedule(); - } + local_irq_disable(); + if (!need_resched()) { + local_irq_enable(); + /* XXX: race here! What if need_resched() gets set now? */ + __asm__("sleep"); + } else + local_irq_enable(); } #else void default_idle(void) { - while(1) { - if (need_resched()) - schedule(); - } + cpu_relax(); } #endif void (*idle)(void) = default_idle; @@ -81,7 +77,13 @@ void (*idle)(void) = default_idle; */ void cpu_idle(void) { - idle(); + while (1) { + while (!need_resched()) + idle(); + preempt_enable_no_resched(); + schedule(); + preempt_disable(); + } } void machine_restart(char * __unused) diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 7a14fdfd3af..5296e284ea3 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -179,7 +179,7 @@ static inline void play_dead(void) */ void cpu_idle(void) { - int cpu = raw_smp_processor_id(); + int cpu = smp_processor_id(); /* endless idle loop with no priority at all */ while (1) { @@ -201,7 +201,9 @@ void cpu_idle(void) __get_cpu_var(irq_stat).idle_timestamp = jiffies; idle(); } + preempt_enable_no_resched(); schedule(); + preempt_disable(); } } diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 47ec76794d0..bc5a9d97466 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -485,6 +485,7 @@ static void __devinit start_secondary(void *unused) * things done here to the most necessary things. */ cpu_init(); + preempt_disable(); smp_callin(); while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) rep_nop(); diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 051e050359e..4c621fc3c3b 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -292,7 +292,9 @@ cpu_idle (void) #ifdef CONFIG_SMP normal_xtp(); #endif + preempt_enable_no_resched(); schedule(); + preempt_disable(); check_pgt_cache(); if (cpu_is_offline(smp_processor_id())) play_dead(); diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 400a4898712..8f44e7d2df6 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -399,6 +399,7 @@ start_secondary (void *unused) Dprintk("start_secondary: starting CPU 0x%x\n", hard_smp_processor_id()); efi_map_pal_code(); cpu_init(); + preempt_disable(); smp_callin(); cpu_idle(); diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c index ea13a8f4d8b..cc4b571e5db 100644 --- a/arch/m32r/kernel/process.c +++ b/arch/m32r/kernel/process.c @@ -104,7 +104,9 @@ void cpu_idle (void) idle(); } + preempt_enable_no_resched(); schedule(); + preempt_disable(); } } diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c index 640d592ea07..b90c54169fa 100644 --- a/arch/m32r/kernel/smpboot.c +++ b/arch/m32r/kernel/smpboot.c @@ -426,6 +426,7 @@ void __init smp_cpus_done(unsigned int max_cpus) int __init start_secondary(void *unused) { cpu_init(); + preempt_disable(); smp_callin(); while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) cpu_relax(); diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index 11b1b90ba6b..13d109328a4 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -102,7 +102,9 @@ void cpu_idle(void) while (1) { while (!need_resched()) idle(); + preempt_enable_no_resched(); schedule(); + preempt_disable(); } } diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 4fe3d5715c4..dd725779d91 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -52,7 +52,9 @@ ATTRIB_NORET void cpu_idle(void) while (!need_resched()) if (cpu_wait) (*cpu_wait)(); + preempt_enable_no_resched(); schedule(); + preempt_disable(); } } diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index fcacf1aae98..25472fcaf71 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -82,7 +82,7 @@ extern ATTRIB_NORET void cpu_idle(void); */ asmlinkage void start_secondary(void) { - unsigned int cpu = smp_processor_id(); + unsigned int cpu; cpu_probe(); cpu_report(); @@ -95,6 +95,8 @@ asmlinkage void start_secondary(void) */ calibrate_delay(); + preempt_disable(); + cpu = smp_processor_id(); cpu_data[cpu].udelay_val = loops_per_jiffy; prom_smp_finish(); diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 7fdca87ef64..f482f78de43 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -92,7 +92,9 @@ void cpu_idle(void) while (1) { while (!need_resched()) barrier(); + preempt_enable_no_resched(); schedule(); + preempt_disable(); check_pgt_cache(); } } diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 5db3be4e270..a9ecf646578 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -463,6 +463,7 @@ void __init smp_callin(void) #endif smp_cpu_init(slave_id); + preempt_disable(); #if 0 /* NOT WORKING YET - see entry.S */ istack = (void *)__get_free_pages(GFP_KERNEL,ISTACK_ORDER); diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index d3e4bf756c8..0130f2619da 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -694,7 +694,9 @@ static void iseries_shared_idle(void) if (hvlpevent_is_pending()) process_iSeries_events(); + preempt_enable_no_resched(); schedule(); + preempt_disable(); } } @@ -726,7 +728,9 @@ static void iseries_dedicated_idle(void) } ppc64_runlatch_on(); + preempt_enable_no_resched(); schedule(); + preempt_disable(); } } diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index e78c3936884..4854f5eb5c3 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -539,7 +539,9 @@ static void pseries_dedicated_idle(void) lpaca->lppaca.idle = 0; ppc64_runlatch_on(); + preempt_enable_no_resched(); schedule(); + preempt_disable(); if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING) cpu_die(); @@ -583,7 +585,9 @@ static void pseries_shared_idle(void) lpaca->lppaca.idle = 0; ppc64_runlatch_on(); + preempt_enable_no_resched(); schedule(); + preempt_disable(); if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING) cpu_die(); diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c index 11e5b44713f..a6141f05c91 100644 --- a/arch/ppc/kernel/idle.c +++ b/arch/ppc/kernel/idle.c @@ -53,10 +53,6 @@ void default_idle(void) } #endif } - if (need_resched()) - schedule(); - if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING) - cpu_die(); } /* @@ -64,11 +60,22 @@ void default_idle(void) */ void cpu_idle(void) { - for (;;) + int cpu = smp_processor_id(); + + for (;;) { if (ppc_md.idle != NULL) ppc_md.idle(); else default_idle(); + if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING) + cpu_die(); + if (need_resched()) { + preempt_enable_no_resched(); + schedule(); + preempt_disable(); + } + + } } #if defined(CONFIG_SYSCTL) && defined(CONFIG_6xx) diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c index bc5bf112483..43b8fc2ca59 100644 --- a/arch/ppc/kernel/smp.c +++ b/arch/ppc/kernel/smp.c @@ -341,6 +341,7 @@ int __devinit start_secondary(void *unused) cpu = smp_processor_id(); smp_store_cpu_info(cpu); set_dec(tb_ticks_per_jiffy); + preempt_disable(); cpu_callin_map[cpu] = 1; printk("CPU %d done callin...\n", cpu); diff --git a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c index 8fec2746980..909ea669af9 100644 --- a/arch/ppc64/kernel/idle.c +++ b/arch/ppc64/kernel/idle.c @@ -61,7 +61,9 @@ void default_idle(void) } ppc64_runlatch_on(); + preempt_enable_no_resched(); schedule(); + preempt_disable(); if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING) cpu_die(); } @@ -77,7 +79,9 @@ void native_idle(void) if (need_resched()) { ppc64_runlatch_on(); + preempt_enable_no_resched(); schedule(); + preempt_disable(); } if (cpu_is_offline(smp_processor_id()) && diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 9f3dff6c0b7..66ca5757e36 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -102,7 +102,6 @@ void default_idle(void) local_irq_disable(); if (need_resched()) { local_irq_enable(); - schedule(); return; } @@ -139,8 +138,14 @@ void default_idle(void) void cpu_idle(void) { - for (;;) - default_idle(); + for (;;) { + while (!need_resched()) + default_idle(); + + preempt_enable_no_resched(); + schedule(); + preempt_disable(); + } } void show_regs(struct pt_regs *regs) diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index e13c87b446b..5856b3fda6b 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -533,6 +533,7 @@ int __devinit start_secondary(void *cpuvoid) { /* Setup the cpu */ cpu_init(); + preempt_disable(); /* init per CPU timer */ init_cpu_timer(); #ifdef CONFIG_VIRT_TIMER diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index 6dce9d0b81f..1cbc26b796a 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -64,7 +64,9 @@ void default_idle(void) cpu_sleep(); } + preempt_enable_no_resched(); schedule(); + preempt_disable(); } } diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index 5ecefc02896..59e49b18252 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -112,7 +112,9 @@ int __cpu_up(unsigned int cpu) int start_secondary(void *unused) { - unsigned int cpu = smp_processor_id(); + unsigned int cpu; + + cpu = smp_processor_id(); atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; @@ -120,6 +122,7 @@ int start_secondary(void *unused) smp_store_cpu_info(cpu); __smp_slave_init(cpu); + preempt_disable(); per_cpu_trap_init(); atomic_inc(&cpus_booted); diff --git a/arch/sh64/kernel/process.c b/arch/sh64/kernel/process.c index efde41c0cd6..0c09537449b 100644 --- a/arch/sh64/kernel/process.c +++ b/arch/sh64/kernel/process.c @@ -334,7 +334,9 @@ void default_idle(void) } local_irq_enable(); } + preempt_enable_no_resched(); schedule(); + preempt_disable(); } } diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 29e72b57d4f..c39f4d01096 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -120,7 +120,9 @@ void cpu_idle(void) (*pm_idle)(); } + preempt_enable_no_resched(); schedule(); + preempt_disable(); check_pgt_cache(); } } @@ -133,7 +135,9 @@ void cpu_idle(void) /* endless idle loop with no priority at all */ while(1) { if(need_resched()) { + preempt_enable_no_resched(); schedule(); + preempt_disable(); check_pgt_cache(); } barrier(); /* or else gcc optimizes... */ diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 7d10b039709..2f89206e008 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -74,7 +74,9 @@ void cpu_idle(void) while (!need_resched()) barrier(); + preempt_enable_no_resched(); schedule(); + preempt_disable(); check_pgt_cache(); } } @@ -93,7 +95,9 @@ void cpu_idle(void) if (need_resched()) { unidle_me(); clear_thread_flag(TIF_POLLING_NRFLAG); + preempt_enable_no_resched(); schedule(); + preempt_disable(); set_thread_flag(TIF_POLLING_NRFLAG); check_pgt_cache(); } diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 5d90ee9aebf..8aca4b1dc04 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -168,6 +168,9 @@ void __init smp_callin(void) rmb(); cpu_set(cpuid, cpu_online_map); + + /* idle thread is expected to have preempt disabled */ + preempt_disable(); } void cpu_panic(void) diff --git a/arch/v850/kernel/process.c b/arch/v850/kernel/process.c index 9c708c32c1f..39cf247cdae 100644 --- a/arch/v850/kernel/process.c +++ b/arch/v850/kernel/process.c @@ -36,11 +36,8 @@ extern void ret_from_fork (void); /* The idle loop. */ void default_idle (void) { - while (1) { - while (! need_resched ()) - asm ("halt; nop; nop; nop; nop; nop" ::: "cc"); - schedule (); - } + while (! need_resched ()) + asm ("halt; nop; nop; nop; nop; nop" ::: "cc"); } void (*idle)(void) = default_idle; @@ -54,7 +51,14 @@ void (*idle)(void) = default_idle; void cpu_idle (void) { /* endless idle loop with no priority at all */ - (*idle) (); + while (1) { + while (!need_resched()) + (*idle) (); + + preempt_enable_no_resched(); + schedule(); + preempt_disable(); + } } /* diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index b5a89c0bdf5..571f9fe490c 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c @@ -204,7 +204,9 @@ void cpu_idle (void) idle(); } + preempt_enable_no_resched(); schedule(); + preempt_disable(); } } diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index 4b5b088ec10..c4e59bbdc18 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c @@ -472,6 +472,7 @@ void __cpuinit start_secondary(void) * things done here to the most necessary things. */ cpu_init(); + preempt_disable(); smp_callin(); /* otherwise gcc will move up the smp_processor_id before the cpu_init */ diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index 08ef6d82ee5..6a44b54ae81 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c @@ -96,8 +96,9 @@ void cpu_idle(void) while (1) { while (!need_resched()) platform_idle(); - preempt_enable(); + preempt_enable_no_resched(); schedule(); + preempt_disable(); } } diff --git a/init/main.c b/init/main.c index f142d403534..27f97f9b463 100644 --- a/init/main.c +++ b/init/main.c @@ -394,14 +394,16 @@ static void noinline rest_init(void) kernel_thread(init, NULL, CLONE_FS | CLONE_SIGHAND); numa_default_policy(); unlock_kernel(); - preempt_enable_no_resched(); /* * The boot idle thread must execute schedule() * at least one to get things moving: */ + preempt_enable_no_resched(); schedule(); + preempt_disable(); + /* Call into cpu_idle with preempt disabled */ cpu_idle(); } -- cgit v1.2.3 From 64c7c8f88559624abdbe12b5da6502e8879f8d28 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Tue, 8 Nov 2005 21:39:04 -0800 Subject: [PATCH] sched: resched and cpu_idle rework Make some changes to the NEED_RESCHED and POLLING_NRFLAG to reduce confusion, and make their semantics rigid. Improves efficiency of resched_task and some cpu_idle routines. * In resched_task: - TIF_NEED_RESCHED is only cleared with the task's runqueue lock held, and as we hold it during resched_task, then there is no need for an atomic test and set there. The only other time this should be set is when the task's quantum expires, in the timer interrupt - this is protected against because the rq lock is irq-safe. - If TIF_NEED_RESCHED is set, then we don't need to do anything. It won't get unset until the task get's schedule()d off. - If we are running on the same CPU as the task we resched, then set TIF_NEED_RESCHED and no further action is required. - If we are running on another CPU, and TIF_POLLING_NRFLAG is *not* set after TIF_NEED_RESCHED has been set, then we need to send an IPI. Using these rules, we are able to remove the test and set operation in resched_task, and make clear the previously vague semantics of POLLING_NRFLAG. * In idle routines: - Enter cpu_idle with preempt disabled. When the need_resched() condition becomes true, explicitly call schedule(). This makes things a bit clearer (IMO), but haven't updated all architectures yet. - Many do a test and clear of TIF_NEED_RESCHED for some reason. According to the resched_task rules, this isn't needed (and actually breaks the assumption that TIF_NEED_RESCHED is only cleared with the runqueue lock held). So remove that. Generally one less locked memory op when switching to the idle thread. - Many idle routines clear TIF_POLLING_NRFLAG, and only set it in the inner most polling idle loops. The above resched_task semantics allow it to be set until before the last time need_resched() is checked before going into a halt requiring interrupt wakeup. Many idle routines simply never enter such a halt, and so POLLING_NRFLAG can be always left set, completely eliminating resched IPIs when rescheduling the idle task. POLLING_NRFLAG width can be increased, to reduce the chance of resched IPIs. Signed-off-by: Nick Piggin Cc: Ingo Molnar Cc: Con Kolivas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/sched-arch.txt | 89 ++++++++++++++++++++++++++++++++++ arch/alpha/kernel/process.c | 10 ++-- arch/arm/kernel/process.c | 14 ++++-- arch/i386/kernel/apm.c | 20 +++++++- arch/i386/kernel/process.c | 64 +++++++++++------------- arch/ia64/kernel/process.c | 32 ++++++------ arch/parisc/kernel/process.c | 2 + arch/powerpc/platforms/iseries/setup.c | 10 +--- arch/powerpc/platforms/pseries/setup.c | 12 ++--- arch/ppc/kernel/idle.c | 20 ++++---- arch/ppc64/kernel/idle.c | 11 +---- arch/s390/kernel/process.c | 13 ++--- arch/sh/kernel/process.c | 12 ++--- arch/sh64/kernel/process.c | 14 ++---- arch/sparc/kernel/process.c | 35 ++++++------- arch/sparc64/kernel/process.c | 20 +++++--- arch/sparc64/kernel/smp.c | 13 +---- arch/x86_64/kernel/process.c | 67 ++++++++++++------------- drivers/acpi/processor_idle.c | 37 ++++++++------ kernel/sched.c | 21 +++++--- 20 files changed, 296 insertions(+), 220 deletions(-) create mode 100644 Documentation/sched-arch.txt diff --git a/Documentation/sched-arch.txt b/Documentation/sched-arch.txt new file mode 100644 index 00000000000..941615a9769 --- /dev/null +++ b/Documentation/sched-arch.txt @@ -0,0 +1,89 @@ + CPU Scheduler implementation hints for architecture specific code + + Nick Piggin, 2005 + +Context switch +============== +1. Runqueue locking +By default, the switch_to arch function is called with the runqueue +locked. This is usually not a problem unless switch_to may need to +take the runqueue lock. This is usually due to a wake up operation in +the context switch. See include/asm-ia64/system.h for an example. + +To request the scheduler call switch_to with the runqueue unlocked, +you must `#define __ARCH_WANT_UNLOCKED_CTXSW` in a header file +(typically the one where switch_to is defined). + +Unlocked context switches introduce only a very minor performance +penalty to the core scheduler implementation in the CONFIG_SMP case. + +2. Interrupt status +By default, the switch_to arch function is called with interrupts +disabled. Interrupts may be enabled over the call if it is likely to +introduce a significant interrupt latency by adding the line +`#define __ARCH_WANT_INTERRUPTS_ON_CTXSW` in the same place as for +unlocked context switches. This define also implies +`__ARCH_WANT_UNLOCKED_CTXSW`. See include/asm-arm/system.h for an +example. + + +CPU idle +======== +Your cpu_idle routines need to obey the following rules: + +1. Preempt should now disabled over idle routines. Should only + be enabled to call schedule() then disabled again. + +2. need_resched/TIF_NEED_RESCHED is only ever set, and will never + be cleared until the running task has called schedule(). Idle + threads need only ever query need_resched, and may never set or + clear it. + +3. When cpu_idle finds (need_resched() == 'true'), it should call + schedule(). It should not call schedule() otherwise. + +4. The only time interrupts need to be disabled when checking + need_resched is if we are about to sleep the processor until + the next interrupt (this doesn't provide any protection of + need_resched, it prevents losing an interrupt). + + 4a. Common problem with this type of sleep appears to be: + local_irq_disable(); + if (!need_resched()) { + local_irq_enable(); + *** resched interrupt arrives here *** + __asm__("sleep until next interrupt"); + } + +5. TIF_POLLING_NRFLAG can be set by idle routines that do not + need an interrupt to wake them up when need_resched goes high. + In other words, they must be periodically polling need_resched, + although it may be reasonable to do some background work or enter + a low CPU priority. + + 5a. If TIF_POLLING_NRFLAG is set, and we do decide to enter + an interrupt sleep, it needs to be cleared then a memory + barrier issued (followed by a test of need_resched with + interrupts disabled, as explained in 3). + +arch/i386/kernel/process.c has examples of both polling and +sleeping idle functions. + + +Possible arch/ problems +======================= + +Possible arch problems I found (and either tried to fix or didn't): + +h8300 - Is such sleeping racy vs interrupts? (See #4a). + The H8/300 manual I found indicates yes, however disabling IRQs + over the sleep mean only NMIs can wake it up, so can't fix easily + without doing spin waiting. + +ia64 - is safe_halt call racy vs interrupts? (does it sleep?) (See #4a) + +sh64 - Is sleeping racy vs interrupts? (See #4a) + +sparc - IRQs on at this point(?), change local_irq_save to _disable. + - TODO: needs secondary CPUs to disable preempt (See #1) + diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index eb20c3afff5..a8682612abc 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -43,21 +43,17 @@ #include "proto.h" #include "pci_impl.h" -void default_idle(void) -{ - barrier(); -} - void cpu_idle(void) { + set_thread_flag(TIF_POLLING_NRFLAG); + while (1) { - void (*idle)(void) = default_idle; /* FIXME -- EV6 and LCA45 know how to power down the CPU. */ while (!need_resched()) - idle(); + cpu_relax(); schedule(); } } diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 93dd92cc12f..c0f6a119de3 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -86,12 +86,16 @@ EXPORT_SYMBOL(pm_power_off); */ void default_idle(void) { - local_irq_disable(); - if (!need_resched() && !hlt_counter) { - timer_dyn_reprogram(); - arch_idle(); + if (hlt_counter) + cpu_relax(); + else { + local_irq_disable(); + if (!need_resched()) { + timer_dyn_reprogram(); + arch_idle(); + } + local_irq_enable(); } - local_irq_enable(); } /* diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 86e80c55147..003548b8735 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -769,8 +769,26 @@ static int set_system_power_state(u_short state) static int apm_do_idle(void) { u32 eax; + u8 ret = 0; + int idled = 0; + int polling; + + polling = test_thread_flag(TIF_POLLING_NRFLAG); + if (polling) { + clear_thread_flag(TIF_POLLING_NRFLAG); + smp_mb__after_clear_bit(); + } + if (!need_resched()) { + idled = 1; + ret = apm_bios_call_simple(APM_FUNC_IDLE, 0, 0, &eax); + } + if (polling) + set_thread_flag(TIF_POLLING_NRFLAG); + + if (!idled) + return 0; - if (apm_bios_call_simple(APM_FUNC_IDLE, 0, 0, &eax)) { + if (ret) { static unsigned long t; /* This always fails on some SMP boards running UP kernels. diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 5296e284ea3..1cb261f225d 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -99,14 +99,22 @@ EXPORT_SYMBOL(enable_hlt); */ void default_idle(void) { + local_irq_enable(); + if (!hlt_counter && boot_cpu_data.hlt_works_ok) { - local_irq_disable(); - if (!need_resched()) - safe_halt(); - else - local_irq_enable(); + clear_thread_flag(TIF_POLLING_NRFLAG); + smp_mb__after_clear_bit(); + while (!need_resched()) { + local_irq_disable(); + if (!need_resched()) + safe_halt(); + else + local_irq_enable(); + } + set_thread_flag(TIF_POLLING_NRFLAG); } else { - cpu_relax(); + while (!need_resched()) + cpu_relax(); } } #ifdef CONFIG_APM_MODULE @@ -120,29 +128,14 @@ EXPORT_SYMBOL(default_idle); */ static void poll_idle (void) { - int oldval; - local_irq_enable(); - /* - * Deal with another CPU just having chosen a thread to - * run here: - */ - oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED); - - if (!oldval) { - set_thread_flag(TIF_POLLING_NRFLAG); - asm volatile( - "2:" - "testl %0, %1;" - "rep; nop;" - "je 2b;" - : : "i"(_TIF_NEED_RESCHED), "m" (current_thread_info()->flags)); - - clear_thread_flag(TIF_POLLING_NRFLAG); - } else { - set_need_resched(); - } + asm volatile( + "2:" + "testl %0, %1;" + "rep; nop;" + "je 2b;" + : : "i"(_TIF_NEED_RESCHED), "m" (current_thread_info()->flags)); } #ifdef CONFIG_HOTPLUG_CPU @@ -181,6 +174,8 @@ void cpu_idle(void) { int cpu = smp_processor_id(); + set_thread_flag(TIF_POLLING_NRFLAG); + /* endless idle loop with no priority at all */ while (1) { while (!need_resched()) { @@ -246,15 +241,12 @@ static void mwait_idle(void) { local_irq_enable(); - if (!need_resched()) { - set_thread_flag(TIF_POLLING_NRFLAG); - do { - __monitor((void *)¤t_thread_info()->flags, 0, 0); - if (need_resched()) - break; - __mwait(0, 0); - } while (!need_resched()); - clear_thread_flag(TIF_POLLING_NRFLAG); + while (!need_resched()) { + __monitor((void *)¤t_thread_info()->flags, 0, 0); + smp_mb(); + if (need_resched()) + break; + __mwait(0, 0); } } diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 4c621fc3c3b..640d6908f8e 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -197,11 +197,15 @@ void default_idle (void) { local_irq_enable(); - while (!need_resched()) - if (can_do_pal_halt) - safe_halt(); - else + while (!need_resched()) { + if (can_do_pal_halt) { + local_irq_disable(); + if (!need_resched()) + safe_halt(); + local_irq_enable(); + } else cpu_relax(); + } } #ifdef CONFIG_HOTPLUG_CPU @@ -263,16 +267,16 @@ void __attribute__((noreturn)) cpu_idle (void) { void (*mark_idle)(int) = ia64_mark_idle; + int cpu = smp_processor_id(); + set_thread_flag(TIF_POLLING_NRFLAG); /* endless idle loop with no priority at all */ while (1) { + if (!need_resched()) { + void (*idle)(void); #ifdef CONFIG_SMP - if (!need_resched()) min_xtp(); #endif - while (!need_resched()) { - void (*idle)(void); - if (__get_cpu_var(cpu_idle_state)) __get_cpu_var(cpu_idle_state) = 0; @@ -284,19 +288,17 @@ cpu_idle (void) if (!idle) idle = default_idle; (*idle)(); - } - - if (mark_idle) - (*mark_idle)(0); - + if (mark_idle) + (*mark_idle)(0); #ifdef CONFIG_SMP - normal_xtp(); + normal_xtp(); #endif + } preempt_enable_no_resched(); schedule(); preempt_disable(); check_pgt_cache(); - if (cpu_is_offline(smp_processor_id())) + if (cpu_is_offline(cpu)) play_dead(); } } diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index f482f78de43..fee4f1f09ad 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -88,6 +88,8 @@ void default_idle(void) */ void cpu_idle(void) { + set_thread_flag(TIF_POLLING_NRFLAG); + /* endless idle loop with no priority at all */ while (1) { while (!need_resched()) diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 0130f2619da..7f8f0cda6a7 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -703,13 +703,10 @@ static void iseries_shared_idle(void) static void iseries_dedicated_idle(void) { long oldval; + set_thread_flag(TIF_POLLING_NRFLAG); while (1) { - oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED); - - if (!oldval) { - set_thread_flag(TIF_POLLING_NRFLAG); - + if (!need_resched()) { while (!need_resched()) { ppc64_runlatch_off(); HMT_low(); @@ -722,9 +719,6 @@ static void iseries_dedicated_idle(void) } HMT_medium(); - clear_thread_flag(TIF_POLLING_NRFLAG); - } else { - set_need_resched(); } ppc64_runlatch_on(); diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 4854f5eb5c3..a093a0d4dd6 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -469,6 +469,7 @@ static inline void dedicated_idle_sleep(unsigned int cpu) * more. */ clear_thread_flag(TIF_POLLING_NRFLAG); + smp_mb__after_clear_bit(); /* * SMT dynamic mode. Cede will result in this thread going @@ -481,6 +482,7 @@ static inline void dedicated_idle_sleep(unsigned int cpu) cede_processor(); else local_irq_enable(); + set_thread_flag(TIF_POLLING_NRFLAG); } else { /* * Give the HV an opportunity at the processor, since we are @@ -492,11 +494,11 @@ static inline void dedicated_idle_sleep(unsigned int cpu) static void pseries_dedicated_idle(void) { - long oldval; struct paca_struct *lpaca = get_paca(); unsigned int cpu = smp_processor_id(); unsigned long start_snooze; unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay); + set_thread_flag(TIF_POLLING_NRFLAG); while (1) { /* @@ -505,10 +507,7 @@ static void pseries_dedicated_idle(void) */ lpaca->lppaca.idle = 1; - oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED); - if (!oldval) { - set_thread_flag(TIF_POLLING_NRFLAG); - + if (!need_resched()) { start_snooze = __get_tb() + *smt_snooze_delay * tb_ticks_per_usec; @@ -531,9 +530,6 @@ static void pseries_dedicated_idle(void) } HMT_medium(); - clear_thread_flag(TIF_POLLING_NRFLAG); - } else { - set_need_resched(); } lpaca->lppaca.idle = 0; diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c index a6141f05c91..3c4e4cb6107 100644 --- a/arch/ppc/kernel/idle.c +++ b/arch/ppc/kernel/idle.c @@ -63,18 +63,18 @@ void cpu_idle(void) int cpu = smp_processor_id(); for (;;) { - if (ppc_md.idle != NULL) - ppc_md.idle(); - else - default_idle(); - if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING) - cpu_die(); - if (need_resched()) { - preempt_enable_no_resched(); - schedule(); - preempt_disable(); + while (need_resched()) { + if (ppc_md.idle != NULL) + ppc_md.idle(); + else + default_idle(); } + if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING) + cpu_die(); + preempt_enable_no_resched(); + schedule(); + preempt_disable(); } } diff --git a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c index 909ea669af9..715bc0e71e0 100644 --- a/arch/ppc64/kernel/idle.c +++ b/arch/ppc64/kernel/idle.c @@ -34,15 +34,11 @@ extern void power4_idle(void); void default_idle(void) { - long oldval; unsigned int cpu = smp_processor_id(); + set_thread_flag(TIF_POLLING_NRFLAG); while (1) { - oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED); - - if (!oldval) { - set_thread_flag(TIF_POLLING_NRFLAG); - + if (!need_resched()) { while (!need_resched() && !cpu_is_offline(cpu)) { ppc64_runlatch_off(); @@ -55,9 +51,6 @@ void default_idle(void) } HMT_medium(); - clear_thread_flag(TIF_POLLING_NRFLAG); - } else { - set_need_resched(); } ppc64_runlatch_on(); diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 66ca5757e36..78b64fe5e7c 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -99,14 +99,15 @@ void default_idle(void) { int cpu, rc; + /* CPU is going idle. */ + cpu = smp_processor_id(); + local_irq_disable(); - if (need_resched()) { + if (need_resched()) { local_irq_enable(); - return; - } + return; + } - /* CPU is going idle. */ - cpu = smp_processor_id(); rc = notifier_call_chain(&idle_chain, CPU_IDLE, (void *)(long) cpu); if (rc != NOTIFY_OK && rc != NOTIFY_DONE) BUG(); @@ -119,7 +120,7 @@ void default_idle(void) __ctl_set_bit(8, 15); #ifdef CONFIG_HOTPLUG_CPU - if (cpu_is_offline(smp_processor_id())) + if (cpu_is_offline(cpu)) cpu_die(); #endif diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index 1cbc26b796a..fd4f240b833 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -51,14 +51,13 @@ void enable_hlt(void) EXPORT_SYMBOL(enable_hlt); -void default_idle(void) +void cpu_idle(void) { /* endless idle loop with no priority at all */ while (1) { if (hlt_counter) { - while (1) - if (need_resched()) - break; + while (!need_resched()) + cpu_relax(); } else { while (!need_resched()) cpu_sleep(); @@ -70,11 +69,6 @@ void default_idle(void) } } -void cpu_idle(void) -{ - default_idle(); -} - void machine_restart(char * __unused) { /* SR.BL=1 and invoke address error to let CPU reset (manual reset) */ diff --git a/arch/sh64/kernel/process.c b/arch/sh64/kernel/process.c index 0c09537449b..b95d0414185 100644 --- a/arch/sh64/kernel/process.c +++ b/arch/sh64/kernel/process.c @@ -307,23 +307,19 @@ __setup("hlt", hlt_setup); static inline void hlt(void) { - if (hlt_counter) - return; - __asm__ __volatile__ ("sleep" : : : "memory"); } /* * The idle loop on a uniprocessor SH.. */ -void default_idle(void) +void cpu_idle(void) { /* endless idle loop with no priority at all */ while (1) { if (hlt_counter) { - while (1) - if (need_resched()) - break; + while (!need_resched()) + cpu_relax(); } else { local_irq_disable(); while (!need_resched()) { @@ -338,11 +334,7 @@ void default_idle(void) schedule(); preempt_disable(); } -} -void cpu_idle(void) -{ - default_idle(); } void machine_restart(char * __unused) diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index c39f4d01096..ea864741146 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -67,13 +67,6 @@ extern void fpsave(unsigned long *, unsigned long *, void *, unsigned long *); struct task_struct *last_task_used_math = NULL; struct thread_info *current_set[NR_CPUS]; -/* - * default_idle is new in 2.5. XXX Review, currently stolen from sparc64. - */ -void default_idle(void) -{ -} - #ifndef CONFIG_SMP #define SUN4C_FAULT_HIGH 100 @@ -92,12 +85,11 @@ void cpu_idle(void) static unsigned long fps; unsigned long now; unsigned long faults; - unsigned long flags; extern unsigned long sun4c_kernel_faults; extern void sun4c_grow_kernel_ring(void); - local_irq_save(flags); + local_irq_disable(); now = jiffies; count -= (now - last_jiffies); last_jiffies = now; @@ -113,13 +105,16 @@ void cpu_idle(void) sun4c_grow_kernel_ring(); } } - local_irq_restore(flags); + local_irq_enable(); } - while((!need_resched()) && pm_idle) { - (*pm_idle)(); + if (pm_idle) { + while (!need_resched()) + (*pm_idle)(); + } else { + while (!need_resched()) + cpu_relax(); } - preempt_enable_no_resched(); schedule(); preempt_disable(); @@ -132,15 +127,15 @@ void cpu_idle(void) /* This is being executed in task 0 'user space'. */ void cpu_idle(void) { + set_thread_flag(TIF_POLLING_NRFLAG); /* endless idle loop with no priority at all */ while(1) { - if(need_resched()) { - preempt_enable_no_resched(); - schedule(); - preempt_disable(); - check_pgt_cache(); - } - barrier(); /* or else gcc optimizes... */ + while (!need_resched()) + cpu_relax(); + preempt_enable_no_resched(); + schedule(); + preempt_disable(); + check_pgt_cache(); } } diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 2f89206e008..02f9dec1d45 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -85,23 +85,31 @@ void cpu_idle(void) /* * the idle loop on a UltraMultiPenguin... + * + * TIF_POLLING_NRFLAG is set because we do not sleep the cpu + * inside of the idler task, so an interrupt is not needed + * to get a clean fast response. + * + * XXX Reverify this assumption... -DaveM + * + * Addendum: We do want it to do something for the signal + * delivery case, we detect that by just seeing + * if we are trying to send this to an idler or not. */ -#define idle_me_harder() (cpu_data(smp_processor_id()).idle_volume += 1) -#define unidle_me() (cpu_data(smp_processor_id()).idle_volume = 0) void cpu_idle(void) { + cpuinfo_sparc *cpuinfo = &local_cpu_data(); set_thread_flag(TIF_POLLING_NRFLAG); + while(1) { if (need_resched()) { - unidle_me(); - clear_thread_flag(TIF_POLLING_NRFLAG); + cpuinfo->idle_volume = 0; preempt_enable_no_resched(); schedule(); preempt_disable(); - set_thread_flag(TIF_POLLING_NRFLAG); check_pgt_cache(); } - idle_me_harder(); + cpuinfo->idle_volume++; /* The store ordering is so that IRQ handlers on * other cpus see our increasing idleness for the buddy diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 8aca4b1dc04..797a65493fb 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -1152,20 +1152,9 @@ void __init smp_cpus_done(unsigned int max_cpus) (bogosum/(5000/HZ))%100); } -/* This needn't do anything as we do not sleep the cpu - * inside of the idler task, so an interrupt is not needed - * to get a clean fast response. - * - * XXX Reverify this assumption... -DaveM - * - * Addendum: We do want it to do something for the signal - * delivery case, we detect that by just seeing - * if we are trying to send this to an idler or not. - */ void smp_send_reschedule(int cpu) { - if (cpu_data(cpu).idle_volume == 0) - smp_receive_signal(cpu); + smp_receive_signal(cpu); } /* This is a nop because we capture all other cpus diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 571f9fe490c..59be85d9a4b 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c @@ -86,12 +86,22 @@ EXPORT_SYMBOL(enable_hlt); */ void default_idle(void) { + local_irq_enable(); + if (!atomic_read(&hlt_counter)) { - local_irq_disable(); - if (!need_resched()) - safe_halt(); - else - local_irq_enable(); + clear_thread_flag(TIF_POLLING_NRFLAG); + smp_mb__after_clear_bit(); + while (!need_resched()) { + local_irq_disable(); + if (!need_resched()) + safe_halt(); + else + local_irq_enable(); + } + set_thread_flag(TIF_POLLING_NRFLAG); + } else { + while (!need_resched()) + cpu_relax(); } } @@ -102,30 +112,16 @@ void default_idle(void) */ static void poll_idle (void) { - int oldval; - local_irq_enable(); - /* - * Deal with another CPU just having chosen a thread to - * run here: - */ - oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED); - - if (!oldval) { - set_thread_flag(TIF_POLLING_NRFLAG); - asm volatile( - "2:" - "testl %0,%1;" - "rep; nop;" - "je 2b;" - : : - "i" (_TIF_NEED_RESCHED), - "m" (current_thread_info()->flags)); - clear_thread_flag(TIF_POLLING_NRFLAG); - } else { - set_need_resched(); - } + asm volatile( + "2:" + "testl %0,%1;" + "rep; nop;" + "je 2b;" + : : + "i" (_TIF_NEED_RESCHED), + "m" (current_thread_info()->flags)); } void cpu_idle_wait(void) @@ -187,6 +183,8 @@ static inline void play_dead(void) */ void cpu_idle (void) { + set_thread_flag(TIF_POLLING_NRFLAG); + /* endless idle loop with no priority at all */ while (1) { while (!need_resched()) { @@ -221,15 +219,12 @@ static void mwait_idle(void) { local_irq_enable(); - if (!need_resched()) { - set_thread_flag(TIF_POLLING_NRFLAG); - do { - __monitor((void *)¤t_thread_info()->flags, 0, 0); - if (need_resched()) - break; - __mwait(0, 0); - } while (!need_resched()); - clear_thread_flag(TIF_POLLING_NRFLAG); + while (!need_resched()) { + __monitor((void *)¤t_thread_info()->flags, 0, 0); + smp_mb(); + if (need_resched()) + break; + __mwait(0, 0); } } diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 161db4acfb9..573b6a97bb1 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -167,6 +167,19 @@ acpi_processor_power_activate(struct acpi_processor *pr, return; } +static void acpi_safe_halt(void) +{ + int polling = test_thread_flag(TIF_POLLING_NRFLAG); + if (polling) { + clear_thread_flag(TIF_POLLING_NRFLAG); + smp_mb__after_clear_bit(); + } + if (!need_resched()) + safe_halt(); + if (polling) + set_thread_flag(TIF_POLLING_NRFLAG); +} + static atomic_t c3_cpu_count; static void acpi_processor_idle(void) @@ -177,7 +190,7 @@ static void acpi_processor_idle(void) int sleep_ticks = 0; u32 t1, t2 = 0; - pr = processors[raw_smp_processor_id()]; + pr = processors[smp_processor_id()]; if (!pr) return; @@ -197,8 +210,13 @@ static void acpi_processor_idle(void) } cx = pr->power.state; - if (!cx) - goto easy_out; + if (!cx) { + if (pm_idle_save) + pm_idle_save(); + else + acpi_safe_halt(); + return; + } /* * Check BM Activity @@ -278,7 +296,8 @@ static void acpi_processor_idle(void) if (pm_idle_save) pm_idle_save(); else - safe_halt(); + acpi_safe_halt(); + /* * TBD: Can't get time duration while in C1, as resumes * go to an ISR rather than here. Need to instrument @@ -414,16 +433,6 @@ static void acpi_processor_idle(void) */ if (next_state != pr->power.state) acpi_processor_power_activate(pr, next_state); - - return; - - easy_out: - /* do C1 instead of busy loop */ - if (pm_idle_save) - pm_idle_save(); - else - safe_halt(); - return; } static int acpi_processor_set_power_policy(struct acpi_processor *pr) diff --git a/kernel/sched.c b/kernel/sched.c index 0f2def82229..ac3f5cc3bb5 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -864,21 +864,28 @@ static void deactivate_task(struct task_struct *p, runqueue_t *rq) #ifdef CONFIG_SMP static void resched_task(task_t *p) { - int need_resched, nrpolling; + int cpu; assert_spin_locked(&task_rq(p)->lock); - /* minimise the chance of sending an interrupt to poll_idle() */ - nrpolling = test_tsk_thread_flag(p,TIF_POLLING_NRFLAG); - need_resched = test_and_set_tsk_thread_flag(p,TIF_NEED_RESCHED); - nrpolling |= test_tsk_thread_flag(p,TIF_POLLING_NRFLAG); + if (unlikely(test_tsk_thread_flag(p, TIF_NEED_RESCHED))) + return; + + set_tsk_thread_flag(p, TIF_NEED_RESCHED); + + cpu = task_cpu(p); + if (cpu == smp_processor_id()) + return; - if (!need_resched && !nrpolling && (task_cpu(p) != smp_processor_id())) - smp_send_reschedule(task_cpu(p)); + /* NEED_RESCHED must be visible before we test POLLING_NRFLAG */ + smp_mb(); + if (!test_tsk_thread_flag(p, TIF_POLLING_NRFLAG)) + smp_send_reschedule(cpu); } #else static inline void resched_task(task_t *p) { + assert_spin_locked(&task_rq(p)->lock); set_tsk_need_resched(p); } #endif -- cgit v1.2.3 From 6d83b0bb8e5efda28ce4a1abc78277f1d03e50e5 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Tue, 8 Nov 2005 21:39:05 -0800 Subject: [PATCH] savagefb: X-panning fixes The driver unconditionally sets xpanstep to 2. However, a value of 4 empirically works better at bpp = 8, and 2 for 16 and 32. This buglet was exposed by the rotation code. Second fix is the unconditional call to update_start() without verifying if the offsets are correct. Remove this call, it's not necessary and secondly, it causes a crash with invalid values. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/savage/savagefb_driver.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index f0dfb35e319..09e2f284190 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c @@ -1315,10 +1315,14 @@ static void savagefb_set_fix(struct fb_info *info) info->fix.line_length = info->var.xres_virtual * info->var.bits_per_pixel / 8; - if (info->var.bits_per_pixel == 8) + if (info->var.bits_per_pixel == 8) { info->fix.visual = FB_VISUAL_PSEUDOCOLOR; - else + info->fix.xpanstep = 4; + } else { info->fix.visual = FB_VISUAL_TRUECOLOR; + info->fix.xpanstep = 2; + } + } #if defined(CONFIG_FB_SAVAGE_ACCEL) @@ -1363,7 +1367,6 @@ static int savagefb_set_par (struct fb_info *info) par->minClock = 10000; savagefb_set_par_int (par); - savagefb_update_start (par, var); fb_set_cmap (&info->cmap, info); savagefb_set_fix(info); savagefb_set_clip(info); @@ -1873,7 +1876,6 @@ static int __devinit savage_init_fb_info (struct fb_info *info, info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.type_aux = 0; - info->fix.xpanstep = 2; info->fix.ypanstep = 1; info->fix.ywrapstep = 0; info->fix.accel = id->driver_data; -- cgit v1.2.3 From 1dfcdfae5783fc10d7f8fcc336de838a44e7636c Mon Sep 17 00:00:00 2001 From: Michael Hanselmann Date: Tue, 8 Nov 2005 21:39:06 -0800 Subject: [PATCH] fbdev: Framebuffer mode required for PowerBook Titanium This patch adds the framebuffer mode required for an Apple PowerBook G4 Titanium. Signed-off-by: Michael Hanselmann Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/modedb.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index 1789a52d776..1da2f84bdc2 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c @@ -251,6 +251,10 @@ static const struct fb_videomode modedb[] = { NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + }, { + /* 1152x768, 60 Hz, PowerBook G4 Titanium I and II */ + NULL, 60, 1152, 768, 15386, 158, 26, 29, 3, 136, 6, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED }, }; -- cgit v1.2.3 From e4fc27618b75234b721c4a13d0e0d9d07e75e641 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Tue, 8 Nov 2005 21:39:09 -0800 Subject: [PATCH] fbcon: Console Rotation - Prepare fbcon for console rotation This patch series implements generic code to rotate the console at 90, 180, and 270 degrees. The implementation is completely done in the framebuffer console level, thus no changes to the framebuffer layer or to the drivers are needed. Console rotation is required by some Sharp-based devices where the natural orientation of the display is not at 0 degrees. Also, users that have displays that can pivot will benefit by having a console in portrait mode if they so desire. The choice to implement the code in the console layer rather than in the framebuffer layer is due to the following reasons: - it's fast - it does not require driver changes - it can coexist with devices that can rotate the display at the hardware level - it complements graphics applications that can do display rotation The changes to core fbcon are minimal-- recognition of the console rotation angle so it can swap directions, origins and axes (xres vs yres, xpanstep vs ypanstep, xoffset vs yoffset, etc) and storage of the rotation angle per display. The bulk of the code that does the actual drawing to the screen are placed in separate files. Each angle of rotation has separate methods (bmove, clear, putcs, cursor, update_start which is derived from update_var, and clear_margins). To mimimize processing time, the fontdata are pre-rotated at each console switch (only if the font or the angle has changed). The option can be compiled out (CONFIG_FRAMEBUFFER_CONSOLE_ROTATION = n) if rotation is not needed. Choosing the rotation angle can be done in several ways: 1. boot option fbcon=rotate:n, where n = 0 - normal n = 1 - 90 degrees (clockwise) n = 2 - 180 degrees (upside down) n = 3 - 270 degrees (counterclockwise) 2. echo n > /sys/class/graphics/fb[num]/con_rotate where n is the same as described above. It sets the angle of rotation of the current console 3 echo n > /sys/class/graphics/fb[num]/con_rotate_all where n is the same as described above. Globally sets the angle of rotation. GOTCHAS: The option, especially at angles of 90 and 270 degrees, will exercise the least used code of drivers. Namely, at these angles, panning is done in the x-axis, so it can reveal bugs in the driver if xpanstep is set incorrectly. A workaround is to set xpanstep = 0. Secondly, at these angles, the framebuffer memory access can be unaligned if (fontheight * bpp) % 32 ~= 0 which can reveal bugs in the drivers imageblit, fillrect and copyarea functions. (I think cfbfillrect may have this buglet). A workaround is to use a standard 8x16 font. Speed: The scrolling speed difference between 0 and 180 degrees is minimal, somewhere areound 1-2%. At 90 or 270 degress, speed drops down to a vicinity of 30-40%. This is understandable because the blit direction is across the framebuffer "direction." Scrolling will be helped at these angles if xpanstep is not equal to zero, use of 8x16 fonts, and setting xres_virtual >= xres * 2. Note: The code is tested on little-endian only, so I don't know if it will work in big-endian. Please let me know, it will take only less than a minute of your time. This patch prepares fbcon for console rotation and contains the following changes: - add rotate field in struct fbcon_ops to keep fbcon's current rotation angle - add con_rotate field in struct display to store per-display rotation angle - create a private copy of the current var to fbcon. This will prevent fbcon from directly manipulating info->var, especially the fields xoffset, yoffset and vmode. - add ability to swap pertinent axes (xres, yres; xpanstep, ypanstep; etc) depending on the rotation angle - change global update_var() (function that sets the screen start address) as an fbcon method update_start. This is required because the axes, start offset, and/or direction can be reversed depending on the rotation angle. - add fbcon method rotate_font() which will rotate each character bitmap to the correct angle of rotation. - add fbcon boot option 'rotate' to select the angle of rotation at bootime. Currently does nothing until all patches are applied. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/Kconfig | 10 ++ drivers/video/console/bitblit.c | 46 +++---- drivers/video/console/fbcon.c | 285 +++++++++++++++++++++++++-------------- drivers/video/console/fbcon.h | 58 +++++++- drivers/video/console/tileblit.c | 13 ++ include/linux/fb.h | 12 +- 6 files changed, 286 insertions(+), 138 deletions(-) diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index fadf7c5d216..94c5f1392cc 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -101,6 +101,16 @@ config FRAMEBUFFER_CONSOLE help Low-level framebuffer-based console driver. +config FRAMEBUFFER_CONSOLE_ROTATION + bool "Framebuffer Console Rotation" + depends on FRAMEBUFFER_CONSOLE + help + Enable display rotation for the framebuffer console. This is done + in software and may be significantly slower than a normally oriented + display. Note that the rotation is done at the console level only + such that other users of the framebuffer will remain normally + oriented. + config STI_CONSOLE tristate "STI text console" depends on PARISC diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c index 67857b3cfc8..e65fc3ef763 100644 --- a/drivers/video/console/bitblit.c +++ b/drivers/video/console/bitblit.c @@ -22,35 +22,6 @@ /* * Accelerated handlers. */ -#define FBCON_ATTRIBUTE_UNDERLINE 1 -#define FBCON_ATTRIBUTE_REVERSE 2 -#define FBCON_ATTRIBUTE_BOLD 4 - -static inline int real_y(struct display *p, int ypos) -{ - int rows = p->vrows; - - ypos += p->yscroll; - return ypos < rows ? ypos : ypos - rows; -} - - -static inline int get_attribute(struct fb_info *info, u16 c) -{ - int attribute = 0; - - if (fb_get_color_depth(&info->var, &info->fix) == 1) { - if (attr_underline(c)) - attribute |= FBCON_ATTRIBUTE_UNDERLINE; - if (attr_reverse(c)) - attribute |= FBCON_ATTRIBUTE_REVERSE; - if (attr_bold(c)) - attribute |= FBCON_ATTRIBUTE_BOLD; - } - - return attribute; -} - static inline void update_attr(u8 *dst, u8 *src, int attribute, struct vc_data *vc) { @@ -418,6 +389,18 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, ops->cursor_reset = 0; } +static int bit_update_start(struct fb_info *info) +{ + struct fbcon_ops *ops = info->fbcon_par; + int err; + + err = fb_pan_display(info, &ops->var); + ops->var.xoffset = info->var.xoffset; + ops->var.yoffset = info->var.yoffset; + ops->var.vmode = info->var.vmode; + return err; +} + void fbcon_set_bitops(struct fbcon_ops *ops) { ops->bmove = bit_bmove; @@ -425,6 +408,11 @@ void fbcon_set_bitops(struct fbcon_ops *ops) ops->putcs = bit_putcs; ops->clear_margins = bit_clear_margins; ops->cursor = bit_cursor; + ops->update_start = bit_update_start; + ops->rotate_font = NULL; + + if (ops->rotate) + fbcon_set_rotate(ops); } EXPORT_SYMBOL(fbcon_set_bitops); diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 3cf1b61ff1f..b5d678c7325 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -107,6 +107,8 @@ enum { }; struct display fb_display[MAX_NR_CONSOLES]; +EXPORT_SYMBOL(fb_display); + static signed char con2fb_map[MAX_NR_CONSOLES]; static signed char con2fb_map_boot[MAX_NR_CONSOLES]; static int logo_height; @@ -130,6 +132,9 @@ static char fontname[40]; /* current fb_info */ static int info_idx = -1; +/* console rotation */ +static int rotate; + static const struct consw fb_con; #define CM_SOFTBACK (8) @@ -176,7 +181,6 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines); /* * Internal routines */ -static __inline__ int real_y(struct display *p, int ypos); static __inline__ void ywrap_up(struct vc_data *vc, int count); static __inline__ void ywrap_down(struct vc_data *vc, int count); static __inline__ void ypan_up(struct vc_data *vc, int count); @@ -203,6 +207,13 @@ static irqreturn_t fb_vbl_detect(int irq, void *dummy, struct pt_regs *fp) } #endif +static inline void fbcon_set_rotation(struct fb_info *info, struct display *p) +{ + struct fbcon_ops *ops = info->fbcon_par; + + ops->rotate = FB_ROTATE_UR; +} + static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info) { struct fbcon_ops *ops = info->fbcon_par; @@ -422,6 +433,14 @@ static int __init fb_console_setup(char *this_opt) last_fb_vc = simple_strtoul(options, &options, 10) - 1; fbcon_is_default = 0; } + + if (!strncmp(options, "rotate:", 7)) { + options += 7; + if (*options) + rotate = simple_strtoul(options, &options, 0); + if (rotate > 3) + rotate = 0; + } } return 0; } @@ -558,16 +577,24 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info, if ((info->flags & FBINFO_MISC_TILEBLITTING)) fbcon_set_tileops(vc, info, p, ops); - else + else { + struct display *disp; + + disp = (p) ? p : &fb_display[vc->vc_num]; + fbcon_set_rotation(info, disp); fbcon_set_bitops(ops); + } } #else static void set_blitting_type(struct vc_data *vc, struct fb_info *info, struct display *p) { struct fbcon_ops *ops = info->fbcon_par; + struct display *disp; info->flags &= ~FBINFO_MISC_TILEBLITTING; + disp = (p) ? p : &fb_display[vc->vc_num]; + fbcon_set_rotation(info, disp); fbcon_set_bitops(ops); } #endif /* CONFIG_MISC_TILEBLITTING */ @@ -627,6 +654,7 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo, fbcon_del_cursor_timer(oldinfo); kfree(ops->cursor_state.mask); kfree(ops->cursor_data); + kfree(ops->fontbuffer); kfree(oldinfo->fbcon_par); oldinfo->fbcon_par = NULL; module_put(oldinfo->fbops->owner); @@ -827,7 +855,9 @@ static const char *fbcon_startup(void) memset(ops, 0, sizeof(struct fbcon_ops)); ops->currcon = -1; ops->graphics = 1; + ops->cur_rotate = -1; info->fbcon_par = ops; + p->con_rotate = rotate; set_blitting_type(vc, info, NULL); if (info->fix.type != FB_TYPE_TEXT) { @@ -866,8 +896,10 @@ static const char *fbcon_startup(void) vc->vc_font.charcount = 256; /* FIXME Need to support more fonts */ } - cols = info->var.xres / vc->vc_font.width; - rows = info->var.yres / vc->vc_font.height; + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= vc->vc_font.width; + rows /= vc->vc_font.height; vc_resize(vc, cols, rows); DPRINTK("mode: %s\n", info->fix.id); @@ -953,8 +985,6 @@ static void fbcon_init(struct vc_data *vc, int init) (info->fix.type == FB_TYPE_TEXT)) logo = 0; - info->var.xoffset = info->var.yoffset = p->yscroll = 0; /* reset wrap/pan */ - if (var_to_display(p, &info->var, info)) return; @@ -986,13 +1016,18 @@ static void fbcon_init(struct vc_data *vc, int init) if (!*vc->vc_uni_pagedir_loc) con_copy_unimap(vc, svc); + ops = info->fbcon_par; + p->con_rotate = rotate; + set_blitting_type(vc, info, NULL); + cols = vc->vc_cols; rows = vc->vc_rows; - new_cols = info->var.xres / vc->vc_font.width; - new_rows = info->var.yres / vc->vc_font.height; + new_cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + new_rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + new_cols /= vc->vc_font.width; + new_rows /= vc->vc_font.height; vc_resize(vc, new_cols, new_rows); - ops = info->fbcon_par; /* * We must always set the mode. The mode of the previous console * driver could be in the same resolution but we are using different @@ -1030,6 +1065,12 @@ static void fbcon_init(struct vc_data *vc, int init) if (vc == svc && softback_buf) fbcon_update_softback(vc); + + if (ops->rotate_font && ops->rotate_font(info, vc, p)) { + ops->rotate = FB_ROTATE_UR; + set_blitting_type(vc, info, p); + } + } static void fbcon_deinit(struct vc_data *vc) @@ -1066,15 +1107,6 @@ static void fbcon_deinit(struct vc_data *vc) * restriction is simplicity & efficiency at the moment. */ -static __inline__ int real_y(struct display *p, int ypos) -{ - int rows = p->vrows; - - ypos += p->yscroll; - return ypos < rows ? ypos : ypos - rows; -} - - static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height, int width) { @@ -1162,13 +1194,6 @@ static int scrollback_phys_max = 0; static int scrollback_max = 0; static int scrollback_current = 0; -static int update_var(int con, struct fb_info *info) -{ - if (con == ((struct fbcon_ops *)info->fbcon_par)->currcon) - return fb_pan_display(info, &info->var); - return 0; -} - /* * If no vc is existent yet, just set struct display */ @@ -1178,7 +1203,6 @@ static void fbcon_preset_disp(struct fb_info *info, struct fb_var_screeninfo *va struct display *p = &fb_display[unit]; struct display *t = &fb_display[fg_console]; - var->xoffset = var->yoffset = p->yscroll = 0; if (var_to_display(p, var, info)) return; @@ -1194,9 +1218,9 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, struct display *p = &fb_display[vc->vc_num], *t; struct vc_data **default_mode = vc->vc_display_fg; struct vc_data *svc = *default_mode; + struct fbcon_ops *ops = info->fbcon_par; int rows, cols, charcnt = 256; - var->xoffset = var->yoffset = p->yscroll = 0; if (var_to_display(p, var, info)) return; t = &fb_display[svc->vc_num]; @@ -1213,9 +1237,10 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, var->activate = FB_ACTIVATE_NOW; info->var.activate = var->activate; - info->var.yoffset = info->var.xoffset = 0; + var->yoffset = info->var.yoffset; + var->xoffset = info->var.xoffset; fb_set_var(info, var); - + ops->var = info->var; vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; if (charcnt == 256) { @@ -1231,9 +1256,12 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, if (!*vc->vc_uni_pagedir_loc) con_copy_unimap(vc, svc); - cols = var->xres / vc->vc_font.width; - rows = var->yres / vc->vc_font.height; + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= vc->vc_font.width; + rows /= vc->vc_font.height; vc_resize(vc, cols, rows); + if (CON_IS_VISIBLE(vc)) { update_screen(vc); if (softback_buf) @@ -1244,15 +1272,16 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, static __inline__ void ywrap_up(struct vc_data *vc, int count) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; p->yscroll += count; if (p->yscroll >= p->vrows) /* Deal with wrap */ p->yscroll -= p->vrows; - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode |= FB_VMODE_YWRAP; - update_var(vc->vc_num, info); + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode |= FB_VMODE_YWRAP; + ops->update_start(info); scrollback_max += count; if (scrollback_max > scrollback_phys_max) scrollback_max = scrollback_phys_max; @@ -1262,15 +1291,16 @@ static __inline__ void ywrap_up(struct vc_data *vc, int count) static __inline__ void ywrap_down(struct vc_data *vc, int count) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; p->yscroll -= count; if (p->yscroll < 0) /* Deal with wrap */ p->yscroll += p->vrows; - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode |= FB_VMODE_YWRAP; - update_var(vc->vc_num, info); + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode |= FB_VMODE_YWRAP; + ops->update_start(info); scrollback_max -= count; if (scrollback_max < 0) scrollback_max = 0; @@ -1289,10 +1319,11 @@ static __inline__ void ypan_up(struct vc_data *vc, int count) 0, 0, 0, vc->vc_rows, vc->vc_cols); p->yscroll -= p->vrows - vc->vc_rows; } - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode &= ~FB_VMODE_YWRAP; - update_var(vc->vc_num, info); + + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode &= ~FB_VMODE_YWRAP; + ops->update_start(info); fbcon_clear_margins(vc, 1); scrollback_max += count; if (scrollback_max > scrollback_phys_max) @@ -1303,6 +1334,7 @@ static __inline__ void ypan_up(struct vc_data *vc, int count) static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; int redraw = 0; @@ -1312,12 +1344,13 @@ static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count) redraw = 1; } - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode &= ~FB_VMODE_YWRAP; if (redraw) fbcon_redraw_move(vc, p, t + count, vc->vc_rows - count, t); - update_var(vc->vc_num, info); + + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode &= ~FB_VMODE_YWRAP; + ops->update_start(info); fbcon_clear_margins(vc, 1); scrollback_max += count; if (scrollback_max > scrollback_phys_max) @@ -1337,10 +1370,11 @@ static __inline__ void ypan_down(struct vc_data *vc, int count) 0, vc->vc_rows, vc->vc_cols); p->yscroll += p->vrows - vc->vc_rows; } - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode &= ~FB_VMODE_YWRAP; - update_var(vc->vc_num, info); + + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode &= ~FB_VMODE_YWRAP; + ops->update_start(info); fbcon_clear_margins(vc, 1); scrollback_max -= count; if (scrollback_max < 0) @@ -1351,6 +1385,7 @@ static __inline__ void ypan_down(struct vc_data *vc, int count) static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; int redraw = 0; @@ -1359,12 +1394,14 @@ static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count) p->yscroll += p->vrows - vc->vc_rows; redraw = 1; } - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode &= ~FB_VMODE_YWRAP; + if (redraw) fbcon_redraw_move(vc, p, t, vc->vc_rows - count, t + count); - update_var(vc->vc_num, info); + + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode &= ~FB_VMODE_YWRAP; + ops->update_start(info); fbcon_clear_margins(vc, 1); scrollback_max -= count; if (scrollback_max < 0) @@ -1838,31 +1875,41 @@ static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int s height, width); } -static __inline__ void updatescrollmode(struct display *p, struct fb_info *info, +static __inline__ void updatescrollmode(struct display *p, + struct fb_info *info, struct vc_data *vc) { + struct fbcon_ops *ops = info->fbcon_par; int fh = vc->vc_font.height; int cap = info->flags; - int good_pan = (cap & FBINFO_HWACCEL_YPAN) - && divides(info->fix.ypanstep, vc->vc_font.height) - && info->var.yres_virtual > info->var.yres; - int good_wrap = (cap & FBINFO_HWACCEL_YWRAP) - && divides(info->fix.ywrapstep, vc->vc_font.height) - && divides(vc->vc_font.height, info->var.yres_virtual); + u16 t = 0; + int ypan = FBCON_SWAP(ops->rotate, info->fix.ypanstep, + info->fix.xpanstep); + int ywrap = FBCON_SWAP(ops->rotate, info->fix.ywrapstep, t); + int yres = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + int vyres = FBCON_SWAP(ops->rotate, info->var.yres_virtual, + info->var.xres_virtual); + int good_pan = (cap & FBINFO_HWACCEL_YPAN) && + divides(ypan, vc->vc_font.height) && vyres > yres; + int good_wrap = (cap & FBINFO_HWACCEL_YWRAP) && + divides(ywrap, vc->vc_font.height) && + divides(vc->vc_font.height, vyres); int reading_fast = cap & FBINFO_READS_FAST; - int fast_copyarea = (cap & FBINFO_HWACCEL_COPYAREA) && !(cap & FBINFO_HWACCEL_DISABLED); - int fast_imageblit = (cap & FBINFO_HWACCEL_IMAGEBLIT) && !(cap & FBINFO_HWACCEL_DISABLED); - - p->vrows = info->var.yres_virtual/fh; - if (info->var.yres > (fh * (vc->vc_rows + 1))) - p->vrows -= (info->var.yres - (fh * vc->vc_rows)) / fh; - if ((info->var.yres % fh) && (info->var.yres_virtual % fh < - info->var.yres % fh)) + int fast_copyarea = (cap & FBINFO_HWACCEL_COPYAREA) && + !(cap & FBINFO_HWACCEL_DISABLED); + int fast_imageblit = (cap & FBINFO_HWACCEL_IMAGEBLIT) && + !(cap & FBINFO_HWACCEL_DISABLED); + + p->vrows = vyres/fh; + if (yres > (fh * (vc->vc_rows + 1))) + p->vrows -= (yres - (fh * vc->vc_rows)) / fh; + if ((yres % fh) && (vyres % fh < yres % fh)) p->vrows--; if (good_wrap || good_pan) { if (reading_fast || fast_copyarea) - p->scrollmode = good_wrap ? SCROLL_WRAP_MOVE : SCROLL_PAN_MOVE; + p->scrollmode = good_wrap ? + SCROLL_WRAP_MOVE : SCROLL_PAN_MOVE; else p->scrollmode = good_wrap ? SCROLL_REDRAW : SCROLL_PAN_REDRAW; @@ -1878,17 +1925,23 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, unsigned int height) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; struct fb_var_screeninfo var = info->var; - int x_diff, y_diff; - int fw = vc->vc_font.width; - int fh = vc->vc_font.height; - - var.xres = width * fw; - var.yres = height * fh; + int x_diff, y_diff, virt_w, virt_h, virt_fw, virt_fh; + + virt_w = FBCON_SWAP(ops->rotate, width, height); + virt_h = FBCON_SWAP(ops->rotate, height, width); + virt_fw = FBCON_SWAP(ops->rotate, vc->vc_font.width, + vc->vc_font.height); + virt_fh = FBCON_SWAP(ops->rotate, vc->vc_font.height, + vc->vc_font.width); + var.xres = virt_w * virt_fw; + var.yres = virt_h * virt_fh; x_diff = info->var.xres - var.xres; y_diff = info->var.yres - var.yres; - if (x_diff < 0 || x_diff > fw || (y_diff < 0 || y_diff > fh)) { + if (x_diff < 0 || x_diff > virt_fw || + y_diff < 0 || y_diff > virt_fh) { struct fb_videomode *mode; DPRINTK("attempting resize %ix%i\n", var.xres, var.yres); @@ -1898,7 +1951,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, display_to_var(&var, p); fb_videomode_to_var(&var, mode); - if (width > var.xres/fw || height > var.yres/fh) + if (virt_w > var.xres/virt_fw || virt_h > var.yres/virt_fh) return -EINVAL; DPRINTK("resize now %ix%i\n", var.xres, var.yres); @@ -1908,6 +1961,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, fb_set_var(info, &var); } var_to_display(p, &info->var, info); + ops->var = info->var; } updatescrollmode(p, info, vc); return 0; @@ -1916,11 +1970,13 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, static int fbcon_switch(struct vc_data *vc) { struct fb_info *info, *old_info = NULL; + struct fbcon_ops *ops; struct display *p = &fb_display[vc->vc_num]; struct fb_var_screeninfo var; int i, prev_console; info = registered_fb[con2fb_map[vc->vc_num]]; + ops = info->fbcon_par; if (softback_top) { if (softback_lines) @@ -1939,7 +1995,7 @@ static int fbcon_switch(struct vc_data *vc) logo_shown = FBCON_LOGO_CANSHOW; } - prev_console = ((struct fbcon_ops *)info->fbcon_par)->currcon; + prev_console = ops->currcon; if (prev_console != -1) old_info = registered_fb[con2fb_map[prev_console]]; /* @@ -1952,9 +2008,9 @@ static int fbcon_switch(struct vc_data *vc) */ for (i = 0; i < FB_MAX; i++) { if (registered_fb[i] != NULL && registered_fb[i]->fbcon_par) { - struct fbcon_ops *ops = registered_fb[i]->fbcon_par; + struct fbcon_ops *o = registered_fb[i]->fbcon_par; - ops->currcon = vc->vc_num; + o->currcon = vc->vc_num; } } memset(&var, 0, sizeof(struct fb_var_screeninfo)); @@ -1966,8 +2022,11 @@ static int fbcon_switch(struct vc_data *vc) * in fb_set_var() */ info->var.activate = var.activate; - info->var.yoffset = info->var.xoffset = p->yscroll = 0; + var.yoffset = info->var.yoffset; + var.xoffset = info->var.xoffset; + var.vmode = info->var.vmode; fb_set_var(info, &var); + ops->var = info->var; if (old_info != NULL && old_info != info) { if (info->fbops->fb_set_par) @@ -1977,7 +2036,12 @@ static int fbcon_switch(struct vc_data *vc) } set_blitting_type(vc, info, p); - ((struct fbcon_ops *)info->fbcon_par)->cursor_reset = 1; + ops->cursor_reset = 1; + + if (ops->rotate_font && ops->rotate_font(info, vc, p)) { + ops->rotate = FB_ROTATE_UR; + set_blitting_type(vc, info, p); + } vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; @@ -1997,10 +2061,11 @@ static int fbcon_switch(struct vc_data *vc) scrollback_phys_max = 0; break; } + scrollback_max = 0; scrollback_current = 0; - - update_var(vc->vc_num, info); + ops->var.xoffset = ops->var.yoffset = p->yscroll = 0; + ops->update_start(info); fbcon_set_palette(vc, color_table); fbcon_clear_margins(vc, 0); @@ -2047,6 +2112,7 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; fb_set_var(info, &var); ops->graphics = 0; + ops->var = info->var; } } @@ -2135,6 +2201,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, const u8 * data, int userfont) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; int resize; int cnt; @@ -2214,9 +2281,13 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, } if (resize) { - /* reset wrap/pan */ - info->var.xoffset = info->var.yoffset = p->yscroll = 0; - vc_resize(vc, info->var.xres / w, info->var.yres / h); + int cols, rows; + + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= w; + rows /= h; + vc_resize(vc, cols, rows); if (CON_IS_VISIBLE(vc) && softback_buf) fbcon_update_softback(vc); } else if (CON_IS_VISIBLE(vc) @@ -2444,6 +2515,7 @@ static void fbcon_invert_region(struct vc_data *vc, u16 * p, int cnt) static int fbcon_scrolldelta(struct vc_data *vc, int lines) { struct fb_info *info = registered_fb[con2fb_map[fg_console]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[fg_console]; int offset, limit, scrollback_old; @@ -2520,9 +2592,11 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines) offset += limit; else if (offset >= limit) offset -= limit; - info->var.xoffset = 0; - info->var.yoffset = offset * vc->vc_font.height; - update_var(vc->vc_num, info); + + ops->var.xoffset = 0; + ops->var.yoffset = offset * vc->vc_font.height; + ops->update_start(info); + if (!scrollback_current) fbcon_cursor(vc, CM_DRAW); return 0; @@ -2570,22 +2644,25 @@ static void fbcon_modechanged(struct fb_info *info) if (!ops || ops->currcon < 0) return; vc = vc_cons[ops->currcon].d; - if (vc->vc_mode != KD_TEXT || registered_fb[con2fb_map[ops->currcon]] != info) + if (vc->vc_mode != KD_TEXT || + registered_fb[con2fb_map[ops->currcon]] != info) return; p = &fb_display[vc->vc_num]; - - info->var.xoffset = info->var.yoffset = p->yscroll = 0; + set_blitting_type(vc, info, p); if (CON_IS_VISIBLE(vc)) { var_to_display(p, &info->var, info); - cols = info->var.xres / vc->vc_font.width; - rows = info->var.yres / vc->vc_font.height; + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= vc->vc_font.width; + rows /= vc->vc_font.height; vc_resize(vc, cols, rows); updatescrollmode(p, info, vc); scrollback_max = 0; scrollback_current = 0; - update_var(vc->vc_num, info); + ops->var.xoffset = ops->var.yoffset = p->yscroll = 0; + ops->update_start(info); fbcon_set_palette(vc, color_table); update_screen(vc); if (softback_buf) @@ -2610,18 +2687,20 @@ static void fbcon_set_all_vcs(struct fb_info *info) continue; p = &fb_display[vc->vc_num]; - - info->var.xoffset = info->var.yoffset = p->yscroll = 0; + set_blitting_type(vc, info, p); var_to_display(p, &info->var, info); - cols = info->var.xres / vc->vc_font.width; - rows = info->var.yres / vc->vc_font.height; + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= vc->vc_font.width; + rows /= vc->vc_font.height; vc_resize(vc, cols, rows); if (CON_IS_VISIBLE(vc)) { updatescrollmode(p, info, vc); scrollback_max = 0; scrollback_current = 0; - update_var(vc->vc_num, info); + ops->var.xoffset = ops->var.yoffset = p->yscroll = 0; + ops->update_start(info); fbcon_set_palette(vc, color_table); update_screen(vc); if (softback_buf) diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h index b68e0e2c2d1..846a5a4e736 100644 --- a/drivers/video/console/fbcon.h +++ b/drivers/video/console/fbcon.h @@ -27,15 +27,15 @@ */ struct display { - /* Filled in by the frame buffer device */ - u_short inverse; /* != 0 text black on white as default */ /* Filled in by the low-level console driver */ const u_char *fontdata; int userfont; /* != 0 if fontdata kmalloc()ed */ u_short scrollmode; /* Scroll Method */ + u_short inverse; /* != 0 text black on white as default */ short yscroll; /* Hardware scrolling */ int vrows; /* number of virtual rows */ int cursor_shape; + int con_rotate; u32 xres_virtual; u32 yres_virtual; u32 height; @@ -52,6 +52,8 @@ struct display { struct fb_videomode *mode; }; +extern struct display fb_display[]; + struct fbcon_ops { void (*bmove)(struct vc_data *vc, struct fb_info *info, int sy, int sx, int dy, int dx, int height, int width); @@ -63,8 +65,12 @@ struct fbcon_ops { void (*clear_margins)(struct vc_data *vc, struct fb_info *info, int bottom_only); void (*cursor)(struct vc_data *vc, struct fb_info *info, - struct display *p, int mode, int softback_lines, int fg, int bg); - + struct display *p, int mode, int softback_lines, + int fg, int bg); + int (*update_start)(struct fb_info *info); + int (*rotate_font)(struct fb_info *info, struct vc_data *vc, + struct display *p); + struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */ struct timer_list cursor_timer; /* Cursor timer */ struct fb_cursor cursor_state; int currcon; /* Current VC. */ @@ -73,7 +79,12 @@ struct fbcon_ops { int blank_state; int graphics; int flags; + int rotate; + int cur_rotate; char *cursor_data; + u8 *fontbuffer; + u8 *fontdata; + u32 fd_size; }; /* * Attribute Decoding @@ -168,4 +179,43 @@ extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info, #endif extern void fbcon_set_bitops(struct fbcon_ops *ops); extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor); + +#define FBCON_ATTRIBUTE_UNDERLINE 1 +#define FBCON_ATTRIBUTE_REVERSE 2 +#define FBCON_ATTRIBUTE_BOLD 4 + +static inline int real_y(struct display *p, int ypos) +{ + int rows = p->vrows; + + ypos += p->yscroll; + return ypos < rows ? ypos : ypos - rows; +} + + +static inline int get_attribute(struct fb_info *info, u16 c) +{ + int attribute = 0; + + if (fb_get_color_depth(&info->var, &info->fix) == 1) { + if (attr_underline(c)) + attribute |= FBCON_ATTRIBUTE_UNDERLINE; + if (attr_reverse(c)) + attribute |= FBCON_ATTRIBUTE_REVERSE; + if (attr_bold(c)) + attribute |= FBCON_ATTRIBUTE_BOLD; + } + + return attribute; +} + +#define FBCON_SWAP(i,r,v) ({ \ + typeof(r) _r = (r); \ + typeof(v) _v = (v); \ + (void) (&_r == &_v); \ + (i == FB_ROTATE_UR || i == FB_ROTATE_UD) ? _r : _v; }) + +#define fbcon_set_rotate(x) do {} while(0) + #endif /* _VIDEO_FBCON_H */ + diff --git a/drivers/video/console/tileblit.c b/drivers/video/console/tileblit.c index 7f76e2c6a4a..cb25324a563 100644 --- a/drivers/video/console/tileblit.c +++ b/drivers/video/console/tileblit.c @@ -118,6 +118,18 @@ static void tile_cursor(struct vc_data *vc, struct fb_info *info, info->tileops->fb_tilecursor(info, &cursor); } +static int tile_update_start(struct fb_info *info) +{ + struct fbcon_ops *ops = info->fbcon_par; + int err; + + err = fb_pan_display(info, &ops->var); + ops->var.xoffset = info->var.xoffset; + ops->var.yoffset = info->var.yoffset; + ops->var.vmode = info->var.vmode; + return err; +} + void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info, struct display *p, struct fbcon_ops *ops) { @@ -128,6 +140,7 @@ void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info, ops->putcs = tile_putcs; ops->clear_margins = tile_clear_margins; ops->cursor = tile_cursor; + ops->update_start = tile_update_start; if (p) { map.width = vc->vc_font.width; diff --git a/include/linux/fb.h b/include/linux/fb.h index e7ff98e395f..51791dc5d4d 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -201,6 +201,14 @@ struct fb_bitfield { #define FB_VMODE_SMOOTH_XPAN 512 /* smooth xpan possible (internally used) */ #define FB_VMODE_CONUPDATE 512 /* don't update x/yoffset */ +/* + * Display rotation support + */ +#define FB_ROTATE_UR 0 +#define FB_ROTATE_CW 1 +#define FB_ROTATE_UD 2 +#define FB_ROTATE_CCW 3 + #define PICOS2KHZ(a) (1000000000UL/(a)) #define KHZ2PICOS(a) (1000000000UL/(a)) @@ -489,9 +497,9 @@ struct fb_cursor_user { #define FB_EVENT_MODE_DELETE 0x04 /* A driver registered itself */ #define FB_EVENT_FB_REGISTERED 0x05 -/* get console to framebuffer mapping */ +/* CONSOLE-SPECIFIC: get console to framebuffer mapping */ #define FB_EVENT_GET_CONSOLE_MAP 0x06 -/* set console to framebuffer mapping */ +/* CONSOLE-SPECIFIC: set console to framebuffer mapping */ #define FB_EVENT_SET_CONSOLE_MAP 0x07 /* A display blank is requested */ #define FB_EVENT_BLANK 0x08 -- cgit v1.2.3 From 9c44e5f6c211a9b7313ded897f3135ef7d9ad3e2 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Tue, 8 Nov 2005 21:39:10 -0800 Subject: [PATCH] fbcon: Console Rotation - Add support to rotate the logo Add support for rotating and positioning of the logo. Rotation and position depends on 'int rotate' parameter added to fb_prepare_logo() and fb_show_logo(). Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/fbcon.c | 5 +- drivers/video/fbmem.c | 130 +++++++++++++++++++++++++++++++++++++----- include/linux/fb.h | 4 +- 3 files changed, 122 insertions(+), 17 deletions(-) diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index b5d678c7325..26935e231a1 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -499,6 +499,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, int cols, int rows, int new_cols, int new_rows) { /* Need to make room for the logo */ + struct fbcon_ops *ops = info->fbcon_par; int cnt, erase = vc->vc_video_erase_char, step; unsigned short *save = NULL, *r, *q; @@ -508,7 +509,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, */ if (fb_get_color_depth(&info->var, &info->fix) == 1) erase &= ~0x400; - logo_height = fb_prepare_logo(info); + logo_height = fb_prepare_logo(info, ops->rotate); logo_lines = (logo_height + vc->vc_font.height - 1) / vc->vc_font.height; q = (unsigned short *) (vc->vc_origin + @@ -2073,7 +2074,7 @@ static int fbcon_switch(struct vc_data *vc) logo_shown = fg_console; /* This is protected above by initmem_freed */ - fb_show_logo(info); + fb_show_logo(info, ops->rotate); update_region(vc, vc->vc_origin + vc->vc_size_row * vc->vc_top, vc->vc_size_row * (vc->vc_bottom - diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index e2667ddab3f..7a2a8fa50b3 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -323,9 +323,103 @@ static struct logo_data { const struct linux_logo *logo; } fb_logo; -int fb_prepare_logo(struct fb_info *info) +static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height) +{ + u32 size = width * height, i; + + out += size - 1; + + for (i = size; i--; ) + *out-- = *in++; +} + +static void fb_rotate_logo_cw(const u8 *in, u8 *out, u32 width, u32 height) +{ + int i, j, w = width - 1; + + for (i = 0; i < height; i++) + for (j = 0; j < width; j++) + out[height * j + w - i] = *in++; +} + +static void fb_rotate_logo_ccw(const u8 *in, u8 *out, u32 width, u32 height) +{ + int i, j, w = width - 1; + + for (i = 0; i < height; i++) + for (j = 0; j < width; j++) + out[height * (w - j) + i] = *in++; +} + +static void fb_rotate_logo(struct fb_info *info, u8 *dst, + struct fb_image *image, int rotate) +{ + u32 tmp; + + if (rotate == FB_ROTATE_UD) { + image->dx = info->var.xres - image->width; + image->dy = info->var.yres - image->height; + fb_rotate_logo_ud(image->data, dst, image->width, + image->height); + } else if (rotate == FB_ROTATE_CW) { + tmp = image->width; + image->width = image->height; + image->height = tmp; + image->dx = info->var.xres - image->height; + fb_rotate_logo_cw(image->data, dst, image->width, + image->height); + } else if (rotate == FB_ROTATE_CCW) { + tmp = image->width; + image->width = image->height; + image->height = tmp; + image->dy = info->var.yres - image->width; + fb_rotate_logo_ccw(image->data, dst, image->width, + image->height); + } + + image->data = dst; +} + +static void fb_do_show_logo(struct fb_info *info, struct fb_image *image, + int rotate) +{ + int x; + + if (rotate == FB_ROTATE_UR) { + for (x = 0; x < num_online_cpus() && + x * (fb_logo.logo->width + 8) <= + info->var.xres - fb_logo.logo->width; x++) { + info->fbops->fb_imageblit(info, image); + image->dx += fb_logo.logo->width + 8; + } + } else if (rotate == FB_ROTATE_UD) { + for (x = 0; x < num_online_cpus() && + x * (fb_logo.logo->width + 8) <= + info->var.xres - fb_logo.logo->width; x++) { + info->fbops->fb_imageblit(info, image); + image->dx -= fb_logo.logo->width + 8; + } + } else if (rotate == FB_ROTATE_CW) { + for (x = 0; x < num_online_cpus() && + x * (fb_logo.logo->width + 8) <= + info->var.yres - fb_logo.logo->width; x++) { + info->fbops->fb_imageblit(info, image); + image->dy += fb_logo.logo->width + 8; + } + } else if (rotate == FB_ROTATE_CCW) { + for (x = 0; x < num_online_cpus() && + x * (fb_logo.logo->width + 8) <= + info->var.yres - fb_logo.logo->width; x++) { + info->fbops->fb_imageblit(info, image); + image->dy -= fb_logo.logo->width + 8; + } + } +} + +int fb_prepare_logo(struct fb_info *info, int rotate) { int depth = fb_get_color_depth(&info->var, &info->fix); + int yres; memset(&fb_logo, 0, sizeof(struct logo_data)); @@ -358,10 +452,16 @@ int fb_prepare_logo(struct fb_info *info) /* Return if no suitable logo was found */ fb_logo.logo = fb_find_logo(depth); - if (!fb_logo.logo || fb_logo.logo->height > info->var.yres) { + if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD) + yres = info->var.yres; + else + yres = info->var.xres; + + if (fb_logo.logo && fb_logo.logo->height > yres) { fb_logo.logo = NULL; return 0; } + /* What depth we asked for might be different from what we get */ if (fb_logo.logo->type == LINUX_LOGO_CLUT224) fb_logo.depth = 8; @@ -372,12 +472,11 @@ int fb_prepare_logo(struct fb_info *info) return fb_logo.logo->height; } -int fb_show_logo(struct fb_info *info) +int fb_show_logo(struct fb_info *info, int rotate) { u32 *palette = NULL, *saved_pseudo_palette = NULL; - unsigned char *logo_new = NULL; + unsigned char *logo_new = NULL, *logo_rotate = NULL; struct fb_image image; - int x; /* Return if the frame buffer is not mapped or suspended */ if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING) @@ -417,25 +516,30 @@ int fb_show_logo(struct fb_info *info) fb_set_logo(info, fb_logo.logo, logo_new, fb_logo.depth); } + image.dx = 0; + image.dy = 0; image.width = fb_logo.logo->width; image.height = fb_logo.logo->height; - image.dy = 0; - for (x = 0; x < num_online_cpus() * (fb_logo.logo->width + 8) && - x <= info->var.xres-fb_logo.logo->width; x += (fb_logo.logo->width + 8)) { - image.dx = x; - info->fbops->fb_imageblit(info, &image); + if (rotate) { + logo_rotate = kmalloc(fb_logo.logo->width * + fb_logo.logo->height, GFP_KERNEL); + if (logo_rotate) + fb_rotate_logo(info, logo_rotate, &image, rotate); } - + + fb_do_show_logo(info, &image, rotate); + kfree(palette); if (saved_pseudo_palette != NULL) info->pseudo_palette = saved_pseudo_palette; kfree(logo_new); + kfree(logo_rotate); return fb_logo.logo->height; } #else -int fb_prepare_logo(struct fb_info *info) { return 0; } -int fb_show_logo(struct fb_info *info) { return 0; } +int fb_prepare_logo(struct fb_info *info, int rotate) { return 0; } +int fb_show_logo(struct fb_info *info, int rotate) { return 0; } #endif /* CONFIG_LOGO */ static int fbmem_read_proc(char *buf, char **start, off_t offset, diff --git a/include/linux/fb.h b/include/linux/fb.h index 51791dc5d4d..357dd3a0a01 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -825,8 +825,8 @@ extern void cfb_imageblit(struct fb_info *info, const struct fb_image *image); /* drivers/video/fbmem.c */ extern int register_framebuffer(struct fb_info *fb_info); extern int unregister_framebuffer(struct fb_info *fb_info); -extern int fb_prepare_logo(struct fb_info *fb_info); -extern int fb_show_logo(struct fb_info *fb_info); +extern int fb_prepare_logo(struct fb_info *fb_info, int rotate); +extern int fb_show_logo(struct fb_info *fb_info, int rotate); extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size); extern void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, u32 height, u32 shift_high, u32 shift_low, u32 mod); -- cgit v1.2.3 From 6cc50e1c5b57180fd37a31282000f43859b0fe73 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Tue, 8 Nov 2005 21:39:11 -0800 Subject: [PATCH] fbcon: Console Rotation - Add support to rotate font bitmap Add support to rotate the font bitmap. To save on processing time, the entire fontdata will be rotated on a console switch, then stored in a buffer private to fbcon. To further save on processing, the fontdata will only be rotated if the font has changed or if the angle of rotation has changed. Only a single copy of the rotated fontdata will be kept. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/Makefile | 3 + drivers/video/console/fbcon.h | 4 ++ drivers/video/console/fbcon_rotate.c | 105 +++++++++++++++++++++++++++++++++++ drivers/video/console/fbcon_rotate.h | 102 ++++++++++++++++++++++++++++++++++ 4 files changed, 214 insertions(+) create mode 100644 drivers/video/console/fbcon_rotate.c create mode 100644 drivers/video/console/fbcon_rotate.h diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile index 5222628accc..4532bdfa94f 100644 --- a/drivers/video/console/Makefile +++ b/drivers/video/console/Makefile @@ -31,6 +31,9 @@ obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o bitblit.o font.o softcursor.o ifeq ($(CONFIG_FB_TILEBLITTING),y) obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += tileblit.o endif +ifeq ($(CONFIG_FRAMEBUFFER_CONSOLE_ROTATION),y) +obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon_rotate.o +endif obj-$(CONFIG_FB_STI) += sticore.o font.o diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h index 846a5a4e736..accfd7bd8e9 100644 --- a/drivers/video/console/fbcon.h +++ b/drivers/video/console/fbcon.h @@ -215,7 +215,11 @@ static inline int get_attribute(struct fb_info *info, u16 c) (void) (&_r == &_v); \ (i == FB_ROTATE_UR || i == FB_ROTATE_UD) ? _r : _v; }) +#ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION +extern void fbcon_set_rotate(struct fbcon_ops *ops); +#else #define fbcon_set_rotate(x) do {} while(0) +#endif /* CONFIG_FRAMEBUFFER_CONSOLE_ROTATION */ #endif /* _VIDEO_FBCON_H */ diff --git a/drivers/video/console/fbcon_rotate.c b/drivers/video/console/fbcon_rotate.c new file mode 100644 index 00000000000..6a969318480 --- /dev/null +++ b/drivers/video/console/fbcon_rotate.c @@ -0,0 +1,105 @@ +/* + * linux/drivers/video/console/fbcon_rotate.c -- Software Rotation + * + * Copyright (C) 2005 Antonino Daplas + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "fbcon.h" +#include "fbcon_rotate.h" + +static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc, + struct display *p) +{ + struct fbcon_ops *ops = info->fbcon_par; + int len, err = 0; + int s_cellsize, d_cellsize, i; + const u8 *src; + u8 *dst; + + if (vc->vc_font.data == ops->fontdata && + p->con_rotate == ops->cur_rotate) + goto finished; + + src = ops->fontdata = vc->vc_font.data; + ops->cur_rotate = p->con_rotate; + len = (!p->userfont) ? 256 : FNTCHARCNT(src); + s_cellsize = ((vc->vc_font.width + 7)/8) * + vc->vc_font.height; + d_cellsize = s_cellsize; + + if (ops->rotate == FB_ROTATE_CW || + ops->rotate == FB_ROTATE_CCW) + d_cellsize = ((vc->vc_font.height + 7)/8) * + vc->vc_font.width; + + if (info->fbops->fb_sync) + info->fbops->fb_sync(info); + + if (ops->fd_size < d_cellsize * len) { + dst = kmalloc(d_cellsize * len, GFP_KERNEL); + + if (dst == NULL) { + err = -ENOMEM; + goto finished; + } + + ops->fd_size = d_cellsize * len; + kfree(ops->fontbuffer); + ops->fontbuffer = dst; + } + + dst = ops->fontbuffer; + memset(dst, 0, ops->fd_size); + + switch (ops->rotate) { + case FB_ROTATE_UD: + for (i = len; i--; ) { + rotate_ud(src, dst, vc->vc_font.width, + vc->vc_font.height); + + src += s_cellsize; + dst += d_cellsize; + } + break; + case FB_ROTATE_CW: + for (i = len; i--; ) { + rotate_cw(src, dst, vc->vc_font.width, + vc->vc_font.height); + src += s_cellsize; + dst += d_cellsize; + } + break; + case FB_ROTATE_CCW: + for (i = len; i--; ) { + rotate_ccw(src, dst, vc->vc_font.width, + vc->vc_font.height); + src += s_cellsize; + dst += d_cellsize; + } + break; + } + +finished: + return err; +} + +void fbcon_set_rotate(struct fbcon_ops *ops) +{ + ops->rotate_font = fbcon_rotate_font; +} +EXPORT_SYMBOL(fbcon_set_rotate); + +MODULE_AUTHOR("Antonino Daplas "); +MODULE_DESCRIPTION("Console Rotation Support"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/console/fbcon_rotate.h b/drivers/video/console/fbcon_rotate.h new file mode 100644 index 00000000000..6cc27d8e5d4 --- /dev/null +++ b/drivers/video/console/fbcon_rotate.h @@ -0,0 +1,102 @@ +/* + * linux/drivers/video/console/fbcon_rotate.h -- Software Display Rotation + * + * Copyright (C) 2005 Antonino Daplas + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#ifndef _FBCON_ROTATE_H +#define _FBCON_ROTATE_H + +#define FNTCHARCNT(fd) (((int *)(fd))[-3]) + +#define GETVYRES(s,i) ({ \ + (s == SCROLL_REDRAW || s == SCROLL_MOVE) ? \ + (i)->var.yres : (i)->var.yres_virtual; }) + +#define GETVXRES(s,i) ({ \ + (s == SCROLL_REDRAW || s == SCROLL_MOVE || !(i)->fix.xpanstep) ? \ + (i)->var.xres : (i)->var.xres_virtual; }) + +/* + * The bitmap is always big endian + */ +#if defined(__LITTLE_ENDIAN) +#define FBCON_BIT(b) (7 - (b)) +#else +#define FBCON_BIT(b) (b) +#endif + +static inline int pattern_test_bit(u32 x, u32 y, u32 pitch, const char *pat) +{ + u32 tmp = (y * pitch) + x, index = tmp / 8, bit = tmp % 8; + + pat +=index; + return (test_bit(FBCON_BIT(bit), (void *)pat)); +} + +static inline void pattern_set_bit(u32 x, u32 y, u32 pitch, char *pat) +{ + u32 tmp = (y * pitch) + x, index = tmp / 8, bit = tmp % 8; + + pat += index; + set_bit(FBCON_BIT(bit), (void *)pat); +} + +static inline void rotate_ud(const char *in, char *out, u32 width, u32 height) +{ + int i, j; + int shift = width % 8; + + width = (width + 7) & ~7; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) { + if (pattern_test_bit(j, i, width, in)) + pattern_set_bit(width - (1 + j + shift), + height - (1 + i), + width, out); + } + + } +} + +static inline void rotate_cw(const char *in, char *out, u32 width, u32 height) +{ + int i, j, h = height, w = width; + int shift = (8 - (height % 8)) & 7; + + width = (width + 7) & ~7; + height = (height + 7) & ~7; + + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + if (pattern_test_bit(j, i, width, in)) + pattern_set_bit(height - 1 - i - shift, j, + height, out); + + } + } +} + +static inline void rotate_ccw(const char *in, char *out, u32 width, u32 height) +{ + int i, j, h = height, w = width; + int shift = width % 8; + + width = (width + 7) & ~7; + height = (height + 7) & ~7; + + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + if (pattern_test_bit(j, i, width, in)) + pattern_set_bit(i, width - 1 - j - shift, + height, out); + } + } +} + +#endif -- cgit v1.2.3 From dbcbfe1ea41e404d960a06fa2faf7da568909f33 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Tue, 8 Nov 2005 21:39:12 -0800 Subject: [PATCH] fbcon: Console Rotation - Add support for 90-degree console rotation Add support for 90-degree (clockwise) rotation of the console. To activate, boot with: fbcon=rotate:1 Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/Makefile | 2 +- drivers/video/console/fbcon.c | 13 ++ drivers/video/console/fbcon_cw.c | 412 +++++++++++++++++++++++++++++++++++ drivers/video/console/fbcon_rotate.c | 6 + drivers/video/console/fbcon_rotate.h | 1 + 5 files changed, 433 insertions(+), 1 deletion(-) create mode 100644 drivers/video/console/fbcon_cw.c diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile index 4532bdfa94f..984f8cd3cc6 100644 --- a/drivers/video/console/Makefile +++ b/drivers/video/console/Makefile @@ -32,7 +32,7 @@ ifeq ($(CONFIG_FB_TILEBLITTING),y) obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += tileblit.o endif ifeq ($(CONFIG_FRAMEBUFFER_CONSOLE_ROTATION),y) -obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon_rotate.o +obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon_rotate.o fbcon_cw.o endif obj-$(CONFIG_FB_STI) += sticore.o font.o diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 26935e231a1..e829ba18e0a 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -207,12 +207,25 @@ static irqreturn_t fb_vbl_detect(int irq, void *dummy, struct pt_regs *fp) } #endif +#ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION +static inline void fbcon_set_rotation(struct fb_info *info, struct display *p) +{ + struct fbcon_ops *ops = info->fbcon_par; + + if (!(info->flags & FBINFO_MISC_TILEBLITTING) && + p->con_rotate < 4) + ops->rotate = p->con_rotate; + else + ops->rotate = 0; +} +#else static inline void fbcon_set_rotation(struct fb_info *info, struct display *p) { struct fbcon_ops *ops = info->fbcon_par; ops->rotate = FB_ROTATE_UR; } +#endif /* CONFIG_FRAMEBUFFER_CONSOLE_ROTATION */ static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info) { diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c new file mode 100644 index 00000000000..6c6f3b6dd17 --- /dev/null +++ b/drivers/video/console/fbcon_cw.c @@ -0,0 +1,412 @@ +/* + * linux/drivers/video/console/fbcon_ud.c -- Software Rotation - 90 degrees + * + * Copyright (C) 2005 Antonino Daplas + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "fbcon.h" +#include "fbcon_rotate.h" + +/* + * Rotation 90 degrees + */ + +static inline void cw_update_attr(u8 *dst, u8 *src, int attribute, + struct vc_data *vc) +{ + int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2; + int width = (vc->vc_font.height + 7) >> 3; + u8 c, t = 0, msk = ~(0xff >> offset); + + for (i = 0; i < vc->vc_font.width; i++) { + for (j = 0; j < width; j++) { + c = *src; + if (attribute & FBCON_ATTRIBUTE_UNDERLINE && !j) + c |= msk; + if (attribute & FBCON_ATTRIBUTE_BOLD && i) + c |= *(src-width); + if (attribute & FBCON_ATTRIBUTE_REVERSE) + c = ~c; + src++; + *dst++ = c; + t = c; + } + } +} + + +static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy, + int sx, int dy, int dx, int height, int width) +{ + struct display *p = &fb_display[vc->vc_num]; + struct fb_copyarea area; + u32 vxres = GETVXRES(p->scrollmode, info); + + area.sx = vxres - ((sy + height) * vc->vc_font.height); + area.sy = sx * vc->vc_font.width; + area.dx = vxres - ((dy + height) * vc->vc_font.height); + area.dy = dx * vc->vc_font.width; + area.width = height * vc->vc_font.height; + area.height = width * vc->vc_font.width; + + info->fbops->fb_copyarea(info, &area); +} + +static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy, + int sx, int height, int width) +{ + struct display *p = &fb_display[vc->vc_num]; + struct fb_fillrect region; + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + u32 vxres = GETVXRES(p->scrollmode, info); + + region.color = attr_bgcol_ec(bgshift,vc); + region.dx = vxres - ((sy + height) * vc->vc_font.height); + region.dy = sx * vc->vc_font.width; + region.height = width * vc->vc_font.width; + region.width = height * vc->vc_font.height; + region.rop = ROP_COPY; + + info->fbops->fb_fillrect(info, ®ion); +} + +static inline void cw_putcs_aligned(struct vc_data *vc, struct fb_info *info, + const u16 *s, u32 attr, u32 cnt, + u32 d_pitch, u32 s_pitch, u32 cellsize, + struct fb_image *image, u8 *buf, u8 *dst) +{ + struct fbcon_ops *ops = info->fbcon_par; + u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; + u32 idx = (vc->vc_font.height + 7) >> 3; + u8 *src; + + while (cnt--) { + src = ops->fontbuffer + (scr_readw(s++) & charmask)*cellsize; + + if (attr) { + cw_update_attr(buf, src, attr, vc); + src = buf; + } + + if (likely(idx == 1)) + __fb_pad_aligned_buffer(dst, d_pitch, src, idx, + vc->vc_font.width); + else + fb_pad_aligned_buffer(dst, d_pitch, src, idx, + vc->vc_font.width); + + dst += d_pitch * vc->vc_font.width; + } + + info->fbops->fb_imageblit(info, image); +} + +static void cw_putcs(struct vc_data *vc, struct fb_info *info, + const unsigned short *s, int count, int yy, int xx, + int fg, int bg) +{ + struct fb_image image; + struct display *p = &fb_display[vc->vc_num]; + struct fbcon_ops *ops = info->fbcon_par; + u32 width = (vc->vc_font.height + 7)/8; + u32 cellsize = width * vc->vc_font.width; + u32 maxcnt = info->pixmap.size/cellsize; + u32 scan_align = info->pixmap.scan_align - 1; + u32 buf_align = info->pixmap.buf_align - 1; + u32 cnt, pitch, size; + u32 attribute = get_attribute(info, scr_readw(s)); + u8 *dst, *buf = NULL; + u32 vxres = GETVXRES(p->scrollmode, info); + + if (!ops->fontbuffer) + return; + + image.fg_color = fg; + image.bg_color = bg; + image.dx = vxres - ((yy + 1) * vc->vc_font.height); + image.dy = xx * vc->vc_font.width; + image.width = vc->vc_font.height; + image.depth = 1; + + if (attribute) { + buf = kmalloc(cellsize, GFP_KERNEL); + if (!buf) + return; + } + + while (count) { + if (count > maxcnt) + cnt = maxcnt; + else + cnt = count; + + image.height = vc->vc_font.width * cnt; + pitch = ((image.width + 7) >> 3) + scan_align; + pitch &= ~scan_align; + size = pitch * image.height + buf_align; + size &= ~buf_align; + dst = fb_get_buffer_offset(info, &info->pixmap, size); + image.data = dst; + cw_putcs_aligned(vc, info, s, attribute, cnt, pitch, + width, cellsize, &image, buf, dst); + image.dy += image.height; + count -= cnt; + s += cnt; + } + + /* buf is always NULL except when in monochrome mode, so in this case + it's a gain to check buf against NULL even though kfree() handles + NULL pointers just fine */ + if (unlikely(buf)) + kfree(buf); + +} + +static void cw_clear_margins(struct vc_data *vc, struct fb_info *info, + int bottom_only) +{ + unsigned int cw = vc->vc_font.width; + unsigned int ch = vc->vc_font.height; + unsigned int rw = info->var.yres - (vc->vc_cols*cw); + unsigned int bh = info->var.xres - (vc->vc_rows*ch); + unsigned int rs = info->var.yres - rw; + struct fb_fillrect region; + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + + region.color = attr_bgcol_ec(bgshift,vc); + region.rop = ROP_COPY; + + if (rw && !bottom_only) { + region.dx = 0; + region.dy = info->var.yoffset + rs; + region.height = rw; + region.width = info->var.xres_virtual; + info->fbops->fb_fillrect(info, ®ion); + } + + if (bh) { + region.dx = info->var.xoffset; + region.dy = info->var.yoffset; + region.height = info->var.yres; + region.width = bh; + info->fbops->fb_fillrect(info, ®ion); + } +} + +static void cw_cursor(struct vc_data *vc, struct fb_info *info, + struct display *p, int mode, int softback_lines, + int fg, int bg) +{ + struct fb_cursor cursor; + struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par; + unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; + int w = (vc->vc_font.height + 7) >> 3, c; + int y = real_y(p, vc->vc_y); + int attribute, use_sw = (vc->vc_cursor_type & 0x10); + int err = 1, dx, dy; + char *src; + u32 vxres = GETVXRES(p->scrollmode, info); + + if (!ops->fontbuffer) + return; + + cursor.set = 0; + + if (softback_lines) { + if (y + softback_lines >= vc->vc_rows) { + mode = CM_ERASE; + ops->cursor_flash = 0; + return; + } else + y += softback_lines; + } + + c = scr_readw((u16 *) vc->vc_pos); + attribute = get_attribute(info, c); + src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width)); + + if (ops->cursor_state.image.data != src || + ops->cursor_reset) { + ops->cursor_state.image.data = src; + cursor.set |= FB_CUR_SETIMAGE; + } + + if (attribute) { + u8 *dst; + + dst = kmalloc(w * vc->vc_font.width, GFP_ATOMIC); + if (!dst) + return; + kfree(ops->cursor_data); + ops->cursor_data = dst; + cw_update_attr(dst, src, attribute, vc); + src = dst; + } + + if (ops->cursor_state.image.fg_color != fg || + ops->cursor_state.image.bg_color != bg || + ops->cursor_reset) { + ops->cursor_state.image.fg_color = fg; + ops->cursor_state.image.bg_color = bg; + cursor.set |= FB_CUR_SETCMAP; + } + + if (ops->cursor_state.image.height != vc->vc_font.width || + ops->cursor_state.image.width != vc->vc_font.height || + ops->cursor_reset) { + ops->cursor_state.image.height = vc->vc_font.width; + ops->cursor_state.image.width = vc->vc_font.height; + cursor.set |= FB_CUR_SETSIZE; + } + + dx = vxres - ((y * vc->vc_font.height) + vc->vc_font.height); + dy = vc->vc_x * vc->vc_font.width; + + if (ops->cursor_state.image.dx != dx || + ops->cursor_state.image.dy != dy || + ops->cursor_reset) { + ops->cursor_state.image.dx = dx; + ops->cursor_state.image.dy = dy; + cursor.set |= FB_CUR_SETPOS; + } + + if (ops->cursor_state.hot.x || ops->cursor_state.hot.y || + ops->cursor_reset) { + ops->cursor_state.hot.x = cursor.hot.y = 0; + cursor.set |= FB_CUR_SETHOT; + } + + if (cursor.set & FB_CUR_SETSIZE || + vc->vc_cursor_type != p->cursor_shape || + ops->cursor_state.mask == NULL || + ops->cursor_reset) { + char *tmp, *mask = kmalloc(w*vc->vc_font.width, GFP_ATOMIC); + int cur_height, size, i = 0; + int width = (vc->vc_font.width + 7)/8; + + if (!mask) + return; + + tmp = kmalloc(width * vc->vc_font.height, GFP_ATOMIC); + + if (!tmp) { + kfree(mask); + return; + } + + kfree(ops->cursor_state.mask); + ops->cursor_state.mask = mask; + + p->cursor_shape = vc->vc_cursor_type; + cursor.set |= FB_CUR_SETSHAPE; + + switch (p->cursor_shape & CUR_HWMASK) { + case CUR_NONE: + cur_height = 0; + break; + case CUR_UNDERLINE: + cur_height = (vc->vc_font.height < 10) ? 1 : 2; + break; + case CUR_LOWER_THIRD: + cur_height = vc->vc_font.height/3; + break; + case CUR_LOWER_HALF: + cur_height = vc->vc_font.height >> 1; + break; + case CUR_TWO_THIRDS: + cur_height = (vc->vc_font.height << 1)/3; + break; + case CUR_BLOCK: + default: + cur_height = vc->vc_font.height; + break; + } + + size = (vc->vc_font.height - cur_height) * width; + while (size--) + tmp[i++] = 0; + size = cur_height * width; + while (size--) + tmp[i++] = 0xff; + memset(mask, 0, w * vc->vc_font.width); + rotate_cw(tmp, mask, vc->vc_font.width, vc->vc_font.height); + kfree(tmp); + } + + switch (mode) { + case CM_ERASE: + ops->cursor_state.enable = 0; + break; + case CM_DRAW: + case CM_MOVE: + default: + ops->cursor_state.enable = (use_sw) ? 0 : 1; + break; + } + + cursor.image.data = src; + cursor.image.fg_color = ops->cursor_state.image.fg_color; + cursor.image.bg_color = ops->cursor_state.image.bg_color; + cursor.image.dx = ops->cursor_state.image.dx; + cursor.image.dy = ops->cursor_state.image.dy; + cursor.image.height = ops->cursor_state.image.height; + cursor.image.width = ops->cursor_state.image.width; + cursor.hot.x = ops->cursor_state.hot.x; + cursor.hot.y = ops->cursor_state.hot.y; + cursor.mask = ops->cursor_state.mask; + cursor.enable = ops->cursor_state.enable; + cursor.image.depth = 1; + cursor.rop = ROP_XOR; + + if (info->fbops->fb_cursor) + err = info->fbops->fb_cursor(info, &cursor); + + if (err) + soft_cursor(info, &cursor); + + ops->cursor_reset = 0; +} + +int cw_update_start(struct fb_info *info) +{ + struct fbcon_ops *ops = info->fbcon_par; + struct display *p = &fb_display[ops->currcon]; + u32 vxres = GETVXRES(p->scrollmode, info); + u32 xoffset; + int err; + + xoffset = vxres - (info->var.xres + ops->var.yoffset); + ops->var.yoffset = ops->var.xoffset; + ops->var.xoffset = xoffset; + err = fb_pan_display(info, &ops->var); + ops->var.xoffset = info->var.xoffset; + ops->var.yoffset = info->var.yoffset; + ops->var.vmode = info->var.vmode; + return err; +} + +void fbcon_rotate_cw(struct fbcon_ops *ops) +{ + ops->bmove = cw_bmove; + ops->clear = cw_clear; + ops->putcs = cw_putcs; + ops->clear_margins = cw_clear_margins; + ops->cursor = cw_cursor; + ops->update_start = cw_update_start; +} +EXPORT_SYMBOL(fbcon_rotate_cw); + +MODULE_AUTHOR("Antonino Daplas "); +MODULE_DESCRIPTION("Console Rotation (90 degrees) Support"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/console/fbcon_rotate.c b/drivers/video/console/fbcon_rotate.c index 6a969318480..9df009c8ab4 100644 --- a/drivers/video/console/fbcon_rotate.c +++ b/drivers/video/console/fbcon_rotate.c @@ -97,6 +97,12 @@ finished: void fbcon_set_rotate(struct fbcon_ops *ops) { ops->rotate_font = fbcon_rotate_font; + + switch(ops->rotate) { + case FB_ROTATE_CW: + fbcon_rotate_cw(ops); + break; + } } EXPORT_SYMBOL(fbcon_set_rotate); diff --git a/drivers/video/console/fbcon_rotate.h b/drivers/video/console/fbcon_rotate.h index 6cc27d8e5d4..709e6b49eab 100644 --- a/drivers/video/console/fbcon_rotate.h +++ b/drivers/video/console/fbcon_rotate.h @@ -99,4 +99,5 @@ static inline void rotate_ccw(const char *in, char *out, u32 width, u32 height) } } +extern void fbcon_rotate_cw(struct fbcon_ops *ops); #endif -- cgit v1.2.3 From 33ee82978c4ecf7cbd56064391c9385264185de2 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Tue, 8 Nov 2005 21:39:13 -0800 Subject: [PATCH] fbcon: Console Rotation - Add support for 180-degree console rotation Add support for 180-degree (upside down) rotation of the console. To activate, boot with: fbcon=rotate:2 Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/Makefile | 2 +- drivers/video/console/fbcon_rotate.c | 3 + drivers/video/console/fbcon_rotate.h | 1 + drivers/video/console/fbcon_ud.c | 454 +++++++++++++++++++++++++++++++++++ 4 files changed, 459 insertions(+), 1 deletion(-) create mode 100644 drivers/video/console/fbcon_ud.c diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile index 984f8cd3cc6..830ff46e0d1 100644 --- a/drivers/video/console/Makefile +++ b/drivers/video/console/Makefile @@ -32,7 +32,7 @@ ifeq ($(CONFIG_FB_TILEBLITTING),y) obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += tileblit.o endif ifeq ($(CONFIG_FRAMEBUFFER_CONSOLE_ROTATION),y) -obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon_rotate.o fbcon_cw.o +obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon_rotate.o fbcon_cw.o fbcon_ud.o endif obj-$(CONFIG_FB_STI) += sticore.o font.o diff --git a/drivers/video/console/fbcon_rotate.c b/drivers/video/console/fbcon_rotate.c index 9df009c8ab4..3d64ad190ff 100644 --- a/drivers/video/console/fbcon_rotate.c +++ b/drivers/video/console/fbcon_rotate.c @@ -102,6 +102,9 @@ void fbcon_set_rotate(struct fbcon_ops *ops) case FB_ROTATE_CW: fbcon_rotate_cw(ops); break; + case FB_ROTATE_UD: + fbcon_rotate_ud(ops); + break; } } EXPORT_SYMBOL(fbcon_set_rotate); diff --git a/drivers/video/console/fbcon_rotate.h b/drivers/video/console/fbcon_rotate.h index 709e6b49eab..f8ddcd6bd89 100644 --- a/drivers/video/console/fbcon_rotate.h +++ b/drivers/video/console/fbcon_rotate.h @@ -100,4 +100,5 @@ static inline void rotate_ccw(const char *in, char *out, u32 width, u32 height) } extern void fbcon_rotate_cw(struct fbcon_ops *ops); +extern void fbcon_rotate_ud(struct fbcon_ops *ops); #endif diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c new file mode 100644 index 00000000000..2e1d9d4249c --- /dev/null +++ b/drivers/video/console/fbcon_ud.c @@ -0,0 +1,454 @@ +/* + * linux/drivers/video/console/fbcon_ud.c -- Software Rotation - 180 degrees + * + * Copyright (C) 2005 Antonino Daplas + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "fbcon.h" +#include "fbcon_rotate.h" + +/* + * Rotation 180 degrees + */ + +static inline void ud_update_attr(u8 *dst, u8 *src, int attribute, + struct vc_data *vc) +{ + int i, offset = (vc->vc_font.height < 10) ? 1 : 2; + int width = (vc->vc_font.width + 7) >> 3; + unsigned int cellsize = vc->vc_font.height * width; + u8 c; + + offset = offset * width; + + for (i = 0; i < cellsize; i++) { + c = src[i]; + if (attribute & FBCON_ATTRIBUTE_UNDERLINE && i < offset) + c = 0xff; + if (attribute & FBCON_ATTRIBUTE_BOLD) + c |= c << 1; + if (attribute & FBCON_ATTRIBUTE_REVERSE) + c = ~c; + dst[i] = c; + } +} + + +static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy, + int sx, int dy, int dx, int height, int width) +{ + struct display *p = &fb_display[vc->vc_num]; + struct fb_copyarea area; + u32 vyres = GETVYRES(p->scrollmode, info); + u32 vxres = GETVXRES(p->scrollmode, info); + + area.sy = vyres - ((sy + height) * vc->vc_font.height); + area.sx = vxres - ((sx + width) * vc->vc_font.width); + area.dy = vyres - ((dy + height) * vc->vc_font.height); + area.dx = vxres - ((dx + width) * vc->vc_font.width); + area.height = height * vc->vc_font.height; + area.width = width * vc->vc_font.width; + + info->fbops->fb_copyarea(info, &area); +} + +static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy, + int sx, int height, int width) +{ + struct display *p = &fb_display[vc->vc_num]; + struct fb_fillrect region; + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + u32 vyres = GETVYRES(p->scrollmode, info); + u32 vxres = GETVXRES(p->scrollmode, info); + + region.color = attr_bgcol_ec(bgshift,vc); + region.dy = vyres - ((sy + height) * vc->vc_font.height); + region.dx = vxres - ((sx + width) * vc->vc_font.width); + region.width = width * vc->vc_font.width; + region.height = height * vc->vc_font.height; + region.rop = ROP_COPY; + + info->fbops->fb_fillrect(info, ®ion); +} + +static inline void ud_putcs_aligned(struct vc_data *vc, struct fb_info *info, + const u16 *s, u32 attr, u32 cnt, + u32 d_pitch, u32 s_pitch, u32 cellsize, + struct fb_image *image, u8 *buf, u8 *dst) +{ + struct fbcon_ops *ops = info->fbcon_par; + u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; + u32 idx = vc->vc_font.width >> 3; + u8 *src; + + while (cnt--) { + src = ops->fontbuffer + (scr_readw(s--) & charmask)*cellsize; + + if (attr) { + ud_update_attr(buf, src, attr, vc); + src = buf; + } + + if (likely(idx == 1)) + __fb_pad_aligned_buffer(dst, d_pitch, src, idx, + image->height); + else + fb_pad_aligned_buffer(dst, d_pitch, src, idx, + image->height); + + dst += s_pitch; + } + + info->fbops->fb_imageblit(info, image); +} + +static inline void ud_putcs_unaligned(struct vc_data *vc, + struct fb_info *info, const u16 *s, + u32 attr, u32 cnt, u32 d_pitch, + u32 s_pitch, u32 cellsize, + struct fb_image *image, u8 *buf, + u8 *dst) +{ + struct fbcon_ops *ops = info->fbcon_par; + u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; + u32 shift_low = 0, mod = vc->vc_font.width % 8; + u32 shift_high = 8; + u32 idx = vc->vc_font.width >> 3; + u8 *src; + + while (cnt--) { + src = ops->fontbuffer + (scr_readw(s--) & charmask)*cellsize; + + if (attr) { + ud_update_attr(buf, src, attr, vc); + src = buf; + } + + fb_pad_unaligned_buffer(dst, d_pitch, src, idx, + image->height, shift_high, + shift_low, mod); + shift_low += mod; + dst += (shift_low >= 8) ? s_pitch : s_pitch - 1; + shift_low &= 7; + shift_high = 8 - shift_low; + } + + info->fbops->fb_imageblit(info, image); + +} + +static void ud_putcs(struct vc_data *vc, struct fb_info *info, + const unsigned short *s, int count, int yy, int xx, + int fg, int bg) +{ + struct fb_image image; + struct display *p = &fb_display[vc->vc_num]; + struct fbcon_ops *ops = info->fbcon_par; + u32 width = (vc->vc_font.width + 7)/8; + u32 cellsize = width * vc->vc_font.height; + u32 maxcnt = info->pixmap.size/cellsize; + u32 scan_align = info->pixmap.scan_align - 1; + u32 buf_align = info->pixmap.buf_align - 1; + u32 mod = vc->vc_font.width % 8, cnt, pitch, size; + u32 attribute = get_attribute(info, scr_readw(s)); + u8 *dst, *buf = NULL; + u32 vyres = GETVYRES(p->scrollmode, info); + u32 vxres = GETVXRES(p->scrollmode, info); + + if (!ops->fontbuffer) + return; + + image.fg_color = fg; + image.bg_color = bg; + image.dy = vyres - ((yy * vc->vc_font.height) + vc->vc_font.height); + image.dx = vxres - ((xx + count) * vc->vc_font.width); + image.height = vc->vc_font.height; + image.depth = 1; + + if (attribute) { + buf = kmalloc(cellsize, GFP_KERNEL); + if (!buf) + return; + } + + s += count - 1; + + while (count) { + if (count > maxcnt) + cnt = maxcnt; + else + cnt = count; + + image.width = vc->vc_font.width * cnt; + pitch = ((image.width + 7) >> 3) + scan_align; + pitch &= ~scan_align; + size = pitch * image.height + buf_align; + size &= ~buf_align; + dst = fb_get_buffer_offset(info, &info->pixmap, size); + image.data = dst; + + if (!mod) + ud_putcs_aligned(vc, info, s, attribute, cnt, pitch, + width, cellsize, &image, buf, dst); + else + ud_putcs_unaligned(vc, info, s, attribute, cnt, pitch, + width, cellsize, &image, + buf, dst); + + image.dx += image.width; + count -= cnt; + s -= cnt; + xx += cnt; + } + + /* buf is always NULL except when in monochrome mode, so in this case + it's a gain to check buf against NULL even though kfree() handles + NULL pointers just fine */ + if (unlikely(buf)) + kfree(buf); + +} + +static void ud_clear_margins(struct vc_data *vc, struct fb_info *info, + int bottom_only) +{ + unsigned int cw = vc->vc_font.width; + unsigned int ch = vc->vc_font.height; + unsigned int rw = info->var.xres - (vc->vc_cols*cw); + unsigned int bh = info->var.yres - (vc->vc_rows*ch); + struct fb_fillrect region; + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + + region.color = attr_bgcol_ec(bgshift,vc); + region.rop = ROP_COPY; + + if (rw && !bottom_only) { + region.dy = 0; + region.dx = info->var.xoffset; + region.width = rw; + region.height = info->var.yres_virtual; + info->fbops->fb_fillrect(info, ®ion); + } + + if (bh) { + region.dy = info->var.yoffset; + region.dx = info->var.xoffset; + region.height = bh; + region.width = info->var.xres; + info->fbops->fb_fillrect(info, ®ion); + } +} + +static void ud_cursor(struct vc_data *vc, struct fb_info *info, + struct display *p, int mode, int softback_lines, + int fg, int bg) +{ + struct fb_cursor cursor; + struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par; + unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; + int w = (vc->vc_font.width + 7) >> 3, c; + int y = real_y(p, vc->vc_y); + int attribute, use_sw = (vc->vc_cursor_type & 0x10); + int err = 1, dx, dy; + char *src; + u32 vyres = GETVYRES(p->scrollmode, info); + u32 vxres = GETVXRES(p->scrollmode, info); + + if (!ops->fontbuffer) + return; + + cursor.set = 0; + + if (softback_lines) { + if (y + softback_lines >= vc->vc_rows) { + mode = CM_ERASE; + ops->cursor_flash = 0; + return; + } else + y += softback_lines; + } + + c = scr_readw((u16 *) vc->vc_pos); + attribute = get_attribute(info, c); + src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.height)); + + if (ops->cursor_state.image.data != src || + ops->cursor_reset) { + ops->cursor_state.image.data = src; + cursor.set |= FB_CUR_SETIMAGE; + } + + if (attribute) { + u8 *dst; + + dst = kmalloc(w * vc->vc_font.height, GFP_ATOMIC); + if (!dst) + return; + kfree(ops->cursor_data); + ops->cursor_data = dst; + ud_update_attr(dst, src, attribute, vc); + src = dst; + } + + if (ops->cursor_state.image.fg_color != fg || + ops->cursor_state.image.bg_color != bg || + ops->cursor_reset) { + ops->cursor_state.image.fg_color = fg; + ops->cursor_state.image.bg_color = bg; + cursor.set |= FB_CUR_SETCMAP; + } + + if (ops->cursor_state.image.height != vc->vc_font.height || + ops->cursor_state.image.width != vc->vc_font.width || + ops->cursor_reset) { + ops->cursor_state.image.height = vc->vc_font.height; + ops->cursor_state.image.width = vc->vc_font.width; + cursor.set |= FB_CUR_SETSIZE; + } + + dy = vyres - ((y * vc->vc_font.height) + vc->vc_font.height); + dx = vxres - ((vc->vc_x * vc->vc_font.width) + vc->vc_font.width); + + if (ops->cursor_state.image.dx != dx || + ops->cursor_state.image.dy != dy || + ops->cursor_reset) { + ops->cursor_state.image.dx = dx; + ops->cursor_state.image.dy = dy; + cursor.set |= FB_CUR_SETPOS; + } + + if (ops->cursor_state.hot.x || ops->cursor_state.hot.y || + ops->cursor_reset) { + ops->cursor_state.hot.x = cursor.hot.y = 0; + cursor.set |= FB_CUR_SETHOT; + } + + if (cursor.set & FB_CUR_SETSIZE || + vc->vc_cursor_type != p->cursor_shape || + ops->cursor_state.mask == NULL || + ops->cursor_reset) { + char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC); + int cur_height, size, i = 0; + u8 msk = 0xff; + + if (!mask) + return; + + kfree(ops->cursor_state.mask); + ops->cursor_state.mask = mask; + + p->cursor_shape = vc->vc_cursor_type; + cursor.set |= FB_CUR_SETSHAPE; + + switch (p->cursor_shape & CUR_HWMASK) { + case CUR_NONE: + cur_height = 0; + break; + case CUR_UNDERLINE: + cur_height = (vc->vc_font.height < 10) ? 1 : 2; + break; + case CUR_LOWER_THIRD: + cur_height = vc->vc_font.height/3; + break; + case CUR_LOWER_HALF: + cur_height = vc->vc_font.height >> 1; + break; + case CUR_TWO_THIRDS: + cur_height = (vc->vc_font.height << 1)/3; + break; + case CUR_BLOCK: + default: + cur_height = vc->vc_font.height; + break; + } + + size = cur_height * w; + + while (size--) + mask[i++] = msk; + + size = (vc->vc_font.height - cur_height) * w; + + while (size--) + mask[i++] = ~msk; + } + + switch (mode) { + case CM_ERASE: + ops->cursor_state.enable = 0; + break; + case CM_DRAW: + case CM_MOVE: + default: + ops->cursor_state.enable = (use_sw) ? 0 : 1; + break; + } + + cursor.image.data = src; + cursor.image.fg_color = ops->cursor_state.image.fg_color; + cursor.image.bg_color = ops->cursor_state.image.bg_color; + cursor.image.dx = ops->cursor_state.image.dx; + cursor.image.dy = ops->cursor_state.image.dy; + cursor.image.height = ops->cursor_state.image.height; + cursor.image.width = ops->cursor_state.image.width; + cursor.hot.x = ops->cursor_state.hot.x; + cursor.hot.y = ops->cursor_state.hot.y; + cursor.mask = ops->cursor_state.mask; + cursor.enable = ops->cursor_state.enable; + cursor.image.depth = 1; + cursor.rop = ROP_XOR; + + if (info->fbops->fb_cursor) + err = info->fbops->fb_cursor(info, &cursor); + + if (err) + soft_cursor(info, &cursor); + + ops->cursor_reset = 0; +} + +int ud_update_start(struct fb_info *info) +{ + struct fbcon_ops *ops = info->fbcon_par; + struct display *p = &fb_display[ops->currcon]; + u32 xoffset, yoffset; + u32 vyres = GETVYRES(p->scrollmode, info); + u32 vxres = GETVXRES(p->scrollmode, info); + int err; + + xoffset = (vxres - info->var.xres) - ops->var.xoffset; + yoffset = (vyres - info->var.yres) - ops->var.yoffset; + ops->var.xoffset = xoffset; + ops->var.yoffset = yoffset; + err = fb_pan_display(info, &ops->var); + ops->var.xoffset = info->var.xoffset; + ops->var.yoffset = info->var.yoffset; + ops->var.vmode = info->var.vmode; + return err; +} + +void fbcon_rotate_ud(struct fbcon_ops *ops) +{ + ops->bmove = ud_bmove; + ops->clear = ud_clear; + ops->putcs = ud_putcs; + ops->clear_margins = ud_clear_margins; + ops->cursor = ud_cursor; + ops->update_start = ud_update_start; +} +EXPORT_SYMBOL(fbcon_rotate_ud); + +MODULE_AUTHOR("Antonino Daplas "); +MODULE_DESCRIPTION("Console Rotation (180 degrees) Support"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From ed8c0e99f27451a9b980adf0de318d60e6de811f Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Tue, 8 Nov 2005 21:39:14 -0800 Subject: [PATCH] fbcon: Console Rotation - Add support for 270-degree rotation Add support for 270-degree (counterclockwise) rotation of the console. To activate, boot with: fbcon=rotate:3 Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/Makefile | 3 +- drivers/video/console/fbcon_ccw.c | 428 +++++++++++++++++++++++++++++++++++ drivers/video/console/fbcon_rotate.c | 3 + drivers/video/console/fbcon_rotate.h | 1 + 4 files changed, 434 insertions(+), 1 deletion(-) create mode 100644 drivers/video/console/fbcon_ccw.c diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile index 830ff46e0d1..fed600c9ca5 100644 --- a/drivers/video/console/Makefile +++ b/drivers/video/console/Makefile @@ -32,7 +32,8 @@ ifeq ($(CONFIG_FB_TILEBLITTING),y) obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += tileblit.o endif ifeq ($(CONFIG_FRAMEBUFFER_CONSOLE_ROTATION),y) -obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon_rotate.o fbcon_cw.o fbcon_ud.o +obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon_rotate.o fbcon_cw.o fbcon_ud.o \ + fbcon_ccw.o endif obj-$(CONFIG_FB_STI) += sticore.o font.o diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c new file mode 100644 index 00000000000..680aabab73c --- /dev/null +++ b/drivers/video/console/fbcon_ccw.c @@ -0,0 +1,428 @@ +/* + * linux/drivers/video/console/fbcon_ccw.c -- Software Rotation - 270 degrees + * + * Copyright (C) 2005 Antonino Daplas + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "fbcon.h" +#include "fbcon_rotate.h" + +/* + * Rotation 270 degrees + */ + +static inline void ccw_update_attr(u8 *dst, u8 *src, int attribute, + struct vc_data *vc) +{ + int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2; + int width = (vc->vc_font.height + 7) >> 3; + int mod = vc->vc_font.height % 8; + u8 c, msk = ~(0xff << offset), msk1 = 0; + + if (mod) + msk <<= (8 - mod); + + if (offset > mod) + set_bit(FBCON_BIT(7), (void *)&msk1); + + for (i = 0; i < vc->vc_font.width; i++) { + for (j = 0; j < width; j++) { + c = *src; + + if (attribute & FBCON_ATTRIBUTE_UNDERLINE) { + if (j == width - 1) + c |= msk; + + if (msk1 && j == width - 2) + c |= msk1; + } + + if (attribute & FBCON_ATTRIBUTE_BOLD && i) + *(dst - width) |= c; + + if (attribute & FBCON_ATTRIBUTE_REVERSE) + c = ~c; + src++; + *dst++ = c; + } + } +} + + +static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy, + int sx, int dy, int dx, int height, int width) +{ + struct display *p = &fb_display[vc->vc_num]; + struct fb_copyarea area; + u32 vyres = GETVYRES(p->scrollmode, info); + + area.sx = sy * vc->vc_font.height; + area.sy = vyres - ((sx + width) * vc->vc_font.width); + area.dx = dy * vc->vc_font.height; + area.dy = vyres - ((dx + width) * vc->vc_font.width); + area.width = height * vc->vc_font.height; + area.height = width * vc->vc_font.width; + + info->fbops->fb_copyarea(info, &area); +} + +static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy, + int sx, int height, int width) +{ + struct display *p = &fb_display[vc->vc_num]; + struct fb_fillrect region; + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + u32 vyres = GETVYRES(p->scrollmode, info); + + region.color = attr_bgcol_ec(bgshift,vc); + region.dx = sy * vc->vc_font.height; + region.dy = vyres - ((sx + width) * vc->vc_font.width); + region.height = width * vc->vc_font.width; + region.width = height * vc->vc_font.height; + region.rop = ROP_COPY; + + info->fbops->fb_fillrect(info, ®ion); +} + +static inline void ccw_putcs_aligned(struct vc_data *vc, struct fb_info *info, + const u16 *s, u32 attr, u32 cnt, + u32 d_pitch, u32 s_pitch, u32 cellsize, + struct fb_image *image, u8 *buf, u8 *dst) +{ + struct fbcon_ops *ops = info->fbcon_par; + u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; + u32 idx = (vc->vc_font.height + 7) >> 3; + u8 *src; + + while (cnt--) { + src = ops->fontbuffer + (scr_readw(s--) & charmask)*cellsize; + + if (attr) { + ccw_update_attr(buf, src, attr, vc); + src = buf; + } + + if (likely(idx == 1)) + __fb_pad_aligned_buffer(dst, d_pitch, src, idx, + vc->vc_font.width); + else + fb_pad_aligned_buffer(dst, d_pitch, src, idx, + vc->vc_font.width); + + dst += d_pitch * vc->vc_font.width; + } + + info->fbops->fb_imageblit(info, image); +} + +static void ccw_putcs(struct vc_data *vc, struct fb_info *info, + const unsigned short *s, int count, int yy, int xx, + int fg, int bg) +{ + struct fb_image image; + struct display *p = &fb_display[vc->vc_num]; + struct fbcon_ops *ops = info->fbcon_par; + u32 width = (vc->vc_font.height + 7)/8; + u32 cellsize = width * vc->vc_font.width; + u32 maxcnt = info->pixmap.size/cellsize; + u32 scan_align = info->pixmap.scan_align - 1; + u32 buf_align = info->pixmap.buf_align - 1; + u32 cnt, pitch, size; + u32 attribute = get_attribute(info, scr_readw(s)); + u8 *dst, *buf = NULL; + u32 vyres = GETVYRES(p->scrollmode, info); + + if (!ops->fontbuffer) + return; + + image.fg_color = fg; + image.bg_color = bg; + image.dx = yy * vc->vc_font.height; + image.dy = vyres - ((xx + count) * vc->vc_font.width); + image.width = vc->vc_font.height; + image.depth = 1; + + if (attribute) { + buf = kmalloc(cellsize, GFP_KERNEL); + if (!buf) + return; + } + + s += count - 1; + + while (count) { + if (count > maxcnt) + cnt = maxcnt; + else + cnt = count; + + image.height = vc->vc_font.width * cnt; + pitch = ((image.width + 7) >> 3) + scan_align; + pitch &= ~scan_align; + size = pitch * image.height + buf_align; + size &= ~buf_align; + dst = fb_get_buffer_offset(info, &info->pixmap, size); + image.data = dst; + ccw_putcs_aligned(vc, info, s, attribute, cnt, pitch, + width, cellsize, &image, buf, dst); + image.dy += image.height; + count -= cnt; + s -= cnt; + } + + /* buf is always NULL except when in monochrome mode, so in this case + it's a gain to check buf against NULL even though kfree() handles + NULL pointers just fine */ + if (unlikely(buf)) + kfree(buf); + +} + +static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info, + int bottom_only) +{ + unsigned int cw = vc->vc_font.width; + unsigned int ch = vc->vc_font.height; + unsigned int rw = info->var.yres - (vc->vc_cols*cw); + unsigned int bh = info->var.xres - (vc->vc_rows*ch); + unsigned int bs = vc->vc_rows*ch; + struct fb_fillrect region; + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + + region.color = attr_bgcol_ec(bgshift,vc); + region.rop = ROP_COPY; + + if (rw && !bottom_only) { + region.dx = 0; + region.dy = info->var.yoffset; + region.height = rw; + region.width = info->var.xres_virtual; + info->fbops->fb_fillrect(info, ®ion); + } + + if (bh) { + region.dx = info->var.xoffset + bs; + region.dy = 0; + region.height = info->var.yres_virtual; + region.width = bh; + info->fbops->fb_fillrect(info, ®ion); + } +} + +static void ccw_cursor(struct vc_data *vc, struct fb_info *info, + struct display *p, int mode, int softback_lines, + int fg, int bg) +{ + struct fb_cursor cursor; + struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par; + unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; + int w = (vc->vc_font.height + 7) >> 3, c; + int y = real_y(p, vc->vc_y); + int attribute, use_sw = (vc->vc_cursor_type & 0x10); + int err = 1, dx, dy; + char *src; + u32 vyres = GETVYRES(p->scrollmode, info); + + if (!ops->fontbuffer) + return; + + cursor.set = 0; + + if (softback_lines) { + if (y + softback_lines >= vc->vc_rows) { + mode = CM_ERASE; + ops->cursor_flash = 0; + return; + } else + y += softback_lines; + } + + c = scr_readw((u16 *) vc->vc_pos); + attribute = get_attribute(info, c); + src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width)); + + if (ops->cursor_state.image.data != src || + ops->cursor_reset) { + ops->cursor_state.image.data = src; + cursor.set |= FB_CUR_SETIMAGE; + } + + if (attribute) { + u8 *dst; + + dst = kmalloc(w * vc->vc_font.width, GFP_ATOMIC); + if (!dst) + return; + kfree(ops->cursor_data); + ops->cursor_data = dst; + ccw_update_attr(dst, src, attribute, vc); + src = dst; + } + + if (ops->cursor_state.image.fg_color != fg || + ops->cursor_state.image.bg_color != bg || + ops->cursor_reset) { + ops->cursor_state.image.fg_color = fg; + ops->cursor_state.image.bg_color = bg; + cursor.set |= FB_CUR_SETCMAP; + } + + if (ops->cursor_state.image.height != vc->vc_font.width || + ops->cursor_state.image.width != vc->vc_font.height || + ops->cursor_reset) { + ops->cursor_state.image.height = vc->vc_font.width; + ops->cursor_state.image.width = vc->vc_font.height; + cursor.set |= FB_CUR_SETSIZE; + } + + dx = y * vc->vc_font.height; + dy = vyres - ((vc->vc_x + 1) * vc->vc_font.width); + + if (ops->cursor_state.image.dx != dx || + ops->cursor_state.image.dy != dy || + ops->cursor_reset) { + ops->cursor_state.image.dx = dx; + ops->cursor_state.image.dy = dy; + cursor.set |= FB_CUR_SETPOS; + } + + if (ops->cursor_state.hot.x || ops->cursor_state.hot.y || + ops->cursor_reset) { + ops->cursor_state.hot.x = cursor.hot.y = 0; + cursor.set |= FB_CUR_SETHOT; + } + + if (cursor.set & FB_CUR_SETSIZE || + vc->vc_cursor_type != p->cursor_shape || + ops->cursor_state.mask == NULL || + ops->cursor_reset) { + char *tmp, *mask = kmalloc(w*vc->vc_font.width, GFP_ATOMIC); + int cur_height, size, i = 0; + int width = (vc->vc_font.width + 7)/8; + + if (!mask) + return; + + tmp = kmalloc(width * vc->vc_font.height, GFP_ATOMIC); + + if (!tmp) { + kfree(mask); + return; + } + + kfree(ops->cursor_state.mask); + ops->cursor_state.mask = mask; + + p->cursor_shape = vc->vc_cursor_type; + cursor.set |= FB_CUR_SETSHAPE; + + switch (p->cursor_shape & CUR_HWMASK) { + case CUR_NONE: + cur_height = 0; + break; + case CUR_UNDERLINE: + cur_height = (vc->vc_font.height < 10) ? 1 : 2; + break; + case CUR_LOWER_THIRD: + cur_height = vc->vc_font.height/3; + break; + case CUR_LOWER_HALF: + cur_height = vc->vc_font.height >> 1; + break; + case CUR_TWO_THIRDS: + cur_height = (vc->vc_font.height << 1)/3; + break; + case CUR_BLOCK: + default: + cur_height = vc->vc_font.height; + break; + } + + size = (vc->vc_font.height - cur_height) * width; + while (size--) + tmp[i++] = 0; + size = cur_height * width; + while (size--) + tmp[i++] = 0xff; + memset(mask, 0, w * vc->vc_font.width); + rotate_ccw(tmp, mask, vc->vc_font.width, vc->vc_font.height); + kfree(tmp); + } + + switch (mode) { + case CM_ERASE: + ops->cursor_state.enable = 0; + break; + case CM_DRAW: + case CM_MOVE: + default: + ops->cursor_state.enable = (use_sw) ? 0 : 1; + break; + } + + cursor.image.data = src; + cursor.image.fg_color = ops->cursor_state.image.fg_color; + cursor.image.bg_color = ops->cursor_state.image.bg_color; + cursor.image.dx = ops->cursor_state.image.dx; + cursor.image.dy = ops->cursor_state.image.dy; + cursor.image.height = ops->cursor_state.image.height; + cursor.image.width = ops->cursor_state.image.width; + cursor.hot.x = ops->cursor_state.hot.x; + cursor.hot.y = ops->cursor_state.hot.y; + cursor.mask = ops->cursor_state.mask; + cursor.enable = ops->cursor_state.enable; + cursor.image.depth = 1; + cursor.rop = ROP_XOR; + + if (info->fbops->fb_cursor) + err = info->fbops->fb_cursor(info, &cursor); + + if (err) + soft_cursor(info, &cursor); + + ops->cursor_reset = 0; +} + +int ccw_update_start(struct fb_info *info) +{ + struct fbcon_ops *ops = info->fbcon_par; + struct display *p = &fb_display[ops->currcon]; + u32 yoffset; + u32 vyres = GETVYRES(p->scrollmode, info); + int err; + + yoffset = (vyres - info->var.yres) - ops->var.xoffset; + ops->var.xoffset = ops->var.yoffset; + ops->var.yoffset = yoffset; + err = fb_pan_display(info, &ops->var); + ops->var.xoffset = info->var.xoffset; + ops->var.yoffset = info->var.yoffset; + ops->var.vmode = info->var.vmode; + return err; +} + +void fbcon_rotate_ccw(struct fbcon_ops *ops) +{ + ops->bmove = ccw_bmove; + ops->clear = ccw_clear; + ops->putcs = ccw_putcs; + ops->clear_margins = ccw_clear_margins; + ops->cursor = ccw_cursor; + ops->update_start = ccw_update_start; +} +EXPORT_SYMBOL(fbcon_rotate_ccw); + +MODULE_AUTHOR("Antonino Daplas "); +MODULE_DESCRIPTION("Console Rotation (270 degrees) Support"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/console/fbcon_rotate.c b/drivers/video/console/fbcon_rotate.c index 3d64ad190ff..ec0dd8fe241 100644 --- a/drivers/video/console/fbcon_rotate.c +++ b/drivers/video/console/fbcon_rotate.c @@ -105,6 +105,9 @@ void fbcon_set_rotate(struct fbcon_ops *ops) case FB_ROTATE_UD: fbcon_rotate_ud(ops); break; + case FB_ROTATE_CCW: + fbcon_rotate_ccw(ops); + break; } } EXPORT_SYMBOL(fbcon_set_rotate); diff --git a/drivers/video/console/fbcon_rotate.h b/drivers/video/console/fbcon_rotate.h index f8ddcd6bd89..90c672096c2 100644 --- a/drivers/video/console/fbcon_rotate.h +++ b/drivers/video/console/fbcon_rotate.h @@ -101,4 +101,5 @@ static inline void rotate_ccw(const char *in, char *out, u32 width, u32 height) extern void fbcon_rotate_cw(struct fbcon_ops *ops); extern void fbcon_rotate_ud(struct fbcon_ops *ops); +extern void fbcon_rotate_ccw(struct fbcon_ops *ops); #endif -- cgit v1.2.3 From a812c94b94e3db76d1af68208fb3edef69070401 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Tue, 8 Nov 2005 21:39:15 -0800 Subject: [PATCH] fbcon: Console Rotation - Add ability to control rotation via sysfs Add ability to set rotation via sysfs. The attributes are located in /sys/class/graphics/fb[n] and accepts 0 - unrotated; 1 - clockwise; 2 - upside down; 3 - counterclockwise. The attributes are: con_rotate (r/w) - set rotation of the active console con_rotate_all (w) - set rotation of all consoles rotate (r/w) - set rotation of the framebuffer, if supported. Currently, none of the drivers support this. This is probably temporary, since con_rotate and con_rotate_all are console-specific and has no business being under the fb device. However, until the console layer acquires it's own sysfs class, these attributes will temporarily reside here. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/fbcon.c | 72 +++++++++++++++++++++++++++++++++++++++++++ drivers/video/fbmem.c | 22 +++++++++++++ drivers/video/fbsysfs.c | 67 ++++++++++++++++++++++++++++++++++++++++ include/linux/fb.h | 7 +++++ 4 files changed, 168 insertions(+) diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index e829ba18e0a..e7802ffe549 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -193,6 +193,8 @@ static void fbcon_preset_disp(struct fb_info *info, struct fb_var_screeninfo *va int unit); static void fbcon_redraw_move(struct vc_data *vc, struct display *p, int line, int count, int dy); +static void fbcon_modechanged(struct fb_info *info); +static void fbcon_set_all_vcs(struct fb_info *info); #ifdef CONFIG_MAC /* @@ -218,6 +220,51 @@ static inline void fbcon_set_rotation(struct fb_info *info, struct display *p) else ops->rotate = 0; } + +static void fbcon_rotate(struct fb_info *info, u32 rotate) +{ + struct fbcon_ops *ops= info->fbcon_par; + struct fb_info *fb_info; + + if (!ops || ops->currcon == -1) + return; + + fb_info = registered_fb[con2fb_map[ops->currcon]]; + + if (info == fb_info) { + struct display *p = &fb_display[ops->currcon]; + + if (rotate < 4) + p->con_rotate = rotate; + else + p->con_rotate = 0; + + fbcon_modechanged(info); + } +} + +static void fbcon_rotate_all(struct fb_info *info, u32 rotate) +{ + struct fbcon_ops *ops = info->fbcon_par; + struct vc_data *vc; + struct display *p; + int i; + + if (!ops || ops->currcon < 0 || rotate > 3) + return; + + for (i = 0; i < MAX_NR_CONSOLES; i++) { + vc = vc_cons[i].d; + if (!vc || vc->vc_mode != KD_TEXT || + registered_fb[con2fb_map[i]] != info) + continue; + + p = &fb_display[vc->vc_num]; + p->con_rotate = rotate; + } + + fbcon_set_all_vcs(info); +} #else static inline void fbcon_set_rotation(struct fb_info *info, struct display *p) { @@ -225,8 +272,25 @@ static inline void fbcon_set_rotation(struct fb_info *info, struct display *p) ops->rotate = FB_ROTATE_UR; } + +static void fbcon_rotate(struct fb_info *info, u32 rotate) +{ + return; +} + +static void fbcon_rotate_all(struct fb_info *info, u32 rotate) +{ + return; +} #endif /* CONFIG_FRAMEBUFFER_CONSOLE_ROTATION */ +static int fbcon_get_rotate(struct fb_info *info) +{ + struct fbcon_ops *ops = info->fbcon_par; + + return (ops) ? ops->rotate : 0; +} + static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info) { struct fbcon_ops *ops = info->fbcon_par; @@ -2864,6 +2928,14 @@ static int fbcon_event_notify(struct notifier_block *self, case FB_EVENT_NEW_MODELIST: fbcon_new_modelist(info); break; + case FB_EVENT_SET_CON_ROTATE: + fbcon_rotate(info, *(int *)event->data); + break; + case FB_EVENT_GET_CON_ROTATE: + ret = fbcon_get_rotate(info); + break; + case FB_EVENT_SET_CON_ROTATE_ALL: + fbcon_rotate_all(info, *(int *)event->data); } return ret; diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 7a2a8fa50b3..81b6cd23ea1 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1319,6 +1319,28 @@ int fb_new_modelist(struct fb_info *info) return err; } +/** + * fb_con_duit - user<->fbcon passthrough + * @info: struct fb_info + * @event: notification event to be passed to fbcon + * @data: private data + * + * DESCRIPTION + * This function is an fbcon-user event passing channel + * which bypasses fbdev. This is hopefully temporary + * until a user interface for fbcon is created + */ +int fb_con_duit(struct fb_info *info, int event, void *data) +{ + struct fb_event evnt; + + evnt.info = info; + evnt.data = data; + + return notifier_call_chain(&fb_notifier_list, event, &evnt); +} +EXPORT_SYMBOL(fb_con_duit); + static char *video_options[FB_MAX]; static int ofonly; diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index 007c8e9b2b3..08dac9580d1 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c @@ -213,6 +213,70 @@ static ssize_t show_bpp(struct class_device *class_device, char *buf) return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.bits_per_pixel); } +static ssize_t store_rotate(struct class_device *class_device, const char *buf, + size_t count) +{ + struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_var_screeninfo var; + char **last = NULL; + int err; + + var = fb_info->var; + var.rotate = simple_strtoul(buf, last, 0); + + if ((err = activate(fb_info, &var))) + return err; + + return count; +} + + +static ssize_t show_rotate(struct class_device *class_device, char *buf) +{ + struct fb_info *fb_info = class_get_devdata(class_device); + + return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.rotate); +} + +static ssize_t store_con_rotate(struct class_device *class_device, + const char *buf, size_t count) +{ + struct fb_info *fb_info = class_get_devdata(class_device); + int rotate; + char **last = NULL; + + acquire_console_sem(); + rotate = simple_strtoul(buf, last, 0); + fb_con_duit(fb_info, FB_EVENT_SET_CON_ROTATE, &rotate); + release_console_sem(); + return count; +} + +static ssize_t store_con_rotate_all(struct class_device *class_device, + const char *buf, size_t count) +{ + struct fb_info *fb_info = class_get_devdata(class_device); + int rotate; + char **last = NULL; + + acquire_console_sem(); + rotate = simple_strtoul(buf, last, 0); + fb_con_duit(fb_info, FB_EVENT_SET_CON_ROTATE_ALL, &rotate); + release_console_sem(); + return count; +} + +static ssize_t show_con_rotate(struct class_device *class_device, char *buf) +{ + struct fb_info *fb_info = class_get_devdata(class_device); + int rotate; + + acquire_console_sem(); + rotate = fb_con_duit(fb_info, FB_EVENT_GET_CON_ROTATE, NULL); + release_console_sem(); + return snprintf(buf, PAGE_SIZE, "%d\n", rotate); +} + static ssize_t store_virtual(struct class_device *class_device, const char * buf, size_t count) { @@ -440,6 +504,9 @@ static struct class_device_attribute class_device_attrs[] = { __ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual), __ATTR(name, S_IRUGO, show_name, NULL), __ATTR(stride, S_IRUGO, show_stride, NULL), + __ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate), + __ATTR(con_rotate, S_IRUGO|S_IWUSR, show_con_rotate, store_con_rotate), + __ATTR(con_rotate_all, S_IWUSR, NULL, store_con_rotate_all), }; int fb_init_class_device(struct fb_info *fb_info) diff --git a/include/linux/fb.h b/include/linux/fb.h index 357dd3a0a01..04a58f33ec5 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -508,6 +508,12 @@ struct fb_cursor_user { /* The resolution of the passed in fb_info about to change and all vc's should be changed */ #define FB_EVENT_MODE_CHANGE_ALL 0x0A +/* CONSOLE-SPECIFIC: set console rotation */ +#define FB_EVENT_SET_CON_ROTATE 0x0B +/* CONSOLE-SPECIFIC: get console rotation */ +#define FB_EVENT_GET_CON_ROTATE 0x0C +/* CONSOLE-SPECIFIC: rotate all consoles */ +#define FB_EVENT_SET_CON_ROTATE_ALL 0x0D struct fb_event { struct fb_info *info; @@ -836,6 +842,7 @@ extern int fb_get_color_depth(struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix); extern int fb_get_options(char *name, char **option); extern int fb_new_modelist(struct fb_info *info); +extern int fb_con_duit(struct fb_info *info, int event, void *data); extern struct fb_info *registered_fb[FB_MAX]; extern int num_registered_fb; -- cgit v1.2.3 From efb985f6b265faed75426010e84a79de972c640a Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Tue, 8 Nov 2005 21:39:15 -0800 Subject: [PATCH] fbcon: Console Rotation - Add framebuffer console documentation Add documentation as Documentation/fb/fbcon.txt describing the framebuffer console and its boot options. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/fb/fbcon.txt | 152 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 Documentation/fb/fbcon.txt diff --git a/Documentation/fb/fbcon.txt b/Documentation/fb/fbcon.txt new file mode 100644 index 00000000000..08dce0f631b --- /dev/null +++ b/Documentation/fb/fbcon.txt @@ -0,0 +1,152 @@ +The Framebuffer Console +======================= + + The framebuffer console (fbcon), as its name implies, is a text +console running on top of the framebuffer device. It has the functionality of +any standard text console driver, such as the VGA console, with the added +features that can be attributed to the graphical nature of the framebuffer. + + In the x86 architecture, the framebuffer console is optional, and +some even treat it as a toy. For other architectures, it is the only available +display device, text or graphical. + + What are the features of fbcon? The framebuffer console supports +high resolutions, varying font types, display rotation, primitive multihead, +etc. Theoretically, multi-colored fonts, blending, aliasing, and any feature +made available by the underlying graphics card are also possible. + +A. Configuration + + The framebuffer console can be enabled by using your favorite kernel +configuration tool. It is under Device Drivers->Graphics Support->Support for +framebuffer devices->Framebuffer Console Support. Select 'y' to compile +support statically, or 'm' for module support. The module will be fbcon. + + In order for fbcon to activate, at least one framebuffer driver is +required, so choose from any of the numerous drivers available. For x86 +systems, they almost universally have VGA cards, so vga16fb and vesafb will +always be available. However, using a chipset-specific driver will give you +more speed and features, such as the ability to change the video mode +dynamically. + + To display the penguin logo, choose any logo available in Logo +Configuration->Boot up logo. + + Also, you will need to select at least one compiled-in fonts, but if +you don't do anything, the kernel configuration tool will select one for you, +usually an 8x16 font. + +GOTCHA: A common bug report is enabling the framebuffer without enabling the +framebuffer console. Depending on the driver, you may get a blanked or +garbled display, but the system still boots to completion. If you are +fortunate to have a driver that does not alter the graphics chip, then you +will still get a VGA console. + +B. Loading + +Possible scenarios: + +1. Driver and fbcon are compiled statically + + Usually, fbcon will automatically take over your console. The notable + exception is vesafb. It needs to be explicitly activated with the + vga= boot option parameter. + +2. Driver is compiled statically, fbcon is compiled as a module + + Depending on the driver, you either get a standard console, or a + garbled display, as mentioned above. To get a framebuffer console, + do a 'modprobe fbcon'. + +3. Driver is compiled as a module, fbcon is compiled statically + + You get your standard console. Once the driver is loaded with + 'modprobe xxxfb', fbcon automatically takes over the console with + the possible exception of using the fbcon=map:n option. See below. + +4. Driver and fbcon are compiled as a module. + + You can load them in any order. Once both are loaded, fbcon will take + over the console. + +C. Boot options + + The framebuffer console has several, largely unknown, boot options + that can change its behavior. + +1. fbcon=font: + + Select the initial font to use. The value 'name' can be any of the + compiled-in fonts: VGA8x16, 7x14, 10x18, VGA8x8, MINI4x6, RomanLarge, + SUN8x16, SUN12x22, ProFont6x11, Acorn8x8, PEARL8x8. + + Note, not all drivers can handle font with widths not divisible by 8, + such as vga16fb. + +2. fbcon=scrollback:[k] + + The scrollback buffer is memory that is used to preserve display + contents that has already scrolled past your view. This is accessed + by using the Shift-PageUp key combination. The value 'value' is any + integer. It defaults to 32KB. The 'k' suffix is optional, and will + multiply the 'value' by 1024. + +3. fbcon=map:<0123> + + This is an interesting option. It tells which driver gets mapped to + which console. The value '0123' is a sequence that gets repeated until + the total length is 64 which is the number of consoles available. In + the above example, it is expanded to 012301230123... and the mapping + will be: + + tty | 1 2 3 4 5 6 7 8 9 ... + fb | 0 1 2 3 0 1 2 3 0 ... + + ('cat /proc/fb' should tell you what the fb numbers are) + + One side effect that may be useful is using a map value that exceeds + the number of loaded fb drivers. For example, if only one driver is + available, fb0, adding fbcon=map:1 tells fbcon not to take over the + console. + + Later on, when you want to map the console the to the framebuffer + device, you can use the con2fbmap utility. + +4. fbcon=vc:- + + This option tells fbcon to take over only a range of consoles as + specified by the values 'n1' and 'n2'. The rest of the consoles + outside the given range will still be controlled by the standard + console driver. + + NOTE: For x86 machines, the standard console is the VGA console which + is typically located on the same video card. Thus, the consoles that + are controlled by the VGA console will be garbled. + +4. fbcon=rotate: + + This option changes the orientation angle of the console display. The + value 'n' accepts the following: + + 0 - normal orientation (0 degree) + 1 - clockwise orientation (90 degrees) + 2 - upside down orientation (180 degrees) + 3 - counterclockwise orientation (270 degrees) + + The angle can be changed anytime afterwards by 'echoing' the same + numbers to any one of the 2 attributes found in + /sys/class/graphics/fb{x} + + con_rotate - rotate the display of the active console + con_rotate_all - rotate the display of all consoles + + Console rotation will only become available if Console Rotation + Support is compiled in your kernel. + + NOTE: This is purely console rotation. Any other applications that + use the framebuffer will remain at their 'normal'orientation. + Actually, the underlying fb driver is totally ignorant of console + rotation. + +--- +Antonino Daplas -- cgit v1.2.3 From 120ddb41f18c2d41702af561f4acfbcbd8d6fb46 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Tue, 8 Nov 2005 21:39:16 -0800 Subject: [PATCH] vga16fb: Convert vga16fb as a platform device - Convert vga16fb as a platform device - use framebuffer_alloc() to dynamically allocate resources, and framebuffer_release() to free - remove unneeded casts - trivial whitespace changes Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/vga16fb.c | 169 +++++++++++++++++++++++++++++++----------------- 1 file changed, 110 insertions(+), 59 deletions(-) diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index 690bb6fe828..226ae8a8848 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include